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