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