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
  88struct dpu_hw_dspp *dpu_hw_dspp_init(enum dpu_dspp idx,
  89                        void __iomem *addr,
  90                        const struct dpu_mdss_cfg *m)
  91{
  92        struct dpu_hw_dspp *c;
  93        const struct dpu_dspp_cfg *cfg;
  94
  95        if (!addr || !m)
  96                return ERR_PTR(-EINVAL);
  97
  98        c = kzalloc(sizeof(*c), GFP_KERNEL);
  99        if (!c)
 100                return ERR_PTR(-ENOMEM);
 101
 102        cfg = _dspp_offset(idx, m, addr, &c->hw);
 103        if (IS_ERR_OR_NULL(cfg)) {
 104                kfree(c);
 105                return ERR_PTR(-EINVAL);
 106        }
 107
 108        /* Assign ops */
 109        c->idx = idx;
 110        c->cap = cfg;
 111        _setup_dspp_ops(c, c->cap->features);
 112
 113        return c;
 114}
 115
 116void dpu_hw_dspp_destroy(struct dpu_hw_dspp *dspp)
 117{
 118        kfree(dspp);
 119}
 120
 121
 122