@@ -223,91 +223,120 @@ int rp1dpi_hw_busy(struct rp1_dpi *dpi)
223223 return (rp1dpi_hw_read (dpi , DPI_DMA_STATUS ) & 0xF8F ) ? 1 : 0 ;
224224}
225225
226- /* Table of supported input (in-memory/DMA) pixel formats. */
226+ /*
227+ * Table of supported input (in-memory/DMA) pixel formats.
228+ *
229+ * RP1 DPI describes RGB components in terms of their MS bit position, a 10-bit
230+ * left-aligned bit-mask, and an optional right-shift-and-OR used for scaling.
231+ * To make it easier to permute R, G and B components, we re-pack these fields
232+ * into 32-bit code-words, which don't themselves correspond to any register.
233+ */
234+
235+ #define RGB_CODE (scale , shift , mask ) (((scale) << 24) | ((shift) << 16) | (mask))
236+ #define RGB_SCALE (c ) ((c) >> 24)
237+ #define RGB_SHIFT (c ) (((c) >> 16) & 31)
238+ #define RGB_MASK (c ) ((c) & 0x3ff)
239+
227240struct rp1dpi_ipixfmt {
228- u32 format ; /* DRM format code */
229- u32 mask ; /* RGB masks (10 bits each, left justified) */
230- u32 shift ; /* RGB MSB positions in the memory word */
231- u32 rgbsz ; /* Shifts used for scaling; also (BPP/8-1) */
241+ u32 format ; /* DRM format code */
242+ u32 rgb_code [3 ]; /* (width&7), MS bit position, 10-bit mask */
243+ u32 sz ; /* Bytes per pixel minus one */
232244};
233245
234- #define IMASK_RGB (r , g , b ) (FIELD_PREP_CONST(DPI_DMA_IMASK_R_MASK, r) | \
235- FIELD_PREP_CONST(DPI_DMA_IMASK_G_MASK, g) | \
236- FIELD_PREP_CONST(DPI_DMA_IMASK_B_MASK, b))
237- #define OMASK_RGB (r , g , b ) (FIELD_PREP_CONST(DPI_DMA_OMASK_R_MASK, r) | \
238- FIELD_PREP_CONST(DPI_DMA_OMASK_G_MASK, g) | \
239- FIELD_PREP_CONST(DPI_DMA_OMASK_B_MASK, b))
240- #define ISHIFT_RGB (r , g , b ) (FIELD_PREP_CONST(DPI_DMA_SHIFT_IR_MASK, r) | \
241- FIELD_PREP_CONST(DPI_DMA_SHIFT_IG_MASK, g) | \
242- FIELD_PREP_CONST(DPI_DMA_SHIFT_IB_MASK, b))
243- #define OSHIFT_RGB (r , g , b ) (FIELD_PREP_CONST(DPI_DMA_SHIFT_OR_MASK, r) | \
244- FIELD_PREP_CONST(DPI_DMA_SHIFT_OG_MASK, g) | \
245- FIELD_PREP_CONST(DPI_DMA_SHIFT_OB_MASK, b))
246-
247246static const struct rp1dpi_ipixfmt my_formats [] = {
248247 {
249- .format = DRM_FORMAT_XRGB8888 ,
250- .mask = IMASK_RGB (0x3fc , 0x3fc , 0x3fc ),
251- .shift = ISHIFT_RGB (23 , 15 , 7 ),
252- .rgbsz = FIELD_PREP_CONST (DPI_DMA_RGBSZ_BPP_MASK , 3 ),
248+ .format = DRM_FORMAT_XRGB8888 ,
249+ .rgb_code = {
250+ RGB_CODE (0 , 23 , 0x3fc ),
251+ RGB_CODE (0 , 15 , 0x3fc ),
252+ RGB_CODE (0 , 7 , 0x3fc ),
253+ },
254+ .sz = 3 ,
253255 },
254256 {
255- .format = DRM_FORMAT_XBGR8888 ,
256- .mask = IMASK_RGB (0x3fc , 0x3fc , 0x3fc ),
257- .shift = ISHIFT_RGB (7 , 15 , 23 ),
258- .rgbsz = FIELD_PREP_CONST (DPI_DMA_RGBSZ_BPP_MASK , 3 ),
257+ .format = DRM_FORMAT_XBGR8888 ,
258+ .rgb_code = {
259+ RGB_CODE (0 , 7 , 0x3fc ),
260+ RGB_CODE (0 , 15 , 0x3fc ),
261+ RGB_CODE (0 , 23 , 0x3fc ),
262+ },
263+ .sz = 3 ,
259264 },
260265 {
261- .format = DRM_FORMAT_ARGB8888 ,
262- .mask = IMASK_RGB (0x3fc , 0x3fc , 0x3fc ),
263- .shift = ISHIFT_RGB (23 , 15 , 7 ),
264- .rgbsz = FIELD_PREP_CONST (DPI_DMA_RGBSZ_BPP_MASK , 3 ),
266+ .format = DRM_FORMAT_ARGB8888 ,
267+ .rgb_code = {
268+ RGB_CODE (0 , 23 , 0x3fc ),
269+ RGB_CODE (0 , 15 , 0x3fc ),
270+ RGB_CODE (0 , 7 , 0x3fc ),
271+ },
272+ .sz = 3 ,
265273 },
266274 {
267- .format = DRM_FORMAT_ABGR8888 ,
268- .mask = IMASK_RGB (0x3fc , 0x3fc , 0x3fc ),
269- .shift = ISHIFT_RGB (7 , 15 , 23 ),
270- .rgbsz = FIELD_PREP_CONST (DPI_DMA_RGBSZ_BPP_MASK , 3 ),
275+ .format = DRM_FORMAT_ABGR8888 ,
276+ .rgb_code = {
277+ RGB_CODE (0 , 7 , 0x3fc ),
278+ RGB_CODE (0 , 15 , 0x3fc ),
279+ RGB_CODE (0 , 23 , 0x3fc ),
280+ },
281+ .sz = 3 ,
271282 },
272283 {
273- .format = DRM_FORMAT_RGB888 ,
274- .mask = IMASK_RGB (0x3fc , 0x3fc , 0x3fc ),
275- .shift = ISHIFT_RGB (23 , 15 , 7 ),
276- .rgbsz = FIELD_PREP_CONST (DPI_DMA_RGBSZ_BPP_MASK , 2 ),
284+ .format = DRM_FORMAT_RGB888 ,
285+ .rgb_code = {
286+ RGB_CODE (0 , 23 , 0x3fc ),
287+ RGB_CODE (0 , 15 , 0x3fc ),
288+ RGB_CODE (0 , 7 , 0x3fc ),
289+ },
290+ .sz = 2 ,
277291 },
278292 {
279- .format = DRM_FORMAT_BGR888 ,
280- .mask = IMASK_RGB (0x3fc , 0x3fc , 0x3fc ),
281- .shift = ISHIFT_RGB (7 , 15 , 23 ),
282- .rgbsz = FIELD_PREP_CONST (DPI_DMA_RGBSZ_BPP_MASK , 2 ),
293+ .format = DRM_FORMAT_BGR888 ,
294+ .rgb_code = {
295+ RGB_CODE (0 , 7 , 0x3fc ),
296+ RGB_CODE (0 , 15 , 0x3fc ),
297+ RGB_CODE (0 , 23 , 0x3fc ),
298+ },
299+ .sz = 2 ,
283300 },
284301 {
285- .format = DRM_FORMAT_RGB565 ,
286- . mask = IMASK_RGB ( 0x3e0 , 0x3f0 , 0x3e0 ),
287- . shift = ISHIFT_RGB ( 15 , 10 , 4 ),
288- . rgbsz = ( FIELD_PREP_CONST ( DPI_DMA_RGBSZ_R_MASK , 5 ) |
289- FIELD_PREP_CONST ( DPI_DMA_RGBSZ_G_MASK , 6 ) |
290- FIELD_PREP_CONST ( DPI_DMA_RGBSZ_B_MASK , 5 ) |
291- FIELD_PREP_CONST ( DPI_DMA_RGBSZ_BPP_MASK , 1 )) ,
302+ .format = DRM_FORMAT_RGB565 ,
303+ . rgb_code = {
304+ RGB_CODE ( 5 , 15 , 0x3e0 ),
305+ RGB_CODE ( 6 , 10 , 0x3f0 ),
306+ RGB_CODE ( 5 , 4 , 0x3e0 ),
307+ },
308+ . sz = 1 ,
292309 },
293- {
294- .format = DRM_FORMAT_BGR565 ,
295- .mask = IMASK_RGB (0x3e0 , 0x3f0 , 0x3e0 ),
296- .shift = ISHIFT_RGB (4 , 10 , 15 ),
297- .rgbsz = (FIELD_PREP_CONST (DPI_DMA_RGBSZ_R_MASK , 5 ) |
298- FIELD_PREP_CONST (DPI_DMA_RGBSZ_G_MASK , 6 ) |
299- FIELD_PREP_CONST (DPI_DMA_RGBSZ_B_MASK , 5 ) |
300- FIELD_PREP_CONST (DPI_DMA_RGBSZ_BPP_MASK , 1 )),
301- }
302310};
303311
312+ #define IMASK_RGB (r , g , b ) (FIELD_PREP_CONST(DPI_DMA_IMASK_R_MASK, r) | \
313+ FIELD_PREP_CONST(DPI_DMA_IMASK_G_MASK, g) | \
314+ FIELD_PREP_CONST(DPI_DMA_IMASK_B_MASK, b))
315+ #define OMASK_RGB (r , g , b ) (FIELD_PREP_CONST(DPI_DMA_OMASK_R_MASK, r) | \
316+ FIELD_PREP_CONST(DPI_DMA_OMASK_G_MASK, g) | \
317+ FIELD_PREP_CONST(DPI_DMA_OMASK_B_MASK, b))
318+ #define ISHIFT_RGB (r , g , b ) (FIELD_PREP_CONST(DPI_DMA_SHIFT_IR_MASK, r) | \
319+ FIELD_PREP_CONST(DPI_DMA_SHIFT_IG_MASK, g) | \
320+ FIELD_PREP_CONST(DPI_DMA_SHIFT_IB_MASK, b))
321+ #define OSHIFT_RGB (r , g , b ) (FIELD_PREP_CONST(DPI_DMA_SHIFT_OR_MASK, r) | \
322+ FIELD_PREP_CONST(DPI_DMA_SHIFT_OG_MASK, g) | \
323+ FIELD_PREP_CONST(DPI_DMA_SHIFT_OB_MASK, b))
324+
325+ /*
326+ * Function to update *shift with output positions, and return output RGB masks.
327+ * By the time we get here, RGB order has been normalized to RGB (R most significant).
328+ * Note that an internal bus is 30 bits wide: bits [21:20], [11:10], [1:0] are dropped.
329+ * This makes the packed RGB5656 and RGB666 formats problematic, as colour components
330+ * need to straddle the gaps; we mitigate this by hijacking input masks and scaling.
331+ */
304332static u32 set_output_format (u32 bus_format , u32 * shift , u32 * imask , u32 * rgbsz )
305333{
306334 switch (bus_format ) {
307335 case MEDIA_BUS_FMT_RGB565_1X16 :
308336 if (* shift == ISHIFT_RGB (15 , 10 , 4 )) {
309337 /* When framebuffer is RGB565, we can output RGB565 */
310338 * shift = ISHIFT_RGB (15 , 7 , 0 ) | OSHIFT_RGB (19 , 9 , 0 );
339+ * imask = IMASK_RGB (0x3fc , 0x3fc , 0 );
311340 * rgbsz &= DPI_DMA_RGBSZ_BPP_MASK ;
312341 return OMASK_RGB (0x3fc , 0x3fc , 0 );
313342 }
@@ -322,7 +351,7 @@ static u32 set_output_format(u32 bus_format, u32 *shift, u32 *imask, u32 *rgbsz)
322351 case MEDIA_BUS_FMT_BGR666_1X18 :
323352 /* due to a HW limitation, bit-depth is effectively RGB444 */
324353 * shift |= OSHIFT_RGB (23 , 15 , 7 );
325- * imask & = IMASK_RGB (0x3c0 , 0x3c0 , 0x3c0 );
354+ * imask = IMASK_RGB (0x3c0 , 0x3c0 , 0x3c0 );
326355 * rgbsz = BITS (DPI_DMA_RGBSZ_R , 2 ) | (* rgbsz & DPI_DMA_RGBSZ_BPP_MASK );
327356 return OMASK_RGB (0x330 , 0x3c0 , 0x3c0 );
328357
@@ -359,7 +388,8 @@ void rp1dpi_hw_setup(struct rp1_dpi *dpi,
359388 struct drm_display_mode const * mode )
360389{
361390 u32 shift , imask , omask , rgbsz , vctrl ;
362- int i ;
391+ u32 rgb_code [3 ];
392+ int order , i ;
363393
364394 drm_info (& dpi -> drm ,
365395 "in_fmt=\'%c%c%c%c\' bus_fmt=0x%x mode=%dx%d total=%dx%d%s %dkHz %cH%cV%cD%cC" ,
@@ -373,26 +403,63 @@ void rp1dpi_hw_setup(struct rp1_dpi *dpi,
373403 de_inv ? '-' : '+' ,
374404 dpi -> clk_inv ? '-' : '+' );
375405
376- /*
377- * Configure all DPI/DMA block registers, except base address.
378- * DMA will not actually start until a FB base address is specified
379- * using rp1dpi_hw_update().
380- */
406+ /* Look up the input (in-memory) pixel format */
381407 for (i = 0 ; i < ARRAY_SIZE (my_formats ); ++ i ) {
382408 if (my_formats [i ].format == in_format )
383409 break ;
384410 }
385411 if (i >= ARRAY_SIZE (my_formats )) {
386412 pr_err ("%s: bad input format\n" , __func__ );
387- i = 4 ;
413+ i = ARRAY_SIZE (my_formats ) - 1 ;
414+ }
415+
416+ /*
417+ * Although these RGB orderings refer to the output (DPI bus) format,
418+ * here we permute the *input* components. After this point, "Red"
419+ * will be most significant (highest numbered GPIOs), regardless
420+ * of rgb_order or bus_format. This simplifies later workarounds.
421+ */
422+ order = dpi -> rgb_order_override ;
423+ if (order < 0 )
424+ order = BUS_FMT_IS_BGR (bus_format ) ? RP1DPI_ORDER_BGR : RP1DPI_ORDER_RGB ;
425+ switch (order ) {
426+ case RP1DPI_ORDER_RGB :
427+ rgb_code [0 ] = my_formats [i ].rgb_code [0 ];
428+ rgb_code [1 ] = my_formats [i ].rgb_code [1 ];
429+ rgb_code [2 ] = my_formats [i ].rgb_code [2 ];
430+ break ;
431+ case RP1DPI_ORDER_BGR :
432+ rgb_code [0 ] = my_formats [i ].rgb_code [2 ];
433+ rgb_code [1 ] = my_formats [i ].rgb_code [1 ];
434+ rgb_code [2 ] = my_formats [i ].rgb_code [0 ];
435+ break ;
436+ case RP1DPI_ORDER_GRB :
437+ rgb_code [0 ] = my_formats [i ].rgb_code [1 ];
438+ rgb_code [1 ] = my_formats [i ].rgb_code [0 ];
439+ rgb_code [2 ] = my_formats [i ].rgb_code [2 ];
440+ break ;
441+ default : /* RP1DPI_ORDER_BRG */
442+ rgb_code [0 ] = my_formats [i ].rgb_code [2 ];
443+ rgb_code [1 ] = my_formats [i ].rgb_code [0 ];
444+ rgb_code [2 ] = my_formats [i ].rgb_code [1 ];
388445 }
389- if (BUS_FMT_IS_BGR (bus_format ))
390- i ^= 1 ;
391- shift = my_formats [i ].shift ;
392- imask = my_formats [i ].mask ;
393- rgbsz = my_formats [i ].rgbsz ;
446+ rgbsz = FIELD_PREP (DPI_DMA_RGBSZ_BPP_MASK , my_formats [i ].sz ) |
447+ FIELD_PREP (DPI_DMA_RGBSZ_R_MASK , RGB_SCALE (rgb_code [0 ])) |
448+ FIELD_PREP (DPI_DMA_RGBSZ_G_MASK , RGB_SCALE (rgb_code [1 ])) |
449+ FIELD_PREP (DPI_DMA_RGBSZ_B_MASK , RGB_SCALE (rgb_code [2 ]));
450+ shift = FIELD_PREP (DPI_DMA_SHIFT_IR_MASK , RGB_SHIFT (rgb_code [0 ])) |
451+ FIELD_PREP (DPI_DMA_SHIFT_IG_MASK , RGB_SHIFT (rgb_code [1 ])) |
452+ FIELD_PREP (DPI_DMA_SHIFT_IB_MASK , RGB_SHIFT (rgb_code [2 ]));
453+ imask = FIELD_PREP (DPI_DMA_IMASK_R_MASK , RGB_MASK (rgb_code [0 ])) |
454+ FIELD_PREP (DPI_DMA_IMASK_G_MASK , RGB_MASK (rgb_code [1 ])) |
455+ FIELD_PREP (DPI_DMA_IMASK_B_MASK , RGB_MASK (rgb_code [2 ]));
394456 omask = set_output_format (bus_format , & shift , & imask , & rgbsz );
395457
458+ /*
459+ * Configure all DPI/DMA block registers, except base address.
460+ * DMA will not actually start until a FB base address is specified
461+ * using rp1dpi_hw_update().
462+ */
396463 rp1dpi_hw_write (dpi , DPI_DMA_IMASK , imask );
397464 rp1dpi_hw_write (dpi , DPI_DMA_OMASK , omask );
398465 rp1dpi_hw_write (dpi , DPI_DMA_SHIFT , shift );
0 commit comments