aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/i915_drv.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/i915/i915_drv.c')
-rw-r--r--drivers/gpu/drm/i915/i915_drv.c176
1 files changed, 108 insertions, 68 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index be631cc3e4dc..79beffcf5936 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -45,6 +45,9 @@ module_param_named(fbpercrtc, i915_fbpercrtc, int, 0400);
45unsigned int i915_powersave = 1; 45unsigned int i915_powersave = 1;
46module_param_named(powersave, i915_powersave, int, 0400); 46module_param_named(powersave, i915_powersave, int, 0400);
47 47
48unsigned int i915_lvds_downclock = 0;
49module_param_named(lvds_downclock, i915_lvds_downclock, int, 0400);
50
48static struct drm_driver driver; 51static struct drm_driver driver;
49 52
50#define INTEL_VGA_DEVICE(id, info) { \ 53#define INTEL_VGA_DEVICE(id, info) { \
@@ -117,7 +120,7 @@ const static struct intel_device_info intel_gm45_info = {
117 120
118const static struct intel_device_info intel_pineview_info = { 121const static struct intel_device_info intel_pineview_info = {
119 .is_g33 = 1, .is_pineview = 1, .is_mobile = 1, .is_i9xx = 1, 122 .is_g33 = 1, .is_pineview = 1, .is_mobile = 1, .is_i9xx = 1,
120 .has_pipe_cxsr = 1, 123 .need_gfx_hws = 1,
121 .has_hotplug = 1, 124 .has_hotplug = 1,
122}; 125};
123 126
@@ -171,78 +174,100 @@ const static struct pci_device_id pciidlist[] = {
171MODULE_DEVICE_TABLE(pci, pciidlist); 174MODULE_DEVICE_TABLE(pci, pciidlist);
172#endif 175#endif
173 176
174static int i915_suspend(struct drm_device *dev, pm_message_t state) 177static int i915_drm_freeze(struct drm_device *dev)
175{ 178{
176 struct drm_i915_private *dev_priv = dev->dev_private;
177
178 if (!dev || !dev_priv) {
179 DRM_ERROR("dev: %p, dev_priv: %p\n", dev, dev_priv);
180 DRM_ERROR("DRM not initialized, aborting suspend.\n");
181 return -ENODEV;
182 }
183
184 if (state.event == PM_EVENT_PRETHAW)
185 return 0;
186
187 pci_save_state(dev->pdev); 179 pci_save_state(dev->pdev);
188 180
189 /* If KMS is active, we do the leavevt stuff here */ 181 /* If KMS is active, we do the leavevt stuff here */
190 if (drm_core_check_feature(dev, DRIVER_MODESET)) { 182 if (drm_core_check_feature(dev, DRIVER_MODESET)) {
191 if (i915_gem_idle(dev)) 183 int error = i915_gem_idle(dev);
184 if (error) {
192 dev_err(&dev->pdev->dev, 185 dev_err(&dev->pdev->dev,
193 "GEM idle failed, resume may fail\n"); 186 "GEM idle failed, resume might fail\n");
187 return error;
188 }
194 drm_irq_uninstall(dev); 189 drm_irq_uninstall(dev);
195 } 190 }
196 191
197 i915_save_state(dev); 192 i915_save_state(dev);
198 193
194 return 0;
195}
196
197static void i915_drm_suspend(struct drm_device *dev)
198{
199 struct drm_i915_private *dev_priv = dev->dev_private;
200
199 intel_opregion_free(dev, 1); 201 intel_opregion_free(dev, 1);
200 202
203 /* Modeset on resume, not lid events */
204 dev_priv->modeset_on_lid = 0;
205}
206
207static int i915_suspend(struct drm_device *dev, pm_message_t state)
208{
209 int error;
210
211 if (!dev || !dev->dev_private) {
212 DRM_ERROR("dev: %p\n", dev);
213 DRM_ERROR("DRM not initialized, aborting suspend.\n");
214 return -ENODEV;
215 }
216
217 if (state.event == PM_EVENT_PRETHAW)
218 return 0;
219
220 error = i915_drm_freeze(dev);
221 if (error)
222 return error;
223
224 i915_drm_suspend(dev);
225
201 if (state.event == PM_EVENT_SUSPEND) { 226 if (state.event == PM_EVENT_SUSPEND) {
202 /* Shut down the device */ 227 /* Shut down the device */
203 pci_disable_device(dev->pdev); 228 pci_disable_device(dev->pdev);
204 pci_set_power_state(dev->pdev, PCI_D3hot); 229 pci_set_power_state(dev->pdev, PCI_D3hot);
205 } 230 }
206 231
207 /* Modeset on resume, not lid events */
208 dev_priv->modeset_on_lid = 0;
209
210 return 0; 232 return 0;
211} 233}
212 234
213static int i915_resume(struct drm_device *dev) 235static int i915_drm_thaw(struct drm_device *dev)
214{ 236{
215 struct drm_i915_private *dev_priv = dev->dev_private; 237 struct drm_i915_private *dev_priv = dev->dev_private;
216 int ret = 0; 238 int error = 0;
217
218 if (pci_enable_device(dev->pdev))
219 return -1;
220 pci_set_master(dev->pdev);
221
222 i915_restore_state(dev);
223
224 intel_opregion_init(dev, 1);
225 239
226 /* KMS EnterVT equivalent */ 240 /* KMS EnterVT equivalent */
227 if (drm_core_check_feature(dev, DRIVER_MODESET)) { 241 if (drm_core_check_feature(dev, DRIVER_MODESET)) {
228 mutex_lock(&dev->struct_mutex); 242 mutex_lock(&dev->struct_mutex);
229 dev_priv->mm.suspended = 0; 243 dev_priv->mm.suspended = 0;
230 244
231 ret = i915_gem_init_ringbuffer(dev); 245 error = i915_gem_init_ringbuffer(dev);
232 if (ret != 0)
233 ret = -1;
234 mutex_unlock(&dev->struct_mutex); 246 mutex_unlock(&dev->struct_mutex);
235 247
236 drm_irq_install(dev); 248 drm_irq_install(dev);
237 } 249
238 if (drm_core_check_feature(dev, DRIVER_MODESET)) {
239 /* Resume the modeset for every activated CRTC */ 250 /* Resume the modeset for every activated CRTC */
240 drm_helper_resume_force_mode(dev); 251 drm_helper_resume_force_mode(dev);
241 } 252 }
242 253
243 dev_priv->modeset_on_lid = 0; 254 dev_priv->modeset_on_lid = 0;
244 255
245 return ret; 256 return error;
257}
258
259static int i915_resume(struct drm_device *dev)
260{
261 if (pci_enable_device(dev->pdev))
262 return -EIO;
263
264 pci_set_master(dev->pdev);
265
266 i915_restore_state(dev);
267
268 intel_opregion_init(dev, 1);
269
270 return i915_drm_thaw(dev);
246} 271}
247 272
248/** 273/**
@@ -383,57 +408,69 @@ i915_pci_remove(struct pci_dev *pdev)
383 drm_put_dev(dev); 408 drm_put_dev(dev);
384} 409}
385 410
386static int 411static int i915_pm_suspend(struct device *dev)
387i915_pci_suspend(struct pci_dev *pdev, pm_message_t state)
388{ 412{
389 struct drm_device *dev = pci_get_drvdata(pdev); 413 struct pci_dev *pdev = to_pci_dev(dev);
414 struct drm_device *drm_dev = pci_get_drvdata(pdev);
415 int error;
390 416
391 return i915_suspend(dev, state); 417 if (!drm_dev || !drm_dev->dev_private) {
392} 418 dev_err(dev, "DRM not initialized, aborting suspend.\n");
419 return -ENODEV;
420 }
393 421
394static int 422 error = i915_drm_freeze(drm_dev);
395i915_pci_resume(struct pci_dev *pdev) 423 if (error)
396{ 424 return error;
397 struct drm_device *dev = pci_get_drvdata(pdev);
398 425
399 return i915_resume(dev); 426 i915_drm_suspend(drm_dev);
400}
401 427
402static int 428 pci_disable_device(pdev);
403i915_pm_suspend(struct device *dev) 429 pci_set_power_state(pdev, PCI_D3hot);
404{
405 return i915_pci_suspend(to_pci_dev(dev), PMSG_SUSPEND);
406}
407 430
408static int 431 return 0;
409i915_pm_resume(struct device *dev)
410{
411 return i915_pci_resume(to_pci_dev(dev));
412} 432}
413 433
414static int 434static int i915_pm_resume(struct device *dev)
415i915_pm_freeze(struct device *dev)
416{ 435{
417 return i915_pci_suspend(to_pci_dev(dev), PMSG_FREEZE); 436 struct pci_dev *pdev = to_pci_dev(dev);
437 struct drm_device *drm_dev = pci_get_drvdata(pdev);
438
439 return i915_resume(drm_dev);
418} 440}
419 441
420static int 442static int i915_pm_freeze(struct device *dev)
421i915_pm_thaw(struct device *dev)
422{ 443{
423 /* thaw during hibernate, do nothing! */ 444 struct pci_dev *pdev = to_pci_dev(dev);
424 return 0; 445 struct drm_device *drm_dev = pci_get_drvdata(pdev);
446
447 if (!drm_dev || !drm_dev->dev_private) {
448 dev_err(dev, "DRM not initialized, aborting suspend.\n");
449 return -ENODEV;
450 }
451
452 return i915_drm_freeze(drm_dev);
425} 453}
426 454
427static int 455static int i915_pm_thaw(struct device *dev)
428i915_pm_poweroff(struct device *dev)
429{ 456{
430 return i915_pci_suspend(to_pci_dev(dev), PMSG_HIBERNATE); 457 struct pci_dev *pdev = to_pci_dev(dev);
458 struct drm_device *drm_dev = pci_get_drvdata(pdev);
459
460 return i915_drm_thaw(drm_dev);
431} 461}
432 462
433static int 463static int i915_pm_poweroff(struct device *dev)
434i915_pm_restore(struct device *dev)
435{ 464{
436 return i915_pci_resume(to_pci_dev(dev)); 465 struct pci_dev *pdev = to_pci_dev(dev);
466 struct drm_device *drm_dev = pci_get_drvdata(pdev);
467 int error;
468
469 error = i915_drm_freeze(drm_dev);
470 if (!error)
471 i915_drm_suspend(drm_dev);
472
473 return error;
437} 474}
438 475
439const struct dev_pm_ops i915_pm_ops = { 476const struct dev_pm_ops i915_pm_ops = {
@@ -442,7 +479,7 @@ const struct dev_pm_ops i915_pm_ops = {
442 .freeze = i915_pm_freeze, 479 .freeze = i915_pm_freeze,
443 .thaw = i915_pm_thaw, 480 .thaw = i915_pm_thaw,
444 .poweroff = i915_pm_poweroff, 481 .poweroff = i915_pm_poweroff,
445 .restore = i915_pm_restore, 482 .restore = i915_pm_resume,
446}; 483};
447 484
448static struct vm_operations_struct i915_gem_vm_ops = { 485static struct vm_operations_struct i915_gem_vm_ops = {
@@ -464,8 +501,11 @@ static struct drm_driver driver = {
464 .lastclose = i915_driver_lastclose, 501 .lastclose = i915_driver_lastclose,
465 .preclose = i915_driver_preclose, 502 .preclose = i915_driver_preclose,
466 .postclose = i915_driver_postclose, 503 .postclose = i915_driver_postclose,
504
505 /* Used in place of i915_pm_ops for non-DRIVER_MODESET */
467 .suspend = i915_suspend, 506 .suspend = i915_suspend,
468 .resume = i915_resume, 507 .resume = i915_resume,
508
469 .device_is_agp = i915_driver_device_is_agp, 509 .device_is_agp = i915_driver_device_is_agp,
470 .enable_vblank = i915_enable_vblank, 510 .enable_vblank = i915_enable_vblank,
471 .disable_vblank = i915_disable_vblank, 511 .disable_vblank = i915_disable_vblank,