diff options
author | Jesse Barnes <jbarnes@virtuousgeek.org> | 2011-01-04 18:09:30 -0500 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2011-01-19 07:35:49 -0500 |
commit | b24e71798871089da1a4ab049db2800afc1aac0c (patch) | |
tree | b189257e13929f115641751061edbee8da861fa0 /drivers/gpu/drm/i915/intel_display.c | |
parent | 65993d64a31844ad444694efb2d159eb9c883e49 (diff) |
drm/i915: add pipe/plane enable/disable functions
Add plane enable/disable functions to prevent duplicated code and allow
us to easily check for plane enable/disable requirements (such as pipe
enable, plane status, pll status etc).
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'drivers/gpu/drm/i915/intel_display.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 308 |
1 files changed, 213 insertions, 95 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 9dcad312b6e5..2bf72a4b069f 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -1058,6 +1058,203 @@ void intel_wait_for_pipe_off(struct drm_device *dev, int pipe) | |||
1058 | } | 1058 | } |
1059 | } | 1059 | } |
1060 | 1060 | ||
1061 | static const char *state_string(bool enabled) | ||
1062 | { | ||
1063 | return enabled ? "on" : "off"; | ||
1064 | } | ||
1065 | |||
1066 | /* Only for pre-ILK configs */ | ||
1067 | static void assert_pll(struct drm_i915_private *dev_priv, | ||
1068 | enum pipe pipe, bool state) | ||
1069 | { | ||
1070 | int reg; | ||
1071 | u32 val; | ||
1072 | bool cur_state; | ||
1073 | |||
1074 | reg = DPLL(pipe); | ||
1075 | val = I915_READ(reg); | ||
1076 | cur_state = !!(val & DPLL_VCO_ENABLE); | ||
1077 | WARN(cur_state != state, | ||
1078 | "PLL state assertion failure (expected %s, current %s)\n", | ||
1079 | state_string(state), state_string(cur_state)); | ||
1080 | } | ||
1081 | #define assert_pll_enabled(d, p) assert_pll(d, p, true) | ||
1082 | #define assert_pll_disabled(d, p) assert_pll(d, p, false) | ||
1083 | |||
1084 | static void assert_pipe_enabled(struct drm_i915_private *dev_priv, | ||
1085 | enum pipe pipe) | ||
1086 | { | ||
1087 | int reg; | ||
1088 | u32 val; | ||
1089 | |||
1090 | reg = PIPECONF(pipe); | ||
1091 | val = I915_READ(reg); | ||
1092 | WARN(!(val & PIPECONF_ENABLE), | ||
1093 | "pipe %c assertion failure, should be active but is disabled\n", | ||
1094 | pipe ? 'B' : 'A'); | ||
1095 | } | ||
1096 | |||
1097 | static void assert_plane_enabled(struct drm_i915_private *dev_priv, | ||
1098 | enum plane plane) | ||
1099 | { | ||
1100 | int reg; | ||
1101 | u32 val; | ||
1102 | |||
1103 | reg = DSPCNTR(plane); | ||
1104 | val = I915_READ(reg); | ||
1105 | WARN(!(val & DISPLAY_PLANE_ENABLE), | ||
1106 | "plane %c assertion failure, should be active but is disabled\n", | ||
1107 | plane ? 'B' : 'A'); | ||
1108 | } | ||
1109 | |||
1110 | static void assert_planes_disabled(struct drm_i915_private *dev_priv, | ||
1111 | enum pipe pipe) | ||
1112 | { | ||
1113 | int reg, i; | ||
1114 | u32 val; | ||
1115 | int cur_pipe; | ||
1116 | |||
1117 | /* Need to check both planes against the pipe */ | ||
1118 | for (i = 0; i < 2; i++) { | ||
1119 | reg = DSPCNTR(i); | ||
1120 | val = I915_READ(reg); | ||
1121 | cur_pipe = (val & DISPPLANE_SEL_PIPE_MASK) >> | ||
1122 | DISPPLANE_SEL_PIPE_SHIFT; | ||
1123 | WARN((val & DISPLAY_PLANE_ENABLE) && pipe == cur_pipe, | ||
1124 | "plane %d assertion failure, should be off on pipe %c but is still active\n", | ||
1125 | i, pipe ? 'B' : 'A'); | ||
1126 | } | ||
1127 | } | ||
1128 | |||
1129 | /** | ||
1130 | * intel_enable_pipe - enable a pipe, assertiing requirements | ||
1131 | * @dev_priv: i915 private structure | ||
1132 | * @pipe: pipe to enable | ||
1133 | * | ||
1134 | * Enable @pipe, making sure that various hardware specific requirements | ||
1135 | * are met, if applicable, e.g. PLL enabled, LVDS pairs enabled, etc. | ||
1136 | * | ||
1137 | * @pipe should be %PIPE_A or %PIPE_B. | ||
1138 | * | ||
1139 | * Will wait until the pipe is actually running (i.e. first vblank) before | ||
1140 | * returning. | ||
1141 | */ | ||
1142 | static void intel_enable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe) | ||
1143 | { | ||
1144 | int reg; | ||
1145 | u32 val; | ||
1146 | |||
1147 | /* | ||
1148 | * A pipe without a PLL won't actually be able to drive bits from | ||
1149 | * a plane. On ILK+ the pipe PLLs are integrated, so we don't | ||
1150 | * need the check. | ||
1151 | */ | ||
1152 | if (!HAS_PCH_SPLIT(dev_priv->dev)) | ||
1153 | assert_pll_enabled(dev_priv, pipe); | ||
1154 | |||
1155 | reg = PIPECONF(pipe); | ||
1156 | val = I915_READ(reg); | ||
1157 | val |= PIPECONF_ENABLE; | ||
1158 | I915_WRITE(reg, val); | ||
1159 | POSTING_READ(reg); | ||
1160 | intel_wait_for_vblank(dev_priv->dev, pipe); | ||
1161 | } | ||
1162 | |||
1163 | /** | ||
1164 | * intel_disable_pipe - disable a pipe, assertiing requirements | ||
1165 | * @dev_priv: i915 private structure | ||
1166 | * @pipe: pipe to disable | ||
1167 | * | ||
1168 | * Disable @pipe, making sure that various hardware specific requirements | ||
1169 | * are met, if applicable, e.g. plane disabled, panel fitter off, etc. | ||
1170 | * | ||
1171 | * @pipe should be %PIPE_A or %PIPE_B. | ||
1172 | * | ||
1173 | * Will wait until the pipe has shut down before returning. | ||
1174 | */ | ||
1175 | static void intel_disable_pipe(struct drm_i915_private *dev_priv, | ||
1176 | enum pipe pipe) | ||
1177 | { | ||
1178 | int reg; | ||
1179 | u32 val; | ||
1180 | |||
1181 | /* | ||
1182 | * Make sure planes won't keep trying to pump pixels to us, | ||
1183 | * or we might hang the display. | ||
1184 | */ | ||
1185 | assert_planes_disabled(dev_priv, pipe); | ||
1186 | |||
1187 | /* Don't disable pipe A or pipe A PLLs if needed */ | ||
1188 | if (pipe == PIPE_A && (dev_priv->quirks & QUIRK_PIPEA_FORCE)) | ||
1189 | return; | ||
1190 | |||
1191 | reg = PIPECONF(pipe); | ||
1192 | val = I915_READ(reg); | ||
1193 | val &= ~PIPECONF_ENABLE; | ||
1194 | I915_WRITE(reg, val); | ||
1195 | POSTING_READ(reg); | ||
1196 | intel_wait_for_pipe_off(dev_priv->dev, pipe); | ||
1197 | } | ||
1198 | |||
1199 | /** | ||
1200 | * intel_enable_plane - enable a display plane on a given pipe | ||
1201 | * @dev_priv: i915 private structure | ||
1202 | * @plane: plane to enable | ||
1203 | * @pipe: pipe being fed | ||
1204 | * | ||
1205 | * Enable @plane on @pipe, making sure that @pipe is running first. | ||
1206 | */ | ||
1207 | static void intel_enable_plane(struct drm_i915_private *dev_priv, | ||
1208 | enum plane plane, enum pipe pipe) | ||
1209 | { | ||
1210 | int reg; | ||
1211 | u32 val; | ||
1212 | |||
1213 | /* If the pipe isn't enabled, we can't pump pixels and may hang */ | ||
1214 | assert_pipe_enabled(dev_priv, pipe); | ||
1215 | |||
1216 | reg = DSPCNTR(plane); | ||
1217 | val = I915_READ(reg); | ||
1218 | val |= DISPLAY_PLANE_ENABLE; | ||
1219 | I915_WRITE(reg, val); | ||
1220 | POSTING_READ(reg); | ||
1221 | intel_wait_for_vblank(dev_priv->dev, pipe); | ||
1222 | } | ||
1223 | |||
1224 | /* | ||
1225 | * Plane regs are double buffered, going from enabled->disabled needs a | ||
1226 | * trigger in order to latch. The display address reg provides this. | ||
1227 | */ | ||
1228 | static void intel_flush_display_plane(struct drm_i915_private *dev_priv, | ||
1229 | enum plane plane) | ||
1230 | { | ||
1231 | u32 reg = DSPADDR(plane); | ||
1232 | I915_WRITE(reg, I915_READ(reg)); | ||
1233 | } | ||
1234 | |||
1235 | /** | ||
1236 | * intel_disable_plane - disable a display plane | ||
1237 | * @dev_priv: i915 private structure | ||
1238 | * @plane: plane to disable | ||
1239 | * @pipe: pipe consuming the data | ||
1240 | * | ||
1241 | * Disable @plane; should be an independent operation. | ||
1242 | */ | ||
1243 | static void intel_disable_plane(struct drm_i915_private *dev_priv, | ||
1244 | enum plane plane, enum pipe pipe) | ||
1245 | { | ||
1246 | int reg; | ||
1247 | u32 val; | ||
1248 | |||
1249 | reg = DSPCNTR(plane); | ||
1250 | val = I915_READ(reg); | ||
1251 | val &= ~DISPLAY_PLANE_ENABLE; | ||
1252 | I915_WRITE(reg, val); | ||
1253 | POSTING_READ(reg); | ||
1254 | intel_flush_display_plane(dev_priv, plane); | ||
1255 | intel_wait_for_vblank(dev_priv->dev, pipe); | ||
1256 | } | ||
1257 | |||
1061 | static void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval) | 1258 | static void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval) |
1062 | { | 1259 | { |
1063 | struct drm_device *dev = crtc->dev; | 1260 | struct drm_device *dev = crtc->dev; |
@@ -1982,14 +2179,6 @@ static void ironlake_fdi_enable(struct drm_crtc *crtc) | |||
1982 | } | 2179 | } |
1983 | } | 2180 | } |
1984 | 2181 | ||
1985 | static void intel_flush_display_plane(struct drm_device *dev, | ||
1986 | int plane) | ||
1987 | { | ||
1988 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
1989 | u32 reg = DSPADDR(plane); | ||
1990 | I915_WRITE(reg, I915_READ(reg)); | ||
1991 | } | ||
1992 | |||
1993 | /* | 2182 | /* |
1994 | * When we disable a pipe, we need to clear any pending scanline wait events | 2183 | * When we disable a pipe, we need to clear any pending scanline wait events |
1995 | * to avoid hanging the ring, which we assume we are waiting on. | 2184 | * to avoid hanging the ring, which we assume we are waiting on. |
@@ -2062,22 +2251,8 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc) | |||
2062 | dev_priv->pch_pf_size); | 2251 | dev_priv->pch_pf_size); |
2063 | } | 2252 | } |
2064 | 2253 | ||
2065 | /* Enable CPU pipe */ | 2254 | intel_enable_pipe(dev_priv, pipe); |
2066 | reg = PIPECONF(pipe); | 2255 | intel_enable_plane(dev_priv, plane, pipe); |
2067 | temp = I915_READ(reg); | ||
2068 | if ((temp & PIPECONF_ENABLE) == 0) { | ||
2069 | I915_WRITE(reg, temp | PIPECONF_ENABLE); | ||
2070 | POSTING_READ(reg); | ||
2071 | intel_wait_for_vblank(dev, intel_crtc->pipe); | ||
2072 | } | ||
2073 | |||
2074 | /* configure and enable CPU plane */ | ||
2075 | reg = DSPCNTR(plane); | ||
2076 | temp = I915_READ(reg); | ||
2077 | if ((temp & DISPLAY_PLANE_ENABLE) == 0) { | ||
2078 | I915_WRITE(reg, temp | DISPLAY_PLANE_ENABLE); | ||
2079 | intel_flush_display_plane(dev, plane); | ||
2080 | } | ||
2081 | 2256 | ||
2082 | /* For PCH output, training FDI link */ | 2257 | /* For PCH output, training FDI link */ |
2083 | if (IS_GEN6(dev)) | 2258 | if (IS_GEN6(dev)) |
@@ -2185,27 +2360,13 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc) | |||
2185 | drm_vblank_off(dev, pipe); | 2360 | drm_vblank_off(dev, pipe); |
2186 | intel_crtc_update_cursor(crtc, false); | 2361 | intel_crtc_update_cursor(crtc, false); |
2187 | 2362 | ||
2188 | /* Disable display plane */ | 2363 | intel_disable_plane(dev_priv, plane, pipe); |
2189 | reg = DSPCNTR(plane); | ||
2190 | temp = I915_READ(reg); | ||
2191 | if (temp & DISPLAY_PLANE_ENABLE) { | ||
2192 | I915_WRITE(reg, temp & ~DISPLAY_PLANE_ENABLE); | ||
2193 | intel_flush_display_plane(dev, plane); | ||
2194 | } | ||
2195 | 2364 | ||
2196 | if (dev_priv->cfb_plane == plane && | 2365 | if (dev_priv->cfb_plane == plane && |
2197 | dev_priv->display.disable_fbc) | 2366 | dev_priv->display.disable_fbc) |
2198 | dev_priv->display.disable_fbc(dev); | 2367 | dev_priv->display.disable_fbc(dev); |
2199 | 2368 | ||
2200 | /* disable cpu pipe, disable after all planes disabled */ | 2369 | intel_disable_pipe(dev_priv, pipe); |
2201 | reg = PIPECONF(pipe); | ||
2202 | temp = I915_READ(reg); | ||
2203 | if (temp & PIPECONF_ENABLE) { | ||
2204 | I915_WRITE(reg, temp & ~PIPECONF_ENABLE); | ||
2205 | POSTING_READ(reg); | ||
2206 | /* wait for cpu pipe off, pipe state */ | ||
2207 | intel_wait_for_pipe_off(dev, intel_crtc->pipe); | ||
2208 | } | ||
2209 | 2370 | ||
2210 | /* Disable PF */ | 2371 | /* Disable PF */ |
2211 | I915_WRITE(pipe ? PFB_CTL_1 : PFA_CTL_1, 0); | 2372 | I915_WRITE(pipe ? PFB_CTL_1 : PFA_CTL_1, 0); |
@@ -2400,19 +2561,8 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc) | |||
2400 | udelay(150); | 2561 | udelay(150); |
2401 | } | 2562 | } |
2402 | 2563 | ||
2403 | /* Enable the pipe */ | 2564 | intel_enable_pipe(dev_priv, pipe); |
2404 | reg = PIPECONF(pipe); | 2565 | intel_enable_plane(dev_priv, plane, pipe); |
2405 | temp = I915_READ(reg); | ||
2406 | if ((temp & PIPECONF_ENABLE) == 0) | ||
2407 | I915_WRITE(reg, temp | PIPECONF_ENABLE); | ||
2408 | |||
2409 | /* Enable the plane */ | ||
2410 | reg = DSPCNTR(plane); | ||
2411 | temp = I915_READ(reg); | ||
2412 | if ((temp & DISPLAY_PLANE_ENABLE) == 0) { | ||
2413 | I915_WRITE(reg, temp | DISPLAY_PLANE_ENABLE); | ||
2414 | intel_flush_display_plane(dev, plane); | ||
2415 | } | ||
2416 | 2566 | ||
2417 | intel_crtc_load_lut(crtc); | 2567 | intel_crtc_load_lut(crtc); |
2418 | intel_update_fbc(dev); | 2568 | intel_update_fbc(dev); |
@@ -2444,33 +2594,13 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc) | |||
2444 | dev_priv->display.disable_fbc) | 2594 | dev_priv->display.disable_fbc) |
2445 | dev_priv->display.disable_fbc(dev); | 2595 | dev_priv->display.disable_fbc(dev); |
2446 | 2596 | ||
2447 | /* Disable display plane */ | 2597 | intel_disable_plane(dev_priv, plane, pipe); |
2448 | reg = DSPCNTR(plane); | ||
2449 | temp = I915_READ(reg); | ||
2450 | if (temp & DISPLAY_PLANE_ENABLE) { | ||
2451 | I915_WRITE(reg, temp & ~DISPLAY_PLANE_ENABLE); | ||
2452 | /* Flush the plane changes */ | ||
2453 | intel_flush_display_plane(dev, plane); | ||
2454 | |||
2455 | /* Wait for vblank for the disable to take effect */ | ||
2456 | if (IS_GEN2(dev)) | ||
2457 | intel_wait_for_vblank(dev, pipe); | ||
2458 | } | ||
2459 | 2598 | ||
2460 | /* Don't disable pipe A or pipe A PLLs if needed */ | 2599 | /* Don't disable pipe A or pipe A PLLs if needed */ |
2461 | if (pipe == 0 && (dev_priv->quirks & QUIRK_PIPEA_FORCE)) | 2600 | if (pipe == 0 && (dev_priv->quirks & QUIRK_PIPEA_FORCE)) |
2462 | goto done; | 2601 | goto done; |
2463 | 2602 | ||
2464 | /* Next, disable display pipes */ | 2603 | intel_disable_pipe(dev_priv, pipe); |
2465 | reg = PIPECONF(pipe); | ||
2466 | temp = I915_READ(reg); | ||
2467 | if (temp & PIPECONF_ENABLE) { | ||
2468 | I915_WRITE(reg, temp & ~PIPECONF_ENABLE); | ||
2469 | |||
2470 | /* Wait for the pipe to turn off */ | ||
2471 | POSTING_READ(reg); | ||
2472 | intel_wait_for_pipe_off(dev, pipe); | ||
2473 | } | ||
2474 | 2604 | ||
2475 | reg = DPLL(pipe); | 2605 | reg = DPLL(pipe); |
2476 | temp = I915_READ(reg); | 2606 | temp = I915_READ(reg); |
@@ -4222,11 +4352,8 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
4222 | pipeconf &= ~PIPECONF_DOUBLE_WIDE; | 4352 | pipeconf &= ~PIPECONF_DOUBLE_WIDE; |
4223 | } | 4353 | } |
4224 | 4354 | ||
4225 | if (!HAS_PCH_SPLIT(dev)) { | 4355 | if (!HAS_PCH_SPLIT(dev)) |
4226 | dspcntr |= DISPLAY_PLANE_ENABLE; | ||
4227 | pipeconf |= PIPECONF_ENABLE; | ||
4228 | dpll |= DPLL_VCO_ENABLE; | 4356 | dpll |= DPLL_VCO_ENABLE; |
4229 | } | ||
4230 | 4357 | ||
4231 | DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B'); | 4358 | DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B'); |
4232 | drm_mode_debug_printmodeline(mode); | 4359 | drm_mode_debug_printmodeline(mode); |
@@ -4435,6 +4562,8 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
4435 | 4562 | ||
4436 | I915_WRITE(PIPECONF(pipe), pipeconf); | 4563 | I915_WRITE(PIPECONF(pipe), pipeconf); |
4437 | POSTING_READ(PIPECONF(pipe)); | 4564 | POSTING_READ(PIPECONF(pipe)); |
4565 | if (!HAS_PCH_SPLIT(dev)) | ||
4566 | intel_enable_pipe(dev_priv, pipe); | ||
4438 | 4567 | ||
4439 | intel_wait_for_vblank(dev, pipe); | 4568 | intel_wait_for_vblank(dev, pipe); |
4440 | 4569 | ||
@@ -4445,6 +4574,9 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
4445 | } | 4574 | } |
4446 | 4575 | ||
4447 | I915_WRITE(DSPCNTR(plane), dspcntr); | 4576 | I915_WRITE(DSPCNTR(plane), dspcntr); |
4577 | POSTING_READ(DSPCNTR(plane)); | ||
4578 | if (!HAS_PCH_SPLIT(dev)) | ||
4579 | intel_enable_plane(dev_priv, plane, pipe); | ||
4448 | 4580 | ||
4449 | ret = intel_pipe_set_base(crtc, x, y, old_fb); | 4581 | ret = intel_pipe_set_base(crtc, x, y, old_fb); |
4450 | 4582 | ||
@@ -5583,22 +5715,8 @@ static void intel_sanitize_modesetting(struct drm_device *dev, | |||
5583 | pipe = !pipe; | 5715 | pipe = !pipe; |
5584 | 5716 | ||
5585 | /* Disable the plane and wait for it to stop reading from the pipe. */ | 5717 | /* Disable the plane and wait for it to stop reading from the pipe. */ |
5586 | I915_WRITE(reg, val & ~DISPLAY_PLANE_ENABLE); | 5718 | intel_disable_plane(dev_priv, plane, pipe); |
5587 | intel_flush_display_plane(dev, plane); | 5719 | intel_disable_pipe(dev_priv, pipe); |
5588 | |||
5589 | if (IS_GEN2(dev)) | ||
5590 | intel_wait_for_vblank(dev, pipe); | ||
5591 | |||
5592 | if (pipe == 0 && (dev_priv->quirks & QUIRK_PIPEA_FORCE)) | ||
5593 | return; | ||
5594 | |||
5595 | /* Switch off the pipe. */ | ||
5596 | reg = PIPECONF(pipe); | ||
5597 | val = I915_READ(reg); | ||
5598 | if (val & PIPECONF_ENABLE) { | ||
5599 | I915_WRITE(reg, val & ~PIPECONF_ENABLE); | ||
5600 | intel_wait_for_pipe_off(dev, pipe); | ||
5601 | } | ||
5602 | } | 5720 | } |
5603 | 5721 | ||
5604 | static void intel_crtc_init(struct drm_device *dev, int pipe) | 5722 | static void intel_crtc_init(struct drm_device *dev, int pipe) |