aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm
diff options
context:
space:
mode:
authorZhenyu Wang <zhenyuw@linux.intel.com>2009-07-23 13:00:31 -0400
committerEric Anholt <eric@anholt.net>2009-07-29 18:16:11 -0400
commit5eb08b69f510fadaba77eb9a1bda0f7299c4ebcc (patch)
tree107cb7647464fe2f8db7e7fdd652b90494cb2815 /drivers/gpu/drm
parenteebc863e469cd91d96c4e3636450596ae29f0502 (diff)
drm/i915: enable DisplayPort support on IGDNG
Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com> Signed-off-by: Eric Anholt <eric@anholt.net>
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r--drivers/gpu/drm/i915/i915_reg.h25
-rw-r--r--drivers/gpu/drm/i915/intel_display.c51
-rw-r--r--drivers/gpu/drm/i915/intel_dp.c102
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,
268static bool 268static bool
269intel_find_pll_g4x_dp(const intel_limit_t *, struct drm_crtc *crtc, 269intel_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);
271static bool
272intel_find_pll_igdng_dp(const intel_limit_t *, struct drm_crtc *crtc,
273 int target, int refclk, intel_clock_t *best_clock);
271 274
272static const intel_limit_t intel_limits_i8xx_dvo = { 275static 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
754static bool 757static bool
758intel_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
781static bool
755intel_igdng_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, 782intel_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
1010static enum drm_connector_status
1011igdng_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