blob: 5655a8ae938ee6809ddcbc6ff3074a53a7173bac [file] [log] [blame]
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -04001/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -040013#include <uapi/drm/drm_fourcc.h>
14
Clarence Ipc475b082016-06-26 09:27:23 -040015#include "sde_kms.h"
16#include "sde_formats.h"
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -040017
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -040018#define SDE_UBWC_META_MACRO_W_H 16
19#define SDE_UBWC_META_BLOCK_SIZE 256
20#define SDE_MAX_IMG_WIDTH 0x3FFF
21#define SDE_MAX_IMG_HEIGHT 0x3FFF
22
23/**
24 * SDE supported format packing, bpp, and other format
25 * information.
26 * SDE currently only supports interleaved RGB formats
27 * UBWC support for a pixel format is indicated by the flag,
28 * there is additional meta data plane for such formats
29 */
30
31#define INTERLEAVED_RGB_FMT(fmt, a, r, g, b, e0, e1, e2, e3, uc, alpha, \
32bp, flg, fm, np) \
33{ \
34 .base.pixel_format = DRM_FORMAT_ ## fmt, \
35 .fetch_planes = SDE_PLANE_INTERLEAVED, \
36 .alpha_enable = alpha, \
37 .element = { (e0), (e1), (e2), (e3) }, \
38 .bits = { g, b, r, a }, \
39 .chroma_sample = SDE_CHROMA_RGB, \
40 .unpack_align_msb = 0, \
41 .unpack_tight = 1, \
42 .unpack_count = uc, \
43 .bpp = bp, \
44 .fetch_mode = fm, \
45 .flag = flg, \
46 .num_planes = np \
47}
48
49#define INTERLEAVED_YUV_FMT(fmt, a, r, g, b, e0, e1, e2, e3, \
50alpha, chroma, count, bp, flg, fm, np) \
51{ \
52 .base.pixel_format = DRM_FORMAT_ ## fmt, \
53 .fetch_planes = SDE_PLANE_INTERLEAVED, \
54 .alpha_enable = alpha, \
55 .element = { (e0), (e1), (e2), (e3)}, \
56 .bits = { g, b, r, a }, \
57 .chroma_sample = chroma, \
58 .unpack_align_msb = 0, \
59 .unpack_tight = 1, \
60 .unpack_count = count, \
61 .bpp = bp, \
62 .fetch_mode = fm, \
63 .flag = flg, \
64 .num_planes = np \
65}
66
67#define PSEDUO_YUV_FMT(fmt, a, r, g, b, e0, e1, chroma, flg, fm, np) \
68{ \
69 .base.pixel_format = DRM_FORMAT_ ## fmt, \
70 .fetch_planes = SDE_PLANE_PSEUDO_PLANAR, \
71 .alpha_enable = false, \
72 .element = { (e0), (e1), 0, 0 }, \
73 .bits = { g, b, r, a }, \
74 .chroma_sample = chroma, \
75 .unpack_align_msb = 0, \
76 .unpack_tight = 1, \
77 .unpack_count = 2, \
78 .bpp = 2, \
79 .fetch_mode = fm, \
80 .flag = flg, \
81 .num_planes = np \
82}
83
84#define PLANAR_YUV_FMT(fmt, a, r, g, b, e0, e1, e2, alpha, chroma, bp, \
85flg, fm, np) \
86{ \
87 .base.pixel_format = DRM_FORMAT_ ## fmt, \
88 .fetch_planes = SDE_PLANE_PLANAR, \
89 .alpha_enable = alpha, \
90 .element = { (e0), (e1), (e2), 0 }, \
91 .bits = { g, b, r, a }, \
92 .chroma_sample = chroma, \
93 .unpack_align_msb = 0, \
94 .unpack_tight = 1, \
95 .unpack_count = 1, \
96 .bpp = bp, \
97 .fetch_mode = fm, \
98 .flag = flg, \
99 .num_planes = np \
100}
101
102static const struct sde_format sde_format_map[] = {
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400103 INTERLEAVED_RGB_FMT(ARGB8888,
104 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400105 C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA, 4,
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400106 true, 4, 0,
107 SDE_FETCH_LINEAR, 1),
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400108
109 INTERLEAVED_RGB_FMT(ABGR8888,
110 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400111 C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400112 true, 4, 0,
113 SDE_FETCH_LINEAR, 1),
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400114
115 INTERLEAVED_RGB_FMT(RGBA8888,
116 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400117 C3_ALPHA, C1_B_Cb, C0_G_Y, C2_R_Cr, 4,
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400118 true, 4, 0,
119 SDE_FETCH_LINEAR, 1),
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400120
121 INTERLEAVED_RGB_FMT(BGRA8888,
122 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400123 C3_ALPHA, C2_R_Cr, C0_G_Y, C1_B_Cb, 4,
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400124 true, 4, 0,
125 SDE_FETCH_LINEAR, 1),
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400126
Alan Kwong3232ca52016-07-29 02:27:47 -0400127 INTERLEAVED_RGB_FMT(BGRX8888,
128 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
129 C3_ALPHA, C2_R_Cr, C0_G_Y, C1_B_Cb, 4,
130 false, 4, 0,
131 SDE_FETCH_LINEAR, 1),
132
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400133 INTERLEAVED_RGB_FMT(XRGB8888,
134 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400135 C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA, 4,
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400136 false, 4, 0,
137 SDE_FETCH_LINEAR, 1),
138
139 INTERLEAVED_RGB_FMT(RGBX8888,
140 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
141 C3_ALPHA, C1_B_Cb, C0_G_Y, C2_R_Cr, 4,
142 false, 4, 0,
143 SDE_FETCH_LINEAR, 1),
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400144
145 INTERLEAVED_RGB_FMT(RGB888,
146 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400147 C1_B_Cb, C0_G_Y, C2_R_Cr, 0, 3,
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400148 false, 3, 0,
149 SDE_FETCH_LINEAR, 1),
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400150
151 INTERLEAVED_RGB_FMT(BGR888,
152 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400153 C2_R_Cr, C0_G_Y, C1_B_Cb, 0, 3,
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400154 false, 3, 0,
155 SDE_FETCH_LINEAR, 1),
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400156
157 INTERLEAVED_RGB_FMT(RGB565,
158 0, COLOR_5BIT, COLOR_6BIT, COLOR_5BIT,
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400159 C1_B_Cb, C0_G_Y, C2_R_Cr, 0, 3,
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400160 false, 2, 0,
161 SDE_FETCH_LINEAR, 1),
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400162
163 INTERLEAVED_RGB_FMT(BGR565,
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400164 0, COLOR_5BIT, COLOR_6BIT, COLOR_5BIT,
165 C2_R_Cr, C0_G_Y, C1_B_Cb, 0, 3,
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400166 false, 2, 0,
167 SDE_FETCH_LINEAR, 1),
168
169 INTERLEAVED_RGB_FMT(ARGB1555,
170 COLOR_ALPHA_1BIT, COLOR_5BIT, COLOR_5BIT, COLOR_5BIT,
171 C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA, 4,
172 true, 2, 0,
173 SDE_FETCH_LINEAR, 1),
174
175 INTERLEAVED_RGB_FMT(ABGR1555,
176 COLOR_ALPHA_1BIT, COLOR_5BIT, COLOR_5BIT, COLOR_5BIT,
177 C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
178 true, 2, 0,
179 SDE_FETCH_LINEAR, 1),
180
181 INTERLEAVED_RGB_FMT(RGBA5551,
182 COLOR_ALPHA_1BIT, COLOR_5BIT, COLOR_5BIT, COLOR_5BIT,
183 C3_ALPHA, C1_B_Cb, C0_G_Y, C2_R_Cr, 4,
184 true, 2, 0,
185 SDE_FETCH_LINEAR, 1),
186
187 INTERLEAVED_RGB_FMT(BGRA5551,
188 COLOR_ALPHA_1BIT, COLOR_5BIT, COLOR_5BIT, COLOR_5BIT,
189 C3_ALPHA, C2_R_Cr, C0_G_Y, C1_B_Cb, 4,
190 true, 2, 0,
191 SDE_FETCH_LINEAR, 1),
192
193 INTERLEAVED_RGB_FMT(XRGB1555,
194 COLOR_ALPHA_1BIT, COLOR_5BIT, COLOR_5BIT, COLOR_5BIT,
195 C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA, 4,
196 false, 2, 0,
197 SDE_FETCH_LINEAR, 1),
198
199 INTERLEAVED_RGB_FMT(XBGR1555,
200 COLOR_ALPHA_1BIT, COLOR_5BIT, COLOR_5BIT, COLOR_5BIT,
201 C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
202 false, 2, 0,
203 SDE_FETCH_LINEAR, 1),
204
205 INTERLEAVED_RGB_FMT(RGBX5551,
206 COLOR_ALPHA_1BIT, COLOR_5BIT, COLOR_5BIT, COLOR_5BIT,
207 C3_ALPHA, C1_B_Cb, C0_G_Y, C2_R_Cr, 4,
208 false, 2, 0,
209 SDE_FETCH_LINEAR, 1),
210
211 INTERLEAVED_RGB_FMT(BGRX5551,
212 COLOR_ALPHA_1BIT, COLOR_5BIT, COLOR_5BIT, COLOR_5BIT,
213 C3_ALPHA, C2_R_Cr, C0_G_Y, C1_B_Cb, 4,
214 false, 2, 0,
215 SDE_FETCH_LINEAR, 1),
216
217 INTERLEAVED_RGB_FMT(ARGB4444,
218 COLOR_ALPHA_4BIT, COLOR_4BIT, COLOR_4BIT, COLOR_4BIT,
219 C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA, 4,
220 true, 2, 0,
221 SDE_FETCH_LINEAR, 1),
222
223 INTERLEAVED_RGB_FMT(ABGR4444,
224 COLOR_ALPHA_4BIT, COLOR_4BIT, COLOR_4BIT, COLOR_4BIT,
225 C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
226 true, 2, 0,
227 SDE_FETCH_LINEAR, 1),
228
229 INTERLEAVED_RGB_FMT(RGBA4444,
230 COLOR_ALPHA_4BIT, COLOR_4BIT, COLOR_4BIT, COLOR_4BIT,
231 C3_ALPHA, C1_B_Cb, C0_G_Y, C2_R_Cr, 4,
232 true, 2, 0,
233 SDE_FETCH_LINEAR, 1),
234
235 INTERLEAVED_RGB_FMT(BGRA4444,
236 COLOR_ALPHA_4BIT, COLOR_4BIT, COLOR_4BIT, COLOR_4BIT,
237 C3_ALPHA, C2_R_Cr, C0_G_Y, C1_B_Cb, 4,
238 true, 2, 0,
239 SDE_FETCH_LINEAR, 1),
240
241 INTERLEAVED_RGB_FMT(XRGB4444,
242 COLOR_ALPHA_4BIT, COLOR_4BIT, COLOR_4BIT, COLOR_4BIT,
243 C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA, 4,
244 false, 2, 0,
245 SDE_FETCH_LINEAR, 1),
246
247 INTERLEAVED_RGB_FMT(XBGR4444,
248 COLOR_ALPHA_4BIT, COLOR_4BIT, COLOR_4BIT, COLOR_4BIT,
249 C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
250 false, 2, 0,
251 SDE_FETCH_LINEAR, 1),
252
253 INTERLEAVED_RGB_FMT(RGBX4444,
254 COLOR_ALPHA_4BIT, COLOR_4BIT, COLOR_4BIT, COLOR_4BIT,
255 C3_ALPHA, C1_B_Cb, C0_G_Y, C2_R_Cr, 4,
256 false, 2, 0,
257 SDE_FETCH_LINEAR, 1),
258
259 INTERLEAVED_RGB_FMT(BGRX4444,
260 COLOR_ALPHA_4BIT, COLOR_4BIT, COLOR_4BIT, COLOR_4BIT,
261 C3_ALPHA, C2_R_Cr, C0_G_Y, C1_B_Cb, 4,
262 false, 2, 0,
263 SDE_FETCH_LINEAR, 1),
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400264
265 PSEDUO_YUV_FMT(NV12,
266 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
267 C1_B_Cb, C2_R_Cr,
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400268 SDE_CHROMA_420, SDE_FORMAT_FLAG_YUV,
269 SDE_FETCH_LINEAR, 2),
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400270
271 PSEDUO_YUV_FMT(NV21,
272 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
273 C2_R_Cr, C1_B_Cb,
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400274 SDE_CHROMA_420, SDE_FORMAT_FLAG_YUV,
275 SDE_FETCH_LINEAR, 2),
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400276
277 PSEDUO_YUV_FMT(NV16,
278 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
279 C1_B_Cb, C2_R_Cr,
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400280 SDE_CHROMA_H2V1, SDE_FORMAT_FLAG_YUV,
281 SDE_FETCH_LINEAR, 2),
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400282
283 PSEDUO_YUV_FMT(NV61,
284 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
285 C2_R_Cr, C1_B_Cb,
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400286 SDE_CHROMA_H2V1, SDE_FORMAT_FLAG_YUV,
287 SDE_FETCH_LINEAR, 2),
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400288
289 INTERLEAVED_YUV_FMT(VYUY,
290 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
291 C2_R_Cr, C0_G_Y, C1_B_Cb, C0_G_Y,
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400292 false, SDE_CHROMA_H2V1, 4, 2, SDE_FORMAT_FLAG_YUV,
293 SDE_FETCH_LINEAR, 2),
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400294
295 INTERLEAVED_YUV_FMT(UYVY,
296 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
297 C1_B_Cb, C0_G_Y, C2_R_Cr, C0_G_Y,
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400298 false, SDE_CHROMA_H2V1, 4, 2, SDE_FORMAT_FLAG_YUV,
299 SDE_FETCH_LINEAR, 2),
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400300
301 INTERLEAVED_YUV_FMT(YUYV,
302 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
303 C0_G_Y, C1_B_Cb, C0_G_Y, C2_R_Cr,
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400304 false, SDE_CHROMA_H2V1, 4, 2, SDE_FORMAT_FLAG_YUV,
305 SDE_FETCH_LINEAR, 2),
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400306
307 INTERLEAVED_YUV_FMT(YVYU,
308 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
309 C0_G_Y, C2_R_Cr, C0_G_Y, C1_B_Cb,
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400310 false, SDE_CHROMA_H2V1, 4, 2, SDE_FORMAT_FLAG_YUV,
311 SDE_FETCH_LINEAR, 2),
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400312
313 PLANAR_YUV_FMT(YUV420,
314 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
315 C2_R_Cr, C1_B_Cb, C0_G_Y,
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400316 false, SDE_CHROMA_420, 1, SDE_FORMAT_FLAG_YUV,
317 SDE_FETCH_LINEAR, 3),
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400318
319 PLANAR_YUV_FMT(YVU420,
320 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
321 C1_B_Cb, C2_R_Cr, C0_G_Y,
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400322 false, SDE_CHROMA_420, 1, SDE_FORMAT_FLAG_YUV,
323 SDE_FETCH_LINEAR, 3),
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400324};
325
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400326/*
327 * UBWC formats table:
328 * This table holds the UBWC formats supported.
329 * If a compression ratio needs to be used for this or any other format,
330 * the data will be passed by user-space.
331 */
332static const struct sde_format sde_format_map_ubwc[] = {
333 INTERLEAVED_RGB_FMT(RGB565,
334 0, COLOR_5BIT, COLOR_6BIT, COLOR_5BIT,
335 C2_R_Cr, C0_G_Y, C1_B_Cb, 0, 3,
336 false, 2, 0,
337 SDE_FETCH_UBWC, 2),
338
339 INTERLEAVED_RGB_FMT(RGBA8888,
340 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
341 C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
342 true, 4, 0,
343 SDE_FETCH_UBWC, 2),
344
345 INTERLEAVED_RGB_FMT(RGBX8888,
346 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
347 C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
348 false, 4, 0,
349 SDE_FETCH_UBWC, 2),
350
351 PSEDUO_YUV_FMT(NV12,
352 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
353 C1_B_Cb, C2_R_Cr,
354 SDE_CHROMA_420, SDE_FORMAT_FLAG_YUV,
355 SDE_FETCH_UBWC, 4),
356};
357
358/* _sde_get_v_h_subsample_rate - Get subsample rates for all formats we support
359 * Note: Not using the drm_format_*_subsampling since we have formats
360 */
361static void _sde_get_v_h_subsample_rate(
362 enum sde_chroma_samp_type chroma_sample,
363 uint32_t *v_sample,
364 uint32_t *h_sample)
365{
366 switch (chroma_sample) {
367 case SDE_CHROMA_H2V1:
368 *v_sample = 1;
369 *h_sample = 2;
370 break;
371 case SDE_CHROMA_H1V2:
372 *v_sample = 2;
373 *h_sample = 1;
374 break;
375 case SDE_CHROMA_420:
376 *v_sample = 2;
377 *h_sample = 2;
378 break;
379 default:
380 *v_sample = 1;
381 *h_sample = 1;
382 break;
383 }
384}
385
386static int _sde_format_get_plane_sizes_ubwc(
387 const struct sde_format *fmt,
388 const uint32_t width,
389 const uint32_t height,
390 struct sde_hw_fmt_layout *layout)
391{
392 int i;
393
394 memset(layout, 0, sizeof(struct sde_hw_fmt_layout));
395 layout->format = fmt;
396 layout->width = width;
397 layout->height = height;
398 layout->num_planes = fmt->num_planes;
399
400 if (fmt->base.pixel_format == DRM_FORMAT_NV12) {
401 uint32_t y_stride_alignment, uv_stride_alignment;
402 uint32_t y_height_alignment, uv_height_alignment;
403 uint32_t y_tile_width = 32;
404 uint32_t y_tile_height = 8;
405 uint32_t uv_tile_width = y_tile_width / 2;
406 uint32_t uv_tile_height = y_tile_height;
407 uint32_t y_bpp_numer = 1, y_bpp_denom = 1;
408 uint32_t uv_bpp_numer = 1, uv_bpp_denom = 1;
409
410 y_stride_alignment = 128;
411 uv_stride_alignment = 64;
412 y_height_alignment = 32;
413 uv_height_alignment = 32;
414 y_bpp_numer = 1;
415 uv_bpp_numer = 2;
416 y_bpp_denom = 1;
417 uv_bpp_denom = 1;
418
419 layout->num_planes = 4;
420 /* Y bitstream stride and plane size */
421 layout->plane_pitch[0] = ALIGN(width, y_stride_alignment);
422 layout->plane_pitch[0] = (layout->plane_pitch[0] * y_bpp_numer)
423 / y_bpp_denom;
424 layout->plane_size[0] = ALIGN(layout->plane_pitch[0] *
425 ALIGN(height, y_height_alignment), 4096);
426
427 /* CbCr bitstream stride and plane size */
428 layout->plane_pitch[1] = ALIGN(width / 2, uv_stride_alignment);
429 layout->plane_pitch[1] = (layout->plane_pitch[1] * uv_bpp_numer)
430 / uv_bpp_denom;
431 layout->plane_size[1] = ALIGN(layout->plane_pitch[1] *
432 ALIGN(height / 2, uv_height_alignment), 4096);
433
434 /* Y meta data stride and plane size */
435 layout->plane_pitch[2] = ALIGN(
436 DIV_ROUND_UP(width, y_tile_width), 64);
437 layout->plane_size[2] = ALIGN(layout->plane_pitch[2] *
438 ALIGN(DIV_ROUND_UP(height, y_tile_height), 16), 4096);
439
440 /* CbCr meta data stride and plane size */
441 layout->plane_pitch[3] = ALIGN(
442 DIV_ROUND_UP(width / 2, uv_tile_width), 64);
443 layout->plane_size[3] = ALIGN(layout->plane_pitch[3] *
444 ALIGN(DIV_ROUND_UP(height / 2, uv_tile_height), 16),
445 4096);
446
447 } else if (fmt->base.pixel_format == DRM_FORMAT_RGBA8888 ||
448 fmt->base.pixel_format == DRM_FORMAT_RGBX8888 ||
449 fmt->base.pixel_format == DRM_FORMAT_RGB565) {
450 uint32_t stride_alignment, aligned_bitstream_width;
451
452 if (fmt->base.pixel_format == DRM_FORMAT_RGB565)
453 stride_alignment = 128;
454 else
455 stride_alignment = 64;
456 layout->num_planes = 3;
457
458 /* Nothing in plane[1] */
459
460 /* RGB bitstream stride and plane size */
461 aligned_bitstream_width = ALIGN(width, stride_alignment);
462 layout->plane_pitch[0] = aligned_bitstream_width * fmt->bpp;
463 layout->plane_size[0] = ALIGN(fmt->bpp * aligned_bitstream_width
464 * ALIGN(height, 16), 4096);
465
466 /* RGB meta data stride and plane size */
467 layout->plane_pitch[2] = ALIGN(DIV_ROUND_UP(
468 aligned_bitstream_width, 16), 64);
469 layout->plane_size[2] = ALIGN(layout->plane_pitch[2] *
470 ALIGN(DIV_ROUND_UP(height, 4), 16), 4096);
471 } else {
472 DRM_ERROR("UBWC format not supported for fmt:0x%X\n",
473 fmt->base.pixel_format);
474 return -EINVAL;
475 }
476
477 for (i = 0; i < SDE_MAX_PLANES; i++)
478 layout->total_size += layout->plane_size[i];
479
480 return 0;
481}
482
483static int _sde_format_get_plane_sizes_linear(
484 const struct sde_format *fmt,
485 const uint32_t width,
486 const uint32_t height,
487 struct sde_hw_fmt_layout *layout)
488{
489 int i;
490
491 memset(layout, 0, sizeof(struct sde_hw_fmt_layout));
492 layout->format = fmt;
493 layout->width = width;
494 layout->height = height;
495 layout->num_planes = fmt->num_planes;
496
497 /* Due to memset above, only need to set planes of interest */
498 if (fmt->fetch_planes == SDE_PLANE_INTERLEAVED) {
499 layout->num_planes = 1;
500 layout->plane_size[0] = width * height * layout->format->bpp;
501 layout->plane_pitch[0] = width * layout->format->bpp;
502 } else {
503 uint32_t v_subsample, h_subsample;
504 uint32_t chroma_samp;
505
506 chroma_samp = fmt->chroma_sample;
507 _sde_get_v_h_subsample_rate(chroma_samp, &v_subsample,
508 &h_subsample);
509
510 if (width % h_subsample || height % v_subsample) {
511 DRM_ERROR("mismatch in subsample vs dimensions\n");
512 return -EINVAL;
513 }
514
515 layout->plane_pitch[0] = width;
516 layout->plane_pitch[1] = width / h_subsample;
517 layout->plane_size[0] = layout->plane_pitch[0] * height;
518 layout->plane_size[1] = layout->plane_pitch[1] *
519 (height / v_subsample);
520
521 if (fmt->fetch_planes == SDE_PLANE_PSEUDO_PLANAR) {
522 layout->num_planes = 2;
523 layout->plane_size[1] *= 2;
524 layout->plane_pitch[1] *= 2;
525 } else {
526 /* planar */
527 layout->num_planes = 3;
528 layout->plane_size[2] = layout->plane_size[1];
529 layout->plane_pitch[2] = layout->plane_pitch[1];
530 }
531 }
532
533 for (i = 0; i < SDE_MAX_PLANES; i++)
534 layout->total_size += layout->plane_size[i];
535
536 return 0;
537}
538
539static int _sde_format_get_plane_sizes(
540 const struct sde_format *fmt,
541 const uint32_t w,
542 const uint32_t h,
543 struct sde_hw_fmt_layout *layout)
544{
545 if (!layout || !fmt) {
546 DRM_ERROR("invalid pointer\n");
547 return -EINVAL;
548 }
549
550 if ((w > SDE_MAX_IMG_WIDTH) || (h > SDE_MAX_IMG_HEIGHT)) {
551 DRM_ERROR("image dimensions outside max range\n");
552 return -ERANGE;
553 }
554
555 if (SDE_FORMAT_IS_UBWC(fmt))
556 return _sde_format_get_plane_sizes_ubwc(fmt, w, h, layout);
557
558 return _sde_format_get_plane_sizes_linear(fmt, w, h, layout);
559}
560
561static int _sde_format_populate_addrs_ubwc(
562 int mmu_id,
563 struct drm_framebuffer *fb,
564 struct sde_hw_fmt_layout *layout)
565{
566 uint32_t base_addr;
567
568 if (!fb || !layout) {
569 DRM_ERROR("invalid pointers\n");
570 return -EINVAL;
571 }
572
573 base_addr = msm_framebuffer_iova(fb, mmu_id, 0);
574 if (!base_addr) {
575 DRM_ERROR("failed to retrieve base addr\n");
576 return -EFAULT;
577 }
578
579 /* Per-format logic for verifying active planes */
580 if (SDE_FORMAT_IS_YUV(layout->format)) {
581 /************************************************/
582 /* UBWC ** */
583 /* buffer ** SDE PLANE */
584 /* format ** */
585 /************************************************/
586 /* ------------------- ** -------------------- */
587 /* | Y meta | ** | Y bitstream | */
588 /* | data | ** | plane | */
589 /* ------------------- ** -------------------- */
590 /* | Y bitstream | ** | CbCr bitstream | */
591 /* | data | ** | plane | */
592 /* ------------------- ** -------------------- */
593 /* | Cbcr metadata | ** | Y meta | */
594 /* | data | ** | plane | */
595 /* ------------------- ** -------------------- */
596 /* | CbCr bitstream | ** | CbCr meta | */
597 /* | data | ** | plane | */
598 /* ------------------- ** -------------------- */
599 /************************************************/
600
601 /* configure Y bitstream plane */
602 layout->plane_addr[0] = base_addr + layout->plane_size[2];
603
604 /* configure CbCr bitstream plane */
605 layout->plane_addr[1] = base_addr + layout->plane_size[0]
606 + layout->plane_size[2] + layout->plane_size[3];
607
608 /* configure Y metadata plane */
609 layout->plane_addr[2] = base_addr;
610
611 /* configure CbCr metadata plane */
612 layout->plane_addr[3] = base_addr + layout->plane_size[0]
613 + layout->plane_size[2];
614
615 } else {
616 /************************************************/
617 /* UBWC ** */
618 /* buffer ** SDE PLANE */
619 /* format ** */
620 /************************************************/
621 /* ------------------- ** -------------------- */
622 /* | RGB meta | ** | RGB bitstream | */
623 /* | data | ** | plane | */
624 /* ------------------- ** -------------------- */
625 /* | RGB bitstream | ** | NONE | */
626 /* | data | ** | | */
627 /* ------------------- ** -------------------- */
628 /* ** | RGB meta | */
629 /* ** | plane | */
630 /* ** -------------------- */
631 /************************************************/
632
633 layout->plane_addr[0] = base_addr + layout->plane_size[2];
634 layout->plane_addr[1] = 0;
635 layout->plane_addr[2] = base_addr;
636 layout->plane_addr[3] = 0;
637 }
638
639 return 0;
640}
641
642static int _sde_format_populate_addrs_linear(
643 int mmu_id,
644 struct drm_framebuffer *fb,
645 struct sde_hw_fmt_layout *layout)
646{
647 unsigned int i;
648
649 /* Can now check the pitches given vs pitches expected */
650 for (i = 0; i < layout->num_planes; ++i) {
651 if (layout->plane_pitch[i] != fb->pitches[i]) {
652 DRM_ERROR("plane %u expected pitch %u, fb %u\n",
653 i, layout->plane_pitch[i], fb->pitches[i]);
654 return -EINVAL;
655 }
656 }
657
658 /* Populate addresses for simple formats here */
659 for (i = 0; i < layout->num_planes; ++i) {
660 layout->plane_addr[i] = msm_framebuffer_iova(fb, mmu_id, i);
661 if (!layout->plane_addr[i]) {
662 DRM_ERROR("failed to retrieve base addr\n");
663 return -EFAULT;
664 }
665 }
666
667 return 0;
668}
669
670int sde_format_populate_layout(
671 int mmu_id,
672 struct drm_framebuffer *fb,
673 struct sde_hw_fmt_layout *layout)
674{
675 int ret;
676
677 if (!fb || !layout) {
678 DRM_ERROR("invalid arguments\n");
679 return -EINVAL;
680 }
681
682 if ((fb->width > SDE_MAX_IMG_WIDTH) ||
683 (fb->height > SDE_MAX_IMG_HEIGHT)) {
684 DRM_ERROR("image dimensions outside max range\n");
685 return -ERANGE;
686 }
687
688 layout->format = to_sde_format(msm_framebuffer_format(fb));
689
690 /* Populate the plane sizes etc via get_format */
691 ret = _sde_format_get_plane_sizes(layout->format, fb->width, fb->height,
692 layout);
693 if (ret)
694 return ret;
695
696 /* Populate the addresses given the fb */
697 if (SDE_FORMAT_IS_UBWC(layout->format))
698 ret = _sde_format_populate_addrs_ubwc(mmu_id, fb, layout);
699 else
700 ret = _sde_format_populate_addrs_linear(mmu_id, fb, layout);
701
702 return ret;
703}
704
705int sde_format_check_modified_format(
706 const struct msm_kms *kms,
707 const struct msm_format *msm_fmt,
708 const struct drm_mode_fb_cmd2 *cmd,
709 struct drm_gem_object **bos)
710{
711 int ret, i, num_base_fmt_planes;
712 const struct sde_format *fmt;
713 struct sde_hw_fmt_layout layout;
714 uint32_t bos_total_size = 0;
715
716 if (!msm_fmt || !cmd || !bos) {
717 DRM_ERROR("invalid arguments\n");
718 return -EINVAL;
719 }
720
721 fmt = to_sde_format(msm_fmt);
722 num_base_fmt_planes = drm_format_num_planes(fmt->base.pixel_format);
723
724 ret = _sde_format_get_plane_sizes(fmt, cmd->width, cmd->height,
725 &layout);
726 if (ret)
727 return ret;
728
729 for (i = 0; i < num_base_fmt_planes; i++) {
730 if (!bos[i]) {
731 DRM_ERROR("invalid handle for plane %d\n", i);
732 return -EINVAL;
733 }
734 bos_total_size += bos[i]->size;
735 }
736
737 if (bos_total_size < layout.total_size) {
738 DRM_ERROR("buffers total size too small %u expected %u\n",
739 bos_total_size, layout.total_size);
740 return -EINVAL;
741 }
742
743 return 0;
744}
745
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400746const struct sde_format *sde_get_sde_format_ext(
747 const uint32_t format,
748 const uint64_t *modifiers,
749 const uint32_t modifiers_len)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400750{
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400751 uint32_t i = 0;
752 uint64_t mod0 = 0;
753 const struct sde_format *fmt = NULL;
754 const struct sde_format *map = NULL;
755 ssize_t map_size = 0;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400756
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400757 /*
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400758 * Currently only support exactly zero or one modifier.
759 * All planes used must specify the same modifier.
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400760 */
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400761 if (modifiers_len && !modifiers) {
762 DRM_ERROR("invalid modifiers array\n");
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400763 return NULL;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400764 } else if (modifiers && modifiers_len && modifiers[0]) {
765 mod0 = modifiers[0];
766 DBG("plane format modifier 0x%llX", mod0);
767 for (i = 1; i < modifiers_len; i++) {
768 if (modifiers[i] != mod0) {
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400769 DRM_ERROR("bad fmt mod 0x%llX on plane %d\n",
770 modifiers[i], i);
771 return NULL;
772 }
773 }
774 }
775
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400776 switch (mod0) {
777 case 0:
778 map = sde_format_map;
779 map_size = ARRAY_SIZE(sde_format_map);
780 break;
781 case DRM_FORMAT_MOD_QCOM_COMPRESSED:
782 map = sde_format_map_ubwc;
783 map_size = ARRAY_SIZE(sde_format_map_ubwc);
784 DBG("found fmt 0x%X DRM_FORMAT_MOD_QCOM_COMPRESSED", format);
785 break;
786 default:
787 DRM_ERROR("unsupported format modifier %llX\n", mod0);
788 return NULL;
789 }
790
791 for (i = 0; i < map_size; i++) {
792 if (format == map[i].base.pixel_format) {
793 fmt = &map[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400794 break;
795 }
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400796 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400797
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400798 if (fmt == NULL)
799 DRM_ERROR("unsupported fmt 0x%X modifier 0x%llX\n",
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400800 format, mod0);
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400801 else
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400802 DBG("fmt %s mod 0x%llX ubwc %d yuv %d",
803 drm_get_format_name(format), mod0,
804 SDE_FORMAT_IS_UBWC(fmt),
805 SDE_FORMAT_IS_YUV(fmt));
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400806
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400807 return fmt;
808}
809
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400810const struct msm_format *sde_get_msm_format(
811 struct msm_kms *kms,
812 const uint32_t format,
813 const uint64_t *modifiers,
814 const uint32_t modifiers_len)
815{
816 const struct sde_format *fmt = sde_get_sde_format_ext(format,
817 modifiers, modifiers_len);
818 if (fmt)
819 return &fmt->base;
820 return NULL;
821}
822
Clarence Ipea3d6262016-07-15 16:20:11 -0400823uint32_t sde_populate_formats(
824 const struct sde_format_extended *format_list,
825 uint32_t *pixel_formats,
826 uint64_t *pixel_modifiers,
827 uint32_t pixel_formats_max)
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400828{
Clarence Ipea3d6262016-07-15 16:20:11 -0400829 uint32_t i, fourcc_format;
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400830
Clarence Ipea3d6262016-07-15 16:20:11 -0400831 if (!format_list || !pixel_formats)
832 return 0;
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400833
Clarence Ipea3d6262016-07-15 16:20:11 -0400834 for (i = 0, fourcc_format = 0;
835 format_list->fourcc_format && i < pixel_formats_max;
836 ++format_list) {
837 /* verify if listed format is in sde_format_map? */
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400838
Clarence Ipea3d6262016-07-15 16:20:11 -0400839 /* optionally return modified formats */
840 if (pixel_modifiers) {
841 /* assume same modifier for all fb planes */
842 pixel_formats[i] = format_list->fourcc_format;
843 pixel_modifiers[i++] = format_list->modifier;
844 } else {
845 /* assume base formats grouped together */
846 if (fourcc_format != format_list->fourcc_format) {
847 fourcc_format = format_list->fourcc_format;
848 pixel_formats[i++] = fourcc_format;
849 }
850 }
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400851 }
852
853 return i;
854}