radeon_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
51b7e1c893Smrgconst char *encoder_name[34] = {
52b7e1c893Smrg    "NONE",
53b7e1c893Smrg    "INTERNAL_LVDS",
54b7e1c893Smrg    "INTERNAL_TMDS1",
55b7e1c893Smrg    "INTERNAL_TMDS2",
56b7e1c893Smrg    "INTERNAL_DAC1",
57b7e1c893Smrg    "INTERNAL_DAC2",
58b7e1c893Smrg    "INTERNAL_SDVOA",
59b7e1c893Smrg    "INTERNAL_SDVOB",
60b7e1c893Smrg    "SI170B",
61b7e1c893Smrg    "CH7303",
62b7e1c893Smrg    "CH7301",
63b7e1c893Smrg    "INTERNAL_DVO1",
64b7e1c893Smrg    "EXTERNAL_SDVOA",
65b7e1c893Smrg    "EXTERNAL_SDVOB",
66b7e1c893Smrg    "TITFP513",
67b7e1c893Smrg    "INTERNAL_LVTM1",
68b7e1c893Smrg    "VT1623",
69b7e1c893Smrg    "HDMI_SI1930",
70b7e1c893Smrg    "HDMI_INTERNAL",
71b7e1c893Smrg    "INTERNAL_KLDSCP_TMDS1",
72b7e1c893Smrg    "INTERNAL_KLDSCP_DVO1",
73b7e1c893Smrg    "INTERNAL_KLDSCP_DAC1",
74b7e1c893Smrg    "INTERNAL_KLDSCP_DAC2",
75b7e1c893Smrg    "SI178",
76b7e1c893Smrg    "MVPU_FPGA",
77b7e1c893Smrg    "INTERNAL_DDI",
78b7e1c893Smrg    "VT1625",
79b7e1c893Smrg    "HDMI_SI1932",
80b7e1c893Smrg    "DP_AN9801",
81b7e1c893Smrg    "DP_DP501",
82b7e1c893Smrg    "INTERNAL_UNIPHY",
83b7e1c893Smrg    "INTERNAL_KLDSCP_LVTMA",
84b7e1c893Smrg    "INTERNAL_UNIPHY1",
85b7e1c893Smrg    "INTERNAL_UNIPHY2",
86209ff23fSmrg};
87209ff23fSmrg
88209ff23fSmrgconst char *ConnectorTypeName[17] = {
89209ff23fSmrg  "None",
90209ff23fSmrg  "VGA",
91209ff23fSmrg  "DVI-I",
92209ff23fSmrg  "DVI-D",
93209ff23fSmrg  "DVI-A",
94b7e1c893Smrg  "S-video",
95b7e1c893Smrg  "Composite",
96209ff23fSmrg  "LVDS",
97209ff23fSmrg  "Digital",
98209ff23fSmrg  "SCART",
99209ff23fSmrg  "HDMI-A",
100209ff23fSmrg  "HDMI-B",
101209ff23fSmrg  "Unsupported",
102209ff23fSmrg  "Unsupported",
103209ff23fSmrg  "DIN",
104209ff23fSmrg  "DisplayPort",
105209ff23fSmrg  "Unsupported"
106209ff23fSmrg};
107209ff23fSmrg
108209ff23fSmrgextern void atombios_output_mode_set(xf86OutputPtr output,
109209ff23fSmrg				     DisplayModePtr mode,
110209ff23fSmrg				     DisplayModePtr adjusted_mode);
111209ff23fSmrgextern void atombios_output_dpms(xf86OutputPtr output, int mode);
112b7e1c893Smrgextern RADEONMonitorType atombios_dac_detect(xf86OutputPtr output);
113b7e1c893Smrgextern AtomBiosResult
114b7e1c893Smrgatombios_lock_crtc(atomBiosHandlePtr atomBIOS, int crtc, int lock);
115209ff23fSmrgstatic void
116209ff23fSmrgradeon_bios_output_dpms(xf86OutputPtr output, int mode);
117209ff23fSmrgstatic void
118209ff23fSmrgradeon_bios_output_crtc(xf86OutputPtr output);
119209ff23fSmrgstatic void
120209ff23fSmrgradeon_bios_output_lock(xf86OutputPtr output, Bool lock);
121209ff23fSmrg
122209ff23fSmrgvoid RADEONPrintPortMap(ScrnInfoPtr pScrn)
123209ff23fSmrg{
124b7e1c893Smrg    RADEONInfoPtr info = RADEONPTR(pScrn);
125209ff23fSmrg    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
126209ff23fSmrg    RADEONOutputPrivatePtr radeon_output;
127209ff23fSmrg    xf86OutputPtr output;
128209ff23fSmrg    int o;
129209ff23fSmrg
130209ff23fSmrg    for (o = 0; o < xf86_config->num_output; o++) {
131209ff23fSmrg	output = xf86_config->output[o];
132209ff23fSmrg	radeon_output = output->driver_private;
133209ff23fSmrg
134b7e1c893Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Port%d:\n", o);
135b7e1c893Smrg	ErrorF("  XRANDR name: %s\n", output->name);
136b7e1c893Smrg	ErrorF("  Connector: %s\n", ConnectorTypeName[radeon_output->ConnectorType]);
137b7e1c893Smrg	if (radeon_output->devices & ATOM_DEVICE_CRT1_SUPPORT)
138b7e1c893Smrg	    ErrorF("  CRT1: %s\n", encoder_name[info->encoders[ATOM_DEVICE_CRT1_INDEX]->encoder_id]);
139b7e1c893Smrg	if (radeon_output->devices & ATOM_DEVICE_CRT2_SUPPORT)
140b7e1c893Smrg	    ErrorF("  CRT2: %s\n", encoder_name[info->encoders[ATOM_DEVICE_CRT2_INDEX]->encoder_id]);
141b7e1c893Smrg	if (radeon_output->devices & ATOM_DEVICE_LCD1_SUPPORT)
142b7e1c893Smrg	    ErrorF("  LCD1: %s\n", encoder_name[info->encoders[ATOM_DEVICE_LCD1_INDEX]->encoder_id]);
143b7e1c893Smrg	if (radeon_output->devices & ATOM_DEVICE_DFP1_SUPPORT)
144b7e1c893Smrg	    ErrorF("  DFP1: %s\n", encoder_name[info->encoders[ATOM_DEVICE_DFP1_INDEX]->encoder_id]);
145b7e1c893Smrg	if (radeon_output->devices & ATOM_DEVICE_DFP2_SUPPORT)
146b7e1c893Smrg	    ErrorF("  DFP2: %s\n", encoder_name[info->encoders[ATOM_DEVICE_DFP2_INDEX]->encoder_id]);
147b7e1c893Smrg	if (radeon_output->devices & ATOM_DEVICE_DFP3_SUPPORT)
148b7e1c893Smrg	    ErrorF("  DFP3: %s\n", encoder_name[info->encoders[ATOM_DEVICE_DFP3_INDEX]->encoder_id]);
149b7e1c893Smrg	if (radeon_output->devices & ATOM_DEVICE_DFP4_SUPPORT)
150b7e1c893Smrg	    ErrorF("  DFP4: %s\n", encoder_name[info->encoders[ATOM_DEVICE_DFP4_INDEX]->encoder_id]);
151b7e1c893Smrg	if (radeon_output->devices & ATOM_DEVICE_DFP5_SUPPORT)
152b7e1c893Smrg	    ErrorF("  DFP5: %s\n", encoder_name[info->encoders[ATOM_DEVICE_DFP5_INDEX]->encoder_id]);
153b7e1c893Smrg	if (radeon_output->devices & ATOM_DEVICE_TV1_SUPPORT)
154b7e1c893Smrg	    ErrorF("  TV1: %s\n", encoder_name[info->encoders[ATOM_DEVICE_TV1_INDEX]->encoder_id]);
155b7e1c893Smrg	if (radeon_output->devices & ATOM_DEVICE_CV_SUPPORT)
156b7e1c893Smrg	    ErrorF("  CV: %s\n", encoder_name[info->encoders[ATOM_DEVICE_CRT1_INDEX]->encoder_id]);
157b7e1c893Smrg	ErrorF("  DDC reg: 0x%x\n",(unsigned int)radeon_output->ddc_i2c.mask_clk_reg);
158209ff23fSmrg    }
159209ff23fSmrg
160209ff23fSmrg}
161209ff23fSmrg
162b7e1c893Smrgstatic void
163b7e1c893Smrgradeon_set_active_device(xf86OutputPtr output)
164209ff23fSmrg{
165209ff23fSmrg    RADEONOutputPrivatePtr radeon_output = output->driver_private;
166209ff23fSmrg
167b7e1c893Smrg    radeon_output->active_device = 0;
168b7e1c893Smrg
169b7e1c893Smrg    switch (radeon_output->MonType) {
170b7e1c893Smrg    case MT_DP:
171b7e1c893Smrg    case MT_DFP:
172b7e1c893Smrg	if (radeon_output->devices & ATOM_DEVICE_DFP1_SUPPORT)
173b7e1c893Smrg	    radeon_output->active_device = ATOM_DEVICE_DFP1_SUPPORT;
174b7e1c893Smrg	else if (radeon_output->devices & ATOM_DEVICE_DFP2_SUPPORT)
175b7e1c893Smrg	    radeon_output->active_device = ATOM_DEVICE_DFP2_SUPPORT;
176b7e1c893Smrg	else if (radeon_output->devices & ATOM_DEVICE_DFP3_SUPPORT)
177b7e1c893Smrg	    radeon_output->active_device = ATOM_DEVICE_DFP3_SUPPORT;
178b7e1c893Smrg	else if (radeon_output->devices & ATOM_DEVICE_DFP4_SUPPORT)
179b7e1c893Smrg	    radeon_output->active_device = ATOM_DEVICE_DFP4_SUPPORT;
180b7e1c893Smrg	else if (radeon_output->devices & ATOM_DEVICE_DFP5_SUPPORT)
181b7e1c893Smrg	    radeon_output->active_device = ATOM_DEVICE_DFP5_SUPPORT;
182b7e1c893Smrg	break;
183b7e1c893Smrg    case MT_CRT:
184b7e1c893Smrg	if (radeon_output->devices & ATOM_DEVICE_CRT1_SUPPORT)
185b7e1c893Smrg	    radeon_output->active_device = ATOM_DEVICE_CRT1_SUPPORT;
186b7e1c893Smrg	else if (radeon_output->devices & ATOM_DEVICE_CRT2_SUPPORT)
187b7e1c893Smrg	    radeon_output->active_device = ATOM_DEVICE_CRT2_SUPPORT;
188b7e1c893Smrg	break;
189b7e1c893Smrg    case MT_LCD:
190b7e1c893Smrg	if (radeon_output->devices & ATOM_DEVICE_LCD1_SUPPORT)
191b7e1c893Smrg	    radeon_output->active_device = ATOM_DEVICE_LCD1_SUPPORT;
192b7e1c893Smrg	else if (radeon_output->devices & ATOM_DEVICE_LCD2_SUPPORT)
193b7e1c893Smrg	    radeon_output->active_device = ATOM_DEVICE_LCD2_SUPPORT;
194b7e1c893Smrg	break;
195b7e1c893Smrg    case MT_STV:
196b7e1c893Smrg    case MT_CTV:
197b7e1c893Smrg	if (radeon_output->devices & ATOM_DEVICE_TV1_SUPPORT)
198b7e1c893Smrg	    radeon_output->active_device = ATOM_DEVICE_TV1_SUPPORT;
199b7e1c893Smrg	else if (radeon_output->devices & ATOM_DEVICE_TV2_SUPPORT)
200b7e1c893Smrg	    radeon_output->active_device = ATOM_DEVICE_TV2_SUPPORT;
201b7e1c893Smrg	break;
202b7e1c893Smrg    case MT_CV:
203b7e1c893Smrg	if (radeon_output->devices & ATOM_DEVICE_CV_SUPPORT)
204b7e1c893Smrg	    radeon_output->active_device = ATOM_DEVICE_CV_SUPPORT;
205b7e1c893Smrg	break;
206b7e1c893Smrg    default:
207b7e1c893Smrg	ErrorF("Unhandled monitor type %d\n", radeon_output->MonType);
208b7e1c893Smrg	radeon_output->active_device = 0;
209209ff23fSmrg    }
210209ff23fSmrg}
211209ff23fSmrg
212209ff23fSmrgstatic RADEONMonitorType
213209ff23fSmrgradeon_ddc_connected(xf86OutputPtr output)
214209ff23fSmrg{
215209ff23fSmrg    ScrnInfoPtr pScrn        = output->scrn;
216209ff23fSmrg    RADEONInfoPtr info = RADEONPTR(pScrn);
217209ff23fSmrg    RADEONMonitorType MonType = MT_NONE;
218209ff23fSmrg    xf86MonPtr MonInfo = NULL;
219209ff23fSmrg    RADEONOutputPrivatePtr radeon_output = output->driver_private;
220209ff23fSmrg
221b7e1c893Smrg    if (radeon_output->pI2CBus) {
222c503f109Smrg	if (info->get_hardcoded_edid_from_bios)
223b7e1c893Smrg	    MonInfo = RADEONGetHardCodedEDIDFromBIOS(output);
224c503f109Smrg	if (MonInfo == NULL) {
225c503f109Smrg	    RADEONI2CDoLock(output, radeon_output->pI2CBus, TRUE);
226b7e1c893Smrg	    MonInfo = xf86OutputGetEDID(output, radeon_output->pI2CBus);
227c503f109Smrg	    RADEONI2CDoLock(output, radeon_output->pI2CBus, FALSE);
228b7e1c893Smrg	}
229b7e1c893Smrg    }
230209ff23fSmrg    if (MonInfo) {
231b7e1c893Smrg	switch (radeon_output->ConnectorType) {
232b7e1c893Smrg	case CONNECTOR_LVDS:
233209ff23fSmrg	    MonType = MT_LCD;
234b7e1c893Smrg	    break;
235b7e1c893Smrg	case CONNECTOR_DVI_D:
236b7e1c893Smrg	case CONNECTOR_HDMI_TYPE_A:
237b7e1c893Smrg	case CONNECTOR_HDMI_TYPE_B:
238b7e1c893Smrg	    if (radeon_output->shared_ddc) {
239b7e1c893Smrg		if (MonInfo->rawData[0x14] & 0x80) /* if it's digital and DVI/HDMI/etc. */
240b7e1c893Smrg		    MonType = MT_DFP;
241b7e1c893Smrg		else
242b7e1c893Smrg		    MonType = MT_NONE;
243b7e1c893Smrg	    } else
244b7e1c893Smrg		MonType = MT_DFP;
245b7e1c893Smrg	    break;
246b7e1c893Smrg	case CONNECTOR_DISPLAY_PORT:
247b7e1c893Smrg	    /*
248b7e1c893Smrg	     * XXX wrong. need to infer based on whether we got DDC from I2C
249b7e1c893Smrg	     * or AUXCH.
250b7e1c893Smrg	     */
251209ff23fSmrg	    MonType = MT_DFP;
252b7e1c893Smrg	case CONNECTOR_DVI_I:
253b7e1c893Smrg	    if (MonInfo->rawData[0x14] & 0x80) /* if it's digital and DVI */
254b7e1c893Smrg		MonType = MT_DFP;
255b7e1c893Smrg	    else
256b7e1c893Smrg		MonType = MT_CRT;
257b7e1c893Smrg	    break;
258b7e1c893Smrg	case CONNECTOR_VGA:
259b7e1c893Smrg	case CONNECTOR_DVI_A:
260b7e1c893Smrg	default:
261b7e1c893Smrg	    if (radeon_output->shared_ddc) {
262b7e1c893Smrg		if (MonInfo->rawData[0x14] & 0x80) /* if it's digital and VGA */
263b7e1c893Smrg		    MonType = MT_NONE;
264b7e1c893Smrg		else
265b7e1c893Smrg		    MonType = MT_CRT;
266b7e1c893Smrg	    } else
267b7e1c893Smrg		MonType = MT_CRT;
268b7e1c893Smrg	    break;
269b7e1c893Smrg	}
270b7e1c893Smrg
271b7e1c893Smrg	if (MonType != MT_NONE)
272b7e1c893Smrg	    if (!xf86ReturnOptValBool(info->Options, OPTION_IGNORE_EDID, FALSE))
273b7e1c893Smrg		xf86OutputSetEDID(output, MonInfo);
274209ff23fSmrg    } else
275209ff23fSmrg	MonType = MT_NONE;
276b7e1c893Smrg
277209ff23fSmrg    return MonType;
278209ff23fSmrg}
279209ff23fSmrg
280209ff23fSmrg#ifndef __powerpc__
281209ff23fSmrg
282209ff23fSmrgstatic RADEONMonitorType
283209ff23fSmrgRADEONDetectLidStatus(ScrnInfoPtr pScrn)
284209ff23fSmrg{
285209ff23fSmrg    RADEONInfoPtr info = RADEONPTR(pScrn);
286209ff23fSmrg    RADEONMonitorType MonType = MT_NONE;
287209ff23fSmrg#ifdef __linux__
288209ff23fSmrg    char lidline[50];  /* 50 should be sufficient for our purposes */
289209ff23fSmrg    FILE *f = fopen ("/proc/acpi/button/lid/LID/state", "r");
290209ff23fSmrg
291209ff23fSmrg    if (f != NULL) {
292209ff23fSmrg	while (fgets(lidline, sizeof lidline, f)) {
293209ff23fSmrg	    if (!strncmp(lidline, "state:", strlen ("state:"))) {
294209ff23fSmrg		if (strstr(lidline, "open")) {
295209ff23fSmrg		    fclose(f);
296209ff23fSmrg		    ErrorF("proc lid open\n");
297209ff23fSmrg		    return MT_LCD;
298209ff23fSmrg		}
299209ff23fSmrg		else if (strstr(lidline, "closed")) {
300209ff23fSmrg		    fclose(f);
301209ff23fSmrg		    ErrorF("proc lid closed\n");
302209ff23fSmrg		    return MT_NONE;
303209ff23fSmrg		}
304209ff23fSmrg	    }
305209ff23fSmrg	}
306209ff23fSmrg	fclose(f);
307209ff23fSmrg    }
308209ff23fSmrg#endif
309209ff23fSmrg
310209ff23fSmrg    if (!info->IsAtomBios) {
311209ff23fSmrg	unsigned char *RADEONMMIO = info->MMIO;
312209ff23fSmrg
313209ff23fSmrg	/* see if the lid is closed -- only works at boot */
314209ff23fSmrg	if (INREG(RADEON_BIOS_6_SCRATCH) & 0x10)
315209ff23fSmrg	    MonType = MT_NONE;
316209ff23fSmrg	else
317209ff23fSmrg	    MonType = MT_LCD;
318209ff23fSmrg    } else
319209ff23fSmrg	MonType = MT_LCD;
320209ff23fSmrg
321209ff23fSmrg    return MonType;
322209ff23fSmrg}
323209ff23fSmrg
324209ff23fSmrg#endif /* __powerpc__ */
325209ff23fSmrg
326209ff23fSmrgstatic void
327209ff23fSmrgradeon_dpms(xf86OutputPtr output, int mode)
328209ff23fSmrg{
329209ff23fSmrg    RADEONInfoPtr info = RADEONPTR(output->scrn);
330209ff23fSmrg    RADEONOutputPrivatePtr radeon_output = output->driver_private;
331209ff23fSmrg
332209ff23fSmrg    if ((mode == DPMSModeOn) && radeon_output->enabled)
333209ff23fSmrg	return;
334209ff23fSmrg
335b7e1c893Smrg    if (IS_AVIVO_VARIANT || info->r4xx_atom) {
336209ff23fSmrg	atombios_output_dpms(output, mode);
337209ff23fSmrg    } else {
338209ff23fSmrg	legacy_output_dpms(output, mode);
339209ff23fSmrg    }
340209ff23fSmrg    radeon_bios_output_dpms(output, mode);
341209ff23fSmrg
342209ff23fSmrg    if (mode == DPMSModeOn)
343209ff23fSmrg	radeon_output->enabled = TRUE;
344209ff23fSmrg    else
345209ff23fSmrg	radeon_output->enabled = FALSE;
346209ff23fSmrg
347209ff23fSmrg}
348209ff23fSmrg
349209ff23fSmrgstatic void
350209ff23fSmrgradeon_save(xf86OutputPtr output)
351209ff23fSmrg{
352209ff23fSmrg
353209ff23fSmrg}
354209ff23fSmrg
355209ff23fSmrgstatic void
356209ff23fSmrgradeon_restore(xf86OutputPtr restore)
357209ff23fSmrg{
358209ff23fSmrg
359209ff23fSmrg}
360209ff23fSmrg
361209ff23fSmrgstatic int
362209ff23fSmrgradeon_mode_valid(xf86OutputPtr output, DisplayModePtr pMode)
363209ff23fSmrg{
364209ff23fSmrg    RADEONOutputPrivatePtr radeon_output = output->driver_private;
365b7e1c893Smrg    radeon_native_mode_ptr native_mode = &radeon_output->native_mode;
366209ff23fSmrg    ScrnInfoPtr pScrn = output->scrn;
367209ff23fSmrg    RADEONInfoPtr info = RADEONPTR(pScrn);
368209ff23fSmrg    RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
369209ff23fSmrg
370209ff23fSmrg    /*
371209ff23fSmrg     * RN50 has effective maximum mode bandwidth of about 300MiB/s.
372209ff23fSmrg     * XXX should really do this for all chips by properly computing
373209ff23fSmrg     * memory bandwidth and an overhead factor.
374209ff23fSmrg     */
375209ff23fSmrg    if (info->ChipFamily == CHIP_FAMILY_RV100 && !pRADEONEnt->HasCRTC2) {
376209ff23fSmrg	if (xf86ModeBandwidth(pMode, pScrn->bitsPerPixel) > 300)
377209ff23fSmrg	    return MODE_BANDWIDTH;
378209ff23fSmrg    }
379209ff23fSmrg
380b7e1c893Smrg    if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT)) {
381b7e1c893Smrg	if (IS_AVIVO_VARIANT)
382b7e1c893Smrg	    return MODE_OK;
383b7e1c893Smrg	else {
384b7e1c893Smrg	    /* FIXME: Update when more modes are added */
385209ff23fSmrg	    if (pMode->HDisplay == 800 && pMode->VDisplay == 600)
386209ff23fSmrg		return MODE_OK;
387209ff23fSmrg	    else
388209ff23fSmrg		return MODE_CLOCK_RANGE;
389209ff23fSmrg	}
390209ff23fSmrg    }
391209ff23fSmrg
392b7e1c893Smrg    /* single link DVI check */
393b7e1c893Smrg    if (pMode->Clock > 165000 && radeon_output->MonType == MT_DFP) {
394b7e1c893Smrg	/* DP->DVI converter */
395b7e1c893Smrg	if (radeon_output->ConnectorType == CONNECTOR_DISPLAY_PORT)
396b7e1c893Smrg	    return MODE_CLOCK_HIGH;
397b7e1c893Smrg
398b7e1c893Smrg	/* XXX some HDMI can do better than 165MHz on a link */
399b7e1c893Smrg	if (radeon_output->ConnectorType == CONNECTOR_HDMI_TYPE_A)
400b7e1c893Smrg	    return MODE_CLOCK_HIGH;
401b7e1c893Smrg
402b7e1c893Smrg	/* XXX some R300 and R400 can actually do this */
403b7e1c893Smrg	if (!IS_AVIVO_VARIANT)
404b7e1c893Smrg	    return MODE_CLOCK_HIGH;
405b7e1c893Smrg
406b7e1c893Smrg	/* XXX and some AVIVO can't */
407b7e1c893Smrg    }
408b7e1c893Smrg
409b7e1c893Smrg    if (radeon_output->active_device & (ATOM_DEVICE_LCD_SUPPORT)) {
410209ff23fSmrg	if (radeon_output->rmx_type == RMX_OFF) {
411b7e1c893Smrg	    if (pMode->HDisplay != native_mode->PanelXRes ||
412b7e1c893Smrg		pMode->VDisplay != native_mode->PanelYRes)
413209ff23fSmrg		return MODE_PANEL;
414209ff23fSmrg	}
415b7e1c893Smrg	if (pMode->HDisplay > native_mode->PanelXRes ||
416b7e1c893Smrg	    pMode->VDisplay > native_mode->PanelYRes)
417209ff23fSmrg	    return MODE_PANEL;
418209ff23fSmrg    }
419209ff23fSmrg
420209ff23fSmrg    return MODE_OK;
421209ff23fSmrg}
422209ff23fSmrg
423209ff23fSmrgstatic Bool
424209ff23fSmrgradeon_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
425209ff23fSmrg		    DisplayModePtr adjusted_mode)
426209ff23fSmrg{
427209ff23fSmrg    RADEONInfoPtr info = RADEONPTR(output->scrn);
428209ff23fSmrg    RADEONOutputPrivatePtr radeon_output = output->driver_private;
429b7e1c893Smrg    radeon_native_mode_ptr native_mode = &radeon_output->native_mode;
430209ff23fSmrg
431209ff23fSmrg    radeon_output->Flags &= ~RADEON_USE_RMX;
432209ff23fSmrg
433b7e1c893Smrg    /*
434b7e1c893Smrg     *  Refresh the Crtc values without INTERLACE_HALVE_V
435b7e1c893Smrg     *  Should we use output->scrn->adjustFlags like xf86RandRModeConvert() does?
436b7e1c893Smrg     */
437b7e1c893Smrg    xf86SetModeCrtc(adjusted_mode, 0);
438b7e1c893Smrg
439209ff23fSmrg    /* decide if we are using RMX */
440b7e1c893Smrg    if ((radeon_output->active_device & (ATOM_DEVICE_LCD_SUPPORT | ATOM_DEVICE_DFP_SUPPORT))
441209ff23fSmrg	&& radeon_output->rmx_type != RMX_OFF) {
442209ff23fSmrg	xf86CrtcPtr crtc = output->crtc;
443209ff23fSmrg	RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
444209ff23fSmrg
445209ff23fSmrg	if (IS_AVIVO_VARIANT || radeon_crtc->crtc_id == 0) {
446b7e1c893Smrg	    if (mode->HDisplay < native_mode->PanelXRes ||
447b7e1c893Smrg		mode->VDisplay < native_mode->PanelYRes) {
448209ff23fSmrg		radeon_output->Flags |= RADEON_USE_RMX;
449209ff23fSmrg		if (IS_AVIVO_VARIANT) {
450209ff23fSmrg		    /* set to the panel's native mode */
451b7e1c893Smrg		    adjusted_mode->HDisplay = native_mode->PanelXRes;
452b7e1c893Smrg		    adjusted_mode->VDisplay = native_mode->PanelYRes;
453b7e1c893Smrg		    adjusted_mode->HTotal = native_mode->PanelXRes + native_mode->HBlank;
454b7e1c893Smrg		    adjusted_mode->HSyncStart = native_mode->PanelXRes + native_mode->HOverPlus;
455b7e1c893Smrg		    adjusted_mode->HSyncEnd = adjusted_mode->HSyncStart + native_mode->HSyncWidth;
456b7e1c893Smrg		    adjusted_mode->VTotal = native_mode->PanelYRes + native_mode->VBlank;
457b7e1c893Smrg		    adjusted_mode->VSyncStart = native_mode->PanelYRes + native_mode->VOverPlus;
458b7e1c893Smrg		    adjusted_mode->VSyncEnd = adjusted_mode->VSyncStart + native_mode->VSyncWidth;
459209ff23fSmrg		    /* update crtc values */
460209ff23fSmrg		    xf86SetModeCrtc(adjusted_mode, INTERLACE_HALVE_V);
461209ff23fSmrg		    /* adjust crtc values */
462b7e1c893Smrg		    adjusted_mode->CrtcHDisplay = native_mode->PanelXRes;
463b7e1c893Smrg		    adjusted_mode->CrtcVDisplay = native_mode->PanelYRes;
464b7e1c893Smrg		    adjusted_mode->CrtcHTotal = adjusted_mode->CrtcHDisplay + native_mode->HBlank;
465b7e1c893Smrg		    adjusted_mode->CrtcHSyncStart = adjusted_mode->CrtcHDisplay + native_mode->HOverPlus;
466b7e1c893Smrg		    adjusted_mode->CrtcHSyncEnd = adjusted_mode->CrtcHSyncStart + native_mode->HSyncWidth;
467b7e1c893Smrg		    adjusted_mode->CrtcVTotal = adjusted_mode->CrtcVDisplay + native_mode->VBlank;
468b7e1c893Smrg		    adjusted_mode->CrtcVSyncStart = adjusted_mode->CrtcVDisplay + native_mode->VOverPlus;
469b7e1c893Smrg		    adjusted_mode->CrtcVSyncEnd = adjusted_mode->CrtcVSyncStart + native_mode->VSyncWidth;
470209ff23fSmrg		} else {
471209ff23fSmrg		    /* set to the panel's native mode */
472b7e1c893Smrg		    adjusted_mode->HTotal = native_mode->PanelXRes + native_mode->HBlank;
473b7e1c893Smrg		    adjusted_mode->HSyncStart = native_mode->PanelXRes + native_mode->HOverPlus;
474b7e1c893Smrg		    adjusted_mode->HSyncEnd = adjusted_mode->HSyncStart + native_mode->HSyncWidth;
475b7e1c893Smrg		    adjusted_mode->VTotal = native_mode->PanelYRes + native_mode->VBlank;
476b7e1c893Smrg		    adjusted_mode->VSyncStart = native_mode->PanelYRes + native_mode->VOverPlus;
477b7e1c893Smrg		    adjusted_mode->VSyncEnd = adjusted_mode->VSyncStart + native_mode->VSyncWidth;
478b7e1c893Smrg		    adjusted_mode->Clock = native_mode->DotClock;
479209ff23fSmrg		    /* update crtc values */
480209ff23fSmrg		    xf86SetModeCrtc(adjusted_mode, INTERLACE_HALVE_V);
481209ff23fSmrg		    /* adjust crtc values */
482b7e1c893Smrg		    adjusted_mode->CrtcHTotal = adjusted_mode->CrtcHDisplay + native_mode->HBlank;
483b7e1c893Smrg		    adjusted_mode->CrtcHSyncStart = adjusted_mode->CrtcHDisplay + native_mode->HOverPlus;
484b7e1c893Smrg		    adjusted_mode->CrtcHSyncEnd = adjusted_mode->CrtcHSyncStart + native_mode->HSyncWidth;
485b7e1c893Smrg		    adjusted_mode->CrtcVTotal = adjusted_mode->CrtcVDisplay + native_mode->VBlank;
486b7e1c893Smrg		    adjusted_mode->CrtcVSyncStart = adjusted_mode->CrtcVDisplay + native_mode->VOverPlus;
487b7e1c893Smrg		    adjusted_mode->CrtcVSyncEnd = adjusted_mode->CrtcVSyncStart + native_mode->VSyncWidth;
488209ff23fSmrg		}
489b7e1c893Smrg		adjusted_mode->Clock = native_mode->DotClock;
490b7e1c893Smrg		adjusted_mode->Flags = native_mode->Flags;
491209ff23fSmrg	    }
492209ff23fSmrg	}
493209ff23fSmrg    }
494209ff23fSmrg
495b7e1c893Smrg    if (IS_AVIVO_VARIANT) {
496b7e1c893Smrg	/* hw bug */
497b7e1c893Smrg	if ((mode->Flags & V_INTERLACE)
498b7e1c893Smrg	    && (adjusted_mode->CrtcVSyncStart < (adjusted_mode->CrtcVDisplay + 2)))
499b7e1c893Smrg	    adjusted_mode->CrtcVSyncStart = adjusted_mode->CrtcVDisplay + 2;
500b7e1c893Smrg    }
501b7e1c893Smrg
502209ff23fSmrg    return TRUE;
503209ff23fSmrg}
504209ff23fSmrg
505209ff23fSmrgstatic void
506209ff23fSmrgradeon_mode_prepare(xf86OutputPtr output)
507209ff23fSmrg{
508c503f109Smrg    RADEONInfoPtr info = RADEONPTR(output->scrn);
509c503f109Smrg    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR (output->scrn);
510c503f109Smrg    int o;
511c503f109Smrg
512c503f109Smrg    for (o = 0; o < config->num_output; o++) {
513c503f109Smrg	xf86OutputPtr loop_output = config->output[o];
514c503f109Smrg	if (loop_output == output)
515c503f109Smrg	    continue;
516c503f109Smrg	else if (loop_output->crtc) {
517c503f109Smrg	    xf86CrtcPtr other_crtc = loop_output->crtc;
518c503f109Smrg	    RADEONCrtcPrivatePtr other_radeon_crtc = other_crtc->driver_private;
519c503f109Smrg	    if (other_crtc->enabled) {
520c503f109Smrg		if (other_radeon_crtc->initialized) {
521c503f109Smrg		    radeon_crtc_dpms(other_crtc, DPMSModeOff);
522c503f109Smrg		    if (IS_AVIVO_VARIANT || info->r4xx_atom)
523c503f109Smrg			atombios_lock_crtc(info->atomBIOS, other_radeon_crtc->crtc_id, 1);
524c503f109Smrg		    radeon_dpms(loop_output, DPMSModeOff);
525c503f109Smrg		}
526c503f109Smrg	    }
527c503f109Smrg	}
528c503f109Smrg    }
529c503f109Smrg
530209ff23fSmrg    radeon_bios_output_lock(output, TRUE);
531209ff23fSmrg    radeon_dpms(output, DPMSModeOff);
532c503f109Smrg    radeon_crtc_dpms(output->crtc, DPMSModeOff);
533c503f109Smrg
534209ff23fSmrg}
535209ff23fSmrg
536209ff23fSmrgstatic void
537209ff23fSmrgradeon_mode_set(xf86OutputPtr output, DisplayModePtr mode,
538209ff23fSmrg		DisplayModePtr adjusted_mode)
539209ff23fSmrg{
540209ff23fSmrg    RADEONInfoPtr info = RADEONPTR(output->scrn);
541209ff23fSmrg
542b7e1c893Smrg    if (IS_AVIVO_VARIANT || info->r4xx_atom)
543209ff23fSmrg	atombios_output_mode_set(output, mode, adjusted_mode);
544209ff23fSmrg    else
545209ff23fSmrg	legacy_output_mode_set(output, mode, adjusted_mode);
546209ff23fSmrg    radeon_bios_output_crtc(output);
547209ff23fSmrg
548209ff23fSmrg}
549209ff23fSmrg
550209ff23fSmrgstatic void
551209ff23fSmrgradeon_mode_commit(xf86OutputPtr output)
552209ff23fSmrg{
553c503f109Smrg    RADEONInfoPtr info = RADEONPTR(output->scrn);
554c503f109Smrg    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR (output->scrn);
555c503f109Smrg    int o;
556c503f109Smrg
557c503f109Smrg    for (o = 0; o < config->num_output; o++) {
558c503f109Smrg	xf86OutputPtr loop_output = config->output[o];
559c503f109Smrg	if (loop_output == output)
560c503f109Smrg	    continue;
561c503f109Smrg	else if (loop_output->crtc) {
562c503f109Smrg	    xf86CrtcPtr other_crtc = loop_output->crtc;
563c503f109Smrg	    RADEONCrtcPrivatePtr other_radeon_crtc = other_crtc->driver_private;
564c503f109Smrg	    if (other_crtc->enabled) {
565c503f109Smrg		if (other_radeon_crtc->initialized) {
566c503f109Smrg		    radeon_crtc_dpms(other_crtc, DPMSModeOn);
567c503f109Smrg		    if (IS_AVIVO_VARIANT || info->r4xx_atom)
568c503f109Smrg			atombios_lock_crtc(info->atomBIOS, other_radeon_crtc->crtc_id, 0);
569c503f109Smrg		    radeon_dpms(loop_output, DPMSModeOn);
570c503f109Smrg		}
571c503f109Smrg	    }
572c503f109Smrg	}
573c503f109Smrg    }
574c503f109Smrg
575209ff23fSmrg    radeon_dpms(output, DPMSModeOn);
576c503f109Smrg    radeon_crtc_dpms(output->crtc, DPMSModeOn);
577209ff23fSmrg    radeon_bios_output_lock(output, FALSE);
578209ff23fSmrg}
579209ff23fSmrg
580209ff23fSmrgstatic void
581209ff23fSmrgradeon_bios_output_lock(xf86OutputPtr output, Bool lock)
582209ff23fSmrg{
583209ff23fSmrg    ScrnInfoPtr	    pScrn = output->scrn;
584209ff23fSmrg    RADEONInfoPtr info = RADEONPTR(pScrn);
585209ff23fSmrg    unsigned char *RADEONMMIO = info->MMIO;
586209ff23fSmrg    RADEONSavePtr save = info->ModeReg;
587209ff23fSmrg
588209ff23fSmrg    if (info->IsAtomBios) {
589209ff23fSmrg	if (lock) {
590209ff23fSmrg	    save->bios_6_scratch |= ATOM_S6_CRITICAL_STATE;
591209ff23fSmrg	} else {
592209ff23fSmrg	    save->bios_6_scratch &= ~ATOM_S6_CRITICAL_STATE;
593209ff23fSmrg	}
594209ff23fSmrg    } else {
595209ff23fSmrg	if (lock) {
596209ff23fSmrg	    save->bios_6_scratch |= RADEON_DRIVER_CRITICAL;
597209ff23fSmrg	} else {
598209ff23fSmrg	    save->bios_6_scratch &= ~RADEON_DRIVER_CRITICAL;
599209ff23fSmrg	}
600209ff23fSmrg    }
601209ff23fSmrg    if (info->ChipFamily >= CHIP_FAMILY_R600)
602209ff23fSmrg	OUTREG(R600_BIOS_6_SCRATCH, save->bios_6_scratch);
603209ff23fSmrg    else
604209ff23fSmrg	OUTREG(RADEON_BIOS_6_SCRATCH, save->bios_6_scratch);
605209ff23fSmrg}
606209ff23fSmrg
607209ff23fSmrgstatic void
608209ff23fSmrgradeon_bios_output_dpms(xf86OutputPtr output, int mode)
609209ff23fSmrg{
610209ff23fSmrg    ScrnInfoPtr	    pScrn = output->scrn;
611209ff23fSmrg    RADEONInfoPtr info = RADEONPTR(pScrn);
612209ff23fSmrg    RADEONOutputPrivatePtr radeon_output = output->driver_private;
613209ff23fSmrg    unsigned char *RADEONMMIO = info->MMIO;
614209ff23fSmrg    RADEONSavePtr save = info->ModeReg;
615209ff23fSmrg
616209ff23fSmrg    if (info->IsAtomBios) {
617b7e1c893Smrg	if (radeon_output->active_device & ATOM_DEVICE_TV1_SUPPORT) {
618b7e1c893Smrg	    if (mode == DPMSModeOn)
619b7e1c893Smrg		save->bios_2_scratch &= ~ATOM_S2_TV1_DPMS_STATE;
620b7e1c893Smrg	    else
621b7e1c893Smrg		save->bios_2_scratch |= ATOM_S2_TV1_DPMS_STATE;
622b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_CV_SUPPORT) {
623b7e1c893Smrg	    if (mode == DPMSModeOn)
624b7e1c893Smrg		save->bios_2_scratch &= ~ATOM_S2_CV_DPMS_STATE;
625b7e1c893Smrg	    else
626b7e1c893Smrg		save->bios_2_scratch |= ATOM_S2_CV_DPMS_STATE;
627b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_CRT1_SUPPORT) {
628b7e1c893Smrg	    if (mode == DPMSModeOn)
629b7e1c893Smrg		save->bios_2_scratch &= ~ATOM_S2_CRT1_DPMS_STATE;
630b7e1c893Smrg	    else
631b7e1c893Smrg		save->bios_2_scratch |= ATOM_S2_CRT1_DPMS_STATE;
632b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_CRT2_SUPPORT) {
633b7e1c893Smrg	    if (mode == DPMSModeOn)
634b7e1c893Smrg		save->bios_2_scratch &= ~ATOM_S2_CRT2_DPMS_STATE;
635b7e1c893Smrg	    else
636b7e1c893Smrg		save->bios_2_scratch |= ATOM_S2_CRT2_DPMS_STATE;
637b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_LCD1_SUPPORT) {
638b7e1c893Smrg	    if (mode == DPMSModeOn)
639b7e1c893Smrg		save->bios_2_scratch &= ~ATOM_S2_LCD1_DPMS_STATE;
640b7e1c893Smrg	    else
641b7e1c893Smrg		save->bios_2_scratch |= ATOM_S2_LCD1_DPMS_STATE;
642b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_DFP1_SUPPORT) {
643b7e1c893Smrg	    if (mode == DPMSModeOn)
644b7e1c893Smrg		save->bios_2_scratch &= ~ATOM_S2_DFP1_DPMS_STATE;
645b7e1c893Smrg	    else
646b7e1c893Smrg		save->bios_2_scratch |= ATOM_S2_DFP1_DPMS_STATE;
647b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_DFP2_SUPPORT) {
648b7e1c893Smrg	    if (mode == DPMSModeOn)
649b7e1c893Smrg		save->bios_2_scratch &= ~ATOM_S2_DFP2_DPMS_STATE;
650b7e1c893Smrg	    else
651b7e1c893Smrg		save->bios_2_scratch |= ATOM_S2_DFP2_DPMS_STATE;
652b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_DFP3_SUPPORT) {
653b7e1c893Smrg	    if (mode == DPMSModeOn)
654b7e1c893Smrg		save->bios_2_scratch &= ~ATOM_S2_DFP3_DPMS_STATE;
655b7e1c893Smrg	    else
656b7e1c893Smrg		save->bios_2_scratch |= ATOM_S2_DFP3_DPMS_STATE;
657b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_DFP4_SUPPORT) {
658b7e1c893Smrg	    if (mode == DPMSModeOn)
659b7e1c893Smrg		save->bios_2_scratch &= ~ATOM_S2_DFP4_DPMS_STATE;
660b7e1c893Smrg	    else
661b7e1c893Smrg		save->bios_2_scratch |= ATOM_S2_DFP4_DPMS_STATE;
662b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_DFP5_SUPPORT) {
663b7e1c893Smrg	    if (mode == DPMSModeOn)
664b7e1c893Smrg		save->bios_2_scratch &= ~ATOM_S2_DFP5_DPMS_STATE;
665b7e1c893Smrg	    else
666b7e1c893Smrg		save->bios_2_scratch |= ATOM_S2_DFP5_DPMS_STATE;
667209ff23fSmrg	}
668b7e1c893Smrg	if (info->ChipFamily >= CHIP_FAMILY_R600)
669209ff23fSmrg	    OUTREG(R600_BIOS_2_SCRATCH, save->bios_2_scratch);
670b7e1c893Smrg	else
671209ff23fSmrg	    OUTREG(RADEON_BIOS_2_SCRATCH, save->bios_2_scratch);
672209ff23fSmrg    } else {
673209ff23fSmrg	if (mode == DPMSModeOn) {
674209ff23fSmrg	    save->bios_6_scratch &= ~(RADEON_DPMS_MASK | RADEON_SCREEN_BLANKING);
675209ff23fSmrg	    save->bios_6_scratch |= RADEON_DPMS_ON;
676209ff23fSmrg	} else {
677209ff23fSmrg	    save->bios_6_scratch &= ~RADEON_DPMS_MASK;
678209ff23fSmrg	    save->bios_6_scratch |= (RADEON_DPMS_OFF | RADEON_SCREEN_BLANKING);
679b7e1c893Smrg	}
680b7e1c893Smrg	if (radeon_output->active_device & ATOM_DEVICE_TV1_SUPPORT) {
681b7e1c893Smrg	    if (mode == DPMSModeOn)
682b7e1c893Smrg		save->bios_6_scratch |= RADEON_TV_DPMS_ON;
683b7e1c893Smrg	    else
684209ff23fSmrg		save->bios_6_scratch &= ~RADEON_TV_DPMS_ON;
685b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_CRT1_SUPPORT) {
686b7e1c893Smrg	    if (mode == DPMSModeOn)
687b7e1c893Smrg		save->bios_6_scratch |= RADEON_CRT_DPMS_ON;
688b7e1c893Smrg	    else
689209ff23fSmrg		save->bios_6_scratch &= ~RADEON_CRT_DPMS_ON;
690b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_CRT2_SUPPORT) {
691b7e1c893Smrg	    if (mode == DPMSModeOn)
692b7e1c893Smrg		save->bios_6_scratch |= RADEON_CRT_DPMS_ON;
693b7e1c893Smrg	    else
694b7e1c893Smrg		save->bios_6_scratch &= ~RADEON_CRT_DPMS_ON;
695b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_LCD1_SUPPORT) {
696b7e1c893Smrg	    if (mode == DPMSModeOn)
697b7e1c893Smrg		save->bios_6_scratch |= RADEON_LCD_DPMS_ON;
698b7e1c893Smrg	    else
699209ff23fSmrg		save->bios_6_scratch &= ~RADEON_LCD_DPMS_ON;
700b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_DFP1_SUPPORT) {
701b7e1c893Smrg	    if (mode == DPMSModeOn)
702b7e1c893Smrg		save->bios_6_scratch |= RADEON_DFP_DPMS_ON;
703b7e1c893Smrg	    else
704b7e1c893Smrg		save->bios_6_scratch &= ~RADEON_DFP_DPMS_ON;
705b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_DFP2_SUPPORT) {
706b7e1c893Smrg	    if (mode == DPMSModeOn)
707b7e1c893Smrg		save->bios_6_scratch |= RADEON_DFP_DPMS_ON;
708b7e1c893Smrg	    else
709209ff23fSmrg		save->bios_6_scratch &= ~RADEON_DFP_DPMS_ON;
710209ff23fSmrg	}
711209ff23fSmrg	OUTREG(RADEON_BIOS_6_SCRATCH, save->bios_6_scratch);
712209ff23fSmrg    }
713209ff23fSmrg}
714209ff23fSmrg
715209ff23fSmrgstatic void
716209ff23fSmrgradeon_bios_output_crtc(xf86OutputPtr output)
717209ff23fSmrg{
718209ff23fSmrg    ScrnInfoPtr	    pScrn = output->scrn;
719209ff23fSmrg    RADEONInfoPtr info = RADEONPTR(pScrn);
720209ff23fSmrg    RADEONOutputPrivatePtr radeon_output = output->driver_private;
721209ff23fSmrg    unsigned char *RADEONMMIO = info->MMIO;
722209ff23fSmrg    RADEONSavePtr save = info->ModeReg;
723209ff23fSmrg    xf86CrtcPtr crtc = output->crtc;
724209ff23fSmrg    RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
725209ff23fSmrg
726209ff23fSmrg    if (info->IsAtomBios) {
727b7e1c893Smrg	if (radeon_output->active_device & ATOM_DEVICE_TV1_SUPPORT) {
728b7e1c893Smrg	    save->bios_3_scratch &= ~ATOM_S3_TV1_CRTC_ACTIVE;
729b7e1c893Smrg	    save->bios_3_scratch |= (radeon_crtc->crtc_id << 18);
730b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_CV_SUPPORT) {
731b7e1c893Smrg	    save->bios_3_scratch &= ~ATOM_S3_CV_CRTC_ACTIVE;
732b7e1c893Smrg	    save->bios_3_scratch |= (radeon_crtc->crtc_id << 24);
733b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_CRT1_SUPPORT) {
734b7e1c893Smrg	    save->bios_3_scratch &= ~ATOM_S3_CRT1_CRTC_ACTIVE;
735b7e1c893Smrg	    save->bios_3_scratch |= (radeon_crtc->crtc_id << 16);
736b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_CRT2_SUPPORT) {
737b7e1c893Smrg	    save->bios_3_scratch &= ~ATOM_S3_CRT2_CRTC_ACTIVE;
738b7e1c893Smrg	    save->bios_3_scratch |= (radeon_crtc->crtc_id << 20);
739b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_LCD1_SUPPORT) {
740b7e1c893Smrg	    save->bios_3_scratch &= ~ATOM_S3_LCD1_CRTC_ACTIVE;
741b7e1c893Smrg	    save->bios_3_scratch |= (radeon_crtc->crtc_id << 17);
742b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_DFP1_SUPPORT) {
743b7e1c893Smrg	    save->bios_3_scratch &= ~ATOM_S3_DFP1_CRTC_ACTIVE;
744b7e1c893Smrg	    save->bios_3_scratch |= (radeon_crtc->crtc_id << 19);
745b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_DFP2_SUPPORT) {
746b7e1c893Smrg	    save->bios_3_scratch &= ~ATOM_S3_DFP2_CRTC_ACTIVE;
747b7e1c893Smrg	    save->bios_3_scratch |= (radeon_crtc->crtc_id << 23);
748b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_DFP3_SUPPORT) {
749b7e1c893Smrg	    save->bios_3_scratch &= ~ATOM_S3_DFP3_CRTC_ACTIVE;
750b7e1c893Smrg	    save->bios_3_scratch |= (radeon_crtc->crtc_id << 25);
751209ff23fSmrg	}
752209ff23fSmrg	if (info->ChipFamily >= CHIP_FAMILY_R600)
753209ff23fSmrg	    OUTREG(R600_BIOS_3_SCRATCH, save->bios_3_scratch);
754209ff23fSmrg	else
755209ff23fSmrg	    OUTREG(RADEON_BIOS_3_SCRATCH, save->bios_3_scratch);
756209ff23fSmrg    } else {
757b7e1c893Smrg	if (radeon_output->active_device & ATOM_DEVICE_TV1_SUPPORT) {
758209ff23fSmrg	    save->bios_5_scratch &= ~RADEON_TV1_CRTC_MASK;
759209ff23fSmrg	    save->bios_5_scratch |= (radeon_crtc->crtc_id << RADEON_TV1_CRTC_SHIFT);
760b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_CRT1_SUPPORT) {
761b7e1c893Smrg	    save->bios_5_scratch &= ~RADEON_CRT1_CRTC_MASK;
762b7e1c893Smrg	    save->bios_5_scratch |= (radeon_crtc->crtc_id << RADEON_CRT1_CRTC_SHIFT);
763b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_CRT2_SUPPORT) {
764b7e1c893Smrg	    save->bios_5_scratch &= ~RADEON_CRT2_CRTC_MASK;
765b7e1c893Smrg	    save->bios_5_scratch |= (radeon_crtc->crtc_id << RADEON_CRT2_CRTC_SHIFT);
766b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_LCD1_SUPPORT) {
767209ff23fSmrg	    save->bios_5_scratch &= ~RADEON_LCD1_CRTC_MASK;
768209ff23fSmrg	    save->bios_5_scratch |= (radeon_crtc->crtc_id << RADEON_LCD1_CRTC_SHIFT);
769b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_DFP1_SUPPORT) {
770b7e1c893Smrg	    save->bios_5_scratch &= ~RADEON_DFP1_CRTC_MASK;
771b7e1c893Smrg	    save->bios_5_scratch |= (radeon_crtc->crtc_id << RADEON_DFP1_CRTC_SHIFT);
772b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_DFP2_SUPPORT) {
773b7e1c893Smrg	    save->bios_5_scratch &= ~RADEON_DFP2_CRTC_MASK;
774b7e1c893Smrg	    save->bios_5_scratch |= (radeon_crtc->crtc_id << RADEON_DFP2_CRTC_SHIFT);
775209ff23fSmrg	}
776209ff23fSmrg	OUTREG(RADEON_BIOS_5_SCRATCH, save->bios_5_scratch);
777209ff23fSmrg    }
778209ff23fSmrg}
779209ff23fSmrg
780209ff23fSmrgstatic void
781209ff23fSmrgradeon_bios_output_connected(xf86OutputPtr output, Bool connected)
782209ff23fSmrg{
783209ff23fSmrg    ScrnInfoPtr	    pScrn = output->scrn;
784209ff23fSmrg    RADEONInfoPtr info = RADEONPTR(pScrn);
785209ff23fSmrg    RADEONOutputPrivatePtr radeon_output = output->driver_private;
786209ff23fSmrg    unsigned char *RADEONMMIO = info->MMIO;
787209ff23fSmrg    RADEONSavePtr save = info->ModeReg;
788209ff23fSmrg
789209ff23fSmrg    if (info->IsAtomBios) {
790b7e1c893Smrg	switch (radeon_output->active_device) {
791b7e1c893Smrg	case ATOM_DEVICE_TV1_SUPPORT:
792b7e1c893Smrg	    if (connected)
793b7e1c893Smrg		save->bios_3_scratch |= ATOM_S3_TV1_ACTIVE;
794b7e1c893Smrg	    else {
795b7e1c893Smrg		save->bios_0_scratch &= ~ATOM_S0_TV1_MASK;
796b7e1c893Smrg		save->bios_3_scratch &= ~ATOM_S3_TV1_ACTIVE;
797209ff23fSmrg	    }
798b7e1c893Smrg	    break;
799b7e1c893Smrg	case ATOM_DEVICE_CV_SUPPORT:
800b7e1c893Smrg	    if (connected)
801b7e1c893Smrg		save->bios_3_scratch |= ATOM_S3_CV_ACTIVE;
802b7e1c893Smrg	    else {
803b7e1c893Smrg		save->bios_0_scratch &= ~ATOM_S0_CV_MASK;
804b7e1c893Smrg		save->bios_3_scratch &= ~ATOM_S3_CV_ACTIVE;
805b7e1c893Smrg	    }
806b7e1c893Smrg	    break;
807b7e1c893Smrg	case ATOM_DEVICE_LCD1_SUPPORT:
808b7e1c893Smrg	    if (connected) {
809b7e1c893Smrg		save->bios_0_scratch |= ATOM_S0_LCD1;
810b7e1c893Smrg		save->bios_3_scratch |= ATOM_S3_LCD1_ACTIVE;
811b7e1c893Smrg	    } else {
812b7e1c893Smrg		save->bios_0_scratch &= ~ATOM_S0_LCD1;
813b7e1c893Smrg		save->bios_3_scratch &= ~ATOM_S3_LCD1_ACTIVE;
814b7e1c893Smrg	    }
815b7e1c893Smrg	    break;
816b7e1c893Smrg	case ATOM_DEVICE_CRT1_SUPPORT:
817b7e1c893Smrg	    if (connected) {
818b7e1c893Smrg		save->bios_0_scratch |= ATOM_S0_CRT1_COLOR;
819b7e1c893Smrg		save->bios_3_scratch |= ATOM_S3_CRT1_ACTIVE;
820b7e1c893Smrg	    } else {
821b7e1c893Smrg		save->bios_0_scratch &= ~ATOM_S0_CRT1_MASK;
822b7e1c893Smrg		save->bios_3_scratch &= ~ATOM_S3_CRT1_ACTIVE;
823b7e1c893Smrg	    }
824b7e1c893Smrg	    break;
825b7e1c893Smrg	case ATOM_DEVICE_CRT2_SUPPORT:
826b7e1c893Smrg	    if (connected) {
827b7e1c893Smrg		save->bios_0_scratch |= ATOM_S0_CRT2_COLOR;
828b7e1c893Smrg		save->bios_3_scratch |= ATOM_S3_CRT2_ACTIVE;
829b7e1c893Smrg	    } else {
830b7e1c893Smrg		save->bios_0_scratch &= ~ATOM_S0_CRT2_MASK;
831b7e1c893Smrg		save->bios_3_scratch &= ~ATOM_S3_CRT2_ACTIVE;
832b7e1c893Smrg	    }
833b7e1c893Smrg	    break;
834b7e1c893Smrg	case ATOM_DEVICE_DFP1_SUPPORT:
835b7e1c893Smrg	    if (connected) {
836b7e1c893Smrg		save->bios_0_scratch |= ATOM_S0_DFP1;
837b7e1c893Smrg		save->bios_3_scratch |= ATOM_S3_DFP1_ACTIVE;
838b7e1c893Smrg	    } else {
839b7e1c893Smrg		save->bios_0_scratch &= ~ATOM_S0_DFP1;
840b7e1c893Smrg		save->bios_3_scratch &= ~ATOM_S3_DFP1_ACTIVE;
841209ff23fSmrg	    }
842b7e1c893Smrg	    break;
843b7e1c893Smrg	case ATOM_DEVICE_DFP2_SUPPORT:
844b7e1c893Smrg	    if (connected) {
845b7e1c893Smrg		save->bios_0_scratch |= ATOM_S0_DFP2;
846b7e1c893Smrg		save->bios_3_scratch |= ATOM_S3_DFP2_ACTIVE;
847b7e1c893Smrg	    } else {
848b7e1c893Smrg		save->bios_0_scratch &= ~ATOM_S0_DFP2;
849b7e1c893Smrg		save->bios_3_scratch &= ~ATOM_S3_DFP2_ACTIVE;
850209ff23fSmrg	    }
851b7e1c893Smrg	    break;
852b7e1c893Smrg	case ATOM_DEVICE_DFP3_SUPPORT:
853b7e1c893Smrg	    if (connected) {
854b7e1c893Smrg		save->bios_0_scratch |= ATOM_S0_DFP3;
855b7e1c893Smrg		save->bios_3_scratch |= ATOM_S3_DFP3_ACTIVE;
856b7e1c893Smrg	    } else {
857b7e1c893Smrg		save->bios_0_scratch &= ~ATOM_S0_DFP3;
858b7e1c893Smrg		save->bios_3_scratch &= ~ATOM_S3_DFP3_ACTIVE;
859209ff23fSmrg	    }
860b7e1c893Smrg	    break;
861b7e1c893Smrg	case ATOM_DEVICE_DFP4_SUPPORT:
862b7e1c893Smrg	    if (connected) {
863b7e1c893Smrg		save->bios_0_scratch |= ATOM_S0_DFP4;
864b7e1c893Smrg		save->bios_3_scratch |= ATOM_S3_DFP4_ACTIVE;
865b7e1c893Smrg	    } else {
866b7e1c893Smrg		save->bios_0_scratch &= ~ATOM_S0_DFP4;
867b7e1c893Smrg		save->bios_3_scratch &= ~ATOM_S3_DFP4_ACTIVE;
868209ff23fSmrg	    }
869b7e1c893Smrg	    break;
870b7e1c893Smrg	case ATOM_DEVICE_DFP5_SUPPORT:
871b7e1c893Smrg	    if (connected) {
872b7e1c893Smrg		save->bios_0_scratch |= ATOM_S0_DFP5;
873b7e1c893Smrg		save->bios_3_scratch |= ATOM_S3_DFP5_ACTIVE;
874b7e1c893Smrg	    } else {
875b7e1c893Smrg		save->bios_0_scratch &= ~ATOM_S0_DFP5;
876b7e1c893Smrg		save->bios_3_scratch &= ~ATOM_S3_DFP5_ACTIVE;
877209ff23fSmrg	    }
878b7e1c893Smrg	    break;
879209ff23fSmrg	}
880b7e1c893Smrg	if (info->ChipFamily >= CHIP_FAMILY_R600) {
881209ff23fSmrg	    OUTREG(R600_BIOS_0_SCRATCH, save->bios_0_scratch);
882b7e1c893Smrg	    OUTREG(R600_BIOS_3_SCRATCH, save->bios_3_scratch);
883b7e1c893Smrg	} else {
884209ff23fSmrg	    OUTREG(RADEON_BIOS_0_SCRATCH, save->bios_0_scratch);
885b7e1c893Smrg	    OUTREG(RADEON_BIOS_3_SCRATCH, save->bios_3_scratch);
886b7e1c893Smrg	}
887209ff23fSmrg    } else {
888b7e1c893Smrg	switch (radeon_output->active_device) {
889b7e1c893Smrg	case ATOM_DEVICE_TV1_SUPPORT:
890b7e1c893Smrg	    if (connected) {
891b7e1c893Smrg		if (radeon_output->MonType == MT_STV)
892b7e1c893Smrg		    save->bios_4_scratch |= RADEON_TV1_ATTACHED_SVIDEO;
893b7e1c893Smrg		else if (radeon_output->MonType == MT_CTV)
894b7e1c893Smrg		    save->bios_4_scratch |= RADEON_TV1_ATTACHED_COMP;
895b7e1c893Smrg		save->bios_5_scratch |= RADEON_TV1_ON;
896b7e1c893Smrg	    } else {
897b7e1c893Smrg		save->bios_4_scratch &= ~RADEON_TV1_ATTACHED_MASK;
898b7e1c893Smrg		save->bios_5_scratch &= ~RADEON_TV1_ON;
899b7e1c893Smrg	    }
900b7e1c893Smrg	    break;
901b7e1c893Smrg	case ATOM_DEVICE_LCD1_SUPPORT:
902b7e1c893Smrg	    if (connected) {
903209ff23fSmrg		save->bios_4_scratch |= RADEON_LCD1_ATTACHED;
904b7e1c893Smrg		save->bios_5_scratch |= RADEON_LCD1_ON;
905b7e1c893Smrg	    } else {
906b7e1c893Smrg		save->bios_4_scratch &= ~RADEON_LCD1_ATTACHED;
907b7e1c893Smrg		save->bios_5_scratch &= ~RADEON_LCD1_ON;
908209ff23fSmrg	    }
909b7e1c893Smrg	    break;
910b7e1c893Smrg	case ATOM_DEVICE_CRT1_SUPPORT:
911b7e1c893Smrg	    if (connected) {
912b7e1c893Smrg		save->bios_4_scratch |= RADEON_CRT1_ATTACHED_COLOR;
913b7e1c893Smrg		save->bios_5_scratch |= RADEON_CRT1_ON;
914b7e1c893Smrg	    } else {
915209ff23fSmrg		save->bios_4_scratch &= ~RADEON_CRT1_ATTACHED_MASK;
916b7e1c893Smrg		save->bios_5_scratch &= ~RADEON_CRT1_ON;
917b7e1c893Smrg	    }
918b7e1c893Smrg	    break;
919b7e1c893Smrg	case ATOM_DEVICE_CRT2_SUPPORT:
920b7e1c893Smrg	    if (connected) {
921b7e1c893Smrg		save->bios_4_scratch |= RADEON_CRT2_ATTACHED_COLOR;
922b7e1c893Smrg		save->bios_5_scratch |= RADEON_CRT2_ON;
923b7e1c893Smrg	    } else {
924b7e1c893Smrg		save->bios_4_scratch &= ~RADEON_CRT2_ATTACHED_MASK;
925b7e1c893Smrg		save->bios_5_scratch &= ~RADEON_CRT2_ON;
926b7e1c893Smrg	    }
927b7e1c893Smrg	    break;
928b7e1c893Smrg	case ATOM_DEVICE_DFP1_SUPPORT:
929b7e1c893Smrg	    if (connected) {
930b7e1c893Smrg		save->bios_4_scratch |= RADEON_DFP1_ATTACHED;
931b7e1c893Smrg		save->bios_5_scratch |= RADEON_DFP1_ON;
932b7e1c893Smrg	    } else {
933209ff23fSmrg		save->bios_4_scratch &= ~RADEON_DFP1_ATTACHED;
934b7e1c893Smrg		save->bios_5_scratch &= ~RADEON_DFP1_ON;
935b7e1c893Smrg	    }
936b7e1c893Smrg	    break;
937b7e1c893Smrg	case ATOM_DEVICE_DFP2_SUPPORT:
938b7e1c893Smrg	    if (connected) {
939b7e1c893Smrg		save->bios_4_scratch |= RADEON_DFP2_ATTACHED;
940b7e1c893Smrg		save->bios_5_scratch |= RADEON_DFP2_ON;
941b7e1c893Smrg	    } else {
942209ff23fSmrg		save->bios_4_scratch &= ~RADEON_DFP2_ATTACHED;
943b7e1c893Smrg		save->bios_5_scratch &= ~RADEON_DFP2_ON;
944b7e1c893Smrg	    }
945b7e1c893Smrg	    break;
946209ff23fSmrg	}
947209ff23fSmrg	OUTREG(RADEON_BIOS_4_SCRATCH, save->bios_4_scratch);
948b7e1c893Smrg	OUTREG(RADEON_BIOS_5_SCRATCH, save->bios_5_scratch);
949209ff23fSmrg    }
950209ff23fSmrg
951209ff23fSmrg}
952209ff23fSmrg
953209ff23fSmrgstatic xf86OutputStatus
954209ff23fSmrgradeon_detect(xf86OutputPtr output)
955209ff23fSmrg{
956209ff23fSmrg    ScrnInfoPtr	    pScrn = output->scrn;
957209ff23fSmrg    RADEONInfoPtr info = RADEONPTR(pScrn);
958209ff23fSmrg    RADEONOutputPrivatePtr radeon_output = output->driver_private;
959209ff23fSmrg    Bool connected = TRUE;
960209ff23fSmrg
961209ff23fSmrg    radeon_output->MonType = MT_UNKNOWN;
962209ff23fSmrg    radeon_bios_output_connected(output, FALSE);
963b7e1c893Smrg    radeon_output->MonType = radeon_ddc_connected(output);
964b7e1c893Smrg    if (!radeon_output->MonType) {
965b7e1c893Smrg	if (radeon_output->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
966b7e1c893Smrg	    if (xf86ReturnOptValBool(info->Options, OPTION_IGNORE_LID_STATUS, TRUE))
967b7e1c893Smrg		radeon_output->MonType = MT_LCD;
968b7e1c893Smrg	    else
969b7e1c893Smrg#if defined(__powerpc__)
970b7e1c893Smrg		radeon_output->MonType = MT_LCD;
971b7e1c893Smrg#else
972b7e1c893Smrg	        radeon_output->MonType = RADEONDetectLidStatus(pScrn);
973b7e1c893Smrg#endif
974b7e1c893Smrg	} else {
975b7e1c893Smrg	    if (info->IsAtomBios)
976b7e1c893Smrg		radeon_output->MonType = atombios_dac_detect(output);
977b7e1c893Smrg	    else
978b7e1c893Smrg		radeon_output->MonType = legacy_dac_detect(output);
979b7e1c893Smrg	}
980b7e1c893Smrg    }
981b7e1c893Smrg
982b7e1c893Smrg    // if size is zero panel probably broken or not connected
983b7e1c893Smrg    if (radeon_output->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
984b7e1c893Smrg	radeon_encoder_ptr radeon_encoder = info->encoders[ATOM_DEVICE_LCD1_INDEX];
985b7e1c893Smrg	if (radeon_encoder) {
986b7e1c893Smrg	    radeon_lvds_ptr lvds = (radeon_lvds_ptr)radeon_encoder->dev_priv;
987b7e1c893Smrg	    if (lvds) {
988b7e1c893Smrg		if ((lvds->native_mode.PanelXRes == 0) || (lvds->native_mode.PanelYRes == 0))
989b7e1c893Smrg		    radeon_output->MonType = MT_NONE;
990b7e1c893Smrg	    }
991b7e1c893Smrg	}
992b7e1c893Smrg    }
993b7e1c893Smrg
994b7e1c893Smrg
995c503f109Smrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
996c503f109Smrg	       "Output: %s, Detected Monitor Type: %d\n", output->name, radeon_output->MonType);
997b7e1c893Smrg    if (output->MonInfo) {
998b7e1c893Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "EDID data from the display on output: %s ----------------------\n",
999b7e1c893Smrg		   output->name);
1000b7e1c893Smrg	xf86PrintEDID( output->MonInfo );
1001b7e1c893Smrg    }
1002209ff23fSmrg
1003209ff23fSmrg    /* nothing connected, light up some defaults so the server comes up */
1004209ff23fSmrg    if (radeon_output->MonType == MT_NONE &&
1005209ff23fSmrg	info->first_load_no_devices) {
1006209ff23fSmrg	if (info->IsMobility) {
1007b7e1c893Smrg	    if (radeon_output->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
1008209ff23fSmrg		radeon_output->MonType = MT_LCD;
1009209ff23fSmrg		info->first_load_no_devices = FALSE;
1010b7e1c893Smrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Using LCD default\n");
1011209ff23fSmrg	    }
1012209ff23fSmrg	} else {
1013b7e1c893Smrg	    if (radeon_output->devices & (ATOM_DEVICE_CRT_SUPPORT)) {
1014209ff23fSmrg		radeon_output->MonType = MT_CRT;
1015209ff23fSmrg		info->first_load_no_devices = FALSE;
1016b7e1c893Smrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Using CRT default\n");
1017b7e1c893Smrg	    } else if (radeon_output->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
1018209ff23fSmrg		radeon_output->MonType = MT_DFP;
1019209ff23fSmrg		info->first_load_no_devices = FALSE;
1020b7e1c893Smrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Using DFP default\n");
1021209ff23fSmrg	    }
1022209ff23fSmrg	}
1023209ff23fSmrg    }
1024209ff23fSmrg
1025209ff23fSmrg    radeon_bios_output_connected(output, TRUE);
1026209ff23fSmrg
1027209ff23fSmrg    /* set montype so users can force outputs on even if detection fails */
1028209ff23fSmrg    if (radeon_output->MonType == MT_NONE) {
1029209ff23fSmrg	connected = FALSE;
1030b7e1c893Smrg	switch (radeon_output->ConnectorType) {
1031b7e1c893Smrg	case CONNECTOR_LVDS:
1032209ff23fSmrg	    radeon_output->MonType = MT_LCD;
1033b7e1c893Smrg	    break;
1034b7e1c893Smrg	case CONNECTOR_DVI_D:
1035b7e1c893Smrg	case CONNECTOR_HDMI_TYPE_A:
1036b7e1c893Smrg	case CONNECTOR_HDMI_TYPE_B:
1037209ff23fSmrg	    radeon_output->MonType = MT_DFP;
1038b7e1c893Smrg	    break;
1039b7e1c893Smrg	case CONNECTOR_VGA:
1040b7e1c893Smrg	case CONNECTOR_DVI_A:
1041b7e1c893Smrg	default:
1042209ff23fSmrg	    radeon_output->MonType = MT_CRT;
1043b7e1c893Smrg	    break;
1044b7e1c893Smrg	case CONNECTOR_DVI_I:
1045209ff23fSmrg	    if (radeon_output->DVIType == DVI_ANALOG)
1046209ff23fSmrg		radeon_output->MonType = MT_CRT;
1047209ff23fSmrg	    else if (radeon_output->DVIType == DVI_DIGITAL)
1048209ff23fSmrg		radeon_output->MonType = MT_DFP;
1049b7e1c893Smrg	    break;
1050b7e1c893Smrg	case CONNECTOR_STV:
1051b7e1c893Smrg            radeon_output->MonType = MT_STV;
1052b7e1c893Smrg	    break;
1053b7e1c893Smrg	case CONNECTOR_CTV:
1054b7e1c893Smrg            radeon_output->MonType = MT_CTV;
1055b7e1c893Smrg	    break;
1056b7e1c893Smrg	case CONNECTOR_DIN:
1057b7e1c893Smrg            radeon_output->MonType = MT_CV;
1058b7e1c893Smrg	    break;
1059b7e1c893Smrg	case CONNECTOR_DISPLAY_PORT:
1060b7e1c893Smrg	    radeon_output->MonType = MT_DP;
1061b7e1c893Smrg	    break;
1062209ff23fSmrg	}
1063209ff23fSmrg    }
1064209ff23fSmrg
1065b7e1c893Smrg    radeon_set_active_device(output);
1066209ff23fSmrg
1067b7e1c893Smrg    if (radeon_output->active_device & (ATOM_DEVICE_LCD_SUPPORT | ATOM_DEVICE_DFP_SUPPORT))
1068b7e1c893Smrg	output->subpixel_order = SubPixelHorizontalRGB;
1069b7e1c893Smrg    else
1070b7e1c893Smrg	output->subpixel_order = SubPixelNone;
1071209ff23fSmrg
1072b7e1c893Smrg    if (connected)
1073b7e1c893Smrg	return XF86OutputStatusConnected;
1074b7e1c893Smrg    else
1075b7e1c893Smrg	return XF86OutputStatusDisconnected;
1076209ff23fSmrg}
1077209ff23fSmrg
1078209ff23fSmrgstatic DisplayModePtr
1079209ff23fSmrgradeon_get_modes(xf86OutputPtr output)
1080209ff23fSmrg{
1081209ff23fSmrg  DisplayModePtr modes;
1082209ff23fSmrg  modes = RADEONProbeOutputModes(output);
1083209ff23fSmrg  return modes;
1084209ff23fSmrg}
1085209ff23fSmrg
1086209ff23fSmrgstatic void
1087209ff23fSmrgradeon_destroy (xf86OutputPtr output)
1088209ff23fSmrg{
1089209ff23fSmrg    if (output->driver_private)
1090209ff23fSmrg        xfree(output->driver_private);
1091209ff23fSmrg}
1092209ff23fSmrg
1093209ff23fSmrgstatic void
1094209ff23fSmrgradeon_set_backlight_level(xf86OutputPtr output, int level)
1095209ff23fSmrg{
1096209ff23fSmrg#if 0
1097209ff23fSmrg    ScrnInfoPtr pScrn = output->scrn;
1098209ff23fSmrg    RADEONInfoPtr info = RADEONPTR(pScrn);
1099209ff23fSmrg    unsigned char * RADEONMMIO = info->MMIO;
1100209ff23fSmrg    uint32_t lvds_gen_cntl;
1101209ff23fSmrg
1102209ff23fSmrg    lvds_gen_cntl = INREG(RADEON_LVDS_GEN_CNTL);
1103209ff23fSmrg    lvds_gen_cntl |= RADEON_LVDS_BL_MOD_EN;
1104209ff23fSmrg    lvds_gen_cntl &= ~RADEON_LVDS_BL_MOD_LEVEL_MASK;
1105209ff23fSmrg    lvds_gen_cntl |= (level << RADEON_LVDS_BL_MOD_LEVEL_SHIFT) & RADEON_LVDS_BL_MOD_LEVEL_MASK;
1106209ff23fSmrg    //usleep (radeon_output->PanelPwrDly * 1000);
1107209ff23fSmrg    OUTREG(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl);
1108209ff23fSmrg    lvds_gen_cntl &= ~RADEON_LVDS_BL_MOD_EN;
1109209ff23fSmrg    //usleep (radeon_output->PanelPwrDly * 1000);
1110209ff23fSmrg    OUTREG(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl);
1111209ff23fSmrg#endif
1112209ff23fSmrg}
1113209ff23fSmrg
1114209ff23fSmrgstatic Atom backlight_atom;
1115209ff23fSmrgstatic Atom tmds_pll_atom;
1116209ff23fSmrgstatic Atom rmx_atom;
1117209ff23fSmrgstatic Atom monitor_type_atom;
1118209ff23fSmrgstatic Atom load_detection_atom;
1119209ff23fSmrgstatic Atom coherent_mode_atom;
1120209ff23fSmrgstatic Atom tv_hsize_atom;
1121209ff23fSmrgstatic Atom tv_hpos_atom;
1122209ff23fSmrgstatic Atom tv_vpos_atom;
1123209ff23fSmrgstatic Atom tv_std_atom;
1124209ff23fSmrg#define RADEON_MAX_BACKLIGHT_LEVEL 255
1125209ff23fSmrg
1126209ff23fSmrgstatic void
1127209ff23fSmrgradeon_create_resources(xf86OutputPtr output)
1128209ff23fSmrg{
1129209ff23fSmrg    ScrnInfoPtr pScrn = output->scrn;
1130209ff23fSmrg    RADEONInfoPtr info = RADEONPTR(pScrn);
1131209ff23fSmrg    RADEONOutputPrivatePtr radeon_output = output->driver_private;
1132209ff23fSmrg    INT32 range[2];
1133209ff23fSmrg    int data, err;
1134209ff23fSmrg    const char *s;
1135209ff23fSmrg
1136b7e1c893Smrg#if 0
1137209ff23fSmrg    /* backlight control */
1138209ff23fSmrg    if (radeon_output->type == OUTPUT_LVDS) {
1139209ff23fSmrg	backlight_atom = MAKE_ATOM("backlight");
1140209ff23fSmrg
1141209ff23fSmrg	range[0] = 0;
1142209ff23fSmrg	range[1] = RADEON_MAX_BACKLIGHT_LEVEL;
1143209ff23fSmrg	err = RRConfigureOutputProperty(output->randr_output, backlight_atom,
1144209ff23fSmrg					FALSE, TRUE, FALSE, 2, range);
1145209ff23fSmrg	if (err != 0) {
1146209ff23fSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1147209ff23fSmrg		       "RRConfigureOutputProperty error, %d\n", err);
1148209ff23fSmrg	}
1149209ff23fSmrg	/* Set the current value of the backlight property */
1150209ff23fSmrg	//data = (info->SavedReg->lvds_gen_cntl & RADEON_LVDS_BL_MOD_LEVEL_MASK) >> RADEON_LVDS_BL_MOD_LEVEL_SHIFT;
1151209ff23fSmrg	data = RADEON_MAX_BACKLIGHT_LEVEL;
1152209ff23fSmrg	err = RRChangeOutputProperty(output->randr_output, backlight_atom,
1153209ff23fSmrg				     XA_INTEGER, 32, PropModeReplace, 1, &data,
1154209ff23fSmrg				     FALSE, TRUE);
1155209ff23fSmrg	if (err != 0) {
1156209ff23fSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1157209ff23fSmrg		       "RRChangeOutputProperty error, %d\n", err);
1158209ff23fSmrg	}
1159209ff23fSmrg    }
1160b7e1c893Smrg#endif
1161209ff23fSmrg
1162b7e1c893Smrg    if (radeon_output->devices & (ATOM_DEVICE_CRT_SUPPORT | ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) {
1163209ff23fSmrg	load_detection_atom = MAKE_ATOM("load_detection");
1164209ff23fSmrg
1165209ff23fSmrg	range[0] = 0; /* off */
1166209ff23fSmrg	range[1] = 1; /* on */
1167209ff23fSmrg	err = RRConfigureOutputProperty(output->randr_output, load_detection_atom,
1168209ff23fSmrg					FALSE, TRUE, FALSE, 2, range);
1169209ff23fSmrg	if (err != 0) {
1170209ff23fSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1171209ff23fSmrg		       "RRConfigureOutputProperty error, %d\n", err);
1172209ff23fSmrg	}
1173209ff23fSmrg
1174209ff23fSmrg	if (radeon_output->load_detection)
1175b7e1c893Smrg	    data = 1;
1176209ff23fSmrg	else
1177b7e1c893Smrg	    data = 0;
1178209ff23fSmrg
1179209ff23fSmrg	err = RRChangeOutputProperty(output->randr_output, load_detection_atom,
1180209ff23fSmrg				     XA_INTEGER, 32, PropModeReplace, 1, &data,
1181209ff23fSmrg				     FALSE, TRUE);
1182209ff23fSmrg	if (err != 0) {
1183209ff23fSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1184209ff23fSmrg		       "RRChangeOutputProperty error, %d\n", err);
1185209ff23fSmrg	}
1186209ff23fSmrg    }
1187209ff23fSmrg
1188b7e1c893Smrg    if (IS_AVIVO_VARIANT && (radeon_output->devices & (ATOM_DEVICE_DFP_SUPPORT))) {
1189209ff23fSmrg	coherent_mode_atom = MAKE_ATOM("coherent_mode");
1190209ff23fSmrg
1191209ff23fSmrg	range[0] = 0; /* off */
1192209ff23fSmrg	range[1] = 1; /* on */
1193209ff23fSmrg	err = RRConfigureOutputProperty(output->randr_output, coherent_mode_atom,
1194209ff23fSmrg					FALSE, TRUE, FALSE, 2, range);
1195209ff23fSmrg	if (err != 0) {
1196209ff23fSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1197209ff23fSmrg		       "RRConfigureOutputProperty error, %d\n", err);
1198209ff23fSmrg	}
1199209ff23fSmrg
1200b7e1c893Smrg	data = 1; /* coherent mode on by default */
1201209ff23fSmrg
1202209ff23fSmrg	err = RRChangeOutputProperty(output->randr_output, coherent_mode_atom,
1203209ff23fSmrg				     XA_INTEGER, 32, PropModeReplace, 1, &data,
1204209ff23fSmrg				     FALSE, TRUE);
1205209ff23fSmrg	if (err != 0) {
1206209ff23fSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1207209ff23fSmrg		       "RRChangeOutputProperty error, %d\n", err);
1208209ff23fSmrg	}
1209209ff23fSmrg    }
1210209ff23fSmrg
1211c503f109Smrg    if ((!IS_AVIVO_VARIANT) && (radeon_output->devices & (ATOM_DEVICE_DFP1_SUPPORT))) {
1212209ff23fSmrg	tmds_pll_atom = MAKE_ATOM("tmds_pll");
1213209ff23fSmrg
1214209ff23fSmrg	err = RRConfigureOutputProperty(output->randr_output, tmds_pll_atom,
1215209ff23fSmrg					FALSE, FALSE, FALSE, 0, NULL);
1216209ff23fSmrg	if (err != 0) {
1217209ff23fSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1218209ff23fSmrg		       "RRConfigureOutputProperty error, %d\n", err);
1219209ff23fSmrg	}
1220209ff23fSmrg	/* Set the current value of the property */
1221209ff23fSmrg#if defined(__powerpc__)
1222209ff23fSmrg	s = "driver";
1223209ff23fSmrg#else
1224209ff23fSmrg	s = "bios";
1225209ff23fSmrg#endif
1226209ff23fSmrg	if (xf86ReturnOptValBool(info->Options, OPTION_DEFAULT_TMDS_PLL, FALSE)) {
1227209ff23fSmrg	    s = "driver";
1228209ff23fSmrg	}
1229209ff23fSmrg
1230209ff23fSmrg	err = RRChangeOutputProperty(output->randr_output, tmds_pll_atom,
1231209ff23fSmrg				     XA_STRING, 8, PropModeReplace, strlen(s), (pointer)s,
1232209ff23fSmrg				     FALSE, FALSE);
1233209ff23fSmrg	if (err != 0) {
1234209ff23fSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1235209ff23fSmrg		       "RRChangeOutputProperty error, %d\n", err);
1236209ff23fSmrg	}
1237209ff23fSmrg
1238209ff23fSmrg    }
1239209ff23fSmrg
1240209ff23fSmrg    /* RMX control - fullscreen, centered, keep ratio, off */
1241209ff23fSmrg    /* actually more of a crtc property as only crtc1 has rmx */
1242b7e1c893Smrg    if (radeon_output->devices & (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) {
1243209ff23fSmrg	rmx_atom = MAKE_ATOM("scaler");
1244209ff23fSmrg
1245209ff23fSmrg	err = RRConfigureOutputProperty(output->randr_output, rmx_atom,
1246209ff23fSmrg					FALSE, FALSE, FALSE, 0, NULL);
1247209ff23fSmrg	if (err != 0) {
1248209ff23fSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1249209ff23fSmrg		       "RRConfigureOutputProperty error, %d\n", err);
1250209ff23fSmrg	}
1251209ff23fSmrg	/* Set the current value of the property */
1252b7e1c893Smrg	switch (radeon_output->rmx_type) {
1253b7e1c893Smrg	case RMX_OFF:
1254b7e1c893Smrg	default:
1255209ff23fSmrg	    s = "off";
1256b7e1c893Smrg	    break;
1257b7e1c893Smrg	case RMX_FULL:
1258b7e1c893Smrg	    s = "full";
1259b7e1c893Smrg	    break;
1260b7e1c893Smrg	case RMX_CENTER:
1261b7e1c893Smrg	    s = "center";
1262b7e1c893Smrg	    break;
1263b7e1c893Smrg	case RMX_ASPECT:
1264b7e1c893Smrg	    s = "aspect";
1265b7e1c893Smrg	    break;
1266b7e1c893Smrg	}
1267209ff23fSmrg	err = RRChangeOutputProperty(output->randr_output, rmx_atom,
1268209ff23fSmrg				     XA_STRING, 8, PropModeReplace, strlen(s), (pointer)s,
1269209ff23fSmrg				     FALSE, FALSE);
1270209ff23fSmrg	if (err != 0) {
1271209ff23fSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1272209ff23fSmrg		       "RRChangeOutputProperty error, %d\n", err);
1273209ff23fSmrg	}
1274209ff23fSmrg    }
1275209ff23fSmrg
1276209ff23fSmrg    /* force auto/analog/digital for DVI-I ports */
1277b7e1c893Smrg    if ((radeon_output->devices & (ATOM_DEVICE_CRT_SUPPORT)) &&
1278b7e1c893Smrg	(radeon_output->devices & (ATOM_DEVICE_DFP_SUPPORT))){
1279209ff23fSmrg	monitor_type_atom = MAKE_ATOM("dvi_monitor_type");
1280209ff23fSmrg
1281209ff23fSmrg	err = RRConfigureOutputProperty(output->randr_output, monitor_type_atom,
1282209ff23fSmrg					FALSE, FALSE, FALSE, 0, NULL);
1283209ff23fSmrg	if (err != 0) {
1284209ff23fSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1285209ff23fSmrg		       "RRConfigureOutputProperty error, %d\n", err);
1286209ff23fSmrg	}
1287209ff23fSmrg	/* Set the current value of the backlight property */
1288209ff23fSmrg	s = "auto";
1289209ff23fSmrg	err = RRChangeOutputProperty(output->randr_output, monitor_type_atom,
1290209ff23fSmrg				     XA_STRING, 8, PropModeReplace, strlen(s), (pointer)s,
1291209ff23fSmrg				     FALSE, FALSE);
1292209ff23fSmrg	if (err != 0) {
1293209ff23fSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1294209ff23fSmrg		       "RRChangeOutputProperty error, %d\n", err);
1295209ff23fSmrg	}
1296209ff23fSmrg    }
1297209ff23fSmrg
1298b7e1c893Smrg    if (radeon_output->devices & (ATOM_DEVICE_TV_SUPPORT)) {
1299b7e1c893Smrg	radeon_tvout_ptr tvout = &radeon_output->tvout;
1300209ff23fSmrg	if (!IS_AVIVO_VARIANT) {
1301209ff23fSmrg	    tv_hsize_atom = MAKE_ATOM("tv_horizontal_size");
1302209ff23fSmrg
1303209ff23fSmrg	    range[0] = -MAX_H_SIZE;
1304209ff23fSmrg	    range[1] = MAX_H_SIZE;
1305209ff23fSmrg	    err = RRConfigureOutputProperty(output->randr_output, tv_hsize_atom,
1306209ff23fSmrg					    FALSE, TRUE, FALSE, 2, range);
1307209ff23fSmrg	    if (err != 0) {
1308209ff23fSmrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1309209ff23fSmrg			   "RRConfigureOutputProperty error, %d\n", err);
1310209ff23fSmrg	    }
1311209ff23fSmrg	    data = 0;
1312209ff23fSmrg	    err = RRChangeOutputProperty(output->randr_output, tv_hsize_atom,
1313209ff23fSmrg					 XA_INTEGER, 32, PropModeReplace, 1, &data,
1314209ff23fSmrg					 FALSE, TRUE);
1315209ff23fSmrg	    if (err != 0) {
1316209ff23fSmrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1317209ff23fSmrg			   "RRChangeOutputProperty error, %d\n", err);
1318209ff23fSmrg	    }
1319209ff23fSmrg
1320209ff23fSmrg	    tv_hpos_atom = MAKE_ATOM("tv_horizontal_position");
1321209ff23fSmrg
1322209ff23fSmrg	    range[0] = -MAX_H_POSITION;
1323209ff23fSmrg	    range[1] = MAX_H_POSITION;
1324209ff23fSmrg	    err = RRConfigureOutputProperty(output->randr_output, tv_hpos_atom,
1325209ff23fSmrg					    FALSE, TRUE, FALSE, 2, range);
1326209ff23fSmrg	    if (err != 0) {
1327209ff23fSmrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1328209ff23fSmrg			   "RRConfigureOutputProperty error, %d\n", err);
1329209ff23fSmrg	    }
1330209ff23fSmrg	    data = 0;
1331209ff23fSmrg	    err = RRChangeOutputProperty(output->randr_output, tv_hpos_atom,
1332209ff23fSmrg					 XA_INTEGER, 32, PropModeReplace, 1, &data,
1333209ff23fSmrg					 FALSE, TRUE);
1334209ff23fSmrg	    if (err != 0) {
1335209ff23fSmrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1336209ff23fSmrg			   "RRChangeOutputProperty error, %d\n", err);
1337209ff23fSmrg	    }
1338209ff23fSmrg
1339209ff23fSmrg	    tv_vpos_atom = MAKE_ATOM("tv_vertical_position");
1340209ff23fSmrg
1341209ff23fSmrg	    range[0] = -MAX_V_POSITION;
1342209ff23fSmrg	    range[1] = MAX_V_POSITION;
1343209ff23fSmrg	    err = RRConfigureOutputProperty(output->randr_output, tv_vpos_atom,
1344209ff23fSmrg					    FALSE, TRUE, FALSE, 2, range);
1345209ff23fSmrg	    if (err != 0) {
1346209ff23fSmrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1347209ff23fSmrg			   "RRConfigureOutputProperty error, %d\n", err);
1348209ff23fSmrg	    }
1349209ff23fSmrg	    data = 0;
1350209ff23fSmrg	    err = RRChangeOutputProperty(output->randr_output, tv_vpos_atom,
1351209ff23fSmrg					 XA_INTEGER, 32, PropModeReplace, 1, &data,
1352209ff23fSmrg					 FALSE, TRUE);
1353209ff23fSmrg	    if (err != 0) {
1354209ff23fSmrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1355209ff23fSmrg			   "RRChangeOutputProperty error, %d\n", err);
1356209ff23fSmrg	    }
1357209ff23fSmrg	}
1358209ff23fSmrg
1359209ff23fSmrg	tv_std_atom = MAKE_ATOM("tv_standard");
1360209ff23fSmrg
1361209ff23fSmrg	err = RRConfigureOutputProperty(output->randr_output, tv_std_atom,
1362209ff23fSmrg					FALSE, FALSE, FALSE, 0, NULL);
1363209ff23fSmrg	if (err != 0) {
1364209ff23fSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1365209ff23fSmrg		       "RRConfigureOutputProperty error, %d\n", err);
1366209ff23fSmrg	}
1367209ff23fSmrg
1368209ff23fSmrg	/* Set the current value of the property */
1369b7e1c893Smrg	switch (tvout->tvStd) {
1370209ff23fSmrg	case TV_STD_PAL:
1371209ff23fSmrg	    s = "pal";
1372209ff23fSmrg	    break;
1373209ff23fSmrg	case TV_STD_PAL_M:
1374209ff23fSmrg	    s = "pal-m";
1375209ff23fSmrg	    break;
1376209ff23fSmrg	case TV_STD_PAL_60:
1377209ff23fSmrg	    s = "pal-60";
1378209ff23fSmrg	    break;
1379209ff23fSmrg	case TV_STD_NTSC_J:
1380209ff23fSmrg	    s = "ntsc-j";
1381209ff23fSmrg	    break;
1382209ff23fSmrg	case TV_STD_SCART_PAL:
1383209ff23fSmrg	    s = "scart-pal";
1384209ff23fSmrg	    break;
1385209ff23fSmrg	case TV_STD_NTSC:
1386209ff23fSmrg	default:
1387209ff23fSmrg	    s = "ntsc";
1388209ff23fSmrg	    break;
1389209ff23fSmrg	}
1390209ff23fSmrg
1391209ff23fSmrg	err = RRChangeOutputProperty(output->randr_output, tv_std_atom,
1392209ff23fSmrg				     XA_STRING, 8, PropModeReplace, strlen(s), (pointer)s,
1393209ff23fSmrg				     FALSE, FALSE);
1394209ff23fSmrg	if (err != 0) {
1395209ff23fSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1396209ff23fSmrg		       "RRChangeOutputProperty error, %d\n", err);
1397209ff23fSmrg	}
1398209ff23fSmrg    }
1399209ff23fSmrg}
1400209ff23fSmrg
1401209ff23fSmrgstatic Bool
1402209ff23fSmrgradeon_set_mode_for_property(xf86OutputPtr output)
1403209ff23fSmrg{
1404209ff23fSmrg    ScrnInfoPtr pScrn = output->scrn;
1405209ff23fSmrg
1406209ff23fSmrg    if (output->crtc) {
1407209ff23fSmrg	xf86CrtcPtr crtc = output->crtc;
1408209ff23fSmrg
1409209ff23fSmrg	if (crtc->enabled) {
1410209ff23fSmrg	    if (!xf86CrtcSetMode(crtc, &crtc->desiredMode, crtc->desiredRotation,
1411209ff23fSmrg				 crtc->desiredX, crtc->desiredY)) {
1412209ff23fSmrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1413209ff23fSmrg			   "Failed to set mode after propery change!\n");
1414209ff23fSmrg		return FALSE;
1415209ff23fSmrg	    }
1416209ff23fSmrg	}
1417209ff23fSmrg    }
1418209ff23fSmrg    return TRUE;
1419209ff23fSmrg}
1420209ff23fSmrg
1421209ff23fSmrgstatic Bool
1422209ff23fSmrgradeon_set_property(xf86OutputPtr output, Atom property,
1423209ff23fSmrg		       RRPropertyValuePtr value)
1424209ff23fSmrg{
1425209ff23fSmrg    RADEONInfoPtr info = RADEONPTR(output->scrn);
1426209ff23fSmrg    RADEONOutputPrivatePtr radeon_output = output->driver_private;
1427209ff23fSmrg    INT32 val;
1428209ff23fSmrg
1429209ff23fSmrg
1430209ff23fSmrg    if (property == backlight_atom) {
1431209ff23fSmrg	if (value->type != XA_INTEGER ||
1432209ff23fSmrg	    value->format != 32 ||
1433209ff23fSmrg	    value->size != 1) {
1434209ff23fSmrg	    return FALSE;
1435209ff23fSmrg	}
1436209ff23fSmrg
1437209ff23fSmrg	val = *(INT32 *)value->data;
1438209ff23fSmrg	if (val < 0 || val > RADEON_MAX_BACKLIGHT_LEVEL)
1439209ff23fSmrg	    return FALSE;
1440209ff23fSmrg
1441209ff23fSmrg#if defined(__powerpc__)
1442209ff23fSmrg	val = RADEON_MAX_BACKLIGHT_LEVEL - val;
1443209ff23fSmrg#endif
1444209ff23fSmrg
1445209ff23fSmrg	radeon_set_backlight_level(output, val);
1446209ff23fSmrg
1447209ff23fSmrg    } else if (property == load_detection_atom) {
1448209ff23fSmrg	if (value->type != XA_INTEGER ||
1449209ff23fSmrg	    value->format != 32 ||
1450209ff23fSmrg	    value->size != 1) {
1451209ff23fSmrg	    return FALSE;
1452209ff23fSmrg	}
1453209ff23fSmrg
1454209ff23fSmrg	val = *(INT32 *)value->data;
1455209ff23fSmrg	if (val < 0 || val > 1)
1456209ff23fSmrg	    return FALSE;
1457209ff23fSmrg
1458209ff23fSmrg	radeon_output->load_detection = val;
1459209ff23fSmrg
1460209ff23fSmrg    } else if (property == coherent_mode_atom) {
1461209ff23fSmrg	Bool coherent_mode = radeon_output->coherent_mode;
1462209ff23fSmrg
1463209ff23fSmrg	if (value->type != XA_INTEGER ||
1464209ff23fSmrg	    value->format != 32 ||
1465209ff23fSmrg	    value->size != 1) {
1466209ff23fSmrg	    return FALSE;
1467209ff23fSmrg	}
1468209ff23fSmrg
1469209ff23fSmrg	val = *(INT32 *)value->data;
1470209ff23fSmrg	if (val < 0 || val > 1)
1471209ff23fSmrg	    return FALSE;
1472209ff23fSmrg
1473209ff23fSmrg	radeon_output->coherent_mode = val;
1474209ff23fSmrg	if (!radeon_set_mode_for_property(output)) {
1475209ff23fSmrg	    radeon_output->coherent_mode = coherent_mode;
1476209ff23fSmrg	    (void)radeon_set_mode_for_property(output);
1477209ff23fSmrg	    return FALSE;
1478209ff23fSmrg	}
1479209ff23fSmrg
1480209ff23fSmrg    } else if (property == rmx_atom) {
1481209ff23fSmrg	const char *s;
1482209ff23fSmrg	RADEONRMXType rmx = radeon_output->rmx_type;
1483209ff23fSmrg
1484209ff23fSmrg	if (value->type != XA_STRING || value->format != 8)
1485209ff23fSmrg	    return FALSE;
1486209ff23fSmrg	s = (char*)value->data;
1487209ff23fSmrg	if (value->size == strlen("full") && !strncmp("full", s, strlen("full"))) {
1488209ff23fSmrg	    radeon_output->rmx_type = RMX_FULL;
1489209ff23fSmrg	} else if (value->size == strlen("center") && !strncmp("center", s, strlen("center"))) {
1490209ff23fSmrg	    radeon_output->rmx_type = RMX_CENTER;
1491b7e1c893Smrg	} else if (value->size == strlen("aspect") && !strncmp("aspect", s, strlen("aspect"))) {
1492b7e1c893Smrg	    if (IS_AVIVO_VARIANT)
1493b7e1c893Smrg		radeon_output->rmx_type = RMX_ASPECT;
1494b7e1c893Smrg	    else
1495b7e1c893Smrg		return FALSE;
1496209ff23fSmrg	} else if (value->size == strlen("off") && !strncmp("off", s, strlen("off"))) {
1497209ff23fSmrg	    radeon_output->rmx_type = RMX_OFF;
1498209ff23fSmrg	} else
1499209ff23fSmrg	    return FALSE;
1500209ff23fSmrg
1501209ff23fSmrg	if (!radeon_set_mode_for_property(output)) {
1502209ff23fSmrg	    radeon_output->rmx_type = rmx;
1503209ff23fSmrg	    (void)radeon_set_mode_for_property(output);
1504209ff23fSmrg	    return FALSE;
1505209ff23fSmrg	}
1506209ff23fSmrg    } else if (property == tmds_pll_atom) {
1507b7e1c893Smrg	radeon_tmds_ptr tmds = NULL;
1508209ff23fSmrg	const char *s;
1509b7e1c893Smrg
1510b7e1c893Smrg	if (info->encoders[ATOM_DEVICE_DFP1_INDEX] && info->encoders[ATOM_DEVICE_DFP1_INDEX]->dev_priv)
1511b7e1c893Smrg	    tmds = (radeon_tmds_ptr)info->encoders[ATOM_DEVICE_DFP1_INDEX]->dev_priv;
1512b7e1c893Smrg	else
1513b7e1c893Smrg	    return FALSE;
1514b7e1c893Smrg
1515209ff23fSmrg	if (value->type != XA_STRING || value->format != 8)
1516209ff23fSmrg	    return FALSE;
1517209ff23fSmrg	s = (char*)value->data;
1518209ff23fSmrg	if (value->size == strlen("bios") && !strncmp("bios", s, strlen("bios"))) {
1519b7e1c893Smrg	    if (!RADEONGetTMDSInfoFromBIOS(output->scrn, tmds))
1520b7e1c893Smrg		RADEONGetTMDSInfoFromTable(output->scrn, tmds);
1521b7e1c893Smrg	} else if (value->size == strlen("driver") && !strncmp("driver", s, strlen("driver")))
1522b7e1c893Smrg	    RADEONGetTMDSInfoFromTable(output->scrn, tmds);
1523b7e1c893Smrg	else
1524209ff23fSmrg	    return FALSE;
1525209ff23fSmrg
1526209ff23fSmrg	return radeon_set_mode_for_property(output);
1527209ff23fSmrg    } else if (property == monitor_type_atom) {
1528209ff23fSmrg	const char *s;
1529209ff23fSmrg	if (value->type != XA_STRING || value->format != 8)
1530209ff23fSmrg	    return FALSE;
1531209ff23fSmrg	s = (char*)value->data;
1532209ff23fSmrg	if (value->size == strlen("auto") && !strncmp("auto", s, strlen("auto"))) {
1533209ff23fSmrg	    radeon_output->DVIType = DVI_AUTO;
1534209ff23fSmrg	    return TRUE;
1535209ff23fSmrg	} else if (value->size == strlen("analog") && !strncmp("analog", s, strlen("analog"))) {
1536209ff23fSmrg	    radeon_output->DVIType = DVI_ANALOG;
1537209ff23fSmrg	    return TRUE;
1538209ff23fSmrg	} else if (value->size == strlen("digital") && !strncmp("digital", s, strlen("digital"))) {
1539209ff23fSmrg	    radeon_output->DVIType = DVI_DIGITAL;
1540209ff23fSmrg	    return TRUE;
1541209ff23fSmrg	} else
1542209ff23fSmrg	    return FALSE;
1543209ff23fSmrg    } else if (property == tv_hsize_atom) {
1544b7e1c893Smrg	radeon_tvout_ptr tvout = &radeon_output->tvout;
1545209ff23fSmrg	if (value->type != XA_INTEGER ||
1546209ff23fSmrg	    value->format != 32 ||
1547209ff23fSmrg	    value->size != 1) {
1548209ff23fSmrg	    return FALSE;
1549209ff23fSmrg	}
1550209ff23fSmrg
1551209ff23fSmrg	val = *(INT32 *)value->data;
1552209ff23fSmrg	if (val < -MAX_H_SIZE || val > MAX_H_SIZE)
1553209ff23fSmrg	    return FALSE;
1554209ff23fSmrg
1555b7e1c893Smrg	tvout->hSize = val;
1556b7e1c893Smrg	if (tvout->tv_on && !IS_AVIVO_VARIANT)
1557209ff23fSmrg	    RADEONUpdateHVPosition(output, &output->crtc->mode);
1558209ff23fSmrg
1559209ff23fSmrg    } else if (property == tv_hpos_atom) {
1560b7e1c893Smrg	radeon_tvout_ptr tvout = &radeon_output->tvout;
1561209ff23fSmrg	if (value->type != XA_INTEGER ||
1562209ff23fSmrg	    value->format != 32 ||
1563209ff23fSmrg	    value->size != 1) {
1564209ff23fSmrg	    return FALSE;
1565209ff23fSmrg	}
1566209ff23fSmrg
1567209ff23fSmrg	val = *(INT32 *)value->data;
1568209ff23fSmrg	if (val < -MAX_H_POSITION || val > MAX_H_POSITION)
1569209ff23fSmrg	    return FALSE;
1570209ff23fSmrg
1571b7e1c893Smrg	tvout->hPos = val;
1572b7e1c893Smrg	if (tvout->tv_on && !IS_AVIVO_VARIANT)
1573209ff23fSmrg	    RADEONUpdateHVPosition(output, &output->crtc->mode);
1574209ff23fSmrg
1575209ff23fSmrg    } else if (property == tv_vpos_atom) {
1576b7e1c893Smrg	radeon_tvout_ptr tvout = &radeon_output->tvout;
1577209ff23fSmrg	if (value->type != XA_INTEGER ||
1578209ff23fSmrg	    value->format != 32 ||
1579209ff23fSmrg	    value->size != 1) {
1580209ff23fSmrg	    return FALSE;
1581209ff23fSmrg	}
1582209ff23fSmrg
1583209ff23fSmrg	val = *(INT32 *)value->data;
1584209ff23fSmrg	if (val < -MAX_H_POSITION || val > MAX_H_POSITION)
1585209ff23fSmrg	    return FALSE;
1586209ff23fSmrg
1587b7e1c893Smrg	tvout->vPos = val;
1588b7e1c893Smrg	if (tvout->tv_on && !IS_AVIVO_VARIANT)
1589209ff23fSmrg	    RADEONUpdateHVPosition(output, &output->crtc->mode);
1590209ff23fSmrg
1591209ff23fSmrg    } else if (property == tv_std_atom) {
1592209ff23fSmrg	const char *s;
1593b7e1c893Smrg	radeon_tvout_ptr tvout = &radeon_output->tvout;
1594b7e1c893Smrg	TVStd std = tvout->tvStd;
1595209ff23fSmrg
1596209ff23fSmrg	if (value->type != XA_STRING || value->format != 8)
1597209ff23fSmrg	    return FALSE;
1598209ff23fSmrg	s = (char*)value->data;
1599209ff23fSmrg	if (value->size == strlen("ntsc") && !strncmp("ntsc", s, strlen("ntsc"))) {
1600b7e1c893Smrg	    tvout->tvStd = TV_STD_NTSC;
1601209ff23fSmrg	} else if (value->size == strlen("pal") && !strncmp("pal", s, strlen("pal"))) {
1602b7e1c893Smrg	    tvout->tvStd = TV_STD_PAL;
1603209ff23fSmrg	} else if (value->size == strlen("pal-m") && !strncmp("pal-m", s, strlen("pal-m"))) {
1604b7e1c893Smrg	    tvout->tvStd = TV_STD_PAL_M;
1605209ff23fSmrg	} else if (value->size == strlen("pal-60") && !strncmp("pal-60", s, strlen("pal-60"))) {
1606b7e1c893Smrg	    tvout->tvStd = TV_STD_PAL_60;
1607209ff23fSmrg	} else if (value->size == strlen("ntsc-j") && !strncmp("ntsc-j", s, strlen("ntsc-j"))) {
1608b7e1c893Smrg	    tvout->tvStd = TV_STD_NTSC_J;
1609209ff23fSmrg	} else if (value->size == strlen("scart-pal") && !strncmp("scart-pal", s, strlen("scart-pal"))) {
1610b7e1c893Smrg	    tvout->tvStd = TV_STD_SCART_PAL;
1611209ff23fSmrg	} else if (value->size == strlen("pal-cn") && !strncmp("pal-cn", s, strlen("pal-cn"))) {
1612b7e1c893Smrg	    tvout->tvStd = TV_STD_PAL_CN;
1613209ff23fSmrg	} else if (value->size == strlen("secam") && !strncmp("secam", s, strlen("secam"))) {
1614b7e1c893Smrg	    tvout->tvStd = TV_STD_SECAM;
1615209ff23fSmrg	} else
1616209ff23fSmrg	    return FALSE;
1617209ff23fSmrg
1618209ff23fSmrg	if (!radeon_set_mode_for_property(output)) {
1619b7e1c893Smrg	    tvout->tvStd = std;
1620209ff23fSmrg	    (void)radeon_set_mode_for_property(output);
1621209ff23fSmrg	    return FALSE;
1622209ff23fSmrg	}
1623209ff23fSmrg    }
1624209ff23fSmrg
1625209ff23fSmrg    return TRUE;
1626209ff23fSmrg}
1627209ff23fSmrg
1628209ff23fSmrgstatic const xf86OutputFuncsRec radeon_output_funcs = {
1629209ff23fSmrg    .create_resources = radeon_create_resources,
1630209ff23fSmrg    .dpms = radeon_dpms,
1631209ff23fSmrg    .save = radeon_save,
1632209ff23fSmrg    .restore = radeon_restore,
1633209ff23fSmrg    .mode_valid = radeon_mode_valid,
1634209ff23fSmrg    .mode_fixup = radeon_mode_fixup,
1635209ff23fSmrg    .prepare = radeon_mode_prepare,
1636209ff23fSmrg    .mode_set = radeon_mode_set,
1637209ff23fSmrg    .commit = radeon_mode_commit,
1638209ff23fSmrg    .detect = radeon_detect,
1639209ff23fSmrg    .get_modes = radeon_get_modes,
1640209ff23fSmrg    .set_property = radeon_set_property,
1641209ff23fSmrg    .destroy = radeon_destroy
1642209ff23fSmrg};
1643209ff23fSmrg
1644b7e1c893SmrgBool
1645c503f109SmrgRADEONI2CDoLock(xf86OutputPtr output, I2CBusPtr b, int lock_state)
1646209ff23fSmrg{
1647209ff23fSmrg    ScrnInfoPtr pScrn = output->scrn;
1648209ff23fSmrg    RADEONInfoPtr  info       = RADEONPTR(pScrn);
1649c503f109Smrg    RADEONI2CBusPtr pRADEONI2CBus = b->DriverPrivate.ptr;
1650209ff23fSmrg    unsigned char *RADEONMMIO = info->MMIO;
1651209ff23fSmrg    uint32_t temp;
1652209ff23fSmrg
1653b7e1c893Smrg    if (lock_state) {
1654c503f109Smrg	/* RV410 appears to have a bug where the hw i2c in reset
1655c503f109Smrg	 * holds the i2c port in a bad state - switch hw i2c away before
1656c503f109Smrg	 * doing DDC - do this for all r200s/r300s for safety sakes */
1657c503f109Smrg	if ((info->ChipFamily >= CHIP_FAMILY_R200) && (!IS_AVIVO_VARIANT)) {
1658c503f109Smrg	    if (pRADEONI2CBus->mask_clk_reg == RADEON_GPIO_MONID)
1659c503f109Smrg                OUTREG(RADEON_DVI_I2C_CNTL_0, (RADEON_I2C_SOFT_RST |
1660c503f109Smrg					       R200_DVI_I2C_PIN_SEL(R200_SEL_DDC1)));
1661c503f109Smrg	    else
1662c503f109Smrg                OUTREG(RADEON_DVI_I2C_CNTL_0, (RADEON_I2C_SOFT_RST |
1663c503f109Smrg					       R200_DVI_I2C_PIN_SEL(R200_SEL_DDC3)));
1664c503f109Smrg	}
1665c503f109Smrg
1666b7e1c893Smrg	temp = INREG(pRADEONI2CBus->a_clk_reg);
1667b7e1c893Smrg	temp &= ~(pRADEONI2CBus->a_clk_mask);
1668b7e1c893Smrg	OUTREG(pRADEONI2CBus->a_clk_reg, temp);
1669b7e1c893Smrg
1670b7e1c893Smrg	temp = INREG(pRADEONI2CBus->a_data_reg);
1671b7e1c893Smrg	temp &= ~(pRADEONI2CBus->a_data_mask);
1672b7e1c893Smrg	OUTREG(pRADEONI2CBus->a_data_reg, temp);
1673b7e1c893Smrg    }
1674b7e1c893Smrg
1675209ff23fSmrg    temp = INREG(pRADEONI2CBus->mask_clk_reg);
1676b7e1c893Smrg    if (lock_state)
1677b7e1c893Smrg	temp |= (pRADEONI2CBus->mask_clk_mask);
1678209ff23fSmrg    else
1679b7e1c893Smrg	temp &= ~(pRADEONI2CBus->mask_clk_mask);
1680209ff23fSmrg    OUTREG(pRADEONI2CBus->mask_clk_reg, temp);
1681209ff23fSmrg    temp = INREG(pRADEONI2CBus->mask_clk_reg);
1682209ff23fSmrg
1683209ff23fSmrg    temp = INREG(pRADEONI2CBus->mask_data_reg);
1684b7e1c893Smrg    if (lock_state)
1685b7e1c893Smrg	temp |= (pRADEONI2CBus->mask_data_mask);
1686209ff23fSmrg    else
1687b7e1c893Smrg	temp &= ~(pRADEONI2CBus->mask_data_mask);
1688209ff23fSmrg    OUTREG(pRADEONI2CBus->mask_data_reg, temp);
1689209ff23fSmrg    temp = INREG(pRADEONI2CBus->mask_data_reg);
1690209ff23fSmrg
1691209ff23fSmrg    return TRUE;
1692209ff23fSmrg}
1693209ff23fSmrg
1694209ff23fSmrgstatic void RADEONI2CGetBits(I2CBusPtr b, int *Clock, int *data)
1695209ff23fSmrg{
1696209ff23fSmrg    ScrnInfoPtr    pScrn      = xf86Screens[b->scrnIndex];
1697209ff23fSmrg    RADEONInfoPtr  info       = RADEONPTR(pScrn);
1698209ff23fSmrg    unsigned long  val;
1699209ff23fSmrg    unsigned char *RADEONMMIO = info->MMIO;
1700209ff23fSmrg    RADEONI2CBusPtr pRADEONI2CBus = b->DriverPrivate.ptr;
1701209ff23fSmrg
1702209ff23fSmrg    /* Get the result */
1703209ff23fSmrg    val = INREG(pRADEONI2CBus->get_clk_reg);
1704209ff23fSmrg    *Clock = (val & pRADEONI2CBus->get_clk_mask) != 0;
1705209ff23fSmrg    val = INREG(pRADEONI2CBus->get_data_reg);
1706209ff23fSmrg    *data  = (val & pRADEONI2CBus->get_data_mask) != 0;
1707209ff23fSmrg
1708209ff23fSmrg}
1709209ff23fSmrg
1710209ff23fSmrgstatic void RADEONI2CPutBits(I2CBusPtr b, int Clock, int data)
1711209ff23fSmrg{
1712209ff23fSmrg    ScrnInfoPtr    pScrn      = xf86Screens[b->scrnIndex];
1713209ff23fSmrg    RADEONInfoPtr  info       = RADEONPTR(pScrn);
1714209ff23fSmrg    unsigned long  val;
1715209ff23fSmrg    unsigned char *RADEONMMIO = info->MMIO;
1716209ff23fSmrg    RADEONI2CBusPtr pRADEONI2CBus = b->DriverPrivate.ptr;
1717209ff23fSmrg
1718209ff23fSmrg    val = INREG(pRADEONI2CBus->put_clk_reg) & (uint32_t)~(pRADEONI2CBus->put_clk_mask);
1719209ff23fSmrg    val |= (Clock ? 0:pRADEONI2CBus->put_clk_mask);
1720209ff23fSmrg    OUTREG(pRADEONI2CBus->put_clk_reg, val);
1721209ff23fSmrg    /* read back to improve reliability on some cards. */
1722209ff23fSmrg    val = INREG(pRADEONI2CBus->put_clk_reg);
1723209ff23fSmrg
1724209ff23fSmrg    val = INREG(pRADEONI2CBus->put_data_reg) & (uint32_t)~(pRADEONI2CBus->put_data_mask);
1725209ff23fSmrg    val |= (data ? 0:pRADEONI2CBus->put_data_mask);
1726209ff23fSmrg    OUTREG(pRADEONI2CBus->put_data_reg, val);
1727209ff23fSmrg    /* read back to improve reliability on some cards. */
1728209ff23fSmrg    val = INREG(pRADEONI2CBus->put_data_reg);
1729209ff23fSmrg
1730209ff23fSmrg}
1731209ff23fSmrg
1732b7e1c893SmrgBool
1733b7e1c893SmrgRADEONI2CInit(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr, char *name, RADEONI2CBusPtr pRADEONI2CBus)
1734209ff23fSmrg{
1735209ff23fSmrg    I2CBusPtr pI2CBus;
1736209ff23fSmrg
1737209ff23fSmrg    pI2CBus = xf86CreateI2CBusRec();
1738209ff23fSmrg    if (!pI2CBus) return FALSE;
1739209ff23fSmrg
1740209ff23fSmrg    pI2CBus->BusName    = name;
1741209ff23fSmrg    pI2CBus->scrnIndex  = pScrn->scrnIndex;
1742209ff23fSmrg    pI2CBus->I2CPutBits = RADEONI2CPutBits;
1743209ff23fSmrg    pI2CBus->I2CGetBits = RADEONI2CGetBits;
1744b7e1c893Smrg    pI2CBus->AcknTimeout = 5;
1745209ff23fSmrg
1746b7e1c893Smrg    pI2CBus->DriverPrivate.ptr = (pointer)pRADEONI2CBus;
1747209ff23fSmrg
1748b7e1c893Smrg    if (!xf86I2CBusInit(pI2CBus))
1749b7e1c893Smrg	return FALSE;
1750209ff23fSmrg
1751b7e1c893Smrg    *bus_ptr = pI2CBus;
1752209ff23fSmrg    return TRUE;
1753209ff23fSmrg}
1754209ff23fSmrg
1755b7e1c893SmrgRADEONI2CBusRec
1756b7e1c893Smrglegacy_setup_i2c_bus(int ddc_line)
1757209ff23fSmrg{
1758b7e1c893Smrg    RADEONI2CBusRec i2c;
1759209ff23fSmrg
1760b7e1c893Smrg    i2c.hw_line = 0;
1761b7e1c893Smrg    i2c.hw_capable = FALSE;
1762b7e1c893Smrg    i2c.mask_clk_mask = RADEON_GPIO_EN_1;
1763b7e1c893Smrg    i2c.mask_data_mask = RADEON_GPIO_EN_0;
1764b7e1c893Smrg    i2c.a_clk_mask = RADEON_GPIO_A_1;
1765b7e1c893Smrg    i2c.a_data_mask = RADEON_GPIO_A_0;
1766b7e1c893Smrg    i2c.put_clk_mask = RADEON_GPIO_EN_1;
1767b7e1c893Smrg    i2c.put_data_mask = RADEON_GPIO_EN_0;
1768b7e1c893Smrg    i2c.get_clk_mask = RADEON_GPIO_Y_1;
1769b7e1c893Smrg    i2c.get_data_mask = RADEON_GPIO_Y_0;
1770b7e1c893Smrg    if ((ddc_line == RADEON_LCD_GPIO_MASK) ||
1771b7e1c893Smrg	(ddc_line == RADEON_MDGPIO_EN_REG)) {
1772b7e1c893Smrg	i2c.mask_clk_reg = ddc_line;
1773b7e1c893Smrg	i2c.mask_data_reg = ddc_line;
1774b7e1c893Smrg	i2c.a_clk_reg = ddc_line;
1775b7e1c893Smrg	i2c.a_data_reg = ddc_line;
1776b7e1c893Smrg	i2c.put_clk_reg = ddc_line;
1777b7e1c893Smrg	i2c.put_data_reg = ddc_line;
1778b7e1c893Smrg	i2c.get_clk_reg = ddc_line + 4;
1779b7e1c893Smrg	i2c.get_data_reg = ddc_line + 4;
1780b7e1c893Smrg    } else {
1781b7e1c893Smrg	i2c.mask_clk_reg = ddc_line;
1782b7e1c893Smrg	i2c.mask_data_reg = ddc_line;
1783b7e1c893Smrg	i2c.a_clk_reg = ddc_line;
1784b7e1c893Smrg	i2c.a_data_reg = ddc_line;
1785b7e1c893Smrg	i2c.put_clk_reg = ddc_line;
1786b7e1c893Smrg	i2c.put_data_reg = ddc_line;
1787b7e1c893Smrg	i2c.get_clk_reg = ddc_line;
1788b7e1c893Smrg	i2c.get_data_reg = ddc_line;
1789209ff23fSmrg    }
1790b7e1c893Smrg
1791b7e1c893Smrg    if (ddc_line)
1792b7e1c893Smrg	i2c.valid = TRUE;
1793b7e1c893Smrg    else
1794b7e1c893Smrg	i2c.valid = FALSE;
1795b7e1c893Smrg
1796b7e1c893Smrg    return i2c;
1797209ff23fSmrg}
1798209ff23fSmrg
1799b7e1c893SmrgRADEONI2CBusRec
1800b7e1c893Smrgatom_setup_i2c_bus(int ddc_line)
1801209ff23fSmrg{
1802b7e1c893Smrg    RADEONI2CBusRec i2c;
1803209ff23fSmrg
1804b7e1c893Smrg    i2c.hw_line = 0;
1805b7e1c893Smrg    i2c.hw_capable = FALSE;
1806b7e1c893Smrg    if (ddc_line == AVIVO_GPIO_0) {
1807b7e1c893Smrg	i2c.put_clk_mask = (1 << 19);
1808b7e1c893Smrg	i2c.put_data_mask = (1 << 18);
1809b7e1c893Smrg	i2c.get_clk_mask = (1 << 19);
1810b7e1c893Smrg	i2c.get_data_mask = (1 << 18);
1811b7e1c893Smrg	i2c.mask_clk_mask = (1 << 19);
1812b7e1c893Smrg	i2c.mask_data_mask = (1 << 18);
1813b7e1c893Smrg	i2c.a_clk_mask = (1 << 19);
1814b7e1c893Smrg	i2c.a_data_mask = (1 << 18);
1815b7e1c893Smrg    } else {
1816b7e1c893Smrg	i2c.put_clk_mask = (1 << 0);
1817b7e1c893Smrg	i2c.put_data_mask = (1 << 8);
1818b7e1c893Smrg	i2c.get_clk_mask = (1 << 0);
1819b7e1c893Smrg	i2c.get_data_mask = (1 << 8);
1820b7e1c893Smrg	i2c.mask_clk_mask = (1 << 0);
1821b7e1c893Smrg	i2c.mask_data_mask = (1 << 8);
1822b7e1c893Smrg	i2c.a_clk_mask = (1 << 0);
1823b7e1c893Smrg	i2c.a_data_mask = (1 << 8);
1824209ff23fSmrg    }
1825b7e1c893Smrg    i2c.mask_clk_reg = ddc_line;
1826b7e1c893Smrg    i2c.mask_data_reg = ddc_line;
1827b7e1c893Smrg    i2c.a_clk_reg = ddc_line + 0x4;
1828b7e1c893Smrg    i2c.a_data_reg = ddc_line + 0x4;
1829b7e1c893Smrg    i2c.put_clk_reg = ddc_line + 0x8;
1830b7e1c893Smrg    i2c.put_data_reg = ddc_line + 0x8;
1831b7e1c893Smrg    i2c.get_clk_reg = ddc_line + 0xc;
1832b7e1c893Smrg    i2c.get_data_reg = ddc_line + 0xc;
1833b7e1c893Smrg    if (ddc_line)
1834b7e1c893Smrg	i2c.valid = TRUE;
1835b7e1c893Smrg    else
1836b7e1c893Smrg	i2c.valid = FALSE;
1837209ff23fSmrg
1838b7e1c893Smrg    return i2c;
1839209ff23fSmrg}
1840209ff23fSmrg
1841209ff23fSmrgstatic void
1842209ff23fSmrgRADEONGetTVInfo(xf86OutputPtr output)
1843209ff23fSmrg{
1844209ff23fSmrg    ScrnInfoPtr pScrn = output->scrn;
1845209ff23fSmrg    RADEONInfoPtr  info       = RADEONPTR(pScrn);
1846209ff23fSmrg    RADEONOutputPrivatePtr radeon_output = output->driver_private;
1847b7e1c893Smrg    radeon_tvout_ptr tvout = &radeon_output->tvout;
1848209ff23fSmrg    char *optstr;
1849209ff23fSmrg
1850b7e1c893Smrg    tvout->hPos = 0;
1851b7e1c893Smrg    tvout->vPos = 0;
1852b7e1c893Smrg    tvout->hSize = 0;
1853b7e1c893Smrg    tvout->tv_on = FALSE;
1854209ff23fSmrg
1855209ff23fSmrg    if (!RADEONGetTVInfoFromBIOS(output)) {
1856209ff23fSmrg	/* set some reasonable defaults */
1857b7e1c893Smrg	tvout->default_tvStd = TV_STD_NTSC;
1858b7e1c893Smrg	tvout->tvStd = TV_STD_NTSC;
1859b7e1c893Smrg	tvout->TVRefClk = 27.000000000;
1860b7e1c893Smrg	tvout->SupportedTVStds = TV_STD_NTSC | TV_STD_PAL;
1861209ff23fSmrg    }
1862209ff23fSmrg
1863209ff23fSmrg    optstr = (char *)xf86GetOptValString(info->Options, OPTION_TVSTD);
1864209ff23fSmrg    if (optstr) {
1865209ff23fSmrg	if (!strncmp("ntsc", optstr, strlen("ntsc")))
1866b7e1c893Smrg	    tvout->tvStd = TV_STD_NTSC;
1867209ff23fSmrg	else if (!strncmp("pal", optstr, strlen("pal")))
1868b7e1c893Smrg	    tvout->tvStd = TV_STD_PAL;
1869209ff23fSmrg	else if (!strncmp("pal-m", optstr, strlen("pal-m")))
1870b7e1c893Smrg	    tvout->tvStd = TV_STD_PAL_M;
1871209ff23fSmrg	else if (!strncmp("pal-60", optstr, strlen("pal-60")))
1872b7e1c893Smrg	    tvout->tvStd = TV_STD_PAL_60;
1873209ff23fSmrg	else if (!strncmp("ntsc-j", optstr, strlen("ntsc-j")))
1874b7e1c893Smrg	    tvout->tvStd = TV_STD_NTSC_J;
1875209ff23fSmrg	else if (!strncmp("scart-pal", optstr, strlen("scart-pal")))
1876b7e1c893Smrg	    tvout->tvStd = TV_STD_SCART_PAL;
1877209ff23fSmrg	else {
1878209ff23fSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Invalid TV Standard: %s\n", optstr);
1879209ff23fSmrg	}
1880209ff23fSmrg    }
1881209ff23fSmrg
1882209ff23fSmrg}
1883209ff23fSmrg
1884209ff23fSmrgvoid RADEONInitConnector(xf86OutputPtr output)
1885209ff23fSmrg{
1886209ff23fSmrg    ScrnInfoPtr	    pScrn = output->scrn;
1887209ff23fSmrg    RADEONInfoPtr  info       = RADEONPTR(pScrn);
1888209ff23fSmrg    RADEONOutputPrivatePtr radeon_output = output->driver_private;
1889209ff23fSmrg
1890b7e1c893Smrg    if (radeon_output->devices & (ATOM_DEVICE_LCD_SUPPORT))
1891b7e1c893Smrg	radeon_output->rmx_type = RMX_FULL;
1892209ff23fSmrg    else
1893b7e1c893Smrg	radeon_output->rmx_type = RMX_OFF;
1894209ff23fSmrg
1895b7e1c893Smrg    /* dce 3.2 chips have problems with low dot clocks, so use the scaler */
1896b7e1c893Smrg    if (IS_DCE32_VARIANT && (radeon_output->devices & (ATOM_DEVICE_DFP_SUPPORT)))
1897209ff23fSmrg	radeon_output->rmx_type = RMX_FULL;
1898209ff23fSmrg
1899b7e1c893Smrg    if (!IS_AVIVO_VARIANT) {
1900b7e1c893Smrg	if (radeon_output->devices & (ATOM_DEVICE_CRT2_SUPPORT)) {
1901b7e1c893Smrg	    if (xf86ReturnOptValBool(info->Options, OPTION_TVDAC_LOAD_DETECT, FALSE))
1902b7e1c893Smrg		radeon_output->load_detection = 1;
1903b7e1c893Smrg	}
1904209ff23fSmrg    }
1905209ff23fSmrg
1906b7e1c893Smrg    if (radeon_output->devices & (ATOM_DEVICE_TV_SUPPORT))
1907209ff23fSmrg	RADEONGetTVInfo(output);
1908209ff23fSmrg
1909b7e1c893Smrg    if (radeon_output->devices & (ATOM_DEVICE_DFP_SUPPORT))
1910209ff23fSmrg	radeon_output->coherent_mode = TRUE;
1911209ff23fSmrg
1912209ff23fSmrg    if (radeon_output->ddc_i2c.valid)
1913b7e1c893Smrg	RADEONI2CInit(pScrn, &radeon_output->pI2CBus, output->name, &radeon_output->ddc_i2c);
1914209ff23fSmrg
1915209ff23fSmrg}
1916209ff23fSmrg
1917209ff23fSmrg#if defined(__powerpc__)
1918209ff23fSmrgstatic Bool RADEONSetupAppleConnectors(ScrnInfoPtr pScrn)
1919209ff23fSmrg{
1920209ff23fSmrg    RADEONInfoPtr info       = RADEONPTR(pScrn);
1921209ff23fSmrg
1922209ff23fSmrg
1923209ff23fSmrg    switch (info->MacModel) {
1924209ff23fSmrg    case RADEON_MAC_IBOOK:
1925209ff23fSmrg	info->BiosConnector[0].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_DVI_DDC);
1926209ff23fSmrg	info->BiosConnector[0].ConnectorType = CONNECTOR_LVDS;
1927209ff23fSmrg	info->BiosConnector[0].valid = TRUE;
1928b7e1c893Smrg	info->BiosConnector[0].devices = ATOM_DEVICE_LCD1_SUPPORT;
1929b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
1930b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
1931b7e1c893Smrg									    ATOM_DEVICE_LCD1_SUPPORT,
1932b7e1c893Smrg									    0),
1933b7e1c893Smrg				ATOM_DEVICE_LCD1_SUPPORT))
1934b7e1c893Smrg	    return FALSE;
1935209ff23fSmrg
1936209ff23fSmrg	info->BiosConnector[1].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
1937b7e1c893Smrg	info->BiosConnector[1].load_detection = FALSE;
1938209ff23fSmrg	info->BiosConnector[1].ConnectorType = CONNECTOR_VGA;
1939209ff23fSmrg	info->BiosConnector[1].valid = TRUE;
1940b7e1c893Smrg	info->BiosConnector[1].devices = ATOM_DEVICE_CRT2_SUPPORT;
1941b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
1942b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
1943b7e1c893Smrg									    ATOM_DEVICE_CRT2_SUPPORT,
1944b7e1c893Smrg									    2),
1945b7e1c893Smrg				ATOM_DEVICE_CRT2_SUPPORT))
1946b7e1c893Smrg	    return FALSE;
1947209ff23fSmrg
1948209ff23fSmrg	info->BiosConnector[2].ConnectorType = CONNECTOR_STV;
1949b7e1c893Smrg	info->BiosConnector[2].load_detection = FALSE;
1950209ff23fSmrg	info->BiosConnector[2].ddc_i2c.valid = FALSE;
1951209ff23fSmrg	info->BiosConnector[2].valid = TRUE;
1952b7e1c893Smrg	info->BiosConnector[2].devices = ATOM_DEVICE_TV1_SUPPORT;
1953b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
1954b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
1955b7e1c893Smrg									    ATOM_DEVICE_TV1_SUPPORT,
1956b7e1c893Smrg									    2),
1957b7e1c893Smrg				ATOM_DEVICE_TV1_SUPPORT))
1958b7e1c893Smrg	    return FALSE;
1959209ff23fSmrg	return TRUE;
1960209ff23fSmrg    case RADEON_MAC_POWERBOOK_EXTERNAL:
1961209ff23fSmrg	info->BiosConnector[0].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_DVI_DDC);
1962209ff23fSmrg	info->BiosConnector[0].ConnectorType = CONNECTOR_LVDS;
1963209ff23fSmrg	info->BiosConnector[0].valid = TRUE;
1964b7e1c893Smrg	info->BiosConnector[0].devices = ATOM_DEVICE_LCD1_SUPPORT;
1965b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
1966b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
1967b7e1c893Smrg									    ATOM_DEVICE_LCD1_SUPPORT,
1968b7e1c893Smrg									    0),
1969b7e1c893Smrg				ATOM_DEVICE_LCD1_SUPPORT))
1970b7e1c893Smrg	    return FALSE;
1971209ff23fSmrg
1972209ff23fSmrg	info->BiosConnector[1].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
1973209ff23fSmrg	info->BiosConnector[1].ConnectorType = CONNECTOR_DVI_I;
1974209ff23fSmrg	info->BiosConnector[1].valid = TRUE;
1975b7e1c893Smrg	info->BiosConnector[1].devices = ATOM_DEVICE_CRT1_SUPPORT | ATOM_DEVICE_DFP2_SUPPORT;
1976b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
1977b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
1978b7e1c893Smrg									    ATOM_DEVICE_CRT1_SUPPORT,
1979b7e1c893Smrg									    1),
1980b7e1c893Smrg				ATOM_DEVICE_CRT1_SUPPORT))
1981b7e1c893Smrg	    return FALSE;
1982b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
1983b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
1984b7e1c893Smrg									    ATOM_DEVICE_DFP2_SUPPORT,
1985b7e1c893Smrg									    0),
1986b7e1c893Smrg				ATOM_DEVICE_DFP2_SUPPORT))
1987b7e1c893Smrg	    return FALSE;
1988209ff23fSmrg
1989209ff23fSmrg	info->BiosConnector[2].ConnectorType = CONNECTOR_STV;
1990b7e1c893Smrg	info->BiosConnector[2].load_detection = FALSE;
1991209ff23fSmrg	info->BiosConnector[2].ddc_i2c.valid = FALSE;
1992209ff23fSmrg	info->BiosConnector[2].valid = TRUE;
1993b7e1c893Smrg	info->BiosConnector[2].devices = ATOM_DEVICE_TV1_SUPPORT;
1994b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
1995b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
1996b7e1c893Smrg									    ATOM_DEVICE_TV1_SUPPORT,
1997b7e1c893Smrg									    2),
1998b7e1c893Smrg				ATOM_DEVICE_TV1_SUPPORT))
1999b7e1c893Smrg	    return FALSE;
2000209ff23fSmrg	return TRUE;
2001209ff23fSmrg    case RADEON_MAC_POWERBOOK_INTERNAL:
2002209ff23fSmrg	info->BiosConnector[0].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_DVI_DDC);
2003209ff23fSmrg	info->BiosConnector[0].ConnectorType = CONNECTOR_LVDS;
2004209ff23fSmrg	info->BiosConnector[0].valid = TRUE;
2005b7e1c893Smrg	info->BiosConnector[0].devices = ATOM_DEVICE_LCD1_SUPPORT;
2006b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
2007b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
2008b7e1c893Smrg									    ATOM_DEVICE_LCD1_SUPPORT,
2009b7e1c893Smrg									    0),
2010b7e1c893Smrg				ATOM_DEVICE_LCD1_SUPPORT))
2011b7e1c893Smrg	    return FALSE;
2012209ff23fSmrg
2013209ff23fSmrg	info->BiosConnector[1].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
2014209ff23fSmrg	info->BiosConnector[1].ConnectorType = CONNECTOR_DVI_I;
2015209ff23fSmrg	info->BiosConnector[1].valid = TRUE;
2016b7e1c893Smrg	info->BiosConnector[1].devices = ATOM_DEVICE_CRT1_SUPPORT | ATOM_DEVICE_DFP1_SUPPORT;
2017b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
2018b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
2019b7e1c893Smrg									    ATOM_DEVICE_CRT1_SUPPORT,
2020b7e1c893Smrg									    1),
2021b7e1c893Smrg				ATOM_DEVICE_CRT1_SUPPORT))
2022b7e1c893Smrg	    return FALSE;
2023b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
2024b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
2025b7e1c893Smrg									    ATOM_DEVICE_DFP1_SUPPORT,
2026b7e1c893Smrg									    0),
2027b7e1c893Smrg				ATOM_DEVICE_DFP1_SUPPORT))
2028b7e1c893Smrg	    return FALSE;
2029209ff23fSmrg
2030209ff23fSmrg	info->BiosConnector[2].ConnectorType = CONNECTOR_STV;
2031b7e1c893Smrg	info->BiosConnector[2].load_detection = FALSE;
2032209ff23fSmrg	info->BiosConnector[2].ddc_i2c.valid = FALSE;
2033209ff23fSmrg	info->BiosConnector[2].valid = TRUE;
2034b7e1c893Smrg	info->BiosConnector[2].devices = ATOM_DEVICE_TV1_SUPPORT;
2035b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
2036b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
2037b7e1c893Smrg									    ATOM_DEVICE_TV1_SUPPORT,
2038b7e1c893Smrg									    2),
2039b7e1c893Smrg				ATOM_DEVICE_TV1_SUPPORT))
2040b7e1c893Smrg	    return FALSE;
2041209ff23fSmrg	return TRUE;
2042209ff23fSmrg    case RADEON_MAC_POWERBOOK_VGA:
2043209ff23fSmrg	info->BiosConnector[0].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_DVI_DDC);
2044b7e1c893Smrg	info->BiosConnector[0].ConnectorType = CONNECTOR_LVDS;
2045209ff23fSmrg	info->BiosConnector[0].valid = TRUE;
2046b7e1c893Smrg	info->BiosConnector[0].devices = ATOM_DEVICE_LCD1_SUPPORT;
2047b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
2048b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
2049b7e1c893Smrg									    ATOM_DEVICE_LCD1_SUPPORT,
2050b7e1c893Smrg									    0),
2051b7e1c893Smrg				ATOM_DEVICE_LCD1_SUPPORT))
2052b7e1c893Smrg	    return FALSE;
2053209ff23fSmrg
2054209ff23fSmrg	info->BiosConnector[1].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
2055b7e1c893Smrg	info->BiosConnector[1].ConnectorType = CONNECTOR_VGA;
2056209ff23fSmrg	info->BiosConnector[1].valid = TRUE;
2057b7e1c893Smrg	info->BiosConnector[1].devices = ATOM_DEVICE_CRT1_SUPPORT;
2058b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
2059b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
2060b7e1c893Smrg									    ATOM_DEVICE_CRT1_SUPPORT,
2061b7e1c893Smrg									    1),
2062b7e1c893Smrg				ATOM_DEVICE_CRT1_SUPPORT))
2063b7e1c893Smrg	    return FALSE;
2064209ff23fSmrg
2065209ff23fSmrg	info->BiosConnector[2].ConnectorType = CONNECTOR_STV;
2066b7e1c893Smrg	info->BiosConnector[2].load_detection = FALSE;
2067209ff23fSmrg	info->BiosConnector[2].ddc_i2c.valid = FALSE;
2068209ff23fSmrg	info->BiosConnector[2].valid = TRUE;
2069b7e1c893Smrg	info->BiosConnector[2].devices = ATOM_DEVICE_TV1_SUPPORT;
2070b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
2071b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
2072b7e1c893Smrg									    ATOM_DEVICE_TV1_SUPPORT,
2073b7e1c893Smrg									    2),
2074b7e1c893Smrg				ATOM_DEVICE_TV1_SUPPORT))
2075b7e1c893Smrg	    return FALSE;
2076209ff23fSmrg	return TRUE;
2077209ff23fSmrg    case RADEON_MAC_MINI_EXTERNAL:
2078209ff23fSmrg	info->BiosConnector[0].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_CRT2_DDC);
2079b7e1c893Smrg	info->BiosConnector[0].load_detection = FALSE;
2080209ff23fSmrg	info->BiosConnector[0].ConnectorType = CONNECTOR_DVI_I;
2081209ff23fSmrg	info->BiosConnector[0].valid = TRUE;
2082b7e1c893Smrg	info->BiosConnector[0].devices = ATOM_DEVICE_CRT2_SUPPORT | ATOM_DEVICE_DFP2_SUPPORT;
2083b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
2084b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
2085b7e1c893Smrg									    ATOM_DEVICE_CRT2_SUPPORT,
2086b7e1c893Smrg									    2),
2087b7e1c893Smrg				ATOM_DEVICE_CRT2_SUPPORT))
2088b7e1c893Smrg	    return FALSE;
2089b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
2090b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
2091b7e1c893Smrg									    ATOM_DEVICE_DFP2_SUPPORT,
2092b7e1c893Smrg									    0),
2093b7e1c893Smrg				ATOM_DEVICE_DFP2_SUPPORT))
2094b7e1c893Smrg	    return FALSE;
2095209ff23fSmrg
2096209ff23fSmrg	info->BiosConnector[1].ConnectorType = CONNECTOR_STV;
2097b7e1c893Smrg	info->BiosConnector[1].load_detection = FALSE;
2098209ff23fSmrg	info->BiosConnector[1].ddc_i2c.valid = FALSE;
2099209ff23fSmrg	info->BiosConnector[1].valid = TRUE;
2100b7e1c893Smrg	info->BiosConnector[1].devices = ATOM_DEVICE_TV1_SUPPORT;
2101b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
2102b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
2103b7e1c893Smrg									    ATOM_DEVICE_TV1_SUPPORT,
2104b7e1c893Smrg									    2),
2105b7e1c893Smrg				ATOM_DEVICE_TV1_SUPPORT))
2106b7e1c893Smrg	    return FALSE;
2107209ff23fSmrg	return TRUE;
2108209ff23fSmrg    case RADEON_MAC_MINI_INTERNAL:
2109209ff23fSmrg	info->BiosConnector[0].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_CRT2_DDC);
2110b7e1c893Smrg	info->BiosConnector[0].load_detection = FALSE;
2111209ff23fSmrg	info->BiosConnector[0].ConnectorType = CONNECTOR_DVI_I;
2112209ff23fSmrg	info->BiosConnector[0].valid = TRUE;
2113b7e1c893Smrg	info->BiosConnector[0].devices = ATOM_DEVICE_CRT2_SUPPORT | ATOM_DEVICE_DFP1_SUPPORT;
2114b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
2115b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
2116b7e1c893Smrg									    ATOM_DEVICE_CRT2_SUPPORT,
2117b7e1c893Smrg									    2),
2118b7e1c893Smrg				ATOM_DEVICE_CRT2_SUPPORT))
2119b7e1c893Smrg	    return FALSE;
2120b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
2121b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
2122b7e1c893Smrg									    ATOM_DEVICE_DFP1_SUPPORT,
2123b7e1c893Smrg									    0),
2124b7e1c893Smrg				ATOM_DEVICE_DFP1_SUPPORT))
2125b7e1c893Smrg	    return FALSE;
2126209ff23fSmrg
2127209ff23fSmrg	info->BiosConnector[1].ConnectorType = CONNECTOR_STV;
2128b7e1c893Smrg	info->BiosConnector[1].load_detection = FALSE;
2129209ff23fSmrg	info->BiosConnector[1].ddc_i2c.valid = FALSE;
2130209ff23fSmrg	info->BiosConnector[1].valid = TRUE;
2131b7e1c893Smrg	info->BiosConnector[1].devices = ATOM_DEVICE_TV1_SUPPORT;
2132b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
2133b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
2134b7e1c893Smrg									    ATOM_DEVICE_TV1_SUPPORT,
2135b7e1c893Smrg									    2),
2136b7e1c893Smrg				ATOM_DEVICE_TV1_SUPPORT))
2137b7e1c893Smrg	    return FALSE;
2138209ff23fSmrg	return TRUE;
2139209ff23fSmrg    case RADEON_MAC_IMAC_G5_ISIGHT:
2140209ff23fSmrg	info->BiosConnector[0].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_MONID);
2141209ff23fSmrg	info->BiosConnector[0].ConnectorType = CONNECTOR_DVI_D;
2142209ff23fSmrg	info->BiosConnector[0].valid = TRUE;
2143b7e1c893Smrg	info->BiosConnector[0].devices = ATOM_DEVICE_DFP1_SUPPORT;
2144b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
2145b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
2146b7e1c893Smrg									    ATOM_DEVICE_DFP1_SUPPORT,
2147b7e1c893Smrg									    0),
2148b7e1c893Smrg				ATOM_DEVICE_DFP1_SUPPORT))
2149b7e1c893Smrg	    return FALSE;
2150209ff23fSmrg
2151209ff23fSmrg	info->BiosConnector[1].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_DVI_DDC);
2152b7e1c893Smrg	info->BiosConnector[1].load_detection = FALSE;
2153b7e1c893Smrg	info->BiosConnector[1].ConnectorType = CONNECTOR_VGA;
2154b7e1c893Smrg	info->BiosConnector[1].valid = TRUE;
2155b7e1c893Smrg	info->BiosConnector[1].devices = ATOM_DEVICE_CRT2_SUPPORT;
2156b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
2157b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
2158b7e1c893Smrg									    ATOM_DEVICE_CRT2_SUPPORT,
2159b7e1c893Smrg									    2),
2160b7e1c893Smrg				ATOM_DEVICE_CRT2_SUPPORT))
2161b7e1c893Smrg	    return FALSE;
2162b7e1c893Smrg
2163b7e1c893Smrg	info->BiosConnector[2].ConnectorType = CONNECTOR_STV;
2164b7e1c893Smrg	info->BiosConnector[2].load_detection = FALSE;
2165b7e1c893Smrg	info->BiosConnector[2].ddc_i2c.valid = FALSE;
2166b7e1c893Smrg	info->BiosConnector[2].valid = TRUE;
2167b7e1c893Smrg	info->BiosConnector[2].devices = ATOM_DEVICE_TV1_SUPPORT;
2168b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
2169b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
2170b7e1c893Smrg									    ATOM_DEVICE_TV1_SUPPORT,
2171b7e1c893Smrg									    2),
2172b7e1c893Smrg				ATOM_DEVICE_TV1_SUPPORT))
2173b7e1c893Smrg	    return FALSE;
2174b7e1c893Smrg	return TRUE;
2175b7e1c893Smrg    case RADEON_MAC_EMAC:
2176b7e1c893Smrg	/* eMac G4 800/1.0 with radeon 7500, no EDID on internal monitor
2177b7e1c893Smrg	 * later eMac's (G4 1.25/1.42) with radeon 9200 and 9600 may have
2178b7e1c893Smrg	 * different ddc setups.  need to verify
2179b7e1c893Smrg	 */
2180b7e1c893Smrg	info->BiosConnector[0].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
2181b7e1c893Smrg	info->BiosConnector[0].ConnectorType = CONNECTOR_VGA;
2182b7e1c893Smrg	info->BiosConnector[0].valid = TRUE;
2183b7e1c893Smrg	info->BiosConnector[0].devices = ATOM_DEVICE_CRT1_SUPPORT;
2184b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
2185b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
2186b7e1c893Smrg									    ATOM_DEVICE_CRT1_SUPPORT,
2187b7e1c893Smrg									    1),
2188b7e1c893Smrg				ATOM_DEVICE_CRT1_SUPPORT))
2189b7e1c893Smrg	    return FALSE;
2190b7e1c893Smrg
2191b7e1c893Smrg	info->BiosConnector[1].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_CRT2_DDC);
2192b7e1c893Smrg	info->BiosConnector[1].load_detection = FALSE;
2193209ff23fSmrg	info->BiosConnector[1].ConnectorType = CONNECTOR_VGA;
2194209ff23fSmrg	info->BiosConnector[1].valid = TRUE;
2195b7e1c893Smrg	info->BiosConnector[1].devices = ATOM_DEVICE_CRT2_SUPPORT;
2196b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
2197b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
2198b7e1c893Smrg									    ATOM_DEVICE_CRT2_SUPPORT,
2199b7e1c893Smrg									    2),
2200b7e1c893Smrg				ATOM_DEVICE_CRT2_SUPPORT))
2201b7e1c893Smrg	    return FALSE;
2202209ff23fSmrg
2203209ff23fSmrg	info->BiosConnector[2].ConnectorType = CONNECTOR_STV;
2204b7e1c893Smrg	info->BiosConnector[2].load_detection = FALSE;
2205209ff23fSmrg	info->BiosConnector[2].ddc_i2c.valid = FALSE;
2206209ff23fSmrg	info->BiosConnector[2].valid = TRUE;
2207b7e1c893Smrg	info->BiosConnector[2].devices = ATOM_DEVICE_TV1_SUPPORT;
2208b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
2209b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
2210b7e1c893Smrg									    ATOM_DEVICE_TV1_SUPPORT,
2211b7e1c893Smrg									    2),
2212b7e1c893Smrg				ATOM_DEVICE_TV1_SUPPORT))
2213b7e1c893Smrg	    return FALSE;
2214209ff23fSmrg	return TRUE;
2215209ff23fSmrg    default:
2216209ff23fSmrg	return FALSE;
2217209ff23fSmrg    }
2218209ff23fSmrg
2219209ff23fSmrg    return FALSE;
2220209ff23fSmrg}
2221209ff23fSmrg#endif
2222209ff23fSmrg
2223209ff23fSmrgstatic void RADEONSetupGenericConnectors(ScrnInfoPtr pScrn)
2224209ff23fSmrg{
2225209ff23fSmrg    RADEONInfoPtr info       = RADEONPTR(pScrn);
2226209ff23fSmrg    RADEONEntPtr pRADEONEnt  = RADEONEntPriv(pScrn);
2227209ff23fSmrg
2228b7e1c893Smrg    if (IS_AVIVO_VARIANT)
2229b7e1c893Smrg	return;
2230b7e1c893Smrg
2231209ff23fSmrg    if (!pRADEONEnt->HasCRTC2) {
2232209ff23fSmrg	info->BiosConnector[0].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
2233209ff23fSmrg	info->BiosConnector[0].ConnectorType = CONNECTOR_VGA;
2234209ff23fSmrg	info->BiosConnector[0].valid = TRUE;
2235b7e1c893Smrg	info->BiosConnector[0].devices = ATOM_DEVICE_CRT1_SUPPORT;
2236b7e1c893Smrg	radeon_add_encoder(pScrn,
2237b7e1c893Smrg			   radeon_get_encoder_id_from_supported_device(pScrn,
2238b7e1c893Smrg								       ATOM_DEVICE_CRT1_SUPPORT,
2239b7e1c893Smrg								       1),
2240b7e1c893Smrg			   ATOM_DEVICE_CRT1_SUPPORT);
2241209ff23fSmrg	return;
2242209ff23fSmrg    }
2243209ff23fSmrg
2244b7e1c893Smrg    if (info->IsMobility) {
2245b7e1c893Smrg	/* Below is the most common setting, but may not be true */
2246b7e1c893Smrg	if (info->IsIGP) {
2247b7e1c893Smrg	    info->BiosConnector[0].ddc_i2c = legacy_setup_i2c_bus(RADEON_LCD_GPIO_MASK);
2248209ff23fSmrg	    info->BiosConnector[0].ConnectorType = CONNECTOR_LVDS;
2249209ff23fSmrg	    info->BiosConnector[0].valid = TRUE;
2250b7e1c893Smrg	    info->BiosConnector[0].devices = ATOM_DEVICE_LCD1_SUPPORT;
2251b7e1c893Smrg	    radeon_add_encoder(pScrn,
2252b7e1c893Smrg			       radeon_get_encoder_id_from_supported_device(pScrn,
2253b7e1c893Smrg									   ATOM_DEVICE_LCD1_SUPPORT,
2254b7e1c893Smrg									   0),
2255b7e1c893Smrg			       ATOM_DEVICE_LCD1_SUPPORT);
2256b7e1c893Smrg
2257b7e1c893Smrg	    /* IGP only has TVDAC */
2258b7e1c893Smrg	    if ((info->ChipFamily == CHIP_FAMILY_RS400) ||
2259b7e1c893Smrg		(info->ChipFamily == CHIP_FAMILY_RS480))
2260b7e1c893Smrg		info->BiosConnector[1].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_CRT2_DDC);
2261b7e1c893Smrg	    else
2262b7e1c893Smrg		info->BiosConnector[1].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
2263b7e1c893Smrg	    info->BiosConnector[1].load_detection = FALSE;
2264209ff23fSmrg	    info->BiosConnector[1].ConnectorType = CONNECTOR_VGA;
2265209ff23fSmrg	    info->BiosConnector[1].valid = TRUE;
2266b7e1c893Smrg	    info->BiosConnector[1].devices = ATOM_DEVICE_CRT1_SUPPORT;
2267b7e1c893Smrg	    radeon_add_encoder(pScrn,
2268b7e1c893Smrg			       radeon_get_encoder_id_from_supported_device(pScrn,
2269b7e1c893Smrg									   ATOM_DEVICE_CRT1_SUPPORT,
2270b7e1c893Smrg									   2),
2271b7e1c893Smrg			       ATOM_DEVICE_CRT1_SUPPORT);
2272209ff23fSmrg	} else {
2273b7e1c893Smrg#if defined(__powerpc__)
2274b7e1c893Smrg	    info->BiosConnector[0].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_DVI_DDC);
2275b7e1c893Smrg#else
2276b7e1c893Smrg	    info->BiosConnector[0].ddc_i2c = legacy_setup_i2c_bus(RADEON_LCD_GPIO_MASK);
2277b7e1c893Smrg#endif
2278b7e1c893Smrg	    info->BiosConnector[0].ConnectorType = CONNECTOR_LVDS;
2279209ff23fSmrg	    info->BiosConnector[0].valid = TRUE;
2280b7e1c893Smrg	    info->BiosConnector[0].devices = ATOM_DEVICE_LCD1_SUPPORT;
2281b7e1c893Smrg	    radeon_add_encoder(pScrn,
2282b7e1c893Smrg			       radeon_get_encoder_id_from_supported_device(pScrn,
2283b7e1c893Smrg									   ATOM_DEVICE_LCD1_SUPPORT,
2284b7e1c893Smrg									   0),
2285b7e1c893Smrg			       ATOM_DEVICE_LCD1_SUPPORT);
2286209ff23fSmrg
2287b7e1c893Smrg	    info->BiosConnector[1].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
2288209ff23fSmrg	    info->BiosConnector[1].ConnectorType = CONNECTOR_VGA;
2289209ff23fSmrg	    info->BiosConnector[1].valid = TRUE;
2290b7e1c893Smrg	    info->BiosConnector[1].devices = ATOM_DEVICE_CRT1_SUPPORT;
2291b7e1c893Smrg	    radeon_add_encoder(pScrn,
2292b7e1c893Smrg			       radeon_get_encoder_id_from_supported_device(pScrn,
2293b7e1c893Smrg									   ATOM_DEVICE_CRT1_SUPPORT,
2294b7e1c893Smrg									   1),
2295b7e1c893Smrg			       ATOM_DEVICE_CRT1_SUPPORT);
2296209ff23fSmrg	}
2297209ff23fSmrg    } else {
2298b7e1c893Smrg	/* Below is the most common setting, but may not be true */
2299b7e1c893Smrg	if (info->IsIGP) {
2300b7e1c893Smrg	    if ((info->ChipFamily == CHIP_FAMILY_RS400) ||
2301b7e1c893Smrg		(info->ChipFamily == CHIP_FAMILY_RS480))
2302b7e1c893Smrg		info->BiosConnector[0].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_CRT2_DDC);
2303b7e1c893Smrg	    else
2304b7e1c893Smrg		info->BiosConnector[0].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
2305b7e1c893Smrg	    info->BiosConnector[0].load_detection = FALSE;
2306b7e1c893Smrg	    info->BiosConnector[0].ConnectorType = CONNECTOR_VGA;
2307b7e1c893Smrg	    info->BiosConnector[0].valid = TRUE;
2308b7e1c893Smrg	    info->BiosConnector[0].devices = ATOM_DEVICE_CRT1_SUPPORT;
2309b7e1c893Smrg	    radeon_add_encoder(pScrn,
2310b7e1c893Smrg			       radeon_get_encoder_id_from_supported_device(pScrn,
2311b7e1c893Smrg									   ATOM_DEVICE_CRT1_SUPPORT,
2312b7e1c893Smrg									   1),
2313b7e1c893Smrg			       ATOM_DEVICE_CRT1_SUPPORT);
2314b7e1c893Smrg
2315b7e1c893Smrg	    /* not sure what a good default DDCType for DVI on
2316b7e1c893Smrg	     * IGP desktop chips is
2317b7e1c893Smrg	     */
2318b7e1c893Smrg	    info->BiosConnector[1].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_MONID); /* DDC_DVI? */
2319b7e1c893Smrg	    info->BiosConnector[1].ConnectorType = CONNECTOR_DVI_D;
2320b7e1c893Smrg	    info->BiosConnector[1].valid = TRUE;
2321b7e1c893Smrg	    info->BiosConnector[1].devices = ATOM_DEVICE_DFP1_SUPPORT;
2322b7e1c893Smrg	    radeon_add_encoder(pScrn,
2323b7e1c893Smrg			       radeon_get_encoder_id_from_supported_device(pScrn,
2324b7e1c893Smrg									   ATOM_DEVICE_DFP1_SUPPORT,
2325b7e1c893Smrg									   0),
2326b7e1c893Smrg			       ATOM_DEVICE_DFP1_SUPPORT);
2327209ff23fSmrg	} else {
2328b7e1c893Smrg	    info->BiosConnector[0].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_DVI_DDC);
2329b7e1c893Smrg	    info->BiosConnector[0].load_detection = FALSE;
2330b7e1c893Smrg	    info->BiosConnector[0].ConnectorType = CONNECTOR_DVI_I;
2331b7e1c893Smrg	    info->BiosConnector[0].valid = TRUE;
2332b7e1c893Smrg	    info->BiosConnector[0].devices = ATOM_DEVICE_CRT2_SUPPORT | ATOM_DEVICE_DFP1_SUPPORT;
2333b7e1c893Smrg	    radeon_add_encoder(pScrn,
2334b7e1c893Smrg			       radeon_get_encoder_id_from_supported_device(pScrn,
2335b7e1c893Smrg									   ATOM_DEVICE_CRT2_SUPPORT,
2336b7e1c893Smrg									   2),
2337b7e1c893Smrg			       ATOM_DEVICE_CRT2_SUPPORT);
2338b7e1c893Smrg	    radeon_add_encoder(pScrn,
2339b7e1c893Smrg			       radeon_get_encoder_id_from_supported_device(pScrn,
2340b7e1c893Smrg									   ATOM_DEVICE_DFP1_SUPPORT,
2341b7e1c893Smrg									   0),
2342b7e1c893Smrg			       ATOM_DEVICE_DFP1_SUPPORT);
2343209ff23fSmrg
2344209ff23fSmrg#if defined(__powerpc__)
2345b7e1c893Smrg	    info->BiosConnector[1].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
2346b7e1c893Smrg	    info->BiosConnector[1].ConnectorType = CONNECTOR_DVI_I;
2347b7e1c893Smrg	    info->BiosConnector[1].valid = TRUE;
2348b7e1c893Smrg	    info->BiosConnector[1].devices = ATOM_DEVICE_CRT1_SUPPORT | ATOM_DEVICE_DFP2_SUPPORT;
2349b7e1c893Smrg	    radeon_add_encoder(pScrn,
2350b7e1c893Smrg			       radeon_get_encoder_id_from_supported_device(pScrn,
2351b7e1c893Smrg									   ATOM_DEVICE_CRT1_SUPPORT,
2352b7e1c893Smrg									   1),
2353b7e1c893Smrg			       ATOM_DEVICE_CRT1_SUPPORT);
2354b7e1c893Smrg	    radeon_add_encoder(pScrn,
2355b7e1c893Smrg			       radeon_get_encoder_id_from_supported_device(pScrn,
2356b7e1c893Smrg									   ATOM_DEVICE_DFP2_SUPPORT,
2357b7e1c893Smrg									   0),
2358b7e1c893Smrg			       ATOM_DEVICE_DFP2_SUPPORT);
2359209ff23fSmrg#else
2360b7e1c893Smrg	    info->BiosConnector[1].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
2361b7e1c893Smrg	    info->BiosConnector[1].ConnectorType = CONNECTOR_VGA;
2362b7e1c893Smrg	    info->BiosConnector[1].valid = TRUE;
2363b7e1c893Smrg	    info->BiosConnector[1].devices = ATOM_DEVICE_CRT1_SUPPORT;
2364b7e1c893Smrg	    radeon_add_encoder(pScrn,
2365b7e1c893Smrg			       radeon_get_encoder_id_from_supported_device(pScrn,
2366b7e1c893Smrg									   ATOM_DEVICE_CRT1_SUPPORT,
2367b7e1c893Smrg									   1),
2368b7e1c893Smrg			       ATOM_DEVICE_CRT1_SUPPORT);
2369209ff23fSmrg#endif
2370209ff23fSmrg	}
2371b7e1c893Smrg    }
2372209ff23fSmrg
2373b7e1c893Smrg    if (info->InternalTVOut) {
2374b7e1c893Smrg	info->BiosConnector[2].ConnectorType = CONNECTOR_STV;
2375b7e1c893Smrg	info->BiosConnector[2].load_detection = FALSE;
2376b7e1c893Smrg	info->BiosConnector[2].ddc_i2c.valid = FALSE;
2377b7e1c893Smrg	info->BiosConnector[2].valid = TRUE;
2378b7e1c893Smrg	info->BiosConnector[2].devices = ATOM_DEVICE_TV1_SUPPORT;
2379b7e1c893Smrg	radeon_add_encoder(pScrn,
2380b7e1c893Smrg			       radeon_get_encoder_id_from_supported_device(pScrn,
2381b7e1c893Smrg									   ATOM_DEVICE_TV1_SUPPORT,
2382b7e1c893Smrg									   2),
2383b7e1c893Smrg			       ATOM_DEVICE_TV1_SUPPORT);
2384b7e1c893Smrg    }
2385209ff23fSmrg
2386b7e1c893Smrg    /* Some cards have the DDC lines swapped and we have no way to
2387b7e1c893Smrg     * detect it yet (Mac cards)
2388b7e1c893Smrg     */
2389b7e1c893Smrg    if (xf86ReturnOptValBool(info->Options, OPTION_REVERSE_DDC, FALSE)) {
2390b7e1c893Smrg	info->BiosConnector[0].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
2391b7e1c893Smrg	info->BiosConnector[1].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_DVI_DDC);
2392209ff23fSmrg    }
2393209ff23fSmrg}
2394209ff23fSmrg
2395209ff23fSmrg#if defined(__powerpc__)
2396209ff23fSmrg
2397209ff23fSmrg/*
2398209ff23fSmrg * Returns RADEONMacModel or 0 based on lines 'detected as' and 'machine'
2399209ff23fSmrg * in /proc/cpuinfo (on Linux) */
2400209ff23fSmrgstatic RADEONMacModel RADEONDetectMacModel(ScrnInfoPtr pScrn)
2401209ff23fSmrg{
2402209ff23fSmrg    RADEONInfoPtr info = RADEONPTR(pScrn);
2403209ff23fSmrg    RADEONMacModel ret = 0;
2404209ff23fSmrg#ifdef __linux__
2405209ff23fSmrg    char cpuline[50];  /* 50 should be sufficient for our purposes */
2406209ff23fSmrg    FILE *f = fopen ("/proc/cpuinfo", "r");
2407209ff23fSmrg
2408209ff23fSmrg    /* Some macs (minis and powerbooks) use internal tmds, others use external tmds
2409209ff23fSmrg     * and not just for dual-link TMDS, it shows up with single-link as well.
2410209ff23fSmrg     * Unforunately, there doesn't seem to be any good way to figure it out.
2411209ff23fSmrg     */
2412209ff23fSmrg
2413b7e1c893Smrg    /*
2414209ff23fSmrg     * PowerBook5,[1-5]: external tmds, single-link
2415209ff23fSmrg     * PowerBook5,[789]: external tmds, dual-link
2416209ff23fSmrg     * PowerBook5,6:     external tmds, single-link or dual-link
2417209ff23fSmrg     * need to add another option to specify the external tmds chip
2418209ff23fSmrg     * or find out what's used and add it.
2419209ff23fSmrg     */
2420209ff23fSmrg
2421209ff23fSmrg
2422209ff23fSmrg    if (f != NULL) {
2423209ff23fSmrg	while (fgets(cpuline, sizeof cpuline, f)) {
2424209ff23fSmrg	    if (!strncmp(cpuline, "machine", strlen ("machine"))) {
2425209ff23fSmrg		if (strstr(cpuline, "PowerBook5,1") ||
2426209ff23fSmrg		    strstr(cpuline, "PowerBook5,2") ||
2427209ff23fSmrg		    strstr(cpuline, "PowerBook5,3") ||
2428209ff23fSmrg		    strstr(cpuline, "PowerBook5,4") ||
2429209ff23fSmrg		    strstr(cpuline, "PowerBook5,5")) {
2430209ff23fSmrg		    ret = RADEON_MAC_POWERBOOK_EXTERNAL; /* single link */
2431209ff23fSmrg		    info->ext_tmds_chip = RADEON_SIL_164; /* works on 5,2 */
2432209ff23fSmrg		    break;
2433209ff23fSmrg		}
2434209ff23fSmrg
2435209ff23fSmrg		if (strstr(cpuline, "PowerBook5,6")) {
2436209ff23fSmrg		    ret = RADEON_MAC_POWERBOOK_EXTERNAL; /* dual or single link */
2437209ff23fSmrg		    break;
2438209ff23fSmrg		}
2439209ff23fSmrg
2440209ff23fSmrg		if (strstr(cpuline, "PowerBook5,7") ||
2441209ff23fSmrg		    strstr(cpuline, "PowerBook5,8") ||
2442209ff23fSmrg		    strstr(cpuline, "PowerBook5,9")) {
2443209ff23fSmrg		    ret = RADEON_MAC_POWERBOOK_EXTERNAL; /* dual link */
2444209ff23fSmrg		    info->ext_tmds_chip = RADEON_SIL_1178; /* guess */
2445209ff23fSmrg		    break;
2446209ff23fSmrg		}
2447209ff23fSmrg
2448209ff23fSmrg		if (strstr(cpuline, "PowerBook3,3")) {
2449209ff23fSmrg		    ret = RADEON_MAC_POWERBOOK_VGA; /* vga rather than dvi */
2450209ff23fSmrg		    break;
2451209ff23fSmrg		}
2452209ff23fSmrg
2453209ff23fSmrg		if (strstr(cpuline, "PowerMac10,1")) {
2454209ff23fSmrg		    ret = RADEON_MAC_MINI_INTERNAL; /* internal tmds */
2455209ff23fSmrg		    break;
2456209ff23fSmrg		}
2457209ff23fSmrg		if (strstr(cpuline, "PowerMac10,2")) {
2458209ff23fSmrg		    ret = RADEON_MAC_MINI_EXTERNAL; /* external tmds */
2459209ff23fSmrg		    break;
2460209ff23fSmrg		}
2461209ff23fSmrg	    } else if (!strncmp(cpuline, "detected as", strlen("detected as"))) {
2462209ff23fSmrg		if (strstr(cpuline, "iBook")) {
2463209ff23fSmrg		    ret = RADEON_MAC_IBOOK;
2464209ff23fSmrg		    break;
2465209ff23fSmrg		} else if (strstr(cpuline, "PowerBook")) {
2466209ff23fSmrg		    ret = RADEON_MAC_POWERBOOK_INTERNAL; /* internal tmds */
2467209ff23fSmrg		    break;
2468209ff23fSmrg		} else if (strstr(cpuline, "iMac G5 (iSight)")) {
2469209ff23fSmrg		    ret = RADEON_MAC_IMAC_G5_ISIGHT;
2470209ff23fSmrg		    break;
2471b7e1c893Smrg		} else if (strstr(cpuline, "eMac")) {
2472b7e1c893Smrg		    ret = RADEON_MAC_EMAC;
2473b7e1c893Smrg		    break;
2474209ff23fSmrg		}
2475209ff23fSmrg
2476209ff23fSmrg		/* No known PowerMac model detected */
2477209ff23fSmrg		break;
2478209ff23fSmrg	    }
2479209ff23fSmrg	}
2480209ff23fSmrg
2481209ff23fSmrg	fclose (f);
2482209ff23fSmrg    } else
2483209ff23fSmrg	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
2484209ff23fSmrg		   "Cannot detect PowerMac model because /proc/cpuinfo not "
2485209ff23fSmrg		   "readable.\n");
2486209ff23fSmrg
2487209ff23fSmrg#endif /* __linux */
2488209ff23fSmrg
2489209ff23fSmrg    if (ret) {
2490209ff23fSmrg	xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "Detected %s.\n",
2491209ff23fSmrg		   ret == RADEON_MAC_POWERBOOK_EXTERNAL ? "PowerBook with external DVI" :
2492209ff23fSmrg		   ret == RADEON_MAC_POWERBOOK_INTERNAL ? "PowerBook with integrated DVI" :
2493209ff23fSmrg		   ret == RADEON_MAC_POWERBOOK_VGA ? "PowerBook with VGA" :
2494209ff23fSmrg		   ret == RADEON_MAC_IBOOK ? "iBook" :
2495209ff23fSmrg		   ret == RADEON_MAC_MINI_EXTERNAL ? "Mac Mini with external DVI" :
2496209ff23fSmrg		   ret == RADEON_MAC_MINI_INTERNAL ? "Mac Mini with integrated DVI" :
2497209ff23fSmrg		   "iMac G5 iSight");
2498209ff23fSmrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2499209ff23fSmrg		   "If this is not correct, try Option \"MacModel\" and "
2500209ff23fSmrg		   "consider reporting to the\n");
2501209ff23fSmrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2502209ff23fSmrg		   "xorg-driver-ati@lists.x.org mailing list"
2503209ff23fSmrg#ifdef __linux__
2504209ff23fSmrg		   " with the contents of /proc/cpuinfo"
2505209ff23fSmrg#endif
2506209ff23fSmrg		   ".\n");
2507209ff23fSmrg    }
2508209ff23fSmrg
2509209ff23fSmrg    return ret;
2510209ff23fSmrg}
2511209ff23fSmrg
2512209ff23fSmrg#endif /* __powerpc__ */
2513209ff23fSmrg
2514209ff23fSmrgstatic int
2515209ff23fSmrgradeon_output_clones (ScrnInfoPtr pScrn, xf86OutputPtr output)
2516209ff23fSmrg{
2517b7e1c893Smrg    RADEONInfoPtr info = RADEONPTR(pScrn);
2518209ff23fSmrg    RADEONOutputPrivatePtr radeon_output = output->driver_private;
2519209ff23fSmrg    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR (pScrn);
2520209ff23fSmrg    int			o;
2521209ff23fSmrg    int			index_mask = 0;
2522209ff23fSmrg
2523b7e1c893Smrg    /* DIG routing gets problematic */
2524b7e1c893Smrg    if (IS_DCE32_VARIANT)
2525209ff23fSmrg	return index_mask;
2526209ff23fSmrg
2527209ff23fSmrg    /* LVDS is too wacky */
2528b7e1c893Smrg    if (radeon_output->devices & (ATOM_DEVICE_LCD_SUPPORT))
2529b7e1c893Smrg	return index_mask;
2530b7e1c893Smrg
2531b7e1c893Smrg    if (radeon_output->devices & (ATOM_DEVICE_TV_SUPPORT))
2532209ff23fSmrg	return index_mask;
2533209ff23fSmrg
2534209ff23fSmrg    for (o = 0; o < config->num_output; o++) {
2535209ff23fSmrg	xf86OutputPtr clone = config->output[o];
2536209ff23fSmrg	RADEONOutputPrivatePtr radeon_clone = clone->driver_private;
2537b7e1c893Smrg
2538209ff23fSmrg	if (output == clone) /* don't clone yourself */
2539209ff23fSmrg	    continue;
2540b7e1c893Smrg	else if (radeon_clone->devices & (ATOM_DEVICE_LCD_SUPPORT)) /* LVDS */
2541209ff23fSmrg	    continue;
2542b7e1c893Smrg	else if (radeon_clone->devices & (ATOM_DEVICE_TV_SUPPORT)) /* TV */
2543209ff23fSmrg	    continue;
2544209ff23fSmrg	else
2545209ff23fSmrg	    index_mask |= (1 << o);
2546209ff23fSmrg    }
2547209ff23fSmrg
2548209ff23fSmrg    return index_mask;
2549209ff23fSmrg}
2550209ff23fSmrg
2551b7e1c893Smrgstatic xf86OutputPtr
2552b7e1c893SmrgRADEONOutputCreate(ScrnInfoPtr pScrn, const char *name, int i)
2553b7e1c893Smrg{
2554b7e1c893Smrg    char buf[32];
2555b7e1c893Smrg    sprintf(buf, name, i);
2556b7e1c893Smrg    return xf86OutputCreate(pScrn, &radeon_output_funcs, buf);
2557b7e1c893Smrg}
2558b7e1c893Smrg
2559209ff23fSmrg/*
2560209ff23fSmrg * initialise the static data sos we don't have to re-do at randr change */
2561209ff23fSmrgBool RADEONSetupConnectors(ScrnInfoPtr pScrn)
2562209ff23fSmrg{
2563209ff23fSmrg    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
2564209ff23fSmrg    RADEONInfoPtr info       = RADEONPTR(pScrn);
2565209ff23fSmrg    xf86OutputPtr output;
2566209ff23fSmrg    char *optstr;
2567b7e1c893Smrg    int i;
2568209ff23fSmrg    int num_vga = 0;
2569209ff23fSmrg    int num_dvi = 0;
2570209ff23fSmrg    int num_hdmi = 0;
2571b7e1c893Smrg    int num_dp = 0;
2572209ff23fSmrg
2573209ff23fSmrg    /* We first get the information about all connectors from BIOS.
2574209ff23fSmrg     * This is how the card is phyiscally wired up.
2575209ff23fSmrg     * The information should be correct even on a OEM card.
2576209ff23fSmrg     */
2577209ff23fSmrg    for (i = 0; i < RADEON_MAX_BIOS_CONNECTOR; i++) {
2578b7e1c893Smrg	info->encoders[i] = NULL;
2579209ff23fSmrg	info->BiosConnector[i].valid = FALSE;
2580b7e1c893Smrg	info->BiosConnector[i].load_detection = TRUE;
2581b7e1c893Smrg	info->BiosConnector[i].shared_ddc = FALSE;
2582209ff23fSmrg	info->BiosConnector[i].ddc_i2c.valid = FALSE;
2583209ff23fSmrg	info->BiosConnector[i].ConnectorType = CONNECTOR_NONE;
2584b7e1c893Smrg	info->BiosConnector[i].devices = 0;
2585209ff23fSmrg    }
2586209ff23fSmrg
2587209ff23fSmrg#if defined(__powerpc__)
2588209ff23fSmrg    info->MacModel = 0;
2589209ff23fSmrg    optstr = (char *)xf86GetOptValString(info->Options, OPTION_MAC_MODEL);
2590209ff23fSmrg    if (optstr) {
2591209ff23fSmrg	if (!strncmp("ibook", optstr, strlen("ibook")))
2592209ff23fSmrg	    info->MacModel = RADEON_MAC_IBOOK;
2593209ff23fSmrg	else if (!strncmp("powerbook-duallink", optstr, strlen("powerbook-duallink"))) /* alias */
2594209ff23fSmrg	    info->MacModel = RADEON_MAC_POWERBOOK_EXTERNAL;
2595209ff23fSmrg	else if (!strncmp("powerbook-external", optstr, strlen("powerbook-external")))
2596209ff23fSmrg	    info->MacModel = RADEON_MAC_POWERBOOK_EXTERNAL;
2597209ff23fSmrg	else if (!strncmp("powerbook-internal", optstr, strlen("powerbook-internal")))
2598209ff23fSmrg	    info->MacModel = RADEON_MAC_POWERBOOK_INTERNAL;
2599209ff23fSmrg	else if (!strncmp("powerbook-vga", optstr, strlen("powerbook-vga")))
2600209ff23fSmrg	    info->MacModel = RADEON_MAC_POWERBOOK_VGA;
2601209ff23fSmrg	else if (!strncmp("powerbook", optstr, strlen("powerbook"))) /* alias */
2602209ff23fSmrg	    info->MacModel = RADEON_MAC_POWERBOOK_INTERNAL;
2603209ff23fSmrg	else if (!strncmp("mini-internal", optstr, strlen("mini-internal")))
2604209ff23fSmrg	    info->MacModel = RADEON_MAC_MINI_INTERNAL;
2605209ff23fSmrg	else if (!strncmp("mini-external", optstr, strlen("mini-external")))
2606209ff23fSmrg	    info->MacModel = RADEON_MAC_MINI_EXTERNAL;
2607209ff23fSmrg	else if (!strncmp("mini", optstr, strlen("mini"))) /* alias */
2608209ff23fSmrg	    info->MacModel = RADEON_MAC_MINI_EXTERNAL;
2609209ff23fSmrg	else if (!strncmp("imac-g5-isight", optstr, strlen("imac-g5-isight")))
2610209ff23fSmrg	    info->MacModel = RADEON_MAC_IMAC_G5_ISIGHT;
2611b7e1c893Smrg	else if (!strncmp("emac", optstr, strlen("emac")))
2612b7e1c893Smrg	    info->MacModel = RADEON_MAC_EMAC;
2613209ff23fSmrg	else {
2614209ff23fSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Invalid Mac Model: %s\n", optstr);
2615209ff23fSmrg	}
2616209ff23fSmrg    }
2617209ff23fSmrg
2618209ff23fSmrg    if (!info->MacModel) {
2619209ff23fSmrg	info->MacModel = RADEONDetectMacModel(pScrn);
2620209ff23fSmrg    }
2621209ff23fSmrg
2622209ff23fSmrg    if (info->MacModel){
2623209ff23fSmrg	if (!RADEONSetupAppleConnectors(pScrn))
2624209ff23fSmrg	    RADEONSetupGenericConnectors(pScrn);
2625209ff23fSmrg    } else
2626209ff23fSmrg#endif
2627209ff23fSmrg    if (xf86ReturnOptValBool(info->Options, OPTION_DEFAULT_CONNECTOR_TABLE, FALSE)) {
2628209ff23fSmrg	RADEONSetupGenericConnectors(pScrn);
2629209ff23fSmrg    } else {
2630209ff23fSmrg	if (!RADEONGetConnectorInfoFromBIOS(pScrn))
2631209ff23fSmrg	    RADEONSetupGenericConnectors(pScrn);
2632209ff23fSmrg    }
2633209ff23fSmrg
2634209ff23fSmrg    /* parse connector table option */
2635209ff23fSmrg    optstr = (char *)xf86GetOptValString(info->Options, OPTION_CONNECTORTABLE);
2636209ff23fSmrg
2637209ff23fSmrg    if (optstr) {
2638209ff23fSmrg	unsigned int ddc_line[2];
2639b7e1c893Smrg	int DACType[2], TMDSType[2];
2640209ff23fSmrg
2641209ff23fSmrg	for (i = 2; i < RADEON_MAX_BIOS_CONNECTOR; i++) {
2642209ff23fSmrg	    info->BiosConnector[i].valid = FALSE;
2643209ff23fSmrg	}
2644b7e1c893Smrg
2645209ff23fSmrg	if (sscanf(optstr, "%u,%u,%u,%u,%u,%u,%u,%u",
2646209ff23fSmrg		   &ddc_line[0],
2647b7e1c893Smrg		   &DACType[0],
2648b7e1c893Smrg		   &TMDSType[0],
2649209ff23fSmrg		   &info->BiosConnector[0].ConnectorType,
2650209ff23fSmrg		   &ddc_line[1],
2651b7e1c893Smrg		   &DACType[1],
2652b7e1c893Smrg		   &TMDSType[1],
2653209ff23fSmrg		   &info->BiosConnector[1].ConnectorType) != 8) {
2654209ff23fSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Invalid ConnectorTable option: %s\n", optstr);
2655209ff23fSmrg	    return FALSE;
2656209ff23fSmrg	}
2657209ff23fSmrg
2658b7e1c893Smrg	for (i = 0; i < 2; i++) {
2659b7e1c893Smrg	    info->BiosConnector[i].valid = TRUE;
2660b7e1c893Smrg	    info->BiosConnector[i].ddc_i2c = legacy_setup_i2c_bus(ddc_line[i]);
2661b7e1c893Smrg	    switch (DACType[i]) {
2662b7e1c893Smrg	    case 1:
2663b7e1c893Smrg		info->BiosConnector[i].devices |= ATOM_DEVICE_CRT1_SUPPORT;
2664b7e1c893Smrg		if (!radeon_add_encoder(pScrn,
2665b7e1c893Smrg					radeon_get_encoder_id_from_supported_device(pScrn,
2666b7e1c893Smrg										    ATOM_DEVICE_CRT1_SUPPORT,
2667b7e1c893Smrg										    1),
2668b7e1c893Smrg					ATOM_DEVICE_CRT1_SUPPORT))
2669b7e1c893Smrg		    return FALSE;
2670b7e1c893Smrg		info->BiosConnector[i].load_detection = TRUE;
2671b7e1c893Smrg		break;
2672b7e1c893Smrg	    case 2:
2673b7e1c893Smrg		info->BiosConnector[i].devices |= ATOM_DEVICE_CRT2_SUPPORT;
2674b7e1c893Smrg		if (!radeon_add_encoder(pScrn,
2675b7e1c893Smrg					radeon_get_encoder_id_from_supported_device(pScrn,
2676b7e1c893Smrg										    ATOM_DEVICE_CRT1_SUPPORT,
2677b7e1c893Smrg										    2),
2678b7e1c893Smrg					ATOM_DEVICE_CRT1_SUPPORT))
2679b7e1c893Smrg		    return FALSE;
2680b7e1c893Smrg		info->BiosConnector[i].load_detection = FALSE;
2681b7e1c893Smrg		break;
2682b7e1c893Smrg	    }
2683b7e1c893Smrg	    switch (TMDSType[i]) {
2684b7e1c893Smrg	    case 1:
2685b7e1c893Smrg		info->BiosConnector[i].devices |= ATOM_DEVICE_DFP1_SUPPORT;
2686b7e1c893Smrg		if (!radeon_add_encoder(pScrn,
2687b7e1c893Smrg					radeon_get_encoder_id_from_supported_device(pScrn,
2688b7e1c893Smrg										    ATOM_DEVICE_DFP1_SUPPORT,
2689b7e1c893Smrg										    0),
2690b7e1c893Smrg					ATOM_DEVICE_DFP1_SUPPORT))
2691b7e1c893Smrg		    return FALSE;
2692b7e1c893Smrg		break;
2693b7e1c893Smrg	    case 2:
2694b7e1c893Smrg		info->BiosConnector[i].devices |= ATOM_DEVICE_DFP2_SUPPORT;
2695b7e1c893Smrg		if (!radeon_add_encoder(pScrn,
2696b7e1c893Smrg					radeon_get_encoder_id_from_supported_device(pScrn,
2697b7e1c893Smrg										    ATOM_DEVICE_DFP2_SUPPORT,
2698b7e1c893Smrg										    0),
2699b7e1c893Smrg					ATOM_DEVICE_DFP2_SUPPORT))
2700b7e1c893Smrg		    return FALSE;
2701b7e1c893Smrg		break;
2702b7e1c893Smrg	    }
2703b7e1c893Smrg	}
2704209ff23fSmrg    }
2705209ff23fSmrg
2706209ff23fSmrg    for (i = 0; i < RADEON_MAX_BIOS_CONNECTOR; i++) {
2707209ff23fSmrg	if (info->BiosConnector[i].valid) {
2708b7e1c893Smrg	    RADEONConnectorType conntype = info->BiosConnector[i].ConnectorType;
2709b7e1c893Smrg	    if ((conntype == CONNECTOR_DVI_D) ||
2710b7e1c893Smrg		(conntype == CONNECTOR_DVI_I) ||
2711b7e1c893Smrg		(conntype == CONNECTOR_DVI_A)) {
2712209ff23fSmrg		num_dvi++;
2713b7e1c893Smrg	    } else if (conntype == CONNECTOR_VGA) {
2714209ff23fSmrg		num_vga++;
2715b7e1c893Smrg	    } else if ((conntype == CONNECTOR_HDMI_TYPE_A) ||
2716b7e1c893Smrg		       (conntype == CONNECTOR_HDMI_TYPE_B)) {
2717209ff23fSmrg		num_hdmi++;
2718b7e1c893Smrg	    } else if (conntype == CONNECTOR_DISPLAY_PORT) {
2719b7e1c893Smrg		num_dp++;
2720209ff23fSmrg	    }
2721209ff23fSmrg	}
2722209ff23fSmrg    }
2723209ff23fSmrg
2724209ff23fSmrg    for (i = 0 ; i < RADEON_MAX_BIOS_CONNECTOR; i++) {
2725209ff23fSmrg	if (info->BiosConnector[i].valid) {
2726209ff23fSmrg	    RADEONOutputPrivatePtr radeon_output;
2727b7e1c893Smrg	    RADEONConnectorType conntype = info->BiosConnector[i].ConnectorType;
2728209ff23fSmrg
2729b7e1c893Smrg	    if (conntype == CONNECTOR_NONE)
2730209ff23fSmrg		continue;
2731209ff23fSmrg
2732209ff23fSmrg	    radeon_output = xnfcalloc(sizeof(RADEONOutputPrivateRec), 1);
2733209ff23fSmrg	    if (!radeon_output) {
2734209ff23fSmrg		return FALSE;
2735209ff23fSmrg	    }
2736209ff23fSmrg	    radeon_output->MonType = MT_UNKNOWN;
2737b7e1c893Smrg	    radeon_output->ConnectorType = conntype;
2738209ff23fSmrg	    radeon_output->devices = info->BiosConnector[i].devices;
2739209ff23fSmrg	    radeon_output->ddc_i2c = info->BiosConnector[i].ddc_i2c;
2740209ff23fSmrg	    radeon_output->igp_lane_info = info->BiosConnector[i].igp_lane_info;
2741b7e1c893Smrg	    radeon_output->shared_ddc = info->BiosConnector[i].shared_ddc;
2742b7e1c893Smrg	    radeon_output->load_detection = info->BiosConnector[i].load_detection;
2743b7e1c893Smrg	    radeon_output->linkb = info->BiosConnector[i].linkb;
2744b7e1c893Smrg	    radeon_output->connector_id = info->BiosConnector[i].connector_object;
2745b7e1c893Smrg
2746b7e1c893Smrg	    if ((conntype == CONNECTOR_DVI_D) ||
2747b7e1c893Smrg		(conntype == CONNECTOR_DVI_I) ||
2748b7e1c893Smrg		(conntype == CONNECTOR_DVI_A)) {
2749b7e1c893Smrg		output = RADEONOutputCreate(pScrn, "DVI-%d", --num_dvi);
2750b7e1c893Smrg	    } else if (conntype == CONNECTOR_VGA) {
2751b7e1c893Smrg		output = RADEONOutputCreate(pScrn, "VGA-%d", --num_vga);
2752b7e1c893Smrg	    } else if ((conntype == CONNECTOR_HDMI_TYPE_A) ||
2753b7e1c893Smrg		       (conntype == CONNECTOR_HDMI_TYPE_B)) {
2754b7e1c893Smrg		output = RADEONOutputCreate(pScrn, "HDMI-%d", --num_hdmi);
2755b7e1c893Smrg	    } else if (conntype == CONNECTOR_DISPLAY_PORT) {
2756b7e1c893Smrg		output = RADEONOutputCreate(pScrn, "DisplayPort-%d", --num_dp);
2757b7e1c893Smrg	    } else {
2758b7e1c893Smrg		output = RADEONOutputCreate(pScrn,
2759b7e1c893Smrg					    ConnectorTypeName[conntype], 0);
2760b7e1c893Smrg	    }
2761209ff23fSmrg
2762209ff23fSmrg	    if (!output) {
2763209ff23fSmrg		return FALSE;
2764209ff23fSmrg	    }
2765209ff23fSmrg	    output->driver_private = radeon_output;
2766209ff23fSmrg	    output->possible_crtcs = 1;
2767209ff23fSmrg	    /* crtc2 can drive LVDS, it just doesn't have RMX */
2768b7e1c893Smrg	    if (!(radeon_output->devices & (ATOM_DEVICE_LCD_SUPPORT)))
2769209ff23fSmrg		output->possible_crtcs |= 2;
2770209ff23fSmrg
2771b7e1c893Smrg	    /* we can clone the DACs, and probably TV-out,
2772209ff23fSmrg	       but I'm not sure it's worth the trouble */
2773209ff23fSmrg	    output->possible_clones = 0;
2774209ff23fSmrg
2775209ff23fSmrg	    RADEONInitConnector(output);
2776209ff23fSmrg	}
2777209ff23fSmrg    }
2778209ff23fSmrg
2779209ff23fSmrg    for (i = 0; i < xf86_config->num_output; i++) {
2780209ff23fSmrg	xf86OutputPtr output = xf86_config->output[i];
2781209ff23fSmrg
2782209ff23fSmrg	output->possible_clones = radeon_output_clones(pScrn, output);
2783209ff23fSmrg    }
2784209ff23fSmrg
2785209ff23fSmrg    return TRUE;
2786209ff23fSmrg}
2787209ff23fSmrg
2788