legacy_output.c revision c503f109
1209ff23fSmrg/*
2209ff23fSmrg * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and
3209ff23fSmrg *                VA Linux Systems Inc., Fremont, California.
4209ff23fSmrg *
5209ff23fSmrg * All Rights Reserved.
6209ff23fSmrg *
7209ff23fSmrg * Permission is hereby granted, free of charge, to any person obtaining
8209ff23fSmrg * a copy of this software and associated documentation files (the
9209ff23fSmrg * "Software"), to deal in the Software without restriction, including
10209ff23fSmrg * without limitation on the rights to use, copy, modify, merge,
11209ff23fSmrg * publish, distribute, sublicense, and/or sell copies of the Software,
12209ff23fSmrg * and to permit persons to whom the Software is furnished to do so,
13209ff23fSmrg * subject to the following conditions:
14209ff23fSmrg *
15209ff23fSmrg * The above copyright notice and this permission notice (including the
16209ff23fSmrg * next paragraph) shall be included in all copies or substantial
17209ff23fSmrg * portions of the Software.
18209ff23fSmrg *
19209ff23fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20209ff23fSmrg * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21209ff23fSmrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22209ff23fSmrg * NON-INFRINGEMENT.  IN NO EVENT SHALL ATI, VA LINUX SYSTEMS AND/OR
23209ff23fSmrg * THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
24209ff23fSmrg * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25209ff23fSmrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26209ff23fSmrg * DEALINGS IN THE SOFTWARE.
27209ff23fSmrg */
28209ff23fSmrg
29209ff23fSmrg#ifdef HAVE_CONFIG_H
30209ff23fSmrg#include "config.h"
31209ff23fSmrg#endif
32209ff23fSmrg
33209ff23fSmrg#include <string.h>
34209ff23fSmrg#include <stdio.h>
35209ff23fSmrg
36209ff23fSmrg/* X and server generic header files */
37209ff23fSmrg#include "xf86.h"
38209ff23fSmrg#include "xf86_OSproc.h"
39209ff23fSmrg#include "vgaHW.h"
40209ff23fSmrg#include "xf86Modes.h"
41209ff23fSmrg
42209ff23fSmrg/* Driver data structures */
43209ff23fSmrg#include "radeon.h"
44209ff23fSmrg#include "radeon_reg.h"
45209ff23fSmrg#include "radeon_macros.h"
46209ff23fSmrg#include "radeon_probe.h"
47209ff23fSmrg#include "radeon_version.h"
48209ff23fSmrg#include "radeon_tv.h"
49209ff23fSmrg#include "radeon_atombios.h"
50209ff23fSmrg
51b7e1c893Smrg#include "ati_pciids_gen.h"
52b7e1c893Smrg
53209ff23fSmrgstatic RADEONMonitorType radeon_detect_tv(ScrnInfoPtr pScrn);
54209ff23fSmrgstatic RADEONMonitorType radeon_detect_primary_dac(ScrnInfoPtr pScrn, Bool color);
55209ff23fSmrgstatic RADEONMonitorType radeon_detect_tv_dac(ScrnInfoPtr pScrn, Bool color);
56209ff23fSmrgstatic RADEONMonitorType radeon_detect_ext_dac(ScrnInfoPtr pScrn);
57209ff23fSmrg
58b7e1c893Smrgextern Bool
59b7e1c893SmrgRADEONI2CInit(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr, char *name, RADEONI2CBusPtr pRADEONI2CBus);
60b7e1c893Smrg
61b7e1c893Smrgstatic const RADEONTMDSPll default_tmds_pll[CHIP_FAMILY_LAST][4] =
62b7e1c893Smrg{
63b7e1c893Smrg    {{0, 0}, {0, 0}, {0, 0}, {0, 0}},				/*CHIP_FAMILY_UNKNOW*/
64b7e1c893Smrg    {{0, 0}, {0, 0}, {0, 0}, {0, 0}},				/*CHIP_FAMILY_LEGACY*/
65b7e1c893Smrg    {{12000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}},	/*CHIP_FAMILY_RADEON*/
66b7e1c893Smrg    {{12000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}},	/*CHIP_FAMILY_RV100*/
67b7e1c893Smrg    {{0, 0}, {0, 0}, {0, 0}, {0, 0}},				/*CHIP_FAMILY_RS100*/
68b7e1c893Smrg    {{15000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}},	/*CHIP_FAMILY_RV200*/
69b7e1c893Smrg    {{12000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}},	/*CHIP_FAMILY_RS200*/
70b7e1c893Smrg    {{15000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}},	/*CHIP_FAMILY_R200*/
71b7e1c893Smrg    {{15500, 0x81b}, {0xffffffff, 0x83f}, {0, 0}, {0, 0}},	/*CHIP_FAMILY_RV250*/
72b7e1c893Smrg    {{0, 0}, {0, 0}, {0, 0}, {0, 0}},				/*CHIP_FAMILY_RS300*/
73b7e1c893Smrg    {{13000, 0x400f4}, {15000, 0x400f7}, {0xffffffff, 0x40111}, {0, 0}}, /*CHIP_FAMILY_RV280*/
74b7e1c893Smrg    {{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}},		/*CHIP_FAMILY_R300*/
75b7e1c893Smrg    {{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}},		/*CHIP_FAMILY_R350*/
76b7e1c893Smrg    {{15000, 0xb0155}, {0xffffffff, 0xb01cb}, {0, 0}, {0, 0}},	/*CHIP_FAMILY_RV350*/
77b7e1c893Smrg    {{15000, 0xb0155}, {0xffffffff, 0xb01cb}, {0, 0}, {0, 0}},	/*CHIP_FAMILY_RV380*/
78b7e1c893Smrg    {{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}},		/*CHIP_FAMILY_R420*/
79b7e1c893Smrg    {{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}},		/*CHIP_FAMILY_RV410*/ /* FIXME: just values from r420 used... */
80b7e1c893Smrg    {{15000, 0xb0155}, {0xffffffff, 0xb01cb}, {0, 0}, {0, 0}},	/*CHIP_FAMILY_RS400*/ /* FIXME: just values from rv380 used... */
81b7e1c893Smrg    {{15000, 0xb0155}, {0xffffffff, 0xb01cb}, {0, 0}, {0, 0}},	/*CHIP_FAMILY_RS480*/ /* FIXME: just values from rv380 used... */
82b7e1c893Smrg};
83b7e1c893Smrg
84b7e1c893Smrgstatic const uint32_t default_tvdac_adj [CHIP_FAMILY_LAST] =
85b7e1c893Smrg{
86b7e1c893Smrg    0x00000000,   /* unknown */
87b7e1c893Smrg    0x00000000,   /* legacy */
88b7e1c893Smrg    0x00000000,   /* r100 */
89b7e1c893Smrg    0x00280000,   /* rv100 */
90b7e1c893Smrg    0x00000000,   /* rs100 */
91b7e1c893Smrg    0x00880000,   /* rv200 */
92b7e1c893Smrg    0x00000000,   /* rs200 */
93b7e1c893Smrg    0x00000000,   /* r200 */
94b7e1c893Smrg    0x00770000,   /* rv250 */
95b7e1c893Smrg    0x00290000,   /* rs300 */
96b7e1c893Smrg    0x00560000,   /* rv280 */
97b7e1c893Smrg    0x00780000,   /* r300 */
98b7e1c893Smrg    0x00770000,   /* r350 */
99b7e1c893Smrg    0x00780000,   /* rv350 */
100b7e1c893Smrg    0x00780000,   /* rv380 */
101b7e1c893Smrg    0x01080000,   /* r420 */
102b7e1c893Smrg    0x01080000,   /* rv410 */ /* FIXME: just values from r420 used... */
103b7e1c893Smrg    0x00780000,   /* rs400 */ /* FIXME: just values from rv380 used... */
104b7e1c893Smrg    0x00780000,   /* rs480 */ /* FIXME: just values from rv380 used... */
105b7e1c893Smrg};
106b7e1c893Smrg
107b7e1c893Smrgvoid
108b7e1c893SmrgRADEONGetTVDacAdjInfo(ScrnInfoPtr pScrn, radeon_tvdac_ptr tvdac)
109b7e1c893Smrg{
110b7e1c893Smrg    RADEONInfoPtr  info       = RADEONPTR(pScrn);
111b7e1c893Smrg
112b7e1c893Smrg    if (!RADEONGetDAC2InfoFromBIOS(pScrn, tvdac)) {
113b7e1c893Smrg	tvdac->ps2_tvdac_adj = default_tvdac_adj[info->ChipFamily];
114b7e1c893Smrg	if (info->IsMobility) { /* some mobility chips may different */
115b7e1c893Smrg	    if (info->ChipFamily == CHIP_FAMILY_RV250)
116b7e1c893Smrg		tvdac->ps2_tvdac_adj = 0x00880000;
117b7e1c893Smrg	}
118b7e1c893Smrg	tvdac->pal_tvdac_adj = tvdac->ps2_tvdac_adj;
119b7e1c893Smrg	tvdac->ntsc_tvdac_adj = tvdac->ps2_tvdac_adj;
120b7e1c893Smrg    }
121b7e1c893Smrg}
122b7e1c893Smrg
123b7e1c893Smrgvoid
124b7e1c893SmrgRADEONGetTMDSInfoFromTable(ScrnInfoPtr pScrn, radeon_tmds_ptr tmds)
125b7e1c893Smrg{
126b7e1c893Smrg    RADEONInfoPtr  info       = RADEONPTR(pScrn);
127b7e1c893Smrg    int i;
128b7e1c893Smrg
129b7e1c893Smrg    for (i = 0; i < 4; i++) {
130b7e1c893Smrg        tmds->tmds_pll[i].value = default_tmds_pll[info->ChipFamily][i].value;
131b7e1c893Smrg        tmds->tmds_pll[i].freq = default_tmds_pll[info->ChipFamily][i].freq;
132b7e1c893Smrg    }
133b7e1c893Smrg}
134b7e1c893Smrg
135b7e1c893Smrgvoid
136b7e1c893SmrgRADEONGetTMDSInfo(ScrnInfoPtr pScrn, radeon_tmds_ptr tmds)
137b7e1c893Smrg{
138b7e1c893Smrg    int i;
139b7e1c893Smrg
140b7e1c893Smrg    for (i = 0; i < 4; i++) {
141b7e1c893Smrg	tmds->tmds_pll[i].value = 0;
142b7e1c893Smrg	tmds->tmds_pll[i].freq = 0;
143b7e1c893Smrg    }
144b7e1c893Smrg
145b7e1c893Smrg    if (!RADEONGetTMDSInfoFromBIOS(pScrn, tmds))
146b7e1c893Smrg	RADEONGetTMDSInfoFromTable(pScrn, tmds);
147b7e1c893Smrg}
148b7e1c893Smrg
149b7e1c893Smrgvoid
150b7e1c893SmrgRADEONGetExtTMDSInfo(ScrnInfoPtr pScrn, radeon_dvo_ptr dvo)
151b7e1c893Smrg{
152b7e1c893Smrg    RADEONInfoPtr  info       = RADEONPTR(pScrn);
153b7e1c893Smrg
154b7e1c893Smrg    if (!info->IsAtomBios) {
155b7e1c893Smrg#if defined(__powerpc__)
156b7e1c893Smrg	dvo->dvo_i2c = legacy_setup_i2c_bus(RADEON_GPIO_MONID);
157b7e1c893Smrg	dvo->dvo_i2c_slave_addr = 0x70;
158b7e1c893Smrg#else
159b7e1c893Smrg	if (!RADEONGetExtTMDSInfoFromBIOS(pScrn, dvo)) {
160b7e1c893Smrg	    dvo->dvo_i2c = legacy_setup_i2c_bus(RADEON_GPIO_CRT2_DDC);
161b7e1c893Smrg	    dvo->dvo_i2c_slave_addr = 0x70;
162b7e1c893Smrg	}
163b7e1c893Smrg#endif
164c503f109Smrg	if (RADEONI2CInit(pScrn, &dvo->pI2CBus, "DVO", &dvo->dvo_i2c)) {
165b7e1c893Smrg	    dvo->DVOChip =
166c503f109Smrg		RADEONDVODeviceInit(dvo->pI2CBus, dvo->dvo_i2c_slave_addr);
167b7e1c893Smrg	    if (!dvo->DVOChip)
168c503f109Smrg		xfree(dvo->pI2CBus);
169b7e1c893Smrg	}
170b7e1c893Smrg    }
171b7e1c893Smrg}
172b7e1c893Smrg
173b7e1c893Smrgstatic void
174b7e1c893SmrgRADEONGetPanelInfoFromReg (ScrnInfoPtr pScrn, radeon_lvds_ptr lvds)
175b7e1c893Smrg{
176b7e1c893Smrg    RADEONInfoPtr  info       = RADEONPTR(pScrn);
177b7e1c893Smrg    unsigned char *RADEONMMIO = info->MMIO;
178b7e1c893Smrg    radeon_native_mode_ptr native_mode = &lvds->native_mode;
179b7e1c893Smrg    uint32_t fp_vert_stretch = INREG(RADEON_FP_VERT_STRETCH);
180b7e1c893Smrg    uint32_t fp_horz_stretch = INREG(RADEON_FP_HORZ_STRETCH);
181b7e1c893Smrg
182b7e1c893Smrg    lvds->PanelPwrDly = 200;
183b7e1c893Smrg    if (fp_vert_stretch & RADEON_VERT_STRETCH_ENABLE) {
184b7e1c893Smrg	native_mode->PanelYRes = ((fp_vert_stretch & RADEON_VERT_PANEL_SIZE) >>
185b7e1c893Smrg				  RADEON_VERT_PANEL_SHIFT) + 1;
186b7e1c893Smrg    } else {
187b7e1c893Smrg	native_mode->PanelYRes = (INREG(RADEON_CRTC_V_TOTAL_DISP)>>16) + 1;
188b7e1c893Smrg    }
189b7e1c893Smrg    if (fp_horz_stretch & RADEON_HORZ_STRETCH_ENABLE) {
190b7e1c893Smrg	native_mode->PanelXRes = (((fp_horz_stretch & RADEON_HORZ_PANEL_SIZE) >>
191b7e1c893Smrg				   RADEON_HORZ_PANEL_SHIFT) + 1) * 8;
192b7e1c893Smrg    } else {
193b7e1c893Smrg	native_mode->PanelXRes = ((INREG(RADEON_CRTC_H_TOTAL_DISP)>>16) + 1) * 8;
194b7e1c893Smrg    }
195b7e1c893Smrg
196b7e1c893Smrg    if ((native_mode->PanelXRes < 640) || (native_mode->PanelYRes < 480)) {
197b7e1c893Smrg	native_mode->PanelXRes = 640;
198b7e1c893Smrg	native_mode->PanelYRes = 480;
199b7e1c893Smrg    }
200b7e1c893Smrg
201b7e1c893Smrg    // move this to crtc function
202b7e1c893Smrg    if (xf86ReturnOptValBool(info->Options, OPTION_LVDS_PROBE_PLL, TRUE)) {
203b7e1c893Smrg           uint32_t ppll_div_sel, ppll_val;
204b7e1c893Smrg
205b7e1c893Smrg           ppll_div_sel = INREG8(RADEON_CLOCK_CNTL_INDEX + 1) & 0x3;
206b7e1c893Smrg	   RADEONPllErrataAfterIndex(info);
207b7e1c893Smrg	   ppll_val = INPLL(pScrn, RADEON_PPLL_DIV_0 + ppll_div_sel);
208b7e1c893Smrg           if ((ppll_val & 0x000707ff) == 0x1bb)
209b7e1c893Smrg		   goto noprobe;
210b7e1c893Smrg	   info->FeedbackDivider = ppll_val & 0x7ff;
211b7e1c893Smrg	   info->PostDivider = (ppll_val >> 16) & 0x7;
212b7e1c893Smrg	   info->RefDivider = info->pll.reference_div;
213b7e1c893Smrg	   info->UseBiosDividers = TRUE;
214b7e1c893Smrg
215b7e1c893Smrg           xf86DrvMsg(pScrn->scrnIndex, X_INFO,
216b7e1c893Smrg                      "Existing panel PLL dividers will be used.\n");
217b7e1c893Smrg    }
218b7e1c893Smrg noprobe:
219b7e1c893Smrg
220b7e1c893Smrg    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
221b7e1c893Smrg	       "Panel size %dx%d is derived, this may not be correct.\n"
222b7e1c893Smrg		   "If not, use PanelSize option to overwrite this setting\n",
223b7e1c893Smrg	       native_mode->PanelXRes, native_mode->PanelYRes);
224b7e1c893Smrg}
225b7e1c893Smrg
226b7e1c893Smrgvoid
227b7e1c893SmrgRADEONGetLVDSInfo (ScrnInfoPtr pScrn, radeon_lvds_ptr lvds)
228b7e1c893Smrg{
229b7e1c893Smrg    RADEONInfoPtr  info       = RADEONPTR(pScrn);
230b7e1c893Smrg    radeon_native_mode_ptr native_mode = &lvds->native_mode;
231b7e1c893Smrg    char* s;
232b7e1c893Smrg
233b7e1c893Smrg    if (!RADEONGetLVDSInfoFromBIOS(pScrn, lvds))
234b7e1c893Smrg	RADEONGetPanelInfoFromReg(pScrn, lvds);
235b7e1c893Smrg
236b7e1c893Smrg    if ((s = xf86GetOptValString(info->Options, OPTION_PANEL_SIZE))) {
237b7e1c893Smrg	lvds->PanelPwrDly = 200;
238b7e1c893Smrg	if (sscanf (s, "%dx%d", &native_mode->PanelXRes, &native_mode->PanelYRes) != 2) {
239b7e1c893Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Invalid PanelSize option: %s\n", s);
240b7e1c893Smrg	    RADEONGetPanelInfoFromReg(pScrn, lvds);
241b7e1c893Smrg	}
242b7e1c893Smrg    }
243b7e1c893Smrg}
244b7e1c893Smrg
245209ff23fSmrgvoid
246209ff23fSmrgRADEONRestoreDACRegisters(ScrnInfoPtr pScrn,
247209ff23fSmrg			  RADEONSavePtr restore)
248209ff23fSmrg{
249209ff23fSmrg    RADEONInfoPtr  info       = RADEONPTR(pScrn);
250209ff23fSmrg    unsigned char *RADEONMMIO = info->MMIO;
251209ff23fSmrg
252209ff23fSmrg    if (IS_R300_VARIANT)
253209ff23fSmrg	OUTREGP(RADEON_GPIOPAD_A, restore->gpiopad_a, ~1);
254209ff23fSmrg
255209ff23fSmrg    OUTREGP(RADEON_DAC_CNTL,
256209ff23fSmrg	    restore->dac_cntl,
257209ff23fSmrg	    RADEON_DAC_RANGE_CNTL |
258209ff23fSmrg	    RADEON_DAC_BLANKING);
259209ff23fSmrg
260209ff23fSmrg    OUTREG(RADEON_DAC_CNTL2, restore->dac2_cntl);
261209ff23fSmrg
262209ff23fSmrg    if ((info->ChipFamily != CHIP_FAMILY_RADEON) &&
263209ff23fSmrg	(info->ChipFamily != CHIP_FAMILY_R200))
264209ff23fSmrg    OUTREG (RADEON_TV_DAC_CNTL, restore->tv_dac_cntl);
265209ff23fSmrg
266209ff23fSmrg    OUTREG(RADEON_DISP_OUTPUT_CNTL, restore->disp_output_cntl);
267209ff23fSmrg
268209ff23fSmrg    if ((info->ChipFamily == CHIP_FAMILY_R200) ||
269209ff23fSmrg	IS_R300_VARIANT) {
270209ff23fSmrg	OUTREG(RADEON_DISP_TV_OUT_CNTL, restore->disp_tv_out_cntl);
271209ff23fSmrg    } else {
272209ff23fSmrg	OUTREG(RADEON_DISP_HW_DEBUG, restore->disp_hw_debug);
273209ff23fSmrg    }
274209ff23fSmrg
275209ff23fSmrg    OUTREG(RADEON_DAC_MACRO_CNTL, restore->dac_macro_cntl);
276209ff23fSmrg
277209ff23fSmrg    /* R200 DAC connected via DVO */
278209ff23fSmrg    if (info->ChipFamily == CHIP_FAMILY_R200)
279209ff23fSmrg	OUTREG(RADEON_FP2_GEN_CNTL, restore->fp2_gen_cntl);
280209ff23fSmrg}
281209ff23fSmrg
282209ff23fSmrg
283209ff23fSmrg/* Write TMDS registers */
284209ff23fSmrgvoid
285209ff23fSmrgRADEONRestoreFPRegisters(ScrnInfoPtr pScrn, RADEONSavePtr restore)
286209ff23fSmrg{
287209ff23fSmrg    RADEONInfoPtr  info       = RADEONPTR(pScrn);
288209ff23fSmrg    RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
289209ff23fSmrg    unsigned char *RADEONMMIO = info->MMIO;
290209ff23fSmrg
291209ff23fSmrg    OUTREG(RADEON_TMDS_PLL_CNTL,        restore->tmds_pll_cntl);
292209ff23fSmrg    OUTREG(RADEON_TMDS_TRANSMITTER_CNTL,restore->tmds_transmitter_cntl);
293209ff23fSmrg    OUTREG(RADEON_FP_GEN_CNTL,          restore->fp_gen_cntl);
294209ff23fSmrg
295209ff23fSmrg    if ((info->ChipFamily == CHIP_FAMILY_RS400) ||
296209ff23fSmrg	(info->ChipFamily == CHIP_FAMILY_RS480)) {
297209ff23fSmrg	OUTREG(RS400_FP_2ND_GEN_CNTL, restore->fp_2nd_gen_cntl);
298209ff23fSmrg	/*OUTREG(RS400_TMDS2_CNTL, restore->tmds2_cntl);*/
299209ff23fSmrg	OUTREG(RS400_TMDS2_TRANSMITTER_CNTL, restore->tmds2_transmitter_cntl);
300209ff23fSmrg    }
301209ff23fSmrg
302209ff23fSmrg    /* old AIW Radeon has some BIOS initialization problem
303209ff23fSmrg     * with display buffer underflow, only occurs to DFP
304209ff23fSmrg     */
305209ff23fSmrg    if (!pRADEONEnt->HasCRTC2)
306209ff23fSmrg	OUTREG(RADEON_GRPH_BUFFER_CNTL,
307209ff23fSmrg	       INREG(RADEON_GRPH_BUFFER_CNTL) & ~0x7f0000);
308209ff23fSmrg
309209ff23fSmrg}
310209ff23fSmrg
311209ff23fSmrg/* Write FP2 registers */
312209ff23fSmrgvoid
313209ff23fSmrgRADEONRestoreFP2Registers(ScrnInfoPtr pScrn, RADEONSavePtr restore)
314209ff23fSmrg{
315209ff23fSmrg    RADEONInfoPtr  info       = RADEONPTR(pScrn);
316209ff23fSmrg    unsigned char *RADEONMMIO = info->MMIO;
317209ff23fSmrg
318209ff23fSmrg    OUTREG(RADEON_FP2_GEN_CNTL,         restore->fp2_gen_cntl);
319209ff23fSmrg
320209ff23fSmrg    if ((info->ChipFamily == CHIP_FAMILY_RS400) ||
321209ff23fSmrg	(info->ChipFamily == CHIP_FAMILY_RS480))
322209ff23fSmrg	OUTREG(RS400_FP2_2_GEN_CNTL, restore->fp2_2_gen_cntl);
323209ff23fSmrg}
324209ff23fSmrg
325209ff23fSmrg/* Write RMX registers */
326209ff23fSmrgvoid
327209ff23fSmrgRADEONRestoreRMXRegisters(ScrnInfoPtr pScrn, RADEONSavePtr restore)
328209ff23fSmrg{
329209ff23fSmrg    RADEONInfoPtr  info       = RADEONPTR(pScrn);
330209ff23fSmrg    unsigned char *RADEONMMIO = info->MMIO;
331209ff23fSmrg
332209ff23fSmrg    OUTREG(RADEON_FP_HORZ_STRETCH,      restore->fp_horz_stretch);
333209ff23fSmrg    OUTREG(RADEON_FP_VERT_STRETCH,      restore->fp_vert_stretch);
334209ff23fSmrg    OUTREG(RADEON_CRTC_MORE_CNTL,       restore->crtc_more_cntl);
335209ff23fSmrg    OUTREG(RADEON_FP_HORZ_VERT_ACTIVE,  restore->fp_horz_vert_active);
336209ff23fSmrg    OUTREG(RADEON_FP_H_SYNC_STRT_WID,   restore->fp_h_sync_strt_wid);
337209ff23fSmrg    OUTREG(RADEON_FP_V_SYNC_STRT_WID,   restore->fp_v_sync_strt_wid);
338209ff23fSmrg    OUTREG(RADEON_FP_CRTC_H_TOTAL_DISP, restore->fp_crtc_h_total_disp);
339209ff23fSmrg    OUTREG(RADEON_FP_CRTC_V_TOTAL_DISP, restore->fp_crtc_v_total_disp);
340209ff23fSmrg
341209ff23fSmrg}
342209ff23fSmrg
343209ff23fSmrg/* Write LVDS registers */
344209ff23fSmrgvoid
345209ff23fSmrgRADEONRestoreLVDSRegisters(ScrnInfoPtr pScrn, RADEONSavePtr restore)
346209ff23fSmrg{
347209ff23fSmrg    RADEONInfoPtr  info       = RADEONPTR(pScrn);
348209ff23fSmrg    unsigned char *RADEONMMIO = info->MMIO;
349209ff23fSmrg
350209ff23fSmrg    if (info->IsMobility) {
351209ff23fSmrg	OUTREG(RADEON_LVDS_GEN_CNTL,  restore->lvds_gen_cntl);
352209ff23fSmrg	/*OUTREG(RADEON_LVDS_PLL_CNTL,  restore->lvds_pll_cntl);*/
353209ff23fSmrg
354209ff23fSmrg	if (info->ChipFamily == CHIP_FAMILY_RV410) {
355209ff23fSmrg	    OUTREG(RADEON_CLOCK_CNTL_INDEX, 0);
356209ff23fSmrg	}
357209ff23fSmrg    }
358209ff23fSmrg
359209ff23fSmrg}
360209ff23fSmrg
361209ff23fSmrgvoid
362209ff23fSmrgRADEONSaveDACRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save)
363209ff23fSmrg{
364209ff23fSmrg    RADEONInfoPtr  info       = RADEONPTR(pScrn);
365209ff23fSmrg    unsigned char *RADEONMMIO = info->MMIO;
366209ff23fSmrg
367209ff23fSmrg    save->dac_cntl              = INREG(RADEON_DAC_CNTL);
368209ff23fSmrg    save->dac2_cntl             = INREG(RADEON_DAC_CNTL2);
369209ff23fSmrg    save->tv_dac_cntl           = INREG(RADEON_TV_DAC_CNTL);
370209ff23fSmrg    save->disp_output_cntl      = INREG(RADEON_DISP_OUTPUT_CNTL);
371209ff23fSmrg    save->disp_tv_out_cntl      = INREG(RADEON_DISP_TV_OUT_CNTL);
372209ff23fSmrg    save->disp_hw_debug         = INREG(RADEON_DISP_HW_DEBUG);
373209ff23fSmrg    save->dac_macro_cntl        = INREG(RADEON_DAC_MACRO_CNTL);
374209ff23fSmrg    save->gpiopad_a             = INREG(RADEON_GPIOPAD_A);
375209ff23fSmrg
376209ff23fSmrg}
377209ff23fSmrg
378209ff23fSmrg/* Read flat panel registers */
379209ff23fSmrgvoid
380209ff23fSmrgRADEONSaveFPRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save)
381209ff23fSmrg{
382209ff23fSmrg    RADEONInfoPtr  info       = RADEONPTR(pScrn);
383209ff23fSmrg    unsigned char *RADEONMMIO = info->MMIO;
384209ff23fSmrg
385209ff23fSmrg    save->fp_gen_cntl          = INREG(RADEON_FP_GEN_CNTL);
386209ff23fSmrg    save->fp2_gen_cntl          = INREG (RADEON_FP2_GEN_CNTL);
387209ff23fSmrg    save->fp_horz_stretch      = INREG(RADEON_FP_HORZ_STRETCH);
388209ff23fSmrg    save->fp_vert_stretch      = INREG(RADEON_FP_VERT_STRETCH);
389209ff23fSmrg    save->fp_horz_vert_active  = INREG(RADEON_FP_HORZ_VERT_ACTIVE);
390209ff23fSmrg    save->crtc_more_cntl       = INREG(RADEON_CRTC_MORE_CNTL);
391209ff23fSmrg    save->lvds_gen_cntl        = INREG(RADEON_LVDS_GEN_CNTL);
392209ff23fSmrg    save->lvds_pll_cntl        = INREG(RADEON_LVDS_PLL_CNTL);
393209ff23fSmrg    save->tmds_pll_cntl        = INREG(RADEON_TMDS_PLL_CNTL);
394209ff23fSmrg    save->tmds_transmitter_cntl= INREG(RADEON_TMDS_TRANSMITTER_CNTL);
395209ff23fSmrg
396209ff23fSmrg    save->fp_h_sync_strt_wid   = INREG(RADEON_FP_H_SYNC_STRT_WID);
397209ff23fSmrg    save->fp_v_sync_strt_wid   = INREG(RADEON_FP_V_SYNC_STRT_WID);
398209ff23fSmrg    save->fp_crtc_h_total_disp = INREG(RADEON_FP_CRTC_H_TOTAL_DISP);
399209ff23fSmrg    save->fp_crtc_v_total_disp = INREG(RADEON_FP_CRTC_V_TOTAL_DISP);
400209ff23fSmrg
401209ff23fSmrg    if (info->ChipFamily == CHIP_FAMILY_RV280) {
402209ff23fSmrg	/* bit 22 of TMDS_PLL_CNTL is read-back inverted */
403209ff23fSmrg	save->tmds_pll_cntl ^= (1 << 22);
404209ff23fSmrg    }
405209ff23fSmrg
406209ff23fSmrg    if ((info->ChipFamily == CHIP_FAMILY_RS400) ||
407209ff23fSmrg	(info->ChipFamily == CHIP_FAMILY_RS480)) {
408209ff23fSmrg	save->fp_2nd_gen_cntl         = INREG(RS400_FP_2ND_GEN_CNTL);
409209ff23fSmrg	save->fp2_2_gen_cntl          = INREG(RS400_FP2_2_GEN_CNTL);
410209ff23fSmrg	save->tmds2_cntl              = INREG(RS400_TMDS2_CNTL);
411209ff23fSmrg	save->tmds2_transmitter_cntl  = INREG(RS400_TMDS2_TRANSMITTER_CNTL);
412209ff23fSmrg    }
413209ff23fSmrg
414209ff23fSmrg}
415209ff23fSmrg
416209ff23fSmrgBool
417209ff23fSmrgRADEONDVOReadByte(I2CDevPtr dvo, int addr, uint8_t *ch)
418209ff23fSmrg{
419209ff23fSmrg    if (!xf86I2CReadByte(dvo, addr, ch)) {
420209ff23fSmrg	xf86DrvMsg(dvo->pI2CBus->scrnIndex, X_ERROR,
421209ff23fSmrg		   "Unable to read from %s Slave %d.\n",
422209ff23fSmrg		   dvo->pI2CBus->BusName, dvo->SlaveAddr);
423209ff23fSmrg	return FALSE;
424209ff23fSmrg    }
425209ff23fSmrg    return TRUE;
426209ff23fSmrg}
427209ff23fSmrg
428209ff23fSmrgBool
429209ff23fSmrgRADEONDVOWriteByte(I2CDevPtr dvo, int addr, uint8_t ch)
430209ff23fSmrg{
431209ff23fSmrg    if (!xf86I2CWriteByte(dvo, addr, ch)) {
432209ff23fSmrg	xf86DrvMsg(dvo->pI2CBus->scrnIndex, X_ERROR,
433209ff23fSmrg		   "Unable to write to %s Slave %d.\n",
434209ff23fSmrg		   dvo->pI2CBus->BusName, dvo->SlaveAddr);
435209ff23fSmrg	return FALSE;
436209ff23fSmrg    }
437209ff23fSmrg    return TRUE;
438209ff23fSmrg}
439209ff23fSmrg
440209ff23fSmrgI2CDevPtr
441209ff23fSmrgRADEONDVODeviceInit(I2CBusPtr b, I2CSlaveAddr addr)
442209ff23fSmrg{
443209ff23fSmrg    I2CDevPtr dvo;
444209ff23fSmrg
445209ff23fSmrg    dvo = xcalloc(1, sizeof(I2CDevRec));
446209ff23fSmrg    if (dvo == NULL)
447209ff23fSmrg	return NULL;
448209ff23fSmrg
449209ff23fSmrg    dvo->DevName = "RADEON DVO Controller";
450209ff23fSmrg    dvo->SlaveAddr = addr;
451209ff23fSmrg    dvo->pI2CBus = b;
452209ff23fSmrg    dvo->StartTimeout = b->StartTimeout;
453209ff23fSmrg    dvo->BitTimeout = b->BitTimeout;
454209ff23fSmrg    dvo->AcknTimeout = b->AcknTimeout;
455209ff23fSmrg    dvo->ByteTimeout = b->ByteTimeout;
456209ff23fSmrg
457209ff23fSmrg    if (xf86I2CDevInit(dvo)) {
458209ff23fSmrg	return dvo;
459209ff23fSmrg    }
460209ff23fSmrg
461209ff23fSmrg    xfree(dvo);
462209ff23fSmrg    return NULL;
463209ff23fSmrg}
464209ff23fSmrg
465209ff23fSmrgstatic void
466209ff23fSmrgRADEONRestoreDVOChip(ScrnInfoPtr pScrn, xf86OutputPtr output)
467209ff23fSmrg{
468209ff23fSmrg    RADEONInfoPtr info = RADEONPTR(pScrn);
469b7e1c893Smrg    radeon_encoder_ptr radeon_encoder = radeon_get_encoder(output);
470b7e1c893Smrg    radeon_dvo_ptr dvo = NULL;
471209ff23fSmrg
472b7e1c893Smrg    if (radeon_encoder == NULL)
473209ff23fSmrg	return;
474209ff23fSmrg
475b7e1c893Smrg    dvo = (radeon_dvo_ptr)radeon_encoder->dev_priv;
476b7e1c893Smrg
477b7e1c893Smrg    if (dvo == NULL)
478b7e1c893Smrg	return;
479209ff23fSmrg
480b7e1c893Smrg    if (!dvo->DVOChip)
481b7e1c893Smrg	return;
482b7e1c893Smrg
483c503f109Smrg    RADEONI2CDoLock(output, dvo->pI2CBus, TRUE);
484209ff23fSmrg    if (!RADEONInitExtTMDSInfoFromBIOS(output)) {
485b7e1c893Smrg	if (dvo->DVOChip) {
486209ff23fSmrg	    switch(info->ext_tmds_chip) {
487209ff23fSmrg	    case RADEON_SIL_164:
488b7e1c893Smrg		RADEONDVOWriteByte(dvo->DVOChip, 0x08, 0x30);
489b7e1c893Smrg		RADEONDVOWriteByte(dvo->DVOChip, 0x09, 0x00);
490b7e1c893Smrg		RADEONDVOWriteByte(dvo->DVOChip, 0x0a, 0x90);
491b7e1c893Smrg		RADEONDVOWriteByte(dvo->DVOChip, 0x0c, 0x89);
492b7e1c893Smrg		RADEONDVOWriteByte(dvo->DVOChip, 0x08, 0x3b);
493209ff23fSmrg		break;
494209ff23fSmrg#if 0
495209ff23fSmrg		/* needs work see bug 10418 */
496209ff23fSmrg	    case RADEON_SIL_1178:
497b7e1c893Smrg		RADEONDVOWriteByte(dvo->DVOChip, 0x0f, 0x44);
498b7e1c893Smrg		RADEONDVOWriteByte(dvo->DVOChip, 0x0f, 0x4c);
499b7e1c893Smrg		RADEONDVOWriteByte(dvo->DVOChip, 0x0e, 0x01);
500b7e1c893Smrg		RADEONDVOWriteByte(dvo->DVOChip, 0x0a, 0x80);
501b7e1c893Smrg                RADEONDVOWriteByte(dvo->DVOChip, 0x09, 0x30);
502b7e1c893Smrg                RADEONDVOWriteByte(dvo->DVOChip, 0x0c, 0xc9);
503b7e1c893Smrg                RADEONDVOWriteByte(dvo->DVOChip, 0x0d, 0x70);
504b7e1c893Smrg                RADEONDVOWriteByte(dvo->DVOChip, 0x08, 0x32);
505b7e1c893Smrg                RADEONDVOWriteByte(dvo->DVOChip, 0x08, 0x33);
506209ff23fSmrg		break;
507209ff23fSmrg#endif
508209ff23fSmrg	    default:
509209ff23fSmrg		break;
510209ff23fSmrg	    }
511209ff23fSmrg	}
512209ff23fSmrg    }
513c503f109Smrg    RADEONI2CDoLock(output, dvo->pI2CBus, FALSE);
514209ff23fSmrg}
515209ff23fSmrg
516209ff23fSmrg#if 0
517209ff23fSmrgstatic RADEONMonitorType
518209ff23fSmrgRADEONCrtIsPhysicallyConnected(ScrnInfoPtr pScrn, int IsCrtDac)
519209ff23fSmrg{
520209ff23fSmrg    RADEONInfoPtr info       = RADEONPTR(pScrn);
521209ff23fSmrg    unsigned char *RADEONMMIO = info->MMIO;
522209ff23fSmrg    int		  bConnected = 0;
523209ff23fSmrg
524209ff23fSmrg    /* the monitor either wasn't connected or it is a non-DDC CRT.
525209ff23fSmrg     * try to probe it
526209ff23fSmrg     */
527209ff23fSmrg    if(IsCrtDac) {
528209ff23fSmrg	unsigned long ulOrigVCLK_ECP_CNTL;
529209ff23fSmrg	unsigned long ulOrigDAC_CNTL;
530209ff23fSmrg	unsigned long ulOrigDAC_MACRO_CNTL;
531209ff23fSmrg	unsigned long ulOrigDAC_EXT_CNTL;
532209ff23fSmrg	unsigned long ulOrigCRTC_EXT_CNTL;
533209ff23fSmrg	unsigned long ulData;
534209ff23fSmrg	unsigned long ulMask;
535209ff23fSmrg
536209ff23fSmrg	ulOrigVCLK_ECP_CNTL = INPLL(pScrn, RADEON_VCLK_ECP_CNTL);
537209ff23fSmrg
538209ff23fSmrg	ulData              = ulOrigVCLK_ECP_CNTL;
539209ff23fSmrg	ulData             &= ~(RADEON_PIXCLK_ALWAYS_ONb
540209ff23fSmrg				| RADEON_PIXCLK_DAC_ALWAYS_ONb);
541209ff23fSmrg	ulMask              = ~(RADEON_PIXCLK_ALWAYS_ONb
542209ff23fSmrg				|RADEON_PIXCLK_DAC_ALWAYS_ONb);
543209ff23fSmrg	OUTPLLP(pScrn, RADEON_VCLK_ECP_CNTL, ulData, ulMask);
544209ff23fSmrg
545209ff23fSmrg	ulOrigCRTC_EXT_CNTL = INREG(RADEON_CRTC_EXT_CNTL);
546209ff23fSmrg	ulData              = ulOrigCRTC_EXT_CNTL;
547209ff23fSmrg	ulData             |= RADEON_CRTC_CRT_ON;
548209ff23fSmrg	OUTREG(RADEON_CRTC_EXT_CNTL, ulData);
549209ff23fSmrg
550209ff23fSmrg	ulOrigDAC_EXT_CNTL = INREG(RADEON_DAC_EXT_CNTL);
551209ff23fSmrg	ulData             = ulOrigDAC_EXT_CNTL;
552209ff23fSmrg	ulData            &= ~RADEON_DAC_FORCE_DATA_MASK;
553209ff23fSmrg	ulData            |=  (RADEON_DAC_FORCE_BLANK_OFF_EN
554209ff23fSmrg			       |RADEON_DAC_FORCE_DATA_EN
555209ff23fSmrg			       |RADEON_DAC_FORCE_DATA_SEL_MASK);
556209ff23fSmrg	if ((info->ChipFamily == CHIP_FAMILY_RV250) ||
557209ff23fSmrg	    (info->ChipFamily == CHIP_FAMILY_RV280))
558209ff23fSmrg	    ulData |= (0x01b6 << RADEON_DAC_FORCE_DATA_SHIFT);
559209ff23fSmrg	else
560209ff23fSmrg	    ulData |= (0x01ac << RADEON_DAC_FORCE_DATA_SHIFT);
561209ff23fSmrg
562209ff23fSmrg	OUTREG(RADEON_DAC_EXT_CNTL, ulData);
563209ff23fSmrg
564209ff23fSmrg	/* turn on power so testing can go through */
565209ff23fSmrg	ulOrigDAC_CNTL = INREG(RADEON_DAC_CNTL);
566209ff23fSmrg	ulOrigDAC_CNTL &= ~RADEON_DAC_PDWN;
567209ff23fSmrg	OUTREG(RADEON_DAC_CNTL, ulOrigDAC_CNTL);
568209ff23fSmrg
569209ff23fSmrg	ulOrigDAC_MACRO_CNTL = INREG(RADEON_DAC_MACRO_CNTL);
570209ff23fSmrg	ulOrigDAC_MACRO_CNTL &= ~(RADEON_DAC_PDWN_R | RADEON_DAC_PDWN_G |
571209ff23fSmrg				  RADEON_DAC_PDWN_B);
572209ff23fSmrg	OUTREG(RADEON_DAC_MACRO_CNTL, ulOrigDAC_MACRO_CNTL);
573209ff23fSmrg
574209ff23fSmrg	/* Enable comparators and set DAC range to PS2 (VGA) output level */
575209ff23fSmrg	ulData = ulOrigDAC_CNTL;
576209ff23fSmrg	ulData |= RADEON_DAC_CMP_EN;
577209ff23fSmrg	ulData &= ~RADEON_DAC_RANGE_CNTL_MASK;
578209ff23fSmrg	ulData |= 0x2;
579209ff23fSmrg	OUTREG(RADEON_DAC_CNTL, ulData);
580209ff23fSmrg
581209ff23fSmrg	/* Settle down */
582209ff23fSmrg	usleep(10000);
583209ff23fSmrg
584209ff23fSmrg	/* Read comparators */
585209ff23fSmrg	ulData     = INREG(RADEON_DAC_CNTL);
586209ff23fSmrg	bConnected =  (RADEON_DAC_CMP_OUTPUT & ulData)?1:0;
587209ff23fSmrg
588209ff23fSmrg	/* Restore things */
589209ff23fSmrg	ulData    = ulOrigVCLK_ECP_CNTL;
590209ff23fSmrg	ulMask    = 0xFFFFFFFFL;
591209ff23fSmrg	OUTPLLP(pScrn, RADEON_VCLK_ECP_CNTL, ulData, ulMask);
592209ff23fSmrg
593209ff23fSmrg	OUTREG(RADEON_DAC_CNTL,      ulOrigDAC_CNTL     );
594209ff23fSmrg	OUTREG(RADEON_DAC_EXT_CNTL,  ulOrigDAC_EXT_CNTL );
595209ff23fSmrg	OUTREG(RADEON_CRTC_EXT_CNTL, ulOrigCRTC_EXT_CNTL);
596209ff23fSmrg
597209ff23fSmrg	if (!bConnected) {
598209ff23fSmrg	    /* Power DAC down if CRT is not connected */
599209ff23fSmrg            ulOrigDAC_MACRO_CNTL = INREG(RADEON_DAC_MACRO_CNTL);
600209ff23fSmrg            ulOrigDAC_MACRO_CNTL |= (RADEON_DAC_PDWN_R | RADEON_DAC_PDWN_G |
601209ff23fSmrg	    	RADEON_DAC_PDWN_B);
602209ff23fSmrg            OUTREG(RADEON_DAC_MACRO_CNTL, ulOrigDAC_MACRO_CNTL);
603209ff23fSmrg
604209ff23fSmrg	    ulData = INREG(RADEON_DAC_CNTL);
605209ff23fSmrg	    ulData |= RADEON_DAC_PDWN;
606209ff23fSmrg	    OUTREG(RADEON_DAC_CNTL, ulData);
607209ff23fSmrg    	}
608209ff23fSmrg    } else { /* TV DAC */
609209ff23fSmrg
610209ff23fSmrg        /* This doesn't seem to work reliably (maybe worse on some OEM cards),
611209ff23fSmrg           for now we always return false. If one wants to connected a
612209ff23fSmrg           non-DDC monitor on the DVI port when CRT port is also connected,
613209ff23fSmrg           he will need to explicitly tell the driver in the config file
614209ff23fSmrg           with Option MonitorLayout.
615209ff23fSmrg        */
616209ff23fSmrg        bConnected = FALSE;
617209ff23fSmrg
618209ff23fSmrg#if 0
619209ff23fSmrg	if (info->ChipFamily == CHIP_FAMILY_R200) {
620209ff23fSmrg	    unsigned long ulOrigGPIO_MONID;
621209ff23fSmrg	    unsigned long ulOrigFP2_GEN_CNTL;
622209ff23fSmrg	    unsigned long ulOrigDISP_OUTPUT_CNTL;
623209ff23fSmrg	    unsigned long ulOrigCRTC2_GEN_CNTL;
624209ff23fSmrg	    unsigned long ulOrigDISP_LIN_TRANS_GRPH_A;
625209ff23fSmrg	    unsigned long ulOrigDISP_LIN_TRANS_GRPH_B;
626209ff23fSmrg	    unsigned long ulOrigDISP_LIN_TRANS_GRPH_C;
627209ff23fSmrg	    unsigned long ulOrigDISP_LIN_TRANS_GRPH_D;
628209ff23fSmrg	    unsigned long ulOrigDISP_LIN_TRANS_GRPH_E;
629209ff23fSmrg	    unsigned long ulOrigDISP_LIN_TRANS_GRPH_F;
630209ff23fSmrg	    unsigned long ulOrigCRTC2_H_TOTAL_DISP;
631209ff23fSmrg	    unsigned long ulOrigCRTC2_V_TOTAL_DISP;
632209ff23fSmrg	    unsigned long ulOrigCRTC2_H_SYNC_STRT_WID;
633209ff23fSmrg	    unsigned long ulOrigCRTC2_V_SYNC_STRT_WID;
634209ff23fSmrg	    unsigned long ulData, i;
635209ff23fSmrg
636209ff23fSmrg	    ulOrigGPIO_MONID = INREG(RADEON_GPIO_MONID);
637209ff23fSmrg	    ulOrigFP2_GEN_CNTL = INREG(RADEON_FP2_GEN_CNTL);
638209ff23fSmrg	    ulOrigDISP_OUTPUT_CNTL = INREG(RADEON_DISP_OUTPUT_CNTL);
639209ff23fSmrg	    ulOrigCRTC2_GEN_CNTL = INREG(RADEON_CRTC2_GEN_CNTL);
640209ff23fSmrg	    ulOrigDISP_LIN_TRANS_GRPH_A = INREG(RADEON_DISP_LIN_TRANS_GRPH_A);
641209ff23fSmrg	    ulOrigDISP_LIN_TRANS_GRPH_B = INREG(RADEON_DISP_LIN_TRANS_GRPH_B);
642209ff23fSmrg	    ulOrigDISP_LIN_TRANS_GRPH_C = INREG(RADEON_DISP_LIN_TRANS_GRPH_C);
643209ff23fSmrg	    ulOrigDISP_LIN_TRANS_GRPH_D = INREG(RADEON_DISP_LIN_TRANS_GRPH_D);
644209ff23fSmrg	    ulOrigDISP_LIN_TRANS_GRPH_E = INREG(RADEON_DISP_LIN_TRANS_GRPH_E);
645209ff23fSmrg	    ulOrigDISP_LIN_TRANS_GRPH_F = INREG(RADEON_DISP_LIN_TRANS_GRPH_F);
646209ff23fSmrg
647209ff23fSmrg	    ulOrigCRTC2_H_TOTAL_DISP = INREG(RADEON_CRTC2_H_TOTAL_DISP);
648209ff23fSmrg	    ulOrigCRTC2_V_TOTAL_DISP = INREG(RADEON_CRTC2_V_TOTAL_DISP);
649209ff23fSmrg	    ulOrigCRTC2_H_SYNC_STRT_WID = INREG(RADEON_CRTC2_H_SYNC_STRT_WID);
650209ff23fSmrg	    ulOrigCRTC2_V_SYNC_STRT_WID = INREG(RADEON_CRTC2_V_SYNC_STRT_WID);
651209ff23fSmrg
652209ff23fSmrg	    ulData     = INREG(RADEON_GPIO_MONID);
653209ff23fSmrg	    ulData    &= ~RADEON_GPIO_A_0;
654209ff23fSmrg	    OUTREG(RADEON_GPIO_MONID, ulData);
655209ff23fSmrg
656209ff23fSmrg	    OUTREG(RADEON_FP2_GEN_CNTL, 0x0a000c0c);
657209ff23fSmrg
658209ff23fSmrg	    OUTREG(RADEON_DISP_OUTPUT_CNTL, 0x00000012);
659209ff23fSmrg
660209ff23fSmrg	    OUTREG(RADEON_CRTC2_GEN_CNTL, 0x06000000);
661209ff23fSmrg	    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_A, 0x00000000);
662209ff23fSmrg	    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_B, 0x000003f0);
663209ff23fSmrg	    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_C, 0x00000000);
664209ff23fSmrg	    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_D, 0x000003f0);
665209ff23fSmrg	    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_E, 0x00000000);
666209ff23fSmrg	    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_F, 0x000003f0);
667209ff23fSmrg	    OUTREG(RADEON_CRTC2_H_TOTAL_DISP, 0x01000008);
668209ff23fSmrg	    OUTREG(RADEON_CRTC2_H_SYNC_STRT_WID, 0x00000800);
669209ff23fSmrg	    OUTREG(RADEON_CRTC2_V_TOTAL_DISP, 0x00080001);
670209ff23fSmrg	    OUTREG(RADEON_CRTC2_V_SYNC_STRT_WID, 0x00000080);
671209ff23fSmrg
672209ff23fSmrg	    for (i = 0; i < 200; i++) {
673209ff23fSmrg		ulData     = INREG(RADEON_GPIO_MONID);
674209ff23fSmrg		bConnected = (ulData & RADEON_GPIO_Y_0)?1:0;
675209ff23fSmrg		if (!bConnected) break;
676209ff23fSmrg
677209ff23fSmrg		usleep(1000);
678209ff23fSmrg	    }
679209ff23fSmrg
680209ff23fSmrg	    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_A, ulOrigDISP_LIN_TRANS_GRPH_A);
681209ff23fSmrg	    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_B, ulOrigDISP_LIN_TRANS_GRPH_B);
682209ff23fSmrg	    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_C, ulOrigDISP_LIN_TRANS_GRPH_C);
683209ff23fSmrg	    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_D, ulOrigDISP_LIN_TRANS_GRPH_D);
684209ff23fSmrg	    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_E, ulOrigDISP_LIN_TRANS_GRPH_E);
685209ff23fSmrg	    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_F, ulOrigDISP_LIN_TRANS_GRPH_F);
686209ff23fSmrg	    OUTREG(RADEON_CRTC2_H_TOTAL_DISP, ulOrigCRTC2_H_TOTAL_DISP);
687209ff23fSmrg	    OUTREG(RADEON_CRTC2_V_TOTAL_DISP, ulOrigCRTC2_V_TOTAL_DISP);
688209ff23fSmrg	    OUTREG(RADEON_CRTC2_H_SYNC_STRT_WID, ulOrigCRTC2_H_SYNC_STRT_WID);
689209ff23fSmrg	    OUTREG(RADEON_CRTC2_V_SYNC_STRT_WID, ulOrigCRTC2_V_SYNC_STRT_WID);
690209ff23fSmrg	    OUTREG(RADEON_CRTC2_GEN_CNTL, ulOrigCRTC2_GEN_CNTL);
691209ff23fSmrg	    OUTREG(RADEON_DISP_OUTPUT_CNTL, ulOrigDISP_OUTPUT_CNTL);
692209ff23fSmrg	    OUTREG(RADEON_FP2_GEN_CNTL, ulOrigFP2_GEN_CNTL);
693209ff23fSmrg	    OUTREG(RADEON_GPIO_MONID, ulOrigGPIO_MONID);
694209ff23fSmrg        } else {
695209ff23fSmrg	    unsigned long ulOrigPIXCLKSDATA;
696209ff23fSmrg	    unsigned long ulOrigTV_MASTER_CNTL;
697209ff23fSmrg	    unsigned long ulOrigTV_DAC_CNTL;
698209ff23fSmrg	    unsigned long ulOrigTV_PRE_DAC_MUX_CNTL;
699209ff23fSmrg	    unsigned long ulOrigDAC_CNTL2;
700209ff23fSmrg	    unsigned long ulData;
701209ff23fSmrg	    unsigned long ulMask;
702209ff23fSmrg
703209ff23fSmrg	    ulOrigPIXCLKSDATA = INPLL(pScrn, RADEON_PIXCLKS_CNTL);
704209ff23fSmrg
705209ff23fSmrg	    ulData            = ulOrigPIXCLKSDATA;
706209ff23fSmrg	    ulData           &= ~(RADEON_PIX2CLK_ALWAYS_ONb
707209ff23fSmrg				  | RADEON_PIX2CLK_DAC_ALWAYS_ONb);
708209ff23fSmrg	    ulMask            = ~(RADEON_PIX2CLK_ALWAYS_ONb
709209ff23fSmrg			  | RADEON_PIX2CLK_DAC_ALWAYS_ONb);
710209ff23fSmrg	    OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL, ulData, ulMask);
711209ff23fSmrg
712209ff23fSmrg	    ulOrigTV_MASTER_CNTL = INREG(RADEON_TV_MASTER_CNTL);
713209ff23fSmrg	    ulData               = ulOrigTV_MASTER_CNTL;
714209ff23fSmrg	    ulData              &= ~RADEON_TVCLK_ALWAYS_ONb;
715209ff23fSmrg	    OUTREG(RADEON_TV_MASTER_CNTL, ulData);
716209ff23fSmrg
717209ff23fSmrg	    ulOrigDAC_CNTL2 = INREG(RADEON_DAC_CNTL2);
718209ff23fSmrg	    ulData          = ulOrigDAC_CNTL2;
719209ff23fSmrg	    ulData          &= ~RADEON_DAC2_DAC2_CLK_SEL;
720209ff23fSmrg	    OUTREG(RADEON_DAC_CNTL2, ulData);
721209ff23fSmrg
722209ff23fSmrg	    ulOrigTV_DAC_CNTL = INREG(RADEON_TV_DAC_CNTL);
723209ff23fSmrg
724209ff23fSmrg	    ulData  = 0x00880213;
725209ff23fSmrg	    OUTREG(RADEON_TV_DAC_CNTL, ulData);
726209ff23fSmrg
727209ff23fSmrg	    ulOrigTV_PRE_DAC_MUX_CNTL = INREG(RADEON_TV_PRE_DAC_MUX_CNTL);
728209ff23fSmrg
729209ff23fSmrg	    ulData  =  (RADEON_Y_RED_EN
730209ff23fSmrg			| RADEON_C_GRN_EN
731209ff23fSmrg			| RADEON_CMP_BLU_EN
732209ff23fSmrg			| RADEON_RED_MX_FORCE_DAC_DATA
733209ff23fSmrg			| RADEON_GRN_MX_FORCE_DAC_DATA
734209ff23fSmrg			| RADEON_BLU_MX_FORCE_DAC_DATA);
735209ff23fSmrg            if (IS_R300_VARIANT)
736209ff23fSmrg		ulData |= 0x180 << RADEON_TV_FORCE_DAC_DATA_SHIFT;
737209ff23fSmrg	    else
738209ff23fSmrg		ulData |= 0x1f5 << RADEON_TV_FORCE_DAC_DATA_SHIFT;
739209ff23fSmrg	    OUTREG(RADEON_TV_PRE_DAC_MUX_CNTL, ulData);
740209ff23fSmrg
741209ff23fSmrg	    usleep(10000);
742209ff23fSmrg
743209ff23fSmrg	    ulData     = INREG(RADEON_TV_DAC_CNTL);
744209ff23fSmrg	    bConnected = (ulData & RADEON_TV_DAC_CMPOUT)?1:0;
745209ff23fSmrg
746209ff23fSmrg	    ulData    = ulOrigPIXCLKSDATA;
747209ff23fSmrg	    ulMask    = 0xFFFFFFFFL;
748209ff23fSmrg	    OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL, ulData, ulMask);
749209ff23fSmrg
750209ff23fSmrg	    OUTREG(RADEON_TV_MASTER_CNTL, ulOrigTV_MASTER_CNTL);
751209ff23fSmrg	    OUTREG(RADEON_DAC_CNTL2, ulOrigDAC_CNTL2);
752209ff23fSmrg	    OUTREG(RADEON_TV_DAC_CNTL, ulOrigTV_DAC_CNTL);
753209ff23fSmrg	    OUTREG(RADEON_TV_PRE_DAC_MUX_CNTL, ulOrigTV_PRE_DAC_MUX_CNTL);
754209ff23fSmrg	}
755209ff23fSmrg#endif
756209ff23fSmrg	return MT_UNKNOWN;
757209ff23fSmrg    }
758209ff23fSmrg
759209ff23fSmrg    return(bConnected ? MT_CRT : MT_NONE);
760209ff23fSmrg}
761209ff23fSmrg#endif
762209ff23fSmrg
763209ff23fSmrgRADEONMonitorType
764b7e1c893Smrglegacy_dac_detect(xf86OutputPtr output)
765209ff23fSmrg{
766b7e1c893Smrg    ScrnInfoPtr pScrn = output->scrn;
767209ff23fSmrg    RADEONInfoPtr info      = RADEONPTR(pScrn);
768209ff23fSmrg    RADEONOutputPrivatePtr radeon_output = output->driver_private;
769209ff23fSmrg    RADEONMonitorType found = MT_NONE;
770209ff23fSmrg
771b7e1c893Smrg    if (radeon_output->devices & (ATOM_DEVICE_TV_SUPPORT)) {
772209ff23fSmrg	if (xf86ReturnOptValBool(info->Options, OPTION_FORCE_TVOUT, FALSE)) {
773b7e1c893Smrg	    if (radeon_output->ConnectorType == CONNECTOR_STV)
774209ff23fSmrg		found = MT_STV;
775209ff23fSmrg	    else
776209ff23fSmrg		found = MT_CTV;
777209ff23fSmrg	} else {
778b7e1c893Smrg	    if (radeon_output->load_detection)
779b7e1c893Smrg		found = radeon_detect_tv(pScrn);
780b7e1c893Smrg	}
781b7e1c893Smrg    } else if (radeon_output->devices & (ATOM_DEVICE_CRT2_SUPPORT)) {
782b7e1c893Smrg	if (info->encoders[ATOM_DEVICE_CRT2_INDEX] &&
783b7e1c893Smrg	    (info->encoders[ATOM_DEVICE_CRT2_INDEX]->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1)) {
784b7e1c893Smrg	    if (radeon_output->load_detection)
785b7e1c893Smrg		found = radeon_detect_primary_dac(pScrn, TRUE);
786b7e1c893Smrg	} else {
787b7e1c893Smrg	    if (radeon_output->load_detection) {
788b7e1c893Smrg		if (info->ChipFamily == CHIP_FAMILY_R200)
789b7e1c893Smrg		    found = radeon_detect_ext_dac(pScrn);
790209ff23fSmrg		else
791b7e1c893Smrg		    found = radeon_detect_tv_dac(pScrn, TRUE);
792209ff23fSmrg	    }
793209ff23fSmrg	}
794b7e1c893Smrg    } else if (radeon_output->devices & (ATOM_DEVICE_CRT1_SUPPORT)) {
795b7e1c893Smrg	if (info->encoders[ATOM_DEVICE_CRT1_INDEX] &&
796b7e1c893Smrg	    (info->encoders[ATOM_DEVICE_CRT1_INDEX]->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1)) {
797209ff23fSmrg	    if (radeon_output->load_detection)
798209ff23fSmrg		found = radeon_detect_primary_dac(pScrn, TRUE);
799b7e1c893Smrg	} else {
800209ff23fSmrg	    if (radeon_output->load_detection) {
801209ff23fSmrg		if (info->ChipFamily == CHIP_FAMILY_R200)
802209ff23fSmrg		    found = radeon_detect_ext_dac(pScrn);
803209ff23fSmrg		else
804209ff23fSmrg		    found = radeon_detect_tv_dac(pScrn, TRUE);
805b7e1c893Smrg	    }
806209ff23fSmrg	}
807209ff23fSmrg    }
808209ff23fSmrg
809209ff23fSmrg    return found;
810209ff23fSmrg}
811209ff23fSmrg
812209ff23fSmrg/*
813209ff23fSmrg * Powering done DAC, needed for DPMS problem with ViewSonic P817 (or its variant).
814209ff23fSmrg *
815209ff23fSmrg */
816209ff23fSmrgstatic void
817209ff23fSmrgRADEONDacPowerSet(ScrnInfoPtr pScrn, Bool IsOn, Bool IsPrimaryDAC)
818209ff23fSmrg{
819209ff23fSmrg    RADEONInfoPtr  info       = RADEONPTR(pScrn);
820209ff23fSmrg    unsigned char *RADEONMMIO = info->MMIO;
821209ff23fSmrg
822209ff23fSmrg    if (IsPrimaryDAC) {
823209ff23fSmrg	uint32_t dac_cntl;
824209ff23fSmrg	uint32_t dac_macro_cntl = 0;
825209ff23fSmrg	dac_cntl = INREG(RADEON_DAC_CNTL);
826209ff23fSmrg	dac_macro_cntl = INREG(RADEON_DAC_MACRO_CNTL);
827209ff23fSmrg	if (IsOn) {
828209ff23fSmrg	    dac_cntl &= ~RADEON_DAC_PDWN;
829209ff23fSmrg	    dac_macro_cntl &= ~(RADEON_DAC_PDWN_R |
830209ff23fSmrg				RADEON_DAC_PDWN_G |
831209ff23fSmrg				RADEON_DAC_PDWN_B);
832209ff23fSmrg	} else {
833209ff23fSmrg	    dac_cntl |= RADEON_DAC_PDWN;
834209ff23fSmrg	    dac_macro_cntl |= (RADEON_DAC_PDWN_R |
835209ff23fSmrg			       RADEON_DAC_PDWN_G |
836209ff23fSmrg			       RADEON_DAC_PDWN_B);
837209ff23fSmrg	}
838209ff23fSmrg	OUTREG(RADEON_DAC_CNTL, dac_cntl);
839209ff23fSmrg	OUTREG(RADEON_DAC_MACRO_CNTL, dac_macro_cntl);
840209ff23fSmrg    } else {
841209ff23fSmrg	uint32_t tv_dac_cntl;
842209ff23fSmrg	uint32_t fp2_gen_cntl;
843209ff23fSmrg
844b7e1c893Smrg	switch(info->ChipFamily) {
845209ff23fSmrg	case CHIP_FAMILY_R420:
846209ff23fSmrg	case CHIP_FAMILY_RV410:
847209ff23fSmrg	    tv_dac_cntl = INREG(RADEON_TV_DAC_CNTL);
848209ff23fSmrg	    if (IsOn) {
849209ff23fSmrg		tv_dac_cntl &= ~(R420_TV_DAC_RDACPD |
850209ff23fSmrg				 R420_TV_DAC_GDACPD |
851209ff23fSmrg				 R420_TV_DAC_BDACPD |
852209ff23fSmrg				 RADEON_TV_DAC_BGSLEEP);
853209ff23fSmrg	    } else {
854209ff23fSmrg		tv_dac_cntl |= (R420_TV_DAC_RDACPD |
855209ff23fSmrg				R420_TV_DAC_GDACPD |
856209ff23fSmrg				R420_TV_DAC_BDACPD |
857209ff23fSmrg				RADEON_TV_DAC_BGSLEEP);
858209ff23fSmrg	    }
859209ff23fSmrg	    OUTREG(RADEON_TV_DAC_CNTL, tv_dac_cntl);
860209ff23fSmrg	    break;
861209ff23fSmrg	case CHIP_FAMILY_R200:
862209ff23fSmrg	    fp2_gen_cntl = INREG(RADEON_FP2_GEN_CNTL);
863209ff23fSmrg	    if (IsOn) {
864209ff23fSmrg		fp2_gen_cntl |= RADEON_FP2_DVO_EN;
865209ff23fSmrg	    } else {
866209ff23fSmrg		fp2_gen_cntl &= ~RADEON_FP2_DVO_EN;
867209ff23fSmrg	    }
868209ff23fSmrg	    OUTREG(RADEON_FP2_GEN_CNTL, fp2_gen_cntl);
869209ff23fSmrg	    break;
870209ff23fSmrg	default:
871209ff23fSmrg	    tv_dac_cntl = INREG(RADEON_TV_DAC_CNTL);
872209ff23fSmrg	    if (IsOn) {
873209ff23fSmrg		tv_dac_cntl &= ~(RADEON_TV_DAC_RDACPD |
874209ff23fSmrg				 RADEON_TV_DAC_GDACPD |
875209ff23fSmrg				 RADEON_TV_DAC_BDACPD |
876209ff23fSmrg				 RADEON_TV_DAC_BGSLEEP);
877209ff23fSmrg	    } else {
878209ff23fSmrg		tv_dac_cntl |= (RADEON_TV_DAC_RDACPD |
879209ff23fSmrg				RADEON_TV_DAC_GDACPD |
880209ff23fSmrg				RADEON_TV_DAC_BDACPD |
881209ff23fSmrg				RADEON_TV_DAC_BGSLEEP);
882209ff23fSmrg	    }
883209ff23fSmrg	    OUTREG(RADEON_TV_DAC_CNTL, tv_dac_cntl);
884209ff23fSmrg	    break;
885209ff23fSmrg	}
886209ff23fSmrg    }
887209ff23fSmrg}
888209ff23fSmrg
889b7e1c893Smrgvoid
890b7e1c893Smrglegacy_output_dpms(xf86OutputPtr output, int mode)
891209ff23fSmrg{
892209ff23fSmrg    ScrnInfoPtr pScrn = output->scrn;
893209ff23fSmrg    RADEONInfoPtr info = RADEONPTR(pScrn);
894209ff23fSmrg    RADEONSavePtr save = info->ModeReg;
895209ff23fSmrg    unsigned char * RADEONMMIO = info->MMIO;
896209ff23fSmrg    unsigned long tmp;
897b7e1c893Smrg    RADEONOutputPrivatePtr radeon_output = output->driver_private;
898b7e1c893Smrg    radeon_encoder_ptr radeon_encoder = radeon_get_encoder(output);
899209ff23fSmrg
900b7e1c893Smrg    if (radeon_encoder == NULL)
901b7e1c893Smrg	return;
902209ff23fSmrg
903b7e1c893Smrg    switch(mode) {
904b7e1c893Smrg    case DPMSModeOn:
905b7e1c893Smrg	radeon_encoder->devices |= radeon_output->active_device;
906b7e1c893Smrg	switch (radeon_encoder->encoder_id) {
907b7e1c893Smrg	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
908b7e1c893Smrg	{
909b7e1c893Smrg	    radeon_lvds_ptr lvds = (radeon_lvds_ptr)radeon_encoder->dev_priv;
910b7e1c893Smrg	    if (lvds == NULL)
911b7e1c893Smrg		return;
912b7e1c893Smrg	    ErrorF("enable LVDS\n");
913b7e1c893Smrg	    tmp = INREG(RADEON_LVDS_GEN_CNTL);
914b7e1c893Smrg	    tmp |= (RADEON_LVDS_ON | RADEON_LVDS_BLON | RADEON_LVDS_EN);
915b7e1c893Smrg	    tmp &= ~(RADEON_LVDS_DISPLAY_DIS);
916b7e1c893Smrg	    usleep (lvds->PanelPwrDly * 1000);
917b7e1c893Smrg	    OUTREG(RADEON_LVDS_GEN_CNTL, tmp);
918b7e1c893Smrg	    save->lvds_gen_cntl |= (RADEON_LVDS_ON | RADEON_LVDS_BLON | RADEON_LVDS_EN);
919b7e1c893Smrg	    save->lvds_gen_cntl &= ~(RADEON_LVDS_DISPLAY_DIS);
920b7e1c893Smrg	}
921b7e1c893Smrg	break;
922b7e1c893Smrg	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
923b7e1c893Smrg	    ErrorF("enable FP1\n");
924b7e1c893Smrg	    tmp = INREG(RADEON_FP_GEN_CNTL);
925b7e1c893Smrg	    tmp |= (RADEON_FP_FPON | RADEON_FP_TMDS_EN);
926b7e1c893Smrg	    OUTREG(RADEON_FP_GEN_CNTL, tmp);
927b7e1c893Smrg	    save->fp_gen_cntl |= (RADEON_FP_FPON | RADEON_FP_TMDS_EN);
928b7e1c893Smrg	    if ((info->ChipFamily == CHIP_FAMILY_RS400) ||
929b7e1c893Smrg		(info->ChipFamily == CHIP_FAMILY_RS480)) {
930b7e1c893Smrg		tmp = INREG(RS400_FP_2ND_GEN_CNTL);
931b7e1c893Smrg		tmp |= (RS400_FP_2ND_ON | RS400_TMDS_2ND_EN);
932b7e1c893Smrg		OUTREG(RS400_FP_2ND_GEN_CNTL, tmp);
933b7e1c893Smrg		save->fp_2nd_gen_cntl |= (RS400_FP_2ND_ON |
934b7e1c893Smrg					  RS400_TMDS_2ND_EN);
935b7e1c893Smrg	    }
936b7e1c893Smrg	    break;
937b7e1c893Smrg	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
938b7e1c893Smrg	    ErrorF("enable FP2\n");
939b7e1c893Smrg	    tmp = INREG(RADEON_FP2_GEN_CNTL);
940b7e1c893Smrg	    tmp &= ~RADEON_FP2_BLANK_EN;
941b7e1c893Smrg	    tmp |= (RADEON_FP2_ON | RADEON_FP2_DVO_EN);
942b7e1c893Smrg	    OUTREG(RADEON_FP2_GEN_CNTL, tmp);
943b7e1c893Smrg	    save->fp2_gen_cntl |= (RADEON_FP2_ON | RADEON_FP2_DVO_EN);
944b7e1c893Smrg	    save->fp2_gen_cntl &= ~RADEON_FP2_BLANK_EN;
945b7e1c893Smrg	    if ((info->ChipFamily == CHIP_FAMILY_RS400) ||
946b7e1c893Smrg		(info->ChipFamily == CHIP_FAMILY_RS480)) {
947b7e1c893Smrg		tmp = INREG(RS400_FP2_2_GEN_CNTL);
948b7e1c893Smrg		tmp &= ~RS400_FP2_2_BLANK_EN;
949b7e1c893Smrg		tmp |= (RS400_FP2_2_ON | RS400_FP2_2_DVO2_EN);
950b7e1c893Smrg		OUTREG(RS400_FP2_2_GEN_CNTL, tmp);
951b7e1c893Smrg		save->fp2_2_gen_cntl |= (RS400_FP2_2_ON | RS400_FP2_2_DVO2_EN);
952b7e1c893Smrg		save->fp2_2_gen_cntl &= ~RS400_FP2_2_BLANK_EN;
953b7e1c893Smrg	    }
954b7e1c893Smrg	    break;
955b7e1c893Smrg	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
956b7e1c893Smrg	    ErrorF("enable primary dac\n");
957b7e1c893Smrg	    tmp = INREG(RADEON_CRTC_EXT_CNTL);
958b7e1c893Smrg	    tmp |= RADEON_CRTC_CRT_ON;
959b7e1c893Smrg	    OUTREG(RADEON_CRTC_EXT_CNTL, tmp);
960b7e1c893Smrg	    save->crtc_ext_cntl |= RADEON_CRTC_CRT_ON;
961b7e1c893Smrg	    RADEONDacPowerSet(pScrn, TRUE, TRUE);
962b7e1c893Smrg	    break;
963b7e1c893Smrg	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
964b7e1c893Smrg	    if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT)) {
965b7e1c893Smrg		ErrorF("enable TV\n");
966b7e1c893Smrg		tmp = INREG(RADEON_TV_MASTER_CNTL);
967b7e1c893Smrg		tmp |= RADEON_TV_ON;
968b7e1c893Smrg		OUTREG(RADEON_TV_MASTER_CNTL, tmp);
969b7e1c893Smrg		radeon_output->tvout.tv_on = TRUE;
970b7e1c893Smrg	    } else {
971b7e1c893Smrg		ErrorF("enable TVDAC\n");
972209ff23fSmrg		if (info->ChipFamily == CHIP_FAMILY_R200) {
973209ff23fSmrg		    tmp = INREG(RADEON_FP2_GEN_CNTL);
974209ff23fSmrg		    tmp |= (RADEON_FP2_ON | RADEON_FP2_DVO_EN);
975209ff23fSmrg		    OUTREG(RADEON_FP2_GEN_CNTL, tmp);
976209ff23fSmrg		    save->fp2_gen_cntl |= (RADEON_FP2_ON | RADEON_FP2_DVO_EN);
977209ff23fSmrg		} else {
978209ff23fSmrg		    tmp = INREG(RADEON_CRTC2_GEN_CNTL);
979209ff23fSmrg		    tmp |= RADEON_CRTC2_CRT2_ON;
980209ff23fSmrg		    OUTREG(RADEON_CRTC2_GEN_CNTL, tmp);
981209ff23fSmrg		    save->crtc2_gen_cntl |= RADEON_CRTC2_CRT2_ON;
982209ff23fSmrg		}
983209ff23fSmrg	    }
984b7e1c893Smrg	    RADEONDacPowerSet(pScrn, TRUE, FALSE);
985b7e1c893Smrg	    break;
986b7e1c893Smrg	}
987b7e1c893Smrg	break;
988b7e1c893Smrg    case DPMSModeOff:
989b7e1c893Smrg    case DPMSModeSuspend:
990b7e1c893Smrg    case DPMSModeStandby:
991b7e1c893Smrg	radeon_encoder->devices &= ~(radeon_output->active_device);
992b7e1c893Smrg	if (!radeon_encoder->devices) {
993b7e1c893Smrg	    switch (radeon_encoder->encoder_id) {
994b7e1c893Smrg	    case ENCODER_OBJECT_ID_INTERNAL_LVDS:
995b7e1c893Smrg		{
996b7e1c893Smrg		    unsigned long tmpPixclksCntl = INPLL(pScrn, RADEON_PIXCLKS_CNTL);
997b7e1c893Smrg		    ErrorF("disable LVDS\n");
998b7e1c893Smrg		    if (info->IsMobility || info->IsIGP) {
999b7e1c893Smrg			/* Asic bug, when turning off LVDS_ON, we have to make sure
1000b7e1c893Smrg			   RADEON_PIXCLK_LVDS_ALWAYS_ON bit is off
1001b7e1c893Smrg			*/
1002b7e1c893Smrg			OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL, 0, ~RADEON_PIXCLK_LVDS_ALWAYS_ONb);
1003b7e1c893Smrg		    }
1004b7e1c893Smrg		    tmp = INREG(RADEON_LVDS_GEN_CNTL);
1005b7e1c893Smrg		    tmp |= RADEON_LVDS_DISPLAY_DIS;
1006b7e1c893Smrg		    tmp &= ~(RADEON_LVDS_ON | RADEON_LVDS_BLON | RADEON_LVDS_EN);
1007b7e1c893Smrg		    OUTREG(RADEON_LVDS_GEN_CNTL, tmp);
1008b7e1c893Smrg		    save->lvds_gen_cntl |= RADEON_LVDS_DISPLAY_DIS;
1009b7e1c893Smrg		    save->lvds_gen_cntl &= ~(RADEON_LVDS_ON | RADEON_LVDS_BLON | RADEON_LVDS_EN);
1010b7e1c893Smrg		    if (info->IsMobility || info->IsIGP) {
1011b7e1c893Smrg			OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, tmpPixclksCntl);
1012b7e1c893Smrg		    }
1013b7e1c893Smrg		}
1014b7e1c893Smrg		break;
1015b7e1c893Smrg	    case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
1016b7e1c893Smrg		ErrorF("disable FP1\n");
1017209ff23fSmrg		tmp = INREG(RADEON_FP_GEN_CNTL);
1018b7e1c893Smrg		tmp &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN);
1019209ff23fSmrg		OUTREG(RADEON_FP_GEN_CNTL, tmp);
1020b7e1c893Smrg		save->fp_gen_cntl &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN);
1021209ff23fSmrg		if ((info->ChipFamily == CHIP_FAMILY_RS400) ||
1022209ff23fSmrg		    (info->ChipFamily == CHIP_FAMILY_RS480)) {
1023209ff23fSmrg		    tmp = INREG(RS400_FP_2ND_GEN_CNTL);
1024b7e1c893Smrg		    tmp &= ~(RS400_FP_2ND_ON | RS400_TMDS_2ND_EN);
1025209ff23fSmrg		    OUTREG(RS400_FP_2ND_GEN_CNTL, tmp);
1026b7e1c893Smrg		    save->fp_2nd_gen_cntl &= ~(RS400_FP_2ND_ON |
1027b7e1c893Smrg					       RS400_TMDS_2ND_EN);
1028209ff23fSmrg		}
1029b7e1c893Smrg	    break;
1030b7e1c893Smrg	    case ENCODER_OBJECT_ID_INTERNAL_DVO1:
1031b7e1c893Smrg		ErrorF("disable FP2\n");
1032209ff23fSmrg		tmp = INREG(RADEON_FP2_GEN_CNTL);
1033b7e1c893Smrg		tmp |= RADEON_FP2_BLANK_EN;
1034b7e1c893Smrg		tmp &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN);
1035209ff23fSmrg		OUTREG(RADEON_FP2_GEN_CNTL, tmp);
1036b7e1c893Smrg		save->fp2_gen_cntl &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN);
1037b7e1c893Smrg		save->fp2_gen_cntl |= RADEON_FP2_BLANK_EN;
1038209ff23fSmrg		if ((info->ChipFamily == CHIP_FAMILY_RS400) ||
1039209ff23fSmrg		    (info->ChipFamily == CHIP_FAMILY_RS480)) {
1040209ff23fSmrg		    tmp = INREG(RS400_FP2_2_GEN_CNTL);
1041b7e1c893Smrg		    tmp |= RS400_FP2_2_BLANK_EN;
1042b7e1c893Smrg		    tmp &= ~(RS400_FP2_2_ON | RS400_FP2_2_DVO2_EN);
1043209ff23fSmrg		    OUTREG(RS400_FP2_2_GEN_CNTL, tmp);
1044b7e1c893Smrg		    save->fp2_2_gen_cntl &= ~(RS400_FP2_2_ON | RS400_FP2_2_DVO2_EN);
1045b7e1c893Smrg		    save->fp2_2_gen_cntl |= RS400_FP2_2_BLANK_EN;
1046209ff23fSmrg		}
1047b7e1c893Smrg		break;
1048b7e1c893Smrg	    case ENCODER_OBJECT_ID_INTERNAL_DAC1:
1049b7e1c893Smrg		ErrorF("disable primary dac\n");
1050b7e1c893Smrg		tmp = INREG(RADEON_CRTC_EXT_CNTL);
1051b7e1c893Smrg		tmp &= ~RADEON_CRTC_CRT_ON;
1052b7e1c893Smrg		OUTREG(RADEON_CRTC_EXT_CNTL, tmp);
1053b7e1c893Smrg		save->crtc_ext_cntl &= ~RADEON_CRTC_CRT_ON;
1054b7e1c893Smrg		RADEONDacPowerSet(pScrn, FALSE, TRUE);
1055b7e1c893Smrg		break;
1056b7e1c893Smrg	    case ENCODER_OBJECT_ID_INTERNAL_DAC2:
1057b7e1c893Smrg		if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT)) {
1058b7e1c893Smrg		    ErrorF("disable TV\n");
1059b7e1c893Smrg		    tmp = INREG(RADEON_TV_MASTER_CNTL);
1060b7e1c893Smrg		    tmp &= ~RADEON_TV_ON;
1061b7e1c893Smrg		    OUTREG(RADEON_TV_MASTER_CNTL, tmp);
1062b7e1c893Smrg		    radeon_output->tvout.tv_on = FALSE;
1063b7e1c893Smrg		} else {
1064b7e1c893Smrg		    ErrorF("disable TVDAC\n");
1065209ff23fSmrg		    if (info->ChipFamily == CHIP_FAMILY_R200) {
1066209ff23fSmrg			tmp = INREG(RADEON_FP2_GEN_CNTL);
1067209ff23fSmrg			tmp &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN);
1068209ff23fSmrg			OUTREG(RADEON_FP2_GEN_CNTL, tmp);
1069209ff23fSmrg			save->fp2_gen_cntl &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN);
1070209ff23fSmrg		    } else {
1071209ff23fSmrg			tmp = INREG(RADEON_CRTC2_GEN_CNTL);
1072209ff23fSmrg			tmp &= ~RADEON_CRTC2_CRT2_ON;
1073209ff23fSmrg			OUTREG(RADEON_CRTC2_GEN_CNTL, tmp);
1074209ff23fSmrg			save->crtc2_gen_cntl &= ~RADEON_CRTC2_CRT2_ON;
1075209ff23fSmrg		    }
1076209ff23fSmrg		}
1077b7e1c893Smrg		RADEONDacPowerSet(pScrn, FALSE, FALSE);
1078b7e1c893Smrg		break;
1079209ff23fSmrg	    }
1080209ff23fSmrg	}
1081209ff23fSmrg	break;
1082209ff23fSmrg    }
1083209ff23fSmrg}
1084209ff23fSmrg
1085209ff23fSmrgstatic void
1086209ff23fSmrgRADEONInitFPRegisters(xf86OutputPtr output, RADEONSavePtr save,
1087209ff23fSmrg		      DisplayModePtr mode, BOOL IsPrimary)
1088209ff23fSmrg{
1089209ff23fSmrg    ScrnInfoPtr pScrn = output->scrn;
1090209ff23fSmrg    RADEONInfoPtr  info       = RADEONPTR(pScrn);
1091209ff23fSmrg    RADEONEntPtr  pRADEONEnt = RADEONEntPriv(pScrn);
1092209ff23fSmrg    RADEONOutputPrivatePtr radeon_output = output->driver_private;
1093b7e1c893Smrg    radeon_encoder_ptr radeon_encoder = radeon_get_encoder(output);
1094b7e1c893Smrg    radeon_tmds_ptr tmds = NULL;
1095209ff23fSmrg    int i;
1096209ff23fSmrg    uint32_t tmp = info->SavedReg->tmds_pll_cntl & 0xfffff;
1097209ff23fSmrg
1098b7e1c893Smrg    if (radeon_encoder == NULL)
1099b7e1c893Smrg	return;
1100b7e1c893Smrg
1101b7e1c893Smrg    tmds = (radeon_tmds_ptr)radeon_encoder->dev_priv;
1102b7e1c893Smrg
1103b7e1c893Smrg    if (tmds == NULL)
1104b7e1c893Smrg	return;
1105b7e1c893Smrg
1106b7e1c893Smrg    for (i = 0; i < 4; i++) {
1107b7e1c893Smrg	if (tmds->tmds_pll[i].freq == 0)
1108b7e1c893Smrg	    break;
1109b7e1c893Smrg	if ((uint32_t)(mode->Clock / 10) < tmds->tmds_pll[i].freq) {
1110b7e1c893Smrg	    tmp = tmds->tmds_pll[i].value ;
1111209ff23fSmrg	    break;
1112209ff23fSmrg	}
1113209ff23fSmrg    }
1114209ff23fSmrg
1115209ff23fSmrg    if (IS_R300_VARIANT || (info->ChipFamily == CHIP_FAMILY_RV280)) {
1116209ff23fSmrg	if (tmp & 0xfff00000)
1117209ff23fSmrg	    save->tmds_pll_cntl = tmp;
1118209ff23fSmrg	else {
1119209ff23fSmrg	    save->tmds_pll_cntl = info->SavedReg->tmds_pll_cntl & 0xfff00000;
1120209ff23fSmrg	    save->tmds_pll_cntl |= tmp;
1121209ff23fSmrg	}
1122209ff23fSmrg    } else save->tmds_pll_cntl = tmp;
1123209ff23fSmrg
1124209ff23fSmrg    save->tmds_transmitter_cntl = info->SavedReg->tmds_transmitter_cntl &
1125209ff23fSmrg					~(RADEON_TMDS_TRANSMITTER_PLLRST);
1126209ff23fSmrg
1127209ff23fSmrg    if (IS_R300_VARIANT || (info->ChipFamily == CHIP_FAMILY_R200) || !pRADEONEnt->HasCRTC2)
1128209ff23fSmrg	save->tmds_transmitter_cntl &= ~(RADEON_TMDS_TRANSMITTER_PLLEN);
1129209ff23fSmrg    else /* weird, RV chips got this bit reversed? */
1130209ff23fSmrg	save->tmds_transmitter_cntl |= (RADEON_TMDS_TRANSMITTER_PLLEN);
1131209ff23fSmrg
1132209ff23fSmrg    save->fp_gen_cntl = info->SavedReg->fp_gen_cntl |
1133209ff23fSmrg			 (RADEON_FP_CRTC_DONT_SHADOW_VPAR |
1134209ff23fSmrg			  RADEON_FP_CRTC_DONT_SHADOW_HEND );
1135209ff23fSmrg
1136209ff23fSmrg    save->fp_gen_cntl &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN);
1137209ff23fSmrg
1138b7e1c893Smrg    save->fp_gen_cntl &= ~(RADEON_FP_RMX_HVSYNC_CONTROL_EN |
1139b7e1c893Smrg			   RADEON_FP_DFP_SYNC_SEL |
1140b7e1c893Smrg			   RADEON_FP_CRT_SYNC_SEL |
1141b7e1c893Smrg			   RADEON_FP_CRTC_LOCK_8DOT |
1142b7e1c893Smrg			   RADEON_FP_USE_SHADOW_EN |
1143b7e1c893Smrg			   RADEON_FP_CRTC_USE_SHADOW_VEND |
1144b7e1c893Smrg			   RADEON_FP_CRT_SYNC_ALT);
1145b7e1c893Smrg
1146209ff23fSmrg    if (pScrn->rgbBits == 8)
1147209ff23fSmrg	save->fp_gen_cntl |= RADEON_FP_PANEL_FORMAT;  /* 24 bit format */
1148209ff23fSmrg    else
1149209ff23fSmrg	save->fp_gen_cntl &= ~RADEON_FP_PANEL_FORMAT;/* 18 bit format */
1150209ff23fSmrg
1151209ff23fSmrg    if (IsPrimary) {
1152209ff23fSmrg	if ((IS_R300_VARIANT) || (info->ChipFamily == CHIP_FAMILY_R200)) {
1153209ff23fSmrg	    save->fp_gen_cntl &= ~R200_FP_SOURCE_SEL_MASK;
1154209ff23fSmrg	    if (radeon_output->Flags & RADEON_USE_RMX)
1155209ff23fSmrg		save->fp_gen_cntl |= R200_FP_SOURCE_SEL_RMX;
1156209ff23fSmrg	    else
1157209ff23fSmrg		save->fp_gen_cntl |= R200_FP_SOURCE_SEL_CRTC1;
1158209ff23fSmrg	} else
1159b7e1c893Smrg	    save->fp_gen_cntl &= ~RADEON_FP_SEL_CRTC2;
1160209ff23fSmrg    } else {
1161209ff23fSmrg	if ((IS_R300_VARIANT) || (info->ChipFamily == CHIP_FAMILY_R200)) {
1162209ff23fSmrg	    save->fp_gen_cntl &= ~R200_FP_SOURCE_SEL_MASK;
1163209ff23fSmrg	    save->fp_gen_cntl |= R200_FP_SOURCE_SEL_CRTC2;
1164209ff23fSmrg	} else
1165209ff23fSmrg	    save->fp_gen_cntl |= RADEON_FP_SEL_CRTC2;
1166209ff23fSmrg    }
1167209ff23fSmrg
1168209ff23fSmrg    if ((info->ChipFamily == CHIP_FAMILY_RS400) ||
1169209ff23fSmrg	(info->ChipFamily == CHIP_FAMILY_RS480)) {
1170209ff23fSmrg	save->tmds2_transmitter_cntl = info->SavedReg->tmds2_transmitter_cntl &
1171209ff23fSmrg	    ~(RS400_TMDS2_PLLRST);
1172209ff23fSmrg	save->tmds2_transmitter_cntl &= ~(RS400_TMDS2_PLLEN);
1173209ff23fSmrg
1174209ff23fSmrg	save->fp_2nd_gen_cntl = info->SavedReg->fp_2nd_gen_cntl;
1175209ff23fSmrg
1176209ff23fSmrg	if (pScrn->rgbBits == 8)
1177209ff23fSmrg	    save->fp_2nd_gen_cntl |= RS400_PANEL_FORMAT_2ND;  /* 24 bit format */
1178209ff23fSmrg	else
1179209ff23fSmrg	    save->fp_2nd_gen_cntl &= ~RS400_PANEL_FORMAT_2ND;/* 18 bit format */
1180209ff23fSmrg
1181209ff23fSmrg	save->fp_2nd_gen_cntl &= ~RS400_FP_2ND_SOURCE_SEL_MASK;
1182209ff23fSmrg
1183209ff23fSmrg	if (IsPrimary) {
1184209ff23fSmrg	    if (radeon_output->Flags & RADEON_USE_RMX)
1185209ff23fSmrg		save->fp_2nd_gen_cntl |= RS400_FP_2ND_SOURCE_SEL_RMX;
1186209ff23fSmrg	    else
1187209ff23fSmrg		save->fp_2nd_gen_cntl |= RS400_FP_2ND_SOURCE_SEL_CRTC1;
1188209ff23fSmrg	} else
1189209ff23fSmrg	    save->fp_2nd_gen_cntl |= RS400_FP_2ND_SOURCE_SEL_CRTC2;
1190209ff23fSmrg    }
1191209ff23fSmrg
1192209ff23fSmrg}
1193209ff23fSmrg
1194209ff23fSmrgstatic void
1195209ff23fSmrgRADEONInitFP2Registers(xf86OutputPtr output, RADEONSavePtr save,
1196209ff23fSmrg		       DisplayModePtr mode, BOOL IsPrimary)
1197209ff23fSmrg{
1198209ff23fSmrg    ScrnInfoPtr pScrn = output->scrn;
1199209ff23fSmrg    RADEONInfoPtr info = RADEONPTR(pScrn);
1200209ff23fSmrg    RADEONOutputPrivatePtr radeon_output = output->driver_private;
1201209ff23fSmrg
1202209ff23fSmrg    if (pScrn->rgbBits == 8)
1203209ff23fSmrg	save->fp2_gen_cntl = info->SavedReg->fp2_gen_cntl |
1204209ff23fSmrg				RADEON_FP2_PANEL_FORMAT; /* 24 bit format, */
1205209ff23fSmrg    else
1206209ff23fSmrg	save->fp2_gen_cntl = info->SavedReg->fp2_gen_cntl &
1207209ff23fSmrg				~RADEON_FP2_PANEL_FORMAT;/* 18 bit format, */
1208209ff23fSmrg
1209209ff23fSmrg    save->fp2_gen_cntl &= ~(RADEON_FP2_ON |
1210209ff23fSmrg			    RADEON_FP2_DVO_EN |
1211209ff23fSmrg			    RADEON_FP2_DVO_RATE_SEL_SDR);
1212209ff23fSmrg
1213209ff23fSmrg
1214b7e1c893Smrg    /* XXX: these are oem specific */
1215209ff23fSmrg    if (IS_R300_VARIANT) {
1216b7e1c893Smrg	if ((info->Chipset == PCI_CHIP_RV350_NP) &&
1217b7e1c893Smrg	    (PCI_SUB_VENDOR_ID(info->PciInfo) == 0x1028) &&
1218b7e1c893Smrg	    (PCI_SUB_DEVICE_ID(info->PciInfo) == 0x2001))
1219b7e1c893Smrg	    save->fp2_gen_cntl |= R300_FP2_DVO_CLOCK_MODE_SINGLE; /* Dell Inspiron 8600 */
1220b7e1c893Smrg	else
1221b7e1c893Smrg	    save->fp2_gen_cntl |= RADEON_FP2_PAD_FLOP_EN | R300_FP2_DVO_CLOCK_MODE_SINGLE;
1222209ff23fSmrg#if 0
1223209ff23fSmrg	if (mode->Clock > 165000)
1224209ff23fSmrg	    save->fp2_gen_cntl |= R300_FP2_DVO_DUAL_CHANNEL_EN;
1225209ff23fSmrg#endif
1226209ff23fSmrg    }
1227209ff23fSmrg
1228209ff23fSmrg    if (IsPrimary) {
1229209ff23fSmrg	if ((info->ChipFamily == CHIP_FAMILY_R200) || IS_R300_VARIANT) {
1230209ff23fSmrg	    save->fp2_gen_cntl &= ~R200_FP2_SOURCE_SEL_MASK;
1231209ff23fSmrg	    if (radeon_output->Flags & RADEON_USE_RMX)
1232209ff23fSmrg		save->fp2_gen_cntl |= R200_FP2_SOURCE_SEL_RMX;
1233209ff23fSmrg	    else
1234209ff23fSmrg		save->fp2_gen_cntl |= R200_FP2_SOURCE_SEL_CRTC1;
1235b7e1c893Smrg	} else
1236209ff23fSmrg	    save->fp2_gen_cntl &= ~RADEON_FP2_SRC_SEL_CRTC2;
1237209ff23fSmrg    } else {
1238209ff23fSmrg	if ((info->ChipFamily == CHIP_FAMILY_R200) || IS_R300_VARIANT) {
1239209ff23fSmrg	    save->fp2_gen_cntl &= ~R200_FP2_SOURCE_SEL_MASK;
1240209ff23fSmrg	    save->fp2_gen_cntl |= R200_FP2_SOURCE_SEL_CRTC2;
1241b7e1c893Smrg	} else
1242209ff23fSmrg	    save->fp2_gen_cntl |= RADEON_FP2_SRC_SEL_CRTC2;
1243209ff23fSmrg    }
1244209ff23fSmrg
1245209ff23fSmrg    if ((info->ChipFamily == CHIP_FAMILY_RS400) ||
1246209ff23fSmrg	(info->ChipFamily == CHIP_FAMILY_RS480)) {
1247209ff23fSmrg	if (pScrn->rgbBits == 8)
1248209ff23fSmrg	    save->fp2_2_gen_cntl = info->SavedReg->fp2_2_gen_cntl |
1249209ff23fSmrg		RS400_FP2_2_PANEL_FORMAT; /* 24 bit format, */
1250209ff23fSmrg	else
1251209ff23fSmrg	    save->fp2_2_gen_cntl = info->SavedReg->fp2_2_gen_cntl &
1252209ff23fSmrg		~RS400_FP2_2_PANEL_FORMAT;/* 18 bit format, */
1253209ff23fSmrg
1254209ff23fSmrg	save->fp2_2_gen_cntl &= ~(RS400_FP2_2_ON |
1255209ff23fSmrg				  RS400_FP2_2_DVO2_EN |
1256209ff23fSmrg				  RS400_FP2_2_SOURCE_SEL_MASK);
1257209ff23fSmrg
1258209ff23fSmrg	if (IsPrimary) {
1259209ff23fSmrg	    if (radeon_output->Flags & RADEON_USE_RMX)
1260209ff23fSmrg		save->fp2_2_gen_cntl |= RS400_FP2_2_SOURCE_SEL_RMX;
1261209ff23fSmrg	    else
1262209ff23fSmrg		save->fp2_2_gen_cntl |= RS400_FP2_2_SOURCE_SEL_CRTC1;
1263209ff23fSmrg	} else
1264209ff23fSmrg	    save->fp2_2_gen_cntl |= RS400_FP2_2_SOURCE_SEL_CRTC2;
1265209ff23fSmrg    }
1266209ff23fSmrg
1267209ff23fSmrg}
1268209ff23fSmrg
1269209ff23fSmrgstatic void
1270209ff23fSmrgRADEONInitLVDSRegisters(xf86OutputPtr output, RADEONSavePtr save,
1271209ff23fSmrg			DisplayModePtr mode, BOOL IsPrimary)
1272209ff23fSmrg{
1273209ff23fSmrg    ScrnInfoPtr pScrn = output->scrn;
1274209ff23fSmrg    RADEONInfoPtr  info       = RADEONPTR(pScrn);
1275209ff23fSmrg    RADEONOutputPrivatePtr radeon_output = output->driver_private;
1276209ff23fSmrg
1277209ff23fSmrg    save->lvds_pll_cntl = (info->SavedReg->lvds_pll_cntl |
1278209ff23fSmrg			   RADEON_LVDS_PLL_EN);
1279209ff23fSmrg
1280209ff23fSmrg    save->lvds_pll_cntl &= ~RADEON_LVDS_PLL_RESET;
1281209ff23fSmrg
1282209ff23fSmrg    save->lvds_gen_cntl = info->SavedReg->lvds_gen_cntl;
1283209ff23fSmrg    save->lvds_gen_cntl |= RADEON_LVDS_DISPLAY_DIS;
1284209ff23fSmrg    save->lvds_gen_cntl &= ~(RADEON_LVDS_ON |
1285209ff23fSmrg			     RADEON_LVDS_BLON |
1286209ff23fSmrg			     RADEON_LVDS_EN |
1287209ff23fSmrg			     RADEON_LVDS_RST_FM);
1288209ff23fSmrg
1289209ff23fSmrg    if (IS_R300_VARIANT)
1290209ff23fSmrg	save->lvds_pll_cntl &= ~(R300_LVDS_SRC_SEL_MASK);
1291209ff23fSmrg
1292209ff23fSmrg    if (IsPrimary) {
1293209ff23fSmrg	if (IS_R300_VARIANT) {
1294209ff23fSmrg	    if (radeon_output->Flags & RADEON_USE_RMX)
1295209ff23fSmrg		save->lvds_pll_cntl |= R300_LVDS_SRC_SEL_RMX;
1296209ff23fSmrg	} else
1297209ff23fSmrg	    save->lvds_gen_cntl &= ~RADEON_LVDS_SEL_CRTC2;
1298209ff23fSmrg    } else {
1299209ff23fSmrg	if (IS_R300_VARIANT) {
1300209ff23fSmrg	    save->lvds_pll_cntl |= R300_LVDS_SRC_SEL_CRTC2;
1301209ff23fSmrg	} else
1302209ff23fSmrg	    save->lvds_gen_cntl |= RADEON_LVDS_SEL_CRTC2;
1303209ff23fSmrg    }
1304209ff23fSmrg
1305209ff23fSmrg}
1306209ff23fSmrg
1307209ff23fSmrgstatic void
1308209ff23fSmrgRADEONInitRMXRegisters(xf86OutputPtr output, RADEONSavePtr save,
1309209ff23fSmrg		       DisplayModePtr mode)
1310209ff23fSmrg{
1311209ff23fSmrg    ScrnInfoPtr pScrn = output->scrn;
1312209ff23fSmrg    RADEONInfoPtr  info       = RADEONPTR(pScrn);
1313209ff23fSmrg    RADEONOutputPrivatePtr radeon_output = output->driver_private;
1314b7e1c893Smrg    radeon_native_mode_ptr native_mode = &radeon_output->native_mode;
1315209ff23fSmrg    int    xres = mode->HDisplay;
1316209ff23fSmrg    int    yres = mode->VDisplay;
1317209ff23fSmrg    Bool   Hscale = TRUE, Vscale = TRUE;
1318209ff23fSmrg    int    hsync_wid;
1319209ff23fSmrg    int    vsync_wid;
1320209ff23fSmrg    int    hsync_start;
1321209ff23fSmrg
1322209ff23fSmrg
1323209ff23fSmrg    save->fp_vert_stretch = info->SavedReg->fp_vert_stretch &
1324209ff23fSmrg	                    (RADEON_VERT_STRETCH_RESERVED |
1325209ff23fSmrg			     RADEON_VERT_AUTO_RATIO_INC);
1326209ff23fSmrg    save->fp_horz_stretch = info->SavedReg->fp_horz_stretch &
1327209ff23fSmrg	                    (RADEON_HORZ_FP_LOOP_STRETCH |
1328209ff23fSmrg	                     RADEON_HORZ_AUTO_RATIO_INC);
1329209ff23fSmrg
1330209ff23fSmrg    save->crtc_more_cntl = 0;
1331209ff23fSmrg    if ((info->ChipFamily == CHIP_FAMILY_RS100) ||
1332209ff23fSmrg	(info->ChipFamily == CHIP_FAMILY_RS200)) {
1333209ff23fSmrg	/* This is to workaround the asic bug for RMX, some versions
1334209ff23fSmrg           of BIOS dosen't have this register initialized correctly.
1335209ff23fSmrg	*/
1336209ff23fSmrg	save->crtc_more_cntl |= RADEON_CRTC_H_CUTOFF_ACTIVE_EN;
1337209ff23fSmrg    }
1338209ff23fSmrg
1339209ff23fSmrg
1340209ff23fSmrg    save->fp_crtc_h_total_disp = ((((mode->CrtcHTotal / 8) - 1) & 0x3ff)
1341209ff23fSmrg				  | ((((mode->CrtcHDisplay / 8) - 1) & 0x1ff)
1342209ff23fSmrg				     << 16));
1343209ff23fSmrg
1344209ff23fSmrg    hsync_wid = (mode->CrtcHSyncEnd - mode->CrtcHSyncStart) / 8;
1345209ff23fSmrg    if (!hsync_wid)       hsync_wid = 1;
1346209ff23fSmrg    hsync_start = mode->CrtcHSyncStart - 8;
1347209ff23fSmrg
1348209ff23fSmrg    save->fp_h_sync_strt_wid = ((hsync_start & 0x1fff)
1349209ff23fSmrg				| ((hsync_wid & 0x3f) << 16)
1350209ff23fSmrg				| ((mode->Flags & V_NHSYNC)
1351209ff23fSmrg				   ? RADEON_CRTC_H_SYNC_POL
1352209ff23fSmrg				   : 0));
1353209ff23fSmrg
1354209ff23fSmrg    save->fp_crtc_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff)
1355209ff23fSmrg				  | ((mode->CrtcVDisplay - 1) << 16));
1356209ff23fSmrg
1357209ff23fSmrg    vsync_wid = mode->CrtcVSyncEnd - mode->CrtcVSyncStart;
1358209ff23fSmrg    if (!vsync_wid)       vsync_wid = 1;
1359209ff23fSmrg
1360209ff23fSmrg    save->fp_v_sync_strt_wid = (((mode->CrtcVSyncStart - 1) & 0xfff)
1361209ff23fSmrg				| ((vsync_wid & 0x1f) << 16)
1362209ff23fSmrg				| ((mode->Flags & V_NVSYNC)
1363209ff23fSmrg				   ? RADEON_CRTC_V_SYNC_POL
1364209ff23fSmrg				   : 0));
1365209ff23fSmrg
1366209ff23fSmrg    save->fp_horz_vert_active = 0;
1367209ff23fSmrg
1368b7e1c893Smrg    if ((radeon_output->active_device & (ATOM_DEVICE_LCD_SUPPORT)) ||
1369b7e1c893Smrg	(radeon_output->active_device & (ATOM_DEVICE_DFP_SUPPORT))) {
1370209ff23fSmrg
1371b7e1c893Smrg	if (native_mode->PanelXRes == 0 || native_mode->PanelYRes == 0) {
1372209ff23fSmrg	    Hscale = FALSE;
1373209ff23fSmrg	    Vscale = FALSE;
1374b7e1c893Smrg	} else {
1375b7e1c893Smrg	    if (xres > native_mode->PanelXRes)
1376b7e1c893Smrg		xres = native_mode->PanelXRes;
1377b7e1c893Smrg	    if (yres > native_mode->PanelYRes)
1378b7e1c893Smrg		yres = native_mode->PanelYRes;
1379b7e1c893Smrg
1380b7e1c893Smrg	    if (xres == native_mode->PanelXRes)
1381b7e1c893Smrg		Hscale = FALSE;
1382b7e1c893Smrg	    if (yres == native_mode->PanelYRes)
1383b7e1c893Smrg		Vscale = FALSE;
1384b7e1c893Smrg	}
1385209ff23fSmrg
1386b7e1c893Smrg	if ((!Hscale) || (!(radeon_output->Flags & RADEON_USE_RMX)) ||
1387b7e1c893Smrg	    (radeon_output->rmx_type == RMX_CENTER)) {
1388b7e1c893Smrg	    save->fp_horz_stretch |= ((xres/8-1)<<16);
1389b7e1c893Smrg	} else {
1390b7e1c893Smrg	    uint32_t scale, inc;
1391b7e1c893Smrg	    inc = (save->fp_horz_stretch & RADEON_HORZ_AUTO_RATIO_INC) ? 1 : 0;
1392b7e1c893Smrg	    scale = ((xres + inc) * RADEON_HORZ_STRETCH_RATIO_MAX)
1393b7e1c893Smrg		/ native_mode->PanelXRes + 1;
1394b7e1c893Smrg	    save->fp_horz_stretch |= (((scale) & RADEON_HORZ_STRETCH_RATIO_MASK) |
1395b7e1c893Smrg				      RADEON_HORZ_STRETCH_BLEND |
1396b7e1c893Smrg				      RADEON_HORZ_STRETCH_ENABLE |
1397b7e1c893Smrg				      ((native_mode->PanelXRes/8-1)<<16));
1398b7e1c893Smrg	}
1399209ff23fSmrg
1400b7e1c893Smrg	if ((!Vscale) || (!(radeon_output->Flags & RADEON_USE_RMX)) ||
1401b7e1c893Smrg	    (radeon_output->rmx_type == RMX_CENTER)) {
1402b7e1c893Smrg	    save->fp_vert_stretch |= ((yres-1)<<12);
1403b7e1c893Smrg	} else {
1404b7e1c893Smrg	    uint32_t scale, inc;
1405b7e1c893Smrg	    inc = (save->fp_vert_stretch & RADEON_VERT_AUTO_RATIO_INC) ? 1 : 0;
1406b7e1c893Smrg	    scale = ((yres + inc) * RADEON_VERT_STRETCH_RATIO_MAX)
1407b7e1c893Smrg		/ native_mode->PanelYRes + 1;
1408b7e1c893Smrg	    save->fp_vert_stretch |= (((scale) & RADEON_VERT_STRETCH_RATIO_MASK) |
1409b7e1c893Smrg				      RADEON_VERT_STRETCH_ENABLE |
1410b7e1c893Smrg				      RADEON_VERT_STRETCH_BLEND |
1411b7e1c893Smrg				      ((native_mode->PanelYRes-1)<<12));
1412b7e1c893Smrg	}
1413209ff23fSmrg
1414b7e1c893Smrg	if ((radeon_output->rmx_type == RMX_CENTER) &&
1415b7e1c893Smrg	    (radeon_output->Flags & RADEON_USE_RMX)) {
1416b7e1c893Smrg	    int    blank_width;
1417209ff23fSmrg
1418b7e1c893Smrg	    save->crtc_more_cntl |= (RADEON_CRTC_AUTO_HORZ_CENTER_EN |
1419b7e1c893Smrg				     RADEON_CRTC_AUTO_VERT_CENTER_EN);
1420209ff23fSmrg
1421b7e1c893Smrg	    blank_width = (mode->CrtcHBlankEnd - mode->CrtcHBlankStart) / 8;
1422b7e1c893Smrg	    if (blank_width > 110)
1423b7e1c893Smrg		blank_width = 110;
1424209ff23fSmrg
1425b7e1c893Smrg	    save->fp_crtc_h_total_disp = (((blank_width) & 0x3ff)
1426b7e1c893Smrg					  | ((((mode->CrtcHDisplay / 8) - 1) & 0x1ff)
1427b7e1c893Smrg					     << 16));
1428209ff23fSmrg
1429b7e1c893Smrg	    hsync_wid = (mode->CrtcHSyncEnd - mode->CrtcHSyncStart) / 8;
1430b7e1c893Smrg	    if (!hsync_wid)
1431b7e1c893Smrg		hsync_wid = 1;
1432209ff23fSmrg
1433b7e1c893Smrg	    save->fp_h_sync_strt_wid = ((((mode->CrtcHSyncStart - mode->CrtcHBlankStart) / 8) & 0x1fff)
1434b7e1c893Smrg					| ((hsync_wid & 0x3f) << 16)
1435b7e1c893Smrg					| ((mode->Flags & V_NHSYNC)
1436b7e1c893Smrg					   ? RADEON_CRTC_H_SYNC_POL
1437b7e1c893Smrg					   : 0));
1438209ff23fSmrg
1439b7e1c893Smrg	    save->fp_crtc_v_total_disp = (((mode->CrtcVBlankEnd - mode->CrtcVBlankStart) & 0xffff)
1440b7e1c893Smrg					  | ((mode->CrtcVDisplay - 1) << 16));
1441209ff23fSmrg
1442b7e1c893Smrg	    vsync_wid = mode->CrtcVSyncEnd - mode->CrtcVSyncStart;
1443b7e1c893Smrg	    if (!vsync_wid)
1444b7e1c893Smrg		vsync_wid = 1;
1445209ff23fSmrg
1446b7e1c893Smrg	    save->fp_v_sync_strt_wid = ((((mode->CrtcVSyncStart - mode->CrtcVBlankStart) & 0xfff)
1447b7e1c893Smrg					 | ((vsync_wid & 0x1f) << 16)
1448b7e1c893Smrg					 | ((mode->Flags & V_NVSYNC)
1449b7e1c893Smrg					    ? RADEON_CRTC_V_SYNC_POL
1450b7e1c893Smrg					    : 0)));
1451209ff23fSmrg
1452b7e1c893Smrg	    save->fp_horz_vert_active = (((native_mode->PanelYRes) & 0xfff) |
1453b7e1c893Smrg					 (((native_mode->PanelXRes / 8) & 0x1ff) << 16));
1454209ff23fSmrg
1455b7e1c893Smrg	}
1456209ff23fSmrg    }
1457209ff23fSmrg}
1458209ff23fSmrg
1459209ff23fSmrgstatic void
1460209ff23fSmrgRADEONInitDACRegisters(xf86OutputPtr output, RADEONSavePtr save,
1461209ff23fSmrg		       DisplayModePtr mode, BOOL IsPrimary)
1462209ff23fSmrg{
1463209ff23fSmrg    ScrnInfoPtr pScrn = output->scrn;
1464209ff23fSmrg    RADEONInfoPtr  info       = RADEONPTR(pScrn);
1465209ff23fSmrg
1466209ff23fSmrg    if (IsPrimary) {
1467209ff23fSmrg	if ((info->ChipFamily == CHIP_FAMILY_R200) || IS_R300_VARIANT) {
1468209ff23fSmrg            save->disp_output_cntl = info->SavedReg->disp_output_cntl &
1469209ff23fSmrg					~RADEON_DISP_DAC_SOURCE_MASK;
1470209ff23fSmrg        } else {
1471209ff23fSmrg            save->dac2_cntl = info->SavedReg->dac2_cntl & ~(RADEON_DAC2_DAC_CLK_SEL);
1472209ff23fSmrg        }
1473209ff23fSmrg    } else {
1474209ff23fSmrg        if ((info->ChipFamily == CHIP_FAMILY_R200) || IS_R300_VARIANT) {
1475209ff23fSmrg            save->disp_output_cntl = info->SavedReg->disp_output_cntl &
1476209ff23fSmrg					~RADEON_DISP_DAC_SOURCE_MASK;
1477209ff23fSmrg            save->disp_output_cntl |= RADEON_DISP_DAC_SOURCE_CRTC2;
1478209ff23fSmrg        } else {
1479209ff23fSmrg            save->dac2_cntl = info->SavedReg->dac2_cntl | RADEON_DAC2_DAC_CLK_SEL;
1480209ff23fSmrg        }
1481209ff23fSmrg    }
1482209ff23fSmrg    save->dac_cntl = (RADEON_DAC_MASK_ALL
1483209ff23fSmrg		      | RADEON_DAC_VGA_ADR_EN
1484209ff23fSmrg		      | (info->dac6bits ? 0 : RADEON_DAC_8BIT_EN));
1485209ff23fSmrg
1486209ff23fSmrg    save->dac_macro_cntl = info->SavedReg->dac_macro_cntl;
1487209ff23fSmrg}
1488209ff23fSmrg
1489209ff23fSmrgstatic void
1490209ff23fSmrgRADEONInitTvDacCntl(xf86OutputPtr output, RADEONSavePtr save)
1491209ff23fSmrg{
1492209ff23fSmrg    ScrnInfoPtr pScrn = output->scrn;
1493209ff23fSmrg    RADEONInfoPtr  info       = RADEONPTR(pScrn);
1494b7e1c893Smrg    radeon_encoder_ptr radeon_encoder = radeon_get_encoder(output);
1495b7e1c893Smrg    radeon_tvdac_ptr tvdac = NULL;
1496b7e1c893Smrg
1497b7e1c893Smrg    if (radeon_encoder == NULL)
1498b7e1c893Smrg	return;
1499b7e1c893Smrg
1500b7e1c893Smrg    tvdac = (radeon_tvdac_ptr)radeon_encoder->dev_priv;
1501b7e1c893Smrg
1502b7e1c893Smrg    if (tvdac == NULL)
1503b7e1c893Smrg	return;
1504209ff23fSmrg
1505209ff23fSmrg    if (info->ChipFamily == CHIP_FAMILY_R420 ||
1506209ff23fSmrg	info->ChipFamily == CHIP_FAMILY_RV410) {
1507209ff23fSmrg	save->tv_dac_cntl = info->SavedReg->tv_dac_cntl &
1508209ff23fSmrg			     ~(RADEON_TV_DAC_STD_MASK |
1509209ff23fSmrg			       RADEON_TV_DAC_BGADJ_MASK |
1510209ff23fSmrg			       R420_TV_DAC_DACADJ_MASK |
1511209ff23fSmrg			       R420_TV_DAC_RDACPD |
1512209ff23fSmrg			       R420_TV_DAC_GDACPD |
1513209ff23fSmrg			       R420_TV_DAC_GDACPD |
1514209ff23fSmrg			       R420_TV_DAC_TVENABLE);
1515209ff23fSmrg    } else {
1516209ff23fSmrg	save->tv_dac_cntl = info->SavedReg->tv_dac_cntl &
1517209ff23fSmrg			     ~(RADEON_TV_DAC_STD_MASK |
1518209ff23fSmrg			       RADEON_TV_DAC_BGADJ_MASK |
1519209ff23fSmrg			       RADEON_TV_DAC_DACADJ_MASK |
1520209ff23fSmrg			       RADEON_TV_DAC_RDACPD |
1521209ff23fSmrg			       RADEON_TV_DAC_GDACPD |
1522209ff23fSmrg			       RADEON_TV_DAC_GDACPD);
1523209ff23fSmrg    }
1524209ff23fSmrg
1525209ff23fSmrg    save->tv_dac_cntl |= (RADEON_TV_DAC_NBLANK |
1526209ff23fSmrg			  RADEON_TV_DAC_NHOLD |
1527209ff23fSmrg			  RADEON_TV_DAC_STD_PS2 |
1528b7e1c893Smrg			  tvdac->ps2_tvdac_adj);
1529209ff23fSmrg
1530209ff23fSmrg}
1531209ff23fSmrg
1532209ff23fSmrgstatic void
1533209ff23fSmrgRADEONInitDAC2Registers(xf86OutputPtr output, RADEONSavePtr save,
1534209ff23fSmrg			DisplayModePtr mode, BOOL IsPrimary)
1535209ff23fSmrg{
1536209ff23fSmrg    ScrnInfoPtr pScrn = output->scrn;
1537209ff23fSmrg    RADEONInfoPtr  info       = RADEONPTR(pScrn);
1538209ff23fSmrg
1539209ff23fSmrg    /*0x0028023;*/
1540209ff23fSmrg    RADEONInitTvDacCntl(output, save);
1541209ff23fSmrg
1542209ff23fSmrg    if (IS_R300_VARIANT)
1543209ff23fSmrg	save->gpiopad_a = info->SavedReg->gpiopad_a | 1;
1544209ff23fSmrg
1545209ff23fSmrg    save->dac2_cntl = info->SavedReg->dac2_cntl | RADEON_DAC2_DAC2_CLK_SEL;
1546209ff23fSmrg
1547209ff23fSmrg    if (IsPrimary) {
1548209ff23fSmrg        if (IS_R300_VARIANT) {
1549209ff23fSmrg            save->disp_output_cntl = info->SavedReg->disp_output_cntl &
1550209ff23fSmrg					~RADEON_DISP_TVDAC_SOURCE_MASK;
1551209ff23fSmrg            save->disp_output_cntl |= RADEON_DISP_TVDAC_SOURCE_CRTC;
1552209ff23fSmrg        } else if (info->ChipFamily == CHIP_FAMILY_R200) {
1553209ff23fSmrg	    save->fp2_gen_cntl = info->SavedReg->fp2_gen_cntl &
1554209ff23fSmrg				  ~(R200_FP2_SOURCE_SEL_MASK |
1555209ff23fSmrg				    RADEON_FP2_DVO_RATE_SEL_SDR);
1556209ff23fSmrg	} else {
1557209ff23fSmrg            save->disp_hw_debug = info->SavedReg->disp_hw_debug | RADEON_CRT2_DISP1_SEL;
1558209ff23fSmrg        }
1559209ff23fSmrg    } else {
1560209ff23fSmrg        if (IS_R300_VARIANT) {
1561209ff23fSmrg            save->disp_output_cntl = info->SavedReg->disp_output_cntl &
1562209ff23fSmrg					~RADEON_DISP_TVDAC_SOURCE_MASK;
1563209ff23fSmrg            save->disp_output_cntl |= RADEON_DISP_TVDAC_SOURCE_CRTC2;
1564209ff23fSmrg	} else if (info->ChipFamily == CHIP_FAMILY_R200) {
1565209ff23fSmrg	    save->fp2_gen_cntl = info->SavedReg->fp2_gen_cntl &
1566209ff23fSmrg				  ~(R200_FP2_SOURCE_SEL_MASK |
1567209ff23fSmrg				    RADEON_FP2_DVO_RATE_SEL_SDR);
1568209ff23fSmrg            save->fp2_gen_cntl |= R200_FP2_SOURCE_SEL_CRTC2;
1569209ff23fSmrg        } else {
1570209ff23fSmrg            save->disp_hw_debug = info->SavedReg->disp_hw_debug &
1571209ff23fSmrg					~RADEON_CRT2_DISP1_SEL;
1572209ff23fSmrg        }
1573209ff23fSmrg    }
1574209ff23fSmrg}
1575209ff23fSmrg
1576209ff23fSmrgvoid
1577209ff23fSmrglegacy_output_mode_set(xf86OutputPtr output, DisplayModePtr mode,
1578b7e1c893Smrg		       DisplayModePtr adjusted_mode)
1579209ff23fSmrg{
1580209ff23fSmrg    ScrnInfoPtr	    pScrn = output->scrn;
1581209ff23fSmrg    RADEONInfoPtr info = RADEONPTR(pScrn);
1582209ff23fSmrg    RADEONOutputPrivatePtr radeon_output = output->driver_private;
1583209ff23fSmrg    xf86CrtcPtr	crtc = output->crtc;
1584209ff23fSmrg    RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
1585b7e1c893Smrg    radeon_encoder_ptr radeon_encoder = radeon_get_encoder(output);
1586b7e1c893Smrg    Bool is_primary = FALSE;
1587209ff23fSmrg
1588b7e1c893Smrg    if (radeon_encoder == NULL)
1589b7e1c893Smrg	return;
1590209ff23fSmrg
1591b7e1c893Smrg    radeon_output->pixel_clock = adjusted_mode->Clock;
1592b7e1c893Smrg    if (radeon_crtc->crtc_id == 0) {
1593b7e1c893Smrg	ErrorF("set RMX\n");
1594b7e1c893Smrg	is_primary = TRUE;
1595b7e1c893Smrg	RADEONInitRMXRegisters(output, info->ModeReg, adjusted_mode);
1596209ff23fSmrg	RADEONRestoreRMXRegisters(pScrn, info->ModeReg);
1597b7e1c893Smrg    }
1598209ff23fSmrg
1599b7e1c893Smrg    switch (radeon_encoder->encoder_id) {
1600b7e1c893Smrg    case ENCODER_OBJECT_ID_INTERNAL_LVDS:
1601b7e1c893Smrg	ErrorF("set LVDS\n");
1602b7e1c893Smrg	RADEONInitLVDSRegisters(output, info->ModeReg, adjusted_mode, is_primary);
1603209ff23fSmrg	RADEONRestoreLVDSRegisters(pScrn, info->ModeReg);
1604209ff23fSmrg	break;
1605b7e1c893Smrg    case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
1606b7e1c893Smrg	ErrorF("set FP1\n");
1607b7e1c893Smrg	RADEONInitFPRegisters(output, info->ModeReg, adjusted_mode, is_primary);
1608b7e1c893Smrg	RADEONRestoreFPRegisters(pScrn, info->ModeReg);
1609b7e1c893Smrg	break;
1610b7e1c893Smrg    case ENCODER_OBJECT_ID_INTERNAL_DVO1:
1611b7e1c893Smrg	ErrorF("set FP2\n");
1612b7e1c893Smrg	RADEONInitFP2Registers(output, info->ModeReg, adjusted_mode, is_primary);
1613b7e1c893Smrg	if (info->IsAtomBios) {
1614b7e1c893Smrg	    unsigned char *RADEONMMIO = info->MMIO;
1615b7e1c893Smrg	    uint32_t fp2_gen_cntl;
1616b7e1c893Smrg
1617b7e1c893Smrg	    atombios_external_tmds_setup(output, ATOM_ENABLE);
1618b7e1c893Smrg	    fp2_gen_cntl = INREG(RADEON_FP2_GEN_CNTL) & ~R200_FP2_SOURCE_SEL_MASK;
1619b7e1c893Smrg	    if (radeon_crtc->crtc_id == 1)
1620b7e1c893Smrg		fp2_gen_cntl |= R200_FP2_SOURCE_SEL_CRTC2;
1621b7e1c893Smrg	    else {
1622b7e1c893Smrg		if (radeon_output->Flags & RADEON_USE_RMX)
1623b7e1c893Smrg		    fp2_gen_cntl |= R200_FP2_SOURCE_SEL_RMX;
1624b7e1c893Smrg		else
1625b7e1c893Smrg		    fp2_gen_cntl |= R200_FP2_SOURCE_SEL_CRTC1;
1626209ff23fSmrg	    }
1627b7e1c893Smrg	    OUTREG(RADEON_FP2_GEN_CNTL, fp2_gen_cntl);
1628b7e1c893Smrg	} else {
1629b7e1c893Smrg	    RADEONRestoreFP2Registers(pScrn, info->ModeReg);
1630b7e1c893Smrg	    RADEONRestoreDVOChip(pScrn, output);
1631209ff23fSmrg	}
1632209ff23fSmrg	break;
1633b7e1c893Smrg    case ENCODER_OBJECT_ID_INTERNAL_DAC1:
1634b7e1c893Smrg	ErrorF("set primary dac\n");
1635b7e1c893Smrg	RADEONInitDACRegisters(output, info->ModeReg, adjusted_mode, is_primary);
1636209ff23fSmrg	RADEONRestoreDACRegisters(pScrn, info->ModeReg);
1637209ff23fSmrg	break;
1638b7e1c893Smrg    case ENCODER_OBJECT_ID_INTERNAL_DAC2:
1639b7e1c893Smrg	if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT)) {
1640b7e1c893Smrg	    ErrorF("set TV\n");
1641b7e1c893Smrg	    RADEONInitTVRegisters(output, info->ModeReg, adjusted_mode, is_primary);
1642b7e1c893Smrg	    RADEONRestoreDACRegisters(pScrn, info->ModeReg);
1643b7e1c893Smrg	    RADEONRestoreTVRegisters(pScrn, info->ModeReg);
1644b7e1c893Smrg	} else {
1645b7e1c893Smrg	    ErrorF("set TVDAC\n");
1646b7e1c893Smrg	    RADEONInitDAC2Registers(output, info->ModeReg, adjusted_mode, is_primary);
1647b7e1c893Smrg	    RADEONRestoreDACRegisters(pScrn, info->ModeReg);
1648b7e1c893Smrg	}
1649b7e1c893Smrg	break;
1650209ff23fSmrg    }
1651209ff23fSmrg
1652209ff23fSmrg}
1653209ff23fSmrg
1654209ff23fSmrg/* the following functions are based on the load detection code
1655209ff23fSmrg * in the beos radeon driver by Thomas Kurschel and the existing
1656209ff23fSmrg * load detection code in this driver.
1657209ff23fSmrg */
1658209ff23fSmrgstatic RADEONMonitorType
1659209ff23fSmrgradeon_detect_primary_dac(ScrnInfoPtr pScrn, Bool color)
1660209ff23fSmrg{
1661209ff23fSmrg    RADEONInfoPtr info = RADEONPTR(pScrn);
1662209ff23fSmrg    unsigned char *RADEONMMIO = info->MMIO;
1663209ff23fSmrg    uint32_t vclk_ecp_cntl, crtc_ext_cntl;
1664209ff23fSmrg    uint32_t dac_ext_cntl, dac_cntl, dac_macro_cntl, tmp;
1665209ff23fSmrg    RADEONMonitorType found = MT_NONE;
1666209ff23fSmrg
1667209ff23fSmrg    /* save the regs we need */
1668209ff23fSmrg    vclk_ecp_cntl = INPLL(pScrn, RADEON_VCLK_ECP_CNTL);
1669209ff23fSmrg    crtc_ext_cntl = INREG(RADEON_CRTC_EXT_CNTL);
1670209ff23fSmrg    dac_ext_cntl = INREG(RADEON_DAC_EXT_CNTL);
1671209ff23fSmrg    dac_cntl = INREG(RADEON_DAC_CNTL);
1672209ff23fSmrg    dac_macro_cntl = INREG(RADEON_DAC_MACRO_CNTL);
1673209ff23fSmrg
1674209ff23fSmrg    tmp = vclk_ecp_cntl &
1675209ff23fSmrg	~(RADEON_PIXCLK_ALWAYS_ONb | RADEON_PIXCLK_DAC_ALWAYS_ONb);
1676209ff23fSmrg    OUTPLL(pScrn, RADEON_VCLK_ECP_CNTL, tmp);
1677209ff23fSmrg
1678209ff23fSmrg    tmp = crtc_ext_cntl | RADEON_CRTC_CRT_ON;
1679209ff23fSmrg    OUTREG(RADEON_CRTC_EXT_CNTL, tmp);
1680209ff23fSmrg
1681209ff23fSmrg    tmp = RADEON_DAC_FORCE_BLANK_OFF_EN |
1682209ff23fSmrg	RADEON_DAC_FORCE_DATA_EN;
1683209ff23fSmrg
1684209ff23fSmrg    if (color)
1685209ff23fSmrg	tmp |= RADEON_DAC_FORCE_DATA_SEL_RGB;
1686209ff23fSmrg    else
1687209ff23fSmrg	tmp |= RADEON_DAC_FORCE_DATA_SEL_G;
1688209ff23fSmrg
1689209ff23fSmrg    if (IS_R300_VARIANT)
1690209ff23fSmrg	tmp |= (0x1b6 << RADEON_DAC_FORCE_DATA_SHIFT);
1691209ff23fSmrg    else
1692209ff23fSmrg	tmp |= (0x180 << RADEON_DAC_FORCE_DATA_SHIFT);
1693209ff23fSmrg
1694209ff23fSmrg    OUTREG(RADEON_DAC_EXT_CNTL, tmp);
1695209ff23fSmrg
1696209ff23fSmrg    tmp = dac_cntl & ~(RADEON_DAC_RANGE_CNTL_MASK | RADEON_DAC_PDWN);
1697209ff23fSmrg    tmp |= RADEON_DAC_RANGE_CNTL_PS2 | RADEON_DAC_CMP_EN;
1698209ff23fSmrg    OUTREG(RADEON_DAC_CNTL, tmp);
1699209ff23fSmrg
1700209ff23fSmrg    tmp &= ~(RADEON_DAC_PDWN_R |
1701209ff23fSmrg	     RADEON_DAC_PDWN_G |
1702209ff23fSmrg	     RADEON_DAC_PDWN_B);
1703209ff23fSmrg
1704209ff23fSmrg    OUTREG(RADEON_DAC_MACRO_CNTL, tmp);
1705209ff23fSmrg
1706209ff23fSmrg    usleep(2000);
1707209ff23fSmrg
1708209ff23fSmrg    if (INREG(RADEON_DAC_CNTL) & RADEON_DAC_CMP_OUTPUT) {
1709209ff23fSmrg	found = MT_CRT;
1710209ff23fSmrg	xf86DrvMsg (pScrn->scrnIndex, X_INFO,
1711209ff23fSmrg		    "Found %s CRT connected to primary DAC\n",
1712209ff23fSmrg		    color ? "color" : "bw");
1713209ff23fSmrg    }
1714209ff23fSmrg
1715209ff23fSmrg    /* restore the regs we used */
1716209ff23fSmrg    OUTREG(RADEON_DAC_CNTL, dac_cntl);
1717209ff23fSmrg    OUTREG(RADEON_DAC_MACRO_CNTL, dac_macro_cntl);
1718209ff23fSmrg    OUTREG(RADEON_DAC_EXT_CNTL, dac_ext_cntl);
1719209ff23fSmrg    OUTREG(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl);
1720209ff23fSmrg    OUTPLL(pScrn, RADEON_VCLK_ECP_CNTL, vclk_ecp_cntl);
1721209ff23fSmrg
1722209ff23fSmrg    return found;
1723209ff23fSmrg}
1724209ff23fSmrg
1725209ff23fSmrgstatic RADEONMonitorType
1726209ff23fSmrgradeon_detect_ext_dac(ScrnInfoPtr pScrn)
1727209ff23fSmrg{
1728209ff23fSmrg    RADEONInfoPtr info = RADEONPTR(pScrn);
1729209ff23fSmrg    unsigned char *RADEONMMIO = info->MMIO;
1730209ff23fSmrg    uint32_t gpio_monid, fp2_gen_cntl, disp_output_cntl, crtc2_gen_cntl;
1731209ff23fSmrg    uint32_t disp_lin_trans_grph_a, disp_lin_trans_grph_b, disp_lin_trans_grph_c;
1732209ff23fSmrg    uint32_t disp_lin_trans_grph_d, disp_lin_trans_grph_e, disp_lin_trans_grph_f;
1733209ff23fSmrg    uint32_t tmp, crtc2_h_total_disp, crtc2_v_total_disp;
1734209ff23fSmrg    uint32_t crtc2_h_sync_strt_wid, crtc2_v_sync_strt_wid;
1735209ff23fSmrg    RADEONMonitorType found = MT_NONE;
1736209ff23fSmrg    int connected = 0;
1737209ff23fSmrg    int i = 0;
1738209ff23fSmrg
1739209ff23fSmrg    /* save the regs we need */
1740209ff23fSmrg    gpio_monid = INREG(RADEON_GPIO_MONID);
1741209ff23fSmrg    fp2_gen_cntl = INREG(RADEON_FP2_GEN_CNTL);
1742209ff23fSmrg    disp_output_cntl = INREG(RADEON_DISP_OUTPUT_CNTL);
1743209ff23fSmrg    crtc2_gen_cntl = INREG(RADEON_CRTC2_GEN_CNTL);
1744209ff23fSmrg    disp_lin_trans_grph_a = INREG(RADEON_DISP_LIN_TRANS_GRPH_A);
1745209ff23fSmrg    disp_lin_trans_grph_b = INREG(RADEON_DISP_LIN_TRANS_GRPH_B);
1746209ff23fSmrg    disp_lin_trans_grph_c = INREG(RADEON_DISP_LIN_TRANS_GRPH_C);
1747209ff23fSmrg    disp_lin_trans_grph_d = INREG(RADEON_DISP_LIN_TRANS_GRPH_D);
1748209ff23fSmrg    disp_lin_trans_grph_e = INREG(RADEON_DISP_LIN_TRANS_GRPH_E);
1749209ff23fSmrg    disp_lin_trans_grph_f = INREG(RADEON_DISP_LIN_TRANS_GRPH_F);
1750209ff23fSmrg    crtc2_h_total_disp = INREG(RADEON_CRTC2_H_TOTAL_DISP);
1751209ff23fSmrg    crtc2_v_total_disp = INREG(RADEON_CRTC2_V_TOTAL_DISP);
1752209ff23fSmrg    crtc2_h_sync_strt_wid = INREG(RADEON_CRTC2_H_SYNC_STRT_WID);
1753209ff23fSmrg    crtc2_v_sync_strt_wid = INREG(RADEON_CRTC2_V_SYNC_STRT_WID);
1754209ff23fSmrg
1755209ff23fSmrg    tmp = INREG(RADEON_GPIO_MONID);
1756209ff23fSmrg    tmp &= ~RADEON_GPIO_A_0;
1757209ff23fSmrg    OUTREG(RADEON_GPIO_MONID, tmp);
1758209ff23fSmrg
1759209ff23fSmrg    OUTREG(RADEON_FP2_GEN_CNTL,
1760209ff23fSmrg	   RADEON_FP2_ON |
1761209ff23fSmrg	   RADEON_FP2_PANEL_FORMAT |
1762209ff23fSmrg	   R200_FP2_SOURCE_SEL_TRANS_UNIT |
1763209ff23fSmrg	   RADEON_FP2_DVO_EN |
1764209ff23fSmrg	   R200_FP2_DVO_RATE_SEL_SDR);
1765209ff23fSmrg
1766209ff23fSmrg    OUTREG(RADEON_DISP_OUTPUT_CNTL,
1767209ff23fSmrg	   RADEON_DISP_DAC_SOURCE_RMX |
1768209ff23fSmrg	   RADEON_DISP_TRANS_MATRIX_GRAPHICS);
1769209ff23fSmrg
1770209ff23fSmrg    OUTREG(RADEON_CRTC2_GEN_CNTL,
1771209ff23fSmrg	   RADEON_CRTC2_EN |
1772209ff23fSmrg	   RADEON_CRTC2_DISP_REQ_EN_B);
1773209ff23fSmrg
1774209ff23fSmrg    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_A, 0x00000000);
1775209ff23fSmrg    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_B, 0x000003f0);
1776209ff23fSmrg    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_C, 0x00000000);
1777209ff23fSmrg    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_D, 0x000003f0);
1778209ff23fSmrg    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_E, 0x00000000);
1779209ff23fSmrg    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_F, 0x000003f0);
1780209ff23fSmrg
1781209ff23fSmrg    OUTREG(RADEON_CRTC2_H_TOTAL_DISP, 0x01000008);
1782209ff23fSmrg    OUTREG(RADEON_CRTC2_H_SYNC_STRT_WID, 0x00000800);
1783209ff23fSmrg    OUTREG(RADEON_CRTC2_V_TOTAL_DISP, 0x00080001);
1784209ff23fSmrg    OUTREG(RADEON_CRTC2_V_SYNC_STRT_WID, 0x00000080);
1785209ff23fSmrg
1786209ff23fSmrg    for (i = 0; i < 200; i++) {
1787209ff23fSmrg	tmp = INREG(RADEON_GPIO_MONID);
1788209ff23fSmrg	if (tmp & RADEON_GPIO_Y_0)
1789209ff23fSmrg	    connected = 1;
1790209ff23fSmrg	else
1791209ff23fSmrg	    connected = 0;
1792209ff23fSmrg
1793209ff23fSmrg	if (!connected)
1794209ff23fSmrg	    break;
1795209ff23fSmrg
1796209ff23fSmrg	usleep(1000);
1797209ff23fSmrg    }
1798209ff23fSmrg
1799209ff23fSmrg    if (connected)
1800209ff23fSmrg	found = MT_CRT;
1801209ff23fSmrg
1802209ff23fSmrg    /* restore the regs we used */
1803209ff23fSmrg    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_A, disp_lin_trans_grph_a);
1804209ff23fSmrg    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_B, disp_lin_trans_grph_b);
1805209ff23fSmrg    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_C, disp_lin_trans_grph_c);
1806209ff23fSmrg    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_D, disp_lin_trans_grph_d);
1807209ff23fSmrg    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_E, disp_lin_trans_grph_e);
1808209ff23fSmrg    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_F, disp_lin_trans_grph_f);
1809209ff23fSmrg    OUTREG(RADEON_CRTC2_H_TOTAL_DISP, crtc2_h_total_disp);
1810209ff23fSmrg    OUTREG(RADEON_CRTC2_V_TOTAL_DISP, crtc2_v_total_disp);
1811209ff23fSmrg    OUTREG(RADEON_CRTC2_H_SYNC_STRT_WID, crtc2_h_sync_strt_wid);
1812209ff23fSmrg    OUTREG(RADEON_CRTC2_V_SYNC_STRT_WID, crtc2_v_sync_strt_wid);
1813209ff23fSmrg    OUTREG(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
1814209ff23fSmrg    OUTREG(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl);
1815209ff23fSmrg    OUTREG(RADEON_FP2_GEN_CNTL, fp2_gen_cntl);
1816209ff23fSmrg    OUTREG(RADEON_GPIO_MONID, gpio_monid);
1817209ff23fSmrg
1818209ff23fSmrg    return found;
1819209ff23fSmrg}
1820209ff23fSmrg
1821209ff23fSmrgstatic RADEONMonitorType
1822209ff23fSmrgradeon_detect_tv_dac(ScrnInfoPtr pScrn, Bool color)
1823209ff23fSmrg{
1824209ff23fSmrg    RADEONInfoPtr info = RADEONPTR(pScrn);
1825209ff23fSmrg    unsigned char *RADEONMMIO = info->MMIO;
1826209ff23fSmrg    uint32_t crtc2_gen_cntl, tv_dac_cntl, dac_cntl2, dac_ext_cntl;
1827209ff23fSmrg    uint32_t disp_hw_debug, disp_output_cntl, gpiopad_a, pixclks_cntl, tmp;
1828209ff23fSmrg    RADEONMonitorType found = MT_NONE;
1829209ff23fSmrg
1830209ff23fSmrg    /* save the regs we need */
1831209ff23fSmrg    pixclks_cntl = INPLL(pScrn, RADEON_PIXCLKS_CNTL);
1832209ff23fSmrg    gpiopad_a = IS_R300_VARIANT ? INREG(RADEON_GPIOPAD_A) : 0;
1833209ff23fSmrg    disp_output_cntl = IS_R300_VARIANT ? INREG(RADEON_DISP_OUTPUT_CNTL) : 0;
1834209ff23fSmrg    disp_hw_debug = !IS_R300_VARIANT ? INREG(RADEON_DISP_HW_DEBUG) : 0;
1835209ff23fSmrg    crtc2_gen_cntl = INREG(RADEON_CRTC2_GEN_CNTL);
1836209ff23fSmrg    tv_dac_cntl = INREG(RADEON_TV_DAC_CNTL);
1837209ff23fSmrg    dac_ext_cntl = INREG(RADEON_DAC_EXT_CNTL);
1838209ff23fSmrg    dac_cntl2 = INREG(RADEON_DAC_CNTL2);
1839209ff23fSmrg
1840209ff23fSmrg    tmp = pixclks_cntl & ~(RADEON_PIX2CLK_ALWAYS_ONb
1841209ff23fSmrg			   | RADEON_PIX2CLK_DAC_ALWAYS_ONb);
1842209ff23fSmrg    OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, tmp);
1843209ff23fSmrg
1844209ff23fSmrg    if (IS_R300_VARIANT) {
1845209ff23fSmrg	OUTREGP(RADEON_GPIOPAD_A, 1, ~1 );
1846209ff23fSmrg    }
1847209ff23fSmrg
1848209ff23fSmrg    tmp = crtc2_gen_cntl & ~RADEON_CRTC2_PIX_WIDTH_MASK;
1849209ff23fSmrg    tmp |= RADEON_CRTC2_CRT2_ON |
1850209ff23fSmrg	(2 << RADEON_CRTC2_PIX_WIDTH_SHIFT);
1851209ff23fSmrg
1852209ff23fSmrg    OUTREG(RADEON_CRTC2_GEN_CNTL, tmp);
1853209ff23fSmrg
1854209ff23fSmrg    if (IS_R300_VARIANT) {
1855209ff23fSmrg	tmp = disp_output_cntl & ~RADEON_DISP_TVDAC_SOURCE_MASK;
1856209ff23fSmrg	tmp |= RADEON_DISP_TVDAC_SOURCE_CRTC2;
1857209ff23fSmrg	OUTREG(RADEON_DISP_OUTPUT_CNTL, tmp);
1858209ff23fSmrg    } else {
1859209ff23fSmrg	tmp = disp_hw_debug & ~RADEON_CRT2_DISP1_SEL;
1860209ff23fSmrg	OUTREG(RADEON_DISP_HW_DEBUG, tmp);
1861209ff23fSmrg    }
1862209ff23fSmrg
1863209ff23fSmrg    tmp = RADEON_TV_DAC_NBLANK |
1864209ff23fSmrg	RADEON_TV_DAC_NHOLD |
1865209ff23fSmrg	RADEON_TV_MONITOR_DETECT_EN |
1866209ff23fSmrg	RADEON_TV_DAC_STD_PS2;
1867209ff23fSmrg
1868209ff23fSmrg    OUTREG(RADEON_TV_DAC_CNTL, tmp);
1869209ff23fSmrg
1870209ff23fSmrg    tmp = RADEON_DAC2_FORCE_BLANK_OFF_EN |
1871209ff23fSmrg	RADEON_DAC2_FORCE_DATA_EN;
1872209ff23fSmrg
1873209ff23fSmrg    if (color)
1874209ff23fSmrg	tmp |= RADEON_DAC_FORCE_DATA_SEL_RGB;
1875209ff23fSmrg    else
1876209ff23fSmrg	tmp |= RADEON_DAC_FORCE_DATA_SEL_G;
1877209ff23fSmrg
1878209ff23fSmrg    if (IS_R300_VARIANT)
1879209ff23fSmrg	tmp |= (0x1b6 << RADEON_DAC_FORCE_DATA_SHIFT);
1880209ff23fSmrg    else
1881209ff23fSmrg	tmp |= (0x180 << RADEON_DAC_FORCE_DATA_SHIFT);
1882209ff23fSmrg
1883209ff23fSmrg    OUTREG(RADEON_DAC_EXT_CNTL, tmp);
1884209ff23fSmrg
1885209ff23fSmrg    tmp = dac_cntl2 | RADEON_DAC2_DAC2_CLK_SEL | RADEON_DAC2_CMP_EN;
1886209ff23fSmrg    OUTREG(RADEON_DAC_CNTL2, tmp);
1887209ff23fSmrg
1888209ff23fSmrg    usleep(10000);
1889209ff23fSmrg
1890209ff23fSmrg    if (IS_R300_VARIANT) {
1891209ff23fSmrg	if (INREG(RADEON_DAC_CNTL2) & RADEON_DAC2_CMP_OUT_B) {
1892209ff23fSmrg	    found = MT_CRT;
1893209ff23fSmrg	    xf86DrvMsg (pScrn->scrnIndex, X_INFO,
1894209ff23fSmrg			"Found %s CRT connected to TV DAC\n",
1895209ff23fSmrg			color ? "color" : "bw");
1896209ff23fSmrg	}
1897209ff23fSmrg    } else {
1898209ff23fSmrg	if (INREG(RADEON_DAC_CNTL2) & RADEON_DAC2_CMP_OUTPUT) {
1899209ff23fSmrg	    found = MT_CRT;
1900209ff23fSmrg	    xf86DrvMsg (pScrn->scrnIndex, X_INFO,
1901209ff23fSmrg			"Found %s CRT connected to TV DAC\n",
1902209ff23fSmrg			color ? "color" : "bw");
1903209ff23fSmrg	}
1904209ff23fSmrg    }
1905209ff23fSmrg
1906209ff23fSmrg    /* restore regs we used */
1907209ff23fSmrg    OUTREG(RADEON_DAC_CNTL2, dac_cntl2);
1908209ff23fSmrg    OUTREG(RADEON_DAC_EXT_CNTL, dac_ext_cntl);
1909209ff23fSmrg    OUTREG(RADEON_TV_DAC_CNTL, tv_dac_cntl);
1910209ff23fSmrg    OUTREG(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
1911209ff23fSmrg
1912209ff23fSmrg    if (IS_R300_VARIANT) {
1913209ff23fSmrg	OUTREG(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl);
1914209ff23fSmrg	OUTREGP(RADEON_GPIOPAD_A, gpiopad_a, ~1 );
1915209ff23fSmrg    } else {
1916209ff23fSmrg	OUTREG(RADEON_DISP_HW_DEBUG, disp_hw_debug);
1917209ff23fSmrg    }
1918209ff23fSmrg    OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, pixclks_cntl);
1919209ff23fSmrg
1920209ff23fSmrg    return found;
1921209ff23fSmrg}
1922209ff23fSmrg
1923209ff23fSmrgstatic RADEONMonitorType
1924209ff23fSmrgr300_detect_tv(ScrnInfoPtr pScrn)
1925209ff23fSmrg{
1926209ff23fSmrg    RADEONInfoPtr info = RADEONPTR(pScrn);
1927209ff23fSmrg    unsigned char *RADEONMMIO = info->MMIO;
1928209ff23fSmrg    uint32_t tmp, dac_cntl2, crtc2_gen_cntl, dac_ext_cntl, tv_dac_cntl;
1929209ff23fSmrg    uint32_t gpiopad_a, disp_output_cntl;
1930209ff23fSmrg    RADEONMonitorType found = MT_NONE;
1931209ff23fSmrg
1932209ff23fSmrg    /* save the regs we need */
1933209ff23fSmrg    gpiopad_a = INREG(RADEON_GPIOPAD_A);
1934209ff23fSmrg    dac_cntl2 = INREG(RADEON_DAC_CNTL2);
1935209ff23fSmrg    crtc2_gen_cntl = INREG(RADEON_CRTC2_GEN_CNTL);
1936209ff23fSmrg    dac_ext_cntl = INREG(RADEON_DAC_EXT_CNTL);
1937209ff23fSmrg    tv_dac_cntl = INREG(RADEON_TV_DAC_CNTL);
1938209ff23fSmrg    disp_output_cntl = INREG(RADEON_DISP_OUTPUT_CNTL);
1939209ff23fSmrg
1940209ff23fSmrg    OUTREGP(RADEON_GPIOPAD_A, 0, ~1 );
1941209ff23fSmrg
1942209ff23fSmrg    OUTREG(RADEON_DAC_CNTL2, RADEON_DAC2_DAC2_CLK_SEL );
1943209ff23fSmrg
1944209ff23fSmrg    OUTREG(RADEON_CRTC2_GEN_CNTL,
1945209ff23fSmrg	   RADEON_CRTC2_CRT2_ON | RADEON_CRTC2_VSYNC_TRISTAT );
1946209ff23fSmrg
1947209ff23fSmrg    tmp = disp_output_cntl & ~RADEON_DISP_TVDAC_SOURCE_MASK;
1948209ff23fSmrg    tmp |= RADEON_DISP_TVDAC_SOURCE_CRTC2;
1949209ff23fSmrg    OUTREG(RADEON_DISP_OUTPUT_CNTL, tmp);
1950209ff23fSmrg
1951209ff23fSmrg    OUTREG(RADEON_DAC_EXT_CNTL,
1952209ff23fSmrg	   RADEON_DAC2_FORCE_BLANK_OFF_EN |
1953209ff23fSmrg	   RADEON_DAC2_FORCE_DATA_EN |
1954209ff23fSmrg	   RADEON_DAC_FORCE_DATA_SEL_RGB |
1955209ff23fSmrg	   (0xec << RADEON_DAC_FORCE_DATA_SHIFT ));
1956209ff23fSmrg
1957209ff23fSmrg    OUTREG(RADEON_TV_DAC_CNTL,
1958209ff23fSmrg	   RADEON_TV_DAC_STD_NTSC |
1959209ff23fSmrg	   (8 << RADEON_TV_DAC_BGADJ_SHIFT) |
1960209ff23fSmrg	   (6 << RADEON_TV_DAC_DACADJ_SHIFT ));
1961209ff23fSmrg
1962209ff23fSmrg    INREG(RADEON_TV_DAC_CNTL);
1963209ff23fSmrg
1964209ff23fSmrg    usleep(4000);
1965209ff23fSmrg
1966209ff23fSmrg    OUTREG(RADEON_TV_DAC_CNTL,
1967209ff23fSmrg	   RADEON_TV_DAC_NBLANK |
1968209ff23fSmrg	   RADEON_TV_DAC_NHOLD |
1969209ff23fSmrg	   RADEON_TV_MONITOR_DETECT_EN |
1970209ff23fSmrg	   RADEON_TV_DAC_STD_NTSC |
1971209ff23fSmrg	   (8 << RADEON_TV_DAC_BGADJ_SHIFT) |
1972209ff23fSmrg	   (6 << RADEON_TV_DAC_DACADJ_SHIFT ));
1973209ff23fSmrg
1974209ff23fSmrg    INREG(RADEON_TV_DAC_CNTL);
1975209ff23fSmrg
1976209ff23fSmrg    usleep(6000);
1977209ff23fSmrg
1978209ff23fSmrg    tmp = INREG(RADEON_TV_DAC_CNTL);
1979209ff23fSmrg    if ( (tmp & RADEON_TV_DAC_GDACDET) != 0 ) {
1980209ff23fSmrg	found = MT_STV;
1981209ff23fSmrg	xf86DrvMsg (pScrn->scrnIndex, X_INFO,
1982209ff23fSmrg		    "S-Video TV connection detected\n");
1983209ff23fSmrg    } else if ( (tmp & RADEON_TV_DAC_BDACDET) != 0 ) {
1984209ff23fSmrg	found = MT_CTV;
1985209ff23fSmrg	xf86DrvMsg (pScrn->scrnIndex, X_INFO,
1986209ff23fSmrg		    "Composite TV connection detected\n" );
1987209ff23fSmrg    }
1988209ff23fSmrg
1989209ff23fSmrg    OUTREG(RADEON_TV_DAC_CNTL, tv_dac_cntl );
1990209ff23fSmrg    OUTREG(RADEON_DAC_EXT_CNTL, dac_ext_cntl);
1991209ff23fSmrg    OUTREG(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
1992209ff23fSmrg    OUTREG(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl);
1993209ff23fSmrg    OUTREG(RADEON_DAC_CNTL2, dac_cntl2);
1994209ff23fSmrg    OUTREGP(RADEON_GPIOPAD_A, gpiopad_a, ~1);
1995209ff23fSmrg
1996209ff23fSmrg    return found;
1997209ff23fSmrg}
1998209ff23fSmrg
1999209ff23fSmrgstatic RADEONMonitorType
2000209ff23fSmrgradeon_detect_tv(ScrnInfoPtr pScrn)
2001209ff23fSmrg{
2002209ff23fSmrg    RADEONInfoPtr info = RADEONPTR(pScrn);
2003209ff23fSmrg    unsigned char *RADEONMMIO = info->MMIO;
2004209ff23fSmrg    uint32_t tmp, dac_cntl2, tv_master_cntl;
2005209ff23fSmrg    uint32_t tv_dac_cntl, tv_pre_dac_mux_cntl, config_cntl;
2006209ff23fSmrg    RADEONMonitorType found = MT_NONE;
2007209ff23fSmrg
2008209ff23fSmrg    if (IS_R300_VARIANT)
2009209ff23fSmrg	return r300_detect_tv(pScrn);
2010209ff23fSmrg
2011209ff23fSmrg    /* save the regs we need */
2012209ff23fSmrg    dac_cntl2 = INREG(RADEON_DAC_CNTL2);
2013209ff23fSmrg    tv_master_cntl = INREG(RADEON_TV_MASTER_CNTL);
2014209ff23fSmrg    tv_dac_cntl = INREG(RADEON_TV_DAC_CNTL);
2015209ff23fSmrg    config_cntl = INREG(RADEON_CONFIG_CNTL);
2016209ff23fSmrg    tv_pre_dac_mux_cntl = INREG(RADEON_TV_PRE_DAC_MUX_CNTL);
2017209ff23fSmrg
2018209ff23fSmrg    tmp = dac_cntl2 & ~RADEON_DAC2_DAC2_CLK_SEL;
2019209ff23fSmrg    OUTREG(RADEON_DAC_CNTL2, tmp);
2020209ff23fSmrg
2021209ff23fSmrg    tmp = tv_master_cntl | RADEON_TV_ON;
2022209ff23fSmrg    tmp &= ~(RADEON_TV_ASYNC_RST |
2023209ff23fSmrg	     RADEON_RESTART_PHASE_FIX |
2024209ff23fSmrg	     RADEON_CRT_FIFO_CE_EN |
2025209ff23fSmrg	     RADEON_TV_FIFO_CE_EN |
2026209ff23fSmrg	     RADEON_RE_SYNC_NOW_SEL_MASK);
2027209ff23fSmrg    tmp |= RADEON_TV_FIFO_ASYNC_RST | RADEON_CRT_ASYNC_RST;
2028209ff23fSmrg
2029209ff23fSmrg    OUTREG(RADEON_TV_MASTER_CNTL, tmp);
2030209ff23fSmrg
2031209ff23fSmrg    tmp = RADEON_TV_DAC_NBLANK | RADEON_TV_DAC_NHOLD |
2032209ff23fSmrg	RADEON_TV_MONITOR_DETECT_EN | RADEON_TV_DAC_STD_NTSC |
2033209ff23fSmrg	(8 << RADEON_TV_DAC_BGADJ_SHIFT);
2034209ff23fSmrg
2035209ff23fSmrg    if (config_cntl & RADEON_CFG_ATI_REV_ID_MASK)
2036209ff23fSmrg	tmp |= (4 << RADEON_TV_DAC_DACADJ_SHIFT);
2037209ff23fSmrg    else
2038209ff23fSmrg	tmp |= (8 << RADEON_TV_DAC_DACADJ_SHIFT);
2039209ff23fSmrg
2040209ff23fSmrg    OUTREG(RADEON_TV_DAC_CNTL, tmp);
2041209ff23fSmrg
2042209ff23fSmrg    tmp = RADEON_C_GRN_EN | RADEON_CMP_BLU_EN |
2043209ff23fSmrg	RADEON_RED_MX_FORCE_DAC_DATA |
2044209ff23fSmrg	RADEON_GRN_MX_FORCE_DAC_DATA |
2045209ff23fSmrg	RADEON_BLU_MX_FORCE_DAC_DATA |
2046209ff23fSmrg	(0x109 << RADEON_TV_FORCE_DAC_DATA_SHIFT);
2047209ff23fSmrg
2048209ff23fSmrg    OUTREG(RADEON_TV_PRE_DAC_MUX_CNTL, tmp);
2049209ff23fSmrg
2050209ff23fSmrg    usleep(3000);
2051209ff23fSmrg
2052209ff23fSmrg    tmp = INREG(RADEON_TV_DAC_CNTL);
2053209ff23fSmrg    if (tmp & RADEON_TV_DAC_GDACDET) {
2054209ff23fSmrg	found = MT_STV;
2055209ff23fSmrg	xf86DrvMsg (pScrn->scrnIndex, X_INFO,
2056209ff23fSmrg		    "S-Video TV connection detected\n");
2057209ff23fSmrg    } else if (tmp & RADEON_TV_DAC_BDACDET) {
2058209ff23fSmrg	found = MT_CTV;
2059209ff23fSmrg	xf86DrvMsg (pScrn->scrnIndex, X_INFO,
2060209ff23fSmrg		    "Composite TV connection detected\n" );
2061209ff23fSmrg    }
2062209ff23fSmrg
2063209ff23fSmrg    OUTREG(RADEON_TV_PRE_DAC_MUX_CNTL, tv_pre_dac_mux_cntl);
2064209ff23fSmrg    OUTREG(RADEON_TV_DAC_CNTL, tv_dac_cntl);
2065209ff23fSmrg    OUTREG(RADEON_TV_MASTER_CNTL, tv_master_cntl);
2066209ff23fSmrg    OUTREG(RADEON_DAC_CNTL2, dac_cntl2);
2067209ff23fSmrg
2068209ff23fSmrg    return found;
2069209ff23fSmrg}
2070