aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/nouveau_drm.c
diff options
context:
space:
mode:
authorAlexandre Courbot <acourbot@nvidia.com>2014-02-17 01:17:26 -0500
committerBen Skeggs <bskeggs@redhat.com>2014-03-26 00:08:04 -0400
commit420b94697722512a2c0732970dc1530197a49adb (patch)
treeeb87f8b5ed60beac890dbe34ca884dc84dc6c765 /drivers/gpu/drm/nouveau/nouveau_drm.c
parent0b681687fe9eaa552059030a90897a78fea8f86a (diff)
support for platform devices
Upcoming mobile Kepler GPUs (such as GK20A) use the platform bus instead of PCI to which Nouveau is tightly dependent. This patch allows Nouveau to handle platform devices by: - abstracting PCI-dependent functions that were typically used for resource querying and page mapping, - introducing a nv_device_is_pci() function that allows to make PCI-dependent code conditional, - providing a nouveau_drm_platform_probe() function that takes a GPU platform device to be probed. Core code as well as engine/subdev drivers are updated wherever possible to make use of these functions. Some older drivers are too dependent on PCI to be properly updated, but all newer code on which future chips may depend should at least be runnable with platform devices. Signed-off-by: Alexandre Courbot <acourbot@nvidia.com> Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau/nouveau_drm.c')
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drm.c59
1 files changed, 51 insertions, 8 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c
index eeadcac8e8f4..8f811a5f16e2 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_drm.c
@@ -82,7 +82,7 @@ module_param_named(runpm, nouveau_runtime_pm, int, 0400);
82static struct drm_driver driver; 82static struct drm_driver driver;
83 83
84static u64 84static u64
85nouveau_name(struct pci_dev *pdev) 85nouveau_pci_name(struct pci_dev *pdev)
86{ 86{
87 u64 name = (u64)pci_domain_nr(pdev->bus) << 32; 87 u64 name = (u64)pci_domain_nr(pdev->bus) << 32;
88 name |= pdev->bus->number << 16; 88 name |= pdev->bus->number << 16;
@@ -90,15 +90,30 @@ nouveau_name(struct pci_dev *pdev)
90 return name | PCI_FUNC(pdev->devfn); 90 return name | PCI_FUNC(pdev->devfn);
91} 91}
92 92
93static u64
94nouveau_platform_name(struct platform_device *platformdev)
95{
96 return platformdev->id;
97}
98
99static u64
100nouveau_name(struct drm_device *dev)
101{
102 if (dev->pdev)
103 return nouveau_pci_name(dev->pdev);
104 else
105 return nouveau_platform_name(dev->platformdev);
106}
107
93static int 108static int
94nouveau_cli_create(struct pci_dev *pdev, const char *name, 109nouveau_cli_create(u64 name, const char *sname,
95 int size, void **pcli) 110 int size, void **pcli)
96{ 111{
97 struct nouveau_cli *cli; 112 struct nouveau_cli *cli;
98 int ret; 113 int ret;
99 114
100 *pcli = NULL; 115 *pcli = NULL;
101 ret = nouveau_client_create_(name, nouveau_name(pdev), nouveau_config, 116 ret = nouveau_client_create_(sname, name, nouveau_config,
102 nouveau_debug, size, pcli); 117 nouveau_debug, size, pcli);
103 cli = *pcli; 118 cli = *pcli;
104 if (ret) { 119 if (ret) {
@@ -282,7 +297,8 @@ static int nouveau_drm_probe(struct pci_dev *pdev,
282 remove_conflicting_framebuffers(aper, "nouveaufb", boot); 297 remove_conflicting_framebuffers(aper, "nouveaufb", boot);
283 kfree(aper); 298 kfree(aper);
284 299
285 ret = nouveau_device_create(pdev, nouveau_name(pdev), pci_name(pdev), 300 ret = nouveau_device_create(pdev, NOUVEAU_BUS_PCI,
301 nouveau_pci_name(pdev), pci_name(pdev),
286 nouveau_config, nouveau_debug, &device); 302 nouveau_config, nouveau_debug, &device);
287 if (ret) 303 if (ret)
288 return ret; 304 return ret;
@@ -305,6 +321,12 @@ nouveau_get_hdmi_dev(struct nouveau_drm *drm)
305{ 321{
306 struct pci_dev *pdev = drm->dev->pdev; 322 struct pci_dev *pdev = drm->dev->pdev;
307 323
324 if (!pdev) {
325 DRM_INFO("not a PCI device; no HDMI");
326 drm->hdmi_device = NULL;
327 return;
328 }
329
308 /* subfunction one is a hdmi audio device? */ 330 /* subfunction one is a hdmi audio device? */
309 drm->hdmi_device = pci_get_bus_and_slot((unsigned int)pdev->bus->number, 331 drm->hdmi_device = pci_get_bus_and_slot((unsigned int)pdev->bus->number,
310 PCI_DEVFN(PCI_SLOT(pdev->devfn), 1)); 332 PCI_DEVFN(PCI_SLOT(pdev->devfn), 1));
@@ -330,7 +352,8 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags)
330 struct nouveau_drm *drm; 352 struct nouveau_drm *drm;
331 int ret; 353 int ret;
332 354
333 ret = nouveau_cli_create(pdev, "DRM", sizeof(*drm), (void**)&drm); 355 ret = nouveau_cli_create(nouveau_name(dev), "DRM", sizeof(*drm),
356 (void **)&drm);
334 if (ret) 357 if (ret)
335 return ret; 358 return ret;
336 359
@@ -346,7 +369,7 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags)
346 /* make sure AGP controller is in a consistent state before we 369 /* make sure AGP controller is in a consistent state before we
347 * (possibly) execute vbios init tables (see nouveau_agp.h) 370 * (possibly) execute vbios init tables (see nouveau_agp.h)
348 */ 371 */
349 if (drm_pci_device_is_agp(dev) && dev->agp) { 372 if (pdev && drm_pci_device_is_agp(dev) && dev->agp) {
350 /* dummy device object, doesn't init anything, but allows 373 /* dummy device object, doesn't init anything, but allows
351 * agp code access to registers 374 * agp code access to registers
352 */ 375 */
@@ -672,7 +695,6 @@ static int nouveau_pmops_thaw(struct device *dev)
672static int 695static int
673nouveau_drm_open(struct drm_device *dev, struct drm_file *fpriv) 696nouveau_drm_open(struct drm_device *dev, struct drm_file *fpriv)
674{ 697{
675 struct pci_dev *pdev = dev->pdev;
676 struct nouveau_drm *drm = nouveau_drm(dev); 698 struct nouveau_drm *drm = nouveau_drm(dev);
677 struct nouveau_cli *cli; 699 struct nouveau_cli *cli;
678 char name[32], tmpname[TASK_COMM_LEN]; 700 char name[32], tmpname[TASK_COMM_LEN];
@@ -686,7 +708,9 @@ nouveau_drm_open(struct drm_device *dev, struct drm_file *fpriv)
686 get_task_comm(tmpname, current); 708 get_task_comm(tmpname, current);
687 snprintf(name, sizeof(name), "%s[%d]", tmpname, pid_nr(fpriv->pid)); 709 snprintf(name, sizeof(name), "%s[%d]", tmpname, pid_nr(fpriv->pid));
688 710
689 ret = nouveau_cli_create(pdev, name, sizeof(*cli), (void **)&cli); 711 ret = nouveau_cli_create(nouveau_name(dev), name, sizeof(*cli),
712 (void **)&cli);
713
690 if (ret) 714 if (ret)
691 goto out_suspend; 715 goto out_suspend;
692 716
@@ -975,6 +999,25 @@ nouveau_drm_pci_driver = {
975 .driver.pm = &nouveau_pm_ops, 999 .driver.pm = &nouveau_pm_ops,
976}; 1000};
977 1001
1002int nouveau_drm_platform_probe(struct platform_device *pdev)
1003{
1004 struct nouveau_device *device;
1005 int ret;
1006
1007 ret = nouveau_device_create(pdev, NOUVEAU_BUS_PLATFORM,
1008 nouveau_platform_name(pdev),
1009 dev_name(&pdev->dev), nouveau_config,
1010 nouveau_debug, &device);
1011
1012 ret = drm_platform_init(&driver, pdev);
1013 if (ret) {
1014 nouveau_object_ref(NULL, (struct nouveau_object **)&device);
1015 return ret;
1016 }
1017
1018 return ret;
1019}
1020
978static int __init 1021static int __init
979nouveau_drm_init(void) 1022nouveau_drm_init(void)
980{ 1023{