diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2010-10-03 05:56:11 -0400 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2010-10-03 05:56:11 -0400 |
commit | 58e10eb92d36a62568349d985c9140d9be16a99c (patch) | |
tree | 6ffaf65e64db390f6a28c1dca8c43d4eb1493f94 /drivers/gpu/drm/i915 | |
parent | 1cdf7fef793c715d8c4998575aba3741fa4a0b01 (diff) | |
parent | ab7ad7f6451580aa7eccc0ba62807c872088a8f9 (diff) |
Merge branch 'drm-intel-fixes' into drm-intel-next
Conflicts:
drivers/gpu/drm/i915/i915_gem_evict.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp.c
Diffstat (limited to 'drivers/gpu/drm/i915')
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem_evict.c | 42 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_reg.h | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 57 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_dp.c | 23 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_drv.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_tv.c | 2 |
7 files changed, 74 insertions, 59 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index a78c97340605..19acf123c1f1 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
@@ -3379,6 +3379,8 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj, | |||
3379 | (int) reloc->offset, | 3379 | (int) reloc->offset, |
3380 | reloc->read_domains, | 3380 | reloc->read_domains, |
3381 | reloc->write_domain); | 3381 | reloc->write_domain); |
3382 | drm_gem_object_unreference(target_obj); | ||
3383 | i915_gem_object_unpin(obj); | ||
3382 | return -EINVAL; | 3384 | return -EINVAL; |
3383 | } | 3385 | } |
3384 | if (reloc->write_domain & I915_GEM_DOMAIN_CPU || | 3386 | if (reloc->write_domain & I915_GEM_DOMAIN_CPU || |
diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c b/drivers/gpu/drm/i915/i915_gem_evict.c index c503c81f4cdf..3d7fbf32bb18 100644 --- a/drivers/gpu/drm/i915/i915_gem_evict.c +++ b/drivers/gpu/drm/i915/i915_gem_evict.c | |||
@@ -93,7 +93,7 @@ i915_gem_evict_something(struct drm_device *dev, int min_size, unsigned alignmen | |||
93 | { | 93 | { |
94 | drm_i915_private_t *dev_priv = dev->dev_private; | 94 | drm_i915_private_t *dev_priv = dev->dev_private; |
95 | struct list_head eviction_list, unwind_list; | 95 | struct list_head eviction_list, unwind_list; |
96 | struct drm_i915_gem_object *obj_priv, *tmp_obj_priv; | 96 | struct drm_i915_gem_object *obj_priv; |
97 | struct list_head *render_iter, *bsd_iter; | 97 | struct list_head *render_iter, *bsd_iter; |
98 | int ret = 0; | 98 | int ret = 0; |
99 | 99 | ||
@@ -175,36 +175,34 @@ i915_gem_evict_something(struct drm_device *dev, int min_size, unsigned alignmen | |||
175 | return -ENOSPC; | 175 | return -ENOSPC; |
176 | 176 | ||
177 | found: | 177 | found: |
178 | /* drm_mm doesn't allow any other other operations while | ||
179 | * scanning, therefore store to be evicted objects on a | ||
180 | * temporary list. */ | ||
178 | INIT_LIST_HEAD(&eviction_list); | 181 | INIT_LIST_HEAD(&eviction_list); |
179 | list_for_each_entry_safe(obj_priv, tmp_obj_priv, | 182 | while (!list_empty(&unwind_list)) { |
180 | &unwind_list, evict_list) { | 183 | obj_priv = list_first_entry(&unwind_list, |
184 | struct drm_i915_gem_object, | ||
185 | evict_list); | ||
181 | if (drm_mm_scan_remove_block(obj_priv->gtt_space)) { | 186 | if (drm_mm_scan_remove_block(obj_priv->gtt_space)) { |
182 | /* drm_mm doesn't allow any other other operations while | ||
183 | * scanning, therefore store to be evicted objects on a | ||
184 | * temporary list. */ | ||
185 | list_move(&obj_priv->evict_list, &eviction_list); | 187 | list_move(&obj_priv->evict_list, &eviction_list); |
186 | } else | 188 | continue; |
187 | drm_gem_object_unreference(&obj_priv->base); | 189 | } |
190 | list_del(&obj_priv->evict_list); | ||
191 | drm_gem_object_unreference(&obj_priv->base); | ||
188 | } | 192 | } |
189 | 193 | ||
190 | /* Unbinding will emit any required flushes */ | 194 | /* Unbinding will emit any required flushes */ |
191 | list_for_each_entry_safe(obj_priv, tmp_obj_priv, | 195 | while (!list_empty(&eviction_list)) { |
192 | &eviction_list, evict_list) { | 196 | obj_priv = list_first_entry(&eviction_list, |
193 | ret = i915_gem_object_unbind(&obj_priv->base); | 197 | struct drm_i915_gem_object, |
194 | if (ret) | 198 | evict_list); |
195 | return ret; | 199 | if (ret == 0) |
196 | 200 | ret = i915_gem_object_unbind(&obj_priv->base); | |
201 | list_del(&obj_priv->evict_list); | ||
197 | drm_gem_object_unreference(&obj_priv->base); | 202 | drm_gem_object_unreference(&obj_priv->base); |
198 | } | 203 | } |
199 | 204 | ||
200 | /* The just created free hole should be on the top of the free stack | 205 | return ret; |
201 | * maintained by drm_mm, so this BUG_ON actually executes in O(1). | ||
202 | * Furthermore all accessed data has just recently been used, so it | ||
203 | * should be really fast, too. */ | ||
204 | BUG_ON(!drm_mm_search_free(&dev_priv->mm.gtt_space, min_size, | ||
205 | alignment, 0)); | ||
206 | |||
207 | return 0; | ||
208 | } | 206 | } |
209 | 207 | ||
210 | int | 208 | int |
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 58cfea25a645..d02de212e6ad 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h | |||
@@ -2105,7 +2105,7 @@ | |||
2105 | 2105 | ||
2106 | /* Pipe A */ | 2106 | /* Pipe A */ |
2107 | #define PIPEADSL 0x70000 | 2107 | #define PIPEADSL 0x70000 |
2108 | #define DSL_LINEMASK 0x00000fff | 2108 | #define DSL_LINEMASK 0x00000fff |
2109 | #define PIPEACONF 0x70008 | 2109 | #define PIPEACONF 0x70008 |
2110 | #define PIPECONF_ENABLE (1<<31) | 2110 | #define PIPECONF_ENABLE (1<<31) |
2111 | #define PIPECONF_DISABLE 0 | 2111 | #define PIPECONF_DISABLE 0 |
@@ -2162,13 +2162,14 @@ | |||
2162 | #define PIPE_START_VBLANK_INTERRUPT_STATUS (1UL<<2) /* 965 or later */ | 2162 | #define PIPE_START_VBLANK_INTERRUPT_STATUS (1UL<<2) /* 965 or later */ |
2163 | #define PIPE_VBLANK_INTERRUPT_STATUS (1UL<<1) | 2163 | #define PIPE_VBLANK_INTERRUPT_STATUS (1UL<<1) |
2164 | #define PIPE_OVERLAY_UPDATED_STATUS (1UL<<0) | 2164 | #define PIPE_OVERLAY_UPDATED_STATUS (1UL<<0) |
2165 | #define PIPE_BPC_MASK (7 << 5) /* Ironlake */ | 2165 | #define PIPE_BPC_MASK (7 << 5) /* Ironlake */ |
2166 | #define PIPE_8BPC (0 << 5) | 2166 | #define PIPE_8BPC (0 << 5) |
2167 | #define PIPE_10BPC (1 << 5) | 2167 | #define PIPE_10BPC (1 << 5) |
2168 | #define PIPE_6BPC (2 << 5) | 2168 | #define PIPE_6BPC (2 << 5) |
2169 | #define PIPE_12BPC (3 << 5) | 2169 | #define PIPE_12BPC (3 << 5) |
2170 | 2170 | ||
2171 | #define PIPECONF(pipe) _PIPE(pipe, PIPEACONF, PIPEBCONF) | 2171 | #define PIPECONF(pipe) _PIPE(pipe, PIPEACONF, PIPEBCONF) |
2172 | #define PIPEDSL(pipe) _PIPE(pipe, PIPEADSL, PIPEBDSL) | ||
2172 | 2173 | ||
2173 | #define DSPARB 0x70030 | 2174 | #define DSPARB 0x70030 |
2174 | #define DSPARB_CSTART_MASK (0x7f << 7) | 2175 | #define DSPARB_CSTART_MASK (0x7f << 7) |
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 00214c123ec2..a2e8e15b8f5a 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -1017,8 +1017,8 @@ void intel_wait_for_vblank(struct drm_device *dev, int pipe) | |||
1017 | DRM_DEBUG_KMS("vblank wait timed out\n"); | 1017 | DRM_DEBUG_KMS("vblank wait timed out\n"); |
1018 | } | 1018 | } |
1019 | 1019 | ||
1020 | /** | 1020 | /* |
1021 | * intel_wait_for_vblank_off - wait for vblank after disabling a pipe | 1021 | * intel_wait_for_pipe_off - wait for pipe to turn off |
1022 | * @dev: drm device | 1022 | * @dev: drm device |
1023 | * @pipe: pipe to wait for | 1023 | * @pipe: pipe to wait for |
1024 | * | 1024 | * |
@@ -1026,26 +1026,39 @@ void intel_wait_for_vblank(struct drm_device *dev, int pipe) | |||
1026 | * spinning on the vblank interrupt status bit, since we won't actually | 1026 | * spinning on the vblank interrupt status bit, since we won't actually |
1027 | * see an interrupt when the pipe is disabled. | 1027 | * see an interrupt when the pipe is disabled. |
1028 | * | 1028 | * |
1029 | * So this function waits for the display line value to settle (it | 1029 | * On Gen4 and above: |
1030 | * usually ends up stopping at the start of the next frame). | 1030 | * wait for the pipe register state bit to turn off |
1031 | * | ||
1032 | * Otherwise: | ||
1033 | * wait for the display line value to settle (it usually | ||
1034 | * ends up stopping at the start of the next frame). | ||
1035 | * | ||
1031 | */ | 1036 | */ |
1032 | void intel_wait_for_vblank_off(struct drm_device *dev, int pipe) | 1037 | void intel_wait_for_pipe_off(struct drm_device *dev, int pipe) |
1033 | { | 1038 | { |
1034 | struct drm_i915_private *dev_priv = dev->dev_private; | 1039 | struct drm_i915_private *dev_priv = dev->dev_private; |
1035 | int pipedsl_reg = (pipe == 0 ? PIPEADSL : PIPEBDSL); | 1040 | |
1036 | unsigned long timeout = jiffies + msecs_to_jiffies(100); | 1041 | if (INTEL_INFO(dev)->gen >= 4) { |
1037 | u32 last_line, line; | 1042 | int reg = PIPECONF(pipe); |
1038 | 1043 | ||
1039 | /* Wait for the display line to settle */ | 1044 | /* Wait for the Pipe State to go off */ |
1040 | line = I915_READ(pipedsl_reg) & DSL_LINEMASK; | 1045 | if (wait_for((I915_READ(reg) & I965_PIPECONF_ACTIVE) == 0, |
1041 | do { | 1046 | 100)) |
1042 | last_line = line; | 1047 | DRM_DEBUG_KMS("pipe_off wait timed out\n"); |
1043 | MSLEEP(5); | 1048 | } else { |
1044 | line = I915_READ(pipedsl_reg) & DSL_LINEMASK; | 1049 | u32 last_line; |
1045 | } while (line != last_line && time_after(timeout, jiffies)); | 1050 | int reg = PIPEDSL(pipe); |
1046 | 1051 | unsigned long timeout = jiffies + msecs_to_jiffies(100); | |
1047 | if (line != last_line) | 1052 | |
1048 | DRM_DEBUG_KMS("vblank wait timed out\n"); | 1053 | /* Wait for the display line to settle */ |
1054 | do { | ||
1055 | last_line = I915_READ(reg) & DSL_LINEMASK; | ||
1056 | mdelay(5); | ||
1057 | } while (((I915_READ(reg) & DSL_LINEMASK) != last_line) && | ||
1058 | time_after(timeout, jiffies)); | ||
1059 | if (time_after(jiffies, timeout)) | ||
1060 | DRM_DEBUG_KMS("pipe_off wait timed out\n"); | ||
1061 | } | ||
1049 | } | 1062 | } |
1050 | 1063 | ||
1051 | static void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval) | 1064 | static void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval) |
@@ -2406,7 +2419,7 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc) | |||
2406 | 2419 | ||
2407 | /* Wait for vblank for the disable to take effect */ | 2420 | /* Wait for vblank for the disable to take effect */ |
2408 | if (IS_GEN2(dev)) | 2421 | if (IS_GEN2(dev)) |
2409 | intel_wait_for_vblank_off(dev, pipe); | 2422 | intel_wait_for_vblank(dev, pipe); |
2410 | } | 2423 | } |
2411 | 2424 | ||
2412 | /* Don't disable pipe A or pipe A PLLs if needed */ | 2425 | /* Don't disable pipe A or pipe A PLLs if needed */ |
@@ -2419,9 +2432,9 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc) | |||
2419 | if (temp & PIPECONF_ENABLE) { | 2432 | if (temp & PIPECONF_ENABLE) { |
2420 | I915_WRITE(reg, temp & ~PIPECONF_ENABLE); | 2433 | I915_WRITE(reg, temp & ~PIPECONF_ENABLE); |
2421 | 2434 | ||
2422 | /* Wait for vblank for the disable to take effect. */ | 2435 | /* Wait for the pipe to turn off */ |
2423 | POSTING_READ(reg); | 2436 | POSTING_READ(reg); |
2424 | intel_wait_for_vblank_off(dev, pipe); | 2437 | intel_wait_for_pipe_off(dev, pipe); |
2425 | } | 2438 | } |
2426 | 2439 | ||
2427 | reg = DPLL(pipe); | 2440 | reg = DPLL(pipe); |
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index d19334aa66ad..9e8fe122b0af 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c | |||
@@ -1186,25 +1186,22 @@ intel_channel_eq_ok(struct intel_dp *intel_dp) | |||
1186 | static bool | 1186 | static bool |
1187 | intel_dp_set_link_train(struct intel_dp *intel_dp, | 1187 | intel_dp_set_link_train(struct intel_dp *intel_dp, |
1188 | uint32_t dp_reg_value, | 1188 | uint32_t dp_reg_value, |
1189 | uint8_t dp_train_pat, | 1189 | uint8_t dp_train_pat) |
1190 | bool first) | ||
1191 | { | 1190 | { |
1192 | struct drm_device *dev = intel_dp->base.base.dev; | 1191 | struct drm_device *dev = intel_dp->base.base.dev; |
1193 | struct drm_i915_private *dev_priv = dev->dev_private; | 1192 | struct drm_i915_private *dev_priv = dev->dev_private; |
1194 | struct intel_crtc *intel_crtc = to_intel_crtc(intel_dp->base.base.crtc); | ||
1195 | int ret; | 1193 | int ret; |
1196 | 1194 | ||
1197 | I915_WRITE(intel_dp->output_reg, dp_reg_value); | 1195 | I915_WRITE(intel_dp->output_reg, dp_reg_value); |
1198 | POSTING_READ(intel_dp->output_reg); | 1196 | POSTING_READ(intel_dp->output_reg); |
1199 | if (first) | ||
1200 | intel_wait_for_vblank(dev, intel_crtc->pipe); | ||
1201 | 1197 | ||
1202 | intel_dp_aux_native_write_1(intel_dp, | 1198 | intel_dp_aux_native_write_1(intel_dp, |
1203 | DP_TRAINING_PATTERN_SET, | 1199 | DP_TRAINING_PATTERN_SET, |
1204 | dp_train_pat); | 1200 | dp_train_pat); |
1205 | 1201 | ||
1206 | ret = intel_dp_aux_native_write(intel_dp, | 1202 | ret = intel_dp_aux_native_write(intel_dp, |
1207 | DP_TRAINING_LANE0_SET, intel_dp->train_set, 4); | 1203 | DP_TRAINING_LANE0_SET, |
1204 | intel_dp->train_set, 4); | ||
1208 | if (ret != 4) | 1205 | if (ret != 4) |
1209 | return false; | 1206 | return false; |
1210 | 1207 | ||
@@ -1216,14 +1213,20 @@ static void | |||
1216 | intel_dp_start_link_train(struct intel_dp *intel_dp) | 1213 | intel_dp_start_link_train(struct intel_dp *intel_dp) |
1217 | { | 1214 | { |
1218 | struct drm_device *dev = intel_dp->base.base.dev; | 1215 | struct drm_device *dev = intel_dp->base.base.dev; |
1216 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
1217 | struct intel_crtc *intel_crtc = to_intel_crtc(intel_dp->base.base.crtc); | ||
1219 | int i; | 1218 | int i; |
1220 | uint8_t voltage; | 1219 | uint8_t voltage; |
1221 | bool clock_recovery = false; | 1220 | bool clock_recovery = false; |
1222 | bool first = true; | ||
1223 | int tries; | 1221 | int tries; |
1224 | u32 reg; | 1222 | u32 reg; |
1225 | uint32_t DP = intel_dp->DP; | 1223 | uint32_t DP = intel_dp->DP; |
1226 | 1224 | ||
1225 | /* Enable output, wait for it to become active */ | ||
1226 | I915_WRITE(intel_dp->output_reg, intel_dp->DP); | ||
1227 | POSTING_READ(intel_dp->output_reg); | ||
1228 | intel_wait_for_vblank(dev, intel_crtc->pipe); | ||
1229 | |||
1227 | /* Write the link configuration data */ | 1230 | /* Write the link configuration data */ |
1228 | intel_dp_aux_native_write(intel_dp, DP_LINK_BW_SET, | 1231 | intel_dp_aux_native_write(intel_dp, DP_LINK_BW_SET, |
1229 | intel_dp->link_configuration, | 1232 | intel_dp->link_configuration, |
@@ -1255,9 +1258,8 @@ intel_dp_start_link_train(struct intel_dp *intel_dp) | |||
1255 | reg = DP | DP_LINK_TRAIN_PAT_1; | 1258 | reg = DP | DP_LINK_TRAIN_PAT_1; |
1256 | 1259 | ||
1257 | if (!intel_dp_set_link_train(intel_dp, reg, | 1260 | if (!intel_dp_set_link_train(intel_dp, reg, |
1258 | DP_TRAINING_PATTERN_1, first)) | 1261 | DP_TRAINING_PATTERN_1)) |
1259 | break; | 1262 | break; |
1260 | first = false; | ||
1261 | /* Set training pattern 1 */ | 1263 | /* Set training pattern 1 */ |
1262 | 1264 | ||
1263 | udelay(100); | 1265 | udelay(100); |
@@ -1324,8 +1326,7 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp) | |||
1324 | 1326 | ||
1325 | /* channel eq pattern */ | 1327 | /* channel eq pattern */ |
1326 | if (!intel_dp_set_link_train(intel_dp, reg, | 1328 | if (!intel_dp_set_link_train(intel_dp, reg, |
1327 | DP_TRAINING_PATTERN_2, | 1329 | DP_TRAINING_PATTERN_2)) |
1328 | false)) | ||
1329 | break; | 1330 | break; |
1330 | 1331 | ||
1331 | udelay(400); | 1332 | udelay(400); |
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 60ce9305e772..40e99bf27ff7 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h | |||
@@ -242,8 +242,8 @@ extern struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev, | |||
242 | struct drm_crtc *crtc); | 242 | struct drm_crtc *crtc); |
243 | int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data, | 243 | int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data, |
244 | struct drm_file *file_priv); | 244 | struct drm_file *file_priv); |
245 | extern void intel_wait_for_vblank_off(struct drm_device *dev, int pipe); | ||
246 | extern void intel_wait_for_vblank(struct drm_device *dev, int pipe); | 245 | extern void intel_wait_for_vblank(struct drm_device *dev, int pipe); |
246 | extern void intel_wait_for_pipe_off(struct drm_device *dev, int pipe); | ||
247 | extern struct drm_crtc *intel_get_load_detect_pipe(struct intel_encoder *intel_encoder, | 247 | extern struct drm_crtc *intel_get_load_detect_pipe(struct intel_encoder *intel_encoder, |
248 | struct drm_connector *connector, | 248 | struct drm_connector *connector, |
249 | struct drm_display_mode *mode, | 249 | struct drm_display_mode *mode, |
diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index 106560bc84db..2f7681989316 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c | |||
@@ -1170,7 +1170,7 @@ intel_tv_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, | |||
1170 | 1170 | ||
1171 | I915_WRITE(pipeconf_reg, pipeconf & ~PIPECONF_ENABLE); | 1171 | I915_WRITE(pipeconf_reg, pipeconf & ~PIPECONF_ENABLE); |
1172 | /* Wait for vblank for the disable to take effect. */ | 1172 | /* Wait for vblank for the disable to take effect. */ |
1173 | intel_wait_for_vblank_off(dev, intel_crtc->pipe); | 1173 | intel_wait_for_pipe_off(dev, intel_crtc->pipe); |
1174 | 1174 | ||
1175 | /* Filter ctl must be set before TV_WIN_SIZE */ | 1175 | /* Filter ctl must be set before TV_WIN_SIZE */ |
1176 | I915_WRITE(TV_FILTER_CTL_1, TV_AUTO_SCALE); | 1176 | I915_WRITE(TV_FILTER_CTL_1, TV_AUTO_SCALE); |