diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2011-10-26 20:24:12 -0400 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2011-12-21 04:01:24 -0500 |
commit | 36f1317ed05f76bfafb442f70575cdaed6da2d8c (patch) | |
tree | 39e750d0ae71281f1fdff8632acf71a4463c5ccd /drivers/gpu/drm/nouveau/nv04_pm.c | |
parent | f3fbaf34e2b1459eab248c5f0180928e7861120b (diff) |
drm/nv04-nv30/pm: port to newer interfaces
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau/nv04_pm.c')
-rw-r--r-- | drivers/gpu/drm/nouveau/nv04_pm.c | 109 |
1 files changed, 76 insertions, 33 deletions
diff --git a/drivers/gpu/drm/nouveau/nv04_pm.c b/drivers/gpu/drm/nouveau/nv04_pm.c index 9ae92a87b8cc..6e7589918fa9 100644 --- a/drivers/gpu/drm/nouveau/nv04_pm.c +++ b/drivers/gpu/drm/nouveau/nv04_pm.c | |||
@@ -27,68 +27,111 @@ | |||
27 | #include "nouveau_hw.h" | 27 | #include "nouveau_hw.h" |
28 | #include "nouveau_pm.h" | 28 | #include "nouveau_pm.h" |
29 | 29 | ||
30 | struct nv04_pm_state { | 30 | int |
31 | nv04_pm_clocks_get(struct drm_device *dev, struct nouveau_pm_level *perflvl) | ||
32 | { | ||
33 | int ret; | ||
34 | |||
35 | ret = nouveau_hw_get_clock(dev, PLL_CORE); | ||
36 | if (ret < 0) | ||
37 | return ret; | ||
38 | perflvl->core = ret; | ||
39 | |||
40 | ret = nouveau_hw_get_clock(dev, PLL_MEMORY); | ||
41 | if (ret < 0) | ||
42 | return ret; | ||
43 | perflvl->memory = ret; | ||
44 | |||
45 | return 0; | ||
46 | } | ||
47 | |||
48 | struct nv04_pm_clock { | ||
31 | struct pll_lims pll; | 49 | struct pll_lims pll; |
32 | struct nouveau_pll_vals calc; | 50 | struct nouveau_pll_vals calc; |
33 | }; | 51 | }; |
34 | 52 | ||
35 | int | 53 | struct nv04_pm_state { |
36 | nv04_pm_clock_get(struct drm_device *dev, u32 id) | 54 | struct nv04_pm_clock core; |
55 | struct nv04_pm_clock memory; | ||
56 | }; | ||
57 | |||
58 | static int | ||
59 | calc_pll(struct drm_device *dev, u32 id, int khz, struct nv04_pm_clock *clk) | ||
37 | { | 60 | { |
38 | return nouveau_hw_get_clock(dev, id); | 61 | int ret; |
62 | |||
63 | ret = get_pll_limits(dev, id, &clk->pll); | ||
64 | if (ret) | ||
65 | return ret; | ||
66 | |||
67 | ret = nouveau_calc_pll_mnp(dev, &clk->pll, khz, &clk->calc); | ||
68 | if (!ret) | ||
69 | return -EINVAL; | ||
70 | |||
71 | return 0; | ||
39 | } | 72 | } |
40 | 73 | ||
41 | void * | 74 | void * |
42 | nv04_pm_clock_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl, | 75 | nv04_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl) |
43 | u32 id, int khz) | ||
44 | { | 76 | { |
45 | struct nv04_pm_state *state; | 77 | struct nv04_pm_state *info; |
46 | int ret; | 78 | int ret; |
47 | 79 | ||
48 | state = kzalloc(sizeof(*state), GFP_KERNEL); | 80 | info = kzalloc(sizeof(*info), GFP_KERNEL); |
49 | if (!state) | 81 | if (!info) |
50 | return ERR_PTR(-ENOMEM); | 82 | return ERR_PTR(-ENOMEM); |
51 | 83 | ||
52 | ret = get_pll_limits(dev, id, &state->pll); | 84 | ret = calc_pll(dev, PLL_CORE, perflvl->core, &info->core); |
53 | if (ret) { | 85 | if (ret) |
54 | kfree(state); | 86 | goto error; |
55 | return (ret == -ENOENT) ? NULL : ERR_PTR(ret); | ||
56 | } | ||
57 | 87 | ||
58 | ret = nouveau_calc_pll_mnp(dev, &state->pll, khz, &state->calc); | 88 | if (perflvl->memory) { |
59 | if (!ret) { | 89 | ret = calc_pll(dev, PLL_MEMORY, perflvl->memory, &info->memory); |
60 | kfree(state); | 90 | if (ret) |
61 | return ERR_PTR(-EINVAL); | 91 | goto error; |
62 | } | 92 | } |
63 | 93 | ||
64 | return state; | 94 | return info; |
95 | error: | ||
96 | kfree(info); | ||
97 | return ERR_PTR(ret); | ||
65 | } | 98 | } |
66 | 99 | ||
67 | void | 100 | static void |
68 | nv04_pm_clock_set(struct drm_device *dev, void *pre_state) | 101 | prog_pll(struct drm_device *dev, struct nv04_pm_clock *clk) |
69 | { | 102 | { |
70 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 103 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
71 | struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer; | 104 | u32 reg = clk->pll.reg; |
72 | struct nv04_pm_state *state = pre_state; | ||
73 | u32 reg = state->pll.reg; | ||
74 | 105 | ||
75 | /* thank the insane nouveau_hw_setpll() interface for this */ | 106 | /* thank the insane nouveau_hw_setpll() interface for this */ |
76 | if (dev_priv->card_type >= NV_40) | 107 | if (dev_priv->card_type >= NV_40) |
77 | reg += 4; | 108 | reg += 4; |
78 | 109 | ||
79 | nouveau_hw_setpll(dev, reg, &state->calc); | 110 | nouveau_hw_setpll(dev, reg, &clk->calc); |
111 | } | ||
112 | |||
113 | int | ||
114 | nv04_pm_clocks_set(struct drm_device *dev, void *pre_state) | ||
115 | { | ||
116 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
117 | struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer; | ||
118 | struct nv04_pm_state *state = pre_state; | ||
119 | |||
120 | prog_pll(dev, &state->core); | ||
80 | 121 | ||
81 | if (dev_priv->card_type < NV_30 && reg == NV_PRAMDAC_MPLL_COEFF) { | 122 | if (state->memory.pll.reg) { |
82 | if (dev_priv->card_type == NV_20) | 123 | prog_pll(dev, &state->memory); |
83 | nv_mask(dev, 0x1002c4, 0, 1 << 20); | 124 | if (dev_priv->card_type < NV_30) { |
125 | if (dev_priv->card_type == NV_20) | ||
126 | nv_mask(dev, 0x1002c4, 0, 1 << 20); | ||
84 | 127 | ||
85 | /* Reset the DLLs */ | 128 | /* Reset the DLLs */ |
86 | nv_mask(dev, 0x1002c0, 0, 1 << 8); | 129 | nv_mask(dev, 0x1002c0, 0, 1 << 8); |
130 | } | ||
87 | } | 131 | } |
88 | 132 | ||
89 | if (reg == NV_PRAMDAC_NVPLL_COEFF) | 133 | ptimer->init(dev); |
90 | ptimer->init(dev); | ||
91 | 134 | ||
92 | kfree(state); | 135 | kfree(state); |
136 | return 0; | ||
93 | } | 137 | } |
94 | |||