@@ -223,91 +223,120 @@ int rp1dpi_hw_busy(struct rp1_dpi *dpi)
223
223
return (rp1dpi_hw_read (dpi , DPI_DMA_STATUS ) & 0xF8F ) ? 1 : 0 ;
224
224
}
225
225
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
+
227
240
struct 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 bpp ; /* Bytes per pixel minus one */
232
244
};
233
245
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
-
247
246
static const struct rp1dpi_ipixfmt my_formats [] = {
248
247
{
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
+ .bpp = 3 ,
253
255
},
254
256
{
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
+ .bpp = 3 ,
259
264
},
260
265
{
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
+ .bpp = 3 ,
265
273
},
266
274
{
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
+ .bpp = 3 ,
271
282
},
272
283
{
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
+ .bpp = 2 ,
277
291
},
278
292
{
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
+ .bpp = 2 ,
283
300
},
284
301
{
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
+ . bpp = 1 ,
292
309
},
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
- }
302
310
};
303
311
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
+ */
304
332
static u32 set_output_format (u32 bus_format , u32 * shift , u32 * imask , u32 * rgbsz )
305
333
{
306
334
switch (bus_format ) {
307
335
case MEDIA_BUS_FMT_RGB565_1X16 :
308
336
if (* shift == ISHIFT_RGB (15 , 10 , 4 )) {
309
337
/* When framebuffer is RGB565, we can output RGB565 */
310
338
* shift = ISHIFT_RGB (15 , 7 , 0 ) | OSHIFT_RGB (19 , 9 , 0 );
339
+ * imask = IMASK_RGB (0x3fc , 0x3fc , 0 );
311
340
* rgbsz &= DPI_DMA_RGBSZ_BPP_MASK ;
312
341
return OMASK_RGB (0x3fc , 0x3fc , 0 );
313
342
}
@@ -322,7 +351,7 @@ static u32 set_output_format(u32 bus_format, u32 *shift, u32 *imask, u32 *rgbsz)
322
351
case MEDIA_BUS_FMT_BGR666_1X18 :
323
352
/* due to a HW limitation, bit-depth is effectively RGB444 */
324
353
* shift |= OSHIFT_RGB (23 , 15 , 7 );
325
- * imask & = IMASK_RGB (0x3c0 , 0x3c0 , 0x3c0 );
354
+ * imask = IMASK_RGB (0x3c0 , 0x3c0 , 0x3c0 );
326
355
* rgbsz = BITS (DPI_DMA_RGBSZ_R , 2 ) | (* rgbsz & DPI_DMA_RGBSZ_BPP_MASK );
327
356
return OMASK_RGB (0x330 , 0x3c0 , 0x3c0 );
328
357
@@ -359,7 +388,8 @@ void rp1dpi_hw_setup(struct rp1_dpi *dpi,
359
388
struct drm_display_mode const * mode )
360
389
{
361
390
u32 shift , imask , omask , rgbsz , vctrl ;
362
- int i ;
391
+ u32 rgb_code [3 ];
392
+ int order , i ;
363
393
364
394
drm_info (& dpi -> drm ,
365
395
"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,45 @@ void rp1dpi_hw_setup(struct rp1_dpi *dpi,
373
403
de_inv ? '-' : '+' ,
374
404
dpi -> clk_inv ? '-' : '+' );
375
405
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 */
381
407
for (i = 0 ; i < ARRAY_SIZE (my_formats ); ++ i ) {
382
408
if (my_formats [i ].format == in_format )
383
409
break ;
384
410
}
385
411
if (i >= ARRAY_SIZE (my_formats )) {
386
412
pr_err ("%s: bad input format\n" , __func__ );
387
- i = 4 ;
413
+ i = ARRAY_SIZE ( my_formats ) - 1 ;
388
414
}
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 ;
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 == RP1DPI_ORDER_UNCHANGED )
424
+ order = BUS_FMT_IS_BGR (bus_format ) ? RP1DPI_ORDER_BGR : RP1DPI_ORDER_RGB ;
425
+ rgb_code [0 ] = my_formats [i ].rgb_code [order & 3 ];
426
+ rgb_code [1 ] = my_formats [i ].rgb_code [(order >> 8 ) & 3 ];
427
+ rgb_code [2 ] = my_formats [i ].rgb_code [(order >> 16 ) & 3 ];
428
+ rgbsz = FIELD_PREP (DPI_DMA_RGBSZ_BPP_MASK , my_formats [i ].bpp ) |
429
+ FIELD_PREP (DPI_DMA_RGBSZ_R_MASK , RGB_SCALE (rgb_code [0 ])) |
430
+ FIELD_PREP (DPI_DMA_RGBSZ_G_MASK , RGB_SCALE (rgb_code [1 ])) |
431
+ FIELD_PREP (DPI_DMA_RGBSZ_B_MASK , RGB_SCALE (rgb_code [2 ]));
432
+ shift = FIELD_PREP (DPI_DMA_SHIFT_IR_MASK , RGB_SHIFT (rgb_code [0 ])) |
433
+ FIELD_PREP (DPI_DMA_SHIFT_IG_MASK , RGB_SHIFT (rgb_code [1 ])) |
434
+ FIELD_PREP (DPI_DMA_SHIFT_IB_MASK , RGB_SHIFT (rgb_code [2 ]));
435
+ imask = FIELD_PREP (DPI_DMA_IMASK_R_MASK , RGB_MASK (rgb_code [0 ])) |
436
+ FIELD_PREP (DPI_DMA_IMASK_G_MASK , RGB_MASK (rgb_code [1 ])) |
437
+ FIELD_PREP (DPI_DMA_IMASK_B_MASK , RGB_MASK (rgb_code [2 ]));
394
438
omask = set_output_format (bus_format , & shift , & imask , & rgbsz );
395
439
440
+ /*
441
+ * Configure all DPI/DMA block registers, except base address.
442
+ * DMA will not actually start until a FB base address is specified
443
+ * using rp1dpi_hw_update().
444
+ */
396
445
rp1dpi_hw_write (dpi , DPI_DMA_IMASK , imask );
397
446
rp1dpi_hw_write (dpi , DPI_DMA_OMASK , omask );
398
447
rp1dpi_hw_write (dpi , DPI_DMA_SHIFT , shift );
0 commit comments