1 // SPDX-License-Identifier: GPL-2.0-only
2 /* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
5 #define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__
7 #include <uapi/drm/drm_fourcc.h>
9 #include "msm_media_info.h"
11 #include "dpu_formats.h"
13 #define DPU_UBWC_META_MACRO_W_H 16
14 #define DPU_UBWC_META_BLOCK_SIZE 256
15 #define DPU_UBWC_PLANE_SIZE_ALIGNMENT 4096
17 #define DPU_TILE_HEIGHT_DEFAULT 1
18 #define DPU_TILE_HEIGHT_TILED 4
19 #define DPU_TILE_HEIGHT_UBWC 4
20 #define DPU_TILE_HEIGHT_NV12 8
22 #define DPU_MAX_IMG_WIDTH 0x3FFF
23 #define DPU_MAX_IMG_HEIGHT 0x3FFF
26 * DPU supported format packing, bpp, and other format
28 * DPU currently only supports interleaved RGB formats
29 * UBWC support for a pixel format is indicated by the flag,
30 * there is additional meta data plane for such formats
33 #define INTERLEAVED_RGB_FMT(fmt, a, r, g, b, e0, e1, e2, e3, uc, alpha, \
36 .base.pixel_format = DRM_FORMAT_ ## fmt, \
37 .fetch_planes = DPU_PLANE_INTERLEAVED, \
38 .alpha_enable = alpha, \
39 .element = { (e0), (e1), (e2), (e3) }, \
40 .bits = { g, b, r, a }, \
41 .chroma_sample = DPU_CHROMA_RGB, \
42 .unpack_align_msb = 0, \
49 .tile_height = DPU_TILE_HEIGHT_DEFAULT \
52 #define INTERLEAVED_RGB_FMT_TILED(fmt, a, r, g, b, e0, e1, e2, e3, uc, \
53 alpha, bp, flg, fm, np, th) \
55 .base.pixel_format = DRM_FORMAT_ ## fmt, \
56 .fetch_planes = DPU_PLANE_INTERLEAVED, \
57 .alpha_enable = alpha, \
58 .element = { (e0), (e1), (e2), (e3) }, \
59 .bits = { g, b, r, a }, \
60 .chroma_sample = DPU_CHROMA_RGB, \
61 .unpack_align_msb = 0, \
72 #define INTERLEAVED_YUV_FMT(fmt, a, r, g, b, e0, e1, e2, e3, \
73 alpha, chroma, count, bp, flg, fm, np) \
75 .base.pixel_format = DRM_FORMAT_ ## fmt, \
76 .fetch_planes = DPU_PLANE_INTERLEAVED, \
77 .alpha_enable = alpha, \
78 .element = { (e0), (e1), (e2), (e3)}, \
79 .bits = { g, b, r, a }, \
80 .chroma_sample = chroma, \
81 .unpack_align_msb = 0, \
83 .unpack_count = count, \
88 .tile_height = DPU_TILE_HEIGHT_DEFAULT \
91 #define PSEUDO_YUV_FMT(fmt, a, r, g, b, e0, e1, chroma, flg, fm, np) \
93 .base.pixel_format = DRM_FORMAT_ ## fmt, \
94 .fetch_planes = DPU_PLANE_PSEUDO_PLANAR, \
95 .alpha_enable = false, \
96 .element = { (e0), (e1), 0, 0 }, \
97 .bits = { g, b, r, a }, \
98 .chroma_sample = chroma, \
99 .unpack_align_msb = 0, \
106 .tile_height = DPU_TILE_HEIGHT_DEFAULT \
109 #define PSEUDO_YUV_FMT_TILED(fmt, a, r, g, b, e0, e1, chroma, \
112 .base.pixel_format = DRM_FORMAT_ ## fmt, \
113 .fetch_planes = DPU_PLANE_PSEUDO_PLANAR, \
114 .alpha_enable = false, \
115 .element = { (e0), (e1), 0, 0 }, \
116 .bits = { g, b, r, a }, \
117 .chroma_sample = chroma, \
118 .unpack_align_msb = 0, \
128 #define PSEUDO_YUV_FMT_LOOSE(fmt, a, r, g, b, e0, e1, chroma, flg, fm, np)\
130 .base.pixel_format = DRM_FORMAT_ ## fmt, \
131 .fetch_planes = DPU_PLANE_PSEUDO_PLANAR, \
132 .alpha_enable = false, \
133 .element = { (e0), (e1), 0, 0 }, \
134 .bits = { g, b, r, a }, \
135 .chroma_sample = chroma, \
136 .unpack_align_msb = 1, \
143 .tile_height = DPU_TILE_HEIGHT_DEFAULT \
146 #define PSEUDO_YUV_FMT_LOOSE_TILED(fmt, a, r, g, b, e0, e1, chroma, \
149 .base.pixel_format = DRM_FORMAT_ ## fmt, \
150 .fetch_planes = DPU_PLANE_PSEUDO_PLANAR, \
151 .alpha_enable = false, \
152 .element = { (e0), (e1), 0, 0 }, \
153 .bits = { g, b, r, a }, \
154 .chroma_sample = chroma, \
155 .unpack_align_msb = 1, \
166 #define PLANAR_YUV_FMT(fmt, a, r, g, b, e0, e1, e2, alpha, chroma, bp, \
169 .base.pixel_format = DRM_FORMAT_ ## fmt, \
170 .fetch_planes = DPU_PLANE_PLANAR, \
171 .alpha_enable = alpha, \
172 .element = { (e0), (e1), (e2), 0 }, \
173 .bits = { g, b, r, a }, \
174 .chroma_sample = chroma, \
175 .unpack_align_msb = 0, \
182 .tile_height = DPU_TILE_HEIGHT_DEFAULT \
186 * struct dpu_media_color_map - maps drm format to media format
187 * @format: DRM base pixel format
188 * @color: Media API color related to DRM format
190 struct dpu_media_color_map
{
195 static const struct dpu_format dpu_format_map
[] = {
196 INTERLEAVED_RGB_FMT(ARGB8888
,
197 COLOR_8BIT
, COLOR_8BIT
, COLOR_8BIT
, COLOR_8BIT
,
198 C1_B_Cb
, C0_G_Y
, C2_R_Cr
, C3_ALPHA
, 4,
200 DPU_FETCH_LINEAR
, 1),
202 INTERLEAVED_RGB_FMT(ABGR8888
,
203 COLOR_8BIT
, COLOR_8BIT
, COLOR_8BIT
, COLOR_8BIT
,
204 C2_R_Cr
, C0_G_Y
, C1_B_Cb
, C3_ALPHA
, 4,
206 DPU_FETCH_LINEAR
, 1),
208 INTERLEAVED_RGB_FMT(XBGR8888
,
209 COLOR_8BIT
, COLOR_8BIT
, COLOR_8BIT
, COLOR_8BIT
,
210 C2_R_Cr
, C0_G_Y
, C1_B_Cb
, C3_ALPHA
, 4,
212 DPU_FETCH_LINEAR
, 1),
214 INTERLEAVED_RGB_FMT(RGBA8888
,
215 COLOR_8BIT
, COLOR_8BIT
, COLOR_8BIT
, COLOR_8BIT
,
216 C3_ALPHA
, C1_B_Cb
, C0_G_Y
, C2_R_Cr
, 4,
218 DPU_FETCH_LINEAR
, 1),
220 INTERLEAVED_RGB_FMT(BGRA8888
,
221 COLOR_8BIT
, COLOR_8BIT
, COLOR_8BIT
, COLOR_8BIT
,
222 C3_ALPHA
, C2_R_Cr
, C0_G_Y
, C1_B_Cb
, 4,
224 DPU_FETCH_LINEAR
, 1),
226 INTERLEAVED_RGB_FMT(BGRX8888
,
227 COLOR_8BIT
, COLOR_8BIT
, COLOR_8BIT
, COLOR_8BIT
,
228 C3_ALPHA
, C2_R_Cr
, C0_G_Y
, C1_B_Cb
, 4,
230 DPU_FETCH_LINEAR
, 1),
232 INTERLEAVED_RGB_FMT(XRGB8888
,
233 COLOR_8BIT
, COLOR_8BIT
, COLOR_8BIT
, COLOR_8BIT
,
234 C1_B_Cb
, C0_G_Y
, C2_R_Cr
, C3_ALPHA
, 4,
236 DPU_FETCH_LINEAR
, 1),
238 INTERLEAVED_RGB_FMT(RGBX8888
,
239 COLOR_8BIT
, COLOR_8BIT
, COLOR_8BIT
, COLOR_8BIT
,
240 C3_ALPHA
, C1_B_Cb
, C0_G_Y
, C2_R_Cr
, 4,
242 DPU_FETCH_LINEAR
, 1),
244 INTERLEAVED_RGB_FMT(RGB888
,
245 0, COLOR_8BIT
, COLOR_8BIT
, COLOR_8BIT
,
246 C1_B_Cb
, C0_G_Y
, C2_R_Cr
, 0, 3,
248 DPU_FETCH_LINEAR
, 1),
250 INTERLEAVED_RGB_FMT(BGR888
,
251 0, COLOR_8BIT
, COLOR_8BIT
, COLOR_8BIT
,
252 C2_R_Cr
, C0_G_Y
, C1_B_Cb
, 0, 3,
254 DPU_FETCH_LINEAR
, 1),
256 INTERLEAVED_RGB_FMT(RGB565
,
257 0, COLOR_5BIT
, COLOR_6BIT
, COLOR_5BIT
,
258 C1_B_Cb
, C0_G_Y
, C2_R_Cr
, 0, 3,
260 DPU_FETCH_LINEAR
, 1),
262 INTERLEAVED_RGB_FMT(BGR565
,
263 0, COLOR_5BIT
, COLOR_6BIT
, COLOR_5BIT
,
264 C2_R_Cr
, C0_G_Y
, C1_B_Cb
, 0, 3,
266 DPU_FETCH_LINEAR
, 1),
268 INTERLEAVED_RGB_FMT(ARGB1555
,
269 COLOR_ALPHA_1BIT
, COLOR_5BIT
, COLOR_5BIT
, COLOR_5BIT
,
270 C1_B_Cb
, C0_G_Y
, C2_R_Cr
, C3_ALPHA
, 4,
272 DPU_FETCH_LINEAR
, 1),
274 INTERLEAVED_RGB_FMT(ABGR1555
,
275 COLOR_ALPHA_1BIT
, COLOR_5BIT
, COLOR_5BIT
, COLOR_5BIT
,
276 C2_R_Cr
, C0_G_Y
, C1_B_Cb
, C3_ALPHA
, 4,
278 DPU_FETCH_LINEAR
, 1),
280 INTERLEAVED_RGB_FMT(RGBA5551
,
281 COLOR_ALPHA_1BIT
, COLOR_5BIT
, COLOR_5BIT
, COLOR_5BIT
,
282 C3_ALPHA
, C1_B_Cb
, C0_G_Y
, C2_R_Cr
, 4,
284 DPU_FETCH_LINEAR
, 1),
286 INTERLEAVED_RGB_FMT(BGRA5551
,
287 COLOR_ALPHA_1BIT
, COLOR_5BIT
, COLOR_5BIT
, COLOR_5BIT
,
288 C3_ALPHA
, C2_R_Cr
, C0_G_Y
, C1_B_Cb
, 4,
290 DPU_FETCH_LINEAR
, 1),
292 INTERLEAVED_RGB_FMT(XRGB1555
,
293 COLOR_ALPHA_1BIT
, COLOR_5BIT
, COLOR_5BIT
, COLOR_5BIT
,
294 C1_B_Cb
, C0_G_Y
, C2_R_Cr
, C3_ALPHA
, 4,
296 DPU_FETCH_LINEAR
, 1),
298 INTERLEAVED_RGB_FMT(XBGR1555
,
299 COLOR_ALPHA_1BIT
, COLOR_5BIT
, COLOR_5BIT
, COLOR_5BIT
,
300 C2_R_Cr
, C0_G_Y
, C1_B_Cb
, C3_ALPHA
, 4,
302 DPU_FETCH_LINEAR
, 1),
304 INTERLEAVED_RGB_FMT(RGBX5551
,
305 COLOR_ALPHA_1BIT
, COLOR_5BIT
, COLOR_5BIT
, COLOR_5BIT
,
306 C3_ALPHA
, C1_B_Cb
, C0_G_Y
, C2_R_Cr
, 4,
308 DPU_FETCH_LINEAR
, 1),
310 INTERLEAVED_RGB_FMT(BGRX5551
,
311 COLOR_ALPHA_1BIT
, COLOR_5BIT
, COLOR_5BIT
, COLOR_5BIT
,
312 C3_ALPHA
, C2_R_Cr
, C0_G_Y
, C1_B_Cb
, 4,
314 DPU_FETCH_LINEAR
, 1),
316 INTERLEAVED_RGB_FMT(ARGB4444
,
317 COLOR_ALPHA_4BIT
, COLOR_4BIT
, COLOR_4BIT
, COLOR_4BIT
,
318 C1_B_Cb
, C0_G_Y
, C2_R_Cr
, C3_ALPHA
, 4,
320 DPU_FETCH_LINEAR
, 1),
322 INTERLEAVED_RGB_FMT(ABGR4444
,
323 COLOR_ALPHA_4BIT
, COLOR_4BIT
, COLOR_4BIT
, COLOR_4BIT
,
324 C2_R_Cr
, C0_G_Y
, C1_B_Cb
, C3_ALPHA
, 4,
326 DPU_FETCH_LINEAR
, 1),
328 INTERLEAVED_RGB_FMT(RGBA4444
,
329 COLOR_ALPHA_4BIT
, COLOR_4BIT
, COLOR_4BIT
, COLOR_4BIT
,
330 C3_ALPHA
, C1_B_Cb
, C0_G_Y
, C2_R_Cr
, 4,
332 DPU_FETCH_LINEAR
, 1),
334 INTERLEAVED_RGB_FMT(BGRA4444
,
335 COLOR_ALPHA_4BIT
, COLOR_4BIT
, COLOR_4BIT
, COLOR_4BIT
,
336 C3_ALPHA
, C2_R_Cr
, C0_G_Y
, C1_B_Cb
, 4,
338 DPU_FETCH_LINEAR
, 1),
340 INTERLEAVED_RGB_FMT(XRGB4444
,
341 COLOR_ALPHA_4BIT
, COLOR_4BIT
, COLOR_4BIT
, COLOR_4BIT
,
342 C1_B_Cb
, C0_G_Y
, C2_R_Cr
, C3_ALPHA
, 4,
344 DPU_FETCH_LINEAR
, 1),
346 INTERLEAVED_RGB_FMT(XBGR4444
,
347 COLOR_ALPHA_4BIT
, COLOR_4BIT
, COLOR_4BIT
, COLOR_4BIT
,
348 C2_R_Cr
, C0_G_Y
, C1_B_Cb
, C3_ALPHA
, 4,
350 DPU_FETCH_LINEAR
, 1),
352 INTERLEAVED_RGB_FMT(RGBX4444
,
353 COLOR_ALPHA_4BIT
, COLOR_4BIT
, COLOR_4BIT
, COLOR_4BIT
,
354 C3_ALPHA
, C1_B_Cb
, C0_G_Y
, C2_R_Cr
, 4,
356 DPU_FETCH_LINEAR
, 1),
358 INTERLEAVED_RGB_FMT(BGRX4444
,
359 COLOR_ALPHA_4BIT
, COLOR_4BIT
, COLOR_4BIT
, COLOR_4BIT
,
360 C3_ALPHA
, C2_R_Cr
, C0_G_Y
, C1_B_Cb
, 4,
362 DPU_FETCH_LINEAR
, 1),
364 INTERLEAVED_RGB_FMT(BGRA1010102
,
365 COLOR_8BIT
, COLOR_8BIT
, COLOR_8BIT
, COLOR_8BIT
,
366 C3_ALPHA
, C2_R_Cr
, C0_G_Y
, C1_B_Cb
, 4,
367 true, 4, DPU_FORMAT_FLAG_DX
,
368 DPU_FETCH_LINEAR
, 1),
370 INTERLEAVED_RGB_FMT(RGBA1010102
,
371 COLOR_8BIT
, COLOR_8BIT
, COLOR_8BIT
, COLOR_8BIT
,
372 C3_ALPHA
, C1_B_Cb
, C0_G_Y
, C2_R_Cr
, 4,
373 true, 4, DPU_FORMAT_FLAG_DX
,
374 DPU_FETCH_LINEAR
, 1),
376 INTERLEAVED_RGB_FMT(ABGR2101010
,
377 COLOR_8BIT
, COLOR_8BIT
, COLOR_8BIT
, COLOR_8BIT
,
378 C2_R_Cr
, C0_G_Y
, C1_B_Cb
, C3_ALPHA
, 4,
379 true, 4, DPU_FORMAT_FLAG_DX
,
380 DPU_FETCH_LINEAR
, 1),
382 INTERLEAVED_RGB_FMT(ARGB2101010
,
383 COLOR_8BIT
, COLOR_8BIT
, COLOR_8BIT
, COLOR_8BIT
,
384 C1_B_Cb
, C0_G_Y
, C2_R_Cr
, C3_ALPHA
, 4,
385 true, 4, DPU_FORMAT_FLAG_DX
,
386 DPU_FETCH_LINEAR
, 1),
388 INTERLEAVED_RGB_FMT(XRGB2101010
,
389 COLOR_8BIT
, COLOR_8BIT
, COLOR_8BIT
, COLOR_8BIT
,
390 C1_B_Cb
, C0_G_Y
, C2_R_Cr
, C3_ALPHA
, 4,
391 false, 4, DPU_FORMAT_FLAG_DX
,
392 DPU_FETCH_LINEAR
, 1),
394 INTERLEAVED_RGB_FMT(BGRX1010102
,
395 COLOR_8BIT
, COLOR_8BIT
, COLOR_8BIT
, COLOR_8BIT
,
396 C3_ALPHA
, C2_R_Cr
, C0_G_Y
, C1_B_Cb
, 4,
397 false, 4, DPU_FORMAT_FLAG_DX
,
398 DPU_FETCH_LINEAR
, 1),
400 INTERLEAVED_RGB_FMT(XBGR2101010
,
401 COLOR_8BIT
, COLOR_8BIT
, COLOR_8BIT
, COLOR_8BIT
,
402 C2_R_Cr
, C0_G_Y
, C1_B_Cb
, C3_ALPHA
, 4,
403 false, 4, DPU_FORMAT_FLAG_DX
,
404 DPU_FETCH_LINEAR
, 1),
406 INTERLEAVED_RGB_FMT(RGBX1010102
,
407 COLOR_8BIT
, COLOR_8BIT
, COLOR_8BIT
, COLOR_8BIT
,
408 C3_ALPHA
, C1_B_Cb
, C0_G_Y
, C2_R_Cr
, 4,
409 false, 4, DPU_FORMAT_FLAG_DX
,
410 DPU_FETCH_LINEAR
, 1),
413 0, COLOR_8BIT
, COLOR_8BIT
, COLOR_8BIT
,
415 DPU_CHROMA_420
, DPU_FORMAT_FLAG_YUV
,
416 DPU_FETCH_LINEAR
, 2),
419 0, COLOR_8BIT
, COLOR_8BIT
, COLOR_8BIT
,
421 DPU_CHROMA_420
, DPU_FORMAT_FLAG_YUV
,
422 DPU_FETCH_LINEAR
, 2),
425 0, COLOR_8BIT
, COLOR_8BIT
, COLOR_8BIT
,
427 DPU_CHROMA_H2V1
, DPU_FORMAT_FLAG_YUV
,
428 DPU_FETCH_LINEAR
, 2),
431 0, COLOR_8BIT
, COLOR_8BIT
, COLOR_8BIT
,
433 DPU_CHROMA_H2V1
, DPU_FORMAT_FLAG_YUV
,
434 DPU_FETCH_LINEAR
, 2),
436 INTERLEAVED_YUV_FMT(VYUY
,
437 0, COLOR_8BIT
, COLOR_8BIT
, COLOR_8BIT
,
438 C2_R_Cr
, C0_G_Y
, C1_B_Cb
, C0_G_Y
,
439 false, DPU_CHROMA_H2V1
, 4, 2, DPU_FORMAT_FLAG_YUV
,
440 DPU_FETCH_LINEAR
, 2),
442 INTERLEAVED_YUV_FMT(UYVY
,
443 0, COLOR_8BIT
, COLOR_8BIT
, COLOR_8BIT
,
444 C1_B_Cb
, C0_G_Y
, C2_R_Cr
, C0_G_Y
,
445 false, DPU_CHROMA_H2V1
, 4, 2, DPU_FORMAT_FLAG_YUV
,
446 DPU_FETCH_LINEAR
, 2),
448 INTERLEAVED_YUV_FMT(YUYV
,
449 0, COLOR_8BIT
, COLOR_8BIT
, COLOR_8BIT
,
450 C0_G_Y
, C1_B_Cb
, C0_G_Y
, C2_R_Cr
,
451 false, DPU_CHROMA_H2V1
, 4, 2, DPU_FORMAT_FLAG_YUV
,
452 DPU_FETCH_LINEAR
, 2),
454 INTERLEAVED_YUV_FMT(YVYU
,
455 0, COLOR_8BIT
, COLOR_8BIT
, COLOR_8BIT
,
456 C0_G_Y
, C2_R_Cr
, C0_G_Y
, C1_B_Cb
,
457 false, DPU_CHROMA_H2V1
, 4, 2, DPU_FORMAT_FLAG_YUV
,
458 DPU_FETCH_LINEAR
, 2),
460 PLANAR_YUV_FMT(YUV420
,
461 0, COLOR_8BIT
, COLOR_8BIT
, COLOR_8BIT
,
462 C2_R_Cr
, C1_B_Cb
, C0_G_Y
,
463 false, DPU_CHROMA_420
, 1, DPU_FORMAT_FLAG_YUV
,
464 DPU_FETCH_LINEAR
, 3),
466 PLANAR_YUV_FMT(YVU420
,
467 0, COLOR_8BIT
, COLOR_8BIT
, COLOR_8BIT
,
468 C1_B_Cb
, C2_R_Cr
, C0_G_Y
,
469 false, DPU_CHROMA_420
, 1, DPU_FORMAT_FLAG_YUV
,
470 DPU_FETCH_LINEAR
, 3),
474 * UBWC formats table:
475 * This table holds the UBWC formats supported.
476 * If a compression ratio needs to be used for this or any other format,
477 * the data will be passed by user-space.
479 static const struct dpu_format dpu_format_map_ubwc
[] = {
480 INTERLEAVED_RGB_FMT_TILED(BGR565
,
481 0, COLOR_5BIT
, COLOR_6BIT
, COLOR_5BIT
,
482 C2_R_Cr
, C0_G_Y
, C1_B_Cb
, 0, 3,
483 false, 2, DPU_FORMAT_FLAG_COMPRESSED
,
484 DPU_FETCH_UBWC
, 2, DPU_TILE_HEIGHT_UBWC
),
486 INTERLEAVED_RGB_FMT_TILED(ABGR8888
,
487 COLOR_8BIT
, COLOR_8BIT
, COLOR_8BIT
, COLOR_8BIT
,
488 C2_R_Cr
, C0_G_Y
, C1_B_Cb
, C3_ALPHA
, 4,
489 true, 4, DPU_FORMAT_FLAG_COMPRESSED
,
490 DPU_FETCH_UBWC
, 2, DPU_TILE_HEIGHT_UBWC
),
492 /* ARGB8888 and ABGR8888 purposely have the same color
493 * ordering. The hardware only supports ABGR8888 UBWC
496 INTERLEAVED_RGB_FMT_TILED(ARGB8888
,
497 COLOR_8BIT
, COLOR_8BIT
, COLOR_8BIT
, COLOR_8BIT
,
498 C2_R_Cr
, C0_G_Y
, C1_B_Cb
, C3_ALPHA
, 4,
499 true, 4, DPU_FORMAT_FLAG_COMPRESSED
,
500 DPU_FETCH_UBWC
, 2, DPU_TILE_HEIGHT_UBWC
),
502 INTERLEAVED_RGB_FMT_TILED(XBGR8888
,
503 COLOR_8BIT
, COLOR_8BIT
, COLOR_8BIT
, COLOR_8BIT
,
504 C2_R_Cr
, C0_G_Y
, C1_B_Cb
, C3_ALPHA
, 4,
505 false, 4, DPU_FORMAT_FLAG_COMPRESSED
,
506 DPU_FETCH_UBWC
, 2, DPU_TILE_HEIGHT_UBWC
),
508 INTERLEAVED_RGB_FMT_TILED(XRGB8888
,
509 COLOR_8BIT
, COLOR_8BIT
, COLOR_8BIT
, COLOR_8BIT
,
510 C2_R_Cr
, C0_G_Y
, C1_B_Cb
, C3_ALPHA
, 4,
511 false, 4, DPU_FORMAT_FLAG_COMPRESSED
,
512 DPU_FETCH_UBWC
, 2, DPU_TILE_HEIGHT_UBWC
),
514 INTERLEAVED_RGB_FMT_TILED(ABGR2101010
,
515 COLOR_8BIT
, COLOR_8BIT
, COLOR_8BIT
, COLOR_8BIT
,
516 C2_R_Cr
, C0_G_Y
, C1_B_Cb
, C3_ALPHA
, 4,
517 true, 4, DPU_FORMAT_FLAG_DX
| DPU_FORMAT_FLAG_COMPRESSED
,
518 DPU_FETCH_UBWC
, 2, DPU_TILE_HEIGHT_UBWC
),
520 INTERLEAVED_RGB_FMT_TILED(XBGR2101010
,
521 COLOR_8BIT
, COLOR_8BIT
, COLOR_8BIT
, COLOR_8BIT
,
522 C2_R_Cr
, C0_G_Y
, C1_B_Cb
, C3_ALPHA
, 4,
523 true, 4, DPU_FORMAT_FLAG_DX
| DPU_FORMAT_FLAG_COMPRESSED
,
524 DPU_FETCH_UBWC
, 2, DPU_TILE_HEIGHT_UBWC
),
526 PSEUDO_YUV_FMT_TILED(NV12
,
527 0, COLOR_8BIT
, COLOR_8BIT
, COLOR_8BIT
,
529 DPU_CHROMA_420
, DPU_FORMAT_FLAG_YUV
|
530 DPU_FORMAT_FLAG_COMPRESSED
,
531 DPU_FETCH_UBWC
, 4, DPU_TILE_HEIGHT_NV12
),
534 /* _dpu_get_v_h_subsample_rate - Get subsample rates for all formats we support
535 * Note: Not using the drm_format_*_subsampling since we have formats
537 static void _dpu_get_v_h_subsample_rate(
538 enum dpu_chroma_samp_type chroma_sample
,
542 if (!v_sample
|| !h_sample
)
545 switch (chroma_sample
) {
546 case DPU_CHROMA_H2V1
:
550 case DPU_CHROMA_H1V2
:
565 static int _dpu_format_get_media_color_ubwc(const struct dpu_format
*fmt
)
567 static const struct dpu_media_color_map dpu_media_ubwc_map
[] = {
568 {DRM_FORMAT_ABGR8888
, COLOR_FMT_RGBA8888_UBWC
},
569 {DRM_FORMAT_ARGB8888
, COLOR_FMT_RGBA8888_UBWC
},
570 {DRM_FORMAT_XBGR8888
, COLOR_FMT_RGBA8888_UBWC
},
571 {DRM_FORMAT_XRGB8888
, COLOR_FMT_RGBA8888_UBWC
},
572 {DRM_FORMAT_ABGR2101010
, COLOR_FMT_RGBA1010102_UBWC
},
573 {DRM_FORMAT_XBGR2101010
, COLOR_FMT_RGBA1010102_UBWC
},
574 {DRM_FORMAT_BGR565
, COLOR_FMT_RGB565_UBWC
},
579 if (fmt
->base
.pixel_format
== DRM_FORMAT_NV12
) {
580 if (DPU_FORMAT_IS_DX(fmt
)) {
581 if (fmt
->unpack_tight
)
582 color_fmt
= COLOR_FMT_NV12_BPP10_UBWC
;
584 color_fmt
= COLOR_FMT_P010_UBWC
;
586 color_fmt
= COLOR_FMT_NV12_UBWC
;
590 for (i
= 0; i
< ARRAY_SIZE(dpu_media_ubwc_map
); ++i
)
591 if (fmt
->base
.pixel_format
== dpu_media_ubwc_map
[i
].format
) {
592 color_fmt
= dpu_media_ubwc_map
[i
].color
;
598 static int _dpu_format_get_plane_sizes_ubwc(
599 const struct dpu_format
*fmt
,
600 const uint32_t width
,
601 const uint32_t height
,
602 struct dpu_hw_fmt_layout
*layout
)
606 bool meta
= DPU_FORMAT_IS_UBWC(fmt
);
608 memset(layout
, 0, sizeof(struct dpu_hw_fmt_layout
));
609 layout
->format
= fmt
;
610 layout
->width
= width
;
611 layout
->height
= height
;
612 layout
->num_planes
= fmt
->num_planes
;
614 color
= _dpu_format_get_media_color_ubwc(fmt
);
616 DRM_ERROR("UBWC format not supported for fmt: %4.4s\n",
617 (char *)&fmt
->base
.pixel_format
);
621 if (DPU_FORMAT_IS_YUV(layout
->format
)) {
622 uint32_t y_sclines
, uv_sclines
;
623 uint32_t y_meta_scanlines
= 0;
624 uint32_t uv_meta_scanlines
= 0;
626 layout
->num_planes
= 2;
627 layout
->plane_pitch
[0] = VENUS_Y_STRIDE(color
, width
);
628 y_sclines
= VENUS_Y_SCANLINES(color
, height
);
629 layout
->plane_size
[0] = MSM_MEDIA_ALIGN(layout
->plane_pitch
[0] *
630 y_sclines
, DPU_UBWC_PLANE_SIZE_ALIGNMENT
);
632 layout
->plane_pitch
[1] = VENUS_UV_STRIDE(color
, width
);
633 uv_sclines
= VENUS_UV_SCANLINES(color
, height
);
634 layout
->plane_size
[1] = MSM_MEDIA_ALIGN(layout
->plane_pitch
[1] *
635 uv_sclines
, DPU_UBWC_PLANE_SIZE_ALIGNMENT
);
640 layout
->num_planes
+= 2;
641 layout
->plane_pitch
[2] = VENUS_Y_META_STRIDE(color
, width
);
642 y_meta_scanlines
= VENUS_Y_META_SCANLINES(color
, height
);
643 layout
->plane_size
[2] = MSM_MEDIA_ALIGN(layout
->plane_pitch
[2] *
644 y_meta_scanlines
, DPU_UBWC_PLANE_SIZE_ALIGNMENT
);
646 layout
->plane_pitch
[3] = VENUS_UV_META_STRIDE(color
, width
);
647 uv_meta_scanlines
= VENUS_UV_META_SCANLINES(color
, height
);
648 layout
->plane_size
[3] = MSM_MEDIA_ALIGN(layout
->plane_pitch
[3] *
649 uv_meta_scanlines
, DPU_UBWC_PLANE_SIZE_ALIGNMENT
);
652 uint32_t rgb_scanlines
, rgb_meta_scanlines
;
654 layout
->num_planes
= 1;
656 layout
->plane_pitch
[0] = VENUS_RGB_STRIDE(color
, width
);
657 rgb_scanlines
= VENUS_RGB_SCANLINES(color
, height
);
658 layout
->plane_size
[0] = MSM_MEDIA_ALIGN(layout
->plane_pitch
[0] *
659 rgb_scanlines
, DPU_UBWC_PLANE_SIZE_ALIGNMENT
);
663 layout
->num_planes
+= 2;
664 layout
->plane_pitch
[2] = VENUS_RGB_META_STRIDE(color
, width
);
665 rgb_meta_scanlines
= VENUS_RGB_META_SCANLINES(color
, height
);
666 layout
->plane_size
[2] = MSM_MEDIA_ALIGN(layout
->plane_pitch
[2] *
667 rgb_meta_scanlines
, DPU_UBWC_PLANE_SIZE_ALIGNMENT
);
671 for (i
= 0; i
< DPU_MAX_PLANES
; i
++)
672 layout
->total_size
+= layout
->plane_size
[i
];
677 static int _dpu_format_get_plane_sizes_linear(
678 const struct dpu_format
*fmt
,
679 const uint32_t width
,
680 const uint32_t height
,
681 struct dpu_hw_fmt_layout
*layout
,
682 const uint32_t *pitches
)
686 memset(layout
, 0, sizeof(struct dpu_hw_fmt_layout
));
687 layout
->format
= fmt
;
688 layout
->width
= width
;
689 layout
->height
= height
;
690 layout
->num_planes
= fmt
->num_planes
;
692 /* Due to memset above, only need to set planes of interest */
693 if (fmt
->fetch_planes
== DPU_PLANE_INTERLEAVED
) {
694 layout
->num_planes
= 1;
695 layout
->plane_size
[0] = width
* height
* layout
->format
->bpp
;
696 layout
->plane_pitch
[0] = width
* layout
->format
->bpp
;
698 uint32_t v_subsample
, h_subsample
;
699 uint32_t chroma_samp
;
702 chroma_samp
= fmt
->chroma_sample
;
703 _dpu_get_v_h_subsample_rate(chroma_samp
, &v_subsample
,
706 if (width
% h_subsample
|| height
% v_subsample
) {
707 DRM_ERROR("mismatch in subsample vs dimensions\n");
711 if ((fmt
->base
.pixel_format
== DRM_FORMAT_NV12
) &&
712 (DPU_FORMAT_IS_DX(fmt
)))
714 layout
->plane_pitch
[0] = width
* bpp
;
715 layout
->plane_pitch
[1] = layout
->plane_pitch
[0] / h_subsample
;
716 layout
->plane_size
[0] = layout
->plane_pitch
[0] * height
;
717 layout
->plane_size
[1] = layout
->plane_pitch
[1] *
718 (height
/ v_subsample
);
720 if (fmt
->fetch_planes
== DPU_PLANE_PSEUDO_PLANAR
) {
721 layout
->num_planes
= 2;
722 layout
->plane_size
[1] *= 2;
723 layout
->plane_pitch
[1] *= 2;
726 layout
->num_planes
= 3;
727 layout
->plane_size
[2] = layout
->plane_size
[1];
728 layout
->plane_pitch
[2] = layout
->plane_pitch
[1];
733 * linear format: allow user allocated pitches if they are greater than
735 * ubwc format: pitch values are computed uniformly across
736 * all the components based on ubwc specifications.
738 for (i
= 0; i
< layout
->num_planes
&& i
< DPU_MAX_PLANES
; ++i
) {
739 if (pitches
&& layout
->plane_pitch
[i
] < pitches
[i
])
740 layout
->plane_pitch
[i
] = pitches
[i
];
743 for (i
= 0; i
< DPU_MAX_PLANES
; i
++)
744 layout
->total_size
+= layout
->plane_size
[i
];
749 static int dpu_format_get_plane_sizes(
750 const struct dpu_format
*fmt
,
753 struct dpu_hw_fmt_layout
*layout
,
754 const uint32_t *pitches
)
756 if (!layout
|| !fmt
) {
757 DRM_ERROR("invalid pointer\n");
761 if ((w
> DPU_MAX_IMG_WIDTH
) || (h
> DPU_MAX_IMG_HEIGHT
)) {
762 DRM_ERROR("image dimensions outside max range\n");
766 if (DPU_FORMAT_IS_UBWC(fmt
) || DPU_FORMAT_IS_TILE(fmt
))
767 return _dpu_format_get_plane_sizes_ubwc(fmt
, w
, h
, layout
);
769 return _dpu_format_get_plane_sizes_linear(fmt
, w
, h
, layout
, pitches
);
772 static int _dpu_format_populate_addrs_ubwc(
773 struct msm_gem_address_space
*aspace
,
774 struct drm_framebuffer
*fb
,
775 struct dpu_hw_fmt_layout
*layout
)
777 uint32_t base_addr
= 0;
780 if (!fb
|| !layout
) {
781 DRM_ERROR("invalid pointers\n");
786 base_addr
= msm_framebuffer_iova(fb
, aspace
, 0);
788 DRM_ERROR("failed to retrieve base addr\n");
792 meta
= DPU_FORMAT_IS_UBWC(layout
->format
);
794 /* Per-format logic for verifying active planes */
795 if (DPU_FORMAT_IS_YUV(layout
->format
)) {
796 /************************************************/
798 /* buffer ** DPU PLANE */
800 /************************************************/
801 /* ------------------- ** -------------------- */
802 /* | Y meta | ** | Y bitstream | */
803 /* | data | ** | plane | */
804 /* ------------------- ** -------------------- */
805 /* | Y bitstream | ** | CbCr bitstream | */
806 /* | data | ** | plane | */
807 /* ------------------- ** -------------------- */
808 /* | Cbcr metadata | ** | Y meta | */
809 /* | data | ** | plane | */
810 /* ------------------- ** -------------------- */
811 /* | CbCr bitstream | ** | CbCr meta | */
812 /* | data | ** | plane | */
813 /* ------------------- ** -------------------- */
814 /************************************************/
816 /* configure Y bitstream plane */
817 layout
->plane_addr
[0] = base_addr
+ layout
->plane_size
[2];
819 /* configure CbCr bitstream plane */
820 layout
->plane_addr
[1] = base_addr
+ layout
->plane_size
[0]
821 + layout
->plane_size
[2] + layout
->plane_size
[3];
826 /* configure Y metadata plane */
827 layout
->plane_addr
[2] = base_addr
;
829 /* configure CbCr metadata plane */
830 layout
->plane_addr
[3] = base_addr
+ layout
->plane_size
[0]
831 + layout
->plane_size
[2];
834 /************************************************/
836 /* buffer ** DPU PLANE */
838 /************************************************/
839 /* ------------------- ** -------------------- */
840 /* | RGB meta | ** | RGB bitstream | */
841 /* | data | ** | plane | */
842 /* ------------------- ** -------------------- */
843 /* | RGB bitstream | ** | NONE | */
844 /* | data | ** | | */
845 /* ------------------- ** -------------------- */
846 /* ** | RGB meta | */
848 /* ** -------------------- */
849 /************************************************/
851 layout
->plane_addr
[0] = base_addr
+ layout
->plane_size
[2];
852 layout
->plane_addr
[1] = 0;
857 layout
->plane_addr
[2] = base_addr
;
858 layout
->plane_addr
[3] = 0;
863 static int _dpu_format_populate_addrs_linear(
864 struct msm_gem_address_space
*aspace
,
865 struct drm_framebuffer
*fb
,
866 struct dpu_hw_fmt_layout
*layout
)
870 /* Can now check the pitches given vs pitches expected */
871 for (i
= 0; i
< layout
->num_planes
; ++i
) {
872 if (layout
->plane_pitch
[i
] > fb
->pitches
[i
]) {
873 DRM_ERROR("plane %u expected pitch %u, fb %u\n",
874 i
, layout
->plane_pitch
[i
], fb
->pitches
[i
]);
879 /* Populate addresses for simple formats here */
880 for (i
= 0; i
< layout
->num_planes
; ++i
) {
882 layout
->plane_addr
[i
] =
883 msm_framebuffer_iova(fb
, aspace
, i
);
884 if (!layout
->plane_addr
[i
]) {
885 DRM_ERROR("failed to retrieve base addr\n");
893 int dpu_format_populate_layout(
894 struct msm_gem_address_space
*aspace
,
895 struct drm_framebuffer
*fb
,
896 struct dpu_hw_fmt_layout
*layout
)
898 uint32_t plane_addr
[DPU_MAX_PLANES
];
901 if (!fb
|| !layout
) {
902 DRM_ERROR("invalid arguments\n");
906 if ((fb
->width
> DPU_MAX_IMG_WIDTH
) ||
907 (fb
->height
> DPU_MAX_IMG_HEIGHT
)) {
908 DRM_ERROR("image dimensions outside max range\n");
912 layout
->format
= to_dpu_format(msm_framebuffer_format(fb
));
914 /* Populate the plane sizes etc via get_format */
915 ret
= dpu_format_get_plane_sizes(layout
->format
, fb
->width
, fb
->height
,
916 layout
, fb
->pitches
);
920 for (i
= 0; i
< DPU_MAX_PLANES
; ++i
)
921 plane_addr
[i
] = layout
->plane_addr
[i
];
923 /* Populate the addresses given the fb */
924 if (DPU_FORMAT_IS_UBWC(layout
->format
) ||
925 DPU_FORMAT_IS_TILE(layout
->format
))
926 ret
= _dpu_format_populate_addrs_ubwc(aspace
, fb
, layout
);
928 ret
= _dpu_format_populate_addrs_linear(aspace
, fb
, layout
);
930 /* check if anything changed */
931 if (!ret
&& !memcmp(plane_addr
, layout
->plane_addr
, sizeof(plane_addr
)))
937 int dpu_format_check_modified_format(
938 const struct msm_kms
*kms
,
939 const struct msm_format
*msm_fmt
,
940 const struct drm_mode_fb_cmd2
*cmd
,
941 struct drm_gem_object
**bos
)
943 const struct drm_format_info
*info
;
944 const struct dpu_format
*fmt
;
945 struct dpu_hw_fmt_layout layout
;
946 uint32_t bos_total_size
= 0;
949 if (!msm_fmt
|| !cmd
|| !bos
) {
950 DRM_ERROR("invalid arguments\n");
954 fmt
= to_dpu_format(msm_fmt
);
955 info
= drm_format_info(fmt
->base
.pixel_format
);
959 ret
= dpu_format_get_plane_sizes(fmt
, cmd
->width
, cmd
->height
,
960 &layout
, cmd
->pitches
);
964 for (i
= 0; i
< info
->num_planes
; i
++) {
966 DRM_ERROR("invalid handle for plane %d\n", i
);
969 if ((i
== 0) || (bos
[i
] != bos
[0]))
970 bos_total_size
+= bos
[i
]->size
;
973 if (bos_total_size
< layout
.total_size
) {
974 DRM_ERROR("buffers total size too small %u expected %u\n",
975 bos_total_size
, layout
.total_size
);
982 const struct dpu_format
*dpu_get_dpu_format_ext(
983 const uint32_t format
,
984 const uint64_t modifier
)
987 const struct dpu_format
*fmt
= NULL
;
988 const struct dpu_format
*map
= NULL
;
989 ssize_t map_size
= 0;
992 * Currently only support exactly zero or one modifier.
993 * All planes use the same modifier.
995 DPU_DEBUG("plane format modifier 0x%llX\n", modifier
);
999 map
= dpu_format_map
;
1000 map_size
= ARRAY_SIZE(dpu_format_map
);
1002 case DRM_FORMAT_MOD_QCOM_COMPRESSED
:
1003 map
= dpu_format_map_ubwc
;
1004 map_size
= ARRAY_SIZE(dpu_format_map_ubwc
);
1005 DPU_DEBUG("found fmt: %4.4s DRM_FORMAT_MOD_QCOM_COMPRESSED\n",
1009 DPU_ERROR("unsupported format modifier %llX\n", modifier
);
1013 for (i
= 0; i
< map_size
; i
++) {
1014 if (format
== map
[i
].base
.pixel_format
) {
1021 DPU_ERROR("unsupported fmt: %4.4s modifier 0x%llX\n",
1022 (char *)&format
, modifier
);
1024 DPU_DEBUG("fmt %4.4s mod 0x%llX ubwc %d yuv %d\n",
1025 (char *)&format
, modifier
,
1026 DPU_FORMAT_IS_UBWC(fmt
),
1027 DPU_FORMAT_IS_YUV(fmt
));
1032 const struct msm_format
*dpu_get_msm_format(
1033 struct msm_kms
*kms
,
1034 const uint32_t format
,
1035 const uint64_t modifiers
)
1037 const struct dpu_format
*fmt
= dpu_get_dpu_format_ext(format
,