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                c->ops.setup_pcc = dpu_setup_dspp_pcc;
  62}
  63
  64static const struct dpu_dspp_cfg *_dspp_offset(enum dpu_dspp dspp,
  65                const struct dpu_mdss_cfg *m,
  66                void __iomem *addr,
  67                struct dpu_hw_blk_reg_map *b)
  68{
  69        int i;
  70
  71        if (!m || !addr || !b)
  72                return ERR_PTR(-EINVAL);
  73
  74        for (i = 0; i < m->dspp_count; i++) {
  75                if (dspp == m->dspp[i].id) {
  76                        b->base_off = addr;
  77                        b->blk_off = m->dspp[i].base;
  78                        b->length = m->dspp[i].len;
  79                        b->hwversion = m->hwversion;
  80                        b->log_mask = DPU_DBG_MASK_DSPP;
  81                        return &m->dspp[i];
  82                }
  83        }
  84
  85        return ERR_PTR(-EINVAL);
  86}
  87
  88static struct dpu_hw_blk_ops dpu_hw_ops;
  89
  90struct dpu_hw_dspp *dpu_hw_dspp_init(enum dpu_dspp idx,
  91                        void __iomem *addr,
  92                        const struct dpu_mdss_cfg *m)
  93{
  94        struct dpu_hw_dspp *c;
  95        const struct dpu_dspp_cfg *cfg;
  96
  97        if (!addr || !m)
  98                return ERR_PTR(-EINVAL);
  99
 100        c = kzalloc(sizeof(*c), GFP_KERNEL);
 101        if (!c)
 102                return ERR_PTR(-ENOMEM);
 103
 104        cfg = _dspp_offset(idx, m, addr, &c->hw);
 105        if (IS_ERR_OR_NULL(cfg)) {
 106                kfree(c);
 107                return ERR_PTR(-EINVAL);
 108        }
 109
 110        /* Assign ops */
 111        c->idx = idx;
 112        c->cap = cfg;
 113        _setup_dspp_ops(c, c->cap->features);
 114
 115        dpu_hw_blk_init(&c->base, DPU_HW_BLK_DSPP, idx, &dpu_hw_ops);
 116
 117        return c;
 118}
 119
 120void dpu_hw_dspp_destroy(struct dpu_hw_dspp *dspp)
 121{
 122        if (dspp)
 123                dpu_hw_blk_destroy(&dspp->base);
 124
 125        kfree(dspp);
 126}
 127
 128
 129