Linux Audio

Check our new training course

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