xref: /linux/drivers/gpu/drm/i915/display/icl_dsi.c (revision 3a39d672e7f48b8d6b91a09afa4b55352773b4b5)
1379bc100SJani Nikula /*
2379bc100SJani Nikula  * Copyright © 2018 Intel Corporation
3379bc100SJani Nikula  *
4379bc100SJani Nikula  * Permission is hereby granted, free of charge, to any person obtaining a
5379bc100SJani Nikula  * copy of this software and associated documentation files (the "Software"),
6379bc100SJani Nikula  * to deal in the Software without restriction, including without limitation
7379bc100SJani Nikula  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8379bc100SJani Nikula  * and/or sell copies of the Software, and to permit persons to whom the
9379bc100SJani Nikula  * Software is furnished to do so, subject to the following conditions:
10379bc100SJani Nikula  *
11379bc100SJani Nikula  * The above copyright notice and this permission notice (including the next
12379bc100SJani Nikula  * paragraph) shall be included in all copies or substantial portions of the
13379bc100SJani Nikula  * Software.
14379bc100SJani Nikula  *
15379bc100SJani Nikula  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16379bc100SJani Nikula  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17379bc100SJani Nikula  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18379bc100SJani Nikula  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19379bc100SJani Nikula  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20379bc100SJani Nikula  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21379bc100SJani Nikula  * DEALINGS IN THE SOFTWARE.
22379bc100SJani Nikula  *
23379bc100SJani Nikula  * Authors:
24379bc100SJani Nikula  *   Madhav Chauhan <madhav.chauhan@intel.com>
25379bc100SJani Nikula  *   Jani Nikula <jani.nikula@intel.com>
26379bc100SJani Nikula  */
27379bc100SJani Nikula 
282a64b147SThomas Zimmermann #include <drm/display/drm_dsc_helper.h>
29379bc100SJani Nikula #include <drm/drm_atomic_helper.h>
308466a141SImre Deak #include <drm/drm_fixed.h>
31379bc100SJani Nikula #include <drm/drm_mipi_dsi.h>
32379bc100SJani Nikula 
33801543b2SJani Nikula #include "i915_reg.h"
34617ed6c2SJani Nikula #include "icl_dsi.h"
353c0deb14SJani Nikula #include "icl_dsi_regs.h"
36379bc100SJani Nikula #include "intel_atomic.h"
376cc42fbeSJani Nikula #include "intel_backlight.h"
38a9b4c16dSJani Nikula #include "intel_backlight_regs.h"
39379bc100SJani Nikula #include "intel_combo_phy.h"
40d0864ee4SMatt Roper #include "intel_combo_phy_regs.h"
41379bc100SJani Nikula #include "intel_connector.h"
427c53e628SJani Nikula #include "intel_crtc.h"
43379bc100SJani Nikula #include "intel_ddi.h"
447785ae0bSVille Syrjälä #include "intel_de.h"
45379bc100SJani Nikula #include "intel_dsi.h"
46aebdd742SJani Nikula #include "intel_dsi_vbt.h"
47379bc100SJani Nikula #include "intel_panel.h"
482b68392eSJani Nikula #include "intel_vdsc.h"
49c3f05948SJani Nikula #include "intel_vdsc_regs.h"
50714b1cdbSDave Airlie #include "skl_scaler.h"
5146d12f91SDave Airlie #include "skl_universal_plane.h"
52379bc100SJani Nikula 
header_credits_available(struct drm_i915_private * dev_priv,enum transcoder dsi_trans)5381b55ef1SJani Nikula static int header_credits_available(struct drm_i915_private *dev_priv,
54379bc100SJani Nikula 				    enum transcoder dsi_trans)
55379bc100SJani Nikula {
561c63f6dfSJani Nikula 	return (intel_de_read(dev_priv, DSI_CMD_TXCTL(dsi_trans)) & FREE_HEADER_CREDIT_MASK)
57379bc100SJani Nikula 		>> FREE_HEADER_CREDIT_SHIFT;
58379bc100SJani Nikula }
59379bc100SJani Nikula 
payload_credits_available(struct drm_i915_private * dev_priv,enum transcoder dsi_trans)6081b55ef1SJani Nikula static int payload_credits_available(struct drm_i915_private *dev_priv,
61379bc100SJani Nikula 				     enum transcoder dsi_trans)
62379bc100SJani Nikula {
631c63f6dfSJani Nikula 	return (intel_de_read(dev_priv, DSI_CMD_TXCTL(dsi_trans)) & FREE_PLOAD_CREDIT_MASK)
64379bc100SJani Nikula 		>> FREE_PLOAD_CREDIT_SHIFT;
65379bc100SJani Nikula }
66379bc100SJani Nikula 
wait_for_header_credits(struct drm_i915_private * dev_priv,enum transcoder dsi_trans,int hdr_credit)6743315f86SLee Shawn C static bool wait_for_header_credits(struct drm_i915_private *dev_priv,
6843315f86SLee Shawn C 				    enum transcoder dsi_trans, int hdr_credit)
69379bc100SJani Nikula {
70379bc100SJani Nikula 	if (wait_for_us(header_credits_available(dev_priv, dsi_trans) >=
7143315f86SLee Shawn C 			hdr_credit, 100)) {
72b5280cd0SWambui Karuga 		drm_err(&dev_priv->drm, "DSI header credits not released\n");
7343315f86SLee Shawn C 		return false;
74379bc100SJani Nikula 	}
75379bc100SJani Nikula 
7643315f86SLee Shawn C 	return true;
7743315f86SLee Shawn C }
7843315f86SLee Shawn C 
wait_for_payload_credits(struct drm_i915_private * dev_priv,enum transcoder dsi_trans,int payld_credit)7943315f86SLee Shawn C static bool wait_for_payload_credits(struct drm_i915_private *dev_priv,
8043315f86SLee Shawn C 				     enum transcoder dsi_trans, int payld_credit)
81379bc100SJani Nikula {
82379bc100SJani Nikula 	if (wait_for_us(payload_credits_available(dev_priv, dsi_trans) >=
8343315f86SLee Shawn C 			payld_credit, 100)) {
84b5280cd0SWambui Karuga 		drm_err(&dev_priv->drm, "DSI payload credits not released\n");
8543315f86SLee Shawn C 		return false;
8643315f86SLee Shawn C 	}
8743315f86SLee Shawn C 
8843315f86SLee Shawn C 	return true;
89379bc100SJani Nikula }
90379bc100SJani Nikula 
dsi_port_to_transcoder(enum port port)91379bc100SJani Nikula static enum transcoder dsi_port_to_transcoder(enum port port)
92379bc100SJani Nikula {
93379bc100SJani Nikula 	if (port == PORT_A)
94379bc100SJani Nikula 		return TRANSCODER_DSI_0;
95379bc100SJani Nikula 	else
96379bc100SJani Nikula 		return TRANSCODER_DSI_1;
97379bc100SJani Nikula }
98379bc100SJani Nikula 
wait_for_cmds_dispatched_to_panel(struct intel_encoder * encoder)99379bc100SJani Nikula static void wait_for_cmds_dispatched_to_panel(struct intel_encoder *encoder)
100379bc100SJani Nikula {
101379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
102b7d02c3aSVille Syrjälä 	struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
103379bc100SJani Nikula 	struct mipi_dsi_device *dsi;
104379bc100SJani Nikula 	enum port port;
105379bc100SJani Nikula 	enum transcoder dsi_trans;
106379bc100SJani Nikula 	int ret;
107379bc100SJani Nikula 
108379bc100SJani Nikula 	/* wait for header/payload credits to be released */
109379bc100SJani Nikula 	for_each_dsi_port(port, intel_dsi->ports) {
110379bc100SJani Nikula 		dsi_trans = dsi_port_to_transcoder(port);
11143315f86SLee Shawn C 		wait_for_header_credits(dev_priv, dsi_trans, MAX_HEADER_CREDIT);
11243315f86SLee Shawn C 		wait_for_payload_credits(dev_priv, dsi_trans, MAX_PLOAD_CREDIT);
113379bc100SJani Nikula 	}
114379bc100SJani Nikula 
115379bc100SJani Nikula 	/* send nop DCS command */
116379bc100SJani Nikula 	for_each_dsi_port(port, intel_dsi->ports) {
117379bc100SJani Nikula 		dsi = intel_dsi->dsi_hosts[port]->device;
118379bc100SJani Nikula 		dsi->mode_flags |= MIPI_DSI_MODE_LPM;
119379bc100SJani Nikula 		dsi->channel = 0;
120379bc100SJani Nikula 		ret = mipi_dsi_dcs_nop(dsi);
121379bc100SJani Nikula 		if (ret < 0)
122b5280cd0SWambui Karuga 			drm_err(&dev_priv->drm,
123b5280cd0SWambui Karuga 				"error sending DCS NOP command\n");
124379bc100SJani Nikula 	}
125379bc100SJani Nikula 
126379bc100SJani Nikula 	/* wait for header credits to be released */
127379bc100SJani Nikula 	for_each_dsi_port(port, intel_dsi->ports) {
128379bc100SJani Nikula 		dsi_trans = dsi_port_to_transcoder(port);
12943315f86SLee Shawn C 		wait_for_header_credits(dev_priv, dsi_trans, MAX_HEADER_CREDIT);
130379bc100SJani Nikula 	}
131379bc100SJani Nikula 
132379bc100SJani Nikula 	/* wait for LP TX in progress bit to be cleared */
133379bc100SJani Nikula 	for_each_dsi_port(port, intel_dsi->ports) {
134379bc100SJani Nikula 		dsi_trans = dsi_port_to_transcoder(port);
1351c63f6dfSJani Nikula 		if (wait_for_us(!(intel_de_read(dev_priv, DSI_LP_MSG(dsi_trans)) &
136379bc100SJani Nikula 				  LPTX_IN_PROGRESS), 20))
137b5280cd0SWambui Karuga 			drm_err(&dev_priv->drm, "LPTX bit not cleared\n");
138379bc100SJani Nikula 	}
139379bc100SJani Nikula }
140379bc100SJani Nikula 
dsi_send_pkt_payld(struct intel_dsi_host * host,const struct mipi_dsi_packet * packet)141207ea507SJani Nikula static int dsi_send_pkt_payld(struct intel_dsi_host *host,
142207ea507SJani Nikula 			      const struct mipi_dsi_packet *packet)
143379bc100SJani Nikula {
144379bc100SJani Nikula 	struct intel_dsi *intel_dsi = host->intel_dsi;
145207ea507SJani Nikula 	struct drm_i915_private *i915 = to_i915(intel_dsi->base.base.dev);
146379bc100SJani Nikula 	enum transcoder dsi_trans = dsi_port_to_transcoder(host->port);
147207ea507SJani Nikula 	const u8 *data = packet->payload;
148207ea507SJani Nikula 	u32 len = packet->payload_length;
149379bc100SJani Nikula 	int i, j;
150379bc100SJani Nikula 
151207ea507SJani Nikula 	/* payload queue can accept *256 bytes*, check limit */
152207ea507SJani Nikula 	if (len > MAX_PLOAD_CREDIT * 4) {
153207ea507SJani Nikula 		drm_err(&i915->drm, "payload size exceeds max queue limit\n");
154207ea507SJani Nikula 		return -EINVAL;
155207ea507SJani Nikula 	}
156207ea507SJani Nikula 
157379bc100SJani Nikula 	for (i = 0; i < len; i += 4) {
158379bc100SJani Nikula 		u32 tmp = 0;
159379bc100SJani Nikula 
160207ea507SJani Nikula 		if (!wait_for_payload_credits(i915, dsi_trans, 1))
161207ea507SJani Nikula 			return -EBUSY;
162379bc100SJani Nikula 
163379bc100SJani Nikula 		for (j = 0; j < min_t(u32, len - i, 4); j++)
164379bc100SJani Nikula 			tmp |= *data++ << 8 * j;
165379bc100SJani Nikula 
166207ea507SJani Nikula 		intel_de_write(i915, DSI_CMD_TXPYLD(dsi_trans), tmp);
167379bc100SJani Nikula 	}
168379bc100SJani Nikula 
169207ea507SJani Nikula 	return 0;
170379bc100SJani Nikula }
171379bc100SJani Nikula 
dsi_send_pkt_hdr(struct intel_dsi_host * host,const struct mipi_dsi_packet * packet,bool enable_lpdt)172379bc100SJani Nikula static int dsi_send_pkt_hdr(struct intel_dsi_host *host,
1733e2947cdSJani Nikula 			    const struct mipi_dsi_packet *packet,
1743e2947cdSJani Nikula 			    bool enable_lpdt)
175379bc100SJani Nikula {
176379bc100SJani Nikula 	struct intel_dsi *intel_dsi = host->intel_dsi;
177379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(intel_dsi->base.base.dev);
178379bc100SJani Nikula 	enum transcoder dsi_trans = dsi_port_to_transcoder(host->port);
179379bc100SJani Nikula 	u32 tmp;
180379bc100SJani Nikula 
18143315f86SLee Shawn C 	if (!wait_for_header_credits(dev_priv, dsi_trans, 1))
182b90acd09SJani Nikula 		return -EBUSY;
183379bc100SJani Nikula 
1841c63f6dfSJani Nikula 	tmp = intel_de_read(dev_priv, DSI_CMD_TXHDR(dsi_trans));
185379bc100SJani Nikula 
1863e2947cdSJani Nikula 	if (packet->payload)
187379bc100SJani Nikula 		tmp |= PAYLOAD_PRESENT;
188379bc100SJani Nikula 	else
189379bc100SJani Nikula 		tmp &= ~PAYLOAD_PRESENT;
190379bc100SJani Nikula 
191379bc100SJani Nikula 	tmp &= ~VBLANK_FENCE;
192379bc100SJani Nikula 
193379bc100SJani Nikula 	if (enable_lpdt)
194379bc100SJani Nikula 		tmp |= LP_DATA_TRANSFER;
19538a1b50cSWilliam Tseng 	else
19638a1b50cSWilliam Tseng 		tmp &= ~LP_DATA_TRANSFER;
197379bc100SJani Nikula 
198379bc100SJani Nikula 	tmp &= ~(PARAM_WC_MASK | VC_MASK | DT_MASK);
1993e2947cdSJani Nikula 	tmp |= ((packet->header[0] & VC_MASK) << VC_SHIFT);
2003e2947cdSJani Nikula 	tmp |= ((packet->header[0] & DT_MASK) << DT_SHIFT);
2013e2947cdSJani Nikula 	tmp |= (packet->header[1] << PARAM_WC_LOWER_SHIFT);
2023e2947cdSJani Nikula 	tmp |= (packet->header[2] << PARAM_WC_UPPER_SHIFT);
2031c63f6dfSJani Nikula 	intel_de_write(dev_priv, DSI_CMD_TXHDR(dsi_trans), tmp);
204379bc100SJani Nikula 
205379bc100SJani Nikula 	return 0;
206379bc100SJani Nikula }
207379bc100SJani Nikula 
icl_dsi_frame_update(struct intel_crtc_state * crtc_state)20826fb0d55SVandita Kulkarni void icl_dsi_frame_update(struct intel_crtc_state *crtc_state)
20926fb0d55SVandita Kulkarni {
21026fb0d55SVandita Kulkarni 	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
21126fb0d55SVandita Kulkarni 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
2121a45d681SAndrzej Hajda 	u32 mode_flags;
21326fb0d55SVandita Kulkarni 	enum port port;
21426fb0d55SVandita Kulkarni 
21526fb0d55SVandita Kulkarni 	mode_flags = crtc_state->mode_flags;
21626fb0d55SVandita Kulkarni 
21726fb0d55SVandita Kulkarni 	/*
21826fb0d55SVandita Kulkarni 	 * case 1 also covers dual link
21926fb0d55SVandita Kulkarni 	 * In case of dual link, frame update should be set on
22026fb0d55SVandita Kulkarni 	 * DSI_0
22126fb0d55SVandita Kulkarni 	 */
22226fb0d55SVandita Kulkarni 	if (mode_flags & I915_MODE_FLAG_DSI_USE_TE0)
22326fb0d55SVandita Kulkarni 		port = PORT_A;
22426fb0d55SVandita Kulkarni 	else if (mode_flags & I915_MODE_FLAG_DSI_USE_TE1)
22526fb0d55SVandita Kulkarni 		port = PORT_B;
22626fb0d55SVandita Kulkarni 	else
22726fb0d55SVandita Kulkarni 		return;
22826fb0d55SVandita Kulkarni 
2291a45d681SAndrzej Hajda 	intel_de_rmw(dev_priv, DSI_CMD_FRMCTL(port), 0, DSI_FRAME_UPDATE_REQUEST);
23026fb0d55SVandita Kulkarni }
23126fb0d55SVandita Kulkarni 
dsi_program_swing_and_deemphasis(struct intel_encoder * encoder)232379bc100SJani Nikula static void dsi_program_swing_and_deemphasis(struct intel_encoder *encoder)
233379bc100SJani Nikula {
234379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
235b7d02c3aSVille Syrjälä 	struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
236dc867bc7SMatt Roper 	enum phy phy;
2371a45d681SAndrzej Hajda 	u32 tmp, mask, val;
238379bc100SJani Nikula 	int lane;
239379bc100SJani Nikula 
240dc867bc7SMatt Roper 	for_each_dsi_phy(phy, intel_dsi->phys) {
241379bc100SJani Nikula 		/*
242379bc100SJani Nikula 		 * Program voltage swing and pre-emphasis level values as per
243379bc100SJani Nikula 		 * table in BSPEC under DDI buffer programing
244379bc100SJani Nikula 		 */
2451a45d681SAndrzej Hajda 		mask = SCALING_MODE_SEL_MASK | RTERM_SELECT_MASK;
2461a45d681SAndrzej Hajda 		val = SCALING_MODE_SEL(0x2) | TAP2_DISABLE | TAP3_DISABLE |
2471a45d681SAndrzej Hajda 		      RTERM_SELECT(0x6);
248e6908588SVille Syrjälä 		tmp = intel_de_read(dev_priv, ICL_PORT_TX_DW5_LN(0, phy));
2491a45d681SAndrzej Hajda 		tmp &= ~mask;
2501a45d681SAndrzej Hajda 		tmp |= val;
2511c63f6dfSJani Nikula 		intel_de_write(dev_priv, ICL_PORT_TX_DW5_GRP(phy), tmp);
2521a45d681SAndrzej Hajda 		intel_de_rmw(dev_priv, ICL_PORT_TX_DW5_AUX(phy), mask, val);
253379bc100SJani Nikula 
2541a45d681SAndrzej Hajda 		mask = SWING_SEL_LOWER_MASK | SWING_SEL_UPPER_MASK |
2551a45d681SAndrzej Hajda 		       RCOMP_SCALAR_MASK;
2561a45d681SAndrzej Hajda 		val = SWING_SEL_UPPER(0x2) | SWING_SEL_LOWER(0x2) |
2571a45d681SAndrzej Hajda 		      RCOMP_SCALAR(0x98);
258e6908588SVille Syrjälä 		tmp = intel_de_read(dev_priv, ICL_PORT_TX_DW2_LN(0, phy));
2591a45d681SAndrzej Hajda 		tmp &= ~mask;
2601a45d681SAndrzej Hajda 		tmp |= val;
2611c63f6dfSJani Nikula 		intel_de_write(dev_priv, ICL_PORT_TX_DW2_GRP(phy), tmp);
2621a45d681SAndrzej Hajda 		intel_de_rmw(dev_priv, ICL_PORT_TX_DW2_AUX(phy), mask, val);
263379bc100SJani Nikula 
2641a45d681SAndrzej Hajda 		mask = POST_CURSOR_1_MASK | POST_CURSOR_2_MASK |
2651a45d681SAndrzej Hajda 		       CURSOR_COEFF_MASK;
2661a45d681SAndrzej Hajda 		val = POST_CURSOR_1(0x0) | POST_CURSOR_2(0x0) |
2671a45d681SAndrzej Hajda 		      CURSOR_COEFF(0x3f);
2681a45d681SAndrzej Hajda 		intel_de_rmw(dev_priv, ICL_PORT_TX_DW4_AUX(phy), mask, val);
269379bc100SJani Nikula 
270379bc100SJani Nikula 		/* Bspec: must not use GRP register for write */
2711a45d681SAndrzej Hajda 		for (lane = 0; lane <= 3; lane++)
2721a45d681SAndrzej Hajda 			intel_de_rmw(dev_priv, ICL_PORT_TX_DW4_LN(lane, phy),
2731a45d681SAndrzej Hajda 				     mask, val);
274379bc100SJani Nikula 	}
275379bc100SJani Nikula }
276379bc100SJani Nikula 
configure_dual_link_mode(struct intel_encoder * encoder,const struct intel_crtc_state * pipe_config)277379bc100SJani Nikula static void configure_dual_link_mode(struct intel_encoder *encoder,
278379bc100SJani Nikula 				     const struct intel_crtc_state *pipe_config)
279379bc100SJani Nikula {
280379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
281b7d02c3aSVille Syrjälä 	struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
2821a62dd98SJani Nikula 	i915_reg_t dss_ctl1_reg, dss_ctl2_reg;
283379bc100SJani Nikula 	u32 dss_ctl1;
284379bc100SJani Nikula 
2851a62dd98SJani Nikula 	/* FIXME: Move all DSS handling to intel_vdsc.c */
2861a62dd98SJani Nikula 	if (DISPLAY_VER(dev_priv) >= 12) {
2871a62dd98SJani Nikula 		struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);
2881a62dd98SJani Nikula 
2891a62dd98SJani Nikula 		dss_ctl1_reg = ICL_PIPE_DSS_CTL1(crtc->pipe);
2901a62dd98SJani Nikula 		dss_ctl2_reg = ICL_PIPE_DSS_CTL2(crtc->pipe);
2911a62dd98SJani Nikula 	} else {
2921a62dd98SJani Nikula 		dss_ctl1_reg = DSS_CTL1;
2931a62dd98SJani Nikula 		dss_ctl2_reg = DSS_CTL2;
2941a62dd98SJani Nikula 	}
2951a62dd98SJani Nikula 
2961a62dd98SJani Nikula 	dss_ctl1 = intel_de_read(dev_priv, dss_ctl1_reg);
297379bc100SJani Nikula 	dss_ctl1 |= SPLITTER_ENABLE;
298379bc100SJani Nikula 	dss_ctl1 &= ~OVERLAP_PIXELS_MASK;
299379bc100SJani Nikula 	dss_ctl1 |= OVERLAP_PIXELS(intel_dsi->pixel_overlap);
300379bc100SJani Nikula 
301379bc100SJani Nikula 	if (intel_dsi->dual_link == DSI_DUAL_LINK_FRONT_BACK) {
302379bc100SJani Nikula 		const struct drm_display_mode *adjusted_mode =
3031326a92cSMaarten Lankhorst 					&pipe_config->hw.adjusted_mode;
304379bc100SJani Nikula 		u16 hactive = adjusted_mode->crtc_hdisplay;
305379bc100SJani Nikula 		u16 dl_buffer_depth;
306379bc100SJani Nikula 
307379bc100SJani Nikula 		dss_ctl1 &= ~DUAL_LINK_MODE_INTERLEAVE;
308379bc100SJani Nikula 		dl_buffer_depth = hactive / 2 + intel_dsi->pixel_overlap;
309379bc100SJani Nikula 
310379bc100SJani Nikula 		if (dl_buffer_depth > MAX_DL_BUFFER_TARGET_DEPTH)
311b5280cd0SWambui Karuga 			drm_err(&dev_priv->drm,
312b5280cd0SWambui Karuga 				"DL buffer depth exceed max value\n");
313379bc100SJani Nikula 
314379bc100SJani Nikula 		dss_ctl1 &= ~LEFT_DL_BUF_TARGET_DEPTH_MASK;
315379bc100SJani Nikula 		dss_ctl1 |= LEFT_DL_BUF_TARGET_DEPTH(dl_buffer_depth);
3161a62dd98SJani Nikula 		intel_de_rmw(dev_priv, dss_ctl2_reg, RIGHT_DL_BUF_TARGET_DEPTH_MASK,
3171a45d681SAndrzej Hajda 			     RIGHT_DL_BUF_TARGET_DEPTH(dl_buffer_depth));
318379bc100SJani Nikula 	} else {
319379bc100SJani Nikula 		/* Interleave */
320379bc100SJani Nikula 		dss_ctl1 |= DUAL_LINK_MODE_INTERLEAVE;
321379bc100SJani Nikula 	}
322379bc100SJani Nikula 
3231a62dd98SJani Nikula 	intel_de_write(dev_priv, dss_ctl1_reg, dss_ctl1);
324379bc100SJani Nikula }
325379bc100SJani Nikula 
32654ed6902SJani Nikula /* aka DSI 8X clock */
afe_clk(struct intel_encoder * encoder,const struct intel_crtc_state * crtc_state)32704865139SJani Nikula static int afe_clk(struct intel_encoder *encoder,
32804865139SJani Nikula 		   const struct intel_crtc_state *crtc_state)
32954ed6902SJani Nikula {
330b7d02c3aSVille Syrjälä 	struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
33154ed6902SJani Nikula 	int bpp;
33254ed6902SJani Nikula 
33304865139SJani Nikula 	if (crtc_state->dsc.compression_enable)
3348466a141SImre Deak 		bpp = fxp_q4_to_int(crtc_state->dsc.compressed_bpp_x16);
33504865139SJani Nikula 	else
33654ed6902SJani Nikula 		bpp = mipi_dsi_pixel_format_to_bpp(intel_dsi->pixel_format);
33754ed6902SJani Nikula 
33854ed6902SJani Nikula 	return DIV_ROUND_CLOSEST(intel_dsi->pclk * bpp, intel_dsi->lane_count);
33954ed6902SJani Nikula }
34054ed6902SJani Nikula 
gen11_dsi_program_esc_clk_div(struct intel_encoder * encoder,const struct intel_crtc_state * crtc_state)34104865139SJani Nikula static void gen11_dsi_program_esc_clk_div(struct intel_encoder *encoder,
34204865139SJani Nikula 					  const struct intel_crtc_state *crtc_state)
343379bc100SJani Nikula {
344379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
345b7d02c3aSVille Syrjälä 	struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
346379bc100SJani Nikula 	enum port port;
34754ed6902SJani Nikula 	int afe_clk_khz;
348510b2814SMika Kahola 	int theo_word_clk, act_word_clk;
349510b2814SMika Kahola 	u32 esc_clk_div_m, esc_clk_div_m_phy;
350379bc100SJani Nikula 
35104865139SJani Nikula 	afe_clk_khz = afe_clk(encoder, crtc_state);
352510b2814SMika Kahola 
353510b2814SMika Kahola 	if (IS_ALDERLAKE_S(dev_priv) || IS_ALDERLAKE_P(dev_priv)) {
354510b2814SMika Kahola 		theo_word_clk = DIV_ROUND_UP(afe_clk_khz, 8 * DSI_MAX_ESC_CLK);
355510b2814SMika Kahola 		act_word_clk = max(3, theo_word_clk + (theo_word_clk + 1) % 2);
356510b2814SMika Kahola 		esc_clk_div_m = act_word_clk * 8;
357510b2814SMika Kahola 		esc_clk_div_m_phy = (act_word_clk - 1) / 2;
358510b2814SMika Kahola 	} else {
359379bc100SJani Nikula 		esc_clk_div_m = DIV_ROUND_UP(afe_clk_khz, DSI_MAX_ESC_CLK);
360510b2814SMika Kahola 	}
361379bc100SJani Nikula 
362379bc100SJani Nikula 	for_each_dsi_port(port, intel_dsi->ports) {
3631c63f6dfSJani Nikula 		intel_de_write(dev_priv, ICL_DSI_ESC_CLK_DIV(port),
364379bc100SJani Nikula 			       esc_clk_div_m & ICL_ESC_CLK_DIV_MASK);
3651c63f6dfSJani Nikula 		intel_de_posting_read(dev_priv, ICL_DSI_ESC_CLK_DIV(port));
366379bc100SJani Nikula 	}
367379bc100SJani Nikula 
368379bc100SJani Nikula 	for_each_dsi_port(port, intel_dsi->ports) {
3691c63f6dfSJani Nikula 		intel_de_write(dev_priv, ICL_DPHY_ESC_CLK_DIV(port),
370379bc100SJani Nikula 			       esc_clk_div_m & ICL_ESC_CLK_DIV_MASK);
3711c63f6dfSJani Nikula 		intel_de_posting_read(dev_priv, ICL_DPHY_ESC_CLK_DIV(port));
372379bc100SJani Nikula 	}
373510b2814SMika Kahola 
374510b2814SMika Kahola 	if (IS_ALDERLAKE_S(dev_priv) || IS_ALDERLAKE_P(dev_priv)) {
375510b2814SMika Kahola 		for_each_dsi_port(port, intel_dsi->ports) {
376510b2814SMika Kahola 			intel_de_write(dev_priv, ADL_MIPIO_DW(port, 8),
377510b2814SMika Kahola 				       esc_clk_div_m_phy & TX_ESC_CLK_DIV_PHY);
378510b2814SMika Kahola 			intel_de_posting_read(dev_priv, ADL_MIPIO_DW(port, 8));
379510b2814SMika Kahola 		}
380510b2814SMika Kahola 	}
381379bc100SJani Nikula }
382379bc100SJani Nikula 
get_dsi_io_power_domains(struct drm_i915_private * dev_priv,struct intel_dsi * intel_dsi)383379bc100SJani Nikula static void get_dsi_io_power_domains(struct drm_i915_private *dev_priv,
384379bc100SJani Nikula 				     struct intel_dsi *intel_dsi)
385379bc100SJani Nikula {
386379bc100SJani Nikula 	enum port port;
387379bc100SJani Nikula 
388379bc100SJani Nikula 	for_each_dsi_port(port, intel_dsi->ports) {
3893dbe5e11SPankaj Bharadiya 		drm_WARN_ON(&dev_priv->drm, intel_dsi->io_wakeref[port]);
390379bc100SJani Nikula 		intel_dsi->io_wakeref[port] =
391379bc100SJani Nikula 			intel_display_power_get(dev_priv,
392379bc100SJani Nikula 						port == PORT_A ?
3930ba2661dSImre Deak 						POWER_DOMAIN_PORT_DDI_IO_A :
3940ba2661dSImre Deak 						POWER_DOMAIN_PORT_DDI_IO_B);
395379bc100SJani Nikula 	}
396379bc100SJani Nikula }
397379bc100SJani Nikula 
gen11_dsi_enable_io_power(struct intel_encoder * encoder)398379bc100SJani Nikula static void gen11_dsi_enable_io_power(struct intel_encoder *encoder)
399379bc100SJani Nikula {
400379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
401b7d02c3aSVille Syrjälä 	struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
402379bc100SJani Nikula 	enum port port;
403379bc100SJani Nikula 
4041a45d681SAndrzej Hajda 	for_each_dsi_port(port, intel_dsi->ports)
4051a45d681SAndrzej Hajda 		intel_de_rmw(dev_priv, ICL_DSI_IO_MODECTL(port),
4061a45d681SAndrzej Hajda 			     0, COMBO_PHY_MODE_DSI);
407379bc100SJani Nikula 
408379bc100SJani Nikula 	get_dsi_io_power_domains(dev_priv, intel_dsi);
409379bc100SJani Nikula }
410379bc100SJani Nikula 
gen11_dsi_power_up_lanes(struct intel_encoder * encoder)411379bc100SJani Nikula static void gen11_dsi_power_up_lanes(struct intel_encoder *encoder)
412379bc100SJani Nikula {
413379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
414b7d02c3aSVille Syrjälä 	struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
415dc867bc7SMatt Roper 	enum phy phy;
416379bc100SJani Nikula 
417dc867bc7SMatt Roper 	for_each_dsi_phy(phy, intel_dsi->phys)
418dc867bc7SMatt Roper 		intel_combo_phy_power_up_lanes(dev_priv, phy, true,
419379bc100SJani Nikula 					       intel_dsi->lane_count, false);
420379bc100SJani Nikula }
421379bc100SJani Nikula 
gen11_dsi_config_phy_lanes_sequence(struct intel_encoder * encoder)422379bc100SJani Nikula static void gen11_dsi_config_phy_lanes_sequence(struct intel_encoder *encoder)
423379bc100SJani Nikula {
424379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
425b7d02c3aSVille Syrjälä 	struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
426dc867bc7SMatt Roper 	enum phy phy;
427379bc100SJani Nikula 	u32 tmp;
428379bc100SJani Nikula 	int lane;
429379bc100SJani Nikula 
430379bc100SJani Nikula 	/* Step 4b(i) set loadgen select for transmit and aux lanes */
431dc867bc7SMatt Roper 	for_each_dsi_phy(phy, intel_dsi->phys) {
4321a45d681SAndrzej Hajda 		intel_de_rmw(dev_priv, ICL_PORT_TX_DW4_AUX(phy), LOADGEN_SELECT, 0);
4331a45d681SAndrzej Hajda 		for (lane = 0; lane <= 3; lane++)
4341a45d681SAndrzej Hajda 			intel_de_rmw(dev_priv, ICL_PORT_TX_DW4_LN(lane, phy),
4351a45d681SAndrzej Hajda 				     LOADGEN_SELECT, lane != 2 ? LOADGEN_SELECT : 0);
436379bc100SJani Nikula 	}
437379bc100SJani Nikula 
438379bc100SJani Nikula 	/* Step 4b(ii) set latency optimization for transmit and aux lanes */
439dc867bc7SMatt Roper 	for_each_dsi_phy(phy, intel_dsi->phys) {
4401a45d681SAndrzej Hajda 		intel_de_rmw(dev_priv, ICL_PORT_TX_DW2_AUX(phy),
4411a45d681SAndrzej Hajda 			     FRC_LATENCY_OPTIM_MASK, FRC_LATENCY_OPTIM_VAL(0x5));
442e6908588SVille Syrjälä 		tmp = intel_de_read(dev_priv, ICL_PORT_TX_DW2_LN(0, phy));
443379bc100SJani Nikula 		tmp &= ~FRC_LATENCY_OPTIM_MASK;
444379bc100SJani Nikula 		tmp |= FRC_LATENCY_OPTIM_VAL(0x5);
4451c63f6dfSJani Nikula 		intel_de_write(dev_priv, ICL_PORT_TX_DW2_GRP(phy), tmp);
4466a7bafe8SVandita Kulkarni 
447960e9836SVandita Kulkarni 		/* For EHL, TGL, set latency optimization for PCS_DW1 lanes */
4480c65dc06SDnyaneshwar Bhadane 		if (IS_JASPERLAKE(dev_priv) || IS_ELKHARTLAKE(dev_priv) ||
4490c65dc06SDnyaneshwar Bhadane 		    (DISPLAY_VER(dev_priv) >= 12)) {
4501a45d681SAndrzej Hajda 			intel_de_rmw(dev_priv, ICL_PORT_PCS_DW1_AUX(phy),
4511a45d681SAndrzej Hajda 				     LATENCY_OPTIM_MASK, LATENCY_OPTIM_VAL(0));
4526a7bafe8SVandita Kulkarni 
4531c63f6dfSJani Nikula 			tmp = intel_de_read(dev_priv,
454e6908588SVille Syrjälä 					    ICL_PORT_PCS_DW1_LN(0, phy));
4556a7bafe8SVandita Kulkarni 			tmp &= ~LATENCY_OPTIM_MASK;
4566a7bafe8SVandita Kulkarni 			tmp |= LATENCY_OPTIM_VAL(0x1);
4571c63f6dfSJani Nikula 			intel_de_write(dev_priv, ICL_PORT_PCS_DW1_GRP(phy),
4581c63f6dfSJani Nikula 				       tmp);
4596a7bafe8SVandita Kulkarni 		}
460379bc100SJani Nikula 	}
461379bc100SJani Nikula 
462379bc100SJani Nikula }
463379bc100SJani Nikula 
gen11_dsi_voltage_swing_program_seq(struct intel_encoder * encoder)464379bc100SJani Nikula static void gen11_dsi_voltage_swing_program_seq(struct intel_encoder *encoder)
465379bc100SJani Nikula {
466379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
467b7d02c3aSVille Syrjälä 	struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
468379bc100SJani Nikula 	u32 tmp;
469dc867bc7SMatt Roper 	enum phy phy;
470379bc100SJani Nikula 
471379bc100SJani Nikula 	/* clear common keeper enable bit */
472dc867bc7SMatt Roper 	for_each_dsi_phy(phy, intel_dsi->phys) {
473e6908588SVille Syrjälä 		tmp = intel_de_read(dev_priv, ICL_PORT_PCS_DW1_LN(0, phy));
474379bc100SJani Nikula 		tmp &= ~COMMON_KEEPER_EN;
4751c63f6dfSJani Nikula 		intel_de_write(dev_priv, ICL_PORT_PCS_DW1_GRP(phy), tmp);
4761a45d681SAndrzej Hajda 		intel_de_rmw(dev_priv, ICL_PORT_PCS_DW1_AUX(phy), COMMON_KEEPER_EN, 0);
477379bc100SJani Nikula 	}
478379bc100SJani Nikula 
479379bc100SJani Nikula 	/*
480379bc100SJani Nikula 	 * Set SUS Clock Config bitfield to 11b
481379bc100SJani Nikula 	 * Note: loadgen select program is done
482379bc100SJani Nikula 	 * as part of lane phy sequence configuration
483379bc100SJani Nikula 	 */
4841a45d681SAndrzej Hajda 	for_each_dsi_phy(phy, intel_dsi->phys)
4851a45d681SAndrzej Hajda 		intel_de_rmw(dev_priv, ICL_PORT_CL_DW5(phy), 0, SUS_CLOCK_CONFIG);
486379bc100SJani Nikula 
487379bc100SJani Nikula 	/* Clear training enable to change swing values */
488dc867bc7SMatt Roper 	for_each_dsi_phy(phy, intel_dsi->phys) {
489e6908588SVille Syrjälä 		tmp = intel_de_read(dev_priv, ICL_PORT_TX_DW5_LN(0, phy));
490379bc100SJani Nikula 		tmp &= ~TX_TRAINING_EN;
4911c63f6dfSJani Nikula 		intel_de_write(dev_priv, ICL_PORT_TX_DW5_GRP(phy), tmp);
4921a45d681SAndrzej Hajda 		intel_de_rmw(dev_priv, ICL_PORT_TX_DW5_AUX(phy), TX_TRAINING_EN, 0);
493379bc100SJani Nikula 	}
494379bc100SJani Nikula 
495379bc100SJani Nikula 	/* Program swing and de-emphasis */
496379bc100SJani Nikula 	dsi_program_swing_and_deemphasis(encoder);
497379bc100SJani Nikula 
498379bc100SJani Nikula 	/* Set training enable to trigger update */
499dc867bc7SMatt Roper 	for_each_dsi_phy(phy, intel_dsi->phys) {
500e6908588SVille Syrjälä 		tmp = intel_de_read(dev_priv, ICL_PORT_TX_DW5_LN(0, phy));
501379bc100SJani Nikula 		tmp |= TX_TRAINING_EN;
5021c63f6dfSJani Nikula 		intel_de_write(dev_priv, ICL_PORT_TX_DW5_GRP(phy), tmp);
5031a45d681SAndrzej Hajda 		intel_de_rmw(dev_priv, ICL_PORT_TX_DW5_AUX(phy), 0, TX_TRAINING_EN);
504379bc100SJani Nikula 	}
505379bc100SJani Nikula }
506379bc100SJani Nikula 
gen11_dsi_enable_ddi_buffer(struct intel_encoder * encoder)507379bc100SJani Nikula static void gen11_dsi_enable_ddi_buffer(struct intel_encoder *encoder)
508379bc100SJani Nikula {
509379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
510b7d02c3aSVille Syrjälä 	struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
511379bc100SJani Nikula 	enum port port;
512379bc100SJani Nikula 
513379bc100SJani Nikula 	for_each_dsi_port(port, intel_dsi->ports) {
5141a45d681SAndrzej Hajda 		intel_de_rmw(dev_priv, DDI_BUF_CTL(port), 0, DDI_BUF_CTL_ENABLE);
515379bc100SJani Nikula 
5161c63f6dfSJani Nikula 		if (wait_for_us(!(intel_de_read(dev_priv, DDI_BUF_CTL(port)) &
517379bc100SJani Nikula 				  DDI_BUF_IS_IDLE),
518379bc100SJani Nikula 				  500))
519b5280cd0SWambui Karuga 			drm_err(&dev_priv->drm, "DDI port:%c buffer idle\n",
520b5280cd0SWambui Karuga 				port_name(port));
521379bc100SJani Nikula 	}
522379bc100SJani Nikula }
523379bc100SJani Nikula 
52404865139SJani Nikula static void
gen11_dsi_setup_dphy_timings(struct intel_encoder * encoder,const struct intel_crtc_state * crtc_state)52504865139SJani Nikula gen11_dsi_setup_dphy_timings(struct intel_encoder *encoder,
52604865139SJani Nikula 			     const struct intel_crtc_state *crtc_state)
527379bc100SJani Nikula {
528379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
529b7d02c3aSVille Syrjälä 	struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
530379bc100SJani Nikula 	enum port port;
531dc867bc7SMatt Roper 	enum phy phy;
532379bc100SJani Nikula 
533379bc100SJani Nikula 	/* Program DPHY clock lanes timings */
534d4121327SVille Syrjälä 	for_each_dsi_port(port, intel_dsi->ports)
5351c63f6dfSJani Nikula 		intel_de_write(dev_priv, DPHY_CLK_TIMING_PARAM(port),
5361c63f6dfSJani Nikula 			       intel_dsi->dphy_reg);
537379bc100SJani Nikula 
538379bc100SJani Nikula 	/* Program DPHY data lanes timings */
539d4121327SVille Syrjälä 	for_each_dsi_port(port, intel_dsi->ports)
5401c63f6dfSJani Nikula 		intel_de_write(dev_priv, DPHY_DATA_TIMING_PARAM(port),
541379bc100SJani Nikula 			       intel_dsi->dphy_data_lane_reg);
542379bc100SJani Nikula 
543379bc100SJani Nikula 	/*
544379bc100SJani Nikula 	 * If DSI link operating at or below an 800 MHz,
545379bc100SJani Nikula 	 * TA_SURE should be override and programmed to
546379bc100SJani Nikula 	 * a value '0' inside TA_PARAM_REGISTERS otherwise
547379bc100SJani Nikula 	 * leave all fields at HW default values.
548379bc100SJani Nikula 	 */
54993e7e61eSLucas De Marchi 	if (DISPLAY_VER(dev_priv) == 11) {
55004865139SJani Nikula 		if (afe_clk(encoder, crtc_state) <= 800000) {
551d4121327SVille Syrjälä 			for_each_dsi_port(port, intel_dsi->ports)
5521a45d681SAndrzej Hajda 				intel_de_rmw(dev_priv, DPHY_TA_TIMING_PARAM(port),
5531a45d681SAndrzej Hajda 					     TA_SURE_MASK,
5541a45d681SAndrzej Hajda 					     TA_SURE_OVERRIDE | TA_SURE(0));
555379bc100SJani Nikula 		}
5567b864f95SVandita Kulkarni 	}
557683d672cSJosé Roberto de Souza 
5580c65dc06SDnyaneshwar Bhadane 	if (IS_JASPERLAKE(dev_priv) || IS_ELKHARTLAKE(dev_priv)) {
5591a45d681SAndrzej Hajda 		for_each_dsi_phy(phy, intel_dsi->phys)
5601a45d681SAndrzej Hajda 			intel_de_rmw(dev_priv, ICL_DPHY_CHKN(phy),
5611a45d681SAndrzej Hajda 				     0, ICL_DPHY_CHKN_AFE_OVER_PPI_STRAP);
562683d672cSJosé Roberto de Souza 	}
563379bc100SJani Nikula }
564379bc100SJani Nikula 
565d4121327SVille Syrjälä static void
gen11_dsi_setup_timings(struct intel_encoder * encoder,const struct intel_crtc_state * crtc_state)566d4121327SVille Syrjälä gen11_dsi_setup_timings(struct intel_encoder *encoder,
567d4121327SVille Syrjälä 			const struct intel_crtc_state *crtc_state)
568d4121327SVille Syrjälä {
569d4121327SVille Syrjälä 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
570d4121327SVille Syrjälä 	struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
571d4121327SVille Syrjälä 	enum port port;
572d4121327SVille Syrjälä 
573d4121327SVille Syrjälä 	/* Program T-INIT master registers */
574d4121327SVille Syrjälä 	for_each_dsi_port(port, intel_dsi->ports)
575d4121327SVille Syrjälä 		intel_de_rmw(dev_priv, ICL_DSI_T_INIT_MASTER(port),
576d4121327SVille Syrjälä 			     DSI_T_INIT_MASTER_MASK, intel_dsi->init_count);
577d4121327SVille Syrjälä 
578d4121327SVille Syrjälä 	/* shadow register inside display core */
579d4121327SVille Syrjälä 	for_each_dsi_port(port, intel_dsi->ports)
580d4121327SVille Syrjälä 		intel_de_write(dev_priv, DSI_CLK_TIMING_PARAM(port),
581d4121327SVille Syrjälä 			       intel_dsi->dphy_reg);
582d4121327SVille Syrjälä 
583d4121327SVille Syrjälä 	/* shadow register inside display core */
584d4121327SVille Syrjälä 	for_each_dsi_port(port, intel_dsi->ports)
585d4121327SVille Syrjälä 		intel_de_write(dev_priv, DSI_DATA_TIMING_PARAM(port),
586d4121327SVille Syrjälä 			       intel_dsi->dphy_data_lane_reg);
587d4121327SVille Syrjälä 
588d4121327SVille Syrjälä 	/* shadow register inside display core */
589d4121327SVille Syrjälä 	if (DISPLAY_VER(dev_priv) == 11) {
590d4121327SVille Syrjälä 		if (afe_clk(encoder, crtc_state) <= 800000) {
591d4121327SVille Syrjälä 			for_each_dsi_port(port, intel_dsi->ports) {
592d4121327SVille Syrjälä 				intel_de_rmw(dev_priv, DSI_TA_TIMING_PARAM(port),
593d4121327SVille Syrjälä 					     TA_SURE_MASK,
594d4121327SVille Syrjälä 					     TA_SURE_OVERRIDE | TA_SURE(0));
595d4121327SVille Syrjälä 			}
596d4121327SVille Syrjälä 		}
597d4121327SVille Syrjälä 	}
598d4121327SVille Syrjälä }
599d4121327SVille Syrjälä 
gen11_dsi_gate_clocks(struct intel_encoder * encoder)600379bc100SJani Nikula static void gen11_dsi_gate_clocks(struct intel_encoder *encoder)
601379bc100SJani Nikula {
602379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
603b7d02c3aSVille Syrjälä 	struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
604379bc100SJani Nikula 	u32 tmp;
605befa372bSMatt Roper 	enum phy phy;
606379bc100SJani Nikula 
60736d225f3SJani Nikula 	mutex_lock(&dev_priv->display.dpll.lock);
6081c63f6dfSJani Nikula 	tmp = intel_de_read(dev_priv, ICL_DPCLKA_CFGCR0);
609dc867bc7SMatt Roper 	for_each_dsi_phy(phy, intel_dsi->phys)
610befa372bSMatt Roper 		tmp |= ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy);
611379bc100SJani Nikula 
6121c63f6dfSJani Nikula 	intel_de_write(dev_priv, ICL_DPCLKA_CFGCR0, tmp);
61336d225f3SJani Nikula 	mutex_unlock(&dev_priv->display.dpll.lock);
614379bc100SJani Nikula }
615379bc100SJani Nikula 
gen11_dsi_ungate_clocks(struct intel_encoder * encoder)616379bc100SJani Nikula static void gen11_dsi_ungate_clocks(struct intel_encoder *encoder)
617379bc100SJani Nikula {
618379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
619b7d02c3aSVille Syrjälä 	struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
620379bc100SJani Nikula 	u32 tmp;
621befa372bSMatt Roper 	enum phy phy;
622379bc100SJani Nikula 
62336d225f3SJani Nikula 	mutex_lock(&dev_priv->display.dpll.lock);
6241c63f6dfSJani Nikula 	tmp = intel_de_read(dev_priv, ICL_DPCLKA_CFGCR0);
625dc867bc7SMatt Roper 	for_each_dsi_phy(phy, intel_dsi->phys)
626befa372bSMatt Roper 		tmp &= ~ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy);
627379bc100SJani Nikula 
6281c63f6dfSJani Nikula 	intel_de_write(dev_priv, ICL_DPCLKA_CFGCR0, tmp);
62936d225f3SJani Nikula 	mutex_unlock(&dev_priv->display.dpll.lock);
630379bc100SJani Nikula }
631379bc100SJani Nikula 
gen11_dsi_is_clock_enabled(struct intel_encoder * encoder)6320fbd8694SVille Syrjälä static bool gen11_dsi_is_clock_enabled(struct intel_encoder *encoder)
6330fbd8694SVille Syrjälä {
6340fbd8694SVille Syrjälä 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
6350fbd8694SVille Syrjälä 	struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
6360fbd8694SVille Syrjälä 	bool clock_enabled = false;
6370fbd8694SVille Syrjälä 	enum phy phy;
6380fbd8694SVille Syrjälä 	u32 tmp;
6390fbd8694SVille Syrjälä 
6400fbd8694SVille Syrjälä 	tmp = intel_de_read(dev_priv, ICL_DPCLKA_CFGCR0);
6410fbd8694SVille Syrjälä 
6420fbd8694SVille Syrjälä 	for_each_dsi_phy(phy, intel_dsi->phys) {
6430fbd8694SVille Syrjälä 		if (!(tmp & ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy)))
6440fbd8694SVille Syrjälä 			clock_enabled = true;
6450fbd8694SVille Syrjälä 	}
6460fbd8694SVille Syrjälä 
6470fbd8694SVille Syrjälä 	return clock_enabled;
6480fbd8694SVille Syrjälä }
6490fbd8694SVille Syrjälä 
gen11_dsi_map_pll(struct intel_encoder * encoder,const struct intel_crtc_state * crtc_state)650379bc100SJani Nikula static void gen11_dsi_map_pll(struct intel_encoder *encoder,
651379bc100SJani Nikula 			      const struct intel_crtc_state *crtc_state)
652379bc100SJani Nikula {
653379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
654b7d02c3aSVille Syrjälä 	struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
655379bc100SJani Nikula 	struct intel_shared_dpll *pll = crtc_state->shared_dpll;
656befa372bSMatt Roper 	enum phy phy;
657379bc100SJani Nikula 	u32 val;
658379bc100SJani Nikula 
65936d225f3SJani Nikula 	mutex_lock(&dev_priv->display.dpll.lock);
660379bc100SJani Nikula 
6611c63f6dfSJani Nikula 	val = intel_de_read(dev_priv, ICL_DPCLKA_CFGCR0);
662dc867bc7SMatt Roper 	for_each_dsi_phy(phy, intel_dsi->phys) {
663befa372bSMatt Roper 		val &= ~ICL_DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(phy);
664befa372bSMatt Roper 		val |= ICL_DPCLKA_CFGCR0_DDI_CLK_SEL(pll->info->id, phy);
665379bc100SJani Nikula 	}
6661c63f6dfSJani Nikula 	intel_de_write(dev_priv, ICL_DPCLKA_CFGCR0, val);
667379bc100SJani Nikula 
668dc867bc7SMatt Roper 	for_each_dsi_phy(phy, intel_dsi->phys) {
669befa372bSMatt Roper 		val &= ~ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy);
670379bc100SJani Nikula 	}
6711c63f6dfSJani Nikula 	intel_de_write(dev_priv, ICL_DPCLKA_CFGCR0, val);
672379bc100SJani Nikula 
6731c63f6dfSJani Nikula 	intel_de_posting_read(dev_priv, ICL_DPCLKA_CFGCR0);
674379bc100SJani Nikula 
67536d225f3SJani Nikula 	mutex_unlock(&dev_priv->display.dpll.lock);
676379bc100SJani Nikula }
677379bc100SJani Nikula 
678379bc100SJani Nikula static void
gen11_dsi_configure_transcoder(struct intel_encoder * encoder,const struct intel_crtc_state * pipe_config)679379bc100SJani Nikula gen11_dsi_configure_transcoder(struct intel_encoder *encoder,
680379bc100SJani Nikula 			       const struct intel_crtc_state *pipe_config)
681379bc100SJani Nikula {
682379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
683b7d02c3aSVille Syrjälä 	struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
684f15f01a7SVille Syrjälä 	struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);
685f15f01a7SVille Syrjälä 	enum pipe pipe = crtc->pipe;
686379bc100SJani Nikula 	u32 tmp;
687379bc100SJani Nikula 	enum port port;
688379bc100SJani Nikula 	enum transcoder dsi_trans;
689379bc100SJani Nikula 
690379bc100SJani Nikula 	for_each_dsi_port(port, intel_dsi->ports) {
691379bc100SJani Nikula 		dsi_trans = dsi_port_to_transcoder(port);
6921c63f6dfSJani Nikula 		tmp = intel_de_read(dev_priv, DSI_TRANS_FUNC_CONF(dsi_trans));
693379bc100SJani Nikula 
694379bc100SJani Nikula 		if (intel_dsi->eotp_pkt)
695379bc100SJani Nikula 			tmp &= ~EOTP_DISABLED;
696379bc100SJani Nikula 		else
697379bc100SJani Nikula 			tmp |= EOTP_DISABLED;
698379bc100SJani Nikula 
699379bc100SJani Nikula 		/* enable link calibration if freq > 1.5Gbps */
70004865139SJani Nikula 		if (afe_clk(encoder, pipe_config) >= 1500 * 1000) {
701379bc100SJani Nikula 			tmp &= ~LINK_CALIBRATION_MASK;
702379bc100SJani Nikula 			tmp |= CALIBRATION_ENABLED_INITIAL_ONLY;
703379bc100SJani Nikula 		}
704379bc100SJani Nikula 
705379bc100SJani Nikula 		/* configure continuous clock */
706379bc100SJani Nikula 		tmp &= ~CONTINUOUS_CLK_MASK;
707379bc100SJani Nikula 		if (intel_dsi->clock_stop)
708379bc100SJani Nikula 			tmp |= CLK_ENTER_LP_AFTER_DATA;
709379bc100SJani Nikula 		else
710379bc100SJani Nikula 			tmp |= CLK_HS_CONTINUOUS;
711379bc100SJani Nikula 
712379bc100SJani Nikula 		/* configure buffer threshold limit to minimum */
713379bc100SJani Nikula 		tmp &= ~PIX_BUF_THRESHOLD_MASK;
714379bc100SJani Nikula 		tmp |= PIX_BUF_THRESHOLD_1_4;
715379bc100SJani Nikula 
716379bc100SJani Nikula 		/* set virtual channel to '0' */
717379bc100SJani Nikula 		tmp &= ~PIX_VIRT_CHAN_MASK;
718379bc100SJani Nikula 		tmp |= PIX_VIRT_CHAN(0);
719379bc100SJani Nikula 
720379bc100SJani Nikula 		/* program BGR transmission */
721379bc100SJani Nikula 		if (intel_dsi->bgr_enabled)
722379bc100SJani Nikula 			tmp |= BGR_TRANSMISSION;
723379bc100SJani Nikula 
724379bc100SJani Nikula 		/* select pixel format */
725379bc100SJani Nikula 		tmp &= ~PIX_FMT_MASK;
72638b89881SJani Nikula 		if (pipe_config->dsc.compression_enable) {
72738b89881SJani Nikula 			tmp |= PIX_FMT_COMPRESSED;
72838b89881SJani Nikula 		} else {
729379bc100SJani Nikula 			switch (intel_dsi->pixel_format) {
730379bc100SJani Nikula 			default:
731379bc100SJani Nikula 				MISSING_CASE(intel_dsi->pixel_format);
732df561f66SGustavo A. R. Silva 				fallthrough;
733379bc100SJani Nikula 			case MIPI_DSI_FMT_RGB565:
734379bc100SJani Nikula 				tmp |= PIX_FMT_RGB565;
735379bc100SJani Nikula 				break;
736379bc100SJani Nikula 			case MIPI_DSI_FMT_RGB666_PACKED:
737379bc100SJani Nikula 				tmp |= PIX_FMT_RGB666_PACKED;
738379bc100SJani Nikula 				break;
739379bc100SJani Nikula 			case MIPI_DSI_FMT_RGB666:
740379bc100SJani Nikula 				tmp |= PIX_FMT_RGB666_LOOSE;
741379bc100SJani Nikula 				break;
742379bc100SJani Nikula 			case MIPI_DSI_FMT_RGB888:
743379bc100SJani Nikula 				tmp |= PIX_FMT_RGB888;
744379bc100SJani Nikula 				break;
745379bc100SJani Nikula 			}
74638b89881SJani Nikula 		}
747379bc100SJani Nikula 
748005e9537SMatt Roper 		if (DISPLAY_VER(dev_priv) >= 12) {
74932d38e6cSVandita Kulkarni 			if (is_vid_mode(intel_dsi))
75032d38e6cSVandita Kulkarni 				tmp |= BLANKING_PACKET_ENABLE;
75132d38e6cSVandita Kulkarni 		}
75232d38e6cSVandita Kulkarni 
753379bc100SJani Nikula 		/* program DSI operation mode */
754379bc100SJani Nikula 		if (is_vid_mode(intel_dsi)) {
755379bc100SJani Nikula 			tmp &= ~OP_MODE_MASK;
7568f0991ccSJani Nikula 			switch (intel_dsi->video_mode) {
757379bc100SJani Nikula 			default:
7588f0991ccSJani Nikula 				MISSING_CASE(intel_dsi->video_mode);
759df561f66SGustavo A. R. Silva 				fallthrough;
7608f0991ccSJani Nikula 			case NON_BURST_SYNC_EVENTS:
761379bc100SJani Nikula 				tmp |= VIDEO_MODE_SYNC_EVENT;
762379bc100SJani Nikula 				break;
7638f0991ccSJani Nikula 			case NON_BURST_SYNC_PULSE:
764379bc100SJani Nikula 				tmp |= VIDEO_MODE_SYNC_PULSE;
765379bc100SJani Nikula 				break;
766379bc100SJani Nikula 			}
767b4b95b05SVandita Kulkarni 		} else {
768b4b95b05SVandita Kulkarni 			/*
769b4b95b05SVandita Kulkarni 			 * FIXME: Retrieve this info from VBT.
770b4b95b05SVandita Kulkarni 			 * As per the spec when dsi transcoder is operating
771b4b95b05SVandita Kulkarni 			 * in TE GATE mode, TE comes from GPIO
772b4b95b05SVandita Kulkarni 			 * which is UTIL PIN for DSI 0.
773b4b95b05SVandita Kulkarni 			 * Also this GPIO would not be used for other
774b4b95b05SVandita Kulkarni 			 * purposes is an assumption.
775b4b95b05SVandita Kulkarni 			 */
776b4b95b05SVandita Kulkarni 			tmp &= ~OP_MODE_MASK;
777b4b95b05SVandita Kulkarni 			tmp |= CMD_MODE_TE_GATE;
778b4b95b05SVandita Kulkarni 			tmp |= TE_SOURCE_GPIO;
779379bc100SJani Nikula 		}
780379bc100SJani Nikula 
7811c63f6dfSJani Nikula 		intel_de_write(dev_priv, DSI_TRANS_FUNC_CONF(dsi_trans), tmp);
782379bc100SJani Nikula 	}
783379bc100SJani Nikula 
784379bc100SJani Nikula 	/* enable port sync mode if dual link */
785379bc100SJani Nikula 	if (intel_dsi->dual_link) {
786379bc100SJani Nikula 		for_each_dsi_port(port, intel_dsi->ports) {
787379bc100SJani Nikula 			dsi_trans = dsi_port_to_transcoder(port);
78876f1b2b1SJani Nikula 			intel_de_rmw(dev_priv,
78976f1b2b1SJani Nikula 				     TRANS_DDI_FUNC_CTL2(dev_priv, dsi_trans),
7901a45d681SAndrzej Hajda 				     0, PORT_SYNC_MODE_ENABLE);
791379bc100SJani Nikula 		}
792379bc100SJani Nikula 
793379bc100SJani Nikula 		/* configure stream splitting */
794379bc100SJani Nikula 		configure_dual_link_mode(encoder, pipe_config);
795379bc100SJani Nikula 	}
796379bc100SJani Nikula 
797379bc100SJani Nikula 	for_each_dsi_port(port, intel_dsi->ports) {
798379bc100SJani Nikula 		dsi_trans = dsi_port_to_transcoder(port);
799379bc100SJani Nikula 
800379bc100SJani Nikula 		/* select data lane width */
801b092d6adSJani Nikula 		tmp = intel_de_read(dev_priv,
802b092d6adSJani Nikula 				    TRANS_DDI_FUNC_CTL(dev_priv, dsi_trans));
803379bc100SJani Nikula 		tmp &= ~DDI_PORT_WIDTH_MASK;
804379bc100SJani Nikula 		tmp |= DDI_PORT_WIDTH(intel_dsi->lane_count);
805379bc100SJani Nikula 
806379bc100SJani Nikula 		/* select input pipe */
807379bc100SJani Nikula 		tmp &= ~TRANS_DDI_EDP_INPUT_MASK;
808379bc100SJani Nikula 		switch (pipe) {
809379bc100SJani Nikula 		default:
810379bc100SJani Nikula 			MISSING_CASE(pipe);
811df561f66SGustavo A. R. Silva 			fallthrough;
812379bc100SJani Nikula 		case PIPE_A:
813379bc100SJani Nikula 			tmp |= TRANS_DDI_EDP_INPUT_A_ON;
814379bc100SJani Nikula 			break;
815379bc100SJani Nikula 		case PIPE_B:
816379bc100SJani Nikula 			tmp |= TRANS_DDI_EDP_INPUT_B_ONOFF;
817379bc100SJani Nikula 			break;
818379bc100SJani Nikula 		case PIPE_C:
819379bc100SJani Nikula 			tmp |= TRANS_DDI_EDP_INPUT_C_ONOFF;
820379bc100SJani Nikula 			break;
8214d89adc7SJosé Roberto de Souza 		case PIPE_D:
8224d89adc7SJosé Roberto de Souza 			tmp |= TRANS_DDI_EDP_INPUT_D_ONOFF;
8234d89adc7SJosé Roberto de Souza 			break;
824379bc100SJani Nikula 		}
825379bc100SJani Nikula 
826379bc100SJani Nikula 		/* enable DDI buffer */
827379bc100SJani Nikula 		tmp |= TRANS_DDI_FUNC_ENABLE;
828b092d6adSJani Nikula 		intel_de_write(dev_priv,
829b092d6adSJani Nikula 			       TRANS_DDI_FUNC_CTL(dev_priv, dsi_trans), tmp);
830379bc100SJani Nikula 	}
831379bc100SJani Nikula 
832379bc100SJani Nikula 	/* wait for link ready */
833379bc100SJani Nikula 	for_each_dsi_port(port, intel_dsi->ports) {
834379bc100SJani Nikula 		dsi_trans = dsi_port_to_transcoder(port);
8351c63f6dfSJani Nikula 		if (wait_for_us((intel_de_read(dev_priv, DSI_TRANS_FUNC_CONF(dsi_trans)) &
836379bc100SJani Nikula 				 LINK_READY), 2500))
837b5280cd0SWambui Karuga 			drm_err(&dev_priv->drm, "DSI link not ready\n");
838379bc100SJani Nikula 	}
839379bc100SJani Nikula }
840379bc100SJani Nikula 
841379bc100SJani Nikula static void
gen11_dsi_set_transcoder_timings(struct intel_encoder * encoder,const struct intel_crtc_state * crtc_state)842379bc100SJani Nikula gen11_dsi_set_transcoder_timings(struct intel_encoder *encoder,
84353693f02SJani Nikula 				 const struct intel_crtc_state *crtc_state)
844379bc100SJani Nikula {
845379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
846b7d02c3aSVille Syrjälä 	struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
847379bc100SJani Nikula 	const struct drm_display_mode *adjusted_mode =
84853693f02SJani Nikula 		&crtc_state->hw.adjusted_mode;
849379bc100SJani Nikula 	enum port port;
850379bc100SJani Nikula 	enum transcoder dsi_trans;
851379bc100SJani Nikula 	/* horizontal timings */
852379bc100SJani Nikula 	u16 htotal, hactive, hsync_start, hsync_end, hsync_size;
8530cc35a9cSYueHaibing 	u16 hback_porch;
854379bc100SJani Nikula 	/* vertical timings */
855379bc100SJani Nikula 	u16 vtotal, vactive, vsync_start, vsync_end, vsync_shift;
85653693f02SJani Nikula 	int mul = 1, div = 1;
85753693f02SJani Nikula 
85853693f02SJani Nikula 	/*
85953693f02SJani Nikula 	 * Adjust horizontal timings (htotal, hsync_start, hsync_end) to account
86053693f02SJani Nikula 	 * for slower link speed if DSC is enabled.
86153693f02SJani Nikula 	 *
86253693f02SJani Nikula 	 * The compression frequency ratio is the ratio between compressed and
86353693f02SJani Nikula 	 * non-compressed link speeds, and simplifies down to the ratio between
86453693f02SJani Nikula 	 * compressed and non-compressed bpp.
86553693f02SJani Nikula 	 */
86653693f02SJani Nikula 	if (crtc_state->dsc.compression_enable) {
8678466a141SImre Deak 		mul = fxp_q4_to_int(crtc_state->dsc.compressed_bpp_x16);
86853693f02SJani Nikula 		div = mipi_dsi_pixel_format_to_bpp(intel_dsi->pixel_format);
86953693f02SJani Nikula 	}
870379bc100SJani Nikula 
871379bc100SJani Nikula 	hactive = adjusted_mode->crtc_hdisplay;
872b9277832SVandita Kulkarni 
873b9277832SVandita Kulkarni 	if (is_vid_mode(intel_dsi))
87453693f02SJani Nikula 		htotal = DIV_ROUND_UP(adjusted_mode->crtc_htotal * mul, div);
875b9277832SVandita Kulkarni 	else
876b9277832SVandita Kulkarni 		htotal = DIV_ROUND_UP((hactive + 160) * mul, div);
877b9277832SVandita Kulkarni 
87853693f02SJani Nikula 	hsync_start = DIV_ROUND_UP(adjusted_mode->crtc_hsync_start * mul, div);
87953693f02SJani Nikula 	hsync_end = DIV_ROUND_UP(adjusted_mode->crtc_hsync_end * mul, div);
880379bc100SJani Nikula 	hsync_size  = hsync_end - hsync_start;
881379bc100SJani Nikula 	hback_porch = (adjusted_mode->crtc_htotal -
882379bc100SJani Nikula 		       adjusted_mode->crtc_hsync_end);
883379bc100SJani Nikula 	vactive = adjusted_mode->crtc_vdisplay;
884b9277832SVandita Kulkarni 
885b9277832SVandita Kulkarni 	if (is_vid_mode(intel_dsi)) {
886379bc100SJani Nikula 		vtotal = adjusted_mode->crtc_vtotal;
887b9277832SVandita Kulkarni 	} else {
888b9277832SVandita Kulkarni 		int bpp, line_time_us, byte_clk_period_ns;
889b9277832SVandita Kulkarni 
890b9277832SVandita Kulkarni 		if (crtc_state->dsc.compression_enable)
8918466a141SImre Deak 			bpp = fxp_q4_to_int(crtc_state->dsc.compressed_bpp_x16);
892b9277832SVandita Kulkarni 		else
893b9277832SVandita Kulkarni 			bpp = mipi_dsi_pixel_format_to_bpp(intel_dsi->pixel_format);
894b9277832SVandita Kulkarni 
895b9277832SVandita Kulkarni 		byte_clk_period_ns = 1000000 / afe_clk(encoder, crtc_state);
896b9277832SVandita Kulkarni 		line_time_us = (htotal * (bpp / 8) * byte_clk_period_ns) / (1000 * intel_dsi->lane_count);
897b9277832SVandita Kulkarni 		vtotal = vactive + DIV_ROUND_UP(400, line_time_us);
898b9277832SVandita Kulkarni 	}
899379bc100SJani Nikula 	vsync_start = adjusted_mode->crtc_vsync_start;
900379bc100SJani Nikula 	vsync_end = adjusted_mode->crtc_vsync_end;
901379bc100SJani Nikula 	vsync_shift = hsync_start - htotal / 2;
902379bc100SJani Nikula 
903379bc100SJani Nikula 	if (intel_dsi->dual_link) {
904379bc100SJani Nikula 		hactive /= 2;
905379bc100SJani Nikula 		if (intel_dsi->dual_link == DSI_DUAL_LINK_FRONT_BACK)
906379bc100SJani Nikula 			hactive += intel_dsi->pixel_overlap;
907379bc100SJani Nikula 		htotal /= 2;
908379bc100SJani Nikula 	}
909379bc100SJani Nikula 
910379bc100SJani Nikula 	/* minimum hactive as per bspec: 256 pixels */
911379bc100SJani Nikula 	if (adjusted_mode->crtc_hdisplay < 256)
912b5280cd0SWambui Karuga 		drm_err(&dev_priv->drm, "hactive is less then 256 pixels\n");
913379bc100SJani Nikula 
914379bc100SJani Nikula 	/* if RGB666 format, then hactive must be multiple of 4 pixels */
915379bc100SJani Nikula 	if (intel_dsi->pixel_format == MIPI_DSI_FMT_RGB666 && hactive % 4 != 0)
916b5280cd0SWambui Karuga 		drm_err(&dev_priv->drm,
917b5280cd0SWambui Karuga 			"hactive pixels are not multiple of 4\n");
918379bc100SJani Nikula 
919379bc100SJani Nikula 	/* program TRANS_HTOTAL register */
920379bc100SJani Nikula 	for_each_dsi_port(port, intel_dsi->ports) {
921379bc100SJani Nikula 		dsi_trans = dsi_port_to_transcoder(port);
922e5799743SJani Nikula 		intel_de_write(dev_priv, TRANS_HTOTAL(dev_priv, dsi_trans),
923050db7d7SVille Syrjälä 			       HACTIVE(hactive - 1) | HTOTAL(htotal - 1));
924379bc100SJani Nikula 	}
925379bc100SJani Nikula 
926379bc100SJani Nikula 	/* TRANS_HSYNC register to be programmed only for video mode */
927b9277832SVandita Kulkarni 	if (is_vid_mode(intel_dsi)) {
9288f0991ccSJani Nikula 		if (intel_dsi->video_mode == NON_BURST_SYNC_PULSE) {
929379bc100SJani Nikula 			/* BSPEC: hsync size should be atleast 16 pixels */
930379bc100SJani Nikula 			if (hsync_size < 16)
931b5280cd0SWambui Karuga 				drm_err(&dev_priv->drm,
932b5280cd0SWambui Karuga 					"hsync size < 16 pixels\n");
933379bc100SJani Nikula 		}
934379bc100SJani Nikula 
935379bc100SJani Nikula 		if (hback_porch < 16)
936b5280cd0SWambui Karuga 			drm_err(&dev_priv->drm, "hback porch < 16 pixels\n");
937379bc100SJani Nikula 
938379bc100SJani Nikula 		if (intel_dsi->dual_link) {
939379bc100SJani Nikula 			hsync_start /= 2;
940379bc100SJani Nikula 			hsync_end /= 2;
941379bc100SJani Nikula 		}
942379bc100SJani Nikula 
943379bc100SJani Nikula 		for_each_dsi_port(port, intel_dsi->ports) {
944379bc100SJani Nikula 			dsi_trans = dsi_port_to_transcoder(port);
9459b2db3bbSJani Nikula 			intel_de_write(dev_priv,
9469b2db3bbSJani Nikula 				       TRANS_HSYNC(dev_priv, dsi_trans),
947050db7d7SVille Syrjälä 				       HSYNC_START(hsync_start - 1) | HSYNC_END(hsync_end - 1));
948379bc100SJani Nikula 		}
949379bc100SJani Nikula 	}
950379bc100SJani Nikula 
951379bc100SJani Nikula 	/* program TRANS_VTOTAL register */
952379bc100SJani Nikula 	for_each_dsi_port(port, intel_dsi->ports) {
953379bc100SJani Nikula 		dsi_trans = dsi_port_to_transcoder(port);
954379bc100SJani Nikula 		/*
955379bc100SJani Nikula 		 * FIXME: Programing this by assuming progressive mode, since
956379bc100SJani Nikula 		 * non-interlaced info from VBT is not saved inside
957379bc100SJani Nikula 		 * struct drm_display_mode.
958379bc100SJani Nikula 		 * For interlace mode: program required pixel minus 2
959379bc100SJani Nikula 		 */
960b3e773f6SJani Nikula 		intel_de_write(dev_priv, TRANS_VTOTAL(dev_priv, dsi_trans),
961050db7d7SVille Syrjälä 			       VACTIVE(vactive - 1) | VTOTAL(vtotal - 1));
962379bc100SJani Nikula 	}
963379bc100SJani Nikula 
964379bc100SJani Nikula 	if (vsync_end < vsync_start || vsync_end > vtotal)
965b5280cd0SWambui Karuga 		drm_err(&dev_priv->drm, "Invalid vsync_end value\n");
966379bc100SJani Nikula 
967379bc100SJani Nikula 	if (vsync_start < vactive)
968b5280cd0SWambui Karuga 		drm_err(&dev_priv->drm, "vsync_start less than vactive\n");
969379bc100SJani Nikula 
970b9277832SVandita Kulkarni 	/* program TRANS_VSYNC register for video mode only */
971b9277832SVandita Kulkarni 	if (is_vid_mode(intel_dsi)) {
972379bc100SJani Nikula 		for_each_dsi_port(port, intel_dsi->ports) {
973379bc100SJani Nikula 			dsi_trans = dsi_port_to_transcoder(port);
9749cacbd23SJani Nikula 			intel_de_write(dev_priv,
9759cacbd23SJani Nikula 				       TRANS_VSYNC(dev_priv, dsi_trans),
976050db7d7SVille Syrjälä 				       VSYNC_START(vsync_start - 1) | VSYNC_END(vsync_end - 1));
977379bc100SJani Nikula 		}
978b9277832SVandita Kulkarni 	}
979379bc100SJani Nikula 
980379bc100SJani Nikula 	/*
981b9277832SVandita Kulkarni 	 * FIXME: It has to be programmed only for video modes and interlaced
982379bc100SJani Nikula 	 * modes. Put the check condition here once interlaced
983379bc100SJani Nikula 	 * info available as described above.
984379bc100SJani Nikula 	 * program TRANS_VSYNCSHIFT register
985379bc100SJani Nikula 	 */
986b9277832SVandita Kulkarni 	if (is_vid_mode(intel_dsi)) {
987379bc100SJani Nikula 		for_each_dsi_port(port, intel_dsi->ports) {
988379bc100SJani Nikula 			dsi_trans = dsi_port_to_transcoder(port);
9898925350cSJani Nikula 			intel_de_write(dev_priv,
9908925350cSJani Nikula 				       TRANS_VSYNCSHIFT(dev_priv, dsi_trans),
991b9277832SVandita Kulkarni 				       vsync_shift);
992b9277832SVandita Kulkarni 		}
993379bc100SJani Nikula 	}
9943522a33aSVandita Kulkarni 
9951552dd6eSVille Syrjälä 	/*
9961552dd6eSVille Syrjälä 	 * program TRANS_VBLANK register, should be same as vtotal programmed
9971552dd6eSVille Syrjälä 	 *
9981552dd6eSVille Syrjälä 	 * FIXME get rid of these local hacks and do it right,
9991552dd6eSVille Syrjälä 	 * this will not handle eg. delayed vblank correctly.
10001552dd6eSVille Syrjälä 	 */
1001005e9537SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 12) {
10023522a33aSVandita Kulkarni 		for_each_dsi_port(port, intel_dsi->ports) {
10033522a33aSVandita Kulkarni 			dsi_trans = dsi_port_to_transcoder(port);
100445f10393SJani Nikula 			intel_de_write(dev_priv,
100545f10393SJani Nikula 				       TRANS_VBLANK(dev_priv, dsi_trans),
1006050db7d7SVille Syrjälä 				       VBLANK_START(vactive - 1) | VBLANK_END(vtotal - 1));
10073522a33aSVandita Kulkarni 		}
10083522a33aSVandita Kulkarni 	}
1009379bc100SJani Nikula }
1010379bc100SJani Nikula 
gen11_dsi_enable_transcoder(struct intel_encoder * encoder)1011379bc100SJani Nikula static void gen11_dsi_enable_transcoder(struct intel_encoder *encoder)
1012379bc100SJani Nikula {
1013379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
1014b7d02c3aSVille Syrjälä 	struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
1015379bc100SJani Nikula 	enum port port;
1016379bc100SJani Nikula 	enum transcoder dsi_trans;
1017379bc100SJani Nikula 
1018379bc100SJani Nikula 	for_each_dsi_port(port, intel_dsi->ports) {
1019379bc100SJani Nikula 		dsi_trans = dsi_port_to_transcoder(port);
1020984b61c3SJani Nikula 		intel_de_rmw(dev_priv, TRANSCONF(dev_priv, dsi_trans), 0,
1021984b61c3SJani Nikula 			     TRANSCONF_ENABLE);
1022379bc100SJani Nikula 
1023379bc100SJani Nikula 		/* wait for transcoder to be enabled */
1024984b61c3SJani Nikula 		if (intel_de_wait_for_set(dev_priv, TRANSCONF(dev_priv, dsi_trans),
10253eb08ea5SVille Syrjälä 					  TRANSCONF_STATE_ENABLE, 10))
1026b5280cd0SWambui Karuga 			drm_err(&dev_priv->drm,
1027b5280cd0SWambui Karuga 				"DSI transcoder not enabled\n");
1028379bc100SJani Nikula 	}
1029379bc100SJani Nikula }
1030379bc100SJani Nikula 
gen11_dsi_setup_timeouts(struct intel_encoder * encoder,const struct intel_crtc_state * crtc_state)103104865139SJani Nikula static void gen11_dsi_setup_timeouts(struct intel_encoder *encoder,
103204865139SJani Nikula 				     const struct intel_crtc_state *crtc_state)
1033379bc100SJani Nikula {
1034379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
1035b7d02c3aSVille Syrjälä 	struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
1036379bc100SJani Nikula 	enum port port;
1037379bc100SJani Nikula 	enum transcoder dsi_trans;
10381a45d681SAndrzej Hajda 	u32 hs_tx_timeout, lp_rx_timeout, ta_timeout, divisor, mul;
1039379bc100SJani Nikula 
1040379bc100SJani Nikula 	/*
1041379bc100SJani Nikula 	 * escape clock count calculation:
1042379bc100SJani Nikula 	 * BYTE_CLK_COUNT = TIME_NS/(8 * UI)
1043379bc100SJani Nikula 	 * UI (nsec) = (10^6)/Bitrate
1044379bc100SJani Nikula 	 * TIME_NS = (BYTE_CLK_COUNT * 8 * 10^6)/ Bitrate
1045379bc100SJani Nikula 	 * ESCAPE_CLK_COUNT  = TIME_NS/ESC_CLK_NS
1046379bc100SJani Nikula 	 */
104704865139SJani Nikula 	divisor = intel_dsi_tlpx_ns(intel_dsi) * afe_clk(encoder, crtc_state) * 1000;
1048379bc100SJani Nikula 	mul = 8 * 1000000;
1049379bc100SJani Nikula 	hs_tx_timeout = DIV_ROUND_UP(intel_dsi->hs_tx_timeout * mul,
1050379bc100SJani Nikula 				     divisor);
1051379bc100SJani Nikula 	lp_rx_timeout = DIV_ROUND_UP(intel_dsi->lp_rx_timeout * mul, divisor);
1052379bc100SJani Nikula 	ta_timeout = DIV_ROUND_UP(intel_dsi->turn_arnd_val * mul, divisor);
1053379bc100SJani Nikula 
1054379bc100SJani Nikula 	for_each_dsi_port(port, intel_dsi->ports) {
1055379bc100SJani Nikula 		dsi_trans = dsi_port_to_transcoder(port);
1056379bc100SJani Nikula 
1057379bc100SJani Nikula 		/* program hst_tx_timeout */
10581a45d681SAndrzej Hajda 		intel_de_rmw(dev_priv, DSI_HSTX_TO(dsi_trans),
10591a45d681SAndrzej Hajda 			     HSTX_TIMEOUT_VALUE_MASK,
10601a45d681SAndrzej Hajda 			     HSTX_TIMEOUT_VALUE(hs_tx_timeout));
1061379bc100SJani Nikula 
1062379bc100SJani Nikula 		/* FIXME: DSI_CALIB_TO */
1063379bc100SJani Nikula 
1064379bc100SJani Nikula 		/* program lp_rx_host timeout */
10651a45d681SAndrzej Hajda 		intel_de_rmw(dev_priv, DSI_LPRX_HOST_TO(dsi_trans),
10661a45d681SAndrzej Hajda 			     LPRX_TIMEOUT_VALUE_MASK,
10671a45d681SAndrzej Hajda 			     LPRX_TIMEOUT_VALUE(lp_rx_timeout));
1068379bc100SJani Nikula 
1069379bc100SJani Nikula 		/* FIXME: DSI_PWAIT_TO */
1070379bc100SJani Nikula 
1071379bc100SJani Nikula 		/* program turn around timeout */
10721a45d681SAndrzej Hajda 		intel_de_rmw(dev_priv, DSI_TA_TO(dsi_trans),
10731a45d681SAndrzej Hajda 			     TA_TIMEOUT_VALUE_MASK,
10741a45d681SAndrzej Hajda 			     TA_TIMEOUT_VALUE(ta_timeout));
1075379bc100SJani Nikula 	}
1076379bc100SJani Nikula }
1077379bc100SJani Nikula 
gen11_dsi_config_util_pin(struct intel_encoder * encoder,bool enable)1078b4b95b05SVandita Kulkarni static void gen11_dsi_config_util_pin(struct intel_encoder *encoder,
1079b4b95b05SVandita Kulkarni 				      bool enable)
1080b4b95b05SVandita Kulkarni {
1081b4b95b05SVandita Kulkarni 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
1082b4b95b05SVandita Kulkarni 	struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
1083b4b95b05SVandita Kulkarni 	u32 tmp;
1084b4b95b05SVandita Kulkarni 
1085b4b95b05SVandita Kulkarni 	/*
1086b4b95b05SVandita Kulkarni 	 * used as TE i/p for DSI0,
1087b4b95b05SVandita Kulkarni 	 * for dual link/DSI1 TE is from slave DSI1
1088b4b95b05SVandita Kulkarni 	 * through GPIO.
1089b4b95b05SVandita Kulkarni 	 */
1090b4b95b05SVandita Kulkarni 	if (is_vid_mode(intel_dsi) || (intel_dsi->ports & BIT(PORT_B)))
1091b4b95b05SVandita Kulkarni 		return;
1092b4b95b05SVandita Kulkarni 
1093b4b95b05SVandita Kulkarni 	tmp = intel_de_read(dev_priv, UTIL_PIN_CTL);
1094b4b95b05SVandita Kulkarni 
1095b4b95b05SVandita Kulkarni 	if (enable) {
1096b4b95b05SVandita Kulkarni 		tmp |= UTIL_PIN_DIRECTION_INPUT;
1097b4b95b05SVandita Kulkarni 		tmp |= UTIL_PIN_ENABLE;
1098b4b95b05SVandita Kulkarni 	} else {
1099b4b95b05SVandita Kulkarni 		tmp &= ~UTIL_PIN_ENABLE;
1100b4b95b05SVandita Kulkarni 	}
1101b4b95b05SVandita Kulkarni 	intel_de_write(dev_priv, UTIL_PIN_CTL, tmp);
1102b4b95b05SVandita Kulkarni }
1103b4b95b05SVandita Kulkarni 
1104379bc100SJani Nikula static void
gen11_dsi_enable_port_and_phy(struct intel_encoder * encoder,const struct intel_crtc_state * crtc_state)1105379bc100SJani Nikula gen11_dsi_enable_port_and_phy(struct intel_encoder *encoder,
110604865139SJani Nikula 			      const struct intel_crtc_state *crtc_state)
1107379bc100SJani Nikula {
1108379bc100SJani Nikula 	/* step 4a: power up all lanes of the DDI used by DSI */
1109379bc100SJani Nikula 	gen11_dsi_power_up_lanes(encoder);
1110379bc100SJani Nikula 
1111379bc100SJani Nikula 	/* step 4b: configure lane sequencing of the Combo-PHY transmitters */
1112379bc100SJani Nikula 	gen11_dsi_config_phy_lanes_sequence(encoder);
1113379bc100SJani Nikula 
1114379bc100SJani Nikula 	/* step 4c: configure voltage swing and skew */
1115379bc100SJani Nikula 	gen11_dsi_voltage_swing_program_seq(encoder);
1116379bc100SJani Nikula 
1117d4121327SVille Syrjälä 	/* setup D-PHY timings */
1118d4121327SVille Syrjälä 	gen11_dsi_setup_dphy_timings(encoder, crtc_state);
1119d4121327SVille Syrjälä 
1120379bc100SJani Nikula 	/* enable DDI buffer */
1121379bc100SJani Nikula 	gen11_dsi_enable_ddi_buffer(encoder);
1122379bc100SJani Nikula 
1123a43d9281SVille Syrjälä 	gen11_dsi_gate_clocks(encoder);
1124a43d9281SVille Syrjälä 
1125d4121327SVille Syrjälä 	gen11_dsi_setup_timings(encoder, crtc_state);
1126379bc100SJani Nikula 
1127b4b95b05SVandita Kulkarni 	/* Since transcoder is configured to take events from GPIO */
1128b4b95b05SVandita Kulkarni 	gen11_dsi_config_util_pin(encoder, true);
1129b4b95b05SVandita Kulkarni 
1130379bc100SJani Nikula 	/* step 4h: setup DSI protocol timeouts */
113104865139SJani Nikula 	gen11_dsi_setup_timeouts(encoder, crtc_state);
1132379bc100SJani Nikula 
1133379bc100SJani Nikula 	/* Step (4h, 4i, 4j, 4k): Configure transcoder */
113404865139SJani Nikula 	gen11_dsi_configure_transcoder(encoder, crtc_state);
1135379bc100SJani Nikula }
1136379bc100SJani Nikula 
gen11_dsi_powerup_panel(struct intel_encoder * encoder)1137379bc100SJani Nikula static void gen11_dsi_powerup_panel(struct intel_encoder *encoder)
1138379bc100SJani Nikula {
1139379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
1140b7d02c3aSVille Syrjälä 	struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
1141379bc100SJani Nikula 	struct mipi_dsi_device *dsi;
1142379bc100SJani Nikula 	enum port port;
1143379bc100SJani Nikula 	enum transcoder dsi_trans;
1144379bc100SJani Nikula 	u32 tmp;
1145379bc100SJani Nikula 	int ret;
1146379bc100SJani Nikula 
1147379bc100SJani Nikula 	/* set maximum return packet size */
1148379bc100SJani Nikula 	for_each_dsi_port(port, intel_dsi->ports) {
1149379bc100SJani Nikula 		dsi_trans = dsi_port_to_transcoder(port);
1150379bc100SJani Nikula 
1151379bc100SJani Nikula 		/*
1152379bc100SJani Nikula 		 * FIXME: This uses the number of DW's currently in the payload
1153379bc100SJani Nikula 		 * receive queue. This is probably not what we want here.
1154379bc100SJani Nikula 		 */
11551c63f6dfSJani Nikula 		tmp = intel_de_read(dev_priv, DSI_CMD_RXCTL(dsi_trans));
1156379bc100SJani Nikula 		tmp &= NUMBER_RX_PLOAD_DW_MASK;
1157379bc100SJani Nikula 		/* multiply "Number Rx Payload DW" by 4 to get max value */
1158379bc100SJani Nikula 		tmp = tmp * 4;
1159379bc100SJani Nikula 		dsi = intel_dsi->dsi_hosts[port]->device;
1160379bc100SJani Nikula 		ret = mipi_dsi_set_maximum_return_packet_size(dsi, tmp);
1161379bc100SJani Nikula 		if (ret < 0)
1162b5280cd0SWambui Karuga 			drm_err(&dev_priv->drm,
1163b5280cd0SWambui Karuga 				"error setting max return pkt size%d\n", tmp);
1164379bc100SJani Nikula 	}
1165379bc100SJani Nikula 
1166379bc100SJani Nikula 	intel_dsi_vbt_exec_sequence(intel_dsi, MIPI_SEQ_INIT_OTP);
1167379bc100SJani Nikula 
1168379bc100SJani Nikula 	/* ensure all panel commands dispatched before enabling transcoder */
1169379bc100SJani Nikula 	wait_for_cmds_dispatched_to_panel(encoder);
1170379bc100SJani Nikula }
1171379bc100SJani Nikula 
gen11_dsi_pre_pll_enable(struct intel_atomic_state * state,struct intel_encoder * encoder,const struct intel_crtc_state * crtc_state,const struct drm_connector_state * conn_state)1172ede9771dSVille Syrjälä static void gen11_dsi_pre_pll_enable(struct intel_atomic_state *state,
1173ede9771dSVille Syrjälä 				     struct intel_encoder *encoder,
117404865139SJani Nikula 				     const struct intel_crtc_state *crtc_state,
1175379bc100SJani Nikula 				     const struct drm_connector_state *conn_state)
1176379bc100SJani Nikula {
117786ecd3b3SVille Syrjälä 	struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
117886ecd3b3SVille Syrjälä 
1179201963a8SVille Syrjälä 	intel_dsi_wait_panel_power_cycle(intel_dsi);
1180201963a8SVille Syrjälä 
118186ecd3b3SVille Syrjälä 	intel_dsi_vbt_exec_sequence(intel_dsi, MIPI_SEQ_POWER_ON);
118286ecd3b3SVille Syrjälä 	msleep(intel_dsi->panel_on_delay);
118386ecd3b3SVille Syrjälä 	intel_dsi_vbt_exec_sequence(intel_dsi, MIPI_SEQ_DEASSERT_RESET);
118486ecd3b3SVille Syrjälä 
1185379bc100SJani Nikula 	/* step2: enable IO power */
1186379bc100SJani Nikula 	gen11_dsi_enable_io_power(encoder);
1187379bc100SJani Nikula 
1188379bc100SJani Nikula 	/* step3: enable DSI PLL */
118904865139SJani Nikula 	gen11_dsi_program_esc_clk_div(encoder, crtc_state);
1190379bc100SJani Nikula }
1191379bc100SJani Nikula 
gen11_dsi_pre_enable(struct intel_atomic_state * state,struct intel_encoder * encoder,const struct intel_crtc_state * pipe_config,const struct drm_connector_state * conn_state)1192ede9771dSVille Syrjälä static void gen11_dsi_pre_enable(struct intel_atomic_state *state,
1193ede9771dSVille Syrjälä 				 struct intel_encoder *encoder,
1194379bc100SJani Nikula 				 const struct intel_crtc_state *pipe_config,
1195379bc100SJani Nikula 				 const struct drm_connector_state *conn_state)
1196379bc100SJani Nikula {
1197379bc100SJani Nikula 	/* step3b */
1198379bc100SJani Nikula 	gen11_dsi_map_pll(encoder, pipe_config);
1199379bc100SJani Nikula 
1200379bc100SJani Nikula 	/* step4: enable DSI port and DPHY */
1201379bc100SJani Nikula 	gen11_dsi_enable_port_and_phy(encoder, pipe_config);
1202379bc100SJani Nikula 
1203379bc100SJani Nikula 	/* step5: program and powerup panel */
1204379bc100SJani Nikula 	gen11_dsi_powerup_panel(encoder);
1205379bc100SJani Nikula 
12063126977dSVille Syrjälä 	intel_dsc_dsi_pps_write(encoder, pipe_config);
12073126977dSVille Syrjälä 
1208379bc100SJani Nikula 	/* step6c: configure transcoder timings */
1209379bc100SJani Nikula 	gen11_dsi_set_transcoder_timings(encoder, pipe_config);
1210379bc100SJani Nikula }
1211379bc100SJani Nikula 
1212544021e3STejas Upadhyay /*
1213544021e3STejas Upadhyay  * Wa_1409054076:icl,jsl,ehl
1214544021e3STejas Upadhyay  * When pipe A is disabled and MIPI DSI is enabled on pipe B,
1215544021e3STejas Upadhyay  * the AMT KVMR feature will incorrectly see pipe A as enabled.
1216544021e3STejas Upadhyay  * Set 0x42080 bit 23=1 before enabling DSI on pipe B and leave
1217544021e3STejas Upadhyay  * it set while DSI is enabled on pipe B
1218544021e3STejas Upadhyay  */
icl_apply_kvmr_pipe_a_wa(struct intel_encoder * encoder,enum pipe pipe,bool enable)1219544021e3STejas Upadhyay static void icl_apply_kvmr_pipe_a_wa(struct intel_encoder *encoder,
1220544021e3STejas Upadhyay 				     enum pipe pipe, bool enable)
1221544021e3STejas Upadhyay {
1222544021e3STejas Upadhyay 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
1223544021e3STejas Upadhyay 
1224544021e3STejas Upadhyay 	if (DISPLAY_VER(dev_priv) == 11 && pipe == PIPE_B)
1225544021e3STejas Upadhyay 		intel_de_rmw(dev_priv, CHICKEN_PAR1_1,
1226544021e3STejas Upadhyay 			     IGNORE_KVMR_PIPE_A,
1227544021e3STejas Upadhyay 			     enable ? IGNORE_KVMR_PIPE_A : 0);
1228544021e3STejas Upadhyay }
1229f87c46c4SVandita Kulkarni 
1230f87c46c4SVandita Kulkarni /*
1231f87c46c4SVandita Kulkarni  * Wa_16012360555:adl-p
1232f87c46c4SVandita Kulkarni  * SW will have to program the "LP to HS Wakeup Guardband"
1233f87c46c4SVandita Kulkarni  * to account for the repeaters on the HS Request/Ready
1234f87c46c4SVandita Kulkarni  * PPI signaling between the Display engine and the DPHY.
1235f87c46c4SVandita Kulkarni  */
adlp_set_lp_hs_wakeup_gb(struct intel_encoder * encoder)1236f87c46c4SVandita Kulkarni static void adlp_set_lp_hs_wakeup_gb(struct intel_encoder *encoder)
1237f87c46c4SVandita Kulkarni {
1238f87c46c4SVandita Kulkarni 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
1239f87c46c4SVandita Kulkarni 	struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
1240f87c46c4SVandita Kulkarni 	enum port port;
1241f87c46c4SVandita Kulkarni 
1242f87c46c4SVandita Kulkarni 	if (DISPLAY_VER(i915) == 13) {
1243f87c46c4SVandita Kulkarni 		for_each_dsi_port(port, intel_dsi->ports)
1244f87c46c4SVandita Kulkarni 			intel_de_rmw(i915, TGL_DSI_CHKN_REG(port),
12456f07707fSVandita Kulkarni 				     TGL_DSI_CHKN_LSHS_GB_MASK,
12466f07707fSVandita Kulkarni 				     TGL_DSI_CHKN_LSHS_GB(4));
1247f87c46c4SVandita Kulkarni 	}
1248f87c46c4SVandita Kulkarni }
1249f87c46c4SVandita Kulkarni 
gen11_dsi_enable(struct intel_atomic_state * state,struct intel_encoder * encoder,const struct intel_crtc_state * crtc_state,const struct drm_connector_state * conn_state)1250ede9771dSVille Syrjälä static void gen11_dsi_enable(struct intel_atomic_state *state,
1251ede9771dSVille Syrjälä 			     struct intel_encoder *encoder,
125221fd23acSJani Nikula 			     const struct intel_crtc_state *crtc_state,
125321fd23acSJani Nikula 			     const struct drm_connector_state *conn_state)
125421fd23acSJani Nikula {
125587e9bb49SVandita Kulkarni 	struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
12563d41ec41SVille Syrjälä 	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
125787e9bb49SVandita Kulkarni 
1258544021e3STejas Upadhyay 	/* Wa_1409054076:icl,jsl,ehl */
1259544021e3STejas Upadhyay 	icl_apply_kvmr_pipe_a_wa(encoder, crtc->pipe, true);
1260544021e3STejas Upadhyay 
1261f87c46c4SVandita Kulkarni 	/* Wa_16012360555:adl-p */
1262f87c46c4SVandita Kulkarni 	adlp_set_lp_hs_wakeup_gb(encoder);
1263f87c46c4SVandita Kulkarni 
126487e9bb49SVandita Kulkarni 	/* step6d: enable dsi transcoder */
126587e9bb49SVandita Kulkarni 	gen11_dsi_enable_transcoder(encoder);
126687e9bb49SVandita Kulkarni 
126794ae4612SVille Syrjälä 	intel_dsi_vbt_exec_sequence(intel_dsi, MIPI_SEQ_DISPLAY_ON);
126894ae4612SVille Syrjälä 
126987e9bb49SVandita Kulkarni 	/* step7: enable backlight */
1270c0a52f8bSJani Nikula 	intel_backlight_enable(crtc_state, conn_state);
127187e9bb49SVandita Kulkarni 	intel_dsi_vbt_exec_sequence(intel_dsi, MIPI_SEQ_BACKLIGHT_ON);
127287e9bb49SVandita Kulkarni 
127321fd23acSJani Nikula 	intel_crtc_vblank_on(crtc_state);
127421fd23acSJani Nikula }
127521fd23acSJani Nikula 
gen11_dsi_disable_transcoder(struct intel_encoder * encoder)1276379bc100SJani Nikula static void gen11_dsi_disable_transcoder(struct intel_encoder *encoder)
1277379bc100SJani Nikula {
1278379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
1279b7d02c3aSVille Syrjälä 	struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
1280379bc100SJani Nikula 	enum port port;
1281379bc100SJani Nikula 	enum transcoder dsi_trans;
1282379bc100SJani Nikula 
1283379bc100SJani Nikula 	for_each_dsi_port(port, intel_dsi->ports) {
1284379bc100SJani Nikula 		dsi_trans = dsi_port_to_transcoder(port);
1285379bc100SJani Nikula 
1286379bc100SJani Nikula 		/* disable transcoder */
1287984b61c3SJani Nikula 		intel_de_rmw(dev_priv, TRANSCONF(dev_priv, dsi_trans),
1288984b61c3SJani Nikula 			     TRANSCONF_ENABLE, 0);
1289379bc100SJani Nikula 
1290379bc100SJani Nikula 		/* wait for transcoder to be disabled */
1291984b61c3SJani Nikula 		if (intel_de_wait_for_clear(dev_priv, TRANSCONF(dev_priv, dsi_trans),
12923eb08ea5SVille Syrjälä 					    TRANSCONF_STATE_ENABLE, 50))
1293b5280cd0SWambui Karuga 			drm_err(&dev_priv->drm,
1294b5280cd0SWambui Karuga 				"DSI trancoder not disabled\n");
1295379bc100SJani Nikula 	}
1296379bc100SJani Nikula }
1297379bc100SJani Nikula 
gen11_dsi_powerdown_panel(struct intel_encoder * encoder)1298379bc100SJani Nikula static void gen11_dsi_powerdown_panel(struct intel_encoder *encoder)
1299379bc100SJani Nikula {
1300b7d02c3aSVille Syrjälä 	struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
1301379bc100SJani Nikula 
1302379bc100SJani Nikula 	intel_dsi_vbt_exec_sequence(intel_dsi, MIPI_SEQ_DISPLAY_OFF);
1303201963a8SVille Syrjälä 
1304379bc100SJani Nikula 	/* ensure cmds dispatched to panel */
1305379bc100SJani Nikula 	wait_for_cmds_dispatched_to_panel(encoder);
1306379bc100SJani Nikula }
1307379bc100SJani Nikula 
gen11_dsi_deconfigure_trancoder(struct intel_encoder * encoder)1308379bc100SJani Nikula static void gen11_dsi_deconfigure_trancoder(struct intel_encoder *encoder)
1309379bc100SJani Nikula {
1310379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
1311b7d02c3aSVille Syrjälä 	struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
1312379bc100SJani Nikula 	enum port port;
1313379bc100SJani Nikula 	enum transcoder dsi_trans;
1314379bc100SJani Nikula 	u32 tmp;
1315379bc100SJani Nikula 
1316b4b95b05SVandita Kulkarni 	/* disable periodic update mode */
1317b4b95b05SVandita Kulkarni 	if (is_cmd_mode(intel_dsi)) {
13181a45d681SAndrzej Hajda 		for_each_dsi_port(port, intel_dsi->ports)
13191a45d681SAndrzej Hajda 			intel_de_rmw(dev_priv, DSI_CMD_FRMCTL(port),
13201a45d681SAndrzej Hajda 				     DSI_PERIODIC_FRAME_UPDATE_ENABLE, 0);
1321b4b95b05SVandita Kulkarni 	}
1322b4b95b05SVandita Kulkarni 
1323379bc100SJani Nikula 	/* put dsi link in ULPS */
1324379bc100SJani Nikula 	for_each_dsi_port(port, intel_dsi->ports) {
1325379bc100SJani Nikula 		dsi_trans = dsi_port_to_transcoder(port);
13261c63f6dfSJani Nikula 		tmp = intel_de_read(dev_priv, DSI_LP_MSG(dsi_trans));
1327379bc100SJani Nikula 		tmp |= LINK_ENTER_ULPS;
1328379bc100SJani Nikula 		tmp &= ~LINK_ULPS_TYPE_LP11;
13291c63f6dfSJani Nikula 		intel_de_write(dev_priv, DSI_LP_MSG(dsi_trans), tmp);
1330379bc100SJani Nikula 
13311c63f6dfSJani Nikula 		if (wait_for_us((intel_de_read(dev_priv, DSI_LP_MSG(dsi_trans)) &
1332379bc100SJani Nikula 				 LINK_IN_ULPS),
1333379bc100SJani Nikula 				10))
1334b5280cd0SWambui Karuga 			drm_err(&dev_priv->drm, "DSI link not in ULPS\n");
1335379bc100SJani Nikula 	}
1336379bc100SJani Nikula 
1337379bc100SJani Nikula 	/* disable ddi function */
1338379bc100SJani Nikula 	for_each_dsi_port(port, intel_dsi->ports) {
1339379bc100SJani Nikula 		dsi_trans = dsi_port_to_transcoder(port);
1340b092d6adSJani Nikula 		intel_de_rmw(dev_priv,
1341b092d6adSJani Nikula 			     TRANS_DDI_FUNC_CTL(dev_priv, dsi_trans),
13421a45d681SAndrzej Hajda 			     TRANS_DDI_FUNC_ENABLE, 0);
1343379bc100SJani Nikula 	}
1344379bc100SJani Nikula 
1345379bc100SJani Nikula 	/* disable port sync mode if dual link */
1346379bc100SJani Nikula 	if (intel_dsi->dual_link) {
1347379bc100SJani Nikula 		for_each_dsi_port(port, intel_dsi->ports) {
1348379bc100SJani Nikula 			dsi_trans = dsi_port_to_transcoder(port);
134976f1b2b1SJani Nikula 			intel_de_rmw(dev_priv,
135076f1b2b1SJani Nikula 				     TRANS_DDI_FUNC_CTL2(dev_priv, dsi_trans),
13511a45d681SAndrzej Hajda 				     PORT_SYNC_MODE_ENABLE, 0);
1352379bc100SJani Nikula 		}
1353379bc100SJani Nikula 	}
1354379bc100SJani Nikula }
1355379bc100SJani Nikula 
gen11_dsi_disable_port(struct intel_encoder * encoder)1356379bc100SJani Nikula static void gen11_dsi_disable_port(struct intel_encoder *encoder)
1357379bc100SJani Nikula {
1358379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
1359b7d02c3aSVille Syrjälä 	struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
1360379bc100SJani Nikula 	enum port port;
1361379bc100SJani Nikula 
1362379bc100SJani Nikula 	gen11_dsi_ungate_clocks(encoder);
1363379bc100SJani Nikula 	for_each_dsi_port(port, intel_dsi->ports) {
13641a45d681SAndrzej Hajda 		intel_de_rmw(dev_priv, DDI_BUF_CTL(port), DDI_BUF_CTL_ENABLE, 0);
1365379bc100SJani Nikula 
13661c63f6dfSJani Nikula 		if (wait_for_us((intel_de_read(dev_priv, DDI_BUF_CTL(port)) &
1367379bc100SJani Nikula 				 DDI_BUF_IS_IDLE),
1368379bc100SJani Nikula 				 8))
1369b5280cd0SWambui Karuga 			drm_err(&dev_priv->drm,
1370b5280cd0SWambui Karuga 				"DDI port:%c buffer not idle\n",
1371379bc100SJani Nikula 				port_name(port));
1372379bc100SJani Nikula 	}
1373379bc100SJani Nikula 	gen11_dsi_gate_clocks(encoder);
1374379bc100SJani Nikula }
1375379bc100SJani Nikula 
gen11_dsi_disable_io_power(struct intel_encoder * encoder)1376379bc100SJani Nikula static void gen11_dsi_disable_io_power(struct intel_encoder *encoder)
1377379bc100SJani Nikula {
1378379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
1379b7d02c3aSVille Syrjälä 	struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
1380379bc100SJani Nikula 	enum port port;
1381379bc100SJani Nikula 
1382379bc100SJani Nikula 	for_each_dsi_port(port, intel_dsi->ports) {
1383379bc100SJani Nikula 		intel_wakeref_t wakeref;
1384379bc100SJani Nikula 
1385379bc100SJani Nikula 		wakeref = fetch_and_zero(&intel_dsi->io_wakeref[port]);
1386379bc100SJani Nikula 		intel_display_power_put(dev_priv,
1387379bc100SJani Nikula 					port == PORT_A ?
13880ba2661dSImre Deak 					POWER_DOMAIN_PORT_DDI_IO_A :
13890ba2661dSImre Deak 					POWER_DOMAIN_PORT_DDI_IO_B,
1390379bc100SJani Nikula 					wakeref);
1391379bc100SJani Nikula 	}
1392379bc100SJani Nikula 
1393379bc100SJani Nikula 	/* set mode to DDI */
13941a45d681SAndrzej Hajda 	for_each_dsi_port(port, intel_dsi->ports)
13951a45d681SAndrzej Hajda 		intel_de_rmw(dev_priv, ICL_DSI_IO_MODECTL(port),
13961a45d681SAndrzej Hajda 			     COMBO_PHY_MODE_DSI, 0);
1397379bc100SJani Nikula }
1398379bc100SJani Nikula 
gen11_dsi_disable(struct intel_atomic_state * state,struct intel_encoder * encoder,const struct intel_crtc_state * old_crtc_state,const struct drm_connector_state * old_conn_state)1399ede9771dSVille Syrjälä static void gen11_dsi_disable(struct intel_atomic_state *state,
1400ede9771dSVille Syrjälä 			      struct intel_encoder *encoder,
1401379bc100SJani Nikula 			      const struct intel_crtc_state *old_crtc_state,
1402379bc100SJani Nikula 			      const struct drm_connector_state *old_conn_state)
1403379bc100SJani Nikula {
1404b7d02c3aSVille Syrjälä 	struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
1405379bc100SJani Nikula 
1406379bc100SJani Nikula 	/* step1: turn off backlight */
1407379bc100SJani Nikula 	intel_dsi_vbt_exec_sequence(intel_dsi, MIPI_SEQ_BACKLIGHT_OFF);
1408c0a52f8bSJani Nikula 	intel_backlight_disable(old_conn_state);
1409a57aa1e3SVille Syrjälä }
1410a57aa1e3SVille Syrjälä 
gen11_dsi_post_disable(struct intel_atomic_state * state,struct intel_encoder * encoder,const struct intel_crtc_state * old_crtc_state,const struct drm_connector_state * old_conn_state)1411a57aa1e3SVille Syrjälä static void gen11_dsi_post_disable(struct intel_atomic_state *state,
1412a57aa1e3SVille Syrjälä 				   struct intel_encoder *encoder,
1413a57aa1e3SVille Syrjälä 				   const struct intel_crtc_state *old_crtc_state,
1414a57aa1e3SVille Syrjälä 				   const struct drm_connector_state *old_conn_state)
1415a57aa1e3SVille Syrjälä {
14165263a63cSVille Syrjälä 	struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
14173d41ec41SVille Syrjälä 	struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc);
1418a57aa1e3SVille Syrjälä 
1419a57aa1e3SVille Syrjälä 	intel_crtc_vblank_off(old_crtc_state);
1420379bc100SJani Nikula 
1421379bc100SJani Nikula 	/* step2d,e: disable transcoder and wait */
1422379bc100SJani Nikula 	gen11_dsi_disable_transcoder(encoder);
1423379bc100SJani Nikula 
1424544021e3STejas Upadhyay 	/* Wa_1409054076:icl,jsl,ehl */
1425544021e3STejas Upadhyay 	icl_apply_kvmr_pipe_a_wa(encoder, crtc->pipe, false);
1426544021e3STejas Upadhyay 
1427379bc100SJani Nikula 	/* step2f,g: powerdown panel */
1428379bc100SJani Nikula 	gen11_dsi_powerdown_panel(encoder);
1429379bc100SJani Nikula 
1430379bc100SJani Nikula 	/* step2h,i,j: deconfig trancoder */
1431379bc100SJani Nikula 	gen11_dsi_deconfigure_trancoder(encoder);
1432379bc100SJani Nikula 
143329428c85SVille Syrjälä 	intel_dsc_disable(old_crtc_state);
143429428c85SVille Syrjälä 	skl_scaler_disable(old_crtc_state);
143529428c85SVille Syrjälä 
1436379bc100SJani Nikula 	/* step3: disable port */
1437379bc100SJani Nikula 	gen11_dsi_disable_port(encoder);
1438379bc100SJani Nikula 
1439b4b95b05SVandita Kulkarni 	gen11_dsi_config_util_pin(encoder, false);
1440b4b95b05SVandita Kulkarni 
1441379bc100SJani Nikula 	/* step4: disable IO power */
1442379bc100SJani Nikula 	gen11_dsi_disable_io_power(encoder);
14435263a63cSVille Syrjälä 
14445263a63cSVille Syrjälä 	intel_dsi_vbt_exec_sequence(intel_dsi, MIPI_SEQ_ASSERT_RESET);
14455263a63cSVille Syrjälä 
14465263a63cSVille Syrjälä 	msleep(intel_dsi->panel_off_delay);
14475263a63cSVille Syrjälä 	intel_dsi_vbt_exec_sequence(intel_dsi, MIPI_SEQ_POWER_OFF);
14485263a63cSVille Syrjälä 
14495263a63cSVille Syrjälä 	intel_dsi->panel_power_off_time = ktime_get_boottime();
1450773b4b54SVille Syrjälä }
1451773b4b54SVille Syrjälä 
gen11_dsi_mode_valid(struct drm_connector * connector,struct drm_display_mode * mode)14522b68392eSJani Nikula static enum drm_mode_status gen11_dsi_mode_valid(struct drm_connector *connector,
14532b68392eSJani Nikula 						 struct drm_display_mode *mode)
14542b68392eSJani Nikula {
1455e0ef2daaSVille Syrjälä 	struct drm_i915_private *i915 = to_i915(connector->dev);
1456e0ef2daaSVille Syrjälä 	enum drm_mode_status status;
1457e0ef2daaSVille Syrjälä 
1458e0ef2daaSVille Syrjälä 	status = intel_cpu_transcoder_mode_valid(i915, mode);
1459e0ef2daaSVille Syrjälä 	if (status != MODE_OK)
1460e0ef2daaSVille Syrjälä 		return status;
1461e0ef2daaSVille Syrjälä 
14622b68392eSJani Nikula 	/* FIXME: DSC? */
14632b68392eSJani Nikula 	return intel_dsi_mode_valid(connector, mode);
14642b68392eSJani Nikula }
14652b68392eSJani Nikula 
gen11_dsi_get_timings(struct intel_encoder * encoder,struct intel_crtc_state * pipe_config)1466379bc100SJani Nikula static void gen11_dsi_get_timings(struct intel_encoder *encoder,
1467379bc100SJani Nikula 				  struct intel_crtc_state *pipe_config)
1468379bc100SJani Nikula {
1469b7d02c3aSVille Syrjälä 	struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
1470379bc100SJani Nikula 	struct drm_display_mode *adjusted_mode =
14711326a92cSMaarten Lankhorst 					&pipe_config->hw.adjusted_mode;
1472379bc100SJani Nikula 
147359a266f0SAnkit Nautiyal 	if (pipe_config->dsc.compressed_bpp_x16) {
14748466a141SImre Deak 		int div = fxp_q4_to_int(pipe_config->dsc.compressed_bpp_x16);
1475c2bb35e9SVandita Kulkarni 		int mul = mipi_dsi_pixel_format_to_bpp(intel_dsi->pixel_format);
1476c2bb35e9SVandita Kulkarni 
1477c2bb35e9SVandita Kulkarni 		adjusted_mode->crtc_htotal =
1478c2bb35e9SVandita Kulkarni 			DIV_ROUND_UP(adjusted_mode->crtc_htotal * mul, div);
1479c2bb35e9SVandita Kulkarni 		adjusted_mode->crtc_hsync_start =
1480c2bb35e9SVandita Kulkarni 			DIV_ROUND_UP(adjusted_mode->crtc_hsync_start * mul, div);
1481c2bb35e9SVandita Kulkarni 		adjusted_mode->crtc_hsync_end =
1482c2bb35e9SVandita Kulkarni 			DIV_ROUND_UP(adjusted_mode->crtc_hsync_end * mul, div);
1483c2bb35e9SVandita Kulkarni 	}
1484c2bb35e9SVandita Kulkarni 
1485379bc100SJani Nikula 	if (intel_dsi->dual_link) {
1486379bc100SJani Nikula 		adjusted_mode->crtc_hdisplay *= 2;
1487379bc100SJani Nikula 		if (intel_dsi->dual_link == DSI_DUAL_LINK_FRONT_BACK)
1488379bc100SJani Nikula 			adjusted_mode->crtc_hdisplay -=
1489379bc100SJani Nikula 						intel_dsi->pixel_overlap;
1490379bc100SJani Nikula 		adjusted_mode->crtc_htotal *= 2;
1491379bc100SJani Nikula 	}
1492379bc100SJani Nikula 	adjusted_mode->crtc_hblank_start = adjusted_mode->crtc_hdisplay;
1493379bc100SJani Nikula 	adjusted_mode->crtc_hblank_end = adjusted_mode->crtc_htotal;
1494379bc100SJani Nikula 
1495379bc100SJani Nikula 	if (intel_dsi->operation_mode == INTEL_DSI_VIDEO_MODE) {
1496379bc100SJani Nikula 		if (intel_dsi->dual_link) {
1497379bc100SJani Nikula 			adjusted_mode->crtc_hsync_start *= 2;
1498379bc100SJani Nikula 			adjusted_mode->crtc_hsync_end *= 2;
1499379bc100SJani Nikula 		}
1500379bc100SJani Nikula 	}
1501379bc100SJani Nikula 	adjusted_mode->crtc_vblank_start = adjusted_mode->crtc_vdisplay;
1502379bc100SJani Nikula 	adjusted_mode->crtc_vblank_end = adjusted_mode->crtc_vtotal;
1503379bc100SJani Nikula }
1504379bc100SJani Nikula 
gen11_dsi_is_periodic_cmd_mode(struct intel_dsi * intel_dsi)1505cebb28acSVandita Kulkarni static bool gen11_dsi_is_periodic_cmd_mode(struct intel_dsi *intel_dsi)
1506cebb28acSVandita Kulkarni {
1507cebb28acSVandita Kulkarni 	struct drm_device *dev = intel_dsi->base.base.dev;
1508cebb28acSVandita Kulkarni 	struct drm_i915_private *dev_priv = to_i915(dev);
1509cebb28acSVandita Kulkarni 	enum transcoder dsi_trans;
1510cebb28acSVandita Kulkarni 	u32 val;
1511cebb28acSVandita Kulkarni 
1512cebb28acSVandita Kulkarni 	if (intel_dsi->ports == BIT(PORT_B))
1513cebb28acSVandita Kulkarni 		dsi_trans = TRANSCODER_DSI_1;
1514cebb28acSVandita Kulkarni 	else
1515cebb28acSVandita Kulkarni 		dsi_trans = TRANSCODER_DSI_0;
1516cebb28acSVandita Kulkarni 
1517cebb28acSVandita Kulkarni 	val = intel_de_read(dev_priv, DSI_TRANS_FUNC_CONF(dsi_trans));
1518cebb28acSVandita Kulkarni 	return (val & DSI_PERIODIC_FRAME_UPDATE_ENABLE);
1519cebb28acSVandita Kulkarni }
1520cebb28acSVandita Kulkarni 
gen11_dsi_get_cmd_mode_config(struct intel_dsi * intel_dsi,struct intel_crtc_state * pipe_config)15215682a41fSVandita Kulkarni static void gen11_dsi_get_cmd_mode_config(struct intel_dsi *intel_dsi,
15225682a41fSVandita Kulkarni 					  struct intel_crtc_state *pipe_config)
15235682a41fSVandita Kulkarni {
15245682a41fSVandita Kulkarni 	if (intel_dsi->ports == (BIT(PORT_B) | BIT(PORT_A)))
15255682a41fSVandita Kulkarni 		pipe_config->mode_flags |= I915_MODE_FLAG_DSI_USE_TE1 |
15265682a41fSVandita Kulkarni 					    I915_MODE_FLAG_DSI_USE_TE0;
15275682a41fSVandita Kulkarni 	else if (intel_dsi->ports == BIT(PORT_B))
15285682a41fSVandita Kulkarni 		pipe_config->mode_flags |= I915_MODE_FLAG_DSI_USE_TE1;
15295682a41fSVandita Kulkarni 	else
15305682a41fSVandita Kulkarni 		pipe_config->mode_flags |= I915_MODE_FLAG_DSI_USE_TE0;
15315682a41fSVandita Kulkarni }
15325682a41fSVandita Kulkarni 
gen11_dsi_get_config(struct intel_encoder * encoder,struct intel_crtc_state * pipe_config)1533379bc100SJani Nikula static void gen11_dsi_get_config(struct intel_encoder *encoder,
1534379bc100SJani Nikula 				 struct intel_crtc_state *pipe_config)
1535379bc100SJani Nikula {
15362225f3c6SMaarten Lankhorst 	struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);
1537b7d02c3aSVille Syrjälä 	struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
1538379bc100SJani Nikula 
1539351221ffSVille Syrjälä 	intel_ddi_get_clock(encoder, pipe_config, icl_ddi_combo_get_pll(encoder));
1540379bc100SJani Nikula 
15411326a92cSMaarten Lankhorst 	pipe_config->hw.adjusted_mode.crtc_clock = intel_dsi->pclk;
1542379bc100SJani Nikula 	if (intel_dsi->dual_link)
15431326a92cSMaarten Lankhorst 		pipe_config->hw.adjusted_mode.crtc_clock *= 2;
1544379bc100SJani Nikula 
1545379bc100SJani Nikula 	gen11_dsi_get_timings(encoder, pipe_config);
1546379bc100SJani Nikula 	pipe_config->output_types |= BIT(INTEL_OUTPUT_DSI);
1547c640f6c5SVille Syrjälä 	pipe_config->pipe_bpp = bdw_get_pipe_misc_bpp(crtc);
1548cebb28acSVandita Kulkarni 
15495682a41fSVandita Kulkarni 	/* Get the details on which TE should be enabled */
15505682a41fSVandita Kulkarni 	if (is_cmd_mode(intel_dsi))
15515682a41fSVandita Kulkarni 		gen11_dsi_get_cmd_mode_config(intel_dsi, pipe_config);
15525682a41fSVandita Kulkarni 
1553cebb28acSVandita Kulkarni 	if (gen11_dsi_is_periodic_cmd_mode(intel_dsi))
1554af157b76SVille Syrjälä 		pipe_config->mode_flags |= I915_MODE_FLAG_DSI_PERIODIC_CMD_MODE;
1555379bc100SJani Nikula }
1556379bc100SJani Nikula 
gen11_dsi_sync_state(struct intel_encoder * encoder,const struct intel_crtc_state * crtc_state)1557544021e3STejas Upadhyay static void gen11_dsi_sync_state(struct intel_encoder *encoder,
1558544021e3STejas Upadhyay 				 const struct intel_crtc_state *crtc_state)
1559544021e3STejas Upadhyay {
1560544021e3STejas Upadhyay 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
15617194dc99SImre Deak 	struct intel_crtc *intel_crtc;
15627194dc99SImre Deak 	enum pipe pipe;
15637194dc99SImre Deak 
15647194dc99SImre Deak 	if (!crtc_state)
15657194dc99SImre Deak 		return;
15667194dc99SImre Deak 
15677194dc99SImre Deak 	intel_crtc = to_intel_crtc(crtc_state->uapi.crtc);
15687194dc99SImre Deak 	pipe = intel_crtc->pipe;
1569544021e3STejas Upadhyay 
1570544021e3STejas Upadhyay 	/* wa verify 1409054076:icl,jsl,ehl */
1571544021e3STejas Upadhyay 	if (DISPLAY_VER(dev_priv) == 11 && pipe == PIPE_B &&
1572544021e3STejas Upadhyay 	    !(intel_de_read(dev_priv, CHICKEN_PAR1_1) & IGNORE_KVMR_PIPE_A))
1573544021e3STejas Upadhyay 		drm_dbg_kms(&dev_priv->drm,
1574544021e3STejas Upadhyay 			    "[ENCODER:%d:%s] BIOS left IGNORE_KVMR_PIPE_A cleared with pipe B enabled\n",
1575544021e3STejas Upadhyay 			    encoder->base.base.id,
1576544021e3STejas Upadhyay 			    encoder->base.name);
1577544021e3STejas Upadhyay }
1578544021e3STejas Upadhyay 
gen11_dsi_dsc_compute_config(struct intel_encoder * encoder,struct intel_crtc_state * crtc_state)15792b68392eSJani Nikula static int gen11_dsi_dsc_compute_config(struct intel_encoder *encoder,
15802b68392eSJani Nikula 					struct intel_crtc_state *crtc_state)
15812b68392eSJani Nikula {
15822b68392eSJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
15832b68392eSJani Nikula 	struct drm_dsc_config *vdsc_cfg = &crtc_state->dsc.config;
1584005e9537SMatt Roper 	int dsc_max_bpc = DISPLAY_VER(dev_priv) >= 12 ? 12 : 10;
15852b68392eSJani Nikula 	bool use_dsc;
15862b68392eSJani Nikula 	int ret;
15872b68392eSJani Nikula 
15882b68392eSJani Nikula 	use_dsc = intel_bios_get_dsc_params(encoder, crtc_state, dsc_max_bpc);
15892b68392eSJani Nikula 	if (!use_dsc)
15902b68392eSJani Nikula 		return 0;
15912b68392eSJani Nikula 
15922b68392eSJani Nikula 	if (crtc_state->pipe_bpp < 8 * 3)
15932b68392eSJani Nikula 		return -EINVAL;
15942b68392eSJani Nikula 
15952b68392eSJani Nikula 	/* FIXME: split only when necessary */
15962b68392eSJani Nikula 	if (crtc_state->dsc.slice_count > 1)
15972b68392eSJani Nikula 		crtc_state->dsc.dsc_split = true;
15982b68392eSJani Nikula 
1599420798a0SJani Nikula 	/* FIXME: initialize from VBT */
1600420798a0SJani Nikula 	vdsc_cfg->rc_model_size = DSC_RC_MODEL_SIZE_CONST;
1601420798a0SJani Nikula 
1602e72df53dSAnkit Nautiyal 	vdsc_cfg->pic_height = crtc_state->hw.adjusted_mode.crtc_vdisplay;
1603e72df53dSAnkit Nautiyal 
16043126977dSVille Syrjälä 	ret = intel_dsc_compute_params(crtc_state);
16052b68392eSJani Nikula 	if (ret)
16062b68392eSJani Nikula 		return ret;
16072b68392eSJani Nikula 
16082b68392eSJani Nikula 	/* DSI specific sanity checks on the common code */
16093dbe5e11SPankaj Bharadiya 	drm_WARN_ON(&dev_priv->drm, vdsc_cfg->vbr_enable);
16103dbe5e11SPankaj Bharadiya 	drm_WARN_ON(&dev_priv->drm, vdsc_cfg->simple_422);
16113dbe5e11SPankaj Bharadiya 	drm_WARN_ON(&dev_priv->drm,
16123dbe5e11SPankaj Bharadiya 		    vdsc_cfg->pic_width % vdsc_cfg->slice_width);
16133dbe5e11SPankaj Bharadiya 	drm_WARN_ON(&dev_priv->drm, vdsc_cfg->slice_height < 8);
16143dbe5e11SPankaj Bharadiya 	drm_WARN_ON(&dev_priv->drm,
16153dbe5e11SPankaj Bharadiya 		    vdsc_cfg->pic_height % vdsc_cfg->slice_height);
16162b68392eSJani Nikula 
16172b68392eSJani Nikula 	ret = drm_dsc_compute_rc_parameters(vdsc_cfg);
16182b68392eSJani Nikula 	if (ret)
16192b68392eSJani Nikula 		return ret;
16202b68392eSJani Nikula 
16212b68392eSJani Nikula 	crtc_state->dsc.compression_enable = true;
16222b68392eSJani Nikula 
16232b68392eSJani Nikula 	return 0;
16242b68392eSJani Nikula }
16252b68392eSJani Nikula 
gen11_dsi_compute_config(struct intel_encoder * encoder,struct intel_crtc_state * pipe_config,struct drm_connector_state * conn_state)1626379bc100SJani Nikula static int gen11_dsi_compute_config(struct intel_encoder *encoder,
1627379bc100SJani Nikula 				    struct intel_crtc_state *pipe_config,
1628379bc100SJani Nikula 				    struct drm_connector_state *conn_state)
1629379bc100SJani Nikula {
1630dd10a80fSJani Nikula 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
16319eae5bacSVille Syrjälä 	struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
1632379bc100SJani Nikula 	struct intel_connector *intel_connector = intel_dsi->attached_connector;
1633379bc100SJani Nikula 	struct drm_display_mode *adjusted_mode =
16341326a92cSMaarten Lankhorst 		&pipe_config->hw.adjusted_mode;
1635d7ff281cSVille Syrjälä 	int ret;
1636379bc100SJani Nikula 
1637a04d27cdSAnkit Nautiyal 	pipe_config->sink_format = INTEL_OUTPUT_FORMAT_RGB;
1638379bc100SJani Nikula 	pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
1639cff4c2c6SVille Syrjälä 
1640cff4c2c6SVille Syrjälä 	ret = intel_panel_compute_config(intel_connector, adjusted_mode);
1641cff4c2c6SVille Syrjälä 	if (ret)
1642cff4c2c6SVille Syrjälä 		return ret;
1643d7ff281cSVille Syrjälä 
16444b93f49dSJani Nikula 	ret = intel_panel_fitting(pipe_config, conn_state);
1645d7ff281cSVille Syrjälä 	if (ret)
1646d7ff281cSVille Syrjälä 		return ret;
1647379bc100SJani Nikula 
1648379bc100SJani Nikula 	adjusted_mode->flags = 0;
1649379bc100SJani Nikula 
1650379bc100SJani Nikula 	/* Dual link goes to trancoder DSI'0' */
1651379bc100SJani Nikula 	if (intel_dsi->ports == BIT(PORT_B))
1652379bc100SJani Nikula 		pipe_config->cpu_transcoder = TRANSCODER_DSI_1;
1653379bc100SJani Nikula 	else
1654379bc100SJani Nikula 		pipe_config->cpu_transcoder = TRANSCODER_DSI_0;
1655379bc100SJani Nikula 
165650003bf5SJani Nikula 	if (intel_dsi->pixel_format == MIPI_DSI_FMT_RGB888)
165750003bf5SJani Nikula 		pipe_config->pipe_bpp = 24;
165850003bf5SJani Nikula 	else
165950003bf5SJani Nikula 		pipe_config->pipe_bpp = 18;
166050003bf5SJani Nikula 
1661379bc100SJani Nikula 	pipe_config->clock_set = true;
16622b68392eSJani Nikula 
16632b68392eSJani Nikula 	if (gen11_dsi_dsc_compute_config(encoder, pipe_config))
1664dd10a80fSJani Nikula 		drm_dbg_kms(&i915->drm, "Attempting to use DSC failed\n");
16652b68392eSJani Nikula 
166604865139SJani Nikula 	pipe_config->port_clock = afe_clk(encoder, pipe_config) / 5;
1667379bc100SJani Nikula 
1668f78a862dSVandita Kulkarni 	/*
1669f78a862dSVandita Kulkarni 	 * In case of TE GATE cmd mode, we
1670f78a862dSVandita Kulkarni 	 * receive TE from the slave if
1671f78a862dSVandita Kulkarni 	 * dual link is enabled
1672f78a862dSVandita Kulkarni 	 */
16735682a41fSVandita Kulkarni 	if (is_cmd_mode(intel_dsi))
16745682a41fSVandita Kulkarni 		gen11_dsi_get_cmd_mode_config(intel_dsi, pipe_config);
1675f78a862dSVandita Kulkarni 
1676379bc100SJani Nikula 	return 0;
1677379bc100SJani Nikula }
1678379bc100SJani Nikula 
gen11_dsi_get_power_domains(struct intel_encoder * encoder,struct intel_crtc_state * crtc_state)1679379bc100SJani Nikula static void gen11_dsi_get_power_domains(struct intel_encoder *encoder,
1680379bc100SJani Nikula 					struct intel_crtc_state *crtc_state)
1681379bc100SJani Nikula {
16822b68392eSJani Nikula 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
16832b68392eSJani Nikula 
1684b7d02c3aSVille Syrjälä 	get_dsi_io_power_domains(i915,
1685b7d02c3aSVille Syrjälä 				 enc_to_intel_dsi(encoder));
1686379bc100SJani Nikula }
1687379bc100SJani Nikula 
gen11_dsi_get_hw_state(struct intel_encoder * encoder,enum pipe * pipe)1688379bc100SJani Nikula static bool gen11_dsi_get_hw_state(struct intel_encoder *encoder,
1689379bc100SJani Nikula 				   enum pipe *pipe)
1690379bc100SJani Nikula {
1691379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
1692b7d02c3aSVille Syrjälä 	struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
1693379bc100SJani Nikula 	enum transcoder dsi_trans;
1694379bc100SJani Nikula 	intel_wakeref_t wakeref;
1695379bc100SJani Nikula 	enum port port;
1696379bc100SJani Nikula 	bool ret = false;
1697379bc100SJani Nikula 	u32 tmp;
1698379bc100SJani Nikula 
1699379bc100SJani Nikula 	wakeref = intel_display_power_get_if_enabled(dev_priv,
1700379bc100SJani Nikula 						     encoder->power_domain);
1701379bc100SJani Nikula 	if (!wakeref)
1702379bc100SJani Nikula 		return false;
1703379bc100SJani Nikula 
1704379bc100SJani Nikula 	for_each_dsi_port(port, intel_dsi->ports) {
1705379bc100SJani Nikula 		dsi_trans = dsi_port_to_transcoder(port);
1706b092d6adSJani Nikula 		tmp = intel_de_read(dev_priv,
1707b092d6adSJani Nikula 				    TRANS_DDI_FUNC_CTL(dev_priv, dsi_trans));
1708379bc100SJani Nikula 		switch (tmp & TRANS_DDI_EDP_INPUT_MASK) {
1709379bc100SJani Nikula 		case TRANS_DDI_EDP_INPUT_A_ON:
1710379bc100SJani Nikula 			*pipe = PIPE_A;
1711379bc100SJani Nikula 			break;
1712379bc100SJani Nikula 		case TRANS_DDI_EDP_INPUT_B_ONOFF:
1713379bc100SJani Nikula 			*pipe = PIPE_B;
1714379bc100SJani Nikula 			break;
1715379bc100SJani Nikula 		case TRANS_DDI_EDP_INPUT_C_ONOFF:
1716379bc100SJani Nikula 			*pipe = PIPE_C;
1717379bc100SJani Nikula 			break;
17184d89adc7SJosé Roberto de Souza 		case TRANS_DDI_EDP_INPUT_D_ONOFF:
17194d89adc7SJosé Roberto de Souza 			*pipe = PIPE_D;
17204d89adc7SJosé Roberto de Souza 			break;
1721379bc100SJani Nikula 		default:
1722b5280cd0SWambui Karuga 			drm_err(&dev_priv->drm, "Invalid PIPE input\n");
1723379bc100SJani Nikula 			goto out;
1724379bc100SJani Nikula 		}
1725379bc100SJani Nikula 
1726984b61c3SJani Nikula 		tmp = intel_de_read(dev_priv, TRANSCONF(dev_priv, dsi_trans));
17273eb08ea5SVille Syrjälä 		ret = tmp & TRANSCONF_ENABLE;
1728379bc100SJani Nikula 	}
1729379bc100SJani Nikula out:
1730379bc100SJani Nikula 	intel_display_power_put(dev_priv, encoder->power_domain, wakeref);
1731379bc100SJani Nikula 	return ret;
1732379bc100SJani Nikula }
1733379bc100SJani Nikula 
gen11_dsi_initial_fastset_check(struct intel_encoder * encoder,struct intel_crtc_state * crtc_state)1734b671d6efSImre Deak static bool gen11_dsi_initial_fastset_check(struct intel_encoder *encoder,
1735b671d6efSImre Deak 					    struct intel_crtc_state *crtc_state)
1736b671d6efSImre Deak {
1737b671d6efSImre Deak 	if (crtc_state->dsc.compression_enable) {
1738b671d6efSImre Deak 		drm_dbg_kms(encoder->base.dev, "Forcing full modeset due to DSC being enabled\n");
1739b671d6efSImre Deak 		crtc_state->uapi.mode_changed = true;
1740b671d6efSImre Deak 
1741b671d6efSImre Deak 		return false;
1742b671d6efSImre Deak 	}
1743b671d6efSImre Deak 
1744b671d6efSImre Deak 	return true;
1745b671d6efSImre Deak }
1746b671d6efSImre Deak 
gen11_dsi_encoder_destroy(struct drm_encoder * encoder)1747379bc100SJani Nikula static void gen11_dsi_encoder_destroy(struct drm_encoder *encoder)
1748379bc100SJani Nikula {
1749379bc100SJani Nikula 	intel_encoder_destroy(encoder);
1750379bc100SJani Nikula }
1751379bc100SJani Nikula 
1752379bc100SJani Nikula static const struct drm_encoder_funcs gen11_dsi_encoder_funcs = {
1753379bc100SJani Nikula 	.destroy = gen11_dsi_encoder_destroy,
1754379bc100SJani Nikula };
1755379bc100SJani Nikula 
1756379bc100SJani Nikula static const struct drm_connector_funcs gen11_dsi_connector_funcs = {
1757b81dddb9SVille Syrjälä 	.detect = intel_panel_detect,
1758379bc100SJani Nikula 	.late_register = intel_connector_register,
1759379bc100SJani Nikula 	.early_unregister = intel_connector_unregister,
1760379bc100SJani Nikula 	.destroy = intel_connector_destroy,
1761379bc100SJani Nikula 	.fill_modes = drm_helper_probe_single_connector_modes,
1762379bc100SJani Nikula 	.atomic_get_property = intel_digital_connector_atomic_get_property,
1763379bc100SJani Nikula 	.atomic_set_property = intel_digital_connector_atomic_set_property,
1764379bc100SJani Nikula 	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
1765379bc100SJani Nikula 	.atomic_duplicate_state = intel_digital_connector_duplicate_state,
1766379bc100SJani Nikula };
1767379bc100SJani Nikula 
1768379bc100SJani Nikula static const struct drm_connector_helper_funcs gen11_dsi_connector_helper_funcs = {
1769379bc100SJani Nikula 	.get_modes = intel_dsi_get_modes,
17702b68392eSJani Nikula 	.mode_valid = gen11_dsi_mode_valid,
1771379bc100SJani Nikula 	.atomic_check = intel_digital_connector_atomic_check,
1772379bc100SJani Nikula };
1773379bc100SJani Nikula 
gen11_dsi_host_attach(struct mipi_dsi_host * host,struct mipi_dsi_device * dsi)1774379bc100SJani Nikula static int gen11_dsi_host_attach(struct mipi_dsi_host *host,
1775379bc100SJani Nikula 				 struct mipi_dsi_device *dsi)
1776379bc100SJani Nikula {
1777379bc100SJani Nikula 	return 0;
1778379bc100SJani Nikula }
1779379bc100SJani Nikula 
gen11_dsi_host_detach(struct mipi_dsi_host * host,struct mipi_dsi_device * dsi)1780379bc100SJani Nikula static int gen11_dsi_host_detach(struct mipi_dsi_host *host,
1781379bc100SJani Nikula 				 struct mipi_dsi_device *dsi)
1782379bc100SJani Nikula {
1783379bc100SJani Nikula 	return 0;
1784379bc100SJani Nikula }
1785379bc100SJani Nikula 
gen11_dsi_host_transfer(struct mipi_dsi_host * host,const struct mipi_dsi_msg * msg)1786379bc100SJani Nikula static ssize_t gen11_dsi_host_transfer(struct mipi_dsi_host *host,
1787379bc100SJani Nikula 				       const struct mipi_dsi_msg *msg)
1788379bc100SJani Nikula {
1789379bc100SJani Nikula 	struct intel_dsi_host *intel_dsi_host = to_intel_dsi_host(host);
1790379bc100SJani Nikula 	struct mipi_dsi_packet dsi_pkt;
1791379bc100SJani Nikula 	ssize_t ret;
1792379bc100SJani Nikula 	bool enable_lpdt = false;
1793379bc100SJani Nikula 
1794379bc100SJani Nikula 	ret = mipi_dsi_create_packet(&dsi_pkt, msg);
1795379bc100SJani Nikula 	if (ret < 0)
1796379bc100SJani Nikula 		return ret;
1797379bc100SJani Nikula 
1798379bc100SJani Nikula 	if (msg->flags & MIPI_DSI_MSG_USE_LPM)
1799379bc100SJani Nikula 		enable_lpdt = true;
1800379bc100SJani Nikula 
1801379bc100SJani Nikula 	/* only long packet contains payload */
1802379bc100SJani Nikula 	if (mipi_dsi_packet_format_is_long(msg->type)) {
18033e2947cdSJani Nikula 		ret = dsi_send_pkt_payld(intel_dsi_host, &dsi_pkt);
1804379bc100SJani Nikula 		if (ret < 0)
1805379bc100SJani Nikula 			return ret;
1806379bc100SJani Nikula 	}
1807379bc100SJani Nikula 
18085ebd50d3SLee Shawn C 	/* send packet header */
18093e2947cdSJani Nikula 	ret  = dsi_send_pkt_hdr(intel_dsi_host, &dsi_pkt, enable_lpdt);
18105ebd50d3SLee Shawn C 	if (ret < 0)
18115ebd50d3SLee Shawn C 		return ret;
18125ebd50d3SLee Shawn C 
1813379bc100SJani Nikula 	//TODO: add payload receive code if needed
1814379bc100SJani Nikula 
1815379bc100SJani Nikula 	ret = sizeof(dsi_pkt.header) + dsi_pkt.payload_length;
1816379bc100SJani Nikula 
1817379bc100SJani Nikula 	return ret;
1818379bc100SJani Nikula }
1819379bc100SJani Nikula 
1820379bc100SJani Nikula static const struct mipi_dsi_host_ops gen11_dsi_host_ops = {
1821379bc100SJani Nikula 	.attach = gen11_dsi_host_attach,
1822379bc100SJani Nikula 	.detach = gen11_dsi_host_detach,
1823379bc100SJani Nikula 	.transfer = gen11_dsi_host_transfer,
1824379bc100SJani Nikula };
1825379bc100SJani Nikula 
1826379bc100SJani Nikula #define ICL_PREPARE_CNT_MAX	0x7
1827379bc100SJani Nikula #define ICL_CLK_ZERO_CNT_MAX	0xf
1828379bc100SJani Nikula #define ICL_TRAIL_CNT_MAX	0x7
1829379bc100SJani Nikula #define ICL_TCLK_PRE_CNT_MAX	0x3
1830379bc100SJani Nikula #define ICL_TCLK_POST_CNT_MAX	0x7
1831379bc100SJani Nikula #define ICL_HS_ZERO_CNT_MAX	0xf
1832379bc100SJani Nikula #define ICL_EXIT_ZERO_CNT_MAX	0x7
1833379bc100SJani Nikula 
icl_dphy_param_init(struct intel_dsi * intel_dsi)1834379bc100SJani Nikula static void icl_dphy_param_init(struct intel_dsi *intel_dsi)
1835379bc100SJani Nikula {
1836379bc100SJani Nikula 	struct drm_device *dev = intel_dsi->base.base.dev;
1837379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(dev);
18383cf05076SVille Syrjälä 	struct intel_connector *connector = intel_dsi->attached_connector;
18393cf05076SVille Syrjälä 	struct mipi_config *mipi_config = connector->panel.vbt.dsi.config;
1840379bc100SJani Nikula 	u32 tlpx_ns;
1841379bc100SJani Nikula 	u32 prepare_cnt, exit_zero_cnt, clk_zero_cnt, trail_cnt;
1842379bc100SJani Nikula 	u32 ths_prepare_ns, tclk_trail_ns;
1843379bc100SJani Nikula 	u32 hs_zero_cnt;
1844fc3bbd57SWilliam Tseng 	u32 tclk_pre_cnt;
1845379bc100SJani Nikula 
1846379bc100SJani Nikula 	tlpx_ns = intel_dsi_tlpx_ns(intel_dsi);
1847379bc100SJani Nikula 
1848379bc100SJani Nikula 	tclk_trail_ns = max(mipi_config->tclk_trail, mipi_config->ths_trail);
1849379bc100SJani Nikula 	ths_prepare_ns = max(mipi_config->ths_prepare,
1850379bc100SJani Nikula 			     mipi_config->tclk_prepare);
1851379bc100SJani Nikula 
1852379bc100SJani Nikula 	/*
1853379bc100SJani Nikula 	 * prepare cnt in escape clocks
1854379bc100SJani Nikula 	 * this field represents a hexadecimal value with a precision
1855379bc100SJani Nikula 	 * of 1.2 – i.e. the most significant bit is the integer
1856379bc100SJani Nikula 	 * and the least significant 2 bits are fraction bits.
1857379bc100SJani Nikula 	 * so, the field can represent a range of 0.25 to 1.75
1858379bc100SJani Nikula 	 */
1859379bc100SJani Nikula 	prepare_cnt = DIV_ROUND_UP(ths_prepare_ns * 4, tlpx_ns);
1860379bc100SJani Nikula 	if (prepare_cnt > ICL_PREPARE_CNT_MAX) {
1861b5280cd0SWambui Karuga 		drm_dbg_kms(&dev_priv->drm, "prepare_cnt out of range (%d)\n",
1862b5280cd0SWambui Karuga 			    prepare_cnt);
1863379bc100SJani Nikula 		prepare_cnt = ICL_PREPARE_CNT_MAX;
1864379bc100SJani Nikula 	}
1865379bc100SJani Nikula 
1866379bc100SJani Nikula 	/* clk zero count in escape clocks */
1867379bc100SJani Nikula 	clk_zero_cnt = DIV_ROUND_UP(mipi_config->tclk_prepare_clkzero -
1868379bc100SJani Nikula 				    ths_prepare_ns, tlpx_ns);
1869379bc100SJani Nikula 	if (clk_zero_cnt > ICL_CLK_ZERO_CNT_MAX) {
1870b5280cd0SWambui Karuga 		drm_dbg_kms(&dev_priv->drm,
1871b5280cd0SWambui Karuga 			    "clk_zero_cnt out of range (%d)\n", clk_zero_cnt);
1872379bc100SJani Nikula 		clk_zero_cnt = ICL_CLK_ZERO_CNT_MAX;
1873379bc100SJani Nikula 	}
1874379bc100SJani Nikula 
1875379bc100SJani Nikula 	/* trail cnt in escape clocks*/
1876379bc100SJani Nikula 	trail_cnt = DIV_ROUND_UP(tclk_trail_ns, tlpx_ns);
1877379bc100SJani Nikula 	if (trail_cnt > ICL_TRAIL_CNT_MAX) {
1878b5280cd0SWambui Karuga 		drm_dbg_kms(&dev_priv->drm, "trail_cnt out of range (%d)\n",
1879b5280cd0SWambui Karuga 			    trail_cnt);
1880379bc100SJani Nikula 		trail_cnt = ICL_TRAIL_CNT_MAX;
1881379bc100SJani Nikula 	}
1882379bc100SJani Nikula 
1883379bc100SJani Nikula 	/* tclk pre count in escape clocks */
1884379bc100SJani Nikula 	tclk_pre_cnt = DIV_ROUND_UP(mipi_config->tclk_pre, tlpx_ns);
1885379bc100SJani Nikula 	if (tclk_pre_cnt > ICL_TCLK_PRE_CNT_MAX) {
1886b5280cd0SWambui Karuga 		drm_dbg_kms(&dev_priv->drm,
1887b5280cd0SWambui Karuga 			    "tclk_pre_cnt out of range (%d)\n", tclk_pre_cnt);
1888379bc100SJani Nikula 		tclk_pre_cnt = ICL_TCLK_PRE_CNT_MAX;
1889379bc100SJani Nikula 	}
1890379bc100SJani Nikula 
1891379bc100SJani Nikula 	/* hs zero cnt in escape clocks */
1892379bc100SJani Nikula 	hs_zero_cnt = DIV_ROUND_UP(mipi_config->ths_prepare_hszero -
1893379bc100SJani Nikula 				   ths_prepare_ns, tlpx_ns);
1894379bc100SJani Nikula 	if (hs_zero_cnt > ICL_HS_ZERO_CNT_MAX) {
1895b5280cd0SWambui Karuga 		drm_dbg_kms(&dev_priv->drm, "hs_zero_cnt out of range (%d)\n",
1896b5280cd0SWambui Karuga 			    hs_zero_cnt);
1897379bc100SJani Nikula 		hs_zero_cnt = ICL_HS_ZERO_CNT_MAX;
1898379bc100SJani Nikula 	}
1899379bc100SJani Nikula 
1900379bc100SJani Nikula 	/* hs exit zero cnt in escape clocks */
1901379bc100SJani Nikula 	exit_zero_cnt = DIV_ROUND_UP(mipi_config->ths_exit, tlpx_ns);
1902379bc100SJani Nikula 	if (exit_zero_cnt > ICL_EXIT_ZERO_CNT_MAX) {
1903b5280cd0SWambui Karuga 		drm_dbg_kms(&dev_priv->drm,
1904b5280cd0SWambui Karuga 			    "exit_zero_cnt out of range (%d)\n",
1905b5280cd0SWambui Karuga 			    exit_zero_cnt);
1906379bc100SJani Nikula 		exit_zero_cnt = ICL_EXIT_ZERO_CNT_MAX;
1907379bc100SJani Nikula 	}
1908379bc100SJani Nikula 
1909379bc100SJani Nikula 	/* clock lane dphy timings */
1910379bc100SJani Nikula 	intel_dsi->dphy_reg = (CLK_PREPARE_OVERRIDE |
1911379bc100SJani Nikula 			       CLK_PREPARE(prepare_cnt) |
1912379bc100SJani Nikula 			       CLK_ZERO_OVERRIDE |
1913379bc100SJani Nikula 			       CLK_ZERO(clk_zero_cnt) |
1914379bc100SJani Nikula 			       CLK_PRE_OVERRIDE |
1915379bc100SJani Nikula 			       CLK_PRE(tclk_pre_cnt) |
1916379bc100SJani Nikula 			       CLK_TRAIL_OVERRIDE |
1917379bc100SJani Nikula 			       CLK_TRAIL(trail_cnt));
1918379bc100SJani Nikula 
1919379bc100SJani Nikula 	/* data lanes dphy timings */
1920379bc100SJani Nikula 	intel_dsi->dphy_data_lane_reg = (HS_PREPARE_OVERRIDE |
1921379bc100SJani Nikula 					 HS_PREPARE(prepare_cnt) |
1922379bc100SJani Nikula 					 HS_ZERO_OVERRIDE |
1923379bc100SJani Nikula 					 HS_ZERO(hs_zero_cnt) |
1924379bc100SJani Nikula 					 HS_TRAIL_OVERRIDE |
1925379bc100SJani Nikula 					 HS_TRAIL(trail_cnt) |
1926379bc100SJani Nikula 					 HS_EXIT_OVERRIDE |
1927379bc100SJani Nikula 					 HS_EXIT(exit_zero_cnt));
1928379bc100SJani Nikula 
1929379bc100SJani Nikula 	intel_dsi_log_params(intel_dsi);
1930379bc100SJani Nikula }
1931379bc100SJani Nikula 
icl_dsi_add_properties(struct intel_connector * connector)1932f6d39f56SVille Syrjälä static void icl_dsi_add_properties(struct intel_connector *connector)
1933f384e48dSVandita Kulkarni {
1934f6d39f56SVille Syrjälä 	const struct drm_display_mode *fixed_mode =
1935f6d39f56SVille Syrjälä 		intel_panel_preferred_fixed_mode(connector);
1936f384e48dSVandita Kulkarni 
19376ac2f04bSVille Syrjälä 	intel_attach_scaling_mode_property(&connector->base);
1938f384e48dSVandita Kulkarni 
193969654c63SDerek Basehore 	drm_connector_set_panel_orientation_with_quirk(&connector->base,
194069654c63SDerek Basehore 						       intel_dsi_get_panel_orientation(connector),
1941dee54887SVille Syrjälä 						       fixed_mode->hdisplay,
1942dee54887SVille Syrjälä 						       fixed_mode->vdisplay);
1943f384e48dSVandita Kulkarni }
1944f384e48dSVandita Kulkarni 
icl_dsi_init(struct drm_i915_private * dev_priv,const struct intel_bios_encoder_data * devdata)1945021a62a5SVille Syrjälä void icl_dsi_init(struct drm_i915_private *dev_priv,
1946021a62a5SVille Syrjälä 		  const struct intel_bios_encoder_data *devdata)
1947379bc100SJani Nikula {
1948*9aec6f76SJani Nikula 	struct intel_display *display = &dev_priv->display;
1949379bc100SJani Nikula 	struct intel_dsi *intel_dsi;
1950379bc100SJani Nikula 	struct intel_encoder *encoder;
1951379bc100SJani Nikula 	struct intel_connector *intel_connector;
1952379bc100SJani Nikula 	struct drm_connector *connector;
1953379bc100SJani Nikula 	enum port port;
1954379bc100SJani Nikula 
1955021a62a5SVille Syrjälä 	port = intel_bios_encoder_port(devdata);
1956021a62a5SVille Syrjälä 	if (port == PORT_NONE)
1957379bc100SJani Nikula 		return;
1958379bc100SJani Nikula 
1959379bc100SJani Nikula 	intel_dsi = kzalloc(sizeof(*intel_dsi), GFP_KERNEL);
1960379bc100SJani Nikula 	if (!intel_dsi)
1961379bc100SJani Nikula 		return;
1962379bc100SJani Nikula 
1963379bc100SJani Nikula 	intel_connector = intel_connector_alloc();
1964379bc100SJani Nikula 	if (!intel_connector) {
1965379bc100SJani Nikula 		kfree(intel_dsi);
1966379bc100SJani Nikula 		return;
1967379bc100SJani Nikula 	}
1968379bc100SJani Nikula 
1969379bc100SJani Nikula 	encoder = &intel_dsi->base;
1970379bc100SJani Nikula 	intel_dsi->attached_connector = intel_connector;
1971379bc100SJani Nikula 	connector = &intel_connector->base;
1972379bc100SJani Nikula 
1973021a62a5SVille Syrjälä 	encoder->devdata = devdata;
1974021a62a5SVille Syrjälä 
1975379bc100SJani Nikula 	/* register DSI encoder with DRM subsystem */
19763703060dSAndrzej Hajda 	drm_encoder_init(&dev_priv->drm, &encoder->base, &gen11_dsi_encoder_funcs,
1977379bc100SJani Nikula 			 DRM_MODE_ENCODER_DSI, "DSI %c", port_name(port));
1978379bc100SJani Nikula 
1979379bc100SJani Nikula 	encoder->pre_pll_enable = gen11_dsi_pre_pll_enable;
1980379bc100SJani Nikula 	encoder->pre_enable = gen11_dsi_pre_enable;
198121fd23acSJani Nikula 	encoder->enable = gen11_dsi_enable;
1982379bc100SJani Nikula 	encoder->disable = gen11_dsi_disable;
1983773b4b54SVille Syrjälä 	encoder->post_disable = gen11_dsi_post_disable;
1984379bc100SJani Nikula 	encoder->port = port;
1985379bc100SJani Nikula 	encoder->get_config = gen11_dsi_get_config;
1986544021e3STejas Upadhyay 	encoder->sync_state = gen11_dsi_sync_state;
1987c0a52f8bSJani Nikula 	encoder->update_pipe = intel_backlight_update;
1988379bc100SJani Nikula 	encoder->compute_config = gen11_dsi_compute_config;
1989379bc100SJani Nikula 	encoder->get_hw_state = gen11_dsi_get_hw_state;
1990b671d6efSImre Deak 	encoder->initial_fastset_check = gen11_dsi_initial_fastset_check;
1991379bc100SJani Nikula 	encoder->type = INTEL_OUTPUT_DSI;
1992379bc100SJani Nikula 	encoder->cloneable = 0;
199334053ee1SVille Syrjälä 	encoder->pipe_mask = ~0;
1994379bc100SJani Nikula 	encoder->power_domain = POWER_DOMAIN_PORT_DSI;
1995379bc100SJani Nikula 	encoder->get_power_domains = gen11_dsi_get_power_domains;
199687bd8498SVille Syrjälä 	encoder->disable_clock = gen11_dsi_gate_clocks;
19970fbd8694SVille Syrjälä 	encoder->is_clock_enabled = gen11_dsi_is_clock_enabled;
1998e3972476SVille Syrjälä 	encoder->shutdown = intel_dsi_shutdown;
1999379bc100SJani Nikula 
2000379bc100SJani Nikula 	/* register DSI connector with DRM subsystem */
20013703060dSAndrzej Hajda 	drm_connector_init(&dev_priv->drm, connector, &gen11_dsi_connector_funcs,
2002379bc100SJani Nikula 			   DRM_MODE_CONNECTOR_DSI);
2003379bc100SJani Nikula 	drm_connector_helper_add(connector, &gen11_dsi_connector_helper_funcs);
2004379bc100SJani Nikula 	connector->display_info.subpixel_order = SubPixelHorizontalRGB;
2005379bc100SJani Nikula 	intel_connector->get_hw_state = intel_connector_get_hw_state;
2006379bc100SJani Nikula 
2007379bc100SJani Nikula 	/* attach connector to encoder */
2008379bc100SJani Nikula 	intel_connector_attach_encoder(intel_connector, encoder);
2009379bc100SJani Nikula 
2010201963a8SVille Syrjälä 	intel_dsi->panel_power_off_time = ktime_get_boottime();
2011201963a8SVille Syrjälä 
2012*9aec6f76SJani Nikula 	intel_bios_init_panel_late(display, &intel_connector->panel, encoder->devdata, NULL);
20133cf05076SVille Syrjälä 
20143703060dSAndrzej Hajda 	mutex_lock(&dev_priv->drm.mode_config.mutex);
2015db10c14aSVille Syrjälä 	intel_panel_add_vbt_lfp_fixed_mode(intel_connector);
20163703060dSAndrzej Hajda 	mutex_unlock(&dev_priv->drm.mode_config.mutex);
2017379bc100SJani Nikula 
2018db10c14aSVille Syrjälä 	if (!intel_panel_preferred_fixed_mode(intel_connector)) {
2019b5280cd0SWambui Karuga 		drm_err(&dev_priv->drm, "DSI fixed mode info missing\n");
2020379bc100SJani Nikula 		goto err;
2021379bc100SJani Nikula 	}
2022379bc100SJani Nikula 
202315d045fdSJani Nikula 	intel_panel_init(intel_connector, NULL);
2024db10c14aSVille Syrjälä 
2025c0a52f8bSJani Nikula 	intel_backlight_setup(intel_connector, INVALID_PIPE);
2026379bc100SJani Nikula 
20273cf05076SVille Syrjälä 	if (intel_connector->panel.vbt.dsi.config->dual_link)
2028379bc100SJani Nikula 		intel_dsi->ports = BIT(PORT_A) | BIT(PORT_B);
2029379bc100SJani Nikula 	else
2030379bc100SJani Nikula 		intel_dsi->ports = BIT(port);
2031379bc100SJani Nikula 
2032f4a6c7a4SJani Nikula 	if (drm_WARN_ON(&dev_priv->drm, intel_connector->panel.vbt.dsi.bl_ports & ~intel_dsi->ports))
2033f4a6c7a4SJani Nikula 		intel_connector->panel.vbt.dsi.bl_ports &= intel_dsi->ports;
2034f4a6c7a4SJani Nikula 
2035f4a6c7a4SJani Nikula 	if (drm_WARN_ON(&dev_priv->drm, intel_connector->panel.vbt.dsi.cabc_ports & ~intel_dsi->ports))
2036f4a6c7a4SJani Nikula 		intel_connector->panel.vbt.dsi.cabc_ports &= intel_dsi->ports;
2037f4a6c7a4SJani Nikula 
2038379bc100SJani Nikula 	for_each_dsi_port(port, intel_dsi->ports) {
2039379bc100SJani Nikula 		struct intel_dsi_host *host;
2040379bc100SJani Nikula 
2041379bc100SJani Nikula 		host = intel_dsi_host_init(intel_dsi, &gen11_dsi_host_ops, port);
2042379bc100SJani Nikula 		if (!host)
2043379bc100SJani Nikula 			goto err;
2044379bc100SJani Nikula 
2045379bc100SJani Nikula 		intel_dsi->dsi_hosts[port] = host;
2046379bc100SJani Nikula 	}
2047379bc100SJani Nikula 
2048379bc100SJani Nikula 	if (!intel_dsi_vbt_init(intel_dsi, MIPI_DSI_GENERIC_PANEL_ID)) {
2049b5280cd0SWambui Karuga 		drm_dbg_kms(&dev_priv->drm, "no device found\n");
2050379bc100SJani Nikula 		goto err;
2051379bc100SJani Nikula 	}
2052379bc100SJani Nikula 
2053379bc100SJani Nikula 	icl_dphy_param_init(intel_dsi);
2054f384e48dSVandita Kulkarni 
2055f6d39f56SVille Syrjälä 	icl_dsi_add_properties(intel_connector);
2056379bc100SJani Nikula 	return;
2057379bc100SJani Nikula 
2058379bc100SJani Nikula err:
2059d1613061SVivek Kasireddy 	drm_connector_cleanup(connector);
2060379bc100SJani Nikula 	drm_encoder_cleanup(&encoder->base);
2061379bc100SJani Nikula 	kfree(intel_dsi);
2062379bc100SJani Nikula 	kfree(intel_connector);
2063379bc100SJani Nikula }
2064