diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau/nv04_pm.c')
-rw-r--r-- | drivers/gpu/drm/nouveau/nv04_pm.c | 107 |
1 files changed, 30 insertions, 77 deletions
diff --git a/drivers/gpu/drm/nouveau/nv04_pm.c b/drivers/gpu/drm/nouveau/nv04_pm.c index 6e75899..eb1c70d 100644 --- a/drivers/gpu/drm/nouveau/nv04_pm.c +++ b/drivers/gpu/drm/nouveau/nv04_pm.c @@ -27,111 +27,64 @@ #include "nouveau_hw.h" #include "nouveau_pm.h" -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 nv04_pm_state { struct pll_lims pll; struct nouveau_pll_vals calc; }; -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) +int +nv04_pm_clock_get(struct drm_device *dev, u32 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; + return nouveau_hw_get_clock(dev, id); } void * -nv04_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl) +nv04_pm_clock_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl, + u32 id, int khz) { - struct nv04_pm_state *info; + struct nv04_pm_state *state; int ret; - info = kzalloc(sizeof(*info), GFP_KERNEL); - if (!info) + state = kzalloc(sizeof(*state), GFP_KERNEL); + if (!state) return ERR_PTR(-ENOMEM); - ret = calc_pll(dev, PLL_CORE, perflvl->core, &info->core); - if (ret) - goto error; + ret = get_pll_limits(dev, id, &state->pll); + if (ret) { + kfree(state); + return (ret == -ENOENT) ? NULL : ERR_PTR(ret); + } - 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 info; -error: - kfree(info); - return ERR_PTR(ret); + return state; } -static void -prog_pll(struct drm_device *dev, struct nv04_pm_clock *clk) +void +nv04_pm_clock_set(struct drm_device *dev, void *pre_state) { struct drm_nouveau_private *dev_priv = dev->dev_private; - u32 reg = clk->pll.reg; + struct nv04_pm_state *state = pre_state; + u32 reg = state->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, &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; + nouveau_hw_setpll(dev, reg, &state->calc); - prog_pll(dev, &state->core); + 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); - 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); - } + /* Reset the DLLs */ + nv_mask(dev, 0x1002c0, 0, 1 << 8); } - ptimer->init(dev); - kfree(state); - return 0; } + |