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