linux/drivers/gpu/drm/msm/dp/dp_ctrl.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved.
   4 */
   5
   6#define pr_fmt(fmt)     "[drm-dp] %s: " fmt, __func__
   7
   8#include <linux/types.h>
   9#include <linux/completion.h>
  10#include <linux/delay.h>
  11#include <linux/phy/phy.h>
  12#include <linux/phy/phy-dp.h>
  13#include <drm/drm_fixed.h>
  14#include <drm/drm_dp_helper.h>
  15#include <drm/drm_print.h>
  16
  17#include "dp_reg.h"
  18#include "dp_ctrl.h"
  19#include "dp_link.h"
  20
  21#define DP_KHZ_TO_HZ 1000
  22#define IDLE_PATTERN_COMPLETION_TIMEOUT_JIFFIES (30 * HZ / 1000) /* 30 ms */
  23#define WAIT_FOR_VIDEO_READY_TIMEOUT_JIFFIES (HZ / 2)
  24
  25#define DP_CTRL_INTR_READY_FOR_VIDEO     BIT(0)
  26#define DP_CTRL_INTR_IDLE_PATTERN_SENT  BIT(3)
  27
  28#define MR_LINK_TRAINING1  0x8
  29#define MR_LINK_SYMBOL_ERM 0x80
  30#define MR_LINK_PRBS7 0x100
  31#define MR_LINK_CUSTOM80 0x200
  32#define MR_LINK_TRAINING4  0x40
  33
  34enum {
  35        DP_TRAINING_NONE,
  36        DP_TRAINING_1,
  37        DP_TRAINING_2,
  38};
  39
  40struct dp_tu_calc_input {
  41        u64 lclk;        /* 162, 270, 540 and 810 */
  42        u64 pclk_khz;    /* in KHz */
  43        u64 hactive;     /* active h-width */
  44        u64 hporch;      /* bp + fp + pulse */
  45        int nlanes;      /* no.of.lanes */
  46        int bpp;         /* bits */
  47        int pixel_enc;   /* 444, 420, 422 */
  48        int dsc_en;     /* dsc on/off */
  49        int async_en;   /* async mode */
  50        int fec_en;     /* fec */
  51        int compress_ratio; /* 2:1 = 200, 3:1 = 300, 3.75:1 = 375 */
  52        int num_of_dsc_slices; /* number of slices per line */
  53};
  54
  55struct dp_vc_tu_mapping_table {
  56        u32 vic;
  57        u8 lanes;
  58        u8 lrate; /* DP_LINK_RATE -> 162(6), 270(10), 540(20), 810 (30) */
  59        u8 bpp;
  60        u8 valid_boundary_link;
  61        u16 delay_start_link;
  62        bool boundary_moderation_en;
  63        u8 valid_lower_boundary_link;
  64        u8 upper_boundary_count;
  65        u8 lower_boundary_count;
  66        u8 tu_size_minus1;
  67};
  68
  69struct dp_ctrl_private {
  70        struct dp_ctrl dp_ctrl;
  71        struct device *dev;
  72        struct drm_dp_aux *aux;
  73        struct dp_panel *panel;
  74        struct dp_link *link;
  75        struct dp_power *power;
  76        struct dp_parser *parser;
  77        struct dp_catalog *catalog;
  78
  79        struct completion idle_comp;
  80        struct completion video_comp;
  81};
  82
  83struct dp_cr_status {
  84        u8 lane_0_1;
  85        u8 lane_2_3;
  86};
  87
  88#define DP_LANE0_1_CR_DONE      0x11
  89
  90static int dp_aux_link_configure(struct drm_dp_aux *aux,
  91                                        struct dp_link_info *link)
  92{
  93        u8 values[2];
  94        int err;
  95
  96        values[0] = drm_dp_link_rate_to_bw_code(link->rate);
  97        values[1] = link->num_lanes;
  98
  99        if (link->capabilities & DP_LINK_CAP_ENHANCED_FRAMING)
 100                values[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
 101
 102        err = drm_dp_dpcd_write(aux, DP_LINK_BW_SET, values, sizeof(values));
 103        if (err < 0)
 104                return err;
 105
 106        return 0;
 107}
 108
 109void dp_ctrl_push_idle(struct dp_ctrl *dp_ctrl)
 110{
 111        struct dp_ctrl_private *ctrl;
 112
 113        ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);
 114
 115        reinit_completion(&ctrl->idle_comp);
 116        dp_catalog_ctrl_state_ctrl(ctrl->catalog, DP_STATE_CTRL_PUSH_IDLE);
 117
 118        if (!wait_for_completion_timeout(&ctrl->idle_comp,
 119                        IDLE_PATTERN_COMPLETION_TIMEOUT_JIFFIES))
 120                pr_warn("PUSH_IDLE pattern timedout\n");
 121
 122        pr_debug("mainlink off done\n");
 123}
 124
 125static void dp_ctrl_config_ctrl(struct dp_ctrl_private *ctrl)
 126{
 127        u32 config = 0, tbd;
 128        u8 *dpcd = ctrl->panel->dpcd;
 129
 130        /* Default-> LSCLK DIV: 1/4 LCLK  */
 131        config |= (2 << DP_CONFIGURATION_CTRL_LSCLK_DIV_SHIFT);
 132
 133        /* Scrambler reset enable */
 134        if (dpcd[DP_EDP_CONFIGURATION_CAP] & DP_ALTERNATE_SCRAMBLER_RESET_CAP)
 135                config |= DP_CONFIGURATION_CTRL_ASSR;
 136
 137        tbd = dp_link_get_test_bits_depth(ctrl->link,
 138                        ctrl->panel->dp_mode.bpp);
 139
 140        if (tbd == DP_TEST_BIT_DEPTH_UNKNOWN) {
 141                pr_debug("BIT_DEPTH not set. Configure default\n");
 142                tbd = DP_TEST_BIT_DEPTH_8;
 143        }
 144
 145        config |= tbd << DP_CONFIGURATION_CTRL_BPC_SHIFT;
 146
 147        /* Num of Lanes */
 148        config |= ((ctrl->link->link_params.num_lanes - 1)
 149                        << DP_CONFIGURATION_CTRL_NUM_OF_LANES_SHIFT);
 150
 151        if (drm_dp_enhanced_frame_cap(dpcd))
 152                config |= DP_CONFIGURATION_CTRL_ENHANCED_FRAMING;
 153
 154        config |= DP_CONFIGURATION_CTRL_P_INTERLACED; /* progressive video */
 155
 156        /* sync clock & static Mvid */
 157        config |= DP_CONFIGURATION_CTRL_STATIC_DYNAMIC_CN;
 158        config |= DP_CONFIGURATION_CTRL_SYNC_ASYNC_CLK;
 159
 160        dp_catalog_ctrl_config_ctrl(ctrl->catalog, config);
 161}
 162
 163static void dp_ctrl_configure_source_params(struct dp_ctrl_private *ctrl)
 164{
 165        u32 cc, tb;
 166
 167        dp_catalog_ctrl_lane_mapping(ctrl->catalog);
 168        dp_catalog_ctrl_mainlink_ctrl(ctrl->catalog, true);
 169
 170        dp_ctrl_config_ctrl(ctrl);
 171
 172        tb = dp_link_get_test_bits_depth(ctrl->link,
 173                ctrl->panel->dp_mode.bpp);
 174        cc = dp_link_get_colorimetry_config(ctrl->link);
 175        dp_catalog_ctrl_config_misc(ctrl->catalog, cc, tb);
 176        dp_panel_timing_cfg(ctrl->panel);
 177}
 178
 179/*
 180 * The structure and few functions present below are IP/Hardware
 181 * specific implementation. Most of the implementation will not
 182 * have coding comments
 183 */
 184struct tu_algo_data {
 185        s64 lclk_fp;
 186        s64 pclk_fp;
 187        s64 lwidth;
 188        s64 lwidth_fp;
 189        s64 hbp_relative_to_pclk;
 190        s64 hbp_relative_to_pclk_fp;
 191        int nlanes;
 192        int bpp;
 193        int pixelEnc;
 194        int dsc_en;
 195        int async_en;
 196        int bpc;
 197
 198        uint delay_start_link_extra_pixclk;
 199        int extra_buffer_margin;
 200        s64 ratio_fp;
 201        s64 original_ratio_fp;
 202
 203        s64 err_fp;
 204        s64 n_err_fp;
 205        s64 n_n_err_fp;
 206        int tu_size;
 207        int tu_size_desired;
 208        int tu_size_minus1;
 209
 210        int valid_boundary_link;
 211        s64 resulting_valid_fp;
 212        s64 total_valid_fp;
 213        s64 effective_valid_fp;
 214        s64 effective_valid_recorded_fp;
 215        int n_tus;
 216        int n_tus_per_lane;
 217        int paired_tus;
 218        int remainder_tus;
 219        int remainder_tus_upper;
 220        int remainder_tus_lower;
 221        int extra_bytes;
 222        int filler_size;
 223        int delay_start_link;
 224
 225        int extra_pclk_cycles;
 226        int extra_pclk_cycles_in_link_clk;
 227        s64 ratio_by_tu_fp;
 228        s64 average_valid2_fp;
 229        int new_valid_boundary_link;
 230        int remainder_symbols_exist;
 231        int n_symbols;
 232        s64 n_remainder_symbols_per_lane_fp;
 233        s64 last_partial_tu_fp;
 234        s64 TU_ratio_err_fp;
 235
 236        int n_tus_incl_last_incomplete_tu;
 237        int extra_pclk_cycles_tmp;
 238        int extra_pclk_cycles_in_link_clk_tmp;
 239        int extra_required_bytes_new_tmp;
 240        int filler_size_tmp;
 241        int lower_filler_size_tmp;
 242        int delay_start_link_tmp;
 243
 244        bool boundary_moderation_en;
 245        int boundary_mod_lower_err;
 246        int upper_boundary_count;
 247        int lower_boundary_count;
 248        int i_upper_boundary_count;
 249        int i_lower_boundary_count;
 250        int valid_lower_boundary_link;
 251        int even_distribution_BF;
 252        int even_distribution_legacy;
 253        int even_distribution;
 254        int min_hblank_violated;
 255        s64 delay_start_time_fp;
 256        s64 hbp_time_fp;
 257        s64 hactive_time_fp;
 258        s64 diff_abs_fp;
 259
 260        s64 ratio;
 261};
 262
 263static int _tu_param_compare(s64 a, s64 b)
 264{
 265        u32 a_sign;
 266        u32 b_sign;
 267        s64 a_temp, b_temp, minus_1;
 268
 269        if (a == b)
 270                return 0;
 271
 272        minus_1 = drm_fixp_from_fraction(-1, 1);
 273
 274        a_sign = (a >> 32) & 0x80000000 ? 1 : 0;
 275
 276        b_sign = (b >> 32) & 0x80000000 ? 1 : 0;
 277
 278        if (a_sign > b_sign)
 279                return 2;
 280        else if (b_sign > a_sign)
 281                return 1;
 282
 283        if (!a_sign && !b_sign) { /* positive */
 284                if (a > b)
 285                        return 1;
 286                else
 287                        return 2;
 288        } else { /* negative */
 289                a_temp = drm_fixp_mul(a, minus_1);
 290                b_temp = drm_fixp_mul(b, minus_1);
 291
 292                if (a_temp > b_temp)
 293                        return 2;
 294                else
 295                        return 1;
 296        }
 297}
 298
 299static void dp_panel_update_tu_timings(struct dp_tu_calc_input *in,
 300                                        struct tu_algo_data *tu)
 301{
 302        int nlanes = in->nlanes;
 303        int dsc_num_slices = in->num_of_dsc_slices;
 304        int dsc_num_bytes  = 0;
 305        int numerator;
 306        s64 pclk_dsc_fp;
 307        s64 dwidth_dsc_fp;
 308        s64 hbp_dsc_fp;
 309
 310        int tot_num_eoc_symbols = 0;
 311        int tot_num_hor_bytes   = 0;
 312        int tot_num_dummy_bytes = 0;
 313        int dwidth_dsc_bytes    = 0;
 314        int  eoc_bytes           = 0;
 315
 316        s64 temp1_fp, temp2_fp, temp3_fp;
 317
 318        tu->lclk_fp              = drm_fixp_from_fraction(in->lclk, 1);
 319        tu->pclk_fp              = drm_fixp_from_fraction(in->pclk_khz, 1000);
 320        tu->lwidth               = in->hactive;
 321        tu->hbp_relative_to_pclk = in->hporch;
 322        tu->nlanes               = in->nlanes;
 323        tu->bpp                  = in->bpp;
 324        tu->pixelEnc             = in->pixel_enc;
 325        tu->dsc_en               = in->dsc_en;
 326        tu->async_en             = in->async_en;
 327        tu->lwidth_fp            = drm_fixp_from_fraction(in->hactive, 1);
 328        tu->hbp_relative_to_pclk_fp = drm_fixp_from_fraction(in->hporch, 1);
 329
 330        if (tu->pixelEnc == 420) {
 331                temp1_fp = drm_fixp_from_fraction(2, 1);
 332                tu->pclk_fp = drm_fixp_div(tu->pclk_fp, temp1_fp);
 333                tu->lwidth_fp = drm_fixp_div(tu->lwidth_fp, temp1_fp);
 334                tu->hbp_relative_to_pclk_fp =
 335                                drm_fixp_div(tu->hbp_relative_to_pclk_fp, 2);
 336        }
 337
 338        if (tu->pixelEnc == 422) {
 339                switch (tu->bpp) {
 340                case 24:
 341                        tu->bpp = 16;
 342                        tu->bpc = 8;
 343                        break;
 344                case 30:
 345                        tu->bpp = 20;
 346                        tu->bpc = 10;
 347                        break;
 348                default:
 349                        tu->bpp = 16;
 350                        tu->bpc = 8;
 351                        break;
 352                }
 353        } else {
 354                tu->bpc = tu->bpp/3;
 355        }
 356
 357        if (!in->dsc_en)
 358                goto fec_check;
 359
 360        temp1_fp = drm_fixp_from_fraction(in->compress_ratio, 100);
 361        temp2_fp = drm_fixp_from_fraction(in->bpp, 1);
 362        temp3_fp = drm_fixp_div(temp2_fp, temp1_fp);
 363        temp2_fp = drm_fixp_mul(tu->lwidth_fp, temp3_fp);
 364
 365        temp1_fp = drm_fixp_from_fraction(8, 1);
 366        temp3_fp = drm_fixp_div(temp2_fp, temp1_fp);
 367
 368        numerator = drm_fixp2int(temp3_fp);
 369
 370        dsc_num_bytes  = numerator / dsc_num_slices;
 371        eoc_bytes           = dsc_num_bytes % nlanes;
 372        tot_num_eoc_symbols = nlanes * dsc_num_slices;
 373        tot_num_hor_bytes   = dsc_num_bytes * dsc_num_slices;
 374        tot_num_dummy_bytes = (nlanes - eoc_bytes) * dsc_num_slices;
 375
 376        if (dsc_num_bytes == 0)
 377                pr_info("incorrect no of bytes per slice=%d\n", dsc_num_bytes);
 378
 379        dwidth_dsc_bytes = (tot_num_hor_bytes +
 380                                tot_num_eoc_symbols +
 381                                (eoc_bytes == 0 ? 0 : tot_num_dummy_bytes));
 382
 383        dwidth_dsc_fp = drm_fixp_from_fraction(dwidth_dsc_bytes, 3);
 384
 385        temp2_fp = drm_fixp_mul(tu->pclk_fp, dwidth_dsc_fp);
 386        temp1_fp = drm_fixp_div(temp2_fp, tu->lwidth_fp);
 387        pclk_dsc_fp = temp1_fp;
 388
 389        temp1_fp = drm_fixp_div(pclk_dsc_fp, tu->pclk_fp);
 390        temp2_fp = drm_fixp_mul(tu->hbp_relative_to_pclk_fp, temp1_fp);
 391        hbp_dsc_fp = temp2_fp;
 392
 393        /* output */
 394        tu->pclk_fp = pclk_dsc_fp;
 395        tu->lwidth_fp = dwidth_dsc_fp;
 396        tu->hbp_relative_to_pclk_fp = hbp_dsc_fp;
 397
 398fec_check:
 399        if (in->fec_en) {
 400                temp1_fp = drm_fixp_from_fraction(976, 1000); /* 0.976 */
 401                tu->lclk_fp = drm_fixp_mul(tu->lclk_fp, temp1_fp);
 402        }
 403}
 404
 405static void _tu_valid_boundary_calc(struct tu_algo_data *tu)
 406{
 407        s64 temp1_fp, temp2_fp, temp, temp1, temp2;
 408        int compare_result_1, compare_result_2, compare_result_3;
 409
 410        temp1_fp = drm_fixp_from_fraction(tu->tu_size, 1);
 411        temp2_fp = drm_fixp_mul(tu->ratio_fp, temp1_fp);
 412
 413        tu->new_valid_boundary_link = drm_fixp2int_ceil(temp2_fp);
 414
 415        temp = (tu->i_upper_boundary_count *
 416                                tu->new_valid_boundary_link +
 417                                tu->i_lower_boundary_count *
 418                                (tu->new_valid_boundary_link-1));
 419        tu->average_valid2_fp = drm_fixp_from_fraction(temp,
 420                                        (tu->i_upper_boundary_count +
 421                                        tu->i_lower_boundary_count));
 422
 423        temp1_fp = drm_fixp_from_fraction(tu->bpp, 8);
 424        temp2_fp = tu->lwidth_fp;
 425        temp1_fp = drm_fixp_mul(temp2_fp, temp1_fp);
 426        temp2_fp = drm_fixp_div(temp1_fp, tu->average_valid2_fp);
 427        tu->n_tus = drm_fixp2int(temp2_fp);
 428        if ((temp2_fp & 0xFFFFFFFF) > 0xFFFFF000)
 429                tu->n_tus += 1;
 430
 431        temp1_fp = drm_fixp_from_fraction(tu->n_tus, 1);
 432        temp2_fp = drm_fixp_mul(temp1_fp, tu->average_valid2_fp);
 433        temp1_fp = drm_fixp_from_fraction(tu->n_symbols, 1);
 434        temp2_fp = temp1_fp - temp2_fp;
 435        temp1_fp = drm_fixp_from_fraction(tu->nlanes, 1);
 436        temp2_fp = drm_fixp_div(temp2_fp, temp1_fp);
 437        tu->n_remainder_symbols_per_lane_fp = temp2_fp;
 438
 439        temp1_fp = drm_fixp_from_fraction(tu->tu_size, 1);
 440        tu->last_partial_tu_fp =
 441                        drm_fixp_div(tu->n_remainder_symbols_per_lane_fp,
 442                                        temp1_fp);
 443
 444        if (tu->n_remainder_symbols_per_lane_fp != 0)
 445                tu->remainder_symbols_exist = 1;
 446        else
 447                tu->remainder_symbols_exist = 0;
 448
 449        temp1_fp = drm_fixp_from_fraction(tu->n_tus, tu->nlanes);
 450        tu->n_tus_per_lane = drm_fixp2int(temp1_fp);
 451
 452        tu->paired_tus = (int)((tu->n_tus_per_lane) /
 453                                        (tu->i_upper_boundary_count +
 454                                         tu->i_lower_boundary_count));
 455
 456        tu->remainder_tus = tu->n_tus_per_lane - tu->paired_tus *
 457                                                (tu->i_upper_boundary_count +
 458                                                tu->i_lower_boundary_count);
 459
 460        if ((tu->remainder_tus - tu->i_upper_boundary_count) > 0) {
 461                tu->remainder_tus_upper = tu->i_upper_boundary_count;
 462                tu->remainder_tus_lower = tu->remainder_tus -
 463                                                tu->i_upper_boundary_count;
 464        } else {
 465                tu->remainder_tus_upper = tu->remainder_tus;
 466                tu->remainder_tus_lower = 0;
 467        }
 468
 469        temp = tu->paired_tus * (tu->i_upper_boundary_count *
 470                                tu->new_valid_boundary_link +
 471                                tu->i_lower_boundary_count *
 472                                (tu->new_valid_boundary_link - 1)) +
 473                                (tu->remainder_tus_upper *
 474                                 tu->new_valid_boundary_link) +
 475                                (tu->remainder_tus_lower *
 476                                (tu->new_valid_boundary_link - 1));
 477        tu->total_valid_fp = drm_fixp_from_fraction(temp, 1);
 478
 479        if (tu->remainder_symbols_exist) {
 480                temp1_fp = tu->total_valid_fp +
 481                                tu->n_remainder_symbols_per_lane_fp;
 482                temp2_fp = drm_fixp_from_fraction(tu->n_tus_per_lane, 1);
 483                temp2_fp = temp2_fp + tu->last_partial_tu_fp;
 484                temp1_fp = drm_fixp_div(temp1_fp, temp2_fp);
 485        } else {
 486                temp2_fp = drm_fixp_from_fraction(tu->n_tus_per_lane, 1);
 487                temp1_fp = drm_fixp_div(tu->total_valid_fp, temp2_fp);
 488        }
 489        tu->effective_valid_fp = temp1_fp;
 490
 491        temp1_fp = drm_fixp_from_fraction(tu->tu_size, 1);
 492        temp2_fp = drm_fixp_mul(tu->ratio_fp, temp1_fp);
 493        tu->n_n_err_fp = tu->effective_valid_fp - temp2_fp;
 494
 495        temp1_fp = drm_fixp_from_fraction(tu->tu_size, 1);
 496        temp2_fp = drm_fixp_mul(tu->ratio_fp, temp1_fp);
 497        tu->n_err_fp = tu->average_valid2_fp - temp2_fp;
 498
 499        tu->even_distribution = tu->n_tus % tu->nlanes == 0 ? 1 : 0;
 500
 501        temp1_fp = drm_fixp_from_fraction(tu->bpp, 8);
 502        temp2_fp = tu->lwidth_fp;
 503        temp1_fp = drm_fixp_mul(temp2_fp, temp1_fp);
 504        temp2_fp = drm_fixp_div(temp1_fp, tu->average_valid2_fp);
 505
 506        if (temp2_fp)
 507                tu->n_tus_incl_last_incomplete_tu = drm_fixp2int_ceil(temp2_fp);
 508        else
 509                tu->n_tus_incl_last_incomplete_tu = 0;
 510
 511        temp1 = 0;
 512        temp1_fp = drm_fixp_from_fraction(tu->tu_size, 1);
 513        temp2_fp = drm_fixp_mul(tu->original_ratio_fp, temp1_fp);
 514        temp1_fp = tu->average_valid2_fp - temp2_fp;
 515        temp2_fp = drm_fixp_from_fraction(tu->n_tus_incl_last_incomplete_tu, 1);
 516        temp1_fp = drm_fixp_mul(temp2_fp, temp1_fp);
 517
 518        if (temp1_fp)
 519                temp1 = drm_fixp2int_ceil(temp1_fp);
 520
 521        temp = tu->i_upper_boundary_count * tu->nlanes;
 522        temp1_fp = drm_fixp_from_fraction(tu->tu_size, 1);
 523        temp2_fp = drm_fixp_mul(tu->original_ratio_fp, temp1_fp);
 524        temp1_fp = drm_fixp_from_fraction(tu->new_valid_boundary_link, 1);
 525        temp2_fp = temp1_fp - temp2_fp;
 526        temp1_fp = drm_fixp_from_fraction(temp, 1);
 527        temp2_fp = drm_fixp_mul(temp1_fp, temp2_fp);
 528
 529        if (temp2_fp)
 530                temp2 = drm_fixp2int_ceil(temp2_fp);
 531        else
 532                temp2 = 0;
 533        tu->extra_required_bytes_new_tmp = (int)(temp1 + temp2);
 534
 535        temp1_fp = drm_fixp_from_fraction(8, tu->bpp);
 536        temp2_fp = drm_fixp_from_fraction(
 537        tu->extra_required_bytes_new_tmp, 1);
 538        temp1_fp = drm_fixp_mul(temp2_fp, temp1_fp);
 539
 540        if (temp1_fp)
 541                tu->extra_pclk_cycles_tmp = drm_fixp2int_ceil(temp1_fp);
 542        else
 543                tu->extra_pclk_cycles_tmp = 0;
 544
 545        temp1_fp = drm_fixp_from_fraction(tu->extra_pclk_cycles_tmp, 1);
 546        temp2_fp = drm_fixp_div(tu->lclk_fp, tu->pclk_fp);
 547        temp1_fp = drm_fixp_mul(temp1_fp, temp2_fp);
 548
 549        if (temp1_fp)
 550                tu->extra_pclk_cycles_in_link_clk_tmp =
 551                                                drm_fixp2int_ceil(temp1_fp);
 552        else
 553                tu->extra_pclk_cycles_in_link_clk_tmp = 0;
 554
 555        tu->filler_size_tmp = tu->tu_size - tu->new_valid_boundary_link;
 556
 557        tu->lower_filler_size_tmp = tu->filler_size_tmp + 1;
 558
 559        tu->delay_start_link_tmp = tu->extra_pclk_cycles_in_link_clk_tmp +
 560                                        tu->lower_filler_size_tmp +
 561                                        tu->extra_buffer_margin;
 562
 563        temp1_fp = drm_fixp_from_fraction(tu->delay_start_link_tmp, 1);
 564        tu->delay_start_time_fp = drm_fixp_div(temp1_fp, tu->lclk_fp);
 565
 566        compare_result_1 = _tu_param_compare(tu->n_n_err_fp, tu->diff_abs_fp);
 567        if (compare_result_1 == 2)
 568                compare_result_1 = 1;
 569        else
 570                compare_result_1 = 0;
 571
 572        compare_result_2 = _tu_param_compare(tu->n_n_err_fp, tu->err_fp);
 573        if (compare_result_2 == 2)
 574                compare_result_2 = 1;
 575        else
 576                compare_result_2 = 0;
 577
 578        compare_result_3 = _tu_param_compare(tu->hbp_time_fp,
 579                                        tu->delay_start_time_fp);
 580        if (compare_result_3 == 2)
 581                compare_result_3 = 0;
 582        else
 583                compare_result_3 = 1;
 584
 585        if (((tu->even_distribution == 1) ||
 586                        ((tu->even_distribution_BF == 0) &&
 587                        (tu->even_distribution_legacy == 0))) &&
 588                        tu->n_err_fp >= 0 && tu->n_n_err_fp >= 0 &&
 589                        compare_result_2 &&
 590                        (compare_result_1 || (tu->min_hblank_violated == 1)) &&
 591                        (tu->new_valid_boundary_link - 1) > 0 &&
 592                        compare_result_3 &&
 593                        (tu->delay_start_link_tmp <= 1023)) {
 594                tu->upper_boundary_count = tu->i_upper_boundary_count;
 595                tu->lower_boundary_count = tu->i_lower_boundary_count;
 596                tu->err_fp = tu->n_n_err_fp;
 597                tu->boundary_moderation_en = true;
 598                tu->tu_size_desired = tu->tu_size;
 599                tu->valid_boundary_link = tu->new_valid_boundary_link;
 600                tu->effective_valid_recorded_fp = tu->effective_valid_fp;
 601                tu->even_distribution_BF = 1;
 602                tu->delay_start_link = tu->delay_start_link_tmp;
 603        } else if (tu->boundary_mod_lower_err == 0) {
 604                compare_result_1 = _tu_param_compare(tu->n_n_err_fp,
 605                                                        tu->diff_abs_fp);
 606                if (compare_result_1 == 2)
 607                        tu->boundary_mod_lower_err = 1;
 608        }
 609}
 610
 611static void _dp_ctrl_calc_tu(struct dp_tu_calc_input *in,
 612                                   struct dp_vc_tu_mapping_table *tu_table)
 613{
 614        struct tu_algo_data tu;
 615        int compare_result_1, compare_result_2;
 616        u64 temp = 0;
 617        s64 temp_fp = 0, temp1_fp = 0, temp2_fp = 0;
 618
 619        s64 LCLK_FAST_SKEW_fp = drm_fixp_from_fraction(6, 10000); /* 0.0006 */
 620        s64 const_p49_fp = drm_fixp_from_fraction(49, 100); /* 0.49 */
 621        s64 const_p56_fp = drm_fixp_from_fraction(56, 100); /* 0.56 */
 622        s64 RATIO_SCALE_fp = drm_fixp_from_fraction(1001, 1000);
 623
 624        u8 DP_BRUTE_FORCE = 1;
 625        s64 BRUTE_FORCE_THRESHOLD_fp = drm_fixp_from_fraction(1, 10); /* 0.1 */
 626        uint EXTRA_PIXCLK_CYCLE_DELAY = 4;
 627        uint HBLANK_MARGIN = 4;
 628
 629        memset(&tu, 0, sizeof(tu));
 630
 631        dp_panel_update_tu_timings(in, &tu);
 632
 633        tu.err_fp = drm_fixp_from_fraction(1000, 1); /* 1000 */
 634
 635        temp1_fp = drm_fixp_from_fraction(4, 1);
 636        temp2_fp = drm_fixp_mul(temp1_fp, tu.lclk_fp);
 637        temp_fp = drm_fixp_div(temp2_fp, tu.pclk_fp);
 638        tu.extra_buffer_margin = drm_fixp2int_ceil(temp_fp);
 639
 640        temp1_fp = drm_fixp_from_fraction(tu.bpp, 8);
 641        temp2_fp = drm_fixp_mul(tu.pclk_fp, temp1_fp);
 642        temp1_fp = drm_fixp_from_fraction(tu.nlanes, 1);
 643        temp2_fp = drm_fixp_div(temp2_fp, temp1_fp);
 644        tu.ratio_fp = drm_fixp_div(temp2_fp, tu.lclk_fp);
 645
 646        tu.original_ratio_fp = tu.ratio_fp;
 647        tu.boundary_moderation_en = false;
 648        tu.upper_boundary_count = 0;
 649        tu.lower_boundary_count = 0;
 650        tu.i_upper_boundary_count = 0;
 651        tu.i_lower_boundary_count = 0;
 652        tu.valid_lower_boundary_link = 0;
 653        tu.even_distribution_BF = 0;
 654        tu.even_distribution_legacy = 0;
 655        tu.even_distribution = 0;
 656        tu.delay_start_time_fp = 0;
 657
 658        tu.err_fp = drm_fixp_from_fraction(1000, 1);
 659        tu.n_err_fp = 0;
 660        tu.n_n_err_fp = 0;
 661
 662        tu.ratio = drm_fixp2int(tu.ratio_fp);
 663        temp1_fp = drm_fixp_from_fraction(tu.nlanes, 1);
 664        div64_u64_rem(tu.lwidth_fp, temp1_fp, &temp2_fp);
 665        if (temp2_fp != 0 &&
 666                        !tu.ratio && tu.dsc_en == 0) {
 667                tu.ratio_fp = drm_fixp_mul(tu.ratio_fp, RATIO_SCALE_fp);
 668                tu.ratio = drm_fixp2int(tu.ratio_fp);
 669                if (tu.ratio)
 670                        tu.ratio_fp = drm_fixp_from_fraction(1, 1);
 671        }
 672
 673        if (tu.ratio > 1)
 674                tu.ratio = 1;
 675
 676        if (tu.ratio == 1)
 677                goto tu_size_calc;
 678
 679        compare_result_1 = _tu_param_compare(tu.ratio_fp, const_p49_fp);
 680        if (!compare_result_1 || compare_result_1 == 1)
 681                compare_result_1 = 1;
 682        else
 683                compare_result_1 = 0;
 684
 685        compare_result_2 = _tu_param_compare(tu.ratio_fp, const_p56_fp);
 686        if (!compare_result_2 || compare_result_2 == 2)
 687                compare_result_2 = 1;
 688        else
 689                compare_result_2 = 0;
 690
 691        if (tu.dsc_en && compare_result_1 && compare_result_2) {
 692                HBLANK_MARGIN += 4;
 693                DRM_DEBUG_DP("Info: increase HBLANK_MARGIN to %d\n",
 694                                HBLANK_MARGIN);
 695        }
 696
 697tu_size_calc:
 698        for (tu.tu_size = 32; tu.tu_size <= 64; tu.tu_size++) {
 699                temp1_fp = drm_fixp_from_fraction(tu.tu_size, 1);
 700                temp2_fp = drm_fixp_mul(tu.ratio_fp, temp1_fp);
 701                temp = drm_fixp2int_ceil(temp2_fp);
 702                temp1_fp = drm_fixp_from_fraction(temp, 1);
 703                tu.n_err_fp = temp1_fp - temp2_fp;
 704
 705                if (tu.n_err_fp < tu.err_fp) {
 706                        tu.err_fp = tu.n_err_fp;
 707                        tu.tu_size_desired = tu.tu_size;
 708                }
 709        }
 710
 711        tu.tu_size_minus1 = tu.tu_size_desired - 1;
 712
 713        temp1_fp = drm_fixp_from_fraction(tu.tu_size_desired, 1);
 714        temp2_fp = drm_fixp_mul(tu.ratio_fp, temp1_fp);
 715        tu.valid_boundary_link = drm_fixp2int_ceil(temp2_fp);
 716
 717        temp1_fp = drm_fixp_from_fraction(tu.bpp, 8);
 718        temp2_fp = tu.lwidth_fp;
 719        temp2_fp = drm_fixp_mul(temp2_fp, temp1_fp);
 720
 721        temp1_fp = drm_fixp_from_fraction(tu.valid_boundary_link, 1);
 722        temp2_fp = drm_fixp_div(temp2_fp, temp1_fp);
 723        tu.n_tus = drm_fixp2int(temp2_fp);
 724        if ((temp2_fp & 0xFFFFFFFF) > 0xFFFFF000)
 725                tu.n_tus += 1;
 726
 727        tu.even_distribution_legacy = tu.n_tus % tu.nlanes == 0 ? 1 : 0;
 728        DRM_DEBUG_DP("Info: n_sym = %d, num_of_tus = %d\n",
 729                tu.valid_boundary_link, tu.n_tus);
 730
 731        temp1_fp = drm_fixp_from_fraction(tu.tu_size_desired, 1);
 732        temp2_fp = drm_fixp_mul(tu.original_ratio_fp, temp1_fp);
 733        temp1_fp = drm_fixp_from_fraction(tu.valid_boundary_link, 1);
 734        temp2_fp = temp1_fp - temp2_fp;
 735        temp1_fp = drm_fixp_from_fraction(tu.n_tus + 1, 1);
 736        temp2_fp = drm_fixp_mul(temp1_fp, temp2_fp);
 737
 738        temp = drm_fixp2int(temp2_fp);
 739        if (temp && temp2_fp)
 740                tu.extra_bytes = drm_fixp2int_ceil(temp2_fp);
 741        else
 742                tu.extra_bytes = 0;
 743
 744        temp1_fp = drm_fixp_from_fraction(tu.extra_bytes, 1);
 745        temp2_fp = drm_fixp_from_fraction(8, tu.bpp);
 746        temp1_fp = drm_fixp_mul(temp1_fp, temp2_fp);
 747
 748        if (temp && temp1_fp)
 749                tu.extra_pclk_cycles = drm_fixp2int_ceil(temp1_fp);
 750        else
 751                tu.extra_pclk_cycles = drm_fixp2int(temp1_fp);
 752
 753        temp1_fp = drm_fixp_div(tu.lclk_fp, tu.pclk_fp);
 754        temp2_fp = drm_fixp_from_fraction(tu.extra_pclk_cycles, 1);
 755        temp1_fp = drm_fixp_mul(temp2_fp, temp1_fp);
 756
 757        if (temp1_fp)
 758                tu.extra_pclk_cycles_in_link_clk = drm_fixp2int_ceil(temp1_fp);
 759        else
 760                tu.extra_pclk_cycles_in_link_clk = drm_fixp2int(temp1_fp);
 761
 762        tu.filler_size = tu.tu_size_desired - tu.valid_boundary_link;
 763
 764        temp1_fp = drm_fixp_from_fraction(tu.tu_size_desired, 1);
 765        tu.ratio_by_tu_fp = drm_fixp_mul(tu.ratio_fp, temp1_fp);
 766
 767        tu.delay_start_link = tu.extra_pclk_cycles_in_link_clk +
 768                                tu.filler_size + tu.extra_buffer_margin;
 769
 770        tu.resulting_valid_fp =
 771                        drm_fixp_from_fraction(tu.valid_boundary_link, 1);
 772
 773        temp1_fp = drm_fixp_from_fraction(tu.tu_size_desired, 1);
 774        temp2_fp = drm_fixp_div(tu.resulting_valid_fp, temp1_fp);
 775        tu.TU_ratio_err_fp = temp2_fp - tu.original_ratio_fp;
 776
 777        temp1_fp = drm_fixp_from_fraction(HBLANK_MARGIN, 1);
 778        temp1_fp = tu.hbp_relative_to_pclk_fp - temp1_fp;
 779        tu.hbp_time_fp = drm_fixp_div(temp1_fp, tu.pclk_fp);
 780
 781        temp1_fp = drm_fixp_from_fraction(tu.delay_start_link, 1);
 782        tu.delay_start_time_fp = drm_fixp_div(temp1_fp, tu.lclk_fp);
 783
 784        compare_result_1 = _tu_param_compare(tu.hbp_time_fp,
 785                                        tu.delay_start_time_fp);
 786        if (compare_result_1 == 2) /* if (hbp_time_fp < delay_start_time_fp) */
 787                tu.min_hblank_violated = 1;
 788
 789        tu.hactive_time_fp = drm_fixp_div(tu.lwidth_fp, tu.pclk_fp);
 790
 791        compare_result_2 = _tu_param_compare(tu.hactive_time_fp,
 792                                                tu.delay_start_time_fp);
 793        if (compare_result_2 == 2)
 794                tu.min_hblank_violated = 1;
 795
 796        tu.delay_start_time_fp = 0;
 797
 798        /* brute force */
 799
 800        tu.delay_start_link_extra_pixclk = EXTRA_PIXCLK_CYCLE_DELAY;
 801        tu.diff_abs_fp = tu.resulting_valid_fp - tu.ratio_by_tu_fp;
 802
 803        temp = drm_fixp2int(tu.diff_abs_fp);
 804        if (!temp && tu.diff_abs_fp <= 0xffff)
 805                tu.diff_abs_fp = 0;
 806
 807        /* if(diff_abs < 0) diff_abs *= -1 */
 808        if (tu.diff_abs_fp < 0)
 809                tu.diff_abs_fp = drm_fixp_mul(tu.diff_abs_fp, -1);
 810
 811        tu.boundary_mod_lower_err = 0;
 812        if ((tu.diff_abs_fp != 0 &&
 813                        ((tu.diff_abs_fp > BRUTE_FORCE_THRESHOLD_fp) ||
 814                         (tu.even_distribution_legacy == 0) ||
 815                         (DP_BRUTE_FORCE == 1))) ||
 816                        (tu.min_hblank_violated == 1)) {
 817                do {
 818                        tu.err_fp = drm_fixp_from_fraction(1000, 1);
 819
 820                        temp1_fp = drm_fixp_div(tu.lclk_fp, tu.pclk_fp);
 821                        temp2_fp = drm_fixp_from_fraction(
 822                                        tu.delay_start_link_extra_pixclk, 1);
 823                        temp1_fp = drm_fixp_mul(temp2_fp, temp1_fp);
 824
 825                        if (temp1_fp)
 826                                tu.extra_buffer_margin =
 827                                        drm_fixp2int_ceil(temp1_fp);
 828                        else
 829                                tu.extra_buffer_margin = 0;
 830
 831                        temp1_fp = drm_fixp_from_fraction(tu.bpp, 8);
 832                        temp1_fp = drm_fixp_mul(tu.lwidth_fp, temp1_fp);
 833
 834                        if (temp1_fp)
 835                                tu.n_symbols = drm_fixp2int_ceil(temp1_fp);
 836                        else
 837                                tu.n_symbols = 0;
 838
 839                        for (tu.tu_size = 32; tu.tu_size <= 64; tu.tu_size++) {
 840                                for (tu.i_upper_boundary_count = 1;
 841                                        tu.i_upper_boundary_count <= 15;
 842                                        tu.i_upper_boundary_count++) {
 843                                        for (tu.i_lower_boundary_count = 1;
 844                                                tu.i_lower_boundary_count <= 15;
 845                                                tu.i_lower_boundary_count++) {
 846                                                _tu_valid_boundary_calc(&tu);
 847                                        }
 848                                }
 849                        }
 850                        tu.delay_start_link_extra_pixclk--;
 851                } while (tu.boundary_moderation_en != true &&
 852                        tu.boundary_mod_lower_err == 1 &&
 853                        tu.delay_start_link_extra_pixclk != 0);
 854
 855                if (tu.boundary_moderation_en == true) {
 856                        temp1_fp = drm_fixp_from_fraction(
 857                                        (tu.upper_boundary_count *
 858                                        tu.valid_boundary_link +
 859                                        tu.lower_boundary_count *
 860                                        (tu.valid_boundary_link - 1)), 1);
 861                        temp2_fp = drm_fixp_from_fraction(
 862                                        (tu.upper_boundary_count +
 863                                        tu.lower_boundary_count), 1);
 864                        tu.resulting_valid_fp =
 865                                        drm_fixp_div(temp1_fp, temp2_fp);
 866
 867                        temp1_fp = drm_fixp_from_fraction(
 868                                        tu.tu_size_desired, 1);
 869                        tu.ratio_by_tu_fp =
 870                                drm_fixp_mul(tu.original_ratio_fp, temp1_fp);
 871
 872                        tu.valid_lower_boundary_link =
 873                                tu.valid_boundary_link - 1;
 874
 875                        temp1_fp = drm_fixp_from_fraction(tu.bpp, 8);
 876                        temp1_fp = drm_fixp_mul(tu.lwidth_fp, temp1_fp);
 877                        temp2_fp = drm_fixp_div(temp1_fp,
 878                                                tu.resulting_valid_fp);
 879                        tu.n_tus = drm_fixp2int(temp2_fp);
 880
 881                        tu.tu_size_minus1 = tu.tu_size_desired - 1;
 882                        tu.even_distribution_BF = 1;
 883
 884                        temp1_fp =
 885                                drm_fixp_from_fraction(tu.tu_size_desired, 1);
 886                        temp2_fp =
 887                                drm_fixp_div(tu.resulting_valid_fp, temp1_fp);
 888                        tu.TU_ratio_err_fp = temp2_fp - tu.original_ratio_fp;
 889                }
 890        }
 891
 892        temp2_fp = drm_fixp_mul(LCLK_FAST_SKEW_fp, tu.lwidth_fp);
 893
 894        if (temp2_fp)
 895                temp = drm_fixp2int_ceil(temp2_fp);
 896        else
 897                temp = 0;
 898
 899        temp1_fp = drm_fixp_from_fraction(tu.nlanes, 1);
 900        temp2_fp = drm_fixp_mul(tu.original_ratio_fp, temp1_fp);
 901        temp1_fp = drm_fixp_from_fraction(tu.bpp, 8);
 902        temp2_fp = drm_fixp_div(temp1_fp, temp2_fp);
 903        temp1_fp = drm_fixp_from_fraction(temp, 1);
 904        temp2_fp = drm_fixp_mul(temp1_fp, temp2_fp);
 905        temp = drm_fixp2int(temp2_fp);
 906
 907        if (tu.async_en)
 908                tu.delay_start_link += (int)temp;
 909
 910        temp1_fp = drm_fixp_from_fraction(tu.delay_start_link, 1);
 911        tu.delay_start_time_fp = drm_fixp_div(temp1_fp, tu.lclk_fp);
 912
 913        /* OUTPUTS */
 914        tu_table->valid_boundary_link       = tu.valid_boundary_link;
 915        tu_table->delay_start_link          = tu.delay_start_link;
 916        tu_table->boundary_moderation_en    = tu.boundary_moderation_en;
 917        tu_table->valid_lower_boundary_link = tu.valid_lower_boundary_link;
 918        tu_table->upper_boundary_count      = tu.upper_boundary_count;
 919        tu_table->lower_boundary_count      = tu.lower_boundary_count;
 920        tu_table->tu_size_minus1            = tu.tu_size_minus1;
 921
 922        DRM_DEBUG_DP("TU: valid_boundary_link: %d\n",
 923                                tu_table->valid_boundary_link);
 924        DRM_DEBUG_DP("TU: delay_start_link: %d\n",
 925                                tu_table->delay_start_link);
 926        DRM_DEBUG_DP("TU: boundary_moderation_en: %d\n",
 927                        tu_table->boundary_moderation_en);
 928        DRM_DEBUG_DP("TU: valid_lower_boundary_link: %d\n",
 929                        tu_table->valid_lower_boundary_link);
 930        DRM_DEBUG_DP("TU: upper_boundary_count: %d\n",
 931                        tu_table->upper_boundary_count);
 932        DRM_DEBUG_DP("TU: lower_boundary_count: %d\n",
 933                        tu_table->lower_boundary_count);
 934        DRM_DEBUG_DP("TU: tu_size_minus1: %d\n", tu_table->tu_size_minus1);
 935}
 936
 937static void dp_ctrl_calc_tu_parameters(struct dp_ctrl_private *ctrl,
 938                struct dp_vc_tu_mapping_table *tu_table)
 939{
 940        struct dp_tu_calc_input in;
 941        struct drm_display_mode *drm_mode;
 942
 943        drm_mode = &ctrl->panel->dp_mode.drm_mode;
 944
 945        in.lclk = ctrl->link->link_params.rate / 1000;
 946        in.pclk_khz = drm_mode->clock;
 947        in.hactive = drm_mode->hdisplay;
 948        in.hporch = drm_mode->htotal - drm_mode->hdisplay;
 949        in.nlanes = ctrl->link->link_params.num_lanes;
 950        in.bpp = ctrl->panel->dp_mode.bpp;
 951        in.pixel_enc = 444;
 952        in.dsc_en = 0;
 953        in.async_en = 0;
 954        in.fec_en = 0;
 955        in.num_of_dsc_slices = 0;
 956        in.compress_ratio = 100;
 957
 958        _dp_ctrl_calc_tu(&in, tu_table);
 959}
 960
 961static void dp_ctrl_setup_tr_unit(struct dp_ctrl_private *ctrl)
 962{
 963        u32 dp_tu = 0x0;
 964        u32 valid_boundary = 0x0;
 965        u32 valid_boundary2 = 0x0;
 966        struct dp_vc_tu_mapping_table tu_calc_table;
 967
 968        dp_ctrl_calc_tu_parameters(ctrl, &tu_calc_table);
 969
 970        dp_tu |= tu_calc_table.tu_size_minus1;
 971        valid_boundary |= tu_calc_table.valid_boundary_link;
 972        valid_boundary |= (tu_calc_table.delay_start_link << 16);
 973
 974        valid_boundary2 |= (tu_calc_table.valid_lower_boundary_link << 1);
 975        valid_boundary2 |= (tu_calc_table.upper_boundary_count << 16);
 976        valid_boundary2 |= (tu_calc_table.lower_boundary_count << 20);
 977
 978        if (tu_calc_table.boundary_moderation_en)
 979                valid_boundary2 |= BIT(0);
 980
 981        pr_debug("dp_tu=0x%x, valid_boundary=0x%x, valid_boundary2=0x%x\n",
 982                        dp_tu, valid_boundary, valid_boundary2);
 983
 984        dp_catalog_ctrl_update_transfer_unit(ctrl->catalog,
 985                                dp_tu, valid_boundary, valid_boundary2);
 986}
 987
 988static int dp_ctrl_wait4video_ready(struct dp_ctrl_private *ctrl)
 989{
 990        int ret = 0;
 991
 992        if (!wait_for_completion_timeout(&ctrl->video_comp,
 993                                WAIT_FOR_VIDEO_READY_TIMEOUT_JIFFIES)) {
 994                DRM_ERROR("wait4video timedout\n");
 995                ret = -ETIMEDOUT;
 996        }
 997        return ret;
 998}
 999
