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