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