diff options
Diffstat (limited to 'drivers/gpu/drm/i915/i915_drv.c')
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.c | 214 |
1 files changed, 149 insertions, 65 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 895ab896e336..3467dd420760 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include "drm.h" | 32 | #include "drm.h" |
33 | #include "i915_drm.h" | 33 | #include "i915_drm.h" |
34 | #include "i915_drv.h" | 34 | #include "i915_drv.h" |
35 | #include "intel_drv.h" | ||
35 | 36 | ||
36 | #include <linux/console.h> | 37 | #include <linux/console.h> |
37 | #include "drm_crtc_helper.h" | 38 | #include "drm_crtc_helper.h" |
@@ -61,86 +62,110 @@ extern int intel_agp_enabled; | |||
61 | .driver_data = (unsigned long) info } | 62 | .driver_data = (unsigned long) info } |
62 | 63 | ||
63 | static const struct intel_device_info intel_i830_info = { | 64 | static const struct intel_device_info intel_i830_info = { |
64 | .gen = 2, .is_i8xx = 1, .is_mobile = 1, .cursor_needs_physical = 1, | 65 | .gen = 2, .is_mobile = 1, .cursor_needs_physical = 1, |
66 | .has_overlay = 1, .overlay_needs_physical = 1, | ||
65 | }; | 67 | }; |
66 | 68 | ||
67 | static const struct intel_device_info intel_845g_info = { | 69 | static const struct intel_device_info intel_845g_info = { |
68 | .gen = 2, .is_i8xx = 1, | 70 | .gen = 2, |
71 | .has_overlay = 1, .overlay_needs_physical = 1, | ||
69 | }; | 72 | }; |
70 | 73 | ||
71 | static const struct intel_device_info intel_i85x_info = { | 74 | static const struct intel_device_info intel_i85x_info = { |
72 | .gen = 2, .is_i8xx = 1, .is_i85x = 1, .is_mobile = 1, | 75 | .gen = 2, .is_i85x = 1, .is_mobile = 1, |
73 | .cursor_needs_physical = 1, | 76 | .cursor_needs_physical = 1, |
77 | .has_overlay = 1, .overlay_needs_physical = 1, | ||
74 | }; | 78 | }; |
75 | 79 | ||
76 | static const struct intel_device_info intel_i865g_info = { | 80 | static const struct intel_device_info intel_i865g_info = { |
77 | .gen = 2, .is_i8xx = 1, | 81 | .gen = 2, |
82 | .has_overlay = 1, .overlay_needs_physical = 1, | ||
78 | }; | 83 | }; |
79 | 84 | ||
80 | static const struct intel_device_info intel_i915g_info = { | 85 | static const struct intel_device_info intel_i915g_info = { |
81 | .gen = 3, .is_i915g = 1, .is_i9xx = 1, .cursor_needs_physical = 1, | 86 | .gen = 3, .is_i915g = 1, .cursor_needs_physical = 1, |
87 | .has_overlay = 1, .overlay_needs_physical = 1, | ||
82 | }; | 88 | }; |
83 | static const struct intel_device_info intel_i915gm_info = { | 89 | static const struct intel_device_info intel_i915gm_info = { |
84 | .gen = 3, .is_i9xx = 1, .is_mobile = 1, | 90 | .gen = 3, .is_mobile = 1, |
85 | .cursor_needs_physical = 1, | 91 | .cursor_needs_physical = 1, |
92 | .has_overlay = 1, .overlay_needs_physical = 1, | ||
93 | .supports_tv = 1, | ||
86 | }; | 94 | }; |
87 | static const struct intel_device_info intel_i945g_info = { | 95 | static const struct intel_device_info intel_i945g_info = { |
88 | .gen = 3, .is_i9xx = 1, .has_hotplug = 1, .cursor_needs_physical = 1, | 96 | .gen = 3, .has_hotplug = 1, .cursor_needs_physical = 1, |
97 | .has_overlay = 1, .overlay_needs_physical = 1, | ||
89 | }; | 98 | }; |
90 | static const struct intel_device_info intel_i945gm_info = { | 99 | static const struct intel_device_info intel_i945gm_info = { |
91 | .gen = 3, .is_i945gm = 1, .is_i9xx = 1, .is_mobile = 1, | 100 | .gen = 3, .is_i945gm = 1, .is_mobile = 1, |
92 | .has_hotplug = 1, .cursor_needs_physical = 1, | 101 | .has_hotplug = 1, .cursor_needs_physical = 1, |
102 | .has_overlay = 1, .overlay_needs_physical = 1, | ||
103 | .supports_tv = 1, | ||
93 | }; | 104 | }; |
94 | 105 | ||
95 | static const struct intel_device_info intel_i965g_info = { | 106 | static const struct intel_device_info intel_i965g_info = { |
96 | .gen = 4, .is_broadwater = 1, .is_i965g = 1, .is_i9xx = 1, | 107 | .gen = 4, .is_broadwater = 1, |
97 | .has_hotplug = 1, | 108 | .has_hotplug = 1, |
109 | .has_overlay = 1, | ||
98 | }; | 110 | }; |
99 | 111 | ||
100 | static const struct intel_device_info intel_i965gm_info = { | 112 | static const struct intel_device_info intel_i965gm_info = { |
101 | .gen = 4, .is_crestline = 1, .is_i965g = 1, .is_i965gm = 1, .is_i9xx = 1, | 113 | .gen = 4, .is_crestline = 1, |
102 | .is_mobile = 1, .has_fbc = 1, .has_rc6 = 1, .has_hotplug = 1, | 114 | .is_mobile = 1, .has_fbc = 1, .has_rc6 = 1, .has_hotplug = 1, |
115 | .has_overlay = 1, | ||
116 | .supports_tv = 1, | ||
103 | }; | 117 | }; |
104 | 118 | ||
105 | static const struct intel_device_info intel_g33_info = { | 119 | static const struct intel_device_info intel_g33_info = { |
106 | .gen = 3, .is_g33 = 1, .is_i9xx = 1, | 120 | .gen = 3, .is_g33 = 1, |
107 | .need_gfx_hws = 1, .has_hotplug = 1, | 121 | .need_gfx_hws = 1, .has_hotplug = 1, |
122 | .has_overlay = 1, | ||
108 | }; | 123 | }; |
109 | 124 | ||
110 | static const struct intel_device_info intel_g45_info = { | 125 | static const struct intel_device_info intel_g45_info = { |
111 | .gen = 4, .is_i965g = 1, .is_g4x = 1, .is_i9xx = 1, .need_gfx_hws = 1, | 126 | .gen = 4, .is_g4x = 1, .need_gfx_hws = 1, |
112 | .has_pipe_cxsr = 1, .has_hotplug = 1, | 127 | .has_pipe_cxsr = 1, .has_hotplug = 1, |
128 | .has_bsd_ring = 1, | ||
113 | }; | 129 | }; |
114 | 130 | ||
115 | static const struct intel_device_info intel_gm45_info = { | 131 | static const struct intel_device_info intel_gm45_info = { |
116 | .gen = 4, .is_i965g = 1, .is_g4x = 1, .is_i9xx = 1, | 132 | .gen = 4, .is_g4x = 1, |
117 | .is_mobile = 1, .need_gfx_hws = 1, .has_fbc = 1, .has_rc6 = 1, | 133 | .is_mobile = 1, .need_gfx_hws = 1, .has_fbc = 1, .has_rc6 = 1, |
118 | .has_pipe_cxsr = 1, .has_hotplug = 1, | 134 | .has_pipe_cxsr = 1, .has_hotplug = 1, |
135 | .supports_tv = 1, | ||
136 | .has_bsd_ring = 1, | ||
119 | }; | 137 | }; |
120 | 138 | ||
121 | static const struct intel_device_info intel_pineview_info = { | 139 | static const struct intel_device_info intel_pineview_info = { |
122 | .gen = 3, .is_g33 = 1, .is_pineview = 1, .is_mobile = 1, .is_i9xx = 1, | 140 | .gen = 3, .is_g33 = 1, .is_pineview = 1, .is_mobile = 1, |
123 | .need_gfx_hws = 1, .has_hotplug = 1, | 141 | .need_gfx_hws = 1, .has_hotplug = 1, |
142 | .has_overlay = 1, | ||
124 | }; | 143 | }; |
125 | 144 | ||
126 | static const struct intel_device_info intel_ironlake_d_info = { | 145 | static const struct intel_device_info intel_ironlake_d_info = { |
127 | .gen = 5, .is_ironlake = 1, .is_i965g = 1, .is_i9xx = 1, | 146 | .gen = 5, |
128 | .need_gfx_hws = 1, .has_pipe_cxsr = 1, .has_hotplug = 1, | 147 | .need_gfx_hws = 1, .has_pipe_cxsr = 1, .has_hotplug = 1, |
148 | .has_bsd_ring = 1, | ||
129 | }; | 149 | }; |
130 | 150 | ||
131 | static const struct intel_device_info intel_ironlake_m_info = { | 151 | static const struct intel_device_info intel_ironlake_m_info = { |
132 | .gen = 5, .is_ironlake = 1, .is_mobile = 1, .is_i965g = 1, .is_i9xx = 1, | 152 | .gen = 5, .is_mobile = 1, |
133 | .need_gfx_hws = 1, .has_fbc = 1, .has_rc6 = 1, .has_hotplug = 1, | 153 | .need_gfx_hws = 1, .has_fbc = 1, .has_rc6 = 1, .has_hotplug = 1, |
154 | .has_bsd_ring = 1, | ||
134 | }; | 155 | }; |
135 | 156 | ||
136 | static const struct intel_device_info intel_sandybridge_d_info = { | 157 | static const struct intel_device_info intel_sandybridge_d_info = { |
137 | .gen = 6, .is_i965g = 1, .is_i9xx = 1, | 158 | .gen = 6, |
138 | .need_gfx_hws = 1, .has_hotplug = 1, | 159 | .need_gfx_hws = 1, .has_hotplug = 1, |
160 | .has_bsd_ring = 1, | ||
161 | .has_blt_ring = 1, | ||
139 | }; | 162 | }; |
140 | 163 | ||
141 | static const struct intel_device_info intel_sandybridge_m_info = { | 164 | static const struct intel_device_info intel_sandybridge_m_info = { |
142 | .gen = 6, .is_i965g = 1, .is_mobile = 1, .is_i9xx = 1, | 165 | .gen = 6, .is_mobile = 1, |
143 | .need_gfx_hws = 1, .has_hotplug = 1, | 166 | .need_gfx_hws = 1, .has_hotplug = 1, |
167 | .has_bsd_ring = 1, | ||
168 | .has_blt_ring = 1, | ||
144 | }; | 169 | }; |
145 | 170 | ||
146 | static const struct pci_device_id pciidlist[] = { /* aka */ | 171 | static const struct pci_device_id pciidlist[] = { /* aka */ |
@@ -237,7 +262,7 @@ static int i915_drm_freeze(struct drm_device *dev) | |||
237 | 262 | ||
238 | i915_save_state(dev); | 263 | i915_save_state(dev); |
239 | 264 | ||
240 | intel_opregion_free(dev, 1); | 265 | intel_opregion_fini(dev); |
241 | 266 | ||
242 | /* Modeset on resume, not lid events */ | 267 | /* Modeset on resume, not lid events */ |
243 | dev_priv->modeset_on_lid = 0; | 268 | dev_priv->modeset_on_lid = 0; |
@@ -258,6 +283,8 @@ int i915_suspend(struct drm_device *dev, pm_message_t state) | |||
258 | if (state.event == PM_EVENT_PRETHAW) | 283 | if (state.event == PM_EVENT_PRETHAW) |
259 | return 0; | 284 | return 0; |
260 | 285 | ||
286 | drm_kms_helper_poll_disable(dev); | ||
287 | |||
261 | error = i915_drm_freeze(dev); | 288 | error = i915_drm_freeze(dev); |
262 | if (error) | 289 | if (error) |
263 | return error; | 290 | return error; |
@@ -277,8 +304,7 @@ static int i915_drm_thaw(struct drm_device *dev) | |||
277 | int error = 0; | 304 | int error = 0; |
278 | 305 | ||
279 | i915_restore_state(dev); | 306 | i915_restore_state(dev); |
280 | 307 | intel_opregion_setup(dev); | |
281 | intel_opregion_init(dev, 1); | ||
282 | 308 | ||
283 | /* KMS EnterVT equivalent */ | 309 | /* KMS EnterVT equivalent */ |
284 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { | 310 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { |
@@ -294,6 +320,8 @@ static int i915_drm_thaw(struct drm_device *dev) | |||
294 | drm_helper_resume_force_mode(dev); | 320 | drm_helper_resume_force_mode(dev); |
295 | } | 321 | } |
296 | 322 | ||
323 | intel_opregion_init(dev); | ||
324 | |||
297 | dev_priv->modeset_on_lid = 0; | 325 | dev_priv->modeset_on_lid = 0; |
298 | 326 | ||
299 | return error; | 327 | return error; |
@@ -301,12 +329,79 @@ static int i915_drm_thaw(struct drm_device *dev) | |||
301 | 329 | ||
302 | int i915_resume(struct drm_device *dev) | 330 | int i915_resume(struct drm_device *dev) |
303 | { | 331 | { |
332 | int ret; | ||
333 | |||
304 | if (pci_enable_device(dev->pdev)) | 334 | if (pci_enable_device(dev->pdev)) |
305 | return -EIO; | 335 | return -EIO; |
306 | 336 | ||
307 | pci_set_master(dev->pdev); | 337 | pci_set_master(dev->pdev); |
308 | 338 | ||
309 | return i915_drm_thaw(dev); | 339 | ret = i915_drm_thaw(dev); |
340 | if (ret) | ||
341 | return ret; | ||
342 | |||
343 | drm_kms_helper_poll_enable(dev); | ||
344 | return 0; | ||
345 | } | ||
346 | |||
347 | static int i8xx_do_reset(struct drm_device *dev, u8 flags) | ||
348 | { | ||
349 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
350 | |||
351 | if (IS_I85X(dev)) | ||
352 | return -ENODEV; | ||
353 | |||
354 | I915_WRITE(D_STATE, I915_READ(D_STATE) | DSTATE_GFX_RESET_I830); | ||
355 | POSTING_READ(D_STATE); | ||
356 | |||
357 | if (IS_I830(dev) || IS_845G(dev)) { | ||
358 | I915_WRITE(DEBUG_RESET_I830, | ||
359 | DEBUG_RESET_DISPLAY | | ||
360 | DEBUG_RESET_RENDER | | ||
361 | DEBUG_RESET_FULL); | ||
362 | POSTING_READ(DEBUG_RESET_I830); | ||
363 | msleep(1); | ||
364 | |||
365 | I915_WRITE(DEBUG_RESET_I830, 0); | ||
366 | POSTING_READ(DEBUG_RESET_I830); | ||
367 | } | ||
368 | |||
369 | msleep(1); | ||
370 | |||
371 | I915_WRITE(D_STATE, I915_READ(D_STATE) & ~DSTATE_GFX_RESET_I830); | ||
372 | POSTING_READ(D_STATE); | ||
373 | |||
374 | return 0; | ||
375 | } | ||
376 | |||
377 | static int i965_reset_complete(struct drm_device *dev) | ||
378 | { | ||
379 | u8 gdrst; | ||
380 | pci_read_config_byte(dev->pdev, I965_GDRST, &gdrst); | ||
381 | return gdrst & 0x1; | ||
382 | } | ||
383 | |||
384 | static int i965_do_reset(struct drm_device *dev, u8 flags) | ||
385 | { | ||
386 | u8 gdrst; | ||
387 | |||
388 | /* | ||
389 | * Set the domains we want to reset (GRDOM/bits 2 and 3) as | ||
390 | * well as the reset bit (GR/bit 0). Setting the GR bit | ||
391 | * triggers the reset; when done, the hardware will clear it. | ||
392 | */ | ||
393 | pci_read_config_byte(dev->pdev, I965_GDRST, &gdrst); | ||
394 | pci_write_config_byte(dev->pdev, I965_GDRST, gdrst | flags | 0x1); | ||
395 | |||
396 | return wait_for(i965_reset_complete(dev), 500); | ||
397 | } | ||
398 | |||
399 | static int ironlake_do_reset(struct drm_device *dev, u8 flags) | ||
400 | { | ||
401 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
402 | u32 gdrst = I915_READ(MCHBAR_MIRROR_BASE + ILK_GDSR); | ||
403 | I915_WRITE(MCHBAR_MIRROR_BASE + ILK_GDSR, gdrst | flags | 0x1); | ||
404 | return wait_for(I915_READ(MCHBAR_MIRROR_BASE + ILK_GDSR) & 0x1, 500); | ||
310 | } | 405 | } |
311 | 406 | ||
312 | /** | 407 | /** |
@@ -325,54 +420,39 @@ int i915_resume(struct drm_device *dev) | |||
325 | * - re-init interrupt state | 420 | * - re-init interrupt state |
326 | * - re-init display | 421 | * - re-init display |
327 | */ | 422 | */ |
328 | int i965_reset(struct drm_device *dev, u8 flags) | 423 | int i915_reset(struct drm_device *dev, u8 flags) |
329 | { | 424 | { |
330 | drm_i915_private_t *dev_priv = dev->dev_private; | 425 | drm_i915_private_t *dev_priv = dev->dev_private; |
331 | unsigned long timeout; | ||
332 | u8 gdrst; | ||
333 | /* | 426 | /* |
334 | * We really should only reset the display subsystem if we actually | 427 | * We really should only reset the display subsystem if we actually |
335 | * need to | 428 | * need to |
336 | */ | 429 | */ |
337 | bool need_display = true; | 430 | bool need_display = true; |
431 | int ret; | ||
338 | 432 | ||
339 | mutex_lock(&dev->struct_mutex); | 433 | mutex_lock(&dev->struct_mutex); |
340 | 434 | ||
341 | /* | 435 | i915_gem_reset(dev); |
342 | * Clear request list | 436 | |
343 | */ | 437 | ret = -ENODEV; |
344 | i915_gem_retire_requests(dev); | 438 | if (get_seconds() - dev_priv->last_gpu_reset < 5) { |
345 | 439 | DRM_ERROR("GPU hanging too fast, declaring wedged!\n"); | |
346 | if (need_display) | 440 | } else switch (INTEL_INFO(dev)->gen) { |
347 | i915_save_display(dev); | 441 | case 5: |
348 | 442 | ret = ironlake_do_reset(dev, flags); | |
349 | if (IS_I965G(dev) || IS_G4X(dev)) { | 443 | break; |
350 | /* | 444 | case 4: |
351 | * Set the domains we want to reset, then the reset bit (bit 0). | 445 | ret = i965_do_reset(dev, flags); |
352 | * Clear the reset bit after a while and wait for hardware status | 446 | break; |
353 | * bit (bit 1) to be set | 447 | case 2: |
354 | */ | 448 | ret = i8xx_do_reset(dev, flags); |
355 | pci_read_config_byte(dev->pdev, GDRST, &gdrst); | 449 | break; |
356 | pci_write_config_byte(dev->pdev, GDRST, gdrst | flags | ((flags == GDRST_FULL) ? 0x1 : 0x0)); | 450 | } |
357 | udelay(50); | 451 | dev_priv->last_gpu_reset = get_seconds(); |
358 | pci_write_config_byte(dev->pdev, GDRST, gdrst & 0xfe); | 452 | if (ret) { |
359 | 453 | DRM_ERROR("Failed to reset chip.\n"); | |
360 | /* ...we don't want to loop forever though, 500ms should be plenty */ | ||
361 | timeout = jiffies + msecs_to_jiffies(500); | ||
362 | do { | ||
363 | udelay(100); | ||
364 | pci_read_config_byte(dev->pdev, GDRST, &gdrst); | ||
365 | } while ((gdrst & 0x1) && time_after(timeout, jiffies)); | ||
366 | |||
367 | if (gdrst & 0x1) { | ||
368 | WARN(true, "i915: Failed to reset chip\n"); | ||
369 | mutex_unlock(&dev->struct_mutex); | ||
370 | return -EIO; | ||
371 | } | ||
372 | } else { | ||
373 | DRM_ERROR("Error occurred. Don't know how to reset this chip.\n"); | ||
374 | mutex_unlock(&dev->struct_mutex); | 454 | mutex_unlock(&dev->struct_mutex); |
375 | return -ENODEV; | 455 | return ret; |
376 | } | 456 | } |
377 | 457 | ||
378 | /* Ok, now get things going again... */ | 458 | /* Ok, now get things going again... */ |
@@ -400,13 +480,19 @@ int i965_reset(struct drm_device *dev, u8 flags) | |||
400 | mutex_lock(&dev->struct_mutex); | 480 | mutex_lock(&dev->struct_mutex); |
401 | } | 481 | } |
402 | 482 | ||
483 | mutex_unlock(&dev->struct_mutex); | ||
484 | |||
403 | /* | 485 | /* |
404 | * Display needs restore too... | 486 | * Perform a full modeset as on later generations, e.g. Ironlake, we may |
487 | * need to retrain the display link and cannot just restore the register | ||
488 | * values. | ||
405 | */ | 489 | */ |
406 | if (need_display) | 490 | if (need_display) { |
407 | i915_restore_display(dev); | 491 | mutex_lock(&dev->mode_config.mutex); |
492 | drm_helper_resume_force_mode(dev); | ||
493 | mutex_unlock(&dev->mode_config.mutex); | ||
494 | } | ||
408 | 495 | ||
409 | mutex_unlock(&dev->struct_mutex); | ||
410 | return 0; | 496 | return 0; |
411 | } | 497 | } |
412 | 498 | ||
@@ -524,8 +610,6 @@ static struct drm_driver driver = { | |||
524 | .irq_uninstall = i915_driver_irq_uninstall, | 610 | .irq_uninstall = i915_driver_irq_uninstall, |
525 | .irq_handler = i915_driver_irq_handler, | 611 | .irq_handler = i915_driver_irq_handler, |
526 | .reclaim_buffers = drm_core_reclaim_buffers, | 612 | .reclaim_buffers = drm_core_reclaim_buffers, |
527 | .get_map_ofs = drm_core_get_map_ofs, | ||
528 | .get_reg_ofs = drm_core_get_reg_ofs, | ||
529 | .master_create = i915_master_create, | 613 | .master_create = i915_master_create, |
530 | .master_destroy = i915_master_destroy, | 614 | .master_destroy = i915_master_destroy, |
531 | #if defined(CONFIG_DEBUG_FS) | 615 | #if defined(CONFIG_DEBUG_FS) |