Loading drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c +179 −77 Original line number Original line Diff line number Diff line Loading @@ -552,6 +552,31 @@ struct sde_rot_cdp_params { /* Invalid software timestamp value for initialization */ /* Invalid software timestamp value for initialization */ #define SDE_REGDMA_SWTS_INVALID (~0) #define SDE_REGDMA_SWTS_INVALID (~0) /** * __sde_hw_rotator_get_timestamp - obtain rotator current timestamp * @rot: rotator context * @q_id: regdma queue id (low/high) * @return: current timestmap */ static u32 __sde_hw_rotator_get_timestamp(struct sde_hw_rotator *rot, u32 q_id) { struct sde_rot_data_type *mdata = sde_rot_get_mdata(); u32 ts; if (test_bit(SDE_CAPS_HW_TIMESTAMP, mdata->sde_caps_map)) { if (q_id == ROT_QUEUE_HIGH_PRIORITY) ts = SDE_ROTREG_READ(rot->mdss_base, ROTTOP_ROT_CNTR_0); else ts = SDE_ROTREG_READ(rot->mdss_base, ROTTOP_ROT_CNTR_1); } else { ts = SDE_ROTREG_READ(rot->mdss_base, REGDMA_TIMESTAMP_REG); if (q_id == ROT_QUEUE_LOW_PRIORITY) ts >>= SDE_REGDMA_SWTS_SHIFT; } return ts & SDE_REGDMA_SWTS_MASK; } /** /** * sde_hw_rotator_elapsed_swts - Find difference of 2 software timestamps * sde_hw_rotator_elapsed_swts - Find difference of 2 software timestamps * @ts_curr: current software timestamp * @ts_curr: current software timestamp Loading @@ -565,6 +590,61 @@ static int sde_hw_rotator_elapsed_swts(u32 ts_curr, u32 ts_prev) return sign_extend32(diff, (SDE_REGDMA_SWTS_SHIFT - 1)); return sign_extend32(diff, (SDE_REGDMA_SWTS_SHIFT - 1)); } } /** * sde_hw_rotator_pending_hwts - Check if the given context is still pending * @rot: Pointer to hw rotator * @ctx: Pointer to rotator context * @phwts: Pointer to returned reference hw timestamp, optional * @return: true if context has pending requests */ static int sde_hw_rotator_pending_hwts(struct sde_hw_rotator *rot, struct sde_hw_rotator_context *ctx, u32 *phwts) { u32 hwts; int ts_diff; bool pending; if (ctx->last_regdma_timestamp == SDE_REGDMA_SWTS_INVALID) { if (ctx->q_id == ROT_QUEUE_LOW_PRIORITY) hwts = SDE_ROTREG_READ(rot->mdss_base, ROTTOP_ROT_CNTR_1); else hwts = SDE_ROTREG_READ(rot->mdss_base, ROTTOP_ROT_CNTR_0); } else { hwts = ctx->last_regdma_timestamp; } hwts &= SDE_REGDMA_SWTS_MASK; ts_diff = sde_hw_rotator_elapsed_swts(ctx->timestamp, hwts); if (phwts) *phwts = hwts; pending = (ts_diff > 0) ? true : false; SDEROT_DBG("ts:0x%x, queue_id:%d, hwts:0x%x, pending:%d\n", ctx->timestamp, ctx->q_id, hwts, pending); SDEROT_EVTLOG(ctx->timestamp, hwts, ctx->q_id, ts_diff); return pending; } /** * sde_hw_rotator_update_hwts - update hw timestamp with given value * @rot: Pointer to hw rotator * @q_id: rotator queue id * @hwts: new hw timestamp */ static void sde_hw_rotator_update_hwts(struct sde_hw_rotator *rot, u32 q_id, u32 hwts) { if (q_id == ROT_QUEUE_LOW_PRIORITY) SDE_ROTREG_WRITE(rot->mdss_base, ROTTOP_ROT_CNTR_1, hwts); else SDE_ROTREG_WRITE(rot->mdss_base, ROTTOP_ROT_CNTR_0, hwts); } /** /** * sde_hw_rotator_pending_swts - Check if the given context is still pending * sde_hw_rotator_pending_swts - Check if the given context is still pending * @rot: Pointer to hw rotator * @rot: Pointer to hw rotator Loading Loading @@ -605,25 +685,22 @@ static int sde_hw_rotator_pending_swts(struct sde_hw_rotator *rot, /** /** * sde_hw_rotator_update_swts - update software timestamp with given value * sde_hw_rotator_update_swts - update software timestamp with given value * @rot: Pointer to hw rotator * @rot: Pointer to hw rotator * @ctx: Pointer to rotator contxt * @q_id: rotator queue id * @swts: new software timestamp * @swts: new software timestamp * @return: new combined swts */ */ static u32 sde_hw_rotator_update_swts(struct sde_hw_rotator *rot, static void sde_hw_rotator_update_swts(struct sde_hw_rotator *rot, struct sde_hw_rotator_context *ctx, u32 swts) u32 q_id, u32 swts) { { u32 mask = SDE_REGDMA_SWTS_MASK; u32 mask = SDE_REGDMA_SWTS_MASK; swts &= SDE_REGDMA_SWTS_MASK; swts &= SDE_REGDMA_SWTS_MASK; if (ctx->q_id == ROT_QUEUE_LOW_PRIORITY) { if (q_id == ROT_QUEUE_LOW_PRIORITY) { swts <<= SDE_REGDMA_SWTS_SHIFT; swts <<= SDE_REGDMA_SWTS_SHIFT; mask <<= SDE_REGDMA_SWTS_SHIFT; mask <<= SDE_REGDMA_SWTS_SHIFT; } } swts |= (SDE_ROTREG_READ(rot->mdss_base, REGDMA_TIMESTAMP_REG) & ~mask); swts |= (SDE_ROTREG_READ(rot->mdss_base, REGDMA_TIMESTAMP_REG) & ~mask); SDE_ROTREG_WRITE(rot->mdss_base, REGDMA_TIMESTAMP_REG, swts); SDE_ROTREG_WRITE(rot->mdss_base, REGDMA_TIMESTAMP_REG, swts); return swts; } } /** /** Loading Loading @@ -738,7 +815,7 @@ static int sde_hw_rotator_reset(struct sde_hw_rotator *rot, /* update timestamp register with current context */ /* update timestamp register with current context */ last_ts[ctx->q_id] = ctx->timestamp; last_ts[ctx->q_id] = ctx->timestamp; sde_hw_rotator_update_swts(rot, ctx, ctx->timestamp); rot->ops.update_ts(rot, ctx->q_id, ctx->timestamp); SDEROT_EVTLOG(ctx->timestamp); SDEROT_EVTLOG(ctx->timestamp); /* /* Loading @@ -762,8 +839,7 @@ static int sde_hw_rotator_reset(struct sde_hw_rotator *rot, if (t < elapsed_time) { if (t < elapsed_time) { elapsed_time = t; elapsed_time = t; last_ts[i] = rctx->timestamp; last_ts[i] = rctx->timestamp; sde_hw_rotator_update_swts(rot, rctx, rot->ops.update_ts(rot, i, last_ts[i]); last_ts[i]); } } SDEROT_DBG("rotctx[%d][%d], ts:%d\n", SDEROT_DBG("rotctx[%d][%d], ts:%d\n", Loading Loading @@ -808,9 +884,9 @@ static void _sde_hw_rotator_dump_status(struct sde_hw_rotator *rot, REGDMA_CSR_REGDMA_INT_STATUS)); REGDMA_CSR_REGDMA_INT_STATUS)); SDEROT_ERR( SDEROT_ERR( "ts = %x, q0_status = %x, q1_status = %x, block_status = %x\n", "ts0/ts1 = %x/%x, q0_status = %x, q1_status = %x, block_status = %x\n", SDE_ROTREG_READ(rot->mdss_base, __sde_hw_rotator_get_timestamp(rot, ROT_QUEUE_HIGH_PRIORITY), REGDMA_TIMESTAMP_REG), __sde_hw_rotator_get_timestamp(rot, ROT_QUEUE_LOW_PRIORITY), SDE_ROTREG_READ(rot->mdss_base, SDE_ROTREG_READ(rot->mdss_base, REGDMA_CSR_REGDMA_QUEUE_0_STATUS), REGDMA_CSR_REGDMA_QUEUE_0_STATUS), SDE_ROTREG_READ(rot->mdss_base, SDE_ROTREG_READ(rot->mdss_base, Loading Loading @@ -1775,6 +1851,7 @@ static u32 sde_hw_rotator_start_no_regdma(struct sde_hw_rotator_context *ctx, static u32 sde_hw_rotator_start_regdma(struct sde_hw_rotator_context *ctx, static u32 sde_hw_rotator_start_regdma(struct sde_hw_rotator_context *ctx, enum sde_rot_queue_prio queue_id) enum sde_rot_queue_prio queue_id) { { struct sde_rot_data_type *mdata = sde_rot_get_mdata(); struct sde_hw_rotator *rot = ctx->rot; struct sde_hw_rotator *rot = ctx->rot; char __iomem *wrptr; char __iomem *wrptr; u32 regdmaSlot; u32 regdmaSlot; Loading @@ -1785,9 +1862,19 @@ static u32 sde_hw_rotator_start_regdma(struct sde_hw_rotator_context *ctx, u32 swts = 0; u32 swts = 0; u32 mask = 0; u32 mask = 0; u32 trig_sel; u32 trig_sel; bool int_trigger = false; wrptr = sde_hw_rotator_get_regdma_segment(ctx); wrptr = sde_hw_rotator_get_regdma_segment(ctx); /* Enable HW timestamp if supported in rotator */ if (test_bit(SDE_CAPS_HW_TIMESTAMP, mdata->sde_caps_map)) { SDE_REGDMA_MODIFY(wrptr, ROTTOP_ROT_CNTR_CTRL, ~BIT(queue_id), BIT(queue_id)); int_trigger = true; } else if (ctx->sbuf_mode) { int_trigger = true; } /* /* * Last ROT command must be ROT_START before REGDMA start * Last ROT command must be ROT_START before REGDMA start */ */ Loading Loading @@ -1818,14 +1905,14 @@ static u32 sde_hw_rotator_start_regdma(struct sde_hw_rotator_context *ctx, if (queue_id == ROT_QUEUE_HIGH_PRIORITY) { if (queue_id == ROT_QUEUE_HIGH_PRIORITY) { SDE_ROTREG_WRITE(rot->mdss_base, SDE_ROTREG_WRITE(rot->mdss_base, REGDMA_CSR_REGDMA_QUEUE_0_SUBMIT, REGDMA_CSR_REGDMA_QUEUE_0_SUBMIT, (ctx->sbuf_mode ? enableInt : 0) | trig_sel | (int_trigger ? enableInt : 0) | trig_sel | ((length & 0x3ff) << 14) | offset); ((length & 0x3ff) << 14) | offset); swts = ctx->timestamp; swts = ctx->timestamp; mask = ~SDE_REGDMA_SWTS_MASK; mask = ~SDE_REGDMA_SWTS_MASK; } else { } else { SDE_ROTREG_WRITE(rot->mdss_base, SDE_ROTREG_WRITE(rot->mdss_base, REGDMA_CSR_REGDMA_QUEUE_1_SUBMIT, REGDMA_CSR_REGDMA_QUEUE_1_SUBMIT, (ctx->sbuf_mode ? enableInt : 0) | trig_sel | (int_trigger ? enableInt : 0) | trig_sel | ((length & 0x3ff) << 14) | offset); ((length & 0x3ff) << 14) | offset); swts = ctx->timestamp << SDE_REGDMA_SWTS_SHIFT; swts = ctx->timestamp << SDE_REGDMA_SWTS_SHIFT; mask = ~(SDE_REGDMA_SWTS_MASK << SDE_REGDMA_SWTS_SHIFT); mask = ~(SDE_REGDMA_SWTS_MASK << SDE_REGDMA_SWTS_SHIFT); Loading @@ -1833,8 +1920,8 @@ static u32 sde_hw_rotator_start_regdma(struct sde_hw_rotator_context *ctx, SDEROT_EVTLOG(ctx->timestamp, queue_id, length, offset, ctx->sbuf_mode); SDEROT_EVTLOG(ctx->timestamp, queue_id, length, offset, ctx->sbuf_mode); /* timestamp update can only be used in offline multi-context mode */ /* sw timestamp update can only be used in offline multi-context mode */ if (!ctx->sbuf_mode) { if (!int_trigger) { /* Write timestamp after previous rotator job finished */ /* Write timestamp after previous rotator job finished */ sde_hw_rotator_setup_timestamp_packet(ctx, mask, swts); sde_hw_rotator_setup_timestamp_packet(ctx, mask, swts); offset += length; offset += length; Loading Loading @@ -1957,7 +2044,7 @@ static u32 sde_hw_rotator_wait_done_regdma( SDEROT_DBG("Wait for REGDMA completion, ctx:%p, ts:%X\n", SDEROT_DBG("Wait for REGDMA completion, ctx:%p, ts:%X\n", ctx, ctx->timestamp); ctx, ctx->timestamp); rc = wait_event_timeout(ctx->regdma_waitq, rc = wait_event_timeout(ctx->regdma_waitq, !sde_hw_rotator_pending_swts(rot, ctx, &swts), !rot->ops.get_pending_ts(rot, ctx, &swts), ctx->sbuf_mode ? ctx->sbuf_mode ? msecs_to_jiffies(KOFF_TIMEOUT_SBUF) : msecs_to_jiffies(KOFF_TIMEOUT_SBUF) : msecs_to_jiffies(rot->koff_timeout)); msecs_to_jiffies(rot->koff_timeout)); Loading @@ -1976,7 +2063,7 @@ static u32 sde_hw_rotator_wait_done_regdma( if (rc == 0 || (status & REGDMA_INT_ERR_MASK) || abort) { if (rc == 0 || (status & REGDMA_INT_ERR_MASK) || abort) { bool pending; bool pending; pending = sde_hw_rotator_pending_swts(rot, ctx, &swts); pending = rot->ops.get_pending_ts(rot, ctx, &swts); SDEROT_ERR( SDEROT_ERR( "Timeout wait for regdma interrupt status, ts:0x%X/0x%X, pending:%d, abort:%d\n", "Timeout wait for regdma interrupt status, ts:0x%X/0x%X, pending:%d, abort:%d\n", ctx->timestamp, swts, pending, abort); ctx->timestamp, swts, pending, abort); Loading Loading @@ -2027,7 +2114,7 @@ static u32 sde_hw_rotator_wait_done_regdma( udelay(500); udelay(500); last_isr = SDE_ROTREG_READ(rot->mdss_base, last_isr = SDE_ROTREG_READ(rot->mdss_base, REGDMA_CSR_REGDMA_INT_STATUS); REGDMA_CSR_REGDMA_INT_STATUS); pending = sde_hw_rotator_pending_swts(rot, ctx, &swts); pending = rot->ops.get_pending_ts(rot, ctx, &swts); cnt--; cnt--; } while ((cnt > 0) && pending && } while ((cnt > 0) && pending && ((last_isr & REGDMA_INT_ERR_MASK) == 0)); ((last_isr & REGDMA_INT_ERR_MASK) == 0)); Loading Loading @@ -2063,9 +2150,11 @@ static u32 sde_hw_rotator_wait_done_regdma( * setup_rotator_ops - setup callback functions for the low-level HAL * setup_rotator_ops - setup callback functions for the low-level HAL * @ops: Pointer to low-level ops callback * @ops: Pointer to low-level ops callback * @mode: Operation mode (non-regdma or regdma) * @mode: Operation mode (non-regdma or regdma) * @use_hwts: HW timestamp support mode */ */ static void setup_rotator_ops(struct sde_hw_rotator_ops *ops, static void setup_rotator_ops(struct sde_hw_rotator_ops *ops, enum sde_rotator_regdma_mode mode) enum sde_rotator_regdma_mode mode, bool use_hwts) { { ops->setup_rotator_fetchengine = sde_hw_rotator_setup_fetchengine; ops->setup_rotator_fetchengine = sde_hw_rotator_setup_fetchengine; ops->setup_rotator_wbengine = sde_hw_rotator_setup_wbengine; ops->setup_rotator_wbengine = sde_hw_rotator_setup_wbengine; Loading @@ -2076,6 +2165,14 @@ static void setup_rotator_ops(struct sde_hw_rotator_ops *ops, ops->start_rotator = sde_hw_rotator_start_no_regdma; ops->start_rotator = sde_hw_rotator_start_no_regdma; ops->wait_rotator_done = sde_hw_rotator_wait_done_no_regdma; ops->wait_rotator_done = sde_hw_rotator_wait_done_no_regdma; } } if (use_hwts) { ops->get_pending_ts = sde_hw_rotator_pending_hwts; ops->update_ts = sde_hw_rotator_update_hwts; } else { ops->get_pending_ts = sde_hw_rotator_pending_swts; ops->update_ts = sde_hw_rotator_update_swts; } } } /* /* Loading Loading @@ -2177,7 +2274,7 @@ static void sde_hw_rotator_swts_destroy(struct sde_hw_rotator *rot) void sde_hw_rotator_pre_pmevent(struct sde_rot_mgr *mgr, bool pmon) void sde_hw_rotator_pre_pmevent(struct sde_rot_mgr *mgr, bool pmon) { { struct sde_hw_rotator *rot; struct sde_hw_rotator *rot; u32 l_ts, h_ts, swts, hwts; u32 l_ts, h_ts, l_hwts, h_hwts; u32 rotsts, regdmasts, rotopmode; u32 rotsts, regdmasts, rotopmode; /* /* Loading @@ -2192,29 +2289,30 @@ void sde_hw_rotator_pre_pmevent(struct sde_rot_mgr *mgr, bool pmon) h_ts = atomic_read(&rot->timestamp[ROT_QUEUE_HIGH_PRIORITY]); h_ts = atomic_read(&rot->timestamp[ROT_QUEUE_HIGH_PRIORITY]); l_ts = atomic_read(&rot->timestamp[ROT_QUEUE_LOW_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 */ /* Need to turn on clock to access rotator register */ sde_rotator_clk_ctrl(mgr, true); sde_rotator_clk_ctrl(mgr, true); hwts = SDE_ROTREG_READ(rot->mdss_base, REGDMA_TIMESTAMP_REG); l_hwts = __sde_hw_rotator_get_timestamp(rot, ROT_QUEUE_LOW_PRIORITY); h_hwts = __sde_hw_rotator_get_timestamp(rot, ROT_QUEUE_HIGH_PRIORITY); regdmasts = SDE_ROTREG_READ(rot->mdss_base, regdmasts = SDE_ROTREG_READ(rot->mdss_base, REGDMA_CSR_REGDMA_BLOCK_STATUS); REGDMA_CSR_REGDMA_BLOCK_STATUS); rotsts = SDE_ROTREG_READ(rot->mdss_base, ROTTOP_STATUS); rotsts = SDE_ROTREG_READ(rot->mdss_base, ROTTOP_STATUS); rotopmode = SDE_ROTREG_READ(rot->mdss_base, ROTTOP_OP_MODE); rotopmode = SDE_ROTREG_READ(rot->mdss_base, ROTTOP_OP_MODE); SDEROT_DBG( SDEROT_DBG( "swts:0x%x, hwts:0x%x, regdma-sts:0x%x, rottop-sts:0x%x, rottop-opmode:0x%x\n", "swts(l/h):0x%x/0x%x, hwts(l/h):0x%x/0x%x, regdma-sts:0x%x, rottop-sts:0x%x\n", swts, hwts, regdmasts, rotsts, rotopmode); l_ts, h_ts, l_hwts, h_hwts, SDEROT_EVTLOG(swts, hwts, regdmasts, rotsts, rotopmode); regdmasts, rotsts); SDEROT_EVTLOG(l_ts, h_ts, l_hwts, h_hwts, regdmasts, rotsts); if ((swts != hwts) && ((regdmasts & REGDMA_BUSY) || if (((l_ts != l_hwts) || (h_ts != h_hwts)) && ((regdmasts & REGDMA_BUSY) || (rotsts & ROT_STATUS_MASK))) { (rotsts & ROT_STATUS_MASK))) { SDEROT_ERR( SDEROT_ERR( "Mismatch SWTS with HWTS: swts:0x%x, hwts:0x%x, regdma-sts:0x%x, rottop-sts:0x%x\n", "Mismatch SWTS with HWTS: swts(l/h):0x%x/0x%x, hwts(l/h):0x%x/0x%x, regdma-sts:0x%x, rottop-sts:0x%x\n", swts, hwts, regdmasts, rotsts); l_ts, h_ts, l_hwts, h_hwts, regdmasts, rotsts); _sde_hw_rotator_dump_status(rot, NULL); _sde_hw_rotator_dump_status(rot, NULL); SDEROT_EVTLOG_TOUT_HANDLER("rot", "rot_dbg_bus", SDEROT_EVTLOG_TOUT_HANDLER("rot", "rot_dbg_bus", "vbif_dbg_bus", "panic"); "vbif_dbg_bus", "panic"); Loading Loading @@ -2250,7 +2348,7 @@ void sde_hw_rotator_pre_pmevent(struct sde_rot_mgr *mgr, bool pmon) void sde_hw_rotator_post_pmevent(struct sde_rot_mgr *mgr, bool pmon) void sde_hw_rotator_post_pmevent(struct sde_rot_mgr *mgr, bool pmon) { { struct sde_hw_rotator *rot; struct sde_hw_rotator *rot; u32 l_ts, h_ts, swts; u32 l_ts, h_ts; /* /* * After a power on event, the rotator HW is reset to default setting. * After a power on event, the rotator HW is reset to default setting. Loading @@ -2261,16 +2359,11 @@ void sde_hw_rotator_post_pmevent(struct sde_rot_mgr *mgr, bool pmon) h_ts = atomic_read(&rot->timestamp[ROT_QUEUE_HIGH_PRIORITY]); h_ts = atomic_read(&rot->timestamp[ROT_QUEUE_HIGH_PRIORITY]); l_ts = atomic_read(&rot->timestamp[ROT_QUEUE_LOW_PRIORITY]); l_ts = atomic_read(&rot->timestamp[ROT_QUEUE_LOW_PRIORITY]); /* contruct the combined timstamp */ SDEROT_DBG("h_ts:0x%x, l_ts;0x%x\n", h_ts, l_ts); swts = (h_ts & SDE_REGDMA_SWTS_MASK) | SDEROT_EVTLOG(h_ts, l_ts); ((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->reset_hw_ts = true; rot->last_hw_ts = swts; rot->last_hwts[ROT_QUEUE_LOW_PRIORITY] = l_ts; rot->last_hwts[ROT_QUEUE_HIGH_PRIORITY] = h_ts; } } } } Loading @@ -2292,7 +2385,8 @@ static void sde_hw_rotator_destroy(struct sde_rot_mgr *mgr) if (rot->irq_num >= 0) if (rot->irq_num >= 0) devm_free_irq(&mgr->pdev->dev, rot->irq_num, mdata); devm_free_irq(&mgr->pdev->dev, rot->irq_num, mdata); if (rot->mode == ROT_REGDMA_ON) if (!test_bit(SDE_CAPS_HW_TIMESTAMP, mdata->sde_caps_map) && rot->mode == ROT_REGDMA_ON) sde_hw_rotator_swts_destroy(rot); sde_hw_rotator_swts_destroy(rot); devm_kfree(&mgr->pdev->dev, mgr->hw_data); devm_kfree(&mgr->pdev->dev, mgr->hw_data); Loading @@ -2310,6 +2404,7 @@ static void sde_hw_rotator_destroy(struct sde_rot_mgr *mgr) static struct sde_rot_hw_resource *sde_hw_rotator_alloc_ext( static struct sde_rot_hw_resource *sde_hw_rotator_alloc_ext( struct sde_rot_mgr *mgr, u32 pipe_id, u32 wb_id) struct sde_rot_mgr *mgr, u32 pipe_id, u32 wb_id) { { struct sde_rot_data_type *mdata = sde_rot_get_mdata(); struct sde_hw_rotator_resource_info *resinfo; struct sde_hw_rotator_resource_info *resinfo; if (!mgr || !mgr->hw_data) { if (!mgr || !mgr->hw_data) { Loading Loading @@ -2338,7 +2433,8 @@ static struct sde_rot_hw_resource *sde_hw_rotator_alloc_ext( else { else { resinfo->hw.max_active = SDE_HW_ROT_REGDMA_TOTAL_CTX - 1; resinfo->hw.max_active = SDE_HW_ROT_REGDMA_TOTAL_CTX - 1; if (resinfo->rot->swts_buf.mapped == false) if (!test_bit(SDE_CAPS_HW_TIMESTAMP, mdata->sde_caps_map) && resinfo->rot->swts_buf.mapped == false) sde_hw_rotator_swts_create(resinfo->rot); sde_hw_rotator_swts_create(resinfo->rot); } } Loading Loading @@ -2561,40 +2657,43 @@ static int sde_hw_rotator_config(struct sde_rot_hw_resource *hw, */ */ rststs = SDE_ROTREG_READ(rot->mdss_base, REGDMA_RESET_STATUS_REG); rststs = SDE_ROTREG_READ(rot->mdss_base, REGDMA_RESET_STATUS_REG); if (!rot->reset_hw_ts && rststs) { if (!rot->reset_hw_ts && rststs) { u32 l_ts, h_ts, swts; u32 l_ts, h_ts, l_hwts, h_hwts; swts = SDE_ROTREG_READ(rot->mdss_base, REGDMA_TIMESTAMP_REG); h_hwts = __sde_hw_rotator_get_timestamp(rot, ROT_QUEUE_HIGH_PRIORITY); l_hwts = __sde_hw_rotator_get_timestamp(rot, ROT_QUEUE_LOW_PRIORITY); h_ts = atomic_read(&rot->timestamp[ROT_QUEUE_HIGH_PRIORITY]); h_ts = atomic_read(&rot->timestamp[ROT_QUEUE_HIGH_PRIORITY]); l_ts = atomic_read(&rot->timestamp[ROT_QUEUE_LOW_PRIORITY]); l_ts = atomic_read(&rot->timestamp[ROT_QUEUE_LOW_PRIORITY]); SDEROT_EVTLOG(0xbad0, rststs, swts, h_ts, l_ts); SDEROT_EVTLOG(0xbad0, rststs, l_hwts, h_hwts, l_ts, h_ts); if (ctx->q_id == ROT_QUEUE_HIGH_PRIORITY) if (ctx->q_id == ROT_QUEUE_HIGH_PRIORITY) h_ts = (h_ts - 1) & SDE_REGDMA_SWTS_MASK; h_ts = (h_ts - 1) & SDE_REGDMA_SWTS_MASK; else else l_ts = (l_ts - 1) & SDE_REGDMA_SWTS_MASK; l_ts = (l_ts - 1) & SDE_REGDMA_SWTS_MASK; /* construct the combined timstamp */ SDEROT_DBG("h_ts:0x%x, l_ts;0x%x\n", h_ts, l_ts); swts = (h_ts & SDE_REGDMA_SWTS_MASK) | SDEROT_EVTLOG(0x900d, h_ts, l_ts); ((l_ts & SDE_REGDMA_SWTS_MASK) << rot->last_hwts[ROT_QUEUE_LOW_PRIORITY] = l_ts; SDE_REGDMA_SWTS_SHIFT); rot->last_hwts[ROT_QUEUE_HIGH_PRIORITY] = h_ts; SDEROT_DBG("swts:0x%x, h_ts:0x%x, l_ts;0x%x\n", swts, h_ts, l_ts); SDEROT_EVTLOG(0x900d, swts, h_ts, l_ts); rot->last_hw_ts = swts; SDE_ROTREG_WRITE(rot->mdss_base, REGDMA_TIMESTAMP_REG, rot->ops.update_ts(rot, ROT_QUEUE_HIGH_PRIORITY, h_ts); rot->last_hw_ts); rot->ops.update_ts(rot, ROT_QUEUE_LOW_PRIORITY, l_ts); SDE_ROTREG_WRITE(rot->mdss_base, REGDMA_RESET_STATUS_REG, 0); SDE_ROTREG_WRITE(rot->mdss_base, REGDMA_RESET_STATUS_REG, 0); /* ensure write is issued to the rotator HW */ /* ensure write is issued to the rotator HW */ wmb(); wmb(); } } if (rot->reset_hw_ts) { if (rot->reset_hw_ts) { SDEROT_EVTLOG(rot->last_hw_ts); SDEROT_EVTLOG(rot->last_hwts[ROT_QUEUE_LOW_PRIORITY], SDE_ROTREG_WRITE(rot->mdss_base, REGDMA_TIMESTAMP_REG, rot->last_hwts[ROT_QUEUE_HIGH_PRIORITY]); rot->last_hw_ts); rot->ops.update_ts(rot, ROT_QUEUE_HIGH_PRIORITY, rot->last_hwts[ROT_QUEUE_HIGH_PRIORITY]); rot->ops.update_ts(rot, ROT_QUEUE_LOW_PRIORITY, rot->last_hwts[ROT_QUEUE_LOW_PRIORITY]); SDE_ROTREG_WRITE(rot->mdss_base, REGDMA_RESET_STATUS_REG, 0); SDE_ROTREG_WRITE(rot->mdss_base, REGDMA_RESET_STATUS_REG, 0); /* ensure write is issued to the rotator HW */ /* ensure write is issued to the rotator HW */ wmb(); wmb(); rot->reset_hw_ts = false; rot->reset_hw_ts = false; Loading Loading @@ -2775,7 +2874,7 @@ static int sde_hw_rotator_cancel(struct sde_rot_hw_resource *hw, } } spin_lock_irqsave(&rot->rotisr_lock, flags); spin_lock_irqsave(&rot->rotisr_lock, flags); sde_hw_rotator_update_swts(rot, ctx, ctx->timestamp); rot->ops.update_ts(rot, ctx->q_id, ctx->timestamp); spin_unlock_irqrestore(&rot->rotisr_lock, flags); spin_unlock_irqrestore(&rot->rotisr_lock, flags); SDEROT_EVTLOG(entry->item.session_id, ctx->timestamp); SDEROT_EVTLOG(entry->item.session_id, ctx->timestamp); Loading Loading @@ -3072,6 +3171,7 @@ static irqreturn_t sde_hw_rotator_rotirq_handler(int irq, void *ptr) */ */ static irqreturn_t sde_hw_rotator_regdmairq_handler(int irq, void *ptr) static irqreturn_t sde_hw_rotator_regdmairq_handler(int irq, void *ptr) { { struct sde_rot_data_type *mdata = sde_rot_get_mdata(); struct sde_hw_rotator *rot = ptr; struct sde_hw_rotator *rot = ptr; struct sde_hw_rotator_context *ctx, *tmp; struct sde_hw_rotator_context *ctx, *tmp; irqreturn_t ret = IRQ_NONE; irqreturn_t ret = IRQ_NONE; Loading @@ -3082,9 +3182,8 @@ static irqreturn_t sde_hw_rotator_regdmairq_handler(int irq, void *ptr) isr = SDE_ROTREG_READ(rot->mdss_base, REGDMA_CSR_REGDMA_INT_STATUS); isr = SDE_ROTREG_READ(rot->mdss_base, REGDMA_CSR_REGDMA_INT_STATUS); /* acknowledge interrupt before reading latest timestamp */ /* acknowledge interrupt before reading latest timestamp */ SDE_ROTREG_WRITE(rot->mdss_base, REGDMA_CSR_REGDMA_INT_CLEAR, isr); SDE_ROTREG_WRITE(rot->mdss_base, REGDMA_CSR_REGDMA_INT_CLEAR, isr); ts = SDE_ROTREG_READ(rot->mdss_base, REGDMA_TIMESTAMP_REG); SDEROT_DBG("intr_status = %8.8x, sw_TS:%X\n", isr, ts); SDEROT_DBG("intr_status = %8.8x\n", isr); /* Any REGDMA status, including error and watchdog timer, should /* Any REGDMA status, including error and watchdog timer, should * trigger and wake up waiting thread * trigger and wake up waiting thread Loading @@ -3098,21 +3197,21 @@ static irqreturn_t sde_hw_rotator_regdmairq_handler(int irq, void *ptr) */ */ if (isr & REGDMA_INT_HIGH_MASK) { if (isr & REGDMA_INT_HIGH_MASK) { q_id = ROT_QUEUE_HIGH_PRIORITY; q_id = ROT_QUEUE_HIGH_PRIORITY; ts = ts & SDE_REGDMA_SWTS_MASK; } else if (isr & REGDMA_INT_LOW_MASK) { } else if (isr & REGDMA_INT_LOW_MASK) { q_id = ROT_QUEUE_LOW_PRIORITY; q_id = ROT_QUEUE_LOW_PRIORITY; ts = (ts >> SDE_REGDMA_SWTS_SHIFT) & SDE_REGDMA_SWTS_MASK; } else { } else { SDEROT_ERR("unknown ISR status: isr=0x%X\n", isr); SDEROT_ERR("unknown ISR status: isr=0x%X\n", isr); goto done_isr_handle; goto done_isr_handle; } } ts = __sde_hw_rotator_get_timestamp(rot, q_id); /* /* * Timestamp packet is not available in sbuf mode. * Timestamp packet is not available in sbuf mode. * Simulate timestamp update in the handler instead. * Simulate timestamp update in the handler instead. */ */ if (list_empty(&rot->sbuf_ctx[q_id])) if (test_bit(SDE_CAPS_HW_TIMESTAMP, mdata->sde_caps_map) || list_empty(&rot->sbuf_ctx[q_id])) goto skip_sbuf; goto skip_sbuf; ctx = NULL; ctx = NULL; Loading @@ -3126,7 +3225,7 @@ static irqreturn_t sde_hw_rotator_regdmairq_handler(int irq, void *ptr) isr_tmp &= ~mask; isr_tmp &= ~mask; ctx = tmp; ctx = tmp; ts = ctx->timestamp; ts = ctx->timestamp; sde_hw_rotator_update_swts(rot, ctx, ts); rot->ops.update_ts(rot, ctx->q_id, ts); SDEROT_DBG("update swts:0x%X\n", ts); SDEROT_DBG("update swts:0x%X\n", ts); } } SDEROT_EVTLOG(isr, tmp->timestamp); SDEROT_EVTLOG(isr, tmp->timestamp); Loading Loading @@ -3173,6 +3272,8 @@ static irqreturn_t sde_hw_rotator_regdmairq_handler(int irq, void *ptr) for (j = 0; j < SDE_HW_ROT_REGDMA_TOTAL_CTX; j++) { for (j = 0; j < SDE_HW_ROT_REGDMA_TOTAL_CTX; j++) { ctx = rot->rotCtx[i][j]; ctx = rot->rotCtx[i][j]; if (ctx && ctx->last_regdma_isr_status == 0) { if (ctx && ctx->last_regdma_isr_status == 0) { ts = __sde_hw_rotator_get_timestamp( rot, i); ctx->last_regdma_isr_status = isr; ctx->last_regdma_isr_status = isr; ctx->last_regdma_timestamp = ts; ctx->last_regdma_timestamp = ts; wake_up_all(&ctx->regdma_waitq); wake_up_all(&ctx->regdma_waitq); Loading Loading @@ -3725,7 +3826,12 @@ int sde_rotator_r3_init(struct sde_rot_mgr *mgr) } } atomic_set(&rot->irq_enabled, 0); atomic_set(&rot->irq_enabled, 0); setup_rotator_ops(&rot->ops, rot->mode); ret = sde_rotator_hw_rev_init(rot); if (ret) goto error_hw_rev_init; setup_rotator_ops(&rot->ops, rot->mode, test_bit(SDE_CAPS_HW_TIMESTAMP, mdata->sde_caps_map)); spin_lock_init(&rot->rotctx_lock); spin_lock_init(&rot->rotctx_lock); spin_lock_init(&rot->rotisr_lock); spin_lock_init(&rot->rotisr_lock); Loading Loading @@ -3756,10 +3862,6 @@ int sde_rotator_r3_init(struct sde_rot_mgr *mgr) INIT_LIST_HEAD(&rot->sbuf_ctx[i]); INIT_LIST_HEAD(&rot->sbuf_ctx[i]); } } ret = sde_rotator_hw_rev_init(rot); if (ret) goto error_hw_rev_init; /* set rotator CBCR to shutoff memory/periphery on clock off.*/ /* set rotator CBCR to shutoff memory/periphery on clock off.*/ clk_set_flags(mgr->rot_clk[SDE_ROTATOR_CLK_MDSS_ROT].clk, clk_set_flags(mgr->rot_clk[SDE_ROTATOR_CLK_MDSS_ROT].clk, CLKFLAG_NORETAIN_MEM); CLKFLAG_NORETAIN_MEM); Loading drivers/media/platform/msm/sde/rotator/sde_rotator_r3_hwio.h +7 −0 Original line number Original line Diff line number Diff line Loading @@ -44,6 +44,13 @@ #define ROTTOP_DEBUGBUS_STATUS (SDE_ROT_ROTTOP_OFFSET+0x54) #define ROTTOP_DEBUGBUS_STATUS (SDE_ROT_ROTTOP_OFFSET+0x54) #define ROTTOP_ROT_UBWC_DEC_VERSION (SDE_ROT_ROTTOP_OFFSET+0x58) #define ROTTOP_ROT_UBWC_DEC_VERSION (SDE_ROT_ROTTOP_OFFSET+0x58) #define ROTTOP_ROT_UBWC_ENC_VERSION (SDE_ROT_ROTTOP_OFFSET+0x5C) #define ROTTOP_ROT_UBWC_ENC_VERSION (SDE_ROT_ROTTOP_OFFSET+0x5C) #define ROTTOP_ROT_CNTR_CTRL (SDE_ROT_ROTTOP_OFFSET+0x60) #define ROTTOP_ROT_CNTR_0 (SDE_ROT_ROTTOP_OFFSET+0x64) #define ROTTOP_ROT_CNTR_1 (SDE_ROT_ROTTOP_OFFSET+0x68) #define ROTTOP_ROT_SCRATCH_0 (SDE_ROT_ROTTOP_OFFSET+0x70) #define ROTTOP_ROT_SCRATCH_1 (SDE_ROT_ROTTOP_OFFSET+0x74) #define ROTTOP_ROT_SCRATCH_2 (SDE_ROT_ROTTOP_OFFSET+0x78) #define ROTTOP_ROT_SCRATCH_3 (SDE_ROT_ROTTOP_OFFSET+0x7C) #define ROTTOP_START_CTRL_TRIG_SEL_SW 0 #define ROTTOP_START_CTRL_TRIG_SEL_SW 0 #define ROTTOP_START_CTRL_TRIG_SEL_DONE 1 #define ROTTOP_START_CTRL_TRIG_SEL_DONE 1 Loading drivers/media/platform/msm/sde/rotator/sde_rotator_r3_internal.h +26 −1 Original line number Original line Diff line number Diff line Loading @@ -180,6 +180,31 @@ struct sde_hw_rotator_ops { struct sde_hw_rotator_context *ctx, struct sde_hw_rotator_context *ctx, enum sde_rot_queue_prio queue_id, enum sde_rot_queue_prio queue_id, u32 flags); u32 flags); /** * get_pending_ts(): * Obtain current active timestamp from rotator hw * @rot: HW Rotator structure * @ctx: Rotator context * @ts: current timestamp return from rot hw * Returns: true if context has pending requests */ int (*get_pending_ts)( struct sde_hw_rotator *rot, struct sde_hw_rotator_context *ctx, u32 *ts); /** * update_ts(): * Update rotator timestmap with given value * @rot: HW Rotator structure * @q_id: rotator queue id * @ts: new timestamp for rotator */ void (*update_ts)( struct sde_hw_rotator *rot, u32 q_id, u32 ts); }; }; /** /** Loading Loading @@ -314,7 +339,7 @@ struct sde_hw_rotator { bool dbgmem; bool dbgmem; bool reset_hw_ts; bool reset_hw_ts; u32 last_hw_ts; u32 last_hwts[ROT_QUEUE_MAX]; u32 koff_timeout; u32 koff_timeout; u32 vid_trigger; u32 vid_trigger; u32 cmd_trigger; u32 cmd_trigger; Loading Loading
drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c +179 −77 Original line number Original line Diff line number Diff line Loading @@ -552,6 +552,31 @@ struct sde_rot_cdp_params { /* Invalid software timestamp value for initialization */ /* Invalid software timestamp value for initialization */ #define SDE_REGDMA_SWTS_INVALID (~0) #define SDE_REGDMA_SWTS_INVALID (~0) /** * __sde_hw_rotator_get_timestamp - obtain rotator current timestamp * @rot: rotator context * @q_id: regdma queue id (low/high) * @return: current timestmap */ static u32 __sde_hw_rotator_get_timestamp(struct sde_hw_rotator *rot, u32 q_id) { struct sde_rot_data_type *mdata = sde_rot_get_mdata(); u32 ts; if (test_bit(SDE_CAPS_HW_TIMESTAMP, mdata->sde_caps_map)) { if (q_id == ROT_QUEUE_HIGH_PRIORITY) ts = SDE_ROTREG_READ(rot->mdss_base, ROTTOP_ROT_CNTR_0); else ts = SDE_ROTREG_READ(rot->mdss_base, ROTTOP_ROT_CNTR_1); } else { ts = SDE_ROTREG_READ(rot->mdss_base, REGDMA_TIMESTAMP_REG); if (q_id == ROT_QUEUE_LOW_PRIORITY) ts >>= SDE_REGDMA_SWTS_SHIFT; } return ts & SDE_REGDMA_SWTS_MASK; } /** /** * sde_hw_rotator_elapsed_swts - Find difference of 2 software timestamps * sde_hw_rotator_elapsed_swts - Find difference of 2 software timestamps * @ts_curr: current software timestamp * @ts_curr: current software timestamp Loading @@ -565,6 +590,61 @@ static int sde_hw_rotator_elapsed_swts(u32 ts_curr, u32 ts_prev) return sign_extend32(diff, (SDE_REGDMA_SWTS_SHIFT - 1)); return sign_extend32(diff, (SDE_REGDMA_SWTS_SHIFT - 1)); } } /** * sde_hw_rotator_pending_hwts - Check if the given context is still pending * @rot: Pointer to hw rotator * @ctx: Pointer to rotator context * @phwts: Pointer to returned reference hw timestamp, optional * @return: true if context has pending requests */ static int sde_hw_rotator_pending_hwts(struct sde_hw_rotator *rot, struct sde_hw_rotator_context *ctx, u32 *phwts) { u32 hwts; int ts_diff; bool pending; if (ctx->last_regdma_timestamp == SDE_REGDMA_SWTS_INVALID) { if (ctx->q_id == ROT_QUEUE_LOW_PRIORITY) hwts = SDE_ROTREG_READ(rot->mdss_base, ROTTOP_ROT_CNTR_1); else hwts = SDE_ROTREG_READ(rot->mdss_base, ROTTOP_ROT_CNTR_0); } else { hwts = ctx->last_regdma_timestamp; } hwts &= SDE_REGDMA_SWTS_MASK; ts_diff = sde_hw_rotator_elapsed_swts(ctx->timestamp, hwts); if (phwts) *phwts = hwts; pending = (ts_diff > 0) ? true : false; SDEROT_DBG("ts:0x%x, queue_id:%d, hwts:0x%x, pending:%d\n", ctx->timestamp, ctx->q_id, hwts, pending); SDEROT_EVTLOG(ctx->timestamp, hwts, ctx->q_id, ts_diff); return pending; } /** * sde_hw_rotator_update_hwts - update hw timestamp with given value * @rot: Pointer to hw rotator * @q_id: rotator queue id * @hwts: new hw timestamp */ static void sde_hw_rotator_update_hwts(struct sde_hw_rotator *rot, u32 q_id, u32 hwts) { if (q_id == ROT_QUEUE_LOW_PRIORITY) SDE_ROTREG_WRITE(rot->mdss_base, ROTTOP_ROT_CNTR_1, hwts); else SDE_ROTREG_WRITE(rot->mdss_base, ROTTOP_ROT_CNTR_0, hwts); } /** /** * sde_hw_rotator_pending_swts - Check if the given context is still pending * sde_hw_rotator_pending_swts - Check if the given context is still pending * @rot: Pointer to hw rotator * @rot: Pointer to hw rotator Loading Loading @@ -605,25 +685,22 @@ static int sde_hw_rotator_pending_swts(struct sde_hw_rotator *rot, /** /** * sde_hw_rotator_update_swts - update software timestamp with given value * sde_hw_rotator_update_swts - update software timestamp with given value * @rot: Pointer to hw rotator * @rot: Pointer to hw rotator * @ctx: Pointer to rotator contxt * @q_id: rotator queue id * @swts: new software timestamp * @swts: new software timestamp * @return: new combined swts */ */ static u32 sde_hw_rotator_update_swts(struct sde_hw_rotator *rot, static void sde_hw_rotator_update_swts(struct sde_hw_rotator *rot, struct sde_hw_rotator_context *ctx, u32 swts) u32 q_id, u32 swts) { { u32 mask = SDE_REGDMA_SWTS_MASK; u32 mask = SDE_REGDMA_SWTS_MASK; swts &= SDE_REGDMA_SWTS_MASK; swts &= SDE_REGDMA_SWTS_MASK; if (ctx->q_id == ROT_QUEUE_LOW_PRIORITY) { if (q_id == ROT_QUEUE_LOW_PRIORITY) { swts <<= SDE_REGDMA_SWTS_SHIFT; swts <<= SDE_REGDMA_SWTS_SHIFT; mask <<= SDE_REGDMA_SWTS_SHIFT; mask <<= SDE_REGDMA_SWTS_SHIFT; } } swts |= (SDE_ROTREG_READ(rot->mdss_base, REGDMA_TIMESTAMP_REG) & ~mask); swts |= (SDE_ROTREG_READ(rot->mdss_base, REGDMA_TIMESTAMP_REG) & ~mask); SDE_ROTREG_WRITE(rot->mdss_base, REGDMA_TIMESTAMP_REG, swts); SDE_ROTREG_WRITE(rot->mdss_base, REGDMA_TIMESTAMP_REG, swts); return swts; } } /** /** Loading Loading @@ -738,7 +815,7 @@ static int sde_hw_rotator_reset(struct sde_hw_rotator *rot, /* update timestamp register with current context */ /* update timestamp register with current context */ last_ts[ctx->q_id] = ctx->timestamp; last_ts[ctx->q_id] = ctx->timestamp; sde_hw_rotator_update_swts(rot, ctx, ctx->timestamp); rot->ops.update_ts(rot, ctx->q_id, ctx->timestamp); SDEROT_EVTLOG(ctx->timestamp); SDEROT_EVTLOG(ctx->timestamp); /* /* Loading @@ -762,8 +839,7 @@ static int sde_hw_rotator_reset(struct sde_hw_rotator *rot, if (t < elapsed_time) { if (t < elapsed_time) { elapsed_time = t; elapsed_time = t; last_ts[i] = rctx->timestamp; last_ts[i] = rctx->timestamp; sde_hw_rotator_update_swts(rot, rctx, rot->ops.update_ts(rot, i, last_ts[i]); last_ts[i]); } } SDEROT_DBG("rotctx[%d][%d], ts:%d\n", SDEROT_DBG("rotctx[%d][%d], ts:%d\n", Loading Loading @@ -808,9 +884,9 @@ static void _sde_hw_rotator_dump_status(struct sde_hw_rotator *rot, REGDMA_CSR_REGDMA_INT_STATUS)); REGDMA_CSR_REGDMA_INT_STATUS)); SDEROT_ERR( SDEROT_ERR( "ts = %x, q0_status = %x, q1_status = %x, block_status = %x\n", "ts0/ts1 = %x/%x, q0_status = %x, q1_status = %x, block_status = %x\n", SDE_ROTREG_READ(rot->mdss_base, __sde_hw_rotator_get_timestamp(rot, ROT_QUEUE_HIGH_PRIORITY), REGDMA_TIMESTAMP_REG), __sde_hw_rotator_get_timestamp(rot, ROT_QUEUE_LOW_PRIORITY), SDE_ROTREG_READ(rot->mdss_base, SDE_ROTREG_READ(rot->mdss_base, REGDMA_CSR_REGDMA_QUEUE_0_STATUS), REGDMA_CSR_REGDMA_QUEUE_0_STATUS), SDE_ROTREG_READ(rot->mdss_base, SDE_ROTREG_READ(rot->mdss_base, Loading Loading @@ -1775,6 +1851,7 @@ static u32 sde_hw_rotator_start_no_regdma(struct sde_hw_rotator_context *ctx, static u32 sde_hw_rotator_start_regdma(struct sde_hw_rotator_context *ctx, static u32 sde_hw_rotator_start_regdma(struct sde_hw_rotator_context *ctx, enum sde_rot_queue_prio queue_id) enum sde_rot_queue_prio queue_id) { { struct sde_rot_data_type *mdata = sde_rot_get_mdata(); struct sde_hw_rotator *rot = ctx->rot; struct sde_hw_rotator *rot = ctx->rot; char __iomem *wrptr; char __iomem *wrptr; u32 regdmaSlot; u32 regdmaSlot; Loading @@ -1785,9 +1862,19 @@ static u32 sde_hw_rotator_start_regdma(struct sde_hw_rotator_context *ctx, u32 swts = 0; u32 swts = 0; u32 mask = 0; u32 mask = 0; u32 trig_sel; u32 trig_sel; bool int_trigger = false; wrptr = sde_hw_rotator_get_regdma_segment(ctx); wrptr = sde_hw_rotator_get_regdma_segment(ctx); /* Enable HW timestamp if supported in rotator */ if (test_bit(SDE_CAPS_HW_TIMESTAMP, mdata->sde_caps_map)) { SDE_REGDMA_MODIFY(wrptr, ROTTOP_ROT_CNTR_CTRL, ~BIT(queue_id), BIT(queue_id)); int_trigger = true; } else if (ctx->sbuf_mode) { int_trigger = true; } /* /* * Last ROT command must be ROT_START before REGDMA start * Last ROT command must be ROT_START before REGDMA start */ */ Loading Loading @@ -1818,14 +1905,14 @@ static u32 sde_hw_rotator_start_regdma(struct sde_hw_rotator_context *ctx, if (queue_id == ROT_QUEUE_HIGH_PRIORITY) { if (queue_id == ROT_QUEUE_HIGH_PRIORITY) { SDE_ROTREG_WRITE(rot->mdss_base, SDE_ROTREG_WRITE(rot->mdss_base, REGDMA_CSR_REGDMA_QUEUE_0_SUBMIT, REGDMA_CSR_REGDMA_QUEUE_0_SUBMIT, (ctx->sbuf_mode ? enableInt : 0) | trig_sel | (int_trigger ? enableInt : 0) | trig_sel | ((length & 0x3ff) << 14) | offset); ((length & 0x3ff) << 14) | offset); swts = ctx->timestamp; swts = ctx->timestamp; mask = ~SDE_REGDMA_SWTS_MASK; mask = ~SDE_REGDMA_SWTS_MASK; } else { } else { SDE_ROTREG_WRITE(rot->mdss_base, SDE_ROTREG_WRITE(rot->mdss_base, REGDMA_CSR_REGDMA_QUEUE_1_SUBMIT, REGDMA_CSR_REGDMA_QUEUE_1_SUBMIT, (ctx->sbuf_mode ? enableInt : 0) | trig_sel | (int_trigger ? enableInt : 0) | trig_sel | ((length & 0x3ff) << 14) | offset); ((length & 0x3ff) << 14) | offset); swts = ctx->timestamp << SDE_REGDMA_SWTS_SHIFT; swts = ctx->timestamp << SDE_REGDMA_SWTS_SHIFT; mask = ~(SDE_REGDMA_SWTS_MASK << SDE_REGDMA_SWTS_SHIFT); mask = ~(SDE_REGDMA_SWTS_MASK << SDE_REGDMA_SWTS_SHIFT); Loading @@ -1833,8 +1920,8 @@ static u32 sde_hw_rotator_start_regdma(struct sde_hw_rotator_context *ctx, SDEROT_EVTLOG(ctx->timestamp, queue_id, length, offset, ctx->sbuf_mode); SDEROT_EVTLOG(ctx->timestamp, queue_id, length, offset, ctx->sbuf_mode); /* timestamp update can only be used in offline multi-context mode */ /* sw timestamp update can only be used in offline multi-context mode */ if (!ctx->sbuf_mode) { if (!int_trigger) { /* Write timestamp after previous rotator job finished */ /* Write timestamp after previous rotator job finished */ sde_hw_rotator_setup_timestamp_packet(ctx, mask, swts); sde_hw_rotator_setup_timestamp_packet(ctx, mask, swts); offset += length; offset += length; Loading Loading @@ -1957,7 +2044,7 @@ static u32 sde_hw_rotator_wait_done_regdma( SDEROT_DBG("Wait for REGDMA completion, ctx:%p, ts:%X\n", SDEROT_DBG("Wait for REGDMA completion, ctx:%p, ts:%X\n", ctx, ctx->timestamp); ctx, ctx->timestamp); rc = wait_event_timeout(ctx->regdma_waitq, rc = wait_event_timeout(ctx->regdma_waitq, !sde_hw_rotator_pending_swts(rot, ctx, &swts), !rot->ops.get_pending_ts(rot, ctx, &swts), ctx->sbuf_mode ? ctx->sbuf_mode ? msecs_to_jiffies(KOFF_TIMEOUT_SBUF) : msecs_to_jiffies(KOFF_TIMEOUT_SBUF) : msecs_to_jiffies(rot->koff_timeout)); msecs_to_jiffies(rot->koff_timeout)); Loading @@ -1976,7 +2063,7 @@ static u32 sde_hw_rotator_wait_done_regdma( if (rc == 0 || (status & REGDMA_INT_ERR_MASK) || abort) { if (rc == 0 || (status & REGDMA_INT_ERR_MASK) || abort) { bool pending; bool pending; pending = sde_hw_rotator_pending_swts(rot, ctx, &swts); pending = rot->ops.get_pending_ts(rot, ctx, &swts); SDEROT_ERR( SDEROT_ERR( "Timeout wait for regdma interrupt status, ts:0x%X/0x%X, pending:%d, abort:%d\n", "Timeout wait for regdma interrupt status, ts:0x%X/0x%X, pending:%d, abort:%d\n", ctx->timestamp, swts, pending, abort); ctx->timestamp, swts, pending, abort); Loading Loading @@ -2027,7 +2114,7 @@ static u32 sde_hw_rotator_wait_done_regdma( udelay(500); udelay(500); last_isr = SDE_ROTREG_READ(rot->mdss_base, last_isr = SDE_ROTREG_READ(rot->mdss_base, REGDMA_CSR_REGDMA_INT_STATUS); REGDMA_CSR_REGDMA_INT_STATUS); pending = sde_hw_rotator_pending_swts(rot, ctx, &swts); pending = rot->ops.get_pending_ts(rot, ctx, &swts); cnt--; cnt--; } while ((cnt > 0) && pending && } while ((cnt > 0) && pending && ((last_isr & REGDMA_INT_ERR_MASK) == 0)); ((last_isr & REGDMA_INT_ERR_MASK) == 0)); Loading Loading @@ -2063,9 +2150,11 @@ static u32 sde_hw_rotator_wait_done_regdma( * setup_rotator_ops - setup callback functions for the low-level HAL * setup_rotator_ops - setup callback functions for the low-level HAL * @ops: Pointer to low-level ops callback * @ops: Pointer to low-level ops callback * @mode: Operation mode (non-regdma or regdma) * @mode: Operation mode (non-regdma or regdma) * @use_hwts: HW timestamp support mode */ */ static void setup_rotator_ops(struct sde_hw_rotator_ops *ops, static void setup_rotator_ops(struct sde_hw_rotator_ops *ops, enum sde_rotator_regdma_mode mode) enum sde_rotator_regdma_mode mode, bool use_hwts) { { ops->setup_rotator_fetchengine = sde_hw_rotator_setup_fetchengine; ops->setup_rotator_fetchengine = sde_hw_rotator_setup_fetchengine; ops->setup_rotator_wbengine = sde_hw_rotator_setup_wbengine; ops->setup_rotator_wbengine = sde_hw_rotator_setup_wbengine; Loading @@ -2076,6 +2165,14 @@ static void setup_rotator_ops(struct sde_hw_rotator_ops *ops, ops->start_rotator = sde_hw_rotator_start_no_regdma; ops->start_rotator = sde_hw_rotator_start_no_regdma; ops->wait_rotator_done = sde_hw_rotator_wait_done_no_regdma; ops->wait_rotator_done = sde_hw_rotator_wait_done_no_regdma; } } if (use_hwts) { ops->get_pending_ts = sde_hw_rotator_pending_hwts; ops->update_ts = sde_hw_rotator_update_hwts; } else { ops->get_pending_ts = sde_hw_rotator_pending_swts; ops->update_ts = sde_hw_rotator_update_swts; } } } /* /* Loading Loading @@ -2177,7 +2274,7 @@ static void sde_hw_rotator_swts_destroy(struct sde_hw_rotator *rot) void sde_hw_rotator_pre_pmevent(struct sde_rot_mgr *mgr, bool pmon) void sde_hw_rotator_pre_pmevent(struct sde_rot_mgr *mgr, bool pmon) { { struct sde_hw_rotator *rot; struct sde_hw_rotator *rot; u32 l_ts, h_ts, swts, hwts; u32 l_ts, h_ts, l_hwts, h_hwts; u32 rotsts, regdmasts, rotopmode; u32 rotsts, regdmasts, rotopmode; /* /* Loading @@ -2192,29 +2289,30 @@ void sde_hw_rotator_pre_pmevent(struct sde_rot_mgr *mgr, bool pmon) h_ts = atomic_read(&rot->timestamp[ROT_QUEUE_HIGH_PRIORITY]); h_ts = atomic_read(&rot->timestamp[ROT_QUEUE_HIGH_PRIORITY]); l_ts = atomic_read(&rot->timestamp[ROT_QUEUE_LOW_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 */ /* Need to turn on clock to access rotator register */ sde_rotator_clk_ctrl(mgr, true); sde_rotator_clk_ctrl(mgr, true); hwts = SDE_ROTREG_READ(rot->mdss_base, REGDMA_TIMESTAMP_REG); l_hwts = __sde_hw_rotator_get_timestamp(rot, ROT_QUEUE_LOW_PRIORITY); h_hwts = __sde_hw_rotator_get_timestamp(rot, ROT_QUEUE_HIGH_PRIORITY); regdmasts = SDE_ROTREG_READ(rot->mdss_base, regdmasts = SDE_ROTREG_READ(rot->mdss_base, REGDMA_CSR_REGDMA_BLOCK_STATUS); REGDMA_CSR_REGDMA_BLOCK_STATUS); rotsts = SDE_ROTREG_READ(rot->mdss_base, ROTTOP_STATUS); rotsts = SDE_ROTREG_READ(rot->mdss_base, ROTTOP_STATUS); rotopmode = SDE_ROTREG_READ(rot->mdss_base, ROTTOP_OP_MODE); rotopmode = SDE_ROTREG_READ(rot->mdss_base, ROTTOP_OP_MODE); SDEROT_DBG( SDEROT_DBG( "swts:0x%x, hwts:0x%x, regdma-sts:0x%x, rottop-sts:0x%x, rottop-opmode:0x%x\n", "swts(l/h):0x%x/0x%x, hwts(l/h):0x%x/0x%x, regdma-sts:0x%x, rottop-sts:0x%x\n", swts, hwts, regdmasts, rotsts, rotopmode); l_ts, h_ts, l_hwts, h_hwts, SDEROT_EVTLOG(swts, hwts, regdmasts, rotsts, rotopmode); regdmasts, rotsts); SDEROT_EVTLOG(l_ts, h_ts, l_hwts, h_hwts, regdmasts, rotsts); if ((swts != hwts) && ((regdmasts & REGDMA_BUSY) || if (((l_ts != l_hwts) || (h_ts != h_hwts)) && ((regdmasts & REGDMA_BUSY) || (rotsts & ROT_STATUS_MASK))) { (rotsts & ROT_STATUS_MASK))) { SDEROT_ERR( SDEROT_ERR( "Mismatch SWTS with HWTS: swts:0x%x, hwts:0x%x, regdma-sts:0x%x, rottop-sts:0x%x\n", "Mismatch SWTS with HWTS: swts(l/h):0x%x/0x%x, hwts(l/h):0x%x/0x%x, regdma-sts:0x%x, rottop-sts:0x%x\n", swts, hwts, regdmasts, rotsts); l_ts, h_ts, l_hwts, h_hwts, regdmasts, rotsts); _sde_hw_rotator_dump_status(rot, NULL); _sde_hw_rotator_dump_status(rot, NULL); SDEROT_EVTLOG_TOUT_HANDLER("rot", "rot_dbg_bus", SDEROT_EVTLOG_TOUT_HANDLER("rot", "rot_dbg_bus", "vbif_dbg_bus", "panic"); "vbif_dbg_bus", "panic"); Loading Loading @@ -2250,7 +2348,7 @@ void sde_hw_rotator_pre_pmevent(struct sde_rot_mgr *mgr, bool pmon) void sde_hw_rotator_post_pmevent(struct sde_rot_mgr *mgr, bool pmon) void sde_hw_rotator_post_pmevent(struct sde_rot_mgr *mgr, bool pmon) { { struct sde_hw_rotator *rot; struct sde_hw_rotator *rot; u32 l_ts, h_ts, swts; u32 l_ts, h_ts; /* /* * After a power on event, the rotator HW is reset to default setting. * After a power on event, the rotator HW is reset to default setting. Loading @@ -2261,16 +2359,11 @@ void sde_hw_rotator_post_pmevent(struct sde_rot_mgr *mgr, bool pmon) h_ts = atomic_read(&rot->timestamp[ROT_QUEUE_HIGH_PRIORITY]); h_ts = atomic_read(&rot->timestamp[ROT_QUEUE_HIGH_PRIORITY]); l_ts = atomic_read(&rot->timestamp[ROT_QUEUE_LOW_PRIORITY]); l_ts = atomic_read(&rot->timestamp[ROT_QUEUE_LOW_PRIORITY]); /* contruct the combined timstamp */ SDEROT_DBG("h_ts:0x%x, l_ts;0x%x\n", h_ts, l_ts); swts = (h_ts & SDE_REGDMA_SWTS_MASK) | SDEROT_EVTLOG(h_ts, l_ts); ((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->reset_hw_ts = true; rot->last_hw_ts = swts; rot->last_hwts[ROT_QUEUE_LOW_PRIORITY] = l_ts; rot->last_hwts[ROT_QUEUE_HIGH_PRIORITY] = h_ts; } } } } Loading @@ -2292,7 +2385,8 @@ static void sde_hw_rotator_destroy(struct sde_rot_mgr *mgr) if (rot->irq_num >= 0) if (rot->irq_num >= 0) devm_free_irq(&mgr->pdev->dev, rot->irq_num, mdata); devm_free_irq(&mgr->pdev->dev, rot->irq_num, mdata); if (rot->mode == ROT_REGDMA_ON) if (!test_bit(SDE_CAPS_HW_TIMESTAMP, mdata->sde_caps_map) && rot->mode == ROT_REGDMA_ON) sde_hw_rotator_swts_destroy(rot); sde_hw_rotator_swts_destroy(rot); devm_kfree(&mgr->pdev->dev, mgr->hw_data); devm_kfree(&mgr->pdev->dev, mgr->hw_data); Loading @@ -2310,6 +2404,7 @@ static void sde_hw_rotator_destroy(struct sde_rot_mgr *mgr) static struct sde_rot_hw_resource *sde_hw_rotator_alloc_ext( static struct sde_rot_hw_resource *sde_hw_rotator_alloc_ext( struct sde_rot_mgr *mgr, u32 pipe_id, u32 wb_id) struct sde_rot_mgr *mgr, u32 pipe_id, u32 wb_id) { { struct sde_rot_data_type *mdata = sde_rot_get_mdata(); struct sde_hw_rotator_resource_info *resinfo; struct sde_hw_rotator_resource_info *resinfo; if (!mgr || !mgr->hw_data) { if (!mgr || !mgr->hw_data) { Loading Loading @@ -2338,7 +2433,8 @@ static struct sde_rot_hw_resource *sde_hw_rotator_alloc_ext( else { else { resinfo->hw.max_active = SDE_HW_ROT_REGDMA_TOTAL_CTX - 1; resinfo->hw.max_active = SDE_HW_ROT_REGDMA_TOTAL_CTX - 1; if (resinfo->rot->swts_buf.mapped == false) if (!test_bit(SDE_CAPS_HW_TIMESTAMP, mdata->sde_caps_map) && resinfo->rot->swts_buf.mapped == false) sde_hw_rotator_swts_create(resinfo->rot); sde_hw_rotator_swts_create(resinfo->rot); } } Loading Loading @@ -2561,40 +2657,43 @@ static int sde_hw_rotator_config(struct sde_rot_hw_resource *hw, */ */ rststs = SDE_ROTREG_READ(rot->mdss_base, REGDMA_RESET_STATUS_REG); rststs = SDE_ROTREG_READ(rot->mdss_base, REGDMA_RESET_STATUS_REG); if (!rot->reset_hw_ts && rststs) { if (!rot->reset_hw_ts && rststs) { u32 l_ts, h_ts, swts; u32 l_ts, h_ts, l_hwts, h_hwts; swts = SDE_ROTREG_READ(rot->mdss_base, REGDMA_TIMESTAMP_REG); h_hwts = __sde_hw_rotator_get_timestamp(rot, ROT_QUEUE_HIGH_PRIORITY); l_hwts = __sde_hw_rotator_get_timestamp(rot, ROT_QUEUE_LOW_PRIORITY); h_ts = atomic_read(&rot->timestamp[ROT_QUEUE_HIGH_PRIORITY]); h_ts = atomic_read(&rot->timestamp[ROT_QUEUE_HIGH_PRIORITY]); l_ts = atomic_read(&rot->timestamp[ROT_QUEUE_LOW_PRIORITY]); l_ts = atomic_read(&rot->timestamp[ROT_QUEUE_LOW_PRIORITY]); SDEROT_EVTLOG(0xbad0, rststs, swts, h_ts, l_ts); SDEROT_EVTLOG(0xbad0, rststs, l_hwts, h_hwts, l_ts, h_ts); if (ctx->q_id == ROT_QUEUE_HIGH_PRIORITY) if (ctx->q_id == ROT_QUEUE_HIGH_PRIORITY) h_ts = (h_ts - 1) & SDE_REGDMA_SWTS_MASK; h_ts = (h_ts - 1) & SDE_REGDMA_SWTS_MASK; else else l_ts = (l_ts - 1) & SDE_REGDMA_SWTS_MASK; l_ts = (l_ts - 1) & SDE_REGDMA_SWTS_MASK; /* construct the combined timstamp */ SDEROT_DBG("h_ts:0x%x, l_ts;0x%x\n", h_ts, l_ts); swts = (h_ts & SDE_REGDMA_SWTS_MASK) | SDEROT_EVTLOG(0x900d, h_ts, l_ts); ((l_ts & SDE_REGDMA_SWTS_MASK) << rot->last_hwts[ROT_QUEUE_LOW_PRIORITY] = l_ts; SDE_REGDMA_SWTS_SHIFT); rot->last_hwts[ROT_QUEUE_HIGH_PRIORITY] = h_ts; SDEROT_DBG("swts:0x%x, h_ts:0x%x, l_ts;0x%x\n", swts, h_ts, l_ts); SDEROT_EVTLOG(0x900d, swts, h_ts, l_ts); rot->last_hw_ts = swts; SDE_ROTREG_WRITE(rot->mdss_base, REGDMA_TIMESTAMP_REG, rot->ops.update_ts(rot, ROT_QUEUE_HIGH_PRIORITY, h_ts); rot->last_hw_ts); rot->ops.update_ts(rot, ROT_QUEUE_LOW_PRIORITY, l_ts); SDE_ROTREG_WRITE(rot->mdss_base, REGDMA_RESET_STATUS_REG, 0); SDE_ROTREG_WRITE(rot->mdss_base, REGDMA_RESET_STATUS_REG, 0); /* ensure write is issued to the rotator HW */ /* ensure write is issued to the rotator HW */ wmb(); wmb(); } } if (rot->reset_hw_ts) { if (rot->reset_hw_ts) { SDEROT_EVTLOG(rot->last_hw_ts); SDEROT_EVTLOG(rot->last_hwts[ROT_QUEUE_LOW_PRIORITY], SDE_ROTREG_WRITE(rot->mdss_base, REGDMA_TIMESTAMP_REG, rot->last_hwts[ROT_QUEUE_HIGH_PRIORITY]); rot->last_hw_ts); rot->ops.update_ts(rot, ROT_QUEUE_HIGH_PRIORITY, rot->last_hwts[ROT_QUEUE_HIGH_PRIORITY]); rot->ops.update_ts(rot, ROT_QUEUE_LOW_PRIORITY, rot->last_hwts[ROT_QUEUE_LOW_PRIORITY]); SDE_ROTREG_WRITE(rot->mdss_base, REGDMA_RESET_STATUS_REG, 0); SDE_ROTREG_WRITE(rot->mdss_base, REGDMA_RESET_STATUS_REG, 0); /* ensure write is issued to the rotator HW */ /* ensure write is issued to the rotator HW */ wmb(); wmb(); rot->reset_hw_ts = false; rot->reset_hw_ts = false; Loading Loading @@ -2775,7 +2874,7 @@ static int sde_hw_rotator_cancel(struct sde_rot_hw_resource *hw, } } spin_lock_irqsave(&rot->rotisr_lock, flags); spin_lock_irqsave(&rot->rotisr_lock, flags); sde_hw_rotator_update_swts(rot, ctx, ctx->timestamp); rot->ops.update_ts(rot, ctx->q_id, ctx->timestamp); spin_unlock_irqrestore(&rot->rotisr_lock, flags); spin_unlock_irqrestore(&rot->rotisr_lock, flags); SDEROT_EVTLOG(entry->item.session_id, ctx->timestamp); SDEROT_EVTLOG(entry->item.session_id, ctx->timestamp); Loading Loading @@ -3072,6 +3171,7 @@ static irqreturn_t sde_hw_rotator_rotirq_handler(int irq, void *ptr) */ */ static irqreturn_t sde_hw_rotator_regdmairq_handler(int irq, void *ptr) static irqreturn_t sde_hw_rotator_regdmairq_handler(int irq, void *ptr) { { struct sde_rot_data_type *mdata = sde_rot_get_mdata(); struct sde_hw_rotator *rot = ptr; struct sde_hw_rotator *rot = ptr; struct sde_hw_rotator_context *ctx, *tmp; struct sde_hw_rotator_context *ctx, *tmp; irqreturn_t ret = IRQ_NONE; irqreturn_t ret = IRQ_NONE; Loading @@ -3082,9 +3182,8 @@ static irqreturn_t sde_hw_rotator_regdmairq_handler(int irq, void *ptr) isr = SDE_ROTREG_READ(rot->mdss_base, REGDMA_CSR_REGDMA_INT_STATUS); isr = SDE_ROTREG_READ(rot->mdss_base, REGDMA_CSR_REGDMA_INT_STATUS); /* acknowledge interrupt before reading latest timestamp */ /* acknowledge interrupt before reading latest timestamp */ SDE_ROTREG_WRITE(rot->mdss_base, REGDMA_CSR_REGDMA_INT_CLEAR, isr); SDE_ROTREG_WRITE(rot->mdss_base, REGDMA_CSR_REGDMA_INT_CLEAR, isr); ts = SDE_ROTREG_READ(rot->mdss_base, REGDMA_TIMESTAMP_REG); SDEROT_DBG("intr_status = %8.8x, sw_TS:%X\n", isr, ts); SDEROT_DBG("intr_status = %8.8x\n", isr); /* Any REGDMA status, including error and watchdog timer, should /* Any REGDMA status, including error and watchdog timer, should * trigger and wake up waiting thread * trigger and wake up waiting thread Loading @@ -3098,21 +3197,21 @@ static irqreturn_t sde_hw_rotator_regdmairq_handler(int irq, void *ptr) */ */ if (isr & REGDMA_INT_HIGH_MASK) { if (isr & REGDMA_INT_HIGH_MASK) { q_id = ROT_QUEUE_HIGH_PRIORITY; q_id = ROT_QUEUE_HIGH_PRIORITY; ts = ts & SDE_REGDMA_SWTS_MASK; } else if (isr & REGDMA_INT_LOW_MASK) { } else if (isr & REGDMA_INT_LOW_MASK) { q_id = ROT_QUEUE_LOW_PRIORITY; q_id = ROT_QUEUE_LOW_PRIORITY; ts = (ts >> SDE_REGDMA_SWTS_SHIFT) & SDE_REGDMA_SWTS_MASK; } else { } else { SDEROT_ERR("unknown ISR status: isr=0x%X\n", isr); SDEROT_ERR("unknown ISR status: isr=0x%X\n", isr); goto done_isr_handle; goto done_isr_handle; } } ts = __sde_hw_rotator_get_timestamp(rot, q_id); /* /* * Timestamp packet is not available in sbuf mode. * Timestamp packet is not available in sbuf mode. * Simulate timestamp update in the handler instead. * Simulate timestamp update in the handler instead. */ */ if (list_empty(&rot->sbuf_ctx[q_id])) if (test_bit(SDE_CAPS_HW_TIMESTAMP, mdata->sde_caps_map) || list_empty(&rot->sbuf_ctx[q_id])) goto skip_sbuf; goto skip_sbuf; ctx = NULL; ctx = NULL; Loading @@ -3126,7 +3225,7 @@ static irqreturn_t sde_hw_rotator_regdmairq_handler(int irq, void *ptr) isr_tmp &= ~mask; isr_tmp &= ~mask; ctx = tmp; ctx = tmp; ts = ctx->timestamp; ts = ctx->timestamp; sde_hw_rotator_update_swts(rot, ctx, ts); rot->ops.update_ts(rot, ctx->q_id, ts); SDEROT_DBG("update swts:0x%X\n", ts); SDEROT_DBG("update swts:0x%X\n", ts); } } SDEROT_EVTLOG(isr, tmp->timestamp); SDEROT_EVTLOG(isr, tmp->timestamp); Loading Loading @@ -3173,6 +3272,8 @@ static irqreturn_t sde_hw_rotator_regdmairq_handler(int irq, void *ptr) for (j = 0; j < SDE_HW_ROT_REGDMA_TOTAL_CTX; j++) { for (j = 0; j < SDE_HW_ROT_REGDMA_TOTAL_CTX; j++) { ctx = rot->rotCtx[i][j]; ctx = rot->rotCtx[i][j]; if (ctx && ctx->last_regdma_isr_status == 0) { if (ctx && ctx->last_regdma_isr_status == 0) { ts = __sde_hw_rotator_get_timestamp( rot, i); ctx->last_regdma_isr_status = isr; ctx->last_regdma_isr_status = isr; ctx->last_regdma_timestamp = ts; ctx->last_regdma_timestamp = ts; wake_up_all(&ctx->regdma_waitq); wake_up_all(&ctx->regdma_waitq); Loading Loading @@ -3725,7 +3826,12 @@ int sde_rotator_r3_init(struct sde_rot_mgr *mgr) } } atomic_set(&rot->irq_enabled, 0); atomic_set(&rot->irq_enabled, 0); setup_rotator_ops(&rot->ops, rot->mode); ret = sde_rotator_hw_rev_init(rot); if (ret) goto error_hw_rev_init; setup_rotator_ops(&rot->ops, rot->mode, test_bit(SDE_CAPS_HW_TIMESTAMP, mdata->sde_caps_map)); spin_lock_init(&rot->rotctx_lock); spin_lock_init(&rot->rotctx_lock); spin_lock_init(&rot->rotisr_lock); spin_lock_init(&rot->rotisr_lock); Loading Loading @@ -3756,10 +3862,6 @@ int sde_rotator_r3_init(struct sde_rot_mgr *mgr) INIT_LIST_HEAD(&rot->sbuf_ctx[i]); INIT_LIST_HEAD(&rot->sbuf_ctx[i]); } } ret = sde_rotator_hw_rev_init(rot); if (ret) goto error_hw_rev_init; /* set rotator CBCR to shutoff memory/periphery on clock off.*/ /* set rotator CBCR to shutoff memory/periphery on clock off.*/ clk_set_flags(mgr->rot_clk[SDE_ROTATOR_CLK_MDSS_ROT].clk, clk_set_flags(mgr->rot_clk[SDE_ROTATOR_CLK_MDSS_ROT].clk, CLKFLAG_NORETAIN_MEM); CLKFLAG_NORETAIN_MEM); Loading
drivers/media/platform/msm/sde/rotator/sde_rotator_r3_hwio.h +7 −0 Original line number Original line Diff line number Diff line Loading @@ -44,6 +44,13 @@ #define ROTTOP_DEBUGBUS_STATUS (SDE_ROT_ROTTOP_OFFSET+0x54) #define ROTTOP_DEBUGBUS_STATUS (SDE_ROT_ROTTOP_OFFSET+0x54) #define ROTTOP_ROT_UBWC_DEC_VERSION (SDE_ROT_ROTTOP_OFFSET+0x58) #define ROTTOP_ROT_UBWC_DEC_VERSION (SDE_ROT_ROTTOP_OFFSET+0x58) #define ROTTOP_ROT_UBWC_ENC_VERSION (SDE_ROT_ROTTOP_OFFSET+0x5C) #define ROTTOP_ROT_UBWC_ENC_VERSION (SDE_ROT_ROTTOP_OFFSET+0x5C) #define ROTTOP_ROT_CNTR_CTRL (SDE_ROT_ROTTOP_OFFSET+0x60) #define ROTTOP_ROT_CNTR_0 (SDE_ROT_ROTTOP_OFFSET+0x64) #define ROTTOP_ROT_CNTR_1 (SDE_ROT_ROTTOP_OFFSET+0x68) #define ROTTOP_ROT_SCRATCH_0 (SDE_ROT_ROTTOP_OFFSET+0x70) #define ROTTOP_ROT_SCRATCH_1 (SDE_ROT_ROTTOP_OFFSET+0x74) #define ROTTOP_ROT_SCRATCH_2 (SDE_ROT_ROTTOP_OFFSET+0x78) #define ROTTOP_ROT_SCRATCH_3 (SDE_ROT_ROTTOP_OFFSET+0x7C) #define ROTTOP_START_CTRL_TRIG_SEL_SW 0 #define ROTTOP_START_CTRL_TRIG_SEL_SW 0 #define ROTTOP_START_CTRL_TRIG_SEL_DONE 1 #define ROTTOP_START_CTRL_TRIG_SEL_DONE 1 Loading
drivers/media/platform/msm/sde/rotator/sde_rotator_r3_internal.h +26 −1 Original line number Original line Diff line number Diff line Loading @@ -180,6 +180,31 @@ struct sde_hw_rotator_ops { struct sde_hw_rotator_context *ctx, struct sde_hw_rotator_context *ctx, enum sde_rot_queue_prio queue_id, enum sde_rot_queue_prio queue_id, u32 flags); u32 flags); /** * get_pending_ts(): * Obtain current active timestamp from rotator hw * @rot: HW Rotator structure * @ctx: Rotator context * @ts: current timestamp return from rot hw * Returns: true if context has pending requests */ int (*get_pending_ts)( struct sde_hw_rotator *rot, struct sde_hw_rotator_context *ctx, u32 *ts); /** * update_ts(): * Update rotator timestmap with given value * @rot: HW Rotator structure * @q_id: rotator queue id * @ts: new timestamp for rotator */ void (*update_ts)( struct sde_hw_rotator *rot, u32 q_id, u32 ts); }; }; /** /** Loading Loading @@ -314,7 +339,7 @@ struct sde_hw_rotator { bool dbgmem; bool dbgmem; bool reset_hw_ts; bool reset_hw_ts; u32 last_hw_ts; u32 last_hwts[ROT_QUEUE_MAX]; u32 koff_timeout; u32 koff_timeout; u32 vid_trigger; u32 vid_trigger; u32 cmd_trigger; u32 cmd_trigger; Loading