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