diff options
| -rw-r--r-- | drivers/gpu/drm/i915/i915_reg.h | 25 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 51 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_dp.c | 102 |
3 files changed, 157 insertions, 21 deletions
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 7c77c4c53c52..4518a9489ed1 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h | |||
| @@ -1444,6 +1444,7 @@ | |||
| 1444 | #define DP_CLOCK_OUTPUT_ENABLE (1 << 13) | 1444 | #define DP_CLOCK_OUTPUT_ENABLE (1 << 13) |
| 1445 | 1445 | ||
| 1446 | #define DP_SCRAMBLING_DISABLE (1 << 12) | 1446 | #define DP_SCRAMBLING_DISABLE (1 << 12) |
| 1447 | #define DP_SCRAMBLING_DISABLE_IGDNG (1 << 7) | ||
| 1447 | 1448 | ||
| 1448 | /** limit RGB values to avoid confusing TVs */ | 1449 | /** limit RGB values to avoid confusing TVs */ |
| 1449 | #define DP_COLOR_RANGE_16_235 (1 << 8) | 1450 | #define DP_COLOR_RANGE_16_235 (1 << 8) |
| @@ -2210,4 +2211,28 @@ | |||
| 2210 | #define PCH_PP_OFF_DELAYS 0xc720c | 2211 | #define PCH_PP_OFF_DELAYS 0xc720c |
| 2211 | #define PCH_PP_DIVISOR 0xc7210 | 2212 | #define PCH_PP_DIVISOR 0xc7210 |
| 2212 | 2213 | ||
| 2214 | #define PCH_DP_B 0xe4100 | ||
| 2215 | #define PCH_DPB_AUX_CH_CTL 0xe4110 | ||
| 2216 | #define PCH_DPB_AUX_CH_DATA1 0xe4114 | ||
| 2217 | #define PCH_DPB_AUX_CH_DATA2 0xe4118 | ||
| 2218 | #define PCH_DPB_AUX_CH_DATA3 0xe411c | ||
| 2219 | #define PCH_DPB_AUX_CH_DATA4 0xe4120 | ||
| 2220 | #define PCH_DPB_AUX_CH_DATA5 0xe4124 | ||
| 2221 | |||
| 2222 | #define PCH_DP_C 0xe4200 | ||
| 2223 | #define PCH_DPC_AUX_CH_CTL 0xe4210 | ||
| 2224 | #define PCH_DPC_AUX_CH_DATA1 0xe4214 | ||
| 2225 | #define PCH_DPC_AUX_CH_DATA2 0xe4218 | ||
| 2226 | #define PCH_DPC_AUX_CH_DATA3 0xe421c | ||
| 2227 | #define PCH_DPC_AUX_CH_DATA4 0xe4220 | ||
| 2228 | #define PCH_DPC_AUX_CH_DATA5 0xe4224 | ||
| 2229 | |||
| 2230 | #define PCH_DP_D 0xe4300 | ||
| 2231 | #define PCH_DPD_AUX_CH_CTL 0xe4310 | ||
| 2232 | #define PCH_DPD_AUX_CH_DATA1 0xe4314 | ||
| 2233 | #define PCH_DPD_AUX_CH_DATA2 0xe4318 | ||
| 2234 | #define PCH_DPD_AUX_CH_DATA3 0xe431c | ||
| 2235 | #define PCH_DPD_AUX_CH_DATA4 0xe4320 | ||
| 2236 | #define PCH_DPD_AUX_CH_DATA5 0xe4324 | ||
| 2237 | |||
| 2213 | #endif /* _I915_REG_H_ */ | 2238 | #endif /* _I915_REG_H_ */ |
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 15a8c3908acb..34c50460eaa7 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
| @@ -268,6 +268,9 @@ intel_igdng_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, | |||
| 268 | static bool | 268 | static bool |
| 269 | intel_find_pll_g4x_dp(const intel_limit_t *, struct drm_crtc *crtc, | 269 | intel_find_pll_g4x_dp(const intel_limit_t *, struct drm_crtc *crtc, |
| 270 | int target, int refclk, intel_clock_t *best_clock); | 270 | int target, int refclk, intel_clock_t *best_clock); |
| 271 | static bool | ||
| 272 | intel_find_pll_igdng_dp(const intel_limit_t *, struct drm_crtc *crtc, | ||
| 273 | int target, int refclk, intel_clock_t *best_clock); | ||
| 271 | 274 | ||
| 272 | static const intel_limit_t intel_limits_i8xx_dvo = { | 275 | static const intel_limit_t intel_limits_i8xx_dvo = { |
| 273 | .dot = { .min = I8XX_DOT_MIN, .max = I8XX_DOT_MAX }, | 276 | .dot = { .min = I8XX_DOT_MIN, .max = I8XX_DOT_MAX }, |
| @@ -752,6 +755,30 @@ intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, | |||
| 752 | } | 755 | } |
| 753 | 756 | ||
| 754 | static bool | 757 | static bool |
| 758 | intel_find_pll_igdng_dp(const intel_limit_t *limit, struct drm_crtc *crtc, | ||
| 759 | int target, int refclk, intel_clock_t *best_clock) | ||
| 760 | { | ||
| 761 | struct drm_device *dev = crtc->dev; | ||
| 762 | intel_clock_t clock; | ||
| 763 | if (target < 200000) { | ||
| 764 | clock.n = 1; | ||
| 765 | clock.p1 = 2; | ||
| 766 | clock.p2 = 10; | ||
| 767 | clock.m1 = 12; | ||
| 768 | clock.m2 = 9; | ||
| 769 | } else { | ||
| 770 | clock.n = 2; | ||
| 771 | clock.p1 = 1; | ||
| 772 | clock.p2 = 10; | ||
| 773 | clock.m1 = 14; | ||
| 774 | clock.m2 = 8; | ||
| 775 | } | ||
| 776 | intel_clock(dev, refclk, &clock); | ||
| 777 | memcpy(best_clock, &clock, sizeof(intel_clock_t)); | ||
| 778 | return true; | ||
| 779 | } | ||
| 780 | |||
| 781 | static bool | ||
| 755 | intel_igdng_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, | 782 | intel_igdng_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, |
| 756 | int target, int refclk, intel_clock_t *best_clock) | 783 | int target, int refclk, intel_clock_t *best_clock) |
| 757 | { | 784 | { |
| @@ -763,6 +790,10 @@ intel_igdng_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, | |||
| 763 | int err_most = 47; | 790 | int err_most = 47; |
| 764 | found = false; | 791 | found = false; |
| 765 | 792 | ||
| 793 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) | ||
| 794 | return intel_find_pll_igdng_dp(limit, crtc, target, | ||
| 795 | refclk, best_clock); | ||
| 796 | |||
| 766 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) { | 797 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) { |
| 767 | if ((I915_READ(LVDS) & LVDS_CLKB_POWER_MASK) == | 798 | if ((I915_READ(LVDS) & LVDS_CLKB_POWER_MASK) == |
| 768 | LVDS_CLKB_POWER_UP) | 799 | LVDS_CLKB_POWER_UP) |
| @@ -2136,6 +2167,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
| 2136 | int lvds_reg = LVDS; | 2167 | int lvds_reg = LVDS; |
| 2137 | u32 temp; | 2168 | u32 temp; |
| 2138 | int sdvo_pixel_multiply; | 2169 | int sdvo_pixel_multiply; |
| 2170 | int target_clock; | ||
| 2139 | 2171 | ||
| 2140 | drm_vblank_pre_modeset(dev, pipe); | 2172 | drm_vblank_pre_modeset(dev, pipe); |
| 2141 | 2173 | ||
| @@ -2218,11 +2250,18 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
| 2218 | } | 2250 | } |
| 2219 | 2251 | ||
| 2220 | /* FDI link */ | 2252 | /* FDI link */ |
| 2221 | if (IS_IGDNG(dev)) | 2253 | if (IS_IGDNG(dev)) { |
| 2254 | /* DP over FDI requires target mode clock | ||
| 2255 | instead of link clock */ | ||
| 2256 | if (is_dp) | ||
| 2257 | target_clock = mode->clock; | ||
| 2258 | else | ||
| 2259 | target_clock = adjusted_mode->clock; | ||
| 2222 | igdng_compute_m_n(3, 4, /* lane num 4 */ | 2260 | igdng_compute_m_n(3, 4, /* lane num 4 */ |
| 2223 | adjusted_mode->clock, | 2261 | target_clock, |
| 2224 | 270000, /* lane clock */ | 2262 | 270000, /* lane clock */ |
| 2225 | &m_n); | 2263 | &m_n); |
| 2264 | } | ||
| 2226 | 2265 | ||
| 2227 | if (IS_IGD(dev)) | 2266 | if (IS_IGD(dev)) |
| 2228 | fp = (1 << clock.n) << 16 | clock.m1 << 8 | clock.m2; | 2267 | fp = (1 << clock.n) << 16 | clock.m1 << 8 | clock.m2; |
| @@ -3050,6 +3089,8 @@ static void intel_setup_outputs(struct drm_device *dev) | |||
| 3050 | found = 0; | 3089 | found = 0; |
| 3051 | if (!found) | 3090 | if (!found) |
| 3052 | intel_hdmi_init(dev, HDMIB); | 3091 | intel_hdmi_init(dev, HDMIB); |
| 3092 | if (!found && (I915_READ(PCH_DP_B) & DP_DETECTED)) | ||
| 3093 | intel_dp_init(dev, PCH_DP_B); | ||
| 3053 | } | 3094 | } |
| 3054 | 3095 | ||
| 3055 | if (I915_READ(HDMIC) & PORT_DETECTED) | 3096 | if (I915_READ(HDMIC) & PORT_DETECTED) |
| @@ -3058,6 +3099,12 @@ static void intel_setup_outputs(struct drm_device *dev) | |||
| 3058 | if (I915_READ(HDMID) & PORT_DETECTED) | 3099 | if (I915_READ(HDMID) & PORT_DETECTED) |
| 3059 | intel_hdmi_init(dev, HDMID); | 3100 | intel_hdmi_init(dev, HDMID); |
| 3060 | 3101 | ||
| 3102 | if (I915_READ(PCH_DP_C) & DP_DETECTED) | ||
| 3103 | intel_dp_init(dev, PCH_DP_C); | ||
| 3104 | |||
| 3105 | if (I915_READ(PCH_DP_D) & DP_DETECTED) | ||
| 3106 | intel_dp_init(dev, PCH_DP_D); | ||
| 3107 | |||
| 3061 | } else if (IS_I9XX(dev)) { | 3108 | } else if (IS_I9XX(dev)) { |
| 3062 | int found; | 3109 | int found; |
| 3063 | u32 reg; | 3110 | u32 reg; |
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index afec65c5ad8a..0715911cbd84 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c | |||
| @@ -206,7 +206,12 @@ intel_dp_aux_ch(struct intel_output *intel_output, | |||
| 206 | * and would like to run at 2MHz. So, take the | 206 | * and would like to run at 2MHz. So, take the |
| 207 | * hrawclk value and divide by 2 and use that | 207 | * hrawclk value and divide by 2 and use that |
| 208 | */ | 208 | */ |
| 209 | aux_clock_divider = intel_hrawclk(dev) / 2; | 209 | /* IGDNG: input clock fixed at 125Mhz, so aux_bit_clk always 62 */ |
| 210 | if (IS_IGDNG(dev)) | ||
| 211 | aux_clock_divider = 62; | ||
| 212 | else | ||
| 213 | aux_clock_divider = intel_hrawclk(dev) / 2; | ||
| 214 | |||
| 210 | /* Must try at least 3 times according to DP spec */ | 215 | /* Must try at least 3 times according to DP spec */ |
| 211 | for (try = 0; try < 5; try++) { | 216 | for (try = 0; try < 5; try++) { |
| 212 | /* Load the send data into the aux channel data registers */ | 217 | /* Load the send data into the aux channel data registers */ |
| @@ -493,22 +498,40 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode, | |||
| 493 | intel_dp_compute_m_n(3, lane_count, | 498 | intel_dp_compute_m_n(3, lane_count, |
| 494 | mode->clock, adjusted_mode->clock, &m_n); | 499 | mode->clock, adjusted_mode->clock, &m_n); |
| 495 | 500 | ||
| 496 | if (intel_crtc->pipe == 0) { | 501 | if (IS_IGDNG(dev)) { |
| 497 | I915_WRITE(PIPEA_GMCH_DATA_M, | 502 | if (intel_crtc->pipe == 0) { |
| 498 | ((m_n.tu - 1) << PIPE_GMCH_DATA_M_TU_SIZE_SHIFT) | | 503 | I915_WRITE(TRANSA_DATA_M1, |
| 499 | m_n.gmch_m); | 504 | ((m_n.tu - 1) << PIPE_GMCH_DATA_M_TU_SIZE_SHIFT) | |
| 500 | I915_WRITE(PIPEA_GMCH_DATA_N, | 505 | m_n.gmch_m); |
| 501 | m_n.gmch_n); | 506 | I915_WRITE(TRANSA_DATA_N1, m_n.gmch_n); |
| 502 | I915_WRITE(PIPEA_DP_LINK_M, m_n.link_m); | 507 | I915_WRITE(TRANSA_DP_LINK_M1, m_n.link_m); |
| 503 | I915_WRITE(PIPEA_DP_LINK_N, m_n.link_n); | 508 | I915_WRITE(TRANSA_DP_LINK_N1, m_n.link_n); |
| 509 | } else { | ||
| 510 | I915_WRITE(TRANSB_DATA_M1, | ||
| 511 | ((m_n.tu - 1) << PIPE_GMCH_DATA_M_TU_SIZE_SHIFT) | | ||
| 512 | m_n.gmch_m); | ||
| 513 | I915_WRITE(TRANSB_DATA_N1, m_n.gmch_n); | ||
| 514 | I915_WRITE(TRANSB_DP_LINK_M1, m_n.link_m); | ||
| 515 | I915_WRITE(TRANSB_DP_LINK_N1, m_n.link_n); | ||
| 516 | } | ||
| 504 | } else { | 517 | } else { |
| 505 | I915_WRITE(PIPEB_GMCH_DATA_M, | 518 | if (intel_crtc->pipe == 0) { |
| 506 | ((m_n.tu - 1) << PIPE_GMCH_DATA_M_TU_SIZE_SHIFT) | | 519 | I915_WRITE(PIPEA_GMCH_DATA_M, |
| 507 | m_n.gmch_m); | 520 | ((m_n.tu - 1) << PIPE_GMCH_DATA_M_TU_SIZE_SHIFT) | |
| 508 | I915_WRITE(PIPEB_GMCH_DATA_N, | 521 | m_n.gmch_m); |
| 509 | m_n.gmch_n); | 522 | I915_WRITE(PIPEA_GMCH_DATA_N, |
| 510 | I915_WRITE(PIPEB_DP_LINK_M, m_n.link_m); | 523 | m_n.gmch_n); |
| 511 | I915_WRITE(PIPEB_DP_LINK_N, m_n.link_n); | 524 | I915_WRITE(PIPEA_DP_LINK_M, m_n.link_m); |
| 525 | I915_WRITE(PIPEA_DP_LINK_N, m_n.link_n); | ||
| 526 | } else { | ||
| 527 | I915_WRITE(PIPEB_GMCH_DATA_M, | ||
| 528 | ((m_n.tu - 1) << PIPE_GMCH_DATA_M_TU_SIZE_SHIFT) | | ||
| 529 | m_n.gmch_m); | ||
| 530 | I915_WRITE(PIPEB_GMCH_DATA_N, | ||
| 531 | m_n.gmch_n); | ||
| 532 | I915_WRITE(PIPEB_DP_LINK_M, m_n.link_m); | ||
| 533 | I915_WRITE(PIPEB_DP_LINK_N, m_n.link_n); | ||
| 534 | } | ||
| 512 | } | 535 | } |
| 513 | } | 536 | } |
| 514 | 537 | ||
| @@ -935,6 +958,12 @@ intel_dp_link_down(struct intel_output *intel_output, uint32_t DP) | |||
| 935 | struct drm_i915_private *dev_priv = dev->dev_private; | 958 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 936 | struct intel_dp_priv *dp_priv = intel_output->dev_priv; | 959 | struct intel_dp_priv *dp_priv = intel_output->dev_priv; |
| 937 | 960 | ||
| 961 | DP &= ~DP_LINK_TRAIN_MASK; | ||
| 962 | I915_WRITE(dp_priv->output_reg, DP | DP_LINK_TRAIN_PAT_IDLE); | ||
| 963 | POSTING_READ(dp_priv->output_reg); | ||
| 964 | |||
| 965 | udelay(17000); | ||
| 966 | |||
| 938 | I915_WRITE(dp_priv->output_reg, DP & ~DP_PORT_EN); | 967 | I915_WRITE(dp_priv->output_reg, DP & ~DP_PORT_EN); |
| 939 | POSTING_READ(dp_priv->output_reg); | 968 | POSTING_READ(dp_priv->output_reg); |
| 940 | } | 969 | } |
| @@ -978,6 +1007,24 @@ intel_dp_check_link_status(struct intel_output *intel_output) | |||
| 978 | intel_dp_link_train(intel_output, dp_priv->DP, dp_priv->link_configuration); | 1007 | intel_dp_link_train(intel_output, dp_priv->DP, dp_priv->link_configuration); |
| 979 | } | 1008 | } |
| 980 | 1009 | ||
| 1010 | static enum drm_connector_status | ||
| 1011 | igdng_dp_detect(struct drm_connector *connector) | ||
| 1012 | { | ||
| 1013 | struct intel_output *intel_output = to_intel_output(connector); | ||
| 1014 | struct intel_dp_priv *dp_priv = intel_output->dev_priv; | ||
| 1015 | enum drm_connector_status status; | ||
| 1016 | |||
| 1017 | status = connector_status_disconnected; | ||
| 1018 | if (intel_dp_aux_native_read(intel_output, | ||
| 1019 | 0x000, dp_priv->dpcd, | ||
| 1020 | sizeof (dp_priv->dpcd)) == sizeof (dp_priv->dpcd)) | ||
| 1021 | { | ||
| 1022 | if (dp_priv->dpcd[0] != 0) | ||
| 1023 | status = connector_status_connected; | ||
| 1024 | } | ||
| 1025 | return status; | ||
| 1026 | } | ||
| 1027 | |||
| 981 | /** | 1028 | /** |
| 982 | * Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect DP connection. | 1029 | * Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect DP connection. |
| 983 | * | 1030 | * |
| @@ -996,6 +1043,9 @@ intel_dp_detect(struct drm_connector *connector) | |||
| 996 | 1043 | ||
| 997 | dp_priv->has_audio = false; | 1044 | dp_priv->has_audio = false; |
| 998 | 1045 | ||
| 1046 | if (IS_IGDNG(dev)) | ||
| 1047 | return igdng_dp_detect(connector); | ||
| 1048 | |||
| 999 | temp = I915_READ(PORT_HOTPLUG_EN); | 1049 | temp = I915_READ(PORT_HOTPLUG_EN); |
| 1000 | 1050 | ||
| 1001 | I915_WRITE(PORT_HOTPLUG_EN, | 1051 | I915_WRITE(PORT_HOTPLUG_EN, |
| @@ -1106,6 +1156,7 @@ intel_dp_init(struct drm_device *dev, int output_reg) | |||
| 1106 | struct drm_connector *connector; | 1156 | struct drm_connector *connector; |
| 1107 | struct intel_output *intel_output; | 1157 | struct intel_output *intel_output; |
| 1108 | struct intel_dp_priv *dp_priv; | 1158 | struct intel_dp_priv *dp_priv; |
| 1159 | const char *name = NULL; | ||
| 1109 | 1160 | ||
| 1110 | intel_output = kcalloc(sizeof(struct intel_output) + | 1161 | intel_output = kcalloc(sizeof(struct intel_output) + |
| 1111 | sizeof(struct intel_dp_priv), 1, GFP_KERNEL); | 1162 | sizeof(struct intel_dp_priv), 1, GFP_KERNEL); |
| @@ -1139,9 +1190,22 @@ intel_dp_init(struct drm_device *dev, int output_reg) | |||
| 1139 | drm_sysfs_connector_add(connector); | 1190 | drm_sysfs_connector_add(connector); |
| 1140 | 1191 | ||
| 1141 | /* Set up the DDC bus. */ | 1192 | /* Set up the DDC bus. */ |
| 1142 | intel_dp_i2c_init(intel_output, | 1193 | switch (output_reg) { |
| 1143 | (output_reg == DP_B) ? "DPDDC-B" : | 1194 | case DP_B: |
| 1144 | (output_reg == DP_C) ? "DPDDC-C" : "DPDDC-D"); | 1195 | case PCH_DP_B: |
| 1196 | name = "DPDDC-B"; | ||
| 1197 | break; | ||
| 1198 | case DP_C: | ||
| 1199 | case PCH_DP_C: | ||
| 1200 | name = "DPDDC-C"; | ||
| 1201 | break; | ||
| 1202 | case DP_D: | ||
| 1203 | case PCH_DP_D: | ||
| 1204 | name = "DPDDC-D"; | ||
| 1205 | break; | ||
| 1206 | } | ||
| 1207 | |||
| 1208 | intel_dp_i2c_init(intel_output, name); | ||
| 1145 | intel_output->ddc_bus = &dp_priv->adapter; | 1209 | intel_output->ddc_bus = &dp_priv->adapter; |
| 1146 | intel_output->hot_plug = intel_dp_hot_plug; | 1210 | intel_output->hot_plug = intel_dp_hot_plug; |
| 1147 | 1211 | ||
