summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2016-09-23 20:19:04 -0700
committerGerrit - the friendly Code Review server <code-review@localhost>2016-09-23 20:19:03 -0700
commitbaa3d606abc47e1b53d43e1acef4f8ebb1f90964 (patch)
treed06ec070a084cd8ab8879827a5656d7b1cbebb9d /drivers
parent25d60ce52e64fa93cb45a150ab16354fe148ecc4 (diff)
parent1db5844b624a028df9ddbb76ca7e354669c025fe (diff)
Merge "msm: sde: Add pre/post power event handler in SDE rotator"
Diffstat (limited to 'drivers')
-rw-r--r--drivers/media/platform/msm/sde/rotator/sde_rotator_core.c9
-rw-r--r--drivers/media/platform/msm/sde/rotator/sde_rotator_core.h4
-rw-r--r--drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c104
-rw-r--r--drivers/media/platform/msm/sde/rotator/sde_rotator_r3_hwio.h3
-rw-r--r--drivers/media/platform/msm/sde/rotator/sde_rotator_r3_internal.h2
5 files changed, 119 insertions, 3 deletions
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c
index 3e5cbdecfba4..041a8219e145 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c
@@ -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;
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_core.h b/drivers/media/platform/msm/sde/rotator/sde_rotator_core.h
index 8659d361be07..aa17341de7c2 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_core.h
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_core.h
@@ -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);
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c
index e9d2dd5ec972..d2bc76874c48 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c
@@ -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;
}
@@ -1240,6 +1241,94 @@ static void sde_hw_rotator_swtc_destroy(struct sde_hw_rotator *rot)
}
/*
+ * 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)
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3_hwio.h b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3_hwio.h
index 3267e4418b3a..a748b87a231a 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3_hwio.h
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3_hwio.h
@@ -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)
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3_internal.h b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3_internal.h
index b95f838f463b..91ac3d0371fa 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3_internal.h
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3_internal.h
@@ -270,6 +270,8 @@ struct sde_hw_rotator {
spinlock_t rotisr_lock;
bool dbgmem;
+ bool reset_hw_ts;
+ u32 last_hw_ts;
};
/**