radeon_output.c revision b7e1c893
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) {
222b7e1c893Smrg	/* RV410 RADEON_GPIO_VGA_DDC seems to only work via hw i2c
223b7e1c893Smrg	 * We may want to extend this to other cases if the need arises...
224b7e1c893Smrg	 */
225b7e1c893Smrg	if ((info->ChipFamily == CHIP_FAMILY_RV410) &&
226b7e1c893Smrg	    (radeon_output->ddc_i2c.mask_clk_reg == RADEON_GPIO_VGA_DDC) &&
227b7e1c893Smrg	    info->IsAtomBios)
228b7e1c893Smrg	    MonInfo = radeon_atom_get_edid(output);
229b7e1c893Smrg	else if (info->get_hardcoded_edid_from_bios) {
230b7e1c893Smrg	    MonInfo = RADEONGetHardCodedEDIDFromBIOS(output);
231b7e1c893Smrg	    if (MonInfo == NULL) {
232b7e1c893Smrg		RADEONI2CDoLock(output, TRUE);
233b7e1c893Smrg		MonInfo = xf86OutputGetEDID(output, radeon_output->pI2CBus);
234b7e1c893Smrg		RADEONI2CDoLock(output, FALSE);
235b7e1c893Smrg	    }
236b7e1c893Smrg	} else {
237b7e1c893Smrg	    RADEONI2CDoLock(output, TRUE);
238b7e1c893Smrg	    MonInfo = xf86OutputGetEDID(output, radeon_output->pI2CBus);
239b7e1c893Smrg	    RADEONI2CDoLock(output, FALSE);
240b7e1c893Smrg	}
241b7e1c893Smrg    }
242209ff23fSmrg    if (MonInfo) {
243b7e1c893Smrg	switch (radeon_output->ConnectorType) {
244b7e1c893Smrg	case CONNECTOR_LVDS:
245209ff23fSmrg	    MonType = MT_LCD;
246b7e1c893Smrg	    break;
247b7e1c893Smrg	case CONNECTOR_DVI_D:
248b7e1c893Smrg	case CONNECTOR_HDMI_TYPE_A:
249b7e1c893Smrg	case CONNECTOR_HDMI_TYPE_B:
250b7e1c893Smrg	    if (radeon_output->shared_ddc) {
251b7e1c893Smrg		if (MonInfo->rawData[0x14] & 0x80) /* if it's digital and DVI/HDMI/etc. */
252b7e1c893Smrg		    MonType = MT_DFP;
253b7e1c893Smrg		else
254b7e1c893Smrg		    MonType = MT_NONE;
255b7e1c893Smrg	    } else
256b7e1c893Smrg		MonType = MT_DFP;
257b7e1c893Smrg	    break;
258b7e1c893Smrg	case CONNECTOR_DISPLAY_PORT:
259b7e1c893Smrg	    /*
260b7e1c893Smrg	     * XXX wrong. need to infer based on whether we got DDC from I2C
261b7e1c893Smrg	     * or AUXCH.
262b7e1c893Smrg	     */
263209ff23fSmrg	    MonType = MT_DFP;
264b7e1c893Smrg	case CONNECTOR_DVI_I:
265b7e1c893Smrg	    if (MonInfo->rawData[0x14] & 0x80) /* if it's digital and DVI */
266b7e1c893Smrg		MonType = MT_DFP;
267b7e1c893Smrg	    else
268b7e1c893Smrg		MonType = MT_CRT;
269b7e1c893Smrg	    break;
270b7e1c893Smrg	case CONNECTOR_VGA:
271b7e1c893Smrg	case CONNECTOR_DVI_A:
272b7e1c893Smrg	default:
273b7e1c893Smrg	    if (radeon_output->shared_ddc) {
274b7e1c893Smrg		if (MonInfo->rawData[0x14] & 0x80) /* if it's digital and VGA */
275b7e1c893Smrg		    MonType = MT_NONE;
276b7e1c893Smrg		else
277b7e1c893Smrg		    MonType = MT_CRT;
278b7e1c893Smrg	    } else
279b7e1c893Smrg		MonType = MT_CRT;
280b7e1c893Smrg	    break;
281b7e1c893Smrg	}
282b7e1c893Smrg
283b7e1c893Smrg	if (MonType != MT_NONE)
284b7e1c893Smrg	    if (!xf86ReturnOptValBool(info->Options, OPTION_IGNORE_EDID, FALSE))
285b7e1c893Smrg		xf86OutputSetEDID(output, MonInfo);
286209ff23fSmrg    } else
287209ff23fSmrg	MonType = MT_NONE;
288b7e1c893Smrg
289209ff23fSmrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
290209ff23fSmrg	       "Output: %s, Detected Monitor Type: %d\n", output->name, MonType);
291209ff23fSmrg
292209ff23fSmrg    return MonType;
293209ff23fSmrg}
294209ff23fSmrg
295209ff23fSmrg#ifndef __powerpc__
296209ff23fSmrg
297209ff23fSmrgstatic RADEONMonitorType
298209ff23fSmrgRADEONDetectLidStatus(ScrnInfoPtr pScrn)
299209ff23fSmrg{
300209ff23fSmrg    RADEONInfoPtr info = RADEONPTR(pScrn);
301209ff23fSmrg    RADEONMonitorType MonType = MT_NONE;
302209ff23fSmrg#ifdef __linux__
303209ff23fSmrg    char lidline[50];  /* 50 should be sufficient for our purposes */
304209ff23fSmrg    FILE *f = fopen ("/proc/acpi/button/lid/LID/state", "r");
305209ff23fSmrg
306209ff23fSmrg    if (f != NULL) {
307209ff23fSmrg	while (fgets(lidline, sizeof lidline, f)) {
308209ff23fSmrg	    if (!strncmp(lidline, "state:", strlen ("state:"))) {
309209ff23fSmrg		if (strstr(lidline, "open")) {
310209ff23fSmrg		    fclose(f);
311209ff23fSmrg		    ErrorF("proc lid open\n");
312209ff23fSmrg		    return MT_LCD;
313209ff23fSmrg		}
314209ff23fSmrg		else if (strstr(lidline, "closed")) {
315209ff23fSmrg		    fclose(f);
316209ff23fSmrg		    ErrorF("proc lid closed\n");
317209ff23fSmrg		    return MT_NONE;
318209ff23fSmrg		}
319209ff23fSmrg	    }
320209ff23fSmrg	}
321209ff23fSmrg	fclose(f);
322209ff23fSmrg    }
323209ff23fSmrg#endif
324209ff23fSmrg
325209ff23fSmrg    if (!info->IsAtomBios) {
326209ff23fSmrg	unsigned char *RADEONMMIO = info->MMIO;
327209ff23fSmrg
328209ff23fSmrg	/* see if the lid is closed -- only works at boot */
329209ff23fSmrg	if (INREG(RADEON_BIOS_6_SCRATCH) & 0x10)
330209ff23fSmrg	    MonType = MT_NONE;
331209ff23fSmrg	else
332209ff23fSmrg	    MonType = MT_LCD;
333209ff23fSmrg    } else
334209ff23fSmrg	MonType = MT_LCD;
335209ff23fSmrg
336209ff23fSmrg    return MonType;
337209ff23fSmrg}
338209ff23fSmrg
339209ff23fSmrg#endif /* __powerpc__ */
340209ff23fSmrg
341209ff23fSmrgstatic void
342209ff23fSmrgradeon_dpms(xf86OutputPtr output, int mode)
343209ff23fSmrg{
344209ff23fSmrg    RADEONInfoPtr info = RADEONPTR(output->scrn);
345209ff23fSmrg    RADEONOutputPrivatePtr radeon_output = output->driver_private;
346209ff23fSmrg
347209ff23fSmrg    if ((mode == DPMSModeOn) && radeon_output->enabled)
348209ff23fSmrg	return;
349209ff23fSmrg
350b7e1c893Smrg    if (IS_AVIVO_VARIANT || info->r4xx_atom) {
351209ff23fSmrg	atombios_output_dpms(output, mode);
352209ff23fSmrg    } else {
353209ff23fSmrg	legacy_output_dpms(output, mode);
354209ff23fSmrg    }
355209ff23fSmrg    radeon_bios_output_dpms(output, mode);
356209ff23fSmrg
357209ff23fSmrg    if (mode == DPMSModeOn)
358209ff23fSmrg	radeon_output->enabled = TRUE;
359209ff23fSmrg    else
360209ff23fSmrg	radeon_output->enabled = FALSE;
361209ff23fSmrg
362209ff23fSmrg}
363209ff23fSmrg
364209ff23fSmrgstatic void
365209ff23fSmrgradeon_save(xf86OutputPtr output)
366209ff23fSmrg{
367209ff23fSmrg
368209ff23fSmrg}
369209ff23fSmrg
370209ff23fSmrgstatic void
371209ff23fSmrgradeon_restore(xf86OutputPtr restore)
372209ff23fSmrg{
373209ff23fSmrg
374209ff23fSmrg}
375209ff23fSmrg
376209ff23fSmrgstatic int
377209ff23fSmrgradeon_mode_valid(xf86OutputPtr output, DisplayModePtr pMode)
378209ff23fSmrg{
379209ff23fSmrg    RADEONOutputPrivatePtr radeon_output = output->driver_private;
380b7e1c893Smrg    radeon_native_mode_ptr native_mode = &radeon_output->native_mode;
381209ff23fSmrg    ScrnInfoPtr pScrn = output->scrn;
382209ff23fSmrg    RADEONInfoPtr info = RADEONPTR(pScrn);
383209ff23fSmrg    RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
384209ff23fSmrg
385209ff23fSmrg    /*
386209ff23fSmrg     * RN50 has effective maximum mode bandwidth of about 300MiB/s.
387209ff23fSmrg     * XXX should really do this for all chips by properly computing
388209ff23fSmrg     * memory bandwidth and an overhead factor.
389209ff23fSmrg     */
390209ff23fSmrg    if (info->ChipFamily == CHIP_FAMILY_RV100 && !pRADEONEnt->HasCRTC2) {
391209ff23fSmrg	if (xf86ModeBandwidth(pMode, pScrn->bitsPerPixel) > 300)
392209ff23fSmrg	    return MODE_BANDWIDTH;
393209ff23fSmrg    }
394209ff23fSmrg
395b7e1c893Smrg    if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT)) {
396b7e1c893Smrg	if (IS_AVIVO_VARIANT)
397b7e1c893Smrg	    return MODE_OK;
398b7e1c893Smrg	else {
399b7e1c893Smrg	    /* FIXME: Update when more modes are added */
400209ff23fSmrg	    if (pMode->HDisplay == 800 && pMode->VDisplay == 600)
401209ff23fSmrg		return MODE_OK;
402209ff23fSmrg	    else
403209ff23fSmrg		return MODE_CLOCK_RANGE;
404209ff23fSmrg	}
405209ff23fSmrg    }
406209ff23fSmrg
407b7e1c893Smrg    /* single link DVI check */
408b7e1c893Smrg    if (pMode->Clock > 165000 && radeon_output->MonType == MT_DFP) {
409b7e1c893Smrg	/* DP->DVI converter */
410b7e1c893Smrg	if (radeon_output->ConnectorType == CONNECTOR_DISPLAY_PORT)
411b7e1c893Smrg	    return MODE_CLOCK_HIGH;
412b7e1c893Smrg
413b7e1c893Smrg	/* XXX some HDMI can do better than 165MHz on a link */
414b7e1c893Smrg	if (radeon_output->ConnectorType == CONNECTOR_HDMI_TYPE_A)
415b7e1c893Smrg	    return MODE_CLOCK_HIGH;
416b7e1c893Smrg
417b7e1c893Smrg	/* XXX some R300 and R400 can actually do this */
418b7e1c893Smrg	if (!IS_AVIVO_VARIANT)
419b7e1c893Smrg	    return MODE_CLOCK_HIGH;
420b7e1c893Smrg
421b7e1c893Smrg	/* XXX and some AVIVO can't */
422b7e1c893Smrg    }
423b7e1c893Smrg
424b7e1c893Smrg    if (radeon_output->active_device & (ATOM_DEVICE_LCD_SUPPORT)) {
425209ff23fSmrg	if (radeon_output->rmx_type == RMX_OFF) {
426b7e1c893Smrg	    if (pMode->HDisplay != native_mode->PanelXRes ||
427b7e1c893Smrg		pMode->VDisplay != native_mode->PanelYRes)
428209ff23fSmrg		return MODE_PANEL;
429209ff23fSmrg	}
430b7e1c893Smrg	if (pMode->HDisplay > native_mode->PanelXRes ||
431b7e1c893Smrg	    pMode->VDisplay > native_mode->PanelYRes)
432209ff23fSmrg	    return MODE_PANEL;
433209ff23fSmrg    }
434209ff23fSmrg
435209ff23fSmrg    return MODE_OK;
436209ff23fSmrg}
437209ff23fSmrg
438209ff23fSmrgstatic Bool
439209ff23fSmrgradeon_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
440209ff23fSmrg		    DisplayModePtr adjusted_mode)
441209ff23fSmrg{
442209ff23fSmrg    RADEONInfoPtr info = RADEONPTR(output->scrn);
443209ff23fSmrg    RADEONOutputPrivatePtr radeon_output = output->driver_private;
444b7e1c893Smrg    radeon_native_mode_ptr native_mode = &radeon_output->native_mode;
445209ff23fSmrg
446209ff23fSmrg    radeon_output->Flags &= ~RADEON_USE_RMX;
447209ff23fSmrg
448b7e1c893Smrg    /*
449b7e1c893Smrg     *  Refresh the Crtc values without INTERLACE_HALVE_V
450b7e1c893Smrg     *  Should we use output->scrn->adjustFlags like xf86RandRModeConvert() does?
451b7e1c893Smrg     */
452b7e1c893Smrg    xf86SetModeCrtc(adjusted_mode, 0);
453b7e1c893Smrg
454209ff23fSmrg    /* decide if we are using RMX */
455b7e1c893Smrg    if ((radeon_output->active_device & (ATOM_DEVICE_LCD_SUPPORT | ATOM_DEVICE_DFP_SUPPORT))
456209ff23fSmrg	&& radeon_output->rmx_type != RMX_OFF) {
457209ff23fSmrg	xf86CrtcPtr crtc = output->crtc;
458209ff23fSmrg	RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
459209ff23fSmrg
460209ff23fSmrg	if (IS_AVIVO_VARIANT || radeon_crtc->crtc_id == 0) {
461b7e1c893Smrg	    if (mode->HDisplay < native_mode->PanelXRes ||
462b7e1c893Smrg		mode->VDisplay < native_mode->PanelYRes) {
463209ff23fSmrg		radeon_output->Flags |= RADEON_USE_RMX;
464209ff23fSmrg		if (IS_AVIVO_VARIANT) {
465209ff23fSmrg		    /* set to the panel's native mode */
466b7e1c893Smrg		    adjusted_mode->HDisplay = native_mode->PanelXRes;
467b7e1c893Smrg		    adjusted_mode->VDisplay = native_mode->PanelYRes;
468b7e1c893Smrg		    adjusted_mode->HTotal = native_mode->PanelXRes + native_mode->HBlank;
469b7e1c893Smrg		    adjusted_mode->HSyncStart = native_mode->PanelXRes + native_mode->HOverPlus;
470b7e1c893Smrg		    adjusted_mode->HSyncEnd = adjusted_mode->HSyncStart + native_mode->HSyncWidth;
471b7e1c893Smrg		    adjusted_mode->VTotal = native_mode->PanelYRes + native_mode->VBlank;
472b7e1c893Smrg		    adjusted_mode->VSyncStart = native_mode->PanelYRes + native_mode->VOverPlus;
473b7e1c893Smrg		    adjusted_mode->VSyncEnd = adjusted_mode->VSyncStart + native_mode->VSyncWidth;
474209ff23fSmrg		    /* update crtc values */
475209ff23fSmrg		    xf86SetModeCrtc(adjusted_mode, INTERLACE_HALVE_V);
476209ff23fSmrg		    /* adjust crtc values */
477b7e1c893Smrg		    adjusted_mode->CrtcHDisplay = native_mode->PanelXRes;
478b7e1c893Smrg		    adjusted_mode->CrtcVDisplay = native_mode->PanelYRes;
479b7e1c893Smrg		    adjusted_mode->CrtcHTotal = adjusted_mode->CrtcHDisplay + native_mode->HBlank;
480b7e1c893Smrg		    adjusted_mode->CrtcHSyncStart = adjusted_mode->CrtcHDisplay + native_mode->HOverPlus;
481b7e1c893Smrg		    adjusted_mode->CrtcHSyncEnd = adjusted_mode->CrtcHSyncStart + native_mode->HSyncWidth;
482b7e1c893Smrg		    adjusted_mode->CrtcVTotal = adjusted_mode->CrtcVDisplay + native_mode->VBlank;
483b7e1c893Smrg		    adjusted_mode->CrtcVSyncStart = adjusted_mode->CrtcVDisplay + native_mode->VOverPlus;
484b7e1c893Smrg		    adjusted_mode->CrtcVSyncEnd = adjusted_mode->CrtcVSyncStart + native_mode->VSyncWidth;
485209ff23fSmrg		} else {
486209ff23fSmrg		    /* set to the panel's native mode */
487b7e1c893Smrg		    adjusted_mode->HTotal = native_mode->PanelXRes + native_mode->HBlank;
488b7e1c893Smrg		    adjusted_mode->HSyncStart = native_mode->PanelXRes + native_mode->HOverPlus;
489b7e1c893Smrg		    adjusted_mode->HSyncEnd = adjusted_mode->HSyncStart + native_mode->HSyncWidth;
490b7e1c893Smrg		    adjusted_mode->VTotal = native_mode->PanelYRes + native_mode->VBlank;
491b7e1c893Smrg		    adjusted_mode->VSyncStart = native_mode->PanelYRes + native_mode->VOverPlus;
492b7e1c893Smrg		    adjusted_mode->VSyncEnd = adjusted_mode->VSyncStart + native_mode->VSyncWidth;
493b7e1c893Smrg		    adjusted_mode->Clock = native_mode->DotClock;
494209ff23fSmrg		    /* update crtc values */
495209ff23fSmrg		    xf86SetModeCrtc(adjusted_mode, INTERLACE_HALVE_V);
496209ff23fSmrg		    /* adjust crtc values */
497b7e1c893Smrg		    adjusted_mode->CrtcHTotal = adjusted_mode->CrtcHDisplay + native_mode->HBlank;
498b7e1c893Smrg		    adjusted_mode->CrtcHSyncStart = adjusted_mode->CrtcHDisplay + native_mode->HOverPlus;
499b7e1c893Smrg		    adjusted_mode->CrtcHSyncEnd = adjusted_mode->CrtcHSyncStart + native_mode->HSyncWidth;
500b7e1c893Smrg		    adjusted_mode->CrtcVTotal = adjusted_mode->CrtcVDisplay + native_mode->VBlank;
501b7e1c893Smrg		    adjusted_mode->CrtcVSyncStart = adjusted_mode->CrtcVDisplay + native_mode->VOverPlus;
502b7e1c893Smrg		    adjusted_mode->CrtcVSyncEnd = adjusted_mode->CrtcVSyncStart + native_mode->VSyncWidth;
503209ff23fSmrg		}
504b7e1c893Smrg		adjusted_mode->Clock = native_mode->DotClock;
505b7e1c893Smrg		adjusted_mode->Flags = native_mode->Flags;
506209ff23fSmrg	    }
507209ff23fSmrg	}
508209ff23fSmrg    }
509209ff23fSmrg
510b7e1c893Smrg    if (IS_AVIVO_VARIANT) {
511b7e1c893Smrg	/* hw bug */
512b7e1c893Smrg	if ((mode->Flags & V_INTERLACE)
513b7e1c893Smrg	    && (adjusted_mode->CrtcVSyncStart < (adjusted_mode->CrtcVDisplay + 2)))
514b7e1c893Smrg	    adjusted_mode->CrtcVSyncStart = adjusted_mode->CrtcVDisplay + 2;
515b7e1c893Smrg    }
516b7e1c893Smrg
517209ff23fSmrg    return TRUE;
518209ff23fSmrg}
519209ff23fSmrg
520209ff23fSmrgstatic void
521209ff23fSmrgradeon_mode_prepare(xf86OutputPtr output)
522209ff23fSmrg{
523209ff23fSmrg    radeon_bios_output_lock(output, TRUE);
524209ff23fSmrg    radeon_dpms(output, DPMSModeOff);
525209ff23fSmrg}
526209ff23fSmrg
527209ff23fSmrgstatic void
528209ff23fSmrgradeon_mode_set(xf86OutputPtr output, DisplayModePtr mode,
529209ff23fSmrg		DisplayModePtr adjusted_mode)
530209ff23fSmrg{
531209ff23fSmrg    RADEONInfoPtr info = RADEONPTR(output->scrn);
532209ff23fSmrg
533b7e1c893Smrg    if (IS_AVIVO_VARIANT || info->r4xx_atom)
534209ff23fSmrg	atombios_output_mode_set(output, mode, adjusted_mode);
535209ff23fSmrg    else
536209ff23fSmrg	legacy_output_mode_set(output, mode, adjusted_mode);
537209ff23fSmrg    radeon_bios_output_crtc(output);
538209ff23fSmrg
539209ff23fSmrg}
540209ff23fSmrg
541209ff23fSmrgstatic void
542209ff23fSmrgradeon_mode_commit(xf86OutputPtr output)
543209ff23fSmrg{
544209ff23fSmrg    radeon_dpms(output, DPMSModeOn);
545209ff23fSmrg    radeon_bios_output_lock(output, FALSE);
546209ff23fSmrg}
547209ff23fSmrg
548209ff23fSmrgstatic void
549209ff23fSmrgradeon_bios_output_lock(xf86OutputPtr output, Bool lock)
550209ff23fSmrg{
551209ff23fSmrg    ScrnInfoPtr	    pScrn = output->scrn;
552209ff23fSmrg    RADEONInfoPtr info = RADEONPTR(pScrn);
553209ff23fSmrg    unsigned char *RADEONMMIO = info->MMIO;
554209ff23fSmrg    RADEONSavePtr save = info->ModeReg;
555209ff23fSmrg
556209ff23fSmrg    if (info->IsAtomBios) {
557209ff23fSmrg	if (lock) {
558209ff23fSmrg	    save->bios_6_scratch |= ATOM_S6_CRITICAL_STATE;
559209ff23fSmrg	} else {
560209ff23fSmrg	    save->bios_6_scratch &= ~ATOM_S6_CRITICAL_STATE;
561209ff23fSmrg	}
562209ff23fSmrg    } else {
563209ff23fSmrg	if (lock) {
564209ff23fSmrg	    save->bios_6_scratch |= RADEON_DRIVER_CRITICAL;
565209ff23fSmrg	} else {
566209ff23fSmrg	    save->bios_6_scratch &= ~RADEON_DRIVER_CRITICAL;
567209ff23fSmrg	}
568209ff23fSmrg    }
569209ff23fSmrg    if (info->ChipFamily >= CHIP_FAMILY_R600)
570209ff23fSmrg	OUTREG(R600_BIOS_6_SCRATCH, save->bios_6_scratch);
571209ff23fSmrg    else
572209ff23fSmrg	OUTREG(RADEON_BIOS_6_SCRATCH, save->bios_6_scratch);
573209ff23fSmrg}
574209ff23fSmrg
575209ff23fSmrgstatic void
576209ff23fSmrgradeon_bios_output_dpms(xf86OutputPtr output, int mode)
577209ff23fSmrg{
578209ff23fSmrg    ScrnInfoPtr	    pScrn = output->scrn;
579209ff23fSmrg    RADEONInfoPtr info = RADEONPTR(pScrn);
580209ff23fSmrg    RADEONOutputPrivatePtr radeon_output = output->driver_private;
581209ff23fSmrg    unsigned char *RADEONMMIO = info->MMIO;
582209ff23fSmrg    RADEONSavePtr save = info->ModeReg;
583209ff23fSmrg
584209ff23fSmrg    if (info->IsAtomBios) {
585b7e1c893Smrg	if (radeon_output->active_device & ATOM_DEVICE_TV1_SUPPORT) {
586b7e1c893Smrg	    if (mode == DPMSModeOn)
587b7e1c893Smrg		save->bios_2_scratch &= ~ATOM_S2_TV1_DPMS_STATE;
588b7e1c893Smrg	    else
589b7e1c893Smrg		save->bios_2_scratch |= ATOM_S2_TV1_DPMS_STATE;
590b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_CV_SUPPORT) {
591b7e1c893Smrg	    if (mode == DPMSModeOn)
592b7e1c893Smrg		save->bios_2_scratch &= ~ATOM_S2_CV_DPMS_STATE;
593b7e1c893Smrg	    else
594b7e1c893Smrg		save->bios_2_scratch |= ATOM_S2_CV_DPMS_STATE;
595b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_CRT1_SUPPORT) {
596b7e1c893Smrg	    if (mode == DPMSModeOn)
597b7e1c893Smrg		save->bios_2_scratch &= ~ATOM_S2_CRT1_DPMS_STATE;
598b7e1c893Smrg	    else
599b7e1c893Smrg		save->bios_2_scratch |= ATOM_S2_CRT1_DPMS_STATE;
600b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_CRT2_SUPPORT) {
601b7e1c893Smrg	    if (mode == DPMSModeOn)
602b7e1c893Smrg		save->bios_2_scratch &= ~ATOM_S2_CRT2_DPMS_STATE;
603b7e1c893Smrg	    else
604b7e1c893Smrg		save->bios_2_scratch |= ATOM_S2_CRT2_DPMS_STATE;
605b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_LCD1_SUPPORT) {
606b7e1c893Smrg	    if (mode == DPMSModeOn)
607b7e1c893Smrg		save->bios_2_scratch &= ~ATOM_S2_LCD1_DPMS_STATE;
608b7e1c893Smrg	    else
609b7e1c893Smrg		save->bios_2_scratch |= ATOM_S2_LCD1_DPMS_STATE;
610b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_DFP1_SUPPORT) {
611b7e1c893Smrg	    if (mode == DPMSModeOn)
612b7e1c893Smrg		save->bios_2_scratch &= ~ATOM_S2_DFP1_DPMS_STATE;
613b7e1c893Smrg	    else
614b7e1c893Smrg		save->bios_2_scratch |= ATOM_S2_DFP1_DPMS_STATE;
615b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_DFP2_SUPPORT) {
616b7e1c893Smrg	    if (mode == DPMSModeOn)
617b7e1c893Smrg		save->bios_2_scratch &= ~ATOM_S2_DFP2_DPMS_STATE;
618b7e1c893Smrg	    else
619b7e1c893Smrg		save->bios_2_scratch |= ATOM_S2_DFP2_DPMS_STATE;
620b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_DFP3_SUPPORT) {
621b7e1c893Smrg	    if (mode == DPMSModeOn)
622b7e1c893Smrg		save->bios_2_scratch &= ~ATOM_S2_DFP3_DPMS_STATE;
623b7e1c893Smrg	    else
624b7e1c893Smrg		save->bios_2_scratch |= ATOM_S2_DFP3_DPMS_STATE;
625b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_DFP4_SUPPORT) {
626b7e1c893Smrg	    if (mode == DPMSModeOn)
627b7e1c893Smrg		save->bios_2_scratch &= ~ATOM_S2_DFP4_DPMS_STATE;
628b7e1c893Smrg	    else
629b7e1c893Smrg		save->bios_2_scratch |= ATOM_S2_DFP4_DPMS_STATE;
630b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_DFP5_SUPPORT) {
631b7e1c893Smrg	    if (mode == DPMSModeOn)
632b7e1c893Smrg		save->bios_2_scratch &= ~ATOM_S2_DFP5_DPMS_STATE;
633b7e1c893Smrg	    else
634b7e1c893Smrg		save->bios_2_scratch |= ATOM_S2_DFP5_DPMS_STATE;
635209ff23fSmrg	}
636b7e1c893Smrg	if (info->ChipFamily >= CHIP_FAMILY_R600)
637209ff23fSmrg	    OUTREG(R600_BIOS_2_SCRATCH, save->bios_2_scratch);
638b7e1c893Smrg	else
639209ff23fSmrg	    OUTREG(RADEON_BIOS_2_SCRATCH, save->bios_2_scratch);
640209ff23fSmrg    } else {
641209ff23fSmrg	if (mode == DPMSModeOn) {
642209ff23fSmrg	    save->bios_6_scratch &= ~(RADEON_DPMS_MASK | RADEON_SCREEN_BLANKING);
643209ff23fSmrg	    save->bios_6_scratch |= RADEON_DPMS_ON;
644209ff23fSmrg	} else {
645209ff23fSmrg	    save->bios_6_scratch &= ~RADEON_DPMS_MASK;
646209ff23fSmrg	    save->bios_6_scratch |= (RADEON_DPMS_OFF | RADEON_SCREEN_BLANKING);
647b7e1c893Smrg	}
648b7e1c893Smrg	if (radeon_output->active_device & ATOM_DEVICE_TV1_SUPPORT) {
649b7e1c893Smrg	    if (mode == DPMSModeOn)
650b7e1c893Smrg		save->bios_6_scratch |= RADEON_TV_DPMS_ON;
651b7e1c893Smrg	    else
652209ff23fSmrg		save->bios_6_scratch &= ~RADEON_TV_DPMS_ON;
653b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_CRT1_SUPPORT) {
654b7e1c893Smrg	    if (mode == DPMSModeOn)
655b7e1c893Smrg		save->bios_6_scratch |= RADEON_CRT_DPMS_ON;
656b7e1c893Smrg	    else
657209ff23fSmrg		save->bios_6_scratch &= ~RADEON_CRT_DPMS_ON;
658b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_CRT2_SUPPORT) {
659b7e1c893Smrg	    if (mode == DPMSModeOn)
660b7e1c893Smrg		save->bios_6_scratch |= RADEON_CRT_DPMS_ON;
661b7e1c893Smrg	    else
662b7e1c893Smrg		save->bios_6_scratch &= ~RADEON_CRT_DPMS_ON;
663b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_LCD1_SUPPORT) {
664b7e1c893Smrg	    if (mode == DPMSModeOn)
665b7e1c893Smrg		save->bios_6_scratch |= RADEON_LCD_DPMS_ON;
666b7e1c893Smrg	    else
667209ff23fSmrg		save->bios_6_scratch &= ~RADEON_LCD_DPMS_ON;
668b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_DFP1_SUPPORT) {
669b7e1c893Smrg	    if (mode == DPMSModeOn)
670b7e1c893Smrg		save->bios_6_scratch |= RADEON_DFP_DPMS_ON;
671b7e1c893Smrg	    else
672b7e1c893Smrg		save->bios_6_scratch &= ~RADEON_DFP_DPMS_ON;
673b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_DFP2_SUPPORT) {
674b7e1c893Smrg	    if (mode == DPMSModeOn)
675b7e1c893Smrg		save->bios_6_scratch |= RADEON_DFP_DPMS_ON;
676b7e1c893Smrg	    else
677209ff23fSmrg		save->bios_6_scratch &= ~RADEON_DFP_DPMS_ON;
678209ff23fSmrg	}
679209ff23fSmrg	OUTREG(RADEON_BIOS_6_SCRATCH, save->bios_6_scratch);
680209ff23fSmrg    }
681209ff23fSmrg}
682209ff23fSmrg
683209ff23fSmrgstatic void
684209ff23fSmrgradeon_bios_output_crtc(xf86OutputPtr output)
685209ff23fSmrg{
686209ff23fSmrg    ScrnInfoPtr	    pScrn = output->scrn;
687209ff23fSmrg    RADEONInfoPtr info = RADEONPTR(pScrn);
688209ff23fSmrg    RADEONOutputPrivatePtr radeon_output = output->driver_private;
689209ff23fSmrg    unsigned char *RADEONMMIO = info->MMIO;
690209ff23fSmrg    RADEONSavePtr save = info->ModeReg;
691209ff23fSmrg    xf86CrtcPtr crtc = output->crtc;
692209ff23fSmrg    RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
693209ff23fSmrg
694209ff23fSmrg    if (info->IsAtomBios) {
695b7e1c893Smrg	if (radeon_output->active_device & ATOM_DEVICE_TV1_SUPPORT) {
696b7e1c893Smrg	    save->bios_3_scratch &= ~ATOM_S3_TV1_CRTC_ACTIVE;
697b7e1c893Smrg	    save->bios_3_scratch |= (radeon_crtc->crtc_id << 18);
698b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_CV_SUPPORT) {
699b7e1c893Smrg	    save->bios_3_scratch &= ~ATOM_S3_CV_CRTC_ACTIVE;
700b7e1c893Smrg	    save->bios_3_scratch |= (radeon_crtc->crtc_id << 24);
701b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_CRT1_SUPPORT) {
702b7e1c893Smrg	    save->bios_3_scratch &= ~ATOM_S3_CRT1_CRTC_ACTIVE;
703b7e1c893Smrg	    save->bios_3_scratch |= (radeon_crtc->crtc_id << 16);
704b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_CRT2_SUPPORT) {
705b7e1c893Smrg	    save->bios_3_scratch &= ~ATOM_S3_CRT2_CRTC_ACTIVE;
706b7e1c893Smrg	    save->bios_3_scratch |= (radeon_crtc->crtc_id << 20);
707b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_LCD1_SUPPORT) {
708b7e1c893Smrg	    save->bios_3_scratch &= ~ATOM_S3_LCD1_CRTC_ACTIVE;
709b7e1c893Smrg	    save->bios_3_scratch |= (radeon_crtc->crtc_id << 17);
710b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_DFP1_SUPPORT) {
711b7e1c893Smrg	    save->bios_3_scratch &= ~ATOM_S3_DFP1_CRTC_ACTIVE;
712b7e1c893Smrg	    save->bios_3_scratch |= (radeon_crtc->crtc_id << 19);
713b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_DFP2_SUPPORT) {
714b7e1c893Smrg	    save->bios_3_scratch &= ~ATOM_S3_DFP2_CRTC_ACTIVE;
715b7e1c893Smrg	    save->bios_3_scratch |= (radeon_crtc->crtc_id << 23);
716b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_DFP3_SUPPORT) {
717b7e1c893Smrg	    save->bios_3_scratch &= ~ATOM_S3_DFP3_CRTC_ACTIVE;
718b7e1c893Smrg	    save->bios_3_scratch |= (radeon_crtc->crtc_id << 25);
719209ff23fSmrg	}
720209ff23fSmrg	if (info->ChipFamily >= CHIP_FAMILY_R600)
721209ff23fSmrg	    OUTREG(R600_BIOS_3_SCRATCH, save->bios_3_scratch);
722209ff23fSmrg	else
723209ff23fSmrg	    OUTREG(RADEON_BIOS_3_SCRATCH, save->bios_3_scratch);
724209ff23fSmrg    } else {
725b7e1c893Smrg	if (radeon_output->active_device & ATOM_DEVICE_TV1_SUPPORT) {
726209ff23fSmrg	    save->bios_5_scratch &= ~RADEON_TV1_CRTC_MASK;
727209ff23fSmrg	    save->bios_5_scratch |= (radeon_crtc->crtc_id << RADEON_TV1_CRTC_SHIFT);
728b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_CRT1_SUPPORT) {
729b7e1c893Smrg	    save->bios_5_scratch &= ~RADEON_CRT1_CRTC_MASK;
730b7e1c893Smrg	    save->bios_5_scratch |= (radeon_crtc->crtc_id << RADEON_CRT1_CRTC_SHIFT);
731b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_CRT2_SUPPORT) {
732b7e1c893Smrg	    save->bios_5_scratch &= ~RADEON_CRT2_CRTC_MASK;
733b7e1c893Smrg	    save->bios_5_scratch |= (radeon_crtc->crtc_id << RADEON_CRT2_CRTC_SHIFT);
734b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_LCD1_SUPPORT) {
735209ff23fSmrg	    save->bios_5_scratch &= ~RADEON_LCD1_CRTC_MASK;
736209ff23fSmrg	    save->bios_5_scratch |= (radeon_crtc->crtc_id << RADEON_LCD1_CRTC_SHIFT);
737b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_DFP1_SUPPORT) {
738b7e1c893Smrg	    save->bios_5_scratch &= ~RADEON_DFP1_CRTC_MASK;
739b7e1c893Smrg	    save->bios_5_scratch |= (radeon_crtc->crtc_id << RADEON_DFP1_CRTC_SHIFT);
740b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_DFP2_SUPPORT) {
741b7e1c893Smrg	    save->bios_5_scratch &= ~RADEON_DFP2_CRTC_MASK;
742b7e1c893Smrg	    save->bios_5_scratch |= (radeon_crtc->crtc_id << RADEON_DFP2_CRTC_SHIFT);
743209ff23fSmrg	}
744209ff23fSmrg	OUTREG(RADEON_BIOS_5_SCRATCH, save->bios_5_scratch);
745209ff23fSmrg    }
746209ff23fSmrg}
747209ff23fSmrg
748209ff23fSmrgstatic void
749209ff23fSmrgradeon_bios_output_connected(xf86OutputPtr output, Bool connected)
750209ff23fSmrg{
751209ff23fSmrg    ScrnInfoPtr	    pScrn = output->scrn;
752209ff23fSmrg    RADEONInfoPtr info = RADEONPTR(pScrn);
753209ff23fSmrg    RADEONOutputPrivatePtr radeon_output = output->driver_private;
754209ff23fSmrg    unsigned char *RADEONMMIO = info->MMIO;
755209ff23fSmrg    RADEONSavePtr save = info->ModeReg;
756209ff23fSmrg
757209ff23fSmrg    if (info->IsAtomBios) {
758b7e1c893Smrg	switch (radeon_output->active_device) {
759b7e1c893Smrg	case ATOM_DEVICE_TV1_SUPPORT:
760b7e1c893Smrg	    if (connected)
761b7e1c893Smrg		save->bios_3_scratch |= ATOM_S3_TV1_ACTIVE;
762b7e1c893Smrg	    else {
763b7e1c893Smrg		save->bios_0_scratch &= ~ATOM_S0_TV1_MASK;
764b7e1c893Smrg		save->bios_3_scratch &= ~ATOM_S3_TV1_ACTIVE;
765209ff23fSmrg	    }
766b7e1c893Smrg	    break;
767b7e1c893Smrg	case ATOM_DEVICE_CV_SUPPORT:
768b7e1c893Smrg	    if (connected)
769b7e1c893Smrg		save->bios_3_scratch |= ATOM_S3_CV_ACTIVE;
770b7e1c893Smrg	    else {
771b7e1c893Smrg		save->bios_0_scratch &= ~ATOM_S0_CV_MASK;
772b7e1c893Smrg		save->bios_3_scratch &= ~ATOM_S3_CV_ACTIVE;
773b7e1c893Smrg	    }
774b7e1c893Smrg	    break;
775b7e1c893Smrg	case ATOM_DEVICE_LCD1_SUPPORT:
776b7e1c893Smrg	    if (connected) {
777b7e1c893Smrg		save->bios_0_scratch |= ATOM_S0_LCD1;
778b7e1c893Smrg		save->bios_3_scratch |= ATOM_S3_LCD1_ACTIVE;
779b7e1c893Smrg	    } else {
780b7e1c893Smrg		save->bios_0_scratch &= ~ATOM_S0_LCD1;
781b7e1c893Smrg		save->bios_3_scratch &= ~ATOM_S3_LCD1_ACTIVE;
782b7e1c893Smrg	    }
783b7e1c893Smrg	    break;
784b7e1c893Smrg	case ATOM_DEVICE_CRT1_SUPPORT:
785b7e1c893Smrg	    if (connected) {
786b7e1c893Smrg		save->bios_0_scratch |= ATOM_S0_CRT1_COLOR;
787b7e1c893Smrg		save->bios_3_scratch |= ATOM_S3_CRT1_ACTIVE;
788b7e1c893Smrg	    } else {
789b7e1c893Smrg		save->bios_0_scratch &= ~ATOM_S0_CRT1_MASK;
790b7e1c893Smrg		save->bios_3_scratch &= ~ATOM_S3_CRT1_ACTIVE;
791b7e1c893Smrg	    }
792b7e1c893Smrg	    break;
793b7e1c893Smrg	case ATOM_DEVICE_CRT2_SUPPORT:
794b7e1c893Smrg	    if (connected) {
795b7e1c893Smrg		save->bios_0_scratch |= ATOM_S0_CRT2_COLOR;
796b7e1c893Smrg		save->bios_3_scratch |= ATOM_S3_CRT2_ACTIVE;
797b7e1c893Smrg	    } else {
798b7e1c893Smrg		save->bios_0_scratch &= ~ATOM_S0_CRT2_MASK;
799b7e1c893Smrg		save->bios_3_scratch &= ~ATOM_S3_CRT2_ACTIVE;
800b7e1c893Smrg	    }
801b7e1c893Smrg	    break;
802b7e1c893Smrg	case ATOM_DEVICE_DFP1_SUPPORT:
803b7e1c893Smrg	    if (connected) {
804b7e1c893Smrg		save->bios_0_scratch |= ATOM_S0_DFP1;
805b7e1c893Smrg		save->bios_3_scratch |= ATOM_S3_DFP1_ACTIVE;
806b7e1c893Smrg	    } else {
807b7e1c893Smrg		save->bios_0_scratch &= ~ATOM_S0_DFP1;
808b7e1c893Smrg		save->bios_3_scratch &= ~ATOM_S3_DFP1_ACTIVE;
809209ff23fSmrg	    }
810b7e1c893Smrg	    break;
811b7e1c893Smrg	case ATOM_DEVICE_DFP2_SUPPORT:
812b7e1c893Smrg	    if (connected) {
813b7e1c893Smrg		save->bios_0_scratch |= ATOM_S0_DFP2;
814b7e1c893Smrg		save->bios_3_scratch |= ATOM_S3_DFP2_ACTIVE;
815b7e1c893Smrg	    } else {
816b7e1c893Smrg		save->bios_0_scratch &= ~ATOM_S0_DFP2;
817b7e1c893Smrg		save->bios_3_scratch &= ~ATOM_S3_DFP2_ACTIVE;
818209ff23fSmrg	    }
819b7e1c893Smrg	    break;
820b7e1c893Smrg	case ATOM_DEVICE_DFP3_SUPPORT:
821b7e1c893Smrg	    if (connected) {
822b7e1c893Smrg		save->bios_0_scratch |= ATOM_S0_DFP3;
823b7e1c893Smrg		save->bios_3_scratch |= ATOM_S3_DFP3_ACTIVE;
824b7e1c893Smrg	    } else {
825b7e1c893Smrg		save->bios_0_scratch &= ~ATOM_S0_DFP3;
826b7e1c893Smrg		save->bios_3_scratch &= ~ATOM_S3_DFP3_ACTIVE;
827209ff23fSmrg	    }
828b7e1c893Smrg	    break;
829b7e1c893Smrg	case ATOM_DEVICE_DFP4_SUPPORT:
830b7e1c893Smrg	    if (connected) {
831b7e1c893Smrg		save->bios_0_scratch |= ATOM_S0_DFP4;
832b7e1c893Smrg		save->bios_3_scratch |= ATOM_S3_DFP4_ACTIVE;
833b7e1c893Smrg	    } else {
834b7e1c893Smrg		save->bios_0_scratch &= ~ATOM_S0_DFP4;
835b7e1c893Smrg		save->bios_3_scratch &= ~ATOM_S3_DFP4_ACTIVE;
836209ff23fSmrg	    }
837b7e1c893Smrg	    break;
838b7e1c893Smrg	case ATOM_DEVICE_DFP5_SUPPORT:
839b7e1c893Smrg	    if (connected) {
840b7e1c893Smrg		save->bios_0_scratch |= ATOM_S0_DFP5;
841b7e1c893Smrg		save->bios_3_scratch |= ATOM_S3_DFP5_ACTIVE;
842b7e1c893Smrg	    } else {
843b7e1c893Smrg		save->bios_0_scratch &= ~ATOM_S0_DFP5;
844b7e1c893Smrg		save->bios_3_scratch &= ~ATOM_S3_DFP5_ACTIVE;
845209ff23fSmrg	    }
846b7e1c893Smrg	    break;
847209ff23fSmrg	}
848b7e1c893Smrg	if (info->ChipFamily >= CHIP_FAMILY_R600) {
849209ff23fSmrg	    OUTREG(R600_BIOS_0_SCRATCH, save->bios_0_scratch);
850b7e1c893Smrg	    OUTREG(R600_BIOS_3_SCRATCH, save->bios_3_scratch);
851b7e1c893Smrg	} else {
852209ff23fSmrg	    OUTREG(RADEON_BIOS_0_SCRATCH, save->bios_0_scratch);
853b7e1c893Smrg	    OUTREG(RADEON_BIOS_3_SCRATCH, save->bios_3_scratch);
854b7e1c893Smrg	}
855209ff23fSmrg    } else {
856b7e1c893Smrg	switch (radeon_output->active_device) {
857b7e1c893Smrg	case ATOM_DEVICE_TV1_SUPPORT:
858b7e1c893Smrg	    if (connected) {
859b7e1c893Smrg		if (radeon_output->MonType == MT_STV)
860b7e1c893Smrg		    save->bios_4_scratch |= RADEON_TV1_ATTACHED_SVIDEO;
861b7e1c893Smrg		else if (radeon_output->MonType == MT_CTV)
862b7e1c893Smrg		    save->bios_4_scratch |= RADEON_TV1_ATTACHED_COMP;
863b7e1c893Smrg		save->bios_5_scratch |= RADEON_TV1_ON;
864b7e1c893Smrg	    } else {
865b7e1c893Smrg		save->bios_4_scratch &= ~RADEON_TV1_ATTACHED_MASK;
866b7e1c893Smrg		save->bios_5_scratch &= ~RADEON_TV1_ON;
867b7e1c893Smrg	    }
868b7e1c893Smrg	    break;
869b7e1c893Smrg	case ATOM_DEVICE_LCD1_SUPPORT:
870b7e1c893Smrg	    if (connected) {
871209ff23fSmrg		save->bios_4_scratch |= RADEON_LCD1_ATTACHED;
872b7e1c893Smrg		save->bios_5_scratch |= RADEON_LCD1_ON;
873b7e1c893Smrg	    } else {
874b7e1c893Smrg		save->bios_4_scratch &= ~RADEON_LCD1_ATTACHED;
875b7e1c893Smrg		save->bios_5_scratch &= ~RADEON_LCD1_ON;
876209ff23fSmrg	    }
877b7e1c893Smrg	    break;
878b7e1c893Smrg	case ATOM_DEVICE_CRT1_SUPPORT:
879b7e1c893Smrg	    if (connected) {
880b7e1c893Smrg		save->bios_4_scratch |= RADEON_CRT1_ATTACHED_COLOR;
881b7e1c893Smrg		save->bios_5_scratch |= RADEON_CRT1_ON;
882b7e1c893Smrg	    } else {
883209ff23fSmrg		save->bios_4_scratch &= ~RADEON_CRT1_ATTACHED_MASK;
884b7e1c893Smrg		save->bios_5_scratch &= ~RADEON_CRT1_ON;
885b7e1c893Smrg	    }
886b7e1c893Smrg	    break;
887b7e1c893Smrg	case ATOM_DEVICE_CRT2_SUPPORT:
888b7e1c893Smrg	    if (connected) {
889b7e1c893Smrg		save->bios_4_scratch |= RADEON_CRT2_ATTACHED_COLOR;
890b7e1c893Smrg		save->bios_5_scratch |= RADEON_CRT2_ON;
891b7e1c893Smrg	    } else {
892b7e1c893Smrg		save->bios_4_scratch &= ~RADEON_CRT2_ATTACHED_MASK;
893b7e1c893Smrg		save->bios_5_scratch &= ~RADEON_CRT2_ON;
894b7e1c893Smrg	    }
895b7e1c893Smrg	    break;
896b7e1c893Smrg	case ATOM_DEVICE_DFP1_SUPPORT:
897b7e1c893Smrg	    if (connected) {
898b7e1c893Smrg		save->bios_4_scratch |= RADEON_DFP1_ATTACHED;
899b7e1c893Smrg		save->bios_5_scratch |= RADEON_DFP1_ON;
900b7e1c893Smrg	    } else {
901209ff23fSmrg		save->bios_4_scratch &= ~RADEON_DFP1_ATTACHED;
902b7e1c893Smrg		save->bios_5_scratch &= ~RADEON_DFP1_ON;
903b7e1c893Smrg	    }
904b7e1c893Smrg	    break;
905b7e1c893Smrg	case ATOM_DEVICE_DFP2_SUPPORT:
906b7e1c893Smrg	    if (connected) {
907b7e1c893Smrg		save->bios_4_scratch |= RADEON_DFP2_ATTACHED;
908b7e1c893Smrg		save->bios_5_scratch |= RADEON_DFP2_ON;
909b7e1c893Smrg	    } else {
910209ff23fSmrg		save->bios_4_scratch &= ~RADEON_DFP2_ATTACHED;
911b7e1c893Smrg		save->bios_5_scratch &= ~RADEON_DFP2_ON;
912b7e1c893Smrg	    }
913b7e1c893Smrg	    break;
914209ff23fSmrg	}
915209ff23fSmrg	OUTREG(RADEON_BIOS_4_SCRATCH, save->bios_4_scratch);
916b7e1c893Smrg	OUTREG(RADEON_BIOS_5_SCRATCH, save->bios_5_scratch);
917209ff23fSmrg    }
918209ff23fSmrg
919209ff23fSmrg}
920209ff23fSmrg
921209ff23fSmrgstatic xf86OutputStatus
922209ff23fSmrgradeon_detect(xf86OutputPtr output)
923209ff23fSmrg{
924209ff23fSmrg    ScrnInfoPtr	    pScrn = output->scrn;
925209ff23fSmrg    RADEONInfoPtr info = RADEONPTR(pScrn);
926209ff23fSmrg    RADEONOutputPrivatePtr radeon_output = output->driver_private;
927209ff23fSmrg    Bool connected = TRUE;
928209ff23fSmrg
929209ff23fSmrg    radeon_output->MonType = MT_UNKNOWN;
930209ff23fSmrg    radeon_bios_output_connected(output, FALSE);
931b7e1c893Smrg    radeon_output->MonType = radeon_ddc_connected(output);
932b7e1c893Smrg    if (!radeon_output->MonType) {
933b7e1c893Smrg	if (radeon_output->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
934b7e1c893Smrg	    if (xf86ReturnOptValBool(info->Options, OPTION_IGNORE_LID_STATUS, TRUE))
935b7e1c893Smrg		radeon_output->MonType = MT_LCD;
936b7e1c893Smrg	    else
937b7e1c893Smrg#if defined(__powerpc__)
938b7e1c893Smrg		radeon_output->MonType = MT_LCD;
939b7e1c893Smrg#else
940b7e1c893Smrg	        radeon_output->MonType = RADEONDetectLidStatus(pScrn);
941b7e1c893Smrg#endif
942b7e1c893Smrg	} else {
943b7e1c893Smrg	    if (info->IsAtomBios)
944b7e1c893Smrg		radeon_output->MonType = atombios_dac_detect(output);
945b7e1c893Smrg	    else
946b7e1c893Smrg		radeon_output->MonType = legacy_dac_detect(output);
947b7e1c893Smrg	}
948b7e1c893Smrg    }
949b7e1c893Smrg
950b7e1c893Smrg    // if size is zero panel probably broken or not connected
951b7e1c893Smrg    if (radeon_output->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
952b7e1c893Smrg	radeon_encoder_ptr radeon_encoder = info->encoders[ATOM_DEVICE_LCD1_INDEX];
953b7e1c893Smrg	if (radeon_encoder) {
954b7e1c893Smrg	    radeon_lvds_ptr lvds = (radeon_lvds_ptr)radeon_encoder->dev_priv;
955b7e1c893Smrg	    if (lvds) {
956b7e1c893Smrg		if ((lvds->native_mode.PanelXRes == 0) || (lvds->native_mode.PanelYRes == 0))
957b7e1c893Smrg		    radeon_output->MonType = MT_NONE;
958b7e1c893Smrg	    }
959b7e1c893Smrg	}
960b7e1c893Smrg    }
961b7e1c893Smrg
962b7e1c893Smrg
963b7e1c893Smrg    if (output->MonInfo) {
964b7e1c893Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "EDID data from the display on output: %s ----------------------\n",
965b7e1c893Smrg		   output->name);
966b7e1c893Smrg	xf86PrintEDID( output->MonInfo );
967b7e1c893Smrg    }
968209ff23fSmrg
969209ff23fSmrg    /* nothing connected, light up some defaults so the server comes up */
970209ff23fSmrg    if (radeon_output->MonType == MT_NONE &&
971209ff23fSmrg	info->first_load_no_devices) {
972209ff23fSmrg	if (info->IsMobility) {
973b7e1c893Smrg	    if (radeon_output->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
974209ff23fSmrg		radeon_output->MonType = MT_LCD;
975209ff23fSmrg		info->first_load_no_devices = FALSE;
976b7e1c893Smrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Using LCD default\n");
977209ff23fSmrg	    }
978209ff23fSmrg	} else {
979b7e1c893Smrg	    if (radeon_output->devices & (ATOM_DEVICE_CRT_SUPPORT)) {
980209ff23fSmrg		radeon_output->MonType = MT_CRT;
981209ff23fSmrg		info->first_load_no_devices = FALSE;
982b7e1c893Smrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Using CRT default\n");
983b7e1c893Smrg	    } else if (radeon_output->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
984209ff23fSmrg		radeon_output->MonType = MT_DFP;
985209ff23fSmrg		info->first_load_no_devices = FALSE;
986b7e1c893Smrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Using DFP default\n");
987209ff23fSmrg	    }
988209ff23fSmrg	}
989209ff23fSmrg    }
990209ff23fSmrg
991209ff23fSmrg    radeon_bios_output_connected(output, TRUE);
992209ff23fSmrg
993209ff23fSmrg    /* set montype so users can force outputs on even if detection fails */
994209ff23fSmrg    if (radeon_output->MonType == MT_NONE) {
995209ff23fSmrg	connected = FALSE;
996b7e1c893Smrg	switch (radeon_output->ConnectorType) {
997b7e1c893Smrg	case CONNECTOR_LVDS:
998209ff23fSmrg	    radeon_output->MonType = MT_LCD;
999b7e1c893Smrg	    break;
1000b7e1c893Smrg	case CONNECTOR_DVI_D:
1001b7e1c893Smrg	case CONNECTOR_HDMI_TYPE_A:
1002b7e1c893Smrg	case CONNECTOR_HDMI_TYPE_B:
1003209ff23fSmrg	    radeon_output->MonType = MT_DFP;
1004b7e1c893Smrg	    break;
1005b7e1c893Smrg	case CONNECTOR_VGA:
1006b7e1c893Smrg	case CONNECTOR_DVI_A:
1007b7e1c893Smrg	default:
1008209ff23fSmrg	    radeon_output->MonType = MT_CRT;
1009b7e1c893Smrg	    break;
1010b7e1c893Smrg	case CONNECTOR_DVI_I:
1011209ff23fSmrg	    if (radeon_output->DVIType == DVI_ANALOG)
1012209ff23fSmrg		radeon_output->MonType = MT_CRT;
1013209ff23fSmrg	    else if (radeon_output->DVIType == DVI_DIGITAL)
1014209ff23fSmrg		radeon_output->MonType = MT_DFP;
1015b7e1c893Smrg	    break;
1016b7e1c893Smrg	case CONNECTOR_STV:
1017b7e1c893Smrg            radeon_output->MonType = MT_STV;
1018b7e1c893Smrg	    break;
1019b7e1c893Smrg	case CONNECTOR_CTV:
1020b7e1c893Smrg            radeon_output->MonType = MT_CTV;
1021b7e1c893Smrg	    break;
1022b7e1c893Smrg	case CONNECTOR_DIN:
1023b7e1c893Smrg            radeon_output->MonType = MT_CV;
1024b7e1c893Smrg	    break;
1025b7e1c893Smrg	case CONNECTOR_DISPLAY_PORT:
1026b7e1c893Smrg	    radeon_output->MonType = MT_DP;
1027b7e1c893Smrg	    break;
1028209ff23fSmrg	}
1029209ff23fSmrg    }
1030209ff23fSmrg
1031b7e1c893Smrg    radeon_set_active_device(output);
1032209ff23fSmrg
1033b7e1c893Smrg    if (radeon_output->active_device & (ATOM_DEVICE_LCD_SUPPORT | ATOM_DEVICE_DFP_SUPPORT))
1034b7e1c893Smrg	output->subpixel_order = SubPixelHorizontalRGB;
1035b7e1c893Smrg    else
1036b7e1c893Smrg	output->subpixel_order = SubPixelNone;
1037209ff23fSmrg
1038b7e1c893Smrg    if (connected)
1039b7e1c893Smrg	return XF86OutputStatusConnected;
1040b7e1c893Smrg    else
1041b7e1c893Smrg	return XF86OutputStatusDisconnected;
1042209ff23fSmrg}
1043209ff23fSmrg
1044209ff23fSmrgstatic DisplayModePtr
1045209ff23fSmrgradeon_get_modes(xf86OutputPtr output)
1046209ff23fSmrg{
1047209ff23fSmrg  DisplayModePtr modes;
1048209ff23fSmrg  modes = RADEONProbeOutputModes(output);
1049209ff23fSmrg  return modes;
1050209ff23fSmrg}
1051209ff23fSmrg
1052209ff23fSmrgstatic void
1053209ff23fSmrgradeon_destroy (xf86OutputPtr output)
1054209ff23fSmrg{
1055209ff23fSmrg    if (output->driver_private)
1056209ff23fSmrg        xfree(output->driver_private);
1057209ff23fSmrg}
1058209ff23fSmrg
1059209ff23fSmrgstatic void
1060209ff23fSmrgradeon_set_backlight_level(xf86OutputPtr output, int level)
1061209ff23fSmrg{
1062209ff23fSmrg#if 0
1063209ff23fSmrg    ScrnInfoPtr pScrn = output->scrn;
1064209ff23fSmrg    RADEONInfoPtr info = RADEONPTR(pScrn);
1065209ff23fSmrg    unsigned char * RADEONMMIO = info->MMIO;
1066209ff23fSmrg    uint32_t lvds_gen_cntl;
1067209ff23fSmrg
1068209ff23fSmrg    lvds_gen_cntl = INREG(RADEON_LVDS_GEN_CNTL);
1069209ff23fSmrg    lvds_gen_cntl |= RADEON_LVDS_BL_MOD_EN;
1070209ff23fSmrg    lvds_gen_cntl &= ~RADEON_LVDS_BL_MOD_LEVEL_MASK;
1071209ff23fSmrg    lvds_gen_cntl |= (level << RADEON_LVDS_BL_MOD_LEVEL_SHIFT) & RADEON_LVDS_BL_MOD_LEVEL_MASK;
1072209ff23fSmrg    //usleep (radeon_output->PanelPwrDly * 1000);
1073209ff23fSmrg    OUTREG(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl);
1074209ff23fSmrg    lvds_gen_cntl &= ~RADEON_LVDS_BL_MOD_EN;
1075209ff23fSmrg    //usleep (radeon_output->PanelPwrDly * 1000);
1076209ff23fSmrg    OUTREG(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl);
1077209ff23fSmrg#endif
1078209ff23fSmrg}
1079209ff23fSmrg
1080209ff23fSmrgstatic Atom backlight_atom;
1081209ff23fSmrgstatic Atom tmds_pll_atom;
1082209ff23fSmrgstatic Atom rmx_atom;
1083209ff23fSmrgstatic Atom monitor_type_atom;
1084209ff23fSmrgstatic Atom load_detection_atom;
1085209ff23fSmrgstatic Atom coherent_mode_atom;
1086209ff23fSmrgstatic Atom tv_hsize_atom;
1087209ff23fSmrgstatic Atom tv_hpos_atom;
1088209ff23fSmrgstatic Atom tv_vpos_atom;
1089209ff23fSmrgstatic Atom tv_std_atom;
1090209ff23fSmrg#define RADEON_MAX_BACKLIGHT_LEVEL 255
1091209ff23fSmrg
1092209ff23fSmrgstatic void
1093209ff23fSmrgradeon_create_resources(xf86OutputPtr output)
1094209ff23fSmrg{
1095209ff23fSmrg    ScrnInfoPtr pScrn = output->scrn;
1096209ff23fSmrg    RADEONInfoPtr info = RADEONPTR(pScrn);
1097209ff23fSmrg    RADEONOutputPrivatePtr radeon_output = output->driver_private;
1098209ff23fSmrg    INT32 range[2];
1099209ff23fSmrg    int data, err;
1100209ff23fSmrg    const char *s;
1101209ff23fSmrg
1102b7e1c893Smrg#if 0
1103209ff23fSmrg    /* backlight control */
1104209ff23fSmrg    if (radeon_output->type == OUTPUT_LVDS) {
1105209ff23fSmrg	backlight_atom = MAKE_ATOM("backlight");
1106209ff23fSmrg
1107209ff23fSmrg	range[0] = 0;
1108209ff23fSmrg	range[1] = RADEON_MAX_BACKLIGHT_LEVEL;
1109209ff23fSmrg	err = RRConfigureOutputProperty(output->randr_output, backlight_atom,
1110209ff23fSmrg					FALSE, TRUE, FALSE, 2, range);
1111209ff23fSmrg	if (err != 0) {
1112209ff23fSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1113209ff23fSmrg		       "RRConfigureOutputProperty error, %d\n", err);
1114209ff23fSmrg	}
1115209ff23fSmrg	/* Set the current value of the backlight property */
1116209ff23fSmrg	//data = (info->SavedReg->lvds_gen_cntl & RADEON_LVDS_BL_MOD_LEVEL_MASK) >> RADEON_LVDS_BL_MOD_LEVEL_SHIFT;
1117209ff23fSmrg	data = RADEON_MAX_BACKLIGHT_LEVEL;
1118209ff23fSmrg	err = RRChangeOutputProperty(output->randr_output, backlight_atom,
1119209ff23fSmrg				     XA_INTEGER, 32, PropModeReplace, 1, &data,
1120209ff23fSmrg				     FALSE, TRUE);
1121209ff23fSmrg	if (err != 0) {
1122209ff23fSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1123209ff23fSmrg		       "RRChangeOutputProperty error, %d\n", err);
1124209ff23fSmrg	}
1125209ff23fSmrg    }
1126b7e1c893Smrg#endif
1127209ff23fSmrg
1128b7e1c893Smrg    if (radeon_output->devices & (ATOM_DEVICE_CRT_SUPPORT | ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) {
1129209ff23fSmrg	load_detection_atom = MAKE_ATOM("load_detection");
1130209ff23fSmrg
1131209ff23fSmrg	range[0] = 0; /* off */
1132209ff23fSmrg	range[1] = 1; /* on */
1133209ff23fSmrg	err = RRConfigureOutputProperty(output->randr_output, load_detection_atom,
1134209ff23fSmrg					FALSE, TRUE, FALSE, 2, range);
1135209ff23fSmrg	if (err != 0) {
1136209ff23fSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1137209ff23fSmrg		       "RRConfigureOutputProperty error, %d\n", err);
1138209ff23fSmrg	}
1139209ff23fSmrg
1140209ff23fSmrg	if (radeon_output->load_detection)
1141b7e1c893Smrg	    data = 1;
1142209ff23fSmrg	else
1143b7e1c893Smrg	    data = 0;
1144209ff23fSmrg
1145209ff23fSmrg	err = RRChangeOutputProperty(output->randr_output, load_detection_atom,
1146209ff23fSmrg				     XA_INTEGER, 32, PropModeReplace, 1, &data,
1147209ff23fSmrg				     FALSE, TRUE);
1148209ff23fSmrg	if (err != 0) {
1149209ff23fSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1150209ff23fSmrg		       "RRChangeOutputProperty error, %d\n", err);
1151209ff23fSmrg	}
1152209ff23fSmrg    }
1153209ff23fSmrg
1154b7e1c893Smrg    if (IS_AVIVO_VARIANT && (radeon_output->devices & (ATOM_DEVICE_DFP_SUPPORT))) {
1155209ff23fSmrg	coherent_mode_atom = MAKE_ATOM("coherent_mode");
1156209ff23fSmrg
1157209ff23fSmrg	range[0] = 0; /* off */
1158209ff23fSmrg	range[1] = 1; /* on */
1159209ff23fSmrg	err = RRConfigureOutputProperty(output->randr_output, coherent_mode_atom,
1160209ff23fSmrg					FALSE, TRUE, FALSE, 2, range);
1161209ff23fSmrg	if (err != 0) {
1162209ff23fSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1163209ff23fSmrg		       "RRConfigureOutputProperty error, %d\n", err);
1164209ff23fSmrg	}
1165209ff23fSmrg
1166b7e1c893Smrg	data = 1; /* coherent mode on by default */
1167209ff23fSmrg
1168209ff23fSmrg	err = RRChangeOutputProperty(output->randr_output, coherent_mode_atom,
1169209ff23fSmrg				     XA_INTEGER, 32, PropModeReplace, 1, &data,
1170209ff23fSmrg				     FALSE, TRUE);
1171209ff23fSmrg	if (err != 0) {
1172209ff23fSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1173209ff23fSmrg		       "RRChangeOutputProperty error, %d\n", err);
1174209ff23fSmrg	}
1175209ff23fSmrg    }
1176209ff23fSmrg
1177b7e1c893Smrg    if ((!IS_AVIVO_VARIANT) && (radeon_output->devices & (ATOM_DEVICE_DFP2_SUPPORT))) {
1178209ff23fSmrg	tmds_pll_atom = MAKE_ATOM("tmds_pll");
1179209ff23fSmrg
1180209ff23fSmrg	err = RRConfigureOutputProperty(output->randr_output, tmds_pll_atom,
1181209ff23fSmrg					FALSE, FALSE, FALSE, 0, NULL);
1182209ff23fSmrg	if (err != 0) {
1183209ff23fSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1184209ff23fSmrg		       "RRConfigureOutputProperty error, %d\n", err);
1185209ff23fSmrg	}
1186209ff23fSmrg	/* Set the current value of the property */
1187209ff23fSmrg#if defined(__powerpc__)
1188209ff23fSmrg	s = "driver";
1189209ff23fSmrg#else
1190209ff23fSmrg	s = "bios";
1191209ff23fSmrg#endif
1192209ff23fSmrg	if (xf86ReturnOptValBool(info->Options, OPTION_DEFAULT_TMDS_PLL, FALSE)) {
1193209ff23fSmrg	    s = "driver";
1194209ff23fSmrg	}
1195209ff23fSmrg
1196209ff23fSmrg	err = RRChangeOutputProperty(output->randr_output, tmds_pll_atom,
1197209ff23fSmrg				     XA_STRING, 8, PropModeReplace, strlen(s), (pointer)s,
1198209ff23fSmrg				     FALSE, FALSE);
1199209ff23fSmrg	if (err != 0) {
1200209ff23fSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1201209ff23fSmrg		       "RRChangeOutputProperty error, %d\n", err);
1202209ff23fSmrg	}
1203209ff23fSmrg
1204209ff23fSmrg    }
1205209ff23fSmrg
1206209ff23fSmrg    /* RMX control - fullscreen, centered, keep ratio, off */
1207209ff23fSmrg    /* actually more of a crtc property as only crtc1 has rmx */
1208b7e1c893Smrg    if (radeon_output->devices & (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) {
1209209ff23fSmrg	rmx_atom = MAKE_ATOM("scaler");
1210209ff23fSmrg
1211209ff23fSmrg	err = RRConfigureOutputProperty(output->randr_output, rmx_atom,
1212209ff23fSmrg					FALSE, FALSE, FALSE, 0, NULL);
1213209ff23fSmrg	if (err != 0) {
1214209ff23fSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1215209ff23fSmrg		       "RRConfigureOutputProperty error, %d\n", err);
1216209ff23fSmrg	}
1217209ff23fSmrg	/* Set the current value of the property */
1218b7e1c893Smrg	switch (radeon_output->rmx_type) {
1219b7e1c893Smrg	case RMX_OFF:
1220b7e1c893Smrg	default:
1221209ff23fSmrg	    s = "off";
1222b7e1c893Smrg	    break;
1223b7e1c893Smrg	case RMX_FULL:
1224b7e1c893Smrg	    s = "full";
1225b7e1c893Smrg	    break;
1226b7e1c893Smrg	case RMX_CENTER:
1227b7e1c893Smrg	    s = "center";
1228b7e1c893Smrg	    break;
1229b7e1c893Smrg	case RMX_ASPECT:
1230b7e1c893Smrg	    s = "aspect";
1231b7e1c893Smrg	    break;
1232b7e1c893Smrg	}
1233209ff23fSmrg	err = RRChangeOutputProperty(output->randr_output, rmx_atom,
1234209ff23fSmrg				     XA_STRING, 8, PropModeReplace, strlen(s), (pointer)s,
1235209ff23fSmrg				     FALSE, FALSE);
1236209ff23fSmrg	if (err != 0) {
1237209ff23fSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1238209ff23fSmrg		       "RRChangeOutputProperty error, %d\n", err);
1239209ff23fSmrg	}
1240209ff23fSmrg    }
1241209ff23fSmrg
1242209ff23fSmrg    /* force auto/analog/digital for DVI-I ports */
1243b7e1c893Smrg    if ((radeon_output->devices & (ATOM_DEVICE_CRT_SUPPORT)) &&
1244b7e1c893Smrg	(radeon_output->devices & (ATOM_DEVICE_DFP_SUPPORT))){
1245209ff23fSmrg	monitor_type_atom = MAKE_ATOM("dvi_monitor_type");
1246209ff23fSmrg
1247209ff23fSmrg	err = RRConfigureOutputProperty(output->randr_output, monitor_type_atom,
1248209ff23fSmrg					FALSE, FALSE, FALSE, 0, NULL);
1249209ff23fSmrg	if (err != 0) {
1250209ff23fSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1251209ff23fSmrg		       "RRConfigureOutputProperty error, %d\n", err);
1252209ff23fSmrg	}
1253209ff23fSmrg	/* Set the current value of the backlight property */
1254209ff23fSmrg	s = "auto";
1255209ff23fSmrg	err = RRChangeOutputProperty(output->randr_output, monitor_type_atom,
1256209ff23fSmrg				     XA_STRING, 8, PropModeReplace, strlen(s), (pointer)s,
1257209ff23fSmrg				     FALSE, FALSE);
1258209ff23fSmrg	if (err != 0) {
1259209ff23fSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1260209ff23fSmrg		       "RRChangeOutputProperty error, %d\n", err);
1261209ff23fSmrg	}
1262209ff23fSmrg    }
1263209ff23fSmrg
1264b7e1c893Smrg    if (radeon_output->devices & (ATOM_DEVICE_TV_SUPPORT)) {
1265b7e1c893Smrg	radeon_tvout_ptr tvout = &radeon_output->tvout;
1266209ff23fSmrg	if (!IS_AVIVO_VARIANT) {
1267209ff23fSmrg	    tv_hsize_atom = MAKE_ATOM("tv_horizontal_size");
1268209ff23fSmrg
1269209ff23fSmrg	    range[0] = -MAX_H_SIZE;
1270209ff23fSmrg	    range[1] = MAX_H_SIZE;
1271209ff23fSmrg	    err = RRConfigureOutputProperty(output->randr_output, tv_hsize_atom,
1272209ff23fSmrg					    FALSE, TRUE, FALSE, 2, range);
1273209ff23fSmrg	    if (err != 0) {
1274209ff23fSmrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1275209ff23fSmrg			   "RRConfigureOutputProperty error, %d\n", err);
1276209ff23fSmrg	    }
1277209ff23fSmrg	    data = 0;
1278209ff23fSmrg	    err = RRChangeOutputProperty(output->randr_output, tv_hsize_atom,
1279209ff23fSmrg					 XA_INTEGER, 32, PropModeReplace, 1, &data,
1280209ff23fSmrg					 FALSE, TRUE);
1281209ff23fSmrg	    if (err != 0) {
1282209ff23fSmrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1283209ff23fSmrg			   "RRChangeOutputProperty error, %d\n", err);
1284209ff23fSmrg	    }
1285209ff23fSmrg
1286209ff23fSmrg	    tv_hpos_atom = MAKE_ATOM("tv_horizontal_position");
1287209ff23fSmrg
1288209ff23fSmrg	    range[0] = -MAX_H_POSITION;
1289209ff23fSmrg	    range[1] = MAX_H_POSITION;
1290209ff23fSmrg	    err = RRConfigureOutputProperty(output->randr_output, tv_hpos_atom,
1291209ff23fSmrg					    FALSE, TRUE, FALSE, 2, range);
1292209ff23fSmrg	    if (err != 0) {
1293209ff23fSmrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1294209ff23fSmrg			   "RRConfigureOutputProperty error, %d\n", err);
1295209ff23fSmrg	    }
1296209ff23fSmrg	    data = 0;
1297209ff23fSmrg	    err = RRChangeOutputProperty(output->randr_output, tv_hpos_atom,
1298209ff23fSmrg					 XA_INTEGER, 32, PropModeReplace, 1, &data,
1299209ff23fSmrg					 FALSE, TRUE);
1300209ff23fSmrg	    if (err != 0) {
1301209ff23fSmrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1302209ff23fSmrg			   "RRChangeOutputProperty error, %d\n", err);
1303209ff23fSmrg	    }
1304209ff23fSmrg
1305209ff23fSmrg	    tv_vpos_atom = MAKE_ATOM("tv_vertical_position");
1306209ff23fSmrg
1307209ff23fSmrg	    range[0] = -MAX_V_POSITION;
1308209ff23fSmrg	    range[1] = MAX_V_POSITION;
1309209ff23fSmrg	    err = RRConfigureOutputProperty(output->randr_output, tv_vpos_atom,
1310209ff23fSmrg					    FALSE, TRUE, FALSE, 2, range);
1311209ff23fSmrg	    if (err != 0) {
1312209ff23fSmrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1313209ff23fSmrg			   "RRConfigureOutputProperty error, %d\n", err);
1314209ff23fSmrg	    }
1315209ff23fSmrg	    data = 0;
1316209ff23fSmrg	    err = RRChangeOutputProperty(output->randr_output, tv_vpos_atom,
1317209ff23fSmrg					 XA_INTEGER, 32, PropModeReplace, 1, &data,
1318209ff23fSmrg					 FALSE, TRUE);
1319209ff23fSmrg	    if (err != 0) {
1320209ff23fSmrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1321209ff23fSmrg			   "RRChangeOutputProperty error, %d\n", err);
1322209ff23fSmrg	    }
1323209ff23fSmrg	}
1324209ff23fSmrg
1325209ff23fSmrg	tv_std_atom = MAKE_ATOM("tv_standard");
1326209ff23fSmrg
1327209ff23fSmrg	err = RRConfigureOutputProperty(output->randr_output, tv_std_atom,
1328209ff23fSmrg					FALSE, FALSE, FALSE, 0, NULL);
1329209ff23fSmrg	if (err != 0) {
1330209ff23fSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1331209ff23fSmrg		       "RRConfigureOutputProperty error, %d\n", err);
1332209ff23fSmrg	}
1333209ff23fSmrg
1334209ff23fSmrg	/* Set the current value of the property */
1335b7e1c893Smrg	switch (tvout->tvStd) {
1336209ff23fSmrg	case TV_STD_PAL:
1337209ff23fSmrg	    s = "pal";
1338209ff23fSmrg	    break;
1339209ff23fSmrg	case TV_STD_PAL_M:
1340209ff23fSmrg	    s = "pal-m";
1341209ff23fSmrg	    break;
1342209ff23fSmrg	case TV_STD_PAL_60:
1343209ff23fSmrg	    s = "pal-60";
1344209ff23fSmrg	    break;
1345209ff23fSmrg	case TV_STD_NTSC_J:
1346209ff23fSmrg	    s = "ntsc-j";
1347209ff23fSmrg	    break;
1348209ff23fSmrg	case TV_STD_SCART_PAL:
1349209ff23fSmrg	    s = "scart-pal";
1350209ff23fSmrg	    break;
1351209ff23fSmrg	case TV_STD_NTSC:
1352209ff23fSmrg	default:
1353209ff23fSmrg	    s = "ntsc";
1354209ff23fSmrg	    break;
1355209ff23fSmrg	}
1356209ff23fSmrg
1357209ff23fSmrg	err = RRChangeOutputProperty(output->randr_output, tv_std_atom,
1358209ff23fSmrg				     XA_STRING, 8, PropModeReplace, strlen(s), (pointer)s,
1359209ff23fSmrg				     FALSE, FALSE);
1360209ff23fSmrg	if (err != 0) {
1361209ff23fSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1362209ff23fSmrg		       "RRChangeOutputProperty error, %d\n", err);
1363209ff23fSmrg	}
1364209ff23fSmrg    }
1365209ff23fSmrg}
1366209ff23fSmrg
1367209ff23fSmrgstatic Bool
1368209ff23fSmrgradeon_set_mode_for_property(xf86OutputPtr output)
1369209ff23fSmrg{
1370209ff23fSmrg    ScrnInfoPtr pScrn = output->scrn;
1371209ff23fSmrg
1372209ff23fSmrg    if (output->crtc) {
1373209ff23fSmrg	xf86CrtcPtr crtc = output->crtc;
1374209ff23fSmrg
1375209ff23fSmrg	if (crtc->enabled) {
1376209ff23fSmrg	    if (!xf86CrtcSetMode(crtc, &crtc->desiredMode, crtc->desiredRotation,
1377209ff23fSmrg				 crtc->desiredX, crtc->desiredY)) {
1378209ff23fSmrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1379209ff23fSmrg			   "Failed to set mode after propery change!\n");
1380209ff23fSmrg		return FALSE;
1381209ff23fSmrg	    }
1382209ff23fSmrg	}
1383209ff23fSmrg    }
1384209ff23fSmrg    return TRUE;
1385209ff23fSmrg}
1386209ff23fSmrg
1387209ff23fSmrgstatic Bool
1388209ff23fSmrgradeon_set_property(xf86OutputPtr output, Atom property,
1389209ff23fSmrg		       RRPropertyValuePtr value)
1390209ff23fSmrg{
1391209ff23fSmrg    RADEONInfoPtr info = RADEONPTR(output->scrn);
1392209ff23fSmrg    RADEONOutputPrivatePtr radeon_output = output->driver_private;
1393209ff23fSmrg    INT32 val;
1394209ff23fSmrg
1395209ff23fSmrg
1396209ff23fSmrg    if (property == backlight_atom) {
1397209ff23fSmrg	if (value->type != XA_INTEGER ||
1398209ff23fSmrg	    value->format != 32 ||
1399209ff23fSmrg	    value->size != 1) {
1400209ff23fSmrg	    return FALSE;
1401209ff23fSmrg	}
1402209ff23fSmrg
1403209ff23fSmrg	val = *(INT32 *)value->data;
1404209ff23fSmrg	if (val < 0 || val > RADEON_MAX_BACKLIGHT_LEVEL)
1405209ff23fSmrg	    return FALSE;
1406209ff23fSmrg
1407209ff23fSmrg#if defined(__powerpc__)
1408209ff23fSmrg	val = RADEON_MAX_BACKLIGHT_LEVEL - val;
1409209ff23fSmrg#endif
1410209ff23fSmrg
1411209ff23fSmrg	radeon_set_backlight_level(output, val);
1412209ff23fSmrg
1413209ff23fSmrg    } else if (property == load_detection_atom) {
1414209ff23fSmrg	if (value->type != XA_INTEGER ||
1415209ff23fSmrg	    value->format != 32 ||
1416209ff23fSmrg	    value->size != 1) {
1417209ff23fSmrg	    return FALSE;
1418209ff23fSmrg	}
1419209ff23fSmrg
1420209ff23fSmrg	val = *(INT32 *)value->data;
1421209ff23fSmrg	if (val < 0 || val > 1)
1422209ff23fSmrg	    return FALSE;
1423209ff23fSmrg
1424209ff23fSmrg	radeon_output->load_detection = val;
1425209ff23fSmrg
1426209ff23fSmrg    } else if (property == coherent_mode_atom) {
1427209ff23fSmrg	Bool coherent_mode = radeon_output->coherent_mode;
1428209ff23fSmrg
1429209ff23fSmrg	if (value->type != XA_INTEGER ||
1430209ff23fSmrg	    value->format != 32 ||
1431209ff23fSmrg	    value->size != 1) {
1432209ff23fSmrg	    return FALSE;
1433209ff23fSmrg	}
1434209ff23fSmrg
1435209ff23fSmrg	val = *(INT32 *)value->data;
1436209ff23fSmrg	if (val < 0 || val > 1)
1437209ff23fSmrg	    return FALSE;
1438209ff23fSmrg
1439209ff23fSmrg	radeon_output->coherent_mode = val;
1440209ff23fSmrg	if (!radeon_set_mode_for_property(output)) {
1441209ff23fSmrg	    radeon_output->coherent_mode = coherent_mode;
1442209ff23fSmrg	    (void)radeon_set_mode_for_property(output);
1443209ff23fSmrg	    return FALSE;
1444209ff23fSmrg	}
1445209ff23fSmrg
1446209ff23fSmrg    } else if (property == rmx_atom) {
1447209ff23fSmrg	const char *s;
1448209ff23fSmrg	RADEONRMXType rmx = radeon_output->rmx_type;
1449209ff23fSmrg
1450209ff23fSmrg	if (value->type != XA_STRING || value->format != 8)
1451209ff23fSmrg	    return FALSE;
1452209ff23fSmrg	s = (char*)value->data;
1453209ff23fSmrg	if (value->size == strlen("full") && !strncmp("full", s, strlen("full"))) {
1454209ff23fSmrg	    radeon_output->rmx_type = RMX_FULL;
1455209ff23fSmrg	} else if (value->size == strlen("center") && !strncmp("center", s, strlen("center"))) {
1456209ff23fSmrg	    radeon_output->rmx_type = RMX_CENTER;
1457b7e1c893Smrg	} else if (value->size == strlen("aspect") && !strncmp("aspect", s, strlen("aspect"))) {
1458b7e1c893Smrg	    if (IS_AVIVO_VARIANT)
1459b7e1c893Smrg		radeon_output->rmx_type = RMX_ASPECT;
1460b7e1c893Smrg	    else
1461b7e1c893Smrg		return FALSE;
1462209ff23fSmrg	} else if (value->size == strlen("off") && !strncmp("off", s, strlen("off"))) {
1463209ff23fSmrg	    radeon_output->rmx_type = RMX_OFF;
1464209ff23fSmrg	} else
1465209ff23fSmrg	    return FALSE;
1466209ff23fSmrg
1467209ff23fSmrg	if (!radeon_set_mode_for_property(output)) {
1468209ff23fSmrg	    radeon_output->rmx_type = rmx;
1469209ff23fSmrg	    (void)radeon_set_mode_for_property(output);
1470209ff23fSmrg	    return FALSE;
1471209ff23fSmrg	}
1472209ff23fSmrg    } else if (property == tmds_pll_atom) {
1473b7e1c893Smrg	radeon_tmds_ptr tmds = NULL;
1474209ff23fSmrg	const char *s;
1475b7e1c893Smrg
1476b7e1c893Smrg	if (info->encoders[ATOM_DEVICE_DFP1_INDEX] && info->encoders[ATOM_DEVICE_DFP1_INDEX]->dev_priv)
1477b7e1c893Smrg	    tmds = (radeon_tmds_ptr)info->encoders[ATOM_DEVICE_DFP1_INDEX]->dev_priv;
1478b7e1c893Smrg	else
1479b7e1c893Smrg	    return FALSE;
1480b7e1c893Smrg
1481209ff23fSmrg	if (value->type != XA_STRING || value->format != 8)
1482209ff23fSmrg	    return FALSE;
1483209ff23fSmrg	s = (char*)value->data;
1484209ff23fSmrg	if (value->size == strlen("bios") && !strncmp("bios", s, strlen("bios"))) {
1485b7e1c893Smrg	    if (!RADEONGetTMDSInfoFromBIOS(output->scrn, tmds))
1486b7e1c893Smrg		RADEONGetTMDSInfoFromTable(output->scrn, tmds);
1487b7e1c893Smrg	} else if (value->size == strlen("driver") && !strncmp("driver", s, strlen("driver")))
1488b7e1c893Smrg	    RADEONGetTMDSInfoFromTable(output->scrn, tmds);
1489b7e1c893Smrg	else
1490209ff23fSmrg	    return FALSE;
1491209ff23fSmrg
1492209ff23fSmrg	return radeon_set_mode_for_property(output);
1493209ff23fSmrg    } else if (property == monitor_type_atom) {
1494209ff23fSmrg	const char *s;
1495209ff23fSmrg	if (value->type != XA_STRING || value->format != 8)
1496209ff23fSmrg	    return FALSE;
1497209ff23fSmrg	s = (char*)value->data;
1498209ff23fSmrg	if (value->size == strlen("auto") && !strncmp("auto", s, strlen("auto"))) {
1499209ff23fSmrg	    radeon_output->DVIType = DVI_AUTO;
1500209ff23fSmrg	    return TRUE;
1501209ff23fSmrg	} else if (value->size == strlen("analog") && !strncmp("analog", s, strlen("analog"))) {
1502209ff23fSmrg	    radeon_output->DVIType = DVI_ANALOG;
1503209ff23fSmrg	    return TRUE;
1504209ff23fSmrg	} else if (value->size == strlen("digital") && !strncmp("digital", s, strlen("digital"))) {
1505209ff23fSmrg	    radeon_output->DVIType = DVI_DIGITAL;
1506209ff23fSmrg	    return TRUE;
1507209ff23fSmrg	} else
1508209ff23fSmrg	    return FALSE;
1509209ff23fSmrg    } else if (property == tv_hsize_atom) {
1510b7e1c893Smrg	radeon_tvout_ptr tvout = &radeon_output->tvout;
1511209ff23fSmrg	if (value->type != XA_INTEGER ||
1512209ff23fSmrg	    value->format != 32 ||
1513209ff23fSmrg	    value->size != 1) {
1514209ff23fSmrg	    return FALSE;
1515209ff23fSmrg	}
1516209ff23fSmrg
1517209ff23fSmrg	val = *(INT32 *)value->data;
1518209ff23fSmrg	if (val < -MAX_H_SIZE || val > MAX_H_SIZE)
1519209ff23fSmrg	    return FALSE;
1520209ff23fSmrg
1521b7e1c893Smrg	tvout->hSize = val;
1522b7e1c893Smrg	if (tvout->tv_on && !IS_AVIVO_VARIANT)
1523209ff23fSmrg	    RADEONUpdateHVPosition(output, &output->crtc->mode);
1524209ff23fSmrg
1525209ff23fSmrg    } else if (property == tv_hpos_atom) {
1526b7e1c893Smrg	radeon_tvout_ptr tvout = &radeon_output->tvout;
1527209ff23fSmrg	if (value->type != XA_INTEGER ||
1528209ff23fSmrg	    value->format != 32 ||
1529209ff23fSmrg	    value->size != 1) {
1530209ff23fSmrg	    return FALSE;
1531209ff23fSmrg	}
1532209ff23fSmrg
1533209ff23fSmrg	val = *(INT32 *)value->data;
1534209ff23fSmrg	if (val < -MAX_H_POSITION || val > MAX_H_POSITION)
1535209ff23fSmrg	    return FALSE;
1536209ff23fSmrg
1537b7e1c893Smrg	tvout->hPos = val;
1538b7e1c893Smrg	if (tvout->tv_on && !IS_AVIVO_VARIANT)
1539209ff23fSmrg	    RADEONUpdateHVPosition(output, &output->crtc->mode);
1540209ff23fSmrg
1541209ff23fSmrg    } else if (property == tv_vpos_atom) {
1542b7e1c893Smrg	radeon_tvout_ptr tvout = &radeon_output->tvout;
1543209ff23fSmrg	if (value->type != XA_INTEGER ||
1544209ff23fSmrg	    value->format != 32 ||
1545209ff23fSmrg	    value->size != 1) {
1546209ff23fSmrg	    return FALSE;
1547209ff23fSmrg	}
1548209ff23fSmrg
1549209ff23fSmrg	val = *(INT32 *)value->data;
1550209ff23fSmrg	if (val < -MAX_H_POSITION || val > MAX_H_POSITION)
1551209ff23fSmrg	    return FALSE;
1552209ff23fSmrg
1553b7e1c893Smrg	tvout->vPos = val;
1554b7e1c893Smrg	if (tvout->tv_on && !IS_AVIVO_VARIANT)
1555209ff23fSmrg	    RADEONUpdateHVPosition(output, &output->crtc->mode);
1556209ff23fSmrg
1557209ff23fSmrg    } else if (property == tv_std_atom) {
1558209ff23fSmrg	const char *s;
1559b7e1c893Smrg	radeon_tvout_ptr tvout = &radeon_output->tvout;
1560b7e1c893Smrg	TVStd std = tvout->tvStd;
1561209ff23fSmrg
1562209ff23fSmrg	if (value->type != XA_STRING || value->format != 8)
1563209ff23fSmrg	    return FALSE;
1564209ff23fSmrg	s = (char*)value->data;
1565209ff23fSmrg	if (value->size == strlen("ntsc") && !strncmp("ntsc", s, strlen("ntsc"))) {
1566b7e1c893Smrg	    tvout->tvStd = TV_STD_NTSC;
1567209ff23fSmrg	} else if (value->size == strlen("pal") && !strncmp("pal", s, strlen("pal"))) {
1568b7e1c893Smrg	    tvout->tvStd = TV_STD_PAL;
1569209ff23fSmrg	} else if (value->size == strlen("pal-m") && !strncmp("pal-m", s, strlen("pal-m"))) {
1570b7e1c893Smrg	    tvout->tvStd = TV_STD_PAL_M;
1571209ff23fSmrg	} else if (value->size == strlen("pal-60") && !strncmp("pal-60", s, strlen("pal-60"))) {
1572b7e1c893Smrg	    tvout->tvStd = TV_STD_PAL_60;
1573209ff23fSmrg	} else if (value->size == strlen("ntsc-j") && !strncmp("ntsc-j", s, strlen("ntsc-j"))) {
1574b7e1c893Smrg	    tvout->tvStd = TV_STD_NTSC_J;
1575209ff23fSmrg	} else if (value->size == strlen("scart-pal") && !strncmp("scart-pal", s, strlen("scart-pal"))) {
1576b7e1c893Smrg	    tvout->tvStd = TV_STD_SCART_PAL;
1577209ff23fSmrg	} else if (value->size == strlen("pal-cn") && !strncmp("pal-cn", s, strlen("pal-cn"))) {
1578b7e1c893Smrg	    tvout->tvStd = TV_STD_PAL_CN;
1579209ff23fSmrg	} else if (value->size == strlen("secam") && !strncmp("secam", s, strlen("secam"))) {
1580b7e1c893Smrg	    tvout->tvStd = TV_STD_SECAM;
1581209ff23fSmrg	} else
1582209ff23fSmrg	    return FALSE;
1583209ff23fSmrg
1584209ff23fSmrg	if (!radeon_set_mode_for_property(output)) {
1585b7e1c893Smrg	    tvout->tvStd = std;
1586209ff23fSmrg	    (void)radeon_set_mode_for_property(output);
1587209ff23fSmrg	    return FALSE;
1588209ff23fSmrg	}
1589209ff23fSmrg    }
1590209ff23fSmrg
1591209ff23fSmrg    return TRUE;
1592209ff23fSmrg}
1593209ff23fSmrg
1594209ff23fSmrgstatic const xf86OutputFuncsRec radeon_output_funcs = {
1595209ff23fSmrg    .create_resources = radeon_create_resources,
1596209ff23fSmrg    .dpms = radeon_dpms,
1597209ff23fSmrg    .save = radeon_save,
1598209ff23fSmrg    .restore = radeon_restore,
1599209ff23fSmrg    .mode_valid = radeon_mode_valid,
1600209ff23fSmrg    .mode_fixup = radeon_mode_fixup,
1601209ff23fSmrg    .prepare = radeon_mode_prepare,
1602209ff23fSmrg    .mode_set = radeon_mode_set,
1603209ff23fSmrg    .commit = radeon_mode_commit,
1604209ff23fSmrg    .detect = radeon_detect,
1605209ff23fSmrg    .get_modes = radeon_get_modes,
1606209ff23fSmrg    .set_property = radeon_set_property,
1607209ff23fSmrg    .destroy = radeon_destroy
1608209ff23fSmrg};
1609209ff23fSmrg
1610b7e1c893SmrgBool
1611b7e1c893SmrgRADEONI2CDoLock(xf86OutputPtr output, int lock_state)
1612209ff23fSmrg{
1613209ff23fSmrg    ScrnInfoPtr pScrn = output->scrn;
1614209ff23fSmrg    RADEONInfoPtr  info       = RADEONPTR(pScrn);
1615209ff23fSmrg    RADEONOutputPrivatePtr radeon_output = output->driver_private;
1616209ff23fSmrg    RADEONI2CBusPtr pRADEONI2CBus = radeon_output->pI2CBus->DriverPrivate.ptr;
1617209ff23fSmrg    unsigned char *RADEONMMIO = info->MMIO;
1618209ff23fSmrg    uint32_t temp;
1619209ff23fSmrg
1620b7e1c893Smrg    if (lock_state) {
1621b7e1c893Smrg	temp = INREG(pRADEONI2CBus->a_clk_reg);
1622b7e1c893Smrg	temp &= ~(pRADEONI2CBus->a_clk_mask);
1623b7e1c893Smrg	OUTREG(pRADEONI2CBus->a_clk_reg, temp);
1624b7e1c893Smrg
1625b7e1c893Smrg	temp = INREG(pRADEONI2CBus->a_data_reg);
1626b7e1c893Smrg	temp &= ~(pRADEONI2CBus->a_data_mask);
1627b7e1c893Smrg	OUTREG(pRADEONI2CBus->a_data_reg, temp);
1628b7e1c893Smrg    }
1629b7e1c893Smrg
1630209ff23fSmrg    temp = INREG(pRADEONI2CBus->mask_clk_reg);
1631b7e1c893Smrg    if (lock_state)
1632b7e1c893Smrg	temp |= (pRADEONI2CBus->mask_clk_mask);
1633209ff23fSmrg    else
1634b7e1c893Smrg	temp &= ~(pRADEONI2CBus->mask_clk_mask);
1635209ff23fSmrg    OUTREG(pRADEONI2CBus->mask_clk_reg, temp);
1636209ff23fSmrg    temp = INREG(pRADEONI2CBus->mask_clk_reg);
1637209ff23fSmrg
1638209ff23fSmrg    temp = INREG(pRADEONI2CBus->mask_data_reg);
1639b7e1c893Smrg    if (lock_state)
1640b7e1c893Smrg	temp |= (pRADEONI2CBus->mask_data_mask);
1641209ff23fSmrg    else
1642b7e1c893Smrg	temp &= ~(pRADEONI2CBus->mask_data_mask);
1643209ff23fSmrg    OUTREG(pRADEONI2CBus->mask_data_reg, temp);
1644209ff23fSmrg    temp = INREG(pRADEONI2CBus->mask_data_reg);
1645209ff23fSmrg
1646209ff23fSmrg    return TRUE;
1647209ff23fSmrg}
1648209ff23fSmrg
1649209ff23fSmrgstatic void RADEONI2CGetBits(I2CBusPtr b, int *Clock, int *data)
1650209ff23fSmrg{
1651209ff23fSmrg    ScrnInfoPtr    pScrn      = xf86Screens[b->scrnIndex];
1652209ff23fSmrg    RADEONInfoPtr  info       = RADEONPTR(pScrn);
1653209ff23fSmrg    unsigned long  val;
1654209ff23fSmrg    unsigned char *RADEONMMIO = info->MMIO;
1655209ff23fSmrg    RADEONI2CBusPtr pRADEONI2CBus = b->DriverPrivate.ptr;
1656209ff23fSmrg
1657209ff23fSmrg    /* Get the result */
1658209ff23fSmrg    val = INREG(pRADEONI2CBus->get_clk_reg);
1659209ff23fSmrg    *Clock = (val & pRADEONI2CBus->get_clk_mask) != 0;
1660209ff23fSmrg    val = INREG(pRADEONI2CBus->get_data_reg);
1661209ff23fSmrg    *data  = (val & pRADEONI2CBus->get_data_mask) != 0;
1662209ff23fSmrg
1663209ff23fSmrg}
1664209ff23fSmrg
1665209ff23fSmrgstatic void RADEONI2CPutBits(I2CBusPtr b, int Clock, int data)
1666209ff23fSmrg{
1667209ff23fSmrg    ScrnInfoPtr    pScrn      = xf86Screens[b->scrnIndex];
1668209ff23fSmrg    RADEONInfoPtr  info       = RADEONPTR(pScrn);
1669209ff23fSmrg    unsigned long  val;
1670209ff23fSmrg    unsigned char *RADEONMMIO = info->MMIO;
1671209ff23fSmrg    RADEONI2CBusPtr pRADEONI2CBus = b->DriverPrivate.ptr;
1672209ff23fSmrg
1673209ff23fSmrg    val = INREG(pRADEONI2CBus->put_clk_reg) & (uint32_t)~(pRADEONI2CBus->put_clk_mask);
1674209ff23fSmrg    val |= (Clock ? 0:pRADEONI2CBus->put_clk_mask);
1675209ff23fSmrg    OUTREG(pRADEONI2CBus->put_clk_reg, val);
1676209ff23fSmrg    /* read back to improve reliability on some cards. */
1677209ff23fSmrg    val = INREG(pRADEONI2CBus->put_clk_reg);
1678209ff23fSmrg
1679209ff23fSmrg    val = INREG(pRADEONI2CBus->put_data_reg) & (uint32_t)~(pRADEONI2CBus->put_data_mask);
1680209ff23fSmrg    val |= (data ? 0:pRADEONI2CBus->put_data_mask);
1681209ff23fSmrg    OUTREG(pRADEONI2CBus->put_data_reg, val);
1682209ff23fSmrg    /* read back to improve reliability on some cards. */
1683209ff23fSmrg    val = INREG(pRADEONI2CBus->put_data_reg);
1684209ff23fSmrg
1685209ff23fSmrg}
1686209ff23fSmrg
1687b7e1c893SmrgBool
1688b7e1c893SmrgRADEONI2CInit(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr, char *name, RADEONI2CBusPtr pRADEONI2CBus)
1689209ff23fSmrg{
1690209ff23fSmrg    I2CBusPtr pI2CBus;
1691209ff23fSmrg
1692209ff23fSmrg    pI2CBus = xf86CreateI2CBusRec();
1693209ff23fSmrg    if (!pI2CBus) return FALSE;
1694209ff23fSmrg
1695209ff23fSmrg    pI2CBus->BusName    = name;
1696209ff23fSmrg    pI2CBus->scrnIndex  = pScrn->scrnIndex;
1697209ff23fSmrg    pI2CBus->I2CPutBits = RADEONI2CPutBits;
1698209ff23fSmrg    pI2CBus->I2CGetBits = RADEONI2CGetBits;
1699b7e1c893Smrg    pI2CBus->AcknTimeout = 5;
1700209ff23fSmrg
1701b7e1c893Smrg    pI2CBus->DriverPrivate.ptr = (pointer)pRADEONI2CBus;
1702209ff23fSmrg
1703b7e1c893Smrg    if (!xf86I2CBusInit(pI2CBus))
1704b7e1c893Smrg	return FALSE;
1705209ff23fSmrg
1706b7e1c893Smrg    *bus_ptr = pI2CBus;
1707209ff23fSmrg    return TRUE;
1708209ff23fSmrg}
1709209ff23fSmrg
1710b7e1c893SmrgRADEONI2CBusRec
1711b7e1c893Smrglegacy_setup_i2c_bus(int ddc_line)
1712209ff23fSmrg{
1713b7e1c893Smrg    RADEONI2CBusRec i2c;
1714209ff23fSmrg
1715b7e1c893Smrg    i2c.hw_line = 0;
1716b7e1c893Smrg    i2c.hw_capable = FALSE;
1717b7e1c893Smrg    i2c.mask_clk_mask = RADEON_GPIO_EN_1;
1718b7e1c893Smrg    i2c.mask_data_mask = RADEON_GPIO_EN_0;
1719b7e1c893Smrg    i2c.a_clk_mask = RADEON_GPIO_A_1;
1720b7e1c893Smrg    i2c.a_data_mask = RADEON_GPIO_A_0;
1721b7e1c893Smrg    i2c.put_clk_mask = RADEON_GPIO_EN_1;
1722b7e1c893Smrg    i2c.put_data_mask = RADEON_GPIO_EN_0;
1723b7e1c893Smrg    i2c.get_clk_mask = RADEON_GPIO_Y_1;
1724b7e1c893Smrg    i2c.get_data_mask = RADEON_GPIO_Y_0;
1725b7e1c893Smrg    if ((ddc_line == RADEON_LCD_GPIO_MASK) ||
1726b7e1c893Smrg	(ddc_line == RADEON_MDGPIO_EN_REG)) {
1727b7e1c893Smrg	i2c.mask_clk_reg = ddc_line;
1728b7e1c893Smrg	i2c.mask_data_reg = ddc_line;
1729b7e1c893Smrg	i2c.a_clk_reg = ddc_line;
1730b7e1c893Smrg	i2c.a_data_reg = ddc_line;
1731b7e1c893Smrg	i2c.put_clk_reg = ddc_line;
1732b7e1c893Smrg	i2c.put_data_reg = ddc_line;
1733b7e1c893Smrg	i2c.get_clk_reg = ddc_line + 4;
1734b7e1c893Smrg	i2c.get_data_reg = ddc_line + 4;
1735b7e1c893Smrg    } else {
1736b7e1c893Smrg	i2c.mask_clk_reg = ddc_line;
1737b7e1c893Smrg	i2c.mask_data_reg = ddc_line;
1738b7e1c893Smrg	i2c.a_clk_reg = ddc_line;
1739b7e1c893Smrg	i2c.a_data_reg = ddc_line;
1740b7e1c893Smrg	i2c.put_clk_reg = ddc_line;
1741b7e1c893Smrg	i2c.put_data_reg = ddc_line;
1742b7e1c893Smrg	i2c.get_clk_reg = ddc_line;
1743b7e1c893Smrg	i2c.get_data_reg = ddc_line;
1744209ff23fSmrg    }
1745b7e1c893Smrg
1746b7e1c893Smrg    if (ddc_line)
1747b7e1c893Smrg	i2c.valid = TRUE;
1748b7e1c893Smrg    else
1749b7e1c893Smrg	i2c.valid = FALSE;
1750b7e1c893Smrg
1751b7e1c893Smrg    return i2c;
1752209ff23fSmrg}
1753209ff23fSmrg
1754b7e1c893SmrgRADEONI2CBusRec
1755b7e1c893Smrgatom_setup_i2c_bus(int ddc_line)
1756209ff23fSmrg{
1757b7e1c893Smrg    RADEONI2CBusRec i2c;
1758209ff23fSmrg
1759b7e1c893Smrg    i2c.hw_line = 0;
1760b7e1c893Smrg    i2c.hw_capable = FALSE;
1761b7e1c893Smrg    if (ddc_line == AVIVO_GPIO_0) {
1762b7e1c893Smrg	i2c.put_clk_mask = (1 << 19);
1763b7e1c893Smrg	i2c.put_data_mask = (1 << 18);
1764b7e1c893Smrg	i2c.get_clk_mask = (1 << 19);
1765b7e1c893Smrg	i2c.get_data_mask = (1 << 18);
1766b7e1c893Smrg	i2c.mask_clk_mask = (1 << 19);
1767b7e1c893Smrg	i2c.mask_data_mask = (1 << 18);
1768b7e1c893Smrg	i2c.a_clk_mask = (1 << 19);
1769b7e1c893Smrg	i2c.a_data_mask = (1 << 18);
1770b7e1c893Smrg    } else {
1771b7e1c893Smrg	i2c.put_clk_mask = (1 << 0);
1772b7e1c893Smrg	i2c.put_data_mask = (1 << 8);
1773b7e1c893Smrg	i2c.get_clk_mask = (1 << 0);
1774b7e1c893Smrg	i2c.get_data_mask = (1 << 8);
1775b7e1c893Smrg	i2c.mask_clk_mask = (1 << 0);
1776b7e1c893Smrg	i2c.mask_data_mask = (1 << 8);
1777b7e1c893Smrg	i2c.a_clk_mask = (1 << 0);
1778b7e1c893Smrg	i2c.a_data_mask = (1 << 8);
1779209ff23fSmrg    }
1780b7e1c893Smrg    i2c.mask_clk_reg = ddc_line;
1781b7e1c893Smrg    i2c.mask_data_reg = ddc_line;
1782b7e1c893Smrg    i2c.a_clk_reg = ddc_line + 0x4;
1783b7e1c893Smrg    i2c.a_data_reg = ddc_line + 0x4;
1784b7e1c893Smrg    i2c.put_clk_reg = ddc_line + 0x8;
1785b7e1c893Smrg    i2c.put_data_reg = ddc_line + 0x8;
1786b7e1c893Smrg    i2c.get_clk_reg = ddc_line + 0xc;
1787b7e1c893Smrg    i2c.get_data_reg = ddc_line + 0xc;
1788b7e1c893Smrg    if (ddc_line)
1789b7e1c893Smrg	i2c.valid = TRUE;
1790b7e1c893Smrg    else
1791b7e1c893Smrg	i2c.valid = FALSE;
1792209ff23fSmrg
1793b7e1c893Smrg    return i2c;
1794209ff23fSmrg}
1795209ff23fSmrg
1796209ff23fSmrgstatic void
1797209ff23fSmrgRADEONGetTVInfo(xf86OutputPtr output)
1798209ff23fSmrg{
1799209ff23fSmrg    ScrnInfoPtr pScrn = output->scrn;
1800209ff23fSmrg    RADEONInfoPtr  info       = RADEONPTR(pScrn);
1801209ff23fSmrg    RADEONOutputPrivatePtr radeon_output = output->driver_private;
1802b7e1c893Smrg    radeon_tvout_ptr tvout = &radeon_output->tvout;
1803209ff23fSmrg    char *optstr;
1804209ff23fSmrg
1805b7e1c893Smrg    tvout->hPos = 0;
1806b7e1c893Smrg    tvout->vPos = 0;
1807b7e1c893Smrg    tvout->hSize = 0;
1808b7e1c893Smrg    tvout->tv_on = FALSE;
1809209ff23fSmrg
1810209ff23fSmrg    if (!RADEONGetTVInfoFromBIOS(output)) {
1811209ff23fSmrg	/* set some reasonable defaults */
1812b7e1c893Smrg	tvout->default_tvStd = TV_STD_NTSC;
1813b7e1c893Smrg	tvout->tvStd = TV_STD_NTSC;
1814b7e1c893Smrg	tvout->TVRefClk = 27.000000000;
1815b7e1c893Smrg	tvout->SupportedTVStds = TV_STD_NTSC | TV_STD_PAL;
1816209ff23fSmrg    }
1817209ff23fSmrg
1818209ff23fSmrg    optstr = (char *)xf86GetOptValString(info->Options, OPTION_TVSTD);
1819209ff23fSmrg    if (optstr) {
1820209ff23fSmrg	if (!strncmp("ntsc", optstr, strlen("ntsc")))
1821b7e1c893Smrg	    tvout->tvStd = TV_STD_NTSC;
1822209ff23fSmrg	else if (!strncmp("pal", optstr, strlen("pal")))
1823b7e1c893Smrg	    tvout->tvStd = TV_STD_PAL;
1824209ff23fSmrg	else if (!strncmp("pal-m", optstr, strlen("pal-m")))
1825b7e1c893Smrg	    tvout->tvStd = TV_STD_PAL_M;
1826209ff23fSmrg	else if (!strncmp("pal-60", optstr, strlen("pal-60")))
1827b7e1c893Smrg	    tvout->tvStd = TV_STD_PAL_60;
1828209ff23fSmrg	else if (!strncmp("ntsc-j", optstr, strlen("ntsc-j")))
1829b7e1c893Smrg	    tvout->tvStd = TV_STD_NTSC_J;
1830209ff23fSmrg	else if (!strncmp("scart-pal", optstr, strlen("scart-pal")))
1831b7e1c893Smrg	    tvout->tvStd = TV_STD_SCART_PAL;
1832209ff23fSmrg	else {
1833209ff23fSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Invalid TV Standard: %s\n", optstr);
1834209ff23fSmrg	}
1835209ff23fSmrg    }
1836209ff23fSmrg
1837209ff23fSmrg}
1838209ff23fSmrg
1839209ff23fSmrgvoid RADEONInitConnector(xf86OutputPtr output)
1840209ff23fSmrg{
1841209ff23fSmrg    ScrnInfoPtr	    pScrn = output->scrn;
1842209ff23fSmrg    RADEONInfoPtr  info       = RADEONPTR(pScrn);
1843209ff23fSmrg    RADEONOutputPrivatePtr radeon_output = output->driver_private;
1844209ff23fSmrg
1845b7e1c893Smrg    if (radeon_output->devices & (ATOM_DEVICE_LCD_SUPPORT))
1846b7e1c893Smrg	radeon_output->rmx_type = RMX_FULL;
1847209ff23fSmrg    else
1848b7e1c893Smrg	radeon_output->rmx_type = RMX_OFF;
1849209ff23fSmrg
1850b7e1c893Smrg    /* dce 3.2 chips have problems with low dot clocks, so use the scaler */
1851b7e1c893Smrg    if (IS_DCE32_VARIANT && (radeon_output->devices & (ATOM_DEVICE_DFP_SUPPORT)))
1852209ff23fSmrg	radeon_output->rmx_type = RMX_FULL;
1853209ff23fSmrg
1854b7e1c893Smrg    if (!IS_AVIVO_VARIANT) {
1855b7e1c893Smrg	if (radeon_output->devices & (ATOM_DEVICE_CRT2_SUPPORT)) {
1856b7e1c893Smrg	    if (xf86ReturnOptValBool(info->Options, OPTION_TVDAC_LOAD_DETECT, FALSE))
1857b7e1c893Smrg		radeon_output->load_detection = 1;
1858b7e1c893Smrg	}
1859209ff23fSmrg    }
1860209ff23fSmrg
1861b7e1c893Smrg    if (radeon_output->devices & (ATOM_DEVICE_TV_SUPPORT))
1862209ff23fSmrg	RADEONGetTVInfo(output);
1863209ff23fSmrg
1864b7e1c893Smrg    if (radeon_output->devices & (ATOM_DEVICE_DFP_SUPPORT))
1865209ff23fSmrg	radeon_output->coherent_mode = TRUE;
1866209ff23fSmrg
1867209ff23fSmrg    if (radeon_output->ddc_i2c.valid)
1868b7e1c893Smrg	RADEONI2CInit(pScrn, &radeon_output->pI2CBus, output->name, &radeon_output->ddc_i2c);
1869209ff23fSmrg
1870209ff23fSmrg}
1871209ff23fSmrg
1872209ff23fSmrg#if defined(__powerpc__)
1873209ff23fSmrgstatic Bool RADEONSetupAppleConnectors(ScrnInfoPtr pScrn)
1874209ff23fSmrg{
1875209ff23fSmrg    RADEONInfoPtr info       = RADEONPTR(pScrn);
1876209ff23fSmrg
1877209ff23fSmrg
1878209ff23fSmrg    switch (info->MacModel) {
1879209ff23fSmrg    case RADEON_MAC_IBOOK:
1880209ff23fSmrg	info->BiosConnector[0].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_DVI_DDC);
1881209ff23fSmrg	info->BiosConnector[0].ConnectorType = CONNECTOR_LVDS;
1882209ff23fSmrg	info->BiosConnector[0].valid = TRUE;
1883b7e1c893Smrg	info->BiosConnector[0].devices = ATOM_DEVICE_LCD1_SUPPORT;
1884b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
1885b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
1886b7e1c893Smrg									    ATOM_DEVICE_LCD1_SUPPORT,
1887b7e1c893Smrg									    0),
1888b7e1c893Smrg				ATOM_DEVICE_LCD1_SUPPORT))
1889b7e1c893Smrg	    return FALSE;
1890209ff23fSmrg
1891209ff23fSmrg	info->BiosConnector[1].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
1892b7e1c893Smrg	info->BiosConnector[1].load_detection = FALSE;
1893209ff23fSmrg	info->BiosConnector[1].ConnectorType = CONNECTOR_VGA;
1894209ff23fSmrg	info->BiosConnector[1].valid = TRUE;
1895b7e1c893Smrg	info->BiosConnector[1].devices = ATOM_DEVICE_CRT2_SUPPORT;
1896b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
1897b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
1898b7e1c893Smrg									    ATOM_DEVICE_CRT2_SUPPORT,
1899b7e1c893Smrg									    2),
1900b7e1c893Smrg				ATOM_DEVICE_CRT2_SUPPORT))
1901b7e1c893Smrg	    return FALSE;
1902209ff23fSmrg
1903209ff23fSmrg	info->BiosConnector[2].ConnectorType = CONNECTOR_STV;
1904b7e1c893Smrg	info->BiosConnector[2].load_detection = FALSE;
1905209ff23fSmrg	info->BiosConnector[2].ddc_i2c.valid = FALSE;
1906209ff23fSmrg	info->BiosConnector[2].valid = TRUE;
1907b7e1c893Smrg	info->BiosConnector[2].devices = ATOM_DEVICE_TV1_SUPPORT;
1908b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
1909b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
1910b7e1c893Smrg									    ATOM_DEVICE_TV1_SUPPORT,
1911b7e1c893Smrg									    2),
1912b7e1c893Smrg				ATOM_DEVICE_TV1_SUPPORT))
1913b7e1c893Smrg	    return FALSE;
1914209ff23fSmrg	return TRUE;
1915209ff23fSmrg    case RADEON_MAC_POWERBOOK_EXTERNAL:
1916209ff23fSmrg	info->BiosConnector[0].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_DVI_DDC);
1917209ff23fSmrg	info->BiosConnector[0].ConnectorType = CONNECTOR_LVDS;
1918209ff23fSmrg	info->BiosConnector[0].valid = TRUE;
1919b7e1c893Smrg	info->BiosConnector[0].devices = ATOM_DEVICE_LCD1_SUPPORT;
1920b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
1921b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
1922b7e1c893Smrg									    ATOM_DEVICE_LCD1_SUPPORT,
1923b7e1c893Smrg									    0),
1924b7e1c893Smrg				ATOM_DEVICE_LCD1_SUPPORT))
1925b7e1c893Smrg	    return FALSE;
1926209ff23fSmrg
1927209ff23fSmrg	info->BiosConnector[1].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
1928209ff23fSmrg	info->BiosConnector[1].ConnectorType = CONNECTOR_DVI_I;
1929209ff23fSmrg	info->BiosConnector[1].valid = TRUE;
1930b7e1c893Smrg	info->BiosConnector[1].devices = ATOM_DEVICE_CRT1_SUPPORT | ATOM_DEVICE_DFP2_SUPPORT;
1931b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
1932b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
1933b7e1c893Smrg									    ATOM_DEVICE_CRT1_SUPPORT,
1934b7e1c893Smrg									    1),
1935b7e1c893Smrg				ATOM_DEVICE_CRT1_SUPPORT))
1936b7e1c893Smrg	    return FALSE;
1937b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
1938b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
1939b7e1c893Smrg									    ATOM_DEVICE_DFP2_SUPPORT,
1940b7e1c893Smrg									    0),
1941b7e1c893Smrg				ATOM_DEVICE_DFP2_SUPPORT))
1942b7e1c893Smrg	    return FALSE;
1943209ff23fSmrg
1944209ff23fSmrg	info->BiosConnector[2].ConnectorType = CONNECTOR_STV;
1945b7e1c893Smrg	info->BiosConnector[2].load_detection = FALSE;
1946209ff23fSmrg	info->BiosConnector[2].ddc_i2c.valid = FALSE;
1947209ff23fSmrg	info->BiosConnector[2].valid = TRUE;
1948b7e1c893Smrg	info->BiosConnector[2].devices = ATOM_DEVICE_TV1_SUPPORT;
1949b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
1950b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
1951b7e1c893Smrg									    ATOM_DEVICE_TV1_SUPPORT,
1952b7e1c893Smrg									    2),
1953b7e1c893Smrg				ATOM_DEVICE_TV1_SUPPORT))
1954b7e1c893Smrg	    return FALSE;
1955209ff23fSmrg	return TRUE;
1956209ff23fSmrg    case RADEON_MAC_POWERBOOK_INTERNAL:
1957209ff23fSmrg	info->BiosConnector[0].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_DVI_DDC);
1958209ff23fSmrg	info->BiosConnector[0].ConnectorType = CONNECTOR_LVDS;
1959209ff23fSmrg	info->BiosConnector[0].valid = TRUE;
1960b7e1c893Smrg	info->BiosConnector[0].devices = ATOM_DEVICE_LCD1_SUPPORT;
1961b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
1962b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
1963b7e1c893Smrg									    ATOM_DEVICE_LCD1_SUPPORT,
1964b7e1c893Smrg									    0),
1965b7e1c893Smrg				ATOM_DEVICE_LCD1_SUPPORT))
1966b7e1c893Smrg	    return FALSE;
1967209ff23fSmrg
1968209ff23fSmrg	info->BiosConnector[1].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
1969209ff23fSmrg	info->BiosConnector[1].ConnectorType = CONNECTOR_DVI_I;
1970209ff23fSmrg	info->BiosConnector[1].valid = TRUE;
1971b7e1c893Smrg	info->BiosConnector[1].devices = ATOM_DEVICE_CRT1_SUPPORT | ATOM_DEVICE_DFP1_SUPPORT;
1972b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
1973b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
1974b7e1c893Smrg									    ATOM_DEVICE_CRT1_SUPPORT,
1975b7e1c893Smrg									    1),
1976b7e1c893Smrg				ATOM_DEVICE_CRT1_SUPPORT))
1977b7e1c893Smrg	    return FALSE;
1978b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
1979b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
1980b7e1c893Smrg									    ATOM_DEVICE_DFP1_SUPPORT,
1981b7e1c893Smrg									    0),
1982b7e1c893Smrg				ATOM_DEVICE_DFP1_SUPPORT))
1983b7e1c893Smrg	    return FALSE;
1984209ff23fSmrg
1985209ff23fSmrg	info->BiosConnector[2].ConnectorType = CONNECTOR_STV;
1986b7e1c893Smrg	info->BiosConnector[2].load_detection = FALSE;
1987209ff23fSmrg	info->BiosConnector[2].ddc_i2c.valid = FALSE;
1988209ff23fSmrg	info->BiosConnector[2].valid = TRUE;
1989b7e1c893Smrg	info->BiosConnector[2].devices = ATOM_DEVICE_TV1_SUPPORT;
1990b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
1991b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
1992b7e1c893Smrg									    ATOM_DEVICE_TV1_SUPPORT,
1993b7e1c893Smrg									    2),
1994b7e1c893Smrg				ATOM_DEVICE_TV1_SUPPORT))
1995b7e1c893Smrg	    return FALSE;
1996209ff23fSmrg	return TRUE;
1997209ff23fSmrg    case RADEON_MAC_POWERBOOK_VGA:
1998209ff23fSmrg	info->BiosConnector[0].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_DVI_DDC);
1999b7e1c893Smrg	info->BiosConnector[0].ConnectorType = CONNECTOR_LVDS;
2000209ff23fSmrg	info->BiosConnector[0].valid = TRUE;
2001b7e1c893Smrg	info->BiosConnector[0].devices = ATOM_DEVICE_LCD1_SUPPORT;
2002b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
2003b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
2004b7e1c893Smrg									    ATOM_DEVICE_LCD1_SUPPORT,
2005b7e1c893Smrg									    0),
2006b7e1c893Smrg				ATOM_DEVICE_LCD1_SUPPORT))
2007b7e1c893Smrg	    return FALSE;
2008209ff23fSmrg
2009209ff23fSmrg	info->BiosConnector[1].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
2010b7e1c893Smrg	info->BiosConnector[1].ConnectorType = CONNECTOR_VGA;
2011209ff23fSmrg	info->BiosConnector[1].valid = TRUE;
2012b7e1c893Smrg	info->BiosConnector[1].devices = ATOM_DEVICE_CRT1_SUPPORT;
2013b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
2014b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
2015b7e1c893Smrg									    ATOM_DEVICE_CRT1_SUPPORT,
2016b7e1c893Smrg									    1),
2017b7e1c893Smrg				ATOM_DEVICE_CRT1_SUPPORT))
2018b7e1c893Smrg	    return FALSE;
2019209ff23fSmrg
2020209ff23fSmrg	info->BiosConnector[2].ConnectorType = CONNECTOR_STV;
2021b7e1c893Smrg	info->BiosConnector[2].load_detection = FALSE;
2022209ff23fSmrg	info->BiosConnector[2].ddc_i2c.valid = FALSE;
2023209ff23fSmrg	info->BiosConnector[2].valid = TRUE;
2024b7e1c893Smrg	info->BiosConnector[2].devices = ATOM_DEVICE_TV1_SUPPORT;
2025b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
2026b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
2027b7e1c893Smrg									    ATOM_DEVICE_TV1_SUPPORT,
2028b7e1c893Smrg									    2),
2029b7e1c893Smrg				ATOM_DEVICE_TV1_SUPPORT))
2030b7e1c893Smrg	    return FALSE;
2031209ff23fSmrg	return TRUE;
2032209ff23fSmrg    case RADEON_MAC_MINI_EXTERNAL:
2033209ff23fSmrg	info->BiosConnector[0].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_CRT2_DDC);
2034b7e1c893Smrg	info->BiosConnector[0].load_detection = FALSE;
2035209ff23fSmrg	info->BiosConnector[0].ConnectorType = CONNECTOR_DVI_I;
2036209ff23fSmrg	info->BiosConnector[0].valid = TRUE;
2037b7e1c893Smrg	info->BiosConnector[0].devices = ATOM_DEVICE_CRT2_SUPPORT | ATOM_DEVICE_DFP2_SUPPORT;
2038b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
2039b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
2040b7e1c893Smrg									    ATOM_DEVICE_CRT2_SUPPORT,
2041b7e1c893Smrg									    2),
2042b7e1c893Smrg				ATOM_DEVICE_CRT2_SUPPORT))
2043b7e1c893Smrg	    return FALSE;
2044b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
2045b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
2046b7e1c893Smrg									    ATOM_DEVICE_DFP2_SUPPORT,
2047b7e1c893Smrg									    0),
2048b7e1c893Smrg				ATOM_DEVICE_DFP2_SUPPORT))
2049b7e1c893Smrg	    return FALSE;
2050209ff23fSmrg
2051209ff23fSmrg	info->BiosConnector[1].ConnectorType = CONNECTOR_STV;
2052b7e1c893Smrg	info->BiosConnector[1].load_detection = FALSE;
2053209ff23fSmrg	info->BiosConnector[1].ddc_i2c.valid = FALSE;
2054209ff23fSmrg	info->BiosConnector[1].valid = TRUE;
2055b7e1c893Smrg	info->BiosConnector[1].devices = ATOM_DEVICE_TV1_SUPPORT;
2056b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
2057b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
2058b7e1c893Smrg									    ATOM_DEVICE_TV1_SUPPORT,
2059b7e1c893Smrg									    2),
2060b7e1c893Smrg				ATOM_DEVICE_TV1_SUPPORT))
2061b7e1c893Smrg	    return FALSE;
2062209ff23fSmrg	return TRUE;
2063209ff23fSmrg    case RADEON_MAC_MINI_INTERNAL:
2064209ff23fSmrg	info->BiosConnector[0].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_CRT2_DDC);
2065b7e1c893Smrg	info->BiosConnector[0].load_detection = FALSE;
2066209ff23fSmrg	info->BiosConnector[0].ConnectorType = CONNECTOR_DVI_I;
2067209ff23fSmrg	info->BiosConnector[0].valid = TRUE;
2068b7e1c893Smrg	info->BiosConnector[0].devices = ATOM_DEVICE_CRT2_SUPPORT | ATOM_DEVICE_DFP1_SUPPORT;
2069b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
2070b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
2071b7e1c893Smrg									    ATOM_DEVICE_CRT2_SUPPORT,
2072b7e1c893Smrg									    2),
2073b7e1c893Smrg				ATOM_DEVICE_CRT2_SUPPORT))
2074b7e1c893Smrg	    return FALSE;
2075b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
2076b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
2077b7e1c893Smrg									    ATOM_DEVICE_DFP1_SUPPORT,
2078b7e1c893Smrg									    0),
2079b7e1c893Smrg				ATOM_DEVICE_DFP1_SUPPORT))
2080b7e1c893Smrg	    return FALSE;
2081209ff23fSmrg
2082209ff23fSmrg	info->BiosConnector[1].ConnectorType = CONNECTOR_STV;
2083b7e1c893Smrg	info->BiosConnector[1].load_detection = FALSE;
2084209ff23fSmrg	info->BiosConnector[1].ddc_i2c.valid = FALSE;
2085209ff23fSmrg	info->BiosConnector[1].valid = TRUE;
2086b7e1c893Smrg	info->BiosConnector[1].devices = ATOM_DEVICE_TV1_SUPPORT;
2087b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
2088b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
2089b7e1c893Smrg									    ATOM_DEVICE_TV1_SUPPORT,
2090b7e1c893Smrg									    2),
2091b7e1c893Smrg				ATOM_DEVICE_TV1_SUPPORT))
2092b7e1c893Smrg	    return FALSE;
2093209ff23fSmrg	return TRUE;
2094209ff23fSmrg    case RADEON_MAC_IMAC_G5_ISIGHT:
2095209ff23fSmrg	info->BiosConnector[0].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_MONID);
2096209ff23fSmrg	info->BiosConnector[0].ConnectorType = CONNECTOR_DVI_D;
2097209ff23fSmrg	info->BiosConnector[0].valid = TRUE;
2098b7e1c893Smrg	info->BiosConnector[0].devices = ATOM_DEVICE_DFP1_SUPPORT;
2099b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
2100b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
2101b7e1c893Smrg									    ATOM_DEVICE_DFP1_SUPPORT,
2102b7e1c893Smrg									    0),
2103b7e1c893Smrg				ATOM_DEVICE_DFP1_SUPPORT))
2104b7e1c893Smrg	    return FALSE;
2105209ff23fSmrg
2106209ff23fSmrg	info->BiosConnector[1].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_DVI_DDC);
2107b7e1c893Smrg	info->BiosConnector[1].load_detection = FALSE;
2108b7e1c893Smrg	info->BiosConnector[1].ConnectorType = CONNECTOR_VGA;
2109b7e1c893Smrg	info->BiosConnector[1].valid = TRUE;
2110b7e1c893Smrg	info->BiosConnector[1].devices = ATOM_DEVICE_CRT2_SUPPORT;
2111b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
2112b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
2113b7e1c893Smrg									    ATOM_DEVICE_CRT2_SUPPORT,
2114b7e1c893Smrg									    2),
2115b7e1c893Smrg				ATOM_DEVICE_CRT2_SUPPORT))
2116b7e1c893Smrg	    return FALSE;
2117b7e1c893Smrg
2118b7e1c893Smrg	info->BiosConnector[2].ConnectorType = CONNECTOR_STV;
2119b7e1c893Smrg	info->BiosConnector[2].load_detection = FALSE;
2120b7e1c893Smrg	info->BiosConnector[2].ddc_i2c.valid = FALSE;
2121b7e1c893Smrg	info->BiosConnector[2].valid = TRUE;
2122b7e1c893Smrg	info->BiosConnector[2].devices = ATOM_DEVICE_TV1_SUPPORT;
2123b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
2124b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
2125b7e1c893Smrg									    ATOM_DEVICE_TV1_SUPPORT,
2126b7e1c893Smrg									    2),
2127b7e1c893Smrg				ATOM_DEVICE_TV1_SUPPORT))
2128b7e1c893Smrg	    return FALSE;
2129b7e1c893Smrg	return TRUE;
2130b7e1c893Smrg    case RADEON_MAC_EMAC:
2131b7e1c893Smrg	/* eMac G4 800/1.0 with radeon 7500, no EDID on internal monitor
2132b7e1c893Smrg	 * later eMac's (G4 1.25/1.42) with radeon 9200 and 9600 may have
2133b7e1c893Smrg	 * different ddc setups.  need to verify
2134b7e1c893Smrg	 */
2135b7e1c893Smrg	info->BiosConnector[0].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
2136b7e1c893Smrg	info->BiosConnector[0].ConnectorType = CONNECTOR_VGA;
2137b7e1c893Smrg	info->BiosConnector[0].valid = TRUE;
2138b7e1c893Smrg	info->BiosConnector[0].devices = ATOM_DEVICE_CRT1_SUPPORT;
2139b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
2140b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
2141b7e1c893Smrg									    ATOM_DEVICE_CRT1_SUPPORT,
2142b7e1c893Smrg									    1),
2143b7e1c893Smrg				ATOM_DEVICE_CRT1_SUPPORT))
2144b7e1c893Smrg	    return FALSE;
2145b7e1c893Smrg
2146b7e1c893Smrg	info->BiosConnector[1].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_CRT2_DDC);
2147b7e1c893Smrg	info->BiosConnector[1].load_detection = FALSE;
2148209ff23fSmrg	info->BiosConnector[1].ConnectorType = CONNECTOR_VGA;
2149209ff23fSmrg	info->BiosConnector[1].valid = TRUE;
2150b7e1c893Smrg	info->BiosConnector[1].devices = ATOM_DEVICE_CRT2_SUPPORT;
2151b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
2152b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
2153b7e1c893Smrg									    ATOM_DEVICE_CRT2_SUPPORT,
2154b7e1c893Smrg									    2),
2155b7e1c893Smrg				ATOM_DEVICE_CRT2_SUPPORT))
2156b7e1c893Smrg	    return FALSE;
2157209ff23fSmrg
2158209ff23fSmrg	info->BiosConnector[2].ConnectorType = CONNECTOR_STV;
2159b7e1c893Smrg	info->BiosConnector[2].load_detection = FALSE;
2160209ff23fSmrg	info->BiosConnector[2].ddc_i2c.valid = FALSE;
2161209ff23fSmrg	info->BiosConnector[2].valid = TRUE;
2162b7e1c893Smrg	info->BiosConnector[2].devices = ATOM_DEVICE_TV1_SUPPORT;
2163b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
2164b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
2165b7e1c893Smrg									    ATOM_DEVICE_TV1_SUPPORT,
2166b7e1c893Smrg									    2),
2167b7e1c893Smrg				ATOM_DEVICE_TV1_SUPPORT))
2168b7e1c893Smrg	    return FALSE;
2169209ff23fSmrg	return TRUE;
2170209ff23fSmrg    default:
2171209ff23fSmrg	return FALSE;
2172209ff23fSmrg    }
2173209ff23fSmrg
2174209ff23fSmrg    return FALSE;
2175209ff23fSmrg}
2176209ff23fSmrg#endif
2177209ff23fSmrg
2178209ff23fSmrgstatic void RADEONSetupGenericConnectors(ScrnInfoPtr pScrn)
2179209ff23fSmrg{
2180209ff23fSmrg    RADEONInfoPtr info       = RADEONPTR(pScrn);
2181209ff23fSmrg    RADEONEntPtr pRADEONEnt  = RADEONEntPriv(pScrn);
2182209ff23fSmrg
2183b7e1c893Smrg    if (IS_AVIVO_VARIANT)
2184b7e1c893Smrg	return;
2185b7e1c893Smrg
2186209ff23fSmrg    if (!pRADEONEnt->HasCRTC2) {
2187209ff23fSmrg	info->BiosConnector[0].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
2188209ff23fSmrg	info->BiosConnector[0].ConnectorType = CONNECTOR_VGA;
2189209ff23fSmrg	info->BiosConnector[0].valid = TRUE;
2190b7e1c893Smrg	info->BiosConnector[0].devices = ATOM_DEVICE_CRT1_SUPPORT;
2191b7e1c893Smrg	radeon_add_encoder(pScrn,
2192b7e1c893Smrg			   radeon_get_encoder_id_from_supported_device(pScrn,
2193b7e1c893Smrg								       ATOM_DEVICE_CRT1_SUPPORT,
2194b7e1c893Smrg								       1),
2195b7e1c893Smrg			   ATOM_DEVICE_CRT1_SUPPORT);
2196209ff23fSmrg	return;
2197209ff23fSmrg    }
2198209ff23fSmrg
2199b7e1c893Smrg    if (info->IsMobility) {
2200b7e1c893Smrg	/* Below is the most common setting, but may not be true */
2201b7e1c893Smrg	if (info->IsIGP) {
2202b7e1c893Smrg	    info->BiosConnector[0].ddc_i2c = legacy_setup_i2c_bus(RADEON_LCD_GPIO_MASK);
2203209ff23fSmrg	    info->BiosConnector[0].ConnectorType = CONNECTOR_LVDS;
2204209ff23fSmrg	    info->BiosConnector[0].valid = TRUE;
2205b7e1c893Smrg	    info->BiosConnector[0].devices = ATOM_DEVICE_LCD1_SUPPORT;
2206b7e1c893Smrg	    radeon_add_encoder(pScrn,
2207b7e1c893Smrg			       radeon_get_encoder_id_from_supported_device(pScrn,
2208b7e1c893Smrg									   ATOM_DEVICE_LCD1_SUPPORT,
2209b7e1c893Smrg									   0),
2210b7e1c893Smrg			       ATOM_DEVICE_LCD1_SUPPORT);
2211b7e1c893Smrg
2212b7e1c893Smrg	    /* IGP only has TVDAC */
2213b7e1c893Smrg	    if ((info->ChipFamily == CHIP_FAMILY_RS400) ||
2214b7e1c893Smrg		(info->ChipFamily == CHIP_FAMILY_RS480))
2215b7e1c893Smrg		info->BiosConnector[1].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_CRT2_DDC);
2216b7e1c893Smrg	    else
2217b7e1c893Smrg		info->BiosConnector[1].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
2218b7e1c893Smrg	    info->BiosConnector[1].load_detection = FALSE;
2219209ff23fSmrg	    info->BiosConnector[1].ConnectorType = CONNECTOR_VGA;
2220209ff23fSmrg	    info->BiosConnector[1].valid = TRUE;
2221b7e1c893Smrg	    info->BiosConnector[1].devices = ATOM_DEVICE_CRT1_SUPPORT;
2222b7e1c893Smrg	    radeon_add_encoder(pScrn,
2223b7e1c893Smrg			       radeon_get_encoder_id_from_supported_device(pScrn,
2224b7e1c893Smrg									   ATOM_DEVICE_CRT1_SUPPORT,
2225b7e1c893Smrg									   2),
2226b7e1c893Smrg			       ATOM_DEVICE_CRT1_SUPPORT);
2227209ff23fSmrg	} else {
2228b7e1c893Smrg#if defined(__powerpc__)
2229b7e1c893Smrg	    info->BiosConnector[0].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_DVI_DDC);
2230b7e1c893Smrg#else
2231b7e1c893Smrg	    info->BiosConnector[0].ddc_i2c = legacy_setup_i2c_bus(RADEON_LCD_GPIO_MASK);
2232b7e1c893Smrg#endif
2233b7e1c893Smrg	    info->BiosConnector[0].ConnectorType = CONNECTOR_LVDS;
2234209ff23fSmrg	    info->BiosConnector[0].valid = TRUE;
2235b7e1c893Smrg	    info->BiosConnector[0].devices = ATOM_DEVICE_LCD1_SUPPORT;
2236b7e1c893Smrg	    radeon_add_encoder(pScrn,
2237b7e1c893Smrg			       radeon_get_encoder_id_from_supported_device(pScrn,
2238b7e1c893Smrg									   ATOM_DEVICE_LCD1_SUPPORT,
2239b7e1c893Smrg									   0),
2240b7e1c893Smrg			       ATOM_DEVICE_LCD1_SUPPORT);
2241209ff23fSmrg
2242b7e1c893Smrg	    info->BiosConnector[1].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
2243209ff23fSmrg	    info->BiosConnector[1].ConnectorType = CONNECTOR_VGA;
2244209ff23fSmrg	    info->BiosConnector[1].valid = TRUE;
2245b7e1c893Smrg	    info->BiosConnector[1].devices = ATOM_DEVICE_CRT1_SUPPORT;
2246b7e1c893Smrg	    radeon_add_encoder(pScrn,
2247b7e1c893Smrg			       radeon_get_encoder_id_from_supported_device(pScrn,
2248b7e1c893Smrg									   ATOM_DEVICE_CRT1_SUPPORT,
2249b7e1c893Smrg									   1),
2250b7e1c893Smrg			       ATOM_DEVICE_CRT1_SUPPORT);
2251209ff23fSmrg	}
2252209ff23fSmrg    } else {
2253b7e1c893Smrg	/* Below is the most common setting, but may not be true */
2254b7e1c893Smrg	if (info->IsIGP) {
2255b7e1c893Smrg	    if ((info->ChipFamily == CHIP_FAMILY_RS400) ||
2256b7e1c893Smrg		(info->ChipFamily == CHIP_FAMILY_RS480))
2257b7e1c893Smrg		info->BiosConnector[0].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_CRT2_DDC);
2258b7e1c893Smrg	    else
2259b7e1c893Smrg		info->BiosConnector[0].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
2260b7e1c893Smrg	    info->BiosConnector[0].load_detection = FALSE;
2261b7e1c893Smrg	    info->BiosConnector[0].ConnectorType = CONNECTOR_VGA;
2262b7e1c893Smrg	    info->BiosConnector[0].valid = TRUE;
2263b7e1c893Smrg	    info->BiosConnector[0].devices = ATOM_DEVICE_CRT1_SUPPORT;
2264b7e1c893Smrg	    radeon_add_encoder(pScrn,
2265b7e1c893Smrg			       radeon_get_encoder_id_from_supported_device(pScrn,
2266b7e1c893Smrg									   ATOM_DEVICE_CRT1_SUPPORT,
2267b7e1c893Smrg									   1),
2268b7e1c893Smrg			       ATOM_DEVICE_CRT1_SUPPORT);
2269b7e1c893Smrg
2270b7e1c893Smrg	    /* not sure what a good default DDCType for DVI on
2271b7e1c893Smrg	     * IGP desktop chips is
2272b7e1c893Smrg	     */
2273b7e1c893Smrg	    info->BiosConnector[1].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_MONID); /* DDC_DVI? */
2274b7e1c893Smrg	    info->BiosConnector[1].ConnectorType = CONNECTOR_DVI_D;
2275b7e1c893Smrg	    info->BiosConnector[1].valid = TRUE;
2276b7e1c893Smrg	    info->BiosConnector[1].devices = ATOM_DEVICE_DFP1_SUPPORT;
2277b7e1c893Smrg	    radeon_add_encoder(pScrn,
2278b7e1c893Smrg			       radeon_get_encoder_id_from_supported_device(pScrn,
2279b7e1c893Smrg									   ATOM_DEVICE_DFP1_SUPPORT,
2280b7e1c893Smrg									   0),
2281b7e1c893Smrg			       ATOM_DEVICE_DFP1_SUPPORT);
2282209ff23fSmrg	} else {
2283b7e1c893Smrg	    info->BiosConnector[0].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_DVI_DDC);
2284b7e1c893Smrg	    info->BiosConnector[0].load_detection = FALSE;
2285b7e1c893Smrg	    info->BiosConnector[0].ConnectorType = CONNECTOR_DVI_I;
2286b7e1c893Smrg	    info->BiosConnector[0].valid = TRUE;
2287b7e1c893Smrg	    info->BiosConnector[0].devices = ATOM_DEVICE_CRT2_SUPPORT | ATOM_DEVICE_DFP1_SUPPORT;
2288b7e1c893Smrg	    radeon_add_encoder(pScrn,
2289b7e1c893Smrg			       radeon_get_encoder_id_from_supported_device(pScrn,
2290b7e1c893Smrg									   ATOM_DEVICE_CRT2_SUPPORT,
2291b7e1c893Smrg									   2),
2292b7e1c893Smrg			       ATOM_DEVICE_CRT2_SUPPORT);
2293b7e1c893Smrg	    radeon_add_encoder(pScrn,
2294b7e1c893Smrg			       radeon_get_encoder_id_from_supported_device(pScrn,
2295b7e1c893Smrg									   ATOM_DEVICE_DFP1_SUPPORT,
2296b7e1c893Smrg									   0),
2297b7e1c893Smrg			       ATOM_DEVICE_DFP1_SUPPORT);
2298209ff23fSmrg
2299209ff23fSmrg#if defined(__powerpc__)
2300b7e1c893Smrg	    info->BiosConnector[1].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
2301b7e1c893Smrg	    info->BiosConnector[1].ConnectorType = CONNECTOR_DVI_I;
2302b7e1c893Smrg	    info->BiosConnector[1].valid = TRUE;
2303b7e1c893Smrg	    info->BiosConnector[1].devices = ATOM_DEVICE_CRT1_SUPPORT | ATOM_DEVICE_DFP2_SUPPORT;
2304b7e1c893Smrg	    radeon_add_encoder(pScrn,
2305b7e1c893Smrg			       radeon_get_encoder_id_from_supported_device(pScrn,
2306b7e1c893Smrg									   ATOM_DEVICE_CRT1_SUPPORT,
2307b7e1c893Smrg									   1),
2308b7e1c893Smrg			       ATOM_DEVICE_CRT1_SUPPORT);
2309b7e1c893Smrg	    radeon_add_encoder(pScrn,
2310b7e1c893Smrg			       radeon_get_encoder_id_from_supported_device(pScrn,
2311b7e1c893Smrg									   ATOM_DEVICE_DFP2_SUPPORT,
2312b7e1c893Smrg									   0),
2313b7e1c893Smrg			       ATOM_DEVICE_DFP2_SUPPORT);
2314209ff23fSmrg#else
2315b7e1c893Smrg	    info->BiosConnector[1].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
2316b7e1c893Smrg	    info->BiosConnector[1].ConnectorType = CONNECTOR_VGA;
2317b7e1c893Smrg	    info->BiosConnector[1].valid = TRUE;
2318b7e1c893Smrg	    info->BiosConnector[1].devices = ATOM_DEVICE_CRT1_SUPPORT;
2319b7e1c893Smrg	    radeon_add_encoder(pScrn,
2320b7e1c893Smrg			       radeon_get_encoder_id_from_supported_device(pScrn,
2321b7e1c893Smrg									   ATOM_DEVICE_CRT1_SUPPORT,
2322b7e1c893Smrg									   1),
2323b7e1c893Smrg			       ATOM_DEVICE_CRT1_SUPPORT);
2324209ff23fSmrg#endif
2325209ff23fSmrg	}
2326b7e1c893Smrg    }
2327209ff23fSmrg
2328b7e1c893Smrg    if (info->InternalTVOut) {
2329b7e1c893Smrg	info->BiosConnector[2].ConnectorType = CONNECTOR_STV;
2330b7e1c893Smrg	info->BiosConnector[2].load_detection = FALSE;
2331b7e1c893Smrg	info->BiosConnector[2].ddc_i2c.valid = FALSE;
2332b7e1c893Smrg	info->BiosConnector[2].valid = TRUE;
2333b7e1c893Smrg	info->BiosConnector[2].devices = ATOM_DEVICE_TV1_SUPPORT;
2334b7e1c893Smrg	radeon_add_encoder(pScrn,
2335b7e1c893Smrg			       radeon_get_encoder_id_from_supported_device(pScrn,
2336b7e1c893Smrg									   ATOM_DEVICE_TV1_SUPPORT,
2337b7e1c893Smrg									   2),
2338b7e1c893Smrg			       ATOM_DEVICE_TV1_SUPPORT);
2339b7e1c893Smrg    }
2340209ff23fSmrg
2341b7e1c893Smrg    /* Some cards have the DDC lines swapped and we have no way to
2342b7e1c893Smrg     * detect it yet (Mac cards)
2343b7e1c893Smrg     */
2344b7e1c893Smrg    if (xf86ReturnOptValBool(info->Options, OPTION_REVERSE_DDC, FALSE)) {
2345b7e1c893Smrg	info->BiosConnector[0].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
2346b7e1c893Smrg	info->BiosConnector[1].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_DVI_DDC);
2347209ff23fSmrg    }
2348209ff23fSmrg}
2349209ff23fSmrg
2350209ff23fSmrg#if defined(__powerpc__)
2351209ff23fSmrg
2352209ff23fSmrg/*
2353209ff23fSmrg * Returns RADEONMacModel or 0 based on lines 'detected as' and 'machine'
2354209ff23fSmrg * in /proc/cpuinfo (on Linux) */
2355209ff23fSmrgstatic RADEONMacModel RADEONDetectMacModel(ScrnInfoPtr pScrn)
2356209ff23fSmrg{
2357209ff23fSmrg    RADEONInfoPtr info = RADEONPTR(pScrn);
2358209ff23fSmrg    RADEONMacModel ret = 0;
2359209ff23fSmrg#ifdef __linux__
2360209ff23fSmrg    char cpuline[50];  /* 50 should be sufficient for our purposes */
2361209ff23fSmrg    FILE *f = fopen ("/proc/cpuinfo", "r");
2362209ff23fSmrg
2363209ff23fSmrg    /* Some macs (minis and powerbooks) use internal tmds, others use external tmds
2364209ff23fSmrg     * and not just for dual-link TMDS, it shows up with single-link as well.
2365209ff23fSmrg     * Unforunately, there doesn't seem to be any good way to figure it out.
2366209ff23fSmrg     */
2367209ff23fSmrg
2368b7e1c893Smrg    /*
2369209ff23fSmrg     * PowerBook5,[1-5]: external tmds, single-link
2370209ff23fSmrg     * PowerBook5,[789]: external tmds, dual-link
2371209ff23fSmrg     * PowerBook5,6:     external tmds, single-link or dual-link
2372209ff23fSmrg     * need to add another option to specify the external tmds chip
2373209ff23fSmrg     * or find out what's used and add it.
2374209ff23fSmrg     */
2375209ff23fSmrg
2376209ff23fSmrg
2377209ff23fSmrg    if (f != NULL) {
2378209ff23fSmrg	while (fgets(cpuline, sizeof cpuline, f)) {
2379209ff23fSmrg	    if (!strncmp(cpuline, "machine", strlen ("machine"))) {
2380209ff23fSmrg		if (strstr(cpuline, "PowerBook5,1") ||
2381209ff23fSmrg		    strstr(cpuline, "PowerBook5,2") ||
2382209ff23fSmrg		    strstr(cpuline, "PowerBook5,3") ||
2383209ff23fSmrg		    strstr(cpuline, "PowerBook5,4") ||
2384209ff23fSmrg		    strstr(cpuline, "PowerBook5,5")) {
2385209ff23fSmrg		    ret = RADEON_MAC_POWERBOOK_EXTERNAL; /* single link */
2386209ff23fSmrg		    info->ext_tmds_chip = RADEON_SIL_164; /* works on 5,2 */
2387209ff23fSmrg		    break;
2388209ff23fSmrg		}
2389209ff23fSmrg
2390209ff23fSmrg		if (strstr(cpuline, "PowerBook5,6")) {
2391209ff23fSmrg		    ret = RADEON_MAC_POWERBOOK_EXTERNAL; /* dual or single link */
2392209ff23fSmrg		    break;
2393209ff23fSmrg		}
2394209ff23fSmrg
2395209ff23fSmrg		if (strstr(cpuline, "PowerBook5,7") ||
2396209ff23fSmrg		    strstr(cpuline, "PowerBook5,8") ||
2397209ff23fSmrg		    strstr(cpuline, "PowerBook5,9")) {
2398209ff23fSmrg		    ret = RADEON_MAC_POWERBOOK_EXTERNAL; /* dual link */
2399209ff23fSmrg		    info->ext_tmds_chip = RADEON_SIL_1178; /* guess */
2400209ff23fSmrg		    break;
2401209ff23fSmrg		}
2402209ff23fSmrg
2403209ff23fSmrg		if (strstr(cpuline, "PowerBook3,3")) {
2404209ff23fSmrg		    ret = RADEON_MAC_POWERBOOK_VGA; /* vga rather than dvi */
2405209ff23fSmrg		    break;
2406209ff23fSmrg		}
2407209ff23fSmrg
2408209ff23fSmrg		if (strstr(cpuline, "PowerMac10,1")) {
2409209ff23fSmrg		    ret = RADEON_MAC_MINI_INTERNAL; /* internal tmds */
2410209ff23fSmrg		    break;
2411209ff23fSmrg		}
2412209ff23fSmrg		if (strstr(cpuline, "PowerMac10,2")) {
2413209ff23fSmrg		    ret = RADEON_MAC_MINI_EXTERNAL; /* external tmds */
2414209ff23fSmrg		    break;
2415209ff23fSmrg		}
2416209ff23fSmrg	    } else if (!strncmp(cpuline, "detected as", strlen("detected as"))) {
2417209ff23fSmrg		if (strstr(cpuline, "iBook")) {
2418209ff23fSmrg		    ret = RADEON_MAC_IBOOK;
2419209ff23fSmrg		    break;
2420209ff23fSmrg		} else if (strstr(cpuline, "PowerBook")) {
2421209ff23fSmrg		    ret = RADEON_MAC_POWERBOOK_INTERNAL; /* internal tmds */
2422209ff23fSmrg		    break;
2423209ff23fSmrg		} else if (strstr(cpuline, "iMac G5 (iSight)")) {
2424209ff23fSmrg		    ret = RADEON_MAC_IMAC_G5_ISIGHT;
2425209ff23fSmrg		    break;
2426b7e1c893Smrg		} else if (strstr(cpuline, "eMac")) {
2427b7e1c893Smrg		    ret = RADEON_MAC_EMAC;
2428b7e1c893Smrg		    break;
2429209ff23fSmrg		}
2430209ff23fSmrg
2431209ff23fSmrg		/* No known PowerMac model detected */
2432209ff23fSmrg		break;
2433209ff23fSmrg	    }
2434209ff23fSmrg	}
2435209ff23fSmrg
2436209ff23fSmrg	fclose (f);
2437209ff23fSmrg    } else
2438209ff23fSmrg	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
2439209ff23fSmrg		   "Cannot detect PowerMac model because /proc/cpuinfo not "
2440209ff23fSmrg		   "readable.\n");
2441209ff23fSmrg
2442209ff23fSmrg#endif /* __linux */
2443209ff23fSmrg
2444209ff23fSmrg    if (ret) {
2445209ff23fSmrg	xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "Detected %s.\n",
2446209ff23fSmrg		   ret == RADEON_MAC_POWERBOOK_EXTERNAL ? "PowerBook with external DVI" :
2447209ff23fSmrg		   ret == RADEON_MAC_POWERBOOK_INTERNAL ? "PowerBook with integrated DVI" :
2448209ff23fSmrg		   ret == RADEON_MAC_POWERBOOK_VGA ? "PowerBook with VGA" :
2449209ff23fSmrg		   ret == RADEON_MAC_IBOOK ? "iBook" :
2450209ff23fSmrg		   ret == RADEON_MAC_MINI_EXTERNAL ? "Mac Mini with external DVI" :
2451209ff23fSmrg		   ret == RADEON_MAC_MINI_INTERNAL ? "Mac Mini with integrated DVI" :
2452209ff23fSmrg		   "iMac G5 iSight");
2453209ff23fSmrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2454209ff23fSmrg		   "If this is not correct, try Option \"MacModel\" and "
2455209ff23fSmrg		   "consider reporting to the\n");
2456209ff23fSmrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2457209ff23fSmrg		   "xorg-driver-ati@lists.x.org mailing list"
2458209ff23fSmrg#ifdef __linux__
2459209ff23fSmrg		   " with the contents of /proc/cpuinfo"
2460209ff23fSmrg#endif
2461209ff23fSmrg		   ".\n");
2462209ff23fSmrg    }
2463209ff23fSmrg
2464209ff23fSmrg    return ret;
2465209ff23fSmrg}
2466209ff23fSmrg
2467209ff23fSmrg#endif /* __powerpc__ */
2468209ff23fSmrg
2469209ff23fSmrgstatic int
2470209ff23fSmrgradeon_output_clones (ScrnInfoPtr pScrn, xf86OutputPtr output)
2471209ff23fSmrg{
2472b7e1c893Smrg    RADEONInfoPtr info = RADEONPTR(pScrn);
2473209ff23fSmrg    RADEONOutputPrivatePtr radeon_output = output->driver_private;
2474209ff23fSmrg    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR (pScrn);
2475209ff23fSmrg    int			o;
2476209ff23fSmrg    int			index_mask = 0;
2477209ff23fSmrg
2478b7e1c893Smrg    /* DIG routing gets problematic */
2479b7e1c893Smrg    if (IS_DCE32_VARIANT)
2480209ff23fSmrg	return index_mask;
2481209ff23fSmrg
2482209ff23fSmrg    /* LVDS is too wacky */
2483b7e1c893Smrg    if (radeon_output->devices & (ATOM_DEVICE_LCD_SUPPORT))
2484b7e1c893Smrg	return index_mask;
2485b7e1c893Smrg
2486b7e1c893Smrg    if (radeon_output->devices & (ATOM_DEVICE_TV_SUPPORT))
2487209ff23fSmrg	return index_mask;
2488209ff23fSmrg
2489209ff23fSmrg    for (o = 0; o < config->num_output; o++) {
2490209ff23fSmrg	xf86OutputPtr clone = config->output[o];
2491209ff23fSmrg	RADEONOutputPrivatePtr radeon_clone = clone->driver_private;
2492b7e1c893Smrg
2493209ff23fSmrg	if (output == clone) /* don't clone yourself */
2494209ff23fSmrg	    continue;
2495b7e1c893Smrg	else if (radeon_clone->devices & (ATOM_DEVICE_LCD_SUPPORT)) /* LVDS */
2496209ff23fSmrg	    continue;
2497b7e1c893Smrg	else if (radeon_clone->devices & (ATOM_DEVICE_TV_SUPPORT)) /* TV */
2498209ff23fSmrg	    continue;
2499209ff23fSmrg	else
2500209ff23fSmrg	    index_mask |= (1 << o);
2501209ff23fSmrg    }
2502209ff23fSmrg
2503209ff23fSmrg    return index_mask;
2504209ff23fSmrg}
2505209ff23fSmrg
2506b7e1c893Smrgstatic xf86OutputPtr
2507b7e1c893SmrgRADEONOutputCreate(ScrnInfoPtr pScrn, const char *name, int i)
2508b7e1c893Smrg{
2509b7e1c893Smrg    char buf[32];
2510b7e1c893Smrg    sprintf(buf, name, i);
2511b7e1c893Smrg    return xf86OutputCreate(pScrn, &radeon_output_funcs, buf);
2512b7e1c893Smrg}
2513b7e1c893Smrg
2514209ff23fSmrg/*
2515209ff23fSmrg * initialise the static data sos we don't have to re-do at randr change */
2516209ff23fSmrgBool RADEONSetupConnectors(ScrnInfoPtr pScrn)
2517209ff23fSmrg{
2518209ff23fSmrg    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
2519209ff23fSmrg    RADEONInfoPtr info       = RADEONPTR(pScrn);
2520209ff23fSmrg    xf86OutputPtr output;
2521209ff23fSmrg    char *optstr;
2522b7e1c893Smrg    int i;
2523209ff23fSmrg    int num_vga = 0;
2524209ff23fSmrg    int num_dvi = 0;
2525209ff23fSmrg    int num_hdmi = 0;
2526b7e1c893Smrg    int num_dp = 0;
2527209ff23fSmrg
2528209ff23fSmrg    /* We first get the information about all connectors from BIOS.
2529209ff23fSmrg     * This is how the card is phyiscally wired up.
2530209ff23fSmrg     * The information should be correct even on a OEM card.
2531209ff23fSmrg     */
2532209ff23fSmrg    for (i = 0; i < RADEON_MAX_BIOS_CONNECTOR; i++) {
2533b7e1c893Smrg	info->encoders[i] = NULL;
2534209ff23fSmrg	info->BiosConnector[i].valid = FALSE;
2535b7e1c893Smrg	info->BiosConnector[i].load_detection = TRUE;
2536b7e1c893Smrg	info->BiosConnector[i].shared_ddc = FALSE;
2537209ff23fSmrg	info->BiosConnector[i].ddc_i2c.valid = FALSE;
2538209ff23fSmrg	info->BiosConnector[i].ConnectorType = CONNECTOR_NONE;
2539b7e1c893Smrg	info->BiosConnector[i].devices = 0;
2540209ff23fSmrg    }
2541209ff23fSmrg
2542209ff23fSmrg#if defined(__powerpc__)
2543209ff23fSmrg    info->MacModel = 0;
2544209ff23fSmrg    optstr = (char *)xf86GetOptValString(info->Options, OPTION_MAC_MODEL);
2545209ff23fSmrg    if (optstr) {
2546209ff23fSmrg	if (!strncmp("ibook", optstr, strlen("ibook")))
2547209ff23fSmrg	    info->MacModel = RADEON_MAC_IBOOK;
2548209ff23fSmrg	else if (!strncmp("powerbook-duallink", optstr, strlen("powerbook-duallink"))) /* alias */
2549209ff23fSmrg	    info->MacModel = RADEON_MAC_POWERBOOK_EXTERNAL;
2550209ff23fSmrg	else if (!strncmp("powerbook-external", optstr, strlen("powerbook-external")))
2551209ff23fSmrg	    info->MacModel = RADEON_MAC_POWERBOOK_EXTERNAL;
2552209ff23fSmrg	else if (!strncmp("powerbook-internal", optstr, strlen("powerbook-internal")))
2553209ff23fSmrg	    info->MacModel = RADEON_MAC_POWERBOOK_INTERNAL;
2554209ff23fSmrg	else if (!strncmp("powerbook-vga", optstr, strlen("powerbook-vga")))
2555209ff23fSmrg	    info->MacModel = RADEON_MAC_POWERBOOK_VGA;
2556209ff23fSmrg	else if (!strncmp("powerbook", optstr, strlen("powerbook"))) /* alias */
2557209ff23fSmrg	    info->MacModel = RADEON_MAC_POWERBOOK_INTERNAL;
2558209ff23fSmrg	else if (!strncmp("mini-internal", optstr, strlen("mini-internal")))
2559209ff23fSmrg	    info->MacModel = RADEON_MAC_MINI_INTERNAL;
2560209ff23fSmrg	else if (!strncmp("mini-external", optstr, strlen("mini-external")))
2561209ff23fSmrg	    info->MacModel = RADEON_MAC_MINI_EXTERNAL;
2562209ff23fSmrg	else if (!strncmp("mini", optstr, strlen("mini"))) /* alias */
2563209ff23fSmrg	    info->MacModel = RADEON_MAC_MINI_EXTERNAL;
2564209ff23fSmrg	else if (!strncmp("imac-g5-isight", optstr, strlen("imac-g5-isight")))
2565209ff23fSmrg	    info->MacModel = RADEON_MAC_IMAC_G5_ISIGHT;
2566b7e1c893Smrg	else if (!strncmp("emac", optstr, strlen("emac")))
2567b7e1c893Smrg	    info->MacModel = RADEON_MAC_EMAC;
2568209ff23fSmrg	else {
2569209ff23fSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Invalid Mac Model: %s\n", optstr);
2570209ff23fSmrg	}
2571209ff23fSmrg    }
2572209ff23fSmrg
2573209ff23fSmrg    if (!info->MacModel) {
2574209ff23fSmrg	info->MacModel = RADEONDetectMacModel(pScrn);
2575209ff23fSmrg    }
2576209ff23fSmrg
2577209ff23fSmrg    if (info->MacModel){
2578209ff23fSmrg	if (!RADEONSetupAppleConnectors(pScrn))
2579209ff23fSmrg	    RADEONSetupGenericConnectors(pScrn);
2580209ff23fSmrg    } else
2581209ff23fSmrg#endif
2582209ff23fSmrg    if (xf86ReturnOptValBool(info->Options, OPTION_DEFAULT_CONNECTOR_TABLE, FALSE)) {
2583209ff23fSmrg	RADEONSetupGenericConnectors(pScrn);
2584209ff23fSmrg    } else {
2585209ff23fSmrg	if (!RADEONGetConnectorInfoFromBIOS(pScrn))
2586209ff23fSmrg	    RADEONSetupGenericConnectors(pScrn);
2587209ff23fSmrg    }
2588209ff23fSmrg
2589209ff23fSmrg    /* parse connector table option */
2590209ff23fSmrg    optstr = (char *)xf86GetOptValString(info->Options, OPTION_CONNECTORTABLE);
2591209ff23fSmrg
2592209ff23fSmrg    if (optstr) {
2593209ff23fSmrg	unsigned int ddc_line[2];
2594b7e1c893Smrg	int DACType[2], TMDSType[2];
2595209ff23fSmrg
2596209ff23fSmrg	for (i = 2; i < RADEON_MAX_BIOS_CONNECTOR; i++) {
2597209ff23fSmrg	    info->BiosConnector[i].valid = FALSE;
2598209ff23fSmrg	}
2599b7e1c893Smrg
2600209ff23fSmrg	if (sscanf(optstr, "%u,%u,%u,%u,%u,%u,%u,%u",
2601209ff23fSmrg		   &ddc_line[0],
2602b7e1c893Smrg		   &DACType[0],
2603b7e1c893Smrg		   &TMDSType[0],
2604209ff23fSmrg		   &info->BiosConnector[0].ConnectorType,
2605209ff23fSmrg		   &ddc_line[1],
2606b7e1c893Smrg		   &DACType[1],
2607b7e1c893Smrg		   &TMDSType[1],
2608209ff23fSmrg		   &info->BiosConnector[1].ConnectorType) != 8) {
2609209ff23fSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Invalid ConnectorTable option: %s\n", optstr);
2610209ff23fSmrg	    return FALSE;
2611209ff23fSmrg	}
2612209ff23fSmrg
2613b7e1c893Smrg	for (i = 0; i < 2; i++) {
2614b7e1c893Smrg	    info->BiosConnector[i].valid = TRUE;
2615b7e1c893Smrg	    info->BiosConnector[i].ddc_i2c = legacy_setup_i2c_bus(ddc_line[i]);
2616b7e1c893Smrg	    switch (DACType[i]) {
2617b7e1c893Smrg	    case 1:
2618b7e1c893Smrg		info->BiosConnector[i].devices |= ATOM_DEVICE_CRT1_SUPPORT;
2619b7e1c893Smrg		if (!radeon_add_encoder(pScrn,
2620b7e1c893Smrg					radeon_get_encoder_id_from_supported_device(pScrn,
2621b7e1c893Smrg										    ATOM_DEVICE_CRT1_SUPPORT,
2622b7e1c893Smrg										    1),
2623b7e1c893Smrg					ATOM_DEVICE_CRT1_SUPPORT))
2624b7e1c893Smrg		    return FALSE;
2625b7e1c893Smrg		info->BiosConnector[i].load_detection = TRUE;
2626b7e1c893Smrg		break;
2627b7e1c893Smrg	    case 2:
2628b7e1c893Smrg		info->BiosConnector[i].devices |= ATOM_DEVICE_CRT2_SUPPORT;
2629b7e1c893Smrg		if (!radeon_add_encoder(pScrn,
2630b7e1c893Smrg					radeon_get_encoder_id_from_supported_device(pScrn,
2631b7e1c893Smrg										    ATOM_DEVICE_CRT1_SUPPORT,
2632b7e1c893Smrg										    2),
2633b7e1c893Smrg					ATOM_DEVICE_CRT1_SUPPORT))
2634b7e1c893Smrg		    return FALSE;
2635b7e1c893Smrg		info->BiosConnector[i].load_detection = FALSE;
2636b7e1c893Smrg		break;
2637b7e1c893Smrg	    }
2638b7e1c893Smrg	    switch (TMDSType[i]) {
2639b7e1c893Smrg	    case 1:
2640b7e1c893Smrg		info->BiosConnector[i].devices |= ATOM_DEVICE_DFP1_SUPPORT;
2641b7e1c893Smrg		if (!radeon_add_encoder(pScrn,
2642b7e1c893Smrg					radeon_get_encoder_id_from_supported_device(pScrn,
2643b7e1c893Smrg										    ATOM_DEVICE_DFP1_SUPPORT,
2644b7e1c893Smrg										    0),
2645b7e1c893Smrg					ATOM_DEVICE_DFP1_SUPPORT))
2646b7e1c893Smrg		    return FALSE;
2647b7e1c893Smrg		break;
2648b7e1c893Smrg	    case 2:
2649b7e1c893Smrg		info->BiosConnector[i].devices |= ATOM_DEVICE_DFP2_SUPPORT;
2650b7e1c893Smrg		if (!radeon_add_encoder(pScrn,
2651b7e1c893Smrg					radeon_get_encoder_id_from_supported_device(pScrn,
2652b7e1c893Smrg										    ATOM_DEVICE_DFP2_SUPPORT,
2653b7e1c893Smrg										    0),
2654b7e1c893Smrg					ATOM_DEVICE_DFP2_SUPPORT))
2655b7e1c893Smrg		    return FALSE;
2656b7e1c893Smrg		break;
2657b7e1c893Smrg	    }
2658b7e1c893Smrg	}
2659209ff23fSmrg    }
2660209ff23fSmrg
2661209ff23fSmrg    for (i = 0; i < RADEON_MAX_BIOS_CONNECTOR; i++) {
2662209ff23fSmrg	if (info->BiosConnector[i].valid) {
2663b7e1c893Smrg	    RADEONConnectorType conntype = info->BiosConnector[i].ConnectorType;
2664b7e1c893Smrg	    if ((conntype == CONNECTOR_DVI_D) ||
2665b7e1c893Smrg		(conntype == CONNECTOR_DVI_I) ||
2666b7e1c893Smrg		(conntype == CONNECTOR_DVI_A)) {
2667209ff23fSmrg		num_dvi++;
2668b7e1c893Smrg	    } else if (conntype == CONNECTOR_VGA) {
2669209ff23fSmrg		num_vga++;
2670b7e1c893Smrg	    } else if ((conntype == CONNECTOR_HDMI_TYPE_A) ||
2671b7e1c893Smrg		       (conntype == CONNECTOR_HDMI_TYPE_B)) {
2672209ff23fSmrg		num_hdmi++;
2673b7e1c893Smrg	    } else if (conntype == CONNECTOR_DISPLAY_PORT) {
2674b7e1c893Smrg		num_dp++;
2675209ff23fSmrg	    }
2676209ff23fSmrg	}
2677209ff23fSmrg    }
2678209ff23fSmrg
2679209ff23fSmrg    for (i = 0 ; i < RADEON_MAX_BIOS_CONNECTOR; i++) {
2680209ff23fSmrg	if (info->BiosConnector[i].valid) {
2681209ff23fSmrg	    RADEONOutputPrivatePtr radeon_output;
2682b7e1c893Smrg	    RADEONConnectorType conntype = info->BiosConnector[i].ConnectorType;
2683209ff23fSmrg
2684b7e1c893Smrg	    if (conntype == CONNECTOR_NONE)
2685209ff23fSmrg		continue;
2686209ff23fSmrg
2687209ff23fSmrg	    radeon_output = xnfcalloc(sizeof(RADEONOutputPrivateRec), 1);
2688209ff23fSmrg	    if (!radeon_output) {
2689209ff23fSmrg		return FALSE;
2690209ff23fSmrg	    }
2691209ff23fSmrg	    radeon_output->MonType = MT_UNKNOWN;
2692b7e1c893Smrg	    radeon_output->ConnectorType = conntype;
2693209ff23fSmrg	    radeon_output->devices = info->BiosConnector[i].devices;
2694209ff23fSmrg	    radeon_output->ddc_i2c = info->BiosConnector[i].ddc_i2c;
2695209ff23fSmrg	    radeon_output->igp_lane_info = info->BiosConnector[i].igp_lane_info;
2696b7e1c893Smrg	    radeon_output->shared_ddc = info->BiosConnector[i].shared_ddc;
2697b7e1c893Smrg	    radeon_output->load_detection = info->BiosConnector[i].load_detection;
2698b7e1c893Smrg	    radeon_output->linkb = info->BiosConnector[i].linkb;
2699b7e1c893Smrg	    radeon_output->connector_id = info->BiosConnector[i].connector_object;
2700b7e1c893Smrg
2701b7e1c893Smrg	    if ((conntype == CONNECTOR_DVI_D) ||
2702b7e1c893Smrg		(conntype == CONNECTOR_DVI_I) ||
2703b7e1c893Smrg		(conntype == CONNECTOR_DVI_A)) {
2704b7e1c893Smrg		output = RADEONOutputCreate(pScrn, "DVI-%d", --num_dvi);
2705b7e1c893Smrg	    } else if (conntype == CONNECTOR_VGA) {
2706b7e1c893Smrg		output = RADEONOutputCreate(pScrn, "VGA-%d", --num_vga);
2707b7e1c893Smrg	    } else if ((conntype == CONNECTOR_HDMI_TYPE_A) ||
2708b7e1c893Smrg		       (conntype == CONNECTOR_HDMI_TYPE_B)) {
2709b7e1c893Smrg		output = RADEONOutputCreate(pScrn, "HDMI-%d", --num_hdmi);
2710b7e1c893Smrg	    } else if (conntype == CONNECTOR_DISPLAY_PORT) {
2711b7e1c893Smrg		output = RADEONOutputCreate(pScrn, "DisplayPort-%d", --num_dp);
2712b7e1c893Smrg	    } else {
2713b7e1c893Smrg		output = RADEONOutputCreate(pScrn,
2714b7e1c893Smrg					    ConnectorTypeName[conntype], 0);
2715b7e1c893Smrg	    }
2716209ff23fSmrg
2717209ff23fSmrg	    if (!output) {
2718209ff23fSmrg		return FALSE;
2719209ff23fSmrg	    }
2720209ff23fSmrg	    output->driver_private = radeon_output;
2721209ff23fSmrg	    output->possible_crtcs = 1;
2722209ff23fSmrg	    /* crtc2 can drive LVDS, it just doesn't have RMX */
2723b7e1c893Smrg	    if (!(radeon_output->devices & (ATOM_DEVICE_LCD_SUPPORT)))
2724209ff23fSmrg		output->possible_crtcs |= 2;
2725209ff23fSmrg
2726b7e1c893Smrg	    /* we can clone the DACs, and probably TV-out,
2727209ff23fSmrg	       but I'm not sure it's worth the trouble */
2728209ff23fSmrg	    output->possible_clones = 0;
2729209ff23fSmrg
2730209ff23fSmrg	    RADEONInitConnector(output);
2731209ff23fSmrg	}
2732209ff23fSmrg    }
2733209ff23fSmrg
2734209ff23fSmrg    for (i = 0; i < xf86_config->num_output; i++) {
2735209ff23fSmrg	xf86OutputPtr output = xf86_config->output[i];
2736209ff23fSmrg
2737209ff23fSmrg	output->possible_clones = radeon_output_clones(pScrn, output);
2738209ff23fSmrg    }
2739209ff23fSmrg
2740209ff23fSmrg    return TRUE;
2741209ff23fSmrg}
2742209ff23fSmrg
2743