@@ -409,6 +409,61 @@ void drm_fb_xrgb8888_to_rgb888_toio(void __iomem *dst, unsigned int dst_pitch,
409409}
410410EXPORT_SYMBOL (drm_fb_xrgb8888_to_rgb888_toio );
411411
412+ static void drm_fb_xrgb8888_to_xrgb2101010_line (u32 * dbuf , const u32 * sbuf ,
413+ unsigned int pixels )
414+ {
415+ unsigned int x ;
416+ u32 val32 ;
417+
418+ for (x = 0 ; x < pixels ; x ++ ) {
419+ val32 = ((sbuf [x ] & 0x000000FF ) << 2 ) |
420+ ((sbuf [x ] & 0x0000FF00 ) << 4 ) |
421+ ((sbuf [x ] & 0x00FF0000 ) << 6 );
422+ * dbuf ++ = val32 | ((val32 >> 8 ) & 0x00300C03 );
423+ }
424+ }
425+
426+ /**
427+ * drm_fb_xrgb8888_to_xrgb2101010_toio - Convert XRGB8888 to XRGB2101010 clip
428+ * buffer
429+ * @dst: XRGB2101010 destination buffer (iomem)
430+ * @dst_pitch: Number of bytes between two consecutive scanlines within dst
431+ * @vaddr: XRGB8888 source buffer
432+ * @fb: DRM framebuffer
433+ * @clip: Clip rectangle area to copy
434+ *
435+ * Drivers can use this function for XRGB2101010 devices that don't natively
436+ * support XRGB8888.
437+ */
438+ void drm_fb_xrgb8888_to_xrgb2101010_toio (void __iomem * dst ,
439+ unsigned int dst_pitch , const void * vaddr ,
440+ const struct drm_framebuffer * fb ,
441+ const struct drm_rect * clip )
442+ {
443+ size_t linepixels = clip -> x2 - clip -> x1 ;
444+ size_t dst_len = linepixels * sizeof (u32 );
445+ unsigned int y , lines = clip -> y2 - clip -> y1 ;
446+ void * dbuf ;
447+
448+ if (!dst_pitch )
449+ dst_pitch = dst_len ;
450+
451+ dbuf = kmalloc (dst_len , GFP_KERNEL );
452+ if (!dbuf )
453+ return ;
454+
455+ vaddr += clip_offset (clip , fb -> pitches [0 ], sizeof (u32 ));
456+ for (y = 0 ; y < lines ; y ++ ) {
457+ drm_fb_xrgb8888_to_xrgb2101010_line (dbuf , vaddr , linepixels );
458+ memcpy_toio (dst , dbuf , dst_len );
459+ vaddr += fb -> pitches [0 ];
460+ dst += dst_pitch ;
461+ }
462+
463+ kfree (dbuf );
464+ }
465+ EXPORT_SYMBOL (drm_fb_xrgb8888_to_xrgb2101010_toio );
466+
412467/**
413468 * drm_fb_xrgb8888_to_gray8 - Convert XRGB8888 to grayscale
414469 * @dst: 8-bit grayscale destination buffer
@@ -500,6 +555,10 @@ int drm_fb_blit_toio(void __iomem *dst, unsigned int dst_pitch, uint32_t dst_for
500555 fb_format = DRM_FORMAT_XRGB8888 ;
501556 if (dst_format == DRM_FORMAT_ARGB8888 )
502557 dst_format = DRM_FORMAT_XRGB8888 ;
558+ if (fb_format == DRM_FORMAT_ARGB2101010 )
559+ fb_format = DRM_FORMAT_XRGB2101010 ;
560+ if (dst_format == DRM_FORMAT_ARGB2101010 )
561+ dst_format = DRM_FORMAT_XRGB2101010 ;
503562
504563 if (dst_format == fb_format ) {
505564 drm_fb_memcpy_toio (dst , dst_pitch , vmap , fb , clip );
@@ -515,6 +574,11 @@ int drm_fb_blit_toio(void __iomem *dst, unsigned int dst_pitch, uint32_t dst_for
515574 drm_fb_xrgb8888_to_rgb888_toio (dst , dst_pitch , vmap , fb , clip );
516575 return 0 ;
517576 }
577+ } else if (dst_format == DRM_FORMAT_XRGB2101010 ) {
578+ if (fb_format == DRM_FORMAT_XRGB8888 ) {
579+ drm_fb_xrgb8888_to_xrgb2101010_toio (dst , dst_pitch , vmap , fb , clip );
580+ return 0 ;
581+ }
518582 }
519583
520584 return - EINVAL ;
0 commit comments