wwan: fix hotplug event handling
[openwrt/openwrt.git] / target / linux / bcm27xx / patches-5.4 / 950-0284-drm-vc4-Query-firmware-for-custom-HDMI-mode.patch
1 From 6402d9c21c9b144d528c3248607589db94ecbce0 Mon Sep 17 00:00:00 2001
2 From: Dave Stevenson <dave.stevenson@raspberrypi.org>
3 Date: Wed, 3 Jul 2019 17:44:53 +0100
4 Subject: [PATCH] drm/vc4: Query firmware for custom HDMI mode
5
6 Allow custom HDMI modes to be specified from config.txt,
7 and these then override EDID parsing.
8
9 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
10 ---
11 drivers/gpu/drm/vc4/vc4_firmware_kms.c | 130 ++++++++++++++-----------
12 1 file changed, 75 insertions(+), 55 deletions(-)
13
14 --- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
15 +++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
16 @@ -1066,6 +1066,56 @@ vc4_fkms_connector_detect(struct drm_con
17 return connector_status_connected;
18 }
19
20 +/* Queries the firmware to populate a drm_mode structure for this display */
21 +static int vc4_fkms_get_fw_mode(struct vc4_fkms_connector *fkms_connector,
22 + struct drm_display_mode *mode)
23 +{
24 + struct vc4_dev *vc4 = fkms_connector->vc4_dev;
25 + struct set_timings timings = { 0 };
26 + int ret;
27 +
28 + timings.display = fkms_connector->display_number;
29 +
30 + ret = rpi_firmware_property(vc4->firmware,
31 + RPI_FIRMWARE_GET_DISPLAY_TIMING, &timings,
32 + sizeof(timings));
33 + if (ret || !timings.clock)
34 + /* No mode returned - abort */
35 + return -1;
36 +
37 + /* Equivalent to DRM_MODE macro. */
38 + memset(mode, 0, sizeof(*mode));
39 + strncpy(mode->name, "FIXED_MODE", sizeof(mode->name));
40 + mode->status = 0;
41 + mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
42 + mode->clock = timings.clock;
43 + mode->hdisplay = timings.hdisplay;
44 + mode->hsync_start = timings.hsync_start;
45 + mode->hsync_end = timings.hsync_end;
46 + mode->htotal = timings.htotal;
47 + mode->hskew = 0;
48 + mode->vdisplay = timings.vdisplay;
49 + mode->vsync_start = timings.vsync_start;
50 + mode->vsync_end = timings.vsync_end;
51 + mode->vtotal = timings.vtotal;
52 + mode->vscan = timings.vscan;
53 +
54 + if (timings.flags & TIMINGS_FLAGS_H_SYNC_POS)
55 + mode->flags |= DRM_MODE_FLAG_PHSYNC;
56 + else
57 + mode->flags |= DRM_MODE_FLAG_NHSYNC;
58 +
59 + if (timings.flags & TIMINGS_FLAGS_V_SYNC_POS)
60 + mode->flags |= DRM_MODE_FLAG_PVSYNC;
61 + else
62 + mode->flags |= DRM_MODE_FLAG_NVSYNC;
63 +
64 + if (timings.flags & TIMINGS_FLAGS_INTERLACE)
65 + mode->flags |= DRM_MODE_FLAG_INTERLACE;
66 +
67 + return 0;
68 +}
69 +
70 static int vc4_fkms_get_edid_block(void *data, u8 *buf, unsigned int block,
71 size_t len)
72 {
73 @@ -1094,25 +1144,35 @@ static int vc4_fkms_connector_get_modes(
74 to_vc4_fkms_connector(connector);
75 struct drm_encoder *encoder = fkms_connector->encoder;
76 struct vc4_fkms_encoder *vc4_encoder = to_vc4_fkms_encoder(encoder);
77 - int ret = 0;
78 + struct drm_display_mode fw_mode;
79 + struct drm_display_mode *mode;
80 struct edid *edid;
81 + int num_modes;
82
83 - edid = drm_do_get_edid(connector, vc4_fkms_get_edid_block,
84 - fkms_connector);
85 + if (!vc4_fkms_get_fw_mode(fkms_connector, &fw_mode)) {
86 + drm_mode_debug_printmodeline(&fw_mode);
87 + mode = drm_mode_duplicate(connector->dev,
88 + &fw_mode);
89 + drm_mode_probed_add(connector, mode);
90 + num_modes = 1; /* 1 mode */
91 + } else {
92 + edid = drm_do_get_edid(connector, vc4_fkms_get_edid_block,
93 + fkms_connector);
94
95 - /* FIXME: Can we do CEC?
96 - * cec_s_phys_addr_from_edid(vc4->hdmi->cec_adap, edid);
97 - * if (!edid)
98 - * return -ENODEV;
99 - */
100 -
101 - vc4_encoder->hdmi_monitor = drm_detect_hdmi_monitor(edid);
102 -
103 - drm_connector_update_edid_property(connector, edid);
104 - ret = drm_add_edid_modes(connector, edid);
105 - kfree(edid);
106 + /* FIXME: Can we do CEC?
107 + * cec_s_phys_addr_from_edid(vc4->hdmi->cec_adap, edid);
108 + * if (!edid)
109 + * return -ENODEV;
110 + */
111 +
112 + vc4_encoder->hdmi_monitor = drm_detect_hdmi_monitor(edid);
113 +
114 + drm_connector_update_edid_property(connector, edid);
115 + num_modes = drm_add_edid_modes(connector, edid);
116 + kfree(edid);
117 + }
118
119 - return ret;
120 + return num_modes;
121 }
122
123 /* This is the DSI panel resolution. Use this as a default should the firmware
124 @@ -1130,55 +1190,15 @@ static int vc4_fkms_lcd_connector_get_mo
125 {
126 struct vc4_fkms_connector *fkms_connector =
127 to_vc4_fkms_connector(connector);
128 - struct vc4_dev *vc4 = fkms_connector->vc4_dev;
129 struct drm_display_mode *mode;
130 - struct mailbox_set_mode mb = {
131 - .tag1 = { RPI_FIRMWARE_GET_DISPLAY_TIMING,
132 - sizeof(struct set_timings), 0},
133 - .timings = { .display = fkms_connector->display_number },
134 - };
135 struct drm_display_mode fw_mode;
136 - int ret = 0;
137 -
138 - ret = rpi_firmware_property_list(vc4->firmware, &mb, sizeof(mb));
139 - if (!ret) {
140 - /* Equivalent to DRM_MODE macro. */
141 - memset(&fw_mode, 0, sizeof(fw_mode));
142 - strncpy(fw_mode.name, "LCD_MODE", sizeof(fw_mode.name));
143 - fw_mode.status = 0;
144 - fw_mode.type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
145 - fw_mode.clock = mb.timings.clock;
146 - fw_mode.hdisplay = mb.timings.hdisplay;
147 - fw_mode.hsync_start = mb.timings.hsync_start;
148 - fw_mode.hsync_end = mb.timings.hsync_end;
149 - fw_mode.htotal = mb.timings.htotal;
150 - fw_mode.hskew = 0;
151 - fw_mode.vdisplay = mb.timings.vdisplay;
152 - fw_mode.vsync_start = mb.timings.vsync_start;
153 - fw_mode.vsync_end = mb.timings.vsync_end;
154 - fw_mode.vtotal = mb.timings.vtotal;
155 - fw_mode.vscan = mb.timings.vscan;
156 - if (mb.timings.flags & TIMINGS_FLAGS_H_SYNC_POS)
157 - fw_mode.flags |= DRM_MODE_FLAG_PHSYNC;
158 - else
159 - fw_mode.flags |= DRM_MODE_FLAG_NHSYNC;
160 - if (mb.timings.flags & TIMINGS_FLAGS_V_SYNC_POS)
161 - fw_mode.flags |= DRM_MODE_FLAG_PVSYNC;
162 - else
163 - fw_mode.flags |= DRM_MODE_FLAG_NVSYNC;
164 - if (mb.timings.flags & TIMINGS_FLAGS_V_SYNC_POS)
165 - fw_mode.flags |= DRM_MODE_FLAG_PVSYNC;
166 - else
167 - fw_mode.flags |= DRM_MODE_FLAG_NVSYNC;
168 - if (mb.timings.flags & TIMINGS_FLAGS_INTERLACE)
169 - fw_mode.flags |= DRM_MODE_FLAG_INTERLACE;
170
171 + if (!vc4_fkms_get_fw_mode(fkms_connector, &fw_mode) && fw_mode.clock)
172 mode = drm_mode_duplicate(connector->dev,
173 &fw_mode);
174 - } else {
175 + else
176 mode = drm_mode_duplicate(connector->dev,
177 &lcd_mode);
178 - }
179
180 if (!mode) {
181 DRM_ERROR("Failed to create a new display mode\n");