xref: /linux/drivers/gpu/drm/radeon/radeon_clocks.c (revision e4862f2f6f5653dfb67f3ba2b6f0bc74516ed51a)
1 /*
2  * Copyright 2008 Advanced Micro Devices, Inc.
3  * Copyright 2008 Red Hat Inc.
4  * Copyright 2009 Jerome Glisse.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
20  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22  * OTHER DEALINGS IN THE SOFTWARE.
23  *
24  * Authors: Dave Airlie
25  *          Alex Deucher
26  *          Jerome Glisse
27  */
28 #include "drmP.h"
29 #include "radeon_drm.h"
30 #include "radeon_reg.h"
31 #include "radeon.h"
32 #include "atom.h"
33 
34 /* 10 khz */
35 uint32_t radeon_legacy_get_engine_clock(struct radeon_device *rdev)
36 {
37 	struct radeon_pll *spll = &rdev->clock.spll;
38 	uint32_t fb_div, ref_div, post_div, sclk;
39 
40 	fb_div = RREG32_PLL(RADEON_M_SPLL_REF_FB_DIV);
41 	fb_div = (fb_div >> RADEON_SPLL_FB_DIV_SHIFT) & RADEON_SPLL_FB_DIV_MASK;
42 	fb_div <<= 1;
43 	fb_div *= spll->reference_freq;
44 
45 	ref_div =
46 	    RREG32_PLL(RADEON_M_SPLL_REF_FB_DIV) & RADEON_M_SPLL_REF_DIV_MASK;
47 
48 	if (ref_div == 0)
49 		return 0;
50 
51 	sclk = fb_div / ref_div;
52 
53 	post_div = RREG32_PLL(RADEON_SCLK_CNTL) & RADEON_SCLK_SRC_SEL_MASK;
54 	if (post_div == 2)
55 		sclk >>= 1;
56 	else if (post_div == 3)
57 		sclk >>= 2;
58 	else if (post_div == 4)
59 		sclk >>= 3;
60 
61 	return sclk;
62 }
63 
64 /* 10 khz */
65 uint32_t radeon_legacy_get_memory_clock(struct radeon_device *rdev)
66 {
67 	struct radeon_pll *mpll = &rdev->clock.mpll;
68 	uint32_t fb_div, ref_div, post_div, mclk;
69 
70 	fb_div = RREG32_PLL(RADEON_M_SPLL_REF_FB_DIV);
71 	fb_div = (fb_div >> RADEON_MPLL_FB_DIV_SHIFT) & RADEON_MPLL_FB_DIV_MASK;
72 	fb_div <<= 1;
73 	fb_div *= mpll->reference_freq;
74 
75 	ref_div =
76 	    RREG32_PLL(RADEON_M_SPLL_REF_FB_DIV) & RADEON_M_SPLL_REF_DIV_MASK;
77 
78 	if (ref_div == 0)
79 		return 0;
80 
81 	mclk = fb_div / ref_div;
82 
83 	post_div = RREG32_PLL(RADEON_MCLK_CNTL) & 0x7;
84 	if (post_div == 2)
85 		mclk >>= 1;
86 	else if (post_div == 3)
87 		mclk >>= 2;
88 	else if (post_div == 4)
89 		mclk >>= 3;
90 
91 	return mclk;
92 }
93 
94 #ifdef CONFIG_OF
95 /*
96  * Read XTAL (ref clock), SCLK and MCLK from Open Firmware device
97  * tree. Hopefully, ATI OF driver is kind enough to fill these
98  */
99 static bool __devinit radeon_read_clocks_OF(struct drm_device *dev)
100 {
101 	struct radeon_device *rdev = dev->dev_private;
102 	struct device_node *dp = rdev->pdev->dev.of_node;
103 	const u32 *val;
104 	struct radeon_pll *p1pll = &rdev->clock.p1pll;
105 	struct radeon_pll *p2pll = &rdev->clock.p2pll;
106 	struct radeon_pll *spll = &rdev->clock.spll;
107 	struct radeon_pll *mpll = &rdev->clock.mpll;
108 
109 	if (dp == NULL)
110 		return false;
111 	val = of_get_property(dp, "ATY,RefCLK", NULL);
112 	if (!val || !*val) {
113 		printk(KERN_WARNING "radeonfb: No ATY,RefCLK property !\n");
114 		return false;
115 	}
116 	p1pll->reference_freq = p2pll->reference_freq = (*val) / 10;
117 	p1pll->reference_div = RREG32_PLL(RADEON_PPLL_REF_DIV) & 0x3ff;
118 	if (p1pll->reference_div < 2)
119 		p1pll->reference_div = 12;
120 	p2pll->reference_div = p1pll->reference_div;
121 
122 	/* These aren't in the device-tree */
123 	if (rdev->family >= CHIP_R420) {
124 		p1pll->pll_in_min = 100;
125 		p1pll->pll_in_max = 1350;
126 		p1pll->pll_out_min = 20000;
127 		p1pll->pll_out_max = 50000;
128 		p2pll->pll_in_min = 100;
129 		p2pll->pll_in_max = 1350;
130 		p2pll->pll_out_min = 20000;
131 		p2pll->pll_out_max = 50000;
132 	} else {
133 		p1pll->pll_in_min = 40;
134 		p1pll->pll_in_max = 500;
135 		p1pll->pll_out_min = 12500;
136 		p1pll->pll_out_max = 35000;
137 		p2pll->pll_in_min = 40;
138 		p2pll->pll_in_max = 500;
139 		p2pll->pll_out_min = 12500;
140 		p2pll->pll_out_max = 35000;
141 	}
142 
143 	spll->reference_freq = mpll->reference_freq = p1pll->reference_freq;
144 	spll->reference_div = mpll->reference_div =
145 		RREG32_PLL(RADEON_M_SPLL_REF_FB_DIV) &
146 			    RADEON_M_SPLL_REF_DIV_MASK;
147 
148 	val = of_get_property(dp, "ATY,SCLK", NULL);
149 	if (val && *val)
150 		rdev->clock.default_sclk = (*val) / 10;
151 	else
152 		rdev->clock.default_sclk =
153 			radeon_legacy_get_engine_clock(rdev);
154 
155 	val = of_get_property(dp, "ATY,MCLK", NULL);
156 	if (val && *val)
157 		rdev->clock.default_mclk = (*val) / 10;
158 	else
159 		rdev->clock.default_mclk =
160 			radeon_legacy_get_memory_clock(rdev);
161 
162 	DRM_INFO("Using device-tree clock info\n");
163 
164 	return true;
165 }
166 #else
167 static bool __devinit radeon_read_clocks_OF(struct drm_device *dev)
168 {
169 	return false;
170 }
171 #endif /* CONFIG_OF */
172 
173 void radeon_get_clock_info(struct drm_device *dev)
174 {
175 	struct radeon_device *rdev = dev->dev_private;
176 	struct radeon_pll *p1pll = &rdev->clock.p1pll;
177 	struct radeon_pll *p2pll = &rdev->clock.p2pll;
178 	struct radeon_pll *dcpll = &rdev->clock.dcpll;
179 	struct radeon_pll *spll = &rdev->clock.spll;
180 	struct radeon_pll *mpll = &rdev->clock.mpll;
181 	int ret;
182 
183 	if (rdev->is_atom_bios)
184 		ret = radeon_atom_get_clock_info(dev);
185 	else
186 		ret = radeon_combios_get_clock_info(dev);
187 	if (!ret)
188 		ret = radeon_read_clocks_OF(dev);
189 
190 	if (ret) {
191 		if (p1pll->reference_div < 2) {
192 			if (!ASIC_IS_AVIVO(rdev)) {
193 				u32 tmp = RREG32_PLL(RADEON_PPLL_REF_DIV);
194 				if (ASIC_IS_R300(rdev))
195 					p1pll->reference_div =
196 						(tmp & R300_PPLL_REF_DIV_ACC_MASK) >> R300_PPLL_REF_DIV_ACC_SHIFT;
197 				else
198 					p1pll->reference_div = tmp & RADEON_PPLL_REF_DIV_MASK;
199 				if (p1pll->reference_div < 2)
200 					p1pll->reference_div = 12;
201 			} else
202 				p1pll->reference_div = 12;
203 		}
204 		if (p2pll->reference_div < 2)
205 			p2pll->reference_div = 12;
206 		if (rdev->family < CHIP_RS600) {
207 			if (spll->reference_div < 2)
208 				spll->reference_div =
209 					RREG32_PLL(RADEON_M_SPLL_REF_FB_DIV) &
210 					RADEON_M_SPLL_REF_DIV_MASK;
211 		}
212 		if (mpll->reference_div < 2)
213 			mpll->reference_div = spll->reference_div;
214 	} else {
215 		if (ASIC_IS_AVIVO(rdev)) {
216 			/* TODO FALLBACK */
217 		} else {
218 			DRM_INFO("Using generic clock info\n");
219 
220 			if (rdev->flags & RADEON_IS_IGP) {
221 				p1pll->reference_freq = 1432;
222 				p2pll->reference_freq = 1432;
223 				spll->reference_freq = 1432;
224 				mpll->reference_freq = 1432;
225 			} else {
226 				p1pll->reference_freq = 2700;
227 				p2pll->reference_freq = 2700;
228 				spll->reference_freq = 2700;
229 				mpll->reference_freq = 2700;
230 			}
231 			p1pll->reference_div =
232 			    RREG32_PLL(RADEON_PPLL_REF_DIV) & 0x3ff;
233 			if (p1pll->reference_div < 2)
234 				p1pll->reference_div = 12;
235 			p2pll->reference_div = p1pll->reference_div;
236 
237 			if (rdev->family >= CHIP_R420) {
238 				p1pll->pll_in_min = 100;
239 				p1pll->pll_in_max = 1350;
240 				p1pll->pll_out_min = 20000;
241 				p1pll->pll_out_max = 50000;
242 				p2pll->pll_in_min = 100;
243 				p2pll->pll_in_max = 1350;
244 				p2pll->pll_out_min = 20000;
245 				p2pll->pll_out_max = 50000;
246 			} else {
247 				p1pll->pll_in_min = 40;
248 				p1pll->pll_in_max = 500;
249 				p1pll->pll_out_min = 12500;
250 				p1pll->pll_out_max = 35000;
251 				p2pll->pll_in_min = 40;
252 				p2pll->pll_in_max = 500;
253 				p2pll->pll_out_min = 12500;
254 				p2pll->pll_out_max = 35000;
255 			}
256 
257 			spll->reference_div =
258 			    RREG32_PLL(RADEON_M_SPLL_REF_FB_DIV) &
259 			    RADEON_M_SPLL_REF_DIV_MASK;
260 			mpll->reference_div = spll->reference_div;
261 			rdev->clock.default_sclk =
262 			    radeon_legacy_get_engine_clock(rdev);
263 			rdev->clock.default_mclk =
264 			    radeon_legacy_get_memory_clock(rdev);
265 		}
266 	}
267 
268 	/* pixel clocks */
269 	if (ASIC_IS_AVIVO(rdev)) {
270 		p1pll->min_post_div = 2;
271 		p1pll->max_post_div = 0x7f;
272 		p1pll->min_frac_feedback_div = 0;
273 		p1pll->max_frac_feedback_div = 9;
274 		p2pll->min_post_div = 2;
275 		p2pll->max_post_div = 0x7f;
276 		p2pll->min_frac_feedback_div = 0;
277 		p2pll->max_frac_feedback_div = 9;
278 	} else {
279 		p1pll->min_post_div = 1;
280 		p1pll->max_post_div = 16;
281 		p1pll->min_frac_feedback_div = 0;
282 		p1pll->max_frac_feedback_div = 0;
283 		p2pll->min_post_div = 1;
284 		p2pll->max_post_div = 12;
285 		p2pll->min_frac_feedback_div = 0;
286 		p2pll->max_frac_feedback_div = 0;
287 	}
288 
289 	/* dcpll is DCE4 only */
290 	dcpll->min_post_div = 2;
291 	dcpll->max_post_div = 0x7f;
292 	dcpll->min_frac_feedback_div = 0;
293 	dcpll->max_frac_feedback_div = 9;
294 	dcpll->min_ref_div = 2;
295 	dcpll->max_ref_div = 0x3ff;
296 	dcpll->min_feedback_div = 4;
297 	dcpll->max_feedback_div = 0xfff;
298 	dcpll->best_vco = 0;
299 
300 	p1pll->min_ref_div = 2;
301 	p1pll->max_ref_div = 0x3ff;
302 	p1pll->min_feedback_div = 4;
303 	p1pll->max_feedback_div = 0x7ff;
304 	p1pll->best_vco = 0;
305 
306 	p2pll->min_ref_div = 2;
307 	p2pll->max_ref_div = 0x3ff;
308 	p2pll->min_feedback_div = 4;
309 	p2pll->max_feedback_div = 0x7ff;
310 	p2pll->best_vco = 0;
311 
312 	/* system clock */
313 	spll->min_post_div = 1;
314 	spll->max_post_div = 1;
315 	spll->min_ref_div = 2;
316 	spll->max_ref_div = 0xff;
317 	spll->min_feedback_div = 4;
318 	spll->max_feedback_div = 0xff;
319 	spll->best_vco = 0;
320 
321 	/* memory clock */
322 	mpll->min_post_div = 1;
323 	mpll->max_post_div = 1;
324 	mpll->min_ref_div = 2;
325 	mpll->max_ref_div = 0xff;
326 	mpll->min_feedback_div = 4;
327 	mpll->max_feedback_div = 0xff;
328 	mpll->best_vco = 0;
329 
330 }
331 
332 /* 10 khz */
333 static uint32_t calc_eng_mem_clock(struct radeon_device *rdev,
334 				   uint32_t req_clock,
335 				   int *fb_div, int *post_div)
336 {
337 	struct radeon_pll *spll = &rdev->clock.spll;
338 	int ref_div = spll->reference_div;
339 
340 	if (!ref_div)
341 		ref_div =
342 		    RREG32_PLL(RADEON_M_SPLL_REF_FB_DIV) &
343 		    RADEON_M_SPLL_REF_DIV_MASK;
344 
345 	if (req_clock < 15000) {
346 		*post_div = 8;
347 		req_clock *= 8;
348 	} else if (req_clock < 30000) {
349 		*post_div = 4;
350 		req_clock *= 4;
351 	} else if (req_clock < 60000) {
352 		*post_div = 2;
353 		req_clock *= 2;
354 	} else
355 		*post_div = 1;
356 
357 	req_clock *= ref_div;
358 	req_clock += spll->reference_freq;
359 	req_clock /= (2 * spll->reference_freq);
360 
361 	*fb_div = req_clock & 0xff;
362 
363 	req_clock = (req_clock & 0xffff) << 1;
364 	req_clock *= spll->reference_freq;
365 	req_clock /= ref_div;
366 	req_clock /= *post_div;
367 
368 	return req_clock;
369 }
370 
371 /* 10 khz */
372 void radeon_legacy_set_engine_clock(struct radeon_device *rdev,
373 				    uint32_t eng_clock)
374 {
375 	uint32_t tmp;
376 	int fb_div, post_div;
377 
378 	/* XXX: wait for idle */
379 
380 	eng_clock = calc_eng_mem_clock(rdev, eng_clock, &fb_div, &post_div);
381 
382 	tmp = RREG32_PLL(RADEON_CLK_PIN_CNTL);
383 	tmp &= ~RADEON_DONT_USE_XTALIN;
384 	WREG32_PLL(RADEON_CLK_PIN_CNTL, tmp);
385 
386 	tmp = RREG32_PLL(RADEON_SCLK_CNTL);
387 	tmp &= ~RADEON_SCLK_SRC_SEL_MASK;
388 	WREG32_PLL(RADEON_SCLK_CNTL, tmp);
389 
390 	udelay(10);
391 
392 	tmp = RREG32_PLL(RADEON_SPLL_CNTL);
393 	tmp |= RADEON_SPLL_SLEEP;
394 	WREG32_PLL(RADEON_SPLL_CNTL, tmp);
395 
396 	udelay(2);
397 
398 	tmp = RREG32_PLL(RADEON_SPLL_CNTL);
399 	tmp |= RADEON_SPLL_RESET;
400 	WREG32_PLL(RADEON_SPLL_CNTL, tmp);
401 
402 	udelay(200);
403 
404 	tmp = RREG32_PLL(RADEON_M_SPLL_REF_FB_DIV);
405 	tmp &= ~(RADEON_SPLL_FB_DIV_MASK << RADEON_SPLL_FB_DIV_SHIFT);
406 	tmp |= (fb_div & RADEON_SPLL_FB_DIV_MASK) << RADEON_SPLL_FB_DIV_SHIFT;
407 	WREG32_PLL(RADEON_M_SPLL_REF_FB_DIV, tmp);
408 
409 	/* XXX: verify on different asics */
410 	tmp = RREG32_PLL(RADEON_SPLL_CNTL);
411 	tmp &= ~RADEON_SPLL_PVG_MASK;
412 	if ((eng_clock * post_div) >= 90000)
413 		tmp |= (0x7 << RADEON_SPLL_PVG_SHIFT);
414 	else
415 		tmp |= (0x4 << RADEON_SPLL_PVG_SHIFT);
416 	WREG32_PLL(RADEON_SPLL_CNTL, tmp);
417 
418 	tmp = RREG32_PLL(RADEON_SPLL_CNTL);
419 	tmp &= ~RADEON_SPLL_SLEEP;
420 	WREG32_PLL(RADEON_SPLL_CNTL, tmp);
421 
422 	udelay(2);
423 
424 	tmp = RREG32_PLL(RADEON_SPLL_CNTL);
425 	tmp &= ~RADEON_SPLL_RESET;
426 	WREG32_PLL(RADEON_SPLL_CNTL, tmp);
427 
428 	udelay(200);
429 
430 	tmp = RREG32_PLL(RADEON_SCLK_CNTL);
431 	tmp &= ~RADEON_SCLK_SRC_SEL_MASK;
432 	switch (post_div) {
433 	case 1:
434 	default:
435 		tmp |= 1;
436 		break;
437 	case 2:
438 		tmp |= 2;
439 		break;
440 	case 4:
441 		tmp |= 3;
442 		break;
443 	case 8:
444 		tmp |= 4;
445 		break;
446 	}
447 	WREG32_PLL(RADEON_SCLK_CNTL, tmp);
448 
449 	udelay(20);
450 
451 	tmp = RREG32_PLL(RADEON_CLK_PIN_CNTL);
452 	tmp |= RADEON_DONT_USE_XTALIN;
453 	WREG32_PLL(RADEON_CLK_PIN_CNTL, tmp);
454 
455 	udelay(10);
456 }
457 
458 void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enable)
459 {
460 	uint32_t tmp;
461 
462 	if (enable) {
463 		if (rdev->flags & RADEON_SINGLE_CRTC) {
464 			tmp = RREG32_PLL(RADEON_SCLK_CNTL);
465 			if ((RREG32(RADEON_CONFIG_CNTL) &
466 			     RADEON_CFG_ATI_REV_ID_MASK) >
467 			    RADEON_CFG_ATI_REV_A13) {
468 				tmp &=
469 				    ~(RADEON_SCLK_FORCE_CP |
470 				      RADEON_SCLK_FORCE_RB);
471 			}
472 			tmp &=
473 			    ~(RADEON_SCLK_FORCE_HDP | RADEON_SCLK_FORCE_DISP1 |
474 			      RADEON_SCLK_FORCE_TOP | RADEON_SCLK_FORCE_SE |
475 			      RADEON_SCLK_FORCE_IDCT | RADEON_SCLK_FORCE_RE |
476 			      RADEON_SCLK_FORCE_PB | RADEON_SCLK_FORCE_TAM |
477 			      RADEON_SCLK_FORCE_TDM);
478 			WREG32_PLL(RADEON_SCLK_CNTL, tmp);
479 		} else if (ASIC_IS_R300(rdev)) {
480 			if ((rdev->family == CHIP_RS400) ||
481 			    (rdev->family == CHIP_RS480)) {
482 				tmp = RREG32_PLL(RADEON_SCLK_CNTL);
483 				tmp &=
484 				    ~(RADEON_SCLK_FORCE_DISP2 |
485 				      RADEON_SCLK_FORCE_CP |
486 				      RADEON_SCLK_FORCE_HDP |
487 				      RADEON_SCLK_FORCE_DISP1 |
488 				      RADEON_SCLK_FORCE_TOP |
489 				      RADEON_SCLK_FORCE_E2 | R300_SCLK_FORCE_VAP
490 				      | RADEON_SCLK_FORCE_IDCT |
491 				      RADEON_SCLK_FORCE_VIP | R300_SCLK_FORCE_SR
492 				      | R300_SCLK_FORCE_PX | R300_SCLK_FORCE_TX
493 				      | R300_SCLK_FORCE_US |
494 				      RADEON_SCLK_FORCE_TV_SCLK |
495 				      R300_SCLK_FORCE_SU |
496 				      RADEON_SCLK_FORCE_OV0);
497 				tmp |= RADEON_DYN_STOP_LAT_MASK;
498 				tmp |=
499 				    RADEON_SCLK_FORCE_TOP |
500 				    RADEON_SCLK_FORCE_VIP;
501 				WREG32_PLL(RADEON_SCLK_CNTL, tmp);
502 
503 				tmp = RREG32_PLL(RADEON_SCLK_MORE_CNTL);
504 				tmp &= ~RADEON_SCLK_MORE_FORCEON;
505 				tmp |= RADEON_SCLK_MORE_MAX_DYN_STOP_LAT;
506 				WREG32_PLL(RADEON_SCLK_MORE_CNTL, tmp);
507 
508 				tmp = RREG32_PLL(RADEON_VCLK_ECP_CNTL);
509 				tmp |= (RADEON_PIXCLK_ALWAYS_ONb |
510 					RADEON_PIXCLK_DAC_ALWAYS_ONb);
511 				WREG32_PLL(RADEON_VCLK_ECP_CNTL, tmp);
512 
513 				tmp = RREG32_PLL(RADEON_PIXCLKS_CNTL);
514 				tmp |= (RADEON_PIX2CLK_ALWAYS_ONb |
515 					RADEON_PIX2CLK_DAC_ALWAYS_ONb |
516 					RADEON_DISP_TVOUT_PIXCLK_TV_ALWAYS_ONb |
517 					R300_DVOCLK_ALWAYS_ONb |
518 					RADEON_PIXCLK_BLEND_ALWAYS_ONb |
519 					RADEON_PIXCLK_GV_ALWAYS_ONb |
520 					R300_PIXCLK_DVO_ALWAYS_ONb |
521 					RADEON_PIXCLK_LVDS_ALWAYS_ONb |
522 					RADEON_PIXCLK_TMDS_ALWAYS_ONb |
523 					R300_PIXCLK_TRANS_ALWAYS_ONb |
524 					R300_PIXCLK_TVO_ALWAYS_ONb |
525 					R300_P2G2CLK_ALWAYS_ONb |
526 					R300_P2G2CLK_DAC_ALWAYS_ONb);
527 				WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp);
528 			} else if (rdev->family >= CHIP_RV350) {
529 				tmp = RREG32_PLL(R300_SCLK_CNTL2);
530 				tmp &= ~(R300_SCLK_FORCE_TCL |
531 					 R300_SCLK_FORCE_GA |
532 					 R300_SCLK_FORCE_CBA);
533 				tmp |= (R300_SCLK_TCL_MAX_DYN_STOP_LAT |
534 					R300_SCLK_GA_MAX_DYN_STOP_LAT |
535 					R300_SCLK_CBA_MAX_DYN_STOP_LAT);
536 				WREG32_PLL(R300_SCLK_CNTL2, tmp);
537 
538 				tmp = RREG32_PLL(RADEON_SCLK_CNTL);
539 				tmp &=
540 				    ~(RADEON_SCLK_FORCE_DISP2 |
541 				      RADEON_SCLK_FORCE_CP |
542 				      RADEON_SCLK_FORCE_HDP |
543 				      RADEON_SCLK_FORCE_DISP1 |
544 				      RADEON_SCLK_FORCE_TOP |
545 				      RADEON_SCLK_FORCE_E2 | R300_SCLK_FORCE_VAP
546 				      | RADEON_SCLK_FORCE_IDCT |
547 				      RADEON_SCLK_FORCE_VIP | R300_SCLK_FORCE_SR
548 				      | R300_SCLK_FORCE_PX | R300_SCLK_FORCE_TX
549 				      | R300_SCLK_FORCE_US |
550 				      RADEON_SCLK_FORCE_TV_SCLK |
551 				      R300_SCLK_FORCE_SU |
552 				      RADEON_SCLK_FORCE_OV0);
553 				tmp |= RADEON_DYN_STOP_LAT_MASK;
554 				WREG32_PLL(RADEON_SCLK_CNTL, tmp);
555 
556 				tmp = RREG32_PLL(RADEON_SCLK_MORE_CNTL);
557 				tmp &= ~RADEON_SCLK_MORE_FORCEON;
558 				tmp |= RADEON_SCLK_MORE_MAX_DYN_STOP_LAT;
559 				WREG32_PLL(RADEON_SCLK_MORE_CNTL, tmp);
560 
561 				tmp = RREG32_PLL(RADEON_VCLK_ECP_CNTL);
562 				tmp |= (RADEON_PIXCLK_ALWAYS_ONb |
563 					RADEON_PIXCLK_DAC_ALWAYS_ONb);
564 				WREG32_PLL(RADEON_VCLK_ECP_CNTL, tmp);
565 
566 				tmp = RREG32_PLL(RADEON_PIXCLKS_CNTL);
567 				tmp |= (RADEON_PIX2CLK_ALWAYS_ONb |
568 					RADEON_PIX2CLK_DAC_ALWAYS_ONb |
569 					RADEON_DISP_TVOUT_PIXCLK_TV_ALWAYS_ONb |
570 					R300_DVOCLK_ALWAYS_ONb |
571 					RADEON_PIXCLK_BLEND_ALWAYS_ONb |
572 					RADEON_PIXCLK_GV_ALWAYS_ONb |
573 					R300_PIXCLK_DVO_ALWAYS_ONb |
574 					RADEON_PIXCLK_LVDS_ALWAYS_ONb |
575 					RADEON_PIXCLK_TMDS_ALWAYS_ONb |
576 					R300_PIXCLK_TRANS_ALWAYS_ONb |
577 					R300_PIXCLK_TVO_ALWAYS_ONb |
578 					R300_P2G2CLK_ALWAYS_ONb |
579 					R300_P2G2CLK_DAC_ALWAYS_ONb);
580 				WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp);
581 
582 				tmp = RREG32_PLL(RADEON_MCLK_MISC);
583 				tmp |= (RADEON_MC_MCLK_DYN_ENABLE |
584 					RADEON_IO_MCLK_DYN_ENABLE);
585 				WREG32_PLL(RADEON_MCLK_MISC, tmp);
586 
587 				tmp = RREG32_PLL(RADEON_MCLK_CNTL);
588 				tmp |= (RADEON_FORCEON_MCLKA |
589 					RADEON_FORCEON_MCLKB);
590 
591 				tmp &= ~(RADEON_FORCEON_YCLKA |
592 					 RADEON_FORCEON_YCLKB |
593 					 RADEON_FORCEON_MC);
594 
595 				/* Some releases of vbios have set DISABLE_MC_MCLKA
596 				   and DISABLE_MC_MCLKB bits in the vbios table.  Setting these
597 				   bits will cause H/W hang when reading video memory with dynamic clocking
598 				   enabled. */
599 				if ((tmp & R300_DISABLE_MC_MCLKA) &&
600 				    (tmp & R300_DISABLE_MC_MCLKB)) {
601 					/* If both bits are set, then check the active channels */
602 					tmp = RREG32_PLL(RADEON_MCLK_CNTL);
603 					if (rdev->mc.vram_width == 64) {
604 						if (RREG32(RADEON_MEM_CNTL) &
605 						    R300_MEM_USE_CD_CH_ONLY)
606 							tmp &=
607 							    ~R300_DISABLE_MC_MCLKB;
608 						else
609 							tmp &=
610 							    ~R300_DISABLE_MC_MCLKA;
611 					} else {
612 						tmp &= ~(R300_DISABLE_MC_MCLKA |
613 							 R300_DISABLE_MC_MCLKB);
614 					}
615 				}
616 
617 				WREG32_PLL(RADEON_MCLK_CNTL, tmp);
618 			} else {
619 				tmp = RREG32_PLL(RADEON_SCLK_CNTL);
620 				tmp &= ~(R300_SCLK_FORCE_VAP);
621 				tmp |= RADEON_SCLK_FORCE_CP;
622 				WREG32_PLL(RADEON_SCLK_CNTL, tmp);
623 				udelay(15000);
624 
625 				tmp = RREG32_PLL(R300_SCLK_CNTL2);
626 				tmp &= ~(R300_SCLK_FORCE_TCL |
627 					 R300_SCLK_FORCE_GA |
628 					 R300_SCLK_FORCE_CBA);
629 				WREG32_PLL(R300_SCLK_CNTL2, tmp);
630 			}
631 		} else {
632 			tmp = RREG32_PLL(RADEON_CLK_PWRMGT_CNTL);
633 
634 			tmp &= ~(RADEON_ACTIVE_HILO_LAT_MASK |
635 				 RADEON_DISP_DYN_STOP_LAT_MASK |
636 				 RADEON_DYN_STOP_MODE_MASK);
637 
638 			tmp |= (RADEON_ENGIN_DYNCLK_MODE |
639 				(0x01 << RADEON_ACTIVE_HILO_LAT_SHIFT));
640 			WREG32_PLL(RADEON_CLK_PWRMGT_CNTL, tmp);
641 			udelay(15000);
642 
643 			tmp = RREG32_PLL(RADEON_CLK_PIN_CNTL);
644 			tmp |= RADEON_SCLK_DYN_START_CNTL;
645 			WREG32_PLL(RADEON_CLK_PIN_CNTL, tmp);
646 			udelay(15000);
647 
648 			/* When DRI is enabled, setting DYN_STOP_LAT to zero can cause some R200
649 			   to lockup randomly, leave them as set by BIOS.
650 			 */
651 			tmp = RREG32_PLL(RADEON_SCLK_CNTL);
652 			/*tmp &= RADEON_SCLK_SRC_SEL_MASK; */
653 			tmp &= ~RADEON_SCLK_FORCEON_MASK;
654 
655 			/*RAGE_6::A11 A12 A12N1 A13, RV250::A11 A12, R300 */
656 			if (((rdev->family == CHIP_RV250) &&
657 			     ((RREG32(RADEON_CONFIG_CNTL) &
658 			       RADEON_CFG_ATI_REV_ID_MASK) <
659 			      RADEON_CFG_ATI_REV_A13))
660 			    || ((rdev->family == CHIP_RV100)
661 				&&
662 				((RREG32(RADEON_CONFIG_CNTL) &
663 				  RADEON_CFG_ATI_REV_ID_MASK) <=
664 				 RADEON_CFG_ATI_REV_A13))) {
665 				tmp |= RADEON_SCLK_FORCE_CP;
666 				tmp |= RADEON_SCLK_FORCE_VIP;
667 			}
668 
669 			WREG32_PLL(RADEON_SCLK_CNTL, tmp);
670 
671 			if ((rdev->family == CHIP_RV200) ||
672 			    (rdev->family == CHIP_RV250) ||
673 			    (rdev->family == CHIP_RV280)) {
674 				tmp = RREG32_PLL(RADEON_SCLK_MORE_CNTL);
675 				tmp &= ~RADEON_SCLK_MORE_FORCEON;
676 
677 				/* RV200::A11 A12 RV250::A11 A12 */
678 				if (((rdev->family == CHIP_RV200) ||
679 				     (rdev->family == CHIP_RV250)) &&
680 				    ((RREG32(RADEON_CONFIG_CNTL) &
681 				      RADEON_CFG_ATI_REV_ID_MASK) <
682 				     RADEON_CFG_ATI_REV_A13)) {
683 					tmp |= RADEON_SCLK_MORE_FORCEON;
684 				}
685 				WREG32_PLL(RADEON_SCLK_MORE_CNTL, tmp);
686 				udelay(15000);
687 			}
688 
689 			/* RV200::A11 A12, RV250::A11 A12 */
690 			if (((rdev->family == CHIP_RV200) ||
691 			     (rdev->family == CHIP_RV250)) &&
692 			    ((RREG32(RADEON_CONFIG_CNTL) &
693 			      RADEON_CFG_ATI_REV_ID_MASK) <
694 			     RADEON_CFG_ATI_REV_A13)) {
695 				tmp = RREG32_PLL(RADEON_PLL_PWRMGT_CNTL);
696 				tmp |= RADEON_TCL_BYPASS_DISABLE;
697 				WREG32_PLL(RADEON_PLL_PWRMGT_CNTL, tmp);
698 			}
699 			udelay(15000);
700 
701 			/*enable dynamic mode for display clocks (PIXCLK and PIX2CLK) */
702 			tmp = RREG32_PLL(RADEON_PIXCLKS_CNTL);
703 			tmp |= (RADEON_PIX2CLK_ALWAYS_ONb |
704 				RADEON_PIX2CLK_DAC_ALWAYS_ONb |
705 				RADEON_PIXCLK_BLEND_ALWAYS_ONb |
706 				RADEON_PIXCLK_GV_ALWAYS_ONb |
707 				RADEON_PIXCLK_DIG_TMDS_ALWAYS_ONb |
708 				RADEON_PIXCLK_LVDS_ALWAYS_ONb |
709 				RADEON_PIXCLK_TMDS_ALWAYS_ONb);
710 
711 			WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp);
712 			udelay(15000);
713 
714 			tmp = RREG32_PLL(RADEON_VCLK_ECP_CNTL);
715 			tmp |= (RADEON_PIXCLK_ALWAYS_ONb |
716 				RADEON_PIXCLK_DAC_ALWAYS_ONb);
717 
718 			WREG32_PLL(RADEON_VCLK_ECP_CNTL, tmp);
719 			udelay(15000);
720 		}
721 	} else {
722 		/* Turn everything OFF (ForceON to everything) */
723 		if (rdev->flags & RADEON_SINGLE_CRTC) {
724 			tmp = RREG32_PLL(RADEON_SCLK_CNTL);
725 			tmp |= (RADEON_SCLK_FORCE_CP | RADEON_SCLK_FORCE_HDP |
726 				RADEON_SCLK_FORCE_DISP1 | RADEON_SCLK_FORCE_TOP
727 				| RADEON_SCLK_FORCE_E2 | RADEON_SCLK_FORCE_SE |
728 				RADEON_SCLK_FORCE_IDCT | RADEON_SCLK_FORCE_VIP |
729 				RADEON_SCLK_FORCE_RE | RADEON_SCLK_FORCE_PB |
730 				RADEON_SCLK_FORCE_TAM | RADEON_SCLK_FORCE_TDM |
731 				RADEON_SCLK_FORCE_RB);
732 			WREG32_PLL(RADEON_SCLK_CNTL, tmp);
733 		} else if ((rdev->family == CHIP_RS400) ||
734 			   (rdev->family == CHIP_RS480)) {
735 			tmp = RREG32_PLL(RADEON_SCLK_CNTL);
736 			tmp |= (RADEON_SCLK_FORCE_DISP2 | RADEON_SCLK_FORCE_CP |
737 				RADEON_SCLK_FORCE_HDP | RADEON_SCLK_FORCE_DISP1
738 				| RADEON_SCLK_FORCE_TOP | RADEON_SCLK_FORCE_E2 |
739 				R300_SCLK_FORCE_VAP | RADEON_SCLK_FORCE_IDCT |
740 				RADEON_SCLK_FORCE_VIP | R300_SCLK_FORCE_SR |
741 				R300_SCLK_FORCE_PX | R300_SCLK_FORCE_TX |
742 				R300_SCLK_FORCE_US | RADEON_SCLK_FORCE_TV_SCLK |
743 				R300_SCLK_FORCE_SU | RADEON_SCLK_FORCE_OV0);
744 			WREG32_PLL(RADEON_SCLK_CNTL, tmp);
745 
746 			tmp = RREG32_PLL(RADEON_SCLK_MORE_CNTL);
747 			tmp |= RADEON_SCLK_MORE_FORCEON;
748 			WREG32_PLL(RADEON_SCLK_MORE_CNTL, tmp);
749 
750 			tmp = RREG32_PLL(RADEON_VCLK_ECP_CNTL);
751 			tmp &= ~(RADEON_PIXCLK_ALWAYS_ONb |
752 				 RADEON_PIXCLK_DAC_ALWAYS_ONb |
753 				 R300_DISP_DAC_PIXCLK_DAC_BLANK_OFF);
754 			WREG32_PLL(RADEON_VCLK_ECP_CNTL, tmp);
755 
756 			tmp = RREG32_PLL(RADEON_PIXCLKS_CNTL);
757 			tmp &= ~(RADEON_PIX2CLK_ALWAYS_ONb |
758 				 RADEON_PIX2CLK_DAC_ALWAYS_ONb |
759 				 RADEON_DISP_TVOUT_PIXCLK_TV_ALWAYS_ONb |
760 				 R300_DVOCLK_ALWAYS_ONb |
761 				 RADEON_PIXCLK_BLEND_ALWAYS_ONb |
762 				 RADEON_PIXCLK_GV_ALWAYS_ONb |
763 				 R300_PIXCLK_DVO_ALWAYS_ONb |
764 				 RADEON_PIXCLK_LVDS_ALWAYS_ONb |
765 				 RADEON_PIXCLK_TMDS_ALWAYS_ONb |
766 				 R300_PIXCLK_TRANS_ALWAYS_ONb |
767 				 R300_PIXCLK_TVO_ALWAYS_ONb |
768 				 R300_P2G2CLK_ALWAYS_ONb |
769 				 R300_P2G2CLK_DAC_ALWAYS_ONb |
770 				 R300_DISP_DAC_PIXCLK_DAC2_BLANK_OFF);
771 			WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp);
772 		} else if (rdev->family >= CHIP_RV350) {
773 			/* for RV350/M10, no delays are required. */
774 			tmp = RREG32_PLL(R300_SCLK_CNTL2);
775 			tmp |= (R300_SCLK_FORCE_TCL |
776 				R300_SCLK_FORCE_GA | R300_SCLK_FORCE_CBA);
777 			WREG32_PLL(R300_SCLK_CNTL2, tmp);
778 
779 			tmp = RREG32_PLL(RADEON_SCLK_CNTL);
780 			tmp |= (RADEON_SCLK_FORCE_DISP2 | RADEON_SCLK_FORCE_CP |
781 				RADEON_SCLK_FORCE_HDP | RADEON_SCLK_FORCE_DISP1
782 				| RADEON_SCLK_FORCE_TOP | RADEON_SCLK_FORCE_E2 |
783 				R300_SCLK_FORCE_VAP | RADEON_SCLK_FORCE_IDCT |
784 				RADEON_SCLK_FORCE_VIP | R300_SCLK_FORCE_SR |
785 				R300_SCLK_FORCE_PX | R300_SCLK_FORCE_TX |
786 				R300_SCLK_FORCE_US | RADEON_SCLK_FORCE_TV_SCLK |
787 				R300_SCLK_FORCE_SU | RADEON_SCLK_FORCE_OV0);
788 			WREG32_PLL(RADEON_SCLK_CNTL, tmp);
789 
790 			tmp = RREG32_PLL(RADEON_SCLK_MORE_CNTL);
791 			tmp |= RADEON_SCLK_MORE_FORCEON;
792 			WREG32_PLL(RADEON_SCLK_MORE_CNTL, tmp);
793 
794 			tmp = RREG32_PLL(RADEON_MCLK_CNTL);
795 			tmp |= (RADEON_FORCEON_MCLKA |
796 				RADEON_FORCEON_MCLKB |
797 				RADEON_FORCEON_YCLKA |
798 				RADEON_FORCEON_YCLKB | RADEON_FORCEON_MC);
799 			WREG32_PLL(RADEON_MCLK_CNTL, tmp);
800 
801 			tmp = RREG32_PLL(RADEON_VCLK_ECP_CNTL);
802 			tmp &= ~(RADEON_PIXCLK_ALWAYS_ONb |
803 				 RADEON_PIXCLK_DAC_ALWAYS_ONb |
804 				 R300_DISP_DAC_PIXCLK_DAC_BLANK_OFF);
805 			WREG32_PLL(RADEON_VCLK_ECP_CNTL, tmp);
806 
807 			tmp = RREG32_PLL(RADEON_PIXCLKS_CNTL);
808 			tmp &= ~(RADEON_PIX2CLK_ALWAYS_ONb |
809 				 RADEON_PIX2CLK_DAC_ALWAYS_ONb |
810 				 RADEON_DISP_TVOUT_PIXCLK_TV_ALWAYS_ONb |
811 				 R300_DVOCLK_ALWAYS_ONb |
812 				 RADEON_PIXCLK_BLEND_ALWAYS_ONb |
813 				 RADEON_PIXCLK_GV_ALWAYS_ONb |
814 				 R300_PIXCLK_DVO_ALWAYS_ONb |
815 				 RADEON_PIXCLK_LVDS_ALWAYS_ONb |
816 				 RADEON_PIXCLK_TMDS_ALWAYS_ONb |
817 				 R300_PIXCLK_TRANS_ALWAYS_ONb |
818 				 R300_PIXCLK_TVO_ALWAYS_ONb |
819 				 R300_P2G2CLK_ALWAYS_ONb |
820 				 R300_P2G2CLK_DAC_ALWAYS_ONb |
821 				 R300_DISP_DAC_PIXCLK_DAC2_BLANK_OFF);
822 			WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp);
823 		} else {
824 			tmp = RREG32_PLL(RADEON_SCLK_CNTL);
825 			tmp |= (RADEON_SCLK_FORCE_CP | RADEON_SCLK_FORCE_E2);
826 			tmp |= RADEON_SCLK_FORCE_SE;
827 
828 			if (rdev->flags & RADEON_SINGLE_CRTC) {
829 				tmp |= (RADEON_SCLK_FORCE_RB |
830 					RADEON_SCLK_FORCE_TDM |
831 					RADEON_SCLK_FORCE_TAM |
832 					RADEON_SCLK_FORCE_PB |
833 					RADEON_SCLK_FORCE_RE |
834 					RADEON_SCLK_FORCE_VIP |
835 					RADEON_SCLK_FORCE_IDCT |
836 					RADEON_SCLK_FORCE_TOP |
837 					RADEON_SCLK_FORCE_DISP1 |
838 					RADEON_SCLK_FORCE_DISP2 |
839 					RADEON_SCLK_FORCE_HDP);
840 			} else if ((rdev->family == CHIP_R300) ||
841 				   (rdev->family == CHIP_R350)) {
842 				tmp |= (RADEON_SCLK_FORCE_HDP |
843 					RADEON_SCLK_FORCE_DISP1 |
844 					RADEON_SCLK_FORCE_DISP2 |
845 					RADEON_SCLK_FORCE_TOP |
846 					RADEON_SCLK_FORCE_IDCT |
847 					RADEON_SCLK_FORCE_VIP);
848 			}
849 			WREG32_PLL(RADEON_SCLK_CNTL, tmp);
850 
851 			udelay(16000);
852 
853 			if ((rdev->family == CHIP_R300) ||
854 			    (rdev->family == CHIP_R350)) {
855 				tmp = RREG32_PLL(R300_SCLK_CNTL2);
856 				tmp |= (R300_SCLK_FORCE_TCL |
857 					R300_SCLK_FORCE_GA |
858 					R300_SCLK_FORCE_CBA);
859 				WREG32_PLL(R300_SCLK_CNTL2, tmp);
860 				udelay(16000);
861 			}
862 
863 			if (rdev->flags & RADEON_IS_IGP) {
864 				tmp = RREG32_PLL(RADEON_MCLK_CNTL);
865 				tmp &= ~(RADEON_FORCEON_MCLKA |
866 					 RADEON_FORCEON_YCLKA);
867 				WREG32_PLL(RADEON_MCLK_CNTL, tmp);
868 				udelay(16000);
869 			}
870 
871 			if ((rdev->family == CHIP_RV200) ||
872 			    (rdev->family == CHIP_RV250) ||
873 			    (rdev->family == CHIP_RV280)) {
874 				tmp = RREG32_PLL(RADEON_SCLK_MORE_CNTL);
875 				tmp |= RADEON_SCLK_MORE_FORCEON;
876 				WREG32_PLL(RADEON_SCLK_MORE_CNTL, tmp);
877 				udelay(16000);
878 			}
879 
880 			tmp = RREG32_PLL(RADEON_PIXCLKS_CNTL);
881 			tmp &= ~(RADEON_PIX2CLK_ALWAYS_ONb |
882 				 RADEON_PIX2CLK_DAC_ALWAYS_ONb |
883 				 RADEON_PIXCLK_BLEND_ALWAYS_ONb |
884 				 RADEON_PIXCLK_GV_ALWAYS_ONb |
885 				 RADEON_PIXCLK_DIG_TMDS_ALWAYS_ONb |
886 				 RADEON_PIXCLK_LVDS_ALWAYS_ONb |
887 				 RADEON_PIXCLK_TMDS_ALWAYS_ONb);
888 
889 			WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp);
890 			udelay(16000);
891 
892 			tmp = RREG32_PLL(RADEON_VCLK_ECP_CNTL);
893 			tmp &= ~(RADEON_PIXCLK_ALWAYS_ONb |
894 				 RADEON_PIXCLK_DAC_ALWAYS_ONb);
895 			WREG32_PLL(RADEON_VCLK_ECP_CNTL, tmp);
896 		}
897 	}
898 }
899 
900 static void radeon_apply_clock_quirks(struct radeon_device *rdev)
901 {
902 	uint32_t tmp;
903 
904 	/* XXX make sure engine is idle */
905 
906 	if (rdev->family < CHIP_RS600) {
907 		tmp = RREG32_PLL(RADEON_SCLK_CNTL);
908 		if (ASIC_IS_R300(rdev) || ASIC_IS_RV100(rdev))
909 			tmp |= RADEON_SCLK_FORCE_CP | RADEON_SCLK_FORCE_VIP;
910 		if ((rdev->family == CHIP_RV250)
911 		    || (rdev->family == CHIP_RV280))
912 			tmp |=
913 			    RADEON_SCLK_FORCE_DISP1 | RADEON_SCLK_FORCE_DISP2;
914 		if ((rdev->family == CHIP_RV350)
915 		    || (rdev->family == CHIP_RV380))
916 			tmp |= R300_SCLK_FORCE_VAP;
917 		if (rdev->family == CHIP_R420)
918 			tmp |= R300_SCLK_FORCE_PX | R300_SCLK_FORCE_TX;
919 		WREG32_PLL(RADEON_SCLK_CNTL, tmp);
920 	} else if (rdev->family < CHIP_R600) {
921 		tmp = RREG32_PLL(AVIVO_CP_DYN_CNTL);
922 		tmp |= AVIVO_CP_FORCEON;
923 		WREG32_PLL(AVIVO_CP_DYN_CNTL, tmp);
924 
925 		tmp = RREG32_PLL(AVIVO_E2_DYN_CNTL);
926 		tmp |= AVIVO_E2_FORCEON;
927 		WREG32_PLL(AVIVO_E2_DYN_CNTL, tmp);
928 
929 		tmp = RREG32_PLL(AVIVO_IDCT_DYN_CNTL);
930 		tmp |= AVIVO_IDCT_FORCEON;
931 		WREG32_PLL(AVIVO_IDCT_DYN_CNTL, tmp);
932 	}
933 }
934 
935 int radeon_static_clocks_init(struct drm_device *dev)
936 {
937 	struct radeon_device *rdev = dev->dev_private;
938 
939 	/* XXX make sure engine is idle */
940 
941 	if (radeon_dynclks != -1) {
942 		if (radeon_dynclks) {
943 			if (rdev->asic->set_clock_gating)
944 				radeon_set_clock_gating(rdev, 1);
945 		}
946 	}
947 	radeon_apply_clock_quirks(rdev);
948 	return 0;
949 }
950