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