xref: /aosp_15_r20/external/coreboot/src/drivers/ti/sn65dsi86bridge/sn65dsi86bridge.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <console/console.h>
4 #include <endian.h>
5 #include <device/i2c_simple.h>
6 #include <dp_aux.h>
7 #include <edid.h>
8 #include <timer.h>
9 #include <types.h>
10 #include <soc/addressmap.h>
11 #include "sn65dsi86bridge.h"
12 
13 #define BRIDGE_GETHIGHERBYTE(x)		((uint8_t)((x & 0xff00) >> 8))
14 #define BRIDGE_GETLOWERBYTE(x)		((uint8_t)(x & 0x00ff))
15 
16 /* fudge factor required to account for 8b/10b encoding */
17 #define DP_CLK_FUDGE_NUM 10
18 #define DP_CLK_FUDGE_DEN 8
19 
20 /* DPCD */
21 #define DP_BRIDGE_DPCD_REV		0x700
22 #define DP_BRIDGE_11			0x00
23 #define DP_BRIDGE_12			0x01
24 #define DP_BRIDGE_13			0x02
25 #define DP_BRIDGE_14			0x03
26 #define DP_BRIDGE_CONFIGURATION_SET	0x10a
27 #define DP_MAX_LINK_RATE		0x001
28 #define DP_MAX_LANE_COUNT		0x002
29 #define DP_SUPPORTED_LINK_RATES		0x010 /* eDP 1.4 */
30 #define DP_MAX_LINK_RATE		0x001
31 #define DP_MAX_SUPPORTED_RATES		8 /* 16-bit little-endian */
32 #define DP_LANE_COUNT_MASK		0xf
33 
34 /* link configuration */
35 #define DP_LINK_BW_SET		0x100
36 #define DP_LINK_BW_1_62		0x06
37 #define DP_LINK_BW_2_7		0x0a
38 #define DP_LINK_BW_5_4		0x14
39 
40 #define AUX_CMD_SEND		0x1
41 #define MIN_DSI_CLK_FREQ_MHZ	40
42 #define MAX_DSI_CLK_FREQ_MHZ    750
43 
44 enum bridge_regs {
45 	SN_DPPLL_SRC_REG = 0x0A,
46 	SN_PLL_ENABLE_REG = 0x0D,
47 	SN_DSI_LANES_REG = 0x10,
48 	SN_DSIA_CLK_FREQ_REG = 0x12,
49 	SN_CHA_ACTIVE_LINE_LENGTH_LOW_REG = 0x20,
50 	SN_CHA_ACTIVE_LINE_LENGTH_HIGH_REG = 0x21,
51 	SN_CHA_VERTICAL_DISPLAY_SIZE_LOW_REG = 0x24,
52 	SN_CHA_VERTICAL_DISPLAY_SIZE_HIGH_REG = 0x25,
53 	SN_CHA_HSYNC_PULSE_WIDTH_LOW_REG = 0x2C,
54 	SN_CHA_HSYNC_PULSE_WIDTH_HIGH_REG = 0x2D,
55 	SN_CHA_VSYNC_PULSE_WIDTH_LOW_REG = 0x30,
56 	SN_CHA_VSYNC_PULSE_WIDTH_HIGH_REG = 0x31,
57 	SN_CHA_HORIZONTAL_BACK_PORCH_REG = 0x34,
58 	SN_CHA_VERTICAL_BACK_PORCH_REG = 0x36,
59 	SN_CHA_HORIZONTAL_FRONT_PORCH_REG = 0x38,
60 	SN_CHA_VERTICAL_FRONT_PORCH_REG = 0x3A,
61 	SN_COLOR_BAR_REG = 0x3C,
62 	SN_ENH_FRAME_REG = 0x5A,
63 	SN_DATA_FORMAT_REG = 0x5B,
64 	SN_HPD_DISABLE_REG = 0x5C,
65 	SN_I2C_CLAIM_ADDR_EN1 = 0x60,
66 	SN_AUX_WDATA_REG_0 = 0x64,
67 	SN_AUX_WDATA_REG_1 = 0x65,
68 	SN_AUX_WDATA_REG_2 = 0x66,
69 	SN_AUX_WDATA_REG_3 = 0x67,
70 	SN_AUX_WDATA_REG_4 = 0x68,
71 	SN_AUX_WDATA_REG_5 = 0x69,
72 	SN_AUX_WDATA_REG_6 = 0x6A,
73 	SN_AUX_WDATA_REG_7 = 0x6B,
74 	SN_AUX_WDATA_REG_8 = 0x6C,
75 	SN_AUX_WDATA_REG_9 = 0x6D,
76 	SN_AUX_WDATA_REG_10 = 0x6E,
77 	SN_AUX_WDATA_REG_11 = 0x6F,
78 	SN_AUX_WDATA_REG_12 = 0x70,
79 	SN_AUX_WDATA_REG_13 = 0x71,
80 	SN_AUX_WDATA_REG_14 = 0x72,
81 	SN_AUX_WDATA_REG_15 = 0x73,
82 	SN_AUX_ADDR_19_16_REG = 0x74,
83 	SN_AUX_ADDR_15_8_REG = 0x75,
84 	SN_AUX_ADDR_7_0_REG = 0x76,
85 	SN_AUX_LENGTH_REG = 0x77,
86 	SN_AUX_CMD_REG = 0x78,
87 	SN_AUX_RDATA_REG_0 = 0x79,
88 	SN_AUX_RDATA_REG_1 = 0x7A,
89 	SN_AUX_RDATA_REG_2 = 0x7B,
90 	SN_AUX_RDATA_REG_3 = 0x7C,
91 	SN_AUX_RDATA_REG_4 = 0x7D,
92 	SN_AUX_RDATA_REG_5 = 0x7E,
93 	SN_AUX_RDATA_REG_6 = 0x7F,
94 	SN_AUX_RDATA_REG_7 = 0x80,
95 	SN_AUX_RDATA_REG_8 = 0x81,
96 	SN_AUX_RDATA_REG_9 = 0x82,
97 	SN_AUX_RDATA_REG_10 = 0x83,
98 	SN_AUX_RDATA_REG_11 = 0x84,
99 	SN_AUX_RDATA_REG_12 = 0x85,
100 	SN_AUX_RDATA_REG_13 = 0x86,
101 	SN_AUX_RDATA_REG_14 = 0x87,
102 	SN_AUX_RDATA_REG_15 = 0x88,
103 	SN_SSC_CONFIG_REG = 0x93,
104 	SN_DATARATE_CONFIG_REG = 0x94,
105 	SN_ML_TX_MODE_REG = 0x96,
106 	SN_AUX_CMD_STATUS_REG = 0xF4,
107 };
108 
109 enum {
110 	HPD_ENABLE = 0x0,
111 	HPD_DISABLE = 0x1,
112 };
113 
114 enum {
115 	SOT_ERR_TOL_DSI = 0x0,
116 	CHB_DSI_LANES = 0x1,
117 	CHA_DSI_LANES = 0x2,
118 	DSI_CHANNEL_MODE = 0x3,
119 	LEFT_RIGHT_PIXELS = 0x4,
120 };
121 
122 enum vstream_config {
123 	VSTREAM_DISABLE = 0,
124 	VSTREAM_ENABLE = 1,
125 };
126 
127 enum aux_cmd_status {
128 	NAT_I2C_FAIL = 1 << 6,
129 	AUX_SHORT = 1 << 5,
130 	AUX_DFER = 1 << 4,
131 	AUX_RPLY_TOUT = 1 << 3,
132 	SEND_INT = 1 << 0,
133 };
134 
135 enum ml_tx_mode {
136 	MAIN_LINK_OFF = 0x0,
137 	NORMAL_MODE = 0x1,
138 	TPS1 = 0x2,
139 	TPS2 = 0x3,
140 	TPS3 = 0x4,
141 	PRBS7 = 0x5,
142 	HBR2_COMPLIANCE_EYE_PATTERN = 0x6,
143 	SYMBOL_ERR_RATE_MEASUREMENT_PATTERN = 0x7,
144 	CUTSOM_PATTERN = 0x8,
145 	FAST_LINK_TRAINING = 0x9,
146 	SEMI_AUTO_LINK_TRAINING = 0xa,
147 	REDRIVER_SEMI_AUTO_LINK_TRAINING = 0xb,
148 };
149 
150 /*
151  * LUT index corresponds to register value and LUT values corresponds
152  * to dp data rate supported by the bridge in Mbps unit.
153  */
154 static const unsigned int sn65dsi86_bridge_dp_rate_lut[] = {
155 	0, 1620, 2160, 2430, 2700, 3240, 4320, 5400
156 };
157 
sn65dsi86_bridge_aux_request(uint8_t bus,uint8_t chip,unsigned int target_reg,unsigned int total_size,enum aux_request request,uint8_t * data)158 static enum cb_err sn65dsi86_bridge_aux_request(uint8_t bus,
159 						uint8_t chip,
160 						unsigned int target_reg,
161 						unsigned int total_size,
162 						enum aux_request request,
163 						uint8_t *data)
164 {
165 	int i;
166 	uint32_t length;
167 	uint8_t buf;
168 	uint8_t reg;
169 
170 	/* Clear old status flags just in case they're left over from a previous transfer. */
171 	i2c_writeb(bus, chip, SN_AUX_CMD_STATUS_REG,
172 		   NAT_I2C_FAIL | AUX_SHORT | AUX_DFER | AUX_RPLY_TOUT | SEND_INT);
173 
174 	while (total_size) {
175 		length = MIN(total_size, DP_AUX_MAX_PAYLOAD_BYTES);
176 		total_size -= length;
177 
178 		enum i2c_over_aux cmd = dp_get_aux_cmd(request, total_size);
179 		if (i2c_writeb(bus, chip, SN_AUX_CMD_REG, (cmd << 4)) ||
180 		    i2c_writeb(bus, chip, SN_AUX_ADDR_19_16_REG, (target_reg >> 16) & 0xF) ||
181 		    i2c_writeb(bus, chip, SN_AUX_ADDR_15_8_REG, (target_reg >> 8) & 0xFF) ||
182 		    i2c_writeb(bus, chip, SN_AUX_ADDR_7_0_REG, (target_reg) & 0xFF) ||
183 		    i2c_writeb(bus, chip, SN_AUX_LENGTH_REG, length))
184 			return CB_ERR;
185 
186 		if (dp_aux_request_is_write(request)) {
187 			reg = SN_AUX_WDATA_REG_0;
188 			for (i = 0; i < length; i++)
189 				if (i2c_writeb(bus, chip, reg++, *data++))
190 					return CB_ERR;
191 		}
192 
193 		if (i2c_writeb(bus, chip, SN_AUX_CMD_REG, AUX_CMD_SEND | (cmd << 4)))
194 			return CB_ERR;
195 		if (!wait_ms(100, !i2c_readb(bus, chip, SN_AUX_CMD_REG, &buf) &&
196 				  !(buf & AUX_CMD_SEND))) {
197 			printk(BIOS_ERR, "AUX_CMD_SEND not acknowledged\n");
198 			return CB_ERR;
199 		}
200 		if (i2c_readb(bus, chip, SN_AUX_CMD_STATUS_REG, &buf))
201 			return CB_ERR;
202 		if (buf & (NAT_I2C_FAIL | AUX_SHORT | AUX_DFER | AUX_RPLY_TOUT)) {
203 			printk(BIOS_ERR, "AUX command failed, status = %#x\n", buf);
204 			return CB_ERR;
205 		}
206 
207 		if (!dp_aux_request_is_write(request)) {
208 			reg = SN_AUX_RDATA_REG_0;
209 			for (i = 0; i < length; i++) {
210 				if (i2c_readb(bus, chip, reg++, &buf))
211 					return CB_ERR;
212 				*data++ = buf;
213 			}
214 		}
215 	}
216 
217 	return CB_SUCCESS;
218 }
219 
sn65dsi86_bridge_read_edid(uint8_t bus,uint8_t chip,struct edid * out)220 enum cb_err sn65dsi86_bridge_read_edid(uint8_t bus, uint8_t chip, struct edid *out)
221 {
222 	enum cb_err err;
223 	u8 edid[EDID_LENGTH * 2];
224 	int edid_size = EDID_LENGTH;
225 
226 	uint8_t reg_addr = 0;
227 	err = sn65dsi86_bridge_aux_request(bus, chip, EDID_I2C_ADDR, 1,
228 					   I2C_RAW_WRITE, &reg_addr);
229 	if (!err)
230 		err = sn65dsi86_bridge_aux_request(bus, chip, EDID_I2C_ADDR, EDID_LENGTH,
231 						   I2C_RAW_READ_AND_STOP, edid);
232 	if (err) {
233 		printk(BIOS_ERR, "Failed to read EDID.\n");
234 		return err;
235 	}
236 
237 	if (edid[EDID_EXTENSION_FLAG]) {
238 		edid_size += EDID_LENGTH;
239 		reg_addr = EDID_LENGTH;
240 		err = sn65dsi86_bridge_aux_request(bus, chip, EDID_I2C_ADDR, 1,
241 						   I2C_RAW_WRITE, &reg_addr);
242 		if (!err)
243 			err = sn65dsi86_bridge_aux_request(bus, chip, EDID_I2C_ADDR,
244 					EDID_LENGTH, I2C_RAW_READ_AND_STOP, &edid[EDID_LENGTH]);
245 		if (err) {
246 			printk(BIOS_ERR, "Failed to read EDID ext block.\n");
247 			return err;
248 		}
249 	}
250 
251 	if (decode_edid(edid, edid_size, out) != EDID_CONFORMANT) {
252 		printk(BIOS_ERR, "Failed to decode EDID.\n");
253 		return CB_ERR;
254 	}
255 
256 	return CB_SUCCESS;
257 }
258 
sn65dsi86_bridge_valid_dp_rates(uint8_t bus,uint8_t chip,bool rate_valid[])259 static void sn65dsi86_bridge_valid_dp_rates(uint8_t bus, uint8_t chip, bool rate_valid[])
260 {
261 	unsigned int rate_per_200khz;
262 	uint8_t dpcd_val;
263 	int i, j;
264 
265 	sn65dsi86_bridge_aux_request(bus, chip,
266 				     DP_BRIDGE_DPCD_REV, 1, DPCD_READ, &dpcd_val);
267 	if (dpcd_val >= DP_BRIDGE_14) {
268 		/* eDP 1.4 devices must provide a custom table */
269 		uint16_t sink_rates[DP_MAX_SUPPORTED_RATES] = {0};
270 
271 		sn65dsi86_bridge_aux_request(bus, chip, DP_SUPPORTED_LINK_RATES,
272 					     sizeof(sink_rates),
273 					     DPCD_READ, (void *)sink_rates);
274 		for (i = 0; i < ARRAY_SIZE(sink_rates); i++) {
275 			rate_per_200khz = le16_to_cpu(sink_rates[i]);
276 
277 			if (!rate_per_200khz)
278 				break;
279 
280 			for (j = 0;
281 			     j < ARRAY_SIZE(sn65dsi86_bridge_dp_rate_lut);
282 			     j++) {
283 				if (sn65dsi86_bridge_dp_rate_lut[j] * (MHz / KHz) ==
284 				    rate_per_200khz * 200)
285 					rate_valid[j] = true;
286 			}
287 		}
288 
289 		for (i = 0; i < ARRAY_SIZE(sn65dsi86_bridge_dp_rate_lut); i++) {
290 			if (rate_valid[i])
291 				return;
292 		}
293 
294 		printk(BIOS_ERR, "No matching eDP rates in table; falling back\n");
295 	}
296 
297 	/* On older versions best we can do is use DP_MAX_LINK_RATE */
298 	sn65dsi86_bridge_aux_request(bus, chip, DP_MAX_LINK_RATE, 1, DPCD_READ, &dpcd_val);
299 
300 	switch (dpcd_val) {
301 	default:
302 		printk(BIOS_ERR, "Unexpected max rate (%#x); assuming 5.4 GHz\n",
303 		       (int)dpcd_val);
304 		__fallthrough;
305 	case DP_LINK_BW_5_4:
306 		rate_valid[7] = 1;
307 		__fallthrough;
308 	case DP_LINK_BW_2_7:
309 		rate_valid[4] = 1;
310 		__fallthrough;
311 	case DP_LINK_BW_1_62:
312 		rate_valid[1] = 1;
313 		break;
314 	}
315 }
316 
sn65dsi86_bridge_set_dsi_clock_range(uint8_t bus,uint8_t chip,struct edid * edid,uint32_t num_of_lanes,uint32_t bpp)317 static void sn65dsi86_bridge_set_dsi_clock_range(uint8_t bus, uint8_t chip,
318 						 struct edid *edid,
319 						 uint32_t num_of_lanes, uint32_t bpp)
320 {
321 	uint64_t pixel_clk_hz;
322 	uint64_t stream_bit_rate_mhz;
323 	uint64_t min_req_dsi_clk;
324 
325 	pixel_clk_hz = edid->mode.pixel_clock * KHz;
326 	stream_bit_rate_mhz = (pixel_clk_hz * bpp) / MHz;
327 
328 	/* For TI the clock frequencies are half the bit rates */
329 	min_req_dsi_clk = stream_bit_rate_mhz / (num_of_lanes * 2);
330 
331 	/* for each increment in val, frequency increases by 5MHz */
332 	min_req_dsi_clk = MAX(MIN_DSI_CLK_FREQ_MHZ,
333 			  MIN(MAX_DSI_CLK_FREQ_MHZ, min_req_dsi_clk)) / 5;
334 	i2c_writeb(bus, chip, SN_DSIA_CLK_FREQ_REG, min_req_dsi_clk);
335 }
336 
sn65dsi86_bridge_set_dp_clock_range(uint8_t bus,uint8_t chip,struct edid * edid,uint32_t num_of_lanes)337 static void sn65dsi86_bridge_set_dp_clock_range(uint8_t bus, uint8_t chip,
338 						struct edid *edid, uint32_t num_of_lanes)
339 {
340 	uint64_t stream_bit_rate_khz;
341 	bool rate_valid[ARRAY_SIZE(sn65dsi86_bridge_dp_rate_lut)] = { };
342 	uint64_t dp_rate_mhz;
343 	int dp_rate_idx, i;
344 
345 	stream_bit_rate_khz = edid->mode.pixel_clock * 18;
346 
347 	/* Calculate minimum DP data rate, taking 80% as per DP spec */
348 	dp_rate_mhz = DIV_ROUND_UP(stream_bit_rate_khz * DP_CLK_FUDGE_NUM,
349 				   KHz * num_of_lanes * DP_CLK_FUDGE_DEN);
350 
351 	for (i = 0; i < ARRAY_SIZE(sn65dsi86_bridge_dp_rate_lut) - 1; i++)
352 		if (sn65dsi86_bridge_dp_rate_lut[i] > dp_rate_mhz)
353 			break;
354 
355 	sn65dsi86_bridge_valid_dp_rates(bus, chip, rate_valid);
356 
357 	/* Train until we run out of rates */
358 	for (dp_rate_idx = i;
359 	     dp_rate_idx < ARRAY_SIZE(sn65dsi86_bridge_dp_rate_lut);
360 	     dp_rate_idx++)
361 		if (rate_valid[dp_rate_idx])
362 			break;
363 
364 	if (dp_rate_idx < ARRAY_SIZE(sn65dsi86_bridge_dp_rate_lut))
365 		i2c_write_field(bus, chip, SN_DATARATE_CONFIG_REG, dp_rate_idx, 8, 5);
366 	else
367 		printk(BIOS_ERR, "valid dp rate not found");
368 }
369 
sn65dsi86_bridge_set_bridge_active_timing(uint8_t bus,uint8_t chip,struct edid * edid)370 static void sn65dsi86_bridge_set_bridge_active_timing(uint8_t bus,
371 						      uint8_t chip,
372 						      struct edid *edid)
373 {
374 	i2c_writeb(bus, chip, SN_CHA_ACTIVE_LINE_LENGTH_LOW_REG,
375 			   BRIDGE_GETLOWERBYTE(edid->mode.ha));
376 	i2c_writeb(bus, chip, SN_CHA_ACTIVE_LINE_LENGTH_HIGH_REG,
377 			   BRIDGE_GETHIGHERBYTE(edid->mode.ha));
378 	i2c_writeb(bus, chip, SN_CHA_VERTICAL_DISPLAY_SIZE_LOW_REG,
379 			   BRIDGE_GETLOWERBYTE(edid->mode.va));
380 	i2c_writeb(bus, chip, SN_CHA_VERTICAL_DISPLAY_SIZE_HIGH_REG,
381 			   BRIDGE_GETHIGHERBYTE(edid->mode.va));
382 	i2c_writeb(bus, chip, SN_CHA_HSYNC_PULSE_WIDTH_LOW_REG,
383 			   BRIDGE_GETLOWERBYTE(edid->mode.hspw));
384 	i2c_writeb(bus, chip, SN_CHA_HSYNC_PULSE_WIDTH_HIGH_REG,
385 			   BRIDGE_GETHIGHERBYTE(edid->mode.hspw));
386 	i2c_writeb(bus, chip, SN_CHA_VSYNC_PULSE_WIDTH_LOW_REG,
387 			   BRIDGE_GETLOWERBYTE(edid->mode.vspw));
388 	i2c_writeb(bus, chip, SN_CHA_VSYNC_PULSE_WIDTH_HIGH_REG,
389 			   BRIDGE_GETHIGHERBYTE(edid->mode.vspw));
390 	i2c_writeb(bus, chip, SN_CHA_HORIZONTAL_BACK_PORCH_REG,
391 			   edid->mode.hbl - edid->mode.hso - edid->mode.hspw);
392 	i2c_writeb(bus, chip, SN_CHA_VERTICAL_BACK_PORCH_REG,
393 			   edid->mode.vbl - edid->mode.vso - edid->mode.vspw);
394 	i2c_writeb(bus, chip, SN_CHA_HORIZONTAL_FRONT_PORCH_REG,
395 			   edid->mode.hso);
396 	i2c_writeb(bus, chip, SN_CHA_VERTICAL_FRONT_PORCH_REG,
397 			   edid->mode.vso);
398 }
399 
sn65dsi86_bridge_link_training(uint8_t bus,uint8_t chip)400 static void sn65dsi86_bridge_link_training(uint8_t bus, uint8_t chip)
401 {
402 	uint8_t buf;
403 
404 	/* enable pll lock */
405 	i2c_writeb(bus, chip, SN_PLL_ENABLE_REG, 0x1);
406 
407 	if (!wait_ms(500,
408 	    !(i2c_readb(bus, chip, SN_DPPLL_SRC_REG, &buf)) &&
409 	    (buf & BIT(7)))) {
410 		printk(BIOS_ERR, "PLL lock failure\n");
411 	}
412 
413 	/*
414 	 * The SN65DSI86 only supports ASSR Display Authentication method and
415 	 * this method is enabled by default. An eDP panel must support this
416 	 * authentication method. We need to enable this method in the eDP panel
417 	 * at DisplayPort address 0x0010A prior to link training.
418 	 */
419 	buf = 0x1;
420 	sn65dsi86_bridge_aux_request(bus, chip,
421 				     DP_BRIDGE_CONFIGURATION_SET, 1, DPCD_WRITE, &buf);
422 
423 	int i;	/* Kernel driver suggests to retry this up to 10 times if it fails. */
424 	for (i = 0; i < 10; i++) {
425 		i2c_writeb(bus, chip, SN_ML_TX_MODE_REG, SEMI_AUTO_LINK_TRAINING);
426 
427 		if (!wait_ms(500, !(i2c_readb(bus, chip, SN_ML_TX_MODE_REG, &buf)) &&
428 				  (buf == NORMAL_MODE || buf == MAIN_LINK_OFF))) {
429 			printk(BIOS_ERR, "unexpected link training state: %#x\n", buf);
430 			return;
431 		}
432 		if (buf == NORMAL_MODE)
433 			return;
434 	}
435 
436 	printk(BIOS_ERR, "Link training failed 10 times\n");
437 }
438 
sn65dsi86_backlight_enable(uint8_t bus,uint8_t chip)439 void sn65dsi86_backlight_enable(uint8_t bus, uint8_t chip)
440 {
441 	uint8_t val = DP_BACKLIGHT_CONTROL_MODE_DPCD;
442 	sn65dsi86_bridge_aux_request(bus, chip, DP_BACKLIGHT_MODE_SET, 1, DPCD_WRITE, &val);
443 
444 	val = 0xff;
445 	sn65dsi86_bridge_aux_request(bus, chip, DP_BACKLIGHT_BRIGHTNESS_MSB, 1,
446 				     DPCD_WRITE, &val);
447 
448 	val = DP_BACKLIGHT_ENABLE;
449 	sn65dsi86_bridge_aux_request(bus, chip, DP_DISPLAY_CONTROL_REGISTER, 1,
450 				     DPCD_WRITE, &val);
451 }
452 
sn65dsi86_bridge_assr_config(uint8_t bus,uint8_t chip,int enable)453 static void sn65dsi86_bridge_assr_config(uint8_t bus, uint8_t chip, int enable)
454 {
455 	if (enable)
456 		i2c_write_field(bus, chip, SN_ENH_FRAME_REG, VSTREAM_ENABLE, 1, 3);
457 	else
458 		i2c_write_field(bus, chip, SN_ENH_FRAME_REG, VSTREAM_DISABLE, 1, 3);
459 }
460 
sn65dsi86_bridge_dp_lane_config(uint8_t bus,uint8_t chip)461 static int sn65dsi86_bridge_dp_lane_config(uint8_t bus, uint8_t chip)
462 {
463 	uint8_t lane_count;
464 
465 	sn65dsi86_bridge_aux_request(bus, chip, DP_MAX_LANE_COUNT, 1, DPCD_READ, &lane_count);
466 	lane_count &= DP_LANE_COUNT_MASK;
467 	i2c_write_field(bus, chip, SN_SSC_CONFIG_REG, MIN(lane_count, 3), 3, 4);
468 
469 	return lane_count;
470 }
471 
sn65dsi86_bridge_init(uint8_t bus,uint8_t chip,enum dp_pll_clk_src ref_clk)472 void sn65dsi86_bridge_init(uint8_t bus, uint8_t chip, enum dp_pll_clk_src ref_clk)
473 {
474 	/* disable HPD */
475 	i2c_write_field(bus, chip, SN_HPD_DISABLE_REG, HPD_DISABLE, 1, 0);
476 
477 	/* set refclk to 19.2 MHZ */
478 	i2c_write_field(bus, chip, SN_DPPLL_SRC_REG, ref_clk, 7, 1);
479 }
480 
sn65dsi86_bridge_configure(uint8_t bus,uint8_t chip,struct edid * edid,uint32_t num_of_lanes,uint32_t dsi_bpp)481 void sn65dsi86_bridge_configure(uint8_t bus, uint8_t chip,
482 				struct edid *edid, uint32_t num_of_lanes,
483 				uint32_t dsi_bpp)
484 {
485 	int dp_lanes;
486 
487 	/* DSI Lanes config */
488 	i2c_write_field(bus, chip, SN_DSI_LANES_REG, (4 - num_of_lanes), 3, 3);
489 
490 	/* DP Lane config */
491 	dp_lanes = sn65dsi86_bridge_dp_lane_config(bus, chip);
492 
493 	sn65dsi86_bridge_set_dsi_clock_range(bus, chip, edid, num_of_lanes, dsi_bpp);
494 
495 	sn65dsi86_bridge_set_dp_clock_range(bus, chip, edid, dp_lanes);
496 
497 	/* Disable vstream */
498 	sn65dsi86_bridge_assr_config(bus, chip, 0);
499 	sn65dsi86_bridge_link_training(bus, chip);
500 	sn65dsi86_bridge_set_bridge_active_timing(bus, chip, edid);
501 
502 	/* DP BPP config */
503 	i2c_writeb(bus, chip, SN_DATA_FORMAT_REG, 0x1);
504 
505 	/* color bar disabled */
506 	i2c_writeb(bus, chip, SN_COLOR_BAR_REG, 0x5);
507 
508 	/* Enable vstream */
509 	sn65dsi86_bridge_assr_config(bus, chip, 1);
510 }
511