video: tegra: dp: fast LT with platform data
Shu Zhong [Thu, 9 Jul 2015 19:12:14 +0000 (12:12 -0700)]
Updated dp LT driver to perform fast LT with precalibrated settings
from DT.

Bug 200090090

Change-Id: Ie7fa0effe654a2bda7b6686c918c2df95b083395
Signed-off-by: Shu Zhong <shuz@nvidia.com>
Reviewed-on: http://git-master/r/769591
Reviewed-by: Mitch Luban <mluban@nvidia.com>
Tested-by: Mitch Luban <mluban@nvidia.com>

Documentation/devicetree/bindings/video/nvidia,tegra210-dp.txt
arch/arm/mach-tegra/include/mach/dc.h
drivers/video/tegra/dc/dp.c
drivers/video/tegra/dc/dp.h
drivers/video/tegra/dc/dp_lt.c
drivers/video/tegra/dc/dp_lt.h
drivers/video/tegra/dc/of_dc.c

index 6c4a585..550d3fd 100644 (file)
@@ -47,7 +47,10 @@ NVIDIA TEGRA210 DisplayPort
  - nvidia,out-yres: Visible resolution for height.
  Optional properties:
  - is_ext_dp_panel: Specifies whether this is an external panel or an eDP panel.
- - nvidia,link-bw: Specifies the preferred link bandwidth to use for main DP link.
+ - nvidia,enable-fast-lt-pdata: Determines whether DP driver will attempt fast LT with
+   the precalibrated settings listed under the dp-lt-settings node.
+ - nvidia,lanes: Specifies the max lane count to use for main DP link.
+ - nvidia,link-bw: Specifies the max link bandwidth to use for main DP link.
 
  1.B) the dp-lt-settings node:
  The dp-lt-settings node holds link training settings for dp.
@@ -66,8 +69,7 @@ NVIDIA TEGRA210 DisplayPort
    POST_CURSOR2_L1, POST_CURSOR2_L2, or POST_CURSOR2_L3.
  Optional properties:
  - nvidia,tx-pu: Specifies TX_PU value.
- - nvidia,load-adj: Specifies LOADADJ value. Can be 0x3, 0x4, or 0x6.
-
+ - nvidia,load-adj: Specifies LOADADJ value.
 
 Example
 
