/* Perodically update dbi panel */ void mdfld_dbi_update_panel(struct drm_device *dev, int pipe) { struct drm_psb_private *dev_priv = dev->dev_private; struct mdfld_dbi_dsr_info *dsr_info = dev_priv->dbi_dsr_info; struct mdfld_dsi_dbi_output **dbi_outputs; struct mdfld_dsi_dbi_output *dbi_output; struct mdfld_dsi_config *dsi_config; struct mdfld_dsi_hw_context *ctx; if (!dsr_info) return; dbi_outputs = dsr_info->dbi_outputs; dbi_output = pipe ? dbi_outputs[1] : dbi_outputs[0]; dsi_config = pipe ? dev_priv->dsi_configs[1] : dev_priv->dsi_configs[0]; if (!dbi_output || !dsi_config || (pipe == 1) || (is_panel_vid_or_cmd(dev) != MDFLD_DSI_ENCODER_DBI)) return; ctx = &dsi_config->dsi_hw_context; /*lock dsi config*/ mutex_lock(&dsi_config->context_lock); /*if FB is damaged and panel is on update on-panel FB*/ if (!ctx->panel_on) goto update_out; intel_dsi_dbi_update_fb(dbi_output); update_out: mutex_unlock(&dsi_config->context_lock); }
/** * Set up the display clock * */ void mrfld_setup_pll(struct drm_device *dev, int pipe, int clk) { DRM_DRIVER_PRIVATE_T *dev_priv = dev->dev_private; int refclk = 0; int clk_n = 0, clk_p2 = 0, clk_byte = 1, m_conv = 0, clk_tmp = 0; struct mrst_clock_t clock; bool ok; u32 pll = 0, fp = 0; bool is_mipi = false, is_mipi2 = false, is_hdmi = false; struct mdfld_dsi_config *dsi_config = NULL; struct mdfld_dsi_hw_context *ctx = NULL; PSB_DEBUG_ENTRY("pipe = 0x%x\n", pipe); if (pipe == 0) dsi_config = dev_priv->dsi_configs[0]; else if (pipe == 2) dsi_config = dev_priv->dsi_configs[1]; if ((pipe != 1) && !dsi_config) { DRM_ERROR("Invalid DSI config\n"); return; } if (pipe != 1) { ctx = &dsi_config->dsi_hw_context; mutex_lock(&dsi_config->context_lock); } switch (pipe) { case 0: is_mipi = true; break; case 1: is_hdmi = true; break; case 2: is_mipi2 = true; break; } if ((dev_priv->ksel == KSEL_CRYSTAL_19) || (dev_priv->ksel == KSEL_BYPASS_19)) { refclk = 19200; if (is_mipi || is_mipi2) { clk_n = 1, clk_p2 = 8; } else if (is_hdmi) { clk_n = 1, clk_p2 = 10; } } else if (dev_priv->ksel == KSEL_BYPASS_25) { refclk = 25000; if (is_mipi || is_mipi2) { clk_n = 1, clk_p2 = 8; } else if (is_hdmi) { clk_n = 1, clk_p2 = 10; } } else if ((dev_priv->ksel == KSEL_BYPASS_83_100) && (dev_priv->core_freq == 166)) { refclk = 83000; if (is_mipi || is_mipi2) { clk_n = 4, clk_p2 = 8; } else if (is_hdmi) { clk_n = 4, clk_p2 = 10; } } else if ((dev_priv->ksel == KSEL_BYPASS_83_100) && (dev_priv->core_freq == 100 || dev_priv->core_freq == 200)) { refclk = 100000; if (is_mipi || is_mipi2) { clk_n = 4, clk_p2 = 8; } else if (is_hdmi) { clk_n = 4, clk_p2 = 10; } } if (is_mipi || is_mipi2) clk_byte = 3; clk_tmp = clk * clk_n * clk_p2 * clk_byte; PSB_DEBUG_ENTRY("clk = %d, clk_n = %d, clk_p2 = %d. \n", clk, clk_n, clk_p2); PSB_DEBUG_ENTRY("clk = %d, clk_tmp = %d, clk_byte = %d. \n", clk, clk_tmp, clk_byte); ok = mrfld_find_best_PLL(dev, pipe, clk_tmp, refclk, &clock); dev_priv->tmds_clock_khz = clock.dot / (clk_n * clk_p2 * clk_byte); /* * FIXME: Hard code the divisors' value for JDI panel, and need to * calculate them according to the DSI PLL HAS spec. */ if (pipe != 1) { if (is_panel_vid_or_cmd(dev) == MDFLD_DSI_ENCODER_DBI) { if (get_panel_type(dev, pipe) == JDI_CMD) { clock.p1 = 4; clk_n = 1; clock.m = 142; } else { clock.p1 = 4; clk_n = 1; clock.m = 120; } } else { clock.p1 = 5; clk_n = 1; clock.m = 130; } } if (!ok) { DRM_ERROR("mdfldFindBestPLL fail in mrfld_crtc_mode_set.\n"); } else { m_conv = mrfld_m_converts[(clock.m - MRFLD_M_MIN)]; PSB_DEBUG_ENTRY("dot clock = %d," "m = %d, p1 = %d, m_conv = %d. \n", clock.dot, clock.m, clock.p1, m_conv); } /* Write the N1 & M1 parameters into DSI_PLL_DIV_REG */ fp = (clk_n / 2) << 16; fp |= m_conv; if (is_mipi) { /* Enable DSI PLL clocks for DSI0 rather than CCK. */ pll |= _CLK_EN_PLL_DSI0; pll &= ~_CLK_EN_CCK_DSI0; /* Select DSI PLL as the source of the mux input clocks. */ pll &= ~_DSI_MUX_SEL_CCK_DSI0; } if (is_mipi2) { /* Enable DSI PLL clocks for DSI1 rather than CCK. */ pll |= _CLK_EN_PLL_DSI1; pll &= ~_CLK_EN_CCK_DSI1; /* Select DSI PLL as the source of the mux input clocks. */ pll &= ~_DSI_MUX_SEL_CCK_DSI1; } if (is_hdmi) pll |= MDFLD_VCO_SEL; /* compute bitmask from p1 value */ pll |= (1 << (clock.p1 - 2)) << 17; if (pipe != 1) { ctx->dpll = pll; ctx->fp = fp; mutex_unlock(&dsi_config->context_lock); } }
static void intel_dsi_dbi_update_fb(struct mdfld_dsi_dbi_output *dbi_output) { struct mdfld_dsi_pkg_sender *sender; struct drm_device *dev = dbi_output->dev; struct drm_crtc *crtc = dbi_output->base.base.crtc; struct psb_intel_crtc *psb_crtc = (crtc) ? to_psb_intel_crtc(crtc) : NULL; int pipe = dbi_output->channel_num ? 2 : 0; u32 dpll_reg = MRST_DPLL_A; u32 dspcntr_reg = DSPACNTR; u32 pipeconf_reg = PIPEACONF; u32 dsplinoff_reg = DSPALINOFF; u32 dspsurf_reg = DSPASURF; sender = mdfld_dsi_encoder_get_pkg_sender(&dbi_output->base); if (!sender) { DRM_ERROR("pkg sender is NULL\n"); return; } /* if mode setting on-going, back off */ if (!IS_ANN_A0(dev)) { if ((dbi_output->mode_flags & MODE_SETTING_ON_GOING) || (psb_crtc && (psb_crtc->mode_flags & MODE_SETTING_ON_GOING)) || !(dbi_output->mode_flags & MODE_SETTING_ENCODER_DONE)) return; } if (pipe == 2) { dspcntr_reg = DSPCCNTR; pipeconf_reg = PIPECCONF; dsplinoff_reg = DSPCLINOFF; dspsurf_reg = DSPCSURF; } /* check DBI FIFO status */ if (is_panel_vid_or_cmd(dev) == MDFLD_DSI_ENCODER_DBI) { if (!(REG_READ(dspcntr_reg) & DISPLAY_PLANE_ENABLE) || !(REG_READ(pipeconf_reg) & DISPLAY_PLANE_ENABLE)) return; } else if (!(REG_READ(dpll_reg) & DPLL_VCO_ENABLE) || !(REG_READ(dspcntr_reg) & DISPLAY_PLANE_ENABLE) || !(REG_READ(pipeconf_reg) & DISPLAY_PLANE_ENABLE)) return; if (!IS_ANN_A0(dev)) { /* refresh plane changes */ REG_WRITE(dsplinoff_reg, REG_READ(dsplinoff_reg)); REG_WRITE(dspsurf_reg, REG_READ(dspsurf_reg)); REG_READ(dspsurf_reg); } mdfld_dsi_send_dcs(sender, write_mem_start, NULL, 0, CMD_DATA_SRC_PIPE, MDFLD_DSI_SEND_PACKAGE); dbi_output->dsr_fb_update_done = true; mdfld_dsi_cmds_kick_out(sender); }