1/* 2 * Copyright © 2007 Red Hat, Inc. 3 * Copyright 2007 Advanced Micro Devices, Inc. 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Software"), 7 * to deal in the Software without restriction, including without limitation 8 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 * and/or sell copies of the Software, and to permit persons to whom the 10 * Software is furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice (including the next 13 * paragraph) shall be included in all copies or substantial portions of the 14 * Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 * SOFTWARE. 23 * 24 * Authors: 25 * Dave Airlie <airlied@redhat.com> 26 * Alex Deucher <alexander.deucher@amd.com> 27 * 28 */ 29/* 30 * avivo crtc handling functions. 31 */ 32#ifdef HAVE_CONFIG_H 33#include "config.h" 34#endif 35/* DPMS */ 36#ifdef HAVE_XEXTPROTO_71 37#include <X11/extensions/dpmsconst.h> 38#else 39#define DPMS_SERVER 40#include <X11/extensions/dpms.h> 41#endif 42 43#include <math.h> 44#include "radeon.h" 45#include "radeon_reg.h" 46#include "radeon_macros.h" 47#include "radeon_atombios.h" 48 49#ifdef XF86DRI 50#define _XF86DRI_SERVER_ 51#include "radeon_drm.h" 52#include "sarea.h" 53#endif 54 55extern int 56atombios_get_encoder_mode(xf86OutputPtr output); 57 58extern void 59RADEONInitCrtcBase(xf86CrtcPtr crtc, RADEONSavePtr save, 60 int x, int y); 61extern void 62RADEONInitCrtc2Base(xf86CrtcPtr crtc, RADEONSavePtr save, 63 int x, int y); 64extern void 65RADEONRestoreCrtcBase(ScrnInfoPtr pScrn, 66 RADEONSavePtr restore); 67extern void 68RADEONRestoreCrtc2Base(ScrnInfoPtr pScrn, 69 RADEONSavePtr restore); 70extern void 71RADEONInitCommonRegisters(RADEONSavePtr save, RADEONInfoPtr info); 72extern void 73RADEONInitSurfaceCntl(xf86CrtcPtr crtc, RADEONSavePtr save); 74 75AtomBiosResult 76atombios_lock_crtc(atomBiosHandlePtr atomBIOS, int crtc, int lock) 77{ 78 ENABLE_CRTC_PS_ALLOCATION crtc_data; 79 AtomBiosArgRec data; 80 unsigned char *space; 81 82 crtc_data.ucCRTC = crtc; 83 crtc_data.ucEnable = lock; 84 85 data.exec.index = GetIndexIntoMasterTable(COMMAND, UpdateCRTC_DoubleBufferRegisters); 86 data.exec.dataSpace = (void *)&space; 87 data.exec.pspace = &crtc_data; 88 89 if (RHDAtomBiosFunc(atomBIOS->pScrn, atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { 90/* ErrorF("%s CRTC %d success\n", lock? "Lock":"Unlock", crtc); */ 91 return ATOM_SUCCESS ; 92 } 93 94 ErrorF("Lock CRTC failed\n"); 95 return ATOM_NOT_IMPLEMENTED; 96} 97 98static AtomBiosResult 99atombios_enable_crtc(atomBiosHandlePtr atomBIOS, int crtc, int state) 100{ 101 ENABLE_CRTC_PS_ALLOCATION crtc_data; 102 AtomBiosArgRec data; 103 unsigned char *space; 104 105 crtc_data.ucCRTC = crtc; 106 crtc_data.ucEnable = state; 107 108 data.exec.index = GetIndexIntoMasterTable(COMMAND, EnableCRTC); 109 data.exec.dataSpace = (void *)&space; 110 data.exec.pspace = &crtc_data; 111 112 if (RHDAtomBiosFunc(atomBIOS->pScrn, atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { 113/* ErrorF("%s CRTC %d success\n", state? "Enable":"Disable", crtc); */ 114 return ATOM_SUCCESS ; 115 } 116 117 ErrorF("Enable CRTC failed\n"); 118 return ATOM_NOT_IMPLEMENTED; 119} 120 121static AtomBiosResult 122atombios_enable_crtc_memreq(atomBiosHandlePtr atomBIOS, int crtc, int state) 123{ 124 ENABLE_CRTC_PS_ALLOCATION crtc_data; 125 AtomBiosArgRec data; 126 unsigned char *space; 127 128 crtc_data.ucCRTC = crtc; 129 crtc_data.ucEnable = state; 130 131 data.exec.index = GetIndexIntoMasterTable(COMMAND, EnableCRTCMemReq); 132 data.exec.dataSpace = (void *)&space; 133 data.exec.pspace = &crtc_data; 134 135 if (RHDAtomBiosFunc(atomBIOS->pScrn, atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { 136/* ErrorF("%s CRTC memreq %d success\n", state? "Enable":"Disable", crtc); */ 137 return ATOM_SUCCESS ; 138 } 139 140 ErrorF("Enable CRTC memreq failed\n"); 141 return ATOM_NOT_IMPLEMENTED; 142} 143 144static AtomBiosResult 145atombios_blank_crtc(atomBiosHandlePtr atomBIOS, int crtc, int state) 146{ 147 BLANK_CRTC_PS_ALLOCATION crtc_data; 148 unsigned char *space; 149 AtomBiosArgRec data; 150 151 memset(&crtc_data, 0, sizeof(crtc_data)); 152 crtc_data.ucCRTC = crtc; 153 crtc_data.ucBlanking = state; 154 155 data.exec.index = GetIndexIntoMasterTable(COMMAND, BlankCRTC); 156 data.exec.dataSpace = (void *)&space; 157 data.exec.pspace = &crtc_data; 158 159 if (RHDAtomBiosFunc(atomBIOS->pScrn, atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { 160/* ErrorF("%s CRTC %d success\n", state? "Blank":"Unblank", crtc); */ 161 return ATOM_SUCCESS ; 162 } 163 164 ErrorF("Blank CRTC failed\n"); 165 return ATOM_NOT_IMPLEMENTED; 166} 167 168void 169atombios_crtc_dpms(xf86CrtcPtr crtc, int mode) 170{ 171 RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; 172 RADEONInfoPtr info = RADEONPTR(crtc->scrn); 173 switch (mode) { 174 case DPMSModeOn: 175 atombios_enable_crtc(info->atomBIOS, radeon_crtc->crtc_id, 1); 176 if (IS_DCE3_VARIANT) 177 atombios_enable_crtc_memreq(info->atomBIOS, radeon_crtc->crtc_id, 1); 178 atombios_blank_crtc(info->atomBIOS, radeon_crtc->crtc_id, 0); 179 break; 180 case DPMSModeStandby: 181 case DPMSModeSuspend: 182 case DPMSModeOff: 183 atombios_blank_crtc(info->atomBIOS, radeon_crtc->crtc_id, 1); 184 if (IS_DCE3_VARIANT) 185 atombios_enable_crtc_memreq(info->atomBIOS, radeon_crtc->crtc_id, 0); 186 atombios_enable_crtc(info->atomBIOS, radeon_crtc->crtc_id, 0); 187 break; 188 } 189} 190 191static AtomBiosResult 192atombios_set_crtc_timing(xf86CrtcPtr crtc, DisplayModePtr mode) 193{ 194 RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; 195 RADEONInfoPtr info = RADEONPTR(crtc->scrn); 196 AtomBiosArgRec data; 197 unsigned char *space; 198 uint16_t misc = 0; 199 SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION param; 200 memset(¶m, 0, sizeof(param)); 201 202 param.usH_Total = cpu_to_le16(mode->CrtcHTotal); 203 param.usH_Disp = cpu_to_le16(mode->CrtcHDisplay); 204 param.usH_SyncStart = cpu_to_le16(mode->CrtcHSyncStart); 205 param.usH_SyncWidth = cpu_to_le16(mode->CrtcHSyncEnd - mode->CrtcHSyncStart); 206 param.usV_Total = cpu_to_le16(mode->CrtcVTotal); 207 param.usV_Disp = cpu_to_le16(mode->CrtcVDisplay); 208 param.usV_SyncStart = cpu_to_le16(mode->CrtcVSyncStart); 209 param.usV_SyncWidth = cpu_to_le16(mode->CrtcVSyncEnd - mode->CrtcVSyncStart); 210 211 if (mode->Flags & V_NVSYNC) 212 misc |= ATOM_VSYNC_POLARITY; 213 214 if (mode->Flags & V_NHSYNC) 215 misc |= ATOM_HSYNC_POLARITY; 216 217 if (mode->Flags & V_CSYNC) 218 misc |= ATOM_COMPOSITESYNC; 219 220 if (mode->Flags & V_INTERLACE) 221 misc |= ATOM_INTERLACE; 222 223 if (mode->Flags & V_DBLSCAN) 224 misc |= ATOM_DOUBLE_CLOCK_MODE; 225 226 param.susModeMiscInfo.usAccess = cpu_to_le16(misc); 227 param.ucCRTC = radeon_crtc->crtc_id; 228 229 data.exec.index = GetIndexIntoMasterTable(COMMAND, SetCRTC_Timing); 230 data.exec.dataSpace = (void *)&space; 231 data.exec.pspace = ¶m; 232 233 if (RHDAtomBiosFunc(info->atomBIOS->pScrn, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { 234/* ErrorF("Set CRTC Timing success\n"); */ 235 return ATOM_SUCCESS ; 236 } 237 238 ErrorF("Set CRTC Timing failed\n"); 239 return ATOM_NOT_IMPLEMENTED; 240} 241 242static AtomBiosResult 243atombios_set_crtc_dtd_timing(xf86CrtcPtr crtc, DisplayModePtr mode) 244{ 245 RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; 246 RADEONInfoPtr info = RADEONPTR(crtc->scrn); 247 AtomBiosArgRec data; 248 unsigned char *space; 249 uint16_t misc = 0; 250 SET_CRTC_USING_DTD_TIMING_PARAMETERS param; 251 memset(¶m, 0, sizeof(param)); 252 253 param.usH_Size = cpu_to_le16(mode->CrtcHDisplay); 254 param.usH_Blanking_Time = cpu_to_le16(mode->CrtcHBlankEnd - mode->CrtcHDisplay); 255 param.usV_Size = cpu_to_le16(mode->CrtcVDisplay); 256 param.usV_Blanking_Time = cpu_to_le16(mode->CrtcVBlankEnd - mode->CrtcVDisplay); 257 param.usH_SyncOffset = cpu_to_le16(mode->CrtcHSyncStart - mode->CrtcHDisplay); 258 param.usH_SyncWidth = cpu_to_le16(mode->CrtcHSyncEnd - mode->CrtcHSyncStart); 259 param.usV_SyncOffset = cpu_to_le16(mode->CrtcVSyncStart - mode->CrtcVDisplay); 260 param.usV_SyncWidth = cpu_to_le16(mode->CrtcVSyncEnd - mode->CrtcVSyncStart); 261 262 if (mode->Flags & V_NVSYNC) 263 misc |= ATOM_VSYNC_POLARITY; 264 265 if (mode->Flags & V_NHSYNC) 266 misc |= ATOM_HSYNC_POLARITY; 267 268 if (mode->Flags & V_CSYNC) 269 misc |= ATOM_COMPOSITESYNC; 270 271 if (mode->Flags & V_INTERLACE) 272 misc |= ATOM_INTERLACE; 273 274 if (mode->Flags & V_DBLSCAN) 275 misc |= ATOM_DOUBLE_CLOCK_MODE; 276 277 param.susModeMiscInfo.usAccess = cpu_to_le16(misc); 278 param.ucCRTC= radeon_crtc->crtc_id; 279 280 data.exec.index = GetIndexIntoMasterTable(COMMAND, SetCRTC_UsingDTDTiming); 281 data.exec.dataSpace = (void *)&space; 282 data.exec.pspace = ¶m; 283 284 if (RHDAtomBiosFunc(info->atomBIOS->pScrn, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { 285/* ErrorF("Set DTD CRTC Timing success\n"); */ 286 return ATOM_SUCCESS ; 287 } 288 289 ErrorF("Set DTD CRTC Timing failed\n"); 290 return ATOM_NOT_IMPLEMENTED; 291} 292 293static void 294atombios_pick_pll(xf86CrtcPtr crtc) 295{ 296 RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; 297 RADEONInfoPtr info = RADEONPTR(crtc->scrn); 298 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn); 299 xf86OutputPtr output; 300 RADEONOutputPrivatePtr radeon_output; 301 int o, c; 302 uint32_t pll_use_mask = 0; 303 Bool is_dp = FALSE; 304 305 if (IS_DCE4_VARIANT) { 306 for (o = 0; o < xf86_config->num_output; o++) { 307 output = xf86_config->output[o]; 308 if (output->crtc == crtc) { 309 int mode = atombios_get_encoder_mode(output); 310 radeon_output = output->driver_private; 311 312 if (mode == ATOM_ENCODER_MODE_DP) { 313 is_dp = TRUE; 314 break; 315 } else { 316 for (c = 0; c < xf86_config->num_crtc; c++) { 317 xf86CrtcPtr test_crtc = xf86_config->crtc[c]; 318 RADEONCrtcPrivatePtr radeon_test_crtc = test_crtc->driver_private; 319 320 if (crtc != test_crtc && (radeon_test_crtc->pll_id >= 0)) 321 pll_use_mask |= (1 << radeon_test_crtc->pll_id); 322 323 } 324 } 325 } 326 } 327 /* DP clock comes from DCPLL, DP PHY CLK comes from ext source 328 * setting ATOM_PPLL_INVALID skips the PPLL programming for DP 329 */ 330 if (is_dp) 331 radeon_crtc->pll_id = ATOM_PPLL_INVALID; 332 else if (!(pll_use_mask & 1)) 333 radeon_crtc->pll_id = ATOM_PPLL1; 334 else 335 radeon_crtc->pll_id = ATOM_PPLL2; 336 } else 337 radeon_crtc->pll_id = radeon_crtc->crtc_id; 338 339/* ErrorF("Picked PLL %d\n", radeon_crtc->pll_id); */ 340 341 for (o = 0; o < xf86_config->num_output; o++) { 342 output = xf86_config->output[o]; 343 if (output->crtc == crtc) { 344 radeon_output = output->driver_private; 345 radeon_output->pll_id = radeon_crtc->pll_id; 346 } 347 } 348} 349 350union adjust_pixel_clock { 351 ADJUST_DISPLAY_PLL_PS_ALLOCATION v1; 352 ADJUST_DISPLAY_PLL_PS_ALLOCATION_V3 v3; 353}; 354 355static uint32_t atombios_adjust_pll(xf86CrtcPtr crtc, DisplayModePtr mode, int *pll_flags_p) 356{ 357 RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; 358 ScrnInfoPtr pScrn = crtc->scrn; 359 RADEONInfoPtr info = RADEONPTR(pScrn); 360 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn); 361 uint32_t adjusted_clock = mode->Clock; 362 RADEONOutputPrivatePtr radeon_output = NULL; 363 radeon_encoder_ptr radeon_encoder = NULL; 364 xf86OutputPtr output; 365 int pll_flags = 0; 366 int i; 367 368 if (IS_AVIVO_VARIANT) { 369 if (xf86ReturnOptValBool(info->Options, OPTION_NEW_PLL, TRUE)) 370 radeon_crtc->pll_algo = RADEON_PLL_NEW; 371 else 372 radeon_crtc->pll_algo = RADEON_PLL_OLD; 373 } else { 374 if (xf86ReturnOptValBool(info->Options, OPTION_NEW_PLL, FALSE)) 375 radeon_crtc->pll_algo = RADEON_PLL_NEW; 376 else 377 radeon_crtc->pll_algo = RADEON_PLL_OLD; 378 } 379 380 if (IS_AVIVO_VARIANT) { 381 if ((info->ChipFamily == CHIP_FAMILY_RS600) || 382 (info->ChipFamily == CHIP_FAMILY_RS690) || 383 (info->ChipFamily == CHIP_FAMILY_RS740)) 384 pll_flags |= /*RADEON_PLL_USE_FRAC_FB_DIV |*/ 385 RADEON_PLL_PREFER_CLOSEST_LOWER; 386 if (IS_DCE32_VARIANT && mode->Clock > 200000) /* range limits??? */ 387 pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV; 388 else 389 pll_flags |= RADEON_PLL_PREFER_LOW_REF_DIV; 390 } else { 391 pll_flags |= RADEON_PLL_LEGACY; 392 393 if (mode->Clock > 200000) /* range limits??? */ 394 pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV; 395 else 396 pll_flags |= RADEON_PLL_PREFER_LOW_REF_DIV; 397 } 398 399 for (i = 0; i < xf86_config->num_output; i++) { 400 output = xf86_config->output[i]; 401 if (output->crtc == crtc) { 402 radeon_output = output->driver_private; 403 radeon_encoder = radeon_get_encoder(output); 404 if (IS_AVIVO_VARIANT) { 405 /* DVO wants 2x pixel clock if the DVO chip is in 12 bit mode */ 406 if (radeon_encoder && 407 (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1) && 408 !IS_DCE3_VARIANT) 409 adjusted_clock *= 2; 410 if (radeon_output->active_device & 411 (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT)) { 412 pll_flags |= RADEON_PLL_PREFER_CLOSEST_LOWER; 413 radeon_crtc->pll_algo = RADEON_PLL_OLD; 414 } 415 } else { 416 if (radeon_output->active_device & (ATOM_DEVICE_LCD_SUPPORT | 417 ATOM_DEVICE_DFP_SUPPORT)) 418 pll_flags |= RADEON_PLL_NO_ODD_POST_DIV; 419 if (radeon_output->active_device & (ATOM_DEVICE_LCD_SUPPORT)) 420 pll_flags |= (RADEON_PLL_USE_BIOS_DIVS | RADEON_PLL_USE_REF_DIV); 421 } 422 if (IS_DCE3_VARIANT) 423 break; 424 } 425 } 426 427 if (IS_DCE3_VARIANT) { 428 union adjust_pixel_clock args; 429 int major, minor, index; 430 AtomBiosArgRec data; 431 unsigned char *space; 432 433 memset(&args, 0, sizeof(args)); 434 435 index = GetIndexIntoMasterTable(COMMAND, AdjustDisplayPll); 436 437 atombios_get_command_table_version(info->atomBIOS, index, &major, &minor); 438 439 data.exec.index = index; 440 data.exec.dataSpace = (void *)&space; 441 data.exec.pspace = &args; 442 443 switch(major) { 444 case 1: 445 switch(minor) { 446 case 1: 447 case 2: 448 args.v1.usPixelClock = cpu_to_le16(adjusted_clock / 10); 449 args.v1.ucTransmitterID = radeon_encoder->encoder_id; 450 args.v1.ucEncodeMode = atombios_get_encoder_mode(output); 451 452/* ErrorF("before %d\n", args.v1.usPixelClock); */ 453 if (RHDAtomBiosFunc(info->atomBIOS->pScrn, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { 454 adjusted_clock = le16_to_cpu(args.v1.usPixelClock) * 10; 455 } 456/* ErrorF("after %d\n", args.v1.usPixelClock); */ 457 break; 458 case 3: 459 args.v3.sInput.usPixelClock = cpu_to_le16(adjusted_clock / 10); 460 args.v3.sInput.ucTransmitterID = radeon_encoder->encoder_id; 461 args.v3.sInput.ucEncodeMode = atombios_get_encoder_mode(output); 462 args.v3.sInput.ucDispPllConfig = 0; 463 if (radeon_output->coherent_mode || (args.v3.sInput.ucEncodeMode == ATOM_ENCODER_MODE_DP)) 464 args.v3.sInput.ucDispPllConfig |= DISPPLL_CONFIG_COHERENT_MODE; 465 if (adjusted_clock > 165000) 466 args.v3.sInput.ucDispPllConfig |= DISPPLL_CONFIG_DUAL_LINK; 467 // if SS 468 // args.v3.sInput.ucDispPllConfig |= DISPPLL_CONFIG_SS_ENABLE; 469 470/* ErrorF("before %d 0x%x\n", args.v3.sInput.usPixelClock, args.v3.sInput.ucDispPllConfig); */ 471 if (RHDAtomBiosFunc(info->atomBIOS->pScrn, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { 472 adjusted_clock = args.v3.sOutput.ulDispPllFreq * 10; 473 if (args.v3.sOutput.ucRefDiv) { 474 pll_flags |= RADEON_PLL_USE_REF_DIV; 475 info->pll.reference_div = args.v3.sOutput.ucRefDiv; 476 } 477 if (args.v3.sOutput.ucPostDiv) { 478 pll_flags |= RADEON_PLL_USE_POST_DIV; 479 info->pll.post_div = args.v3.sOutput.ucPostDiv; 480 } 481/* ErrorF("after %d %d %d\n", args.v3.sOutput.ulDispPllFreq, 482 args.v3.sOutput.ucRefDiv, args.v3.sOutput.ucPostDiv); */ 483 } 484 break; 485 default: 486 ErrorF("%s: Unknown table version %d %d\n", __func__, major, minor); 487 goto out; 488 } 489 break; 490 default: 491 ErrorF("%s: Unknown table version %d %d\n", __func__, major, minor); 492 goto out; 493 } 494 } 495out: 496 *pll_flags_p = pll_flags; 497 return adjusted_clock; 498} 499 500union set_pixel_clock { 501 SET_PIXEL_CLOCK_PS_ALLOCATION base; 502 PIXEL_CLOCK_PARAMETERS v1; 503 PIXEL_CLOCK_PARAMETERS_V2 v2; 504 PIXEL_CLOCK_PARAMETERS_V3 v3; 505 PIXEL_CLOCK_PARAMETERS_V5 v5; 506}; 507 508static void 509atombios_crtc_set_dcpll(xf86CrtcPtr crtc) 510{ 511 RADEONInfoPtr info = RADEONPTR(crtc->scrn); 512 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn); 513 xf86OutputPtr output = NULL; 514 RADEONOutputPrivatePtr radeon_output = NULL; 515 radeon_encoder_ptr radeon_encoder = NULL; 516 int index; 517 int major, minor, i; 518 union set_pixel_clock args; 519 AtomBiosArgRec data; 520 unsigned char *space; 521 522 memset(&args, 0, sizeof(args)); 523 524 for (i = 0; i < xf86_config->num_output; i++) { 525 output = xf86_config->output[i]; 526 if (output->crtc == crtc) { 527 radeon_output = output->driver_private; 528 radeon_encoder = radeon_get_encoder(output); 529 break; 530 } 531 } 532 533 if (radeon_output == NULL) { 534 xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR, "No output assigned to crtc!\n"); 535 return; 536 } 537 538 if (radeon_encoder == NULL) { 539 xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR, "No encoder assigned to output!\n"); 540 return; 541 } 542 543 index = GetIndexIntoMasterTable(COMMAND, SetPixelClock); 544 atombios_get_command_table_version(info->atomBIOS, index, &major, &minor); 545 546 /*ErrorF("table is %d %d\n", major, minor);*/ 547 switch(major) { 548 case 1: 549 switch(minor) { 550 case 5: 551 args.v5.ucCRTC = ATOM_CRTC_INVALID; 552 /* XXX: get this from the firmwareinfo table */ 553 args.v5.usPixelClock = info->default_dispclk; 554 args.v5.ucPpll = ATOM_DCPLL; 555 break; 556 default: 557 ErrorF("Unknown table version\n"); 558 exit(-1); 559 } 560 break; 561 default: 562 ErrorF("Unknown table version\n"); 563 exit(-1); 564 } 565 566 data.exec.index = index; 567 data.exec.dataSpace = (void *)&space; 568 data.exec.pspace = &args; 569 570 if (RHDAtomBiosFunc(info->atomBIOS->pScrn, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { 571/* ErrorF("Set DCPLL success\n"); */ 572 return; 573 } 574 575 ErrorF("Set DCPLL failed\n"); 576 return; 577} 578 579static void 580atombios_crtc_set_pll(xf86CrtcPtr crtc, DisplayModePtr mode) 581{ 582 RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; 583 ScrnInfoPtr pScrn = crtc->scrn; 584 RADEONInfoPtr info = RADEONPTR(pScrn); 585 unsigned char *RADEONMMIO = info->MMIO; 586 int index; 587 uint32_t sclock; 588 uint32_t ref_div = 0, fb_div = 0, frac_fb_div = 0, post_div = 0; 589 int major, minor; 590 union set_pixel_clock args; 591 xf86OutputPtr output = NULL; 592 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn); 593 radeon_encoder_ptr radeon_encoder = NULL; 594 int pll_flags = 0; 595 uint32_t temp; 596 AtomBiosArgRec data; 597 unsigned char *space; 598 int i; 599 600 memset(&args, 0, sizeof(args)); 601 602 if (IS_DCE4_VARIANT) { 603 /* XXX 6 crtcs, but only 2 plls */ 604 switch (radeon_crtc->pll_id) { 605 case ATOM_PPLL1: 606 temp = INREG(EVERGREEN_P1PLL_SS_CNTL); 607 OUTREG(EVERGREEN_P1PLL_SS_CNTL, temp & ~EVERGREEN_PxPLL_SS_EN); 608 break; 609 case ATOM_PPLL2: 610 temp = INREG(EVERGREEN_P2PLL_SS_CNTL); 611 OUTREG(EVERGREEN_P2PLL_SS_CNTL, temp & ~EVERGREEN_PxPLL_SS_EN); 612 break; 613 } 614 } else { 615 if (radeon_crtc->crtc_id == 0) { 616 temp = INREG(AVIVO_P1PLL_INT_SS_CNTL); 617 OUTREG(AVIVO_P1PLL_INT_SS_CNTL, temp & ~1); 618 } else { 619 temp = INREG(AVIVO_P2PLL_INT_SS_CNTL); 620 OUTREG(AVIVO_P2PLL_INT_SS_CNTL, temp & ~1); 621 } 622 } 623 624 if (IS_DCE3_VARIANT) { 625 for (i = 0; i < xf86_config->num_output; i++) { 626 output = xf86_config->output[i]; 627 if (output->crtc == crtc) { 628 radeon_encoder = radeon_get_encoder(output); 629 break; 630 } 631 } 632 633 if (output->driver_private == NULL) { 634 xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR, "No output assigned to crtc!\n"); 635 return; 636 } 637 if (radeon_encoder == NULL) { 638 xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR, "No encoder assigned to output!\n"); 639 return; 640 } 641 } 642 643 sclock = atombios_adjust_pll(crtc, mode, &pll_flags); 644 645 RADEONComputePLL(crtc, &info->pll, sclock, &temp, 646 &fb_div, &frac_fb_div, &ref_div, &post_div, pll_flags); 647 sclock = temp; /* 10 khz */ 648 649 xf86DrvMsg(crtc->scrn->scrnIndex, X_INFO, 650 "crtc(%d) Clock: mode %d, PLL %lu\n", 651 radeon_crtc->crtc_id, mode->Clock, (long unsigned int)sclock * 10); 652 xf86DrvMsg(crtc->scrn->scrnIndex, X_INFO, 653 "crtc(%d) PLL : refdiv %u, fbdiv 0x%X(%u), fracfbdiv %u, pdiv %u\n", 654 radeon_crtc->crtc_id, (unsigned int)ref_div, (unsigned int)fb_div, 655 (unsigned int)fb_div, (unsigned int)frac_fb_div, (unsigned int)post_div); 656 657 index = GetIndexIntoMasterTable(COMMAND, SetPixelClock); 658 atombios_get_command_table_version(info->atomBIOS, index, &major, &minor); 659 660 /*ErrorF("table is %d %d\n", major, minor);*/ 661 switch(major) { 662 case 1: 663 switch(minor) { 664 case 1: 665 case 2: 666 args.v2.usPixelClock = cpu_to_le16(mode->Clock / 10); 667 args.v2.usRefDiv = cpu_to_le16(ref_div); 668 args.v2.usFbDiv = cpu_to_le16(fb_div); 669 args.v2.ucFracFbDiv = frac_fb_div; 670 args.v2.ucPostDiv = post_div; 671 args.v2.ucPpll = radeon_crtc->pll_id; 672 args.v2.ucCRTC = radeon_crtc->crtc_id; 673 args.v2.ucRefDivSrc = 1; 674 break; 675 case 3: 676 args.v3.usPixelClock = cpu_to_le16(mode->Clock / 10); 677 args.v3.usRefDiv = cpu_to_le16(ref_div); 678 args.v3.usFbDiv = cpu_to_le16(fb_div); 679 args.v3.ucFracFbDiv = frac_fb_div; 680 args.v3.ucPostDiv = post_div; 681 args.v3.ucPpll = radeon_crtc->pll_id; 682 args.v3.ucMiscInfo = (radeon_crtc->crtc_id << 2); 683 args.v3.ucTransmitterId = radeon_encoder->encoder_id; 684 args.v3.ucEncoderMode = atombios_get_encoder_mode(output); 685 break; 686 case 5: 687 args.v5.ucCRTC = radeon_crtc->crtc_id; 688 args.v5.usPixelClock = cpu_to_le16(mode->Clock / 10); 689 args.v5.ucRefDiv = ref_div; 690 args.v5.usFbDiv = cpu_to_le16(fb_div); 691 args.v5.ulFbDivDecFrac = cpu_to_le32(frac_fb_div * 100000); 692 args.v5.ucPostDiv = post_div; 693 args.v5.ucPpll = radeon_crtc->pll_id; 694 args.v5.ucMiscInfo = 0; //HDMI depth 695 args.v5.ucTransmitterID = radeon_encoder->encoder_id; 696 args.v5.ucEncoderMode = atombios_get_encoder_mode(output); 697 break; 698 default: 699 ErrorF("Unknown table version\n"); 700 exit(-1); 701 } 702 break; 703 default: 704 ErrorF("Unknown table version\n"); 705 exit(-1); 706 } 707 708 data.exec.index = index; 709 data.exec.dataSpace = (void *)&space; 710 data.exec.pspace = &args; 711 712 if (RHDAtomBiosFunc(info->atomBIOS->pScrn, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { 713/* ErrorF("Set CRTC %d PLL success\n", radeon_crtc->crtc_id); */ 714 return; 715 } 716 717 ErrorF("Set CRTC %d PLL failed\n", radeon_crtc->crtc_id); 718 return; 719} 720 721static void evergreen_set_base_format(xf86CrtcPtr crtc, 722 DisplayModePtr mode, 723 DisplayModePtr adjusted_mode, 724 int x, int y) 725{ 726 ScrnInfoPtr pScrn = crtc->scrn; 727 RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; 728 RADEONInfoPtr info = RADEONPTR(pScrn); 729 unsigned char *RADEONMMIO = info->MMIO; 730 uint64_t fb_location = crtc->scrn->fbOffset + info->fbLocation; 731 uint32_t fb_format; 732 uint32_t fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_NONE); 733 734 switch (crtc->scrn->bitsPerPixel) { 735 case 15: 736 fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_16BPP) | 737 EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_ARGB1555)); 738 break; 739 case 16: 740 fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_16BPP) | 741 EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_ARGB565)); 742#if X_BYTE_ORDER == X_BIG_ENDIAN 743 fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_8IN16); 744#endif 745 break; 746 case 24: 747 case 32: 748 fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_32BPP) | 749 EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_ARGB8888)); 750#if X_BYTE_ORDER == X_BIG_ENDIAN 751 fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_8IN32); 752#endif 753 break; 754 default: 755 FatalError("Unsupported screen depth: %d\n", xf86GetDepth()); 756 } 757 758 switch (radeon_crtc->crtc_id) { 759 case 0: 760 default: 761 OUTREG(AVIVO_D1VGA_CONTROL, 0); 762 break; 763 case 1: 764 OUTREG(AVIVO_D2VGA_CONTROL, 0); 765 break; 766 case 2: 767 OUTREG(EVERGREEN_D3VGA_CONTROL, 0); 768 break; 769 case 3: 770 OUTREG(EVERGREEN_D4VGA_CONTROL, 0); 771 break; 772 case 4: 773 OUTREG(EVERGREEN_D5VGA_CONTROL, 0); 774 break; 775 case 5: 776 OUTREG(EVERGREEN_D6VGA_CONTROL, 0); 777 break; 778 } 779 780 /* setup fb format and location 781 */ 782 if (crtc->rotatedData != NULL) { 783 /* x/y offset is already included */ 784 x = 0; 785 y = 0; 786 fb_location = fb_location + (char *)crtc->rotatedData - (char *)info->FB; 787 } 788 789 790 OUTREG(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset, 791 (fb_location >> 32) & 0xf); 792 OUTREG(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset, 793 (fb_location >> 32) & 0xf); 794 OUTREG(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset, 795 fb_location & EVERGREEN_GRPH_SURFACE_ADDRESS_MASK); 796 OUTREG(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset, 797 fb_location & EVERGREEN_GRPH_SURFACE_ADDRESS_MASK); 798 OUTREG(EVERGREEN_GRPH_CONTROL + radeon_crtc->crtc_offset, fb_format); 799 OUTREG(EVERGREEN_GRPH_SWAP_CONTROL + radeon_crtc->crtc_offset, fb_swap); 800 801 OUTREG(EVERGREEN_GRPH_SURFACE_OFFSET_X + radeon_crtc->crtc_offset, 0); 802 OUTREG(EVERGREEN_GRPH_SURFACE_OFFSET_Y + radeon_crtc->crtc_offset, 0); 803 OUTREG(EVERGREEN_GRPH_X_START + radeon_crtc->crtc_offset, 0); 804 OUTREG(EVERGREEN_GRPH_Y_START + radeon_crtc->crtc_offset, 0); 805 OUTREG(EVERGREEN_GRPH_X_END + radeon_crtc->crtc_offset, info->virtualX); 806 OUTREG(EVERGREEN_GRPH_Y_END + radeon_crtc->crtc_offset, info->virtualY); 807 OUTREG(EVERGREEN_GRPH_PITCH + radeon_crtc->crtc_offset, 808 crtc->scrn->displayWidth); 809 OUTREG(EVERGREEN_GRPH_ENABLE + radeon_crtc->crtc_offset, 1); 810 811 OUTREG(EVERGREEN_DESKTOP_HEIGHT + radeon_crtc->crtc_offset, mode->VDisplay); 812 x &= ~3; 813 y &= ~1; 814 OUTREG(EVERGREEN_VIEWPORT_START + radeon_crtc->crtc_offset, (x << 16) | y); 815 OUTREG(EVERGREEN_VIEWPORT_SIZE + radeon_crtc->crtc_offset, (mode->HDisplay << 16) | mode->VDisplay); 816 817 if (adjusted_mode->Flags & V_INTERLACE) 818 OUTREG(EVERGREEN_DATA_FORMAT + radeon_crtc->crtc_offset, EVERGREEN_INTERLEAVE_EN); 819 else 820 OUTREG(EVERGREEN_DATA_FORMAT + radeon_crtc->crtc_offset, 0); 821 822} 823 824static void avivo_set_base_format(xf86CrtcPtr crtc, 825 DisplayModePtr mode, 826 DisplayModePtr adjusted_mode, 827 int x, int y) 828{ 829 ScrnInfoPtr pScrn = crtc->scrn; 830 RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; 831 RADEONInfoPtr info = RADEONPTR(pScrn); 832 unsigned char *RADEONMMIO = info->MMIO; 833 uint64_t fb_location = crtc->scrn->fbOffset + info->fbLocation; 834 uint32_t fb_format; 835#if X_BYTE_ORDER == X_BIG_ENDIAN 836 uint32_t fb_swap = R600_D1GRPH_SWAP_ENDIAN_NONE; 837#endif 838 839 switch (crtc->scrn->bitsPerPixel) { 840 case 15: 841 fb_format = AVIVO_D1GRPH_CONTROL_DEPTH_16BPP | AVIVO_D1GRPH_CONTROL_16BPP_ARGB1555; 842 break; 843 case 16: 844 fb_format = AVIVO_D1GRPH_CONTROL_DEPTH_16BPP | AVIVO_D1GRPH_CONTROL_16BPP_RGB565; 845#if X_BYTE_ORDER == X_BIG_ENDIAN 846 fb_swap = R600_D1GRPH_SWAP_ENDIAN_16BIT; 847#endif 848 break; 849 case 24: 850 case 32: 851 fb_format = AVIVO_D1GRPH_CONTROL_DEPTH_32BPP | AVIVO_D1GRPH_CONTROL_32BPP_ARGB8888; 852#if X_BYTE_ORDER == X_BIG_ENDIAN 853 fb_swap = R600_D1GRPH_SWAP_ENDIAN_32BIT; 854#endif 855 break; 856 default: 857 FatalError("Unsupported screen depth: %d\n", xf86GetDepth()); 858 } 859 860 if (info->tilingEnabled && (crtc->rotatedData == NULL)) { 861 fb_format |= AVIVO_D1GRPH_MACRO_ADDRESS_MODE; 862 } 863 864 if (radeon_crtc->crtc_id == 0) 865 OUTREG(AVIVO_D1VGA_CONTROL, 0); 866 else 867 OUTREG(AVIVO_D2VGA_CONTROL, 0); 868 869 /* setup fb format and location 870 */ 871 if (crtc->rotatedData != NULL) { 872 /* x/y offset is already included */ 873 x = 0; 874 y = 0; 875 fb_location = fb_location + (char *)crtc->rotatedData - (char *)info->FB; 876 } 877 878 if (info->ChipFamily >= CHIP_FAMILY_RV770) { 879 if (radeon_crtc->crtc_id) { 880 OUTREG(R700_D2GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, (fb_location >> 32) & 0xf); 881 OUTREG(R700_D2GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, (fb_location >> 32) & 0xf); 882 } else { 883 OUTREG(R700_D1GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, (fb_location >> 32) & 0xf); 884 OUTREG(R700_D1GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, (fb_location >> 32) & 0xf); 885 } 886 } 887 OUTREG(AVIVO_D1GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset, 888 fb_location & 0xffffffff); 889 OUTREG(AVIVO_D1GRPH_SECONDARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset, 890 fb_location & 0xffffffff); 891 OUTREG(AVIVO_D1GRPH_CONTROL + radeon_crtc->crtc_offset, fb_format); 892 893#if X_BYTE_ORDER == X_BIG_ENDIAN 894 if (info->ChipFamily >= CHIP_FAMILY_R600) 895 OUTREG(R600_D1GRPH_SWAP_CONTROL + radeon_crtc->crtc_offset, fb_swap); 896#endif 897 898 OUTREG(AVIVO_D1GRPH_SURFACE_OFFSET_X + radeon_crtc->crtc_offset, 0); 899 OUTREG(AVIVO_D1GRPH_SURFACE_OFFSET_Y + radeon_crtc->crtc_offset, 0); 900 OUTREG(AVIVO_D1GRPH_X_START + radeon_crtc->crtc_offset, 0); 901 OUTREG(AVIVO_D1GRPH_Y_START + radeon_crtc->crtc_offset, 0); 902 OUTREG(AVIVO_D1GRPH_X_END + radeon_crtc->crtc_offset, info->virtualX); 903 OUTREG(AVIVO_D1GRPH_Y_END + radeon_crtc->crtc_offset, info->virtualY); 904 OUTREG(AVIVO_D1GRPH_PITCH + radeon_crtc->crtc_offset, 905 crtc->scrn->displayWidth); 906 OUTREG(AVIVO_D1GRPH_ENABLE + radeon_crtc->crtc_offset, 1); 907 908 OUTREG(AVIVO_D1MODE_DESKTOP_HEIGHT + radeon_crtc->crtc_offset, mode->VDisplay); 909 x &= ~3; 910 y &= ~1; 911 OUTREG(AVIVO_D1MODE_VIEWPORT_START + radeon_crtc->crtc_offset, (x << 16) | y); 912 OUTREG(AVIVO_D1MODE_VIEWPORT_SIZE + radeon_crtc->crtc_offset, 913 (mode->HDisplay << 16) | mode->VDisplay); 914 915 if (mode->Flags & V_INTERLACE) 916 OUTREG(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset, 917 AVIVO_D1MODE_INTERLEAVE_EN); 918 else 919 OUTREG(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset, 0); 920} 921 922static void legacy_set_base_format(xf86CrtcPtr crtc, 923 DisplayModePtr mode, 924 DisplayModePtr adjusted_mode, 925 int x, int y) 926{ 927 ScrnInfoPtr pScrn = crtc->scrn; 928 RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; 929 RADEONInfoPtr info = RADEONPTR(pScrn); 930 unsigned char *RADEONMMIO = info->MMIO; 931 int format = 0; 932 uint32_t crtc_gen_cntl, crtc2_gen_cntl, crtc_pitch; 933 934 RADEONInitCommonRegisters(info->ModeReg, info); 935 RADEONInitSurfaceCntl(crtc, info->ModeReg); 936 RADEONRestoreCommonRegisters(pScrn, info->ModeReg); 937 938 switch (info->CurrentLayout.pixel_code) { 939 case 4: format = 1; break; 940 case 8: format = 2; break; 941 case 15: format = 3; break; /* 555 */ 942 case 16: format = 4; break; /* 565 */ 943 case 24: format = 5; break; /* RGB */ 944 case 32: format = 6; break; /* xRGB */ 945 default: 946 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 947 "Unsupported pixel depth (%d)\n", 948 info->CurrentLayout.bitsPerPixel); 949 } 950 951 crtc_pitch = (((pScrn->displayWidth * pScrn->bitsPerPixel) + 952 ((pScrn->bitsPerPixel * 8) -1)) / 953 (pScrn->bitsPerPixel * 8)); 954 crtc_pitch |= crtc_pitch << 16; 955 956 switch (radeon_crtc->crtc_id) { 957 case 0: 958 crtc_gen_cntl = INREG(RADEON_CRTC_GEN_CNTL) & 0xfffff0ff; 959 crtc_gen_cntl |= (format << 8); 960 OUTREG(RADEON_CRTC_GEN_CNTL, crtc_gen_cntl); 961 OUTREG(RADEON_CRTC_PITCH, crtc_pitch); 962 RADEONInitCrtcBase(crtc, info->ModeReg, x, y); 963 RADEONRestoreCrtcBase(pScrn, info->ModeReg); 964 break; 965 case 1: 966 crtc2_gen_cntl = INREG(RADEON_CRTC2_GEN_CNTL) & 0xfffff0ff; 967 crtc2_gen_cntl |= (format << 8); 968 OUTREG(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); 969 OUTREG(RADEON_CRTC2_PITCH, crtc_pitch); 970 RADEONInitCrtc2Base(crtc, info->ModeReg, x, y); 971 RADEONRestoreCrtc2Base(pScrn, info->ModeReg); 972 OUTREG(RADEON_FP_H2_SYNC_STRT_WID, INREG(RADEON_CRTC2_H_SYNC_STRT_WID)); 973 OUTREG(RADEON_FP_V2_SYNC_STRT_WID, INREG(RADEON_CRTC2_V_SYNC_STRT_WID)); 974 break; 975 } 976} 977 978void 979atombios_crtc_mode_set(xf86CrtcPtr crtc, 980 DisplayModePtr mode, 981 DisplayModePtr adjusted_mode, 982 int x, int y) 983{ 984 ScrnInfoPtr pScrn = crtc->scrn; 985 RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; 986 RADEONInfoPtr info = RADEONPTR(pScrn); 987 Bool tilingChanged = FALSE; 988 989 if (info->allowColorTiling) { 990 radeon_crtc->can_tile = (mode->Flags & (V_DBLSCAN | V_INTERLACE)) ? FALSE : TRUE; 991 tilingChanged = RADEONSetTiling(pScrn); 992 } 993 994/* ErrorF("Mode %dx%d - %d %d %d\n", adjusted_mode->CrtcHDisplay, adjusted_mode->CrtcVDisplay, 995 adjusted_mode->CrtcHTotal, adjusted_mode->CrtcVTotal, adjusted_mode->Flags); */ 996 997 RADEONInitMemMapRegisters(pScrn, info->ModeReg, info); 998 RADEONRestoreMemMapRegisters(pScrn, info->ModeReg); 999 1000 if (IS_DCE4_VARIANT) 1001 atombios_crtc_set_dcpll(crtc); 1002 atombios_pick_pll(crtc); 1003 atombios_crtc_set_pll(crtc, adjusted_mode); 1004 if (IS_DCE4_VARIANT) 1005 atombios_set_crtc_dtd_timing(crtc, adjusted_mode); 1006 else { 1007 atombios_set_crtc_timing(crtc, adjusted_mode); 1008 if (!IS_AVIVO_VARIANT && (radeon_crtc->crtc_id == 0)) 1009 atombios_set_crtc_dtd_timing(crtc, adjusted_mode); 1010 } 1011 1012 if (IS_DCE4_VARIANT) 1013 evergreen_set_base_format(crtc, mode, adjusted_mode, x, y); 1014 else if (IS_AVIVO_VARIANT) 1015 avivo_set_base_format(crtc, mode, adjusted_mode, x, y); 1016 else 1017 legacy_set_base_format(crtc, mode, adjusted_mode, x, y); 1018 1019 if (info->DispPriority) 1020 RADEONInitDispBandwidth(pScrn); 1021 1022 radeon_crtc->initialized = TRUE; 1023 1024 if (tilingChanged) { 1025 /* need to redraw front buffer, I guess this can be considered a hack ? */ 1026 /* if this is called during ScreenInit() we don't have pScrn->pScreen yet */ 1027 if (pScrn->pScreen) 1028 xf86EnableDisableFBAccess(XF86_ENABLEDISABLEFB_ARG(pScrn), FALSE); 1029 RADEONChangeSurfaces(pScrn); 1030 if (pScrn->pScreen) 1031 xf86EnableDisableFBAccess(XF86_ENABLEDISABLEFB_ARG(pScrn), TRUE); 1032 /* xf86SetRootClip would do, but can't access that here */ 1033 } 1034 1035} 1036 1037/* Calculate display buffer watermark to prevent buffer underflow */ 1038void 1039RADEONInitDispBandwidthAVIVO(ScrnInfoPtr pScrn, 1040 DisplayModePtr mode1, int pixel_bytes1, 1041 DisplayModePtr mode2, int pixel_bytes2) 1042{ 1043 RADEONInfoPtr info = RADEONPTR(pScrn); 1044 RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); 1045 unsigned char *RADEONMMIO = info->MMIO; 1046 1047 uint32_t dc_lb_memory_split; 1048 float available_bandwidth = 0; 1049 float read_delay_latency = 1000; 1050 int i; 1051 Bool sideport = FALSE; 1052 1053 /* 1054 * Set display0/1 priority up in the memory controller for 1055 * modes if the user specifies HIGH for displaypriority 1056 * option. 1057 */ 1058 if (info->DispPriority == 2) { 1059 uint32_t mc_init_misc_lat_timer = 0; 1060 if (info->ChipFamily == CHIP_FAMILY_RV515) 1061 mc_init_misc_lat_timer = INMC(pScrn, RV515_MC_INIT_MISC_LAT_TIMER); 1062 else if ((info->ChipFamily == CHIP_FAMILY_RS690) || 1063 (info->ChipFamily == CHIP_FAMILY_RS740)) 1064 mc_init_misc_lat_timer = INMC(pScrn, RS690_MC_INIT_MISC_LAT_TIMER); 1065 1066 mc_init_misc_lat_timer &= ~(R300_MC_DISP1R_INIT_LAT_MASK << R300_MC_DISP1R_INIT_LAT_SHIFT); 1067 mc_init_misc_lat_timer &= ~(R300_MC_DISP0R_INIT_LAT_MASK << R300_MC_DISP0R_INIT_LAT_SHIFT); 1068 1069 if (pRADEONEnt->pCrtc[1]->enabled) 1070 mc_init_misc_lat_timer |= (1 << R300_MC_DISP1R_INIT_LAT_SHIFT); /* display 1 */ 1071 if (pRADEONEnt->pCrtc[0]->enabled) 1072 mc_init_misc_lat_timer |= (1 << R300_MC_DISP0R_INIT_LAT_SHIFT); /* display 0 */ 1073 1074 if (info->ChipFamily == CHIP_FAMILY_RV515) 1075 OUTMC(pScrn, RV515_MC_INIT_MISC_LAT_TIMER, mc_init_misc_lat_timer); 1076 else if ((info->ChipFamily == CHIP_FAMILY_RS690) || 1077 (info->ChipFamily == CHIP_FAMILY_RS740)) 1078 OUTMC(pScrn, RS690_MC_INIT_MISC_LAT_TIMER, mc_init_misc_lat_timer); 1079 } 1080 1081 /* 1082 * Line Buffer Setup 1083 * There is a single line buffer shared by both display controllers. 1084 * DC_LB_MEMORY_SPLIT controls how that line buffer is shared between the display 1085 * controllers. The paritioning can either be done manually or via one of four 1086 * preset allocations specified in bits 1:0: 1087 * 0 - line buffer is divided in half and shared between each display controller 1088 * 1 - D1 gets 3/4 of the line buffer, D2 gets 1/4 1089 * 2 - D1 gets the whole buffer 1090 * 3 - D1 gets 1/4 of the line buffer, D2 gets 3/4 1091 * Setting bit 2 of DC_LB_MEMORY_SPLIT controls switches to manual allocation mode. 1092 * In manual allocation mode, D1 always starts at 0, D1 end/2 is specified in bits 1093 * 14:4; D2 allocation follows D1. 1094 */ 1095 1096 dc_lb_memory_split = INREG(AVIVO_DC_LB_MEMORY_SPLIT) & ~AVIVO_DC_LB_MEMORY_SPLIT_MASK; 1097 dc_lb_memory_split &= ~AVIVO_DC_LB_MEMORY_SPLIT_SHIFT_MODE; 1098 /* auto */ 1099 if (mode1 && mode2) { 1100 if (mode1->HDisplay > mode2->HDisplay) { 1101 if (mode1->HDisplay > 2560) 1102 dc_lb_memory_split |= AVIVO_DC_LB_MEMORY_SPLIT_D1_3Q_D2_1Q; 1103 else 1104 dc_lb_memory_split |= AVIVO_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF; 1105 } else if (mode2->HDisplay > mode1->HDisplay) { 1106 if (mode2->HDisplay > 2560) 1107 dc_lb_memory_split |= AVIVO_DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q; 1108 else 1109 dc_lb_memory_split |= AVIVO_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF; 1110 } else 1111 dc_lb_memory_split |= AVIVO_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF; 1112 } else if (mode1) { 1113 dc_lb_memory_split |= AVIVO_DC_LB_MEMORY_SPLIT_D1_ONLY; 1114 } else if (mode2) { 1115 dc_lb_memory_split |= AVIVO_DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q; 1116 } 1117 OUTREG(AVIVO_DC_LB_MEMORY_SPLIT, dc_lb_memory_split); 1118#if 0 1119 /* manual */ 1120 dc_lb_memory_split |= AVIVO_DC_LB_MEMORY_SPLIT_SHIFT_MODE; 1121 dc_lb_memory_split &= ~(AVIVO_DC_LB_DISP1_END_ADR_MASK << AVIVO_DC_LB_DISP1_END_ADR_SHIFT); 1122 if (mode1) { 1123 dc_lb_memory_split |= ((((mode1->HDisplay / 2) + 64 /*???*/) & AVIVO_DC_LB_DISP1_END_ADR_MASK) 1124 << AVIVO_DC_LB_DISP1_END_ADR_SHIFT); 1125 } else if (mode2) { 1126 dc_lb_memory_split |= (0 << AVIVO_DC_LB_DISP1_END_ADR_SHIFT); 1127 } 1128 OUTREG(AVIVO_DC_LB_MEMORY_SPLIT, dc_lb_memory_split); 1129#endif 1130 1131 /* fixme 1132 * Still need to implement the actual watermark calculation 1133 * for rs600. This just allows us to force high display 1134 * priority. 1135 */ 1136 if (info->ChipFamily == CHIP_FAMILY_RS600) { 1137 if (info->DispPriority == 2) { 1138 uint32_t priority_cnt; 1139 1140 if (mode1) { 1141 priority_cnt = INREG(AVIVO_D1MODE_PRIORITY_A_CNT); 1142 priority_cnt |= AVIVO_DxMODE_PRIORITY_ALWAYS_ON; 1143 OUTREG(AVIVO_D1MODE_PRIORITY_A_CNT, priority_cnt); 1144 1145 priority_cnt = INREG(AVIVO_D1MODE_PRIORITY_B_CNT); 1146 priority_cnt |= AVIVO_DxMODE_PRIORITY_ALWAYS_ON; 1147 OUTREG(AVIVO_D1MODE_PRIORITY_B_CNT, priority_cnt); 1148 } 1149 1150 if (mode2) { 1151 priority_cnt = INREG(AVIVO_D2MODE_PRIORITY_A_CNT); 1152 priority_cnt |= AVIVO_DxMODE_PRIORITY_ALWAYS_ON; 1153 OUTREG(AVIVO_D2MODE_PRIORITY_A_CNT, priority_cnt); 1154 1155 priority_cnt = INREG(AVIVO_D2MODE_PRIORITY_B_CNT); 1156 priority_cnt |= AVIVO_DxMODE_PRIORITY_ALWAYS_ON; 1157 OUTREG(AVIVO_D2MODE_PRIORITY_B_CNT, priority_cnt); 1158 } 1159 } 1160 return; 1161 } 1162 1163 /* IGP bandwidth - get from integrated systems table 1164 * SYSTEM_MEMORY_BANDWIDTH (Mbyte/s) = SYSTEM_MEMORY_CLOCK (MHz) * (1+DDR) * 8 * EFF * Num of channels 1165 * SIDEPORT_MEMORY_BANDWIDTH = SIDEPORT_MEMORY_CLOCK * 2(byte) * 2(DDR) * 0.7(Eff) 1166 * CORE_CLOCK_BANDWIDTH (Mbyte/s) = SCLK (MHz) * 16 / Dynamic Engine clock Divider 1167 * HT_LINK_BANDWIDTH = HT_LINK_CLOCK * 2 * HT_LINK_WIDTH/8 * HT_LINK_EFF 1168 * system read delay 1169 * READ_DLY_MAX_LATENCY: 5000 ns 1170 * sideport read delay 1171 * READ_DLY_MAX_LATENCY: 370 * MCLK + 800 ns 1172 * MCLK is the sideport memory clock period in ns (MCLK = 1000 / MCLKfreq MHz) 1173 */ 1174 1175 if (info->IsIGP) { 1176 float core_clock_bandwidth = ((float)info->pm.mode[info->pm.current_mode].sclk / 100) * 16 / 1; 1177 1178 if (sideport) { 1179 float sideport_memory_bandwidth = (info->igp_sideport_mclk / 2) * 2 * 2 * 0.7; 1180 float mclk = 1000 / info->igp_sideport_mclk; 1181 read_delay_latency = 370 * mclk * 800; 1182 available_bandwidth = MIN(sideport_memory_bandwidth, core_clock_bandwidth); 1183 } else { 1184 float system_memory_bandwidth = (info->igp_system_mclk / 2) * (1 + 1) * 8 * 0.5 * 1; 1185 float ht_link_bandwidth = info->igp_ht_link_clk * 2 * (info->igp_ht_link_width / 8) * 0.8; 1186 read_delay_latency = 5000; 1187 available_bandwidth = MIN(system_memory_bandwidth, MIN(ht_link_bandwidth, core_clock_bandwidth)); 1188 } 1189 } 1190 1191 /* calculate for each display */ 1192 for (i = 0; i < 2; i++) { 1193 DisplayModePtr current = NULL; 1194 //RADEONCrtcPrivatePtr radeon_crtc = pRADEONEnt->Controller[i]; 1195 float pclk, sclk, sclkfreq = 0; 1196 float consumption_time, consumption_rate; 1197 int num_line_pair, request_fifo_depth, lb_request_fifo_depth; 1198 int max_req; 1199 uint32_t lb_max_req_outstanding, priority_cnt; 1200 float line_time, active_time, chunk_time; 1201 float worst_case_latency, tolerable_latency; 1202 float fill_rate; 1203 int priority_mark_max, priority_mark, priority_mark2; 1204 int width, estimated_width; 1205 /* FIXME: handle the scalers better */ 1206 Bool d1_scale_en = pRADEONEnt->Controller[0]->scaler_enabled; 1207 Bool d2_scale_en = pRADEONEnt->Controller[1]->scaler_enabled; 1208 float vtaps1 = 2; /* XXX */ 1209 float vsc1 = pRADEONEnt->Controller[0]->vsc; 1210 float hsc1 = pRADEONEnt->Controller[0]->hsc; 1211 float vtaps2 = 2; /* XXX */ 1212 float vsc2 = pRADEONEnt->Controller[1]->vsc; 1213 float hsc2 = pRADEONEnt->Controller[1]->hsc; 1214 1215 if (i == 0) 1216 current = mode1; 1217 else 1218 current = mode2; 1219 1220 if (current == NULL) 1221 continue; 1222 1223 /* Determine consumption rate 1224 pclk = pixel clock period(ns) 1225 vtaps = number of vertical taps, 1226 vsc = vertical scaling ratio, defined as source/destination 1227 hsc = horizontal scaling ration, defined as source/destination 1228 */ 1229 1230 pclk = 1000 / ((float)current->Clock / 1000); 1231 1232 if (i == 0) { 1233 if (d1_scale_en) 1234 consumption_time = pclk / ((MAX(vtaps1, vsc1) * hsc1) / vtaps1); 1235 else 1236 consumption_time = pclk; 1237 } else { 1238 if (d2_scale_en) 1239 consumption_time = pclk / ((MAX(vtaps2, vsc2) * hsc2) / vtaps2); 1240 else 1241 consumption_time = pclk; 1242 } 1243 1244 consumption_rate = 1 / consumption_time; 1245 1246 /* Determine request line buffer fifo depth 1247 NumLinePair = Number of line pairs to request(1 = 2 lines, 2 = 4 lines) 1248 LBRequestFifoDepth = Number of chunk requests the LB can put into the request FIFO for a display 1249 width = viewport width in pixels 1250 */ 1251 if (i == 0) { 1252 if (vsc1 > 2) 1253 num_line_pair = 2; 1254 else 1255 num_line_pair = 1; 1256 } else { 1257 if (vsc2 > 2) 1258 num_line_pair = 2; 1259 else 1260 num_line_pair = 1; 1261 } 1262 1263 width = current->CrtcHDisplay; 1264 request_fifo_depth = ceil(width/256) * num_line_pair; 1265 if (request_fifo_depth < 4) 1266 lb_request_fifo_depth = 4; 1267 else 1268 lb_request_fifo_depth = request_fifo_depth; 1269 1270 if (info->IsIGP) { 1271 if ((info->ChipFamily == CHIP_FAMILY_RS690) || 1272 (info->ChipFamily == CHIP_FAMILY_RS740)) 1273 OUTREG(RS690_DCP_CONTROL, 0); 1274 else if ((info->ChipFamily == CHIP_FAMILY_RS780) || 1275 (info->ChipFamily == CHIP_FAMILY_RS880)) 1276 OUTREG(RS690_DCP_CONTROL, 2); 1277 max_req = lb_request_fifo_depth - 1; 1278 } else 1279 max_req = lb_request_fifo_depth; 1280 1281 /*ErrorF("max_req %d: 0x%x\n", i, max_req);*/ 1282 1283 lb_max_req_outstanding = INREG(AVIVO_LB_MAX_REQ_OUTSTANDING); 1284 if (i == 0) { 1285 lb_max_req_outstanding &= ~(AVIVO_LB_D1_MAX_REQ_OUTSTANDING_MASK << AVIVO_LB_D1_MAX_REQ_OUTSTANDING_SHIFT); 1286 lb_max_req_outstanding |= (max_req & AVIVO_LB_D1_MAX_REQ_OUTSTANDING_MASK) << AVIVO_LB_D1_MAX_REQ_OUTSTANDING_SHIFT; 1287 } else { 1288 lb_max_req_outstanding &= ~(AVIVO_LB_D2_MAX_REQ_OUTSTANDING_MASK << AVIVO_LB_D2_MAX_REQ_OUTSTANDING_SHIFT); 1289 lb_max_req_outstanding |= (max_req & AVIVO_LB_D2_MAX_REQ_OUTSTANDING_MASK) << AVIVO_LB_D2_MAX_REQ_OUTSTANDING_SHIFT; 1290 } 1291 OUTREG(AVIVO_LB_MAX_REQ_OUTSTANDING, lb_max_req_outstanding); 1292 1293 /* Determine line time 1294 LineTime = total time for one line of displayhtotal = total number of horizontal pixels 1295 pclk = pixel clock period(ns) 1296 */ 1297 line_time = current->CrtcHTotal * pclk; 1298 1299 /* Determine active time 1300 ActiveTime = time of active region of display within one line, 1301 hactive = total number of horizontal active pixels 1302 htotal = total number of horizontal pixels 1303 */ 1304 active_time = line_time * current->CrtcHDisplay / current->CrtcHTotal; 1305 1306 /* Determine chunk time 1307 ChunkTime = the time it takes the DCP to send one chunk of data 1308 to the LB which consists of pipeline delay and inter chunk gap 1309 sclk = system clock(ns) 1310 */ 1311 if (info->IsIGP) { 1312 sclk = 1000 / (available_bandwidth / 16); 1313 /* Sclkfreq = sclk in MHz = 1000/sclk (because sclk is in ns). */ 1314 sclkfreq = 1000 / sclk; 1315 chunk_time = sclk * 256 * 1.3; 1316 } else { 1317 sclk = 1000 / ((float)info->pm.mode[info->pm.current_mode].sclk / 100); 1318 chunk_time = sclk * 600; 1319 } 1320 1321 /* Determine the worst case latency 1322 NumLinePair = Number of line pairs to request(1 = 2 lines, 2 = 4 lines) 1323 WorstCaseLatency = The worst case time from urgent to when the MC starts 1324 to return data 1325 READ_DELAY_IDLE_MAX = constant of 1us 1326 ChunkTime = the time it takes the DCP to send one chunk of data to the LB 1327 which consists of pipeline delay and 1328 inter chunk gap 1329 */ 1330 if (info->IsIGP) { 1331 if (num_line_pair > 1) 1332 worst_case_latency = read_delay_latency + 3 * chunk_time; 1333 else 1334 worst_case_latency = read_delay_latency + 2 * chunk_time; 1335 } else { 1336 if (num_line_pair > 1) 1337 worst_case_latency = read_delay_latency + 3 * chunk_time; 1338 else 1339 worst_case_latency = read_delay_latency + chunk_time; 1340 } 1341 1342 /* Determine the tolerable latency 1343 TolerableLatency = Any given request has only 1 line time for the data to be returned 1344 LBRequestFifoDepth = Number of chunk requests the LB can put into the request FIFO for a display 1345 LineTime = total time for one line of display 1346 ChunkTime = the time it takes the DCP to send one chunk of data to the LB which consists of 1347 pipeline delay and inter chunk gap 1348 */ 1349 if ((2 + lb_request_fifo_depth) >= request_fifo_depth) 1350 tolerable_latency = line_time; 1351 else 1352 tolerable_latency = line_time - (request_fifo_depth - lb_request_fifo_depth - 2) * chunk_time; 1353 1354 if (mode1 && mode2) { 1355 int d1bpp, d2bpp; 1356 int d1_graph_enable = 1; 1357 int d2_graph_enable = 1; 1358 int d1_ovl_enable = 0; 1359 int d2_ovl_enable = 0; 1360 int d1grph_depth, d2grph_depth; 1361 int d1ovl_depth = 0; 1362 int d2ovl_depth = 0; 1363 int d1_num_line_pair, d2_num_line_pair; 1364 float d1_fill_rate_coeff, d2_fill_rate_coeff; 1365 1366 switch (pixel_bytes1) { 1367 case 2: 1368 d1grph_depth = 1; 1369 break; 1370 case 4: 1371 d1grph_depth = 2; 1372 break; 1373 default: 1374 d1grph_depth = 0; 1375 break; 1376 } 1377 1378 switch (pixel_bytes2) { 1379 case 2: 1380 d2grph_depth = 1; 1381 break; 1382 case 4: 1383 d2grph_depth = 2; 1384 break; 1385 default: 1386 d2grph_depth = 0; 1387 break; 1388 } 1389 1390 /* If both displays are active, determine line buffer fill rate */ 1391 if (d1_scale_en && (vsc1 > 2)) 1392 d1_num_line_pair = 2; 1393 else 1394 d1_num_line_pair = 1; 1395 1396 if (d2_scale_en && (vsc2 > 2)) 1397 d2_num_line_pair = 2; 1398 else 1399 d2_num_line_pair = 1; 1400 1401 if (info->IsIGP) { 1402 d1bpp = (d1_graph_enable * pow(2, d1grph_depth) * 8) + (d1_ovl_enable * pow(2, d1ovl_depth) * 8); 1403 d2bpp = (d2_graph_enable * pow(2, d2grph_depth) * 8) + (d2_ovl_enable * pow(2, d2ovl_depth) * 8); 1404 1405 if (d1bpp > 64) 1406 d1_fill_rate_coeff = d1bpp * d1_num_line_pair; 1407 else 1408 d1_fill_rate_coeff = d1_num_line_pair; 1409 1410 if (d2bpp > 64) 1411 d2_fill_rate_coeff = d2bpp * d2_num_line_pair; 1412 else 1413 d2_fill_rate_coeff = d2_num_line_pair; 1414 1415 fill_rate = sclkfreq / (d1_fill_rate_coeff + d2_fill_rate_coeff); 1416 } else { 1417 d1bpp = (d1grph_depth + d1ovl_depth) * 16; 1418 d2bpp = (d2grph_depth + d2ovl_depth) * 16; 1419 1420 if (d1bpp > 64) 1421 d1_fill_rate_coeff = d1bpp / d1_num_line_pair; 1422 else 1423 d1_fill_rate_coeff = d1_num_line_pair; 1424 1425 if (d2bpp > 64) 1426 d2_fill_rate_coeff = d2bpp / d2_num_line_pair; 1427 else 1428 d2_fill_rate_coeff = d2_num_line_pair; 1429 1430 fill_rate = sclk / (d1_fill_rate_coeff + d2_fill_rate_coeff); 1431 1432 /* Convert line buffer fill rate from period to frequency */ 1433 fill_rate = 1 / fill_rate; 1434 } 1435 } else { 1436 int dxbpp; 1437 int dx_grph_enable = 1; 1438 int dx_ovl_enable = 0; 1439 int dxgrph_depth; 1440 int dxovl_depth = 0; 1441 int cpp; 1442 1443 if (i == 0) 1444 cpp = pixel_bytes1; 1445 else 1446 cpp = pixel_bytes2; 1447 1448 switch (cpp) { 1449 case 2: 1450 dxgrph_depth = 1; 1451 break; 1452 case 4: 1453 dxgrph_depth = 2; 1454 break; 1455 default: 1456 dxgrph_depth = 0; 1457 break; 1458 } 1459 1460 /* If only one display active, the line buffer fill rate becomes */ 1461 if (info->IsIGP) { 1462 dxbpp = (dx_grph_enable * pow(2, dxgrph_depth) * 8) + (dx_ovl_enable * pow(2, dxovl_depth) * 8); 1463 if (dxbpp > 64) 1464 fill_rate = sclkfreq / dxbpp / num_line_pair; 1465 else 1466 fill_rate = sclkfreq / num_line_pair; 1467 } else { 1468 dxbpp = (dxgrph_depth + dxovl_depth) * 16; 1469 1470 if (dxbpp > 64) 1471 fill_rate = sclk / dxbpp / num_line_pair; 1472 else 1473 fill_rate = sclk / num_line_pair; 1474 1475 /* Convert line buffer fill rate from period to frequency */ 1476 fill_rate = 1 / fill_rate; 1477 } 1478 } 1479 1480 /* Determine the maximum priority mark 1481 width = viewport width in pixels 1482 */ 1483 priority_mark_max = ceil(width/16); 1484 1485 /* Determine estimated width */ 1486 estimated_width = (tolerable_latency - worst_case_latency) / consumption_time; 1487 1488 /* Determine priority mark based on active time */ 1489 if (info->IsIGP) { 1490 if (estimated_width > width) 1491 priority_mark = 10; 1492 else 1493 priority_mark = priority_mark_max - ceil(estimated_width / 16); 1494 } else { 1495 if (estimated_width > width) 1496 priority_mark = priority_mark_max; 1497 else 1498 priority_mark = priority_mark_max - ceil(estimated_width / 16); 1499 } 1500 1501 /* Determine priority mark 2 based on worst case latency, 1502 consumption rate, fill rate and active time 1503 */ 1504 if (info->IsIGP) { 1505 if (consumption_rate > fill_rate) 1506 priority_mark2 = ceil((worst_case_latency * consumption_rate + (consumption_rate - fill_rate) * active_time) / 1000 / 16); 1507 else 1508 priority_mark2 = ceil(worst_case_latency * consumption_rate / 1000 / 16); 1509 } else { 1510 if (consumption_rate > fill_rate) 1511 priority_mark2 = ceil(worst_case_latency * consumption_rate + (consumption_rate - fill_rate) * active_time / 16); 1512 else 1513 priority_mark2 = ceil(worst_case_latency * consumption_rate / 16); 1514 } 1515 1516 /* Determine final priority mark and clamp if necessary */ 1517 priority_mark = max(priority_mark, priority_mark2); 1518 if (priority_mark < 0) 1519 priority_mark = 0; 1520 else if (priority_mark > priority_mark_max) 1521 priority_mark = priority_mark_max; 1522 1523 priority_cnt = priority_mark & AVIVO_DxMODE_PRIORITY_MARK_MASK; 1524 1525 if (info->DispPriority == 2) 1526 priority_cnt |= AVIVO_DxMODE_PRIORITY_ALWAYS_ON; 1527 1528 /*ErrorF("priority_mark %d: 0x%x\n", i, priority_mark);*/ 1529 1530 /* Determine which display to program priority mark for */ 1531 /* FIXME: program DxMODE_PRIORITY_B_CNT for slower sclk */ 1532 if (i == 0) { 1533 OUTREG(AVIVO_D1MODE_PRIORITY_A_CNT, priority_cnt); 1534 OUTREG(AVIVO_D1MODE_PRIORITY_B_CNT, priority_cnt); 1535 } else { 1536 OUTREG(AVIVO_D2MODE_PRIORITY_A_CNT, priority_cnt); 1537 OUTREG(AVIVO_D2MODE_PRIORITY_B_CNT, priority_cnt); 1538 } 1539 } 1540 1541} 1542