1000static int dp_ctrl_update_vx_px(struct dp_ctrl_private *ctrl)
1001{
1002        struct dp_link *link = ctrl->link;
1003        int ret = 0, lane, lane_cnt;
1004        u8 buf[4];
1005        u32 max_level_reached = 0;
1006        u32 voltage_swing_level = link->phy_params.v_level;
1007        u32 pre_emphasis_level = link->phy_params.p_level;
1008
1009        ret = dp_catalog_ctrl_update_vx_px(ctrl->catalog,
1010                voltage_swing_level, pre_emphasis_level);
1011
1012        if (ret)
1013                return ret;
1014
1015        if (voltage_swing_level >= DP_TRAIN_VOLTAGE_SWING_MAX) {
1016                DRM_DEBUG_DP("max. voltage swing level reached %d\n",
1017                                voltage_swing_level);
1018                max_level_reached |= DP_TRAIN_MAX_SWING_REACHED;
1019        }
1020
1021        if (pre_emphasis_level >= DP_TRAIN_PRE_EMPHASIS_MAX) {
1022                DRM_DEBUG_DP("max. pre-emphasis level reached %d\n",
1023                                pre_emphasis_level);
1024                max_level_reached  |= DP_TRAIN_MAX_PRE_EMPHASIS_REACHED;
1025        }
1026
1027        pre_emphasis_level <<= DP_TRAIN_PRE_EMPHASIS_SHIFT;
1028
1029        lane_cnt = ctrl->link->link_params.num_lanes;
1030        for (lane = 0; lane < lane_cnt; lane++)
1031                buf[lane] = voltage_swing_level | pre_emphasis_level
1032                                | max_level_reached;
1033
1034        DRM_DEBUG_DP("sink: p|v=0x%x\n", voltage_swing_level
1035                                        | pre_emphasis_level);
1036        ret = drm_dp_dpcd_write(ctrl->aux, DP_TRAINING_LANE0_SET,
1037                                        buf, lane_cnt);
1038        if (ret == lane_cnt)
1039                ret = 0;
1040
1041        return ret;
1042}
1043
1044static bool dp_ctrl_train_pattern_set(struct dp_ctrl_private *ctrl,
1045                u8 pattern)
1046{
1047        u8 buf;
1048        int ret = 0;
1049
1050        DRM_DEBUG_DP("sink: pattern=%x\n", pattern);
1051
1052        buf = pattern;
1053
1054        if (pattern && pattern != DP_TRAINING_PATTERN_4)
1055                buf |= DP_LINK_SCRAMBLING_DISABLE;
1056
1057        ret = drm_dp_dpcd_writeb(ctrl->aux, DP_TRAINING_PATTERN_SET, buf);
1058        return ret == 1;
1059}
1060
1061static int dp_ctrl_read_link_status(struct dp_ctrl_private *ctrl,
1062                                    u8 *link_status)
1063{
1064        int len = 0;
1065        u32 const offset = DP_LANE_ALIGN_STATUS_UPDATED - DP_LANE0_1_STATUS;
1066        u32 link_status_read_max_retries = 100;
1067
1068        while (--link_status_read_max_retries) {
1069                len = drm_dp_dpcd_read_link_status(ctrl->aux,
1070                        link_status);
1071                if (len != DP_LINK_STATUS_SIZE) {
1072                        DRM_ERROR("DP link status read failed, err: %d\n", len);
1073                        return len;
1074                }
1075
1076                if (!(link_status[offset] & DP_LINK_STATUS_UPDATED))
1077                        return 0;
1078        }
1079
1080        return -ETIMEDOUT;
1081}
1082
1083static int dp_ctrl_link_train_1(struct dp_ctrl_private *ctrl,
1084                struct dp_cr_status *cr, int *training_step)
1085{
1086        int tries, old_v_level, ret = 0;
1087        u8 link_status[DP_LINK_STATUS_SIZE];
1088        int const maximum_retries = 4;
1089
1090        dp_catalog_ctrl_state_ctrl(ctrl->catalog, 0);
1091
1092        *training_step = DP_TRAINING_1;
1093
1094        ret = dp_catalog_ctrl_set_pattern(ctrl->catalog, DP_TRAINING_PATTERN_1);
1095        if (ret)
1096                return ret;
1097        dp_ctrl_train_pattern_set(ctrl, DP_TRAINING_PATTERN_1 |
1098                DP_LINK_SCRAMBLING_DISABLE);
1099
1100        ret = dp_ctrl_update_vx_px(ctrl);
1101        if (ret)
1102                return ret;
1103
1104        tries = 0;
1105        old_v_level = ctrl->link->phy_params.v_level;
1106        for (tries = 0; tries < maximum_retries; tries++) {
1107                drm_dp_link_train_clock_recovery_delay(ctrl->panel->dpcd);
1108
1109                ret = dp_ctrl_read_link_status(ctrl, link_status);
1110                if (ret)
1111                        return ret;
1112
1113                cr->lane_0_1 = link_status[0];
1114                cr->lane_2_3 = link_status[1];
1115
1116                if (drm_dp_clock_recovery_ok(link_status,
1117                        ctrl->link->link_params.num_lanes)) {
1118                        return 0;
1119                }
1120
1121                if (ctrl->link->phy_params.v_level >=
1122                        DP_TRAIN_VOLTAGE_SWING_MAX) {
1123                        DRM_ERROR_RATELIMITED("max v_level reached\n");
1124                        return -EAGAIN;
1125                }
1126
1127                if (old_v_level != ctrl->link->phy_params.v_level) {
1128                        tries = 0;
1129                        old_v_level = ctrl->link->phy_params.v_level;
1130                }
1131
1132                DRM_DEBUG_DP("clock recovery not done, adjusting vx px\n");
1133
1134                dp_link_adjust_levels(ctrl->link, link_status);
1135                ret = dp_ctrl_update_vx_px(ctrl);
1136                if (ret)
1137                        return ret;
1138        }
1139
1140        DRM_ERROR("max tries reached\n");
1141        return -ETIMEDOUT;
1142}
1143
1144static int dp_ctrl_link_rate_down_shift(struct dp_ctrl_private *ctrl)
1145{
1146        int ret = 0;
1147
1148        switch (ctrl->link->link_params.rate) {
1149        case 810000:
1150                ctrl->link->link_params.rate = 540000;
1151                break;
1152        case 540000:
1153                ctrl->link->link_params.rate = 270000;
1154                break;
1155        case 270000:
1156                ctrl->link->link_params.rate = 162000;
1157                break;
1158        case 162000:
1159        default:
1160                ret = -EINVAL;
1161                break;
1162        };
1163
1164        if (!ret)
1165                DRM_DEBUG_DP("new rate=0x%x\n", ctrl->link->link_params.rate);
1166
1167        return ret;
1168}
1169
1170static int dp_ctrl_link_lane_down_shift(struct dp_ctrl_private *ctrl)
1171{
1172
1173        if (ctrl->link->link_params.num_lanes == 1)
1174                return -1;
1175
1176        ctrl->link->link_params.num_lanes /= 2;
1177        ctrl->link->link_params.rate = ctrl->panel->link_info.rate;
1178
1179        ctrl->link->phy_params.p_level = 0;
1180        ctrl->link->phy_params.v_level = 0;
1181
1182        return 0;
1183}
1184
1185static void dp_ctrl_clear_training_pattern(struct dp_ctrl_private *ctrl)
1186{
1187        dp_ctrl_train_pattern_set(ctrl, DP_TRAINING_PATTERN_DISABLE);
1188        drm_dp_link_train_channel_eq_delay(ctrl->panel->dpcd);
1189}
1190
1191static int dp_ctrl_link_train_2(struct dp_ctrl_private *ctrl,
1192                struct dp_cr_status *cr, int *training_step)
1193{
1194        int tries = 0, ret = 0;
1195        char pattern;
1196        int const maximum_retries = 5;
1197        u8 link_status[DP_LINK_STATUS_SIZE];
1198
1199        dp_catalog_ctrl_state_ctrl(ctrl->catalog, 0);
1200
1201        *training_step = DP_TRAINING_2;
1202
1203        if (drm_dp_tps3_supported(ctrl->panel->dpcd))
1204                pattern = DP_TRAINING_PATTERN_3;
1205        else
1206                pattern = DP_TRAINING_PATTERN_2;
1207
1208        ret = dp_ctrl_update_vx_px(ctrl);
1209        if (ret)
1210                return ret;
1211
1212        ret = dp_catalog_ctrl_set_pattern(ctrl->catalog, pattern);
1213        if (ret)
1214                return ret;
1215
1216        dp_ctrl_train_pattern_set(ctrl, pattern | DP_RECOVERED_CLOCK_OUT_EN);
1217
1218        for (tries = 0; tries <= maximum_retries; tries++) {
1219                drm_dp_link_train_channel_eq_delay(ctrl->panel->dpcd);
1220
1221                ret = dp_ctrl_read_link_status(ctrl, link_status);
1222                if (ret)
1223                        return ret;
1224                cr->lane_0_1 = link_status[0];
1225                cr->lane_2_3 = link_status[1];
1226
1227                if (drm_dp_channel_eq_ok(link_status,
1228                        ctrl->link->link_params.num_lanes)) {
1229                        return 0;
1230                }
1231
1232                dp_link_adjust_levels(ctrl->link, link_status);
1233                ret = dp_ctrl_update_vx_px(ctrl);
1234                if (ret)
1235                        return ret;
1236
1237        }
1238
1239        return -ETIMEDOUT;
1240}
1241
1242static int dp_ctrl_reinitialize_mainlink(struct dp_ctrl_private *ctrl);
1243
1244static int dp_ctrl_link_train(struct dp_ctrl_private *ctrl,
1245                struct dp_cr_status *cr, int *training_step)
1246{
1247        int ret = 0;
1248        u8 encoding = DP_SET_ANSI_8B10B;
1249        struct dp_link_info link_info = {0};
1250
1251        dp_ctrl_config_ctrl(ctrl);
1252
1253        link_info.num_lanes = ctrl->link->link_params.num_lanes;
1254        link_info.rate = ctrl->link->link_params.rate;
1255        link_info.capabilities = DP_LINK_CAP_ENHANCED_FRAMING;
1256
1257        dp_aux_link_configure(ctrl->aux, &link_info);
1258        drm_dp_dpcd_write(ctrl->aux, DP_MAIN_LINK_CHANNEL_CODING_SET,
1259                                &encoding, 1);
1260
1261        ret = dp_ctrl_link_train_1(ctrl, cr, training_step);
1262        if (ret) {
1263                DRM_ERROR("link training #1 failed. ret=%d\n", ret);
1264                goto end;
1265        }
1266
1267        /* print success info as this is a result of user initiated action */
1268        DRM_DEBUG_DP("link training #1 successful\n");
1269
1270        ret = dp_ctrl_link_train_2(ctrl, cr, training_step);
1271        if (ret) {
1272                DRM_ERROR("link training #2 failed. ret=%d\n", ret);
1273                goto end;
1274        }
1275
1276        /* print success info as this is a result of user initiated action */
1277        DRM_DEBUG_DP("link training #2 successful\n");
1278
1279end:
1280        dp_catalog_ctrl_state_ctrl(ctrl->catalog, 0);
1281
1282        return ret;
1283}
1284
1285static int dp_ctrl_setup_main_link(struct dp_ctrl_private *ctrl,
1286                struct dp_cr_status *cr, int *training_step)
1287{
1288        int ret = 0;
1289
1290        dp_catalog_ctrl_mainlink_ctrl(ctrl->catalog, true);
1291
1292        if (ctrl->link->sink_request & DP_TEST_LINK_PHY_TEST_PATTERN)
1293                return ret;
1294
1295        /*
1296         * As part of previous calls, DP controller state might have
1297         * transitioned to PUSH_IDLE. In order to start transmitting
1298         * a link training pattern, we have to first do soft reset.
1299         */
1300        dp_catalog_ctrl_reset(ctrl->catalog);
1301
1302        ret = dp_ctrl_link_train(ctrl, cr, training_step);
1303
1304        return ret;
1305}
1306
1307static void dp_ctrl_set_clock_rate(struct dp_ctrl_private *ctrl,
1308                        enum dp_pm_type module, char *name, unsigned long rate)
1309{
1310        u32 num = ctrl->parser->mp[module].num_clk;
1311        struct dss_clk *cfg = ctrl->parser->mp[module].clk_config;
1312
1313        while (num && strcmp(cfg->clk_name, name)) {
1314                num--;
1315                cfg++;
1316        }
1317
1318        DRM_DEBUG_DP("setting rate=%lu on clk=%s\n", rate, name);
1319
1320        if (num)
1321                cfg->rate = rate;
1322        else
1323                DRM_ERROR("%s clock doesn't exit to set rate %lu\n",
1324                                name, rate);
1325}
1326
1327static int dp_ctrl_enable_mainlink_clocks(struct dp_ctrl_private *ctrl)
1328{
1329        int ret = 0;
1330        struct dp_io *dp_io = &ctrl->parser->io;
1331        struct phy *phy = dp_io->phy;
1332        struct phy_configure_opts_dp *opts_dp = &dp_io->phy_opts.dp;
1333
1334        opts_dp->lanes = ctrl->link->link_params.num_lanes;
1335        opts_dp->link_rate = ctrl->link->link_params.rate / 100;
1336        dp_ctrl_set_clock_rate(ctrl, DP_CTRL_PM, "ctrl_link",
1337                                        ctrl->link->link_params.rate * 1000);
1338
1339        phy_configure(phy, &dp_io->phy_opts);
1340        phy_power_on(phy);
1341
1342        ret = dp_power_clk_enable(ctrl->power, DP_CTRL_PM, true);
1343        if (ret)
1344                DRM_ERROR("Unable to start link clocks. ret=%d\n", ret);
1345
1346        DRM_DEBUG_DP("link rate=%d pixel_clk=%d\n",
1347                ctrl->link->link_params.rate, ctrl->dp_ctrl.pixel_rate);
1348
1349        return ret;
1350}
1351
1352static int dp_ctrl_enable_stream_clocks(struct dp_ctrl_private *ctrl)
1353{
1354        int ret = 0;
1355
1356        dp_ctrl_set_clock_rate(ctrl, DP_STREAM_PM, "stream_pixel",
1357                                        ctrl->dp_ctrl.pixel_rate * 1000);
1358
1359        ret = dp_power_clk_enable(ctrl->power, DP_STREAM_PM, true);
1360        if (ret)
1361                DRM_ERROR("Unabled to start pixel clocks. ret=%d\n", ret);
1362
1363        DRM_DEBUG_DP("link rate=%d pixel_clk=%d\n",
1364                        ctrl->link->link_params.rate, ctrl->dp_ctrl.pixel_rate);
1365
1366        return ret;
1367}
1368
1369int dp_ctrl_host_init(struct dp_ctrl *dp_ctrl, bool flip)
1370{
1371        struct dp_ctrl_private *ctrl;
1372        struct dp_io *dp_io;
1373        struct phy *phy;
1374
1375        if (!dp_ctrl) {
1376                DRM_ERROR("Invalid input data\n");
1377                return -EINVAL;
1378        }
1379
1380        ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);
1381        dp_io = &ctrl->parser->io;
1382        phy = dp_io->phy;
1383
1384        ctrl->dp_ctrl.orientation = flip;
1385
1386        dp_catalog_ctrl_phy_reset(ctrl->catalog);
1387        phy_init(phy);
1388        dp_catalog_ctrl_enable_irq(ctrl->catalog, true);
1389
1390        return 0;
1391}
1392
1393/**
1394 * dp_ctrl_host_deinit() - Uninitialize DP controller
1395 * @dp_ctrl: Display Port Driver data
1396 *
1397 * Perform required steps to uninitialize DP controller
1398 * and its resources.
1399 */
1400void dp_ctrl_host_deinit(struct dp_ctrl *dp_ctrl)
1401{
1402        struct dp_ctrl_private *ctrl;
1403
1404        if (!dp_ctrl) {
1405                DRM_ERROR("Invalid input data\n");
1406                return;
1407        }
1408
1409        ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);
1410
1411        dp_catalog_ctrl_enable_irq(ctrl->catalog, false);
1412
1413        DRM_DEBUG_DP("Host deinitialized successfully\n");
1414}
1415
1416static bool dp_ctrl_use_fixed_nvid(struct dp_ctrl_private *ctrl)
1417{
1418        u8 *dpcd = ctrl->panel->dpcd;
1419        u32 edid_quirks = 0;
1420
1421        edid_quirks = drm_dp_get_edid_quirks(ctrl->panel->edid);
1422        /*
1423         * For better interop experience, used a fixed NVID=0x8000
1424         * whenever connected to a VGA dongle downstream.
1425         */
1426        if (drm_dp_is_branch(dpcd))
1427                return (drm_dp_has_quirk(&ctrl->panel->desc, edid_quirks,
1428                                DP_DPCD_QUIRK_CONSTANT_N));
1429
1430        return false;
1431}
1432
1433static int dp_ctrl_reinitialize_mainlink(struct dp_ctrl_private *ctrl)
1434{
1435        int ret = 0;
1436        struct dp_io *dp_io = &ctrl->parser->io;
1437        struct phy *phy = dp_io->phy;
1438        struct phy_configure_opts_dp *opts_dp = &dp_io->phy_opts.dp;
1439
1440        dp_catalog_ctrl_mainlink_ctrl(ctrl->catalog, false);
1441        opts_dp->lanes = ctrl->link->link_params.num_lanes;
1442        phy_configure(phy, &dp_io->phy_opts);
1443        /*
1444         * Disable and re-enable the mainlink clock since the
1445         * link clock might have been adjusted as part of the
1446         * link maintenance.
1447         */
1448        ret = dp_power_clk_enable(ctrl->power, DP_CTRL_PM, false);
1449        if (ret) {
1450                DRM_ERROR("Failed to disable clocks. ret=%d\n", ret);
1451                return ret;
1452        }
1453        phy_power_off(phy);
1454        /* hw recommended delay before re-enabling clocks */
1455        msleep(20);
1456
1457        ret = dp_ctrl_enable_mainlink_clocks(ctrl);
1458        if (ret) {
1459                DRM_ERROR("Failed to enable mainlink clks. ret=%d\n", ret);
1460                return ret;
1461        }
1462
1463        return ret;
1464}
1465
1466static int dp_ctrl_link_maintenance(struct dp_ctrl_private *ctrl)
1467{
1468        int ret = 0;
1469        struct dp_cr_status cr;
1470        int training_step = DP_TRAINING_NONE;
1471
1472        dp_ctrl_push_idle(&ctrl->dp_ctrl);
1473        dp_catalog_ctrl_reset(ctrl->catalog);
1474
1475        ctrl->dp_ctrl.pixel_rate = ctrl->panel->dp_mode.drm_mode.clock;
1476
1477        ret = dp_ctrl_setup_main_link(ctrl, &cr, &training_step);
1478        if (ret)
1479                goto end;
1480
1481        dp_ctrl_clear_training_pattern(ctrl);
1482
1483        dp_catalog_ctrl_state_ctrl(ctrl->catalog, DP_STATE_CTRL_SEND_VIDEO);
1484
1485        ret = dp_ctrl_wait4video_ready(ctrl);
1486end:
1487        return ret;
1488}
1489
1490static int dp_ctrl_process_phy_test_request(struct dp_ctrl_private *ctrl)
1491{
1492        int ret = 0;
1493
1494        if (!ctrl->link->phy_params.phy_test_pattern_sel) {
1495                DRM_DEBUG_DP("no test pattern selected by sink\n");
1496                return ret;
1497        }
1498
1499        /*
1500         * The global reset will need DP link related clocks to be
1501         * running. Add the global reset just before disabling the
1502         * link clocks and core clocks.
1503         */
1504        ret = dp_ctrl_off(&ctrl->dp_ctrl);
1505        if (ret) {
1506                DRM_ERROR("failed to disable DP controller\n");
1507                return ret;
1508        }
1509
1510        ret = dp_ctrl_on_link(&ctrl->dp_ctrl);
1511        if (!ret)
1512                ret = dp_ctrl_on_stream(&ctrl->dp_ctrl);
1513        else
1514                DRM_ERROR("failed to enable DP link controller\n");
1515
1516        return ret;
1517}
1518
1519static bool dp_ctrl_send_phy_test_pattern(struct dp_ctrl_private *ctrl)
1520{
1521        bool success = false;
1522        u32 pattern_sent = 0x0;
1523        u32 pattern_requested = ctrl->link->phy_params.phy_test_pattern_sel;
1524
1525        DRM_DEBUG_DP("request: 0x%x\n", pattern_requested);
1526
1527        if (dp_catalog_ctrl_update_vx_px(ctrl->catalog,
1528                        ctrl->link->phy_params.v_level,
1529                        ctrl->link->phy_params.p_level)) {
1530                DRM_ERROR("Failed to set v/p levels\n");
1531                return false;
1532        }
1533        dp_catalog_ctrl_send_phy_pattern(ctrl->catalog, pattern_requested);
1534        dp_ctrl_update_vx_px(ctrl);
1535        dp_link_send_test_response(ctrl->link);
1536
1537        pattern_sent = dp_catalog_ctrl_read_phy_pattern(ctrl->catalog);
1538
1539        switch (pattern_sent) {
1540        case MR_LINK_TRAINING1:
1541                success = (pattern_requested ==
1542                                DP_PHY_TEST_PATTERN_D10_2);
1543                break;
1544        case MR_LINK_SYMBOL_ERM:
1545                success = ((pattern_requested ==
1546                        DP_PHY_TEST_PATTERN_ERROR_COUNT) ||
1547                                (pattern_requested ==
1548                                DP_PHY_TEST_PATTERN_CP2520));
1549                break;
1550        case MR_LINK_PRBS7:
1551                success = (pattern_requested ==
1552                                DP_PHY_TEST_PATTERN_PRBS7);
1553                break;
1554        case MR_LINK_CUSTOM80:
1555                success = (pattern_requested ==
1556                                DP_PHY_TEST_PATTERN_80BIT_CUSTOM);
1557                break;
1558        case MR_LINK_TRAINING4:
1559                success = (pattern_requested ==
1560                                DP_PHY_TEST_PATTERN_SEL_MASK);
1561                break;
1562        default:
1563                success = false;
1564        }
1565
1566        DRM_DEBUG_DP("%s: test->0x%x\n", success ? "success" : "failed",
1567                                                pattern_requested);
1568        return success;
1569}
1570
1571void dp_ctrl_handle_sink_request(struct dp_ctrl *dp_ctrl)
1572{
1573        struct dp_ctrl_private *ctrl;
1574        u32 sink_request = 0x0;
1575
1576        if (!dp_ctrl) {
1577                DRM_ERROR("invalid input\n");
1578                return;
1579        }
1580
1581        ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);
1582        sink_request = ctrl->link->sink_request;
1583
1584        if (sink_request & DP_TEST_LINK_PHY_TEST_PATTERN) {
1585                DRM_DEBUG_DP("PHY_TEST_PATTERN request\n");
1586                if (dp_ctrl_process_phy_test_request(ctrl)) {
1587                        DRM_ERROR("process phy_test_req failed\n");
1588                        return;
1589                }
1590        }
1591
1592        if (sink_request & DP_LINK_STATUS_UPDATED) {
1593                if (dp_ctrl_link_maintenance(ctrl)) {
1594                        DRM_ERROR("LM failed: TEST_LINK_TRAINING\n");
1595                        return;
1596                }
1597        }
1598
1599        if (sink_request & DP_TEST_LINK_TRAINING) {
1600                dp_link_send_test_response(ctrl->link);
1601                if (dp_ctrl_link_maintenance(ctrl)) {
1602                        DRM_ERROR("LM failed: TEST_LINK_TRAINING\n");
1603                        return;
1604                }
1605        }
1606}
1607
1608int dp_ctrl_on_link(struct dp_ctrl *dp_ctrl)
1609{
1610        int rc = 0;
1611        struct dp_ctrl_private *ctrl;
1612        u32 rate = 0;
1613        int link_train_max_retries = 5;
1614        u32 const phy_cts_pixel_clk_khz = 148500;
1615        struct dp_cr_status cr;
1616        unsigned int training_step;
1617
1618        if (!dp_ctrl)
1619                return -EINVAL;
1620
1621        ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);
1622
1623        rate = ctrl->panel->link_info.rate;
1624
1625        dp_power_clk_enable(ctrl->power, DP_CORE_PM, true);
1626
1627        if (ctrl->link->sink_request & DP_TEST_LINK_PHY_TEST_PATTERN) {
1628                DRM_DEBUG_DP("using phy test link parameters\n");
1629                if (!ctrl->panel->dp_mode.drm_mode.clock)
1630                        ctrl->dp_ctrl.pixel_rate = phy_cts_pixel_clk_khz;
1631        } else {
1632                ctrl->link->link_params.rate = rate;
1633                ctrl->link->link_params.num_lanes =
1634                        ctrl->panel->link_info.num_lanes;
1635                ctrl->dp_ctrl.pixel_rate = ctrl->panel->dp_mode.drm_mode.clock;
1636        }
1637
1638        DRM_DEBUG_DP("rate=%d, num_lanes=%d, pixel_rate=%d\n",
1639                ctrl->link->link_params.rate,
1640                ctrl->link->link_params.num_lanes, ctrl->dp_ctrl.pixel_rate);
1641
1642        rc = dp_ctrl_enable_mainlink_clocks(ctrl);
1643        if (rc)
1644                return rc;
1645
1646        ctrl->link->phy_params.p_level = 0;
1647        ctrl->link->phy_params.v_level = 0;
1648
1649        while (--link_train_max_retries &&
1650                !atomic_read(&ctrl->dp_ctrl.aborted)) {
1651                rc = dp_ctrl_reinitialize_mainlink(ctrl);
1652                if (rc) {
1653                        DRM_ERROR("Failed to reinitialize mainlink. rc=%d\n",
1654                                        rc);
1655                        break;
1656                }
1657
1658                training_step = DP_TRAINING_NONE;
1659                rc = dp_ctrl_setup_main_link(ctrl, &cr, &training_step);
1660                if (rc == 0) {
1661                        /* training completed successfully */
1662                        break;
1663                } else if (training_step == DP_TRAINING_1) {
1664                        /* link train_1 failed */
1665                        rc = dp_ctrl_link_rate_down_shift(ctrl);
1666                        if (rc < 0) { /* already in RBR = 1.6G */
1667                                if (cr.lane_0_1 & DP_LANE0_1_CR_DONE) {
1668                                        /*
1669                                         * some lanes are ready,
1670                                         * reduce lane number
1671                                         */
1672                                        rc = dp_ctrl_link_lane_down_shift(ctrl);
1673                                        if (rc < 0) { /* lane == 1 already */
1674                                                /* end with failure */
1675                                                break;
1676                                        }
1677                                } else {
1678                                        /* end with failure */
1679                                        break; /* lane == 1 already */
1680                                }
1681                        }
1682                } else if (training_step == DP_TRAINING_2) {
1683                        /* link train_2 failed, lower lane rate */
1684                        rc = dp_ctrl_link_lane_down_shift(ctrl);
1685                        if (rc < 0) {
1686                                /* end with failure */
1687                                break; /* lane == 1 already */
1688                        }
1689                }
1690        }
1691
1692        if (ctrl->link->sink_request & DP_TEST_LINK_PHY_TEST_PATTERN)
1693                return rc;
1694
1695        /* stop txing train pattern */
1696        dp_ctrl_clear_training_pattern(ctrl);
1697
1698        /*
1699         * keep transmitting idle pattern until video ready
1700         * to avoid main link from loss of sync
1701         */
1702        if (rc == 0)  /* link train successfully */
1703                dp_ctrl_push_idle(dp_ctrl);
1704
1705        return rc;
1706}
1707
1708int dp_ctrl_on_stream(struct dp_ctrl *dp_ctrl)
1709{
1710        u32 rate = 0;
1711        int ret = 0;
1712        bool mainlink_ready = false;
1713        struct dp_ctrl_private *ctrl;
1714
1715        if (!dp_ctrl)
1716                return -EINVAL;
1717
1718        ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);
1719
1720        rate = ctrl->panel->link_info.rate;
1721
1722        ctrl->link->link_params.rate = rate;
1723        ctrl->link->link_params.num_lanes = ctrl->panel->link_info.num_lanes;
1724        ctrl->dp_ctrl.pixel_rate = ctrl->panel->dp_mode.drm_mode.clock;
1725
1726        DRM_DEBUG_DP("rate=%d, num_lanes=%d, pixel_rate=%d\n",
1727                ctrl->link->link_params.rate,
1728                ctrl->link->link_params.num_lanes, ctrl->dp_ctrl.pixel_rate);
1729
1730        if (!dp_power_clk_status(ctrl->power, DP_CTRL_PM)) { /* link clk is off */
1731                ret = dp_ctrl_enable_mainlink_clocks(ctrl);
1732                if (ret) {
1733                        DRM_ERROR("Failed to start link clocks. ret=%d\n", ret);
1734                        goto end;
1735                }
1736        }
1737
1738        ret = dp_ctrl_enable_stream_clocks(ctrl);
1739        if (ret) {
1740                DRM_ERROR("Failed to start pixel clocks. ret=%d\n", ret);
1741                goto end;
1742        }
1743
1744        if (ctrl->link->sink_request & DP_TEST_LINK_PHY_TEST_PATTERN) {
1745                dp_ctrl_send_phy_test_pattern(ctrl);
1746                return 0;
1747        }
1748
1749        /*
1750         * Set up transfer unit values and set controller state to send
1751         * video.
1752         */
1753        dp_ctrl_configure_source_params(ctrl);
1754
1755        dp_catalog_ctrl_config_msa(ctrl->catalog,
1756                ctrl->link->link_params.rate,
1757                ctrl->dp_ctrl.pixel_rate, dp_ctrl_use_fixed_nvid(ctrl));
1758
1759        reinit_completion(&ctrl->video_comp);
1760
1761        dp_ctrl_setup_tr_unit(ctrl);
1762
1763        dp_catalog_ctrl_state_ctrl(ctrl->catalog, DP_STATE_CTRL_SEND_VIDEO);
1764
1765        ret = dp_ctrl_wait4video_ready(ctrl);
1766        if (ret)
1767                return ret;
1768
1769        mainlink_ready = dp_catalog_ctrl_mainlink_ready(ctrl->catalog);
1770        DRM_DEBUG_DP("mainlink %s\n", mainlink_ready ? "READY" : "NOT READY");
1771
1772end:
1773        return ret;
1774}
1775
1776int dp_ctrl_off(struct dp_ctrl *dp_ctrl)
1777{
1778        struct dp_ctrl_private *ctrl;
1779        struct dp_io *dp_io;
1780        struct phy *phy;
1781        int ret = 0;
1782
1783        if (!dp_ctrl)
1784                return -EINVAL;
1785
1786        ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);
1787        dp_io = &ctrl->parser->io;
1788        phy = dp_io->phy;
1789
1790        dp_catalog_ctrl_mainlink_ctrl(ctrl->catalog, false);
1791
1792        dp_catalog_ctrl_reset(ctrl->catalog);
1793
1794        ret = dp_power_clk_enable(ctrl->power, DP_STREAM_PM, false);
1795        if (ret)
1796                DRM_ERROR("Failed to disable pixel clocks. ret=%d\n", ret);
1797
1798        ret = dp_power_clk_enable(ctrl->power, DP_CTRL_PM, false);
1799        if (ret) {
1800                DRM_ERROR("Failed to disable link clocks. ret=%d\n", ret);
1801        }
1802
1803        phy_power_off(phy);
1804        phy_exit(phy);
1805
1806        DRM_DEBUG_DP("DP off done\n");
1807        return ret;
1808}
1809
1810void dp_ctrl_isr(struct dp_ctrl *dp_ctrl)
1811{
1812        struct dp_ctrl_private *ctrl;
1813        u32 isr;
1814
1815        if (!dp_ctrl)
1816                return;
1817
1818        ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);
1819
1820        isr = dp_catalog_ctrl_get_interrupt(ctrl->catalog);
1821
1822        if (isr & DP_CTRL_INTR_READY_FOR_VIDEO) {
1823                DRM_DEBUG_DP("dp_video_ready\n");
1824                complete(&ctrl->video_comp);
1825        }
1826
1827        if (isr & DP_CTRL_INTR_IDLE_PATTERN_SENT) {
1828                DRM_DEBUG_DP("idle_patterns_sent\n");
1829                complete(&ctrl->idle_comp);
1830        }
1831}
1832
1833struct dp_ctrl *dp_ctrl_get(struct device *dev, struct dp_link *link,
1834                        struct dp_panel *panel, struct drm_dp_aux *aux,
1835                        struct dp_power *power, struct dp_catalog *catalog,
1836                        struct dp_parser *parser)
1837{
1838        struct dp_ctrl_private *ctrl;
1839
1840        if (!dev || !panel || !aux ||
1841            !link || !catalog) {
1842                DRM_ERROR("invalid input\n");
1843                return ERR_PTR(-EINVAL);
1844        }
1845
1846        ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL);
1847        if (!ctrl) {
1848                DRM_ERROR("Mem allocation failure\n");
1849                return ERR_PTR(-ENOMEM);
1850        }
1851
1852        init_completion(&ctrl->idle_comp);
1853        init_completion(&ctrl->video_comp);
1854
1855        /* in parameters */
1856        ctrl->parser   = parser;
1857        ctrl->panel    = panel;
1858        ctrl->power    = power;
1859        ctrl->aux      = aux;
1860        ctrl->link     = link;
1861        ctrl->catalog  = catalog;
1862        ctrl->dev      = dev;
1863
1864        return &ctrl->dp_ctrl;
1865}
1866
1867void dp_ctrl_put(struct dp_ctrl *dp_ctrl)
1868{
1869}
1870