blob: 48a832a9d95503a73f1e5ca6262f9600c5a6a190 [file] [log] [blame]
Vinod Polimera4e93e942022-02-25 13:21:42 +05301// SPDX-License-Identifier: GPL-2.0-only
2
3#include <device/mmio.h>
4#include <commonlib/rational.h>
5#include <console/console.h>
6#include <edid.h>
7#include <delay.h>
8#include <types.h>
9#include <string.h>
Vinod Polimera4e93e942022-02-25 13:21:42 +053010#include <soc/clock.h>
11#include <gpio.h>
12#include <soc/display/edp_reg.h>
13#include <soc/display/edp_aux.h>
14#include <soc/display/edp_ctrl.h>
15#include <soc/display/edp_phy.h>
16
17#define DPCD_LINK_VOLTAGE_MAX 4
18#define DPCD_LINK_PRE_EMPHASIS_MAX 4
19#define MAX_LINK_TRAINING_LOOP 5
20
21/* DP_TX Registers */
22#define MAX_16BITS_VALUE ((1 << 16) - 1) /* 16 bits value */
23#define EDP_INTR_AUX_I2C_DONE BIT(3)
24#define EDP_INTR_WRONG_ADDR BIT(6)
25#define EDP_INTR_TIMEOUT BIT(9)
26#define EDP_INTR_NACK_DEFER BIT(12)
27#define EDP_INTR_WRONG_DATA_CNT BIT(15)
28#define EDP_INTR_I2C_NACK BIT(18)
29#define EDP_INTR_I2C_DEFER BIT(21)
30#define EDP_INTR_PLL_UNLOCKED BIT(24)
31#define EDP_INTR_AUX_ERROR BIT(27)
32#define EDP_INTR_READY_FOR_VIDEO BIT(0)
33#define EDP_INTR_IDLE_PATTERN_SENT BIT(3)
34#define EDP_INTR_FRAME_END BIT(6)
35#define EDP_INTR_CRC_UPDATED BIT(9)
36#define EDP_INTR_SST_FIFO_UNDERFLOW BIT(28)
37#define REG_EDP_DP_HPD_CTRL (0x00000000)
38#define EDP_DP_HPD_CTRL_HPD_EN (0x00000001)
39#define EDP_DP_HPD_PLUG_INT_ACK (0x00000001)
40#define EDP_DP_IRQ_HPD_INT_ACK (0x00000002)
41#define EDP_DP_HPD_REPLUG_INT_ACK (0x00000004)
42#define EDP_DP_HPD_UNPLUG_INT_ACK (0x00000008)
43#define EDP_DP_HPD_STATE_STATUS_BITS_MASK (0x0000000F)
44#define EDP_DP_HPD_STATE_STATUS_BITS_SHIFT (0x1C)
45#define EDP_DP_HPD_PLUG_INT_MASK (0x00000001)
46#define EDP_DP_IRQ_HPD_INT_MASK (0x00000002)
47#define EDP_DP_HPD_REPLUG_INT_MASK (0x00000004)
48#define EDP_DP_HPD_UNPLUG_INT_MASK (0x00000008)
49#define EDP_DP_HPD_INT_MASK (EDP_DP_HPD_PLUG_INT_MASK | \
50 EDP_DP_IRQ_HPD_INT_MASK | \
51 EDP_DP_HPD_REPLUG_INT_MASK | \
52 EDP_DP_HPD_UNPLUG_INT_MASK)
53#define EDP_DP_HPD_STATE_STATUS_CONNECTED (0x40000000)
54#define EDP_DP_HPD_STATE_STATUS_PENDING (0x20000000)
55#define EDP_DP_HPD_STATE_STATUS_DISCONNECTED (0x00000000)
56#define EDP_DP_HPD_STATE_STATUS_MASK (0xE0000000)
57#define EDP_DP_HPD_REFTIMER_ENABLE (1 << 16)
58#define EDP_DP_HPD_EVENT_TIME_0_VAL (0x3E800FA)
59#define EDP_DP_HPD_EVENT_TIME_1_VAL (0x1F407D0)
60#define EDP_INTERRUPT_TRANS_NUM (0x000000A0)
61#define EDP_MAINLINK_CTRL_ENABLE (0x00000001)
62#define EDP_MAINLINK_CTRL_RESET (0x00000002)
63#define EDP_MAINLINK_CTRL_SW_BYPASS_SCRAMBLER (0x00000010)
64#define EDP_MAINLINK_FB_BOUNDARY_SEL (0x02000000)
65#define EDP_CONFIGURATION_CTRL_SYNC_ASYNC_CLK (0x00000001)
66#define EDP_CONFIGURATION_CTRL_STATIC_DYNAMIC_CN (0x00000002)
67#define EDP_CONFIGURATION_CTRL_P_INTERLACED (0x00000004)
68#define EDP_CONFIGURATION_CTRL_INTERLACED_BTF (0x00000008)
69#define EDP_CONFIGURATION_CTRL_NUM_OF_LANES (0x00000010)
70#define EDP_CONFIGURATION_CTRL_ENHANCED_FRAMING (0x00000040)
71#define EDP_CONFIGURATION_CTRL_SEND_VSC (0x00000080)
72#define EDP_CONFIGURATION_CTRL_BPC (0x00000100)
73#define EDP_CONFIGURATION_CTRL_ASSR (0x00000400)
74#define EDP_CONFIGURATION_CTRL_RGB_YUV (0x00000800)
75#define EDP_CONFIGURATION_CTRL_LSCLK_DIV (0x00002000)
76#define EDP_CONFIGURATION_CTRL_NUM_OF_LANES_SHIFT (0x04)
77#define EDP_CONFIGURATION_CTRL_BPC_SHIFT (0x08)
78#define EDP_CONFIGURATION_CTRL_LSCLK_DIV_SHIFT (0x0D)
79#define EDP_TOTAL_HOR_VER_HORIZ__MASK (0x0000FFFF)
80#define EDP_TOTAL_HOR_VER_HORIZ__SHIFT (0)
81#define DP_EDP_CONFIGURATION_CAP 0x00d /* XXX 1.2? */
82#define DP_ALTERNATE_SCRAMBLER_RESET_CAP (1 << 0)
83#define DP_FRAMING_CHANGE_CAP (1 << 1)
84#define DP_DPCD_DISPLAY_CONTROL_CAPABLE (1 << 3) /* edp v1.2 or higher */
85#define EDP_MISC0_SYNCHRONOUS_CLK (0x00000001)
86#define EDP_MISC0_COLORIMETRY_CFG_SHIFT (0x00000001)
87#define EDP_MISC0_TEST_BITS_DEPTH_SHIFT (0x00000005)
88#define LANE0_MAPPING_SHIFT (0x00000000)
89#define LANE1_MAPPING_SHIFT (0x00000002)
90#define LANE2_MAPPING_SHIFT (0x00000004)
91#define LANE3_MAPPING_SHIFT (0x00000006)
92#define EDP_MAINLINK_READY_FOR_VIDEO (0x00000001)
93#define EDP_MAINLINK_READY_TRAIN_PATTERN_1_READY (0x00000008)
94#define EDP_MAINLINK_SAFE_TO_EXIT_LEVEL_2 (0x00000002)
95#define EDP_LINK_BW_MAX DP_LINK_BW_5_4
96#define DP_RECEIVER_CAP_SIZE 0xf
97#define DP_LINK_STATUS_SIZE 6
98#define DP_TRAINING_AUX_RD_MASK 0x7F /* DP 1.3 */
99
100/* AUX CH addresses */
101/* DPCD */
102#define DP_DPCD_REV 0x000
103#define DP_DPCD_REV_10 0x10
104#define DP_DPCD_REV_11 0x11
105#define DP_DPCD_REV_12 0x12
106#define DP_DPCD_REV_13 0x13
107#define DP_DPCD_REV_14 0x14
108#define DP_SET_POWER 0x600
109#define DP_SET_POWER_D0 0x1
110#define DP_SET_POWER_D3 0x2
111#define DP_SET_POWER_MASK 0x3
112#define DP_MAX_LINK_RATE 0x001
113#define DP_MAX_LANE_COUNT 0x002
114#define DP_MAX_LANE_COUNT_MASK 0x1f
115#define DP_TPS3_SUPPORTED (1 << 6)
116#define DP_ENHANCED_FRAME_CAP (1 << 7)
117#define DP_MAX_DOWNSPREAD 0x003
118#define DP_NO_AUX_HANDSHAKE_LINK_TRAINING (1 << 6)
119#define DP_NORP 0x004
120#define DP_DOWNSTREAMPORT_PRESENT 0x005
121#define DP_DWN_STRM_PORT_PRESENT (1 << 0)
122#define DP_DWN_STRM_PORT_TYPE_MASK 0x06
123#define DP_FORMAT_CONVERSION (1 << 3)
124#define DP_MAIN_LINK_CHANNEL_CODING 0x006
125#define DP_EDP_CONFIGURATION_CAP 0x00d
126#define DP_TRAINING_AUX_RD_INTERVAL 0x00e
127
128/* link configuration */
129#define DP_LINK_BW_SET 0x100
130#define DP_LINK_RATE_TABLE 0x00 /* eDP 1.4 */
131#define DP_LINK_BW_1_62 0x06
132#define DP_LINK_BW_2_7 0x0a
133#define DP_LINK_BW_5_4 0x14 /* 1.2 */
134#define DP_LINK_BW_8_1 0x1e /* 1.4 */
135#define DP_LANE_COUNT_SET 0x101
136#define DP_LANE_COUNT_MASK 0x0f
137#define DP_LANE_COUNT_ENHANCED_FRAME_EN (1 << 7)
138#define DP_TRAINING_PATTERN_SET 0x102
139#define DP_TRAINING_PATTERN_DISABLE 0
140#define DP_TRAINING_PATTERN_1 1
141#define DP_TRAINING_PATTERN_2 2
142#define DP_TRAINING_PATTERN_3 3
143#define DP_TRAINING_PATTERN_MASK 0x3
144#define DP_LINK_QUAL_PATTERN_DISABLE (0 << 2)
145#define DP_LINK_QUAL_PATTERN_D10_2 (1 << 2)
146#define DP_LINK_QUAL_PATTERN_ERROR_RATE (2 << 2)
147#define DP_LINK_QUAL_PATTERN_PRBS7 (3 << 2)
148#define DP_LINK_QUAL_PATTERN_MASK (3 << 2)
149#define DP_RECOVERED_CLOCK_OUT_EN (1 << 4)
150#define DP_LINK_SCRAMBLING_DISABLE (1 << 5)
151#define DP_EDP_CONFIGURATION_SET 0x10a
152#define DP_ALTERNATE_SCRAMBLER_RESET_ENABLE (1 << 0)
153#define DP_FRAMING_CHANGE_ENABLE (1 << 1)
154#define DP_PANEL_SELF_TEST_ENABLE (1 << 7)
155#define DP_SYMBOL_ERROR_COUNT_BOTH (0 << 6)
156#define DP_SYMBOL_ERROR_COUNT_DISPARITY (1 << 6)
157#define DP_SYMBOL_ERROR_COUNT_SYMBOL (2 << 6)
158#define DP_SYMBOL_ERROR_COUNT_MASK (3 << 6)
159#define DP_TRAINING_LANE0_SET 0x103
160#define DP_TRAINING_LANE1_SET 0x104
161#define DP_TRAINING_LANE2_SET 0x105
162#define DP_TRAINING_LANE3_SET 0x106
163
164#define DP_TRAIN_VOLTAGE_SWING_MASK 0x3
165#define DP_TRAIN_VOLTAGE_SWING_SHIFT 0
166#define DP_TRAIN_MAX_SWING_REACHED (1 << 2)
167#define DP_TRAIN_VOLTAGE_SWING_400 (0 << 0)
168#define DP_TRAIN_VOLTAGE_SWING_600 (1 << 0)
169#define DP_TRAIN_VOLTAGE_SWING_800 (2 << 0)
170#define DP_TRAIN_VOLTAGE_SWING_1200 (3 << 0)
171#define DP_TRAIN_PRE_EMPHASIS_MASK (3 << 3)
172#define DP_TRAIN_PRE_EMPHASIS_0 (0 << 3)
173#define DP_TRAIN_PRE_EMPHASIS_3_5 (1 << 3)
174#define DP_TRAIN_PRE_EMPHASIS_6 (2 << 3)
175#define DP_TRAIN_PRE_EMPHASIS_9_5 (3 << 3)
176#define DP_TRAIN_PRE_EMPHASIS_SHIFT 3
177#define DP_TRAIN_MAX_PRE_EMPHASIS_REACHED (1 << 5)
178#define DP_DOWNSPREAD_CTRL 0x107
179#define DP_SPREAD_AMP_0_5 (1 << 4)
180#define DP_MAIN_LINK_CHANNEL_CODING_SET 0x108
181#define DP_SET_ANSI_8B10B (1 << 0)
182#define DP_LANE0_1_STATUS 0x202
183#define DP_LANE2_3_STATUS 0x203
184#define DP_LANE_CR_DONE (1 << 0)
185#define DP_LANE_CHANNEL_EQ_DONE (1 << 1)
186#define DP_LANE_SYMBOL_LOCKED (1 << 2)
187#define DP_CHANNEL_EQ_BITS (DP_LANE_CR_DONE | \
188 DP_LANE_CHANNEL_EQ_DONE | \
189 DP_LANE_SYMBOL_LOCKED)
190#define DP_LANE_ALIGN_STATUS_UPDATED 0x204
191#define DP_INTERLANE_ALIGN_DONE (1 << 0)
192#define DP_DOWNSTREAM_PORT_STATUS_CHANGED (1 << 6)
193#define DP_LINK_STATUS_UPDATED (1 << 7)
194#define DP_ADJUST_REQUEST_LANE0_1 0x206
195#define DP_ADJUST_REQUEST_LANE2_3 0x207
196#define DP_ADJUST_VOLTAGE_SWING_LANE0_MASK 0x03
197#define DP_ADJUST_VOLTAGE_SWING_LANE0_SHIFT 0
198#define DP_ADJUST_PRE_EMPHASIS_LANE0_MASK 0x0c
199#define DP_ADJUST_PRE_EMPHASIS_LANE0_SHIFT 2
200#define DP_ADJUST_VOLTAGE_SWING_LANE1_MASK 0x30
201#define DP_ADJUST_VOLTAGE_SWING_LANE1_SHIFT 4
202#define DP_ADJUST_PRE_EMPHASIS_LANE1_MASK 0xc0
203#define DP_ADJUST_PRE_EMPHASIS_LANE1_SHIFT 6
204#define DP_TEST_REQUEST 0x218
205#define DP_TEST_LINK_TRAINING (1 << 0)
206#define DP_TEST_LINK_PATTERN (1 << 1)
207#define DP_TEST_LINK_EDID_READ (1 << 2)
208#define DP_TEST_LINK_PHY_TEST_PATTERN (1 << 3) /* DPCD >= 1.1 */
209#define DP_TEST_LINK_RATE 0x219
210#define DP_LINK_RATE_162 (0x6)
211#define DP_LINK_RATE_27 (0xa)
212
213#define DP_TEST_LANE_COUNT 0x220
214#define DP_TEST_PATTERN 0x221
215#define DP_TEST_RESPONSE 0x260
216#define DP_TEST_ACK (1 << 0)
217#define DP_TEST_NAK (1 << 1)
218#define DP_TEST_EDID_CHECKSUM_WRITE (1 << 2)
219
220#define DP_SET_POWER 0x600
221#define DP_SET_POWER_D0 0x1
222#define DP_SET_POWER_D3 0x2
223
224/* Link training return value */
225#define EDP_TRAIN_FAIL -1
226#define EDP_TRAIN_SUCCESS 0
227#define EDP_TRAIN_RECONFIG 1
228
229#define EDP_INTERRUPT_STATUS_ACK_SHIFT 1
230#define EDP_INTERRUPT_STATUS_MASK_SHIFT 2
231
232#define EDP_INTERRUPT_STATUS1 \
233 (EDP_INTR_AUX_I2C_DONE| \
234 EDP_INTR_WRONG_ADDR | EDP_INTR_TIMEOUT | \
235 EDP_INTR_NACK_DEFER | EDP_INTR_WRONG_DATA_CNT | \
236 EDP_INTR_I2C_NACK | EDP_INTR_I2C_DEFER | \
237 EDP_INTR_PLL_UNLOCKED | EDP_INTR_AUX_ERROR)
238
239#define EDP_INTERRUPT_STATUS1_ACK \
240 (EDP_INTERRUPT_STATUS1 << EDP_INTERRUPT_STATUS_ACK_SHIFT)
241#define EDP_INTERRUPT_STATUS1_MASK \
242 (EDP_INTERRUPT_STATUS1 << EDP_INTERRUPT_STATUS_MASK_SHIFT)
243
244#define EDP_INTERRUPT_STATUS2 \
245 (EDP_INTR_READY_FOR_VIDEO | EDP_INTR_IDLE_PATTERN_SENT | \
246 EDP_INTR_FRAME_END | EDP_INTR_CRC_UPDATED | EDP_INTR_SST_FIFO_UNDERFLOW)
247
248#define EDP_INTERRUPT_STATUS2_ACK \
249 (EDP_INTERRUPT_STATUS2 << EDP_INTERRUPT_STATUS_ACK_SHIFT)
250#define EDP_INTERRUPT_STATUS2_MASK \
251 (EDP_INTERRUPT_STATUS2 << EDP_INTERRUPT_STATUS_MASK_SHIFT)
252
253enum edp_color_depth {
254 EDP_6BIT = 0,
255 EDP_8BIT = 1,
256 EDP_10BIT = 2,
257 EDP_12BIT = 3,
258 EDP_16BIT = 4,
259};
260
261struct tu_algo_data {
262 int64_t lclk_fp;
263 int64_t lclk;
264 int64_t pclk;
265 int64_t pclk_fp;
266 int64_t lwidth;
267 int64_t lwidth_fp;
268 int64_t hbp_relative_to_pclk;
269 int64_t hbp_relative_to_pclk_fp;
270 int nlanes;
271 int bpp;
272 int async_en;
273 int bpc;
274 int delay_start_link_extra_pclk;
275 int extra_buffer_margin;
276 int64_t ratio_fp;
277 int64_t original_ratio_fp;
278 int64_t err_fp;
279 int64_t old_err_fp;
280 int64_t new_err_fp;
281 int tu_size;
282 int tu_size_desired;
283 int tu_size_minus1;
284 int valid_boundary_link;
285 int64_t resulting_valid_fp;
286 int64_t total_valid_fp;
287 int64_t effective_valid_fp;
288 int64_t effective_valid_recorded_fp;
289 int num_tus;
290 int num_tus_per_lane;
291 int paired_tus;
292 int remainder_tus;
293 int remainder_tus_upper;
294 int remainder_tus_lower;
295 int extra_bytes;
296 int filler_size;
297 int delay_start_link;
298 int extra_pclk_cycles;
299 int extra_pclk_cycles_in_link_clk;
300 int64_t ratio_by_tu_fp;
301 int64_t average_valid2_fp;
302 int new_valid_boundary_link;
303 int remainder_symbols_exist;
304 int n_symbols;
305 int64_t n_remainder_symbols_per_lane_fp;
306 int64_t last_partial_tu_fp;
307 int64_t TU_ratio_err_fp;
308 int n_tus_incl_last_incomplete_tu;
309 int extra_pclk_cycles_tmp;
310 int extra_pclk_cycles_in_link_clk_tmp;
311 int extra_required_bytes_new_tmp;
312 int filler_size_tmp;
313 int lower_filler_size_tmp;
314 int delay_start_link_tmp;
315 bool boundary_moderation_en;
316 int boundary_mod_lower_err;
317 int upper_boundary_count;
318 int lower_boundary_count;
319 int i_upper_boundary_count;
320 int i_lower_boundary_count;
321 int valid_lower_boundary_link;
322 int even_distribution_BF;
323 int even_distribution_legacy;
324 int even_distribution;
325 int min_hblank_violated;
326 int64_t delay_start_time_fp;
327 int64_t hbp_time_fp;
328 int64_t hactive_time_fp;
329 int64_t diff_abs_fp;
330 int64_t ratio;
331};
332
333struct edp_ctrl {
334 /* Link status */
335 uint32_t link_rate_khz;
336 uint8_t link_rate;
337 uint32_t lane_cnt;
338 uint8_t v_level;
339 uint8_t p_level;
340
341 /* Timing status */
342 uint32_t pixel_rate; /* in kHz */
343 uint32_t color_depth;
344};
345
346struct edp_ctrl_tu {
347 uint32_t tu_size_minus1; /* Desired TU Size */
348 uint32_t valid_boundary_link; /* Upper valid boundary */
349 uint32_t delay_start_link; /* # of clock cycles to delay */
350 bool boundary_moderation_en; /* Enable boundary Moderation? */
351 uint32_t valid_lower_boundary_link; /* Valid lower boundary link */
352 uint32_t upper_boundary_count; /* Upper boundary Count */
353 uint32_t lower_boundary_count; /* Lower boundary Count */
354};
355
356static uint8_t dp_get_lane_status(const uint8_t link_status[DP_LINK_STATUS_SIZE], int lane)
357{
358 int i = DP_LANE0_1_STATUS + (lane >> 1);
359 int s = (lane & 1) * 4;
360 uint8_t l = link_status[i - DP_LANE0_1_STATUS];
361 return (l >> s) & 0xf;
362}
363
364
365static uint8_t edp_get_adjust_request_voltage(
366 const uint8_t link_status[DP_LINK_STATUS_SIZE],
367 int lane)
368{
369 int i = DP_ADJUST_REQUEST_LANE0_1 + (lane >> 1);
370 int s = ((lane & 1) ?
371 DP_ADJUST_VOLTAGE_SWING_LANE1_SHIFT :
372 DP_ADJUST_VOLTAGE_SWING_LANE0_SHIFT);
373 uint8_t l = link_status[i - DP_LANE0_1_STATUS];
374
375 return ((l >> s) & 0x3) << DP_TRAIN_VOLTAGE_SWING_SHIFT;
376}
377
378static uint8_t edp_get_adjust_request_pre_emphasis(
379 const uint8_t link_status[DP_LINK_STATUS_SIZE],
380 int lane)
381{
382 int i = DP_ADJUST_REQUEST_LANE0_1 + (lane >> 1);
383 int s = ((lane & 1) ?
384 DP_ADJUST_PRE_EMPHASIS_LANE1_SHIFT :
385 DP_ADJUST_PRE_EMPHASIS_LANE0_SHIFT);
386 uint8_t l = link_status[i - DP_LANE0_1_STATUS];
387
388 return ((l >> s) & 0x3) << DP_TRAIN_PRE_EMPHASIS_SHIFT;
389}
390
391static void edp_link_train_clock_recovery_delay(const uint8_t dpcd[DP_RECEIVER_CAP_SIZE])
392{
393 int rd_interval = dpcd[DP_TRAINING_AUX_RD_INTERVAL] & DP_TRAINING_AUX_RD_MASK;
394
395 if (rd_interval > 4)
396 printk(BIOS_ERR, "AUX interval %d, out of range (max 4)\n", rd_interval);
397
398 /*
399 * The DPCD stores the AUX read interval in units of 4 ms.
400 * for DP v1.4 and above, clock recovery should use 100 us for AUX read intervals.
401 */
402 if (rd_interval == 0 || dpcd[DP_DPCD_REV] >= DP_DPCD_REV_14)
403 udelay(100);
404 else
405 mdelay(rd_interval * 4);
406}
407
408static bool edp_clock_recovery_ok(const uint8_t link_status[DP_LINK_STATUS_SIZE],
409 int lane_count)
410{
411 int lane;
412 uint8_t lane_status;
413
414 for (lane = 0; lane < lane_count; lane++) {
415 lane_status = dp_get_lane_status(link_status, lane);
416 if ((lane_status & DP_LANE_CR_DONE) == 0) {
417 printk(BIOS_ERR, "clock recovery ok failed : %x\n", lane_status);
418 return false;
419 }
420 }
421 return true;
422}
423
424static void edp_link_train_channel_eq_delay(const uint8_t dpcd[DP_RECEIVER_CAP_SIZE])
425{
426 int rd_interval = dpcd[DP_TRAINING_AUX_RD_INTERVAL] &
427 DP_TRAINING_AUX_RD_MASK;
428
429 if (rd_interval > 4)
430 printk(BIOS_INFO, "AUX interval %d, out of range (max 4)\n",
431 rd_interval);
432
433 /*
434 * The DPCD stores the AUX read interval in units of 4 ms.
435 * if the TRAINING_AUX_RD_INTERVAL field is 0, the channel equalization
436 * should use 400 us AUX read intervals.
437 */
438 if (rd_interval == 0)
439 udelay(400);
440 else
441 mdelay(rd_interval * 4);
442}
443
444static bool edp_channel_eq_ok(const uint8_t link_status[DP_LINK_STATUS_SIZE], int lane_count)
445{
446 uint8_t lane_align;
447 uint8_t lane_status;
448 int lane;
449
450 lane_align = link_status[DP_LANE_ALIGN_STATUS_UPDATED - DP_LANE0_1_STATUS];
451 if ((lane_align & DP_INTERLANE_ALIGN_DONE) == 0)
452 return false;
453
454 for (lane = 0; lane < lane_count; lane++) {
455 lane_status = dp_get_lane_status(link_status, lane);
456 if ((lane_status & DP_CHANNEL_EQ_BITS) != DP_CHANNEL_EQ_BITS)
457 return false;
458 }
459 return true;
460}
461
462static void edp_ctrl_irq_enable(int enable)
463{
464 if (enable) {
465 write32(&edp_ahbclk->interrupt_status, EDP_INTERRUPT_STATUS1_MASK);
466 write32(&edp_ahbclk->interrupt_status2,
467 EDP_INTERRUPT_STATUS2_MASK);
468 } else {
469 write32(&edp_ahbclk->interrupt_status,
470 EDP_INTERRUPT_STATUS1_ACK);
471 write32(&edp_ahbclk->interrupt_status2,
472 EDP_INTERRUPT_STATUS2_ACK);
473 }
474}
475
476static void edp_config_ctrl(struct edp_ctrl *ctrl, uint8_t *dpcd)
477{
478 uint32_t config = 0, depth = 0;
479
480 /* Default-> LSCLK DIV: 1/4 LCLK */
481 config |= (2 << EDP_CONFIGURATION_CTRL_LSCLK_DIV_SHIFT);
482
483 /* Scrambler reset enable */
484 if (dpcd[DP_EDP_CONFIGURATION_CAP] & DP_ALTERNATE_SCRAMBLER_RESET_CAP)
485 config |= EDP_CONFIGURATION_CTRL_ASSR;
486
487 if (ctrl->color_depth == 8)
488 depth = EDP_8BIT;
489 else if (ctrl->color_depth == 10)
490 depth = EDP_10BIT;
491 else if (ctrl->color_depth == 12)
492 depth = EDP_12BIT;
493 else if (ctrl->color_depth == 16)
494 depth = EDP_16BIT;
Vinod Polimera50bdc612023-02-03 10:59:56 +0530495 else
496 depth = EDP_6BIT;
497
Vinod Polimera4e93e942022-02-25 13:21:42 +0530498 config |= depth << EDP_CONFIGURATION_CTRL_BPC_SHIFT;
499
500 /* Num of Lanes */
501 config |= ((ctrl->lane_cnt - 1)
502 << EDP_CONFIGURATION_CTRL_NUM_OF_LANES_SHIFT);
503
504 if (dpcd[DP_DPCD_REV] >= 0x11 &&
505 (dpcd[DP_MAX_LANE_COUNT] & DP_ENHANCED_FRAME_CAP))
506 config |= EDP_CONFIGURATION_CTRL_ENHANCED_FRAMING;
507
508 config |= EDP_CONFIGURATION_CTRL_P_INTERLACED; /* progressive video */
509
510 /* sync clock & static Mvid */
511 config |= EDP_CONFIGURATION_CTRL_STATIC_DYNAMIC_CN;
512 config |= EDP_CONFIGURATION_CTRL_SYNC_ASYNC_CLK;
513
514 write32(&edp_lclk->configuration_ctrl, config);
515}
516
517static void edp_state_ctrl(uint32_t state)
518{
519 write32(&edp_lclk->state_ctrl, state);
520}
521
522static int edp_lane_set_write(uint8_t voltage_level, uint8_t pre_emphasis_level)
523{
524 int i;
525 uint8_t buf[4];
526
527 if (voltage_level >= DPCD_LINK_VOLTAGE_MAX)
528 voltage_level |= 0x04;
529
530 if (pre_emphasis_level >= DPCD_LINK_PRE_EMPHASIS_MAX)
531 pre_emphasis_level |= 0x20;
532
533 for (i = 0; i < 4; i++)
534 buf[i] = voltage_level | pre_emphasis_level;
535
536 if (edp_aux_transfer(DP_TRAINING_LANE0_SET, DP_AUX_NATIVE_WRITE, buf, 2) < 2) {
537 printk(BIOS_ERR, "%s: Set sw/pe to panel failed\n", __func__);
538 return -1;
539 }
540
541 return 0;
542}
543
544static int edp_train_pattern_set_write(uint8_t pattern)
545{
546 uint8_t p = pattern;
547
548 printk(BIOS_INFO, "pattern=%x\n", p);
549 if (edp_aux_transfer(DP_TRAINING_PATTERN_SET, DP_AUX_NATIVE_WRITE, &p, 1) < 1) {
550 printk(BIOS_ERR, "%s: Set training pattern to panel failed\n", __func__);
551 return -1;
552 }
553
554 return 0;
555}
556
557static void edp_sink_train_set_adjust(struct edp_ctrl *ctrl,
558 const uint8_t *link_status)
559{
560 int i;
561 uint8_t max = 0;
562 uint8_t data;
563
564 /* use the max level across lanes */
565 for (i = 0; i < ctrl->lane_cnt; i++) {
566 data = edp_get_adjust_request_voltage(link_status, i);
567 printk(BIOS_INFO, "lane=%d req_voltage_swing=0x%x\n", i, data);
568 if (max < data)
569 max = data;
570 }
571
572 ctrl->v_level = max >> DP_TRAIN_VOLTAGE_SWING_SHIFT;
573
574 /* use the max level across lanes */
575 max = 0;
576 for (i = 0; i < ctrl->lane_cnt; i++) {
577 data = edp_get_adjust_request_pre_emphasis(link_status, i);
578 printk(BIOS_INFO, "lane=%d req_pre_emphasis=0x%x\n", i, data);
579 if (max < data)
580 max = data;
581 }
582
583 ctrl->p_level = max >> DP_TRAIN_PRE_EMPHASIS_SHIFT;
584 printk(BIOS_INFO, "v_level=%d, p_level=%d\n", ctrl->v_level, ctrl->p_level);
585}
586
587static void edp_host_train_set(uint32_t train)
588{
589 int cnt = 10;
590 uint32_t data = 0;
591 uint32_t shift = train - 1;
592
Yu-Ping Wufae1eb32023-08-21 16:02:57 +0800593 printk(BIOS_INFO, "train=%d\n", train);
Vinod Polimera4e93e942022-02-25 13:21:42 +0530594
595 edp_state_ctrl(SW_LINK_TRAINING_PATTERN1 << shift);
596 while (--cnt) {
597 data = read32(&edp_lclk->mainlink_ready);
598 if (data & (EDP_MAINLINK_READY_TRAIN_PATTERN_1_READY << shift))
599 break;
600 }
601
602 if (cnt == 0)
603 printk(BIOS_INFO, "%s: set link_train=%u failed\n", __func__, data);
604}
605
606static int edp_voltage_pre_emphasis_set(struct edp_ctrl *ctrl)
607{
608 printk(BIOS_INFO, "v=%d p=%d\n", ctrl->v_level, ctrl->p_level);
609
610 edp_phy_config(ctrl->v_level, ctrl->p_level);
611 return edp_lane_set_write(ctrl->v_level, ctrl->p_level);
612}
613
614static int edp_start_link_train_1(struct edp_ctrl *ctrl, uint8_t *dpcd)
615{
616 uint8_t link_status[DP_LINK_STATUS_SIZE];
617 uint8_t old_v_level;
618 int tries;
619 int ret, rlen;
620
621 edp_state_ctrl(0);
622 edp_host_train_set(DP_TRAINING_PATTERN_1);
623
624 ret = edp_train_pattern_set_write(DP_TRAINING_PATTERN_1 | DP_LINK_SCRAMBLING_DISABLE);
625 if (ret)
626 return ret;
627
628 ret = edp_voltage_pre_emphasis_set(ctrl);
629 if (ret)
630 return ret;
631
632 tries = 0;
633 old_v_level = ctrl->v_level;
634 while (1) {
635 edp_link_train_clock_recovery_delay(dpcd);
636
637 rlen = edp_aux_transfer(DP_LANE0_1_STATUS, DP_AUX_NATIVE_READ,
638 &link_status, DP_LINK_STATUS_SIZE);
639 if (rlen < DP_LINK_STATUS_SIZE) {
640 printk(BIOS_ERR, "%s: read link status failed\n", __func__);
641 return -1;
642 }
643
644 if (edp_clock_recovery_ok(link_status, ctrl->lane_cnt)) {
645 ret = 0;
646 break;
647 }
648
649 if (ctrl->v_level == DPCD_LINK_VOLTAGE_MAX) {
650 ret = -1;
651 break;
652 }
653
654 if (old_v_level != ctrl->v_level) {
655 tries++;
656 if (tries >= 5) {
657 ret = -1;
658 break;
659 }
660 } else {
661 tries = 0;
662 old_v_level = ctrl->v_level;
663 }
664
665 edp_sink_train_set_adjust(ctrl, link_status);
666 ret = edp_voltage_pre_emphasis_set(ctrl);
667 if (ret)
668 return ret;
669 }
670
671 return 0;
672}
673
674static int edp_start_link_train_2(struct edp_ctrl *ctrl, uint8_t *dpcd)
675{
676 uint8_t link_status[DP_LINK_STATUS_SIZE];
677 int tries = 0;
678 int ret, rlen;
679
680 edp_host_train_set(DP_TRAINING_PATTERN_2);
681 ret = edp_voltage_pre_emphasis_set(ctrl);
682 if (ret)
683 return ret;
684
685 ret = edp_train_pattern_set_write(DP_TRAINING_PATTERN_2 | DP_RECOVERED_CLOCK_OUT_EN);
686 if (ret)
687 return ret;
688
689 while (1) {
690 edp_link_train_channel_eq_delay(dpcd);
691
692 rlen = edp_aux_transfer(DP_LANE0_1_STATUS, DP_AUX_NATIVE_READ,
693 &link_status, DP_LINK_STATUS_SIZE);
694 if (rlen < DP_LINK_STATUS_SIZE) {
695 printk(BIOS_ERR, "%s: read link status failed\n", __func__);
696 return -1;
697 }
698
699 if (edp_channel_eq_ok(link_status, ctrl->lane_cnt)) {
700 ret = 0;
701 break;
702 }
703
704 tries++;
705 if (tries > 10) {
706 ret = -1;
707 break;
708 }
709
710 edp_sink_train_set_adjust(ctrl, link_status);
711 ret = edp_voltage_pre_emphasis_set(ctrl);
712 if (ret)
713 return ret;
714 }
715
716 return ret;
717}
718
719static int edp_link_rate_down_shift(struct edp_ctrl *ctrl, uint8_t *dpcd)
720{
721 int ret = 0;
722 int link_rate = ctrl->link_rate_khz;
723
724 switch (link_rate) {
725 case 810000:
726 link_rate = 540000;
727 break;
728 case 540000:
729 link_rate = 270000;
730 break;
731 case 270000:
732 link_rate = 162000;
733 break;
734 case 162000:
735 default:
736 ret = -1;
737 break;
738 }
739
740 if (!ret) {
741 ctrl->link_rate_khz = link_rate;
742 ctrl->link_rate = link_rate / 27000;
743 printk(BIOS_INFO, "new rate=0x%x\n", ctrl->link_rate_khz);
Vinod Polimera042ba162022-08-23 14:25:02 +0530744 }
Vinod Polimera4e93e942022-02-25 13:21:42 +0530745
746 return ret;
747}
748
749static bool edp_clock_recovery_reduced_lanes(
750 const uint8_t link_status[DP_LINK_STATUS_SIZE], uint32_t lane_cnt)
751{
752 int reduced_lanes = 0;
753
754 if (lane_cnt <= 1)
755 return -1;
756
757 reduced_lanes = lane_cnt >> 1;
758
759 return edp_clock_recovery_ok(link_status, reduced_lanes);
760}
761
762static int edp_link_lane_down_shift(struct edp_ctrl *ctrl, uint8_t *dpcd)
763{
Vinod Polimera4e93e942022-02-25 13:21:42 +0530764 if (ctrl->lane_cnt <= 1)
765 return -1;
766
767 ctrl->lane_cnt = ctrl->lane_cnt >> 1;
768 ctrl->link_rate_khz = dpcd[DP_MAX_LINK_RATE] * 27000;
769 ctrl->link_rate = dpcd[DP_MAX_LINK_RATE];
770 ctrl->p_level = 0;
771 ctrl->v_level = 0;
772
773 return 0;
774}
775
776static int edp_clear_training_pattern(uint8_t *dpcd)
777{
778 int ret;
779
780 ret = edp_train_pattern_set_write(0);
781 edp_link_train_channel_eq_delay(dpcd);
782
783 return ret;
784}
785
786static int edp_do_link_train(struct edp_ctrl *ctrl, uint8_t *dpcd)
787{
788 uint8_t values[2], edp_config = 0;
789 int ret;
790 int rlen;
791 uint8_t link_status[DP_LINK_STATUS_SIZE];
792
793 /*
794 * Set the current link rate and lane cnt to panel. They may have been
795 * adjusted and the values are different from them in DPCD CAP
796 */
797
798 values[0] = ctrl->link_rate;
799 values[1] = ctrl->lane_cnt;
800
801 if (dpcd[DP_DPCD_REV] >= 0x11 &&
802 (dpcd[DP_MAX_LANE_COUNT] & DP_ENHANCED_FRAME_CAP))
803 values[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
804
805 if (edp_aux_transfer(DP_LINK_BW_SET, DP_AUX_NATIVE_WRITE, &values[0], 1) < 0)
806 return EDP_TRAIN_FAIL;
807
808 edp_aux_transfer(DP_LANE_COUNT_SET, DP_AUX_NATIVE_WRITE, &values[1], 1);
809 ctrl->v_level = 0; /* start from default level */
810 ctrl->p_level = 0;
811
812 values[0] = 0x10;
813
814 if (dpcd[DP_MAX_DOWNSPREAD] & 1)
815 values[0] = DP_SPREAD_AMP_0_5;
816
817 values[1] = 1;
818 edp_aux_transfer(DP_DOWNSPREAD_CTRL, DP_AUX_NATIVE_WRITE, &values[0], 1);
819 edp_aux_transfer(DP_MAIN_LINK_CHANNEL_CODING_SET, DP_AUX_NATIVE_WRITE, &values[1], 1);
820
821 ret = edp_start_link_train_1(ctrl, dpcd);
822 if (ret < 0) {
823 rlen = edp_aux_transfer(DP_LANE0_1_STATUS, DP_AUX_NATIVE_READ,
824 &link_status, DP_LINK_STATUS_SIZE);
825 if (rlen < DP_LINK_STATUS_SIZE) {
826 printk(BIOS_ERR, "%s: read link status failed\n", __func__);
827 return -1;
828 }
829
830 ret = edp_link_rate_down_shift(ctrl, dpcd);
831 if (!ret) {
832 printk(BIOS_ERR, "link reconfig\n");
833 ret = EDP_TRAIN_RECONFIG;
834 } else if (ret < 0) {
835 if (edp_clock_recovery_reduced_lanes(link_status,
836 ctrl->lane_cnt) == 0) {
837 if (edp_link_lane_down_shift(ctrl, dpcd) < 0) {
838 printk(BIOS_ERR, "%s: Training 1 failed\n", __func__);
839 ret = EDP_TRAIN_FAIL;
840 } else {
841 printk(BIOS_ERR, "link reconfig\n");
842 ret = EDP_TRAIN_RECONFIG;
843 }
844 } else {
845 printk(BIOS_ERR, "%s: Training 1 failed\n", __func__);
846 ret = EDP_TRAIN_FAIL;
847 }
848 }
849 edp_clear_training_pattern(dpcd);
850 return ret;
851 }
852
853 printk(BIOS_INFO, "Training 1 completed successfully\n");
854 edp_state_ctrl(0);
855 if (edp_clear_training_pattern(dpcd))
856 return EDP_TRAIN_FAIL;
857
858 ret = edp_start_link_train_2(ctrl, dpcd);
859 if (ret < 0) {
860 rlen = edp_aux_transfer(DP_LANE0_1_STATUS, DP_AUX_NATIVE_READ,
861 &link_status, DP_LINK_STATUS_SIZE);
862 if (rlen < DP_LINK_STATUS_SIZE) {
863 printk(BIOS_ERR, "%s: read link status failed\n", __func__);
864 return -1;
865 }
866
867 if (edp_clock_recovery_ok(link_status, ctrl->lane_cnt)) {
868 if (edp_link_rate_down_shift(ctrl, dpcd) == 0) {
869 printk(BIOS_ERR, "link reconfig\n");
870 ret = EDP_TRAIN_RECONFIG;
871 } else {
872 printk(BIOS_ERR, "%s: Training 2 failed\n", __func__);
873 ret = EDP_TRAIN_FAIL;
874 }
875 } else {
876 if (edp_link_lane_down_shift(ctrl, dpcd) < 0) {
877 printk(BIOS_ERR, "%s: Training 1 failed\n", __func__);
878 ret = EDP_TRAIN_FAIL;
879 } else {
880 printk(BIOS_ERR, "link reconfig\n");
881 ret = EDP_TRAIN_RECONFIG;
882 }
883 }
884
885 edp_clear_training_pattern(dpcd);
886 return ret;
887 }
888
889 printk(BIOS_INFO, "Training 2 completed successfully\n");
890 edp_config = DP_ALTERNATE_SCRAMBLER_RESET_ENABLE;
891 edp_aux_transfer(DP_EDP_CONFIGURATION_SET, DP_AUX_NATIVE_WRITE, &edp_config, 1);
892
893 return ret;
894}
895
896static void edp_ctrl_config_misc(struct edp_ctrl *ctrl)
897{
898 uint32_t misc_val;
Vinod Polimera50bdc612023-02-03 10:59:56 +0530899 enum edp_color_depth depth = EDP_6BIT;
Vinod Polimera4e93e942022-02-25 13:21:42 +0530900
901 misc_val = read32(&edp_lclk->misc1_misc0);
902 if (ctrl->color_depth == 8)
903 depth = EDP_8BIT;
904 else if (ctrl->color_depth == 10)
905 depth = EDP_10BIT;
906 else if (ctrl->color_depth == 12)
907 depth = EDP_12BIT;
908 else if (ctrl->color_depth == 16)
909 depth = EDP_16BIT;
910
911 /* clear bpp bits */
912 misc_val &= ~(0x07 << EDP_MISC0_TEST_BITS_DEPTH_SHIFT);
913 misc_val |= depth << EDP_MISC0_TEST_BITS_DEPTH_SHIFT;
914
915 /* Configure clock to synchronous mode */
916 misc_val |= EDP_MISC0_SYNCHRONOUS_CLK;
917 write32(&edp_lclk->misc1_misc0, misc_val);
918}
919
Vinod Polimera042ba162022-08-23 14:25:02 +0530920static int edp_ctrl_pixel_clock_dividers(struct edp_ctrl *ctrl,
Vinod Polimera4e93e942022-02-25 13:21:42 +0530921 uint32_t *pixel_m, uint32_t *pixel_n)
922{
923 uint32_t pixel_div = 0, dispcc_input_rate;
924 unsigned long den, num;
925 uint8_t rate = ctrl->link_rate;
926 uint32_t stream_rate_khz = ctrl->pixel_rate;
927
Vinod Polimera042ba162022-08-23 14:25:02 +0530928 if (rate == DP_LINK_BW_8_1) {
Vinod Polimera4e93e942022-02-25 13:21:42 +0530929 pixel_div = 6;
Vinod Polimera042ba162022-08-23 14:25:02 +0530930 } else if (rate == DP_LINK_BW_1_62 || rate == DP_LINK_BW_2_7) {
Vinod Polimera4e93e942022-02-25 13:21:42 +0530931 pixel_div = 2;
Vinod Polimera042ba162022-08-23 14:25:02 +0530932 } else if (rate == DP_LINK_BW_5_4) {
Vinod Polimera4e93e942022-02-25 13:21:42 +0530933 pixel_div = 4;
Vinod Polimera042ba162022-08-23 14:25:02 +0530934 } else {
Vinod Polimera4e93e942022-02-25 13:21:42 +0530935 printk(BIOS_ERR, "Invalid pixel mux divider\n");
Vinod Polimera042ba162022-08-23 14:25:02 +0530936 return -1;
937 }
Vinod Polimera4e93e942022-02-25 13:21:42 +0530938
939 dispcc_input_rate = (ctrl->link_rate_khz * 10) / pixel_div;
940
941 rational_best_approximation(dispcc_input_rate, stream_rate_khz,
942 (unsigned long)(1 << 16) - 1,
943 (unsigned long)(1 << 16) - 1, &den, &num);
944 *pixel_m = num;
945 *pixel_n = den;
Vinod Polimera042ba162022-08-23 14:25:02 +0530946
947 return 0;
Vinod Polimera4e93e942022-02-25 13:21:42 +0530948}
949
Vinod Polimera042ba162022-08-23 14:25:02 +0530950static int edp_ctrl_config_msa(struct edp_ctrl *ctrl)
Vinod Polimera4e93e942022-02-25 13:21:42 +0530951{
952 uint32_t pixel_m, pixel_n;
953 uint32_t mvid, nvid;
954 u32 const nvid_fixed = 0x8000;
955 uint8_t rate = ctrl->link_rate;
956
Vinod Polimera042ba162022-08-23 14:25:02 +0530957 if (edp_ctrl_pixel_clock_dividers(ctrl, &pixel_m, &pixel_n) < 0)
958 return -1;
959
Vinod Polimera4e93e942022-02-25 13:21:42 +0530960 pixel_n = ~(pixel_n - pixel_m);
961 pixel_n = pixel_n & 0xFFFF;
962 mvid = (pixel_m & 0xFFFF) * 5;
963 nvid = (0xFFFF & (~pixel_n)) + (pixel_m & 0xFFFF);
964
965 if (nvid < nvid_fixed) {
966 u32 temp;
967
968 temp = (nvid_fixed / nvid) * nvid;
969 mvid = (nvid_fixed / nvid) * mvid;
970 nvid = temp;
971 }
972
973 if (rate == DP_LINK_BW_5_4)
974 nvid *= 2;
975
976 if (rate == DP_LINK_BW_8_1)
977 nvid *= 3;
978
979 printk(BIOS_INFO, "mvid=0x%x, nvid=0x%x\n", mvid, nvid);
980 write32(&edp_lclk->software_mvid, mvid);
981 write32(&edp_lclk->software_nvid, nvid);
982 write32(&edp_p0clk->dsc_dto, 0x0);
Vinod Polimera042ba162022-08-23 14:25:02 +0530983
984 return 0;
Vinod Polimera4e93e942022-02-25 13:21:42 +0530985}
986
987static void tu_valid_boundary_calc(struct tu_algo_data *tu)
988{
989 int64_t f = 100000;
990
991 tu->new_valid_boundary_link = DIV_ROUND_UP(tu->tu_size * tu->ratio_fp, f);
992 tu->average_valid2_fp = ((tu->i_upper_boundary_count * tu->new_valid_boundary_link +
993 tu->i_lower_boundary_count *
994 (tu->new_valid_boundary_link - 1)) * f) /
995 (tu->i_upper_boundary_count + tu->i_lower_boundary_count);
996 tu->num_tus = ((tu->bpp * tu->lwidth_fp) / 8) / tu->average_valid2_fp;
997 tu->n_remainder_symbols_per_lane_fp = ((tu->n_symbols * f) -
998 (tu->num_tus * tu->average_valid2_fp)) /
999 tu->nlanes;
1000 tu->last_partial_tu_fp = (tu->n_remainder_symbols_per_lane_fp / tu->tu_size);
1001 if (tu->n_remainder_symbols_per_lane_fp != 0)
1002 tu->remainder_symbols_exist = 1;
1003 else
1004 tu->remainder_symbols_exist = 0;
1005
1006 tu->num_tus_per_lane = tu->num_tus / tu->nlanes;
1007 tu->paired_tus = (int)((tu->num_tus_per_lane) / (tu->i_upper_boundary_count +
1008 tu->i_lower_boundary_count));
1009 tu->remainder_tus = tu->num_tus_per_lane - tu->paired_tus *
1010 (tu->i_upper_boundary_count + tu->i_lower_boundary_count);
1011 if ((tu->remainder_tus - tu->i_upper_boundary_count) > 0) {
1012 tu->remainder_tus_upper = tu->i_upper_boundary_count;
1013 tu->remainder_tus_lower = tu->remainder_tus - tu->i_upper_boundary_count;
1014 } else {
1015 tu->remainder_tus_upper = tu->remainder_tus;
1016 tu->remainder_tus_lower = 0;
1017 }
1018
1019 tu->total_valid_fp = (tu->paired_tus * (tu->i_upper_boundary_count *
1020 tu->new_valid_boundary_link + tu->i_lower_boundary_count *
1021 (tu->new_valid_boundary_link - 1)) + (tu->remainder_tus_upper *
1022 tu->new_valid_boundary_link) + (tu->remainder_tus_lower *
1023 (tu->new_valid_boundary_link - 1))) * f;
1024 if (tu->remainder_symbols_exist) {
1025 tu->effective_valid_fp = (((tu->total_valid_fp +
1026 tu->n_remainder_symbols_per_lane_fp) * f) /
1027 (tu->num_tus_per_lane * f + tu->last_partial_tu_fp));
1028 } else {
1029 tu->effective_valid_fp = (tu->total_valid_fp / tu->num_tus_per_lane);
1030 }
1031
1032 tu->new_err_fp = tu->effective_valid_fp - (tu->ratio_fp * tu->tu_size);
1033 tu->old_err_fp = tu->average_valid2_fp - (tu->ratio_fp * tu->tu_size);
1034 tu->even_distribution = tu->num_tus % tu->nlanes == 0 ? 1 : 0;
1035 tu->n_tus_incl_last_incomplete_tu = DIV_ROUND_UP((tu->bpp * tu->lwidth_fp / 8),
1036 tu->average_valid2_fp);
1037 tu->extra_required_bytes_new_tmp = DIV_ROUND_UP((tu->average_valid2_fp - (tu->tu_size *
1038 tu->original_ratio_fp)) *
1039 tu->n_tus_incl_last_incomplete_tu, f);
1040 tu->extra_required_bytes_new_tmp += DIV_ROUND_UP(((tu->i_upper_boundary_count *
1041 tu->nlanes) *
1042 (tu->new_valid_boundary_link * f -
1043 tu->tu_size * tu->original_ratio_fp)),
1044 f);
1045 tu->extra_pclk_cycles_tmp = DIV_ROUND_UP(8 * tu->extra_required_bytes_new_tmp,
1046 tu->bpp);
1047 tu->extra_pclk_cycles_in_link_clk_tmp = DIV_ROUND_UP(tu->extra_pclk_cycles_tmp *
1048 tu->lclk_fp, tu->pclk_fp);
1049 tu->filler_size_tmp = tu->tu_size - tu->new_valid_boundary_link;
1050 tu->lower_filler_size_tmp = tu->filler_size_tmp + 1;
1051 tu->delay_start_link_tmp = tu->extra_pclk_cycles_in_link_clk_tmp +
1052 tu->lower_filler_size_tmp + tu->extra_buffer_margin;
1053 tu->delay_start_time_fp = tu->delay_start_link_tmp * f / tu->lclk;
1054 if (((tu->even_distribution == 1) ||
1055 ((tu->even_distribution_BF == 0) &&
1056 (tu->even_distribution_legacy == 0))) &&
1057 tu->old_err_fp >= 0 && tu->new_err_fp >= 0 &&
1058 (tu->new_err_fp < tu->err_fp) &&
1059 ((tu->new_err_fp < tu->diff_abs_fp) ||
1060 (tu->min_hblank_violated == 1)) &&
1061 (tu->new_valid_boundary_link - 1) > 0 &&
1062 (tu->hbp_time_fp > tu->delay_start_time_fp) &&
1063 (tu->delay_start_link_tmp <= 1023)) {
1064 tu->upper_boundary_count = tu->i_upper_boundary_count;
1065 tu->lower_boundary_count = tu->i_lower_boundary_count;
1066 tu->err_fp = tu->new_err_fp;
1067 tu->boundary_moderation_en = true;
1068 tu->tu_size_desired = tu->tu_size;
1069 tu->valid_boundary_link = tu->new_valid_boundary_link;
1070 tu->effective_valid_recorded_fp = tu->effective_valid_fp;
1071 tu->even_distribution_BF = 1;
1072 tu->delay_start_link = tu->delay_start_link_tmp;
1073 } else if (tu->boundary_mod_lower_err == 0) {
1074 if (tu->new_err_fp < tu->diff_abs_fp)
1075 tu->boundary_mod_lower_err = 1;
1076 }
1077}
1078
1079static void edp_ctrl_calc_tu(struct edp_ctrl *ctrl, struct edid *edid,
1080 struct edp_ctrl_tu *tu_table)
1081{
Vinod Polimera25f6db42022-09-14 19:49:08 +05301082 struct tu_algo_data tu = {0};
Vinod Polimera4e93e942022-02-25 13:21:42 +05301083 int64_t f = 100000;
1084 int64_t LCLK_FAST_SKEW_fp = (6 * f) / 1000; /* 0.0006 */
1085 uint8_t DP_BRUTE_FORCE = 1;
1086 int64_t BRUTE_FORCE_THRESHOLD_fp = (1 * f) / 10; /* 0.1 */
1087 int RATIO_SCALE_NUM = 1001;
1088 int RATIO_SCALE_DEN = 1000;
1089 int HBLANK_MARGIN = 4;
1090 int EXTRA_PIXCLK_CYCLE_DELAY = 4;
1091 int64_t temp = 0;
1092 int64_t temp_fp = 0;
Vinod Polimera4e93e942022-02-25 13:21:42 +05301093
Vinod Polimera042ba162022-08-23 14:25:02 +05301094 tu.lclk_fp = ctrl->link_rate_khz * f;
1095 tu.lclk = ctrl->link_rate_khz;
1096 tu.pclk = edid->mode.pixel_clock;
1097 tu.pclk_fp = edid->mode.pixel_clock * f;
1098 tu.nlanes = ctrl->lane_cnt;
1099 tu.bpp = edid->panel_bits_per_pixel;
1100 tu.lwidth = edid->mode.ha;
1101 tu.lwidth_fp = tu.lwidth * f;
1102 tu.hbp_relative_to_pclk = edid->mode.hbl;
1103 tu.hbp_relative_to_pclk_fp = tu.hbp_relative_to_pclk * f;
1104 tu.err_fp = 1000 * f;
1105 tu.extra_buffer_margin = DIV_ROUND_UP(tu.lclk * 4, tu.pclk);
1106 tu.ratio_fp = ((int64_t)(tu.pclk_fp * tu.bpp) / 8) / (tu.nlanes * tu.lclk);
1107 tu.original_ratio_fp = tu.ratio_fp;
Vinod Polimera042ba162022-08-23 14:25:02 +05301108 if (((tu.lwidth % tu.nlanes) != 0) && (tu.ratio_fp < f)) {
1109 tu.ratio_fp = (tu.ratio_fp * RATIO_SCALE_NUM) / RATIO_SCALE_DEN;
1110 tu.ratio_fp = tu.ratio_fp < f ? tu.ratio_fp : f;
Vinod Polimera4e93e942022-02-25 13:21:42 +05301111 }
1112
Vinod Polimera042ba162022-08-23 14:25:02 +05301113 if (tu.ratio_fp > f)
1114 tu.ratio_fp = f;
Vinod Polimera4e93e942022-02-25 13:21:42 +05301115
Vinod Polimera042ba162022-08-23 14:25:02 +05301116 for (tu.tu_size = 32; tu.tu_size <= 64; tu.tu_size++) {
1117 tu.new_err_fp = (tu.ratio_fp * tu.tu_size) -
1118 (((tu.ratio_fp * tu.tu_size) / f) * f);
1119 if (tu.new_err_fp > 0)
1120 tu.new_err_fp = f - tu.new_err_fp;
Vinod Polimera4e93e942022-02-25 13:21:42 +05301121
Vinod Polimera042ba162022-08-23 14:25:02 +05301122 if (tu.new_err_fp < tu.err_fp) {
1123 tu.err_fp = tu.new_err_fp;
1124 tu.tu_size_desired = tu.tu_size;
Vinod Polimera4e93e942022-02-25 13:21:42 +05301125 }
1126 }
1127
Vinod Polimera042ba162022-08-23 14:25:02 +05301128 tu.tu_size_minus1 = tu.tu_size_desired - 1;
1129 tu.valid_boundary_link = DIV_ROUND_UP(tu.tu_size_desired * tu.ratio_fp, f);
1130 tu.num_tus = ((tu.bpp * tu.lwidth) / 8) / tu.valid_boundary_link;
1131 tu.even_distribution_legacy = tu.num_tus % tu.nlanes == 0 ? 1 : 0;
1132 tu.extra_bytes = DIV_ROUND_UP(((tu.num_tus + 1) * (tu.valid_boundary_link * f -
1133 tu.original_ratio_fp * tu.tu_size_desired)), f);
1134 tu.extra_pclk_cycles = DIV_ROUND_UP(tu.extra_bytes * 8, tu.bpp);
1135 tu.extra_pclk_cycles_in_link_clk = DIV_ROUND_UP(tu.extra_pclk_cycles * tu.lclk,
1136 tu.pclk);
1137 tu.filler_size = tu.tu_size_desired - tu.valid_boundary_link;
1138 tu.ratio_by_tu_fp = tu.ratio_fp * tu.tu_size_desired;
1139 tu.delay_start_link = tu.extra_pclk_cycles_in_link_clk + tu.filler_size +
1140 tu.extra_buffer_margin;
1141 tu.resulting_valid_fp = tu.valid_boundary_link * f;
1142 tu.TU_ratio_err_fp = (tu.resulting_valid_fp / tu.tu_size_desired) -
1143 tu.original_ratio_fp;
1144 tu.hbp_time_fp = (tu.hbp_relative_to_pclk_fp - HBLANK_MARGIN * f) / tu.pclk;
1145 tu.delay_start_time_fp = (tu.delay_start_link * f) / tu.lclk;
1146 if (tu.hbp_time_fp < tu.delay_start_time_fp)
1147 tu.min_hblank_violated = 1;
Vinod Polimera4e93e942022-02-25 13:21:42 +05301148
Vinod Polimera042ba162022-08-23 14:25:02 +05301149 tu.hactive_time_fp = (tu.lwidth * f) / tu.pclk;
1150 if (tu.hactive_time_fp < tu.delay_start_time_fp)
1151 tu.min_hblank_violated = 1;
Vinod Polimera4e93e942022-02-25 13:21:42 +05301152
Vinod Polimera042ba162022-08-23 14:25:02 +05301153 tu.delay_start_time_fp = 0;
Vinod Polimera4e93e942022-02-25 13:21:42 +05301154
1155 /* brute force */
Vinod Polimera042ba162022-08-23 14:25:02 +05301156 tu.delay_start_link_extra_pclk = EXTRA_PIXCLK_CYCLE_DELAY;
1157 tu.diff_abs_fp = tu.resulting_valid_fp - tu.ratio_by_tu_fp;
1158 if (tu.diff_abs_fp < 0)
1159 tu.diff_abs_fp = tu.diff_abs_fp * -1;
Vinod Polimera4e93e942022-02-25 13:21:42 +05301160
Vinod Polimera042ba162022-08-23 14:25:02 +05301161 tu.boundary_mod_lower_err = 0;
1162 if ((tu.diff_abs_fp != 0 &&
1163 ((tu.diff_abs_fp > BRUTE_FORCE_THRESHOLD_fp) ||
1164 (tu.even_distribution_legacy == 0) ||
Vinod Polimera4e93e942022-02-25 13:21:42 +05301165 (DP_BRUTE_FORCE == 1))) ||
Vinod Polimera042ba162022-08-23 14:25:02 +05301166 (tu.min_hblank_violated == 1)) {
Vinod Polimera4e93e942022-02-25 13:21:42 +05301167 do {
Vinod Polimera042ba162022-08-23 14:25:02 +05301168 tu.err_fp = 1000 * f;
1169 tu.extra_buffer_margin = DIV_ROUND_UP(tu.lclk_fp *
1170 tu.delay_start_link_extra_pclk,
1171 tu.pclk_fp);
1172 tu.n_symbols = DIV_ROUND_UP(tu.bpp * tu.lwidth, 8);
1173 for (tu.tu_size = 32; tu.tu_size <= 64; tu.tu_size++) {
1174 for (tu.i_upper_boundary_count = 1;
1175 tu.i_upper_boundary_count <= 15;
1176 tu.i_upper_boundary_count++) {
1177 for (tu.i_lower_boundary_count = 1;
1178 tu.i_lower_boundary_count <= 15;
1179 tu.i_lower_boundary_count++) {
1180 tu_valid_boundary_calc(&tu);
Vinod Polimera4e93e942022-02-25 13:21:42 +05301181 }
1182 }
1183 }
Vinod Polimera042ba162022-08-23 14:25:02 +05301184 tu.delay_start_link_extra_pclk--;
1185 } while (tu.boundary_moderation_en != true &&
1186 tu.boundary_mod_lower_err == 1 &&
1187 tu.delay_start_link_extra_pclk != 0);
Vinod Polimera4e93e942022-02-25 13:21:42 +05301188
Vinod Polimera042ba162022-08-23 14:25:02 +05301189 if (tu.boundary_moderation_en == true) {
1190 tu.resulting_valid_fp = f * (tu.upper_boundary_count *
1191 tu.valid_boundary_link +
1192 tu.lower_boundary_count *
1193 (tu.valid_boundary_link - 1));
1194 tu.resulting_valid_fp /= (tu.upper_boundary_count +
1195 tu.lower_boundary_count);
1196 tu.ratio_by_tu_fp = tu.original_ratio_fp * tu.tu_size_desired;
1197 tu.valid_lower_boundary_link = tu.valid_boundary_link - 1;
1198 tu.num_tus = ((tu.bpp / 8) * tu.lwidth_fp) / tu.resulting_valid_fp;
1199 tu.tu_size_minus1 = tu.tu_size_desired - 1;
1200 tu.even_distribution_BF = 1;
1201 tu.TU_ratio_err_fp = ((tu.tu_size_desired * f /
1202 tu.resulting_valid_fp) * f);
1203 tu.TU_ratio_err_fp -= tu.original_ratio_fp;
Vinod Polimera4e93e942022-02-25 13:21:42 +05301204 }
1205 }
1206
Vinod Polimera042ba162022-08-23 14:25:02 +05301207 temp_fp = LCLK_FAST_SKEW_fp * tu.lwidth;
Vinod Polimera4e93e942022-02-25 13:21:42 +05301208 temp = DIV_ROUND_UP(temp_fp, f);
Vinod Polimera042ba162022-08-23 14:25:02 +05301209 temp_fp = ((tu.bpp * f / 8) / (tu.nlanes * tu.original_ratio_fp)) * f * temp;
Vinod Polimera4e93e942022-02-25 13:21:42 +05301210 temp = temp_fp / f;
1211
Vinod Polimera042ba162022-08-23 14:25:02 +05301212 tu.delay_start_time_fp = (tu.delay_start_link * f) / tu.lclk;
Vinod Polimera4e93e942022-02-25 13:21:42 +05301213
1214 /* OUTPUTS */
Vinod Polimera042ba162022-08-23 14:25:02 +05301215 tu_table->valid_boundary_link = tu.valid_boundary_link;
1216 tu_table->delay_start_link = tu.delay_start_link;
1217 tu_table->boundary_moderation_en = tu.boundary_moderation_en;
1218 tu_table->valid_lower_boundary_link = tu.valid_lower_boundary_link;
1219 tu_table->upper_boundary_count = tu.upper_boundary_count;
1220 tu_table->lower_boundary_count = tu.lower_boundary_count;
1221 tu_table->tu_size_minus1 = tu.tu_size_minus1;
Vinod Polimera4e93e942022-02-25 13:21:42 +05301222
1223 printk(BIOS_INFO, "TU: valid_boundary_link: %d\n",
Vinod Polimera042ba162022-08-23 14:25:02 +05301224 tu_table->valid_boundary_link);
Vinod Polimera4e93e942022-02-25 13:21:42 +05301225 printk(BIOS_INFO, "TU: delay_start_link: %d\n",
Vinod Polimera042ba162022-08-23 14:25:02 +05301226 tu_table->delay_start_link);
Vinod Polimera4e93e942022-02-25 13:21:42 +05301227 printk(BIOS_INFO, "TU: boundary_moderation_en: %d\n",
Vinod Polimera042ba162022-08-23 14:25:02 +05301228 tu_table->boundary_moderation_en);
Vinod Polimera4e93e942022-02-25 13:21:42 +05301229 printk(BIOS_INFO, "TU: valid_lower_boundary_link: %d\n",
Vinod Polimera042ba162022-08-23 14:25:02 +05301230 tu_table->valid_lower_boundary_link);
Vinod Polimera4e93e942022-02-25 13:21:42 +05301231 printk(BIOS_INFO, "TU: upper_boundary_count: %d\n",
Vinod Polimera042ba162022-08-23 14:25:02 +05301232 tu_table->upper_boundary_count);
Vinod Polimera4e93e942022-02-25 13:21:42 +05301233 printk(BIOS_INFO, "TU: lower_boundary_count: %d\n",
Vinod Polimera042ba162022-08-23 14:25:02 +05301234 tu_table->lower_boundary_count);
Vinod Polimera4e93e942022-02-25 13:21:42 +05301235 printk(BIOS_INFO, "TU: tu_size_minus1: %d\n", tu_table->tu_size_minus1);
1236}
1237
1238static void edp_ctrl_config_TU(struct edp_ctrl *ctrl, struct edid *edid)
1239{
1240 struct edp_ctrl_tu tu_config;
1241
1242 edp_ctrl_calc_tu(ctrl, edid, &tu_config);
1243 write32(&edp_lclk->valid_boundary, tu_config.delay_start_link << 16 |
1244 tu_config.valid_boundary_link);
1245 write32(&edp_lclk->tu, tu_config.tu_size_minus1);
1246 write32(&edp_lclk->valid_boundary2, tu_config.boundary_moderation_en |
1247 tu_config.valid_lower_boundary_link << 1|
1248 tu_config.upper_boundary_count << 16 |
1249 tu_config.lower_boundary_count << 20);
1250}
1251
1252static void edp_ctrl_timing_cfg(struct edid *edid)
1253{
1254 uint32_t hpolarity;
1255 uint32_t vpolarity;
1256
1257 hpolarity = (edid->mode.phsync == '+');
1258 vpolarity = (edid->mode.pvsync == '+');
1259
1260 /* Configure eDP timing to HW */
1261 write32(&edp_lclk->total_hor_ver,
1262 (edid->mode.ha + edid->mode.hbl) |
1263 (((edid->mode.va + edid->mode.vbl) << 16) & 0xffff0000));
1264
1265 write32(&edp_lclk->start_hor_ver_from_sync,
1266 (edid->mode.hbl - edid->mode.hso) |
1267 (((edid->mode.vbl - edid->mode.vso) << 16) & 0xffff0000));
1268
1269 write32(&edp_lclk->hysnc_vsync_width_polarity, edid->mode.hspw |
1270 ((hpolarity << 15) & 0x8000) | ((edid->mode.vspw << 16) &
1271 0x7fff0000) | ((vpolarity << 31) & 0x80000000));
1272
1273 write32(&edp_lclk->active_hor_ver,
1274 (edid->mode.ha) |
1275 ((edid->mode.va << 16) & 0xffff0000));
Vinod Polimera4e93e942022-02-25 13:21:42 +05301276}
1277
1278static void edp_mainlink_ctrl(int enable)
1279{
1280 uint32_t data = 0;
1281
1282 write32(&edp_lclk->mainlink_ctrl, 0x2);
1283 if (enable)
1284 data |= (0x1);
1285
1286 write32(&edp_lclk->mainlink_ctrl, data);
1287}
1288
1289static void edp_ctrl_phy_enable(int enable)
1290{
1291 if (enable) {
1292 write32(&edp_ahbclk->phy_ctrl, 0x4 | 0x1);
1293 write32(&edp_ahbclk->phy_ctrl, 0x0);
1294 edp_phy_enable();
1295 }
1296}
1297
1298static void edp_ctrl_phy_aux_enable(int enable)
1299{
1300 if (enable) {
1301 /* regulators are enabled in QCLIB */
1302 edp_ctrl_phy_enable(1);
1303 edp_aux_ctrl(1);
1304 } else {
1305 edp_aux_ctrl(0);
1306 }
1307}
1308
1309static void edp_ctrl_link_enable(struct edp_ctrl *ctrl,
1310 struct edid *edid, uint8_t *dpcd, int enable)
1311{
1312 int ret = 0;
1313 uint32_t m = 0, n = 0;
1314
1315 if (enable) {
1316 edp_phy_power_on(ctrl->link_rate_khz);
1317 edp_phy_vm_pe_init();
1318 mdss_clock_configure(MDSS_CLK_EDP_LINK, 0, 1, 0, 0, 0, 0);
1319 ret = mdss_clock_enable(MDSS_CLK_EDP_LINK);
1320 if (ret != 0)
Yu-Ping Wufae1eb32023-08-21 16:02:57 +08001321 printk(BIOS_ERR, "failed to enable link clk\n");
Vinod Polimera4e93e942022-02-25 13:21:42 +05301322
1323 mdss_clock_configure(MDSS_CLK_EDP_LINK_INTF, 0, 1, 0, 0, 0, 0);
1324 ret = mdss_clock_enable(MDSS_CLK_EDP_LINK_INTF);
1325 if (ret != 0)
Yu-Ping Wufae1eb32023-08-21 16:02:57 +08001326 printk(BIOS_ERR, "failed to enable link intf clk\n");
Vinod Polimera4e93e942022-02-25 13:21:42 +05301327
1328 edp_ctrl_pixel_clock_dividers(ctrl, &m, &n);
1329 mdss_clock_configure(MDSS_CLK_EDP_PIXEL, 0, 2, 0, m, n, n);
1330 ret = mdss_clock_enable(MDSS_CLK_EDP_PIXEL);
1331 if (ret != 0)
Yu-Ping Wufae1eb32023-08-21 16:02:57 +08001332 printk(BIOS_ERR, "failed to enable pixel clk\n");
Vinod Polimera4e93e942022-02-25 13:21:42 +05301333
1334 edp_mainlink_ctrl(1);
1335 } else {
1336 edp_mainlink_ctrl(0);
1337 }
1338}
1339
1340static int edp_ctrl_training(struct edp_ctrl *ctrl, struct edid *edid, uint8_t *dpcd)
1341{
1342 int ret;
1343
1344 /* Do link training only when power is on */
1345 ret = edp_do_link_train(ctrl, dpcd);
1346 while (ret == EDP_TRAIN_RECONFIG) {
1347 /* Re-configure main link */
1348 edp_ctrl_irq_enable(0);
1349 edp_ctrl_link_enable(ctrl, edid, dpcd, 0);
1350 edp_ctrl_phy_enable(1);
1351 edp_ctrl_irq_enable(1);
1352 edp_ctrl_link_enable(ctrl, edid, dpcd, 1);
1353 ret = edp_do_link_train(ctrl, dpcd);
1354 }
1355
1356 return ret;
1357}
1358
Vinod Polimera042ba162022-08-23 14:25:02 +05301359static int edp_ctrl_on(struct edp_ctrl *ctrl, struct edid *edid, uint8_t *dpcd)
Vinod Polimera4e93e942022-02-25 13:21:42 +05301360{
1361 uint8_t value;
1362 int ret;
1363
1364 /*
1365 * By default, use the maximum link rate and minimum lane count,
1366 * so that we can do rate down shift during link training.
1367 */
1368 ctrl->link_rate_khz = dpcd[DP_MAX_LINK_RATE] * 27000;
1369 ctrl->link_rate = dpcd[DP_MAX_LINK_RATE];
1370 ctrl->lane_cnt = dpcd[DP_MAX_LANE_COUNT] & DP_MAX_LANE_COUNT_MASK;
1371 ctrl->color_depth = edid->panel_bits_per_color;
1372 ctrl->pixel_rate = edid->mode.pixel_clock;
1373
1374 /* DP_SET_POWER register is only available on DPCD v1.1 and later */
1375 if (dpcd[DP_DPCD_REV] >= 0x11) {
1376 ret = edp_aux_transfer(DP_SET_POWER, DP_AUX_NATIVE_READ, &value, 1);
Vinod Polimera042ba162022-08-23 14:25:02 +05301377 if (ret < 0) {
Elyes Haouasaba1c942022-11-09 15:05:23 +01001378 printk(BIOS_ERR, "edp native read failure\n");
Vinod Polimera042ba162022-08-23 14:25:02 +05301379 return -1;
1380 }
Vinod Polimera4e93e942022-02-25 13:21:42 +05301381
1382 value &= ~DP_SET_POWER_MASK;
1383 value |= DP_SET_POWER_D0;
1384
1385 ret = edp_aux_transfer(DP_SET_POWER, DP_AUX_NATIVE_WRITE, &value, 1);
Vinod Polimera042ba162022-08-23 14:25:02 +05301386 if (ret < 0) {
Elyes Haouasaba1c942022-11-09 15:05:23 +01001387 printk(BIOS_ERR, "edp native read failure\n");
Vinod Polimera042ba162022-08-23 14:25:02 +05301388 return -1;
1389 }
Vinod Polimera4e93e942022-02-25 13:21:42 +05301390
1391 /*
1392 * According to the DP 1.1 specification, a "Sink Device must
1393 * exit the power saving state within 1 ms" (Section 2.5.3.1,
1394 * Table 5-52, "Sink Control Field" (register 0x600).
1395 */
1396 udelay(1000);
1397 }
1398
1399 edp_ctrl_irq_enable(1);
1400 edp_ctrl_link_enable(ctrl, edid, dpcd, 1);
1401 /* Start link training */
1402 ret = edp_ctrl_training(ctrl, edid, dpcd);
Vinod Polimera042ba162022-08-23 14:25:02 +05301403 if (ret != EDP_TRAIN_SUCCESS) {
Elyes Haouasaba1c942022-11-09 15:05:23 +01001404 printk(BIOS_ERR, "edp training failure\n");
Vinod Polimera042ba162022-08-23 14:25:02 +05301405 return -1;
1406 }
Vinod Polimera4e93e942022-02-25 13:21:42 +05301407
1408 edp_train_pattern_set_write(0);
1409
1410 write32(&edp_lclk->mainlink_ctrl, 0x2000000);
1411 write32(&edp_lclk->mainlink_ctrl, 0x2000002);
1412 write32(&edp_lclk->mainlink_ctrl, 0x2000000);
1413 write32(&edp_lclk->mainlink_ctrl, 0x2000001);
1414 edp_config_ctrl(ctrl, dpcd);
1415 edp_ctrl_config_misc(ctrl);
1416 edp_ctrl_timing_cfg(edid);
Vinod Polimera042ba162022-08-23 14:25:02 +05301417
1418 if (edp_ctrl_config_msa(ctrl) < 0)
1419 return -1;
1420
Vinod Polimera4e93e942022-02-25 13:21:42 +05301421 edp_ctrl_config_TU(ctrl, edid);
1422 edp_state_ctrl(SW_SEND_VIDEO);
1423 edp_ctrl_irq_enable(0);
Vinod Polimera042ba162022-08-23 14:25:02 +05301424
1425 return 0;
Vinod Polimera4e93e942022-02-25 13:21:42 +05301426}
1427
1428static bool edp_ctrl_panel_connected(uint8_t *dpcd)
1429{
1430 /* enable aux clk */
1431 mdss_clock_configure(MDSS_CLK_EDP_AUX, 0, 0, 0, 0, 0, 0);
1432 mdss_clock_enable(MDSS_CLK_EDP_AUX);
1433 edp_ctrl_phy_aux_enable(1);
1434 edp_ctrl_irq_enable(1);
1435 if (edp_aux_transfer(DP_DPCD_REV, DP_AUX_NATIVE_READ, dpcd,
1436 DP_RECEIVER_CAP_SIZE) < DP_RECEIVER_CAP_SIZE) {
1437 printk(BIOS_ERR, "%s: AUX channel is NOT ready\n", __func__);
1438
1439 } else {
1440 return true;
1441 }
1442
1443 return false;
1444}
1445
1446enum cb_err edp_ctrl_init(struct edid *edid)
1447{
1448 uint8_t dpcd[DP_RECEIVER_CAP_SIZE];
1449 struct edp_ctrl ctrl;
1450
1451 memset(&ctrl, 0, sizeof(struct edp_ctrl));
1452 mdss_clock_enable(GCC_EDP_CLKREF_EN);
1453
1454 if (edp_ctrl_panel_connected(dpcd) && edp_read_edid(edid) == 0) {
Vinod Polimera042ba162022-08-23 14:25:02 +05301455 if (edp_ctrl_on(&ctrl, edid, dpcd) < 0)
1456 return CB_ERR;
1457
Vinod Polimera4e93e942022-02-25 13:21:42 +05301458 return CB_SUCCESS;
1459 }
1460
1461 edp_ctrl_irq_enable(0);
1462
1463 return CB_ERR;
1464}