4892c271ffc933a241651c8939e097d56ffc6f91
[openwrt/staging/linusw.git] /
1 From ba9883e3b667e4f1fbeacc4346f6e9179a3a5479 Mon Sep 17 00:00:00 2001
2 From: Nick Hollinghurst <nick.hollinghurst@raspberrypi.com>
3 Date: Mon, 20 Jan 2025 11:20:48 +0000
4 Subject: [PATCH] drm: rp1: rp1-dpi: Add "rgb_order" property (to match VC4
5 DPI)
6
7 As on VC4, the OF property overrides the order implied by media
8 bus format. Only 4 of the 6 possible orders are supported. New
9 add-on hardware designs should not rely on this "legacy" feature.
10
11 Signed-off-by: Nick Hollinghurst <nick.hollinghurst@raspberrypi.com>
12 ---
13 drivers/gpu/drm/rp1/rp1-dpi/rp1_dpi.c | 15 ++
14 drivers/gpu/drm/rp1/rp1-dpi/rp1_dpi.h | 8 +
15 drivers/gpu/drm/rp1/rp1-dpi/rp1_dpi_hw.c | 191 ++++++++++++++---------
16 3 files changed, 143 insertions(+), 71 deletions(-)
17
18 --- a/drivers/gpu/drm/rp1/rp1-dpi/rp1_dpi.c
19 +++ b/drivers/gpu/drm/rp1/rp1-dpi/rp1_dpi.c
20 @@ -292,6 +292,7 @@ static int rp1dpi_platform_probe(struct
21 struct device *dev = &pdev->dev;
22 struct rp1_dpi *dpi;
23 struct drm_bridge *bridge = NULL;
24 + const char *rgb_order = NULL;
25 struct drm_panel *panel;
26 int i, j, ret;
27
28 @@ -353,6 +354,20 @@ static int rp1dpi_platform_probe(struct
29 if (ret)
30 goto done_err;
31
32 + dpi->rgb_order_override = RP1DPI_ORDER_UNCHANGED;
33 + if (!of_property_read_string(dev->of_node, "rgb_order", &rgb_order)) {
34 + if (!strcmp(rgb_order, "rgb"))
35 + dpi->rgb_order_override = RP1DPI_ORDER_RGB;
36 + else if (!strcmp(rgb_order, "bgr"))
37 + dpi->rgb_order_override = RP1DPI_ORDER_BGR;
38 + else if (!strcmp(rgb_order, "grb"))
39 + dpi->rgb_order_override = RP1DPI_ORDER_GRB;
40 + else if (!strcmp(rgb_order, "brg"))
41 + dpi->rgb_order_override = RP1DPI_ORDER_BRG;
42 + else
43 + DRM_ERROR("Invalid dpi order %s - ignored\n", rgb_order);
44 + }
45 +
46 /* Check if PIO can snoop on or override DPI's GPIO1 */
47 dpi->gpio1_used = false;
48 for (i = 0; !dpi->gpio1_used; i++) {
49 --- a/drivers/gpu/drm/rp1/rp1-dpi/rp1_dpi.h
50 +++ b/drivers/gpu/drm/rp1/rp1-dpi/rp1_dpi.h
51 @@ -25,6 +25,13 @@
52 #define RP1DPI_CLK_PLLCORE 2
53 #define RP1DPI_NUM_CLOCKS 3
54
55 +/* Codes (in LE byte order) used for S/W permutation */
56 +#define RP1DPI_ORDER_UNCHANGED 0
57 +#define RP1DPI_ORDER_RGB 0x020100
58 +#define RP1DPI_ORDER_BGR 0x000102
59 +#define RP1DPI_ORDER_GRB 0x020001
60 +#define RP1DPI_ORDER_BRG 0x010002
61 +
62 /* ---------------------------------------------------------------------- */
63
64 struct rp1_dpi {
65 @@ -45,6 +52,7 @@ struct rp1_dpi {
66 u32 bus_fmt;
67 bool de_inv, clk_inv;
68 bool dpi_running, pipe_enabled;
69 + unsigned int rgb_order_override;
70 struct completion finished;
71
72 /* Experimental stuff for interlace follows */
73 --- a/drivers/gpu/drm/rp1/rp1-dpi/rp1_dpi_hw.c
74 +++ b/drivers/gpu/drm/rp1/rp1-dpi/rp1_dpi_hw.c
75 @@ -223,12 +223,90 @@ int rp1dpi_hw_busy(struct rp1_dpi *dpi)
76 return (rp1dpi_hw_read(dpi, DPI_DMA_STATUS) & 0xF8F) ? 1 : 0;
77 }
78
79 -/* Table of supported input (in-memory/DMA) pixel formats. */
80 +/*
81 + * Table of supported input (in-memory/DMA) pixel formats.
82 + *
83 + * RP1 DPI describes RGB components in terms of their MS bit position, a 10-bit
84 + * left-aligned bit-mask, and an optional right-shift-and-OR used for scaling.
85 + * To make it easier to permute R, G and B components, we re-pack these fields
86 + * into 32-bit code-words, which don't themselves correspond to any register.
87 + */
88 +
89 +#define RGB_CODE(scale, shift, mask) (((scale) << 24) | ((shift) << 16) | (mask))
90 +#define RGB_SCALE(c) ((c) >> 24)
91 +#define RGB_SHIFT(c) (((c) >> 16) & 31)
92 +#define RGB_MASK(c) ((c) & 0x3ff)
93 +
94 struct rp1dpi_ipixfmt {
95 - u32 format; /* DRM format code */
96 - u32 mask; /* RGB masks (10 bits each, left justified) */
97 - u32 shift; /* RGB MSB positions in the memory word */
98 - u32 rgbsz; /* Shifts used for scaling; also (BPP/8-1) */
99 + u32 format; /* DRM format code */
100 + u32 rgb_code[3]; /* (width&7), MS bit position, 10-bit mask */
101 + u32 bpp; /* Bytes per pixel minus one */
102 +};
103 +
104 +static const struct rp1dpi_ipixfmt my_formats[] = {
105 + {
106 + .format = DRM_FORMAT_XRGB8888,
107 + .rgb_code = {
108 + RGB_CODE(0, 23, 0x3fc),
109 + RGB_CODE(0, 15, 0x3fc),
110 + RGB_CODE(0, 7, 0x3fc),
111 + },
112 + .bpp = 3,
113 + },
114 + {
115 + .format = DRM_FORMAT_XBGR8888,
116 + .rgb_code = {
117 + RGB_CODE(0, 7, 0x3fc),
118 + RGB_CODE(0, 15, 0x3fc),
119 + RGB_CODE(0, 23, 0x3fc),
120 + },
121 + .bpp = 3,
122 + },
123 + {
124 + .format = DRM_FORMAT_ARGB8888,
125 + .rgb_code = {
126 + RGB_CODE(0, 23, 0x3fc),
127 + RGB_CODE(0, 15, 0x3fc),
128 + RGB_CODE(0, 7, 0x3fc),
129 + },
130 + .bpp = 3,
131 + },
132 + {
133 + .format = DRM_FORMAT_ABGR8888,
134 + .rgb_code = {
135 + RGB_CODE(0, 7, 0x3fc),
136 + RGB_CODE(0, 15, 0x3fc),
137 + RGB_CODE(0, 23, 0x3fc),
138 + },
139 + .bpp = 3,
140 + },
141 + {
142 + .format = DRM_FORMAT_RGB888,
143 + .rgb_code = {
144 + RGB_CODE(0, 23, 0x3fc),
145 + RGB_CODE(0, 15, 0x3fc),
146 + RGB_CODE(0, 7, 0x3fc),
147 + },
148 + .bpp = 2,
149 + },
150 + {
151 + .format = DRM_FORMAT_BGR888,
152 + .rgb_code = {
153 + RGB_CODE(0, 7, 0x3fc),
154 + RGB_CODE(0, 15, 0x3fc),
155 + RGB_CODE(0, 23, 0x3fc),
156 + },
157 + .bpp = 2,
158 + },
159 + {
160 + .format = DRM_FORMAT_RGB565,
161 + .rgb_code = {
162 + RGB_CODE(5, 15, 0x3e0),
163 + RGB_CODE(6, 10, 0x3f0),
164 + RGB_CODE(5, 4, 0x3e0),
165 + },
166 + .bpp = 1,
167 + },
168 };
169
170 #define IMASK_RGB(r, g, b) (FIELD_PREP_CONST(DPI_DMA_IMASK_R_MASK, r) | \
171 @@ -244,63 +322,13 @@ struct rp1dpi_ipixfmt {
172 FIELD_PREP_CONST(DPI_DMA_SHIFT_OG_MASK, g) | \
173 FIELD_PREP_CONST(DPI_DMA_SHIFT_OB_MASK, b))
174
175 -static const struct rp1dpi_ipixfmt my_formats[] = {
176 - {
177 - .format = DRM_FORMAT_XRGB8888,
178 - .mask = IMASK_RGB(0x3fc, 0x3fc, 0x3fc),
179 - .shift = ISHIFT_RGB(23, 15, 7),
180 - .rgbsz = FIELD_PREP_CONST(DPI_DMA_RGBSZ_BPP_MASK, 3),
181 - },
182 - {
183 - .format = DRM_FORMAT_XBGR8888,
184 - .mask = IMASK_RGB(0x3fc, 0x3fc, 0x3fc),
185 - .shift = ISHIFT_RGB(7, 15, 23),
186 - .rgbsz = FIELD_PREP_CONST(DPI_DMA_RGBSZ_BPP_MASK, 3),
187 - },
188 - {
189 - .format = DRM_FORMAT_ARGB8888,
190 - .mask = IMASK_RGB(0x3fc, 0x3fc, 0x3fc),
191 - .shift = ISHIFT_RGB(23, 15, 7),
192 - .rgbsz = FIELD_PREP_CONST(DPI_DMA_RGBSZ_BPP_MASK, 3),
193 - },
194 - {
195 - .format = DRM_FORMAT_ABGR8888,
196 - .mask = IMASK_RGB(0x3fc, 0x3fc, 0x3fc),
197 - .shift = ISHIFT_RGB(7, 15, 23),
198 - .rgbsz = FIELD_PREP_CONST(DPI_DMA_RGBSZ_BPP_MASK, 3),
199 - },
200 - {
201 - .format = DRM_FORMAT_RGB888,
202 - .mask = IMASK_RGB(0x3fc, 0x3fc, 0x3fc),
203 - .shift = ISHIFT_RGB(23, 15, 7),
204 - .rgbsz = FIELD_PREP_CONST(DPI_DMA_RGBSZ_BPP_MASK, 2),
205 - },
206 - {
207 - .format = DRM_FORMAT_BGR888,
208 - .mask = IMASK_RGB(0x3fc, 0x3fc, 0x3fc),
209 - .shift = ISHIFT_RGB(7, 15, 23),
210 - .rgbsz = FIELD_PREP_CONST(DPI_DMA_RGBSZ_BPP_MASK, 2),
211 - },
212 - {
213 - .format = DRM_FORMAT_RGB565,
214 - .mask = IMASK_RGB(0x3e0, 0x3f0, 0x3e0),
215 - .shift = ISHIFT_RGB(15, 10, 4),
216 - .rgbsz = (FIELD_PREP_CONST(DPI_DMA_RGBSZ_R_MASK, 5) |
217 - FIELD_PREP_CONST(DPI_DMA_RGBSZ_G_MASK, 6) |
218 - FIELD_PREP_CONST(DPI_DMA_RGBSZ_B_MASK, 5) |
219 - FIELD_PREP_CONST(DPI_DMA_RGBSZ_BPP_MASK, 1)),
220 - },
221 - {
222 - .format = DRM_FORMAT_BGR565,
223 - .mask = IMASK_RGB(0x3e0, 0x3f0, 0x3e0),
224 - .shift = ISHIFT_RGB(4, 10, 15),
225 - .rgbsz = (FIELD_PREP_CONST(DPI_DMA_RGBSZ_R_MASK, 5) |
226 - FIELD_PREP_CONST(DPI_DMA_RGBSZ_G_MASK, 6) |
227 - FIELD_PREP_CONST(DPI_DMA_RGBSZ_B_MASK, 5) |
228 - FIELD_PREP_CONST(DPI_DMA_RGBSZ_BPP_MASK, 1)),
229 - }
230 -};
231 -
232 +/*
233 + * Function to update *shift with output positions, and return output RGB masks.
234 + * By the time we get here, RGB order has been normalized to RGB (R most significant).
235 + * Note that an internal bus is 30 bits wide: bits [21:20], [11:10], [1:0] are dropped.
236 + * This makes the packed RGB5656 and RGB666 formats problematic, as colour components
237 + * need to straddle the gaps; we mitigate this by hijacking input masks and scaling.
238 + */
239 static u32 set_output_format(u32 bus_format, u32 *shift, u32 *imask, u32 *rgbsz)
240 {
241 switch (bus_format) {
242 @@ -308,6 +336,7 @@ static u32 set_output_format(u32 bus_for
243 if (*shift == ISHIFT_RGB(15, 10, 4)) {
244 /* When framebuffer is RGB565, we can output RGB565 */
245 *shift = ISHIFT_RGB(15, 7, 0) | OSHIFT_RGB(19, 9, 0);
246 + *imask = IMASK_RGB(0x3fc, 0x3fc, 0);
247 *rgbsz &= DPI_DMA_RGBSZ_BPP_MASK;
248 return OMASK_RGB(0x3fc, 0x3fc, 0);
249 }
250 @@ -322,7 +351,7 @@ static u32 set_output_format(u32 bus_for
251 case MEDIA_BUS_FMT_BGR666_1X18:
252 /* due to a HW limitation, bit-depth is effectively RGB444 */
253 *shift |= OSHIFT_RGB(23, 15, 7);
254 - *imask &= IMASK_RGB(0x3c0, 0x3c0, 0x3c0);
255 + *imask = IMASK_RGB(0x3c0, 0x3c0, 0x3c0);
256 *rgbsz = BITS(DPI_DMA_RGBSZ_R, 2) | (*rgbsz & DPI_DMA_RGBSZ_BPP_MASK);
257 return OMASK_RGB(0x330, 0x3c0, 0x3c0);
258
259 @@ -359,7 +388,8 @@ void rp1dpi_hw_setup(struct rp1_dpi *dpi
260 struct drm_display_mode const *mode)
261 {
262 u32 shift, imask, omask, rgbsz, vctrl;
263 - int i;
264 + u32 rgb_code[3];
265 + int order, i;
266
267 drm_info(&dpi->drm,
268 "in_fmt=\'%c%c%c%c\' bus_fmt=0x%x mode=%dx%d total=%dx%d%s %dkHz %cH%cV%cD%cC",
269 @@ -373,26 +403,45 @@ void rp1dpi_hw_setup(struct rp1_dpi *dpi
270 de_inv ? '-' : '+',
271 dpi->clk_inv ? '-' : '+');
272
273 - /*
274 - * Configure all DPI/DMA block registers, except base address.
275 - * DMA will not actually start until a FB base address is specified
276 - * using rp1dpi_hw_update().
277 - */
278 + /* Look up the input (in-memory) pixel format */
279 for (i = 0; i < ARRAY_SIZE(my_formats); ++i) {
280 if (my_formats[i].format == in_format)
281 break;
282 }
283 if (i >= ARRAY_SIZE(my_formats)) {
284 pr_err("%s: bad input format\n", __func__);
285 - i = 4;
286 + i = ARRAY_SIZE(my_formats) - 1;
287 }
288 - if (BUS_FMT_IS_BGR(bus_format))
289 - i ^= 1;
290 - shift = my_formats[i].shift;
291 - imask = my_formats[i].mask;
292 - rgbsz = my_formats[i].rgbsz;
293 +
294 + /*
295 + * Although these RGB orderings refer to the output (DPI bus) format,
296 + * here we permute the *input* components. After this point, "Red"
297 + * will be most significant (highest numbered GPIOs), regardless
298 + * of rgb_order or bus_format. This simplifies later workarounds.
299 + */
300 + order = dpi->rgb_order_override;
301 + if (order == RP1DPI_ORDER_UNCHANGED)
302 + order = BUS_FMT_IS_BGR(bus_format) ? RP1DPI_ORDER_BGR : RP1DPI_ORDER_RGB;
303 + rgb_code[0] = my_formats[i].rgb_code[order & 3];
304 + rgb_code[1] = my_formats[i].rgb_code[(order >> 8) & 3];
305 + rgb_code[2] = my_formats[i].rgb_code[(order >> 16) & 3];
306 + rgbsz = FIELD_PREP(DPI_DMA_RGBSZ_BPP_MASK, my_formats[i].bpp) |
307 + FIELD_PREP(DPI_DMA_RGBSZ_R_MASK, RGB_SCALE(rgb_code[0])) |
308 + FIELD_PREP(DPI_DMA_RGBSZ_G_MASK, RGB_SCALE(rgb_code[1])) |
309 + FIELD_PREP(DPI_DMA_RGBSZ_B_MASK, RGB_SCALE(rgb_code[2]));
310 + shift = FIELD_PREP(DPI_DMA_SHIFT_IR_MASK, RGB_SHIFT(rgb_code[0])) |
311 + FIELD_PREP(DPI_DMA_SHIFT_IG_MASK, RGB_SHIFT(rgb_code[1])) |
312 + FIELD_PREP(DPI_DMA_SHIFT_IB_MASK, RGB_SHIFT(rgb_code[2]));
313 + imask = FIELD_PREP(DPI_DMA_IMASK_R_MASK, RGB_MASK(rgb_code[0])) |
314 + FIELD_PREP(DPI_DMA_IMASK_G_MASK, RGB_MASK(rgb_code[1])) |
315 + FIELD_PREP(DPI_DMA_IMASK_B_MASK, RGB_MASK(rgb_code[2]));
316 omask = set_output_format(bus_format, &shift, &imask, &rgbsz);
317
318 + /*
319 + * Configure all DPI/DMA block registers, except base address.
320 + * DMA will not actually start until a FB base address is specified
321 + * using rp1dpi_hw_update().
322 + */
323 rp1dpi_hw_write(dpi, DPI_DMA_IMASK, imask);
324 rp1dpi_hw_write(dpi, DPI_DMA_OMASK, omask);
325 rp1dpi_hw_write(dpi, DPI_DMA_SHIFT, shift);