1 // SPDX-License-Identifier: GPL-2.0 or MIT
3 * Copyright (C) 2016 Noralf Trønnes
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.
12 #include <linux/iosys-map.h>
13 #include <linux/module.h>
14 #include <linux/slab.h>
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>
23 #include "drm_format_internal.h"
26 * drm_format_conv_state_init - Initialize format-conversion state
27 * @state: The state to initialize
29 * Clears all fields in struct drm_format_conv_state. The state will
30 * be empty with no preallocated resources.
32 void drm_format_conv_state_init(struct drm_format_conv_state *state)
34 state->tmp.mem = NULL;
36 state->tmp.preallocated = false;
38 EXPORT_SYMBOL(drm_format_conv_state_init);
41 * drm_format_conv_state_copy - Copy format-conversion state
42 * @state: Destination state
43 * @old_state: Source state
45 * Copies format-conversion state from @old_state to @state; except for
48 void drm_format_conv_state_copy(struct drm_format_conv_state *state,
49 const struct drm_format_conv_state *old_state)
52 * So far, there's only temporary storage here, which we don't
53 * duplicate. Just clear the fields.
55 state->tmp.mem = NULL;
57 state->tmp.preallocated = false;
59 EXPORT_SYMBOL(drm_format_conv_state_copy);
62 * drm_format_conv_state_reserve - Allocates storage for format conversion
63 * @state: The format-conversion state
64 * @new_size: The minimum allocation size
65 * @flags: Flags for kmalloc()
67 * Allocates at least @new_size bytes and returns a pointer to the memory
68 * range. After calling this function, previously returned memory blocks
69 * are invalid. It's best to collect all memory requirements of a format
70 * conversion and call this function once to allocate the range.
73 * A pointer to the allocated memory range, or NULL otherwise.
75 void *drm_format_conv_state_reserve(struct drm_format_conv_state *state,
76 size_t new_size, gfp_t flags)
80 if (new_size <= state->tmp.size)
82 else if (state->tmp.preallocated)
85 mem = krealloc(state->tmp.mem, new_size, flags);
90 state->tmp.size = new_size;
93 return state->tmp.mem;
95 EXPORT_SYMBOL(drm_format_conv_state_reserve);
98 * drm_format_conv_state_release - Releases an format-conversion storage
99 * @state: The format-conversion state
101 * Releases the memory range references by the format-conversion state.
102 * After this call, all pointers to the memory are invalid. Prefer
103 * drm_format_conv_state_init() for cleaning up and unloading a driver.
105 void drm_format_conv_state_release(struct drm_format_conv_state *state)
107 if (state->tmp.preallocated)
110 kfree(state->tmp.mem);
111 state->tmp.mem = NULL;
114 EXPORT_SYMBOL(drm_format_conv_state_release);
116 static unsigned int clip_offset(const struct drm_rect *clip, unsigned int pitch, unsigned int cpp)
118 return clip->y1 * pitch + clip->x1 * cpp;
122 * drm_fb_clip_offset - Returns the clipping rectangles byte-offset in a framebuffer
123 * @pitch: Framebuffer line pitch in byte
124 * @format: Framebuffer format
125 * @clip: Clip rectangle
128 * The byte offset of the clip rectangle's top-left corner within the framebuffer.
130 unsigned int drm_fb_clip_offset(unsigned int pitch, const struct drm_format_info *format,
131 const struct drm_rect *clip)
133 return clip_offset(clip, pitch, format->cpp[0]);
135 EXPORT_SYMBOL(drm_fb_clip_offset);
137 /* TODO: Make this function work with multi-plane formats. */
138 static int __drm_fb_xfrm(void *dst, unsigned long dst_pitch, unsigned long dst_pixsize,
139 const void *vaddr, const struct drm_framebuffer *fb,
140 const struct drm_rect *clip, bool vaddr_cached_hint,
141 struct drm_format_conv_state *state,
142 void (*xfrm_line)(void *dbuf, const void *sbuf, unsigned int npixels))
144 unsigned long linepixels = drm_rect_width(clip);
145 unsigned long lines = drm_rect_height(clip);
146 size_t sbuf_len = linepixels * fb->format->cpp[0];
152 * Some source buffers, such as DMA memory, use write-combine
153 * caching, so reads are uncached. Speed up access by fetching
154 * one line at a time.
156 if (!vaddr_cached_hint) {
157 stmp = drm_format_conv_state_reserve(state, sbuf_len, GFP_KERNEL);
163 dst_pitch = drm_rect_width(clip) * dst_pixsize;
164 vaddr += clip_offset(clip, fb->pitches[0], fb->format->cpp[0]);
166 for (i = 0; i < lines; ++i) {
168 sbuf = memcpy(stmp, vaddr, sbuf_len);
171 xfrm_line(dst, sbuf, linepixels);
172 vaddr += fb->pitches[0];
179 /* TODO: Make this function work with multi-plane formats. */
180 static int __drm_fb_xfrm_toio(void __iomem *dst, unsigned long dst_pitch, unsigned long dst_pixsize,
181 const void *vaddr, const struct drm_framebuffer *fb,
182 const struct drm_rect *clip, bool vaddr_cached_hint,
183 struct drm_format_conv_state *state,
184 void (*xfrm_line)(void *dbuf, const void *sbuf, unsigned int npixels))
186 unsigned long linepixels = drm_rect_width(clip);
187 unsigned long lines = drm_rect_height(clip);
188 size_t dbuf_len = linepixels * dst_pixsize;
189 size_t stmp_off = round_up(dbuf_len, ARCH_KMALLOC_MINALIGN); /* for sbuf alignment */
190 size_t sbuf_len = linepixels * fb->format->cpp[0];
196 if (vaddr_cached_hint) {
197 dbuf = drm_format_conv_state_reserve(state, dbuf_len, GFP_KERNEL);
199 dbuf = drm_format_conv_state_reserve(state, stmp_off + sbuf_len, GFP_KERNEL);
200 stmp = dbuf + stmp_off;
206 dst_pitch = linepixels * dst_pixsize;
207 vaddr += clip_offset(clip, fb->pitches[0], fb->format->cpp[0]);
209 for (i = 0; i < lines; ++i) {
211 sbuf = memcpy(stmp, vaddr, sbuf_len);
214 xfrm_line(dbuf, sbuf, linepixels);
215 memcpy_toio(dst, dbuf, dbuf_len);
216 vaddr += fb->pitches[0];
223 /* TODO: Make this function work with multi-plane formats. */
224 static int drm_fb_xfrm(struct iosys_map *dst,
225 const unsigned int *dst_pitch, const u8 *dst_pixsize,
226 const struct iosys_map *src, const struct drm_framebuffer *fb,
227 const struct drm_rect *clip, bool vaddr_cached_hint,
228 struct drm_format_conv_state *state,
229 void (*xfrm_line)(void *dbuf, const void *sbuf, unsigned int npixels))
231 static const unsigned int default_dst_pitch[DRM_FORMAT_MAX_PLANES] = {
236 dst_pitch = default_dst_pitch;
238 /* TODO: handle src in I/O memory here */
240 return __drm_fb_xfrm_toio(dst[0].vaddr_iomem, dst_pitch[0], dst_pixsize[0],
241 src[0].vaddr, fb, clip, vaddr_cached_hint, state,
244 return __drm_fb_xfrm(dst[0].vaddr, dst_pitch[0], dst_pixsize[0],
245 src[0].vaddr, fb, clip, vaddr_cached_hint, state,
249 #define ALIGN_DOWN_PIXELS(end, n, a) \
250 ((end) - ((n) & ((a) - 1)))
252 static __always_inline void drm_fb_xfrm_line_32to8(void *dbuf, const void *sbuf,
254 u32 (*xfrm_pixel)(u32))
256 __le32 *dbuf32 = dbuf;
258 const __le32 *sbuf32 = sbuf;
259 const __le32 *send32 = sbuf32 + pixels;
261 /* write 4 pixels at once */
262 while (sbuf32 < ALIGN_DOWN_PIXELS(send32, pixels, 4)) {
264 le32_to_cpup(sbuf32),
265 le32_to_cpup(sbuf32 + 1),
266 le32_to_cpup(sbuf32 + 2),
267 le32_to_cpup(sbuf32 + 3),
269 /* write output bytes in reverse order for little endianness */
270 u32 val32 = xfrm_pixel(pix[0]) |
271 (xfrm_pixel(pix[1]) << 8) |
272 (xfrm_pixel(pix[2]) << 16) |
273 (xfrm_pixel(pix[3]) << 24);
274 *dbuf32++ = cpu_to_le32(val32);
275 sbuf32 += ARRAY_SIZE(pix);
278 /* write trailing pixels */
279 dbuf8 = (u8 __force *)dbuf32;
280 while (sbuf32 < send32)
281 *dbuf8++ = xfrm_pixel(le32_to_cpup(sbuf32++));
284 static __always_inline void drm_fb_xfrm_line_32to16(void *dbuf, const void *sbuf,
286 u32 (*xfrm_pixel)(u32))
288 __le64 *dbuf64 = dbuf;
291 const __le32 *sbuf32 = sbuf;
292 const __le32 *send32 = sbuf32 + pixels;
294 #if defined(CONFIG_64BIT)
295 /* write 4 pixels at once */
296 while (sbuf32 < ALIGN_DOWN_PIXELS(send32, pixels, 4)) {
298 le32_to_cpup(sbuf32),
299 le32_to_cpup(sbuf32 + 1),
300 le32_to_cpup(sbuf32 + 2),
301 le32_to_cpup(sbuf32 + 3),
303 /* write output bytes in reverse order for little endianness */
304 u64 val64 = ((u64)xfrm_pixel(pix[0])) |
305 ((u64)xfrm_pixel(pix[1]) << 16) |
306 ((u64)xfrm_pixel(pix[2]) << 32) |
307 ((u64)xfrm_pixel(pix[3]) << 48);
308 *dbuf64++ = cpu_to_le64(val64);
309 sbuf32 += ARRAY_SIZE(pix);
313 /* write 2 pixels at once */
314 dbuf32 = (__le32 __force *)dbuf64;
315 while (sbuf32 < ALIGN_DOWN_PIXELS(send32, pixels, 2)) {
317 le32_to_cpup(sbuf32),
318 le32_to_cpup(sbuf32 + 1),
320 /* write output bytes in reverse order for little endianness */
321 u32 val32 = xfrm_pixel(pix[0]) |
322 (xfrm_pixel(pix[1]) << 16);
323 *dbuf32++ = cpu_to_le32(val32);
324 sbuf32 += ARRAY_SIZE(pix);
327 /* write trailing pixel */
328 dbuf16 = (__le16 __force *)dbuf32;
329 while (sbuf32 < send32)
330 *dbuf16++ = cpu_to_le16(xfrm_pixel(le32_to_cpup(sbuf32++)));
333 static __always_inline void drm_fb_xfrm_line_32to24(void *dbuf, const void *sbuf,
335 u32 (*xfrm_pixel)(u32))
337 __le32 *dbuf32 = dbuf;
339 const __le32 *sbuf32 = sbuf;
340 const __le32 *send32 = sbuf32 + pixels;
342 /* write pixels in chunks of 4 */
343 while (sbuf32 < ALIGN_DOWN_PIXELS(send32, pixels, 4)) {
345 xfrm_pixel(le32_to_cpup(sbuf32)),
346 xfrm_pixel(le32_to_cpup(sbuf32 + 1)),
347 xfrm_pixel(le32_to_cpup(sbuf32 + 2)),
348 xfrm_pixel(le32_to_cpup(sbuf32 + 3)),
351 /* write output bytes in reverse order for little endianness */
352 ((val24[0] & 0x000000ff)) |
353 ((val24[0] & 0x0000ff00)) |
354 ((val24[0] & 0x00ff0000)) |
355 ((val24[1] & 0x000000ff) << 24),
356 ((val24[1] & 0x0000ff00) >> 8) |
357 ((val24[1] & 0x00ff0000) >> 8) |
358 ((val24[2] & 0x000000ff) << 16) |
359 ((val24[2] & 0x0000ff00) << 16),
360 ((val24[2] & 0x00ff0000) >> 16) |
361 ((val24[3] & 0x000000ff) << 8) |
362 ((val24[3] & 0x0000ff00) << 8) |
363 ((val24[3] & 0x00ff0000) << 8),
366 *dbuf32++ = cpu_to_le32(out32[0]);
367 *dbuf32++ = cpu_to_le32(out32[1]);
368 *dbuf32++ = cpu_to_le32(out32[2]);
369 sbuf32 += ARRAY_SIZE(val24);
372 /* write trailing pixel */
373 dbuf8 = (u8 __force *)dbuf32;
374 while (sbuf32 < send32) {
375 u32 val24 = xfrm_pixel(le32_to_cpup(sbuf32++));
376 /* write output in reverse order for little endianness */
377 *dbuf8++ = (val24 & 0x000000ff);
378 *dbuf8++ = (val24 & 0x0000ff00) >> 8;
379 *dbuf8++ = (val24 & 0x00ff0000) >> 16;
383 static __always_inline void drm_fb_xfrm_line_32to32(void *dbuf, const void *sbuf,
385 u32 (*xfrm_pixel)(u32))
387 __le32 *dbuf32 = dbuf;
388 const __le32 *sbuf32 = sbuf;
389 const __le32 *send32 = sbuf32 + pixels;
391 while (sbuf32 < send32)
392 *dbuf32++ = cpu_to_le32(xfrm_pixel(le32_to_cpup(sbuf32++)));
396 * drm_fb_memcpy - Copy clip buffer
397 * @dst: Array of destination buffers
398 * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines
399 * within @dst; can be NULL if scanlines are stored next to each other.
400 * @src: Array of source buffers
401 * @fb: DRM framebuffer
402 * @clip: Clip rectangle area to copy
404 * This function copies parts of a framebuffer to display memory. Destination and
405 * framebuffer formats must match. No conversion takes place. The parameters @dst,
406 * @dst_pitch and @src refer to arrays. Each array must have at least as many entries
407 * as there are planes in @fb's format. Each entry stores the value for the format's
408 * respective color plane at the same index.
410 * This function does not apply clipping on @dst (i.e. the destination is at the
413 void drm_fb_memcpy(struct iosys_map *dst, const unsigned int *dst_pitch,
414 const struct iosys_map *src, const struct drm_framebuffer *fb,
415 const struct drm_rect *clip)
417 static const unsigned int default_dst_pitch[DRM_FORMAT_MAX_PLANES] = {
421 const struct drm_format_info *format = fb->format;
422 unsigned int i, y, lines = drm_rect_height(clip);
425 dst_pitch = default_dst_pitch;
427 for (i = 0; i < format->num_planes; ++i) {
428 unsigned int bpp_i = drm_format_info_bpp(format, i);
429 unsigned int cpp_i = DIV_ROUND_UP(bpp_i, 8);
430 size_t len_i = DIV_ROUND_UP(drm_rect_width(clip) * bpp_i, 8);
431 unsigned int dst_pitch_i = dst_pitch[i];
432 struct iosys_map dst_i = dst[i];
433 struct iosys_map src_i = src[i];
438 iosys_map_incr(&src_i, clip_offset(clip, fb->pitches[i], cpp_i));
439 for (y = 0; y < lines; y++) {
440 /* TODO: handle src_i in I/O memory here */
441 iosys_map_memcpy_to(&dst_i, 0, src_i.vaddr, len_i);
442 iosys_map_incr(&src_i, fb->pitches[i]);
443 iosys_map_incr(&dst_i, dst_pitch_i);
447 EXPORT_SYMBOL(drm_fb_memcpy);
449 static void drm_fb_swab16_line(void *dbuf, const void *sbuf, unsigned int pixels)
452 const u16 *sbuf16 = sbuf;
453 const u16 *send16 = sbuf16 + pixels;
455 while (sbuf16 < send16)
456 *dbuf16++ = swab16(*sbuf16++);
459 static void drm_fb_swab32_line(void *dbuf, const void *sbuf, unsigned int pixels)
462 const u32 *sbuf32 = sbuf;
463 const u32 *send32 = sbuf32 + pixels;
465 while (sbuf32 < send32)
466 *dbuf32++ = swab32(*sbuf32++);
470 * drm_fb_swab - Swap bytes into clip buffer
471 * @dst: Array of destination buffers
472 * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines
473 * within @dst; can be NULL if scanlines are stored next to each other.
474 * @src: Array of source buffers
475 * @fb: DRM framebuffer
476 * @clip: Clip rectangle area to copy
477 * @cached: Source buffer is mapped cached (eg. not write-combined)
478 * @state: Transform and conversion state
480 * This function copies parts of a framebuffer to display memory and swaps per-pixel
481 * bytes during the process. Destination and framebuffer formats must match. The
482 * parameters @dst, @dst_pitch and @src refer to arrays. Each array must have at
483 * least as many entries as there are planes in @fb's format. Each entry stores the
484 * value for the format's respective color plane at the same index. If @cached is
485 * false a temporary buffer is used to cache one pixel line at a time to speed up
486 * slow uncached reads.
488 * This function does not apply clipping on @dst (i.e. the destination is at the
491 void drm_fb_swab(struct iosys_map *dst, const unsigned int *dst_pitch,
492 const struct iosys_map *src, const struct drm_framebuffer *fb,
493 const struct drm_rect *clip, bool cached,
494 struct drm_format_conv_state *state)
496 const struct drm_format_info *format = fb->format;
497 u8 cpp = DIV_ROUND_UP(drm_format_info_bpp(format, 0), 8);
498 void (*swab_line)(void *dbuf, const void *sbuf, unsigned int npixels);
502 swab_line = drm_fb_swab32_line;
505 swab_line = drm_fb_swab16_line;
508 drm_warn_once(fb->dev, "Format %p4cc has unsupported pixel size.\n",
513 drm_fb_xfrm(dst, dst_pitch, &cpp, src, fb, clip, cached, state, swab_line);
515 EXPORT_SYMBOL(drm_fb_swab);
517 static void drm_fb_xrgb8888_to_rgb332_line(void *dbuf, const void *sbuf, unsigned int pixels)
519 drm_fb_xfrm_line_32to8(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_rgb332);
523 * drm_fb_xrgb8888_to_rgb332 - Convert XRGB8888 to RGB332 clip buffer
524 * @dst: Array of RGB332 destination buffers
525 * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines
526 * within @dst; can be NULL if scanlines are stored next to each other.
527 * @src: Array of XRGB8888 source buffers
528 * @fb: DRM framebuffer
529 * @clip: Clip rectangle area to copy
530 * @state: Transform and conversion state
532 * This function copies parts of a framebuffer to display memory and converts the
533 * color format during the process. Destination and framebuffer formats must match. The
534 * parameters @dst, @dst_pitch and @src refer to arrays. Each array must have at
535 * least as many entries as there are planes in @fb's format. Each entry stores the
536 * value for the format's respective color plane at the same index.
538 * This function does not apply clipping on @dst (i.e. the destination is at the
541 * Drivers can use this function for RGB332 devices that don't support XRGB8888 natively.
543 void drm_fb_xrgb8888_to_rgb332(struct iosys_map *dst, const unsigned int *dst_pitch,
544 const struct iosys_map *src, const struct drm_framebuffer *fb,
545 const struct drm_rect *clip, struct drm_format_conv_state *state)
547 static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = {
551 drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state,
552 drm_fb_xrgb8888_to_rgb332_line);
554 EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb332);
556 static void drm_fb_xrgb8888_to_rgb565_line(void *dbuf, const void *sbuf, unsigned int pixels)
558 drm_fb_xfrm_line_32to16(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_rgb565);
561 static __always_inline u32 drm_xrgb8888_to_rgb565_swab(u32 pix)
563 return swab16(drm_pixel_xrgb8888_to_rgb565(pix));
566 /* TODO: implement this helper as conversion to RGB565|BIG_ENDIAN */
567 static void drm_fb_xrgb8888_to_rgb565_swab_line(void *dbuf, const void *sbuf,
570 drm_fb_xfrm_line_32to16(dbuf, sbuf, pixels, drm_xrgb8888_to_rgb565_swab);
574 * drm_fb_xrgb8888_to_rgb565 - Convert XRGB8888 to RGB565 clip buffer
575 * @dst: Array of RGB565 destination buffers
576 * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines
577 * within @dst; can be NULL if scanlines are stored next to each other.
578 * @src: Array of XRGB8888 source buffer
579 * @fb: DRM framebuffer
580 * @clip: Clip rectangle area to copy
581 * @state: Transform and conversion state
584 * This function copies parts of a framebuffer to display memory and converts the
585 * color format during the process. Destination and framebuffer formats must match. The
586 * parameters @dst, @dst_pitch and @src refer to arrays. Each array must have at
587 * least as many entries as there are planes in @fb's format. Each entry stores the
588 * value for the format's respective color plane at the same index.
590 * This function does not apply clipping on @dst (i.e. the destination is at the
593 * Drivers can use this function for RGB565 devices that don't support XRGB8888 natively.
595 void drm_fb_xrgb8888_to_rgb565(struct iosys_map *dst, const unsigned int *dst_pitch,
596 const struct iosys_map *src, const struct drm_framebuffer *fb,
597 const struct drm_rect *clip, struct drm_format_conv_state *state,
600 static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = {
604 void (*xfrm_line)(void *dbuf, const void *sbuf, unsigned int npixels);
607 xfrm_line = drm_fb_xrgb8888_to_rgb565_swab_line;
609 xfrm_line = drm_fb_xrgb8888_to_rgb565_line;
611 drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state, xfrm_line);
613 EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb565);
615 static void drm_fb_xrgb8888_to_xrgb1555_line(void *dbuf, const void *sbuf, unsigned int pixels)
617 drm_fb_xfrm_line_32to16(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_xrgb1555);
621 * drm_fb_xrgb8888_to_xrgb1555 - Convert XRGB8888 to XRGB1555 clip buffer
622 * @dst: Array of XRGB1555 destination buffers
623 * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines
624 * within @dst; can be NULL if scanlines are stored next to each other.
625 * @src: Array of XRGB8888 source buffer
626 * @fb: DRM framebuffer
627 * @clip: Clip rectangle area to copy
628 * @state: Transform and conversion state
630 * This function copies parts of a framebuffer to display memory and converts
631 * the color format during the process. The parameters @dst, @dst_pitch and
632 * @src refer to arrays. Each array must have at least as many entries as
633 * there are planes in @fb's format. Each entry stores the value for the
634 * format's respective color plane at the same index.
636 * This function does not apply clipping on @dst (i.e. the destination is at the
639 * Drivers can use this function for XRGB1555 devices that don't support
642 void drm_fb_xrgb8888_to_xrgb1555(struct iosys_map *dst, const unsigned int *dst_pitch,
643 const struct iosys_map *src, const struct drm_framebuffer *fb,
644 const struct drm_rect *clip, struct drm_format_conv_state *state)
646 static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = {
650 drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state,
651 drm_fb_xrgb8888_to_xrgb1555_line);
653 EXPORT_SYMBOL(drm_fb_xrgb8888_to_xrgb1555);
655 static void drm_fb_xrgb8888_to_argb1555_line(void *dbuf, const void *sbuf, unsigned int pixels)
657 drm_fb_xfrm_line_32to16(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_argb1555);
661 * drm_fb_xrgb8888_to_argb1555 - Convert XRGB8888 to ARGB1555 clip buffer
662 * @dst: Array of ARGB1555 destination buffers
663 * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines
664 * within @dst; can be NULL if scanlines are stored next to each other.
665 * @src: Array of XRGB8888 source buffer
666 * @fb: DRM framebuffer
667 * @clip: Clip rectangle area to copy
668 * @state: Transform and conversion state
670 * This function copies parts of a framebuffer to display memory and converts
671 * the color format during the process. The parameters @dst, @dst_pitch and
672 * @src refer to arrays. Each array must have at least as many entries as
673 * there are planes in @fb's format. Each entry stores the value for the
674 * format's respective color plane at the same index.
676 * This function does not apply clipping on @dst (i.e. the destination is at the
679 * Drivers can use this function for ARGB1555 devices that don't support
680 * XRGB8888 natively. It sets an opaque alpha channel as part of the conversion.
682 void drm_fb_xrgb8888_to_argb1555(struct iosys_map *dst, const unsigned int *dst_pitch,
683 const struct iosys_map *src, const struct drm_framebuffer *fb,
684 const struct drm_rect *clip, struct drm_format_conv_state *state)
686 static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = {
690 drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state,
691 drm_fb_xrgb8888_to_argb1555_line);
693 EXPORT_SYMBOL(drm_fb_xrgb8888_to_argb1555);
695 static void drm_fb_xrgb8888_to_rgba5551_line(void *dbuf, const void *sbuf, unsigned int pixels)
697 drm_fb_xfrm_line_32to16(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_rgba5551);
701 * drm_fb_xrgb8888_to_rgba5551 - Convert XRGB8888 to RGBA5551 clip buffer
702 * @dst: Array of RGBA5551 destination buffers
703 * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines
704 * within @dst; can be NULL if scanlines are stored next to each other.
705 * @src: Array of XRGB8888 source buffer
706 * @fb: DRM framebuffer
707 * @clip: Clip rectangle area to copy
708 * @state: Transform and conversion state
710 * This function copies parts of a framebuffer to display memory and converts
711 * the color format during the process. The parameters @dst, @dst_pitch and
712 * @src refer to arrays. Each array must have at least as many entries as
713 * there are planes in @fb's format. Each entry stores the value for the
714 * format's respective color plane at the same index.
716 * This function does not apply clipping on @dst (i.e. the destination is at the
719 * Drivers can use this function for RGBA5551 devices that don't support
720 * XRGB8888 natively. It sets an opaque alpha channel as part of the conversion.
722 void drm_fb_xrgb8888_to_rgba5551(struct iosys_map *dst, const unsigned int *dst_pitch,
723 const struct iosys_map *src, const struct drm_framebuffer *fb,
724 const struct drm_rect *clip, struct drm_format_conv_state *state)
726 static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = {
730 drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state,
731 drm_fb_xrgb8888_to_rgba5551_line);
733 EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgba5551);
735 static void drm_fb_xrgb8888_to_rgb888_line(void *dbuf, const void *sbuf, unsigned int pixels)
737 drm_fb_xfrm_line_32to24(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_rgb888);
741 * drm_fb_xrgb8888_to_rgb888 - Convert XRGB8888 to RGB888 clip buffer
742 * @dst: Array of RGB888 destination buffers
743 * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines
744 * within @dst; can be NULL if scanlines are stored next to each other.
745 * @src: Array of XRGB8888 source buffers
746 * @fb: DRM framebuffer
747 * @clip: Clip rectangle area to copy
748 * @state: Transform and conversion state
750 * This function copies parts of a framebuffer to display memory and converts the
751 * color format during the process. Destination and framebuffer formats must match. The
752 * parameters @dst, @dst_pitch and @src refer to arrays. Each array must have at
753 * least as many entries as there are planes in @fb's format. Each entry stores the
754 * value for the format's respective color plane at the same index.
756 * This function does not apply clipping on @dst (i.e. the destination is at the
759 * Drivers can use this function for RGB888 devices that don't natively
762 void drm_fb_xrgb8888_to_rgb888(struct iosys_map *dst, const unsigned int *dst_pitch,
763 const struct iosys_map *src, const struct drm_framebuffer *fb,
764 const struct drm_rect *clip, struct drm_format_conv_state *state)
766 static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = {
770 drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state,
771 drm_fb_xrgb8888_to_rgb888_line);
773 EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb888);
775 static void drm_fb_xrgb8888_to_bgr888_line(void *dbuf, const void *sbuf, unsigned int pixels)
777 drm_fb_xfrm_line_32to24(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_bgr888);
781 * drm_fb_xrgb8888_to_bgr888 - Convert XRGB8888 to BGR888 clip buffer
782 * @dst: Array of BGR888 destination buffers
783 * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines
784 * within @dst; can be NULL if scanlines are stored next to each other.
785 * @src: Array of XRGB8888 source buffers
786 * @fb: DRM framebuffer
787 * @clip: Clip rectangle area to copy
788 * @state: Transform and conversion state
790 * This function copies parts of a framebuffer to display memory and converts the
791 * color format during the process. Destination and framebuffer formats must match. The
792 * parameters @dst, @dst_pitch and @src refer to arrays. Each array must have at
793 * least as many entries as there are planes in @fb's format. Each entry stores the
794 * value for the format's respective color plane at the same index.
796 * This function does not apply clipping on @dst (i.e. the destination is at the
799 * Drivers can use this function for BGR888 devices that don't natively
802 void drm_fb_xrgb8888_to_bgr888(struct iosys_map *dst, const unsigned int *dst_pitch,
803 const struct iosys_map *src, const struct drm_framebuffer *fb,
804 const struct drm_rect *clip, struct drm_format_conv_state *state)
806 static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = {
810 drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state,
811 drm_fb_xrgb8888_to_bgr888_line);
813 EXPORT_SYMBOL(drm_fb_xrgb8888_to_bgr888);
815 static void drm_fb_xrgb8888_to_argb8888_line(void *dbuf, const void *sbuf, unsigned int pixels)
817 drm_fb_xfrm_line_32to32(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_argb8888);
821 * drm_fb_xrgb8888_to_argb8888 - Convert XRGB8888 to ARGB8888 clip buffer
822 * @dst: Array of ARGB8888 destination buffers
823 * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines
824 * within @dst; can be NULL if scanlines are stored next to each other.
825 * @src: Array of XRGB8888 source buffer
826 * @fb: DRM framebuffer
827 * @clip: Clip rectangle area to copy
828 * @state: Transform and conversion state
830 * This function copies parts of a framebuffer to display memory and converts the
831 * color format during the process. The parameters @dst, @dst_pitch and @src refer
832 * to arrays. Each array must have at least as many entries as there are planes in
833 * @fb's format. Each entry stores the value for the format's respective color plane
836 * This function does not apply clipping on @dst (i.e. the destination is at the
839 * Drivers can use this function for ARGB8888 devices that don't support XRGB8888
840 * natively. It sets an opaque alpha channel as part of the conversion.
842 void drm_fb_xrgb8888_to_argb8888(struct iosys_map *dst, const unsigned int *dst_pitch,
843 const struct iosys_map *src, const struct drm_framebuffer *fb,
844 const struct drm_rect *clip, struct drm_format_conv_state *state)
846 static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = {
850 drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state,
851 drm_fb_xrgb8888_to_argb8888_line);
853 EXPORT_SYMBOL(drm_fb_xrgb8888_to_argb8888);
855 static void drm_fb_xrgb8888_to_abgr8888_line(void *dbuf, const void *sbuf, unsigned int pixels)
857 drm_fb_xfrm_line_32to32(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_abgr8888);
860 static void drm_fb_xrgb8888_to_abgr8888(struct iosys_map *dst, const unsigned int *dst_pitch,
861 const struct iosys_map *src,
862 const struct drm_framebuffer *fb,
863 const struct drm_rect *clip,
864 struct drm_format_conv_state *state)
866 static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = {
870 drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state,
871 drm_fb_xrgb8888_to_abgr8888_line);
874 static void drm_fb_xrgb8888_to_xbgr8888_line(void *dbuf, const void *sbuf, unsigned int pixels)
876 drm_fb_xfrm_line_32to32(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_xbgr8888);
879 static void drm_fb_xrgb8888_to_xbgr8888(struct iosys_map *dst, const unsigned int *dst_pitch,
880 const struct iosys_map *src,
881 const struct drm_framebuffer *fb,
882 const struct drm_rect *clip,
883 struct drm_format_conv_state *state)
885 static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = {
889 drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state,
890 drm_fb_xrgb8888_to_xbgr8888_line);
893 static void drm_fb_xrgb8888_to_xrgb2101010_line(void *dbuf, const void *sbuf, unsigned int pixels)
895 drm_fb_xfrm_line_32to32(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_xrgb2101010);
899 * drm_fb_xrgb8888_to_xrgb2101010 - Convert XRGB8888 to XRGB2101010 clip buffer
900 * @dst: Array of XRGB2101010 destination buffers
901 * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines
902 * within @dst; can be NULL if scanlines are stored next to each other.
903 * @src: Array of XRGB8888 source buffers
904 * @fb: DRM framebuffer
905 * @clip: Clip rectangle area to copy
906 * @state: Transform and conversion state
908 * This function copies parts of a framebuffer to display memory and converts the
909 * color format during the process. Destination and framebuffer formats must match. The
910 * parameters @dst, @dst_pitch and @src refer to arrays. Each array must have at
911 * least as many entries as there are planes in @fb's format. Each entry stores the
912 * value for the format's respective color plane at the same index.
914 * This function does not apply clipping on @dst (i.e. the destination is at the
917 * Drivers can use this function for XRGB2101010 devices that don't support XRGB8888
920 void drm_fb_xrgb8888_to_xrgb2101010(struct iosys_map *dst, const unsigned int *dst_pitch,
921 const struct iosys_map *src, const struct drm_framebuffer *fb,
922 const struct drm_rect *clip,
923 struct drm_format_conv_state *state)
925 static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = {
929 drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state,
930 drm_fb_xrgb8888_to_xrgb2101010_line);
932 EXPORT_SYMBOL(drm_fb_xrgb8888_to_xrgb2101010);
934 static void drm_fb_xrgb8888_to_argb2101010_line(void *dbuf, const void *sbuf, unsigned int pixels)
936 drm_fb_xfrm_line_32to32(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_argb2101010);
940 * drm_fb_xrgb8888_to_argb2101010 - Convert XRGB8888 to ARGB2101010 clip buffer
941 * @dst: Array of ARGB2101010 destination buffers
942 * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines
943 * within @dst; can be NULL if scanlines are stored next to each other.
944 * @src: Array of XRGB8888 source buffers
945 * @fb: DRM framebuffer
946 * @clip: Clip rectangle area to copy
947 * @state: Transform and conversion state
949 * This function copies parts of a framebuffer to display memory and converts
950 * the color format during the process. The parameters @dst, @dst_pitch and
951 * @src refer to arrays. Each array must have at least as many entries as
952 * there are planes in @fb's format. Each entry stores the value for the
953 * format's respective color plane at the same index.
955 * This function does not apply clipping on @dst (i.e. the destination is at the
958 * Drivers can use this function for ARGB2101010 devices that don't support XRGB8888
961 void drm_fb_xrgb8888_to_argb2101010(struct iosys_map *dst, const unsigned int *dst_pitch,
962 const struct iosys_map *src, const struct drm_framebuffer *fb,
963 const struct drm_rect *clip,
964 struct drm_format_conv_state *state)
966 static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = {
970 drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state,
971 drm_fb_xrgb8888_to_argb2101010_line);
973 EXPORT_SYMBOL(drm_fb_xrgb8888_to_argb2101010);
975 static void drm_fb_xrgb8888_to_gray8_line(void *dbuf, const void *sbuf, unsigned int pixels)
977 drm_fb_xfrm_line_32to8(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_r8_bt601);
981 * drm_fb_xrgb8888_to_gray8 - Convert XRGB8888 to grayscale
982 * @dst: Array of 8-bit grayscale destination buffers
983 * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines
984 * within @dst; can be NULL if scanlines are stored next to each other.
985 * @src: Array of XRGB8888 source buffers
986 * @fb: DRM framebuffer
987 * @clip: Clip rectangle area to copy
988 * @state: Transform and conversion state
990 * This function copies parts of a framebuffer to display memory and converts the
991 * color format during the process. Destination and framebuffer formats must match. The
992 * parameters @dst, @dst_pitch and @src refer to arrays. Each array must have at
993 * least as many entries as there are planes in @fb's format. Each entry stores the
994 * value for the format's respective color plane at the same index.
996 * This function does not apply clipping on @dst (i.e. the destination is at the
999 * DRM doesn't have native monochrome or grayscale support. Drivers can use this
1000 * function for grayscale devices that don't support XRGB8888 natively.Such
1001 * drivers can announce the commonly supported XR24 format to userspace and use
1002 * this function to convert to the native format. Monochrome drivers will use the
1003 * most significant bit, where 1 means foreground color and 0 background color.
1004 * ITU BT.601 is being used for the RGB -> luma (brightness) conversion.
1006 void drm_fb_xrgb8888_to_gray8(struct iosys_map *dst, const unsigned int *dst_pitch,
1007 const struct iosys_map *src, const struct drm_framebuffer *fb,
1008 const struct drm_rect *clip, struct drm_format_conv_state *state)
1010 static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = {
1014 drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state,
1015 drm_fb_xrgb8888_to_gray8_line);
1017 EXPORT_SYMBOL(drm_fb_xrgb8888_to_gray8);
1019 static void drm_fb_argb8888_to_argb4444_line(void *dbuf, const void *sbuf, unsigned int pixels)
1021 drm_fb_xfrm_line_32to16(dbuf, sbuf, pixels, drm_pixel_argb8888_to_argb4444);
1025 * drm_fb_argb8888_to_argb4444 - Convert ARGB8888 to ARGB4444 clip buffer
1026 * @dst: Array of ARGB4444 destination buffers
1027 * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines
1028 * within @dst; can be NULL if scanlines are stored next to each other.
1029 * @src: Array of ARGB8888 source buffer
1030 * @fb: DRM framebuffer
1031 * @clip: Clip rectangle area to copy
1032 * @state: Transform and conversion state
1034 * This function copies parts of a framebuffer to display memory and converts
1035 * the color format during the process. The parameters @dst, @dst_pitch and
1036 * @src refer to arrays. Each array must have at least as many entries as
1037 * there are planes in @fb's format. Each entry stores the value for the
1038 * format's respective color plane at the same index.
1040 * This function does not apply clipping on @dst (i.e. the destination is at the
1043 * Drivers can use this function for ARGB4444 devices that don't support
1044 * ARGB8888 natively.
1046 void drm_fb_argb8888_to_argb4444(struct iosys_map *dst, const unsigned int *dst_pitch,
1047 const struct iosys_map *src, const struct drm_framebuffer *fb,
1048 const struct drm_rect *clip, struct drm_format_conv_state *state)
1050 static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = {
1054 drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state,
1055 drm_fb_argb8888_to_argb4444_line);
1057 EXPORT_SYMBOL(drm_fb_argb8888_to_argb4444);
1060 * drm_fb_blit - Copy parts of a framebuffer to display memory
1061 * @dst: Array of display-memory addresses to copy to
1062 * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines
1063 * within @dst; can be NULL if scanlines are stored next to each other.
1064 * @dst_format: FOURCC code of the display's color format
1065 * @src: The framebuffer memory to copy from
1066 * @fb: The framebuffer to copy from
1067 * @clip: Clip rectangle area to copy
1068 * @state: Transform and conversion state
1070 * This function copies parts of a framebuffer to display memory. If the
1071 * formats of the display and the framebuffer mismatch, the blit function
1072 * will attempt to convert between them during the process. The parameters @dst,
1073 * @dst_pitch and @src refer to arrays. Each array must have at least as many
1074 * entries as there are planes in @dst_format's format. Each entry stores the
1075 * value for the format's respective color plane at the same index.
1077 * This function does not apply clipping on @dst (i.e. the destination is at the
1082 * -EINVAL if the color-format conversion failed, or
1083 * a negative error code otherwise.
1085 int drm_fb_blit(struct iosys_map *dst, const unsigned int *dst_pitch, uint32_t dst_format,
1086 const struct iosys_map *src, const struct drm_framebuffer *fb,
1087 const struct drm_rect *clip, struct drm_format_conv_state *state)
1089 uint32_t fb_format = fb->format->format;
1091 if (fb_format == dst_format) {
1092 drm_fb_memcpy(dst, dst_pitch, src, fb, clip);
1094 } else if (fb_format == (dst_format | DRM_FORMAT_BIG_ENDIAN)) {
1095 drm_fb_swab(dst, dst_pitch, src, fb, clip, false, state);
1097 } else if (fb_format == (dst_format & ~DRM_FORMAT_BIG_ENDIAN)) {
1098 drm_fb_swab(dst, dst_pitch, src, fb, clip, false, state);
1100 } else if (fb_format == DRM_FORMAT_XRGB8888) {
1101 if (dst_format == DRM_FORMAT_RGB565) {
1102 drm_fb_xrgb8888_to_rgb565(dst, dst_pitch, src, fb, clip, state, false);
1104 } else if (dst_format == DRM_FORMAT_XRGB1555) {
1105 drm_fb_xrgb8888_to_xrgb1555(dst, dst_pitch, src, fb, clip, state);
1107 } else if (dst_format == DRM_FORMAT_ARGB1555) {
1108 drm_fb_xrgb8888_to_argb1555(dst, dst_pitch, src, fb, clip, state);
1110 } else if (dst_format == DRM_FORMAT_RGBA5551) {
1111 drm_fb_xrgb8888_to_rgba5551(dst, dst_pitch, src, fb, clip, state);
1113 } else if (dst_format == DRM_FORMAT_RGB888) {
1114 drm_fb_xrgb8888_to_rgb888(dst, dst_pitch, src, fb, clip, state);
1116 } else if (dst_format == DRM_FORMAT_BGR888) {
1117 drm_fb_xrgb8888_to_bgr888(dst, dst_pitch, src, fb, clip, state);
1119 } else if (dst_format == DRM_FORMAT_ARGB8888) {
1120 drm_fb_xrgb8888_to_argb8888(dst, dst_pitch, src, fb, clip, state);
1122 } else if (dst_format == DRM_FORMAT_XBGR8888) {
1123 drm_fb_xrgb8888_to_xbgr8888(dst, dst_pitch, src, fb, clip, state);
1125 } else if (dst_format == DRM_FORMAT_ABGR8888) {
1126 drm_fb_xrgb8888_to_abgr8888(dst, dst_pitch, src, fb, clip, state);
1128 } else if (dst_format == DRM_FORMAT_XRGB2101010) {
1129 drm_fb_xrgb8888_to_xrgb2101010(dst, dst_pitch, src, fb, clip, state);
1131 } else if (dst_format == DRM_FORMAT_ARGB2101010) {
1132 drm_fb_xrgb8888_to_argb2101010(dst, dst_pitch, src, fb, clip, state);
1134 } else if (dst_format == DRM_FORMAT_BGRX8888) {
1135 drm_fb_swab(dst, dst_pitch, src, fb, clip, false, state);
1140 drm_warn_once(fb->dev, "No conversion helper from %p4cc to %p4cc found.\n",
1141 &fb_format, &dst_format);
1145 EXPORT_SYMBOL(drm_fb_blit);
1147 static void drm_fb_gray8_to_mono_line(void *dbuf, const void *sbuf, unsigned int pixels)
1150 const u8 *sbuf8 = sbuf;
1153 unsigned int i, bits = min(pixels, 8U);
1156 for (i = 0; i < bits; i++, pixels--) {
1157 if (*sbuf8++ >= 128)
1165 * drm_fb_xrgb8888_to_mono - Convert XRGB8888 to monochrome
1166 * @dst: Array of monochrome destination buffers (0=black, 1=white)
1167 * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines
1168 * within @dst; can be NULL if scanlines are stored next to each other.
1169 * @src: Array of XRGB8888 source buffers
1170 * @fb: DRM framebuffer
1171 * @clip: Clip rectangle area to copy
1172 * @state: Transform and conversion state
1174 * This function copies parts of a framebuffer to display memory and converts the
1175 * color format during the process. Destination and framebuffer formats must match. The
1176 * parameters @dst, @dst_pitch and @src refer to arrays. Each array must have at
1177 * least as many entries as there are planes in @fb's format. Each entry stores the
1178 * value for the format's respective color plane at the same index.
1180 * This function does not apply clipping on @dst (i.e. the destination is at the
1181 * top-left corner). The first pixel (upper left corner of the clip rectangle) will
1182 * be converted and copied to the first bit (LSB) in the first byte of the monochrome
1183 * destination buffer. If the caller requires that the first pixel in a byte must
1184 * be located at an x-coordinate that is a multiple of 8, then the caller must take
1185 * care itself of supplying a suitable clip rectangle.
1187 * DRM doesn't have native monochrome support. Drivers can use this function for
1188 * monochrome devices that don't support XRGB8888 natively. Such drivers can
1189 * announce the commonly supported XR24 format to userspace and use this function
1190 * to convert to the native format.
1192 * This function uses drm_fb_xrgb8888_to_gray8() to convert to grayscale and
1193 * then the result is converted from grayscale to monochrome.
1195 void drm_fb_xrgb8888_to_mono(struct iosys_map *dst, const unsigned int *dst_pitch,
1196 const struct iosys_map *src, const struct drm_framebuffer *fb,
1197 const struct drm_rect *clip, struct drm_format_conv_state *state)
1199 static const unsigned int default_dst_pitch[DRM_FORMAT_MAX_PLANES] = {
1202 unsigned int linepixels = drm_rect_width(clip);
1203 unsigned int lines = drm_rect_height(clip);
1204 unsigned int cpp = fb->format->cpp[0];
1205 unsigned int len_src32 = linepixels * cpp;
1206 struct drm_device *dev = fb->dev;
1207 void *vaddr = src[0].vaddr;
1208 unsigned int dst_pitch_0;
1210 u8 *mono = dst[0].vaddr, *gray8;
1213 if (drm_WARN_ON(dev, fb->format->format != DRM_FORMAT_XRGB8888))
1217 dst_pitch = default_dst_pitch;
1218 dst_pitch_0 = dst_pitch[0];
1221 * The mono destination buffer contains 1 bit per pixel
1224 dst_pitch_0 = DIV_ROUND_UP(linepixels, 8);
1227 * The dma memory is write-combined so reads are uncached.
1228 * Speed up by fetching one line at a time.
1230 * Also, format conversion from XR24 to monochrome are done
1231 * line-by-line but are converted to 8-bit grayscale as an
1232 * intermediate step.
1234 * Allocate a buffer to be used for both copying from the cma
1235 * memory and to store the intermediate grayscale line pixels.
1237 src32 = drm_format_conv_state_reserve(state, len_src32 + linepixels, GFP_KERNEL);
1241 gray8 = (u8 *)src32 + len_src32;
1243 vaddr += clip_offset(clip, fb->pitches[0], cpp);
1244 for (y = 0; y < lines; y++) {
1245 src32 = memcpy(src32, vaddr, len_src32);
1246 drm_fb_xrgb8888_to_gray8_line(gray8, src32, linepixels);
1247 drm_fb_gray8_to_mono_line(mono, gray8, linepixels);
1248 vaddr += fb->pitches[0];
1249 mono += dst_pitch_0;
1252 EXPORT_SYMBOL(drm_fb_xrgb8888_to_mono);
1254 static uint32_t drm_fb_nonalpha_fourcc(uint32_t fourcc)
1256 /* only handle formats with depth != 0 and alpha channel */
1258 case DRM_FORMAT_ARGB1555:
1259 return DRM_FORMAT_XRGB1555;
1260 case DRM_FORMAT_ABGR1555:
1261 return DRM_FORMAT_XBGR1555;
1262 case DRM_FORMAT_RGBA5551:
1263 return DRM_FORMAT_RGBX5551;
1264 case DRM_FORMAT_BGRA5551:
1265 return DRM_FORMAT_BGRX5551;
1266 case DRM_FORMAT_ARGB8888:
1267 return DRM_FORMAT_XRGB8888;
1268 case DRM_FORMAT_ABGR8888:
1269 return DRM_FORMAT_XBGR8888;
1270 case DRM_FORMAT_RGBA8888:
1271 return DRM_FORMAT_RGBX8888;
1272 case DRM_FORMAT_BGRA8888:
1273 return DRM_FORMAT_BGRX8888;
1274 case DRM_FORMAT_ARGB2101010:
1275 return DRM_FORMAT_XRGB2101010;
1276 case DRM_FORMAT_ABGR2101010:
1277 return DRM_FORMAT_XBGR2101010;
1278 case DRM_FORMAT_RGBA1010102:
1279 return DRM_FORMAT_RGBX1010102;
1280 case DRM_FORMAT_BGRA1010102:
1281 return DRM_FORMAT_BGRX1010102;
1287 static bool is_listed_fourcc(const uint32_t *fourccs, size_t nfourccs, uint32_t fourcc)
1289 const uint32_t *fourccs_end = fourccs + nfourccs;
1291 while (fourccs < fourccs_end) {
1292 if (*fourccs == fourcc)
1300 * drm_fb_build_fourcc_list - Filters a list of supported color formats against
1301 * the device's native formats
1303 * @native_fourccs: 4CC codes of natively supported color formats
1304 * @native_nfourccs: The number of entries in @native_fourccs
1305 * @fourccs_out: Returns 4CC codes of supported color formats
1306 * @nfourccs_out: The number of available entries in @fourccs_out
1308 * This function create a list of supported color format from natively
1309 * supported formats and additional emulated formats.
1310 * At a minimum, most userspace programs expect at least support for
1311 * XRGB8888 on the primary plane. Devices that have to emulate the
1312 * format, and possibly others, can use drm_fb_build_fourcc_list() to
1313 * create a list of supported color formats. The returned list can
1314 * be handed over to drm_universal_plane_init() et al. Native formats
1315 * will go before emulated formats. Native formats with alpha channel
1316 * will be replaced by such without, as primary planes usually don't
1317 * support alpha. Other heuristics might be applied
1318 * to optimize the order. Formats near the beginning of the list are
1319 * usually preferred over formats near the end of the list.
1322 * The number of color-formats 4CC codes returned in @fourccs_out.
1324 size_t drm_fb_build_fourcc_list(struct drm_device *dev,
1325 const u32 *native_fourccs, size_t native_nfourccs,
1326 u32 *fourccs_out, size_t nfourccs_out)
1329 * XRGB8888 is the default fallback format for most of userspace
1330 * and it's currently the only format that should be emulated for
1331 * the primary plane. Only if there's ever another default fallback,
1332 * it should be added here.
1334 static const uint32_t extra_fourccs[] = {
1335 DRM_FORMAT_XRGB8888,
1337 static const size_t extra_nfourccs = ARRAY_SIZE(extra_fourccs);
1339 u32 *fourccs = fourccs_out;
1340 const u32 *fourccs_end = fourccs_out + nfourccs_out;
1344 * The device's native formats go first.
1347 for (i = 0; i < native_nfourccs; ++i) {
1349 * Several DTs, boot loaders and firmware report native
1350 * alpha formats that are non-alpha formats instead. So
1351 * replace alpha formats by non-alpha formats.
1353 u32 fourcc = drm_fb_nonalpha_fourcc(native_fourccs[i]);
1355 if (is_listed_fourcc(fourccs_out, fourccs - fourccs_out, fourcc)) {
1356 continue; /* skip duplicate entries */
1357 } else if (fourccs == fourccs_end) {
1358 drm_warn(dev, "Ignoring native format %p4cc\n", &fourcc);
1359 continue; /* end of available output buffer */
1362 drm_dbg_kms(dev, "adding native format %p4cc\n", &fourcc);
1369 * The extra formats, emulated by the driver, go second.
1372 for (i = 0; (i < extra_nfourccs) && (fourccs < fourccs_end); ++i) {
1373 u32 fourcc = extra_fourccs[i];
1375 if (is_listed_fourcc(fourccs_out, fourccs - fourccs_out, fourcc)) {
1376 continue; /* skip duplicate and native entries */
1377 } else if (fourccs == fourccs_end) {
1378 drm_warn(dev, "Ignoring emulated format %p4cc\n", &fourcc);
1379 continue; /* end of available output buffer */
1382 drm_dbg_kms(dev, "adding emulated format %p4cc\n", &fourcc);
1388 return fourccs - fourccs_out;
1390 EXPORT_SYMBOL(drm_fb_build_fourcc_list);