Commit 24ee0e64 authored by Gaurav K Singh's avatar Gaurav K Singh Committed by Daniel Vetter
Browse files

drm/i915: Update the DSI enable path to support dual



We need to program both port registers during dual link enable path.

v2: Address review comments by Jani
    - Used a for loop instead of do-while loop.

v3: Used for_each_dsi_port macro instead of for loop

v4: Renamed mode_hactive variable to mode_hdisplay

Signed-off-by: default avatarGaurav K Singh <gaurav.k.singh@intel.com>
Signed-off-by: default avatarShobhit Kumar <shobhit.kumar@intel.com>
Reviewed-by: default avatarJani Nikula <jani.nikula@intel.com>
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
parent 384f02a2
Loading
Loading
Loading
Loading
+131 −110
Original line number Original line Diff line number Diff line
@@ -156,8 +156,8 @@ static void intel_dsi_port_disable(struct intel_encoder *encoder)
static void intel_dsi_device_ready(struct intel_encoder *encoder)
static void intel_dsi_device_ready(struct intel_encoder *encoder)
{
{
	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
	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);
	enum port port = intel_dsi_pipe_to_port(intel_crtc->pipe);
	enum port port;
	u32 val;
	u32 val;


	DRM_DEBUG_KMS("\n");
	DRM_DEBUG_KMS("\n");
@@ -171,6 +171,8 @@ static void intel_dsi_device_ready(struct intel_encoder *encoder)
	/* bandgap reset is needed after everytime we do power gate */
	/* bandgap reset is needed after everytime we do power gate */
	band_gap_reset(dev_priv);
	band_gap_reset(dev_priv);


	for_each_dsi_port(port, intel_dsi->ports) {

		I915_WRITE(MIPI_DEVICE_READY(port), ULPS_STATE_ENTER);
		I915_WRITE(MIPI_DEVICE_READY(port), ULPS_STATE_ENTER);
		usleep_range(2500, 3000);
		usleep_range(2500, 3000);


@@ -184,6 +186,7 @@ static void intel_dsi_device_ready(struct intel_encoder *encoder)
		I915_WRITE(MIPI_DEVICE_READY(port), DEVICE_READY);
		I915_WRITE(MIPI_DEVICE_READY(port), DEVICE_READY);
		usleep_range(2500, 3000);
		usleep_range(2500, 3000);
	}
	}
}


