cpu/intel: Add socket types
[coreboot2.git] / src / drivers / ti / sn65dsi86bridge / sn65dsi86bridge.c
blobc9f4ba5a817050e2365533c493e77b7792f7f5ca
1 /* SPDX-License-Identifier: GPL-2.0-only */
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"
13 #define BRIDGE_GETHIGHERBYTE(x) ((uint8_t)((x & 0xff00) >> 8))
14 #define BRIDGE_GETLOWERBYTE(x) ((uint8_t)(x & 0x00ff))
16 /* fudge factor required to account for 8b/10b encoding */
17 #define DP_CLK_FUDGE_NUM 10
18 #define DP_CLK_FUDGE_DEN 8
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
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
40 #define AUX_CMD_SEND 0x1
41 #define MIN_DSI_CLK_FREQ_MHZ 40
42 #define MAX_DSI_CLK_FREQ_MHZ 750
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,
109 enum {
110 HPD_ENABLE = 0x0,
111 HPD_DISABLE = 0x1,
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,
122 enum vstream_config {
123 VSTREAM_DISABLE = 0,
124 VSTREAM_ENABLE = 1,
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,
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,
151 * LUT index corresponds to register value and LUT values corresponds
152 * to dp data rate supported by the bridge in Mbps unit.
154 static const unsigned int sn65dsi86_bridge_dp_rate_lut[] = {
155 0, 1620, 2160, 2430, 2700, 3240, 4320, 5400
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)
165 int i;
166 uint32_t length;
167 uint8_t buf;
168 uint8_t reg;
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);
174 while (total_size) {
175 length = MIN(total_size, DP_AUX_MAX_PAYLOAD_BYTES);
176 total_size -= length;
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;
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;
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;
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;
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;
217 return CB_SUCCESS;
220 enum cb_err sn65dsi86_bridge_read_edid(uint8_t bus, uint8_t chip, struct edid *out)
222 enum cb_err err;
223 u8 edid[EDID_LENGTH * 2];
224 int edid_size = EDID_LENGTH;
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;
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;
251 if (decode_edid(edid, edid_size, out) != EDID_CONFORMANT) {
252 printk(BIOS_ERR, "Failed to decode EDID.\n");
253 return CB_ERR;
256 return CB_SUCCESS;
259 static void sn65dsi86_bridge_valid_dp_rates(uint8_t bus, uint8_t chip, bool rate_valid[])
261 unsigned int rate_per_200khz;
262 uint8_t dpcd_val;
263 int i, j;
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};
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]);
277 if (!rate_per_200khz)
278 break;
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;
289 for (i = 0; i < ARRAY_SIZE(sn65dsi86_bridge_dp_rate_lut); i++) {
290 if (rate_valid[i])
291 return;
294 printk(BIOS_ERR, "No matching eDP rates in table; falling back\n");
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);
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;
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)
321 uint64_t pixel_clk_hz;
322 uint64_t stream_bit_rate_mhz;
323 uint64_t min_req_dsi_clk;
325 pixel_clk_hz = edid->mode.pixel_clock * KHz;
326 stream_bit_rate_mhz = (pixel_clk_hz * bpp) / MHz;
328 /* For TI the clock frequencies are half the bit rates */
329 min_req_dsi_clk = stream_bit_rate_mhz / (num_of_lanes * 2);
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);
337 static void sn65dsi86_bridge_set_dp_clock_range(uint8_t bus, uint8_t chip,
338 struct edid *edid, uint32_t num_of_lanes)
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;
345 stream_bit_rate_khz = edid->mode.pixel_clock * 18;
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);
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;
355 sn65dsi86_bridge_valid_dp_rates(bus, chip, rate_valid);
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;
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");
370 static void sn65dsi86_bridge_set_bridge_active_timing(uint8_t bus,
371 uint8_t chip,
372 struct edid *edid)
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);
400 static void sn65dsi86_bridge_link_training(uint8_t bus, uint8_t chip)
402 uint8_t buf;
404 /* enable pll lock */
405 i2c_writeb(bus, chip, SN_PLL_ENABLE_REG, 0x1);
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");
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.
419 buf = 0x1;
420 sn65dsi86_bridge_aux_request(bus, chip,
421 DP_BRIDGE_CONFIGURATION_SET, 1, DPCD_WRITE, &buf);
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);
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;
432 if (buf == NORMAL_MODE)
433 return;
436 printk(BIOS_ERR, "Link training failed 10 times\n");
439 void sn65dsi86_backlight_enable(uint8_t bus, uint8_t chip)
441 uint8_t val = DP_BACKLIGHT_CONTROL_MODE_DPCD;
442 sn65dsi86_bridge_aux_request(bus, chip, DP_BACKLIGHT_MODE_SET, 1, DPCD_WRITE, &val);
444 val = 0xff;
445 sn65dsi86_bridge_aux_request(bus, chip, DP_BACKLIGHT_BRIGHTNESS_MSB, 1,
446 DPCD_WRITE, &val);
448 val = DP_BACKLIGHT_ENABLE;
449 sn65dsi86_bridge_aux_request(bus, chip, DP_DISPLAY_CONTROL_REGISTER, 1,
450 DPCD_WRITE, &val);
453 static void sn65dsi86_bridge_assr_config(uint8_t bus, uint8_t chip, int enable)
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);
461 static int sn65dsi86_bridge_dp_lane_config(uint8_t bus, uint8_t chip)
463 uint8_t lane_count;
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);
469 return lane_count;
472 void sn65dsi86_bridge_init(uint8_t bus, uint8_t chip, enum dp_pll_clk_src ref_clk)
474 /* disable HPD */
475 i2c_write_field(bus, chip, SN_HPD_DISABLE_REG, HPD_DISABLE, 1, 0);
477 /* set refclk to 19.2 MHZ */
478 i2c_write_field(bus, chip, SN_DPPLL_SRC_REG, ref_clk, 7, 1);
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)
485 int dp_lanes;
487 /* DSI Lanes config */
488 i2c_write_field(bus, chip, SN_DSI_LANES_REG, (4 - num_of_lanes), 3, 3);
490 /* DP Lane config */
491 dp_lanes = sn65dsi86_bridge_dp_lane_config(bus, chip);
493 sn65dsi86_bridge_set_dsi_clock_range(bus, chip, edid, num_of_lanes, dsi_bpp);
495 sn65dsi86_bridge_set_dp_clock_range(bus, chip, edid, dp_lanes);
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);
502 /* DP BPP config */
503 i2c_writeb(bus, chip, SN_DATA_FORMAT_REG, 0x1);
505 /* color bar disabled */
506 i2c_writeb(bus, chip, SN_COLOR_BAR_REG, 0x5);
508 /* Enable vstream */
509 sn65dsi86_bridge_assr_config(bus, chip, 1);