xref: /linux/drivers/gpu/drm/drm_format_helper.c (revision 1a45ef022f0364186d4fb2f4e5255dcae1ff638a)
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 /**
862  * drm_fb_xrgb8888_to_abgr8888 - Convert XRGB8888 to ABGR8888 clip buffer
863  * @dst: Array of ABGR8888 destination buffers
864  * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines
865  *             within @dst; can be NULL if scanlines are stored next to each other.
866  * @src: Array of XRGB8888 source buffer
867  * @fb: DRM framebuffer
868  * @clip: Clip rectangle area to copy
869  * @state: Transform and conversion state
870  *
871  * This function copies parts of a framebuffer to display memory and converts the
872  * color format during the process. The parameters @dst, @dst_pitch and @src refer
873  * to arrays. Each array must have at least as many entries as there are planes in
874  * @fb's format. Each entry stores the value for the format's respective color plane
875  * at the same index.
876  *
877  * This function does not apply clipping on @dst (i.e. the destination is at the
878  * top-left corner).
879  *
880  * Drivers can use this function for ABGR8888 devices that don't support XRGB8888
881  * natively. It sets an opaque alpha channel as part of the conversion.
882  */
883 void drm_fb_xrgb8888_to_abgr8888(struct iosys_map *dst, const unsigned int *dst_pitch,
884 				 const struct iosys_map *src,
885 				 const struct drm_framebuffer *fb,
886 				 const struct drm_rect *clip,
887 				 struct drm_format_conv_state *state)
888 {
889 	static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = {
890 		4,
891 	};
892 
893 	drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state,
894 		    drm_fb_xrgb8888_to_abgr8888_line);
895 }
896 EXPORT_SYMBOL(drm_fb_xrgb8888_to_abgr8888);
897 
898 static void drm_fb_xrgb8888_to_xbgr8888_line(void *dbuf, const void *sbuf, unsigned int pixels)
899 {
900 	drm_fb_xfrm_line_32to32(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_xbgr8888);
901 }
902 
903 /**
904  * drm_fb_xrgb8888_to_xbgr8888 - Convert XRGB8888 to XBGR8888 clip buffer
905  * @dst: Array of XBGR8888 destination buffers
906  * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines
907  *             within @dst; can be NULL if scanlines are stored next to each other.
908  * @src: Array of XRGB8888 source buffer
909  * @fb: DRM framebuffer
910  * @clip: Clip rectangle area to copy
911  * @state: Transform and conversion state
912  *
913  * This function copies parts of a framebuffer to display memory and converts the
914  * color format during the process. The parameters @dst, @dst_pitch and @src refer
915  * to arrays. Each array must have at least as many entries as there are planes in
916  * @fb's format. Each entry stores the value for the format's respective color plane
917  * at the same index.
918  *
919  * This function does not apply clipping on @dst (i.e. the destination is at the
920  * top-left corner).
921  *
922  * Drivers can use this function for XBGR8888 devices that don't support XRGB8888
923  * natively.
924  */
925 void drm_fb_xrgb8888_to_xbgr8888(struct iosys_map *dst, const unsigned int *dst_pitch,
926 				 const struct iosys_map *src,
927 				 const struct drm_framebuffer *fb,
928 				 const struct drm_rect *clip,
929 				 struct drm_format_conv_state *state)
930 {
931 	static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = {
932 		4,
933 	};
934 
935 	drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state,
936 		    drm_fb_xrgb8888_to_xbgr8888_line);
937 }
938 EXPORT_SYMBOL(drm_fb_xrgb8888_to_xbgr8888);
939 
940 static void drm_fb_xrgb8888_to_bgrx8888_line(void *dbuf, const void *sbuf, unsigned int pixels)
941 {
942 	drm_fb_xfrm_line_32to32(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_bgrx8888);
943 }
944 
945 /**
946  * drm_fb_xrgb8888_to_bgrx8888 - Convert XRGB8888 to BGRX8888 clip buffer
947  * @dst: Array of BGRX8888 destination buffers
948  * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines
949  *             within @dst; can be NULL if scanlines are stored next to each other.
950  * @src: Array of XRGB8888 source buffer
951  * @fb: DRM framebuffer
952  * @clip: Clip rectangle area to copy
953  * @state: Transform and conversion state
954  *
955  * This function copies parts of a framebuffer to display memory and converts the
956  * color format during the process. The parameters @dst, @dst_pitch and @src refer
957  * to arrays. Each array must have at least as many entries as there are planes in
958  * @fb's format. Each entry stores the value for the format's respective color plane
959  * at the same index.
960  *
961  * This function does not apply clipping on @dst (i.e. the destination is at the
962  * top-left corner).
963  *
964  * Drivers can use this function for BGRX8888 devices that don't support XRGB8888
965  * natively.
966  */
967 void drm_fb_xrgb8888_to_bgrx8888(struct iosys_map *dst, const unsigned int *dst_pitch,
968 				 const struct iosys_map *src,
969 				 const struct drm_framebuffer *fb,
970 				 const struct drm_rect *clip,
971 				 struct drm_format_conv_state *state)
972 {
973 	static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = {
974 		4,
975 	};
976 
977 	drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state,
978 		    drm_fb_xrgb8888_to_bgrx8888_line);
979 }
980 EXPORT_SYMBOL(drm_fb_xrgb8888_to_bgrx8888);
981 
982 static void drm_fb_xrgb8888_to_xrgb2101010_line(void *dbuf, const void *sbuf, unsigned int pixels)
983 {
984 	drm_fb_xfrm_line_32to32(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_xrgb2101010);
985 }
986 
987 /**
988  * drm_fb_xrgb8888_to_xrgb2101010 - Convert XRGB8888 to XRGB2101010 clip buffer
989  * @dst: Array of XRGB2101010 destination buffers
990  * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines
991  *             within @dst; can be NULL if scanlines are stored next to each other.
992  * @src: Array of XRGB8888 source buffers
993  * @fb: DRM framebuffer
994  * @clip: Clip rectangle area to copy
995  * @state: Transform and conversion state
996  *
997  * This function copies parts of a framebuffer to display memory and converts the
998  * color format during the process. Destination and framebuffer formats must match. The
999  * parameters @dst, @dst_pitch and @src refer to arrays. Each array must have at
1000  * least as many entries as there are planes in @fb's format. Each entry stores the
1001  * value for the format's respective color plane at the same index.
1002  *
1003  * This function does not apply clipping on @dst (i.e. the destination is at the
1004  * top-left corner).
1005  *
1006  * Drivers can use this function for XRGB2101010 devices that don't support XRGB8888
1007  * natively.
1008  */
1009 void drm_fb_xrgb8888_to_xrgb2101010(struct iosys_map *dst, const unsigned int *dst_pitch,
1010 				    const struct iosys_map *src, const struct drm_framebuffer *fb,
1011 				    const struct drm_rect *clip,
1012 				    struct drm_format_conv_state *state)
1013 {
1014 	static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = {
1015 		4,
1016 	};
1017 
1018 	drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state,
1019 		    drm_fb_xrgb8888_to_xrgb2101010_line);
1020 }
1021 EXPORT_SYMBOL(drm_fb_xrgb8888_to_xrgb2101010);
1022 
1023 static void drm_fb_xrgb8888_to_argb2101010_line(void *dbuf, const void *sbuf, unsigned int pixels)
1024 {
1025 	drm_fb_xfrm_line_32to32(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_argb2101010);
1026 }
1027 
1028 /**
1029  * drm_fb_xrgb8888_to_argb2101010 - Convert XRGB8888 to ARGB2101010 clip buffer
1030  * @dst: Array of ARGB2101010 destination buffers
1031  * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines
1032  *             within @dst; can be NULL if scanlines are stored next to each other.
1033  * @src: Array of XRGB8888 source buffers
1034  * @fb: DRM framebuffer
1035  * @clip: Clip rectangle area to copy
1036  * @state: Transform and conversion state
1037  *
1038  * This function copies parts of a framebuffer to display memory and converts
1039  * the color format during the process. The parameters @dst, @dst_pitch and
1040  * @src refer to arrays. Each array must have at least as many entries as
1041  * there are planes in @fb's format. Each entry stores the value for the
1042  * format's respective color plane at the same index.
1043  *
1044  * This function does not apply clipping on @dst (i.e. the destination is at the
1045  * top-left corner).
1046  *
1047  * Drivers can use this function for ARGB2101010 devices that don't support XRGB8888
1048  * natively.
1049  */
1050 void drm_fb_xrgb8888_to_argb2101010(struct iosys_map *dst, const unsigned int *dst_pitch,
1051 				    const struct iosys_map *src, const struct drm_framebuffer *fb,
1052 				    const struct drm_rect *clip,
1053 				    struct drm_format_conv_state *state)
1054 {
1055 	static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = {
1056 		4,
1057 	};
1058 
1059 	drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state,
1060 		    drm_fb_xrgb8888_to_argb2101010_line);
1061 }
1062 EXPORT_SYMBOL(drm_fb_xrgb8888_to_argb2101010);
1063 
1064 static void drm_fb_xrgb8888_to_gray8_line(void *dbuf, const void *sbuf, unsigned int pixels)
1065 {
1066 	drm_fb_xfrm_line_32to8(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_r8_bt601);
1067 }
1068 
1069 /**
1070  * drm_fb_xrgb8888_to_gray8 - Convert XRGB8888 to grayscale
1071  * @dst: Array of 8-bit grayscale destination buffers
1072  * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines
1073  *             within @dst; can be NULL if scanlines are stored next to each other.
1074  * @src: Array of XRGB8888 source buffers
1075  * @fb: DRM framebuffer
1076  * @clip: Clip rectangle area to copy
1077  * @state: Transform and conversion state
1078  *
1079  * This function copies parts of a framebuffer to display memory and converts the
1080  * color format during the process. Destination and framebuffer formats must match. The
1081  * parameters @dst, @dst_pitch and @src refer to arrays. Each array must have at
1082  * least as many entries as there are planes in @fb's format. Each entry stores the
1083  * value for the format's respective color plane at the same index.
1084  *
1085  * This function does not apply clipping on @dst (i.e. the destination is at the
1086  * top-left corner).
1087  *
1088  * DRM doesn't have native monochrome or grayscale support. Drivers can use this
1089  * function for grayscale devices that don't support XRGB8888 natively.Such
1090  * drivers can announce the commonly supported XR24 format to userspace and use
1091  * this function to convert to the native format. Monochrome drivers will use the
1092  * most significant bit, where 1 means foreground color and 0 background color.
1093  * ITU BT.601 is being used for the RGB -> luma (brightness) conversion.
1094  */
1095 void drm_fb_xrgb8888_to_gray8(struct iosys_map *dst, const unsigned int *dst_pitch,
1096 			      const struct iosys_map *src, const struct drm_framebuffer *fb,
1097 			      const struct drm_rect *clip, struct drm_format_conv_state *state)
1098 {
1099 	static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = {
1100 		1,
1101 	};
1102 
1103 	drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state,
1104 		    drm_fb_xrgb8888_to_gray8_line);
1105 }
1106 EXPORT_SYMBOL(drm_fb_xrgb8888_to_gray8);
1107 
1108 static void drm_fb_argb8888_to_argb4444_line(void *dbuf, const void *sbuf, unsigned int pixels)
1109 {
1110 	drm_fb_xfrm_line_32to16(dbuf, sbuf, pixels, drm_pixel_argb8888_to_argb4444);
1111 }
1112 
1113 /**
1114  * drm_fb_argb8888_to_argb4444 - Convert ARGB8888 to ARGB4444 clip buffer
1115  * @dst: Array of ARGB4444 destination buffers
1116  * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines
1117  *             within @dst; can be NULL if scanlines are stored next to each other.
1118  * @src: Array of ARGB8888 source buffer
1119  * @fb: DRM framebuffer
1120  * @clip: Clip rectangle area to copy
1121  * @state: Transform and conversion state
1122  *
1123  * This function copies parts of a framebuffer to display memory and converts
1124  * the color format during the process. The parameters @dst, @dst_pitch and
1125  * @src refer to arrays. Each array must have at least as many entries as
1126  * there are planes in @fb's format. Each entry stores the value for the
1127  * format's respective color plane at the same index.
1128  *
1129  * This function does not apply clipping on @dst (i.e. the destination is at the
1130  * top-left corner).
1131  *
1132  * Drivers can use this function for ARGB4444 devices that don't support
1133  * ARGB8888 natively.
1134  */
1135 void drm_fb_argb8888_to_argb4444(struct iosys_map *dst, const unsigned int *dst_pitch,
1136 				 const struct iosys_map *src, const struct drm_framebuffer *fb,
1137 				 const struct drm_rect *clip, struct drm_format_conv_state *state)
1138 {
1139 	static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = {
1140 		2,
1141 	};
1142 
1143 	drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state,
1144 		    drm_fb_argb8888_to_argb4444_line);
1145 }
1146 EXPORT_SYMBOL(drm_fb_argb8888_to_argb4444);
1147 
1148 /**
1149  * drm_fb_blit - Copy parts of a framebuffer to display memory
1150  * @dst:	Array of display-memory addresses to copy to
1151  * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines
1152  *             within @dst; can be NULL if scanlines are stored next to each other.
1153  * @dst_format:	FOURCC code of the display's color format
1154  * @src:	The framebuffer memory to copy from
1155  * @fb:		The framebuffer to copy from
1156  * @clip:	Clip rectangle area to copy
1157  * @state: Transform and conversion state
1158  *
1159  * This function copies parts of a framebuffer to display memory. If the
1160  * formats of the display and the framebuffer mismatch, the blit function
1161  * will attempt to convert between them during the process. The parameters @dst,
1162  * @dst_pitch and @src refer to arrays. Each array must have at least as many
1163  * entries as there are planes in @dst_format's format. Each entry stores the
1164  * value for the format's respective color plane at the same index.
1165  *
1166  * This function does not apply clipping on @dst (i.e. the destination is at the
1167  * top-left corner).
1168  *
1169  * Returns:
1170  * 0 on success, or
1171  * -EINVAL if the color-format conversion failed, or
1172  * a negative error code otherwise.
1173  */
1174 int drm_fb_blit(struct iosys_map *dst, const unsigned int *dst_pitch, uint32_t dst_format,
1175 		const struct iosys_map *src, const struct drm_framebuffer *fb,
1176 		const struct drm_rect *clip, struct drm_format_conv_state *state)
1177 {
1178 	uint32_t fb_format = fb->format->format;
1179 
1180 	if (fb_format == dst_format) {
1181 		drm_fb_memcpy(dst, dst_pitch, src, fb, clip);
1182 		return 0;
1183 	} else if (fb_format == (dst_format | DRM_FORMAT_BIG_ENDIAN)) {
1184 		drm_fb_swab(dst, dst_pitch, src, fb, clip, false, state);
1185 		return 0;
1186 	} else if (fb_format == (dst_format & ~DRM_FORMAT_BIG_ENDIAN)) {
1187 		drm_fb_swab(dst, dst_pitch, src, fb, clip, false, state);
1188 		return 0;
1189 	} else if (fb_format == DRM_FORMAT_XRGB8888) {
1190 		if (dst_format == DRM_FORMAT_RGB565) {
1191 			drm_fb_xrgb8888_to_rgb565(dst, dst_pitch, src, fb, clip, state, false);
1192 			return 0;
1193 		} else if (dst_format == DRM_FORMAT_XRGB1555) {
1194 			drm_fb_xrgb8888_to_xrgb1555(dst, dst_pitch, src, fb, clip, state);
1195 			return 0;
1196 		} else if (dst_format == DRM_FORMAT_ARGB1555) {
1197 			drm_fb_xrgb8888_to_argb1555(dst, dst_pitch, src, fb, clip, state);
1198 			return 0;
1199 		} else if (dst_format == DRM_FORMAT_RGBA5551) {
1200 			drm_fb_xrgb8888_to_rgba5551(dst, dst_pitch, src, fb, clip, state);
1201 			return 0;
1202 		} else if (dst_format == DRM_FORMAT_RGB888) {
1203 			drm_fb_xrgb8888_to_rgb888(dst, dst_pitch, src, fb, clip, state);
1204 			return 0;
1205 		} else if (dst_format == DRM_FORMAT_BGR888) {
1206 			drm_fb_xrgb8888_to_bgr888(dst, dst_pitch, src, fb, clip, state);
1207 			return 0;
1208 		} else if (dst_format == DRM_FORMAT_ARGB8888) {
1209 			drm_fb_xrgb8888_to_argb8888(dst, dst_pitch, src, fb, clip, state);
1210 			return 0;
1211 		} else if (dst_format == DRM_FORMAT_XBGR8888) {
1212 			drm_fb_xrgb8888_to_xbgr8888(dst, dst_pitch, src, fb, clip, state);
1213 			return 0;
1214 		} else if (dst_format == DRM_FORMAT_ABGR8888) {
1215 			drm_fb_xrgb8888_to_abgr8888(dst, dst_pitch, src, fb, clip, state);
1216 			return 0;
1217 		} else if (dst_format == DRM_FORMAT_XRGB2101010) {
1218 			drm_fb_xrgb8888_to_xrgb2101010(dst, dst_pitch, src, fb, clip, state);
1219 			return 0;
1220 		} else if (dst_format == DRM_FORMAT_ARGB2101010) {
1221 			drm_fb_xrgb8888_to_argb2101010(dst, dst_pitch, src, fb, clip, state);
1222 			return 0;
1223 		} else if (dst_format == DRM_FORMAT_BGRX8888) {
1224 			drm_fb_swab(dst, dst_pitch, src, fb, clip, false, state);
1225 			return 0;
1226 		}
1227 	}
1228 
1229 	drm_warn_once(fb->dev, "No conversion helper from %p4cc to %p4cc found.\n",
1230 		      &fb_format, &dst_format);
1231 
1232 	return -EINVAL;
1233 }
1234 EXPORT_SYMBOL(drm_fb_blit);
1235 
1236 static void drm_fb_gray8_to_mono_line(void *dbuf, const void *sbuf, unsigned int pixels)
1237 {
1238 	u8 *dbuf8 = dbuf;
1239 	const u8 *sbuf8 = sbuf;
1240 
1241 	while (pixels) {
1242 		unsigned int i, bits = min(pixels, 8U);
1243 		u8 byte = 0;
1244 
1245 		for (i = 0; i < bits; i++, pixels--) {
1246 			if (*sbuf8++ >= 128)
1247 				byte |= BIT(i);
1248 		}
1249 		*dbuf8++ = byte;
1250 	}
1251 }
1252 
1253 /**
1254  * drm_fb_xrgb8888_to_mono - Convert XRGB8888 to monochrome
1255  * @dst: Array of monochrome destination buffers (0=black, 1=white)
1256  * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines
1257  *             within @dst; can be NULL if scanlines are stored next to each other.
1258  * @src: Array of XRGB8888 source buffers
1259  * @fb: DRM framebuffer
1260  * @clip: Clip rectangle area to copy
1261  * @state: Transform and conversion state
1262  *
1263  * This function copies parts of a framebuffer to display memory and converts the
1264  * color format during the process. Destination and framebuffer formats must match. The
1265  * parameters @dst, @dst_pitch and @src refer to arrays. Each array must have at
1266  * least as many entries as there are planes in @fb's format. Each entry stores the
1267  * value for the format's respective color plane at the same index.
1268  *
1269  * This function does not apply clipping on @dst (i.e. the destination is at the
1270  * top-left corner). The first pixel (upper left corner of the clip rectangle) will
1271  * be converted and copied to the first bit (LSB) in the first byte of the monochrome
1272  * destination buffer. If the caller requires that the first pixel in a byte must
1273  * be located at an x-coordinate that is a multiple of 8, then the caller must take
1274  * care itself of supplying a suitable clip rectangle.
1275  *
1276  * DRM doesn't have native monochrome support. Drivers can use this function for
1277  * monochrome devices that don't support XRGB8888 natively. Such drivers can
1278  * announce the commonly supported XR24 format to userspace and use this function
1279  * to convert to the native format.
1280  *
1281  * This function uses drm_fb_xrgb8888_to_gray8() to convert to grayscale and
1282  * then the result is converted from grayscale to monochrome.
1283  */
1284 void drm_fb_xrgb8888_to_mono(struct iosys_map *dst, const unsigned int *dst_pitch,
1285 			     const struct iosys_map *src, const struct drm_framebuffer *fb,
1286 			     const struct drm_rect *clip, struct drm_format_conv_state *state)
1287 {
1288 	static const unsigned int default_dst_pitch[DRM_FORMAT_MAX_PLANES] = {
1289 		0, 0, 0, 0
1290 	};
1291 	unsigned int linepixels = drm_rect_width(clip);
1292 	unsigned int lines = drm_rect_height(clip);
1293 	unsigned int cpp = fb->format->cpp[0];
1294 	unsigned int len_src32 = linepixels * cpp;
1295 	struct drm_device *dev = fb->dev;
1296 	void *vaddr = src[0].vaddr;
1297 	unsigned int dst_pitch_0;
1298 	unsigned int y;
1299 	u8 *mono = dst[0].vaddr, *gray8;
1300 	u32 *src32;
1301 
1302 	if (drm_WARN_ON(dev, fb->format->format != DRM_FORMAT_XRGB8888))
1303 		return;
1304 
1305 	if (!dst_pitch)
1306 		dst_pitch = default_dst_pitch;
1307 	dst_pitch_0 = dst_pitch[0];
1308 
1309 	/*
1310 	 * The mono destination buffer contains 1 bit per pixel
1311 	 */
1312 	if (!dst_pitch_0)
1313 		dst_pitch_0 = DIV_ROUND_UP(linepixels, 8);
1314 
1315 	/*
1316 	 * The dma memory is write-combined so reads are uncached.
1317 	 * Speed up by fetching one line at a time.
1318 	 *
1319 	 * Also, format conversion from XR24 to monochrome are done
1320 	 * line-by-line but are converted to 8-bit grayscale as an
1321 	 * intermediate step.
1322 	 *
1323 	 * Allocate a buffer to be used for both copying from the cma
1324 	 * memory and to store the intermediate grayscale line pixels.
1325 	 */
1326 	src32 = drm_format_conv_state_reserve(state, len_src32 + linepixels, GFP_KERNEL);
1327 	if (!src32)
1328 		return;
1329 
1330 	gray8 = (u8 *)src32 + len_src32;
1331 
1332 	vaddr += clip_offset(clip, fb->pitches[0], cpp);
1333 	for (y = 0; y < lines; y++) {
1334 		src32 = memcpy(src32, vaddr, len_src32);
1335 		drm_fb_xrgb8888_to_gray8_line(gray8, src32, linepixels);
1336 		drm_fb_gray8_to_mono_line(mono, gray8, linepixels);
1337 		vaddr += fb->pitches[0];
1338 		mono += dst_pitch_0;
1339 	}
1340 }
1341 EXPORT_SYMBOL(drm_fb_xrgb8888_to_mono);
1342