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