atombios_output.c revision b7e1c893
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 */ 37209ff23fSmrg#define DPMS_SERVER 38209ff23fSmrg#include <X11/extensions/dpms.h> 39209ff23fSmrg#include <unistd.h> 40209ff23fSmrg 41209ff23fSmrg#include "radeon.h" 42209ff23fSmrg#include "radeon_reg.h" 43209ff23fSmrg#include "radeon_macros.h" 44209ff23fSmrg#include "radeon_atombios.h" 45209ff23fSmrg 46b7e1c893Smrg#include "ati_pciids_gen.h" 47b7e1c893Smrg 48b7e1c893Smrgconst char *device_name[12] = { 49b7e1c893Smrg "CRT1", 50b7e1c893Smrg "LCD1", 51b7e1c893Smrg "TV1", 52b7e1c893Smrg "DFP1", 53b7e1c893Smrg "CRT2", 54b7e1c893Smrg "LCD2", 55b7e1c893Smrg "TV2", 56b7e1c893Smrg "DFP2", 57b7e1c893Smrg "CV", 58b7e1c893Smrg "DFP3", 59b7e1c893Smrg "DFP4", 60b7e1c893Smrg "DFP5", 61b7e1c893Smrg}; 62b7e1c893Smrg 63209ff23fSmrgstatic int 64b7e1c893Smrgatombios_output_dac_setup(xf86OutputPtr output, int action) 65209ff23fSmrg{ 66209ff23fSmrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 67209ff23fSmrg RADEONInfoPtr info = RADEONPTR(output->scrn); 68b7e1c893Smrg radeon_encoder_ptr radeon_encoder = radeon_get_encoder(output); 69b7e1c893Smrg radeon_tvout_ptr tvout = &radeon_output->tvout; 70209ff23fSmrg DAC_ENCODER_CONTROL_PS_ALLOCATION disp_data; 71209ff23fSmrg AtomBiosArgRec data; 72209ff23fSmrg unsigned char *space; 73b7e1c893Smrg int index = 0, num = 0; 74b7e1c893Smrg int clock = radeon_output->pixel_clock; 75b7e1c893Smrg 76b7e1c893Smrg if (radeon_encoder == NULL) 77b7e1c893Smrg return ATOM_NOT_IMPLEMENTED; 78b7e1c893Smrg 79b7e1c893Smrg memset(&disp_data,0, sizeof(disp_data)); 80b7e1c893Smrg 81b7e1c893Smrg switch (radeon_encoder->encoder_id) { 82b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_DAC1: 83b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 84b7e1c893Smrg index = GetIndexIntoMasterTable(COMMAND, DAC1EncoderControl); 85b7e1c893Smrg num = 1; 86b7e1c893Smrg break; 87b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_DAC2: 88b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 89b7e1c893Smrg index = GetIndexIntoMasterTable(COMMAND, DAC2EncoderControl); 90b7e1c893Smrg num = 2; 91b7e1c893Smrg break; 92b7e1c893Smrg } 93209ff23fSmrg 94b7e1c893Smrg disp_data.ucAction =action; 95209ff23fSmrg 96b7e1c893Smrg if (radeon_output->active_device & (ATOM_DEVICE_CRT_SUPPORT)) 97209ff23fSmrg disp_data.ucDacStandard = ATOM_DAC1_PS2; 98b7e1c893Smrg else if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT)) 99209ff23fSmrg disp_data.ucDacStandard = ATOM_DAC1_CV; 100b7e1c893Smrg else { 101b7e1c893Smrg switch (tvout->tvStd) { 102209ff23fSmrg case TV_STD_PAL: 103209ff23fSmrg case TV_STD_PAL_M: 104209ff23fSmrg case TV_STD_SCART_PAL: 105209ff23fSmrg case TV_STD_SECAM: 106209ff23fSmrg case TV_STD_PAL_CN: 107209ff23fSmrg disp_data.ucDacStandard = ATOM_DAC1_PAL; 108209ff23fSmrg break; 109209ff23fSmrg case TV_STD_NTSC: 110209ff23fSmrg case TV_STD_NTSC_J: 111209ff23fSmrg case TV_STD_PAL_60: 112209ff23fSmrg default: 113b7e1c893Smrg disp_data.ucDacStandard = ATOM_DAC1_NTSC; 114209ff23fSmrg break; 115209ff23fSmrg } 116209ff23fSmrg } 117b7e1c893Smrg disp_data.usPixelClock = cpu_to_le16(clock / 10); 118209ff23fSmrg 119b7e1c893Smrg data.exec.index = index; 120209ff23fSmrg data.exec.dataSpace = (void *)&space; 121209ff23fSmrg data.exec.pspace = &disp_data; 122209ff23fSmrg 123209ff23fSmrg if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { 124b7e1c893Smrg ErrorF("Output DAC%d setup success\n", num); 125209ff23fSmrg return ATOM_SUCCESS; 126209ff23fSmrg } 127209ff23fSmrg 128b7e1c893Smrg ErrorF("Output DAC%d setup failed\n", num); 129209ff23fSmrg return ATOM_NOT_IMPLEMENTED; 130209ff23fSmrg 131209ff23fSmrg} 132209ff23fSmrg 133209ff23fSmrgstatic int 134b7e1c893Smrgatombios_output_tv_setup(xf86OutputPtr output, int action) 135209ff23fSmrg{ 136209ff23fSmrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 137b7e1c893Smrg radeon_tvout_ptr tvout = &radeon_output->tvout; 138209ff23fSmrg RADEONInfoPtr info = RADEONPTR(output->scrn); 139209ff23fSmrg TV_ENCODER_CONTROL_PS_ALLOCATION disp_data; 140209ff23fSmrg AtomBiosArgRec data; 141209ff23fSmrg unsigned char *space; 142b7e1c893Smrg int clock = radeon_output->pixel_clock; 143b7e1c893Smrg 144b7e1c893Smrg memset(&disp_data,0, sizeof(disp_data)); 145209ff23fSmrg 146b7e1c893Smrg disp_data.sTVEncoder.ucAction = action; 147209ff23fSmrg 148b7e1c893Smrg if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT)) 149209ff23fSmrg disp_data.sTVEncoder.ucTvStandard = ATOM_TV_CV; 150209ff23fSmrg else { 151b7e1c893Smrg switch (tvout->tvStd) { 152209ff23fSmrg case TV_STD_NTSC: 153209ff23fSmrg disp_data.sTVEncoder.ucTvStandard = ATOM_TV_NTSC; 154209ff23fSmrg break; 155209ff23fSmrg case TV_STD_PAL: 156209ff23fSmrg disp_data.sTVEncoder.ucTvStandard = ATOM_TV_PAL; 157209ff23fSmrg break; 158209ff23fSmrg case TV_STD_PAL_M: 159209ff23fSmrg disp_data.sTVEncoder.ucTvStandard = ATOM_TV_PALM; 160209ff23fSmrg break; 161209ff23fSmrg case TV_STD_PAL_60: 162209ff23fSmrg disp_data.sTVEncoder.ucTvStandard = ATOM_TV_PAL60; 163209ff23fSmrg break; 164209ff23fSmrg case TV_STD_NTSC_J: 165209ff23fSmrg disp_data.sTVEncoder.ucTvStandard = ATOM_TV_NTSCJ; 166209ff23fSmrg break; 167209ff23fSmrg case TV_STD_SCART_PAL: 168209ff23fSmrg disp_data.sTVEncoder.ucTvStandard = ATOM_TV_PAL; /* ??? */ 169209ff23fSmrg break; 170209ff23fSmrg case TV_STD_SECAM: 171209ff23fSmrg disp_data.sTVEncoder.ucTvStandard = ATOM_TV_SECAM; 172209ff23fSmrg break; 173209ff23fSmrg case TV_STD_PAL_CN: 174209ff23fSmrg disp_data.sTVEncoder.ucTvStandard = ATOM_TV_PALCN; 175209ff23fSmrg break; 176209ff23fSmrg default: 177209ff23fSmrg disp_data.sTVEncoder.ucTvStandard = ATOM_TV_NTSC; 178209ff23fSmrg break; 179209ff23fSmrg } 180209ff23fSmrg } 181209ff23fSmrg 182b7e1c893Smrg disp_data.sTVEncoder.usPixelClock = cpu_to_le16(clock / 10); 183209ff23fSmrg data.exec.index = GetIndexIntoMasterTable(COMMAND, TVEncoderControl); 184209ff23fSmrg data.exec.dataSpace = (void *)&space; 185209ff23fSmrg data.exec.pspace = &disp_data; 186209ff23fSmrg 187209ff23fSmrg if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { 188b7e1c893Smrg ErrorF("Output TV setup success\n"); 189209ff23fSmrg return ATOM_SUCCESS; 190209ff23fSmrg } 191209ff23fSmrg 192b7e1c893Smrg ErrorF("Output TV setup failed\n"); 193209ff23fSmrg return ATOM_NOT_IMPLEMENTED; 194209ff23fSmrg 195209ff23fSmrg} 196209ff23fSmrg 197209ff23fSmrgint 198b7e1c893Smrgatombios_external_tmds_setup(xf86OutputPtr output, int action) 199209ff23fSmrg{ 200b7e1c893Smrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 201b7e1c893Smrg ScrnInfoPtr pScrn = output->scrn; 202b7e1c893Smrg RADEONInfoPtr info = RADEONPTR(pScrn); 203209ff23fSmrg ENABLE_EXTERNAL_TMDS_ENCODER_PS_ALLOCATION disp_data; 204209ff23fSmrg AtomBiosArgRec data; 205209ff23fSmrg unsigned char *space; 206b7e1c893Smrg int clock = radeon_output->pixel_clock; 207209ff23fSmrg 208b7e1c893Smrg memset(&disp_data,0, sizeof(disp_data)); 209209ff23fSmrg 210b7e1c893Smrg disp_data.sXTmdsEncoder.ucEnable = action; 211b7e1c893Smrg 212b7e1c893Smrg if (clock > 165000) 213b7e1c893Smrg disp_data.sXTmdsEncoder.ucMisc = PANEL_ENCODER_MISC_DUAL; 214209ff23fSmrg 215b7e1c893Smrg if (pScrn->rgbBits == 8) 216209ff23fSmrg disp_data.sXTmdsEncoder.ucMisc |= (1 << 1); 217209ff23fSmrg 218209ff23fSmrg data.exec.index = GetIndexIntoMasterTable(COMMAND, DVOEncoderControl); 219209ff23fSmrg data.exec.dataSpace = (void *)&space; 220209ff23fSmrg data.exec.pspace = &disp_data; 221209ff23fSmrg 222209ff23fSmrg if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { 223209ff23fSmrg ErrorF("External TMDS setup success\n"); 224209ff23fSmrg return ATOM_SUCCESS; 225209ff23fSmrg } 226209ff23fSmrg 227209ff23fSmrg ErrorF("External TMDS setup failed\n"); 228209ff23fSmrg return ATOM_NOT_IMPLEMENTED; 229209ff23fSmrg} 230209ff23fSmrg 231209ff23fSmrgstatic int 232b7e1c893Smrgatombios_output_ddia_setup(xf86OutputPtr output, int action) 233209ff23fSmrg{ 234b7e1c893Smrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 235209ff23fSmrg RADEONInfoPtr info = RADEONPTR(output->scrn); 236209ff23fSmrg DVO_ENCODER_CONTROL_PS_ALLOCATION disp_data; 237209ff23fSmrg AtomBiosArgRec data; 238209ff23fSmrg unsigned char *space; 239b7e1c893Smrg int clock = radeon_output->pixel_clock; 240b7e1c893Smrg 241b7e1c893Smrg memset(&disp_data,0, sizeof(disp_data)); 242209ff23fSmrg 243b7e1c893Smrg disp_data.sDVOEncoder.ucAction = action; 244b7e1c893Smrg disp_data.sDVOEncoder.usPixelClock = cpu_to_le16(clock / 10); 245209ff23fSmrg 246b7e1c893Smrg if (clock > 165000) 247209ff23fSmrg disp_data.sDVOEncoder.usDevAttr.sDigAttrib.ucAttribute = PANEL_ENCODER_MISC_DUAL; 248209ff23fSmrg 249209ff23fSmrg data.exec.index = GetIndexIntoMasterTable(COMMAND, DVOEncoderControl); 250209ff23fSmrg data.exec.dataSpace = (void *)&space; 251209ff23fSmrg data.exec.pspace = &disp_data; 252209ff23fSmrg 253209ff23fSmrg if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { 254209ff23fSmrg ErrorF("DDIA setup success\n"); 255209ff23fSmrg return ATOM_SUCCESS; 256209ff23fSmrg } 257209ff23fSmrg 258209ff23fSmrg ErrorF("DDIA setup failed\n"); 259209ff23fSmrg return ATOM_NOT_IMPLEMENTED; 260209ff23fSmrg} 261209ff23fSmrg 262209ff23fSmrgstatic int 263b7e1c893Smrgatombios_output_digital_setup(xf86OutputPtr output, int action) 264209ff23fSmrg{ 265b7e1c893Smrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 266b7e1c893Smrg ScrnInfoPtr pScrn = output->scrn; 267b7e1c893Smrg RADEONInfoPtr info = RADEONPTR(pScrn); 268b7e1c893Smrg radeon_encoder_ptr radeon_encoder = radeon_get_encoder(output); 269b7e1c893Smrg LVDS_ENCODER_CONTROL_PS_ALLOCATION disp_data; 270b7e1c893Smrg LVDS_ENCODER_CONTROL_PS_ALLOCATION_V2 disp_data2; 271209ff23fSmrg AtomBiosArgRec data; 272209ff23fSmrg unsigned char *space; 273b7e1c893Smrg int index = 0; 274b7e1c893Smrg int major, minor; 275b7e1c893Smrg int lvds_misc = 0; 276b7e1c893Smrg int clock = radeon_output->pixel_clock; 277209ff23fSmrg 278b7e1c893Smrg if (radeon_encoder == NULL) 279b7e1c893Smrg return ATOM_NOT_IMPLEMENTED; 280b7e1c893Smrg 281b7e1c893Smrg if (radeon_output->active_device & (ATOM_DEVICE_LCD_SUPPORT)) { 282b7e1c893Smrg radeon_lvds_ptr lvds = (radeon_lvds_ptr)radeon_encoder->dev_priv; 283b7e1c893Smrg if (lvds == NULL) 284b7e1c893Smrg return ATOM_NOT_IMPLEMENTED; 285b7e1c893Smrg lvds_misc = lvds->lvds_misc; 286b7e1c893Smrg } 287b7e1c893Smrg 288b7e1c893Smrg memset(&disp_data,0, sizeof(disp_data)); 289b7e1c893Smrg memset(&disp_data2,0, sizeof(disp_data2)); 290b7e1c893Smrg 291b7e1c893Smrg switch (radeon_encoder->encoder_id) { 292b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_LVDS: 293b7e1c893Smrg index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl); 294b7e1c893Smrg break; 295b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 296b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 297b7e1c893Smrg index = GetIndexIntoMasterTable(COMMAND, TMDS1EncoderControl); 298b7e1c893Smrg break; 299b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 300b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 301b7e1c893Smrg if (radeon_output->active_device & (ATOM_DEVICE_LCD_SUPPORT)) 302b7e1c893Smrg index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl); 303b7e1c893Smrg else 304b7e1c893Smrg index = GetIndexIntoMasterTable(COMMAND, TMDS2EncoderControl); 305b7e1c893Smrg break; 306b7e1c893Smrg } 307b7e1c893Smrg 308b7e1c893Smrg atombios_get_command_table_version(info->atomBIOS, index, &major, &minor); 309b7e1c893Smrg 310b7e1c893Smrg /*ErrorF("table is %d %d\n", major, minor);*/ 311b7e1c893Smrg switch (major) { 312b7e1c893Smrg case 0: 313b7e1c893Smrg case 1: 314b7e1c893Smrg case 2: 315b7e1c893Smrg switch (minor) { 316b7e1c893Smrg case 1: 317b7e1c893Smrg disp_data.ucMisc = 0; 318b7e1c893Smrg disp_data.ucAction = action; 319b7e1c893Smrg if ((radeon_output->ConnectorType == CONNECTOR_HDMI_TYPE_A) || 320b7e1c893Smrg (radeon_output->ConnectorType == CONNECTOR_HDMI_TYPE_B)) 321b7e1c893Smrg disp_data.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE; 322b7e1c893Smrg disp_data.usPixelClock = cpu_to_le16(clock / 10); 323b7e1c893Smrg if (radeon_output->active_device & (ATOM_DEVICE_LCD_SUPPORT)) { 324b7e1c893Smrg if (lvds_misc & (1 << 0)) 325b7e1c893Smrg disp_data.ucMisc |= PANEL_ENCODER_MISC_DUAL; 326b7e1c893Smrg if (lvds_misc & (1 << 1)) 327b7e1c893Smrg disp_data.ucMisc |= (1 << 1); 328b7e1c893Smrg } else { 329b7e1c893Smrg if (radeon_output->linkb) 330b7e1c893Smrg disp_data.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB; 331b7e1c893Smrg if (clock > 165000) 332b7e1c893Smrg disp_data.ucMisc |= PANEL_ENCODER_MISC_DUAL; 333b7e1c893Smrg if (pScrn->rgbBits == 8) 334b7e1c893Smrg disp_data.ucMisc |= (1 << 1); 335b7e1c893Smrg } 336b7e1c893Smrg data.exec.pspace = &disp_data; 337b7e1c893Smrg break; 338b7e1c893Smrg case 2: 339b7e1c893Smrg case 3: 340b7e1c893Smrg disp_data2.ucMisc = 0; 341b7e1c893Smrg disp_data2.ucAction = action; 342b7e1c893Smrg if (minor == 3) { 343b7e1c893Smrg if (radeon_output->coherent_mode) { 344b7e1c893Smrg disp_data2.ucMisc |= PANEL_ENCODER_MISC_COHERENT; 345b7e1c893Smrg xf86DrvMsg(output->scrn->scrnIndex, X_INFO, "Coherent Mode enabled\n"); 346b7e1c893Smrg } 347b7e1c893Smrg } 348b7e1c893Smrg if ((radeon_output->ConnectorType == CONNECTOR_HDMI_TYPE_A) || 349b7e1c893Smrg (radeon_output->ConnectorType == CONNECTOR_HDMI_TYPE_B)) 350b7e1c893Smrg disp_data2.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE; 351b7e1c893Smrg disp_data2.usPixelClock = cpu_to_le16(clock / 10); 352b7e1c893Smrg disp_data2.ucTruncate = 0; 353b7e1c893Smrg disp_data2.ucSpatial = 0; 354b7e1c893Smrg disp_data2.ucTemporal = 0; 355b7e1c893Smrg disp_data2.ucFRC = 0; 356b7e1c893Smrg if (radeon_output->active_device & (ATOM_DEVICE_LCD_SUPPORT)) { 357b7e1c893Smrg if (lvds_misc & (1 << 0)) 358b7e1c893Smrg disp_data2.ucMisc |= PANEL_ENCODER_MISC_DUAL; 359b7e1c893Smrg if (lvds_misc & (1 << 5)) { 360b7e1c893Smrg disp_data2.ucSpatial = PANEL_ENCODER_SPATIAL_DITHER_EN; 361b7e1c893Smrg if (lvds_misc & (1 << 1)) 362b7e1c893Smrg disp_data2.ucSpatial |= PANEL_ENCODER_SPATIAL_DITHER_DEPTH; 363b7e1c893Smrg } 364b7e1c893Smrg if (lvds_misc & (1 << 6)) { 365b7e1c893Smrg disp_data2.ucTemporal = PANEL_ENCODER_TEMPORAL_DITHER_EN; 366b7e1c893Smrg if (lvds_misc & (1 << 1)) 367b7e1c893Smrg disp_data2.ucTemporal |= PANEL_ENCODER_TEMPORAL_DITHER_DEPTH; 368b7e1c893Smrg if (((lvds_misc >> 2) & 0x3) == 2) 369b7e1c893Smrg disp_data2.ucTemporal |= PANEL_ENCODER_TEMPORAL_LEVEL_4; 370b7e1c893Smrg } 371b7e1c893Smrg } else { 372b7e1c893Smrg if (radeon_output->linkb) 373b7e1c893Smrg disp_data2.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB; 374b7e1c893Smrg if (clock > 165000) 375b7e1c893Smrg disp_data2.ucMisc |= PANEL_ENCODER_MISC_DUAL; 376b7e1c893Smrg } 377b7e1c893Smrg data.exec.pspace = &disp_data2; 378b7e1c893Smrg break; 379b7e1c893Smrg default: 380b7e1c893Smrg ErrorF("Unknown table version\n"); 381b7e1c893Smrg exit(-1); 382b7e1c893Smrg } 383b7e1c893Smrg break; 384b7e1c893Smrg default: 385b7e1c893Smrg ErrorF("Unknown table version\n"); 386b7e1c893Smrg exit(-1); 387b7e1c893Smrg } 388b7e1c893Smrg 389b7e1c893Smrg data.exec.index = index; 390209ff23fSmrg data.exec.dataSpace = (void *)&space; 391209ff23fSmrg 392209ff23fSmrg if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { 393b7e1c893Smrg ErrorF("Output digital setup success\n"); 394209ff23fSmrg return ATOM_SUCCESS; 395209ff23fSmrg } 396209ff23fSmrg 397b7e1c893Smrg ErrorF("Output digital setup failed\n"); 398209ff23fSmrg return ATOM_NOT_IMPLEMENTED; 399209ff23fSmrg} 400209ff23fSmrg 401209ff23fSmrgstatic int 402b7e1c893Smrgatombios_maybe_hdmi_mode(xf86OutputPtr output) 403209ff23fSmrg{ 404b7e1c893Smrg#ifndef EDID_COMPLETE_RAWDATA 405b7e1c893Smrg /* there's no getting this right unless we have complete EDID */ 406b7e1c893Smrg return ATOM_ENCODER_MODE_HDMI; 407b7e1c893Smrg#else 408b7e1c893Smrg if (output && xf86MonitorIsHDMI(output->MonInfo)) 409b7e1c893Smrg return ATOM_ENCODER_MODE_HDMI; 410b7e1c893Smrg 411b7e1c893Smrg return ATOM_ENCODER_MODE_DVI; 412b7e1c893Smrg#endif 413b7e1c893Smrg} 414209ff23fSmrg 415b7e1c893Smrgint 416b7e1c893Smrgatombios_get_encoder_mode(xf86OutputPtr output) 417b7e1c893Smrg{ 418b7e1c893Smrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 419209ff23fSmrg 420b7e1c893Smrg /* DVI should really be atombios_maybe_hdmi_mode() as well */ 421b7e1c893Smrg switch (radeon_output->ConnectorType) { 422b7e1c893Smrg case CONNECTOR_DVI_I: 423b7e1c893Smrg if (radeon_output->active_device & (ATOM_DEVICE_DFP_SUPPORT)) 424b7e1c893Smrg return ATOM_ENCODER_MODE_DVI; 425b7e1c893Smrg else 426b7e1c893Smrg return ATOM_ENCODER_MODE_CRT; 427b7e1c893Smrg break; 428b7e1c893Smrg case CONNECTOR_DVI_D: 429b7e1c893Smrg default: 430b7e1c893Smrg return ATOM_ENCODER_MODE_DVI; 431b7e1c893Smrg break; 432b7e1c893Smrg case CONNECTOR_HDMI_TYPE_A: 433b7e1c893Smrg case CONNECTOR_HDMI_TYPE_B: 434b7e1c893Smrg return atombios_maybe_hdmi_mode(output); 435b7e1c893Smrg break; 436b7e1c893Smrg case CONNECTOR_LVDS: 437b7e1c893Smrg return ATOM_ENCODER_MODE_LVDS; 438b7e1c893Smrg break; 439b7e1c893Smrg case CONNECTOR_DISPLAY_PORT: 440b7e1c893Smrg if (radeon_output->MonType == MT_DP) 441b7e1c893Smrg return ATOM_ENCODER_MODE_DP; 442b7e1c893Smrg else 443b7e1c893Smrg return atombios_maybe_hdmi_mode(output); 444b7e1c893Smrg break; 445b7e1c893Smrg case CONNECTOR_DVI_A: 446b7e1c893Smrg case CONNECTOR_VGA: 447b7e1c893Smrg case CONNECTOR_STV: 448b7e1c893Smrg case CONNECTOR_CTV: 449b7e1c893Smrg case CONNECTOR_DIN: 450b7e1c893Smrg if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT)) 451b7e1c893Smrg return ATOM_ENCODER_MODE_TV; 452b7e1c893Smrg else if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT)) 453b7e1c893Smrg return ATOM_ENCODER_MODE_CV; 454b7e1c893Smrg else 455b7e1c893Smrg return ATOM_ENCODER_MODE_CRT; 456b7e1c893Smrg break; 457209ff23fSmrg } 458209ff23fSmrg 459209ff23fSmrg} 460209ff23fSmrg 461b7e1c893Smrgstatic const int dp_clocks[] = { 462b7e1c893Smrg 16200, 463b7e1c893Smrg 27000, 464b7e1c893Smrg 32400, 465b7e1c893Smrg 54000, 466b7e1c893Smrg 0, 467b7e1c893Smrg 0, 468b7e1c893Smrg 64800, 469b7e1c893Smrg 108000, 470b7e1c893Smrg}; 471b7e1c893Smrgstatic const int num_dp_clocks = sizeof(dp_clocks) / sizeof(int); 472b7e1c893Smrg 473209ff23fSmrgstatic int 474b7e1c893Smrgdp_lanes_for_mode_clock(int mode_clock) 475209ff23fSmrg{ 476b7e1c893Smrg int i; 477b7e1c893Smrg 478b7e1c893Smrg for (i = 0; i < num_dp_clocks; i++) 479b7e1c893Smrg if (dp_clocks[i] > (mode_clock / 10)) 480b7e1c893Smrg return (i / 2) + 1; 481209ff23fSmrg 482b7e1c893Smrg return 0; 483b7e1c893Smrg} 484209ff23fSmrg 485b7e1c893Smrgstatic int 486b7e1c893Smrgdp_link_clock_for_mode_clock(int mode_clock) 487b7e1c893Smrg{ 488b7e1c893Smrg int i; 489209ff23fSmrg 490b7e1c893Smrg for (i = 0; i < num_dp_clocks; i++) 491b7e1c893Smrg if (dp_clocks[i] > (mode_clock / 10)) 492b7e1c893Smrg return (dp_clocks[i % 2]); 493b7e1c893Smrg 494b7e1c893Smrg return 0; 495209ff23fSmrg} 496209ff23fSmrg 497209ff23fSmrgstatic int 498b7e1c893Smrgatombios_output_dig_encoder_setup(xf86OutputPtr output, int action) 499209ff23fSmrg{ 500209ff23fSmrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 501209ff23fSmrg RADEONInfoPtr info = RADEONPTR(output->scrn); 502b7e1c893Smrg radeon_encoder_ptr radeon_encoder = radeon_get_encoder(output); 503209ff23fSmrg DIG_ENCODER_CONTROL_PS_ALLOCATION disp_data; 504209ff23fSmrg AtomBiosArgRec data; 505209ff23fSmrg unsigned char *space; 506b7e1c893Smrg int index = 0, major, minor, num = 0; 507b7e1c893Smrg int clock = radeon_output->pixel_clock; 508b7e1c893Smrg int dig_block = radeon_output->dig_block; 509b7e1c893Smrg 510b7e1c893Smrg if (radeon_encoder == NULL) 511b7e1c893Smrg return ATOM_NOT_IMPLEMENTED; 512b7e1c893Smrg 513b7e1c893Smrg memset(&disp_data,0, sizeof(disp_data)); 514b7e1c893Smrg 515b7e1c893Smrg if (IS_DCE32_VARIANT) { 516b7e1c893Smrg if (dig_block) 517b7e1c893Smrg index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl); 518b7e1c893Smrg else 519b7e1c893Smrg index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl); 520b7e1c893Smrg num = dig_block + 1; 521b7e1c893Smrg } else { 522b7e1c893Smrg switch (radeon_encoder->encoder_id) { 523b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 524b7e1c893Smrg index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl); 525b7e1c893Smrg num = 1; 526b7e1c893Smrg break; 527b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 528b7e1c893Smrg index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl); 529b7e1c893Smrg num = 2; 530b7e1c893Smrg break; 531b7e1c893Smrg } 532b7e1c893Smrg } 533209ff23fSmrg 534b7e1c893Smrg atombios_get_command_table_version(info->atomBIOS, index, &major, &minor); 535b7e1c893Smrg 536b7e1c893Smrg disp_data.ucAction = action; 537b7e1c893Smrg disp_data.usPixelClock = cpu_to_le16(clock / 10); 538b7e1c893Smrg 539b7e1c893Smrg if (IS_DCE32_VARIANT) { 540b7e1c893Smrg switch (radeon_encoder->encoder_id) { 541b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 542b7e1c893Smrg disp_data.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER1; 543b7e1c893Smrg break; 544b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 545b7e1c893Smrg disp_data.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER2; 546b7e1c893Smrg break; 547b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 548b7e1c893Smrg disp_data.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER3; 549b7e1c893Smrg break; 550b7e1c893Smrg } 551b7e1c893Smrg } else { 552b7e1c893Smrg switch (radeon_encoder->encoder_id) { 553b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 554b7e1c893Smrg disp_data.ucConfig = ATOM_ENCODER_CONFIG_UNIPHY; 555b7e1c893Smrg break; 556b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 557b7e1c893Smrg disp_data.ucConfig = ATOM_ENCODER_CONFIG_LVTMA; 558b7e1c893Smrg break; 559b7e1c893Smrg } 560209ff23fSmrg } 561209ff23fSmrg 562b7e1c893Smrg disp_data.ucEncoderMode = atombios_get_encoder_mode(output); 563b7e1c893Smrg 564b7e1c893Smrg if (disp_data.ucEncoderMode == ATOM_ENCODER_MODE_DP) { 565b7e1c893Smrg if (radeon_output->linkb) 566b7e1c893Smrg disp_data.ucConfig |= ATOM_ENCODER_CONFIG_LINKB; 567b7e1c893Smrg else 568b7e1c893Smrg disp_data.ucConfig |= ATOM_ENCODER_CONFIG_LINKA; 569b7e1c893Smrg 570b7e1c893Smrg if (dp_link_clock_for_mode_clock(clock) == 27000) 571b7e1c893Smrg disp_data.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ; 572b7e1c893Smrg 573b7e1c893Smrg disp_data.ucLaneNum = dp_lanes_for_mode_clock(clock); 574b7e1c893Smrg } else if (clock > 165000) { 575209ff23fSmrg disp_data.ucConfig |= ATOM_ENCODER_CONFIG_LINKA_B; 576209ff23fSmrg disp_data.ucLaneNum = 8; 577209ff23fSmrg } else { 578b7e1c893Smrg if (radeon_output->linkb) 579b7e1c893Smrg disp_data.ucConfig |= ATOM_ENCODER_CONFIG_LINKB; 580b7e1c893Smrg else 581b7e1c893Smrg disp_data.ucConfig |= ATOM_ENCODER_CONFIG_LINKA; 582b7e1c893Smrg 583209ff23fSmrg disp_data.ucLaneNum = 4; 584209ff23fSmrg } 585209ff23fSmrg 586b7e1c893Smrg data.exec.index = index; 587209ff23fSmrg data.exec.dataSpace = (void *)&space; 588209ff23fSmrg data.exec.pspace = &disp_data; 589209ff23fSmrg 590209ff23fSmrg if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { 591b7e1c893Smrg ErrorF("Output DIG%d encoder setup success\n", num); 592209ff23fSmrg return ATOM_SUCCESS; 593209ff23fSmrg } 594209ff23fSmrg 595b7e1c893Smrg ErrorF("Output DIG%d setup failed\n", num); 596209ff23fSmrg return ATOM_NOT_IMPLEMENTED; 597209ff23fSmrg 598209ff23fSmrg} 599209ff23fSmrg 600b7e1c893Smrgunion dig_transmitter_control { 601b7e1c893Smrg DIG_TRANSMITTER_CONTROL_PS_ALLOCATION v1; 602b7e1c893Smrg DIG_TRANSMITTER_CONTROL_PARAMETERS_V2 v2; 603b7e1c893Smrg}; 604b7e1c893Smrg 605209ff23fSmrgstatic int 606b7e1c893Smrgatombios_output_dig_transmitter_setup(xf86OutputPtr output, int action) 607209ff23fSmrg{ 608209ff23fSmrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 609209ff23fSmrg RADEONInfoPtr info = RADEONPTR(output->scrn); 610b7e1c893Smrg radeon_encoder_ptr radeon_encoder = radeon_get_encoder(output); 611b7e1c893Smrg union dig_transmitter_control disp_data; 612209ff23fSmrg AtomBiosArgRec data; 613209ff23fSmrg unsigned char *space; 614b7e1c893Smrg int index = 0, num = 0; 615b7e1c893Smrg int major, minor; 616b7e1c893Smrg int clock = radeon_output->pixel_clock; 617b7e1c893Smrg int dig_block = radeon_output->dig_block; 618b7e1c893Smrg 619b7e1c893Smrg if (radeon_encoder == NULL) 620b7e1c893Smrg return ATOM_NOT_IMPLEMENTED; 621b7e1c893Smrg 622b7e1c893Smrg memset(&disp_data,0, sizeof(disp_data)); 623b7e1c893Smrg 624b7e1c893Smrg if (IS_DCE32_VARIANT) 625b7e1c893Smrg index = GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl); 626b7e1c893Smrg else { 627b7e1c893Smrg switch (radeon_encoder->encoder_id) { 628b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 629b7e1c893Smrg index = GetIndexIntoMasterTable(COMMAND, DIG1TransmitterControl); 630b7e1c893Smrg break; 631b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 632b7e1c893Smrg index = GetIndexIntoMasterTable(COMMAND, DIG2TransmitterControl); 633b7e1c893Smrg break; 634b7e1c893Smrg } 635b7e1c893Smrg } 636209ff23fSmrg 637b7e1c893Smrg atombios_get_command_table_version(info->atomBIOS, index, &major, &minor); 638b7e1c893Smrg 639b7e1c893Smrg disp_data.v1.ucAction = action; 640b7e1c893Smrg 641b7e1c893Smrg if (IS_DCE32_VARIANT) { 642b7e1c893Smrg if (radeon_output->MonType == MT_DP) { 643b7e1c893Smrg disp_data.v2.usPixelClock = 644b7e1c893Smrg cpu_to_le16(dp_link_clock_for_mode_clock(clock)); 645b7e1c893Smrg disp_data.v2.acConfig.fDPConnector = 1; 646b7e1c893Smrg } else if (clock > 165000) { 647b7e1c893Smrg disp_data.v2.usPixelClock = cpu_to_le16((clock * 10 * 2) / 100); 648b7e1c893Smrg disp_data.v2.acConfig.fDualLinkConnector = 1; 649209ff23fSmrg } else { 650b7e1c893Smrg disp_data.v2.usPixelClock = cpu_to_le16((clock * 10 * 4) / 100); 651b7e1c893Smrg } 652b7e1c893Smrg if (dig_block) 653b7e1c893Smrg disp_data.v2.acConfig.ucEncoderSel = 1; 654b7e1c893Smrg 655b7e1c893Smrg switch (radeon_encoder->encoder_id) { 656b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 657b7e1c893Smrg disp_data.v2.acConfig.ucTransmitterSel = 0; 658b7e1c893Smrg num = 0; 659b7e1c893Smrg break; 660b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 661b7e1c893Smrg disp_data.v2.acConfig.ucTransmitterSel = 1; 662b7e1c893Smrg num = 1; 663b7e1c893Smrg break; 664b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 665b7e1c893Smrg disp_data.v2.acConfig.ucTransmitterSel = 2; 666b7e1c893Smrg num = 2; 667b7e1c893Smrg break; 668b7e1c893Smrg } 669b7e1c893Smrg 670b7e1c893Smrg if (radeon_output->active_device & (ATOM_DEVICE_DFP_SUPPORT)) { 671b7e1c893Smrg if (radeon_output->coherent_mode) { 672b7e1c893Smrg disp_data.v2.acConfig.fCoherentMode = 1; 673b7e1c893Smrg xf86DrvMsg(output->scrn->scrnIndex, X_INFO, "UNIPHY%d transmitter: Coherent Mode enabled\n",disp_data.v2.acConfig.ucTransmitterSel); 674b7e1c893Smrg } else 675b7e1c893Smrg xf86DrvMsg(output->scrn->scrnIndex, X_INFO, "UNIPHY%d transmitter: Coherent Mode disabled\n",disp_data.v2.acConfig.ucTransmitterSel); 676209ff23fSmrg } 677209ff23fSmrg } else { 678b7e1c893Smrg disp_data.v1.ucConfig = ATOM_TRANSMITTER_CONFIG_CLKSRC_PPLL; 679b7e1c893Smrg 680b7e1c893Smrg if (radeon_output->MonType == MT_DP) 681b7e1c893Smrg disp_data.v1.usPixelClock = 682b7e1c893Smrg cpu_to_le16(dp_link_clock_for_mode_clock(clock)); 683209ff23fSmrg else 684b7e1c893Smrg disp_data.v1.usPixelClock = cpu_to_le16((clock) / 10); 685b7e1c893Smrg 686b7e1c893Smrg switch (radeon_encoder->encoder_id) { 687b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 688b7e1c893Smrg disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER; 689b7e1c893Smrg if (info->IsIGP) { 690b7e1c893Smrg if (clock > 165000) { 691b7e1c893Smrg disp_data.v1.ucConfig |= (ATOM_TRANSMITTER_CONFIG_8LANE_LINK | 692b7e1c893Smrg ATOM_TRANSMITTER_CONFIG_LINKA_B); 693b7e1c893Smrg 694b7e1c893Smrg if (radeon_output->igp_lane_info & 0x3) 695b7e1c893Smrg disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_7; 696b7e1c893Smrg else if (radeon_output->igp_lane_info & 0xc) 697b7e1c893Smrg disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_15; 698b7e1c893Smrg } else { 699b7e1c893Smrg disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA; 700b7e1c893Smrg if (radeon_output->igp_lane_info & 0x1) 701b7e1c893Smrg disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_3; 702b7e1c893Smrg else if (radeon_output->igp_lane_info & 0x2) 703b7e1c893Smrg disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_4_7; 704b7e1c893Smrg else if (radeon_output->igp_lane_info & 0x4) 705b7e1c893Smrg disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_11; 706b7e1c893Smrg else if (radeon_output->igp_lane_info & 0x8) 707b7e1c893Smrg disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_12_15; 708b7e1c893Smrg } 709b7e1c893Smrg } else { 710b7e1c893Smrg if (clock > 165000) 711b7e1c893Smrg disp_data.v1.ucConfig |= (ATOM_TRANSMITTER_CONFIG_8LANE_LINK | 712b7e1c893Smrg ATOM_TRANSMITTER_CONFIG_LINKA_B | 713b7e1c893Smrg ATOM_TRANSMITTER_CONFIG_LANE_0_7); 714b7e1c893Smrg else { 715b7e1c893Smrg /* XXX */ 716b7e1c893Smrg if (radeon_output->linkb) 717b7e1c893Smrg disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB | ATOM_TRANSMITTER_CONFIG_LANE_0_3; 718b7e1c893Smrg else 719b7e1c893Smrg disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA | ATOM_TRANSMITTER_CONFIG_LANE_0_3; 720b7e1c893Smrg } 721b7e1c893Smrg } 722b7e1c893Smrg break; 723b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 724b7e1c893Smrg disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER; 725b7e1c893Smrg if (clock > 165000) 726b7e1c893Smrg disp_data.v1.ucConfig |= (ATOM_TRANSMITTER_CONFIG_8LANE_LINK | 727b7e1c893Smrg ATOM_TRANSMITTER_CONFIG_LINKA_B | 728b7e1c893Smrg ATOM_TRANSMITTER_CONFIG_LANE_0_7); 729b7e1c893Smrg else { 730b7e1c893Smrg /* XXX */ 731b7e1c893Smrg if (radeon_output->linkb) 732b7e1c893Smrg disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB | ATOM_TRANSMITTER_CONFIG_LANE_0_3; 733b7e1c893Smrg else 734b7e1c893Smrg disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA | ATOM_TRANSMITTER_CONFIG_LANE_0_3; 735b7e1c893Smrg } 736b7e1c893Smrg break; 737b7e1c893Smrg } 738209ff23fSmrg 739b7e1c893Smrg if (radeon_output->active_device & (ATOM_DEVICE_DFP_SUPPORT)) { 740b7e1c893Smrg if (radeon_output->coherent_mode && 741b7e1c893Smrg radeon_output->MonType != MT_DP) { 742b7e1c893Smrg disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT; 743b7e1c893Smrg xf86DrvMsg(output->scrn->scrnIndex, X_INFO, 744b7e1c893Smrg "DIG%d transmitter: Coherent Mode enabled\n", num); 745b7e1c893Smrg } else { 746b7e1c893Smrg xf86DrvMsg(output->scrn->scrnIndex, X_INFO, 747b7e1c893Smrg "DIG%d transmitter: Coherent Mode disabled\n", num); 748b7e1c893Smrg } 749b7e1c893Smrg } 750b7e1c893Smrg } 751209ff23fSmrg 752b7e1c893Smrg data.exec.index = index; 753209ff23fSmrg data.exec.dataSpace = (void *)&space; 754209ff23fSmrg data.exec.pspace = &disp_data; 755209ff23fSmrg 756209ff23fSmrg if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { 757b7e1c893Smrg if (IS_DCE32_VARIANT) 758b7e1c893Smrg ErrorF("Output UNIPHY%d transmitter setup success\n", num); 759b7e1c893Smrg else 760b7e1c893Smrg ErrorF("Output DIG%d transmitter setup success\n", num); 761209ff23fSmrg return ATOM_SUCCESS; 762209ff23fSmrg } 763209ff23fSmrg 764b7e1c893Smrg ErrorF("Output DIG%d transmitter setup failed\n", num); 765209ff23fSmrg return ATOM_NOT_IMPLEMENTED; 766209ff23fSmrg 767209ff23fSmrg} 768209ff23fSmrg 769b7e1c893Smrgstatic void atom_rv515_force_tv_scaler(ScrnInfoPtr pScrn) 770b7e1c893Smrg{ 771b7e1c893Smrg RADEONInfoPtr info = RADEONPTR(pScrn); 772b7e1c893Smrg unsigned char *RADEONMMIO = info->MMIO; 773b7e1c893Smrg 774b7e1c893Smrg OUTREG(0x659C,0x0); 775b7e1c893Smrg OUTREG(0x6594,0x705); 776b7e1c893Smrg OUTREG(0x65A4,0x10001); 777b7e1c893Smrg OUTREG(0x65D8,0x0); 778b7e1c893Smrg OUTREG(0x65B0,0x0); 779b7e1c893Smrg OUTREG(0x65C0,0x0); 780b7e1c893Smrg OUTREG(0x65D4,0x0); 781b7e1c893Smrg OUTREG(0x6578,0x0); 782b7e1c893Smrg OUTREG(0x657C,0x841880A8); 783b7e1c893Smrg OUTREG(0x6578,0x1); 784b7e1c893Smrg OUTREG(0x657C,0x84208680); 785b7e1c893Smrg OUTREG(0x6578,0x2); 786b7e1c893Smrg OUTREG(0x657C,0xBFF880B0); 787b7e1c893Smrg OUTREG(0x6578,0x100); 788b7e1c893Smrg OUTREG(0x657C,0x83D88088); 789b7e1c893Smrg OUTREG(0x6578,0x101); 790b7e1c893Smrg OUTREG(0x657C,0x84608680); 791b7e1c893Smrg OUTREG(0x6578,0x102); 792b7e1c893Smrg OUTREG(0x657C,0xBFF080D0); 793b7e1c893Smrg OUTREG(0x6578,0x200); 794b7e1c893Smrg OUTREG(0x657C,0x83988068); 795b7e1c893Smrg OUTREG(0x6578,0x201); 796b7e1c893Smrg OUTREG(0x657C,0x84A08680); 797b7e1c893Smrg OUTREG(0x6578,0x202); 798b7e1c893Smrg OUTREG(0x657C,0xBFF080F8); 799b7e1c893Smrg OUTREG(0x6578,0x300); 800b7e1c893Smrg OUTREG(0x657C,0x83588058); 801b7e1c893Smrg OUTREG(0x6578,0x301); 802b7e1c893Smrg OUTREG(0x657C,0x84E08660); 803b7e1c893Smrg OUTREG(0x6578,0x302); 804b7e1c893Smrg OUTREG(0x657C,0xBFF88120); 805b7e1c893Smrg OUTREG(0x6578,0x400); 806b7e1c893Smrg OUTREG(0x657C,0x83188040); 807b7e1c893Smrg OUTREG(0x6578,0x401); 808b7e1c893Smrg OUTREG(0x657C,0x85008660); 809b7e1c893Smrg OUTREG(0x6578,0x402); 810b7e1c893Smrg OUTREG(0x657C,0xBFF88150); 811b7e1c893Smrg OUTREG(0x6578,0x500); 812b7e1c893Smrg OUTREG(0x657C,0x82D88030); 813b7e1c893Smrg OUTREG(0x6578,0x501); 814b7e1c893Smrg OUTREG(0x657C,0x85408640); 815b7e1c893Smrg OUTREG(0x6578,0x502); 816b7e1c893Smrg OUTREG(0x657C,0xBFF88180); 817b7e1c893Smrg OUTREG(0x6578,0x600); 818b7e1c893Smrg OUTREG(0x657C,0x82A08018); 819b7e1c893Smrg OUTREG(0x6578,0x601); 820b7e1c893Smrg OUTREG(0x657C,0x85808620); 821b7e1c893Smrg OUTREG(0x6578,0x602); 822b7e1c893Smrg OUTREG(0x657C,0xBFF081B8); 823b7e1c893Smrg OUTREG(0x6578,0x700); 824b7e1c893Smrg OUTREG(0x657C,0x82608010); 825b7e1c893Smrg OUTREG(0x6578,0x701); 826b7e1c893Smrg OUTREG(0x657C,0x85A08600); 827b7e1c893Smrg OUTREG(0x6578,0x702); 828b7e1c893Smrg OUTREG(0x657C,0x800081F0); 829b7e1c893Smrg OUTREG(0x6578,0x800); 830b7e1c893Smrg OUTREG(0x657C,0x8228BFF8); 831b7e1c893Smrg OUTREG(0x6578,0x801); 832b7e1c893Smrg OUTREG(0x657C,0x85E085E0); 833b7e1c893Smrg OUTREG(0x6578,0x802); 834b7e1c893Smrg OUTREG(0x657C,0xBFF88228); 835b7e1c893Smrg OUTREG(0x6578,0x10000); 836b7e1c893Smrg OUTREG(0x657C,0x82A8BF00); 837b7e1c893Smrg OUTREG(0x6578,0x10001); 838b7e1c893Smrg OUTREG(0x657C,0x82A08CC0); 839b7e1c893Smrg OUTREG(0x6578,0x10002); 840b7e1c893Smrg OUTREG(0x657C,0x8008BEF8); 841b7e1c893Smrg OUTREG(0x6578,0x10100); 842b7e1c893Smrg OUTREG(0x657C,0x81F0BF28); 843b7e1c893Smrg OUTREG(0x6578,0x10101); 844b7e1c893Smrg OUTREG(0x657C,0x83608CA0); 845b7e1c893Smrg OUTREG(0x6578,0x10102); 846b7e1c893Smrg OUTREG(0x657C,0x8018BED0); 847b7e1c893Smrg OUTREG(0x6578,0x10200); 848b7e1c893Smrg OUTREG(0x657C,0x8148BF38); 849b7e1c893Smrg OUTREG(0x6578,0x10201); 850b7e1c893Smrg OUTREG(0x657C,0x84408C80); 851b7e1c893Smrg OUTREG(0x6578,0x10202); 852b7e1c893Smrg OUTREG(0x657C,0x8008BEB8); 853b7e1c893Smrg OUTREG(0x6578,0x10300); 854b7e1c893Smrg OUTREG(0x657C,0x80B0BF78); 855b7e1c893Smrg OUTREG(0x6578,0x10301); 856b7e1c893Smrg OUTREG(0x657C,0x85008C20); 857b7e1c893Smrg OUTREG(0x6578,0x10302); 858b7e1c893Smrg OUTREG(0x657C,0x8020BEA0); 859b7e1c893Smrg OUTREG(0x6578,0x10400); 860b7e1c893Smrg OUTREG(0x657C,0x8028BF90); 861b7e1c893Smrg OUTREG(0x6578,0x10401); 862b7e1c893Smrg OUTREG(0x657C,0x85E08BC0); 863b7e1c893Smrg OUTREG(0x6578,0x10402); 864b7e1c893Smrg OUTREG(0x657C,0x8018BE90); 865b7e1c893Smrg OUTREG(0x6578,0x10500); 866b7e1c893Smrg OUTREG(0x657C,0xBFB8BFB0); 867b7e1c893Smrg OUTREG(0x6578,0x10501); 868b7e1c893Smrg OUTREG(0x657C,0x86C08B40); 869b7e1c893Smrg OUTREG(0x6578,0x10502); 870b7e1c893Smrg OUTREG(0x657C,0x8010BE90); 871b7e1c893Smrg OUTREG(0x6578,0x10600); 872b7e1c893Smrg OUTREG(0x657C,0xBF58BFC8); 873b7e1c893Smrg OUTREG(0x6578,0x10601); 874b7e1c893Smrg OUTREG(0x657C,0x87A08AA0); 875b7e1c893Smrg OUTREG(0x6578,0x10602); 876b7e1c893Smrg OUTREG(0x657C,0x8010BE98); 877b7e1c893Smrg OUTREG(0x6578,0x10700); 878b7e1c893Smrg OUTREG(0x657C,0xBF10BFF0); 879b7e1c893Smrg OUTREG(0x6578,0x10701); 880b7e1c893Smrg OUTREG(0x657C,0x886089E0); 881b7e1c893Smrg OUTREG(0x6578,0x10702); 882b7e1c893Smrg OUTREG(0x657C,0x8018BEB0); 883b7e1c893Smrg OUTREG(0x6578,0x10800); 884b7e1c893Smrg OUTREG(0x657C,0xBED8BFE8); 885b7e1c893Smrg OUTREG(0x6578,0x10801); 886b7e1c893Smrg OUTREG(0x657C,0x89408940); 887b7e1c893Smrg OUTREG(0x6578,0x10802); 888b7e1c893Smrg OUTREG(0x657C,0xBFE8BED8); 889b7e1c893Smrg OUTREG(0x6578,0x20000); 890b7e1c893Smrg OUTREG(0x657C,0x80008000); 891b7e1c893Smrg OUTREG(0x6578,0x20001); 892b7e1c893Smrg OUTREG(0x657C,0x90008000); 893b7e1c893Smrg OUTREG(0x6578,0x20002); 894b7e1c893Smrg OUTREG(0x657C,0x80008000); 895b7e1c893Smrg OUTREG(0x6578,0x20003); 896b7e1c893Smrg OUTREG(0x657C,0x80008000); 897b7e1c893Smrg OUTREG(0x6578,0x20100); 898b7e1c893Smrg OUTREG(0x657C,0x80108000); 899b7e1c893Smrg OUTREG(0x6578,0x20101); 900b7e1c893Smrg OUTREG(0x657C,0x8FE0BF70); 901b7e1c893Smrg OUTREG(0x6578,0x20102); 902b7e1c893Smrg OUTREG(0x657C,0xBFE880C0); 903b7e1c893Smrg OUTREG(0x6578,0x20103); 904b7e1c893Smrg OUTREG(0x657C,0x80008000); 905b7e1c893Smrg OUTREG(0x6578,0x20200); 906b7e1c893Smrg OUTREG(0x657C,0x8018BFF8); 907b7e1c893Smrg OUTREG(0x6578,0x20201); 908b7e1c893Smrg OUTREG(0x657C,0x8F80BF08); 909b7e1c893Smrg OUTREG(0x6578,0x20202); 910b7e1c893Smrg OUTREG(0x657C,0xBFD081A0); 911b7e1c893Smrg OUTREG(0x6578,0x20203); 912b7e1c893Smrg OUTREG(0x657C,0xBFF88000); 913b7e1c893Smrg OUTREG(0x6578,0x20300); 914b7e1c893Smrg OUTREG(0x657C,0x80188000); 915b7e1c893Smrg OUTREG(0x6578,0x20301); 916b7e1c893Smrg OUTREG(0x657C,0x8EE0BEC0); 917b7e1c893Smrg OUTREG(0x6578,0x20302); 918b7e1c893Smrg OUTREG(0x657C,0xBFB082A0); 919b7e1c893Smrg OUTREG(0x6578,0x20303); 920b7e1c893Smrg OUTREG(0x657C,0x80008000); 921b7e1c893Smrg OUTREG(0x6578,0x20400); 922b7e1c893Smrg OUTREG(0x657C,0x80188000); 923b7e1c893Smrg OUTREG(0x6578,0x20401); 924b7e1c893Smrg OUTREG(0x657C,0x8E00BEA0); 925b7e1c893Smrg OUTREG(0x6578,0x20402); 926b7e1c893Smrg OUTREG(0x657C,0xBF8883C0); 927b7e1c893Smrg OUTREG(0x6578,0x20403); 928b7e1c893Smrg OUTREG(0x657C,0x80008000); 929b7e1c893Smrg OUTREG(0x6578,0x20500); 930b7e1c893Smrg OUTREG(0x657C,0x80188000); 931b7e1c893Smrg OUTREG(0x6578,0x20501); 932b7e1c893Smrg OUTREG(0x657C,0x8D00BE90); 933b7e1c893Smrg OUTREG(0x6578,0x20502); 934b7e1c893Smrg OUTREG(0x657C,0xBF588500); 935b7e1c893Smrg OUTREG(0x6578,0x20503); 936b7e1c893Smrg OUTREG(0x657C,0x80008008); 937b7e1c893Smrg OUTREG(0x6578,0x20600); 938b7e1c893Smrg OUTREG(0x657C,0x80188000); 939b7e1c893Smrg OUTREG(0x6578,0x20601); 940b7e1c893Smrg OUTREG(0x657C,0x8BC0BE98); 941b7e1c893Smrg OUTREG(0x6578,0x20602); 942b7e1c893Smrg OUTREG(0x657C,0xBF308660); 943b7e1c893Smrg OUTREG(0x6578,0x20603); 944b7e1c893Smrg OUTREG(0x657C,0x80008008); 945b7e1c893Smrg OUTREG(0x6578,0x20700); 946b7e1c893Smrg OUTREG(0x657C,0x80108000); 947b7e1c893Smrg OUTREG(0x6578,0x20701); 948b7e1c893Smrg OUTREG(0x657C,0x8A80BEB0); 949b7e1c893Smrg OUTREG(0x6578,0x20702); 950b7e1c893Smrg OUTREG(0x657C,0xBF0087C0); 951b7e1c893Smrg OUTREG(0x6578,0x20703); 952b7e1c893Smrg OUTREG(0x657C,0x80008008); 953b7e1c893Smrg OUTREG(0x6578,0x20800); 954b7e1c893Smrg OUTREG(0x657C,0x80108000); 955b7e1c893Smrg OUTREG(0x6578,0x20801); 956b7e1c893Smrg OUTREG(0x657C,0x8920BED0); 957b7e1c893Smrg OUTREG(0x6578,0x20802); 958b7e1c893Smrg OUTREG(0x657C,0xBED08920); 959b7e1c893Smrg OUTREG(0x6578,0x20803); 960b7e1c893Smrg OUTREG(0x657C,0x80008010); 961b7e1c893Smrg OUTREG(0x6578,0x30000); 962b7e1c893Smrg OUTREG(0x657C,0x90008000); 963b7e1c893Smrg OUTREG(0x6578,0x30001); 964b7e1c893Smrg OUTREG(0x657C,0x80008000); 965b7e1c893Smrg OUTREG(0x6578,0x30100); 966b7e1c893Smrg OUTREG(0x657C,0x8FE0BF90); 967b7e1c893Smrg OUTREG(0x6578,0x30101); 968b7e1c893Smrg OUTREG(0x657C,0xBFF880A0); 969b7e1c893Smrg OUTREG(0x6578,0x30200); 970b7e1c893Smrg OUTREG(0x657C,0x8F60BF40); 971b7e1c893Smrg OUTREG(0x6578,0x30201); 972b7e1c893Smrg OUTREG(0x657C,0xBFE88180); 973b7e1c893Smrg OUTREG(0x6578,0x30300); 974b7e1c893Smrg OUTREG(0x657C,0x8EC0BF00); 975b7e1c893Smrg OUTREG(0x6578,0x30301); 976b7e1c893Smrg OUTREG(0x657C,0xBFC88280); 977b7e1c893Smrg OUTREG(0x6578,0x30400); 978b7e1c893Smrg OUTREG(0x657C,0x8DE0BEE0); 979b7e1c893Smrg OUTREG(0x6578,0x30401); 980b7e1c893Smrg OUTREG(0x657C,0xBFA083A0); 981b7e1c893Smrg OUTREG(0x6578,0x30500); 982b7e1c893Smrg OUTREG(0x657C,0x8CE0BED0); 983b7e1c893Smrg OUTREG(0x6578,0x30501); 984b7e1c893Smrg OUTREG(0x657C,0xBF7884E0); 985b7e1c893Smrg OUTREG(0x6578,0x30600); 986b7e1c893Smrg OUTREG(0x657C,0x8BA0BED8); 987b7e1c893Smrg OUTREG(0x6578,0x30601); 988b7e1c893Smrg OUTREG(0x657C,0xBF508640); 989b7e1c893Smrg OUTREG(0x6578,0x30700); 990b7e1c893Smrg OUTREG(0x657C,0x8A60BEE8); 991b7e1c893Smrg OUTREG(0x6578,0x30701); 992b7e1c893Smrg OUTREG(0x657C,0xBF2087A0); 993b7e1c893Smrg OUTREG(0x6578,0x30800); 994b7e1c893Smrg OUTREG(0x657C,0x8900BF00); 995b7e1c893Smrg OUTREG(0x6578,0x30801); 996b7e1c893Smrg OUTREG(0x657C,0xBF008900); 997b7e1c893Smrg} 998b7e1c893Smrg 999209ff23fSmrgstatic int 1000b7e1c893Smrgatombios_output_yuv_setup(xf86OutputPtr output, Bool enable) 1001209ff23fSmrg{ 1002209ff23fSmrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 1003209ff23fSmrg RADEONInfoPtr info = RADEONPTR(output->scrn); 1004b7e1c893Smrg RADEONCrtcPrivatePtr radeon_crtc = output->crtc->driver_private; 1005b7e1c893Smrg ENABLE_YUV_PS_ALLOCATION disp_data; 1006209ff23fSmrg AtomBiosArgRec data; 1007209ff23fSmrg unsigned char *space; 1008b7e1c893Smrg unsigned char *RADEONMMIO = info->MMIO; 1009b7e1c893Smrg uint32_t temp, reg; 1010209ff23fSmrg 1011b7e1c893Smrg if (info->ChipFamily >= CHIP_FAMILY_R600) 1012b7e1c893Smrg reg = R600_BIOS_3_SCRATCH; 1013b7e1c893Smrg else 1014b7e1c893Smrg reg = RADEON_BIOS_3_SCRATCH; 1015b7e1c893Smrg 1016b7e1c893Smrg //fix up scratch reg handling 1017b7e1c893Smrg temp = INREG(reg); 1018b7e1c893Smrg if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT)) 1019b7e1c893Smrg OUTREG(reg, (ATOM_S3_TV1_ACTIVE | 1020b7e1c893Smrg (radeon_crtc->crtc_id << 18))); 1021b7e1c893Smrg else if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT)) 1022b7e1c893Smrg OUTREG(reg, (ATOM_S3_CV_ACTIVE | 1023b7e1c893Smrg (radeon_crtc->crtc_id << 24))); 1024b7e1c893Smrg else 1025b7e1c893Smrg OUTREG(reg, 0); 1026209ff23fSmrg 1027b7e1c893Smrg memset(&disp_data, 0, sizeof(disp_data)); 1028209ff23fSmrg 1029b7e1c893Smrg if (enable) 1030b7e1c893Smrg disp_data.ucEnable = ATOM_ENABLE; 1031b7e1c893Smrg disp_data.ucCRTC = radeon_crtc->crtc_id; 1032209ff23fSmrg 1033b7e1c893Smrg data.exec.index = GetIndexIntoMasterTable(COMMAND, EnableYUV); 1034209ff23fSmrg data.exec.dataSpace = (void *)&space; 1035209ff23fSmrg data.exec.pspace = &disp_data; 1036209ff23fSmrg 1037209ff23fSmrg if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { 1038b7e1c893Smrg 1039b7e1c893Smrg OUTREG(reg, temp); 1040b7e1c893Smrg 1041b7e1c893Smrg ErrorF("crtc %d YUV %s setup success\n", radeon_crtc->crtc_id, enable ? "enable" : "disable"); 1042209ff23fSmrg return ATOM_SUCCESS; 1043209ff23fSmrg } 1044209ff23fSmrg 1045b7e1c893Smrg OUTREG(reg, temp); 1046b7e1c893Smrg 1047b7e1c893Smrg ErrorF("crtc %d YUV %s setup failed\n", radeon_crtc->crtc_id, enable ? "enable" : "disable"); 1048209ff23fSmrg return ATOM_NOT_IMPLEMENTED; 1049209ff23fSmrg 1050209ff23fSmrg} 1051209ff23fSmrg 1052209ff23fSmrgstatic int 1053b7e1c893Smrgatombios_output_overscan_setup(xf86OutputPtr output, DisplayModePtr mode, DisplayModePtr adjusted_mode) 1054209ff23fSmrg{ 1055209ff23fSmrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 1056b7e1c893Smrg RADEONCrtcPrivatePtr radeon_crtc = output->crtc->driver_private; 1057209ff23fSmrg RADEONInfoPtr info = RADEONPTR(output->scrn); 1058b7e1c893Smrg SET_CRTC_OVERSCAN_PS_ALLOCATION overscan_param; 1059209ff23fSmrg AtomBiosArgRec data; 1060209ff23fSmrg unsigned char *space; 1061b7e1c893Smrg memset(&overscan_param, 0, sizeof(overscan_param)); 1062209ff23fSmrg 1063b7e1c893Smrg overscan_param.usOverscanRight = 0; 1064b7e1c893Smrg overscan_param.usOverscanLeft = 0; 1065b7e1c893Smrg overscan_param.usOverscanBottom = 0; 1066b7e1c893Smrg overscan_param.usOverscanTop = 0; 1067b7e1c893Smrg overscan_param.ucCRTC = radeon_crtc->crtc_id; 1068b7e1c893Smrg 1069b7e1c893Smrg if (radeon_output->Flags & RADEON_USE_RMX) { 1070b7e1c893Smrg if (radeon_output->rmx_type == RMX_FULL) { 1071b7e1c893Smrg overscan_param.usOverscanRight = 0; 1072b7e1c893Smrg overscan_param.usOverscanLeft = 0; 1073b7e1c893Smrg overscan_param.usOverscanBottom = 0; 1074b7e1c893Smrg overscan_param.usOverscanTop = 0; 1075b7e1c893Smrg } else if (radeon_output->rmx_type == RMX_CENTER) { 1076b7e1c893Smrg overscan_param.usOverscanTop = (adjusted_mode->CrtcVDisplay - mode->CrtcVDisplay) / 2; 1077b7e1c893Smrg overscan_param.usOverscanBottom = (adjusted_mode->CrtcVDisplay - mode->CrtcVDisplay) / 2; 1078b7e1c893Smrg overscan_param.usOverscanLeft = (adjusted_mode->CrtcHDisplay - mode->CrtcHDisplay) / 2; 1079b7e1c893Smrg overscan_param.usOverscanRight = (adjusted_mode->CrtcHDisplay - mode->CrtcHDisplay) / 2; 1080b7e1c893Smrg } else if (radeon_output->rmx_type == RMX_ASPECT) { 1081b7e1c893Smrg int a1 = mode->CrtcVDisplay * adjusted_mode->CrtcHDisplay; 1082b7e1c893Smrg int a2 = adjusted_mode->CrtcVDisplay * mode->CrtcHDisplay; 1083b7e1c893Smrg 1084b7e1c893Smrg if (a1 > a2) { 1085b7e1c893Smrg overscan_param.usOverscanLeft = (adjusted_mode->CrtcHDisplay - (a2 / mode->CrtcVDisplay)) / 2; 1086b7e1c893Smrg overscan_param.usOverscanRight = (adjusted_mode->CrtcHDisplay - (a2 / mode->CrtcVDisplay)) / 2; 1087b7e1c893Smrg } else if (a2 > a1) { 1088b7e1c893Smrg overscan_param.usOverscanLeft = (adjusted_mode->CrtcVDisplay - (a1 / mode->CrtcHDisplay)) / 2; 1089b7e1c893Smrg overscan_param.usOverscanRight = (adjusted_mode->CrtcVDisplay - (a1 / mode->CrtcHDisplay)) / 2; 1090b7e1c893Smrg } 1091209ff23fSmrg } 1092209ff23fSmrg } 1093209ff23fSmrg 1094b7e1c893Smrg data.exec.index = GetIndexIntoMasterTable(COMMAND, SetCRTC_OverScan); 1095209ff23fSmrg data.exec.dataSpace = (void *)&space; 1096b7e1c893Smrg data.exec.pspace = &overscan_param; 1097209ff23fSmrg 1098209ff23fSmrg if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { 1099b7e1c893Smrg ErrorF("Set CRTC %d Overscan success\n", radeon_crtc->crtc_id); 1100b7e1c893Smrg return ATOM_SUCCESS ; 1101209ff23fSmrg } 1102209ff23fSmrg 1103b7e1c893Smrg ErrorF("Set CRTC %d Overscan failed\n", radeon_crtc->crtc_id); 1104209ff23fSmrg return ATOM_NOT_IMPLEMENTED; 1105209ff23fSmrg} 1106209ff23fSmrg 1107209ff23fSmrgstatic int 1108b7e1c893Smrgatombios_output_scaler_setup(xf86OutputPtr output) 1109209ff23fSmrg{ 1110209ff23fSmrg RADEONInfoPtr info = RADEONPTR(output->scrn); 1111209ff23fSmrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 1112b7e1c893Smrg radeon_tvout_ptr tvout = &radeon_output->tvout; 1113209ff23fSmrg RADEONCrtcPrivatePtr radeon_crtc = output->crtc->driver_private; 1114209ff23fSmrg ENABLE_SCALER_PS_ALLOCATION disp_data; 1115209ff23fSmrg AtomBiosArgRec data; 1116209ff23fSmrg unsigned char *space; 1117209ff23fSmrg 1118b7e1c893Smrg if (!IS_AVIVO_VARIANT && radeon_crtc->crtc_id) 1119b7e1c893Smrg return ATOM_SUCCESS; 1120b7e1c893Smrg 1121b7e1c893Smrg memset(&disp_data, 0, sizeof(disp_data)); 1122b7e1c893Smrg 1123209ff23fSmrg disp_data.ucScaler = radeon_crtc->crtc_id; 1124209ff23fSmrg 1125b7e1c893Smrg if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT)) { 1126b7e1c893Smrg switch (tvout->tvStd) { 1127b7e1c893Smrg case TV_STD_NTSC: 1128b7e1c893Smrg disp_data.ucTVStandard = ATOM_TV_NTSC; 1129b7e1c893Smrg break; 1130b7e1c893Smrg case TV_STD_PAL: 1131b7e1c893Smrg disp_data.ucTVStandard = ATOM_TV_PAL; 1132b7e1c893Smrg break; 1133b7e1c893Smrg case TV_STD_PAL_M: 1134b7e1c893Smrg disp_data.ucTVStandard = ATOM_TV_PALM; 1135b7e1c893Smrg break; 1136b7e1c893Smrg case TV_STD_PAL_60: 1137b7e1c893Smrg disp_data.ucTVStandard = ATOM_TV_PAL60; 1138b7e1c893Smrg break; 1139b7e1c893Smrg case TV_STD_NTSC_J: 1140b7e1c893Smrg disp_data.ucTVStandard = ATOM_TV_NTSCJ; 1141b7e1c893Smrg break; 1142b7e1c893Smrg case TV_STD_SCART_PAL: 1143b7e1c893Smrg disp_data.ucTVStandard = ATOM_TV_PAL; /* ??? */ 1144b7e1c893Smrg break; 1145b7e1c893Smrg case TV_STD_SECAM: 1146b7e1c893Smrg disp_data.ucTVStandard = ATOM_TV_SECAM; 1147b7e1c893Smrg break; 1148b7e1c893Smrg case TV_STD_PAL_CN: 1149b7e1c893Smrg disp_data.ucTVStandard = ATOM_TV_PALCN; 1150b7e1c893Smrg break; 1151b7e1c893Smrg default: 1152b7e1c893Smrg disp_data.ucTVStandard = ATOM_TV_NTSC; 1153b7e1c893Smrg break; 1154b7e1c893Smrg } 1155b7e1c893Smrg disp_data.ucEnable = SCALER_ENABLE_MULTITAP_MODE; 1156b7e1c893Smrg ErrorF("Using TV scaler %x %x\n", disp_data.ucTVStandard, disp_data.ucEnable); 1157b7e1c893Smrg } else if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT)) { 1158b7e1c893Smrg disp_data.ucTVStandard = ATOM_TV_CV; 1159b7e1c893Smrg disp_data.ucEnable = SCALER_ENABLE_MULTITAP_MODE; 1160b7e1c893Smrg ErrorF("Using CV scaler %x %x\n", disp_data.ucTVStandard, disp_data.ucEnable); 1161b7e1c893Smrg } else if (radeon_output->Flags & RADEON_USE_RMX) { 1162209ff23fSmrg ErrorF("Using RMX\n"); 1163209ff23fSmrg if (radeon_output->rmx_type == RMX_FULL) 1164209ff23fSmrg disp_data.ucEnable = ATOM_SCALER_EXPANSION; 1165209ff23fSmrg else if (radeon_output->rmx_type == RMX_CENTER) 1166209ff23fSmrg disp_data.ucEnable = ATOM_SCALER_CENTER; 1167b7e1c893Smrg else if (radeon_output->rmx_type == RMX_ASPECT) 1168b7e1c893Smrg disp_data.ucEnable = ATOM_SCALER_EXPANSION; 1169209ff23fSmrg } else { 1170209ff23fSmrg ErrorF("Not using RMX\n"); 1171b7e1c893Smrg if (IS_AVIVO_VARIANT) 1172b7e1c893Smrg disp_data.ucEnable = ATOM_SCALER_DISABLE; 1173b7e1c893Smrg else 1174b7e1c893Smrg disp_data.ucEnable = ATOM_SCALER_CENTER; 1175209ff23fSmrg } 1176209ff23fSmrg 1177209ff23fSmrg data.exec.index = GetIndexIntoMasterTable(COMMAND, EnableScaler); 1178209ff23fSmrg data.exec.dataSpace = (void *)&space; 1179209ff23fSmrg data.exec.pspace = &disp_data; 1180209ff23fSmrg 1181209ff23fSmrg if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { 1182b7e1c893Smrg if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT) 1183b7e1c893Smrg && info->ChipFamily >= CHIP_FAMILY_RV515 && info->ChipFamily <= CHIP_FAMILY_RV570) { 1184b7e1c893Smrg ErrorF("forcing TV scaler\n"); 1185b7e1c893Smrg atom_rv515_force_tv_scaler(output->scrn); 1186b7e1c893Smrg } 1187209ff23fSmrg ErrorF("scaler %d setup success\n", radeon_crtc->crtc_id); 1188209ff23fSmrg return ATOM_SUCCESS; 1189209ff23fSmrg } 1190209ff23fSmrg 1191209ff23fSmrg ErrorF("scaler %d setup failed\n", radeon_crtc->crtc_id); 1192209ff23fSmrg return ATOM_NOT_IMPLEMENTED; 1193209ff23fSmrg 1194209ff23fSmrg} 1195209ff23fSmrg 1196b7e1c893Smrgvoid 1197b7e1c893Smrgatombios_output_dpms(xf86OutputPtr output, int mode) 1198209ff23fSmrg{ 1199b7e1c893Smrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 1200b7e1c893Smrg radeon_encoder_ptr radeon_encoder = radeon_get_encoder(output); 1201209ff23fSmrg RADEONInfoPtr info = RADEONPTR(output->scrn); 1202209ff23fSmrg DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION disp_data; 1203209ff23fSmrg AtomBiosArgRec data; 1204209ff23fSmrg unsigned char *space; 1205209ff23fSmrg int index = 0; 1206b7e1c893Smrg Bool is_dig = FALSE; 1207209ff23fSmrg 1208b7e1c893Smrg if (radeon_encoder == NULL) 1209b7e1c893Smrg return; 1210b7e1c893Smrg 1211b7e1c893Smrg switch (radeon_encoder->encoder_id) { 1212b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 1213b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 1214209ff23fSmrg index = GetIndexIntoMasterTable(COMMAND, TMDSAOutputControl); 1215209ff23fSmrg break; 1216b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 1217b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 1218b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 1219b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 1220b7e1c893Smrg is_dig = TRUE; 1221209ff23fSmrg break; 1222b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_DVO1: 1223b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_DDI: 1224b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 1225b7e1c893Smrg index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl); 1226209ff23fSmrg break; 1227b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_LVDS: 1228209ff23fSmrg index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl); 1229209ff23fSmrg break; 1230b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 1231b7e1c893Smrg if (radeon_output->active_device & (ATOM_DEVICE_LCD_SUPPORT)) 1232b7e1c893Smrg index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl); 1233b7e1c893Smrg else 1234b7e1c893Smrg index = GetIndexIntoMasterTable(COMMAND, LVTMAOutputControl); 1235209ff23fSmrg break; 1236b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_DAC1: 1237b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 1238b7e1c893Smrg if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT)) 1239b7e1c893Smrg index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl); 1240b7e1c893Smrg else if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT)) 1241b7e1c893Smrg index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl); 1242b7e1c893Smrg else 1243b7e1c893Smrg index = GetIndexIntoMasterTable(COMMAND, DAC1OutputControl); 1244209ff23fSmrg break; 1245b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_DAC2: 1246b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 1247b7e1c893Smrg if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT)) 1248b7e1c893Smrg index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl); 1249b7e1c893Smrg else if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT)) 1250b7e1c893Smrg index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl); 1251b7e1c893Smrg else 1252b7e1c893Smrg index = GetIndexIntoMasterTable(COMMAND, DAC2OutputControl); 1253209ff23fSmrg break; 1254209ff23fSmrg } 1255209ff23fSmrg 1256209ff23fSmrg switch (mode) { 1257209ff23fSmrg case DPMSModeOn: 1258b7e1c893Smrg radeon_encoder->devices |= radeon_output->active_device; 1259b7e1c893Smrg if (is_dig) 1260b7e1c893Smrg atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT); 1261b7e1c893Smrg else { 1262b7e1c893Smrg disp_data.ucAction = ATOM_ENABLE; 1263b7e1c893Smrg data.exec.index = index; 1264b7e1c893Smrg data.exec.dataSpace = (void *)&space; 1265b7e1c893Smrg data.exec.pspace = &disp_data; 1266b7e1c893Smrg 1267b7e1c893Smrg if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) 1268b7e1c893Smrg ErrorF("Output %s enable success\n", 1269b7e1c893Smrg device_name[radeon_get_device_index(radeon_output->active_device)]); 1270b7e1c893Smrg else 1271b7e1c893Smrg ErrorF("Output %s enable failed\n", 1272b7e1c893Smrg device_name[radeon_get_device_index(radeon_output->active_device)]); 1273b7e1c893Smrg } 1274209ff23fSmrg break; 1275209ff23fSmrg case DPMSModeStandby: 1276209ff23fSmrg case DPMSModeSuspend: 1277209ff23fSmrg case DPMSModeOff: 1278b7e1c893Smrg radeon_encoder->devices &= ~(radeon_output->active_device); 1279b7e1c893Smrg if (!radeon_encoder->devices) { 1280b7e1c893Smrg if (is_dig) 1281b7e1c893Smrg atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT); 1282b7e1c893Smrg else { 1283b7e1c893Smrg disp_data.ucAction = ATOM_DISABLE; 1284b7e1c893Smrg data.exec.index = index; 1285b7e1c893Smrg data.exec.dataSpace = (void *)&space; 1286b7e1c893Smrg data.exec.pspace = &disp_data; 1287b7e1c893Smrg 1288b7e1c893Smrg if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) 1289b7e1c893Smrg == ATOM_SUCCESS) 1290b7e1c893Smrg ErrorF("Output %s disable success\n", 1291b7e1c893Smrg device_name[radeon_get_device_index(radeon_output->active_device)]); 1292b7e1c893Smrg else 1293b7e1c893Smrg ErrorF("Output %s disable failed\n", 1294b7e1c893Smrg device_name[radeon_get_device_index(radeon_output->active_device)]); 1295b7e1c893Smrg } 1296209ff23fSmrg } 1297b7e1c893Smrg break; 1298209ff23fSmrg } 1299209ff23fSmrg} 1300209ff23fSmrg 1301209ff23fSmrgstatic void 1302209ff23fSmrgatombios_set_output_crtc_source(xf86OutputPtr output) 1303209ff23fSmrg{ 1304209ff23fSmrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 1305209ff23fSmrg RADEONCrtcPrivatePtr radeon_crtc = output->crtc->driver_private; 1306209ff23fSmrg RADEONInfoPtr info = RADEONPTR(output->scrn); 1307b7e1c893Smrg radeon_encoder_ptr radeon_encoder = radeon_get_encoder(output); 1308209ff23fSmrg AtomBiosArgRec data; 1309209ff23fSmrg unsigned char *space; 1310209ff23fSmrg SELECT_CRTC_SOURCE_PS_ALLOCATION crtc_src_param; 1311209ff23fSmrg SELECT_CRTC_SOURCE_PARAMETERS_V2 crtc_src_param2; 1312209ff23fSmrg int index = GetIndexIntoMasterTable(COMMAND, SelectCRTC_Source); 1313209ff23fSmrg int major, minor; 1314209ff23fSmrg 1315b7e1c893Smrg if (radeon_encoder == NULL) 1316b7e1c893Smrg return; 1317b7e1c893Smrg 1318b7e1c893Smrg memset(&crtc_src_param, 0, sizeof(crtc_src_param)); 1319b7e1c893Smrg memset(&crtc_src_param2, 0, sizeof(crtc_src_param2)); 1320209ff23fSmrg atombios_get_command_table_version(info->atomBIOS, index, &major, &minor); 1321209ff23fSmrg 1322209ff23fSmrg /*ErrorF("select crtc source table is %d %d\n", major, minor);*/ 1323209ff23fSmrg 1324209ff23fSmrg switch(major) { 1325b7e1c893Smrg case 1: 1326209ff23fSmrg switch(minor) { 1327209ff23fSmrg case 0: 1328209ff23fSmrg case 1: 1329209ff23fSmrg default: 1330b7e1c893Smrg if (IS_AVIVO_VARIANT) 1331b7e1c893Smrg crtc_src_param.ucCRTC = radeon_crtc->crtc_id; 1332b7e1c893Smrg else { 1333b7e1c893Smrg if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1) 1334b7e1c893Smrg crtc_src_param.ucCRTC = radeon_crtc->crtc_id; 1335b7e1c893Smrg else 1336b7e1c893Smrg crtc_src_param.ucCRTC = radeon_crtc->crtc_id << 2; 1337b7e1c893Smrg } 1338b7e1c893Smrg switch (radeon_encoder->encoder_id) { 1339b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 1340b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 1341b7e1c893Smrg crtc_src_param.ucDevice = ATOM_DEVICE_DFP1_INDEX; 1342b7e1c893Smrg break; 1343b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_LVDS: 1344b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 1345b7e1c893Smrg if (radeon_output->active_device & ATOM_DEVICE_LCD1_SUPPORT) 1346209ff23fSmrg crtc_src_param.ucDevice = ATOM_DEVICE_LCD1_INDEX; 1347b7e1c893Smrg else 1348b7e1c893Smrg crtc_src_param.ucDevice = ATOM_DEVICE_DFP3_INDEX; 1349b7e1c893Smrg break; 1350b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_DVO1: 1351b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_DDI: 1352b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 1353b7e1c893Smrg crtc_src_param.ucDevice = ATOM_DEVICE_DFP2_INDEX; 1354b7e1c893Smrg break; 1355b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_DAC1: 1356b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 1357b7e1c893Smrg if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT)) 1358b7e1c893Smrg crtc_src_param.ucDevice = ATOM_DEVICE_TV1_INDEX; 1359b7e1c893Smrg else if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT)) 1360b7e1c893Smrg crtc_src_param.ucDevice = ATOM_DEVICE_CV_INDEX; 1361b7e1c893Smrg else 1362b7e1c893Smrg crtc_src_param.ucDevice = ATOM_DEVICE_CRT1_INDEX; 1363b7e1c893Smrg break; 1364b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_DAC2: 1365b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 1366b7e1c893Smrg if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT)) 1367209ff23fSmrg crtc_src_param.ucDevice = ATOM_DEVICE_TV1_INDEX; 1368b7e1c893Smrg else if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT)) 1369209ff23fSmrg crtc_src_param.ucDevice = ATOM_DEVICE_CV_INDEX; 1370b7e1c893Smrg else 1371b7e1c893Smrg crtc_src_param.ucDevice = ATOM_DEVICE_CRT2_INDEX; 1372b7e1c893Smrg break; 1373209ff23fSmrg } 1374209ff23fSmrg data.exec.pspace = &crtc_src_param; 1375209ff23fSmrg /*ErrorF("device sourced: 0x%x\n", crtc_src_param.ucDevice);*/ 1376209ff23fSmrg break; 1377209ff23fSmrg case 2: 1378209ff23fSmrg crtc_src_param2.ucCRTC = radeon_crtc->crtc_id; 1379b7e1c893Smrg crtc_src_param2.ucEncodeMode = atombios_get_encoder_mode(output); 1380b7e1c893Smrg switch (radeon_encoder->encoder_id) { 1381b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 1382b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 1383b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 1384b7e1c893Smrg if (IS_DCE32_VARIANT) { 1385b7e1c893Smrg if (radeon_crtc->crtc_id) 1386b7e1c893Smrg crtc_src_param2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID; 1387b7e1c893Smrg else 1388b7e1c893Smrg crtc_src_param2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID; 1389b7e1c893Smrg } else 1390b7e1c893Smrg crtc_src_param2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID; 1391b7e1c893Smrg break; 1392b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 1393b7e1c893Smrg crtc_src_param2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID; 1394b7e1c893Smrg break; 1395b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 1396b7e1c893Smrg if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT)) 1397b7e1c893Smrg crtc_src_param2.ucEncoderID = ASIC_INT_TV_ENCODER_ID; 1398b7e1c893Smrg else if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT)) 1399b7e1c893Smrg crtc_src_param2.ucEncoderID = ASIC_INT_TV_ENCODER_ID; 1400b7e1c893Smrg else 1401b7e1c893Smrg crtc_src_param2.ucEncoderID = ASIC_INT_DAC1_ENCODER_ID; 1402b7e1c893Smrg break; 1403b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 1404b7e1c893Smrg if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT)) 1405b7e1c893Smrg crtc_src_param2.ucEncoderID = ASIC_INT_TV_ENCODER_ID; 1406b7e1c893Smrg else if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT)) 1407b7e1c893Smrg crtc_src_param2.ucEncoderID = ASIC_INT_TV_ENCODER_ID; 1408b7e1c893Smrg else 1409b7e1c893Smrg crtc_src_param2.ucEncoderID = ASIC_INT_DAC2_ENCODER_ID; 1410b7e1c893Smrg break; 1411209ff23fSmrg } 1412209ff23fSmrg data.exec.pspace = &crtc_src_param2; 1413209ff23fSmrg /*ErrorF("device sourced: 0x%x\n", crtc_src_param2.ucEncoderID);*/ 1414209ff23fSmrg break; 1415209ff23fSmrg } 1416209ff23fSmrg break; 1417209ff23fSmrg default: 1418b7e1c893Smrg ErrorF("Unknown table version\n"); 1419b7e1c893Smrg exit(-1); 1420209ff23fSmrg } 1421209ff23fSmrg 1422209ff23fSmrg data.exec.index = index; 1423209ff23fSmrg data.exec.dataSpace = (void *)&space; 1424209ff23fSmrg 1425209ff23fSmrg if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { 1426209ff23fSmrg ErrorF("Set CRTC %d Source success\n", radeon_crtc->crtc_id); 1427209ff23fSmrg return; 1428209ff23fSmrg } 1429209ff23fSmrg 1430209ff23fSmrg ErrorF("Set CRTC Source failed\n"); 1431209ff23fSmrg return; 1432209ff23fSmrg} 1433209ff23fSmrg 1434b7e1c893Smrgstatic void 1435b7e1c893Smrgatombios_apply_output_quirks(xf86OutputPtr output, DisplayModePtr mode) 1436b7e1c893Smrg{ 1437b7e1c893Smrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 1438b7e1c893Smrg RADEONCrtcPrivatePtr radeon_crtc = output->crtc->driver_private; 1439b7e1c893Smrg RADEONInfoPtr info = RADEONPTR(output->scrn); 1440b7e1c893Smrg unsigned char *RADEONMMIO = info->MMIO; 1441b7e1c893Smrg 1442b7e1c893Smrg /* Funky macbooks */ 1443b7e1c893Smrg if ((info->Chipset == PCI_CHIP_RV530_71C5) && 1444b7e1c893Smrg (PCI_SUB_VENDOR_ID(info->PciInfo) == 0x106b) && 1445b7e1c893Smrg (PCI_SUB_DEVICE_ID(info->PciInfo) == 0x0080)) { 1446b7e1c893Smrg if (radeon_output->MonType == MT_LCD) { 1447b7e1c893Smrg if (radeon_output->devices & ATOM_DEVICE_LCD1_SUPPORT) { 1448b7e1c893Smrg uint32_t lvtma_bit_depth_control = INREG(AVIVO_LVTMA_BIT_DEPTH_CONTROL); 1449b7e1c893Smrg 1450b7e1c893Smrg lvtma_bit_depth_control &= ~AVIVO_LVTMA_BIT_DEPTH_CONTROL_TRUNCATE_EN; 1451b7e1c893Smrg lvtma_bit_depth_control &= ~AVIVO_LVTMA_BIT_DEPTH_CONTROL_SPATIAL_DITHER_EN; 1452b7e1c893Smrg 1453b7e1c893Smrg OUTREG(AVIVO_LVTMA_BIT_DEPTH_CONTROL, lvtma_bit_depth_control); 1454b7e1c893Smrg } 1455b7e1c893Smrg } 1456b7e1c893Smrg } 1457b7e1c893Smrg 1458b7e1c893Smrg /* set scaler clears this on some chips */ 1459b7e1c893Smrg if (IS_AVIVO_VARIANT && (mode->Flags & V_INTERLACE)) 1460b7e1c893Smrg OUTREG(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset, AVIVO_D1MODE_INTERLEAVE_EN); 1461b7e1c893Smrg} 1462b7e1c893Smrg 1463209ff23fSmrgvoid 1464209ff23fSmrgatombios_output_mode_set(xf86OutputPtr output, 1465209ff23fSmrg DisplayModePtr mode, 1466209ff23fSmrg DisplayModePtr adjusted_mode) 1467209ff23fSmrg{ 1468209ff23fSmrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 1469b7e1c893Smrg RADEONCrtcPrivatePtr radeon_crtc = output->crtc->driver_private; 1470b7e1c893Smrg radeon_encoder_ptr radeon_encoder = radeon_get_encoder(output); 1471209ff23fSmrg RADEONInfoPtr info = RADEONPTR(output->scrn); 1472b7e1c893Smrg if (radeon_encoder == NULL) 1473b7e1c893Smrg return; 1474209ff23fSmrg 1475b7e1c893Smrg radeon_output->pixel_clock = adjusted_mode->Clock; 1476b7e1c893Smrg radeon_output->dig_block = radeon_crtc->crtc_id; 1477b7e1c893Smrg atombios_output_overscan_setup(output, mode, adjusted_mode); 1478b7e1c893Smrg atombios_output_scaler_setup(output); 1479209ff23fSmrg atombios_set_output_crtc_source(output); 1480209ff23fSmrg 1481b7e1c893Smrg if (IS_AVIVO_VARIANT) { 1482b7e1c893Smrg if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT)) 1483b7e1c893Smrg atombios_output_yuv_setup(output, TRUE); 1484b7e1c893Smrg else 1485b7e1c893Smrg atombios_output_yuv_setup(output, FALSE); 1486209ff23fSmrg } 1487209ff23fSmrg 1488b7e1c893Smrg switch (radeon_encoder->encoder_id) { 1489b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 1490b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 1491b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_LVDS: 1492b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 1493b7e1c893Smrg atombios_output_digital_setup(output, PANEL_ENCODER_ACTION_ENABLE); 1494b7e1c893Smrg break; 1495b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 1496b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 1497b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 1498b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 1499b7e1c893Smrg /* disable encoder and transmitter */ 1500b7e1c893Smrg atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_DISABLE); 1501b7e1c893Smrg atombios_output_dig_encoder_setup(output, ATOM_DISABLE); 1502b7e1c893Smrg 1503b7e1c893Smrg /* setup and enable the encoder and transmitter */ 1504b7e1c893Smrg atombios_output_dig_encoder_setup(output, ATOM_ENABLE); 1505b7e1c893Smrg atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_SETUP); 1506b7e1c893Smrg atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_ENABLE); 1507b7e1c893Smrg break; 1508b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_DDI: 1509b7e1c893Smrg atombios_output_ddia_setup(output, ATOM_ENABLE); 1510b7e1c893Smrg break; 1511b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_DVO1: 1512b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 1513b7e1c893Smrg atombios_external_tmds_setup(output, ATOM_ENABLE); 1514b7e1c893Smrg break; 1515b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_DAC1: 1516b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 1517b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_DAC2: 1518b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 1519b7e1c893Smrg atombios_output_dac_setup(output, ATOM_ENABLE); 1520b7e1c893Smrg if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) 1521b7e1c893Smrg atombios_output_tv_setup(output, ATOM_ENABLE); 1522b7e1c893Smrg break; 1523b7e1c893Smrg } 1524b7e1c893Smrg atombios_apply_output_quirks(output, adjusted_mode); 1525209ff23fSmrg} 1526209ff23fSmrg 1527209ff23fSmrgstatic AtomBiosResult 1528209ff23fSmrgatom_bios_dac_load_detect(atomBiosHandlePtr atomBIOS, xf86OutputPtr output) 1529209ff23fSmrg{ 1530209ff23fSmrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 1531209ff23fSmrg RADEONInfoPtr info = RADEONPTR(output->scrn); 1532209ff23fSmrg DAC_LOAD_DETECTION_PS_ALLOCATION dac_data; 1533209ff23fSmrg AtomBiosArgRec data; 1534209ff23fSmrg unsigned char *space; 1535b7e1c893Smrg int major, minor; 1536b7e1c893Smrg int index = GetIndexIntoMasterTable(COMMAND, DAC_LoadDetection); 1537b7e1c893Smrg 1538b7e1c893Smrg atombios_get_command_table_version(info->atomBIOS, index, &major, &minor); 1539209ff23fSmrg 1540209ff23fSmrg dac_data.sDacload.ucMisc = 0; 1541209ff23fSmrg 1542209ff23fSmrg if (radeon_output->devices & ATOM_DEVICE_CRT1_SUPPORT) { 1543b7e1c893Smrg dac_data.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT1_SUPPORT); 1544b7e1c893Smrg if (info->encoders[ATOM_DEVICE_CRT1_INDEX] && 1545b7e1c893Smrg ((info->encoders[ATOM_DEVICE_CRT1_INDEX]->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1) || 1546b7e1c893Smrg (info->encoders[ATOM_DEVICE_CRT1_INDEX]->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1))) 1547209ff23fSmrg dac_data.sDacload.ucDacType = ATOM_DAC_A; 1548b7e1c893Smrg else 1549209ff23fSmrg dac_data.sDacload.ucDacType = ATOM_DAC_B; 1550209ff23fSmrg } else if (radeon_output->devices & ATOM_DEVICE_CRT2_SUPPORT) { 1551b7e1c893Smrg dac_data.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT2_SUPPORT); 1552b7e1c893Smrg if (info->encoders[ATOM_DEVICE_CRT2_INDEX] && 1553b7e1c893Smrg ((info->encoders[ATOM_DEVICE_CRT2_INDEX]->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1) || 1554b7e1c893Smrg (info->encoders[ATOM_DEVICE_CRT2_INDEX]->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1))) 1555209ff23fSmrg dac_data.sDacload.ucDacType = ATOM_DAC_A; 1556b7e1c893Smrg else 1557209ff23fSmrg dac_data.sDacload.ucDacType = ATOM_DAC_B; 1558209ff23fSmrg } else if (radeon_output->devices & ATOM_DEVICE_CV_SUPPORT) { 1559b7e1c893Smrg dac_data.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CV_SUPPORT); 1560b7e1c893Smrg if (info->encoders[ATOM_DEVICE_CV_INDEX] && 1561b7e1c893Smrg ((info->encoders[ATOM_DEVICE_CV_INDEX]->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1) || 1562b7e1c893Smrg (info->encoders[ATOM_DEVICE_CV_INDEX]->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1))) 1563209ff23fSmrg dac_data.sDacload.ucDacType = ATOM_DAC_A; 1564b7e1c893Smrg else 1565209ff23fSmrg dac_data.sDacload.ucDacType = ATOM_DAC_B; 1566b7e1c893Smrg if (minor >= 3) 1567b7e1c893Smrg dac_data.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb; 1568209ff23fSmrg } else if (radeon_output->devices & ATOM_DEVICE_TV1_SUPPORT) { 1569b7e1c893Smrg dac_data.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_TV1_SUPPORT); 1570b7e1c893Smrg if (info->encoders[ATOM_DEVICE_TV1_INDEX] && 1571b7e1c893Smrg ((info->encoders[ATOM_DEVICE_TV1_INDEX]->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1) || 1572b7e1c893Smrg (info->encoders[ATOM_DEVICE_TV1_INDEX]->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1))) 1573209ff23fSmrg dac_data.sDacload.ucDacType = ATOM_DAC_A; 1574b7e1c893Smrg else 1575209ff23fSmrg dac_data.sDacload.ucDacType = ATOM_DAC_B; 1576b7e1c893Smrg if (minor >= 3) 1577b7e1c893Smrg dac_data.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb; 1578b7e1c893Smrg } else 1579209ff23fSmrg return ATOM_NOT_IMPLEMENTED; 1580209ff23fSmrg 1581b7e1c893Smrg data.exec.index = index; 1582209ff23fSmrg data.exec.dataSpace = (void *)&space; 1583209ff23fSmrg data.exec.pspace = &dac_data; 1584209ff23fSmrg 1585209ff23fSmrg if (RHDAtomBiosFunc(atomBIOS->scrnIndex, atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { 1586209ff23fSmrg ErrorF("Dac detection success\n"); 1587209ff23fSmrg return ATOM_SUCCESS ; 1588209ff23fSmrg } 1589209ff23fSmrg 1590209ff23fSmrg ErrorF("DAC detection failed\n"); 1591209ff23fSmrg return ATOM_NOT_IMPLEMENTED; 1592209ff23fSmrg} 1593209ff23fSmrg 1594209ff23fSmrgRADEONMonitorType 1595b7e1c893Smrgatombios_dac_detect(xf86OutputPtr output) 1596209ff23fSmrg{ 1597b7e1c893Smrg ScrnInfoPtr pScrn = output->scrn; 1598209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 1599209ff23fSmrg unsigned char *RADEONMMIO = info->MMIO; 1600209ff23fSmrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 1601209ff23fSmrg RADEONMonitorType MonType = MT_NONE; 1602209ff23fSmrg AtomBiosResult ret; 1603209ff23fSmrg uint32_t bios_0_scratch; 1604209ff23fSmrg 1605b7e1c893Smrg if (radeon_output->devices & ATOM_DEVICE_TV1_SUPPORT) { 1606209ff23fSmrg if (xf86ReturnOptValBool(info->Options, OPTION_FORCE_TVOUT, FALSE)) { 1607b7e1c893Smrg if (radeon_output->ConnectorType == CONNECTOR_STV) 1608209ff23fSmrg return MT_STV; 1609209ff23fSmrg else 1610209ff23fSmrg return MT_CTV; 1611209ff23fSmrg } 1612209ff23fSmrg } 1613209ff23fSmrg 1614209ff23fSmrg ret = atom_bios_dac_load_detect(info->atomBIOS, output); 1615209ff23fSmrg if (ret == ATOM_SUCCESS) { 1616209ff23fSmrg if (info->ChipFamily >= CHIP_FAMILY_R600) 1617209ff23fSmrg bios_0_scratch = INREG(R600_BIOS_0_SCRATCH); 1618209ff23fSmrg else 1619209ff23fSmrg bios_0_scratch = INREG(RADEON_BIOS_0_SCRATCH); 1620209ff23fSmrg /*ErrorF("DAC connect %08X\n", (unsigned int)bios_0_scratch);*/ 1621209ff23fSmrg 1622209ff23fSmrg if (radeon_output->devices & ATOM_DEVICE_CRT1_SUPPORT) { 1623209ff23fSmrg if (bios_0_scratch & ATOM_S0_CRT1_MASK) 1624209ff23fSmrg MonType = MT_CRT; 1625209ff23fSmrg } else if (radeon_output->devices & ATOM_DEVICE_CRT2_SUPPORT) { 1626209ff23fSmrg if (bios_0_scratch & ATOM_S0_CRT2_MASK) 1627209ff23fSmrg MonType = MT_CRT; 1628209ff23fSmrg } else if (radeon_output->devices & ATOM_DEVICE_CV_SUPPORT) { 1629209ff23fSmrg if (bios_0_scratch & (ATOM_S0_CV_MASK | ATOM_S0_CV_MASK_A)) 1630209ff23fSmrg MonType = MT_CV; 1631209ff23fSmrg } else if (radeon_output->devices & ATOM_DEVICE_TV1_SUPPORT) { 1632209ff23fSmrg if (bios_0_scratch & (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A)) 1633209ff23fSmrg MonType = MT_CTV; 1634209ff23fSmrg else if (bios_0_scratch & (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A)) 1635209ff23fSmrg MonType = MT_STV; 1636209ff23fSmrg } 1637209ff23fSmrg } 1638209ff23fSmrg 1639209ff23fSmrg return MonType; 1640209ff23fSmrg} 1641209ff23fSmrg 1642