drm/nv04-nv30/pm: port to newer interfaces

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
diff --git a/drivers/gpu/drm/nouveau/nouveau_pm.h b/drivers/gpu/drm/nouveau/nouveau_pm.h
index 06df411..663088d 100644
--- a/drivers/gpu/drm/nouveau/nouveau_pm.h
+++ b/drivers/gpu/drm/nouveau/nouveau_pm.h
@@ -47,10 +47,9 @@
 void nouveau_mem_timing_fini(struct drm_device *);
 
 /* nv04_pm.c */
-int nv04_pm_clock_get(struct drm_device *, u32 id);
-void *nv04_pm_clock_pre(struct drm_device *, struct nouveau_pm_level *,
-			u32 id, int khz);
-void nv04_pm_clock_set(struct drm_device *, void *);
+int nv04_pm_clocks_get(struct drm_device *, struct nouveau_pm_level *);
+void *nv04_pm_clocks_pre(struct drm_device *, struct nouveau_pm_level *);
+int nv04_pm_clocks_set(struct drm_device *, void *);
 
 /* nv40_pm.c */
 int nv40_pm_clocks_get(struct drm_device *, struct nouveau_pm_level *);
diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c
index 6b4aaec..3e3798f 100644
--- a/drivers/gpu/drm/nouveau/nouveau_state.c
+++ b/drivers/gpu/drm/nouveau/nouveau_state.c
@@ -87,9 +87,9 @@
 		engine->gpio.get		= NULL;
 		engine->gpio.set		= NULL;
 		engine->gpio.irq_enable		= NULL;
-		engine->pm.clock_get		= nv04_pm_clock_get;
-		engine->pm.clock_pre		= nv04_pm_clock_pre;
-		engine->pm.clock_set		= nv04_pm_clock_set;
+		engine->pm.clocks_get		= nv04_pm_clocks_get;
+		engine->pm.clocks_pre		= nv04_pm_clocks_pre;
+		engine->pm.clocks_set		= nv04_pm_clocks_set;
 		engine->vram.init		= nouveau_mem_detect;
 		engine->vram.takedown		= nouveau_stub_takedown;
 		engine->vram.flags_valid	= nouveau_mem_flags_valid;
@@ -136,9 +136,9 @@
 		engine->gpio.get		= nv10_gpio_get;
 		engine->gpio.set		= nv10_gpio_set;
 		engine->gpio.irq_enable		= NULL;
-		engine->pm.clock_get		= nv04_pm_clock_get;
-		engine->pm.clock_pre		= nv04_pm_clock_pre;
-		engine->pm.clock_set		= nv04_pm_clock_set;
+		engine->pm.clocks_get		= nv04_pm_clocks_get;
+		engine->pm.clocks_pre		= nv04_pm_clocks_pre;
+		engine->pm.clocks_set		= nv04_pm_clocks_set;
 		engine->vram.init		= nouveau_mem_detect;
 		engine->vram.takedown		= nouveau_stub_takedown;
 		engine->vram.flags_valid	= nouveau_mem_flags_valid;
@@ -185,9 +185,9 @@
 		engine->gpio.get		= nv10_gpio_get;
 		engine->gpio.set		= nv10_gpio_set;
 		engine->gpio.irq_enable		= NULL;
-		engine->pm.clock_get		= nv04_pm_clock_get;
-		engine->pm.clock_pre		= nv04_pm_clock_pre;
-		engine->pm.clock_set		= nv04_pm_clock_set;
+		engine->pm.clocks_get		= nv04_pm_clocks_get;
+		engine->pm.clocks_pre		= nv04_pm_clocks_pre;
+		engine->pm.clocks_set		= nv04_pm_clocks_set;
 		engine->vram.init		= nouveau_mem_detect;
 		engine->vram.takedown		= nouveau_stub_takedown;
 		engine->vram.flags_valid	= nouveau_mem_flags_valid;
@@ -234,9 +234,9 @@
 		engine->gpio.get		= nv10_gpio_get;
 		engine->gpio.set		= nv10_gpio_set;
 		engine->gpio.irq_enable		= NULL;
-		engine->pm.clock_get		= nv04_pm_clock_get;
-		engine->pm.clock_pre		= nv04_pm_clock_pre;
-		engine->pm.clock_set		= nv04_pm_clock_set;
+		engine->pm.clocks_get		= nv04_pm_clocks_get;
+		engine->pm.clocks_pre		= nv04_pm_clocks_pre;
+		engine->pm.clocks_set		= nv04_pm_clocks_set;
 		engine->pm.voltage_get		= nouveau_voltage_gpio_get;
 		engine->pm.voltage_set		= nouveau_voltage_gpio_set;
 		engine->vram.init		= nouveau_mem_detect;
