Later we will have situations where the expected and the current state
isn't the same.

Signed-off-by: Karol Herbst <karolher...@gmail.com>
Reviewed-by: Martin Peres <martin.pe...@free.fr>
---
 drm/nouveau/include/nvkm/subdev/clk.h |  2 ++
 drm/nouveau/nvkm/subdev/clk/base.c    | 32 +++++++++++++++++++++++++-------
 2 files changed, 27 insertions(+), 7 deletions(-)

diff --git a/drm/nouveau/include/nvkm/subdev/clk.h 
b/drm/nouveau/include/nvkm/subdev/clk.h
index 37263b7f..0e0af704 100644
--- a/drm/nouveau/include/nvkm/subdev/clk.h
+++ b/drm/nouveau/include/nvkm/subdev/clk.h
@@ -101,6 +101,8 @@ struct nvkm_clk {
        int ustate_ac; /* user-requested (-1 disabled, -2 perfmon) */
        int ustate_dc; /* user-requested (-1 disabled, -2 perfmon) */
        int astate; /* perfmon adjustment (base) */
+       struct nvkm_cstate *cstate;
+       int exp_cstateid;
        u8  temp;
 
        bool allow_reclock;
diff --git a/drm/nouveau/nvkm/subdev/clk/base.c 
b/drm/nouveau/nvkm/subdev/clk/base.c
index 0d4d9fdf..d37c13b7 100644
--- a/drm/nouveau/nvkm/subdev/clk/base.c
+++ b/drm/nouveau/nvkm/subdev/clk/base.c
@@ -146,9 +146,14 @@ static struct nvkm_cstate *
 nvkm_cstate_get(struct nvkm_clk *clk, struct nvkm_pstate *pstate, int cstatei)
 {
        struct nvkm_cstate *cstate;
-       if (cstatei == NVKM_CLK_CSTATE_HIGHEST)
+       switch (cstatei) {
+       case NVKM_CLK_CSTATE_HIGHEST:
                return list_last_entry(&pstate->list, typeof(*cstate), head);
-       else {
+       case NVKM_CLK_CSTATE_BASE:
+               return &pstate->base;
+       case NVKM_CLK_CSTATE_DEFAULT:
+               return NULL;
+       default:
                list_for_each_entry(cstate, &pstate->list, head) {
                        if (cstate->id == cstatei)
                                return cstate;
@@ -167,6 +172,9 @@ nvkm_cstate_prog(struct nvkm_clk *clk, struct nvkm_pstate 
*pstate, int cstatei)
        struct nvkm_cstate *cstate;
        int ret;
 
+       if (cstatei == NVKM_CLK_CSTATE_DEFAULT)
+               return 0;
+
        if (!list_empty(&pstate->list)) {
                cstate = nvkm_cstate_get(clk, pstate, cstatei);
                cstate = nvkm_cstate_find_best(clk, pstate, cstate);
@@ -193,6 +201,7 @@ nvkm_cstate_prog(struct nvkm_clk *clk, struct nvkm_pstate 
*pstate, int cstatei)
 
        ret = clk->func->calc(clk, cstate);
        if (ret == 0) {
+               clk->cstate = cstate;
                ret = clk->func->prog(clk);
                clk->func->tidy(clk);
        }
@@ -295,7 +304,7 @@ nvkm_pstate_prog(struct nvkm_clk *clk, int pstatei)
                ram->func->tidy(ram);
        }
 
-       return nvkm_cstate_prog(clk, pstate, NVKM_CLK_CSTATE_HIGHEST);
+       return nvkm_cstate_prog(clk, pstate, clk->exp_cstateid);
 }
 
 static void
@@ -313,9 +322,9 @@ nvkm_clk_update_work(struct work_struct *work)
                pstate = clk->pstate->pstate;
        else
                pstate = NVKM_CLK_PSTATE_DEFAULT;
-       nvkm_trace(subdev, "P %d PWR %d U(AC) %d U(DC) %d A %d T %d°C\n",
+       nvkm_trace(subdev, "P %d PWR %d U(AC) %d U(DC) %d A %d C %d T %d°C\n",
                   pstate, clk->pwrsrc, clk->ustate_ac, clk->ustate_dc,
-                  clk->astate, clk->temp);
+                  clk->astate, clk->exp_cstateid, clk->temp);
 
        pstate = clk->pwrsrc ? clk->ustate_ac : clk->ustate_dc;
        if (clk->state_nr && pstate != -1) {
@@ -536,6 +545,7 @@ nvkm_clk_ustate(struct nvkm_clk *clk, int req, int pwr)
        if (ret >= 0) {
                if (ret -= 2, pwr) clk->ustate_ac = ret;
                else               clk->ustate_dc = ret;
+               clk->exp_cstateid = NVKM_CLK_CSTATE_HIGHEST;
                return nvkm_clk_update(clk, true);
        }
        return ret;
@@ -548,6 +558,7 @@ nvkm_clk_astate(struct nvkm_clk *clk, int req, int rel, 
bool wait)
        if ( rel) clk->astate += rel;
        clk->astate = min(clk->astate, clk->state_nr - 1);
        clk->astate = max(clk->astate, 0);
+       clk->exp_cstateid = NVKM_CLK_CSTATE_BASE;
        return nvkm_clk_update(clk, wait);
 }
 
@@ -618,6 +629,8 @@ nvkm_clk_init(struct nvkm_subdev *subdev)
 
        clk->astate = clk->state_nr - 1;
        clk->pstate = NULL;
+       clk->exp_cstateid = NVKM_CLK_CSTATE_DEFAULT;
+       clk->cstate = NULL;
        clk->temp = 90; /* reasonable default value */
        nvkm_clk_update(clk, true);
        return 0;
@@ -701,15 +714,20 @@ nvkm_clk_ctor(const struct nvkm_clk_func *func, struct 
nvkm_device *device,
        if (mode) {
                clk->ustate_ac = nvkm_clk_nstate(clk, mode, arglen);
                clk->ustate_dc = nvkm_clk_nstate(clk, mode, arglen);
+               clk->exp_cstateid = NVKM_CLK_CSTATE_HIGHEST;
        }
 
        mode = nvkm_stropt(device->cfgopt, "NvClkModeAC", &arglen);
-       if (mode)
+       if (mode) {
                clk->ustate_ac = nvkm_clk_nstate(clk, mode, arglen);
+               clk->exp_cstateid = NVKM_CLK_CSTATE_HIGHEST;
+       }
 
        mode = nvkm_stropt(device->cfgopt, "NvClkModeDC", &arglen);
-       if (mode)
+       if (mode) {
                clk->ustate_dc = nvkm_clk_nstate(clk, mode, arglen);
+               clk->exp_cstateid = NVKM_CLK_CSTATE_HIGHEST;
+       }
 
        clk->boost_mode = nvkm_longopt(device->cfgopt, "NvBoost",
                                       NVKM_CLK_BOOST_NONE);
-- 
2.12.0

_______________________________________________
Nouveau mailing list
Nouveau@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/nouveau

Reply via email to