1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. 4 * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. 5 */ 6 #define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__ 7 8 #include "msm_drv.h" 9 #include "dpu_kms.h" 10 #include "dpu_hw_mdss.h" 11 #include "dpu_hw_util.h" 12 13 /* using a file static variables for debugfs access */ 14 static u32 dpu_hw_util_log_mask = DPU_DBG_MASK_NONE; 15 16 /* DPU_SCALER_QSEED3 */ 17 #define QSEED3_HW_VERSION 0x00 18 #define QSEED3_OP_MODE 0x04 19 #define QSEED3_RGB2Y_COEFF 0x08 20 #define QSEED3_PHASE_INIT 0x0C 21 #define QSEED3_PHASE_STEP_Y_H 0x10 22 #define QSEED3_PHASE_STEP_Y_V 0x14 23 #define QSEED3_PHASE_STEP_UV_H 0x18 24 #define QSEED3_PHASE_STEP_UV_V 0x1C 25 #define QSEED3_PRELOAD 0x20 26 #define QSEED3_DE_SHARPEN 0x24 27 #define QSEED3_DE_SHARPEN_CTL 0x28 28 #define QSEED3_DE_SHAPE_CTL 0x2C 29 #define QSEED3_DE_THRESHOLD 0x30 30 #define QSEED3_DE_ADJUST_DATA_0 0x34 31 #define QSEED3_DE_ADJUST_DATA_1 0x38 32 #define QSEED3_DE_ADJUST_DATA_2 0x3C 33 #define QSEED3_SRC_SIZE_Y_RGB_A 0x40 34 #define QSEED3_SRC_SIZE_UV 0x44 35 #define QSEED3_DST_SIZE 0x48 36 #define QSEED3_COEF_LUT_CTRL 0x4C 37 #define QSEED3_COEF_LUT_SWAP_BIT 0 38 #define QSEED3_COEF_LUT_DIR_BIT 1 39 #define QSEED3_COEF_LUT_Y_CIR_BIT 2 40 #define QSEED3_COEF_LUT_UV_CIR_BIT 3 41 #define QSEED3_COEF_LUT_Y_SEP_BIT 4 42 #define QSEED3_COEF_LUT_UV_SEP_BIT 5 43 #define QSEED3_BUFFER_CTRL 0x50 44 #define QSEED3_CLK_CTRL0 0x54 45 #define QSEED3_CLK_CTRL1 0x58 46 #define QSEED3_CLK_STATUS 0x5C 47 #define QSEED3_PHASE_INIT_Y_H 0x90 48 #define QSEED3_PHASE_INIT_Y_V 0x94 49 #define QSEED3_PHASE_INIT_UV_H 0x98 50 #define QSEED3_PHASE_INIT_UV_V 0x9C 51 #define QSEED3_COEF_LUT 0x100 52 #define QSEED3_FILTERS 5 53 #define QSEED3_LUT_REGIONS 4 54 #define QSEED3_CIRCULAR_LUTS 9 55 #define QSEED3_SEPARABLE_LUTS 10 56 #define QSEED3_LUT_SIZE 60 57 #define QSEED3_ENABLE 2 58 #define QSEED3_DIR_LUT_SIZE (200 * sizeof(u32)) 59 #define QSEED3_CIR_LUT_SIZE \ 60 (QSEED3_LUT_SIZE * QSEED3_CIRCULAR_LUTS * sizeof(u32)) 61 #define QSEED3_SEP_LUT_SIZE \ 62 (QSEED3_LUT_SIZE * QSEED3_SEPARABLE_LUTS * sizeof(u32)) 63 64 /* DPU_SCALER_QSEED3LITE */ 65 #define QSEED3LITE_COEF_LUT_Y_SEP_BIT 4 66 #define QSEED3LITE_COEF_LUT_UV_SEP_BIT 5 67 #define QSEED3LITE_COEF_LUT_CTRL 0x4C 68 #define QSEED3LITE_COEF_LUT_SWAP_BIT 0 69 #define QSEED3LITE_DIR_FILTER_WEIGHT 0x60 70 #define QSEED3LITE_FILTERS 2 71 #define QSEED3LITE_SEPARABLE_LUTS 10 72 #define QSEED3LITE_LUT_SIZE 33 73 #define QSEED3LITE_SEP_LUT_SIZE \ 74 (QSEED3LITE_LUT_SIZE * QSEED3LITE_SEPARABLE_LUTS * sizeof(u32)) 75 76 /* QOS_LUT */ 77 #define QOS_DANGER_LUT 0x00 78 #define QOS_SAFE_LUT 0x04 79 #define QOS_CREQ_LUT 0x08 80 #define QOS_QOS_CTRL 0x0C 81 #define QOS_CREQ_LUT_0 0x14 82 #define QOS_CREQ_LUT_1 0x18 83 84 /* QOS_QOS_CTRL */ 85 #define QOS_QOS_CTRL_DANGER_SAFE_EN BIT(0) 86 #define QOS_QOS_CTRL_DANGER_VBLANK_MASK GENMASK(5, 4) 87 #define QOS_QOS_CTRL_VBLANK_EN BIT(16) 88 #define QOS_QOS_CTRL_CREQ_VBLANK_MASK GENMASK(21, 20) 89 90 void dpu_reg_write(struct dpu_hw_blk_reg_map *c, 91 u32 reg_off, 92 u32 val, 93 const char *name) 94 { 95 /* don't need to mutex protect this */ 96 if (c->log_mask & dpu_hw_util_log_mask) 97 DPU_DEBUG_DRIVER("[%s:0x%X] <= 0x%X\n", 98 name, reg_off, val); 99 writel_relaxed(val, c->blk_addr + reg_off); 100 } 101 102 int dpu_reg_read(struct dpu_hw_blk_reg_map *c, u32 reg_off) 103 { 104 return readl_relaxed(c->blk_addr + reg_off); 105 } 106 107 u32 *dpu_hw_util_get_log_mask_ptr(void) 108 { 109 return &dpu_hw_util_log_mask; 110 } 111 112 static void _dpu_hw_setup_scaler3_lut(struct dpu_hw_blk_reg_map *c, 113 struct dpu_hw_scaler3_cfg *scaler3_cfg, u32 offset) 114 { 115 int i, j, filter; 116 int config_lut = 0x0; 117 unsigned long lut_flags; 118 u32 lut_addr, lut_offset, lut_len; 119 u32 *lut[QSEED3_FILTERS] = {NULL, NULL, NULL, NULL, NULL}; 120 static const uint32_t off_tbl[QSEED3_FILTERS][QSEED3_LUT_REGIONS][2] = { 121 {{18, 0x000}, {12, 0x120}, {12, 0x1E0}, {8, 0x2A0} }, 122 {{6, 0x320}, {3, 0x3E0}, {3, 0x440}, {3, 0x4A0} }, 123 {{6, 0x500}, {3, 0x5c0}, {3, 0x620}, {3, 0x680} }, 124 {{6, 0x380}, {3, 0x410}, {3, 0x470}, {3, 0x4d0} }, 125 {{6, 0x560}, {3, 0x5f0}, {3, 0x650}, {3, 0x6b0} }, 126 }; 127 128 lut_flags = (unsigned long) scaler3_cfg->lut_flag; 129 if (test_bit(QSEED3_COEF_LUT_DIR_BIT, &lut_flags) && 130 (scaler3_cfg->dir_len == QSEED3_DIR_LUT_SIZE)) { 131 lut[0] = scaler3_cfg->dir_lut; 132 config_lut = 1; 133 } 134 if (test_bit(QSEED3_COEF_LUT_Y_CIR_BIT, &lut_flags) && 135 (scaler3_cfg->y_rgb_cir_lut_idx < QSEED3_CIRCULAR_LUTS) && 136 (scaler3_cfg->cir_len == QSEED3_CIR_LUT_SIZE)) { 137 lut[1] = scaler3_cfg->cir_lut + 138 scaler3_cfg->y_rgb_cir_lut_idx * QSEED3_LUT_SIZE; 139 config_lut = 1; 140 } 141 if (test_bit(QSEED3_COEF_LUT_UV_CIR_BIT, &lut_flags) && 142 (scaler3_cfg->uv_cir_lut_idx < QSEED3_CIRCULAR_LUTS) && 143 (scaler3_cfg->cir_len == QSEED3_CIR_LUT_SIZE)) { 144 lut[2] = scaler3_cfg->cir_lut + 145 scaler3_cfg->uv_cir_lut_idx * QSEED3_LUT_SIZE; 146 config_lut = 1; 147 } 148 if (test_bit(QSEED3_COEF_LUT_Y_SEP_BIT, &lut_flags) && 149 (scaler3_cfg->y_rgb_sep_lut_idx < QSEED3_SEPARABLE_LUTS) && 150 (scaler3_cfg->sep_len == QSEED3_SEP_LUT_SIZE)) { 151 lut[3] = scaler3_cfg->sep_lut + 152 scaler3_cfg->y_rgb_sep_lut_idx * QSEED3_LUT_SIZE; 153 config_lut = 1; 154 } 155 if (test_bit(QSEED3_COEF_LUT_UV_SEP_BIT, &lut_flags) && 156 (scaler3_cfg->uv_sep_lut_idx < QSEED3_SEPARABLE_LUTS) && 157 (scaler3_cfg->sep_len == QSEED3_SEP_LUT_SIZE)) { 158 lut[4] = scaler3_cfg->sep_lut + 159 scaler3_cfg->uv_sep_lut_idx * QSEED3_LUT_SIZE; 160 config_lut = 1; 161 } 162 163 if (config_lut) { 164 for (filter = 0; filter < QSEED3_FILTERS; filter++) { 165 if (!lut[filter]) 166 continue; 167 lut_offset = 0; 168 for (i = 0; i < QSEED3_LUT_REGIONS; i++) { 169 lut_addr = QSEED3_COEF_LUT + offset 170 + off_tbl[filter][i][1]; 171 lut_len = off_tbl[filter][i][0] << 2; 172 for (j = 0; j < lut_len; j++) { 173 DPU_REG_WRITE(c, 174 lut_addr, 175 (lut[filter])[lut_offset++]); 176 lut_addr += 4; 177 } 178 } 179 } 180 } 181 182 if (test_bit(QSEED3_COEF_LUT_SWAP_BIT, &lut_flags)) 183 DPU_REG_WRITE(c, QSEED3_COEF_LUT_CTRL + offset, BIT(0)); 184 185 } 186 187 static void _dpu_hw_setup_scaler3lite_lut(struct dpu_hw_blk_reg_map *c, 188 struct dpu_hw_scaler3_cfg *scaler3_cfg, u32 offset) 189 { 190 int j, filter; 191 int config_lut = 0x0; 192 unsigned long lut_flags; 193 u32 lut_addr, lut_offset; 194 u32 *lut[QSEED3LITE_FILTERS] = {NULL, NULL}; 195 static const uint32_t off_tbl[QSEED3_FILTERS] = { 0x000, 0x200 }; 196 197 DPU_REG_WRITE(c, QSEED3LITE_DIR_FILTER_WEIGHT + offset, scaler3_cfg->dir_weight); 198 199 if (!scaler3_cfg->sep_lut) 200 return; 201 202 lut_flags = (unsigned long) scaler3_cfg->lut_flag; 203 if (test_bit(QSEED3_COEF_LUT_Y_SEP_BIT, &lut_flags) && 204 (scaler3_cfg->y_rgb_sep_lut_idx < QSEED3LITE_SEPARABLE_LUTS) && 205 (scaler3_cfg->sep_len == QSEED3LITE_SEP_LUT_SIZE)) { 206 lut[0] = scaler3_cfg->sep_lut + 207 scaler3_cfg->y_rgb_sep_lut_idx * QSEED3LITE_LUT_SIZE; 208 config_lut = 1; 209 } 210 if (test_bit(QSEED3_COEF_LUT_UV_SEP_BIT, &lut_flags) && 211 (scaler3_cfg->uv_sep_lut_idx < QSEED3LITE_SEPARABLE_LUTS) && 212 (scaler3_cfg->sep_len == QSEED3LITE_SEP_LUT_SIZE)) { 213 lut[1] = scaler3_cfg->sep_lut + 214 scaler3_cfg->uv_sep_lut_idx * QSEED3LITE_LUT_SIZE; 215 config_lut = 1; 216 } 217 218 if (config_lut) { 219 for (filter = 0; filter < QSEED3LITE_FILTERS; filter++) { 220 if (!lut[filter]) 221 continue; 222 lut_offset = 0; 223 lut_addr = QSEED3_COEF_LUT + offset + off_tbl[filter]; 224 for (j = 0; j < QSEED3LITE_LUT_SIZE; j++) { 225 DPU_REG_WRITE(c, 226 lut_addr, 227 (lut[filter])[lut_offset++]); 228 lut_addr += 4; 229 } 230 } 231 } 232 233 if (test_bit(QSEED3_COEF_LUT_SWAP_BIT, &lut_flags)) 234 DPU_REG_WRITE(c, QSEED3_COEF_LUT_CTRL + offset, BIT(0)); 235 236 } 237 238 static void _dpu_hw_setup_scaler3_de(struct dpu_hw_blk_reg_map *c, 239 struct dpu_hw_scaler3_de_cfg *de_cfg, u32 offset) 240 { 241 u32 sharp_lvl, sharp_ctl, shape_ctl, de_thr; 242 u32 adjust_a, adjust_b, adjust_c; 243 244 if (!de_cfg->enable) 245 return; 246 247 sharp_lvl = (de_cfg->sharpen_level1 & 0x1FF) | 248 ((de_cfg->sharpen_level2 & 0x1FF) << 16); 249 250 sharp_ctl = ((de_cfg->limit & 0xF) << 9) | 251 ((de_cfg->prec_shift & 0x7) << 13) | 252 ((de_cfg->clip & 0x7) << 16); 253 254 shape_ctl = (de_cfg->thr_quiet & 0xFF) | 255 ((de_cfg->thr_dieout & 0x3FF) << 16); 256 257 de_thr = (de_cfg->thr_low & 0x3FF) | 258 ((de_cfg->thr_high & 0x3FF) << 16); 259 260 adjust_a = (de_cfg->adjust_a[0] & 0x3FF) | 261 ((de_cfg->adjust_a[1] & 0x3FF) << 10) | 262 ((de_cfg->adjust_a[2] & 0x3FF) << 20); 263 264 adjust_b = (de_cfg->adjust_b[0] & 0x3FF) | 265 ((de_cfg->adjust_b[1] & 0x3FF) << 10) | 266 ((de_cfg->adjust_b[2] & 0x3FF) << 20); 267 268 adjust_c = (de_cfg->adjust_c[0] & 0x3FF) | 269 ((de_cfg->adjust_c[1] & 0x3FF) << 10) | 270 ((de_cfg->adjust_c[2] & 0x3FF) << 20); 271 272 DPU_REG_WRITE(c, QSEED3_DE_SHARPEN + offset, sharp_lvl); 273 DPU_REG_WRITE(c, QSEED3_DE_SHARPEN_CTL + offset, sharp_ctl); 274 DPU_REG_WRITE(c, QSEED3_DE_SHAPE_CTL + offset, shape_ctl); 275 DPU_REG_WRITE(c, QSEED3_DE_THRESHOLD + offset, de_thr); 276 DPU_REG_WRITE(c, QSEED3_DE_ADJUST_DATA_0 + offset, adjust_a); 277 DPU_REG_WRITE(c, QSEED3_DE_ADJUST_DATA_1 + offset, adjust_b); 278 DPU_REG_WRITE(c, QSEED3_DE_ADJUST_DATA_2 + offset, adjust_c); 279 280 } 281 282 void dpu_hw_setup_scaler3(struct dpu_hw_blk_reg_map *c, 283 struct dpu_hw_scaler3_cfg *scaler3_cfg, 284 u32 scaler_offset, u32 scaler_version, 285 const struct dpu_format *format) 286 { 287 u32 op_mode = 0; 288 u32 phase_init, preload, src_y_rgb, src_uv, dst; 289 290 if (!scaler3_cfg->enable) 291 goto end; 292 293 op_mode |= BIT(0); 294 op_mode |= (scaler3_cfg->y_rgb_filter_cfg & 0x3) << 16; 295 296 if (format && DPU_FORMAT_IS_YUV(format)) { 297 op_mode |= BIT(12); 298 op_mode |= (scaler3_cfg->uv_filter_cfg & 0x3) << 24; 299 } 300 301 op_mode |= (scaler3_cfg->blend_cfg & 1) << 31; 302 op_mode |= (scaler3_cfg->dir_en) ? BIT(4) : 0; 303 304 preload = 305 ((scaler3_cfg->preload_x[0] & 0x7F) << 0) | 306 ((scaler3_cfg->preload_y[0] & 0x7F) << 8) | 307 ((scaler3_cfg->preload_x[1] & 0x7F) << 16) | 308 ((scaler3_cfg->preload_y[1] & 0x7F) << 24); 309 310 src_y_rgb = (scaler3_cfg->src_width[0] & 0x1FFFF) | 311 ((scaler3_cfg->src_height[0] & 0x1FFFF) << 16); 312 313 src_uv = (scaler3_cfg->src_width[1] & 0x1FFFF) | 314 ((scaler3_cfg->src_height[1] & 0x1FFFF) << 16); 315 316 dst = (scaler3_cfg->dst_width & 0x1FFFF) | 317 ((scaler3_cfg->dst_height & 0x1FFFF) << 16); 318 319 if (scaler3_cfg->de.enable) { 320 _dpu_hw_setup_scaler3_de(c, &scaler3_cfg->de, scaler_offset); 321 op_mode |= BIT(8); 322 } 323 324 if (scaler3_cfg->lut_flag) { 325 if (scaler_version < 0x2004) 326 _dpu_hw_setup_scaler3_lut(c, scaler3_cfg, scaler_offset); 327 else 328 _dpu_hw_setup_scaler3lite_lut(c, scaler3_cfg, scaler_offset); 329 } 330 331 if (scaler_version == 0x1002) { 332 phase_init = 333 ((scaler3_cfg->init_phase_x[0] & 0x3F) << 0) | 334 ((scaler3_cfg->init_phase_y[0] & 0x3F) << 8) | 335 ((scaler3_cfg->init_phase_x[1] & 0x3F) << 16) | 336 ((scaler3_cfg->init_phase_y[1] & 0x3F) << 24); 337 DPU_REG_WRITE(c, QSEED3_PHASE_INIT + scaler_offset, phase_init); 338 } else { 339 DPU_REG_WRITE(c, QSEED3_PHASE_INIT_Y_H + scaler_offset, 340 scaler3_cfg->init_phase_x[0] & 0x1FFFFF); 341 DPU_REG_WRITE(c, QSEED3_PHASE_INIT_Y_V + scaler_offset, 342 scaler3_cfg->init_phase_y[0] & 0x1FFFFF); 343 DPU_REG_WRITE(c, QSEED3_PHASE_INIT_UV_H + scaler_offset, 344 scaler3_cfg->init_phase_x[1] & 0x1FFFFF); 345 DPU_REG_WRITE(c, QSEED3_PHASE_INIT_UV_V + scaler_offset, 346 scaler3_cfg->init_phase_y[1] & 0x1FFFFF); 347 } 348 349 DPU_REG_WRITE(c, QSEED3_PHASE_STEP_Y_H + scaler_offset, 350 scaler3_cfg->phase_step_x[0] & 0xFFFFFF); 351 352 DPU_REG_WRITE(c, QSEED3_PHASE_STEP_Y_V + scaler_offset, 353 scaler3_cfg->phase_step_y[0] & 0xFFFFFF); 354 355 DPU_REG_WRITE(c, QSEED3_PHASE_STEP_UV_H + scaler_offset, 356 scaler3_cfg->phase_step_x[1] & 0xFFFFFF); 357 358 DPU_REG_WRITE(c, QSEED3_PHASE_STEP_UV_V + scaler_offset, 359 scaler3_cfg->phase_step_y[1] & 0xFFFFFF); 360 361 DPU_REG_WRITE(c, QSEED3_PRELOAD + scaler_offset, preload); 362 363 DPU_REG_WRITE(c, QSEED3_SRC_SIZE_Y_RGB_A + scaler_offset, src_y_rgb); 364 365 DPU_REG_WRITE(c, QSEED3_SRC_SIZE_UV + scaler_offset, src_uv); 366 367 DPU_REG_WRITE(c, QSEED3_DST_SIZE + scaler_offset, dst); 368 369 end: 370 if (format && !DPU_FORMAT_IS_DX(format)) 371 op_mode |= BIT(14); 372 373 if (format && format->alpha_enable) { 374 op_mode |= BIT(10); 375 if (scaler_version == 0x1002) 376 op_mode |= (scaler3_cfg->alpha_filter_cfg & 0x1) << 30; 377 else 378 op_mode |= (scaler3_cfg->alpha_filter_cfg & 0x3) << 29; 379 } 380 381 DPU_REG_WRITE(c, QSEED3_OP_MODE + scaler_offset, op_mode); 382 } 383 384 void dpu_hw_csc_setup(struct dpu_hw_blk_reg_map *c, 385 u32 csc_reg_off, 386 const struct dpu_csc_cfg *data, bool csc10) 387 { 388 static const u32 matrix_shift = 7; 389 u32 clamp_shift = csc10 ? 16 : 8; 390 u32 val; 391 392 /* matrix coeff - convert S15.16 to S4.9 */ 393 val = ((data->csc_mv[0] >> matrix_shift) & 0x1FFF) | 394 (((data->csc_mv[1] >> matrix_shift) & 0x1FFF) << 16); 395 DPU_REG_WRITE(c, csc_reg_off, val); 396 val = ((data->csc_mv[2] >> matrix_shift) & 0x1FFF) | 397 (((data->csc_mv[3] >> matrix_shift) & 0x1FFF) << 16); 398 DPU_REG_WRITE(c, csc_reg_off + 0x4, val); 399 val = ((data->csc_mv[4] >> matrix_shift) & 0x1FFF) | 400 (((data->csc_mv[5] >> matrix_shift) & 0x1FFF) << 16); 401 DPU_REG_WRITE(c, csc_reg_off + 0x8, val); 402 val = ((data->csc_mv[6] >> matrix_shift) & 0x1FFF) | 403 (((data->csc_mv[7] >> matrix_shift) & 0x1FFF) << 16); 404 DPU_REG_WRITE(c, csc_reg_off + 0xc, val); 405 val = (data->csc_mv[8] >> matrix_shift) & 0x1FFF; 406 DPU_REG_WRITE(c, csc_reg_off + 0x10, val); 407 408 /* Pre clamp */ 409 val = (data->csc_pre_lv[0] << clamp_shift) | data->csc_pre_lv[1]; 410 DPU_REG_WRITE(c, csc_reg_off + 0x14, val); 411 val = (data->csc_pre_lv[2] << clamp_shift) | data->csc_pre_lv[3]; 412 DPU_REG_WRITE(c, csc_reg_off + 0x18, val); 413 val = (data->csc_pre_lv[4] << clamp_shift) | data->csc_pre_lv[5]; 414 DPU_REG_WRITE(c, csc_reg_off + 0x1c, val); 415 416 /* Post clamp */ 417 val = (data->csc_post_lv[0] << clamp_shift) | data->csc_post_lv[1]; 418 DPU_REG_WRITE(c, csc_reg_off + 0x20, val); 419 val = (data->csc_post_lv[2] << clamp_shift) | data->csc_post_lv[3]; 420 DPU_REG_WRITE(c, csc_reg_off + 0x24, val); 421 val = (data->csc_post_lv[4] << clamp_shift) | data->csc_post_lv[5]; 422 DPU_REG_WRITE(c, csc_reg_off + 0x28, val); 423 424 /* Pre-Bias */ 425 DPU_REG_WRITE(c, csc_reg_off + 0x2c, data->csc_pre_bv[0]); 426 DPU_REG_WRITE(c, csc_reg_off + 0x30, data->csc_pre_bv[1]); 427 DPU_REG_WRITE(c, csc_reg_off + 0x34, data->csc_pre_bv[2]); 428 429 /* Post-Bias */ 430 DPU_REG_WRITE(c, csc_reg_off + 0x38, data->csc_post_bv[0]); 431 DPU_REG_WRITE(c, csc_reg_off + 0x3c, data->csc_post_bv[1]); 432 DPU_REG_WRITE(c, csc_reg_off + 0x40, data->csc_post_bv[2]); 433 } 434 435 /** 436 * _dpu_hw_get_qos_lut - get LUT mapping based on fill level 437 * @tbl: Pointer to LUT table 438 * @total_fl: fill level 439 * Return: LUT setting corresponding to the fill level 440 */ 441 u64 _dpu_hw_get_qos_lut(const struct dpu_qos_lut_tbl *tbl, 442 u32 total_fl) 443 { 444 int i; 445 446 if (!tbl || !tbl->nentry || !tbl->entries) 447 return 0; 448 449 for (i = 0; i < tbl->nentry; i++) 450 if (total_fl <= tbl->entries[i].fl) 451 return tbl->entries[i].lut; 452 453 /* if last fl is zero, use as default */ 454 if (!tbl->entries[i-1].fl) 455 return tbl->entries[i-1].lut; 456 457 return 0; 458 } 459 460 void _dpu_hw_setup_qos_lut(struct dpu_hw_blk_reg_map *c, u32 offset, 461 bool qos_8lvl, 462 const struct dpu_hw_qos_cfg *cfg) 463 { 464 DPU_REG_WRITE(c, offset + QOS_DANGER_LUT, cfg->danger_lut); 465 DPU_REG_WRITE(c, offset + QOS_SAFE_LUT, cfg->safe_lut); 466 467 if (qos_8lvl) { 468 DPU_REG_WRITE(c, offset + QOS_CREQ_LUT_0, cfg->creq_lut); 469 DPU_REG_WRITE(c, offset + QOS_CREQ_LUT_1, cfg->creq_lut >> 32); 470 } else { 471 DPU_REG_WRITE(c, offset + QOS_CREQ_LUT, cfg->creq_lut); 472 } 473 474 DPU_REG_WRITE(c, offset + QOS_QOS_CTRL, 475 cfg->danger_safe_en ? QOS_QOS_CTRL_DANGER_SAFE_EN : 0); 476 } 477 478 /* 479 * note: Aside from encoders, input_sel should be set to 0x0 by default 480 */ 481 void dpu_hw_setup_misr(struct dpu_hw_blk_reg_map *c, 482 u32 misr_ctrl_offset, u8 input_sel) 483 { 484 u32 config = 0; 485 486 DPU_REG_WRITE(c, misr_ctrl_offset, MISR_CTRL_STATUS_CLEAR); 487 488 /* Clear old MISR value (in case it's read before a new value is calculated)*/ 489 wmb(); 490 491 config = MISR_FRAME_COUNT | MISR_CTRL_ENABLE | MISR_CTRL_FREE_RUN_MASK | 492 ((input_sel & 0xF) << 24); 493 DPU_REG_WRITE(c, misr_ctrl_offset, config); 494 } 495 496 int dpu_hw_collect_misr(struct dpu_hw_blk_reg_map *c, 497 u32 misr_ctrl_offset, 498 u32 misr_signature_offset, 499 u32 *misr_value) 500 { 501 u32 ctrl = 0; 502 503 if (!misr_value) 504 return -EINVAL; 505 506 ctrl = DPU_REG_READ(c, misr_ctrl_offset); 507 508 if (!(ctrl & MISR_CTRL_ENABLE)) 509 return -ENODATA; 510 511 if (!(ctrl & MISR_CTRL_STATUS)) 512 return -EINVAL; 513 514 *misr_value = DPU_REG_READ(c, misr_signature_offset); 515 516 return 0; 517 } 518 519 #define CDP_ENABLE BIT(0) 520 #define CDP_UBWC_META_ENABLE BIT(1) 521 #define CDP_TILE_AMORTIZE_ENABLE BIT(2) 522 #define CDP_PRELOAD_AHEAD_64 BIT(3) 523 524 void dpu_setup_cdp(struct dpu_hw_blk_reg_map *c, u32 offset, 525 const struct dpu_format *fmt, bool enable) 526 { 527 u32 cdp_cntl = CDP_PRELOAD_AHEAD_64; 528 529 if (enable) 530 cdp_cntl |= CDP_ENABLE; 531 if (DPU_FORMAT_IS_UBWC(fmt)) 532 cdp_cntl |= CDP_UBWC_META_ENABLE; 533 if (DPU_FORMAT_IS_UBWC(fmt) || 534 DPU_FORMAT_IS_TILE(fmt)) 535 cdp_cntl |= CDP_TILE_AMORTIZE_ENABLE; 536 537 DPU_REG_WRITE(c, offset, cdp_cntl); 538 } 539 540 bool dpu_hw_clk_force_ctrl(struct dpu_hw_blk_reg_map *c, 541 const struct dpu_clk_ctrl_reg *clk_ctrl_reg, 542 bool enable) 543 { 544 u32 reg_val, new_val; 545 bool clk_forced_on; 546 547 reg_val = DPU_REG_READ(c, clk_ctrl_reg->reg_off); 548 549 if (enable) 550 new_val = reg_val | BIT(clk_ctrl_reg->bit_off); 551 else 552 new_val = reg_val & ~BIT(clk_ctrl_reg->bit_off); 553 554 DPU_REG_WRITE(c, clk_ctrl_reg->reg_off, new_val); 555 556 clk_forced_on = !(reg_val & BIT(clk_ctrl_reg->bit_off)); 557 558 return clk_forced_on; 559 } 560 561 #define TO_S15D16(_x_)((_x_) << 7) 562 563 const struct dpu_csc_cfg dpu_csc_YUV2RGB_601L = { 564 { 565 /* S15.16 format */ 566 0x00012A00, 0x00000000, 0x00019880, 567 0x00012A00, 0xFFFF9B80, 0xFFFF3000, 568 0x00012A00, 0x00020480, 0x00000000, 569 }, 570 /* signed bias */ 571 { 0xfff0, 0xff80, 0xff80,}, 572 { 0x0, 0x0, 0x0,}, 573 /* unsigned clamp */ 574 { 0x10, 0xeb, 0x10, 0xf0, 0x10, 0xf0,}, 575 { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,}, 576 }; 577 578 const struct dpu_csc_cfg dpu_csc10_YUV2RGB_601L = { 579 { 580 /* S15.16 format */ 581 0x00012A00, 0x00000000, 0x00019880, 582 0x00012A00, 0xFFFF9B80, 0xFFFF3000, 583 0x00012A00, 0x00020480, 0x00000000, 584 }, 585 /* signed bias */ 586 { 0xffc0, 0xfe00, 0xfe00,}, 587 { 0x0, 0x0, 0x0,}, 588 /* unsigned clamp */ 589 { 0x40, 0x3ac, 0x40, 0x3c0, 0x40, 0x3c0,}, 590 { 0x00, 0x3ff, 0x00, 0x3ff, 0x00, 0x3ff,}, 591 }; 592 593 const struct dpu_csc_cfg dpu_csc10_rgb2yuv_601l = { 594 { 595 TO_S15D16(0x0083), TO_S15D16(0x0102), TO_S15D16(0x0032), 596 TO_S15D16(0x1fb5), TO_S15D16(0x1f6c), TO_S15D16(0x00e1), 597 TO_S15D16(0x00e1), TO_S15D16(0x1f45), TO_S15D16(0x1fdc) 598 }, 599 { 0x00, 0x00, 0x00 }, 600 { 0x0040, 0x0200, 0x0200 }, 601 { 0x000, 0x3ff, 0x000, 0x3ff, 0x000, 0x3ff }, 602 { 0x040, 0x3ac, 0x040, 0x3c0, 0x040, 0x3c0 }, 603 }; 604