Loading drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c +30 −0 Original line number Diff line number Diff line Loading @@ -700,6 +700,35 @@ static int sde_encoder_phys_vid_wait_for_commit_done( return ret; } static void sde_encoder_phys_vid_prepare_for_kickoff( struct sde_encoder_phys *phys_enc) { struct sde_encoder_phys_vid *vid_enc; struct sde_hw_ctl *ctl; int rc; if (!phys_enc) { SDE_ERROR("invalid encoder\n"); return; } vid_enc = to_sde_encoder_phys_vid(phys_enc); ctl = phys_enc->hw_ctl; if (!ctl || !ctl->ops.wait_reset_status) return; /* * hw supports hardware initiated ctl reset, so before we kickoff a new * frame, need to check and wait for hw initiated ctl reset completion */ rc = ctl->ops.wait_reset_status(ctl); if (rc) { SDE_ERROR_VIDENC(vid_enc, "ctl %d reset failure: %d\n", ctl->idx, rc); SDE_DBG_DUMP("panic"); } } static void sde_encoder_phys_vid_disable(struct sde_encoder_phys *phys_enc) { struct msm_drm_private *priv; Loading Loading @@ -832,6 +861,7 @@ static void sde_encoder_phys_vid_init_ops(struct sde_encoder_phys_ops *ops) ops->get_hw_resources = sde_encoder_phys_vid_get_hw_resources; ops->control_vblank_irq = sde_encoder_phys_vid_control_vblank_irq; ops->wait_for_commit_done = sde_encoder_phys_vid_wait_for_commit_done; ops->prepare_for_kickoff = sde_encoder_phys_vid_prepare_for_kickoff; ops->handle_post_kickoff = sde_encoder_phys_vid_handle_post_kickoff; ops->needs_single_flush = sde_encoder_phys_vid_needs_single_flush; ops->setup_misr = sde_encoder_phys_vid_setup_misr; Loading drivers/gpu/drm/msm/sde/sde_hw_ctl.c +45 −9 Original line number Diff line number Diff line Loading @@ -247,25 +247,60 @@ static inline int sde_hw_ctl_get_bitmask_cdm(struct sde_hw_ctl *ctx, return 0; } static u32 sde_hw_ctl_poll_reset_status(struct sde_hw_ctl *ctx, u32 count) { struct sde_hw_blk_reg_map *c = &ctx->hw; u32 status; /* protect to do at least one iteration */ if (!count) count = 1; /* * it takes around 30us to have mdp finish resetting its ctl path * poll every 50us so that reset should be completed at 1st poll */ do { status = SDE_REG_READ(c, CTL_SW_RESET); status &= 0x01; if (status) usleep_range(20, 50); } while (status && --count > 0); return status; } static int sde_hw_ctl_reset_control(struct sde_hw_ctl *ctx) { struct sde_hw_blk_reg_map *c = &ctx->hw; int count = SDE_REG_RESET_TIMEOUT_COUNT; int reset; pr_debug("issuing hw ctl reset for ctl:%d\n", ctx->idx); SDE_REG_WRITE(c, CTL_SW_RESET, 0x1); if (sde_hw_ctl_poll_reset_status(ctx, SDE_REG_RESET_TIMEOUT_COUNT)) return -EINVAL; for (; count > 0; count--) { /* insert small delay to avoid spinning the cpu while waiting */ usleep_range(20, 50); reset = SDE_REG_READ(c, CTL_SW_RESET); if (reset == 0) return 0; } static int sde_hw_ctl_wait_reset_status(struct sde_hw_ctl *ctx) { struct sde_hw_blk_reg_map *c = &ctx->hw; u32 status; status = SDE_REG_READ(c, CTL_SW_RESET); status &= 0x01; if (!status) return 0; pr_debug("hw ctl reset is set for ctl:%d\n", ctx->idx); if (sde_hw_ctl_poll_reset_status(ctx, SDE_REG_RESET_TIMEOUT_COUNT)) { pr_err("hw recovery is not complete for ctl:%d\n", ctx->idx); return -EINVAL; } return 0; } static void sde_hw_ctl_clear_all_blendstages(struct sde_hw_ctl *ctx) { struct sde_hw_blk_reg_map *c = &ctx->hw; Loading Loading @@ -418,6 +453,7 @@ static void _setup_ctl_ops(struct sde_hw_ctl_ops *ops, ops->trigger_start = sde_hw_ctl_trigger_start; ops->setup_intf_cfg = sde_hw_ctl_intf_cfg; ops->reset = sde_hw_ctl_reset_control; ops->wait_reset_status = sde_hw_ctl_wait_reset_status; ops->clear_all_blendstages = sde_hw_ctl_clear_all_blendstages; ops->setup_blendstage = sde_hw_ctl_setup_blendstage; ops->get_bitmask_sspp = sde_hw_ctl_get_bitmask_sspp; Loading drivers/gpu/drm/msm/sde/sde_hw_ctl.h +11 −0 Original line number Diff line number Diff line Loading @@ -103,6 +103,17 @@ struct sde_hw_ctl_ops { int (*reset)(struct sde_hw_ctl *c); /* * wait_reset_status - checks ctl reset status * @ctx : ctl path ctx pointer * * This function checks the ctl reset status bit. * If the reset bit is set, it keeps polling the status till the hw * reset is complete. * Returns: 0 on success or -error if reset incomplete within interval */ int (*wait_reset_status)(struct sde_hw_ctl *ctx); uint32_t (*get_bitmask_sspp)(struct sde_hw_ctl *ctx, enum sde_sspp blk); Loading Loading
drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c +30 −0 Original line number Diff line number Diff line Loading @@ -700,6 +700,35 @@ static int sde_encoder_phys_vid_wait_for_commit_done( return ret; } static void sde_encoder_phys_vid_prepare_for_kickoff( struct sde_encoder_phys *phys_enc) { struct sde_encoder_phys_vid *vid_enc; struct sde_hw_ctl *ctl; int rc; if (!phys_enc) { SDE_ERROR("invalid encoder\n"); return; } vid_enc = to_sde_encoder_phys_vid(phys_enc); ctl = phys_enc->hw_ctl; if (!ctl || !ctl->ops.wait_reset_status) return; /* * hw supports hardware initiated ctl reset, so before we kickoff a new * frame, need to check and wait for hw initiated ctl reset completion */ rc = ctl->ops.wait_reset_status(ctl); if (rc) { SDE_ERROR_VIDENC(vid_enc, "ctl %d reset failure: %d\n", ctl->idx, rc); SDE_DBG_DUMP("panic"); } } static void sde_encoder_phys_vid_disable(struct sde_encoder_phys *phys_enc) { struct msm_drm_private *priv; Loading Loading @@ -832,6 +861,7 @@ static void sde_encoder_phys_vid_init_ops(struct sde_encoder_phys_ops *ops) ops->get_hw_resources = sde_encoder_phys_vid_get_hw_resources; ops->control_vblank_irq = sde_encoder_phys_vid_control_vblank_irq; ops->wait_for_commit_done = sde_encoder_phys_vid_wait_for_commit_done; ops->prepare_for_kickoff = sde_encoder_phys_vid_prepare_for_kickoff; ops->handle_post_kickoff = sde_encoder_phys_vid_handle_post_kickoff; ops->needs_single_flush = sde_encoder_phys_vid_needs_single_flush; ops->setup_misr = sde_encoder_phys_vid_setup_misr; Loading
drivers/gpu/drm/msm/sde/sde_hw_ctl.c +45 −9 Original line number Diff line number Diff line Loading @@ -247,25 +247,60 @@ static inline int sde_hw_ctl_get_bitmask_cdm(struct sde_hw_ctl *ctx, return 0; } static u32 sde_hw_ctl_poll_reset_status(struct sde_hw_ctl *ctx, u32 count) { struct sde_hw_blk_reg_map *c = &ctx->hw; u32 status; /* protect to do at least one iteration */ if (!count) count = 1; /* * it takes around 30us to have mdp finish resetting its ctl path * poll every 50us so that reset should be completed at 1st poll */ do { status = SDE_REG_READ(c, CTL_SW_RESET); status &= 0x01; if (status) usleep_range(20, 50); } while (status && --count > 0); return status; } static int sde_hw_ctl_reset_control(struct sde_hw_ctl *ctx) { struct sde_hw_blk_reg_map *c = &ctx->hw; int count = SDE_REG_RESET_TIMEOUT_COUNT; int reset; pr_debug("issuing hw ctl reset for ctl:%d\n", ctx->idx); SDE_REG_WRITE(c, CTL_SW_RESET, 0x1); if (sde_hw_ctl_poll_reset_status(ctx, SDE_REG_RESET_TIMEOUT_COUNT)) return -EINVAL; for (; count > 0; count--) { /* insert small delay to avoid spinning the cpu while waiting */ usleep_range(20, 50); reset = SDE_REG_READ(c, CTL_SW_RESET); if (reset == 0) return 0; } static int sde_hw_ctl_wait_reset_status(struct sde_hw_ctl *ctx) { struct sde_hw_blk_reg_map *c = &ctx->hw; u32 status; status = SDE_REG_READ(c, CTL_SW_RESET); status &= 0x01; if (!status) return 0; pr_debug("hw ctl reset is set for ctl:%d\n", ctx->idx); if (sde_hw_ctl_poll_reset_status(ctx, SDE_REG_RESET_TIMEOUT_COUNT)) { pr_err("hw recovery is not complete for ctl:%d\n", ctx->idx); return -EINVAL; } return 0; } static void sde_hw_ctl_clear_all_blendstages(struct sde_hw_ctl *ctx) { struct sde_hw_blk_reg_map *c = &ctx->hw; Loading Loading @@ -418,6 +453,7 @@ static void _setup_ctl_ops(struct sde_hw_ctl_ops *ops, ops->trigger_start = sde_hw_ctl_trigger_start; ops->setup_intf_cfg = sde_hw_ctl_intf_cfg; ops->reset = sde_hw_ctl_reset_control; ops->wait_reset_status = sde_hw_ctl_wait_reset_status; ops->clear_all_blendstages = sde_hw_ctl_clear_all_blendstages; ops->setup_blendstage = sde_hw_ctl_setup_blendstage; ops->get_bitmask_sspp = sde_hw_ctl_get_bitmask_sspp; Loading
drivers/gpu/drm/msm/sde/sde_hw_ctl.h +11 −0 Original line number Diff line number Diff line Loading @@ -103,6 +103,17 @@ struct sde_hw_ctl_ops { int (*reset)(struct sde_hw_ctl *c); /* * wait_reset_status - checks ctl reset status * @ctx : ctl path ctx pointer * * This function checks the ctl reset status bit. * If the reset bit is set, it keeps polling the status till the hw * reset is complete. * Returns: 0 on success or -error if reset incomplete within interval */ int (*wait_reset_status)(struct sde_hw_ctl *ctx); uint32_t (*get_bitmask_sspp)(struct sde_hw_ctl *ctx, enum sde_sspp blk); Loading