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: Dave Airlie <airlied@redhat.com>
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
This commit is contained in:
Dave Airlie 2012-11-02 11:04:28 +10:00 committed by Ben Skeggs
parent c839d748bd
commit 2d8b9ccbce
3 changed files with 71 additions and 31 deletions

View File

@ -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 @@ nouveau_drm_suspend(struct pci_dev *pdev, pm_message_t pm_state)
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

View File

@ -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)

View File

@ -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;
}
}