root/drivers/gpu/drm/drm_format_helper.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. clip_offset
  2. drm_fb_memcpy
  3. drm_fb_memcpy_dstclip
  4. drm_fb_swab16
  5. drm_fb_xrgb8888_to_rgb565_line
  6. drm_fb_xrgb8888_to_rgb565
  7. drm_fb_xrgb8888_to_rgb565_dstclip
  8. drm_fb_xrgb8888_to_rgb888_line
  9. drm_fb_xrgb8888_to_rgb888_dstclip
  10. drm_fb_xrgb8888_to_gray8

   1 /* SPDX-License-Identifier: GPL-2.0 */
   2 /*
   3  * Copyright (C) 2016 Noralf Trønnes
   4  *
   5  * This program is free software; you can redistribute it and/or modify
   6  * it under the terms of the GNU General Public License as published by
   7  * the Free Software Foundation; either version 2 of the License, or
   8  * (at your option) any later version.
   9  */
  10 
  11 #include <linux/module.h>
  12 #include <linux/slab.h>
  13 #include <linux/io.h>
  14 
  15 #include <drm/drm_format_helper.h>
  16 #include <drm/drm_framebuffer.h>
  17 #include <drm/drm_fourcc.h>
  18 #include <drm/drm_rect.h>
  19 
  20 static unsigned int clip_offset(struct drm_rect *clip,
  21                                 unsigned int pitch, unsigned int cpp)
  22 {
  23         return clip->y1 * pitch + clip->x1 * cpp;
  24 }
  25 
  26 /**
  27  * drm_fb_memcpy - Copy clip buffer
  28  * @dst: Destination buffer
  29  * @vaddr: Source buffer
  30  * @fb: DRM framebuffer
  31  * @clip: Clip rectangle area to copy
  32  *
  33  * This function does not apply clipping on dst, i.e. the destination
  34  * is a small buffer containing the clip rect only.
  35  */
  36 void drm_fb_memcpy(void *dst, void *vaddr, struct drm_framebuffer *fb,
  37                    struct drm_rect *clip)
  38 {
  39         unsigned int cpp = fb->format->cpp[0];
  40         size_t len = (clip->x2 - clip->x1) * cpp;
  41         unsigned int y, lines = clip->y2 - clip->y1;
  42 
  43         vaddr += clip_offset(clip, fb->pitches[0], cpp);
  44         for (y = 0; y < lines; y++) {
  45                 memcpy(dst, vaddr, len);
  46                 vaddr += fb->pitches[0];
  47                 dst += len;
  48         }
  49 }
  50 EXPORT_SYMBOL(drm_fb_memcpy);
  51 
  52 /**
  53  * drm_fb_memcpy_dstclip - Copy clip buffer
  54  * @dst: Destination buffer (iomem)
  55  * @vaddr: Source buffer
  56  * @fb: DRM framebuffer
  57  * @clip: Clip rectangle area to copy
  58  *
  59  * This function applies clipping on dst, i.e. the destination is a
  60  * full (iomem) framebuffer but only the clip rect content is copied over.
  61  */
  62 void drm_fb_memcpy_dstclip(void __iomem *dst, void *vaddr,
  63                            struct drm_framebuffer *fb,
  64                            struct drm_rect *clip)
  65 {
  66         unsigned int cpp = fb->format->cpp[0];
  67         unsigned int offset = clip_offset(clip, fb->pitches[0], cpp);
  68         size_t len = (clip->x2 - clip->x1) * cpp;
  69         unsigned int y, lines = clip->y2 - clip->y1;
  70 
  71         vaddr += offset;
  72         dst += offset;
  73         for (y = 0; y < lines; y++) {
  74                 memcpy_toio(dst, vaddr, len);
  75                 vaddr += fb->pitches[0];
  76                 dst += fb->pitches[0];
  77         }
  78 }
  79 EXPORT_SYMBOL(drm_fb_memcpy_dstclip);
  80 
  81 /**
  82  * drm_fb_swab16 - Swap bytes into clip buffer
  83  * @dst: RGB565 destination buffer
  84  * @vaddr: RGB565 source buffer
  85  * @fb: DRM framebuffer
  86  * @clip: Clip rectangle area to copy
  87  */
  88 void drm_fb_swab16(u16 *dst, void *vaddr, struct drm_framebuffer *fb,
  89                    struct drm_rect *clip)
  90 {
  91         size_t len = (clip->x2 - clip->x1) * sizeof(u16);
  92         unsigned int x, y;
  93         u16 *src, *buf;
  94 
  95         /*
  96          * The cma memory is write-combined so reads are uncached.
  97          * Speed up by fetching one line at a time.
  98          */
  99         buf = kmalloc(len, GFP_KERNEL);
 100         if (!buf)
 101                 return;
 102 
 103         for (y = clip->y1; y < clip->y2; y++) {
 104                 src = vaddr + (y * fb->pitches[0]);
 105                 src += clip->x1;
 106                 memcpy(buf, src, len);
 107                 src = buf;
 108                 for (x = clip->x1; x < clip->x2; x++)
 109                         *dst++ = swab16(*src++);
 110         }
 111 
 112         kfree(buf);
 113 }
 114 EXPORT_SYMBOL(drm_fb_swab16);
 115 
 116 static void drm_fb_xrgb8888_to_rgb565_line(u16 *dbuf, u32 *sbuf,
 117                                            unsigned int pixels,
 118                                            bool swab)
 119 {
 120         unsigned int x;
 121         u16 val16;
 122 
 123         for (x = 0; x < pixels; x++) {
 124                 val16 = ((sbuf[x] & 0x00F80000) >> 8) |
 125                         ((sbuf[x] & 0x0000FC00) >> 5) |
 126                         ((sbuf[x] & 0x000000F8) >> 3);
 127                 if (swab)
 128                         dbuf[x] = swab16(val16);
 129                 else
 130                         dbuf[x] = val16;
 131         }
 132 }
 133 
 134 /**
 135  * drm_fb_xrgb8888_to_rgb565 - Convert XRGB8888 to RGB565 clip buffer
 136  * @dst: RGB565 destination buffer
 137  * @vaddr: XRGB8888 source buffer
 138  * @fb: DRM framebuffer
 139  * @clip: Clip rectangle area to copy
 140  * @swab: Swap bytes
 141  *
 142  * Drivers can use this function for RGB565 devices that don't natively
 143  * support XRGB8888.
 144  *
 145  * This function does not apply clipping on dst, i.e. the destination
 146  * is a small buffer containing the clip rect only.
 147  */
 148 void drm_fb_xrgb8888_to_rgb565(void *dst, void *vaddr,
 149                                struct drm_framebuffer *fb,
 150                                struct drm_rect *clip, bool swab)
 151 {
 152         size_t linepixels = clip->x2 - clip->x1;
 153         size_t src_len = linepixels * sizeof(u32);
 154         size_t dst_len = linepixels * sizeof(u16);
 155         unsigned y, lines = clip->y2 - clip->y1;
 156         void *sbuf;
 157 
 158         /*
 159          * The cma memory is write-combined so reads are uncached.
 160          * Speed up by fetching one line at a time.
 161          */
 162         sbuf = kmalloc(src_len, GFP_KERNEL);
 163         if (!sbuf)
 164                 return;
 165 
 166         vaddr += clip_offset(clip, fb->pitches[0], sizeof(u32));
 167         for (y = 0; y < lines; y++) {
 168                 memcpy(sbuf, vaddr, src_len);
 169                 drm_fb_xrgb8888_to_rgb565_line(dst, sbuf, linepixels, swab);
 170                 vaddr += fb->pitches[0];
 171                 dst += dst_len;
 172         }
 173 
 174         kfree(sbuf);
 175 }
 176 EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb565);
 177 
 178 /**
 179  * drm_fb_xrgb8888_to_rgb565_dstclip - Convert XRGB8888 to RGB565 clip buffer
 180  * @dst: RGB565 destination buffer (iomem)
 181  * @dst_pitch: destination buffer pitch
 182  * @vaddr: XRGB8888 source buffer
 183  * @fb: DRM framebuffer
 184  * @clip: Clip rectangle area to copy
 185  * @swab: Swap bytes
 186  *
 187  * Drivers can use this function for RGB565 devices that don't natively
 188  * support XRGB8888.
 189  *
 190  * This function applies clipping on dst, i.e. the destination is a
 191  * full (iomem) framebuffer but only the clip rect content is copied over.
 192  */
 193 void drm_fb_xrgb8888_to_rgb565_dstclip(void __iomem *dst, unsigned int dst_pitch,
 194                                        void *vaddr, struct drm_framebuffer *fb,
 195                                        struct drm_rect *clip, bool swab)
 196 {
 197         size_t linepixels = clip->x2 - clip->x1;
 198         size_t dst_len = linepixels * sizeof(u16);
 199         unsigned y, lines = clip->y2 - clip->y1;
 200         void *dbuf;
 201 
 202         dbuf = kmalloc(dst_len, GFP_KERNEL);
 203         if (!dbuf)
 204                 return;
 205 
 206         vaddr += clip_offset(clip, fb->pitches[0], sizeof(u32));
 207         dst += clip_offset(clip, dst_pitch, sizeof(u16));
 208         for (y = 0; y < lines; y++) {
 209                 drm_fb_xrgb8888_to_rgb565_line(dbuf, vaddr, linepixels, swab);
 210                 memcpy_toio(dst, dbuf, dst_len);
 211                 vaddr += fb->pitches[0];
 212                 dst += dst_len;
 213         }
 214 
 215         kfree(dbuf);
 216 }
 217 EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb565_dstclip);
 218 
 219 static void drm_fb_xrgb8888_to_rgb888_line(u8 *dbuf, u32 *sbuf,
 220                                            unsigned int pixels)
 221 {
 222         unsigned int x;
 223 
 224         for (x = 0; x < pixels; x++) {
 225                 *dbuf++ = (sbuf[x] & 0x000000FF) >>  0;
 226                 *dbuf++ = (sbuf[x] & 0x0000FF00) >>  8;
 227                 *dbuf++ = (sbuf[x] & 0x00FF0000) >> 16;
 228         }
 229 }
 230 
 231 /**
 232  * drm_fb_xrgb8888_to_rgb888_dstclip - Convert XRGB8888 to RGB888 clip buffer
 233  * @dst: RGB565 destination buffer (iomem)
 234  * @dst_pitch: destination buffer pitch
 235  * @vaddr: XRGB8888 source buffer
 236  * @fb: DRM framebuffer
 237  * @clip: Clip rectangle area to copy
 238  *
 239  * Drivers can use this function for RGB888 devices that don't natively
 240  * support XRGB8888.
 241  *
 242  * This function applies clipping on dst, i.e. the destination is a
 243  * full (iomem) framebuffer but only the clip rect content is copied over.
 244  */
 245 void drm_fb_xrgb8888_to_rgb888_dstclip(void __iomem *dst, unsigned int dst_pitch,
 246                                        void *vaddr, struct drm_framebuffer *fb,
 247                                        struct drm_rect *clip)
 248 {
 249         size_t linepixels = clip->x2 - clip->x1;
 250         size_t dst_len = linepixels * 3;
 251         unsigned y, lines = clip->y2 - clip->y1;
 252         void *dbuf;
 253 
 254         dbuf = kmalloc(dst_len, GFP_KERNEL);
 255         if (!dbuf)
 256                 return;
 257 
 258         vaddr += clip_offset(clip, fb->pitches[0], sizeof(u32));
 259         dst += clip_offset(clip, dst_pitch, sizeof(u16));
 260         for (y = 0; y < lines; y++) {
 261                 drm_fb_xrgb8888_to_rgb888_line(dbuf, vaddr, linepixels);
 262                 memcpy_toio(dst, dbuf, dst_len);
 263                 vaddr += fb->pitches[0];
 264                 dst += dst_len;
 265         }
 266 
 267         kfree(dbuf);
 268 }
 269 EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb888_dstclip);
 270 
 271 /**
 272  * drm_fb_xrgb8888_to_gray8 - Convert XRGB8888 to grayscale
 273  * @dst: 8-bit grayscale destination buffer
 274  * @vaddr: XRGB8888 source buffer
 275  * @fb: DRM framebuffer
 276  * @clip: Clip rectangle area to copy
 277  *
 278  * Drm doesn't have native monochrome or grayscale support.
 279  * Such drivers can announce the commonly supported XR24 format to userspace
 280  * and use this function to convert to the native format.
 281  *
 282  * Monochrome drivers will use the most significant bit,
 283  * where 1 means foreground color and 0 background color.
 284  *
 285  * ITU BT.601 is used for the RGB -> luma (brightness) conversion.
 286  */
 287 void drm_fb_xrgb8888_to_gray8(u8 *dst, void *vaddr, struct drm_framebuffer *fb,
 288                                struct drm_rect *clip)
 289 {
 290         unsigned int len = (clip->x2 - clip->x1) * sizeof(u32);
 291         unsigned int x, y;
 292         void *buf;
 293         u32 *src;
 294 
 295         if (WARN_ON(fb->format->format != DRM_FORMAT_XRGB8888))
 296                 return;
 297         /*
 298          * The cma memory is write-combined so reads are uncached.
 299          * Speed up by fetching one line at a time.
 300          */
 301         buf = kmalloc(len, GFP_KERNEL);
 302         if (!buf)
 303                 return;
 304 
 305         for (y = clip->y1; y < clip->y2; y++) {
 306                 src = vaddr + (y * fb->pitches[0]);
 307                 src += clip->x1;
 308                 memcpy(buf, src, len);
 309                 src = buf;
 310                 for (x = clip->x1; x < clip->x2; x++) {
 311                         u8 r = (*src & 0x00ff0000) >> 16;
 312                         u8 g = (*src & 0x0000ff00) >> 8;
 313                         u8 b =  *src & 0x000000ff;
 314 
 315                         /* ITU BT.601: Y = 0.299 R + 0.587 G + 0.114 B */
 316                         *dst++ = (3 * r + 6 * g + b) / 10;
 317                         src++;
 318                 }
 319         }
 320 
 321         kfree(buf);
 322 }
 323 EXPORT_SYMBOL(drm_fb_xrgb8888_to_gray8);
 324 

/* [<][>][^][v][top][bottom][index][help] */