drm/nouveau/clk: Allow boosting only when NvBoost is set
authorKarol Herbst <karolherbst@gmail.com>
Tue, 12 Jul 2016 19:36:08 +0000 (21:36 +0200)
committerBen Skeggs <bskeggs@redhat.com>
Wed, 12 Oct 2016 07:29:25 +0000 (17:29 +1000)
0: base clock from the vbios is max clock (default)
1: boost only to boost clock from the vbios
2: boost to max clock available

v2: Moved into nvkm_cstate_valid.
v4: Check the existence of the clocks before limiting.
v5: Default to boost level 0.

Signed-off-by: Karol Herbst <karolherbst@gmail.com>
Reviewed-by: Martin Peres <martin.peres@free.fr>
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
drivers/gpu/drm/nouveau/include/nvkm/subdev/clk.h
drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c
drivers/gpu/drm/nouveau/nvkm/subdev/clk/gf100.c
drivers/gpu/drm/nouveau/nvkm/subdev/clk/gk104.c

index cc2a976446a90a1d565d8a044367d7b04ac54e3e..e5275f742977f01a0fca31e099ac0a16639b2ef3 100644 (file)
@@ -72,7 +72,8 @@ struct nvkm_pstate {
 struct nvkm_domain {
        enum nv_clk_src name;
        u8 bios; /* 0xff for none */
-#define NVKM_CLK_DOM_FLAG_CORE 0x01
+#define NVKM_CLK_DOM_FLAG_CORE    0x01
+#define NVKM_CLK_DOM_FLAG_VPSTATE 0x02
        u8 flags;
        const char *mname;
        int mdiv;
@@ -102,6 +103,12 @@ struct nvkm_clk {
        u8  temp;
 
        bool allow_reclock;
+#define NVKM_CLK_BOOST_NONE 0x0
+#define NVKM_CLK_BOOST_BIOS 0x1
+#define NVKM_CLK_BOOST_FULL 0x2
+       u8  boost_mode;
+       u32 base_khz;
+       u32 boost_khz;
 
        /*XXX: die, these are here *only* to support the completely
         *     bat-shit insane what-was-nouveau_hw.c code
index 60392b2edcbbe7cac6c4d8f7f3a8311133fdb888..fa1c12185e19f54abe95fd04e772dadf8b9a1470 100644 (file)
@@ -27,6 +27,7 @@
 #include <subdev/bios/boost.h>
 #include <subdev/bios/cstep.h>
 #include <subdev/bios/perf.h>
+#include <subdev/bios/vpstate.h>
 #include <subdev/fb.h>
 #include <subdev/therm.h>
 #include <subdev/volt.h>
@@ -78,9 +79,25 @@ static bool
 nvkm_cstate_valid(struct nvkm_clk *clk, struct nvkm_cstate *cstate,
                  u32 max_volt, int temp)
 {
+       const struct nvkm_domain *domain = clk->domains;
        struct nvkm_volt *volt = clk->subdev.device->volt;
        int voltage;
 
+       while (domain && domain->name != nv_clk_src_max) {
+               if (domain->flags & NVKM_CLK_DOM_FLAG_VPSTATE) {
+                       u32 freq = cstate->domain[domain->name];
+                       switch (clk->boost_mode) {
+                       case NVKM_CLK_BOOST_NONE:
+                               if (clk->base_khz && freq > clk->base_khz)
+                                       return false;
+                       case NVKM_CLK_BOOST_BIOS:
+                               if (clk->boost_khz && freq > clk->boost_khz)
+                                       return false;
+                       }
+               }
+               domain++;
+       }
+
        if (!volt)
                return true;
 
@@ -635,10 +652,22 @@ int
 nvkm_clk_ctor(const struct nvkm_clk_func *func, struct nvkm_device *device,
              int index, bool allow_reclock, struct nvkm_clk *clk)
 {
+       struct nvkm_subdev *subdev = &clk->subdev;
+       struct nvkm_bios *bios = device->bios;
        int ret, idx, arglen;
        const char *mode;
+       struct nvbios_vpstate_header h;
+
+       nvkm_subdev_ctor(&nvkm_clk, device, index, subdev);
+
+       if (bios && !nvbios_vpstate_parse(bios, &h)) {
+               struct nvbios_vpstate_entry base, boost;
+               if (!nvbios_vpstate_entry(bios, &h, h.boost_id, &boost))
+                       clk->boost_khz = boost.clock_mhz * 1000;
+               if (!nvbios_vpstate_entry(bios, &h, h.base_id, &base))
+                       clk->base_khz = base.clock_mhz * 1000;
+       }
 
-       nvkm_subdev_ctor(&nvkm_clk, device, index, &clk->subdev);
        clk->func = func;
        INIT_LIST_HEAD(&clk->states);
        clk->domains = func->domains;
@@ -681,6 +710,8 @@ nvkm_clk_ctor(const struct nvkm_clk_func *func, struct nvkm_device *device,
        if (mode)
                clk->ustate_dc = nvkm_clk_nstate(clk, mode, arglen);
 
+       clk->boost_mode = nvkm_longopt(device->cfgopt, "NvBoost",
+                                      NVKM_CLK_BOOST_NONE);
        return 0;
 }
 
index 89d5543118cff139e7736d2d69dcab0c12984041..7f67f9f5a550120e405337be5f5bc50bd7a419dd 100644 (file)
@@ -457,7 +457,7 @@ gf100_clk = {
                { nv_clk_src_hubk06 , 0x00 },
                { nv_clk_src_hubk01 , 0x01 },
                { nv_clk_src_copy   , 0x02 },
-               { nv_clk_src_gpc    , 0x03, 0, "core", 2000 },
+               { nv_clk_src_gpc    , 0x03, NVKM_CLK_DOM_FLAG_VPSTATE, "core", 2000 },
                { nv_clk_src_rop    , 0x04 },
                { nv_clk_src_mem    , 0x05, 0, "memory", 1000 },
                { nv_clk_src_vdec   , 0x06 },
index 06bc0d2d6ae195bb6c9cf5f88141bfef8e572a31..0b37e3da7feb6b8d0e7eecbfe64b7ee958fbe4b3 100644 (file)
@@ -491,7 +491,7 @@ gk104_clk = {
        .domains = {
                { nv_clk_src_crystal, 0xff },
                { nv_clk_src_href   , 0xff },
-               { nv_clk_src_gpc    , 0x00, NVKM_CLK_DOM_FLAG_CORE, "core", 2000 },
+               { nv_clk_src_gpc    , 0x00, NVKM_CLK_DOM_FLAG_CORE | NVKM_CLK_DOM_FLAG_VPSTATE, "core", 2000 },
                { nv_clk_src_hubk07 , 0x01, NVKM_CLK_DOM_FLAG_CORE },
                { nv_clk_src_rop    , 0x02, NVKM_CLK_DOM_FLAG_CORE },
                { nv_clk_src_mem    , 0x03, 0, "memory", 500 },