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