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
27static 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
66static 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
73struct 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