diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-12-23 13:22:16 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-12-23 13:22:16 -0500 |
commit | 5b726e06d6e8309e5c9ef4109a32caf27c71dfc8 (patch) | |
tree | adb05b238921b3631063ba54c0077f00b85c375b /drivers/gpu | |
parent | 2bfd43d80679db786e4349dc4711e2075a66d46b (diff) | |
parent | a98728e0bb978fbe9246c93ea89198de612c22e6 (diff) |
Merge tag 'drm-intel-fixes-2015-12-23' of git://anongit.freedesktop.org/drm-intel
Pull i915 drm fixes from Jani Nikula:
"Here's a batch of i915 fixes all around. It may be slightly bigger
than one would hope for at this stage, but they've all been through
testing in our -next before being picked up for v4.4. Also, I missed
Dave's fixes pull earlier today just because I wanted an extra testing
round on this. So I'm fairly confident.
Wishing you all the things it is customary to wish this time of the
year"
* tag 'drm-intel-fixes-2015-12-23' of git://anongit.freedesktop.org/drm-intel:
drm/i915: Correct max delay for HDMI hotplug live status checking
drm/i915: mdelay(10) considered harmful
drm/i915: Kill intel_crtc->cursor_bo
drm/i915: Workaround CHV pipe C cursor fail
drm/i915: Only spin whilst waiting on the current request
drm/i915: Limit the busy wait on requests to 5us not 10ms!
drm/i915: Break busywaiting for requests on pending signals
drm/i915: Disable primary plane if we fail to reconstruct BIOS fb (v2)
drm/i915: Set the map-and-fenceable flag for preallocated objects
drm/i915: Drop the broken cursor base==0 special casing
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 28 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 111 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem_gtt.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem_stolen.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 66 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_drv.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_hdmi.c | 7 |
7 files changed, 154 insertions, 61 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index a01e51581c4c..f4af19a0d569 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
@@ -2193,8 +2193,17 @@ struct drm_i915_gem_request { | |||
2193 | struct drm_i915_private *i915; | 2193 | struct drm_i915_private *i915; |
2194 | struct intel_engine_cs *ring; | 2194 | struct intel_engine_cs *ring; |
2195 | 2195 | ||
2196 | /** GEM sequence number associated with this request. */ | 2196 | /** GEM sequence number associated with the previous request, |
2197 | uint32_t seqno; | 2197 | * when the HWS breadcrumb is equal to this the GPU is processing |
2198 | * this request. | ||
2199 | */ | ||
2200 | u32 previous_seqno; | ||
2201 | |||
2202 | /** GEM sequence number associated with this request, | ||
2203 | * when the HWS breadcrumb is equal or greater than this the GPU | ||
2204 | * has finished processing this request. | ||
2205 | */ | ||
2206 | u32 seqno; | ||
2198 | 2207 | ||
2199 | /** Position in the ringbuffer of the start of the request */ | 2208 | /** Position in the ringbuffer of the start of the request */ |
2200 | u32 head; | 2209 | u32 head; |
@@ -2839,6 +2848,7 @@ i915_gem_object_ggtt_pin(struct drm_i915_gem_object *obj, | |||
2839 | 2848 | ||
2840 | int i915_vma_bind(struct i915_vma *vma, enum i915_cache_level cache_level, | 2849 | int i915_vma_bind(struct i915_vma *vma, enum i915_cache_level cache_level, |
2841 | u32 flags); | 2850 | u32 flags); |
2851 | void __i915_vma_set_map_and_fenceable(struct i915_vma *vma); | ||
2842 | int __must_check i915_vma_unbind(struct i915_vma *vma); | 2852 | int __must_check i915_vma_unbind(struct i915_vma *vma); |
2843 | /* | 2853 | /* |
2844 | * BEWARE: Do not use the function below unless you can _absolutely_ | 2854 | * BEWARE: Do not use the function below unless you can _absolutely_ |
@@ -2910,15 +2920,17 @@ i915_seqno_passed(uint32_t seq1, uint32_t seq2) | |||
2910 | return (int32_t)(seq1 - seq2) >= 0; | 2920 | return (int32_t)(seq1 - seq2) >= 0; |
2911 | } | 2921 | } |
2912 | 2922 | ||
2923 | static inline bool i915_gem_request_started(struct drm_i915_gem_request *req, | ||
2924 | bool lazy_coherency) | ||
2925 | { | ||
2926 | u32 seqno = req->ring->get_seqno(req->ring, lazy_coherency); | ||
2927 | return i915_seqno_passed(seqno, req->previous_seqno); | ||
2928 | } | ||
2929 | |||
2913 | static inline bool i915_gem_request_completed(struct drm_i915_gem_request *req, | 2930 | static inline bool i915_gem_request_completed(struct drm_i915_gem_request *req, |
2914 | bool lazy_coherency) | 2931 | bool lazy_coherency) |
2915 | { | 2932 | { |
2916 | u32 seqno; | 2933 | u32 seqno = req->ring->get_seqno(req->ring, lazy_coherency); |
2917 | |||
2918 | BUG_ON(req == NULL); | ||
2919 | |||
2920 | seqno = req->ring->get_seqno(req->ring, lazy_coherency); | ||
2921 | |||
2922 | return i915_seqno_passed(seqno, req->seqno); | 2934 | return i915_seqno_passed(seqno, req->seqno); |
2923 | } | 2935 | } |
2924 | 2936 | ||
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 32e6aade6223..f56af0aaafde 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
@@ -1146,23 +1146,74 @@ static bool missed_irq(struct drm_i915_private *dev_priv, | |||
1146 | return test_bit(ring->id, &dev_priv->gpu_error.missed_irq_rings); | 1146 | return test_bit(ring->id, &dev_priv->gpu_error.missed_irq_rings); |
1147 | } | 1147 | } |
1148 | 1148 | ||
1149 | static int __i915_spin_request(struct drm_i915_gem_request *req) | 1149 | static unsigned long local_clock_us(unsigned *cpu) |
1150 | { | ||
1151 | unsigned long t; | ||
1152 | |||
1153 | /* Cheaply and approximately convert from nanoseconds to microseconds. | ||
1154 | * The result and subsequent calculations are also defined in the same | ||
1155 | * approximate microseconds units. The principal source of timing | ||
1156 | * error here is from the simple truncation. | ||
1157 | * | ||
1158 | * Note that local_clock() is only defined wrt to the current CPU; | ||
1159 | * the comparisons are no longer valid if we switch CPUs. Instead of | ||
1160 | * blocking preemption for the entire busywait, we can detect the CPU | ||
1161 | * switch and use that as indicator of system load and a reason to | ||
1162 | * stop busywaiting, see busywait_stop(). | ||
1163 | */ | ||
1164 | *cpu = get_cpu(); | ||
1165 | t = local_clock() >> 10; | ||
1166 | put_cpu(); | ||
1167 | |||
1168 | return t; | ||
1169 | } | ||
1170 | |||
1171 | static bool busywait_stop(unsigned long timeout, unsigned cpu) | ||
1172 | { | ||
1173 | unsigned this_cpu; | ||
1174 | |||
1175 | if (time_after(local_clock_us(&this_cpu), timeout)) | ||
1176 | return true; | ||
1177 | |||
1178 | return this_cpu != cpu; | ||
1179 | } | ||
1180 | |||
1181 | static int __i915_spin_request(struct drm_i915_gem_request *req, int state) | ||
1150 | { | 1182 | { |
1151 | unsigned long timeout; | 1183 | unsigned long timeout; |
1184 | unsigned cpu; | ||
1185 | |||
1186 | /* When waiting for high frequency requests, e.g. during synchronous | ||
1187 | * rendering split between the CPU and GPU, the finite amount of time | ||
1188 | * required to set up the irq and wait upon it limits the response | ||
1189 | * rate. By busywaiting on the request completion for a short while we | ||
1190 | * can service the high frequency waits as quick as possible. However, | ||
1191 | * if it is a slow request, we want to sleep as quickly as possible. | ||
1192 | * The tradeoff between waiting and sleeping is roughly the time it | ||
1193 | * takes to sleep on a request, on the order of a microsecond. | ||
1194 | */ | ||
1152 | 1195 | ||
1153 | if (i915_gem_request_get_ring(req)->irq_refcount) | 1196 | if (req->ring->irq_refcount) |
1154 | return -EBUSY; | 1197 | return -EBUSY; |
1155 | 1198 | ||
1156 | timeout = jiffies + 1; | 1199 | /* Only spin if we know the GPU is processing this request */ |
1200 | if (!i915_gem_request_started(req, true)) | ||
1201 | return -EAGAIN; | ||
1202 | |||
1203 | timeout = local_clock_us(&cpu) + 5; | ||
1157 | while (!need_resched()) { | 1204 | while (!need_resched()) { |
1158 | if (i915_gem_request_completed(req, true)) | 1205 | if (i915_gem_request_completed(req, true)) |
1159 | return 0; | 1206 | return 0; |
1160 | 1207 | ||
1161 | if (time_after_eq(jiffies, timeout)) | 1208 | if (signal_pending_state(state, current)) |
1209 | break; | ||
1210 | |||
1211 | if (busywait_stop(timeout, cpu)) | ||
1162 | break; | 1212 | break; |
1163 | 1213 | ||
1164 | cpu_relax_lowlatency(); | 1214 | cpu_relax_lowlatency(); |
1165 | } | 1215 | } |
1216 | |||
1166 | if (i915_gem_request_completed(req, false)) | 1217 | if (i915_gem_request_completed(req, false)) |
1167 | return 0; | 1218 | return 0; |
1168 | 1219 | ||
@@ -1197,6 +1248,7 @@ int __i915_wait_request(struct drm_i915_gem_request *req, | |||
1197 | struct drm_i915_private *dev_priv = dev->dev_private; | 1248 | struct drm_i915_private *dev_priv = dev->dev_private; |
1198 | const bool irq_test_in_progress = | 1249 | const bool irq_test_in_progress = |
1199 | ACCESS_ONCE(dev_priv->gpu_error.test_irq_rings) & intel_ring_flag(ring); | 1250 | ACCESS_ONCE(dev_priv->gpu_error.test_irq_rings) & intel_ring_flag(ring); |
1251 | int state = interruptible ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE; | ||
1200 | DEFINE_WAIT(wait); | 1252 | DEFINE_WAIT(wait); |
1201 | unsigned long timeout_expire; | 1253 | unsigned long timeout_expire; |
1202 | s64 before, now; | 1254 | s64 before, now; |
@@ -1229,7 +1281,7 @@ int __i915_wait_request(struct drm_i915_gem_request *req, | |||
1229 | before = ktime_get_raw_ns(); | 1281 | before = ktime_get_raw_ns(); |
1230 | 1282 | ||
1231 | /* Optimistic spin for the next jiffie before touching IRQs */ | 1283 | /* Optimistic spin for the next jiffie before touching IRQs */ |
1232 | ret = __i915_spin_request(req); | 1284 | ret = __i915_spin_request(req, state); |
1233 | if (ret == 0) | 1285 | if (ret == 0) |
1234 | goto out; | 1286 | goto out; |
1235 | 1287 | ||
@@ -1241,8 +1293,7 @@ int __i915_wait_request(struct drm_i915_gem_request *req, | |||
1241 | for (;;) { | 1293 | for (;;) { |
1242 | struct timer_list timer; | 1294 | struct timer_list timer; |
1243 | 1295 | ||
1244 | prepare_to_wait(&ring->irq_queue, &wait, | 1296 | prepare_to_wait(&ring->irq_queue, &wait, state); |
1245 | interruptible ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE); | ||
1246 | 1297 | ||
1247 | /* We need to check whether any gpu reset happened in between | 1298 | /* We need to check whether any gpu reset happened in between |
1248 | * the caller grabbing the seqno and now ... */ | 1299 | * the caller grabbing the seqno and now ... */ |
@@ -1260,7 +1311,7 @@ int __i915_wait_request(struct drm_i915_gem_request *req, | |||
1260 | break; | 1311 | break; |
1261 | } | 1312 | } |
1262 | 1313 | ||
1263 | if (interruptible && signal_pending(current)) { | 1314 | if (signal_pending_state(state, current)) { |
1264 | ret = -ERESTARTSYS; | 1315 | ret = -ERESTARTSYS; |
1265 | break; | 1316 | break; |
1266 | } | 1317 | } |
@@ -2554,6 +2605,7 @@ void __i915_add_request(struct drm_i915_gem_request *request, | |||
2554 | request->batch_obj = obj; | 2605 | request->batch_obj = obj; |
2555 | 2606 | ||
2556 | request->emitted_jiffies = jiffies; | 2607 | request->emitted_jiffies = jiffies; |
2608 | request->previous_seqno = ring->last_submitted_seqno; | ||
2557 | ring->last_submitted_seqno = request->seqno; | 2609 | ring->last_submitted_seqno = request->seqno; |
2558 | list_add_tail(&request->list, &ring->request_list); | 2610 | list_add_tail(&request->list, &ring->request_list); |
2559 | 2611 | ||
@@ -4080,6 +4132,29 @@ i915_vma_misplaced(struct i915_vma *vma, uint32_t alignment, uint64_t flags) | |||
4080 | return false; | 4132 | return false; |
4081 | } | 4133 | } |
4082 | 4134 | ||
4135 | void __i915_vma_set_map_and_fenceable(struct i915_vma *vma) | ||
4136 | { | ||
4137 | struct drm_i915_gem_object *obj = vma->obj; | ||
4138 | bool mappable, fenceable; | ||
4139 | u32 fence_size, fence_alignment; | ||
4140 | |||
4141 | fence_size = i915_gem_get_gtt_size(obj->base.dev, | ||
4142 | obj->base.size, | ||
4143 | obj->tiling_mode); | ||
4144 | fence_alignment = i915_gem_get_gtt_alignment(obj->base.dev, | ||
4145 | obj->base.size, | ||
4146 | obj->tiling_mode, | ||
4147 | true); | ||
4148 | |||
4149 | fenceable = (vma->node.size == fence_size && | ||
4150 | (vma->node.start & (fence_alignment - 1)) == 0); | ||
4151 | |||
4152 | mappable = (vma->node.start + fence_size <= | ||
4153 | to_i915(obj->base.dev)->gtt.mappable_end); | ||
4154 | |||
4155 | obj->map_and_fenceable = mappable && fenceable; | ||
4156 | } | ||
4157 | |||
4083 | static int | 4158 | static int |
4084 | i915_gem_object_do_pin(struct drm_i915_gem_object *obj, | 4159 | i915_gem_object_do_pin(struct drm_i915_gem_object *obj, |
4085 | struct i915_address_space *vm, | 4160 | struct i915_address_space *vm, |
@@ -4147,25 +4222,7 @@ i915_gem_object_do_pin(struct drm_i915_gem_object *obj, | |||
4147 | 4222 | ||
4148 | if (ggtt_view && ggtt_view->type == I915_GGTT_VIEW_NORMAL && | 4223 | if (ggtt_view && ggtt_view->type == I915_GGTT_VIEW_NORMAL && |
4149 | (bound ^ vma->bound) & GLOBAL_BIND) { | 4224 | (bound ^ vma->bound) & GLOBAL_BIND) { |
4150 | bool mappable, fenceable; | 4225 | __i915_vma_set_map_and_fenceable(vma); |
4151 | u32 fence_size, fence_alignment; | ||
4152 | |||
4153 | fence_size = i915_gem_get_gtt_size(obj->base.dev, | ||
4154 | obj->base.size, | ||
4155 | obj->tiling_mode); | ||
4156 | fence_alignment = i915_gem_get_gtt_alignment(obj->base.dev, | ||
4157 | obj->base.size, | ||
4158 | obj->tiling_mode, | ||
4159 | true); | ||
4160 | |||
4161 | fenceable = (vma->node.size == fence_size && | ||
4162 | (vma->node.start & (fence_alignment - 1)) == 0); | ||
4163 | |||
4164 | mappable = (vma->node.start + fence_size <= | ||
4165 | dev_priv->gtt.mappable_end); | ||
4166 | |||
4167 | obj->map_and_fenceable = mappable && fenceable; | ||
4168 | |||
4169 | WARN_ON(flags & PIN_MAPPABLE && !obj->map_and_fenceable); | 4226 | WARN_ON(flags & PIN_MAPPABLE && !obj->map_and_fenceable); |
4170 | } | 4227 | } |
4171 | 4228 | ||
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 43f35d12b677..86c7500454b4 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c | |||
@@ -2676,6 +2676,7 @@ static int i915_gem_setup_global_gtt(struct drm_device *dev, | |||
2676 | return ret; | 2676 | return ret; |
2677 | } | 2677 | } |
2678 | vma->bound |= GLOBAL_BIND; | 2678 | vma->bound |= GLOBAL_BIND; |
2679 | __i915_vma_set_map_and_fenceable(vma); | ||
2679 | list_add_tail(&vma->mm_list, &ggtt_vm->inactive_list); | 2680 | list_add_tail(&vma->mm_list, &ggtt_vm->inactive_list); |
2680 | } | 2681 | } |
2681 | 2682 | ||
diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c index cdacf3f5b77a..87e919a06b27 100644 --- a/drivers/gpu/drm/i915/i915_gem_stolen.c +++ b/drivers/gpu/drm/i915/i915_gem_stolen.c | |||
@@ -687,6 +687,7 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_device *dev, | |||
687 | } | 687 | } |
688 | 688 | ||
689 | vma->bound |= GLOBAL_BIND; | 689 | vma->bound |= GLOBAL_BIND; |
690 | __i915_vma_set_map_and_fenceable(vma); | ||
690 | list_add_tail(&vma->mm_list, &ggtt->inactive_list); | 691 | list_add_tail(&vma->mm_list, &ggtt->inactive_list); |
691 | } | 692 | } |
692 | 693 | ||
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 62211abe4922..beb0374a19f1 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -116,6 +116,7 @@ static void skylake_pfit_enable(struct intel_crtc *crtc); | |||
116 | static void ironlake_pfit_disable(struct intel_crtc *crtc, bool force); | 116 | static void ironlake_pfit_disable(struct intel_crtc *crtc, bool force); |
117 | static void ironlake_pfit_enable(struct intel_crtc *crtc); | 117 | static void ironlake_pfit_enable(struct intel_crtc *crtc); |
118 | static void intel_modeset_setup_hw_state(struct drm_device *dev); | 118 | static void intel_modeset_setup_hw_state(struct drm_device *dev); |
119 | static void intel_pre_disable_primary(struct drm_crtc *crtc); | ||
119 | 120 | ||
120 | typedef struct { | 121 | typedef struct { |
121 | int min, max; | 122 | int min, max; |
@@ -2607,6 +2608,8 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc, | |||
2607 | struct drm_i915_gem_object *obj; | 2608 | struct drm_i915_gem_object *obj; |
2608 | struct drm_plane *primary = intel_crtc->base.primary; | 2609 | struct drm_plane *primary = intel_crtc->base.primary; |
2609 | struct drm_plane_state *plane_state = primary->state; | 2610 | struct drm_plane_state *plane_state = primary->state; |
2611 | struct drm_crtc_state *crtc_state = intel_crtc->base.state; | ||
2612 | struct intel_plane *intel_plane = to_intel_plane(primary); | ||
2610 | struct drm_framebuffer *fb; | 2613 | struct drm_framebuffer *fb; |
2611 | 2614 | ||
2612 | if (!plane_config->fb) | 2615 | if (!plane_config->fb) |
@@ -2643,6 +2646,18 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc, | |||
2643 | } | 2646 | } |
2644 | } | 2647 | } |
2645 | 2648 | ||
2649 | /* | ||
2650 | * We've failed to reconstruct the BIOS FB. Current display state | ||
2651 | * indicates that the primary plane is visible, but has a NULL FB, | ||
2652 | * which will lead to problems later if we don't fix it up. The | ||
2653 | * simplest solution is to just disable the primary plane now and | ||
2654 | * pretend the BIOS never had it enabled. | ||
2655 | */ | ||
2656 | to_intel_plane_state(plane_state)->visible = false; | ||
2657 | crtc_state->plane_mask &= ~(1 << drm_plane_index(primary)); | ||
2658 | intel_pre_disable_primary(&intel_crtc->base); | ||
2659 | intel_plane->disable_plane(primary, &intel_crtc->base); | ||
2660 | |||
2646 | return; | 2661 | return; |
2647 | 2662 | ||
2648 | valid_fb: | 2663 | valid_fb: |
@@ -9910,14 +9925,14 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc, | |||
9910 | return true; | 9925 | return true; |
9911 | } | 9926 | } |
9912 | 9927 | ||
9913 | static void i845_update_cursor(struct drm_crtc *crtc, u32 base) | 9928 | static void i845_update_cursor(struct drm_crtc *crtc, u32 base, bool on) |
9914 | { | 9929 | { |
9915 | struct drm_device *dev = crtc->dev; | 9930 | struct drm_device *dev = crtc->dev; |
9916 | struct drm_i915_private *dev_priv = dev->dev_private; | 9931 | struct drm_i915_private *dev_priv = dev->dev_private; |
9917 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 9932 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
9918 | uint32_t cntl = 0, size = 0; | 9933 | uint32_t cntl = 0, size = 0; |
9919 | 9934 | ||
9920 | if (base) { | 9935 | if (on) { |
9921 | unsigned int width = intel_crtc->base.cursor->state->crtc_w; | 9936 | unsigned int width = intel_crtc->base.cursor->state->crtc_w; |
9922 | unsigned int height = intel_crtc->base.cursor->state->crtc_h; | 9937 | unsigned int height = intel_crtc->base.cursor->state->crtc_h; |
9923 | unsigned int stride = roundup_pow_of_two(width) * 4; | 9938 | unsigned int stride = roundup_pow_of_two(width) * 4; |
@@ -9972,16 +9987,15 @@ static void i845_update_cursor(struct drm_crtc *crtc, u32 base) | |||
9972 | } | 9987 | } |
9973 | } | 9988 | } |
9974 | 9989 | ||
9975 | static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base) | 9990 | static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base, bool on) |
9976 | { | 9991 | { |
9977 | struct drm_device *dev = crtc->dev; | 9992 | struct drm_device *dev = crtc->dev; |
9978 | struct drm_i915_private *dev_priv = dev->dev_private; | 9993 | struct drm_i915_private *dev_priv = dev->dev_private; |
9979 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 9994 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
9980 | int pipe = intel_crtc->pipe; | 9995 | int pipe = intel_crtc->pipe; |
9981 | uint32_t cntl; | 9996 | uint32_t cntl = 0; |
9982 | 9997 | ||
9983 | cntl = 0; | 9998 | if (on) { |
9984 | if (base) { | ||
9985 | cntl = MCURSOR_GAMMA_ENABLE; | 9999 | cntl = MCURSOR_GAMMA_ENABLE; |
9986 | switch (intel_crtc->base.cursor->state->crtc_w) { | 10000 | switch (intel_crtc->base.cursor->state->crtc_w) { |
9987 | case 64: | 10001 | case 64: |
@@ -10032,18 +10046,17 @@ static void intel_crtc_update_cursor(struct drm_crtc *crtc, | |||
10032 | int y = cursor_state->crtc_y; | 10046 | int y = cursor_state->crtc_y; |
10033 | u32 base = 0, pos = 0; | 10047 | u32 base = 0, pos = 0; |
10034 | 10048 | ||
10035 | if (on) | 10049 | base = intel_crtc->cursor_addr; |
10036 | base = intel_crtc->cursor_addr; | ||
10037 | 10050 | ||
10038 | if (x >= intel_crtc->config->pipe_src_w) | 10051 | if (x >= intel_crtc->config->pipe_src_w) |
10039 | base = 0; | 10052 | on = false; |
10040 | 10053 | ||
10041 | if (y >= intel_crtc->config->pipe_src_h) | 10054 | if (y >= intel_crtc->config->pipe_src_h) |
10042 | base = 0; | 10055 | on = false; |
10043 | 10056 | ||
10044 | if (x < 0) { | 10057 | if (x < 0) { |
10045 | if (x + cursor_state->crtc_w <= 0) | 10058 | if (x + cursor_state->crtc_w <= 0) |
10046 | base = 0; | 10059 | on = false; |
10047 | 10060 | ||
10048 | pos |= CURSOR_POS_SIGN << CURSOR_X_SHIFT; | 10061 | pos |= CURSOR_POS_SIGN << CURSOR_X_SHIFT; |
10049 | x = -x; | 10062 | x = -x; |
@@ -10052,16 +10065,13 @@ static void intel_crtc_update_cursor(struct drm_crtc *crtc, | |||
10052 | 10065 | ||
10053 | if (y < 0) { | 10066 | if (y < 0) { |
10054 | if (y + cursor_state->crtc_h <= 0) | 10067 | if (y + cursor_state->crtc_h <= 0) |
10055 | base = 0; | 10068 | on = false; |
10056 | 10069 | ||
10057 | pos |= CURSOR_POS_SIGN << CURSOR_Y_SHIFT; | 10070 | pos |= CURSOR_POS_SIGN << CURSOR_Y_SHIFT; |
10058 | y = -y; | 10071 | y = -y; |
10059 | } | 10072 | } |
10060 | pos |= y << CURSOR_Y_SHIFT; | 10073 | pos |= y << CURSOR_Y_SHIFT; |
10061 | 10074 | ||
10062 | if (base == 0 && intel_crtc->cursor_base == 0) | ||
10063 | return; | ||
10064 | |||
10065 | I915_WRITE(CURPOS(pipe), pos); | 10075 | I915_WRITE(CURPOS(pipe), pos); |
10066 | 10076 | ||
10067 | /* ILK+ do this automagically */ | 10077 | /* ILK+ do this automagically */ |
@@ -10072,9 +10082,9 @@ static void intel_crtc_update_cursor(struct drm_crtc *crtc, | |||
10072 | } | 10082 | } |
10073 | 10083 | ||
10074 | if (IS_845G(dev) || IS_I865G(dev)) | 10084 | if (IS_845G(dev) || IS_I865G(dev)) |
10075 | i845_update_cursor(crtc, base); | 10085 | i845_update_cursor(crtc, base, on); |
10076 | else | 10086 | else |
10077 | i9xx_update_cursor(crtc, base); | 10087 | i9xx_update_cursor(crtc, base, on); |
10078 | } | 10088 | } |
10079 | 10089 | ||
10080 | static bool cursor_size_ok(struct drm_device *dev, | 10090 | static bool cursor_size_ok(struct drm_device *dev, |
@@ -13718,6 +13728,7 @@ intel_check_cursor_plane(struct drm_plane *plane, | |||
13718 | struct drm_crtc *crtc = crtc_state->base.crtc; | 13728 | struct drm_crtc *crtc = crtc_state->base.crtc; |
13719 | struct drm_framebuffer *fb = state->base.fb; | 13729 | struct drm_framebuffer *fb = state->base.fb; |
13720 | struct drm_i915_gem_object *obj = intel_fb_obj(fb); | 13730 | struct drm_i915_gem_object *obj = intel_fb_obj(fb); |
13731 | enum pipe pipe = to_intel_plane(plane)->pipe; | ||
13721 | unsigned stride; | 13732 | unsigned stride; |
13722 | int ret; | 13733 | int ret; |
13723 | 13734 | ||
@@ -13751,6 +13762,22 @@ intel_check_cursor_plane(struct drm_plane *plane, | |||
13751 | return -EINVAL; | 13762 | return -EINVAL; |
13752 | } | 13763 | } |
13753 | 13764 | ||
13765 | /* | ||
13766 | * There's something wrong with the cursor on CHV pipe C. | ||
13767 | * If it straddles the left edge of the screen then | ||
13768 | * moving it away from the edge or disabling it often | ||
13769 | * results in a pipe underrun, and often that can lead to | ||
13770 | * dead pipe (constant underrun reported, and it scans | ||
13771 | * out just a solid color). To recover from that, the | ||
13772 | * display power well must be turned off and on again. | ||
13773 | * Refuse the put the cursor into that compromised position. | ||
13774 | */ | ||
13775 | if (IS_CHERRYVIEW(plane->dev) && pipe == PIPE_C && | ||
13776 | state->visible && state->base.crtc_x < 0) { | ||
13777 | DRM_DEBUG_KMS("CHV cursor C not allowed to straddle the left screen edge\n"); | ||
13778 | return -EINVAL; | ||
13779 | } | ||
13780 | |||
13754 | return 0; | 13781 | return 0; |
13755 | } | 13782 | } |
13756 | 13783 | ||
@@ -13774,9 +13801,6 @@ intel_commit_cursor_plane(struct drm_plane *plane, | |||
13774 | crtc = crtc ? crtc : plane->crtc; | 13801 | crtc = crtc ? crtc : plane->crtc; |
13775 | intel_crtc = to_intel_crtc(crtc); | 13802 | intel_crtc = to_intel_crtc(crtc); |
13776 | 13803 | ||
13777 | if (intel_crtc->cursor_bo == obj) | ||
13778 | goto update; | ||
13779 | |||
13780 | if (!obj) | 13804 | if (!obj) |
13781 | addr = 0; | 13805 | addr = 0; |
13782 | else if (!INTEL_INFO(dev)->cursor_needs_physical) | 13806 | else if (!INTEL_INFO(dev)->cursor_needs_physical) |
@@ -13785,9 +13809,7 @@ intel_commit_cursor_plane(struct drm_plane *plane, | |||
13785 | addr = obj->phys_handle->busaddr; | 13809 | addr = obj->phys_handle->busaddr; |
13786 | 13810 | ||
13787 | intel_crtc->cursor_addr = addr; | 13811 | intel_crtc->cursor_addr = addr; |
13788 | intel_crtc->cursor_bo = obj; | ||
13789 | 13812 | ||
13790 | update: | ||
13791 | if (crtc->state->active) | 13813 | if (crtc->state->active) |
13792 | intel_crtc_update_cursor(crtc, state->visible); | 13814 | intel_crtc_update_cursor(crtc, state->visible); |
13793 | } | 13815 | } |
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index f2a1142bff34..0d00f07b7163 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h | |||
@@ -550,7 +550,6 @@ struct intel_crtc { | |||
550 | int adjusted_x; | 550 | int adjusted_x; |
551 | int adjusted_y; | 551 | int adjusted_y; |
552 | 552 | ||
553 | struct drm_i915_gem_object *cursor_bo; | ||
554 | uint32_t cursor_addr; | 553 | uint32_t cursor_addr; |
555 | uint32_t cursor_cntl; | 554 | uint32_t cursor_cntl; |
556 | uint32_t cursor_size; | 555 | uint32_t cursor_size; |
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 81cdd9ff3892..64086f2d4e26 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c | |||
@@ -1374,17 +1374,18 @@ intel_hdmi_detect(struct drm_connector *connector, bool force) | |||
1374 | struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector); | 1374 | struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector); |
1375 | struct drm_i915_private *dev_priv = to_i915(connector->dev); | 1375 | struct drm_i915_private *dev_priv = to_i915(connector->dev); |
1376 | bool live_status = false; | 1376 | bool live_status = false; |
1377 | unsigned int retry = 3; | 1377 | unsigned int try; |
1378 | 1378 | ||
1379 | DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", | 1379 | DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", |
1380 | connector->base.id, connector->name); | 1380 | connector->base.id, connector->name); |
1381 | 1381 | ||
1382 | intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS); | 1382 | intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS); |
1383 | 1383 | ||
1384 | while (!live_status && --retry) { | 1384 | for (try = 0; !live_status && try < 4; try++) { |
1385 | if (try) | ||
1386 | msleep(10); | ||
1385 | live_status = intel_digital_port_connected(dev_priv, | 1387 | live_status = intel_digital_port_connected(dev_priv, |
1386 | hdmi_to_dig_port(intel_hdmi)); | 1388 | hdmi_to_dig_port(intel_hdmi)); |
1387 | mdelay(10); | ||
1388 | } | 1389 | } |
1389 | 1390 | ||
1390 | if (!live_status) | 1391 | if (!live_status) |