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