Signed-off-by: Karol Herbst <karolher...@gmail.com> --- drm/nouveau/nvkm/subdev/clk/base.c | 62 ++++++++++++++++++++++++++++++++------ 1 file changed, 52 insertions(+), 10 deletions(-)
diff --git a/drm/nouveau/nvkm/subdev/clk/base.c b/drm/nouveau/nvkm/subdev/clk/base.c index 9f44ace0..2a51c078 100644 --- a/drm/nouveau/nvkm/subdev/clk/base.c +++ b/drm/nouveau/nvkm/subdev/clk/base.c @@ -288,6 +288,52 @@ nvkm_cstate_new(struct nvkm_clk *clk, int idx, struct nvkm_pstate *pstate) /****************************************************************************** * P-States *****************************************************************************/ +static struct nvkm_pstate * +nvkm_pstate_find_best(struct nvkm_clk *clk, struct nvkm_pstate *start) +{ + struct nvkm_pstate *pstate; + u8 limit; + + switch (clk->boost_mode) { + case NVKM_CLK_BOOST_NONE: + limit = clk->base_limit.pstate; + if (limit) + break; + case NVKM_CLK_BOOST_BIOS: + limit = clk->boost_limit.pstate; + break; + default: + limit = 0; + break; + } + + if (!limit) + return start; + + for (pstate = start; &pstate->head != &clk->states; + pstate = list_entry(pstate->head.prev, typeof(*pstate), head)) { + if (limit >= pstate->pstate) + break; + } + return pstate; +} + +static struct nvkm_pstate * +nvkm_pstate_get(struct nvkm_clk *clk, int pstateid) +{ + struct nvkm_pstate *pstate; + switch (pstateid) { + case NVKM_CLK_PSTATE_DEFAULT: + return NULL; + default: + list_for_each_entry(pstate, &clk->states, head) { + if (pstate->pstate == pstateid) + return pstate; + } + } + return NULL; +} + static int nvkm_pstate_prog(struct nvkm_clk *clk, int pstateid) { @@ -300,20 +346,16 @@ nvkm_pstate_prog(struct nvkm_clk *clk, int pstateid) if (pstateid == NVKM_CLK_PSTATE_DEFAULT) return 0; - if (clk->pstate && clk->pstate->pstate == pstateid) { - pstate = clk->pstate; - goto cstate; - } - - list_for_each_entry(pstate, &clk->states, head) { - if (pstate->pstate == pstateid) - break; - } + pstate = nvkm_pstate_get(clk, pstateid); + pstate = nvkm_pstate_find_best(clk, pstate); if (!pstate) return -EINVAL; - nvkm_debug(subdev, "setting performance state %x\n", pstateid); + if (clk->pstate && clk->pstate == pstate) + goto cstate; + + nvkm_debug(subdev, "setting performance state %x\n", pstate->pstate); clk->pstate = pstate; nvkm_pcie_set_link(pci, pstate->pcie_speed, pstate->pcie_width); -- 2.14.1 _______________________________________________ Nouveau mailing list Nouveau@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/nouveau