1/*
2 * Copyright 2011 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: Ben Skeggs
23 */
24
25#include "drmP.h"
26#include "nouveau_drv.h"
27#include "nouveau_bios.h"
28#include "nouveau_pm.h"
29#include "nouveau_hw.h"
30
31#define min2(a,b) ((a) < (b) ? (a) : (b))
32
33static u32
34read_pll_1(struct drm_device *dev, u32 reg)
35{
36	u32 ctrl = nv_rd32(dev, reg + 0x00);
37	int P = (ctrl & 0x00070000) >> 16;
38	int N = (ctrl & 0x0000ff00) >> 8;
39	int M = (ctrl & 0x000000ff) >> 0;
40	u32 ref = 27000, clk = 0;
41
42	if (ctrl & 0x80000000)
43		clk = ref * N / M;
44
45	return clk >> P;
46}
47
48static u32
49read_pll_2(struct drm_device *dev, u32 reg)
50{
51	u32 ctrl = nv_rd32(dev, reg + 0x00);
52	u32 coef = nv_rd32(dev, reg + 0x04);
53	int N2 = (coef & 0xff000000) >> 24;
54	int M2 = (coef & 0x00ff0000) >> 16;
55	int N1 = (coef & 0x0000ff00) >> 8;
56	int M1 = (coef & 0x000000ff) >> 0;
57	int P = (ctrl & 0x00070000) >> 16;
58	u32 ref = 27000, clk = 0;
59
60	if ((ctrl & 0x80000000) && M1) {
61		clk = ref * N1 / M1;
62		if ((ctrl & 0x40000100) == 0x40000000) {
63			if (M2)
64				clk = clk * N2 / M2;
65			else
66				clk = 0;
67		}
68	}
69
70	return clk >> P;
71}
72
73static u32
74read_clk(struct drm_device *dev, u32 src)
75{
76	switch (src) {
77	case 3:
78		return read_pll_2(dev, 0x004000);
79	case 2:
80		return read_pll_1(dev, 0x004008);
81	default:
82		break;
83	}
84
85	return 0;
86}
87
88int
89nv40_pm_clocks_get(struct drm_device *dev, struct nouveau_pm_level *perflvl)
90{
91	u32 ctrl = nv_rd32(dev, 0x00c040);
92
93	perflvl->core   = read_clk(dev, (ctrl & 0x00000003) >> 0);
94	perflvl->shader = read_clk(dev, (ctrl & 0x00000030) >> 4);
95	perflvl->memory = read_pll_2(dev, 0x4020);
96	return 0;
97}
98
99struct nv40_pm_state {
100	u32 ctrl;
101	u32 npll_ctrl;
102	u32 npll_coef;
103	u32 spll;
104	u32 mpll_ctrl;
105	u32 mpll_coef;
106};
107
108static int
109nv40_calc_pll(struct drm_device *dev, u32 reg, struct pll_lims *pll,
110	      u32 clk, int *N1, int *M1, int *N2, int *M2, int *log2P)
111{
112	struct nouveau_pll_vals coef;
113	int ret;
114
115	ret = get_pll_limits(dev, reg, pll);
116	if (ret)
117		return ret;
118
119	if (clk < pll->vco1.maxfreq)
120		pll->vco2.maxfreq = 0;
121
122	ret = nouveau_calc_pll_mnp(dev, pll, clk, &coef);
123	if (ret == 0)
124		return -ERANGE;
125
126	*N1 = coef.N1;
127	*M1 = coef.M1;
128	if (N2 && M2) {
129		if (pll->vco2.maxfreq) {
130			*N2 = coef.N2;
131			*M2 = coef.M2;
132		} else {
133			*N2 = 1;
134			*M2 = 1;
135		}
136	}
137	*log2P = coef.log2P;
138	return 0;
139}
140
141void *
142nv40_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl)
143{
144	struct nv40_pm_state *info;
145	struct pll_lims pll;
146	int N1, N2, M1, M2, log2P;
147	int ret;
148
149	info = kmalloc(sizeof(*info), GFP_KERNEL);
150	if (!info)
151		return ERR_PTR(-ENOMEM);
152
153	/* core/geometric clock */
154	ret = nv40_calc_pll(dev, 0x004000, &pll, perflvl->core,
155			    &N1, &M1, &N2, &M2, &log2P);
156	if (ret < 0)
157		goto out;
158
159	if (N2 == M2) {
160		info->npll_ctrl = 0x80000100 | (log2P << 16);
161		info->npll_coef = (N1 << 8) | M1;
162	} else {
163		info->npll_ctrl = 0xc0000000 | (log2P << 16);
164		info->npll_coef = (N2 << 24) | (M2 << 16) | (N1 << 8) | M1;
165	}
166
167	/* use the second PLL for shader/rop clock, if it differs from core */
168	if (perflvl->shader && perflvl->shader != perflvl->core) {
169		ret = nv40_calc_pll(dev, 0x004008, &pll, perflvl->shader,
170				    &N1, &M1, NULL, NULL, &log2P);
171		if (ret < 0)
172			goto out;
173
174		info->spll = 0xc0000000 | (log2P << 16) | (N1 << 8) | M1;
175		info->ctrl = 0x00000223;
176	} else {
177		info->spll = 0x00000000;
178		info->ctrl = 0x00000333;
179	}
180
181	/* memory clock */
182	if (!perflvl->memory) {
183		info->mpll_ctrl = 0x00000000;
184		goto out;
185	}
186
187	ret = nv40_calc_pll(dev, 0x004020, &pll, perflvl->memory,
188			    &N1, &M1, &N2, &M2, &log2P);
189	if (ret < 0)
190		goto out;
191
192	info->mpll_ctrl  = 0x80000000 | (log2P << 16);
193	info->mpll_ctrl |= min2(pll.log2p_bias + log2P, pll.max_log2p) << 20;
194	if (N2 == M2) {
195		info->mpll_ctrl |= 0x00000100;
196		info->mpll_coef  = (N1 << 8) | M1;
197	} else {
198		info->mpll_ctrl |= 0x40000000;
199		info->mpll_coef  = (N2 << 24) | (M2 << 16) | (N1 << 8) | M1;
200	}
201
202out:
203	if (ret < 0) {
204		kfree(info);
205		info = ERR_PTR(ret);
206	}
207	return info;
208}
209
210static bool
211nv40_pm_gr_idle(void *data)
212{
213	struct drm_device *dev = data;
214
215	if ((nv_rd32(dev, 0x400760) & 0x000000f0) >> 4 !=
216	    (nv_rd32(dev, 0x400760) & 0x0000000f))
217		return false;
218
219	if (nv_rd32(dev, 0x400700))
220		return false;
221
222	return true;
223}
224
225int
226nv40_pm_clocks_set(struct drm_device *dev, void *pre_state)
227{
228	struct drm_nouveau_private *dev_priv = dev->dev_private;
229	struct nv40_pm_state *info = pre_state;
230	unsigned long flags;
231	struct bit_entry M;
232	u32 crtc_mask = 0;
233	u8 sr1[2];
234	int i, ret = -EAGAIN;
235
236	/* determine which CRTCs are active, fetch VGA_SR1 for each */
237	for (i = 0; i < 2; i++) {
238		u32 vbl = nv_rd32(dev, 0x600808 + (i * 0x2000));
239		u32 cnt = 0;
240		do {
241			if (vbl != nv_rd32(dev, 0x600808 + (i * 0x2000))) {
242				nv_wr08(dev, 0x0c03c4 + (i * 0x2000), 0x01);
243				sr1[i] = nv_rd08(dev, 0x0c03c5 + (i * 0x2000));
244				if (!(sr1[i] & 0x20))
245					crtc_mask |= (1 << i);
246				break;
247			}
248			udelay(1);
249		} while (cnt++ < 32);
250	}
251
252	/* halt and idle engines */
253	spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
254	nv_mask(dev, 0x002500, 0x00000001, 0x00000000);
255	if (!nv_wait(dev, 0x002500, 0x00000010, 0x00000000))
256		goto resume;
257	nv_mask(dev, 0x003220, 0x00000001, 0x00000000);
258	if (!nv_wait(dev, 0x003220, 0x00000010, 0x00000000))
259		goto resume;
260	nv_mask(dev, 0x003200, 0x00000001, 0x00000000);
261	nv04_fifo_cache_pull(dev, false);
262
263	if (!nv_wait_cb(dev, nv40_pm_gr_idle, dev))
264		goto resume;
265
266	ret = 0;
267
268	/* set engine clocks */
269	nv_mask(dev, 0x00c040, 0x00000333, 0x00000000);
270	nv_wr32(dev, 0x004004, info->npll_coef);
271	nv_mask(dev, 0x004000, 0xc0070100, info->npll_ctrl);
272	nv_mask(dev, 0x004008, 0xc007ffff, info->spll);
273	mdelay(5);
274	nv_mask(dev, 0x00c040, 0x00000333, info->ctrl);
275
276	if (!info->mpll_ctrl)
277		goto resume;
278
279	/* wait for vblank start on active crtcs, disable memory access */
280	for (i = 0; i < 2; i++) {
281		if (!(crtc_mask & (1 << i)))
282			continue;
283		nv_wait(dev, 0x600808 + (i * 0x2000), 0x00010000, 0x00000000);
284		nv_wait(dev, 0x600808 + (i * 0x2000), 0x00010000, 0x00010000);
285		nv_wr08(dev, 0x0c03c4 + (i * 0x2000), 0x01);
286		nv_wr08(dev, 0x0c03c5 + (i * 0x2000), sr1[i] | 0x20);
287	}
288
289	/* prepare ram for reclocking */
290	nv_wr32(dev, 0x1002d4, 0x00000001); /* precharge */
291	nv_wr32(dev, 0x1002d0, 0x00000001); /* refresh */
292	nv_wr32(dev, 0x1002d0, 0x00000001); /* refresh */
293	nv_mask(dev, 0x100210, 0x80000000, 0x00000000); /* no auto refresh */
294	nv_wr32(dev, 0x1002dc, 0x00000001); /* enable self-refresh */
295
296	/* change the PLL of each memory partition */
297	nv_mask(dev, 0x00c040, 0x0000c000, 0x00000000);
298	switch (dev_priv->chipset) {
299	case 0x40:
300	case 0x45:
301	case 0x41:
302	case 0x42:
303	case 0x47:
304		nv_mask(dev, 0x004044, 0xc0771100, info->mpll_ctrl);
305		nv_mask(dev, 0x00402c, 0xc0771100, info->mpll_ctrl);
306		nv_wr32(dev, 0x004048, info->mpll_coef);
307		nv_wr32(dev, 0x004030, info->mpll_coef);
308	case 0x43:
309	case 0x49:
310	case 0x4b:
311		nv_mask(dev, 0x004038, 0xc0771100, info->mpll_ctrl);
312		nv_wr32(dev, 0x00403c, info->mpll_coef);
313	default:
314		nv_mask(dev, 0x004020, 0xc0771100, info->mpll_ctrl);
315		nv_wr32(dev, 0x004024, info->mpll_coef);
316		break;
317	}
318	udelay(100);
319	nv_mask(dev, 0x00c040, 0x0000c000, 0x0000c000);
320
321	/* re-enable normal operation of memory controller */
322	nv_wr32(dev, 0x1002dc, 0x00000000);
323	nv_mask(dev, 0x100210, 0x80000000, 0x80000000);
324	udelay(100);
325
326	/* execute memory reset script from vbios */
327	if (!bit_table(dev, 'M', &M))
328		nouveau_bios_init_exec(dev, ROM16(M.data[0]));
329
330	/* make sure we're in vblank (hopefully the same one as before), and
331	 * then re-enable crtc memory access
332	 */
333	for (i = 0; i < 2; i++) {
334		if (!(crtc_mask & (1 << i)))
335			continue;
336		nv_wait(dev, 0x600808 + (i * 0x2000), 0x00010000, 0x00010000);
337		nv_wr08(dev, 0x0c03c4 + (i * 0x2000), 0x01);
338		nv_wr08(dev, 0x0c03c5 + (i * 0x2000), sr1[i]);
339	}
340
341	/* resume engines */
342resume:
343	nv_wr32(dev, 0x003250, 0x00000001);
344	nv_mask(dev, 0x003220, 0x00000001, 0x00000001);
345	nv_wr32(dev, 0x003200, 0x00000001);
346	nv_wr32(dev, 0x002500, 0x00000001);
347	spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
348
349	kfree(info);
350	return ret;
351}
352
353int
354nv40_pm_pwm_get(struct drm_device *dev, int line, u32 *divs, u32 *duty)
355{
356	if (line == 2) {
357		u32 reg = nv_rd32(dev, 0x0010f0);
358		if (reg & 0x80000000) {
359			*duty = (reg & 0x7fff0000) >> 16;
360			*divs = (reg & 0x00007fff);
361			return 0;
362		}
363	} else
364	if (line == 9) {
365		u32 reg = nv_rd32(dev, 0x0015f4);
366		if (reg & 0x80000000) {
367			*divs = nv_rd32(dev, 0x0015f8);
368			*duty = (reg & 0x7fffffff);
369			return 0;
370		}
371	} else {
372		NV_ERROR(dev, "unknown pwm ctrl for gpio %d\n", line);
373		return -ENODEV;
374	}
375
376	return -EINVAL;
377}
378
379int
380nv40_pm_pwm_set(struct drm_device *dev, int line, u32 divs, u32 duty)
381{
382	if (line == 2) {
383		nv_wr32(dev, 0x0010f0, 0x80000000 | (duty << 16) | divs);
384	} else
385	if (line == 9) {
386		nv_wr32(dev, 0x0015f8, divs);
387		nv_wr32(dev, 0x0015f4, duty | 0x80000000);
388	} else {
389		NV_ERROR(dev, "unknown pwm ctrl for gpio %d\n", line);
390		return -ENODEV;
391	}
392
393	return 0;
394}
395