void mdss_dsi_cmd_mdp_busy(struct mdss_dsi_ctrl_pdata *ctrl)
{
	unsigned long flags;
	int need_wait = 0;

	pr_debug("%s: start pid=%d\n",
				__func__, current->pid);

	MDSS_XLOG(ctrl->ndx, ctrl->mdp_busy, current->pid, XLOG_FUNC_ENTRY);
	spin_lock_irqsave(&ctrl->mdp_lock, flags);
	if (ctrl->mdp_busy == true)
		need_wait++;
	spin_unlock_irqrestore(&ctrl->mdp_lock, flags);

	if (need_wait) {
		/* wait until DMA finishes the current job */
		pr_debug("%s: pending pid=%d\n",
				__func__, current->pid);
		if (!wait_for_completion_timeout(&ctrl->mdp_comp,
					msecs_to_jiffies(DMA_TX_TIMEOUT))) {
			pr_err("%s: timeout error\n", __func__);
			MDSS_XLOG_TOUT_HANDLER("mdp", "dsi0", "dsi1",
						"edp", "hdmi", "panic");
		}
	}
	pr_debug("%s: done pid=%d\n", __func__, current->pid);
	MDSS_XLOG(ctrl->ndx, ctrl->mdp_busy, current->pid, XLOG_FUNC_EXIT);
}
int mdss_dsi_cmdlist_commit(struct mdss_dsi_ctrl_pdata *ctrl, int from_mdp)
{
	struct dcs_cmd_req *req;
	int ret = -EINVAL;
	int rc = 0;
	mutex_lock(&ctrl->cmd_mutex);
	req = mdss_dsi_cmdlist_get(ctrl);

	MDSS_XLOG(ctrl->ndx, from_mdp, ctrl->mdp_busy, current->pid,
							XLOG_FUNC_ENTRY);

	/* make sure dsi_cmd_mdp is idle */
	mdss_dsi_cmd_mdp_busy(ctrl);

	pr_debug("%s:  from_mdp=%d pid=%d\n", __func__, from_mdp, current->pid);

	if (req == NULL)
		goto need_lock;

	MDSS_XLOG(ctrl->ndx, req->flags, req->cmds_cnt, from_mdp, current->pid);

	/*
	 * mdss interrupt is generated in mdp core clock domain
	 * mdp clock need to be enabled to receive dsi interrupt
	 * also, axi bus bandwidth need since dsi controller will
	 * fetch dcs commands from axi bus
	 */
	mdss_bus_bandwidth_ctrl(1);
	pr_debug("%s:  from_mdp=%d pid=%d\n", __func__, from_mdp, current->pid);
	mdss_dsi_clk_ctrl(ctrl, 1);

	rc = mdss_iommu_ctrl(1);
	if (IS_ERR_VALUE(rc)) {
		pr_err("IOMMU attach failed\n");
		mutex_unlock(&ctrl->cmd_mutex);
		return rc;
	}
	if (req->flags & CMD_REQ_RX)
		ret = mdss_dsi_cmdlist_rx(ctrl, req);
	else
		ret = mdss_dsi_cmdlist_tx(ctrl, req);

	mdss_iommu_ctrl(0);
	mdss_dsi_clk_ctrl(ctrl, 0);
	mdss_bus_bandwidth_ctrl(0);

need_lock:

	if (from_mdp) /* from pipe_commit */
		mdss_dsi_cmd_mdp_start(ctrl);

	MDSS_XLOG(ctrl->ndx, from_mdp, ctrl->mdp_busy, current->pid,
							XLOG_FUNC_EXIT);
	mutex_unlock(&ctrl->cmd_mutex);
	return ret;
}
Esempio n. 3
0
irqreturn_t mdss_dsi_isr(int irq, void *ptr)
{
    u32 isr;
    struct mdss_dsi_ctrl_pdata *ctrl =
        (struct mdss_dsi_ctrl_pdata *)ptr;

    if (!ctrl->ctrl_base)
        pr_err("%s:%d DSI base adr no Initialized",
               __func__, __LINE__);

    isr = MIPI_INP(ctrl->ctrl_base + 0x0110);/* DSI_INTR_CTRL */
    MIPI_OUTP(ctrl->ctrl_base + 0x0110, isr);

    pr_debug("%s: ndx=%d isr=%x\n", __func__, ctrl->ndx, isr);

    if (isr & DSI_INTR_ERROR) {
        MDSS_XLOG(ctrl->ndx, ctrl->mdp_busy, isr, 0x97);
        pr_err("%s: ndx=%d isr=%x\n", __func__, ctrl->ndx, isr);
        mdss_dsi_error(ctrl);
    }

    if (isr & DSI_INTR_VIDEO_DONE) {
        spin_lock(&ctrl->mdp_lock);
        mdss_dsi_disable_irq_nosync(ctrl, DSI_VIDEO_TERM);
        complete(&ctrl->video_comp);
        spin_unlock(&ctrl->mdp_lock);
    }

    if (isr & DSI_INTR_CMD_DMA_DONE) {
        MDSS_XLOG(ctrl->ndx, ctrl->mdp_busy, isr, 0x98);
        spin_lock(&ctrl->mdp_lock);
        mdss_dsi_disable_irq_nosync(ctrl, DSI_CMD_TERM);
        complete(&ctrl->dma_comp);
        spin_unlock(&ctrl->mdp_lock);
    }

    if (isr & DSI_INTR_CMD_MDP_DONE) {
        MDSS_XLOG(ctrl->ndx, ctrl->mdp_busy, isr, 0x99);
        spin_lock(&ctrl->mdp_lock);
        ctrl->mdp_busy = false;
        mdss_dsi_disable_irq_nosync(ctrl, DSI_MDP_TERM);
        complete(&ctrl->mdp_comp);
        spin_unlock(&ctrl->mdp_lock);
    }

    if (isr & DSI_INTR_BTA_DONE) {
        spin_lock(&ctrl->mdp_lock);
        mdss_dsi_disable_irq_nosync(ctrl, DSI_BTA_TERM);
        complete(&ctrl->bta_comp);
        spin_unlock(&ctrl->mdp_lock);
    }

    return IRQ_HANDLED;
}
void mdss_dsi_clk_req(struct mdss_dsi_ctrl_pdata *ctrl, int enable)
{
	MDSS_XLOG(ctrl->ndx, enable, ctrl->mdp_busy, current->pid);
	if (enable == 0) {
		/* need wait before disable */
		mutex_lock(&ctrl->cmd_mutex);
		mdss_dsi_cmd_mdp_busy(ctrl);
		mutex_unlock(&ctrl->cmd_mutex);
	}
	MDSS_XLOG(ctrl->ndx, enable, ctrl->mdp_busy, current->pid);
	mdss_dsi_clk_ctrl(ctrl, enable);
}
void mdss_dsi_cmd_mdp_start(struct mdss_dsi_ctrl_pdata *ctrl)
{
	unsigned long flag;

	spin_lock_irqsave(&ctrl->mdp_lock, flag);
	mdss_dsi_enable_irq(ctrl, DSI_MDP_TERM);
	ctrl->mdp_busy = true;
	INIT_COMPLETION(ctrl->mdp_comp);
	MDSS_XLOG(ctrl->ndx, ctrl->mdp_busy, current->pid);
	spin_unlock_irqrestore(&ctrl->mdp_lock, flag);
}
/*
 * mdss_dsi_disale_irq_nosync() should be called
 * from interrupt context
 */
