1 // SPDX-License-Identifier: GPL-2.0 or MIT 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/io.h> 12 #include <linux/iosys-map.h> 13 #include <linux/module.h> 14 #include <linux/slab.h> 15 16 #include <drm/drm_device.h> 17 #include <drm/drm_format_helper.h> 18 #include <drm/drm_framebuffer.h> 19 #include <drm/drm_fourcc.h> 20 #include <drm/drm_print.h> 21 #include <drm/drm_rect.h> 22 23 static unsigned int clip_offset(const struct drm_rect *clip, unsigned int pitch, unsigned int cpp) 24 { 25 return clip->y1 * pitch + clip->x1 * cpp; 26 } 27 28 /** 29 * drm_fb_clip_offset - Returns the clipping rectangles byte-offset in a framebuffer 30 * @pitch: Framebuffer line pitch in byte 31 * @format: Framebuffer format 32 * @clip: Clip rectangle 33 * 34 * Returns: 35 * The byte offset of the clip rectangle's top-left corner within the framebuffer. 36 */ 37 unsigned int drm_fb_clip_offset(unsigned int pitch, const struct drm_format_info *format, 38 const struct drm_rect *clip) 39 { 40 return clip_offset(clip, pitch, format->cpp[0]); 41 } 42 EXPORT_SYMBOL(drm_fb_clip_offset); 43 44 /* TODO: Make this function work with multi-plane formats. */ 45 static int __drm_fb_xfrm(void *dst, unsigned long dst_pitch, unsigned long dst_pixsize, 46 const void *vaddr, const struct drm_framebuffer *fb, 47 const struct drm_rect *clip, bool vaddr_cached_hint, 48 void (*xfrm_line)(void *dbuf, const void *sbuf, unsigned int npixels)) 49 { 50 unsigned long linepixels = drm_rect_width(clip); 51 unsigned long lines = drm_rect_height(clip); 52 size_t sbuf_len = linepixels * fb->format->cpp[0]; 53 void *stmp = NULL; 54 unsigned long i; 55 const void *sbuf; 56 57 /* 58 * Some source buffers, such as DMA memory, use write-combine 59 * caching, so reads are uncached. Speed up access by fetching 60 * one line at a time. 61 */ 62 if (!vaddr_cached_hint) { 63 stmp = kmalloc(sbuf_len, GFP_KERNEL); 64 if (!stmp) 65 return -ENOMEM; 66 } 67 68 if (!dst_pitch) 69 dst_pitch = drm_rect_width(clip) * dst_pixsize; 70 vaddr += clip_offset(clip, fb->pitches[0], fb->format->cpp[0]); 71 72 for (i = 0; i < lines; ++i) { 73 if (stmp) 74 sbuf = memcpy(stmp, vaddr, sbuf_len); 75 else 76 sbuf = vaddr; 77 xfrm_line(dst, sbuf, linepixels); 78 vaddr += fb->pitches[0]; 79 dst += dst_pitch; 80 } 81 82 kfree(stmp); 83 84 return 0; 85 } 86 87 /* TODO: Make this function work with multi-plane formats. */ 88 static int __drm_fb_xfrm_toio(void __iomem *dst, unsigned long dst_pitch, unsigned long dst_pixsize, 89 const void *vaddr, const struct drm_framebuffer *fb, 90 const struct drm_rect *clip, bool vaddr_cached_hint, 91 void (*xfrm_line)(void *dbuf, const void *sbuf, unsigned int npixels)) 92 { 93 unsigned long linepixels = drm_rect_width(clip); 94 unsigned long lines = drm_rect_height(clip); 95 size_t dbuf_len = linepixels * dst_pixsize; 96 size_t stmp_off = round_up(dbuf_len, ARCH_KMALLOC_MINALIGN); /* for sbuf alignment */ 97 size_t sbuf_len = linepixels * fb->format->cpp[0]; 98 void *stmp = NULL; 99 unsigned long i; 100 const void *sbuf; 101 void *dbuf; 102 103 if (vaddr_cached_hint) { 104 dbuf = kmalloc(dbuf_len, GFP_KERNEL); 105 } else { 106 dbuf = kmalloc(stmp_off + sbuf_len, GFP_KERNEL); 107 stmp = dbuf + stmp_off; 108 } 109 if (!dbuf) 110 return -ENOMEM; 111 112 if (!dst_pitch) 113 dst_pitch = linepixels * dst_pixsize; 114 vaddr += clip_offset(clip, fb->pitches[0], fb->format->cpp[0]); 115 116 for (i = 0; i < lines; ++i) { 117 if (stmp) 118 sbuf = memcpy(stmp, vaddr, sbuf_len); 119 else 120 sbuf = vaddr; 121 xfrm_line(dbuf, sbuf, linepixels); 122 memcpy_toio(dst, dbuf, dbuf_len); 123 vaddr += fb->pitches[0]; 124 dst += dst_pitch; 125 } 126 127 kfree(dbuf); 128 129 return 0; 130 } 131 132 /* TODO: Make this function work with multi-plane formats. */ 133 static int drm_fb_xfrm(struct iosys_map *dst, 134 const unsigned int *dst_pitch, const u8 *dst_pixsize, 135 const struct iosys_map *src, const struct drm_framebuffer *fb, 136 const struct drm_rect *clip, bool vaddr_cached_hint, 137 void (*xfrm_line)(void *dbuf, const void *sbuf, unsigned int npixels)) 138 { 139 static const unsigned int default_dst_pitch[DRM_FORMAT_MAX_PLANES] = { 140 0, 0, 0, 0 141 }; 142 143 if (!dst_pitch) 144 dst_pitch = default_dst_pitch; 145 146 /* TODO: handle src in I/O memory here */ 147 if (dst[0].is_iomem) 148 return __drm_fb_xfrm_toio(dst[0].vaddr_iomem, dst_pitch[0], dst_pixsize[0], 149 src[0].vaddr, fb, clip, vaddr_cached_hint, xfrm_line); 150 else 151 return __drm_fb_xfrm(dst[0].vaddr, dst_pitch[0], dst_pixsize[0], 152 src[0].vaddr, fb, clip, vaddr_cached_hint, xfrm_line); 153 } 154 155 /** 156 * drm_fb_memcpy - Copy clip buffer 157 * @dst: Array of destination buffers 158 * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines 159 * within @dst; can be NULL if scanlines are stored next to each other. 160 * @src: Array of source buffers 161 * @fb: DRM framebuffer 162 * @clip: Clip rectangle area to copy 163 * 164 * This function copies parts of a framebuffer to display memory. Destination and 165 * framebuffer formats must match. No conversion takes place. The parameters @dst, 166 * @dst_pitch and @src refer to arrays. Each array must have at least as many entries 167 * as there are planes in @fb's format. Each entry stores the value for the format's 168 * respective color plane at the same index. 169 * 170 * This function does not apply clipping on @dst (i.e. the destination is at the 171 * top-left corner). 172 */ 173 void drm_fb_memcpy(struct iosys_map *dst, const unsigned int *dst_pitch, 174 const struct iosys_map *src, const struct drm_framebuffer *fb, 175 const struct drm_rect *clip) 176 { 177 static const unsigned int default_dst_pitch[DRM_FORMAT_MAX_PLANES] = { 178 0, 0, 0, 0 179 }; 180 181 const struct drm_format_info *format = fb->format; 182 unsigned int i, y, lines = drm_rect_height(clip); 183 184 if (!dst_pitch) 185 dst_pitch = default_dst_pitch; 186 187 for (i = 0; i < format->num_planes; ++i) { 188 unsigned int bpp_i = drm_format_info_bpp(format, i); 189 unsigned int cpp_i = DIV_ROUND_UP(bpp_i, 8); 190 size_t len_i = DIV_ROUND_UP(drm_rect_width(clip) * bpp_i, 8); 191 unsigned int dst_pitch_i = dst_pitch[i]; 192 struct iosys_map dst_i = dst[i]; 193 struct iosys_map src_i = src[i]; 194 195 if (!dst_pitch_i) 196 dst_pitch_i = len_i; 197 198 iosys_map_incr(&src_i, clip_offset(clip, fb->pitches[i], cpp_i)); 199 for (y = 0; y < lines; y++) { 200 /* TODO: handle src_i in I/O memory here */ 201 iosys_map_memcpy_to(&dst_i, 0, src_i.vaddr, len_i); 202 iosys_map_incr(&src_i, fb->pitches[i]); 203 iosys_map_incr(&dst_i, dst_pitch_i); 204 } 205 } 206 } 207 EXPORT_SYMBOL(drm_fb_memcpy); 208 209 static void drm_fb_swab16_line(void *dbuf, const void *sbuf, unsigned int pixels) 210 { 211 u16 *dbuf16 = dbuf; 212 const u16 *sbuf16 = sbuf; 213 const u16 *send16 = sbuf16 + pixels; 214 215 while (sbuf16 < send16) 216 *dbuf16++ = swab16(*sbuf16++); 217 } 218 219 static void drm_fb_swab32_line(void *dbuf, const void *sbuf, unsigned int pixels) 220 { 221 u32 *dbuf32 = dbuf; 222 const u32 *sbuf32 = sbuf; 223 const u32 *send32 = sbuf32 + pixels; 224 225 while (sbuf32 < send32) 226 *dbuf32++ = swab32(*sbuf32++); 227 } 228 229 /** 230 * drm_fb_swab - Swap bytes into clip buffer 231 * @dst: Array of destination buffers 232 * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines 233 * within @dst; can be NULL if scanlines are stored next to each other. 234 * @src: Array of source buffers 235 * @fb: DRM framebuffer 236 * @clip: Clip rectangle area to copy 237 * @cached: Source buffer is mapped cached (eg. not write-combined) 238 * 239 * This function copies parts of a framebuffer to display memory and swaps per-pixel 240 * bytes during the process. Destination and framebuffer formats must match. The 241 * parameters @dst, @dst_pitch and @src refer to arrays. Each array must have at 242 * least as many entries as there are planes in @fb's format. Each entry stores the 243 * value for the format's respective color plane at the same index. If @cached is 244 * false a temporary buffer is used to cache one pixel line at a time to speed up 245 * slow uncached reads. 246 * 247 * This function does not apply clipping on @dst (i.e. the destination is at the 248 * top-left corner). 249 */ 250 void drm_fb_swab(struct iosys_map *dst, const unsigned int *dst_pitch, 251 const struct iosys_map *src, const struct drm_framebuffer *fb, 252 const struct drm_rect *clip, bool cached) 253 { 254 const struct drm_format_info *format = fb->format; 255 u8 cpp = DIV_ROUND_UP(drm_format_info_bpp(format, 0), 8); 256 void (*swab_line)(void *dbuf, const void *sbuf, unsigned int npixels); 257 258 switch (cpp) { 259 case 4: 260 swab_line = drm_fb_swab32_line; 261 break; 262 case 2: 263 swab_line = drm_fb_swab16_line; 264 break; 265 default: 266 drm_warn_once(fb->dev, "Format %p4cc has unsupported pixel size.\n", 267 &format->format); 268 return; 269 } 270 271 drm_fb_xfrm(dst, dst_pitch, &cpp, src, fb, clip, cached, swab_line); 272 } 273 EXPORT_SYMBOL(drm_fb_swab); 274 275 static void drm_fb_xrgb8888_to_rgb332_line(void *dbuf, const void *sbuf, unsigned int pixels) 276 { 277 u8 *dbuf8 = dbuf; 278 const __le32 *sbuf32 = sbuf; 279 unsigned int x; 280 u32 pix; 281 282 for (x = 0; x < pixels; x++) { 283 pix = le32_to_cpu(sbuf32[x]); 284 dbuf8[x] = ((pix & 0x00e00000) >> 16) | 285 ((pix & 0x0000e000) >> 11) | 286 ((pix & 0x000000c0) >> 6); 287 } 288 } 289 290 /** 291 * drm_fb_xrgb8888_to_rgb332 - Convert XRGB8888 to RGB332 clip buffer 292 * @dst: Array of RGB332 destination buffers 293 * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines 294 * within @dst; can be NULL if scanlines are stored next to each other. 295 * @src: Array of XRGB8888 source buffers 296 * @fb: DRM framebuffer 297 * @clip: Clip rectangle area to copy 298 * 299 * This function copies parts of a framebuffer to display memory and converts the 300 * color format during the process. Destination and framebuffer formats must match. The 301 * parameters @dst, @dst_pitch and @src refer to arrays. Each array must have at 302 * least as many entries as there are planes in @fb's format. Each entry stores the 303 * value for the format's respective color plane at the same index. 304 * 305 * This function does not apply clipping on @dst (i.e. the destination is at the 306 * top-left corner). 307 * 308 * Drivers can use this function for RGB332 devices that don't support XRGB8888 natively. 309 */ 310 void drm_fb_xrgb8888_to_rgb332(struct iosys_map *dst, const unsigned int *dst_pitch, 311 const struct iosys_map *src, const struct drm_framebuffer *fb, 312 const struct drm_rect *clip) 313 { 314 static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = { 315 1, 316 }; 317 318 drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, 319 drm_fb_xrgb8888_to_rgb332_line); 320 } 321 EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb332); 322 323 static void drm_fb_xrgb8888_to_rgb565_line(void *dbuf, const void *sbuf, unsigned int pixels) 324 { 325 u16 *dbuf16 = dbuf; 326 const __le32 *sbuf32 = sbuf; 327 unsigned int x; 328 u16 val16; 329 u32 pix; 330 331 for (x = 0; x < pixels; x++) { 332 pix = le32_to_cpu(sbuf32[x]); 333 val16 = ((pix & 0x00F80000) >> 8) | 334 ((pix & 0x0000FC00) >> 5) | 335 ((pix & 0x000000F8) >> 3); 336 dbuf16[x] = val16; 337 } 338 } 339 340 static void drm_fb_xrgb8888_to_rgb565_swab_line(void *dbuf, const void *sbuf, 341 unsigned int pixels) 342 { 343 u16 *dbuf16 = dbuf; 344 const __le32 *sbuf32 = sbuf; 345 unsigned int x; 346 u16 val16; 347 u32 pix; 348 349 for (x = 0; x < pixels; x++) { 350 pix = le32_to_cpu(sbuf32[x]); 351 val16 = ((pix & 0x00F80000) >> 8) | 352 ((pix & 0x0000FC00) >> 5) | 353 ((pix & 0x000000F8) >> 3); 354 dbuf16[x] = swab16(val16); 355 } 356 } 357 358 /** 359 * drm_fb_xrgb8888_to_rgb565 - Convert XRGB8888 to RGB565 clip buffer 360 * @dst: Array of RGB565 destination buffers 361 * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines 362 * within @dst; can be NULL if scanlines are stored next to each other. 363 * @src: Array of XRGB8888 source buffer 364 * @fb: DRM framebuffer 365 * @clip: Clip rectangle area to copy 366 * @swab: Swap bytes 367 * 368 * This function copies parts of a framebuffer to display memory and converts the 369 * color format during the process. Destination and framebuffer formats must match. The 370 * parameters @dst, @dst_pitch and @src refer to arrays. Each array must have at 371 * least as many entries as there are planes in @fb's format. Each entry stores the 372 * value for the format's respective color plane at the same index. 373 * 374 * This function does not apply clipping on @dst (i.e. the destination is at the 375 * top-left corner). 376 * 377 * Drivers can use this function for RGB565 devices that don't support XRGB8888 natively. 378 */ 379 void drm_fb_xrgb8888_to_rgb565(struct iosys_map *dst, const unsigned int *dst_pitch, 380 const struct iosys_map *src, const struct drm_framebuffer *fb, 381 const struct drm_rect *clip, bool swab) 382 { 383 static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = { 384 2, 385 }; 386 387 void (*xfrm_line)(void *dbuf, const void *sbuf, unsigned int npixels); 388 389 if (swab) 390 xfrm_line = drm_fb_xrgb8888_to_rgb565_swab_line; 391 else 392 xfrm_line = drm_fb_xrgb8888_to_rgb565_line; 393 394 drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, xfrm_line); 395 } 396 EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb565); 397 398 static void drm_fb_xrgb8888_to_rgb888_line(void *dbuf, const void *sbuf, unsigned int pixels) 399 { 400 u8 *dbuf8 = dbuf; 401 const __le32 *sbuf32 = sbuf; 402 unsigned int x; 403 u32 pix; 404 405 for (x = 0; x < pixels; x++) { 406 pix = le32_to_cpu(sbuf32[x]); 407 *dbuf8++ = (pix & 0x000000FF) >> 0; 408 *dbuf8++ = (pix & 0x0000FF00) >> 8; 409 *dbuf8++ = (pix & 0x00FF0000) >> 16; 410 } 411 } 412 413 /** 414 * drm_fb_xrgb8888_to_rgb888 - Convert XRGB8888 to RGB888 clip buffer 415 * @dst: Array of RGB888 destination buffers 416 * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines 417 * within @dst; can be NULL if scanlines are stored next to each other. 418 * @src: Array of XRGB8888 source buffers 419 * @fb: DRM framebuffer 420 * @clip: Clip rectangle area to copy 421 * 422 * This function copies parts of a framebuffer to display memory and converts the 423 * color format during the process. Destination and framebuffer formats must match. The 424 * parameters @dst, @dst_pitch and @src refer to arrays. Each array must have at 425 * least as many entries as there are planes in @fb's format. Each entry stores the 426 * value for the format's respective color plane at the same index. 427 * 428 * This function does not apply clipping on @dst (i.e. the destination is at the 429 * top-left corner). 430 * 431 * Drivers can use this function for RGB888 devices that don't natively 432 * support XRGB8888. 433 */ 434 void drm_fb_xrgb8888_to_rgb888(struct iosys_map *dst, const unsigned int *dst_pitch, 435 const struct iosys_map *src, const struct drm_framebuffer *fb, 436 const struct drm_rect *clip) 437 { 438 static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = { 439 3, 440 }; 441 442 drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, 443 drm_fb_xrgb8888_to_rgb888_line); 444 } 445 EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb888); 446 447 static void drm_fb_rgb565_to_xrgb8888_line(void *dbuf, const void *sbuf, unsigned int pixels) 448 { 449 __le32 *dbuf32 = dbuf; 450 const __le16 *sbuf16 = sbuf; 451 unsigned int x; 452 453 for (x = 0; x < pixels; x++) { 454 u16 val16 = le16_to_cpu(sbuf16[x]); 455 u32 val32 = ((val16 & 0xf800) << 8) | 456 ((val16 & 0x07e0) << 5) | 457 ((val16 & 0x001f) << 3); 458 val32 = 0xff000000 | val32 | 459 ((val32 >> 3) & 0x00070007) | 460 ((val32 >> 2) & 0x00000300); 461 dbuf32[x] = cpu_to_le32(val32); 462 } 463 } 464 465 static void drm_fb_rgb565_to_xrgb8888(struct iosys_map *dst, const unsigned int *dst_pitch, 466 const struct iosys_map *src, 467 const struct drm_framebuffer *fb, 468 const struct drm_rect *clip) 469 { 470 static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = { 471 4, 472 }; 473 474 drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, 475 drm_fb_rgb565_to_xrgb8888_line); 476 } 477 478 static void drm_fb_rgb888_to_xrgb8888_line(void *dbuf, const void *sbuf, unsigned int pixels) 479 { 480 __le32 *dbuf32 = dbuf; 481 const u8 *sbuf8 = sbuf; 482 unsigned int x; 483 484 for (x = 0; x < pixels; x++) { 485 u8 r = *sbuf8++; 486 u8 g = *sbuf8++; 487 u8 b = *sbuf8++; 488 u32 pix = 0xff000000 | (r << 16) | (g << 8) | b; 489 dbuf32[x] = cpu_to_le32(pix); 490 } 491 } 492 493 static void drm_fb_rgb888_to_xrgb8888(struct iosys_map *dst, const unsigned int *dst_pitch, 494 const struct iosys_map *src, 495 const struct drm_framebuffer *fb, 496 const struct drm_rect *clip) 497 { 498 static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = { 499 4, 500 }; 501 502 drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, 503 drm_fb_rgb888_to_xrgb8888_line); 504 } 505 506 static void drm_fb_xrgb8888_to_xrgb2101010_line(void *dbuf, const void *sbuf, unsigned int pixels) 507 { 508 __le32 *dbuf32 = dbuf; 509 const __le32 *sbuf32 = sbuf; 510 unsigned int x; 511 u32 val32; 512 u32 pix; 513 514 for (x = 0; x < pixels; x++) { 515 pix = le32_to_cpu(sbuf32[x]); 516 val32 = ((pix & 0x000000FF) << 2) | 517 ((pix & 0x0000FF00) << 4) | 518 ((pix & 0x00FF0000) << 6); 519 pix = val32 | ((val32 >> 8) & 0x00300C03); 520 *dbuf32++ = cpu_to_le32(pix); 521 } 522 } 523 524 /** 525 * drm_fb_xrgb8888_to_xrgb2101010 - Convert XRGB8888 to XRGB2101010 clip buffer 526 * @dst: Array of XRGB2101010 destination buffers 527 * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines 528 * within @dst; can be NULL if scanlines are stored next to each other. 529 * @src: Array of XRGB8888 source buffers 530 * @fb: DRM framebuffer 531 * @clip: Clip rectangle area to copy 532 * 533 * This function copies parts of a framebuffer to display memory and converts the 534 * color format during the process. Destination and framebuffer formats must match. The 535 * parameters @dst, @dst_pitch and @src refer to arrays. Each array must have at 536 * least as many entries as there are planes in @fb's format. Each entry stores the 537 * value for the format's respective color plane at the same index. 538 * 539 * This function does not apply clipping on @dst (i.e. the destination is at the 540 * top-left corner). 541 * 542 * Drivers can use this function for XRGB2101010 devices that don't support XRGB8888 543 * natively. 544 */ 545 void drm_fb_xrgb8888_to_xrgb2101010(struct iosys_map *dst, const unsigned int *dst_pitch, 546 const struct iosys_map *src, const struct drm_framebuffer *fb, 547 const struct drm_rect *clip) 548 { 549 static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = { 550 4, 551 }; 552 553 drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, 554 drm_fb_xrgb8888_to_xrgb2101010_line); 555 } 556 557 static void drm_fb_xrgb8888_to_gray8_line(void *dbuf, const void *sbuf, unsigned int pixels) 558 { 559 u8 *dbuf8 = dbuf; 560 const __le32 *sbuf32 = sbuf; 561 unsigned int x; 562 563 for (x = 0; x < pixels; x++) { 564 u32 pix = le32_to_cpu(sbuf32[x]); 565 u8 r = (pix & 0x00ff0000) >> 16; 566 u8 g = (pix & 0x0000ff00) >> 8; 567 u8 b = pix & 0x000000ff; 568 569 /* ITU BT.601: Y = 0.299 R + 0.587 G + 0.114 B */ 570 *dbuf8++ = (3 * r + 6 * g + b) / 10; 571 } 572 } 573 574 /** 575 * drm_fb_xrgb8888_to_gray8 - Convert XRGB8888 to grayscale 576 * @dst: Array of 8-bit grayscale destination buffers 577 * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines 578 * within @dst; can be NULL if scanlines are stored next to each other. 579 * @src: Array of XRGB8888 source buffers 580 * @fb: DRM framebuffer 581 * @clip: Clip rectangle area to copy 582 * 583 * This function copies parts of a framebuffer to display memory and converts the 584 * color format during the process. Destination and framebuffer formats must match. The 585 * parameters @dst, @dst_pitch and @src refer to arrays. Each array must have at 586 * least as many entries as there are planes in @fb's format. Each entry stores the 587 * value for the format's respective color plane at the same index. 588 * 589 * This function does not apply clipping on @dst (i.e. the destination is at the 590 * top-left corner). 591 * 592 * DRM doesn't have native monochrome or grayscale support. Drivers can use this 593 * function for grayscale devices that don't support XRGB8888 natively.Such 594 * drivers can announce the commonly supported XR24 format to userspace and use 595 * this function to convert to the native format. Monochrome drivers will use the 596 * most significant bit, where 1 means foreground color and 0 background color. 597 * ITU BT.601 is being used for the RGB -> luma (brightness) conversion. 598 */ 599 void drm_fb_xrgb8888_to_gray8(struct iosys_map *dst, const unsigned int *dst_pitch, 600 const struct iosys_map *src, const struct drm_framebuffer *fb, 601 const struct drm_rect *clip) 602 { 603 static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = { 604 1, 605 }; 606 607 drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, 608 drm_fb_xrgb8888_to_gray8_line); 609 } 610 EXPORT_SYMBOL(drm_fb_xrgb8888_to_gray8); 611 612 /** 613 * drm_fb_blit - Copy parts of a framebuffer to display memory 614 * @dst: Array of display-memory addresses to copy to 615 * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines 616 * within @dst; can be NULL if scanlines are stored next to each other. 617 * @dst_format: FOURCC code of the display's color format 618 * @src: The framebuffer memory to copy from 619 * @fb: The framebuffer to copy from 620 * @clip: Clip rectangle area to copy 621 * 622 * This function copies parts of a framebuffer to display memory. If the 623 * formats of the display and the framebuffer mismatch, the blit function 624 * will attempt to convert between them during the process. The parameters @dst, 625 * @dst_pitch and @src refer to arrays. Each array must have at least as many 626 * entries as there are planes in @dst_format's format. Each entry stores the 627 * value for the format's respective color plane at the same index. 628 * 629 * This function does not apply clipping on @dst (i.e. the destination is at the 630 * top-left corner). 631 * 632 * Returns: 633 * 0 on success, or 634 * -EINVAL if the color-format conversion failed, or 635 * a negative error code otherwise. 636 */ 637 int drm_fb_blit(struct iosys_map *dst, const unsigned int *dst_pitch, uint32_t dst_format, 638 const struct iosys_map *src, const struct drm_framebuffer *fb, 639 const struct drm_rect *clip) 640 { 641 uint32_t fb_format = fb->format->format; 642 643 /* treat alpha channel like filler bits */ 644 if (fb_format == DRM_FORMAT_ARGB8888) 645 fb_format = DRM_FORMAT_XRGB8888; 646 if (dst_format == DRM_FORMAT_ARGB8888) 647 dst_format = DRM_FORMAT_XRGB8888; 648 if (fb_format == DRM_FORMAT_ARGB2101010) 649 fb_format = DRM_FORMAT_XRGB2101010; 650 if (dst_format == DRM_FORMAT_ARGB2101010) 651 dst_format = DRM_FORMAT_XRGB2101010; 652 653 if (dst_format == fb_format) { 654 drm_fb_memcpy(dst, dst_pitch, src, fb, clip); 655 return 0; 656 657 } else if (dst_format == DRM_FORMAT_RGB565) { 658 if (fb_format == DRM_FORMAT_XRGB8888) { 659 drm_fb_xrgb8888_to_rgb565(dst, dst_pitch, src, fb, clip, false); 660 return 0; 661 } 662 } else if (dst_format == DRM_FORMAT_RGB888) { 663 if (fb_format == DRM_FORMAT_XRGB8888) { 664 drm_fb_xrgb8888_to_rgb888(dst, dst_pitch, src, fb, clip); 665 return 0; 666 } 667 } else if (dst_format == DRM_FORMAT_XRGB8888) { 668 if (fb_format == DRM_FORMAT_RGB888) { 669 drm_fb_rgb888_to_xrgb8888(dst, dst_pitch, src, fb, clip); 670 return 0; 671 } else if (fb_format == DRM_FORMAT_RGB565) { 672 drm_fb_rgb565_to_xrgb8888(dst, dst_pitch, src, fb, clip); 673 return 0; 674 } 675 } else if (dst_format == DRM_FORMAT_XRGB2101010) { 676 if (fb_format == DRM_FORMAT_XRGB8888) { 677 drm_fb_xrgb8888_to_xrgb2101010(dst, dst_pitch, src, fb, clip); 678 return 0; 679 } 680 } 681 682 drm_warn_once(fb->dev, "No conversion helper from %p4cc to %p4cc found.\n", 683 &fb_format, &dst_format); 684 685 return -EINVAL; 686 } 687 EXPORT_SYMBOL(drm_fb_blit); 688 689 static void drm_fb_gray8_to_mono_line(void *dbuf, const void *sbuf, unsigned int pixels) 690 { 691 u8 *dbuf8 = dbuf; 692 const u8 *sbuf8 = sbuf; 693 694 while (pixels) { 695 unsigned int i, bits = min(pixels, 8U); 696 u8 byte = 0; 697 698 for (i = 0; i < bits; i++, pixels--) { 699 if (*sbuf8++ >= 128) 700 byte |= BIT(i); 701 } 702 *dbuf8++ = byte; 703 } 704 } 705 706 /** 707 * drm_fb_xrgb8888_to_mono - Convert XRGB8888 to monochrome 708 * @dst: Array of monochrome destination buffers (0=black, 1=white) 709 * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines 710 * within @dst; can be NULL if scanlines are stored next to each other. 711 * @src: Array of XRGB8888 source buffers 712 * @fb: DRM framebuffer 713 * @clip: Clip rectangle area to copy 714 * 715 * This function copies parts of a framebuffer to display memory and converts the 716 * color format during the process. Destination and framebuffer formats must match. The 717 * parameters @dst, @dst_pitch and @src refer to arrays. Each array must have at 718 * least as many entries as there are planes in @fb's format. Each entry stores the 719 * value for the format's respective color plane at the same index. 720 * 721 * This function does not apply clipping on @dst (i.e. the destination is at the 722 * top-left corner). The first pixel (upper left corner of the clip rectangle) will 723 * be converted and copied to the first bit (LSB) in the first byte of the monochrome 724 * destination buffer. If the caller requires that the first pixel in a byte must 725 * be located at an x-coordinate that is a multiple of 8, then the caller must take 726 * care itself of supplying a suitable clip rectangle. 727 * 728 * DRM doesn't have native monochrome support. Drivers can use this function for 729 * monochrome devices that don't support XRGB8888 natively. Such drivers can 730 * announce the commonly supported XR24 format to userspace and use this function 731 * to convert to the native format. 732 * 733 * This function uses drm_fb_xrgb8888_to_gray8() to convert to grayscale and 734 * then the result is converted from grayscale to monochrome. 735 */ 736 void drm_fb_xrgb8888_to_mono(struct iosys_map *dst, const unsigned int *dst_pitch, 737 const struct iosys_map *src, const struct drm_framebuffer *fb, 738 const struct drm_rect *clip) 739 { 740 static const unsigned int default_dst_pitch[DRM_FORMAT_MAX_PLANES] = { 741 0, 0, 0, 0 742 }; 743 unsigned int linepixels = drm_rect_width(clip); 744 unsigned int lines = drm_rect_height(clip); 745 unsigned int cpp = fb->format->cpp[0]; 746 unsigned int len_src32 = linepixels * cpp; 747 struct drm_device *dev = fb->dev; 748 void *vaddr = src[0].vaddr; 749 unsigned int dst_pitch_0; 750 unsigned int y; 751 u8 *mono = dst[0].vaddr, *gray8; 752 u32 *src32; 753 754 if (drm_WARN_ON(dev, fb->format->format != DRM_FORMAT_XRGB8888)) 755 return; 756 757 if (!dst_pitch) 758 dst_pitch = default_dst_pitch; 759 dst_pitch_0 = dst_pitch[0]; 760 761 /* 762 * The mono destination buffer contains 1 bit per pixel 763 */ 764 if (!dst_pitch_0) 765 dst_pitch_0 = DIV_ROUND_UP(linepixels, 8); 766 767 /* 768 * The dma memory is write-combined so reads are uncached. 769 * Speed up by fetching one line at a time. 770 * 771 * Also, format conversion from XR24 to monochrome are done 772 * line-by-line but are converted to 8-bit grayscale as an 773 * intermediate step. 774 * 775 * Allocate a buffer to be used for both copying from the cma 776 * memory and to store the intermediate grayscale line pixels. 777 */ 778 src32 = kmalloc(len_src32 + linepixels, GFP_KERNEL); 779 if (!src32) 780 return; 781 782 gray8 = (u8 *)src32 + len_src32; 783 784 vaddr += clip_offset(clip, fb->pitches[0], cpp); 785 for (y = 0; y < lines; y++) { 786 src32 = memcpy(src32, vaddr, len_src32); 787 drm_fb_xrgb8888_to_gray8_line(gray8, src32, linepixels); 788 drm_fb_gray8_to_mono_line(mono, gray8, linepixels); 789 vaddr += fb->pitches[0]; 790 mono += dst_pitch_0; 791 } 792 793 kfree(src32); 794 } 795 EXPORT_SYMBOL(drm_fb_xrgb8888_to_mono); 796