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 /** 563 * drm_fb_xrgb8888_to_rgb565 - Convert XRGB8888 to RGB565 clip buffer 564 * @dst: Array of RGB565 destination buffers 565 * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines 566 * within @dst; can be NULL if scanlines are stored next to each other. 567 * @src: Array of XRGB8888 source buffer 568 * @fb: DRM framebuffer 569 * @clip: Clip rectangle area to copy 570 * @state: Transform and conversion state 571 * 572 * This function copies parts of a framebuffer to display memory and converts the 573 * color format during the process. Destination and framebuffer formats must match. The 574 * parameters @dst, @dst_pitch and @src refer to arrays. Each array must have at 575 * least as many entries as there are planes in @fb's format. Each entry stores the 576 * value for the format's respective color plane at the same index. 577 * 578 * This function does not apply clipping on @dst (i.e. the destination is at the 579 * top-left corner). 580 * 581 * Drivers can use this function for RGB565 devices that don't support XRGB8888 natively. 582 */ 583 void drm_fb_xrgb8888_to_rgb565(struct iosys_map *dst, const unsigned int *dst_pitch, 584 const struct iosys_map *src, const struct drm_framebuffer *fb, 585 const struct drm_rect *clip, struct drm_format_conv_state *state) 586 { 587 static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = { 588 2, 589 }; 590 591 drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state, 592 drm_fb_xrgb8888_to_rgb565_line); 593 } 594 EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb565); 595 596 static void drm_fb_xrgb8888_to_rgb565be_line(void *dbuf, const void *sbuf, 597 unsigned int pixels) 598 { 599 drm_fb_xfrm_line_32to16(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_rgb565be); 600 } 601 602 /** 603 * drm_fb_xrgb8888_to_rgb565be - Convert XRGB8888 to RGB565|DRM_FORMAT_BIG_ENDIAN clip buffer 604 * @dst: Array of RGB565BE destination buffers 605 * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines 606 * within @dst; can be NULL if scanlines are stored next to each other. 607 * @src: Array of XRGB8888 source buffer 608 * @fb: DRM framebuffer 609 * @clip: Clip rectangle area to copy 610 * @state: Transform and conversion state 611 * 612 * This function copies parts of a framebuffer to display memory and converts the 613 * color format during the process. Destination and framebuffer formats must match. The 614 * parameters @dst, @dst_pitch and @src refer to arrays. Each array must have at 615 * least as many entries as there are planes in @fb's format. Each entry stores the 616 * value for the format's respective color plane at the same index. 617 * 618 * This function does not apply clipping on @dst (i.e. the destination is at the 619 * top-left corner). 620 * 621 * Drivers can use this function for RGB565BE devices that don't support XRGB8888 natively. 622 */ 623 void drm_fb_xrgb8888_to_rgb565be(struct iosys_map *dst, const unsigned int *dst_pitch, 624 const struct iosys_map *src, const struct drm_framebuffer *fb, 625 const struct drm_rect *clip, struct drm_format_conv_state *state) 626 { 627 static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = { 628 2, 629 }; 630 631 drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state, 632 drm_fb_xrgb8888_to_rgb565be_line); 633 } 634 EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb565be); 635 636 static void drm_fb_xrgb8888_to_xrgb1555_line(void *dbuf, const void *sbuf, unsigned int pixels) 637 { 638 drm_fb_xfrm_line_32to16(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_xrgb1555); 639 } 640 641 /** 642 * drm_fb_xrgb8888_to_xrgb1555 - Convert XRGB8888 to XRGB1555 clip buffer 643 * @dst: Array of XRGB1555 destination buffers 644 * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines 645 * within @dst; can be NULL if scanlines are stored next to each other. 646 * @src: Array of XRGB8888 source buffer 647 * @fb: DRM framebuffer 648 * @clip: Clip rectangle area to copy 649 * @state: Transform and conversion state 650 * 651 * This function copies parts of a framebuffer to display memory and converts 652 * the color format during the process. The parameters @dst, @dst_pitch and 653 * @src refer to arrays. Each array must have at least as many entries as 654 * there are planes in @fb's format. Each entry stores the value for the 655 * format's respective color plane at the same index. 656 * 657 * This function does not apply clipping on @dst (i.e. the destination is at the 658 * top-left corner). 659 * 660 * Drivers can use this function for XRGB1555 devices that don't support 661 * XRGB8888 natively. 662 */ 663 void drm_fb_xrgb8888_to_xrgb1555(struct iosys_map *dst, const unsigned int *dst_pitch, 664 const struct iosys_map *src, const struct drm_framebuffer *fb, 665 const struct drm_rect *clip, struct drm_format_conv_state *state) 666 { 667 static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = { 668 2, 669 }; 670 671 drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state, 672 drm_fb_xrgb8888_to_xrgb1555_line); 673 } 674 EXPORT_SYMBOL(drm_fb_xrgb8888_to_xrgb1555); 675 676 static void drm_fb_xrgb8888_to_argb1555_line(void *dbuf, const void *sbuf, unsigned int pixels) 677 { 678 drm_fb_xfrm_line_32to16(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_argb1555); 679 } 680 681 /** 682 * drm_fb_xrgb8888_to_argb1555 - Convert XRGB8888 to ARGB1555 clip buffer 683 * @dst: Array of ARGB1555 destination buffers 684 * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines 685 * within @dst; can be NULL if scanlines are stored next to each other. 686 * @src: Array of XRGB8888 source buffer 687 * @fb: DRM framebuffer 688 * @clip: Clip rectangle area to copy 689 * @state: Transform and conversion state 690 * 691 * This function copies parts of a framebuffer to display memory and converts 692 * the color format during the process. The parameters @dst, @dst_pitch and 693 * @src refer to arrays. Each array must have at least as many entries as 694 * there are planes in @fb's format. Each entry stores the value for the 695 * format's respective color plane at the same index. 696 * 697 * This function does not apply clipping on @dst (i.e. the destination is at the 698 * top-left corner). 699 * 700 * Drivers can use this function for ARGB1555 devices that don't support 701 * XRGB8888 natively. It sets an opaque alpha channel as part of the conversion. 702 */ 703 void drm_fb_xrgb8888_to_argb1555(struct iosys_map *dst, const unsigned int *dst_pitch, 704 const struct iosys_map *src, const struct drm_framebuffer *fb, 705 const struct drm_rect *clip, struct drm_format_conv_state *state) 706 { 707 static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = { 708 2, 709 }; 710 711 drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state, 712 drm_fb_xrgb8888_to_argb1555_line); 713 } 714 EXPORT_SYMBOL(drm_fb_xrgb8888_to_argb1555); 715 716 static void drm_fb_xrgb8888_to_rgba5551_line(void *dbuf, const void *sbuf, unsigned int pixels) 717 { 718 drm_fb_xfrm_line_32to16(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_rgba5551); 719 } 720 721 /** 722 * drm_fb_xrgb8888_to_rgba5551 - Convert XRGB8888 to RGBA5551 clip buffer 723 * @dst: Array of RGBA5551 destination buffers 724 * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines 725 * within @dst; can be NULL if scanlines are stored next to each other. 726 * @src: Array of XRGB8888 source buffer 727 * @fb: DRM framebuffer 728 * @clip: Clip rectangle area to copy 729 * @state: Transform and conversion state 730 * 731 * This function copies parts of a framebuffer to display memory and converts 732 * the color format during the process. The parameters @dst, @dst_pitch and 733 * @src refer to arrays. Each array must have at least as many entries as 734 * there are planes in @fb's format. Each entry stores the value for the 735 * format's respective color plane at the same index. 736 * 737 * This function does not apply clipping on @dst (i.e. the destination is at the 738 * top-left corner). 739 * 740 * Drivers can use this function for RGBA5551 devices that don't support 741 * XRGB8888 natively. It sets an opaque alpha channel as part of the conversion. 742 */ 743 void drm_fb_xrgb8888_to_rgba5551(struct iosys_map *dst, const unsigned int *dst_pitch, 744 const struct iosys_map *src, const struct drm_framebuffer *fb, 745 const struct drm_rect *clip, struct drm_format_conv_state *state) 746 { 747 static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = { 748 2, 749 }; 750 751 drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state, 752 drm_fb_xrgb8888_to_rgba5551_line); 753 } 754 EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgba5551); 755 756 static void drm_fb_xrgb8888_to_rgb888_line(void *dbuf, const void *sbuf, unsigned int pixels) 757 { 758 drm_fb_xfrm_line_32to24(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_rgb888); 759 } 760 761 /** 762 * drm_fb_xrgb8888_to_rgb888 - Convert XRGB8888 to RGB888 clip buffer 763 * @dst: Array of RGB888 destination buffers 764 * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines 765 * within @dst; can be NULL if scanlines are stored next to each other. 766 * @src: Array of XRGB8888 source buffers 767 * @fb: DRM framebuffer 768 * @clip: Clip rectangle area to copy 769 * @state: Transform and conversion state 770 * 771 * This function copies parts of a framebuffer to display memory and converts the 772 * color format during the process. Destination and framebuffer formats must match. The 773 * parameters @dst, @dst_pitch and @src refer to arrays. Each array must have at 774 * least as many entries as there are planes in @fb's format. Each entry stores the 775 * value for the format's respective color plane at the same index. 776 * 777 * This function does not apply clipping on @dst (i.e. the destination is at the 778 * top-left corner). 779 * 780 * Drivers can use this function for RGB888 devices that don't natively 781 * support XRGB8888. 782 */ 783 void drm_fb_xrgb8888_to_rgb888(struct iosys_map *dst, const unsigned int *dst_pitch, 784 const struct iosys_map *src, const struct drm_framebuffer *fb, 785 const struct drm_rect *clip, struct drm_format_conv_state *state) 786 { 787 static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = { 788 3, 789 }; 790 791 drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state, 792 drm_fb_xrgb8888_to_rgb888_line); 793 } 794 EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb888); 795 796 static void drm_fb_xrgb8888_to_bgr888_line(void *dbuf, const void *sbuf, unsigned int pixels) 797 { 798 drm_fb_xfrm_line_32to24(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_bgr888); 799 } 800 801 /** 802 * drm_fb_xrgb8888_to_bgr888 - Convert XRGB8888 to BGR888 clip buffer 803 * @dst: Array of BGR888 destination buffers 804 * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines 805 * within @dst; can be NULL if scanlines are stored next to each other. 806 * @src: Array of XRGB8888 source buffers 807 * @fb: DRM framebuffer 808 * @clip: Clip rectangle area to copy 809 * @state: Transform and conversion state 810 * 811 * This function copies parts of a framebuffer to display memory and converts the 812 * color format during the process. Destination and framebuffer formats must match. The 813 * parameters @dst, @dst_pitch and @src refer to arrays. Each array must have at 814 * least as many entries as there are planes in @fb's format. Each entry stores the 815 * value for the format's respective color plane at the same index. 816 * 817 * This function does not apply clipping on @dst (i.e. the destination is at the 818 * top-left corner). 819 * 820 * Drivers can use this function for BGR888 devices that don't natively 821 * support XRGB8888. 822 */ 823 void drm_fb_xrgb8888_to_bgr888(struct iosys_map *dst, const unsigned int *dst_pitch, 824 const struct iosys_map *src, const struct drm_framebuffer *fb, 825 const struct drm_rect *clip, struct drm_format_conv_state *state) 826 { 827 static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = { 828 3, 829 }; 830 831 drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state, 832 drm_fb_xrgb8888_to_bgr888_line); 833 } 834 EXPORT_SYMBOL(drm_fb_xrgb8888_to_bgr888); 835 836 static void drm_fb_xrgb8888_to_argb8888_line(void *dbuf, const void *sbuf, unsigned int pixels) 837 { 838 drm_fb_xfrm_line_32to32(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_argb8888); 839 } 840 841 /** 842 * drm_fb_xrgb8888_to_argb8888 - Convert XRGB8888 to ARGB8888 clip buffer 843 * @dst: Array of ARGB8888 destination buffers 844 * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines 845 * within @dst; can be NULL if scanlines are stored next to each other. 846 * @src: Array of XRGB8888 source buffer 847 * @fb: DRM framebuffer 848 * @clip: Clip rectangle area to copy 849 * @state: Transform and conversion state 850 * 851 * This function copies parts of a framebuffer to display memory and converts the 852 * color format during the process. The parameters @dst, @dst_pitch and @src refer 853 * to arrays. Each array must have at least as many entries as there are planes in 854 * @fb's format. Each entry stores the value for the format's respective color plane 855 * at the same index. 856 * 857 * This function does not apply clipping on @dst (i.e. the destination is at the 858 * top-left corner). 859 * 860 * Drivers can use this function for ARGB8888 devices that don't support XRGB8888 861 * natively. It sets an opaque alpha channel as part of the conversion. 862 */ 863 void drm_fb_xrgb8888_to_argb8888(struct iosys_map *dst, const unsigned int *dst_pitch, 864 const struct iosys_map *src, const struct drm_framebuffer *fb, 865 const struct drm_rect *clip, 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_argb8888_line); 873 } 874 EXPORT_SYMBOL(drm_fb_xrgb8888_to_argb8888); 875 876 static void drm_fb_xrgb8888_to_abgr8888_line(void *dbuf, const void *sbuf, unsigned int pixels) 877 { 878 drm_fb_xfrm_line_32to32(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_abgr8888); 879 } 880 881 /** 882 * drm_fb_xrgb8888_to_abgr8888 - Convert XRGB8888 to ABGR8888 clip buffer 883 * @dst: Array of ABGR8888 destination buffers 884 * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines 885 * within @dst; can be NULL if scanlines are stored next to each other. 886 * @src: Array of XRGB8888 source buffer 887 * @fb: DRM framebuffer 888 * @clip: Clip rectangle area to copy 889 * @state: Transform and conversion state 890 * 891 * This function copies parts of a framebuffer to display memory and converts the 892 * color format during the process. The parameters @dst, @dst_pitch and @src refer 893 * to arrays. Each array must have at least as many entries as there are planes in 894 * @fb's format. Each entry stores the value for the format's respective color plane 895 * at the same index. 896 * 897 * This function does not apply clipping on @dst (i.e. the destination is at the 898 * top-left corner). 899 * 900 * Drivers can use this function for ABGR8888 devices that don't support XRGB8888 901 * natively. It sets an opaque alpha channel as part of the conversion. 902 */ 903 void drm_fb_xrgb8888_to_abgr8888(struct iosys_map *dst, const unsigned int *dst_pitch, 904 const struct iosys_map *src, 905 const struct drm_framebuffer *fb, 906 const struct drm_rect *clip, 907 struct drm_format_conv_state *state) 908 { 909 static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = { 910 4, 911 }; 912 913 drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state, 914 drm_fb_xrgb8888_to_abgr8888_line); 915 } 916 EXPORT_SYMBOL(drm_fb_xrgb8888_to_abgr8888); 917 918 static void drm_fb_xrgb8888_to_xbgr8888_line(void *dbuf, const void *sbuf, unsigned int pixels) 919 { 920 drm_fb_xfrm_line_32to32(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_xbgr8888); 921 } 922 923 /** 924 * drm_fb_xrgb8888_to_xbgr8888 - Convert XRGB8888 to XBGR8888 clip buffer 925 * @dst: Array of XBGR8888 destination buffers 926 * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines 927 * within @dst; can be NULL if scanlines are stored next to each other. 928 * @src: Array of XRGB8888 source buffer 929 * @fb: DRM framebuffer 930 * @clip: Clip rectangle area to copy 931 * @state: Transform and conversion state 932 * 933 * This function copies parts of a framebuffer to display memory and converts the 934 * color format during the process. The parameters @dst, @dst_pitch and @src refer 935 * to arrays. Each array must have at least as many entries as there are planes in 936 * @fb's format. Each entry stores the value for the format's respective color plane 937 * at the same index. 938 * 939 * This function does not apply clipping on @dst (i.e. the destination is at the 940 * top-left corner). 941 * 942 * Drivers can use this function for XBGR8888 devices that don't support XRGB8888 943 * natively. 944 */ 945 void drm_fb_xrgb8888_to_xbgr8888(struct iosys_map *dst, const unsigned int *dst_pitch, 946 const struct iosys_map *src, 947 const struct drm_framebuffer *fb, 948 const struct drm_rect *clip, 949 struct drm_format_conv_state *state) 950 { 951 static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = { 952 4, 953 }; 954 955 drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state, 956 drm_fb_xrgb8888_to_xbgr8888_line); 957 } 958 EXPORT_SYMBOL(drm_fb_xrgb8888_to_xbgr8888); 959 960 static void drm_fb_xrgb8888_to_bgrx8888_line(void *dbuf, const void *sbuf, unsigned int pixels) 961 { 962 drm_fb_xfrm_line_32to32(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_bgrx8888); 963 } 964 965 /** 966 * drm_fb_xrgb8888_to_bgrx8888 - Convert XRGB8888 to BGRX8888 clip buffer 967 * @dst: Array of BGRX8888 destination buffers 968 * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines 969 * within @dst; can be NULL if scanlines are stored next to each other. 970 * @src: Array of XRGB8888 source buffer 971 * @fb: DRM framebuffer 972 * @clip: Clip rectangle area to copy 973 * @state: Transform and conversion state 974 * 975 * This function copies parts of a framebuffer to display memory and converts the 976 * color format during the process. The parameters @dst, @dst_pitch and @src refer 977 * to arrays. Each array must have at least as many entries as there are planes in 978 * @fb's format. Each entry stores the value for the format's respective color plane 979 * at the same index. 980 * 981 * This function does not apply clipping on @dst (i.e. the destination is at the 982 * top-left corner). 983 * 984 * Drivers can use this function for BGRX8888 devices that don't support XRGB8888 985 * natively. 986 */ 987 void drm_fb_xrgb8888_to_bgrx8888(struct iosys_map *dst, const unsigned int *dst_pitch, 988 const struct iosys_map *src, 989 const struct drm_framebuffer *fb, 990 const struct drm_rect *clip, 991 struct drm_format_conv_state *state) 992 { 993 static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = { 994 4, 995 }; 996 997 drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state, 998 drm_fb_xrgb8888_to_bgrx8888_line); 999 } 1000 EXPORT_SYMBOL(drm_fb_xrgb8888_to_bgrx8888); 1001 1002 static void drm_fb_xrgb8888_to_xrgb2101010_line(void *dbuf, const void *sbuf, unsigned int pixels) 1003 { 1004 drm_fb_xfrm_line_32to32(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_xrgb2101010); 1005 } 1006 1007 /** 1008 * drm_fb_xrgb8888_to_xrgb2101010 - Convert XRGB8888 to XRGB2101010 clip buffer 1009 * @dst: Array of XRGB2101010 destination buffers 1010 * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines 1011 * within @dst; can be NULL if scanlines are stored next to each other. 1012 * @src: Array of XRGB8888 source buffers 1013 * @fb: DRM framebuffer 1014 * @clip: Clip rectangle area to copy 1015 * @state: Transform and conversion state 1016 * 1017 * This function copies parts of a framebuffer to display memory and converts the 1018 * color format during the process. Destination and framebuffer formats must match. The 1019 * parameters @dst, @dst_pitch and @src refer to arrays. Each array must have at 1020 * least as many entries as there are planes in @fb's format. Each entry stores the 1021 * value for the format's respective color plane at the same index. 1022 * 1023 * This function does not apply clipping on @dst (i.e. the destination is at the 1024 * top-left corner). 1025 * 1026 * Drivers can use this function for XRGB2101010 devices that don't support XRGB8888 1027 * natively. 1028 */ 1029 void drm_fb_xrgb8888_to_xrgb2101010(struct iosys_map *dst, const unsigned int *dst_pitch, 1030 const struct iosys_map *src, const struct drm_framebuffer *fb, 1031 const struct drm_rect *clip, 1032 struct drm_format_conv_state *state) 1033 { 1034 static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = { 1035 4, 1036 }; 1037 1038 drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state, 1039 drm_fb_xrgb8888_to_xrgb2101010_line); 1040 } 1041 EXPORT_SYMBOL(drm_fb_xrgb8888_to_xrgb2101010); 1042 1043 static void drm_fb_xrgb8888_to_argb2101010_line(void *dbuf, const void *sbuf, unsigned int pixels) 1044 { 1045 drm_fb_xfrm_line_32to32(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_argb2101010); 1046 } 1047 1048 /** 1049 * drm_fb_xrgb8888_to_argb2101010 - Convert XRGB8888 to ARGB2101010 clip buffer 1050 * @dst: Array of ARGB2101010 destination buffers 1051 * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines 1052 * within @dst; can be NULL if scanlines are stored next to each other. 1053 * @src: Array of XRGB8888 source buffers 1054 * @fb: DRM framebuffer 1055 * @clip: Clip rectangle area to copy 1056 * @state: Transform and conversion state 1057 * 1058 * This function copies parts of a framebuffer to display memory and converts 1059 * the color format during the process. The parameters @dst, @dst_pitch and 1060 * @src refer to arrays. Each array must have at least as many entries as 1061 * there are planes in @fb's format. Each entry stores the value for the 1062 * format's respective color plane at the same index. 1063 * 1064 * This function does not apply clipping on @dst (i.e. the destination is at the 1065 * top-left corner). 1066 * 1067 * Drivers can use this function for ARGB2101010 devices that don't support XRGB8888 1068 * natively. 1069 */ 1070 void drm_fb_xrgb8888_to_argb2101010(struct iosys_map *dst, const unsigned int *dst_pitch, 1071 const struct iosys_map *src, const struct drm_framebuffer *fb, 1072 const struct drm_rect *clip, 1073 struct drm_format_conv_state *state) 1074 { 1075 static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = { 1076 4, 1077 }; 1078 1079 drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state, 1080 drm_fb_xrgb8888_to_argb2101010_line); 1081 } 1082 EXPORT_SYMBOL(drm_fb_xrgb8888_to_argb2101010); 1083 1084 static void drm_fb_xrgb8888_to_gray8_line(void *dbuf, const void *sbuf, unsigned int pixels) 1085 { 1086 drm_fb_xfrm_line_32to8(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_r8_bt601); 1087 } 1088 1089 /** 1090 * drm_fb_xrgb8888_to_gray8 - Convert XRGB8888 to grayscale 1091 * @dst: Array of 8-bit grayscale destination buffers 1092 * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines 1093 * within @dst; can be NULL if scanlines are stored next to each other. 1094 * @src: Array of XRGB8888 source buffers 1095 * @fb: DRM framebuffer 1096 * @clip: Clip rectangle area to copy 1097 * @state: Transform and conversion state 1098 * 1099 * This function copies parts of a framebuffer to display memory and converts the 1100 * color format during the process. Destination and framebuffer formats must match. The 1101 * parameters @dst, @dst_pitch and @src refer to arrays. Each array must have at 1102 * least as many entries as there are planes in @fb's format. Each entry stores the 1103 * value for the format's respective color plane at the same index. 1104 * 1105 * This function does not apply clipping on @dst (i.e. the destination is at the 1106 * top-left corner). 1107 * 1108 * DRM doesn't have native monochrome or grayscale support. Drivers can use this 1109 * function for grayscale devices that don't support XRGB8888 natively.Such 1110 * drivers can announce the commonly supported XR24 format to userspace and use 1111 * this function to convert to the native format. Monochrome drivers will use the 1112 * most significant bit, where 1 means foreground color and 0 background color. 1113 * ITU BT.601 is being used for the RGB -> luma (brightness) conversion. 1114 */ 1115 void drm_fb_xrgb8888_to_gray8(struct iosys_map *dst, const unsigned int *dst_pitch, 1116 const struct iosys_map *src, const struct drm_framebuffer *fb, 1117 const struct drm_rect *clip, struct drm_format_conv_state *state) 1118 { 1119 static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = { 1120 1, 1121 }; 1122 1123 drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state, 1124 drm_fb_xrgb8888_to_gray8_line); 1125 } 1126 EXPORT_SYMBOL(drm_fb_xrgb8888_to_gray8); 1127 1128 static void drm_fb_argb8888_to_argb4444_line(void *dbuf, const void *sbuf, unsigned int pixels) 1129 { 1130 drm_fb_xfrm_line_32to16(dbuf, sbuf, pixels, drm_pixel_argb8888_to_argb4444); 1131 } 1132 1133 /** 1134 * drm_fb_argb8888_to_argb4444 - Convert ARGB8888 to ARGB4444 clip buffer 1135 * @dst: Array of ARGB4444 destination buffers 1136 * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines 1137 * within @dst; can be NULL if scanlines are stored next to each other. 1138 * @src: Array of ARGB8888 source buffer 1139 * @fb: DRM framebuffer 1140 * @clip: Clip rectangle area to copy 1141 * @state: Transform and conversion state 1142 * 1143 * This function copies parts of a framebuffer to display memory and converts 1144 * the color format during the process. The parameters @dst, @dst_pitch and 1145 * @src refer to arrays. Each array must have at least as many entries as 1146 * there are planes in @fb's format. Each entry stores the value for the 1147 * format's respective color plane at the same index. 1148 * 1149 * This function does not apply clipping on @dst (i.e. the destination is at the 1150 * top-left corner). 1151 * 1152 * Drivers can use this function for ARGB4444 devices that don't support 1153 * ARGB8888 natively. 1154 */ 1155 void drm_fb_argb8888_to_argb4444(struct iosys_map *dst, const unsigned int *dst_pitch, 1156 const struct iosys_map *src, const struct drm_framebuffer *fb, 1157 const struct drm_rect *clip, struct drm_format_conv_state *state) 1158 { 1159 static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = { 1160 2, 1161 }; 1162 1163 drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state, 1164 drm_fb_argb8888_to_argb4444_line); 1165 } 1166 EXPORT_SYMBOL(drm_fb_argb8888_to_argb4444); 1167 1168 /** 1169 * drm_fb_blit - Copy parts of a framebuffer to display memory 1170 * @dst: Array of display-memory addresses to copy to 1171 * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines 1172 * within @dst; can be NULL if scanlines are stored next to each other. 1173 * @dst_format: FOURCC code of the display's color format 1174 * @src: The framebuffer memory to copy from 1175 * @fb: The framebuffer to copy from 1176 * @clip: Clip rectangle area to copy 1177 * @state: Transform and conversion state 1178 * 1179 * This function copies parts of a framebuffer to display memory. If the 1180 * formats of the display and the framebuffer mismatch, the blit function 1181 * will attempt to convert between them during the process. The parameters @dst, 1182 * @dst_pitch and @src refer to arrays. Each array must have at least as many 1183 * entries as there are planes in @dst_format's format. Each entry stores the 1184 * value for the format's respective color plane at the same index. 1185 * 1186 * This function does not apply clipping on @dst (i.e. the destination is at the 1187 * top-left corner). 1188 * 1189 * Returns: 1190 * 0 on success, or 1191 * -EINVAL if the color-format conversion failed, or 1192 * a negative error code otherwise. 1193 */ 1194 int drm_fb_blit(struct iosys_map *dst, const unsigned int *dst_pitch, uint32_t dst_format, 1195 const struct iosys_map *src, const struct drm_framebuffer *fb, 1196 const struct drm_rect *clip, struct drm_format_conv_state *state) 1197 { 1198 uint32_t fb_format = fb->format->format; 1199 1200 if (fb_format == dst_format) { 1201 drm_fb_memcpy(dst, dst_pitch, src, fb, clip); 1202 return 0; 1203 } else if (fb_format == (dst_format | DRM_FORMAT_BIG_ENDIAN)) { 1204 drm_fb_swab(dst, dst_pitch, src, fb, clip, false, state); 1205 return 0; 1206 } else if (fb_format == (dst_format & ~DRM_FORMAT_BIG_ENDIAN)) { 1207 drm_fb_swab(dst, dst_pitch, src, fb, clip, false, state); 1208 return 0; 1209 } else if (fb_format == DRM_FORMAT_XRGB8888) { 1210 if (dst_format == DRM_FORMAT_RGB565) { 1211 drm_fb_xrgb8888_to_rgb565(dst, dst_pitch, src, fb, clip, state); 1212 return 0; 1213 } else if (dst_format == DRM_FORMAT_XRGB1555) { 1214 drm_fb_xrgb8888_to_xrgb1555(dst, dst_pitch, src, fb, clip, state); 1215 return 0; 1216 } else if (dst_format == DRM_FORMAT_ARGB1555) { 1217 drm_fb_xrgb8888_to_argb1555(dst, dst_pitch, src, fb, clip, state); 1218 return 0; 1219 } else if (dst_format == DRM_FORMAT_RGBA5551) { 1220 drm_fb_xrgb8888_to_rgba5551(dst, dst_pitch, src, fb, clip, state); 1221 return 0; 1222 } else if (dst_format == DRM_FORMAT_RGB888) { 1223 drm_fb_xrgb8888_to_rgb888(dst, dst_pitch, src, fb, clip, state); 1224 return 0; 1225 } else if (dst_format == DRM_FORMAT_BGR888) { 1226 drm_fb_xrgb8888_to_bgr888(dst, dst_pitch, src, fb, clip, state); 1227 return 0; 1228 } else if (dst_format == DRM_FORMAT_ARGB8888) { 1229 drm_fb_xrgb8888_to_argb8888(dst, dst_pitch, src, fb, clip, state); 1230 return 0; 1231 } else if (dst_format == DRM_FORMAT_XBGR8888) { 1232 drm_fb_xrgb8888_to_xbgr8888(dst, dst_pitch, src, fb, clip, state); 1233 return 0; 1234 } else if (dst_format == DRM_FORMAT_ABGR8888) { 1235 drm_fb_xrgb8888_to_abgr8888(dst, dst_pitch, src, fb, clip, state); 1236 return 0; 1237 } else if (dst_format == DRM_FORMAT_XRGB2101010) { 1238 drm_fb_xrgb8888_to_xrgb2101010(dst, dst_pitch, src, fb, clip, state); 1239 return 0; 1240 } else if (dst_format == DRM_FORMAT_ARGB2101010) { 1241 drm_fb_xrgb8888_to_argb2101010(dst, dst_pitch, src, fb, clip, state); 1242 return 0; 1243 } else if (dst_format == DRM_FORMAT_BGRX8888) { 1244 drm_fb_swab(dst, dst_pitch, src, fb, clip, false, state); 1245 return 0; 1246 } 1247 } 1248 1249 drm_warn_once(fb->dev, "No conversion helper from %p4cc to %p4cc found.\n", 1250 &fb_format, &dst_format); 1251 1252 return -EINVAL; 1253 } 1254 EXPORT_SYMBOL(drm_fb_blit); 1255 1256 static void drm_fb_gray8_to_mono_line(void *dbuf, const void *sbuf, unsigned int pixels) 1257 { 1258 u8 *dbuf8 = dbuf; 1259 const u8 *sbuf8 = sbuf; 1260 1261 while (pixels) { 1262 unsigned int i, bits = min(pixels, 8U); 1263 u8 byte = 0; 1264 1265 for (i = 0; i < bits; i++, pixels--) { 1266 if (*sbuf8++ >= 128) 1267 byte |= BIT(i); 1268 } 1269 *dbuf8++ = byte; 1270 } 1271 } 1272 1273 /** 1274 * drm_fb_xrgb8888_to_mono - Convert XRGB8888 to monochrome 1275 * @dst: Array of monochrome destination buffers (0=black, 1=white) 1276 * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines 1277 * within @dst; can be NULL if scanlines are stored next to each other. 1278 * @src: Array of XRGB8888 source buffers 1279 * @fb: DRM framebuffer 1280 * @clip: Clip rectangle area to copy 1281 * @state: Transform and conversion state 1282 * 1283 * This function copies parts of a framebuffer to display memory and converts the 1284 * color format during the process. Destination and framebuffer formats must match. The 1285 * parameters @dst, @dst_pitch and @src refer to arrays. Each array must have at 1286 * least as many entries as there are planes in @fb's format. Each entry stores the 1287 * value for the format's respective color plane at the same index. 1288 * 1289 * This function does not apply clipping on @dst (i.e. the destination is at the 1290 * top-left corner). The first pixel (upper left corner of the clip rectangle) will 1291 * be converted and copied to the first bit (LSB) in the first byte of the monochrome 1292 * destination buffer. If the caller requires that the first pixel in a byte must 1293 * be located at an x-coordinate that is a multiple of 8, then the caller must take 1294 * care itself of supplying a suitable clip rectangle. 1295 * 1296 * DRM doesn't have native monochrome support. Drivers can use this function for 1297 * monochrome devices that don't support XRGB8888 natively. Such drivers can 1298 * announce the commonly supported XR24 format to userspace and use this function 1299 * to convert to the native format. 1300 * 1301 * This function uses drm_fb_xrgb8888_to_gray8() to convert to grayscale and 1302 * then the result is converted from grayscale to monochrome. 1303 */ 1304 void drm_fb_xrgb8888_to_mono(struct iosys_map *dst, const unsigned int *dst_pitch, 1305 const struct iosys_map *src, const struct drm_framebuffer *fb, 1306 const struct drm_rect *clip, struct drm_format_conv_state *state) 1307 { 1308 static const unsigned int default_dst_pitch[DRM_FORMAT_MAX_PLANES] = { 1309 0, 0, 0, 0 1310 }; 1311 unsigned int linepixels = drm_rect_width(clip); 1312 unsigned int lines = drm_rect_height(clip); 1313 unsigned int cpp = fb->format->cpp[0]; 1314 unsigned int len_src32 = linepixels * cpp; 1315 struct drm_device *dev = fb->dev; 1316 void *vaddr = src[0].vaddr; 1317 unsigned int dst_pitch_0; 1318 unsigned int y; 1319 u8 *mono = dst[0].vaddr, *gray8; 1320 u32 *src32; 1321 1322 if (drm_WARN_ON(dev, fb->format->format != DRM_FORMAT_XRGB8888)) 1323 return; 1324 1325 if (!dst_pitch) 1326 dst_pitch = default_dst_pitch; 1327 dst_pitch_0 = dst_pitch[0]; 1328 1329 /* 1330 * The mono destination buffer contains 1 bit per pixel 1331 */ 1332 if (!dst_pitch_0) 1333 dst_pitch_0 = DIV_ROUND_UP(linepixels, 8); 1334 1335 /* 1336 * The dma memory is write-combined so reads are uncached. 1337 * Speed up by fetching one line at a time. 1338 * 1339 * Also, format conversion from XR24 to monochrome are done 1340 * line-by-line but are converted to 8-bit grayscale as an 1341 * intermediate step. 1342 * 1343 * Allocate a buffer to be used for both copying from the cma 1344 * memory and to store the intermediate grayscale line pixels. 1345 */ 1346 src32 = drm_format_conv_state_reserve(state, len_src32 + linepixels, GFP_KERNEL); 1347 if (!src32) 1348 return; 1349 1350 gray8 = (u8 *)src32 + len_src32; 1351 1352 vaddr += clip_offset(clip, fb->pitches[0], cpp); 1353 for (y = 0; y < lines; y++) { 1354 src32 = memcpy(src32, vaddr, len_src32); 1355 drm_fb_xrgb8888_to_gray8_line(gray8, src32, linepixels); 1356 drm_fb_gray8_to_mono_line(mono, gray8, linepixels); 1357 vaddr += fb->pitches[0]; 1358 mono += dst_pitch_0; 1359 } 1360 } 1361 EXPORT_SYMBOL(drm_fb_xrgb8888_to_mono); 1362