static void intel_dsi_enable(struct intel_encoder *encoder)
static void intel_dsi_enable(struct intel_encoder *encoder)
{
{
@@ -547,14 +550,24 @@ static void intel_dsi_prepare(struct intel_encoder *intel_encoder)
	struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
	struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
	struct drm_display_mode *adjusted_mode =
	struct drm_display_mode *adjusted_mode =
		&intel_crtc->config.adjusted_mode;
		&intel_crtc->config.adjusted_mode;
	enum port port = intel_dsi_pipe_to_port(intel_crtc->pipe);
	enum port port;
	unsigned int bpp = intel_crtc->config.pipe_bpp;
	unsigned int bpp = intel_crtc->config.pipe_bpp;
	u32 val, tmp;
	u32 val, tmp;
	u16 mode_hdisplay;


	DRM_DEBUG_KMS("pipe %c\n", pipe_name(intel_crtc->pipe));
	DRM_DEBUG_KMS("pipe %c\n", pipe_name(intel_crtc->pipe));


	/* escape clock divider, 20MHz, shared for A and C. device ready must be
	mode_hdisplay = adjusted_mode->hdisplay;
	 * off when doing this! txclkesc? */

	if (intel_dsi->dual_link) {
		mode_hdisplay /= 2;
		if (intel_dsi->dual_link == DSI_DUAL_LINK_FRONT_BACK)
			mode_hdisplay += intel_dsi->pixel_overlap;
	}

	for_each_dsi_port(port, intel_dsi->ports) {
		/* escape clock divider, 20MHz, shared for A and C.
		 * device ready must be off when doing this! txclkesc? */
		tmp = I915_READ(MIPI_CTRL(PORT_A));
		tmp = I915_READ(MIPI_CTRL(PORT_A));
		tmp &= ~ESCAPE_CLOCK_DIVIDER_MASK;
		tmp &= ~ESCAPE_CLOCK_DIVIDER_MASK;
		I915_WRITE(MIPI_CTRL(PORT_A), tmp | ESCAPE_CLOCK_DIVIDER_1);
		I915_WRITE(MIPI_CTRL(PORT_A), tmp | ESCAPE_CLOCK_DIVIDER_1);
@@ -572,7 +585,8 @@ static void intel_dsi_prepare(struct intel_encoder *intel_encoder)


		I915_WRITE(MIPI_DPI_RESOLUTION(port),
		I915_WRITE(MIPI_DPI_RESOLUTION(port),
			adjusted_mode->vdisplay << VERTICAL_ADDRESS_SHIFT |
			adjusted_mode->vdisplay << VERTICAL_ADDRESS_SHIFT |
		   adjusted_mode->hdisplay << HORIZONTAL_ADDRESS_SHIFT);
			mode_hdisplay << HORIZONTAL_ADDRESS_SHIFT);
	}


	set_dsi_timings(encoder, adjusted_mode);
	set_dsi_timings(encoder, adjusted_mode);


@@ -586,23 +600,31 @@ static void intel_dsi_prepare(struct intel_encoder *intel_encoder)
		/* XXX: cross-check bpp vs. pixel format? */
		/* XXX: cross-check bpp vs. pixel format? */
		val |= intel_dsi->pixel_format;
		val |= intel_dsi->pixel_format;
	}
	}

	tmp = 0;
	if (intel_dsi->eotp_pkt == 0)
		tmp |= EOT_DISABLE;
	if (intel_dsi->clock_stop)
		tmp |= CLOCKSTOP;

	for_each_dsi_port(port, intel_dsi->ports) {
		I915_WRITE(MIPI_DSI_FUNC_PRG(port), val);
		I915_WRITE(MIPI_DSI_FUNC_PRG(port), val);


	/* timeouts for recovery. one frame IIUC. if counter expires, EOT and
		/* timeouts for recovery. one frame IIUC. if counter expires,
	 * stop state. */
		 * EOT and stop state. */


		/*
		/*
	 * In burst mode, value greater than one DPI line Time in byte clock
		 * In burst mode, value greater than one DPI line Time in byte
	 * (txbyteclkhs) To timeout this timer 1+ of the above said value is
		 * clock (txbyteclkhs) To timeout this timer 1+ of the above
	 * recommended.
		 * said value is recommended.
		 *
		 *
	 * In non-burst mode, Value greater than one DPI frame time in byte
		 * In non-burst mode, Value greater than one DPI frame time in
	 * clock(txbyteclkhs) To timeout this timer 1+ of the above said value
		 * byte clock(txbyteclkhs) To timeout this timer 1+ of the above
	 * is recommended.
		 * said value is recommended.
		 *
		 *
	 * In DBI only mode, value greater than one DBI frame time in byte
		 * In DBI only mode, value greater than one DBI frame time in
	 * clock(txbyteclkhs) To timeout this timer 1+ of the above said value
		 * byte clock(txbyteclkhs) To timeout this timer 1+ of the above
	 * is recommended.
		 * said value is recommended.
		 */
		 */


		if (is_vid_mode(intel_dsi) &&
		if (is_vid_mode(intel_dsi) &&
@@ -619,20 +641,17 @@ static void intel_dsi_prepare(struct intel_encoder *intel_encoder)
					intel_dsi->burst_mode_ratio) + 1);
					intel_dsi->burst_mode_ratio) + 1);
		}
		}
		I915_WRITE(MIPI_LP_RX_TIMEOUT(port), intel_dsi->lp_rx_timeout);
		I915_WRITE(MIPI_LP_RX_TIMEOUT(port), intel_dsi->lp_rx_timeout);
	I915_WRITE(MIPI_TURN_AROUND_TIMEOUT(port), intel_dsi->turn_arnd_val);
		I915_WRITE(MIPI_TURN_AROUND_TIMEOUT(port),
	I915_WRITE(MIPI_DEVICE_RESET_TIMER(port), intel_dsi->rst_timer_val);
						intel_dsi->turn_arnd_val);
		I915_WRITE(MIPI_DEVICE_RESET_TIMER(port),
						intel_dsi->rst_timer_val);


		/* dphy stuff */
		/* dphy stuff */


		/* in terms of low power clock */
		/* in terms of low power clock */
	I915_WRITE(MIPI_INIT_COUNT(port), txclkesc(intel_dsi->escape_clk_div, 100));
		I915_WRITE(MIPI_INIT_COUNT(port),

				txclkesc(intel_dsi->escape_clk_div, 100));
	val = 0;
	if (intel_dsi->eotp_pkt == 0)
		val |= EOT_DISABLE;


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


		/* recovery disables */
		/* recovery disables */
		I915_WRITE(MIPI_EOT_DISABLE(port), val);
		I915_WRITE(MIPI_EOT_DISABLE(port), val);
