mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-08 03:40:35 +09:00
drm/rockchip: vop2: Add submem power gate support
RK3588 VOP2 has power gates for VP0/1/2/3, DB0/1/2 and WB. Signed-off-by: Andy Yan <andy.yan@rock-chips.com> Change-Id: Ie3d67aa804282834949d6950470ba960ea51fcdb
This commit is contained in:
@@ -117,6 +117,20 @@ enum vop2_win_dly_mode {
|
||||
#define VOP2_PD_DSC_8K BIT(5)
|
||||
#define VOP2_PD_DSC_4K BIT(6)
|
||||
|
||||
/*
|
||||
* vop2 submem power gate,
|
||||
* should be all none zero, 0 will be
|
||||
* treat as invalid;
|
||||
*/
|
||||
#define VOP2_MEM_PG_VP0 BIT(0)
|
||||
#define VOP2_MEM_PG_VP1 BIT(1)
|
||||
#define VOP2_MEM_PG_VP2 BIT(2)
|
||||
#define VOP2_MEM_PG_VP3 BIT(3)
|
||||
#define VOP2_MEM_PG_DB0 BIT(4)
|
||||
#define VOP2_MEM_PG_DB1 BIT(5)
|
||||
#define VOP2_MEM_PG_DB2 BIT(6)
|
||||
#define VOP2_MEM_PG_WB BIT(7)
|
||||
|
||||
#define DSP_BG_SWAP 0x1
|
||||
#define DSP_RB_SWAP 0x2
|
||||
#define DSP_RG_SWAP 0x4
|
||||
@@ -1027,6 +1041,7 @@ struct vop2_data {
|
||||
uint8_t nr_gammas;
|
||||
uint8_t nr_conns;
|
||||
uint8_t nr_pds;
|
||||
uint8_t nr_mem_pgs;
|
||||
bool delayed_pd;
|
||||
const struct vop_intr *axi_intr;
|
||||
const struct vop2_ctrl *ctrl;
|
||||
@@ -1039,6 +1054,7 @@ struct vop2_data {
|
||||
const struct vop2_wb_data *wb;
|
||||
const struct vop2_layer_data *layer;
|
||||
const struct vop2_power_domain_data *pd;
|
||||
const struct vop2_power_domain_data *mem_pg;
|
||||
const struct vop_csc_table *csc_table;
|
||||
const struct vop_hdr_table *hdr_table;
|
||||
const struct vop_grf_ctrl *sys_grf;
|
||||
|
||||
@@ -655,6 +655,7 @@ struct vop2 {
|
||||
struct regmap *sys_grf;
|
||||
struct regmap *vo0_grf;
|
||||
struct regmap *vo1_grf;
|
||||
struct regmap *pmu;
|
||||
|
||||
/* physical map length of vop2 register */
|
||||
uint32_t len;
|
||||
@@ -2946,7 +2947,7 @@ static void rk3588_vop2_regsbak(struct vop2 *vop2)
|
||||
/*
|
||||
* No need to backup DSC/GAMMA_LUT/BPP_LUT/MMU
|
||||
*/
|
||||
for (i = 0; i < (RK3588_DSC_8K_PPS0_3 >> 2); i++)
|
||||
for (i = 0; i < (0x2000 >> 2); i++)
|
||||
vop2->regsbak[i] = base[i];
|
||||
|
||||
for (i = 0; i < vop2_data->nr_dscs; i++) {
|
||||
@@ -7071,7 +7072,7 @@ static irqreturn_t vop2_isr(int irq, void *data)
|
||||
do { \
|
||||
if (active_irqs & x##_INTR) {\
|
||||
if (x##_INTR == POST_BUF_EMPTY_INTR) \
|
||||
DRM_DEV_ERROR_RATELIMITED(vop2->dev, #x " irq err at vp%d\n", vp->id); \
|
||||
printk(KERN_DEBUG #x " irq err at vp%d\n", vp->id); \
|
||||
else \
|
||||
DRM_DEV_ERROR_RATELIMITED(vop2->dev, #x " irq err\n"); \
|
||||
active_irqs &= ~x##_INTR; \
|
||||
@@ -7922,6 +7923,7 @@ static int vop2_bind(struct device *dev, struct device *master, void *data)
|
||||
vop2->sys_grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,grf");
|
||||
vop2->grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,vop-grf");
|
||||
vop2->vo1_grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,vo1-grf");
|
||||
vop2->pmu = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,pmu");
|
||||
|
||||
vop2->hclk = devm_clk_get(vop2->dev, "hclk_vop");
|
||||
if (IS_ERR(vop2->hclk)) {
|
||||
|
||||
@@ -1974,13 +1974,13 @@ static const struct vop2_power_domain_data rk3588_vop_pd_data[] = {
|
||||
{
|
||||
.id = VOP2_PD_CLUSTER2,
|
||||
.parent_id = VOP2_PD_CLUSTER0,
|
||||
.regs = &rk3588_cluster0_pd_regs,
|
||||
.regs = &rk3588_cluster2_pd_regs,
|
||||
},
|
||||
|
||||
{
|
||||
.id = VOP2_PD_CLUSTER3,
|
||||
.parent_id = VOP2_PD_CLUSTER0,
|
||||
.regs = &rk3588_cluster1_pd_regs,
|
||||
.regs = &rk3588_cluster3_pd_regs,
|
||||
},
|
||||
|
||||
{
|
||||
@@ -1999,6 +1999,98 @@ static const struct vop2_power_domain_data rk3588_vop_pd_data[] = {
|
||||
},
|
||||
};
|
||||
|
||||
const struct vop2_power_domain_regs rk3588_mem_pg_vp0_regs = {
|
||||
.pd = VOP_REG(RK3588_PMU_SUBMEM_PWR_GATE_CON1, 0x1, 15),
|
||||
.status = VOP_REG(RK3588_PMU_SUBMEM_PWR_GATE_STATUS, 0x1, 19),
|
||||
};
|
||||
|
||||
const struct vop2_power_domain_regs rk3588_mem_pg_vp1_regs = {
|
||||
.pd = VOP_REG(RK3588_PMU_SUBMEM_PWR_GATE_CON2, 0x1, 0),
|
||||
.status = VOP_REG(RK3588_PMU_SUBMEM_PWR_GATE_STATUS, 0x1, 20),
|
||||
};
|
||||
|
||||
const struct vop2_power_domain_regs rk3588_mem_pg_vp2_regs = {
|
||||
.pd = VOP_REG(RK3588_PMU_SUBMEM_PWR_GATE_CON2, 0x1, 1),
|
||||
.status = VOP_REG(RK3588_PMU_SUBMEM_PWR_GATE_STATUS, 0x1, 21),
|
||||
};
|
||||
|
||||
const struct vop2_power_domain_regs rk3588_mem_pg_vp3_regs = {
|
||||
.pd = VOP_REG(RK3588_PMU_SUBMEM_PWR_GATE_CON2, 0x1, 2),
|
||||
.status = VOP_REG(RK3588_PMU_SUBMEM_PWR_GATE_STATUS, 0x1, 22),
|
||||
};
|
||||
|
||||
const struct vop2_power_domain_regs rk3588_mem_pg_db0_regs = {
|
||||
.pd = VOP_REG(RK3588_PMU_SUBMEM_PWR_GATE_CON2, 0x1, 3),
|
||||
.status = VOP_REG(RK3588_PMU_SUBMEM_PWR_GATE_STATUS, 0x1, 23),
|
||||
};
|
||||
|
||||
const struct vop2_power_domain_regs rk3588_mem_pg_db1_regs = {
|
||||
.pd = VOP_REG(RK3588_PMU_SUBMEM_PWR_GATE_CON2, 0x1, 4),
|
||||
.status = VOP_REG(RK3588_PMU_SUBMEM_PWR_GATE_STATUS, 0x1, 24),
|
||||
};
|
||||
|
||||
const struct vop2_power_domain_regs rk3588_mem_pg_db2_regs = {
|
||||
.pd = VOP_REG(RK3588_PMU_SUBMEM_PWR_GATE_CON2, 0x1, 5),
|
||||
.status = VOP_REG(RK3588_PMU_SUBMEM_PWR_GATE_STATUS, 0x1, 25),
|
||||
};
|
||||
|
||||
const struct vop2_power_domain_regs rk3588_mem_pg_wb_regs = {
|
||||
.pd = VOP_REG(RK3588_PMU_SUBMEM_PWR_GATE_CON2, 0x1, 6),
|
||||
.status = VOP_REG(RK3588_PMU_SUBMEM_PWR_GATE_STATUS, 0x1, 26),
|
||||
};
|
||||
|
||||
/*
|
||||
* All power gates will power on when PD_VOP is turn on.
|
||||
* Corresponding mem_pwr_ack_bypass bit should be enabled
|
||||
* if power gate powe down before PD_VOP.
|
||||
* power gates take effect immediately, this means there
|
||||
* is no synchronization between vop frame scanout, so
|
||||
* we can only enable a power gate before we enable
|
||||
* a module, and turn off power gate after the module
|
||||
* is actually disabled.
|
||||
*/
|
||||
static const struct vop2_power_domain_data rk3588_vop_mem_pg_data[] = {
|
||||
{
|
||||
.id = VOP2_MEM_PG_VP0,
|
||||
.regs = &rk3588_mem_pg_vp0_regs,
|
||||
},
|
||||
|
||||
{
|
||||
.id = VOP2_MEM_PG_VP1,
|
||||
.regs = &rk3588_mem_pg_vp1_regs,
|
||||
},
|
||||
|
||||
{
|
||||
.id = VOP2_MEM_PG_VP2,
|
||||
.regs = &rk3588_mem_pg_vp2_regs,
|
||||
},
|
||||
|
||||
{
|
||||
.id = VOP2_MEM_PG_VP3,
|
||||
.regs = &rk3588_mem_pg_vp3_regs,
|
||||
},
|
||||
|
||||
{
|
||||
.id = VOP2_MEM_PG_DB0,
|
||||
.regs = &rk3588_mem_pg_db0_regs,
|
||||
},
|
||||
|
||||
{
|
||||
.id = VOP2_MEM_PG_DB1,
|
||||
.regs = &rk3588_mem_pg_db1_regs,
|
||||
},
|
||||
|
||||
{
|
||||
.id = VOP2_MEM_PG_DB2,
|
||||
.regs = &rk3588_mem_pg_db2_regs,
|
||||
},
|
||||
|
||||
{
|
||||
.id = VOP2_MEM_PG_WB,
|
||||
.regs = &rk3588_mem_pg_wb_regs,
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
* rk3588 vop with 4 cluster, 4 esmart win.
|
||||
* Every cluster can work as 4K win or split into two win.
|
||||
@@ -2511,6 +2603,8 @@ static const struct vop2_data rk3588_vop = {
|
||||
.win_size = ARRAY_SIZE(rk3588_vop_win_data),
|
||||
.pd = rk3588_vop_pd_data,
|
||||
.nr_pds = ARRAY_SIZE(rk3588_vop_pd_data),
|
||||
.mem_pg = rk3588_vop_mem_pg_data,
|
||||
.nr_mem_pgs = ARRAY_SIZE(rk3588_vop_mem_pg_data),
|
||||
};
|
||||
|
||||
static const struct of_device_id vop2_dt_match[] = {
|
||||
|
||||
@@ -1613,4 +1613,11 @@
|
||||
#define RK3588_GRF_VOP_CON2 0x08
|
||||
#define RK3588_GRF_VO1_CON0 0x00
|
||||
|
||||
|
||||
#define RK3588_PMU_PWR_GATE_CON1 0x150
|
||||
#define RK3588_PMU_SUBMEM_PWR_GATE_CON1 0x1B4
|
||||
#define RK3588_PMU_SUBMEM_PWR_GATE_CON2 0x1B8
|
||||
#define RK3588_PMU_SUBMEM_PWR_GATE_STATUS 0x1BC
|
||||
#define RK3588_PMU_BISR_STATUS5 0x294
|
||||
|
||||
#endif /* _ROCKCHIP_VOP_REG_H */
|
||||
|
||||
Reference in New Issue
Block a user