[05/19] clk: allow boosting only when NvBoost is set

Submitted by Karol Herbst on March 17, 2016, 11:03 p.m.

Details

Message ID 1458255836-3878-6-git-send-email-nouveau@karolherbst.de
State New
Headers show
Series "Volting/Clocking improvements for Fermi and newer" ( rev: 1 ) in Nouveau

Not browsing as part of any series.

Commit Message

Karol Herbst March 17, 2016, 11:03 p.m.
0: base clock from the vbios is max clock
1: boost only to boost clock from the vbios (default)
2: boost to max clock available
Signed-off-by: Karol Herbst <nouveau@karolherbst.de>
---
 drm/nouveau/include/nvkm/subdev/clk.h |  9 ++++++++-
 drm/nouveau/nvkm/subdev/clk/base.c    | 26 ++++++++++++++++++++++++--
 drm/nouveau/nvkm/subdev/clk/gf100.c   |  2 +-
 drm/nouveau/nvkm/subdev/clk/gk104.c   |  2 +-
 4 files changed, 34 insertions(+), 5 deletions(-)

Patch hide | download patch | download mbox

diff --git a/drm/nouveau/include/nvkm/subdev/clk.h b/drm/nouveau/include/nvkm/subdev/clk.h
index fb54417..a292e5a 100644
--- a/drm/nouveau/include/nvkm/subdev/clk.h
+++ b/drm/nouveau/include/nvkm/subdev/clk.h
@@ -67,7 +67,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_BASECLK 0x02
 	u8 flags;
 	const char *mname;
 	int mdiv;
