diff options
Diffstat (limited to 'drivers/gpu/drm/ast/ast_drv.c')
-rw-r--r-- | drivers/gpu/drm/ast/ast_drv.c | 242 |
1 files changed, 242 insertions, 0 deletions
diff --git a/drivers/gpu/drm/ast/ast_drv.c b/drivers/gpu/drm/ast/ast_drv.c new file mode 100644 index 000000000000..b56eac6b155f --- /dev/null +++ b/drivers/gpu/drm/ast/ast_drv.c | |||
@@ -0,0 +1,242 @@ | |||
1 | /* | ||
2 | * Copyright 2012 Red Hat Inc. | ||
3 | * | ||
4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
5 | * copy of this software and associated documentation files (the | ||
6 | * "Software"), to deal in the Software without restriction, including | ||
7 | * without limitation the rights to use, copy, modify, merge, publish, | ||
8 | * distribute, sub license, and/or sell copies of the Software, and to | ||
9 | * permit persons to whom the Software is furnished to do so, subject to | ||
10 | * the following conditions: | ||
11 | * | ||
12 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
13 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
14 | * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | ||
15 | * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, | ||
16 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR | ||
17 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE | ||
18 | * USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
19 | * | ||
20 | * The above copyright notice and this permission notice (including the | ||
21 | * next paragraph) shall be included in all copies or substantial portions | ||
22 | * of the Software. | ||
23 | * | ||
24 | */ | ||
25 | /* | ||
26 | * Authors: Dave Airlie <airlied@redhat.com> | ||
27 | */ | ||
28 | #include <linux/module.h> | ||
29 | #include <linux/console.h> | ||
30 | |||
31 | #include "drmP.h" | ||
32 | #include "drm.h" | ||
33 | #include "drm_crtc_helper.h" | ||
34 | |||
35 | #include "ast_drv.h" | ||
36 | |||
37 | int ast_modeset = -1; | ||
38 | |||
39 | MODULE_PARM_DESC(modeset, "Disable/Enable modesetting"); | ||
40 | module_param_named(modeset, ast_modeset, int, 0400); | ||
41 | |||
42 | #define PCI_VENDOR_ASPEED 0x1a03 | ||
43 | |||
44 | static struct drm_driver driver; | ||
45 | |||
46 | #define AST_VGA_DEVICE(id, info) { \ | ||
47 | .class = PCI_BASE_CLASS_DISPLAY << 16, \ | ||
48 | .class_mask = 0xff0000, \ | ||
49 | .vendor = PCI_VENDOR_ASPEED, \ | ||
50 | .device = id, \ | ||
51 | .subvendor = PCI_ANY_ID, \ | ||
52 | .subdevice = PCI_ANY_ID, \ | ||
53 | .driver_data = (unsigned long) info } | ||
54 | |||
55 | static DEFINE_PCI_DEVICE_TABLE(pciidlist) = { | ||
56 | AST_VGA_DEVICE(PCI_CHIP_AST2000, NULL), | ||
57 | AST_VGA_DEVICE(PCI_CHIP_AST2100, NULL), | ||
58 | /* AST_VGA_DEVICE(PCI_CHIP_AST1180, NULL), - don't bind to 1180 for now */ | ||
59 | {0, 0, 0}, | ||
60 | }; | ||
61 | |||
62 | MODULE_DEVICE_TABLE(pci, pciidlist); | ||
63 | |||
64 | static int __devinit | ||
65 | ast_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | ||
66 | { | ||
67 | return drm_get_pci_dev(pdev, ent, &driver); | ||
68 | } | ||
69 | |||
70 | static void | ||
71 | ast_pci_remove(struct pci_dev *pdev) | ||
72 | { | ||
73 | struct drm_device *dev = pci_get_drvdata(pdev); | ||
74 | |||
75 | drm_put_dev(dev); | ||
76 | } | ||
77 | |||
78 | |||
79 | |||
80 | static int ast_drm_freeze(struct drm_device *dev) | ||
81 | { | ||
82 | drm_kms_helper_poll_disable(dev); | ||
83 | |||
84 | pci_save_state(dev->pdev); | ||
85 | |||
86 | console_lock(); | ||
87 | ast_fbdev_set_suspend(dev, 1); | ||
88 | console_unlock(); | ||
89 | return 0; | ||
90 | } | ||
91 | |||
92 | static int ast_drm_thaw(struct drm_device *dev) | ||
93 | { | ||
94 | int error = 0; | ||
95 | |||
96 | ast_post_gpu(dev); | ||
97 | |||
98 | drm_mode_config_reset(dev); | ||
99 | mutex_lock(&dev->mode_config.mutex); | ||
100 | drm_helper_resume_force_mode(dev); | ||
101 | mutex_unlock(&dev->mode_config.mutex); | ||
102 | |||
103 | console_lock(); | ||
104 | ast_fbdev_set_suspend(dev, 0); | ||
105 | console_unlock(); | ||
106 | return error; | ||
107 | } | ||
108 | |||
109 | static int ast_drm_resume(struct drm_device *dev) | ||
110 | { | ||
111 | int ret; | ||
112 | |||
113 | if (pci_enable_device(dev->pdev)) | ||
114 | return -EIO; | ||
115 | |||
116 | ret = ast_drm_thaw(dev); | ||
117 | if (ret) | ||
118 | return ret; | ||
119 | |||
120 | drm_kms_helper_poll_enable(dev); | ||
121 | return 0; | ||
122 | } | ||
123 | |||
124 | static int ast_pm_suspend(struct device *dev) | ||
125 | { | ||
126 | struct pci_dev *pdev = to_pci_dev(dev); | ||
127 | struct drm_device *ddev = pci_get_drvdata(pdev); | ||
128 | int error; | ||
129 | |||
130 | error = ast_drm_freeze(ddev); | ||
131 | if (error) | ||
132 | return error; | ||
133 | |||
134 | pci_disable_device(pdev); | ||
135 | pci_set_power_state(pdev, PCI_D3hot); | ||
136 | return 0; | ||
137 | } | ||
138 | static int ast_pm_resume(struct device *dev) | ||
139 | { | ||
140 | struct pci_dev *pdev = to_pci_dev(dev); | ||
141 | struct drm_device *ddev = pci_get_drvdata(pdev); | ||
142 | return ast_drm_resume(ddev); | ||
143 | } | ||
144 | |||
145 | static int ast_pm_freeze(struct device *dev) | ||
146 | { | ||
147 | struct pci_dev *pdev = to_pci_dev(dev); | ||
148 | struct drm_device *ddev = pci_get_drvdata(pdev); | ||
149 | |||
150 | if (!ddev || !ddev->dev_private) | ||
151 | return -ENODEV; | ||
152 | return ast_drm_freeze(ddev); | ||
153 | |||
154 | } | ||
155 | |||
156 | static int ast_pm_thaw(struct device *dev) | ||
157 | { | ||
158 | struct pci_dev *pdev = to_pci_dev(dev); | ||
159 | struct drm_device *ddev = pci_get_drvdata(pdev); | ||
160 | return ast_drm_thaw(ddev); | ||
161 | } | ||
162 | |||
163 | static int ast_pm_poweroff(struct device *dev) | ||
164 | { | ||
165 | struct pci_dev *pdev = to_pci_dev(dev); | ||
166 | struct drm_device *ddev = pci_get_drvdata(pdev); | ||
167 | |||
168 | return ast_drm_freeze(ddev); | ||
169 | } | ||
170 | |||
171 | static const struct dev_pm_ops ast_pm_ops = { | ||
172 | .suspend = ast_pm_suspend, | ||
173 | .resume = ast_pm_resume, | ||
174 | .freeze = ast_pm_freeze, | ||
175 | .thaw = ast_pm_thaw, | ||
176 | .poweroff = ast_pm_poweroff, | ||
177 | .restore = ast_pm_resume, | ||
178 | }; | ||
179 | |||
180 | static struct pci_driver ast_pci_driver = { | ||
181 | .name = DRIVER_NAME, | ||
182 | .id_table = pciidlist, | ||
183 | .probe = ast_pci_probe, | ||
184 | .remove = ast_pci_remove, | ||
185 | .driver.pm = &ast_pm_ops, | ||
186 | }; | ||
187 | |||
188 | static const struct file_operations ast_fops = { | ||
189 | .owner = THIS_MODULE, | ||
190 | .open = drm_open, | ||
191 | .release = drm_release, | ||
192 | .unlocked_ioctl = drm_ioctl, | ||
193 | .mmap = ast_mmap, | ||
194 | .poll = drm_poll, | ||
195 | .fasync = drm_fasync, | ||
196 | .read = drm_read, | ||
197 | }; | ||
198 | |||
199 | static struct drm_driver driver = { | ||
200 | .driver_features = DRIVER_USE_MTRR | DRIVER_MODESET | DRIVER_GEM, | ||
201 | .dev_priv_size = 0, | ||
202 | |||
203 | .load = ast_driver_load, | ||
204 | .unload = ast_driver_unload, | ||
205 | |||
206 | .fops = &ast_fops, | ||
207 | .name = DRIVER_NAME, | ||
208 | .desc = DRIVER_DESC, | ||
209 | .date = DRIVER_DATE, | ||
210 | .major = DRIVER_MAJOR, | ||
211 | .minor = DRIVER_MINOR, | ||
212 | .patchlevel = DRIVER_PATCHLEVEL, | ||
213 | |||
214 | .gem_init_object = ast_gem_init_object, | ||
215 | .gem_free_object = ast_gem_free_object, | ||
216 | .dumb_create = ast_dumb_create, | ||
217 | .dumb_map_offset = ast_dumb_mmap_offset, | ||
218 | .dumb_destroy = ast_dumb_destroy, | ||
219 | |||
220 | }; | ||
221 | |||
222 | static int __init ast_init(void) | ||
223 | { | ||
224 | if (vgacon_text_force() && ast_modeset == -1) | ||
225 | return -EINVAL; | ||
226 | |||
227 | if (ast_modeset == 0) | ||
228 | return -EINVAL; | ||
229 | return drm_pci_init(&driver, &ast_pci_driver); | ||
230 | } | ||
231 | static void __exit ast_exit(void) | ||
232 | { | ||
233 | drm_pci_exit(&driver, &ast_pci_driver); | ||
234 | } | ||
235 | |||
236 | module_init(ast_init); | ||
237 | module_exit(ast_exit); | ||
238 | |||
239 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
240 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
241 | MODULE_LICENSE("GPL and additional rights"); | ||
242 | |||