void mdss_dsi_disable_irq_nosync(struct mdss_dsi_ctrl_pdata *ctrl, u32 term)
{
	spin_lock(&ctrl->irq_lock);
	if (!(ctrl->dsi_irq_mask & term)) {
		spin_unlock(&ctrl->irq_lock);
		return;
	}
	ctrl->dsi_irq_mask &= ~term;
	if (ctrl->dsi_irq_mask == 0) {
		MDSS_XLOG(ctrl->ndx, term);
		mdss_disable_irq_nosync(ctrl->dsi_hw);
		pr_debug("%s: IRQ Disable, ndx=%d mask=%x term=%x\n", __func__,
			ctrl->ndx, (int)ctrl->dsi_irq_mask, (int)term);
	}
	spin_unlock(&ctrl->irq_lock);
}
void mdss_dsi_disable_irq(struct mdss_dsi_ctrl_pdata *ctrl, u32 term)
{
	unsigned long flags;

	spin_lock_irqsave(&ctrl->irq_lock, flags);
	if (!(ctrl->dsi_irq_mask & term)) {
		spin_unlock_irqrestore(&ctrl->irq_lock, flags);
		return;
	}
	ctrl->dsi_irq_mask &= ~term;
	if (ctrl->dsi_irq_mask == 0) {
		MDSS_XLOG(ctrl->ndx, term);
		mdss_disable_irq(ctrl->dsi_hw);
		pr_debug("%s: IRQ Disable, ndx=%d mask=%x term=%x\n", __func__,
			ctrl->ndx, (int)ctrl->dsi_irq_mask, (int)term);
	}
	spin_unlock_irqrestore(&ctrl->irq_lock, flags);
}
static int mdss_mdp_rotator_busy_wait(struct mdss_mdp_rotator_session *rot)
{

	mutex_lock(&rot->lock);
	if (!rot->pipe || !rot->pipe->mixer_left ||
		!rot->pipe->mixer_left->ctl) {
		mutex_unlock(&rot->lock);
		return -ENODEV;
	}

	if (rot->busy) {
		struct mdss_mdp_ctl *ctl = rot->pipe->mixer_left->ctl;
		mdss_mdp_display_wait4comp(ctl);
		rot->busy = false;
		MDSS_XLOG(rot->session_id, 0x222);
		if (ctl->shared_lock)
			mutex_unlock(ctl->shared_lock);
	}
	mutex_unlock(&rot->lock);

	return 0;
}
Esempio n. 9
0
static struct mdss_mdp_pipe *mdss_mdp_rotator_pipe_alloc(void)
{
	struct mdss_mdp_mixer *mixer;
	struct mdss_mdp_pipe *pipe = NULL;

	mixer = mdss_mdp_wb_mixer_alloc(1);
	if (!mixer) {
		pr_debug("wb mixer alloc failed\n");
		return NULL;
	}

	pipe = mdss_mdp_pipe_alloc_dma(mixer);
	if (!pipe) {
		mdss_mdp_wb_mixer_destroy(mixer);
		pr_debug("dma pipe allocation failed\n");
		return NULL;
	}

	MDSS_XLOG(pipe->num, mixer->num);
	pipe->mixer_stage = MDSS_MDP_STAGE_UNUSED;

	return pipe;
}
Esempio n. 10
0
static int mdss_dsi_event_handler(struct mdss_panel_data *pdata,
				  int event, void *arg)
{
	int rc = 0;
	struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;

	if (pdata == NULL) {
		pr_err("%s: Invalid input data\n", __func__);
		return -EINVAL;
	}
	ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
				panel_data);
	pr_debug("%s+:event=%d\n", __func__, event);

	MDSS_XLOG(event, arg, ctrl_pdata->ndx, 0x3333);

	switch (event) {
	case MDSS_EVENT_UNBLANK:
		rc = mdss_dsi_on(pdata);
		mdss_dsi_op_mode_config(pdata->panel_info.mipi.mode,
							pdata);
		if (ctrl_pdata->on_cmds.link_state == DSI_LP_MODE)
			rc = mdss_dsi_unblank(pdata);
		break;
	case MDSS_EVENT_PANEL_ON:
		ctrl_pdata->ctrl_state |= CTRL_STATE_MDP_ACTIVE;
		if (ctrl_pdata->on_cmds.link_state == DSI_HS_MODE)
			rc = mdss_dsi_unblank(pdata);
		break;
	case MDSS_EVENT_BLANK:
		if (ctrl_pdata->off_cmds.link_state == DSI_HS_MODE)
			rc = mdss_dsi_blank(pdata);
		break;
	case MDSS_EVENT_PANEL_OFF:
		ctrl_pdata->ctrl_state &= ~CTRL_STATE_MDP_ACTIVE;
		if (ctrl_pdata->off_cmds.link_state == DSI_LP_MODE)
			rc = mdss_dsi_blank(pdata);
		rc = mdss_dsi_off(pdata);
		break;
	case MDSS_EVENT_CONT_SPLASH_FINISH:
		if (ctrl_pdata->off_cmds.link_state == DSI_LP_MODE)
			rc = mdss_dsi_blank(pdata);
		ctrl_pdata->ctrl_state &= ~CTRL_STATE_MDP_ACTIVE;
		rc = mdss_dsi_cont_splash_on(pdata);
		break;
	case MDSS_EVENT_PANEL_CLK_CTRL:
		mdss_dsi_clk_req(ctrl_pdata, (int) (unsigned long) arg);
		break;
	case MDSS_EVENT_DSI_CMDLIST_KOFF:
		ctrl_pdata->recovery = (struct mdss_panel_recovery *)arg;
		mdss_dsi_cmdlist_commit(ctrl_pdata, 1);
		break;
	case MDSS_EVENT_PANEL_UPDATE_FPS:
		if (arg != NULL) {
			rc = mdss_dsi_dfps_config(pdata,
					 (int) (unsigned long) arg);
			pr_debug("%s:update fps to = %d\n",
				 __func__, (int) (unsigned long) arg);
		}
		break;
	case MDSS_EVENT_CONT_SPLASH_BEGIN:
		if (ctrl_pdata->off_cmds.link_state == DSI_HS_MODE) {
			/* Panel is Enabled in Bootloader */
			rc = mdss_dsi_blank(pdata);
		}
		break;
	case MDSS_EVENT_ENABLE_PARTIAL_UPDATE:
		rc = mdss_dsi_ctl_partial_update(pdata);
		break;
	case MDSS_EVENT_DSI_DYNAMIC_SWITCH:
		rc = mdss_dsi_update_panel_config(ctrl_pdata,
					(int)(unsigned long) arg);
		break;
	default:
		pr_debug("%s: unhandled event=%d\n", __func__, event);
		break;
	}
	pr_debug("%s-:event=%d, rc=%d\n", __func__, event, rc);
	return rc;
}
Esempio n. 11
0
static int mdss_dsi_event_handler(struct mdss_panel_data *pdata,
				  int event, void *arg)
{
	int rc = 0;
	struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
	int power_state;

	if (pdata == NULL) {
		pr_err("%s: Invalid input data\n", __func__);
		return -EINVAL;
	}
	ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
				panel_data);
	pr_debug("%s+: ctrl=%d event=%d\n", __func__, ctrl_pdata->ndx, event);

	MDSS_XLOG(event, arg, ctrl_pdata->ndx, 0x3333);

	switch (event) {
	case MDSS_EVENT_UNBLANK:
//		pr_info("%s : MDSS_EVENT_UNBLANK \n", __func__);
		pr_info("%s :(%d) MDSS_EVENT_UNBLANK (%s)\n", __func__, ctrl_pdata->ndx, ctrl_pdata->on_cmds.link_state? "HS" : "LP");
		rc = mdss_dsi_on(pdata);
		mdss_dsi_op_mode_config(pdata->panel_info.mipi.mode,
							pdata);
		if (ctrl_pdata->on_cmds.link_state == DSI_LP_MODE)
			rc = mdss_dsi_unblank(pdata);
		break;
	case MDSS_EVENT_PANEL_ON:
		//pr_info("%s : MDSS_EVENT_PANEL_ON \n", __func__);
		pr_info("%s :(%d) MDSS_EVENT_PANEL_ON (%s)\n", __func__, ctrl_pdata->ndx, ctrl_pdata->on_cmds.link_state? "HS" : "LP");
		ctrl_pdata->ctrl_state |= CTRL_STATE_MDP_ACTIVE;
		if (ctrl_pdata->on_cmds.link_state == DSI_HS_MODE)
			rc = mdss_dsi_unblank(pdata);
		break;
	case MDSS_EVENT_BLANK:
		pr_info("%s :(%d) MDSS_EVENT_BLANK (%s)\n", __func__, ctrl_pdata->ndx, ctrl_pdata->off_cmds.link_state? "HS" : "LP");
		power_state = (int) (unsigned long) arg;
		if (ctrl_pdata->off_cmds.link_state == DSI_HS_MODE)
			rc = mdss_dsi_blank(pdata, power_state);
		break;
	case MDSS_EVENT_PANEL_OFF:
		pr_info("%s :(%d) MDSS_EVENT_PANEL_OFF (%s) \n", __func__, ctrl_pdata->ndx, ctrl_pdata->off_cmds.link_state? "HS" : "LP");
		power_state = (int) (unsigned long) arg;
		ctrl_pdata->ctrl_state &= ~CTRL_STATE_MDP_ACTIVE;
		if (ctrl_pdata->off_cmds.link_state == DSI_LP_MODE)
			rc = mdss_dsi_blank(pdata, power_state);
		rc = mdss_dsi_off(pdata, power_state);
		break;
	case MDSS_EVENT_FB_REGISTERED:
		pr_info("%s : MDSS_EVENT_FB_REGISTERED \n", __func__);
		if (ctrl_pdata->registered) {
			pr_debug("%s:event=%d, calling panel registered callback \n",
				 __func__, event);
			rc = ctrl_pdata->registered(pdata);
		}
		break;
	case MDSS_EVENT_CONT_SPLASH_FINISH:
		pr_info("%s : MDSS_EVENT_CONT_SPLASH_FINISH \n", __func__);
		if (ctrl_pdata->off_cmds.link_state == DSI_LP_MODE)
			rc = mdss_dsi_blank(pdata, MDSS_PANEL_POWER_OFF);
		ctrl_pdata->ctrl_state &= ~CTRL_STATE_MDP_ACTIVE;

#if defined(CONFIG_FB_MSM_MDSS_SAMSUNG)
		ctrl_pdata->ctrl_state &= ~CTRL_STATE_PANEL_INIT;
#endif
		rc = mdss_dsi_cont_splash_on(pdata);
		break;
	case MDSS_EVENT_PANEL_CLK_CTRL:
		mdss_dsi_clk_req(ctrl_pdata, (int) (unsigned long) arg);
		break;
	case MDSS_EVENT_DSI_CMDLIST_KOFF:
		ctrl_pdata->recovery = (struct mdss_panel_recovery *)arg;
		mdss_dsi_cmdlist_commit(ctrl_pdata, 1);
		break;
	case MDSS_EVENT_PANEL_UPDATE_FPS:
		if (arg != NULL) {
			rc = mdss_dsi_dfps_config(pdata,
					 (int) (unsigned long) arg);
			pr_debug("%s:update fps to = %d\n",
				 __func__, (int) (unsigned long) arg);
		}
		break;
	case MDSS_EVENT_CONT_SPLASH_BEGIN:
		pr_info("%s : MDSS_EVENT_CONT_SPLASH_BEGIN \n", __func__);
		if (ctrl_pdata->off_cmds.link_state == DSI_HS_MODE) {
			/* Panel is Enabled in Bootloader */
			rc = mdss_dsi_blank(pdata, MDSS_PANEL_POWER_OFF);
		}
		break;
	case MDSS_EVENT_ENABLE_PARTIAL_ROI:
		rc = mdss_dsi_ctl_partial_roi(pdata);
		break;
	case MDSS_EVENT_DSI_STREAM_SIZE:
		rc = mdss_dsi_set_stream_size(pdata);
		break;
	default:
#if defined(CONFIG_FB_MSM_MDSS_SAMSUNG)
		if(ctrl_pdata->event_handler)
			rc = ctrl_pdata->event_handler(pdata, event, arg);
		else
#endif
		pr_debug("%s: unhandled event=%d\n", __func__, event);
		break;
	}
	pr_debug("%s-:event=%d, rc=%d\n", __func__, event, rc);
	return rc;
}
Esempio n. 12
0
int mdss_dsi_cmdlist_commit(struct mdss_dsi_ctrl_pdata *ctrl, int from_mdp)
{
    struct dcs_cmd_req *req;
    struct mdss_panel_info *pinfo;
    struct mdss_rect *roi = NULL;
    int ret = -EINVAL;
    int rc = 0;

    if (from_mdp)	/* from mdp kickoff */
        mutex_lock(&ctrl->cmd_mutex);

    req = mdss_dsi_cmdlist_get(ctrl);

    MDSS_XLOG(ctrl->ndx, from_mdp, ctrl->mdp_busy, current->pid,
              XLOG_FUNC_ENTRY);

    /* make sure dsi_cmd_mdp is idle */
    mdss_dsi_cmd_mdp_busy(ctrl);

    pr_debug("%s: ctrl=%d from_mdp=%d pid=%d\n", __func__,
             ctrl->ndx, from_mdp, current->pid);

    if (req == NULL)
        goto need_lock;

    MDSS_XLOG(ctrl->ndx, req->flags, req->cmds_cnt, from_mdp, current->pid);

    /*
     * mdss interrupt is generated in mdp core clock domain
     * mdp clock need to be enabled to receive dsi interrupt
     * also, axi bus bandwidth need since dsi controller will
     * fetch dcs commands from axi bus
     */
    mdss_bus_scale_set_quota(MDSS_HW_DSI0, SZ_1M, SZ_1M);

    pr_debug("%s:  from_mdp=%d pid=%d\n", __func__, from_mdp, current->pid);
    mdss_dsi_clk_ctrl(ctrl, DSI_ALL_CLKS, 1);

    rc = mdss_iommu_ctrl(1);
    if (IS_ERR_VALUE(rc)) {
        pr_err("IOMMU attach failed\n");
        mutex_unlock(&ctrl->cmd_mutex);
        return rc;
    }
    if (req->flags & CMD_REQ_RX)
        ret = mdss_dsi_cmdlist_rx(ctrl, req);
    else
        ret = mdss_dsi_cmdlist_tx(ctrl, req);
    mdss_iommu_ctrl(0);
    mdss_dsi_clk_ctrl(ctrl, DSI_ALL_CLKS, 0);
    mdss_bus_scale_set_quota(MDSS_HW_DSI0, 0, 0);
need_lock:

    MDSS_XLOG(ctrl->ndx, from_mdp, ctrl->mdp_busy, current->pid,
              XLOG_FUNC_EXIT);

    if (from_mdp) { /* from mdp kickoff */
        /*
         * when partial update enabled, the roi of pinfo
         * is updated before mdp kickoff. Either width or
         * height of roi is 0, then it is false kickoff so
         * no mdp_busy flag set needed.
         * when partial update disabled, mdp_busy flag
         * alway set.
         */
        pinfo = &ctrl->panel_data.panel_info;
        if (pinfo->partial_update_enabled)
            roi = &pinfo->roi;

        if (!roi || (roi->w != 0 || roi->h != 0))
            mdss_dsi_cmd_mdp_start(ctrl);

        mutex_unlock(&ctrl->cmd_mutex);
    }

    return ret;
}