Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/tegra: sor: Use DP link training helpers

Make use of the DP link training helpers to implement full and fast link
training. While at it, refactor some of the code and remove various code
sequences that are not necessary.

Signed-off-by: Thierry Reding <treding@nvidia.com>

+480 -300
-69
drivers/gpu/drm/tegra/dpaux.c
··· 821 821 822 822 return 0; 823 823 } 824 - 825 - int drm_dp_aux_prepare(struct drm_dp_aux *aux, u8 encoding) 826 - { 827 - int err; 828 - 829 - err = drm_dp_dpcd_writeb(aux, DP_MAIN_LINK_CHANNEL_CODING_SET, 830 - encoding); 831 - if (err < 0) 832 - return err; 833 - 834 - return 0; 835 - } 836 - 837 - int drm_dp_aux_train(struct drm_dp_aux *aux, struct drm_dp_link *link, 838 - u8 pattern) 839 - { 840 - u8 tp = pattern & DP_TRAINING_PATTERN_MASK; 841 - u8 status[DP_LINK_STATUS_SIZE], values[4]; 842 - unsigned int i; 843 - int err; 844 - 845 - err = drm_dp_dpcd_writeb(aux, DP_TRAINING_PATTERN_SET, pattern); 846 - if (err < 0) 847 - return err; 848 - 849 - if (tp == DP_TRAINING_PATTERN_DISABLE) 850 - return 0; 851 - 852 - for (i = 0; i < link->lanes; i++) 853 - values[i] = DP_TRAIN_MAX_PRE_EMPHASIS_REACHED | 854 - DP_TRAIN_PRE_EMPH_LEVEL_0 | 855 - DP_TRAIN_MAX_SWING_REACHED | 856 - DP_TRAIN_VOLTAGE_SWING_LEVEL_0; 857 - 858 - err = drm_dp_dpcd_write(aux, DP_TRAINING_LANE0_SET, values, 859 - link->lanes); 860 - if (err < 0) 861 - return err; 862 - 863 - usleep_range(500, 1000); 864 - 865 - err = drm_dp_dpcd_read_link_status(aux, status); 866 - if (err < 0) 867 - return err; 868 - 869 - switch (tp) { 870 - case DP_TRAINING_PATTERN_1: 871 - if (!drm_dp_clock_recovery_ok(status, link->lanes)) 872 - return -EAGAIN; 873 - 874 - break; 875 - 876 - case DP_TRAINING_PATTERN_2: 877 - if (!drm_dp_channel_eq_ok(status, link->lanes)) 878 - return -EAGAIN; 879 - 880 - break; 881 - 882 - default: 883 - dev_err(aux->dev, "unsupported training pattern %u\n", tp); 884 - return -EINVAL; 885 - } 886 - 887 - err = drm_dp_dpcd_writeb(aux, DP_EDP_CONFIGURATION_SET, 0); 888 - if (err < 0) 889 - return err; 890 - 891 - return 0; 892 - }
-5
drivers/gpu/drm/tegra/drm.h
··· 153 153 void tegra_output_encoder_destroy(struct drm_encoder *encoder); 154 154 155 155 /* from dpaux.c */ 156 - struct drm_dp_link; 157 - 158 156 struct drm_dp_aux *drm_dp_aux_find_by_of_node(struct device_node *np); 159 157 enum drm_connector_status drm_dp_aux_detect(struct drm_dp_aux *aux); 160 158 int drm_dp_aux_attach(struct drm_dp_aux *aux, struct tegra_output *output); 161 159 int drm_dp_aux_detach(struct drm_dp_aux *aux); 162 160 int drm_dp_aux_enable(struct drm_dp_aux *aux); 163 161 int drm_dp_aux_disable(struct drm_dp_aux *aux); 164 - int drm_dp_aux_prepare(struct drm_dp_aux *aux, u8 encoding); 165 - int drm_dp_aux_train(struct drm_dp_aux *aux, struct drm_dp_link *link, 166 - u8 pattern); 167 162 168 163 /* from fb.c */ 169 164 struct tegra_bo *tegra_fb_get_plane(struct drm_framebuffer *framebuffer,
+478 -226
drivers/gpu/drm/tegra/sor.c
··· 383 383 unsigned int num_settings; 384 384 385 385 const u8 *xbar_cfg; 386 + const u8 *lane_map; 387 + 388 + const u8 (*voltage_swing)[4][4]; 389 + const u8 (*pre_emphasis)[4][4]; 390 + const u8 (*post_cursor)[4][4]; 391 + const u8 (*tx_pu)[4][4]; 386 392 }; 387 393 388 394 struct tegra_sor; ··· 419 413 420 414 u8 xbar_cfg[5]; 421 415 416 + struct drm_dp_link link; 422 417 struct drm_dp_aux *aux; 423 418 424 419 struct drm_info_list *debugfs_files; ··· 605 598 return clk; 606 599 } 607 600 608 - static int tegra_sor_dp_train_fast(struct tegra_sor *sor, 609 - struct drm_dp_link *link) 601 + static int tegra_sor_power_up_lanes(struct tegra_sor *sor, unsigned int lanes) 610 602 { 611 - unsigned int i; 612 - u8 pattern; 603 + unsigned long timeout; 613 604 u32 value; 614 - int err; 615 605 616 - /* setup lane parameters */ 617 - value = SOR_LANE_DRIVE_CURRENT_LANE3(0x40) | 618 - SOR_LANE_DRIVE_CURRENT_LANE2(0x40) | 619 - SOR_LANE_DRIVE_CURRENT_LANE1(0x40) | 620 - SOR_LANE_DRIVE_CURRENT_LANE0(0x40); 621 - tegra_sor_writel(sor, value, SOR_LANE_DRIVE_CURRENT0); 622 - 623 - value = SOR_LANE_PREEMPHASIS_LANE3(0x0f) | 624 - SOR_LANE_PREEMPHASIS_LANE2(0x0f) | 625 - SOR_LANE_PREEMPHASIS_LANE1(0x0f) | 626 - SOR_LANE_PREEMPHASIS_LANE0(0x0f); 627 - tegra_sor_writel(sor, value, SOR_LANE_PREEMPHASIS0); 628 - 629 - value = SOR_LANE_POSTCURSOR_LANE3(0x00) | 630 - SOR_LANE_POSTCURSOR_LANE2(0x00) | 631 - SOR_LANE_POSTCURSOR_LANE1(0x00) | 632 - SOR_LANE_POSTCURSOR_LANE0(0x00); 633 - tegra_sor_writel(sor, value, SOR_LANE_POSTCURSOR0); 634 - 635 - /* disable LVDS mode */ 636 - tegra_sor_writel(sor, 0, SOR_LVDS); 637 - 606 + /* 607 + * Clear or set the PD_TXD bit corresponding to each lane, depending 608 + * on whether it is used or not. 609 + */ 638 610 value = tegra_sor_readl(sor, sor->soc->regs->dp_padctl0); 639 - value |= SOR_DP_PADCTL_TX_PU_ENABLE; 640 - value &= ~SOR_DP_PADCTL_TX_PU_MASK; 641 - value |= SOR_DP_PADCTL_TX_PU(2); /* XXX: don't hardcode? */ 611 + 612 + if (lanes <= 2) 613 + value &= ~(SOR_DP_PADCTL_PD_TXD(sor->soc->lane_map[3]) | 614 + SOR_DP_PADCTL_PD_TXD(sor->soc->lane_map[2])); 615 + else 616 + value |= SOR_DP_PADCTL_PD_TXD(sor->soc->lane_map[3]) | 617 + SOR_DP_PADCTL_PD_TXD(sor->soc->lane_map[2]); 618 + 619 + if (lanes <= 1) 620 + value &= ~SOR_DP_PADCTL_PD_TXD(sor->soc->lane_map[1]); 621 + else 622 + value |= SOR_DP_PADCTL_PD_TXD(sor->soc->lane_map[1]); 623 + 624 + if (lanes == 0) 625 + value &= ~SOR_DP_PADCTL_PD_TXD(sor->soc->lane_map[0]); 626 + else 627 + value |= SOR_DP_PADCTL_PD_TXD(sor->soc->lane_map[0]); 628 + 642 629 tegra_sor_writel(sor, value, sor->soc->regs->dp_padctl0); 643 630 631 + /* start lane sequencer */ 632 + value = SOR_LANE_SEQ_CTL_TRIGGER | SOR_LANE_SEQ_CTL_SEQUENCE_DOWN | 633 + SOR_LANE_SEQ_CTL_POWER_STATE_UP; 634 + tegra_sor_writel(sor, value, SOR_LANE_SEQ_CTL); 635 + 636 + timeout = jiffies + msecs_to_jiffies(250); 637 + 638 + while (time_before(jiffies, timeout)) { 639 + value = tegra_sor_readl(sor, SOR_LANE_SEQ_CTL); 640 + if ((value & SOR_LANE_SEQ_CTL_TRIGGER) == 0) 641 + break; 642 + 643 + usleep_range(250, 1000); 644 + } 645 + 646 + if ((value & SOR_LANE_SEQ_CTL_TRIGGER) != 0) 647 + return -ETIMEDOUT; 648 + 649 + return 0; 650 + } 651 + 652 + static int tegra_sor_power_down_lanes(struct tegra_sor *sor) 653 + { 654 + unsigned long timeout; 655 + u32 value; 656 + 657 + /* power down all lanes */ 644 658 value = tegra_sor_readl(sor, sor->soc->regs->dp_padctl0); 645 - value |= SOR_DP_PADCTL_CM_TXD_3 | SOR_DP_PADCTL_CM_TXD_2 | 646 - SOR_DP_PADCTL_CM_TXD_1 | SOR_DP_PADCTL_CM_TXD_0; 659 + value &= ~(SOR_DP_PADCTL_PD_TXD_3 | SOR_DP_PADCTL_PD_TXD_0 | 660 + SOR_DP_PADCTL_PD_TXD_1 | SOR_DP_PADCTL_PD_TXD_2); 647 661 tegra_sor_writel(sor, value, sor->soc->regs->dp_padctl0); 648 662 649 - usleep_range(10, 100); 663 + /* start lane sequencer */ 664 + value = SOR_LANE_SEQ_CTL_TRIGGER | SOR_LANE_SEQ_CTL_SEQUENCE_UP | 665 + SOR_LANE_SEQ_CTL_POWER_STATE_DOWN; 666 + tegra_sor_writel(sor, value, SOR_LANE_SEQ_CTL); 667 + 668 + timeout = jiffies + msecs_to_jiffies(250); 669 + 670 + while (time_before(jiffies, timeout)) { 671 + value = tegra_sor_readl(sor, SOR_LANE_SEQ_CTL); 672 + if ((value & SOR_LANE_SEQ_CTL_TRIGGER) == 0) 673 + break; 674 + 675 + usleep_range(25, 100); 676 + } 677 + 678 + if ((value & SOR_LANE_SEQ_CTL_TRIGGER) != 0) 679 + return -ETIMEDOUT; 680 + 681 + return 0; 682 + } 683 + 684 + static void tegra_sor_dp_precharge(struct tegra_sor *sor, unsigned int lanes) 685 + { 686 + u32 value; 687 + 688 + /* pre-charge all used lanes */ 689 + value = tegra_sor_readl(sor, sor->soc->regs->dp_padctl0); 690 + 691 + if (lanes <= 2) 692 + value &= ~(SOR_DP_PADCTL_CM_TXD(sor->soc->lane_map[3]) | 693 + SOR_DP_PADCTL_CM_TXD(sor->soc->lane_map[2])); 694 + else 695 + value |= SOR_DP_PADCTL_CM_TXD(sor->soc->lane_map[3]) | 696 + SOR_DP_PADCTL_CM_TXD(sor->soc->lane_map[2]); 697 + 698 + if (lanes <= 1) 699 + value &= ~SOR_DP_PADCTL_CM_TXD(sor->soc->lane_map[1]); 700 + else 701 + value |= SOR_DP_PADCTL_CM_TXD(sor->soc->lane_map[1]); 702 + 703 + if (lanes == 0) 704 + value &= ~SOR_DP_PADCTL_CM_TXD(sor->soc->lane_map[0]); 705 + else 706 + value |= SOR_DP_PADCTL_CM_TXD(sor->soc->lane_map[0]); 707 + 708 + tegra_sor_writel(sor, value, sor->soc->regs->dp_padctl0); 709 + 710 + usleep_range(15, 100); 650 711 651 712 value = tegra_sor_readl(sor, sor->soc->regs->dp_padctl0); 652 713 value &= ~(SOR_DP_PADCTL_CM_TXD_3 | SOR_DP_PADCTL_CM_TXD_2 | 653 714 SOR_DP_PADCTL_CM_TXD_1 | SOR_DP_PADCTL_CM_TXD_0); 654 715 tegra_sor_writel(sor, value, sor->soc->regs->dp_padctl0); 716 + } 655 717 656 - err = drm_dp_aux_prepare(sor->aux, DP_SET_ANSI_8B10B); 657 - if (err < 0) 658 - return err; 718 + static void tegra_sor_dp_term_calibrate(struct tegra_sor *sor) 719 + { 720 + u32 mask = 0x08, adj = 0, value; 659 721 660 - for (i = 0, value = 0; i < link->lanes; i++) { 661 - unsigned long lane = SOR_DP_TPG_CHANNEL_CODING | 662 - SOR_DP_TPG_SCRAMBLER_NONE | 663 - SOR_DP_TPG_PATTERN_TRAIN1; 664 - value = (value << 8) | lane; 722 + /* enable pad calibration logic */ 723 + value = tegra_sor_readl(sor, sor->soc->regs->dp_padctl0); 724 + value &= ~SOR_DP_PADCTL_PAD_CAL_PD; 725 + tegra_sor_writel(sor, value, sor->soc->regs->dp_padctl0); 726 + 727 + value = tegra_sor_readl(sor, sor->soc->regs->pll1); 728 + value |= SOR_PLL1_TMDS_TERM; 729 + tegra_sor_writel(sor, value, sor->soc->regs->pll1); 730 + 731 + while (mask) { 732 + adj |= mask; 733 + 734 + value = tegra_sor_readl(sor, sor->soc->regs->pll1); 735 + value &= ~SOR_PLL1_TMDS_TERMADJ_MASK; 736 + value |= SOR_PLL1_TMDS_TERMADJ(adj); 737 + tegra_sor_writel(sor, value, sor->soc->regs->pll1); 738 + 739 + usleep_range(100, 200); 740 + 741 + value = tegra_sor_readl(sor, sor->soc->regs->pll1); 742 + if (value & SOR_PLL1_TERM_COMPOUT) 743 + adj &= ~mask; 744 + 745 + mask >>= 1; 665 746 } 666 747 667 - tegra_sor_writel(sor, value, SOR_DP_TPG); 748 + value = tegra_sor_readl(sor, sor->soc->regs->pll1); 749 + value &= ~SOR_PLL1_TMDS_TERMADJ_MASK; 750 + value |= SOR_PLL1_TMDS_TERMADJ(adj); 751 + tegra_sor_writel(sor, value, sor->soc->regs->pll1); 668 752 669 - pattern = DP_TRAINING_PATTERN_1; 753 + /* disable pad calibration logic */ 754 + value = tegra_sor_readl(sor, sor->soc->regs->dp_padctl0); 755 + value |= SOR_DP_PADCTL_PAD_CAL_PD; 756 + tegra_sor_writel(sor, value, sor->soc->regs->dp_padctl0); 757 + } 670 758 671 - err = drm_dp_aux_train(sor->aux, link, pattern); 672 - if (err < 0) 673 - return err; 759 + static int tegra_sor_dp_link_apply_training(struct drm_dp_link *link) 760 + { 761 + struct tegra_sor *sor = container_of(link, struct tegra_sor, link); 762 + u32 voltage_swing = 0, pre_emphasis = 0, post_cursor = 0; 763 + const struct tegra_sor_soc *soc = sor->soc; 764 + u32 pattern = 0, tx_pu = 0, value; 765 + unsigned int i; 674 766 675 - value = tegra_sor_readl(sor, SOR_DP_SPARE0); 676 - value |= SOR_DP_SPARE_SEQ_ENABLE; 677 - value &= ~SOR_DP_SPARE_PANEL_INTERNAL; 678 - value |= SOR_DP_SPARE_MACRO_SOR_CLK; 679 - tegra_sor_writel(sor, value, SOR_DP_SPARE0); 767 + for (value = 0, i = 0; i < link->lanes; i++) { 768 + u8 vs = link->train.request.voltage_swing[i]; 769 + u8 pe = link->train.request.pre_emphasis[i]; 770 + u8 pc = link->train.request.post_cursor[i]; 771 + u8 shift = sor->soc->lane_map[i] << 3; 680 772 681 - for (i = 0, value = 0; i < link->lanes; i++) { 682 - unsigned long lane = SOR_DP_TPG_CHANNEL_CODING | 683 - SOR_DP_TPG_SCRAMBLER_NONE | 684 - SOR_DP_TPG_PATTERN_TRAIN2; 685 - value = (value << 8) | lane; 773 + voltage_swing |= soc->voltage_swing[pc][vs][pe] << shift; 774 + pre_emphasis |= soc->pre_emphasis[pc][vs][pe] << shift; 775 + post_cursor |= soc->post_cursor[pc][vs][pe] << shift; 776 + 777 + if (sor->soc->tx_pu[pc][vs][pe] > tx_pu) 778 + tx_pu = sor->soc->tx_pu[pc][vs][pe]; 779 + 780 + switch (link->train.pattern) { 781 + case DP_TRAINING_PATTERN_DISABLE: 782 + value = SOR_DP_TPG_SCRAMBLER_GALIOS | 783 + SOR_DP_TPG_PATTERN_NONE; 784 + break; 785 + 786 + case DP_TRAINING_PATTERN_1: 787 + value = SOR_DP_TPG_SCRAMBLER_NONE | 788 + SOR_DP_TPG_PATTERN_TRAIN1; 789 + break; 790 + 791 + case DP_TRAINING_PATTERN_2: 792 + value = SOR_DP_TPG_SCRAMBLER_NONE | 793 + SOR_DP_TPG_PATTERN_TRAIN2; 794 + break; 795 + 796 + case DP_TRAINING_PATTERN_3: 797 + value = SOR_DP_TPG_SCRAMBLER_NONE | 798 + SOR_DP_TPG_PATTERN_TRAIN3; 799 + break; 800 + 801 + default: 802 + return -EINVAL; 803 + } 804 + 805 + if (link->caps.channel_coding) 806 + value |= SOR_DP_TPG_CHANNEL_CODING; 807 + 808 + pattern = pattern << 8 | value; 686 809 } 687 810 688 - tegra_sor_writel(sor, value, SOR_DP_TPG); 811 + tegra_sor_writel(sor, voltage_swing, SOR_LANE_DRIVE_CURRENT0); 812 + tegra_sor_writel(sor, pre_emphasis, SOR_LANE_PREEMPHASIS0); 689 813 690 - pattern = DP_LINK_SCRAMBLING_DISABLE | DP_TRAINING_PATTERN_2; 814 + if (link->caps.tps3_supported) 815 + tegra_sor_writel(sor, post_cursor, SOR_LANE_POSTCURSOR0); 691 816 692 - err = drm_dp_aux_train(sor->aux, link, pattern); 693 - if (err < 0) 694 - return err; 817 + tegra_sor_writel(sor, pattern, SOR_DP_TPG); 695 818 696 - for (i = 0, value = 0; i < link->lanes; i++) { 697 - unsigned long lane = SOR_DP_TPG_CHANNEL_CODING | 698 - SOR_DP_TPG_SCRAMBLER_GALIOS | 699 - SOR_DP_TPG_PATTERN_NONE; 700 - value = (value << 8) | lane; 701 - } 819 + value = tegra_sor_readl(sor, sor->soc->regs->dp_padctl0); 820 + value &= ~SOR_DP_PADCTL_TX_PU_MASK; 821 + value |= SOR_DP_PADCTL_TX_PU_ENABLE; 822 + value |= SOR_DP_PADCTL_TX_PU(tx_pu); 823 + tegra_sor_writel(sor, value, sor->soc->regs->dp_padctl0); 702 824 703 - tegra_sor_writel(sor, value, SOR_DP_TPG); 704 - 705 - pattern = DP_TRAINING_PATTERN_DISABLE; 706 - 707 - err = drm_dp_aux_train(sor->aux, link, pattern); 708 - if (err < 0) 709 - return err; 825 + usleep_range(20, 100); 710 826 711 827 return 0; 712 828 } 829 + 830 + static int tegra_sor_dp_link_configure(struct drm_dp_link *link) 831 + { 832 + struct tegra_sor *sor = container_of(link, struct tegra_sor, link); 833 + unsigned int rate, lanes; 834 + u32 value; 835 + int err; 836 + 837 + rate = drm_dp_link_rate_to_bw_code(link->rate); 838 + lanes = link->lanes; 839 + 840 + /* configure link speed and lane count */ 841 + value = tegra_sor_readl(sor, SOR_CLK_CNTRL); 842 + value &= ~SOR_CLK_CNTRL_DP_LINK_SPEED_MASK; 843 + value |= SOR_CLK_CNTRL_DP_LINK_SPEED(rate); 844 + tegra_sor_writel(sor, value, SOR_CLK_CNTRL); 845 + 846 + value = tegra_sor_readl(sor, SOR_DP_LINKCTL0); 847 + value &= ~SOR_DP_LINKCTL_LANE_COUNT_MASK; 848 + value |= SOR_DP_LINKCTL_LANE_COUNT(lanes); 849 + 850 + if (link->caps.enhanced_framing) 851 + value |= SOR_DP_LINKCTL_ENHANCED_FRAME; 852 + 853 + tegra_sor_writel(sor, value, SOR_DP_LINKCTL0); 854 + 855 + usleep_range(400, 1000); 856 + 857 + /* configure load pulse position adjustment */ 858 + value = tegra_sor_readl(sor, sor->soc->regs->pll1); 859 + value &= ~SOR_PLL1_LOADADJ_MASK; 860 + 861 + switch (rate) { 862 + case DP_LINK_BW_1_62: 863 + value |= SOR_PLL1_LOADADJ(0x3); 864 + break; 865 + 866 + case DP_LINK_BW_2_7: 867 + value |= SOR_PLL1_LOADADJ(0x4); 868 + break; 869 + 870 + case DP_LINK_BW_5_4: 871 + value |= SOR_PLL1_LOADADJ(0x6); 872 + break; 873 + } 874 + 875 + tegra_sor_writel(sor, value, sor->soc->regs->pll1); 876 + 877 + /* use alternate scrambler reset for eDP */ 878 + value = tegra_sor_readl(sor, SOR_DP_SPARE0); 879 + 880 + if (link->edp == 0) 881 + value &= ~SOR_DP_SPARE_PANEL_INTERNAL; 882 + else 883 + value |= SOR_DP_SPARE_PANEL_INTERNAL; 884 + 885 + tegra_sor_writel(sor, value, SOR_DP_SPARE0); 886 + 887 + err = tegra_sor_power_down_lanes(sor); 888 + if (err < 0) { 889 + dev_err(sor->dev, "failed to power down lanes: %d\n", err); 890 + return err; 891 + } 892 + 893 + /* power up and pre-charge lanes */ 894 + err = tegra_sor_power_up_lanes(sor, lanes); 895 + if (err < 0) { 896 + dev_err(sor->dev, "failed to power up %u lane%s: %d\n", 897 + lanes, (lanes != 1) ? "s" : "", err); 898 + return err; 899 + } 900 + 901 + tegra_sor_dp_precharge(sor, lanes); 902 + 903 + return 0; 904 + } 905 + 906 + static const struct drm_dp_link_ops tegra_sor_dp_link_ops = { 907 + .apply_training = tegra_sor_dp_link_apply_training, 908 + .configure = tegra_sor_dp_link_configure, 909 + }; 713 910 714 911 static void tegra_sor_super_update(struct tegra_sor *sor) 715 912 { ··· 1412 1201 return err; 1413 1202 } 1414 1203 1415 - value = tegra_sor_readl(sor, sor->soc->regs->dp_padctl0); 1416 - value &= ~(SOR_DP_PADCTL_PD_TXD_3 | SOR_DP_PADCTL_PD_TXD_0 | 1417 - SOR_DP_PADCTL_PD_TXD_1 | SOR_DP_PADCTL_PD_TXD_2); 1418 - tegra_sor_writel(sor, value, sor->soc->regs->dp_padctl0); 1419 - 1420 - /* stop lane sequencer */ 1421 - value = SOR_LANE_SEQ_CTL_TRIGGER | SOR_LANE_SEQ_CTL_SEQUENCE_UP | 1422 - SOR_LANE_SEQ_CTL_POWER_STATE_DOWN; 1423 - tegra_sor_writel(sor, value, SOR_LANE_SEQ_CTL); 1424 - 1425 - timeout = jiffies + msecs_to_jiffies(250); 1426 - 1427 - while (time_before(jiffies, timeout)) { 1428 - value = tegra_sor_readl(sor, SOR_LANE_SEQ_CTL); 1429 - if ((value & SOR_LANE_SEQ_CTL_TRIGGER) == 0) 1430 - break; 1431 - 1432 - usleep_range(25, 100); 1433 - } 1434 - 1435 - if ((value & SOR_LANE_SEQ_CTL_TRIGGER) != 0) 1436 - return -ETIMEDOUT; 1437 - 1438 1204 value = tegra_sor_readl(sor, sor->soc->regs->pll2); 1439 1205 value |= SOR_PLL2_PORT_POWERDOWN; 1440 1206 tegra_sor_writel(sor, value, sor->soc->regs->pll2); ··· 1791 1603 tegra_sor_writel(sor, 0, SOR_STATE1); 1792 1604 tegra_sor_update(sor); 1793 1605 1794 - /* 1795 - * The following accesses registers of the display controller, so make 1796 - * sure it's only executed when the output is attached to one. 1797 - */ 1798 - if (dc) { 1799 - value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS); 1800 - value &= ~SOR_ENABLE(0); 1801 - tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS); 1606 + value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS); 1607 + value &= ~SOR_ENABLE(0); 1608 + tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS); 1802 1609 1803 - tegra_dc_commit(dc); 1804 - } 1610 + tegra_dc_commit(dc); 1805 1611 1806 1612 err = tegra_sor_power_down(sor); 1807 1613 if (err < 0) ··· 1861 1679 1862 1680 static void tegra_sor_edp_enable(struct drm_encoder *encoder) 1863 1681 { 1864 - struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode; 1865 1682 struct tegra_output *output = encoder_to_output(encoder); 1866 1683 struct tegra_dc *dc = to_tegra_dc(encoder->crtc); 1867 1684 struct tegra_sor *sor = to_sor(output); 1868 1685 struct tegra_sor_config config; 1869 1686 struct tegra_sor_state *state; 1870 - struct drm_dp_link link; 1871 - u8 rate, lanes; 1687 + struct drm_display_mode *mode; 1688 + struct drm_display_info *info; 1872 1689 unsigned int i; 1873 - int err = 0; 1874 1690 u32 value; 1691 + int err; 1875 1692 1876 1693 state = to_sor_state(output->connector.state); 1694 + mode = &encoder->crtc->state->adjusted_mode; 1695 + info = &output->connector.display_info; 1877 1696 1878 1697 pm_runtime_get_sync(sor->dev); 1879 1698 ··· 1885 1702 if (err < 0) 1886 1703 dev_err(sor->dev, "failed to enable DP: %d\n", err); 1887 1704 1888 - err = drm_dp_link_probe(sor->aux, &link); 1705 + err = drm_dp_link_probe(sor->aux, &sor->link); 1889 1706 if (err < 0) { 1890 1707 dev_err(sor->dev, "failed to probe eDP link: %d\n", err); 1891 1708 return; ··· 1895 1712 err = tegra_sor_set_parent_clock(sor, sor->clk_safe); 1896 1713 if (err < 0) 1897 1714 dev_err(sor->dev, "failed to set safe parent clock: %d\n", err); 1898 - 1899 - memset(&config, 0, sizeof(config)); 1900 - config.bits_per_pixel = state->bpc * 3; 1901 - 1902 - err = tegra_sor_compute_config(sor, mode, &config, &link); 1903 - if (err < 0) 1904 - dev_err(sor->dev, "failed to compute configuration: %d\n", err); 1905 1715 1906 1716 value = tegra_sor_readl(sor, SOR_CLK_CNTRL); 1907 1717 value &= ~SOR_CLK_CNTRL_DP_CLK_SEL_MASK; ··· 2004 1828 if (err < 0) 2005 1829 dev_err(sor->dev, "failed to set parent clock: %d\n", err); 2006 1830 2007 - /* power DP lanes */ 2008 - value = tegra_sor_readl(sor, sor->soc->regs->dp_padctl0); 1831 + /* use DP-A protocol */ 1832 + value = tegra_sor_readl(sor, SOR_STATE1); 1833 + value &= ~SOR_STATE_ASY_PROTOCOL_MASK; 1834 + value |= SOR_STATE_ASY_PROTOCOL_DP_A; 1835 + tegra_sor_writel(sor, value, SOR_STATE1); 2009 1836 2010 - if (link.lanes <= 2) 2011 - value &= ~(SOR_DP_PADCTL_PD_TXD_3 | SOR_DP_PADCTL_PD_TXD_2); 2012 - else 2013 - value |= SOR_DP_PADCTL_PD_TXD_3 | SOR_DP_PADCTL_PD_TXD_2; 2014 - 2015 - if (link.lanes <= 1) 2016 - value &= ~SOR_DP_PADCTL_PD_TXD_1; 2017 - else 2018 - value |= SOR_DP_PADCTL_PD_TXD_1; 2019 - 2020 - if (link.lanes == 0) 2021 - value &= ~SOR_DP_PADCTL_PD_TXD_0; 2022 - else 2023 - value |= SOR_DP_PADCTL_PD_TXD_0; 2024 - 2025 - tegra_sor_writel(sor, value, sor->soc->regs->dp_padctl0); 2026 - 2027 - value = tegra_sor_readl(sor, SOR_DP_LINKCTL0); 2028 - value &= ~SOR_DP_LINKCTL_LANE_COUNT_MASK; 2029 - value |= SOR_DP_LINKCTL_LANE_COUNT(link.lanes); 2030 - tegra_sor_writel(sor, value, SOR_DP_LINKCTL0); 2031 - 2032 - /* start lane sequencer */ 2033 - value = SOR_LANE_SEQ_CTL_TRIGGER | SOR_LANE_SEQ_CTL_SEQUENCE_DOWN | 2034 - SOR_LANE_SEQ_CTL_POWER_STATE_UP; 2035 - tegra_sor_writel(sor, value, SOR_LANE_SEQ_CTL); 2036 - 2037 - while (true) { 2038 - value = tegra_sor_readl(sor, SOR_LANE_SEQ_CTL); 2039 - if ((value & SOR_LANE_SEQ_CTL_TRIGGER) == 0) 2040 - break; 2041 - 2042 - usleep_range(250, 1000); 2043 - } 2044 - 2045 - /* set link bandwidth */ 2046 - value = tegra_sor_readl(sor, SOR_CLK_CNTRL); 2047 - value &= ~SOR_CLK_CNTRL_DP_LINK_SPEED_MASK; 2048 - value |= drm_dp_link_rate_to_bw_code(link.rate) << 2; 2049 - tegra_sor_writel(sor, value, SOR_CLK_CNTRL); 2050 - 2051 - tegra_sor_apply_config(sor, &config); 2052 - 2053 - /* enable link */ 1837 + /* enable port */ 2054 1838 value = tegra_sor_readl(sor, SOR_DP_LINKCTL0); 2055 1839 value |= SOR_DP_LINKCTL_ENABLE; 2056 - value |= SOR_DP_LINKCTL_ENHANCED_FRAME; 2057 1840 tegra_sor_writel(sor, value, SOR_DP_LINKCTL0); 2058 1841 2059 - for (i = 0, value = 0; i < 4; i++) { 2060 - unsigned long lane = SOR_DP_TPG_CHANNEL_CODING | 2061 - SOR_DP_TPG_SCRAMBLER_GALIOS | 2062 - SOR_DP_TPG_PATTERN_NONE; 2063 - value = (value << 8) | lane; 1842 + /* calibrate termination resistance (XXX do this only on HPD) */ 1843 + tegra_sor_dp_term_calibrate(sor); 1844 + 1845 + err = drm_dp_link_train(&sor->link); 1846 + if (err < 0) 1847 + dev_err(sor->dev, "link training failed: %d\n", err); 1848 + else 1849 + dev_dbg(sor->dev, "link training succeeded\n"); 1850 + 1851 + err = drm_dp_link_power_up(sor->aux, &sor->link); 1852 + if (err < 0) { 1853 + dev_err(sor->dev, "failed to power up eDP link: %d\n", 1854 + err); 1855 + return; 2064 1856 } 2065 1857 2066 - tegra_sor_writel(sor, value, SOR_DP_TPG); 1858 + /* compute configuration */ 1859 + memset(&config, 0, sizeof(config)); 1860 + config.bits_per_pixel = state->bpc * 3; 2067 1861 2068 - /* enable pad calibration logic */ 2069 - value = tegra_sor_readl(sor, sor->soc->regs->dp_padctl0); 2070 - value |= SOR_DP_PADCTL_PAD_CAL_PD; 2071 - tegra_sor_writel(sor, value, sor->soc->regs->dp_padctl0); 2072 - 2073 - err = drm_dp_link_probe(sor->aux, &link); 2074 - if (err < 0) 2075 - dev_err(sor->dev, "failed to probe eDP link: %d\n", err); 2076 - 2077 - err = drm_dp_link_power_up(sor->aux, &link); 2078 - if (err < 0) 2079 - dev_err(sor->dev, "failed to power up eDP link: %d\n", err); 2080 - 2081 - err = drm_dp_link_configure(sor->aux, &link); 2082 - if (err < 0) 2083 - dev_err(sor->dev, "failed to configure eDP link: %d\n", err); 2084 - 2085 - rate = drm_dp_link_rate_to_bw_code(link.rate); 2086 - lanes = link.lanes; 2087 - 2088 - value = tegra_sor_readl(sor, SOR_CLK_CNTRL); 2089 - value &= ~SOR_CLK_CNTRL_DP_LINK_SPEED_MASK; 2090 - value |= SOR_CLK_CNTRL_DP_LINK_SPEED(rate); 2091 - tegra_sor_writel(sor, value, SOR_CLK_CNTRL); 2092 - 2093 - value = tegra_sor_readl(sor, SOR_DP_LINKCTL0); 2094 - value &= ~SOR_DP_LINKCTL_LANE_COUNT_MASK; 2095 - value |= SOR_DP_LINKCTL_LANE_COUNT(lanes); 2096 - 2097 - if (link.caps.enhanced_framing) 2098 - value |= SOR_DP_LINKCTL_ENHANCED_FRAME; 2099 - 2100 - tegra_sor_writel(sor, value, SOR_DP_LINKCTL0); 2101 - 2102 - /* disable training pattern generator */ 2103 - 2104 - for (i = 0; i < link.lanes; i++) { 2105 - unsigned long lane = SOR_DP_TPG_CHANNEL_CODING | 2106 - SOR_DP_TPG_SCRAMBLER_GALIOS | 2107 - SOR_DP_TPG_PATTERN_NONE; 2108 - value = (value << 8) | lane; 1862 + err = tegra_sor_compute_config(sor, mode, &config, &sor->link); 1863 + if (err < 0) { 1864 + dev_err(sor->dev, "failed to compute configuration: %d\n", err); 1865 + return; 2109 1866 } 2110 1867 2111 - tegra_sor_writel(sor, value, SOR_DP_TPG); 2112 - 2113 - err = tegra_sor_dp_train_fast(sor, &link); 2114 - if (err < 0) 2115 - dev_err(sor->dev, "DP fast link training failed: %d\n", err); 2116 - 2117 - dev_dbg(sor->dev, "fast link training succeeded\n"); 1868 + tegra_sor_apply_config(sor, &config); 2118 1869 2119 1870 err = tegra_sor_power_up(sor, 250); 2120 1871 if (err < 0) ··· 2945 2842 connector = DRM_MODE_CONNECTOR_DisplayPort; 2946 2843 encoder = DRM_MODE_ENCODER_TMDS; 2947 2844 } 2845 + 2846 + sor->link.ops = &tegra_sor_dp_link_ops; 2847 + sor->link.aux = sor->aux; 2948 2848 } 2949 2849 2950 2850 sor->output.dev = sor->dev; ··· 3148 3042 .dp_padctl2 = 0x73, 3149 3043 }; 3150 3044 3045 + /* Tegra124 and Tegra132 have lanes 0 and 2 swapped. */ 3046 + static const u8 tegra124_sor_lane_map[4] = { 3047 + 2, 1, 0, 3, 3048 + }; 3049 + 3050 + static const u8 tegra124_sor_voltage_swing[4][4][4] = { 3051 + { 3052 + { 0x13, 0x19, 0x1e, 0x28 }, 3053 + { 0x1e, 0x25, 0x2d, }, 3054 + { 0x28, 0x32, }, 3055 + { 0x3c, }, 3056 + }, { 3057 + { 0x12, 0x17, 0x1b, 0x25 }, 3058 + { 0x1c, 0x23, 0x2a, }, 3059 + { 0x25, 0x2f, }, 3060 + { 0x39, } 3061 + }, { 3062 + { 0x12, 0x16, 0x1a, 0x22 }, 3063 + { 0x1b, 0x20, 0x27, }, 3064 + { 0x24, 0x2d, }, 3065 + { 0x36, }, 3066 + }, { 3067 + { 0x11, 0x14, 0x17, 0x1f }, 3068 + { 0x19, 0x1e, 0x24, }, 3069 + { 0x22, 0x2a, }, 3070 + { 0x32, }, 3071 + }, 3072 + }; 3073 + 3074 + static const u8 tegra124_sor_pre_emphasis[4][4][4] = { 3075 + { 3076 + { 0x00, 0x09, 0x13, 0x25 }, 3077 + { 0x00, 0x0f, 0x1e, }, 3078 + { 0x00, 0x14, }, 3079 + { 0x00, }, 3080 + }, { 3081 + { 0x00, 0x0a, 0x14, 0x28 }, 3082 + { 0x00, 0x0f, 0x1e, }, 3083 + { 0x00, 0x14, }, 3084 + { 0x00 }, 3085 + }, { 3086 + { 0x00, 0x0a, 0x14, 0x28 }, 3087 + { 0x00, 0x0f, 0x1e, }, 3088 + { 0x00, 0x14, }, 3089 + { 0x00, }, 3090 + }, { 3091 + { 0x00, 0x0a, 0x14, 0x28 }, 3092 + { 0x00, 0x0f, 0x1e, }, 3093 + { 0x00, 0x14, }, 3094 + { 0x00, }, 3095 + }, 3096 + }; 3097 + 3098 + static const u8 tegra124_sor_post_cursor[4][4][4] = { 3099 + { 3100 + { 0x00, 0x00, 0x00, 0x00 }, 3101 + { 0x00, 0x00, 0x00, }, 3102 + { 0x00, 0x00, }, 3103 + { 0x00, }, 3104 + }, { 3105 + { 0x02, 0x02, 0x04, 0x05 }, 3106 + { 0x02, 0x04, 0x05, }, 3107 + { 0x04, 0x05, }, 3108 + { 0x05, }, 3109 + }, { 3110 + { 0x04, 0x05, 0x08, 0x0b }, 3111 + { 0x05, 0x09, 0x0b, }, 3112 + { 0x08, 0x0a, }, 3113 + { 0x0b, }, 3114 + }, { 3115 + { 0x05, 0x09, 0x0b, 0x12 }, 3116 + { 0x09, 0x0d, 0x12, }, 3117 + { 0x0b, 0x0f, }, 3118 + { 0x12, }, 3119 + }, 3120 + }; 3121 + 3122 + static const u8 tegra124_sor_tx_pu[4][4][4] = { 3123 + { 3124 + { 0x20, 0x30, 0x40, 0x60 }, 3125 + { 0x30, 0x40, 0x60, }, 3126 + { 0x40, 0x60, }, 3127 + { 0x60, }, 3128 + }, { 3129 + { 0x20, 0x20, 0x30, 0x50 }, 3130 + { 0x30, 0x40, 0x50, }, 3131 + { 0x40, 0x50, }, 3132 + { 0x60, }, 3133 + }, { 3134 + { 0x20, 0x20, 0x30, 0x40, }, 3135 + { 0x30, 0x30, 0x40, }, 3136 + { 0x40, 0x50, }, 3137 + { 0x60, }, 3138 + }, { 3139 + { 0x20, 0x20, 0x20, 0x40, }, 3140 + { 0x30, 0x30, 0x40, }, 3141 + { 0x40, 0x40, }, 3142 + { 0x60, }, 3143 + }, 3144 + }; 3145 + 3151 3146 static const struct tegra_sor_soc tegra124_sor = { 3152 3147 .supports_edp = true, 3153 3148 .supports_lvds = true, ··· 3257 3050 .regs = &tegra124_sor_regs, 3258 3051 .has_nvdisplay = false, 3259 3052 .xbar_cfg = tegra124_sor_xbar_cfg, 3053 + .lane_map = tegra124_sor_lane_map, 3054 + .voltage_swing = tegra124_sor_voltage_swing, 3055 + .pre_emphasis = tegra124_sor_pre_emphasis, 3056 + .post_cursor = tegra124_sor_post_cursor, 3057 + .tx_pu = tegra124_sor_tx_pu, 3058 + }; 3059 + 3060 + static const u8 tegra132_sor_pre_emphasis[4][4][4] = { 3061 + { 3062 + { 0x00, 0x08, 0x12, 0x24 }, 3063 + { 0x01, 0x0e, 0x1d, }, 3064 + { 0x01, 0x13, }, 3065 + { 0x00, }, 3066 + }, { 3067 + { 0x00, 0x08, 0x12, 0x24 }, 3068 + { 0x00, 0x0e, 0x1d, }, 3069 + { 0x00, 0x13, }, 3070 + { 0x00 }, 3071 + }, { 3072 + { 0x00, 0x08, 0x12, 0x24 }, 3073 + { 0x00, 0x0e, 0x1d, }, 3074 + { 0x00, 0x13, }, 3075 + { 0x00, }, 3076 + }, { 3077 + { 0x00, 0x08, 0x12, 0x24 }, 3078 + { 0x00, 0x0e, 0x1d, }, 3079 + { 0x00, 0x13, }, 3080 + { 0x00, }, 3081 + }, 3082 + }; 3083 + 3084 + static const struct tegra_sor_soc tegra132_sor = { 3085 + .supports_edp = true, 3086 + .supports_lvds = true, 3087 + .supports_hdmi = false, 3088 + .supports_dp = false, 3089 + .regs = &tegra124_sor_regs, 3090 + .has_nvdisplay = false, 3091 + .xbar_cfg = tegra124_sor_xbar_cfg, 3092 + .lane_map = tegra124_sor_lane_map, 3093 + .voltage_swing = tegra124_sor_voltage_swing, 3094 + .pre_emphasis = tegra132_sor_pre_emphasis, 3095 + .post_cursor = tegra124_sor_post_cursor, 3096 + .tx_pu = tegra124_sor_tx_pu, 3260 3097 }; 3261 3098 3262 3099 static const struct tegra_sor_regs tegra210_sor_regs = { ··· 3318 3067 .dp_padctl2 = 0x73, 3319 3068 }; 3320 3069 3070 + static const u8 tegra210_sor_xbar_cfg[5] = { 3071 + 2, 1, 0, 3, 4 3072 + }; 3073 + 3321 3074 static const struct tegra_sor_soc tegra210_sor = { 3322 3075 .supports_edp = true, 3323 3076 .supports_lvds = false, 3324 3077 .supports_hdmi = false, 3325 3078 .supports_dp = false, 3079 + 3326 3080 .regs = &tegra210_sor_regs, 3327 3081 .has_nvdisplay = false, 3328 - .xbar_cfg = tegra124_sor_xbar_cfg, 3329 - }; 3330 3082 3331 - static const u8 tegra210_sor_xbar_cfg[5] = { 3332 - 2, 1, 0, 3, 4 3083 + .xbar_cfg = tegra210_sor_xbar_cfg, 3333 3084 }; 3334 3085 3335 3086 static const struct tegra_sor_soc tegra210_sor1 = { ··· 3345 3092 3346 3093 .num_settings = ARRAY_SIZE(tegra210_sor_hdmi_defaults), 3347 3094 .settings = tegra210_sor_hdmi_defaults, 3348 - 3349 3095 .xbar_cfg = tegra210_sor_xbar_cfg, 3350 3096 }; 3351 3097 ··· 3386 3134 3387 3135 .num_settings = ARRAY_SIZE(tegra186_sor_hdmi_defaults), 3388 3136 .settings = tegra186_sor_hdmi_defaults, 3389 - 3390 3137 .xbar_cfg = tegra124_sor_xbar_cfg, 3391 3138 }; 3392 3139 ··· 3425 3174 { .compatible = "nvidia,tegra186-sor", .data = &tegra186_sor }, 3426 3175 { .compatible = "nvidia,tegra210-sor1", .data = &tegra210_sor1 }, 3427 3176 { .compatible = "nvidia,tegra210-sor", .data = &tegra210_sor }, 3177 + { .compatible = "nvidia,tegra132-sor", .data = &tegra132_sor }, 3428 3178 { .compatible = "nvidia,tegra124-sor", .data = &tegra124_sor }, 3429 3179 { }, 3430 3180 };
+2
drivers/gpu/drm/tegra/sor.h
··· 283 283 #define SOR_DP_PADCTL_CM_TXD_2 (1 << 6) 284 284 #define SOR_DP_PADCTL_CM_TXD_1 (1 << 5) 285 285 #define SOR_DP_PADCTL_CM_TXD_0 (1 << 4) 286 + #define SOR_DP_PADCTL_CM_TXD(x) (1 << (4 + (x))) 286 287 #define SOR_DP_PADCTL_PD_TXD_3 (1 << 3) 287 288 #define SOR_DP_PADCTL_PD_TXD_0 (1 << 2) 288 289 #define SOR_DP_PADCTL_PD_TXD_1 (1 << 1) 289 290 #define SOR_DP_PADCTL_PD_TXD_2 (1 << 0) 291 + #define SOR_DP_PADCTL_PD_TXD(x) (1 << (0 + (x))) 290 292 291 293 #define SOR_DP_PADCTL1 0x5d 292 294