Lines Matching +full:preemphasis +full:- +full:width

2  * Copyright (c) 2011-2013, NVIDIA Corporation.
5 * SPDX-License-Identifier: GPL-2.0
15 #include <asm/arch-tegra/dc.h>
30 * struct tegra_dp_priv - private displayport driver info
46 return readl((u32 *)dp->regs + reg); in tegra_dpaux_readl()
52 writel(val, (u32 *)dp->regs + reg); in tegra_dpaux_writel()
67 timeout_us -= poll_interval_us; in tegra_dc_dpaux_poll_register()
88 return -1; in tegra_dpaux_wait_transaction()
104 return -1; /* only write one chunk of data */ in tegra_dc_dpaux_write_chunk()
114 return -EINVAL; in tegra_dc_dpaux_write_chunk()
128 reg_val |= ((*size - 1) << DPAUX_DP_AUXCTL_CMDLEN_SHIFT); in tegra_dc_dpaux_write_chunk()
147 if (timeout_retries-- > 0) { in tegra_dc_dpaux_write_chunk()
148 debug("dp: aux write retry (0x%x) -- %d\n", in tegra_dc_dpaux_write_chunk()
157 return -ETIMEDOUT; in tegra_dc_dpaux_write_chunk()
163 if (defer_retries-- > 0) { in tegra_dc_dpaux_write_chunk()
164 debug("dp: aux write defer (0x%x) -- %d\n", in tegra_dc_dpaux_write_chunk()
173 return -ETIMEDOUT; in tegra_dc_dpaux_write_chunk()
183 return -EIO; in tegra_dc_dpaux_write_chunk()
187 return -EIO; in tegra_dc_dpaux_write_chunk()
200 return -EIO; /* only read one chunk */ in tegra_dc_dpaux_read_chunk()
212 return -EIO; in tegra_dc_dpaux_read_chunk()
218 return -EIO; in tegra_dc_dpaux_read_chunk()
227 reg_val |= ((*size - 1) << DPAUX_DP_AUXCTL_CMDLEN_SHIFT); in tegra_dc_dpaux_read_chunk()
245 if (timeout_retries-- > 0) { in tegra_dc_dpaux_read_chunk()
246 debug("dp: aux read retry (0x%x) -- %d\n", in tegra_dc_dpaux_read_chunk()
255 return -ETIMEDOUT; in tegra_dc_dpaux_read_chunk()
261 if (defer_retries-- > 0) { in tegra_dc_dpaux_read_chunk()
262 debug("dp: aux read defer (0x%x) -- %d\n", in tegra_dc_dpaux_read_chunk()
271 return -ETIMEDOUT; in tegra_dc_dpaux_read_chunk()
290 return -EIO; in tegra_dc_dpaux_read_chunk()
296 return -EIO; in tegra_dc_dpaux_read_chunk()
307 cur_size = *size - finished; in tegra_dc_dpaux_read()
368 u32 cur_size = min((u32)DP_AUX_MAX_BYTES, size - finished); in tegra_dc_i2c_aux_read()
420 link_cfg->max_lane_count); in tegra_dc_dp_dump_link_cfg()
422 link_cfg->support_enhanced_framing ? "Y" : "N"); in tegra_dc_dp_dump_link_cfg()
424 link_cfg->max_link_bw); in tegra_dc_dp_dump_link_cfg()
426 link_cfg->bits_per_pixel); in tegra_dc_dp_dump_link_cfg()
428 link_cfg->enhanced_framing ? "Y" : "N"); in tegra_dc_dp_dump_link_cfg()
430 link_cfg->scramble_ena ? "Y" : "N"); in tegra_dc_dp_dump_link_cfg()
432 link_cfg->link_bw); in tegra_dc_dp_dump_link_cfg()
434 link_cfg->lane_count); in tegra_dc_dp_dump_link_cfg()
436 link_cfg->activepolarity); in tegra_dc_dp_dump_link_cfg()
438 link_cfg->active_count); in tegra_dc_dp_dump_link_cfg()
440 link_cfg->tu_size); in tegra_dc_dp_dump_link_cfg()
442 link_cfg->active_frac); in tegra_dc_dp_dump_link_cfg()
444 link_cfg->watermark); in tegra_dc_dp_dump_link_cfg()
446 link_cfg->hblank_sym); in tegra_dc_dp_dump_link_cfg()
448 link_cfg->vblank_sym); in tegra_dc_dp_dump_link_cfg()
455 switch (cfg->link_bw) { in _tegra_dp_lower_link_config()
457 if (cfg->max_link_bw > SOR_LINK_SPEED_G1_62) in _tegra_dp_lower_link_config()
458 cfg->link_bw = SOR_LINK_SPEED_G2_7; in _tegra_dp_lower_link_config()
459 cfg->lane_count /= 2; in _tegra_dp_lower_link_config()
462 cfg->link_bw = SOR_LINK_SPEED_G1_62; in _tegra_dp_lower_link_config()
465 if (cfg->lane_count == 1) { in _tegra_dp_lower_link_config()
466 cfg->link_bw = SOR_LINK_SPEED_G2_7; in _tegra_dp_lower_link_config()
467 cfg->lane_count = cfg->max_lane_count; in _tegra_dp_lower_link_config()
469 cfg->lane_count /= 2; in _tegra_dp_lower_link_config()
473 debug("dp: Error link rate %d\n", cfg->link_bw); in _tegra_dp_lower_link_config()
474 return -ENOLINK; in _tegra_dp_lower_link_config()
477 return (cfg->lane_count > 0) ? 0 : -ENOLINK; in _tegra_dp_lower_link_config()
482 * Return 0 if mode is possible, -1 otherwise
488 const u32 link_rate = 27 * link_cfg->link_bw * 1000 * 1000; in tegra_dc_dp_calc_config()
510 if (!link_rate || !link_cfg->lane_count || !timing->pixelclock.typ || in tegra_dc_dp_calc_config()
511 !link_cfg->bits_per_pixel) in tegra_dc_dp_calc_config()
512 return -1; in tegra_dc_dp_calc_config()
514 if ((u64)timing->pixelclock.typ * link_cfg->bits_per_pixel >= in tegra_dc_dp_calc_config()
515 (u64)link_rate * 8 * link_cfg->lane_count) in tegra_dc_dp_calc_config()
516 return -1; in tegra_dc_dp_calc_config()
518 num_linkclk_line = (u32)(lldiv(link_rate * timing->hactive.typ, in tegra_dc_dp_calc_config()
519 timing->pixelclock.typ)); in tegra_dc_dp_calc_config()
521 ratio_f = (u64)timing->pixelclock.typ * link_cfg->bits_per_pixel * f; in tegra_dc_dp_calc_config()
523 do_div(ratio_f, link_rate * link_cfg->lane_count); in tegra_dc_dp_calc_config()
525 for (i = 64; i >= 32; --i) { in tegra_dc_dp_calc_config()
528 frac_f = activesym_f - activecount_f; in tegra_dc_dp_calc_config()
535 frac_f = f - frac_f; in tegra_dc_dp_calc_config()
539 /* warning: frac_f should be 64-bit */ in tegra_dc_dp_calc_config()
554 (activecount_f + (activefrac * f - f) * f), in tegra_dc_dp_calc_config()
564 lldiv(approx_value_f - activesym_f, i); in tegra_dc_dp_calc_config()
568 lldiv(activesym_f - approx_value_f, i); in tegra_dc_dp_calc_config()
586 link_cfg->activepolarity = 0; in tegra_dc_dp_calc_config()
587 link_cfg->active_count = lowest_neg_activepolarity ? in tegra_dc_dp_calc_config()
588 lowest_neg_activecount : lowest_neg_activecount - 1; in tegra_dc_dp_calc_config()
589 link_cfg->tu_size = lowest_neg_tusize; in tegra_dc_dp_calc_config()
590 link_cfg->active_frac = 1; in tegra_dc_dp_calc_config()
592 link_cfg->activepolarity = lowest_neg_activepolarity; in tegra_dc_dp_calc_config()
593 link_cfg->active_count = (u32)lowest_neg_activecount; in tegra_dc_dp_calc_config()
594 link_cfg->tu_size = lowest_neg_tusize; in tegra_dc_dp_calc_config()
595 link_cfg->active_frac = (u32)lowest_neg_activefrac; in tegra_dc_dp_calc_config()
598 watermark_f = lldiv(ratio_f * link_cfg->tu_size * (f - ratio_f), f); in tegra_dc_dp_calc_config()
599 link_cfg->watermark = (u32)(lldiv(watermark_f + lowest_neg_error_f, in tegra_dc_dp_calc_config()
600 f)) + link_cfg->bits_per_pixel / 4 - 1; in tegra_dc_dp_calc_config()
601 num_symbols_per_line = (timing->hactive.typ * in tegra_dc_dp_calc_config()
602 link_cfg->bits_per_pixel) / in tegra_dc_dp_calc_config()
603 (8 * link_cfg->lane_count); in tegra_dc_dp_calc_config()
605 if (link_cfg->watermark > 30) { in tegra_dc_dp_calc_config()
607 link_cfg->watermark = 30; in tegra_dc_dp_calc_config()
608 return -1; in tegra_dc_dp_calc_config()
609 } else if (link_cfg->watermark > num_symbols_per_line) { in tegra_dc_dp_calc_config()
611 link_cfg->watermark = num_symbols_per_line; in tegra_dc_dp_calc_config()
612 return -1; in tegra_dc_dp_calc_config()
617 * # symbols/hblank = ((SetRasterBlankEnd.X + SetRasterSize.Width - in tegra_dc_dp_calc_config()
618 * SetRasterBlankStart.X - 7) * link_clk / pclk) in tegra_dc_dp_calc_config()
619 * - 3 * enhanced_framing - Y in tegra_dc_dp_calc_config()
622 link_cfg->hblank_sym = (int)lldiv(((uint64_t)timing->hback_porch.typ + in tegra_dc_dp_calc_config()
623 timing->hfront_porch.typ + timing->hsync_len.typ - 7) * in tegra_dc_dp_calc_config()
624 link_rate, timing->pixelclock.typ) - in tegra_dc_dp_calc_config()
625 3 * link_cfg->enhanced_framing - in tegra_dc_dp_calc_config()
626 (12 / link_cfg->lane_count); in tegra_dc_dp_calc_config()
628 if (link_cfg->hblank_sym < 0) in tegra_dc_dp_calc_config()
629 link_cfg->hblank_sym = 0; in tegra_dc_dp_calc_config()
634 * # symbols/vblank = ((SetRasterBlankStart.X - in tegra_dc_dp_calc_config()
635 * SetRasterBlankEen.X - 25) * link_clk / pclk) in tegra_dc_dp_calc_config()
636 * - Y - 1; in tegra_dc_dp_calc_config()
639 link_cfg->vblank_sym = (int)lldiv(((uint64_t)timing->hactive.typ - 25) in tegra_dc_dp_calc_config()
640 * link_rate, timing->pixelclock.typ) - (36 / in tegra_dc_dp_calc_config()
641 link_cfg->lane_count) - 4; in tegra_dc_dp_calc_config()
643 if (link_cfg->vblank_sym < 0) in tegra_dc_dp_calc_config()
644 link_cfg->vblank_sym = 0; in tegra_dc_dp_calc_config()
646 link_cfg->is_valid = 1; in tegra_dc_dp_calc_config()
660 const int preemphasis = 0x0f0f0f0f; in tegra_dc_dp_init_max_link_cfg() local
668 link_cfg->max_lane_count = dpcd_data & DP_MAX_LANE_COUNT_MASK; in tegra_dc_dp_init_max_link_cfg()
669 link_cfg->tps3_supported = (dpcd_data & in tegra_dc_dp_init_max_link_cfg()
672 link_cfg->support_enhanced_framing = in tegra_dc_dp_init_max_link_cfg()
679 link_cfg->downspread = (dpcd_data & DP_MAX_DOWNSPREAD_VAL_0_5_PCT) ? in tegra_dc_dp_init_max_link_cfg()
683 &link_cfg->aux_rd_interval); in tegra_dc_dp_init_max_link_cfg()
687 &link_cfg->max_link_bw); in tegra_dc_dp_init_max_link_cfg()
693 * Will be re-programmed when dp is enabled. in tegra_dc_dp_init_max_link_cfg()
695 link_cfg->drive_current = drive_current; in tegra_dc_dp_init_max_link_cfg()
696 link_cfg->preemphasis = preemphasis; in tegra_dc_dp_init_max_link_cfg()
697 link_cfg->postcursor = postcursor; in tegra_dc_dp_init_max_link_cfg()
703 link_cfg->alt_scramber_reset_cap = in tegra_dc_dp_init_max_link_cfg()
706 link_cfg->only_enhanced_framing = in tegra_dc_dp_init_max_link_cfg()
710 link_cfg->lane_count = link_cfg->max_lane_count; in tegra_dc_dp_init_max_link_cfg()
711 link_cfg->link_bw = link_cfg->max_link_bw; in tegra_dc_dp_init_max_link_cfg()
712 link_cfg->enhanced_framing = link_cfg->support_enhanced_framing; in tegra_dc_dp_init_max_link_cfg()
713 link_cfg->frame_in_ms = (1000 / 60) + 1; in tegra_dc_dp_init_max_link_cfg()
756 dpcd_data = link_cfg->lane_count; in tegra_dp_set_lane_count()
757 if (link_cfg->enhanced_framing) in tegra_dp_set_lane_count()
763 tegra_dc_sor_set_lane_count(sor, link_cfg->lane_count); in tegra_dp_set_lane_count()
777 for (lane = 0; lane < cfg->lane_count; ++lane) { in tegra_dc_dp_link_trained()
791 return -1; in tegra_dc_dp_link_trained()
800 u32 n_lanes = cfg->lane_count; in tegra_dp_channel_eq_status()
824 return -EIO; in tegra_dp_channel_eq_status()
837 return ce_done ? 0 : -EIO; in tegra_dp_channel_eq_status()
844 u32 n_lanes = cfg->lane_count; in tegra_dp_clock_recovery_status()
871 u32 n_lanes = cfg->lane_count; in tegra_dp_lt_adjust()
909 if (!cfg->aux_rd_interval) in tegra_dp_wait_aux_training()
912 mdelay(cfg->aux_rd_interval * 4); in tegra_dp_wait_aux_training()
922 tegra_dc_sor_set_dp_linkctl(dp->sor, 1, tp, cfg); in tegra_dp_tpg()
933 if (link_cfg->lane_count == 0) { in tegra_dp_link_config()
935 return -ENOLINK; in tegra_dp_link_config()
947 for (retry = 3; retry > 0; --retry) { in tegra_dp_link_config()
960 if (link_cfg->alt_scramber_reset_cap) { in tegra_dp_link_config()
961 ret = tegra_dc_dp_set_assr(dp, dp->sor, 1); in tegra_dp_link_config()
966 ret = tegra_dp_set_link_bandwidth(dp, dp->sor, link_cfg->link_bw); in tegra_dp_link_config()
971 ret = tegra_dp_set_lane_count(dp, link_cfg, dp->sor); in tegra_dp_link_config()
976 tegra_dc_sor_set_dp_linkctl(dp->sor, 1, training_pattern_none, in tegra_dp_link_config()
990 cfg->is_valid = 0; in tegra_dp_lower_link_config()
1011 struct udevice *sor = dp->sor; in tegra_dp_lt_config()
1012 u32 n_lanes = cfg->lane_count; in tegra_dp_lt_config()
1013 u8 pc_supported = cfg->tps3_supported; in tegra_dp_lt_config()
1041 return -EINVAL; in tegra_dp_lt_config()
1053 tegra_dp_disable_tx_pu(dp->sor); in tegra_dp_lt_config()
1122 return -EIO; in _tegra_dp_channel_eq()
1129 u32 n_lanes = cfg->lane_count; in tegra_dp_channel_eq()
1130 u8 pc_supported = cfg->tps3_supported; in tegra_dp_channel_eq()
1170 return -EIO; in _tegra_dp_clk_recovery()
1177 u32 n_lanes = cfg->lane_count; in tegra_dp_clk_recovery()
1178 u8 pc_supported = cfg->tps3_supported; in tegra_dp_clk_recovery()
1195 struct udevice *sor = dp->sor; in tegra_dc_dp_full_link_training()
1247 u32 mask = 0xffff >> ((4 - link_cfg->lane_count) * 4); in tegra_dc_dp_fast_link_training()
1258 for (j = 0; j < link_cfg->lane_count; ++j) in tegra_dc_dp_fast_link_training()
1269 return -EFAULT; in tegra_dc_dp_fast_link_training()
1273 tegra_dc_dp_set_assr(dp, sor, link_cfg->scramble_ena); in tegra_dc_dp_fast_link_training()
1277 link_cfg->link_bw == 20 ? 0x23 : 0x22); in tegra_dc_dp_fast_link_training()
1278 for (j = 0; j < link_cfg->lane_count; ++j) in tegra_dc_dp_fast_link_training()
1287 return -EFAULT; in tegra_dc_dp_fast_link_training()
1298 return -EFAULT; in tegra_dc_dp_fast_link_training()
1302 link_cfg->link_bw, link_cfg->lane_count); in tegra_dc_dp_fast_link_training()
1322 * set to a known-good drive setting if fast link in tegra_dp_do_link_training()
1325 ret = tegra_dc_sor_set_voltage_swing(dp->sor, link_cfg); in tegra_dp_do_link_training()
1330 ret = -ENOSYS; in tegra_dp_do_link_training()
1344 if ((link_cfg->link_bw == link_bw) && in tegra_dp_do_link_training()
1345 (link_cfg->lane_count == lane_count)) in tegra_dp_do_link_training()
1348 return -EFAULT; in tegra_dp_do_link_training()
1358 if (!timing->pixelclock.typ || !timing->hactive.typ || in tegra_dc_dp_explore_link_cfg()
1359 !timing->vactive.typ) { in tegra_dc_dp_explore_link_cfg()
1361 return -EINVAL; in tegra_dc_dp_explore_link_cfg()
1363 if (!link_cfg->max_link_bw || !link_cfg->max_lane_count) { in tegra_dc_dp_explore_link_cfg()
1365 return -EINVAL; in tegra_dc_dp_explore_link_cfg()
1368 link_cfg->is_valid = 0; in tegra_dc_dp_explore_link_cfg()
1384 return link_cfg->is_valid ? 0 : -EFAULT; in tegra_dc_dp_explore_link_cfg()
1401 return -EIO; in tegra_dp_hpd_plug()
1444 if (!tegra_dc_dp_sink_out_of_sync(dp, link_cfg->frame_in_ms * in tegra_dc_dp_check_sink()
1449 if (!retries--) { in tegra_dc_dp_check_sink()
1451 return -EIO; in tegra_dc_dp_check_sink()
1453 ret = tegra_dc_sor_detach(dp->dc_dev, dp->sor); in tegra_dc_dp_check_sink()
1456 if (tegra_dc_dp_explore_link_cfg(dp, link_cfg, dp->sor, in tegra_dc_dp_check_sink()
1462 tegra_dc_sor_set_power_state(dp->sor, 1); in tegra_dc_dp_check_sink()
1463 tegra_dc_sor_attach(dp->dc_dev, dp->sor, link_cfg, timing); in tegra_dc_dp_check_sink()
1482 link_cfg->is_valid = 0; in tegra_dp_enable()
1483 link_cfg->scramble_ena = 1; in tegra_dp_enable()
1489 return -EIO; in tegra_dp_enable()
1492 link_cfg->bits_per_pixel = panel_bpp; in tegra_dp_enable()
1495 return -ENOLINK; in tegra_dp_enable()
1503 priv->sor = sor; in tegra_dp_enable()
1519 return -ENETUNREACH; in tegra_dp_enable()
1527 return -ENXIO; in tegra_dp_enable()
1531 if (tegra_dc_dp_dpcd_read(priv, DP_DPCD_REV, &priv->revision)) { in tegra_dp_enable()
1533 return -EIO; in tegra_dp_enable()
1538 return -ENOMEDIUM; in tegra_dp_enable()
1542 ret = tegra_dc_sor_attach(priv->dc_dev, sor, link_cfg, timing); in tegra_dp_enable()
1543 if (ret && ret != -EEXIST) in tegra_dp_enable()
1556 /* Power down the unused lanes to save power - a few hundred mW */ in tegra_dp_enable()
1565 priv->enabled = true; in tegra_dp_enable()
1574 plat->base = dev_read_addr(dev); in tegra_dp_ofdata_to_platdata()
1602 priv->regs = (struct dpaux_ctlr *)plat->base; in dp_tegra_probe()
1603 priv->enabled = false; in dp_tegra_probe()
1606 priv->dc_dev = disp_uc_plat->src_dev; in dp_tegra_probe()
1612 { .compatible = "nvidia,tegra124-dpaux" },