1254885Sdumbbell/*
2254885Sdumbbell * Copyright 2008 Advanced Micro Devices, Inc.
3254885Sdumbbell * Copyright 2008 Red Hat Inc.
4254885Sdumbbell * Copyright 2009 Jerome Glisse.
5254885Sdumbbell *
6254885Sdumbbell * Permission is hereby granted, free of charge, to any person obtaining a
7254885Sdumbbell * copy of this software and associated documentation files (the "Software"),
8254885Sdumbbell * to deal in the Software without restriction, including without limitation
9254885Sdumbbell * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10254885Sdumbbell * and/or sell copies of the Software, and to permit persons to whom the
11254885Sdumbbell * Software is furnished to do so, subject to the following conditions:
12254885Sdumbbell *
13254885Sdumbbell * The above copyright notice and this permission notice shall be included in
14254885Sdumbbell * all copies or substantial portions of the Software.
15254885Sdumbbell *
16254885Sdumbbell * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17254885Sdumbbell * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18254885Sdumbbell * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19254885Sdumbbell * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
20254885Sdumbbell * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21254885Sdumbbell * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22254885Sdumbbell * OTHER DEALINGS IN THE SOFTWARE.
23254885Sdumbbell *
24254885Sdumbbell * Authors: Dave Airlie
25254885Sdumbbell *          Alex Deucher
26254885Sdumbbell *          Jerome Glisse
27254885Sdumbbell */
28254885Sdumbbell
29254885Sdumbbell#include <sys/cdefs.h>
30254885Sdumbbell__FBSDID("$FreeBSD$");
31254885Sdumbbell
32254885Sdumbbell#include <dev/drm2/drmP.h>
33254885Sdumbbell#include <dev/drm2/radeon/radeon_drm.h>
34254885Sdumbbell#include "radeon_reg.h"
35254885Sdumbbell#include "radeon.h"
36254885Sdumbbell#include "radeon_asic.h"
37254885Sdumbbell#include "atom.h"
38254885Sdumbbell
39254885Sdumbbell/* 10 khz */
40254885Sdumbbelluint32_t radeon_legacy_get_engine_clock(struct radeon_device *rdev)
41254885Sdumbbell{
42254885Sdumbbell	struct radeon_pll *spll = &rdev->clock.spll;
43254885Sdumbbell	uint32_t fb_div, ref_div, post_div, sclk;
44254885Sdumbbell
45254885Sdumbbell	fb_div = RREG32_PLL(RADEON_M_SPLL_REF_FB_DIV);
46254885Sdumbbell	fb_div = (fb_div >> RADEON_SPLL_FB_DIV_SHIFT) & RADEON_SPLL_FB_DIV_MASK;
47254885Sdumbbell	fb_div <<= 1;
48254885Sdumbbell	fb_div *= spll->reference_freq;
49254885Sdumbbell
50254885Sdumbbell	ref_div =
51254885Sdumbbell	    RREG32_PLL(RADEON_M_SPLL_REF_FB_DIV) & RADEON_M_SPLL_REF_DIV_MASK;
52254885Sdumbbell
53254885Sdumbbell	if (ref_div == 0)
54254885Sdumbbell		return 0;
55254885Sdumbbell
56254885Sdumbbell	sclk = fb_div / ref_div;
57254885Sdumbbell
58254885Sdumbbell	post_div = RREG32_PLL(RADEON_SCLK_CNTL) & RADEON_SCLK_SRC_SEL_MASK;
59254885Sdumbbell	if (post_div == 2)
60254885Sdumbbell		sclk >>= 1;
61254885Sdumbbell	else if (post_div == 3)
62254885Sdumbbell		sclk >>= 2;
63254885Sdumbbell	else if (post_div == 4)
64254885Sdumbbell		sclk >>= 3;
65254885Sdumbbell
66254885Sdumbbell	return sclk;
67254885Sdumbbell}
68254885Sdumbbell
69254885Sdumbbell/* 10 khz */
70254885Sdumbbelluint32_t radeon_legacy_get_memory_clock(struct radeon_device *rdev)
71254885Sdumbbell{
72254885Sdumbbell	struct radeon_pll *mpll = &rdev->clock.mpll;
73254885Sdumbbell	uint32_t fb_div, ref_div, post_div, mclk;
74254885Sdumbbell
75254885Sdumbbell	fb_div = RREG32_PLL(RADEON_M_SPLL_REF_FB_DIV);
76254885Sdumbbell	fb_div = (fb_div >> RADEON_MPLL_FB_DIV_SHIFT) & RADEON_MPLL_FB_DIV_MASK;
77254885Sdumbbell	fb_div <<= 1;
78254885Sdumbbell	fb_div *= mpll->reference_freq;
79254885Sdumbbell
80254885Sdumbbell	ref_div =
81254885Sdumbbell	    RREG32_PLL(RADEON_M_SPLL_REF_FB_DIV) & RADEON_M_SPLL_REF_DIV_MASK;
82254885Sdumbbell
83254885Sdumbbell	if (ref_div == 0)
84254885Sdumbbell		return 0;
85254885Sdumbbell
86254885Sdumbbell	mclk = fb_div / ref_div;
87254885Sdumbbell
88254885Sdumbbell	post_div = RREG32_PLL(RADEON_MCLK_CNTL) & 0x7;
89254885Sdumbbell	if (post_div == 2)
90254885Sdumbbell		mclk >>= 1;
91254885Sdumbbell	else if (post_div == 3)
92254885Sdumbbell		mclk >>= 2;
93254885Sdumbbell	else if (post_div == 4)
94254885Sdumbbell		mclk >>= 3;
95254885Sdumbbell
96254885Sdumbbell	return mclk;
97254885Sdumbbell}
98254885Sdumbbell
99254885Sdumbbell#ifdef CONFIG_OF
100254885Sdumbbell/*
101254885Sdumbbell * Read XTAL (ref clock), SCLK and MCLK from Open Firmware device
102254885Sdumbbell * tree. Hopefully, ATI OF driver is kind enough to fill these
103254885Sdumbbell */
104254885Sdumbbellstatic bool radeon_read_clocks_OF(struct drm_device *dev)
105254885Sdumbbell{
106254885Sdumbbell	struct radeon_device *rdev = dev->dev_private;
107254885Sdumbbell	struct device_node *dp = rdev->pdev->dev.of_node;
108254885Sdumbbell	const u32 *val;
109254885Sdumbbell	struct radeon_pll *p1pll = &rdev->clock.p1pll;
110254885Sdumbbell	struct radeon_pll *p2pll = &rdev->clock.p2pll;
111254885Sdumbbell	struct radeon_pll *spll = &rdev->clock.spll;
112254885Sdumbbell	struct radeon_pll *mpll = &rdev->clock.mpll;
113254885Sdumbbell
114254885Sdumbbell	if (dp == NULL)
115254885Sdumbbell		return false;
116254885Sdumbbell	val = of_get_property(dp, "ATY,RefCLK", NULL);
117254885Sdumbbell	if (!val || !*val) {
118254885Sdumbbell		printk(KERN_WARNING "radeonfb: No ATY,RefCLK property !\n");
119254885Sdumbbell		return false;
120254885Sdumbbell	}
121254885Sdumbbell	p1pll->reference_freq = p2pll->reference_freq = (*val) / 10;
122254885Sdumbbell	p1pll->reference_div = RREG32_PLL(RADEON_PPLL_REF_DIV) & 0x3ff;
123254885Sdumbbell	if (p1pll->reference_div < 2)
124254885Sdumbbell		p1pll->reference_div = 12;
125254885Sdumbbell	p2pll->reference_div = p1pll->reference_div;
126254885Sdumbbell
127254885Sdumbbell	/* These aren't in the device-tree */
128254885Sdumbbell	if (rdev->family >= CHIP_R420) {
129254885Sdumbbell		p1pll->pll_in_min = 100;
130254885Sdumbbell		p1pll->pll_in_max = 1350;
131254885Sdumbbell		p1pll->pll_out_min = 20000;
132254885Sdumbbell		p1pll->pll_out_max = 50000;
133254885Sdumbbell		p2pll->pll_in_min = 100;
134254885Sdumbbell		p2pll->pll_in_max = 1350;
135254885Sdumbbell		p2pll->pll_out_min = 20000;
136254885Sdumbbell		p2pll->pll_out_max = 50000;
137254885Sdumbbell	} else {
138254885Sdumbbell		p1pll->pll_in_min = 40;
139254885Sdumbbell		p1pll->pll_in_max = 500;
140254885Sdumbbell		p1pll->pll_out_min = 12500;
141254885Sdumbbell		p1pll->pll_out_max = 35000;
142254885Sdumbbell		p2pll->pll_in_min = 40;
143254885Sdumbbell		p2pll->pll_in_max = 500;
144254885Sdumbbell		p2pll->pll_out_min = 12500;
145254885Sdumbbell		p2pll->pll_out_max = 35000;
146254885Sdumbbell	}
147254885Sdumbbell	/* not sure what the max should be in all cases */
148254885Sdumbbell	rdev->clock.max_pixel_clock = 35000;
149254885Sdumbbell
150254885Sdumbbell	spll->reference_freq = mpll->reference_freq = p1pll->reference_freq;
151254885Sdumbbell	spll->reference_div = mpll->reference_div =
152254885Sdumbbell		RREG32_PLL(RADEON_M_SPLL_REF_FB_DIV) &
153254885Sdumbbell			    RADEON_M_SPLL_REF_DIV_MASK;
154254885Sdumbbell
155254885Sdumbbell	val = of_get_property(dp, "ATY,SCLK", NULL);
156254885Sdumbbell	if (val && *val)
157254885Sdumbbell		rdev->clock.default_sclk = (*val) / 10;
158254885Sdumbbell	else
159254885Sdumbbell		rdev->clock.default_sclk =
160254885Sdumbbell			radeon_legacy_get_engine_clock(rdev);
161254885Sdumbbell
162254885Sdumbbell	val = of_get_property(dp, "ATY,MCLK", NULL);
163254885Sdumbbell	if (val && *val)
164254885Sdumbbell		rdev->clock.default_mclk = (*val) / 10;
165254885Sdumbbell	else
166254885Sdumbbell		rdev->clock.default_mclk =
167254885Sdumbbell			radeon_legacy_get_memory_clock(rdev);
168254885Sdumbbell
169254885Sdumbbell	DRM_INFO("Using device-tree clock info\n");
170254885Sdumbbell
171254885Sdumbbell	return true;
172254885Sdumbbell}
173254885Sdumbbell#else
174254885Sdumbbellstatic bool radeon_read_clocks_OF(struct drm_device *dev)
175254885Sdumbbell{
176254885Sdumbbell	return false;
177254885Sdumbbell}
178254885Sdumbbell#endif /* CONFIG_OF */
179254885Sdumbbell
180254885Sdumbbellvoid radeon_get_clock_info(struct drm_device *dev)
181254885Sdumbbell{
182254885Sdumbbell	struct radeon_device *rdev = dev->dev_private;
183254885Sdumbbell	struct radeon_pll *p1pll = &rdev->clock.p1pll;
184254885Sdumbbell	struct radeon_pll *p2pll = &rdev->clock.p2pll;
185254885Sdumbbell	struct radeon_pll *dcpll = &rdev->clock.dcpll;
186254885Sdumbbell	struct radeon_pll *spll = &rdev->clock.spll;
187254885Sdumbbell	struct radeon_pll *mpll = &rdev->clock.mpll;
188254885Sdumbbell	int ret;
189254885Sdumbbell
190254885Sdumbbell	if (rdev->is_atom_bios)
191254885Sdumbbell		ret = radeon_atom_get_clock_info(dev);
192254885Sdumbbell	else
193254885Sdumbbell		ret = radeon_combios_get_clock_info(dev);
194254885Sdumbbell	if (!ret)
195254885Sdumbbell		ret = radeon_read_clocks_OF(dev);
196254885Sdumbbell
197254885Sdumbbell	if (ret) {
198254885Sdumbbell		if (p1pll->reference_div < 2) {
199254885Sdumbbell			if (!ASIC_IS_AVIVO(rdev)) {
200254885Sdumbbell				u32 tmp = RREG32_PLL(RADEON_PPLL_REF_DIV);
201254885Sdumbbell				if (ASIC_IS_R300(rdev))
202254885Sdumbbell					p1pll->reference_div =
203254885Sdumbbell						(tmp & R300_PPLL_REF_DIV_ACC_MASK) >> R300_PPLL_REF_DIV_ACC_SHIFT;
204254885Sdumbbell				else
205254885Sdumbbell					p1pll->reference_div = tmp & RADEON_PPLL_REF_DIV_MASK;
206254885Sdumbbell				if (p1pll->reference_div < 2)
207254885Sdumbbell					p1pll->reference_div = 12;
208254885Sdumbbell			} else
209254885Sdumbbell				p1pll->reference_div = 12;
210254885Sdumbbell		}
211254885Sdumbbell		if (p2pll->reference_div < 2)
212254885Sdumbbell			p2pll->reference_div = 12;
213254885Sdumbbell		if (rdev->family < CHIP_RS600) {
214254885Sdumbbell			if (spll->reference_div < 2)
215254885Sdumbbell				spll->reference_div =
216254885Sdumbbell					RREG32_PLL(RADEON_M_SPLL_REF_FB_DIV) &
217254885Sdumbbell					RADEON_M_SPLL_REF_DIV_MASK;
218254885Sdumbbell		}
219254885Sdumbbell		if (mpll->reference_div < 2)
220254885Sdumbbell			mpll->reference_div = spll->reference_div;
221254885Sdumbbell	} else {
222254885Sdumbbell		if (ASIC_IS_AVIVO(rdev)) {
223254885Sdumbbell			/* TODO FALLBACK */
224254885Sdumbbell		} else {
225254885Sdumbbell			DRM_INFO("Using generic clock info\n");
226254885Sdumbbell
227254885Sdumbbell			/* may need to be per card */
228254885Sdumbbell			rdev->clock.max_pixel_clock = 35000;
229254885Sdumbbell
230254885Sdumbbell			if (rdev->flags & RADEON_IS_IGP) {
231254885Sdumbbell				p1pll->reference_freq = 1432;
232254885Sdumbbell				p2pll->reference_freq = 1432;
233254885Sdumbbell				spll->reference_freq = 1432;
234254885Sdumbbell				mpll->reference_freq = 1432;
235254885Sdumbbell			} else {
236254885Sdumbbell				p1pll->reference_freq = 2700;
237254885Sdumbbell				p2pll->reference_freq = 2700;
238254885Sdumbbell				spll->reference_freq = 2700;
239254885Sdumbbell				mpll->reference_freq = 2700;
240254885Sdumbbell			}
241254885Sdumbbell			p1pll->reference_div =
242254885Sdumbbell			    RREG32_PLL(RADEON_PPLL_REF_DIV) & 0x3ff;
243254885Sdumbbell			if (p1pll->reference_div < 2)
244254885Sdumbbell				p1pll->reference_div = 12;
245254885Sdumbbell			p2pll->reference_div = p1pll->reference_div;
246254885Sdumbbell
247254885Sdumbbell			if (rdev->family >= CHIP_R420) {
248254885Sdumbbell				p1pll->pll_in_min = 100;
249254885Sdumbbell				p1pll->pll_in_max = 1350;
250254885Sdumbbell				p1pll->pll_out_min = 20000;
251254885Sdumbbell				p1pll->pll_out_max = 50000;
252254885Sdumbbell				p2pll->pll_in_min = 100;
253254885Sdumbbell				p2pll->pll_in_max = 1350;
254254885Sdumbbell				p2pll->pll_out_min = 20000;
255254885Sdumbbell				p2pll->pll_out_max = 50000;
256254885Sdumbbell			} else {
257254885Sdumbbell				p1pll->pll_in_min = 40;
258254885Sdumbbell				p1pll->pll_in_max = 500;
259254885Sdumbbell				p1pll->pll_out_min = 12500;
260254885Sdumbbell				p1pll->pll_out_max = 35000;
261254885Sdumbbell				p2pll->pll_in_min = 40;
262254885Sdumbbell				p2pll->pll_in_max = 500;
263254885Sdumbbell				p2pll->pll_out_min = 12500;
264254885Sdumbbell				p2pll->pll_out_max = 35000;
265254885Sdumbbell			}
266254885Sdumbbell
267254885Sdumbbell			spll->reference_div =
268254885Sdumbbell			    RREG32_PLL(RADEON_M_SPLL_REF_FB_DIV) &
269254885Sdumbbell			    RADEON_M_SPLL_REF_DIV_MASK;
270254885Sdumbbell			mpll->reference_div = spll->reference_div;
271254885Sdumbbell			rdev->clock.default_sclk =
272254885Sdumbbell			    radeon_legacy_get_engine_clock(rdev);
273254885Sdumbbell			rdev->clock.default_mclk =
274254885Sdumbbell			    radeon_legacy_get_memory_clock(rdev);
275254885Sdumbbell		}
276254885Sdumbbell	}
277254885Sdumbbell
278254885Sdumbbell	/* pixel clocks */
279254885Sdumbbell	if (ASIC_IS_AVIVO(rdev)) {
280254885Sdumbbell		p1pll->min_post_div = 2;
281254885Sdumbbell		p1pll->max_post_div = 0x7f;
282254885Sdumbbell		p1pll->min_frac_feedback_div = 0;
283254885Sdumbbell		p1pll->max_frac_feedback_div = 9;
284254885Sdumbbell		p2pll->min_post_div = 2;
285254885Sdumbbell		p2pll->max_post_div = 0x7f;
286254885Sdumbbell		p2pll->min_frac_feedback_div = 0;
287254885Sdumbbell		p2pll->max_frac_feedback_div = 9;
288254885Sdumbbell	} else {
289254885Sdumbbell		p1pll->min_post_div = 1;
290254885Sdumbbell		p1pll->max_post_div = 16;
291254885Sdumbbell		p1pll->min_frac_feedback_div = 0;
292254885Sdumbbell		p1pll->max_frac_feedback_div = 0;
293254885Sdumbbell		p2pll->min_post_div = 1;
294254885Sdumbbell		p2pll->max_post_div = 12;
295254885Sdumbbell		p2pll->min_frac_feedback_div = 0;
296254885Sdumbbell		p2pll->max_frac_feedback_div = 0;
297254885Sdumbbell	}
298254885Sdumbbell
299254885Sdumbbell	/* dcpll is DCE4 only */
300254885Sdumbbell	dcpll->min_post_div = 2;
301254885Sdumbbell	dcpll->max_post_div = 0x7f;
302254885Sdumbbell	dcpll->min_frac_feedback_div = 0;
303254885Sdumbbell	dcpll->max_frac_feedback_div = 9;
304254885Sdumbbell	dcpll->min_ref_div = 2;
305254885Sdumbbell	dcpll->max_ref_div = 0x3ff;
306254885Sdumbbell	dcpll->min_feedback_div = 4;
307254885Sdumbbell	dcpll->max_feedback_div = 0xfff;
308254885Sdumbbell	dcpll->best_vco = 0;
309254885Sdumbbell
310254885Sdumbbell	p1pll->min_ref_div = 2;
311254885Sdumbbell	p1pll->max_ref_div = 0x3ff;
312254885Sdumbbell	p1pll->min_feedback_div = 4;
313254885Sdumbbell	p1pll->max_feedback_div = 0x7ff;
314254885Sdumbbell	p1pll->best_vco = 0;
315254885Sdumbbell
316254885Sdumbbell	p2pll->min_ref_div = 2;
317254885Sdumbbell	p2pll->max_ref_div = 0x3ff;
318254885Sdumbbell	p2pll->min_feedback_div = 4;
319254885Sdumbbell	p2pll->max_feedback_div = 0x7ff;
320254885Sdumbbell	p2pll->best_vco = 0;
321254885Sdumbbell
322254885Sdumbbell	/* system clock */
323254885Sdumbbell	spll->min_post_div = 1;
324254885Sdumbbell	spll->max_post_div = 1;
325254885Sdumbbell	spll->min_ref_div = 2;
326254885Sdumbbell	spll->max_ref_div = 0xff;
327254885Sdumbbell	spll->min_feedback_div = 4;
328254885Sdumbbell	spll->max_feedback_div = 0xff;
329254885Sdumbbell	spll->best_vco = 0;
330254885Sdumbbell
331254885Sdumbbell	/* memory clock */
332254885Sdumbbell	mpll->min_post_div = 1;
333254885Sdumbbell	mpll->max_post_div = 1;
334254885Sdumbbell	mpll->min_ref_div = 2;
335254885Sdumbbell	mpll->max_ref_div = 0xff;
336254885Sdumbbell	mpll->min_feedback_div = 4;
337254885Sdumbbell	mpll->max_feedback_div = 0xff;
338254885Sdumbbell	mpll->best_vco = 0;
339254885Sdumbbell
340254885Sdumbbell	if (!rdev->clock.default_sclk)
341254885Sdumbbell		rdev->clock.default_sclk = radeon_get_engine_clock(rdev);
342254885Sdumbbell	if ((!rdev->clock.default_mclk) && rdev->asic->pm.get_memory_clock)
343254885Sdumbbell		rdev->clock.default_mclk = radeon_get_memory_clock(rdev);
344254885Sdumbbell
345254885Sdumbbell	rdev->pm.current_sclk = rdev->clock.default_sclk;
346254885Sdumbbell	rdev->pm.current_mclk = rdev->clock.default_mclk;
347254885Sdumbbell
348254885Sdumbbell}
349254885Sdumbbell
350254885Sdumbbell/* 10 khz */
351254885Sdumbbellstatic uint32_t calc_eng_mem_clock(struct radeon_device *rdev,
352254885Sdumbbell				   uint32_t req_clock,
353254885Sdumbbell				   int *fb_div, int *post_div)
354254885Sdumbbell{
355254885Sdumbbell	struct radeon_pll *spll = &rdev->clock.spll;
356254885Sdumbbell	int ref_div = spll->reference_div;
357254885Sdumbbell
358254885Sdumbbell	if (!ref_div)
359254885Sdumbbell		ref_div =
360254885Sdumbbell		    RREG32_PLL(RADEON_M_SPLL_REF_FB_DIV) &
361254885Sdumbbell		    RADEON_M_SPLL_REF_DIV_MASK;
362254885Sdumbbell
363254885Sdumbbell	if (req_clock < 15000) {
364254885Sdumbbell		*post_div = 8;
365254885Sdumbbell		req_clock *= 8;
366254885Sdumbbell	} else if (req_clock < 30000) {
367254885Sdumbbell		*post_div = 4;
368254885Sdumbbell		req_clock *= 4;
369254885Sdumbbell	} else if (req_clock < 60000) {
370254885Sdumbbell		*post_div = 2;
371254885Sdumbbell		req_clock *= 2;
372254885Sdumbbell	} else
373254885Sdumbbell		*post_div = 1;
374254885Sdumbbell
375254885Sdumbbell	req_clock *= ref_div;
376254885Sdumbbell	req_clock += spll->reference_freq;
377254885Sdumbbell	req_clock /= (2 * spll->reference_freq);
378254885Sdumbbell
379254885Sdumbbell	*fb_div = req_clock & 0xff;
380254885Sdumbbell
381254885Sdumbbell	req_clock = (req_clock & 0xffff) << 1;
382254885Sdumbbell	req_clock *= spll->reference_freq;
383254885Sdumbbell	req_clock /= ref_div;
384254885Sdumbbell	req_clock /= *post_div;
385254885Sdumbbell
386254885Sdumbbell	return req_clock;
387254885Sdumbbell}
388254885Sdumbbell
389254885Sdumbbell/* 10 khz */
390254885Sdumbbellvoid radeon_legacy_set_engine_clock(struct radeon_device *rdev,
391254885Sdumbbell				    uint32_t eng_clock)
392254885Sdumbbell{
393254885Sdumbbell	uint32_t tmp;
394254885Sdumbbell	int fb_div, post_div;
395254885Sdumbbell
396254885Sdumbbell	/* XXX: wait for idle */
397254885Sdumbbell
398254885Sdumbbell	eng_clock = calc_eng_mem_clock(rdev, eng_clock, &fb_div, &post_div);
399254885Sdumbbell
400254885Sdumbbell	tmp = RREG32_PLL(RADEON_CLK_PIN_CNTL);
401254885Sdumbbell	tmp &= ~RADEON_DONT_USE_XTALIN;
402254885Sdumbbell	WREG32_PLL(RADEON_CLK_PIN_CNTL, tmp);
403254885Sdumbbell
404254885Sdumbbell	tmp = RREG32_PLL(RADEON_SCLK_CNTL);
405254885Sdumbbell	tmp &= ~RADEON_SCLK_SRC_SEL_MASK;
406254885Sdumbbell	WREG32_PLL(RADEON_SCLK_CNTL, tmp);
407254885Sdumbbell
408280183Sdumbbell	udelay(10);
409254885Sdumbbell
410254885Sdumbbell	tmp = RREG32_PLL(RADEON_SPLL_CNTL);
411254885Sdumbbell	tmp |= RADEON_SPLL_SLEEP;
412254885Sdumbbell	WREG32_PLL(RADEON_SPLL_CNTL, tmp);
413254885Sdumbbell
414280183Sdumbbell	udelay(2);
415254885Sdumbbell
416254885Sdumbbell	tmp = RREG32_PLL(RADEON_SPLL_CNTL);
417254885Sdumbbell	tmp |= RADEON_SPLL_RESET;
418254885Sdumbbell	WREG32_PLL(RADEON_SPLL_CNTL, tmp);
419254885Sdumbbell
420280183Sdumbbell	udelay(200);
421254885Sdumbbell
422254885Sdumbbell	tmp = RREG32_PLL(RADEON_M_SPLL_REF_FB_DIV);
423254885Sdumbbell	tmp &= ~(RADEON_SPLL_FB_DIV_MASK << RADEON_SPLL_FB_DIV_SHIFT);
424254885Sdumbbell	tmp |= (fb_div & RADEON_SPLL_FB_DIV_MASK) << RADEON_SPLL_FB_DIV_SHIFT;
425254885Sdumbbell	WREG32_PLL(RADEON_M_SPLL_REF_FB_DIV, tmp);
426254885Sdumbbell
427254885Sdumbbell	/* XXX: verify on different asics */
428254885Sdumbbell	tmp = RREG32_PLL(RADEON_SPLL_CNTL);
429254885Sdumbbell	tmp &= ~RADEON_SPLL_PVG_MASK;
430254885Sdumbbell	if ((eng_clock * post_div) >= 90000)
431254885Sdumbbell		tmp |= (0x7 << RADEON_SPLL_PVG_SHIFT);
432254885Sdumbbell	else
433254885Sdumbbell		tmp |= (0x4 << RADEON_SPLL_PVG_SHIFT);
434254885Sdumbbell	WREG32_PLL(RADEON_SPLL_CNTL, tmp);
435254885Sdumbbell
436254885Sdumbbell	tmp = RREG32_PLL(RADEON_SPLL_CNTL);
437254885Sdumbbell	tmp &= ~RADEON_SPLL_SLEEP;
438254885Sdumbbell	WREG32_PLL(RADEON_SPLL_CNTL, tmp);
439254885Sdumbbell
440280183Sdumbbell	udelay(2);
441254885Sdumbbell
442254885Sdumbbell	tmp = RREG32_PLL(RADEON_SPLL_CNTL);
443254885Sdumbbell	tmp &= ~RADEON_SPLL_RESET;
444254885Sdumbbell	WREG32_PLL(RADEON_SPLL_CNTL, tmp);
445254885Sdumbbell
446280183Sdumbbell	udelay(200);
447254885Sdumbbell
448254885Sdumbbell	tmp = RREG32_PLL(RADEON_SCLK_CNTL);
449254885Sdumbbell	tmp &= ~RADEON_SCLK_SRC_SEL_MASK;
450254885Sdumbbell	switch (post_div) {
451254885Sdumbbell	case 1:
452254885Sdumbbell	default:
453254885Sdumbbell		tmp |= 1;
454254885Sdumbbell		break;
455254885Sdumbbell	case 2:
456254885Sdumbbell		tmp |= 2;
457254885Sdumbbell		break;
458254885Sdumbbell	case 4:
459254885Sdumbbell		tmp |= 3;
460254885Sdumbbell		break;
461254885Sdumbbell	case 8:
462254885Sdumbbell		tmp |= 4;
463254885Sdumbbell		break;
464254885Sdumbbell	}
465254885Sdumbbell	WREG32_PLL(RADEON_SCLK_CNTL, tmp);
466254885Sdumbbell
467280183Sdumbbell	udelay(20);
468254885Sdumbbell
469254885Sdumbbell	tmp = RREG32_PLL(RADEON_CLK_PIN_CNTL);
470254885Sdumbbell	tmp |= RADEON_DONT_USE_XTALIN;
471254885Sdumbbell	WREG32_PLL(RADEON_CLK_PIN_CNTL, tmp);
472254885Sdumbbell
473280183Sdumbbell	udelay(10);
474254885Sdumbbell}
475254885Sdumbbell
476254885Sdumbbellvoid radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enable)
477254885Sdumbbell{
478254885Sdumbbell	uint32_t tmp;
479254885Sdumbbell
480254885Sdumbbell	if (enable) {
481254885Sdumbbell		if (rdev->flags & RADEON_SINGLE_CRTC) {
482254885Sdumbbell			tmp = RREG32_PLL(RADEON_SCLK_CNTL);
483254885Sdumbbell			if ((RREG32(RADEON_CONFIG_CNTL) &
484254885Sdumbbell			     RADEON_CFG_ATI_REV_ID_MASK) >
485254885Sdumbbell			    RADEON_CFG_ATI_REV_A13) {
486254885Sdumbbell				tmp &=
487254885Sdumbbell				    ~(RADEON_SCLK_FORCE_CP |
488254885Sdumbbell				      RADEON_SCLK_FORCE_RB);
489254885Sdumbbell			}
490254885Sdumbbell			tmp &=
491254885Sdumbbell			    ~(RADEON_SCLK_FORCE_HDP | RADEON_SCLK_FORCE_DISP1 |
492254885Sdumbbell			      RADEON_SCLK_FORCE_TOP | RADEON_SCLK_FORCE_SE |
493254885Sdumbbell			      RADEON_SCLK_FORCE_IDCT | RADEON_SCLK_FORCE_RE |
494254885Sdumbbell			      RADEON_SCLK_FORCE_PB | RADEON_SCLK_FORCE_TAM |
495254885Sdumbbell			      RADEON_SCLK_FORCE_TDM);
496254885Sdumbbell			WREG32_PLL(RADEON_SCLK_CNTL, tmp);
497254885Sdumbbell		} else if (ASIC_IS_R300(rdev)) {
498254885Sdumbbell			if ((rdev->family == CHIP_RS400) ||
499254885Sdumbbell			    (rdev->family == CHIP_RS480)) {
500254885Sdumbbell				tmp = RREG32_PLL(RADEON_SCLK_CNTL);
501254885Sdumbbell				tmp &=
502254885Sdumbbell				    ~(RADEON_SCLK_FORCE_DISP2 |
503254885Sdumbbell				      RADEON_SCLK_FORCE_CP |
504254885Sdumbbell				      RADEON_SCLK_FORCE_HDP |
505254885Sdumbbell				      RADEON_SCLK_FORCE_DISP1 |
506254885Sdumbbell				      RADEON_SCLK_FORCE_TOP |
507254885Sdumbbell				      RADEON_SCLK_FORCE_E2 | R300_SCLK_FORCE_VAP
508254885Sdumbbell				      | RADEON_SCLK_FORCE_IDCT |
509254885Sdumbbell				      RADEON_SCLK_FORCE_VIP | R300_SCLK_FORCE_SR
510254885Sdumbbell				      | R300_SCLK_FORCE_PX | R300_SCLK_FORCE_TX
511254885Sdumbbell				      | R300_SCLK_FORCE_US |
512254885Sdumbbell				      RADEON_SCLK_FORCE_TV_SCLK |
513254885Sdumbbell				      R300_SCLK_FORCE_SU |
514254885Sdumbbell				      RADEON_SCLK_FORCE_OV0);
515254885Sdumbbell				tmp |= RADEON_DYN_STOP_LAT_MASK;
516254885Sdumbbell				tmp |=
517254885Sdumbbell				    RADEON_SCLK_FORCE_TOP |
518254885Sdumbbell				    RADEON_SCLK_FORCE_VIP;
519254885Sdumbbell				WREG32_PLL(RADEON_SCLK_CNTL, tmp);
520254885Sdumbbell
521254885Sdumbbell				tmp = RREG32_PLL(RADEON_SCLK_MORE_CNTL);
522254885Sdumbbell				tmp &= ~RADEON_SCLK_MORE_FORCEON;
523254885Sdumbbell				tmp |= RADEON_SCLK_MORE_MAX_DYN_STOP_LAT;
524254885Sdumbbell				WREG32_PLL(RADEON_SCLK_MORE_CNTL, tmp);
525254885Sdumbbell
526254885Sdumbbell				tmp = RREG32_PLL(RADEON_VCLK_ECP_CNTL);
527254885Sdumbbell				tmp |= (RADEON_PIXCLK_ALWAYS_ONb |
528254885Sdumbbell					RADEON_PIXCLK_DAC_ALWAYS_ONb);
529254885Sdumbbell				WREG32_PLL(RADEON_VCLK_ECP_CNTL, tmp);
530254885Sdumbbell
531254885Sdumbbell				tmp = RREG32_PLL(RADEON_PIXCLKS_CNTL);
532254885Sdumbbell				tmp |= (RADEON_PIX2CLK_ALWAYS_ONb |
533254885Sdumbbell					RADEON_PIX2CLK_DAC_ALWAYS_ONb |
534254885Sdumbbell					RADEON_DISP_TVOUT_PIXCLK_TV_ALWAYS_ONb |
535254885Sdumbbell					R300_DVOCLK_ALWAYS_ONb |
536254885Sdumbbell					RADEON_PIXCLK_BLEND_ALWAYS_ONb |
537254885Sdumbbell					RADEON_PIXCLK_GV_ALWAYS_ONb |
538254885Sdumbbell					R300_PIXCLK_DVO_ALWAYS_ONb |
539254885Sdumbbell					RADEON_PIXCLK_LVDS_ALWAYS_ONb |
540254885Sdumbbell					RADEON_PIXCLK_TMDS_ALWAYS_ONb |
541254885Sdumbbell					R300_PIXCLK_TRANS_ALWAYS_ONb |
542254885Sdumbbell					R300_PIXCLK_TVO_ALWAYS_ONb |
543254885Sdumbbell					R300_P2G2CLK_ALWAYS_ONb |
544254885Sdumbbell					R300_P2G2CLK_DAC_ALWAYS_ONb);
545254885Sdumbbell				WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp);
546254885Sdumbbell			} else if (rdev->family >= CHIP_RV350) {
547254885Sdumbbell				tmp = RREG32_PLL(R300_SCLK_CNTL2);
548254885Sdumbbell				tmp &= ~(R300_SCLK_FORCE_TCL |
549254885Sdumbbell					 R300_SCLK_FORCE_GA |
550254885Sdumbbell					 R300_SCLK_FORCE_CBA);
551254885Sdumbbell				tmp |= (R300_SCLK_TCL_MAX_DYN_STOP_LAT |
552254885Sdumbbell					R300_SCLK_GA_MAX_DYN_STOP_LAT |
553254885Sdumbbell					R300_SCLK_CBA_MAX_DYN_STOP_LAT);
554254885Sdumbbell				WREG32_PLL(R300_SCLK_CNTL2, tmp);
555254885Sdumbbell
556254885Sdumbbell				tmp = RREG32_PLL(RADEON_SCLK_CNTL);
557254885Sdumbbell				tmp &=
558254885Sdumbbell				    ~(RADEON_SCLK_FORCE_DISP2 |
559254885Sdumbbell				      RADEON_SCLK_FORCE_CP |
560254885Sdumbbell				      RADEON_SCLK_FORCE_HDP |
561254885Sdumbbell				      RADEON_SCLK_FORCE_DISP1 |
562254885Sdumbbell				      RADEON_SCLK_FORCE_TOP |
563254885Sdumbbell				      RADEON_SCLK_FORCE_E2 | R300_SCLK_FORCE_VAP
564254885Sdumbbell				      | RADEON_SCLK_FORCE_IDCT |
565254885Sdumbbell				      RADEON_SCLK_FORCE_VIP | R300_SCLK_FORCE_SR
566254885Sdumbbell				      | R300_SCLK_FORCE_PX | R300_SCLK_FORCE_TX
567254885Sdumbbell				      | R300_SCLK_FORCE_US |
568254885Sdumbbell				      RADEON_SCLK_FORCE_TV_SCLK |
569254885Sdumbbell				      R300_SCLK_FORCE_SU |
570254885Sdumbbell				      RADEON_SCLK_FORCE_OV0);
571254885Sdumbbell				tmp |= RADEON_DYN_STOP_LAT_MASK;
572254885Sdumbbell				WREG32_PLL(RADEON_SCLK_CNTL, tmp);
573254885Sdumbbell
574254885Sdumbbell				tmp = RREG32_PLL(RADEON_SCLK_MORE_CNTL);
575254885Sdumbbell				tmp &= ~RADEON_SCLK_MORE_FORCEON;
576254885Sdumbbell				tmp |= RADEON_SCLK_MORE_MAX_DYN_STOP_LAT;
577254885Sdumbbell				WREG32_PLL(RADEON_SCLK_MORE_CNTL, tmp);
578254885Sdumbbell
579254885Sdumbbell				tmp = RREG32_PLL(RADEON_VCLK_ECP_CNTL);
580254885Sdumbbell				tmp |= (RADEON_PIXCLK_ALWAYS_ONb |
581254885Sdumbbell					RADEON_PIXCLK_DAC_ALWAYS_ONb);
582254885Sdumbbell				WREG32_PLL(RADEON_VCLK_ECP_CNTL, tmp);
583254885Sdumbbell
584254885Sdumbbell				tmp = RREG32_PLL(RADEON_PIXCLKS_CNTL);
585254885Sdumbbell				tmp |= (RADEON_PIX2CLK_ALWAYS_ONb |
586254885Sdumbbell					RADEON_PIX2CLK_DAC_ALWAYS_ONb |
587254885Sdumbbell					RADEON_DISP_TVOUT_PIXCLK_TV_ALWAYS_ONb |
588254885Sdumbbell					R300_DVOCLK_ALWAYS_ONb |
589254885Sdumbbell					RADEON_PIXCLK_BLEND_ALWAYS_ONb |
590254885Sdumbbell					RADEON_PIXCLK_GV_ALWAYS_ONb |
591254885Sdumbbell					R300_PIXCLK_DVO_ALWAYS_ONb |
592254885Sdumbbell					RADEON_PIXCLK_LVDS_ALWAYS_ONb |
593254885Sdumbbell					RADEON_PIXCLK_TMDS_ALWAYS_ONb |
594254885Sdumbbell					R300_PIXCLK_TRANS_ALWAYS_ONb |
595254885Sdumbbell					R300_PIXCLK_TVO_ALWAYS_ONb |
596254885Sdumbbell					R300_P2G2CLK_ALWAYS_ONb |
597254885Sdumbbell					R300_P2G2CLK_DAC_ALWAYS_ONb);
598254885Sdumbbell				WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp);
599254885Sdumbbell
600254885Sdumbbell				tmp = RREG32_PLL(RADEON_MCLK_MISC);
601254885Sdumbbell				tmp |= (RADEON_MC_MCLK_DYN_ENABLE |
602254885Sdumbbell					RADEON_IO_MCLK_DYN_ENABLE);
603254885Sdumbbell				WREG32_PLL(RADEON_MCLK_MISC, tmp);
604254885Sdumbbell
605254885Sdumbbell				tmp = RREG32_PLL(RADEON_MCLK_CNTL);
606254885Sdumbbell				tmp |= (RADEON_FORCEON_MCLKA |
607254885Sdumbbell					RADEON_FORCEON_MCLKB);
608254885Sdumbbell
609254885Sdumbbell				tmp &= ~(RADEON_FORCEON_YCLKA |
610254885Sdumbbell					 RADEON_FORCEON_YCLKB |
611254885Sdumbbell					 RADEON_FORCEON_MC);
612254885Sdumbbell
613254885Sdumbbell				/* Some releases of vbios have set DISABLE_MC_MCLKA
614254885Sdumbbell				   and DISABLE_MC_MCLKB bits in the vbios table.  Setting these
615254885Sdumbbell				   bits will cause H/W hang when reading video memory with dynamic clocking
616254885Sdumbbell				   enabled. */
617254885Sdumbbell				if ((tmp & R300_DISABLE_MC_MCLKA) &&
618254885Sdumbbell				    (tmp & R300_DISABLE_MC_MCLKB)) {
619254885Sdumbbell					/* If both bits are set, then check the active channels */
620254885Sdumbbell					tmp = RREG32_PLL(RADEON_MCLK_CNTL);
621254885Sdumbbell					if (rdev->mc.vram_width == 64) {
622254885Sdumbbell						if (RREG32(RADEON_MEM_CNTL) &
623254885Sdumbbell						    R300_MEM_USE_CD_CH_ONLY)
624254885Sdumbbell							tmp &=
625254885Sdumbbell							    ~R300_DISABLE_MC_MCLKB;
626254885Sdumbbell						else
627254885Sdumbbell							tmp &=
628254885Sdumbbell							    ~R300_DISABLE_MC_MCLKA;
629254885Sdumbbell					} else {
630254885Sdumbbell						tmp &= ~(R300_DISABLE_MC_MCLKA |
631254885Sdumbbell							 R300_DISABLE_MC_MCLKB);
632254885Sdumbbell					}
633254885Sdumbbell				}
634254885Sdumbbell
635254885Sdumbbell				WREG32_PLL(RADEON_MCLK_CNTL, tmp);
636254885Sdumbbell			} else {
637254885Sdumbbell				tmp = RREG32_PLL(RADEON_SCLK_CNTL);
638254885Sdumbbell				tmp &= ~(R300_SCLK_FORCE_VAP);
639254885Sdumbbell				tmp |= RADEON_SCLK_FORCE_CP;
640254885Sdumbbell				WREG32_PLL(RADEON_SCLK_CNTL, tmp);
641280183Sdumbbell				mdelay(15);
642254885Sdumbbell
643254885Sdumbbell				tmp = RREG32_PLL(R300_SCLK_CNTL2);
644254885Sdumbbell				tmp &= ~(R300_SCLK_FORCE_TCL |
645254885Sdumbbell					 R300_SCLK_FORCE_GA |
646254885Sdumbbell					 R300_SCLK_FORCE_CBA);
647254885Sdumbbell				WREG32_PLL(R300_SCLK_CNTL2, tmp);
648254885Sdumbbell			}
649254885Sdumbbell		} else {
650254885Sdumbbell			tmp = RREG32_PLL(RADEON_CLK_PWRMGT_CNTL);
651254885Sdumbbell
652254885Sdumbbell			tmp &= ~(RADEON_ACTIVE_HILO_LAT_MASK |
653254885Sdumbbell				 RADEON_DISP_DYN_STOP_LAT_MASK |
654254885Sdumbbell				 RADEON_DYN_STOP_MODE_MASK);
655254885Sdumbbell
656254885Sdumbbell			tmp |= (RADEON_ENGIN_DYNCLK_MODE |
657254885Sdumbbell				(0x01 << RADEON_ACTIVE_HILO_LAT_SHIFT));
658254885Sdumbbell			WREG32_PLL(RADEON_CLK_PWRMGT_CNTL, tmp);
659280183Sdumbbell			mdelay(15);
660254885Sdumbbell
661254885Sdumbbell			tmp = RREG32_PLL(RADEON_CLK_PIN_CNTL);
662254885Sdumbbell			tmp |= RADEON_SCLK_DYN_START_CNTL;
663254885Sdumbbell			WREG32_PLL(RADEON_CLK_PIN_CNTL, tmp);
664280183Sdumbbell			mdelay(15);
665254885Sdumbbell
666254885Sdumbbell			/* When DRI is enabled, setting DYN_STOP_LAT to zero can cause some R200
667254885Sdumbbell			   to lockup randomly, leave them as set by BIOS.
668254885Sdumbbell			 */
669254885Sdumbbell			tmp = RREG32_PLL(RADEON_SCLK_CNTL);
670254885Sdumbbell			/*tmp &= RADEON_SCLK_SRC_SEL_MASK; */
671254885Sdumbbell			tmp &= ~RADEON_SCLK_FORCEON_MASK;
672254885Sdumbbell
673254885Sdumbbell			/*RAGE_6::A11 A12 A12N1 A13, RV250::A11 A12, R300 */
674254885Sdumbbell			if (((rdev->family == CHIP_RV250) &&
675254885Sdumbbell			     ((RREG32(RADEON_CONFIG_CNTL) &
676254885Sdumbbell			       RADEON_CFG_ATI_REV_ID_MASK) <
677254885Sdumbbell			      RADEON_CFG_ATI_REV_A13))
678254885Sdumbbell			    || ((rdev->family == CHIP_RV100)
679254885Sdumbbell				&&
680254885Sdumbbell				((RREG32(RADEON_CONFIG_CNTL) &
681254885Sdumbbell				  RADEON_CFG_ATI_REV_ID_MASK) <=
682254885Sdumbbell				 RADEON_CFG_ATI_REV_A13))) {
683254885Sdumbbell				tmp |= RADEON_SCLK_FORCE_CP;
684254885Sdumbbell				tmp |= RADEON_SCLK_FORCE_VIP;
685254885Sdumbbell			}
686254885Sdumbbell
687254885Sdumbbell			WREG32_PLL(RADEON_SCLK_CNTL, tmp);
688254885Sdumbbell
689254885Sdumbbell			if ((rdev->family == CHIP_RV200) ||
690254885Sdumbbell			    (rdev->family == CHIP_RV250) ||
691254885Sdumbbell			    (rdev->family == CHIP_RV280)) {
692254885Sdumbbell				tmp = RREG32_PLL(RADEON_SCLK_MORE_CNTL);
693254885Sdumbbell				tmp &= ~RADEON_SCLK_MORE_FORCEON;
694254885Sdumbbell
695254885Sdumbbell				/* RV200::A11 A12 RV250::A11 A12 */
696254885Sdumbbell				if (((rdev->family == CHIP_RV200) ||
697254885Sdumbbell				     (rdev->family == CHIP_RV250)) &&
698254885Sdumbbell				    ((RREG32(RADEON_CONFIG_CNTL) &
699254885Sdumbbell				      RADEON_CFG_ATI_REV_ID_MASK) <
700254885Sdumbbell				     RADEON_CFG_ATI_REV_A13)) {
701254885Sdumbbell					tmp |= RADEON_SCLK_MORE_FORCEON;
702254885Sdumbbell				}
703254885Sdumbbell				WREG32_PLL(RADEON_SCLK_MORE_CNTL, tmp);
704280183Sdumbbell				mdelay(15);
705254885Sdumbbell			}
706254885Sdumbbell
707254885Sdumbbell			/* RV200::A11 A12, RV250::A11 A12 */
708254885Sdumbbell			if (((rdev->family == CHIP_RV200) ||
709254885Sdumbbell			     (rdev->family == CHIP_RV250)) &&
710254885Sdumbbell			    ((RREG32(RADEON_CONFIG_CNTL) &
711254885Sdumbbell			      RADEON_CFG_ATI_REV_ID_MASK) <
712254885Sdumbbell			     RADEON_CFG_ATI_REV_A13)) {
713254885Sdumbbell				tmp = RREG32_PLL(RADEON_PLL_PWRMGT_CNTL);
714254885Sdumbbell				tmp |= RADEON_TCL_BYPASS_DISABLE;
715254885Sdumbbell				WREG32_PLL(RADEON_PLL_PWRMGT_CNTL, tmp);
716254885Sdumbbell			}
717280183Sdumbbell			mdelay(15);
718254885Sdumbbell
719254885Sdumbbell			/*enable dynamic mode for display clocks (PIXCLK and PIX2CLK) */
720254885Sdumbbell			tmp = RREG32_PLL(RADEON_PIXCLKS_CNTL);
721254885Sdumbbell			tmp |= (RADEON_PIX2CLK_ALWAYS_ONb |
722254885Sdumbbell				RADEON_PIX2CLK_DAC_ALWAYS_ONb |
723254885Sdumbbell				RADEON_PIXCLK_BLEND_ALWAYS_ONb |
724254885Sdumbbell				RADEON_PIXCLK_GV_ALWAYS_ONb |
725254885Sdumbbell				RADEON_PIXCLK_DIG_TMDS_ALWAYS_ONb |
726254885Sdumbbell				RADEON_PIXCLK_LVDS_ALWAYS_ONb |
727254885Sdumbbell				RADEON_PIXCLK_TMDS_ALWAYS_ONb);
728254885Sdumbbell
729254885Sdumbbell			WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp);
730280183Sdumbbell			mdelay(15);
731254885Sdumbbell
732254885Sdumbbell			tmp = RREG32_PLL(RADEON_VCLK_ECP_CNTL);
733254885Sdumbbell			tmp |= (RADEON_PIXCLK_ALWAYS_ONb |
734254885Sdumbbell				RADEON_PIXCLK_DAC_ALWAYS_ONb);
735254885Sdumbbell
736254885Sdumbbell			WREG32_PLL(RADEON_VCLK_ECP_CNTL, tmp);
737280183Sdumbbell			mdelay(15);
738254885Sdumbbell		}
739254885Sdumbbell	} else {
740254885Sdumbbell		/* Turn everything OFF (ForceON to everything) */
741254885Sdumbbell		if (rdev->flags & RADEON_SINGLE_CRTC) {
742254885Sdumbbell			tmp = RREG32_PLL(RADEON_SCLK_CNTL);
743254885Sdumbbell			tmp |= (RADEON_SCLK_FORCE_CP | RADEON_SCLK_FORCE_HDP |
744254885Sdumbbell				RADEON_SCLK_FORCE_DISP1 | RADEON_SCLK_FORCE_TOP
745254885Sdumbbell				| RADEON_SCLK_FORCE_E2 | RADEON_SCLK_FORCE_SE |
746254885Sdumbbell				RADEON_SCLK_FORCE_IDCT | RADEON_SCLK_FORCE_VIP |
747254885Sdumbbell				RADEON_SCLK_FORCE_RE | RADEON_SCLK_FORCE_PB |
748254885Sdumbbell				RADEON_SCLK_FORCE_TAM | RADEON_SCLK_FORCE_TDM |
749254885Sdumbbell				RADEON_SCLK_FORCE_RB);
750254885Sdumbbell			WREG32_PLL(RADEON_SCLK_CNTL, tmp);
751254885Sdumbbell		} else if ((rdev->family == CHIP_RS400) ||
752254885Sdumbbell			   (rdev->family == CHIP_RS480)) {
753254885Sdumbbell			tmp = RREG32_PLL(RADEON_SCLK_CNTL);
754254885Sdumbbell			tmp |= (RADEON_SCLK_FORCE_DISP2 | RADEON_SCLK_FORCE_CP |
755254885Sdumbbell				RADEON_SCLK_FORCE_HDP | RADEON_SCLK_FORCE_DISP1
756254885Sdumbbell				| RADEON_SCLK_FORCE_TOP | RADEON_SCLK_FORCE_E2 |
757254885Sdumbbell				R300_SCLK_FORCE_VAP | RADEON_SCLK_FORCE_IDCT |
758254885Sdumbbell				RADEON_SCLK_FORCE_VIP | R300_SCLK_FORCE_SR |
759254885Sdumbbell				R300_SCLK_FORCE_PX | R300_SCLK_FORCE_TX |
760254885Sdumbbell				R300_SCLK_FORCE_US | RADEON_SCLK_FORCE_TV_SCLK |
761254885Sdumbbell				R300_SCLK_FORCE_SU | RADEON_SCLK_FORCE_OV0);
762254885Sdumbbell			WREG32_PLL(RADEON_SCLK_CNTL, tmp);
763254885Sdumbbell
764254885Sdumbbell			tmp = RREG32_PLL(RADEON_SCLK_MORE_CNTL);
765254885Sdumbbell			tmp |= RADEON_SCLK_MORE_FORCEON;
766254885Sdumbbell			WREG32_PLL(RADEON_SCLK_MORE_CNTL, tmp);
767254885Sdumbbell
768254885Sdumbbell			tmp = RREG32_PLL(RADEON_VCLK_ECP_CNTL);
769254885Sdumbbell			tmp &= ~(RADEON_PIXCLK_ALWAYS_ONb |
770254885Sdumbbell				 RADEON_PIXCLK_DAC_ALWAYS_ONb |
771254885Sdumbbell				 R300_DISP_DAC_PIXCLK_DAC_BLANK_OFF);
772254885Sdumbbell			WREG32_PLL(RADEON_VCLK_ECP_CNTL, tmp);
773254885Sdumbbell
774254885Sdumbbell			tmp = RREG32_PLL(RADEON_PIXCLKS_CNTL);
775254885Sdumbbell			tmp &= ~(RADEON_PIX2CLK_ALWAYS_ONb |
776254885Sdumbbell				 RADEON_PIX2CLK_DAC_ALWAYS_ONb |
777254885Sdumbbell				 RADEON_DISP_TVOUT_PIXCLK_TV_ALWAYS_ONb |
778254885Sdumbbell				 R300_DVOCLK_ALWAYS_ONb |
779254885Sdumbbell				 RADEON_PIXCLK_BLEND_ALWAYS_ONb |
780254885Sdumbbell				 RADEON_PIXCLK_GV_ALWAYS_ONb |
781254885Sdumbbell				 R300_PIXCLK_DVO_ALWAYS_ONb |
782254885Sdumbbell				 RADEON_PIXCLK_LVDS_ALWAYS_ONb |
783254885Sdumbbell				 RADEON_PIXCLK_TMDS_ALWAYS_ONb |
784254885Sdumbbell				 R300_PIXCLK_TRANS_ALWAYS_ONb |
785254885Sdumbbell				 R300_PIXCLK_TVO_ALWAYS_ONb |
786254885Sdumbbell				 R300_P2G2CLK_ALWAYS_ONb |
787254885Sdumbbell				 R300_P2G2CLK_DAC_ALWAYS_ONb |
788254885Sdumbbell				 R300_DISP_DAC_PIXCLK_DAC2_BLANK_OFF);
789254885Sdumbbell			WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp);
790254885Sdumbbell		} else if (rdev->family >= CHIP_RV350) {
791254885Sdumbbell			/* for RV350/M10, no delays are required. */
792254885Sdumbbell			tmp = RREG32_PLL(R300_SCLK_CNTL2);
793254885Sdumbbell			tmp |= (R300_SCLK_FORCE_TCL |
794254885Sdumbbell				R300_SCLK_FORCE_GA | R300_SCLK_FORCE_CBA);
795254885Sdumbbell			WREG32_PLL(R300_SCLK_CNTL2, tmp);
796254885Sdumbbell
797254885Sdumbbell			tmp = RREG32_PLL(RADEON_SCLK_CNTL);
798254885Sdumbbell			tmp |= (RADEON_SCLK_FORCE_DISP2 | RADEON_SCLK_FORCE_CP |
799254885Sdumbbell				RADEON_SCLK_FORCE_HDP | RADEON_SCLK_FORCE_DISP1
800254885Sdumbbell				| RADEON_SCLK_FORCE_TOP | RADEON_SCLK_FORCE_E2 |
801254885Sdumbbell				R300_SCLK_FORCE_VAP | RADEON_SCLK_FORCE_IDCT |
802254885Sdumbbell				RADEON_SCLK_FORCE_VIP | R300_SCLK_FORCE_SR |
803254885Sdumbbell				R300_SCLK_FORCE_PX | R300_SCLK_FORCE_TX |
804254885Sdumbbell				R300_SCLK_FORCE_US | RADEON_SCLK_FORCE_TV_SCLK |
805254885Sdumbbell				R300_SCLK_FORCE_SU | RADEON_SCLK_FORCE_OV0);
806254885Sdumbbell			WREG32_PLL(RADEON_SCLK_CNTL, tmp);
807254885Sdumbbell
808254885Sdumbbell			tmp = RREG32_PLL(RADEON_SCLK_MORE_CNTL);
809254885Sdumbbell			tmp |= RADEON_SCLK_MORE_FORCEON;
810254885Sdumbbell			WREG32_PLL(RADEON_SCLK_MORE_CNTL, tmp);
811254885Sdumbbell
812254885Sdumbbell			tmp = RREG32_PLL(RADEON_MCLK_CNTL);
813254885Sdumbbell			tmp |= (RADEON_FORCEON_MCLKA |
814254885Sdumbbell				RADEON_FORCEON_MCLKB |
815254885Sdumbbell				RADEON_FORCEON_YCLKA |
816254885Sdumbbell				RADEON_FORCEON_YCLKB | RADEON_FORCEON_MC);
817254885Sdumbbell			WREG32_PLL(RADEON_MCLK_CNTL, tmp);
818254885Sdumbbell
819254885Sdumbbell			tmp = RREG32_PLL(RADEON_VCLK_ECP_CNTL);
820254885Sdumbbell			tmp &= ~(RADEON_PIXCLK_ALWAYS_ONb |
821254885Sdumbbell				 RADEON_PIXCLK_DAC_ALWAYS_ONb |
822254885Sdumbbell				 R300_DISP_DAC_PIXCLK_DAC_BLANK_OFF);
823254885Sdumbbell			WREG32_PLL(RADEON_VCLK_ECP_CNTL, tmp);
824254885Sdumbbell
825254885Sdumbbell			tmp = RREG32_PLL(RADEON_PIXCLKS_CNTL);
826254885Sdumbbell			tmp &= ~(RADEON_PIX2CLK_ALWAYS_ONb |
827254885Sdumbbell				 RADEON_PIX2CLK_DAC_ALWAYS_ONb |
828254885Sdumbbell				 RADEON_DISP_TVOUT_PIXCLK_TV_ALWAYS_ONb |
829254885Sdumbbell				 R300_DVOCLK_ALWAYS_ONb |
830254885Sdumbbell				 RADEON_PIXCLK_BLEND_ALWAYS_ONb |
831254885Sdumbbell				 RADEON_PIXCLK_GV_ALWAYS_ONb |
832254885Sdumbbell				 R300_PIXCLK_DVO_ALWAYS_ONb |
833254885Sdumbbell				 RADEON_PIXCLK_LVDS_ALWAYS_ONb |
834254885Sdumbbell				 RADEON_PIXCLK_TMDS_ALWAYS_ONb |
835254885Sdumbbell				 R300_PIXCLK_TRANS_ALWAYS_ONb |
836254885Sdumbbell				 R300_PIXCLK_TVO_ALWAYS_ONb |
837254885Sdumbbell				 R300_P2G2CLK_ALWAYS_ONb |
838254885Sdumbbell				 R300_P2G2CLK_DAC_ALWAYS_ONb |
839254885Sdumbbell				 R300_DISP_DAC_PIXCLK_DAC2_BLANK_OFF);
840254885Sdumbbell			WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp);
841254885Sdumbbell		} else {
842254885Sdumbbell			tmp = RREG32_PLL(RADEON_SCLK_CNTL);
843254885Sdumbbell			tmp |= (RADEON_SCLK_FORCE_CP | RADEON_SCLK_FORCE_E2);
844254885Sdumbbell			tmp |= RADEON_SCLK_FORCE_SE;
845254885Sdumbbell
846254885Sdumbbell			if (rdev->flags & RADEON_SINGLE_CRTC) {
847254885Sdumbbell				tmp |= (RADEON_SCLK_FORCE_RB |
848254885Sdumbbell					RADEON_SCLK_FORCE_TDM |
849254885Sdumbbell					RADEON_SCLK_FORCE_TAM |
850254885Sdumbbell					RADEON_SCLK_FORCE_PB |
851254885Sdumbbell					RADEON_SCLK_FORCE_RE |
852254885Sdumbbell					RADEON_SCLK_FORCE_VIP |
853254885Sdumbbell					RADEON_SCLK_FORCE_IDCT |
854254885Sdumbbell					RADEON_SCLK_FORCE_TOP |
855254885Sdumbbell					RADEON_SCLK_FORCE_DISP1 |
856254885Sdumbbell					RADEON_SCLK_FORCE_DISP2 |
857254885Sdumbbell					RADEON_SCLK_FORCE_HDP);
858254885Sdumbbell			} else if ((rdev->family == CHIP_R300) ||
859254885Sdumbbell				   (rdev->family == CHIP_R350)) {
860254885Sdumbbell				tmp |= (RADEON_SCLK_FORCE_HDP |
861254885Sdumbbell					RADEON_SCLK_FORCE_DISP1 |
862254885Sdumbbell					RADEON_SCLK_FORCE_DISP2 |
863254885Sdumbbell					RADEON_SCLK_FORCE_TOP |
864254885Sdumbbell					RADEON_SCLK_FORCE_IDCT |
865254885Sdumbbell					RADEON_SCLK_FORCE_VIP);
866254885Sdumbbell			}
867254885Sdumbbell			WREG32_PLL(RADEON_SCLK_CNTL, tmp);
868254885Sdumbbell
869280183Sdumbbell			mdelay(16);
870254885Sdumbbell
871254885Sdumbbell			if ((rdev->family == CHIP_R300) ||
872254885Sdumbbell			    (rdev->family == CHIP_R350)) {
873254885Sdumbbell				tmp = RREG32_PLL(R300_SCLK_CNTL2);
874254885Sdumbbell				tmp |= (R300_SCLK_FORCE_TCL |
875254885Sdumbbell					R300_SCLK_FORCE_GA |
876254885Sdumbbell					R300_SCLK_FORCE_CBA);
877254885Sdumbbell				WREG32_PLL(R300_SCLK_CNTL2, tmp);
878280183Sdumbbell				mdelay(16);
879254885Sdumbbell			}
880254885Sdumbbell
881254885Sdumbbell			if (rdev->flags & RADEON_IS_IGP) {
882254885Sdumbbell				tmp = RREG32_PLL(RADEON_MCLK_CNTL);
883254885Sdumbbell				tmp &= ~(RADEON_FORCEON_MCLKA |
884254885Sdumbbell					 RADEON_FORCEON_YCLKA);
885254885Sdumbbell				WREG32_PLL(RADEON_MCLK_CNTL, tmp);
886280183Sdumbbell				mdelay(16);
887254885Sdumbbell			}
888254885Sdumbbell
889254885Sdumbbell			if ((rdev->family == CHIP_RV200) ||
890254885Sdumbbell			    (rdev->family == CHIP_RV250) ||
891254885Sdumbbell			    (rdev->family == CHIP_RV280)) {
892254885Sdumbbell				tmp = RREG32_PLL(RADEON_SCLK_MORE_CNTL);
893254885Sdumbbell				tmp |= RADEON_SCLK_MORE_FORCEON;
894254885Sdumbbell				WREG32_PLL(RADEON_SCLK_MORE_CNTL, tmp);
895280183Sdumbbell				mdelay(16);
896254885Sdumbbell			}
897254885Sdumbbell
898254885Sdumbbell			tmp = RREG32_PLL(RADEON_PIXCLKS_CNTL);
899254885Sdumbbell			tmp &= ~(RADEON_PIX2CLK_ALWAYS_ONb |
900254885Sdumbbell				 RADEON_PIX2CLK_DAC_ALWAYS_ONb |
901254885Sdumbbell				 RADEON_PIXCLK_BLEND_ALWAYS_ONb |
902254885Sdumbbell				 RADEON_PIXCLK_GV_ALWAYS_ONb |
903254885Sdumbbell				 RADEON_PIXCLK_DIG_TMDS_ALWAYS_ONb |
904254885Sdumbbell				 RADEON_PIXCLK_LVDS_ALWAYS_ONb |
905254885Sdumbbell				 RADEON_PIXCLK_TMDS_ALWAYS_ONb);
906254885Sdumbbell
907254885Sdumbbell			WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp);
908280183Sdumbbell			mdelay(16);
909254885Sdumbbell
910254885Sdumbbell			tmp = RREG32_PLL(RADEON_VCLK_ECP_CNTL);
911254885Sdumbbell			tmp &= ~(RADEON_PIXCLK_ALWAYS_ONb |
912254885Sdumbbell				 RADEON_PIXCLK_DAC_ALWAYS_ONb);
913254885Sdumbbell			WREG32_PLL(RADEON_VCLK_ECP_CNTL, tmp);
914254885Sdumbbell		}
915254885Sdumbbell	}
916254885Sdumbbell}
917254885Sdumbbell
918