
This change brings msm display driver including sde, dp, dsi, rotator, dsi pll and dp pll from base 4.19 kernel project. It is first source code snapshot from base kernel project. Change-Id: Iec864c064ce5ea04e170f24414c728684002f284 Signed-off-by: Narendra Muppalla <NarendraM@codeaurora.org>
215 lignes
6.0 KiB
C
215 lignes
6.0 KiB
C
// SPDX-License-Identifier: GPL-2.0-only
|
|
/*
|
|
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
|
*
|
|
*/
|
|
|
|
#include "sde_hwio.h"
|
|
#include "sde_hw_catalog.h"
|
|
#include "sde_hw_top.h"
|
|
#include "sde_dbg.h"
|
|
#include "sde_kms.h"
|
|
|
|
#define UIDLE_CTL 0x0
|
|
#define UIDLE_STATUS 0x4
|
|
#define UIDLE_FAL10_VETO_OVERRIDE 0x8
|
|
|
|
#define UIDLE_WD_TIMER_CTL 0x10
|
|
#define UIDLE_WD_TIMER_CTL2 0x14
|
|
#define UIDLE_WD_TIMER_LOAD_VALUE 0x18
|
|
|
|
#define UIDLE_DANGER_STATUS_0 0x20
|
|
#define UIDLE_DANGER_STATUS_1 0x24
|
|
#define UIDLE_SAFE_STATUS_0 0x30
|
|
#define UIDLE_SAFE_STATUS_1 0x34
|
|
#define UIDLE_IDLE_STATUS_0 0x38
|
|
#define UIDLE_IDLE_STATUS_1 0x3c
|
|
#define UIDLE_FAL_STATUS_0 0x40
|
|
#define UIDLE_FAL_STATUS_1 0x44
|
|
|
|
#define UIDLE_GATE_CNTR_CTL 0x50
|
|
#define UIDLE_FAL1_GATE_CNTR 0x54
|
|
#define UIDLE_FAL10_GATE_CNTR 0x58
|
|
#define UIDLE_FAL_WAIT_GATE_CNTR 0x5c
|
|
#define UIDLE_FAL1_NUM_TRANSITIONS_CNTR 0x60
|
|
#define UIDLE_FAL10_NUM_TRANSITIONS_CNTR 0x64
|
|
#define UIDLE_MIN_GATE_CNTR 0x68
|
|
#define UIDLE_MAX_GATE_CNTR 0x6c
|
|
|
|
static const struct sde_uidle_cfg *_top_offset(enum sde_uidle uidle,
|
|
struct sde_mdss_cfg *m, void __iomem *addr,
|
|
unsigned long len, struct sde_hw_blk_reg_map *b)
|
|
{
|
|
|
|
/* Make sure length of regs offsets is within the mapped memory */
|
|
if ((uidle == m->uidle_cfg.id) &&
|
|
(m->uidle_cfg.base + m->uidle_cfg.len) < len) {
|
|
|
|
b->base_off = addr;
|
|
b->blk_off = m->uidle_cfg.base;
|
|
b->length = m->uidle_cfg.len;
|
|
b->hwversion = m->hwversion;
|
|
b->log_mask = SDE_DBG_MASK_UIDLE;
|
|
SDE_DEBUG("base:0x%p blk_off:0x%x length:%d hwversion:0x%x\n",
|
|
b->base_off, b->blk_off, b->length, b->hwversion);
|
|
return &m->uidle_cfg;
|
|
}
|
|
|
|
SDE_ERROR("wrong uidle mapping params, will disable UIDLE!\n");
|
|
SDE_ERROR("base_off:0x%pK id:%d base:0x%x len:%d mmio_len:%ld\n",
|
|
addr, m->uidle_cfg.id, m->uidle_cfg.base,
|
|
m->uidle_cfg.len, len);
|
|
m->uidle_cfg.uidle_rev = 0;
|
|
|
|
return ERR_PTR(-EINVAL);
|
|
}
|
|
|
|
void sde_hw_uidle_get_status(struct sde_hw_uidle *uidle,
|
|
struct sde_uidle_status *status)
|
|
{
|
|
struct sde_hw_blk_reg_map *c = &uidle->hw;
|
|
|
|
status->uidle_danger_status_0 =
|
|
SDE_REG_READ(c, UIDLE_DANGER_STATUS_0);
|
|
status->uidle_danger_status_1 =
|
|
SDE_REG_READ(c, UIDLE_DANGER_STATUS_1);
|
|
status->uidle_safe_status_0 =
|
|
SDE_REG_READ(c, UIDLE_SAFE_STATUS_0);
|
|
status->uidle_safe_status_1 =
|
|
SDE_REG_READ(c, UIDLE_SAFE_STATUS_1);
|
|
status->uidle_idle_status_0 =
|
|
SDE_REG_READ(c, UIDLE_IDLE_STATUS_0);
|
|
status->uidle_idle_status_1 =
|
|
SDE_REG_READ(c, UIDLE_IDLE_STATUS_1);
|
|
status->uidle_fal_status_0 =
|
|
SDE_REG_READ(c, UIDLE_FAL_STATUS_0);
|
|
status->uidle_fal_status_1 =
|
|
SDE_REG_READ(c, UIDLE_FAL_STATUS_1);
|
|
}
|
|
|
|
void sde_hw_uidle_get_cntr(struct sde_hw_uidle *uidle,
|
|
struct sde_uidle_cntr *cntr)
|
|
{
|
|
struct sde_hw_blk_reg_map *c = &uidle->hw;
|
|
u32 reg_val;
|
|
|
|
cntr->fal1_gate_cntr =
|
|
SDE_REG_READ(c, UIDLE_FAL1_GATE_CNTR);
|
|
cntr->fal10_gate_cntr =
|
|
SDE_REG_READ(c, UIDLE_FAL10_GATE_CNTR);
|
|
cntr->fal_wait_gate_cntr =
|
|
SDE_REG_READ(c, UIDLE_FAL_WAIT_GATE_CNTR);
|
|
cntr->fal1_num_transitions_cntr =
|
|
SDE_REG_READ(c, UIDLE_FAL1_NUM_TRANSITIONS_CNTR);
|
|
cntr->fal10_num_transitions_cntr =
|
|
SDE_REG_READ(c, UIDLE_FAL10_NUM_TRANSITIONS_CNTR);
|
|
cntr->min_gate_cntr =
|
|
SDE_REG_READ(c, UIDLE_MIN_GATE_CNTR);
|
|
cntr->max_gate_cntr =
|
|
SDE_REG_READ(c, UIDLE_MAX_GATE_CNTR);
|
|
|
|
/* clear counters after read */
|
|
reg_val = SDE_REG_READ(c, UIDLE_GATE_CNTR_CTL);
|
|
reg_val = reg_val | BIT(31);
|
|
SDE_REG_WRITE(c, UIDLE_GATE_CNTR_CTL, reg_val);
|
|
reg_val = (reg_val & ~BIT(31));
|
|
SDE_REG_WRITE(c, UIDLE_GATE_CNTR_CTL, reg_val);
|
|
}
|
|
|
|
void sde_hw_uidle_setup_cntr(struct sde_hw_uidle *uidle, bool enable)
|
|
{
|
|
struct sde_hw_blk_reg_map *c = &uidle->hw;
|
|
u32 reg_val;
|
|
|
|
reg_val = SDE_REG_READ(c, UIDLE_GATE_CNTR_CTL);
|
|
reg_val = (reg_val & ~BIT(8)) | (enable ? BIT(8) : 0);
|
|
|
|
SDE_REG_WRITE(c, UIDLE_GATE_CNTR_CTL, reg_val);
|
|
}
|
|
|
|
void sde_hw_uidle_setup_wd_timer(struct sde_hw_uidle *uidle,
|
|
struct sde_uidle_wd_cfg *cfg)
|
|
{
|
|
struct sde_hw_blk_reg_map *c = &uidle->hw;
|
|
u32 val_ctl, val_ctl2, val_ld;
|
|
|
|
val_ctl = SDE_REG_READ(c, UIDLE_WD_TIMER_CTL);
|
|
val_ctl2 = SDE_REG_READ(c, UIDLE_WD_TIMER_CTL2);
|
|
val_ld = SDE_REG_READ(c, UIDLE_WD_TIMER_LOAD_VALUE);
|
|
|
|
val_ctl = (val_ctl & ~BIT(0)) | (cfg->clear ? BIT(0) : 0);
|
|
|
|
val_ctl2 = (val_ctl2 & ~BIT(0)) | (cfg->enable ? BIT(0) : 0);
|
|
val_ctl2 = (val_ctl2 & ~GENMASK(4, 1)) |
|
|
((cfg->granularity & 0xF) << 1);
|
|
val_ctl2 = (val_ctl2 & ~BIT(8)) | (cfg->heart_beat ? BIT(8) : 0);
|
|
|
|
val_ld = cfg->load_value;
|
|
|
|
SDE_REG_WRITE(c, UIDLE_WD_TIMER_CTL, val_ctl);
|
|
SDE_REG_WRITE(c, UIDLE_WD_TIMER_CTL2, val_ctl2);
|
|
SDE_REG_WRITE(c, UIDLE_WD_TIMER_LOAD_VALUE, val_ld);
|
|
}
|
|
|
|
void sde_hw_uidle_setup_ctl(struct sde_hw_uidle *uidle,
|
|
struct sde_uidle_ctl_cfg *cfg)
|
|
{
|
|
struct sde_hw_blk_reg_map *c = &uidle->hw;
|
|
u32 reg_val;
|
|
|
|
reg_val = SDE_REG_READ(c, UIDLE_CTL);
|
|
reg_val = (reg_val & ~BIT(31)) | (cfg->uidle_enable ? BIT(31) : 0);
|
|
reg_val = (reg_val & ~FAL10_DANGER_MSK) |
|
|
((cfg->fal10_danger << FAL10_DANGER_SHFT) &
|
|
FAL10_DANGER_MSK);
|
|
reg_val = (reg_val & ~FAL10_EXIT_DANGER_MSK) |
|
|
((cfg->fal10_exit_danger << FAL10_EXIT_DANGER_SHFT) &
|
|
FAL10_EXIT_DANGER_MSK);
|
|
reg_val = (reg_val & ~FAL10_EXIT_CNT_MSK) |
|
|
((cfg->fal10_exit_cnt << FAL10_EXIT_CNT_SHFT) &
|
|
FAL10_EXIT_CNT_MSK);
|
|
|
|
SDE_REG_WRITE(c, UIDLE_CTL, reg_val);
|
|
}
|
|
|
|
static inline void _setup_uidle_ops(struct sde_hw_uidle_ops *ops,
|
|
unsigned long cap)
|
|
{
|
|
ops->set_uidle_ctl = sde_hw_uidle_setup_ctl;
|
|
ops->setup_wd_timer = sde_hw_uidle_setup_wd_timer;
|
|
ops->uidle_setup_cntr = sde_hw_uidle_setup_cntr;
|
|
ops->uidle_get_cntr = sde_hw_uidle_get_cntr;
|
|
ops->uidle_get_status = sde_hw_uidle_get_status;
|
|
}
|
|
|
|
struct sde_hw_uidle *sde_hw_uidle_init(enum sde_uidle idx,
|
|
void __iomem *addr, unsigned long len,
|
|
struct sde_mdss_cfg *m)
|
|
{
|
|
struct sde_hw_uidle *c;
|
|
const struct sde_uidle_cfg *cfg;
|
|
|
|
c = kzalloc(sizeof(*c), GFP_KERNEL);
|
|
if (!c)
|
|
return ERR_PTR(-ENOMEM);
|
|
|
|
cfg = _top_offset(idx, m, addr, len, &c->hw);
|
|
if (IS_ERR_OR_NULL(cfg)) {
|
|
kfree(c);
|
|
return ERR_PTR(-EINVAL);
|
|
}
|
|
|
|
/*
|
|
* Assign ops
|
|
*/
|
|
c->idx = idx;
|
|
c->cap = cfg;
|
|
_setup_uidle_ops(&c->ops, c->cap->features);
|
|
|
|
sde_dbg_reg_register_dump_range(SDE_DBG_NAME, "uidle", c->hw.blk_off,
|
|
c->hw.blk_off + c->hw.length, 0);
|
|
|
|
return c;
|
|
}
|
|
|