Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2d8b9ccb authored by Dave Airlie's avatar Dave Airlie Committed by Ben Skeggs
Browse files

drm/nouveau: convert to dev_pm_ops



This is a precursor to dynamic power management support for nouveau,

we need to use pm ops for that, so first convert the driver to using pm ops
interfaces.

Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent c839d748
Loading
Loading
Loading
Loading
+67 −26
Original line number Diff line number Diff line
@@ -395,17 +395,12 @@ nouveau_drm_remove(struct pci_dev *pdev)
}

int
nouveau_drm_suspend(struct pci_dev *pdev, pm_message_t pm_state)
nouveau_do_suspend(struct drm_device *dev)
{
	struct drm_device *dev = pci_get_drvdata(pdev);
	struct nouveau_drm *drm = nouveau_drm(dev);
	struct nouveau_cli *cli;
	int ret;

	if (dev->switch_power_state == DRM_SWITCH_POWER_OFF ||
	    pm_state.event == PM_EVENT_PRETHAW)
		return 0;

	if (dev->mode_config.num_crtc) {
		NV_INFO(drm, "suspending fbcon...\n");
		nouveau_fbcon_set_suspend(dev, 1);
@@ -436,13 +431,6 @@ nouveau_drm_suspend(struct pci_dev *pdev, pm_message_t pm_state)
		goto fail_client;

	nouveau_agp_fini(drm);

	pci_save_state(pdev);
	if (pm_state.event == PM_EVENT_SUSPEND) {
		pci_disable_device(pdev);
		pci_set_power_state(pdev, PCI_D3hot);
	}

	return 0;

fail_client:
@@ -457,24 +445,33 @@ fail_client:
	return ret;
}

int
nouveau_drm_resume(struct pci_dev *pdev)
int nouveau_pmops_suspend(struct device *dev)
{
	struct drm_device *dev = pci_get_drvdata(pdev);
	struct nouveau_drm *drm = nouveau_drm(dev);
	struct nouveau_cli *cli;
	struct pci_dev *pdev = to_pci_dev(dev);
	struct drm_device *drm_dev = pci_get_drvdata(pdev);
	int ret;

	if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
	if (drm_dev->switch_power_state == DRM_SWITCH_POWER_OFF)
		return 0;

	NV_INFO(drm, "re-enabling device...\n");
	pci_set_power_state(pdev, PCI_D0);
	pci_restore_state(pdev);
	ret = pci_enable_device(pdev);
	ret = nouveau_do_suspend(drm_dev);
	if (ret)
		return ret;
	pci_set_master(pdev);

	pci_save_state(pdev);
	pci_disable_device(pdev);
	pci_set_power_state(pdev, PCI_D3hot);

	return 0;
}

int
nouveau_do_resume(struct drm_device *dev)
{
	struct nouveau_drm *drm = nouveau_drm(dev);
	struct nouveau_cli *cli;

	NV_INFO(drm, "re-enabling device...\n");

	nouveau_agp_reset(drm);

@@ -500,6 +497,42 @@ nouveau_drm_resume(struct pci_dev *pdev)
	return 0;
}

int nouveau_pmops_resume(struct device *dev)
{
	struct pci_dev *pdev = to_pci_dev(dev);
	struct drm_device *drm_dev = pci_get_drvdata(pdev);
	int ret;

	if (drm_dev->switch_power_state == DRM_SWITCH_POWER_OFF)
		return 0;

	pci_set_power_state(pdev, PCI_D0);
	pci_restore_state(pdev);
	ret = pci_enable_device(pdev);
	if (ret)
		return ret;
	pci_set_master(pdev);

	return nouveau_do_resume(drm_dev);
}

static int nouveau_pmops_freeze(struct device *dev)
{
	struct pci_dev *pdev = to_pci_dev(dev);
	struct drm_device *drm_dev = pci_get_drvdata(pdev);

	return nouveau_do_suspend(drm_dev);
}

static int nouveau_pmops_thaw(struct device *dev)
{
	struct pci_dev *pdev = to_pci_dev(dev);
	struct drm_device *drm_dev = pci_get_drvdata(pdev);

	return nouveau_do_resume(drm_dev);
}


static int
nouveau_drm_open(struct drm_device *dev, struct drm_file *fpriv)
{
@@ -652,14 +685,22 @@ nouveau_drm_pci_table[] = {
	{}
};

static const struct dev_pm_ops nouveau_pm_ops = {
	.suspend = nouveau_pmops_suspend,
	.resume = nouveau_pmops_resume,
	.freeze = nouveau_pmops_freeze,
	.thaw = nouveau_pmops_thaw,
	.poweroff = nouveau_pmops_freeze,
	.restore = nouveau_pmops_resume,
};

static struct pci_driver
nouveau_drm_pci_driver = {
	.name = "nouveau",
	.id_table = nouveau_drm_pci_table,
	.probe = nouveau_drm_probe,
	.remove = nouveau_drm_remove,
	.suspend = nouveau_drm_suspend,
	.resume = nouveau_drm_resume,
	.driver.pm = &nouveau_pm_ops,
};

static int __init
+2 −2
Original line number Diff line number Diff line
@@ -129,8 +129,8 @@ nouveau_dev(struct drm_device *dev)
	return nv_device(nouveau_drm(dev)->device);
}

int nouveau_drm_suspend(struct pci_dev *, pm_message_t);
int nouveau_drm_resume(struct pci_dev *);
int nouveau_pmops_suspend(struct device *);
int nouveau_pmops_resume(struct device *);

#define NV_FATAL(cli, fmt, args...) nv_fatal((cli), fmt, ##args)
#define NV_ERROR(cli, fmt, args...) nv_error((cli), fmt, ##args)
+2 −3
Original line number Diff line number Diff line
@@ -31,12 +31,11 @@ nouveau_switcheroo_set_state(struct pci_dev *pdev,
			     enum vga_switcheroo_state state)
{
	struct drm_device *dev = pci_get_drvdata(pdev);
	pm_message_t pmm = { .event = PM_EVENT_SUSPEND };

	if (state == VGA_SWITCHEROO_ON) {
		printk(KERN_ERR "VGA switcheroo: switched nouveau on\n");
		dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
		nouveau_drm_resume(pdev);
		nouveau_pmops_resume(&pdev->dev);
		drm_kms_helper_poll_enable(dev);
		dev->switch_power_state = DRM_SWITCH_POWER_ON;
	} else {
@@ -44,7 +43,7 @@ nouveau_switcheroo_set_state(struct pci_dev *pdev,
		dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
		drm_kms_helper_poll_disable(dev);
		nouveau_switcheroo_optimus_dsm();
		nouveau_drm_suspend(pdev, pmm);
		nouveau_pmops_suspend(&pdev->dev);
		dev->switch_power_state = DRM_SWITCH_POWER_OFF;
	}
}