drm_format_helper.c 50 KB

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