atombios_output.c revision c503f109
1209ff23fSmrg/* 2209ff23fSmrg * Copyright © 2007 Red Hat, Inc. 3209ff23fSmrg * Copyright 2007 Advanced Micro Devices, Inc. 4209ff23fSmrg * 5209ff23fSmrg * Permission is hereby granted, free of charge, to any person obtaining a 6209ff23fSmrg * copy of this software and associated documentation files (the "Software"), 7209ff23fSmrg * to deal in the Software without restriction, including without limitation 8209ff23fSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9209ff23fSmrg * and/or sell copies of the Software, and to permit persons to whom the 10209ff23fSmrg * Software is furnished to do so, subject to the following conditions: 11209ff23fSmrg * 12209ff23fSmrg * The above copyright notice and this permission notice (including the next 13209ff23fSmrg * paragraph) shall be included in all copies or substantial portions of the 14209ff23fSmrg * Software. 15209ff23fSmrg * 16209ff23fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17209ff23fSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18209ff23fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19209ff23fSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20209ff23fSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21209ff23fSmrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22209ff23fSmrg * SOFTWARE. 23209ff23fSmrg * 24209ff23fSmrg * Authors: 25209ff23fSmrg * Dave Airlie <airlied@redhat.com> 26209ff23fSmrg * Alex Deucher <alexdeucher@gmail.com> 27209ff23fSmrg * 28209ff23fSmrg */ 29209ff23fSmrg 30209ff23fSmrg/* 31209ff23fSmrg * avivo output handling functions. 32209ff23fSmrg */ 33209ff23fSmrg#ifdef HAVE_CONFIG_H 34209ff23fSmrg#include "config.h" 35209ff23fSmrg#endif 36209ff23fSmrg/* DPMS */ 37c503f109Smrg#ifdef HAVE_XEXTPROTO_71 38c503f109Smrg#include <X11/extensions/dpmsconst.h> 39c503f109Smrg#else 40209ff23fSmrg#define DPMS_SERVER 41209ff23fSmrg#include <X11/extensions/dpms.h> 42c503f109Smrg#endif 43c503f109Smrg 44209ff23fSmrg#include <unistd.h> 45209ff23fSmrg 46209ff23fSmrg#include "radeon.h" 47209ff23fSmrg#include "radeon_reg.h" 48209ff23fSmrg#include "radeon_macros.h" 49209ff23fSmrg#include "radeon_atombios.h" 50209ff23fSmrg 51b7e1c893Smrg#include "ati_pciids_gen.h" 52b7e1c893Smrg 53b7e1c893Smrgconst char *device_name[12] = { 54b7e1c893Smrg "CRT1", 55b7e1c893Smrg "LCD1", 56b7e1c893Smrg "TV1", 57b7e1c893Smrg "DFP1", 58b7e1c893Smrg "CRT2", 59b7e1c893Smrg "LCD2", 60b7e1c893Smrg "TV2", 61b7e1c893Smrg "DFP2", 62b7e1c893Smrg "CV", 63b7e1c893Smrg "DFP3", 64b7e1c893Smrg "DFP4", 65b7e1c893Smrg "DFP5", 66b7e1c893Smrg}; 67b7e1c893Smrg 68c503f109Smrgstatic void atombios_set_output_crtc_source(xf86OutputPtr output); 69c503f109Smrg 70209ff23fSmrgstatic int 71b7e1c893Smrgatombios_output_dac_setup(xf86OutputPtr output, int action) 72209ff23fSmrg{ 73209ff23fSmrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 74209ff23fSmrg RADEONInfoPtr info = RADEONPTR(output->scrn); 75b7e1c893Smrg radeon_encoder_ptr radeon_encoder = radeon_get_encoder(output); 76b7e1c893Smrg radeon_tvout_ptr tvout = &radeon_output->tvout; 77209ff23fSmrg DAC_ENCODER_CONTROL_PS_ALLOCATION disp_data; 78209ff23fSmrg AtomBiosArgRec data; 79209ff23fSmrg unsigned char *space; 80b7e1c893Smrg int index = 0, num = 0; 81b7e1c893Smrg int clock = radeon_output->pixel_clock; 82b7e1c893Smrg 83b7e1c893Smrg if (radeon_encoder == NULL) 84b7e1c893Smrg return ATOM_NOT_IMPLEMENTED; 85b7e1c893Smrg 86b7e1c893Smrg memset(&disp_data,0, sizeof(disp_data)); 87b7e1c893Smrg 88b7e1c893Smrg switch (radeon_encoder->encoder_id) { 89b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_DAC1: 90b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 91b7e1c893Smrg index = GetIndexIntoMasterTable(COMMAND, DAC1EncoderControl); 92b7e1c893Smrg num = 1; 93b7e1c893Smrg break; 94b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_DAC2: 95b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 96b7e1c893Smrg index = GetIndexIntoMasterTable(COMMAND, DAC2EncoderControl); 97b7e1c893Smrg num = 2; 98b7e1c893Smrg break; 99b7e1c893Smrg } 100209ff23fSmrg 101b7e1c893Smrg disp_data.ucAction =action; 102209ff23fSmrg 103b7e1c893Smrg if (radeon_output->active_device & (ATOM_DEVICE_CRT_SUPPORT)) 104209ff23fSmrg disp_data.ucDacStandard = ATOM_DAC1_PS2; 105b7e1c893Smrg else if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT)) 106209ff23fSmrg disp_data.ucDacStandard = ATOM_DAC1_CV; 107b7e1c893Smrg else { 108b7e1c893Smrg switch (tvout->tvStd) { 109209ff23fSmrg case TV_STD_PAL: 110209ff23fSmrg case TV_STD_PAL_M: 111209ff23fSmrg case TV_STD_SCART_PAL: 112209ff23fSmrg case TV_STD_SECAM: 113209ff23fSmrg case TV_STD_PAL_CN: 114209ff23fSmrg disp_data.ucDacStandard = ATOM_DAC1_PAL; 115209ff23fSmrg break; 116209ff23fSmrg case TV_STD_NTSC: 117209ff23fSmrg case TV_STD_NTSC_J: 118209ff23fSmrg case TV_STD_PAL_60: 119209ff23fSmrg default: 120b7e1c893Smrg disp_data.ucDacStandard = ATOM_DAC1_NTSC; 121209ff23fSmrg break; 122209ff23fSmrg } 123209ff23fSmrg } 124b7e1c893Smrg disp_data.usPixelClock = cpu_to_le16(clock / 10); 125209ff23fSmrg 126b7e1c893Smrg data.exec.index = index; 127209ff23fSmrg data.exec.dataSpace = (void *)&space; 128209ff23fSmrg data.exec.pspace = &disp_data; 129209ff23fSmrg 130209ff23fSmrg if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { 131b7e1c893Smrg ErrorF("Output DAC%d setup success\n", num); 132209ff23fSmrg return ATOM_SUCCESS; 133209ff23fSmrg } 134209ff23fSmrg 135b7e1c893Smrg ErrorF("Output DAC%d setup failed\n", num); 136209ff23fSmrg return ATOM_NOT_IMPLEMENTED; 137209ff23fSmrg 138209ff23fSmrg} 139209ff23fSmrg 140209ff23fSmrgstatic int 141b7e1c893Smrgatombios_output_tv_setup(xf86OutputPtr output, int action) 142209ff23fSmrg{ 143209ff23fSmrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 144b7e1c893Smrg radeon_tvout_ptr tvout = &radeon_output->tvout; 145209ff23fSmrg RADEONInfoPtr info = RADEONPTR(output->scrn); 146209ff23fSmrg TV_ENCODER_CONTROL_PS_ALLOCATION disp_data; 147209ff23fSmrg AtomBiosArgRec data; 148209ff23fSmrg unsigned char *space; 149b7e1c893Smrg int clock = radeon_output->pixel_clock; 150b7e1c893Smrg 151b7e1c893Smrg memset(&disp_data,0, sizeof(disp_data)); 152209ff23fSmrg 153b7e1c893Smrg disp_data.sTVEncoder.ucAction = action; 154209ff23fSmrg 155b7e1c893Smrg if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT)) 156209ff23fSmrg disp_data.sTVEncoder.ucTvStandard = ATOM_TV_CV; 157209ff23fSmrg else { 158b7e1c893Smrg switch (tvout->tvStd) { 159209ff23fSmrg case TV_STD_NTSC: 160209ff23fSmrg disp_data.sTVEncoder.ucTvStandard = ATOM_TV_NTSC; 161209ff23fSmrg break; 162209ff23fSmrg case TV_STD_PAL: 163209ff23fSmrg disp_data.sTVEncoder.ucTvStandard = ATOM_TV_PAL; 164209ff23fSmrg break; 165209ff23fSmrg case TV_STD_PAL_M: 166209ff23fSmrg disp_data.sTVEncoder.ucTvStandard = ATOM_TV_PALM; 167209ff23fSmrg break; 168209ff23fSmrg case TV_STD_PAL_60: 169209ff23fSmrg disp_data.sTVEncoder.ucTvStandard = ATOM_TV_PAL60; 170209ff23fSmrg break; 171209ff23fSmrg case TV_STD_NTSC_J: 172209ff23fSmrg disp_data.sTVEncoder.ucTvStandard = ATOM_TV_NTSCJ; 173209ff23fSmrg break; 174209ff23fSmrg case TV_STD_SCART_PAL: 175209ff23fSmrg disp_data.sTVEncoder.ucTvStandard = ATOM_TV_PAL; /* ??? */ 176209ff23fSmrg break; 177209ff23fSmrg case TV_STD_SECAM: 178209ff23fSmrg disp_data.sTVEncoder.ucTvStandard = ATOM_TV_SECAM; 179209ff23fSmrg break; 180209ff23fSmrg case TV_STD_PAL_CN: 181209ff23fSmrg disp_data.sTVEncoder.ucTvStandard = ATOM_TV_PALCN; 182209ff23fSmrg break; 183209ff23fSmrg default: 184209ff23fSmrg disp_data.sTVEncoder.ucTvStandard = ATOM_TV_NTSC; 185209ff23fSmrg break; 186209ff23fSmrg } 187209ff23fSmrg } 188209ff23fSmrg 189b7e1c893Smrg disp_data.sTVEncoder.usPixelClock = cpu_to_le16(clock / 10); 190209ff23fSmrg data.exec.index = GetIndexIntoMasterTable(COMMAND, TVEncoderControl); 191209ff23fSmrg data.exec.dataSpace = (void *)&space; 192209ff23fSmrg data.exec.pspace = &disp_data; 193209ff23fSmrg 194209ff23fSmrg if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { 195b7e1c893Smrg ErrorF("Output TV setup success\n"); 196209ff23fSmrg return ATOM_SUCCESS; 197209ff23fSmrg } 198209ff23fSmrg 199b7e1c893Smrg ErrorF("Output TV setup failed\n"); 200209ff23fSmrg return ATOM_NOT_IMPLEMENTED; 201209ff23fSmrg 202209ff23fSmrg} 203209ff23fSmrg 204209ff23fSmrgint 205b7e1c893Smrgatombios_external_tmds_setup(xf86OutputPtr output, int action) 206209ff23fSmrg{ 207b7e1c893Smrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 208b7e1c893Smrg ScrnInfoPtr pScrn = output->scrn; 209b7e1c893Smrg RADEONInfoPtr info = RADEONPTR(pScrn); 210209ff23fSmrg ENABLE_EXTERNAL_TMDS_ENCODER_PS_ALLOCATION disp_data; 211209ff23fSmrg AtomBiosArgRec data; 212209ff23fSmrg unsigned char *space; 213b7e1c893Smrg int clock = radeon_output->pixel_clock; 214209ff23fSmrg 215b7e1c893Smrg memset(&disp_data,0, sizeof(disp_data)); 216209ff23fSmrg 217b7e1c893Smrg disp_data.sXTmdsEncoder.ucEnable = action; 218b7e1c893Smrg 219b7e1c893Smrg if (clock > 165000) 220b7e1c893Smrg disp_data.sXTmdsEncoder.ucMisc = PANEL_ENCODER_MISC_DUAL; 221209ff23fSmrg 222b7e1c893Smrg if (pScrn->rgbBits == 8) 223209ff23fSmrg disp_data.sXTmdsEncoder.ucMisc |= (1 << 1); 224209ff23fSmrg 225209ff23fSmrg data.exec.index = GetIndexIntoMasterTable(COMMAND, DVOEncoderControl); 226209ff23fSmrg data.exec.dataSpace = (void *)&space; 227209ff23fSmrg data.exec.pspace = &disp_data; 228209ff23fSmrg 229209ff23fSmrg if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { 230209ff23fSmrg ErrorF("External TMDS setup success\n"); 231209ff23fSmrg return ATOM_SUCCESS; 232209ff23fSmrg } 233209ff23fSmrg 234209ff23fSmrg ErrorF("External TMDS setup failed\n"); 235209ff23fSmrg return ATOM_NOT_IMPLEMENTED; 236209ff23fSmrg} 237209ff23fSmrg 238209ff23fSmrgstatic int 239b7e1c893Smrgatombios_output_ddia_setup(xf86OutputPtr output, int action) 240209ff23fSmrg{ 241b7e1c893Smrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 242209ff23fSmrg RADEONInfoPtr info = RADEONPTR(output->scrn); 243209ff23fSmrg DVO_ENCODER_CONTROL_PS_ALLOCATION disp_data; 244209ff23fSmrg AtomBiosArgRec data; 245209ff23fSmrg unsigned char *space; 246b7e1c893Smrg int clock = radeon_output->pixel_clock; 247b7e1c893Smrg 248b7e1c893Smrg memset(&disp_data,0, sizeof(disp_data)); 249209ff23fSmrg 250b7e1c893Smrg disp_data.sDVOEncoder.ucAction = action; 251b7e1c893Smrg disp_data.sDVOEncoder.usPixelClock = cpu_to_le16(clock / 10); 252209ff23fSmrg 253b7e1c893Smrg if (clock > 165000) 254209ff23fSmrg disp_data.sDVOEncoder.usDevAttr.sDigAttrib.ucAttribute = PANEL_ENCODER_MISC_DUAL; 255209ff23fSmrg 256209ff23fSmrg data.exec.index = GetIndexIntoMasterTable(COMMAND, DVOEncoderControl); 257209ff23fSmrg data.exec.dataSpace = (void *)&space; 258209ff23fSmrg data.exec.pspace = &disp_data; 259209ff23fSmrg 260209ff23fSmrg if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { 261209ff23fSmrg ErrorF("DDIA setup success\n"); 262209ff23fSmrg return ATOM_SUCCESS; 263209ff23fSmrg } 264209ff23fSmrg 265209ff23fSmrg ErrorF("DDIA setup failed\n"); 266209ff23fSmrg return ATOM_NOT_IMPLEMENTED; 267209ff23fSmrg} 268209ff23fSmrg 269209ff23fSmrgstatic int 270b7e1c893Smrgatombios_output_digital_setup(xf86OutputPtr output, int action) 271209ff23fSmrg{ 272b7e1c893Smrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 273b7e1c893Smrg ScrnInfoPtr pScrn = output->scrn; 274b7e1c893Smrg RADEONInfoPtr info = RADEONPTR(pScrn); 275b7e1c893Smrg radeon_encoder_ptr radeon_encoder = radeon_get_encoder(output); 276b7e1c893Smrg LVDS_ENCODER_CONTROL_PS_ALLOCATION disp_data; 277b7e1c893Smrg LVDS_ENCODER_CONTROL_PS_ALLOCATION_V2 disp_data2; 278209ff23fSmrg AtomBiosArgRec data; 279209ff23fSmrg unsigned char *space; 280b7e1c893Smrg int index = 0; 281b7e1c893Smrg int major, minor; 282b7e1c893Smrg int lvds_misc = 0; 283b7e1c893Smrg int clock = radeon_output->pixel_clock; 284209ff23fSmrg 285b7e1c893Smrg if (radeon_encoder == NULL) 286b7e1c893Smrg return ATOM_NOT_IMPLEMENTED; 287b7e1c893Smrg 288b7e1c893Smrg if (radeon_output->active_device & (ATOM_DEVICE_LCD_SUPPORT)) { 289b7e1c893Smrg radeon_lvds_ptr lvds = (radeon_lvds_ptr)radeon_encoder->dev_priv; 290b7e1c893Smrg if (lvds == NULL) 291b7e1c893Smrg return ATOM_NOT_IMPLEMENTED; 292b7e1c893Smrg lvds_misc = lvds->lvds_misc; 293b7e1c893Smrg } 294b7e1c893Smrg 295b7e1c893Smrg memset(&disp_data,0, sizeof(disp_data)); 296b7e1c893Smrg memset(&disp_data2,0, sizeof(disp_data2)); 297b7e1c893Smrg 298b7e1c893Smrg switch (radeon_encoder->encoder_id) { 299b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_LVDS: 300b7e1c893Smrg index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl); 301b7e1c893Smrg break; 302b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 303b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 304b7e1c893Smrg index = GetIndexIntoMasterTable(COMMAND, TMDS1EncoderControl); 305b7e1c893Smrg break; 306b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 307b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 308b7e1c893Smrg if (radeon_output->active_device & (ATOM_DEVICE_LCD_SUPPORT)) 309b7e1c893Smrg index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl); 310b7e1c893Smrg else 311b7e1c893Smrg index = GetIndexIntoMasterTable(COMMAND, TMDS2EncoderControl); 312b7e1c893Smrg break; 313b7e1c893Smrg } 314b7e1c893Smrg 315b7e1c893Smrg atombios_get_command_table_version(info->atomBIOS, index, &major, &minor); 316b7e1c893Smrg 317b7e1c893Smrg /*ErrorF("table is %d %d\n", major, minor);*/ 318b7e1c893Smrg switch (major) { 319b7e1c893Smrg case 0: 320b7e1c893Smrg case 1: 321b7e1c893Smrg case 2: 322b7e1c893Smrg switch (minor) { 323b7e1c893Smrg case 1: 324b7e1c893Smrg disp_data.ucMisc = 0; 325b7e1c893Smrg disp_data.ucAction = action; 326b7e1c893Smrg if ((radeon_output->ConnectorType == CONNECTOR_HDMI_TYPE_A) || 327b7e1c893Smrg (radeon_output->ConnectorType == CONNECTOR_HDMI_TYPE_B)) 328b7e1c893Smrg disp_data.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE; 329b7e1c893Smrg disp_data.usPixelClock = cpu_to_le16(clock / 10); 330b7e1c893Smrg if (radeon_output->active_device & (ATOM_DEVICE_LCD_SUPPORT)) { 331b7e1c893Smrg if (lvds_misc & (1 << 0)) 332b7e1c893Smrg disp_data.ucMisc |= PANEL_ENCODER_MISC_DUAL; 333b7e1c893Smrg if (lvds_misc & (1 << 1)) 334b7e1c893Smrg disp_data.ucMisc |= (1 << 1); 335b7e1c893Smrg } else { 336b7e1c893Smrg if (radeon_output->linkb) 337b7e1c893Smrg disp_data.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB; 338b7e1c893Smrg if (clock > 165000) 339b7e1c893Smrg disp_data.ucMisc |= PANEL_ENCODER_MISC_DUAL; 340b7e1c893Smrg if (pScrn->rgbBits == 8) 341b7e1c893Smrg disp_data.ucMisc |= (1 << 1); 342b7e1c893Smrg } 343b7e1c893Smrg data.exec.pspace = &disp_data; 344b7e1c893Smrg break; 345b7e1c893Smrg case 2: 346b7e1c893Smrg case 3: 347b7e1c893Smrg disp_data2.ucMisc = 0; 348b7e1c893Smrg disp_data2.ucAction = action; 349b7e1c893Smrg if (minor == 3) { 350b7e1c893Smrg if (radeon_output->coherent_mode) { 351b7e1c893Smrg disp_data2.ucMisc |= PANEL_ENCODER_MISC_COHERENT; 352b7e1c893Smrg xf86DrvMsg(output->scrn->scrnIndex, X_INFO, "Coherent Mode enabled\n"); 353b7e1c893Smrg } 354b7e1c893Smrg } 355b7e1c893Smrg if ((radeon_output->ConnectorType == CONNECTOR_HDMI_TYPE_A) || 356b7e1c893Smrg (radeon_output->ConnectorType == CONNECTOR_HDMI_TYPE_B)) 357b7e1c893Smrg disp_data2.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE; 358b7e1c893Smrg disp_data2.usPixelClock = cpu_to_le16(clock / 10); 359b7e1c893Smrg disp_data2.ucTruncate = 0; 360b7e1c893Smrg disp_data2.ucSpatial = 0; 361b7e1c893Smrg disp_data2.ucTemporal = 0; 362b7e1c893Smrg disp_data2.ucFRC = 0; 363b7e1c893Smrg if (radeon_output->active_device & (ATOM_DEVICE_LCD_SUPPORT)) { 364b7e1c893Smrg if (lvds_misc & (1 << 0)) 365b7e1c893Smrg disp_data2.ucMisc |= PANEL_ENCODER_MISC_DUAL; 366b7e1c893Smrg if (lvds_misc & (1 << 5)) { 367b7e1c893Smrg disp_data2.ucSpatial = PANEL_ENCODER_SPATIAL_DITHER_EN; 368b7e1c893Smrg if (lvds_misc & (1 << 1)) 369b7e1c893Smrg disp_data2.ucSpatial |= PANEL_ENCODER_SPATIAL_DITHER_DEPTH; 370b7e1c893Smrg } 371b7e1c893Smrg if (lvds_misc & (1 << 6)) { 372b7e1c893Smrg disp_data2.ucTemporal = PANEL_ENCODER_TEMPORAL_DITHER_EN; 373b7e1c893Smrg if (lvds_misc & (1 << 1)) 374b7e1c893Smrg disp_data2.ucTemporal |= PANEL_ENCODER_TEMPORAL_DITHER_DEPTH; 375b7e1c893Smrg if (((lvds_misc >> 2) & 0x3) == 2) 376b7e1c893Smrg disp_data2.ucTemporal |= PANEL_ENCODER_TEMPORAL_LEVEL_4; 377b7e1c893Smrg } 378b7e1c893Smrg } else { 379b7e1c893Smrg if (radeon_output->linkb) 380b7e1c893Smrg disp_data2.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB; 381b7e1c893Smrg if (clock > 165000) 382b7e1c893Smrg disp_data2.ucMisc |= PANEL_ENCODER_MISC_DUAL; 383b7e1c893Smrg } 384b7e1c893Smrg data.exec.pspace = &disp_data2; 385b7e1c893Smrg break; 386b7e1c893Smrg default: 387b7e1c893Smrg ErrorF("Unknown table version\n"); 388b7e1c893Smrg exit(-1); 389b7e1c893Smrg } 390b7e1c893Smrg break; 391b7e1c893Smrg default: 392b7e1c893Smrg ErrorF("Unknown table version\n"); 393b7e1c893Smrg exit(-1); 394b7e1c893Smrg } 395b7e1c893Smrg 396b7e1c893Smrg data.exec.index = index; 397209ff23fSmrg data.exec.dataSpace = (void *)&space; 398209ff23fSmrg 399209ff23fSmrg if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { 400b7e1c893Smrg ErrorF("Output digital setup success\n"); 401209ff23fSmrg return ATOM_SUCCESS; 402209ff23fSmrg } 403209ff23fSmrg 404b7e1c893Smrg ErrorF("Output digital setup failed\n"); 405209ff23fSmrg return ATOM_NOT_IMPLEMENTED; 406209ff23fSmrg} 407209ff23fSmrg 408209ff23fSmrgstatic int 409b7e1c893Smrgatombios_maybe_hdmi_mode(xf86OutputPtr output) 410209ff23fSmrg{ 411b7e1c893Smrg#ifndef EDID_COMPLETE_RAWDATA 412b7e1c893Smrg /* there's no getting this right unless we have complete EDID */ 413b7e1c893Smrg return ATOM_ENCODER_MODE_HDMI; 414b7e1c893Smrg#else 415b7e1c893Smrg if (output && xf86MonitorIsHDMI(output->MonInfo)) 416b7e1c893Smrg return ATOM_ENCODER_MODE_HDMI; 417b7e1c893Smrg 418b7e1c893Smrg return ATOM_ENCODER_MODE_DVI; 419b7e1c893Smrg#endif 420b7e1c893Smrg} 421209ff23fSmrg 422b7e1c893Smrgint 423b7e1c893Smrgatombios_get_encoder_mode(xf86OutputPtr output) 424b7e1c893Smrg{ 425b7e1c893Smrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 426209ff23fSmrg 427b7e1c893Smrg /* DVI should really be atombios_maybe_hdmi_mode() as well */ 428b7e1c893Smrg switch (radeon_output->ConnectorType) { 429b7e1c893Smrg case CONNECTOR_DVI_I: 430b7e1c893Smrg if (radeon_output->active_device & (ATOM_DEVICE_DFP_SUPPORT)) 431b7e1c893Smrg return ATOM_ENCODER_MODE_DVI; 432b7e1c893Smrg else 433b7e1c893Smrg return ATOM_ENCODER_MODE_CRT; 434b7e1c893Smrg break; 435b7e1c893Smrg case CONNECTOR_DVI_D: 436b7e1c893Smrg default: 437b7e1c893Smrg return ATOM_ENCODER_MODE_DVI; 438b7e1c893Smrg break; 439b7e1c893Smrg case CONNECTOR_HDMI_TYPE_A: 440b7e1c893Smrg case CONNECTOR_HDMI_TYPE_B: 441b7e1c893Smrg return atombios_maybe_hdmi_mode(output); 442b7e1c893Smrg break; 443b7e1c893Smrg case CONNECTOR_LVDS: 444b7e1c893Smrg return ATOM_ENCODER_MODE_LVDS; 445b7e1c893Smrg break; 446b7e1c893Smrg case CONNECTOR_DISPLAY_PORT: 447b7e1c893Smrg if (radeon_output->MonType == MT_DP) 448b7e1c893Smrg return ATOM_ENCODER_MODE_DP; 449b7e1c893Smrg else 450b7e1c893Smrg return atombios_maybe_hdmi_mode(output); 451b7e1c893Smrg break; 452b7e1c893Smrg case CONNECTOR_DVI_A: 453b7e1c893Smrg case CONNECTOR_VGA: 454b7e1c893Smrg case CONNECTOR_STV: 455b7e1c893Smrg case CONNECTOR_CTV: 456b7e1c893Smrg case CONNECTOR_DIN: 457b7e1c893Smrg if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT)) 458b7e1c893Smrg return ATOM_ENCODER_MODE_TV; 459b7e1c893Smrg else if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT)) 460b7e1c893Smrg return ATOM_ENCODER_MODE_CV; 461b7e1c893Smrg else 462b7e1c893Smrg return ATOM_ENCODER_MODE_CRT; 463b7e1c893Smrg break; 464209ff23fSmrg } 465209ff23fSmrg 466209ff23fSmrg} 467209ff23fSmrg 468b7e1c893Smrgstatic const int dp_clocks[] = { 469b7e1c893Smrg 16200, 470b7e1c893Smrg 27000, 471b7e1c893Smrg 32400, 472b7e1c893Smrg 54000, 473b7e1c893Smrg 0, 474b7e1c893Smrg 0, 475b7e1c893Smrg 64800, 476b7e1c893Smrg 108000, 477b7e1c893Smrg}; 478b7e1c893Smrgstatic const int num_dp_clocks = sizeof(dp_clocks) / sizeof(int); 479b7e1c893Smrg 480209ff23fSmrgstatic int 481b7e1c893Smrgdp_lanes_for_mode_clock(int mode_clock) 482209ff23fSmrg{ 483b7e1c893Smrg int i; 484b7e1c893Smrg 485b7e1c893Smrg for (i = 0; i < num_dp_clocks; i++) 486b7e1c893Smrg if (dp_clocks[i] > (mode_clock / 10)) 487b7e1c893Smrg return (i / 2) + 1; 488209ff23fSmrg 489b7e1c893Smrg return 0; 490b7e1c893Smrg} 491209ff23fSmrg 492b7e1c893Smrgstatic int 493b7e1c893Smrgdp_link_clock_for_mode_clock(int mode_clock) 494b7e1c893Smrg{ 495b7e1c893Smrg int i; 496209ff23fSmrg 497b7e1c893Smrg for (i = 0; i < num_dp_clocks; i++) 498b7e1c893Smrg if (dp_clocks[i] > (mode_clock / 10)) 499b7e1c893Smrg return (dp_clocks[i % 2]); 500b7e1c893Smrg 501b7e1c893Smrg return 0; 502209ff23fSmrg} 503209ff23fSmrg 504209ff23fSmrgstatic int 505b7e1c893Smrgatombios_output_dig_encoder_setup(xf86OutputPtr output, int action) 506209ff23fSmrg{ 507209ff23fSmrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 508209ff23fSmrg RADEONInfoPtr info = RADEONPTR(output->scrn); 509b7e1c893Smrg radeon_encoder_ptr radeon_encoder = radeon_get_encoder(output); 510209ff23fSmrg DIG_ENCODER_CONTROL_PS_ALLOCATION disp_data; 511209ff23fSmrg AtomBiosArgRec data; 512209ff23fSmrg unsigned char *space; 513b7e1c893Smrg int index = 0, major, minor, num = 0; 514b7e1c893Smrg int clock = radeon_output->pixel_clock; 515b7e1c893Smrg int dig_block = radeon_output->dig_block; 516b7e1c893Smrg 517b7e1c893Smrg if (radeon_encoder == NULL) 518b7e1c893Smrg return ATOM_NOT_IMPLEMENTED; 519b7e1c893Smrg 520b7e1c893Smrg memset(&disp_data,0, sizeof(disp_data)); 521b7e1c893Smrg 522b7e1c893Smrg if (IS_DCE32_VARIANT) { 523b7e1c893Smrg if (dig_block) 524b7e1c893Smrg index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl); 525b7e1c893Smrg else 526b7e1c893Smrg index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl); 527b7e1c893Smrg num = dig_block + 1; 528b7e1c893Smrg } else { 529b7e1c893Smrg switch (radeon_encoder->encoder_id) { 530b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 531b7e1c893Smrg index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl); 532b7e1c893Smrg num = 1; 533b7e1c893Smrg break; 534b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 535b7e1c893Smrg index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl); 536b7e1c893Smrg num = 2; 537b7e1c893Smrg break; 538b7e1c893Smrg } 539b7e1c893Smrg } 540209ff23fSmrg 541b7e1c893Smrg atombios_get_command_table_version(info->atomBIOS, index, &major, &minor); 542b7e1c893Smrg 543b7e1c893Smrg disp_data.ucAction = action; 544b7e1c893Smrg disp_data.usPixelClock = cpu_to_le16(clock / 10); 545b7e1c893Smrg 546b7e1c893Smrg if (IS_DCE32_VARIANT) { 547b7e1c893Smrg switch (radeon_encoder->encoder_id) { 548b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 549b7e1c893Smrg disp_data.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER1; 550b7e1c893Smrg break; 551b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 552b7e1c893Smrg disp_data.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER2; 553b7e1c893Smrg break; 554b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 555b7e1c893Smrg disp_data.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER3; 556b7e1c893Smrg break; 557b7e1c893Smrg } 558b7e1c893Smrg } else { 559b7e1c893Smrg switch (radeon_encoder->encoder_id) { 560b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 561b7e1c893Smrg disp_data.ucConfig = ATOM_ENCODER_CONFIG_UNIPHY; 562b7e1c893Smrg break; 563b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 564b7e1c893Smrg disp_data.ucConfig = ATOM_ENCODER_CONFIG_LVTMA; 565b7e1c893Smrg break; 566b7e1c893Smrg } 567209ff23fSmrg } 568209ff23fSmrg 569b7e1c893Smrg disp_data.ucEncoderMode = atombios_get_encoder_mode(output); 570b7e1c893Smrg 571b7e1c893Smrg if (disp_data.ucEncoderMode == ATOM_ENCODER_MODE_DP) { 572b7e1c893Smrg if (radeon_output->linkb) 573b7e1c893Smrg disp_data.ucConfig |= ATOM_ENCODER_CONFIG_LINKB; 574b7e1c893Smrg else 575b7e1c893Smrg disp_data.ucConfig |= ATOM_ENCODER_CONFIG_LINKA; 576b7e1c893Smrg 577b7e1c893Smrg if (dp_link_clock_for_mode_clock(clock) == 27000) 578b7e1c893Smrg disp_data.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ; 579b7e1c893Smrg 580b7e1c893Smrg disp_data.ucLaneNum = dp_lanes_for_mode_clock(clock); 581b7e1c893Smrg } else if (clock > 165000) { 582209ff23fSmrg disp_data.ucConfig |= ATOM_ENCODER_CONFIG_LINKA_B; 583209ff23fSmrg disp_data.ucLaneNum = 8; 584209ff23fSmrg } else { 585b7e1c893Smrg if (radeon_output->linkb) 586b7e1c893Smrg disp_data.ucConfig |= ATOM_ENCODER_CONFIG_LINKB; 587b7e1c893Smrg else 588b7e1c893Smrg disp_data.ucConfig |= ATOM_ENCODER_CONFIG_LINKA; 589b7e1c893Smrg 590209ff23fSmrg disp_data.ucLaneNum = 4; 591209ff23fSmrg } 592209ff23fSmrg 593b7e1c893Smrg data.exec.index = index; 594209ff23fSmrg data.exec.dataSpace = (void *)&space; 595209ff23fSmrg data.exec.pspace = &disp_data; 596209ff23fSmrg 597209ff23fSmrg if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { 598b7e1c893Smrg ErrorF("Output DIG%d encoder setup success\n", num); 599209ff23fSmrg return ATOM_SUCCESS; 600209ff23fSmrg } 601209ff23fSmrg 602b7e1c893Smrg ErrorF("Output DIG%d setup failed\n", num); 603209ff23fSmrg return ATOM_NOT_IMPLEMENTED; 604209ff23fSmrg 605209ff23fSmrg} 606209ff23fSmrg 607b7e1c893Smrgunion dig_transmitter_control { 608b7e1c893Smrg DIG_TRANSMITTER_CONTROL_PS_ALLOCATION v1; 609b7e1c893Smrg DIG_TRANSMITTER_CONTROL_PARAMETERS_V2 v2; 610b7e1c893Smrg}; 611b7e1c893Smrg 612209ff23fSmrgstatic int 613b7e1c893Smrgatombios_output_dig_transmitter_setup(xf86OutputPtr output, int action) 614209ff23fSmrg{ 615209ff23fSmrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 616209ff23fSmrg RADEONInfoPtr info = RADEONPTR(output->scrn); 617b7e1c893Smrg radeon_encoder_ptr radeon_encoder = radeon_get_encoder(output); 618b7e1c893Smrg union dig_transmitter_control disp_data; 619209ff23fSmrg AtomBiosArgRec data; 620209ff23fSmrg unsigned char *space; 621b7e1c893Smrg int index = 0, num = 0; 622b7e1c893Smrg int major, minor; 623b7e1c893Smrg int clock = radeon_output->pixel_clock; 624b7e1c893Smrg int dig_block = radeon_output->dig_block; 625b7e1c893Smrg 626b7e1c893Smrg if (radeon_encoder == NULL) 627b7e1c893Smrg return ATOM_NOT_IMPLEMENTED; 628b7e1c893Smrg 629b7e1c893Smrg memset(&disp_data,0, sizeof(disp_data)); 630b7e1c893Smrg 631b7e1c893Smrg if (IS_DCE32_VARIANT) 632b7e1c893Smrg index = GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl); 633b7e1c893Smrg else { 634b7e1c893Smrg switch (radeon_encoder->encoder_id) { 635b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 636b7e1c893Smrg index = GetIndexIntoMasterTable(COMMAND, DIG1TransmitterControl); 637b7e1c893Smrg break; 638b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 639b7e1c893Smrg index = GetIndexIntoMasterTable(COMMAND, DIG2TransmitterControl); 640b7e1c893Smrg break; 641b7e1c893Smrg } 642b7e1c893Smrg } 643209ff23fSmrg 644b7e1c893Smrg atombios_get_command_table_version(info->atomBIOS, index, &major, &minor); 645b7e1c893Smrg 646b7e1c893Smrg disp_data.v1.ucAction = action; 647b7e1c893Smrg 648b7e1c893Smrg if (IS_DCE32_VARIANT) { 649b7e1c893Smrg if (radeon_output->MonType == MT_DP) { 650b7e1c893Smrg disp_data.v2.usPixelClock = 651b7e1c893Smrg cpu_to_le16(dp_link_clock_for_mode_clock(clock)); 652b7e1c893Smrg disp_data.v2.acConfig.fDPConnector = 1; 653b7e1c893Smrg } else if (clock > 165000) { 654b7e1c893Smrg disp_data.v2.usPixelClock = cpu_to_le16((clock * 10 * 2) / 100); 655b7e1c893Smrg disp_data.v2.acConfig.fDualLinkConnector = 1; 656209ff23fSmrg } else { 657b7e1c893Smrg disp_data.v2.usPixelClock = cpu_to_le16((clock * 10 * 4) / 100); 658b7e1c893Smrg } 659b7e1c893Smrg if (dig_block) 660b7e1c893Smrg disp_data.v2.acConfig.ucEncoderSel = 1; 661b7e1c893Smrg 662b7e1c893Smrg switch (radeon_encoder->encoder_id) { 663b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 664b7e1c893Smrg disp_data.v2.acConfig.ucTransmitterSel = 0; 665b7e1c893Smrg num = 0; 666b7e1c893Smrg break; 667b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 668b7e1c893Smrg disp_data.v2.acConfig.ucTransmitterSel = 1; 669b7e1c893Smrg num = 1; 670b7e1c893Smrg break; 671b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 672b7e1c893Smrg disp_data.v2.acConfig.ucTransmitterSel = 2; 673b7e1c893Smrg num = 2; 674b7e1c893Smrg break; 675b7e1c893Smrg } 676b7e1c893Smrg 677b7e1c893Smrg if (radeon_output->active_device & (ATOM_DEVICE_DFP_SUPPORT)) { 678b7e1c893Smrg if (radeon_output->coherent_mode) { 679b7e1c893Smrg disp_data.v2.acConfig.fCoherentMode = 1; 680b7e1c893Smrg xf86DrvMsg(output->scrn->scrnIndex, X_INFO, "UNIPHY%d transmitter: Coherent Mode enabled\n",disp_data.v2.acConfig.ucTransmitterSel); 681b7e1c893Smrg } else 682b7e1c893Smrg xf86DrvMsg(output->scrn->scrnIndex, X_INFO, "UNIPHY%d transmitter: Coherent Mode disabled\n",disp_data.v2.acConfig.ucTransmitterSel); 683209ff23fSmrg } 684209ff23fSmrg } else { 685b7e1c893Smrg disp_data.v1.ucConfig = ATOM_TRANSMITTER_CONFIG_CLKSRC_PPLL; 686b7e1c893Smrg 687b7e1c893Smrg if (radeon_output->MonType == MT_DP) 688b7e1c893Smrg disp_data.v1.usPixelClock = 689b7e1c893Smrg cpu_to_le16(dp_link_clock_for_mode_clock(clock)); 690209ff23fSmrg else 691b7e1c893Smrg disp_data.v1.usPixelClock = cpu_to_le16((clock) / 10); 692b7e1c893Smrg 693b7e1c893Smrg switch (radeon_encoder->encoder_id) { 694b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 695b7e1c893Smrg disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER; 696b7e1c893Smrg if (info->IsIGP) { 697b7e1c893Smrg if (clock > 165000) { 698b7e1c893Smrg disp_data.v1.ucConfig |= (ATOM_TRANSMITTER_CONFIG_8LANE_LINK | 699b7e1c893Smrg ATOM_TRANSMITTER_CONFIG_LINKA_B); 700b7e1c893Smrg 701b7e1c893Smrg if (radeon_output->igp_lane_info & 0x3) 702b7e1c893Smrg disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_7; 703b7e1c893Smrg else if (radeon_output->igp_lane_info & 0xc) 704b7e1c893Smrg disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_15; 705b7e1c893Smrg } else { 706b7e1c893Smrg disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA; 707b7e1c893Smrg if (radeon_output->igp_lane_info & 0x1) 708b7e1c893Smrg disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_3; 709b7e1c893Smrg else if (radeon_output->igp_lane_info & 0x2) 710b7e1c893Smrg disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_4_7; 711b7e1c893Smrg else if (radeon_output->igp_lane_info & 0x4) 712b7e1c893Smrg disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_11; 713b7e1c893Smrg else if (radeon_output->igp_lane_info & 0x8) 714b7e1c893Smrg disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_12_15; 715b7e1c893Smrg } 716b7e1c893Smrg } else { 717b7e1c893Smrg if (clock > 165000) 718b7e1c893Smrg disp_data.v1.ucConfig |= (ATOM_TRANSMITTER_CONFIG_8LANE_LINK | 719b7e1c893Smrg ATOM_TRANSMITTER_CONFIG_LINKA_B | 720b7e1c893Smrg ATOM_TRANSMITTER_CONFIG_LANE_0_7); 721b7e1c893Smrg else { 722b7e1c893Smrg /* XXX */ 723b7e1c893Smrg if (radeon_output->linkb) 724b7e1c893Smrg disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB | ATOM_TRANSMITTER_CONFIG_LANE_0_3; 725b7e1c893Smrg else 726b7e1c893Smrg disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA | ATOM_TRANSMITTER_CONFIG_LANE_0_3; 727b7e1c893Smrg } 728b7e1c893Smrg } 729b7e1c893Smrg break; 730b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 731b7e1c893Smrg disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER; 732b7e1c893Smrg if (clock > 165000) 733b7e1c893Smrg disp_data.v1.ucConfig |= (ATOM_TRANSMITTER_CONFIG_8LANE_LINK | 734b7e1c893Smrg ATOM_TRANSMITTER_CONFIG_LINKA_B | 735b7e1c893Smrg ATOM_TRANSMITTER_CONFIG_LANE_0_7); 736b7e1c893Smrg else { 737b7e1c893Smrg /* XXX */ 738b7e1c893Smrg if (radeon_output->linkb) 739b7e1c893Smrg disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB | ATOM_TRANSMITTER_CONFIG_LANE_0_3; 740b7e1c893Smrg else 741b7e1c893Smrg disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA | ATOM_TRANSMITTER_CONFIG_LANE_0_3; 742b7e1c893Smrg } 743b7e1c893Smrg break; 744b7e1c893Smrg } 745209ff23fSmrg 746b7e1c893Smrg if (radeon_output->active_device & (ATOM_DEVICE_DFP_SUPPORT)) { 747b7e1c893Smrg if (radeon_output->coherent_mode && 748b7e1c893Smrg radeon_output->MonType != MT_DP) { 749b7e1c893Smrg disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT; 750b7e1c893Smrg xf86DrvMsg(output->scrn->scrnIndex, X_INFO, 751b7e1c893Smrg "DIG%d transmitter: Coherent Mode enabled\n", num); 752b7e1c893Smrg } else { 753b7e1c893Smrg xf86DrvMsg(output->scrn->scrnIndex, X_INFO, 754b7e1c893Smrg "DIG%d transmitter: Coherent Mode disabled\n", num); 755b7e1c893Smrg } 756b7e1c893Smrg } 757b7e1c893Smrg } 758209ff23fSmrg 759b7e1c893Smrg data.exec.index = index; 760209ff23fSmrg data.exec.dataSpace = (void *)&space; 761209ff23fSmrg data.exec.pspace = &disp_data; 762209ff23fSmrg 763209ff23fSmrg if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { 764b7e1c893Smrg if (IS_DCE32_VARIANT) 765b7e1c893Smrg ErrorF("Output UNIPHY%d transmitter setup success\n", num); 766b7e1c893Smrg else 767b7e1c893Smrg ErrorF("Output DIG%d transmitter setup success\n", num); 768209ff23fSmrg return ATOM_SUCCESS; 769209ff23fSmrg } 770209ff23fSmrg 771b7e1c893Smrg ErrorF("Output DIG%d transmitter setup failed\n", num); 772209ff23fSmrg return ATOM_NOT_IMPLEMENTED; 773209ff23fSmrg 774209ff23fSmrg} 775209ff23fSmrg 776c503f109Smrgstatic void atom_rv515_force_tv_scaler(ScrnInfoPtr pScrn, RADEONCrtcPrivatePtr radeon_crtc) 777b7e1c893Smrg{ 778b7e1c893Smrg RADEONInfoPtr info = RADEONPTR(pScrn); 779b7e1c893Smrg unsigned char *RADEONMMIO = info->MMIO; 780c503f109Smrg int index_reg = 0x6578, data_reg = 0x657c; 781c503f109Smrg 782c503f109Smrg index_reg += radeon_crtc->crtc_offset; 783c503f109Smrg data_reg += radeon_crtc->crtc_offset; 784c503f109Smrg 785c503f109Smrg OUTREG(0x659C + radeon_crtc->crtc_offset, 0x0); 786c503f109Smrg OUTREG(0x6594 + radeon_crtc->crtc_offset, 0x705); 787c503f109Smrg OUTREG(0x65A4 + radeon_crtc->crtc_offset, 0x10001); 788c503f109Smrg OUTREG(0x65D8 + radeon_crtc->crtc_offset, 0x0); 789c503f109Smrg OUTREG(0x65B0 + radeon_crtc->crtc_offset, 0x0); 790c503f109Smrg OUTREG(0x65C0 + radeon_crtc->crtc_offset, 0x0); 791c503f109Smrg OUTREG(0x65D4 + radeon_crtc->crtc_offset, 0x0); 792c503f109Smrg OUTREG(index_reg,0x0); 793c503f109Smrg OUTREG(data_reg,0x841880A8); 794c503f109Smrg OUTREG(index_reg,0x1); 795c503f109Smrg OUTREG(data_reg,0x84208680); 796c503f109Smrg OUTREG(index_reg,0x2); 797c503f109Smrg OUTREG(data_reg,0xBFF880B0); 798c503f109Smrg OUTREG(index_reg,0x100); 799c503f109Smrg OUTREG(data_reg,0x83D88088); 800c503f109Smrg OUTREG(index_reg,0x101); 801c503f109Smrg OUTREG(data_reg,0x84608680); 802c503f109Smrg OUTREG(index_reg,0x102); 803c503f109Smrg OUTREG(data_reg,0xBFF080D0); 804c503f109Smrg OUTREG(index_reg,0x200); 805c503f109Smrg OUTREG(data_reg,0x83988068); 806c503f109Smrg OUTREG(index_reg,0x201); 807c503f109Smrg OUTREG(data_reg,0x84A08680); 808c503f109Smrg OUTREG(index_reg,0x202); 809c503f109Smrg OUTREG(data_reg,0xBFF080F8); 810c503f109Smrg OUTREG(index_reg,0x300); 811c503f109Smrg OUTREG(data_reg,0x83588058); 812c503f109Smrg OUTREG(index_reg,0x301); 813c503f109Smrg OUTREG(data_reg,0x84E08660); 814c503f109Smrg OUTREG(index_reg,0x302); 815c503f109Smrg OUTREG(data_reg,0xBFF88120); 816c503f109Smrg OUTREG(index_reg,0x400); 817c503f109Smrg OUTREG(data_reg,0x83188040); 818c503f109Smrg OUTREG(index_reg,0x401); 819c503f109Smrg OUTREG(data_reg,0x85008660); 820c503f109Smrg OUTREG(index_reg,0x402); 821c503f109Smrg OUTREG(data_reg,0xBFF88150); 822c503f109Smrg OUTREG(index_reg,0x500); 823c503f109Smrg OUTREG(data_reg,0x82D88030); 824c503f109Smrg OUTREG(index_reg,0x501); 825c503f109Smrg OUTREG(data_reg,0x85408640); 826c503f109Smrg OUTREG(index_reg,0x502); 827c503f109Smrg OUTREG(data_reg,0xBFF88180); 828c503f109Smrg OUTREG(index_reg,0x600); 829c503f109Smrg OUTREG(data_reg,0x82A08018); 830c503f109Smrg OUTREG(index_reg,0x601); 831c503f109Smrg OUTREG(data_reg,0x85808620); 832c503f109Smrg OUTREG(index_reg,0x602); 833c503f109Smrg OUTREG(data_reg,0xBFF081B8); 834c503f109Smrg OUTREG(index_reg,0x700); 835c503f109Smrg OUTREG(data_reg,0x82608010); 836c503f109Smrg OUTREG(index_reg,0x701); 837c503f109Smrg OUTREG(data_reg,0x85A08600); 838c503f109Smrg OUTREG(index_reg,0x702); 839c503f109Smrg OUTREG(data_reg,0x800081F0); 840c503f109Smrg OUTREG(index_reg,0x800); 841c503f109Smrg OUTREG(data_reg,0x8228BFF8); 842c503f109Smrg OUTREG(index_reg,0x801); 843c503f109Smrg OUTREG(data_reg,0x85E085E0); 844c503f109Smrg OUTREG(index_reg,0x802); 845c503f109Smrg OUTREG(data_reg,0xBFF88228); 846c503f109Smrg OUTREG(index_reg,0x10000); 847c503f109Smrg OUTREG(data_reg,0x82A8BF00); 848c503f109Smrg OUTREG(index_reg,0x10001); 849c503f109Smrg OUTREG(data_reg,0x82A08CC0); 850c503f109Smrg OUTREG(index_reg,0x10002); 851c503f109Smrg OUTREG(data_reg,0x8008BEF8); 852c503f109Smrg OUTREG(index_reg,0x10100); 853c503f109Smrg OUTREG(data_reg,0x81F0BF28); 854c503f109Smrg OUTREG(index_reg,0x10101); 855c503f109Smrg OUTREG(data_reg,0x83608CA0); 856c503f109Smrg OUTREG(index_reg,0x10102); 857c503f109Smrg OUTREG(data_reg,0x8018BED0); 858c503f109Smrg OUTREG(index_reg,0x10200); 859c503f109Smrg OUTREG(data_reg,0x8148BF38); 860c503f109Smrg OUTREG(index_reg,0x10201); 861c503f109Smrg OUTREG(data_reg,0x84408C80); 862c503f109Smrg OUTREG(index_reg,0x10202); 863c503f109Smrg OUTREG(data_reg,0x8008BEB8); 864c503f109Smrg OUTREG(index_reg,0x10300); 865c503f109Smrg OUTREG(data_reg,0x80B0BF78); 866c503f109Smrg OUTREG(index_reg,0x10301); 867c503f109Smrg OUTREG(data_reg,0x85008C20); 868c503f109Smrg OUTREG(index_reg,0x10302); 869c503f109Smrg OUTREG(data_reg,0x8020BEA0); 870c503f109Smrg OUTREG(index_reg,0x10400); 871c503f109Smrg OUTREG(data_reg,0x8028BF90); 872c503f109Smrg OUTREG(index_reg,0x10401); 873c503f109Smrg OUTREG(data_reg,0x85E08BC0); 874c503f109Smrg OUTREG(index_reg,0x10402); 875c503f109Smrg OUTREG(data_reg,0x8018BE90); 876c503f109Smrg OUTREG(index_reg,0x10500); 877c503f109Smrg OUTREG(data_reg,0xBFB8BFB0); 878c503f109Smrg OUTREG(index_reg,0x10501); 879c503f109Smrg OUTREG(data_reg,0x86C08B40); 880c503f109Smrg OUTREG(index_reg,0x10502); 881c503f109Smrg OUTREG(data_reg,0x8010BE90); 882c503f109Smrg OUTREG(index_reg,0x10600); 883c503f109Smrg OUTREG(data_reg,0xBF58BFC8); 884c503f109Smrg OUTREG(index_reg,0x10601); 885c503f109Smrg OUTREG(data_reg,0x87A08AA0); 886c503f109Smrg OUTREG(index_reg,0x10602); 887c503f109Smrg OUTREG(data_reg,0x8010BE98); 888c503f109Smrg OUTREG(index_reg,0x10700); 889c503f109Smrg OUTREG(data_reg,0xBF10BFF0); 890c503f109Smrg OUTREG(index_reg,0x10701); 891c503f109Smrg OUTREG(data_reg,0x886089E0); 892c503f109Smrg OUTREG(index_reg,0x10702); 893c503f109Smrg OUTREG(data_reg,0x8018BEB0); 894c503f109Smrg OUTREG(index_reg,0x10800); 895c503f109Smrg OUTREG(data_reg,0xBED8BFE8); 896c503f109Smrg OUTREG(index_reg,0x10801); 897c503f109Smrg OUTREG(data_reg,0x89408940); 898c503f109Smrg OUTREG(index_reg,0x10802); 899c503f109Smrg OUTREG(data_reg,0xBFE8BED8); 900c503f109Smrg OUTREG(index_reg,0x20000); 901c503f109Smrg OUTREG(data_reg,0x80008000); 902c503f109Smrg OUTREG(index_reg,0x20001); 903c503f109Smrg OUTREG(data_reg,0x90008000); 904c503f109Smrg OUTREG(index_reg,0x20002); 905c503f109Smrg OUTREG(data_reg,0x80008000); 906c503f109Smrg OUTREG(index_reg,0x20003); 907c503f109Smrg OUTREG(data_reg,0x80008000); 908c503f109Smrg OUTREG(index_reg,0x20100); 909c503f109Smrg OUTREG(data_reg,0x80108000); 910c503f109Smrg OUTREG(index_reg,0x20101); 911c503f109Smrg OUTREG(data_reg,0x8FE0BF70); 912c503f109Smrg OUTREG(index_reg,0x20102); 913c503f109Smrg OUTREG(data_reg,0xBFE880C0); 914c503f109Smrg OUTREG(index_reg,0x20103); 915c503f109Smrg OUTREG(data_reg,0x80008000); 916c503f109Smrg OUTREG(index_reg,0x20200); 917c503f109Smrg OUTREG(data_reg,0x8018BFF8); 918c503f109Smrg OUTREG(index_reg,0x20201); 919c503f109Smrg OUTREG(data_reg,0x8F80BF08); 920c503f109Smrg OUTREG(index_reg,0x20202); 921c503f109Smrg OUTREG(data_reg,0xBFD081A0); 922c503f109Smrg OUTREG(index_reg,0x20203); 923c503f109Smrg OUTREG(data_reg,0xBFF88000); 924c503f109Smrg OUTREG(index_reg,0x20300); 925c503f109Smrg OUTREG(data_reg,0x80188000); 926c503f109Smrg OUTREG(index_reg,0x20301); 927c503f109Smrg OUTREG(data_reg,0x8EE0BEC0); 928c503f109Smrg OUTREG(index_reg,0x20302); 929c503f109Smrg OUTREG(data_reg,0xBFB082A0); 930c503f109Smrg OUTREG(index_reg,0x20303); 931c503f109Smrg OUTREG(data_reg,0x80008000); 932c503f109Smrg OUTREG(index_reg,0x20400); 933c503f109Smrg OUTREG(data_reg,0x80188000); 934c503f109Smrg OUTREG(index_reg,0x20401); 935c503f109Smrg OUTREG(data_reg,0x8E00BEA0); 936c503f109Smrg OUTREG(index_reg,0x20402); 937c503f109Smrg OUTREG(data_reg,0xBF8883C0); 938c503f109Smrg OUTREG(index_reg,0x20403); 939c503f109Smrg OUTREG(data_reg,0x80008000); 940c503f109Smrg OUTREG(index_reg,0x20500); 941c503f109Smrg OUTREG(data_reg,0x80188000); 942c503f109Smrg OUTREG(index_reg,0x20501); 943c503f109Smrg OUTREG(data_reg,0x8D00BE90); 944c503f109Smrg OUTREG(index_reg,0x20502); 945c503f109Smrg OUTREG(data_reg,0xBF588500); 946c503f109Smrg OUTREG(index_reg,0x20503); 947c503f109Smrg OUTREG(data_reg,0x80008008); 948c503f109Smrg OUTREG(index_reg,0x20600); 949c503f109Smrg OUTREG(data_reg,0x80188000); 950c503f109Smrg OUTREG(index_reg,0x20601); 951c503f109Smrg OUTREG(data_reg,0x8BC0BE98); 952c503f109Smrg OUTREG(index_reg,0x20602); 953c503f109Smrg OUTREG(data_reg,0xBF308660); 954c503f109Smrg OUTREG(index_reg,0x20603); 955c503f109Smrg OUTREG(data_reg,0x80008008); 956c503f109Smrg OUTREG(index_reg,0x20700); 957c503f109Smrg OUTREG(data_reg,0x80108000); 958c503f109Smrg OUTREG(index_reg,0x20701); 959c503f109Smrg OUTREG(data_reg,0x8A80BEB0); 960c503f109Smrg OUTREG(index_reg,0x20702); 961c503f109Smrg OUTREG(data_reg,0xBF0087C0); 962c503f109Smrg OUTREG(index_reg,0x20703); 963c503f109Smrg OUTREG(data_reg,0x80008008); 964c503f109Smrg OUTREG(index_reg,0x20800); 965c503f109Smrg OUTREG(data_reg,0x80108000); 966c503f109Smrg OUTREG(index_reg,0x20801); 967c503f109Smrg OUTREG(data_reg,0x8920BED0); 968c503f109Smrg OUTREG(index_reg,0x20802); 969c503f109Smrg OUTREG(data_reg,0xBED08920); 970c503f109Smrg OUTREG(index_reg,0x20803); 971c503f109Smrg OUTREG(data_reg,0x80008010); 972c503f109Smrg OUTREG(index_reg,0x30000); 973c503f109Smrg OUTREG(data_reg,0x90008000); 974c503f109Smrg OUTREG(index_reg,0x30001); 975c503f109Smrg OUTREG(data_reg,0x80008000); 976c503f109Smrg OUTREG(index_reg,0x30100); 977c503f109Smrg OUTREG(data_reg,0x8FE0BF90); 978c503f109Smrg OUTREG(index_reg,0x30101); 979c503f109Smrg OUTREG(data_reg,0xBFF880A0); 980c503f109Smrg OUTREG(index_reg,0x30200); 981c503f109Smrg OUTREG(data_reg,0x8F60BF40); 982c503f109Smrg OUTREG(index_reg,0x30201); 983c503f109Smrg OUTREG(data_reg,0xBFE88180); 984c503f109Smrg OUTREG(index_reg,0x30300); 985c503f109Smrg OUTREG(data_reg,0x8EC0BF00); 986c503f109Smrg OUTREG(index_reg,0x30301); 987c503f109Smrg OUTREG(data_reg,0xBFC88280); 988c503f109Smrg OUTREG(index_reg,0x30400); 989c503f109Smrg OUTREG(data_reg,0x8DE0BEE0); 990c503f109Smrg OUTREG(index_reg,0x30401); 991c503f109Smrg OUTREG(data_reg,0xBFA083A0); 992c503f109Smrg OUTREG(index_reg,0x30500); 993c503f109Smrg OUTREG(data_reg,0x8CE0BED0); 994c503f109Smrg OUTREG(index_reg,0x30501); 995c503f109Smrg OUTREG(data_reg,0xBF7884E0); 996c503f109Smrg OUTREG(index_reg,0x30600); 997c503f109Smrg OUTREG(data_reg,0x8BA0BED8); 998c503f109Smrg OUTREG(index_reg,0x30601); 999c503f109Smrg OUTREG(data_reg,0xBF508640); 1000c503f109Smrg OUTREG(index_reg,0x30700); 1001c503f109Smrg OUTREG(data_reg,0x8A60BEE8); 1002c503f109Smrg OUTREG(index_reg,0x30701); 1003c503f109Smrg OUTREG(data_reg,0xBF2087A0); 1004c503f109Smrg OUTREG(index_reg,0x30800); 1005c503f109Smrg OUTREG(data_reg,0x8900BF00); 1006c503f109Smrg OUTREG(index_reg,0x30801); 1007c503f109Smrg OUTREG(data_reg,0xBF008900); 1008b7e1c893Smrg} 1009b7e1c893Smrg 1010209ff23fSmrgstatic int 1011b7e1c893Smrgatombios_output_yuv_setup(xf86OutputPtr output, Bool enable) 1012209ff23fSmrg{ 1013209ff23fSmrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 1014209ff23fSmrg RADEONInfoPtr info = RADEONPTR(output->scrn); 1015b7e1c893Smrg RADEONCrtcPrivatePtr radeon_crtc = output->crtc->driver_private; 1016b7e1c893Smrg ENABLE_YUV_PS_ALLOCATION disp_data; 1017209ff23fSmrg AtomBiosArgRec data; 1018209ff23fSmrg unsigned char *space; 1019b7e1c893Smrg unsigned char *RADEONMMIO = info->MMIO; 1020b7e1c893Smrg uint32_t temp, reg; 1021209ff23fSmrg 1022b7e1c893Smrg if (info->ChipFamily >= CHIP_FAMILY_R600) 1023b7e1c893Smrg reg = R600_BIOS_3_SCRATCH; 1024b7e1c893Smrg else 1025b7e1c893Smrg reg = RADEON_BIOS_3_SCRATCH; 1026b7e1c893Smrg 1027b7e1c893Smrg //fix up scratch reg handling 1028b7e1c893Smrg temp = INREG(reg); 1029b7e1c893Smrg if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT)) 1030b7e1c893Smrg OUTREG(reg, (ATOM_S3_TV1_ACTIVE | 1031b7e1c893Smrg (radeon_crtc->crtc_id << 18))); 1032b7e1c893Smrg else if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT)) 1033b7e1c893Smrg OUTREG(reg, (ATOM_S3_CV_ACTIVE | 1034b7e1c893Smrg (radeon_crtc->crtc_id << 24))); 1035b7e1c893Smrg else 1036b7e1c893Smrg OUTREG(reg, 0); 1037209ff23fSmrg 1038b7e1c893Smrg memset(&disp_data, 0, sizeof(disp_data)); 1039209ff23fSmrg 1040b7e1c893Smrg if (enable) 1041b7e1c893Smrg disp_data.ucEnable = ATOM_ENABLE; 1042b7e1c893Smrg disp_data.ucCRTC = radeon_crtc->crtc_id; 1043209ff23fSmrg 1044b7e1c893Smrg data.exec.index = GetIndexIntoMasterTable(COMMAND, EnableYUV); 1045209ff23fSmrg data.exec.dataSpace = (void *)&space; 1046209ff23fSmrg data.exec.pspace = &disp_data; 1047209ff23fSmrg 1048209ff23fSmrg if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { 1049b7e1c893Smrg 1050b7e1c893Smrg OUTREG(reg, temp); 1051b7e1c893Smrg 1052b7e1c893Smrg ErrorF("crtc %d YUV %s setup success\n", radeon_crtc->crtc_id, enable ? "enable" : "disable"); 1053209ff23fSmrg return ATOM_SUCCESS; 1054209ff23fSmrg } 1055209ff23fSmrg 1056b7e1c893Smrg OUTREG(reg, temp); 1057b7e1c893Smrg 1058b7e1c893Smrg ErrorF("crtc %d YUV %s setup failed\n", radeon_crtc->crtc_id, enable ? "enable" : "disable"); 1059209ff23fSmrg return ATOM_NOT_IMPLEMENTED; 1060209ff23fSmrg 1061209ff23fSmrg} 1062209ff23fSmrg 1063209ff23fSmrgstatic int 1064b7e1c893Smrgatombios_output_overscan_setup(xf86OutputPtr output, DisplayModePtr mode, DisplayModePtr adjusted_mode) 1065209ff23fSmrg{ 1066209ff23fSmrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 1067b7e1c893Smrg RADEONCrtcPrivatePtr radeon_crtc = output->crtc->driver_private; 1068209ff23fSmrg RADEONInfoPtr info = RADEONPTR(output->scrn); 1069b7e1c893Smrg SET_CRTC_OVERSCAN_PS_ALLOCATION overscan_param; 1070209ff23fSmrg AtomBiosArgRec data; 1071209ff23fSmrg unsigned char *space; 1072b7e1c893Smrg memset(&overscan_param, 0, sizeof(overscan_param)); 1073209ff23fSmrg 1074b7e1c893Smrg overscan_param.usOverscanRight = 0; 1075b7e1c893Smrg overscan_param.usOverscanLeft = 0; 1076b7e1c893Smrg overscan_param.usOverscanBottom = 0; 1077b7e1c893Smrg overscan_param.usOverscanTop = 0; 1078b7e1c893Smrg overscan_param.ucCRTC = radeon_crtc->crtc_id; 1079b7e1c893Smrg 1080b7e1c893Smrg if (radeon_output->Flags & RADEON_USE_RMX) { 1081b7e1c893Smrg if (radeon_output->rmx_type == RMX_FULL) { 1082b7e1c893Smrg overscan_param.usOverscanRight = 0; 1083b7e1c893Smrg overscan_param.usOverscanLeft = 0; 1084b7e1c893Smrg overscan_param.usOverscanBottom = 0; 1085b7e1c893Smrg overscan_param.usOverscanTop = 0; 1086b7e1c893Smrg } else if (radeon_output->rmx_type == RMX_CENTER) { 1087b7e1c893Smrg overscan_param.usOverscanTop = (adjusted_mode->CrtcVDisplay - mode->CrtcVDisplay) / 2; 1088b7e1c893Smrg overscan_param.usOverscanBottom = (adjusted_mode->CrtcVDisplay - mode->CrtcVDisplay) / 2; 1089b7e1c893Smrg overscan_param.usOverscanLeft = (adjusted_mode->CrtcHDisplay - mode->CrtcHDisplay) / 2; 1090b7e1c893Smrg overscan_param.usOverscanRight = (adjusted_mode->CrtcHDisplay - mode->CrtcHDisplay) / 2; 1091b7e1c893Smrg } else if (radeon_output->rmx_type == RMX_ASPECT) { 1092b7e1c893Smrg int a1 = mode->CrtcVDisplay * adjusted_mode->CrtcHDisplay; 1093b7e1c893Smrg int a2 = adjusted_mode->CrtcVDisplay * mode->CrtcHDisplay; 1094b7e1c893Smrg 1095b7e1c893Smrg if (a1 > a2) { 1096b7e1c893Smrg overscan_param.usOverscanLeft = (adjusted_mode->CrtcHDisplay - (a2 / mode->CrtcVDisplay)) / 2; 1097b7e1c893Smrg overscan_param.usOverscanRight = (adjusted_mode->CrtcHDisplay - (a2 / mode->CrtcVDisplay)) / 2; 1098b7e1c893Smrg } else if (a2 > a1) { 1099b7e1c893Smrg overscan_param.usOverscanLeft = (adjusted_mode->CrtcVDisplay - (a1 / mode->CrtcHDisplay)) / 2; 1100b7e1c893Smrg overscan_param.usOverscanRight = (adjusted_mode->CrtcVDisplay - (a1 / mode->CrtcHDisplay)) / 2; 1101b7e1c893Smrg } 1102209ff23fSmrg } 1103209ff23fSmrg } 1104209ff23fSmrg 1105b7e1c893Smrg data.exec.index = GetIndexIntoMasterTable(COMMAND, SetCRTC_OverScan); 1106209ff23fSmrg data.exec.dataSpace = (void *)&space; 1107b7e1c893Smrg data.exec.pspace = &overscan_param; 1108209ff23fSmrg 1109209ff23fSmrg if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { 1110b7e1c893Smrg ErrorF("Set CRTC %d Overscan success\n", radeon_crtc->crtc_id); 1111b7e1c893Smrg return ATOM_SUCCESS ; 1112209ff23fSmrg } 1113209ff23fSmrg 1114b7e1c893Smrg ErrorF("Set CRTC %d Overscan failed\n", radeon_crtc->crtc_id); 1115209ff23fSmrg return ATOM_NOT_IMPLEMENTED; 1116209ff23fSmrg} 1117209ff23fSmrg 1118209ff23fSmrgstatic int 1119b7e1c893Smrgatombios_output_scaler_setup(xf86OutputPtr output) 1120209ff23fSmrg{ 1121209ff23fSmrg RADEONInfoPtr info = RADEONPTR(output->scrn); 1122209ff23fSmrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 1123b7e1c893Smrg radeon_tvout_ptr tvout = &radeon_output->tvout; 1124209ff23fSmrg RADEONCrtcPrivatePtr radeon_crtc = output->crtc->driver_private; 1125209ff23fSmrg ENABLE_SCALER_PS_ALLOCATION disp_data; 1126209ff23fSmrg AtomBiosArgRec data; 1127209ff23fSmrg unsigned char *space; 1128209ff23fSmrg 1129b7e1c893Smrg if (!IS_AVIVO_VARIANT && radeon_crtc->crtc_id) 1130b7e1c893Smrg return ATOM_SUCCESS; 1131b7e1c893Smrg 1132b7e1c893Smrg memset(&disp_data, 0, sizeof(disp_data)); 1133b7e1c893Smrg 1134209ff23fSmrg disp_data.ucScaler = radeon_crtc->crtc_id; 1135209ff23fSmrg 1136b7e1c893Smrg if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT)) { 1137b7e1c893Smrg switch (tvout->tvStd) { 1138b7e1c893Smrg case TV_STD_NTSC: 1139b7e1c893Smrg disp_data.ucTVStandard = ATOM_TV_NTSC; 1140b7e1c893Smrg break; 1141b7e1c893Smrg case TV_STD_PAL: 1142b7e1c893Smrg disp_data.ucTVStandard = ATOM_TV_PAL; 1143b7e1c893Smrg break; 1144b7e1c893Smrg case TV_STD_PAL_M: 1145b7e1c893Smrg disp_data.ucTVStandard = ATOM_TV_PALM; 1146b7e1c893Smrg break; 1147b7e1c893Smrg case TV_STD_PAL_60: 1148b7e1c893Smrg disp_data.ucTVStandard = ATOM_TV_PAL60; 1149b7e1c893Smrg break; 1150b7e1c893Smrg case TV_STD_NTSC_J: 1151b7e1c893Smrg disp_data.ucTVStandard = ATOM_TV_NTSCJ; 1152b7e1c893Smrg break; 1153b7e1c893Smrg case TV_STD_SCART_PAL: 1154b7e1c893Smrg disp_data.ucTVStandard = ATOM_TV_PAL; /* ??? */ 1155b7e1c893Smrg break; 1156b7e1c893Smrg case TV_STD_SECAM: 1157b7e1c893Smrg disp_data.ucTVStandard = ATOM_TV_SECAM; 1158b7e1c893Smrg break; 1159b7e1c893Smrg case TV_STD_PAL_CN: 1160b7e1c893Smrg disp_data.ucTVStandard = ATOM_TV_PALCN; 1161b7e1c893Smrg break; 1162b7e1c893Smrg default: 1163b7e1c893Smrg disp_data.ucTVStandard = ATOM_TV_NTSC; 1164b7e1c893Smrg break; 1165b7e1c893Smrg } 1166b7e1c893Smrg disp_data.ucEnable = SCALER_ENABLE_MULTITAP_MODE; 1167b7e1c893Smrg ErrorF("Using TV scaler %x %x\n", disp_data.ucTVStandard, disp_data.ucEnable); 1168b7e1c893Smrg } else if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT)) { 1169b7e1c893Smrg disp_data.ucTVStandard = ATOM_TV_CV; 1170b7e1c893Smrg disp_data.ucEnable = SCALER_ENABLE_MULTITAP_MODE; 1171b7e1c893Smrg ErrorF("Using CV scaler %x %x\n", disp_data.ucTVStandard, disp_data.ucEnable); 1172b7e1c893Smrg } else if (radeon_output->Flags & RADEON_USE_RMX) { 1173209ff23fSmrg ErrorF("Using RMX\n"); 1174209ff23fSmrg if (radeon_output->rmx_type == RMX_FULL) 1175209ff23fSmrg disp_data.ucEnable = ATOM_SCALER_EXPANSION; 1176209ff23fSmrg else if (radeon_output->rmx_type == RMX_CENTER) 1177209ff23fSmrg disp_data.ucEnable = ATOM_SCALER_CENTER; 1178b7e1c893Smrg else if (radeon_output->rmx_type == RMX_ASPECT) 1179b7e1c893Smrg disp_data.ucEnable = ATOM_SCALER_EXPANSION; 1180209ff23fSmrg } else { 1181209ff23fSmrg ErrorF("Not using RMX\n"); 1182b7e1c893Smrg if (IS_AVIVO_VARIANT) 1183b7e1c893Smrg disp_data.ucEnable = ATOM_SCALER_DISABLE; 1184b7e1c893Smrg else 1185b7e1c893Smrg disp_data.ucEnable = ATOM_SCALER_CENTER; 1186209ff23fSmrg } 1187209ff23fSmrg 1188209ff23fSmrg data.exec.index = GetIndexIntoMasterTable(COMMAND, EnableScaler); 1189209ff23fSmrg data.exec.dataSpace = (void *)&space; 1190209ff23fSmrg data.exec.pspace = &disp_data; 1191209ff23fSmrg 1192209ff23fSmrg if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { 1193b7e1c893Smrg if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT) 1194b7e1c893Smrg && info->ChipFamily >= CHIP_FAMILY_RV515 && info->ChipFamily <= CHIP_FAMILY_RV570) { 1195b7e1c893Smrg ErrorF("forcing TV scaler\n"); 1196c503f109Smrg atom_rv515_force_tv_scaler(output->scrn, radeon_crtc); 1197b7e1c893Smrg } 1198209ff23fSmrg ErrorF("scaler %d setup success\n", radeon_crtc->crtc_id); 1199209ff23fSmrg return ATOM_SUCCESS; 1200209ff23fSmrg } 1201209ff23fSmrg 1202209ff23fSmrg ErrorF("scaler %d setup failed\n", radeon_crtc->crtc_id); 1203209ff23fSmrg return ATOM_NOT_IMPLEMENTED; 1204209ff23fSmrg 1205209ff23fSmrg} 1206209ff23fSmrg 1207b7e1c893Smrgvoid 1208b7e1c893Smrgatombios_output_dpms(xf86OutputPtr output, int mode) 1209209ff23fSmrg{ 1210b7e1c893Smrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 1211b7e1c893Smrg radeon_encoder_ptr radeon_encoder = radeon_get_encoder(output); 1212209ff23fSmrg RADEONInfoPtr info = RADEONPTR(output->scrn); 1213209ff23fSmrg DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION disp_data; 1214209ff23fSmrg AtomBiosArgRec data; 1215209ff23fSmrg unsigned char *space; 1216209ff23fSmrg int index = 0; 1217b7e1c893Smrg Bool is_dig = FALSE; 1218209ff23fSmrg 1219b7e1c893Smrg if (radeon_encoder == NULL) 1220b7e1c893Smrg return; 1221b7e1c893Smrg 1222b7e1c893Smrg switch (radeon_encoder->encoder_id) { 1223b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 1224b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 1225209ff23fSmrg index = GetIndexIntoMasterTable(COMMAND, TMDSAOutputControl); 1226209ff23fSmrg break; 1227b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 1228b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 1229b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 1230b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 1231b7e1c893Smrg is_dig = TRUE; 1232209ff23fSmrg break; 1233b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_DVO1: 1234b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_DDI: 1235b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 1236b7e1c893Smrg index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl); 1237209ff23fSmrg break; 1238b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_LVDS: 1239209ff23fSmrg index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl); 1240209ff23fSmrg break; 1241b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 1242b7e1c893Smrg if (radeon_output->active_device & (ATOM_DEVICE_LCD_SUPPORT)) 1243b7e1c893Smrg index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl); 1244b7e1c893Smrg else 1245b7e1c893Smrg index = GetIndexIntoMasterTable(COMMAND, LVTMAOutputControl); 1246209ff23fSmrg break; 1247b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_DAC1: 1248b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 1249b7e1c893Smrg if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT)) 1250b7e1c893Smrg index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl); 1251b7e1c893Smrg else if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT)) 1252b7e1c893Smrg index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl); 1253b7e1c893Smrg else 1254b7e1c893Smrg index = GetIndexIntoMasterTable(COMMAND, DAC1OutputControl); 1255209ff23fSmrg break; 1256b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_DAC2: 1257b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 1258b7e1c893Smrg if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT)) 1259b7e1c893Smrg index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl); 1260b7e1c893Smrg else if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT)) 1261b7e1c893Smrg index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl); 1262b7e1c893Smrg else 1263b7e1c893Smrg index = GetIndexIntoMasterTable(COMMAND, DAC2OutputControl); 1264209ff23fSmrg break; 1265209ff23fSmrg } 1266209ff23fSmrg 1267209ff23fSmrg switch (mode) { 1268209ff23fSmrg case DPMSModeOn: 1269b7e1c893Smrg radeon_encoder->devices |= radeon_output->active_device; 1270b7e1c893Smrg if (is_dig) 1271b7e1c893Smrg atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT); 1272b7e1c893Smrg else { 1273b7e1c893Smrg disp_data.ucAction = ATOM_ENABLE; 1274b7e1c893Smrg data.exec.index = index; 1275b7e1c893Smrg data.exec.dataSpace = (void *)&space; 1276b7e1c893Smrg data.exec.pspace = &disp_data; 1277b7e1c893Smrg 1278b7e1c893Smrg if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) 1279b7e1c893Smrg ErrorF("Output %s enable success\n", 1280b7e1c893Smrg device_name[radeon_get_device_index(radeon_output->active_device)]); 1281b7e1c893Smrg else 1282b7e1c893Smrg ErrorF("Output %s enable failed\n", 1283b7e1c893Smrg device_name[radeon_get_device_index(radeon_output->active_device)]); 1284b7e1c893Smrg } 1285c503f109Smrg /* at least for TV atom fails to reassociate the correct crtc source at dpms on */ 1286c503f109Smrg if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT)) 1287c503f109Smrg atombios_set_output_crtc_source(output); 1288209ff23fSmrg break; 1289209ff23fSmrg case DPMSModeStandby: 1290209ff23fSmrg case DPMSModeSuspend: 1291209ff23fSmrg case DPMSModeOff: 1292b7e1c893Smrg radeon_encoder->devices &= ~(radeon_output->active_device); 1293b7e1c893Smrg if (!radeon_encoder->devices) { 1294b7e1c893Smrg if (is_dig) 1295b7e1c893Smrg atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT); 1296b7e1c893Smrg else { 1297b7e1c893Smrg disp_data.ucAction = ATOM_DISABLE; 1298b7e1c893Smrg data.exec.index = index; 1299b7e1c893Smrg data.exec.dataSpace = (void *)&space; 1300b7e1c893Smrg data.exec.pspace = &disp_data; 1301b7e1c893Smrg 1302b7e1c893Smrg if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) 1303b7e1c893Smrg == ATOM_SUCCESS) 1304b7e1c893Smrg ErrorF("Output %s disable success\n", 1305b7e1c893Smrg device_name[radeon_get_device_index(radeon_output->active_device)]); 1306b7e1c893Smrg else 1307b7e1c893Smrg ErrorF("Output %s disable failed\n", 1308b7e1c893Smrg device_name[radeon_get_device_index(radeon_output->active_device)]); 1309b7e1c893Smrg } 1310209ff23fSmrg } 1311b7e1c893Smrg break; 1312209ff23fSmrg } 1313209ff23fSmrg} 1314209ff23fSmrg 1315209ff23fSmrgstatic void 1316209ff23fSmrgatombios_set_output_crtc_source(xf86OutputPtr output) 1317209ff23fSmrg{ 1318209ff23fSmrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 1319209ff23fSmrg RADEONCrtcPrivatePtr radeon_crtc = output->crtc->driver_private; 1320209ff23fSmrg RADEONInfoPtr info = RADEONPTR(output->scrn); 1321b7e1c893Smrg radeon_encoder_ptr radeon_encoder = radeon_get_encoder(output); 1322209ff23fSmrg AtomBiosArgRec data; 1323209ff23fSmrg unsigned char *space; 1324209ff23fSmrg SELECT_CRTC_SOURCE_PS_ALLOCATION crtc_src_param; 1325209ff23fSmrg SELECT_CRTC_SOURCE_PARAMETERS_V2 crtc_src_param2; 1326209ff23fSmrg int index = GetIndexIntoMasterTable(COMMAND, SelectCRTC_Source); 1327209ff23fSmrg int major, minor; 1328209ff23fSmrg 1329b7e1c893Smrg if (radeon_encoder == NULL) 1330b7e1c893Smrg return; 1331b7e1c893Smrg 1332b7e1c893Smrg memset(&crtc_src_param, 0, sizeof(crtc_src_param)); 1333b7e1c893Smrg memset(&crtc_src_param2, 0, sizeof(crtc_src_param2)); 1334209ff23fSmrg atombios_get_command_table_version(info->atomBIOS, index, &major, &minor); 1335209ff23fSmrg 1336209ff23fSmrg /*ErrorF("select crtc source table is %d %d\n", major, minor);*/ 1337209ff23fSmrg 1338209ff23fSmrg switch(major) { 1339b7e1c893Smrg case 1: 1340209ff23fSmrg switch(minor) { 1341209ff23fSmrg case 0: 1342209ff23fSmrg case 1: 1343209ff23fSmrg default: 1344b7e1c893Smrg if (IS_AVIVO_VARIANT) 1345b7e1c893Smrg crtc_src_param.ucCRTC = radeon_crtc->crtc_id; 1346b7e1c893Smrg else { 1347b7e1c893Smrg if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1) 1348b7e1c893Smrg crtc_src_param.ucCRTC = radeon_crtc->crtc_id; 1349b7e1c893Smrg else 1350b7e1c893Smrg crtc_src_param.ucCRTC = radeon_crtc->crtc_id << 2; 1351b7e1c893Smrg } 1352b7e1c893Smrg switch (radeon_encoder->encoder_id) { 1353b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 1354b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 1355b7e1c893Smrg crtc_src_param.ucDevice = ATOM_DEVICE_DFP1_INDEX; 1356b7e1c893Smrg break; 1357b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_LVDS: 1358b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 1359b7e1c893Smrg if (radeon_output->active_device & ATOM_DEVICE_LCD1_SUPPORT) 1360209ff23fSmrg crtc_src_param.ucDevice = ATOM_DEVICE_LCD1_INDEX; 1361b7e1c893Smrg else 1362b7e1c893Smrg crtc_src_param.ucDevice = ATOM_DEVICE_DFP3_INDEX; 1363b7e1c893Smrg break; 1364b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_DVO1: 1365b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_DDI: 1366b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 1367b7e1c893Smrg crtc_src_param.ucDevice = ATOM_DEVICE_DFP2_INDEX; 1368b7e1c893Smrg break; 1369b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_DAC1: 1370b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 1371b7e1c893Smrg if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT)) 1372b7e1c893Smrg crtc_src_param.ucDevice = ATOM_DEVICE_TV1_INDEX; 1373b7e1c893Smrg else if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT)) 1374b7e1c893Smrg crtc_src_param.ucDevice = ATOM_DEVICE_CV_INDEX; 1375b7e1c893Smrg else 1376b7e1c893Smrg crtc_src_param.ucDevice = ATOM_DEVICE_CRT1_INDEX; 1377b7e1c893Smrg break; 1378b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_DAC2: 1379b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 1380b7e1c893Smrg if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT)) 1381209ff23fSmrg crtc_src_param.ucDevice = ATOM_DEVICE_TV1_INDEX; 1382b7e1c893Smrg else if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT)) 1383209ff23fSmrg crtc_src_param.ucDevice = ATOM_DEVICE_CV_INDEX; 1384b7e1c893Smrg else 1385b7e1c893Smrg crtc_src_param.ucDevice = ATOM_DEVICE_CRT2_INDEX; 1386b7e1c893Smrg break; 1387209ff23fSmrg } 1388209ff23fSmrg data.exec.pspace = &crtc_src_param; 1389209ff23fSmrg /*ErrorF("device sourced: 0x%x\n", crtc_src_param.ucDevice);*/ 1390209ff23fSmrg break; 1391209ff23fSmrg case 2: 1392209ff23fSmrg crtc_src_param2.ucCRTC = radeon_crtc->crtc_id; 1393b7e1c893Smrg crtc_src_param2.ucEncodeMode = atombios_get_encoder_mode(output); 1394b7e1c893Smrg switch (radeon_encoder->encoder_id) { 1395b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 1396b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 1397b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 1398b7e1c893Smrg if (IS_DCE32_VARIANT) { 1399b7e1c893Smrg if (radeon_crtc->crtc_id) 1400b7e1c893Smrg crtc_src_param2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID; 1401b7e1c893Smrg else 1402b7e1c893Smrg crtc_src_param2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID; 1403b7e1c893Smrg } else 1404b7e1c893Smrg crtc_src_param2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID; 1405b7e1c893Smrg break; 1406b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 1407b7e1c893Smrg crtc_src_param2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID; 1408b7e1c893Smrg break; 1409b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 1410b7e1c893Smrg if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT)) 1411b7e1c893Smrg crtc_src_param2.ucEncoderID = ASIC_INT_TV_ENCODER_ID; 1412b7e1c893Smrg else if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT)) 1413b7e1c893Smrg crtc_src_param2.ucEncoderID = ASIC_INT_TV_ENCODER_ID; 1414b7e1c893Smrg else 1415b7e1c893Smrg crtc_src_param2.ucEncoderID = ASIC_INT_DAC1_ENCODER_ID; 1416b7e1c893Smrg break; 1417b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 1418b7e1c893Smrg if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT)) 1419b7e1c893Smrg crtc_src_param2.ucEncoderID = ASIC_INT_TV_ENCODER_ID; 1420b7e1c893Smrg else if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT)) 1421b7e1c893Smrg crtc_src_param2.ucEncoderID = ASIC_INT_TV_ENCODER_ID; 1422b7e1c893Smrg else 1423b7e1c893Smrg crtc_src_param2.ucEncoderID = ASIC_INT_DAC2_ENCODER_ID; 1424b7e1c893Smrg break; 1425209ff23fSmrg } 1426209ff23fSmrg data.exec.pspace = &crtc_src_param2; 1427209ff23fSmrg /*ErrorF("device sourced: 0x%x\n", crtc_src_param2.ucEncoderID);*/ 1428209ff23fSmrg break; 1429209ff23fSmrg } 1430209ff23fSmrg break; 1431209ff23fSmrg default: 1432b7e1c893Smrg ErrorF("Unknown table version\n"); 1433b7e1c893Smrg exit(-1); 1434209ff23fSmrg } 1435209ff23fSmrg 1436209ff23fSmrg data.exec.index = index; 1437209ff23fSmrg data.exec.dataSpace = (void *)&space; 1438209ff23fSmrg 1439209ff23fSmrg if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { 1440209ff23fSmrg ErrorF("Set CRTC %d Source success\n", radeon_crtc->crtc_id); 1441209ff23fSmrg return; 1442209ff23fSmrg } 1443209ff23fSmrg 1444209ff23fSmrg ErrorF("Set CRTC Source failed\n"); 1445209ff23fSmrg return; 1446209ff23fSmrg} 1447209ff23fSmrg 1448b7e1c893Smrgstatic void 1449b7e1c893Smrgatombios_apply_output_quirks(xf86OutputPtr output, DisplayModePtr mode) 1450b7e1c893Smrg{ 1451b7e1c893Smrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 1452b7e1c893Smrg RADEONCrtcPrivatePtr radeon_crtc = output->crtc->driver_private; 1453b7e1c893Smrg RADEONInfoPtr info = RADEONPTR(output->scrn); 1454b7e1c893Smrg unsigned char *RADEONMMIO = info->MMIO; 1455b7e1c893Smrg 1456b7e1c893Smrg /* Funky macbooks */ 1457b7e1c893Smrg if ((info->Chipset == PCI_CHIP_RV530_71C5) && 1458b7e1c893Smrg (PCI_SUB_VENDOR_ID(info->PciInfo) == 0x106b) && 1459b7e1c893Smrg (PCI_SUB_DEVICE_ID(info->PciInfo) == 0x0080)) { 1460b7e1c893Smrg if (radeon_output->MonType == MT_LCD) { 1461b7e1c893Smrg if (radeon_output->devices & ATOM_DEVICE_LCD1_SUPPORT) { 1462b7e1c893Smrg uint32_t lvtma_bit_depth_control = INREG(AVIVO_LVTMA_BIT_DEPTH_CONTROL); 1463b7e1c893Smrg 1464b7e1c893Smrg lvtma_bit_depth_control &= ~AVIVO_LVTMA_BIT_DEPTH_CONTROL_TRUNCATE_EN; 1465b7e1c893Smrg lvtma_bit_depth_control &= ~AVIVO_LVTMA_BIT_DEPTH_CONTROL_SPATIAL_DITHER_EN; 1466b7e1c893Smrg 1467b7e1c893Smrg OUTREG(AVIVO_LVTMA_BIT_DEPTH_CONTROL, lvtma_bit_depth_control); 1468b7e1c893Smrg } 1469b7e1c893Smrg } 1470b7e1c893Smrg } 1471b7e1c893Smrg 1472b7e1c893Smrg /* set scaler clears this on some chips */ 1473b7e1c893Smrg if (IS_AVIVO_VARIANT && (mode->Flags & V_INTERLACE)) 1474b7e1c893Smrg OUTREG(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset, AVIVO_D1MODE_INTERLEAVE_EN); 1475b7e1c893Smrg} 1476b7e1c893Smrg 1477209ff23fSmrgvoid 1478209ff23fSmrgatombios_output_mode_set(xf86OutputPtr output, 1479209ff23fSmrg DisplayModePtr mode, 1480209ff23fSmrg DisplayModePtr adjusted_mode) 1481209ff23fSmrg{ 1482209ff23fSmrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 1483b7e1c893Smrg RADEONCrtcPrivatePtr radeon_crtc = output->crtc->driver_private; 1484b7e1c893Smrg radeon_encoder_ptr radeon_encoder = radeon_get_encoder(output); 1485209ff23fSmrg RADEONInfoPtr info = RADEONPTR(output->scrn); 1486b7e1c893Smrg if (radeon_encoder == NULL) 1487b7e1c893Smrg return; 1488209ff23fSmrg 1489b7e1c893Smrg radeon_output->pixel_clock = adjusted_mode->Clock; 1490b7e1c893Smrg radeon_output->dig_block = radeon_crtc->crtc_id; 1491b7e1c893Smrg atombios_output_overscan_setup(output, mode, adjusted_mode); 1492b7e1c893Smrg atombios_output_scaler_setup(output); 1493209ff23fSmrg atombios_set_output_crtc_source(output); 1494209ff23fSmrg 1495b7e1c893Smrg if (IS_AVIVO_VARIANT) { 1496b7e1c893Smrg if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT)) 1497b7e1c893Smrg atombios_output_yuv_setup(output, TRUE); 1498b7e1c893Smrg else 1499b7e1c893Smrg atombios_output_yuv_setup(output, FALSE); 1500209ff23fSmrg } 1501209ff23fSmrg 1502b7e1c893Smrg switch (radeon_encoder->encoder_id) { 1503b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 1504b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 1505b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_LVDS: 1506b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 1507b7e1c893Smrg atombios_output_digital_setup(output, PANEL_ENCODER_ACTION_ENABLE); 1508b7e1c893Smrg break; 1509b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 1510b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 1511b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 1512b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 1513b7e1c893Smrg /* disable encoder and transmitter */ 1514b7e1c893Smrg atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_DISABLE); 1515b7e1c893Smrg atombios_output_dig_encoder_setup(output, ATOM_DISABLE); 1516b7e1c893Smrg 1517b7e1c893Smrg /* setup and enable the encoder and transmitter */ 1518b7e1c893Smrg atombios_output_dig_encoder_setup(output, ATOM_ENABLE); 1519b7e1c893Smrg atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_SETUP); 1520b7e1c893Smrg atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_ENABLE); 1521b7e1c893Smrg break; 1522b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_DDI: 1523b7e1c893Smrg atombios_output_ddia_setup(output, ATOM_ENABLE); 1524b7e1c893Smrg break; 1525b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_DVO1: 1526b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 1527b7e1c893Smrg atombios_external_tmds_setup(output, ATOM_ENABLE); 1528b7e1c893Smrg break; 1529b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_DAC1: 1530b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 1531b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_DAC2: 1532b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 1533b7e1c893Smrg atombios_output_dac_setup(output, ATOM_ENABLE); 1534b7e1c893Smrg if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) 1535b7e1c893Smrg atombios_output_tv_setup(output, ATOM_ENABLE); 1536b7e1c893Smrg break; 1537b7e1c893Smrg } 1538b7e1c893Smrg atombios_apply_output_quirks(output, adjusted_mode); 1539209ff23fSmrg} 1540209ff23fSmrg 1541209ff23fSmrgstatic AtomBiosResult 1542209ff23fSmrgatom_bios_dac_load_detect(atomBiosHandlePtr atomBIOS, xf86OutputPtr output) 1543209ff23fSmrg{ 1544209ff23fSmrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 1545209ff23fSmrg RADEONInfoPtr info = RADEONPTR(output->scrn); 1546209ff23fSmrg DAC_LOAD_DETECTION_PS_ALLOCATION dac_data; 1547209ff23fSmrg AtomBiosArgRec data; 1548209ff23fSmrg unsigned char *space; 1549b7e1c893Smrg int major, minor; 1550b7e1c893Smrg int index = GetIndexIntoMasterTable(COMMAND, DAC_LoadDetection); 1551b7e1c893Smrg 1552b7e1c893Smrg atombios_get_command_table_version(info->atomBIOS, index, &major, &minor); 1553209ff23fSmrg 1554209ff23fSmrg dac_data.sDacload.ucMisc = 0; 1555209ff23fSmrg 1556209ff23fSmrg if (radeon_output->devices & ATOM_DEVICE_CRT1_SUPPORT) { 1557b7e1c893Smrg dac_data.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT1_SUPPORT); 1558b7e1c893Smrg if (info->encoders[ATOM_DEVICE_CRT1_INDEX] && 1559b7e1c893Smrg ((info->encoders[ATOM_DEVICE_CRT1_INDEX]->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1) || 1560b7e1c893Smrg (info->encoders[ATOM_DEVICE_CRT1_INDEX]->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1))) 1561209ff23fSmrg dac_data.sDacload.ucDacType = ATOM_DAC_A; 1562b7e1c893Smrg else 1563209ff23fSmrg dac_data.sDacload.ucDacType = ATOM_DAC_B; 1564209ff23fSmrg } else if (radeon_output->devices & ATOM_DEVICE_CRT2_SUPPORT) { 1565b7e1c893Smrg dac_data.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT2_SUPPORT); 1566b7e1c893Smrg if (info->encoders[ATOM_DEVICE_CRT2_INDEX] && 1567b7e1c893Smrg ((info->encoders[ATOM_DEVICE_CRT2_INDEX]->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1) || 1568b7e1c893Smrg (info->encoders[ATOM_DEVICE_CRT2_INDEX]->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1))) 1569209ff23fSmrg dac_data.sDacload.ucDacType = ATOM_DAC_A; 1570b7e1c893Smrg else 1571209ff23fSmrg dac_data.sDacload.ucDacType = ATOM_DAC_B; 1572209ff23fSmrg } else if (radeon_output->devices & ATOM_DEVICE_CV_SUPPORT) { 1573b7e1c893Smrg dac_data.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CV_SUPPORT); 1574b7e1c893Smrg if (info->encoders[ATOM_DEVICE_CV_INDEX] && 1575b7e1c893Smrg ((info->encoders[ATOM_DEVICE_CV_INDEX]->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1) || 1576b7e1c893Smrg (info->encoders[ATOM_DEVICE_CV_INDEX]->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1))) 1577209ff23fSmrg dac_data.sDacload.ucDacType = ATOM_DAC_A; 1578b7e1c893Smrg else 1579209ff23fSmrg dac_data.sDacload.ucDacType = ATOM_DAC_B; 1580b7e1c893Smrg if (minor >= 3) 1581b7e1c893Smrg dac_data.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb; 1582209ff23fSmrg } else if (radeon_output->devices & ATOM_DEVICE_TV1_SUPPORT) { 1583b7e1c893Smrg dac_data.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_TV1_SUPPORT); 1584b7e1c893Smrg if (info->encoders[ATOM_DEVICE_TV1_INDEX] && 1585b7e1c893Smrg ((info->encoders[ATOM_DEVICE_TV1_INDEX]->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1) || 1586b7e1c893Smrg (info->encoders[ATOM_DEVICE_TV1_INDEX]->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1))) 1587209ff23fSmrg dac_data.sDacload.ucDacType = ATOM_DAC_A; 1588b7e1c893Smrg else 1589209ff23fSmrg dac_data.sDacload.ucDacType = ATOM_DAC_B; 1590b7e1c893Smrg if (minor >= 3) 1591b7e1c893Smrg dac_data.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb; 1592b7e1c893Smrg } else 1593209ff23fSmrg return ATOM_NOT_IMPLEMENTED; 1594209ff23fSmrg 1595b7e1c893Smrg data.exec.index = index; 1596209ff23fSmrg data.exec.dataSpace = (void *)&space; 1597209ff23fSmrg data.exec.pspace = &dac_data; 1598209ff23fSmrg 1599209ff23fSmrg if (RHDAtomBiosFunc(atomBIOS->scrnIndex, atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { 1600209ff23fSmrg ErrorF("Dac detection success\n"); 1601209ff23fSmrg return ATOM_SUCCESS ; 1602209ff23fSmrg } 1603209ff23fSmrg 1604209ff23fSmrg ErrorF("DAC detection failed\n"); 1605209ff23fSmrg return ATOM_NOT_IMPLEMENTED; 1606209ff23fSmrg} 1607209ff23fSmrg 1608209ff23fSmrgRADEONMonitorType 1609b7e1c893Smrgatombios_dac_detect(xf86OutputPtr output) 1610209ff23fSmrg{ 1611b7e1c893Smrg ScrnInfoPtr pScrn = output->scrn; 1612209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 1613209ff23fSmrg unsigned char *RADEONMMIO = info->MMIO; 1614209ff23fSmrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 1615209ff23fSmrg RADEONMonitorType MonType = MT_NONE; 1616209ff23fSmrg AtomBiosResult ret; 1617c503f109Smrg RADEONSavePtr save = info->ModeReg; 1618209ff23fSmrg 1619b7e1c893Smrg if (radeon_output->devices & ATOM_DEVICE_TV1_SUPPORT) { 1620209ff23fSmrg if (xf86ReturnOptValBool(info->Options, OPTION_FORCE_TVOUT, FALSE)) { 1621b7e1c893Smrg if (radeon_output->ConnectorType == CONNECTOR_STV) 1622209ff23fSmrg return MT_STV; 1623209ff23fSmrg else 1624209ff23fSmrg return MT_CTV; 1625209ff23fSmrg } 1626209ff23fSmrg } 1627209ff23fSmrg 1628209ff23fSmrg ret = atom_bios_dac_load_detect(info->atomBIOS, output); 1629209ff23fSmrg if (ret == ATOM_SUCCESS) { 1630209ff23fSmrg if (info->ChipFamily >= CHIP_FAMILY_R600) 1631c503f109Smrg save->bios_0_scratch = INREG(R600_BIOS_0_SCRATCH); 1632209ff23fSmrg else 1633c503f109Smrg save->bios_0_scratch = INREG(RADEON_BIOS_0_SCRATCH); 1634c503f109Smrg /*ErrorF("DAC connect %08X\n", (unsigned int)save->bios_0_scratch);*/ 1635209ff23fSmrg 1636209ff23fSmrg if (radeon_output->devices & ATOM_DEVICE_CRT1_SUPPORT) { 1637c503f109Smrg if (save->bios_0_scratch & ATOM_S0_CRT1_MASK) 1638209ff23fSmrg MonType = MT_CRT; 1639209ff23fSmrg } else if (radeon_output->devices & ATOM_DEVICE_CRT2_SUPPORT) { 1640c503f109Smrg if (save->bios_0_scratch & ATOM_S0_CRT2_MASK) 1641209ff23fSmrg MonType = MT_CRT; 1642209ff23fSmrg } else if (radeon_output->devices & ATOM_DEVICE_CV_SUPPORT) { 1643c503f109Smrg if (save->bios_0_scratch & (ATOM_S0_CV_MASK | ATOM_S0_CV_MASK_A)) 1644209ff23fSmrg MonType = MT_CV; 1645209ff23fSmrg } else if (radeon_output->devices & ATOM_DEVICE_TV1_SUPPORT) { 1646c503f109Smrg if (save->bios_0_scratch & (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A)) 1647209ff23fSmrg MonType = MT_CTV; 1648c503f109Smrg else if (save->bios_0_scratch & (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A)) 1649209ff23fSmrg MonType = MT_STV; 1650209ff23fSmrg } 1651209ff23fSmrg } 1652209ff23fSmrg 1653209ff23fSmrg return MonType; 1654209ff23fSmrg} 1655209ff23fSmrg 1656