@@ -97,6 +98,12 @@  struct nvkm_clk {
 	int dstate; /* display adjustment (min+) */
 
 	bool allow_reclock;
+#define NVKM_CLK_BOOST_NONE 0x0
+#define NVKM_CLK_BOOST_AVG  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
diff --git a/drm/nouveau/nvkm/subdev/clk/base.c b/drm/nouveau/nvkm/subdev/clk/base.c
index 4928668..d575412 100644
--- a/drm/nouveau/nvkm/subdev/clk/base.c
+++ b/drm/nouveau/nvkm/subdev/clk/base.c
@@ -160,6 +160,18 @@  nvkm_cstate_new(struct nvkm_clk *clk, int idx, struct nvkm_pstate *pstate)
 		if (domain->flags & NVKM_CLK_DOM_FLAG_CORE) {
 			u32 freq = nvkm_clk_adjust(clk, true, pstate->pstate,
 						   domain->bios, cstepX.freq);
+			if (domain->flags & NVKM_CLK_DOM_FLAG_BASECLK) {
+				switch (clk->boost_mode) {
+				case NVKM_CLK_BOOST_NONE:
+					if (clk->base_khz
+					    && freq > clk->base_khz)
+						goto err;
+				case NVKM_CLK_BOOST_AVG:
+					if (clk->boost_khz
+					    && freq > clk->boost_khz)
+						goto err;
+				}
+			}
 			cstate->domain[domain->name] = freq;
 		}
 		domain++;
@@ -167,6 +179,9 @@  nvkm_cstate_new(struct nvkm_clk *clk, int idx, struct nvkm_pstate *pstate)
 
 	list_add(&cstate->head, &pstate->list);
 	return 0;
+err:
+	kfree(cstate);
+	return -EINVAL;
 }
 
 /******************************************************************************
@@ -570,14 +585,21 @@  nvkm_clk_ctor(const struct nvkm_clk_func *func, struct nvkm_device *device,
 
 	nvkm_subdev_ctor(&nvkm_clk, device, index, 0, subdev);
 
+	clk->boost_mode = nvkm_longopt(device->cfgopt, "NvBoost",
+				       NVKM_CLK_BOOST_AVG);
 	if (bios && !nvbios_baseclock_parse(bios, &h)) {
 		struct nvbios_baseclk_entry base, boost;
-		if (!nvbios_baseclock_entry(bios, &h, h.boost, &boost))
+		if (!nvbios_baseclock_entry(bios, &h, h.boost, &boost)) {
+			clk->boost_khz = boost.clock_mhz * 1000;
 			nvkm_info(subdev, "boost: %i MHz\n",
 				  boost.clock_mhz / 2);
-		if (!nvbios_baseclock_entry(bios, &h, h.base, &base))
+		}
+
+		if (!nvbios_baseclock_entry(bios, &h, h.base, &base)) {
+			clk->base_khz = base.clock_mhz * 1000;
 			nvkm_info(subdev, "base: %i MHz\n",
 				  base.clock_mhz / 2);
+		}
 	}
 
 	clk->func = func;
diff --git a/drm/nouveau/nvkm/subdev/clk/gf100.c b/drm/nouveau/nvkm/subdev/clk/gf100.c
index 78c449b..71b7c9f 100644
--- a/drm/nouveau/nvkm/subdev/clk/gf100.c
+++ b/drm/nouveau/nvkm/subdev/clk/gf100.c
@@ -443,7 +443,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_BASECLK, "core", 2000 },
 		{ nv_clk_src_rop    , 0x04 },
 		{ nv_clk_src_mem    , 0x05, 0, "memory", 1000 },
 		{ nv_clk_src_vdec   , 0x06 },
diff --git a/drm/nouveau/nvkm/subdev/clk/gk104.c b/drm/nouveau/nvkm/subdev/clk/gk104.c
index 975c401..639234f 100644
--- a/drm/nouveau/nvkm/subdev/clk/gk104.c
+++ b/drm/nouveau/nvkm/subdev/clk/gk104.c
@@ -485,7 +485,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_BASECLK, "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 },

Comments

On 18/03/16 01:03, Karol Herbst wrote:
> 0: base clock from the vbios is max clock
> 1: boost only to boost clock from the vbios (default)
> 2: boost to max clock available
> Signed-off-by: Karol Herbst <nouveau@karolherbst.de>
> ---
>   drm/nouveau/include/nvkm/subdev/clk.h |  9 ++++++++-
>   drm/nouveau/nvkm/subdev/clk/base.c    | 26 ++++++++++++++++++++++++--
>   drm/nouveau/nvkm/subdev/clk/gf100.c   |  2 +-
>   drm/nouveau/nvkm/subdev/clk/gk104.c   |  2 +-
>   4 files changed, 34 insertions(+), 5 deletions(-)
>
> diff --git a/drm/nouveau/include/nvkm/subdev/clk.h b/drm/nouveau/include/nvkm/subdev/clk.h
> index fb54417..a292e5a 100644
> --- a/drm/nouveau/include/nvkm/subdev/clk.h
> +++ b/drm/nouveau/include/nvkm/subdev/clk.h
> @@ -67,7 +67,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_BASECLK 0x02
>   	u8 flags;
>   	const char *mname;
>   	int mdiv;
> @@ -97,6 +98,12 @@ struct nvkm_clk {
>   	int dstate; /* display adjustment (min+) */
>   
>   	bool allow_reclock;
> +#define NVKM_CLK_BOOST_NONE 0x0
> +#define NVKM_CLK_BOOST_AVG  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
> diff --git a/drm/nouveau/nvkm/subdev/clk/base.c b/drm/nouveau/nvkm/subdev/clk/base.c
> index 4928668..d575412 100644
> --- a/drm/nouveau/nvkm/subdev/clk/base.c
> +++ b/drm/nouveau/nvkm/subdev/clk/base.c
> @@ -160,6 +160,18 @@ nvkm_cstate_new(struct nvkm_clk *clk, int idx, struct nvkm_pstate *pstate)
>   		if (domain->flags & NVKM_CLK_DOM_FLAG_CORE) {
>   			u32 freq = nvkm_clk_adjust(clk, true, pstate->pstate,
>   						   domain->bios, cstepX.freq);
> +			if (domain->flags & NVKM_CLK_DOM_FLAG_BASECLK) {
> +				switch (clk->boost_mode) {
> +				case NVKM_CLK_BOOST_NONE:
> +					if (clk->base_khz
> +					    && freq > clk->base_khz)
> +						goto err;
> +				case NVKM_CLK_BOOST_AVG:
> +					if (clk->boost_khz
> +					    && freq > clk->boost_khz)
> +						goto err;
> +				}
> +			}
>   			cstate->domain[domain->name] = freq;
>   		}
>   		domain++;
> @@ -167,6 +179,9 @@ nvkm_cstate_new(struct nvkm_clk *clk, int idx, struct nvkm_pstate *pstate)
>   
>   	list_add(&cstate->head, &pstate->list);
>   	return 0;
> +err:
> +	kfree(cstate);
> +	return -EINVAL;
>   }
>   
>   /******************************************************************************
> @@ -570,14 +585,21 @@ nvkm_clk_ctor(const struct nvkm_clk_func *func, struct nvkm_device *device,
>   
>   	nvkm_subdev_ctor(&nvkm_clk, device, index, 0, subdev);
>   
> +	clk->boost_mode = nvkm_longopt(device->cfgopt, "NvBoost",
> +				       NVKM_CLK_BOOST_AVG);
>   	if (bios && !nvbios_baseclock_parse(bios, &h)) {
>   		struct nvbios_baseclk_entry base, boost;
> -		if (!nvbios_baseclock_entry(bios, &h, h.boost, &boost))
> +		if (!nvbios_baseclock_entry(bios, &h, h.boost, &boost)) {
> +			clk->boost_khz = boost.clock_mhz * 1000;
>   			nvkm_info(subdev, "boost: %i MHz\n",
>   				  boost.clock_mhz / 2);
> -		if (!nvbios_baseclock_entry(bios, &h, h.base, &base))
> +		}
> +
> +		if (!nvbios_baseclock_entry(bios, &h, h.base, &base)) {
> +			clk->base_khz = base.clock_mhz * 1000;
>   			nvkm_info(subdev, "base: %i MHz\n",
>   				  base.clock_mhz / 2);
> +		}
>   	}
>   
>   	clk->func = func;
> diff --git a/drm/nouveau/nvkm/subdev/clk/gf100.c b/drm/nouveau/nvkm/subdev/clk/gf100.c
> index 78c449b..71b7c9f 100644
> --- a/drm/nouveau/nvkm/subdev/clk/gf100.c
> +++ b/drm/nouveau/nvkm/subdev/clk/gf100.c
> @@ -443,7 +443,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_BASECLK, "core", 2000 },
>   		{ nv_clk_src_rop    , 0x04 },
>   		{ nv_clk_src_mem    , 0x05, 0, "memory", 1000 },
>   		{ nv_clk_src_vdec   , 0x06 },
> diff --git a/drm/nouveau/nvkm/subdev/clk/gk104.c b/drm/nouveau/nvkm/subdev/clk/gk104.c
> index 975c401..639234f 100644
> --- a/drm/nouveau/nvkm/subdev/clk/gk104.c
> +++ b/drm/nouveau/nvkm/subdev/clk/gk104.c
> @@ -485,7 +485,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_BASECLK, "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 },

Reviewed-by: Martin Peres <martin.peres@free.fr>