blob: ac14bad5670c0a6ce7ef08cd4fe0e702b713fabe [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
127 INTERLEAVED_RGB_FMT(XRGB8888,
128 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400129 C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA, 4,
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400130 false, 4, 0,
131 SDE_FETCH_LINEAR, 1),
132
133 INTERLEAVED_RGB_FMT(RGBX8888,
134 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
135 C3_ALPHA, C1_B_Cb, C0_G_Y, C2_R_Cr, 4,
136 false, 4, 0,
137 SDE_FETCH_LINEAR, 1),
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400138
139 INTERLEAVED_RGB_FMT(RGB888,
140 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400141 C1_B_Cb, C0_G_Y, C2_R_Cr, 0, 3,
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400142 false, 3, 0,
143 SDE_FETCH_LINEAR, 1),
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400144
145 INTERLEAVED_RGB_FMT(BGR888,
146 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400147 C2_R_Cr, C0_G_Y, C1_B_Cb, 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(RGB565,
152 0, COLOR_5BIT, COLOR_6BIT, COLOR_5BIT,
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400153 C1_B_Cb, C0_G_Y, C2_R_Cr, 0, 3,
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400154 false, 2, 0,
155 SDE_FETCH_LINEAR, 1),
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400156
157 INTERLEAVED_RGB_FMT(BGR565,
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400158 0, COLOR_5BIT, COLOR_6BIT, COLOR_5BIT,
159 C2_R_Cr, C0_G_Y, C1_B_Cb, 0, 3,
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400160 false, 2, 0,
161 SDE_FETCH_LINEAR, 1),
162
163 INTERLEAVED_RGB_FMT(ARGB1555,
164 COLOR_ALPHA_1BIT, COLOR_5BIT, COLOR_5BIT, COLOR_5BIT,
165 C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA, 4,
166 true, 2, 0,
167 SDE_FETCH_LINEAR, 1),
168
169 INTERLEAVED_RGB_FMT(ABGR1555,
170 COLOR_ALPHA_1BIT, COLOR_5BIT, COLOR_5BIT, COLOR_5BIT,
171 C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
172 true, 2, 0,
173 SDE_FETCH_LINEAR, 1),
174
175 INTERLEAVED_RGB_FMT(RGBA5551,
176 COLOR_ALPHA_1BIT, COLOR_5BIT, COLOR_5BIT, COLOR_5BIT,
177 C3_ALPHA, C1_B_Cb, C0_G_Y, C2_R_Cr, 4,
178 true, 2, 0,
179 SDE_FETCH_LINEAR, 1),
180
181 INTERLEAVED_RGB_FMT(BGRA5551,
182 COLOR_ALPHA_1BIT, COLOR_5BIT, COLOR_5BIT, COLOR_5BIT,
183 C3_ALPHA, C2_R_Cr, C0_G_Y, C1_B_Cb, 4,
184 true, 2, 0,
185 SDE_FETCH_LINEAR, 1),
186
187 INTERLEAVED_RGB_FMT(XRGB1555,
188 COLOR_ALPHA_1BIT, COLOR_5BIT, COLOR_5BIT, COLOR_5BIT,
189 C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA, 4,
190 false, 2, 0,
191 SDE_FETCH_LINEAR, 1),
192
193 INTERLEAVED_RGB_FMT(XBGR1555,
194 COLOR_ALPHA_1BIT, COLOR_5BIT, COLOR_5BIT, COLOR_5BIT,
195 C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
196 false, 2, 0,
197 SDE_FETCH_LINEAR, 1),
198
199 INTERLEAVED_RGB_FMT(RGBX5551,
200 COLOR_ALPHA_1BIT, COLOR_5BIT, COLOR_5BIT, COLOR_5BIT,
201 C3_ALPHA, C1_B_Cb, C0_G_Y, C2_R_Cr, 4,
202 false, 2, 0,
203 SDE_FETCH_LINEAR, 1),
204
205 INTERLEAVED_RGB_FMT(BGRX5551,
206 COLOR_ALPHA_1BIT, COLOR_5BIT, COLOR_5BIT, COLOR_5BIT,
207 C3_ALPHA, C2_R_Cr, C0_G_Y, C1_B_Cb, 4,
208 false, 2, 0,
209 SDE_FETCH_LINEAR, 1),
210
211 INTERLEAVED_RGB_FMT(ARGB4444,
212 COLOR_ALPHA_4BIT, COLOR_4BIT, COLOR_4BIT, COLOR_4BIT,
213 C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA, 4,
214 true, 2, 0,
215 SDE_FETCH_LINEAR, 1),
216
217 INTERLEAVED_RGB_FMT(ABGR4444,
218 COLOR_ALPHA_4BIT, COLOR_4BIT, COLOR_4BIT, COLOR_4BIT,
219 C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
220 true, 2, 0,
221 SDE_FETCH_LINEAR, 1),
222
223 INTERLEAVED_RGB_FMT(RGBA4444,
224 COLOR_ALPHA_4BIT, COLOR_4BIT, COLOR_4BIT, COLOR_4BIT,
225 C3_ALPHA, C1_B_Cb, C0_G_Y, C2_R_Cr, 4,
226 true, 2, 0,
227 SDE_FETCH_LINEAR, 1),
228
229 INTERLEAVED_RGB_FMT(BGRA4444,
230 COLOR_ALPHA_4BIT, COLOR_4BIT, COLOR_4BIT, COLOR_4BIT,
231 C3_ALPHA, C2_R_Cr, C0_G_Y, C1_B_Cb, 4,
232 true, 2, 0,
233 SDE_FETCH_LINEAR, 1),
234
235 INTERLEAVED_RGB_FMT(XRGB4444,
236 COLOR_ALPHA_4BIT, COLOR_4BIT, COLOR_4BIT, COLOR_4BIT,
237 C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA, 4,
238 false, 2, 0,
239 SDE_FETCH_LINEAR, 1),
240
241 INTERLEAVED_RGB_FMT(XBGR4444,
242 COLOR_ALPHA_4BIT, COLOR_4BIT, COLOR_4BIT, COLOR_4BIT,
243 C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
244 false, 2, 0,
245 SDE_FETCH_LINEAR, 1),
246
247 INTERLEAVED_RGB_FMT(RGBX4444,
248 COLOR_ALPHA_4BIT, COLOR_4BIT, COLOR_4BIT, COLOR_4BIT,
249 C3_ALPHA, C1_B_Cb, C0_G_Y, C2_R_Cr, 4,
250 false, 2, 0,
251 SDE_FETCH_LINEAR, 1),
252
253 INTERLEAVED_RGB_FMT(BGRX4444,
254 COLOR_ALPHA_4BIT, COLOR_4BIT, COLOR_4BIT, COLOR_4BIT,
255 C3_ALPHA, C2_R_Cr, C0_G_Y, C1_B_Cb, 4,
256 false, 2, 0,
257 SDE_FETCH_LINEAR, 1),
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400258
259 PSEDUO_YUV_FMT(NV12,
260 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
261 C1_B_Cb, C2_R_Cr,
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400262 SDE_CHROMA_420, SDE_FORMAT_FLAG_YUV,
263 SDE_FETCH_LINEAR, 2),
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400264
265 PSEDUO_YUV_FMT(NV21,
266 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
267 C2_R_Cr, C1_B_Cb,
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(NV16,
272 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
273 C1_B_Cb, C2_R_Cr,
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400274 SDE_CHROMA_H2V1, SDE_FORMAT_FLAG_YUV,
275 SDE_FETCH_LINEAR, 2),
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400276
277 PSEDUO_YUV_FMT(NV61,
278 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
279 C2_R_Cr, C1_B_Cb,
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 INTERLEAVED_YUV_FMT(VYUY,
284 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
285 C2_R_Cr, C0_G_Y, C1_B_Cb, C0_G_Y,
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400286 false, SDE_CHROMA_H2V1, 4, 2, SDE_FORMAT_FLAG_YUV,
287 SDE_FETCH_LINEAR, 2),
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400288
289 INTERLEAVED_YUV_FMT(UYVY,
290 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
291 C1_B_Cb, C0_G_Y, C2_R_Cr, 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(YUYV,
296 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
297 C0_G_Y, C1_B_Cb, C0_G_Y, C2_R_Cr,
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(YVYU,
302 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
303 C0_G_Y, C2_R_Cr, C0_G_Y, C1_B_Cb,
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 PLANAR_YUV_FMT(YUV420,
308 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
309 C2_R_Cr, C1_B_Cb, C0_G_Y,
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400310 false, SDE_CHROMA_420, 1, SDE_FORMAT_FLAG_YUV,
311 SDE_FETCH_LINEAR, 3),
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400312
313 PLANAR_YUV_FMT(YVU420,
314 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
315 C1_B_Cb, C2_R_Cr, 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
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400320/*
321 * UBWC formats table:
322 * This table holds the UBWC formats supported.
323 * If a compression ratio needs to be used for this or any other format,
324 * the data will be passed by user-space.
325 */
326static const struct sde_format sde_format_map_ubwc[] = {
327 INTERLEAVED_RGB_FMT(RGB565,
328 0, COLOR_5BIT, COLOR_6BIT, COLOR_5BIT,
329 C2_R_Cr, C0_G_Y, C1_B_Cb, 0, 3,
330 false, 2, 0,
331 SDE_FETCH_UBWC, 2),
332
333 INTERLEAVED_RGB_FMT(RGBA8888,
334 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
335 C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
336 true, 4, 0,
337 SDE_FETCH_UBWC, 2),
338
339 INTERLEAVED_RGB_FMT(RGBX8888,
340 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
341 C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
342 false, 4, 0,
343 SDE_FETCH_UBWC, 2),
344
345 PSEDUO_YUV_FMT(NV12,
346 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
347 C1_B_Cb, C2_R_Cr,
348 SDE_CHROMA_420, SDE_FORMAT_FLAG_YUV,
349 SDE_FETCH_UBWC, 4),
350};
351
352/* _sde_get_v_h_subsample_rate - Get subsample rates for all formats we support
353 * Note: Not using the drm_format_*_subsampling since we have formats
354 */
355static void _sde_get_v_h_subsample_rate(
356 enum sde_chroma_samp_type chroma_sample,
357 uint32_t *v_sample,
358 uint32_t *h_sample)
359{
360 switch (chroma_sample) {
361 case SDE_CHROMA_H2V1:
362 *v_sample = 1;
363 *h_sample = 2;
364 break;
365 case SDE_CHROMA_H1V2:
366 *v_sample = 2;
367 *h_sample = 1;
368 break;
369 case SDE_CHROMA_420:
370 *v_sample = 2;
371 *h_sample = 2;
372 break;
373 default:
374 *v_sample = 1;
375 *h_sample = 1;
376 break;
377 }
378}
379
380static int _sde_format_get_plane_sizes_ubwc(
381 const struct sde_format *fmt,
382 const uint32_t width,
383 const uint32_t height,
384 struct sde_hw_fmt_layout *layout)
385{
386 int i;
387
388 memset(layout, 0, sizeof(struct sde_hw_fmt_layout));
389 layout->format = fmt;
390 layout->width = width;
391 layout->height = height;
392 layout->num_planes = fmt->num_planes;
393
394 if (fmt->base.pixel_format == DRM_FORMAT_NV12) {
395 uint32_t y_stride_alignment, uv_stride_alignment;
396 uint32_t y_height_alignment, uv_height_alignment;
397 uint32_t y_tile_width = 32;
398 uint32_t y_tile_height = 8;
399 uint32_t uv_tile_width = y_tile_width / 2;
400 uint32_t uv_tile_height = y_tile_height;
401 uint32_t y_bpp_numer = 1, y_bpp_denom = 1;
402 uint32_t uv_bpp_numer = 1, uv_bpp_denom = 1;
403
404 y_stride_alignment = 128;
405 uv_stride_alignment = 64;
406 y_height_alignment = 32;
407 uv_height_alignment = 32;
408 y_bpp_numer = 1;
409 uv_bpp_numer = 2;
410 y_bpp_denom = 1;
411 uv_bpp_denom = 1;
412
413 layout->num_planes = 4;
414 /* Y bitstream stride and plane size */
415 layout->plane_pitch[0] = ALIGN(width, y_stride_alignment);
416 layout->plane_pitch[0] = (layout->plane_pitch[0] * y_bpp_numer)
417 / y_bpp_denom;
418 layout->plane_size[0] = ALIGN(layout->plane_pitch[0] *
419 ALIGN(height, y_height_alignment), 4096);
420
421 /* CbCr bitstream stride and plane size */
422 layout->plane_pitch[1] = ALIGN(width / 2, uv_stride_alignment);
423 layout->plane_pitch[1] = (layout->plane_pitch[1] * uv_bpp_numer)
424 / uv_bpp_denom;
425 layout->plane_size[1] = ALIGN(layout->plane_pitch[1] *
426 ALIGN(height / 2, uv_height_alignment), 4096);
427
428 /* Y meta data stride and plane size */
429 layout->plane_pitch[2] = ALIGN(
430 DIV_ROUND_UP(width, y_tile_width), 64);
431 layout->plane_size[2] = ALIGN(layout->plane_pitch[2] *
432 ALIGN(DIV_ROUND_UP(height, y_tile_height), 16), 4096);
433
434 /* CbCr meta data stride and plane size */
435 layout->plane_pitch[3] = ALIGN(
436 DIV_ROUND_UP(width / 2, uv_tile_width), 64);
437 layout->plane_size[3] = ALIGN(layout->plane_pitch[3] *
438 ALIGN(DIV_ROUND_UP(height / 2, uv_tile_height), 16),
439 4096);
440
441 } else if (fmt->base.pixel_format == DRM_FORMAT_RGBA8888 ||
442 fmt->base.pixel_format == DRM_FORMAT_RGBX8888 ||
443 fmt->base.pixel_format == DRM_FORMAT_RGB565) {
444 uint32_t stride_alignment, aligned_bitstream_width;
445
446 if (fmt->base.pixel_format == DRM_FORMAT_RGB565)
447 stride_alignment = 128;
448 else
449 stride_alignment = 64;
450 layout->num_planes = 3;
451
452 /* Nothing in plane[1] */
453
454 /* RGB bitstream stride and plane size */
455 aligned_bitstream_width = ALIGN(width, stride_alignment);
456 layout->plane_pitch[0] = aligned_bitstream_width * fmt->bpp;
457 layout->plane_size[0] = ALIGN(fmt->bpp * aligned_bitstream_width
458 * ALIGN(height, 16), 4096);
459
460 /* RGB meta data stride and plane size */
461 layout->plane_pitch[2] = ALIGN(DIV_ROUND_UP(
462 aligned_bitstream_width, 16), 64);
463 layout->plane_size[2] = ALIGN(layout->plane_pitch[2] *
464 ALIGN(DIV_ROUND_UP(height, 4), 16), 4096);
465 } else {
466 DRM_ERROR("UBWC format not supported for fmt:0x%X\n",
467 fmt->base.pixel_format);
468 return -EINVAL;
469 }
470
471 for (i = 0; i < SDE_MAX_PLANES; i++)
472 layout->total_size += layout->plane_size[i];
473
474 return 0;
475}
476
477static int _sde_format_get_plane_sizes_linear(
478 const struct sde_format *fmt,
479 const uint32_t width,
480 const uint32_t height,
481 struct sde_hw_fmt_layout *layout)
482{
483 int i;
484
485 memset(layout, 0, sizeof(struct sde_hw_fmt_layout));
486 layout->format = fmt;
487 layout->width = width;
488 layout->height = height;
489 layout->num_planes = fmt->num_planes;
490
491 /* Due to memset above, only need to set planes of interest */
492 if (fmt->fetch_planes == SDE_PLANE_INTERLEAVED) {
493 layout->num_planes = 1;
494 layout->plane_size[0] = width * height * layout->format->bpp;
495 layout->plane_pitch[0] = width * layout->format->bpp;
496 } else {
497 uint32_t v_subsample, h_subsample;
498 uint32_t chroma_samp;
499
500 chroma_samp = fmt->chroma_sample;
501 _sde_get_v_h_subsample_rate(chroma_samp, &v_subsample,
502 &h_subsample);
503
504 if (width % h_subsample || height % v_subsample) {
505 DRM_ERROR("mismatch in subsample vs dimensions\n");
506 return -EINVAL;
507 }
508
509 layout->plane_pitch[0] = width;
510 layout->plane_pitch[1] = width / h_subsample;
511 layout->plane_size[0] = layout->plane_pitch[0] * height;
512 layout->plane_size[1] = layout->plane_pitch[1] *
513 (height / v_subsample);
514
515 if (fmt->fetch_planes == SDE_PLANE_PSEUDO_PLANAR) {
516 layout->num_planes = 2;
517 layout->plane_size[1] *= 2;
518 layout->plane_pitch[1] *= 2;
519 } else {
520 /* planar */
521 layout->num_planes = 3;
522 layout->plane_size[2] = layout->plane_size[1];
523 layout->plane_pitch[2] = layout->plane_pitch[1];
524 }
525 }
526
527 for (i = 0; i < SDE_MAX_PLANES; i++)
528 layout->total_size += layout->plane_size[i];
529
530 return 0;
531}
532
533static int _sde_format_get_plane_sizes(
534 const struct sde_format *fmt,
535 const uint32_t w,
536 const uint32_t h,
537 struct sde_hw_fmt_layout *layout)
538{
539 if (!layout || !fmt) {
540 DRM_ERROR("invalid pointer\n");
541 return -EINVAL;
542 }
543
544 if ((w > SDE_MAX_IMG_WIDTH) || (h > SDE_MAX_IMG_HEIGHT)) {
545 DRM_ERROR("image dimensions outside max range\n");
546 return -ERANGE;
547 }
548
549 if (SDE_FORMAT_IS_UBWC(fmt))
550 return _sde_format_get_plane_sizes_ubwc(fmt, w, h, layout);
551
552 return _sde_format_get_plane_sizes_linear(fmt, w, h, layout);
553}
554
555static int _sde_format_populate_addrs_ubwc(
556 int mmu_id,
557 struct drm_framebuffer *fb,
558 struct sde_hw_fmt_layout *layout)
559{
560 uint32_t base_addr;
561
562 if (!fb || !layout) {
563 DRM_ERROR("invalid pointers\n");
564 return -EINVAL;
565 }
566
567 base_addr = msm_framebuffer_iova(fb, mmu_id, 0);
568 if (!base_addr) {
569 DRM_ERROR("failed to retrieve base addr\n");
570 return -EFAULT;
571 }
572
573 /* Per-format logic for verifying active planes */
574 if (SDE_FORMAT_IS_YUV(layout->format)) {
575 /************************************************/
576 /* UBWC ** */
577 /* buffer ** SDE PLANE */
578 /* format ** */
579 /************************************************/
580 /* ------------------- ** -------------------- */
581 /* | Y meta | ** | Y bitstream | */
582 /* | data | ** | plane | */
583 /* ------------------- ** -------------------- */
584 /* | Y bitstream | ** | CbCr bitstream | */
585 /* | data | ** | plane | */
586 /* ------------------- ** -------------------- */
587 /* | Cbcr metadata | ** | Y meta | */
588 /* | data | ** | plane | */
589 /* ------------------- ** -------------------- */
590 /* | CbCr bitstream | ** | CbCr meta | */
591 /* | data | ** | plane | */
592 /* ------------------- ** -------------------- */
593 /************************************************/
594
595 /* configure Y bitstream plane */
596 layout->plane_addr[0] = base_addr + layout->plane_size[2];
597
598 /* configure CbCr bitstream plane */
599 layout->plane_addr[1] = base_addr + layout->plane_size[0]
600 + layout->plane_size[2] + layout->plane_size[3];
601
602 /* configure Y metadata plane */
603 layout->plane_addr[2] = base_addr;
604
605 /* configure CbCr metadata plane */
606 layout->plane_addr[3] = base_addr + layout->plane_size[0]
607 + layout->plane_size[2];
608
609 } else {
610 /************************************************/
611 /* UBWC ** */
612 /* buffer ** SDE PLANE */
613 /* format ** */
614 /************************************************/
615 /* ------------------- ** -------------------- */
616 /* | RGB meta | ** | RGB bitstream | */
617 /* | data | ** | plane | */
618 /* ------------------- ** -------------------- */
619 /* | RGB bitstream | ** | NONE | */
620 /* | data | ** | | */
621 /* ------------------- ** -------------------- */
622 /* ** | RGB meta | */
623 /* ** | plane | */
624 /* ** -------------------- */
625 /************************************************/
626
627 layout->plane_addr[0] = base_addr + layout->plane_size[2];
628 layout->plane_addr[1] = 0;
629 layout->plane_addr[2] = base_addr;
630 layout->plane_addr[3] = 0;
631 }
632
633 return 0;
634}
635
636static int _sde_format_populate_addrs_linear(
637 int mmu_id,
638 struct drm_framebuffer *fb,
639 struct sde_hw_fmt_layout *layout)
640{
641 unsigned int i;
642
643 /* Can now check the pitches given vs pitches expected */
644 for (i = 0; i < layout->num_planes; ++i) {
645 if (layout->plane_pitch[i] != fb->pitches[i]) {
646 DRM_ERROR("plane %u expected pitch %u, fb %u\n",
647 i, layout->plane_pitch[i], fb->pitches[i]);
648 return -EINVAL;
649 }
650 }
651
652 /* Populate addresses for simple formats here */
653 for (i = 0; i < layout->num_planes; ++i) {
654 layout->plane_addr[i] = msm_framebuffer_iova(fb, mmu_id, i);
655 if (!layout->plane_addr[i]) {
656 DRM_ERROR("failed to retrieve base addr\n");
657 return -EFAULT;
658 }
659 }
660
661 return 0;
662}
663
664int sde_format_populate_layout(
665 int mmu_id,
666 struct drm_framebuffer *fb,
667 struct sde_hw_fmt_layout *layout)
668{
669 int ret;
670
671 if (!fb || !layout) {
672 DRM_ERROR("invalid arguments\n");
673 return -EINVAL;
674 }
675
676 if ((fb->width > SDE_MAX_IMG_WIDTH) ||
677 (fb->height > SDE_MAX_IMG_HEIGHT)) {
678 DRM_ERROR("image dimensions outside max range\n");
679 return -ERANGE;
680 }
681
682 layout->format = to_sde_format(msm_framebuffer_format(fb));
683
684 /* Populate the plane sizes etc via get_format */
685 ret = _sde_format_get_plane_sizes(layout->format, fb->width, fb->height,
686 layout);
687 if (ret)
688 return ret;
689
690 /* Populate the addresses given the fb */
691 if (SDE_FORMAT_IS_UBWC(layout->format))
692 ret = _sde_format_populate_addrs_ubwc(mmu_id, fb, layout);
693 else
694 ret = _sde_format_populate_addrs_linear(mmu_id, fb, layout);
695
696 return ret;
697}
698
699int sde_format_check_modified_format(
700 const struct msm_kms *kms,
701 const struct msm_format *msm_fmt,
702 const struct drm_mode_fb_cmd2 *cmd,
703 struct drm_gem_object **bos)
704{
705 int ret, i, num_base_fmt_planes;
706 const struct sde_format *fmt;
707 struct sde_hw_fmt_layout layout;
708 uint32_t bos_total_size = 0;
709
710 if (!msm_fmt || !cmd || !bos) {
711 DRM_ERROR("invalid arguments\n");
712 return -EINVAL;
713 }
714
715 fmt = to_sde_format(msm_fmt);
716 num_base_fmt_planes = drm_format_num_planes(fmt->base.pixel_format);
717
718 ret = _sde_format_get_plane_sizes(fmt, cmd->width, cmd->height,
719 &layout);
720 if (ret)
721 return ret;
722
723 for (i = 0; i < num_base_fmt_planes; i++) {
724 if (!bos[i]) {
725 DRM_ERROR("invalid handle for plane %d\n", i);
726 return -EINVAL;
727 }
728 bos_total_size += bos[i]->size;
729 }
730
731 if (bos_total_size < layout.total_size) {
732 DRM_ERROR("buffers total size too small %u expected %u\n",
733 bos_total_size, layout.total_size);
734 return -EINVAL;
735 }
736
737 return 0;
738}
739
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400740const struct sde_format *sde_get_sde_format_ext(
741 const uint32_t format,
742 const uint64_t *modifiers,
743 const uint32_t modifiers_len)
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400744{
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400745 uint32_t i = 0;
746 uint64_t mod0 = 0;
747 const struct sde_format *fmt = NULL;
748 const struct sde_format *map = NULL;
749 ssize_t map_size = 0;
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400750
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400751 /*
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400752 * Currently only support exactly zero or one modifier.
753 * All planes used must specify the same modifier.
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400754 */
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400755 if (modifiers_len && !modifiers) {
756 DRM_ERROR("invalid modifiers array\n");
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400757 return NULL;
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400758 } else if (modifiers && modifiers_len && modifiers[0]) {
759 mod0 = modifiers[0];
760 DBG("plane format modifier 0x%llX", mod0);
761 for (i = 1; i < modifiers_len; i++) {
762 if (modifiers[i] != mod0) {
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400763 DRM_ERROR("bad fmt mod 0x%llX on plane %d\n",
764 modifiers[i], i);
765 return NULL;
766 }
767 }
768 }
769
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400770 switch (mod0) {
771 case 0:
772 map = sde_format_map;
773 map_size = ARRAY_SIZE(sde_format_map);
774 break;
775 case DRM_FORMAT_MOD_QCOM_COMPRESSED:
776 map = sde_format_map_ubwc;
777 map_size = ARRAY_SIZE(sde_format_map_ubwc);
778 DBG("found fmt 0x%X DRM_FORMAT_MOD_QCOM_COMPRESSED", format);
779 break;
780 default:
781 DRM_ERROR("unsupported format modifier %llX\n", mod0);
782 return NULL;
783 }
784
785 for (i = 0; i < map_size; i++) {
786 if (format == map[i].base.pixel_format) {
787 fmt = &map[i];
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400788 break;
789 }
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400790 }
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400791
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400792 if (fmt == NULL)
793 DRM_ERROR("unsupported fmt 0x%X modifier 0x%llX\n",
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400794 format, mod0);
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400795 else
Lloyd Atkinsonfa2489c2016-05-25 15:16:03 -0400796 DBG("fmt %s mod 0x%llX ubwc %d yuv %d",
797 drm_get_format_name(format), mod0,
798 SDE_FORMAT_IS_UBWC(fmt),
799 SDE_FORMAT_IS_YUV(fmt));
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400800
Abhijit Kulkarni3e3e0d22016-06-24 17:56:13 -0400801 return fmt;
802}
803
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400804const struct msm_format *sde_get_msm_format(
805 struct msm_kms *kms,
806 const uint32_t format,
807 const uint64_t *modifiers,
808 const uint32_t modifiers_len)
809{
810 const struct sde_format *fmt = sde_get_sde_format_ext(format,
811 modifiers, modifiers_len);
812 if (fmt)
813 return &fmt->base;
814 return NULL;
815}
816
Clarence Ipea3d6262016-07-15 16:20:11 -0400817uint32_t sde_populate_formats(
818 const struct sde_format_extended *format_list,
819 uint32_t *pixel_formats,
820 uint64_t *pixel_modifiers,
821 uint32_t pixel_formats_max)
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400822{
Clarence Ipea3d6262016-07-15 16:20:11 -0400823 uint32_t i, fourcc_format;
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400824
Clarence Ipea3d6262016-07-15 16:20:11 -0400825 if (!format_list || !pixel_formats)
826 return 0;
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400827
Clarence Ipea3d6262016-07-15 16:20:11 -0400828 for (i = 0, fourcc_format = 0;
829 format_list->fourcc_format && i < pixel_formats_max;
830 ++format_list) {
831 /* verify if listed format is in sde_format_map? */
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400832
Clarence Ipea3d6262016-07-15 16:20:11 -0400833 /* optionally return modified formats */
834 if (pixel_modifiers) {
835 /* assume same modifier for all fb planes */
836 pixel_formats[i] = format_list->fourcc_format;
837 pixel_modifiers[i++] = format_list->modifier;
838 } else {
839 /* assume base formats grouped together */
840 if (fourcc_format != format_list->fourcc_format) {
841 fourcc_format = format_list->fourcc_format;
842 pixel_formats[i++] = fourcc_format;
843 }
844 }
Lloyd Atkinson9a673492016-07-05 11:41:57 -0400845 }
846
847 return i;
848}