static int __dpi_enter_ulps_locked(struct mdfld_dsi_config *dsi_config, int offset) { struct mdfld_dsi_hw_registers *regs = &dsi_config->regs; struct mdfld_dsi_hw_context *ctx = &dsi_config->dsi_hw_context; struct drm_device *dev = dsi_config->dev; struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_get_pkg_sender(dsi_config); if (!sender) { DRM_ERROR("pkg sender is NULL\n"); return -EINVAL; } ctx->device_ready = REG_READ(regs->device_ready_reg + offset); if (ctx->device_ready & DSI_POWER_STATE_ULPS_MASK) { DRM_ERROR("Broken ULPS states\n"); return -EINVAL; } /*wait for all FIFOs empty*/ mdfld_dsi_wait_for_fifos_empty(sender); /*inform DSI host is to be put on ULPS*/ ctx->device_ready |= DSI_POWER_STATE_ULPS_ENTER; REG_WRITE(regs->device_ready_reg + offset, ctx->device_ready); PSB_DEBUG_ENTRY("entered ULPS state\n"); return 0; }
static int __dpi_enter_ulps_locked(struct mdfld_dsi_config *dsi_config) { struct mdfld_dsi_hw_registers *regs = &dsi_config->regs; struct mdfld_dsi_hw_context *ctx = &dsi_config->dsi_hw_context; struct drm_device *dev = dsi_config->dev; struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_get_pkg_sender(dsi_config); int retry = 5; ulps_recovery: PSB_DEBUG_ENTRY("\n"); ctx->device_ready = REG_READ(regs->device_ready_reg); if (ctx->device_ready & DSI_POWER_STATE_ULPS_MASK) { DRM_ERROR("Broken ULPS states\n"); return -EINVAL; } if (!sender) { DRM_ERROR("Cannot get sender\n"); return -EINVAL; } /* check latch out, expected to be lp11 */ intel_dc_dsi_check_latch_out(dsi_config); /*wait for all FIFOs empty*/ mdfld_dsi_wait_for_fifos_empty(sender); /*inform DSI host is to be put on ULPS*/ ctx->device_ready |= (DSI_POWER_STATE_ULPS_ENTER | DSI_DEVICE_READY); REG_WRITE(regs->device_ready_reg, ctx->device_ready); mdelay(1); /* check latch out, expected to be lp00 */ intel_dc_dsi_check_latch_out(dsi_config); if (intel_dc_dsi_wait_for_lp00(dsi_config)) { DRM_ERROR("faild to wait for lp00 status\n"); DRM_ERROR("reg[0x%x] = 0x%x\n", regs->mipi_reg, REG_READ(regs->mipi_reg)); if (retry--) { DRM_INFO("%s: retry enter ulps (times=%d)\n", __func__, 5-retry); if (__dpi_exit_ulps_locked(dsi_config)) { DRM_ERROR("Failed to exit ULPS\n"); } goto ulps_recovery; } } /* set AFE hold value*/ REG_WRITE(regs->mipi_reg, REG_READ(regs->mipi_reg) & (~PASS_FROM_SPHY_TO_AFE)); DRM_INFO("%s: entered ULPS state\n", __func__); return 0; }
static int __dbi_enter_ulps_locked(struct mdfld_dsi_config *dsi_config, int offset) { struct mdfld_dsi_hw_registers *regs = &dsi_config->regs; struct mdfld_dsi_hw_context *ctx = &dsi_config->dsi_hw_context; struct drm_device *dev = dsi_config->dev; struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_get_pkg_sender(dsi_config); if (!sender) { DRM_ERROR("pkg sender is NULL\n"); return -EINVAL; } ctx->device_ready = REG_READ(regs->device_ready_reg + offset); if ((offset == 0) && (ctx->device_ready & DSI_POWER_STATE_ULPS_MASK)) { DRM_ERROR("Broken ULPS states\n"); return -EINVAL; } if (offset != 0) sender->work_for_slave_panel = true; /*wait for all FIFOs empty*/ mdfld_dsi_wait_for_fifos_empty(sender); sender->work_for_slave_panel = false; /*inform DSI host is to be put on ULPS*/ ctx->device_ready |= (DSI_POWER_STATE_ULPS_ENTER | DSI_DEVICE_READY); REG_WRITE(regs->device_ready_reg + offset, ctx->device_ready); mdelay(1); /* set AFE hold value*/ REG_WRITE(regs->mipi_reg + offset, REG_READ(regs->mipi_reg + offset) & (~PASS_FROM_SPHY_TO_AFE)); PSB_DEBUG_ENTRY("%s: entered ULPS state\n", __func__); return 0; }
/** * Power on sequence for command mode MIPI panel. * NOTE: do NOT modify this function */ static int __dbi_panel_power_on(struct mdfld_dsi_config *dsi_config, struct panel_funcs *p_funcs) { struct mdfld_dsi_hw_registers *regs; struct mdfld_dsi_hw_context *ctx; struct drm_psb_private *dev_priv; struct drm_device *dev; int reset_count = 10; int err = 0; struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_get_pkg_sender(dsi_config); struct mdfld_dbi_dsr_info *dsr_info; struct mdfld_dsi_dbi_output **dbi_outputs; struct mdfld_dsi_dbi_output *dbi_output; if (!sender) { DRM_ERROR("pkg sender is NULL\n"); return -EINVAL; } PSB_DEBUG_ENTRY("\n"); if (!dsi_config) return -EINVAL; regs = &dsi_config->regs; ctx = &dsi_config->dsi_hw_context; dev = dsi_config->dev; dev_priv = dev->dev_private; mdfld_dsi_dsr_forbid_locked(dsi_config); reset_recovery: --reset_count; err = 0; /*after entering dstb mode, need reset*/ if (p_funcs && p_funcs->exit_deep_standby) p_funcs->exit_deep_standby(dsi_config); if (__dbi_power_on(dsi_config)) { DRM_ERROR("Failed to init display controller!\n"); err = -EAGAIN; goto power_on_err; } /** * Different panel may have different ways to have * drvIC initialized. Support it! */ if (p_funcs && p_funcs->drv_ic_init) { if (p_funcs->drv_ic_init(dsi_config)) { DRM_ERROR("Failed to init dsi controller!\n"); err = -EAGAIN; goto power_on_err; } } /* Issue "write_mem_start" DSI command during power on. */ dsr_info = dev_priv->dbi_dsr_info; dbi_outputs = dsr_info->dbi_outputs; dbi_output = dsi_config->pipe ? dbi_outputs[1] : dbi_outputs[0]; if (!IS_ANN_A0(dev)) intel_dsi_dbi_update_fb(dbi_output); /** * Different panel may have different ways to have * panel turned on. Support it! */ if (p_funcs && p_funcs->power_on) if (p_funcs->power_on(dsi_config)) { DRM_ERROR("Failed to power on panel\n"); err = -EAGAIN; goto power_on_err; } if (p_funcs && p_funcs->set_brightness) if (p_funcs->set_brightness(dsi_config, ctx->lastbrightnesslevel)) DRM_ERROR("Failed to set panel brightness\n"); /*wait for all FIFOs empty*/ mdfld_dsi_wait_for_fifos_empty(sender); if (is_dual_dsi(dev)) { sender->work_for_slave_panel = true; mdfld_dsi_wait_for_fifos_empty(sender); sender->work_for_slave_panel = false; } if (IS_ANN_A0(dev)) intel_dsi_dbi_update_fb(dbi_output); power_on_err: if (err && reset_count) { DRM_ERROR("Failed to init panel, try reset it again!\n"); goto reset_recovery; } mdfld_dsi_dsr_allow_locked(dsi_config); return err; }
static int enter_dsr_locked(struct mdfld_dsi_config *dsi_config, int level) { u32 val = 0; struct mdfld_dsi_hw_registers *regs; struct mdfld_dsi_hw_context *ctx; struct drm_psb_private *dev_priv; struct drm_device *dev; struct mdfld_dsi_pkg_sender *sender; int err; pm_message_t state; int pipe0_enabled; int pipe2_enabled; PSB_DEBUG_ENTRY("mdfld_dsi_dsr: enter dsr\n"); if (!dsi_config) return -EINVAL; regs = &dsi_config->regs; ctx = &dsi_config->dsi_hw_context; dev = dsi_config->dev; dev_priv = dev->dev_private; sender = mdfld_dsi_get_pkg_sender(dsi_config); if (!sender) { DRM_ERROR("Failed to get dsi sender\n"); return -EINVAL; } if (level < DSR_EXITED) { DRM_ERROR("Why to do this?"); return -EINVAL; } if (level > DSR_ENTERED_LEVEL0) { /** * TODO: require OSPM interfaces to tell OSPM module that * display controller is ready to be power gated. * OSPM module needs to response this request ASAP. * NOTE: it makes no sense to have display controller islands * & pci power gated here directly. OSPM module is the only one * who can power gate/ungate power islands. * FIXME: since there's no ospm interfaces for acquiring * suspending DSI related power islands, we have to call OSPM * interfaces to power gate display islands and pci right now, * which should NOT happen in this way!!! */ if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_FORCE_POWER_ON)) { DRM_ERROR("Failed power on display island\n"); return -EINVAL; } PSB_DEBUG_ENTRY("mdfld_dsi_dsr: entering DSR level 1\n"); /*Disable TE, don't need it anymore*/ mdfld_disable_te(dev, dsi_config->pipe); err = mdfld_dsi_wait_for_fifos_empty(sender); if (err) { DRM_ERROR("mdfld_dsi_dsr: FIFO not empty\n"); mdfld_enable_te(dev, dsi_config->pipe); ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); return err; } ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); /*suspend whole PCI host and related islands ** if failed at this try, revive te for another chance */ state.event = 0; if (ospm_power_suspend(gpDrmDevice->pdev, state)) { /* Only display island is powered off then ** need revive the whole TE */ if (!ospm_power_is_hw_on(OSPM_DISPLAY_ISLAND)) exit_dsr_locked(dsi_config); else mdfld_enable_te(dev, dsi_config->pipe); return -EINVAL; } /* *suspend pci *FIXME: should I do it here? *how about decoder/encoder is working?? *OSPM should check the refcout of each islands before *actually power off PCI!!! *need invoke this in the same context, we need deal with *DSR lock later for suspend PCI may go to sleep!!! */ /*ospm_suspend_pci(dev->pdev);*/ PSB_DEBUG_ENTRY("mdfld_dsi_dsr: entered\n"); return 0; } /* * if DSR_EXITED < level < DSR_ENTERED_LEVEL1, we only have the display * controller components turned off instead of power gate them. * this is useful for HDMI & WIDI. */ if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_FORCE_POWER_ON)) { DRM_ERROR("Failed power on display island\n"); return -EINVAL; } PSB_DEBUG_ENTRY("mdfld_dsi_dsr: entering DSR level 0\n"); /*Disable TE, don't need it anymore*/ mdfld_disable_te(dev, dsi_config->pipe); err = mdfld_dsi_wait_for_fifos_empty(sender); if (err) { DRM_ERROR("mdfld_dsi_dsr: FIFO not empty\n"); mdfld_enable_te(dev, dsi_config->pipe); ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); return err; } /*turn off dbi interface put in ulps*/ __dbi_power_off(dsi_config); ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); PSB_DEBUG_ENTRY("entered\n"); return 0; }