index 982fc0c..252d5e0 100644 (file)
@@ -1191,9 +1191,10 @@ struct tegra_dc_dp_lt_settings {
 struct tegra_dp_out {
        struct tegra_dc_dp_lt_settings *lt_settings;
        int n_lt_settings;
+       bool enable_fast_lt_pdata;
        bool tx_pu_disable;
-       int lanes;
-       u8 link_bw;
+       int max_n_lanes;
+       u8 max_link_bw;
 };
 
 #ifdef CONFIG_PM_SLEEP
index 07f108a..d30f991 100644 (file)
@@ -716,7 +716,7 @@ int tegra_dc_dp_dpcd_write(struct tegra_dc_dp_data *dp, u32 cmd,
        return ret;
 }
 
-static inline int tegra_dp_dpcd_write_field(struct tegra_dc_dp_data *dp,
+int tegra_dp_dpcd_write_field(struct tegra_dc_dp_data *dp,
                                        u32 cmd, u8 mask, u8 data)
 {
        u8 dpcd_data;
@@ -1297,9 +1297,9 @@ static int tegra_dp_init_max_link_cfg(struct tegra_dc_dp_data *dp,
                        &dpcd_data));
 
                cfg->max_lane_count = dpcd_data & NV_DPCD_MAX_LANE_COUNT_MASK;
-               if (dp->pdata && dp->pdata->lanes &&
-                       dp->pdata->lanes < cfg->max_lane_count)
-                       cfg->max_lane_count = dp->pdata->lanes;
+               if (dp->pdata && dp->pdata->max_n_lanes &&
+                       dp->pdata->max_n_lanes < cfg->max_lane_count)
+                       cfg->max_lane_count = dp->pdata->max_n_lanes;
 
                cfg->tps3_supported =
                (dpcd_data & NV_DPCD_MAX_LANE_COUNT_TPS3_SUPPORTED_YES) ?
@@ -1324,9 +1324,9 @@ static int tegra_dp_init_max_link_cfg(struct tegra_dc_dp_data *dp,
 
                CHECK_RET(tegra_dc_dp_dpcd_read(dp, NV_DPCD_MAX_LINK_BANDWIDTH,
                        &cfg->max_link_bw));
-               if (dp->pdata && dp->pdata->link_bw &&
-                       dp->pdata->link_bw < cfg->max_link_bw)
-                       cfg->max_link_bw = dp->pdata->link_bw;
+               if (dp->pdata && dp->pdata->max_link_bw &&
+                       dp->pdata->max_link_bw < cfg->max_link_bw)
+                       cfg->max_link_bw = dp->pdata->max_link_bw;
 
                CHECK_RET(tegra_dc_dp_dpcd_read(dp, NV_DPCD_EDP_CONFIG_CAP,
                        &dpcd_data));
@@ -1372,15 +1372,6 @@ static int tegra_dc_dp_set_assr(struct tegra_dc_dp_data *dp, bool ena)
        return 0;
 }
 
-
-static int tegra_dp_set_link_bandwidth(struct tegra_dc_dp_data *dp, u8 link_bw)
-{
-       tegra_dc_sor_set_link_bandwidth(dp->sor, link_bw);
-
-       /* Sink side */
-       return tegra_dc_dp_dpcd_write(dp, NV_DPCD_LINK_BANDWIDTH_SET, link_bw);
-}
-
 static int tegra_dp_set_enhanced_framing(struct tegra_dc_dp_data *dp,
                                                bool enable)
 {
@@ -1400,44 +1391,6 @@ static int tegra_dp_set_enhanced_framing(struct tegra_dc_dp_data *dp,
        return 0;
 }
 
-static int tegra_dp_set_lane_count(struct tegra_dc_dp_data *dp, u8 lane_cnt)
-{
-       int ret;
-
-       tegra_sor_power_lanes(dp->sor, lane_cnt, true);
-
-       CHECK_RET(tegra_dp_dpcd_write_field(dp, NV_DPCD_LANE_COUNT_SET,
-                               NV_DPCD_LANE_COUNT_SET_MASK,
-                               lane_cnt));
-
-       return 0;
-}
-
-static void tegra_dp_link_cal(struct tegra_dc_dp_data *dp)
-{
-       struct tegra_dc_sor_data *sor = dp->sor;
-       struct tegra_dc_dp_link_config *cfg = &dp->link_cfg;
-       u32 load_adj;
-
-       switch (cfg->link_bw) {
-       case SOR_LINK_SPEED_G1_62:
-               load_adj = 0x3;
-               break;
-       case SOR_LINK_SPEED_G2_7:
-               load_adj = 0x4;
-               break;
-       case SOR_LINK_SPEED_G5_4:
-               load_adj = 0x6;
-               break;
-       default:
-               BUG();
-       }
-
-       tegra_sor_write_field(sor, NV_SOR_PLL1,
-                       NV_SOR_PLL1_LOADADJ_DEFAULT_MASK,
-                       load_adj << NV_SOR_PLL1_LOADADJ_SHIFT);
-}
-
 static void tegra_dp_irq_evt_worker(struct work_struct *work)
 {
 #define LANE0_1_CR_CE_SL_MASK (0x7 | (0x7 << 4))
@@ -1884,56 +1837,6 @@ void tegra_dp_tpg(struct tegra_dc_dp_data *dp, u32 tp, u32 n_lanes)
        tegra_sor_tpg(dp->sor, tp, n_lanes);
 }
 
-static void tegra_dp_tu_config(struct tegra_dc_dp_data *dp,
-                               const struct tegra_dc_dp_link_config *cfg)
-{
-       struct tegra_dc_sor_data *sor = dp->sor;
-       u32 reg_val;
-
-       tegra_sor_write_field(sor, NV_SOR_DP_LINKCTL(sor->portnum),
-                       NV_SOR_DP_LINKCTL_TUSIZE_MASK,
-                       (cfg->tu_size << NV_SOR_DP_LINKCTL_TUSIZE_SHIFT));
-
-       tegra_sor_write_field(sor, NV_SOR_DP_CONFIG(sor->portnum),
-                               NV_SOR_DP_CONFIG_WATERMARK_MASK,
-                               cfg->watermark);
-
-       tegra_sor_write_field(sor, NV_SOR_DP_CONFIG(sor->portnum),
-                               NV_SOR_DP_CONFIG_ACTIVESYM_COUNT_MASK,
-                               (cfg->active_count <<
-                               NV_SOR_DP_CONFIG_ACTIVESYM_COUNT_SHIFT));
-
-       tegra_sor_write_field(sor, NV_SOR_DP_CONFIG(sor->portnum),
-                               NV_SOR_DP_CONFIG_ACTIVESYM_FRAC_MASK,
-                               (cfg->active_frac <<
-                               NV_SOR_DP_CONFIG_ACTIVESYM_FRAC_SHIFT));
-
-       reg_val = cfg->activepolarity ?
-               NV_SOR_DP_CONFIG_ACTIVESYM_POLARITY_POSITIVE :
-               NV_SOR_DP_CONFIG_ACTIVESYM_POLARITY_NEGATIVE;
-       tegra_sor_write_field(sor, NV_SOR_DP_CONFIG(sor->portnum),
-                               NV_SOR_DP_CONFIG_ACTIVESYM_POLARITY_POSITIVE,
-                               reg_val);
-
-       tegra_sor_write_field(sor, NV_SOR_DP_CONFIG(sor->portnum),
-                               NV_SOR_DP_CONFIG_ACTIVESYM_CNTL_ENABLE,
-                               NV_SOR_DP_CONFIG_ACTIVESYM_CNTL_ENABLE);
-
-       tegra_sor_write_field(sor, NV_SOR_DP_CONFIG(sor->portnum),
-                               NV_SOR_DP_CONFIG_RD_RESET_VAL_NEGATIVE,
-                               NV_SOR_DP_CONFIG_RD_RESET_VAL_NEGATIVE);
-}
-
-void tegra_dp_update_link_config(struct tegra_dc_dp_data *dp)
-{
-       struct tegra_dc_dp_link_config *cfg = &dp->link_cfg;
-
-       tegra_dp_set_link_bandwidth(dp, cfg->link_bw);
-       tegra_dp_set_lane_count(dp, cfg->lane_count);
-       tegra_dp_link_cal(dp);
-       tegra_dp_tu_config(dp, cfg);
-}
-
 static void tegra_dp_hpd_op_edid_ready(void *drv_data)
 {
        struct tegra_dc_dp_data *dp = drv_data;
@@ -2104,20 +2007,15 @@ static void tegra_dc_dp_enable(struct tegra_dc *dc)
                                NV_SOR_DP_CONFIG_IDLE_BEFORE_ATTACH_ENABLE,
                                NV_SOR_DP_CONFIG_IDLE_BEFORE_ATTACH_ENABLE);
 
-       tegra_dp_set_link_bandwidth(dp, cfg->link_bw);
-
        /*
         * enhanced framing enable field shares DPCD offset
         * with lane count set field. Make sure lane count is set
         * before enhanced framing enable. CTS waits on first
         * write to this offset to check for lane count set.
         */
-       tegra_dp_set_lane_count(dp, cfg->lane_count);
+       tegra_dp_update_link_config(dp);
        tegra_dp_set_enhanced_framing(dp, cfg->enhanced_framing);
 
-       tegra_dp_link_cal(dp);
-       tegra_dp_tu_config(dp, cfg);
-
        tegra_dp_tpg(dp, TRAINING_PATTERN_DISABLE, cfg->lane_count);
 
        tegra_sor_port_enable(sor, true);
index 717e668..6120dd6 100644 (file)
@@ -94,6 +94,8 @@ struct tegra_dc_dp_data {
        struct tegra_prod_list *prod_list;
 };
 
+int tegra_dp_dpcd_write_field(struct tegra_dc_dp_data *dp, u32 cmd,
+       u8 mask, u8 data);
 int tegra_dc_dpaux_read(struct tegra_dc_dp_data *dp, u32 cmd, u32 addr,
        u8 *data, u32 *size, u32 *aux_stat);
 int tegra_dc_dpaux_write(struct tegra_dc_dp_data *dp, u32 cmd, u32 addr,
@@ -105,7 +107,6 @@ int tegra_dc_dpaux_read_chunk_locked(struct tegra_dc_dp_data *dp,
        u32 cmd, u32 addr, u8 *data, u32 *size, u32 *aux_stat);
 int tegra_dc_dpaux_write_chunk_locked(struct tegra_dc_dp_data *dp,
        u32 cmd, u32 addr, u8 *data, u32 *size, u32 *aux_stat);
-void tegra_dp_update_link_config(struct tegra_dc_dp_data *dp);
 int tegra_dc_dp_dpcd_read(struct tegra_dc_dp_data *dp, u32 cmd, u8 *data_ptr);
 int tegra_dc_dp_dpcd_write(struct tegra_dc_dp_data *dp, u32 cmd, u8 data);
 void tegra_dp_tpg(struct tegra_dc_dp_data *dp, u32 tp, u32 n_lanes);
index 6cd9e2d..ce6223d 100644 (file)
@@ -230,6 +230,103 @@ static void get_lt_new_config(struct tegra_dp_lt_data *lt_data)
                        cnt, vs[cnt], pe[cnt], pc_supported ? pc[cnt] : 0);
 }
 
+static int tegra_dp_set_link_bandwidth(struct tegra_dc_dp_data *dp, u8 link_bw)
+{
+       tegra_dc_sor_set_link_bandwidth(dp->sor, link_bw);
+
+       /* Sink side */
+       return tegra_dc_dp_dpcd_write(dp, NV_DPCD_LINK_BANDWIDTH_SET, link_bw);
+}
+
+static int tegra_dp_set_lane_count(struct tegra_dc_dp_data *dp, u8 lane_cnt)
+{
+       int ret;
+
+       tegra_sor_power_lanes(dp->sor, lane_cnt, true);
+
+       CHECK_RET(tegra_dp_dpcd_write_field(dp, NV_DPCD_LANE_COUNT_SET,
+                               NV_DPCD_LANE_COUNT_SET_MASK,
+                               lane_cnt));
+
+       return 0;
+}
+
+static void tegra_dp_link_cal(struct tegra_dc_dp_data *dp)
+{
+       struct tegra_dc_sor_data *sor = dp->sor;
+       struct tegra_dc_dp_link_config *cfg = &dp->link_cfg;
+       u32 load_adj = dp->lt_data.load_adj;
+
+       if (load_adj == UINT_MAX)
+               switch (cfg->link_bw) {
+               case SOR_LINK_SPEED_G1_62:
+                       load_adj = 0x3;
+                       break;
+               case SOR_LINK_SPEED_G2_7:
+                       load_adj = 0x4;
+                       break;
+               case SOR_LINK_SPEED_G5_4:
+                       load_adj = 0x6;
+                       break;
+               default:
+                       BUG();
+               }
+
+       tegra_sor_write_field(sor, NV_SOR_PLL1,
+                       NV_SOR_PLL1_LOADADJ_DEFAULT_MASK,
+                       load_adj << NV_SOR_PLL1_LOADADJ_SHIFT);
+}
+
+static void tegra_dp_tu_config(struct tegra_dc_dp_data *dp,
+                               const struct tegra_dc_dp_link_config *cfg)
+{
+       struct tegra_dc_sor_data *sor = dp->sor;
+       u32 reg_val;
+
+       tegra_sor_write_field(sor, NV_SOR_DP_LINKCTL(sor->portnum),
+                       NV_SOR_DP_LINKCTL_TUSIZE_MASK,
+                       (cfg->tu_size << NV_SOR_DP_LINKCTL_TUSIZE_SHIFT));
+
+       tegra_sor_write_field(sor, NV_SOR_DP_CONFIG(sor->portnum),
+                               NV_SOR_DP_CONFIG_WATERMARK_MASK,
+                               cfg->watermark);
+
+       tegra_sor_write_field(sor, NV_SOR_DP_CONFIG(sor->portnum),
+                               NV_SOR_DP_CONFIG_ACTIVESYM_COUNT_MASK,
+                               (cfg->active_count <<
+                               NV_SOR_DP_CONFIG_ACTIVESYM_COUNT_SHIFT));
+
+       tegra_sor_write_field(sor, NV_SOR_DP_CONFIG(sor->portnum),
+                               NV_SOR_DP_CONFIG_ACTIVESYM_FRAC_MASK,
+                               (cfg->active_frac <<
+                               NV_SOR_DP_CONFIG_ACTIVESYM_FRAC_SHIFT));
+
+       reg_val = cfg->activepolarity ?
+               NV_SOR_DP_CONFIG_ACTIVESYM_POLARITY_POSITIVE :
+               NV_SOR_DP_CONFIG_ACTIVESYM_POLARITY_NEGATIVE;
+       tegra_sor_write_field(sor, NV_SOR_DP_CONFIG(sor->portnum),
+                               NV_SOR_DP_CONFIG_ACTIVESYM_POLARITY_POSITIVE,
+                               reg_val);
+
+       tegra_sor_write_field(sor, NV_SOR_DP_CONFIG(sor->portnum),
+                               NV_SOR_DP_CONFIG_ACTIVESYM_CNTL_ENABLE,
+                               NV_SOR_DP_CONFIG_ACTIVESYM_CNTL_ENABLE);
+
+       tegra_sor_write_field(sor, NV_SOR_DP_CONFIG(sor->portnum),
+                               NV_SOR_DP_CONFIG_RD_RESET_VAL_NEGATIVE,
+                               NV_SOR_DP_CONFIG_RD_RESET_VAL_NEGATIVE);
+}
+
+void tegra_dp_update_link_config(struct tegra_dc_dp_data *dp)
+{
+       struct tegra_dc_dp_link_config *cfg = &dp->link_cfg;
+
+       tegra_dp_set_link_bandwidth(dp, cfg->link_bw);
+       tegra_dp_set_lane_count(dp, cfg->lane_count);
+       tegra_dp_link_cal(dp);
+       tegra_dp_tu_config(dp, cfg);
+}
+
 static void set_tx_pu(struct tegra_dp_lt_data *lt_data)
 {
        struct tegra_dc_dp_data *dp = lt_data->dp;
@@ -250,21 +347,24 @@ static void set_tx_pu(struct tegra_dp_lt_data *lt_data)
                return;
        }
 
-       for (; cnt < n_lanes; cnt++) {
-               max_tx_pu = (max_tx_pu <
-                       tegra_dp_tx_pu[pc[cnt]][vs[cnt]][pe[cnt]]) ?
-                       tegra_dp_tx_pu[pc[cnt]][vs[cnt]][pe[cnt]] :
-                       max_tx_pu;
+       if (lt_data->tx_pu == UINT_MAX) {
+               for (; cnt < n_lanes; cnt++) {
+                       max_tx_pu = (max_tx_pu <
+                               tegra_dp_tx_pu[pc[cnt]][vs[cnt]][pe[cnt]]) ?
+                               tegra_dp_tx_pu[pc[cnt]][vs[cnt]][pe[cnt]] :
+                               max_tx_pu;
+               }
+
+               lt_data->tx_pu = max_tx_pu;
        }
 
-       lt_data->tx_pu = max_tx_pu;
        tegra_sor_write_field(sor, NV_SOR_DP_PADCTL(sor->portnum),
                                NV_SOR_DP_PADCTL_TX_PU_VALUE_DEFAULT_MASK,
-                               (max_tx_pu <<
+                               (lt_data->tx_pu <<
                                NV_SOR_DP_PADCTL_TX_PU_VALUE_SHIFT |
                                NV_SOR_DP_PADCTL_TX_PU_ENABLE));
 
-       pr_info("dp lt: tx_pu: 0x%x\n", max_tx_pu);
+       pr_info("dp lt: tx_pu: 0x%x\n", lt_data->tx_pu);
 }
 
 /*
@@ -409,13 +509,12 @@ static int do_fast_lt_no_handshake(struct tegra_dp_lt_data *lt_data)
        return 0;
 }
 
-__maybe_unused
 static int do_fast_lt_handshake(struct tegra_dp_lt_data *lt_data)
 {
        bool cr_done;
        bool lt_done;
 
-       BUG_ON(!lt_data->lt_config_valid);
+       set_lt_config(lt_data);
 
        set_lt_tpg(lt_data, TRAINING_PATTERN_1);
 
@@ -446,7 +545,8 @@ static void lt_data_sw_reset(struct tegra_dp_lt_data *lt_data)
        lt_data->lt_config_valid = false;
        lt_data->cr_retry = 0;
        lt_data->ce_retry = 0;
-       lt_data->tx_pu = 0;
+       lt_data->tx_pu = UINT_MAX;
+       lt_data->load_adj = UINT_MAX;
        lt_data->n_lanes = dp->link_cfg.lane_count;
        lt_data->link_bw = dp->link_cfg.link_bw;
        lt_data->no_aux_handshake = dp->link_cfg.support_fast_lt;
@@ -480,6 +580,52 @@ static void lt_data_reset(struct tegra_dp_lt_data *lt_data)
        }
 }
 
+static void get_lt_config_from_dt(struct tegra_dp_lt_data *lt_data,
+       struct tegra_dc_dp_lt_settings *lt)
+{
+       struct tegra_dc_dp_data *dp = lt_data->dp;
+       size_t copy_bytes = sizeof(lt->post_cursor[0]) * 4;
+
+       mutex_lock(&lt_data->lock);
+
+       lt_data_reset(lt_data);
+       lt_data->tx_pu = lt->tx_pu;
+       lt_data->load_adj = lt->load_adj;
+       tegra_dp_link_cal(dp);
+
+       memcpy(lt_data->pre_emphasis, lt->lane_preemphasis,
+               copy_bytes);
+       memcpy(lt_data->drive_current, lt->drive_current,
+               copy_bytes);
+       memcpy(lt_data->post_cursor2, lt->post_cursor,
+               copy_bytes);
+
+       mutex_unlock(&lt_data->lock);
+}
+
+static int do_fast_lt_with_pdata(struct tegra_dp_lt_data *lt_data)
+{
+       struct tegra_dc_dp_data *dp = lt_data->dp;
+       struct tegra_dp_out *dp_pdata = dp->pdata;
+       struct tegra_dc_dp_link_config *cfg = &dp->link_cfg;
+       size_t cnt = 0;
+       bool fast_lt_passed = false;
+
+       for (; cnt < dp_pdata->n_lt_settings && !fast_lt_passed; cnt++) {
+               get_lt_config_from_dt(lt_data, &dp_pdata->lt_settings[cnt]);
+               if (do_fast_lt_handshake(lt_data) != -EINVAL)
+                       fast_lt_passed = true;
+       }
+
+       if (!fast_lt_passed) {
+               *cfg = dp->max_link_cfg;
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+
 static void set_lt_tpg(struct tegra_dp_lt_data *lt_data, u32 tp)
 {
        bool cur_hpd = tegra_dc_hpd(lt_data->dp->dc);
@@ -568,7 +714,8 @@ static void lt_reset_state(struct tegra_dp_lt_data *lt_data)
        tegra_dc_sor_detach(sor);
        mutex_unlock(&lt_data->lock);
 
-       if (lt_data->lt_config_valid && lt_data->no_aux_handshake) {
+       if ((lt_data->lt_config_valid && lt_data->no_aux_handshake) ||
+               (dp->pdata && dp->pdata->enable_fast_lt_pdata)) {
                tgt_state = STATE_FAST_LT;
                timeout = 0;
        } else {
@@ -604,7 +751,8 @@ static void fast_lt_state(struct tegra_dp_lt_data *lt_data)
        dp = lt_data->dp;
        sor = dp->sor;
 
-       BUG_ON(!lt_data->no_aux_handshake);
+       BUG_ON(!lt_data->no_aux_handshake &&
+               (dp->pdata && !dp->pdata->enable_fast_lt_pdata));
 
        cur_hpd = tegra_dc_hpd(dp->dc);
        if (!cur_hpd) {
@@ -616,12 +764,20 @@ static void fast_lt_state(struct tegra_dp_lt_data *lt_data)
                goto done;
        }
 
-       do_fast_lt_no_handshake(lt_data);
+       if (lt_data->no_aux_handshake)
+               do_fast_lt_no_handshake(lt_data);
+       else
+               do_fast_lt_with_pdata(lt_data);
+
        lt_status = get_lt_status(lt_data);
        if (lt_status) {
                lt_passed(lt_data);
                tgt_state = STATE_DONE_PASS;
                timeout = -1;
+       } else if (!lt_data->no_aux_handshake) {
+               lt_failed(lt_data);
+               tgt_state = STATE_DONE_FAIL;
+               timeout = -1;
        } else {
                lt_data_reset(lt_data);
                tgt_state = STATE_CLOCK_RECOVERY;
index 4f8796a..efaba32 100644 (file)
@@ -63,6 +63,7 @@ struct tegra_dp_lt_data {
        u32 pre_emphasis[4]; /* post cursor1 */
        u32 post_cursor2[4];
        u32 tx_pu;
+       u32 load_adj;
        u32 n_lanes;
        u32 link_bw;
 
@@ -280,6 +281,7 @@ static inline int tegra_dp_is_max_pc(u32 pc)
        return pc >= POST_CURSOR2_L3;
 }
 
+void tegra_dp_update_link_config(struct tegra_dc_dp_data *dp);
 void tegra_dp_lt_init(struct tegra_dp_lt_data *lt_data,
                        struct tegra_dc_dp_data *dp);
 void tegra_dp_lt_set_pending_evt(struct tegra_dp_lt_data *lt_data);
index 438dfc3..d1a71c8 100644 (file)
@@ -1632,10 +1632,14 @@ static int parse_lt_setting(struct device_node *np,
        if (!of_property_read_u32(np, "nvidia,tx-pu", &temp)) {
                lt_setting_addr->tx_pu = (u32)temp;
                OF_DC_LOG("tx_pu %d\n", temp);
+       } else {
+               lt_setting_addr->tx_pu = UINT_MAX;
        }
        if (!of_property_read_u32(np, "nvidia,load-adj", &temp)) {
                lt_setting_addr->load_adj = (u32)temp;
                OF_DC_LOG("load_adj %d\n", temp);
+       } else {
+               lt_setting_addr->load_adj = UINT_MAX;
        }
        return 0;
 }
@@ -1664,12 +1668,19 @@ static struct device_node *parse_dp_settings(struct platform_device *ndev,
                return NULL;
        }
 
-       np_dp_lt_set =
-               of_get_child_by_name(np_dp_panel,
+       if (!of_property_read_u32(np_dp_panel,
+                       "nvidia,enable-fast-lt-pdata", &temp)) {
+               dpout->enable_fast_lt_pdata = (bool)temp;
+               OF_DC_LOG("enable_fast_lt_pdata %d\n",
+               dpout->enable_fast_lt_pdata);
+       }
+
+       if (dpout->enable_fast_lt_pdata)
+               np_dp_lt_set = of_get_child_by_name(np_dp_panel,
                "dp-lt-settings");
 
        if (!np_dp_lt_set) {
-               pr_info("%s: No dp-lt-settings node\n",
+               pr_info("%s: dp-lt-settings node not parsed\n",
                        __func__);
        } else {
                int n_lt_settings =
@@ -1704,16 +1715,16 @@ static struct device_node *parse_dp_settings(struct platform_device *ndev,
        }
        if (!of_property_read_u32(np_dp_panel,
                        "nvidia,lanes", &temp)) {
-               dpout->lanes = (int)temp;
-               OF_DC_LOG("lanes %d\n", dpout->lanes);
+               dpout->max_n_lanes = (int)temp;
+               OF_DC_LOG("lanes %d\n", dpout->max_n_lanes);
        } else {
-               dpout->lanes = 4;
-               OF_DC_LOG("default lanes %d\n", dpout->lanes);
+               dpout->max_n_lanes = 4;
+               OF_DC_LOG("default lanes %d\n", dpout->max_n_lanes);
        }
        if (!of_property_read_u32(np_dp_panel,
                        "nvidia,link-bw", &temp)) {
-               dpout->link_bw = (u8)temp;
-               OF_DC_LOG("link_bw %d\n", dpout->link_bw);
+               dpout->max_link_bw = (u8)temp;
+               OF_DC_LOG("link_bw %d\n", dpout->max_link_bw);
        }
 
        of_node_put(np_dp_lt_set);