@@ -648,18 +667,19 @@ static void intel_dsi_prepare(struct intel_encoder *intel_encoder)
		I915_WRITE(MIPI_HIGH_LOW_SWITCH_COUNT(port),
		I915_WRITE(MIPI_HIGH_LOW_SWITCH_COUNT(port),
						intel_dsi->hs_to_lp_count);
						intel_dsi->hs_to_lp_count);


	/* XXX: low power clock equivalence in terms of byte clock. the number
		/* XXX: low power clock equivalence in terms of byte clock.
	 * of byte clocks occupied in one low power clock. based on txbyteclkhs
		 * the number of byte clocks occupied in one low power clock.
	 * and txclkesc. txclkesc time / txbyteclk time * (105 +
		 * based on txbyteclkhs and txclkesc.
	 * MIPI_STOP_STATE_STALL) / 105.???
		 * txclkesc time / txbyteclk time * (105 + MIPI_STOP_STATE_STALL
		 * ) / 105.???
		 */
		 */
		I915_WRITE(MIPI_LP_BYTECLK(port), intel_dsi->lp_byte_clk);
		I915_WRITE(MIPI_LP_BYTECLK(port), intel_dsi->lp_byte_clk);


	/* the bw essential for transmitting 16 long packets containing 252
		/* the bw essential for transmitting 16 long packets containing
	 * bytes meant for dcs write memory command is programmed in this
		 * 252 bytes meant for dcs write memory command is programmed in
	 * register in terms of byte clocks. based on dsi transfer rate and the
		 * this register in terms of byte clocks. based on dsi transfer
	 * number of lanes configured the time taken to transmit 16 long packets
		 * rate and the number of lanes configured the time taken to
	 * in a dsi stream varies. */
		 * transmit 16 long packets in a dsi stream varies. */
		I915_WRITE(MIPI_DBI_BW_CTRL(port), intel_dsi->bw_timer);
		I915_WRITE(MIPI_DBI_BW_CTRL(port), intel_dsi->bw_timer);


		I915_WRITE(MIPI_CLK_LANE_SWITCH_TIME_CNT(port),
		I915_WRITE(MIPI_CLK_LANE_SWITCH_TIME_CNT(port),
@@ -667,15 +687,16 @@ static void intel_dsi_prepare(struct intel_encoder *intel_encoder)
		intel_dsi->clk_hs_to_lp_count << HS_LP_PWR_SW_CNT_SHIFT);
		intel_dsi->clk_hs_to_lp_count << HS_LP_PWR_SW_CNT_SHIFT);


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


static void intel_dsi_pre_pll_enable(struct intel_encoder *encoder)
static void intel_dsi_pre_pll_enable(struct intel_encoder *encoder)
{
{