1 // SPDX-License-Identifier: GPL-2.0-only
2 /* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
3 */
4
5 #define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__
6
7 #include <uapi/drm/drm_fourcc.h>
8 #include <drm/drm_framebuffer.h>
9
10 #include "msm_media_info.h"
11 #include "dpu_kms.h"
12 #include "dpu_formats.h"
13
14 #define DPU_UBWC_META_MACRO_W_H 16
15 #define DPU_UBWC_META_BLOCK_SIZE 256
16 #define DPU_UBWC_PLANE_SIZE_ALIGNMENT 4096
17
18 #define DPU_TILE_HEIGHT_DEFAULT 1
19 #define DPU_TILE_HEIGHT_TILED 4
20 #define DPU_TILE_HEIGHT_UBWC 4
21 #define DPU_TILE_HEIGHT_NV12 8
22
23 #define DPU_MAX_IMG_WIDTH 0x3FFF
24 #define DPU_MAX_IMG_HEIGHT 0x3FFF
25
26 /*
27 * DPU supported format packing, bpp, and other format
28 * information.
29 * DPU currently only supports interleaved RGB formats
30 * UBWC support for a pixel format is indicated by the flag,
31 * there is additional meta data plane for such formats
32 */
33
34 #define INTERLEAVED_RGB_FMT(fmt, a, r, g, b, e0, e1, e2, e3, uc, alpha, \
35 bp, flg, fm, np) \
36 { \
37 .base.pixel_format = DRM_FORMAT_ ## fmt, \
38 .fetch_planes = DPU_PLANE_INTERLEAVED, \
39 .alpha_enable = alpha, \
40 .element = { (e0), (e1), (e2), (e3) }, \
41 .bits = { g, b, r, a }, \
42 .chroma_sample = DPU_CHROMA_RGB, \
43 .unpack_align_msb = 0, \
44 .unpack_tight = 1, \
45 .unpack_count = uc, \
46 .bpp = bp, \
47 .fetch_mode = fm, \
48 .flag = {(flg)}, \
49 .num_planes = np, \
50 .tile_height = DPU_TILE_HEIGHT_DEFAULT \
51 }
52
53 #define INTERLEAVED_RGB_FMT_TILED(fmt, a, r, g, b, e0, e1, e2, e3, uc, \
54 alpha, bp, flg, fm, np, th) \
55 { \
56 .base.pixel_format = DRM_FORMAT_ ## fmt, \
57 .fetch_planes = DPU_PLANE_INTERLEAVED, \
58 .alpha_enable = alpha, \
59 .element = { (e0), (e1), (e2), (e3) }, \
60 .bits = { g, b, r, a }, \
61 .chroma_sample = DPU_CHROMA_RGB, \
62 .unpack_align_msb = 0, \
63 .unpack_tight = 1, \
64 .unpack_count = uc, \
65 .bpp = bp, \
66 .fetch_mode = fm, \
67 .flag = {(flg)}, \
68 .num_planes = np, \
69 .tile_height = th \
70 }
71
72
73 #define INTERLEAVED_YUV_FMT(fmt, a, r, g, b, e0, e1, e2, e3, \
74 alpha, chroma, count, bp, flg, fm, np) \
75 { \
76 .base.pixel_format = DRM_FORMAT_ ## fmt, \
77 .fetch_planes = DPU_PLANE_INTERLEAVED, \
78 .alpha_enable = alpha, \
79 .element = { (e0), (e1), (e2), (e3)}, \
80 .bits = { g, b, r, a }, \
81 .chroma_sample = chroma, \
82 .unpack_align_msb = 0, \
83 .unpack_tight = 1, \
84 .unpack_count = count, \
85 .bpp = bp, \
86 .fetch_mode = fm, \
87 .flag = {(flg)}, \
88 .num_planes = np, \
89 .tile_height = DPU_TILE_HEIGHT_DEFAULT \
90 }
91
92 #define PSEUDO_YUV_FMT(fmt, a, r, g, b, e0, e1, chroma, flg, fm, np) \
93 { \
94 .base.pixel_format = DRM_FORMAT_ ## fmt, \
95 .fetch_planes = DPU_PLANE_PSEUDO_PLANAR, \
96 .alpha_enable = false, \
97 .element = { (e0), (e1), 0, 0 }, \
98 .bits = { g, b, r, a }, \
99 .chroma_sample = chroma, \
100 .unpack_align_msb = 0, \
101 .unpack_tight = 1, \
102 .unpack_count = 2, \
103 .bpp = 2, \
104 .fetch_mode = fm, \
105 .flag = {(flg)}, \
106 .num_planes = np, \
107 .tile_height = DPU_TILE_HEIGHT_DEFAULT \
108 }
109
110 #define PSEUDO_YUV_FMT_TILED(fmt, a, r, g, b, e0, e1, chroma, \
111 flg, fm, np, th) \
112 { \
113 .base.pixel_format = DRM_FORMAT_ ## fmt, \
114 .fetch_planes = DPU_PLANE_PSEUDO_PLANAR, \
115 .alpha_enable = false, \
116 .element = { (e0), (e1), 0, 0 }, \
117 .bits = { g, b, r, a }, \
118 .chroma_sample = chroma, \
119 .unpack_align_msb = 0, \
120 .unpack_tight = 1, \
121 .unpack_count = 2, \
122 .bpp = 2, \
123 .fetch_mode = fm, \
124 .flag = {(flg)}, \
125 .num_planes = np, \
126 .tile_height = th \
127 }
128
129 #define PSEUDO_YUV_FMT_LOOSE(fmt, a, r, g, b, e0, e1, chroma, flg, fm, np)\
130 { \
131 .base.pixel_format = DRM_FORMAT_ ## fmt, \
132 .fetch_planes = DPU_PLANE_PSEUDO_PLANAR, \
133 .alpha_enable = false, \
134 .element = { (e0), (e1), 0, 0 }, \
135 .bits = { g, b, r, a }, \
136 .chroma_sample = chroma, \
137 .unpack_align_msb = 1, \
138 .unpack_tight = 0, \
139 .unpack_count = 2, \
140 .bpp = 2, \
141 .fetch_mode = fm, \
142 .flag = {(flg)}, \
143 .num_planes = np, \
144 .tile_height = DPU_TILE_HEIGHT_DEFAULT \
145 }
146
147 #define PSEUDO_YUV_FMT_LOOSE_TILED(fmt, a, r, g, b, e0, e1, chroma, \
148 flg, fm, np, th) \
149 { \
150 .base.pixel_format = DRM_FORMAT_ ## fmt, \
151 .fetch_planes = DPU_PLANE_PSEUDO_PLANAR, \
152 .alpha_enable = false, \
153 .element = { (e0), (e1), 0, 0 }, \
154 .bits = { g, b, r, a }, \
155 .chroma_sample = chroma, \
156 .unpack_align_msb = 1, \
157 .unpack_tight = 0, \
158 .unpack_count = 2, \
159 .bpp = 2, \
160 .fetch_mode = fm, \
161 .flag = {(flg)}, \
162 .num_planes = np, \
163 .tile_height = th \
164 }
165
166
167 #define PLANAR_YUV_FMT(fmt, a, r, g, b, e0, e1, e2, alpha, chroma, bp, \
168 flg, fm, np) \
169 { \
170 .base.pixel_format = DRM_FORMAT_ ## fmt, \
171 .fetch_planes = DPU_PLANE_PLANAR, \
172 .alpha_enable = alpha, \
173 .element = { (e0), (e1), (e2), 0 }, \
174 .bits = { g, b, r, a }, \
175 .chroma_sample = chroma, \
176 .unpack_align_msb = 0, \
177 .unpack_tight = 1, \
178 .unpack_count = 1, \
179 .bpp = bp, \
180 .fetch_mode = fm, \
181 .flag = {(flg)}, \
182 .num_planes = np, \
183 .tile_height = DPU_TILE_HEIGHT_DEFAULT \
184 }
185
186 /*
187 * struct dpu_media_color_map - maps drm format to media format
188 * @format: DRM base pixel format
189 * @color: Media API color related to DRM format
190 */
191 struct dpu_media_color_map {
192 uint32_t format;
193 uint32_t color;
194 };
195
196 static const struct dpu_format dpu_format_map[] = {
197 INTERLEAVED_RGB_FMT(ARGB8888,
198 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
199 C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA, 4,
200 true, 4, 0,
201 DPU_FETCH_LINEAR, 1),
202
203 INTERLEAVED_RGB_FMT(ABGR8888,
204 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
205 C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
206 true, 4, 0,
207 DPU_FETCH_LINEAR, 1),
208
209 INTERLEAVED_RGB_FMT(XBGR8888,
210 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
211 C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
212 false, 4, 0,
213 DPU_FETCH_LINEAR, 1),
214
215 INTERLEAVED_RGB_FMT(RGBA8888,
216 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
217 C3_ALPHA, C1_B_Cb, C0_G_Y, C2_R_Cr, 4,
218 true, 4, 0,
219 DPU_FETCH_LINEAR, 1),
220
221 INTERLEAVED_RGB_FMT(BGRA8888,
222 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
223 C3_ALPHA, C2_R_Cr, C0_G_Y, C1_B_Cb, 4,
224 true, 4, 0,
225 DPU_FETCH_LINEAR, 1),
226
227 INTERLEAVED_RGB_FMT(BGRX8888,
228 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
229 C3_ALPHA, C2_R_Cr, C0_G_Y, C1_B_Cb, 4,
230 false, 4, 0,
231 DPU_FETCH_LINEAR, 1),
232
233 INTERLEAVED_RGB_FMT(XRGB8888,
234 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
235 C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA, 4,
236 false, 4, 0,
237 DPU_FETCH_LINEAR, 1),
238
239 INTERLEAVED_RGB_FMT(RGBX8888,
240 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
241 C3_ALPHA, C1_B_Cb, C0_G_Y, C2_R_Cr, 4,
242 false, 4, 0,
243 DPU_FETCH_LINEAR, 1),
244
245 INTERLEAVED_RGB_FMT(RGB888,
246 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
247 C1_B_Cb, C0_G_Y, C2_R_Cr, 0, 3,
248 false, 3, 0,
249 DPU_FETCH_LINEAR, 1),
250
251 INTERLEAVED_RGB_FMT(BGR888,
252 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
253 C2_R_Cr, C0_G_Y, C1_B_Cb, 0, 3,
254 false, 3, 0,
255 DPU_FETCH_LINEAR, 1),
256
257 INTERLEAVED_RGB_FMT(RGB565,
258 0, COLOR_5BIT, COLOR_6BIT, COLOR_5BIT,
259 C1_B_Cb, C0_G_Y, C2_R_Cr, 0, 3,
260 false, 2, 0,
261 DPU_FETCH_LINEAR, 1),
262
263 INTERLEAVED_RGB_FMT(BGR565,
264 0, COLOR_5BIT, COLOR_6BIT, COLOR_5BIT,
265 C2_R_Cr, C0_G_Y, C1_B_Cb, 0, 3,
266 false, 2, 0,
267 DPU_FETCH_LINEAR, 1),
268
269 INTERLEAVED_RGB_FMT(ARGB1555,
270 COLOR_ALPHA_1BIT, COLOR_5BIT, COLOR_5BIT, COLOR_5BIT,
271 C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA, 4,
272 true, 2, 0,
273 DPU_FETCH_LINEAR, 1),
274
275 INTERLEAVED_RGB_FMT(ABGR1555,
276 COLOR_ALPHA_1BIT, COLOR_5BIT, COLOR_5BIT, COLOR_5BIT,
277 C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
278 true, 2, 0,
279 DPU_FETCH_LINEAR, 1),
280
281 INTERLEAVED_RGB_FMT(RGBA5551,
282 COLOR_ALPHA_1BIT, COLOR_5BIT, COLOR_5BIT, COLOR_5BIT,
283 C3_ALPHA, C1_B_Cb, C0_G_Y, C2_R_Cr, 4,
284 true, 2, 0,
285 DPU_FETCH_LINEAR, 1),
286
287 INTERLEAVED_RGB_FMT(BGRA5551,
288 COLOR_ALPHA_1BIT, COLOR_5BIT, COLOR_5BIT, COLOR_5BIT,
289 C3_ALPHA, C2_R_Cr, C0_G_Y, C1_B_Cb, 4,
290 true, 2, 0,
291 DPU_FETCH_LINEAR, 1),
292
293 INTERLEAVED_RGB_FMT(XRGB1555,
294 COLOR_ALPHA_1BIT, COLOR_5BIT, COLOR_5BIT, COLOR_5BIT,
295 C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA, 4,
296 false, 2, 0,
297 DPU_FETCH_LINEAR, 1),
298
299 INTERLEAVED_RGB_FMT(XBGR1555,
300 COLOR_ALPHA_1BIT, COLOR_5BIT, COLOR_5BIT, COLOR_5BIT,
301 C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
302 false, 2, 0,
303 DPU_FETCH_LINEAR, 1),
304
305 INTERLEAVED_RGB_FMT(RGBX5551,
306 COLOR_ALPHA_1BIT, COLOR_5BIT, COLOR_5BIT, COLOR_5BIT,
307 C3_ALPHA, C1_B_Cb, C0_G_Y, C2_R_Cr, 4,
308 false, 2, 0,
309 DPU_FETCH_LINEAR, 1),
310
311 INTERLEAVED_RGB_FMT(BGRX5551,
312 COLOR_ALPHA_1BIT, COLOR_5BIT, COLOR_5BIT, COLOR_5BIT,
313 C3_ALPHA, C2_R_Cr, C0_G_Y, C1_B_Cb, 4,
314 false, 2, 0,
315 DPU_FETCH_LINEAR, 1),
316
317 INTERLEAVED_RGB_FMT(ARGB4444,
318 COLOR_ALPHA_4BIT, COLOR_4BIT, COLOR_4BIT, COLOR_4BIT,
319 C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA, 4,
320 true, 2, 0,
321 DPU_FETCH_LINEAR, 1),
322
323 INTERLEAVED_RGB_FMT(ABGR4444,
324 COLOR_ALPHA_4BIT, COLOR_4BIT, COLOR_4BIT, COLOR_4BIT,
325 C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
326 true, 2, 0,
327 DPU_FETCH_LINEAR, 1),
328
329 INTERLEAVED_RGB_FMT(RGBA4444,
330 COLOR_ALPHA_4BIT, COLOR_4BIT, COLOR_4BIT, COLOR_4BIT,
331 C3_ALPHA, C1_B_Cb, C0_G_Y, C2_R_Cr, 4,
332 true, 2, 0,
333 DPU_FETCH_LINEAR, 1),
334
335 INTERLEAVED_RGB_FMT(BGRA4444,
336 COLOR_ALPHA_4BIT, COLOR_4BIT, COLOR_4BIT, COLOR_4BIT,
337 C3_ALPHA, C2_R_Cr, C0_G_Y, C1_B_Cb, 4,
338 true, 2, 0,
339 DPU_FETCH_LINEAR, 1),
340
341 INTERLEAVED_RGB_FMT(XRGB4444,
342 COLOR_ALPHA_4BIT, COLOR_4BIT, COLOR_4BIT, COLOR_4BIT,
343 C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA, 4,
344 false, 2, 0,
345 DPU_FETCH_LINEAR, 1),
346
347 INTERLEAVED_RGB_FMT(XBGR4444,
348 COLOR_ALPHA_4BIT, COLOR_4BIT, COLOR_4BIT, COLOR_4BIT,
349 C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
350 false, 2, 0,
351 DPU_FETCH_LINEAR, 1),
352
353 INTERLEAVED_RGB_FMT(RGBX4444,
354 COLOR_ALPHA_4BIT, COLOR_4BIT, COLOR_4BIT, COLOR_4BIT,
355 C3_ALPHA, C1_B_Cb, C0_G_Y, C2_R_Cr, 4,
356 false, 2, 0,
357 DPU_FETCH_LINEAR, 1),
358
359 INTERLEAVED_RGB_FMT(BGRX4444,
360 COLOR_ALPHA_4BIT, COLOR_4BIT, COLOR_4BIT, COLOR_4BIT,
361 C3_ALPHA, C2_R_Cr, C0_G_Y, C1_B_Cb, 4,
362 false, 2, 0,
363 DPU_FETCH_LINEAR, 1),
364
365 INTERLEAVED_RGB_FMT(BGRA1010102,
366 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
367 C3_ALPHA, C2_R_Cr, C0_G_Y, C1_B_Cb, 4,
368 true, 4, DPU_FORMAT_FLAG_DX,
369 DPU_FETCH_LINEAR, 1),
370
371 INTERLEAVED_RGB_FMT(RGBA1010102,
372 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
373 C3_ALPHA, C1_B_Cb, C0_G_Y, C2_R_Cr, 4,
374 true, 4, DPU_FORMAT_FLAG_DX,
375 DPU_FETCH_LINEAR, 1),
376
377 INTERLEAVED_RGB_FMT(ABGR2101010,
378 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
379 C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
380 true, 4, DPU_FORMAT_FLAG_DX,
381 DPU_FETCH_LINEAR, 1),
382
383 INTERLEAVED_RGB_FMT(ARGB2101010,
384 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
385 C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA, 4,
386 true, 4, DPU_FORMAT_FLAG_DX,
387 DPU_FETCH_LINEAR, 1),
388
389 INTERLEAVED_RGB_FMT(XRGB2101010,
390 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
391 C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA, 4,
392 false, 4, DPU_FORMAT_FLAG_DX,
393 DPU_FETCH_LINEAR, 1),
394
395 INTERLEAVED_RGB_FMT(BGRX1010102,
396 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
397 C3_ALPHA, C2_R_Cr, C0_G_Y, C1_B_Cb, 4,
398 false, 4, DPU_FORMAT_FLAG_DX,
399 DPU_FETCH_LINEAR, 1),
400
401 INTERLEAVED_RGB_FMT(XBGR2101010,
402 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
403 C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
404 false, 4, DPU_FORMAT_FLAG_DX,
405 DPU_FETCH_LINEAR, 1),
406
407 INTERLEAVED_RGB_FMT(RGBX1010102,
408 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
409 C3_ALPHA, C1_B_Cb, C0_G_Y, C2_R_Cr, 4,
410 false, 4, DPU_FORMAT_FLAG_DX,
411 DPU_FETCH_LINEAR, 1),
412
413 PSEUDO_YUV_FMT(NV12,
414 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
415 C1_B_Cb, C2_R_Cr,
416 DPU_CHROMA_420, DPU_FORMAT_FLAG_YUV,
417 DPU_FETCH_LINEAR, 2),
418
419 PSEUDO_YUV_FMT(NV21,
420 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
421 C2_R_Cr, C1_B_Cb,
422 DPU_CHROMA_420, DPU_FORMAT_FLAG_YUV,
423 DPU_FETCH_LINEAR, 2),
424
425 PSEUDO_YUV_FMT(NV16,
426 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
427 C1_B_Cb, C2_R_Cr,
428 DPU_CHROMA_H2V1, DPU_FORMAT_FLAG_YUV,
429 DPU_FETCH_LINEAR, 2),
430
431 PSEUDO_YUV_FMT(NV61,
432 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
433 C2_R_Cr, C1_B_Cb,
434 DPU_CHROMA_H2V1, DPU_FORMAT_FLAG_YUV,
435 DPU_FETCH_LINEAR, 2),
436
437 PSEUDO_YUV_FMT_LOOSE(P010,
438 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
439 C1_B_Cb, C2_R_Cr,
440 DPU_CHROMA_420, DPU_FORMAT_FLAG_DX | DPU_FORMAT_FLAG_YUV,
441 DPU_FETCH_LINEAR, 2),
442
443 INTERLEAVED_YUV_FMT(VYUY,
444 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
445 C2_R_Cr, C0_G_Y, C1_B_Cb, C0_G_Y,
446 false, DPU_CHROMA_H2V1, 4, 2, DPU_FORMAT_FLAG_YUV,
447 DPU_FETCH_LINEAR, 2),
448
449 INTERLEAVED_YUV_FMT(UYVY,
450 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
451 C1_B_Cb, C0_G_Y, C2_R_Cr, C0_G_Y,
452 false, DPU_CHROMA_H2V1, 4, 2, DPU_FORMAT_FLAG_YUV,
453 DPU_FETCH_LINEAR, 2),
454
455 INTERLEAVED_YUV_FMT(YUYV,
456 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
457 C0_G_Y, C1_B_Cb, C0_G_Y, C2_R_Cr,
458 false, DPU_CHROMA_H2V1, 4, 2, DPU_FORMAT_FLAG_YUV,
459 DPU_FETCH_LINEAR, 2),
460
461 INTERLEAVED_YUV_FMT(YVYU,
462 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
463 C0_G_Y, C2_R_Cr, C0_G_Y, C1_B_Cb,
464 false, DPU_CHROMA_H2V1, 4, 2, DPU_FORMAT_FLAG_YUV,
465 DPU_FETCH_LINEAR, 2),
466
467 PLANAR_YUV_FMT(YUV420,
468 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
469 C2_R_Cr, C1_B_Cb, C0_G_Y,
470 false, DPU_CHROMA_420, 1, DPU_FORMAT_FLAG_YUV,
471 DPU_FETCH_LINEAR, 3),
472
473 PLANAR_YUV_FMT(YVU420,
474 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
475 C1_B_Cb, C2_R_Cr, C0_G_Y,
476 false, DPU_CHROMA_420, 1, DPU_FORMAT_FLAG_YUV,
477 DPU_FETCH_LINEAR, 3),
478 };
479
480 /*
481 * UBWC formats table:
482 * This table holds the UBWC formats supported.
483 * If a compression ratio needs to be used for this or any other format,
484 * the data will be passed by user-space.
485 */
486 static const struct dpu_format dpu_format_map_ubwc[] = {
487 INTERLEAVED_RGB_FMT_TILED(BGR565,
488 0, COLOR_5BIT, COLOR_6BIT, COLOR_5BIT,
489 C2_R_Cr, C0_G_Y, C1_B_Cb, 0, 3,
490 false, 2, DPU_FORMAT_FLAG_COMPRESSED,
491 DPU_FETCH_UBWC, 2, DPU_TILE_HEIGHT_UBWC),
492
493 INTERLEAVED_RGB_FMT_TILED(ABGR8888,
494 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
495 C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
496 true, 4, DPU_FORMAT_FLAG_COMPRESSED,
497 DPU_FETCH_UBWC, 2, DPU_TILE_HEIGHT_UBWC),
498
499 /* ARGB8888 and ABGR8888 purposely have the same color
500 * ordering. The hardware only supports ABGR8888 UBWC
501 * natively.
502 */
503 INTERLEAVED_RGB_FMT_TILED(ARGB8888,
504 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
505 C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
506 true, 4, DPU_FORMAT_FLAG_COMPRESSED,
507 DPU_FETCH_UBWC, 2, DPU_TILE_HEIGHT_UBWC),
508
509 INTERLEAVED_RGB_FMT_TILED(XBGR8888,
510 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
511 C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
512 false, 4, DPU_FORMAT_FLAG_COMPRESSED,
513 DPU_FETCH_UBWC, 2, DPU_TILE_HEIGHT_UBWC),
514
515 INTERLEAVED_RGB_FMT_TILED(XRGB8888,
516 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
517 C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
518 false, 4, DPU_FORMAT_FLAG_COMPRESSED,
519 DPU_FETCH_UBWC, 2, DPU_TILE_HEIGHT_UBWC),
520
521 INTERLEAVED_RGB_FMT_TILED(ABGR2101010,
522 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
523 C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
524 true, 4, DPU_FORMAT_FLAG_DX | DPU_FORMAT_FLAG_COMPRESSED,
525 DPU_FETCH_UBWC, 2, DPU_TILE_HEIGHT_UBWC),
526
527 INTERLEAVED_RGB_FMT_TILED(XBGR2101010,
528 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
529 C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
530 true, 4, DPU_FORMAT_FLAG_DX | DPU_FORMAT_FLAG_COMPRESSED,
531 DPU_FETCH_UBWC, 2, DPU_TILE_HEIGHT_UBWC),
532
533 INTERLEAVED_RGB_FMT_TILED(XRGB2101010,
534 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
535 C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
536 true, 4, DPU_FORMAT_FLAG_DX | DPU_FORMAT_FLAG_COMPRESSED,
537 DPU_FETCH_UBWC, 2, DPU_TILE_HEIGHT_UBWC),
538
539 /* XRGB2101010 and ARGB2101010 purposely have the same color
540 * ordering. The hardware only supports ARGB2101010 UBWC
541 * natively.
542 */
543 INTERLEAVED_RGB_FMT_TILED(ARGB2101010,
544 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
545 C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
546 true, 4, DPU_FORMAT_FLAG_DX | DPU_FORMAT_FLAG_COMPRESSED,
547 DPU_FETCH_UBWC, 2, DPU_TILE_HEIGHT_UBWC),
548
549 PSEUDO_YUV_FMT_TILED(NV12,
550 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
551 C1_B_Cb, C2_R_Cr,
552 DPU_CHROMA_420, DPU_FORMAT_FLAG_YUV |
553 DPU_FORMAT_FLAG_COMPRESSED,
554 DPU_FETCH_UBWC, 4, DPU_TILE_HEIGHT_NV12),
555
556 PSEUDO_YUV_FMT_TILED(P010,
557 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
558 C1_B_Cb, C2_R_Cr,
559 DPU_CHROMA_420, DPU_FORMAT_FLAG_DX |
560 DPU_FORMAT_FLAG_YUV |
561 DPU_FORMAT_FLAG_COMPRESSED,
562 DPU_FETCH_UBWC, 4, DPU_TILE_HEIGHT_UBWC),
563 };
564
565 /* _dpu_get_v_h_subsample_rate - Get subsample rates for all formats we support
566 * Note: Not using the drm_format_*_subsampling since we have formats
567 */
_dpu_get_v_h_subsample_rate(enum dpu_chroma_samp_type chroma_sample,uint32_t * v_sample,uint32_t * h_sample)568 static void _dpu_get_v_h_subsample_rate(
569 enum dpu_chroma_samp_type chroma_sample,
570 uint32_t *v_sample,
571 uint32_t *h_sample)
572 {
573 if (!v_sample || !h_sample)
574 return;
575
576 switch (chroma_sample) {
577 case DPU_CHROMA_H2V1:
578 *v_sample = 1;
579 *h_sample = 2;
580 break;
581 case DPU_CHROMA_H1V2:
582 *v_sample = 2;
583 *h_sample = 1;
584 break;
585 case DPU_CHROMA_420:
586 *v_sample = 2;
587 *h_sample = 2;
588 break;
589 default:
590 *v_sample = 1;
591 *h_sample = 1;
592 break;
593 }
594 }
595
_dpu_format_get_media_color_ubwc(const struct dpu_format * fmt)596 static int _dpu_format_get_media_color_ubwc(const struct dpu_format *fmt)
597 {
598 static const struct dpu_media_color_map dpu_media_ubwc_map[] = {
599 {DRM_FORMAT_ABGR8888, COLOR_FMT_RGBA8888_UBWC},
600 {DRM_FORMAT_ARGB8888, COLOR_FMT_RGBA8888_UBWC},
601 {DRM_FORMAT_XBGR8888, COLOR_FMT_RGBA8888_UBWC},
602 {DRM_FORMAT_XRGB8888, COLOR_FMT_RGBA8888_UBWC},
603 {DRM_FORMAT_ABGR2101010, COLOR_FMT_RGBA1010102_UBWC},
604 {DRM_FORMAT_ARGB2101010, COLOR_FMT_RGBA1010102_UBWC},
605 {DRM_FORMAT_XRGB2101010, COLOR_FMT_RGBA1010102_UBWC},
606 {DRM_FORMAT_XBGR2101010, COLOR_FMT_RGBA1010102_UBWC},
607 {DRM_FORMAT_BGR565, COLOR_FMT_RGB565_UBWC},
608 };
609 int color_fmt = -1;
610 int i;
611
612 if (fmt->base.pixel_format == DRM_FORMAT_NV12 ||
613 fmt->base.pixel_format == DRM_FORMAT_P010) {
614 if (DPU_FORMAT_IS_DX(fmt)) {
615 if (fmt->unpack_tight)
616 color_fmt = COLOR_FMT_NV12_BPP10_UBWC;
617 else
618 color_fmt = COLOR_FMT_P010_UBWC;
619 } else
620 color_fmt = COLOR_FMT_NV12_UBWC;
621 return color_fmt;
622 }
623
624 for (i = 0; i < ARRAY_SIZE(dpu_media_ubwc_map); ++i)
625 if (fmt->base.pixel_format == dpu_media_ubwc_map[i].format) {
626 color_fmt = dpu_media_ubwc_map[i].color;
627 break;
628 }
629 return color_fmt;
630 }
631
_dpu_format_get_plane_sizes_ubwc(const struct dpu_format * fmt,const uint32_t width,const uint32_t height,struct dpu_hw_fmt_layout * layout)632 static int _dpu_format_get_plane_sizes_ubwc(
633 const struct dpu_format *fmt,
634 const uint32_t width,
635 const uint32_t height,
636 struct dpu_hw_fmt_layout *layout)
637 {
638 int i;
639 int color;
640 bool meta = DPU_FORMAT_IS_UBWC(fmt);
641
642 memset(layout, 0, sizeof(struct dpu_hw_fmt_layout));
643 layout->format = fmt;
644 layout->width = width;
645 layout->height = height;
646 layout->num_planes = fmt->num_planes;
647
648 color = _dpu_format_get_media_color_ubwc(fmt);
649 if (color < 0) {
650 DRM_ERROR("UBWC format not supported for fmt: %4.4s\n",
651 (char *)&fmt->base.pixel_format);
652 return -EINVAL;
653 }
654
655 if (DPU_FORMAT_IS_YUV(layout->format)) {
656 uint32_t y_sclines, uv_sclines;
657 uint32_t y_meta_scanlines = 0;
658 uint32_t uv_meta_scanlines = 0;
659
660 layout->num_planes = 2;
661 layout->plane_pitch[0] = VENUS_Y_STRIDE(color, width);
662 y_sclines = VENUS_Y_SCANLINES(color, height);
663 layout->plane_size[0] = MSM_MEDIA_ALIGN(layout->plane_pitch[0] *
664 y_sclines, DPU_UBWC_PLANE_SIZE_ALIGNMENT);
665
666 layout->plane_pitch[1] = VENUS_UV_STRIDE(color, width);
667 uv_sclines = VENUS_UV_SCANLINES(color, height);
668 layout->plane_size[1] = MSM_MEDIA_ALIGN(layout->plane_pitch[1] *
669 uv_sclines, DPU_UBWC_PLANE_SIZE_ALIGNMENT);
670
671 if (!meta)
672 goto done;
673
674 layout->num_planes += 2;
675 layout->plane_pitch[2] = VENUS_Y_META_STRIDE(color, width);
676 y_meta_scanlines = VENUS_Y_META_SCANLINES(color, height);
677 layout->plane_size[2] = MSM_MEDIA_ALIGN(layout->plane_pitch[2] *
678 y_meta_scanlines, DPU_UBWC_PLANE_SIZE_ALIGNMENT);
679
680 layout->plane_pitch[3] = VENUS_UV_META_STRIDE(color, width);
681 uv_meta_scanlines = VENUS_UV_META_SCANLINES(color, height);
682 layout->plane_size[3] = MSM_MEDIA_ALIGN(layout->plane_pitch[3] *
683 uv_meta_scanlines, DPU_UBWC_PLANE_SIZE_ALIGNMENT);
684
685 } else {
686 uint32_t rgb_scanlines, rgb_meta_scanlines;
687
688 layout->num_planes = 1;
689
690 layout->plane_pitch[0] = VENUS_RGB_STRIDE(color, width);
691 rgb_scanlines = VENUS_RGB_SCANLINES(color, height);
692 layout->plane_size[0] = MSM_MEDIA_ALIGN(layout->plane_pitch[0] *
693 rgb_scanlines, DPU_UBWC_PLANE_SIZE_ALIGNMENT);
694
695 if (!meta)
696 goto done;
697 layout->num_planes += 2;
698 layout->plane_pitch[2] = VENUS_RGB_META_STRIDE(color, width);
699 rgb_meta_scanlines = VENUS_RGB_META_SCANLINES(color, height);
700 layout->plane_size[2] = MSM_MEDIA_ALIGN(layout->plane_pitch[2] *
701 rgb_meta_scanlines, DPU_UBWC_PLANE_SIZE_ALIGNMENT);
702 }
703
704 done:
705 for (i = 0; i < DPU_MAX_PLANES; i++)
706 layout->total_size += layout->plane_size[i];
707
708 return 0;
709 }
710
_dpu_format_get_plane_sizes_linear(const struct dpu_format * fmt,const uint32_t width,const uint32_t height,struct dpu_hw_fmt_layout * layout,const uint32_t * pitches)711 static int _dpu_format_get_plane_sizes_linear(
712 const struct dpu_format *fmt,
713 const uint32_t width,
714 const uint32_t height,
715 struct dpu_hw_fmt_layout *layout,
716 const uint32_t *pitches)
717 {
718 int i;
719
720 memset(layout, 0, sizeof(struct dpu_hw_fmt_layout));
721 layout->format = fmt;
722 layout->width = width;
723 layout->height = height;
724 layout->num_planes = fmt->num_planes;
725
726 /* Due to memset above, only need to set planes of interest */
727 if (fmt->fetch_planes == DPU_PLANE_INTERLEAVED) {
728 layout->num_planes = 1;
729 layout->plane_size[0] = width * height * layout->format->bpp;
730 layout->plane_pitch[0] = width * layout->format->bpp;
731 } else {
732 uint32_t v_subsample, h_subsample;
733 uint32_t chroma_samp;
734 uint32_t bpp = 1;
735
736 chroma_samp = fmt->chroma_sample;
737 _dpu_get_v_h_subsample_rate(chroma_samp, &v_subsample,
738 &h_subsample);
739
740 if (width % h_subsample || height % v_subsample) {
741 DRM_ERROR("mismatch in subsample vs dimensions\n");
742 return -EINVAL;
743 }
744
745 if ((fmt->base.pixel_format == DRM_FORMAT_NV12) &&
746 (DPU_FORMAT_IS_DX(fmt)))
747 bpp = 2;
748 layout->plane_pitch[0] = width * bpp;
749 layout->plane_pitch[1] = layout->plane_pitch[0] / h_subsample;
750 layout->plane_size[0] = layout->plane_pitch[0] * height;
751 layout->plane_size[1] = layout->plane_pitch[1] *
752 (height / v_subsample);
753
754 if (fmt->fetch_planes == DPU_PLANE_PSEUDO_PLANAR) {
755 layout->num_planes = 2;
756 layout->plane_size[1] *= 2;
757 layout->plane_pitch[1] *= 2;
758 } else {
759 /* planar */
760 layout->num_planes = 3;
761 layout->plane_size[2] = layout->plane_size[1];
762 layout->plane_pitch[2] = layout->plane_pitch[1];
763 }
764 }
765
766 /*
767 * linear format: allow user allocated pitches if they are greater than
768 * the requirement.
769 * ubwc format: pitch values are computed uniformly across
770 * all the components based on ubwc specifications.
771 */
772 for (i = 0; i < layout->num_planes && i < DPU_MAX_PLANES; ++i) {
773 if (pitches && layout->plane_pitch[i] < pitches[i])
774 layout->plane_pitch[i] = pitches[i];
775 }
776
777 for (i = 0; i < DPU_MAX_PLANES; i++)
778 layout->total_size += layout->plane_size[i];
779
780 return 0;
781 }
782
dpu_format_get_plane_sizes(const struct dpu_format * fmt,const uint32_t w,const uint32_t h,struct dpu_hw_fmt_layout * layout,const uint32_t * pitches)783 static int dpu_format_get_plane_sizes(
784 const struct dpu_format *fmt,
785 const uint32_t w,
786 const uint32_t h,
787 struct dpu_hw_fmt_layout *layout,
788 const uint32_t *pitches)
789 {
790 if (!layout || !fmt) {
791 DRM_ERROR("invalid pointer\n");
792 return -EINVAL;
793 }
794
795 if ((w > DPU_MAX_IMG_WIDTH) || (h > DPU_MAX_IMG_HEIGHT)) {
796 DRM_ERROR("image dimensions outside max range\n");
797 return -ERANGE;
798 }
799
800 if (DPU_FORMAT_IS_UBWC(fmt) || DPU_FORMAT_IS_TILE(fmt))
801 return _dpu_format_get_plane_sizes_ubwc(fmt, w, h, layout);
802
803 return _dpu_format_get_plane_sizes_linear(fmt, w, h, layout, pitches);
804 }
805
_dpu_format_populate_addrs_ubwc(struct msm_gem_address_space * aspace,struct drm_framebuffer * fb,struct dpu_hw_fmt_layout * layout)806 static int _dpu_format_populate_addrs_ubwc(
807 struct msm_gem_address_space *aspace,
808 struct drm_framebuffer *fb,
809 struct dpu_hw_fmt_layout *layout)
810 {
811 uint32_t base_addr = 0;
812 bool meta;
813
814 if (!fb || !layout) {
815 DRM_ERROR("invalid pointers\n");
816 return -EINVAL;
817 }
818
819 if (aspace)
820 base_addr = msm_framebuffer_iova(fb, aspace, 0);
821 if (!base_addr) {
822 DRM_ERROR("failed to retrieve base addr\n");
823 return -EFAULT;
824 }
825
826 meta = DPU_FORMAT_IS_UBWC(layout->format);
827
828 /* Per-format logic for verifying active planes */
829 if (DPU_FORMAT_IS_YUV(layout->format)) {
830 /************************************************/
831 /* UBWC ** */
832 /* buffer ** DPU PLANE */
833 /* format ** */
834 /************************************************/
835 /* ------------------- ** -------------------- */
836 /* | Y meta | ** | Y bitstream | */
837 /* | data | ** | plane | */
838 /* ------------------- ** -------------------- */
839 /* | Y bitstream | ** | CbCr bitstream | */
840 /* | data | ** | plane | */
841 /* ------------------- ** -------------------- */
842 /* | Cbcr metadata | ** | Y meta | */
843 /* | data | ** | plane | */
844 /* ------------------- ** -------------------- */
845 /* | CbCr bitstream | ** | CbCr meta | */
846 /* | data | ** | plane | */
847 /* ------------------- ** -------------------- */
848 /************************************************/
849
850 /* configure Y bitstream plane */
851 layout->plane_addr[0] = base_addr + layout->plane_size[2];
852
853 /* configure CbCr bitstream plane */
854 layout->plane_addr[1] = base_addr + layout->plane_size[0]
855 + layout->plane_size[2] + layout->plane_size[3];
856
857 if (!meta)
858 return 0;
859
860 /* configure Y metadata plane */
861 layout->plane_addr[2] = base_addr;
862
863 /* configure CbCr metadata plane */
864 layout->plane_addr[3] = base_addr + layout->plane_size[0]
865 + layout->plane_size[2];
866
867 } else {
868 /************************************************/
869 /* UBWC ** */
870 /* buffer ** DPU PLANE */
871 /* format ** */
872 /************************************************/
873 /* ------------------- ** -------------------- */
874 /* | RGB meta | ** | RGB bitstream | */
875 /* | data | ** | plane | */
876 /* ------------------- ** -------------------- */
877 /* | RGB bitstream | ** | NONE | */
878 /* | data | ** | | */
879 /* ------------------- ** -------------------- */
880 /* ** | RGB meta | */
881 /* ** | plane | */
882 /* ** -------------------- */
883 /************************************************/
884
885 layout->plane_addr[0] = base_addr + layout->plane_size[2];
886 layout->plane_addr[1] = 0;
887
888 if (!meta)
889 return 0;
890
891 layout->plane_addr[2] = base_addr;
892 layout->plane_addr[3] = 0;
893 }
894 return 0;
895 }
896
_dpu_format_populate_addrs_linear(struct msm_gem_address_space * aspace,struct drm_framebuffer * fb,struct dpu_hw_fmt_layout * layout)897 static int _dpu_format_populate_addrs_linear(
898 struct msm_gem_address_space *aspace,
899 struct drm_framebuffer *fb,
900 struct dpu_hw_fmt_layout *layout)
901 {
902 unsigned int i;
903
904 /* Can now check the pitches given vs pitches expected */
905 for (i = 0; i < layout->num_planes; ++i) {
906 if (layout->plane_pitch[i] > fb->pitches[i]) {
907 DRM_ERROR("plane %u expected pitch %u, fb %u\n",
908 i, layout->plane_pitch[i], fb->pitches[i]);
909 return -EINVAL;
910 }
911 }
912
913 /* Populate addresses for simple formats here */
914 for (i = 0; i < layout->num_planes; ++i) {
915 if (aspace)
916 layout->plane_addr[i] =
917 msm_framebuffer_iova(fb, aspace, i);
918 if (!layout->plane_addr[i]) {
919 DRM_ERROR("failed to retrieve base addr\n");
920 return -EFAULT;
921 }
922 }
923
924 return 0;
925 }
926
dpu_format_populate_layout(struct msm_gem_address_space * aspace,struct drm_framebuffer * fb,struct dpu_hw_fmt_layout * layout)927 int dpu_format_populate_layout(
928 struct msm_gem_address_space *aspace,
929 struct drm_framebuffer *fb,
930 struct dpu_hw_fmt_layout *layout)
931 {
932 int ret;
933
934 if (!fb || !layout) {
935 DRM_ERROR("invalid arguments\n");
936 return -EINVAL;
937 }
938
939 if ((fb->width > DPU_MAX_IMG_WIDTH) ||
940 (fb->height > DPU_MAX_IMG_HEIGHT)) {
941 DRM_ERROR("image dimensions outside max range\n");
942 return -ERANGE;
943 }
944
945 layout->format = to_dpu_format(msm_framebuffer_format(fb));
946
947 /* Populate the plane sizes etc via get_format */
948 ret = dpu_format_get_plane_sizes(layout->format, fb->width, fb->height,
949 layout, fb->pitches);
950 if (ret)
951 return ret;
952
953 /* Populate the addresses given the fb */
954 if (DPU_FORMAT_IS_UBWC(layout->format) ||
955 DPU_FORMAT_IS_TILE(layout->format))
956 ret = _dpu_format_populate_addrs_ubwc(aspace, fb, layout);
957 else
958 ret = _dpu_format_populate_addrs_linear(aspace, fb, layout);
959
960 return ret;
961 }
962
dpu_format_check_modified_format(const struct msm_kms * kms,const struct msm_format * msm_fmt,const struct drm_mode_fb_cmd2 * cmd,struct drm_gem_object ** bos)963 int dpu_format_check_modified_format(
964 const struct msm_kms *kms,
965 const struct msm_format *msm_fmt,
966 const struct drm_mode_fb_cmd2 *cmd,
967 struct drm_gem_object **bos)
968 {
969 const struct drm_format_info *info;
970 const struct dpu_format *fmt;
971 struct dpu_hw_fmt_layout layout;
972 uint32_t bos_total_size = 0;
973 int ret, i;
974
975 if (!msm_fmt || !cmd || !bos) {
976 DRM_ERROR("invalid arguments\n");
977 return -EINVAL;
978 }
979
980 fmt = to_dpu_format(msm_fmt);
981 info = drm_format_info(fmt->base.pixel_format);
982 if (!info)
983 return -EINVAL;
984
985 ret = dpu_format_get_plane_sizes(fmt, cmd->width, cmd->height,
986 &layout, cmd->pitches);
987 if (ret)
988 return ret;
989
990 for (i = 0; i < info->num_planes; i++) {
991 if (!bos[i]) {
992 DRM_ERROR("invalid handle for plane %d\n", i);
993 return -EINVAL;
994 }
995 if ((i == 0) || (bos[i] != bos[0]))
996 bos_total_size += bos[i]->size;
997 }
998
999 if (bos_total_size < layout.total_size) {
1000 DRM_ERROR("buffers total size too small %u expected %u\n",
1001 bos_total_size, layout.total_size);
1002 return -EINVAL;
1003 }
1004
1005 return 0;
1006 }
1007
dpu_get_dpu_format_ext(const uint32_t format,const uint64_t modifier)1008 const struct dpu_format *dpu_get_dpu_format_ext(
1009 const uint32_t format,
1010 const uint64_t modifier)
1011 {
1012 uint32_t i = 0;
1013 const struct dpu_format *fmt = NULL;
1014 const struct dpu_format *map = NULL;
1015 ssize_t map_size = 0;
1016
1017 /*
1018 * Currently only support exactly zero or one modifier.
1019 * All planes use the same modifier.
1020 */
1021 DRM_DEBUG_ATOMIC("plane format modifier 0x%llX\n", modifier);
1022
1023 switch (modifier) {
1024 case 0:
1025 map = dpu_format_map;
1026 map_size = ARRAY_SIZE(dpu_format_map);
1027 break;
1028 case DRM_FORMAT_MOD_QCOM_COMPRESSED:
1029 map = dpu_format_map_ubwc;
1030 map_size = ARRAY_SIZE(dpu_format_map_ubwc);
1031 DRM_DEBUG_ATOMIC("found fmt: %4.4s DRM_FORMAT_MOD_QCOM_COMPRESSED\n",
1032 (char *)&format);
1033 break;
1034 default:
1035 DPU_ERROR("unsupported format modifier %llX\n", modifier);
1036 return NULL;
1037 }
1038
1039 for (i = 0; i < map_size; i++) {
1040 if (format == map[i].base.pixel_format) {
1041 fmt = &map[i];
1042 break;
1043 }
1044 }
1045
1046 if (fmt == NULL)
1047 DPU_ERROR("unsupported fmt: %4.4s modifier 0x%llX\n",
1048 (char *)&format, modifier);
1049 else
1050 DRM_DEBUG_ATOMIC("fmt %4.4s mod 0x%llX ubwc %d yuv %d\n",
1051 (char *)&format, modifier,
1052 DPU_FORMAT_IS_UBWC(fmt),
1053 DPU_FORMAT_IS_YUV(fmt));
1054
1055 return fmt;
1056 }
1057
dpu_get_msm_format(struct msm_kms * kms,const uint32_t format,const uint64_t modifiers)1058 const struct msm_format *dpu_get_msm_format(
1059 struct msm_kms *kms,
1060 const uint32_t format,
1061 const uint64_t modifiers)
1062 {
1063 const struct dpu_format *fmt = dpu_get_dpu_format_ext(format,
1064 modifiers);
1065 if (fmt)
1066 return &fmt->base;
1067 return NULL;
1068 }
1069