Home | History | Annotate | Line # | Download | only in src
      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 (at) redhat.com>
     26  *    Alex Deucher <alexander.deucher (at) 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 
     55 extern int
     56 atombios_get_encoder_mode(xf86OutputPtr output);
     57 
     58 extern void
     59 RADEONInitCrtcBase(xf86CrtcPtr crtc, RADEONSavePtr save,
     60 		   int x, int y);
     61 extern void
     62 RADEONInitCrtc2Base(xf86CrtcPtr crtc, RADEONSavePtr save,
     63 		    int x, int y);
     64 extern void
     65 RADEONRestoreCrtcBase(ScrnInfoPtr pScrn,
     66 		      RADEONSavePtr restore);
     67 extern void
     68 RADEONRestoreCrtc2Base(ScrnInfoPtr pScrn,
     69 		       RADEONSavePtr restore);
     70 extern void
     71 RADEONInitCommonRegisters(RADEONSavePtr save, RADEONInfoPtr info);
     72 extern void
     73 RADEONInitSurfaceCntl(xf86CrtcPtr crtc, RADEONSavePtr save);
     74 
     75 AtomBiosResult
     76 atombios_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 
     98 static AtomBiosResult
     99 atombios_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 
    121 static AtomBiosResult
    122 atombios_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 
    144 static AtomBiosResult
    145 atombios_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 
    168 void
    169 atombios_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 
    191 static AtomBiosResult
    192 atombios_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(&param, 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 = &param;
    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 
    242 static AtomBiosResult
    243 atombios_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(&param, 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 = &param;
    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 
    293 static void
    294 atombios_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 
    350 union adjust_pixel_clock {
    351 	ADJUST_DISPLAY_PLL_PS_ALLOCATION v1;
    352 	ADJUST_DISPLAY_PLL_PS_ALLOCATION_V3 v3;
    353 };
    354 
    355 static 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     }
    495 out:
    496     *pll_flags_p = pll_flags;
    497     return adjusted_clock;
    498 }
    499 
    500 union 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 
    508 static void
    509 atombios_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 
    579 static void
    580 atombios_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 
    721 static 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 
    824 static 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 
    922 static 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 
    978 void
    979 atombios_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 */
   1038 void
   1039 RADEONInitDispBandwidthAVIVO(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