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