aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/qxl/qxl_drv.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-07-09 19:04:31 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-07-09 19:04:31 -0400
commit2e17c5a97e231f3cb426f4b7895eab5be5c5442e (patch)
tree80871817427250200d6931a45ccb4833c4add74a /drivers/gpu/drm/qxl/qxl_drv.c
parent5f097cd249f00683442c3e265d6f27d80fc83563 (diff)
parent774d8e34e46506222bb5e2888e3ef42b2775715f (diff)
Merge branch 'drm-next' of git://people.freedesktop.org/~airlied/linux
Pull drm updates from Dave Airlie: "Okay this is the big one, I was stalled on the fbdev pull req as I stupidly let fbdev guys merge a patch I required to fix a warning with some patches I had, they ended up merging the patch from the wrong place, but the warning should be fixed. In future I'll just take the patch myself! Outside drm: There are some snd changes for the HDMI audio interactions on haswell, they've been acked for inclusion via my tree. This relies on the wound/wait tree from Ingo which is already merged. Major changes: AMD finally released the dynamic power management code for all their GPUs from r600->present day, this is great, off by default for now but also a huge amount of code, in fact it is most of this pull request. Since it landed there has been a lot of community testing and Alex has sent a lot of fixes for any bugs found so far. I suspect radeon might now be the biggest kernel driver ever :-P p.s. radeon.dpm=1 to enable dynamic powermanagement for anyone. New drivers: Renesas r-car display unit. Other highlights: - core: GEM CMA prime support, use new w/w mutexs for TTM reservations, cursor hotspot, doc updates - dvo chips: chrontel 7010B support - i915: Haswell (fbc, ips, vecs, watermarks, audio powerwell), Valleyview (enabled by default, rc6), lots of pll reworking, 30bpp support (this time for sure) - nouveau: async buffer object deletion, context/register init updates, kernel vp2 engine support, GF117 support, GK110 accel support (with external nvidia ucode), context cleanups. - exynos: memory leak fixes, Add S3C64XX SoC series support, device tree updates, common clock framework support, - qxl: cursor hotspot support, multi-monitor support, suspend/resume support - mgag200: hw cursor support, g200 mode limiting - shmobile: prime support - tegra: fixes mostly I've been banging on this quite a lot due to the size of it, and it seems to okay on everything I've tested it on." * 'drm-next' of git://people.freedesktop.org/~airlied/linux: (811 commits) drm/radeon/dpm: implement vblank_too_short callback for si drm/radeon/dpm: implement vblank_too_short callback for cayman drm/radeon/dpm: implement vblank_too_short callback for btc drm/radeon/dpm: implement vblank_too_short callback for evergreen drm/radeon/dpm: implement vblank_too_short callback for 7xx drm/radeon/dpm: add checks against vblank time drm/radeon/dpm: add helper to calculate vblank time drm/radeon: remove stray line in old pm code drm/radeon/dpm: fix display_gap programming on rv7xx drm/nvc0/gr: fix gpc firmware regression drm/nouveau: fix minor thinko causing bo moves to not be async on kepler drm/radeon/dpm: implement force performance level for TN drm/radeon/dpm: implement force performance level for ON/LN drm/radeon/dpm: implement force performance level for SI drm/radeon/dpm: implement force performance level for cayman drm/radeon/dpm: implement force performance levels for 7xx/eg/btc drm/radeon/dpm: add infrastructure to force performance levels drm/radeon: fix surface setup on r1xx drm/radeon: add support for 3d perf states on older asics drm/radeon: set default clocks for SI when DPM is disabled ...
Diffstat (limited to 'drivers/gpu/drm/qxl/qxl_drv.c')
-rw-r--r--drivers/gpu/drm/qxl/qxl_drv.c138
1 files changed, 130 insertions, 8 deletions
diff --git a/drivers/gpu/drm/qxl/qxl_drv.c b/drivers/gpu/drm/qxl/qxl_drv.c
index aa291d8a98a2..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) = {
@@ -47,10 +48,14 @@ static DEFINE_PCI_DEVICE_TABLE(pciidlist) = {
47MODULE_DEVICE_TABLE(pci, pciidlist); 48MODULE_DEVICE_TABLE(pci, pciidlist);
48 49
49static int qxl_modeset = -1; 50static int qxl_modeset = -1;
51int qxl_num_crtc = 4;
50 52
51MODULE_PARM_DESC(modeset, "Disable/Enable modesetting"); 53MODULE_PARM_DESC(modeset, "Disable/Enable modesetting");
52module_param_named(modeset, qxl_modeset, int, 0400); 54module_param_named(modeset, qxl_modeset, int, 0400);
53 55
56MODULE_PARM_DESC(num_heads, "Number of virtual crtcs to expose (default 4)");
57module_param_named(num_heads, qxl_num_crtc, int, 0400);
58
54static struct drm_driver qxl_driver; 59static struct drm_driver qxl_driver;
55static struct pci_driver qxl_pci_driver; 60static struct pci_driver qxl_pci_driver;
56 61
@@ -73,13 +78,6 @@ qxl_pci_remove(struct pci_dev *pdev)
73 drm_put_dev(dev); 78 drm_put_dev(dev);
74} 79}
75 80
76static struct pci_driver qxl_pci_driver = {
77 .name = DRIVER_NAME,
78 .id_table = pciidlist,
79 .probe = qxl_pci_probe,
80 .remove = qxl_pci_remove,
81};
82
83static const struct file_operations qxl_fops = { 81static const struct file_operations qxl_fops = {
84 .owner = THIS_MODULE, 82 .owner = THIS_MODULE,
85 .open = drm_open, 83 .open = drm_open,
@@ -90,6 +88,130 @@ static const struct file_operations qxl_fops = {
90 .mmap = qxl_mmap, 88 .mmap = qxl_mmap,
91}; 89};
92 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
93static struct drm_driver qxl_driver = { 215static struct drm_driver qxl_driver = {
94 .driver_features = DRIVER_GEM | DRIVER_MODESET | 216 .driver_features = DRIVER_GEM | DRIVER_MODESET |
95 DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED, 217 DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED,