static void mdfld_dsi_dpi_shut_down(struct mdfld_dsi_dpi_output *output,
								int pipe)
{
	struct drm_device *dev = output->dev;

	/*if output is on, or mode setting didn't happen, ignore this*/
	if ((!output->panel_on) || output->first_boot) {
		output->first_boot = 0;
		return;
	}

	/* Wait for dpi fifo to empty */
	mdfld_wait_for_DPI_CTRL_FIFO(dev, pipe);

	/* Clear the special packet interrupt bit if set */
	if (REG_READ(MIPI_INTR_STAT_REG(pipe)) & DSI_INTR_STATE_SPL_PKG_SENT)
		REG_WRITE(MIPI_INTR_STAT_REG(pipe),
					DSI_INTR_STATE_SPL_PKG_SENT);

	if (REG_READ(MIPI_DPI_CONTROL_REG(pipe)) == DSI_DPI_CTRL_HS_SHUTDOWN)
		goto shutdown_out;

	REG_WRITE(MIPI_DPI_CONTROL_REG(pipe), DSI_DPI_CTRL_HS_SHUTDOWN);

shutdown_out:
	output->panel_on = 0;
	output->first_boot = 0;

	/* FIXME the following is disabled to WA the X slow start issue
	   for TMD panel
	if (pipe == 2)
		dev_priv->dpi_panel_on2 = false;
	else if (pipe == 0)
		dev_priv->dpi_panel_on = false;	 */
}
void mdfld_dsi_dpi_turn_on(struct mdfld_dsi_dpi_output *output, int pipe)
{
	struct drm_device *dev = output->dev;

	/* clear special packet sent bit */
	if (REG_READ(MIPI_INTR_STAT_REG(pipe)) & DSI_INTR_STATE_SPL_PKG_SENT)
		REG_WRITE(MIPI_INTR_STAT_REG(pipe),
					DSI_INTR_STATE_SPL_PKG_SENT);

	/*send turn on package*/
	REG_WRITE(MIPI_DPI_CONTROL_REG(pipe), DSI_DPI_CTRL_HS_TURN_ON);

	/*wait for SPL_PKG_SENT interrupt*/
	mdfld_wait_for_SPL_PKG_SENT(dev, pipe);

	if (REG_READ(MIPI_INTR_STAT_REG(pipe)) & DSI_INTR_STATE_SPL_PKG_SENT)
		REG_WRITE(MIPI_INTR_STAT_REG(pipe),
					DSI_INTR_STATE_SPL_PKG_SENT);

	output->panel_on = 1;

	/* FIXME the following is disabled to WA the X slow start issue
	   for TMD panel
	if (pipe == 2)
		dev_priv->dpi_panel_on2 = true;
	else if (pipe == 0)
		dev_priv->dpi_panel_on = true; */
}
static void mdfld_wait_for_SPL_PKG_SENT(struct drm_device *dev, u32 pipe)
{
	u32 intr_stat_reg = MIPI_INTR_STAT_REG(pipe);
	int timeout = 0;

	udelay(500);

	/* This will time out after approximately 2+ seconds */
	while ((timeout < 20000) && (!(REG_READ(intr_stat_reg)
					& DSI_INTR_STATE_SPL_PKG_SENT))) {
		udelay(100);
		timeout++;
	}

	if (timeout == 20000)
                DRM_ERROR("MIPI: SPL_PKT_SENT_INTERRUPT was not sent successfully!\n");
}
Exemple #4
0
static int mdfld_dpu_update_fb(struct drm_device * dev) {
	struct drm_crtc * crtc;
	struct psb_intel_crtc * psb_crtc;
	struct mdfld_dsi_dbi_output ** dbi_output;
	struct drm_psb_private * dev_priv = dev->dev_private;
	struct mdfld_dbi_dpu_info * dpu_info = dev_priv->dbi_dpu_info;
	bool pipe_updated[2];
	unsigned long irq_flags;
	u32 dpll_reg = PSB_DSI_PLL_CTRL;
	u32 dspcntr_reg = PSB_DSPCNTR(PSB_PIPE_A);
	u32 pipeconf_reg = PSB_PIPECONF(PSB_PIPE_A);
	u32 dsplinoff_reg = PSB_DSPLINOFF(PSB_PIPE_A);
	u32 dspsurf_reg = PSB_DSPSURF(PSB_PIPE_A);
	int pipe;
	int i;
	int ret;

	dbi_output = dpu_info->dbi_outputs;
	pipe_updated[0] = pipe_updated[1] = false;
	
	if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, true))
		return -EAGAIN;

	/*try to prevent any new damage reports*/	
	if(!spin_trylock_irqsave(&dpu_info->dpu_update_lock, irq_flags)) {
		return -EAGAIN;
	}

	for(i=0; i<dpu_info->dbi_output_num; i++) {
		crtc = dbi_output[i]->base.base.crtc;
		psb_crtc = (crtc) ? to_psb_intel_crtc(crtc) : NULL; 

                pipe = dbi_output[i]->channel_num ? 2 : 0;

                if(pipe == 2) {
			dspcntr_reg = PSB_DSPCNTR(PSB_PIPE_C);
			pipeconf_reg = PSB_PIPECONF(PSB_PIPE_C);
			dsplinoff_reg = PSB_DSPLINOFF(PSB_PIPE_C);
			dspsurf_reg = PSB_DSPSURF(PSB_PIPE_C);
                }

                if (!(REG_READ(MIPI_GEN_FIFO_STAT_REG(pipe)) & BIT(27)) ||
                   !(REG_READ(dpll_reg) & DPLL_VCO_ENABLE) ||
                   !(REG_READ(dspcntr_reg) & DISPLAY_PLANE_ENABLE) ||
                   !(REG_READ(pipeconf_reg) & DISPLAY_PLANE_ENABLE)) {
                        PSB_DEBUG_ENTRY("DBI FIFO is busy, DSI %d state %x\n",
                                        pipe,
                                        REG_READ(MIPI_INTR_STAT_REG(pipe)));
                        continue;
                }

		/*if dbi output is in a exclusive state, pipe change won't be updated*/
		if(dbi_output[i]->dbi_panel_on &&
		   !(dbi_output[i]->mode_flags & MODE_SETTING_ON_GOING) &&
		   !(psb_crtc && psb_crtc->mode_flags & MODE_SETTING_ON_GOING) &&
		   !(dbi_output[i]->mode_flags & MODE_SETTING_IN_DSR)) {
			ret = mdfld_dpu_update_pipe(dbi_output[i], dpu_info, dbi_output[i]->channel_num ? 2 : 0);
			if(!ret) {
				pipe_updated[i] = true;
			}
		} 
	}
	
	for(i=0; i<dpu_info->dbi_output_num; i++) {
		if(pipe_updated[i]) {
			mdfld_dbi_flush_cb(dbi_output[i], dbi_output[i]->channel_num ? 2 : 0);
		}
	}

	spin_unlock_irqrestore(&dpu_info->dpu_update_lock, irq_flags);
	
	ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
	
	return 0;
}
Exemple #5
0
int mdfld_dsi_pkg_sender_init(struct mdfld_dsi_connector *dsi_connector,
								int pipe)
{
	struct mdfld_dsi_pkg_sender *pkg_sender;
	struct mdfld_dsi_config *dsi_config =
				mdfld_dsi_get_config(dsi_connector);
	struct drm_device *dev = dsi_config->dev;
	struct drm_psb_private *dev_priv = dev->dev_private;
	const struct psb_offset *map = &dev_priv->regmap[pipe];
	u32 mipi_val = 0;

	if (!dsi_connector) {
		DRM_ERROR("Invalid parameter\n");
		return -EINVAL;
	}

	pkg_sender = dsi_connector->pkg_sender;

	if (!pkg_sender || IS_ERR(pkg_sender)) {
		pkg_sender = kzalloc(sizeof(struct mdfld_dsi_pkg_sender),
								GFP_KERNEL);
		if (!pkg_sender) {
			DRM_ERROR("Create DSI pkg sender failed\n");
			return -ENOMEM;
		}
		dsi_connector->pkg_sender = (void *)pkg_sender;
	}

	pkg_sender->dev = dev;
	pkg_sender->dsi_connector = dsi_connector;
	pkg_sender->pipe = pipe;
	pkg_sender->pkg_num = 0;
	pkg_sender->panel_mode = 0;
	pkg_sender->status = MDFLD_DSI_PKG_SENDER_FREE;

	/*init regs*/
	/* FIXME: should just copy the regmap ptr ? */
	pkg_sender->dpll_reg = map->dpll;
	pkg_sender->dspcntr_reg = map->cntr;
	pkg_sender->pipeconf_reg = map->conf;
	pkg_sender->dsplinoff_reg = map->linoff;
	pkg_sender->dspsurf_reg = map->surf;
	pkg_sender->pipestat_reg = map->status;

	pkg_sender->mipi_intr_stat_reg = MIPI_INTR_STAT_REG(pipe);
	pkg_sender->mipi_lp_gen_data_reg = MIPI_LP_GEN_DATA_REG(pipe);
	pkg_sender->mipi_hs_gen_data_reg = MIPI_HS_GEN_DATA_REG(pipe);
	pkg_sender->mipi_lp_gen_ctrl_reg = MIPI_LP_GEN_CTRL_REG(pipe);
	pkg_sender->mipi_hs_gen_ctrl_reg = MIPI_HS_GEN_CTRL_REG(pipe);
	pkg_sender->mipi_gen_fifo_stat_reg = MIPI_GEN_FIFO_STAT_REG(pipe);
	pkg_sender->mipi_data_addr_reg = MIPI_DATA_ADD_REG(pipe);
	pkg_sender->mipi_data_len_reg = MIPI_DATA_LEN_REG(pipe);
	pkg_sender->mipi_cmd_addr_reg = MIPI_CMD_ADD_REG(pipe);
	pkg_sender->mipi_cmd_len_reg = MIPI_CMD_LEN_REG(pipe);

	/*init lock*/
	spin_lock_init(&pkg_sender->lock);

	if (mdfld_get_panel_type(dev, pipe) != TC35876X) {
		/**
		 * For video mode, don't enable DPI timing output here,
		 * will init the DPI timing output during mode setting.
		 */
		mipi_val = PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX;

		if (pipe == 0)
			mipi_val |= 0x2;

		REG_WRITE(MIPI_PORT_CONTROL(pipe), mipi_val);
		REG_READ(MIPI_PORT_CONTROL(pipe));

		/* do dsi controller init */
		mdfld_dsi_controller_init(dsi_config, pipe);
	}

	return 0;
}