xref: /OK3568_Linux_fs/kernel/drivers/gpu/drm/rockchip/rockchip_drm_display_pattern.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 // SPDX-License-Identifier: (GPL-2.0+ OR MIT)
2 /*
3  * Copyright (c) 2022 Rockchip Electronics Co., Ltd.
4  * Author: Sandy Huang <hjc@rock-chips.com>
5  */
6 
7 #include "rockchip_drm_display_pattern.h"
8 
9 #define MAKE_RGB_INFO(rl, ro, gl, go, bl, bo, al, ao) \
10 	.rgb = { { (rl), (ro) }, { (gl), (go) }, { (bl), (bo) }, { (al), (ao) } }
11 
12 #define MAKE_YUV_INFO(order, xsub, ysub, chroma_stride) \
13 	.yuv = { (order), (xsub), (ysub), (chroma_stride) }
14 
15 struct color_rgb24 {
16 	unsigned int value : 24;
17 } __attribute__((__packed__));
18 
19 struct color_yuv {
20 	unsigned char y;
21 	unsigned char u;
22 	unsigned char v;
23 };
24 
25 #define MAKE_YUV_601_Y(r, g, b) \
26 	(((66 * (r) + 129 * (g) +  25 * (b) + 128) >> 8) + 16)
27 #define MAKE_YUV_601_U(r, g, b) \
28 	(((-38 * (r) -  74 * (g) + 112 * (b) + 128) >> 8) + 128)
29 #define MAKE_YUV_601_V(r, g, b) \
30 	(((112 * (r) -  94 * (g) -  18 * (b) + 128) >> 8) + 128)
31 
32 #define MAKE_YUV_601(r, g, b) \
33 	{ .y = MAKE_YUV_601_Y(r, g, b), \
34 	  .u = MAKE_YUV_601_U(r, g, b), \
35 	  .v = MAKE_YUV_601_V(r, g, b) }
36 
37 #define MAKE_RGBA(rgb, r, g, b, a) \
38 	((((r) >> (8 - (rgb)->red.length)) << (rgb)->red.offset) | \
39 	 (((g) >> (8 - (rgb)->green.length)) << (rgb)->green.offset) | \
40 	 (((b) >> (8 - (rgb)->blue.length)) << (rgb)->blue.offset) | \
41 	 (((a) >> (8 - (rgb)->alpha.length)) << (rgb)->alpha.offset))
42 
43 #define MAKE_RGB24(rgb, r, g, b) { .value = MAKE_RGBA(rgb, r, g, b, 0) }
44 
45 static const struct util_format_info format_info[] = {
46 	/* YUV semi-planar */
47 	{ DRM_FORMAT_NV12, "NV12", MAKE_YUV_INFO(YUV_YCbCr, 2, 2, 2) },
48 	{ DRM_FORMAT_NV21, "NV21", MAKE_YUV_INFO(YUV_YCrCb, 2, 2, 2) },
49 	{ DRM_FORMAT_NV16, "NV16", MAKE_YUV_INFO(YUV_YCbCr, 2, 1, 2) },
50 	{ DRM_FORMAT_NV61, "NV61", MAKE_YUV_INFO(YUV_YCrCb, 2, 1, 2) },
51 	/* RGB565 */
52 	{ DRM_FORMAT_RGB565, "RG16", MAKE_RGB_INFO(5, 11, 6, 5, 5, 0, 0, 0) },
53 	{ DRM_FORMAT_BGR565, "BG16", MAKE_RGB_INFO(5, 0, 6, 5, 5, 11, 0, 0) },
54 	/* RGB888 */
55 	{ DRM_FORMAT_BGR888, "BG24", MAKE_RGB_INFO(8, 0, 8, 8, 8, 16, 0, 0) },
56 	{ DRM_FORMAT_RGB888, "RG24", MAKE_RGB_INFO(8, 16, 8, 8, 8, 0, 0, 0) },
57 	/* ARGB8888 */
58 	{ DRM_FORMAT_ARGB8888, "AR24", MAKE_RGB_INFO(8, 16, 8, 8, 8, 0, 8, 24) },
59 	{ DRM_FORMAT_XRGB8888, "XR24", MAKE_RGB_INFO(8, 16, 8, 8, 8, 0, 0, 0) },
60 	{ DRM_FORMAT_ABGR8888, "AB24", MAKE_RGB_INFO(8, 0, 8, 8, 8, 16, 8, 24) },
61 	{ DRM_FORMAT_XBGR8888, "XB24", MAKE_RGB_INFO(8, 0, 8, 8, 8, 16, 0, 0) },
62 	{ DRM_FORMAT_RGBA8888, "RA24", MAKE_RGB_INFO(8, 24, 8, 16, 8, 8, 8, 0) },
63 	{ DRM_FORMAT_RGBX8888, "RX24", MAKE_RGB_INFO(8, 24, 8, 16, 8, 8, 0, 0) },
64 	{ DRM_FORMAT_BGRA8888, "BA24", MAKE_RGB_INFO(8, 8, 8, 16, 8, 24, 8, 0) },
65 	{ DRM_FORMAT_BGRX8888, "BX24", MAKE_RGB_INFO(8, 8, 8, 16, 8, 24, 0, 0) },
66 };
67 
util_format_info_find(uint32_t format)68 static const struct util_format_info *util_format_info_find(uint32_t format)
69 {
70 	unsigned int i;
71 
72 	for (i = 0; i < ARRAY_SIZE(format_info); i++)
73 		if (format_info[i].format == format)
74 			return &format_info[i];
75 
76 	return NULL;
77 }
78 #define MAKE_RGB24(rgb, r, g, b) \
79 	{ .value = MAKE_RGBA(rgb, r, g, b, 0) }
80 
fill_smpte_yuv_planar(const struct util_yuv_info * yuv,unsigned char * y_mem,unsigned char * u_mem,unsigned char * v_mem,unsigned int width,unsigned int height,unsigned int stride)81 static void fill_smpte_yuv_planar(const struct util_yuv_info *yuv,
82 				  unsigned char *y_mem, unsigned char *u_mem,
83 				  unsigned char *v_mem, unsigned int width,
84 				  unsigned int height, unsigned int stride)
85 {
86 	const struct color_yuv colors_top[] = {
87 		MAKE_YUV_601(191, 192, 192),	/* grey */
88 		MAKE_YUV_601(192, 192, 0),	/* yellow */
89 		MAKE_YUV_601(0, 192, 192),	/* cyan */
90 		MAKE_YUV_601(0, 192, 0),	/* green */
91 		MAKE_YUV_601(192, 0, 192),	/* magenta */
92 		MAKE_YUV_601(192, 0, 0),	/* red */
93 		MAKE_YUV_601(0, 0, 192),	/* blue */
94 	};
95 	const struct color_yuv colors_middle[] = {
96 		MAKE_YUV_601(0, 0, 192),	/* blue */
97 		MAKE_YUV_601(19, 19, 19),	/* black */
98 		MAKE_YUV_601(192, 0, 192),	/* magenta */
99 		MAKE_YUV_601(19, 19, 19),	/* black */
100 		MAKE_YUV_601(0, 192, 192),	/* cyan */
101 		MAKE_YUV_601(19, 19, 19),	/* black */
102 		MAKE_YUV_601(192, 192, 192),	/* grey */
103 	};
104 	const struct color_yuv colors_bottom[] = {
105 		MAKE_YUV_601(0, 33, 76),	/* in-phase */
106 		MAKE_YUV_601(255, 255, 255),	/* super white */
107 		MAKE_YUV_601(50, 0, 106),	/* quadrature */
108 		MAKE_YUV_601(19, 19, 19),	/* black */
109 		MAKE_YUV_601(9, 9, 9),		/* 3.5% */
110 		MAKE_YUV_601(19, 19, 19),	/* 7.5% */
111 		MAKE_YUV_601(29, 29, 29),	/* 11.5% */
112 		MAKE_YUV_601(19, 19, 19),	/* black */
113 	};
114 	unsigned int cs = yuv->chroma_stride;
115 	unsigned int xsub = yuv->xsub;
116 	unsigned int ysub = yuv->ysub;
117 	unsigned int x;
118 	unsigned int y;
119 
120 	/* Luma */
121 	for (y = 0; y < height * 6 / 9; ++y) {
122 		for (x = 0; x < width; ++x)
123 			y_mem[x] = colors_top[x * 7 / width].y;
124 		y_mem += stride;
125 	}
126 
127 	for (; y < height * 7 / 9; ++y) {
128 		for (x = 0; x < width; ++x)
129 			y_mem[x] = colors_middle[x * 7 / width].y;
130 		y_mem += stride;
131 	}
132 
133 	for (; y < height; ++y) {
134 		for (x = 0; x < width * 5 / 7; ++x)
135 			y_mem[x] = colors_bottom[x * 4 / (width * 5 / 7)].y;
136 		for (; x < width * 6 / 7; ++x)
137 			y_mem[x] = colors_bottom[(x - width * 5 / 7) * 3 / (width / 7) + 4].y;
138 		for (; x < width; ++x)
139 			y_mem[x] = colors_bottom[7].y;
140 		y_mem += stride;
141 	}
142 
143 	/* Chroma */
144 	for (y = 0; y < height / ysub * 6 / 9; ++y) {
145 		for (x = 0; x < width; x += xsub) {
146 			u_mem[x * cs / xsub] = colors_top[x * 7 / width].u;
147 			v_mem[x * cs / xsub] = colors_top[x * 7 / width].v;
148 		}
149 		u_mem += stride * cs / xsub;
150 		v_mem += stride * cs / xsub;
151 	}
152 
153 	for (; y < height / ysub * 7 / 9; ++y) {
154 		for (x = 0; x < width; x += xsub) {
155 			u_mem[x * cs / xsub] = colors_middle[x * 7 / width].u;
156 			v_mem[x * cs / xsub] = colors_middle[x * 7 / width].v;
157 		}
158 		u_mem += stride * cs / xsub;
159 		v_mem += stride * cs / xsub;
160 	}
161 
162 	for (; y < height / ysub; ++y) {
163 		for (x = 0; x < width * 5 / 7; x += xsub) {
164 			u_mem[x * cs / xsub] =
165 			colors_bottom[x * 4 / (width * 5 / 7)].u;
166 			v_mem[x * cs / xsub] =
167 			colors_bottom[x * 4 / (width * 5 / 7)].v;
168 		}
169 		for (; x < width * 6 / 7; x += xsub) {
170 			u_mem[x * cs / xsub] = colors_bottom[(x - width * 5 / 7) * 3 / (width / 7) + 4].u;
171 			v_mem[x * cs / xsub] = colors_bottom[(x - width * 5 / 7) * 3 / (width / 7) + 4].v;
172 		}
173 		for (; x < width; x += xsub) {
174 			u_mem[x * cs / xsub] = colors_bottom[7].u;
175 			v_mem[x * cs / xsub] = colors_bottom[7].v;
176 		}
177 		u_mem += stride * cs / xsub;
178 		v_mem += stride * cs / xsub;
179 	}
180 }
181 
fill_smpte_rgb16(const struct util_rgb_info * rgb,void * mem,unsigned int width,unsigned int height,unsigned int stride)182 static void fill_smpte_rgb16(const struct util_rgb_info *rgb, void *mem,
183 			     unsigned int width, unsigned int height,
184 			     unsigned int stride)
185 {
186 	unsigned int x;
187 	unsigned int y;
188 
189 	const uint16_t colors_top[] = {
190 		MAKE_RGBA(rgb, 192, 192, 192, 255),	/* grey */
191 		MAKE_RGBA(rgb, 192, 192, 0, 255),	/* yellow */
192 		MAKE_RGBA(rgb, 0, 192, 192, 255),	/* cyan */
193 		MAKE_RGBA(rgb, 0, 192, 0, 255),		/* green */
194 		MAKE_RGBA(rgb, 192, 0, 192, 255),	/* magenta */
195 		MAKE_RGBA(rgb, 192, 0, 0, 255),		/* red */
196 		MAKE_RGBA(rgb, 0, 0, 192, 255),		/* blue */
197 	};
198 	const uint16_t colors_middle[] = {
199 		MAKE_RGBA(rgb, 0, 0, 192, 127),		/* blue */
200 		MAKE_RGBA(rgb, 19, 19, 19, 127),	/* black */
201 		MAKE_RGBA(rgb, 192, 0, 192, 127),	/* magenta */
202 		MAKE_RGBA(rgb, 19, 19, 19, 127),	/* black */
203 		MAKE_RGBA(rgb, 0, 192, 192, 127),	/* cyan */
204 		MAKE_RGBA(rgb, 19, 19, 19, 127),	/* black */
205 		MAKE_RGBA(rgb, 192, 192, 192, 127),	/* grey */
206 	};
207 	const uint16_t colors_bottom[] = {
208 		MAKE_RGBA(rgb, 0, 33, 76, 255),		/* in-phase */
209 		MAKE_RGBA(rgb, 255, 255, 255, 255),	/* super white */
210 		MAKE_RGBA(rgb, 50, 0, 106, 255),	/* quadrature */
211 		MAKE_RGBA(rgb, 19, 19, 19, 255),	/* black */
212 		MAKE_RGBA(rgb, 9, 9, 9, 255),		/* 3.5% */
213 		MAKE_RGBA(rgb, 19, 19, 19, 255),	/* 7.5% */
214 		MAKE_RGBA(rgb, 29, 29, 29, 255),	/* 11.5% */
215 		MAKE_RGBA(rgb, 19, 19, 19, 255),	/* black */
216 	};
217 
218 	for (y = 0; y < height * 6 / 9; ++y) {
219 		for (x = 0; x < width; ++x)
220 			((uint16_t *)mem)[x] = colors_top[x * 7 / width];
221 		mem += stride;
222 	}
223 
224 	for (; y < height * 7 / 9; ++y) {
225 		for (x = 0; x < width; ++x)
226 			((uint16_t *)mem)[x] = colors_middle[x * 7 / width];
227 		mem += stride;
228 	}
229 
230 	for (; y < height; ++y) {
231 		for (x = 0; x < width * 5 / 7; ++x)
232 			((uint16_t *)mem)[x] =
233 				colors_bottom[x * 4 / (width * 5 / 7)];
234 		for (; x < width * 6 / 7; ++x)
235 			((uint16_t *)mem)[x] =
236 			colors_bottom[(x - width * 5 / 7) * 3 / (width / 7) + 4];
237 		for (; x < width; ++x)
238 			((uint16_t *)mem)[x] = colors_bottom[7];
239 		mem += stride;
240 	}
241 }
242 
fill_smpte_rgb24(const struct util_rgb_info * rgb,void * mem,unsigned int width,unsigned int height,unsigned int stride)243 static void fill_smpte_rgb24(const struct util_rgb_info *rgb, void *mem,
244 			     unsigned int width, unsigned int height,
245 			     unsigned int stride)
246 {
247 	unsigned int x;
248 	unsigned int y;
249 
250 	const struct color_rgb24 colors_top[] = {
251 		MAKE_RGB24(rgb, 192, 192, 192),		/* grey */
252 		MAKE_RGB24(rgb, 192, 192, 0),		/* yellow */
253 		MAKE_RGB24(rgb, 0, 192, 192),		/* cyan */
254 		MAKE_RGB24(rgb, 0, 192, 0),		/* green */
255 		MAKE_RGB24(rgb, 192, 0, 192),		/* magenta */
256 		MAKE_RGB24(rgb, 192, 0, 0),		/* red */
257 		MAKE_RGB24(rgb, 0, 0, 192),		/* blue */
258 	};
259 	const struct color_rgb24 colors_middle[] = {
260 		MAKE_RGB24(rgb, 0, 0, 192),		/* blue */
261 		MAKE_RGB24(rgb, 19, 19, 19),		/* black */
262 		MAKE_RGB24(rgb, 192, 0, 192),		/* magenta */
263 		MAKE_RGB24(rgb, 19, 19, 19),		/* black */
264 		MAKE_RGB24(rgb, 0, 192, 192),		/* cyan */
265 		MAKE_RGB24(rgb, 19, 19, 19),		/* black */
266 		MAKE_RGB24(rgb, 192, 192, 192),		/* grey */
267 	};
268 	const struct color_rgb24 colors_bottom[] = {
269 		MAKE_RGB24(rgb, 0, 33, 76),		/* in-phase */
270 		MAKE_RGB24(rgb, 255, 255, 255),		/* super white */
271 		MAKE_RGB24(rgb, 50, 0, 106),		/* quadrature */
272 		MAKE_RGB24(rgb, 19, 19, 19),		/* black */
273 		MAKE_RGB24(rgb, 9, 9, 9),		/* 3.5% */
274 		MAKE_RGB24(rgb, 19, 19, 19),		/* 7.5% */
275 		MAKE_RGB24(rgb, 29, 29, 29),		/* 11.5% */
276 		MAKE_RGB24(rgb, 19, 19, 19),		/* black */
277 	};
278 
279 	for (y = 0; y < height * 6 / 9; ++y) {
280 		for (x = 0; x < width; ++x)
281 			((struct color_rgb24 *)mem)[x] = colors_top[x * 7 / width];
282 		mem += stride;
283 	}
284 
285 	for (; y < height * 7 / 9; ++y) {
286 		for (x = 0; x < width; ++x)
287 			((struct color_rgb24 *)mem)[x] = colors_middle[x * 7 / width];
288 		mem += stride;
289 	}
290 
291 	for (; y < height; ++y) {
292 		for (x = 0; x < width * 5 / 7; ++x)
293 			((struct color_rgb24 *)mem)[x] =
294 				colors_bottom[x * 4 / (width * 5 / 7)];
295 		for (; x < width * 6 / 7; ++x)
296 			((struct color_rgb24 *)mem)[x] =
297 				colors_bottom[(x - width * 5 / 7) * 3 / (width / 7) + 4];
298 		for (; x < width; ++x)
299 			((struct color_rgb24 *)mem)[x] = colors_bottom[7];
300 		mem += stride;
301 	}
302 }
303 
fill_smpte_rgb32(const struct util_rgb_info * rgb,void * mem,unsigned int width,unsigned int height,unsigned int stride)304 static void fill_smpte_rgb32(const struct util_rgb_info *rgb, void *mem,
305 			     unsigned int width, unsigned int height,
306 			     unsigned int stride)
307 {
308 	unsigned int x;
309 	unsigned int y;
310 
311 	const uint32_t colors_top[] = {
312 		MAKE_RGBA(rgb, 192, 192, 192, 255),	/* grey */
313 		MAKE_RGBA(rgb, 192, 192, 0, 255),	/* yellow */
314 		MAKE_RGBA(rgb, 0, 192, 192, 255),	/* cyan */
315 		MAKE_RGBA(rgb, 0, 255, 0, 255),		/* green */
316 		MAKE_RGBA(rgb, 192, 0, 192, 255),	/* magenta */
317 		MAKE_RGBA(rgb, 255, 0, 0, 255),		/* red */
318 		MAKE_RGBA(rgb, 0, 0, 255, 255),		/* blue */
319 	};
320 	const uint32_t colors_middle[] = {
321 		MAKE_RGBA(rgb, 0, 0, 192, 127),		/* blue */
322 		MAKE_RGBA(rgb, 19, 19, 19, 127),	/* black */
323 		MAKE_RGBA(rgb, 192, 0, 192, 127),	/* magenta */
324 		MAKE_RGBA(rgb, 19, 19, 19, 127),	/* black */
325 		MAKE_RGBA(rgb, 0, 192, 192, 127),	/* cyan */
326 		MAKE_RGBA(rgb, 19, 19, 19, 127),	/* black */
327 		MAKE_RGBA(rgb, 192, 192, 192, 127),	/* grey */
328 	};
329 	const uint32_t colors_bottom[] = {
330 		MAKE_RGBA(rgb, 0, 33, 76, 255),		/* in-phase */
331 		MAKE_RGBA(rgb, 255, 255, 255, 255),	/* super white */
332 		MAKE_RGBA(rgb, 50, 0, 106, 255),	/* quadrature */
333 		MAKE_RGBA(rgb, 19, 19, 19, 255),	/* black */
334 		MAKE_RGBA(rgb, 9, 9, 9, 255),		/* 3.5% */
335 		MAKE_RGBA(rgb, 19, 19, 19, 255),	/* 7.5% */
336 		MAKE_RGBA(rgb, 29, 29, 29, 255),	/* 11.5% */
337 		MAKE_RGBA(rgb, 19, 19, 19, 255),	/* black */
338 	};
339 
340 	for (y = 0; y < height * 6 / 9; ++y) {
341 		for (x = 0; x < width; ++x)
342 			((uint32_t *)mem)[x] = colors_top[x * 7 / width];
343 		mem += stride;
344 	}
345 
346 	for (; y < height * 7 / 9; ++y) {
347 		for (x = 0; x < width; ++x)
348 			((uint32_t *)mem)[x] = colors_middle[x * 7 / width];
349 		mem += stride;
350 	}
351 
352 	for (; y < height; ++y) {
353 		for (x = 0; x < width * 5 / 7; ++x)
354 			((uint32_t *)mem)[x] = colors_bottom[x * 4 / (width * 5 / 7)];
355 		for (; x < width * 6 / 7; ++x)
356 			((uint32_t *)mem)[x] = colors_bottom[(x - width * 5 / 7) * 3 / (width / 7) + 4];
357 		for (; x < width; ++x)
358 			((uint32_t *)mem)[x] = colors_bottom[7];
359 		mem += stride;
360 	}
361 }
362 
fill_smpte(const struct util_format_info * info,void * planes[3],unsigned int width,unsigned int height,unsigned int stride)363 static void fill_smpte(const struct util_format_info *info, void *planes[3],
364 		       unsigned int width, unsigned int height, unsigned int stride)
365 {
366 	unsigned char *u, *v;
367 
368 	if (width < 7)
369 		width = 7;
370 	switch (info->format) {
371 	case DRM_FORMAT_NV12:
372 	case DRM_FORMAT_NV21:
373 	case DRM_FORMAT_NV16:
374 	case DRM_FORMAT_NV61:
375 		u = info->yuv.order & YUV_YCbCr ? planes[1] : planes[1] + 1;
376 		v = info->yuv.order & YUV_YCrCb ? planes[1] : planes[1] + 1;
377 		return fill_smpte_yuv_planar(&info->yuv, planes[0], u, v,
378 					     width, height, stride);
379 	case DRM_FORMAT_RGB565:
380 	case DRM_FORMAT_BGR565:
381 		return fill_smpte_rgb16(&info->rgb, planes[0], width, height, stride);
382 	case DRM_FORMAT_BGR888:
383 	case DRM_FORMAT_RGB888:
384 		return fill_smpte_rgb24(&info->rgb, planes[0], width, height, stride);
385 	case DRM_FORMAT_ARGB8888:
386 	case DRM_FORMAT_XRGB8888:
387 	case DRM_FORMAT_ABGR8888:
388 	case DRM_FORMAT_XBGR8888:
389 	case DRM_FORMAT_RGBA8888:
390 	case DRM_FORMAT_RGBX8888:
391 	case DRM_FORMAT_BGRA8888:
392 	case DRM_FORMAT_BGRX8888:
393 		return fill_smpte_rgb32(&info->rgb, planes[0], width, height, stride);
394 	}
395 }
396 
397 /*
398  * util_fill_pattern - Fill a buffer with a test pattern
399  * @format: Pixel format
400  * @pattern: Test pattern
401  * @planes: Array of buffers
402  * @width: Width in pixels
403  * @height: Height in pixels
404  * @stride: Line stride (pitch) in bytes
405  *
406  * Fill the buffers with the test pattern specified by the pattern parameter.
407  * Supported formats vary depending on the selected pattern.
408  */
rockchip_drm_fill_color_bar(uint32_t format,void * planes[3],unsigned int width,unsigned int height,unsigned int stride)409 void rockchip_drm_fill_color_bar(uint32_t format,
410 				 void *planes[3], unsigned int width,
411 				 unsigned int height, unsigned int stride)
412 {
413 	const struct util_format_info *info;
414 
415 	info = util_format_info_find(format);
416 	if (info == NULL)
417 		return;
418 	return fill_smpte(info, planes, width, height, stride);
419 }
420