Loading...
Note: File does not exist in v3.1.
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, \
35bp, 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, \
54alpha, 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, \
74alpha, 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, \
111flg, 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, \
148flg, 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, \
168flg, 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 */
191struct dpu_media_color_map {
192 uint32_t format;
193 uint32_t color;
194};
195
196static 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 */
486static 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 PSEUDO_YUV_FMT_TILED(NV12,
540 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
541 C1_B_Cb, C2_R_Cr,
542 DPU_CHROMA_420, DPU_FORMAT_FLAG_YUV |
543 DPU_FORMAT_FLAG_COMPRESSED,
544 DPU_FETCH_UBWC, 4, DPU_TILE_HEIGHT_NV12),
545
546 PSEUDO_YUV_FMT_TILED(P010,
547 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
548 C1_B_Cb, C2_R_Cr,
549 DPU_CHROMA_420, DPU_FORMAT_FLAG_DX |
550 DPU_FORMAT_FLAG_YUV |
551 DPU_FORMAT_FLAG_COMPRESSED,
552 DPU_FETCH_UBWC, 4, DPU_TILE_HEIGHT_UBWC),
553};
554
555/* _dpu_get_v_h_subsample_rate - Get subsample rates for all formats we support
556 * Note: Not using the drm_format_*_subsampling since we have formats
557 */
558static void _dpu_get_v_h_subsample_rate(
559 enum dpu_chroma_samp_type chroma_sample,
560 uint32_t *v_sample,
561 uint32_t *h_sample)
562{
563 if (!v_sample || !h_sample)
564 return;
565
566 switch (chroma_sample) {
567 case DPU_CHROMA_H2V1:
568 *v_sample = 1;
569 *h_sample = 2;
570 break;
571 case DPU_CHROMA_H1V2:
572 *v_sample = 2;
573 *h_sample = 1;
574 break;
575 case DPU_CHROMA_420:
576 *v_sample = 2;
577 *h_sample = 2;
578 break;
579 default:
580 *v_sample = 1;
581 *h_sample = 1;
582 break;
583 }
584}
585
586static int _dpu_format_get_media_color_ubwc(const struct dpu_format *fmt)
587{
588 static const struct dpu_media_color_map dpu_media_ubwc_map[] = {
589 {DRM_FORMAT_ABGR8888, COLOR_FMT_RGBA8888_UBWC},
590 {DRM_FORMAT_ARGB8888, COLOR_FMT_RGBA8888_UBWC},
591 {DRM_FORMAT_XBGR8888, COLOR_FMT_RGBA8888_UBWC},
592 {DRM_FORMAT_XRGB8888, COLOR_FMT_RGBA8888_UBWC},
593 {DRM_FORMAT_ABGR2101010, COLOR_FMT_RGBA1010102_UBWC},
594 {DRM_FORMAT_XRGB2101010, COLOR_FMT_RGBA1010102_UBWC},
595 {DRM_FORMAT_XBGR2101010, COLOR_FMT_RGBA1010102_UBWC},
596 {DRM_FORMAT_BGR565, COLOR_FMT_RGB565_UBWC},
597 };
598 int color_fmt = -1;
599 int i;
600
601 if (fmt->base.pixel_format == DRM_FORMAT_NV12 ||
602 fmt->base.pixel_format == DRM_FORMAT_P010) {
603 if (DPU_FORMAT_IS_DX(fmt)) {
604 if (fmt->unpack_tight)
605 color_fmt = COLOR_FMT_NV12_BPP10_UBWC;
606 else
607 color_fmt = COLOR_FMT_P010_UBWC;
608 } else
609 color_fmt = COLOR_FMT_NV12_UBWC;
610 return color_fmt;
611 }
612
613 for (i = 0; i < ARRAY_SIZE(dpu_media_ubwc_map); ++i)
614 if (fmt->base.pixel_format == dpu_media_ubwc_map[i].format) {
615 color_fmt = dpu_media_ubwc_map[i].color;
616 break;
617 }
618 return color_fmt;
619}
620
621static int _dpu_format_get_plane_sizes_ubwc(
622 const struct dpu_format *fmt,
623 const uint32_t width,
624 const uint32_t height,
625 struct dpu_hw_fmt_layout *layout)
626{
627 int i;
628 int color;
629 bool meta = DPU_FORMAT_IS_UBWC(fmt);
630
631 memset(layout, 0, sizeof(struct dpu_hw_fmt_layout));
632 layout->format = fmt;
633 layout->width = width;
634 layout->height = height;
635 layout->num_planes = fmt->num_planes;
636
637 color = _dpu_format_get_media_color_ubwc(fmt);
638 if (color < 0) {
639 DRM_ERROR("UBWC format not supported for fmt: %4.4s\n",
640 (char *)&fmt->base.pixel_format);
641 return -EINVAL;
642 }
643
644 if (DPU_FORMAT_IS_YUV(layout->format)) {
645 uint32_t y_sclines, uv_sclines;
646 uint32_t y_meta_scanlines = 0;
647 uint32_t uv_meta_scanlines = 0;
648
649 layout->num_planes = 2;
650 layout->plane_pitch[0] = VENUS_Y_STRIDE(color, width);
651 y_sclines = VENUS_Y_SCANLINES(color, height);
652 layout->plane_size[0] = MSM_MEDIA_ALIGN(layout->plane_pitch[0] *
653 y_sclines, DPU_UBWC_PLANE_SIZE_ALIGNMENT);
654
655 layout->plane_pitch[1] = VENUS_UV_STRIDE(color, width);
656 uv_sclines = VENUS_UV_SCANLINES(color, height);
657 layout->plane_size[1] = MSM_MEDIA_ALIGN(layout->plane_pitch[1] *
658 uv_sclines, DPU_UBWC_PLANE_SIZE_ALIGNMENT);
659
660 if (!meta)
661 goto done;
662
663 layout->num_planes += 2;
664 layout->plane_pitch[2] = VENUS_Y_META_STRIDE(color, width);
665 y_meta_scanlines = VENUS_Y_META_SCANLINES(color, height);
666 layout->plane_size[2] = MSM_MEDIA_ALIGN(layout->plane_pitch[2] *
667 y_meta_scanlines, DPU_UBWC_PLANE_SIZE_ALIGNMENT);
668
669 layout->plane_pitch[3] = VENUS_UV_META_STRIDE(color, width);
670 uv_meta_scanlines = VENUS_UV_META_SCANLINES(color, height);
671 layout->plane_size[3] = MSM_MEDIA_ALIGN(layout->plane_pitch[3] *
672 uv_meta_scanlines, DPU_UBWC_PLANE_SIZE_ALIGNMENT);
673
674 } else {
675 uint32_t rgb_scanlines, rgb_meta_scanlines;
676
677 layout->num_planes = 1;
678
679 layout->plane_pitch[0] = VENUS_RGB_STRIDE(color, width);
680 rgb_scanlines = VENUS_RGB_SCANLINES(color, height);
681 layout->plane_size[0] = MSM_MEDIA_ALIGN(layout->plane_pitch[0] *
682 rgb_scanlines, DPU_UBWC_PLANE_SIZE_ALIGNMENT);
683
684 if (!meta)
685 goto done;
686 layout->num_planes += 2;
687 layout->plane_pitch[2] = VENUS_RGB_META_STRIDE(color, width);
688 rgb_meta_scanlines = VENUS_RGB_META_SCANLINES(color, height);
689 layout->plane_size[2] = MSM_MEDIA_ALIGN(layout->plane_pitch[2] *
690 rgb_meta_scanlines, DPU_UBWC_PLANE_SIZE_ALIGNMENT);
691 }
692
693done:
694 for (i = 0; i < DPU_MAX_PLANES; i++)
695 layout->total_size += layout->plane_size[i];
696
697 return 0;
698}
699
700static int _dpu_format_get_plane_sizes_linear(
701 const struct dpu_format *fmt,
702 const uint32_t width,
703 const uint32_t height,
704 struct dpu_hw_fmt_layout *layout,
705 const uint32_t *pitches)
706{
707 int i;
708
709 memset(layout, 0, sizeof(struct dpu_hw_fmt_layout));
710 layout->format = fmt;
711 layout->width = width;
712 layout->height = height;
713 layout->num_planes = fmt->num_planes;
714
715 /* Due to memset above, only need to set planes of interest */
716 if (fmt->fetch_planes == DPU_PLANE_INTERLEAVED) {
717 layout->num_planes = 1;
718 layout->plane_size[0] = width * height * layout->format->bpp;
719 layout->plane_pitch[0] = width * layout->format->bpp;
720 } else {
721 uint32_t v_subsample, h_subsample;
722 uint32_t chroma_samp;
723 uint32_t bpp = 1;
724
725 chroma_samp = fmt->chroma_sample;
726 _dpu_get_v_h_subsample_rate(chroma_samp, &v_subsample,
727 &h_subsample);
728
729 if (width % h_subsample || height % v_subsample) {
730 DRM_ERROR("mismatch in subsample vs dimensions\n");
731 return -EINVAL;
732 }
733
734 if ((fmt->base.pixel_format == DRM_FORMAT_NV12) &&
735 (DPU_FORMAT_IS_DX(fmt)))
736 bpp = 2;
737 layout->plane_pitch[0] = width * bpp;
738 layout->plane_pitch[1] = layout->plane_pitch[0] / h_subsample;
739 layout->plane_size[0] = layout->plane_pitch[0] * height;
740 layout->plane_size[1] = layout->plane_pitch[1] *
741 (height / v_subsample);
742
743 if (fmt->fetch_planes == DPU_PLANE_PSEUDO_PLANAR) {
744 layout->num_planes = 2;
745 layout->plane_size[1] *= 2;
746 layout->plane_pitch[1] *= 2;
747 } else {
748 /* planar */
749 layout->num_planes = 3;
750 layout->plane_size[2] = layout->plane_size[1];
751 layout->plane_pitch[2] = layout->plane_pitch[1];
752 }
753 }
754
755 /*
756 * linear format: allow user allocated pitches if they are greater than
757 * the requirement.
758 * ubwc format: pitch values are computed uniformly across
759 * all the components based on ubwc specifications.
760 */
761 for (i = 0; i < layout->num_planes && i < DPU_MAX_PLANES; ++i) {
762 if (pitches && layout->plane_pitch[i] < pitches[i])
763 layout->plane_pitch[i] = pitches[i];
764 }
765
766 for (i = 0; i < DPU_MAX_PLANES; i++)
767 layout->total_size += layout->plane_size[i];
768
769 return 0;
770}
771
772static int dpu_format_get_plane_sizes(
773 const struct dpu_format *fmt,
774 const uint32_t w,
775 const uint32_t h,
776 struct dpu_hw_fmt_layout *layout,
777 const uint32_t *pitches)
778{
779 if (!layout || !fmt) {
780 DRM_ERROR("invalid pointer\n");
781 return -EINVAL;
782 }
783
784 if ((w > DPU_MAX_IMG_WIDTH) || (h > DPU_MAX_IMG_HEIGHT)) {
785 DRM_ERROR("image dimensions outside max range\n");
786 return -ERANGE;
787 }
788
789 if (DPU_FORMAT_IS_UBWC(fmt) || DPU_FORMAT_IS_TILE(fmt))
790 return _dpu_format_get_plane_sizes_ubwc(fmt, w, h, layout);
791
792 return _dpu_format_get_plane_sizes_linear(fmt, w, h, layout, pitches);
793}
794
795static int _dpu_format_populate_addrs_ubwc(
796 struct msm_gem_address_space *aspace,
797 struct drm_framebuffer *fb,
798 struct dpu_hw_fmt_layout *layout)
799{
800 uint32_t base_addr = 0;
801 bool meta;
802
803 if (!fb || !layout) {
804 DRM_ERROR("invalid pointers\n");
805 return -EINVAL;
806 }
807
808 if (aspace)
809 base_addr = msm_framebuffer_iova(fb, aspace, 0);
810 if (!base_addr) {
811 DRM_ERROR("failed to retrieve base addr\n");
812 return -EFAULT;
813 }
814
815 meta = DPU_FORMAT_IS_UBWC(layout->format);
816
817 /* Per-format logic for verifying active planes */
818 if (DPU_FORMAT_IS_YUV(layout->format)) {
819 /************************************************/
820 /* UBWC ** */
821 /* buffer ** DPU PLANE */
822 /* format ** */
823 /************************************************/
824 /* ------------------- ** -------------------- */
825 /* | Y meta | ** | Y bitstream | */
826 /* | data | ** | plane | */
827 /* ------------------- ** -------------------- */
828 /* | Y bitstream | ** | CbCr bitstream | */
829 /* | data | ** | plane | */
830 /* ------------------- ** -------------------- */
831 /* | Cbcr metadata | ** | Y meta | */
832 /* | data | ** | plane | */
833 /* ------------------- ** -------------------- */
834 /* | CbCr bitstream | ** | CbCr meta | */
835 /* | data | ** | plane | */
836 /* ------------------- ** -------------------- */
837 /************************************************/
838
839 /* configure Y bitstream plane */
840 layout->plane_addr[0] = base_addr + layout->plane_size[2];
841
842 /* configure CbCr bitstream plane */
843 layout->plane_addr[1] = base_addr + layout->plane_size[0]
844 + layout->plane_size[2] + layout->plane_size[3];
845
846 if (!meta)
847 return 0;
848
849 /* configure Y metadata plane */
850 layout->plane_addr[2] = base_addr;
851
852 /* configure CbCr metadata plane */
853 layout->plane_addr[3] = base_addr + layout->plane_size[0]
854 + layout->plane_size[2];
855
856 } else {
857 /************************************************/
858 /* UBWC ** */
859 /* buffer ** DPU PLANE */
860 /* format ** */
861 /************************************************/
862 /* ------------------- ** -------------------- */
863 /* | RGB meta | ** | RGB bitstream | */
864 /* | data | ** | plane | */
865 /* ------------------- ** -------------------- */
866 /* | RGB bitstream | ** | NONE | */
867 /* | data | ** | | */
868 /* ------------------- ** -------------------- */
869 /* ** | RGB meta | */
870 /* ** | plane | */
871 /* ** -------------------- */
872 /************************************************/
873
874 layout->plane_addr[0] = base_addr + layout->plane_size[2];
875 layout->plane_addr[1] = 0;
876
877 if (!meta)
878 return 0;
879
880 layout->plane_addr[2] = base_addr;
881 layout->plane_addr[3] = 0;
882 }
883 return 0;
884}
885
886static int _dpu_format_populate_addrs_linear(
887 struct msm_gem_address_space *aspace,
888 struct drm_framebuffer *fb,
889 struct dpu_hw_fmt_layout *layout)
890{
891 unsigned int i;
892
893 /* Can now check the pitches given vs pitches expected */
894 for (i = 0; i < layout->num_planes; ++i) {
895 if (layout->plane_pitch[i] > fb->pitches[i]) {
896 DRM_ERROR("plane %u expected pitch %u, fb %u\n",
897 i, layout->plane_pitch[i], fb->pitches[i]);
898 return -EINVAL;
899 }
900 }
901
902 /* Populate addresses for simple formats here */
903 for (i = 0; i < layout->num_planes; ++i) {
904 if (aspace)
905 layout->plane_addr[i] =
906 msm_framebuffer_iova(fb, aspace, i);
907 if (!layout->plane_addr[i]) {
908 DRM_ERROR("failed to retrieve base addr\n");
909 return -EFAULT;
910 }
911 }
912
913 return 0;
914}
915
916int dpu_format_populate_layout(
917 struct msm_gem_address_space *aspace,
918 struct drm_framebuffer *fb,
919 struct dpu_hw_fmt_layout *layout)
920{
921 uint32_t plane_addr[DPU_MAX_PLANES];
922 int i, ret;
923
924 if (!fb || !layout) {
925 DRM_ERROR("invalid arguments\n");
926 return -EINVAL;
927 }
928
929 if ((fb->width > DPU_MAX_IMG_WIDTH) ||
930 (fb->height > DPU_MAX_IMG_HEIGHT)) {
931 DRM_ERROR("image dimensions outside max range\n");
932 return -ERANGE;
933 }
934
935 layout->format = to_dpu_format(msm_framebuffer_format(fb));
936
937 /* Populate the plane sizes etc via get_format */
938 ret = dpu_format_get_plane_sizes(layout->format, fb->width, fb->height,
939 layout, fb->pitches);
940 if (ret)
941 return ret;
942
943 for (i = 0; i < DPU_MAX_PLANES; ++i)
944 plane_addr[i] = layout->plane_addr[i];
945
946 /* Populate the addresses given the fb */
947 if (DPU_FORMAT_IS_UBWC(layout->format) ||
948 DPU_FORMAT_IS_TILE(layout->format))
949 ret = _dpu_format_populate_addrs_ubwc(aspace, fb, layout);
950 else
951 ret = _dpu_format_populate_addrs_linear(aspace, fb, layout);
952
953 /* check if anything changed */
954 if (!ret && !memcmp(plane_addr, layout->plane_addr, sizeof(plane_addr)))
955 ret = -EAGAIN;
956
957 return ret;
958}
959
960int dpu_format_check_modified_format(
961 const struct msm_kms *kms,
962 const struct msm_format *msm_fmt,
963 const struct drm_mode_fb_cmd2 *cmd,
964 struct drm_gem_object **bos)
965{
966 const struct drm_format_info *info;
967 const struct dpu_format *fmt;
968 struct dpu_hw_fmt_layout layout;
969 uint32_t bos_total_size = 0;
970 int ret, i;
971
972 if (!msm_fmt || !cmd || !bos) {
973 DRM_ERROR("invalid arguments\n");
974 return -EINVAL;
975 }
976
977 fmt = to_dpu_format(msm_fmt);
978 info = drm_format_info(fmt->base.pixel_format);
979 if (!info)
980 return -EINVAL;
981
982 ret = dpu_format_get_plane_sizes(fmt, cmd->width, cmd->height,
983 &layout, cmd->pitches);
984 if (ret)
985 return ret;
986
987 for (i = 0; i < info->num_planes; i++) {
988 if (!bos[i]) {
989 DRM_ERROR("invalid handle for plane %d\n", i);
990 return -EINVAL;
991 }
992 if ((i == 0) || (bos[i] != bos[0]))
993 bos_total_size += bos[i]->size;
994 }
995
996 if (bos_total_size < layout.total_size) {
997 DRM_ERROR("buffers total size too small %u expected %u\n",
998 bos_total_size, layout.total_size);
999 return -EINVAL;
1000 }
1001
1002 return 0;
1003}
1004
1005const struct dpu_format *dpu_get_dpu_format_ext(
1006 const uint32_t format,
1007 const uint64_t modifier)
1008{
1009 uint32_t i = 0;
1010 const struct dpu_format *fmt = NULL;
1011 const struct dpu_format *map = NULL;
1012 ssize_t map_size = 0;
1013
1014 /*
1015 * Currently only support exactly zero or one modifier.
1016 * All planes use the same modifier.
1017 */
1018 DRM_DEBUG_ATOMIC("plane format modifier 0x%llX\n", modifier);
1019
1020 switch (modifier) {
1021 case 0:
1022 map = dpu_format_map;
1023 map_size = ARRAY_SIZE(dpu_format_map);
1024 break;
1025 case DRM_FORMAT_MOD_QCOM_COMPRESSED:
1026 map = dpu_format_map_ubwc;
1027 map_size = ARRAY_SIZE(dpu_format_map_ubwc);
1028 DRM_DEBUG_ATOMIC("found fmt: %4.4s DRM_FORMAT_MOD_QCOM_COMPRESSED\n",
1029 (char *)&format);
1030 break;
1031 default:
1032 DPU_ERROR("unsupported format modifier %llX\n", modifier);
1033 return NULL;
1034 }
1035
1036 for (i = 0; i < map_size; i++) {
1037 if (format == map[i].base.pixel_format) {
1038 fmt = &map[i];
1039 break;
1040 }
1041 }
1042
1043 if (fmt == NULL)
1044 DPU_ERROR("unsupported fmt: %4.4s modifier 0x%llX\n",
1045 (char *)&format, modifier);
1046 else
1047 DRM_DEBUG_ATOMIC("fmt %4.4s mod 0x%llX ubwc %d yuv %d\n",
1048 (char *)&format, modifier,
1049 DPU_FORMAT_IS_UBWC(fmt),
1050 DPU_FORMAT_IS_YUV(fmt));
1051
1052 return fmt;
1053}
1054
1055const struct msm_format *dpu_get_msm_format(
1056 struct msm_kms *kms,
1057 const uint32_t format,
1058 const uint64_t modifiers)
1059{
1060 const struct dpu_format *fmt = dpu_get_dpu_format_ext(format,
1061 modifiers);
1062 if (fmt)
1063 return &fmt->base;
1064 return NULL;
1065}