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>
35ad43ddacSmrg#include <fcntl.h>
36ba58b518Smacallan#ifdef __NetBSD__
37ba58b518Smacallan#include <sys/ioctl.h>
38ba58b518Smacallan#include <dev/ofw/openfirmio.h>
39ba58b518Smacallan#endif
40209ff23fSmrg/* X and server generic header files */
41209ff23fSmrg#include "xf86.h"
42209ff23fSmrg#include "xf86_OSproc.h"
43209ff23fSmrg#include "vgaHW.h"
44209ff23fSmrg#include "xf86Modes.h"
45209ff23fSmrg
46209ff23fSmrg/* Driver data structures */
47209ff23fSmrg#include "radeon.h"
48209ff23fSmrg#include "radeon_reg.h"
49209ff23fSmrg#include "radeon_macros.h"
50209ff23fSmrg#include "radeon_probe.h"
51209ff23fSmrg#include "radeon_version.h"
52209ff23fSmrg#include "radeon_tv.h"
53209ff23fSmrg#include "radeon_atombios.h"
54209ff23fSmrg
55b7e1c893Smrgconst char *encoder_name[34] = {
56b7e1c893Smrg    "NONE",
57b7e1c893Smrg    "INTERNAL_LVDS",
58b7e1c893Smrg    "INTERNAL_TMDS1",
59b7e1c893Smrg    "INTERNAL_TMDS2",
60b7e1c893Smrg    "INTERNAL_DAC1",
61b7e1c893Smrg    "INTERNAL_DAC2",
62b7e1c893Smrg    "INTERNAL_SDVOA",
63b7e1c893Smrg    "INTERNAL_SDVOB",
64b7e1c893Smrg    "SI170B",
65b7e1c893Smrg    "CH7303",
66b7e1c893Smrg    "CH7301",
67b7e1c893Smrg    "INTERNAL_DVO1",
68b7e1c893Smrg    "EXTERNAL_SDVOA",
69b7e1c893Smrg    "EXTERNAL_SDVOB",
70b7e1c893Smrg    "TITFP513",
71b7e1c893Smrg    "INTERNAL_LVTM1",
72b7e1c893Smrg    "VT1623",
73b7e1c893Smrg    "HDMI_SI1930",
74b7e1c893Smrg    "HDMI_INTERNAL",
75b7e1c893Smrg    "INTERNAL_KLDSCP_TMDS1",
76b7e1c893Smrg    "INTERNAL_KLDSCP_DVO1",
77b7e1c893Smrg    "INTERNAL_KLDSCP_DAC1",
78b7e1c893Smrg    "INTERNAL_KLDSCP_DAC2",
79b7e1c893Smrg    "SI178",
80b7e1c893Smrg    "MVPU_FPGA",
81b7e1c893Smrg    "INTERNAL_DDI",
82b7e1c893Smrg    "VT1625",
83b7e1c893Smrg    "HDMI_SI1932",
84b7e1c893Smrg    "DP_AN9801",
85b7e1c893Smrg    "DP_DP501",
86b7e1c893Smrg    "INTERNAL_UNIPHY",
87b7e1c893Smrg    "INTERNAL_KLDSCP_LVTMA",
88b7e1c893Smrg    "INTERNAL_UNIPHY1",
89b7e1c893Smrg    "INTERNAL_UNIPHY2",
90209ff23fSmrg};
91209ff23fSmrg
92ad43ddacSmrgconst char *ConnectorTypeName[18] = {
93209ff23fSmrg  "None",
94209ff23fSmrg  "VGA",
95209ff23fSmrg  "DVI-I",
96209ff23fSmrg  "DVI-D",
97209ff23fSmrg  "DVI-A",
98b7e1c893Smrg  "S-video",
99b7e1c893Smrg  "Composite",
100209ff23fSmrg  "LVDS",
101209ff23fSmrg  "Digital",
102209ff23fSmrg  "SCART",
103209ff23fSmrg  "HDMI-A",
104209ff23fSmrg  "HDMI-B",
105209ff23fSmrg  "Unsupported",
106209ff23fSmrg  "Unsupported",
107209ff23fSmrg  "DIN",
108209ff23fSmrg  "DisplayPort",
109ad43ddacSmrg  "eDP",
110209ff23fSmrg  "Unsupported"
111209ff23fSmrg};
112209ff23fSmrg
113209ff23fSmrgextern void atombios_output_mode_set(xf86OutputPtr output,
114209ff23fSmrg				     DisplayModePtr mode,
115209ff23fSmrg				     DisplayModePtr adjusted_mode);
116209ff23fSmrgextern void atombios_output_dpms(xf86OutputPtr output, int mode);
117b7e1c893Smrgextern RADEONMonitorType atombios_dac_detect(xf86OutputPtr output);
118b7e1c893Smrgextern AtomBiosResult
119b7e1c893Smrgatombios_lock_crtc(atomBiosHandlePtr atomBIOS, int crtc, int lock);
120209ff23fSmrgstatic void
121209ff23fSmrgradeon_bios_output_dpms(xf86OutputPtr output, int mode);
122209ff23fSmrgstatic void
123209ff23fSmrgradeon_bios_output_crtc(xf86OutputPtr output);
124209ff23fSmrgstatic void
125209ff23fSmrgradeon_bios_output_lock(xf86OutputPtr output, Bool lock);
126b13dfe66Smrgextern void
127b13dfe66Smrgatombios_pick_dig_encoder(xf86OutputPtr output);
128209ff23fSmrg
129209ff23fSmrgvoid RADEONPrintPortMap(ScrnInfoPtr pScrn)
130209ff23fSmrg{
131b7e1c893Smrg    RADEONInfoPtr info = RADEONPTR(pScrn);
132209ff23fSmrg    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
133209ff23fSmrg    RADEONOutputPrivatePtr radeon_output;
134209ff23fSmrg    xf86OutputPtr output;
135209ff23fSmrg    int o;
136209ff23fSmrg
137209ff23fSmrg    for (o = 0; o < xf86_config->num_output; o++) {
138209ff23fSmrg	output = xf86_config->output[o];
139209ff23fSmrg	radeon_output = output->driver_private;
140209ff23fSmrg
141b7e1c893Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Port%d:\n", o);
142b7e1c893Smrg	ErrorF("  XRANDR name: %s\n", output->name);
143b7e1c893Smrg	ErrorF("  Connector: %s\n", ConnectorTypeName[radeon_output->ConnectorType]);
144b7e1c893Smrg	if (radeon_output->devices & ATOM_DEVICE_CRT1_SUPPORT)
145b7e1c893Smrg	    ErrorF("  CRT1: %s\n", encoder_name[info->encoders[ATOM_DEVICE_CRT1_INDEX]->encoder_id]);
146b7e1c893Smrg	if (radeon_output->devices & ATOM_DEVICE_CRT2_SUPPORT)
147b7e1c893Smrg	    ErrorF("  CRT2: %s\n", encoder_name[info->encoders[ATOM_DEVICE_CRT2_INDEX]->encoder_id]);
148b7e1c893Smrg	if (radeon_output->devices & ATOM_DEVICE_LCD1_SUPPORT)
149b7e1c893Smrg	    ErrorF("  LCD1: %s\n", encoder_name[info->encoders[ATOM_DEVICE_LCD1_INDEX]->encoder_id]);
150b7e1c893Smrg	if (radeon_output->devices & ATOM_DEVICE_DFP1_SUPPORT)
151b7e1c893Smrg	    ErrorF("  DFP1: %s\n", encoder_name[info->encoders[ATOM_DEVICE_DFP1_INDEX]->encoder_id]);
152b7e1c893Smrg	if (radeon_output->devices & ATOM_DEVICE_DFP2_SUPPORT)
153b7e1c893Smrg	    ErrorF("  DFP2: %s\n", encoder_name[info->encoders[ATOM_DEVICE_DFP2_INDEX]->encoder_id]);
154b7e1c893Smrg	if (radeon_output->devices & ATOM_DEVICE_DFP3_SUPPORT)
155b7e1c893Smrg	    ErrorF("  DFP3: %s\n", encoder_name[info->encoders[ATOM_DEVICE_DFP3_INDEX]->encoder_id]);
156b7e1c893Smrg	if (radeon_output->devices & ATOM_DEVICE_DFP4_SUPPORT)
157b7e1c893Smrg	    ErrorF("  DFP4: %s\n", encoder_name[info->encoders[ATOM_DEVICE_DFP4_INDEX]->encoder_id]);
158b7e1c893Smrg	if (radeon_output->devices & ATOM_DEVICE_DFP5_SUPPORT)
159b7e1c893Smrg	    ErrorF("  DFP5: %s\n", encoder_name[info->encoders[ATOM_DEVICE_DFP5_INDEX]->encoder_id]);
160b7e1c893Smrg	if (radeon_output->devices & ATOM_DEVICE_TV1_SUPPORT)
161b7e1c893Smrg	    ErrorF("  TV1: %s\n", encoder_name[info->encoders[ATOM_DEVICE_TV1_INDEX]->encoder_id]);
162b7e1c893Smrg	if (radeon_output->devices & ATOM_DEVICE_CV_SUPPORT)
163ad43ddacSmrg	    ErrorF("  CV: %s\n", encoder_name[info->encoders[ATOM_DEVICE_CV_INDEX]->encoder_id]);
164b7e1c893Smrg	ErrorF("  DDC reg: 0x%x\n",(unsigned int)radeon_output->ddc_i2c.mask_clk_reg);
165209ff23fSmrg    }
166209ff23fSmrg
167209ff23fSmrg}
168209ff23fSmrg
169b7e1c893Smrgstatic void
170b7e1c893Smrgradeon_set_active_device(xf86OutputPtr output)
171209ff23fSmrg{
172209ff23fSmrg    RADEONOutputPrivatePtr radeon_output = output->driver_private;
173209ff23fSmrg
174b7e1c893Smrg    radeon_output->active_device = 0;
175b7e1c893Smrg
176b7e1c893Smrg    switch (radeon_output->MonType) {
177b7e1c893Smrg    case MT_DP:
178b7e1c893Smrg    case MT_DFP:
179b7e1c893Smrg	if (radeon_output->devices & ATOM_DEVICE_DFP1_SUPPORT)
180b7e1c893Smrg	    radeon_output->active_device = ATOM_DEVICE_DFP1_SUPPORT;
181b7e1c893Smrg	else if (radeon_output->devices & ATOM_DEVICE_DFP2_SUPPORT)
182b7e1c893Smrg	    radeon_output->active_device = ATOM_DEVICE_DFP2_SUPPORT;
183b7e1c893Smrg	else if (radeon_output->devices & ATOM_DEVICE_DFP3_SUPPORT)
184b7e1c893Smrg	    radeon_output->active_device = ATOM_DEVICE_DFP3_SUPPORT;
185b7e1c893Smrg	else if (radeon_output->devices & ATOM_DEVICE_DFP4_SUPPORT)
186b7e1c893Smrg	    radeon_output->active_device = ATOM_DEVICE_DFP4_SUPPORT;
187b7e1c893Smrg	else if (radeon_output->devices & ATOM_DEVICE_DFP5_SUPPORT)
188b7e1c893Smrg	    radeon_output->active_device = ATOM_DEVICE_DFP5_SUPPORT;
189ad43ddacSmrg	else if (radeon_output->devices & ATOM_DEVICE_LCD1_SUPPORT)
190ad43ddacSmrg	    radeon_output->active_device = ATOM_DEVICE_LCD1_SUPPORT;
191ad43ddacSmrg	else if (radeon_output->devices & ATOM_DEVICE_LCD2_SUPPORT)
192ad43ddacSmrg	    radeon_output->active_device = ATOM_DEVICE_LCD2_SUPPORT;
193b7e1c893Smrg	break;
194b7e1c893Smrg    case MT_CRT:
195b7e1c893Smrg	if (radeon_output->devices & ATOM_DEVICE_CRT1_SUPPORT)
196b7e1c893Smrg	    radeon_output->active_device = ATOM_DEVICE_CRT1_SUPPORT;
197b7e1c893Smrg	else if (radeon_output->devices & ATOM_DEVICE_CRT2_SUPPORT)
198b7e1c893Smrg	    radeon_output->active_device = ATOM_DEVICE_CRT2_SUPPORT;
199b7e1c893Smrg	break;
200b7e1c893Smrg    case MT_LCD:
201b7e1c893Smrg	if (radeon_output->devices & ATOM_DEVICE_LCD1_SUPPORT)
202b7e1c893Smrg	    radeon_output->active_device = ATOM_DEVICE_LCD1_SUPPORT;
203b7e1c893Smrg	else if (radeon_output->devices & ATOM_DEVICE_LCD2_SUPPORT)
204b7e1c893Smrg	    radeon_output->active_device = ATOM_DEVICE_LCD2_SUPPORT;
205b7e1c893Smrg	break;
206b7e1c893Smrg    case MT_STV:
207b7e1c893Smrg    case MT_CTV:
208b7e1c893Smrg	if (radeon_output->devices & ATOM_DEVICE_TV1_SUPPORT)
209b7e1c893Smrg	    radeon_output->active_device = ATOM_DEVICE_TV1_SUPPORT;
210b7e1c893Smrg	else if (radeon_output->devices & ATOM_DEVICE_TV2_SUPPORT)
211b7e1c893Smrg	    radeon_output->active_device = ATOM_DEVICE_TV2_SUPPORT;
212b7e1c893Smrg	break;
213b7e1c893Smrg    case MT_CV:
214b7e1c893Smrg	if (radeon_output->devices & ATOM_DEVICE_CV_SUPPORT)
215b7e1c893Smrg	    radeon_output->active_device = ATOM_DEVICE_CV_SUPPORT;
216b7e1c893Smrg	break;
217b7e1c893Smrg    default:
218b7e1c893Smrg	ErrorF("Unhandled monitor type %d\n", radeon_output->MonType);
219b7e1c893Smrg	radeon_output->active_device = 0;
220209ff23fSmrg    }
221209ff23fSmrg}
222209ff23fSmrg
223ad43ddacSmrgstatic Bool
224ad43ddacSmrgmonitor_is_digital(xf86MonPtr MonInfo)
225ad43ddacSmrg{
226ad43ddacSmrg    return (MonInfo->rawData[0x14] & 0x80) != 0;
227ad43ddacSmrg}
228ad43ddacSmrg
229ad43ddacSmrgstatic void
230ad43ddacSmrgRADEONGetHardCodedEDIDFromFile(xf86OutputPtr output)
231ad43ddacSmrg{
232ad43ddacSmrg    ScrnInfoPtr pScrn = output->scrn;
233ad43ddacSmrg    RADEONInfoPtr info = RADEONPTR(pScrn);
234ad43ddacSmrg    RADEONOutputPrivatePtr radeon_output = output->driver_private;
235ad43ddacSmrg    char *EDIDlist = (char *)xf86GetOptValString(info->Options, OPTION_CUSTOM_EDID);
236ad43ddacSmrg
237ad43ddacSmrg    radeon_output->custom_edid = FALSE;
238ad43ddacSmrg    radeon_output->custom_mon = NULL;
239ad43ddacSmrg
240ad43ddacSmrg    if (EDIDlist != NULL) {
241ad43ddacSmrg	unsigned char* edid = xnfcalloc(128, 1);
242ad43ddacSmrg	char *name = output->name;
243ad43ddacSmrg	char *outputEDID = strstr(EDIDlist, name);
244ad43ddacSmrg
245ad43ddacSmrg	if (outputEDID != NULL) {
246ad43ddacSmrg	    char *end;
247ad43ddacSmrg	    char *colon;
248ad43ddacSmrg	    char *command = NULL;
249ad43ddacSmrg	    int fd;
250ad43ddacSmrg
251ad43ddacSmrg	    outputEDID += strlen(name) + 1;
252ad43ddacSmrg	    end = strstr(outputEDID, ";");
253ad43ddacSmrg	    if (end != NULL)
254ad43ddacSmrg		*end = 0;
255ad43ddacSmrg
256ad43ddacSmrg	    colon = strstr(outputEDID, ":");
257ad43ddacSmrg	    if (colon != NULL) {
258ad43ddacSmrg		*colon = 0;
259ad43ddacSmrg		command = colon + 1;
260ad43ddacSmrg	    }
261ad43ddacSmrg
262ad43ddacSmrg	    fd = open (outputEDID, O_RDONLY);
263ad43ddacSmrg	    if (fd >= 0) {
264ad43ddacSmrg		read(fd, edid, 128);
265ad43ddacSmrg		close(fd);
266ad43ddacSmrg		if (edid[1] == 0xff) {
267ad43ddacSmrg		    radeon_output->custom_mon = xf86InterpretEDID(output->scrn->scrnIndex, edid);
268ad43ddacSmrg		    radeon_output->custom_edid = TRUE;
269ad43ddacSmrg		    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
270ad43ddacSmrg			       "Successfully read Custom EDID data for output %s from %s.\n",
271ad43ddacSmrg			       name, outputEDID);
272ad43ddacSmrg		    if (command != NULL) {
273ad43ddacSmrg			if (!strcmp(command, "digital")) {
274ad43ddacSmrg			    radeon_output->custom_mon->rawData[0x14] |= 0x80;
275ad43ddacSmrg			    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
276ad43ddacSmrg				       "Forcing digital output for output %s.\n", name);
277ad43ddacSmrg			} else if (!strcmp(command, "analog")) {
278ad43ddacSmrg			    radeon_output->custom_mon->rawData[0x14] &= ~0x80;
279ad43ddacSmrg			    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
280ad43ddacSmrg				       "Forcing analog output for output %s.\n", name);
281ad43ddacSmrg			} else {
282ad43ddacSmrg			    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
283ad43ddacSmrg				       "Unknown custom EDID command: '%s'.\n",
284ad43ddacSmrg				       command);
285ad43ddacSmrg			}
286ad43ddacSmrg		    }
287ad43ddacSmrg		} else {
288ad43ddacSmrg		    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
289ad43ddacSmrg			       "Custom EDID data for %s read from %s was invalid.\n",
290ad43ddacSmrg			       name, outputEDID);
291ad43ddacSmrg		}
292ad43ddacSmrg	    } else {
293ad43ddacSmrg		xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
294ad43ddacSmrg			   "Could not read custom EDID for output %s from file %s.\n",
295ad43ddacSmrg			   name, outputEDID);
296ad43ddacSmrg	    }
297ad43ddacSmrg	} else {
298ad43ddacSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
299ad43ddacSmrg		       "Could not find EDID file name for output %s; using auto detection.\n",
300ad43ddacSmrg		       name);
301ad43ddacSmrg	}
302ad43ddacSmrg    }
303ad43ddacSmrg}
304ad43ddacSmrg
305ad43ddacSmrg
306209ff23fSmrgstatic RADEONMonitorType
307209ff23fSmrgradeon_ddc_connected(xf86OutputPtr output)
308209ff23fSmrg{
309209ff23fSmrg    ScrnInfoPtr pScrn        = output->scrn;
310209ff23fSmrg    RADEONInfoPtr info = RADEONPTR(pScrn);
311209ff23fSmrg    RADEONMonitorType MonType = MT_NONE;
312209ff23fSmrg    xf86MonPtr MonInfo = NULL;
313209ff23fSmrg    RADEONOutputPrivatePtr radeon_output = output->driver_private;
314ad43ddacSmrg    int ret;
315ad43ddacSmrg
316ad43ddacSmrg    if (radeon_output->custom_edid) {
317ad43ddacSmrg	MonInfo = xnfcalloc(sizeof(xf86Monitor), 1);
318ad43ddacSmrg	*MonInfo = *radeon_output->custom_mon;
319ad43ddacSmrg    } else if ((radeon_output->ConnectorType == CONNECTOR_DISPLAY_PORT) ||
320ad43ddacSmrg	       (radeon_output->ConnectorType == CONNECTOR_EDP)) {
321ad43ddacSmrg	ret = RADEON_DP_GetSinkType(output);
322ad43ddacSmrg	if (ret == CONNECTOR_OBJECT_ID_DISPLAYPORT ||
323ad43ddacSmrg	    ret == CONNECTOR_OBJECT_ID_eDP) {
324ad43ddacSmrg		MonInfo = xf86OutputGetEDID(output, radeon_output->dp_pI2CBus);
325ad43ddacSmrg	}
326ad43ddacSmrg	if (MonInfo == NULL) {
327ad43ddacSmrg	    if (radeon_output->pI2CBus) {
328ad43ddacSmrg		RADEONI2CDoLock(output, radeon_output->pI2CBus, TRUE);
329ad43ddacSmrg		MonInfo = xf86OutputGetEDID(output, radeon_output->pI2CBus);
330ad43ddacSmrg		RADEONI2CDoLock(output, radeon_output->pI2CBus, FALSE);
331ad43ddacSmrg	    }
332ad43ddacSmrg	}
333ad43ddacSmrg    } else if (radeon_output->pI2CBus) {
334c503f109Smrg	if (info->get_hardcoded_edid_from_bios)
335b7e1c893Smrg	    MonInfo = RADEONGetHardCodedEDIDFromBIOS(output);
336c503f109Smrg	if (MonInfo == NULL) {
337c503f109Smrg	    RADEONI2CDoLock(output, radeon_output->pI2CBus, TRUE);
338b7e1c893Smrg	    MonInfo = xf86OutputGetEDID(output, radeon_output->pI2CBus);
339c503f109Smrg	    RADEONI2CDoLock(output, radeon_output->pI2CBus, FALSE);
340b7e1c893Smrg	}
341b7e1c893Smrg    }
342209ff23fSmrg    if (MonInfo) {
343b7e1c893Smrg	switch (radeon_output->ConnectorType) {
344b7e1c893Smrg	case CONNECTOR_LVDS:
345209ff23fSmrg	    MonType = MT_LCD;
346b7e1c893Smrg	    break;
347b7e1c893Smrg	case CONNECTOR_DVI_D:
348b7e1c893Smrg	case CONNECTOR_HDMI_TYPE_A:
349b7e1c893Smrg	    if (radeon_output->shared_ddc) {
350ad43ddacSmrg		xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR (output->scrn);
351ad43ddacSmrg		int i;
352ad43ddacSmrg
353ad43ddacSmrg		if (monitor_is_digital(MonInfo))
354b7e1c893Smrg		    MonType = MT_DFP;
355b7e1c893Smrg		else
356b7e1c893Smrg		    MonType = MT_NONE;
357ad43ddacSmrg
358ad43ddacSmrg		for (i = 0; i < config->num_output; i++) {
359ad43ddacSmrg		    if (output != config->output[i]) {
360ad43ddacSmrg			RADEONOutputPrivatePtr other_radeon_output =
361ad43ddacSmrg			    config->output[i]->driver_private;
362ad43ddacSmrg			if (radeon_output->devices & other_radeon_output->devices) {
363ad43ddacSmrg#ifndef EDID_COMPLETE_RAWDATA
364ad43ddacSmrg			    if (radeon_output->ConnectorType == CONNECTOR_HDMI_TYPE_A) {
365ad43ddacSmrg				MonType = MT_NONE;
366ad43ddacSmrg				break;
367ad43ddacSmrg			    }
368ad43ddacSmrg#else
369ad43ddacSmrg			    if (xf86MonitorIsHDMI(MonInfo)) {
370ad43ddacSmrg				if (radeon_output->ConnectorType == CONNECTOR_DVI_D) {
371ad43ddacSmrg				    MonType = MT_NONE;
372ad43ddacSmrg				    break;
373ad43ddacSmrg				}
374ad43ddacSmrg			    } else {
375ad43ddacSmrg				if (radeon_output->ConnectorType == CONNECTOR_HDMI_TYPE_A) {
376ad43ddacSmrg				    MonType = MT_NONE;
377ad43ddacSmrg				    break;
378ad43ddacSmrg				}
379ad43ddacSmrg			    }
380ad43ddacSmrg#endif
381ad43ddacSmrg			}
382ad43ddacSmrg		    }
383ad43ddacSmrg		}
384b7e1c893Smrg	    } else
385b7e1c893Smrg		MonType = MT_DFP;
386b7e1c893Smrg	    break;
387b7e1c893Smrg	case CONNECTOR_DISPLAY_PORT:
388ad43ddacSmrg	case CONNECTOR_EDP:
389b7e1c893Smrg	    /*
390b7e1c893Smrg	     * XXX wrong. need to infer based on whether we got DDC from I2C
391b7e1c893Smrg	     * or AUXCH.
392b7e1c893Smrg	     */
393ad43ddacSmrg	    ret = RADEON_DP_GetSinkType(output);
394ad43ddacSmrg
395ad43ddacSmrg	    if ((ret == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
396ad43ddacSmrg		(ret == CONNECTOR_OBJECT_ID_eDP)) {
397ad43ddacSmrg		MonType = MT_DP;
398ad43ddacSmrg		RADEON_DP_GetDPCD(output);
399ad43ddacSmrg	    } else
400ad43ddacSmrg		MonType = MT_DFP;
401ad43ddacSmrg	    break;
402ad43ddacSmrg	case CONNECTOR_HDMI_TYPE_B:
403b7e1c893Smrg	case CONNECTOR_DVI_I:
404ad43ddacSmrg	    if (monitor_is_digital(MonInfo))
405b7e1c893Smrg		MonType = MT_DFP;
406b7e1c893Smrg	    else
407b7e1c893Smrg		MonType = MT_CRT;
408b7e1c893Smrg	    break;
409b7e1c893Smrg	case CONNECTOR_VGA:
410b7e1c893Smrg	case CONNECTOR_DVI_A:
411b7e1c893Smrg	default:
412b7e1c893Smrg	    if (radeon_output->shared_ddc) {
413ad43ddacSmrg		if (monitor_is_digital(MonInfo))
414b7e1c893Smrg		    MonType = MT_NONE;
415b7e1c893Smrg		else
416b7e1c893Smrg		    MonType = MT_CRT;
417b7e1c893Smrg	    } else
418b7e1c893Smrg		MonType = MT_CRT;
419b7e1c893Smrg	    break;
420b7e1c893Smrg	}
421b7e1c893Smrg
422ad43ddacSmrg	if (MonType != MT_NONE) {
423b7e1c893Smrg	    if (!xf86ReturnOptValBool(info->Options, OPTION_IGNORE_EDID, FALSE))
424b7e1c893Smrg		xf86OutputSetEDID(output, MonInfo);
425ad43ddacSmrg	} else
4262f39173dSmrg	    free(MonInfo);
427209ff23fSmrg    } else
428209ff23fSmrg	MonType = MT_NONE;
429b7e1c893Smrg
430209ff23fSmrg    return MonType;
431209ff23fSmrg}
432209ff23fSmrg
433209ff23fSmrg#ifndef __powerpc__
434209ff23fSmrg
435209ff23fSmrgstatic RADEONMonitorType
436209ff23fSmrgRADEONDetectLidStatus(ScrnInfoPtr pScrn)
437209ff23fSmrg{
438209ff23fSmrg    RADEONInfoPtr info = RADEONPTR(pScrn);
439209ff23fSmrg    RADEONMonitorType MonType = MT_NONE;
440209ff23fSmrg#ifdef __linux__
441209ff23fSmrg    char lidline[50];  /* 50 should be sufficient for our purposes */
442209ff23fSmrg    FILE *f = fopen ("/proc/acpi/button/lid/LID/state", "r");
443209ff23fSmrg
444209ff23fSmrg    if (f != NULL) {
445209ff23fSmrg	while (fgets(lidline, sizeof lidline, f)) {
446209ff23fSmrg	    if (!strncmp(lidline, "state:", strlen ("state:"))) {
447209ff23fSmrg		if (strstr(lidline, "open")) {
448209ff23fSmrg		    fclose(f);
449209ff23fSmrg		    ErrorF("proc lid open\n");
450209ff23fSmrg		    return MT_LCD;
451209ff23fSmrg		}
452209ff23fSmrg		else if (strstr(lidline, "closed")) {
453209ff23fSmrg		    fclose(f);
454209ff23fSmrg		    ErrorF("proc lid closed\n");
455209ff23fSmrg		    return MT_NONE;
456209ff23fSmrg		}
457209ff23fSmrg	    }
458209ff23fSmrg	}
459209ff23fSmrg	fclose(f);
460209ff23fSmrg    }
461209ff23fSmrg#endif
462209ff23fSmrg
463209ff23fSmrg    if (!info->IsAtomBios) {
464209ff23fSmrg	unsigned char *RADEONMMIO = info->MMIO;
465209ff23fSmrg
466209ff23fSmrg	/* see if the lid is closed -- only works at boot */
467209ff23fSmrg	if (INREG(RADEON_BIOS_6_SCRATCH) & 0x10)
468209ff23fSmrg	    MonType = MT_NONE;
469209ff23fSmrg	else
470209ff23fSmrg	    MonType = MT_LCD;
471209ff23fSmrg    } else
472209ff23fSmrg	MonType = MT_LCD;
473209ff23fSmrg
474209ff23fSmrg    return MonType;
475209ff23fSmrg}
476209ff23fSmrg
477209ff23fSmrg#endif /* __powerpc__ */
478209ff23fSmrg
479209ff23fSmrgstatic void
480209ff23fSmrgradeon_dpms(xf86OutputPtr output, int mode)
481209ff23fSmrg{
482209ff23fSmrg    RADEONInfoPtr info = RADEONPTR(output->scrn);
483209ff23fSmrg    RADEONOutputPrivatePtr radeon_output = output->driver_private;
484209ff23fSmrg
485209ff23fSmrg    if ((mode == DPMSModeOn) && radeon_output->enabled)
486209ff23fSmrg	return;
487209ff23fSmrg
488ad43ddacSmrg    if ((mode != DPMSModeOn) && radeon_output->shared_ddc) {
489ad43ddacSmrg	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR (output->scrn);
490ad43ddacSmrg	int i;
491ad43ddacSmrg
492ad43ddacSmrg	for (i = 0; i < config->num_output; i++) {
493ad43ddacSmrg	    if (output != config->output[i]) {
494ad43ddacSmrg		RADEONOutputPrivatePtr other_radeon_output =
495ad43ddacSmrg		    config->output[i]->driver_private;
496ad43ddacSmrg		if (radeon_output->devices & other_radeon_output->devices) {
497ad43ddacSmrg		    if (output->status == XF86OutputStatusDisconnected)
498ad43ddacSmrg			return;
499ad43ddacSmrg		}
500ad43ddacSmrg	    }
501ad43ddacSmrg	}
502ad43ddacSmrg    }
503ad43ddacSmrg
504b7e1c893Smrg    if (IS_AVIVO_VARIANT || info->r4xx_atom) {
505209ff23fSmrg	atombios_output_dpms(output, mode);
506209ff23fSmrg    } else {
507209ff23fSmrg	legacy_output_dpms(output, mode);
508209ff23fSmrg    }
509209ff23fSmrg    radeon_bios_output_dpms(output, mode);
510209ff23fSmrg
511209ff23fSmrg    if (mode == DPMSModeOn)
512209ff23fSmrg	radeon_output->enabled = TRUE;
513209ff23fSmrg    else
514209ff23fSmrg	radeon_output->enabled = FALSE;
515209ff23fSmrg
516209ff23fSmrg}
517209ff23fSmrg
518209ff23fSmrgstatic void
519209ff23fSmrgradeon_save(xf86OutputPtr output)
520209ff23fSmrg{
521209ff23fSmrg
522209ff23fSmrg}
523209ff23fSmrg
524209ff23fSmrgstatic void
525209ff23fSmrgradeon_restore(xf86OutputPtr restore)
526209ff23fSmrg{
527209ff23fSmrg
528209ff23fSmrg}
529209ff23fSmrg
530209ff23fSmrgstatic int
531209ff23fSmrgradeon_mode_valid(xf86OutputPtr output, DisplayModePtr pMode)
532209ff23fSmrg{
533209ff23fSmrg    RADEONOutputPrivatePtr radeon_output = output->driver_private;
534b7e1c893Smrg    radeon_native_mode_ptr native_mode = &radeon_output->native_mode;
535209ff23fSmrg    ScrnInfoPtr pScrn = output->scrn;
536209ff23fSmrg    RADEONInfoPtr info = RADEONPTR(pScrn);
537209ff23fSmrg    RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
538209ff23fSmrg
539209ff23fSmrg    /*
540209ff23fSmrg     * RN50 has effective maximum mode bandwidth of about 300MiB/s.
541209ff23fSmrg     * XXX should really do this for all chips by properly computing
542209ff23fSmrg     * memory bandwidth and an overhead factor.
543209ff23fSmrg     */
544209ff23fSmrg    if (info->ChipFamily == CHIP_FAMILY_RV100 && !pRADEONEnt->HasCRTC2) {
545209ff23fSmrg	if (xf86ModeBandwidth(pMode, pScrn->bitsPerPixel) > 300)
546209ff23fSmrg	    return MODE_BANDWIDTH;
547209ff23fSmrg    }
548209ff23fSmrg
549b7e1c893Smrg    if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT)) {
550b7e1c893Smrg	if (IS_AVIVO_VARIANT)
551b7e1c893Smrg	    return MODE_OK;
552b7e1c893Smrg	else {
553b7e1c893Smrg	    /* FIXME: Update when more modes are added */
554209ff23fSmrg	    if (pMode->HDisplay == 800 && pMode->VDisplay == 600)
555209ff23fSmrg		return MODE_OK;
556209ff23fSmrg	    else
557209ff23fSmrg		return MODE_CLOCK_RANGE;
558209ff23fSmrg	}
559209ff23fSmrg    }
560209ff23fSmrg
561ad43ddacSmrg    /* clocks over 135 MHz have heat issues with DVI on RV100 */
562ad43ddacSmrg    if ((radeon_output->MonType == MT_DFP) &&
563ad43ddacSmrg	(info->ChipFamily == CHIP_FAMILY_RV100) &&
564ad43ddacSmrg	(pMode->Clock > 135000))
565ad43ddacSmrg	    return MODE_CLOCK_HIGH;
566ad43ddacSmrg
567b7e1c893Smrg    /* single link DVI check */
568b7e1c893Smrg    if (pMode->Clock > 165000 && radeon_output->MonType == MT_DFP) {
569b7e1c893Smrg	/* DP->DVI converter */
570b7e1c893Smrg	if (radeon_output->ConnectorType == CONNECTOR_DISPLAY_PORT)
571b7e1c893Smrg	    return MODE_CLOCK_HIGH;
572b7e1c893Smrg
573ad43ddacSmrg	if (radeon_output->ConnectorType == CONNECTOR_EDP)
574ad43ddacSmrg	    return MODE_CLOCK_HIGH;
575ad43ddacSmrg
576b7e1c893Smrg	/* XXX some HDMI can do better than 165MHz on a link */
577b7e1c893Smrg	if (radeon_output->ConnectorType == CONNECTOR_HDMI_TYPE_A)
578b7e1c893Smrg	    return MODE_CLOCK_HIGH;
579b7e1c893Smrg
580b7e1c893Smrg	/* XXX some R300 and R400 can actually do this */
581b7e1c893Smrg	if (!IS_AVIVO_VARIANT)
582b7e1c893Smrg	    return MODE_CLOCK_HIGH;
583b7e1c893Smrg
584b7e1c893Smrg	/* XXX and some AVIVO can't */
585b7e1c893Smrg    }
586b7e1c893Smrg
587b7e1c893Smrg    if (radeon_output->active_device & (ATOM_DEVICE_LCD_SUPPORT)) {
588209ff23fSmrg	if (radeon_output->rmx_type == RMX_OFF) {
589b7e1c893Smrg	    if (pMode->HDisplay != native_mode->PanelXRes ||
590b7e1c893Smrg		pMode->VDisplay != native_mode->PanelYRes)
591209ff23fSmrg		return MODE_PANEL;
592209ff23fSmrg	}
593b7e1c893Smrg	if (pMode->HDisplay > native_mode->PanelXRes ||
594b7e1c893Smrg	    pMode->VDisplay > native_mode->PanelYRes)
595209ff23fSmrg	    return MODE_PANEL;
596209ff23fSmrg    }
597209ff23fSmrg
598209ff23fSmrg    return MODE_OK;
599209ff23fSmrg}
600209ff23fSmrg
601209ff23fSmrgstatic Bool
602209ff23fSmrgradeon_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
603209ff23fSmrg		    DisplayModePtr adjusted_mode)
604209ff23fSmrg{
605209ff23fSmrg    RADEONInfoPtr info = RADEONPTR(output->scrn);
606209ff23fSmrg    RADEONOutputPrivatePtr radeon_output = output->driver_private;
607b7e1c893Smrg    radeon_native_mode_ptr native_mode = &radeon_output->native_mode;
608ad43ddacSmrg    xf86CrtcPtr crtc = output->crtc;
609ad43ddacSmrg    RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
610209ff23fSmrg
611209ff23fSmrg    radeon_output->Flags &= ~RADEON_USE_RMX;
612ad43ddacSmrg    radeon_crtc->scaler_enabled = FALSE;
613209ff23fSmrg
614b7e1c893Smrg    /*
615b7e1c893Smrg     *  Refresh the Crtc values without INTERLACE_HALVE_V
616b7e1c893Smrg     *  Should we use output->scrn->adjustFlags like xf86RandRModeConvert() does?
617b7e1c893Smrg     */
618b7e1c893Smrg    xf86SetModeCrtc(adjusted_mode, 0);
619b7e1c893Smrg
620209ff23fSmrg    /* decide if we are using RMX */
621b7e1c893Smrg    if ((radeon_output->active_device & (ATOM_DEVICE_LCD_SUPPORT | ATOM_DEVICE_DFP_SUPPORT))
622209ff23fSmrg	&& radeon_output->rmx_type != RMX_OFF) {
623209ff23fSmrg
624209ff23fSmrg	if (IS_AVIVO_VARIANT || radeon_crtc->crtc_id == 0) {
625b7e1c893Smrg	    if (mode->HDisplay < native_mode->PanelXRes ||
626b7e1c893Smrg		mode->VDisplay < native_mode->PanelYRes) {
627209ff23fSmrg		radeon_output->Flags |= RADEON_USE_RMX;
628ad43ddacSmrg		radeon_crtc->scaler_enabled = TRUE;
629209ff23fSmrg		if (IS_AVIVO_VARIANT) {
630ad43ddacSmrg		    radeon_crtc->hsc = (float)mode->HDisplay / (float)native_mode->PanelXRes;
631ad43ddacSmrg		    radeon_crtc->vsc = (float)mode->VDisplay / (float)native_mode->PanelYRes;
632209ff23fSmrg		    /* set to the panel's native mode */
633b7e1c893Smrg		    adjusted_mode->HDisplay = native_mode->PanelXRes;
634b7e1c893Smrg		    adjusted_mode->VDisplay = native_mode->PanelYRes;
635b7e1c893Smrg		    adjusted_mode->HTotal = native_mode->PanelXRes + native_mode->HBlank;
636b7e1c893Smrg		    adjusted_mode->HSyncStart = native_mode->PanelXRes + native_mode->HOverPlus;
637b7e1c893Smrg		    adjusted_mode->HSyncEnd = adjusted_mode->HSyncStart + native_mode->HSyncWidth;
638b7e1c893Smrg		    adjusted_mode->VTotal = native_mode->PanelYRes + native_mode->VBlank;
639b7e1c893Smrg		    adjusted_mode->VSyncStart = native_mode->PanelYRes + native_mode->VOverPlus;
640b7e1c893Smrg		    adjusted_mode->VSyncEnd = adjusted_mode->VSyncStart + native_mode->VSyncWidth;
641209ff23fSmrg		    /* update crtc values */
642209ff23fSmrg		    xf86SetModeCrtc(adjusted_mode, INTERLACE_HALVE_V);
643209ff23fSmrg		    /* adjust crtc values */
644b7e1c893Smrg		    adjusted_mode->CrtcHDisplay = native_mode->PanelXRes;
645b7e1c893Smrg		    adjusted_mode->CrtcVDisplay = native_mode->PanelYRes;
646b7e1c893Smrg		    adjusted_mode->CrtcHTotal = adjusted_mode->CrtcHDisplay + native_mode->HBlank;
647b7e1c893Smrg		    adjusted_mode->CrtcHSyncStart = adjusted_mode->CrtcHDisplay + native_mode->HOverPlus;
648b7e1c893Smrg		    adjusted_mode->CrtcHSyncEnd = adjusted_mode->CrtcHSyncStart + native_mode->HSyncWidth;
649b7e1c893Smrg		    adjusted_mode->CrtcVTotal = adjusted_mode->CrtcVDisplay + native_mode->VBlank;
650b7e1c893Smrg		    adjusted_mode->CrtcVSyncStart = adjusted_mode->CrtcVDisplay + native_mode->VOverPlus;
651b7e1c893Smrg		    adjusted_mode->CrtcVSyncEnd = adjusted_mode->CrtcVSyncStart + native_mode->VSyncWidth;
652209ff23fSmrg		} else {
653209ff23fSmrg		    /* set to the panel's native mode */
654b7e1c893Smrg		    adjusted_mode->HTotal = native_mode->PanelXRes + native_mode->HBlank;
655b7e1c893Smrg		    adjusted_mode->HSyncStart = native_mode->PanelXRes + native_mode->HOverPlus;
656b7e1c893Smrg		    adjusted_mode->HSyncEnd = adjusted_mode->HSyncStart + native_mode->HSyncWidth;
657b7e1c893Smrg		    adjusted_mode->VTotal = native_mode->PanelYRes + native_mode->VBlank;
658b7e1c893Smrg		    adjusted_mode->VSyncStart = native_mode->PanelYRes + native_mode->VOverPlus;
659b7e1c893Smrg		    adjusted_mode->VSyncEnd = adjusted_mode->VSyncStart + native_mode->VSyncWidth;
660b7e1c893Smrg		    adjusted_mode->Clock = native_mode->DotClock;
661209ff23fSmrg		    /* update crtc values */
662209ff23fSmrg		    xf86SetModeCrtc(adjusted_mode, INTERLACE_HALVE_V);
663209ff23fSmrg		    /* adjust crtc values */
664b7e1c893Smrg		    adjusted_mode->CrtcHTotal = adjusted_mode->CrtcHDisplay + native_mode->HBlank;
665b7e1c893Smrg		    adjusted_mode->CrtcHSyncStart = adjusted_mode->CrtcHDisplay + native_mode->HOverPlus;
666b7e1c893Smrg		    adjusted_mode->CrtcHSyncEnd = adjusted_mode->CrtcHSyncStart + native_mode->HSyncWidth;
667b7e1c893Smrg		    adjusted_mode->CrtcVTotal = adjusted_mode->CrtcVDisplay + native_mode->VBlank;
668b7e1c893Smrg		    adjusted_mode->CrtcVSyncStart = adjusted_mode->CrtcVDisplay + native_mode->VOverPlus;
669b7e1c893Smrg		    adjusted_mode->CrtcVSyncEnd = adjusted_mode->CrtcVSyncStart + native_mode->VSyncWidth;
670209ff23fSmrg		}
671b7e1c893Smrg		adjusted_mode->Clock = native_mode->DotClock;
672b7e1c893Smrg		adjusted_mode->Flags = native_mode->Flags;
673209ff23fSmrg	    }
674209ff23fSmrg	}
675209ff23fSmrg    }
676209ff23fSmrg
677ad43ddacSmrg    /* FIXME: vsc/hsc */
678ad43ddacSmrg    if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) {
679ad43ddacSmrg	radeon_crtc->scaler_enabled = TRUE;
680ad43ddacSmrg	radeon_crtc->hsc = (float)mode->HDisplay / (float)640;
681ad43ddacSmrg	radeon_crtc->vsc = (float)mode->VDisplay / (float)480;
682ad43ddacSmrg    }
683ad43ddacSmrg
684b7e1c893Smrg    if (IS_AVIVO_VARIANT) {
685b7e1c893Smrg	/* hw bug */
686b7e1c893Smrg	if ((mode->Flags & V_INTERLACE)
687b7e1c893Smrg	    && (adjusted_mode->CrtcVSyncStart < (adjusted_mode->CrtcVDisplay + 2)))
688b7e1c893Smrg	    adjusted_mode->CrtcVSyncStart = adjusted_mode->CrtcVDisplay + 2;
689b7e1c893Smrg    }
690b7e1c893Smrg
691ad43ddacSmrg    if (IS_AVIVO_VARIANT || info->r4xx_atom) {
692ad43ddacSmrg	if (radeon_output->MonType == MT_STV || radeon_output->MonType == MT_CTV) {
693ad43ddacSmrg	    radeon_tvout_ptr tvout = &radeon_output->tvout;
694ad43ddacSmrg	    ScrnInfoPtr pScrn = output->scrn;
695ad43ddacSmrg
696ad43ddacSmrg	    if (tvout->tvStd == TV_STD_NTSC ||
697ad43ddacSmrg		tvout->tvStd == TV_STD_NTSC_J ||
698ad43ddacSmrg		tvout->tvStd == TV_STD_PAL_M)
699ad43ddacSmrg		RADEONATOMGetTVTimings(pScrn, 0, adjusted_mode);
700ad43ddacSmrg	    else
701ad43ddacSmrg		RADEONATOMGetTVTimings(pScrn, 1, adjusted_mode);
702ad43ddacSmrg	}
703ad43ddacSmrg    }
704ad43ddacSmrg
705ad43ddacSmrg    if (((radeon_output->ConnectorType == CONNECTOR_DISPLAY_PORT) ||
706ad43ddacSmrg	 (radeon_output->ConnectorType == CONNECTOR_EDP)) &&
707ad43ddacSmrg	(radeon_output->MonType == MT_DP)) {
708ad43ddacSmrg      radeon_dp_mode_fixup(output, mode, adjusted_mode);
709ad43ddacSmrg    }
710209ff23fSmrg    return TRUE;
711209ff23fSmrg}
712209ff23fSmrg
713209ff23fSmrgstatic void
714209ff23fSmrgradeon_mode_prepare(xf86OutputPtr output)
715209ff23fSmrg{
716c503f109Smrg    RADEONInfoPtr info = RADEONPTR(output->scrn);
717c503f109Smrg    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR (output->scrn);
718c503f109Smrg    int o;
719c503f109Smrg
720c503f109Smrg    for (o = 0; o < config->num_output; o++) {
721c503f109Smrg	xf86OutputPtr loop_output = config->output[o];
722c503f109Smrg	if (loop_output == output)
723c503f109Smrg	    continue;
724c503f109Smrg	else if (loop_output->crtc) {
725c503f109Smrg	    xf86CrtcPtr other_crtc = loop_output->crtc;
726c503f109Smrg	    RADEONCrtcPrivatePtr other_radeon_crtc = other_crtc->driver_private;
727c503f109Smrg	    if (other_crtc->enabled) {
728c503f109Smrg		if (other_radeon_crtc->initialized) {
729c503f109Smrg		    radeon_crtc_dpms(other_crtc, DPMSModeOff);
730c503f109Smrg		    if (IS_AVIVO_VARIANT || info->r4xx_atom)
731c503f109Smrg			atombios_lock_crtc(info->atomBIOS, other_radeon_crtc->crtc_id, 1);
732c503f109Smrg		    radeon_dpms(loop_output, DPMSModeOff);
733c503f109Smrg		}
734c503f109Smrg	    }
735c503f109Smrg	}
736c503f109Smrg    }
737c503f109Smrg
738209ff23fSmrg    radeon_bios_output_lock(output, TRUE);
739b13dfe66Smrg    if (IS_AVIVO_VARIANT)
740b13dfe66Smrg	atombios_pick_dig_encoder(output);
741209ff23fSmrg    radeon_dpms(output, DPMSModeOff);
742c503f109Smrg    radeon_crtc_dpms(output->crtc, DPMSModeOff);
743c503f109Smrg
7440974d292Smrg    if (IS_AVIVO_VARIANT || info->r4xx_atom)
7450974d292Smrg        atombios_set_output_crtc_source(output);
7460974d292Smrg
747209ff23fSmrg}
748209ff23fSmrg
749209ff23fSmrgstatic void
750209ff23fSmrgradeon_mode_set(xf86OutputPtr output, DisplayModePtr mode,
751209ff23fSmrg		DisplayModePtr adjusted_mode)
752209ff23fSmrg{
753209ff23fSmrg    RADEONInfoPtr info = RADEONPTR(output->scrn);
754209ff23fSmrg
755b7e1c893Smrg    if (IS_AVIVO_VARIANT || info->r4xx_atom)
756209ff23fSmrg	atombios_output_mode_set(output, mode, adjusted_mode);
757209ff23fSmrg    else
758209ff23fSmrg	legacy_output_mode_set(output, mode, adjusted_mode);
759209ff23fSmrg    radeon_bios_output_crtc(output);
760209ff23fSmrg
761209ff23fSmrg}
762209ff23fSmrg
763209ff23fSmrgstatic void
764209ff23fSmrgradeon_mode_commit(xf86OutputPtr output)
765209ff23fSmrg{
766c503f109Smrg    RADEONInfoPtr info = RADEONPTR(output->scrn);
767c503f109Smrg    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR (output->scrn);
768c503f109Smrg    int o;
769c503f109Smrg
770c503f109Smrg    for (o = 0; o < config->num_output; o++) {
771c503f109Smrg	xf86OutputPtr loop_output = config->output[o];
772c503f109Smrg	if (loop_output == output)
773c503f109Smrg	    continue;
774c503f109Smrg	else if (loop_output->crtc) {
775c503f109Smrg	    xf86CrtcPtr other_crtc = loop_output->crtc;
776c503f109Smrg	    RADEONCrtcPrivatePtr other_radeon_crtc = other_crtc->driver_private;
777c503f109Smrg	    if (other_crtc->enabled) {
778c503f109Smrg		if (other_radeon_crtc->initialized) {
779c503f109Smrg		    radeon_crtc_dpms(other_crtc, DPMSModeOn);
780c503f109Smrg		    if (IS_AVIVO_VARIANT || info->r4xx_atom)
781c503f109Smrg			atombios_lock_crtc(info->atomBIOS, other_radeon_crtc->crtc_id, 0);
782c503f109Smrg		    radeon_dpms(loop_output, DPMSModeOn);
783c503f109Smrg		}
784c503f109Smrg	    }
785c503f109Smrg	}
786c503f109Smrg    }
787c503f109Smrg
788209ff23fSmrg    radeon_dpms(output, DPMSModeOn);
789c503f109Smrg    radeon_crtc_dpms(output->crtc, DPMSModeOn);
790209ff23fSmrg    radeon_bios_output_lock(output, FALSE);
791209ff23fSmrg}
792209ff23fSmrg
793209ff23fSmrgstatic void
794209ff23fSmrgradeon_bios_output_lock(xf86OutputPtr output, Bool lock)
795209ff23fSmrg{
796209ff23fSmrg    ScrnInfoPtr	    pScrn = output->scrn;
797209ff23fSmrg    RADEONInfoPtr info = RADEONPTR(pScrn);
798209ff23fSmrg    unsigned char *RADEONMMIO = info->MMIO;
799209ff23fSmrg    RADEONSavePtr save = info->ModeReg;
800209ff23fSmrg
801209ff23fSmrg    if (info->IsAtomBios) {
802209ff23fSmrg	if (lock) {
803209ff23fSmrg	    save->bios_6_scratch |= ATOM_S6_CRITICAL_STATE;
804209ff23fSmrg	} else {
805209ff23fSmrg	    save->bios_6_scratch &= ~ATOM_S6_CRITICAL_STATE;
806209ff23fSmrg	}
807209ff23fSmrg    } else {
808209ff23fSmrg	if (lock) {
809209ff23fSmrg	    save->bios_6_scratch |= RADEON_DRIVER_CRITICAL;
810209ff23fSmrg	} else {
811209ff23fSmrg	    save->bios_6_scratch &= ~RADEON_DRIVER_CRITICAL;
812209ff23fSmrg	}
813209ff23fSmrg    }
814209ff23fSmrg    if (info->ChipFamily >= CHIP_FAMILY_R600)
815209ff23fSmrg	OUTREG(R600_BIOS_6_SCRATCH, save->bios_6_scratch);
816209ff23fSmrg    else
817209ff23fSmrg	OUTREG(RADEON_BIOS_6_SCRATCH, save->bios_6_scratch);
818209ff23fSmrg}
819209ff23fSmrg
820209ff23fSmrgstatic void
821209ff23fSmrgradeon_bios_output_dpms(xf86OutputPtr output, int mode)
822209ff23fSmrg{
823209ff23fSmrg    ScrnInfoPtr	    pScrn = output->scrn;
824209ff23fSmrg    RADEONInfoPtr info = RADEONPTR(pScrn);
825209ff23fSmrg    RADEONOutputPrivatePtr radeon_output = output->driver_private;
826209ff23fSmrg    unsigned char *RADEONMMIO = info->MMIO;
827209ff23fSmrg    RADEONSavePtr save = info->ModeReg;
828209ff23fSmrg
829209ff23fSmrg    if (info->IsAtomBios) {
830b7e1c893Smrg	if (radeon_output->active_device & ATOM_DEVICE_TV1_SUPPORT) {
831b7e1c893Smrg	    if (mode == DPMSModeOn)
832b7e1c893Smrg		save->bios_2_scratch &= ~ATOM_S2_TV1_DPMS_STATE;
833b7e1c893Smrg	    else
834b7e1c893Smrg		save->bios_2_scratch |= ATOM_S2_TV1_DPMS_STATE;
835b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_CV_SUPPORT) {
836b7e1c893Smrg	    if (mode == DPMSModeOn)
837b7e1c893Smrg		save->bios_2_scratch &= ~ATOM_S2_CV_DPMS_STATE;
838b7e1c893Smrg	    else
839b7e1c893Smrg		save->bios_2_scratch |= ATOM_S2_CV_DPMS_STATE;
840b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_CRT1_SUPPORT) {
841b7e1c893Smrg	    if (mode == DPMSModeOn)
842b7e1c893Smrg		save->bios_2_scratch &= ~ATOM_S2_CRT1_DPMS_STATE;
843b7e1c893Smrg	    else
844b7e1c893Smrg		save->bios_2_scratch |= ATOM_S2_CRT1_DPMS_STATE;
845b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_CRT2_SUPPORT) {
846b7e1c893Smrg	    if (mode == DPMSModeOn)
847b7e1c893Smrg		save->bios_2_scratch &= ~ATOM_S2_CRT2_DPMS_STATE;
848b7e1c893Smrg	    else
849b7e1c893Smrg		save->bios_2_scratch |= ATOM_S2_CRT2_DPMS_STATE;
850b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_LCD1_SUPPORT) {
851b7e1c893Smrg	    if (mode == DPMSModeOn)
852b7e1c893Smrg		save->bios_2_scratch &= ~ATOM_S2_LCD1_DPMS_STATE;
853b7e1c893Smrg	    else
854b7e1c893Smrg		save->bios_2_scratch |= ATOM_S2_LCD1_DPMS_STATE;
855b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_DFP1_SUPPORT) {
856b7e1c893Smrg	    if (mode == DPMSModeOn)
857b7e1c893Smrg		save->bios_2_scratch &= ~ATOM_S2_DFP1_DPMS_STATE;
858b7e1c893Smrg	    else
859b7e1c893Smrg		save->bios_2_scratch |= ATOM_S2_DFP1_DPMS_STATE;
860b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_DFP2_SUPPORT) {
861b7e1c893Smrg	    if (mode == DPMSModeOn)
862b7e1c893Smrg		save->bios_2_scratch &= ~ATOM_S2_DFP2_DPMS_STATE;
863b7e1c893Smrg	    else
864b7e1c893Smrg		save->bios_2_scratch |= ATOM_S2_DFP2_DPMS_STATE;
865b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_DFP3_SUPPORT) {
866b7e1c893Smrg	    if (mode == DPMSModeOn)
867b7e1c893Smrg		save->bios_2_scratch &= ~ATOM_S2_DFP3_DPMS_STATE;
868b7e1c893Smrg	    else
869b7e1c893Smrg		save->bios_2_scratch |= ATOM_S2_DFP3_DPMS_STATE;
870b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_DFP4_SUPPORT) {
871b7e1c893Smrg	    if (mode == DPMSModeOn)
872b7e1c893Smrg		save->bios_2_scratch &= ~ATOM_S2_DFP4_DPMS_STATE;
873b7e1c893Smrg	    else
874b7e1c893Smrg		save->bios_2_scratch |= ATOM_S2_DFP4_DPMS_STATE;
875b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_DFP5_SUPPORT) {
876b7e1c893Smrg	    if (mode == DPMSModeOn)
877b7e1c893Smrg		save->bios_2_scratch &= ~ATOM_S2_DFP5_DPMS_STATE;
878b7e1c893Smrg	    else
879b7e1c893Smrg		save->bios_2_scratch |= ATOM_S2_DFP5_DPMS_STATE;
880209ff23fSmrg	}
881b7e1c893Smrg	if (info->ChipFamily >= CHIP_FAMILY_R600)
882209ff23fSmrg	    OUTREG(R600_BIOS_2_SCRATCH, save->bios_2_scratch);
883b7e1c893Smrg	else
884209ff23fSmrg	    OUTREG(RADEON_BIOS_2_SCRATCH, save->bios_2_scratch);
885209ff23fSmrg    } else {
886209ff23fSmrg	if (mode == DPMSModeOn) {
887209ff23fSmrg	    save->bios_6_scratch &= ~(RADEON_DPMS_MASK | RADEON_SCREEN_BLANKING);
888209ff23fSmrg	    save->bios_6_scratch |= RADEON_DPMS_ON;
889209ff23fSmrg	} else {
890209ff23fSmrg	    save->bios_6_scratch &= ~RADEON_DPMS_MASK;
891209ff23fSmrg	    save->bios_6_scratch |= (RADEON_DPMS_OFF | RADEON_SCREEN_BLANKING);
892b7e1c893Smrg	}
893b7e1c893Smrg	if (radeon_output->active_device & ATOM_DEVICE_TV1_SUPPORT) {
894b7e1c893Smrg	    if (mode == DPMSModeOn)
895b7e1c893Smrg		save->bios_6_scratch |= RADEON_TV_DPMS_ON;
896b7e1c893Smrg	    else
897209ff23fSmrg		save->bios_6_scratch &= ~RADEON_TV_DPMS_ON;
898b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_CRT1_SUPPORT) {
899b7e1c893Smrg	    if (mode == DPMSModeOn)
900b7e1c893Smrg		save->bios_6_scratch |= RADEON_CRT_DPMS_ON;
901b7e1c893Smrg	    else
902209ff23fSmrg		save->bios_6_scratch &= ~RADEON_CRT_DPMS_ON;
903b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_CRT2_SUPPORT) {
904b7e1c893Smrg	    if (mode == DPMSModeOn)
905b7e1c893Smrg		save->bios_6_scratch |= RADEON_CRT_DPMS_ON;
906b7e1c893Smrg	    else
907b7e1c893Smrg		save->bios_6_scratch &= ~RADEON_CRT_DPMS_ON;
908b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_LCD1_SUPPORT) {
909b7e1c893Smrg	    if (mode == DPMSModeOn)
910b7e1c893Smrg		save->bios_6_scratch |= RADEON_LCD_DPMS_ON;
911b7e1c893Smrg	    else
912209ff23fSmrg		save->bios_6_scratch &= ~RADEON_LCD_DPMS_ON;
913b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_DFP1_SUPPORT) {
914b7e1c893Smrg	    if (mode == DPMSModeOn)
915b7e1c893Smrg		save->bios_6_scratch |= RADEON_DFP_DPMS_ON;
916b7e1c893Smrg	    else
917b7e1c893Smrg		save->bios_6_scratch &= ~RADEON_DFP_DPMS_ON;
918b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_DFP2_SUPPORT) {
919b7e1c893Smrg	    if (mode == DPMSModeOn)
920b7e1c893Smrg		save->bios_6_scratch |= RADEON_DFP_DPMS_ON;
921b7e1c893Smrg	    else
922209ff23fSmrg		save->bios_6_scratch &= ~RADEON_DFP_DPMS_ON;
923209ff23fSmrg	}
924209ff23fSmrg	OUTREG(RADEON_BIOS_6_SCRATCH, save->bios_6_scratch);
925209ff23fSmrg    }
926209ff23fSmrg}
927209ff23fSmrg
928209ff23fSmrgstatic void
929209ff23fSmrgradeon_bios_output_crtc(xf86OutputPtr output)
930209ff23fSmrg{
931209ff23fSmrg    ScrnInfoPtr	    pScrn = output->scrn;
932209ff23fSmrg    RADEONInfoPtr info = RADEONPTR(pScrn);
933209ff23fSmrg    RADEONOutputPrivatePtr radeon_output = output->driver_private;
934209ff23fSmrg    unsigned char *RADEONMMIO = info->MMIO;
935209ff23fSmrg    RADEONSavePtr save = info->ModeReg;
936209ff23fSmrg    xf86CrtcPtr crtc = output->crtc;
937209ff23fSmrg    RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
938209ff23fSmrg
939ad43ddacSmrg    /* no need to update crtc routing scratch regs on DCE4 */
940ad43ddacSmrg    if (IS_DCE4_VARIANT)
941ad43ddacSmrg	return;
942ad43ddacSmrg
943209ff23fSmrg    if (info->IsAtomBios) {
944b7e1c893Smrg	if (radeon_output->active_device & ATOM_DEVICE_TV1_SUPPORT) {
945b7e1c893Smrg	    save->bios_3_scratch &= ~ATOM_S3_TV1_CRTC_ACTIVE;
946b7e1c893Smrg	    save->bios_3_scratch |= (radeon_crtc->crtc_id << 18);
947b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_CV_SUPPORT) {
948b7e1c893Smrg	    save->bios_3_scratch &= ~ATOM_S3_CV_CRTC_ACTIVE;
949b7e1c893Smrg	    save->bios_3_scratch |= (radeon_crtc->crtc_id << 24);
950b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_CRT1_SUPPORT) {
951b7e1c893Smrg	    save->bios_3_scratch &= ~ATOM_S3_CRT1_CRTC_ACTIVE;
952b7e1c893Smrg	    save->bios_3_scratch |= (radeon_crtc->crtc_id << 16);
953b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_CRT2_SUPPORT) {
954b7e1c893Smrg	    save->bios_3_scratch &= ~ATOM_S3_CRT2_CRTC_ACTIVE;
955b7e1c893Smrg	    save->bios_3_scratch |= (radeon_crtc->crtc_id << 20);
956b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_LCD1_SUPPORT) {
957b7e1c893Smrg	    save->bios_3_scratch &= ~ATOM_S3_LCD1_CRTC_ACTIVE;
958b7e1c893Smrg	    save->bios_3_scratch |= (radeon_crtc->crtc_id << 17);
959b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_DFP1_SUPPORT) {
960b7e1c893Smrg	    save->bios_3_scratch &= ~ATOM_S3_DFP1_CRTC_ACTIVE;
961b7e1c893Smrg	    save->bios_3_scratch |= (radeon_crtc->crtc_id << 19);
962b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_DFP2_SUPPORT) {
963b7e1c893Smrg	    save->bios_3_scratch &= ~ATOM_S3_DFP2_CRTC_ACTIVE;
964b7e1c893Smrg	    save->bios_3_scratch |= (radeon_crtc->crtc_id << 23);
965b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_DFP3_SUPPORT) {
966b7e1c893Smrg	    save->bios_3_scratch &= ~ATOM_S3_DFP3_CRTC_ACTIVE;
967b7e1c893Smrg	    save->bios_3_scratch |= (radeon_crtc->crtc_id << 25);
968209ff23fSmrg	}
969209ff23fSmrg	if (info->ChipFamily >= CHIP_FAMILY_R600)
970209ff23fSmrg	    OUTREG(R600_BIOS_3_SCRATCH, save->bios_3_scratch);
971209ff23fSmrg	else
972209ff23fSmrg	    OUTREG(RADEON_BIOS_3_SCRATCH, save->bios_3_scratch);
973209ff23fSmrg    } else {
974b7e1c893Smrg	if (radeon_output->active_device & ATOM_DEVICE_TV1_SUPPORT) {
975209ff23fSmrg	    save->bios_5_scratch &= ~RADEON_TV1_CRTC_MASK;
976209ff23fSmrg	    save->bios_5_scratch |= (radeon_crtc->crtc_id << RADEON_TV1_CRTC_SHIFT);
977b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_CRT1_SUPPORT) {
978b7e1c893Smrg	    save->bios_5_scratch &= ~RADEON_CRT1_CRTC_MASK;
979b7e1c893Smrg	    save->bios_5_scratch |= (radeon_crtc->crtc_id << RADEON_CRT1_CRTC_SHIFT);
980b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_CRT2_SUPPORT) {
981b7e1c893Smrg	    save->bios_5_scratch &= ~RADEON_CRT2_CRTC_MASK;
982b7e1c893Smrg	    save->bios_5_scratch |= (radeon_crtc->crtc_id << RADEON_CRT2_CRTC_SHIFT);
983b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_LCD1_SUPPORT) {
984209ff23fSmrg	    save->bios_5_scratch &= ~RADEON_LCD1_CRTC_MASK;
985209ff23fSmrg	    save->bios_5_scratch |= (radeon_crtc->crtc_id << RADEON_LCD1_CRTC_SHIFT);
986b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_DFP1_SUPPORT) {
987b7e1c893Smrg	    save->bios_5_scratch &= ~RADEON_DFP1_CRTC_MASK;
988b7e1c893Smrg	    save->bios_5_scratch |= (radeon_crtc->crtc_id << RADEON_DFP1_CRTC_SHIFT);
989b7e1c893Smrg	} else if (radeon_output->active_device & ATOM_DEVICE_DFP2_SUPPORT) {
990b7e1c893Smrg	    save->bios_5_scratch &= ~RADEON_DFP2_CRTC_MASK;
991b7e1c893Smrg	    save->bios_5_scratch |= (radeon_crtc->crtc_id << RADEON_DFP2_CRTC_SHIFT);
992209ff23fSmrg	}
993209ff23fSmrg	OUTREG(RADEON_BIOS_5_SCRATCH, save->bios_5_scratch);
994209ff23fSmrg    }
995209ff23fSmrg}
996209ff23fSmrg
997209ff23fSmrgstatic void
998209ff23fSmrgradeon_bios_output_connected(xf86OutputPtr output, Bool connected)
999209ff23fSmrg{
1000209ff23fSmrg    ScrnInfoPtr	    pScrn = output->scrn;
1001209ff23fSmrg    RADEONInfoPtr info = RADEONPTR(pScrn);
1002209ff23fSmrg    RADEONOutputPrivatePtr radeon_output = output->driver_private;
1003209ff23fSmrg    unsigned char *RADEONMMIO = info->MMIO;
1004209ff23fSmrg    RADEONSavePtr save = info->ModeReg;
1005209ff23fSmrg
1006209ff23fSmrg    if (info->IsAtomBios) {
1007b7e1c893Smrg	switch (radeon_output->active_device) {
1008b7e1c893Smrg	case ATOM_DEVICE_TV1_SUPPORT:
1009b7e1c893Smrg	    if (connected)
1010b7e1c893Smrg		save->bios_3_scratch |= ATOM_S3_TV1_ACTIVE;
1011b7e1c893Smrg	    else {
1012b7e1c893Smrg		save->bios_0_scratch &= ~ATOM_S0_TV1_MASK;
1013b7e1c893Smrg		save->bios_3_scratch &= ~ATOM_S3_TV1_ACTIVE;
1014209ff23fSmrg	    }
1015b7e1c893Smrg	    break;
1016b7e1c893Smrg	case ATOM_DEVICE_CV_SUPPORT:
1017b7e1c893Smrg	    if (connected)
1018b7e1c893Smrg		save->bios_3_scratch |= ATOM_S3_CV_ACTIVE;
1019b7e1c893Smrg	    else {
1020b7e1c893Smrg		save->bios_0_scratch &= ~ATOM_S0_CV_MASK;
1021b7e1c893Smrg		save->bios_3_scratch &= ~ATOM_S3_CV_ACTIVE;
1022b7e1c893Smrg	    }
1023b7e1c893Smrg	    break;
1024b7e1c893Smrg	case ATOM_DEVICE_LCD1_SUPPORT:
1025b7e1c893Smrg	    if (connected) {
1026b7e1c893Smrg		save->bios_0_scratch |= ATOM_S0_LCD1;
1027b7e1c893Smrg		save->bios_3_scratch |= ATOM_S3_LCD1_ACTIVE;
1028b7e1c893Smrg	    } else {
1029b7e1c893Smrg		save->bios_0_scratch &= ~ATOM_S0_LCD1;
1030b7e1c893Smrg		save->bios_3_scratch &= ~ATOM_S3_LCD1_ACTIVE;
1031b7e1c893Smrg	    }
1032b7e1c893Smrg	    break;
1033b7e1c893Smrg	case ATOM_DEVICE_CRT1_SUPPORT:
1034b7e1c893Smrg	    if (connected) {
1035b7e1c893Smrg		save->bios_0_scratch |= ATOM_S0_CRT1_COLOR;
1036b7e1c893Smrg		save->bios_3_scratch |= ATOM_S3_CRT1_ACTIVE;
1037b7e1c893Smrg	    } else {
1038b7e1c893Smrg		save->bios_0_scratch &= ~ATOM_S0_CRT1_MASK;
1039b7e1c893Smrg		save->bios_3_scratch &= ~ATOM_S3_CRT1_ACTIVE;
1040b7e1c893Smrg	    }
1041b7e1c893Smrg	    break;
1042b7e1c893Smrg	case ATOM_DEVICE_CRT2_SUPPORT:
1043b7e1c893Smrg	    if (connected) {
1044b7e1c893Smrg		save->bios_0_scratch |= ATOM_S0_CRT2_COLOR;
1045b7e1c893Smrg		save->bios_3_scratch |= ATOM_S3_CRT2_ACTIVE;
1046b7e1c893Smrg	    } else {
1047b7e1c893Smrg		save->bios_0_scratch &= ~ATOM_S0_CRT2_MASK;
1048b7e1c893Smrg		save->bios_3_scratch &= ~ATOM_S3_CRT2_ACTIVE;
1049b7e1c893Smrg	    }
1050b7e1c893Smrg	    break;
1051b7e1c893Smrg	case ATOM_DEVICE_DFP1_SUPPORT:
1052b7e1c893Smrg	    if (connected) {
1053b7e1c893Smrg		save->bios_0_scratch |= ATOM_S0_DFP1;
1054b7e1c893Smrg		save->bios_3_scratch |= ATOM_S3_DFP1_ACTIVE;
1055b7e1c893Smrg	    } else {
1056b7e1c893Smrg		save->bios_0_scratch &= ~ATOM_S0_DFP1;
1057b7e1c893Smrg		save->bios_3_scratch &= ~ATOM_S3_DFP1_ACTIVE;
1058209ff23fSmrg	    }
1059b7e1c893Smrg	    break;
1060b7e1c893Smrg	case ATOM_DEVICE_DFP2_SUPPORT:
1061b7e1c893Smrg	    if (connected) {
1062b7e1c893Smrg		save->bios_0_scratch |= ATOM_S0_DFP2;
1063b7e1c893Smrg		save->bios_3_scratch |= ATOM_S3_DFP2_ACTIVE;
1064b7e1c893Smrg	    } else {
1065b7e1c893Smrg		save->bios_0_scratch &= ~ATOM_S0_DFP2;
1066b7e1c893Smrg		save->bios_3_scratch &= ~ATOM_S3_DFP2_ACTIVE;
1067209ff23fSmrg	    }
1068b7e1c893Smrg	    break;
1069b7e1c893Smrg	case ATOM_DEVICE_DFP3_SUPPORT:
1070b7e1c893Smrg	    if (connected) {
1071b7e1c893Smrg		save->bios_0_scratch |= ATOM_S0_DFP3;
1072b7e1c893Smrg		save->bios_3_scratch |= ATOM_S3_DFP3_ACTIVE;
1073b7e1c893Smrg	    } else {
1074b7e1c893Smrg		save->bios_0_scratch &= ~ATOM_S0_DFP3;
1075b7e1c893Smrg		save->bios_3_scratch &= ~ATOM_S3_DFP3_ACTIVE;
1076209ff23fSmrg	    }
1077b7e1c893Smrg	    break;
1078b7e1c893Smrg	case ATOM_DEVICE_DFP4_SUPPORT:
1079b7e1c893Smrg	    if (connected) {
1080b7e1c893Smrg		save->bios_0_scratch |= ATOM_S0_DFP4;
1081b7e1c893Smrg		save->bios_3_scratch |= ATOM_S3_DFP4_ACTIVE;
1082b7e1c893Smrg	    } else {
1083b7e1c893Smrg		save->bios_0_scratch &= ~ATOM_S0_DFP4;
1084b7e1c893Smrg		save->bios_3_scratch &= ~ATOM_S3_DFP4_ACTIVE;
1085209ff23fSmrg	    }
1086b7e1c893Smrg	    break;
1087b7e1c893Smrg	case ATOM_DEVICE_DFP5_SUPPORT:
1088b7e1c893Smrg	    if (connected) {
1089b7e1c893Smrg		save->bios_0_scratch |= ATOM_S0_DFP5;
1090b7e1c893Smrg		save->bios_3_scratch |= ATOM_S3_DFP5_ACTIVE;
1091b7e1c893Smrg	    } else {
1092b7e1c893Smrg		save->bios_0_scratch &= ~ATOM_S0_DFP5;
1093b7e1c893Smrg		save->bios_3_scratch &= ~ATOM_S3_DFP5_ACTIVE;
1094209ff23fSmrg	    }
1095b7e1c893Smrg	    break;
1096209ff23fSmrg	}
1097b7e1c893Smrg	if (info->ChipFamily >= CHIP_FAMILY_R600) {
1098209ff23fSmrg	    OUTREG(R600_BIOS_0_SCRATCH, save->bios_0_scratch);
1099b7e1c893Smrg	    OUTREG(R600_BIOS_3_SCRATCH, save->bios_3_scratch);
1100b7e1c893Smrg	} else {
1101209ff23fSmrg	    OUTREG(RADEON_BIOS_0_SCRATCH, save->bios_0_scratch);
1102b7e1c893Smrg	    OUTREG(RADEON_BIOS_3_SCRATCH, save->bios_3_scratch);
1103b7e1c893Smrg	}
1104209ff23fSmrg    } else {
1105b7e1c893Smrg	switch (radeon_output->active_device) {
1106b7e1c893Smrg	case ATOM_DEVICE_TV1_SUPPORT:
1107b7e1c893Smrg	    if (connected) {
1108b7e1c893Smrg		if (radeon_output->MonType == MT_STV)
1109b7e1c893Smrg		    save->bios_4_scratch |= RADEON_TV1_ATTACHED_SVIDEO;
1110b7e1c893Smrg		else if (radeon_output->MonType == MT_CTV)
1111b7e1c893Smrg		    save->bios_4_scratch |= RADEON_TV1_ATTACHED_COMP;
1112b7e1c893Smrg		save->bios_5_scratch |= RADEON_TV1_ON;
1113b7e1c893Smrg	    } else {
1114b7e1c893Smrg		save->bios_4_scratch &= ~RADEON_TV1_ATTACHED_MASK;
1115b7e1c893Smrg		save->bios_5_scratch &= ~RADEON_TV1_ON;
1116b7e1c893Smrg	    }
1117b7e1c893Smrg	    break;
1118b7e1c893Smrg	case ATOM_DEVICE_LCD1_SUPPORT:
1119b7e1c893Smrg	    if (connected) {
1120209ff23fSmrg		save->bios_4_scratch |= RADEON_LCD1_ATTACHED;
1121b7e1c893Smrg		save->bios_5_scratch |= RADEON_LCD1_ON;
1122b7e1c893Smrg	    } else {
1123b7e1c893Smrg		save->bios_4_scratch &= ~RADEON_LCD1_ATTACHED;
1124b7e1c893Smrg		save->bios_5_scratch &= ~RADEON_LCD1_ON;
1125209ff23fSmrg	    }
1126b7e1c893Smrg	    break;
1127b7e1c893Smrg	case ATOM_DEVICE_CRT1_SUPPORT:
1128b7e1c893Smrg	    if (connected) {
1129b7e1c893Smrg		save->bios_4_scratch |= RADEON_CRT1_ATTACHED_COLOR;
1130b7e1c893Smrg		save->bios_5_scratch |= RADEON_CRT1_ON;
1131b7e1c893Smrg	    } else {
1132209ff23fSmrg		save->bios_4_scratch &= ~RADEON_CRT1_ATTACHED_MASK;
1133b7e1c893Smrg		save->bios_5_scratch &= ~RADEON_CRT1_ON;
1134b7e1c893Smrg	    }
1135b7e1c893Smrg	    break;
1136b7e1c893Smrg	case ATOM_DEVICE_CRT2_SUPPORT:
1137b7e1c893Smrg	    if (connected) {
1138b7e1c893Smrg		save->bios_4_scratch |= RADEON_CRT2_ATTACHED_COLOR;
1139b7e1c893Smrg		save->bios_5_scratch |= RADEON_CRT2_ON;
1140b7e1c893Smrg	    } else {
1141b7e1c893Smrg		save->bios_4_scratch &= ~RADEON_CRT2_ATTACHED_MASK;
1142b7e1c893Smrg		save->bios_5_scratch &= ~RADEON_CRT2_ON;
1143b7e1c893Smrg	    }
1144b7e1c893Smrg	    break;
1145b7e1c893Smrg	case ATOM_DEVICE_DFP1_SUPPORT:
1146b7e1c893Smrg	    if (connected) {
1147b7e1c893Smrg		save->bios_4_scratch |= RADEON_DFP1_ATTACHED;
1148b7e1c893Smrg		save->bios_5_scratch |= RADEON_DFP1_ON;
1149b7e1c893Smrg	    } else {
1150209ff23fSmrg		save->bios_4_scratch &= ~RADEON_DFP1_ATTACHED;
1151b7e1c893Smrg		save->bios_5_scratch &= ~RADEON_DFP1_ON;
1152b7e1c893Smrg	    }
1153b7e1c893Smrg	    break;
1154b7e1c893Smrg	case ATOM_DEVICE_DFP2_SUPPORT:
1155b7e1c893Smrg	    if (connected) {
1156b7e1c893Smrg		save->bios_4_scratch |= RADEON_DFP2_ATTACHED;
1157b7e1c893Smrg		save->bios_5_scratch |= RADEON_DFP2_ON;
1158b7e1c893Smrg	    } else {
1159209ff23fSmrg		save->bios_4_scratch &= ~RADEON_DFP2_ATTACHED;
1160b7e1c893Smrg		save->bios_5_scratch &= ~RADEON_DFP2_ON;
1161b7e1c893Smrg	    }
1162b7e1c893Smrg	    break;
1163209ff23fSmrg	}
1164209ff23fSmrg	OUTREG(RADEON_BIOS_4_SCRATCH, save->bios_4_scratch);
1165b7e1c893Smrg	OUTREG(RADEON_BIOS_5_SCRATCH, save->bios_5_scratch);
1166209ff23fSmrg    }
1167209ff23fSmrg
1168209ff23fSmrg}
1169209ff23fSmrg
1170209ff23fSmrgstatic xf86OutputStatus
1171209ff23fSmrgradeon_detect(xf86OutputPtr output)
1172209ff23fSmrg{
1173209ff23fSmrg    ScrnInfoPtr	    pScrn = output->scrn;
1174209ff23fSmrg    RADEONInfoPtr info = RADEONPTR(pScrn);
1175209ff23fSmrg    RADEONOutputPrivatePtr radeon_output = output->driver_private;
1176209ff23fSmrg    Bool connected = TRUE;
1177209ff23fSmrg
1178209ff23fSmrg    radeon_output->MonType = MT_UNKNOWN;
1179209ff23fSmrg    radeon_bios_output_connected(output, FALSE);
1180b7e1c893Smrg    radeon_output->MonType = radeon_ddc_connected(output);
1181b7e1c893Smrg    if (!radeon_output->MonType) {
1182b7e1c893Smrg	if (radeon_output->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
1183b7e1c893Smrg	    if (xf86ReturnOptValBool(info->Options, OPTION_IGNORE_LID_STATUS, TRUE))
1184b7e1c893Smrg		radeon_output->MonType = MT_LCD;
1185b7e1c893Smrg	    else
1186b7e1c893Smrg#if defined(__powerpc__)
1187b7e1c893Smrg		radeon_output->MonType = MT_LCD;
1188b7e1c893Smrg#else
1189b7e1c893Smrg	        radeon_output->MonType = RADEONDetectLidStatus(pScrn);
1190b7e1c893Smrg#endif
1191b7e1c893Smrg	} else {
1192b7e1c893Smrg	    if (info->IsAtomBios)
1193b7e1c893Smrg		radeon_output->MonType = atombios_dac_detect(output);
1194b7e1c893Smrg	    else
1195b7e1c893Smrg		radeon_output->MonType = legacy_dac_detect(output);
1196b7e1c893Smrg	}
1197b7e1c893Smrg    }
1198b7e1c893Smrg
1199b7e1c893Smrg    // if size is zero panel probably broken or not connected
1200b7e1c893Smrg    if (radeon_output->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
1201b7e1c893Smrg	radeon_encoder_ptr radeon_encoder = info->encoders[ATOM_DEVICE_LCD1_INDEX];
1202b7e1c893Smrg	if (radeon_encoder) {
1203b7e1c893Smrg	    radeon_lvds_ptr lvds = (radeon_lvds_ptr)radeon_encoder->dev_priv;
1204b7e1c893Smrg	    if (lvds) {
1205b7e1c893Smrg		if ((lvds->native_mode.PanelXRes == 0) || (lvds->native_mode.PanelYRes == 0))
1206b7e1c893Smrg		    radeon_output->MonType = MT_NONE;
1207b7e1c893Smrg	    }
1208b7e1c893Smrg	}
1209b7e1c893Smrg    }
1210b7e1c893Smrg
1211b7e1c893Smrg
1212c503f109Smrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1213c503f109Smrg	       "Output: %s, Detected Monitor Type: %d\n", output->name, radeon_output->MonType);
1214b7e1c893Smrg    if (output->MonInfo) {
1215b7e1c893Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "EDID data from the display on output: %s ----------------------\n",
1216b7e1c893Smrg		   output->name);
1217b7e1c893Smrg	xf86PrintEDID( output->MonInfo );
1218b7e1c893Smrg    }
1219209ff23fSmrg
1220209ff23fSmrg    /* nothing connected, light up some defaults so the server comes up */
1221209ff23fSmrg    if (radeon_output->MonType == MT_NONE &&
1222209ff23fSmrg	info->first_load_no_devices) {
1223209ff23fSmrg	if (info->IsMobility) {
1224b7e1c893Smrg	    if (radeon_output->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
1225209ff23fSmrg		radeon_output->MonType = MT_LCD;
1226209ff23fSmrg		info->first_load_no_devices = FALSE;
1227b7e1c893Smrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Using LCD default\n");
1228209ff23fSmrg	    }
1229209ff23fSmrg	} else {
1230b7e1c893Smrg	    if (radeon_output->devices & (ATOM_DEVICE_CRT_SUPPORT)) {
1231209ff23fSmrg		radeon_output->MonType = MT_CRT;
1232209ff23fSmrg		info->first_load_no_devices = FALSE;
1233b7e1c893Smrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Using CRT default\n");
1234b7e1c893Smrg	    } else if (radeon_output->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
1235209ff23fSmrg		radeon_output->MonType = MT_DFP;
1236209ff23fSmrg		info->first_load_no_devices = FALSE;
1237b7e1c893Smrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Using DFP default\n");
1238209ff23fSmrg	    }
1239209ff23fSmrg	}
1240209ff23fSmrg    }
1241209ff23fSmrg
1242209ff23fSmrg    radeon_bios_output_connected(output, TRUE);
1243209ff23fSmrg
1244209ff23fSmrg    /* set montype so users can force outputs on even if detection fails */
1245209ff23fSmrg    if (radeon_output->MonType == MT_NONE) {
1246209ff23fSmrg	connected = FALSE;
1247b7e1c893Smrg	switch (radeon_output->ConnectorType) {
1248b7e1c893Smrg	case CONNECTOR_LVDS:
1249209ff23fSmrg	    radeon_output->MonType = MT_LCD;
1250b7e1c893Smrg	    break;
1251b7e1c893Smrg	case CONNECTOR_DVI_D:
1252b7e1c893Smrg	case CONNECTOR_HDMI_TYPE_A:
1253b7e1c893Smrg	case CONNECTOR_HDMI_TYPE_B:
1254209ff23fSmrg	    radeon_output->MonType = MT_DFP;
1255b7e1c893Smrg	    break;
1256b7e1c893Smrg	case CONNECTOR_VGA:
1257b7e1c893Smrg	case CONNECTOR_DVI_A:
1258b7e1c893Smrg	default:
1259209ff23fSmrg	    radeon_output->MonType = MT_CRT;
1260b7e1c893Smrg	    break;
1261b7e1c893Smrg	case CONNECTOR_DVI_I:
1262209ff23fSmrg	    if (radeon_output->DVIType == DVI_ANALOG)
1263209ff23fSmrg		radeon_output->MonType = MT_CRT;
1264209ff23fSmrg	    else if (radeon_output->DVIType == DVI_DIGITAL)
1265209ff23fSmrg		radeon_output->MonType = MT_DFP;
1266b7e1c893Smrg	    break;
1267b7e1c893Smrg	case CONNECTOR_STV:
1268b7e1c893Smrg            radeon_output->MonType = MT_STV;
1269b7e1c893Smrg	    break;
1270b7e1c893Smrg	case CONNECTOR_CTV:
1271b7e1c893Smrg            radeon_output->MonType = MT_CTV;
1272b7e1c893Smrg	    break;
1273b7e1c893Smrg	case CONNECTOR_DIN:
1274b7e1c893Smrg            radeon_output->MonType = MT_CV;
1275b7e1c893Smrg	    break;
1276b7e1c893Smrg	case CONNECTOR_DISPLAY_PORT:
1277ad43ddacSmrg	case CONNECTOR_EDP:
1278b7e1c893Smrg	    radeon_output->MonType = MT_DP;
1279b7e1c893Smrg	    break;
1280209ff23fSmrg	}
1281209ff23fSmrg    }
1282209ff23fSmrg
1283b7e1c893Smrg    radeon_set_active_device(output);
1284209ff23fSmrg
1285b7e1c893Smrg    if (radeon_output->active_device & (ATOM_DEVICE_LCD_SUPPORT | ATOM_DEVICE_DFP_SUPPORT))
1286b7e1c893Smrg	output->subpixel_order = SubPixelHorizontalRGB;
1287b7e1c893Smrg    else
1288b7e1c893Smrg	output->subpixel_order = SubPixelNone;
1289209ff23fSmrg
1290b7e1c893Smrg    if (connected)
1291b7e1c893Smrg	return XF86OutputStatusConnected;
1292b7e1c893Smrg    else
1293b7e1c893Smrg	return XF86OutputStatusDisconnected;
1294209ff23fSmrg}
1295209ff23fSmrg
1296209ff23fSmrgstatic DisplayModePtr
1297209ff23fSmrgradeon_get_modes(xf86OutputPtr output)
1298209ff23fSmrg{
1299209ff23fSmrg  DisplayModePtr modes;
1300209ff23fSmrg  modes = RADEONProbeOutputModes(output);
1301209ff23fSmrg  return modes;
1302209ff23fSmrg}
1303209ff23fSmrg
1304209ff23fSmrgstatic void
1305209ff23fSmrgradeon_destroy (xf86OutputPtr output)
1306209ff23fSmrg{
1307209ff23fSmrg    if (output->driver_private)
13082f39173dSmrg        free(output->driver_private);
1309209ff23fSmrg}
1310209ff23fSmrg
1311209ff23fSmrgstatic void
1312209ff23fSmrgradeon_set_backlight_level(xf86OutputPtr output, int level)
1313209ff23fSmrg{
1314209ff23fSmrg#if 0
1315209ff23fSmrg    ScrnInfoPtr pScrn = output->scrn;
1316209ff23fSmrg    RADEONInfoPtr info = RADEONPTR(pScrn);
1317209ff23fSmrg    unsigned char * RADEONMMIO = info->MMIO;
1318209ff23fSmrg    uint32_t lvds_gen_cntl;
1319209ff23fSmrg
1320209ff23fSmrg    lvds_gen_cntl = INREG(RADEON_LVDS_GEN_CNTL);
1321209ff23fSmrg    lvds_gen_cntl |= RADEON_LVDS_BL_MOD_EN;
1322209ff23fSmrg    lvds_gen_cntl &= ~RADEON_LVDS_BL_MOD_LEVEL_MASK;
1323209ff23fSmrg    lvds_gen_cntl |= (level << RADEON_LVDS_BL_MOD_LEVEL_SHIFT) & RADEON_LVDS_BL_MOD_LEVEL_MASK;
1324209ff23fSmrg    //usleep (radeon_output->PanelPwrDly * 1000);
1325209ff23fSmrg    OUTREG(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl);
1326209ff23fSmrg    lvds_gen_cntl &= ~RADEON_LVDS_BL_MOD_EN;
1327209ff23fSmrg    //usleep (radeon_output->PanelPwrDly * 1000);
1328209ff23fSmrg    OUTREG(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl);
1329209ff23fSmrg#endif
1330209ff23fSmrg}
1331209ff23fSmrg
1332209ff23fSmrgstatic Atom backlight_atom;
1333209ff23fSmrgstatic Atom tmds_pll_atom;
1334209ff23fSmrgstatic Atom rmx_atom;
1335209ff23fSmrgstatic Atom monitor_type_atom;
1336209ff23fSmrgstatic Atom load_detection_atom;
1337209ff23fSmrgstatic Atom coherent_mode_atom;
1338209ff23fSmrgstatic Atom tv_hsize_atom;
1339209ff23fSmrgstatic Atom tv_hpos_atom;
1340209ff23fSmrgstatic Atom tv_vpos_atom;
1341209ff23fSmrgstatic Atom tv_std_atom;
1342209ff23fSmrg#define RADEON_MAX_BACKLIGHT_LEVEL 255
1343209ff23fSmrg
1344209ff23fSmrgstatic void
1345209ff23fSmrgradeon_create_resources(xf86OutputPtr output)
1346209ff23fSmrg{
1347209ff23fSmrg    ScrnInfoPtr pScrn = output->scrn;
1348209ff23fSmrg    RADEONInfoPtr info = RADEONPTR(pScrn);
1349209ff23fSmrg    RADEONOutputPrivatePtr radeon_output = output->driver_private;
1350209ff23fSmrg    INT32 range[2];
1351209ff23fSmrg    int data, err;
1352209ff23fSmrg    const char *s;
1353209ff23fSmrg
1354b7e1c893Smrg#if 0
1355209ff23fSmrg    /* backlight control */
1356209ff23fSmrg    if (radeon_output->type == OUTPUT_LVDS) {
1357209ff23fSmrg	backlight_atom = MAKE_ATOM("backlight");
1358209ff23fSmrg
1359209ff23fSmrg	range[0] = 0;
1360209ff23fSmrg	range[1] = RADEON_MAX_BACKLIGHT_LEVEL;
1361209ff23fSmrg	err = RRConfigureOutputProperty(output->randr_output, backlight_atom,
1362209ff23fSmrg					FALSE, TRUE, FALSE, 2, range);
1363209ff23fSmrg	if (err != 0) {
1364209ff23fSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1365209ff23fSmrg		       "RRConfigureOutputProperty error, %d\n", err);
1366209ff23fSmrg	}
1367209ff23fSmrg	/* Set the current value of the backlight property */
1368209ff23fSmrg	//data = (info->SavedReg->lvds_gen_cntl & RADEON_LVDS_BL_MOD_LEVEL_MASK) >> RADEON_LVDS_BL_MOD_LEVEL_SHIFT;
1369209ff23fSmrg	data = RADEON_MAX_BACKLIGHT_LEVEL;
1370209ff23fSmrg	err = RRChangeOutputProperty(output->randr_output, backlight_atom,
1371209ff23fSmrg				     XA_INTEGER, 32, PropModeReplace, 1, &data,
1372209ff23fSmrg				     FALSE, TRUE);
1373209ff23fSmrg	if (err != 0) {
1374209ff23fSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1375209ff23fSmrg		       "RRChangeOutputProperty error, %d\n", err);
1376209ff23fSmrg	}
1377209ff23fSmrg    }
1378b7e1c893Smrg#endif
1379209ff23fSmrg
1380b7e1c893Smrg    if (radeon_output->devices & (ATOM_DEVICE_CRT_SUPPORT | ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) {
1381209ff23fSmrg	load_detection_atom = MAKE_ATOM("load_detection");
1382209ff23fSmrg
1383209ff23fSmrg	range[0] = 0; /* off */
1384209ff23fSmrg	range[1] = 1; /* on */
1385209ff23fSmrg	err = RRConfigureOutputProperty(output->randr_output, load_detection_atom,
1386209ff23fSmrg					FALSE, TRUE, FALSE, 2, range);
1387209ff23fSmrg	if (err != 0) {
1388209ff23fSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1389209ff23fSmrg		       "RRConfigureOutputProperty error, %d\n", err);
1390209ff23fSmrg	}
1391209ff23fSmrg
1392209ff23fSmrg	if (radeon_output->load_detection)
1393b7e1c893Smrg	    data = 1;
1394209ff23fSmrg	else
1395b7e1c893Smrg	    data = 0;
1396209ff23fSmrg
1397209ff23fSmrg	err = RRChangeOutputProperty(output->randr_output, load_detection_atom,
1398209ff23fSmrg				     XA_INTEGER, 32, PropModeReplace, 1, &data,
1399209ff23fSmrg				     FALSE, TRUE);
1400209ff23fSmrg	if (err != 0) {
1401209ff23fSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1402209ff23fSmrg		       "RRChangeOutputProperty error, %d\n", err);
1403209ff23fSmrg	}
1404209ff23fSmrg    }
1405209ff23fSmrg
1406b7e1c893Smrg    if (IS_AVIVO_VARIANT && (radeon_output->devices & (ATOM_DEVICE_DFP_SUPPORT))) {
1407209ff23fSmrg	coherent_mode_atom = MAKE_ATOM("coherent_mode");
1408209ff23fSmrg
1409209ff23fSmrg	range[0] = 0; /* off */
1410209ff23fSmrg	range[1] = 1; /* on */
1411209ff23fSmrg	err = RRConfigureOutputProperty(output->randr_output, coherent_mode_atom,
1412209ff23fSmrg					FALSE, TRUE, FALSE, 2, range);
1413209ff23fSmrg	if (err != 0) {
1414209ff23fSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1415209ff23fSmrg		       "RRConfigureOutputProperty error, %d\n", err);
1416209ff23fSmrg	}
1417209ff23fSmrg
1418b7e1c893Smrg	data = 1; /* coherent mode on by default */
1419209ff23fSmrg
1420209ff23fSmrg	err = RRChangeOutputProperty(output->randr_output, coherent_mode_atom,
1421209ff23fSmrg				     XA_INTEGER, 32, PropModeReplace, 1, &data,
1422209ff23fSmrg				     FALSE, TRUE);
1423209ff23fSmrg	if (err != 0) {
1424209ff23fSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1425209ff23fSmrg		       "RRChangeOutputProperty error, %d\n", err);
1426209ff23fSmrg	}
1427209ff23fSmrg    }
1428209ff23fSmrg
1429c503f109Smrg    if ((!IS_AVIVO_VARIANT) && (radeon_output->devices & (ATOM_DEVICE_DFP1_SUPPORT))) {
1430209ff23fSmrg	tmds_pll_atom = MAKE_ATOM("tmds_pll");
1431209ff23fSmrg
1432209ff23fSmrg	err = RRConfigureOutputProperty(output->randr_output, tmds_pll_atom,
1433209ff23fSmrg					FALSE, FALSE, FALSE, 0, NULL);
1434209ff23fSmrg	if (err != 0) {
1435209ff23fSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1436209ff23fSmrg		       "RRConfigureOutputProperty error, %d\n", err);
1437209ff23fSmrg	}
1438209ff23fSmrg	/* Set the current value of the property */
1439209ff23fSmrg#if defined(__powerpc__)
1440209ff23fSmrg	s = "driver";
1441209ff23fSmrg#else
1442209ff23fSmrg	s = "bios";
1443209ff23fSmrg#endif
1444209ff23fSmrg	if (xf86ReturnOptValBool(info->Options, OPTION_DEFAULT_TMDS_PLL, FALSE)) {
1445209ff23fSmrg	    s = "driver";
1446209ff23fSmrg	}
1447209ff23fSmrg
1448209ff23fSmrg	err = RRChangeOutputProperty(output->randr_output, tmds_pll_atom,
1449209ff23fSmrg				     XA_STRING, 8, PropModeReplace, strlen(s), (pointer)s,
1450209ff23fSmrg				     FALSE, FALSE);
1451209ff23fSmrg	if (err != 0) {
1452209ff23fSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1453209ff23fSmrg		       "RRChangeOutputProperty error, %d\n", err);
1454209ff23fSmrg	}
1455209ff23fSmrg
1456209ff23fSmrg    }
1457209ff23fSmrg
1458209ff23fSmrg    /* RMX control - fullscreen, centered, keep ratio, off */
1459209ff23fSmrg    /* actually more of a crtc property as only crtc1 has rmx */
1460b7e1c893Smrg    if (radeon_output->devices & (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) {
1461209ff23fSmrg	rmx_atom = MAKE_ATOM("scaler");
1462209ff23fSmrg
1463209ff23fSmrg	err = RRConfigureOutputProperty(output->randr_output, rmx_atom,
1464209ff23fSmrg					FALSE, FALSE, FALSE, 0, NULL);
1465209ff23fSmrg	if (err != 0) {
1466209ff23fSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1467209ff23fSmrg		       "RRConfigureOutputProperty error, %d\n", err);
1468209ff23fSmrg	}
1469209ff23fSmrg	/* Set the current value of the property */
1470b7e1c893Smrg	switch (radeon_output->rmx_type) {
1471b7e1c893Smrg	case RMX_OFF:
1472b7e1c893Smrg	default:
1473209ff23fSmrg	    s = "off";
1474b7e1c893Smrg	    break;
1475b7e1c893Smrg	case RMX_FULL:
1476b7e1c893Smrg	    s = "full";
1477b7e1c893Smrg	    break;
1478b7e1c893Smrg	case RMX_CENTER:
1479b7e1c893Smrg	    s = "center";
1480b7e1c893Smrg	    break;
1481b7e1c893Smrg	case RMX_ASPECT:
1482b7e1c893Smrg	    s = "aspect";
1483b7e1c893Smrg	    break;
1484b7e1c893Smrg	}
1485209ff23fSmrg	err = RRChangeOutputProperty(output->randr_output, rmx_atom,
1486209ff23fSmrg				     XA_STRING, 8, PropModeReplace, strlen(s), (pointer)s,
1487209ff23fSmrg				     FALSE, FALSE);
1488209ff23fSmrg	if (err != 0) {
1489209ff23fSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1490209ff23fSmrg		       "RRChangeOutputProperty error, %d\n", err);
1491209ff23fSmrg	}
1492209ff23fSmrg    }
1493209ff23fSmrg
1494209ff23fSmrg    /* force auto/analog/digital for DVI-I ports */
1495b7e1c893Smrg    if ((radeon_output->devices & (ATOM_DEVICE_CRT_SUPPORT)) &&
1496b7e1c893Smrg	(radeon_output->devices & (ATOM_DEVICE_DFP_SUPPORT))){
1497209ff23fSmrg	monitor_type_atom = MAKE_ATOM("dvi_monitor_type");
1498209ff23fSmrg
1499209ff23fSmrg	err = RRConfigureOutputProperty(output->randr_output, monitor_type_atom,
1500209ff23fSmrg					FALSE, FALSE, FALSE, 0, NULL);
1501209ff23fSmrg	if (err != 0) {
1502209ff23fSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1503209ff23fSmrg		       "RRConfigureOutputProperty error, %d\n", err);
1504209ff23fSmrg	}
1505209ff23fSmrg	/* Set the current value of the backlight property */
1506209ff23fSmrg	s = "auto";
1507209ff23fSmrg	err = RRChangeOutputProperty(output->randr_output, monitor_type_atom,
1508209ff23fSmrg				     XA_STRING, 8, PropModeReplace, strlen(s), (pointer)s,
1509209ff23fSmrg				     FALSE, FALSE);
1510209ff23fSmrg	if (err != 0) {
1511209ff23fSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1512209ff23fSmrg		       "RRChangeOutputProperty error, %d\n", err);
1513209ff23fSmrg	}
1514209ff23fSmrg    }
1515209ff23fSmrg
1516b7e1c893Smrg    if (radeon_output->devices & (ATOM_DEVICE_TV_SUPPORT)) {
1517b7e1c893Smrg	radeon_tvout_ptr tvout = &radeon_output->tvout;
1518209ff23fSmrg	if (!IS_AVIVO_VARIANT) {
1519209ff23fSmrg	    tv_hsize_atom = MAKE_ATOM("tv_horizontal_size");
1520209ff23fSmrg
1521209ff23fSmrg	    range[0] = -MAX_H_SIZE;
1522209ff23fSmrg	    range[1] = MAX_H_SIZE;
1523209ff23fSmrg	    err = RRConfigureOutputProperty(output->randr_output, tv_hsize_atom,
1524209ff23fSmrg					    FALSE, TRUE, FALSE, 2, range);
1525209ff23fSmrg	    if (err != 0) {
1526209ff23fSmrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1527209ff23fSmrg			   "RRConfigureOutputProperty error, %d\n", err);
1528209ff23fSmrg	    }
1529209ff23fSmrg	    data = 0;
1530209ff23fSmrg	    err = RRChangeOutputProperty(output->randr_output, tv_hsize_atom,
1531209ff23fSmrg					 XA_INTEGER, 32, PropModeReplace, 1, &data,
1532209ff23fSmrg					 FALSE, TRUE);
1533209ff23fSmrg	    if (err != 0) {
1534209ff23fSmrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1535209ff23fSmrg			   "RRChangeOutputProperty error, %d\n", err);
1536209ff23fSmrg	    }
1537209ff23fSmrg
1538209ff23fSmrg	    tv_hpos_atom = MAKE_ATOM("tv_horizontal_position");
1539209ff23fSmrg
1540209ff23fSmrg	    range[0] = -MAX_H_POSITION;
1541209ff23fSmrg	    range[1] = MAX_H_POSITION;
1542209ff23fSmrg	    err = RRConfigureOutputProperty(output->randr_output, tv_hpos_atom,
1543209ff23fSmrg					    FALSE, TRUE, FALSE, 2, range);
1544209ff23fSmrg	    if (err != 0) {
1545209ff23fSmrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1546209ff23fSmrg			   "RRConfigureOutputProperty error, %d\n", err);
1547209ff23fSmrg	    }
1548209ff23fSmrg	    data = 0;
1549209ff23fSmrg	    err = RRChangeOutputProperty(output->randr_output, tv_hpos_atom,
1550209ff23fSmrg					 XA_INTEGER, 32, PropModeReplace, 1, &data,
1551209ff23fSmrg					 FALSE, TRUE);
1552209ff23fSmrg	    if (err != 0) {
1553209ff23fSmrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1554209ff23fSmrg			   "RRChangeOutputProperty error, %d\n", err);
1555209ff23fSmrg	    }
1556209ff23fSmrg
1557209ff23fSmrg	    tv_vpos_atom = MAKE_ATOM("tv_vertical_position");
1558209ff23fSmrg
1559209ff23fSmrg	    range[0] = -MAX_V_POSITION;
1560209ff23fSmrg	    range[1] = MAX_V_POSITION;
1561209ff23fSmrg	    err = RRConfigureOutputProperty(output->randr_output, tv_vpos_atom,
1562209ff23fSmrg					    FALSE, TRUE, FALSE, 2, range);
1563209ff23fSmrg	    if (err != 0) {
1564209ff23fSmrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1565209ff23fSmrg			   "RRConfigureOutputProperty error, %d\n", err);
1566209ff23fSmrg	    }
1567209ff23fSmrg	    data = 0;
1568209ff23fSmrg	    err = RRChangeOutputProperty(output->randr_output, tv_vpos_atom,
1569209ff23fSmrg					 XA_INTEGER, 32, PropModeReplace, 1, &data,
1570209ff23fSmrg					 FALSE, TRUE);
1571209ff23fSmrg	    if (err != 0) {
1572209ff23fSmrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1573209ff23fSmrg			   "RRChangeOutputProperty error, %d\n", err);
1574209ff23fSmrg	    }
1575209ff23fSmrg	}
1576209ff23fSmrg
1577209ff23fSmrg	tv_std_atom = MAKE_ATOM("tv_standard");
1578209ff23fSmrg
1579209ff23fSmrg	err = RRConfigureOutputProperty(output->randr_output, tv_std_atom,
1580209ff23fSmrg					FALSE, FALSE, FALSE, 0, NULL);
1581209ff23fSmrg	if (err != 0) {
1582209ff23fSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1583209ff23fSmrg		       "RRConfigureOutputProperty error, %d\n", err);
1584209ff23fSmrg	}
1585209ff23fSmrg
1586209ff23fSmrg	/* Set the current value of the property */
1587b7e1c893Smrg	switch (tvout->tvStd) {
1588209ff23fSmrg	case TV_STD_PAL:
1589209ff23fSmrg	    s = "pal";
1590209ff23fSmrg	    break;
1591209ff23fSmrg	case TV_STD_PAL_M:
1592209ff23fSmrg	    s = "pal-m";
1593209ff23fSmrg	    break;
1594209ff23fSmrg	case TV_STD_PAL_60:
1595209ff23fSmrg	    s = "pal-60";
1596209ff23fSmrg	    break;
1597209ff23fSmrg	case TV_STD_NTSC_J:
1598209ff23fSmrg	    s = "ntsc-j";
1599209ff23fSmrg	    break;
1600209ff23fSmrg	case TV_STD_SCART_PAL:
1601209ff23fSmrg	    s = "scart-pal";
1602209ff23fSmrg	    break;
1603209ff23fSmrg	case TV_STD_NTSC:
1604209ff23fSmrg	default:
1605209ff23fSmrg	    s = "ntsc";
1606209ff23fSmrg	    break;
1607209ff23fSmrg	}
1608209ff23fSmrg
1609209ff23fSmrg	err = RRChangeOutputProperty(output->randr_output, tv_std_atom,
1610209ff23fSmrg				     XA_STRING, 8, PropModeReplace, strlen(s), (pointer)s,
1611209ff23fSmrg				     FALSE, FALSE);
1612209ff23fSmrg	if (err != 0) {
1613209ff23fSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1614209ff23fSmrg		       "RRChangeOutputProperty error, %d\n", err);
1615209ff23fSmrg	}
1616209ff23fSmrg    }
1617209ff23fSmrg}
1618209ff23fSmrg
1619209ff23fSmrgstatic Bool
1620209ff23fSmrgradeon_set_mode_for_property(xf86OutputPtr output)
1621209ff23fSmrg{
1622209ff23fSmrg    ScrnInfoPtr pScrn = output->scrn;
1623209ff23fSmrg
1624209ff23fSmrg    if (output->crtc) {
1625209ff23fSmrg	xf86CrtcPtr crtc = output->crtc;
1626209ff23fSmrg
1627209ff23fSmrg	if (crtc->enabled) {
1628b13dfe66Smrg#ifdef RANDR_14_INTERFACE
1629921a55d8Smrg	    xf86CrtcSetRec crtc_set_rec;
1630921a55d8Smrg
1631921a55d8Smrg	    crtc_set_rec.flags = (XF86CrtcSetMode |
1632921a55d8Smrg				  XF86CrtcSetOutput |
1633921a55d8Smrg				  XF86CrtcSetOrigin |
1634921a55d8Smrg				  XF86CrtcSetRotation);
1635921a55d8Smrg	    crtc_set_rec.mode = &crtc->desiredMode;
1636921a55d8Smrg	    crtc_set_rec.rotation = crtc->desiredRotation;
1637921a55d8Smrg	    crtc_set_rec.transform = NULL;
1638921a55d8Smrg	    crtc_set_rec.x = crtc->desiredX;
1639921a55d8Smrg	    crtc_set_rec.y = crtc->desiredY;
1640921a55d8Smrg	    if (!xf86CrtcSet(crtc, &crtc_set_rec)) {
1641921a55d8Smrg#else
1642209ff23fSmrg	    if (!xf86CrtcSetMode(crtc, &crtc->desiredMode, crtc->desiredRotation,
1643209ff23fSmrg				 crtc->desiredX, crtc->desiredY)) {
1644921a55d8Smrg#endif
1645209ff23fSmrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1646b13dfe66Smrg			   "Failed to set mode after property change!\n");
1647209ff23fSmrg		return FALSE;
1648209ff23fSmrg	    }
1649209ff23fSmrg	}
1650209ff23fSmrg    }
1651209ff23fSmrg    return TRUE;
1652209ff23fSmrg}
1653209ff23fSmrg
1654209ff23fSmrgstatic Bool
1655209ff23fSmrgradeon_set_property(xf86OutputPtr output, Atom property,
1656209ff23fSmrg		       RRPropertyValuePtr value)
1657209ff23fSmrg{
1658209ff23fSmrg    RADEONInfoPtr info = RADEONPTR(output->scrn);
1659209ff23fSmrg    RADEONOutputPrivatePtr radeon_output = output->driver_private;
1660209ff23fSmrg    INT32 val;
1661209ff23fSmrg
1662209ff23fSmrg
1663209ff23fSmrg    if (property == backlight_atom) {
1664209ff23fSmrg	if (value->type != XA_INTEGER ||
1665209ff23fSmrg	    value->format != 32 ||
1666209ff23fSmrg	    value->size != 1) {
1667209ff23fSmrg	    return FALSE;
1668209ff23fSmrg	}
1669209ff23fSmrg
1670209ff23fSmrg	val = *(INT32 *)value->data;
1671209ff23fSmrg	if (val < 0 || val > RADEON_MAX_BACKLIGHT_LEVEL)
1672209ff23fSmrg	    return FALSE;
1673209ff23fSmrg
1674209ff23fSmrg#if defined(__powerpc__)
1675209ff23fSmrg	val = RADEON_MAX_BACKLIGHT_LEVEL - val;
1676209ff23fSmrg#endif
1677209ff23fSmrg
1678209ff23fSmrg	radeon_set_backlight_level(output, val);
1679209ff23fSmrg
1680209ff23fSmrg    } else if (property == load_detection_atom) {
1681209ff23fSmrg	if (value->type != XA_INTEGER ||
1682209ff23fSmrg	    value->format != 32 ||
1683209ff23fSmrg	    value->size != 1) {
1684209ff23fSmrg	    return FALSE;
1685209ff23fSmrg	}
1686209ff23fSmrg
1687209ff23fSmrg	val = *(INT32 *)value->data;
1688209ff23fSmrg	if (val < 0 || val > 1)
1689209ff23fSmrg	    return FALSE;
1690209ff23fSmrg
1691209ff23fSmrg	radeon_output->load_detection = val;
1692209ff23fSmrg
1693209ff23fSmrg    } else if (property == coherent_mode_atom) {
1694209ff23fSmrg	Bool coherent_mode = radeon_output->coherent_mode;
1695209ff23fSmrg
1696209ff23fSmrg	if (value->type != XA_INTEGER ||
1697209ff23fSmrg	    value->format != 32 ||
1698209ff23fSmrg	    value->size != 1) {
1699209ff23fSmrg	    return FALSE;
1700209ff23fSmrg	}
1701209ff23fSmrg
1702209ff23fSmrg	val = *(INT32 *)value->data;
1703209ff23fSmrg	if (val < 0 || val > 1)
1704209ff23fSmrg	    return FALSE;
1705209ff23fSmrg
1706209ff23fSmrg	radeon_output->coherent_mode = val;
1707209ff23fSmrg	if (!radeon_set_mode_for_property(output)) {
1708209ff23fSmrg	    radeon_output->coherent_mode = coherent_mode;
1709209ff23fSmrg	    (void)radeon_set_mode_for_property(output);
1710209ff23fSmrg	    return FALSE;
1711209ff23fSmrg	}
1712209ff23fSmrg
1713209ff23fSmrg    } else if (property == rmx_atom) {
1714209ff23fSmrg	const char *s;
1715209ff23fSmrg	RADEONRMXType rmx = radeon_output->rmx_type;
1716209ff23fSmrg
1717209ff23fSmrg	if (value->type != XA_STRING || value->format != 8)
1718209ff23fSmrg	    return FALSE;
1719209ff23fSmrg	s = (char*)value->data;
1720209ff23fSmrg	if (value->size == strlen("full") && !strncmp("full", s, strlen("full"))) {
1721209ff23fSmrg	    radeon_output->rmx_type = RMX_FULL;
1722209ff23fSmrg	} else if (value->size == strlen("center") && !strncmp("center", s, strlen("center"))) {
1723209ff23fSmrg	    radeon_output->rmx_type = RMX_CENTER;
1724b7e1c893Smrg	} else if (value->size == strlen("aspect") && !strncmp("aspect", s, strlen("aspect"))) {
1725b7e1c893Smrg	    if (IS_AVIVO_VARIANT)
1726b7e1c893Smrg		radeon_output->rmx_type = RMX_ASPECT;
1727b7e1c893Smrg	    else
1728b7e1c893Smrg		return FALSE;
1729209ff23fSmrg	} else if (value->size == strlen("off") && !strncmp("off", s, strlen("off"))) {
1730209ff23fSmrg	    radeon_output->rmx_type = RMX_OFF;
1731209ff23fSmrg	} else
1732209ff23fSmrg	    return FALSE;
1733209ff23fSmrg
1734209ff23fSmrg	if (!radeon_set_mode_for_property(output)) {
1735209ff23fSmrg	    radeon_output->rmx_type = rmx;
1736209ff23fSmrg	    (void)radeon_set_mode_for_property(output);
1737209ff23fSmrg	    return FALSE;
1738209ff23fSmrg	}
1739209ff23fSmrg    } else if (property == tmds_pll_atom) {
1740b7e1c893Smrg	radeon_tmds_ptr tmds = NULL;
1741209ff23fSmrg	const char *s;
1742b7e1c893Smrg
1743b7e1c893Smrg	if (info->encoders[ATOM_DEVICE_DFP1_INDEX] && info->encoders[ATOM_DEVICE_DFP1_INDEX]->dev_priv)
1744b7e1c893Smrg	    tmds = (radeon_tmds_ptr)info->encoders[ATOM_DEVICE_DFP1_INDEX]->dev_priv;
1745b7e1c893Smrg	else
1746b7e1c893Smrg	    return FALSE;
1747b7e1c893Smrg
1748209ff23fSmrg	if (value->type != XA_STRING || value->format != 8)
1749209ff23fSmrg	    return FALSE;
1750209ff23fSmrg	s = (char*)value->data;
1751209ff23fSmrg	if (value->size == strlen("bios") && !strncmp("bios", s, strlen("bios"))) {
1752b7e1c893Smrg	    if (!RADEONGetTMDSInfoFromBIOS(output->scrn, tmds))
1753b7e1c893Smrg		RADEONGetTMDSInfoFromTable(output->scrn, tmds);
1754b7e1c893Smrg	} else if (value->size == strlen("driver") && !strncmp("driver", s, strlen("driver")))
1755b7e1c893Smrg	    RADEONGetTMDSInfoFromTable(output->scrn, tmds);
1756b7e1c893Smrg	else
1757209ff23fSmrg	    return FALSE;
1758209ff23fSmrg
1759209ff23fSmrg	return radeon_set_mode_for_property(output);
1760209ff23fSmrg    } else if (property == monitor_type_atom) {
1761209ff23fSmrg	const char *s;
1762209ff23fSmrg	if (value->type != XA_STRING || value->format != 8)
1763209ff23fSmrg	    return FALSE;
1764209ff23fSmrg	s = (char*)value->data;
1765209ff23fSmrg	if (value->size == strlen("auto") && !strncmp("auto", s, strlen("auto"))) {
1766209ff23fSmrg	    radeon_output->DVIType = DVI_AUTO;
1767209ff23fSmrg	    return TRUE;
1768209ff23fSmrg	} else if (value->size == strlen("analog") && !strncmp("analog", s, strlen("analog"))) {
1769209ff23fSmrg	    radeon_output->DVIType = DVI_ANALOG;
1770209ff23fSmrg	    return TRUE;
1771209ff23fSmrg	} else if (value->size == strlen("digital") && !strncmp("digital", s, strlen("digital"))) {
1772209ff23fSmrg	    radeon_output->DVIType = DVI_DIGITAL;
1773209ff23fSmrg	    return TRUE;
1774209ff23fSmrg	} else
1775209ff23fSmrg	    return FALSE;
1776209ff23fSmrg    } else if (property == tv_hsize_atom) {
1777b7e1c893Smrg	radeon_tvout_ptr tvout = &radeon_output->tvout;
1778209ff23fSmrg	if (value->type != XA_INTEGER ||
1779209ff23fSmrg	    value->format != 32 ||
1780209ff23fSmrg	    value->size != 1) {
1781209ff23fSmrg	    return FALSE;
1782209ff23fSmrg	}
1783209ff23fSmrg
1784209ff23fSmrg	val = *(INT32 *)value->data;
1785209ff23fSmrg	if (val < -MAX_H_SIZE || val > MAX_H_SIZE)
1786209ff23fSmrg	    return FALSE;
1787209ff23fSmrg
1788b7e1c893Smrg	tvout->hSize = val;
1789b7e1c893Smrg	if (tvout->tv_on && !IS_AVIVO_VARIANT)
1790209ff23fSmrg	    RADEONUpdateHVPosition(output, &output->crtc->mode);
1791209ff23fSmrg
1792209ff23fSmrg    } else if (property == tv_hpos_atom) {
1793b7e1c893Smrg	radeon_tvout_ptr tvout = &radeon_output->tvout;
1794209ff23fSmrg	if (value->type != XA_INTEGER ||
1795209ff23fSmrg	    value->format != 32 ||
1796209ff23fSmrg	    value->size != 1) {
1797209ff23fSmrg	    return FALSE;
1798209ff23fSmrg	}
1799209ff23fSmrg
1800209ff23fSmrg	val = *(INT32 *)value->data;
1801209ff23fSmrg	if (val < -MAX_H_POSITION || val > MAX_H_POSITION)
1802209ff23fSmrg	    return FALSE;
1803209ff23fSmrg
1804b7e1c893Smrg	tvout->hPos = val;
1805b7e1c893Smrg	if (tvout->tv_on && !IS_AVIVO_VARIANT)
1806209ff23fSmrg	    RADEONUpdateHVPosition(output, &output->crtc->mode);
1807209ff23fSmrg
1808209ff23fSmrg    } else if (property == tv_vpos_atom) {
1809b7e1c893Smrg	radeon_tvout_ptr tvout = &radeon_output->tvout;
1810209ff23fSmrg	if (value->type != XA_INTEGER ||
1811209ff23fSmrg	    value->format != 32 ||
1812209ff23fSmrg	    value->size != 1) {
1813209ff23fSmrg	    return FALSE;
1814209ff23fSmrg	}
1815209ff23fSmrg
1816209ff23fSmrg	val = *(INT32 *)value->data;
1817209ff23fSmrg	if (val < -MAX_H_POSITION || val > MAX_H_POSITION)
1818209ff23fSmrg	    return FALSE;
1819209ff23fSmrg
1820b7e1c893Smrg	tvout->vPos = val;
1821b7e1c893Smrg	if (tvout->tv_on && !IS_AVIVO_VARIANT)
1822209ff23fSmrg	    RADEONUpdateHVPosition(output, &output->crtc->mode);
1823209ff23fSmrg
1824209ff23fSmrg    } else if (property == tv_std_atom) {
1825209ff23fSmrg	const char *s;
1826b7e1c893Smrg	radeon_tvout_ptr tvout = &radeon_output->tvout;
1827b7e1c893Smrg	TVStd std = tvout->tvStd;
1828209ff23fSmrg
1829209ff23fSmrg	if (value->type != XA_STRING || value->format != 8)
1830209ff23fSmrg	    return FALSE;
1831209ff23fSmrg	s = (char*)value->data;
1832209ff23fSmrg	if (value->size == strlen("ntsc") && !strncmp("ntsc", s, strlen("ntsc"))) {
1833b7e1c893Smrg	    tvout->tvStd = TV_STD_NTSC;
1834209ff23fSmrg	} else if (value->size == strlen("pal") && !strncmp("pal", s, strlen("pal"))) {
1835b7e1c893Smrg	    tvout->tvStd = TV_STD_PAL;
1836209ff23fSmrg	} else if (value->size == strlen("pal-m") && !strncmp("pal-m", s, strlen("pal-m"))) {
1837b7e1c893Smrg	    tvout->tvStd = TV_STD_PAL_M;
1838209ff23fSmrg	} else if (value->size == strlen("pal-60") && !strncmp("pal-60", s, strlen("pal-60"))) {
1839b7e1c893Smrg	    tvout->tvStd = TV_STD_PAL_60;
1840209ff23fSmrg	} else if (value->size == strlen("ntsc-j") && !strncmp("ntsc-j", s, strlen("ntsc-j"))) {
1841b7e1c893Smrg	    tvout->tvStd = TV_STD_NTSC_J;
1842209ff23fSmrg	} else if (value->size == strlen("scart-pal") && !strncmp("scart-pal", s, strlen("scart-pal"))) {
1843b7e1c893Smrg	    tvout->tvStd = TV_STD_SCART_PAL;
1844209ff23fSmrg	} else if (value->size == strlen("pal-cn") && !strncmp("pal-cn", s, strlen("pal-cn"))) {
1845b7e1c893Smrg	    tvout->tvStd = TV_STD_PAL_CN;
1846209ff23fSmrg	} else if (value->size == strlen("secam") && !strncmp("secam", s, strlen("secam"))) {
1847b7e1c893Smrg	    tvout->tvStd = TV_STD_SECAM;
1848209ff23fSmrg	} else
1849209ff23fSmrg	    return FALSE;
1850209ff23fSmrg
1851209ff23fSmrg	if (!radeon_set_mode_for_property(output)) {
1852b7e1c893Smrg	    tvout->tvStd = std;
1853209ff23fSmrg	    (void)radeon_set_mode_for_property(output);
1854209ff23fSmrg	    return FALSE;
1855209ff23fSmrg	}
1856209ff23fSmrg    }
1857209ff23fSmrg
1858209ff23fSmrg    return TRUE;
1859209ff23fSmrg}
1860209ff23fSmrg
1861209ff23fSmrgstatic const xf86OutputFuncsRec radeon_output_funcs = {
1862209ff23fSmrg    .create_resources = radeon_create_resources,
1863209ff23fSmrg    .dpms = radeon_dpms,
1864209ff23fSmrg    .save = radeon_save,
1865209ff23fSmrg    .restore = radeon_restore,
1866209ff23fSmrg    .mode_valid = radeon_mode_valid,
1867209ff23fSmrg    .mode_fixup = radeon_mode_fixup,
1868209ff23fSmrg    .prepare = radeon_mode_prepare,
1869209ff23fSmrg    .mode_set = radeon_mode_set,
1870209ff23fSmrg    .commit = radeon_mode_commit,
1871209ff23fSmrg    .detect = radeon_detect,
1872209ff23fSmrg    .get_modes = radeon_get_modes,
1873209ff23fSmrg    .set_property = radeon_set_property,
1874209ff23fSmrg    .destroy = radeon_destroy
1875209ff23fSmrg};
1876209ff23fSmrg
1877b7e1c893SmrgBool
1878c503f109SmrgRADEONI2CDoLock(xf86OutputPtr output, I2CBusPtr b, int lock_state)
1879209ff23fSmrg{
1880209ff23fSmrg    ScrnInfoPtr pScrn = output->scrn;
1881209ff23fSmrg    RADEONInfoPtr  info       = RADEONPTR(pScrn);
1882c503f109Smrg    RADEONI2CBusPtr pRADEONI2CBus = b->DriverPrivate.ptr;
1883209ff23fSmrg    unsigned char *RADEONMMIO = info->MMIO;
1884209ff23fSmrg    uint32_t temp;
1885209ff23fSmrg
1886b7e1c893Smrg    if (lock_state) {
1887c503f109Smrg	/* RV410 appears to have a bug where the hw i2c in reset
1888c503f109Smrg	 * holds the i2c port in a bad state - switch hw i2c away before
1889c503f109Smrg	 * doing DDC - do this for all r200s/r300s for safety sakes */
1890c503f109Smrg	if ((info->ChipFamily >= CHIP_FAMILY_R200) && (!IS_AVIVO_VARIANT)) {
1891c503f109Smrg	    if (pRADEONI2CBus->mask_clk_reg == RADEON_GPIO_MONID)
1892c503f109Smrg                OUTREG(RADEON_DVI_I2C_CNTL_0, (RADEON_I2C_SOFT_RST |
1893c503f109Smrg					       R200_DVI_I2C_PIN_SEL(R200_SEL_DDC1)));
1894c503f109Smrg	    else
1895c503f109Smrg                OUTREG(RADEON_DVI_I2C_CNTL_0, (RADEON_I2C_SOFT_RST |
1896c503f109Smrg					       R200_DVI_I2C_PIN_SEL(R200_SEL_DDC3)));
1897c503f109Smrg	}
1898c503f109Smrg
18990974d292Smrg	/* set the pad in ddc mode */
1900921a55d8Smrg	if (IS_DCE3_VARIANT &&
1901921a55d8Smrg	    pRADEONI2CBus->hw_capable) {
19020974d292Smrg	    temp = INREG(pRADEONI2CBus->mask_clk_reg);
19030974d292Smrg	    temp &= ~(1 << 16);
19040974d292Smrg	    OUTREG(pRADEONI2CBus->mask_clk_reg, temp);
19050974d292Smrg	}
19060974d292Smrg
1907b7e1c893Smrg	temp = INREG(pRADEONI2CBus->a_clk_reg);
1908b7e1c893Smrg	temp &= ~(pRADEONI2CBus->a_clk_mask);
1909b7e1c893Smrg	OUTREG(pRADEONI2CBus->a_clk_reg, temp);
1910b7e1c893Smrg
1911b7e1c893Smrg	temp = INREG(pRADEONI2CBus->a_data_reg);
1912b7e1c893Smrg	temp &= ~(pRADEONI2CBus->a_data_mask);
1913b7e1c893Smrg	OUTREG(pRADEONI2CBus->a_data_reg, temp);
1914b7e1c893Smrg    }
1915b7e1c893Smrg
1916209ff23fSmrg    temp = INREG(pRADEONI2CBus->mask_clk_reg);
1917b7e1c893Smrg    if (lock_state)
1918b7e1c893Smrg	temp |= (pRADEONI2CBus->mask_clk_mask);
1919209ff23fSmrg    else
1920b7e1c893Smrg	temp &= ~(pRADEONI2CBus->mask_clk_mask);
1921209ff23fSmrg    OUTREG(pRADEONI2CBus->mask_clk_reg, temp);
1922209ff23fSmrg    temp = INREG(pRADEONI2CBus->mask_clk_reg);
1923209ff23fSmrg
1924209ff23fSmrg    temp = INREG(pRADEONI2CBus->mask_data_reg);
1925b7e1c893Smrg    if (lock_state)
1926b7e1c893Smrg	temp |= (pRADEONI2CBus->mask_data_mask);
1927209ff23fSmrg    else
1928b7e1c893Smrg	temp &= ~(pRADEONI2CBus->mask_data_mask);
1929209ff23fSmrg    OUTREG(pRADEONI2CBus->mask_data_reg, temp);
1930209ff23fSmrg    temp = INREG(pRADEONI2CBus->mask_data_reg);
1931209ff23fSmrg
1932209ff23fSmrg    return TRUE;
1933209ff23fSmrg}
1934209ff23fSmrg
1935209ff23fSmrgstatic void RADEONI2CGetBits(I2CBusPtr b, int *Clock, int *data)
1936209ff23fSmrg{
1937209ff23fSmrg    ScrnInfoPtr    pScrn      = xf86Screens[b->scrnIndex];
1938209ff23fSmrg    RADEONInfoPtr  info       = RADEONPTR(pScrn);
1939209ff23fSmrg    unsigned long  val;
1940209ff23fSmrg    unsigned char *RADEONMMIO = info->MMIO;
1941209ff23fSmrg    RADEONI2CBusPtr pRADEONI2CBus = b->DriverPrivate.ptr;
1942209ff23fSmrg
1943209ff23fSmrg    /* Get the result */
1944209ff23fSmrg    val = INREG(pRADEONI2CBus->get_clk_reg);
1945209ff23fSmrg    *Clock = (val & pRADEONI2CBus->get_clk_mask) != 0;
1946209ff23fSmrg    val = INREG(pRADEONI2CBus->get_data_reg);
1947209ff23fSmrg    *data  = (val & pRADEONI2CBus->get_data_mask) != 0;
1948209ff23fSmrg
1949209ff23fSmrg}
1950209ff23fSmrg
1951209ff23fSmrgstatic void RADEONI2CPutBits(I2CBusPtr b, int Clock, int data)
1952209ff23fSmrg{
1953209ff23fSmrg    ScrnInfoPtr    pScrn      = xf86Screens[b->scrnIndex];
1954209ff23fSmrg    RADEONInfoPtr  info       = RADEONPTR(pScrn);
1955209ff23fSmrg    unsigned long  val;
1956209ff23fSmrg    unsigned char *RADEONMMIO = info->MMIO;
1957209ff23fSmrg    RADEONI2CBusPtr pRADEONI2CBus = b->DriverPrivate.ptr;
1958209ff23fSmrg
1959209ff23fSmrg    val = INREG(pRADEONI2CBus->put_clk_reg) & (uint32_t)~(pRADEONI2CBus->put_clk_mask);
1960209ff23fSmrg    val |= (Clock ? 0:pRADEONI2CBus->put_clk_mask);
1961209ff23fSmrg    OUTREG(pRADEONI2CBus->put_clk_reg, val);
1962209ff23fSmrg    /* read back to improve reliability on some cards. */
1963209ff23fSmrg    val = INREG(pRADEONI2CBus->put_clk_reg);
1964209ff23fSmrg
1965209ff23fSmrg    val = INREG(pRADEONI2CBus->put_data_reg) & (uint32_t)~(pRADEONI2CBus->put_data_mask);
1966209ff23fSmrg    val |= (data ? 0:pRADEONI2CBus->put_data_mask);
1967209ff23fSmrg    OUTREG(pRADEONI2CBus->put_data_reg, val);
1968209ff23fSmrg    /* read back to improve reliability on some cards. */
1969209ff23fSmrg    val = INREG(pRADEONI2CBus->put_data_reg);
1970209ff23fSmrg
1971209ff23fSmrg}
1972209ff23fSmrg
1973b7e1c893SmrgBool
1974b7e1c893SmrgRADEONI2CInit(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr, char *name, RADEONI2CBusPtr pRADEONI2CBus)
1975209ff23fSmrg{
1976209ff23fSmrg    I2CBusPtr pI2CBus;
1977209ff23fSmrg
1978209ff23fSmrg    pI2CBus = xf86CreateI2CBusRec();
1979209ff23fSmrg    if (!pI2CBus) return FALSE;
1980209ff23fSmrg
1981209ff23fSmrg    pI2CBus->BusName    = name;
1982209ff23fSmrg    pI2CBus->scrnIndex  = pScrn->scrnIndex;
1983209ff23fSmrg    pI2CBus->I2CPutBits = RADEONI2CPutBits;
1984209ff23fSmrg    pI2CBus->I2CGetBits = RADEONI2CGetBits;
1985b7e1c893Smrg    pI2CBus->AcknTimeout = 5;
1986209ff23fSmrg
1987b7e1c893Smrg    pI2CBus->DriverPrivate.ptr = (pointer)pRADEONI2CBus;
1988209ff23fSmrg
1989b7e1c893Smrg    if (!xf86I2CBusInit(pI2CBus))
1990b7e1c893Smrg	return FALSE;
1991209ff23fSmrg
1992b7e1c893Smrg    *bus_ptr = pI2CBus;
1993209ff23fSmrg    return TRUE;
1994209ff23fSmrg}
1995209ff23fSmrg
1996b7e1c893SmrgRADEONI2CBusRec
1997b7e1c893Smrglegacy_setup_i2c_bus(int ddc_line)
1998209ff23fSmrg{
1999b7e1c893Smrg    RADEONI2CBusRec i2c;
2000209ff23fSmrg
2001b7e1c893Smrg    i2c.hw_line = 0;
2002b7e1c893Smrg    i2c.hw_capable = FALSE;
2003b7e1c893Smrg    i2c.mask_clk_mask = RADEON_GPIO_EN_1;
2004b7e1c893Smrg    i2c.mask_data_mask = RADEON_GPIO_EN_0;
2005b7e1c893Smrg    i2c.a_clk_mask = RADEON_GPIO_A_1;
2006b7e1c893Smrg    i2c.a_data_mask = RADEON_GPIO_A_0;
2007b7e1c893Smrg    i2c.put_clk_mask = RADEON_GPIO_EN_1;
2008b7e1c893Smrg    i2c.put_data_mask = RADEON_GPIO_EN_0;
2009b7e1c893Smrg    i2c.get_clk_mask = RADEON_GPIO_Y_1;
2010b7e1c893Smrg    i2c.get_data_mask = RADEON_GPIO_Y_0;
2011b7e1c893Smrg    if ((ddc_line == RADEON_LCD_GPIO_MASK) ||
2012b7e1c893Smrg	(ddc_line == RADEON_MDGPIO_EN_REG)) {
2013b7e1c893Smrg	i2c.mask_clk_reg = ddc_line;
2014b7e1c893Smrg	i2c.mask_data_reg = ddc_line;
2015b7e1c893Smrg	i2c.a_clk_reg = ddc_line;
2016b7e1c893Smrg	i2c.a_data_reg = ddc_line;
2017b7e1c893Smrg	i2c.put_clk_reg = ddc_line;
2018b7e1c893Smrg	i2c.put_data_reg = ddc_line;
2019b7e1c893Smrg	i2c.get_clk_reg = ddc_line + 4;
2020b7e1c893Smrg	i2c.get_data_reg = ddc_line + 4;
2021b7e1c893Smrg    } else {
2022b7e1c893Smrg	i2c.mask_clk_reg = ddc_line;
2023b7e1c893Smrg	i2c.mask_data_reg = ddc_line;
2024b7e1c893Smrg	i2c.a_clk_reg = ddc_line;
2025b7e1c893Smrg	i2c.a_data_reg = ddc_line;
2026b7e1c893Smrg	i2c.put_clk_reg = ddc_line;
2027b7e1c893Smrg	i2c.put_data_reg = ddc_line;
2028b7e1c893Smrg	i2c.get_clk_reg = ddc_line;
2029b7e1c893Smrg	i2c.get_data_reg = ddc_line;
2030209ff23fSmrg    }
2031b7e1c893Smrg
2032b7e1c893Smrg    if (ddc_line)
2033b7e1c893Smrg	i2c.valid = TRUE;
2034b7e1c893Smrg    else
2035b7e1c893Smrg	i2c.valid = FALSE;
2036b7e1c893Smrg
2037b7e1c893Smrg    return i2c;
2038209ff23fSmrg}
2039209ff23fSmrg
2040b7e1c893SmrgRADEONI2CBusRec
2041b7e1c893Smrgatom_setup_i2c_bus(int ddc_line)
2042209ff23fSmrg{
2043b7e1c893Smrg    RADEONI2CBusRec i2c;
2044209ff23fSmrg
2045b7e1c893Smrg    i2c.hw_line = 0;
2046b7e1c893Smrg    i2c.hw_capable = FALSE;
2047b7e1c893Smrg    if (ddc_line == AVIVO_GPIO_0) {
2048b7e1c893Smrg	i2c.put_clk_mask = (1 << 19);
2049b7e1c893Smrg	i2c.put_data_mask = (1 << 18);
2050b7e1c893Smrg	i2c.get_clk_mask = (1 << 19);
2051b7e1c893Smrg	i2c.get_data_mask = (1 << 18);
2052b7e1c893Smrg	i2c.mask_clk_mask = (1 << 19);
2053b7e1c893Smrg	i2c.mask_data_mask = (1 << 18);
2054b7e1c893Smrg	i2c.a_clk_mask = (1 << 19);
2055b7e1c893Smrg	i2c.a_data_mask = (1 << 18);
2056b7e1c893Smrg    } else {
2057b7e1c893Smrg	i2c.put_clk_mask = (1 << 0);
2058b7e1c893Smrg	i2c.put_data_mask = (1 << 8);
2059b7e1c893Smrg	i2c.get_clk_mask = (1 << 0);
2060b7e1c893Smrg	i2c.get_data_mask = (1 << 8);
2061b7e1c893Smrg	i2c.mask_clk_mask = (1 << 0);
2062b7e1c893Smrg	i2c.mask_data_mask = (1 << 8);
2063b7e1c893Smrg	i2c.a_clk_mask = (1 << 0);
2064b7e1c893Smrg	i2c.a_data_mask = (1 << 8);
2065209ff23fSmrg    }
2066b7e1c893Smrg    i2c.mask_clk_reg = ddc_line;
2067b7e1c893Smrg    i2c.mask_data_reg = ddc_line;
2068b7e1c893Smrg    i2c.a_clk_reg = ddc_line + 0x4;
2069b7e1c893Smrg    i2c.a_data_reg = ddc_line + 0x4;
2070b7e1c893Smrg    i2c.put_clk_reg = ddc_line + 0x8;
2071b7e1c893Smrg    i2c.put_data_reg = ddc_line + 0x8;
2072b7e1c893Smrg    i2c.get_clk_reg = ddc_line + 0xc;
2073b7e1c893Smrg    i2c.get_data_reg = ddc_line + 0xc;
2074b7e1c893Smrg    if (ddc_line)
2075b7e1c893Smrg	i2c.valid = TRUE;
2076b7e1c893Smrg    else
2077b7e1c893Smrg	i2c.valid = FALSE;
2078209ff23fSmrg
2079b7e1c893Smrg    return i2c;
2080209ff23fSmrg}
2081209ff23fSmrg
2082209ff23fSmrgstatic void
2083209ff23fSmrgRADEONGetTVInfo(xf86OutputPtr output)
2084209ff23fSmrg{
2085209ff23fSmrg    ScrnInfoPtr pScrn = output->scrn;
2086209ff23fSmrg    RADEONInfoPtr  info       = RADEONPTR(pScrn);
2087209ff23fSmrg    RADEONOutputPrivatePtr radeon_output = output->driver_private;
2088b7e1c893Smrg    radeon_tvout_ptr tvout = &radeon_output->tvout;
2089209ff23fSmrg    char *optstr;
2090209ff23fSmrg
2091b7e1c893Smrg    tvout->hPos = 0;
2092b7e1c893Smrg    tvout->vPos = 0;
2093b7e1c893Smrg    tvout->hSize = 0;
2094b7e1c893Smrg    tvout->tv_on = FALSE;
2095209ff23fSmrg
2096209ff23fSmrg    if (!RADEONGetTVInfoFromBIOS(output)) {
2097209ff23fSmrg	/* set some reasonable defaults */
2098b7e1c893Smrg	tvout->default_tvStd = TV_STD_NTSC;
2099b7e1c893Smrg	tvout->tvStd = TV_STD_NTSC;
2100b7e1c893Smrg	tvout->TVRefClk = 27.000000000;
2101b7e1c893Smrg	tvout->SupportedTVStds = TV_STD_NTSC | TV_STD_PAL;
2102209ff23fSmrg    }
2103209ff23fSmrg
2104209ff23fSmrg    optstr = (char *)xf86GetOptValString(info->Options, OPTION_TVSTD);
2105209ff23fSmrg    if (optstr) {
2106209ff23fSmrg	if (!strncmp("ntsc", optstr, strlen("ntsc")))
2107b7e1c893Smrg	    tvout->tvStd = TV_STD_NTSC;
2108209ff23fSmrg	else if (!strncmp("pal", optstr, strlen("pal")))
2109b7e1c893Smrg	    tvout->tvStd = TV_STD_PAL;
2110209ff23fSmrg	else if (!strncmp("pal-m", optstr, strlen("pal-m")))
2111b7e1c893Smrg	    tvout->tvStd = TV_STD_PAL_M;
2112209ff23fSmrg	else if (!strncmp("pal-60", optstr, strlen("pal-60")))
2113b7e1c893Smrg	    tvout->tvStd = TV_STD_PAL_60;
2114209ff23fSmrg	else if (!strncmp("ntsc-j", optstr, strlen("ntsc-j")))
2115b7e1c893Smrg	    tvout->tvStd = TV_STD_NTSC_J;
2116209ff23fSmrg	else if (!strncmp("scart-pal", optstr, strlen("scart-pal")))
2117b7e1c893Smrg	    tvout->tvStd = TV_STD_SCART_PAL;
2118209ff23fSmrg	else {
2119209ff23fSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Invalid TV Standard: %s\n", optstr);
2120209ff23fSmrg	}
2121209ff23fSmrg    }
2122209ff23fSmrg
2123209ff23fSmrg}
2124209ff23fSmrg
2125209ff23fSmrgvoid RADEONInitConnector(xf86OutputPtr output)
2126209ff23fSmrg{
2127209ff23fSmrg    ScrnInfoPtr	    pScrn = output->scrn;
2128209ff23fSmrg    RADEONInfoPtr  info       = RADEONPTR(pScrn);
2129209ff23fSmrg    RADEONOutputPrivatePtr radeon_output = output->driver_private;
2130209ff23fSmrg
2131b7e1c893Smrg    if (radeon_output->devices & (ATOM_DEVICE_LCD_SUPPORT))
2132b7e1c893Smrg	radeon_output->rmx_type = RMX_FULL;
2133209ff23fSmrg    else
2134b7e1c893Smrg	radeon_output->rmx_type = RMX_OFF;
2135209ff23fSmrg
2136b7e1c893Smrg    if (!IS_AVIVO_VARIANT) {
2137b7e1c893Smrg	if (radeon_output->devices & (ATOM_DEVICE_CRT2_SUPPORT)) {
2138b7e1c893Smrg	    if (xf86ReturnOptValBool(info->Options, OPTION_TVDAC_LOAD_DETECT, FALSE))
2139b7e1c893Smrg		radeon_output->load_detection = 1;
2140b7e1c893Smrg	}
2141209ff23fSmrg    }
2142209ff23fSmrg
2143b7e1c893Smrg    if (radeon_output->devices & (ATOM_DEVICE_TV_SUPPORT))
2144209ff23fSmrg	RADEONGetTVInfo(output);
2145209ff23fSmrg
2146b7e1c893Smrg    if (radeon_output->devices & (ATOM_DEVICE_DFP_SUPPORT))
2147209ff23fSmrg	radeon_output->coherent_mode = TRUE;
2148209ff23fSmrg
2149ad43ddacSmrg    if (radeon_output->ConnectorType == CONNECTOR_DISPLAY_PORT) {
2150ad43ddacSmrg	strcpy(radeon_output->dp_bus_name, output->name);
2151ad43ddacSmrg	strcat(radeon_output->dp_bus_name, "-DP");
2152ad43ddacSmrg	RADEON_DP_I2CInit(pScrn, &radeon_output->dp_pI2CBus, radeon_output->dp_bus_name, output);
2153ad43ddacSmrg	RADEON_DP_GetSinkType(output);
2154ad43ddacSmrg    }
2155ad43ddacSmrg
2156ad43ddacSmrg    if (radeon_output->ConnectorType == CONNECTOR_EDP) {
2157ad43ddacSmrg	strcpy(radeon_output->dp_bus_name, output->name);
2158ad43ddacSmrg	strcat(radeon_output->dp_bus_name, "-eDP");
2159ad43ddacSmrg	RADEON_DP_I2CInit(pScrn, &radeon_output->dp_pI2CBus, radeon_output->dp_bus_name, output);
2160ad43ddacSmrg	RADEON_DP_GetSinkType(output);
2161ad43ddacSmrg    }
2162ad43ddacSmrg
2163209ff23fSmrg    if (radeon_output->ddc_i2c.valid)
2164b7e1c893Smrg	RADEONI2CInit(pScrn, &radeon_output->pI2CBus, output->name, &radeon_output->ddc_i2c);
2165209ff23fSmrg
2166209ff23fSmrg}
2167209ff23fSmrg
2168209ff23fSmrg#if defined(__powerpc__)
2169209ff23fSmrgstatic Bool RADEONSetupAppleConnectors(ScrnInfoPtr pScrn)
2170209ff23fSmrg{
2171209ff23fSmrg    RADEONInfoPtr info       = RADEONPTR(pScrn);
2172209ff23fSmrg
2173209ff23fSmrg
2174209ff23fSmrg    switch (info->MacModel) {
2175209ff23fSmrg    case RADEON_MAC_IBOOK:
2176209ff23fSmrg	info->BiosConnector[0].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_DVI_DDC);
2177209ff23fSmrg	info->BiosConnector[0].ConnectorType = CONNECTOR_LVDS;
2178209ff23fSmrg	info->BiosConnector[0].valid = TRUE;
2179b7e1c893Smrg	info->BiosConnector[0].devices = ATOM_DEVICE_LCD1_SUPPORT;
2180b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
2181b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
2182b7e1c893Smrg									    ATOM_DEVICE_LCD1_SUPPORT,
2183b7e1c893Smrg									    0),
2184b7e1c893Smrg				ATOM_DEVICE_LCD1_SUPPORT))
2185b7e1c893Smrg	    return FALSE;
2186209ff23fSmrg
2187209ff23fSmrg	info->BiosConnector[1].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
2188b7e1c893Smrg	info->BiosConnector[1].load_detection = FALSE;
2189209ff23fSmrg	info->BiosConnector[1].ConnectorType = CONNECTOR_VGA;
2190209ff23fSmrg	info->BiosConnector[1].valid = TRUE;
2191b7e1c893Smrg	info->BiosConnector[1].devices = ATOM_DEVICE_CRT2_SUPPORT;
2192b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
2193b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
2194b7e1c893Smrg									    ATOM_DEVICE_CRT2_SUPPORT,
2195b7e1c893Smrg									    2),
2196b7e1c893Smrg				ATOM_DEVICE_CRT2_SUPPORT))
2197b7e1c893Smrg	    return FALSE;
2198209ff23fSmrg
2199209ff23fSmrg	info->BiosConnector[2].ConnectorType = CONNECTOR_STV;
2200b7e1c893Smrg	info->BiosConnector[2].load_detection = FALSE;
2201209ff23fSmrg	info->BiosConnector[2].ddc_i2c.valid = FALSE;
2202209ff23fSmrg	info->BiosConnector[2].valid = TRUE;
2203b7e1c893Smrg	info->BiosConnector[2].devices = ATOM_DEVICE_TV1_SUPPORT;
2204b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
2205b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
2206b7e1c893Smrg									    ATOM_DEVICE_TV1_SUPPORT,
2207b7e1c893Smrg									    2),
2208b7e1c893Smrg				ATOM_DEVICE_TV1_SUPPORT))
2209b7e1c893Smrg	    return FALSE;
2210209ff23fSmrg	return TRUE;
2211209ff23fSmrg    case RADEON_MAC_POWERBOOK_EXTERNAL:
2212209ff23fSmrg	info->BiosConnector[0].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_DVI_DDC);
2213209ff23fSmrg	info->BiosConnector[0].ConnectorType = CONNECTOR_LVDS;
2214209ff23fSmrg	info->BiosConnector[0].valid = TRUE;
2215b7e1c893Smrg	info->BiosConnector[0].devices = ATOM_DEVICE_LCD1_SUPPORT;
2216b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
2217b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
2218b7e1c893Smrg									    ATOM_DEVICE_LCD1_SUPPORT,
2219b7e1c893Smrg									    0),
2220b7e1c893Smrg				ATOM_DEVICE_LCD1_SUPPORT))
2221b7e1c893Smrg	    return FALSE;
2222209ff23fSmrg
2223209ff23fSmrg	info->BiosConnector[1].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
2224209ff23fSmrg	info->BiosConnector[1].ConnectorType = CONNECTOR_DVI_I;
2225209ff23fSmrg	info->BiosConnector[1].valid = TRUE;
2226b7e1c893Smrg	info->BiosConnector[1].devices = ATOM_DEVICE_CRT1_SUPPORT | ATOM_DEVICE_DFP2_SUPPORT;
2227b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
2228b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
2229b7e1c893Smrg									    ATOM_DEVICE_CRT1_SUPPORT,
2230b7e1c893Smrg									    1),
2231b7e1c893Smrg				ATOM_DEVICE_CRT1_SUPPORT))
2232b7e1c893Smrg	    return FALSE;
2233b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
2234b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
2235b7e1c893Smrg									    ATOM_DEVICE_DFP2_SUPPORT,
2236b7e1c893Smrg									    0),
2237b7e1c893Smrg				ATOM_DEVICE_DFP2_SUPPORT))
2238b7e1c893Smrg	    return FALSE;
2239209ff23fSmrg
2240209ff23fSmrg	info->BiosConnector[2].ConnectorType = CONNECTOR_STV;
2241b7e1c893Smrg	info->BiosConnector[2].load_detection = FALSE;
2242209ff23fSmrg	info->BiosConnector[2].ddc_i2c.valid = FALSE;
2243209ff23fSmrg	info->BiosConnector[2].valid = TRUE;
2244b7e1c893Smrg	info->BiosConnector[2].devices = ATOM_DEVICE_TV1_SUPPORT;
2245b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
2246b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
2247b7e1c893Smrg									    ATOM_DEVICE_TV1_SUPPORT,
2248b7e1c893Smrg									    2),
2249b7e1c893Smrg				ATOM_DEVICE_TV1_SUPPORT))
2250b7e1c893Smrg	    return FALSE;
2251209ff23fSmrg	return TRUE;
2252209ff23fSmrg    case RADEON_MAC_POWERBOOK_INTERNAL:
2253209ff23fSmrg	info->BiosConnector[0].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_DVI_DDC);
2254209ff23fSmrg	info->BiosConnector[0].ConnectorType = CONNECTOR_LVDS;
2255209ff23fSmrg	info->BiosConnector[0].valid = TRUE;
2256b7e1c893Smrg	info->BiosConnector[0].devices = ATOM_DEVICE_LCD1_SUPPORT;
2257b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
2258b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
2259b7e1c893Smrg									    ATOM_DEVICE_LCD1_SUPPORT,
2260b7e1c893Smrg									    0),
2261b7e1c893Smrg				ATOM_DEVICE_LCD1_SUPPORT))
2262b7e1c893Smrg	    return FALSE;
2263209ff23fSmrg
2264209ff23fSmrg	info->BiosConnector[1].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
2265209ff23fSmrg	info->BiosConnector[1].ConnectorType = CONNECTOR_DVI_I;
2266209ff23fSmrg	info->BiosConnector[1].valid = TRUE;
2267b7e1c893Smrg	info->BiosConnector[1].devices = ATOM_DEVICE_CRT1_SUPPORT | ATOM_DEVICE_DFP1_SUPPORT;
2268b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
2269b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
2270b7e1c893Smrg									    ATOM_DEVICE_CRT1_SUPPORT,
2271b7e1c893Smrg									    1),
2272b7e1c893Smrg				ATOM_DEVICE_CRT1_SUPPORT))
2273b7e1c893Smrg	    return FALSE;
2274b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
2275b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
2276b7e1c893Smrg									    ATOM_DEVICE_DFP1_SUPPORT,
2277b7e1c893Smrg									    0),
2278b7e1c893Smrg				ATOM_DEVICE_DFP1_SUPPORT))
2279b7e1c893Smrg	    return FALSE;
2280209ff23fSmrg
2281209ff23fSmrg	info->BiosConnector[2].ConnectorType = CONNECTOR_STV;
2282b7e1c893Smrg	info->BiosConnector[2].load_detection = FALSE;
2283209ff23fSmrg	info->BiosConnector[2].ddc_i2c.valid = FALSE;
2284209ff23fSmrg	info->BiosConnector[2].valid = TRUE;
2285b7e1c893Smrg	info->BiosConnector[2].devices = ATOM_DEVICE_TV1_SUPPORT;
2286b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
2287b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
2288b7e1c893Smrg									    ATOM_DEVICE_TV1_SUPPORT,
2289b7e1c893Smrg									    2),
2290b7e1c893Smrg				ATOM_DEVICE_TV1_SUPPORT))
2291b7e1c893Smrg	    return FALSE;
2292209ff23fSmrg	return TRUE;
2293209ff23fSmrg    case RADEON_MAC_POWERBOOK_VGA:
2294209ff23fSmrg	info->BiosConnector[0].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_DVI_DDC);
2295b7e1c893Smrg	info->BiosConnector[0].ConnectorType = CONNECTOR_LVDS;
2296209ff23fSmrg	info->BiosConnector[0].valid = TRUE;
2297b7e1c893Smrg	info->BiosConnector[0].devices = ATOM_DEVICE_LCD1_SUPPORT;
2298b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
2299b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
2300b7e1c893Smrg									    ATOM_DEVICE_LCD1_SUPPORT,
2301b7e1c893Smrg									    0),
2302b7e1c893Smrg				ATOM_DEVICE_LCD1_SUPPORT))
2303b7e1c893Smrg	    return FALSE;
2304209ff23fSmrg
2305209ff23fSmrg	info->BiosConnector[1].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
2306b7e1c893Smrg	info->BiosConnector[1].ConnectorType = CONNECTOR_VGA;
2307209ff23fSmrg	info->BiosConnector[1].valid = TRUE;
2308b7e1c893Smrg	info->BiosConnector[1].devices = ATOM_DEVICE_CRT1_SUPPORT;
2309b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
2310b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
2311b7e1c893Smrg									    ATOM_DEVICE_CRT1_SUPPORT,
2312b7e1c893Smrg									    1),
2313b7e1c893Smrg				ATOM_DEVICE_CRT1_SUPPORT))
2314b7e1c893Smrg	    return FALSE;
2315209ff23fSmrg
2316209ff23fSmrg	info->BiosConnector[2].ConnectorType = CONNECTOR_STV;
2317b7e1c893Smrg	info->BiosConnector[2].load_detection = FALSE;
2318209ff23fSmrg	info->BiosConnector[2].ddc_i2c.valid = FALSE;
2319209ff23fSmrg	info->BiosConnector[2].valid = TRUE;
2320b7e1c893Smrg	info->BiosConnector[2].devices = ATOM_DEVICE_TV1_SUPPORT;
2321b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
2322b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
2323b7e1c893Smrg									    ATOM_DEVICE_TV1_SUPPORT,
2324b7e1c893Smrg									    2),
2325b7e1c893Smrg				ATOM_DEVICE_TV1_SUPPORT))
2326b7e1c893Smrg	    return FALSE;
2327209ff23fSmrg	return TRUE;
2328209ff23fSmrg    case RADEON_MAC_MINI_EXTERNAL:
2329209ff23fSmrg	info->BiosConnector[0].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_CRT2_DDC);
2330b7e1c893Smrg	info->BiosConnector[0].load_detection = FALSE;
2331209ff23fSmrg	info->BiosConnector[0].ConnectorType = CONNECTOR_DVI_I;
2332209ff23fSmrg	info->BiosConnector[0].valid = TRUE;
2333b7e1c893Smrg	info->BiosConnector[0].devices = ATOM_DEVICE_CRT2_SUPPORT | ATOM_DEVICE_DFP2_SUPPORT;
2334b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
2335b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
2336b7e1c893Smrg									    ATOM_DEVICE_CRT2_SUPPORT,
2337b7e1c893Smrg									    2),
2338b7e1c893Smrg				ATOM_DEVICE_CRT2_SUPPORT))
2339b7e1c893Smrg	    return FALSE;
2340b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
2341b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
2342b7e1c893Smrg									    ATOM_DEVICE_DFP2_SUPPORT,
2343b7e1c893Smrg									    0),
2344b7e1c893Smrg				ATOM_DEVICE_DFP2_SUPPORT))
2345b7e1c893Smrg	    return FALSE;
2346209ff23fSmrg
2347209ff23fSmrg	info->BiosConnector[1].ConnectorType = CONNECTOR_STV;
2348b7e1c893Smrg	info->BiosConnector[1].load_detection = FALSE;
2349209ff23fSmrg	info->BiosConnector[1].ddc_i2c.valid = FALSE;
2350209ff23fSmrg	info->BiosConnector[1].valid = TRUE;
2351b7e1c893Smrg	info->BiosConnector[1].devices = ATOM_DEVICE_TV1_SUPPORT;
2352b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
2353b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
2354b7e1c893Smrg									    ATOM_DEVICE_TV1_SUPPORT,
2355b7e1c893Smrg									    2),
2356b7e1c893Smrg				ATOM_DEVICE_TV1_SUPPORT))
2357b7e1c893Smrg	    return FALSE;
2358209ff23fSmrg	return TRUE;
2359209ff23fSmrg    case RADEON_MAC_MINI_INTERNAL:
2360209ff23fSmrg	info->BiosConnector[0].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_CRT2_DDC);
2361b7e1c893Smrg	info->BiosConnector[0].load_detection = FALSE;
2362209ff23fSmrg	info->BiosConnector[0].ConnectorType = CONNECTOR_DVI_I;
2363209ff23fSmrg	info->BiosConnector[0].valid = TRUE;
2364b7e1c893Smrg	info->BiosConnector[0].devices = ATOM_DEVICE_CRT2_SUPPORT | ATOM_DEVICE_DFP1_SUPPORT;
2365b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
2366b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
2367b7e1c893Smrg									    ATOM_DEVICE_CRT2_SUPPORT,
2368b7e1c893Smrg									    2),
2369b7e1c893Smrg				ATOM_DEVICE_CRT2_SUPPORT))
2370b7e1c893Smrg	    return FALSE;
2371b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
2372b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
2373b7e1c893Smrg									    ATOM_DEVICE_DFP1_SUPPORT,
2374b7e1c893Smrg									    0),
2375b7e1c893Smrg				ATOM_DEVICE_DFP1_SUPPORT))
2376b7e1c893Smrg	    return FALSE;
2377209ff23fSmrg
2378209ff23fSmrg	info->BiosConnector[1].ConnectorType = CONNECTOR_STV;
2379b7e1c893Smrg	info->BiosConnector[1].load_detection = FALSE;
2380209ff23fSmrg	info->BiosConnector[1].ddc_i2c.valid = FALSE;
2381209ff23fSmrg	info->BiosConnector[1].valid = TRUE;
2382b7e1c893Smrg	info->BiosConnector[1].devices = ATOM_DEVICE_TV1_SUPPORT;
2383b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
2384b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
2385b7e1c893Smrg									    ATOM_DEVICE_TV1_SUPPORT,
2386b7e1c893Smrg									    2),
2387b7e1c893Smrg				ATOM_DEVICE_TV1_SUPPORT))
2388b7e1c893Smrg	    return FALSE;
2389209ff23fSmrg	return TRUE;
2390209ff23fSmrg    case RADEON_MAC_IMAC_G5_ISIGHT:
2391209ff23fSmrg	info->BiosConnector[0].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_MONID);
2392209ff23fSmrg	info->BiosConnector[0].ConnectorType = CONNECTOR_DVI_D;
2393209ff23fSmrg	info->BiosConnector[0].valid = TRUE;
2394b7e1c893Smrg	info->BiosConnector[0].devices = ATOM_DEVICE_DFP1_SUPPORT;
2395b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
2396b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
2397b7e1c893Smrg									    ATOM_DEVICE_DFP1_SUPPORT,
2398b7e1c893Smrg									    0),
2399b7e1c893Smrg				ATOM_DEVICE_DFP1_SUPPORT))
2400b7e1c893Smrg	    return FALSE;
2401209ff23fSmrg
2402209ff23fSmrg	info->BiosConnector[1].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_DVI_DDC);
2403b7e1c893Smrg	info->BiosConnector[1].load_detection = FALSE;
2404b7e1c893Smrg	info->BiosConnector[1].ConnectorType = CONNECTOR_VGA;
2405b7e1c893Smrg	info->BiosConnector[1].valid = TRUE;
2406b7e1c893Smrg	info->BiosConnector[1].devices = ATOM_DEVICE_CRT2_SUPPORT;
2407b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
2408b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
2409b7e1c893Smrg									    ATOM_DEVICE_CRT2_SUPPORT,
2410b7e1c893Smrg									    2),
2411b7e1c893Smrg				ATOM_DEVICE_CRT2_SUPPORT))
2412b7e1c893Smrg	    return FALSE;
2413b7e1c893Smrg
2414b7e1c893Smrg	info->BiosConnector[2].ConnectorType = CONNECTOR_STV;
2415b7e1c893Smrg	info->BiosConnector[2].load_detection = FALSE;
2416b7e1c893Smrg	info->BiosConnector[2].ddc_i2c.valid = FALSE;
2417b7e1c893Smrg	info->BiosConnector[2].valid = TRUE;
2418b7e1c893Smrg	info->BiosConnector[2].devices = ATOM_DEVICE_TV1_SUPPORT;
2419b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
2420b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
2421b7e1c893Smrg									    ATOM_DEVICE_TV1_SUPPORT,
2422b7e1c893Smrg									    2),
2423b7e1c893Smrg				ATOM_DEVICE_TV1_SUPPORT))
2424b7e1c893Smrg	    return FALSE;
2425b7e1c893Smrg	return TRUE;
2426b7e1c893Smrg    case RADEON_MAC_EMAC:
2427b7e1c893Smrg	/* eMac G4 800/1.0 with radeon 7500, no EDID on internal monitor
2428b7e1c893Smrg	 * later eMac's (G4 1.25/1.42) with radeon 9200 and 9600 may have
2429b7e1c893Smrg	 * different ddc setups.  need to verify
2430b7e1c893Smrg	 */
2431b7e1c893Smrg	info->BiosConnector[0].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
2432b7e1c893Smrg	info->BiosConnector[0].ConnectorType = CONNECTOR_VGA;
2433b7e1c893Smrg	info->BiosConnector[0].valid = TRUE;
2434b7e1c893Smrg	info->BiosConnector[0].devices = ATOM_DEVICE_CRT1_SUPPORT;
2435b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
2436b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
2437b7e1c893Smrg									    ATOM_DEVICE_CRT1_SUPPORT,
2438b7e1c893Smrg									    1),
2439b7e1c893Smrg				ATOM_DEVICE_CRT1_SUPPORT))
2440b7e1c893Smrg	    return FALSE;
2441b7e1c893Smrg
2442b7e1c893Smrg	info->BiosConnector[1].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_CRT2_DDC);
2443b7e1c893Smrg	info->BiosConnector[1].load_detection = FALSE;
2444209ff23fSmrg	info->BiosConnector[1].ConnectorType = CONNECTOR_VGA;
2445209ff23fSmrg	info->BiosConnector[1].valid = TRUE;
2446b7e1c893Smrg	info->BiosConnector[1].devices = ATOM_DEVICE_CRT2_SUPPORT;
2447b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
2448b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
2449b7e1c893Smrg									    ATOM_DEVICE_CRT2_SUPPORT,
2450b7e1c893Smrg									    2),
2451b7e1c893Smrg				ATOM_DEVICE_CRT2_SUPPORT))
2452b7e1c893Smrg	    return FALSE;
2453209ff23fSmrg
2454209ff23fSmrg	info->BiosConnector[2].ConnectorType = CONNECTOR_STV;
2455b7e1c893Smrg	info->BiosConnector[2].load_detection = FALSE;
2456209ff23fSmrg	info->BiosConnector[2].ddc_i2c.valid = FALSE;
2457209ff23fSmrg	info->BiosConnector[2].valid = TRUE;
2458b7e1c893Smrg	info->BiosConnector[2].devices = ATOM_DEVICE_TV1_SUPPORT;
2459b7e1c893Smrg	if (!radeon_add_encoder(pScrn,
2460b7e1c893Smrg				radeon_get_encoder_id_from_supported_device(pScrn,
2461b7e1c893Smrg									    ATOM_DEVICE_TV1_SUPPORT,
2462b7e1c893Smrg									    2),
2463b7e1c893Smrg				ATOM_DEVICE_TV1_SUPPORT))
2464b7e1c893Smrg	    return FALSE;
2465209ff23fSmrg	return TRUE;
246668105dcbSveego    case RADEON_MAC_SAM440EP:
246768105dcbSveego	/* LVDS header */
246868105dcbSveego	info->BiosConnector[0].ddc_i2c = legacy_setup_i2c_bus(0);
246968105dcbSveego	info->BiosConnector[0].ConnectorType = CONNECTOR_LVDS;
247068105dcbSveego	info->BiosConnector[0].valid = TRUE;
247168105dcbSveego	info->BiosConnector[0].devices = ATOM_DEVICE_LCD1_SUPPORT;
247268105dcbSveego	if (!radeon_add_encoder(pScrn,
247368105dcbSveego				radeon_get_encoder_id_from_supported_device(pScrn,
247468105dcbSveego									    ATOM_DEVICE_LCD1_SUPPORT,
247568105dcbSveego									    0),
247668105dcbSveego				ATOM_DEVICE_LCD1_SUPPORT))
247768105dcbSveego	    return FALSE;
247868105dcbSveego
247968105dcbSveego	/* DVI-I port */
248068105dcbSveego	info->BiosConnector[1].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_DVI_DDC);
248168105dcbSveego	info->BiosConnector[1].ConnectorType = CONNECTOR_DVI_I;
248268105dcbSveego	info->BiosConnector[1].valid = TRUE;
248368105dcbSveego	info->BiosConnector[1].devices = ATOM_DEVICE_CRT2_SUPPORT | ATOM_DEVICE_DFP1_SUPPORT;
248468105dcbSveego	if (!radeon_add_encoder(pScrn,
248568105dcbSveego				radeon_get_encoder_id_from_supported_device(pScrn,
248668105dcbSveego									    ATOM_DEVICE_CRT2_SUPPORT,
248768105dcbSveego									    2),
248868105dcbSveego				ATOM_DEVICE_CRT2_SUPPORT))
248968105dcbSveego	    return FALSE;
249068105dcbSveego	if (!radeon_add_encoder(pScrn,
249168105dcbSveego				radeon_get_encoder_id_from_supported_device(pScrn,
249268105dcbSveego									    ATOM_DEVICE_DFP1_SUPPORT,
249368105dcbSveego									    0),
249468105dcbSveego				ATOM_DEVICE_DFP1_SUPPORT))
249568105dcbSveego	    return FALSE;
249668105dcbSveego
249768105dcbSveego	/* VGA header */
249868105dcbSveego	info->BiosConnector[2].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
249968105dcbSveego	info->BiosConnector[2].ConnectorType = CONNECTOR_VGA;
250068105dcbSveego	info->BiosConnector[2].valid = TRUE;
250168105dcbSveego	info->BiosConnector[2].devices = ATOM_DEVICE_CRT1_SUPPORT;
250268105dcbSveego	if (!radeon_add_encoder(pScrn,
250368105dcbSveego				radeon_get_encoder_id_from_supported_device(pScrn,
250468105dcbSveego									    ATOM_DEVICE_CRT1_SUPPORT,
250568105dcbSveego									    1),
250668105dcbSveego				ATOM_DEVICE_CRT1_SUPPORT))
250768105dcbSveego	    return FALSE;
250868105dcbSveego
250968105dcbSveego	/* s-video */
251068105dcbSveego	info->BiosConnector[3].ConnectorType = CONNECTOR_STV;
251168105dcbSveego	info->BiosConnector[3].load_detection = FALSE;
251268105dcbSveego	info->BiosConnector[3].ddc_i2c.valid = FALSE;
251368105dcbSveego	info->BiosConnector[3].valid = TRUE;
251468105dcbSveego	info->BiosConnector[3].devices = ATOM_DEVICE_TV1_SUPPORT;
251568105dcbSveego	if (!radeon_add_encoder(pScrn,
251668105dcbSveego				radeon_get_encoder_id_from_supported_device(pScrn,
251768105dcbSveego									    ATOM_DEVICE_TV1_SUPPORT,
251868105dcbSveego									    2),
251968105dcbSveego				ATOM_DEVICE_TV1_SUPPORT))
252068105dcbSveego	    return FALSE;
252168105dcbSveego	return TRUE;
2522209ff23fSmrg    default:
2523209ff23fSmrg	return FALSE;
2524209ff23fSmrg    }
2525209ff23fSmrg
2526209ff23fSmrg    return FALSE;
2527209ff23fSmrg}
2528209ff23fSmrg#endif
2529209ff23fSmrg
2530209ff23fSmrgstatic void RADEONSetupGenericConnectors(ScrnInfoPtr pScrn)
2531209ff23fSmrg{
2532209ff23fSmrg    RADEONInfoPtr info       = RADEONPTR(pScrn);
2533209ff23fSmrg    RADEONEntPtr pRADEONEnt  = RADEONEntPriv(pScrn);
2534209ff23fSmrg
2535b7e1c893Smrg    if (IS_AVIVO_VARIANT)
2536b7e1c893Smrg	return;
2537b7e1c893Smrg
2538209ff23fSmrg    if (!pRADEONEnt->HasCRTC2) {
2539209ff23fSmrg	info->BiosConnector[0].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
2540209ff23fSmrg	info->BiosConnector[0].ConnectorType = CONNECTOR_VGA;
2541209ff23fSmrg	info->BiosConnector[0].valid = TRUE;
2542b7e1c893Smrg	info->BiosConnector[0].devices = ATOM_DEVICE_CRT1_SUPPORT;
2543b7e1c893Smrg	radeon_add_encoder(pScrn,
2544b7e1c893Smrg			   radeon_get_encoder_id_from_supported_device(pScrn,
2545b7e1c893Smrg								       ATOM_DEVICE_CRT1_SUPPORT,
2546b7e1c893Smrg								       1),
2547b7e1c893Smrg			   ATOM_DEVICE_CRT1_SUPPORT);
2548209ff23fSmrg	return;
2549209ff23fSmrg    }
2550209ff23fSmrg
2551b7e1c893Smrg    if (info->IsMobility) {
2552b7e1c893Smrg	/* Below is the most common setting, but may not be true */
2553b7e1c893Smrg	if (info->IsIGP) {
2554b7e1c893Smrg	    info->BiosConnector[0].ddc_i2c = legacy_setup_i2c_bus(RADEON_LCD_GPIO_MASK);
2555209ff23fSmrg	    info->BiosConnector[0].ConnectorType = CONNECTOR_LVDS;
2556209ff23fSmrg	    info->BiosConnector[0].valid = TRUE;
2557b7e1c893Smrg	    info->BiosConnector[0].devices = ATOM_DEVICE_LCD1_SUPPORT;
2558b7e1c893Smrg	    radeon_add_encoder(pScrn,
2559b7e1c893Smrg			       radeon_get_encoder_id_from_supported_device(pScrn,
2560b7e1c893Smrg									   ATOM_DEVICE_LCD1_SUPPORT,
2561b7e1c893Smrg									   0),
2562b7e1c893Smrg			       ATOM_DEVICE_LCD1_SUPPORT);
2563b7e1c893Smrg
2564b7e1c893Smrg	    /* IGP only has TVDAC */
2565b7e1c893Smrg	    if ((info->ChipFamily == CHIP_FAMILY_RS400) ||
2566b7e1c893Smrg		(info->ChipFamily == CHIP_FAMILY_RS480))
2567b7e1c893Smrg		info->BiosConnector[1].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_CRT2_DDC);
2568b7e1c893Smrg	    else
2569b7e1c893Smrg		info->BiosConnector[1].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
2570b7e1c893Smrg	    info->BiosConnector[1].load_detection = FALSE;
2571209ff23fSmrg	    info->BiosConnector[1].ConnectorType = CONNECTOR_VGA;
2572209ff23fSmrg	    info->BiosConnector[1].valid = TRUE;
2573b7e1c893Smrg	    info->BiosConnector[1].devices = ATOM_DEVICE_CRT1_SUPPORT;
2574b7e1c893Smrg	    radeon_add_encoder(pScrn,
2575b7e1c893Smrg			       radeon_get_encoder_id_from_supported_device(pScrn,
2576b7e1c893Smrg									   ATOM_DEVICE_CRT1_SUPPORT,
2577b7e1c893Smrg									   2),
2578b7e1c893Smrg			       ATOM_DEVICE_CRT1_SUPPORT);
2579209ff23fSmrg	} else {
2580b7e1c893Smrg#if defined(__powerpc__)
2581b7e1c893Smrg	    info->BiosConnector[0].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_DVI_DDC);
2582b7e1c893Smrg#else
2583b7e1c893Smrg	    info->BiosConnector[0].ddc_i2c = legacy_setup_i2c_bus(RADEON_LCD_GPIO_MASK);
2584b7e1c893Smrg#endif
2585b7e1c893Smrg	    info->BiosConnector[0].ConnectorType = CONNECTOR_LVDS;
2586209ff23fSmrg	    info->BiosConnector[0].valid = TRUE;
2587b7e1c893Smrg	    info->BiosConnector[0].devices = ATOM_DEVICE_LCD1_SUPPORT;
2588b7e1c893Smrg	    radeon_add_encoder(pScrn,
2589b7e1c893Smrg			       radeon_get_encoder_id_from_supported_device(pScrn,
2590b7e1c893Smrg									   ATOM_DEVICE_LCD1_SUPPORT,
2591b7e1c893Smrg									   0),
2592b7e1c893Smrg			       ATOM_DEVICE_LCD1_SUPPORT);
2593209ff23fSmrg
2594b7e1c893Smrg	    info->BiosConnector[1].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
2595209ff23fSmrg	    info->BiosConnector[1].ConnectorType = CONNECTOR_VGA;
2596209ff23fSmrg	    info->BiosConnector[1].valid = TRUE;
2597b7e1c893Smrg	    info->BiosConnector[1].devices = ATOM_DEVICE_CRT1_SUPPORT;
2598b7e1c893Smrg	    radeon_add_encoder(pScrn,
2599b7e1c893Smrg			       radeon_get_encoder_id_from_supported_device(pScrn,
2600b7e1c893Smrg									   ATOM_DEVICE_CRT1_SUPPORT,
2601b7e1c893Smrg									   1),
2602b7e1c893Smrg			       ATOM_DEVICE_CRT1_SUPPORT);
2603209ff23fSmrg	}
2604209ff23fSmrg    } else {
2605b7e1c893Smrg	/* Below is the most common setting, but may not be true */
2606b7e1c893Smrg	if (info->IsIGP) {
2607b7e1c893Smrg	    if ((info->ChipFamily == CHIP_FAMILY_RS400) ||
2608b7e1c893Smrg		(info->ChipFamily == CHIP_FAMILY_RS480))
2609b7e1c893Smrg		info->BiosConnector[0].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_CRT2_DDC);
2610b7e1c893Smrg	    else
2611b7e1c893Smrg		info->BiosConnector[0].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
2612b7e1c893Smrg	    info->BiosConnector[0].load_detection = FALSE;
2613b7e1c893Smrg	    info->BiosConnector[0].ConnectorType = CONNECTOR_VGA;
2614b7e1c893Smrg	    info->BiosConnector[0].valid = TRUE;
2615b7e1c893Smrg	    info->BiosConnector[0].devices = ATOM_DEVICE_CRT1_SUPPORT;
2616b7e1c893Smrg	    radeon_add_encoder(pScrn,
2617b7e1c893Smrg			       radeon_get_encoder_id_from_supported_device(pScrn,
2618b7e1c893Smrg									   ATOM_DEVICE_CRT1_SUPPORT,
2619b7e1c893Smrg									   1),
2620b7e1c893Smrg			       ATOM_DEVICE_CRT1_SUPPORT);
2621b7e1c893Smrg
2622b7e1c893Smrg	    /* not sure what a good default DDCType for DVI on
2623b7e1c893Smrg	     * IGP desktop chips is
2624b7e1c893Smrg	     */
2625b7e1c893Smrg	    info->BiosConnector[1].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_MONID); /* DDC_DVI? */
2626b7e1c893Smrg	    info->BiosConnector[1].ConnectorType = CONNECTOR_DVI_D;
2627b7e1c893Smrg	    info->BiosConnector[1].valid = TRUE;
2628b7e1c893Smrg	    info->BiosConnector[1].devices = ATOM_DEVICE_DFP1_SUPPORT;
2629b7e1c893Smrg	    radeon_add_encoder(pScrn,
2630b7e1c893Smrg			       radeon_get_encoder_id_from_supported_device(pScrn,
2631b7e1c893Smrg									   ATOM_DEVICE_DFP1_SUPPORT,
2632b7e1c893Smrg									   0),
2633b7e1c893Smrg			       ATOM_DEVICE_DFP1_SUPPORT);
2634209ff23fSmrg	} else {
2635b7e1c893Smrg	    info->BiosConnector[0].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_DVI_DDC);
2636b7e1c893Smrg	    info->BiosConnector[0].load_detection = FALSE;
2637b7e1c893Smrg	    info->BiosConnector[0].ConnectorType = CONNECTOR_DVI_I;
2638b7e1c893Smrg	    info->BiosConnector[0].valid = TRUE;
2639b7e1c893Smrg	    info->BiosConnector[0].devices = ATOM_DEVICE_CRT2_SUPPORT | ATOM_DEVICE_DFP1_SUPPORT;
2640b7e1c893Smrg	    radeon_add_encoder(pScrn,
2641b7e1c893Smrg			       radeon_get_encoder_id_from_supported_device(pScrn,
2642b7e1c893Smrg									   ATOM_DEVICE_CRT2_SUPPORT,
2643b7e1c893Smrg									   2),
2644b7e1c893Smrg			       ATOM_DEVICE_CRT2_SUPPORT);
2645b7e1c893Smrg	    radeon_add_encoder(pScrn,
2646b7e1c893Smrg			       radeon_get_encoder_id_from_supported_device(pScrn,
2647b7e1c893Smrg									   ATOM_DEVICE_DFP1_SUPPORT,
2648b7e1c893Smrg									   0),
2649b7e1c893Smrg			       ATOM_DEVICE_DFP1_SUPPORT);
2650209ff23fSmrg
2651209ff23fSmrg#if defined(__powerpc__)
2652b7e1c893Smrg	    info->BiosConnector[1].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
2653b7e1c893Smrg	    info->BiosConnector[1].ConnectorType = CONNECTOR_DVI_I;
2654b7e1c893Smrg	    info->BiosConnector[1].valid = TRUE;
2655b7e1c893Smrg	    info->BiosConnector[1].devices = ATOM_DEVICE_CRT1_SUPPORT | ATOM_DEVICE_DFP2_SUPPORT;
2656b7e1c893Smrg	    radeon_add_encoder(pScrn,
2657b7e1c893Smrg			       radeon_get_encoder_id_from_supported_device(pScrn,
2658b7e1c893Smrg									   ATOM_DEVICE_CRT1_SUPPORT,
2659b7e1c893Smrg									   1),
2660b7e1c893Smrg			       ATOM_DEVICE_CRT1_SUPPORT);
2661b7e1c893Smrg	    radeon_add_encoder(pScrn,
2662b7e1c893Smrg			       radeon_get_encoder_id_from_supported_device(pScrn,
2663b7e1c893Smrg									   ATOM_DEVICE_DFP2_SUPPORT,
2664b7e1c893Smrg									   0),
2665b7e1c893Smrg			       ATOM_DEVICE_DFP2_SUPPORT);
2666209ff23fSmrg#else
2667b7e1c893Smrg	    info->BiosConnector[1].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
2668b7e1c893Smrg	    info->BiosConnector[1].ConnectorType = CONNECTOR_VGA;
2669b7e1c893Smrg	    info->BiosConnector[1].valid = TRUE;
2670b7e1c893Smrg	    info->BiosConnector[1].devices = ATOM_DEVICE_CRT1_SUPPORT;
2671b7e1c893Smrg	    radeon_add_encoder(pScrn,
2672b7e1c893Smrg			       radeon_get_encoder_id_from_supported_device(pScrn,
2673b7e1c893Smrg									   ATOM_DEVICE_CRT1_SUPPORT,
2674b7e1c893Smrg									   1),
2675b7e1c893Smrg			       ATOM_DEVICE_CRT1_SUPPORT);
2676209ff23fSmrg#endif
2677209ff23fSmrg	}
2678b7e1c893Smrg    }
2679209ff23fSmrg
2680b7e1c893Smrg    if (info->InternalTVOut) {
2681b7e1c893Smrg	info->BiosConnector[2].ConnectorType = CONNECTOR_STV;
2682b7e1c893Smrg	info->BiosConnector[2].load_detection = FALSE;
2683b7e1c893Smrg	info->BiosConnector[2].ddc_i2c.valid = FALSE;
2684b7e1c893Smrg	info->BiosConnector[2].valid = TRUE;
2685b7e1c893Smrg	info->BiosConnector[2].devices = ATOM_DEVICE_TV1_SUPPORT;
2686b7e1c893Smrg	radeon_add_encoder(pScrn,
2687b7e1c893Smrg			       radeon_get_encoder_id_from_supported_device(pScrn,
2688b7e1c893Smrg									   ATOM_DEVICE_TV1_SUPPORT,
2689b7e1c893Smrg									   2),
2690b7e1c893Smrg			       ATOM_DEVICE_TV1_SUPPORT);
2691b7e1c893Smrg    }
2692209ff23fSmrg
2693b7e1c893Smrg    /* Some cards have the DDC lines swapped and we have no way to
2694b7e1c893Smrg     * detect it yet (Mac cards)
2695b7e1c893Smrg     */
2696b7e1c893Smrg    if (xf86ReturnOptValBool(info->Options, OPTION_REVERSE_DDC, FALSE)) {
2697b7e1c893Smrg	info->BiosConnector[0].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
2698b7e1c893Smrg	info->BiosConnector[1].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_DVI_DDC);
2699209ff23fSmrg    }
2700209ff23fSmrg}
2701209ff23fSmrg
2702209ff23fSmrg#if defined(__powerpc__)
2703209ff23fSmrg
2704ad43ddacSmrg#ifdef __OpenBSD__
2705ad43ddacSmrg#include <sys/param.h>
2706ad43ddacSmrg#include <sys/sysctl.h>
2707ad43ddacSmrg#endif
2708ad43ddacSmrg
2709209ff23fSmrg/*
2710209ff23fSmrg * Returns RADEONMacModel or 0 based on lines 'detected as' and 'machine'
2711209ff23fSmrg * in /proc/cpuinfo (on Linux) */
2712209ff23fSmrgstatic RADEONMacModel RADEONDetectMacModel(ScrnInfoPtr pScrn)
2713209ff23fSmrg{
2714209ff23fSmrg    RADEONInfoPtr info = RADEONPTR(pScrn);
2715209ff23fSmrg    RADEONMacModel ret = 0;
2716209ff23fSmrg#ifdef __linux__
2717209ff23fSmrg    char cpuline[50];  /* 50 should be sufficient for our purposes */
2718209ff23fSmrg    FILE *f = fopen ("/proc/cpuinfo", "r");
2719209ff23fSmrg
2720209ff23fSmrg    /* Some macs (minis and powerbooks) use internal tmds, others use external tmds
2721209ff23fSmrg     * and not just for dual-link TMDS, it shows up with single-link as well.
2722209ff23fSmrg     * Unforunately, there doesn't seem to be any good way to figure it out.
2723209ff23fSmrg     */
2724209ff23fSmrg
2725b7e1c893Smrg    /*
2726209ff23fSmrg     * PowerBook5,[1-5]: external tmds, single-link
2727209ff23fSmrg     * PowerBook5,[789]: external tmds, dual-link
2728209ff23fSmrg     * PowerBook5,6:     external tmds, single-link or dual-link
2729209ff23fSmrg     * need to add another option to specify the external tmds chip
2730209ff23fSmrg     * or find out what's used and add it.
2731209ff23fSmrg     */
2732209ff23fSmrg
2733209ff23fSmrg
2734209ff23fSmrg    if (f != NULL) {
2735209ff23fSmrg	while (fgets(cpuline, sizeof cpuline, f)) {
2736209ff23fSmrg	    if (!strncmp(cpuline, "machine", strlen ("machine"))) {
2737ba58b518Smacallan#elif defined(__NetBSD__)
2738ba58b518Smacallan    char cpuline[50];
2739ba58b518Smacallan    int of;
2740ba58b518Smacallan    struct ofiocdesc ofio;
2741ba58b518Smacallan
2742ba58b518Smacallan    of = open("/dev/openfirm", O_RDONLY);
2743ba58b518Smacallan    if (of > 0) {
2744ba58b518Smacallan	ofio.of_nodeid = 0;
2745ba58b518Smacallan        ofio.of_name = "/";
2746ba58b518Smacallan	ofio.of_namelen = 1;
2747ba58b518Smacallan	if (ioctl(of, OFIOCFINDDEVICE, &ofio) != -1) {
2748ba58b518Smacallan	    ofio.of_name = "model";
2749ba58b518Smacallan	    ofio.of_namelen = 5;
2750ba58b518Smacallan	    ofio.of_buf = cpuline;
2751ba58b518Smacallan	    ofio.of_buflen = sizeof(cpuline);
2752ba58b518Smacallan	    while (ioctl(of, OFIOCGET, &ofio) != -1) {
2753ba58b518Smacallan	    	cpuline[49] = 0;
2754ba58b518Smacallan	        xf86Msg(X_ERROR, "model %s\n", cpuline);
2755ba58b518Smacallan#endif
2756209ff23fSmrg		if (strstr(cpuline, "PowerBook5,1") ||
2757209ff23fSmrg		    strstr(cpuline, "PowerBook5,2") ||
2758209ff23fSmrg		    strstr(cpuline, "PowerBook5,3") ||
2759209ff23fSmrg		    strstr(cpuline, "PowerBook5,4") ||
2760209ff23fSmrg		    strstr(cpuline, "PowerBook5,5")) {
2761209ff23fSmrg		    ret = RADEON_MAC_POWERBOOK_EXTERNAL; /* single link */
2762209ff23fSmrg		    info->ext_tmds_chip = RADEON_SIL_164; /* works on 5,2 */
2763209ff23fSmrg		    break;
2764209ff23fSmrg		}
2765209ff23fSmrg
2766209ff23fSmrg		if (strstr(cpuline, "PowerBook5,6")) {
2767209ff23fSmrg		    ret = RADEON_MAC_POWERBOOK_EXTERNAL; /* dual or single link */
2768209ff23fSmrg		    break;
2769209ff23fSmrg		}
2770209ff23fSmrg
2771209ff23fSmrg		if (strstr(cpuline, "PowerBook5,7") ||
2772209ff23fSmrg		    strstr(cpuline, "PowerBook5,8") ||
2773209ff23fSmrg		    strstr(cpuline, "PowerBook5,9")) {
2774209ff23fSmrg		    ret = RADEON_MAC_POWERBOOK_EXTERNAL; /* dual link */
2775209ff23fSmrg		    info->ext_tmds_chip = RADEON_SIL_1178; /* guess */
2776209ff23fSmrg		    break;
2777209ff23fSmrg		}
2778209ff23fSmrg
2779209ff23fSmrg		if (strstr(cpuline, "PowerBook3,3")) {
2780209ff23fSmrg		    ret = RADEON_MAC_POWERBOOK_VGA; /* vga rather than dvi */
2781209ff23fSmrg		    break;
2782209ff23fSmrg		}
2783209ff23fSmrg
2784209ff23fSmrg		if (strstr(cpuline, "PowerMac10,1")) {
2785209ff23fSmrg		    ret = RADEON_MAC_MINI_INTERNAL; /* internal tmds */
2786209ff23fSmrg		    break;
2787209ff23fSmrg		}
2788209ff23fSmrg		if (strstr(cpuline, "PowerMac10,2")) {
2789209ff23fSmrg		    ret = RADEON_MAC_MINI_EXTERNAL; /* external tmds */
2790209ff23fSmrg		    break;
2791209ff23fSmrg		}
2792ba58b518Smacallan#ifdef __linux__
2793209ff23fSmrg	    } else if (!strncmp(cpuline, "detected as", strlen("detected as"))) {
2794209ff23fSmrg		if (strstr(cpuline, "iBook")) {
2795209ff23fSmrg		    ret = RADEON_MAC_IBOOK;
2796209ff23fSmrg		    break;
2797209ff23fSmrg		} else if (strstr(cpuline, "PowerBook")) {
2798209ff23fSmrg		    ret = RADEON_MAC_POWERBOOK_INTERNAL; /* internal tmds */
2799209ff23fSmrg		    break;
2800209ff23fSmrg		} else if (strstr(cpuline, "iMac G5 (iSight)")) {
2801209ff23fSmrg		    ret = RADEON_MAC_IMAC_G5_ISIGHT;
2802209ff23fSmrg		    break;
2803b7e1c893Smrg		} else if (strstr(cpuline, "eMac")) {
2804b7e1c893Smrg		    ret = RADEON_MAC_EMAC;
2805b7e1c893Smrg		    break;
2806209ff23fSmrg		}
2807ba58b518Smacallan#endif
2808209ff23fSmrg		/* No known PowerMac model detected */
2809209ff23fSmrg		break;
2810209ff23fSmrg	    }
2811209ff23fSmrg	}
2812209ff23fSmrg
2813ba58b518Smacallan#ifdef __linux__
2814209ff23fSmrg	fclose (f);
2815209ff23fSmrg    } else
2816209ff23fSmrg	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
2817209ff23fSmrg		   "Cannot detect PowerMac model because /proc/cpuinfo not "
2818209ff23fSmrg		   "readable.\n");
2819ba58b518Smacallan#elif defined(__NetBSD__)
2820ba58b518Smacallan	close(of);
2821ba58b518Smacallan    } else
2822ba58b518Smacallan	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
2823ba58b518Smacallan		   "Cannot detect PowerMac model because /dev/openfirm not "
2824ba58b518Smacallan		   "readable.\n");
2825ba58b518Smacallan#endif
2826209ff23fSmrg
2827ad43ddacSmrg#ifdef __OpenBSD__
2828ad43ddacSmrg    char model[32];
2829ad43ddacSmrg    int mib[2];
2830ad43ddacSmrg    size_t len;
2831ad43ddacSmrg
2832ad43ddacSmrg    mib[0] = CTL_HW;
2833ad43ddacSmrg    mib[1] = HW_PRODUCT;
2834ad43ddacSmrg    len = sizeof(model);
2835ad43ddacSmrg    if (sysctl(mib, 2, model, &len, NULL, 0) >= 0) {
2836ad43ddacSmrg	if (strcmp(model, "PowerBook5,1") == 0 ||
2837ad43ddacSmrg	    strcmp(model, "PowerBook5,2") == 0 ||
2838ad43ddacSmrg	    strcmp(model, "PowerBook5,3") == 0 ||
2839ad43ddacSmrg	    strcmp(model, "PowerBook5,4") == 0 ||
2840ad43ddacSmrg	    strcmp(model, "PowerBook5,5") == 0) {
2841ad43ddacSmrg	    ret = RADEON_MAC_POWERBOOK_EXTERNAL; /* single link */
2842ad43ddacSmrg	    info->ext_tmds_chip = RADEON_SIL_164; /* works on 5,2 */
2843ad43ddacSmrg	}
2844ad43ddacSmrg
2845ad43ddacSmrg	if (strcmp(model, "PowerBook5,6") == 0) {
2846ad43ddacSmrg	    ret = RADEON_MAC_POWERBOOK_EXTERNAL; /* dual or single link */
2847ad43ddacSmrg	}
2848ad43ddacSmrg
2849ad43ddacSmrg	if (strcmp(model, "PowerBook5,7") ||
2850ad43ddacSmrg	    strcmp(model, "PowerBook5,8") == 0 ||
2851ad43ddacSmrg	    strcmp(model, "PowerBook5,9") == 0) {
2852ad43ddacSmrg	    ret = RADEON_MAC_POWERBOOK_EXTERNAL; /* dual link */
2853ad43ddacSmrg	    info->ext_tmds_chip = RADEON_SIL_1178; /* guess */
2854ad43ddacSmrg	}
2855ad43ddacSmrg
2856ad43ddacSmrg	if (strcmp(model, "PowerBook3,3") == 0) {
2857ad43ddacSmrg	    ret = RADEON_MAC_POWERBOOK_VGA; /* vga rather than dvi */
2858ad43ddacSmrg	}
2859ad43ddacSmrg
2860ad43ddacSmrg	if (strcmp(model, "PowerMac10,1") == 0) {
2861ad43ddacSmrg	    ret = RADEON_MAC_MINI_INTERNAL; /* internal tmds */
2862ad43ddacSmrg	}
2863ad43ddacSmrg
2864ad43ddacSmrg	if (strcmp(model, "PowerMac10,2") == 0) {
2865ad43ddacSmrg	    ret = RADEON_MAC_MINI_EXTERNAL; /* external tmds */
2866ad43ddacSmrg	}
2867ad43ddacSmrg
2868ad43ddacSmrg	if (strcmp(model, "PowerBook2,1") == 0 ||
2869ad43ddacSmrg	    strcmp(model, "PowerBook2,2") == 0 ||
2870ad43ddacSmrg	    strcmp(model, "PowerBook4,1") == 0 ||
2871ad43ddacSmrg	    strcmp(model, "PowerBook4,2") == 0 ||
2872ad43ddacSmrg	    strcmp(model, "PowerBook4,3") == 0 ||
2873ad43ddacSmrg	    strcmp(model, "PowerBook6,3") == 0 ||
2874ad43ddacSmrg	    strcmp(model, "PowerBook6,5") == 0 ||
2875ad43ddacSmrg	    strcmp(model, "PowerBook6,7") == 0) {
2876ad43ddacSmrg	    ret = RADEON_MAC_IBOOK;
2877ad43ddacSmrg	}
2878ad43ddacSmrg
2879ad43ddacSmrg	if (strcmp(model, "PowerBook1,1") == 0 ||
2880ad43ddacSmrg	    strcmp(model, "PowerBook3,1") == 0 ||
2881ad43ddacSmrg	    strcmp(model, "PowerBook3,2") == 0 ||
2882ad43ddacSmrg	    strcmp(model, "PowerBook3,4") == 0 ||
2883ad43ddacSmrg	    strcmp(model, "PowerBook3,5") == 0) {
2884ad43ddacSmrg	    ret = RADEON_MAC_POWERBOOK_INTERNAL;
2885ad43ddacSmrg	}
2886ad43ddacSmrg
2887ad43ddacSmrg	if (strcmp(model, "PowerMac12,1") == 0) {
2888ad43ddacSmrg	    ret = RADEON_MAC_IMAC_G5_ISIGHT;
2889ad43ddacSmrg	}
2890ad43ddacSmrg    }
2891ad43ddacSmrg#endif /* __OpenBSD__ */
2892ad43ddacSmrg
2893209ff23fSmrg    if (ret) {
2894209ff23fSmrg	xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "Detected %s.\n",
2895209ff23fSmrg		   ret == RADEON_MAC_POWERBOOK_EXTERNAL ? "PowerBook with external DVI" :
2896209ff23fSmrg		   ret == RADEON_MAC_POWERBOOK_INTERNAL ? "PowerBook with integrated DVI" :
2897209ff23fSmrg		   ret == RADEON_MAC_POWERBOOK_VGA ? "PowerBook with VGA" :
2898209ff23fSmrg		   ret == RADEON_MAC_IBOOK ? "iBook" :
2899209ff23fSmrg		   ret == RADEON_MAC_MINI_EXTERNAL ? "Mac Mini with external DVI" :
2900209ff23fSmrg		   ret == RADEON_MAC_MINI_INTERNAL ? "Mac Mini with integrated DVI" :
2901209ff23fSmrg		   "iMac G5 iSight");
2902209ff23fSmrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2903209ff23fSmrg		   "If this is not correct, try Option \"MacModel\" and "
2904209ff23fSmrg		   "consider reporting to the\n");
2905209ff23fSmrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2906209ff23fSmrg		   "xorg-driver-ati@lists.x.org mailing list"
2907209ff23fSmrg#ifdef __linux__
2908209ff23fSmrg		   " with the contents of /proc/cpuinfo"
2909209ff23fSmrg#endif
2910209ff23fSmrg		   ".\n");
2911209ff23fSmrg    }
2912209ff23fSmrg
2913209ff23fSmrg    return ret;
2914209ff23fSmrg}
2915209ff23fSmrg
2916209ff23fSmrg#endif /* __powerpc__ */
2917209ff23fSmrg
2918209ff23fSmrgstatic int
2919209ff23fSmrgradeon_output_clones (ScrnInfoPtr pScrn, xf86OutputPtr output)
2920209ff23fSmrg{
2921b7e1c893Smrg    RADEONInfoPtr info = RADEONPTR(pScrn);
2922209ff23fSmrg    RADEONOutputPrivatePtr radeon_output = output->driver_private;
2923209ff23fSmrg    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR (pScrn);
2924209ff23fSmrg    int			o;
2925209ff23fSmrg    int			index_mask = 0;
2926209ff23fSmrg
2927ad43ddacSmrg    /* no cloning with zaphod */
2928ad43ddacSmrg    if (info->IsPrimary || info->IsSecondary)
2929ad43ddacSmrg	return index_mask;
2930ad43ddacSmrg
2931b7e1c893Smrg    /* DIG routing gets problematic */
2932ad43ddacSmrg    if (info->ChipFamily >= CHIP_FAMILY_R600)
2933209ff23fSmrg	return index_mask;
2934209ff23fSmrg
2935209ff23fSmrg    /* LVDS is too wacky */
2936b7e1c893Smrg    if (radeon_output->devices & (ATOM_DEVICE_LCD_SUPPORT))
2937b7e1c893Smrg	return index_mask;
2938b7e1c893Smrg
2939ad43ddacSmrg    /* TV requires very specific timing */
2940b7e1c893Smrg    if (radeon_output->devices & (ATOM_DEVICE_TV_SUPPORT))
2941209ff23fSmrg	return index_mask;
2942209ff23fSmrg
2943ad43ddacSmrg    /* DVO requires 2x ppll clocks depending on the tmds chip */
2944ad43ddacSmrg    if (radeon_output->devices & (ATOM_DEVICE_DFP2_SUPPORT))
2945ad43ddacSmrg	return index_mask;
2946ad43ddacSmrg
2947209ff23fSmrg    for (o = 0; o < config->num_output; o++) {
2948209ff23fSmrg	xf86OutputPtr clone = config->output[o];
2949209ff23fSmrg	RADEONOutputPrivatePtr radeon_clone = clone->driver_private;
2950b7e1c893Smrg
2951209ff23fSmrg	if (output == clone) /* don't clone yourself */
2952209ff23fSmrg	    continue;
2953b7e1c893Smrg	else if (radeon_clone->devices & (ATOM_DEVICE_LCD_SUPPORT)) /* LVDS */
2954209ff23fSmrg	    continue;
2955b7e1c893Smrg	else if (radeon_clone->devices & (ATOM_DEVICE_TV_SUPPORT)) /* TV */
2956209ff23fSmrg	    continue;
2957209ff23fSmrg	else
2958209ff23fSmrg	    index_mask |= (1 << o);
2959209ff23fSmrg    }
2960209ff23fSmrg
2961209ff23fSmrg    return index_mask;
2962209ff23fSmrg}
2963209ff23fSmrg
2964b7e1c893Smrgstatic xf86OutputPtr
2965b7e1c893SmrgRADEONOutputCreate(ScrnInfoPtr pScrn, const char *name, int i)
2966b7e1c893Smrg{
2967b7e1c893Smrg    char buf[32];
2968b7e1c893Smrg    sprintf(buf, name, i);
2969b7e1c893Smrg    return xf86OutputCreate(pScrn, &radeon_output_funcs, buf);
2970b7e1c893Smrg}
2971b7e1c893Smrg
2972209ff23fSmrg/*
2973209ff23fSmrg * initialise the static data sos we don't have to re-do at randr change */
2974209ff23fSmrgBool RADEONSetupConnectors(ScrnInfoPtr pScrn)
2975209ff23fSmrg{
2976209ff23fSmrg    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
2977209ff23fSmrg    RADEONInfoPtr info       = RADEONPTR(pScrn);
2978209ff23fSmrg    xf86OutputPtr output;
2979209ff23fSmrg    char *optstr;
2980b7e1c893Smrg    int i;
2981209ff23fSmrg    int num_vga = 0;
2982209ff23fSmrg    int num_dvi = 0;
2983209ff23fSmrg    int num_hdmi = 0;
2984b7e1c893Smrg    int num_dp = 0;
2985ad43ddacSmrg    int num_edp = 0;
2986209ff23fSmrg
2987209ff23fSmrg    /* We first get the information about all connectors from BIOS.
2988209ff23fSmrg     * This is how the card is phyiscally wired up.
2989209ff23fSmrg     * The information should be correct even on a OEM card.
2990209ff23fSmrg     */
2991209ff23fSmrg    for (i = 0; i < RADEON_MAX_BIOS_CONNECTOR; i++) {
2992b7e1c893Smrg	info->encoders[i] = NULL;
2993209ff23fSmrg	info->BiosConnector[i].valid = FALSE;
2994b7e1c893Smrg	info->BiosConnector[i].load_detection = TRUE;
2995b7e1c893Smrg	info->BiosConnector[i].shared_ddc = FALSE;
2996209ff23fSmrg	info->BiosConnector[i].ddc_i2c.valid = FALSE;
2997209ff23fSmrg	info->BiosConnector[i].ConnectorType = CONNECTOR_NONE;
2998b7e1c893Smrg	info->BiosConnector[i].devices = 0;
2999209ff23fSmrg    }
3000209ff23fSmrg
3001209ff23fSmrg#if defined(__powerpc__)
3002209ff23fSmrg    info->MacModel = 0;
3003209ff23fSmrg    optstr = (char *)xf86GetOptValString(info->Options, OPTION_MAC_MODEL);
3004209ff23fSmrg    if (optstr) {
3005209ff23fSmrg	if (!strncmp("ibook", optstr, strlen("ibook")))
3006209ff23fSmrg	    info->MacModel = RADEON_MAC_IBOOK;
3007209ff23fSmrg	else if (!strncmp("powerbook-duallink", optstr, strlen("powerbook-duallink"))) /* alias */
3008209ff23fSmrg	    info->MacModel = RADEON_MAC_POWERBOOK_EXTERNAL;
3009209ff23fSmrg	else if (!strncmp("powerbook-external", optstr, strlen("powerbook-external")))
3010209ff23fSmrg	    info->MacModel = RADEON_MAC_POWERBOOK_EXTERNAL;
3011209ff23fSmrg	else if (!strncmp("powerbook-internal", optstr, strlen("powerbook-internal")))
3012209ff23fSmrg	    info->MacModel = RADEON_MAC_POWERBOOK_INTERNAL;
3013209ff23fSmrg	else if (!strncmp("powerbook-vga", optstr, strlen("powerbook-vga")))
3014209ff23fSmrg	    info->MacModel = RADEON_MAC_POWERBOOK_VGA;
3015209ff23fSmrg	else if (!strncmp("powerbook", optstr, strlen("powerbook"))) /* alias */
3016209ff23fSmrg	    info->MacModel = RADEON_MAC_POWERBOOK_INTERNAL;
3017209ff23fSmrg	else if (!strncmp("mini-internal", optstr, strlen("mini-internal")))
3018209ff23fSmrg	    info->MacModel = RADEON_MAC_MINI_INTERNAL;
3019209ff23fSmrg	else if (!strncmp("mini-external", optstr, strlen("mini-external")))
3020209ff23fSmrg	    info->MacModel = RADEON_MAC_MINI_EXTERNAL;
3021209ff23fSmrg	else if (!strncmp("mini", optstr, strlen("mini"))) /* alias */
3022209ff23fSmrg	    info->MacModel = RADEON_MAC_MINI_EXTERNAL;
3023209ff23fSmrg	else if (!strncmp("imac-g5-isight", optstr, strlen("imac-g5-isight")))
3024209ff23fSmrg	    info->MacModel = RADEON_MAC_IMAC_G5_ISIGHT;
3025b7e1c893Smrg	else if (!strncmp("emac", optstr, strlen("emac")))
3026b7e1c893Smrg	    info->MacModel = RADEON_MAC_EMAC;
302768105dcbSveego	else if (!strncmp("sam440ep", optstr, strlen("sam440ep")))
302868105dcbSveego	    info->MacModel = RADEON_MAC_SAM440EP;
3029209ff23fSmrg	else {
3030209ff23fSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Invalid Mac Model: %s\n", optstr);
3031209ff23fSmrg	}
3032209ff23fSmrg    }
3033209ff23fSmrg
3034209ff23fSmrg    if (!info->MacModel) {
3035209ff23fSmrg	info->MacModel = RADEONDetectMacModel(pScrn);
3036209ff23fSmrg    }
3037209ff23fSmrg
3038209ff23fSmrg    if (info->MacModel){
3039209ff23fSmrg	if (!RADEONSetupAppleConnectors(pScrn))
3040209ff23fSmrg	    RADEONSetupGenericConnectors(pScrn);
3041209ff23fSmrg    } else
3042209ff23fSmrg#endif
3043209ff23fSmrg    if (xf86ReturnOptValBool(info->Options, OPTION_DEFAULT_CONNECTOR_TABLE, FALSE)) {
3044209ff23fSmrg	RADEONSetupGenericConnectors(pScrn);
3045209ff23fSmrg    } else {
3046209ff23fSmrg	if (!RADEONGetConnectorInfoFromBIOS(pScrn))
3047209ff23fSmrg	    RADEONSetupGenericConnectors(pScrn);
3048209ff23fSmrg    }
3049209ff23fSmrg
3050209ff23fSmrg    /* parse connector table option */
3051209ff23fSmrg    optstr = (char *)xf86GetOptValString(info->Options, OPTION_CONNECTORTABLE);
3052209ff23fSmrg
3053209ff23fSmrg    if (optstr) {
3054209ff23fSmrg	unsigned int ddc_line[2];
3055b7e1c893Smrg	int DACType[2], TMDSType[2];
3056209ff23fSmrg
3057209ff23fSmrg	for (i = 2; i < RADEON_MAX_BIOS_CONNECTOR; i++) {
3058209ff23fSmrg	    info->BiosConnector[i].valid = FALSE;
3059209ff23fSmrg	}
3060b7e1c893Smrg
3061209ff23fSmrg	if (sscanf(optstr, "%u,%u,%u,%u,%u,%u,%u,%u",
3062209ff23fSmrg		   &ddc_line[0],
3063b7e1c893Smrg		   &DACType[0],
3064b7e1c893Smrg		   &TMDSType[0],
3065209ff23fSmrg		   &info->BiosConnector[0].ConnectorType,
3066209ff23fSmrg		   &ddc_line[1],
3067b7e1c893Smrg		   &DACType[1],
3068b7e1c893Smrg		   &TMDSType[1],
3069209ff23fSmrg		   &info->BiosConnector[1].ConnectorType) != 8) {
3070209ff23fSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Invalid ConnectorTable option: %s\n", optstr);
3071209ff23fSmrg	    return FALSE;
3072209ff23fSmrg	}
3073209ff23fSmrg
3074b7e1c893Smrg	for (i = 0; i < 2; i++) {
3075b7e1c893Smrg	    info->BiosConnector[i].valid = TRUE;
3076b7e1c893Smrg	    info->BiosConnector[i].ddc_i2c = legacy_setup_i2c_bus(ddc_line[i]);
3077b7e1c893Smrg	    switch (DACType[i]) {
3078b7e1c893Smrg	    case 1:
3079b7e1c893Smrg		info->BiosConnector[i].devices |= ATOM_DEVICE_CRT1_SUPPORT;
3080b7e1c893Smrg		if (!radeon_add_encoder(pScrn,
3081b7e1c893Smrg					radeon_get_encoder_id_from_supported_device(pScrn,
3082b7e1c893Smrg										    ATOM_DEVICE_CRT1_SUPPORT,
3083b7e1c893Smrg										    1),
3084b7e1c893Smrg					ATOM_DEVICE_CRT1_SUPPORT))
3085b7e1c893Smrg		    return FALSE;
3086b7e1c893Smrg		info->BiosConnector[i].load_detection = TRUE;
3087b7e1c893Smrg		break;
3088b7e1c893Smrg	    case 2:
3089b7e1c893Smrg		info->BiosConnector[i].devices |= ATOM_DEVICE_CRT2_SUPPORT;
3090b7e1c893Smrg		if (!radeon_add_encoder(pScrn,
3091b7e1c893Smrg					radeon_get_encoder_id_from_supported_device(pScrn,
309240732134Srjs										    ATOM_DEVICE_CRT2_SUPPORT,
3093b7e1c893Smrg										    2),
309440732134Srjs					ATOM_DEVICE_CRT2_SUPPORT))
3095b7e1c893Smrg		    return FALSE;
3096b7e1c893Smrg		info->BiosConnector[i].load_detection = FALSE;
3097b7e1c893Smrg		break;
3098b7e1c893Smrg	    }
3099b7e1c893Smrg	    switch (TMDSType[i]) {
3100b7e1c893Smrg	    case 1:
3101b7e1c893Smrg		info->BiosConnector[i].devices |= ATOM_DEVICE_DFP1_SUPPORT;
3102b7e1c893Smrg		if (!radeon_add_encoder(pScrn,
3103b7e1c893Smrg					radeon_get_encoder_id_from_supported_device(pScrn,
3104b7e1c893Smrg										    ATOM_DEVICE_DFP1_SUPPORT,
3105b7e1c893Smrg										    0),
3106b7e1c893Smrg					ATOM_DEVICE_DFP1_SUPPORT))
3107b7e1c893Smrg		    return FALSE;
3108b7e1c893Smrg		break;
3109b7e1c893Smrg	    case 2:
3110b7e1c893Smrg		info->BiosConnector[i].devices |= ATOM_DEVICE_DFP2_SUPPORT;
3111b7e1c893Smrg		if (!radeon_add_encoder(pScrn,
3112b7e1c893Smrg					radeon_get_encoder_id_from_supported_device(pScrn,
3113b7e1c893Smrg										    ATOM_DEVICE_DFP2_SUPPORT,
3114b7e1c893Smrg										    0),
3115b7e1c893Smrg					ATOM_DEVICE_DFP2_SUPPORT))
3116b7e1c893Smrg		    return FALSE;
3117b7e1c893Smrg		break;
3118b7e1c893Smrg	    }
3119b7e1c893Smrg	}
3120209ff23fSmrg    }
3121209ff23fSmrg
3122209ff23fSmrg    for (i = 0; i < RADEON_MAX_BIOS_CONNECTOR; i++) {
3123209ff23fSmrg	if (info->BiosConnector[i].valid) {
3124b7e1c893Smrg	    RADEONConnectorType conntype = info->BiosConnector[i].ConnectorType;
3125b7e1c893Smrg	    if ((conntype == CONNECTOR_DVI_D) ||
3126b7e1c893Smrg		(conntype == CONNECTOR_DVI_I) ||
3127ad43ddacSmrg		(conntype == CONNECTOR_DVI_A) ||
3128ad43ddacSmrg		(conntype == CONNECTOR_HDMI_TYPE_B)) {
3129209ff23fSmrg		num_dvi++;
3130b7e1c893Smrg	    } else if (conntype == CONNECTOR_VGA) {
3131209ff23fSmrg		num_vga++;
3132ad43ddacSmrg	    } else if (conntype == CONNECTOR_HDMI_TYPE_A) {
3133209ff23fSmrg		num_hdmi++;
3134b7e1c893Smrg	    } else if (conntype == CONNECTOR_DISPLAY_PORT) {
3135b7e1c893Smrg		num_dp++;
3136ad43ddacSmrg	    } else if (conntype == CONNECTOR_EDP) {
3137ad43ddacSmrg		num_edp++;
3138209ff23fSmrg	    }
3139209ff23fSmrg	}
3140209ff23fSmrg    }
3141209ff23fSmrg
3142209ff23fSmrg    for (i = 0 ; i < RADEON_MAX_BIOS_CONNECTOR; i++) {
3143209ff23fSmrg	if (info->BiosConnector[i].valid) {
3144209ff23fSmrg	    RADEONOutputPrivatePtr radeon_output;
3145b7e1c893Smrg	    RADEONConnectorType conntype = info->BiosConnector[i].ConnectorType;
3146209ff23fSmrg
3147b7e1c893Smrg	    if (conntype == CONNECTOR_NONE)
3148209ff23fSmrg		continue;
3149209ff23fSmrg
3150209ff23fSmrg	    radeon_output = xnfcalloc(sizeof(RADEONOutputPrivateRec), 1);
3151209ff23fSmrg	    if (!radeon_output) {
3152209ff23fSmrg		return FALSE;
3153209ff23fSmrg	    }
3154209ff23fSmrg	    radeon_output->MonType = MT_UNKNOWN;
3155b7e1c893Smrg	    radeon_output->ConnectorType = conntype;
3156209ff23fSmrg	    radeon_output->devices = info->BiosConnector[i].devices;
3157209ff23fSmrg	    radeon_output->ddc_i2c = info->BiosConnector[i].ddc_i2c;
3158209ff23fSmrg	    radeon_output->igp_lane_info = info->BiosConnector[i].igp_lane_info;
3159b7e1c893Smrg	    radeon_output->shared_ddc = info->BiosConnector[i].shared_ddc;
3160b7e1c893Smrg	    radeon_output->load_detection = info->BiosConnector[i].load_detection;
3161b7e1c893Smrg	    radeon_output->linkb = info->BiosConnector[i].linkb;
3162ad43ddacSmrg	    radeon_output->dig_encoder = -1;
3163b7e1c893Smrg	    radeon_output->connector_id = info->BiosConnector[i].connector_object;
3164ad43ddacSmrg	    radeon_output->connector_object_id = info->BiosConnector[i].connector_object_id;
3165ad43ddacSmrg	    radeon_output->ucI2cId = info->BiosConnector[i].ucI2cId;
3166ad43ddacSmrg	    radeon_output->hpd_id = info->BiosConnector[i].hpd_id;
3167b7e1c893Smrg
3168ad43ddacSmrg	    /* Technically HDMI-B is a glorfied DL DVI so the bios is correct,
3169ad43ddacSmrg	     * but this can be confusing to users when it comes to output names,
3170ad43ddacSmrg	     * so call it DVI
3171ad43ddacSmrg	     */
3172b7e1c893Smrg	    if ((conntype == CONNECTOR_DVI_D) ||
3173b7e1c893Smrg		(conntype == CONNECTOR_DVI_I) ||
3174ad43ddacSmrg		(conntype == CONNECTOR_DVI_A) ||
3175ad43ddacSmrg		(conntype == CONNECTOR_HDMI_TYPE_B)) {
3176b7e1c893Smrg		output = RADEONOutputCreate(pScrn, "DVI-%d", --num_dvi);
3177b7e1c893Smrg	    } else if (conntype == CONNECTOR_VGA) {
3178b7e1c893Smrg		output = RADEONOutputCreate(pScrn, "VGA-%d", --num_vga);
3179ad43ddacSmrg	    } else if (conntype == CONNECTOR_HDMI_TYPE_A) {
3180b7e1c893Smrg		output = RADEONOutputCreate(pScrn, "HDMI-%d", --num_hdmi);
3181b7e1c893Smrg	    } else if (conntype == CONNECTOR_DISPLAY_PORT) {
3182b7e1c893Smrg		output = RADEONOutputCreate(pScrn, "DisplayPort-%d", --num_dp);
3183ad43ddacSmrg	    } else if (conntype == CONNECTOR_EDP) {
3184ad43ddacSmrg		output = RADEONOutputCreate(pScrn, "eDP-%d", --num_edp);
3185b7e1c893Smrg	    } else {
3186b7e1c893Smrg		output = RADEONOutputCreate(pScrn,
3187b7e1c893Smrg					    ConnectorTypeName[conntype], 0);
3188b7e1c893Smrg	    }
3189209ff23fSmrg
3190209ff23fSmrg	    if (!output) {
3191209ff23fSmrg		return FALSE;
3192209ff23fSmrg	    }
31930974d292Smrg	    output->interlaceAllowed = TRUE;
31940974d292Smrg	    output->doubleScanAllowed = TRUE;
3195209ff23fSmrg	    output->driver_private = radeon_output;
3196ad43ddacSmrg	    if (IS_DCE4_VARIANT) {
3197ad43ddacSmrg		output->possible_crtcs = 0x3f;
3198ad43ddacSmrg	    } else {
3199ad43ddacSmrg		output->possible_crtcs = 1;
3200ad43ddacSmrg		/* crtc2 can drive LVDS, it just doesn't have RMX */
3201ad43ddacSmrg		if (!(radeon_output->devices & (ATOM_DEVICE_LCD_SUPPORT)))
3202ad43ddacSmrg		    output->possible_crtcs |= 2;
3203ad43ddacSmrg	    }
3204209ff23fSmrg
3205b7e1c893Smrg	    /* we can clone the DACs, and probably TV-out,
3206209ff23fSmrg	       but I'm not sure it's worth the trouble */
3207209ff23fSmrg	    output->possible_clones = 0;
3208209ff23fSmrg
3209209ff23fSmrg	    RADEONInitConnector(output);
3210209ff23fSmrg	}
3211209ff23fSmrg    }
3212209ff23fSmrg
3213209ff23fSmrg    for (i = 0; i < xf86_config->num_output; i++) {
3214209ff23fSmrg	xf86OutputPtr output = xf86_config->output[i];
3215209ff23fSmrg
3216209ff23fSmrg	output->possible_clones = radeon_output_clones(pScrn, output);
3217ad43ddacSmrg	RADEONGetHardCodedEDIDFromFile(output);
3218209ff23fSmrg    }
3219209ff23fSmrg
3220209ff23fSmrg    return TRUE;
3221209ff23fSmrg}
3222209ff23fSmrg
3223