drm_format_helper.c 49 KB

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