blob: 4fbe0d64c0a830561c144b63cf5b85426398d02e [file] [log] [blame]
Angel Ponsbbc99cf2020-04-04 18:51:23 +02001/* SPDX-License-Identifier: GPL-2.0-only */
huang lin40f558e2014-09-19 14:51:52 +08002
Kyösti Mälkki13f66502019-03-03 08:01:05 +02003#include <device/mmio.h>
huang lin40f558e2014-09-19 14:51:52 +08004#include <console/console.h>
5#include <delay.h>
Lin Huangb9a78772016-04-25 18:50:55 +08006#include <device/device.h>
huang lin40f558e2014-09-19 14:51:52 +08007#include <edid.h>
huang lin40f558e2014-09-19 14:51:52 +08008#include <string.h>
9#include <soc/addressmap.h>
Lin Huangb9a78772016-04-25 18:50:55 +080010#include <soc/display.h>
huang lin40f558e2014-09-19 14:51:52 +080011#include <soc/edp.h>
huang lin40f558e2014-09-19 14:51:52 +080012#include <timer.h>
Elyes HAOUAS17b1a162019-06-23 07:08:12 +020013#include <types.h>
huang lin40f558e2014-09-19 14:51:52 +080014
huang lin40f558e2014-09-19 14:51:52 +080015#define edp_debug(x...) do {if (0) printk(BIOS_DEBUG, x); } while (0)
16
17static struct rk_edp rk_edp;
18
19#define MAX_CR_LOOP 5
20#define MAX_EQ_LOOP 5
21#define DP_LINK_STATUS_SIZE 6
22
23static const char *voltage_names[] = {
24 "0.4V", "0.6V", "0.8V", "1.2V"
25};
26static const char *pre_emph_names[] = {
27 "0dB", "3.5dB", "6dB", "9.5dB"
28};
29
30#define DP_VOLTAGE_MAX DP_TRAIN_VOLTAGE_SWING_1200
31#define DP_PRE_EMPHASIS_MAX DP_TRAIN_PRE_EMPHASIS_9_5
32
huang lin40f558e2014-09-19 14:51:52 +080033static void rk_edp_init_refclk(struct rk_edp *edp)
34{
Julius Werner2f37bd62015-02-19 14:51:15 -080035 write32(&edp->regs->analog_ctl_2, SEL_24M);
36 write32(&edp->regs->pll_reg_1, REF_CLK_24M);
huang lin40f558e2014-09-19 14:51:52 +080037
38 /*initial value*/
Julius Werner94184762015-02-19 20:19:23 -080039 write32(&edp->regs->pll_reg_2, LDO_OUTPUT_V_SEL_145 | KVCO_DEFALUT |
40 CHG_PUMP_CUR_SEL_5US | V2L_CUR_SEL_1MA);
huang lin40f558e2014-09-19 14:51:52 +080041
Julius Werner94184762015-02-19 20:19:23 -080042 write32(&edp->regs->pll_reg_3, LOCK_DET_CNT_SEL_256 |
43 LOOP_FILTER_RESET | PALL_SSC_RESET | LOCK_DET_BYPASS |
44 PLL_LOCK_DET_MODE | PLL_LOCK_DET_FORCE);
huang lin40f558e2014-09-19 14:51:52 +080045
Julius Werner94184762015-02-19 20:19:23 -080046 write32(&edp->regs->pll_reg_5, REGULATOR_V_SEL_950MV | STANDBY_CUR_SEL |
47 CHG_PUMP_INOUT_CTRL_1200MV | CHG_PUMP_INPUT_CTRL_OP);
huang lin40f558e2014-09-19 14:51:52 +080048
Julius Werner2f37bd62015-02-19 14:51:15 -080049 write32(&edp->regs->ssc_reg, SSC_OFFSET | SSC_MODE | SSC_DEPTH);
huang lin40f558e2014-09-19 14:51:52 +080050
Julius Werner94184762015-02-19 20:19:23 -080051 write32(&edp->regs->tx_common, TX_SWING_PRE_EMP_MODE |
52 PRE_DRIVER_PW_CTRL1 | LP_MODE_CLK_REGULATOR |
53 RESISTOR_MSB_CTRL | RESISTOR_CTRL);
huang lin40f558e2014-09-19 14:51:52 +080054
Julius Werner94184762015-02-19 20:19:23 -080055 write32(&edp->regs->dp_aux, DP_AUX_COMMON_MODE |
56 DP_AUX_EN | AUX_TERM_50OHM);
huang lin40f558e2014-09-19 14:51:52 +080057
Julius Werner94184762015-02-19 20:19:23 -080058 write32(&edp->regs->dp_bias, DP_BG_OUT_SEL | DP_DB_CUR_CTRL |
59 DP_BG_SEL | DP_RESISTOR_TUNE_BG);
huang lin40f558e2014-09-19 14:51:52 +080060
Julius Werner2f37bd62015-02-19 14:51:15 -080061 write32(&edp->regs->dp_reserv2,
62 CH1_CH3_SWING_EMP_CTRL | CH0_CH2_SWING_EMP_CTRL);
huang lin40f558e2014-09-19 14:51:52 +080063}
64
65static void rk_edp_init_interrupt(struct rk_edp *edp)
66{
67 /* Set interrupt pin assertion polarity as high */
Julius Werner2f37bd62015-02-19 14:51:15 -080068 write32(&edp->regs->int_ctl, INT_POL);
huang lin40f558e2014-09-19 14:51:52 +080069
70 /* Clear pending registers */
Julius Werner2f37bd62015-02-19 14:51:15 -080071 write32(&edp->regs->common_int_sta_1, 0xff);
72 write32(&edp->regs->common_int_sta_2, 0x4f);
73 write32(&edp->regs->common_int_sta_3, 0xff);
74 write32(&edp->regs->common_int_sta_4, 0x27);
75 write32(&edp->regs->dp_int_sta, 0x7f);
huang lin40f558e2014-09-19 14:51:52 +080076
77 /* 0:mask,1: unmask */
Julius Werner2f37bd62015-02-19 14:51:15 -080078 write32(&edp->regs->common_int_mask_1, 0x00);
79 write32(&edp->regs->common_int_mask_2, 0x00);
80 write32(&edp->regs->common_int_mask_3, 0x00);
81 write32(&edp->regs->common_int_mask_4, 0x00);
82 write32(&edp->regs->int_sta_mask, 0x00);
huang lin40f558e2014-09-19 14:51:52 +080083}
84
85static void rk_edp_enable_sw_function(struct rk_edp *edp)
86{
Julius Werner55009af2019-12-02 22:03:27 -080087 clrbits32(&edp->regs->func_en_1, SW_FUNC_EN_N);
huang lin40f558e2014-09-19 14:51:52 +080088}
89
90static int rk_edp_get_pll_lock_status(struct rk_edp *edp)
91{
92 u32 val;
93
Julius Werner2f37bd62015-02-19 14:51:15 -080094 val = read32(&edp->regs->dp_debug_ctl);
huang lin40f558e2014-09-19 14:51:52 +080095 return (val & PLL_LOCK) ? DP_PLL_LOCKED : DP_PLL_UNLOCKED;
96}
97
98static void rk_edp_init_analog_func(struct rk_edp *edp)
99{
100 struct stopwatch sw;
101
Julius Werner2f37bd62015-02-19 14:51:15 -0800102 write32(&edp->regs->dp_pd, 0x00);
huang lin40f558e2014-09-19 14:51:52 +0800103
Julius Werner2f37bd62015-02-19 14:51:15 -0800104 write32(&edp->regs->common_int_sta_1, PLL_LOCK_CHG);
huang lin40f558e2014-09-19 14:51:52 +0800105
Julius Werner55009af2019-12-02 22:03:27 -0800106 clrbits32(&edp->regs->dp_debug_ctl, F_PLL_LOCK | PLL_LOCK_CTRL);
huang lin40f558e2014-09-19 14:51:52 +0800107
108 stopwatch_init_msecs_expire(&sw, PLL_LOCK_TIMEOUT);
109
110 while (rk_edp_get_pll_lock_status(edp) == DP_PLL_UNLOCKED) {
111 if (stopwatch_expired(&sw)) {
112 printk(BIOS_ERR, "%s: PLL is not locked\n", __func__);
113 return;
114 }
115 }
116
117 /* Enable Serdes FIFO function and Link symbol clock domain module */
Julius Werner55009af2019-12-02 22:03:27 -0800118 clrbits32(&edp->regs->func_en_2, SERDES_FIFO_FUNC_EN_N |
huang lin40f558e2014-09-19 14:51:52 +0800119 LS_CLK_DOMAIN_FUNC_EN_N | AUX_FUNC_EN_N |
120 SSC_FUNC_EN_N);
121}
122
123static void rk_edp_init_aux(struct rk_edp *edp)
124{
Elyes HAOUAS8d1b0f12020-02-20 18:20:57 +0100125 /* Clear interrupts related to AUX channel */
Julius Werner2f37bd62015-02-19 14:51:15 -0800126 write32(&edp->regs->dp_int_sta, AUX_FUNC_EN_N);
huang lin40f558e2014-09-19 14:51:52 +0800127
128 /* Disable AUX channel module */
Julius Werner55009af2019-12-02 22:03:27 -0800129 setbits32(&edp->regs->func_en_2, AUX_FUNC_EN_N);
huang lin40f558e2014-09-19 14:51:52 +0800130
131 /* Receive AUX Channel DEFER commands equal to DEFFER_COUNT*64 */
Julius Werner2f37bd62015-02-19 14:51:15 -0800132 write32(&edp->regs->aux_ch_defer_dtl, DEFER_CTRL_EN | DEFER_COUNT(1));
huang lin40f558e2014-09-19 14:51:52 +0800133
134 /* Enable AUX channel module */
Julius Werner55009af2019-12-02 22:03:27 -0800135 clrbits32(&edp->regs->func_en_2, AUX_FUNC_EN_N);
huang lin40f558e2014-09-19 14:51:52 +0800136}
137
138static int rk_edp_aux_enable(struct rk_edp *edp)
139{
140 struct stopwatch sw;
141
Julius Werner55009af2019-12-02 22:03:27 -0800142 setbits32(&edp->regs->aux_ch_ctl_2, AUX_EN);
huang lin40f558e2014-09-19 14:51:52 +0800143 stopwatch_init_msecs_expire(&sw, 20);
144 do {
Julius Werner2f37bd62015-02-19 14:51:15 -0800145 if (!(read32(&edp->regs->aux_ch_ctl_2) & AUX_EN))
huang lin40f558e2014-09-19 14:51:52 +0800146 return 0;
147 } while (!stopwatch_expired(&sw));
148
149 return -1;
huang lin40f558e2014-09-19 14:51:52 +0800150}
151
152static int rk_edp_is_aux_reply(struct rk_edp *edp)
153{
154 struct stopwatch sw;
155
156 stopwatch_init_msecs_expire(&sw, 10);
157
Julius Werner2f37bd62015-02-19 14:51:15 -0800158 while (!(read32(&edp->regs->dp_int_sta) & RPLY_RECEIV)) {
huang lin40f558e2014-09-19 14:51:52 +0800159 if (stopwatch_expired(&sw))
160 return -1;
161 }
162
Julius Werner2f37bd62015-02-19 14:51:15 -0800163 write32(&edp->regs->dp_int_sta, RPLY_RECEIV);
huang lin40f558e2014-09-19 14:51:52 +0800164
165 return 0;
166}
167
168static int rk_edp_start_aux_transaction(struct rk_edp *edp)
169{
170 int val;
171
172 /* Enable AUX CH operation */
173 if (rk_edp_aux_enable(edp)) {
174 edp_debug("AUX CH enable timeout!\n");
175 return -1;
176 }
177
178 /* Is AUX CH command reply received? */
179 if (rk_edp_is_aux_reply(edp)) {
180 edp_debug("AUX CH command reply failed!\n");
181 return -1;
182 }
183
184 /* Clear interrupt source for AUX CH access error */
Julius Werner2f37bd62015-02-19 14:51:15 -0800185 val = read32(&edp->regs->dp_int_sta);
huang lin40f558e2014-09-19 14:51:52 +0800186 if (val & AUX_ERR) {
Julius Werner2f37bd62015-02-19 14:51:15 -0800187 write32(&edp->regs->dp_int_sta, AUX_ERR);
huang lin40f558e2014-09-19 14:51:52 +0800188 return -1;
189 }
190
191 /* Check AUX CH error access status */
Julius Werner2f37bd62015-02-19 14:51:15 -0800192 val = read32(&edp->regs->dp_int_sta);
huang lin40f558e2014-09-19 14:51:52 +0800193 if ((val & AUX_STATUS_MASK) != 0) {
194 edp_debug("AUX CH error happens: %d\n\n",
195 val & AUX_STATUS_MASK);
196 return -1;
197 }
198
199 return 0;
200}
201
202static int rk_edp_dpcd_transfer(struct rk_edp *edp,
203 unsigned int val_addr, u8 *data,
204 unsigned int length,
205 enum dpcd_request request)
206{
207 int val;
208 int i, try_times;
209 int retval = 0;
210 u32 len = 0;
211
212 while (length) {
213 len = MIN(length, 16);
214 for (try_times = 0; try_times < 10; try_times++) {
huang lin40f558e2014-09-19 14:51:52 +0800215 /* Clear AUX CH data buffer */
216 val = BUF_CLR;
Julius Werner2f37bd62015-02-19 14:51:15 -0800217 write32(&edp->regs->buf_data_ctl, val);
huang lin40f558e2014-09-19 14:51:52 +0800218
219 /* Select DPCD device address */
220 val = AUX_ADDR_7_0(val_addr);
Julius Werner2f37bd62015-02-19 14:51:15 -0800221 write32(&edp->regs->aux_addr_7_0, val);
huang lin40f558e2014-09-19 14:51:52 +0800222 val = AUX_ADDR_15_8(val_addr);
Julius Werner2f37bd62015-02-19 14:51:15 -0800223 write32(&edp->regs->aux_addr_15_8, val);
huang lin40f558e2014-09-19 14:51:52 +0800224 val = AUX_ADDR_19_16(val_addr);
Julius Werner2f37bd62015-02-19 14:51:15 -0800225 write32(&edp->regs->aux_addr_19_16, val);
huang lin40f558e2014-09-19 14:51:52 +0800226
227 /*
228 * Set DisplayPort transaction and read 1 byte
229 * If bit 3 is 1, DisplayPort transaction.
230 * If Bit 3 is 0, I2C transaction.
231 */
232 if (request == DPCD_WRITE) {
233 val = AUX_LENGTH(len) |
234 AUX_TX_COMM_DP_TRANSACTION |
235 AUX_TX_COMM_WRITE;
236 for (i = 0; i < len; i++)
Julius Werner2f37bd62015-02-19 14:51:15 -0800237 write32(&edp->regs->buf_data[i],
238 *data++);
huang lin40f558e2014-09-19 14:51:52 +0800239 } else
240 val = AUX_LENGTH(len) |
241 AUX_TX_COMM_DP_TRANSACTION |
242 AUX_TX_COMM_READ;
243
Julius Werner2f37bd62015-02-19 14:51:15 -0800244 write32(&edp->regs->aux_ch_ctl_1, val);
huang lin40f558e2014-09-19 14:51:52 +0800245
246 /* Start AUX transaction */
247 retval = rk_edp_start_aux_transaction(edp);
248 if (retval == 0)
249 break;
250 else
251 printk(BIOS_WARNING, "read dpcd Aux Transaction fail!\n");
huang lin40f558e2014-09-19 14:51:52 +0800252 }
253
254 if (retval)
255 return -1;
256
257 if (request == DPCD_READ) {
258 for (i = 0; i < len; i++)
Julius Werner2f37bd62015-02-19 14:51:15 -0800259 *data++ = (u8)read32(&edp->regs->buf_data[i]);
huang lin40f558e2014-09-19 14:51:52 +0800260 }
261
262 length -= len;
263 val_addr += 16;
264 }
265 return 0;
266}
267
Lin Huangb9a78772016-04-25 18:50:55 +0800268static int rk_edp_dpcd_read(struct rk_edp *edp, u32 addr,
269 u8 *values, size_t size)
huang lin40f558e2014-09-19 14:51:52 +0800270{
271 return rk_edp_dpcd_transfer(edp, addr, values, size, DPCD_READ);
272}
273
Lin Huangb9a78772016-04-25 18:50:55 +0800274static int rk_edp_dpcd_write(struct rk_edp *edp, u32 addr,
275 u8 *values, size_t size)
huang lin40f558e2014-09-19 14:51:52 +0800276{
277 return rk_edp_dpcd_transfer(edp, addr, values, size, DPCD_WRITE);
278}
279
huang lin40f558e2014-09-19 14:51:52 +0800280static int rk_edp_link_power_up(struct rk_edp *edp)
281{
282 u8 value;
283 int err;
284
285 /* DP_SET_POWER register is only available on DPCD v1.1 and later */
286 if (edp->link_train.revision < 0x11)
287 return 0;
288
289 err = rk_edp_dpcd_read(edp, DPCD_LINK_POWER_STATE, &value, 1);
290 if (err < 0)
291 return err;
292
293 value &= ~DP_SET_POWER_MASK;
294 value |= DP_SET_POWER_D0;
295
296 err = rk_edp_dpcd_write(edp, DPCD_LINK_POWER_STATE, &value, 1);
297 if (err < 0)
298 return err;
299
300 /*
301 * According to the DP 1.1 specification, a "Sink Device must exit the
302 * power saving state within 1 ms" (Section 2.5.3.1, Table 5-52, "Sink
303 * Control Field" (register 0x600).
304 */
305 mdelay(1);
306
307 return 0;
308}
309
310static int rk_edp_link_configure(struct rk_edp *edp)
311{
312 u8 values[2];
313
314 values[0] = edp->link_train.link_rate;
315 values[1] = edp->link_train.lane_count;
316
317 return rk_edp_dpcd_write(edp, DPCD_LINK_BW_SET, values, sizeof(values));
318}
319
320static void rk_edp_set_link_training(struct rk_edp *edp,
321 const u8 *training_values)
322{
323 int i;
324
325 for (i = 0; i < edp->link_train.lane_count; i++)
Julius Werner2f37bd62015-02-19 14:51:15 -0800326 write32(&edp->regs->ln_link_trn_ctl[i], training_values[i]);
huang lin40f558e2014-09-19 14:51:52 +0800327}
328
329static u8 edp_link_status(const u8 *link_status, int r)
330{
331 return link_status[r - DPCD_LANE0_1_STATUS];
332}
333
334static int rk_edp_dpcd_read_link_status(struct rk_edp *edp, u8 *link_status)
335{
336 return rk_edp_dpcd_read(edp, DPCD_LANE0_1_STATUS, link_status,
337 DP_LINK_STATUS_SIZE);
338}
339
340static u8 edp_get_lane_status(const u8 *link_status, int lane)
341{
342 int i = DPCD_LANE0_1_STATUS + (lane >> 1);
343 int s = (lane & 1) * 4;
344 u8 l = edp_link_status(link_status, i);
Lin Huangb9a78772016-04-25 18:50:55 +0800345
huang lin40f558e2014-09-19 14:51:52 +0800346 return (l >> s) & 0xf;
347}
348
349static int rk_edp_clock_recovery_ok(const u8 *link_status, int lane_count)
350{
351 int lane;
352 u8 lane_status;
353
354 for (lane = 0; lane < lane_count; lane++) {
355 lane_status = edp_get_lane_status(link_status, lane);
356 if ((lane_status & DP_LANE_CR_DONE) == 0)
357 return 0;
358 }
359 return 1;
360}
361
362static int rk_edp_channel_eq_ok(const u8 *link_status, int lane_count)
363{
364 u8 lane_align;
365 u8 lane_status;
366 int lane;
367
368 lane_align = edp_link_status(link_status,
369 DPCD_LANE_ALIGN_STATUS_UPDATED);
370 if ((lane_align & DP_INTERLANE_ALIGN_DONE) == 0)
371 return 0;
372 for (lane = 0; lane < lane_count; lane++) {
373 lane_status = edp_get_lane_status(link_status, lane);
374 if ((lane_status & DP_CHANNEL_EQ_BITS) != DP_CHANNEL_EQ_BITS)
375 return 0;
376 }
377 return 1;
378}
379
380static u8
381rk_edp_get_adjust_request_voltage(const u8 *link_status, int lane)
382{
383 int i = DPCD_ADJUST_REQUEST_LANE0_1 + (lane >> 1);
384 int s = ((lane & 1) ?
385 DP_ADJUST_VOLTAGE_SWING_LANE1_SHIFT :
386 DP_ADJUST_VOLTAGE_SWING_LANE0_SHIFT);
387 u8 l = edp_link_status(link_status, i);
388
389 return ((l >> s) & 0x3) << DP_TRAIN_VOLTAGE_SWING_SHIFT;
390}
391
392static u8 rk_edp_get_adjust_request_pre_emphasis(const u8 *link_status,
393 int lane)
394{
395 int i = DPCD_ADJUST_REQUEST_LANE0_1 + (lane >> 1);
396 int s = ((lane & 1) ?
397 DP_ADJUST_PRE_EMPHASIS_LANE1_SHIFT :
398 DP_ADJUST_PRE_EMPHASIS_LANE0_SHIFT);
399 u8 l = edp_link_status(link_status, i);
400
401 return ((l >> s) & 0x3) << DP_TRAIN_PRE_EMPHASIS_SHIFT;
402}
403
404static void edp_get_adjust_train(const u8 *link_status, int lane_count,
405 u8 train_set[])
406{
407 u8 v = 0;
408 u8 p = 0;
409 int lane;
410
411 for (lane = 0; lane < lane_count; lane++) {
412 u8 this_v =
413 rk_edp_get_adjust_request_voltage(link_status, lane);
414 u8 this_p =
415 rk_edp_get_adjust_request_pre_emphasis(link_status,
416 lane);
417
418 printk(BIOS_DEBUG, "requested signal parameters: lane %d "
419 "voltage %s pre_emph %s\n", lane,
420 voltage_names[this_v >> DP_TRAIN_VOLTAGE_SWING_SHIFT],
421 pre_emph_names[this_p >> DP_TRAIN_PRE_EMPHASIS_SHIFT]);
422
423 if (this_v > v)
424 v = this_v;
425 if (this_p > p)
426 p = this_p;
427 }
428
429 if (v >= DP_VOLTAGE_MAX)
430 v |= DP_TRAIN_MAX_SWING_REACHED;
431
432 if (p >= DP_PRE_EMPHASIS_MAX)
433 p |= DP_TRAIN_MAX_PRE_EMPHASIS_REACHED;
434
435 printk(BIOS_DEBUG, "using signal parameters: voltage %s pre_emph %s\n",
436 voltage_names[(v & DP_TRAIN_VOLTAGE_SWING_MASK)
437 >> DP_TRAIN_VOLTAGE_SWING_SHIFT],
438 pre_emph_names[(p & DP_TRAIN_PRE_EMPHASIS_MASK)
439 >> DP_TRAIN_PRE_EMPHASIS_SHIFT]);
440
441 for (lane = 0; lane < 4; lane++)
442 train_set[lane] = v | p;
443}
444
445static int rk_edp_link_train_cr(struct rk_edp *edp)
446{
447 int clock_recovery;
448 u8 voltage, tries = 0;
449 u8 status[DP_LINK_STATUS_SIZE];
450 int i;
451 u8 value;
452
453 value = DP_TRAINING_PATTERN_1;
Julius Werner2f37bd62015-02-19 14:51:15 -0800454 write32(&edp->regs->dp_training_ptn_set, value);
huang lin40f558e2014-09-19 14:51:52 +0800455 rk_edp_dpcd_write(edp, DPCD_TRAINING_PATTERN_SET, &value, 1);
456 memset(edp->train_set, 0, 4);
457
458 /* clock recovery loop */
459 clock_recovery = 0;
460 tries = 0;
461 voltage = 0xff;
462
463 while (1) {
464 rk_edp_set_link_training(edp, edp->train_set);
465 rk_edp_dpcd_write(edp, DPCD_TRAINING_LANE0_SET,
466 edp->train_set,
467 edp->link_train.lane_count);
468
469 mdelay(1);
470
471 if (rk_edp_dpcd_read_link_status(edp, status) < 0) {
472 printk(BIOS_ERR, "displayport link status failed\n");
473 break;
474 }
475
476 if (rk_edp_clock_recovery_ok(status,
477 edp->link_train.lane_count)) {
478 clock_recovery = 1;
479 break;
480 }
481
482 for (i = 0; i < edp->link_train.lane_count; i++) {
483 if ((edp->train_set[i] &
484 DP_TRAIN_MAX_SWING_REACHED) == 0)
485 break;
486 }
487 if (i == edp->link_train.lane_count) {
488 printk(BIOS_ERR, "clock recovery reached max voltage\n");
489 break;
490 }
491
492 if ((edp->train_set[0] &
493 DP_TRAIN_VOLTAGE_SWING_MASK) == voltage) {
494 ++tries;
495 if (tries == MAX_CR_LOOP) {
496 printk(BIOS_ERR, "clock recovery tried 5 times\n");
497 break;
498 }
499 } else
500 tries = 0;
501
502 voltage = edp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK;
503
504 /* Compute new train_set as requested by sink */
505 edp_get_adjust_train(status, edp->link_train.lane_count,
506 edp->train_set);
507 }
508 if (!clock_recovery) {
509 printk(BIOS_ERR, "clock recovery failed\n");
510 return -1;
511 } else {
512 printk(BIOS_DEBUG, "clock recovery at voltage %d pre-emphasis %d\n",
513 edp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK,
514 (edp->train_set[0] & DP_TRAIN_PRE_EMPHASIS_MASK) >>
515 DP_TRAIN_PRE_EMPHASIS_SHIFT);
516 return 0;
517 }
518}
519
520static int rk_edp_link_train_ce(struct rk_edp *edp)
521{
522 int channel_eq;
523 u8 value, tries = 0;
524 u8 status[DP_LINK_STATUS_SIZE];
525
526 value = DP_TRAINING_PATTERN_2;
Julius Werner2f37bd62015-02-19 14:51:15 -0800527 write32(&edp->regs->dp_training_ptn_set, value);
huang lin40f558e2014-09-19 14:51:52 +0800528 rk_edp_dpcd_write(edp, DPCD_TRAINING_PATTERN_SET, &value, 1);
529
530 /* channel equalization loop */
531 channel_eq = 0;
532 for (tries = 0; tries < 5; tries++) {
533 rk_edp_set_link_training(edp, edp->train_set);
Lin Huangb9a78772016-04-25 18:50:55 +0800534 rk_edp_dpcd_write(edp, DPCD_TRAINING_LANE0_SET,
535 edp->train_set,
536 edp->link_train.lane_count);
huang lin40f558e2014-09-19 14:51:52 +0800537
Lin Huangb9a78772016-04-25 18:50:55 +0800538 udelay(400);
huang lin40f558e2014-09-19 14:51:52 +0800539 if (rk_edp_dpcd_read_link_status(edp, status) < 0) {
540 printk(BIOS_ERR, "displayport link status failed\n");
541 return -1;
542 }
543
544 if (rk_edp_channel_eq_ok(status,
545 edp->link_train.lane_count)) {
546 channel_eq = 1;
547 break;
548 }
549 edp_get_adjust_train(status,
550 edp->link_train.lane_count,
551 edp->train_set);
552 }
553
554 if (!channel_eq) {
555 printk(BIOS_ERR, "channel eq failed\n");
556 return -1;
557 } else {
558 printk(BIOS_DEBUG, "channel eq at voltage %d pre-emphasis %d\n",
559 edp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK,
560 (edp->train_set[0] & DP_TRAIN_PRE_EMPHASIS_MASK)
561 >> DP_TRAIN_PRE_EMPHASIS_SHIFT);
562 return 0;
563 }
564}
565
566static int rk_edp_init_training(struct rk_edp *edp)
567{
568 u8 values[3];
569 int err;
570
571 err = rk_edp_dpcd_read(edp, DPCD_DPCD_REV, values, sizeof(values));
572 if (err < 0)
573 return err;
574
575 edp->link_train.revision = values[0];
576 edp->link_train.link_rate = values[1];
577 edp->link_train.lane_count = values[2] & DP_MAX_LANE_COUNT_MASK;
578
579 edp_debug("max link rate:%d.%dGps max number of lanes:%d\n",
580 edp->link_train.link_rate * 27 / 100,
581 edp->link_train.link_rate * 27 % 100,
582 edp->link_train.lane_count);
583
584 if ((edp->link_train.link_rate != LINK_RATE_1_62GBPS) &&
585 (edp->link_train.link_rate != LINK_RATE_2_70GBPS)) {
586 edp_debug("Rx Max Link Rate is abnormal :%x\n",
587 edp->link_train.link_rate);
588 return -1;
589 }
590
591 if (edp->link_train.lane_count == 0) {
592 edp_debug("Rx Max Lane count is abnormal :%x\n",
593 edp->link_train.lane_count);
594 return -1;
595 }
596
597 rk_edp_link_power_up(edp);
598 rk_edp_link_configure(edp);
599 return 0;
600}
601
602static int rk_edp_hw_link_training(struct rk_edp *edp)
603{
604 u32 val;
605 struct stopwatch sw;
606
607 /* Set link rate and count as you want to establish*/
Julius Werner2f37bd62015-02-19 14:51:15 -0800608 write32(&edp->regs->link_bw_set, edp->link_train.link_rate);
609 write32(&edp->regs->lane_count_set, edp->link_train.lane_count);
huang lin40f558e2014-09-19 14:51:52 +0800610
611 if (rk_edp_link_train_cr(edp))
612 return -1;
613 if (rk_edp_link_train_ce(edp))
614 return -1;
615
Julius Werner2f37bd62015-02-19 14:51:15 -0800616 write32(&edp->regs->dp_hw_link_training, HW_LT_EN);
huang lin40f558e2014-09-19 14:51:52 +0800617 stopwatch_init_msecs_expire(&sw, 10);
618 do {
Julius Werner2f37bd62015-02-19 14:51:15 -0800619 val = read32(&edp->regs->dp_hw_link_training);
huang lin40f558e2014-09-19 14:51:52 +0800620 if (!(val & HW_LT_EN))
621 break;
622 } while (!stopwatch_expired(&sw));
623 if (val & HW_LT_ERR_CODE_MASK) {
624 printk(BIOS_ERR, "edp hw link training error: %d\n",
625 val >> HW_LT_ERR_CODE_SHIFT);
626 return -1;
627 }
628 return 0;
huang lin40f558e2014-09-19 14:51:52 +0800629}
630
631static int rk_edp_select_i2c_device(struct rk_edp *edp,
632 unsigned int device_addr,
633 unsigned int val_addr)
634{
635 u32 val;
636 int retval;
637
638 /* Set EDID device address */
639 val = device_addr;
Julius Werner2f37bd62015-02-19 14:51:15 -0800640 write32(&edp->regs->aux_addr_7_0, val);
641 write32(&edp->regs->aux_addr_15_8, 0x0);
642 write32(&edp->regs->aux_addr_19_16, 0x0);
huang lin40f558e2014-09-19 14:51:52 +0800643
644 /* Set offset from base address of EDID device */
Julius Werner2f37bd62015-02-19 14:51:15 -0800645 write32(&edp->regs->buf_data[0], val_addr);
huang lin40f558e2014-09-19 14:51:52 +0800646
647 /*
648 * Set I2C transaction and write address
649 * If bit 3 is 1, DisplayPort transaction.
650 * If Bit 3 is 0, I2C transaction.
651 */
652 val = AUX_TX_COMM_I2C_TRANSACTION | AUX_TX_COMM_MOT |
653 AUX_TX_COMM_WRITE;
Julius Werner2f37bd62015-02-19 14:51:15 -0800654 write32(&edp->regs->aux_ch_ctl_1, val);
huang lin40f558e2014-09-19 14:51:52 +0800655
656 /* Start AUX transaction */
657 retval = rk_edp_start_aux_transaction(edp);
658 if (retval != 0)
659 edp_debug("select_i2c_device Aux Transaction fail!\n");
660
661 return retval;
662}
663
664static int rk_edp_read_bytes_from_i2c(struct rk_edp *edp,
665 unsigned int device_addr,
666 unsigned int val_addr,
667 unsigned int count,
668 u8 edid[])
669{
670 u32 val;
671 unsigned int i, j;
672 unsigned int cur_data_idx;
673 unsigned int defer = 0;
674 int retval = 0;
675
676 for (i = 0; i < count; i += 16) {
677 for (j = 0; j < 10; j++) { /* try 10 times */
678 /* Clear AUX CH data buffer */
679 val = BUF_CLR;
Julius Werner2f37bd62015-02-19 14:51:15 -0800680 write32(&edp->regs->buf_data_ctl, val);
huang lin40f558e2014-09-19 14:51:52 +0800681
682 /* Set normal AUX CH command */
Julius Werner55009af2019-12-02 22:03:27 -0800683 clrbits32(&edp->regs->aux_ch_ctl_2, ADDR_ONLY);
huang lin40f558e2014-09-19 14:51:52 +0800684
685 /*
686 * If Rx sends defer, Tx sends only reads
Lin Huangb9a78772016-04-25 18:50:55 +0800687 * request without sending address
huang lin40f558e2014-09-19 14:51:52 +0800688 */
689 if (!defer)
690 retval = rk_edp_select_i2c_device(edp,
691 device_addr, val_addr + i);
692 else
693 defer = 0;
694
695 /*
696 * Set I2C transaction and write data
697 * If bit 3 is 1, DisplayPort transaction.
698 * If Bit 3 is 0, I2C transaction.
699 */
700 val = AUX_LENGTH(16) | AUX_TX_COMM_I2C_TRANSACTION |
701 AUX_TX_COMM_READ;
Julius Werner2f37bd62015-02-19 14:51:15 -0800702 write32(&edp->regs->aux_ch_ctl_1, val);
huang lin40f558e2014-09-19 14:51:52 +0800703
704 /* Start AUX transaction */
705 retval = rk_edp_start_aux_transaction(edp);
706 if (retval == 0)
707 break;
708 else {
709 edp_debug("Aux Transaction fail!\n");
710 continue;
711 }
712
713 /* Check if Rx sends defer */
Julius Werner2f37bd62015-02-19 14:51:15 -0800714 val = read32(&edp->regs->aux_rx_comm);
huang lin40f558e2014-09-19 14:51:52 +0800715 if (val == AUX_RX_COMM_AUX_DEFER ||
716 val == AUX_RX_COMM_I2C_DEFER) {
717 edp_debug("Defer: %d\n\n", val);
718 defer = 1;
719 }
720 }
721
722 if (retval)
723 return -1;
724
725 for (cur_data_idx = 0; cur_data_idx < 16; cur_data_idx++) {
Julius Werner2f37bd62015-02-19 14:51:15 -0800726 val = read32(&edp->regs->buf_data[cur_data_idx]);
huang lin40f558e2014-09-19 14:51:52 +0800727 edid[i + cur_data_idx] = (u8)val;
728 }
729 }
730
731 return retval;
732}
733
734static int rk_edp_read_edid(struct rk_edp *edp, struct edid *edid)
735{
736 u8 buf[EDID_LENGTH * 2];
huang linc16ba0a2015-01-14 13:56:40 +0800737 u32 edid_size = EDID_LENGTH;
huang lin40f558e2014-09-19 14:51:52 +0800738 int retval;
739
740 /* Read EDID data */
741 retval = rk_edp_read_bytes_from_i2c(edp, EDID_ADDR,
742 EDID_HEADER, EDID_LENGTH,
743 &buf[EDID_HEADER]);
744 if (retval != 0) {
745 printk(BIOS_ERR, "EDID Read failed!\n");
746 return -1;
747 }
748
749 /* check if edid have extension flag, and read additional EDID data */
750 if (buf[EDID_EXTENSION_FLAG]) {
huang linc16ba0a2015-01-14 13:56:40 +0800751 edid_size += EDID_LENGTH;
huang lin40f558e2014-09-19 14:51:52 +0800752 retval = rk_edp_read_bytes_from_i2c(edp, EDID_ADDR,
753 EDID_LENGTH, EDID_LENGTH,
754 &buf[EDID_LENGTH]);
755 if (retval != 0) {
756 printk(BIOS_ERR, "EDID Read failed!\n");
757 return -1;
758 }
759 }
760
Arthur Heymans8c5884e2017-04-30 08:28:05 +0200761 if (decode_edid(buf, edid_size, edid) != EDID_CONFORMANT) {
huang lin40f558e2014-09-19 14:51:52 +0800762 printk(BIOS_ERR, "%s: Failed to decode EDID.\n",
763 __func__);
764 return -1;
765 }
766
767 edp_debug("EDID Read success!\n");
768 return 0;
769}
770
771static int rk_edp_set_link_train(struct rk_edp *edp)
772{
773 int retval;
774
775 if (rk_edp_init_training(edp)) {
776 printk(BIOS_ERR, "DP LT init failed!\n");
777 return -1;
778 }
779
780 retval = rk_edp_hw_link_training(edp);
781
782 return retval;
783}
784
785static void rk_edp_init_video(struct rk_edp *edp)
786{
787 u32 val;
788
789 val = VSYNC_DET | VID_FORMAT_CHG | VID_CLK_CHG;
Julius Werner2f37bd62015-02-19 14:51:15 -0800790 write32(&edp->regs->common_int_sta_1, val);
huang lin40f558e2014-09-19 14:51:52 +0800791
792 val = CHA_CRI(4) | CHA_CTRL;
Julius Werner2f37bd62015-02-19 14:51:15 -0800793 write32(&edp->regs->sys_ctl_2, val);
huang lin40f558e2014-09-19 14:51:52 +0800794
795 val = VID_HRES_TH(2) | VID_VRES_TH(0);
Julius Werner2f37bd62015-02-19 14:51:15 -0800796 write32(&edp->regs->video_ctl_8, val);
huang lin40f558e2014-09-19 14:51:52 +0800797}
798
799static void rk_edp_config_video_slave_mode(struct rk_edp *edp)
800{
Julius Werner55009af2019-12-02 22:03:27 -0800801 clrbits32(&edp->regs->func_en_1,
huang lin40f558e2014-09-19 14:51:52 +0800802 VID_FIFO_FUNC_EN_N | VID_CAP_FUNC_EN_N);
803}
804
805static void rk_edp_set_video_cr_mn(struct rk_edp *edp,
806 enum clock_recovery_m_value_type type,
807 u32 m_value,
808 u32 n_value)
809{
810 u32 val;
811
812 if (type == REGISTER_M) {
Julius Werner55009af2019-12-02 22:03:27 -0800813 setbits32(&edp->regs->sys_ctl_4, FIX_M_VID);
huang lin40f558e2014-09-19 14:51:52 +0800814 val = m_value & 0xff;
Julius Werner2f37bd62015-02-19 14:51:15 -0800815 write32(&edp->regs->m_vid_0, val);
huang lin40f558e2014-09-19 14:51:52 +0800816 val = (m_value >> 8) & 0xff;
Julius Werner2f37bd62015-02-19 14:51:15 -0800817 write32(&edp->regs->m_vid_1, val);
huang lin40f558e2014-09-19 14:51:52 +0800818 val = (m_value >> 16) & 0xff;
Julius Werner2f37bd62015-02-19 14:51:15 -0800819 write32(&edp->regs->m_vid_2, val);
huang lin40f558e2014-09-19 14:51:52 +0800820
821 val = n_value & 0xff;
Julius Werner2f37bd62015-02-19 14:51:15 -0800822 write32(&edp->regs->n_vid_0, val);
huang lin40f558e2014-09-19 14:51:52 +0800823 val = (n_value >> 8) & 0xff;
Julius Werner2f37bd62015-02-19 14:51:15 -0800824 write32(&edp->regs->n_vid_1, val);
huang lin40f558e2014-09-19 14:51:52 +0800825 val = (n_value >> 16) & 0xff;
Julius Werner2f37bd62015-02-19 14:51:15 -0800826 write32(&edp->regs->n_vid_2, val);
huang lin40f558e2014-09-19 14:51:52 +0800827 } else {
Julius Werner55009af2019-12-02 22:03:27 -0800828 clrbits32(&edp->regs->sys_ctl_4, FIX_M_VID);
huang lin40f558e2014-09-19 14:51:52 +0800829
Julius Werner2f37bd62015-02-19 14:51:15 -0800830 write32(&edp->regs->n_vid_0, 0x00);
831 write32(&edp->regs->n_vid_1, 0x80);
832 write32(&edp->regs->n_vid_2, 0x00);
huang lin40f558e2014-09-19 14:51:52 +0800833 }
834}
835
836static int rk_edp_is_video_stream_clock_on(struct rk_edp *edp)
837{
838 u32 val;
839 struct stopwatch sw;
840
841 stopwatch_init_msecs_expire(&sw, 100);
842 do {
Julius Werner2f37bd62015-02-19 14:51:15 -0800843 val = read32(&edp->regs->sys_ctl_1);
huang lin40f558e2014-09-19 14:51:52 +0800844
845 /*must write value to update DET_STA bit status*/
Julius Werner2f37bd62015-02-19 14:51:15 -0800846 write32(&edp->regs->sys_ctl_1, val);
847 val = read32(&edp->regs->sys_ctl_1);
huang lin40f558e2014-09-19 14:51:52 +0800848 if (!(val & DET_STA))
849 continue;
850
Julius Werner2f37bd62015-02-19 14:51:15 -0800851 val = read32(&edp->regs->sys_ctl_2);
huang lin40f558e2014-09-19 14:51:52 +0800852
853 /*must write value to update CHA_STA bit status*/
Julius Werner2f37bd62015-02-19 14:51:15 -0800854 write32(&edp->regs->sys_ctl_2, val);
855 val = read32(&edp->regs->sys_ctl_2);
huang lin40f558e2014-09-19 14:51:52 +0800856 if (!(val & CHA_STA))
857 return 0;
858 } while (!stopwatch_expired(&sw));
859
860 return -1;
861}
862
863static int rk_edp_is_video_stream_on(struct rk_edp *edp)
864{
865 u32 val;
866 struct stopwatch sw;
867
868 stopwatch_init_msecs_expire(&sw, 100);
869 do {
Julius Werner2f37bd62015-02-19 14:51:15 -0800870 val = read32(&edp->regs->sys_ctl_3);
huang lin40f558e2014-09-19 14:51:52 +0800871
872 /*must write value to update STRM_VALID bit status*/
Julius Werner2f37bd62015-02-19 14:51:15 -0800873 write32(&edp->regs->sys_ctl_3, val);
huang lin40f558e2014-09-19 14:51:52 +0800874
Julius Werner2f37bd62015-02-19 14:51:15 -0800875 val = read32(&edp->regs->sys_ctl_3);
huang lin40f558e2014-09-19 14:51:52 +0800876 if (!(val & STRM_VALID))
877 return 0;
878 } while (!stopwatch_expired(&sw));
879
880 return -1;
881}
882
883static int rk_edp_config_video(struct rk_edp *edp)
884{
885 rk_edp_config_video_slave_mode(edp);
886
887 if (rk_edp_get_pll_lock_status(edp) == DP_PLL_UNLOCKED) {
888 edp_debug("PLL is not locked yet.\n");
889 return -1;
890 }
891
892 if (rk_edp_is_video_stream_clock_on(edp))
893 return -1;
894
895 /* Set to use the register calculated M/N video */
896 rk_edp_set_video_cr_mn(edp, CALCULATED_M, 0, 0);
897
898 /* For video bist, Video timing must be generated by register */
Julius Werner55009af2019-12-02 22:03:27 -0800899 clrbits32(&edp->regs->video_ctl_10, F_SEL);
huang lin40f558e2014-09-19 14:51:52 +0800900
901 /* Disable video mute */
Julius Werner55009af2019-12-02 22:03:27 -0800902 clrbits32(&edp->regs->video_ctl_1, VIDEO_MUTE);
huang lin40f558e2014-09-19 14:51:52 +0800903
Lin Huanga09b3382016-10-23 14:17:25 -0700904 return 0;
huang lin40f558e2014-09-19 14:51:52 +0800905}
906
huang linc14e4262015-01-23 16:41:20 +0800907static void rockchip_edp_force_hpd(struct rk_edp *edp)
908{
909 u32 val;
910
Julius Werner2f37bd62015-02-19 14:51:15 -0800911 val = read32(&edp->regs->sys_ctl_3);
huang linc14e4262015-01-23 16:41:20 +0800912 val |= (F_HPD | HPD_CTRL);
Julius Werner2f37bd62015-02-19 14:51:15 -0800913 write32(&edp->regs->sys_ctl_3, val);
huang linc14e4262015-01-23 16:41:20 +0800914}
915
916static int rockchip_edp_get_plug_in_status(struct rk_edp *edp)
917{
918 u32 val;
919
Julius Werner2f37bd62015-02-19 14:51:15 -0800920 val = read32(&edp->regs->sys_ctl_3);
huang linc14e4262015-01-23 16:41:20 +0800921 if (val & HPD_STATUS)
922 return 1;
923
924 return 0;
925}
926
927/*
928 * support edp HPD function
929 * some hardware version do not support edp hdp,
Lin Huangb9a78772016-04-25 18:50:55 +0800930 * we use 360ms to try to get the hpd single now,
931 * if we can not get edp hpd single, it will delay 360ms,
huang linc14e4262015-01-23 16:41:20 +0800932 * also meet the edp power timing request, to compatible
933 * all of the hardware version
934 */
Lin Huangb9a78772016-04-25 18:50:55 +0800935static void rk_edp_wait_hpd(struct rk_edp *edp)
huang linc14e4262015-01-23 16:41:20 +0800936{
937 struct stopwatch hpd;
938
Lin Huangb9a78772016-04-25 18:50:55 +0800939 stopwatch_init_msecs_expire(&hpd, 360);
huang linc14e4262015-01-23 16:41:20 +0800940 do {
941 if (rockchip_edp_get_plug_in_status(edp))
942 return;
943 udelay(100);
944 } while (!stopwatch_expired(&hpd));
945
946 printk(BIOS_DEBUG, "do not get hpd single, force hpd\n");
947 rockchip_edp_force_hpd(edp);
948}
949
huang lin40f558e2014-09-19 14:51:52 +0800950int rk_edp_get_edid(struct edid *edid)
951{
952 int i;
953 int retval;
954
955 /* Read EDID */
956 for (i = 0; i < 3; i++) {
957 retval = rk_edp_read_edid(&rk_edp, edid);
958 if (retval == 0)
959 break;
960 }
961
962 return retval;
963}
964
Lin Huanga09b3382016-10-23 14:17:25 -0700965int rk_edp_prepare(void)
huang lin40f558e2014-09-19 14:51:52 +0800966{
967 int ret = 0;
968
969 if (rk_edp_set_link_train(&rk_edp)) {
970 printk(BIOS_ERR, "link train failed!\n");
971 return -1;
972 }
973
974 rk_edp_init_video(&rk_edp);
975 ret = rk_edp_config_video(&rk_edp);
976 if (ret)
977 printk(BIOS_ERR, "config video failed\n");
978
979 return ret;
980}
981
Lin Huanga09b3382016-10-23 14:17:25 -0700982int rk_edp_enable(void)
983{
984 /* Enable video at next frame */
Julius Werner55009af2019-12-02 22:03:27 -0800985 setbits32(&rk_edp.regs->video_ctl_1, VIDEO_EN);
Lin Huanga09b3382016-10-23 14:17:25 -0700986
987 return rk_edp_is_video_stream_on(&rk_edp);
988}
989
Lin Huangb9a78772016-04-25 18:50:55 +0800990void rk_edp_init(void)
huang lin40f558e2014-09-19 14:51:52 +0800991{
Lin Huangb9a78772016-04-25 18:50:55 +0800992 rk_edp.regs = (struct rk_edp_regs *)EDP_BASE;
huang lin40f558e2014-09-19 14:51:52 +0800993
Lin Huangb9a78772016-04-25 18:50:55 +0800994 rk_edp_wait_hpd(&rk_edp);
huang linc14e4262015-01-23 16:41:20 +0800995
huang lin40f558e2014-09-19 14:51:52 +0800996 rk_edp_init_refclk(&rk_edp);
997 rk_edp_init_interrupt(&rk_edp);
998 rk_edp_enable_sw_function(&rk_edp);
999 rk_edp_init_analog_func(&rk_edp);
1000 rk_edp_init_aux(&rk_edp);
1001}