drm/nouveau/pm: extend profile interface for destroy/init/fini
authorBen Skeggs <bskeggs@redhat.com>
Tue, 24 Jan 2012 08:03:25 +0000 (18:03 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Tue, 13 Mar 2012 07:09:11 +0000 (17:09 +1000)
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Signed-off-by: Martin Peres <martin.peres@labri.fr>
drivers/gpu/drm/nouveau/nouveau_drv.h
drivers/gpu/drm/nouveau/nouveau_pm.c

index 009089e093f3c559930e41dc1386391a8d62dee4..63e77fc282f2f0eb552cbbb357571c776179f692 100644 (file)
@@ -487,6 +487,9 @@ struct nouveau_pm_tbl_entry {
 
 struct nouveau_pm_profile;
 struct nouveau_pm_profile_func {
+       void (*destroy)(struct nouveau_pm_profile *);
+       void (*init)(struct nouveau_pm_profile *);
+       void (*fini)(struct nouveau_pm_profile *);
        struct nouveau_pm_level *(*select)(struct nouveau_pm_profile *);
 };
 
@@ -556,6 +559,7 @@ struct nouveau_pm_engine {
 
        struct nouveau_pm_profile *profile_ac;
        struct nouveau_pm_profile *profile_dc;
+       struct nouveau_pm_profile *profile;
        struct list_head profiles;
 
        struct nouveau_pm_level boot;
index 4fff09e3f5928b78a9a0cac7eda7eccf2cf1f1c1..dcc16927716faef72952a1c20bd9f4c2dedd46c4 100644 (file)
@@ -183,6 +183,12 @@ nouveau_pm_trigger(struct drm_device *dev)
        else
                profile = pm->profile_dc;
 
+       if (profile != pm->profile) {
+               pm->profile->func->fini(pm->profile);
+               pm->profile = profile;
+               pm->profile->func->init(pm->profile);
+       }
+
        /* select performance level based on profile */
        perflvl = profile->func->select(profile);
 
@@ -251,6 +257,11 @@ nouveau_pm_profile_set(struct drm_device *dev, const char *profile)
        return 0;
 }
 
+static void
+nouveau_pm_static_dummy(struct nouveau_pm_profile *profile)
+{
+}
+
 static struct nouveau_pm_level *
 nouveau_pm_static_select(struct nouveau_pm_profile *profile)
 {
@@ -258,6 +269,9 @@ nouveau_pm_static_select(struct nouveau_pm_profile *profile)
 }
 
 const struct nouveau_pm_profile_func nouveau_pm_static_profile_func = {
+       .destroy = nouveau_pm_static_dummy,
+       .init = nouveau_pm_static_dummy,
+       .fini = nouveau_pm_static_dummy,
        .select = nouveau_pm_static_select,
 };
 
@@ -856,6 +870,7 @@ nouveau_pm_init(struct drm_device *dev)
 
        pm->profile_ac = &pm->boot.profile;
        pm->profile_dc = &pm->boot.profile;
+       pm->profile = &pm->boot.profile;
        pm->cur = &pm->boot;
 
        /* add performance levels from vbios */
@@ -893,6 +908,12 @@ nouveau_pm_fini(struct drm_device *dev)
 {
        struct drm_nouveau_private *dev_priv = dev->dev_private;
        struct nouveau_pm_engine *pm = &dev_priv->engine.pm;
+       struct nouveau_pm_profile *profile, *tmp;
+
+       list_for_each_entry_safe(profile, tmp, &pm->profiles, head) {
+               list_del(&profile->head);
+               profile->func->destroy(profile);
+       }
 
        if (pm->cur != &pm->boot)
                nouveau_pm_perflvl_set(dev, &pm->boot);