drm/nouveau/clk: allow end-user reclocking for nv40, nvaa, and nve0 clock types
authorIlia Mirkin <imirkin@alum.mit.edu>
Sun, 18 May 2014 05:04:16 +0000 (01:04 -0400)
committerBen Skeggs <bskeggs@redhat.com>
Tue, 10 Jun 2014 06:05:51 +0000 (16:05 +1000)
Use with caution.

Signed-off-by: Ilia Mirkin <imirkin@alum.mit.edu>
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
drivers/gpu/drm/nouveau/core/include/subdev/clock.h
drivers/gpu/drm/nouveau/core/subdev/clock/base.c
drivers/gpu/drm/nouveau/core/subdev/clock/nv04.c
drivers/gpu/drm/nouveau/core/subdev/clock/nv40.c
drivers/gpu/drm/nouveau/core/subdev/clock/nv50.c
drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c
drivers/gpu/drm/nouveau/core/subdev/clock/nvaa.c
drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c
drivers/gpu/drm/nouveau/core/subdev/clock/nve0.c

index 8f4ced75444a95478887b4be5791fc99dd3499dc..c01e29c9f89ac023ce24c9229fe1cdf14e5c4c16 100644 (file)
@@ -77,6 +77,8 @@ struct nouveau_clock {
        int tstate; /* thermal adjustment (max-) */
        int dstate; /* display adjustment (min+) */
 
+       bool allow_reclock;
+
        int  (*read)(struct nouveau_clock *, enum nv_clk_src);
        int  (*calc)(struct nouveau_clock *, struct nouveau_cstate *);
        int  (*prog)(struct nouveau_clock *);
@@ -106,8 +108,8 @@ struct nouveau_clocks {
        int mdiv;
 };
 
-#define nouveau_clock_create(p,e,o,i,d)                                        \
-       nouveau_clock_create_((p), (e), (o), (i), sizeof(**d), (void **)d)
+#define nouveau_clock_create(p,e,o,i,r,d)                                      \
+       nouveau_clock_create_((p), (e), (o), (i), (r), sizeof(**d), (void **)d)
 #define nouveau_clock_destroy(p) ({                                            \
        struct nouveau_clock *clk = (p);                                       \
        _nouveau_clock_dtor(nv_object(clk));                                   \
@@ -121,7 +123,7 @@ struct nouveau_clocks {
 
 int  nouveau_clock_create_(struct nouveau_object *, struct nouveau_object *,
                           struct nouveau_oclass *,
-                          struct nouveau_clocks *, int, void **);
+                          struct nouveau_clocks *, bool, int, void **);
 void _nouveau_clock_dtor(struct nouveau_object *);
 int _nouveau_clock_init(struct nouveau_object *);
 #define _nouveau_clock_fini _nouveau_subdev_fini
index dd62baead39c54c9a906939576553b59bf9355a2..22351f594d2aaa72713fbb3d56f5151ec4c34e20 100644 (file)
@@ -346,8 +346,8 @@ nouveau_clock_ustate_update(struct nouveau_clock *clk, int req)
        struct nouveau_pstate *pstate;
        int i = 0;
 
-       /* YKW repellant */
-       return -ENOSYS;
+       if (!clk->allow_reclock)
+               return -ENOSYS;
 
        if (req != -1 && req != -2) {
                list_for_each_entry(pstate, &clk->states, head) {
@@ -456,6 +456,7 @@ nouveau_clock_create_(struct nouveau_object *parent,
                      struct nouveau_object *engine,
                      struct nouveau_oclass *oclass,
                      struct nouveau_clocks *clocks,
+                     bool allow_reclock,
                      int length, void **object)
 {
        struct nouveau_device *device = nv_device(parent);
@@ -478,6 +479,8 @@ nouveau_clock_create_(struct nouveau_object *parent,
                ret = nouveau_pstate_new(clk, idx++);
        } while (ret == 0);
 
+       clk->allow_reclock = allow_reclock;
+
        mode = nouveau_stropt(device->cfgopt, "NvClkMode", &arglen);
        if (mode) {
                if (!strncasecmpz(mode, "disabled", arglen)) {
index b74db6cfc4e21ee8f811a08e54da3dfdc7f824a1..eb2d4425a49e45e87fe49983fda2fe48c69adf88 100644 (file)
@@ -82,7 +82,8 @@ nv04_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        struct nv04_clock_priv *priv;
        int ret;
 
-       ret = nouveau_clock_create(parent, engine, oclass, nv04_domain, &priv);
+       ret = nouveau_clock_create(parent, engine, oclass, nv04_domain, false,
+                                  &priv);
        *pobject = nv_object(priv);
        if (ret)
                return ret;
index db7346f79080a2345c7a08c943ee934b4055a569..8a9e168397912f3d040846f548e5852ed1ca6c61 100644 (file)
@@ -213,7 +213,8 @@ nv40_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        struct nv40_clock_priv *priv;
        int ret;
 
-       ret = nouveau_clock_create(parent, engine, oclass, nv40_domain, &priv);
+       ret = nouveau_clock_create(parent, engine, oclass, nv40_domain, true,
+                                  &priv);
        *pobject = nv_object(priv);
        if (ret)
                return ret;
index 250a6d96016bff563946563e93d2aec4a3eeba13..8c132772ba9ea526a5cd2f9339ace5e6a22fd299 100644 (file)
@@ -507,7 +507,7 @@ nv50_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        int ret;
 
        ret = nouveau_clock_create(parent, engine, oclass, pclass->domains,
-                                 &priv);
+                                  false, &priv);
        *pobject = nv_object(priv);
        if (ret)
                return ret;
index 4f5a1373f002b9c09e55f36e8a0acd24fd18ec46..9fb58354a80bd12d3be11866bff5078c23f55494 100644 (file)
@@ -302,7 +302,8 @@ nva3_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        struct nva3_clock_priv *priv;
        int ret;
 
-       ret = nouveau_clock_create(parent, engine, oclass, nva3_domain, &priv);
+       ret = nouveau_clock_create(parent, engine, oclass, nva3_domain, false,
+                                  &priv);
        *pobject = nv_object(priv);
        if (ret)
                return ret;
index 7a723b4f564d18f7506506a6f388db9de378ac9d..6a65fc9e9663a2187c4826efa4ddbb8e31400211 100644 (file)
@@ -421,7 +421,8 @@ nvaa_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        struct nvaa_clock_priv *priv;
        int ret;
 
-       ret = nouveau_clock_create(parent, engine, oclass, nvaa_domains, &priv);
+       ret = nouveau_clock_create(parent, engine, oclass, nvaa_domains, true,
+                                  &priv);
        *pobject = nv_object(priv);
        if (ret)
                return ret;
index c3105720ed246c08064c53c92d73db898366bdf7..dbf8517f54da906fc4ad634950217977565092f8 100644 (file)
@@ -437,7 +437,8 @@ nvc0_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        struct nvc0_clock_priv *priv;
        int ret;
 
-       ret = nouveau_clock_create(parent, engine, oclass, nvc0_domain, &priv);
+       ret = nouveau_clock_create(parent, engine, oclass, nvc0_domain, false,
+                                  &priv);
        *pobject = nv_object(priv);
        if (ret)
                return ret;
index d3c37c96f0e7eaeed97c08749bc23611642705db..4ac1aa30ea11f156adc347cc87839ae72ef7ebd1 100644 (file)
@@ -473,7 +473,8 @@ nve0_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        struct nve0_clock_priv *priv;
        int ret;
 
-       ret = nouveau_clock_create(parent, engine, oclass, nve0_domain, &priv);
+       ret = nouveau_clock_create(parent, engine, oclass, nve0_domain, true,
+                                  &priv);
        *pobject = nv_object(priv);
        if (ret)
                return ret;