root/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. _sspp_subblk_offset
  2. dpu_hw_sspp_setup_multirect
  3. _sspp_setup_opmode
  4. _sspp_setup_csc10_opmode
  5. dpu_hw_sspp_setup_format
  6. dpu_hw_sspp_setup_pe_config
  7. _dpu_hw_sspp_setup_scaler3
  8. _dpu_hw_sspp_get_scaler3_ver
  9. dpu_hw_sspp_setup_rects
  10. dpu_hw_sspp_setup_sourceaddress
  11. dpu_hw_sspp_setup_csc
  12. dpu_hw_sspp_setup_solidfill
  13. dpu_hw_sspp_setup_danger_safe_lut
  14. dpu_hw_sspp_setup_creq_lut
  15. dpu_hw_sspp_setup_qos_ctrl
  16. dpu_hw_sspp_setup_cdp
  17. _setup_layer_ops
  18. _sspp_offset
  19. dpu_hw_sspp_init
  20. dpu_hw_sspp_destroy

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
   3  */
   4 
   5 #include "dpu_hwio.h"
   6 #include "dpu_hw_catalog.h"
   7 #include "dpu_hw_lm.h"
   8 #include "dpu_hw_sspp.h"
   9 #include "dpu_kms.h"
  10 
  11 #define DPU_FETCH_CONFIG_RESET_VALUE   0x00000087
  12 
  13 /* DPU_SSPP_SRC */
  14 #define SSPP_SRC_SIZE                      0x00
  15 #define SSPP_SRC_XY                        0x08
  16 #define SSPP_OUT_SIZE                      0x0c
  17 #define SSPP_OUT_XY                        0x10
  18 #define SSPP_SRC0_ADDR                     0x14
  19 #define SSPP_SRC1_ADDR                     0x18
  20 #define SSPP_SRC2_ADDR                     0x1C
  21 #define SSPP_SRC3_ADDR                     0x20
  22 #define SSPP_SRC_YSTRIDE0                  0x24
  23 #define SSPP_SRC_YSTRIDE1                  0x28
  24 #define SSPP_SRC_FORMAT                    0x30
  25 #define SSPP_SRC_UNPACK_PATTERN            0x34
  26 #define SSPP_SRC_OP_MODE                   0x38
  27 
  28 /* SSPP_MULTIRECT*/
  29 #define SSPP_SRC_SIZE_REC1                 0x16C
  30 #define SSPP_SRC_XY_REC1                   0x168
  31 #define SSPP_OUT_SIZE_REC1                 0x160
  32 #define SSPP_OUT_XY_REC1                   0x164
  33 #define SSPP_SRC_FORMAT_REC1               0x174
  34 #define SSPP_SRC_UNPACK_PATTERN_REC1       0x178
  35 #define SSPP_SRC_OP_MODE_REC1              0x17C
  36 #define SSPP_MULTIRECT_OPMODE              0x170
  37 #define SSPP_SRC_CONSTANT_COLOR_REC1       0x180
  38 #define SSPP_EXCL_REC_SIZE_REC1            0x184
  39 #define SSPP_EXCL_REC_XY_REC1              0x188
  40 
  41 #define MDSS_MDP_OP_DEINTERLACE            BIT(22)
  42 #define MDSS_MDP_OP_DEINTERLACE_ODD        BIT(23)
  43 #define MDSS_MDP_OP_IGC_ROM_1              BIT(18)
  44 #define MDSS_MDP_OP_IGC_ROM_0              BIT(17)
  45 #define MDSS_MDP_OP_IGC_EN                 BIT(16)
  46 #define MDSS_MDP_OP_FLIP_UD                BIT(14)
  47 #define MDSS_MDP_OP_FLIP_LR                BIT(13)
  48 #define MDSS_MDP_OP_BWC_EN                 BIT(0)
  49 #define MDSS_MDP_OP_PE_OVERRIDE            BIT(31)
  50 #define MDSS_MDP_OP_BWC_LOSSLESS           (0 << 1)
  51 #define MDSS_MDP_OP_BWC_Q_HIGH             (1 << 1)
  52 #define MDSS_MDP_OP_BWC_Q_MED              (2 << 1)
  53 
  54 #define SSPP_SRC_CONSTANT_COLOR            0x3c
  55 #define SSPP_EXCL_REC_CTL                  0x40
  56 #define SSPP_UBWC_STATIC_CTRL              0x44
  57 #define SSPP_FETCH_CONFIG                  0x048
  58 #define SSPP_DANGER_LUT                    0x60
  59 #define SSPP_SAFE_LUT                      0x64
  60 #define SSPP_CREQ_LUT                      0x68
  61 #define SSPP_QOS_CTRL                      0x6C
  62 #define SSPP_DECIMATION_CONFIG             0xB4
  63 #define SSPP_SRC_ADDR_SW_STATUS            0x70
  64 #define SSPP_CREQ_LUT_0                    0x74
  65 #define SSPP_CREQ_LUT_1                    0x78
  66 #define SSPP_SW_PIX_EXT_C0_LR              0x100
  67 #define SSPP_SW_PIX_EXT_C0_TB              0x104
  68 #define SSPP_SW_PIX_EXT_C0_REQ_PIXELS      0x108
  69 #define SSPP_SW_PIX_EXT_C1C2_LR            0x110
  70 #define SSPP_SW_PIX_EXT_C1C2_TB            0x114
  71 #define SSPP_SW_PIX_EXT_C1C2_REQ_PIXELS    0x118
  72 #define SSPP_SW_PIX_EXT_C3_LR              0x120
  73 #define SSPP_SW_PIX_EXT_C3_TB              0x124
  74 #define SSPP_SW_PIX_EXT_C3_REQ_PIXELS      0x128
  75 #define SSPP_TRAFFIC_SHAPER                0x130
  76 #define SSPP_CDP_CNTL                      0x134
  77 #define SSPP_UBWC_ERROR_STATUS             0x138
  78 #define SSPP_TRAFFIC_SHAPER_PREFILL        0x150
  79 #define SSPP_TRAFFIC_SHAPER_REC1_PREFILL   0x154
  80 #define SSPP_TRAFFIC_SHAPER_REC1           0x158
  81 #define SSPP_EXCL_REC_SIZE                 0x1B4
  82 #define SSPP_EXCL_REC_XY                   0x1B8
  83 #define SSPP_VIG_OP_MODE                   0x0
  84 #define SSPP_VIG_CSC_10_OP_MODE            0x0
  85 #define SSPP_TRAFFIC_SHAPER_BPC_MAX        0xFF
  86 
  87 /* SSPP_QOS_CTRL */
  88 #define SSPP_QOS_CTRL_VBLANK_EN            BIT(16)
  89 #define SSPP_QOS_CTRL_DANGER_SAFE_EN       BIT(0)
  90 #define SSPP_QOS_CTRL_DANGER_VBLANK_MASK   0x3
  91 #define SSPP_QOS_CTRL_DANGER_VBLANK_OFF    4
  92 #define SSPP_QOS_CTRL_CREQ_VBLANK_MASK     0x3
  93 #define SSPP_QOS_CTRL_CREQ_VBLANK_OFF      20
  94 
  95 /* DPU_SSPP_SCALER_QSEED2 */
  96 #define SCALE_CONFIG                       0x04
  97 #define COMP0_3_PHASE_STEP_X               0x10
  98 #define COMP0_3_PHASE_STEP_Y               0x14
  99 #define COMP1_2_PHASE_STEP_X               0x18
 100 #define COMP1_2_PHASE_STEP_Y               0x1c
 101 #define COMP0_3_INIT_PHASE_X               0x20
 102 #define COMP0_3_INIT_PHASE_Y               0x24
 103 #define COMP1_2_INIT_PHASE_X               0x28
 104 #define COMP1_2_INIT_PHASE_Y               0x2C
 105 #define VIG_0_QSEED2_SHARP                 0x30
 106 
 107 /*
 108  * Definitions for ViG op modes
 109  */
 110 #define VIG_OP_CSC_DST_DATAFMT BIT(19)
 111 #define VIG_OP_CSC_SRC_DATAFMT BIT(18)
 112 #define VIG_OP_CSC_EN          BIT(17)
 113 #define VIG_OP_MEM_PROT_CONT   BIT(15)
 114 #define VIG_OP_MEM_PROT_VAL    BIT(14)
 115 #define VIG_OP_MEM_PROT_SAT    BIT(13)
 116 #define VIG_OP_MEM_PROT_HUE    BIT(12)
 117 #define VIG_OP_HIST            BIT(8)
 118 #define VIG_OP_SKY_COL         BIT(7)
 119 #define VIG_OP_FOIL            BIT(6)
 120 #define VIG_OP_SKIN_COL        BIT(5)
 121 #define VIG_OP_PA_EN           BIT(4)
 122 #define VIG_OP_PA_SAT_ZERO_EXP BIT(2)
 123 #define VIG_OP_MEM_PROT_BLEND  BIT(1)
 124 
 125 /*
 126  * Definitions for CSC 10 op modes
 127  */
 128 #define VIG_CSC_10_SRC_DATAFMT BIT(1)
 129 #define VIG_CSC_10_EN          BIT(0)
 130 #define CSC_10BIT_OFFSET       4
 131 
 132 /* traffic shaper clock in Hz */
 133 #define TS_CLK                  19200000
 134 
 135 static int _sspp_subblk_offset(struct dpu_hw_pipe *ctx,
 136                 int s_id,
 137                 u32 *idx)
 138 {
 139         int rc = 0;
 140         const struct dpu_sspp_sub_blks *sblk = ctx->cap->sblk;
 141 
 142         if (!ctx)
 143                 return -EINVAL;
 144 
 145         switch (s_id) {
 146         case DPU_SSPP_SRC:
 147                 *idx = sblk->src_blk.base;
 148                 break;
 149         case DPU_SSPP_SCALER_QSEED2:
 150         case DPU_SSPP_SCALER_QSEED3:
 151         case DPU_SSPP_SCALER_RGB:
 152                 *idx = sblk->scaler_blk.base;
 153                 break;
 154         case DPU_SSPP_CSC:
 155         case DPU_SSPP_CSC_10BIT:
 156                 *idx = sblk->csc_blk.base;
 157                 break;
 158         default:
 159                 rc = -EINVAL;
 160         }
 161 
 162         return rc;
 163 }
 164 
 165 static void dpu_hw_sspp_setup_multirect(struct dpu_hw_pipe *ctx,
 166                 enum dpu_sspp_multirect_index index,
 167                 enum dpu_sspp_multirect_mode mode)
 168 {
 169         u32 mode_mask;
 170         u32 idx;
 171 
 172         if (_sspp_subblk_offset(ctx, DPU_SSPP_SRC, &idx))
 173                 return;
 174 
 175         if (index == DPU_SSPP_RECT_SOLO) {
 176                 /**
 177                  * if rect index is RECT_SOLO, we cannot expect a
 178                  * virtual plane sharing the same SSPP id. So we go
 179                  * and disable multirect
 180                  */
 181                 mode_mask = 0;
 182         } else {
 183                 mode_mask = DPU_REG_READ(&ctx->hw, SSPP_MULTIRECT_OPMODE + idx);
 184                 mode_mask |= index;
 185                 if (mode == DPU_SSPP_MULTIRECT_TIME_MX)
 186                         mode_mask |= BIT(2);
 187                 else
 188                         mode_mask &= ~BIT(2);
 189         }
 190 
 191         DPU_REG_WRITE(&ctx->hw, SSPP_MULTIRECT_OPMODE + idx, mode_mask);
 192 }
 193 
 194 static void _sspp_setup_opmode(struct dpu_hw_pipe *ctx,
 195                 u32 mask, u8 en)
 196 {
 197         u32 idx;
 198         u32 opmode;
 199 
 200         if (!test_bit(DPU_SSPP_SCALER_QSEED2, &ctx->cap->features) ||
 201                 _sspp_subblk_offset(ctx, DPU_SSPP_SCALER_QSEED2, &idx) ||
 202                 !test_bit(DPU_SSPP_CSC, &ctx->cap->features))
 203                 return;
 204 
 205         opmode = DPU_REG_READ(&ctx->hw, SSPP_VIG_OP_MODE + idx);
 206 
 207         if (en)
 208                 opmode |= mask;
 209         else
 210                 opmode &= ~mask;
 211 
 212         DPU_REG_WRITE(&ctx->hw, SSPP_VIG_OP_MODE + idx, opmode);
 213 }
 214 
 215 static void _sspp_setup_csc10_opmode(struct dpu_hw_pipe *ctx,
 216                 u32 mask, u8 en)
 217 {
 218         u32 idx;
 219         u32 opmode;
 220 
 221         if (_sspp_subblk_offset(ctx, DPU_SSPP_CSC_10BIT, &idx))
 222                 return;
 223 
 224         opmode = DPU_REG_READ(&ctx->hw, SSPP_VIG_CSC_10_OP_MODE + idx);
 225         if (en)
 226                 opmode |= mask;
 227         else
 228                 opmode &= ~mask;
 229 
 230         DPU_REG_WRITE(&ctx->hw, SSPP_VIG_CSC_10_OP_MODE + idx, opmode);
 231 }
 232 
 233 /**
 234  * Setup source pixel format, flip,
 235  */
 236 static void dpu_hw_sspp_setup_format(struct dpu_hw_pipe *ctx,
 237                 const struct dpu_format *fmt, u32 flags,
 238                 enum dpu_sspp_multirect_index rect_mode)
 239 {
 240         struct dpu_hw_blk_reg_map *c;
 241         u32 chroma_samp, unpack, src_format;
 242         u32 opmode = 0;
 243         u32 fast_clear = 0;
 244         u32 op_mode_off, unpack_pat_off, format_off;
 245         u32 idx;
 246 
 247         if (_sspp_subblk_offset(ctx, DPU_SSPP_SRC, &idx) || !fmt)
 248                 return;
 249 
 250         if (rect_mode == DPU_SSPP_RECT_SOLO || rect_mode == DPU_SSPP_RECT_0) {
 251                 op_mode_off = SSPP_SRC_OP_MODE;
 252                 unpack_pat_off = SSPP_SRC_UNPACK_PATTERN;
 253                 format_off = SSPP_SRC_FORMAT;
 254         } else {
 255                 op_mode_off = SSPP_SRC_OP_MODE_REC1;
 256                 unpack_pat_off = SSPP_SRC_UNPACK_PATTERN_REC1;
 257                 format_off = SSPP_SRC_FORMAT_REC1;
 258         }
 259 
 260         c = &ctx->hw;
 261         opmode = DPU_REG_READ(c, op_mode_off + idx);
 262         opmode &= ~(MDSS_MDP_OP_FLIP_LR | MDSS_MDP_OP_FLIP_UD |
 263                         MDSS_MDP_OP_BWC_EN | MDSS_MDP_OP_PE_OVERRIDE);
 264 
 265         if (flags & DPU_SSPP_FLIP_LR)
 266                 opmode |= MDSS_MDP_OP_FLIP_LR;
 267         if (flags & DPU_SSPP_FLIP_UD)
 268                 opmode |= MDSS_MDP_OP_FLIP_UD;
 269 
 270         chroma_samp = fmt->chroma_sample;
 271         if (flags & DPU_SSPP_SOURCE_ROTATED_90) {
 272                 if (chroma_samp == DPU_CHROMA_H2V1)
 273                         chroma_samp = DPU_CHROMA_H1V2;
 274                 else if (chroma_samp == DPU_CHROMA_H1V2)
 275                         chroma_samp = DPU_CHROMA_H2V1;
 276         }
 277 
 278         src_format = (chroma_samp << 23) | (fmt->fetch_planes << 19) |
 279                 (fmt->bits[C3_ALPHA] << 6) | (fmt->bits[C2_R_Cr] << 4) |
 280                 (fmt->bits[C1_B_Cb] << 2) | (fmt->bits[C0_G_Y] << 0);
 281 
 282         if (flags & DPU_SSPP_ROT_90)
 283                 src_format |= BIT(11); /* ROT90 */
 284 
 285         if (fmt->alpha_enable && fmt->fetch_planes == DPU_PLANE_INTERLEAVED)
 286                 src_format |= BIT(8); /* SRCC3_EN */
 287 
 288         if (flags & DPU_SSPP_SOLID_FILL)
 289                 src_format |= BIT(22);
 290 
 291         unpack = (fmt->element[3] << 24) | (fmt->element[2] << 16) |
 292                 (fmt->element[1] << 8) | (fmt->element[0] << 0);
 293         src_format |= ((fmt->unpack_count - 1) << 12) |
 294                 (fmt->unpack_tight << 17) |
 295                 (fmt->unpack_align_msb << 18) |
 296                 ((fmt->bpp - 1) << 9);
 297 
 298         if (fmt->fetch_mode != DPU_FETCH_LINEAR) {
 299                 if (DPU_FORMAT_IS_UBWC(fmt))
 300                         opmode |= MDSS_MDP_OP_BWC_EN;
 301                 src_format |= (fmt->fetch_mode & 3) << 30; /*FRAME_FORMAT */
 302                 DPU_REG_WRITE(c, SSPP_FETCH_CONFIG,
 303                         DPU_FETCH_CONFIG_RESET_VALUE |
 304                         ctx->mdp->highest_bank_bit << 18);
 305                 if (IS_UBWC_20_SUPPORTED(ctx->catalog->caps->ubwc_version)) {
 306                         fast_clear = fmt->alpha_enable ? BIT(31) : 0;
 307                         DPU_REG_WRITE(c, SSPP_UBWC_STATIC_CTRL,
 308                                         fast_clear | (ctx->mdp->ubwc_swizzle) |
 309                                         (ctx->mdp->highest_bank_bit << 4));
 310                 }
 311         }
 312 
 313         opmode |= MDSS_MDP_OP_PE_OVERRIDE;
 314 
 315         /* if this is YUV pixel format, enable CSC */
 316         if (DPU_FORMAT_IS_YUV(fmt))
 317                 src_format |= BIT(15);
 318 
 319         if (DPU_FORMAT_IS_DX(fmt))
 320                 src_format |= BIT(14);
 321 
 322         /* update scaler opmode, if appropriate */
 323         if (test_bit(DPU_SSPP_CSC, &ctx->cap->features))
 324                 _sspp_setup_opmode(ctx, VIG_OP_CSC_EN | VIG_OP_CSC_SRC_DATAFMT,
 325                         DPU_FORMAT_IS_YUV(fmt));
 326         else if (test_bit(DPU_SSPP_CSC_10BIT, &ctx->cap->features))
 327                 _sspp_setup_csc10_opmode(ctx,
 328                         VIG_CSC_10_EN | VIG_CSC_10_SRC_DATAFMT,
 329                         DPU_FORMAT_IS_YUV(fmt));
 330 
 331         DPU_REG_WRITE(c, format_off + idx, src_format);
 332         DPU_REG_WRITE(c, unpack_pat_off + idx, unpack);
 333         DPU_REG_WRITE(c, op_mode_off + idx, opmode);
 334 
 335         /* clear previous UBWC error */
 336         DPU_REG_WRITE(c, SSPP_UBWC_ERROR_STATUS + idx, BIT(31));
 337 }
 338 
 339 static void dpu_hw_sspp_setup_pe_config(struct dpu_hw_pipe *ctx,
 340                 struct dpu_hw_pixel_ext *pe_ext)
 341 {
 342         struct dpu_hw_blk_reg_map *c;
 343         u8 color;
 344         u32 lr_pe[4], tb_pe[4], tot_req_pixels[4];
 345         const u32 bytemask = 0xff;
 346         const u32 shortmask = 0xffff;
 347         u32 idx;
 348 
 349         if (_sspp_subblk_offset(ctx, DPU_SSPP_SRC, &idx) || !pe_ext)
 350                 return;
 351 
 352         c = &ctx->hw;
 353 
 354         /* program SW pixel extension override for all pipes*/
 355         for (color = 0; color < DPU_MAX_PLANES; color++) {
 356                 /* color 2 has the same set of registers as color 1 */
 357                 if (color == 2)
 358                         continue;
 359 
 360                 lr_pe[color] = ((pe_ext->right_ftch[color] & bytemask) << 24)|
 361                         ((pe_ext->right_rpt[color] & bytemask) << 16)|
 362                         ((pe_ext->left_ftch[color] & bytemask) << 8)|
 363                         (pe_ext->left_rpt[color] & bytemask);
 364 
 365                 tb_pe[color] = ((pe_ext->btm_ftch[color] & bytemask) << 24)|
 366                         ((pe_ext->btm_rpt[color] & bytemask) << 16)|
 367                         ((pe_ext->top_ftch[color] & bytemask) << 8)|
 368                         (pe_ext->top_rpt[color] & bytemask);
 369 
 370                 tot_req_pixels[color] = (((pe_ext->roi_h[color] +
 371                         pe_ext->num_ext_pxls_top[color] +
 372                         pe_ext->num_ext_pxls_btm[color]) & shortmask) << 16) |
 373                         ((pe_ext->roi_w[color] +
 374                         pe_ext->num_ext_pxls_left[color] +
 375                         pe_ext->num_ext_pxls_right[color]) & shortmask);
 376         }
 377 
 378         /* color 0 */
 379         DPU_REG_WRITE(c, SSPP_SW_PIX_EXT_C0_LR + idx, lr_pe[0]);
 380         DPU_REG_WRITE(c, SSPP_SW_PIX_EXT_C0_TB + idx, tb_pe[0]);
 381         DPU_REG_WRITE(c, SSPP_SW_PIX_EXT_C0_REQ_PIXELS + idx,
 382                         tot_req_pixels[0]);
 383 
 384         /* color 1 and color 2 */
 385         DPU_REG_WRITE(c, SSPP_SW_PIX_EXT_C1C2_LR + idx, lr_pe[1]);
 386         DPU_REG_WRITE(c, SSPP_SW_PIX_EXT_C1C2_TB + idx, tb_pe[1]);
 387         DPU_REG_WRITE(c, SSPP_SW_PIX_EXT_C1C2_REQ_PIXELS + idx,
 388                         tot_req_pixels[1]);
 389 
 390         /* color 3 */
 391         DPU_REG_WRITE(c, SSPP_SW_PIX_EXT_C3_LR + idx, lr_pe[3]);
 392         DPU_REG_WRITE(c, SSPP_SW_PIX_EXT_C3_TB + idx, lr_pe[3]);
 393         DPU_REG_WRITE(c, SSPP_SW_PIX_EXT_C3_REQ_PIXELS + idx,
 394                         tot_req_pixels[3]);
 395 }
 396 
 397 static void _dpu_hw_sspp_setup_scaler3(struct dpu_hw_pipe *ctx,
 398                 struct dpu_hw_pipe_cfg *sspp,
 399                 struct dpu_hw_pixel_ext *pe,
 400                 void *scaler_cfg)
 401 {
 402         u32 idx;
 403         struct dpu_hw_scaler3_cfg *scaler3_cfg = scaler_cfg;
 404 
 405         (void)pe;
 406         if (_sspp_subblk_offset(ctx, DPU_SSPP_SCALER_QSEED3, &idx) || !sspp
 407                 || !scaler3_cfg || !ctx || !ctx->cap || !ctx->cap->sblk)
 408                 return;
 409 
 410         dpu_hw_setup_scaler3(&ctx->hw, scaler3_cfg, idx,
 411                         ctx->cap->sblk->scaler_blk.version,
 412                         sspp->layout.format);
 413 }
 414 
 415 static u32 _dpu_hw_sspp_get_scaler3_ver(struct dpu_hw_pipe *ctx)
 416 {
 417         u32 idx;
 418 
 419         if (!ctx || _sspp_subblk_offset(ctx, DPU_SSPP_SCALER_QSEED3, &idx))
 420                 return 0;
 421 
 422         return dpu_hw_get_scaler3_ver(&ctx->hw, idx);
 423 }
 424 
 425 /**
 426  * dpu_hw_sspp_setup_rects()
 427  */
 428 static void dpu_hw_sspp_setup_rects(struct dpu_hw_pipe *ctx,
 429                 struct dpu_hw_pipe_cfg *cfg,
 430                 enum dpu_sspp_multirect_index rect_index)
 431 {
 432         struct dpu_hw_blk_reg_map *c;
 433         u32 src_size, src_xy, dst_size, dst_xy, ystride0, ystride1;
 434         u32 src_size_off, src_xy_off, out_size_off, out_xy_off;
 435         u32 idx;
 436 
 437         if (_sspp_subblk_offset(ctx, DPU_SSPP_SRC, &idx) || !cfg)
 438                 return;
 439 
 440         c = &ctx->hw;
 441 
 442         if (rect_index == DPU_SSPP_RECT_SOLO || rect_index == DPU_SSPP_RECT_0) {
 443                 src_size_off = SSPP_SRC_SIZE;
 444                 src_xy_off = SSPP_SRC_XY;
 445                 out_size_off = SSPP_OUT_SIZE;
 446                 out_xy_off = SSPP_OUT_XY;
 447         } else {
 448                 src_size_off = SSPP_SRC_SIZE_REC1;
 449                 src_xy_off = SSPP_SRC_XY_REC1;
 450                 out_size_off = SSPP_OUT_SIZE_REC1;
 451                 out_xy_off = SSPP_OUT_XY_REC1;
 452         }
 453 
 454 
 455         /* src and dest rect programming */
 456         src_xy = (cfg->src_rect.y1 << 16) | cfg->src_rect.x1;
 457         src_size = (drm_rect_height(&cfg->src_rect) << 16) |
 458                    drm_rect_width(&cfg->src_rect);
 459         dst_xy = (cfg->dst_rect.y1 << 16) | cfg->dst_rect.x1;
 460         dst_size = (drm_rect_height(&cfg->dst_rect) << 16) |
 461                 drm_rect_width(&cfg->dst_rect);
 462 
 463         if (rect_index == DPU_SSPP_RECT_SOLO) {
 464                 ystride0 = (cfg->layout.plane_pitch[0]) |
 465                         (cfg->layout.plane_pitch[1] << 16);
 466                 ystride1 = (cfg->layout.plane_pitch[2]) |
 467                         (cfg->layout.plane_pitch[3] << 16);
 468         } else {
 469                 ystride0 = DPU_REG_READ(c, SSPP_SRC_YSTRIDE0 + idx);
 470                 ystride1 = DPU_REG_READ(c, SSPP_SRC_YSTRIDE1 + idx);
 471 
 472                 if (rect_index == DPU_SSPP_RECT_0) {
 473                         ystride0 = (ystride0 & 0xFFFF0000) |
 474                                 (cfg->layout.plane_pitch[0] & 0x0000FFFF);
 475                         ystride1 = (ystride1 & 0xFFFF0000)|
 476                                 (cfg->layout.plane_pitch[2] & 0x0000FFFF);
 477                 } else {
 478                         ystride0 = (ystride0 & 0x0000FFFF) |
 479                                 ((cfg->layout.plane_pitch[0] << 16) &
 480                                  0xFFFF0000);
 481                         ystride1 = (ystride1 & 0x0000FFFF) |
 482                                 ((cfg->layout.plane_pitch[2] << 16) &
 483                                  0xFFFF0000);
 484                 }
 485         }
 486 
 487         /* rectangle register programming */
 488         DPU_REG_WRITE(c, src_size_off + idx, src_size);
 489         DPU_REG_WRITE(c, src_xy_off + idx, src_xy);
 490         DPU_REG_WRITE(c, out_size_off + idx, dst_size);
 491         DPU_REG_WRITE(c, out_xy_off + idx, dst_xy);
 492 
 493         DPU_REG_WRITE(c, SSPP_SRC_YSTRIDE0 + idx, ystride0);
 494         DPU_REG_WRITE(c, SSPP_SRC_YSTRIDE1 + idx, ystride1);
 495 }
 496 
 497 static void dpu_hw_sspp_setup_sourceaddress(struct dpu_hw_pipe *ctx,
 498                 struct dpu_hw_pipe_cfg *cfg,
 499                 enum dpu_sspp_multirect_index rect_mode)
 500 {
 501         int i;
 502         u32 idx;
 503 
 504         if (_sspp_subblk_offset(ctx, DPU_SSPP_SRC, &idx))
 505                 return;
 506 
 507         if (rect_mode == DPU_SSPP_RECT_SOLO) {
 508                 for (i = 0; i < ARRAY_SIZE(cfg->layout.plane_addr); i++)
 509                         DPU_REG_WRITE(&ctx->hw, SSPP_SRC0_ADDR + idx + i * 0x4,
 510                                         cfg->layout.plane_addr[i]);
 511         } else if (rect_mode == DPU_SSPP_RECT_0) {
 512                 DPU_REG_WRITE(&ctx->hw, SSPP_SRC0_ADDR + idx,
 513                                 cfg->layout.plane_addr[0]);
 514                 DPU_REG_WRITE(&ctx->hw, SSPP_SRC2_ADDR + idx,
 515                                 cfg->layout.plane_addr[2]);
 516         } else {
 517                 DPU_REG_WRITE(&ctx->hw, SSPP_SRC1_ADDR + idx,
 518                                 cfg->layout.plane_addr[0]);
 519                 DPU_REG_WRITE(&ctx->hw, SSPP_SRC3_ADDR + idx,
 520                                 cfg->layout.plane_addr[2]);
 521         }
 522 }
 523 
 524 static void dpu_hw_sspp_setup_csc(struct dpu_hw_pipe *ctx,
 525                 struct dpu_csc_cfg *data)
 526 {
 527         u32 idx;
 528         bool csc10 = false;
 529 
 530         if (_sspp_subblk_offset(ctx, DPU_SSPP_CSC, &idx) || !data)
 531                 return;
 532 
 533         if (test_bit(DPU_SSPP_CSC_10BIT, &ctx->cap->features)) {
 534                 idx += CSC_10BIT_OFFSET;
 535                 csc10 = true;
 536         }
 537 
 538         dpu_hw_csc_setup(&ctx->hw, idx, data, csc10);
 539 }
 540 
 541 static void dpu_hw_sspp_setup_solidfill(struct dpu_hw_pipe *ctx, u32 color, enum
 542                 dpu_sspp_multirect_index rect_index)
 543 {
 544         u32 idx;
 545 
 546         if (_sspp_subblk_offset(ctx, DPU_SSPP_SRC, &idx))
 547                 return;
 548 
 549         if (rect_index == DPU_SSPP_RECT_SOLO || rect_index == DPU_SSPP_RECT_0)
 550                 DPU_REG_WRITE(&ctx->hw, SSPP_SRC_CONSTANT_COLOR + idx, color);
 551         else
 552                 DPU_REG_WRITE(&ctx->hw, SSPP_SRC_CONSTANT_COLOR_REC1 + idx,
 553                                 color);
 554 }
 555 
 556 static void dpu_hw_sspp_setup_danger_safe_lut(struct dpu_hw_pipe *ctx,
 557                 struct dpu_hw_pipe_qos_cfg *cfg)
 558 {
 559         u32 idx;
 560 
 561         if (_sspp_subblk_offset(ctx, DPU_SSPP_SRC, &idx))
 562                 return;
 563 
 564         DPU_REG_WRITE(&ctx->hw, SSPP_DANGER_LUT + idx, cfg->danger_lut);
 565         DPU_REG_WRITE(&ctx->hw, SSPP_SAFE_LUT + idx, cfg->safe_lut);
 566 }
 567 
 568 static void dpu_hw_sspp_setup_creq_lut(struct dpu_hw_pipe *ctx,
 569                 struct dpu_hw_pipe_qos_cfg *cfg)
 570 {
 571         u32 idx;
 572 
 573         if (_sspp_subblk_offset(ctx, DPU_SSPP_SRC, &idx))
 574                 return;
 575 
 576         if (ctx->cap && test_bit(DPU_SSPP_QOS_8LVL, &ctx->cap->features)) {
 577                 DPU_REG_WRITE(&ctx->hw, SSPP_CREQ_LUT_0 + idx, cfg->creq_lut);
 578                 DPU_REG_WRITE(&ctx->hw, SSPP_CREQ_LUT_1 + idx,
 579                                 cfg->creq_lut >> 32);
 580         } else {
 581                 DPU_REG_WRITE(&ctx->hw, SSPP_CREQ_LUT + idx, cfg->creq_lut);
 582         }
 583 }
 584 
 585 static void dpu_hw_sspp_setup_qos_ctrl(struct dpu_hw_pipe *ctx,
 586                 struct dpu_hw_pipe_qos_cfg *cfg)
 587 {
 588         u32 idx;
 589         u32 qos_ctrl = 0;
 590 
 591         if (_sspp_subblk_offset(ctx, DPU_SSPP_SRC, &idx))
 592                 return;
 593 
 594         if (cfg->vblank_en) {
 595                 qos_ctrl |= ((cfg->creq_vblank &
 596                                 SSPP_QOS_CTRL_CREQ_VBLANK_MASK) <<
 597                                 SSPP_QOS_CTRL_CREQ_VBLANK_OFF);
 598                 qos_ctrl |= ((cfg->danger_vblank &
 599                                 SSPP_QOS_CTRL_DANGER_VBLANK_MASK) <<
 600                                 SSPP_QOS_CTRL_DANGER_VBLANK_OFF);
 601                 qos_ctrl |= SSPP_QOS_CTRL_VBLANK_EN;
 602         }
 603 
 604         if (cfg->danger_safe_en)
 605                 qos_ctrl |= SSPP_QOS_CTRL_DANGER_SAFE_EN;
 606 
 607         DPU_REG_WRITE(&ctx->hw, SSPP_QOS_CTRL + idx, qos_ctrl);
 608 }
 609 
 610 static void dpu_hw_sspp_setup_cdp(struct dpu_hw_pipe *ctx,
 611                 struct dpu_hw_pipe_cdp_cfg *cfg)
 612 {
 613         u32 idx;
 614         u32 cdp_cntl = 0;
 615 
 616         if (!ctx || !cfg)
 617                 return;
 618 
 619         if (_sspp_subblk_offset(ctx, DPU_SSPP_SRC, &idx))
 620                 return;
 621 
 622         if (cfg->enable)
 623                 cdp_cntl |= BIT(0);
 624         if (cfg->ubwc_meta_enable)
 625                 cdp_cntl |= BIT(1);
 626         if (cfg->tile_amortize_enable)
 627                 cdp_cntl |= BIT(2);
 628         if (cfg->preload_ahead == DPU_SSPP_CDP_PRELOAD_AHEAD_64)
 629                 cdp_cntl |= BIT(3);
 630 
 631         DPU_REG_WRITE(&ctx->hw, SSPP_CDP_CNTL, cdp_cntl);
 632 }
 633 
 634 static void _setup_layer_ops(struct dpu_hw_pipe *c,
 635                 unsigned long features)
 636 {
 637         if (test_bit(DPU_SSPP_SRC, &features)) {
 638                 c->ops.setup_format = dpu_hw_sspp_setup_format;
 639                 c->ops.setup_rects = dpu_hw_sspp_setup_rects;
 640                 c->ops.setup_sourceaddress = dpu_hw_sspp_setup_sourceaddress;
 641                 c->ops.setup_solidfill = dpu_hw_sspp_setup_solidfill;
 642                 c->ops.setup_pe = dpu_hw_sspp_setup_pe_config;
 643         }
 644 
 645         if (test_bit(DPU_SSPP_QOS, &features)) {
 646                 c->ops.setup_danger_safe_lut =
 647                         dpu_hw_sspp_setup_danger_safe_lut;
 648                 c->ops.setup_creq_lut = dpu_hw_sspp_setup_creq_lut;
 649                 c->ops.setup_qos_ctrl = dpu_hw_sspp_setup_qos_ctrl;
 650         }
 651 
 652         if (test_bit(DPU_SSPP_CSC, &features) ||
 653                 test_bit(DPU_SSPP_CSC_10BIT, &features))
 654                 c->ops.setup_csc = dpu_hw_sspp_setup_csc;
 655 
 656         if (test_bit(DPU_SSPP_SMART_DMA_V1, &c->cap->features) ||
 657                 test_bit(DPU_SSPP_SMART_DMA_V2, &c->cap->features))
 658                 c->ops.setup_multirect = dpu_hw_sspp_setup_multirect;
 659 
 660         if (test_bit(DPU_SSPP_SCALER_QSEED3, &features)) {
 661                 c->ops.setup_scaler = _dpu_hw_sspp_setup_scaler3;
 662                 c->ops.get_scaler_ver = _dpu_hw_sspp_get_scaler3_ver;
 663         }
 664 
 665         if (test_bit(DPU_SSPP_CDP, &features))
 666                 c->ops.setup_cdp = dpu_hw_sspp_setup_cdp;
 667 }
 668 
 669 static struct dpu_sspp_cfg *_sspp_offset(enum dpu_sspp sspp,
 670                 void __iomem *addr,
 671                 struct dpu_mdss_cfg *catalog,
 672                 struct dpu_hw_blk_reg_map *b)
 673 {
 674         int i;
 675 
 676         if ((sspp < SSPP_MAX) && catalog && addr && b) {
 677                 for (i = 0; i < catalog->sspp_count; i++) {
 678                         if (sspp == catalog->sspp[i].id) {
 679                                 b->base_off = addr;
 680                                 b->blk_off = catalog->sspp[i].base;
 681                                 b->length = catalog->sspp[i].len;
 682                                 b->hwversion = catalog->hwversion;
 683                                 b->log_mask = DPU_DBG_MASK_SSPP;
 684                                 return &catalog->sspp[i];
 685                         }
 686                 }
 687         }
 688 
 689         return ERR_PTR(-ENOMEM);
 690 }
 691 
 692 static struct dpu_hw_blk_ops dpu_hw_ops;
 693 
 694 struct dpu_hw_pipe *dpu_hw_sspp_init(enum dpu_sspp idx,
 695                 void __iomem *addr, struct dpu_mdss_cfg *catalog,
 696                 bool is_virtual_pipe)
 697 {
 698         struct dpu_hw_pipe *hw_pipe;
 699         struct dpu_sspp_cfg *cfg;
 700 
 701         if (!addr || !catalog)
 702                 return ERR_PTR(-EINVAL);
 703 
 704         hw_pipe = kzalloc(sizeof(*hw_pipe), GFP_KERNEL);
 705         if (!hw_pipe)
 706                 return ERR_PTR(-ENOMEM);
 707 
 708         cfg = _sspp_offset(idx, addr, catalog, &hw_pipe->hw);
 709         if (IS_ERR_OR_NULL(cfg)) {
 710                 kfree(hw_pipe);
 711                 return ERR_PTR(-EINVAL);
 712         }
 713 
 714         /* Assign ops */
 715         hw_pipe->catalog = catalog;
 716         hw_pipe->mdp = &catalog->mdp[0];
 717         hw_pipe->idx = idx;
 718         hw_pipe->cap = cfg;
 719         _setup_layer_ops(hw_pipe, hw_pipe->cap->features);
 720 
 721         dpu_hw_blk_init(&hw_pipe->base, DPU_HW_BLK_SSPP, idx, &dpu_hw_ops);
 722 
 723         return hw_pipe;
 724 }
 725 
 726 void dpu_hw_sspp_destroy(struct dpu_hw_pipe *ctx)
 727 {
 728         if (ctx)
 729                 dpu_hw_blk_destroy(&ctx->base);
 730         kfree(ctx);
 731 }
 732 

/* [<][>][^][v][top][bottom][index][help] */