diff options
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_reg.h | 19 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_bios.h | 8 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_dp.c | 135 |
4 files changed, 123 insertions, 40 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 7916bd97d5c1..bcdf58b1cb7a 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
@@ -672,7 +672,6 @@ typedef struct drm_i915_private { | |||
672 | unsigned int lvds_border_bits; | 672 | unsigned int lvds_border_bits; |
673 | /* Panel fitter placement and size for Ironlake+ */ | 673 | /* Panel fitter placement and size for Ironlake+ */ |
674 | u32 pch_pf_pos, pch_pf_size; | 674 | u32 pch_pf_pos, pch_pf_size; |
675 | int panel_t3, panel_t12; | ||
676 | 675 | ||
677 | struct drm_crtc *plane_to_crtc_mapping[2]; | 676 | struct drm_crtc *plane_to_crtc_mapping[2]; |
678 | struct drm_crtc *pipe_to_crtc_mapping[2]; | 677 | struct drm_crtc *pipe_to_crtc_mapping[2]; |
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 5596e8e0ead7..793cae7f1ab9 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h | |||
@@ -3318,9 +3318,28 @@ | |||
3318 | #define PANEL_POWER_OFF (0 << 0) | 3318 | #define PANEL_POWER_OFF (0 << 0) |
3319 | #define PANEL_POWER_ON (1 << 0) | 3319 | #define PANEL_POWER_ON (1 << 0) |
3320 | #define PCH_PP_ON_DELAYS 0xc7208 | 3320 | #define PCH_PP_ON_DELAYS 0xc7208 |
3321 | #define PANEL_PORT_SELECT_MASK (3 << 30) | ||
3322 | #define PANEL_PORT_SELECT_LVDS (0 << 30) | ||
3323 | #define PANEL_PORT_SELECT_DPA (1 << 30) | ||
3321 | #define EDP_PANEL (1 << 30) | 3324 | #define EDP_PANEL (1 << 30) |
3325 | #define PANEL_PORT_SELECT_DPC (2 << 30) | ||
3326 | #define PANEL_PORT_SELECT_DPD (3 << 30) | ||
3327 | #define PANEL_POWER_UP_DELAY_MASK (0x1fff0000) | ||
3328 | #define PANEL_POWER_UP_DELAY_SHIFT 16 | ||
3329 | #define PANEL_LIGHT_ON_DELAY_MASK (0x1fff) | ||
3330 | #define PANEL_LIGHT_ON_DELAY_SHIFT 0 | ||
3331 | |||
3322 | #define PCH_PP_OFF_DELAYS 0xc720c | 3332 | #define PCH_PP_OFF_DELAYS 0xc720c |
3333 | #define PANEL_POWER_DOWN_DELAY_MASK (0x1fff0000) | ||
3334 | #define PANEL_POWER_DOWN_DELAY_SHIFT 16 | ||
3335 | #define PANEL_LIGHT_OFF_DELAY_MASK (0x1fff) | ||
3336 | #define PANEL_LIGHT_OFF_DELAY_SHIFT 0 | ||
3337 | |||
3323 | #define PCH_PP_DIVISOR 0xc7210 | 3338 | #define PCH_PP_DIVISOR 0xc7210 |
3339 | #define PP_REFERENCE_DIVIDER_MASK (0xffffff00) | ||
3340 | #define PP_REFERENCE_DIVIDER_SHIFT 8 | ||
3341 | #define PANEL_POWER_CYCLE_DELAY_MASK (0x1f) | ||
3342 | #define PANEL_POWER_CYCLE_DELAY_SHIFT 0 | ||
3324 | 3343 | ||
3325 | #define PCH_DP_B 0xe4100 | 3344 | #define PCH_DP_B 0xe4100 |
3326 | #define PCH_DPB_AUX_CH_CTL 0xe4110 | 3345 | #define PCH_DPB_AUX_CH_CTL 0xe4110 |
diff --git a/drivers/gpu/drm/i915/intel_bios.h b/drivers/gpu/drm/i915/intel_bios.h index 5f8e4edcbbb9..35d2a5027ed4 100644 --- a/drivers/gpu/drm/i915/intel_bios.h +++ b/drivers/gpu/drm/i915/intel_bios.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright © 2006 Intel Corporation | 2 | * Copyright © 2006 Intel Corporation |
3 | * | 3 | * |
4 | * Permission is hereby granted, free of charge, to any person obtaining a | 4 | * Permission is hereby granted, free of charge, to any person obtaining a |
5 | * copy of this software and associated documentation files (the "Software"), | 5 | * copy of this software and associated documentation files (the "Software"), |
@@ -446,11 +446,11 @@ struct bdb_driver_features { | |||
446 | #define EDP_VSWING_1_2V 3 | 446 | #define EDP_VSWING_1_2V 3 |
447 | 447 | ||
448 | struct edp_power_seq { | 448 | struct edp_power_seq { |
449 | u16 t3; | 449 | u16 t1_t3; |
450 | u16 t7; | 450 | u16 t8; |
451 | u16 t9; | 451 | u16 t9; |
452 | u16 t10; | 452 | u16 t10; |
453 | u16 t12; | 453 | u16 t11_t12; |
454 | } __attribute__ ((packed)); | 454 | } __attribute__ ((packed)); |
455 | 455 | ||
456 | struct edp_link_params { | 456 | struct edp_link_params { |
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index a178414d5d67..ad682a5ffe8c 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c | |||
@@ -59,6 +59,11 @@ struct intel_dp { | |||
59 | bool is_pch_edp; | 59 | bool is_pch_edp; |
60 | uint8_t train_set[4]; | 60 | uint8_t train_set[4]; |
61 | uint8_t link_status[DP_LINK_STATUS_SIZE]; | 61 | uint8_t link_status[DP_LINK_STATUS_SIZE]; |
62 | int panel_power_up_delay; | ||
63 | int panel_power_down_delay; | ||
64 | int panel_power_cycle_delay; | ||
65 | int backlight_on_delay; | ||
66 | int backlight_off_delay; | ||
62 | }; | 67 | }; |
63 | 68 | ||
64 | /** | 69 | /** |
@@ -770,6 +775,9 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode, | |||
770 | } | 775 | } |
771 | } | 776 | } |
772 | 777 | ||
778 | static void ironlake_edp_pll_on(struct drm_encoder *encoder); | ||
779 | static void ironlake_edp_pll_off(struct drm_encoder *encoder); | ||
780 | |||
773 | static void | 781 | static void |
774 | intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, | 782 | intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, |
775 | struct drm_display_mode *adjusted_mode) | 783 | struct drm_display_mode *adjusted_mode) |
@@ -779,6 +787,14 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, | |||
779 | struct drm_crtc *crtc = intel_dp->base.base.crtc; | 787 | struct drm_crtc *crtc = intel_dp->base.base.crtc; |
780 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 788 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
781 | 789 | ||
790 | /* Turn on the eDP PLL if needed */ | ||
791 | if (is_edp(intel_dp)) { | ||
792 | if (!is_pch_edp(intel_dp)) | ||
793 | ironlake_edp_pll_on(encoder); | ||
794 | else | ||
795 | ironlake_edp_pll_off(encoder); | ||
796 | } | ||
797 | |||
782 | intel_dp->DP = DP_VOLTAGE_0_4 | DP_PRE_EMPHASIS_0; | 798 | intel_dp->DP = DP_VOLTAGE_0_4 | DP_PRE_EMPHASIS_0; |
783 | intel_dp->DP |= intel_dp->color_range; | 799 | intel_dp->DP |= intel_dp->color_range; |
784 | 800 | ||
@@ -838,16 +854,16 @@ static void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp) | |||
838 | { | 854 | { |
839 | struct drm_device *dev = intel_dp->base.base.dev; | 855 | struct drm_device *dev = intel_dp->base.base.dev; |
840 | struct drm_i915_private *dev_priv = dev->dev_private; | 856 | struct drm_i915_private *dev_priv = dev->dev_private; |
841 | u32 pp; | 857 | u32 pp, pp_status; |
842 | 858 | ||
843 | if (!is_edp(intel_dp)) | 859 | if (!is_edp(intel_dp)) |
844 | return; | 860 | return; |
861 | DRM_DEBUG_KMS("Turn eDP VDD on\n"); | ||
845 | /* | 862 | /* |
846 | * If the panel wasn't on, make sure there's not a currently | 863 | * If the panel wasn't on, make sure there's not a currently |
847 | * active PP sequence before enabling AUX VDD. | 864 | * active PP sequence before enabling AUX VDD. |
848 | */ | 865 | */ |
849 | if (!(I915_READ(PCH_PP_STATUS) & PP_ON)) | 866 | pp_status = I915_READ(PCH_PP_STATUS); |
850 | msleep(dev_priv->panel_t3); | ||
851 | 867 | ||
852 | pp = I915_READ(PCH_PP_CONTROL); | 868 | pp = I915_READ(PCH_PP_CONTROL); |
853 | pp &= ~PANEL_UNLOCK_MASK; | 869 | pp &= ~PANEL_UNLOCK_MASK; |
@@ -855,6 +871,12 @@ static void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp) | |||
855 | pp |= EDP_FORCE_VDD; | 871 | pp |= EDP_FORCE_VDD; |
856 | I915_WRITE(PCH_PP_CONTROL, pp); | 872 | I915_WRITE(PCH_PP_CONTROL, pp); |
857 | POSTING_READ(PCH_PP_CONTROL); | 873 | POSTING_READ(PCH_PP_CONTROL); |
874 | DRM_DEBUG_KMS("PCH_PP_STATUS: 0x%08x PCH_PP_CONTROL: 0x%08x\n", | ||
875 | I915_READ(PCH_PP_STATUS), I915_READ(PCH_PP_CONTROL)); | ||
876 | if (!(pp_status & PP_ON)) { | ||
877 | msleep(intel_dp->panel_power_up_delay); | ||
878 | DRM_DEBUG_KMS("eDP VDD was not on\n"); | ||
879 | } | ||
858 | } | 880 | } |
859 | 881 | ||
860 | static void ironlake_edp_panel_vdd_off(struct intel_dp *intel_dp) | 882 | static void ironlake_edp_panel_vdd_off(struct intel_dp *intel_dp) |
@@ -865,6 +887,7 @@ static void ironlake_edp_panel_vdd_off(struct intel_dp *intel_dp) | |||
865 | 887 | ||
866 | if (!is_edp(intel_dp)) | 888 | if (!is_edp(intel_dp)) |
867 | return; | 889 | return; |
890 | DRM_DEBUG_KMS("Turn eDP VDD off\n"); | ||
868 | pp = I915_READ(PCH_PP_CONTROL); | 891 | pp = I915_READ(PCH_PP_CONTROL); |
869 | pp &= ~PANEL_UNLOCK_MASK; | 892 | pp &= ~PANEL_UNLOCK_MASK; |
870 | pp |= PANEL_UNLOCK_REGS; | 893 | pp |= PANEL_UNLOCK_REGS; |
@@ -873,7 +896,9 @@ static void ironlake_edp_panel_vdd_off(struct intel_dp *intel_dp) | |||
873 | POSTING_READ(PCH_PP_CONTROL); | 896 | POSTING_READ(PCH_PP_CONTROL); |
874 | 897 | ||
875 | /* Make sure sequencer is idle before allowing subsequent activity */ | 898 | /* Make sure sequencer is idle before allowing subsequent activity */ |
876 | msleep(dev_priv->panel_t12); | 899 | DRM_DEBUG_KMS("PCH_PP_STATUS: 0x%08x PCH_PP_CONTROL: 0x%08x\n", |
900 | I915_READ(PCH_PP_STATUS), I915_READ(PCH_PP_CONTROL)); | ||
901 | msleep(intel_dp->panel_power_cycle_delay); | ||
877 | } | 902 | } |
878 | 903 | ||
879 | /* Returns true if the panel was already on when called */ | 904 | /* Returns true if the panel was already on when called */ |
@@ -884,7 +909,7 @@ static bool ironlake_edp_panel_on (struct intel_dp *intel_dp) | |||
884 | u32 pp, idle_on_mask = PP_ON | PP_SEQUENCE_STATE_ON_IDLE; | 909 | u32 pp, idle_on_mask = PP_ON | PP_SEQUENCE_STATE_ON_IDLE; |
885 | 910 | ||
886 | if (!is_edp(intel_dp)) | 911 | if (!is_edp(intel_dp)) |
887 | return; | 912 | return true; |
888 | if (I915_READ(PCH_PP_STATUS) & PP_ON) | 913 | if (I915_READ(PCH_PP_STATUS) & PP_ON) |
889 | return true; | 914 | return true; |
890 | 915 | ||
@@ -913,8 +938,10 @@ static bool ironlake_edp_panel_on (struct intel_dp *intel_dp) | |||
913 | return false; | 938 | return false; |
914 | } | 939 | } |
915 | 940 | ||
916 | static void ironlake_edp_panel_off (struct drm_device *dev) | 941 | static void ironlake_edp_panel_off(struct drm_encoder *encoder) |
917 | { | 942 | { |
943 | struct intel_dp *intel_dp = enc_to_intel_dp(encoder); | ||
944 | struct drm_device *dev = encoder->dev; | ||
918 | struct drm_i915_private *dev_priv = dev->dev_private; | 945 | struct drm_i915_private *dev_priv = dev->dev_private; |
919 | u32 pp, idle_off_mask = PP_ON | PP_SEQUENCE_MASK | | 946 | u32 pp, idle_off_mask = PP_ON | PP_SEQUENCE_MASK | |
920 | PP_CYCLE_DELAY_ACTIVE | PP_SEQUENCE_STATE_MASK; | 947 | PP_CYCLE_DELAY_ACTIVE | PP_SEQUENCE_STATE_MASK; |
@@ -933,6 +960,7 @@ static void ironlake_edp_panel_off (struct drm_device *dev) | |||
933 | pp &= ~POWER_TARGET_ON; | 960 | pp &= ~POWER_TARGET_ON; |
934 | I915_WRITE(PCH_PP_CONTROL, pp); | 961 | I915_WRITE(PCH_PP_CONTROL, pp); |
935 | POSTING_READ(PCH_PP_CONTROL); | 962 | POSTING_READ(PCH_PP_CONTROL); |
963 | msleep(intel_dp->panel_power_cycle_delay); | ||
936 | 964 | ||
937 | if (wait_for((I915_READ(PCH_PP_STATUS) & idle_off_mask) == 0, 5000)) | 965 | if (wait_for((I915_READ(PCH_PP_STATUS) & idle_off_mask) == 0, 5000)) |
938 | DRM_ERROR("panel off wait timed out: 0x%08x\n", | 966 | DRM_ERROR("panel off wait timed out: 0x%08x\n", |
@@ -943,11 +971,15 @@ static void ironlake_edp_panel_off (struct drm_device *dev) | |||
943 | POSTING_READ(PCH_PP_CONTROL); | 971 | POSTING_READ(PCH_PP_CONTROL); |
944 | } | 972 | } |
945 | 973 | ||
946 | static void ironlake_edp_backlight_on (struct drm_device *dev) | 974 | static void ironlake_edp_backlight_on (struct intel_dp *intel_dp) |
947 | { | 975 | { |
976 | struct drm_device *dev = intel_dp->base.base.dev; | ||
948 | struct drm_i915_private *dev_priv = dev->dev_private; | 977 | struct drm_i915_private *dev_priv = dev->dev_private; |
949 | u32 pp; | 978 | u32 pp; |
950 | 979 | ||
980 | if (!is_edp(intel_dp)) | ||
981 | return; | ||
982 | |||
951 | DRM_DEBUG_KMS("\n"); | 983 | DRM_DEBUG_KMS("\n"); |
952 | /* | 984 | /* |
953 | * If we enable the backlight right away following a panel power | 985 | * If we enable the backlight right away following a panel power |
@@ -955,25 +987,32 @@ static void ironlake_edp_backlight_on (struct drm_device *dev) | |||
955 | * link. So delay a bit to make sure the image is solid before | 987 | * link. So delay a bit to make sure the image is solid before |
956 | * allowing it to appear. | 988 | * allowing it to appear. |
957 | */ | 989 | */ |
958 | msleep(300); | 990 | msleep(intel_dp->backlight_on_delay); |
959 | pp = I915_READ(PCH_PP_CONTROL); | 991 | pp = I915_READ(PCH_PP_CONTROL); |
960 | pp &= ~PANEL_UNLOCK_MASK; | 992 | pp &= ~PANEL_UNLOCK_MASK; |
961 | pp |= PANEL_UNLOCK_REGS; | 993 | pp |= PANEL_UNLOCK_REGS; |
962 | pp |= EDP_BLC_ENABLE; | 994 | pp |= EDP_BLC_ENABLE; |
963 | I915_WRITE(PCH_PP_CONTROL, pp); | 995 | I915_WRITE(PCH_PP_CONTROL, pp); |
996 | POSTING_READ(PCH_PP_CONTROL); | ||
964 | } | 997 | } |
965 | 998 | ||
966 | static void ironlake_edp_backlight_off (struct drm_device *dev) | 999 | static void ironlake_edp_backlight_off (struct intel_dp *intel_dp) |
967 | { | 1000 | { |
1001 | struct drm_device *dev = intel_dp->base.base.dev; | ||
968 | struct drm_i915_private *dev_priv = dev->dev_private; | 1002 | struct drm_i915_private *dev_priv = dev->dev_private; |
969 | u32 pp; | 1003 | u32 pp; |
970 | 1004 | ||
1005 | if (!is_edp(intel_dp)) | ||
1006 | return; | ||
1007 | |||
971 | DRM_DEBUG_KMS("\n"); | 1008 | DRM_DEBUG_KMS("\n"); |
972 | pp = I915_READ(PCH_PP_CONTROL); | 1009 | pp = I915_READ(PCH_PP_CONTROL); |
973 | pp &= ~PANEL_UNLOCK_MASK; | 1010 | pp &= ~PANEL_UNLOCK_MASK; |
974 | pp |= PANEL_UNLOCK_REGS; | 1011 | pp |= PANEL_UNLOCK_REGS; |
975 | pp &= ~EDP_BLC_ENABLE; | 1012 | pp &= ~EDP_BLC_ENABLE; |
976 | I915_WRITE(PCH_PP_CONTROL, pp); | 1013 | I915_WRITE(PCH_PP_CONTROL, pp); |
1014 | POSTING_READ(PCH_PP_CONTROL); | ||
1015 | msleep(intel_dp->backlight_off_delay); | ||
977 | } | 1016 | } |
978 | 1017 | ||
979 | static void ironlake_edp_pll_on(struct drm_encoder *encoder) | 1018 | static void ironlake_edp_pll_on(struct drm_encoder *encoder) |
@@ -1036,40 +1075,31 @@ static void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode) | |||
1036 | static void intel_dp_prepare(struct drm_encoder *encoder) | 1075 | static void intel_dp_prepare(struct drm_encoder *encoder) |
1037 | { | 1076 | { |
1038 | struct intel_dp *intel_dp = enc_to_intel_dp(encoder); | 1077 | struct intel_dp *intel_dp = enc_to_intel_dp(encoder); |
1039 | struct drm_device *dev = encoder->dev; | ||
1040 | 1078 | ||
1041 | /* Wake up the sink first */ | 1079 | /* Wake up the sink first */ |
1042 | ironlake_edp_panel_vdd_on(intel_dp); | 1080 | ironlake_edp_panel_vdd_on(intel_dp); |
1043 | intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON); | 1081 | intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON); |
1044 | ironlake_edp_panel_vdd_off(intel_dp); | 1082 | ironlake_edp_panel_vdd_off(intel_dp); |
1045 | 1083 | ||
1046 | if (is_edp(intel_dp)) { | 1084 | /* Make sure the panel is off before trying to |
1047 | ironlake_edp_backlight_off(dev); | 1085 | * change the mode |
1048 | ironlake_edp_panel_off(dev); | 1086 | */ |
1049 | if (!is_pch_edp(intel_dp)) | 1087 | ironlake_edp_backlight_off(intel_dp); |
1050 | ironlake_edp_pll_on(encoder); | ||
1051 | else | ||
1052 | ironlake_edp_pll_off(encoder); | ||
1053 | } | ||
1054 | intel_dp_link_down(intel_dp); | 1088 | intel_dp_link_down(intel_dp); |
1089 | ironlake_edp_panel_off(encoder); | ||
1055 | } | 1090 | } |
1056 | 1091 | ||
1057 | static void intel_dp_commit(struct drm_encoder *encoder) | 1092 | static void intel_dp_commit(struct drm_encoder *encoder) |
1058 | { | 1093 | { |
1059 | struct intel_dp *intel_dp = enc_to_intel_dp(encoder); | 1094 | struct intel_dp *intel_dp = enc_to_intel_dp(encoder); |
1060 | struct drm_device *dev = encoder->dev; | ||
1061 | 1095 | ||
1062 | ironlake_edp_panel_vdd_on(intel_dp); | 1096 | ironlake_edp_panel_vdd_on(intel_dp); |
1063 | 1097 | intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON); | |
1064 | intel_dp_start_link_train(intel_dp); | 1098 | intel_dp_start_link_train(intel_dp); |
1065 | |||
1066 | ironlake_edp_panel_on(intel_dp); | 1099 | ironlake_edp_panel_on(intel_dp); |
1067 | ironlake_edp_panel_vdd_off(intel_dp); | 1100 | ironlake_edp_panel_vdd_off(intel_dp); |
1068 | |||
1069 | intel_dp_complete_link_train(intel_dp); | 1101 | intel_dp_complete_link_train(intel_dp); |
1070 | 1102 | ironlake_edp_backlight_on(intel_dp); | |
1071 | if (is_edp(intel_dp)) | ||
1072 | ironlake_edp_backlight_on(dev); | ||
1073 | 1103 | ||
1074 | intel_dp->dpms_mode = DRM_MODE_DPMS_ON; | 1104 | intel_dp->dpms_mode = DRM_MODE_DPMS_ON; |
1075 | } | 1105 | } |
@@ -1085,10 +1115,10 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode) | |||
1085 | if (mode != DRM_MODE_DPMS_ON) { | 1115 | if (mode != DRM_MODE_DPMS_ON) { |
1086 | ironlake_edp_panel_vdd_on(intel_dp); | 1116 | ironlake_edp_panel_vdd_on(intel_dp); |
1087 | if (is_edp(intel_dp)) | 1117 | if (is_edp(intel_dp)) |
1088 | ironlake_edp_backlight_off(dev); | 1118 | ironlake_edp_backlight_off(intel_dp); |
1089 | intel_dp_sink_dpms(intel_dp, mode); | 1119 | intel_dp_sink_dpms(intel_dp, mode); |
1090 | intel_dp_link_down(intel_dp); | 1120 | intel_dp_link_down(intel_dp); |
1091 | ironlake_edp_panel_off(dev); | 1121 | ironlake_edp_panel_off(encoder); |
1092 | if (is_edp(intel_dp) && !is_pch_edp(intel_dp)) | 1122 | if (is_edp(intel_dp) && !is_pch_edp(intel_dp)) |
1093 | ironlake_edp_pll_off(encoder); | 1123 | ironlake_edp_pll_off(encoder); |
1094 | ironlake_edp_panel_vdd_off(intel_dp); | 1124 | ironlake_edp_panel_vdd_off(intel_dp); |
@@ -1100,10 +1130,9 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode) | |||
1100 | ironlake_edp_panel_on(intel_dp); | 1130 | ironlake_edp_panel_on(intel_dp); |
1101 | ironlake_edp_panel_vdd_off(intel_dp); | 1131 | ironlake_edp_panel_vdd_off(intel_dp); |
1102 | intel_dp_complete_link_train(intel_dp); | 1132 | intel_dp_complete_link_train(intel_dp); |
1133 | ironlake_edp_backlight_on(intel_dp); | ||
1103 | } else | 1134 | } else |
1104 | ironlake_edp_panel_vdd_off(intel_dp); | 1135 | ironlake_edp_panel_vdd_off(intel_dp); |
1105 | if (is_edp(intel_dp)) | ||
1106 | ironlake_edp_backlight_on(dev); | ||
1107 | } | 1136 | } |
1108 | intel_dp->dpms_mode = mode; | 1137 | intel_dp->dpms_mode = mode; |
1109 | } | 1138 | } |
@@ -1626,6 +1655,7 @@ intel_dp_link_down(struct intel_dp *intel_dp) | |||
1626 | 1655 | ||
1627 | I915_WRITE(intel_dp->output_reg, DP & ~DP_PORT_EN); | 1656 | I915_WRITE(intel_dp->output_reg, DP & ~DP_PORT_EN); |
1628 | POSTING_READ(intel_dp->output_reg); | 1657 | POSTING_READ(intel_dp->output_reg); |
1658 | msleep(intel_dp->panel_power_down_delay); | ||
1629 | } | 1659 | } |
1630 | 1660 | ||
1631 | static bool | 1661 | static bool |
@@ -2117,16 +2147,51 @@ intel_dp_init(struct drm_device *dev, int output_reg) | |||
2117 | /* Cache some DPCD data in the eDP case */ | 2147 | /* Cache some DPCD data in the eDP case */ |
2118 | if (is_edp(intel_dp)) { | 2148 | if (is_edp(intel_dp)) { |
2119 | bool ret; | 2149 | bool ret; |
2120 | u32 pp_on, pp_div; | 2150 | struct edp_power_seq cur, vbt; |
2151 | u32 pp_on, pp_off, pp_div; | ||
2121 | 2152 | ||
2122 | pp_on = I915_READ(PCH_PP_ON_DELAYS); | 2153 | pp_on = I915_READ(PCH_PP_ON_DELAYS); |
2154 | pp_off = I915_READ(PCH_PP_OFF_DELAYS); | ||
2123 | pp_div = I915_READ(PCH_PP_DIVISOR); | 2155 | pp_div = I915_READ(PCH_PP_DIVISOR); |
2124 | 2156 | ||
2125 | /* Get T3 & T12 values (note: VESA not bspec terminology) */ | 2157 | /* Pull timing values out of registers */ |
2126 | dev_priv->panel_t3 = (pp_on & 0x1fff0000) >> 16; | 2158 | cur.t1_t3 = (pp_on & PANEL_POWER_UP_DELAY_MASK) >> |
2127 | dev_priv->panel_t3 /= 10; /* t3 in 100us units */ | 2159 | PANEL_POWER_UP_DELAY_SHIFT; |
2128 | dev_priv->panel_t12 = pp_div & 0xf; | 2160 | |
2129 | dev_priv->panel_t12 *= 100; /* t12 in 100ms units */ | 2161 | cur.t8 = (pp_on & PANEL_LIGHT_ON_DELAY_MASK) >> |
2162 | PANEL_LIGHT_ON_DELAY_SHIFT; | ||
2163 | |||
2164 | cur.t9 = (pp_off & PANEL_LIGHT_OFF_DELAY_MASK) >> | ||
2165 | PANEL_LIGHT_OFF_DELAY_SHIFT; | ||
2166 | |||
2167 | cur.t10 = (pp_off & PANEL_POWER_DOWN_DELAY_MASK) >> | ||
2168 | PANEL_POWER_DOWN_DELAY_SHIFT; | ||
2169 | |||
2170 | cur.t11_t12 = ((pp_div & PANEL_POWER_CYCLE_DELAY_MASK) >> | ||
2171 | PANEL_POWER_CYCLE_DELAY_SHIFT) * 1000; | ||
2172 | |||
2173 | DRM_DEBUG_KMS("cur t1_t3 %d t8 %d t9 %d t10 %d t11_t12 %d\n", | ||
2174 | cur.t1_t3, cur.t8, cur.t9, cur.t10, cur.t11_t12); | ||
2175 | |||
2176 | vbt = dev_priv->edp.pps; | ||
2177 | |||
2178 | DRM_DEBUG_KMS("vbt t1_t3 %d t8 %d t9 %d t10 %d t11_t12 %d\n", | ||
2179 | vbt.t1_t3, vbt.t8, vbt.t9, vbt.t10, vbt.t11_t12); | ||
2180 | |||
2181 | #define get_delay(field) ((max(cur.field, vbt.field) + 9) / 10) | ||
2182 | |||
2183 | intel_dp->panel_power_up_delay = get_delay(t1_t3); | ||
2184 | intel_dp->backlight_on_delay = get_delay(t8); | ||
2185 | intel_dp->backlight_off_delay = get_delay(t9); | ||
2186 | intel_dp->panel_power_down_delay = get_delay(t10); | ||
2187 | intel_dp->panel_power_cycle_delay = get_delay(t11_t12); | ||
2188 | |||
2189 | DRM_DEBUG_KMS("panel power up delay %d, power down delay %d, power cycle delay %d\n", | ||
2190 | intel_dp->panel_power_up_delay, intel_dp->panel_power_down_delay, | ||
2191 | intel_dp->panel_power_cycle_delay); | ||
2192 | |||
2193 | DRM_DEBUG_KMS("backlight on delay %d, off delay %d\n", | ||
2194 | intel_dp->backlight_on_delay, intel_dp->backlight_off_delay); | ||
2130 | 2195 | ||
2131 | ironlake_edp_panel_vdd_on(intel_dp); | 2196 | ironlake_edp_panel_vdd_on(intel_dp); |
2132 | ret = intel_dp_get_dpcd(intel_dp); | 2197 | ret = intel_dp_get_dpcd(intel_dp); |