xref: /linux/drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c (revision ebf68996de0ab250c5d520eb2291ab65643e9a1e)
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 
9 #include "msm_media_info.h"
10 #include "dpu_kms.h"
11 #include "dpu_formats.h"
12 
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
16 
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
21 
22 #define DPU_MAX_IMG_WIDTH		0x3FFF
23 #define DPU_MAX_IMG_HEIGHT		0x3FFF
24 
25 /**
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
31  */
32 
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                            \
50 }
51 
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                                                 \
69 }
70 
71 
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                            \
89 }
90 
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                            \
107 }
108 
109 #define PSEUDO_YUV_FMT_TILED(fmt, a, r, g, b, e0, e1, chroma,             \
110 flg, fm, np, th)                                                          \
111 {                                                                         \
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                                                 \
126 }
127 
128 #define PSEUDO_YUV_FMT_LOOSE(fmt, a, r, g, b, e0, e1, chroma, flg, fm, np)\
129 {                                                                         \
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                            \
144 }
145 
146 #define PSEUDO_YUV_FMT_LOOSE_TILED(fmt, a, r, g, b, e0, e1, chroma,       \
147 flg, fm, np, th)                                                          \
148 {                                                                         \
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                                                 \
163 }
164 
165 
166 #define PLANAR_YUV_FMT(fmt, a, r, g, b, e0, e1, e2, alpha, chroma, bp,    \
167 flg, fm, np)                                                      \
168 {                                                                         \
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                            \
183 }
184 
185 /*
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
189  */
190 struct dpu_media_color_map {
191 	uint32_t format;
192 	uint32_t color;
193 };
194 
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),
201 
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),
207 
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),
213 
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),
219 
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),
225 
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),
231 
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),
237 
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),
243 
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),
249 
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),
255 
256 	INTERLEAVED_RGB_FMT(RGB565,
257 		0, COLOR_5BIT, COLOR_6BIT, COLOR_5BIT,
258 		C2_R_Cr, C0_G_Y, C1_B_Cb, 0, 3,
259 		false, 2, 0,
260 		DPU_FETCH_LINEAR, 1),
261 
262 	INTERLEAVED_RGB_FMT(BGR565,
263 		0, COLOR_5BIT, COLOR_6BIT, COLOR_5BIT,
264 		C1_B_Cb, C0_G_Y, C2_R_Cr, 0, 3,
265 		false, 2, 0,
266 		DPU_FETCH_LINEAR, 1),
267 
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),
273 
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),
279 
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),
285 
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),
291 
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),
297 
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),
303 
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),
309 
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),
315 
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),
321 
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),
327 
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),
333 
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),
339 
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),
345 
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),
351 
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),
357 
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),
363 
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),
369 
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),
375 
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),
381 
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),
387 
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),
393 
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),
399 
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),
405 
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),
411 
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),
417 
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),
423 
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),
429 
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),
435 
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),
441 
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),
447 
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),
453 
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),
459 
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),
465 
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),
471 };
472 
473 /*
474  * A5x tile formats tables:
475  * These tables hold the A5x tile formats supported.
476  */
477 static const struct dpu_format dpu_format_map_tile[] = {
478 	INTERLEAVED_RGB_FMT_TILED(BGR565,
479 		0, COLOR_5BIT, COLOR_6BIT, COLOR_5BIT,
480 		C2_R_Cr, C0_G_Y, C1_B_Cb, 0, 3,
481 		false, 2, 0,
482 		DPU_FETCH_UBWC, 1, DPU_TILE_HEIGHT_TILED),
483 
484 	INTERLEAVED_RGB_FMT_TILED(ARGB8888,
485 		COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
486 		C3_ALPHA, C2_R_Cr, C0_G_Y, C1_B_Cb, 4,
487 		true, 4, 0,
488 		DPU_FETCH_UBWC, 1, DPU_TILE_HEIGHT_TILED),
489 
490 	INTERLEAVED_RGB_FMT_TILED(ABGR8888,
491 		COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
492 		C3_ALPHA, C1_B_Cb, C0_G_Y, C2_R_Cr, 4,
493 		true, 4, 0,
494 		DPU_FETCH_UBWC, 1, DPU_TILE_HEIGHT_TILED),
495 
496 	INTERLEAVED_RGB_FMT_TILED(XBGR8888,
497 		COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
498 		C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
499 		false, 4, 0,
500 		DPU_FETCH_UBWC, 1, DPU_TILE_HEIGHT_TILED),
501 
502 	INTERLEAVED_RGB_FMT_TILED(RGBA8888,
503 		COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
504 		C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
505 		true, 4, 0,
506 		DPU_FETCH_UBWC, 1, DPU_TILE_HEIGHT_TILED),
507 
508 	INTERLEAVED_RGB_FMT_TILED(BGRA8888,
509 		COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
510 		C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA, 4,
511 		true, 4, 0,
512 		DPU_FETCH_UBWC, 1, DPU_TILE_HEIGHT_TILED),
513 
514 	INTERLEAVED_RGB_FMT_TILED(BGRX8888,
515 		COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
516 		C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA, 4,
517 		false, 4, 0,
518 		DPU_FETCH_UBWC, 1, DPU_TILE_HEIGHT_TILED),
519 
520 	INTERLEAVED_RGB_FMT_TILED(XRGB8888,
521 		COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
522 		C3_ALPHA, C2_R_Cr, C0_G_Y, C1_B_Cb, 4,
523 		false, 4, 0,
524 		DPU_FETCH_UBWC, 1, DPU_TILE_HEIGHT_TILED),
525 
526 	INTERLEAVED_RGB_FMT_TILED(RGBX8888,
527 		COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
528 		C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
529 		false, 4, 0,
530 		DPU_FETCH_UBWC, 1, DPU_TILE_HEIGHT_TILED),
531 
532 	INTERLEAVED_RGB_FMT_TILED(ABGR2101010,
533 		COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
534 		C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
535 		true, 4, DPU_FORMAT_FLAG_DX,
536 		DPU_FETCH_UBWC, 1, DPU_TILE_HEIGHT_TILED),
537 
538 	INTERLEAVED_RGB_FMT_TILED(XBGR2101010,
539 		COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
540 		C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
541 		true, 4, DPU_FORMAT_FLAG_DX,
542 		DPU_FETCH_UBWC, 1, DPU_TILE_HEIGHT_TILED),
543 
544 	PSEUDO_YUV_FMT_TILED(NV12,
545 		0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
546 		C1_B_Cb, C2_R_Cr,
547 		DPU_CHROMA_420, DPU_FORMAT_FLAG_YUV,
548 		DPU_FETCH_UBWC, 2, DPU_TILE_HEIGHT_NV12),
549 
550 	PSEUDO_YUV_FMT_TILED(NV21,
551 		0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
552 		C2_R_Cr, C1_B_Cb,
553 		DPU_CHROMA_420, DPU_FORMAT_FLAG_YUV,
554 		DPU_FETCH_UBWC, 2, DPU_TILE_HEIGHT_NV12),
555 };
556 
557 /*
558  * UBWC formats table:
559  * This table holds the UBWC formats supported.
560  * If a compression ratio needs to be used for this or any other format,
561  * the data will be passed by user-space.
562  */
563 static const struct dpu_format dpu_format_map_ubwc[] = {
564 	INTERLEAVED_RGB_FMT_TILED(BGR565,
565 		0, COLOR_5BIT, COLOR_6BIT, COLOR_5BIT,
566 		C2_R_Cr, C0_G_Y, C1_B_Cb, 0, 3,
567 		false, 2, DPU_FORMAT_FLAG_COMPRESSED,
568 		DPU_FETCH_UBWC, 2, DPU_TILE_HEIGHT_UBWC),
569 
570 	INTERLEAVED_RGB_FMT_TILED(ABGR8888,
571 		COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
572 		C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
573 		true, 4, DPU_FORMAT_FLAG_COMPRESSED,
574 		DPU_FETCH_UBWC, 2, DPU_TILE_HEIGHT_UBWC),
575 
576 	INTERLEAVED_RGB_FMT_TILED(XBGR8888,
577 		COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
578 		C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
579 		false, 4, DPU_FORMAT_FLAG_COMPRESSED,
580 		DPU_FETCH_UBWC, 2, DPU_TILE_HEIGHT_UBWC),
581 
582 	INTERLEAVED_RGB_FMT_TILED(ABGR2101010,
583 		COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
584 		C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
585 		true, 4, DPU_FORMAT_FLAG_DX | DPU_FORMAT_FLAG_COMPRESSED,
586 		DPU_FETCH_UBWC, 2, DPU_TILE_HEIGHT_UBWC),
587 
588 	INTERLEAVED_RGB_FMT_TILED(XBGR2101010,
589 		COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
590 		C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
591 		true, 4, DPU_FORMAT_FLAG_DX | DPU_FORMAT_FLAG_COMPRESSED,
592 		DPU_FETCH_UBWC, 2, DPU_TILE_HEIGHT_UBWC),
593 
594 	PSEUDO_YUV_FMT_TILED(NV12,
595 		0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
596 		C1_B_Cb, C2_R_Cr,
597 		DPU_CHROMA_420, DPU_FORMAT_FLAG_YUV |
598 				DPU_FORMAT_FLAG_COMPRESSED,
599 		DPU_FETCH_UBWC, 4, DPU_TILE_HEIGHT_NV12),
600 };
601 
602 static const struct dpu_format dpu_format_map_p010[] = {
603 	PSEUDO_YUV_FMT_LOOSE(NV12,
604 		0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
605 		C1_B_Cb, C2_R_Cr,
606 		DPU_CHROMA_420, (DPU_FORMAT_FLAG_YUV | DPU_FORMAT_FLAG_DX),
607 		DPU_FETCH_LINEAR, 2),
608 };
609 
610 static const struct dpu_format dpu_format_map_p010_ubwc[] = {
611 	PSEUDO_YUV_FMT_LOOSE_TILED(NV12,
612 		0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
613 		C1_B_Cb, C2_R_Cr,
614 		DPU_CHROMA_420, (DPU_FORMAT_FLAG_YUV | DPU_FORMAT_FLAG_DX |
615 				DPU_FORMAT_FLAG_COMPRESSED),
616 		DPU_FETCH_UBWC, 4, DPU_TILE_HEIGHT_NV12),
617 };
618 
619 static const struct dpu_format dpu_format_map_tp10_ubwc[] = {
620 	PSEUDO_YUV_FMT_TILED(NV12,
621 		0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
622 		C1_B_Cb, C2_R_Cr,
623 		DPU_CHROMA_420, (DPU_FORMAT_FLAG_YUV | DPU_FORMAT_FLAG_DX |
624 				DPU_FORMAT_FLAG_COMPRESSED),
625 		DPU_FETCH_UBWC, 4, DPU_TILE_HEIGHT_NV12),
626 };
627 
628 /* _dpu_get_v_h_subsample_rate - Get subsample rates for all formats we support
629  *   Note: Not using the drm_format_*_subsampling since we have formats
630  */
631 static void _dpu_get_v_h_subsample_rate(
632 	enum dpu_chroma_samp_type chroma_sample,
633 	uint32_t *v_sample,
634 	uint32_t *h_sample)
635 {
636 	if (!v_sample || !h_sample)
637 		return;
638 
639 	switch (chroma_sample) {
640 	case DPU_CHROMA_H2V1:
641 		*v_sample = 1;
642 		*h_sample = 2;
643 		break;
644 	case DPU_CHROMA_H1V2:
645 		*v_sample = 2;
646 		*h_sample = 1;
647 		break;
648 	case DPU_CHROMA_420:
649 		*v_sample = 2;
650 		*h_sample = 2;
651 		break;
652 	default:
653 		*v_sample = 1;
654 		*h_sample = 1;
655 		break;
656 	}
657 }
658 
659 static int _dpu_format_get_media_color_ubwc(const struct dpu_format *fmt)
660 {
661 	static const struct dpu_media_color_map dpu_media_ubwc_map[] = {
662 		{DRM_FORMAT_ABGR8888, COLOR_FMT_RGBA8888_UBWC},
663 		{DRM_FORMAT_XBGR8888, COLOR_FMT_RGBA8888_UBWC},
664 		{DRM_FORMAT_ABGR2101010, COLOR_FMT_RGBA1010102_UBWC},
665 		{DRM_FORMAT_XBGR2101010, COLOR_FMT_RGBA1010102_UBWC},
666 		{DRM_FORMAT_BGR565, COLOR_FMT_RGB565_UBWC},
667 	};
668 	int color_fmt = -1;
669 	int i;
670 
671 	if (fmt->base.pixel_format == DRM_FORMAT_NV12) {
672 		if (DPU_FORMAT_IS_DX(fmt)) {
673 			if (fmt->unpack_tight)
674 				color_fmt = COLOR_FMT_NV12_BPP10_UBWC;
675 			else
676 				color_fmt = COLOR_FMT_P010_UBWC;
677 		} else
678 			color_fmt = COLOR_FMT_NV12_UBWC;
679 		return color_fmt;
680 	}
681 
682 	for (i = 0; i < ARRAY_SIZE(dpu_media_ubwc_map); ++i)
683 		if (fmt->base.pixel_format == dpu_media_ubwc_map[i].format) {
684 			color_fmt = dpu_media_ubwc_map[i].color;
685 			break;
686 		}
687 	return color_fmt;
688 }
689 
690 static int _dpu_format_get_plane_sizes_ubwc(
691 		const struct dpu_format *fmt,
692 		const uint32_t width,
693 		const uint32_t height,
694 		struct dpu_hw_fmt_layout *layout)
695 {
696 	int i;
697 	int color;
698 	bool meta = DPU_FORMAT_IS_UBWC(fmt);
699 
700 	memset(layout, 0, sizeof(struct dpu_hw_fmt_layout));
701 	layout->format = fmt;
702 	layout->width = width;
703 	layout->height = height;
704 	layout->num_planes = fmt->num_planes;
705 
706 	color = _dpu_format_get_media_color_ubwc(fmt);
707 	if (color < 0) {
708 		DRM_ERROR("UBWC format not supported for fmt: %4.4s\n",
709 			(char *)&fmt->base.pixel_format);
710 		return -EINVAL;
711 	}
712 
713 	if (DPU_FORMAT_IS_YUV(layout->format)) {
714 		uint32_t y_sclines, uv_sclines;
715 		uint32_t y_meta_scanlines = 0;
716 		uint32_t uv_meta_scanlines = 0;
717 
718 		layout->num_planes = 2;
719 		layout->plane_pitch[0] = VENUS_Y_STRIDE(color, width);
720 		y_sclines = VENUS_Y_SCANLINES(color, height);
721 		layout->plane_size[0] = MSM_MEDIA_ALIGN(layout->plane_pitch[0] *
722 			y_sclines, DPU_UBWC_PLANE_SIZE_ALIGNMENT);
723 
724 		layout->plane_pitch[1] = VENUS_UV_STRIDE(color, width);
725 		uv_sclines = VENUS_UV_SCANLINES(color, height);
726 		layout->plane_size[1] = MSM_MEDIA_ALIGN(layout->plane_pitch[1] *
727 			uv_sclines, DPU_UBWC_PLANE_SIZE_ALIGNMENT);
728 
729 		if (!meta)
730 			goto done;
731 
732 		layout->num_planes += 2;
733 		layout->plane_pitch[2] = VENUS_Y_META_STRIDE(color, width);
734 		y_meta_scanlines = VENUS_Y_META_SCANLINES(color, height);
735 		layout->plane_size[2] = MSM_MEDIA_ALIGN(layout->plane_pitch[2] *
736 			y_meta_scanlines, DPU_UBWC_PLANE_SIZE_ALIGNMENT);
737 
738 		layout->plane_pitch[3] = VENUS_UV_META_STRIDE(color, width);
739 		uv_meta_scanlines = VENUS_UV_META_SCANLINES(color, height);
740 		layout->plane_size[3] = MSM_MEDIA_ALIGN(layout->plane_pitch[3] *
741 			uv_meta_scanlines, DPU_UBWC_PLANE_SIZE_ALIGNMENT);
742 
743 	} else {
744 		uint32_t rgb_scanlines, rgb_meta_scanlines;
745 
746 		layout->num_planes = 1;
747 
748 		layout->plane_pitch[0] = VENUS_RGB_STRIDE(color, width);
749 		rgb_scanlines = VENUS_RGB_SCANLINES(color, height);
750 		layout->plane_size[0] = MSM_MEDIA_ALIGN(layout->plane_pitch[0] *
751 			rgb_scanlines, DPU_UBWC_PLANE_SIZE_ALIGNMENT);
752 
753 		if (!meta)
754 			goto done;
755 		layout->num_planes += 2;
756 		layout->plane_pitch[2] = VENUS_RGB_META_STRIDE(color, width);
757 		rgb_meta_scanlines = VENUS_RGB_META_SCANLINES(color, height);
758 		layout->plane_size[2] = MSM_MEDIA_ALIGN(layout->plane_pitch[2] *
759 			rgb_meta_scanlines, DPU_UBWC_PLANE_SIZE_ALIGNMENT);
760 	}
761 
762 done:
763 	for (i = 0; i < DPU_MAX_PLANES; i++)
764 		layout->total_size += layout->plane_size[i];
765 
766 	return 0;
767 }
768 
769 static int _dpu_format_get_plane_sizes_linear(
770 		const struct dpu_format *fmt,
771 		const uint32_t width,
772 		const uint32_t height,
773 		struct dpu_hw_fmt_layout *layout,
774 		const uint32_t *pitches)
775 {
776 	int i;
777 
778 	memset(layout, 0, sizeof(struct dpu_hw_fmt_layout));
779 	layout->format = fmt;
780 	layout->width = width;
781 	layout->height = height;
782 	layout->num_planes = fmt->num_planes;
783 
784 	/* Due to memset above, only need to set planes of interest */
785 	if (fmt->fetch_planes == DPU_PLANE_INTERLEAVED) {
786 		layout->num_planes = 1;
787 		layout->plane_size[0] = width * height * layout->format->bpp;
788 		layout->plane_pitch[0] = width * layout->format->bpp;
789 	} else {
790 		uint32_t v_subsample, h_subsample;
791 		uint32_t chroma_samp;
792 		uint32_t bpp = 1;
793 
794 		chroma_samp = fmt->chroma_sample;
795 		_dpu_get_v_h_subsample_rate(chroma_samp, &v_subsample,
796 				&h_subsample);
797 
798 		if (width % h_subsample || height % v_subsample) {
799 			DRM_ERROR("mismatch in subsample vs dimensions\n");
800 			return -EINVAL;
801 		}
802 
803 		if ((fmt->base.pixel_format == DRM_FORMAT_NV12) &&
804 			(DPU_FORMAT_IS_DX(fmt)))
805 			bpp = 2;
806 		layout->plane_pitch[0] = width * bpp;
807 		layout->plane_pitch[1] = layout->plane_pitch[0] / h_subsample;
808 		layout->plane_size[0] = layout->plane_pitch[0] * height;
809 		layout->plane_size[1] = layout->plane_pitch[1] *
810 				(height / v_subsample);
811 
812 		if (fmt->fetch_planes == DPU_PLANE_PSEUDO_PLANAR) {
813 			layout->num_planes = 2;
814 			layout->plane_size[1] *= 2;
815 			layout->plane_pitch[1] *= 2;
816 		} else {
817 			/* planar */
818 			layout->num_planes = 3;
819 			layout->plane_size[2] = layout->plane_size[1];
820 			layout->plane_pitch[2] = layout->plane_pitch[1];
821 		}
822 	}
823 
824 	/*
825 	 * linear format: allow user allocated pitches if they are greater than
826 	 * the requirement.
827 	 * ubwc format: pitch values are computed uniformly across
828 	 * all the components based on ubwc specifications.
829 	 */
830 	for (i = 0; i < layout->num_planes && i < DPU_MAX_PLANES; ++i) {
831 		if (pitches && layout->plane_pitch[i] < pitches[i])
832 			layout->plane_pitch[i] = pitches[i];
833 	}
834 
835 	for (i = 0; i < DPU_MAX_PLANES; i++)
836 		layout->total_size += layout->plane_size[i];
837 
838 	return 0;
839 }
840 
841 static int dpu_format_get_plane_sizes(
842 		const struct dpu_format *fmt,
843 		const uint32_t w,
844 		const uint32_t h,
845 		struct dpu_hw_fmt_layout *layout,
846 		const uint32_t *pitches)
847 {
848 	if (!layout || !fmt) {
849 		DRM_ERROR("invalid pointer\n");
850 		return -EINVAL;
851 	}
852 
853 	if ((w > DPU_MAX_IMG_WIDTH) || (h > DPU_MAX_IMG_HEIGHT)) {
854 		DRM_ERROR("image dimensions outside max range\n");
855 		return -ERANGE;
856 	}
857 
858 	if (DPU_FORMAT_IS_UBWC(fmt) || DPU_FORMAT_IS_TILE(fmt))
859 		return _dpu_format_get_plane_sizes_ubwc(fmt, w, h, layout);
860 
861 	return _dpu_format_get_plane_sizes_linear(fmt, w, h, layout, pitches);
862 }
863 
864 static int _dpu_format_populate_addrs_ubwc(
865 		struct msm_gem_address_space *aspace,
866 		struct drm_framebuffer *fb,
867 		struct dpu_hw_fmt_layout *layout)
868 {
869 	uint32_t base_addr = 0;
870 	bool meta;
871 
872 	if (!fb || !layout) {
873 		DRM_ERROR("invalid pointers\n");
874 		return -EINVAL;
875 	}
876 
877 	if (aspace)
878 		base_addr = msm_framebuffer_iova(fb, aspace, 0);
879 	if (!base_addr) {
880 		DRM_ERROR("failed to retrieve base addr\n");
881 		return -EFAULT;
882 	}
883 
884 	meta = DPU_FORMAT_IS_UBWC(layout->format);
885 
886 	/* Per-format logic for verifying active planes */
887 	if (DPU_FORMAT_IS_YUV(layout->format)) {
888 		/************************************************/
889 		/*      UBWC            **                      */
890 		/*      buffer          **      DPU PLANE       */
891 		/*      format          **                      */
892 		/************************************************/
893 		/* -------------------  ** -------------------- */
894 		/* |      Y meta     |  ** |    Y bitstream   | */
895 		/* |       data      |  ** |       plane      | */
896 		/* -------------------  ** -------------------- */
897 		/* |    Y bitstream  |  ** |  CbCr bitstream  | */
898 		/* |       data      |  ** |       plane      | */
899 		/* -------------------  ** -------------------- */
900 		/* |   Cbcr metadata |  ** |       Y meta     | */
901 		/* |       data      |  ** |       plane      | */
902 		/* -------------------  ** -------------------- */
903 		/* |  CbCr bitstream |  ** |     CbCr meta    | */
904 		/* |       data      |  ** |       plane      | */
905 		/* -------------------  ** -------------------- */
906 		/************************************************/
907 
908 		/* configure Y bitstream plane */
909 		layout->plane_addr[0] = base_addr + layout->plane_size[2];
910 
911 		/* configure CbCr bitstream plane */
912 		layout->plane_addr[1] = base_addr + layout->plane_size[0]
913 			+ layout->plane_size[2] + layout->plane_size[3];
914 
915 		if (!meta)
916 			return 0;
917 
918 		/* configure Y metadata plane */
919 		layout->plane_addr[2] = base_addr;
920 
921 		/* configure CbCr metadata plane */
922 		layout->plane_addr[3] = base_addr + layout->plane_size[0]
923 			+ layout->plane_size[2];
924 
925 	} else {
926 		/************************************************/
927 		/*      UBWC            **                      */
928 		/*      buffer          **      DPU PLANE       */
929 		/*      format          **                      */
930 		/************************************************/
931 		/* -------------------  ** -------------------- */
932 		/* |      RGB meta   |  ** |   RGB bitstream  | */
933 		/* |       data      |  ** |       plane      | */
934 		/* -------------------  ** -------------------- */
935 		/* |  RGB bitstream  |  ** |       NONE       | */
936 		/* |       data      |  ** |                  | */
937 		/* -------------------  ** -------------------- */
938 		/*                      ** |     RGB meta     | */
939 		/*                      ** |       plane      | */
940 		/*                      ** -------------------- */
941 		/************************************************/
942 
943 		layout->plane_addr[0] = base_addr + layout->plane_size[2];
944 		layout->plane_addr[1] = 0;
945 
946 		if (!meta)
947 			return 0;
948 
949 		layout->plane_addr[2] = base_addr;
950 		layout->plane_addr[3] = 0;
951 	}
952 	return 0;
953 }
954 
955 static int _dpu_format_populate_addrs_linear(
956 		struct msm_gem_address_space *aspace,
957 		struct drm_framebuffer *fb,
958 		struct dpu_hw_fmt_layout *layout)
959 {
960 	unsigned int i;
961 
962 	/* Can now check the pitches given vs pitches expected */
963 	for (i = 0; i < layout->num_planes; ++i) {
964 		if (layout->plane_pitch[i] > fb->pitches[i]) {
965 			DRM_ERROR("plane %u expected pitch %u, fb %u\n",
966 				i, layout->plane_pitch[i], fb->pitches[i]);
967 			return -EINVAL;
968 		}
969 	}
970 
971 	/* Populate addresses for simple formats here */
972 	for (i = 0; i < layout->num_planes; ++i) {
973 		if (aspace)
974 			layout->plane_addr[i] =
975 				msm_framebuffer_iova(fb, aspace, i);
976 		if (!layout->plane_addr[i]) {
977 			DRM_ERROR("failed to retrieve base addr\n");
978 			return -EFAULT;
979 		}
980 	}
981 
982 	return 0;
983 }
984 
985 int dpu_format_populate_layout(
986 		struct msm_gem_address_space *aspace,
987 		struct drm_framebuffer *fb,
988 		struct dpu_hw_fmt_layout *layout)
989 {
990 	uint32_t plane_addr[DPU_MAX_PLANES];
991 	int i, ret;
992 
993 	if (!fb || !layout) {
994 		DRM_ERROR("invalid arguments\n");
995 		return -EINVAL;
996 	}
997 
998 	if ((fb->width > DPU_MAX_IMG_WIDTH) ||
999 			(fb->height > DPU_MAX_IMG_HEIGHT)) {
1000 		DRM_ERROR("image dimensions outside max range\n");
1001 		return -ERANGE;
1002 	}
1003 
1004 	layout->format = to_dpu_format(msm_framebuffer_format(fb));
1005 
1006 	/* Populate the plane sizes etc via get_format */
1007 	ret = dpu_format_get_plane_sizes(layout->format, fb->width, fb->height,
1008 			layout, fb->pitches);
1009 	if (ret)
1010 		return ret;
1011 
1012 	for (i = 0; i < DPU_MAX_PLANES; ++i)
1013 		plane_addr[i] = layout->plane_addr[i];
1014 
1015 	/* Populate the addresses given the fb */
1016 	if (DPU_FORMAT_IS_UBWC(layout->format) ||
1017 			DPU_FORMAT_IS_TILE(layout->format))
1018 		ret = _dpu_format_populate_addrs_ubwc(aspace, fb, layout);
1019 	else
1020 		ret = _dpu_format_populate_addrs_linear(aspace, fb, layout);
1021 
1022 	/* check if anything changed */
1023 	if (!ret && !memcmp(plane_addr, layout->plane_addr, sizeof(plane_addr)))
1024 		ret = -EAGAIN;
1025 
1026 	return ret;
1027 }
1028 
1029 int dpu_format_check_modified_format(
1030 		const struct msm_kms *kms,
1031 		const struct msm_format *msm_fmt,
1032 		const struct drm_mode_fb_cmd2 *cmd,
1033 		struct drm_gem_object **bos)
1034 {
1035 	const struct drm_format_info *info;
1036 	const struct dpu_format *fmt;
1037 	struct dpu_hw_fmt_layout layout;
1038 	uint32_t bos_total_size = 0;
1039 	int ret, i;
1040 
1041 	if (!msm_fmt || !cmd || !bos) {
1042 		DRM_ERROR("invalid arguments\n");
1043 		return -EINVAL;
1044 	}
1045 
1046 	fmt = to_dpu_format(msm_fmt);
1047 	info = drm_format_info(fmt->base.pixel_format);
1048 	if (!info)
1049 		return -EINVAL;
1050 
1051 	ret = dpu_format_get_plane_sizes(fmt, cmd->width, cmd->height,
1052 			&layout, cmd->pitches);
1053 	if (ret)
1054 		return ret;
1055 
1056 	for (i = 0; i < info->num_planes; i++) {
1057 		if (!bos[i]) {
1058 			DRM_ERROR("invalid handle for plane %d\n", i);
1059 			return -EINVAL;
1060 		}
1061 		if ((i == 0) || (bos[i] != bos[0]))
1062 			bos_total_size += bos[i]->size;
1063 	}
1064 
1065 	if (bos_total_size < layout.total_size) {
1066 		DRM_ERROR("buffers total size too small %u expected %u\n",
1067 				bos_total_size, layout.total_size);
1068 		return -EINVAL;
1069 	}
1070 
1071 	return 0;
1072 }
1073 
1074 const struct dpu_format *dpu_get_dpu_format_ext(
1075 		const uint32_t format,
1076 		const uint64_t modifier)
1077 {
1078 	uint32_t i = 0;
1079 	const struct dpu_format *fmt = NULL;
1080 	const struct dpu_format *map = NULL;
1081 	ssize_t map_size = 0;
1082 
1083 	/*
1084 	 * Currently only support exactly zero or one modifier.
1085 	 * All planes use the same modifier.
1086 	 */
1087 	DPU_DEBUG("plane format modifier 0x%llX\n", modifier);
1088 
1089 	switch (modifier) {
1090 	case 0:
1091 		map = dpu_format_map;
1092 		map_size = ARRAY_SIZE(dpu_format_map);
1093 		break;
1094 	case DRM_FORMAT_MOD_QCOM_COMPRESSED:
1095 		map = dpu_format_map_ubwc;
1096 		map_size = ARRAY_SIZE(dpu_format_map_ubwc);
1097 		DPU_DEBUG("found fmt: %4.4s  DRM_FORMAT_MOD_QCOM_COMPRESSED\n",
1098 				(char *)&format);
1099 		break;
1100 	default:
1101 		DPU_ERROR("unsupported format modifier %llX\n", modifier);
1102 		return NULL;
1103 	}
1104 
1105 	for (i = 0; i < map_size; i++) {
1106 		if (format == map[i].base.pixel_format) {
1107 			fmt = &map[i];
1108 			break;
1109 		}
1110 	}
1111 
1112 	if (fmt == NULL)
1113 		DPU_ERROR("unsupported fmt: %4.4s modifier 0x%llX\n",
1114 			(char *)&format, modifier);
1115 	else
1116 		DPU_DEBUG("fmt %4.4s mod 0x%llX ubwc %d yuv %d\n",
1117 				(char *)&format, modifier,
1118 				DPU_FORMAT_IS_UBWC(fmt),
1119 				DPU_FORMAT_IS_YUV(fmt));
1120 
1121 	return fmt;
1122 }
1123 
1124 const struct msm_format *dpu_get_msm_format(
1125 		struct msm_kms *kms,
1126 		const uint32_t format,
1127 		const uint64_t modifiers)
1128 {
1129 	const struct dpu_format *fmt = dpu_get_dpu_format_ext(format,
1130 			modifiers);
1131 	if (fmt)
1132 		return &fmt->base;
1133 	return NULL;
1134 }
1135