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/export.h> 12 #include <linux/io.h> 13 #include <linux/iosys-map.h> 14 #include <linux/module.h> 15 #include <linux/slab.h> 16 17 #include <drm/drm_device.h> 18 #include <drm/drm_format_helper.h> 19 #include <drm/drm_framebuffer.h> 20 #include <drm/drm_fourcc.h> 21 #include <drm/drm_print.h> 22 #include <drm/drm_rect.h> 23 24 #include "drm_format_internal.h" 25 26 /** 27 * drm_format_conv_state_init - Initialize format-conversion state 28 * @state: The state to initialize 29 * 30 * Clears all fields in struct drm_format_conv_state. The state will 31 * be empty with no preallocated resources. 32 */ 33 void drm_format_conv_state_init(struct drm_format_conv_state *state) 34 { 35 state->tmp.mem = NULL; 36 state->tmp.size = 0; 37 state->tmp.preallocated = false; 38 } 39 EXPORT_SYMBOL(drm_format_conv_state_init); 40 41 /** 42 * drm_format_conv_state_copy - Copy format-conversion state 43 * @state: Destination state 44 * @old_state: Source state 45 * 46 * Copies format-conversion state from @old_state to @state; except for 47 * temporary storage. 48 */ 49 void drm_format_conv_state_copy(struct drm_format_conv_state *state, 50 const struct drm_format_conv_state *old_state) 51 { 52 /* 53 * So far, there's only temporary storage here, which we don't 54 * duplicate. Just clear the fields. 55 */ 56 state->tmp.mem = NULL; 57 state->tmp.size = 0; 58 state->tmp.preallocated = false; 59 } 60 EXPORT_SYMBOL(drm_format_conv_state_copy); 61 62 /** 63 * drm_format_conv_state_reserve - Allocates storage for format conversion 64 * @state: The format-conversion state 65 * @new_size: The minimum allocation size 66 * @flags: Flags for kmalloc() 67 * 68 * Allocates at least @new_size bytes and returns a pointer to the memory 69 * range. After calling this function, previously returned memory blocks 70 * are invalid. It's best to collect all memory requirements of a format 71 * conversion and call this function once to allocate the range. 72 * 73 * Returns: 74 * A pointer to the allocated memory range, or NULL otherwise. 75 */ 76 void *drm_format_conv_state_reserve(struct drm_format_conv_state *state, 77 size_t new_size, gfp_t flags) 78 { 79 void *mem; 80 81 if (new_size <= state->tmp.size) 82 goto out; 83 else if (state->tmp.preallocated) 84 return NULL; 85 86 mem = krealloc(state->tmp.mem, new_size, flags); 87 if (!mem) 88 return NULL; 89 90 state->tmp.mem = mem; 91 state->tmp.size = new_size; 92 93 out: 94 return state->tmp.mem; 95 } 96 EXPORT_SYMBOL(drm_format_conv_state_reserve); 97 98 /** 99 * drm_format_conv_state_release - Releases an format-conversion storage 100 * @state: The format-conversion state 101 * 102 * Releases the memory range references by the format-conversion state. 103 * After this call, all pointers to the memory are invalid. Prefer 104 * drm_format_conv_state_init() for cleaning up and unloading a driver. 105 */ 106 void drm_format_conv_state_release(struct drm_format_conv_state *state) 107 { 108 if (state->tmp.preallocated) 109 return; 110 111 kfree(state->tmp.mem); 112 state->tmp.mem = NULL; 113 state->tmp.size = 0; 114 } 115 EXPORT_SYMBOL(drm_format_conv_state_release); 116 117 static unsigned int clip_offset(const struct drm_rect *clip, unsigned int pitch, unsigned int cpp) 118 { 119 return clip->y1 * pitch + clip->x1 * cpp; 120 } 121 122 /** 123 * drm_fb_clip_offset - Returns the clipping rectangles byte-offset in a framebuffer 124 * @pitch: Framebuffer line pitch in byte 125 * @format: Framebuffer format 126 * @clip: Clip rectangle 127 * 128 * Returns: 129 * The byte offset of the clip rectangle's top-left corner within the framebuffer. 130 */ 131 unsigned int drm_fb_clip_offset(unsigned int pitch, const struct drm_format_info *format, 132 const struct drm_rect *clip) 133 { 134 return clip_offset(clip, pitch, format->cpp[0]); 135 } 136 EXPORT_SYMBOL(drm_fb_clip_offset); 137 138 /* TODO: Make this function work with multi-plane formats. */ 139 static int __drm_fb_xfrm(void *dst, unsigned long dst_pitch, unsigned long dst_pixsize, 140 const void *vaddr, const struct drm_framebuffer *fb, 141 const struct drm_rect *clip, bool vaddr_cached_hint, 142 struct drm_format_conv_state *state, 143 void (*xfrm_line)(void *dbuf, const void *sbuf, unsigned int npixels)) 144 { 145 unsigned long linepixels = drm_rect_width(clip); 146 unsigned long lines = drm_rect_height(clip); 147 size_t sbuf_len = linepixels * fb->format->cpp[0]; 148 void *stmp = NULL; 149 unsigned long i; 150 const void *sbuf; 151 152 /* 153 * Some source buffers, such as DMA memory, use write-combine 154 * caching, so reads are uncached. Speed up access by fetching 155 * one line at a time. 156 */ 157 if (!vaddr_cached_hint) { 158 stmp = drm_format_conv_state_reserve(state, sbuf_len, GFP_KERNEL); 159 if (!stmp) 160 return -ENOMEM; 161 } 162 163 if (!dst_pitch) 164 dst_pitch = drm_rect_width(clip) * dst_pixsize; 165 vaddr += clip_offset(clip, fb->pitches[0], fb->format->cpp[0]); 166 167 for (i = 0; i < lines; ++i) { 168 if (stmp) 169 sbuf = memcpy(stmp, vaddr, sbuf_len); 170 else 171 sbuf = vaddr; 172 xfrm_line(dst, sbuf, linepixels); 173 vaddr += fb->pitches[0]; 174 dst += dst_pitch; 175 } 176 177 return 0; 178 } 179 180 /* TODO: Make this function work with multi-plane formats. */ 181 static int __drm_fb_xfrm_toio(void __iomem *dst, unsigned long dst_pitch, unsigned long dst_pixsize, 182 const void *vaddr, const struct drm_framebuffer *fb, 183 const struct drm_rect *clip, bool vaddr_cached_hint, 184 struct drm_format_conv_state *state, 185 void (*xfrm_line)(void *dbuf, const void *sbuf, unsigned int npixels)) 186 { 187 unsigned long linepixels = drm_rect_width(clip); 188 unsigned long lines = drm_rect_height(clip); 189 size_t dbuf_len = linepixels * dst_pixsize; 190 size_t stmp_off = round_up(dbuf_len, ARCH_KMALLOC_MINALIGN); /* for sbuf alignment */ 191 size_t sbuf_len = linepixels * fb->format->cpp[0]; 192 void *stmp = NULL; 193 unsigned long i; 194 const void *sbuf; 195 void *dbuf; 196 197 if (vaddr_cached_hint) { 198 dbuf = drm_format_conv_state_reserve(state, dbuf_len, GFP_KERNEL); 199 } else { 200 dbuf = drm_format_conv_state_reserve(state, stmp_off + sbuf_len, GFP_KERNEL); 201 stmp = dbuf + stmp_off; 202 } 203 if (!dbuf) 204 return -ENOMEM; 205 206 if (!dst_pitch) 207 dst_pitch = linepixels * dst_pixsize; 208 vaddr += clip_offset(clip, fb->pitches[0], fb->format->cpp[0]); 209 210 for (i = 0; i < lines; ++i) { 211 if (stmp) 212 sbuf = memcpy(stmp, vaddr, sbuf_len); 213 else 214 sbuf = vaddr; 215 xfrm_line(dbuf, sbuf, linepixels); 216 memcpy_toio(dst, dbuf, dbuf_len); 217 vaddr += fb->pitches[0]; 218 dst += dst_pitch; 219 } 220 221 return 0; 222 } 223 224 /* TODO: Make this function work with multi-plane formats. */ 225 static int drm_fb_xfrm(struct iosys_map *dst, 226 const unsigned int *dst_pitch, const u8 *dst_pixsize, 227 const struct iosys_map *src, const struct drm_framebuffer *fb, 228 const struct drm_rect *clip, bool vaddr_cached_hint, 229 struct drm_format_conv_state *state, 230 void (*xfrm_line)(void *dbuf, const void *sbuf, unsigned int npixels)) 231 { 232 static const unsigned int default_dst_pitch[DRM_FORMAT_MAX_PLANES] = { 233 0, 0, 0, 0 234 }; 235 236 if (!dst_pitch) 237 dst_pitch = default_dst_pitch; 238 239 /* TODO: handle src in I/O memory here */ 240 if (dst[0].is_iomem) 241 return __drm_fb_xfrm_toio(dst[0].vaddr_iomem, dst_pitch[0], dst_pixsize[0], 242 src[0].vaddr, fb, clip, vaddr_cached_hint, state, 243 xfrm_line); 244 else 245 return __drm_fb_xfrm(dst[0].vaddr, dst_pitch[0], dst_pixsize[0], 246 src[0].vaddr, fb, clip, vaddr_cached_hint, state, 247 xfrm_line); 248 } 249 250 #define ALIGN_DOWN_PIXELS(end, n, a) \ 251 ((end) - ((n) & ((a) - 1))) 252 253 static __always_inline void drm_fb_xfrm_line_32to8(void *dbuf, const void *sbuf, 254 unsigned int pixels, 255 u32 (*xfrm_pixel)(u32)) 256 { 257 __le32 *dbuf32 = dbuf; 258 u8 *dbuf8; 259 const __le32 *sbuf32 = sbuf; 260 const __le32 *send32 = sbuf32 + pixels; 261 262 /* write 4 pixels at once */ 263 while (sbuf32 < ALIGN_DOWN_PIXELS(send32, pixels, 4)) { 264 u32 pix[4] = { 265 le32_to_cpup(sbuf32), 266 le32_to_cpup(sbuf32 + 1), 267 le32_to_cpup(sbuf32 + 2), 268 le32_to_cpup(sbuf32 + 3), 269 }; 270 /* write output bytes in reverse order for little endianness */ 271 u32 val32 = xfrm_pixel(pix[0]) | 272 (xfrm_pixel(pix[1]) << 8) | 273 (xfrm_pixel(pix[2]) << 16) | 274 (xfrm_pixel(pix[3]) << 24); 275 *dbuf32++ = cpu_to_le32(val32); 276 sbuf32 += ARRAY_SIZE(pix); 277 } 278 279 /* write trailing pixels */ 280 dbuf8 = (u8 __force *)dbuf32; 281 while (sbuf32 < send32) 282 *dbuf8++ = xfrm_pixel(le32_to_cpup(sbuf32++)); 283 } 284 285 static __always_inline void drm_fb_xfrm_line_32to16(void *dbuf, const void *sbuf, 286 unsigned int pixels, 287 u32 (*xfrm_pixel)(u32)) 288 { 289 __le64 *dbuf64 = dbuf; 290 __le32 *dbuf32; 291 __le16 *dbuf16; 292 const __le32 *sbuf32 = sbuf; 293 const __le32 *send32 = sbuf32 + pixels; 294 295 #if defined(CONFIG_64BIT) 296 /* write 4 pixels at once */ 297 while (sbuf32 < ALIGN_DOWN_PIXELS(send32, pixels, 4)) { 298 u32 pix[4] = { 299 le32_to_cpup(sbuf32), 300 le32_to_cpup(sbuf32 + 1), 301 le32_to_cpup(sbuf32 + 2), 302 le32_to_cpup(sbuf32 + 3), 303 }; 304 /* write output bytes in reverse order for little endianness */ 305 u64 val64 = ((u64)xfrm_pixel(pix[0])) | 306 ((u64)xfrm_pixel(pix[1]) << 16) | 307 ((u64)xfrm_pixel(pix[2]) << 32) | 308 ((u64)xfrm_pixel(pix[3]) << 48); 309 *dbuf64++ = cpu_to_le64(val64); 310 sbuf32 += ARRAY_SIZE(pix); 311 } 312 #endif 313 314 /* write 2 pixels at once */ 315 dbuf32 = (__le32 __force *)dbuf64; 316 while (sbuf32 < ALIGN_DOWN_PIXELS(send32, pixels, 2)) { 317 u32 pix[2] = { 318 le32_to_cpup(sbuf32), 319 le32_to_cpup(sbuf32 + 1), 320 }; 321 /* write output bytes in reverse order for little endianness */ 322 u32 val32 = xfrm_pixel(pix[0]) | 323 (xfrm_pixel(pix[1]) << 16); 324 *dbuf32++ = cpu_to_le32(val32); 325 sbuf32 += ARRAY_SIZE(pix); 326 } 327 328 /* write trailing pixel */ 329 dbuf16 = (__le16 __force *)dbuf32; 330 while (sbuf32 < send32) 331 *dbuf16++ = cpu_to_le16(xfrm_pixel(le32_to_cpup(sbuf32++))); 332 } 333 334 static __always_inline void drm_fb_xfrm_line_32to24(void *dbuf, const void *sbuf, 335 unsigned int pixels, 336 u32 (*xfrm_pixel)(u32)) 337 { 338 __le32 *dbuf32 = dbuf; 339 u8 *dbuf8; 340 const __le32 *sbuf32 = sbuf; 341 const __le32 *send32 = sbuf32 + pixels; 342 343 /* write pixels in chunks of 4 */ 344 while (sbuf32 < ALIGN_DOWN_PIXELS(send32, pixels, 4)) { 345 u32 val24[4] = { 346 xfrm_pixel(le32_to_cpup(sbuf32)), 347 xfrm_pixel(le32_to_cpup(sbuf32 + 1)), 348 xfrm_pixel(le32_to_cpup(sbuf32 + 2)), 349 xfrm_pixel(le32_to_cpup(sbuf32 + 3)), 350 }; 351 u32 out32[3] = { 352 /* write output bytes in reverse order for little endianness */ 353 ((val24[0] & 0x000000ff)) | 354 ((val24[0] & 0x0000ff00)) | 355 ((val24[0] & 0x00ff0000)) | 356 ((val24[1] & 0x000000ff) << 24), 357 ((val24[1] & 0x0000ff00) >> 8) | 358 ((val24[1] & 0x00ff0000) >> 8) | 359 ((val24[2] & 0x000000ff) << 16) | 360 ((val24[2] & 0x0000ff00) << 16), 361 ((val24[2] & 0x00ff0000) >> 16) | 362 ((val24[3] & 0x000000ff) << 8) | 363 ((val24[3] & 0x0000ff00) << 8) | 364 ((val24[3] & 0x00ff0000) << 8), 365 }; 366 367 *dbuf32++ = cpu_to_le32(out32[0]); 368 *dbuf32++ = cpu_to_le32(out32[1]); 369 *dbuf32++ = cpu_to_le32(out32[2]); 370 sbuf32 += ARRAY_SIZE(val24); 371 } 372 373 /* write trailing pixel */ 374 dbuf8 = (u8 __force *)dbuf32; 375 while (sbuf32 < send32) { 376 u32 val24 = xfrm_pixel(le32_to_cpup(sbuf32++)); 377 /* write output in reverse order for little endianness */ 378 *dbuf8++ = (val24 & 0x000000ff); 379 *dbuf8++ = (val24 & 0x0000ff00) >> 8; 380 *dbuf8++ = (val24 & 0x00ff0000) >> 16; 381 } 382 } 383 384 static __always_inline void drm_fb_xfrm_line_32to32(void *dbuf, const void *sbuf, 385 unsigned int pixels, 386 u32 (*xfrm_pixel)(u32)) 387 { 388 __le32 *dbuf32 = dbuf; 389 const __le32 *sbuf32 = sbuf; 390 const __le32 *send32 = sbuf32 + pixels; 391 392 while (sbuf32 < send32) 393 *dbuf32++ = cpu_to_le32(xfrm_pixel(le32_to_cpup(sbuf32++))); 394 } 395 396 /** 397 * drm_fb_memcpy - Copy clip buffer 398 * @dst: Array of destination buffers 399 * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines 400 * within @dst; can be NULL if scanlines are stored next to each other. 401 * @src: Array of source buffers 402 * @fb: DRM framebuffer 403 * @clip: Clip rectangle area to copy 404 * 405 * This function copies parts of a framebuffer to display memory. Destination and 406 * framebuffer formats must match. No conversion takes place. The parameters @dst, 407 * @dst_pitch and @src refer to arrays. Each array must have at least as many entries 408 * as there are planes in @fb's format. Each entry stores the value for the format's 409 * respective color plane at the same index. 410 * 411 * This function does not apply clipping on @dst (i.e. the destination is at the 412 * top-left corner). 413 */ 414 void drm_fb_memcpy(struct iosys_map *dst, const unsigned int *dst_pitch, 415 const struct iosys_map *src, const struct drm_framebuffer *fb, 416 const struct drm_rect *clip) 417 { 418 static const unsigned int default_dst_pitch[DRM_FORMAT_MAX_PLANES] = { 419 0, 0, 0, 0 420 }; 421 422 const struct drm_format_info *format = fb->format; 423 unsigned int i, y, lines = drm_rect_height(clip); 424 425 if (!dst_pitch) 426 dst_pitch = default_dst_pitch; 427 428 for (i = 0; i < format->num_planes; ++i) { 429 unsigned int bpp_i = drm_format_info_bpp(format, i); 430 unsigned int cpp_i = DIV_ROUND_UP(bpp_i, 8); 431 size_t len_i = DIV_ROUND_UP(drm_rect_width(clip) * bpp_i, 8); 432 unsigned int dst_pitch_i = dst_pitch[i]; 433 struct iosys_map dst_i = dst[i]; 434 struct iosys_map src_i = src[i]; 435 436 if (!dst_pitch_i) 437 dst_pitch_i = len_i; 438 439 iosys_map_incr(&src_i, clip_offset(clip, fb->pitches[i], cpp_i)); 440 for (y = 0; y < lines; y++) { 441 /* TODO: handle src_i in I/O memory here */ 442 iosys_map_memcpy_to(&dst_i, 0, src_i.vaddr, len_i); 443 iosys_map_incr(&src_i, fb->pitches[i]); 444 iosys_map_incr(&dst_i, dst_pitch_i); 445 } 446 } 447 } 448 EXPORT_SYMBOL(drm_fb_memcpy); 449 450 static void drm_fb_swab16_line(void *dbuf, const void *sbuf, unsigned int pixels) 451 { 452 u16 *dbuf16 = dbuf; 453 const u16 *sbuf16 = sbuf; 454 const u16 *send16 = sbuf16 + pixels; 455 456 while (sbuf16 < send16) 457 *dbuf16++ = swab16(*sbuf16++); 458 } 459 460 static void drm_fb_swab32_line(void *dbuf, const void *sbuf, unsigned int pixels) 461 { 462 u32 *dbuf32 = dbuf; 463 const u32 *sbuf32 = sbuf; 464 const u32 *send32 = sbuf32 + pixels; 465 466 while (sbuf32 < send32) 467 *dbuf32++ = swab32(*sbuf32++); 468 } 469 470 /** 471 * drm_fb_swab - Swap bytes into clip buffer 472 * @dst: Array of destination buffers 473 * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines 474 * within @dst; can be NULL if scanlines are stored next to each other. 475 * @src: Array of source buffers 476 * @fb: DRM framebuffer 477 * @clip: Clip rectangle area to copy 478 * @cached: Source buffer is mapped cached (eg. not write-combined) 479 * @state: Transform and conversion state 480 * 481 * This function copies parts of a framebuffer to display memory and swaps per-pixel 482 * bytes during the process. Destination and framebuffer formats must match. The 483 * parameters @dst, @dst_pitch and @src refer to arrays. Each array must have at 484 * least as many entries as there are planes in @fb's format. Each entry stores the 485 * value for the format's respective color plane at the same index. If @cached is 486 * false a temporary buffer is used to cache one pixel line at a time to speed up 487 * slow uncached reads. 488 * 489 * This function does not apply clipping on @dst (i.e. the destination is at the 490 * top-left corner). 491 */ 492 void drm_fb_swab(struct iosys_map *dst, const unsigned int *dst_pitch, 493 const struct iosys_map *src, const struct drm_framebuffer *fb, 494 const struct drm_rect *clip, bool cached, 495 struct drm_format_conv_state *state) 496 { 497 const struct drm_format_info *format = fb->format; 498 u8 cpp = DIV_ROUND_UP(drm_format_info_bpp(format, 0), 8); 499 void (*swab_line)(void *dbuf, const void *sbuf, unsigned int npixels); 500 501 switch (cpp) { 502 case 4: 503 swab_line = drm_fb_swab32_line; 504 break; 505 case 2: 506 swab_line = drm_fb_swab16_line; 507 break; 508 default: 509 drm_warn_once(fb->dev, "Format %p4cc has unsupported pixel size.\n", 510 &format->format); 511 return; 512 } 513 514 drm_fb_xfrm(dst, dst_pitch, &cpp, src, fb, clip, cached, state, swab_line); 515 } 516 EXPORT_SYMBOL(drm_fb_swab); 517 518 static void drm_fb_xrgb8888_to_rgb332_line(void *dbuf, const void *sbuf, unsigned int pixels) 519 { 520 drm_fb_xfrm_line_32to8(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_rgb332); 521 } 522 523 /** 524 * drm_fb_xrgb8888_to_rgb332 - Convert XRGB8888 to RGB332 clip buffer 525 * @dst: Array of RGB332 destination buffers 526 * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines 527 * within @dst; can be NULL if scanlines are stored next to each other. 528 * @src: Array of XRGB8888 source buffers 529 * @fb: DRM framebuffer 530 * @clip: Clip rectangle area to copy 531 * @state: Transform and conversion state 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 RGB332 devices that don't support XRGB8888 natively. 543 */ 544 void drm_fb_xrgb8888_to_rgb332(struct iosys_map *dst, const unsigned int *dst_pitch, 545 const struct iosys_map *src, const struct drm_framebuffer *fb, 546 const struct drm_rect *clip, struct drm_format_conv_state *state) 547 { 548 static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = { 549 1, 550 }; 551 552 drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state, 553 drm_fb_xrgb8888_to_rgb332_line); 554 } 555 EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb332); 556 557 static void drm_fb_xrgb8888_to_rgb565_line(void *dbuf, const void *sbuf, unsigned int pixels) 558 { 559 drm_fb_xfrm_line_32to16(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_rgb565); 560 } 561 562 static __always_inline u32 drm_xrgb8888_to_rgb565_swab(u32 pix) 563 { 564 return swab16(drm_pixel_xrgb8888_to_rgb565(pix)); 565 } 566 567 /* TODO: implement this helper as conversion to RGB565|BIG_ENDIAN */ 568 static void drm_fb_xrgb8888_to_rgb565_swab_line(void *dbuf, const void *sbuf, 569 unsigned int pixels) 570 { 571 drm_fb_xfrm_line_32to16(dbuf, sbuf, pixels, drm_xrgb8888_to_rgb565_swab); 572 } 573 574 /** 575 * drm_fb_xrgb8888_to_rgb565 - Convert XRGB8888 to RGB565 clip buffer 576 * @dst: Array of RGB565 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 buffer 580 * @fb: DRM framebuffer 581 * @clip: Clip rectangle area to copy 582 * @state: Transform and conversion state 583 * @swab: Swap bytes 584 * 585 * This function copies parts of a framebuffer to display memory and converts the 586 * color format during the process. Destination and framebuffer formats must match. The 587 * parameters @dst, @dst_pitch and @src refer to arrays. Each array must have at 588 * least as many entries as there are planes in @fb's format. Each entry stores the 589 * value for the format's respective color plane at the same index. 590 * 591 * This function does not apply clipping on @dst (i.e. the destination is at the 592 * top-left corner). 593 * 594 * Drivers can use this function for RGB565 devices that don't support XRGB8888 natively. 595 */ 596 void drm_fb_xrgb8888_to_rgb565(struct iosys_map *dst, const unsigned int *dst_pitch, 597 const struct iosys_map *src, const struct drm_framebuffer *fb, 598 const struct drm_rect *clip, struct drm_format_conv_state *state, 599 bool swab) 600 { 601 static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = { 602 2, 603 }; 604 605 void (*xfrm_line)(void *dbuf, const void *sbuf, unsigned int npixels); 606 607 if (swab) 608 xfrm_line = drm_fb_xrgb8888_to_rgb565_swab_line; 609 else 610 xfrm_line = drm_fb_xrgb8888_to_rgb565_line; 611 612 drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state, xfrm_line); 613 } 614 EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb565); 615 616 static void drm_fb_xrgb8888_to_xrgb1555_line(void *dbuf, const void *sbuf, unsigned int pixels) 617 { 618 drm_fb_xfrm_line_32to16(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_xrgb1555); 619 } 620 621 /** 622 * drm_fb_xrgb8888_to_xrgb1555 - Convert XRGB8888 to XRGB1555 clip buffer 623 * @dst: Array of XRGB1555 destination buffers 624 * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines 625 * within @dst; can be NULL if scanlines are stored next to each other. 626 * @src: Array of XRGB8888 source buffer 627 * @fb: DRM framebuffer 628 * @clip: Clip rectangle area to copy 629 * @state: Transform and conversion state 630 * 631 * This function copies parts of a framebuffer to display memory and converts 632 * the color format during the process. The parameters @dst, @dst_pitch and 633 * @src refer to arrays. Each array must have at least as many entries as 634 * there are planes in @fb's format. Each entry stores the value for the 635 * format's respective color plane at the same index. 636 * 637 * This function does not apply clipping on @dst (i.e. the destination is at the 638 * top-left corner). 639 * 640 * Drivers can use this function for XRGB1555 devices that don't support 641 * XRGB8888 natively. 642 */ 643 void drm_fb_xrgb8888_to_xrgb1555(struct iosys_map *dst, const unsigned int *dst_pitch, 644 const struct iosys_map *src, const struct drm_framebuffer *fb, 645 const struct drm_rect *clip, struct drm_format_conv_state *state) 646 { 647 static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = { 648 2, 649 }; 650 651 drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state, 652 drm_fb_xrgb8888_to_xrgb1555_line); 653 } 654 EXPORT_SYMBOL(drm_fb_xrgb8888_to_xrgb1555); 655 656 static void drm_fb_xrgb8888_to_argb1555_line(void *dbuf, const void *sbuf, unsigned int pixels) 657 { 658 drm_fb_xfrm_line_32to16(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_argb1555); 659 } 660 661 /** 662 * drm_fb_xrgb8888_to_argb1555 - Convert XRGB8888 to ARGB1555 clip buffer 663 * @dst: Array of ARGB1555 destination buffers 664 * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines 665 * within @dst; can be NULL if scanlines are stored next to each other. 666 * @src: Array of XRGB8888 source buffer 667 * @fb: DRM framebuffer 668 * @clip: Clip rectangle area to copy 669 * @state: Transform and conversion state 670 * 671 * This function copies parts of a framebuffer to display memory and converts 672 * the color format during the process. The parameters @dst, @dst_pitch and 673 * @src refer to arrays. Each array must have at least as many entries as 674 * there are planes in @fb's format. Each entry stores the value for the 675 * format's respective color plane at the same index. 676 * 677 * This function does not apply clipping on @dst (i.e. the destination is at the 678 * top-left corner). 679 * 680 * Drivers can use this function for ARGB1555 devices that don't support 681 * XRGB8888 natively. It sets an opaque alpha channel as part of the conversion. 682 */ 683 void drm_fb_xrgb8888_to_argb1555(struct iosys_map *dst, const unsigned int *dst_pitch, 684 const struct iosys_map *src, const struct drm_framebuffer *fb, 685 const struct drm_rect *clip, struct drm_format_conv_state *state) 686 { 687 static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = { 688 2, 689 }; 690 691 drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state, 692 drm_fb_xrgb8888_to_argb1555_line); 693 } 694 EXPORT_SYMBOL(drm_fb_xrgb8888_to_argb1555); 695 696 static void drm_fb_xrgb8888_to_rgba5551_line(void *dbuf, const void *sbuf, unsigned int pixels) 697 { 698 drm_fb_xfrm_line_32to16(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_rgba5551); 699 } 700 701 /** 702 * drm_fb_xrgb8888_to_rgba5551 - Convert XRGB8888 to RGBA5551 clip buffer 703 * @dst: Array of RGBA5551 destination buffers 704 * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines 705 * within @dst; can be NULL if scanlines are stored next to each other. 706 * @src: Array of XRGB8888 source buffer 707 * @fb: DRM framebuffer 708 * @clip: Clip rectangle area to copy 709 * @state: Transform and conversion state 710 * 711 * This function copies parts of a framebuffer to display memory and converts 712 * the color format during the process. The parameters @dst, @dst_pitch and 713 * @src refer to arrays. Each array must have at least as many entries as 714 * there are planes in @fb's format. Each entry stores the value for the 715 * format's respective color plane at the same index. 716 * 717 * This function does not apply clipping on @dst (i.e. the destination is at the 718 * top-left corner). 719 * 720 * Drivers can use this function for RGBA5551 devices that don't support 721 * XRGB8888 natively. It sets an opaque alpha channel as part of the conversion. 722 */ 723 void drm_fb_xrgb8888_to_rgba5551(struct iosys_map *dst, const unsigned int *dst_pitch, 724 const struct iosys_map *src, const struct drm_framebuffer *fb, 725 const struct drm_rect *clip, struct drm_format_conv_state *state) 726 { 727 static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = { 728 2, 729 }; 730 731 drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state, 732 drm_fb_xrgb8888_to_rgba5551_line); 733 } 734 EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgba5551); 735 736 static void drm_fb_xrgb8888_to_rgb888_line(void *dbuf, const void *sbuf, unsigned int pixels) 737 { 738 drm_fb_xfrm_line_32to24(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_rgb888); 739 } 740 741 /** 742 * drm_fb_xrgb8888_to_rgb888 - Convert XRGB8888 to RGB888 clip buffer 743 * @dst: Array of RGB888 destination buffers 744 * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines 745 * within @dst; can be NULL if scanlines are stored next to each other. 746 * @src: Array of XRGB8888 source buffers 747 * @fb: DRM framebuffer 748 * @clip: Clip rectangle area to copy 749 * @state: Transform and conversion state 750 * 751 * This function copies parts of a framebuffer to display memory and converts the 752 * color format during the process. Destination and framebuffer formats must match. The 753 * parameters @dst, @dst_pitch and @src refer to arrays. Each array must have at 754 * least as many entries as there are planes in @fb's format. Each entry stores the 755 * value for the format's respective color plane at the same index. 756 * 757 * This function does not apply clipping on @dst (i.e. the destination is at the 758 * top-left corner). 759 * 760 * Drivers can use this function for RGB888 devices that don't natively 761 * support XRGB8888. 762 */ 763 void drm_fb_xrgb8888_to_rgb888(struct iosys_map *dst, const unsigned int *dst_pitch, 764 const struct iosys_map *src, const struct drm_framebuffer *fb, 765 const struct drm_rect *clip, struct drm_format_conv_state *state) 766 { 767 static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = { 768 3, 769 }; 770 771 drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state, 772 drm_fb_xrgb8888_to_rgb888_line); 773 } 774 EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb888); 775 776 static void drm_fb_xrgb8888_to_bgr888_line(void *dbuf, const void *sbuf, unsigned int pixels) 777 { 778 drm_fb_xfrm_line_32to24(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_bgr888); 779 } 780 781 /** 782 * drm_fb_xrgb8888_to_bgr888 - Convert XRGB8888 to BGR888 clip buffer 783 * @dst: Array of BGR888 destination buffers 784 * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines 785 * within @dst; can be NULL if scanlines are stored next to each other. 786 * @src: Array of XRGB8888 source buffers 787 * @fb: DRM framebuffer 788 * @clip: Clip rectangle area to copy 789 * @state: Transform and conversion state 790 * 791 * This function copies parts of a framebuffer to display memory and converts the 792 * color format during the process. Destination and framebuffer formats must match. The 793 * parameters @dst, @dst_pitch and @src refer to arrays. Each array must have at 794 * least as many entries as there are planes in @fb's format. Each entry stores the 795 * value for the format's respective color plane at the same index. 796 * 797 * This function does not apply clipping on @dst (i.e. the destination is at the 798 * top-left corner). 799 * 800 * Drivers can use this function for BGR888 devices that don't natively 801 * support XRGB8888. 802 */ 803 void drm_fb_xrgb8888_to_bgr888(struct iosys_map *dst, const unsigned int *dst_pitch, 804 const struct iosys_map *src, const struct drm_framebuffer *fb, 805 const struct drm_rect *clip, struct drm_format_conv_state *state) 806 { 807 static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = { 808 3, 809 }; 810 811 drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state, 812 drm_fb_xrgb8888_to_bgr888_line); 813 } 814 EXPORT_SYMBOL(drm_fb_xrgb8888_to_bgr888); 815 816 static void drm_fb_xrgb8888_to_argb8888_line(void *dbuf, const void *sbuf, unsigned int pixels) 817 { 818 drm_fb_xfrm_line_32to32(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_argb8888); 819 } 820 821 /** 822 * drm_fb_xrgb8888_to_argb8888 - Convert XRGB8888 to ARGB8888 clip buffer 823 * @dst: Array of ARGB8888 destination buffers 824 * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines 825 * within @dst; can be NULL if scanlines are stored next to each other. 826 * @src: Array of XRGB8888 source buffer 827 * @fb: DRM framebuffer 828 * @clip: Clip rectangle area to copy 829 * @state: Transform and conversion state 830 * 831 * This function copies parts of a framebuffer to display memory and converts the 832 * color format during the process. The parameters @dst, @dst_pitch and @src refer 833 * to arrays. Each array must have at least as many entries as there are planes in 834 * @fb's format. Each entry stores the value for the format's respective color plane 835 * at the same index. 836 * 837 * This function does not apply clipping on @dst (i.e. the destination is at the 838 * top-left corner). 839 * 840 * Drivers can use this function for ARGB8888 devices that don't support XRGB8888 841 * natively. It sets an opaque alpha channel as part of the conversion. 842 */ 843 void drm_fb_xrgb8888_to_argb8888(struct iosys_map *dst, const unsigned int *dst_pitch, 844 const struct iosys_map *src, const struct drm_framebuffer *fb, 845 const struct drm_rect *clip, struct drm_format_conv_state *state) 846 { 847 static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = { 848 4, 849 }; 850 851 drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state, 852 drm_fb_xrgb8888_to_argb8888_line); 853 } 854 EXPORT_SYMBOL(drm_fb_xrgb8888_to_argb8888); 855 856 static void drm_fb_xrgb8888_to_abgr8888_line(void *dbuf, const void *sbuf, unsigned int pixels) 857 { 858 drm_fb_xfrm_line_32to32(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_abgr8888); 859 } 860 861 /** 862 * drm_fb_xrgb8888_to_abgr8888 - Convert XRGB8888 to ABGR8888 clip buffer 863 * @dst: Array of ABGR8888 destination buffers 864 * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines 865 * within @dst; can be NULL if scanlines are stored next to each other. 866 * @src: Array of XRGB8888 source buffer 867 * @fb: DRM framebuffer 868 * @clip: Clip rectangle area to copy 869 * @state: Transform and conversion state 870 * 871 * This function copies parts of a framebuffer to display memory and converts the 872 * color format during the process. The parameters @dst, @dst_pitch and @src refer 873 * to arrays. Each array must have at least as many entries as there are planes in 874 * @fb's format. Each entry stores the value for the format's respective color plane 875 * at the same index. 876 * 877 * This function does not apply clipping on @dst (i.e. the destination is at the 878 * top-left corner). 879 * 880 * Drivers can use this function for ABGR8888 devices that don't support XRGB8888 881 * natively. It sets an opaque alpha channel as part of the conversion. 882 */ 883 void drm_fb_xrgb8888_to_abgr8888(struct iosys_map *dst, const unsigned int *dst_pitch, 884 const struct iosys_map *src, 885 const struct drm_framebuffer *fb, 886 const struct drm_rect *clip, 887 struct drm_format_conv_state *state) 888 { 889 static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = { 890 4, 891 }; 892 893 drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state, 894 drm_fb_xrgb8888_to_abgr8888_line); 895 } 896 EXPORT_SYMBOL(drm_fb_xrgb8888_to_abgr8888); 897 898 static void drm_fb_xrgb8888_to_xbgr8888_line(void *dbuf, const void *sbuf, unsigned int pixels) 899 { 900 drm_fb_xfrm_line_32to32(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_xbgr8888); 901 } 902 903 /** 904 * drm_fb_xrgb8888_to_xbgr8888 - Convert XRGB8888 to XBGR8888 clip buffer 905 * @dst: Array of XBGR8888 destination buffers 906 * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines 907 * within @dst; can be NULL if scanlines are stored next to each other. 908 * @src: Array of XRGB8888 source buffer 909 * @fb: DRM framebuffer 910 * @clip: Clip rectangle area to copy 911 * @state: Transform and conversion state 912 * 913 * This function copies parts of a framebuffer to display memory and converts the 914 * color format during the process. The parameters @dst, @dst_pitch and @src refer 915 * to arrays. Each array must have at least as many entries as there are planes in 916 * @fb's format. Each entry stores the value for the format's respective color plane 917 * at the same index. 918 * 919 * This function does not apply clipping on @dst (i.e. the destination is at the 920 * top-left corner). 921 * 922 * Drivers can use this function for XBGR8888 devices that don't support XRGB8888 923 * natively. 924 */ 925 void drm_fb_xrgb8888_to_xbgr8888(struct iosys_map *dst, const unsigned int *dst_pitch, 926 const struct iosys_map *src, 927 const struct drm_framebuffer *fb, 928 const struct drm_rect *clip, 929 struct drm_format_conv_state *state) 930 { 931 static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = { 932 4, 933 }; 934 935 drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state, 936 drm_fb_xrgb8888_to_xbgr8888_line); 937 } 938 EXPORT_SYMBOL(drm_fb_xrgb8888_to_xbgr8888); 939 940 static void drm_fb_xrgb8888_to_bgrx8888_line(void *dbuf, const void *sbuf, unsigned int pixels) 941 { 942 drm_fb_xfrm_line_32to32(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_bgrx8888); 943 } 944 945 /** 946 * drm_fb_xrgb8888_to_bgrx8888 - Convert XRGB8888 to BGRX8888 clip buffer 947 * @dst: Array of BGRX8888 destination buffers 948 * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines 949 * within @dst; can be NULL if scanlines are stored next to each other. 950 * @src: Array of XRGB8888 source buffer 951 * @fb: DRM framebuffer 952 * @clip: Clip rectangle area to copy 953 * @state: Transform and conversion state 954 * 955 * This function copies parts of a framebuffer to display memory and converts the 956 * color format during the process. The parameters @dst, @dst_pitch and @src refer 957 * to arrays. Each array must have at least as many entries as there are planes in 958 * @fb's format. Each entry stores the value for the format's respective color plane 959 * at the same index. 960 * 961 * This function does not apply clipping on @dst (i.e. the destination is at the 962 * top-left corner). 963 * 964 * Drivers can use this function for BGRX8888 devices that don't support XRGB8888 965 * natively. 966 */ 967 void drm_fb_xrgb8888_to_bgrx8888(struct iosys_map *dst, const unsigned int *dst_pitch, 968 const struct iosys_map *src, 969 const struct drm_framebuffer *fb, 970 const struct drm_rect *clip, 971 struct drm_format_conv_state *state) 972 { 973 static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = { 974 4, 975 }; 976 977 drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state, 978 drm_fb_xrgb8888_to_bgrx8888_line); 979 } 980 EXPORT_SYMBOL(drm_fb_xrgb8888_to_bgrx8888); 981 982 static void drm_fb_xrgb8888_to_xrgb2101010_line(void *dbuf, const void *sbuf, unsigned int pixels) 983 { 984 drm_fb_xfrm_line_32to32(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_xrgb2101010); 985 } 986 987 /** 988 * drm_fb_xrgb8888_to_xrgb2101010 - Convert XRGB8888 to XRGB2101010 clip buffer 989 * @dst: Array of XRGB2101010 destination buffers 990 * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines 991 * within @dst; can be NULL if scanlines are stored next to each other. 992 * @src: Array of XRGB8888 source buffers 993 * @fb: DRM framebuffer 994 * @clip: Clip rectangle area to copy 995 * @state: Transform and conversion state 996 * 997 * This function copies parts of a framebuffer to display memory and converts the 998 * color format during the process. Destination and framebuffer formats must match. The 999 * parameters @dst, @dst_pitch and @src refer to arrays. Each array must have at 1000 * least as many entries as there are planes in @fb's format. Each entry stores the 1001 * value for the format's respective color plane at the same index. 1002 * 1003 * This function does not apply clipping on @dst (i.e. the destination is at the 1004 * top-left corner). 1005 * 1006 * Drivers can use this function for XRGB2101010 devices that don't support XRGB8888 1007 * natively. 1008 */ 1009 void drm_fb_xrgb8888_to_xrgb2101010(struct iosys_map *dst, const unsigned int *dst_pitch, 1010 const struct iosys_map *src, const struct drm_framebuffer *fb, 1011 const struct drm_rect *clip, 1012 struct drm_format_conv_state *state) 1013 { 1014 static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = { 1015 4, 1016 }; 1017 1018 drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state, 1019 drm_fb_xrgb8888_to_xrgb2101010_line); 1020 } 1021 EXPORT_SYMBOL(drm_fb_xrgb8888_to_xrgb2101010); 1022 1023 static void drm_fb_xrgb8888_to_argb2101010_line(void *dbuf, const void *sbuf, unsigned int pixels) 1024 { 1025 drm_fb_xfrm_line_32to32(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_argb2101010); 1026 } 1027 1028 /** 1029 * drm_fb_xrgb8888_to_argb2101010 - Convert XRGB8888 to ARGB2101010 clip buffer 1030 * @dst: Array of ARGB2101010 destination buffers 1031 * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines 1032 * within @dst; can be NULL if scanlines are stored next to each other. 1033 * @src: Array of XRGB8888 source buffers 1034 * @fb: DRM framebuffer 1035 * @clip: Clip rectangle area to copy 1036 * @state: Transform and conversion state 1037 * 1038 * This function copies parts of a framebuffer to display memory and converts 1039 * the color format during the process. The parameters @dst, @dst_pitch and 1040 * @src refer to arrays. Each array must have at least as many entries as 1041 * there are planes in @fb's format. Each entry stores the value for the 1042 * format's respective color plane at the same index. 1043 * 1044 * This function does not apply clipping on @dst (i.e. the destination is at the 1045 * top-left corner). 1046 * 1047 * Drivers can use this function for ARGB2101010 devices that don't support XRGB8888 1048 * natively. 1049 */ 1050 void drm_fb_xrgb8888_to_argb2101010(struct iosys_map *dst, const unsigned int *dst_pitch, 1051 const struct iosys_map *src, const struct drm_framebuffer *fb, 1052 const struct drm_rect *clip, 1053 struct drm_format_conv_state *state) 1054 { 1055 static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = { 1056 4, 1057 }; 1058 1059 drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state, 1060 drm_fb_xrgb8888_to_argb2101010_line); 1061 } 1062 EXPORT_SYMBOL(drm_fb_xrgb8888_to_argb2101010); 1063 1064 static void drm_fb_xrgb8888_to_gray8_line(void *dbuf, const void *sbuf, unsigned int pixels) 1065 { 1066 drm_fb_xfrm_line_32to8(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_r8_bt601); 1067 } 1068 1069 /** 1070 * drm_fb_xrgb8888_to_gray8 - Convert XRGB8888 to grayscale 1071 * @dst: Array of 8-bit grayscale destination buffers 1072 * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines 1073 * within @dst; can be NULL if scanlines are stored next to each other. 1074 * @src: Array of XRGB8888 source buffers 1075 * @fb: DRM framebuffer 1076 * @clip: Clip rectangle area to copy 1077 * @state: Transform and conversion state 1078 * 1079 * This function copies parts of a framebuffer to display memory and converts the 1080 * color format during the process. Destination and framebuffer formats must match. The 1081 * parameters @dst, @dst_pitch and @src refer to arrays. Each array must have at 1082 * least as many entries as there are planes in @fb's format. Each entry stores the 1083 * value for the format's respective color plane at the same index. 1084 * 1085 * This function does not apply clipping on @dst (i.e. the destination is at the 1086 * top-left corner). 1087 * 1088 * DRM doesn't have native monochrome or grayscale support. Drivers can use this 1089 * function for grayscale devices that don't support XRGB8888 natively.Such 1090 * drivers can announce the commonly supported XR24 format to userspace and use 1091 * this function to convert to the native format. Monochrome drivers will use the 1092 * most significant bit, where 1 means foreground color and 0 background color. 1093 * ITU BT.601 is being used for the RGB -> luma (brightness) conversion. 1094 */ 1095 void drm_fb_xrgb8888_to_gray8(struct iosys_map *dst, const unsigned int *dst_pitch, 1096 const struct iosys_map *src, const struct drm_framebuffer *fb, 1097 const struct drm_rect *clip, struct drm_format_conv_state *state) 1098 { 1099 static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = { 1100 1, 1101 }; 1102 1103 drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state, 1104 drm_fb_xrgb8888_to_gray8_line); 1105 } 1106 EXPORT_SYMBOL(drm_fb_xrgb8888_to_gray8); 1107 1108 static void drm_fb_argb8888_to_argb4444_line(void *dbuf, const void *sbuf, unsigned int pixels) 1109 { 1110 drm_fb_xfrm_line_32to16(dbuf, sbuf, pixels, drm_pixel_argb8888_to_argb4444); 1111 } 1112 1113 /** 1114 * drm_fb_argb8888_to_argb4444 - Convert ARGB8888 to ARGB4444 clip buffer 1115 * @dst: Array of ARGB4444 destination buffers 1116 * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines 1117 * within @dst; can be NULL if scanlines are stored next to each other. 1118 * @src: Array of ARGB8888 source buffer 1119 * @fb: DRM framebuffer 1120 * @clip: Clip rectangle area to copy 1121 * @state: Transform and conversion state 1122 * 1123 * This function copies parts of a framebuffer to display memory and converts 1124 * the color format during the process. The parameters @dst, @dst_pitch and 1125 * @src refer to arrays. Each array must have at least as many entries as 1126 * there are planes in @fb's format. Each entry stores the value for the 1127 * format's respective color plane at the same index. 1128 * 1129 * This function does not apply clipping on @dst (i.e. the destination is at the 1130 * top-left corner). 1131 * 1132 * Drivers can use this function for ARGB4444 devices that don't support 1133 * ARGB8888 natively. 1134 */ 1135 void drm_fb_argb8888_to_argb4444(struct iosys_map *dst, const unsigned int *dst_pitch, 1136 const struct iosys_map *src, const struct drm_framebuffer *fb, 1137 const struct drm_rect *clip, struct drm_format_conv_state *state) 1138 { 1139 static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = { 1140 2, 1141 }; 1142 1143 drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state, 1144 drm_fb_argb8888_to_argb4444_line); 1145 } 1146 EXPORT_SYMBOL(drm_fb_argb8888_to_argb4444); 1147 1148 /** 1149 * drm_fb_blit - Copy parts of a framebuffer to display memory 1150 * @dst: Array of display-memory addresses to copy to 1151 * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines 1152 * within @dst; can be NULL if scanlines are stored next to each other. 1153 * @dst_format: FOURCC code of the display's color format 1154 * @src: The framebuffer memory to copy from 1155 * @fb: The framebuffer to copy from 1156 * @clip: Clip rectangle area to copy 1157 * @state: Transform and conversion state 1158 * 1159 * This function copies parts of a framebuffer to display memory. If the 1160 * formats of the display and the framebuffer mismatch, the blit function 1161 * will attempt to convert between them during the process. The parameters @dst, 1162 * @dst_pitch and @src refer to arrays. Each array must have at least as many 1163 * entries as there are planes in @dst_format's format. Each entry stores the 1164 * value for the format's respective color plane at the same index. 1165 * 1166 * This function does not apply clipping on @dst (i.e. the destination is at the 1167 * top-left corner). 1168 * 1169 * Returns: 1170 * 0 on success, or 1171 * -EINVAL if the color-format conversion failed, or 1172 * a negative error code otherwise. 1173 */ 1174 int drm_fb_blit(struct iosys_map *dst, const unsigned int *dst_pitch, uint32_t dst_format, 1175 const struct iosys_map *src, const struct drm_framebuffer *fb, 1176 const struct drm_rect *clip, struct drm_format_conv_state *state) 1177 { 1178 uint32_t fb_format = fb->format->format; 1179 1180 if (fb_format == dst_format) { 1181 drm_fb_memcpy(dst, dst_pitch, src, fb, clip); 1182 return 0; 1183 } else if (fb_format == (dst_format | DRM_FORMAT_BIG_ENDIAN)) { 1184 drm_fb_swab(dst, dst_pitch, src, fb, clip, false, state); 1185 return 0; 1186 } else if (fb_format == (dst_format & ~DRM_FORMAT_BIG_ENDIAN)) { 1187 drm_fb_swab(dst, dst_pitch, src, fb, clip, false, state); 1188 return 0; 1189 } else if (fb_format == DRM_FORMAT_XRGB8888) { 1190 if (dst_format == DRM_FORMAT_RGB565) { 1191 drm_fb_xrgb8888_to_rgb565(dst, dst_pitch, src, fb, clip, state, false); 1192 return 0; 1193 } else if (dst_format == DRM_FORMAT_XRGB1555) { 1194 drm_fb_xrgb8888_to_xrgb1555(dst, dst_pitch, src, fb, clip, state); 1195 return 0; 1196 } else if (dst_format == DRM_FORMAT_ARGB1555) { 1197 drm_fb_xrgb8888_to_argb1555(dst, dst_pitch, src, fb, clip, state); 1198 return 0; 1199 } else if (dst_format == DRM_FORMAT_RGBA5551) { 1200 drm_fb_xrgb8888_to_rgba5551(dst, dst_pitch, src, fb, clip, state); 1201 return 0; 1202 } else if (dst_format == DRM_FORMAT_RGB888) { 1203 drm_fb_xrgb8888_to_rgb888(dst, dst_pitch, src, fb, clip, state); 1204 return 0; 1205 } else if (dst_format == DRM_FORMAT_BGR888) { 1206 drm_fb_xrgb8888_to_bgr888(dst, dst_pitch, src, fb, clip, state); 1207 return 0; 1208 } else if (dst_format == DRM_FORMAT_ARGB8888) { 1209 drm_fb_xrgb8888_to_argb8888(dst, dst_pitch, src, fb, clip, state); 1210 return 0; 1211 } else if (dst_format == DRM_FORMAT_XBGR8888) { 1212 drm_fb_xrgb8888_to_xbgr8888(dst, dst_pitch, src, fb, clip, state); 1213 return 0; 1214 } else if (dst_format == DRM_FORMAT_ABGR8888) { 1215 drm_fb_xrgb8888_to_abgr8888(dst, dst_pitch, src, fb, clip, state); 1216 return 0; 1217 } else if (dst_format == DRM_FORMAT_XRGB2101010) { 1218 drm_fb_xrgb8888_to_xrgb2101010(dst, dst_pitch, src, fb, clip, state); 1219 return 0; 1220 } else if (dst_format == DRM_FORMAT_ARGB2101010) { 1221 drm_fb_xrgb8888_to_argb2101010(dst, dst_pitch, src, fb, clip, state); 1222 return 0; 1223 } else if (dst_format == DRM_FORMAT_BGRX8888) { 1224 drm_fb_swab(dst, dst_pitch, src, fb, clip, false, state); 1225 return 0; 1226 } 1227 } 1228 1229 drm_warn_once(fb->dev, "No conversion helper from %p4cc to %p4cc found.\n", 1230 &fb_format, &dst_format); 1231 1232 return -EINVAL; 1233 } 1234 EXPORT_SYMBOL(drm_fb_blit); 1235 1236 static void drm_fb_gray8_to_mono_line(void *dbuf, const void *sbuf, unsigned int pixels) 1237 { 1238 u8 *dbuf8 = dbuf; 1239 const u8 *sbuf8 = sbuf; 1240 1241 while (pixels) { 1242 unsigned int i, bits = min(pixels, 8U); 1243 u8 byte = 0; 1244 1245 for (i = 0; i < bits; i++, pixels--) { 1246 if (*sbuf8++ >= 128) 1247 byte |= BIT(i); 1248 } 1249 *dbuf8++ = byte; 1250 } 1251 } 1252 1253 /** 1254 * drm_fb_xrgb8888_to_mono - Convert XRGB8888 to monochrome 1255 * @dst: Array of monochrome destination buffers (0=black, 1=white) 1256 * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines 1257 * within @dst; can be NULL if scanlines are stored next to each other. 1258 * @src: Array of XRGB8888 source buffers 1259 * @fb: DRM framebuffer 1260 * @clip: Clip rectangle area to copy 1261 * @state: Transform and conversion state 1262 * 1263 * This function copies parts of a framebuffer to display memory and converts the 1264 * color format during the process. Destination and framebuffer formats must match. The 1265 * parameters @dst, @dst_pitch and @src refer to arrays. Each array must have at 1266 * least as many entries as there are planes in @fb's format. Each entry stores the 1267 * value for the format's respective color plane at the same index. 1268 * 1269 * This function does not apply clipping on @dst (i.e. the destination is at the 1270 * top-left corner). The first pixel (upper left corner of the clip rectangle) will 1271 * be converted and copied to the first bit (LSB) in the first byte of the monochrome 1272 * destination buffer. If the caller requires that the first pixel in a byte must 1273 * be located at an x-coordinate that is a multiple of 8, then the caller must take 1274 * care itself of supplying a suitable clip rectangle. 1275 * 1276 * DRM doesn't have native monochrome support. Drivers can use this function for 1277 * monochrome devices that don't support XRGB8888 natively. Such drivers can 1278 * announce the commonly supported XR24 format to userspace and use this function 1279 * to convert to the native format. 1280 * 1281 * This function uses drm_fb_xrgb8888_to_gray8() to convert to grayscale and 1282 * then the result is converted from grayscale to monochrome. 1283 */ 1284 void drm_fb_xrgb8888_to_mono(struct iosys_map *dst, const unsigned int *dst_pitch, 1285 const struct iosys_map *src, const struct drm_framebuffer *fb, 1286 const struct drm_rect *clip, struct drm_format_conv_state *state) 1287 { 1288 static const unsigned int default_dst_pitch[DRM_FORMAT_MAX_PLANES] = { 1289 0, 0, 0, 0 1290 }; 1291 unsigned int linepixels = drm_rect_width(clip); 1292 unsigned int lines = drm_rect_height(clip); 1293 unsigned int cpp = fb->format->cpp[0]; 1294 unsigned int len_src32 = linepixels * cpp; 1295 struct drm_device *dev = fb->dev; 1296 void *vaddr = src[0].vaddr; 1297 unsigned int dst_pitch_0; 1298 unsigned int y; 1299 u8 *mono = dst[0].vaddr, *gray8; 1300 u32 *src32; 1301 1302 if (drm_WARN_ON(dev, fb->format->format != DRM_FORMAT_XRGB8888)) 1303 return; 1304 1305 if (!dst_pitch) 1306 dst_pitch = default_dst_pitch; 1307 dst_pitch_0 = dst_pitch[0]; 1308 1309 /* 1310 * The mono destination buffer contains 1 bit per pixel 1311 */ 1312 if (!dst_pitch_0) 1313 dst_pitch_0 = DIV_ROUND_UP(linepixels, 8); 1314 1315 /* 1316 * The dma memory is write-combined so reads are uncached. 1317 * Speed up by fetching one line at a time. 1318 * 1319 * Also, format conversion from XR24 to monochrome are done 1320 * line-by-line but are converted to 8-bit grayscale as an 1321 * intermediate step. 1322 * 1323 * Allocate a buffer to be used for both copying from the cma 1324 * memory and to store the intermediate grayscale line pixels. 1325 */ 1326 src32 = drm_format_conv_state_reserve(state, len_src32 + linepixels, GFP_KERNEL); 1327 if (!src32) 1328 return; 1329 1330 gray8 = (u8 *)src32 + len_src32; 1331 1332 vaddr += clip_offset(clip, fb->pitches[0], cpp); 1333 for (y = 0; y < lines; y++) { 1334 src32 = memcpy(src32, vaddr, len_src32); 1335 drm_fb_xrgb8888_to_gray8_line(gray8, src32, linepixels); 1336 drm_fb_gray8_to_mono_line(mono, gray8, linepixels); 1337 vaddr += fb->pitches[0]; 1338 mono += dst_pitch_0; 1339 } 1340 } 1341 EXPORT_SYMBOL(drm_fb_xrgb8888_to_mono); 1342