aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/qxl/qxl_drv.c134
-rw-r--r--drivers/gpu/drm/qxl/qxl_drv.h1
-rw-r--r--drivers/gpu/drm/qxl/qxl_object.c5
3 files changed, 132 insertions, 8 deletions
diff --git a/drivers/gpu/drm/qxl/qxl_drv.c b/drivers/gpu/drm/qxl/qxl_drv.c
index 00e57b76f4f5..df0b577a6608 100644
--- a/drivers/gpu/drm/qxl/qxl_drv.c
+++ b/drivers/gpu/drm/qxl/qxl_drv.c
@@ -33,8 +33,9 @@
33 33
34#include "drmP.h" 34#include "drmP.h"
35#include "drm/drm.h" 35#include "drm/drm.h"
36 36#include "drm_crtc_helper.h"
37#include "qxl_drv.h" 37#include "qxl_drv.h"
38#include "qxl_object.h"
38 39
39extern int qxl_max_ioctls; 40extern int qxl_max_ioctls;
40static DEFINE_PCI_DEVICE_TABLE(pciidlist) = { 41static DEFINE_PCI_DEVICE_TABLE(pciidlist) = {
@@ -77,13 +78,6 @@ qxl_pci_remove(struct pci_dev *pdev)
77 drm_put_dev(dev); 78 drm_put_dev(dev);
78} 79}
79 80
80static struct pci_driver qxl_pci_driver = {
81 .name = DRIVER_NAME,
82 .id_table = pciidlist,
83 .probe = qxl_pci_probe,
84 .remove = qxl_pci_remove,
85};
86
87static const struct file_operations qxl_fops = { 81static const struct file_operations qxl_fops = {
88 .owner = THIS_MODULE, 82 .owner = THIS_MODULE,
89 .open = drm_open, 83 .open = drm_open,
@@ -94,6 +88,130 @@ static const struct file_operations qxl_fops = {
94 .mmap = qxl_mmap, 88 .mmap = qxl_mmap,
95}; 89};
96 90
91static int qxl_drm_freeze(struct drm_device *dev)
92{
93 struct pci_dev *pdev = dev->pdev;
94 struct qxl_device *qdev = dev->dev_private;
95 struct drm_crtc *crtc;
96
97 drm_kms_helper_poll_disable(dev);
98
99 console_lock();
100 qxl_fbdev_set_suspend(qdev, 1);
101 console_unlock();
102
103 /* unpin the front buffers */
104 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
105 struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
106 if (crtc->enabled)
107 (*crtc_funcs->disable)(crtc);
108 }
109
110 qxl_destroy_monitors_object(qdev);
111 qxl_surf_evict(qdev);
112 qxl_vram_evict(qdev);
113
114 while (!qxl_check_idle(qdev->command_ring));
115 while (!qxl_check_idle(qdev->release_ring))
116 qxl_queue_garbage_collect(qdev, 1);
117
118 pci_save_state(pdev);
119
120 return 0;
121}
122
123static int qxl_drm_resume(struct drm_device *dev, bool thaw)
124{
125 struct qxl_device *qdev = dev->dev_private;
126
127 qdev->ram_header->int_mask = QXL_INTERRUPT_MASK;
128 if (!thaw) {
129 qxl_reinit_memslots(qdev);
130 qxl_ring_init_hdr(qdev->release_ring);
131 }
132
133 qxl_create_monitors_object(qdev);
134 drm_helper_resume_force_mode(dev);
135
136 console_lock();
137 qxl_fbdev_set_suspend(qdev, 0);
138 console_unlock();
139
140 drm_kms_helper_poll_enable(dev);
141 return 0;
142}
143
144static int qxl_pm_suspend(struct device *dev)
145{
146 struct pci_dev *pdev = to_pci_dev(dev);
147 struct drm_device *drm_dev = pci_get_drvdata(pdev);
148 int error;
149
150 error = qxl_drm_freeze(drm_dev);
151 if (error)
152 return error;
153
154 pci_disable_device(pdev);
155 pci_set_power_state(pdev, PCI_D3hot);
156 return 0;
157}
158
159static int qxl_pm_resume(struct device *dev)
160{
161 struct pci_dev *pdev = to_pci_dev(dev);
162 struct drm_device *drm_dev = pci_get_drvdata(pdev);
163
164 pci_set_power_state(pdev, PCI_D0);
165 pci_restore_state(pdev);
166 if (pci_enable_device(pdev)) {
167 return -EIO;
168 }
169
170 return qxl_drm_resume(drm_dev, false);
171}
172
173static int qxl_pm_thaw(struct device *dev)
174{
175 struct pci_dev *pdev = to_pci_dev(dev);
176 struct drm_device *drm_dev = pci_get_drvdata(pdev);
177
178 return qxl_drm_resume(drm_dev, true);
179}
180
181static int qxl_pm_freeze(struct device *dev)
182{
183 struct pci_dev *pdev = to_pci_dev(dev);
184 struct drm_device *drm_dev = pci_get_drvdata(pdev);
185
186 return qxl_drm_freeze(drm_dev);
187}
188
189static int qxl_pm_restore(struct device *dev)
190{
191 struct pci_dev *pdev = to_pci_dev(dev);
192 struct drm_device *drm_dev = pci_get_drvdata(pdev);
193 struct qxl_device *qdev = drm_dev->dev_private;
194
195 qxl_io_reset(qdev);
196 return qxl_drm_resume(drm_dev, false);
197}
198
199static const struct dev_pm_ops qxl_pm_ops = {
200 .suspend = qxl_pm_suspend,
201 .resume = qxl_pm_resume,
202 .freeze = qxl_pm_freeze,
203 .thaw = qxl_pm_thaw,
204 .poweroff = qxl_pm_freeze,
205 .restore = qxl_pm_restore,
206};
207static struct pci_driver qxl_pci_driver = {
208 .name = DRIVER_NAME,
209 .id_table = pciidlist,
210 .probe = qxl_pci_probe,
211 .remove = qxl_pci_remove,
212 .driver.pm = &qxl_pm_ops,
213};
214
97static struct drm_driver qxl_driver = { 215static struct drm_driver qxl_driver = {
98 .driver_features = DRIVER_GEM | DRIVER_MODESET | 216 .driver_features = DRIVER_GEM | DRIVER_MODESET |
99 DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED, 217 DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED,
diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h
index 70a67862673a..aacb791464a3 100644
--- a/drivers/gpu/drm/qxl/qxl_drv.h
+++ b/drivers/gpu/drm/qxl/qxl_drv.h
@@ -333,6 +333,7 @@ void qxl_bo_fini(struct qxl_device *qdev);
333 333
334void qxl_reinit_memslots(struct qxl_device *qdev); 334void qxl_reinit_memslots(struct qxl_device *qdev);
335int qxl_surf_evict(struct qxl_device *qdev); 335int qxl_surf_evict(struct qxl_device *qdev);
336int qxl_vram_evict(struct qxl_device *qdev);
336 337
337struct qxl_ring *qxl_ring_create(struct qxl_ring_header *header, 338struct qxl_ring *qxl_ring_create(struct qxl_ring_header *header,
338 int element_size, 339 int element_size,
diff --git a/drivers/gpu/drm/qxl/qxl_object.c b/drivers/gpu/drm/qxl/qxl_object.c
index 62a046e4a036..1191fe7788c9 100644
--- a/drivers/gpu/drm/qxl/qxl_object.c
+++ b/drivers/gpu/drm/qxl/qxl_object.c
@@ -368,3 +368,8 @@ int qxl_surf_evict(struct qxl_device *qdev)
368{ 368{
369 return ttm_bo_evict_mm(&qdev->mman.bdev, TTM_PL_PRIV0); 369 return ttm_bo_evict_mm(&qdev->mman.bdev, TTM_PL_PRIV0);
370} 370}
371
372int qxl_vram_evict(struct qxl_device *qdev)
373{
374 return ttm_bo_evict_mm(&qdev->mman.bdev, TTM_PL_VRAM);
375}