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"); }
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; }
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; }