Merge tag 'block-5.11-2021-01-10' of git://git.kernel.dk/linux-block
[linux/fpc-iii.git] / drivers / gpu / drm / msm / disp / dpu1 / dpu_formats.c
blob21ff8f9e5dfd14878bb67dc533ea6681d56dd030
1 // SPDX-License-Identifier: GPL-2.0-only
2 /* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
3 */
5 #define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__
7 #include <uapi/drm/drm_fourcc.h>
9 #include "msm_media_info.h"
10 #include "dpu_kms.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
27 * information.
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, \
34 bp, flg, fm, np) \
35 { \
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, \
43 .unpack_tight = 1, \
44 .unpack_count = uc, \
45 .bpp = bp, \
46 .fetch_mode = fm, \
47 .flag = {(flg)}, \
48 .num_planes = np, \
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) \
54 { \
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, \
62 .unpack_tight = 1, \
63 .unpack_count = uc, \
64 .bpp = bp, \
65 .fetch_mode = fm, \
66 .flag = {(flg)}, \
67 .num_planes = np, \
68 .tile_height = th \
72 #define INTERLEAVED_YUV_FMT(fmt, a, r, g, b, e0, e1, e2, e3, \
73 alpha, chroma, count, bp, flg, fm, np) \
74 { \
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, \
82 .unpack_tight = 1, \
83 .unpack_count = count, \
84 .bpp = bp, \
85 .fetch_mode = fm, \
86 .flag = {(flg)}, \
87 .num_planes = np, \
88 .tile_height = DPU_TILE_HEIGHT_DEFAULT \
91 #define PSEUDO_YUV_FMT(fmt, a, r, g, b, e0, e1, chroma, flg, fm, np) \
92 { \
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, \
100 .unpack_tight = 1, \
101 .unpack_count = 2, \
102 .bpp = 2, \
103 .fetch_mode = fm, \
104 .flag = {(flg)}, \
105 .num_planes = np, \
106 .tile_height = DPU_TILE_HEIGHT_DEFAULT \
109 #define PSEUDO_YUV_FMT_TILED(fmt, a, r, g, b, e0, e1, chroma, \
110 flg, fm, np, th) \
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, \
119 .unpack_tight = 1, \
120 .unpack_count = 2, \
121 .bpp = 2, \
122 .fetch_mode = fm, \
123 .flag = {(flg)}, \
124 .num_planes = np, \
125 .tile_height = th \
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, \
137 .unpack_tight = 0, \
138 .unpack_count = 2, \
139 .bpp = 2, \
140 .fetch_mode = fm, \
141 .flag = {(flg)}, \
142 .num_planes = np, \
143 .tile_height = DPU_TILE_HEIGHT_DEFAULT \
146 #define PSEUDO_YUV_FMT_LOOSE_TILED(fmt, a, r, g, b, e0, e1, chroma, \
147 flg, fm, np, th) \
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, \
156 .unpack_tight = 0, \
157 .unpack_count = 2, \
158 .bpp = 2, \
159 .fetch_mode = fm, \
160 .flag = {(flg)}, \
161 .num_planes = np, \
162 .tile_height = th \
166 #define PLANAR_YUV_FMT(fmt, a, r, g, b, e0, e1, e2, alpha, chroma, bp, \
167 flg, fm, np) \
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, \
176 .unpack_tight = 1, \
177 .unpack_count = 1, \
178 .bpp = bp, \
179 .fetch_mode = fm, \
180 .flag = {(flg)}, \
181 .num_planes = np, \
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 {
191 uint32_t format;
192 uint32_t color;
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,
199 true, 4, 0,
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,
205 true, 4, 0,
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,
211 false, 4, 0,
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,
217 true, 4, 0,
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,
223 true, 4, 0,
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,
229 false, 4, 0,
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,
235 false, 4, 0,
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,
241 false, 4, 0,
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,
247 false, 3, 0,
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,
253 false, 3, 0,
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,
259 false, 2, 0,
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,
265 false, 2, 0,
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,
271 true, 2, 0,
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,
277 true, 2, 0,
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,
283 true, 2, 0,
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,
289 true, 2, 0,
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,
295 false, 2, 0,
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,
301 false, 2, 0,
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,
307 false, 2, 0,
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,
313 false, 2, 0,
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,
319 true, 2, 0,
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,
325 true, 2, 0,
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,
331 true, 2, 0,
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,
337 true, 2, 0,
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,
343 false, 2, 0,
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,
349 false, 2, 0,
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,
355 false, 2, 0,
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,
361 false, 2, 0,
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),
412 PSEUDO_YUV_FMT(NV12,
413 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
414 C1_B_Cb, C2_R_Cr,
415 DPU_CHROMA_420, DPU_FORMAT_FLAG_YUV,
416 DPU_FETCH_LINEAR, 2),
418 PSEUDO_YUV_FMT(NV21,
419 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
420 C2_R_Cr, C1_B_Cb,
421 DPU_CHROMA_420, DPU_FORMAT_FLAG_YUV,
422 DPU_FETCH_LINEAR, 2),
424 PSEUDO_YUV_FMT(NV16,
425 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
426 C1_B_Cb, C2_R_Cr,
427 DPU_CHROMA_H2V1, DPU_FORMAT_FLAG_YUV,
428 DPU_FETCH_LINEAR, 2),
430 PSEUDO_YUV_FMT(NV61,
431 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
432 C2_R_Cr, C1_B_Cb,
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
494 * natively.
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,
528 C1_B_Cb, C2_R_Cr,
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,
539 uint32_t *v_sample,
540 uint32_t *h_sample)
542 if (!v_sample || !h_sample)
543 return;
545 switch (chroma_sample) {
546 case DPU_CHROMA_H2V1:
547 *v_sample = 1;
548 *h_sample = 2;
549 break;
550 case DPU_CHROMA_H1V2:
551 *v_sample = 2;
552 *h_sample = 1;
553 break;
554 case DPU_CHROMA_420:
555 *v_sample = 2;
556 *h_sample = 2;
557 break;
558 default:
559 *v_sample = 1;
560 *h_sample = 1;
561 break;
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},
576 int color_fmt = -1;
577 int i;
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;
583 else
584 color_fmt = COLOR_FMT_P010_UBWC;
585 } else
586 color_fmt = COLOR_FMT_NV12_UBWC;
587 return color_fmt;
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;
593 break;
595 return color_fmt;
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)
604 int i;
605 int color;
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);
615 if (color < 0) {
616 DRM_ERROR("UBWC format not supported for fmt: %4.4s\n",
617 (char *)&fmt->base.pixel_format);
618 return -EINVAL;
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);
637 if (!meta)
638 goto done;
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);
651 } else {
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);
661 if (!meta)
662 goto done;
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);
670 done:
671 for (i = 0; i < DPU_MAX_PLANES; i++)
672 layout->total_size += layout->plane_size[i];
674 return 0;
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)
684 int i;
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;
697 } else {
698 uint32_t v_subsample, h_subsample;
699 uint32_t chroma_samp;
700 uint32_t bpp = 1;
702 chroma_samp = fmt->chroma_sample;
703 _dpu_get_v_h_subsample_rate(chroma_samp, &v_subsample,
704 &h_subsample);
706 if (width % h_subsample || height % v_subsample) {
707 DRM_ERROR("mismatch in subsample vs dimensions\n");
708 return -EINVAL;
711 if ((fmt->base.pixel_format == DRM_FORMAT_NV12) &&
712 (DPU_FORMAT_IS_DX(fmt)))
713 bpp = 2;
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;
724 } else {
725 /* planar */
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
734 * the requirement.
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];
746 return 0;
749 static int dpu_format_get_plane_sizes(
750 const struct dpu_format *fmt,
751 const uint32_t w,
752 const uint32_t h,
753 struct dpu_hw_fmt_layout *layout,
754 const uint32_t *pitches)
756 if (!layout || !fmt) {
757 DRM_ERROR("invalid pointer\n");
758 return -EINVAL;
761 if ((w > DPU_MAX_IMG_WIDTH) || (h > DPU_MAX_IMG_HEIGHT)) {
762 DRM_ERROR("image dimensions outside max range\n");
763 return -ERANGE;
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;
778 bool meta;
780 if (!fb || !layout) {
781 DRM_ERROR("invalid pointers\n");
782 return -EINVAL;
785 if (aspace)
786 base_addr = msm_framebuffer_iova(fb, aspace, 0);
787 if (!base_addr) {
788 DRM_ERROR("failed to retrieve base addr\n");
789 return -EFAULT;
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 /************************************************/
797 /* UBWC ** */
798 /* buffer ** DPU PLANE */
799 /* format ** */
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];
823 if (!meta)
824 return 0;
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];
833 } else {
834 /************************************************/
835 /* UBWC ** */
836 /* buffer ** DPU PLANE */
837 /* format ** */
838 /************************************************/
839 /* ------------------- ** -------------------- */
840 /* | RGB meta | ** | RGB bitstream | */
841 /* | data | ** | plane | */
842 /* ------------------- ** -------------------- */
843 /* | RGB bitstream | ** | NONE | */
844 /* | data | ** | | */
845 /* ------------------- ** -------------------- */
846 /* ** | RGB meta | */
847 /* ** | plane | */
848 /* ** -------------------- */
849 /************************************************/
851 layout->plane_addr[0] = base_addr + layout->plane_size[2];
852 layout->plane_addr[1] = 0;
854 if (!meta)
855 return 0;
857 layout->plane_addr[2] = base_addr;
858 layout->plane_addr[3] = 0;
860 return 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)
868 unsigned int i;
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]);
875 return -EINVAL;
879 /* Populate addresses for simple formats here */
880 for (i = 0; i < layout->num_planes; ++i) {
881 if (aspace)
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");
886 return -EFAULT;
890 return 0;
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];
899 int i, ret;
901 if (!fb || !layout) {
902 DRM_ERROR("invalid arguments\n");
903 return -EINVAL;
906 if ((fb->width > DPU_MAX_IMG_WIDTH) ||
907 (fb->height > DPU_MAX_IMG_HEIGHT)) {
908 DRM_ERROR("image dimensions outside max range\n");
909 return -ERANGE;
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);
917 if (ret)
918 return ret;
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);
927 else
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)))
932 ret = -EAGAIN;
934 return ret;
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;
947 int ret, i;
949 if (!msm_fmt || !cmd || !bos) {
950 DRM_ERROR("invalid arguments\n");
951 return -EINVAL;
954 fmt = to_dpu_format(msm_fmt);
955 info = drm_format_info(fmt->base.pixel_format);
956 if (!info)
957 return -EINVAL;
959 ret = dpu_format_get_plane_sizes(fmt, cmd->width, cmd->height,
960 &layout, cmd->pitches);
961 if (ret)
962 return ret;
964 for (i = 0; i < info->num_planes; i++) {
965 if (!bos[i]) {
966 DRM_ERROR("invalid handle for plane %d\n", i);
967 return -EINVAL;
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);
976 return -EINVAL;
979 return 0;
982 const struct dpu_format *dpu_get_dpu_format_ext(
983 const uint32_t format,
984 const uint64_t modifier)
986 uint32_t i = 0;
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);
997 switch (modifier) {
998 case 0:
999 map = dpu_format_map;
1000 map_size = ARRAY_SIZE(dpu_format_map);
1001 break;
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",
1006 (char *)&format);
1007 break;
1008 default:
1009 DPU_ERROR("unsupported format modifier %llX\n", modifier);
1010 return NULL;
1013 for (i = 0; i < map_size; i++) {
1014 if (format == map[i].base.pixel_format) {
1015 fmt = &map[i];
1016 break;
1020 if (fmt == NULL)
1021 DPU_ERROR("unsupported fmt: %4.4s modifier 0x%llX\n",
1022 (char *)&format, modifier);
1023 else
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));
1029 return 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,
1038 modifiers);
1039 if (fmt)
1040 return &fmt->base;
1041 return NULL;