summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/drm_format_helper.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/drm_format_helper.c')
-rw-r--r--drivers/gpu/drm/drm_format_helper.c46
1 files changed, 46 insertions, 0 deletions
diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c
index c83e0bb2e8c7..34b7ef443ad2 100644
--- a/drivers/gpu/drm/drm_format_helper.c
+++ b/drivers/gpu/drm/drm_format_helper.c
@@ -411,6 +411,49 @@ void drm_fb_xrgb8888_to_rgb888_toio(void __iomem *dst, unsigned int dst_pitch,
}
EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb888_toio);
+static void drm_fb_rgb565_to_xrgb8888_line(void *dbuf, const void *sbuf, unsigned int pixels)
+{
+ u32 *dbuf32 = dbuf;
+ const u16 *sbuf16 = sbuf;
+ unsigned int x;
+
+ for (x = 0; x < pixels; x++, ++sbuf16, ++dbuf32) {
+ u32 val32 = ((*sbuf16 & 0xf800) << 8) |
+ ((*sbuf16 & 0x07e0) << 5) |
+ ((*sbuf16 & 0x001f) << 3);
+ *dbuf32 = 0xff000000 | val32 |
+ ((val32 >> 3) & 0x00070007) |
+ ((val32 >> 2) & 0x00000300);
+ }
+}
+
+static void drm_fb_rgb565_to_xrgb8888_toio(void __iomem *dst, unsigned int dst_pitch,
+ const void *vaddr, const struct drm_framebuffer *fb,
+ const struct drm_rect *clip)
+{
+ size_t linepixels = drm_rect_width(clip);
+ size_t dst_len = linepixels * 4;
+ unsigned int y, lines = drm_rect_height(clip);
+ void *dbuf;
+
+ if (!dst_pitch)
+ dst_pitch = dst_len;
+
+ dbuf = kmalloc(dst_len, GFP_KERNEL);
+ if (!dbuf)
+ return;
+
+ vaddr += clip_offset(clip, fb->pitches[0], 2);
+ for (y = 0; y < lines; y++) {
+ drm_fb_rgb565_to_xrgb8888_line(dbuf, vaddr, linepixels);
+ memcpy_toio(dst, dbuf, dst_len);
+ vaddr += fb->pitches[0];
+ dst += dst_pitch;
+ }
+
+ kfree(dbuf);
+}
+
static void drm_fb_rgb888_to_xrgb8888_line(void *dbuf, const void *sbuf, unsigned int pixels)
{
u32 *dbuf32 = dbuf;
@@ -628,6 +671,9 @@ int drm_fb_blit_toio(void __iomem *dst, unsigned int dst_pitch, uint32_t dst_for
if (fb_format == DRM_FORMAT_RGB888) {
drm_fb_rgb888_to_xrgb8888_toio(dst, dst_pitch, vmap, fb, clip);
return 0;
+ } else if (fb_format == DRM_FORMAT_RGB565) {
+ drm_fb_rgb565_to_xrgb8888_toio(dst, dst_pitch, vmap, fb, clip);
+ return 0;
}
} else if (dst_format == DRM_FORMAT_XRGB2101010) {
if (fb_format == DRM_FORMAT_XRGB8888) {