2 * Copyright 2012 Red Hat Inc.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
25 #include <linux/module.h>
26 #include <linux/pci.h>
28 #include <core/device.h>
29 #include <core/client.h>
30 #include <core/class.h>
32 #include <subdev/device.h>
34 #include "nouveau_drm.h"
36 int __devinit nouveau_pci_probe(struct pci_dev *, const struct pci_device_id *);
37 void nouveau_pci_remove(struct pci_dev *);
38 int nouveau_pci_suspend(struct pci_dev *, pm_message_t);
39 int nouveau_pci_resume(struct pci_dev *);
40 int __init nouveau_init(struct pci_driver *);
41 void __exit nouveau_exit(struct pci_driver *);
43 int nouveau_load(struct drm_device *, unsigned long);
44 int nouveau_unload(struct drm_device *);
45 void *nouveau_newpriv(struct drm_device *);
47 MODULE_PARM_DESC(config, "option string to pass to driver core");
48 static char *nouveau_config;
49 module_param_named(config, nouveau_config, charp, 0400);
51 MODULE_PARM_DESC(debug, "debug string to pass to driver core");
52 static char *nouveau_debug;
53 module_param_named(debug, nouveau_debug, charp, 0400);
56 nouveau_name(struct pci_dev *pdev)
58 u64 name = (u64)pci_domain_nr(pdev->bus) << 32;
59 name |= pdev->bus->number << 16;
60 name |= PCI_SLOT(pdev->devfn) << 8;
61 return name | PCI_FUNC(pdev->devfn);
65 nouveau_cli_create(struct pci_dev *pdev, u32 name, int size, void **pcli)
67 struct nouveau_cli *cli;
70 ret = nouveau_client_create_(name, nouveau_name(pdev), nouveau_config,
71 nouveau_debug, size, pcli);
76 mutex_init(&cli->mutex);
81 nouveau_cli_destroy(struct nouveau_cli *cli)
83 struct nouveau_object *client = nv_object(cli);
84 nouveau_client_fini(&cli->base, false);
85 atomic_set(&client->refcount, 1);
86 nouveau_object_ref(NULL, &client);
90 nouveau_drm_probe(struct pci_dev *pdev, const struct pci_device_id *pent)
92 struct nouveau_device *device;
95 ret = nouveau_device_create(pdev, nouveau_name(pdev), pci_name(pdev),
96 nouveau_config, nouveau_debug, &device);
100 pci_set_master(pdev);
102 ret = nouveau_pci_probe(pdev, pent);
104 nouveau_device_destroy(&device);
112 nouveau_drm_load(struct drm_device *dev, unsigned long flags)
114 struct pci_dev *pdev = dev->pdev;
115 struct nouveau_drm *drm;
118 ret = nouveau_cli_create(pdev, 0, sizeof(*drm), (void**)&drm);
119 dev->dev_private = drm;
123 INIT_LIST_HEAD(&drm->clients);
126 ret = nouveau_object_new(nv_object(drm), NVDRM_CLIENT, NVDRM_DEVICE,
127 0x0080, &(struct nv_device_class) {
131 }, sizeof(struct nv_device_class),
136 ret = nouveau_load(dev, flags);
143 nouveau_cli_destroy(&drm->client);
148 nouveau_drm_unload(struct drm_device *dev)
150 struct nouveau_drm *drm = nouveau_newpriv(dev);
151 struct pci_dev *pdev = dev->pdev;
154 ret = nouveau_unload(dev);
158 pci_set_drvdata(pdev, drm->client.base.device);
159 nouveau_cli_destroy(&drm->client);
164 nouveau_drm_remove(struct pci_dev *pdev)
166 struct nouveau_device *device;
167 nouveau_pci_remove(pdev);
168 device = pci_get_drvdata(pdev);
169 nouveau_device_destroy(&device);
173 nouveau_drm_suspend(struct pci_dev *pdev, pm_message_t pm_state)
175 struct drm_device *dev = pci_get_drvdata(pdev);
176 struct nouveau_drm *drm = nouveau_newpriv(dev);
177 struct nouveau_cli *cli;
180 if (dev->switch_power_state == DRM_SWITCH_POWER_OFF ||
181 pm_state.event == PM_EVENT_PRETHAW)
184 ret = nouveau_pci_suspend(pdev, pm_state);
188 list_for_each_entry(cli, &drm->clients, head) {
189 ret = nouveau_client_fini(&cli->base, true);
194 ret = nouveau_client_fini(&drm->client.base, true);
198 pci_save_state(pdev);
199 if (pm_state.event == PM_EVENT_SUSPEND) {
200 pci_disable_device(pdev);
201 pci_set_power_state(pdev, PCI_D3hot);
207 list_for_each_entry_continue_reverse(cli, &drm->clients, head) {
208 nouveau_client_init(&cli->base);
211 nouveau_pci_resume(pdev);
216 nouveau_drm_resume(struct pci_dev *pdev)
218 struct drm_device *dev = pci_get_drvdata(pdev);
219 struct nouveau_drm *drm = nouveau_newpriv(dev);
220 struct nouveau_cli *cli;
223 if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
226 pci_set_power_state(pdev, PCI_D0);
227 pci_restore_state(pdev);
228 ret = pci_enable_device(pdev);
231 pci_set_master(pdev);
233 nouveau_client_init(&drm->client.base);
235 list_for_each_entry(cli, &drm->clients, head) {
236 nouveau_client_init(&cli->base);
239 return nouveau_pci_resume(pdev);
242 static struct pci_device_id
243 nouveau_drm_pci_table[] = {
245 PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID),
246 .class = PCI_BASE_CLASS_DISPLAY << 16,
247 .class_mask = 0xff << 16,
250 PCI_DEVICE(PCI_VENDOR_ID_NVIDIA_SGS, PCI_ANY_ID),
251 .class = PCI_BASE_CLASS_DISPLAY << 16,
252 .class_mask = 0xff << 16,
257 static struct pci_driver
258 nouveau_drm_pci_driver = {
260 .id_table = nouveau_drm_pci_table,
261 .probe = nouveau_drm_probe,
262 .remove = nouveau_drm_remove,
263 .suspend = nouveau_drm_suspend,
264 .resume = nouveau_drm_resume,
268 nouveau_drm_init(void)
270 return nouveau_init(&nouveau_drm_pci_driver);
274 nouveau_drm_exit(void)
276 nouveau_exit(&nouveau_drm_pci_driver);
279 module_init(nouveau_drm_init);
280 module_exit(nouveau_drm_exit);
282 MODULE_DEVICE_TABLE(pci, nouveau_drm_pci_table);
283 MODULE_AUTHOR("Nouveau Project");
284 MODULE_DESCRIPTION("nVidia Riva/TNT/GeForce/Quadro/Tesla");
285 MODULE_LICENSE("GPL and additional rights");