void intel_dsi_clear_device_ready(struct intel_encoder *encoder)
{
	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
	struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
	int pipe = intel_crtc->pipe;
	u32 val;

	DRM_DEBUG_KMS("\n");

	I915_WRITE_BITS(MIPI_DEVICE_READY(pipe), ULPS_STATE_ENTER | DEVICE_READY,
							ULPS_STATE_MASK | DEVICE_READY);
	usleep_range(2000, 2500);

	I915_WRITE_BITS(MIPI_DEVICE_READY(pipe), ULPS_STATE_EXIT | DEVICE_READY,
							ULPS_STATE_MASK | DEVICE_READY);
	usleep_range(2000, 2500);

	I915_WRITE_BITS(MIPI_DEVICE_READY(pipe), ULPS_STATE_ENTER | DEVICE_READY,
							ULPS_STATE_MASK | DEVICE_READY);
	usleep_range(2000, 2500);

	if (wait_for(((I915_READ(MIPI_PORT_CTRL(pipe)) & 0x20000)
					== 0x00000), 30))
		DRM_ERROR("DSI LP not going Low\n");

	I915_WRITE_BITS(MIPI_PORT_CTRL(pipe), 0, LP_OUTPUT_HOLD);
	usleep_range(1000, 1500);

	I915_WRITE_BITS(MIPI_DEVICE_READY(pipe), 0x00, DEVICE_READY);
	usleep_range(2000, 2500);

	intel_disable_dsi_pll(intel_dsi);

	val = I915_READ(DSPCLK_GATE_D);
	val &= ~VSUNIT_CLOCK_GATE_DISABLE;
	I915_WRITE(DSPCLK_GATE_D, val);

	if (intel_dsi->dev.dev_ops->disable_panel_power)
		intel_dsi->dev.dev_ops->disable_panel_power(&intel_dsi->dev);

#ifdef CONFIG_CRYSTAL_COVE
	if (BYT_CR_CONFIG) {
		/* Disable Panel */
		vlv_gpio_nc_write(dev_priv, GPIO_NC_11_PCONF0, 0x2000CC00);
		vlv_gpio_nc_write(dev_priv, GPIO_NC_11_PAD, 0x00000004);
		udelay(500);
	} else
		intel_mid_pmic_writeb(PMIC_PANEL_EN, 0x00);
#else
	/* need to code for BYT-CR for example where things have changed */
	DRM_ERROR("PANEL Disable to supported yet\n");
#endif
	msleep(intel_dsi->panel_off_delay);
	msleep(intel_dsi->panel_pwr_cycle_delay);
}
void intel_dsi_port_disable(struct intel_encoder *encoder)
{
	struct drm_device *dev = encoder->base.dev;
	struct drm_i915_private *dev_priv = dev->dev_private;
	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
	struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
	int pipe = intel_crtc->pipe;

	if (intel_dsi->dual_link) {
		I915_WRITE_BITS(MIPI_PORT_CTRL(0), 0, DPI_ENABLE);
		POSTING_READ(MIPI_PORT_CTRL(0));

		I915_WRITE_BITS(MIPI_PORT_CTRL(1), 0, DPI_ENABLE);
		POSTING_READ(MIPI_PORT_CTRL(1));
	} else {
		I915_WRITE_BITS(MIPI_PORT_CTRL(pipe), 0, DPI_ENABLE);
		POSTING_READ(MIPI_PORT_CTRL(pipe));
	}

	usleep_range(2000, 2500);
}
static void intel_dsi_post_disable(struct intel_encoder *encoder)
{
	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
	struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
	int pipe = intel_crtc->pipe;
	u32 tmp;

	wait_for_dsi_fifo_empty(intel_dsi);

	I915_WRITE_BITS(MIPI_PORT_CTRL(pipe), 0, DPI_ENABLE);
	POSTING_READ(MIPI_PORT_CTRL(pipe));
	usleep_range(2000, 2500);

	/* Panel commands can be sent when clock is in LP11 */
	tmp = I915_READ(MIPI_DEVICE_READY(pipe));
	tmp &= ~DEVICE_READY;
	I915_WRITE(MIPI_DEVICE_READY(pipe), tmp);

	tmp = I915_READ(MIPI_CTRL(pipe));
	tmp &= ~ESCAPE_CLOCK_DIVIDER_MASK;
	I915_WRITE(MIPI_CTRL(pipe), tmp |
		intel_dsi->escape_clk_div <<
			ESCAPE_CLOCK_DIVIDER_SHIFT);

	tmp = I915_READ(MIPI_DSI_FUNC_PRG(pipe));
	tmp &= ~VID_MODE_FORMAT_MASK;
	I915_WRITE(MIPI_DSI_FUNC_PRG(pipe), tmp);

	I915_WRITE(MIPI_EOT_DISABLE(pipe), CLOCKSTOP);

	tmp = I915_READ(MIPI_DEVICE_READY(pipe));
	tmp &= DEVICE_READY;
	I915_WRITE(MIPI_DEVICE_READY(pipe), tmp);

	/* if disable packets are sent before sending shutdown packet then in
	* some next enable sequence send turn on packet error is observed */

	if (intel_dsi->dev.dev_ops->disable)
		intel_dsi->dev.dev_ops->disable(&intel_dsi->dev);

	wait_for_dsi_fifo_empty(intel_dsi);
	intel_dsi_clear_device_ready(encoder);
}
int intel_disable_dsi_pll(struct intel_dsi *intel_dsi)
{
	struct drm_i915_private *dev_priv =
			intel_dsi->base.base.dev->dev_private;

	intel_cck_write32_bits(dev_priv, 0x48, 0x00000000, 0x80000000);
	udelay(500);

	/* FIXME: DSI PLL is disable before pipe is disabled, because of this
	 * ref clock will not be disabled when only mipi panel is connected.
	 * Need to fix this.
	 */
	if ((PIPECONF(PIPE_A) & PIPECONF_ENABLE == 0) &&
		(PIPECONF(PIPE_B) & PIPECONF_ENABLE == 0)
		)
		I915_WRITE_BITS(_DPLL_A, 0x00000000, DPLL_REFA_CLK_ENABLE_VLV);

	return 0;
}
int intel_disable_dsi_pll(struct intel_dsi *intel_dsi)
{
	struct drm_i915_private *dev_priv = intel_dsi->base.base.dev->dev_private;
	u32 tmp;

	DRM_DEBUG_KMS("\n");

	mutex_lock(&dev_priv->dpio_lock);
	tmp = vlv_cck_read(dev_priv, CCK_REG_DSI_PLL_CONTROL);
	tmp &= ~DSI_PLL_VCO_EN;
	tmp |= DSI_PLL_LDO_GATE;
	vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_CONTROL, tmp);
	if ((I915_READ(PIPECONF(PIPE_A)) & (PIPECONF_ENABLE == 0)) &&
		(I915_READ(PIPECONF(PIPE_B)) & (PIPECONF_ENABLE == 0)))
		I915_WRITE_BITS(_DPLL_A, 0x00000000, DPLL_REFA_CLK_ENABLE_VLV);

	mutex_unlock(&dev_priv->dpio_lock);

	return 0;
}
int intel_enable_dsi_pll(struct intel_dsi *intel_dsi)
{
	struct drm_i915_private *dev_priv =
			intel_dsi->base.base.dev->dev_private;

	/* enable DPLL ref clock */
	I915_WRITE_BITS(_DPLL_A, DPLL_REFA_CLK_ENABLE_VLV,
						DPLL_REFA_CLK_ENABLE_VLV);

	udelay(1000);	/*wait 0.5us after ungating before enabling again */
	intel_cck_write32_bits(dev_priv, 0x48, 1 << 31,  1 << 31);

	if (wait_for(((I915_READ(PIPECONF(intel_dsi->pipe)) & (1 << 29)) ==
			(1 << 29)), 20)) {
		DRM_ERROR("DSI PLL lock failed\n");
		return -EIO;
	}

	DRM_DEBUG_KMS("DSI PLL locked\n");
	return 0;
}
int intel_enable_dsi_pll(struct intel_dsi *intel_dsi)
{
	struct drm_encoder *encoder = &(intel_dsi->base.base);
	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
	struct drm_display_mode *mode = &intel_crtc->config.adjusted_mode;
	struct drm_i915_private *dev_priv =
					intel_dsi->base.base.dev->dev_private;
	u32 tmp;

	DRM_DEBUG_KMS("\n");
	if ((I915_READ(PIPECONF(PIPE_A)) & PIPECONF_DSI_PLL_LOCKED)) {
		DRM_DEBUG_KMS("DSI PLL Already locked\n");
		return 0;
	}

	mutex_lock(&dev_priv->dpio_lock);
	intel_configure_dsi_pll(intel_dsi, mode);

	/* wait at least 0.5 us after ungating before enabling VCO */
	usleep_range(1, 10);

	tmp = vlv_cck_read(dev_priv, CCK_REG_DSI_PLL_CONTROL);
	tmp |= DSI_PLL_VCO_EN;
	/* enable DPLL ref clock */
	I915_WRITE_BITS(_DPLL_A, DPLL_REFA_CLK_ENABLE_VLV,
						DPLL_REFA_CLK_ENABLE_VLV);
	udelay(1000);
	vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_CONTROL, tmp);

	mutex_unlock(&dev_priv->dpio_lock);

	if (wait_for(I915_READ(PIPECONF(PIPE_A)) & PIPECONF_DSI_PLL_LOCKED, 20)) {
		DRM_ERROR("DSI PLL lock failed\n");
		return -1;
	}

	DRM_DEBUG_KMS("DSI PLL locked\n");
	return 0;
}
static void intel_dsi_mode_set(struct intel_encoder *intel_encoder)
{
	struct drm_encoder *encoder = &intel_encoder->base;
	struct drm_device *dev = encoder->dev;
	struct drm_i915_private *dev_priv = dev->dev_private;
	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
	struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
	int pipe = intel_crtc->pipe;
	unsigned int bpp = intel_crtc->config.pipe_bpp;
	struct drm_display_mode *adjusted_mode = &intel_crtc->config.adjusted_mode;
	u32 val;

	intel_dsi_device_ready(intel_encoder);

	I915_WRITE(MIPI_DEVICE_READY(pipe), 0x0);

	dsi_config(encoder);

	I915_WRITE(MIPI_LP_RX_TIMEOUT(pipe), intel_dsi->lp_rx_timeout);
	I915_WRITE(MIPI_TURN_AROUND_TIMEOUT(pipe),
					intel_dsi->turn_arnd_val);
	I915_WRITE(MIPI_DEVICE_RESET_TIMER(pipe),
					intel_dsi->rst_timer_val);
	/* in terms of low power clock */
	I915_WRITE(MIPI_INIT_COUNT(pipe), intel_dsi->init_count);

	I915_WRITE(MIPI_HIGH_LOW_SWITCH_COUNT(pipe), \
					intel_dsi->hs_to_lp_count);
	I915_WRITE(MIPI_LP_BYTECLK(pipe), intel_dsi->lp_byte_clk);

	I915_WRITE(MIPI_CLK_LANE_SWITCH_TIME_CNT(pipe),
		((u32)intel_dsi->clk_lp_to_hs_count
		<< LP_HS_SSW_CNT_SHIFT) |
		(intel_dsi->clk_hs_to_lp_count << HS_LP_PWR_SW_CNT_SHIFT));

	if (is_vid_mode(intel_dsi)) {
		I915_WRITE(MIPI_DPI_RESOLUTION(pipe),
			(adjusted_mode->vdisplay << VERTICAL_ADDRESS_SHIFT) |
			(adjusted_mode->hdisplay << HORIZONTAL_ADDRESS_SHIFT));

		set_dsi_timings(encoder, adjusted_mode);

		if (intel_dsi->video_mode_type == DSI_VIDEO_BURST) {
			I915_WRITE(MIPI_HS_TX_TIMEOUT(pipe),
				txbyteclkhs(adjusted_mode->htotal, bpp,
				intel_dsi->lane_count) + 1);
		}
		else {
			I915_WRITE(MIPI_HS_TX_TIMEOUT(pipe),
			   txbyteclkhs(adjusted_mode->vtotal *
				   adjusted_mode->htotal,
				   bpp, intel_dsi->lane_count) + 1);
		}
	} else {
		val = intel_dsi->channel << CMD_MODE_CHANNEL_NUMBER_SHIFT |
			intel_dsi->lane_count << DATA_LANES_PRG_REG_SHIFT |
			intel_dsi->data_width;
		I915_WRITE(MIPI_DSI_FUNC_PRG(pipe), val);

		I915_WRITE(MIPI_HS_TX_TIMEOUT(pipe),
			txbyteclkhs(adjusted_mode->hdisplay *
			adjusted_mode->vdisplay,
			bpp, intel_dsi->lane_count) + 1);

		I915_WRITE(MIPI_DBI_BW_CTRL(pipe), intel_dsi->bw_timer);
	}

	I915_WRITE(MIPI_EOT_DISABLE(pipe), CLOCKSTOP);

	val = I915_READ(MIPI_DSI_FUNC_PRG(pipe));
	val &= ~VID_MODE_FORMAT_MASK;
	I915_WRITE(MIPI_DSI_FUNC_PRG(pipe), val);

	I915_WRITE(MIPI_DEVICE_READY(pipe), 0x1);

#if 0
//in dual display config, dsi 0 is not init. so this function may not
    //be called with pipe0. set this flag for pipe0 so that pipe b can work
    #ifdef BYT_DUAL_MIPI_DSI  
    if(pipe != 0)
    {

        I915_WRITE_BITS(MIPI_PORT_CTRL(0), LP_OUTPUT_HOLD,
                LP_OUTPUT_HOLD);

        usleep_range(1000, 1500);
    }
    #endif
#endif
    
	if (intel_dsi->dev.dev_ops->send_otp_cmds)
		intel_dsi->dev.dev_ops->send_otp_cmds(&intel_dsi->dev);

	I915_WRITE(MIPI_DEVICE_READY(pipe), 0x0);

	set_dsi_timings(encoder, adjusted_mode);

	/* Some panels might have resolution which is not a multiple of
	 * 64 like 1366 x 768. Enable RANDOM resolution support for such
	 * panels by default */
	I915_WRITE(MIPI_VIDEO_MODE_FORMAT(pipe),
				intel_dsi->video_frmt_cfg_bits |
				intel_dsi->video_mode_type |
				IP_TG_CONFIG |
				RANDOM_DPI_DISPLAY_RESOLUTION);

	val = 0;
	if (intel_dsi->eotp_pkt == 0)
		val |= EOT_DISABLE;

	if (intel_dsi->clock_stop)
		val |= CLOCKSTOP;

	I915_WRITE(MIPI_EOT_DISABLE(pipe), val);

	val = intel_dsi->channel << VID_MODE_CHANNEL_NUMBER_SHIFT |
		intel_dsi->lane_count << DATA_LANES_PRG_REG_SHIFT |
		intel_dsi->pixel_format;
	I915_WRITE(MIPI_DSI_FUNC_PRG(pipe), val);

	I915_WRITE(MIPI_DEVICE_READY(pipe), 0x1);

	I915_WRITE(MIPI_INTR_STAT(pipe), 0xFFFFFFFF);
	/* Max packet return size limits the size of returning
	* packet so that host processor can prevent buffer overflow
	* condition when receiving data from peripheral. DCS read
	* need this to be set.*/
	I915_WRITE(MIPI_MAX_RETURN_PKT_SIZE(pipe), 0xff);
}
void intel_dsi_device_ready(struct intel_encoder *encoder)
{
	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
	struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
	int pipe = intel_crtc->pipe;
	u32 tmp;

	DRM_DEBUG_KMS("\n");

	/* program rcomp for compliance
	 * reduce form 50 ohms to 45 ohms */
	intel_flisdsi_write32(dev_priv, 0x04, 0x00f0);

	band_gap_reset(dev_priv);

#ifdef CONFIG_CRYSTAL_COVE
	/* Panel Enable */
	if (BYT_CR_CONFIG) {
		/*  cabc disable */
		vlv_gpio_nc_write(dev_priv, GPIO_NC_9_PCONF0, 0x2000CC00);
		vlv_gpio_nc_write(dev_priv, GPIO_NC_9_PAD, 0x00000004);

		/* panel enable */
		vlv_gpio_nc_write(dev_priv, GPIO_NC_11_PCONF0, 0x2000CC00);
		vlv_gpio_nc_write(dev_priv, GPIO_NC_11_PAD, 0x00000005);
		udelay(500);
	} else
		intel_mid_pmic_writeb(PMIC_PANEL_EN, 0x01);

#else
	/* need to code for BYT-CR for example where things have changed */
	DRM_ERROR("PANEL Enable to supported yet\n");
#endif
	msleep(intel_dsi->panel_on_delay);

	if (intel_dsi->dev.dev_ops->panel_reset)
		intel_dsi->dev.dev_ops->panel_reset(&intel_dsi->dev);

	/* Disable DPOunit clock gating, can stall pipe */
	tmp = I915_READ(DPLL(pipe));
	tmp |= DPLL_RESERVED_BIT;
	I915_WRITE(DPLL(pipe), tmp);

	tmp = I915_READ(DSPCLK_GATE_D);
	tmp |= VSUNIT_CLOCK_GATE_DISABLE;
	I915_WRITE(DSPCLK_GATE_D, tmp);

	intel_enable_dsi_pll(intel_dsi);

    //in dual display config, dsi 0 is not init. so this function may not
    //be called with pipe0. set this flag for pipe0 so that pipe b can work
    #ifdef BYT_DUAL_MIPI_DSI  
    if(pipe != 0)
    {

        I915_WRITE_BITS(MIPI_PORT_CTRL(0), LP_OUTPUT_HOLD,
                LP_OUTPUT_HOLD);

        usleep_range(1000, 1500);
    }
    #endif


	I915_WRITE_BITS(MIPI_PORT_CTRL(pipe), LP_OUTPUT_HOLD,
						LP_OUTPUT_HOLD);

	usleep_range(1000, 1500);
	I915_WRITE_BITS(MIPI_DEVICE_READY(pipe), DEVICE_READY |
			ULPS_STATE_EXIT, DEVICE_READY |
			ULPS_STATE_MASK);

	usleep_range(2000, 2500);
	I915_WRITE_BITS(MIPI_DEVICE_READY(pipe), DEVICE_READY,
			DEVICE_READY | ULPS_STATE_MASK);
	usleep_range(2000, 2500);
	I915_WRITE_BITS(MIPI_DEVICE_READY(pipe), 0x00,
			DEVICE_READY | ULPS_STATE_MASK);
	usleep_range(2000, 2500);
	I915_WRITE_BITS(MIPI_DEVICE_READY(pipe), DEVICE_READY,
			DEVICE_READY | ULPS_STATE_MASK);
	usleep_range(2000, 2500);
}
void intel_dsi_device_ready(struct intel_encoder *encoder)
{
	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
	struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
	int pipe = intel_crtc->pipe;
	u32 tmp;
	int count = 1;

	DRM_DEBUG_KMS("\n");

	/* program rcomp for compliance
	 * reduce form 50 ohms to 45 ohms */
	intel_flisdsi_write32(dev_priv, 0x04, 0x0004);

	band_gap_reset(dev_priv);

#ifdef CONFIG_CRYSTAL_COVE
	if (BYT_CR_CONFIG) {
		/*  cabc disable */
		vlv_gpio_nc_write(dev_priv, GPIO_NC_9_PCONF0, 0x2000CC00);
		vlv_gpio_nc_write(dev_priv, GPIO_NC_9_PAD, 0x00000004);

		/* panel enable */
		vlv_gpio_nc_write(dev_priv, GPIO_NC_11_PCONF0, 0x2000CC00);
		vlv_gpio_nc_write(dev_priv, GPIO_NC_11_PAD, 0x00000005);
		udelay(500);
	} else
		intel_mid_pmic_writeb(PMIC_PANEL_EN, 0x01);
#else
	/* need to code for BYT-CR for example where things have changed */
	DRM_ERROR("PANEL Enable to supported yet\n");
#endif
	msleep(intel_dsi->panel_on_delay);

	if (intel_dsi->dev.dev_ops->panel_reset)
		intel_dsi->dev.dev_ops->panel_reset(&intel_dsi->dev);

	/* Disable DPOunit clock gating, can stall pipe */
	tmp = I915_READ(DPLL(pipe));
	tmp |= DPLL_RESERVED_BIT;
	I915_WRITE(DPLL(pipe), tmp);

	tmp = I915_READ(DSPCLK_GATE_D);
	tmp |= VSUNIT_CLOCK_GATE_DISABLE;
	I915_WRITE(DSPCLK_GATE_D, tmp);

	intel_enable_dsi_pll(intel_dsi);
	if (intel_dsi->operation_mode == DSI_VIDEO_MODE) {

		I915_WRITE_BITS(MIPI_PORT_CTRL(pipe), LP_OUTPUT_HOLD,
							LP_OUTPUT_HOLD);

		usleep_range(1000, 1500);

		if (intel_dsi->dual_link)
			count = 2;
		do {

			I915_WRITE_BITS(MIPI_DEVICE_READY(pipe), DEVICE_READY |
					ULPS_STATE_EXIT, DEVICE_READY |
					ULPS_STATE_MASK);

			usleep_range(2000, 2500);
			I915_WRITE_BITS(MIPI_DEVICE_READY(pipe), DEVICE_READY,
					DEVICE_READY | ULPS_STATE_MASK);
			usleep_range(2000, 2500);
			I915_WRITE_BITS(MIPI_DEVICE_READY(pipe), 0x00,
					DEVICE_READY | ULPS_STATE_MASK);
			usleep_range(2000, 2500);
			I915_WRITE_BITS(MIPI_DEVICE_READY(pipe), DEVICE_READY,
					DEVICE_READY | ULPS_STATE_MASK);
			usleep_range(2000, 2500);
			/* For Port C for dual link */
			pipe = PIPE_B;
		} while (--count > 0);
	}
}