diff options
-rw-r--r-- | drivers/gpu/drm/qxl/qxl_drv.c | 134 | ||||
-rw-r--r-- | drivers/gpu/drm/qxl/qxl_drv.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/qxl/qxl_object.c | 5 |
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 | ||
39 | extern int qxl_max_ioctls; | 40 | extern int qxl_max_ioctls; |
40 | static DEFINE_PCI_DEVICE_TABLE(pciidlist) = { | 41 | static 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 | ||
80 | static 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 | |||
87 | static const struct file_operations qxl_fops = { | 81 | static 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 | ||
91 | static 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 | |||
123 | static 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 | |||
144 | static 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 | |||
159 | static 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 | |||
173 | static 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 | |||
181 | static 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 | |||
189 | static 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 | |||
199 | static 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 | }; | ||
207 | static 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 | |||
97 | static struct drm_driver qxl_driver = { | 215 | static 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 | ||
334 | void qxl_reinit_memslots(struct qxl_device *qdev); | 334 | void qxl_reinit_memslots(struct qxl_device *qdev); |
335 | int qxl_surf_evict(struct qxl_device *qdev); | 335 | int qxl_surf_evict(struct qxl_device *qdev); |
336 | int qxl_vram_evict(struct qxl_device *qdev); | ||
336 | 337 | ||
337 | struct qxl_ring *qxl_ring_create(struct qxl_ring_header *header, | 338 | struct 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 | |||
372 | int qxl_vram_evict(struct qxl_device *qdev) | ||
373 | { | ||
374 | return ttm_bo_evict_mm(&qdev->mman.bdev, TTM_PL_VRAM); | ||
375 | } | ||