1ad43ddacSmrg/*
2ad43ddacSmrg * Copyright 2009 Advanced Micro Devices, Inc.
3ad43ddacSmrg *
4ad43ddacSmrg * All Rights Reserved.
5ad43ddacSmrg *
6ad43ddacSmrg * Permission is hereby granted, free of charge, to any person obtaining
7ad43ddacSmrg * a copy of this software and associated documentation files (the
8ad43ddacSmrg * "Software"), to deal in the Software without restriction, including
9ad43ddacSmrg * without limitation on the rights to use, copy, modify, merge,
10ad43ddacSmrg * publish, distribute, sublicense, and/or sell copies of the Software,
11ad43ddacSmrg * and to permit persons to whom the Software is furnished to do so,
12ad43ddacSmrg * subject to the following conditions:
13ad43ddacSmrg *
14ad43ddacSmrg * The above copyright notice and this permission notice (including the
15ad43ddacSmrg * next paragraph) shall be included in all copies or substantial
16ad43ddacSmrg * portions of the Software.
17ad43ddacSmrg *
18ad43ddacSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19ad43ddacSmrg * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20ad43ddacSmrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21ad43ddacSmrg * NON-INFRINGEMENT.  IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR
22ad43ddacSmrg * AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23ad43ddacSmrg * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24ad43ddacSmrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25ad43ddacSmrg * DEALINGS IN THE SOFTWARE.
26ad43ddacSmrg *
27ad43ddacSmrg * Author: Alex Deucher <alexander.deucher@amd.com>
28ad43ddacSmrg *
29ad43ddacSmrg */
30ad43ddacSmrg
31ad43ddacSmrg#ifdef HAVE_CONFIG_H
32ad43ddacSmrg#include "config.h"
33ad43ddacSmrg#endif
34ad43ddacSmrg
35ad43ddacSmrg				/* Driver data structures */
36ad43ddacSmrg#include "radeon.h"
37ad43ddacSmrg#include "radeon_reg.h"
38ad43ddacSmrg#include "radeon_macros.h"
39ad43ddacSmrg#include "radeon_atombios.h"
40ad43ddacSmrg
41ad43ddacSmrg#include "ati_pciids_gen.h"
42ad43ddacSmrg
43ad43ddacSmrg/* 10 khz */
44ad43ddacSmrgstatic uint32_t calc_eng_mem_clock(ScrnInfoPtr pScrn,
45ad43ddacSmrg				   uint32_t req_clock,
46ad43ddacSmrg				   int ref_div,
47ad43ddacSmrg				   int *fb_div,
48ad43ddacSmrg				   int *post_div)
49ad43ddacSmrg{
50ad43ddacSmrg    RADEONInfoPtr info = RADEONPTR(pScrn);
51ad43ddacSmrg    RADEONPLLPtr pll = &info->pll;
52ad43ddacSmrg
53ad43ddacSmrg    if (req_clock < 15000) {
54ad43ddacSmrg	*post_div = 8;
55ad43ddacSmrg	req_clock *= 8;
56ad43ddacSmrg    } else if (req_clock < 30000) {
57ad43ddacSmrg	*post_div = 4;
58ad43ddacSmrg	req_clock *= 4;
59ad43ddacSmrg    } else if (req_clock < 60000) {
60ad43ddacSmrg	*post_div = 2;
61ad43ddacSmrg	req_clock *= 2;
62ad43ddacSmrg    } else
63ad43ddacSmrg	*post_div = 1;
64ad43ddacSmrg
65ad43ddacSmrg    req_clock *= ref_div;
66ad43ddacSmrg    req_clock += pll->reference_freq;
67ad43ddacSmrg    req_clock /= (2 * pll->reference_freq);
68ad43ddacSmrg
69ad43ddacSmrg    *fb_div = req_clock & 0xff;
70ad43ddacSmrg
71ad43ddacSmrg    req_clock = (req_clock & 0xffff) << 1;
72ad43ddacSmrg    req_clock *= pll->reference_freq;
73ad43ddacSmrg    req_clock /= ref_div;
74ad43ddacSmrg    req_clock /= *post_div;
75ad43ddacSmrg
76ad43ddacSmrg    return req_clock;
77ad43ddacSmrg
78ad43ddacSmrg}
79ad43ddacSmrg
80ad43ddacSmrgstatic void
81ad43ddacSmrgRADEONSetEngineClock(ScrnInfoPtr pScrn, uint32_t eng_clock)
82ad43ddacSmrg{
83ad43ddacSmrg    uint32_t tmp;
84ad43ddacSmrg    int ref_div, fb_div, post_div;
85ad43ddacSmrg
86ad43ddacSmrg    RADEONWaitForIdleMMIO(pScrn);
87ad43ddacSmrg
88ad43ddacSmrg    tmp = INPLL(pScrn, RADEON_M_SPLL_REF_FB_DIV);
89ad43ddacSmrg    ref_div = tmp & RADEON_M_SPLL_REF_DIV_MASK;
90ad43ddacSmrg
91ad43ddacSmrg    eng_clock = calc_eng_mem_clock(pScrn, eng_clock, ref_div, &fb_div, &post_div);
92ad43ddacSmrg
93ad43ddacSmrg    tmp = INPLL(pScrn, RADEON_CLK_PIN_CNTL);
94ad43ddacSmrg    tmp &= ~RADEON_DONT_USE_XTALIN;
95ad43ddacSmrg    OUTPLL(pScrn, RADEON_CLK_PIN_CNTL, tmp);
96ad43ddacSmrg
97ad43ddacSmrg    tmp = INPLL(pScrn, RADEON_SCLK_CNTL);
98ad43ddacSmrg    tmp &= ~RADEON_SCLK_SRC_SEL_MASK;
99ad43ddacSmrg    OUTPLL(pScrn, RADEON_SCLK_CNTL, tmp);
100ad43ddacSmrg
101ad43ddacSmrg    usleep(10);
102ad43ddacSmrg
103ad43ddacSmrg    tmp = INPLL(pScrn, RADEON_SPLL_CNTL);
104ad43ddacSmrg    tmp |= RADEON_SPLL_SLEEP;
105ad43ddacSmrg    OUTPLL(pScrn, RADEON_SPLL_CNTL, tmp);
106ad43ddacSmrg
107ad43ddacSmrg    usleep(2);
108ad43ddacSmrg
109ad43ddacSmrg    tmp = INPLL(pScrn, RADEON_SPLL_CNTL);
110ad43ddacSmrg    tmp |= RADEON_SPLL_RESET;
111ad43ddacSmrg    OUTPLL(pScrn, RADEON_SPLL_CNTL, tmp);
112ad43ddacSmrg
113ad43ddacSmrg    usleep(200);
114ad43ddacSmrg
115ad43ddacSmrg    tmp = INPLL(pScrn, RADEON_M_SPLL_REF_FB_DIV);
116ad43ddacSmrg    tmp &= ~(RADEON_SPLL_FB_DIV_MASK << RADEON_SPLL_FB_DIV_SHIFT);
117ad43ddacSmrg    tmp |= (fb_div & RADEON_SPLL_FB_DIV_MASK) << RADEON_SPLL_FB_DIV_SHIFT;
118ad43ddacSmrg    OUTPLL(pScrn, RADEON_M_SPLL_REF_FB_DIV, tmp);
119ad43ddacSmrg
120ad43ddacSmrg    /* XXX: verify on different asics */
121ad43ddacSmrg    tmp = INPLL(pScrn, RADEON_SPLL_CNTL);
122ad43ddacSmrg    tmp &= ~RADEON_SPLL_PVG_MASK;
123ad43ddacSmrg    if ((eng_clock * post_div) >= 90000)
124ad43ddacSmrg	tmp |= (0x7 << RADEON_SPLL_PVG_SHIFT);
125ad43ddacSmrg    else
126ad43ddacSmrg	tmp |= (0x4 << RADEON_SPLL_PVG_SHIFT);
127ad43ddacSmrg    OUTPLL(pScrn, RADEON_SPLL_CNTL, tmp);
128ad43ddacSmrg
129ad43ddacSmrg    tmp = INPLL(pScrn, RADEON_SPLL_CNTL);
130ad43ddacSmrg    tmp &= ~RADEON_SPLL_SLEEP;
131ad43ddacSmrg    OUTPLL(pScrn, RADEON_SPLL_CNTL, tmp);
132ad43ddacSmrg
133ad43ddacSmrg    usleep(2);
134ad43ddacSmrg
135ad43ddacSmrg    tmp = INPLL(pScrn, RADEON_SPLL_CNTL);
136ad43ddacSmrg    tmp &= ~RADEON_SPLL_RESET;
137ad43ddacSmrg    OUTPLL(pScrn, RADEON_SPLL_CNTL, tmp);
138ad43ddacSmrg
139ad43ddacSmrg    usleep(200);
140ad43ddacSmrg
141ad43ddacSmrg    tmp = INPLL(pScrn, RADEON_SCLK_CNTL);
142ad43ddacSmrg    tmp &= ~RADEON_SCLK_SRC_SEL_MASK;
143ad43ddacSmrg    switch (post_div) {
144ad43ddacSmrg    case 1:
145ad43ddacSmrg    default:
146ad43ddacSmrg	tmp |= 1;
147ad43ddacSmrg	break;
148ad43ddacSmrg    case 2:
149ad43ddacSmrg	tmp |= 2;
150ad43ddacSmrg	break;
151ad43ddacSmrg    case 4:
152ad43ddacSmrg	tmp |= 3;
153ad43ddacSmrg	break;
154ad43ddacSmrg    case 8:
155ad43ddacSmrg	tmp |= 4;
156ad43ddacSmrg	break;
157ad43ddacSmrg    }
158ad43ddacSmrg    OUTPLL(pScrn, RADEON_SCLK_CNTL, tmp);
159ad43ddacSmrg
160ad43ddacSmrg    usleep(20);
161ad43ddacSmrg
162ad43ddacSmrg    tmp = INPLL(pScrn, RADEON_CLK_PIN_CNTL);
163ad43ddacSmrg    tmp |= RADEON_DONT_USE_XTALIN;
164ad43ddacSmrg    OUTPLL(pScrn, RADEON_CLK_PIN_CNTL, tmp);
165ad43ddacSmrg
166ad43ddacSmrg    usleep(10);
167ad43ddacSmrg
168ad43ddacSmrg}
169ad43ddacSmrg
170ad43ddacSmrgstatic void LegacySetClockGating(ScrnInfoPtr pScrn, Bool enable)
171ad43ddacSmrg{
172ad43ddacSmrg    RADEONInfoPtr  info       = RADEONPTR(pScrn);
173ad43ddacSmrg    RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
174ad43ddacSmrg    unsigned char *RADEONMMIO = info->MMIO;
175ad43ddacSmrg    uint32_t tmp;
176ad43ddacSmrg
177ad43ddacSmrg    if (enable) {
178ad43ddacSmrg	if (!pRADEONEnt->HasCRTC2) {
179ad43ddacSmrg	    tmp = INPLL(pScrn, RADEON_SCLK_CNTL);
180ad43ddacSmrg	    if ((INREG(RADEON_CONFIG_CNTL) & RADEON_CFG_ATI_REV_ID_MASK) >
181ad43ddacSmrg		RADEON_CFG_ATI_REV_A13) {
182ad43ddacSmrg		tmp &= ~(RADEON_SCLK_FORCE_CP | RADEON_SCLK_FORCE_RB);
183ad43ddacSmrg	    }
184ad43ddacSmrg	    tmp &= ~(RADEON_SCLK_FORCE_HDP  | RADEON_SCLK_FORCE_DISP1 |
185ad43ddacSmrg		     RADEON_SCLK_FORCE_TOP  | RADEON_SCLK_FORCE_SE   |
186ad43ddacSmrg		     RADEON_SCLK_FORCE_IDCT | RADEON_SCLK_FORCE_RE   |
187ad43ddacSmrg		     RADEON_SCLK_FORCE_PB   | RADEON_SCLK_FORCE_TAM  |
188ad43ddacSmrg		     RADEON_SCLK_FORCE_TDM);
189ad43ddacSmrg	    OUTPLL(pScrn, RADEON_SCLK_CNTL, tmp);
190ad43ddacSmrg	} else if (IS_R300_VARIANT) {
191ad43ddacSmrg	    if ((info->ChipFamily == CHIP_FAMILY_RS400) ||
192ad43ddacSmrg		(info->ChipFamily == CHIP_FAMILY_RS480)) {
193ad43ddacSmrg		tmp = INPLL(pScrn, RADEON_SCLK_CNTL);
194ad43ddacSmrg		tmp &= ~(RADEON_SCLK_FORCE_DISP2 | RADEON_SCLK_FORCE_CP      |
195ad43ddacSmrg			 RADEON_SCLK_FORCE_HDP   | RADEON_SCLK_FORCE_DISP1   |
196ad43ddacSmrg			 RADEON_SCLK_FORCE_TOP   | RADEON_SCLK_FORCE_E2      |
197ad43ddacSmrg			 R300_SCLK_FORCE_VAP     | RADEON_SCLK_FORCE_IDCT    |
198ad43ddacSmrg			 RADEON_SCLK_FORCE_VIP   | R300_SCLK_FORCE_SR        |
199ad43ddacSmrg			 R300_SCLK_FORCE_PX      | R300_SCLK_FORCE_TX        |
200ad43ddacSmrg			 R300_SCLK_FORCE_US      | RADEON_SCLK_FORCE_TV_SCLK |
201ad43ddacSmrg			 R300_SCLK_FORCE_SU      | RADEON_SCLK_FORCE_OV0);
202ad43ddacSmrg		tmp |=  RADEON_DYN_STOP_LAT_MASK;
203ad43ddacSmrg		tmp |= RADEON_SCLK_FORCE_TOP | RADEON_SCLK_FORCE_VIP;
204ad43ddacSmrg		OUTPLL(pScrn, RADEON_SCLK_CNTL, tmp);
205ad43ddacSmrg
206ad43ddacSmrg		tmp = INPLL(pScrn, RADEON_SCLK_MORE_CNTL);
207ad43ddacSmrg		tmp &= ~RADEON_SCLK_MORE_FORCEON;
208ad43ddacSmrg		tmp |=  RADEON_SCLK_MORE_MAX_DYN_STOP_LAT;
209ad43ddacSmrg		OUTPLL(pScrn, RADEON_SCLK_MORE_CNTL, tmp);
210ad43ddacSmrg
211ad43ddacSmrg		tmp = INPLL(pScrn, RADEON_VCLK_ECP_CNTL);
212ad43ddacSmrg		tmp |= (RADEON_PIXCLK_ALWAYS_ONb |
213ad43ddacSmrg			RADEON_PIXCLK_DAC_ALWAYS_ONb);
214ad43ddacSmrg		OUTPLL(pScrn, RADEON_VCLK_ECP_CNTL, tmp);
215ad43ddacSmrg
216ad43ddacSmrg		tmp = INPLL(pScrn, RADEON_PIXCLKS_CNTL);
217ad43ddacSmrg		tmp |= (RADEON_PIX2CLK_ALWAYS_ONb         |
218ad43ddacSmrg			RADEON_PIX2CLK_DAC_ALWAYS_ONb     |
219ad43ddacSmrg			RADEON_DISP_TVOUT_PIXCLK_TV_ALWAYS_ONb |
220ad43ddacSmrg			R300_DVOCLK_ALWAYS_ONb            |
221ad43ddacSmrg			RADEON_PIXCLK_BLEND_ALWAYS_ONb    |
222ad43ddacSmrg			RADEON_PIXCLK_GV_ALWAYS_ONb       |
223ad43ddacSmrg			R300_PIXCLK_DVO_ALWAYS_ONb        |
224ad43ddacSmrg			RADEON_PIXCLK_LVDS_ALWAYS_ONb     |
225ad43ddacSmrg			RADEON_PIXCLK_TMDS_ALWAYS_ONb     |
226ad43ddacSmrg			R300_PIXCLK_TRANS_ALWAYS_ONb      |
227ad43ddacSmrg			R300_PIXCLK_TVO_ALWAYS_ONb        |
228ad43ddacSmrg			R300_P2G2CLK_ALWAYS_ONb           |
229ad43ddacSmrg			R300_P2G2CLK_DAC_ALWAYS_ONb);
230ad43ddacSmrg		OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, tmp);
231ad43ddacSmrg	    } else if (info->ChipFamily >= CHIP_FAMILY_RV350) {
232ad43ddacSmrg		tmp = INPLL(pScrn, R300_SCLK_CNTL2);
233ad43ddacSmrg		tmp &= ~(R300_SCLK_FORCE_TCL |
234ad43ddacSmrg			 R300_SCLK_FORCE_GA  |
235ad43ddacSmrg			 R300_SCLK_FORCE_CBA);
236ad43ddacSmrg		tmp |=  (R300_SCLK_TCL_MAX_DYN_STOP_LAT |
237ad43ddacSmrg			 R300_SCLK_GA_MAX_DYN_STOP_LAT  |
238ad43ddacSmrg			 R300_SCLK_CBA_MAX_DYN_STOP_LAT);
239ad43ddacSmrg		OUTPLL(pScrn, R300_SCLK_CNTL2, tmp);
240ad43ddacSmrg
241ad43ddacSmrg		tmp = INPLL(pScrn, RADEON_SCLK_CNTL);
242ad43ddacSmrg		tmp &= ~(RADEON_SCLK_FORCE_DISP2 | RADEON_SCLK_FORCE_CP      |
243ad43ddacSmrg			 RADEON_SCLK_FORCE_HDP   | RADEON_SCLK_FORCE_DISP1   |
244ad43ddacSmrg			 RADEON_SCLK_FORCE_TOP   | RADEON_SCLK_FORCE_E2      |
245ad43ddacSmrg			 R300_SCLK_FORCE_VAP     | RADEON_SCLK_FORCE_IDCT    |
246ad43ddacSmrg			 RADEON_SCLK_FORCE_VIP   | R300_SCLK_FORCE_SR        |
247ad43ddacSmrg			 R300_SCLK_FORCE_PX      | R300_SCLK_FORCE_TX        |
248ad43ddacSmrg			 R300_SCLK_FORCE_US      | RADEON_SCLK_FORCE_TV_SCLK |
249ad43ddacSmrg			 R300_SCLK_FORCE_SU      | RADEON_SCLK_FORCE_OV0);
250ad43ddacSmrg		tmp |=  RADEON_DYN_STOP_LAT_MASK;
251ad43ddacSmrg		OUTPLL(pScrn, RADEON_SCLK_CNTL, tmp);
252ad43ddacSmrg
253ad43ddacSmrg		tmp = INPLL(pScrn, RADEON_SCLK_MORE_CNTL);
254ad43ddacSmrg		tmp &= ~RADEON_SCLK_MORE_FORCEON;
255ad43ddacSmrg		tmp |=  RADEON_SCLK_MORE_MAX_DYN_STOP_LAT;
256ad43ddacSmrg		OUTPLL(pScrn, RADEON_SCLK_MORE_CNTL, tmp);
257ad43ddacSmrg
258ad43ddacSmrg		tmp = INPLL(pScrn, RADEON_VCLK_ECP_CNTL);
259ad43ddacSmrg		tmp |= (RADEON_PIXCLK_ALWAYS_ONb |
260ad43ddacSmrg			RADEON_PIXCLK_DAC_ALWAYS_ONb);
261ad43ddacSmrg		OUTPLL(pScrn, RADEON_VCLK_ECP_CNTL, tmp);
262ad43ddacSmrg
263ad43ddacSmrg		tmp = INPLL(pScrn, RADEON_PIXCLKS_CNTL);
264ad43ddacSmrg		tmp |= (RADEON_PIX2CLK_ALWAYS_ONb         |
265ad43ddacSmrg			RADEON_PIX2CLK_DAC_ALWAYS_ONb     |
266ad43ddacSmrg			RADEON_DISP_TVOUT_PIXCLK_TV_ALWAYS_ONb |
267ad43ddacSmrg			R300_DVOCLK_ALWAYS_ONb            |
268ad43ddacSmrg			RADEON_PIXCLK_BLEND_ALWAYS_ONb    |
269ad43ddacSmrg			RADEON_PIXCLK_GV_ALWAYS_ONb       |
270ad43ddacSmrg			R300_PIXCLK_DVO_ALWAYS_ONb        |
271ad43ddacSmrg			RADEON_PIXCLK_LVDS_ALWAYS_ONb     |
272ad43ddacSmrg			RADEON_PIXCLK_TMDS_ALWAYS_ONb     |
273ad43ddacSmrg			R300_PIXCLK_TRANS_ALWAYS_ONb      |
274ad43ddacSmrg			R300_PIXCLK_TVO_ALWAYS_ONb        |
275ad43ddacSmrg			R300_P2G2CLK_ALWAYS_ONb           |
276ad43ddacSmrg			R300_P2G2CLK_DAC_ALWAYS_ONb);
277ad43ddacSmrg		OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, tmp);
278ad43ddacSmrg
279ad43ddacSmrg		tmp = INPLL(pScrn, RADEON_MCLK_MISC);
280ad43ddacSmrg		tmp |= (RADEON_MC_MCLK_DYN_ENABLE |
281ad43ddacSmrg			RADEON_IO_MCLK_DYN_ENABLE);
282ad43ddacSmrg		OUTPLL(pScrn, RADEON_MCLK_MISC, tmp);
283ad43ddacSmrg
284ad43ddacSmrg		tmp = INPLL(pScrn, RADEON_MCLK_CNTL);
285ad43ddacSmrg		tmp |= (RADEON_FORCEON_MCLKA |
286ad43ddacSmrg			RADEON_FORCEON_MCLKB);
287ad43ddacSmrg
288ad43ddacSmrg		tmp &= ~(RADEON_FORCEON_YCLKA  |
289ad43ddacSmrg			 RADEON_FORCEON_YCLKB  |
290ad43ddacSmrg			 RADEON_FORCEON_MC);
291ad43ddacSmrg
292ad43ddacSmrg		/* Some releases of vbios have set DISABLE_MC_MCLKA
293ad43ddacSmrg		   and DISABLE_MC_MCLKB bits in the vbios table.  Setting these
294ad43ddacSmrg		   bits will cause H/W hang when reading video memory with dynamic clocking
295ad43ddacSmrg		   enabled. */
296ad43ddacSmrg		if ((tmp & R300_DISABLE_MC_MCLKA) &&
297ad43ddacSmrg		    (tmp & R300_DISABLE_MC_MCLKB)) {
298ad43ddacSmrg		    /* If both bits are set, then check the active channels */
299ad43ddacSmrg		    tmp = INPLL(pScrn, RADEON_MCLK_CNTL);
300ad43ddacSmrg		    if (info->RamWidth == 64) {
301ad43ddacSmrg			if (INREG(RADEON_MEM_CNTL) & R300_MEM_USE_CD_CH_ONLY)
302ad43ddacSmrg			    tmp &= ~R300_DISABLE_MC_MCLKB;
303ad43ddacSmrg			else
304ad43ddacSmrg			    tmp &= ~R300_DISABLE_MC_MCLKA;
305ad43ddacSmrg		    } else {
306ad43ddacSmrg			tmp &= ~(R300_DISABLE_MC_MCLKA |
307ad43ddacSmrg				 R300_DISABLE_MC_MCLKB);
308ad43ddacSmrg		    }
309ad43ddacSmrg		}
310ad43ddacSmrg
311ad43ddacSmrg		OUTPLL(pScrn, RADEON_MCLK_CNTL, tmp);
312ad43ddacSmrg	    } else {
313ad43ddacSmrg		tmp = INPLL(pScrn, RADEON_SCLK_CNTL);
314ad43ddacSmrg		tmp &= ~(R300_SCLK_FORCE_VAP);
315ad43ddacSmrg		tmp |= RADEON_SCLK_FORCE_CP;
316ad43ddacSmrg		OUTPLL(pScrn, RADEON_SCLK_CNTL, tmp);
317ad43ddacSmrg		usleep(15000);
318ad43ddacSmrg
319ad43ddacSmrg		tmp = INPLL(pScrn, R300_SCLK_CNTL2);
320ad43ddacSmrg		tmp &= ~(R300_SCLK_FORCE_TCL |
321ad43ddacSmrg			 R300_SCLK_FORCE_GA  |
322ad43ddacSmrg			 R300_SCLK_FORCE_CBA);
323ad43ddacSmrg		OUTPLL(pScrn, R300_SCLK_CNTL2, tmp);
324ad43ddacSmrg	    }
325ad43ddacSmrg	} else {
326ad43ddacSmrg	    tmp = INPLL(pScrn, RADEON_CLK_PWRMGT_CNTL);
327ad43ddacSmrg
328ad43ddacSmrg	    tmp &= ~(RADEON_ACTIVE_HILO_LAT_MASK     |
329ad43ddacSmrg		     RADEON_DISP_DYN_STOP_LAT_MASK   |
330ad43ddacSmrg		     RADEON_DYN_STOP_MODE_MASK);
331ad43ddacSmrg
332ad43ddacSmrg	    tmp |= (RADEON_ENGIN_DYNCLK_MODE |
333ad43ddacSmrg		    (0x01 << RADEON_ACTIVE_HILO_LAT_SHIFT));
334ad43ddacSmrg	    OUTPLL(pScrn, RADEON_CLK_PWRMGT_CNTL, tmp);
335ad43ddacSmrg	    usleep(15000);
336ad43ddacSmrg
337ad43ddacSmrg	    tmp = INPLL(pScrn, RADEON_CLK_PIN_CNTL);
338ad43ddacSmrg	    tmp |= RADEON_SCLK_DYN_START_CNTL;
339ad43ddacSmrg	    OUTPLL(pScrn, RADEON_CLK_PIN_CNTL, tmp);
340ad43ddacSmrg	    usleep(15000);
341ad43ddacSmrg
342ad43ddacSmrg	    /* When DRI is enabled, setting DYN_STOP_LAT to zero can cause some R200
343ad43ddacSmrg	       to lockup randomly, leave them as set by BIOS.
344ad43ddacSmrg	    */
345ad43ddacSmrg	    tmp = INPLL(pScrn, RADEON_SCLK_CNTL);
346ad43ddacSmrg	    /*tmp &= RADEON_SCLK_SRC_SEL_MASK;*/
347ad43ddacSmrg	    tmp &= ~RADEON_SCLK_FORCEON_MASK;
348ad43ddacSmrg
349ad43ddacSmrg	    /*RAGE_6::A11 A12 A12N1 A13, RV250::A11 A12, R300*/
350ad43ddacSmrg	    if (((info->ChipFamily == CHIP_FAMILY_RV250) &&
351ad43ddacSmrg		 ((INREG(RADEON_CONFIG_CNTL) & RADEON_CFG_ATI_REV_ID_MASK) <
352ad43ddacSmrg		  RADEON_CFG_ATI_REV_A13)) ||
353ad43ddacSmrg		((info->ChipFamily == CHIP_FAMILY_RV100) &&
354ad43ddacSmrg		 ((INREG(RADEON_CONFIG_CNTL) & RADEON_CFG_ATI_REV_ID_MASK) <=
355ad43ddacSmrg		  RADEON_CFG_ATI_REV_A13))) {
356ad43ddacSmrg		tmp |= RADEON_SCLK_FORCE_CP;
357ad43ddacSmrg		tmp |= RADEON_SCLK_FORCE_VIP;
358ad43ddacSmrg	    }
359ad43ddacSmrg
360ad43ddacSmrg	    OUTPLL(pScrn, RADEON_SCLK_CNTL, tmp);
361ad43ddacSmrg
362ad43ddacSmrg	    if ((info->ChipFamily == CHIP_FAMILY_RV200) ||
363ad43ddacSmrg		(info->ChipFamily == CHIP_FAMILY_RV250) ||
364ad43ddacSmrg		(info->ChipFamily == CHIP_FAMILY_RV280)) {
365ad43ddacSmrg		tmp = INPLL(pScrn, RADEON_SCLK_MORE_CNTL);
366ad43ddacSmrg		tmp &= ~RADEON_SCLK_MORE_FORCEON;
367ad43ddacSmrg
368ad43ddacSmrg		/* RV200::A11 A12 RV250::A11 A12 */
369ad43ddacSmrg		if (((info->ChipFamily == CHIP_FAMILY_RV200) ||
370ad43ddacSmrg		     (info->ChipFamily == CHIP_FAMILY_RV250)) &&
371ad43ddacSmrg		    ((INREG(RADEON_CONFIG_CNTL) & RADEON_CFG_ATI_REV_ID_MASK) <
372ad43ddacSmrg		     RADEON_CFG_ATI_REV_A13)) {
373ad43ddacSmrg		    tmp |= RADEON_SCLK_MORE_FORCEON;
374ad43ddacSmrg		}
375ad43ddacSmrg		OUTPLL(pScrn, RADEON_SCLK_MORE_CNTL, tmp);
376ad43ddacSmrg		usleep(15000);
377ad43ddacSmrg	    }
378ad43ddacSmrg
379ad43ddacSmrg	    /* RV200::A11 A12, RV250::A11 A12 */
380ad43ddacSmrg	    if (((info->ChipFamily == CHIP_FAMILY_RV200) ||
381ad43ddacSmrg		 (info->ChipFamily == CHIP_FAMILY_RV250)) &&
382ad43ddacSmrg		((INREG(RADEON_CONFIG_CNTL) & RADEON_CFG_ATI_REV_ID_MASK) <
383ad43ddacSmrg		 RADEON_CFG_ATI_REV_A13)) {
384ad43ddacSmrg		tmp = INPLL(pScrn, RADEON_PLL_PWRMGT_CNTL);
385ad43ddacSmrg		tmp |= RADEON_TCL_BYPASS_DISABLE;
386ad43ddacSmrg		OUTPLL(pScrn, RADEON_PLL_PWRMGT_CNTL, tmp);
387ad43ddacSmrg	    }
388ad43ddacSmrg	    usleep(15000);
389ad43ddacSmrg
390ad43ddacSmrg	    /*enable dynamic mode for display clocks (PIXCLK and PIX2CLK)*/
391ad43ddacSmrg	    tmp = INPLL(pScrn, RADEON_PIXCLKS_CNTL);
392ad43ddacSmrg	    tmp |=  (RADEON_PIX2CLK_ALWAYS_ONb         |
393ad43ddacSmrg		     RADEON_PIX2CLK_DAC_ALWAYS_ONb     |
394ad43ddacSmrg		     RADEON_PIXCLK_BLEND_ALWAYS_ONb    |
395ad43ddacSmrg		     RADEON_PIXCLK_GV_ALWAYS_ONb       |
396ad43ddacSmrg		     RADEON_PIXCLK_DIG_TMDS_ALWAYS_ONb |
397ad43ddacSmrg		     RADEON_PIXCLK_LVDS_ALWAYS_ONb     |
398ad43ddacSmrg		     RADEON_PIXCLK_TMDS_ALWAYS_ONb);
399ad43ddacSmrg
400ad43ddacSmrg	    OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, tmp);
401ad43ddacSmrg	    usleep(15000);
402ad43ddacSmrg
403ad43ddacSmrg	    tmp = INPLL(pScrn, RADEON_VCLK_ECP_CNTL);
404ad43ddacSmrg	    tmp |= (RADEON_PIXCLK_ALWAYS_ONb  |
405ad43ddacSmrg		    RADEON_PIXCLK_DAC_ALWAYS_ONb);
406ad43ddacSmrg
407ad43ddacSmrg	    OUTPLL(pScrn, RADEON_VCLK_ECP_CNTL, tmp);
408ad43ddacSmrg	    usleep(15000);
409ad43ddacSmrg	}
410ad43ddacSmrg    } else {
411ad43ddacSmrg	/* Turn everything OFF (ForceON to everything)*/
412ad43ddacSmrg	if ( !pRADEONEnt->HasCRTC2 ) {
413ad43ddacSmrg	    tmp = INPLL(pScrn, RADEON_SCLK_CNTL);
414ad43ddacSmrg	    tmp |= (RADEON_SCLK_FORCE_CP   | RADEON_SCLK_FORCE_HDP |
415ad43ddacSmrg		    RADEON_SCLK_FORCE_DISP1 | RADEON_SCLK_FORCE_TOP |
416ad43ddacSmrg		    RADEON_SCLK_FORCE_E2   | RADEON_SCLK_FORCE_SE  |
417ad43ddacSmrg		    RADEON_SCLK_FORCE_IDCT | RADEON_SCLK_FORCE_VIP |
418ad43ddacSmrg		    RADEON_SCLK_FORCE_RE   | RADEON_SCLK_FORCE_PB  |
419ad43ddacSmrg		    RADEON_SCLK_FORCE_TAM  | RADEON_SCLK_FORCE_TDM |
420ad43ddacSmrg		    RADEON_SCLK_FORCE_RB);
421ad43ddacSmrg	    OUTPLL(pScrn, RADEON_SCLK_CNTL, tmp);
422ad43ddacSmrg	} else if ((info->ChipFamily == CHIP_FAMILY_RS400) ||
423ad43ddacSmrg		   (info->ChipFamily == CHIP_FAMILY_RS480)) {
424ad43ddacSmrg	    tmp = INPLL(pScrn, RADEON_SCLK_CNTL);
425ad43ddacSmrg	    tmp |= (RADEON_SCLK_FORCE_DISP2 | RADEON_SCLK_FORCE_CP      |
426ad43ddacSmrg		    RADEON_SCLK_FORCE_HDP   | RADEON_SCLK_FORCE_DISP1   |
427ad43ddacSmrg		    RADEON_SCLK_FORCE_TOP   | RADEON_SCLK_FORCE_E2      |
428ad43ddacSmrg		    R300_SCLK_FORCE_VAP     | RADEON_SCLK_FORCE_IDCT    |
429ad43ddacSmrg		    RADEON_SCLK_FORCE_VIP   | R300_SCLK_FORCE_SR        |
430ad43ddacSmrg		    R300_SCLK_FORCE_PX      | R300_SCLK_FORCE_TX        |
431ad43ddacSmrg		    R300_SCLK_FORCE_US      | RADEON_SCLK_FORCE_TV_SCLK |
432ad43ddacSmrg		    R300_SCLK_FORCE_SU      | RADEON_SCLK_FORCE_OV0);
433ad43ddacSmrg	    OUTPLL(pScrn, RADEON_SCLK_CNTL, tmp);
434ad43ddacSmrg
435ad43ddacSmrg	    tmp = INPLL(pScrn, RADEON_SCLK_MORE_CNTL);
436ad43ddacSmrg	    tmp |= RADEON_SCLK_MORE_FORCEON;
437ad43ddacSmrg	    OUTPLL(pScrn, RADEON_SCLK_MORE_CNTL, tmp);
438ad43ddacSmrg
439ad43ddacSmrg	    tmp = INPLL(pScrn, RADEON_VCLK_ECP_CNTL);
440ad43ddacSmrg	    tmp &= ~(RADEON_PIXCLK_ALWAYS_ONb  |
441ad43ddacSmrg		     RADEON_PIXCLK_DAC_ALWAYS_ONb |
442ad43ddacSmrg		     R300_DISP_DAC_PIXCLK_DAC_BLANK_OFF);
443ad43ddacSmrg	    OUTPLL(pScrn, RADEON_VCLK_ECP_CNTL, tmp);
444ad43ddacSmrg
445ad43ddacSmrg	    tmp = INPLL(pScrn, RADEON_PIXCLKS_CNTL);
446ad43ddacSmrg	    tmp &= ~(RADEON_PIX2CLK_ALWAYS_ONb         |
447ad43ddacSmrg		     RADEON_PIX2CLK_DAC_ALWAYS_ONb     |
448ad43ddacSmrg		     RADEON_DISP_TVOUT_PIXCLK_TV_ALWAYS_ONb |
449ad43ddacSmrg		     R300_DVOCLK_ALWAYS_ONb            |
450ad43ddacSmrg		     RADEON_PIXCLK_BLEND_ALWAYS_ONb    |
451ad43ddacSmrg		     RADEON_PIXCLK_GV_ALWAYS_ONb       |
452ad43ddacSmrg		     R300_PIXCLK_DVO_ALWAYS_ONb        |
453ad43ddacSmrg		     RADEON_PIXCLK_LVDS_ALWAYS_ONb     |
454ad43ddacSmrg		     RADEON_PIXCLK_TMDS_ALWAYS_ONb     |
455ad43ddacSmrg		     R300_PIXCLK_TRANS_ALWAYS_ONb      |
456ad43ddacSmrg		     R300_PIXCLK_TVO_ALWAYS_ONb        |
457ad43ddacSmrg		     R300_P2G2CLK_ALWAYS_ONb           |
458ad43ddacSmrg		     R300_P2G2CLK_DAC_ALWAYS_ONb       |
459ad43ddacSmrg		     R300_DISP_DAC_PIXCLK_DAC2_BLANK_OFF);
460ad43ddacSmrg	    OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, tmp);
461ad43ddacSmrg	} else if (info->ChipFamily >= CHIP_FAMILY_RV350) {
462ad43ddacSmrg	    /* for RV350/M10, no delays are required. */
463ad43ddacSmrg	    tmp = INPLL(pScrn, R300_SCLK_CNTL2);
464ad43ddacSmrg	    tmp |= (R300_SCLK_FORCE_TCL |
465ad43ddacSmrg		    R300_SCLK_FORCE_GA  |
466ad43ddacSmrg		    R300_SCLK_FORCE_CBA);
467ad43ddacSmrg	    OUTPLL(pScrn, R300_SCLK_CNTL2, tmp);
468ad43ddacSmrg
469ad43ddacSmrg	    tmp = INPLL(pScrn, RADEON_SCLK_CNTL);
470ad43ddacSmrg	    tmp |= (RADEON_SCLK_FORCE_DISP2 | RADEON_SCLK_FORCE_CP      |
471ad43ddacSmrg		    RADEON_SCLK_FORCE_HDP   | RADEON_SCLK_FORCE_DISP1   |
472ad43ddacSmrg		    RADEON_SCLK_FORCE_TOP   | RADEON_SCLK_FORCE_E2      |
473ad43ddacSmrg		    R300_SCLK_FORCE_VAP     | RADEON_SCLK_FORCE_IDCT    |
474ad43ddacSmrg		    RADEON_SCLK_FORCE_VIP   | R300_SCLK_FORCE_SR        |
475ad43ddacSmrg		    R300_SCLK_FORCE_PX      | R300_SCLK_FORCE_TX        |
476ad43ddacSmrg		    R300_SCLK_FORCE_US      | RADEON_SCLK_FORCE_TV_SCLK |
477ad43ddacSmrg		    R300_SCLK_FORCE_SU      | RADEON_SCLK_FORCE_OV0);
478ad43ddacSmrg	    OUTPLL(pScrn, RADEON_SCLK_CNTL, tmp);
479ad43ddacSmrg
480ad43ddacSmrg	    tmp = INPLL(pScrn, RADEON_SCLK_MORE_CNTL);
481ad43ddacSmrg	    tmp |= RADEON_SCLK_MORE_FORCEON;
482ad43ddacSmrg	    OUTPLL(pScrn, RADEON_SCLK_MORE_CNTL, tmp);
483ad43ddacSmrg
484ad43ddacSmrg	    tmp = INPLL(pScrn, RADEON_MCLK_CNTL);
485ad43ddacSmrg	    tmp |= (RADEON_FORCEON_MCLKA |
486ad43ddacSmrg		    RADEON_FORCEON_MCLKB |
487ad43ddacSmrg		    RADEON_FORCEON_YCLKA |
488ad43ddacSmrg		    RADEON_FORCEON_YCLKB |
489ad43ddacSmrg		    RADEON_FORCEON_MC);
490ad43ddacSmrg	    OUTPLL(pScrn, RADEON_MCLK_CNTL, tmp);
491ad43ddacSmrg
492ad43ddacSmrg	    tmp = INPLL(pScrn, RADEON_VCLK_ECP_CNTL);
493ad43ddacSmrg	    tmp &= ~(RADEON_PIXCLK_ALWAYS_ONb  |
494ad43ddacSmrg		     RADEON_PIXCLK_DAC_ALWAYS_ONb |
495ad43ddacSmrg		     R300_DISP_DAC_PIXCLK_DAC_BLANK_OFF);
496ad43ddacSmrg	    OUTPLL(pScrn, RADEON_VCLK_ECP_CNTL, tmp);
497ad43ddacSmrg
498ad43ddacSmrg	    tmp = INPLL(pScrn, RADEON_PIXCLKS_CNTL);
499ad43ddacSmrg	    tmp &= ~(RADEON_PIX2CLK_ALWAYS_ONb         |
500ad43ddacSmrg		     RADEON_PIX2CLK_DAC_ALWAYS_ONb     |
501ad43ddacSmrg		     RADEON_DISP_TVOUT_PIXCLK_TV_ALWAYS_ONb |
502ad43ddacSmrg		     R300_DVOCLK_ALWAYS_ONb            |
503ad43ddacSmrg		     RADEON_PIXCLK_BLEND_ALWAYS_ONb    |
504ad43ddacSmrg		     RADEON_PIXCLK_GV_ALWAYS_ONb       |
505ad43ddacSmrg		     R300_PIXCLK_DVO_ALWAYS_ONb        |
506ad43ddacSmrg		     RADEON_PIXCLK_LVDS_ALWAYS_ONb     |
507ad43ddacSmrg		     RADEON_PIXCLK_TMDS_ALWAYS_ONb     |
508ad43ddacSmrg		     R300_PIXCLK_TRANS_ALWAYS_ONb      |
509ad43ddacSmrg		     R300_PIXCLK_TVO_ALWAYS_ONb        |
510ad43ddacSmrg		     R300_P2G2CLK_ALWAYS_ONb           |
511ad43ddacSmrg		     R300_P2G2CLK_DAC_ALWAYS_ONb       |
512ad43ddacSmrg		     R300_DISP_DAC_PIXCLK_DAC2_BLANK_OFF);
513ad43ddacSmrg	    OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, tmp);
514ad43ddacSmrg	}  else {
515ad43ddacSmrg	    tmp = INPLL(pScrn, RADEON_SCLK_CNTL);
516ad43ddacSmrg	    tmp |= (RADEON_SCLK_FORCE_CP | RADEON_SCLK_FORCE_E2);
517ad43ddacSmrg	    tmp |= RADEON_SCLK_FORCE_SE;
518ad43ddacSmrg
519ad43ddacSmrg	    if ( !pRADEONEnt->HasCRTC2 ) {
520ad43ddacSmrg		tmp |= ( RADEON_SCLK_FORCE_RB    |
521ad43ddacSmrg			 RADEON_SCLK_FORCE_TDM   |
522ad43ddacSmrg			 RADEON_SCLK_FORCE_TAM   |
523ad43ddacSmrg			 RADEON_SCLK_FORCE_PB    |
524ad43ddacSmrg			 RADEON_SCLK_FORCE_RE    |
525ad43ddacSmrg			 RADEON_SCLK_FORCE_VIP   |
526ad43ddacSmrg			 RADEON_SCLK_FORCE_IDCT  |
527ad43ddacSmrg			 RADEON_SCLK_FORCE_TOP   |
528ad43ddacSmrg			 RADEON_SCLK_FORCE_DISP1 |
529ad43ddacSmrg			 RADEON_SCLK_FORCE_DISP2 |
530ad43ddacSmrg			 RADEON_SCLK_FORCE_HDP    );
531ad43ddacSmrg	    } else if ((info->ChipFamily == CHIP_FAMILY_R300) ||
532ad43ddacSmrg		       (info->ChipFamily == CHIP_FAMILY_R350)) {
533ad43ddacSmrg		tmp |= ( RADEON_SCLK_FORCE_HDP   |
534ad43ddacSmrg			 RADEON_SCLK_FORCE_DISP1 |
535ad43ddacSmrg			 RADEON_SCLK_FORCE_DISP2 |
536ad43ddacSmrg			 RADEON_SCLK_FORCE_TOP   |
537ad43ddacSmrg			 RADEON_SCLK_FORCE_IDCT  |
538ad43ddacSmrg			 RADEON_SCLK_FORCE_VIP);
539ad43ddacSmrg	    }
540ad43ddacSmrg	    OUTPLL(pScrn, RADEON_SCLK_CNTL, tmp);
541ad43ddacSmrg
542ad43ddacSmrg	    usleep(16000);
543ad43ddacSmrg
544ad43ddacSmrg	    if ((info->ChipFamily == CHIP_FAMILY_R300) ||
545ad43ddacSmrg		(info->ChipFamily == CHIP_FAMILY_R350)) {
546ad43ddacSmrg		tmp = INPLL(pScrn, R300_SCLK_CNTL2);
547ad43ddacSmrg		tmp |= ( R300_SCLK_FORCE_TCL |
548ad43ddacSmrg			 R300_SCLK_FORCE_GA  |
549ad43ddacSmrg			 R300_SCLK_FORCE_CBA);
550ad43ddacSmrg		OUTPLL(pScrn, R300_SCLK_CNTL2, tmp);
551ad43ddacSmrg		usleep(16000);
552ad43ddacSmrg	    }
553ad43ddacSmrg
554ad43ddacSmrg	    if (info->IsIGP) {
555ad43ddacSmrg		tmp = INPLL(pScrn, RADEON_MCLK_CNTL);
556ad43ddacSmrg		tmp &= ~(RADEON_FORCEON_MCLKA |
557ad43ddacSmrg			 RADEON_FORCEON_YCLKA);
558ad43ddacSmrg		OUTPLL(pScrn, RADEON_MCLK_CNTL, tmp);
559ad43ddacSmrg		usleep(16000);
560ad43ddacSmrg	    }
561ad43ddacSmrg
562ad43ddacSmrg	    if ((info->ChipFamily == CHIP_FAMILY_RV200) ||
563ad43ddacSmrg		(info->ChipFamily == CHIP_FAMILY_RV250) ||
564ad43ddacSmrg		(info->ChipFamily == CHIP_FAMILY_RV280)) {
565ad43ddacSmrg		tmp = INPLL(pScrn, RADEON_SCLK_MORE_CNTL);
566ad43ddacSmrg		tmp |= RADEON_SCLK_MORE_FORCEON;
567ad43ddacSmrg		OUTPLL(pScrn, RADEON_SCLK_MORE_CNTL, tmp);
568ad43ddacSmrg		usleep(16000);
569ad43ddacSmrg	    }
570ad43ddacSmrg
571ad43ddacSmrg	    tmp = INPLL(pScrn, RADEON_PIXCLKS_CNTL);
572ad43ddacSmrg	    tmp &= ~(RADEON_PIX2CLK_ALWAYS_ONb         |
573ad43ddacSmrg		     RADEON_PIX2CLK_DAC_ALWAYS_ONb     |
574ad43ddacSmrg		     RADEON_PIXCLK_BLEND_ALWAYS_ONb    |
575ad43ddacSmrg		     RADEON_PIXCLK_GV_ALWAYS_ONb       |
576ad43ddacSmrg		     RADEON_PIXCLK_DIG_TMDS_ALWAYS_ONb |
577ad43ddacSmrg		     RADEON_PIXCLK_LVDS_ALWAYS_ONb     |
578ad43ddacSmrg		     RADEON_PIXCLK_TMDS_ALWAYS_ONb);
579ad43ddacSmrg
580ad43ddacSmrg	    OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, tmp);
581ad43ddacSmrg	    usleep(16000);
582ad43ddacSmrg
583ad43ddacSmrg	    tmp = INPLL(pScrn, RADEON_VCLK_ECP_CNTL);
584ad43ddacSmrg	    tmp &= ~(RADEON_PIXCLK_ALWAYS_ONb  |
585ad43ddacSmrg		     RADEON_PIXCLK_DAC_ALWAYS_ONb);
586ad43ddacSmrg	    OUTPLL(pScrn, RADEON_VCLK_ECP_CNTL, tmp);
587ad43ddacSmrg	}
588ad43ddacSmrg    }
589ad43ddacSmrg}
590ad43ddacSmrg
591ad43ddacSmrgstatic void RADEONPMQuirks(ScrnInfoPtr pScrn)
592ad43ddacSmrg{
593ad43ddacSmrg    RADEONInfoPtr  info       = RADEONPTR(pScrn);
594ad43ddacSmrg    uint32_t tmp;
595ad43ddacSmrg
596ad43ddacSmrg    RADEONWaitForIdleMMIO(pScrn);
597ad43ddacSmrg
598ad43ddacSmrg    if (info->ChipFamily < CHIP_FAMILY_RV515) {
599ad43ddacSmrg	tmp = INPLL(pScrn, RADEON_SCLK_CNTL);
600ad43ddacSmrg	if (IS_R300_VARIANT || IS_RV100_VARIANT)
601ad43ddacSmrg	    tmp |= RADEON_SCLK_FORCE_CP | RADEON_SCLK_FORCE_VIP;
602ad43ddacSmrg	if ((info->ChipFamily == CHIP_FAMILY_RV250) || (info->ChipFamily == CHIP_FAMILY_RV280))
603ad43ddacSmrg	    tmp |= RADEON_SCLK_FORCE_DISP1 | RADEON_SCLK_FORCE_DISP2;
604ad43ddacSmrg	if ((info->ChipFamily == CHIP_FAMILY_RV350) || (info->ChipFamily == CHIP_FAMILY_RV380))
605ad43ddacSmrg	    tmp |= R300_SCLK_FORCE_VAP;
606ad43ddacSmrg	if (info->ChipFamily == CHIP_FAMILY_R420)
607ad43ddacSmrg	    tmp |= R300_SCLK_FORCE_PX | R300_SCLK_FORCE_TX;
608ad43ddacSmrg	OUTPLL(pScrn, RADEON_SCLK_CNTL, tmp);
609ad43ddacSmrg    } else if (info->ChipFamily < CHIP_FAMILY_R600) {
610ad43ddacSmrg	tmp = INPLL(pScrn, AVIVO_CP_DYN_CNTL);
611ad43ddacSmrg	tmp |= AVIVO_CP_FORCEON;
612ad43ddacSmrg	OUTPLL(pScrn, AVIVO_CP_DYN_CNTL, tmp);
613ad43ddacSmrg
614ad43ddacSmrg	tmp = INPLL(pScrn, AVIVO_E2_DYN_CNTL);
615ad43ddacSmrg	tmp |= AVIVO_E2_FORCEON;
616ad43ddacSmrg	OUTPLL(pScrn, AVIVO_E2_DYN_CNTL, tmp);
617ad43ddacSmrg
618ad43ddacSmrg	tmp = INPLL(pScrn, AVIVO_IDCT_DYN_CNTL);
619ad43ddacSmrg	tmp |= AVIVO_IDCT_FORCEON;
620ad43ddacSmrg	OUTPLL(pScrn, AVIVO_IDCT_DYN_CNTL, tmp);
621ad43ddacSmrg    }
622ad43ddacSmrg}
623ad43ddacSmrg
624ad43ddacSmrgstatic void
625ad43ddacSmrgRADEONSetPCIELanes(ScrnInfoPtr pScrn, int lanes)
626ad43ddacSmrg{
627ad43ddacSmrg    RADEONInfoPtr  info       = RADEONPTR(pScrn);
628ad43ddacSmrg    unsigned char *RADEONMMIO = info->MMIO;
629ad43ddacSmrg    uint32_t link_width_cntl, mask, target_reg;
630ad43ddacSmrg
631ad43ddacSmrg    if (info->IsIGP)
632ad43ddacSmrg	return;
633ad43ddacSmrg
634ad43ddacSmrg    /* don't change lanes on multi-gpu cards for now */
635ad43ddacSmrg    if ((info->Chipset == PCI_CHIP_RV770_9441) ||
636ad43ddacSmrg	(info->Chipset == PCI_CHIP_RV770_9443) ||
637ad43ddacSmrg	(info->Chipset == PCI_CHIP_RV770_944B) ||
638ad43ddacSmrg	(info->Chipset == PCI_CHIP_RV670_9506) ||
639ad43ddacSmrg	(info->Chipset == PCI_CHIP_RV670_9509) ||
640ad43ddacSmrg	(info->Chipset == PCI_CHIP_RV670_950F))
641ad43ddacSmrg	return;
642ad43ddacSmrg
643ad43ddacSmrg    RADEONWaitForIdleMMIO(pScrn);
644ad43ddacSmrg
645ad43ddacSmrg    switch (lanes) {
646ad43ddacSmrg    case 0:
647ad43ddacSmrg	mask = RADEON_PCIE_LC_LINK_WIDTH_X0;
648ad43ddacSmrg	break;
649ad43ddacSmrg    case 1:
650ad43ddacSmrg	mask = RADEON_PCIE_LC_LINK_WIDTH_X1;
651ad43ddacSmrg	break;
652ad43ddacSmrg    case 2:
653ad43ddacSmrg	mask = RADEON_PCIE_LC_LINK_WIDTH_X2;
654ad43ddacSmrg	break;
655ad43ddacSmrg    case 4:
656ad43ddacSmrg	mask = RADEON_PCIE_LC_LINK_WIDTH_X4;
657ad43ddacSmrg	break;
658ad43ddacSmrg    case 8:
659ad43ddacSmrg	mask = RADEON_PCIE_LC_LINK_WIDTH_X8;
660ad43ddacSmrg	break;
661ad43ddacSmrg    case 12:
662ad43ddacSmrg	mask = RADEON_PCIE_LC_LINK_WIDTH_X12;
663ad43ddacSmrg	break;
664ad43ddacSmrg    case 16:
665ad43ddacSmrg    default:
666ad43ddacSmrg	mask = RADEON_PCIE_LC_LINK_WIDTH_X16;
667ad43ddacSmrg	break;
668ad43ddacSmrg    }
669ad43ddacSmrg
670ad43ddacSmrg    if (info->ChipFamily >= CHIP_FAMILY_R600) {
671ad43ddacSmrg	link_width_cntl = INPCIE_P(pScrn, RADEON_PCIE_LC_LINK_WIDTH_CNTL);
672ad43ddacSmrg
673ad43ddacSmrg	if ((link_width_cntl & RADEON_PCIE_LC_LINK_WIDTH_RD_MASK) ==
674ad43ddacSmrg	    (mask << RADEON_PCIE_LC_LINK_WIDTH_RD_SHIFT))
675ad43ddacSmrg	    return;
676ad43ddacSmrg
677ad43ddacSmrg	link_width_cntl &= ~(RADEON_PCIE_LC_LINK_WIDTH_MASK |
678ad43ddacSmrg			     RADEON_PCIE_LC_RECONFIG_NOW |
679ad43ddacSmrg			     R600_PCIE_LC_RECONFIG_ARC_MISSING_ESCAPE |
680ad43ddacSmrg			     R600_PCIE_LC_SHORT_RECONFIG_EN |
681ad43ddacSmrg			     R600_PCIE_LC_RENEGOTIATE_EN);
682ad43ddacSmrg	link_width_cntl |= mask;
683ad43ddacSmrg
684ad43ddacSmrg#if 0
685ad43ddacSmrg	/* some northbridges can renegotiate the link rather than requiring
686ad43ddacSmrg	 * a complete re-config.
687ad43ddacSmrg	 * e.g., AMD 780/790 northbridges (pci ids: 0x5956, 0x5957, 0x5958, etc.)
688ad43ddacSmrg	 */
689ad43ddacSmrg	if (northbridge can renegotiate)
690ad43ddacSmrg	    link_width_cntl |= R600_PCIE_LC_RENEGOTIATE_EN;
691ad43ddacSmrg	else
692ad43ddacSmrg#endif
693ad43ddacSmrg	    link_width_cntl |= R600_PCIE_LC_RECONFIG_ARC_MISSING_ESCAPE;
694ad43ddacSmrg
695ad43ddacSmrg	OUTPCIE_P(pScrn, RADEON_PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl);
696ad43ddacSmrg	OUTPCIE_P(pScrn, RADEON_PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl | RADEON_PCIE_LC_RECONFIG_NOW);
697ad43ddacSmrg
698ad43ddacSmrg	if (info->ChipFamily >= CHIP_FAMILY_RV770)
699ad43ddacSmrg	    target_reg = R700_TARGET_AND_CURRENT_PROFILE_INDEX;
700ad43ddacSmrg	else
701ad43ddacSmrg	    target_reg = R600_TARGET_AND_CURRENT_PROFILE_INDEX;
702ad43ddacSmrg
703ad43ddacSmrg	/* wait for lane set to complete */
704ad43ddacSmrg	link_width_cntl = INREG(target_reg);
705ad43ddacSmrg	while (link_width_cntl == 0xffffffff)
706ad43ddacSmrg	    link_width_cntl = INREG(target_reg);
707ad43ddacSmrg
708ad43ddacSmrg    } else {
709ad43ddacSmrg	link_width_cntl = INPCIE(pScrn, RADEON_PCIE_LC_LINK_WIDTH_CNTL);
710ad43ddacSmrg
711ad43ddacSmrg	if ((link_width_cntl & RADEON_PCIE_LC_LINK_WIDTH_RD_MASK) ==
712ad43ddacSmrg	    (mask << RADEON_PCIE_LC_LINK_WIDTH_RD_SHIFT))
713ad43ddacSmrg	    return;
714ad43ddacSmrg
715ad43ddacSmrg	link_width_cntl &= ~(RADEON_PCIE_LC_LINK_WIDTH_MASK |
716ad43ddacSmrg			     RADEON_PCIE_LC_RECONFIG_NOW |
717ad43ddacSmrg			     RADEON_PCIE_LC_RECONFIG_LATER |
718ad43ddacSmrg			     RADEON_PCIE_LC_SHORT_RECONFIG_EN);
719ad43ddacSmrg	link_width_cntl |= mask;
720ad43ddacSmrg	OUTPCIE(pScrn, RADEON_PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl);
721ad43ddacSmrg	OUTPCIE(pScrn, RADEON_PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl | RADEON_PCIE_LC_RECONFIG_NOW);
722ad43ddacSmrg
723ad43ddacSmrg	/* wait for lane set to complete */
724ad43ddacSmrg	link_width_cntl = INPCIE(pScrn, RADEON_PCIE_LC_LINK_WIDTH_CNTL);
725ad43ddacSmrg	while (link_width_cntl == 0xffffffff)
726ad43ddacSmrg	    link_width_cntl = INPCIE(pScrn, RADEON_PCIE_LC_LINK_WIDTH_CNTL);
727ad43ddacSmrg
728ad43ddacSmrg    }
729ad43ddacSmrg
730ad43ddacSmrg}
731ad43ddacSmrg
732ad43ddacSmrgstatic void
733ad43ddacSmrgRADEONSetClockGating(ScrnInfoPtr pScrn, Bool enable)
734ad43ddacSmrg{
735ad43ddacSmrg    RADEONInfoPtr  info       = RADEONPTR(pScrn);
736ad43ddacSmrg
737ad43ddacSmrg    RADEONWaitForIdleMMIO(pScrn);
738ad43ddacSmrg
739ad43ddacSmrg    if (info->ChipFamily >= CHIP_FAMILY_R600)
740ad43ddacSmrg	atombios_static_pwrmgt_setup(pScrn, enable);
741ad43ddacSmrg    else {
742ad43ddacSmrg	if (info->IsAtomBios) {
743ad43ddacSmrg	    atombios_static_pwrmgt_setup(pScrn, enable);
744ad43ddacSmrg	    atombios_clk_gating_setup(pScrn, enable);
745ad43ddacSmrg	} else if (info->IsMobility)
746ad43ddacSmrg	    LegacySetClockGating(pScrn, enable);
747ad43ddacSmrg    }
748ad43ddacSmrg
749ad43ddacSmrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Dynamic Clock Gating %sabled\n",
750ad43ddacSmrg	       enable ? "En" : "Dis");
751ad43ddacSmrg}
752ad43ddacSmrg
753ad43ddacSmrgstatic void RADEONSetStaticPowerMode(ScrnInfoPtr pScrn, RADEONPMType type)
754ad43ddacSmrg{
755ad43ddacSmrg    RADEONInfoPtr  info       = RADEONPTR(pScrn);
756ad43ddacSmrg    int i;
757ad43ddacSmrg
758ad43ddacSmrg    for (i = 0; i < info->pm.num_modes; i++) {
759ad43ddacSmrg	if (info->pm.mode[i].type == type)
760ad43ddacSmrg	    break;
761ad43ddacSmrg    }
762ad43ddacSmrg
763ad43ddacSmrg    if (i == info->pm.num_modes)
764ad43ddacSmrg	return;
765ad43ddacSmrg
766ad43ddacSmrg    if (i == info->pm.current_mode)
767ad43ddacSmrg	return;
768ad43ddacSmrg
769ad43ddacSmrg    RADEONWaitForIdleMMIO(pScrn);
770ad43ddacSmrg
771ad43ddacSmrg    if (info->IsAtomBios)
772ad43ddacSmrg	atombios_set_engine_clock(pScrn, info->pm.mode[i].sclk);
773ad43ddacSmrg    else
774ad43ddacSmrg	RADEONSetEngineClock(pScrn, info->pm.mode[i].sclk);
775ad43ddacSmrg
776ad43ddacSmrg    if (info->cardType == CARD_PCIE)
777ad43ddacSmrg	RADEONSetPCIELanes(pScrn, info->pm.mode[i].pcie_lanes);
778ad43ddacSmrg
779ad43ddacSmrg    info->pm.current_mode = i;
780ad43ddacSmrg
781ad43ddacSmrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Power Mode Switch\n");
782ad43ddacSmrg}
783ad43ddacSmrg
784ad43ddacSmrg
785ad43ddacSmrgvoid RADEONPMInit(ScrnInfoPtr pScrn)
786ad43ddacSmrg{
787ad43ddacSmrg    RADEONInfoPtr  info       = RADEONPTR(pScrn);
788ad43ddacSmrg
789ad43ddacSmrg    if (xf86ReturnOptValBool(info->Options, OPTION_CLOCK_GATING, FALSE)) {
790ad43ddacSmrg	info->pm.clock_gating_enabled = TRUE;
791ad43ddacSmrg	RADEONSetClockGating(pScrn, info->pm.clock_gating_enabled);
792ad43ddacSmrg    } else
793ad43ddacSmrg	info->pm.clock_gating_enabled = FALSE;
794ad43ddacSmrg
795ad43ddacSmrg    info->pm.mode[0].type = POWER_DEFAULT;
796ad43ddacSmrg    info->pm.mode[0].sclk = (uint32_t)info->sclk * 100; /* 10 khz */
797ad43ddacSmrg    info->pm.mode[0].mclk = (uint32_t)info->mclk * 100; /* 10 khz */
798ad43ddacSmrg    info->pm.mode[0].pcie_lanes = 16; /* XXX: read back current lane config */
799ad43ddacSmrg    info->pm.current_mode = 0;
800ad43ddacSmrg    info->pm.num_modes = 1;
801ad43ddacSmrg
802ad43ddacSmrg    if (xf86ReturnOptValBool(info->Options, OPTION_DYNAMIC_PM, FALSE)) {
803ad43ddacSmrg	info->pm.dynamic_mode_enabled = TRUE;
804ad43ddacSmrg	info->pm.mode[1].type = POWER_LOW;
805ad43ddacSmrg	info->pm.mode[1].sclk = info->pm.mode[0].sclk / 4;
806ad43ddacSmrg	info->pm.mode[1].mclk = info->pm.mode[0].mclk / 4;
807ad43ddacSmrg	info->pm.mode[1].pcie_lanes = 1;
808ad43ddacSmrg
809ad43ddacSmrg	info->pm.mode[2].type = POWER_HIGH;
810ad43ddacSmrg	info->pm.mode[2].sclk = info->pm.mode[0].sclk;
811ad43ddacSmrg	info->pm.mode[2].mclk = info->pm.mode[0].mclk;
812ad43ddacSmrg	info->pm.mode[2].pcie_lanes = 16;
813ad43ddacSmrg
814ad43ddacSmrg	info->pm.num_modes += 2;
815ad43ddacSmrg
816ad43ddacSmrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Dynamic Power Management Enabled\n");
817ad43ddacSmrg    } else {
818ad43ddacSmrg	info->pm.dynamic_mode_enabled = FALSE;
819ad43ddacSmrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Dynamic Power Management Disabled\n");
820ad43ddacSmrg    }
821ad43ddacSmrg
822ad43ddacSmrg    if (xf86ReturnOptValBool(info->Options, OPTION_FORCE_LOW_POWER, FALSE)) {
823ad43ddacSmrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Force Low Power Mode Enabled\n");
824ad43ddacSmrg	info->pm.force_low_power_enabled = TRUE;
825ad43ddacSmrg	if (info->pm.dynamic_mode_enabled) {
826ad43ddacSmrg	    info->pm.mode[2].type = POWER_HIGH;
827ad43ddacSmrg	    info->pm.mode[2].sclk = info->pm.mode[0].sclk / 2;
828ad43ddacSmrg	    info->pm.mode[2].mclk = info->pm.mode[0].mclk / 2;
829ad43ddacSmrg	    info->pm.mode[2].pcie_lanes = 4;
830ad43ddacSmrg	} else {
831ad43ddacSmrg	    info->pm.mode[1].type = POWER_HIGH;
832ad43ddacSmrg	    info->pm.mode[1].sclk = info->pm.mode[0].sclk / 2;
833ad43ddacSmrg	    info->pm.mode[1].mclk = info->pm.mode[0].mclk / 2;
834ad43ddacSmrg	    info->pm.mode[1].pcie_lanes = 4;
835ad43ddacSmrg	    info->pm.num_modes += 1;
836ad43ddacSmrg	}
837ad43ddacSmrg	RADEONSetStaticPowerMode(pScrn, POWER_HIGH);
838ad43ddacSmrg    } else
839ad43ddacSmrg	info->pm.force_low_power_enabled = FALSE;
840ad43ddacSmrg
841ad43ddacSmrg    RADEONPMQuirks(pScrn);
842ad43ddacSmrg}
843ad43ddacSmrg
844ad43ddacSmrgvoid RADEONPMEnterVT(ScrnInfoPtr pScrn)
845ad43ddacSmrg{
846ad43ddacSmrg    RADEONInfoPtr  info       = RADEONPTR(pScrn);
847ad43ddacSmrg
848ad43ddacSmrg    if (info->pm.clock_gating_enabled)
849ad43ddacSmrg	RADEONSetClockGating(pScrn, info->pm.clock_gating_enabled);
850ad43ddacSmrg    RADEONPMQuirks(pScrn);
851ad43ddacSmrg    if (info->pm.force_low_power_enabled || info->pm.dynamic_mode_enabled)
852ad43ddacSmrg	RADEONSetStaticPowerMode(pScrn, POWER_HIGH);
853ad43ddacSmrg}
854ad43ddacSmrg
855ad43ddacSmrgvoid RADEONPMLeaveVT(ScrnInfoPtr pScrn)
856ad43ddacSmrg{
857ad43ddacSmrg    RADEONInfoPtr  info       = RADEONPTR(pScrn);
858ad43ddacSmrg
859ad43ddacSmrg    if (info->pm.clock_gating_enabled)
860ad43ddacSmrg	RADEONSetClockGating(pScrn, FALSE);
861ad43ddacSmrg    if (info->pm.force_low_power_enabled || info->pm.dynamic_mode_enabled)
862ad43ddacSmrg	RADEONSetStaticPowerMode(pScrn, POWER_DEFAULT);
863ad43ddacSmrg}
864ad43ddacSmrg
865ad43ddacSmrgvoid RADEONPMFini(ScrnInfoPtr pScrn)
866ad43ddacSmrg{
867ad43ddacSmrg    RADEONInfoPtr info = RADEONPTR(pScrn);
868ad43ddacSmrg
869ad43ddacSmrg    if (info->pm.clock_gating_enabled)
870ad43ddacSmrg	RADEONSetClockGating(pScrn, FALSE);
871ad43ddacSmrg    if (info->pm.force_low_power_enabled || info->pm.dynamic_mode_enabled)
872ad43ddacSmrg	RADEONSetStaticPowerMode(pScrn, POWER_DEFAULT);
873ad43ddacSmrg}
874ad43ddacSmrg
875ad43ddacSmrgvoid RADEONPMBlockHandler(ScrnInfoPtr pScrn)
876ad43ddacSmrg{
877ad43ddacSmrg    RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
878ad43ddacSmrg
879ad43ddacSmrg    if ((!pRADEONEnt->Controller[0]->enabled) &&
880ad43ddacSmrg	(!pRADEONEnt->Controller[1]->enabled))
881ad43ddacSmrg	RADEONSetStaticPowerMode(pScrn, POWER_LOW);
882ad43ddacSmrg    else
883ad43ddacSmrg	RADEONSetStaticPowerMode(pScrn, POWER_HIGH);
884ad43ddacSmrg
885ad43ddacSmrg}
886ad43ddacSmrg
887