1 // SPDX-License-Identifier: GPL-2.0-only 2 /* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. 3 */ 4 5 #include <drm/drm_managed.h> 6 7 #include "dpu_hwio.h" 8 #include "dpu_hw_catalog.h" 9 #include "dpu_hw_lm.h" 10 #include "dpu_hw_dspp.h" 11 #include "dpu_kms.h" 12 13 14 /* DSPP_PCC */ 15 #define PCC_EN BIT(0) 16 #define PCC_DIS 0 17 #define PCC_RED_R_OFF 0x10 18 #define PCC_RED_G_OFF 0x1C 19 #define PCC_RED_B_OFF 0x28 20 #define PCC_GREEN_R_OFF 0x14 21 #define PCC_GREEN_G_OFF 0x20 22 #define PCC_GREEN_B_OFF 0x2C 23 #define PCC_BLUE_R_OFF 0x18 24 #define PCC_BLUE_G_OFF 0x24 25 #define PCC_BLUE_B_OFF 0x30 26 27 static void dpu_setup_dspp_pcc(struct dpu_hw_dspp *ctx, 28 struct dpu_hw_pcc_cfg *cfg) 29 { 30 31 u32 base; 32 33 if (!ctx) { 34 DRM_ERROR("invalid ctx %pK\n", ctx); 35 return; 36 } 37 38 base = ctx->cap->sblk->pcc.base; 39 40 if (!base) { 41 DRM_ERROR("invalid ctx %pK pcc base 0x%x\n", ctx, base); 42 return; 43 } 44 45 if (!cfg) { 46 DRM_DEBUG_DRIVER("disable pcc feature\n"); 47 DPU_REG_WRITE(&ctx->hw, base, PCC_DIS); 48 return; 49 } 50 51 DPU_REG_WRITE(&ctx->hw, base + PCC_RED_R_OFF, cfg->r.r); 52 DPU_REG_WRITE(&ctx->hw, base + PCC_RED_G_OFF, cfg->r.g); 53 DPU_REG_WRITE(&ctx->hw, base + PCC_RED_B_OFF, cfg->r.b); 54 55 DPU_REG_WRITE(&ctx->hw, base + PCC_GREEN_R_OFF, cfg->g.r); 56 DPU_REG_WRITE(&ctx->hw, base + PCC_GREEN_G_OFF, cfg->g.g); 57 DPU_REG_WRITE(&ctx->hw, base + PCC_GREEN_B_OFF, cfg->g.b); 58 59 DPU_REG_WRITE(&ctx->hw, base + PCC_BLUE_R_OFF, cfg->b.r); 60 DPU_REG_WRITE(&ctx->hw, base + PCC_BLUE_G_OFF, cfg->b.g); 61 DPU_REG_WRITE(&ctx->hw, base + PCC_BLUE_B_OFF, cfg->b.b); 62 63 DPU_REG_WRITE(&ctx->hw, base, PCC_EN); 64 } 65 66 static void _setup_dspp_ops(struct dpu_hw_dspp *c, 67 unsigned long features) 68 { 69 if (test_bit(DPU_DSPP_PCC, &features)) 70 c->ops.setup_pcc = dpu_setup_dspp_pcc; 71 } 72 73 struct dpu_hw_dspp *dpu_hw_dspp_init(struct drm_device *dev, 74 const struct dpu_dspp_cfg *cfg, 75 void __iomem *addr) 76 { 77 struct dpu_hw_dspp *c; 78 79 if (!addr) 80 return ERR_PTR(-EINVAL); 81 82 c = drmm_kzalloc(dev, sizeof(*c), GFP_KERNEL); 83 if (!c) 84 return ERR_PTR(-ENOMEM); 85 86 c->hw.blk_addr = addr + cfg->base; 87 c->hw.log_mask = DPU_DBG_MASK_DSPP; 88 89 /* Assign ops */ 90 c->idx = cfg->id; 91 c->cap = cfg; 92 _setup_dspp_ops(c, c->cap->features); 93 94 return c; 95 } 96