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 static void drm_fb_xrgb8888_to_abgr8888(struct iosys_map *dst, const unsigned int *dst_pitch, 862 const struct iosys_map *src, 863 const struct drm_framebuffer *fb, 864 const struct drm_rect *clip, 865 struct drm_format_conv_state *state) 866 { 867 static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = { 868 4, 869 }; 870 871 drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state, 872 drm_fb_xrgb8888_to_abgr8888_line); 873 } 874 875 static void drm_fb_xrgb8888_to_xbgr8888_line(void *dbuf, const void *sbuf, unsigned int pixels) 876 { 877 drm_fb_xfrm_line_32to32(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_xbgr8888); 878 } 879 880 static void drm_fb_xrgb8888_to_xbgr8888(struct iosys_map *dst, const unsigned int *dst_pitch, 881 const struct iosys_map *src, 882 const struct drm_framebuffer *fb, 883 const struct drm_rect *clip, 884 struct drm_format_conv_state *state) 885 { 886 static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = { 887 4, 888 }; 889 890 drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state, 891 drm_fb_xrgb8888_to_xbgr8888_line); 892 } 893 894 static void drm_fb_xrgb8888_to_xrgb2101010_line(void *dbuf, const void *sbuf, unsigned int pixels) 895 { 896 drm_fb_xfrm_line_32to32(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_xrgb2101010); 897 } 898 899 /** 900 * drm_fb_xrgb8888_to_xrgb2101010 - Convert XRGB8888 to XRGB2101010 clip buffer 901 * @dst: Array of XRGB2101010 destination buffers 902 * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines 903 * within @dst; can be NULL if scanlines are stored next to each other. 904 * @src: Array of XRGB8888 source buffers 905 * @fb: DRM framebuffer 906 * @clip: Clip rectangle area to copy 907 * @state: Transform and conversion state 908 * 909 * This function copies parts of a framebuffer to display memory and converts the 910 * color format during the process. Destination and framebuffer formats must match. The 911 * parameters @dst, @dst_pitch and @src refer to arrays. Each array must have at 912 * least as many entries as there are planes in @fb's format. Each entry stores the 913 * value for the format's respective color plane at the same index. 914 * 915 * This function does not apply clipping on @dst (i.e. the destination is at the 916 * top-left corner). 917 * 918 * Drivers can use this function for XRGB2101010 devices that don't support XRGB8888 919 * natively. 920 */ 921 void drm_fb_xrgb8888_to_xrgb2101010(struct iosys_map *dst, const unsigned int *dst_pitch, 922 const struct iosys_map *src, const struct drm_framebuffer *fb, 923 const struct drm_rect *clip, 924 struct drm_format_conv_state *state) 925 { 926 static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = { 927 4, 928 }; 929 930 drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state, 931 drm_fb_xrgb8888_to_xrgb2101010_line); 932 } 933 EXPORT_SYMBOL(drm_fb_xrgb8888_to_xrgb2101010); 934 935 static void drm_fb_xrgb8888_to_argb2101010_line(void *dbuf, const void *sbuf, unsigned int pixels) 936 { 937 drm_fb_xfrm_line_32to32(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_argb2101010); 938 } 939 940 /** 941 * drm_fb_xrgb8888_to_argb2101010 - Convert XRGB8888 to ARGB2101010 clip buffer 942 * @dst: Array of ARGB2101010 destination buffers 943 * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines 944 * within @dst; can be NULL if scanlines are stored next to each other. 945 * @src: Array of XRGB8888 source buffers 946 * @fb: DRM framebuffer 947 * @clip: Clip rectangle area to copy 948 * @state: Transform and conversion state 949 * 950 * This function copies parts of a framebuffer to display memory and converts 951 * the color format during the process. The parameters @dst, @dst_pitch and 952 * @src refer to arrays. Each array must have at least as many entries as 953 * there are planes in @fb's format. Each entry stores the value for the 954 * format's respective color plane at the same index. 955 * 956 * This function does not apply clipping on @dst (i.e. the destination is at the 957 * top-left corner). 958 * 959 * Drivers can use this function for ARGB2101010 devices that don't support XRGB8888 960 * natively. 961 */ 962 void drm_fb_xrgb8888_to_argb2101010(struct iosys_map *dst, const unsigned int *dst_pitch, 963 const struct iosys_map *src, const struct drm_framebuffer *fb, 964 const struct drm_rect *clip, 965 struct drm_format_conv_state *state) 966 { 967 static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = { 968 4, 969 }; 970 971 drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state, 972 drm_fb_xrgb8888_to_argb2101010_line); 973 } 974 EXPORT_SYMBOL(drm_fb_xrgb8888_to_argb2101010); 975 976 static void drm_fb_xrgb8888_to_gray8_line(void *dbuf, const void *sbuf, unsigned int pixels) 977 { 978 drm_fb_xfrm_line_32to8(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_r8_bt601); 979 } 980 981 /** 982 * drm_fb_xrgb8888_to_gray8 - Convert XRGB8888 to grayscale 983 * @dst: Array of 8-bit grayscale destination buffers 984 * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines 985 * within @dst; can be NULL if scanlines are stored next to each other. 986 * @src: Array of XRGB8888 source buffers 987 * @fb: DRM framebuffer 988 * @clip: Clip rectangle area to copy 989 * @state: Transform and conversion state 990 * 991 * This function copies parts of a framebuffer to display memory and converts the 992 * color format during the process. Destination and framebuffer formats must match. The 993 * parameters @dst, @dst_pitch and @src refer to arrays. Each array must have at 994 * least as many entries as there are planes in @fb's format. Each entry stores the 995 * value for the format's respective color plane at the same index. 996 * 997 * This function does not apply clipping on @dst (i.e. the destination is at the 998 * top-left corner). 999 * 1000 * DRM doesn't have native monochrome or grayscale support. Drivers can use this 1001 * function for grayscale devices that don't support XRGB8888 natively.Such 1002 * drivers can announce the commonly supported XR24 format to userspace and use 1003 * this function to convert to the native format. Monochrome drivers will use the 1004 * most significant bit, where 1 means foreground color and 0 background color. 1005 * ITU BT.601 is being used for the RGB -> luma (brightness) conversion. 1006 */ 1007 void drm_fb_xrgb8888_to_gray8(struct iosys_map *dst, const unsigned int *dst_pitch, 1008 const struct iosys_map *src, const struct drm_framebuffer *fb, 1009 const struct drm_rect *clip, struct drm_format_conv_state *state) 1010 { 1011 static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = { 1012 1, 1013 }; 1014 1015 drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state, 1016 drm_fb_xrgb8888_to_gray8_line); 1017 } 1018 EXPORT_SYMBOL(drm_fb_xrgb8888_to_gray8); 1019 1020 static void drm_fb_argb8888_to_argb4444_line(void *dbuf, const void *sbuf, unsigned int pixels) 1021 { 1022 drm_fb_xfrm_line_32to16(dbuf, sbuf, pixels, drm_pixel_argb8888_to_argb4444); 1023 } 1024 1025 /** 1026 * drm_fb_argb8888_to_argb4444 - Convert ARGB8888 to ARGB4444 clip buffer 1027 * @dst: Array of ARGB4444 destination buffers 1028 * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines 1029 * within @dst; can be NULL if scanlines are stored next to each other. 1030 * @src: Array of ARGB8888 source buffer 1031 * @fb: DRM framebuffer 1032 * @clip: Clip rectangle area to copy 1033 * @state: Transform and conversion state 1034 * 1035 * This function copies parts of a framebuffer to display memory and converts 1036 * the color format during the process. The parameters @dst, @dst_pitch and 1037 * @src refer to arrays. Each array must have at least as many entries as 1038 * there are planes in @fb's format. Each entry stores the value for the 1039 * format's respective color plane at the same index. 1040 * 1041 * This function does not apply clipping on @dst (i.e. the destination is at the 1042 * top-left corner). 1043 * 1044 * Drivers can use this function for ARGB4444 devices that don't support 1045 * ARGB8888 natively. 1046 */ 1047 void drm_fb_argb8888_to_argb4444(struct iosys_map *dst, const unsigned int *dst_pitch, 1048 const struct iosys_map *src, const struct drm_framebuffer *fb, 1049 const struct drm_rect *clip, struct drm_format_conv_state *state) 1050 { 1051 static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = { 1052 2, 1053 }; 1054 1055 drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state, 1056 drm_fb_argb8888_to_argb4444_line); 1057 } 1058 EXPORT_SYMBOL(drm_fb_argb8888_to_argb4444); 1059 1060 /** 1061 * drm_fb_blit - Copy parts of a framebuffer to display memory 1062 * @dst: Array of display-memory addresses to copy to 1063 * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines 1064 * within @dst; can be NULL if scanlines are stored next to each other. 1065 * @dst_format: FOURCC code of the display's color format 1066 * @src: The framebuffer memory to copy from 1067 * @fb: The framebuffer to copy from 1068 * @clip: Clip rectangle area to copy 1069 * @state: Transform and conversion state 1070 * 1071 * This function copies parts of a framebuffer to display memory. If the 1072 * formats of the display and the framebuffer mismatch, the blit function 1073 * will attempt to convert between them during the process. The parameters @dst, 1074 * @dst_pitch and @src refer to arrays. Each array must have at least as many 1075 * entries as there are planes in @dst_format's format. Each entry stores the 1076 * value for the format's respective color plane at the same index. 1077 * 1078 * This function does not apply clipping on @dst (i.e. the destination is at the 1079 * top-left corner). 1080 * 1081 * Returns: 1082 * 0 on success, or 1083 * -EINVAL if the color-format conversion failed, or 1084 * a negative error code otherwise. 1085 */ 1086 int drm_fb_blit(struct iosys_map *dst, const unsigned int *dst_pitch, uint32_t dst_format, 1087 const struct iosys_map *src, const struct drm_framebuffer *fb, 1088 const struct drm_rect *clip, struct drm_format_conv_state *state) 1089 { 1090 uint32_t fb_format = fb->format->format; 1091 1092 if (fb_format == dst_format) { 1093 drm_fb_memcpy(dst, dst_pitch, src, fb, clip); 1094 return 0; 1095 } else if (fb_format == (dst_format | DRM_FORMAT_BIG_ENDIAN)) { 1096 drm_fb_swab(dst, dst_pitch, src, fb, clip, false, state); 1097 return 0; 1098 } else if (fb_format == (dst_format & ~DRM_FORMAT_BIG_ENDIAN)) { 1099 drm_fb_swab(dst, dst_pitch, src, fb, clip, false, state); 1100 return 0; 1101 } else if (fb_format == DRM_FORMAT_XRGB8888) { 1102 if (dst_format == DRM_FORMAT_RGB565) { 1103 drm_fb_xrgb8888_to_rgb565(dst, dst_pitch, src, fb, clip, state, false); 1104 return 0; 1105 } else if (dst_format == DRM_FORMAT_XRGB1555) { 1106 drm_fb_xrgb8888_to_xrgb1555(dst, dst_pitch, src, fb, clip, state); 1107 return 0; 1108 } else if (dst_format == DRM_FORMAT_ARGB1555) { 1109 drm_fb_xrgb8888_to_argb1555(dst, dst_pitch, src, fb, clip, state); 1110 return 0; 1111 } else if (dst_format == DRM_FORMAT_RGBA5551) { 1112 drm_fb_xrgb8888_to_rgba5551(dst, dst_pitch, src, fb, clip, state); 1113 return 0; 1114 } else if (dst_format == DRM_FORMAT_RGB888) { 1115 drm_fb_xrgb8888_to_rgb888(dst, dst_pitch, src, fb, clip, state); 1116 return 0; 1117 } else if (dst_format == DRM_FORMAT_BGR888) { 1118 drm_fb_xrgb8888_to_bgr888(dst, dst_pitch, src, fb, clip, state); 1119 return 0; 1120 } else if (dst_format == DRM_FORMAT_ARGB8888) { 1121 drm_fb_xrgb8888_to_argb8888(dst, dst_pitch, src, fb, clip, state); 1122 return 0; 1123 } else if (dst_format == DRM_FORMAT_XBGR8888) { 1124 drm_fb_xrgb8888_to_xbgr8888(dst, dst_pitch, src, fb, clip, state); 1125 return 0; 1126 } else if (dst_format == DRM_FORMAT_ABGR8888) { 1127 drm_fb_xrgb8888_to_abgr8888(dst, dst_pitch, src, fb, clip, state); 1128 return 0; 1129 } else if (dst_format == DRM_FORMAT_XRGB2101010) { 1130 drm_fb_xrgb8888_to_xrgb2101010(dst, dst_pitch, src, fb, clip, state); 1131 return 0; 1132 } else if (dst_format == DRM_FORMAT_ARGB2101010) { 1133 drm_fb_xrgb8888_to_argb2101010(dst, dst_pitch, src, fb, clip, state); 1134 return 0; 1135 } else if (dst_format == DRM_FORMAT_BGRX8888) { 1136 drm_fb_swab(dst, dst_pitch, src, fb, clip, false, state); 1137 return 0; 1138 } 1139 } 1140 1141 drm_warn_once(fb->dev, "No conversion helper from %p4cc to %p4cc found.\n", 1142 &fb_format, &dst_format); 1143 1144 return -EINVAL; 1145 } 1146 EXPORT_SYMBOL(drm_fb_blit); 1147 1148 static void drm_fb_gray8_to_mono_line(void *dbuf, const void *sbuf, unsigned int pixels) 1149 { 1150 u8 *dbuf8 = dbuf; 1151 const u8 *sbuf8 = sbuf; 1152 1153 while (pixels) { 1154 unsigned int i, bits = min(pixels, 8U); 1155 u8 byte = 0; 1156 1157 for (i = 0; i < bits; i++, pixels--) { 1158 if (*sbuf8++ >= 128) 1159 byte |= BIT(i); 1160 } 1161 *dbuf8++ = byte; 1162 } 1163 } 1164 1165 /** 1166 * drm_fb_xrgb8888_to_mono - Convert XRGB8888 to monochrome 1167 * @dst: Array of monochrome destination buffers (0=black, 1=white) 1168 * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines 1169 * within @dst; can be NULL if scanlines are stored next to each other. 1170 * @src: Array of XRGB8888 source buffers 1171 * @fb: DRM framebuffer 1172 * @clip: Clip rectangle area to copy 1173 * @state: Transform and conversion state 1174 * 1175 * This function copies parts of a framebuffer to display memory and converts the 1176 * color format during the process. Destination and framebuffer formats must match. The 1177 * parameters @dst, @dst_pitch and @src refer to arrays. Each array must have at 1178 * least as many entries as there are planes in @fb's format. Each entry stores the 1179 * value for the format's respective color plane at the same index. 1180 * 1181 * This function does not apply clipping on @dst (i.e. the destination is at the 1182 * top-left corner). The first pixel (upper left corner of the clip rectangle) will 1183 * be converted and copied to the first bit (LSB) in the first byte of the monochrome 1184 * destination buffer. If the caller requires that the first pixel in a byte must 1185 * be located at an x-coordinate that is a multiple of 8, then the caller must take 1186 * care itself of supplying a suitable clip rectangle. 1187 * 1188 * DRM doesn't have native monochrome support. Drivers can use this function for 1189 * monochrome devices that don't support XRGB8888 natively. Such drivers can 1190 * announce the commonly supported XR24 format to userspace and use this function 1191 * to convert to the native format. 1192 * 1193 * This function uses drm_fb_xrgb8888_to_gray8() to convert to grayscale and 1194 * then the result is converted from grayscale to monochrome. 1195 */ 1196 void drm_fb_xrgb8888_to_mono(struct iosys_map *dst, const unsigned int *dst_pitch, 1197 const struct iosys_map *src, const struct drm_framebuffer *fb, 1198 const struct drm_rect *clip, struct drm_format_conv_state *state) 1199 { 1200 static const unsigned int default_dst_pitch[DRM_FORMAT_MAX_PLANES] = { 1201 0, 0, 0, 0 1202 }; 1203 unsigned int linepixels = drm_rect_width(clip); 1204 unsigned int lines = drm_rect_height(clip); 1205 unsigned int cpp = fb->format->cpp[0]; 1206 unsigned int len_src32 = linepixels * cpp; 1207 struct drm_device *dev = fb->dev; 1208 void *vaddr = src[0].vaddr; 1209 unsigned int dst_pitch_0; 1210 unsigned int y; 1211 u8 *mono = dst[0].vaddr, *gray8; 1212 u32 *src32; 1213 1214 if (drm_WARN_ON(dev, fb->format->format != DRM_FORMAT_XRGB8888)) 1215 return; 1216 1217 if (!dst_pitch) 1218 dst_pitch = default_dst_pitch; 1219 dst_pitch_0 = dst_pitch[0]; 1220 1221 /* 1222 * The mono destination buffer contains 1 bit per pixel 1223 */ 1224 if (!dst_pitch_0) 1225 dst_pitch_0 = DIV_ROUND_UP(linepixels, 8); 1226 1227 /* 1228 * The dma memory is write-combined so reads are uncached. 1229 * Speed up by fetching one line at a time. 1230 * 1231 * Also, format conversion from XR24 to monochrome are done 1232 * line-by-line but are converted to 8-bit grayscale as an 1233 * intermediate step. 1234 * 1235 * Allocate a buffer to be used for both copying from the cma 1236 * memory and to store the intermediate grayscale line pixels. 1237 */ 1238 src32 = drm_format_conv_state_reserve(state, len_src32 + linepixels, GFP_KERNEL); 1239 if (!src32) 1240 return; 1241 1242 gray8 = (u8 *)src32 + len_src32; 1243 1244 vaddr += clip_offset(clip, fb->pitches[0], cpp); 1245 for (y = 0; y < lines; y++) { 1246 src32 = memcpy(src32, vaddr, len_src32); 1247 drm_fb_xrgb8888_to_gray8_line(gray8, src32, linepixels); 1248 drm_fb_gray8_to_mono_line(mono, gray8, linepixels); 1249 vaddr += fb->pitches[0]; 1250 mono += dst_pitch_0; 1251 } 1252 } 1253 EXPORT_SYMBOL(drm_fb_xrgb8888_to_mono); 1254 1255 static uint32_t drm_fb_nonalpha_fourcc(uint32_t fourcc) 1256 { 1257 /* only handle formats with depth != 0 and alpha channel */ 1258 switch (fourcc) { 1259 case DRM_FORMAT_ARGB1555: 1260 return DRM_FORMAT_XRGB1555; 1261 case DRM_FORMAT_ABGR1555: 1262 return DRM_FORMAT_XBGR1555; 1263 case DRM_FORMAT_RGBA5551: 1264 return DRM_FORMAT_RGBX5551; 1265 case DRM_FORMAT_BGRA5551: 1266 return DRM_FORMAT_BGRX5551; 1267 case DRM_FORMAT_ARGB8888: 1268 return DRM_FORMAT_XRGB8888; 1269 case DRM_FORMAT_ABGR8888: 1270 return DRM_FORMAT_XBGR8888; 1271 case DRM_FORMAT_RGBA8888: 1272 return DRM_FORMAT_RGBX8888; 1273 case DRM_FORMAT_BGRA8888: 1274 return DRM_FORMAT_BGRX8888; 1275 case DRM_FORMAT_ARGB2101010: 1276 return DRM_FORMAT_XRGB2101010; 1277 case DRM_FORMAT_ABGR2101010: 1278 return DRM_FORMAT_XBGR2101010; 1279 case DRM_FORMAT_RGBA1010102: 1280 return DRM_FORMAT_RGBX1010102; 1281 case DRM_FORMAT_BGRA1010102: 1282 return DRM_FORMAT_BGRX1010102; 1283 } 1284 1285 return fourcc; 1286 } 1287 1288 static bool is_listed_fourcc(const uint32_t *fourccs, size_t nfourccs, uint32_t fourcc) 1289 { 1290 const uint32_t *fourccs_end = fourccs + nfourccs; 1291 1292 while (fourccs < fourccs_end) { 1293 if (*fourccs == fourcc) 1294 return true; 1295 ++fourccs; 1296 } 1297 return false; 1298 } 1299 1300 /** 1301 * drm_fb_build_fourcc_list - Filters a list of supported color formats against 1302 * the device's native formats 1303 * @dev: DRM device 1304 * @native_fourccs: 4CC codes of natively supported color formats 1305 * @native_nfourccs: The number of entries in @native_fourccs 1306 * @fourccs_out: Returns 4CC codes of supported color formats 1307 * @nfourccs_out: The number of available entries in @fourccs_out 1308 * 1309 * This function create a list of supported color format from natively 1310 * supported formats and additional emulated formats. 1311 * At a minimum, most userspace programs expect at least support for 1312 * XRGB8888 on the primary plane. Devices that have to emulate the 1313 * format, and possibly others, can use drm_fb_build_fourcc_list() to 1314 * create a list of supported color formats. The returned list can 1315 * be handed over to drm_universal_plane_init() et al. Native formats 1316 * will go before emulated formats. Native formats with alpha channel 1317 * will be replaced by such without, as primary planes usually don't 1318 * support alpha. Other heuristics might be applied 1319 * to optimize the order. Formats near the beginning of the list are 1320 * usually preferred over formats near the end of the list. 1321 * 1322 * Returns: 1323 * The number of color-formats 4CC codes returned in @fourccs_out. 1324 */ 1325 size_t drm_fb_build_fourcc_list(struct drm_device *dev, 1326 const u32 *native_fourccs, size_t native_nfourccs, 1327 u32 *fourccs_out, size_t nfourccs_out) 1328 { 1329 /* 1330 * XRGB8888 is the default fallback format for most of userspace 1331 * and it's currently the only format that should be emulated for 1332 * the primary plane. Only if there's ever another default fallback, 1333 * it should be added here. 1334 */ 1335 static const uint32_t extra_fourccs[] = { 1336 DRM_FORMAT_XRGB8888, 1337 }; 1338 static const size_t extra_nfourccs = ARRAY_SIZE(extra_fourccs); 1339 1340 u32 *fourccs = fourccs_out; 1341 const u32 *fourccs_end = fourccs_out + nfourccs_out; 1342 size_t i; 1343 1344 /* 1345 * The device's native formats go first. 1346 */ 1347 1348 for (i = 0; i < native_nfourccs; ++i) { 1349 /* 1350 * Several DTs, boot loaders and firmware report native 1351 * alpha formats that are non-alpha formats instead. So 1352 * replace alpha formats by non-alpha formats. 1353 */ 1354 u32 fourcc = drm_fb_nonalpha_fourcc(native_fourccs[i]); 1355 1356 if (is_listed_fourcc(fourccs_out, fourccs - fourccs_out, fourcc)) { 1357 continue; /* skip duplicate entries */ 1358 } else if (fourccs == fourccs_end) { 1359 drm_warn(dev, "Ignoring native format %p4cc\n", &fourcc); 1360 continue; /* end of available output buffer */ 1361 } 1362 1363 drm_dbg_kms(dev, "adding native format %p4cc\n", &fourcc); 1364 1365 *fourccs = fourcc; 1366 ++fourccs; 1367 } 1368 1369 /* 1370 * The extra formats, emulated by the driver, go second. 1371 */ 1372 1373 for (i = 0; (i < extra_nfourccs) && (fourccs < fourccs_end); ++i) { 1374 u32 fourcc = extra_fourccs[i]; 1375 1376 if (is_listed_fourcc(fourccs_out, fourccs - fourccs_out, fourcc)) { 1377 continue; /* skip duplicate and native entries */ 1378 } else if (fourccs == fourccs_end) { 1379 drm_warn(dev, "Ignoring emulated format %p4cc\n", &fourcc); 1380 continue; /* end of available output buffer */ 1381 } 1382 1383 drm_dbg_kms(dev, "adding emulated format %p4cc\n", &fourcc); 1384 1385 *fourccs = fourcc; 1386 ++fourccs; 1387 } 1388 1389 return fourccs - fourccs_out; 1390 } 1391 EXPORT_SYMBOL(drm_fb_build_fourcc_list); 1392