atombios_output.c revision 2f39173d
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 68ad43ddacSmrgstatic void do_displayport_link_train(xf86OutputPtr output); 69ad43ddacSmrg 70c503f109Smrgstatic void atombios_set_output_crtc_source(xf86OutputPtr output); 71c503f109Smrg 72209ff23fSmrgstatic int 73b7e1c893Smrgatombios_output_dac_setup(xf86OutputPtr output, int action) 74209ff23fSmrg{ 75209ff23fSmrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 76209ff23fSmrg RADEONInfoPtr info = RADEONPTR(output->scrn); 77b7e1c893Smrg radeon_encoder_ptr radeon_encoder = radeon_get_encoder(output); 78b7e1c893Smrg radeon_tvout_ptr tvout = &radeon_output->tvout; 79209ff23fSmrg DAC_ENCODER_CONTROL_PS_ALLOCATION disp_data; 80209ff23fSmrg AtomBiosArgRec data; 81209ff23fSmrg unsigned char *space; 82b7e1c893Smrg int index = 0, num = 0; 83b7e1c893Smrg int clock = radeon_output->pixel_clock; 84b7e1c893Smrg 85b7e1c893Smrg if (radeon_encoder == NULL) 86b7e1c893Smrg return ATOM_NOT_IMPLEMENTED; 87b7e1c893Smrg 88b7e1c893Smrg memset(&disp_data,0, sizeof(disp_data)); 89b7e1c893Smrg 90b7e1c893Smrg switch (radeon_encoder->encoder_id) { 91b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_DAC1: 92b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 93b7e1c893Smrg index = GetIndexIntoMasterTable(COMMAND, DAC1EncoderControl); 94b7e1c893Smrg num = 1; 95b7e1c893Smrg break; 96b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_DAC2: 97b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 98b7e1c893Smrg index = GetIndexIntoMasterTable(COMMAND, DAC2EncoderControl); 99b7e1c893Smrg num = 2; 100b7e1c893Smrg break; 101b7e1c893Smrg } 102209ff23fSmrg 103b7e1c893Smrg disp_data.ucAction =action; 104209ff23fSmrg 105b7e1c893Smrg if (radeon_output->active_device & (ATOM_DEVICE_CRT_SUPPORT)) 106209ff23fSmrg disp_data.ucDacStandard = ATOM_DAC1_PS2; 107b7e1c893Smrg else if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT)) 108209ff23fSmrg disp_data.ucDacStandard = ATOM_DAC1_CV; 109b7e1c893Smrg else { 110b7e1c893Smrg switch (tvout->tvStd) { 111209ff23fSmrg case TV_STD_PAL: 112209ff23fSmrg case TV_STD_PAL_M: 113209ff23fSmrg case TV_STD_SCART_PAL: 114209ff23fSmrg case TV_STD_SECAM: 115209ff23fSmrg case TV_STD_PAL_CN: 116209ff23fSmrg disp_data.ucDacStandard = ATOM_DAC1_PAL; 117209ff23fSmrg break; 118209ff23fSmrg case TV_STD_NTSC: 119209ff23fSmrg case TV_STD_NTSC_J: 120209ff23fSmrg case TV_STD_PAL_60: 121209ff23fSmrg default: 122b7e1c893Smrg disp_data.ucDacStandard = ATOM_DAC1_NTSC; 123209ff23fSmrg break; 124209ff23fSmrg } 125209ff23fSmrg } 126b7e1c893Smrg disp_data.usPixelClock = cpu_to_le16(clock / 10); 127209ff23fSmrg 128b7e1c893Smrg data.exec.index = index; 129209ff23fSmrg data.exec.dataSpace = (void *)&space; 130209ff23fSmrg data.exec.pspace = &disp_data; 131209ff23fSmrg 132209ff23fSmrg if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { 133b7e1c893Smrg ErrorF("Output DAC%d setup success\n", num); 134209ff23fSmrg return ATOM_SUCCESS; 135209ff23fSmrg } 136209ff23fSmrg 137b7e1c893Smrg ErrorF("Output DAC%d setup failed\n", num); 138209ff23fSmrg return ATOM_NOT_IMPLEMENTED; 139209ff23fSmrg 140209ff23fSmrg} 141209ff23fSmrg 142209ff23fSmrgstatic int 143b7e1c893Smrgatombios_output_tv_setup(xf86OutputPtr output, int action) 144209ff23fSmrg{ 145209ff23fSmrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 146b7e1c893Smrg radeon_tvout_ptr tvout = &radeon_output->tvout; 147209ff23fSmrg RADEONInfoPtr info = RADEONPTR(output->scrn); 148209ff23fSmrg TV_ENCODER_CONTROL_PS_ALLOCATION disp_data; 149209ff23fSmrg AtomBiosArgRec data; 150209ff23fSmrg unsigned char *space; 151b7e1c893Smrg int clock = radeon_output->pixel_clock; 152b7e1c893Smrg 153b7e1c893Smrg memset(&disp_data,0, sizeof(disp_data)); 154209ff23fSmrg 155b7e1c893Smrg disp_data.sTVEncoder.ucAction = action; 156209ff23fSmrg 157b7e1c893Smrg if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT)) 158209ff23fSmrg disp_data.sTVEncoder.ucTvStandard = ATOM_TV_CV; 159209ff23fSmrg else { 160b7e1c893Smrg switch (tvout->tvStd) { 161209ff23fSmrg case TV_STD_NTSC: 162209ff23fSmrg disp_data.sTVEncoder.ucTvStandard = ATOM_TV_NTSC; 163209ff23fSmrg break; 164209ff23fSmrg case TV_STD_PAL: 165209ff23fSmrg disp_data.sTVEncoder.ucTvStandard = ATOM_TV_PAL; 166209ff23fSmrg break; 167209ff23fSmrg case TV_STD_PAL_M: 168209ff23fSmrg disp_data.sTVEncoder.ucTvStandard = ATOM_TV_PALM; 169209ff23fSmrg break; 170209ff23fSmrg case TV_STD_PAL_60: 171209ff23fSmrg disp_data.sTVEncoder.ucTvStandard = ATOM_TV_PAL60; 172209ff23fSmrg break; 173209ff23fSmrg case TV_STD_NTSC_J: 174209ff23fSmrg disp_data.sTVEncoder.ucTvStandard = ATOM_TV_NTSCJ; 175209ff23fSmrg break; 176209ff23fSmrg case TV_STD_SCART_PAL: 177209ff23fSmrg disp_data.sTVEncoder.ucTvStandard = ATOM_TV_PAL; /* ??? */ 178209ff23fSmrg break; 179209ff23fSmrg case TV_STD_SECAM: 180209ff23fSmrg disp_data.sTVEncoder.ucTvStandard = ATOM_TV_SECAM; 181209ff23fSmrg break; 182209ff23fSmrg case TV_STD_PAL_CN: 183209ff23fSmrg disp_data.sTVEncoder.ucTvStandard = ATOM_TV_PALCN; 184209ff23fSmrg break; 185209ff23fSmrg default: 186209ff23fSmrg disp_data.sTVEncoder.ucTvStandard = ATOM_TV_NTSC; 187209ff23fSmrg break; 188209ff23fSmrg } 189209ff23fSmrg } 190209ff23fSmrg 191b7e1c893Smrg disp_data.sTVEncoder.usPixelClock = cpu_to_le16(clock / 10); 192209ff23fSmrg data.exec.index = GetIndexIntoMasterTable(COMMAND, TVEncoderControl); 193209ff23fSmrg data.exec.dataSpace = (void *)&space; 194209ff23fSmrg data.exec.pspace = &disp_data; 195209ff23fSmrg 196209ff23fSmrg if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { 197b7e1c893Smrg ErrorF("Output TV setup success\n"); 198209ff23fSmrg return ATOM_SUCCESS; 199209ff23fSmrg } 200209ff23fSmrg 201b7e1c893Smrg ErrorF("Output TV setup failed\n"); 202209ff23fSmrg return ATOM_NOT_IMPLEMENTED; 203209ff23fSmrg 204209ff23fSmrg} 205209ff23fSmrg 206209ff23fSmrgint 207b7e1c893Smrgatombios_external_tmds_setup(xf86OutputPtr output, int action) 208209ff23fSmrg{ 209b7e1c893Smrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 210b7e1c893Smrg ScrnInfoPtr pScrn = output->scrn; 211b7e1c893Smrg RADEONInfoPtr info = RADEONPTR(pScrn); 212209ff23fSmrg ENABLE_EXTERNAL_TMDS_ENCODER_PS_ALLOCATION disp_data; 213209ff23fSmrg AtomBiosArgRec data; 214209ff23fSmrg unsigned char *space; 215b7e1c893Smrg int clock = radeon_output->pixel_clock; 216209ff23fSmrg 217b7e1c893Smrg memset(&disp_data,0, sizeof(disp_data)); 218209ff23fSmrg 219b7e1c893Smrg disp_data.sXTmdsEncoder.ucEnable = action; 220b7e1c893Smrg 221b7e1c893Smrg if (clock > 165000) 222b7e1c893Smrg disp_data.sXTmdsEncoder.ucMisc = PANEL_ENCODER_MISC_DUAL; 223209ff23fSmrg 224b7e1c893Smrg if (pScrn->rgbBits == 8) 225209ff23fSmrg disp_data.sXTmdsEncoder.ucMisc |= (1 << 1); 226209ff23fSmrg 227209ff23fSmrg data.exec.index = GetIndexIntoMasterTable(COMMAND, DVOEncoderControl); 228209ff23fSmrg data.exec.dataSpace = (void *)&space; 229209ff23fSmrg data.exec.pspace = &disp_data; 230209ff23fSmrg 231209ff23fSmrg if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { 232209ff23fSmrg ErrorF("External TMDS setup success\n"); 233209ff23fSmrg return ATOM_SUCCESS; 234209ff23fSmrg } 235209ff23fSmrg 236209ff23fSmrg ErrorF("External TMDS setup failed\n"); 237209ff23fSmrg return ATOM_NOT_IMPLEMENTED; 238209ff23fSmrg} 239209ff23fSmrg 240209ff23fSmrgstatic int 241b7e1c893Smrgatombios_output_ddia_setup(xf86OutputPtr output, int action) 242209ff23fSmrg{ 243b7e1c893Smrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 244209ff23fSmrg RADEONInfoPtr info = RADEONPTR(output->scrn); 245209ff23fSmrg DVO_ENCODER_CONTROL_PS_ALLOCATION disp_data; 246209ff23fSmrg AtomBiosArgRec data; 247209ff23fSmrg unsigned char *space; 248b7e1c893Smrg int clock = radeon_output->pixel_clock; 249b7e1c893Smrg 250b7e1c893Smrg memset(&disp_data,0, sizeof(disp_data)); 251209ff23fSmrg 252b7e1c893Smrg disp_data.sDVOEncoder.ucAction = action; 253b7e1c893Smrg disp_data.sDVOEncoder.usPixelClock = cpu_to_le16(clock / 10); 254209ff23fSmrg 255b7e1c893Smrg if (clock > 165000) 256209ff23fSmrg disp_data.sDVOEncoder.usDevAttr.sDigAttrib.ucAttribute = PANEL_ENCODER_MISC_DUAL; 257209ff23fSmrg 258209ff23fSmrg data.exec.index = GetIndexIntoMasterTable(COMMAND, DVOEncoderControl); 259209ff23fSmrg data.exec.dataSpace = (void *)&space; 260209ff23fSmrg data.exec.pspace = &disp_data; 261209ff23fSmrg 262209ff23fSmrg if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { 263209ff23fSmrg ErrorF("DDIA setup success\n"); 264209ff23fSmrg return ATOM_SUCCESS; 265209ff23fSmrg } 266209ff23fSmrg 267209ff23fSmrg ErrorF("DDIA setup failed\n"); 268209ff23fSmrg return ATOM_NOT_IMPLEMENTED; 269209ff23fSmrg} 270209ff23fSmrg 271209ff23fSmrgstatic int 272b7e1c893Smrgatombios_output_digital_setup(xf86OutputPtr output, int action) 273209ff23fSmrg{ 274b7e1c893Smrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 275b7e1c893Smrg ScrnInfoPtr pScrn = output->scrn; 276b7e1c893Smrg RADEONInfoPtr info = RADEONPTR(pScrn); 277b7e1c893Smrg radeon_encoder_ptr radeon_encoder = radeon_get_encoder(output); 278b7e1c893Smrg LVDS_ENCODER_CONTROL_PS_ALLOCATION disp_data; 279b7e1c893Smrg LVDS_ENCODER_CONTROL_PS_ALLOCATION_V2 disp_data2; 280209ff23fSmrg AtomBiosArgRec data; 281209ff23fSmrg unsigned char *space; 282b7e1c893Smrg int index = 0; 283b7e1c893Smrg int major, minor; 284b7e1c893Smrg int lvds_misc = 0; 285b7e1c893Smrg int clock = radeon_output->pixel_clock; 286209ff23fSmrg 287b7e1c893Smrg if (radeon_encoder == NULL) 288b7e1c893Smrg return ATOM_NOT_IMPLEMENTED; 289b7e1c893Smrg 290b7e1c893Smrg if (radeon_output->active_device & (ATOM_DEVICE_LCD_SUPPORT)) { 291b7e1c893Smrg radeon_lvds_ptr lvds = (radeon_lvds_ptr)radeon_encoder->dev_priv; 292b7e1c893Smrg if (lvds == NULL) 293b7e1c893Smrg return ATOM_NOT_IMPLEMENTED; 294b7e1c893Smrg lvds_misc = lvds->lvds_misc; 295b7e1c893Smrg } 296b7e1c893Smrg 297b7e1c893Smrg memset(&disp_data,0, sizeof(disp_data)); 298b7e1c893Smrg memset(&disp_data2,0, sizeof(disp_data2)); 299b7e1c893Smrg 300b7e1c893Smrg switch (radeon_encoder->encoder_id) { 301b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_LVDS: 302b7e1c893Smrg index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl); 303b7e1c893Smrg break; 304b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 305b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 306b7e1c893Smrg index = GetIndexIntoMasterTable(COMMAND, TMDS1EncoderControl); 307b7e1c893Smrg break; 308b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 309b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 310b7e1c893Smrg if (radeon_output->active_device & (ATOM_DEVICE_LCD_SUPPORT)) 311b7e1c893Smrg index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl); 312b7e1c893Smrg else 313b7e1c893Smrg index = GetIndexIntoMasterTable(COMMAND, TMDS2EncoderControl); 314b7e1c893Smrg break; 315b7e1c893Smrg } 316b7e1c893Smrg 317b7e1c893Smrg atombios_get_command_table_version(info->atomBIOS, index, &major, &minor); 318b7e1c893Smrg 319b7e1c893Smrg /*ErrorF("table is %d %d\n", major, minor);*/ 320b7e1c893Smrg switch (major) { 321b7e1c893Smrg case 0: 322b7e1c893Smrg case 1: 323b7e1c893Smrg case 2: 324b7e1c893Smrg switch (minor) { 325b7e1c893Smrg case 1: 326b7e1c893Smrg disp_data.ucMisc = 0; 327b7e1c893Smrg disp_data.ucAction = action; 328b7e1c893Smrg if ((radeon_output->ConnectorType == CONNECTOR_HDMI_TYPE_A) || 329b7e1c893Smrg (radeon_output->ConnectorType == CONNECTOR_HDMI_TYPE_B)) 330b7e1c893Smrg disp_data.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE; 331b7e1c893Smrg disp_data.usPixelClock = cpu_to_le16(clock / 10); 332b7e1c893Smrg if (radeon_output->active_device & (ATOM_DEVICE_LCD_SUPPORT)) { 333b7e1c893Smrg if (lvds_misc & (1 << 0)) 334b7e1c893Smrg disp_data.ucMisc |= PANEL_ENCODER_MISC_DUAL; 335b7e1c893Smrg if (lvds_misc & (1 << 1)) 336b7e1c893Smrg disp_data.ucMisc |= (1 << 1); 337b7e1c893Smrg } else { 338b7e1c893Smrg if (radeon_output->linkb) 339b7e1c893Smrg disp_data.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB; 340b7e1c893Smrg if (clock > 165000) 341b7e1c893Smrg disp_data.ucMisc |= PANEL_ENCODER_MISC_DUAL; 342b7e1c893Smrg if (pScrn->rgbBits == 8) 343b7e1c893Smrg disp_data.ucMisc |= (1 << 1); 344b7e1c893Smrg } 345b7e1c893Smrg data.exec.pspace = &disp_data; 346b7e1c893Smrg break; 347b7e1c893Smrg case 2: 348b7e1c893Smrg case 3: 349b7e1c893Smrg disp_data2.ucMisc = 0; 350b7e1c893Smrg disp_data2.ucAction = action; 351b7e1c893Smrg if (minor == 3) { 352b7e1c893Smrg if (radeon_output->coherent_mode) { 353b7e1c893Smrg disp_data2.ucMisc |= PANEL_ENCODER_MISC_COHERENT; 354b7e1c893Smrg xf86DrvMsg(output->scrn->scrnIndex, X_INFO, "Coherent Mode enabled\n"); 355b7e1c893Smrg } 356b7e1c893Smrg } 357b7e1c893Smrg if ((radeon_output->ConnectorType == CONNECTOR_HDMI_TYPE_A) || 358b7e1c893Smrg (radeon_output->ConnectorType == CONNECTOR_HDMI_TYPE_B)) 359b7e1c893Smrg disp_data2.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE; 360b7e1c893Smrg disp_data2.usPixelClock = cpu_to_le16(clock / 10); 361b7e1c893Smrg disp_data2.ucTruncate = 0; 362b7e1c893Smrg disp_data2.ucSpatial = 0; 363b7e1c893Smrg disp_data2.ucTemporal = 0; 364b7e1c893Smrg disp_data2.ucFRC = 0; 365b7e1c893Smrg if (radeon_output->active_device & (ATOM_DEVICE_LCD_SUPPORT)) { 366b7e1c893Smrg if (lvds_misc & (1 << 0)) 367b7e1c893Smrg disp_data2.ucMisc |= PANEL_ENCODER_MISC_DUAL; 368b7e1c893Smrg if (lvds_misc & (1 << 5)) { 369b7e1c893Smrg disp_data2.ucSpatial = PANEL_ENCODER_SPATIAL_DITHER_EN; 370b7e1c893Smrg if (lvds_misc & (1 << 1)) 371b7e1c893Smrg disp_data2.ucSpatial |= PANEL_ENCODER_SPATIAL_DITHER_DEPTH; 372b7e1c893Smrg } 373b7e1c893Smrg if (lvds_misc & (1 << 6)) { 374b7e1c893Smrg disp_data2.ucTemporal = PANEL_ENCODER_TEMPORAL_DITHER_EN; 375b7e1c893Smrg if (lvds_misc & (1 << 1)) 376b7e1c893Smrg disp_data2.ucTemporal |= PANEL_ENCODER_TEMPORAL_DITHER_DEPTH; 377b7e1c893Smrg if (((lvds_misc >> 2) & 0x3) == 2) 378b7e1c893Smrg disp_data2.ucTemporal |= PANEL_ENCODER_TEMPORAL_LEVEL_4; 379b7e1c893Smrg } 380b7e1c893Smrg } else { 381b7e1c893Smrg if (radeon_output->linkb) 382b7e1c893Smrg disp_data2.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB; 383b7e1c893Smrg if (clock > 165000) 384b7e1c893Smrg disp_data2.ucMisc |= PANEL_ENCODER_MISC_DUAL; 385b7e1c893Smrg } 386b7e1c893Smrg data.exec.pspace = &disp_data2; 387b7e1c893Smrg break; 388b7e1c893Smrg default: 389b7e1c893Smrg ErrorF("Unknown table version\n"); 390b7e1c893Smrg exit(-1); 391b7e1c893Smrg } 392b7e1c893Smrg break; 393b7e1c893Smrg default: 394b7e1c893Smrg ErrorF("Unknown table version\n"); 395b7e1c893Smrg exit(-1); 396b7e1c893Smrg } 397b7e1c893Smrg 398b7e1c893Smrg data.exec.index = index; 399209ff23fSmrg data.exec.dataSpace = (void *)&space; 400209ff23fSmrg 401209ff23fSmrg if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { 402b7e1c893Smrg ErrorF("Output digital setup success\n"); 403209ff23fSmrg return ATOM_SUCCESS; 404209ff23fSmrg } 405209ff23fSmrg 406b7e1c893Smrg ErrorF("Output digital setup failed\n"); 407209ff23fSmrg return ATOM_NOT_IMPLEMENTED; 408209ff23fSmrg} 409209ff23fSmrg 410209ff23fSmrgstatic int 411b7e1c893Smrgatombios_maybe_hdmi_mode(xf86OutputPtr output) 412209ff23fSmrg{ 413b7e1c893Smrg#ifndef EDID_COMPLETE_RAWDATA 414b7e1c893Smrg /* there's no getting this right unless we have complete EDID */ 415b7e1c893Smrg return ATOM_ENCODER_MODE_HDMI; 416b7e1c893Smrg#else 417b7e1c893Smrg if (output && xf86MonitorIsHDMI(output->MonInfo)) 418b7e1c893Smrg return ATOM_ENCODER_MODE_HDMI; 419b7e1c893Smrg 420b7e1c893Smrg return ATOM_ENCODER_MODE_DVI; 421b7e1c893Smrg#endif 422b7e1c893Smrg} 423209ff23fSmrg 424b7e1c893Smrgint 425b7e1c893Smrgatombios_get_encoder_mode(xf86OutputPtr output) 426b7e1c893Smrg{ 427b7e1c893Smrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 428209ff23fSmrg 429b7e1c893Smrg /* DVI should really be atombios_maybe_hdmi_mode() as well */ 430b7e1c893Smrg switch (radeon_output->ConnectorType) { 431b7e1c893Smrg case CONNECTOR_DVI_I: 432b7e1c893Smrg if (radeon_output->active_device & (ATOM_DEVICE_DFP_SUPPORT)) 433b7e1c893Smrg return ATOM_ENCODER_MODE_DVI; 434b7e1c893Smrg else 435b7e1c893Smrg return ATOM_ENCODER_MODE_CRT; 436b7e1c893Smrg break; 437b7e1c893Smrg case CONNECTOR_DVI_D: 438b7e1c893Smrg default: 439b7e1c893Smrg return ATOM_ENCODER_MODE_DVI; 440b7e1c893Smrg break; 441b7e1c893Smrg case CONNECTOR_HDMI_TYPE_A: 442b7e1c893Smrg case CONNECTOR_HDMI_TYPE_B: 443b7e1c893Smrg return atombios_maybe_hdmi_mode(output); 444b7e1c893Smrg break; 445b7e1c893Smrg case CONNECTOR_LVDS: 446b7e1c893Smrg return ATOM_ENCODER_MODE_LVDS; 447b7e1c893Smrg break; 448b7e1c893Smrg case CONNECTOR_DISPLAY_PORT: 449ad43ddacSmrg case CONNECTOR_EDP: 450b7e1c893Smrg if (radeon_output->MonType == MT_DP) 451b7e1c893Smrg return ATOM_ENCODER_MODE_DP; 452b7e1c893Smrg else 453b7e1c893Smrg return atombios_maybe_hdmi_mode(output); 454b7e1c893Smrg break; 455b7e1c893Smrg case CONNECTOR_DVI_A: 456b7e1c893Smrg case CONNECTOR_VGA: 457b7e1c893Smrg case CONNECTOR_STV: 458b7e1c893Smrg case CONNECTOR_CTV: 459b7e1c893Smrg case CONNECTOR_DIN: 460b7e1c893Smrg if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT)) 461b7e1c893Smrg return ATOM_ENCODER_MODE_TV; 462b7e1c893Smrg else if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT)) 463b7e1c893Smrg return ATOM_ENCODER_MODE_CV; 464b7e1c893Smrg else 465b7e1c893Smrg return ATOM_ENCODER_MODE_CRT; 466b7e1c893Smrg break; 467209ff23fSmrg } 468209ff23fSmrg 469209ff23fSmrg} 470209ff23fSmrg 471b7e1c893Smrgstatic const int dp_clocks[] = { 472ad43ddacSmrg 5400, // 1 lane, 1.62 Ghz 473ad43ddacSmrg 9000, // 1 lane, 2.70 Ghz 474ad43ddacSmrg 10800, // 2 lane, 1.62 Ghz 475ad43ddacSmrg 18000, // 2 lane, 2.70 Ghz 476ad43ddacSmrg 21600, // 4 lane, 1.62 Ghz 477ad43ddacSmrg 36000, // 4 lane, 2.70 Ghz 478b7e1c893Smrg}; 479b7e1c893Smrgstatic const int num_dp_clocks = sizeof(dp_clocks) / sizeof(int); 480b7e1c893Smrg 481ad43ddacSmrg# define DP_LINK_BW_1_62 0x06 482ad43ddacSmrg# define DP_LINK_BW_2_7 0x0a 483ad43ddacSmrg 484209ff23fSmrgstatic int 485ad43ddacSmrgdp_lanes_for_mode_clock(RADEONOutputPrivatePtr radeon_output, 486ad43ddacSmrg int mode_clock) 487209ff23fSmrg{ 488b7e1c893Smrg int i; 489ad43ddacSmrg int max_link_bw = radeon_output->dpcd[1]; 490ad43ddacSmrg 491ad43ddacSmrg switch (max_link_bw) { 492ad43ddacSmrg case DP_LINK_BW_1_62: 493ad43ddacSmrg default: 494ad43ddacSmrg for (i = 0; i < num_dp_clocks; i++) { 495ad43ddacSmrg if (i % 2) 496ad43ddacSmrg continue; 497ad43ddacSmrg if (dp_clocks[i] > (mode_clock / 10)) { 498ad43ddacSmrg if (i < 2) 499ad43ddacSmrg return 1; 500ad43ddacSmrg else if (i < 4) 501ad43ddacSmrg return 2; 502ad43ddacSmrg else 503ad43ddacSmrg return 4; 504ad43ddacSmrg } 505ad43ddacSmrg } 506ad43ddacSmrg break; 507ad43ddacSmrg case DP_LINK_BW_2_7: 508ad43ddacSmrg for (i = 0; i < num_dp_clocks; i++) { 509ad43ddacSmrg if (dp_clocks[i] > (mode_clock / 10)) { 510ad43ddacSmrg if (i < 2) 511ad43ddacSmrg return 1; 512ad43ddacSmrg else if (i < 4) 513ad43ddacSmrg return 2; 514ad43ddacSmrg else 515ad43ddacSmrg return 4; 516ad43ddacSmrg } 517ad43ddacSmrg } 518ad43ddacSmrg break; 519ad43ddacSmrg } 520209ff23fSmrg 521b7e1c893Smrg return 0; 522b7e1c893Smrg} 523209ff23fSmrg 524b7e1c893Smrgstatic int 525ad43ddacSmrgdp_link_clock_for_mode_clock(RADEONOutputPrivatePtr radeon_output, 526ad43ddacSmrg int mode_clock) 527b7e1c893Smrg{ 528b7e1c893Smrg int i; 529ad43ddacSmrg int max_link_bw = radeon_output->dpcd[1]; 530209ff23fSmrg 531ad43ddacSmrg switch (max_link_bw) { 532ad43ddacSmrg case DP_LINK_BW_1_62: 533ad43ddacSmrg default: 534ad43ddacSmrg return 16200; 535ad43ddacSmrg break; 536ad43ddacSmrg case DP_LINK_BW_2_7: 537ad43ddacSmrg for (i = 0; i < num_dp_clocks; i++) 538ad43ddacSmrg if (dp_clocks[i] > (mode_clock / 10)) 539ad43ddacSmrg return (i % 2) ? 27000 : 16200; 540ad43ddacSmrg break; 541ad43ddacSmrg } 542b7e1c893Smrg 543b7e1c893Smrg return 0; 544209ff23fSmrg} 545209ff23fSmrg 546ad43ddacSmrg/* 547ad43ddacSmrg * DIG Encoder/Transmitter Setup 548ad43ddacSmrg * 549ad43ddacSmrg * DCE 3.0/3.1 550ad43ddacSmrg * - 2 DIG transmitter blocks. UNIPHY (links A and B) and LVTMA. 551ad43ddacSmrg * Supports up to 3 digital outputs 552ad43ddacSmrg * - 2 DIG encoder blocks. 553ad43ddacSmrg * DIG1 can drive UNIPHY link A or link B 554ad43ddacSmrg * DIG2 can drive UNIPHY link B or LVTMA 555ad43ddacSmrg * 556ad43ddacSmrg * DCE 3.2 557ad43ddacSmrg * - 3 DIG transmitter blocks. UNIPHY0/1/2 (links A and B). 558ad43ddacSmrg * Supports up to 5 digital outputs 559ad43ddacSmrg * - 2 DIG encoder blocks. 560ad43ddacSmrg * DIG1/2 can drive UNIPHY0/1/2 link A or link B 561ad43ddacSmrg * 562ad43ddacSmrg * Routing 563ad43ddacSmrg * crtc -> dig encoder -> UNIPHY/LVTMA (1 or 2 links) 564ad43ddacSmrg * Examples: 565ad43ddacSmrg * crtc0 -> dig2 -> LVTMA links A+B 566ad43ddacSmrg * crtc1 -> dig1 -> UNIPHY0 link B 567ad43ddacSmrg */ 568209ff23fSmrgstatic int 569b7e1c893Smrgatombios_output_dig_encoder_setup(xf86OutputPtr output, int action) 570209ff23fSmrg{ 571209ff23fSmrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 572209ff23fSmrg RADEONInfoPtr info = RADEONPTR(output->scrn); 573b7e1c893Smrg radeon_encoder_ptr radeon_encoder = radeon_get_encoder(output); 574209ff23fSmrg DIG_ENCODER_CONTROL_PS_ALLOCATION disp_data; 575209ff23fSmrg AtomBiosArgRec data; 576209ff23fSmrg unsigned char *space; 577ad43ddacSmrg int index = 0, major, minor; 578b7e1c893Smrg int clock = radeon_output->pixel_clock; 579b7e1c893Smrg 580b7e1c893Smrg if (radeon_encoder == NULL) 581b7e1c893Smrg return ATOM_NOT_IMPLEMENTED; 582b7e1c893Smrg 583b7e1c893Smrg memset(&disp_data,0, sizeof(disp_data)); 584b7e1c893Smrg 585ad43ddacSmrg if (radeon_output->dig_encoder) 586ad43ddacSmrg index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl); 587ad43ddacSmrg else 588ad43ddacSmrg index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl); 589209ff23fSmrg 590b7e1c893Smrg atombios_get_command_table_version(info->atomBIOS, index, &major, &minor); 591b7e1c893Smrg 592b7e1c893Smrg disp_data.ucAction = action; 593b7e1c893Smrg disp_data.usPixelClock = cpu_to_le16(clock / 10); 594b7e1c893Smrg 595b7e1c893Smrg if (IS_DCE32_VARIANT) { 596b7e1c893Smrg switch (radeon_encoder->encoder_id) { 597b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 598b7e1c893Smrg disp_data.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER1; 599b7e1c893Smrg break; 600b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 601b7e1c893Smrg disp_data.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER2; 602b7e1c893Smrg break; 603b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 604b7e1c893Smrg disp_data.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER3; 605b7e1c893Smrg break; 606b7e1c893Smrg } 607b7e1c893Smrg } else { 608b7e1c893Smrg switch (radeon_encoder->encoder_id) { 609b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 610b7e1c893Smrg disp_data.ucConfig = ATOM_ENCODER_CONFIG_UNIPHY; 611b7e1c893Smrg break; 612b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 613b7e1c893Smrg disp_data.ucConfig = ATOM_ENCODER_CONFIG_LVTMA; 614b7e1c893Smrg break; 615b7e1c893Smrg } 616209ff23fSmrg } 617209ff23fSmrg 618b7e1c893Smrg disp_data.ucEncoderMode = atombios_get_encoder_mode(output); 619b7e1c893Smrg 620b7e1c893Smrg if (disp_data.ucEncoderMode == ATOM_ENCODER_MODE_DP) { 621ad43ddacSmrg if (dp_link_clock_for_mode_clock(radeon_output, clock) == 27000) 622b7e1c893Smrg disp_data.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ; 623ad43ddacSmrg disp_data.ucLaneNum = dp_lanes_for_mode_clock(radeon_output, clock); 624ad43ddacSmrg } else if (clock > 165000) 625209ff23fSmrg disp_data.ucLaneNum = 8; 626ad43ddacSmrg else 627209ff23fSmrg disp_data.ucLaneNum = 4; 628ad43ddacSmrg 629ad43ddacSmrg if (radeon_output->linkb) 630ad43ddacSmrg disp_data.ucConfig |= ATOM_ENCODER_CONFIG_LINKB; 631ad43ddacSmrg else 632ad43ddacSmrg disp_data.ucConfig |= ATOM_ENCODER_CONFIG_LINKA; 633209ff23fSmrg 634b7e1c893Smrg data.exec.index = index; 635209ff23fSmrg data.exec.dataSpace = (void *)&space; 636209ff23fSmrg data.exec.pspace = &disp_data; 637209ff23fSmrg 638209ff23fSmrg if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { 639ad43ddacSmrg ErrorF("Output DIG%d encoder setup success\n", radeon_output->dig_encoder); 640209ff23fSmrg return ATOM_SUCCESS; 641209ff23fSmrg } 642209ff23fSmrg 643ad43ddacSmrg ErrorF("Output DIG%d setup failed\n", radeon_output->dig_encoder); 644209ff23fSmrg return ATOM_NOT_IMPLEMENTED; 645209ff23fSmrg 646209ff23fSmrg} 647209ff23fSmrg 648ad43ddacSmrgstatic int 649ad43ddacSmrgatombios_dce4_output_dig_encoder_setup(xf86OutputPtr output, int action) 650ad43ddacSmrg{ 651ad43ddacSmrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 652ad43ddacSmrg RADEONInfoPtr info = RADEONPTR(output->scrn); 653ad43ddacSmrg radeon_encoder_ptr radeon_encoder = radeon_get_encoder(output); 654ad43ddacSmrg DIG_ENCODER_CONTROL_PARAMETERS_V3 disp_data; 655ad43ddacSmrg AtomBiosArgRec data; 656ad43ddacSmrg unsigned char *space; 657ad43ddacSmrg int index; 658ad43ddacSmrg int clock = radeon_output->pixel_clock; 659ad43ddacSmrg 660ad43ddacSmrg if (radeon_encoder == NULL) 661ad43ddacSmrg return ATOM_NOT_IMPLEMENTED; 662ad43ddacSmrg 663ad43ddacSmrg memset(&disp_data,0, sizeof(disp_data)); 664ad43ddacSmrg 665ad43ddacSmrg index = GetIndexIntoMasterTable(COMMAND, DIGxEncoderControl); 666ad43ddacSmrg 667ad43ddacSmrg disp_data.ucAction = action; 668ad43ddacSmrg disp_data.usPixelClock = cpu_to_le16(clock / 10); 669ad43ddacSmrg disp_data.ucEncoderMode = atombios_get_encoder_mode(output); 670ad43ddacSmrg disp_data.acConfig.ucDigSel = radeon_output->dig_encoder; 671ad43ddacSmrg 672ad43ddacSmrg if (disp_data.ucEncoderMode == ATOM_ENCODER_MODE_DP) { 673ad43ddacSmrg if (dp_link_clock_for_mode_clock(radeon_output, clock) == 27000) 674ad43ddacSmrg disp_data.acConfig.ucDPLinkRate = 1; 675ad43ddacSmrg disp_data.ucLaneNum = dp_lanes_for_mode_clock(radeon_output, clock); 676ad43ddacSmrg } else if (clock > 165000) 677ad43ddacSmrg disp_data.ucLaneNum = 8; 678ad43ddacSmrg else 679ad43ddacSmrg disp_data.ucLaneNum = 4; 680ad43ddacSmrg 681ad43ddacSmrg disp_data.ucBitPerColor = PANEL_8BIT_PER_COLOR; 682ad43ddacSmrg 683ad43ddacSmrg data.exec.index = index; 684ad43ddacSmrg data.exec.dataSpace = (void *)&space; 685ad43ddacSmrg data.exec.pspace = &disp_data; 686ad43ddacSmrg 687ad43ddacSmrg if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { 688ad43ddacSmrg ErrorF("Output DIG%d encoder setup success\n", radeon_output->dig_encoder); 689ad43ddacSmrg return ATOM_SUCCESS; 690ad43ddacSmrg } 691ad43ddacSmrg 692ad43ddacSmrg ErrorF("Output DIG%d setup failed\n", radeon_output->dig_encoder); 693ad43ddacSmrg return ATOM_NOT_IMPLEMENTED; 694ad43ddacSmrg} 695ad43ddacSmrg 696b7e1c893Smrgunion dig_transmitter_control { 697b7e1c893Smrg DIG_TRANSMITTER_CONTROL_PS_ALLOCATION v1; 698b7e1c893Smrg DIG_TRANSMITTER_CONTROL_PARAMETERS_V2 v2; 699ad43ddacSmrg DIG_TRANSMITTER_CONTROL_PARAMETERS_V3 v3; 700b7e1c893Smrg}; 701b7e1c893Smrg 702209ff23fSmrgstatic int 703ad43ddacSmrgatombios_output_dig_transmitter_setup(xf86OutputPtr output, int action, uint8_t lane_num, uint8_t lane_set) 704209ff23fSmrg{ 705209ff23fSmrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 706209ff23fSmrg RADEONInfoPtr info = RADEONPTR(output->scrn); 707b7e1c893Smrg radeon_encoder_ptr radeon_encoder = radeon_get_encoder(output); 708b7e1c893Smrg union dig_transmitter_control disp_data; 709209ff23fSmrg AtomBiosArgRec data; 710209ff23fSmrg unsigned char *space; 711b7e1c893Smrg int index = 0, num = 0; 712b7e1c893Smrg int major, minor; 713b7e1c893Smrg int clock = radeon_output->pixel_clock; 714b7e1c893Smrg 715b7e1c893Smrg if (radeon_encoder == NULL) 716b7e1c893Smrg return ATOM_NOT_IMPLEMENTED; 717b7e1c893Smrg 718b7e1c893Smrg memset(&disp_data,0, sizeof(disp_data)); 719b7e1c893Smrg 720ad43ddacSmrg if (IS_DCE32_VARIANT || IS_DCE4_VARIANT) 721b7e1c893Smrg index = GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl); 722b7e1c893Smrg else { 723b7e1c893Smrg switch (radeon_encoder->encoder_id) { 724b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 725b7e1c893Smrg index = GetIndexIntoMasterTable(COMMAND, DIG1TransmitterControl); 726b7e1c893Smrg break; 727b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 728b7e1c893Smrg index = GetIndexIntoMasterTable(COMMAND, DIG2TransmitterControl); 729b7e1c893Smrg break; 730b7e1c893Smrg } 731b7e1c893Smrg } 732209ff23fSmrg 733b7e1c893Smrg atombios_get_command_table_version(info->atomBIOS, index, &major, &minor); 734b7e1c893Smrg 735b7e1c893Smrg disp_data.v1.ucAction = action; 736b7e1c893Smrg 737ad43ddacSmrg if (IS_DCE4_VARIANT) { 738ad43ddacSmrg if (action == ATOM_TRANSMITTER_ACTION_INIT) { 739ad43ddacSmrg disp_data.v3.usInitInfo = radeon_output->connector_object_id; 740ad43ddacSmrg } else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) { 741ad43ddacSmrg disp_data.v3.asMode.ucLaneSel = lane_num; 742ad43ddacSmrg disp_data.v3.asMode.ucLaneSet = lane_set; 743209ff23fSmrg } else { 744ad43ddacSmrg if (radeon_output->MonType == MT_DP) { 745ad43ddacSmrg disp_data.v3.usPixelClock = 746ad43ddacSmrg cpu_to_le16(dp_link_clock_for_mode_clock(radeon_output, clock)); 747ad43ddacSmrg } else if (clock > 165000) { 748ad43ddacSmrg disp_data.v3.usPixelClock = cpu_to_le16((clock / 2) / 10); 749ad43ddacSmrg disp_data.v3.acConfig.fDualLinkConnector = 1; 750ad43ddacSmrg } else { 751ad43ddacSmrg disp_data.v3.usPixelClock = cpu_to_le16(clock / 10); 752ad43ddacSmrg } 753b7e1c893Smrg } 754ad43ddacSmrg 755ad43ddacSmrg if (radeon_output->MonType == MT_DP) 756ad43ddacSmrg disp_data.v3.ucLaneNum = dp_lanes_for_mode_clock(radeon_output, clock); 757ad43ddacSmrg else if (clock > 165000) 758ad43ddacSmrg disp_data.v3.ucLaneNum = 8; 759ad43ddacSmrg else 760ad43ddacSmrg disp_data.v3.ucLaneNum = 4; 761ad43ddacSmrg 762ad43ddacSmrg if (radeon_output->linkb) { 763ad43ddacSmrg disp_data.v3.acConfig.ucLinkSel = 1; 764b7e1c893Smrg disp_data.v2.acConfig.ucEncoderSel = 1; 765ad43ddacSmrg } 766ad43ddacSmrg 767ad43ddacSmrg // select the PLL for the UNIPHY 768ad43ddacSmrg if (radeon_output->MonType == MT_DP) 769ad43ddacSmrg disp_data.v3.acConfig.ucRefClkSource = 2; /* ext clk */ 770ad43ddacSmrg else 771ad43ddacSmrg disp_data.v3.acConfig.ucRefClkSource = radeon_output->pll_id; 772ad43ddacSmrg 773ad43ddacSmrg switch (radeon_encoder->encoder_id) { 774ad43ddacSmrg case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 775ad43ddacSmrg disp_data.v3.acConfig.ucTransmitterSel = 0; 776ad43ddacSmrg num = 0; 777ad43ddacSmrg break; 778ad43ddacSmrg case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 779ad43ddacSmrg disp_data.v3.acConfig.ucTransmitterSel = 1; 780ad43ddacSmrg num = 1; 781ad43ddacSmrg break; 782ad43ddacSmrg case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 783ad43ddacSmrg disp_data.v3.acConfig.ucTransmitterSel = 2; 784ad43ddacSmrg num = 2; 785ad43ddacSmrg break; 786ad43ddacSmrg } 787ad43ddacSmrg 788ad43ddacSmrg if (radeon_output->MonType == MT_DP) 789ad43ddacSmrg disp_data.v3.acConfig.fCoherentMode = 1; /* DP requires coherent */ 790ad43ddacSmrg else if (radeon_output->active_device & (ATOM_DEVICE_DFP_SUPPORT)) { 791ad43ddacSmrg if (radeon_output->coherent_mode) 792ad43ddacSmrg disp_data.v3.acConfig.fCoherentMode = 1; 793ad43ddacSmrg } 794ad43ddacSmrg } else if (IS_DCE32_VARIANT) { 795ad43ddacSmrg if (action == ATOM_TRANSMITTER_ACTION_INIT) { 796ad43ddacSmrg disp_data.v2.usInitInfo = radeon_output->connector_object_id; 797ad43ddacSmrg } else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) { 798ad43ddacSmrg disp_data.v2.asMode.ucLaneSel = lane_num; 799ad43ddacSmrg disp_data.v2.asMode.ucLaneSet = lane_set; 800ad43ddacSmrg } else { 801ad43ddacSmrg if (radeon_output->MonType == MT_DP) { 802ad43ddacSmrg disp_data.v2.usPixelClock = 803ad43ddacSmrg cpu_to_le16(dp_link_clock_for_mode_clock(radeon_output, clock)); 804ad43ddacSmrg disp_data.v2.acConfig.fDPConnector = 1; 805ad43ddacSmrg } else if (clock > 165000) { 806ad43ddacSmrg disp_data.v2.usPixelClock = cpu_to_le16((clock / 2) / 10); 807ad43ddacSmrg disp_data.v2.acConfig.fDualLinkConnector = 1; 808ad43ddacSmrg } else { 809ad43ddacSmrg disp_data.v2.usPixelClock = cpu_to_le16(clock / 10); 810ad43ddacSmrg } 811ad43ddacSmrg } 812ad43ddacSmrg if (radeon_output->dig_encoder) 813ad43ddacSmrg disp_data.v2.acConfig.ucEncoderSel = 1; 814ad43ddacSmrg 815ad43ddacSmrg if (radeon_output->linkb) 816ad43ddacSmrg disp_data.v2.acConfig.ucLinkSel = 1; 817b7e1c893Smrg 818b7e1c893Smrg switch (radeon_encoder->encoder_id) { 819b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 820b7e1c893Smrg disp_data.v2.acConfig.ucTransmitterSel = 0; 821b7e1c893Smrg num = 0; 822b7e1c893Smrg break; 823b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 824b7e1c893Smrg disp_data.v2.acConfig.ucTransmitterSel = 1; 825b7e1c893Smrg num = 1; 826b7e1c893Smrg break; 827b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 828b7e1c893Smrg disp_data.v2.acConfig.ucTransmitterSel = 2; 829b7e1c893Smrg num = 2; 830b7e1c893Smrg break; 831b7e1c893Smrg } 832b7e1c893Smrg 833ad43ddacSmrg if (radeon_output->MonType == MT_DP) 834ad43ddacSmrg disp_data.v2.acConfig.fCoherentMode = 1; /* DP requires coherent */ 835ad43ddacSmrg else if (radeon_output->active_device & (ATOM_DEVICE_DFP_SUPPORT)) { 836ad43ddacSmrg if (radeon_output->coherent_mode) 837b7e1c893Smrg disp_data.v2.acConfig.fCoherentMode = 1; 838209ff23fSmrg } 839209ff23fSmrg } else { 840b7e1c893Smrg disp_data.v1.ucConfig = ATOM_TRANSMITTER_CONFIG_CLKSRC_PPLL; 841b7e1c893Smrg 842ad43ddacSmrg if (action == ATOM_TRANSMITTER_ACTION_INIT) { 843ad43ddacSmrg disp_data.v1.usInitInfo = radeon_output->connector_object_id; 844ad43ddacSmrg } else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) { 845ad43ddacSmrg disp_data.v1.asMode.ucLaneSel = lane_num; 846ad43ddacSmrg disp_data.v1.asMode.ucLaneSet = lane_set; 847ad43ddacSmrg } else { 848ad43ddacSmrg if (radeon_output->MonType == MT_DP) 849ad43ddacSmrg disp_data.v1.usPixelClock = 850ad43ddacSmrg cpu_to_le16(dp_link_clock_for_mode_clock(radeon_output, clock)); 851ad43ddacSmrg else if (clock > 165000) 852ad43ddacSmrg disp_data.v1.usPixelClock = cpu_to_le16((clock / 2) / 10); 853ad43ddacSmrg else 854ad43ddacSmrg disp_data.v1.usPixelClock = cpu_to_le16(clock / 10); 855ad43ddacSmrg } 856ad43ddacSmrg 857ad43ddacSmrg if (radeon_output->dig_encoder) 858ad43ddacSmrg disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER; 859209ff23fSmrg else 860ad43ddacSmrg disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER; 861b7e1c893Smrg 862b7e1c893Smrg switch (radeon_encoder->encoder_id) { 863b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 864b7e1c893Smrg if (info->IsIGP) { 865b7e1c893Smrg if (clock > 165000) { 866b7e1c893Smrg if (radeon_output->igp_lane_info & 0x3) 867b7e1c893Smrg disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_7; 868b7e1c893Smrg else if (radeon_output->igp_lane_info & 0xc) 869b7e1c893Smrg disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_15; 870b7e1c893Smrg } else { 871b7e1c893Smrg if (radeon_output->igp_lane_info & 0x1) 872b7e1c893Smrg disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_3; 873b7e1c893Smrg else if (radeon_output->igp_lane_info & 0x2) 874b7e1c893Smrg disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_4_7; 875b7e1c893Smrg else if (radeon_output->igp_lane_info & 0x4) 876b7e1c893Smrg disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_11; 877b7e1c893Smrg else if (radeon_output->igp_lane_info & 0x8) 878b7e1c893Smrg disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_12_15; 879b7e1c893Smrg } 880b7e1c893Smrg } 881b7e1c893Smrg break; 882b7e1c893Smrg } 883ad43ddacSmrg if (clock > 165000) 884ad43ddacSmrg disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_8LANE_LINK; 885ad43ddacSmrg if (radeon_output->linkb) 886ad43ddacSmrg disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB; 887ad43ddacSmrg else 888ad43ddacSmrg disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA; 889209ff23fSmrg 890ad43ddacSmrg if (radeon_output->MonType == MT_DP) 891ad43ddacSmrg disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT; /* DP requires coherent */ 892ad43ddacSmrg else if (radeon_output->active_device & (ATOM_DEVICE_DFP_SUPPORT)) { 893ad43ddacSmrg if (radeon_output->coherent_mode) 894b7e1c893Smrg disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT; 895b7e1c893Smrg } 896b7e1c893Smrg } 897209ff23fSmrg 898b7e1c893Smrg data.exec.index = index; 899209ff23fSmrg data.exec.dataSpace = (void *)&space; 900209ff23fSmrg data.exec.pspace = &disp_data; 901209ff23fSmrg 902209ff23fSmrg if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { 903b7e1c893Smrg if (IS_DCE32_VARIANT) 904b7e1c893Smrg ErrorF("Output UNIPHY%d transmitter setup success\n", num); 905b7e1c893Smrg else 906b7e1c893Smrg ErrorF("Output DIG%d transmitter setup success\n", num); 907209ff23fSmrg return ATOM_SUCCESS; 908209ff23fSmrg } 909209ff23fSmrg 910b7e1c893Smrg ErrorF("Output DIG%d transmitter setup failed\n", num); 911209ff23fSmrg return ATOM_NOT_IMPLEMENTED; 912209ff23fSmrg 913209ff23fSmrg} 914209ff23fSmrg 915c503f109Smrgstatic void atom_rv515_force_tv_scaler(ScrnInfoPtr pScrn, RADEONCrtcPrivatePtr radeon_crtc) 916b7e1c893Smrg{ 917b7e1c893Smrg RADEONInfoPtr info = RADEONPTR(pScrn); 918b7e1c893Smrg unsigned char *RADEONMMIO = info->MMIO; 919c503f109Smrg int index_reg = 0x6578, data_reg = 0x657c; 920c503f109Smrg 921c503f109Smrg index_reg += radeon_crtc->crtc_offset; 922c503f109Smrg data_reg += radeon_crtc->crtc_offset; 923c503f109Smrg 924c503f109Smrg OUTREG(0x659C + radeon_crtc->crtc_offset, 0x0); 925c503f109Smrg OUTREG(0x6594 + radeon_crtc->crtc_offset, 0x705); 926c503f109Smrg OUTREG(0x65A4 + radeon_crtc->crtc_offset, 0x10001); 927c503f109Smrg OUTREG(0x65D8 + radeon_crtc->crtc_offset, 0x0); 928c503f109Smrg OUTREG(0x65B0 + radeon_crtc->crtc_offset, 0x0); 929c503f109Smrg OUTREG(0x65C0 + radeon_crtc->crtc_offset, 0x0); 930c503f109Smrg OUTREG(0x65D4 + radeon_crtc->crtc_offset, 0x0); 931c503f109Smrg OUTREG(index_reg,0x0); 932c503f109Smrg OUTREG(data_reg,0x841880A8); 933c503f109Smrg OUTREG(index_reg,0x1); 934c503f109Smrg OUTREG(data_reg,0x84208680); 935c503f109Smrg OUTREG(index_reg,0x2); 936c503f109Smrg OUTREG(data_reg,0xBFF880B0); 937c503f109Smrg OUTREG(index_reg,0x100); 938c503f109Smrg OUTREG(data_reg,0x83D88088); 939c503f109Smrg OUTREG(index_reg,0x101); 940c503f109Smrg OUTREG(data_reg,0x84608680); 941c503f109Smrg OUTREG(index_reg,0x102); 942c503f109Smrg OUTREG(data_reg,0xBFF080D0); 943c503f109Smrg OUTREG(index_reg,0x200); 944c503f109Smrg OUTREG(data_reg,0x83988068); 945c503f109Smrg OUTREG(index_reg,0x201); 946c503f109Smrg OUTREG(data_reg,0x84A08680); 947c503f109Smrg OUTREG(index_reg,0x202); 948c503f109Smrg OUTREG(data_reg,0xBFF080F8); 949c503f109Smrg OUTREG(index_reg,0x300); 950c503f109Smrg OUTREG(data_reg,0x83588058); 951c503f109Smrg OUTREG(index_reg,0x301); 952c503f109Smrg OUTREG(data_reg,0x84E08660); 953c503f109Smrg OUTREG(index_reg,0x302); 954c503f109Smrg OUTREG(data_reg,0xBFF88120); 955c503f109Smrg OUTREG(index_reg,0x400); 956c503f109Smrg OUTREG(data_reg,0x83188040); 957c503f109Smrg OUTREG(index_reg,0x401); 958c503f109Smrg OUTREG(data_reg,0x85008660); 959c503f109Smrg OUTREG(index_reg,0x402); 960c503f109Smrg OUTREG(data_reg,0xBFF88150); 961c503f109Smrg OUTREG(index_reg,0x500); 962c503f109Smrg OUTREG(data_reg,0x82D88030); 963c503f109Smrg OUTREG(index_reg,0x501); 964c503f109Smrg OUTREG(data_reg,0x85408640); 965c503f109Smrg OUTREG(index_reg,0x502); 966c503f109Smrg OUTREG(data_reg,0xBFF88180); 967c503f109Smrg OUTREG(index_reg,0x600); 968c503f109Smrg OUTREG(data_reg,0x82A08018); 969c503f109Smrg OUTREG(index_reg,0x601); 970c503f109Smrg OUTREG(data_reg,0x85808620); 971c503f109Smrg OUTREG(index_reg,0x602); 972c503f109Smrg OUTREG(data_reg,0xBFF081B8); 973c503f109Smrg OUTREG(index_reg,0x700); 974c503f109Smrg OUTREG(data_reg,0x82608010); 975c503f109Smrg OUTREG(index_reg,0x701); 976c503f109Smrg OUTREG(data_reg,0x85A08600); 977c503f109Smrg OUTREG(index_reg,0x702); 978c503f109Smrg OUTREG(data_reg,0x800081F0); 979c503f109Smrg OUTREG(index_reg,0x800); 980c503f109Smrg OUTREG(data_reg,0x8228BFF8); 981c503f109Smrg OUTREG(index_reg,0x801); 982c503f109Smrg OUTREG(data_reg,0x85E085E0); 983c503f109Smrg OUTREG(index_reg,0x802); 984c503f109Smrg OUTREG(data_reg,0xBFF88228); 985c503f109Smrg OUTREG(index_reg,0x10000); 986c503f109Smrg OUTREG(data_reg,0x82A8BF00); 987c503f109Smrg OUTREG(index_reg,0x10001); 988c503f109Smrg OUTREG(data_reg,0x82A08CC0); 989c503f109Smrg OUTREG(index_reg,0x10002); 990c503f109Smrg OUTREG(data_reg,0x8008BEF8); 991c503f109Smrg OUTREG(index_reg,0x10100); 992c503f109Smrg OUTREG(data_reg,0x81F0BF28); 993c503f109Smrg OUTREG(index_reg,0x10101); 994c503f109Smrg OUTREG(data_reg,0x83608CA0); 995c503f109Smrg OUTREG(index_reg,0x10102); 996c503f109Smrg OUTREG(data_reg,0x8018BED0); 997c503f109Smrg OUTREG(index_reg,0x10200); 998c503f109Smrg OUTREG(data_reg,0x8148BF38); 999c503f109Smrg OUTREG(index_reg,0x10201); 1000c503f109Smrg OUTREG(data_reg,0x84408C80); 1001c503f109Smrg OUTREG(index_reg,0x10202); 1002c503f109Smrg OUTREG(data_reg,0x8008BEB8); 1003c503f109Smrg OUTREG(index_reg,0x10300); 1004c503f109Smrg OUTREG(data_reg,0x80B0BF78); 1005c503f109Smrg OUTREG(index_reg,0x10301); 1006c503f109Smrg OUTREG(data_reg,0x85008C20); 1007c503f109Smrg OUTREG(index_reg,0x10302); 1008c503f109Smrg OUTREG(data_reg,0x8020BEA0); 1009c503f109Smrg OUTREG(index_reg,0x10400); 1010c503f109Smrg OUTREG(data_reg,0x8028BF90); 1011c503f109Smrg OUTREG(index_reg,0x10401); 1012c503f109Smrg OUTREG(data_reg,0x85E08BC0); 1013c503f109Smrg OUTREG(index_reg,0x10402); 1014c503f109Smrg OUTREG(data_reg,0x8018BE90); 1015c503f109Smrg OUTREG(index_reg,0x10500); 1016c503f109Smrg OUTREG(data_reg,0xBFB8BFB0); 1017c503f109Smrg OUTREG(index_reg,0x10501); 1018c503f109Smrg OUTREG(data_reg,0x86C08B40); 1019c503f109Smrg OUTREG(index_reg,0x10502); 1020c503f109Smrg OUTREG(data_reg,0x8010BE90); 1021c503f109Smrg OUTREG(index_reg,0x10600); 1022c503f109Smrg OUTREG(data_reg,0xBF58BFC8); 1023c503f109Smrg OUTREG(index_reg,0x10601); 1024c503f109Smrg OUTREG(data_reg,0x87A08AA0); 1025c503f109Smrg OUTREG(index_reg,0x10602); 1026c503f109Smrg OUTREG(data_reg,0x8010BE98); 1027c503f109Smrg OUTREG(index_reg,0x10700); 1028c503f109Smrg OUTREG(data_reg,0xBF10BFF0); 1029c503f109Smrg OUTREG(index_reg,0x10701); 1030c503f109Smrg OUTREG(data_reg,0x886089E0); 1031c503f109Smrg OUTREG(index_reg,0x10702); 1032c503f109Smrg OUTREG(data_reg,0x8018BEB0); 1033c503f109Smrg OUTREG(index_reg,0x10800); 1034c503f109Smrg OUTREG(data_reg,0xBED8BFE8); 1035c503f109Smrg OUTREG(index_reg,0x10801); 1036c503f109Smrg OUTREG(data_reg,0x89408940); 1037c503f109Smrg OUTREG(index_reg,0x10802); 1038c503f109Smrg OUTREG(data_reg,0xBFE8BED8); 1039c503f109Smrg OUTREG(index_reg,0x20000); 1040c503f109Smrg OUTREG(data_reg,0x80008000); 1041c503f109Smrg OUTREG(index_reg,0x20001); 1042c503f109Smrg OUTREG(data_reg,0x90008000); 1043c503f109Smrg OUTREG(index_reg,0x20002); 1044c503f109Smrg OUTREG(data_reg,0x80008000); 1045c503f109Smrg OUTREG(index_reg,0x20003); 1046c503f109Smrg OUTREG(data_reg,0x80008000); 1047c503f109Smrg OUTREG(index_reg,0x20100); 1048c503f109Smrg OUTREG(data_reg,0x80108000); 1049c503f109Smrg OUTREG(index_reg,0x20101); 1050c503f109Smrg OUTREG(data_reg,0x8FE0BF70); 1051c503f109Smrg OUTREG(index_reg,0x20102); 1052c503f109Smrg OUTREG(data_reg,0xBFE880C0); 1053c503f109Smrg OUTREG(index_reg,0x20103); 1054c503f109Smrg OUTREG(data_reg,0x80008000); 1055c503f109Smrg OUTREG(index_reg,0x20200); 1056c503f109Smrg OUTREG(data_reg,0x8018BFF8); 1057c503f109Smrg OUTREG(index_reg,0x20201); 1058c503f109Smrg OUTREG(data_reg,0x8F80BF08); 1059c503f109Smrg OUTREG(index_reg,0x20202); 1060c503f109Smrg OUTREG(data_reg,0xBFD081A0); 1061c503f109Smrg OUTREG(index_reg,0x20203); 1062c503f109Smrg OUTREG(data_reg,0xBFF88000); 1063c503f109Smrg OUTREG(index_reg,0x20300); 1064c503f109Smrg OUTREG(data_reg,0x80188000); 1065c503f109Smrg OUTREG(index_reg,0x20301); 1066c503f109Smrg OUTREG(data_reg,0x8EE0BEC0); 1067c503f109Smrg OUTREG(index_reg,0x20302); 1068c503f109Smrg OUTREG(data_reg,0xBFB082A0); 1069c503f109Smrg OUTREG(index_reg,0x20303); 1070c503f109Smrg OUTREG(data_reg,0x80008000); 1071c503f109Smrg OUTREG(index_reg,0x20400); 1072c503f109Smrg OUTREG(data_reg,0x80188000); 1073c503f109Smrg OUTREG(index_reg,0x20401); 1074c503f109Smrg OUTREG(data_reg,0x8E00BEA0); 1075c503f109Smrg OUTREG(index_reg,0x20402); 1076c503f109Smrg OUTREG(data_reg,0xBF8883C0); 1077c503f109Smrg OUTREG(index_reg,0x20403); 1078c503f109Smrg OUTREG(data_reg,0x80008000); 1079c503f109Smrg OUTREG(index_reg,0x20500); 1080c503f109Smrg OUTREG(data_reg,0x80188000); 1081c503f109Smrg OUTREG(index_reg,0x20501); 1082c503f109Smrg OUTREG(data_reg,0x8D00BE90); 1083c503f109Smrg OUTREG(index_reg,0x20502); 1084c503f109Smrg OUTREG(data_reg,0xBF588500); 1085c503f109Smrg OUTREG(index_reg,0x20503); 1086c503f109Smrg OUTREG(data_reg,0x80008008); 1087c503f109Smrg OUTREG(index_reg,0x20600); 1088c503f109Smrg OUTREG(data_reg,0x80188000); 1089c503f109Smrg OUTREG(index_reg,0x20601); 1090c503f109Smrg OUTREG(data_reg,0x8BC0BE98); 1091c503f109Smrg OUTREG(index_reg,0x20602); 1092c503f109Smrg OUTREG(data_reg,0xBF308660); 1093c503f109Smrg OUTREG(index_reg,0x20603); 1094c503f109Smrg OUTREG(data_reg,0x80008008); 1095c503f109Smrg OUTREG(index_reg,0x20700); 1096c503f109Smrg OUTREG(data_reg,0x80108000); 1097c503f109Smrg OUTREG(index_reg,0x20701); 1098c503f109Smrg OUTREG(data_reg,0x8A80BEB0); 1099c503f109Smrg OUTREG(index_reg,0x20702); 1100c503f109Smrg OUTREG(data_reg,0xBF0087C0); 1101c503f109Smrg OUTREG(index_reg,0x20703); 1102c503f109Smrg OUTREG(data_reg,0x80008008); 1103c503f109Smrg OUTREG(index_reg,0x20800); 1104c503f109Smrg OUTREG(data_reg,0x80108000); 1105c503f109Smrg OUTREG(index_reg,0x20801); 1106c503f109Smrg OUTREG(data_reg,0x8920BED0); 1107c503f109Smrg OUTREG(index_reg,0x20802); 1108c503f109Smrg OUTREG(data_reg,0xBED08920); 1109c503f109Smrg OUTREG(index_reg,0x20803); 1110c503f109Smrg OUTREG(data_reg,0x80008010); 1111c503f109Smrg OUTREG(index_reg,0x30000); 1112c503f109Smrg OUTREG(data_reg,0x90008000); 1113c503f109Smrg OUTREG(index_reg,0x30001); 1114c503f109Smrg OUTREG(data_reg,0x80008000); 1115c503f109Smrg OUTREG(index_reg,0x30100); 1116c503f109Smrg OUTREG(data_reg,0x8FE0BF90); 1117c503f109Smrg OUTREG(index_reg,0x30101); 1118c503f109Smrg OUTREG(data_reg,0xBFF880A0); 1119c503f109Smrg OUTREG(index_reg,0x30200); 1120c503f109Smrg OUTREG(data_reg,0x8F60BF40); 1121c503f109Smrg OUTREG(index_reg,0x30201); 1122c503f109Smrg OUTREG(data_reg,0xBFE88180); 1123c503f109Smrg OUTREG(index_reg,0x30300); 1124c503f109Smrg OUTREG(data_reg,0x8EC0BF00); 1125c503f109Smrg OUTREG(index_reg,0x30301); 1126c503f109Smrg OUTREG(data_reg,0xBFC88280); 1127c503f109Smrg OUTREG(index_reg,0x30400); 1128c503f109Smrg OUTREG(data_reg,0x8DE0BEE0); 1129c503f109Smrg OUTREG(index_reg,0x30401); 1130c503f109Smrg OUTREG(data_reg,0xBFA083A0); 1131c503f109Smrg OUTREG(index_reg,0x30500); 1132c503f109Smrg OUTREG(data_reg,0x8CE0BED0); 1133c503f109Smrg OUTREG(index_reg,0x30501); 1134c503f109Smrg OUTREG(data_reg,0xBF7884E0); 1135c503f109Smrg OUTREG(index_reg,0x30600); 1136c503f109Smrg OUTREG(data_reg,0x8BA0BED8); 1137c503f109Smrg OUTREG(index_reg,0x30601); 1138c503f109Smrg OUTREG(data_reg,0xBF508640); 1139c503f109Smrg OUTREG(index_reg,0x30700); 1140c503f109Smrg OUTREG(data_reg,0x8A60BEE8); 1141c503f109Smrg OUTREG(index_reg,0x30701); 1142c503f109Smrg OUTREG(data_reg,0xBF2087A0); 1143c503f109Smrg OUTREG(index_reg,0x30800); 1144c503f109Smrg OUTREG(data_reg,0x8900BF00); 1145c503f109Smrg OUTREG(index_reg,0x30801); 1146c503f109Smrg OUTREG(data_reg,0xBF008900); 1147b7e1c893Smrg} 1148b7e1c893Smrg 1149209ff23fSmrgstatic int 1150b7e1c893Smrgatombios_output_yuv_setup(xf86OutputPtr output, Bool enable) 1151209ff23fSmrg{ 1152209ff23fSmrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 1153209ff23fSmrg RADEONInfoPtr info = RADEONPTR(output->scrn); 1154b7e1c893Smrg RADEONCrtcPrivatePtr radeon_crtc = output->crtc->driver_private; 1155b7e1c893Smrg ENABLE_YUV_PS_ALLOCATION disp_data; 1156209ff23fSmrg AtomBiosArgRec data; 1157209ff23fSmrg unsigned char *space; 1158b7e1c893Smrg unsigned char *RADEONMMIO = info->MMIO; 1159b7e1c893Smrg uint32_t temp, reg; 1160209ff23fSmrg 1161b7e1c893Smrg if (info->ChipFamily >= CHIP_FAMILY_R600) 1162b7e1c893Smrg reg = R600_BIOS_3_SCRATCH; 1163b7e1c893Smrg else 1164b7e1c893Smrg reg = RADEON_BIOS_3_SCRATCH; 1165b7e1c893Smrg 1166b7e1c893Smrg //fix up scratch reg handling 1167b7e1c893Smrg temp = INREG(reg); 1168b7e1c893Smrg if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT)) 1169b7e1c893Smrg OUTREG(reg, (ATOM_S3_TV1_ACTIVE | 1170b7e1c893Smrg (radeon_crtc->crtc_id << 18))); 1171b7e1c893Smrg else if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT)) 1172b7e1c893Smrg OUTREG(reg, (ATOM_S3_CV_ACTIVE | 1173b7e1c893Smrg (radeon_crtc->crtc_id << 24))); 1174b7e1c893Smrg else 1175b7e1c893Smrg OUTREG(reg, 0); 1176209ff23fSmrg 1177b7e1c893Smrg memset(&disp_data, 0, sizeof(disp_data)); 1178209ff23fSmrg 1179b7e1c893Smrg if (enable) 1180b7e1c893Smrg disp_data.ucEnable = ATOM_ENABLE; 1181b7e1c893Smrg disp_data.ucCRTC = radeon_crtc->crtc_id; 1182209ff23fSmrg 1183b7e1c893Smrg data.exec.index = GetIndexIntoMasterTable(COMMAND, EnableYUV); 1184209ff23fSmrg data.exec.dataSpace = (void *)&space; 1185209ff23fSmrg data.exec.pspace = &disp_data; 1186209ff23fSmrg 1187209ff23fSmrg if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { 1188b7e1c893Smrg 1189b7e1c893Smrg OUTREG(reg, temp); 1190b7e1c893Smrg 1191b7e1c893Smrg ErrorF("crtc %d YUV %s setup success\n", radeon_crtc->crtc_id, enable ? "enable" : "disable"); 1192209ff23fSmrg return ATOM_SUCCESS; 1193209ff23fSmrg } 1194209ff23fSmrg 1195b7e1c893Smrg OUTREG(reg, temp); 1196b7e1c893Smrg 1197b7e1c893Smrg ErrorF("crtc %d YUV %s setup failed\n", radeon_crtc->crtc_id, enable ? "enable" : "disable"); 1198209ff23fSmrg return ATOM_NOT_IMPLEMENTED; 1199209ff23fSmrg 1200209ff23fSmrg} 1201209ff23fSmrg 1202209ff23fSmrgstatic int 1203b7e1c893Smrgatombios_output_overscan_setup(xf86OutputPtr output, DisplayModePtr mode, DisplayModePtr adjusted_mode) 1204209ff23fSmrg{ 1205209ff23fSmrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 1206b7e1c893Smrg RADEONCrtcPrivatePtr radeon_crtc = output->crtc->driver_private; 1207209ff23fSmrg RADEONInfoPtr info = RADEONPTR(output->scrn); 1208b7e1c893Smrg SET_CRTC_OVERSCAN_PS_ALLOCATION overscan_param; 1209209ff23fSmrg AtomBiosArgRec data; 1210209ff23fSmrg unsigned char *space; 1211b7e1c893Smrg memset(&overscan_param, 0, sizeof(overscan_param)); 1212209ff23fSmrg 1213b7e1c893Smrg overscan_param.usOverscanRight = 0; 1214b7e1c893Smrg overscan_param.usOverscanLeft = 0; 1215b7e1c893Smrg overscan_param.usOverscanBottom = 0; 1216b7e1c893Smrg overscan_param.usOverscanTop = 0; 1217b7e1c893Smrg overscan_param.ucCRTC = radeon_crtc->crtc_id; 1218b7e1c893Smrg 1219b7e1c893Smrg if (radeon_output->Flags & RADEON_USE_RMX) { 1220b7e1c893Smrg if (radeon_output->rmx_type == RMX_FULL) { 1221b7e1c893Smrg overscan_param.usOverscanRight = 0; 1222b7e1c893Smrg overscan_param.usOverscanLeft = 0; 1223b7e1c893Smrg overscan_param.usOverscanBottom = 0; 1224b7e1c893Smrg overscan_param.usOverscanTop = 0; 1225b7e1c893Smrg } else if (radeon_output->rmx_type == RMX_CENTER) { 1226b7e1c893Smrg overscan_param.usOverscanTop = (adjusted_mode->CrtcVDisplay - mode->CrtcVDisplay) / 2; 1227b7e1c893Smrg overscan_param.usOverscanBottom = (adjusted_mode->CrtcVDisplay - mode->CrtcVDisplay) / 2; 1228b7e1c893Smrg overscan_param.usOverscanLeft = (adjusted_mode->CrtcHDisplay - mode->CrtcHDisplay) / 2; 1229b7e1c893Smrg overscan_param.usOverscanRight = (adjusted_mode->CrtcHDisplay - mode->CrtcHDisplay) / 2; 1230b7e1c893Smrg } else if (radeon_output->rmx_type == RMX_ASPECT) { 1231b7e1c893Smrg int a1 = mode->CrtcVDisplay * adjusted_mode->CrtcHDisplay; 1232b7e1c893Smrg int a2 = adjusted_mode->CrtcVDisplay * mode->CrtcHDisplay; 1233b7e1c893Smrg 1234b7e1c893Smrg if (a1 > a2) { 1235b7e1c893Smrg overscan_param.usOverscanLeft = (adjusted_mode->CrtcHDisplay - (a2 / mode->CrtcVDisplay)) / 2; 1236b7e1c893Smrg overscan_param.usOverscanRight = (adjusted_mode->CrtcHDisplay - (a2 / mode->CrtcVDisplay)) / 2; 1237b7e1c893Smrg } else if (a2 > a1) { 1238b7e1c893Smrg overscan_param.usOverscanLeft = (adjusted_mode->CrtcVDisplay - (a1 / mode->CrtcHDisplay)) / 2; 1239b7e1c893Smrg overscan_param.usOverscanRight = (adjusted_mode->CrtcVDisplay - (a1 / mode->CrtcHDisplay)) / 2; 1240b7e1c893Smrg } 1241209ff23fSmrg } 1242209ff23fSmrg } 1243209ff23fSmrg 1244b7e1c893Smrg data.exec.index = GetIndexIntoMasterTable(COMMAND, SetCRTC_OverScan); 1245209ff23fSmrg data.exec.dataSpace = (void *)&space; 1246b7e1c893Smrg data.exec.pspace = &overscan_param; 1247209ff23fSmrg 1248209ff23fSmrg if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { 1249b7e1c893Smrg ErrorF("Set CRTC %d Overscan success\n", radeon_crtc->crtc_id); 1250b7e1c893Smrg return ATOM_SUCCESS ; 1251209ff23fSmrg } 1252209ff23fSmrg 1253b7e1c893Smrg ErrorF("Set CRTC %d Overscan failed\n", radeon_crtc->crtc_id); 1254209ff23fSmrg return ATOM_NOT_IMPLEMENTED; 1255209ff23fSmrg} 1256209ff23fSmrg 1257209ff23fSmrgstatic int 1258b7e1c893Smrgatombios_output_scaler_setup(xf86OutputPtr output) 1259209ff23fSmrg{ 1260209ff23fSmrg RADEONInfoPtr info = RADEONPTR(output->scrn); 1261209ff23fSmrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 1262b7e1c893Smrg radeon_tvout_ptr tvout = &radeon_output->tvout; 1263209ff23fSmrg RADEONCrtcPrivatePtr radeon_crtc = output->crtc->driver_private; 1264209ff23fSmrg ENABLE_SCALER_PS_ALLOCATION disp_data; 1265209ff23fSmrg AtomBiosArgRec data; 1266209ff23fSmrg unsigned char *space; 1267209ff23fSmrg 1268b7e1c893Smrg if (!IS_AVIVO_VARIANT && radeon_crtc->crtc_id) 1269b7e1c893Smrg return ATOM_SUCCESS; 1270b7e1c893Smrg 1271b7e1c893Smrg memset(&disp_data, 0, sizeof(disp_data)); 1272b7e1c893Smrg 1273209ff23fSmrg disp_data.ucScaler = radeon_crtc->crtc_id; 1274209ff23fSmrg 1275b7e1c893Smrg if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT)) { 1276b7e1c893Smrg switch (tvout->tvStd) { 1277b7e1c893Smrg case TV_STD_NTSC: 1278b7e1c893Smrg disp_data.ucTVStandard = ATOM_TV_NTSC; 1279b7e1c893Smrg break; 1280b7e1c893Smrg case TV_STD_PAL: 1281b7e1c893Smrg disp_data.ucTVStandard = ATOM_TV_PAL; 1282b7e1c893Smrg break; 1283b7e1c893Smrg case TV_STD_PAL_M: 1284b7e1c893Smrg disp_data.ucTVStandard = ATOM_TV_PALM; 1285b7e1c893Smrg break; 1286b7e1c893Smrg case TV_STD_PAL_60: 1287b7e1c893Smrg disp_data.ucTVStandard = ATOM_TV_PAL60; 1288b7e1c893Smrg break; 1289b7e1c893Smrg case TV_STD_NTSC_J: 1290b7e1c893Smrg disp_data.ucTVStandard = ATOM_TV_NTSCJ; 1291b7e1c893Smrg break; 1292b7e1c893Smrg case TV_STD_SCART_PAL: 1293b7e1c893Smrg disp_data.ucTVStandard = ATOM_TV_PAL; /* ??? */ 1294b7e1c893Smrg break; 1295b7e1c893Smrg case TV_STD_SECAM: 1296b7e1c893Smrg disp_data.ucTVStandard = ATOM_TV_SECAM; 1297b7e1c893Smrg break; 1298b7e1c893Smrg case TV_STD_PAL_CN: 1299b7e1c893Smrg disp_data.ucTVStandard = ATOM_TV_PALCN; 1300b7e1c893Smrg break; 1301b7e1c893Smrg default: 1302b7e1c893Smrg disp_data.ucTVStandard = ATOM_TV_NTSC; 1303b7e1c893Smrg break; 1304b7e1c893Smrg } 1305b7e1c893Smrg disp_data.ucEnable = SCALER_ENABLE_MULTITAP_MODE; 1306b7e1c893Smrg ErrorF("Using TV scaler %x %x\n", disp_data.ucTVStandard, disp_data.ucEnable); 1307b7e1c893Smrg } else if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT)) { 1308b7e1c893Smrg disp_data.ucTVStandard = ATOM_TV_CV; 1309b7e1c893Smrg disp_data.ucEnable = SCALER_ENABLE_MULTITAP_MODE; 1310b7e1c893Smrg ErrorF("Using CV scaler %x %x\n", disp_data.ucTVStandard, disp_data.ucEnable); 1311b7e1c893Smrg } else if (radeon_output->Flags & RADEON_USE_RMX) { 1312209ff23fSmrg ErrorF("Using RMX\n"); 1313209ff23fSmrg if (radeon_output->rmx_type == RMX_FULL) 1314209ff23fSmrg disp_data.ucEnable = ATOM_SCALER_EXPANSION; 1315209ff23fSmrg else if (radeon_output->rmx_type == RMX_CENTER) 1316209ff23fSmrg disp_data.ucEnable = ATOM_SCALER_CENTER; 1317b7e1c893Smrg else if (radeon_output->rmx_type == RMX_ASPECT) 1318b7e1c893Smrg disp_data.ucEnable = ATOM_SCALER_EXPANSION; 1319209ff23fSmrg } else { 1320209ff23fSmrg ErrorF("Not using RMX\n"); 1321b7e1c893Smrg if (IS_AVIVO_VARIANT) 1322b7e1c893Smrg disp_data.ucEnable = ATOM_SCALER_DISABLE; 1323b7e1c893Smrg else 1324b7e1c893Smrg disp_data.ucEnable = ATOM_SCALER_CENTER; 1325209ff23fSmrg } 1326209ff23fSmrg 1327209ff23fSmrg data.exec.index = GetIndexIntoMasterTable(COMMAND, EnableScaler); 1328209ff23fSmrg data.exec.dataSpace = (void *)&space; 1329209ff23fSmrg data.exec.pspace = &disp_data; 1330209ff23fSmrg 1331209ff23fSmrg if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { 1332b7e1c893Smrg if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT) 1333b7e1c893Smrg && info->ChipFamily >= CHIP_FAMILY_RV515 && info->ChipFamily <= CHIP_FAMILY_RV570) { 1334b7e1c893Smrg ErrorF("forcing TV scaler\n"); 1335c503f109Smrg atom_rv515_force_tv_scaler(output->scrn, radeon_crtc); 1336b7e1c893Smrg } 1337209ff23fSmrg ErrorF("scaler %d setup success\n", radeon_crtc->crtc_id); 1338209ff23fSmrg return ATOM_SUCCESS; 1339209ff23fSmrg } 1340209ff23fSmrg 1341209ff23fSmrg ErrorF("scaler %d setup failed\n", radeon_crtc->crtc_id); 1342209ff23fSmrg return ATOM_NOT_IMPLEMENTED; 1343209ff23fSmrg 1344209ff23fSmrg} 1345209ff23fSmrg 1346b7e1c893Smrgvoid 1347b7e1c893Smrgatombios_output_dpms(xf86OutputPtr output, int mode) 1348209ff23fSmrg{ 1349b7e1c893Smrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 1350b7e1c893Smrg radeon_encoder_ptr radeon_encoder = radeon_get_encoder(output); 1351209ff23fSmrg RADEONInfoPtr info = RADEONPTR(output->scrn); 1352209ff23fSmrg DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION disp_data; 1353209ff23fSmrg AtomBiosArgRec data; 1354209ff23fSmrg unsigned char *space; 1355209ff23fSmrg int index = 0; 1356b7e1c893Smrg Bool is_dig = FALSE; 1357209ff23fSmrg 1358b7e1c893Smrg if (radeon_encoder == NULL) 1359b7e1c893Smrg return; 1360b7e1c893Smrg 1361b7e1c893Smrg switch (radeon_encoder->encoder_id) { 1362b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 1363b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 1364209ff23fSmrg index = GetIndexIntoMasterTable(COMMAND, TMDSAOutputControl); 1365209ff23fSmrg break; 1366b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 1367b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 1368b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 1369b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 1370b7e1c893Smrg is_dig = TRUE; 1371209ff23fSmrg break; 1372b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_DVO1: 1373b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_DDI: 1374b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 1375b7e1c893Smrg index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl); 1376209ff23fSmrg break; 1377b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_LVDS: 1378209ff23fSmrg index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl); 1379209ff23fSmrg break; 1380b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 1381b7e1c893Smrg if (radeon_output->active_device & (ATOM_DEVICE_LCD_SUPPORT)) 1382b7e1c893Smrg index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl); 1383b7e1c893Smrg else 1384b7e1c893Smrg index = GetIndexIntoMasterTable(COMMAND, LVTMAOutputControl); 1385209ff23fSmrg break; 1386b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_DAC1: 1387b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 1388ad43ddacSmrg if (IS_DCE32_VARIANT) 1389b7e1c893Smrg index = GetIndexIntoMasterTable(COMMAND, DAC1OutputControl); 1390ad43ddacSmrg else { 1391ad43ddacSmrg if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT)) 1392ad43ddacSmrg index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl); 1393ad43ddacSmrg else if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT)) 1394ad43ddacSmrg index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl); 1395ad43ddacSmrg else 1396ad43ddacSmrg index = GetIndexIntoMasterTable(COMMAND, DAC1OutputControl); 1397ad43ddacSmrg } 1398209ff23fSmrg break; 1399b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_DAC2: 1400b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 1401ad43ddacSmrg if (IS_DCE32_VARIANT) 1402b7e1c893Smrg index = GetIndexIntoMasterTable(COMMAND, DAC2OutputControl); 1403ad43ddacSmrg else { 1404ad43ddacSmrg if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT)) 1405ad43ddacSmrg index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl); 1406ad43ddacSmrg else if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT)) 1407ad43ddacSmrg index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl); 1408ad43ddacSmrg else 1409ad43ddacSmrg index = GetIndexIntoMasterTable(COMMAND, DAC2OutputControl); 1410ad43ddacSmrg } 1411209ff23fSmrg break; 1412209ff23fSmrg } 1413209ff23fSmrg 1414209ff23fSmrg switch (mode) { 1415209ff23fSmrg case DPMSModeOn: 1416b7e1c893Smrg radeon_encoder->devices |= radeon_output->active_device; 1417ad43ddacSmrg if (is_dig) { 1418ad43ddacSmrg atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0); 1419ad43ddacSmrg if (((radeon_output->ConnectorType == CONNECTOR_DISPLAY_PORT) || 1420ad43ddacSmrg (radeon_output->ConnectorType == CONNECTOR_EDP)) && 1421ad43ddacSmrg (radeon_output->MonType == MT_DP)) { 1422ad43ddacSmrg do_displayport_link_train(output); 1423ad43ddacSmrg if (IS_DCE4_VARIANT) 1424ad43ddacSmrg atombios_dce4_output_dig_encoder_setup(output, ATOM_ENCODER_CMD_DP_VIDEO_ON); 1425ad43ddacSmrg } 1426ad43ddacSmrg } 1427b7e1c893Smrg else { 1428b7e1c893Smrg disp_data.ucAction = ATOM_ENABLE; 1429b7e1c893Smrg data.exec.index = index; 1430b7e1c893Smrg data.exec.dataSpace = (void *)&space; 1431b7e1c893Smrg data.exec.pspace = &disp_data; 1432b7e1c893Smrg 1433b7e1c893Smrg if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) 1434b7e1c893Smrg ErrorF("Output %s enable success\n", 1435b7e1c893Smrg device_name[radeon_get_device_index(radeon_output->active_device)]); 1436b7e1c893Smrg else 1437b7e1c893Smrg ErrorF("Output %s enable failed\n", 1438b7e1c893Smrg device_name[radeon_get_device_index(radeon_output->active_device)]); 1439b7e1c893Smrg } 1440c503f109Smrg /* at least for TV atom fails to reassociate the correct crtc source at dpms on */ 1441c503f109Smrg if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT)) 1442c503f109Smrg atombios_set_output_crtc_source(output); 1443209ff23fSmrg break; 1444209ff23fSmrg case DPMSModeStandby: 1445209ff23fSmrg case DPMSModeSuspend: 1446209ff23fSmrg case DPMSModeOff: 1447b7e1c893Smrg radeon_encoder->devices &= ~(radeon_output->active_device); 1448b7e1c893Smrg if (!radeon_encoder->devices) { 1449ad43ddacSmrg if (is_dig) { 1450ad43ddacSmrg if (((radeon_output->ConnectorType == CONNECTOR_DISPLAY_PORT) || 1451ad43ddacSmrg (radeon_output->ConnectorType == CONNECTOR_EDP)) && 1452ad43ddacSmrg (radeon_output->MonType == MT_DP)) { 1453ad43ddacSmrg if (IS_DCE4_VARIANT) 1454ad43ddacSmrg atombios_dce4_output_dig_encoder_setup(output, ATOM_ENCODER_CMD_DP_VIDEO_OFF); 1455ad43ddacSmrg } 1456ad43ddacSmrg atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT, 0, 0); 1457ad43ddacSmrg } else { 1458b7e1c893Smrg disp_data.ucAction = ATOM_DISABLE; 1459b7e1c893Smrg data.exec.index = index; 1460b7e1c893Smrg data.exec.dataSpace = (void *)&space; 1461b7e1c893Smrg data.exec.pspace = &disp_data; 1462b7e1c893Smrg 1463b7e1c893Smrg if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) 1464b7e1c893Smrg == ATOM_SUCCESS) 1465b7e1c893Smrg ErrorF("Output %s disable success\n", 1466b7e1c893Smrg device_name[radeon_get_device_index(radeon_output->active_device)]); 1467b7e1c893Smrg else 1468b7e1c893Smrg ErrorF("Output %s disable failed\n", 1469b7e1c893Smrg device_name[radeon_get_device_index(radeon_output->active_device)]); 1470b7e1c893Smrg } 1471209ff23fSmrg } 1472b7e1c893Smrg break; 1473209ff23fSmrg } 1474209ff23fSmrg} 1475209ff23fSmrg 1476209ff23fSmrgstatic void 1477209ff23fSmrgatombios_set_output_crtc_source(xf86OutputPtr output) 1478209ff23fSmrg{ 1479209ff23fSmrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 1480209ff23fSmrg RADEONCrtcPrivatePtr radeon_crtc = output->crtc->driver_private; 1481209ff23fSmrg RADEONInfoPtr info = RADEONPTR(output->scrn); 1482b7e1c893Smrg radeon_encoder_ptr radeon_encoder = radeon_get_encoder(output); 1483209ff23fSmrg AtomBiosArgRec data; 1484209ff23fSmrg unsigned char *space; 1485209ff23fSmrg SELECT_CRTC_SOURCE_PS_ALLOCATION crtc_src_param; 1486209ff23fSmrg SELECT_CRTC_SOURCE_PARAMETERS_V2 crtc_src_param2; 1487209ff23fSmrg int index = GetIndexIntoMasterTable(COMMAND, SelectCRTC_Source); 1488209ff23fSmrg int major, minor; 1489209ff23fSmrg 1490b7e1c893Smrg if (radeon_encoder == NULL) 1491b7e1c893Smrg return; 1492b7e1c893Smrg 1493b7e1c893Smrg memset(&crtc_src_param, 0, sizeof(crtc_src_param)); 1494b7e1c893Smrg memset(&crtc_src_param2, 0, sizeof(crtc_src_param2)); 1495209ff23fSmrg atombios_get_command_table_version(info->atomBIOS, index, &major, &minor); 1496209ff23fSmrg 1497209ff23fSmrg /*ErrorF("select crtc source table is %d %d\n", major, minor);*/ 1498209ff23fSmrg 1499209ff23fSmrg switch(major) { 1500b7e1c893Smrg case 1: 1501209ff23fSmrg switch(minor) { 1502209ff23fSmrg case 0: 1503209ff23fSmrg case 1: 1504209ff23fSmrg default: 1505b7e1c893Smrg if (IS_AVIVO_VARIANT) 1506b7e1c893Smrg crtc_src_param.ucCRTC = radeon_crtc->crtc_id; 1507b7e1c893Smrg else { 1508b7e1c893Smrg if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1) 1509b7e1c893Smrg crtc_src_param.ucCRTC = radeon_crtc->crtc_id; 1510b7e1c893Smrg else 1511b7e1c893Smrg crtc_src_param.ucCRTC = radeon_crtc->crtc_id << 2; 1512b7e1c893Smrg } 1513b7e1c893Smrg switch (radeon_encoder->encoder_id) { 1514b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 1515b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 1516b7e1c893Smrg crtc_src_param.ucDevice = ATOM_DEVICE_DFP1_INDEX; 1517b7e1c893Smrg break; 1518b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_LVDS: 1519b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 1520b7e1c893Smrg if (radeon_output->active_device & ATOM_DEVICE_LCD1_SUPPORT) 1521209ff23fSmrg crtc_src_param.ucDevice = ATOM_DEVICE_LCD1_INDEX; 1522b7e1c893Smrg else 1523b7e1c893Smrg crtc_src_param.ucDevice = ATOM_DEVICE_DFP3_INDEX; 1524b7e1c893Smrg break; 1525b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_DVO1: 1526b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_DDI: 1527b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 1528b7e1c893Smrg crtc_src_param.ucDevice = ATOM_DEVICE_DFP2_INDEX; 1529b7e1c893Smrg break; 1530b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_DAC1: 1531b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 1532b7e1c893Smrg if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT)) 1533b7e1c893Smrg crtc_src_param.ucDevice = ATOM_DEVICE_TV1_INDEX; 1534b7e1c893Smrg else if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT)) 1535b7e1c893Smrg crtc_src_param.ucDevice = ATOM_DEVICE_CV_INDEX; 1536b7e1c893Smrg else 1537b7e1c893Smrg crtc_src_param.ucDevice = ATOM_DEVICE_CRT1_INDEX; 1538b7e1c893Smrg break; 1539b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_DAC2: 1540b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 1541b7e1c893Smrg if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT)) 1542209ff23fSmrg crtc_src_param.ucDevice = ATOM_DEVICE_TV1_INDEX; 1543b7e1c893Smrg else if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT)) 1544209ff23fSmrg crtc_src_param.ucDevice = ATOM_DEVICE_CV_INDEX; 1545b7e1c893Smrg else 1546b7e1c893Smrg crtc_src_param.ucDevice = ATOM_DEVICE_CRT2_INDEX; 1547b7e1c893Smrg break; 1548209ff23fSmrg } 1549209ff23fSmrg data.exec.pspace = &crtc_src_param; 1550209ff23fSmrg /*ErrorF("device sourced: 0x%x\n", crtc_src_param.ucDevice);*/ 1551209ff23fSmrg break; 1552209ff23fSmrg case 2: 1553209ff23fSmrg crtc_src_param2.ucCRTC = radeon_crtc->crtc_id; 1554b7e1c893Smrg crtc_src_param2.ucEncodeMode = atombios_get_encoder_mode(output); 1555b7e1c893Smrg switch (radeon_encoder->encoder_id) { 1556b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 1557b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 1558b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 1559b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 1560ad43ddacSmrg switch (radeon_output->dig_encoder) { 1561ad43ddacSmrg case 0: 1562ad43ddacSmrg crtc_src_param2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID; 1563ad43ddacSmrg break; 1564ad43ddacSmrg case 1: 1565ad43ddacSmrg crtc_src_param2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID; 1566ad43ddacSmrg break; 1567ad43ddacSmrg case 2: 1568ad43ddacSmrg crtc_src_param2.ucEncoderID = ASIC_INT_DIG3_ENCODER_ID; 1569ad43ddacSmrg break; 1570ad43ddacSmrg case 3: 1571ad43ddacSmrg crtc_src_param2.ucEncoderID = ASIC_INT_DIG4_ENCODER_ID; 1572ad43ddacSmrg break; 1573ad43ddacSmrg case 4: 1574ad43ddacSmrg crtc_src_param2.ucEncoderID = ASIC_INT_DIG5_ENCODER_ID; 1575ad43ddacSmrg break; 1576ad43ddacSmrg case 5: 1577ad43ddacSmrg crtc_src_param2.ucEncoderID = ASIC_INT_DIG6_ENCODER_ID; 1578ad43ddacSmrg break; 1579ad43ddacSmrg } 1580b7e1c893Smrg break; 1581b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 1582b7e1c893Smrg if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT)) 1583b7e1c893Smrg crtc_src_param2.ucEncoderID = ASIC_INT_TV_ENCODER_ID; 1584b7e1c893Smrg else if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT)) 1585b7e1c893Smrg crtc_src_param2.ucEncoderID = ASIC_INT_TV_ENCODER_ID; 1586b7e1c893Smrg else 1587b7e1c893Smrg crtc_src_param2.ucEncoderID = ASIC_INT_DAC1_ENCODER_ID; 1588b7e1c893Smrg break; 1589b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 1590b7e1c893Smrg if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT)) 1591b7e1c893Smrg crtc_src_param2.ucEncoderID = ASIC_INT_TV_ENCODER_ID; 1592b7e1c893Smrg else if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT)) 1593b7e1c893Smrg crtc_src_param2.ucEncoderID = ASIC_INT_TV_ENCODER_ID; 1594b7e1c893Smrg else 1595b7e1c893Smrg crtc_src_param2.ucEncoderID = ASIC_INT_DAC2_ENCODER_ID; 1596b7e1c893Smrg break; 1597209ff23fSmrg } 1598209ff23fSmrg data.exec.pspace = &crtc_src_param2; 1599209ff23fSmrg /*ErrorF("device sourced: 0x%x\n", crtc_src_param2.ucEncoderID);*/ 1600209ff23fSmrg break; 1601209ff23fSmrg } 1602209ff23fSmrg break; 1603209ff23fSmrg default: 1604b7e1c893Smrg ErrorF("Unknown table version\n"); 1605b7e1c893Smrg exit(-1); 1606209ff23fSmrg } 1607209ff23fSmrg 1608209ff23fSmrg data.exec.index = index; 1609209ff23fSmrg data.exec.dataSpace = (void *)&space; 1610209ff23fSmrg 1611209ff23fSmrg if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { 1612209ff23fSmrg ErrorF("Set CRTC %d Source success\n", radeon_crtc->crtc_id); 1613209ff23fSmrg return; 1614209ff23fSmrg } 1615209ff23fSmrg 1616209ff23fSmrg ErrorF("Set CRTC Source failed\n"); 1617209ff23fSmrg return; 1618209ff23fSmrg} 1619209ff23fSmrg 1620b7e1c893Smrgstatic void 1621b7e1c893Smrgatombios_apply_output_quirks(xf86OutputPtr output, DisplayModePtr mode) 1622b7e1c893Smrg{ 1623b7e1c893Smrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 1624b7e1c893Smrg RADEONCrtcPrivatePtr radeon_crtc = output->crtc->driver_private; 1625b7e1c893Smrg RADEONInfoPtr info = RADEONPTR(output->scrn); 1626b7e1c893Smrg unsigned char *RADEONMMIO = info->MMIO; 1627b7e1c893Smrg 1628b7e1c893Smrg /* Funky macbooks */ 1629b7e1c893Smrg if ((info->Chipset == PCI_CHIP_RV530_71C5) && 1630b7e1c893Smrg (PCI_SUB_VENDOR_ID(info->PciInfo) == 0x106b) && 1631b7e1c893Smrg (PCI_SUB_DEVICE_ID(info->PciInfo) == 0x0080)) { 1632b7e1c893Smrg if (radeon_output->MonType == MT_LCD) { 1633b7e1c893Smrg if (radeon_output->devices & ATOM_DEVICE_LCD1_SUPPORT) { 1634b7e1c893Smrg uint32_t lvtma_bit_depth_control = INREG(AVIVO_LVTMA_BIT_DEPTH_CONTROL); 1635b7e1c893Smrg 1636b7e1c893Smrg lvtma_bit_depth_control &= ~AVIVO_LVTMA_BIT_DEPTH_CONTROL_TRUNCATE_EN; 1637b7e1c893Smrg lvtma_bit_depth_control &= ~AVIVO_LVTMA_BIT_DEPTH_CONTROL_SPATIAL_DITHER_EN; 1638b7e1c893Smrg 1639b7e1c893Smrg OUTREG(AVIVO_LVTMA_BIT_DEPTH_CONTROL, lvtma_bit_depth_control); 1640b7e1c893Smrg } 1641b7e1c893Smrg } 1642b7e1c893Smrg } 1643b7e1c893Smrg 1644b7e1c893Smrg /* set scaler clears this on some chips */ 1645ad43ddacSmrg if (!(radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT))) { 1646ad43ddacSmrg if (IS_AVIVO_VARIANT && (mode->Flags & V_INTERLACE)) 1647ad43ddacSmrg OUTREG(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset, AVIVO_D1MODE_INTERLEAVE_EN); 1648ad43ddacSmrg } 1649ad43ddacSmrg 1650ad43ddacSmrg if (IS_DCE32_VARIANT && 1651ad43ddacSmrg (!IS_DCE4_VARIANT) && 1652ad43ddacSmrg (radeon_output->active_device & (ATOM_DEVICE_DFP_SUPPORT))) { 1653ad43ddacSmrg radeon_encoder_ptr radeon_encoder = radeon_get_encoder(output); 1654ad43ddacSmrg if (radeon_encoder == NULL) 1655ad43ddacSmrg return; 1656ad43ddacSmrg /* XXX: need to sort out why transmitter control table sometimes sets this to a 1657ad43ddacSmrg * different golden value. 1658ad43ddacSmrg */ 1659ad43ddacSmrg if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_UNIPHY2) { 1660ad43ddacSmrg OUTREG(0x7ec4, 0x00824002); 1661ad43ddacSmrg } 1662ad43ddacSmrg } 1663b7e1c893Smrg} 1664b7e1c893Smrg 1665ad43ddacSmrgstatic void 1666ad43ddacSmrgatombios_pick_dig_encoder(xf86OutputPtr output) 1667ad43ddacSmrg{ 1668ad43ddacSmrg xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(output->scrn); 1669ad43ddacSmrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 1670ad43ddacSmrg RADEONInfoPtr info = RADEONPTR(output->scrn); 1671ad43ddacSmrg radeon_encoder_ptr radeon_encoder = NULL; 1672ad43ddacSmrg Bool is_lvtma = FALSE; 1673ad43ddacSmrg int i, mode; 1674ad43ddacSmrg uint32_t dig_enc_use_mask = 0; 1675ad43ddacSmrg 1676ad43ddacSmrg /* non digital encoders don't need a dig block */ 1677ad43ddacSmrg mode = atombios_get_encoder_mode(output); 1678ad43ddacSmrg if (mode == ATOM_ENCODER_MODE_CRT || 1679ad43ddacSmrg mode == ATOM_ENCODER_MODE_TV || 1680ad43ddacSmrg mode == ATOM_ENCODER_MODE_CV) 1681ad43ddacSmrg return; 1682ad43ddacSmrg 1683ad43ddacSmrg if (IS_DCE4_VARIANT) { 1684ad43ddacSmrg radeon_encoder = radeon_get_encoder(output); 1685ad43ddacSmrg 1686ad43ddacSmrg switch (radeon_encoder->encoder_id) { 1687ad43ddacSmrg case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 1688ad43ddacSmrg if (radeon_output->linkb) 1689ad43ddacSmrg radeon_output->dig_encoder = 1; 1690ad43ddacSmrg else 1691ad43ddacSmrg radeon_output->dig_encoder = 0; 1692ad43ddacSmrg break; 1693ad43ddacSmrg case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 1694ad43ddacSmrg if (radeon_output->linkb) 1695ad43ddacSmrg radeon_output->dig_encoder = 3; 1696ad43ddacSmrg else 1697ad43ddacSmrg radeon_output->dig_encoder = 2; 1698ad43ddacSmrg break; 1699ad43ddacSmrg case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 1700ad43ddacSmrg if (radeon_output->linkb) 1701ad43ddacSmrg radeon_output->dig_encoder = 5; 1702ad43ddacSmrg else 1703ad43ddacSmrg radeon_output->dig_encoder = 4; 1704ad43ddacSmrg break; 1705ad43ddacSmrg default: 1706ad43ddacSmrg ErrorF("Unknown encoder\n"); 1707ad43ddacSmrg break; 1708ad43ddacSmrg } 1709ad43ddacSmrg return; 1710ad43ddacSmrg } 1711ad43ddacSmrg 1712ad43ddacSmrg if (IS_DCE32_VARIANT) { 1713ad43ddacSmrg RADEONCrtcPrivatePtr radeon_crtc = output->crtc->driver_private; 1714ad43ddacSmrg radeon_output->dig_encoder = radeon_crtc->crtc_id; 1715ad43ddacSmrg return; 1716ad43ddacSmrg } 1717ad43ddacSmrg 1718ad43ddacSmrg for (i = 0; i < xf86_config->num_output; i++) { 1719ad43ddacSmrg xf86OutputPtr test = xf86_config->output[i]; 1720ad43ddacSmrg RADEONOutputPrivatePtr radeon_test = test->driver_private; 1721ad43ddacSmrg radeon_encoder = radeon_get_encoder(test); 1722ad43ddacSmrg 1723ad43ddacSmrg if (!radeon_encoder || !test->crtc) 1724ad43ddacSmrg continue; 1725ad43ddacSmrg 1726ad43ddacSmrg if (output == test && radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA) 1727ad43ddacSmrg is_lvtma = TRUE; 1728ad43ddacSmrg if (output != test && (radeon_test->dig_encoder >= 0)) 1729ad43ddacSmrg dig_enc_use_mask |= (1 << radeon_test->dig_encoder); 1730ad43ddacSmrg 1731ad43ddacSmrg } 1732ad43ddacSmrg if (is_lvtma) { 1733ad43ddacSmrg if (dig_enc_use_mask & 0x2) 1734ad43ddacSmrg ErrorF("Need digital encoder 2 for LVTMA and it isn't free - stealing\n"); 1735ad43ddacSmrg radeon_output->dig_encoder = 1; 1736ad43ddacSmrg return; 1737ad43ddacSmrg } 1738ad43ddacSmrg if (!(dig_enc_use_mask & 1)) 1739ad43ddacSmrg radeon_output->dig_encoder = 0; 1740ad43ddacSmrg else 1741ad43ddacSmrg radeon_output->dig_encoder = 1; 1742ad43ddacSmrg} 1743209ff23fSmrgvoid 1744209ff23fSmrgatombios_output_mode_set(xf86OutputPtr output, 1745209ff23fSmrg DisplayModePtr mode, 1746209ff23fSmrg DisplayModePtr adjusted_mode) 1747209ff23fSmrg{ 1748209ff23fSmrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 1749b7e1c893Smrg radeon_encoder_ptr radeon_encoder = radeon_get_encoder(output); 1750209ff23fSmrg RADEONInfoPtr info = RADEONPTR(output->scrn); 1751b7e1c893Smrg if (radeon_encoder == NULL) 1752ad43ddacSmrg return; 1753209ff23fSmrg 1754b7e1c893Smrg radeon_output->pixel_clock = adjusted_mode->Clock; 1755ad43ddacSmrg atombios_pick_dig_encoder(output); 1756b7e1c893Smrg atombios_output_overscan_setup(output, mode, adjusted_mode); 1757b7e1c893Smrg atombios_output_scaler_setup(output); 1758209ff23fSmrg atombios_set_output_crtc_source(output); 1759209ff23fSmrg 1760b7e1c893Smrg if (IS_AVIVO_VARIANT) { 1761b7e1c893Smrg if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT)) 1762b7e1c893Smrg atombios_output_yuv_setup(output, TRUE); 1763b7e1c893Smrg else 1764b7e1c893Smrg atombios_output_yuv_setup(output, FALSE); 1765209ff23fSmrg } 1766209ff23fSmrg 1767b7e1c893Smrg switch (radeon_encoder->encoder_id) { 1768b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 1769b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 1770b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_LVDS: 1771b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 1772b7e1c893Smrg atombios_output_digital_setup(output, PANEL_ENCODER_ACTION_ENABLE); 1773b7e1c893Smrg break; 1774b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 1775b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 1776b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 1777b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 1778b7e1c893Smrg /* disable encoder and transmitter */ 1779b7e1c893Smrg /* setup and enable the encoder and transmitter */ 1780ad43ddacSmrg atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); 1781ad43ddacSmrg if (IS_DCE4_VARIANT) 1782ad43ddacSmrg atombios_dce4_output_dig_encoder_setup(output, ATOM_ENCODER_CMD_SETUP); 1783ad43ddacSmrg else { 1784ad43ddacSmrg atombios_output_dig_encoder_setup(output, ATOM_DISABLE); 1785ad43ddacSmrg atombios_output_dig_encoder_setup(output, ATOM_ENABLE); 1786ad43ddacSmrg } 1787b7e1c893Smrg atombios_output_dig_encoder_setup(output, ATOM_ENABLE); 1788ad43ddacSmrg atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_INIT, 0, 0); 1789ad43ddacSmrg atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0); 1790ad43ddacSmrg atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); 1791b7e1c893Smrg break; 1792b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_DDI: 1793b7e1c893Smrg atombios_output_ddia_setup(output, ATOM_ENABLE); 1794b7e1c893Smrg break; 1795b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_DVO1: 1796b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 1797b7e1c893Smrg atombios_external_tmds_setup(output, ATOM_ENABLE); 1798b7e1c893Smrg break; 1799b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_DAC1: 1800b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 1801b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_DAC2: 1802b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 1803b7e1c893Smrg atombios_output_dac_setup(output, ATOM_ENABLE); 18042f39173dSmrg if (radeon_output->devices & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) { 18052f39173dSmrg if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) 18062f39173dSmrg atombios_output_tv_setup(output, ATOM_ENABLE); 18072f39173dSmrg else 18082f39173dSmrg atombios_output_tv_setup(output, ATOM_DISABLE); 18092f39173dSmrg } 1810b7e1c893Smrg break; 1811b7e1c893Smrg } 1812b7e1c893Smrg atombios_apply_output_quirks(output, adjusted_mode); 1813209ff23fSmrg} 1814209ff23fSmrg 1815209ff23fSmrgstatic AtomBiosResult 1816209ff23fSmrgatom_bios_dac_load_detect(atomBiosHandlePtr atomBIOS, xf86OutputPtr output) 1817209ff23fSmrg{ 1818209ff23fSmrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 1819209ff23fSmrg RADEONInfoPtr info = RADEONPTR(output->scrn); 1820209ff23fSmrg DAC_LOAD_DETECTION_PS_ALLOCATION dac_data; 1821209ff23fSmrg AtomBiosArgRec data; 1822209ff23fSmrg unsigned char *space; 1823b7e1c893Smrg int major, minor; 1824b7e1c893Smrg int index = GetIndexIntoMasterTable(COMMAND, DAC_LoadDetection); 1825b7e1c893Smrg 1826b7e1c893Smrg atombios_get_command_table_version(info->atomBIOS, index, &major, &minor); 1827209ff23fSmrg 1828209ff23fSmrg dac_data.sDacload.ucMisc = 0; 1829209ff23fSmrg 1830209ff23fSmrg if (radeon_output->devices & ATOM_DEVICE_CRT1_SUPPORT) { 1831b7e1c893Smrg dac_data.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT1_SUPPORT); 1832b7e1c893Smrg if (info->encoders[ATOM_DEVICE_CRT1_INDEX] && 1833b7e1c893Smrg ((info->encoders[ATOM_DEVICE_CRT1_INDEX]->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1) || 1834b7e1c893Smrg (info->encoders[ATOM_DEVICE_CRT1_INDEX]->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1))) 1835209ff23fSmrg dac_data.sDacload.ucDacType = ATOM_DAC_A; 1836b7e1c893Smrg else 1837209ff23fSmrg dac_data.sDacload.ucDacType = ATOM_DAC_B; 1838209ff23fSmrg } else if (radeon_output->devices & ATOM_DEVICE_CRT2_SUPPORT) { 1839b7e1c893Smrg dac_data.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT2_SUPPORT); 1840b7e1c893Smrg if (info->encoders[ATOM_DEVICE_CRT2_INDEX] && 1841b7e1c893Smrg ((info->encoders[ATOM_DEVICE_CRT2_INDEX]->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1) || 1842b7e1c893Smrg (info->encoders[ATOM_DEVICE_CRT2_INDEX]->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1))) 1843209ff23fSmrg dac_data.sDacload.ucDacType = ATOM_DAC_A; 1844b7e1c893Smrg else 1845209ff23fSmrg dac_data.sDacload.ucDacType = ATOM_DAC_B; 1846209ff23fSmrg } else if (radeon_output->devices & ATOM_DEVICE_CV_SUPPORT) { 1847b7e1c893Smrg dac_data.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CV_SUPPORT); 1848b7e1c893Smrg if (info->encoders[ATOM_DEVICE_CV_INDEX] && 1849b7e1c893Smrg ((info->encoders[ATOM_DEVICE_CV_INDEX]->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1) || 1850b7e1c893Smrg (info->encoders[ATOM_DEVICE_CV_INDEX]->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1))) 1851209ff23fSmrg dac_data.sDacload.ucDacType = ATOM_DAC_A; 1852b7e1c893Smrg else 1853209ff23fSmrg dac_data.sDacload.ucDacType = ATOM_DAC_B; 1854b7e1c893Smrg if (minor >= 3) 1855b7e1c893Smrg dac_data.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb; 1856209ff23fSmrg } else if (radeon_output->devices & ATOM_DEVICE_TV1_SUPPORT) { 1857b7e1c893Smrg dac_data.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_TV1_SUPPORT); 1858b7e1c893Smrg if (info->encoders[ATOM_DEVICE_TV1_INDEX] && 1859b7e1c893Smrg ((info->encoders[ATOM_DEVICE_TV1_INDEX]->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1) || 1860b7e1c893Smrg (info->encoders[ATOM_DEVICE_TV1_INDEX]->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1))) 1861209ff23fSmrg dac_data.sDacload.ucDacType = ATOM_DAC_A; 1862b7e1c893Smrg else 1863209ff23fSmrg dac_data.sDacload.ucDacType = ATOM_DAC_B; 1864b7e1c893Smrg if (minor >= 3) 1865b7e1c893Smrg dac_data.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb; 1866b7e1c893Smrg } else 1867209ff23fSmrg return ATOM_NOT_IMPLEMENTED; 1868209ff23fSmrg 1869b7e1c893Smrg data.exec.index = index; 1870209ff23fSmrg data.exec.dataSpace = (void *)&space; 1871209ff23fSmrg data.exec.pspace = &dac_data; 1872209ff23fSmrg 1873209ff23fSmrg if (RHDAtomBiosFunc(atomBIOS->scrnIndex, atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { 1874209ff23fSmrg ErrorF("Dac detection success\n"); 1875209ff23fSmrg return ATOM_SUCCESS ; 1876209ff23fSmrg } 1877209ff23fSmrg 1878209ff23fSmrg ErrorF("DAC detection failed\n"); 1879209ff23fSmrg return ATOM_NOT_IMPLEMENTED; 1880209ff23fSmrg} 1881209ff23fSmrg 1882209ff23fSmrgRADEONMonitorType 1883b7e1c893Smrgatombios_dac_detect(xf86OutputPtr output) 1884209ff23fSmrg{ 1885b7e1c893Smrg ScrnInfoPtr pScrn = output->scrn; 1886209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 1887209ff23fSmrg unsigned char *RADEONMMIO = info->MMIO; 1888209ff23fSmrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 1889209ff23fSmrg RADEONMonitorType MonType = MT_NONE; 1890209ff23fSmrg AtomBiosResult ret; 1891c503f109Smrg RADEONSavePtr save = info->ModeReg; 1892209ff23fSmrg 1893b7e1c893Smrg if (radeon_output->devices & ATOM_DEVICE_TV1_SUPPORT) { 1894209ff23fSmrg if (xf86ReturnOptValBool(info->Options, OPTION_FORCE_TVOUT, FALSE)) { 1895b7e1c893Smrg if (radeon_output->ConnectorType == CONNECTOR_STV) 1896209ff23fSmrg return MT_STV; 1897209ff23fSmrg else 1898209ff23fSmrg return MT_CTV; 1899209ff23fSmrg } 1900209ff23fSmrg } 1901209ff23fSmrg 1902209ff23fSmrg ret = atom_bios_dac_load_detect(info->atomBIOS, output); 1903209ff23fSmrg if (ret == ATOM_SUCCESS) { 1904209ff23fSmrg if (info->ChipFamily >= CHIP_FAMILY_R600) 1905c503f109Smrg save->bios_0_scratch = INREG(R600_BIOS_0_SCRATCH); 1906209ff23fSmrg else 1907c503f109Smrg save->bios_0_scratch = INREG(RADEON_BIOS_0_SCRATCH); 1908c503f109Smrg /*ErrorF("DAC connect %08X\n", (unsigned int)save->bios_0_scratch);*/ 1909209ff23fSmrg 1910209ff23fSmrg if (radeon_output->devices & ATOM_DEVICE_CRT1_SUPPORT) { 1911c503f109Smrg if (save->bios_0_scratch & ATOM_S0_CRT1_MASK) 1912209ff23fSmrg MonType = MT_CRT; 1913209ff23fSmrg } else if (radeon_output->devices & ATOM_DEVICE_CRT2_SUPPORT) { 1914c503f109Smrg if (save->bios_0_scratch & ATOM_S0_CRT2_MASK) 1915209ff23fSmrg MonType = MT_CRT; 1916209ff23fSmrg } else if (radeon_output->devices & ATOM_DEVICE_CV_SUPPORT) { 1917c503f109Smrg if (save->bios_0_scratch & (ATOM_S0_CV_MASK | ATOM_S0_CV_MASK_A)) 1918209ff23fSmrg MonType = MT_CV; 1919209ff23fSmrg } else if (radeon_output->devices & ATOM_DEVICE_TV1_SUPPORT) { 1920c503f109Smrg if (save->bios_0_scratch & (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A)) 1921209ff23fSmrg MonType = MT_CTV; 1922c503f109Smrg else if (save->bios_0_scratch & (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A)) 1923209ff23fSmrg MonType = MT_STV; 1924209ff23fSmrg } 1925209ff23fSmrg } 1926209ff23fSmrg 1927209ff23fSmrg return MonType; 1928209ff23fSmrg} 1929209ff23fSmrg 1930ad43ddacSmrg#define AUX_NATIVE_WRITE 0x8 1931ad43ddacSmrg#define AUX_NATIVE_READ 0x9 1932ad43ddacSmrg 1933ad43ddacSmrg#define AUX_I2C_WRITE 0x0 1934ad43ddacSmrg#define AUX_I2C_READ 0x1 1935ad43ddacSmrg#define AUX_I2C_STATUS 0x2 1936ad43ddacSmrg#define AUX_I2C_MOT 0x4 1937ad43ddacSmrg 1938ad43ddacSmrg#define DP_DPCD_REV 0x0 1939ad43ddacSmrg#define DP_MAX_LINK_RATE 0x1 1940ad43ddacSmrg#define DP_MAX_LANE_COUNT 0x2 1941ad43ddacSmrg#define DP_MAX_DOWNSPREAD 0x3 1942ad43ddacSmrg#define DP_NORP 0x4 1943ad43ddacSmrg#define DP_DOWNSTREAMPORT_PRESENT 0x5 1944ad43ddacSmrg#define DP_MAIN_LINK_CHANNEL_CONFIG 0x6 1945ad43ddacSmrg#define DP_DP11_DOWNSTREAM_PORT_COUNT 0x7 1946ad43ddacSmrg 1947ad43ddacSmrg/* from intel i830_dp.h */ 1948ad43ddacSmrg#define DP_LINK_BW_SET 0x100 1949ad43ddacSmrg//# define DP_LINK_BW_1_62 0x06 1950ad43ddacSmrg//# define DP_LINK_BW_2_7 0x0a 1951ad43ddacSmrg#define DP_LANE_COUNT_SET 0x101 1952ad43ddacSmrg# define DP_LANE_COUNT_MASK 0x0f 1953ad43ddacSmrg# define DP_LANE_COUNT_ENHANCED_FRAME_EN (1 << 7) 1954ad43ddacSmrg 1955ad43ddacSmrg#define DP_TRAINING_PATTERN_SET 0x102 1956ad43ddacSmrg 1957ad43ddacSmrg# define DP_TRAINING_PATTERN_DISABLE 0 1958ad43ddacSmrg# define DP_TRAINING_PATTERN_1 1 1959ad43ddacSmrg# define DP_TRAINING_PATTERN_2 2 1960ad43ddacSmrg# define DP_TRAINING_PATTERN_MASK 0x3 1961ad43ddacSmrg 1962ad43ddacSmrg# define DP_LINK_QUAL_PATTERN_DISABLE (0 << 2) 1963ad43ddacSmrg# define DP_LINK_QUAL_PATTERN_D10_2 (1 << 2) 1964ad43ddacSmrg# define DP_LINK_QUAL_PATTERN_ERROR_RATE (2 << 2) 1965ad43ddacSmrg# define DP_LINK_QUAL_PATTERN_PRBS7 (3 << 2) 1966ad43ddacSmrg# define DP_LINK_QUAL_PATTERN_MASK (3 << 2) 1967ad43ddacSmrg# define DP_RECOVERED_CLOCK_OUT_EN (1 << 4) 1968ad43ddacSmrg# define DP_LINK_SCRAMBLING_DISABLE (1 << 5) 1969ad43ddacSmrg 1970ad43ddacSmrg# define DP_SYMBOL_ERROR_COUNT_BOTH (0 << 6) 1971ad43ddacSmrg# define DP_SYMBOL_ERROR_COUNT_DISPARITY (1 << 6) 1972ad43ddacSmrg# define DP_SYMBOL_ERROR_COUNT_SYMBOL (2 << 6) 1973ad43ddacSmrg# define DP_SYMBOL_ERROR_COUNT_MASK (3 << 6) 1974ad43ddacSmrg 1975ad43ddacSmrg#define DP_TRAINING_LANE0_SET 0x103 1976ad43ddacSmrg#define DP_TRAINING_LANE1_SET 0x104 1977ad43ddacSmrg#define DP_TRAINING_LANE2_SET 0x105 1978ad43ddacSmrg#define DP_TRAINING_LANE3_SET 0x106 1979ad43ddacSmrg# define DP_TRAIN_VOLTAGE_SWING_MASK 0x3 1980ad43ddacSmrg# define DP_TRAIN_VOLTAGE_SWING_SHIFT 0 1981ad43ddacSmrg# define DP_TRAIN_MAX_SWING_REACHED (1 << 2) 1982ad43ddacSmrg# define DP_TRAIN_VOLTAGE_SWING_400 (0 << 0) 1983ad43ddacSmrg# define DP_TRAIN_VOLTAGE_SWING_600 (1 << 0) 1984ad43ddacSmrg# define DP_TRAIN_VOLTAGE_SWING_800 (2 << 0) 1985ad43ddacSmrg# define DP_TRAIN_VOLTAGE_SWING_1200 (3 << 0) 1986ad43ddacSmrg 1987ad43ddacSmrg# define DP_TRAIN_PRE_EMPHASIS_MASK (3 << 3) 1988ad43ddacSmrg# define DP_TRAIN_PRE_EMPHASIS_0 (0 << 3) 1989ad43ddacSmrg# define DP_TRAIN_PRE_EMPHASIS_3_5 (1 << 3) 1990ad43ddacSmrg# define DP_TRAIN_PRE_EMPHASIS_6 (2 << 3) 1991ad43ddacSmrg# define DP_TRAIN_PRE_EMPHASIS_9_5 (3 << 3) 1992ad43ddacSmrg 1993ad43ddacSmrg# define DP_TRAIN_PRE_EMPHASIS_SHIFT 3 1994ad43ddacSmrg# define DP_TRAIN_MAX_PRE_EMPHASIS_REACHED (1 << 5) 1995ad43ddacSmrg#define DP_DOWNSPREAD_CTRL 0x107 1996ad43ddacSmrg# define DP_SPREAD_AMP_0_5 (1 << 4) 1997ad43ddacSmrg 1998ad43ddacSmrg#define DP_MAIN_LINK_CHANNEL_CODING_SET 0x108 1999ad43ddacSmrg# define DP_SET_ANSI_8B10B (1 << 0) 2000ad43ddacSmrg 2001ad43ddacSmrg#define DP_LANE0_1_STATUS 0x202 2002ad43ddacSmrg#define DP_LANE2_3_STATUS 0x203 2003ad43ddacSmrg 2004ad43ddacSmrg# define DP_LANE_CR_DONE (1 << 0) 2005ad43ddacSmrg# define DP_LANE_CHANNEL_EQ_DONE (1 << 1) 2006ad43ddacSmrg# define DP_LANE_SYMBOL_LOCKED (1 << 2) 2007ad43ddacSmrg 2008ad43ddacSmrg#define DP_LANE_ALIGN_STATUS_UPDATED 0x204 2009ad43ddacSmrg#define DP_INTERLANE_ALIGN_DONE (1 << 0) 2010ad43ddacSmrg#define DP_DOWNSTREAM_PORT_STATUS_CHANGED (1 << 6) 2011ad43ddacSmrg#define DP_LINK_STATUS_UPDATED (1 << 7) 2012ad43ddacSmrg 2013ad43ddacSmrg#define DP_SINK_STATUS 0x205 2014ad43ddacSmrg 2015ad43ddacSmrg#define DP_RECEIVE_PORT_0_STATUS (1 << 0) 2016ad43ddacSmrg#define DP_RECEIVE_PORT_1_STATUS (1 << 1) 2017ad43ddacSmrg 2018ad43ddacSmrg#define DP_ADJUST_REQUEST_LANE0_1 0x206 2019ad43ddacSmrg#define DP_ADJUST_REQUEST_LANE2_3 0x207 2020ad43ddacSmrg 2021ad43ddacSmrg#define DP_ADJUST_VOLTAGE_SWING_LANE0_MASK 0x03 2022ad43ddacSmrg#define DP_ADJUST_VOLTAGE_SWING_LANE0_SHIFT 0 2023ad43ddacSmrg#define DP_ADJUST_PRE_EMPHASIS_LANE0_MASK 0x0c 2024ad43ddacSmrg#define DP_ADJUST_PRE_EMPHASIS_LANE0_SHIFT 2 2025ad43ddacSmrg#define DP_ADJUST_VOLTAGE_SWING_LANE1_MASK 0x30 2026ad43ddacSmrg#define DP_ADJUST_VOLTAGE_SWING_LANE1_SHIFT 4 2027ad43ddacSmrg#define DP_ADJUST_PRE_EMPHASIS_LANE1_MASK 0xc0 2028ad43ddacSmrg#define DP_ADJUST_PRE_EMPHASIS_LANE1_SHIFT 6 2029ad43ddacSmrg 2030ad43ddacSmrg#define DP_LINK_STATUS_SIZE 6 2031ad43ddacSmrg#define DP_LINK_CONFIGURATION_SIZE 9 2032ad43ddacSmrg 2033ad43ddacSmrg#define DP_SET_POWER_D0 0x1 2034ad43ddacSmrg#define DP_SET_POWER_D3 0x2 2035ad43ddacSmrg 2036ad43ddacSmrgstatic inline int atom_dp_get_encoder_id(xf86OutputPtr output) 2037ad43ddacSmrg{ 2038ad43ddacSmrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 2039ad43ddacSmrg int ret = 0; 2040ad43ddacSmrg if (radeon_output->dig_encoder) 2041ad43ddacSmrg ret |= ATOM_DP_CONFIG_DIG2_ENCODER; 2042ad43ddacSmrg else 2043ad43ddacSmrg ret |= ATOM_DP_CONFIG_DIG1_ENCODER; 2044ad43ddacSmrg if (radeon_output->linkb) 2045ad43ddacSmrg ret |= ATOM_DP_CONFIG_LINK_B; 2046ad43ddacSmrg else 2047ad43ddacSmrg ret |= ATOM_DP_CONFIG_LINK_A; 2048ad43ddacSmrg return ret; 2049ad43ddacSmrg} 2050ad43ddacSmrg 2051ad43ddacSmrgunion aux_channel_transaction { 2052ad43ddacSmrg PROCESS_AUX_CHANNEL_TRANSACTION_PS_ALLOCATION v1; 2053ad43ddacSmrg PROCESS_AUX_CHANNEL_TRANSACTION_PARAMETERS_V2 v2; 2054ad43ddacSmrg}; 2055ad43ddacSmrg 2056ad43ddacSmrgBool 2057ad43ddacSmrgRADEONProcessAuxCH(xf86OutputPtr output, uint8_t *req_bytes, uint8_t num_bytes, 2058ad43ddacSmrg uint8_t *read_byte, uint8_t read_buf_len, uint8_t delay) 2059ad43ddacSmrg{ 2060ad43ddacSmrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 2061ad43ddacSmrg RADEONInfoPtr info = RADEONPTR(output->scrn); 2062ad43ddacSmrg union aux_channel_transaction args; 2063ad43ddacSmrg AtomBiosArgRec data; 2064ad43ddacSmrg unsigned char *space; 2065ad43ddacSmrg unsigned char *base; 2066ad43ddacSmrg 2067ad43ddacSmrg memset(&args, 0, sizeof(args)); 2068ad43ddacSmrg if (info->atomBIOS->fbBase) 2069ad43ddacSmrg base = info->FB + info->atomBIOS->fbBase; 2070ad43ddacSmrg else if (info->atomBIOS->scratchBase) 2071ad43ddacSmrg base = (unsigned char *)info->atomBIOS->scratchBase; 2072ad43ddacSmrg else 2073ad43ddacSmrg return FALSE; 2074ad43ddacSmrg 2075ad43ddacSmrg memcpy(base, req_bytes, num_bytes); 2076ad43ddacSmrg 2077ad43ddacSmrg args.v1.lpAuxRequest = 0; 2078ad43ddacSmrg args.v1.lpDataOut = 16; 2079ad43ddacSmrg args.v1.ucDataOutLen = 0; 2080ad43ddacSmrg args.v1.ucChannelID = radeon_output->ucI2cId; 2081ad43ddacSmrg args.v1.ucDelay = delay / 10; /* 10 usec */ 2082ad43ddacSmrg if (IS_DCE4_VARIANT) 2083ad43ddacSmrg args.v2.ucHPD_ID = radeon_output->hpd_id; 2084ad43ddacSmrg 2085ad43ddacSmrg data.exec.index = GetIndexIntoMasterTable(COMMAND, ProcessAuxChannelTransaction); 2086ad43ddacSmrg data.exec.dataSpace = (void *)&space; 2087ad43ddacSmrg data.exec.pspace = &args; 2088ad43ddacSmrg 2089ad43ddacSmrg RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data); 2090ad43ddacSmrg if (args.v1.ucReplyStatus) { 2091ad43ddacSmrg ErrorF("failed to get auxch %02x%02x %02x %02x %02x\n", 2092ad43ddacSmrg req_bytes[1], req_bytes[0], req_bytes[2], req_bytes[3], args.v1.ucReplyStatus); 2093ad43ddacSmrg return FALSE; 2094ad43ddacSmrg } 2095ad43ddacSmrg if (args.v1.ucDataOutLen && read_byte && read_buf_len) { 2096ad43ddacSmrg if (read_buf_len < args.v1.ucDataOutLen) { 2097ad43ddacSmrg ErrorF("%s: Buffer too small for return answer %d %d\n", __func__, read_buf_len, args.v1.ucDataOutLen); 2098ad43ddacSmrg return FALSE; 2099ad43ddacSmrg } 2100ad43ddacSmrg { 2101ad43ddacSmrg int len = read_buf_len < args.v1.ucDataOutLen ? read_buf_len : args.v1.ucDataOutLen; 2102ad43ddacSmrg memcpy(read_byte, base+16, len); 2103ad43ddacSmrg } 2104ad43ddacSmrg } 2105ad43ddacSmrg return TRUE; 2106ad43ddacSmrg} 2107ad43ddacSmrg 2108ad43ddacSmrgstatic int 2109ad43ddacSmrgRADEONDPEncoderService(xf86OutputPtr output, int action, uint8_t ucconfig, uint8_t lane_num) 2110ad43ddacSmrg{ 2111ad43ddacSmrg RADEONInfoPtr info = RADEONPTR(output->scrn); 2112ad43ddacSmrg DP_ENCODER_SERVICE_PARAMETERS args; 2113ad43ddacSmrg AtomBiosArgRec data; 2114ad43ddacSmrg unsigned char *space; 2115ad43ddacSmrg 2116ad43ddacSmrg memset(&args, 0, sizeof(args)); 2117ad43ddacSmrg 2118ad43ddacSmrg args.ucLinkClock = 0; 2119ad43ddacSmrg args.ucConfig = ucconfig; 2120ad43ddacSmrg args.ucAction = action; 2121ad43ddacSmrg args.ucLaneNum = lane_num; 2122ad43ddacSmrg args.ucStatus = 0; 2123ad43ddacSmrg 2124ad43ddacSmrg data.exec.index = GetIndexIntoMasterTable(COMMAND, DPEncoderService); 2125ad43ddacSmrg data.exec.dataSpace = (void *)&space; 2126ad43ddacSmrg data.exec.pspace = &args; 2127ad43ddacSmrg 2128ad43ddacSmrg RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data); 2129ad43ddacSmrg 2130ad43ddacSmrg ErrorF("%s: %d\n", __func__, args.ucStatus); 2131ad43ddacSmrg return args.ucStatus; 2132ad43ddacSmrg} 2133ad43ddacSmrg 2134ad43ddacSmrgint RADEON_DP_GetSinkType(xf86OutputPtr output) 2135ad43ddacSmrg{ 2136ad43ddacSmrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 2137ad43ddacSmrg 2138ad43ddacSmrg return RADEONDPEncoderService(output, ATOM_DP_ACTION_GET_SINK_TYPE, radeon_output->ucI2cId, 0); 2139ad43ddacSmrg} 2140ad43ddacSmrg 2141ad43ddacSmrgstatic Bool atom_dp_aux_native_write(xf86OutputPtr output, uint16_t address, 2142ad43ddacSmrg uint8_t send_bytes, uint8_t *send) 2143ad43ddacSmrg{ 2144ad43ddacSmrg uint8_t msg[20]; 2145ad43ddacSmrg uint8_t msg_len, dp_msg_len; 2146ad43ddacSmrg int ret; 2147ad43ddacSmrg 2148ad43ddacSmrg dp_msg_len = 4; 2149ad43ddacSmrg msg[0] = address; 2150ad43ddacSmrg msg[1] = address >> 8; 2151ad43ddacSmrg msg[2] = AUX_NATIVE_WRITE << 4; 2152ad43ddacSmrg dp_msg_len += send_bytes; 2153ad43ddacSmrg msg[3] = (dp_msg_len << 4)| (send_bytes - 1); 2154ad43ddacSmrg 2155ad43ddacSmrg if (0) 2156ad43ddacSmrg ErrorF("writing %02x %02x %02x, %d, %d\n", msg[0], msg[1], msg[3], send_bytes, dp_msg_len); 2157ad43ddacSmrg if (send_bytes > 16) 2158ad43ddacSmrg return FALSE; 2159ad43ddacSmrg 2160ad43ddacSmrg memcpy(&msg[4], send, send_bytes); 2161ad43ddacSmrg msg_len = 4 + send_bytes; 2162ad43ddacSmrg ret = RADEONProcessAuxCH(output, msg, msg_len, NULL, 0, 0); 2163ad43ddacSmrg return ret; 2164ad43ddacSmrg} 2165ad43ddacSmrg 2166ad43ddacSmrgstatic Bool atom_dp_aux_native_read(xf86OutputPtr output, uint16_t address, 2167ad43ddacSmrg uint8_t delay, 2168ad43ddacSmrg uint8_t expected_bytes, uint8_t *read_p) 2169ad43ddacSmrg{ 2170ad43ddacSmrg uint8_t msg[20]; 2171ad43ddacSmrg uint8_t msg_len, dp_msg_len; 2172ad43ddacSmrg int ret; 2173ad43ddacSmrg 2174ad43ddacSmrg msg_len = 4; 2175ad43ddacSmrg dp_msg_len = 4; 2176ad43ddacSmrg msg[0] = address; 2177ad43ddacSmrg msg[1] = address >> 8; 2178ad43ddacSmrg msg[2] = AUX_NATIVE_READ << 4; 2179ad43ddacSmrg msg[3] = (dp_msg_len) << 4; 2180ad43ddacSmrg msg[3] |= expected_bytes - 1; 2181ad43ddacSmrg 2182ad43ddacSmrg if (0) 2183ad43ddacSmrg ErrorF("reading %02x %02x %02x, %d, %d\n", msg[0], msg[1], msg[3], expected_bytes, dp_msg_len); 2184ad43ddacSmrg ret = RADEONProcessAuxCH(output, msg, msg_len, read_p, expected_bytes, delay); 2185ad43ddacSmrg return ret; 2186ad43ddacSmrg} 2187ad43ddacSmrg 2188ad43ddacSmrg/* fill out the DPCD structure */ 2189ad43ddacSmrgvoid RADEON_DP_GetDPCD(xf86OutputPtr output) 2190ad43ddacSmrg{ 2191ad43ddacSmrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 2192ad43ddacSmrg uint8_t msg[25]; 2193ad43ddacSmrg int ret; 2194ad43ddacSmrg 2195ad43ddacSmrg ret = atom_dp_aux_native_read(output, DP_DPCD_REV, 0, 8, msg); 2196ad43ddacSmrg if (ret) { 2197ad43ddacSmrg memcpy(radeon_output->dpcd, msg, 8); 2198ad43ddacSmrg if (0) { 2199ad43ddacSmrg int i; 2200ad43ddacSmrg ErrorF("DPCD: "); 2201ad43ddacSmrg for (i = 0; i < 8; i++) 2202ad43ddacSmrg ErrorF("%02x ", radeon_output->dpcd[i]); 2203ad43ddacSmrg ErrorF("\n"); 2204ad43ddacSmrg } 2205ad43ddacSmrg ret = atom_dp_aux_native_read(output, DP_LINK_BW_SET, 0, 2, msg); 2206ad43ddacSmrg if (0) { 2207ad43ddacSmrg ErrorF("0x200: %02x %02x\n", msg[0], msg[1]); 2208ad43ddacSmrg } 2209ad43ddacSmrg return; 2210ad43ddacSmrg } 2211ad43ddacSmrg radeon_output->dpcd[0] = 0; 2212ad43ddacSmrg return; 2213ad43ddacSmrg} 2214ad43ddacSmrg 2215ad43ddacSmrg 2216ad43ddacSmrgenum dp_aux_i2c_mode { 2217ad43ddacSmrg dp_aux_i2c_start, 2218ad43ddacSmrg dp_aux_i2c_write, 2219ad43ddacSmrg dp_aux_i2c_read, 2220ad43ddacSmrg dp_aux_i2c_stop, 2221ad43ddacSmrg}; 2222ad43ddacSmrg 2223ad43ddacSmrg 2224ad43ddacSmrgstatic Bool atom_dp_aux_i2c_transaction(xf86OutputPtr output, uint16_t address, 2225ad43ddacSmrg enum dp_aux_i2c_mode mode, 2226ad43ddacSmrg uint8_t write_byte, uint8_t *read_byte) 2227ad43ddacSmrg{ 2228ad43ddacSmrg uint8_t msg[8], msg_len, dp_msg_len; 2229ad43ddacSmrg int ret; 2230ad43ddacSmrg int auxch_cmd = 0; 2231ad43ddacSmrg 2232ad43ddacSmrg memset(msg, 0, 8); 2233ad43ddacSmrg 2234ad43ddacSmrg if (mode != dp_aux_i2c_stop) 2235ad43ddacSmrg auxch_cmd = AUX_I2C_MOT; 2236ad43ddacSmrg 2237ad43ddacSmrg if (address & 1) 2238ad43ddacSmrg auxch_cmd |= AUX_I2C_READ; 2239ad43ddacSmrg else 2240ad43ddacSmrg auxch_cmd |= AUX_I2C_WRITE; 2241ad43ddacSmrg 2242ad43ddacSmrg msg[2] = auxch_cmd << 4; 2243ad43ddacSmrg 2244ad43ddacSmrg msg[4] = 0; 2245ad43ddacSmrg msg[0] = (address >> 1); 2246ad43ddacSmrg msg[1] = (address >> 9); 2247ad43ddacSmrg 2248ad43ddacSmrg msg_len = 4; 2249ad43ddacSmrg dp_msg_len = 3; 2250ad43ddacSmrg switch (mode) { 2251ad43ddacSmrg case dp_aux_i2c_read: 2252ad43ddacSmrg /* bottom bits is byte count - 1 so for 1 byte == 0 */ 2253ad43ddacSmrg dp_msg_len += 1; 2254ad43ddacSmrg break; 2255ad43ddacSmrg case dp_aux_i2c_write: 2256ad43ddacSmrg dp_msg_len += 2; 2257ad43ddacSmrg msg[4] = write_byte; 2258ad43ddacSmrg msg_len++; 2259ad43ddacSmrg break; 2260ad43ddacSmrg default: 2261ad43ddacSmrg break; 2262ad43ddacSmrg } 2263ad43ddacSmrg msg[3] = dp_msg_len << 4; 2264ad43ddacSmrg 2265ad43ddacSmrg ret = RADEONProcessAuxCH(output, msg, msg_len, read_byte, 1, 0); 2266ad43ddacSmrg return ret; 2267ad43ddacSmrg} 2268ad43ddacSmrg 2269ad43ddacSmrgstatic Bool 2270ad43ddacSmrgatom_dp_i2c_address(I2CDevPtr dev, I2CSlaveAddr addr) 2271ad43ddacSmrg{ 2272ad43ddacSmrg I2CBusPtr bus = dev->pI2CBus; 2273ad43ddacSmrg xf86OutputPtr output = bus->DriverPrivate.ptr; 2274ad43ddacSmrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 2275ad43ddacSmrg int ret; 2276ad43ddacSmrg 2277ad43ddacSmrg radeon_output->dp_i2c_addr = addr; 2278ad43ddacSmrg radeon_output->dp_i2c_running = TRUE; 2279ad43ddacSmrg 2280ad43ddacSmrg /* call i2c start */ 2281ad43ddacSmrg ret = atom_dp_aux_i2c_transaction(output, radeon_output->dp_i2c_addr, 2282ad43ddacSmrg dp_aux_i2c_start, 0, NULL); 2283ad43ddacSmrg 2284ad43ddacSmrg return ret; 2285ad43ddacSmrg} 2286ad43ddacSmrgstatic Bool 2287ad43ddacSmrgatom_dp_i2c_start(I2CBusPtr bus, int timeout) 2288ad43ddacSmrg{ 2289ad43ddacSmrg ErrorF("%s\n", __func__); 2290ad43ddacSmrg return TRUE; 2291ad43ddacSmrg} 2292ad43ddacSmrg 2293ad43ddacSmrgstatic void 2294ad43ddacSmrgatom_dp_i2c_stop(I2CDevPtr dev) 2295ad43ddacSmrg{ 2296ad43ddacSmrg I2CBusPtr bus = dev->pI2CBus; 2297ad43ddacSmrg xf86OutputPtr output = bus->DriverPrivate.ptr; 2298ad43ddacSmrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 2299ad43ddacSmrg 2300ad43ddacSmrg if (radeon_output->dp_i2c_running) 2301ad43ddacSmrg atom_dp_aux_i2c_transaction(output, radeon_output->dp_i2c_addr, 2302ad43ddacSmrg dp_aux_i2c_stop, 0, NULL); 2303ad43ddacSmrg radeon_output->dp_i2c_running = FALSE; 2304ad43ddacSmrg} 2305ad43ddacSmrg 2306ad43ddacSmrg 2307ad43ddacSmrgstatic Bool 2308ad43ddacSmrgatom_dp_i2c_put_byte(I2CDevPtr dev, I2CByte byte) 2309ad43ddacSmrg{ 2310ad43ddacSmrg I2CBusPtr bus = dev->pI2CBus; 2311ad43ddacSmrg xf86OutputPtr output = bus->DriverPrivate.ptr; 2312ad43ddacSmrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 2313ad43ddacSmrg Bool ret; 2314ad43ddacSmrg 2315ad43ddacSmrg ret = (atom_dp_aux_i2c_transaction(output, radeon_output->dp_i2c_addr, 2316ad43ddacSmrg dp_aux_i2c_write, byte, NULL)); 2317ad43ddacSmrg return ret; 2318ad43ddacSmrg} 2319ad43ddacSmrg 2320ad43ddacSmrgstatic Bool 2321ad43ddacSmrgatom_dp_i2c_get_byte(I2CDevPtr dev, I2CByte *byte_ret, Bool last) 2322ad43ddacSmrg{ 2323ad43ddacSmrg I2CBusPtr bus = dev->pI2CBus; 2324ad43ddacSmrg xf86OutputPtr output = bus->DriverPrivate.ptr; 2325ad43ddacSmrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 2326ad43ddacSmrg Bool ret; 2327ad43ddacSmrg 2328ad43ddacSmrg ret = (atom_dp_aux_i2c_transaction(output, radeon_output->dp_i2c_addr, 2329ad43ddacSmrg dp_aux_i2c_read, 0, byte_ret)); 2330ad43ddacSmrg return ret; 2331ad43ddacSmrg} 2332ad43ddacSmrg 2333ad43ddacSmrgBool 2334ad43ddacSmrgRADEON_DP_I2CInit(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr, char *name, xf86OutputPtr output) 2335ad43ddacSmrg{ 2336ad43ddacSmrg I2CBusPtr pI2CBus; 2337ad43ddacSmrg 2338ad43ddacSmrg pI2CBus = xf86CreateI2CBusRec(); 2339ad43ddacSmrg if (!pI2CBus) return FALSE; 2340ad43ddacSmrg 2341ad43ddacSmrg pI2CBus->BusName = name; 2342ad43ddacSmrg pI2CBus->scrnIndex = pScrn->scrnIndex; 2343ad43ddacSmrg pI2CBus->I2CGetByte = atom_dp_i2c_get_byte; 2344ad43ddacSmrg pI2CBus->I2CPutByte = atom_dp_i2c_put_byte; 2345ad43ddacSmrg pI2CBus->I2CAddress = atom_dp_i2c_address; 2346ad43ddacSmrg pI2CBus->I2CStart = atom_dp_i2c_start; 2347ad43ddacSmrg pI2CBus->I2CStop = atom_dp_i2c_stop; 2348ad43ddacSmrg pI2CBus->DriverPrivate.ptr = output; 2349ad43ddacSmrg 2350ad43ddacSmrg /* 2351ad43ddacSmrg * These were set incorrectly in the server pre-1.3, Having 2352ad43ddacSmrg * duplicate settings is sub-optimal, but this lets the driver 2353ad43ddacSmrg * work with older servers 2354ad43ddacSmrg */ 2355ad43ddacSmrg pI2CBus->ByteTimeout = 2200; /* VESA DDC spec 3 p. 43 (+10 %) */ 2356ad43ddacSmrg pI2CBus->StartTimeout = 550; 2357ad43ddacSmrg pI2CBus->BitTimeout = 40; 2358ad43ddacSmrg pI2CBus->AcknTimeout = 40; 2359ad43ddacSmrg pI2CBus->RiseFallTime = 20; 2360ad43ddacSmrg 2361ad43ddacSmrg if (!xf86I2CBusInit(pI2CBus)) 2362ad43ddacSmrg return FALSE; 2363ad43ddacSmrg 2364ad43ddacSmrg *bus_ptr = pI2CBus; 2365ad43ddacSmrg return TRUE; 2366ad43ddacSmrg} 2367ad43ddacSmrg 2368ad43ddacSmrg 2369ad43ddacSmrgstatic uint8_t dp_link_status(uint8_t link_status[DP_LINK_STATUS_SIZE], int r) 2370ad43ddacSmrg{ 2371ad43ddacSmrg return link_status[r - DP_LANE0_1_STATUS]; 2372ad43ddacSmrg} 2373ad43ddacSmrg 2374ad43ddacSmrgstatic uint8_t dp_get_lane_status(uint8_t link_status[DP_LINK_STATUS_SIZE], int lane) 2375ad43ddacSmrg{ 2376ad43ddacSmrg int i = DP_LANE0_1_STATUS + (lane >> 1); 2377ad43ddacSmrg int s = (lane & 1) * 4; 2378ad43ddacSmrg uint8_t l = dp_link_status(link_status, i); 2379ad43ddacSmrg return (l >> s) & 0xf; 2380ad43ddacSmrg} 2381ad43ddacSmrg 2382ad43ddacSmrgstatic Bool dp_clock_recovery_ok(uint8_t link_status[DP_LINK_STATUS_SIZE], int lane_count) 2383ad43ddacSmrg{ 2384ad43ddacSmrg int lane; 2385ad43ddacSmrg 2386ad43ddacSmrg uint8_t lane_status; 2387ad43ddacSmrg 2388ad43ddacSmrg for (lane = 0; lane < lane_count; lane++) { 2389ad43ddacSmrg lane_status = dp_get_lane_status(link_status, lane); 2390ad43ddacSmrg if ((lane_status & DP_LANE_CR_DONE) == 0) 2391ad43ddacSmrg return FALSE; 2392ad43ddacSmrg } 2393ad43ddacSmrg return TRUE; 2394ad43ddacSmrg} 2395ad43ddacSmrg 2396ad43ddacSmrg 2397ad43ddacSmrg/* Check to see if channel eq is done on all channels */ 2398ad43ddacSmrg#define CHANNEL_EQ_BITS (DP_LANE_CR_DONE|\ 2399ad43ddacSmrg DP_LANE_CHANNEL_EQ_DONE|\ 2400ad43ddacSmrg DP_LANE_SYMBOL_LOCKED) 2401ad43ddacSmrgstatic Bool 2402ad43ddacSmrgdp_channel_eq_ok(uint8_t link_status[DP_LINK_STATUS_SIZE], int lane_count) 2403ad43ddacSmrg{ 2404ad43ddacSmrg uint8_t lane_align; 2405ad43ddacSmrg uint8_t lane_status; 2406ad43ddacSmrg int lane; 2407ad43ddacSmrg 2408ad43ddacSmrg lane_align = dp_link_status(link_status, 2409ad43ddacSmrg DP_LANE_ALIGN_STATUS_UPDATED); 2410ad43ddacSmrg if ((lane_align & DP_INTERLANE_ALIGN_DONE) == 0) 2411ad43ddacSmrg return FALSE; 2412ad43ddacSmrg for (lane = 0; lane < lane_count; lane++) { 2413ad43ddacSmrg lane_status = dp_get_lane_status(link_status, lane); 2414ad43ddacSmrg if ((lane_status & CHANNEL_EQ_BITS) != CHANNEL_EQ_BITS) 2415ad43ddacSmrg return FALSE; 2416ad43ddacSmrg } 2417ad43ddacSmrg return TRUE; 2418ad43ddacSmrg} 2419ad43ddacSmrg 2420ad43ddacSmrg/* 2421ad43ddacSmrg * Fetch AUX CH registers 0x202 - 0x207 which contain 2422ad43ddacSmrg * link status information 2423ad43ddacSmrg */ 2424ad43ddacSmrgstatic Bool 2425ad43ddacSmrgatom_dp_get_link_status(xf86OutputPtr output, 2426ad43ddacSmrg uint8_t link_status[DP_LINK_STATUS_SIZE]) 2427ad43ddacSmrg{ 2428ad43ddacSmrg ScrnInfoPtr pScrn = output->scrn; 2429ad43ddacSmrg int ret; 2430ad43ddacSmrg ret = atom_dp_aux_native_read(output, DP_LANE0_1_STATUS, 100, 2431ad43ddacSmrg DP_LINK_STATUS_SIZE, link_status); 2432ad43ddacSmrg if (!ret) { 2433ad43ddacSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "dp link status failed\n"); 2434ad43ddacSmrg return FALSE; 2435ad43ddacSmrg } 2436ad43ddacSmrg ErrorF("link status %02x %02x %02x %02x %02x %02x\n", link_status[0], link_status[1], 2437ad43ddacSmrg link_status[2], link_status[3], link_status[4], link_status[5]); 2438ad43ddacSmrg 2439ad43ddacSmrg return TRUE; 2440ad43ddacSmrg} 2441ad43ddacSmrg 2442ad43ddacSmrgstatic uint8_t 2443ad43ddacSmrgdp_get_adjust_request_voltage(uint8_t link_status[DP_LINK_STATUS_SIZE], 2444ad43ddacSmrg int lane) 2445ad43ddacSmrg 2446ad43ddacSmrg{ 2447ad43ddacSmrg int i = DP_ADJUST_REQUEST_LANE0_1 + (lane >> 1); 2448ad43ddacSmrg int s = ((lane & 1) ? 2449ad43ddacSmrg DP_ADJUST_VOLTAGE_SWING_LANE1_SHIFT : 2450ad43ddacSmrg DP_ADJUST_VOLTAGE_SWING_LANE0_SHIFT); 2451ad43ddacSmrg uint8_t l = dp_link_status(link_status, i); 2452ad43ddacSmrg 2453ad43ddacSmrg return ((l >> s) & 3) << DP_TRAIN_VOLTAGE_SWING_SHIFT; 2454ad43ddacSmrg} 2455ad43ddacSmrg 2456ad43ddacSmrgstatic uint8_t 2457ad43ddacSmrgdp_get_adjust_request_pre_emphasis(uint8_t link_status[DP_LINK_STATUS_SIZE], 2458ad43ddacSmrg int lane) 2459ad43ddacSmrg{ 2460ad43ddacSmrg int i = DP_ADJUST_REQUEST_LANE0_1 + (lane >> 1); 2461ad43ddacSmrg int s = ((lane & 1) ? 2462ad43ddacSmrg DP_ADJUST_PRE_EMPHASIS_LANE1_SHIFT : 2463ad43ddacSmrg DP_ADJUST_PRE_EMPHASIS_LANE0_SHIFT); 2464ad43ddacSmrg uint8_t l = dp_link_status(link_status, i); 2465ad43ddacSmrg 2466ad43ddacSmrg return ((l >> s) & 3) << DP_TRAIN_PRE_EMPHASIS_SHIFT; 2467ad43ddacSmrg} 2468ad43ddacSmrg 2469ad43ddacSmrgstatic char *voltage_names[] = { 2470ad43ddacSmrg "0.4V", "0.6V", "0.8V", "1.2V" 2471ad43ddacSmrg}; 2472ad43ddacSmrgstatic char *pre_emph_names[] = { 2473ad43ddacSmrg "0dB", "3.5dB", "6dB", "9.5dB" 2474ad43ddacSmrg}; 2475ad43ddacSmrg 2476ad43ddacSmrg/* 2477ad43ddacSmrg * These are source-specific values; current Intel hardware supports 2478ad43ddacSmrg * a maximum voltage of 800mV and a maximum pre-emphasis of 6dB 2479ad43ddacSmrg */ 2480ad43ddacSmrg#define DP_VOLTAGE_MAX DP_TRAIN_VOLTAGE_SWING_1200 2481ad43ddacSmrg 2482ad43ddacSmrgstatic uint8_t 2483ad43ddacSmrgdp_pre_emphasis_max(uint8_t voltage_swing) 2484ad43ddacSmrg{ 2485ad43ddacSmrg switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) { 2486ad43ddacSmrg case DP_TRAIN_VOLTAGE_SWING_400: 2487ad43ddacSmrg return DP_TRAIN_PRE_EMPHASIS_6; 2488ad43ddacSmrg case DP_TRAIN_VOLTAGE_SWING_600: 2489ad43ddacSmrg return DP_TRAIN_PRE_EMPHASIS_6; 2490ad43ddacSmrg case DP_TRAIN_VOLTAGE_SWING_800: 2491ad43ddacSmrg return DP_TRAIN_PRE_EMPHASIS_3_5; 2492ad43ddacSmrg case DP_TRAIN_VOLTAGE_SWING_1200: 2493ad43ddacSmrg default: 2494ad43ddacSmrg return DP_TRAIN_PRE_EMPHASIS_0; 2495ad43ddacSmrg } 2496ad43ddacSmrg} 2497ad43ddacSmrg 2498ad43ddacSmrgstatic void dp_set_training(xf86OutputPtr output, uint8_t training) 2499ad43ddacSmrg{ 2500ad43ddacSmrg atom_dp_aux_native_write(output, DP_TRAINING_PATTERN_SET, 1, &training); 2501ad43ddacSmrg} 2502ad43ddacSmrg 2503ad43ddacSmrgstatic void dp_set_power(xf86OutputPtr output, uint8_t power_state) 2504ad43ddacSmrg{ 2505ad43ddacSmrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 2506ad43ddacSmrg 2507ad43ddacSmrg if (radeon_output->dpcd[0] >= 0x11) { 2508ad43ddacSmrg atom_dp_aux_native_write(output, 0x600, 1, &power_state); 2509ad43ddacSmrg } 2510ad43ddacSmrg} 2511ad43ddacSmrg 2512ad43ddacSmrgstatic void 2513ad43ddacSmrgdp_get_adjust_train(xf86OutputPtr output, 2514ad43ddacSmrg uint8_t link_status[DP_LINK_STATUS_SIZE], 2515ad43ddacSmrg int lane_count, 2516ad43ddacSmrg uint8_t train_set[4]) 2517ad43ddacSmrg{ 2518ad43ddacSmrg ScrnInfoPtr pScrn = output->scrn; 2519ad43ddacSmrg uint8_t v = 0; 2520ad43ddacSmrg uint8_t p = 0; 2521ad43ddacSmrg int lane; 2522ad43ddacSmrg 2523ad43ddacSmrg for (lane = 0; lane < lane_count; lane++) { 2524ad43ddacSmrg uint8_t this_v = dp_get_adjust_request_voltage(link_status, lane); 2525ad43ddacSmrg uint8_t this_p = dp_get_adjust_request_pre_emphasis(link_status, lane); 2526ad43ddacSmrg 2527ad43ddacSmrg if (0) { 2528ad43ddacSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2529ad43ddacSmrg "requested signal parameters: lane %d voltage %s pre_emph %s\n", 2530ad43ddacSmrg lane, 2531ad43ddacSmrg voltage_names[this_v >> DP_TRAIN_VOLTAGE_SWING_SHIFT], 2532ad43ddacSmrg pre_emph_names[this_p >> DP_TRAIN_PRE_EMPHASIS_SHIFT]); 2533ad43ddacSmrg } 2534ad43ddacSmrg if (this_v > v) 2535ad43ddacSmrg v = this_v; 2536ad43ddacSmrg if (this_p > p) 2537ad43ddacSmrg p = this_p; 2538ad43ddacSmrg } 2539ad43ddacSmrg 2540ad43ddacSmrg if (v >= DP_VOLTAGE_MAX) 2541ad43ddacSmrg v = DP_VOLTAGE_MAX | DP_TRAIN_MAX_SWING_REACHED; 2542ad43ddacSmrg 2543ad43ddacSmrg if (p >= dp_pre_emphasis_max(v)) 2544ad43ddacSmrg p = dp_pre_emphasis_max(v) | DP_TRAIN_MAX_PRE_EMPHASIS_REACHED; 2545ad43ddacSmrg 2546ad43ddacSmrg if (0) { 2547ad43ddacSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2548ad43ddacSmrg "using signal parameters: voltage %s pre_emph %s\n", 2549ad43ddacSmrg voltage_names[(v & DP_TRAIN_VOLTAGE_SWING_MASK) >> DP_TRAIN_VOLTAGE_SWING_SHIFT], 2550ad43ddacSmrg pre_emph_names[(p & DP_TRAIN_PRE_EMPHASIS_MASK) >> DP_TRAIN_PRE_EMPHASIS_SHIFT]); 2551ad43ddacSmrg } 2552ad43ddacSmrg for (lane = 0; lane < 4; lane++) 2553ad43ddacSmrg train_set[lane] = v | p; 2554ad43ddacSmrg} 2555ad43ddacSmrg 2556ad43ddacSmrgstatic int radeon_dp_max_lane_count(xf86OutputPtr output) 2557ad43ddacSmrg{ 2558ad43ddacSmrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 2559ad43ddacSmrg int max_lane_count = 4; 2560ad43ddacSmrg 2561ad43ddacSmrg if (radeon_output->dpcd[0] >= 0x11) { 2562ad43ddacSmrg max_lane_count = radeon_output->dpcd[2] & 0x1f; 2563ad43ddacSmrg switch(max_lane_count) { 2564ad43ddacSmrg case 1: case 2: case 4: 2565ad43ddacSmrg break; 2566ad43ddacSmrg default: 2567ad43ddacSmrg max_lane_count = 4; 2568ad43ddacSmrg } 2569ad43ddacSmrg } 2570ad43ddacSmrg return max_lane_count; 2571ad43ddacSmrg} 2572ad43ddacSmrg 2573ad43ddacSmrgstatic int radeon_dp_max_link_bw(xf86OutputPtr output) 2574ad43ddacSmrg{ 2575ad43ddacSmrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 2576ad43ddacSmrg int max_link_bw = radeon_output->dpcd[1]; 2577ad43ddacSmrg switch(max_link_bw) { 2578ad43ddacSmrg case DP_LINK_BW_1_62: 2579ad43ddacSmrg case DP_LINK_BW_2_7: 2580ad43ddacSmrg break; 2581ad43ddacSmrg default: 2582ad43ddacSmrg max_link_bw = DP_LINK_BW_1_62; 2583ad43ddacSmrg break; 2584ad43ddacSmrg } 2585ad43ddacSmrg return max_link_bw; 2586ad43ddacSmrg} 2587ad43ddacSmrg 2588ad43ddacSmrgstatic int radeon_dp_link_clock(uint8_t link_bw) 2589ad43ddacSmrg{ 2590ad43ddacSmrg if (link_bw == DP_LINK_BW_2_7) 2591ad43ddacSmrg return 270000; 2592ad43ddacSmrg else 2593ad43ddacSmrg return 162000; 2594ad43ddacSmrg} 2595ad43ddacSmrg 2596ad43ddacSmrg 2597ad43ddacSmrg/* I think this is a fiction */ 2598ad43ddacSmrgstatic int radeon_dp_link_required(int pixel_clock) 2599ad43ddacSmrg{ 2600ad43ddacSmrg return pixel_clock * 3; 2601ad43ddacSmrg} 2602ad43ddacSmrg 2603ad43ddacSmrgBool radeon_dp_mode_fixup(xf86OutputPtr output, DisplayModePtr mode, DisplayModePtr adjusted_mode) 2604ad43ddacSmrg{ 2605ad43ddacSmrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 2606ad43ddacSmrg int lane_count, clock; 2607ad43ddacSmrg int max_lane_count = radeon_dp_max_lane_count(output); 2608ad43ddacSmrg int max_clock = radeon_dp_max_link_bw(output) == DP_LINK_BW_2_7 ? 1 : 0; 2609ad43ddacSmrg static int bws[2] = { DP_LINK_BW_1_62, DP_LINK_BW_2_7 }; 2610ad43ddacSmrg 2611ad43ddacSmrg for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) { 2612ad43ddacSmrg for (clock = 0; clock <= max_clock; clock++) { 2613ad43ddacSmrg int link_avail = radeon_dp_link_clock(bws[clock]) * lane_count; 2614ad43ddacSmrg 2615ad43ddacSmrg if (radeon_dp_link_required(mode->Clock) <= link_avail) { 2616ad43ddacSmrg radeon_output->dp_lane_count = lane_count; 2617ad43ddacSmrg radeon_output->dp_clock = radeon_dp_link_clock(bws[clock]); 2618ad43ddacSmrg if (0) 2619ad43ddacSmrg xf86DrvMsg(0, X_INFO, 2620ad43ddacSmrg "lane_count %d clock %d\n", 2621ad43ddacSmrg radeon_output->dp_lane_count, 2622ad43ddacSmrg radeon_output->dp_clock); 2623ad43ddacSmrg return TRUE; 2624ad43ddacSmrg } 2625ad43ddacSmrg } 2626ad43ddacSmrg } 2627ad43ddacSmrg return FALSE; 2628ad43ddacSmrg} 2629ad43ddacSmrg 2630ad43ddacSmrgstatic void dp_update_dpvs_emph(xf86OutputPtr output, uint8_t train_set[4]) 2631ad43ddacSmrg{ 2632ad43ddacSmrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 2633ad43ddacSmrg int i; 2634ad43ddacSmrg for (i = 0; i < radeon_output->dp_lane_count; i++) 2635ad43ddacSmrg atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH, i, train_set[i]); 2636ad43ddacSmrg 2637ad43ddacSmrg atom_dp_aux_native_write(output, DP_TRAINING_LANE0_SET, radeon_output->dp_lane_count, train_set); 2638ad43ddacSmrg} 2639ad43ddacSmrg 2640ad43ddacSmrgstatic void do_displayport_link_train(xf86OutputPtr output) 2641ad43ddacSmrg{ 2642ad43ddacSmrg ScrnInfoPtr pScrn = output->scrn; 2643ad43ddacSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 2644ad43ddacSmrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 2645ad43ddacSmrg int enc_id = atom_dp_get_encoder_id(output); 2646ad43ddacSmrg Bool clock_recovery; 2647ad43ddacSmrg uint8_t link_status[DP_LINK_STATUS_SIZE]; 2648ad43ddacSmrg uint8_t tries, voltage, ss_cntl; 2649ad43ddacSmrg uint8_t train_set[4]; 2650ad43ddacSmrg int i; 2651ad43ddacSmrg Bool channel_eq; 2652ad43ddacSmrg uint8_t dp_link_configuration[DP_LINK_CONFIGURATION_SIZE]; 2653ad43ddacSmrg 2654ad43ddacSmrg memset(train_set, 0, 4); 2655ad43ddacSmrg 2656ad43ddacSmrg /* set up link configuration */ 2657ad43ddacSmrg memset(dp_link_configuration, 0, DP_LINK_CONFIGURATION_SIZE); 2658ad43ddacSmrg 2659ad43ddacSmrg if (radeon_output->dp_clock == 270000) 2660ad43ddacSmrg dp_link_configuration[0] = DP_LINK_BW_2_7; 2661ad43ddacSmrg else 2662ad43ddacSmrg dp_link_configuration[0] = DP_LINK_BW_1_62; 2663ad43ddacSmrg dp_link_configuration[1] = radeon_output->dp_lane_count; 2664ad43ddacSmrg 2665ad43ddacSmrg if (radeon_output->dpcd[0] >= 0x11) { 2666ad43ddacSmrg dp_link_configuration[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN; 2667ad43ddacSmrg } 2668ad43ddacSmrg 2669ad43ddacSmrg /* power up to D0 */ 2670ad43ddacSmrg dp_set_power(output, DP_SET_POWER_D0); 2671ad43ddacSmrg 2672ad43ddacSmrg /* disable training */ 2673ad43ddacSmrg dp_set_training(output, DP_TRAINING_PATTERN_DISABLE); 2674ad43ddacSmrg 2675ad43ddacSmrg /* write link rate / num / eh framing */ 2676ad43ddacSmrg atom_dp_aux_native_write(output, DP_LINK_BW_SET, 2, 2677ad43ddacSmrg dp_link_configuration); 2678ad43ddacSmrg 2679ad43ddacSmrg /* write ss cntl */ 2680ad43ddacSmrg ss_cntl = 0; 2681ad43ddacSmrg atom_dp_aux_native_write(output, DP_DOWNSPREAD_CTRL, 1, 2682ad43ddacSmrg &ss_cntl); 2683ad43ddacSmrg 2684ad43ddacSmrg /* start local training start */ 2685ad43ddacSmrg if (IS_DCE4_VARIANT) { 2686ad43ddacSmrg atombios_dce4_output_dig_encoder_setup(output, ATOM_ENCODER_CMD_DP_LINK_TRAINING_START); 2687ad43ddacSmrg atombios_dce4_output_dig_encoder_setup(output, ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN1); 2688ad43ddacSmrg } else { 2689ad43ddacSmrg RADEONDPEncoderService(output, ATOM_DP_ACTION_TRAINING_START, enc_id, 0); 2690ad43ddacSmrg RADEONDPEncoderService(output, ATOM_DP_ACTION_TRAINING_PATTERN_SEL, enc_id, 0); 2691ad43ddacSmrg } 2692ad43ddacSmrg 2693ad43ddacSmrg usleep(400); 2694ad43ddacSmrg dp_set_training(output, DP_TRAINING_PATTERN_1); 2695ad43ddacSmrg dp_update_dpvs_emph(output, train_set); 2696ad43ddacSmrg 2697ad43ddacSmrg /* loop around doing configuration reads and DP encoder setups */ 2698ad43ddacSmrg clock_recovery = FALSE; 2699ad43ddacSmrg tries = 0; 2700ad43ddacSmrg voltage = 0xff; 2701ad43ddacSmrg for (;;) { 2702ad43ddacSmrg usleep(100); 2703ad43ddacSmrg if (!atom_dp_get_link_status(output, link_status)) 2704ad43ddacSmrg break; 2705ad43ddacSmrg 2706ad43ddacSmrg if (dp_clock_recovery_ok(link_status, radeon_output->dp_lane_count)) { 2707ad43ddacSmrg clock_recovery = TRUE; 2708ad43ddacSmrg break; 2709ad43ddacSmrg } 2710ad43ddacSmrg 2711ad43ddacSmrg for (i = 0; i < radeon_output->dp_lane_count; i++) 2712ad43ddacSmrg if ((train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0) 2713ad43ddacSmrg break; 2714ad43ddacSmrg if (i == radeon_output->dp_lane_count) { 2715ad43ddacSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2716ad43ddacSmrg "clock recovery reached max voltage\n"); 2717ad43ddacSmrg break; 2718ad43ddacSmrg } 2719ad43ddacSmrg 2720ad43ddacSmrg /* Check to see if we've tried the same voltage 5 times */ 2721ad43ddacSmrg if ((train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == voltage) { 2722ad43ddacSmrg ++tries; 2723ad43ddacSmrg if (tries == 5) { 2724ad43ddacSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2725ad43ddacSmrg "clock recovery tried 5 times\n"); 2726ad43ddacSmrg break; 2727ad43ddacSmrg } 2728ad43ddacSmrg } else 2729ad43ddacSmrg tries = 0; 2730ad43ddacSmrg 2731ad43ddacSmrg voltage = train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK; 2732ad43ddacSmrg 2733ad43ddacSmrg dp_get_adjust_train(output, link_status, radeon_output->dp_lane_count, train_set); 2734ad43ddacSmrg dp_update_dpvs_emph(output, train_set); 2735ad43ddacSmrg 2736ad43ddacSmrg } 2737ad43ddacSmrg 2738ad43ddacSmrg if (!clock_recovery) 2739ad43ddacSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 2740ad43ddacSmrg "clock recovery failed\n"); 2741ad43ddacSmrg 2742ad43ddacSmrg /* channel equalization */ 2743ad43ddacSmrg tries = 0; 2744ad43ddacSmrg channel_eq = FALSE; 2745ad43ddacSmrg dp_set_training(output, DP_TRAINING_PATTERN_2); 2746ad43ddacSmrg if (IS_DCE4_VARIANT) 2747ad43ddacSmrg atombios_dce4_output_dig_encoder_setup(output, ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN2); 2748ad43ddacSmrg else 2749ad43ddacSmrg RADEONDPEncoderService(output, ATOM_DP_ACTION_TRAINING_PATTERN_SEL, enc_id, 1); 2750ad43ddacSmrg 2751ad43ddacSmrg for (;;) { 2752ad43ddacSmrg usleep(400); 2753ad43ddacSmrg if (!atom_dp_get_link_status(output, link_status)) 2754ad43ddacSmrg break; 2755ad43ddacSmrg 2756ad43ddacSmrg if (dp_channel_eq_ok(link_status, radeon_output->dp_lane_count)) { 2757ad43ddacSmrg channel_eq = TRUE; 2758ad43ddacSmrg break; 2759ad43ddacSmrg } 2760ad43ddacSmrg 2761ad43ddacSmrg /* Try 5 times */ 2762ad43ddacSmrg if (tries > 5) { 2763ad43ddacSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2764ad43ddacSmrg "channel eq failed: 5 tries\n"); 2765ad43ddacSmrg break; 2766ad43ddacSmrg } 2767ad43ddacSmrg 2768ad43ddacSmrg /* Compute new train_set as requested by target */ 2769ad43ddacSmrg dp_get_adjust_train(output, link_status, radeon_output->dp_lane_count, train_set); 2770ad43ddacSmrg dp_update_dpvs_emph(output, train_set); 2771ad43ddacSmrg 2772ad43ddacSmrg ++tries; 2773ad43ddacSmrg } 2774ad43ddacSmrg 2775ad43ddacSmrg if (!channel_eq) 2776ad43ddacSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 2777ad43ddacSmrg "channel eq failed\n"); 2778ad43ddacSmrg 2779ad43ddacSmrg dp_set_training(output, DP_TRAINING_PATTERN_DISABLE); 2780ad43ddacSmrg if (IS_DCE4_VARIANT) 2781ad43ddacSmrg atombios_dce4_output_dig_encoder_setup(output, ATOM_ENCODER_CMD_DP_LINK_TRAINING_COMPLETE); 2782ad43ddacSmrg else 2783ad43ddacSmrg RADEONDPEncoderService(output, ATOM_DP_ACTION_TRAINING_COMPLETE, enc_id, 0); 2784ad43ddacSmrg 2785ad43ddacSmrg} 2786ad43ddacSmrg 2787