File Index
Files and directories
Sign in
FILE

drm_format_helper.c

File preview with syntax highlighting.

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