0001
0002
0003
0004
0005 #define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__
0006
0007 #include <uapi/drm/drm_fourcc.h>
0008 #include <drm/drm_framebuffer.h>
0009
0010 #include "msm_media_info.h"
0011 #include "dpu_kms.h"
0012 #include "dpu_formats.h"
0013
0014 #define DPU_UBWC_META_MACRO_W_H 16
0015 #define DPU_UBWC_META_BLOCK_SIZE 256
0016 #define DPU_UBWC_PLANE_SIZE_ALIGNMENT 4096
0017
0018 #define DPU_TILE_HEIGHT_DEFAULT 1
0019 #define DPU_TILE_HEIGHT_TILED 4
0020 #define DPU_TILE_HEIGHT_UBWC 4
0021 #define DPU_TILE_HEIGHT_NV12 8
0022
0023 #define DPU_MAX_IMG_WIDTH 0x3FFF
0024 #define DPU_MAX_IMG_HEIGHT 0x3FFF
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034 #define INTERLEAVED_RGB_FMT(fmt, a, r, g, b, e0, e1, e2, e3, uc, alpha, \
0035 bp, flg, fm, np) \
0036 { \
0037 .base.pixel_format = DRM_FORMAT_ ## fmt, \
0038 .fetch_planes = DPU_PLANE_INTERLEAVED, \
0039 .alpha_enable = alpha, \
0040 .element = { (e0), (e1), (e2), (e3) }, \
0041 .bits = { g, b, r, a }, \
0042 .chroma_sample = DPU_CHROMA_RGB, \
0043 .unpack_align_msb = 0, \
0044 .unpack_tight = 1, \
0045 .unpack_count = uc, \
0046 .bpp = bp, \
0047 .fetch_mode = fm, \
0048 .flag = {(flg)}, \
0049 .num_planes = np, \
0050 .tile_height = DPU_TILE_HEIGHT_DEFAULT \
0051 }
0052
0053 #define INTERLEAVED_RGB_FMT_TILED(fmt, a, r, g, b, e0, e1, e2, e3, uc, \
0054 alpha, bp, flg, fm, np, th) \
0055 { \
0056 .base.pixel_format = DRM_FORMAT_ ## fmt, \
0057 .fetch_planes = DPU_PLANE_INTERLEAVED, \
0058 .alpha_enable = alpha, \
0059 .element = { (e0), (e1), (e2), (e3) }, \
0060 .bits = { g, b, r, a }, \
0061 .chroma_sample = DPU_CHROMA_RGB, \
0062 .unpack_align_msb = 0, \
0063 .unpack_tight = 1, \
0064 .unpack_count = uc, \
0065 .bpp = bp, \
0066 .fetch_mode = fm, \
0067 .flag = {(flg)}, \
0068 .num_planes = np, \
0069 .tile_height = th \
0070 }
0071
0072
0073 #define INTERLEAVED_YUV_FMT(fmt, a, r, g, b, e0, e1, e2, e3, \
0074 alpha, chroma, count, bp, flg, fm, np) \
0075 { \
0076 .base.pixel_format = DRM_FORMAT_ ## fmt, \
0077 .fetch_planes = DPU_PLANE_INTERLEAVED, \
0078 .alpha_enable = alpha, \
0079 .element = { (e0), (e1), (e2), (e3)}, \
0080 .bits = { g, b, r, a }, \
0081 .chroma_sample = chroma, \
0082 .unpack_align_msb = 0, \
0083 .unpack_tight = 1, \
0084 .unpack_count = count, \
0085 .bpp = bp, \
0086 .fetch_mode = fm, \
0087 .flag = {(flg)}, \
0088 .num_planes = np, \
0089 .tile_height = DPU_TILE_HEIGHT_DEFAULT \
0090 }
0091
0092 #define PSEUDO_YUV_FMT(fmt, a, r, g, b, e0, e1, chroma, flg, fm, np) \
0093 { \
0094 .base.pixel_format = DRM_FORMAT_ ## fmt, \
0095 .fetch_planes = DPU_PLANE_PSEUDO_PLANAR, \
0096 .alpha_enable = false, \
0097 .element = { (e0), (e1), 0, 0 }, \
0098 .bits = { g, b, r, a }, \
0099 .chroma_sample = chroma, \
0100 .unpack_align_msb = 0, \
0101 .unpack_tight = 1, \
0102 .unpack_count = 2, \
0103 .bpp = 2, \
0104 .fetch_mode = fm, \
0105 .flag = {(flg)}, \
0106 .num_planes = np, \
0107 .tile_height = DPU_TILE_HEIGHT_DEFAULT \
0108 }
0109
0110 #define PSEUDO_YUV_FMT_TILED(fmt, a, r, g, b, e0, e1, chroma, \
0111 flg, fm, np, th) \
0112 { \
0113 .base.pixel_format = DRM_FORMAT_ ## fmt, \
0114 .fetch_planes = DPU_PLANE_PSEUDO_PLANAR, \
0115 .alpha_enable = false, \
0116 .element = { (e0), (e1), 0, 0 }, \
0117 .bits = { g, b, r, a }, \
0118 .chroma_sample = chroma, \
0119 .unpack_align_msb = 0, \
0120 .unpack_tight = 1, \
0121 .unpack_count = 2, \
0122 .bpp = 2, \
0123 .fetch_mode = fm, \
0124 .flag = {(flg)}, \
0125 .num_planes = np, \
0126 .tile_height = th \
0127 }
0128
0129 #define PSEUDO_YUV_FMT_LOOSE(fmt, a, r, g, b, e0, e1, chroma, flg, fm, np)\
0130 { \
0131 .base.pixel_format = DRM_FORMAT_ ## fmt, \
0132 .fetch_planes = DPU_PLANE_PSEUDO_PLANAR, \
0133 .alpha_enable = false, \
0134 .element = { (e0), (e1), 0, 0 }, \
0135 .bits = { g, b, r, a }, \
0136 .chroma_sample = chroma, \
0137 .unpack_align_msb = 1, \
0138 .unpack_tight = 0, \
0139 .unpack_count = 2, \
0140 .bpp = 2, \
0141 .fetch_mode = fm, \
0142 .flag = {(flg)}, \
0143 .num_planes = np, \
0144 .tile_height = DPU_TILE_HEIGHT_DEFAULT \
0145 }
0146
0147 #define PSEUDO_YUV_FMT_LOOSE_TILED(fmt, a, r, g, b, e0, e1, chroma, \
0148 flg, fm, np, th) \
0149 { \
0150 .base.pixel_format = DRM_FORMAT_ ## fmt, \
0151 .fetch_planes = DPU_PLANE_PSEUDO_PLANAR, \
0152 .alpha_enable = false, \
0153 .element = { (e0), (e1), 0, 0 }, \
0154 .bits = { g, b, r, a }, \
0155 .chroma_sample = chroma, \
0156 .unpack_align_msb = 1, \
0157 .unpack_tight = 0, \
0158 .unpack_count = 2, \
0159 .bpp = 2, \
0160 .fetch_mode = fm, \
0161 .flag = {(flg)}, \
0162 .num_planes = np, \
0163 .tile_height = th \
0164 }
0165
0166
0167 #define PLANAR_YUV_FMT(fmt, a, r, g, b, e0, e1, e2, alpha, chroma, bp, \
0168 flg, fm, np) \
0169 { \
0170 .base.pixel_format = DRM_FORMAT_ ## fmt, \
0171 .fetch_planes = DPU_PLANE_PLANAR, \
0172 .alpha_enable = alpha, \
0173 .element = { (e0), (e1), (e2), 0 }, \
0174 .bits = { g, b, r, a }, \
0175 .chroma_sample = chroma, \
0176 .unpack_align_msb = 0, \
0177 .unpack_tight = 1, \
0178 .unpack_count = 1, \
0179 .bpp = bp, \
0180 .fetch_mode = fm, \
0181 .flag = {(flg)}, \
0182 .num_planes = np, \
0183 .tile_height = DPU_TILE_HEIGHT_DEFAULT \
0184 }
0185
0186
0187
0188
0189
0190
0191 struct dpu_media_color_map {
0192 uint32_t format;
0193 uint32_t color;
0194 };
0195
0196 static const struct dpu_format dpu_format_map[] = {
0197 INTERLEAVED_RGB_FMT(ARGB8888,
0198 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
0199 C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA, 4,
0200 true, 4, 0,
0201 DPU_FETCH_LINEAR, 1),
0202
0203 INTERLEAVED_RGB_FMT(ABGR8888,
0204 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
0205 C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
0206 true, 4, 0,
0207 DPU_FETCH_LINEAR, 1),
0208
0209 INTERLEAVED_RGB_FMT(XBGR8888,
0210 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
0211 C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
0212 false, 4, 0,
0213 DPU_FETCH_LINEAR, 1),
0214
0215 INTERLEAVED_RGB_FMT(RGBA8888,
0216 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
0217 C3_ALPHA, C1_B_Cb, C0_G_Y, C2_R_Cr, 4,
0218 true, 4, 0,
0219 DPU_FETCH_LINEAR, 1),
0220
0221 INTERLEAVED_RGB_FMT(BGRA8888,
0222 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
0223 C3_ALPHA, C2_R_Cr, C0_G_Y, C1_B_Cb, 4,
0224 true, 4, 0,
0225 DPU_FETCH_LINEAR, 1),
0226
0227 INTERLEAVED_RGB_FMT(BGRX8888,
0228 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
0229 C3_ALPHA, C2_R_Cr, C0_G_Y, C1_B_Cb, 4,
0230 false, 4, 0,
0231 DPU_FETCH_LINEAR, 1),
0232
0233 INTERLEAVED_RGB_FMT(XRGB8888,
0234 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
0235 C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA, 4,
0236 false, 4, 0,
0237 DPU_FETCH_LINEAR, 1),
0238
0239 INTERLEAVED_RGB_FMT(RGBX8888,
0240 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
0241 C3_ALPHA, C1_B_Cb, C0_G_Y, C2_R_Cr, 4,
0242 false, 4, 0,
0243 DPU_FETCH_LINEAR, 1),
0244
0245 INTERLEAVED_RGB_FMT(RGB888,
0246 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
0247 C1_B_Cb, C0_G_Y, C2_R_Cr, 0, 3,
0248 false, 3, 0,
0249 DPU_FETCH_LINEAR, 1),
0250
0251 INTERLEAVED_RGB_FMT(BGR888,
0252 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
0253 C2_R_Cr, C0_G_Y, C1_B_Cb, 0, 3,
0254 false, 3, 0,
0255 DPU_FETCH_LINEAR, 1),
0256
0257 INTERLEAVED_RGB_FMT(RGB565,
0258 0, COLOR_5BIT, COLOR_6BIT, COLOR_5BIT,
0259 C1_B_Cb, C0_G_Y, C2_R_Cr, 0, 3,
0260 false, 2, 0,
0261 DPU_FETCH_LINEAR, 1),
0262
0263 INTERLEAVED_RGB_FMT(BGR565,
0264 0, COLOR_5BIT, COLOR_6BIT, COLOR_5BIT,
0265 C2_R_Cr, C0_G_Y, C1_B_Cb, 0, 3,
0266 false, 2, 0,
0267 DPU_FETCH_LINEAR, 1),
0268
0269 INTERLEAVED_RGB_FMT(ARGB1555,
0270 COLOR_ALPHA_1BIT, COLOR_5BIT, COLOR_5BIT, COLOR_5BIT,
0271 C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA, 4,
0272 true, 2, 0,
0273 DPU_FETCH_LINEAR, 1),
0274
0275 INTERLEAVED_RGB_FMT(ABGR1555,
0276 COLOR_ALPHA_1BIT, COLOR_5BIT, COLOR_5BIT, COLOR_5BIT,
0277 C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
0278 true, 2, 0,
0279 DPU_FETCH_LINEAR, 1),
0280
0281 INTERLEAVED_RGB_FMT(RGBA5551,
0282 COLOR_ALPHA_1BIT, COLOR_5BIT, COLOR_5BIT, COLOR_5BIT,
0283 C3_ALPHA, C1_B_Cb, C0_G_Y, C2_R_Cr, 4,
0284 true, 2, 0,
0285 DPU_FETCH_LINEAR, 1),
0286
0287 INTERLEAVED_RGB_FMT(BGRA5551,
0288 COLOR_ALPHA_1BIT, COLOR_5BIT, COLOR_5BIT, COLOR_5BIT,
0289 C3_ALPHA, C2_R_Cr, C0_G_Y, C1_B_Cb, 4,
0290 true, 2, 0,
0291 DPU_FETCH_LINEAR, 1),
0292
0293 INTERLEAVED_RGB_FMT(XRGB1555,
0294 COLOR_ALPHA_1BIT, COLOR_5BIT, COLOR_5BIT, COLOR_5BIT,
0295 C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA, 4,
0296 false, 2, 0,
0297 DPU_FETCH_LINEAR, 1),
0298
0299 INTERLEAVED_RGB_FMT(XBGR1555,
0300 COLOR_ALPHA_1BIT, COLOR_5BIT, COLOR_5BIT, COLOR_5BIT,
0301 C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
0302 false, 2, 0,
0303 DPU_FETCH_LINEAR, 1),
0304
0305 INTERLEAVED_RGB_FMT(RGBX5551,
0306 COLOR_ALPHA_1BIT, COLOR_5BIT, COLOR_5BIT, COLOR_5BIT,
0307 C3_ALPHA, C1_B_Cb, C0_G_Y, C2_R_Cr, 4,
0308 false, 2, 0,
0309 DPU_FETCH_LINEAR, 1),
0310
0311 INTERLEAVED_RGB_FMT(BGRX5551,
0312 COLOR_ALPHA_1BIT, COLOR_5BIT, COLOR_5BIT, COLOR_5BIT,
0313 C3_ALPHA, C2_R_Cr, C0_G_Y, C1_B_Cb, 4,
0314 false, 2, 0,
0315 DPU_FETCH_LINEAR, 1),
0316
0317 INTERLEAVED_RGB_FMT(ARGB4444,
0318 COLOR_ALPHA_4BIT, COLOR_4BIT, COLOR_4BIT, COLOR_4BIT,
0319 C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA, 4,
0320 true, 2, 0,
0321 DPU_FETCH_LINEAR, 1),
0322
0323 INTERLEAVED_RGB_FMT(ABGR4444,
0324 COLOR_ALPHA_4BIT, COLOR_4BIT, COLOR_4BIT, COLOR_4BIT,
0325 C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
0326 true, 2, 0,
0327 DPU_FETCH_LINEAR, 1),
0328
0329 INTERLEAVED_RGB_FMT(RGBA4444,
0330 COLOR_ALPHA_4BIT, COLOR_4BIT, COLOR_4BIT, COLOR_4BIT,
0331 C3_ALPHA, C1_B_Cb, C0_G_Y, C2_R_Cr, 4,
0332 true, 2, 0,
0333 DPU_FETCH_LINEAR, 1),
0334
0335 INTERLEAVED_RGB_FMT(BGRA4444,
0336 COLOR_ALPHA_4BIT, COLOR_4BIT, COLOR_4BIT, COLOR_4BIT,
0337 C3_ALPHA, C2_R_Cr, C0_G_Y, C1_B_Cb, 4,
0338 true, 2, 0,
0339 DPU_FETCH_LINEAR, 1),
0340
0341 INTERLEAVED_RGB_FMT(XRGB4444,
0342 COLOR_ALPHA_4BIT, COLOR_4BIT, COLOR_4BIT, COLOR_4BIT,
0343 C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA, 4,
0344 false, 2, 0,
0345 DPU_FETCH_LINEAR, 1),
0346
0347 INTERLEAVED_RGB_FMT(XBGR4444,
0348 COLOR_ALPHA_4BIT, COLOR_4BIT, COLOR_4BIT, COLOR_4BIT,
0349 C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
0350 false, 2, 0,
0351 DPU_FETCH_LINEAR, 1),
0352
0353 INTERLEAVED_RGB_FMT(RGBX4444,
0354 COLOR_ALPHA_4BIT, COLOR_4BIT, COLOR_4BIT, COLOR_4BIT,
0355 C3_ALPHA, C1_B_Cb, C0_G_Y, C2_R_Cr, 4,
0356 false, 2, 0,
0357 DPU_FETCH_LINEAR, 1),
0358
0359 INTERLEAVED_RGB_FMT(BGRX4444,
0360 COLOR_ALPHA_4BIT, COLOR_4BIT, COLOR_4BIT, COLOR_4BIT,
0361 C3_ALPHA, C2_R_Cr, C0_G_Y, C1_B_Cb, 4,
0362 false, 2, 0,
0363 DPU_FETCH_LINEAR, 1),
0364
0365 INTERLEAVED_RGB_FMT(BGRA1010102,
0366 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
0367 C3_ALPHA, C2_R_Cr, C0_G_Y, C1_B_Cb, 4,
0368 true, 4, DPU_FORMAT_FLAG_DX,
0369 DPU_FETCH_LINEAR, 1),
0370
0371 INTERLEAVED_RGB_FMT(RGBA1010102,
0372 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
0373 C3_ALPHA, C1_B_Cb, C0_G_Y, C2_R_Cr, 4,
0374 true, 4, DPU_FORMAT_FLAG_DX,
0375 DPU_FETCH_LINEAR, 1),
0376
0377 INTERLEAVED_RGB_FMT(ABGR2101010,
0378 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
0379 C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
0380 true, 4, DPU_FORMAT_FLAG_DX,
0381 DPU_FETCH_LINEAR, 1),
0382
0383 INTERLEAVED_RGB_FMT(ARGB2101010,
0384 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
0385 C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA, 4,
0386 true, 4, DPU_FORMAT_FLAG_DX,
0387 DPU_FETCH_LINEAR, 1),
0388
0389 INTERLEAVED_RGB_FMT(XRGB2101010,
0390 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
0391 C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA, 4,
0392 false, 4, DPU_FORMAT_FLAG_DX,
0393 DPU_FETCH_LINEAR, 1),
0394
0395 INTERLEAVED_RGB_FMT(BGRX1010102,
0396 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
0397 C3_ALPHA, C2_R_Cr, C0_G_Y, C1_B_Cb, 4,
0398 false, 4, DPU_FORMAT_FLAG_DX,
0399 DPU_FETCH_LINEAR, 1),
0400
0401 INTERLEAVED_RGB_FMT(XBGR2101010,
0402 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
0403 C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
0404 false, 4, DPU_FORMAT_FLAG_DX,
0405 DPU_FETCH_LINEAR, 1),
0406
0407 INTERLEAVED_RGB_FMT(RGBX1010102,
0408 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
0409 C3_ALPHA, C1_B_Cb, C0_G_Y, C2_R_Cr, 4,
0410 false, 4, DPU_FORMAT_FLAG_DX,
0411 DPU_FETCH_LINEAR, 1),
0412
0413 PSEUDO_YUV_FMT(NV12,
0414 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
0415 C1_B_Cb, C2_R_Cr,
0416 DPU_CHROMA_420, DPU_FORMAT_FLAG_YUV,
0417 DPU_FETCH_LINEAR, 2),
0418
0419 PSEUDO_YUV_FMT(NV21,
0420 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
0421 C2_R_Cr, C1_B_Cb,
0422 DPU_CHROMA_420, DPU_FORMAT_FLAG_YUV,
0423 DPU_FETCH_LINEAR, 2),
0424
0425 PSEUDO_YUV_FMT(NV16,
0426 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
0427 C1_B_Cb, C2_R_Cr,
0428 DPU_CHROMA_H2V1, DPU_FORMAT_FLAG_YUV,
0429 DPU_FETCH_LINEAR, 2),
0430
0431 PSEUDO_YUV_FMT(NV61,
0432 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
0433 C2_R_Cr, C1_B_Cb,
0434 DPU_CHROMA_H2V1, DPU_FORMAT_FLAG_YUV,
0435 DPU_FETCH_LINEAR, 2),
0436
0437 INTERLEAVED_YUV_FMT(VYUY,
0438 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
0439 C2_R_Cr, C0_G_Y, C1_B_Cb, C0_G_Y,
0440 false, DPU_CHROMA_H2V1, 4, 2, DPU_FORMAT_FLAG_YUV,
0441 DPU_FETCH_LINEAR, 2),
0442
0443 INTERLEAVED_YUV_FMT(UYVY,
0444 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
0445 C1_B_Cb, C0_G_Y, C2_R_Cr, C0_G_Y,
0446 false, DPU_CHROMA_H2V1, 4, 2, DPU_FORMAT_FLAG_YUV,
0447 DPU_FETCH_LINEAR, 2),
0448
0449 INTERLEAVED_YUV_FMT(YUYV,
0450 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
0451 C0_G_Y, C1_B_Cb, C0_G_Y, C2_R_Cr,
0452 false, DPU_CHROMA_H2V1, 4, 2, DPU_FORMAT_FLAG_YUV,
0453 DPU_FETCH_LINEAR, 2),
0454
0455 INTERLEAVED_YUV_FMT(YVYU,
0456 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
0457 C0_G_Y, C2_R_Cr, C0_G_Y, C1_B_Cb,
0458 false, DPU_CHROMA_H2V1, 4, 2, DPU_FORMAT_FLAG_YUV,
0459 DPU_FETCH_LINEAR, 2),
0460
0461 PLANAR_YUV_FMT(YUV420,
0462 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
0463 C2_R_Cr, C1_B_Cb, C0_G_Y,
0464 false, DPU_CHROMA_420, 1, DPU_FORMAT_FLAG_YUV,
0465 DPU_FETCH_LINEAR, 3),
0466
0467 PLANAR_YUV_FMT(YVU420,
0468 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
0469 C1_B_Cb, C2_R_Cr, C0_G_Y,
0470 false, DPU_CHROMA_420, 1, DPU_FORMAT_FLAG_YUV,
0471 DPU_FETCH_LINEAR, 3),
0472 };
0473
0474
0475
0476
0477
0478
0479
0480 static const struct dpu_format dpu_format_map_ubwc[] = {
0481 INTERLEAVED_RGB_FMT_TILED(BGR565,
0482 0, COLOR_5BIT, COLOR_6BIT, COLOR_5BIT,
0483 C2_R_Cr, C0_G_Y, C1_B_Cb, 0, 3,
0484 false, 2, DPU_FORMAT_FLAG_COMPRESSED,
0485 DPU_FETCH_UBWC, 2, DPU_TILE_HEIGHT_UBWC),
0486
0487 INTERLEAVED_RGB_FMT_TILED(ABGR8888,
0488 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
0489 C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
0490 true, 4, DPU_FORMAT_FLAG_COMPRESSED,
0491 DPU_FETCH_UBWC, 2, DPU_TILE_HEIGHT_UBWC),
0492
0493
0494
0495
0496
0497 INTERLEAVED_RGB_FMT_TILED(ARGB8888,
0498 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
0499 C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
0500 true, 4, DPU_FORMAT_FLAG_COMPRESSED,
0501 DPU_FETCH_UBWC, 2, DPU_TILE_HEIGHT_UBWC),
0502
0503 INTERLEAVED_RGB_FMT_TILED(XBGR8888,
0504 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
0505 C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
0506 false, 4, DPU_FORMAT_FLAG_COMPRESSED,
0507 DPU_FETCH_UBWC, 2, DPU_TILE_HEIGHT_UBWC),
0508
0509 INTERLEAVED_RGB_FMT_TILED(XRGB8888,
0510 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
0511 C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
0512 false, 4, DPU_FORMAT_FLAG_COMPRESSED,
0513 DPU_FETCH_UBWC, 2, DPU_TILE_HEIGHT_UBWC),
0514
0515 INTERLEAVED_RGB_FMT_TILED(ABGR2101010,
0516 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
0517 C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
0518 true, 4, DPU_FORMAT_FLAG_DX | DPU_FORMAT_FLAG_COMPRESSED,
0519 DPU_FETCH_UBWC, 2, DPU_TILE_HEIGHT_UBWC),
0520
0521 INTERLEAVED_RGB_FMT_TILED(XBGR2101010,
0522 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
0523 C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
0524 true, 4, DPU_FORMAT_FLAG_DX | DPU_FORMAT_FLAG_COMPRESSED,
0525 DPU_FETCH_UBWC, 2, DPU_TILE_HEIGHT_UBWC),
0526
0527 PSEUDO_YUV_FMT_TILED(NV12,
0528 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
0529 C1_B_Cb, C2_R_Cr,
0530 DPU_CHROMA_420, DPU_FORMAT_FLAG_YUV |
0531 DPU_FORMAT_FLAG_COMPRESSED,
0532 DPU_FETCH_UBWC, 4, DPU_TILE_HEIGHT_NV12),
0533 };
0534
0535
0536
0537
0538 static void _dpu_get_v_h_subsample_rate(
0539 enum dpu_chroma_samp_type chroma_sample,
0540 uint32_t *v_sample,
0541 uint32_t *h_sample)
0542 {
0543 if (!v_sample || !h_sample)
0544 return;
0545
0546 switch (chroma_sample) {
0547 case DPU_CHROMA_H2V1:
0548 *v_sample = 1;
0549 *h_sample = 2;
0550 break;
0551 case DPU_CHROMA_H1V2:
0552 *v_sample = 2;
0553 *h_sample = 1;
0554 break;
0555 case DPU_CHROMA_420:
0556 *v_sample = 2;
0557 *h_sample = 2;
0558 break;
0559 default:
0560 *v_sample = 1;
0561 *h_sample = 1;
0562 break;
0563 }
0564 }
0565
0566 static int _dpu_format_get_media_color_ubwc(const struct dpu_format *fmt)
0567 {
0568 static const struct dpu_media_color_map dpu_media_ubwc_map[] = {
0569 {DRM_FORMAT_ABGR8888, COLOR_FMT_RGBA8888_UBWC},
0570 {DRM_FORMAT_ARGB8888, COLOR_FMT_RGBA8888_UBWC},
0571 {DRM_FORMAT_XBGR8888, COLOR_FMT_RGBA8888_UBWC},
0572 {DRM_FORMAT_XRGB8888, COLOR_FMT_RGBA8888_UBWC},
0573 {DRM_FORMAT_ABGR2101010, COLOR_FMT_RGBA1010102_UBWC},
0574 {DRM_FORMAT_XBGR2101010, COLOR_FMT_RGBA1010102_UBWC},
0575 {DRM_FORMAT_BGR565, COLOR_FMT_RGB565_UBWC},
0576 };
0577 int color_fmt = -1;
0578 int i;
0579
0580 if (fmt->base.pixel_format == DRM_FORMAT_NV12) {
0581 if (DPU_FORMAT_IS_DX(fmt)) {
0582 if (fmt->unpack_tight)
0583 color_fmt = COLOR_FMT_NV12_BPP10_UBWC;
0584 else
0585 color_fmt = COLOR_FMT_P010_UBWC;
0586 } else
0587 color_fmt = COLOR_FMT_NV12_UBWC;
0588 return color_fmt;
0589 }
0590
0591 for (i = 0; i < ARRAY_SIZE(dpu_media_ubwc_map); ++i)
0592 if (fmt->base.pixel_format == dpu_media_ubwc_map[i].format) {
0593 color_fmt = dpu_media_ubwc_map[i].color;
0594 break;
0595 }
0596 return color_fmt;
0597 }
0598
0599 static int _dpu_format_get_plane_sizes_ubwc(
0600 const struct dpu_format *fmt,
0601 const uint32_t width,
0602 const uint32_t height,
0603 struct dpu_hw_fmt_layout *layout)
0604 {
0605 int i;
0606 int color;
0607 bool meta = DPU_FORMAT_IS_UBWC(fmt);
0608
0609 memset(layout, 0, sizeof(struct dpu_hw_fmt_layout));
0610 layout->format = fmt;
0611 layout->width = width;
0612 layout->height = height;
0613 layout->num_planes = fmt->num_planes;
0614
0615 color = _dpu_format_get_media_color_ubwc(fmt);
0616 if (color < 0) {
0617 DRM_ERROR("UBWC format not supported for fmt: %4.4s\n",
0618 (char *)&fmt->base.pixel_format);
0619 return -EINVAL;
0620 }
0621
0622 if (DPU_FORMAT_IS_YUV(layout->format)) {
0623 uint32_t y_sclines, uv_sclines;
0624 uint32_t y_meta_scanlines = 0;
0625 uint32_t uv_meta_scanlines = 0;
0626
0627 layout->num_planes = 2;
0628 layout->plane_pitch[0] = VENUS_Y_STRIDE(color, width);
0629 y_sclines = VENUS_Y_SCANLINES(color, height);
0630 layout->plane_size[0] = MSM_MEDIA_ALIGN(layout->plane_pitch[0] *
0631 y_sclines, DPU_UBWC_PLANE_SIZE_ALIGNMENT);
0632
0633 layout->plane_pitch[1] = VENUS_UV_STRIDE(color, width);
0634 uv_sclines = VENUS_UV_SCANLINES(color, height);
0635 layout->plane_size[1] = MSM_MEDIA_ALIGN(layout->plane_pitch[1] *
0636 uv_sclines, DPU_UBWC_PLANE_SIZE_ALIGNMENT);
0637
0638 if (!meta)
0639 goto done;
0640
0641 layout->num_planes += 2;
0642 layout->plane_pitch[2] = VENUS_Y_META_STRIDE(color, width);
0643 y_meta_scanlines = VENUS_Y_META_SCANLINES(color, height);
0644 layout->plane_size[2] = MSM_MEDIA_ALIGN(layout->plane_pitch[2] *
0645 y_meta_scanlines, DPU_UBWC_PLANE_SIZE_ALIGNMENT);
0646
0647 layout->plane_pitch[3] = VENUS_UV_META_STRIDE(color, width);
0648 uv_meta_scanlines = VENUS_UV_META_SCANLINES(color, height);
0649 layout->plane_size[3] = MSM_MEDIA_ALIGN(layout->plane_pitch[3] *
0650 uv_meta_scanlines, DPU_UBWC_PLANE_SIZE_ALIGNMENT);
0651
0652 } else {
0653 uint32_t rgb_scanlines, rgb_meta_scanlines;
0654
0655 layout->num_planes = 1;
0656
0657 layout->plane_pitch[0] = VENUS_RGB_STRIDE(color, width);
0658 rgb_scanlines = VENUS_RGB_SCANLINES(color, height);
0659 layout->plane_size[0] = MSM_MEDIA_ALIGN(layout->plane_pitch[0] *
0660 rgb_scanlines, DPU_UBWC_PLANE_SIZE_ALIGNMENT);
0661
0662 if (!meta)
0663 goto done;
0664 layout->num_planes += 2;
0665 layout->plane_pitch[2] = VENUS_RGB_META_STRIDE(color, width);
0666 rgb_meta_scanlines = VENUS_RGB_META_SCANLINES(color, height);
0667 layout->plane_size[2] = MSM_MEDIA_ALIGN(layout->plane_pitch[2] *
0668 rgb_meta_scanlines, DPU_UBWC_PLANE_SIZE_ALIGNMENT);
0669 }
0670
0671 done:
0672 for (i = 0; i < DPU_MAX_PLANES; i++)
0673 layout->total_size += layout->plane_size[i];
0674
0675 return 0;
0676 }
0677
0678 static int _dpu_format_get_plane_sizes_linear(
0679 const struct dpu_format *fmt,
0680 const uint32_t width,
0681 const uint32_t height,
0682 struct dpu_hw_fmt_layout *layout,
0683 const uint32_t *pitches)
0684 {
0685 int i;
0686
0687 memset(layout, 0, sizeof(struct dpu_hw_fmt_layout));
0688 layout->format = fmt;
0689 layout->width = width;
0690 layout->height = height;
0691 layout->num_planes = fmt->num_planes;
0692
0693
0694 if (fmt->fetch_planes == DPU_PLANE_INTERLEAVED) {
0695 layout->num_planes = 1;
0696 layout->plane_size[0] = width * height * layout->format->bpp;
0697 layout->plane_pitch[0] = width * layout->format->bpp;
0698 } else {
0699 uint32_t v_subsample, h_subsample;
0700 uint32_t chroma_samp;
0701 uint32_t bpp = 1;
0702
0703 chroma_samp = fmt->chroma_sample;
0704 _dpu_get_v_h_subsample_rate(chroma_samp, &v_subsample,
0705 &h_subsample);
0706
0707 if (width % h_subsample || height % v_subsample) {
0708 DRM_ERROR("mismatch in subsample vs dimensions\n");
0709 return -EINVAL;
0710 }
0711
0712 if ((fmt->base.pixel_format == DRM_FORMAT_NV12) &&
0713 (DPU_FORMAT_IS_DX(fmt)))
0714 bpp = 2;
0715 layout->plane_pitch[0] = width * bpp;
0716 layout->plane_pitch[1] = layout->plane_pitch[0] / h_subsample;
0717 layout->plane_size[0] = layout->plane_pitch[0] * height;
0718 layout->plane_size[1] = layout->plane_pitch[1] *
0719 (height / v_subsample);
0720
0721 if (fmt->fetch_planes == DPU_PLANE_PSEUDO_PLANAR) {
0722 layout->num_planes = 2;
0723 layout->plane_size[1] *= 2;
0724 layout->plane_pitch[1] *= 2;
0725 } else {
0726
0727 layout->num_planes = 3;
0728 layout->plane_size[2] = layout->plane_size[1];
0729 layout->plane_pitch[2] = layout->plane_pitch[1];
0730 }
0731 }
0732
0733
0734
0735
0736
0737
0738
0739 for (i = 0; i < layout->num_planes && i < DPU_MAX_PLANES; ++i) {
0740 if (pitches && layout->plane_pitch[i] < pitches[i])
0741 layout->plane_pitch[i] = pitches[i];
0742 }
0743
0744 for (i = 0; i < DPU_MAX_PLANES; i++)
0745 layout->total_size += layout->plane_size[i];
0746
0747 return 0;
0748 }
0749
0750 static int dpu_format_get_plane_sizes(
0751 const struct dpu_format *fmt,
0752 const uint32_t w,
0753 const uint32_t h,
0754 struct dpu_hw_fmt_layout *layout,
0755 const uint32_t *pitches)
0756 {
0757 if (!layout || !fmt) {
0758 DRM_ERROR("invalid pointer\n");
0759 return -EINVAL;
0760 }
0761
0762 if ((w > DPU_MAX_IMG_WIDTH) || (h > DPU_MAX_IMG_HEIGHT)) {
0763 DRM_ERROR("image dimensions outside max range\n");
0764 return -ERANGE;
0765 }
0766
0767 if (DPU_FORMAT_IS_UBWC(fmt) || DPU_FORMAT_IS_TILE(fmt))
0768 return _dpu_format_get_plane_sizes_ubwc(fmt, w, h, layout);
0769
0770 return _dpu_format_get_plane_sizes_linear(fmt, w, h, layout, pitches);
0771 }
0772
0773 static int _dpu_format_populate_addrs_ubwc(
0774 struct msm_gem_address_space *aspace,
0775 struct drm_framebuffer *fb,
0776 struct dpu_hw_fmt_layout *layout)
0777 {
0778 uint32_t base_addr = 0;
0779 bool meta;
0780
0781 if (!fb || !layout) {
0782 DRM_ERROR("invalid pointers\n");
0783 return -EINVAL;
0784 }
0785
0786 if (aspace)
0787 base_addr = msm_framebuffer_iova(fb, aspace, 0);
0788 if (!base_addr) {
0789 DRM_ERROR("failed to retrieve base addr\n");
0790 return -EFAULT;
0791 }
0792
0793 meta = DPU_FORMAT_IS_UBWC(layout->format);
0794
0795
0796 if (DPU_FORMAT_IS_YUV(layout->format)) {
0797
0798
0799
0800
0801
0802
0803
0804
0805
0806
0807
0808
0809
0810
0811
0812
0813
0814
0815
0816
0817
0818 layout->plane_addr[0] = base_addr + layout->plane_size[2];
0819
0820
0821 layout->plane_addr[1] = base_addr + layout->plane_size[0]
0822 + layout->plane_size[2] + layout->plane_size[3];
0823
0824 if (!meta)
0825 return 0;
0826
0827
0828 layout->plane_addr[2] = base_addr;
0829
0830
0831 layout->plane_addr[3] = base_addr + layout->plane_size[0]
0832 + layout->plane_size[2];
0833
0834 } else {
0835
0836
0837
0838
0839
0840
0841
0842
0843
0844
0845
0846
0847
0848
0849
0850
0851
0852 layout->plane_addr[0] = base_addr + layout->plane_size[2];
0853 layout->plane_addr[1] = 0;
0854
0855 if (!meta)
0856 return 0;
0857
0858 layout->plane_addr[2] = base_addr;
0859 layout->plane_addr[3] = 0;
0860 }
0861 return 0;
0862 }
0863
0864 static int _dpu_format_populate_addrs_linear(
0865 struct msm_gem_address_space *aspace,
0866 struct drm_framebuffer *fb,
0867 struct dpu_hw_fmt_layout *layout)
0868 {
0869 unsigned int i;
0870
0871
0872 for (i = 0; i < layout->num_planes; ++i) {
0873 if (layout->plane_pitch[i] > fb->pitches[i]) {
0874 DRM_ERROR("plane %u expected pitch %u, fb %u\n",
0875 i, layout->plane_pitch[i], fb->pitches[i]);
0876 return -EINVAL;
0877 }
0878 }
0879
0880
0881 for (i = 0; i < layout->num_planes; ++i) {
0882 if (aspace)
0883 layout->plane_addr[i] =
0884 msm_framebuffer_iova(fb, aspace, i);
0885 if (!layout->plane_addr[i]) {
0886 DRM_ERROR("failed to retrieve base addr\n");
0887 return -EFAULT;
0888 }
0889 }
0890
0891 return 0;
0892 }
0893
0894 int dpu_format_populate_layout(
0895 struct msm_gem_address_space *aspace,
0896 struct drm_framebuffer *fb,
0897 struct dpu_hw_fmt_layout *layout)
0898 {
0899 uint32_t plane_addr[DPU_MAX_PLANES];
0900 int i, ret;
0901
0902 if (!fb || !layout) {
0903 DRM_ERROR("invalid arguments\n");
0904 return -EINVAL;
0905 }
0906
0907 if ((fb->width > DPU_MAX_IMG_WIDTH) ||
0908 (fb->height > DPU_MAX_IMG_HEIGHT)) {
0909 DRM_ERROR("image dimensions outside max range\n");
0910 return -ERANGE;
0911 }
0912
0913 layout->format = to_dpu_format(msm_framebuffer_format(fb));
0914
0915
0916 ret = dpu_format_get_plane_sizes(layout->format, fb->width, fb->height,
0917 layout, fb->pitches);
0918 if (ret)
0919 return ret;
0920
0921 for (i = 0; i < DPU_MAX_PLANES; ++i)
0922 plane_addr[i] = layout->plane_addr[i];
0923
0924
0925 if (DPU_FORMAT_IS_UBWC(layout->format) ||
0926 DPU_FORMAT_IS_TILE(layout->format))
0927 ret = _dpu_format_populate_addrs_ubwc(aspace, fb, layout);
0928 else
0929 ret = _dpu_format_populate_addrs_linear(aspace, fb, layout);
0930
0931
0932 if (!ret && !memcmp(plane_addr, layout->plane_addr, sizeof(plane_addr)))
0933 ret = -EAGAIN;
0934
0935 return ret;
0936 }
0937
0938 int dpu_format_check_modified_format(
0939 const struct msm_kms *kms,
0940 const struct msm_format *msm_fmt,
0941 const struct drm_mode_fb_cmd2 *cmd,
0942 struct drm_gem_object **bos)
0943 {
0944 const struct drm_format_info *info;
0945 const struct dpu_format *fmt;
0946 struct dpu_hw_fmt_layout layout;
0947 uint32_t bos_total_size = 0;
0948 int ret, i;
0949
0950 if (!msm_fmt || !cmd || !bos) {
0951 DRM_ERROR("invalid arguments\n");
0952 return -EINVAL;
0953 }
0954
0955 fmt = to_dpu_format(msm_fmt);
0956 info = drm_format_info(fmt->base.pixel_format);
0957 if (!info)
0958 return -EINVAL;
0959
0960 ret = dpu_format_get_plane_sizes(fmt, cmd->width, cmd->height,
0961 &layout, cmd->pitches);
0962 if (ret)
0963 return ret;
0964
0965 for (i = 0; i < info->num_planes; i++) {
0966 if (!bos[i]) {
0967 DRM_ERROR("invalid handle for plane %d\n", i);
0968 return -EINVAL;
0969 }
0970 if ((i == 0) || (bos[i] != bos[0]))
0971 bos_total_size += bos[i]->size;
0972 }
0973
0974 if (bos_total_size < layout.total_size) {
0975 DRM_ERROR("buffers total size too small %u expected %u\n",
0976 bos_total_size, layout.total_size);
0977 return -EINVAL;
0978 }
0979
0980 return 0;
0981 }
0982
0983 const struct dpu_format *dpu_get_dpu_format_ext(
0984 const uint32_t format,
0985 const uint64_t modifier)
0986 {
0987 uint32_t i = 0;
0988 const struct dpu_format *fmt = NULL;
0989 const struct dpu_format *map = NULL;
0990 ssize_t map_size = 0;
0991
0992
0993
0994
0995
0996 DRM_DEBUG_ATOMIC("plane format modifier 0x%llX\n", modifier);
0997
0998 switch (modifier) {
0999 case 0:
1000 map = dpu_format_map;
1001 map_size = ARRAY_SIZE(dpu_format_map);
1002 break;
1003 case DRM_FORMAT_MOD_QCOM_COMPRESSED:
1004 map = dpu_format_map_ubwc;
1005 map_size = ARRAY_SIZE(dpu_format_map_ubwc);
1006 DRM_DEBUG_ATOMIC("found fmt: %4.4s DRM_FORMAT_MOD_QCOM_COMPRESSED\n",
1007 (char *)&format);
1008 break;
1009 default:
1010 DPU_ERROR("unsupported format modifier %llX\n", modifier);
1011 return NULL;
1012 }
1013
1014 for (i = 0; i < map_size; i++) {
1015 if (format == map[i].base.pixel_format) {
1016 fmt = &map[i];
1017 break;
1018 }
1019 }
1020
1021 if (fmt == NULL)
1022 DPU_ERROR("unsupported fmt: %4.4s modifier 0x%llX\n",
1023 (char *)&format, modifier);
1024 else
1025 DRM_DEBUG_ATOMIC("fmt %4.4s mod 0x%llX ubwc %d yuv %d\n",
1026 (char *)&format, modifier,
1027 DPU_FORMAT_IS_UBWC(fmt),
1028 DPU_FORMAT_IS_YUV(fmt));
1029
1030 return fmt;
1031 }
1032
1033 const struct msm_format *dpu_get_msm_format(
1034 struct msm_kms *kms,
1035 const uint32_t format,
1036 const uint64_t modifiers)
1037 {
1038 const struct dpu_format *fmt = dpu_get_dpu_format_ext(format,
1039 modifiers);
1040 if (fmt)
1041 return &fmt->base;
1042 return NULL;
1043 }