1 /* Copyright (c) 2015-2018, 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 13 #define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__ 14 15 #include <uapi/drm/drm_fourcc.h> 16 17 #include "msm_media_info.h" 18 #include "dpu_kms.h" 19 #include "dpu_formats.h" 20 21 #define DPU_UBWC_META_MACRO_W_H 16 22 #define DPU_UBWC_META_BLOCK_SIZE 256 23 #define DPU_UBWC_PLANE_SIZE_ALIGNMENT 4096 24 25 #define DPU_TILE_HEIGHT_DEFAULT 1 26 #define DPU_TILE_HEIGHT_TILED 4 27 #define DPU_TILE_HEIGHT_UBWC 4 28 #define DPU_TILE_HEIGHT_NV12 8 29 30 #define DPU_MAX_IMG_WIDTH 0x3FFF 31 #define DPU_MAX_IMG_HEIGHT 0x3FFF 32 33 /** 34 * DPU supported format packing, bpp, and other format 35 * information. 36 * DPU currently only supports interleaved RGB formats 37 * UBWC support for a pixel format is indicated by the flag, 38 * there is additional meta data plane for such formats 39 */ 40 41 #define INTERLEAVED_RGB_FMT(fmt, a, r, g, b, e0, e1, e2, e3, uc, alpha, \ 42 bp, flg, fm, np) \ 43 { \ 44 .base.pixel_format = DRM_FORMAT_ ## fmt, \ 45 .fetch_planes = DPU_PLANE_INTERLEAVED, \ 46 .alpha_enable = alpha, \ 47 .element = { (e0), (e1), (e2), (e3) }, \ 48 .bits = { g, b, r, a }, \ 49 .chroma_sample = DPU_CHROMA_RGB, \ 50 .unpack_align_msb = 0, \ 51 .unpack_tight = 1, \ 52 .unpack_count = uc, \ 53 .bpp = bp, \ 54 .fetch_mode = fm, \ 55 .flag = {(flg)}, \ 56 .num_planes = np, \ 57 .tile_height = DPU_TILE_HEIGHT_DEFAULT \ 58 } 59 60 #define INTERLEAVED_RGB_FMT_TILED(fmt, a, r, g, b, e0, e1, e2, e3, uc, \ 61 alpha, bp, flg, fm, np, th) \ 62 { \ 63 .base.pixel_format = DRM_FORMAT_ ## fmt, \ 64 .fetch_planes = DPU_PLANE_INTERLEAVED, \ 65 .alpha_enable = alpha, \ 66 .element = { (e0), (e1), (e2), (e3) }, \ 67 .bits = { g, b, r, a }, \ 68 .chroma_sample = DPU_CHROMA_RGB, \ 69 .unpack_align_msb = 0, \ 70 .unpack_tight = 1, \ 71 .unpack_count = uc, \ 72 .bpp = bp, \ 73 .fetch_mode = fm, \ 74 .flag = {(flg)}, \ 75 .num_planes = np, \ 76 .tile_height = th \ 77 } 78 79 80 #define INTERLEAVED_YUV_FMT(fmt, a, r, g, b, e0, e1, e2, e3, \ 81 alpha, chroma, count, bp, flg, fm, np) \ 82 { \ 83 .base.pixel_format = DRM_FORMAT_ ## fmt, \ 84 .fetch_planes = DPU_PLANE_INTERLEAVED, \ 85 .alpha_enable = alpha, \ 86 .element = { (e0), (e1), (e2), (e3)}, \ 87 .bits = { g, b, r, a }, \ 88 .chroma_sample = chroma, \ 89 .unpack_align_msb = 0, \ 90 .unpack_tight = 1, \ 91 .unpack_count = count, \ 92 .bpp = bp, \ 93 .fetch_mode = fm, \ 94 .flag = {(flg)}, \ 95 .num_planes = np, \ 96 .tile_height = DPU_TILE_HEIGHT_DEFAULT \ 97 } 98 99 #define PSEUDO_YUV_FMT(fmt, a, r, g, b, e0, e1, chroma, flg, fm, np) \ 100 { \ 101 .base.pixel_format = DRM_FORMAT_ ## fmt, \ 102 .fetch_planes = DPU_PLANE_PSEUDO_PLANAR, \ 103 .alpha_enable = false, \ 104 .element = { (e0), (e1), 0, 0 }, \ 105 .bits = { g, b, r, a }, \ 106 .chroma_sample = chroma, \ 107 .unpack_align_msb = 0, \ 108 .unpack_tight = 1, \ 109 .unpack_count = 2, \ 110 .bpp = 2, \ 111 .fetch_mode = fm, \ 112 .flag = {(flg)}, \ 113 .num_planes = np, \ 114 .tile_height = DPU_TILE_HEIGHT_DEFAULT \ 115 } 116 117 #define PSEUDO_YUV_FMT_TILED(fmt, a, r, g, b, e0, e1, chroma, \ 118 flg, fm, np, th) \ 119 { \ 120 .base.pixel_format = DRM_FORMAT_ ## fmt, \ 121 .fetch_planes = DPU_PLANE_PSEUDO_PLANAR, \ 122 .alpha_enable = false, \ 123 .element = { (e0), (e1), 0, 0 }, \ 124 .bits = { g, b, r, a }, \ 125 .chroma_sample = chroma, \ 126 .unpack_align_msb = 0, \ 127 .unpack_tight = 1, \ 128 .unpack_count = 2, \ 129 .bpp = 2, \ 130 .fetch_mode = fm, \ 131 .flag = {(flg)}, \ 132 .num_planes = np, \ 133 .tile_height = th \ 134 } 135 136 #define PSEUDO_YUV_FMT_LOOSE(fmt, a, r, g, b, e0, e1, chroma, flg, fm, np)\ 137 { \ 138 .base.pixel_format = DRM_FORMAT_ ## fmt, \ 139 .fetch_planes = DPU_PLANE_PSEUDO_PLANAR, \ 140 .alpha_enable = false, \ 141 .element = { (e0), (e1), 0, 0 }, \ 142 .bits = { g, b, r, a }, \ 143 .chroma_sample = chroma, \ 144 .unpack_align_msb = 1, \ 145 .unpack_tight = 0, \ 146 .unpack_count = 2, \ 147 .bpp = 2, \ 148 .fetch_mode = fm, \ 149 .flag = {(flg)}, \ 150 .num_planes = np, \ 151 .tile_height = DPU_TILE_HEIGHT_DEFAULT \ 152 } 153 154 #define PSEUDO_YUV_FMT_LOOSE_TILED(fmt, a, r, g, b, e0, e1, chroma, \ 155 flg, fm, np, th) \ 156 { \ 157 .base.pixel_format = DRM_FORMAT_ ## fmt, \ 158 .fetch_planes = DPU_PLANE_PSEUDO_PLANAR, \ 159 .alpha_enable = false, \ 160 .element = { (e0), (e1), 0, 0 }, \ 161 .bits = { g, b, r, a }, \ 162 .chroma_sample = chroma, \ 163 .unpack_align_msb = 1, \ 164 .unpack_tight = 0, \ 165 .unpack_count = 2, \ 166 .bpp = 2, \ 167 .fetch_mode = fm, \ 168 .flag = {(flg)}, \ 169 .num_planes = np, \ 170 .tile_height = th \ 171 } 172 173 174 #define PLANAR_YUV_FMT(fmt, a, r, g, b, e0, e1, e2, alpha, chroma, bp, \ 175 flg, fm, np) \ 176 { \ 177 .base.pixel_format = DRM_FORMAT_ ## fmt, \ 178 .fetch_planes = DPU_PLANE_PLANAR, \ 179 .alpha_enable = alpha, \ 180 .element = { (e0), (e1), (e2), 0 }, \ 181 .bits = { g, b, r, a }, \ 182 .chroma_sample = chroma, \ 183 .unpack_align_msb = 0, \ 184 .unpack_tight = 1, \ 185 .unpack_count = 1, \ 186 .bpp = bp, \ 187 .fetch_mode = fm, \ 188 .flag = {(flg)}, \ 189 .num_planes = np, \ 190 .tile_height = DPU_TILE_HEIGHT_DEFAULT \ 191 } 192 193 /* 194 * struct dpu_media_color_map - maps drm format to media format 195 * @format: DRM base pixel format 196 * @color: Media API color related to DRM format 197 */ 198 struct dpu_media_color_map { 199 uint32_t format; 200 uint32_t color; 201 }; 202 203 static const struct dpu_format dpu_format_map[] = { 204 INTERLEAVED_RGB_FMT(ARGB8888, 205 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, 206 C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA, 4, 207 true, 4, 0, 208 DPU_FETCH_LINEAR, 1), 209 210 INTERLEAVED_RGB_FMT(ABGR8888, 211 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, 212 C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4, 213 true, 4, 0, 214 DPU_FETCH_LINEAR, 1), 215 216 INTERLEAVED_RGB_FMT(XBGR8888, 217 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, 218 C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4, 219 false, 4, 0, 220 DPU_FETCH_LINEAR, 1), 221 222 INTERLEAVED_RGB_FMT(RGBA8888, 223 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, 224 C3_ALPHA, C1_B_Cb, C0_G_Y, C2_R_Cr, 4, 225 true, 4, 0, 226 DPU_FETCH_LINEAR, 1), 227 228 INTERLEAVED_RGB_FMT(BGRA8888, 229 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, 230 C3_ALPHA, C2_R_Cr, C0_G_Y, C1_B_Cb, 4, 231 true, 4, 0, 232 DPU_FETCH_LINEAR, 1), 233 234 INTERLEAVED_RGB_FMT(BGRX8888, 235 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, 236 C3_ALPHA, C2_R_Cr, C0_G_Y, C1_B_Cb, 4, 237 false, 4, 0, 238 DPU_FETCH_LINEAR, 1), 239 240 INTERLEAVED_RGB_FMT(XRGB8888, 241 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, 242 C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA, 4, 243 false, 4, 0, 244 DPU_FETCH_LINEAR, 1), 245 246 INTERLEAVED_RGB_FMT(RGBX8888, 247 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, 248 C3_ALPHA, C1_B_Cb, C0_G_Y, C2_R_Cr, 4, 249 false, 4, 0, 250 DPU_FETCH_LINEAR, 1), 251 252 INTERLEAVED_RGB_FMT(RGB888, 253 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, 254 C1_B_Cb, C0_G_Y, C2_R_Cr, 0, 3, 255 false, 3, 0, 256 DPU_FETCH_LINEAR, 1), 257 258 INTERLEAVED_RGB_FMT(BGR888, 259 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, 260 C2_R_Cr, C0_G_Y, C1_B_Cb, 0, 3, 261 false, 3, 0, 262 DPU_FETCH_LINEAR, 1), 263 264 INTERLEAVED_RGB_FMT(RGB565, 265 0, COLOR_5BIT, COLOR_6BIT, COLOR_5BIT, 266 C1_B_Cb, C0_G_Y, C2_R_Cr, 0, 3, 267 false, 2, 0, 268 DPU_FETCH_LINEAR, 1), 269 270 INTERLEAVED_RGB_FMT(BGR565, 271 0, COLOR_5BIT, COLOR_6BIT, COLOR_5BIT, 272 C2_R_Cr, C0_G_Y, C1_B_Cb, 0, 3, 273 false, 2, 0, 274 DPU_FETCH_LINEAR, 1), 275 276 INTERLEAVED_RGB_FMT(ARGB1555, 277 COLOR_ALPHA_1BIT, COLOR_5BIT, COLOR_5BIT, COLOR_5BIT, 278 C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA, 4, 279 true, 2, 0, 280 DPU_FETCH_LINEAR, 1), 281 282 INTERLEAVED_RGB_FMT(ABGR1555, 283 COLOR_ALPHA_1BIT, COLOR_5BIT, COLOR_5BIT, COLOR_5BIT, 284 C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4, 285 true, 2, 0, 286 DPU_FETCH_LINEAR, 1), 287 288 INTERLEAVED_RGB_FMT(RGBA5551, 289 COLOR_ALPHA_1BIT, COLOR_5BIT, COLOR_5BIT, COLOR_5BIT, 290 C3_ALPHA, C1_B_Cb, C0_G_Y, C2_R_Cr, 4, 291 true, 2, 0, 292 DPU_FETCH_LINEAR, 1), 293 294 INTERLEAVED_RGB_FMT(BGRA5551, 295 COLOR_ALPHA_1BIT, COLOR_5BIT, COLOR_5BIT, COLOR_5BIT, 296 C3_ALPHA, C2_R_Cr, C0_G_Y, C1_B_Cb, 4, 297 true, 2, 0, 298 DPU_FETCH_LINEAR, 1), 299 300 INTERLEAVED_RGB_FMT(XRGB1555, 301 COLOR_ALPHA_1BIT, COLOR_5BIT, COLOR_5BIT, COLOR_5BIT, 302 C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA, 4, 303 false, 2, 0, 304 DPU_FETCH_LINEAR, 1), 305 306 INTERLEAVED_RGB_FMT(XBGR1555, 307 COLOR_ALPHA_1BIT, COLOR_5BIT, COLOR_5BIT, COLOR_5BIT, 308 C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4, 309 false, 2, 0, 310 DPU_FETCH_LINEAR, 1), 311 312 INTERLEAVED_RGB_FMT(RGBX5551, 313 COLOR_ALPHA_1BIT, COLOR_5BIT, COLOR_5BIT, COLOR_5BIT, 314 C3_ALPHA, C1_B_Cb, C0_G_Y, C2_R_Cr, 4, 315 false, 2, 0, 316 DPU_FETCH_LINEAR, 1), 317 318 INTERLEAVED_RGB_FMT(BGRX5551, 319 COLOR_ALPHA_1BIT, COLOR_5BIT, COLOR_5BIT, COLOR_5BIT, 320 C3_ALPHA, C2_R_Cr, C0_G_Y, C1_B_Cb, 4, 321 false, 2, 0, 322 DPU_FETCH_LINEAR, 1), 323 324 INTERLEAVED_RGB_FMT(ARGB4444, 325 COLOR_ALPHA_4BIT, COLOR_4BIT, COLOR_4BIT, COLOR_4BIT, 326 C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA, 4, 327 true, 2, 0, 328 DPU_FETCH_LINEAR, 1), 329 330 INTERLEAVED_RGB_FMT(ABGR4444, 331 COLOR_ALPHA_4BIT, COLOR_4BIT, COLOR_4BIT, COLOR_4BIT, 332 C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4, 333 true, 2, 0, 334 DPU_FETCH_LINEAR, 1), 335 336 INTERLEAVED_RGB_FMT(RGBA4444, 337 COLOR_ALPHA_4BIT, COLOR_4BIT, COLOR_4BIT, COLOR_4BIT, 338 C3_ALPHA, C1_B_Cb, C0_G_Y, C2_R_Cr, 4, 339 true, 2, 0, 340 DPU_FETCH_LINEAR, 1), 341 342 INTERLEAVED_RGB_FMT(BGRA4444, 343 COLOR_ALPHA_4BIT, COLOR_4BIT, COLOR_4BIT, COLOR_4BIT, 344 C3_ALPHA, C2_R_Cr, C0_G_Y, C1_B_Cb, 4, 345 true, 2, 0, 346 DPU_FETCH_LINEAR, 1), 347 348 INTERLEAVED_RGB_FMT(XRGB4444, 349 COLOR_ALPHA_4BIT, COLOR_4BIT, COLOR_4BIT, COLOR_4BIT, 350 C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA, 4, 351 false, 2, 0, 352 DPU_FETCH_LINEAR, 1), 353 354 INTERLEAVED_RGB_FMT(XBGR4444, 355 COLOR_ALPHA_4BIT, COLOR_4BIT, COLOR_4BIT, COLOR_4BIT, 356 C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4, 357 false, 2, 0, 358 DPU_FETCH_LINEAR, 1), 359 360 INTERLEAVED_RGB_FMT(RGBX4444, 361 COLOR_ALPHA_4BIT, COLOR_4BIT, COLOR_4BIT, COLOR_4BIT, 362 C3_ALPHA, C1_B_Cb, C0_G_Y, C2_R_Cr, 4, 363 false, 2, 0, 364 DPU_FETCH_LINEAR, 1), 365 366 INTERLEAVED_RGB_FMT(BGRX4444, 367 COLOR_ALPHA_4BIT, COLOR_4BIT, COLOR_4BIT, COLOR_4BIT, 368 C3_ALPHA, C2_R_Cr, C0_G_Y, C1_B_Cb, 4, 369 false, 2, 0, 370 DPU_FETCH_LINEAR, 1), 371 372 INTERLEAVED_RGB_FMT(BGRA1010102, 373 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, 374 C3_ALPHA, C2_R_Cr, C0_G_Y, C1_B_Cb, 4, 375 true, 4, DPU_FORMAT_FLAG_DX, 376 DPU_FETCH_LINEAR, 1), 377 378 INTERLEAVED_RGB_FMT(RGBA1010102, 379 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, 380 C3_ALPHA, C1_B_Cb, C0_G_Y, C2_R_Cr, 4, 381 true, 4, DPU_FORMAT_FLAG_DX, 382 DPU_FETCH_LINEAR, 1), 383 384 INTERLEAVED_RGB_FMT(ABGR2101010, 385 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, 386 C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4, 387 true, 4, DPU_FORMAT_FLAG_DX, 388 DPU_FETCH_LINEAR, 1), 389 390 INTERLEAVED_RGB_FMT(ARGB2101010, 391 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, 392 C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA, 4, 393 true, 4, DPU_FORMAT_FLAG_DX, 394 DPU_FETCH_LINEAR, 1), 395 396 INTERLEAVED_RGB_FMT(XRGB2101010, 397 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, 398 C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA, 4, 399 false, 4, DPU_FORMAT_FLAG_DX, 400 DPU_FETCH_LINEAR, 1), 401 402 INTERLEAVED_RGB_FMT(BGRX1010102, 403 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, 404 C3_ALPHA, C2_R_Cr, C0_G_Y, C1_B_Cb, 4, 405 false, 4, DPU_FORMAT_FLAG_DX, 406 DPU_FETCH_LINEAR, 1), 407 408 INTERLEAVED_RGB_FMT(XBGR2101010, 409 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, 410 C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4, 411 false, 4, DPU_FORMAT_FLAG_DX, 412 DPU_FETCH_LINEAR, 1), 413 414 INTERLEAVED_RGB_FMT(RGBX1010102, 415 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, 416 C3_ALPHA, C1_B_Cb, C0_G_Y, C2_R_Cr, 4, 417 false, 4, DPU_FORMAT_FLAG_DX, 418 DPU_FETCH_LINEAR, 1), 419 420 PSEUDO_YUV_FMT(NV12, 421 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, 422 C1_B_Cb, C2_R_Cr, 423 DPU_CHROMA_420, DPU_FORMAT_FLAG_YUV, 424 DPU_FETCH_LINEAR, 2), 425 426 PSEUDO_YUV_FMT(NV21, 427 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, 428 C2_R_Cr, C1_B_Cb, 429 DPU_CHROMA_420, DPU_FORMAT_FLAG_YUV, 430 DPU_FETCH_LINEAR, 2), 431 432 PSEUDO_YUV_FMT(NV16, 433 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, 434 C1_B_Cb, C2_R_Cr, 435 DPU_CHROMA_H2V1, DPU_FORMAT_FLAG_YUV, 436 DPU_FETCH_LINEAR, 2), 437 438 PSEUDO_YUV_FMT(NV61, 439 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, 440 C2_R_Cr, C1_B_Cb, 441 DPU_CHROMA_H2V1, DPU_FORMAT_FLAG_YUV, 442 DPU_FETCH_LINEAR, 2), 443 444 INTERLEAVED_YUV_FMT(VYUY, 445 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, 446 C2_R_Cr, C0_G_Y, C1_B_Cb, C0_G_Y, 447 false, DPU_CHROMA_H2V1, 4, 2, DPU_FORMAT_FLAG_YUV, 448 DPU_FETCH_LINEAR, 2), 449 450 INTERLEAVED_YUV_FMT(UYVY, 451 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, 452 C1_B_Cb, C0_G_Y, C2_R_Cr, C0_G_Y, 453 false, DPU_CHROMA_H2V1, 4, 2, DPU_FORMAT_FLAG_YUV, 454 DPU_FETCH_LINEAR, 2), 455 456 INTERLEAVED_YUV_FMT(YUYV, 457 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, 458 C0_G_Y, C1_B_Cb, C0_G_Y, C2_R_Cr, 459 false, DPU_CHROMA_H2V1, 4, 2, DPU_FORMAT_FLAG_YUV, 460 DPU_FETCH_LINEAR, 2), 461 462 INTERLEAVED_YUV_FMT(YVYU, 463 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, 464 C0_G_Y, C2_R_Cr, C0_G_Y, C1_B_Cb, 465 false, DPU_CHROMA_H2V1, 4, 2, DPU_FORMAT_FLAG_YUV, 466 DPU_FETCH_LINEAR, 2), 467 468 PLANAR_YUV_FMT(YUV420, 469 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, 470 C2_R_Cr, C1_B_Cb, C0_G_Y, 471 false, DPU_CHROMA_420, 1, DPU_FORMAT_FLAG_YUV, 472 DPU_FETCH_LINEAR, 3), 473 474 PLANAR_YUV_FMT(YVU420, 475 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, 476 C1_B_Cb, C2_R_Cr, C0_G_Y, 477 false, DPU_CHROMA_420, 1, DPU_FORMAT_FLAG_YUV, 478 DPU_FETCH_LINEAR, 3), 479 }; 480 481 /* 482 * A5x tile formats tables: 483 * These tables hold the A5x tile formats supported. 484 */ 485 static const struct dpu_format dpu_format_map_tile[] = { 486 INTERLEAVED_RGB_FMT_TILED(BGR565, 487 0, COLOR_5BIT, COLOR_6BIT, COLOR_5BIT, 488 C2_R_Cr, C0_G_Y, C1_B_Cb, 0, 3, 489 false, 2, 0, 490 DPU_FETCH_UBWC, 1, DPU_TILE_HEIGHT_TILED), 491 492 INTERLEAVED_RGB_FMT_TILED(ARGB8888, 493 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, 494 C3_ALPHA, C2_R_Cr, C0_G_Y, C1_B_Cb, 4, 495 true, 4, 0, 496 DPU_FETCH_UBWC, 1, DPU_TILE_HEIGHT_TILED), 497 498 INTERLEAVED_RGB_FMT_TILED(ABGR8888, 499 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, 500 C3_ALPHA, C1_B_Cb, C0_G_Y, C2_R_Cr, 4, 501 true, 4, 0, 502 DPU_FETCH_UBWC, 1, DPU_TILE_HEIGHT_TILED), 503 504 INTERLEAVED_RGB_FMT_TILED(XBGR8888, 505 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, 506 C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4, 507 false, 4, 0, 508 DPU_FETCH_UBWC, 1, DPU_TILE_HEIGHT_TILED), 509 510 INTERLEAVED_RGB_FMT_TILED(RGBA8888, 511 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, 512 C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4, 513 true, 4, 0, 514 DPU_FETCH_UBWC, 1, DPU_TILE_HEIGHT_TILED), 515 516 INTERLEAVED_RGB_FMT_TILED(BGRA8888, 517 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, 518 C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA, 4, 519 true, 4, 0, 520 DPU_FETCH_UBWC, 1, DPU_TILE_HEIGHT_TILED), 521 522 INTERLEAVED_RGB_FMT_TILED(BGRX8888, 523 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, 524 C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA, 4, 525 false, 4, 0, 526 DPU_FETCH_UBWC, 1, DPU_TILE_HEIGHT_TILED), 527 528 INTERLEAVED_RGB_FMT_TILED(XRGB8888, 529 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, 530 C3_ALPHA, C2_R_Cr, C0_G_Y, C1_B_Cb, 4, 531 false, 4, 0, 532 DPU_FETCH_UBWC, 1, DPU_TILE_HEIGHT_TILED), 533 534 INTERLEAVED_RGB_FMT_TILED(RGBX8888, 535 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, 536 C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4, 537 false, 4, 0, 538 DPU_FETCH_UBWC, 1, DPU_TILE_HEIGHT_TILED), 539 540 INTERLEAVED_RGB_FMT_TILED(ABGR2101010, 541 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, 542 C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4, 543 true, 4, DPU_FORMAT_FLAG_DX, 544 DPU_FETCH_UBWC, 1, DPU_TILE_HEIGHT_TILED), 545 546 INTERLEAVED_RGB_FMT_TILED(XBGR2101010, 547 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, 548 C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4, 549 true, 4, DPU_FORMAT_FLAG_DX, 550 DPU_FETCH_UBWC, 1, DPU_TILE_HEIGHT_TILED), 551 552 PSEUDO_YUV_FMT_TILED(NV12, 553 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, 554 C1_B_Cb, C2_R_Cr, 555 DPU_CHROMA_420, DPU_FORMAT_FLAG_YUV, 556 DPU_FETCH_UBWC, 2, DPU_TILE_HEIGHT_NV12), 557 558 PSEUDO_YUV_FMT_TILED(NV21, 559 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, 560 C2_R_Cr, C1_B_Cb, 561 DPU_CHROMA_420, DPU_FORMAT_FLAG_YUV, 562 DPU_FETCH_UBWC, 2, DPU_TILE_HEIGHT_NV12), 563 }; 564 565 /* 566 * UBWC formats table: 567 * This table holds the UBWC formats supported. 568 * If a compression ratio needs to be used for this or any other format, 569 * the data will be passed by user-space. 570 */ 571 static const struct dpu_format dpu_format_map_ubwc[] = { 572 INTERLEAVED_RGB_FMT_TILED(BGR565, 573 0, COLOR_5BIT, COLOR_6BIT, COLOR_5BIT, 574 C2_R_Cr, C0_G_Y, C1_B_Cb, 0, 3, 575 false, 2, DPU_FORMAT_FLAG_COMPRESSED, 576 DPU_FETCH_UBWC, 2, DPU_TILE_HEIGHT_UBWC), 577 578 INTERLEAVED_RGB_FMT_TILED(ABGR8888, 579 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, 580 C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4, 581 true, 4, DPU_FORMAT_FLAG_COMPRESSED, 582 DPU_FETCH_UBWC, 2, DPU_TILE_HEIGHT_UBWC), 583 584 INTERLEAVED_RGB_FMT_TILED(XBGR8888, 585 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, 586 C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4, 587 false, 4, DPU_FORMAT_FLAG_COMPRESSED, 588 DPU_FETCH_UBWC, 2, DPU_TILE_HEIGHT_UBWC), 589 590 INTERLEAVED_RGB_FMT_TILED(ABGR2101010, 591 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, 592 C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4, 593 true, 4, DPU_FORMAT_FLAG_DX | DPU_FORMAT_FLAG_COMPRESSED, 594 DPU_FETCH_UBWC, 2, DPU_TILE_HEIGHT_UBWC), 595 596 INTERLEAVED_RGB_FMT_TILED(XBGR2101010, 597 COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, 598 C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4, 599 true, 4, DPU_FORMAT_FLAG_DX | DPU_FORMAT_FLAG_COMPRESSED, 600 DPU_FETCH_UBWC, 2, DPU_TILE_HEIGHT_UBWC), 601 602 PSEUDO_YUV_FMT_TILED(NV12, 603 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, 604 C1_B_Cb, C2_R_Cr, 605 DPU_CHROMA_420, DPU_FORMAT_FLAG_YUV | 606 DPU_FORMAT_FLAG_COMPRESSED, 607 DPU_FETCH_UBWC, 4, DPU_TILE_HEIGHT_NV12), 608 }; 609 610 static const struct dpu_format dpu_format_map_p010[] = { 611 PSEUDO_YUV_FMT_LOOSE(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_FETCH_LINEAR, 2), 616 }; 617 618 static const struct dpu_format dpu_format_map_p010_ubwc[] = { 619 PSEUDO_YUV_FMT_LOOSE_TILED(NV12, 620 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, 621 C1_B_Cb, C2_R_Cr, 622 DPU_CHROMA_420, (DPU_FORMAT_FLAG_YUV | DPU_FORMAT_FLAG_DX | 623 DPU_FORMAT_FLAG_COMPRESSED), 624 DPU_FETCH_UBWC, 4, DPU_TILE_HEIGHT_NV12), 625 }; 626 627 static const struct dpu_format dpu_format_map_tp10_ubwc[] = { 628 PSEUDO_YUV_FMT_TILED(NV12, 629 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, 630 C1_B_Cb, C2_R_Cr, 631 DPU_CHROMA_420, (DPU_FORMAT_FLAG_YUV | DPU_FORMAT_FLAG_DX | 632 DPU_FORMAT_FLAG_COMPRESSED), 633 DPU_FETCH_UBWC, 4, DPU_TILE_HEIGHT_NV12), 634 }; 635 636 /* _dpu_get_v_h_subsample_rate - Get subsample rates for all formats we support 637 * Note: Not using the drm_format_*_subsampling since we have formats 638 */ 639 static void _dpu_get_v_h_subsample_rate( 640 enum dpu_chroma_samp_type chroma_sample, 641 uint32_t *v_sample, 642 uint32_t *h_sample) 643 { 644 if (!v_sample || !h_sample) 645 return; 646 647 switch (chroma_sample) { 648 case DPU_CHROMA_H2V1: 649 *v_sample = 1; 650 *h_sample = 2; 651 break; 652 case DPU_CHROMA_H1V2: 653 *v_sample = 2; 654 *h_sample = 1; 655 break; 656 case DPU_CHROMA_420: 657 *v_sample = 2; 658 *h_sample = 2; 659 break; 660 default: 661 *v_sample = 1; 662 *h_sample = 1; 663 break; 664 } 665 } 666 667 static int _dpu_format_get_media_color_ubwc(const struct dpu_format *fmt) 668 { 669 static const struct dpu_media_color_map dpu_media_ubwc_map[] = { 670 {DRM_FORMAT_ABGR8888, COLOR_FMT_RGBA8888_UBWC}, 671 {DRM_FORMAT_XBGR8888, COLOR_FMT_RGBA8888_UBWC}, 672 {DRM_FORMAT_ABGR2101010, COLOR_FMT_RGBA1010102_UBWC}, 673 {DRM_FORMAT_XBGR2101010, COLOR_FMT_RGBA1010102_UBWC}, 674 {DRM_FORMAT_BGR565, COLOR_FMT_RGB565_UBWC}, 675 }; 676 int color_fmt = -1; 677 int i; 678 679 if (fmt->base.pixel_format == DRM_FORMAT_NV12) { 680 if (DPU_FORMAT_IS_DX(fmt)) { 681 if (fmt->unpack_tight) 682 color_fmt = COLOR_FMT_NV12_BPP10_UBWC; 683 else 684 color_fmt = COLOR_FMT_P010_UBWC; 685 } else 686 color_fmt = COLOR_FMT_NV12_UBWC; 687 return color_fmt; 688 } 689 690 for (i = 0; i < ARRAY_SIZE(dpu_media_ubwc_map); ++i) 691 if (fmt->base.pixel_format == dpu_media_ubwc_map[i].format) { 692 color_fmt = dpu_media_ubwc_map[i].color; 693 break; 694 } 695 return color_fmt; 696 } 697 698 static int _dpu_format_get_plane_sizes_ubwc( 699 const struct dpu_format *fmt, 700 const uint32_t width, 701 const uint32_t height, 702 struct dpu_hw_fmt_layout *layout) 703 { 704 int i; 705 int color; 706 bool meta = DPU_FORMAT_IS_UBWC(fmt); 707 708 memset(layout, 0, sizeof(struct dpu_hw_fmt_layout)); 709 layout->format = fmt; 710 layout->width = width; 711 layout->height = height; 712 layout->num_planes = fmt->num_planes; 713 714 color = _dpu_format_get_media_color_ubwc(fmt); 715 if (color < 0) { 716 DRM_ERROR("UBWC format not supported for fmt: %4.4s\n", 717 (char *)&fmt->base.pixel_format); 718 return -EINVAL; 719 } 720 721 if (DPU_FORMAT_IS_YUV(layout->format)) { 722 uint32_t y_sclines, uv_sclines; 723 uint32_t y_meta_scanlines = 0; 724 uint32_t uv_meta_scanlines = 0; 725 726 layout->num_planes = 2; 727 layout->plane_pitch[0] = VENUS_Y_STRIDE(color, width); 728 y_sclines = VENUS_Y_SCANLINES(color, height); 729 layout->plane_size[0] = MSM_MEDIA_ALIGN(layout->plane_pitch[0] * 730 y_sclines, DPU_UBWC_PLANE_SIZE_ALIGNMENT); 731 732 layout->plane_pitch[1] = VENUS_UV_STRIDE(color, width); 733 uv_sclines = VENUS_UV_SCANLINES(color, height); 734 layout->plane_size[1] = MSM_MEDIA_ALIGN(layout->plane_pitch[1] * 735 uv_sclines, DPU_UBWC_PLANE_SIZE_ALIGNMENT); 736 737 if (!meta) 738 goto done; 739 740 layout->num_planes += 2; 741 layout->plane_pitch[2] = VENUS_Y_META_STRIDE(color, width); 742 y_meta_scanlines = VENUS_Y_META_SCANLINES(color, height); 743 layout->plane_size[2] = MSM_MEDIA_ALIGN(layout->plane_pitch[2] * 744 y_meta_scanlines, DPU_UBWC_PLANE_SIZE_ALIGNMENT); 745 746 layout->plane_pitch[3] = VENUS_UV_META_STRIDE(color, width); 747 uv_meta_scanlines = VENUS_UV_META_SCANLINES(color, height); 748 layout->plane_size[3] = MSM_MEDIA_ALIGN(layout->plane_pitch[3] * 749 uv_meta_scanlines, DPU_UBWC_PLANE_SIZE_ALIGNMENT); 750 751 } else { 752 uint32_t rgb_scanlines, rgb_meta_scanlines; 753 754 layout->num_planes = 1; 755 756 layout->plane_pitch[0] = VENUS_RGB_STRIDE(color, width); 757 rgb_scanlines = VENUS_RGB_SCANLINES(color, height); 758 layout->plane_size[0] = MSM_MEDIA_ALIGN(layout->plane_pitch[0] * 759 rgb_scanlines, DPU_UBWC_PLANE_SIZE_ALIGNMENT); 760 761 if (!meta) 762 goto done; 763 layout->num_planes += 2; 764 layout->plane_pitch[2] = VENUS_RGB_META_STRIDE(color, width); 765 rgb_meta_scanlines = VENUS_RGB_META_SCANLINES(color, height); 766 layout->plane_size[2] = MSM_MEDIA_ALIGN(layout->plane_pitch[2] * 767 rgb_meta_scanlines, DPU_UBWC_PLANE_SIZE_ALIGNMENT); 768 } 769 770 done: 771 for (i = 0; i < DPU_MAX_PLANES; i++) 772 layout->total_size += layout->plane_size[i]; 773 774 return 0; 775 } 776 777 static int _dpu_format_get_plane_sizes_linear( 778 const struct dpu_format *fmt, 779 const uint32_t width, 780 const uint32_t height, 781 struct dpu_hw_fmt_layout *layout, 782 const uint32_t *pitches) 783 { 784 int i; 785 786 memset(layout, 0, sizeof(struct dpu_hw_fmt_layout)); 787 layout->format = fmt; 788 layout->width = width; 789 layout->height = height; 790 layout->num_planes = fmt->num_planes; 791 792 /* Due to memset above, only need to set planes of interest */ 793 if (fmt->fetch_planes == DPU_PLANE_INTERLEAVED) { 794 layout->num_planes = 1; 795 layout->plane_size[0] = width * height * layout->format->bpp; 796 layout->plane_pitch[0] = width * layout->format->bpp; 797 } else { 798 uint32_t v_subsample, h_subsample; 799 uint32_t chroma_samp; 800 uint32_t bpp = 1; 801 802 chroma_samp = fmt->chroma_sample; 803 _dpu_get_v_h_subsample_rate(chroma_samp, &v_subsample, 804 &h_subsample); 805 806 if (width % h_subsample || height % v_subsample) { 807 DRM_ERROR("mismatch in subsample vs dimensions\n"); 808 return -EINVAL; 809 } 810 811 if ((fmt->base.pixel_format == DRM_FORMAT_NV12) && 812 (DPU_FORMAT_IS_DX(fmt))) 813 bpp = 2; 814 layout->plane_pitch[0] = width * bpp; 815 layout->plane_pitch[1] = layout->plane_pitch[0] / h_subsample; 816 layout->plane_size[0] = layout->plane_pitch[0] * height; 817 layout->plane_size[1] = layout->plane_pitch[1] * 818 (height / v_subsample); 819 820 if (fmt->fetch_planes == DPU_PLANE_PSEUDO_PLANAR) { 821 layout->num_planes = 2; 822 layout->plane_size[1] *= 2; 823 layout->plane_pitch[1] *= 2; 824 } else { 825 /* planar */ 826 layout->num_planes = 3; 827 layout->plane_size[2] = layout->plane_size[1]; 828 layout->plane_pitch[2] = layout->plane_pitch[1]; 829 } 830 } 831 832 /* 833 * linear format: allow user allocated pitches if they are greater than 834 * the requirement. 835 * ubwc format: pitch values are computed uniformly across 836 * all the components based on ubwc specifications. 837 */ 838 for (i = 0; i < layout->num_planes && i < DPU_MAX_PLANES; ++i) { 839 if (pitches && layout->plane_pitch[i] < pitches[i]) 840 layout->plane_pitch[i] = pitches[i]; 841 } 842 843 for (i = 0; i < DPU_MAX_PLANES; i++) 844 layout->total_size += layout->plane_size[i]; 845 846 return 0; 847 } 848 849 static int dpu_format_get_plane_sizes( 850 const struct dpu_format *fmt, 851 const uint32_t w, 852 const uint32_t h, 853 struct dpu_hw_fmt_layout *layout, 854 const uint32_t *pitches) 855 { 856 if (!layout || !fmt) { 857 DRM_ERROR("invalid pointer\n"); 858 return -EINVAL; 859 } 860 861 if ((w > DPU_MAX_IMG_WIDTH) || (h > DPU_MAX_IMG_HEIGHT)) { 862 DRM_ERROR("image dimensions outside max range\n"); 863 return -ERANGE; 864 } 865 866 if (DPU_FORMAT_IS_UBWC(fmt) || DPU_FORMAT_IS_TILE(fmt)) 867 return _dpu_format_get_plane_sizes_ubwc(fmt, w, h, layout); 868 869 return _dpu_format_get_plane_sizes_linear(fmt, w, h, layout, pitches); 870 } 871 872 static int _dpu_format_populate_addrs_ubwc( 873 struct msm_gem_address_space *aspace, 874 struct drm_framebuffer *fb, 875 struct dpu_hw_fmt_layout *layout) 876 { 877 uint32_t base_addr = 0; 878 bool meta; 879 880 if (!fb || !layout) { 881 DRM_ERROR("invalid pointers\n"); 882 return -EINVAL; 883 } 884 885 if (aspace) 886 base_addr = msm_framebuffer_iova(fb, aspace, 0); 887 if (!base_addr) { 888 DRM_ERROR("failed to retrieve base addr\n"); 889 return -EFAULT; 890 } 891 892 meta = DPU_FORMAT_IS_UBWC(layout->format); 893 894 /* Per-format logic for verifying active planes */ 895 if (DPU_FORMAT_IS_YUV(layout->format)) { 896 /************************************************/ 897 /* UBWC ** */ 898 /* buffer ** DPU PLANE */ 899 /* format ** */ 900 /************************************************/ 901 /* ------------------- ** -------------------- */ 902 /* | Y meta | ** | Y bitstream | */ 903 /* | data | ** | plane | */ 904 /* ------------------- ** -------------------- */ 905 /* | Y bitstream | ** | CbCr bitstream | */ 906 /* | data | ** | plane | */ 907 /* ------------------- ** -------------------- */ 908 /* | Cbcr metadata | ** | Y meta | */ 909 /* | data | ** | plane | */ 910 /* ------------------- ** -------------------- */ 911 /* | CbCr bitstream | ** | CbCr meta | */ 912 /* | data | ** | plane | */ 913 /* ------------------- ** -------------------- */ 914 /************************************************/ 915 916 /* configure Y bitstream plane */ 917 layout->plane_addr[0] = base_addr + layout->plane_size[2]; 918 919 /* configure CbCr bitstream plane */ 920 layout->plane_addr[1] = base_addr + layout->plane_size[0] 921 + layout->plane_size[2] + layout->plane_size[3]; 922 923 if (!meta) 924 return 0; 925 926 /* configure Y metadata plane */ 927 layout->plane_addr[2] = base_addr; 928 929 /* configure CbCr metadata plane */ 930 layout->plane_addr[3] = base_addr + layout->plane_size[0] 931 + layout->plane_size[2]; 932 933 } else { 934 /************************************************/ 935 /* UBWC ** */ 936 /* buffer ** DPU PLANE */ 937 /* format ** */ 938 /************************************************/ 939 /* ------------------- ** -------------------- */ 940 /* | RGB meta | ** | RGB bitstream | */ 941 /* | data | ** | plane | */ 942 /* ------------------- ** -------------------- */ 943 /* | RGB bitstream | ** | NONE | */ 944 /* | data | ** | | */ 945 /* ------------------- ** -------------------- */ 946 /* ** | RGB meta | */ 947 /* ** | plane | */ 948 /* ** -------------------- */ 949 /************************************************/ 950 951 layout->plane_addr[0] = base_addr + layout->plane_size[2]; 952 layout->plane_addr[1] = 0; 953 954 if (!meta) 955 return 0; 956 957 layout->plane_addr[2] = base_addr; 958 layout->plane_addr[3] = 0; 959 } 960 return 0; 961 } 962 963 static int _dpu_format_populate_addrs_linear( 964 struct msm_gem_address_space *aspace, 965 struct drm_framebuffer *fb, 966 struct dpu_hw_fmt_layout *layout) 967 { 968 unsigned int i; 969 970 /* Can now check the pitches given vs pitches expected */ 971 for (i = 0; i < layout->num_planes; ++i) { 972 if (layout->plane_pitch[i] > fb->pitches[i]) { 973 DRM_ERROR("plane %u expected pitch %u, fb %u\n", 974 i, layout->plane_pitch[i], fb->pitches[i]); 975 return -EINVAL; 976 } 977 } 978 979 /* Populate addresses for simple formats here */ 980 for (i = 0; i < layout->num_planes; ++i) { 981 if (aspace) 982 layout->plane_addr[i] = 983 msm_framebuffer_iova(fb, aspace, i); 984 if (!layout->plane_addr[i]) { 985 DRM_ERROR("failed to retrieve base addr\n"); 986 return -EFAULT; 987 } 988 } 989 990 return 0; 991 } 992 993 int dpu_format_populate_layout( 994 struct msm_gem_address_space *aspace, 995 struct drm_framebuffer *fb, 996 struct dpu_hw_fmt_layout *layout) 997 { 998 uint32_t plane_addr[DPU_MAX_PLANES]; 999 int i, ret; 1000 1001 if (!fb || !layout) { 1002 DRM_ERROR("invalid arguments\n"); 1003 return -EINVAL; 1004 } 1005 1006 if ((fb->width > DPU_MAX_IMG_WIDTH) || 1007 (fb->height > DPU_MAX_IMG_HEIGHT)) { 1008 DRM_ERROR("image dimensions outside max range\n"); 1009 return -ERANGE; 1010 } 1011 1012 layout->format = to_dpu_format(msm_framebuffer_format(fb)); 1013 1014 /* Populate the plane sizes etc via get_format */ 1015 ret = dpu_format_get_plane_sizes(layout->format, fb->width, fb->height, 1016 layout, fb->pitches); 1017 if (ret) 1018 return ret; 1019 1020 for (i = 0; i < DPU_MAX_PLANES; ++i) 1021 plane_addr[i] = layout->plane_addr[i]; 1022 1023 /* Populate the addresses given the fb */ 1024 if (DPU_FORMAT_IS_UBWC(layout->format) || 1025 DPU_FORMAT_IS_TILE(layout->format)) 1026 ret = _dpu_format_populate_addrs_ubwc(aspace, fb, layout); 1027 else 1028 ret = _dpu_format_populate_addrs_linear(aspace, fb, layout); 1029 1030 /* check if anything changed */ 1031 if (!ret && !memcmp(plane_addr, layout->plane_addr, sizeof(plane_addr))) 1032 ret = -EAGAIN; 1033 1034 return ret; 1035 } 1036 1037 int dpu_format_check_modified_format( 1038 const struct msm_kms *kms, 1039 const struct msm_format *msm_fmt, 1040 const struct drm_mode_fb_cmd2 *cmd, 1041 struct drm_gem_object **bos) 1042 { 1043 int ret, i, num_base_fmt_planes; 1044 const struct dpu_format *fmt; 1045 struct dpu_hw_fmt_layout layout; 1046 uint32_t bos_total_size = 0; 1047 1048 if (!msm_fmt || !cmd || !bos) { 1049 DRM_ERROR("invalid arguments\n"); 1050 return -EINVAL; 1051 } 1052 1053 fmt = to_dpu_format(msm_fmt); 1054 num_base_fmt_planes = drm_format_num_planes(fmt->base.pixel_format); 1055 1056 ret = dpu_format_get_plane_sizes(fmt, cmd->width, cmd->height, 1057 &layout, cmd->pitches); 1058 if (ret) 1059 return ret; 1060 1061 for (i = 0; i < num_base_fmt_planes; i++) { 1062 if (!bos[i]) { 1063 DRM_ERROR("invalid handle for plane %d\n", i); 1064 return -EINVAL; 1065 } 1066 if ((i == 0) || (bos[i] != bos[0])) 1067 bos_total_size += bos[i]->size; 1068 } 1069 1070 if (bos_total_size < layout.total_size) { 1071 DRM_ERROR("buffers total size too small %u expected %u\n", 1072 bos_total_size, layout.total_size); 1073 return -EINVAL; 1074 } 1075 1076 return 0; 1077 } 1078 1079 const struct dpu_format *dpu_get_dpu_format_ext( 1080 const uint32_t format, 1081 const uint64_t modifier) 1082 { 1083 uint32_t i = 0; 1084 const struct dpu_format *fmt = NULL; 1085 const struct dpu_format *map = NULL; 1086 ssize_t map_size = 0; 1087 1088 /* 1089 * Currently only support exactly zero or one modifier. 1090 * All planes use the same modifier. 1091 */ 1092 DPU_DEBUG("plane format modifier 0x%llX\n", modifier); 1093 1094 switch (modifier) { 1095 case 0: 1096 map = dpu_format_map; 1097 map_size = ARRAY_SIZE(dpu_format_map); 1098 break; 1099 case DRM_FORMAT_MOD_QCOM_COMPRESSED: 1100 map = dpu_format_map_ubwc; 1101 map_size = ARRAY_SIZE(dpu_format_map_ubwc); 1102 DPU_DEBUG("found fmt: %4.4s DRM_FORMAT_MOD_QCOM_COMPRESSED\n", 1103 (char *)&format); 1104 break; 1105 default: 1106 DPU_ERROR("unsupported format modifier %llX\n", modifier); 1107 return NULL; 1108 } 1109 1110 for (i = 0; i < map_size; i++) { 1111 if (format == map[i].base.pixel_format) { 1112 fmt = &map[i]; 1113 break; 1114 } 1115 } 1116 1117 if (fmt == NULL) 1118 DPU_ERROR("unsupported fmt: %4.4s modifier 0x%llX\n", 1119 (char *)&format, modifier); 1120 else 1121 DPU_DEBUG("fmt %4.4s mod 0x%llX ubwc %d yuv %d\n", 1122 (char *)&format, modifier, 1123 DPU_FORMAT_IS_UBWC(fmt), 1124 DPU_FORMAT_IS_YUV(fmt)); 1125 1126 return fmt; 1127 } 1128 1129 const struct msm_format *dpu_get_msm_format( 1130 struct msm_kms *kms, 1131 const uint32_t format, 1132 const uint64_t modifiers) 1133 { 1134 const struct dpu_format *fmt = dpu_get_dpu_format_ext(format, 1135 modifiers); 1136 if (fmt) 1137 return &fmt->base; 1138 return NULL; 1139 } 1140 1141 uint32_t dpu_populate_formats( 1142 const struct dpu_format_extended *format_list, 1143 uint32_t *pixel_formats, 1144 uint64_t *pixel_modifiers, 1145 uint32_t pixel_formats_max) 1146 { 1147 uint32_t i, fourcc_format; 1148 1149 if (!format_list || !pixel_formats) 1150 return 0; 1151 1152 for (i = 0, fourcc_format = 0; 1153 format_list->fourcc_format && i < pixel_formats_max; 1154 ++format_list) { 1155 /* verify if listed format is in dpu_format_map? */ 1156 1157 /* optionally return modified formats */ 1158 if (pixel_modifiers) { 1159 /* assume same modifier for all fb planes */ 1160 pixel_formats[i] = format_list->fourcc_format; 1161 pixel_modifiers[i++] = format_list->modifier; 1162 } else { 1163 /* assume base formats grouped together */ 1164 if (fourcc_format != format_list->fourcc_format) { 1165 fourcc_format = format_list->fourcc_format; 1166 pixel_formats[i++] = fourcc_format; 1167 } 1168 } 1169 } 1170 1171 return i; 1172 } 1173