uboot/drivers/video/exynos/exynos_dp.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (C) 2012 Samsung Electronics
   4 *
   5 * Author: Donghwa Lee <dh09.lee@samsung.com>
   6 */
   7
   8#include <common.h>
   9#include <dm.h>
  10#include <common.h>
  11#include <display.h>
  12#include <fdtdec.h>
  13#include <log.h>
  14#include <linux/delay.h>
  15#include <linux/libfdt.h>
  16#include <malloc.h>
  17#include <video_bridge.h>
  18#include <linux/compat.h>
  19#include <linux/err.h>
  20#include <asm/arch/clk.h>
  21#include <asm/arch/cpu.h>
  22#include <asm/arch/dp_info.h>
  23#include <asm/arch/dp.h>
  24#include <asm/arch/pinmux.h>
  25#include <asm/arch/power.h>
  26
  27#include "exynos_dp_lowlevel.h"
  28
  29DECLARE_GLOBAL_DATA_PTR;
  30
  31static void exynos_dp_disp_info(struct edp_disp_info *disp_info)
  32{
  33        disp_info->h_total = disp_info->h_res + disp_info->h_sync_width +
  34                disp_info->h_back_porch + disp_info->h_front_porch;
  35        disp_info->v_total = disp_info->v_res + disp_info->v_sync_width +
  36                disp_info->v_back_porch + disp_info->v_front_porch;
  37
  38        return;
  39}
  40
  41static int exynos_dp_init_dp(struct exynos_dp *regs)
  42{
  43        int ret;
  44        exynos_dp_reset(regs);
  45
  46        /* SW defined function Normal operation */
  47        exynos_dp_enable_sw_func(regs, DP_ENABLE);
  48
  49        ret = exynos_dp_init_analog_func(regs);
  50        if (ret != EXYNOS_DP_SUCCESS)
  51                return ret;
  52
  53        exynos_dp_init_hpd(regs);
  54        exynos_dp_init_aux(regs);
  55
  56        return ret;
  57}
  58
  59static unsigned char exynos_dp_calc_edid_check_sum(unsigned char *edid_data)
  60{
  61        int i;
  62        unsigned char sum = 0;
  63
  64        for (i = 0; i < EDID_BLOCK_LENGTH; i++)
  65                sum = sum + edid_data[i];
  66
  67        return sum;
  68}
  69
  70static unsigned int exynos_dp_read_edid(struct exynos_dp *regs)
  71{
  72        unsigned char edid[EDID_BLOCK_LENGTH * 2];
  73        unsigned int extend_block = 0;
  74        unsigned char sum;
  75        unsigned char test_vector;
  76        int retval;
  77
  78        /*
  79         * EDID device address is 0x50.
  80         * However, if necessary, you must have set upper address
  81         * into E-EDID in I2C device, 0x30.
  82         */
  83
  84        /* Read Extension Flag, Number of 128-byte EDID extension blocks */
  85        exynos_dp_read_byte_from_i2c(regs, I2C_EDID_DEVICE_ADDR,
  86                                     EDID_EXTENSION_FLAG, &extend_block);
  87
  88        if (extend_block > 0) {
  89                printf("DP EDID data includes a single extension!\n");
  90
  91                /* Read EDID data */
  92                retval = exynos_dp_read_bytes_from_i2c(regs,
  93                                                I2C_EDID_DEVICE_ADDR,
  94                                                EDID_HEADER_PATTERN,
  95                                                EDID_BLOCK_LENGTH,
  96                                                &edid[EDID_HEADER_PATTERN]);
  97                if (retval != 0) {
  98                        printf("DP EDID Read failed!\n");
  99                        return -1;
 100                }
 101                sum = exynos_dp_calc_edid_check_sum(edid);
 102                if (sum != 0) {
 103                        printf("DP EDID bad checksum!\n");
 104                        return -1;
 105                }
 106
 107                /* Read additional EDID data */
 108                retval = exynos_dp_read_bytes_from_i2c(regs,
 109                                I2C_EDID_DEVICE_ADDR,
 110                                EDID_BLOCK_LENGTH,
 111                                EDID_BLOCK_LENGTH,
 112                                &edid[EDID_BLOCK_LENGTH]);
 113                if (retval != 0) {
 114                        printf("DP EDID Read failed!\n");
 115                        return -1;
 116                }
 117                sum = exynos_dp_calc_edid_check_sum(&edid[EDID_BLOCK_LENGTH]);
 118                if (sum != 0) {
 119                        printf("DP EDID bad checksum!\n");
 120                        return -1;
 121                }
 122
 123                exynos_dp_read_byte_from_dpcd(regs, DPCD_TEST_REQUEST,
 124                                              &test_vector);
 125                if (test_vector & DPCD_TEST_EDID_READ) {
 126                        exynos_dp_write_byte_to_dpcd(regs,
 127                                DPCD_TEST_EDID_CHECKSUM,
 128                                edid[EDID_BLOCK_LENGTH + EDID_CHECKSUM]);
 129                        exynos_dp_write_byte_to_dpcd(regs,
 130                                DPCD_TEST_RESPONSE,
 131                                DPCD_TEST_EDID_CHECKSUM_WRITE);
 132                }
 133        } else {
 134                debug("DP EDID data does not include any extensions.\n");
 135
 136                /* Read EDID data */
 137                retval = exynos_dp_read_bytes_from_i2c(regs,
 138                                I2C_EDID_DEVICE_ADDR,
 139                                EDID_HEADER_PATTERN,
 140                                EDID_BLOCK_LENGTH,
 141                                &edid[EDID_HEADER_PATTERN]);
 142
 143                if (retval != 0) {
 144                        printf("DP EDID Read failed!\n");
 145                        return -1;
 146                }
 147                sum = exynos_dp_calc_edid_check_sum(edid);
 148                if (sum != 0) {
 149                        printf("DP EDID bad checksum!\n");
 150                        return -1;
 151                }
 152
 153                exynos_dp_read_byte_from_dpcd(regs, DPCD_TEST_REQUEST,
 154                        &test_vector);
 155                if (test_vector & DPCD_TEST_EDID_READ) {
 156                        exynos_dp_write_byte_to_dpcd(regs,
 157                                DPCD_TEST_EDID_CHECKSUM, edid[EDID_CHECKSUM]);
 158                        exynos_dp_write_byte_to_dpcd(regs,
 159                                DPCD_TEST_RESPONSE,
 160                                DPCD_TEST_EDID_CHECKSUM_WRITE);
 161                }
 162        }
 163
 164        debug("DP EDID Read success!\n");
 165
 166        return 0;
 167}
 168
 169static unsigned int exynos_dp_handle_edid(struct exynos_dp *regs,
 170                                          struct exynos_dp_priv *priv)
 171{
 172        unsigned char buf[12];
 173        unsigned int ret;
 174        unsigned char temp;
 175        unsigned char retry_cnt;
 176        unsigned char dpcd_rev[16];
 177        unsigned char lane_bw[16];
 178        unsigned char lane_cnt[16];
 179
 180        memset(dpcd_rev, 0, 16);
 181        memset(lane_bw, 0, 16);
 182        memset(lane_cnt, 0, 16);
 183        memset(buf, 0, 12);
 184
 185        retry_cnt = 5;
 186        while (retry_cnt) {
 187                /* Read DPCD 0x0000-0x000b */
 188                ret = exynos_dp_read_bytes_from_dpcd(regs, DPCD_DPCD_REV, 12,
 189                                                     buf);
 190                if (ret != EXYNOS_DP_SUCCESS) {
 191                        if (retry_cnt == 0) {
 192                                printf("DP read_byte_from_dpcd() failed\n");
 193                                return ret;
 194                        }
 195                        retry_cnt--;
 196                } else
 197                        break;
 198        }
 199
 200        /* */
 201        temp = buf[DPCD_DPCD_REV];
 202        if (temp == DP_DPCD_REV_10 || temp == DP_DPCD_REV_11)
 203                priv->dpcd_rev = temp;
 204        else {
 205                printf("DP Wrong DPCD Rev : %x\n", temp);
 206                return -ENODEV;
 207        }
 208
 209        temp = buf[DPCD_MAX_LINK_RATE];
 210        if (temp == DP_LANE_BW_1_62 || temp == DP_LANE_BW_2_70)
 211                priv->lane_bw = temp;
 212        else {
 213                printf("DP Wrong MAX LINK RATE : %x\n", temp);
 214                return -EINVAL;
 215        }
 216
 217        /* Refer VESA Display Port Standard Ver1.1a Page 120 */
 218        if (priv->dpcd_rev == DP_DPCD_REV_11) {
 219                temp = buf[DPCD_MAX_LANE_COUNT] & 0x1f;
 220                if (buf[DPCD_MAX_LANE_COUNT] & 0x80)
 221                        priv->dpcd_efc = 1;
 222                else
 223                        priv->dpcd_efc = 0;
 224        } else {
 225                temp = buf[DPCD_MAX_LANE_COUNT];
 226                priv->dpcd_efc = 0;
 227        }
 228
 229        if (temp == DP_LANE_CNT_1 || temp == DP_LANE_CNT_2 ||
 230                        temp == DP_LANE_CNT_4) {
 231                priv->lane_cnt = temp;
 232        } else {
 233                printf("DP Wrong MAX LANE COUNT : %x\n", temp);
 234                return -EINVAL;
 235        }
 236
 237        ret = exynos_dp_read_edid(regs);
 238        if (ret != EXYNOS_DP_SUCCESS) {
 239                printf("DP exynos_dp_read_edid() failed\n");
 240                return -EINVAL;
 241        }
 242
 243        return ret;
 244}
 245
 246static void exynos_dp_init_training(struct exynos_dp *regs)
 247{
 248        /*
 249         * MACRO_RST must be applied after the PLL_LOCK to avoid
 250         * the DP inter pair skew issue for at least 10 us
 251         */
 252        exynos_dp_reset_macro(regs);
 253
 254        /* All DP analog module power up */
 255        exynos_dp_set_analog_power_down(regs, POWER_ALL, 0);
 256}
 257
 258static unsigned int exynos_dp_link_start(struct exynos_dp *regs,
 259                                         struct exynos_dp_priv *priv)
 260{
 261        unsigned char buf[5];
 262        unsigned int ret = 0;
 263
 264        debug("DP: %s was called\n", __func__);
 265
 266        priv->lt_info.lt_status = DP_LT_CR;
 267        priv->lt_info.ep_loop = 0;
 268        priv->lt_info.cr_loop[0] = 0;
 269        priv->lt_info.cr_loop[1] = 0;
 270        priv->lt_info.cr_loop[2] = 0;
 271        priv->lt_info.cr_loop[3] = 0;
 272
 273                /* Set sink to D0 (Sink Not Ready) mode. */
 274        ret = exynos_dp_write_byte_to_dpcd(regs, DPCD_SINK_POWER_STATE,
 275                                           DPCD_SET_POWER_STATE_D0);
 276        if (ret != EXYNOS_DP_SUCCESS) {
 277                printf("DP write_dpcd_byte failed\n");
 278                return ret;
 279        }
 280
 281        /* Set link rate and count as you want to establish */
 282        exynos_dp_set_link_bandwidth(regs, priv->lane_bw);
 283        exynos_dp_set_lane_count(regs, priv->lane_cnt);
 284
 285        /* Setup RX configuration */
 286        buf[0] = priv->lane_bw;
 287        buf[1] = priv->lane_cnt;
 288
 289        ret = exynos_dp_write_bytes_to_dpcd(regs, DPCD_LINK_BW_SET, 2, buf);
 290        if (ret != EXYNOS_DP_SUCCESS) {
 291                printf("DP write_dpcd_byte failed\n");
 292                return ret;
 293        }
 294
 295        exynos_dp_set_lane_pre_emphasis(regs, PRE_EMPHASIS_LEVEL_0,
 296                        priv->lane_cnt);
 297
 298        /* Set training pattern 1 */
 299        exynos_dp_set_training_pattern(regs, TRAINING_PTN1);
 300
 301        /* Set RX training pattern */
 302        buf[0] = DPCD_SCRAMBLING_DISABLED | DPCD_TRAINING_PATTERN_1;
 303
 304        buf[1] = DPCD_PRE_EMPHASIS_SET_PATTERN_2_LEVEL_0 |
 305                DPCD_VOLTAGE_SWING_SET_PATTERN_1_LEVEL_0;
 306        buf[2] = DPCD_PRE_EMPHASIS_SET_PATTERN_2_LEVEL_0 |
 307                DPCD_VOLTAGE_SWING_SET_PATTERN_1_LEVEL_0;
 308        buf[3] = DPCD_PRE_EMPHASIS_SET_PATTERN_2_LEVEL_0 |
 309                DPCD_VOLTAGE_SWING_SET_PATTERN_1_LEVEL_0;
 310        buf[4] = DPCD_PRE_EMPHASIS_SET_PATTERN_2_LEVEL_0 |
 311                DPCD_VOLTAGE_SWING_SET_PATTERN_1_LEVEL_0;
 312
 313        ret = exynos_dp_write_bytes_to_dpcd(regs, DPCD_TRAINING_PATTERN_SET,
 314                                            5, buf);
 315        if (ret != EXYNOS_DP_SUCCESS) {
 316                printf("DP write_dpcd_byte failed\n");
 317                return ret;
 318        }
 319
 320        return ret;
 321}
 322
 323static unsigned int exynos_dp_training_pattern_dis(struct exynos_dp *regs)
 324{
 325        unsigned int ret;
 326
 327        exynos_dp_set_training_pattern(regs, DP_NONE);
 328
 329        ret = exynos_dp_write_byte_to_dpcd(regs, DPCD_TRAINING_PATTERN_SET,
 330                                           DPCD_TRAINING_PATTERN_DISABLED);
 331        if (ret != EXYNOS_DP_SUCCESS) {
 332                printf("DP request_link_training_req failed\n");
 333                return -EAGAIN;
 334        }
 335
 336        return ret;
 337}
 338
 339static unsigned int exynos_dp_enable_rx_to_enhanced_mode(
 340                struct exynos_dp *regs, unsigned char enable)
 341{
 342        unsigned char data;
 343        unsigned int ret;
 344
 345        ret = exynos_dp_read_byte_from_dpcd(regs, DPCD_LANE_COUNT_SET,
 346                                            &data);
 347        if (ret != EXYNOS_DP_SUCCESS) {
 348                printf("DP read_from_dpcd failed\n");
 349                return -EAGAIN;
 350        }
 351
 352        if (enable)
 353                data = DPCD_ENHANCED_FRAME_EN | DPCD_LN_COUNT_SET(data);
 354        else
 355                data = DPCD_LN_COUNT_SET(data);
 356
 357        ret = exynos_dp_write_byte_to_dpcd(regs, DPCD_LANE_COUNT_SET, data);
 358        if (ret != EXYNOS_DP_SUCCESS) {
 359                        printf("DP write_to_dpcd failed\n");
 360                        return -EAGAIN;
 361
 362        }
 363
 364        return ret;
 365}
 366
 367static unsigned int exynos_dp_set_enhanced_mode(struct exynos_dp *regs,
 368                                                unsigned char enhance_mode)
 369{
 370        unsigned int ret;
 371
 372        ret = exynos_dp_enable_rx_to_enhanced_mode(regs, enhance_mode);
 373        if (ret != EXYNOS_DP_SUCCESS) {
 374                printf("DP rx_enhance_mode failed\n");
 375                return -EAGAIN;
 376        }
 377
 378        exynos_dp_enable_enhanced_mode(regs, enhance_mode);
 379
 380        return ret;
 381}
 382
 383static int exynos_dp_read_dpcd_lane_stat(struct exynos_dp *regs,
 384                                         struct exynos_dp_priv *priv,
 385                                         unsigned char *status)
 386{
 387        unsigned int ret, i;
 388        unsigned char buf[2];
 389        unsigned char lane_stat[DP_LANE_CNT_4] = {0,};
 390        unsigned char shift_val[DP_LANE_CNT_4] = {0,};
 391
 392        shift_val[0] = 0;
 393        shift_val[1] = 4;
 394        shift_val[2] = 0;
 395        shift_val[3] = 4;
 396
 397        ret = exynos_dp_read_bytes_from_dpcd(regs, DPCD_LANE0_1_STATUS, 2,
 398                                             buf);
 399        if (ret != EXYNOS_DP_SUCCESS) {
 400                printf("DP read lane status failed\n");
 401                return ret;
 402        }
 403
 404        for (i = 0; i < priv->lane_cnt; i++) {
 405                lane_stat[i] = (buf[(i / 2)] >> shift_val[i]) & 0x0f;
 406                if (lane_stat[0] != lane_stat[i]) {
 407                        printf("Wrong lane status\n");
 408                        return -EINVAL;
 409                }
 410        }
 411
 412        *status = lane_stat[0];
 413
 414        return ret;
 415}
 416
 417static unsigned int exynos_dp_read_dpcd_adj_req(struct exynos_dp *regs,
 418                unsigned char lane_num, unsigned char *sw, unsigned char *em)
 419{
 420        unsigned int ret;
 421        unsigned char buf;
 422        unsigned int dpcd_addr;
 423        unsigned char shift_val[DP_LANE_CNT_4] = {0, 4, 0, 4};
 424
 425        /* lane_num value is used as array index, so this range 0 ~ 3 */
 426        dpcd_addr = DPCD_ADJUST_REQUEST_LANE0_1 + (lane_num / 2);
 427
 428        ret = exynos_dp_read_byte_from_dpcd(regs, dpcd_addr, &buf);
 429        if (ret != EXYNOS_DP_SUCCESS) {
 430                printf("DP read adjust request failed\n");
 431                return -EAGAIN;
 432        }
 433
 434        *sw = ((buf >> shift_val[lane_num]) & 0x03);
 435        *em = ((buf >> shift_val[lane_num]) & 0x0c) >> 2;
 436
 437        return ret;
 438}
 439
 440static int exynos_dp_equalizer_err_link(struct exynos_dp *regs,
 441                                        struct exynos_dp_priv *priv)
 442{
 443        int ret;
 444
 445        ret = exynos_dp_training_pattern_dis(regs);
 446        if (ret != EXYNOS_DP_SUCCESS) {
 447                printf("DP training_pattern_disable() failed\n");
 448                priv->lt_info.lt_status = DP_LT_FAIL;
 449        }
 450
 451        ret = exynos_dp_set_enhanced_mode(regs, priv->dpcd_efc);
 452        if (ret != EXYNOS_DP_SUCCESS) {
 453                printf("DP set_enhanced_mode() failed\n");
 454                priv->lt_info.lt_status = DP_LT_FAIL;
 455        }
 456
 457        return ret;
 458}
 459
 460static int exynos_dp_reduce_link_rate(struct exynos_dp *regs,
 461                                      struct exynos_dp_priv *priv)
 462{
 463        int ret;
 464
 465        if (priv->lane_bw == DP_LANE_BW_2_70) {
 466                priv->lane_bw = DP_LANE_BW_1_62;
 467                printf("DP Change lane bw to 1.62Gbps\n");
 468                priv->lt_info.lt_status = DP_LT_START;
 469                ret = EXYNOS_DP_SUCCESS;
 470        } else {
 471                ret = exynos_dp_training_pattern_dis(regs);
 472                if (ret != EXYNOS_DP_SUCCESS)
 473                        printf("DP training_patter_disable() failed\n");
 474
 475                ret = exynos_dp_set_enhanced_mode(regs, priv->dpcd_efc);
 476                if (ret != EXYNOS_DP_SUCCESS)
 477                        printf("DP set_enhanced_mode() failed\n");
 478
 479                priv->lt_info.lt_status = DP_LT_FAIL;
 480        }
 481
 482        return ret;
 483}
 484
 485static unsigned int exynos_dp_process_clock_recovery(struct exynos_dp *regs,
 486                                        struct exynos_dp_priv *priv)
 487{
 488        unsigned int ret;
 489        unsigned char lane_stat;
 490        unsigned char lt_ctl_val[DP_LANE_CNT_4] = {0, };
 491        unsigned int i;
 492        unsigned char adj_req_sw;
 493        unsigned char adj_req_em;
 494        unsigned char buf[5];
 495
 496        debug("DP: %s was called\n", __func__);
 497        mdelay(1);
 498
 499        ret = exynos_dp_read_dpcd_lane_stat(regs, priv, &lane_stat);
 500        if (ret != EXYNOS_DP_SUCCESS) {
 501                        printf("DP read lane status failed\n");
 502                        priv->lt_info.lt_status = DP_LT_FAIL;
 503                        return ret;
 504        }
 505
 506        if (lane_stat & DP_LANE_STAT_CR_DONE) {
 507                debug("DP clock Recovery training succeed\n");
 508                exynos_dp_set_training_pattern(regs, TRAINING_PTN2);
 509
 510                for (i = 0; i < priv->lane_cnt; i++) {
 511                        ret = exynos_dp_read_dpcd_adj_req(regs, i,
 512                                                &adj_req_sw, &adj_req_em);
 513                        if (ret != EXYNOS_DP_SUCCESS) {
 514                                priv->lt_info.lt_status = DP_LT_FAIL;
 515                                return ret;
 516                        }
 517
 518                        lt_ctl_val[i] = 0;
 519                        lt_ctl_val[i] = adj_req_em << 3 | adj_req_sw;
 520
 521                        if ((adj_req_sw == VOLTAGE_LEVEL_3)
 522                                || (adj_req_em == PRE_EMPHASIS_LEVEL_3)) {
 523                                lt_ctl_val[i] |= MAX_DRIVE_CURRENT_REACH_3 |
 524                                        MAX_PRE_EMPHASIS_REACH_3;
 525                        }
 526                        exynos_dp_set_lanex_pre_emphasis(regs,
 527                                                         lt_ctl_val[i], i);
 528                }
 529
 530                buf[0] =  DPCD_SCRAMBLING_DISABLED | DPCD_TRAINING_PATTERN_2;
 531                buf[1] = lt_ctl_val[0];
 532                buf[2] = lt_ctl_val[1];
 533                buf[3] = lt_ctl_val[2];
 534                buf[4] = lt_ctl_val[3];
 535
 536                ret = exynos_dp_write_bytes_to_dpcd(regs,
 537                                DPCD_TRAINING_PATTERN_SET, 5, buf);
 538                if (ret != EXYNOS_DP_SUCCESS) {
 539                        printf("DP write training pattern1 failed\n");
 540                        priv->lt_info.lt_status = DP_LT_FAIL;
 541                        return ret;
 542                } else
 543                        priv->lt_info.lt_status = DP_LT_ET;
 544        } else {
 545                for (i = 0; i < priv->lane_cnt; i++) {
 546                        lt_ctl_val[i] = exynos_dp_get_lanex_pre_emphasis(
 547                                                regs, i);
 548                                ret = exynos_dp_read_dpcd_adj_req(regs, i,
 549                                                &adj_req_sw, &adj_req_em);
 550                        if (ret != EXYNOS_DP_SUCCESS) {
 551                                printf("DP read adj req failed\n");
 552                                priv->lt_info.lt_status = DP_LT_FAIL;
 553                                return ret;
 554                        }
 555
 556                        if ((adj_req_sw == VOLTAGE_LEVEL_3) ||
 557                                        (adj_req_em == PRE_EMPHASIS_LEVEL_3))
 558                                ret = exynos_dp_reduce_link_rate(regs,
 559                                                                 priv);
 560
 561                        if ((DRIVE_CURRENT_SET_0_GET(lt_ctl_val[i]) ==
 562                                                adj_req_sw) &&
 563                                (PRE_EMPHASIS_SET_0_GET(lt_ctl_val[i]) ==
 564                                                adj_req_em)) {
 565                                priv->lt_info.cr_loop[i]++;
 566                                if (priv->lt_info.cr_loop[i] == MAX_CR_LOOP)
 567                                        ret = exynos_dp_reduce_link_rate(
 568                                                        regs, priv);
 569                        }
 570
 571                        lt_ctl_val[i] = 0;
 572                        lt_ctl_val[i] = adj_req_em << 3 | adj_req_sw;
 573
 574                        if ((adj_req_sw == VOLTAGE_LEVEL_3) ||
 575                                        (adj_req_em == PRE_EMPHASIS_LEVEL_3)) {
 576                                lt_ctl_val[i] |= MAX_DRIVE_CURRENT_REACH_3 |
 577                                        MAX_PRE_EMPHASIS_REACH_3;
 578                        }
 579                        exynos_dp_set_lanex_pre_emphasis(regs,
 580                                                         lt_ctl_val[i], i);
 581                }
 582
 583                ret = exynos_dp_write_bytes_to_dpcd(regs,
 584                                DPCD_TRAINING_LANE0_SET, 4, lt_ctl_val);
 585                if (ret != EXYNOS_DP_SUCCESS) {
 586                        printf("DP write training pattern2 failed\n");
 587                        priv->lt_info.lt_status = DP_LT_FAIL;
 588                        return ret;
 589                }
 590        }
 591
 592        return ret;
 593}
 594
 595static unsigned int exynos_dp_process_equalizer_training(
 596                struct exynos_dp *regs, struct exynos_dp_priv *priv)
 597{
 598        unsigned int ret;
 599        unsigned char lane_stat, adj_req_sw, adj_req_em, i;
 600        unsigned char lt_ctl_val[DP_LANE_CNT_4] = {0,};
 601        unsigned char interlane_aligned = 0;
 602        unsigned char f_bw;
 603        unsigned char f_lane_cnt;
 604        unsigned char sink_stat;
 605
 606        mdelay(1);
 607
 608        ret = exynos_dp_read_dpcd_lane_stat(regs, priv, &lane_stat);
 609        if (ret != EXYNOS_DP_SUCCESS) {
 610                printf("DP read lane status failed\n");
 611                priv->lt_info.lt_status = DP_LT_FAIL;
 612                return ret;
 613        }
 614
 615        debug("DP lane stat : %x\n", lane_stat);
 616
 617        if (lane_stat & DP_LANE_STAT_CR_DONE) {
 618                ret = exynos_dp_read_byte_from_dpcd(regs,
 619                                                    DPCD_LN_ALIGN_UPDATED,
 620                                                    &sink_stat);
 621                if (ret != EXYNOS_DP_SUCCESS) {
 622                        priv->lt_info.lt_status = DP_LT_FAIL;
 623
 624                        return ret;
 625                }
 626
 627                interlane_aligned = (sink_stat & DPCD_INTERLANE_ALIGN_DONE);
 628
 629                for (i = 0; i < priv->lane_cnt; i++) {
 630                        ret = exynos_dp_read_dpcd_adj_req(regs, i,
 631                                        &adj_req_sw, &adj_req_em);
 632                        if (ret != EXYNOS_DP_SUCCESS) {
 633                                printf("DP read adj req 1 failed\n");
 634                                priv->lt_info.lt_status = DP_LT_FAIL;
 635
 636                                return ret;
 637                        }
 638
 639                        lt_ctl_val[i] = 0;
 640                        lt_ctl_val[i] = adj_req_em << 3 | adj_req_sw;
 641
 642                        if ((adj_req_sw == VOLTAGE_LEVEL_3) ||
 643                                (adj_req_em == PRE_EMPHASIS_LEVEL_3)) {
 644                                lt_ctl_val[i] |= MAX_DRIVE_CURRENT_REACH_3;
 645                                lt_ctl_val[i] |= MAX_PRE_EMPHASIS_REACH_3;
 646                        }
 647                }
 648
 649                if (((lane_stat&DP_LANE_STAT_CE_DONE) &&
 650                        (lane_stat&DP_LANE_STAT_SYM_LOCK))
 651                        && (interlane_aligned == DPCD_INTERLANE_ALIGN_DONE)) {
 652                        debug("DP Equalizer training succeed\n");
 653
 654                        f_bw = exynos_dp_get_link_bandwidth(regs);
 655                        f_lane_cnt = exynos_dp_get_lane_count(regs);
 656
 657                        debug("DP final BandWidth : %x\n", f_bw);
 658                        debug("DP final Lane Count : %x\n", f_lane_cnt);
 659
 660                        priv->lt_info.lt_status = DP_LT_FINISHED;
 661
 662                        exynos_dp_equalizer_err_link(regs, priv);
 663
 664                } else {
 665                        priv->lt_info.ep_loop++;
 666
 667                        if (priv->lt_info.ep_loop > MAX_EQ_LOOP) {
 668                                if (priv->lane_bw == DP_LANE_BW_2_70) {
 669                                        ret = exynos_dp_reduce_link_rate(
 670                                                        regs, priv);
 671                                } else {
 672                                        priv->lt_info.lt_status =
 673                                                                DP_LT_FAIL;
 674                                        exynos_dp_equalizer_err_link(regs,
 675                                                                     priv);
 676                                }
 677                        } else {
 678                                for (i = 0; i < priv->lane_cnt; i++)
 679                                        exynos_dp_set_lanex_pre_emphasis(
 680                                                regs, lt_ctl_val[i], i);
 681
 682                                ret = exynos_dp_write_bytes_to_dpcd(regs,
 683                                                DPCD_TRAINING_LANE0_SET,
 684                                                4, lt_ctl_val);
 685                                if (ret != EXYNOS_DP_SUCCESS) {
 686                                        printf("DP set lt pattern failed\n");
 687                                        priv->lt_info.lt_status =
 688                                                                DP_LT_FAIL;
 689                                        exynos_dp_equalizer_err_link(regs,
 690                                                                     priv);
 691                                }
 692                        }
 693                }
 694        } else if (priv->lane_bw == DP_LANE_BW_2_70) {
 695                ret = exynos_dp_reduce_link_rate(regs, priv);
 696        } else {
 697                priv->lt_info.lt_status = DP_LT_FAIL;
 698                exynos_dp_equalizer_err_link(regs, priv);
 699        }
 700
 701        return ret;
 702}
 703
 704static unsigned int exynos_dp_sw_link_training(struct exynos_dp *regs,
 705                                               struct exynos_dp_priv *priv)
 706{
 707        unsigned int ret = 0;
 708        int training_finished;
 709
 710        /* Turn off unnecessary lane */
 711        if (priv->lane_cnt == 1)
 712                exynos_dp_set_analog_power_down(regs, CH1_BLOCK, 1);
 713
 714        training_finished = 0;
 715
 716        priv->lt_info.lt_status = DP_LT_START;
 717
 718        /* Process here */
 719        while (!training_finished) {
 720                switch (priv->lt_info.lt_status) {
 721                case DP_LT_START:
 722                        ret = exynos_dp_link_start(regs, priv);
 723                        if (ret != EXYNOS_DP_SUCCESS) {
 724                                printf("DP LT:link start failed\n");
 725                                return ret;
 726                        }
 727                        break;
 728                case DP_LT_CR:
 729                        ret = exynos_dp_process_clock_recovery(regs,
 730                                                               priv);
 731                        if (ret != EXYNOS_DP_SUCCESS) {
 732                                printf("DP LT:clock recovery failed\n");
 733                                return ret;
 734                        }
 735                        break;
 736                case DP_LT_ET:
 737                        ret = exynos_dp_process_equalizer_training(regs,
 738                                                                   priv);
 739                        if (ret != EXYNOS_DP_SUCCESS) {
 740                                printf("DP LT:equalizer training failed\n");
 741                                return ret;
 742                        }
 743                        break;
 744                case DP_LT_FINISHED:
 745                        training_finished = 1;
 746                        break;
 747                case DP_LT_FAIL:
 748                        return -1;
 749                }
 750        }
 751
 752        return ret;
 753}
 754
 755static unsigned int exynos_dp_set_link_train(struct exynos_dp *regs,
 756                                             struct exynos_dp_priv *priv)
 757{
 758        unsigned int ret;
 759
 760        exynos_dp_init_training(regs);
 761
 762        ret = exynos_dp_sw_link_training(regs, priv);
 763        if (ret != EXYNOS_DP_SUCCESS)
 764                printf("DP dp_sw_link_training() failed\n");
 765
 766        return ret;
 767}
 768
 769static void exynos_dp_enable_scramble(struct exynos_dp *regs,
 770                                      unsigned int enable)
 771{
 772        unsigned char data;
 773
 774        if (enable) {
 775                exynos_dp_enable_scrambling(regs, DP_ENABLE);
 776
 777                exynos_dp_read_byte_from_dpcd(regs,
 778                                              DPCD_TRAINING_PATTERN_SET, &data);
 779                exynos_dp_write_byte_to_dpcd(regs, DPCD_TRAINING_PATTERN_SET,
 780                        (u8)(data & ~DPCD_SCRAMBLING_DISABLED));
 781        } else {
 782                exynos_dp_enable_scrambling(regs, DP_DISABLE);
 783                exynos_dp_read_byte_from_dpcd(regs,
 784                                              DPCD_TRAINING_PATTERN_SET, &data);
 785                exynos_dp_write_byte_to_dpcd(regs, DPCD_TRAINING_PATTERN_SET,
 786                        (u8)(data | DPCD_SCRAMBLING_DISABLED));
 787        }
 788}
 789
 790static unsigned int exynos_dp_config_video(struct exynos_dp *regs,
 791                                           struct exynos_dp_priv *priv)
 792{
 793        unsigned int ret = 0;
 794        unsigned int retry_cnt;
 795
 796        mdelay(1);
 797
 798        if (priv->video_info.master_mode) {
 799                printf("DP does not support master mode\n");
 800                return -ENODEV;
 801        } else {
 802                /* debug slave */
 803                exynos_dp_config_video_slave_mode(regs,
 804                                                  &priv->video_info);
 805        }
 806
 807        exynos_dp_set_video_color_format(regs, &priv->video_info);
 808
 809        if (priv->video_info.bist_mode) {
 810                if (exynos_dp_config_video_bist(regs, priv) != 0)
 811                        return -1;
 812        }
 813
 814        ret = exynos_dp_get_pll_lock_status(regs);
 815        if (ret != PLL_LOCKED) {
 816                printf("DP PLL is not locked yet\n");
 817                return -EIO;
 818        }
 819
 820        if (priv->video_info.master_mode == 0) {
 821                retry_cnt = 10;
 822                while (retry_cnt) {
 823                        ret = exynos_dp_is_slave_video_stream_clock_on(regs);
 824                        if (ret != EXYNOS_DP_SUCCESS) {
 825                                if (retry_cnt == 0) {
 826                                        printf("DP stream_clock_on failed\n");
 827                                        return ret;
 828                                }
 829                                retry_cnt--;
 830                                mdelay(1);
 831                        } else
 832                                break;
 833                }
 834        }
 835
 836        /* Set to use the register calculated M/N video */
 837        exynos_dp_set_video_cr_mn(regs, CALCULATED_M, 0, 0);
 838
 839        /* For video bist, Video timing must be generated by register */
 840        exynos_dp_set_video_timing_mode(regs, VIDEO_TIMING_FROM_CAPTURE);
 841
 842        /* Enable video bist */
 843        if (priv->video_info.bist_pattern != COLOR_RAMP &&
 844                priv->video_info.bist_pattern != BALCK_WHITE_V_LINES &&
 845                priv->video_info.bist_pattern != COLOR_SQUARE)
 846                exynos_dp_enable_video_bist(regs,
 847                                            priv->video_info.bist_mode);
 848        else
 849                exynos_dp_enable_video_bist(regs, DP_DISABLE);
 850
 851        /* Disable video mute */
 852        exynos_dp_enable_video_mute(regs, DP_DISABLE);
 853
 854        /* Configure video Master or Slave mode */
 855        exynos_dp_enable_video_master(regs,
 856                                      priv->video_info.master_mode);
 857
 858        /* Enable video */
 859        exynos_dp_start_video(regs);
 860
 861        if (priv->video_info.master_mode == 0) {
 862                retry_cnt = 100;
 863                while (retry_cnt) {
 864                        ret = exynos_dp_is_video_stream_on(regs);
 865                        if (ret != EXYNOS_DP_SUCCESS) {
 866                                if (retry_cnt == 0) {
 867                                        printf("DP Timeout of video stream\n");
 868                                        return ret;
 869                                }
 870                                retry_cnt--;
 871                                mdelay(5);
 872                        } else
 873                                break;
 874                }
 875        }
 876
 877        return ret;
 878}
 879
 880static int exynos_dp_ofdata_to_platdata(struct udevice *dev)
 881{
 882        struct exynos_dp_priv *priv = dev_get_priv(dev);
 883        const void *blob = gd->fdt_blob;
 884        unsigned int node = dev_of_offset(dev);
 885        fdt_addr_t addr;
 886
 887        addr = dev_read_addr(dev);
 888        if (addr == FDT_ADDR_T_NONE) {
 889                debug("Can't get the DP base address\n");
 890                return -EINVAL;
 891        }
 892        priv->regs = (struct exynos_dp *)addr;
 893        priv->disp_info.h_res = fdtdec_get_int(blob, node,
 894                                                        "samsung,h-res", 0);
 895        priv->disp_info.h_sync_width = fdtdec_get_int(blob, node,
 896                                                "samsung,h-sync-width", 0);
 897        priv->disp_info.h_back_porch = fdtdec_get_int(blob, node,
 898                                                "samsung,h-back-porch", 0);
 899        priv->disp_info.h_front_porch = fdtdec_get_int(blob, node,
 900                                                "samsung,h-front-porch", 0);
 901        priv->disp_info.v_res = fdtdec_get_int(blob, node,
 902                                                "samsung,v-res", 0);
 903        priv->disp_info.v_sync_width = fdtdec_get_int(blob, node,
 904                                                "samsung,v-sync-width", 0);
 905        priv->disp_info.v_back_porch = fdtdec_get_int(blob, node,
 906                                                "samsung,v-back-porch", 0);
 907        priv->disp_info.v_front_porch = fdtdec_get_int(blob, node,
 908                                                "samsung,v-front-porch", 0);
 909        priv->disp_info.v_sync_rate = fdtdec_get_int(blob, node,
 910                                                "samsung,v-sync-rate", 0);
 911
 912        priv->lt_info.lt_status = fdtdec_get_int(blob, node,
 913                                                "samsung,lt-status", 0);
 914
 915        priv->video_info.master_mode = fdtdec_get_int(blob, node,
 916                                                "samsung,master-mode", 0);
 917        priv->video_info.bist_mode = fdtdec_get_int(blob, node,
 918                                                "samsung,bist-mode", 0);
 919        priv->video_info.bist_pattern = fdtdec_get_int(blob, node,
 920                                                "samsung,bist-pattern", 0);
 921        priv->video_info.h_sync_polarity = fdtdec_get_int(blob, node,
 922                                                "samsung,h-sync-polarity", 0);
 923        priv->video_info.v_sync_polarity = fdtdec_get_int(blob, node,
 924                                                "samsung,v-sync-polarity", 0);
 925        priv->video_info.interlaced = fdtdec_get_int(blob, node,
 926                                                "samsung,interlaced", 0);
 927        priv->video_info.color_space = fdtdec_get_int(blob, node,
 928                                                "samsung,color-space", 0);
 929        priv->video_info.dynamic_range = fdtdec_get_int(blob, node,
 930                                                "samsung,dynamic-range", 0);
 931        priv->video_info.ycbcr_coeff = fdtdec_get_int(blob, node,
 932                                                "samsung,ycbcr-coeff", 0);
 933        priv->video_info.color_depth = fdtdec_get_int(blob, node,
 934                                                "samsung,color-depth", 0);
 935        return 0;
 936}
 937
 938static int exynos_dp_bridge_init(struct udevice *dev)
 939{
 940        const int max_tries = 10;
 941        int num_tries;
 942        int ret;
 943
 944        debug("%s\n", __func__);
 945        ret = video_bridge_attach(dev);
 946        if (ret) {
 947                debug("video bridge init failed: %d\n", ret);
 948                return ret;
 949        }
 950
 951        /*
 952         * We need to wait for 90ms after bringing up the bridge since there
 953         * is a phantom "high" on the HPD chip during its bootup.  The phantom
 954         * high comes within 7ms of de-asserting PD and persists for at least
 955         * 15ms.  The real high comes roughly 50ms after PD is de-asserted. The
 956         * phantom high makes it hard for us to know when the NXP chip is up.
 957         */
 958        mdelay(90);
 959
 960        for (num_tries = 0; num_tries < max_tries; num_tries++) {
 961                /* Check HPD. If it's high, or we don't have it, all is well */
 962                ret = video_bridge_check_attached(dev);
 963                if (!ret || ret == -ENOENT)
 964                        return 0;
 965
 966                debug("%s: eDP bridge failed to come up; try %d of %d\n",
 967                      __func__, num_tries, max_tries);
 968        }
 969
 970        /* Immediately go into bridge reset if the hp line is not high */
 971        return -EIO;
 972}
 973
 974static int exynos_dp_bridge_setup(const void *blob)
 975{
 976        const int max_tries = 2;
 977        int num_tries;
 978        struct udevice *dev;
 979        int ret;
 980
 981        /* Configure I2C registers for Parade bridge */
 982        ret = uclass_get_device(UCLASS_VIDEO_BRIDGE, 0, &dev);
 983        if (ret) {
 984                debug("video bridge init failed: %d\n", ret);
 985                return ret;
 986        }
 987
 988        if (strncmp(dev->driver->name, "parade", 6)) {
 989                /* Mux HPHPD to the special hotplug detect mode */
 990                exynos_pinmux_config(PERIPH_ID_DPHPD, 0);
 991        }
 992
 993        for (num_tries = 0; num_tries < max_tries; num_tries++) {
 994                ret = exynos_dp_bridge_init(dev);
 995                if (!ret)
 996                        return 0;
 997                if (num_tries == max_tries - 1)
 998                        break;
 999
1000                /*
1001                * If we're here, the bridge chip failed to initialise.
1002                * Power down the bridge in an attempt to reset.
1003                */
1004                video_bridge_set_active(dev, false);
1005
1006                /*
1007                * Arbitrarily wait 300ms here with DP_N low.  Don't know for
1008                * sure how long we should wait, but we're being paranoid.
1009                */
1010                mdelay(300);
1011        }
1012
1013        return ret;
1014}
1015int exynos_dp_enable(struct udevice *dev, int panel_bpp,
1016                     const struct display_timing *timing)
1017{
1018        struct exynos_dp_priv *priv = dev_get_priv(dev);
1019        struct exynos_dp *regs = priv->regs;
1020        unsigned int ret;
1021
1022        debug("%s: start\n", __func__);
1023        exynos_dp_disp_info(&priv->disp_info);
1024
1025        ret = exynos_dp_bridge_setup(gd->fdt_blob);
1026        if (ret && ret != -ENODEV)
1027                printf("LCD bridge failed to enable: %d\n", ret);
1028
1029        exynos_dp_phy_ctrl(1);
1030
1031        ret = exynos_dp_init_dp(regs);
1032        if (ret != EXYNOS_DP_SUCCESS) {
1033                printf("DP exynos_dp_init_dp() failed\n");
1034                return ret;
1035        }
1036
1037        ret = exynos_dp_handle_edid(regs, priv);
1038        if (ret != EXYNOS_DP_SUCCESS) {
1039                printf("EDP handle_edid fail\n");
1040                return ret;
1041        }
1042
1043        ret = exynos_dp_set_link_train(regs, priv);
1044        if (ret != EXYNOS_DP_SUCCESS) {
1045                printf("DP link training fail\n");
1046                return ret;
1047        }
1048
1049        exynos_dp_enable_scramble(regs, DP_ENABLE);
1050        exynos_dp_enable_rx_to_enhanced_mode(regs, DP_ENABLE);
1051        exynos_dp_enable_enhanced_mode(regs, DP_ENABLE);
1052
1053        exynos_dp_set_link_bandwidth(regs, priv->lane_bw);
1054        exynos_dp_set_lane_count(regs, priv->lane_cnt);
1055
1056        exynos_dp_init_video(regs);
1057        ret = exynos_dp_config_video(regs, priv);
1058        if (ret != EXYNOS_DP_SUCCESS) {
1059                printf("Exynos DP init failed\n");
1060                return ret;
1061        }
1062
1063        debug("Exynos DP init done\n");
1064
1065        return ret;
1066}
1067
1068
1069static const struct dm_display_ops exynos_dp_ops = {
1070        .enable = exynos_dp_enable,
1071};
1072
1073static const struct udevice_id exynos_dp_ids[] = {
1074        { .compatible = "samsung,exynos5-dp" },
1075        { }
1076};
1077
1078U_BOOT_DRIVER(exynos_dp) = {
1079        .name   = "exynos_dp",
1080        .id     = UCLASS_DISPLAY,
1081        .of_match = exynos_dp_ids,
1082        .ops    = &exynos_dp_ops,
1083        .ofdata_to_platdata     = exynos_dp_ofdata_to_platdata,
1084        .priv_auto_alloc_size   = sizeof(struct exynos_dp_priv),
1085};
1086