diff mbox series

[v5,1/6] drm/format-helper: Add drm_fb_blit_from_r1 and drm_fb_fill

Message ID 20231103145526.628138-2-jfalempe@redhat.com (mailing list archive)
State New, archived
Headers show
Series drm/panic: Add a drm panic handler | expand

Commit Message

Jocelyn Falempe Nov. 3, 2023, 2:53 p.m. UTC
This is needed for drm_panic, to draw the font, and fill
the background color, in multiple color format.

v5:
 * Change the drawing API, use drm_fb_blit_from_r1() to draw the font.
 * Also add drm_fb_fill() to fill area with background color.

Signed-off-by: Jocelyn Falempe <jfalempe@redhat.com>
---
 drivers/gpu/drm/drm_format_helper.c | 421 ++++++++++++++++++++++------
 include/drm/drm_format_helper.h     |   9 +
 2 files changed, 349 insertions(+), 81 deletions(-)

Comments

kernel test robot Nov. 3, 2023, 6:34 p.m. UTC | #1
Hi Jocelyn,

kernel test robot noticed the following build warnings:

[auto build test WARNING on ffc253263a1375a65fa6c9f62a893e9767fbebfa]

url:    https://github.com/intel-lab-lkp/linux/commits/Jocelyn-Falempe/drm-format-helper-Add-drm_fb_blit_from_r1-and-drm_fb_fill/20231103-225824
base:   ffc253263a1375a65fa6c9f62a893e9767fbebfa
patch link:    https://lore.kernel.org/r/20231103145526.628138-2-jfalempe%40redhat.com
patch subject: [PATCH v5 1/6] drm/format-helper: Add drm_fb_blit_from_r1 and drm_fb_fill
config: csky-randconfig-002-20231104 (https://download.01.org/0day-ci/archive/20231104/202311040208.JqcG6ZbK-lkp@intel.com/config)
compiler: csky-linux-gcc (GCC) 13.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20231104/202311040208.JqcG6ZbK-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202311040208.JqcG6ZbK-lkp@intel.com/

All warnings (new ones prefixed by >>):

>> drivers/gpu/drm/drm_format_helper.c:491: warning: Function parameter or member 'dpitch' not described in 'drm_fb_blit_from_r1'
>> drivers/gpu/drm/drm_format_helper.c:491: warning: Excess function parameter 'dpich' description in 'drm_fb_blit_from_r1'
>> drivers/gpu/drm/drm_format_helper.c:578: warning: Function parameter or member 'dpitch' not described in 'drm_fb_fill'
>> drivers/gpu/drm/drm_format_helper.c:578: warning: Function parameter or member 'color' not described in 'drm_fb_fill'
>> drivers/gpu/drm/drm_format_helper.c:578: warning: Excess function parameter 'dpich' description in 'drm_fb_fill'
>> drivers/gpu/drm/drm_format_helper.c:578: warning: Excess function parameter 'fg_color' description in 'drm_fb_fill'
>> drivers/gpu/drm/drm_format_helper.c:578: warning: Excess function parameter 'bg_color' description in 'drm_fb_fill'


vim +491 drivers/gpu/drm/drm_format_helper.c

   470	
   471	/**
   472	 * drm_fb_blit_from_r1 - convert a monochrome image to a linear framebuffer
   473	 * @dmap: destination iosys_map
   474	 * @dpich: destination pitch in bytes
   475	 * @sbuf8: source buffer, in monochrome format, 8 pixels per byte.
   476	 * @spitch: source pitch in bytes
   477	 * @height: height of the image to copy, in pixels
   478	 * @width: width of the image to copy, in pixels
   479	 * @fg_color: foreground color, in destination format
   480	 * @bg_color: background color, in destination format
   481	 * @pixel_width: pixel width in bytes.
   482	 *
   483	 * This can be used to draw font which are monochrome images, to a framebuffer
   484	 * in other supported format.
   485	 */
   486	void drm_fb_blit_from_r1(struct iosys_map *dmap, unsigned int dpitch,
   487				 const u8 *sbuf8, unsigned int spitch,
   488				 unsigned int height, unsigned int width,
   489				 u32 fg_color, u32 bg_color,
   490				 unsigned int pixel_width)
 > 491	{
   492		switch (pixel_width) {
   493		case 2:
   494			drm_fb_r1_to_16bit(dmap, dpitch, sbuf8, spitch,
   495					   height, width, fg_color, bg_color);
   496		break;
   497		case 3:
   498			drm_fb_r1_to_24bit(dmap, dpitch, sbuf8, spitch,
   499					   height, width, fg_color, bg_color);
   500		break;
   501		case 4:
   502			drm_fb_r1_to_32bit(dmap, dpitch, sbuf8, spitch,
   503					   height, width, fg_color, bg_color);
   504		break;
   505		default:
   506			WARN_ONCE(1, "Can't blit with pixel width %d\n", pixel_width);
   507		}
   508	}
   509	EXPORT_SYMBOL(drm_fb_blit_from_r1);
   510	
   511	static void drm_fb_fill8(struct iosys_map *dmap, unsigned int dpitch,
   512				 unsigned int height, unsigned int width,
   513				 u8 color)
   514	{
   515		unsigned int l, x;
   516	
   517		for (l = 0; l < height; l++)
   518			for (x = 0; x < width; x++)
   519				iosys_map_wr(dmap, l * dpitch + x * sizeof(u8), u8, color);
   520	}
   521	
   522	static void drm_fb_fill16(struct iosys_map *dmap, unsigned int dpitch,
   523				  unsigned int height, unsigned int width,
   524				  u16 color)
   525	{
   526		unsigned int l, x;
   527	
   528		for (l = 0; l < height; l++)
   529			for (x = 0; x < width; x++)
   530				iosys_map_wr(dmap, l * dpitch + x * sizeof(u16), u16, color);
   531	}
   532	
   533	static void drm_fb_fill24(struct iosys_map *dmap, unsigned int dpitch,
   534				  unsigned int height, unsigned int width,
   535				  u32 color)
   536	{
   537		unsigned int l, x;
   538	
   539		for (l = 0; l < height; l++) {
   540			for (x = 0; x < width; x++) {
   541				unsigned int off = l * dpitch + x * 3;
   542				u32 val32 = le32_to_cpu(color);
   543	
   544				/* write blue-green-red to output in little endianness */
   545				iosys_map_wr(dmap, off, u8, (val32 & 0x000000FF) >> 0);
   546				iosys_map_wr(dmap, off + 1, u8, (val32 & 0x0000FF00) >> 8);
   547				iosys_map_wr(dmap, off + 2, u8, (val32 & 0x00FF0000) >> 16);
   548			}
   549		}
   550	}
   551	
   552	static void drm_fb_fill32(struct iosys_map *dmap, unsigned int dpitch,
   553				  unsigned int height, unsigned int width,
   554				  u32 color)
   555	{
   556		unsigned int l, x;
   557	
   558		for (l = 0; l < height; l++)
   559			for (x = 0; x < width; x++)
   560				iosys_map_wr(dmap, l * dpitch + x * sizeof(u32), u32, color);
   561	}
   562	
   563	/**
   564	 * drm_fb_fill - Fill a rectangle with a color
   565	 * @dmap: destination iosys_map, pointing to the top left corner of the rectangle
   566	 * @dpich: destination pitch in bytes
   567	 * @height: height of the rectangle, in pixels
   568	 * @width: width of the rectangle, in pixels
   569	 * @fg_color: foreground color, in destination format
   570	 * @bg_color: background color, in destination format
   571	 * @pixel_width: pixel width in bytes
   572	 *
   573	 * Fill a rectangle with a color, in a linear framebuffer.
   574	 */
   575	void drm_fb_fill(struct iosys_map *dmap, unsigned int dpitch,
   576				 unsigned int height, unsigned int width,
   577				 u32 color, unsigned int pixel_width)
 > 578	{
   579		switch (pixel_width) {
   580		case 1:
   581			drm_fb_fill8(dmap, dpitch, height, width, color);
   582		break;
   583		case 2:
   584			drm_fb_fill16(dmap, dpitch, height, width, color);
   585		break;
   586		case 3:
   587			drm_fb_fill24(dmap, dpitch, height, width, color);
   588		break;
   589		case 4:
   590			drm_fb_fill32(dmap, dpitch, height, width, color);
   591		break;
   592		default:
   593			WARN_ONCE(1, "Can't fill with pixel width %d\n", pixel_width);
   594		}
   595	}
   596	EXPORT_SYMBOL(drm_fb_fill);
   597
kernel test robot Nov. 4, 2023, 6:04 a.m. UTC | #2
Hi Jocelyn,

kernel test robot noticed the following build warnings:

[auto build test WARNING on ffc253263a1375a65fa6c9f62a893e9767fbebfa]

url:    https://github.com/intel-lab-lkp/linux/commits/Jocelyn-Falempe/drm-format-helper-Add-drm_fb_blit_from_r1-and-drm_fb_fill/20231103-225824
base:   ffc253263a1375a65fa6c9f62a893e9767fbebfa
patch link:    https://lore.kernel.org/r/20231103145526.628138-2-jfalempe%40redhat.com
patch subject: [PATCH v5 1/6] drm/format-helper: Add drm_fb_blit_from_r1 and drm_fb_fill
config: i386-randconfig-062-20231104 (https://download.01.org/0day-ci/archive/20231104/202311041300.X5kh1Yvx-lkp@intel.com/config)
compiler: gcc-11 (Debian 11.3.0-12) 11.3.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20231104/202311041300.X5kh1Yvx-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202311041300.X5kh1Yvx-lkp@intel.com/

sparse warnings: (new ones prefixed by >>)
>> drivers/gpu/drm/drm_format_helper.c:445:33: sparse: sparse: cast to restricted __le32
   drivers/gpu/drm/drm_format_helper.c:542:37: sparse: sparse: cast to restricted __le32
>> drivers/gpu/drm/drm_format_helper.c:653:65: sparse: sparse: incorrect type in argument 1 (different base types) @@     expected unsigned int [usertype] pix @@     got restricted __le32 const [usertype] @@
   drivers/gpu/drm/drm_format_helper.c:653:65: sparse:     expected unsigned int [usertype] pix
   drivers/gpu/drm/drm_format_helper.c:653:65: sparse:     got restricted __le32 const [usertype]
>> drivers/gpu/drm/drm_format_helper.c:653:27: sparse: sparse: incorrect type in assignment (different base types) @@     expected restricted __le16 [usertype] @@     got unsigned short @@
   drivers/gpu/drm/drm_format_helper.c:653:27: sparse:     expected restricted __le16 [usertype]
   drivers/gpu/drm/drm_format_helper.c:653:27: sparse:     got unsigned short
   drivers/gpu/drm/drm_format_helper.c:723:67: sparse: sparse: incorrect type in argument 1 (different base types) @@     expected unsigned int [usertype] pix @@     got restricted __le32 const [usertype] @@
   drivers/gpu/drm/drm_format_helper.c:723:67: sparse:     expected unsigned int [usertype] pix
   drivers/gpu/drm/drm_format_helper.c:723:67: sparse:     got restricted __le32 const [usertype]
   drivers/gpu/drm/drm_format_helper.c:723:27: sparse: sparse: incorrect type in assignment (different base types) @@     expected restricted __le16 [usertype] @@     got unsigned short @@
   drivers/gpu/drm/drm_format_helper.c:723:27: sparse:     expected restricted __le16 [usertype]
   drivers/gpu/drm/drm_format_helper.c:723:27: sparse:     got unsigned short
   drivers/gpu/drm/drm_format_helper.c:767:67: sparse: sparse: incorrect type in argument 1 (different base types) @@     expected unsigned int [usertype] pix @@     got restricted __le32 const [usertype] @@
   drivers/gpu/drm/drm_format_helper.c:767:67: sparse:     expected unsigned int [usertype] pix
   drivers/gpu/drm/drm_format_helper.c:767:67: sparse:     got restricted __le32 const [usertype]
   drivers/gpu/drm/drm_format_helper.c:767:27: sparse: sparse: incorrect type in assignment (different base types) @@     expected restricted __le16 [usertype] @@     got unsigned short @@
   drivers/gpu/drm/drm_format_helper.c:767:27: sparse:     expected restricted __le16 [usertype]
   drivers/gpu/drm/drm_format_helper.c:767:27: sparse:     got unsigned short
   drivers/gpu/drm/drm_format_helper.c:811:67: sparse: sparse: incorrect type in argument 1 (different base types) @@     expected unsigned int [usertype] pix @@     got restricted __le32 const [usertype] @@
   drivers/gpu/drm/drm_format_helper.c:811:67: sparse:     expected unsigned int [usertype] pix
   drivers/gpu/drm/drm_format_helper.c:811:67: sparse:     got restricted __le32 const [usertype]
   drivers/gpu/drm/drm_format_helper.c:811:27: sparse: sparse: incorrect type in assignment (different base types) @@     expected restricted __le16 [usertype] @@     got unsigned short @@
   drivers/gpu/drm/drm_format_helper.c:811:27: sparse:     expected restricted __le16 [usertype]
   drivers/gpu/drm/drm_format_helper.c:811:27: sparse:     got unsigned short
   drivers/gpu/drm/drm_format_helper.c:905:67: sparse: sparse: incorrect type in argument 1 (different base types) @@     expected unsigned int [usertype] pix @@     got restricted __le32 const [usertype] @@
   drivers/gpu/drm/drm_format_helper.c:905:67: sparse:     expected unsigned int [usertype] pix
   drivers/gpu/drm/drm_format_helper.c:905:67: sparse:     got restricted __le32 const [usertype]
>> drivers/gpu/drm/drm_format_helper.c:905:27: sparse: sparse: incorrect type in assignment (different base types) @@     expected restricted __le32 [usertype] @@     got unsigned int @@
   drivers/gpu/drm/drm_format_helper.c:905:27: sparse:     expected restricted __le32 [usertype]
   drivers/gpu/drm/drm_format_helper.c:905:27: sparse:     got unsigned int
   drivers/gpu/drm/drm_format_helper.c:949:67: sparse: sparse: incorrect type in argument 1 (different base types) @@     expected unsigned int [usertype] pix @@     got restricted __le32 const [usertype] @@
   drivers/gpu/drm/drm_format_helper.c:949:67: sparse:     expected unsigned int [usertype] pix
   drivers/gpu/drm/drm_format_helper.c:949:67: sparse:     got restricted __le32 const [usertype]
   drivers/gpu/drm/drm_format_helper.c:949:27: sparse: sparse: incorrect type in assignment (different base types) @@     expected restricted __le32 [usertype] @@     got unsigned int @@
   drivers/gpu/drm/drm_format_helper.c:949:27: sparse:     expected restricted __le32 [usertype]
   drivers/gpu/drm/drm_format_helper.c:949:27: sparse:     got unsigned int
   drivers/gpu/drm/drm_format_helper.c:972:67: sparse: sparse: incorrect type in argument 1 (different base types) @@     expected unsigned int [usertype] pix @@     got restricted __le32 const [usertype] @@
   drivers/gpu/drm/drm_format_helper.c:972:67: sparse:     expected unsigned int [usertype] pix
   drivers/gpu/drm/drm_format_helper.c:972:67: sparse:     got restricted __le32 const [usertype]
   drivers/gpu/drm/drm_format_helper.c:972:27: sparse: sparse: incorrect type in assignment (different base types) @@     expected restricted __le32 [usertype] @@     got unsigned int @@
   drivers/gpu/drm/drm_format_helper.c:972:27: sparse:     expected restricted __le32 [usertype]
   drivers/gpu/drm/drm_format_helper.c:972:27: sparse:     got unsigned int
   drivers/gpu/drm/drm_format_helper.c:995:70: sparse: sparse: incorrect type in argument 1 (different base types) @@     expected unsigned int [usertype] pix @@     got restricted __le32 const [usertype] @@
   drivers/gpu/drm/drm_format_helper.c:995:70: sparse:     expected unsigned int [usertype] pix
   drivers/gpu/drm/drm_format_helper.c:995:70: sparse:     got restricted __le32 const [usertype]
   drivers/gpu/drm/drm_format_helper.c:995:27: sparse: sparse: incorrect type in assignment (different base types) @@     expected restricted __le32 [usertype] @@     got unsigned int @@
   drivers/gpu/drm/drm_format_helper.c:995:27: sparse:     expected restricted __le32 [usertype]
   drivers/gpu/drm/drm_format_helper.c:995:27: sparse:     got unsigned int
   drivers/gpu/drm/drm_format_helper.c:1039:70: sparse: sparse: incorrect type in argument 1 (different base types) @@     expected unsigned int [usertype] pix @@     got restricted __le32 const [usertype] @@
   drivers/gpu/drm/drm_format_helper.c:1039:70: sparse:     expected unsigned int [usertype] pix
   drivers/gpu/drm/drm_format_helper.c:1039:70: sparse:     got restricted __le32 const [usertype]
   drivers/gpu/drm/drm_format_helper.c:1039:27: sparse: sparse: incorrect type in assignment (different base types) @@     expected restricted __le32 [usertype] @@     got unsigned int @@
   drivers/gpu/drm/drm_format_helper.c:1039:27: sparse:     expected restricted __le32 [usertype]
   drivers/gpu/drm/drm_format_helper.c:1039:27: sparse:     got unsigned int
   drivers/gpu/drm/drm_format_helper.c:27:15: sparse: sparse: cast to restricted __le32
>> drivers/gpu/drm/drm_format_helper.c:31:16: sparse: sparse: incorrect type in return expression (different base types) @@     expected unsigned short @@     got restricted __le16 [usertype] @@
   drivers/gpu/drm/drm_format_helper.c:31:16: sparse:     expected unsigned short
   drivers/gpu/drm/drm_format_helper.c:31:16: sparse:     got restricted __le16 [usertype]
   drivers/gpu/drm/drm_format_helper.c:38:15: sparse: sparse: cast to restricted __le32
   drivers/gpu/drm/drm_format_helper.c:43:16: sparse: sparse: incorrect type in return expression (different base types) @@     expected unsigned short @@     got restricted __le16 [usertype] @@
   drivers/gpu/drm/drm_format_helper.c:43:16: sparse:     expected unsigned short
   drivers/gpu/drm/drm_format_helper.c:43:16: sparse:     got restricted __le16 [usertype]
   drivers/gpu/drm/drm_format_helper.c:50:15: sparse: sparse: cast to restricted __le32
   drivers/gpu/drm/drm_format_helper.c:54:16: sparse: sparse: incorrect type in return expression (different base types) @@     expected unsigned short @@     got restricted __le16 [usertype] @@
   drivers/gpu/drm/drm_format_helper.c:54:16: sparse:     expected unsigned short
   drivers/gpu/drm/drm_format_helper.c:54:16: sparse:     got restricted __le16 [usertype]
   drivers/gpu/drm/drm_format_helper.c:61:15: sparse: sparse: cast to restricted __le32
   drivers/gpu/drm/drm_format_helper.c:66:16: sparse: sparse: incorrect type in return expression (different base types) @@     expected unsigned short @@     got restricted __le16 [usertype] @@
   drivers/gpu/drm/drm_format_helper.c:66:16: sparse:     expected unsigned short
   drivers/gpu/drm/drm_format_helper.c:66:16: sparse:     got restricted __le16 [usertype]
   drivers/gpu/drm/drm_format_helper.c:73:17: sparse: sparse: cast to restricted __le32
>> drivers/gpu/drm/drm_format_helper.c:75:16: sparse: sparse: incorrect type in return expression (different base types) @@     expected unsigned int @@     got restricted __le32 [usertype] @@
   drivers/gpu/drm/drm_format_helper.c:75:16: sparse:     expected unsigned int
   drivers/gpu/drm/drm_format_helper.c:75:16: sparse:     got restricted __le32 [usertype]
   drivers/gpu/drm/drm_format_helper.c:82:15: sparse: sparse: cast to restricted __le32
   drivers/gpu/drm/drm_format_helper.c:87:16: sparse: sparse: incorrect type in return expression (different base types) @@     expected unsigned int @@     got restricted __le32 [usertype] @@
   drivers/gpu/drm/drm_format_helper.c:87:16: sparse:     expected unsigned int
   drivers/gpu/drm/drm_format_helper.c:87:16: sparse:     got restricted __le32 [usertype]
   drivers/gpu/drm/drm_format_helper.c:106:15: sparse: sparse: cast to restricted __le32
   drivers/gpu/drm/drm_format_helper.c:111:16: sparse: sparse: incorrect type in return expression (different base types) @@     expected unsigned int @@     got restricted __le32 [usertype] @@
   drivers/gpu/drm/drm_format_helper.c:111:16: sparse:     expected unsigned int
   drivers/gpu/drm/drm_format_helper.c:111:16: sparse:     got restricted __le32 [usertype]
   drivers/gpu/drm/drm_format_helper.c:118:15: sparse: sparse: cast to restricted __le32
   drivers/gpu/drm/drm_format_helper.c:124:16: sparse: sparse: incorrect type in return expression (different base types) @@     expected unsigned int @@     got restricted __le32 [usertype] @@
   drivers/gpu/drm/drm_format_helper.c:124:16: sparse:     expected unsigned int
   drivers/gpu/drm/drm_format_helper.c:124:16: sparse:     got restricted __le32 [usertype]

vim +445 drivers/gpu/drm/drm_format_helper.c

   431	
   432	static void drm_fb_r1_to_24bit(struct iosys_map *dmap, unsigned int dpitch,
   433				       const u8 *sbuf8, unsigned int spitch,
   434				       unsigned int height, unsigned int width,
   435				       u32 fg32, u32 bg32)
   436	{
   437		unsigned int l, x;
   438		u32 val32;
   439	
   440		for (l = 0; l < height; l++) {
   441			for (x = 0; x < width; x++) {
   442				u32 off = l * dpitch + x * 3;
   443	
   444				val32 = (sbuf8[(l * spitch) + x / 8] & (0x80 >> (x % 8))) ? fg32 : bg32;
 > 445				val32 = le32_to_cpu(val32);
   446	
   447				/* write blue-green-red to output in little endianness */
   448				iosys_map_wr(dmap, off, u8, (val32 & 0x000000FF) >> 0);
   449				iosys_map_wr(dmap, off + 1, u8, (val32 & 0x0000FF00) >> 8);
   450				iosys_map_wr(dmap, off + 2, u8, (val32 & 0x00FF0000) >> 16);
   451			}
   452		}
   453	}
   454
diff mbox series

Patch

diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c
index f93a4efcee90..c29495f51684 100644
--- a/drivers/gpu/drm/drm_format_helper.c
+++ b/drivers/gpu/drm/drm_format_helper.c
@@ -20,6 +20,147 @@ 
 #include <drm/drm_print.h>
 #include <drm/drm_rect.h>
 
+static inline u16 drm_format_xrgb8888_to_rgb565(u32 pix)
+{
+	u16 val16;
+
+	pix = le32_to_cpu(pix);
+	val16 = ((pix & 0x00F80000) >> 8) |
+		((pix & 0x0000FC00) >> 5) |
+		((pix & 0x000000F8) >> 3);
+	return cpu_to_le16(val16);
+}
+
+static inline u16 drm_format_xrgb8888_to_rgba5551(u32 pix)
+{
+	u16 val16;
+
+	pix = le32_to_cpu(pix);
+	val16 = ((pix & 0x00f80000) >> 8) |
+		((pix & 0x0000f800) >> 5) |
+		((pix & 0x000000f8) >> 2) |
+		BIT(0); /* set alpha bit */
+	return cpu_to_le16(val16);
+}
+
+static inline u16 drm_format_xrgb8888_to_xrgb1555(u32 pix)
+{
+	u16 val16;
+
+	pix = le32_to_cpu(pix);
+	val16 = ((pix & 0x00f80000) >> 9) |
+		((pix & 0x0000f800) >> 6) |
+		((pix & 0x000000f8) >> 3);
+	return cpu_to_le16(val16);
+}
+
+static inline u16 drm_format_xrgb8888_to_argb1555(u32 pix)
+{
+	u16 val16;
+
+	pix = le32_to_cpu(pix);
+	val16 = BIT(15) | /* set alpha bit */
+		((pix & 0x00f80000) >> 9) |
+		((pix & 0x0000f800) >> 6) |
+		((pix & 0x000000f8) >> 3);
+	return cpu_to_le16(val16);
+}
+
+static inline u32 drm_format_xrgb8888_to_argb8888(u32 pix)
+{
+	u32 val32;
+
+	val32 = le32_to_cpu(pix);
+	val32 |= GENMASK(31, 24); /* fill alpha bits */
+	return cpu_to_le32(val32);
+}
+
+static inline u32 drm_format_xrgb8888_to_xbgr8888(u32 pix)
+{
+	u32 val32;
+
+	pix = le32_to_cpu(pix);
+	val32 = ((pix & 0x00ff0000) >> 16) <<  0 |
+		((pix & 0x0000ff00) >>  8) <<  8 |
+		((pix & 0x000000ff) >>  0) << 16 |
+		((pix & 0xff000000) >> 24) << 24;
+	return cpu_to_le32(val32);
+}
+
+static inline u32 drm_format_xrgb8888_to_abgr8888(u32 pix)
+{
+	u32 val32;
+
+	pix = le32_to_cpu(pix);
+	val32 = ((pix & 0x00ff0000) >> 16) <<  0 |
+		((pix & 0x0000ff00) >>  8) <<  8 |
+		((pix & 0x000000ff) >>  0) << 16 |
+		GENMASK(31, 24); /* fill alpha bits */
+	return cpu_to_le32(val32);
+}
+
+static inline u32 drm_format_xrgb8888_to_xrgb2101010(u32 pix)
+{
+	u32 val32;
+
+	pix = le32_to_cpu(pix);
+	val32 = ((pix & 0x000000FF) << 2) |
+		((pix & 0x0000FF00) << 4) |
+		((pix & 0x00FF0000) << 6);
+	pix = val32 | ((val32 >> 8) & 0x00300C03);
+	return cpu_to_le32(pix);
+}
+
+static inline u32 drm_format_xrgb8888_to_argb2101010(u32 pix)
+{
+	u32 val32;
+
+	pix = le32_to_cpu(pix);
+	val32 = ((pix & 0x000000FF) << 2) |
+		((pix & 0x0000FF00) << 4) |
+		((pix & 0x00FF0000) << 6);
+	pix = GENMASK(31, 30) | /* set alpha bits */
+	      val32 | ((val32 >> 8) & 0x00300c03);
+	return cpu_to_le32(pix);
+}
+
+/**
+ * drm_fb_convert_from_xrgb8888 - convert one pixel from xrgb8888 to the desired format
+ * @color: input color, in xrgb8888 format
+ * @format: output format
+ *
+ * Returns:
+ * Color in the format specified, casted to u32.
+ */
+u32 drm_fb_convert_from_xrgb8888(u32 color, u32 format)
+{
+	switch (format) {
+	case DRM_FORMAT_RGB565:
+		return drm_format_xrgb8888_to_rgb565(color);
+	case DRM_FORMAT_RGBA5551:
+		return drm_format_xrgb8888_to_rgba5551(color);
+	case DRM_FORMAT_XRGB1555:
+		return drm_format_xrgb8888_to_xrgb1555(color);
+	case DRM_FORMAT_ARGB1555:
+		return drm_format_xrgb8888_to_argb1555(color);
+	case DRM_FORMAT_RGB888:
+	case DRM_FORMAT_XRGB8888:
+		return color;
+	case DRM_FORMAT_ARGB8888:
+		return drm_format_xrgb8888_to_argb8888(color);
+	case DRM_FORMAT_XBGR8888:
+		return drm_format_xrgb8888_to_xbgr8888(color);
+	case DRM_FORMAT_XRGB2101010:
+		return drm_format_xrgb8888_to_xrgb2101010(color);
+	case DRM_FORMAT_ARGB2101010:
+		return drm_format_xrgb8888_to_argb2101010(color);
+	default:
+		WARN_ONCE(1, "Can't convert to %p4cc\n", &format);
+		return color;
+	}
+}
+EXPORT_SYMBOL(drm_fb_convert_from_xrgb8888);
+
 static unsigned int clip_offset(const struct drm_rect *clip, unsigned int pitch, unsigned int cpp)
 {
 	return clip->y1 * pitch + clip->x1 * cpp;
@@ -272,6 +413,188 @@  void drm_fb_swab(struct iosys_map *dst, const unsigned int *dst_pitch,
 }
 EXPORT_SYMBOL(drm_fb_swab);
 
+static void drm_fb_r1_to_16bit(struct iosys_map *dmap, unsigned int dpitch,
+			       const u8 *sbuf8, unsigned int spitch,
+			       unsigned int height, unsigned int width,
+			       u16 fg16, u16 bg16)
+{
+	unsigned int l, x;
+	u16 val16;
+
+	for (l = 0; l < height; l++) {
+		for (x = 0; x < width; x++) {
+			val16 = (sbuf8[(l * spitch) + x / 8] & (0x80 >> (x % 8))) ? fg16 : bg16;
+			iosys_map_wr(dmap, l * dpitch + x * sizeof(u16), u16, val16);
+		}
+	}
+}
+
+static void drm_fb_r1_to_24bit(struct iosys_map *dmap, unsigned int dpitch,
+			       const u8 *sbuf8, unsigned int spitch,
+			       unsigned int height, unsigned int width,
+			       u32 fg32, u32 bg32)
+{
+	unsigned int l, x;
+	u32 val32;
+
+	for (l = 0; l < height; l++) {
+		for (x = 0; x < width; x++) {
+			u32 off = l * dpitch + x * 3;
+
+			val32 = (sbuf8[(l * spitch) + x / 8] & (0x80 >> (x % 8))) ? fg32 : bg32;
+			val32 = le32_to_cpu(val32);
+
+			/* write blue-green-red to output in little endianness */
+			iosys_map_wr(dmap, off, u8, (val32 & 0x000000FF) >> 0);
+			iosys_map_wr(dmap, off + 1, u8, (val32 & 0x0000FF00) >> 8);
+			iosys_map_wr(dmap, off + 2, u8, (val32 & 0x00FF0000) >> 16);
+		}
+	}
+}
+
+static void drm_fb_r1_to_32bit(struct iosys_map *dmap, unsigned int dpitch,
+			       const u8 *sbuf8, unsigned int spitch,
+			       unsigned int height, unsigned int width,
+			       u32 fg32, u32 bg32)
+{
+	unsigned int l, x;
+	u32 val32;
+
+	for (l = 0; l < height; l++) {
+		for (x = 0; x < width; x++) {
+			val32 = (sbuf8[(l * spitch) + x / 8] & (0x80 >> (x % 8))) ? fg32 : bg32;
+			iosys_map_wr(dmap, l * dpitch + x * sizeof(u32), u32, val32);
+		}
+	}
+}
+
+/**
+ * drm_fb_blit_from_r1 - convert a monochrome image to a linear framebuffer
+ * @dmap: destination iosys_map
+ * @dpich: destination pitch in bytes
+ * @sbuf8: source buffer, in monochrome format, 8 pixels per byte.
+ * @spitch: source pitch in bytes
+ * @height: height of the image to copy, in pixels
+ * @width: width of the image to copy, in pixels
+ * @fg_color: foreground color, in destination format
+ * @bg_color: background color, in destination format
+ * @pixel_width: pixel width in bytes.
+ *
+ * This can be used to draw font which are monochrome images, to a framebuffer
+ * in other supported format.
+ */
+void drm_fb_blit_from_r1(struct iosys_map *dmap, unsigned int dpitch,
+			 const u8 *sbuf8, unsigned int spitch,
+			 unsigned int height, unsigned int width,
+			 u32 fg_color, u32 bg_color,
+			 unsigned int pixel_width)
+{
+	switch (pixel_width) {
+	case 2:
+		drm_fb_r1_to_16bit(dmap, dpitch, sbuf8, spitch,
+				   height, width, fg_color, bg_color);
+	break;
+	case 3:
+		drm_fb_r1_to_24bit(dmap, dpitch, sbuf8, spitch,
+				   height, width, fg_color, bg_color);
+	break;
+	case 4:
+		drm_fb_r1_to_32bit(dmap, dpitch, sbuf8, spitch,
+				   height, width, fg_color, bg_color);
+	break;
+	default:
+		WARN_ONCE(1, "Can't blit with pixel width %d\n", pixel_width);
+	}
+}
+EXPORT_SYMBOL(drm_fb_blit_from_r1);
+
+static void drm_fb_fill8(struct iosys_map *dmap, unsigned int dpitch,
+			 unsigned int height, unsigned int width,
+			 u8 color)
+{
+	unsigned int l, x;
+
+	for (l = 0; l < height; l++)
+		for (x = 0; x < width; x++)
+			iosys_map_wr(dmap, l * dpitch + x * sizeof(u8), u8, color);
+}
+
+static void drm_fb_fill16(struct iosys_map *dmap, unsigned int dpitch,
+			  unsigned int height, unsigned int width,
+			  u16 color)
+{
+	unsigned int l, x;
+
+	for (l = 0; l < height; l++)
+		for (x = 0; x < width; x++)
+			iosys_map_wr(dmap, l * dpitch + x * sizeof(u16), u16, color);
+}
+
+static void drm_fb_fill24(struct iosys_map *dmap, unsigned int dpitch,
+			  unsigned int height, unsigned int width,
+			  u32 color)
+{
+	unsigned int l, x;
+
+	for (l = 0; l < height; l++) {
+		for (x = 0; x < width; x++) {
+			unsigned int off = l * dpitch + x * 3;
+			u32 val32 = le32_to_cpu(color);
+
+			/* write blue-green-red to output in little endianness */
+			iosys_map_wr(dmap, off, u8, (val32 & 0x000000FF) >> 0);
+			iosys_map_wr(dmap, off + 1, u8, (val32 & 0x0000FF00) >> 8);
+			iosys_map_wr(dmap, off + 2, u8, (val32 & 0x00FF0000) >> 16);
+		}
+	}
+}
+
+static void drm_fb_fill32(struct iosys_map *dmap, unsigned int dpitch,
+			  unsigned int height, unsigned int width,
+			  u32 color)
+{
+	unsigned int l, x;
+
+	for (l = 0; l < height; l++)
+		for (x = 0; x < width; x++)
+			iosys_map_wr(dmap, l * dpitch + x * sizeof(u32), u32, color);
+}
+
+/**
+ * drm_fb_fill - Fill a rectangle with a color
+ * @dmap: destination iosys_map, pointing to the top left corner of the rectangle
+ * @dpich: destination pitch in bytes
+ * @height: height of the rectangle, in pixels
+ * @width: width of the rectangle, in pixels
+ * @fg_color: foreground color, in destination format
+ * @bg_color: background color, in destination format
+ * @pixel_width: pixel width in bytes
+ *
+ * Fill a rectangle with a color, in a linear framebuffer.
+ */
+void drm_fb_fill(struct iosys_map *dmap, unsigned int dpitch,
+			 unsigned int height, unsigned int width,
+			 u32 color, unsigned int pixel_width)
+{
+	switch (pixel_width) {
+	case 1:
+		drm_fb_fill8(dmap, dpitch, height, width, color);
+	break;
+	case 2:
+		drm_fb_fill16(dmap, dpitch, height, width, color);
+	break;
+	case 3:
+		drm_fb_fill24(dmap, dpitch, height, width, color);
+	break;
+	case 4:
+		drm_fb_fill32(dmap, dpitch, height, width, color);
+	break;
+	default:
+		WARN_ONCE(1, "Can't fill with pixel width %d\n", pixel_width);
+	}
+}
+EXPORT_SYMBOL(drm_fb_fill);
+
 static void drm_fb_xrgb8888_to_rgb332_line(void *dbuf, const void *sbuf, unsigned int pixels)
 {
 	u8 *dbuf8 = dbuf;
@@ -325,15 +648,9 @@  static void drm_fb_xrgb8888_to_rgb565_line(void *dbuf, const void *sbuf, unsigne
 	__le16 *dbuf16 = dbuf;
 	const __le32 *sbuf32 = sbuf;
 	unsigned int x;
-	u16 val16;
-	u32 pix;
 
 	for (x = 0; x < pixels; x++) {
-		pix = le32_to_cpu(sbuf32[x]);
-		val16 = ((pix & 0x00F80000) >> 8) |
-			((pix & 0x0000FC00) >> 5) |
-			((pix & 0x000000F8) >> 3);
-		dbuf16[x] = cpu_to_le16(val16);
+		dbuf16[x] = drm_format_xrgb8888_to_rgb565(sbuf32[x]);
 	}
 }
 
@@ -401,16 +718,9 @@  static void drm_fb_xrgb8888_to_xrgb1555_line(void *dbuf, const void *sbuf, unsig
 	__le16 *dbuf16 = dbuf;
 	const __le32 *sbuf32 = sbuf;
 	unsigned int x;
-	u16 val16;
-	u32 pix;
 
-	for (x = 0; x < pixels; x++) {
-		pix = le32_to_cpu(sbuf32[x]);
-		val16 = ((pix & 0x00f80000) >> 9) |
-			((pix & 0x0000f800) >> 6) |
-			((pix & 0x000000f8) >> 3);
-		dbuf16[x] = cpu_to_le16(val16);
-	}
+	for (x = 0; x < pixels; x++)
+		dbuf16[x] = drm_format_xrgb8888_to_xrgb1555(sbuf32[x]);
 }
 
 /**
@@ -452,17 +762,9 @@  static void drm_fb_xrgb8888_to_argb1555_line(void *dbuf, const void *sbuf, unsig
 	__le16 *dbuf16 = dbuf;
 	const __le32 *sbuf32 = sbuf;
 	unsigned int x;
-	u16 val16;
-	u32 pix;
 
-	for (x = 0; x < pixels; x++) {
-		pix = le32_to_cpu(sbuf32[x]);
-		val16 = BIT(15) | /* set alpha bit */
-			((pix & 0x00f80000) >> 9) |
-			((pix & 0x0000f800) >> 6) |
-			((pix & 0x000000f8) >> 3);
-		dbuf16[x] = cpu_to_le16(val16);
-	}
+	for (x = 0; x < pixels; x++)
+		dbuf16[x] = drm_format_xrgb8888_to_argb1555(sbuf32[x]);
 }
 
 /**
@@ -504,17 +806,9 @@  static void drm_fb_xrgb8888_to_rgba5551_line(void *dbuf, const void *sbuf, unsig
 	__le16 *dbuf16 = dbuf;
 	const __le32 *sbuf32 = sbuf;
 	unsigned int x;
-	u16 val16;
-	u32 pix;
 
-	for (x = 0; x < pixels; x++) {
-		pix = le32_to_cpu(sbuf32[x]);
-		val16 = ((pix & 0x00f80000) >> 8) |
-			((pix & 0x0000f800) >> 5) |
-			((pix & 0x000000f8) >> 2) |
-			BIT(0); /* set alpha bit */
-		dbuf16[x] = cpu_to_le16(val16);
-	}
+	for (x = 0; x < pixels; x++)
+		dbuf16[x] = drm_format_xrgb8888_to_rgba5551(sbuf32[x]);
 }
 
 /**
@@ -606,13 +900,9 @@  static void drm_fb_xrgb8888_to_argb8888_line(void *dbuf, const void *sbuf, unsig
 	__le32 *dbuf32 = dbuf;
 	const __le32 *sbuf32 = sbuf;
 	unsigned int x;
-	u32 pix;
 
-	for (x = 0; x < pixels; x++) {
-		pix = le32_to_cpu(sbuf32[x]);
-		pix |= GENMASK(31, 24); /* fill alpha bits */
-		dbuf32[x] = cpu_to_le32(pix);
-	}
+	for (x = 0; x < pixels; x++)
+		dbuf32[x] = drm_format_xrgb8888_to_argb8888(sbuf32[x]);
 }
 
 /**
@@ -654,16 +944,9 @@  static void drm_fb_xrgb8888_to_abgr8888_line(void *dbuf, const void *sbuf, unsig
 	__le32 *dbuf32 = dbuf;
 	const __le32 *sbuf32 = sbuf;
 	unsigned int x;
-	u32 pix;
 
-	for (x = 0; x < pixels; x++) {
-		pix = le32_to_cpu(sbuf32[x]);
-		pix = ((pix & 0x00ff0000) >> 16) <<  0 |
-		      ((pix & 0x0000ff00) >>  8) <<  8 |
-		      ((pix & 0x000000ff) >>  0) << 16 |
-		      GENMASK(31, 24); /* fill alpha bits */
-		*dbuf32++ = cpu_to_le32(pix);
-	}
+	for (x = 0; x < pixels; x++)
+		*dbuf32++ = drm_format_xrgb8888_to_abgr8888(sbuf32[x]);
 }
 
 static void drm_fb_xrgb8888_to_abgr8888(struct iosys_map *dst, const unsigned int *dst_pitch,
@@ -684,16 +967,9 @@  static void drm_fb_xrgb8888_to_xbgr8888_line(void *dbuf, const void *sbuf, unsig
 	__le32 *dbuf32 = dbuf;
 	const __le32 *sbuf32 = sbuf;
 	unsigned int x;
-	u32 pix;
 
-	for (x = 0; x < pixels; x++) {
-		pix = le32_to_cpu(sbuf32[x]);
-		pix = ((pix & 0x00ff0000) >> 16) <<  0 |
-		      ((pix & 0x0000ff00) >>  8) <<  8 |
-		      ((pix & 0x000000ff) >>  0) << 16 |
-		      ((pix & 0xff000000) >> 24) << 24;
-		*dbuf32++ = cpu_to_le32(pix);
-	}
+	for (x = 0; x < pixels; x++)
+		*dbuf32++ = drm_format_xrgb8888_to_xbgr8888(sbuf32[x]);
 }
 
 static void drm_fb_xrgb8888_to_xbgr8888(struct iosys_map *dst, const unsigned int *dst_pitch,
@@ -714,17 +990,9 @@  static void drm_fb_xrgb8888_to_xrgb2101010_line(void *dbuf, const void *sbuf, un
 	__le32 *dbuf32 = dbuf;
 	const __le32 *sbuf32 = sbuf;
 	unsigned int x;
-	u32 val32;
-	u32 pix;
 
-	for (x = 0; x < pixels; x++) {
-		pix = le32_to_cpu(sbuf32[x]);
-		val32 = ((pix & 0x000000FF) << 2) |
-			((pix & 0x0000FF00) << 4) |
-			((pix & 0x00FF0000) << 6);
-		pix = val32 | ((val32 >> 8) & 0x00300C03);
-		*dbuf32++ = cpu_to_le32(pix);
-	}
+	for (x = 0; x < pixels; x++)
+		*dbuf32++ = drm_format_xrgb8888_to_xrgb2101010(sbuf32[x]);
 }
 
 /**
@@ -766,18 +1034,9 @@  static void drm_fb_xrgb8888_to_argb2101010_line(void *dbuf, const void *sbuf, un
 	__le32 *dbuf32 = dbuf;
 	const __le32 *sbuf32 = sbuf;
 	unsigned int x;
-	u32 val32;
-	u32 pix;
 
-	for (x = 0; x < pixels; x++) {
-		pix = le32_to_cpu(sbuf32[x]);
-		val32 = ((pix & 0x000000ff) << 2) |
-			((pix & 0x0000ff00) << 4) |
-			((pix & 0x00ff0000) << 6);
-		pix = GENMASK(31, 30) | /* set alpha bits */
-		      val32 | ((val32 >> 8) & 0x00300c03);
-		*dbuf32++ = cpu_to_le32(pix);
-	}
+	for (x = 0; x < pixels; x++)
+		*dbuf32++ = drm_format_xrgb8888_to_argb2101010(sbuf32[x]);
 }
 
 /**
diff --git a/include/drm/drm_format_helper.h b/include/drm/drm_format_helper.h
index 291deb09475b..7881cd46b9cc 100644
--- a/include/drm/drm_format_helper.h
+++ b/include/drm/drm_format_helper.h
@@ -15,6 +15,7 @@  struct drm_rect;
 
 struct iosys_map;
 
+u32 drm_fb_convert_from_xrgb8888(u32 color, u32 format);
 unsigned int drm_fb_clip_offset(unsigned int pitch, const struct drm_format_info *format,
 				const struct drm_rect *clip);
 
@@ -24,6 +25,14 @@  void drm_fb_memcpy(struct iosys_map *dst, const unsigned int *dst_pitch,
 void drm_fb_swab(struct iosys_map *dst, const unsigned int *dst_pitch,
 		 const struct iosys_map *src, const struct drm_framebuffer *fb,
 		 const struct drm_rect *clip, bool cached);
+void drm_fb_blit_from_r1(struct iosys_map *dmap, unsigned int dpitch,
+			 const u8 *sbuf8, unsigned int spitch,
+			 unsigned int height, unsigned int width,
+			 u32 fg_color, u32 bg_color,
+			 unsigned int pixel_width);
+void drm_fb_fill(struct iosys_map *dmap, unsigned int dpitch,
+		 unsigned int height, unsigned int width,
+		 u32 color, unsigned int pixel_width);
 void drm_fb_xrgb8888_to_rgb332(struct iosys_map *dst, const unsigned int *dst_pitch,
 			       const struct iosys_map *src, const struct drm_framebuffer *fb,
 			       const struct drm_rect *clip);