int mdss_mdp_cmd_stop(struct mdss_mdp_ctl *ctl) { struct mdss_mdp_cmd_ctx *ctx; unsigned long flags; int need_wait = 0; int ret = 0; ctx = (struct mdss_mdp_cmd_ctx *) ctl->priv_data; if (!ctx) { pr_err("invalid ctx\n"); return -ENODEV; } spin_lock_irqsave(&ctx->clk_lock, flags); if (ctx->rdptr_enabled) { INIT_COMPLETION(ctx->stop_comp); need_wait = 1; } if (ctx->vsync_enabled) { pr_err("%s: vsync should be disabled\n", __func__); ctx->vsync_enabled = 0; } spin_unlock_irqrestore(&ctx->clk_lock, flags); if (need_wait) if (wait_for_completion_timeout(&ctx->stop_comp, STOP_TIMEOUT) <= 0) WARN(1, "stop cmd time out\n"); if (cancel_work_sync(&ctx->clk_work)) pr_debug("no pending clk work\n"); mdss_mdp_cmd_clk_off(ctx); ctx->panel_on = 0; mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_PING_PONG_RD_PTR, ctx->pp_num, NULL, NULL); mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_PING_PONG_COMP, ctx->pp_num, NULL, NULL); memset(ctx, 0, sizeof(*ctx)); ctl->priv_data = NULL; ret = mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_BLANK, NULL); WARN(ret, "intf %d unblank error (%d)\n", ctl->intf_num, ret); ret = mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_PANEL_OFF, NULL); WARN(ret, "intf %d unblank error (%d)\n", ctl->intf_num, ret); ctl->stop_fnc = NULL; ctl->display_fnc = NULL; ctl->wait_pingpong = NULL; ctl->add_vsync_handler = NULL; ctl->remove_vsync_handler = NULL; pr_debug("%s:-\n", __func__); return 0; }
static int mdss_mdp_video_display(struct mdss_mdp_ctl *ctl, void *arg) { struct mdss_mdp_video_ctx *ctx; u32 intr_type = MDSS_MDP_IRQ_INTF_VSYNC; pr_debug("kickoff ctl=%d\n", ctl->num); ctx = (struct mdss_mdp_video_ctx *) ctl->priv_data; if (!ctx) { pr_err("invalid ctx\n"); return -ENODEV; } mdss_mdp_set_intr_callback(intr_type, ctl->intf_num, mdss_mdp_video_vsync_intr_done, ctx); mdss_mdp_irq_enable(intr_type, ctl->intf_num); if (!ctx->timegen_en) { int off = MDSS_MDP_REG_INTF_OFFSET(ctl->intf_num); pr_debug("enabling timing gen for intf=%d\n", ctl->intf_num); mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false); MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_INTF_TIMING_ENGINE_EN, 1); ctx->timegen_en = true; wmb(); } wait_for_completion_interruptible(&ctx->vsync_comp); mdss_mdp_irq_disable(intr_type, ctl->intf_num); return 0; }
static int mdss_mdp_video_prepare(struct mdss_mdp_ctl *ctl, void *arg) { struct mdss_mdp_video_ctx *ctx; ctx = (struct mdss_mdp_video_ctx *) ctl->priv_data; if (!ctx) { pr_err("invalid ctx\n"); return -ENODEV; } if (ctx->timegen_en) { u32 intr_type = MDSS_MDP_IRQ_PING_PONG_COMP; pr_debug("waiting for ping pong %d done\n", ctx->pp_num); mdss_mdp_set_intr_callback(intr_type, ctx->pp_num, mdss_mdp_video_pp_intr_done, ctx); mdss_mdp_irq_enable(intr_type, ctx->pp_num); wait_for_completion_interruptible(&ctx->pp_comp); mdss_mdp_irq_disable(intr_type, ctx->pp_num); } return 0; }
int mdss_mdp_cmd_start(struct mdss_mdp_ctl *ctl) { struct mdss_mdp_cmd_ctx *ctx; struct mdss_mdp_mixer *mixer; int i, ret; pr_debug("%s:+\n", __func__); mixer = mdss_mdp_mixer_get(ctl, MDSS_MDP_MIXER_MUX_LEFT); if (!mixer) { pr_err("mixer not setup correctly\n"); return -ENODEV; } for (i = 0; i < MAX_SESSIONS; i++) { ctx = &mdss_mdp_cmd_ctx_list[i]; if (ctx->ref_cnt == 0) { ctx->ref_cnt++; break; } } if (i == MAX_SESSIONS) { pr_err("too many sessions\n"); return -ENOMEM; } ctl->priv_data = ctx; if (!ctx) { pr_err("invalid ctx\n"); return -ENODEV; } ctx->ctl = ctl; ctx->pp_num = mixer->num; init_completion(&ctx->pp_comp); init_completion(&ctx->stop_comp); spin_lock_init(&ctx->clk_lock); mutex_init(&ctx->clk_mtx); INIT_WORK(&ctx->clk_work, clk_ctrl_work); pr_debug("%s: ctx=%p num=%d mixer=%d\n", __func__, ctx, ctx->pp_num, mixer->num); mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_PING_PONG_RD_PTR, ctx->pp_num, mdss_mdp_cmd_readptr_done, ctl); mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_PING_PONG_COMP, ctx->pp_num, mdss_mdp_cmd_pingpong_done, ctl); ret = mdss_mdp_cmd_tearcheck_setup(ctl, 1); if (ret) { pr_err("tearcheck setup failed\n"); return ret; } ctl->stop_fnc = mdss_mdp_cmd_stop; ctl->display_fnc = mdss_mdp_cmd_kickoff; ctl->wait_pingpong = mdss_mdp_cmd_wait4pingpong; ctl->add_vsync_handler = mdss_mdp_cmd_add_vsync_handler; ctl->remove_vsync_handler = mdss_mdp_cmd_remove_vsync_handler; ctl->read_line_cnt_fnc = mdss_mdp_cmd_line_count; pr_debug("%s:-\n", __func__); return 0; }