Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
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  * DPU supported format packing, bpp, and other format
0028  * information.
0029  * DPU currently only supports interleaved RGB formats
0030  * UBWC support for a pixel format is indicated by the flag,
0031  * there is additional meta data plane for such formats
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  * struct dpu_media_color_map - maps drm format to media format
0188  * @format: DRM base pixel format
0189  * @color: Media API color related to DRM format
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  * UBWC formats table:
0476  * This table holds the UBWC formats supported.
0477  * If a compression ratio needs to be used for this or any other format,
0478  * the data will be passed by user-space.
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     /* ARGB8888 and ABGR8888 purposely have the same color
0494      * ordering.  The hardware only supports ABGR8888 UBWC
0495      * natively.
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 /* _dpu_get_v_h_subsample_rate - Get subsample rates for all formats we support
0536  *   Note: Not using the drm_format_*_subsampling since we have formats
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     /* Due to memset above, only need to set planes of interest */
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             /* planar */
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      * linear format: allow user allocated pitches if they are greater than
0735      * the requirement.
0736      * ubwc format: pitch values are computed uniformly across
0737      * all the components based on ubwc specifications.
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     /* Per-format logic for verifying active planes */
0796     if (DPU_FORMAT_IS_YUV(layout->format)) {
0797         /************************************************/
0798         /*      UBWC            **                      */
0799         /*      buffer          **      DPU PLANE       */
0800         /*      format          **                      */
0801         /************************************************/
0802         /* -------------------  ** -------------------- */
0803         /* |      Y meta     |  ** |    Y bitstream   | */
0804         /* |       data      |  ** |       plane      | */
0805         /* -------------------  ** -------------------- */
0806         /* |    Y bitstream  |  ** |  CbCr bitstream  | */
0807         /* |       data      |  ** |       plane      | */
0808         /* -------------------  ** -------------------- */
0809         /* |   Cbcr metadata |  ** |       Y meta     | */
0810         /* |       data      |  ** |       plane      | */
0811         /* -------------------  ** -------------------- */
0812         /* |  CbCr bitstream |  ** |     CbCr meta    | */
0813         /* |       data      |  ** |       plane      | */
0814         /* -------------------  ** -------------------- */
0815         /************************************************/
0816 
0817         /* configure Y bitstream plane */
0818         layout->plane_addr[0] = base_addr + layout->plane_size[2];
0819 
0820         /* configure CbCr bitstream plane */
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         /* configure Y metadata plane */
0828         layout->plane_addr[2] = base_addr;
0829 
0830         /* configure CbCr metadata plane */
0831         layout->plane_addr[3] = base_addr + layout->plane_size[0]
0832             + layout->plane_size[2];
0833 
0834     } else {
0835         /************************************************/
0836         /*      UBWC            **                      */
0837         /*      buffer          **      DPU PLANE       */
0838         /*      format          **                      */
0839         /************************************************/
0840         /* -------------------  ** -------------------- */
0841         /* |      RGB meta   |  ** |   RGB bitstream  | */
0842         /* |       data      |  ** |       plane      | */
0843         /* -------------------  ** -------------------- */
0844         /* |  RGB bitstream  |  ** |       NONE       | */
0845         /* |       data      |  ** |                  | */
0846         /* -------------------  ** -------------------- */
0847         /*                      ** |     RGB meta     | */
0848         /*                      ** |       plane      | */
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     /* Can now check the pitches given vs pitches expected */
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     /* Populate addresses for simple formats here */
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     /* Populate the plane sizes etc via get_format */
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     /* Populate the addresses given the fb */
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     /* check if anything changed */
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      * Currently only support exactly zero or one modifier.
0994      * All planes use the same modifier.
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 }