Loading drivers/media/platform/msm/sde/rotator/sde_rotator_core.c +8 −1 Original line number Diff line number Diff line Loading @@ -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) { Loading @@ -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; Loading drivers/media/platform/msm/sde/rotator/sde_rotator_core.h +4 −0 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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); Loading drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c +103 −1 Original line number Diff line number Diff line Loading @@ -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; } Loading Loading @@ -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 Loading Loading @@ -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) ? Loading Loading @@ -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); Loading Loading @@ -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; } Loading Loading @@ -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) Loading drivers/media/platform/msm/sde/rotator/sde_rotator_r3_hwio.h +2 −1 Original line number Diff line number Diff line Loading @@ -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) Loading drivers/media/platform/msm/sde/rotator/sde_rotator_r3_internal.h +2 −0 Original line number Diff line number Diff line Loading @@ -270,6 +270,8 @@ struct sde_hw_rotator { spinlock_t rotisr_lock; bool dbgmem; bool reset_hw_ts; u32 last_hw_ts; }; /** Loading Loading
drivers/media/platform/msm/sde/rotator/sde_rotator_core.c +8 −1 Original line number Diff line number Diff line Loading @@ -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) { Loading @@ -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; Loading
drivers/media/platform/msm/sde/rotator/sde_rotator_core.h +4 −0 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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); Loading
drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c +103 −1 Original line number Diff line number Diff line Loading @@ -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; } Loading Loading @@ -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 Loading Loading @@ -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) ? Loading Loading @@ -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); Loading Loading @@ -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; } Loading Loading @@ -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) Loading
drivers/media/platform/msm/sde/rotator/sde_rotator_r3_hwio.h +2 −1 Original line number Diff line number Diff line Loading @@ -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) Loading
drivers/media/platform/msm/sde/rotator/sde_rotator_r3_internal.h +2 −0 Original line number Diff line number Diff line Loading @@ -270,6 +270,8 @@ struct sde_hw_rotator { spinlock_t rotisr_lock; bool dbgmem; bool reset_hw_ts; u32 last_hw_ts; }; /** Loading