1 // SPDX-License-Identifier: GPL-2.0 or MIT 2 /* 3 * Copyright (c) 2023 Red Hat. 4 * Author: Jocelyn Falempe <jfalempe@redhat.com> 5 */ 6 7 #include <linux/bits.h> 8 #include <linux/bug.h> 9 #include <linux/export.h> 10 #include <linux/iosys-map.h> 11 #include <linux/types.h> 12 13 #include <drm/drm_fourcc.h> 14 15 #include "drm_draw_internal.h" 16 17 /* 18 * Conversions from xrgb8888 19 */ 20 21 static u16 convert_xrgb8888_to_rgb565(u32 pix) 22 { 23 return ((pix & 0x00F80000) >> 8) | 24 ((pix & 0x0000FC00) >> 5) | 25 ((pix & 0x000000F8) >> 3); 26 } 27 28 static u16 convert_xrgb8888_to_rgba5551(u32 pix) 29 { 30 return ((pix & 0x00f80000) >> 8) | 31 ((pix & 0x0000f800) >> 5) | 32 ((pix & 0x000000f8) >> 2) | 33 BIT(0); /* set alpha bit */ 34 } 35 36 static u16 convert_xrgb8888_to_xrgb1555(u32 pix) 37 { 38 return ((pix & 0x00f80000) >> 9) | 39 ((pix & 0x0000f800) >> 6) | 40 ((pix & 0x000000f8) >> 3); 41 } 42 43 static u16 convert_xrgb8888_to_argb1555(u32 pix) 44 { 45 return BIT(15) | /* set alpha bit */ 46 ((pix & 0x00f80000) >> 9) | 47 ((pix & 0x0000f800) >> 6) | 48 ((pix & 0x000000f8) >> 3); 49 } 50 51 static u32 convert_xrgb8888_to_argb8888(u32 pix) 52 { 53 return pix | GENMASK(31, 24); /* fill alpha bits */ 54 } 55 56 static u32 convert_xrgb8888_to_xbgr8888(u32 pix) 57 { 58 return ((pix & 0x00ff0000) >> 16) << 0 | 59 ((pix & 0x0000ff00) >> 8) << 8 | 60 ((pix & 0x000000ff) >> 0) << 16 | 61 ((pix & 0xff000000) >> 24) << 24; 62 } 63 64 static u32 convert_xrgb8888_to_abgr8888(u32 pix) 65 { 66 return ((pix & 0x00ff0000) >> 16) << 0 | 67 ((pix & 0x0000ff00) >> 8) << 8 | 68 ((pix & 0x000000ff) >> 0) << 16 | 69 GENMASK(31, 24); /* fill alpha bits */ 70 } 71 72 static u32 convert_xrgb8888_to_xrgb2101010(u32 pix) 73 { 74 pix = ((pix & 0x000000FF) << 2) | 75 ((pix & 0x0000FF00) << 4) | 76 ((pix & 0x00FF0000) << 6); 77 return pix | ((pix >> 8) & 0x00300C03); 78 } 79 80 static u32 convert_xrgb8888_to_argb2101010(u32 pix) 81 { 82 pix = ((pix & 0x000000FF) << 2) | 83 ((pix & 0x0000FF00) << 4) | 84 ((pix & 0x00FF0000) << 6); 85 return GENMASK(31, 30) /* set alpha bits */ | pix | ((pix >> 8) & 0x00300C03); 86 } 87 88 static u32 convert_xrgb8888_to_abgr2101010(u32 pix) 89 { 90 pix = ((pix & 0x00FF0000) >> 14) | 91 ((pix & 0x0000FF00) << 4) | 92 ((pix & 0x000000FF) << 22); 93 return GENMASK(31, 30) /* set alpha bits */ | pix | ((pix >> 8) & 0x00300C03); 94 } 95 96 /** 97 * drm_draw_color_from_xrgb8888 - convert one pixel from xrgb8888 to the desired format 98 * @color: input color, in xrgb8888 format 99 * @format: output format 100 * 101 * Returns: 102 * Color in the format specified, casted to u32. 103 * Or 0 if the format is not supported. 104 */ 105 u32 drm_draw_color_from_xrgb8888(u32 color, u32 format) 106 { 107 switch (format) { 108 case DRM_FORMAT_RGB565: 109 return convert_xrgb8888_to_rgb565(color); 110 case DRM_FORMAT_RGBA5551: 111 return convert_xrgb8888_to_rgba5551(color); 112 case DRM_FORMAT_XRGB1555: 113 return convert_xrgb8888_to_xrgb1555(color); 114 case DRM_FORMAT_ARGB1555: 115 return convert_xrgb8888_to_argb1555(color); 116 case DRM_FORMAT_RGB888: 117 case DRM_FORMAT_XRGB8888: 118 return color; 119 case DRM_FORMAT_ARGB8888: 120 return convert_xrgb8888_to_argb8888(color); 121 case DRM_FORMAT_XBGR8888: 122 return convert_xrgb8888_to_xbgr8888(color); 123 case DRM_FORMAT_ABGR8888: 124 return convert_xrgb8888_to_abgr8888(color); 125 case DRM_FORMAT_XRGB2101010: 126 return convert_xrgb8888_to_xrgb2101010(color); 127 case DRM_FORMAT_ARGB2101010: 128 return convert_xrgb8888_to_argb2101010(color); 129 case DRM_FORMAT_ABGR2101010: 130 return convert_xrgb8888_to_abgr2101010(color); 131 default: 132 WARN_ONCE(1, "Can't convert to %p4cc\n", &format); 133 return 0; 134 } 135 } 136 EXPORT_SYMBOL(drm_draw_color_from_xrgb8888); 137 138 /* 139 * Blit functions 140 */ 141 void drm_draw_blit16(struct iosys_map *dmap, unsigned int dpitch, 142 const u8 *sbuf8, unsigned int spitch, 143 unsigned int height, unsigned int width, 144 unsigned int scale, u16 fg16) 145 { 146 unsigned int y, x; 147 148 for (y = 0; y < height; y++) 149 for (x = 0; x < width; x++) 150 if (drm_draw_is_pixel_fg(sbuf8, spitch, x / scale, y / scale)) 151 iosys_map_wr(dmap, y * dpitch + x * sizeof(u16), u16, fg16); 152 } 153 EXPORT_SYMBOL(drm_draw_blit16); 154 155 void drm_draw_blit24(struct iosys_map *dmap, unsigned int dpitch, 156 const u8 *sbuf8, unsigned int spitch, 157 unsigned int height, unsigned int width, 158 unsigned int scale, u32 fg32) 159 { 160 unsigned int y, x; 161 162 for (y = 0; y < height; y++) { 163 for (x = 0; x < width; x++) { 164 u32 off = y * dpitch + x * 3; 165 166 if (drm_draw_is_pixel_fg(sbuf8, spitch, x / scale, y / scale)) { 167 /* write blue-green-red to output in little endianness */ 168 iosys_map_wr(dmap, off, u8, (fg32 & 0x000000FF) >> 0); 169 iosys_map_wr(dmap, off + 1, u8, (fg32 & 0x0000FF00) >> 8); 170 iosys_map_wr(dmap, off + 2, u8, (fg32 & 0x00FF0000) >> 16); 171 } 172 } 173 } 174 } 175 EXPORT_SYMBOL(drm_draw_blit24); 176 177 void drm_draw_blit32(struct iosys_map *dmap, unsigned int dpitch, 178 const u8 *sbuf8, unsigned int spitch, 179 unsigned int height, unsigned int width, 180 unsigned int scale, u32 fg32) 181 { 182 unsigned int y, x; 183 184 for (y = 0; y < height; y++) 185 for (x = 0; x < width; x++) 186 if (drm_draw_is_pixel_fg(sbuf8, spitch, x / scale, y / scale)) 187 iosys_map_wr(dmap, y * dpitch + x * sizeof(u32), u32, fg32); 188 } 189 EXPORT_SYMBOL(drm_draw_blit32); 190 191 /* 192 * Fill functions 193 */ 194 void drm_draw_fill16(struct iosys_map *dmap, unsigned int dpitch, 195 unsigned int height, unsigned int width, 196 u16 color) 197 { 198 unsigned int y, x; 199 200 for (y = 0; y < height; y++) 201 for (x = 0; x < width; x++) 202 iosys_map_wr(dmap, y * dpitch + x * sizeof(u16), u16, color); 203 } 204 EXPORT_SYMBOL(drm_draw_fill16); 205 206 void drm_draw_fill24(struct iosys_map *dmap, unsigned int dpitch, 207 unsigned int height, unsigned int width, 208 u16 color) 209 { 210 unsigned int y, x; 211 212 for (y = 0; y < height; y++) { 213 for (x = 0; x < width; x++) { 214 unsigned int off = y * dpitch + x * 3; 215 216 /* write blue-green-red to output in little endianness */ 217 iosys_map_wr(dmap, off, u8, (color & 0x000000FF) >> 0); 218 iosys_map_wr(dmap, off + 1, u8, (color & 0x0000FF00) >> 8); 219 iosys_map_wr(dmap, off + 2, u8, (color & 0x00FF0000) >> 16); 220 } 221 } 222 } 223 EXPORT_SYMBOL(drm_draw_fill24); 224 225 void drm_draw_fill32(struct iosys_map *dmap, unsigned int dpitch, 226 unsigned int height, unsigned int width, 227 u32 color) 228 { 229 unsigned int y, x; 230 231 for (y = 0; y < height; y++) 232 for (x = 0; x < width; x++) 233 iosys_map_wr(dmap, y * dpitch + x * sizeof(u32), u32, color); 234 } 235 EXPORT_SYMBOL(drm_draw_fill32); 236