0001
0002
0003
0004
0005 #include "dpu_hwio.h"
0006 #include "dpu_hw_catalog.h"
0007 #include "dpu_hw_lm.h"
0008 #include "dpu_hw_dspp.h"
0009 #include "dpu_kms.h"
0010
0011
0012
0013 #define PCC_EN BIT(0)
0014 #define PCC_DIS 0
0015 #define PCC_RED_R_OFF 0x10
0016 #define PCC_RED_G_OFF 0x1C
0017 #define PCC_RED_B_OFF 0x28
0018 #define PCC_GREEN_R_OFF 0x14
0019 #define PCC_GREEN_G_OFF 0x20
0020 #define PCC_GREEN_B_OFF 0x2C
0021 #define PCC_BLUE_R_OFF 0x18
0022 #define PCC_BLUE_G_OFF 0x24
0023 #define PCC_BLUE_B_OFF 0x30
0024
0025 static void dpu_setup_dspp_pcc(struct dpu_hw_dspp *ctx,
0026 struct dpu_hw_pcc_cfg *cfg)
0027 {
0028
0029 u32 base;
0030
0031 if (!ctx) {
0032 DRM_ERROR("invalid ctx %pK\n", ctx);
0033 return;
0034 }
0035
0036 base = ctx->cap->sblk->pcc.base;
0037
0038 if (!base) {
0039 DRM_ERROR("invalid ctx %pK pcc base 0x%x\n", ctx, base);
0040 return;
0041 }
0042
0043 if (!cfg) {
0044 DRM_DEBUG_DRIVER("disable pcc feature\n");
0045 DPU_REG_WRITE(&ctx->hw, base, PCC_DIS);
0046 return;
0047 }
0048
0049 DPU_REG_WRITE(&ctx->hw, base + PCC_RED_R_OFF, cfg->r.r);
0050 DPU_REG_WRITE(&ctx->hw, base + PCC_RED_G_OFF, cfg->r.g);
0051 DPU_REG_WRITE(&ctx->hw, base + PCC_RED_B_OFF, cfg->r.b);
0052
0053 DPU_REG_WRITE(&ctx->hw, base + PCC_GREEN_R_OFF, cfg->g.r);
0054 DPU_REG_WRITE(&ctx->hw, base + PCC_GREEN_G_OFF, cfg->g.g);
0055 DPU_REG_WRITE(&ctx->hw, base + PCC_GREEN_B_OFF, cfg->g.b);
0056
0057 DPU_REG_WRITE(&ctx->hw, base + PCC_BLUE_R_OFF, cfg->b.r);
0058 DPU_REG_WRITE(&ctx->hw, base + PCC_BLUE_G_OFF, cfg->b.g);
0059 DPU_REG_WRITE(&ctx->hw, base + PCC_BLUE_B_OFF, cfg->b.b);
0060
0061 DPU_REG_WRITE(&ctx->hw, base, PCC_EN);
0062 }
0063
0064 static void _setup_dspp_ops(struct dpu_hw_dspp *c,
0065 unsigned long features)
0066 {
0067 if (test_bit(DPU_DSPP_PCC, &features))
0068 c->ops.setup_pcc = dpu_setup_dspp_pcc;
0069 }
0070
0071 static const struct dpu_dspp_cfg *_dspp_offset(enum dpu_dspp dspp,
0072 const struct dpu_mdss_cfg *m,
0073 void __iomem *addr,
0074 struct dpu_hw_blk_reg_map *b)
0075 {
0076 int i;
0077
0078 if (!m || !addr || !b)
0079 return ERR_PTR(-EINVAL);
0080
0081 for (i = 0; i < m->dspp_count; i++) {
0082 if (dspp == m->dspp[i].id) {
0083 b->blk_addr = addr + m->dspp[i].base;
0084 b->log_mask = DPU_DBG_MASK_DSPP;
0085 return &m->dspp[i];
0086 }
0087 }
0088
0089 return ERR_PTR(-EINVAL);
0090 }
0091
0092 struct dpu_hw_dspp *dpu_hw_dspp_init(enum dpu_dspp idx,
0093 void __iomem *addr,
0094 const struct dpu_mdss_cfg *m)
0095 {
0096 struct dpu_hw_dspp *c;
0097 const struct dpu_dspp_cfg *cfg;
0098
0099 if (!addr || !m)
0100 return ERR_PTR(-EINVAL);
0101
0102 c = kzalloc(sizeof(*c), GFP_KERNEL);
0103 if (!c)
0104 return ERR_PTR(-ENOMEM);
0105
0106 cfg = _dspp_offset(idx, m, addr, &c->hw);
0107 if (IS_ERR_OR_NULL(cfg)) {
0108 kfree(c);
0109 return ERR_PTR(-EINVAL);
0110 }
0111
0112
0113 c->idx = idx;
0114 c->cap = cfg;
0115 _setup_dspp_ops(c, c->cap->features);
0116
0117 return c;
0118 }
0119
0120 void dpu_hw_dspp_destroy(struct dpu_hw_dspp *dspp)
0121 {
0122 kfree(dspp);
0123 }
0124
0125