linux/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.c
<<
>>
Prefs
   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_dspp.h"
   9#include "dpu_kms.h"
  10
  11
  12/* DSPP_PCC */
  13#define PCC_EN BIT(0)
  14#define PCC_DIS 0
  15#define PCC_RED_R_OFF 0x10
  16#define PCC_RED_G_OFF 0x1C
  17#define PCC_RED_B_OFF 0x28
  18#define PCC_GREEN_R_OFF 0x14
  19#define PCC_GREEN_G_OFF 0x20
  20#define PCC_GREEN_B_OFF 0x2C
  21#define PCC_BLUE_R_OFF 0x18
  22#define PCC_BLUE_G_OFF 0x24
  23#define PCC_BLUE_B_OFF 0x30
  24
  25static void dpu_setup_dspp_pcc(struct dpu_hw_dspp *ctx,
  26                struct dpu_hw_pcc_cfg *cfg)
  27{
  28
  29        u32 base = ctx->cap->sblk->pcc.base;
  30
  31        if (!ctx || !base) {
  32                DRM_ERROR("invalid ctx %pK pcc base 0x%x\n", ctx, base);
  33                return;
  34        }
  35
  36        if (!cfg) {
  37                DRM_DEBUG_DRIVER("disable pcc feature\n");
  38                DPU_REG_WRITE(&ctx->hw, base, PCC_DIS);
  39                return;
  40        }
  41
  42        DPU_REG_WRITE(&ctx->hw, base + PCC_RED_R_OFF, cfg->r.r);
  43        DPU_REG_WRITE(&ctx->hw, base + PCC_RED_G_OFF, cfg->r.g);
  44        DPU_REG_WRITE(&ctx->hw, base + PCC_RED_B_OFF, cfg->r.b);
  45
  46        DPU_REG_WRITE(&ctx->hw, base + PCC_GREEN_R_OFF, cfg->g.r);
  47        DPU_REG_WRITE(&ctx->hw, base + PCC_GREEN_G_OFF, cfg->g.g);
  48        DPU_REG_WRITE(&ctx->hw, base + PCC_GREEN_B_OFF, cfg->g.b);
  49
  50        DPU_REG_WRITE(&ctx->hw, base + PCC_BLUE_R_OFF, cfg->b.r);
  51        DPU_REG_WRITE(&ctx->hw, base + PCC_BLUE_G_OFF, cfg->b.g);
  52        DPU_REG_WRITE(&ctx->hw, base + PCC_BLUE_B_OFF, cfg->b.b);
  53
  54        DPU_REG_WRITE(&ctx->hw, base, PCC_EN);
  55}
  56
  57static void _setup_dspp_ops(struct dpu_hw_dspp *c,
  58                unsigned long features)
  59{
  60        if (test_bit(DPU_DSPP_PCC, &features) &&
  61                IS_SC7180_TARGET(c->hw.hwversion))
  62                c->ops.setup_pcc = dpu_setup_dspp_pcc;
  63}
  64
  65static const struct dpu_dspp_cfg *_dspp_offset(enum dpu_dspp dspp,
  66                const struct dpu_mdss_cfg *m,
  67                void __iomem *addr,
  68                struct dpu_hw_blk_reg_map *b)
  69{
  70        int i;
  71
  72        if (!m || !addr || !b)
  73                return ERR_PTR(-EINVAL);
  74
  75        for (i = 0; i < m->dspp_count; i++) {
  76                if (dspp == m->dspp[i].id) {
  77                        b->base_off = addr;
  78                        b->blk_off = m->dspp[i].base;
  79                        b->length = m->dspp[i].len;
  80                        b->hwversion = m->hwversion;
  81                        b->log_mask = DPU_DBG_MASK_DSPP;
  82                        return &m->dspp[i];
  83                }
  84        }
  85
  86        return ERR_PTR(-EINVAL);
  87}
  88
  89static struct dpu_hw_blk_ops dpu_hw_ops;
  90
  91struct dpu_hw_dspp *dpu_hw_dspp_init(enum dpu_dspp idx,
  92                        void __iomem *addr,
  93                        const struct dpu_mdss_cfg *m)
  94{
  95        struct dpu_hw_dspp *c;
  96        const struct dpu_dspp_cfg *cfg;
  97
  98        if (!addr || !m)
  99                return ERR_PTR(-EINVAL);
 100
 101        c = kzalloc(sizeof(*c), GFP_KERNEL);
 102        if (!c)
 103                return ERR_PTR(-ENOMEM);
 104
 105        cfg = _dspp_offset(idx, m, addr, &c->hw);
 106        if (IS_ERR_OR_NULL(cfg)) {
 107                kfree(c);
 108                return ERR_PTR(-EINVAL);
 109        }
 110
 111        /* Assign ops */
 112        c->idx = idx;
 113        c->cap = cfg;
 114        _setup_dspp_ops(c, c->cap->features);
 115
 116        dpu_hw_blk_init(&c->base, DPU_HW_BLK_DSPP, idx, &dpu_hw_ops);
 117
 118        return c;
 119}
 120
 121void dpu_hw_dspp_destroy(struct dpu_hw_dspp *dspp)
 122{
 123        if (dspp)
 124                dpu_hw_blk_destroy(&dspp->base);
 125
 126        kfree(dspp);
 127}
 128
 129
 130