Merge tag 'pci-v6.16-fixes-3' of git://git.kernel.org/pub/scm/linux/kernel/git/pci/pci
[linux-block.git] / drivers / gpu / drm / drm_format_helper.c
CommitLineData
0bd65bd8 1// SPDX-License-Identifier: GPL-2.0 or MIT
7415287e
GH
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
71bf5587
TZ
11#include <linux/io.h>
12#include <linux/iosys-map.h>
7415287e
GH
13#include <linux/module.h>
14#include <linux/slab.h>
15
bcf8b616 16#include <drm/drm_device.h>
7415287e
GH
17#include <drm/drm_format_helper.h>
18#include <drm/drm_framebuffer.h>
19#include <drm/drm_fourcc.h>
bcf8b616 20#include <drm/drm_print.h>
7415287e
GH
21#include <drm/drm_rect.h>
22
d55d0b06
TZ
23#include "drm_format_internal.h"
24
38b2d9d3
TZ
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 */
32void 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}
38EXPORT_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 */
48void 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}
59EXPORT_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 */
75void *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
92out:
93 return state->tmp.mem;
94}
95EXPORT_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 */
105void 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}
114EXPORT_SYMBOL(drm_format_conv_state_release);
115
452290f3 116static unsigned int clip_offset(const struct drm_rect *clip, unsigned int pitch, unsigned int cpp)
26f024f5 117{
bf4f6d16 118 return clip->y1 * pitch + clip->x1 * cpp;
26f024f5
GH
119}
120
452290f3
TZ
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 */
130unsigned 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}
135EXPORT_SYMBOL(drm_fb_clip_offset);
136
f241b064
TZ
137/* TODO: Make this function work with multi-plane formats. */
138static 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,
38b2d9d3 141 struct drm_format_conv_state *state,
f241b064 142 void (*xfrm_line)(void *dbuf, const void *sbuf, unsigned int npixels))
cce6bedb
TZ
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 /*
6bcfe8ea 152 * Some source buffers, such as DMA memory, use write-combine
cce6bedb
TZ
153 * caching, so reads are uncached. Speed up access by fetching
154 * one line at a time.
155 */
156 if (!vaddr_cached_hint) {
38b2d9d3 157 stmp = drm_format_conv_state_reserve(state, sbuf_len, GFP_KERNEL);
cce6bedb
TZ
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
cce6bedb
TZ
176 return 0;
177}
178
f241b064
TZ
179/* TODO: Make this function work with multi-plane formats. */
180static 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,
38b2d9d3 183 struct drm_format_conv_state *state,
f241b064 184 void (*xfrm_line)(void *dbuf, const void *sbuf, unsigned int npixels))
cce6bedb
TZ
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) {
38b2d9d3 197 dbuf = drm_format_conv_state_reserve(state, dbuf_len, GFP_KERNEL);
cce6bedb 198 } else {
38b2d9d3 199 dbuf = drm_format_conv_state_reserve(state, stmp_off + sbuf_len, GFP_KERNEL);
cce6bedb
TZ
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
cce6bedb
TZ
220 return 0;
221}
222
f241b064
TZ
223/* TODO: Make this function work with multi-plane formats. */
224static int drm_fb_xfrm(struct iosys_map *dst,
225 const unsigned int *dst_pitch, const u8 *dst_pixsize,
504a51d7 226 const struct iosys_map *src, const struct drm_framebuffer *fb,
f241b064 227 const struct drm_rect *clip, bool vaddr_cached_hint,
4cd24d4b 228 struct drm_format_conv_state *state,
f241b064
TZ
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
504a51d7 238 /* TODO: handle src in I/O memory here */
f241b064 239 if (dst[0].is_iomem)
4cd24d4b
TZ
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);
f241b064 243 else
4cd24d4b
TZ
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);
f241b064
TZ
247}
248
58523a25
TZ
249#define ALIGN_DOWN_PIXELS(end, n, a) \
250 ((end) - ((n) & ((a) - 1)))
251
a376dcf4
TZ
252static __always_inline void drm_fb_xfrm_line_32to8(void *dbuf, const void *sbuf,
253 unsigned int pixels,
254 u32 (*xfrm_pixel)(u32))
255{
65931bbc
TZ
256 __le32 *dbuf32 = dbuf;
257 u8 *dbuf8;
a376dcf4
TZ
258 const __le32 *sbuf32 = sbuf;
259 const __le32 *send32 = sbuf32 + pixels;
260
65931bbc
TZ
261 /* write 4 pixels at once */
262 while (sbuf32 < ALIGN_DOWN_PIXELS(send32, pixels, 4)) {
263 u32 pix[4] = {
5024aa7a
MA
264 le32_to_cpup(sbuf32),
265 le32_to_cpup(sbuf32 + 1),
266 le32_to_cpup(sbuf32 + 2),
267 le32_to_cpup(sbuf32 + 3),
65931bbc
TZ
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);
5024aa7a 275 sbuf32 += ARRAY_SIZE(pix);
65931bbc
TZ
276 }
277
278 /* write trailing pixels */
279 dbuf8 = (u8 __force *)dbuf32;
a376dcf4
TZ
280 while (sbuf32 < send32)
281 *dbuf8++ = xfrm_pixel(le32_to_cpup(sbuf32++));
282}
283
b39e5ba0
TZ
284static __always_inline void drm_fb_xfrm_line_32to16(void *dbuf, const void *sbuf,
285 unsigned int pixels,
286 u32 (*xfrm_pixel)(u32))
287{
3f31a017
TZ
288 __le64 *dbuf64 = dbuf;
289 __le32 *dbuf32;
290 __le16 *dbuf16;
b39e5ba0
TZ
291 const __le32 *sbuf32 = sbuf;
292 const __le32 *send32 = sbuf32 + pixels;
293
3f31a017
TZ
294#if defined(CONFIG_64BIT)
295 /* write 4 pixels at once */
296 while (sbuf32 < ALIGN_DOWN_PIXELS(send32, pixels, 4)) {
297 u32 pix[4] = {
5024aa7a
MA
298 le32_to_cpup(sbuf32),
299 le32_to_cpup(sbuf32 + 1),
300 le32_to_cpup(sbuf32 + 2),
301 le32_to_cpup(sbuf32 + 3),
3f31a017
TZ
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);
5024aa7a 309 sbuf32 += ARRAY_SIZE(pix);
3f31a017
TZ
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] = {
5024aa7a
MA
317 le32_to_cpup(sbuf32),
318 le32_to_cpup(sbuf32 + 1),
3f31a017
TZ
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);
5024aa7a 324 sbuf32 += ARRAY_SIZE(pix);
3f31a017
TZ
325 }
326
327 /* write trailing pixel */
328 dbuf16 = (__le16 __force *)dbuf32;
b39e5ba0
TZ
329 while (sbuf32 < send32)
330 *dbuf16++ = cpu_to_le16(xfrm_pixel(le32_to_cpup(sbuf32++)));
331}
332
f46bf572
TZ
333static __always_inline void drm_fb_xfrm_line_32to24(void *dbuf, const void *sbuf,
334 unsigned int pixels,
335 u32 (*xfrm_pixel)(u32))
336{
58523a25
TZ
337 __le32 *dbuf32 = dbuf;
338 u8 *dbuf8;
f46bf572
TZ
339 const __le32 *sbuf32 = sbuf;
340 const __le32 *send32 = sbuf32 + pixels;
341
58523a25
TZ
342 /* write pixels in chunks of 4 */
343 while (sbuf32 < ALIGN_DOWN_PIXELS(send32, pixels, 4)) {
344 u32 val24[4] = {
5024aa7a
MA
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)),
58523a25
TZ
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]);
5024aa7a 369 sbuf32 += ARRAY_SIZE(val24);
58523a25
TZ
370 }
371
372 /* write trailing pixel */
373 dbuf8 = (u8 __force *)dbuf32;
f46bf572
TZ
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
d55d0b06
TZ
383static __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
7415287e
GH
395/**
396 * drm_fb_memcpy - Copy clip buffer
edbe262a
TZ
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.
504a51d7 400 * @src: Array of source buffers
7415287e
GH
401 * @fb: DRM framebuffer
402 * @clip: Clip rectangle area to copy
26f024f5 403 *
edbe262a
TZ
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,
504a51d7 406 * @dst_pitch and @src refer to arrays. Each array must have at least as many entries
edbe262a
TZ
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.
26f024f5 409 *
edbe262a
TZ
410 * This function does not apply clipping on @dst (i.e. the destination is at the
411 * top-left corner).
26f024f5 412 */
edbe262a 413void drm_fb_memcpy(struct iosys_map *dst, const unsigned int *dst_pitch,
504a51d7 414 const struct iosys_map *src, const struct drm_framebuffer *fb,
edbe262a 415 const struct drm_rect *clip)
26f024f5 416{
edbe262a
TZ
417 static const unsigned int default_dst_pitch[DRM_FORMAT_MAX_PLANES] = {
418 0, 0, 0, 0
419 };
26f024f5 420
edbe262a
TZ
421 const struct drm_format_info *format = fb->format;
422 unsigned int i, y, lines = drm_rect_height(clip);
27bd66dd 423
edbe262a
TZ
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];
504a51d7 433 struct iosys_map src_i = src[i];
edbe262a
TZ
434
435 if (!dst_pitch_i)
436 dst_pitch_i = len_i;
437
504a51d7 438 iosys_map_incr(&src_i, clip_offset(clip, fb->pitches[i], cpp_i));
edbe262a 439 for (y = 0; y < lines; y++) {
504a51d7
TZ
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]);
edbe262a
TZ
443 iosys_map_incr(&dst_i, dst_pitch_i);
444 }
bf4f6d16 445 }
26f024f5 446}
edbe262a 447EXPORT_SYMBOL(drm_fb_memcpy);
26f024f5 448
41fd6f0a
TZ
449static 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
459static 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
7415287e 469/**
bd34cea2 470 * drm_fb_swab - Swap bytes into clip buffer
ce582859
TZ
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.
504a51d7 474 * @src: Array of source buffers
7415287e
GH
475 * @fb: DRM framebuffer
476 * @clip: Clip rectangle area to copy
bd34cea2 477 * @cached: Source buffer is mapped cached (eg. not write-combined)
4cd24d4b 478 * @state: Transform and conversion state
bd34cea2 479 *
ce582859
TZ
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
504a51d7 482 * parameters @dst, @dst_pitch and @src refer to arrays. Each array must have at
ce582859
TZ
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.
bd34cea2 487 *
ce582859
TZ
488 * This function does not apply clipping on @dst (i.e. the destination is at the
489 * top-left corner).
7415287e 490 */
ce582859 491void drm_fb_swab(struct iosys_map *dst, const unsigned int *dst_pitch,
504a51d7 492 const struct iosys_map *src, const struct drm_framebuffer *fb,
4cd24d4b
TZ
493 const struct drm_rect *clip, bool cached,
494 struct drm_format_conv_state *state)
7415287e 495{
ce582859
TZ
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);
bd34cea2 499
cce6bedb
TZ
500 switch (cpp) {
501 case 4:
ce582859 502 swab_line = drm_fb_swab32_line;
cce6bedb
TZ
503 break;
504 case 2:
ce582859 505 swab_line = drm_fb_swab16_line;
cce6bedb
TZ
506 break;
507 default:
508 drm_warn_once(fb->dev, "Format %p4cc has unsupported pixel size.\n",
ce582859 509 &format->format);
ce582859 510 return;
f241b064 511 }
ce582859 512
4cd24d4b 513 drm_fb_xfrm(dst, dst_pitch, &cpp, src, fb, clip, cached, state, swab_line);
7415287e 514}
bd34cea2 515EXPORT_SYMBOL(drm_fb_swab);
7415287e 516
cce6bedb 517static void drm_fb_xrgb8888_to_rgb332_line(void *dbuf, const void *sbuf, unsigned int pixels)
cee0b7cb 518{
a376dcf4 519 drm_fb_xfrm_line_32to8(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_rgb332);
cee0b7cb
NT
520}
521
522/**
523 * drm_fb_xrgb8888_to_rgb332 - Convert XRGB8888 to RGB332 clip buffer
e13140a0
TZ
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.
504a51d7 527 * @src: Array of XRGB8888 source buffers
cee0b7cb
NT
528 * @fb: DRM framebuffer
529 * @clip: Clip rectangle area to copy
4cd24d4b 530 * @state: Transform and conversion state
cee0b7cb 531 *
e13140a0
TZ
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
504a51d7 534 * parameters @dst, @dst_pitch and @src refer to arrays. Each array must have at
e13140a0
TZ
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.
cee0b7cb 542 */
e13140a0 543void drm_fb_xrgb8888_to_rgb332(struct iosys_map *dst, const unsigned int *dst_pitch,
504a51d7 544 const struct iosys_map *src, const struct drm_framebuffer *fb,
4cd24d4b 545 const struct drm_rect *clip, struct drm_format_conv_state *state)
cee0b7cb 546{
f241b064
TZ
547 static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = {
548 1,
e13140a0
TZ
549 };
550
4cd24d4b 551 drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state,
f241b064 552 drm_fb_xrgb8888_to_rgb332_line);
cee0b7cb
NT
553}
554EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb332);
555
a6fdb669 556static void drm_fb_xrgb8888_to_rgb565_line(void *dbuf, const void *sbuf, unsigned int pixels)
7415287e 557{
b39e5ba0
TZ
558 drm_fb_xfrm_line_32to16(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_rgb565);
559}
d653bd39 560
b39e5ba0
TZ
561static __always_inline u32 drm_xrgb8888_to_rgb565_swab(u32 pix)
562{
563 return swab16(drm_pixel_xrgb8888_to_rgb565(pix));
69add027
TZ
564}
565
f21d62c9 566/* TODO: implement this helper as conversion to RGB565|BIG_ENDIAN */
a6fdb669 567static void drm_fb_xrgb8888_to_rgb565_swab_line(void *dbuf, const void *sbuf,
69add027
TZ
568 unsigned int pixels)
569{
b39e5ba0 570 drm_fb_xfrm_line_32to16(dbuf, sbuf, pixels, drm_xrgb8888_to_rgb565_swab);
bcc44420
GH
571}
572
573/**
574 * drm_fb_xrgb8888_to_rgb565 - Convert XRGB8888 to RGB565 clip buffer
ab298c29
TZ
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.
504a51d7 578 * @src: Array of XRGB8888 source buffer
bcc44420
GH
579 * @fb: DRM framebuffer
580 * @clip: Clip rectangle area to copy
4cd24d4b 581 * @state: Transform and conversion state
d653bd39 582 * @swab: Swap bytes
bcc44420 583 *
ab298c29
TZ
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
504a51d7 586 * parameters @dst, @dst_pitch and @src refer to arrays. Each array must have at
ab298c29
TZ
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.
bcc44420 594 */
ab298c29 595void drm_fb_xrgb8888_to_rgb565(struct iosys_map *dst, const unsigned int *dst_pitch,
504a51d7 596 const struct iosys_map *src, const struct drm_framebuffer *fb,
4cd24d4b
TZ
597 const struct drm_rect *clip, struct drm_format_conv_state *state,
598 bool swab)
bcc44420 599{
f241b064
TZ
600 static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = {
601 2,
ab298c29 602 };
f241b064 603
ab298c29
TZ
604 void (*xfrm_line)(void *dbuf, const void *sbuf, unsigned int npixels);
605
cce6bedb 606 if (swab)
ab298c29 607 xfrm_line = drm_fb_xrgb8888_to_rgb565_swab_line;
cce6bedb 608 else
ab298c29 609 xfrm_line = drm_fb_xrgb8888_to_rgb565_line;
7415287e 610
4cd24d4b 611 drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state, xfrm_line);
bcc44420 612}
ab298c29 613EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb565);
bcc44420 614
10cd592e
TZ
615static void drm_fb_xrgb8888_to_xrgb1555_line(void *dbuf, const void *sbuf, unsigned int pixels)
616{
b39e5ba0 617 drm_fb_xfrm_line_32to16(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_xrgb1555);
10cd592e
TZ
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
4cd24d4b 628 * @state: Transform and conversion state
10cd592e
TZ
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 */
642void 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,
4cd24d4b 644 const struct drm_rect *clip, struct drm_format_conv_state *state)
10cd592e
TZ
645{
646 static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = {
647 2,
648 };
649
4cd24d4b 650 drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state,
10cd592e
TZ
651 drm_fb_xrgb8888_to_xrgb1555_line);
652}
653EXPORT_SYMBOL(drm_fb_xrgb8888_to_xrgb1555);
654
655static void drm_fb_xrgb8888_to_argb1555_line(void *dbuf, const void *sbuf, unsigned int pixels)
656{
b39e5ba0 657 drm_fb_xfrm_line_32to16(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_argb1555);
10cd592e
TZ
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
4cd24d4b 668 * @state: Transform and conversion state
10cd592e
TZ
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 */
682void 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,
4cd24d4b 684 const struct drm_rect *clip, struct drm_format_conv_state *state)
10cd592e
TZ
685{
686 static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = {
687 2,
688 };
689
4cd24d4b 690 drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state,
10cd592e
TZ
691 drm_fb_xrgb8888_to_argb1555_line);
692}
693EXPORT_SYMBOL(drm_fb_xrgb8888_to_argb1555);
694
695static void drm_fb_xrgb8888_to_rgba5551_line(void *dbuf, const void *sbuf, unsigned int pixels)
696{
b39e5ba0 697 drm_fb_xfrm_line_32to16(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_rgba5551);
10cd592e
TZ
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
4cd24d4b 708 * @state: Transform and conversion state
10cd592e
TZ
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 */
722void 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,
4cd24d4b 724 const struct drm_rect *clip, struct drm_format_conv_state *state)
10cd592e
TZ
725{
726 static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = {
727 2,
728 };
729
4cd24d4b 730 drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state,
10cd592e
TZ
731 drm_fb_xrgb8888_to_rgba5551_line);
732}
733EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgba5551);
734
a6fdb669 735static void drm_fb_xrgb8888_to_rgb888_line(void *dbuf, const void *sbuf, unsigned int pixels)
ec3de7a4 736{
f46bf572 737 drm_fb_xfrm_line_32to24(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_rgb888);
ec3de7a4
GH
738}
739
bcf80d6e
NT
740/**
741 * drm_fb_xrgb8888_to_rgb888 - Convert XRGB8888 to RGB888 clip buffer
c4863ce0
TZ
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.
504a51d7 745 * @src: Array of XRGB8888 source buffers
bcf80d6e
NT
746 * @fb: DRM framebuffer
747 * @clip: Clip rectangle area to copy
4cd24d4b 748 * @state: Transform and conversion state
bcf80d6e 749 *
c4863ce0
TZ
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
504a51d7 752 * parameters @dst, @dst_pitch and @src refer to arrays. Each array must have at
c4863ce0
TZ
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).
ec3de7a4
GH
758 *
759 * Drivers can use this function for RGB888 devices that don't natively
760 * support XRGB8888.
ec3de7a4 761 */
c4863ce0 762void drm_fb_xrgb8888_to_rgb888(struct iosys_map *dst, const unsigned int *dst_pitch,
504a51d7 763 const struct iosys_map *src, const struct drm_framebuffer *fb,
4cd24d4b 764 const struct drm_rect *clip, struct drm_format_conv_state *state)
ec3de7a4 765{
f241b064
TZ
766 static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = {
767 3,
c4863ce0
TZ
768 };
769
4cd24d4b 770 drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state,
f241b064 771 drm_fb_xrgb8888_to_rgb888_line);
ec3de7a4 772}
c4863ce0 773EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb888);
ec3de7a4 774
c9043706
KK
775static void drm_fb_xrgb8888_to_bgr888_line(void *dbuf, const void *sbuf, unsigned int pixels)
776{
f46bf572 777 drm_fb_xfrm_line_32to24(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_bgr888);
c9043706
KK
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 */
802void 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}
813EXPORT_SYMBOL(drm_fb_xrgb8888_to_bgr888);
814
175073d6
TZ
815static void drm_fb_xrgb8888_to_argb8888_line(void *dbuf, const void *sbuf, unsigned int pixels)
816{
d55d0b06 817 drm_fb_xfrm_line_32to32(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_argb8888);
175073d6
TZ
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
4cd24d4b 828 * @state: Transform and conversion state
175073d6
TZ
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 */
842void 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,
4cd24d4b 844 const struct drm_rect *clip, struct drm_format_conv_state *state)
175073d6
TZ
845{
846 static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = {
847 4,
848 };
849
4cd24d4b 850 drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state,
175073d6
TZ
851 drm_fb_xrgb8888_to_argb8888_line);
852}
853EXPORT_SYMBOL(drm_fb_xrgb8888_to_argb8888);
854
9abecb1d
TR
855static void drm_fb_xrgb8888_to_abgr8888_line(void *dbuf, const void *sbuf, unsigned int pixels)
856{
d55d0b06 857 drm_fb_xfrm_line_32to32(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_abgr8888);
9abecb1d
TR
858}
859
860static 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,
4cd24d4b
TZ
863 const struct drm_rect *clip,
864 struct drm_format_conv_state *state)
9abecb1d
TR
865{
866 static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = {
867 4,
868 };
869
4cd24d4b 870 drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state,
9abecb1d
TR
871 drm_fb_xrgb8888_to_abgr8888_line);
872}
873
874static void drm_fb_xrgb8888_to_xbgr8888_line(void *dbuf, const void *sbuf, unsigned int pixels)
875{
d55d0b06 876 drm_fb_xfrm_line_32to32(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_xbgr8888);
9abecb1d
TR
877}
878
879static 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,
4cd24d4b
TZ
882 const struct drm_rect *clip,
883 struct drm_format_conv_state *state)
9abecb1d
TR
884{
885 static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = {
886 4,
887 };
888
4cd24d4b 889 drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state,
9abecb1d
TR
890 drm_fb_xrgb8888_to_xbgr8888_line);
891}
892
a6fdb669 893static void drm_fb_xrgb8888_to_xrgb2101010_line(void *dbuf, const void *sbuf, unsigned int pixels)
877691b9 894{
d55d0b06 895 drm_fb_xfrm_line_32to32(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_xrgb2101010);
877691b9
HM
896}
897
898/**
ce73f456
TZ
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.
504a51d7 903 * @src: Array of XRGB8888 source buffers
877691b9
HM
904 * @fb: DRM framebuffer
905 * @clip: Clip rectangle area to copy
4cd24d4b 906 * @state: Transform and conversion state
877691b9 907 *
ce73f456
TZ
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
504a51d7 910 * parameters @dst, @dst_pitch and @src refer to arrays. Each array must have at
ce73f456
TZ
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.
877691b9 919 */
ce73f456 920void drm_fb_xrgb8888_to_xrgb2101010(struct iosys_map *dst, const unsigned int *dst_pitch,
504a51d7 921 const struct iosys_map *src, const struct drm_framebuffer *fb,
4cd24d4b
TZ
922 const struct drm_rect *clip,
923 struct drm_format_conv_state *state)
877691b9 924{
f241b064
TZ
925 static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = {
926 4,
ce73f456
TZ
927 };
928
4cd24d4b 929 drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state,
f241b064 930 drm_fb_xrgb8888_to_xrgb2101010_line);
877691b9 931}
45311431 932EXPORT_SYMBOL(drm_fb_xrgb8888_to_xrgb2101010);
877691b9 933
56119bfb
TZ
934static void drm_fb_xrgb8888_to_argb2101010_line(void *dbuf, const void *sbuf, unsigned int pixels)
935{
d55d0b06 936 drm_fb_xfrm_line_32to32(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_argb2101010);
56119bfb
TZ
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
4cd24d4b 947 * @state: Transform and conversion state
56119bfb
TZ
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 */
961void 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,
4cd24d4b
TZ
963 const struct drm_rect *clip,
964 struct drm_format_conv_state *state)
56119bfb
TZ
965{
966 static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = {
967 4,
968 };
969
4cd24d4b 970 drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state,
56119bfb
TZ
971 drm_fb_xrgb8888_to_argb2101010_line);
972}
973EXPORT_SYMBOL(drm_fb_xrgb8888_to_argb2101010);
974
a6fdb669 975static void drm_fb_xrgb8888_to_gray8_line(void *dbuf, const void *sbuf, unsigned int pixels)
4a564e59 976{
a376dcf4 977 drm_fb_xfrm_line_32to8(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_r8_bt601);
4a564e59
JMC
978}
979
7415287e
GH
980/**
981 * drm_fb_xrgb8888_to_gray8 - Convert XRGB8888 to grayscale
7bef6449
TZ
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.
504a51d7 985 * @src: Array of XRGB8888 source buffers
7415287e
GH
986 * @fb: DRM framebuffer
987 * @clip: Clip rectangle area to copy
4cd24d4b 988 * @state: Transform and conversion state
7415287e 989 *
7bef6449
TZ
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
504a51d7 992 * parameters @dst, @dst_pitch and @src refer to arrays. Each array must have at
7bef6449
TZ
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.
7415287e 995 *
7bef6449
TZ
996 * This function does not apply clipping on @dst (i.e. the destination is at the
997 * top-left corner).
7415287e 998 *
7bef6449
TZ
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.
7415287e 1005 */
7bef6449 1006void drm_fb_xrgb8888_to_gray8(struct iosys_map *dst, const unsigned int *dst_pitch,
504a51d7 1007 const struct iosys_map *src, const struct drm_framebuffer *fb,
4cd24d4b 1008 const struct drm_rect *clip, struct drm_format_conv_state *state)
7415287e 1009{
f241b064
TZ
1010 static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = {
1011 1,
7bef6449
TZ
1012 };
1013
4cd24d4b 1014 drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state,
f241b064 1015 drm_fb_xrgb8888_to_gray8_line);
7415287e
GH
1016}
1017EXPORT_SYMBOL(drm_fb_xrgb8888_to_gray8);
1018
966a0d49
TZ
1019static void drm_fb_argb8888_to_argb4444_line(void *dbuf, const void *sbuf, unsigned int pixels)
1020{
b39e5ba0 1021 drm_fb_xfrm_line_32to16(dbuf, sbuf, pixels, drm_pixel_argb8888_to_argb4444);
966a0d49
TZ
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 */
1046void 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}
1057EXPORT_SYMBOL(drm_fb_argb8888_to_argb4444);
1058
900d3e4a 1059/**
71bf5587
TZ
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.
900d3e4a 1064 * @dst_format: FOURCC code of the display's color format
504a51d7 1065 * @src: The framebuffer memory to copy from
900d3e4a
TZ
1066 * @fb: The framebuffer to copy from
1067 * @clip: Clip rectangle area to copy
4cd24d4b 1068 * @state: Transform and conversion state
900d3e4a
TZ
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
71bf5587 1072 * will attempt to convert between them during the process. The parameters @dst,
504a51d7 1073 * @dst_pitch and @src refer to arrays. Each array must have at least as many
71bf5587
TZ
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).
900d3e4a 1079 *
900d3e4a
TZ
1080 * Returns:
1081 * 0 on success, or
1082 * -EINVAL if the color-format conversion failed, or
1083 * a negative error code otherwise.
1084 */
71bf5587 1085int drm_fb_blit(struct iosys_map *dst, const unsigned int *dst_pitch, uint32_t dst_format,
504a51d7 1086 const struct iosys_map *src, const struct drm_framebuffer *fb,
4cd24d4b 1087 const struct drm_rect *clip, struct drm_format_conv_state *state)
900d3e4a
TZ
1088{
1089 uint32_t fb_format = fb->format->format;
1090
f238ac30 1091 if (fb_format == dst_format) {
504a51d7 1092 drm_fb_memcpy(dst, dst_pitch, src, fb, clip);
900d3e4a 1093 return 0;
f238ac30 1094 } else if (fb_format == (dst_format | DRM_FORMAT_BIG_ENDIAN)) {
4cd24d4b 1095 drm_fb_swab(dst, dst_pitch, src, fb, clip, false, state);
f238ac30
TZ
1096 return 0;
1097 } else if (fb_format == (dst_format & ~DRM_FORMAT_BIG_ENDIAN)) {
4cd24d4b 1098 drm_fb_swab(dst, dst_pitch, src, fb, clip, false, state);
f238ac30
TZ
1099 return 0;
1100 } else if (fb_format == DRM_FORMAT_XRGB8888) {
1101 if (dst_format == DRM_FORMAT_RGB565) {
4cd24d4b 1102 drm_fb_xrgb8888_to_rgb565(dst, dst_pitch, src, fb, clip, state, false);
900d3e4a 1103 return 0;
10cd592e 1104 } else if (dst_format == DRM_FORMAT_XRGB1555) {
4cd24d4b 1105 drm_fb_xrgb8888_to_xrgb1555(dst, dst_pitch, src, fb, clip, state);
10cd592e
TZ
1106 return 0;
1107 } else if (dst_format == DRM_FORMAT_ARGB1555) {
4cd24d4b 1108 drm_fb_xrgb8888_to_argb1555(dst, dst_pitch, src, fb, clip, state);
10cd592e
TZ
1109 return 0;
1110 } else if (dst_format == DRM_FORMAT_RGBA5551) {
4cd24d4b 1111 drm_fb_xrgb8888_to_rgba5551(dst, dst_pitch, src, fb, clip, state);
10cd592e 1112 return 0;
f238ac30 1113 } else if (dst_format == DRM_FORMAT_RGB888) {
4cd24d4b 1114 drm_fb_xrgb8888_to_rgb888(dst, dst_pitch, src, fb, clip, state);
900d3e4a 1115 return 0;
c9043706
KK
1116 } else if (dst_format == DRM_FORMAT_BGR888) {
1117 drm_fb_xrgb8888_to_bgr888(dst, dst_pitch, src, fb, clip, state);
1118 return 0;
175073d6 1119 } else if (dst_format == DRM_FORMAT_ARGB8888) {
4cd24d4b 1120 drm_fb_xrgb8888_to_argb8888(dst, dst_pitch, src, fb, clip, state);
175073d6 1121 return 0;
9abecb1d 1122 } else if (dst_format == DRM_FORMAT_XBGR8888) {
4cd24d4b 1123 drm_fb_xrgb8888_to_xbgr8888(dst, dst_pitch, src, fb, clip, state);
9abecb1d
TR
1124 return 0;
1125 } else if (dst_format == DRM_FORMAT_ABGR8888) {
4cd24d4b 1126 drm_fb_xrgb8888_to_abgr8888(dst, dst_pitch, src, fb, clip, state);
9abecb1d 1127 return 0;
f238ac30 1128 } else if (dst_format == DRM_FORMAT_XRGB2101010) {
4cd24d4b 1129 drm_fb_xrgb8888_to_xrgb2101010(dst, dst_pitch, src, fb, clip, state);
26c30f22 1130 return 0;
56119bfb 1131 } else if (dst_format == DRM_FORMAT_ARGB2101010) {
4cd24d4b 1132 drm_fb_xrgb8888_to_argb2101010(dst, dst_pitch, src, fb, clip, state);
56119bfb 1133 return 0;
f238ac30 1134 } else if (dst_format == DRM_FORMAT_BGRX8888) {
4cd24d4b 1135 drm_fb_swab(dst, dst_pitch, src, fb, clip, false, state);
e08a99d0 1136 return 0;
26c30f22 1137 }
900d3e4a
TZ
1138 }
1139
7e553e2a
TZ
1140 drm_warn_once(fb->dev, "No conversion helper from %p4cc to %p4cc found.\n",
1141 &fb_format, &dst_format);
1142
900d3e4a
TZ
1143 return -EINVAL;
1144}
71bf5587 1145EXPORT_SYMBOL(drm_fb_blit);
bcf8b616 1146
a6fdb669 1147static void drm_fb_gray8_to_mono_line(void *dbuf, const void *sbuf, unsigned int pixels)
7392f245 1148{
a6fdb669
TZ
1149 u8 *dbuf8 = dbuf;
1150 const u8 *sbuf8 = sbuf;
1151
7392f245
GU
1152 while (pixels) {
1153 unsigned int i, bits = min(pixels, 8U);
1154 u8 byte = 0;
bcf8b616 1155
7392f245 1156 for (i = 0; i < bits; i++, pixels--) {
a6fdb669 1157 if (*sbuf8++ >= 128)
7392f245 1158 byte |= BIT(i);
bcf8b616 1159 }
a6fdb669 1160 *dbuf8++ = byte;
bcf8b616
JMC
1161 }
1162}
1163
1164/**
9b13a3fc 1165 * drm_fb_xrgb8888_to_mono - Convert XRGB8888 to monochrome
b3aca563
TZ
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.
504a51d7 1169 * @src: Array of XRGB8888 source buffers
bcf8b616
JMC
1170 * @fb: DRM framebuffer
1171 * @clip: Clip rectangle area to copy
4cd24d4b 1172 * @state: Transform and conversion state
bcf8b616 1173 *
b3aca563
TZ
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
504a51d7 1176 * parameters @dst, @dst_pitch and @src refer to arrays. Each array must have at
b3aca563
TZ
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.
bcf8b616
JMC
1191 *
1192 * This function uses drm_fb_xrgb8888_to_gray8() to convert to grayscale and
9b13a3fc 1193 * then the result is converted from grayscale to monochrome.
bcf8b616 1194 */
b3aca563 1195void drm_fb_xrgb8888_to_mono(struct iosys_map *dst, const unsigned int *dst_pitch,
504a51d7 1196 const struct iosys_map *src, const struct drm_framebuffer *fb,
4cd24d4b 1197 const struct drm_rect *clip, struct drm_format_conv_state *state)
bcf8b616 1198{
b3aca563
TZ
1199 static const unsigned int default_dst_pitch[DRM_FORMAT_MAX_PLANES] = {
1200 0, 0, 0, 0
1201 };
bcf8b616 1202 unsigned int linepixels = drm_rect_width(clip);
7392f245 1203 unsigned int lines = drm_rect_height(clip);
bcf8b616
JMC
1204 unsigned int cpp = fb->format->cpp[0];
1205 unsigned int len_src32 = linepixels * cpp;
1206 struct drm_device *dev = fb->dev;
504a51d7 1207 void *vaddr = src[0].vaddr;
b3aca563 1208 unsigned int dst_pitch_0;
bcf8b616 1209 unsigned int y;
b3aca563 1210 u8 *mono = dst[0].vaddr, *gray8;
bcf8b616
JMC
1211 u32 *src32;
1212
1213 if (drm_WARN_ON(dev, fb->format->format != DRM_FORMAT_XRGB8888))
1214 return;
1215
b3aca563
TZ
1216 if (!dst_pitch)
1217 dst_pitch = default_dst_pitch;
1218 dst_pitch_0 = dst_pitch[0];
1219
bcf8b616 1220 /*
7392f245 1221 * The mono destination buffer contains 1 bit per pixel
bcf8b616 1222 */
b3aca563
TZ
1223 if (!dst_pitch_0)
1224 dst_pitch_0 = DIV_ROUND_UP(linepixels, 8);
bcf8b616 1225
bcf8b616 1226 /*
6bcfe8ea 1227 * The dma memory is write-combined so reads are uncached.
bcf8b616
JMC
1228 * Speed up by fetching one line at a time.
1229 *
9b13a3fc
GU
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.
bcf8b616
JMC
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 */
4cd24d4b 1237 src32 = drm_format_conv_state_reserve(state, len_src32 + linepixels, GFP_KERNEL);
bcf8b616
JMC
1238 if (!src32)
1239 return;
1240
1241 gray8 = (u8 *)src32 + len_src32;
1242
bcf8b616
JMC
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);
7392f245 1247 drm_fb_gray8_to_mono_line(mono, gray8, linepixels);
bcf8b616 1248 vaddr += fb->pitches[0];
b3aca563 1249 mono += dst_pitch_0;
bcf8b616 1250 }
bcf8b616 1251}
9b13a3fc 1252EXPORT_SYMBOL(drm_fb_xrgb8888_to_mono);
4a85b0b5 1253
29fca6d5
TZ
1254static 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
4a85b0b5
TZ
1287static 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
4a85b0b5
TZ
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
29fca6d5 1309 * supported formats and additional emulated formats.
4a85b0b5
TZ
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
29fca6d5
TZ
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
4a85b0b5 1318 * to optimize the order. Formats near the beginning of the list are
29fca6d5 1319 * usually preferred over formats near the end of the list.
4a85b0b5
TZ
1320 *
1321 * Returns:
1322 * The number of color-formats 4CC codes returned in @fourccs_out.
1323 */
1324size_t drm_fb_build_fourcc_list(struct drm_device *dev,
1325 const u32 *native_fourccs, size_t native_nfourccs,
4a85b0b5
TZ
1326 u32 *fourccs_out, size_t nfourccs_out)
1327{
29fca6d5
TZ
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
4a85b0b5
TZ
1339 u32 *fourccs = fourccs_out;
1340 const u32 *fourccs_end = fourccs_out + nfourccs_out;
4a85b0b5
TZ
1341 size_t i;
1342
1343 /*
1344 * The device's native formats go first.
1345 */
1346
1347 for (i = 0; i < native_nfourccs; ++i) {
29fca6d5
TZ
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]);
4a85b0b5
TZ
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
4a85b0b5
TZ
1364 *fourccs = fourcc;
1365 ++fourccs;
1366 }
1367
4a85b0b5
TZ
1368 /*
1369 * The extra formats, emulated by the driver, go second.
1370 */
1371
29fca6d5
TZ
1372 for (i = 0; (i < extra_nfourccs) && (fourccs < fourccs_end); ++i) {
1373 u32 fourcc = extra_fourccs[i];
4a85b0b5
TZ
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
4a85b0b5
TZ
1388 return fourccs - fourccs_out;
1389}
1390EXPORT_SYMBOL(drm_fb_build_fourcc_list);