Merge "msm: sde: Add pre/post power event handler in SDE rotator"
This commit is contained in:
commit
baa3d606ab
5 changed files with 119 additions and 3 deletions
drivers/media/platform/msm/sde/rotator
|
@ -278,6 +278,10 @@ static void sde_rotator_footswitch_ctrl(struct sde_rot_mgr *mgr, bool on)
|
|||
|
||||
SDEROT_EVTLOG(on);
|
||||
SDEROT_DBG("%s: rotator regulators", on ? "Enable" : "Disable");
|
||||
|
||||
if (mgr->ops_hw_pre_pmevent)
|
||||
mgr->ops_hw_pre_pmevent(mgr, on);
|
||||
|
||||
ret = sde_rot_enable_vreg(mgr->module_power.vreg_config,
|
||||
mgr->module_power.num_vreg, on);
|
||||
if (ret) {
|
||||
|
@ -286,10 +290,13 @@ static void sde_rotator_footswitch_ctrl(struct sde_rot_mgr *mgr, bool on)
|
|||
return;
|
||||
}
|
||||
|
||||
if (mgr->ops_hw_post_pmevent)
|
||||
mgr->ops_hw_post_pmevent(mgr, on);
|
||||
|
||||
mgr->regulator_enable = on;
|
||||
}
|
||||
|
||||
static int sde_rotator_clk_ctrl(struct sde_rot_mgr *mgr, int enable)
|
||||
int sde_rotator_clk_ctrl(struct sde_rot_mgr *mgr, int enable)
|
||||
{
|
||||
struct clk *clk;
|
||||
int ret = 0;
|
||||
|
|
|
@ -293,6 +293,8 @@ struct sde_rot_mgr {
|
|||
void (*ops_hw_free)(struct sde_rot_mgr *mgr,
|
||||
struct sde_rot_hw_resource *hw);
|
||||
int (*ops_hw_init)(struct sde_rot_mgr *mgr);
|
||||
void (*ops_hw_pre_pmevent)(struct sde_rot_mgr *mgr, bool pmon);
|
||||
void (*ops_hw_post_pmevent)(struct sde_rot_mgr *mgr, bool pmon);
|
||||
void (*ops_hw_destroy)(struct sde_rot_mgr *mgr);
|
||||
ssize_t (*ops_hw_show_caps)(struct sde_rot_mgr *mgr,
|
||||
struct device_attribute *attr, char *buf, ssize_t len);
|
||||
|
@ -405,6 +407,8 @@ int sde_rotator_validate_request(struct sde_rot_mgr *rot_dev,
|
|||
struct sde_rot_file_private *ctx,
|
||||
struct sde_rot_entry_container *req);
|
||||
|
||||
int sde_rotator_clk_ctrl(struct sde_rot_mgr *mgr, int enable);
|
||||
|
||||
static inline void sde_rot_mgr_lock(struct sde_rot_mgr *mgr)
|
||||
{
|
||||
mutex_lock(&mgr->lock);
|
||||
|
|
|
@ -271,6 +271,7 @@ static int sde_hw_rotator_pending_swts(struct sde_hw_rotator *rot,
|
|||
|
||||
SDEROT_DBG("ts:0x%x, queue_id:%d, swts:0x%x, pending:%d\n",
|
||||
ctx->timestamp, ctx->q_id, swts, pending);
|
||||
SDEROT_EVTLOG(ctx->timestamp, swts, ctx->q_id, ts_diff);
|
||||
return pending;
|
||||
}
|
||||
|
||||
|
@ -1239,6 +1240,94 @@ static void sde_hw_rotator_swtc_destroy(struct sde_hw_rotator *rot)
|
|||
data->srcp_dma_buf = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* sde_hw_rotator_pre_pmevent - SDE rotator core will call this before a
|
||||
* PM event occurs
|
||||
* @mgr: Pointer to rotator manager
|
||||
* @pmon: Boolean indicate an on/off power event
|
||||
*/
|
||||
void sde_hw_rotator_pre_pmevent(struct sde_rot_mgr *mgr, bool pmon)
|
||||
{
|
||||
struct sde_hw_rotator *rot;
|
||||
u32 l_ts, h_ts, swts, hwts;
|
||||
u32 rotsts, regdmasts;
|
||||
|
||||
/*
|
||||
* Check last HW timestamp with SW timestamp before power off event.
|
||||
* If there is a mismatch, that will be quite possible the rotator HW
|
||||
* is either hang or not finishing last submitted job. In that case,
|
||||
* it is best to do a timeout eventlog to capture some good events
|
||||
* log data for analysis.
|
||||
*/
|
||||
if (!pmon && mgr && mgr->hw_data) {
|
||||
rot = mgr->hw_data;
|
||||
h_ts = atomic_read(&rot->timestamp[ROT_QUEUE_HIGH_PRIORITY]);
|
||||
l_ts = atomic_read(&rot->timestamp[ROT_QUEUE_LOW_PRIORITY]);
|
||||
|
||||
/* contruct the combined timstamp */
|
||||
swts = (h_ts & SDE_REGDMA_SWTS_MASK) |
|
||||
((l_ts & SDE_REGDMA_SWTS_MASK) <<
|
||||
SDE_REGDMA_SWTS_SHIFT);
|
||||
|
||||
/* Need to turn on clock to access rotator register */
|
||||
sde_rotator_clk_ctrl(mgr, true);
|
||||
hwts = SDE_ROTREG_READ(rot->mdss_base, REGDMA_TIMESTAMP_REG);
|
||||
regdmasts = SDE_ROTREG_READ(rot->mdss_base,
|
||||
REGDMA_CSR_REGDMA_BLOCK_STATUS);
|
||||
rotsts = SDE_ROTREG_READ(rot->mdss_base, ROTTOP_STATUS);
|
||||
|
||||
SDEROT_DBG(
|
||||
"swts:0x%x, hwts:0x%x, regdma-sts:0x%x, rottop-sts:0x%x\n",
|
||||
swts, hwts, regdmasts, rotsts);
|
||||
SDEROT_EVTLOG(swts, hwts, regdmasts, rotsts);
|
||||
|
||||
if ((swts != hwts) && ((regdmasts & REGDMA_BUSY) ||
|
||||
(rotsts & ROT_STATUS_MASK))) {
|
||||
SDEROT_ERR(
|
||||
"Mismatch SWTS with HWTS: swts:0x%x, hwts:0x%x, regdma-sts:0x%x, rottop-sts:0x%x\n",
|
||||
swts, hwts, regdmasts, rotsts);
|
||||
SDEROT_EVTLOG_TOUT_HANDLER("rot", "vbif_dbg_bus",
|
||||
"panic");
|
||||
}
|
||||
|
||||
/* Turn off rotator clock after checking rotator registers */
|
||||
sde_rotator_clk_ctrl(mgr, false);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* sde_hw_rotator_post_pmevent - SDE rotator core will call this after a
|
||||
* PM event occurs
|
||||
* @mgr: Pointer to rotator manager
|
||||
* @pmon: Boolean indicate an on/off power event
|
||||
*/
|
||||
void sde_hw_rotator_post_pmevent(struct sde_rot_mgr *mgr, bool pmon)
|
||||
{
|
||||
struct sde_hw_rotator *rot;
|
||||
u32 l_ts, h_ts, swts;
|
||||
|
||||
/*
|
||||
* After a power on event, the rotator HW is reset to default setting.
|
||||
* It is necessary to synchronize the SW timestamp with the HW.
|
||||
*/
|
||||
if (pmon && mgr && mgr->hw_data) {
|
||||
rot = mgr->hw_data;
|
||||
h_ts = atomic_read(&rot->timestamp[ROT_QUEUE_HIGH_PRIORITY]);
|
||||
l_ts = atomic_read(&rot->timestamp[ROT_QUEUE_LOW_PRIORITY]);
|
||||
|
||||
/* contruct the combined timstamp */
|
||||
swts = (h_ts & SDE_REGDMA_SWTS_MASK) |
|
||||
((l_ts & SDE_REGDMA_SWTS_MASK) <<
|
||||
SDE_REGDMA_SWTS_SHIFT);
|
||||
|
||||
SDEROT_DBG("swts:0x%x, h_ts:0x%x, l_ts;0x%x\n",
|
||||
swts, h_ts, l_ts);
|
||||
SDEROT_EVTLOG(swts, h_ts, l_ts);
|
||||
rot->reset_hw_ts = true;
|
||||
rot->last_hw_ts = swts;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* sde_hw_rotator_destroy - Destroy hw rotator and free allocated resources
|
||||
* @mgr: Pointer to rotator manager
|
||||
|
@ -1455,6 +1544,15 @@ static int sde_hw_rotator_config(struct sde_rot_hw_resource *hw,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (rot->reset_hw_ts) {
|
||||
SDEROT_EVTLOG(rot->last_hw_ts);
|
||||
SDE_ROTREG_WRITE(rot->mdss_base, REGDMA_TIMESTAMP_REG,
|
||||
rot->last_hw_ts);
|
||||
/* ensure write is issued to the rotator HW */
|
||||
wmb();
|
||||
rot->reset_hw_ts = false;
|
||||
}
|
||||
|
||||
flags = (item->flags & SDE_ROTATION_FLIP_LR) ?
|
||||
SDE_ROT_FLAG_FLIP_LR : 0;
|
||||
flags |= (item->flags & SDE_ROTATION_FLIP_UD) ?
|
||||
|
@ -1511,7 +1609,8 @@ static int sde_hw_rotator_config(struct sde_rot_hw_resource *hw,
|
|||
&entry->dst_buf);
|
||||
}
|
||||
|
||||
SDEROT_EVTLOG(flags, item->input.width, item->input.height,
|
||||
SDEROT_EVTLOG(ctx->timestamp, flags,
|
||||
item->input.width, item->input.height,
|
||||
item->output.width, item->output.height,
|
||||
entry->src_buf.p[0].addr, entry->dst_buf.p[0].addr);
|
||||
|
||||
|
@ -1715,6 +1814,7 @@ static int sde_rotator_hw_rev_init(struct sde_hw_rotator *rot)
|
|||
mdata->regdump = sde_rot_r3_regdump;
|
||||
mdata->regdump_size = ARRAY_SIZE(sde_rot_r3_regdump);
|
||||
|
||||
SDE_ROTREG_WRITE(rot->mdss_base, REGDMA_TIMESTAMP_REG, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2174,6 +2274,8 @@ int sde_rotator_r3_init(struct sde_rot_mgr *mgr)
|
|||
mgr->ops_hw_create_debugfs = sde_rotator_r3_create_debugfs;
|
||||
mgr->ops_hw_get_pixfmt = sde_hw_rotator_get_pixfmt;
|
||||
mgr->ops_hw_is_valid_pixfmt = sde_hw_rotator_is_valid_pixfmt;
|
||||
mgr->ops_hw_pre_pmevent = sde_hw_rotator_pre_pmevent;
|
||||
mgr->ops_hw_post_pmevent = sde_hw_rotator_post_pmevent;
|
||||
|
||||
ret = sde_hw_rotator_parse_dt(mgr->hw_data, mgr->pdev);
|
||||
if (ret)
|
||||
|
|
|
@ -250,9 +250,10 @@
|
|||
/* General defines */
|
||||
#define ROT_DONE_MASK 0x1
|
||||
#define ROT_DONE_CLEAR 0x1
|
||||
#define ROT_BUSY_BIT BIT(1)
|
||||
#define ROT_BUSY_BIT BIT(0)
|
||||
#define ROT_ERROR_BIT BIT(8)
|
||||
#define ROT_STATUS_MASK (ROT_BUSY_BIT | ROT_ERROR_BIT)
|
||||
#define REGDMA_BUSY BIT(0)
|
||||
#define REGDMA_EN 0x1
|
||||
#define REGDMA_SECURE_EN BIT(8)
|
||||
#define REGDMA_HALT BIT(16)
|
||||
|
|
|
@ -270,6 +270,8 @@ struct sde_hw_rotator {
|
|||
spinlock_t rotisr_lock;
|
||||
|
||||
bool dbgmem;
|
||||
bool reset_hw_ts;
|
||||
u32 last_hw_ts;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
Loading…
Add table
Reference in a new issue