brcm2708-gpu-fw: update to latest firmware
[openwrt/staging/chunkeey.git] / target / linux / brcm2708 / patches-4.19 / 950-0542-drm-vc4-Probe-DPI-DSI-timings-from-the-firmware.patch
1 From b4ffa49d762a4af832d0d8660caf59722c0ff75a Mon Sep 17 00:00:00 2001
2 From: Dave Stevenson <dave.stevenson@raspberrypi.org>
3 Date: Tue, 21 May 2019 11:50:00 +0100
4 Subject: [PATCH] drm: vc4: Probe DPI/DSI timings from the firmware
5
6 For DPI and DSI displays query the firmware as to the configuration
7 and add it as the only mode for DRM.
8
9 In theory we can add plumbing for setting the DPI/DSI mode from
10 KMS, but this is not being added at present as the support frameworks
11 aren't present in the firmware.
12
13 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
14 ---
15 drivers/gpu/drm/vc4/vc4_firmware_kms.c | 60 ++++++++++++++++++----
16 include/soc/bcm2835/raspberrypi-firmware.h | 1 +
17 2 files changed, 51 insertions(+), 10 deletions(-)
18
19 --- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
20 +++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
21 @@ -280,7 +280,7 @@ static u32 vc4_get_display_type(u32 disp
22 /* The firmware display (DispmanX) IDs map to specific types in
23 * a fixed manner.
24 */
25 - DRM_MODE_ENCODER_DSI, /* MAIN_LCD */
26 + DRM_MODE_ENCODER_DSI, /* MAIN_LCD - DSI or DPI */
27 DRM_MODE_ENCODER_DSI, /* AUX_LCD */
28 DRM_MODE_ENCODER_TMDS, /* HDMI0 */
29 DRM_MODE_ENCODER_TVDAC, /* VEC */
30 @@ -362,7 +362,6 @@ static void vc4_plane_atomic_update(stru
31 vc4_get_vc_image_fmt(drm_fmt->format);
32 struct vc4_fkms_plane *vc4_plane = to_vc4_fkms_plane(plane);
33 struct mailbox_set_plane *mb = &vc4_plane->mb;
34 - struct vc4_crtc *vc4_crtc = to_vc4_crtc(state->crtc);
35 int num_planes = fb->format->num_planes;
36 struct drm_display_mode *mode = &state->crtc->mode;
37 unsigned int rotation = SUPPORTED_ROTATIONS;
38 @@ -997,7 +996,9 @@ static int vc4_fkms_connector_get_modes(
39 return ret;
40 }
41
42 -/* FIXME: Read LCD mode from the firmware. This is the DSI panel resolution. */
43 +/* This is the DSI panel resolution. Use this as a default should the firmware
44 + * not respond to our request for the timings.
45 + */
46 static const struct drm_display_mode lcd_mode = {
47 DRM_MODE("800x480", DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
48 25979400 / 1000,
49 @@ -1008,15 +1009,54 @@ static const struct drm_display_mode lcd
50
51 static int vc4_fkms_lcd_connector_get_modes(struct drm_connector *connector)
52 {
53 - //struct vc4_fkms_connector *fkms_connector =
54 - // to_vc4_fkms_connector(connector);
55 - //struct drm_encoder *encoder = fkms_connector->encoder;
56 - //struct vc4_fkms_encoder *vc4_encoder = to_vc4_fkms_encoder(encoder);
57 + struct vc4_fkms_connector *fkms_connector =
58 + to_vc4_fkms_connector(connector);
59 + struct vc4_dev *vc4 = fkms_connector->vc4_dev;
60 struct drm_display_mode *mode;
61 - //int ret = 0;
62 + struct mailbox_set_mode mb = {
63 + .tag1 = { RPI_FIRMWARE_GET_DISPLAY_TIMING,
64 + sizeof(struct set_timings), 0},
65 + .timings = { .display = fkms_connector->display_number },
66 + };
67 + struct drm_display_mode fw_mode;
68 + int ret = 0;
69 +
70 + ret = rpi_firmware_property_list(vc4->firmware, &mb, sizeof(mb));
71 + if (!ret) {
72 + /* Equivalent to DRM_MODE macro. */
73 + memset(&fw_mode, 0, sizeof(fw_mode));
74 + strncpy(fw_mode.name, "LCD_MODE", sizeof(fw_mode.name));
75 + fw_mode.status = 0;
76 + fw_mode.type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
77 + fw_mode.clock = mb.timings.clock;
78 + fw_mode.hdisplay = mb.timings.hdisplay;
79 + fw_mode.hsync_start = mb.timings.hsync_start;
80 + fw_mode.hsync_end = mb.timings.hsync_end;
81 + fw_mode.htotal = mb.timings.htotal;
82 + fw_mode.hskew = 0;
83 + fw_mode.vdisplay = mb.timings.vdisplay;
84 + fw_mode.vsync_start = mb.timings.vsync_start;
85 + fw_mode.vsync_end = mb.timings.vsync_end;
86 + fw_mode.vtotal = mb.timings.vtotal;
87 + fw_mode.vscan = mb.timings.vscan;
88 + if (mb.timings.flags & TIMINGS_FLAGS_H_SYNC_POS)
89 + fw_mode.flags |= DRM_MODE_FLAG_PHSYNC;
90 + else
91 + fw_mode.flags |= DRM_MODE_FLAG_NHSYNC;
92 + if (mb.timings.flags & TIMINGS_FLAGS_V_SYNC_POS)
93 + fw_mode.flags |= DRM_MODE_FLAG_PVSYNC;
94 + else
95 + fw_mode.flags |= DRM_MODE_FLAG_NVSYNC;
96 +
97 + fw_mode.base.type = DRM_MODE_OBJECT_MODE;
98 +
99 + mode = drm_mode_duplicate(connector->dev,
100 + &fw_mode);
101 + } else {
102 + mode = drm_mode_duplicate(connector->dev,
103 + &lcd_mode);
104 + }
105
106 - mode = drm_mode_duplicate(connector->dev,
107 - &lcd_mode);
108 if (!mode) {
109 DRM_ERROR("Failed to create a new display mode\n");
110 return -ENOMEM;
111 --- a/include/soc/bcm2835/raspberrypi-firmware.h
112 +++ b/include/soc/bcm2835/raspberrypi-firmware.h
113 @@ -151,6 +151,7 @@ enum rpi_firmware_property_tag {
114 RPI_FIRMWARE_VCHIQ_INIT = 0x00048010,
115
116 RPI_FIRMWARE_SET_PLANE = 0x00048015,
117 + RPI_FIRMWARE_GET_DISPLAY_TIMING = 0x00040017,
118 RPI_FIRMWARE_SET_TIMING = 0x00048017,
119
120 RPI_FIRMWARE_GET_COMMAND_LINE = 0x00050001,