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