diff --git a/drivers/gpu/drm/nouveau/nv04_pm.c b/drivers/gpu/drm/nouveau/nv04_pm.c
index 9ae92a8..6e75899 100644
--- a/drivers/gpu/drm/nouveau/nv04_pm.c
+++ b/drivers/gpu/drm/nouveau/nv04_pm.c
@@ -27,68 +27,111 @@
 #include "nouveau_hw.h"
 #include "nouveau_pm.h"
 
-struct nv04_pm_state {
+int
+nv04_pm_clocks_get(struct drm_device *dev, struct nouveau_pm_level *perflvl)
+{
+	int ret;
+
+	ret = nouveau_hw_get_clock(dev, PLL_CORE);
+	if (ret < 0)
+		return ret;
+	perflvl->core = ret;
+
+	ret = nouveau_hw_get_clock(dev, PLL_MEMORY);
+	if (ret < 0)
+		return ret;
+	perflvl->memory = ret;
+
+	return 0;
+}
+
+struct nv04_pm_clock {
 	struct pll_lims pll;
 	struct nouveau_pll_vals calc;
 };
 
-int
-nv04_pm_clock_get(struct drm_device *dev, u32 id)
+struct nv04_pm_state {
+	struct nv04_pm_clock core;
+	struct nv04_pm_clock memory;
+};
+
+static int
+calc_pll(struct drm_device *dev, u32 id, int khz, struct nv04_pm_clock *clk)
 {
-	return nouveau_hw_get_clock(dev, id);
+	int ret;
+
+	ret = get_pll_limits(dev, id, &clk->pll);
+	if (ret)
+		return ret;
+
+	ret = nouveau_calc_pll_mnp(dev, &clk->pll, khz, &clk->calc);
+	if (!ret)
+		return -EINVAL;
+
+	return 0;
 }
 
 void *
-nv04_pm_clock_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl,
-		  u32 id, int khz)
+nv04_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl)
 {
-	struct nv04_pm_state *state;
+	struct nv04_pm_state *info;
 	int ret;
 
-	state = kzalloc(sizeof(*state), GFP_KERNEL);
-	if (!state)
+	info = kzalloc(sizeof(*info), GFP_KERNEL);
+	if (!info)
 		return ERR_PTR(-ENOMEM);
 
-	ret = get_pll_limits(dev, id, &state->pll);
-	if (ret) {
-		kfree(state);
-		return (ret == -ENOENT) ? NULL : ERR_PTR(ret);
+	ret = calc_pll(dev, PLL_CORE, perflvl->core, &info->core);
+	if (ret)
+		goto error;
+
+	if (perflvl->memory) {
+		ret = calc_pll(dev, PLL_MEMORY, perflvl->memory, &info->memory);
+		if (ret)
+			goto error;
 	}
 
-	ret = nouveau_calc_pll_mnp(dev, &state->pll, khz, &state->calc);
-	if (!ret) {
-		kfree(state);
-		return ERR_PTR(-EINVAL);
-	}
-
-	return state;
+	return info;
+error:
+	kfree(info);
+	return ERR_PTR(ret);
 }
 
-void
-nv04_pm_clock_set(struct drm_device *dev, void *pre_state)
+static void
+prog_pll(struct drm_device *dev, struct nv04_pm_clock *clk)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer;
-	struct nv04_pm_state *state = pre_state;
-	u32 reg = state->pll.reg;
+	u32 reg = clk->pll.reg;
 
 	/* thank the insane nouveau_hw_setpll() interface for this */
 	if (dev_priv->card_type >= NV_40)
 		reg += 4;
 
-	nouveau_hw_setpll(dev, reg, &state->calc);
-
-	if (dev_priv->card_type < NV_30 && reg == NV_PRAMDAC_MPLL_COEFF) {
-		if (dev_priv->card_type == NV_20)
-			nv_mask(dev, 0x1002c4, 0, 1 << 20);
-
-		/* Reset the DLLs */
-		nv_mask(dev, 0x1002c0, 0, 1 << 8);
-	}
-
-	if (reg == NV_PRAMDAC_NVPLL_COEFF)
-		ptimer->init(dev);
-
-	kfree(state);
+	nouveau_hw_setpll(dev, reg, &clk->calc);
 }
 
+int
+nv04_pm_clocks_set(struct drm_device *dev, void *pre_state)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer;
+	struct nv04_pm_state *state = pre_state;
+
+	prog_pll(dev, &state->core);
+
+	if (state->memory.pll.reg) {
+		prog_pll(dev, &state->memory);
+		if (dev_priv->card_type < NV_30) {
+			if (dev_priv->card_type == NV_20)
+				nv_mask(dev, 0x1002c4, 0, 1 << 20);
+
+			/* Reset the DLLs */
+			nv_mask(dev, 0x1002c0, 0, 1 << 8);
+		}
+	}
+
+	ptimer->init(dev);
+
+	kfree(state);
+	return 0;
+}