void enable_HFPLL(struct drm_device *dev) { uint32_t pll_select = 0, ctrl_reg5 = 0; struct drm_psb_private *dev_priv = (struct drm_psb_private *)dev->dev_private; /* Enable HFPLL for command mode panel */ if (dev_priv->bUseHFPLL) { pll_select = intel_mid_msgbus_read32(CCK_PORT, DSI_PLL_CTRL_REG); ctrl_reg5 = intel_mid_msgbus_read32(CCK_PORT, FUSE_OVERRIDE_FREQ_CNTRL_REG5); pll_select &= ~(_DSI_MUX_SEL_CCK_DSI1 | _DSI_MUX_SEL_CCK_DSI0); intel_mid_msgbus_write32(CCK_PORT, DSI_PLL_CTRL_REG, pll_select | _DSI_CCK_PLL_SELECT); ctrl_reg5 |= (1 << 7) | 0xF; if (get_panel_type(dev, 0) == SHARP_10x19_CMD) ctrl_reg5 = 0x1f87; intel_mid_msgbus_write32(CCK_PORT, FUSE_OVERRIDE_FREQ_CNTRL_REG5, ctrl_reg5); } }
/** * 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); } }
void mdfld_reset_panel_handler_work(struct work_struct *work) { struct drm_psb_private *dev_priv = container_of(work, struct drm_psb_private, reset_panel_work); struct mdfld_dsi_config *dsi_config = NULL; struct mdfld_dsi_dbi_output *dbi_output = NULL; struct panel_funcs *p_funcs = NULL; struct drm_device *dev; dbi_output = dev_priv->dbi_output; dsi_config = dev_priv->dsi_configs[0]; if (!dsi_config || !dbi_output) return; dev = dsi_config->dev; /*disable ESD when HDMI connected*/ if (hdmi_state) return; PSB_DEBUG_ENTRY("\n"); p_funcs = dbi_output->p_funcs; if (p_funcs) { mutex_lock(&dsi_config->context_lock); if (!dsi_config->dsi_hw_context.panel_on) { DRM_INFO("don't reset panel when panel is off\n"); mutex_unlock(&dsi_config->context_lock); return; } DRM_INFO("Starts ESD panel reset\n"); /* * since panel is in abnormal state, * we do a power off/on first */ power_island_put(OSPM_DISPLAY_A | OSPM_DISPLAY_C | OSPM_DISPLAY_MIO); power_island_get(OSPM_DISPLAY_A | OSPM_DISPLAY_C | OSPM_DISPLAY_MIO); if (__dbi_panel_power_off(dsi_config, p_funcs)) DRM_INFO("failed to power off dbi panel\n"); if (get_panel_type(dev, 0) == JDI_7x12_CMD) if (p_funcs && p_funcs->reset) p_funcs->reset(dsi_config); if (__dbi_panel_power_on(dsi_config, p_funcs)) { DRM_ERROR("failed to power on dbi panel\n"); mutex_unlock(&dsi_config->context_lock); return; } mutex_unlock(&dsi_config->context_lock); /*recover pipestat in case island once been poweroff and pipestat was reset to default*/ mdfld_recover_te(dev, dsi_config->pipe); DRM_INFO("%s: End panel reset\n", __func__); } else { DRM_INFO("%s invalid panel init\n", __func__); } }
bool enable_DSIPLL(struct drm_device *dev) { DRM_DRIVER_PRIVATE_T *dev_priv = dev->dev_private; struct mdfld_dsi_config *dsi_config = NULL; struct mdfld_dsi_hw_context *ctx = NULL; u32 guit_val = 0x0; u32 retry; if (!dev_priv) goto err_out; dsi_config = dev_priv->dsi_configs[0]; if (!dsi_config) goto err_out; ctx = &dsi_config->dsi_hw_context; if (IS_ANN(dev)) { int dspfreq; if ((get_panel_type(dev, 0) == JDI_7x12_CMD) || (get_panel_type(dev, 0) == JDI_7x12_VID)) dspfreq = DISPLAY_FREQ_FOR_200; else dspfreq = DISPLAY_FREQ_FOR_333; intel_mid_msgbus_write32(CCK_PORT, FUSE_OVERRIDE_FREQ_CNTRL_REG5, CKESC_GATE_EN | CKDP1X_GATE_EN | DISPLAY_FRE_EN | dspfreq); } /* Prepare DSI PLL register before enabling */ intel_mid_msgbus_write32(CCK_PORT, DSI_PLL_DIV_REG, 0); guit_val = intel_mid_msgbus_read32(CCK_PORT, DSI_PLL_CTRL_REG); guit_val &= ~(DPLL_VCO_ENABLE | _DSI_LDO_EN |_CLK_EN_MASK | _DSI_MUX_SEL_CCK_DSI0 | _DSI_MUX_SEL_CCK_DSI1); intel_mid_msgbus_write32(CCK_PORT, DSI_PLL_CTRL_REG, guit_val); udelay(1); /* Program PLL */ /*first set up the dpll and fp variables * dpll - will contain the following information * - the clock source - DSI vs HFH vs LFH PLL * - what clocks should be running DSI0, DSI1 * - and the divisor. * */ intel_mid_msgbus_write32(CCK_PORT, DSI_PLL_DIV_REG, ctx->fp); guit_val &= ~_P1_POST_DIV_MASK; /*clear the divisor bit*/ /* the ctx->dpll contains the divisor that we need to use as well as which clocks * need to start up */ guit_val |= ctx->dpll; guit_val &= ~_DSI_LDO_EN; /* We want to clear the LDO enable when programming*/ guit_val |= DPLL_VCO_ENABLE; /* Enable the DSI PLL */ /* For the CD clock (clock used by Display controller), we need to set * the DSI_CCK_PLL_SELECT bit (bit 11). This should already be set. But * setting it just in case */ if (dev_priv->bUseHFPLL) guit_val |= _DSI_CCK_PLL_SELECT; intel_mid_msgbus_write32(CCK_PORT, DSI_PLL_CTRL_REG, guit_val); /* Wait for DSI PLL lock */ retry = 10000; guit_val = intel_mid_msgbus_read32(CCK_PORT, DSI_PLL_CTRL_REG); while (((guit_val & _DSI_PLL_LOCK) != _DSI_PLL_LOCK) && (--retry)) { udelay(3); guit_val = intel_mid_msgbus_read32(CCK_PORT, DSI_PLL_CTRL_REG); if (!retry%1000) DRM_ERROR("DSI PLL taking too long to lock" "- retry count=%d\n", 10000-retry); } if (retry == 0) { DRM_ERROR("DSI PLL fails to lock\n"); return false; } return true; err_out: return false; }