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 #include <linux/slab.h> 7 #include <linux/of_address.h> 8 #include <linux/platform_device.h> 9 #include "dpu_hw_mdss.h" 10 #include "dpu_hw_catalog.h" 11 #include "dpu_hw_catalog_format.h" 12 #include "dpu_kms.h" 13 14 #define VIG_SDM845_MASK \ 15 (BIT(DPU_SSPP_SRC) | BIT(DPU_SSPP_SCALER_QSEED3) | BIT(DPU_SSPP_QOS) |\ 16 BIT(DPU_SSPP_CSC_10BIT) | BIT(DPU_SSPP_CDP) | BIT(DPU_SSPP_QOS_8LVL) |\ 17 BIT(DPU_SSPP_TS_PREFILL) | BIT(DPU_SSPP_EXCL_RECT)) 18 19 #define DMA_SDM845_MASK \ 20 (BIT(DPU_SSPP_SRC) | BIT(DPU_SSPP_QOS) | BIT(DPU_SSPP_QOS_8LVL) |\ 21 BIT(DPU_SSPP_TS_PREFILL) | BIT(DPU_SSPP_TS_PREFILL_REC1) |\ 22 BIT(DPU_SSPP_CDP) | BIT(DPU_SSPP_EXCL_RECT)) 23 24 #define DMA_CURSOR_SDM845_MASK \ 25 (DMA_SDM845_MASK | BIT(DPU_SSPP_CURSOR)) 26 27 #define MIXER_SDM845_MASK \ 28 (BIT(DPU_MIXER_SOURCESPLIT) | BIT(DPU_DIM_LAYER)) 29 30 #define PINGPONG_SDM845_MASK BIT(DPU_PINGPONG_DITHER) 31 32 #define PINGPONG_SDM845_SPLIT_MASK \ 33 (PINGPONG_SDM845_MASK | BIT(DPU_PINGPONG_TE2)) 34 35 #define DEFAULT_PIXEL_RAM_SIZE (50 * 1024) 36 #define DEFAULT_DPU_LINE_WIDTH 2048 37 #define DEFAULT_DPU_OUTPUT_LINE_WIDTH 2560 38 39 #define MAX_HORZ_DECIMATION 4 40 #define MAX_VERT_DECIMATION 4 41 42 #define MAX_UPSCALE_RATIO 20 43 #define MAX_DOWNSCALE_RATIO 4 44 #define SSPP_UNITY_SCALE 1 45 46 #define STRCAT(X, Y) (X Y) 47 48 /************************************************************* 49 * DPU sub blocks config 50 *************************************************************/ 51 /* DPU top level caps */ 52 static const struct dpu_caps sdm845_dpu_caps = { 53 .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, 54 .max_mixer_blendstages = 0xb, 55 .qseed_type = DPU_SSPP_SCALER_QSEED3, 56 .smart_dma_rev = DPU_SSPP_SMART_DMA_V2, 57 .ubwc_version = DPU_HW_UBWC_VER_20, 58 .has_src_split = true, 59 .has_dim_layer = true, 60 .has_idle_pc = true, 61 }; 62 63 static struct dpu_mdp_cfg sdm845_mdp[] = { 64 { 65 .name = "top_0", .id = MDP_TOP, 66 .base = 0x0, .len = 0x45C, 67 .features = 0, 68 .highest_bank_bit = 0x2, 69 .clk_ctrls[DPU_CLK_CTRL_VIG0] = { 70 .reg_off = 0x2AC, .bit_off = 0}, 71 .clk_ctrls[DPU_CLK_CTRL_VIG1] = { 72 .reg_off = 0x2B4, .bit_off = 0}, 73 .clk_ctrls[DPU_CLK_CTRL_VIG2] = { 74 .reg_off = 0x2BC, .bit_off = 0}, 75 .clk_ctrls[DPU_CLK_CTRL_VIG3] = { 76 .reg_off = 0x2C4, .bit_off = 0}, 77 .clk_ctrls[DPU_CLK_CTRL_DMA0] = { 78 .reg_off = 0x2AC, .bit_off = 8}, 79 .clk_ctrls[DPU_CLK_CTRL_DMA1] = { 80 .reg_off = 0x2B4, .bit_off = 8}, 81 .clk_ctrls[DPU_CLK_CTRL_CURSOR0] = { 82 .reg_off = 0x2BC, .bit_off = 8}, 83 .clk_ctrls[DPU_CLK_CTRL_CURSOR1] = { 84 .reg_off = 0x2C4, .bit_off = 8}, 85 }, 86 }; 87 88 /************************************************************* 89 * CTL sub blocks config 90 *************************************************************/ 91 static struct dpu_ctl_cfg sdm845_ctl[] = { 92 { 93 .name = "ctl_0", .id = CTL_0, 94 .base = 0x1000, .len = 0xE4, 95 .features = BIT(DPU_CTL_SPLIT_DISPLAY) 96 }, 97 { 98 .name = "ctl_1", .id = CTL_1, 99 .base = 0x1200, .len = 0xE4, 100 .features = BIT(DPU_CTL_SPLIT_DISPLAY) 101 }, 102 { 103 .name = "ctl_2", .id = CTL_2, 104 .base = 0x1400, .len = 0xE4, 105 .features = 0 106 }, 107 { 108 .name = "ctl_3", .id = CTL_3, 109 .base = 0x1600, .len = 0xE4, 110 .features = 0 111 }, 112 { 113 .name = "ctl_4", .id = CTL_4, 114 .base = 0x1800, .len = 0xE4, 115 .features = 0 116 }, 117 }; 118 119 /************************************************************* 120 * SSPP sub blocks config 121 *************************************************************/ 122 123 /* SSPP common configuration */ 124 static const struct dpu_sspp_blks_common sdm845_sspp_common = { 125 .maxlinewidth = DEFAULT_DPU_OUTPUT_LINE_WIDTH, 126 .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE, 127 .maxhdeciexp = MAX_HORZ_DECIMATION, 128 .maxvdeciexp = MAX_VERT_DECIMATION, 129 }; 130 131 #define _VIG_SBLK(num, sdma_pri) \ 132 { \ 133 .common = &sdm845_sspp_common, \ 134 .maxdwnscale = MAX_DOWNSCALE_RATIO, \ 135 .maxupscale = MAX_UPSCALE_RATIO, \ 136 .smart_dma_priority = sdma_pri, \ 137 .src_blk = {.name = STRCAT("sspp_src_", num), \ 138 .id = DPU_SSPP_SRC, .base = 0x00, .len = 0x150,}, \ 139 .scaler_blk = {.name = STRCAT("sspp_scaler", num), \ 140 .id = DPU_SSPP_SCALER_QSEED3, \ 141 .base = 0xa00, .len = 0xa0,}, \ 142 .csc_blk = {.name = STRCAT("sspp_csc", num), \ 143 .id = DPU_SSPP_CSC_10BIT, \ 144 .base = 0x1a00, .len = 0x100,}, \ 145 .format_list = plane_formats_yuv, \ 146 .num_formats = ARRAY_SIZE(plane_formats_yuv), \ 147 .virt_format_list = plane_formats, \ 148 .virt_num_formats = ARRAY_SIZE(plane_formats), \ 149 } 150 151 #define _DMA_SBLK(num, sdma_pri) \ 152 { \ 153 .common = &sdm845_sspp_common, \ 154 .maxdwnscale = SSPP_UNITY_SCALE, \ 155 .maxupscale = SSPP_UNITY_SCALE, \ 156 .smart_dma_priority = sdma_pri, \ 157 .src_blk = {.name = STRCAT("sspp_src_", num), \ 158 .id = DPU_SSPP_SRC, .base = 0x00, .len = 0x150,}, \ 159 .format_list = plane_formats, \ 160 .num_formats = ARRAY_SIZE(plane_formats), \ 161 .virt_format_list = plane_formats, \ 162 .virt_num_formats = ARRAY_SIZE(plane_formats), \ 163 } 164 165 static const struct dpu_sspp_sub_blks sdm845_vig_sblk_0 = _VIG_SBLK("0", 5); 166 static const struct dpu_sspp_sub_blks sdm845_vig_sblk_1 = _VIG_SBLK("1", 6); 167 static const struct dpu_sspp_sub_blks sdm845_vig_sblk_2 = _VIG_SBLK("2", 7); 168 static const struct dpu_sspp_sub_blks sdm845_vig_sblk_3 = _VIG_SBLK("3", 8); 169 170 static const struct dpu_sspp_sub_blks sdm845_dma_sblk_0 = _DMA_SBLK("8", 1); 171 static const struct dpu_sspp_sub_blks sdm845_dma_sblk_1 = _DMA_SBLK("9", 2); 172 static const struct dpu_sspp_sub_blks sdm845_dma_sblk_2 = _DMA_SBLK("10", 3); 173 static const struct dpu_sspp_sub_blks sdm845_dma_sblk_3 = _DMA_SBLK("11", 4); 174 175 #define SSPP_BLK(_name, _id, _base, _features, \ 176 _sblk, _xinid, _type, _clkctrl) \ 177 { \ 178 .name = _name, .id = _id, \ 179 .base = _base, .len = 0x1c8, \ 180 .features = _features, \ 181 .sblk = &_sblk, \ 182 .xin_id = _xinid, \ 183 .type = _type, \ 184 .clk_ctrl = _clkctrl \ 185 } 186 187 static struct dpu_sspp_cfg sdm845_sspp[] = { 188 SSPP_BLK("sspp_0", SSPP_VIG0, 0x4000, VIG_SDM845_MASK, 189 sdm845_vig_sblk_0, 0, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG0), 190 SSPP_BLK("sspp_1", SSPP_VIG1, 0x6000, VIG_SDM845_MASK, 191 sdm845_vig_sblk_1, 4, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG1), 192 SSPP_BLK("sspp_2", SSPP_VIG2, 0x8000, VIG_SDM845_MASK, 193 sdm845_vig_sblk_2, 8, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG2), 194 SSPP_BLK("sspp_3", SSPP_VIG3, 0xa000, VIG_SDM845_MASK, 195 sdm845_vig_sblk_3, 12, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG3), 196 SSPP_BLK("sspp_8", SSPP_DMA0, 0x24000, DMA_SDM845_MASK, 197 sdm845_dma_sblk_0, 1, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA0), 198 SSPP_BLK("sspp_9", SSPP_DMA1, 0x26000, DMA_SDM845_MASK, 199 sdm845_dma_sblk_1, 5, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA1), 200 SSPP_BLK("sspp_10", SSPP_DMA2, 0x28000, DMA_CURSOR_SDM845_MASK, 201 sdm845_dma_sblk_2, 9, SSPP_TYPE_DMA, DPU_CLK_CTRL_CURSOR0), 202 SSPP_BLK("sspp_11", SSPP_DMA3, 0x2a000, DMA_CURSOR_SDM845_MASK, 203 sdm845_dma_sblk_3, 13, SSPP_TYPE_DMA, DPU_CLK_CTRL_CURSOR1), 204 }; 205 206 /************************************************************* 207 * MIXER sub blocks config 208 *************************************************************/ 209 static const struct dpu_lm_sub_blks sdm845_lm_sblk = { 210 .maxwidth = DEFAULT_DPU_OUTPUT_LINE_WIDTH, 211 .maxblendstages = 11, /* excluding base layer */ 212 .blendstage_base = { /* offsets relative to mixer base */ 213 0x20, 0x38, 0x50, 0x68, 0x80, 0x98, 214 0xb0, 0xc8, 0xe0, 0xf8, 0x110 215 }, 216 }; 217 218 #define LM_BLK(_name, _id, _base, _pp, _lmpair) \ 219 { \ 220 .name = _name, .id = _id, \ 221 .base = _base, .len = 0x320, \ 222 .features = MIXER_SDM845_MASK, \ 223 .sblk = &sdm845_lm_sblk, \ 224 .pingpong = _pp, \ 225 .lm_pair_mask = (1 << _lmpair) \ 226 } 227 228 static struct dpu_lm_cfg sdm845_lm[] = { 229 LM_BLK("lm_0", LM_0, 0x44000, PINGPONG_0, LM_1), 230 LM_BLK("lm_1", LM_1, 0x45000, PINGPONG_1, LM_0), 231 LM_BLK("lm_2", LM_2, 0x46000, PINGPONG_2, LM_5), 232 LM_BLK("lm_3", LM_3, 0x0, PINGPONG_MAX, 0), 233 LM_BLK("lm_4", LM_4, 0x0, PINGPONG_MAX, 0), 234 LM_BLK("lm_5", LM_5, 0x49000, PINGPONG_3, LM_2), 235 }; 236 237 /************************************************************* 238 * PINGPONG sub blocks config 239 *************************************************************/ 240 static const struct dpu_pingpong_sub_blks sdm845_pp_sblk_te = { 241 .te2 = {.id = DPU_PINGPONG_TE2, .base = 0x2000, .len = 0x0, 242 .version = 0x1}, 243 .dither = {.id = DPU_PINGPONG_DITHER, .base = 0x30e0, 244 .len = 0x20, .version = 0x10000}, 245 }; 246 247 static const struct dpu_pingpong_sub_blks sdm845_pp_sblk = { 248 .dither = {.id = DPU_PINGPONG_DITHER, .base = 0x30e0, 249 .len = 0x20, .version = 0x10000}, 250 }; 251 252 #define PP_BLK_TE(_name, _id, _base) \ 253 {\ 254 .name = _name, .id = _id, \ 255 .base = _base, .len = 0xd4, \ 256 .features = PINGPONG_SDM845_SPLIT_MASK, \ 257 .sblk = &sdm845_pp_sblk_te \ 258 } 259 #define PP_BLK(_name, _id, _base) \ 260 {\ 261 .name = _name, .id = _id, \ 262 .base = _base, .len = 0xd4, \ 263 .features = PINGPONG_SDM845_MASK, \ 264 .sblk = &sdm845_pp_sblk \ 265 } 266 267 static struct dpu_pingpong_cfg sdm845_pp[] = { 268 PP_BLK_TE("pingpong_0", PINGPONG_0, 0x70000), 269 PP_BLK_TE("pingpong_1", PINGPONG_1, 0x70800), 270 PP_BLK("pingpong_2", PINGPONG_2, 0x71000), 271 PP_BLK("pingpong_3", PINGPONG_3, 0x71800), 272 }; 273 274 /************************************************************* 275 * INTF sub blocks config 276 *************************************************************/ 277 #define INTF_BLK(_name, _id, _base, _type, _ctrl_id) \ 278 {\ 279 .name = _name, .id = _id, \ 280 .base = _base, .len = 0x280, \ 281 .type = _type, \ 282 .controller_id = _ctrl_id, \ 283 .prog_fetch_lines_worst_case = 24 \ 284 } 285 286 static struct dpu_intf_cfg sdm845_intf[] = { 287 INTF_BLK("intf_0", INTF_0, 0x6A000, INTF_DP, 0), 288 INTF_BLK("intf_1", INTF_1, 0x6A800, INTF_DSI, 0), 289 INTF_BLK("intf_2", INTF_2, 0x6B000, INTF_DSI, 1), 290 INTF_BLK("intf_3", INTF_3, 0x6B800, INTF_DP, 1), 291 }; 292 293 /************************************************************* 294 * VBIF sub blocks config 295 *************************************************************/ 296 /* VBIF QOS remap */ 297 static u32 sdm845_rt_pri_lvl[] = {3, 3, 4, 4, 5, 5, 6, 6}; 298 static u32 sdm845_nrt_pri_lvl[] = {3, 3, 3, 3, 3, 3, 3, 3}; 299 300 static struct dpu_vbif_cfg sdm845_vbif[] = { 301 { 302 .name = "vbif_0", .id = VBIF_0, 303 .base = 0, .len = 0x1040, 304 .features = BIT(DPU_VBIF_QOS_REMAP), 305 .xin_halt_timeout = 0x4000, 306 .qos_rt_tbl = { 307 .npriority_lvl = ARRAY_SIZE(sdm845_rt_pri_lvl), 308 .priority_lvl = sdm845_rt_pri_lvl, 309 }, 310 .qos_nrt_tbl = { 311 .npriority_lvl = ARRAY_SIZE(sdm845_nrt_pri_lvl), 312 .priority_lvl = sdm845_nrt_pri_lvl, 313 }, 314 .memtype_count = 14, 315 .memtype = {3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3}, 316 }, 317 }; 318 319 static struct dpu_reg_dma_cfg sdm845_regdma = { 320 .base = 0x0, .version = 0x1, .trigger_sel_off = 0x119c 321 }; 322 323 /************************************************************* 324 * PERF data config 325 *************************************************************/ 326 327 /* SSPP QOS LUTs */ 328 static struct dpu_qos_lut_entry sdm845_qos_linear[] = { 329 {.fl = 4, .lut = 0x357}, 330 {.fl = 5, .lut = 0x3357}, 331 {.fl = 6, .lut = 0x23357}, 332 {.fl = 7, .lut = 0x223357}, 333 {.fl = 8, .lut = 0x2223357}, 334 {.fl = 9, .lut = 0x22223357}, 335 {.fl = 10, .lut = 0x222223357}, 336 {.fl = 11, .lut = 0x2222223357}, 337 {.fl = 12, .lut = 0x22222223357}, 338 {.fl = 13, .lut = 0x222222223357}, 339 {.fl = 14, .lut = 0x1222222223357}, 340 {.fl = 0, .lut = 0x11222222223357} 341 }; 342 343 static struct dpu_qos_lut_entry sdm845_qos_macrotile[] = { 344 {.fl = 10, .lut = 0x344556677}, 345 {.fl = 11, .lut = 0x3344556677}, 346 {.fl = 12, .lut = 0x23344556677}, 347 {.fl = 13, .lut = 0x223344556677}, 348 {.fl = 14, .lut = 0x1223344556677}, 349 {.fl = 0, .lut = 0x112233344556677}, 350 }; 351 352 static struct dpu_qos_lut_entry sdm845_qos_nrt[] = { 353 {.fl = 0, .lut = 0x0}, 354 }; 355 356 static struct dpu_perf_cfg sdm845_perf_data = { 357 .max_bw_low = 6800000, 358 .max_bw_high = 6800000, 359 .min_core_ib = 2400000, 360 .min_llcc_ib = 800000, 361 .min_dram_ib = 800000, 362 .core_ib_ff = "6.0", 363 .core_clk_ff = "1.0", 364 .comp_ratio_rt = 365 "NV12/5/1/1.23 AB24/5/1/1.23 XB24/5/1/1.23", 366 .comp_ratio_nrt = 367 "NV12/5/1/1.25 AB24/5/1/1.25 XB24/5/1/1.25", 368 .undersized_prefill_lines = 2, 369 .xtra_prefill_lines = 2, 370 .dest_scale_prefill_lines = 3, 371 .macrotile_prefill_lines = 4, 372 .yuv_nv12_prefill_lines = 8, 373 .linear_prefill_lines = 1, 374 .downscaling_prefill_lines = 1, 375 .amortizable_threshold = 25, 376 .min_prefill_lines = 24, 377 .danger_lut_tbl = {0xf, 0xffff, 0x0}, 378 .qos_lut_tbl = { 379 {.nentry = ARRAY_SIZE(sdm845_qos_linear), 380 .entries = sdm845_qos_linear 381 }, 382 {.nentry = ARRAY_SIZE(sdm845_qos_macrotile), 383 .entries = sdm845_qos_macrotile 384 }, 385 {.nentry = ARRAY_SIZE(sdm845_qos_nrt), 386 .entries = sdm845_qos_nrt 387 }, 388 }, 389 .cdp_cfg = { 390 {.rd_enable = 1, .wr_enable = 1}, 391 {.rd_enable = 1, .wr_enable = 0} 392 }, 393 }; 394 395 /************************************************************* 396 * Hardware catalog init 397 *************************************************************/ 398 399 /* 400 * sdm845_cfg_init(): populate sdm845 dpu sub-blocks reg offsets 401 * and instance counts. 402 */ 403 static void sdm845_cfg_init(struct dpu_mdss_cfg *dpu_cfg) 404 { 405 *dpu_cfg = (struct dpu_mdss_cfg){ 406 .caps = &sdm845_dpu_caps, 407 .mdp_count = ARRAY_SIZE(sdm845_mdp), 408 .mdp = sdm845_mdp, 409 .ctl_count = ARRAY_SIZE(sdm845_ctl), 410 .ctl = sdm845_ctl, 411 .sspp_count = ARRAY_SIZE(sdm845_sspp), 412 .sspp = sdm845_sspp, 413 .mixer_count = ARRAY_SIZE(sdm845_lm), 414 .mixer = sdm845_lm, 415 .pingpong_count = ARRAY_SIZE(sdm845_pp), 416 .pingpong = sdm845_pp, 417 .intf_count = ARRAY_SIZE(sdm845_intf), 418 .intf = sdm845_intf, 419 .vbif_count = ARRAY_SIZE(sdm845_vbif), 420 .vbif = sdm845_vbif, 421 .reg_dma_count = 1, 422 .dma_cfg = sdm845_regdma, 423 .perf = sdm845_perf_data, 424 }; 425 } 426 427 static struct dpu_mdss_hw_cfg_handler cfg_handler[] = { 428 { .hw_rev = DPU_HW_VER_400, .cfg_init = sdm845_cfg_init}, 429 { .hw_rev = DPU_HW_VER_401, .cfg_init = sdm845_cfg_init}, 430 }; 431 432 void dpu_hw_catalog_deinit(struct dpu_mdss_cfg *dpu_cfg) 433 { 434 kfree(dpu_cfg); 435 } 436 437 struct dpu_mdss_cfg *dpu_hw_catalog_init(u32 hw_rev) 438 { 439 int i; 440 struct dpu_mdss_cfg *dpu_cfg; 441 442 dpu_cfg = kzalloc(sizeof(*dpu_cfg), GFP_KERNEL); 443 if (!dpu_cfg) 444 return ERR_PTR(-ENOMEM); 445 446 for (i = 0; i < ARRAY_SIZE(cfg_handler); i++) { 447 if (cfg_handler[i].hw_rev == hw_rev) { 448 cfg_handler[i].cfg_init(dpu_cfg); 449 dpu_cfg->hwversion = hw_rev; 450 return dpu_cfg; 451 } 452 } 453 454 DPU_ERROR("unsupported chipset id:%X\n", hw_rev); 455 dpu_hw_catalog_deinit(dpu_cfg); 456 return ERR_PTR(-ENODEV); 457 } 458 459