Home | History | Annotate | Line # | Download | only in src
      1 /*
      2  * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and
      3  *                VA Linux Systems Inc., Fremont, California.
      4  *
      5  * All Rights Reserved.
      6  *
      7  * Permission is hereby granted, free of charge, to any person obtaining
      8  * a copy of this software and associated documentation files (the
      9  * "Software"), to deal in the Software without restriction, including
     10  * without limitation on the rights to use, copy, modify, merge,
     11  * publish, distribute, sublicense, and/or sell copies of the Software,
     12  * and to permit persons to whom the Software is furnished to do so,
     13  * subject to the following conditions:
     14  *
     15  * The above copyright notice and this permission notice (including the
     16  * next paragraph) shall be included in all copies or substantial
     17  * portions of the Software.
     18  *
     19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     20  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     21  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
     22  * NON-INFRINGEMENT.  IN NO EVENT SHALL ATI, VA LINUX SYSTEMS AND/OR
     23  * THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
     24  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     25  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     26  * DEALINGS IN THE SOFTWARE.
     27  */
     28 
     29 #ifdef HAVE_CONFIG_H
     30 #include "config.h"
     31 #endif
     32 
     33 #include <string.h>
     34 #include <stdio.h>
     35 #include <assert.h>
     36 #include <math.h>
     37 
     38 /* X and server generic header files */
     39 #include "xf86.h"
     40 #include "xf86_OSproc.h"
     41 #include "vgaHW.h"
     42 #include "xf86Modes.h"
     43 
     44 /* Driver data structures */
     45 #include "radeon.h"
     46 #include "radeon_reg.h"
     47 #include "radeon_macros.h"
     48 #include "radeon_probe.h"
     49 #include "radeon_version.h"
     50 
     51 #ifdef XF86DRI
     52 #define _XF86DRI_SERVER_
     53 #include "radeon_drm.h"
     54 #include "sarea.h"
     55 #endif
     56 
     57 extern void atombios_crtc_mode_set(xf86CrtcPtr crtc,
     58 				   DisplayModePtr mode,
     59 				   DisplayModePtr adjusted_mode,
     60 				   int x, int y);
     61 extern void atombios_crtc_dpms(xf86CrtcPtr crtc, int mode);
     62 extern void
     63 RADEONInitDispBandwidthLegacy(ScrnInfoPtr pScrn,
     64 			      DisplayModePtr mode1, int pixel_bytes1,
     65 			      DisplayModePtr mode2, int pixel_bytes2);
     66 extern void
     67 RADEONInitDispBandwidthAVIVO(ScrnInfoPtr pScrn,
     68 			     DisplayModePtr mode1, int pixel_bytes1,
     69 			     DisplayModePtr mode2, int pixel_bytes2);
     70 
     71 void
     72 radeon_do_crtc_dpms(xf86CrtcPtr crtc, int mode)
     73 {
     74     RADEONInfoPtr info = RADEONPTR(crtc->scrn);
     75     RADEONEntPtr pRADEONEnt = RADEONEntPriv(crtc->scrn);
     76     xf86CrtcPtr crtc0 = pRADEONEnt->pCrtc[0];
     77     RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
     78 
     79     if (IS_AVIVO_VARIANT || info->r4xx_atom) {
     80 	atombios_crtc_dpms(crtc, mode);
     81     } else {
     82 
     83 	/* need to restore crtc1 before crtc0 or we may get a blank screen
     84 	 * in some cases
     85 	 */
     86 	if ((radeon_crtc->crtc_id == 1) && (mode == DPMSModeOn)) {
     87 	    if (crtc0->enabled)
     88 		legacy_crtc_dpms(crtc0,  DPMSModeOff);
     89 	}
     90 
     91 	legacy_crtc_dpms(crtc, mode);
     92 
     93 	if ((radeon_crtc->crtc_id == 1) && (mode == DPMSModeOn)) {
     94 	    if (crtc0->enabled)
     95 		legacy_crtc_dpms(crtc0, mode);
     96 	}
     97     }
     98 }
     99 
    100 void
    101 radeon_crtc_dpms(xf86CrtcPtr crtc, int mode)
    102 {
    103     RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
    104 
    105     if ((mode == DPMSModeOn) && radeon_crtc->enabled)
    106 	return;
    107 
    108     if (mode == DPMSModeOff)
    109 	radeon_crtc_modeset_ioctl(crtc, FALSE);
    110 
    111     radeon_do_crtc_dpms(crtc, mode);
    112 
    113     if (mode != DPMSModeOff) {
    114 	radeon_crtc_modeset_ioctl(crtc, TRUE);
    115 	radeon_crtc_load_lut(crtc);
    116     }
    117 
    118     if (mode == DPMSModeOn)
    119 	radeon_crtc->enabled = TRUE;
    120     else
    121 	radeon_crtc->enabled = FALSE;
    122 }
    123 
    124 static Bool
    125 radeon_crtc_mode_fixup(xf86CrtcPtr crtc, DisplayModePtr mode,
    126 		     DisplayModePtr adjusted_mode)
    127 {
    128     return TRUE;
    129 }
    130 
    131 static void
    132 radeon_crtc_mode_prepare(xf86CrtcPtr crtc)
    133 {
    134     RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
    135 
    136     if (radeon_crtc->enabled)
    137 	crtc->funcs->hide_cursor(crtc);
    138 }
    139 
    140 static uint32_t RADEONDiv(CARD64 n, uint32_t d)
    141 {
    142     return (n + (d / 2)) / d;
    143 }
    144 
    145 static void
    146 RADEONComputePLL_old(RADEONPLLPtr pll,
    147 		     unsigned long freq,
    148 		     uint32_t *chosen_dot_clock_freq,
    149 		     uint32_t *chosen_feedback_div,
    150 		     uint32_t *chosen_frac_feedback_div,
    151 		     uint32_t *chosen_reference_div,
    152 		     uint32_t *chosen_post_div,
    153 		     int flags)
    154 {
    155     uint32_t min_ref_div = pll->min_ref_div;
    156     uint32_t max_ref_div = pll->max_ref_div;
    157     uint32_t min_post_div = pll->min_post_div;
    158     uint32_t max_post_div = pll->max_post_div;
    159     uint32_t min_fractional_feed_div = 0;
    160     uint32_t max_fractional_feed_div = 0;
    161     uint32_t best_vco = pll->best_vco;
    162     uint32_t best_post_div = 1;
    163     uint32_t best_ref_div = 1;
    164     uint32_t best_feedback_div = 1;
    165     uint32_t best_frac_feedback_div = 0;
    166     uint32_t best_freq = -1;
    167     uint32_t best_error = 0xffffffff;
    168     uint32_t best_vco_diff = 1;
    169     uint32_t post_div;
    170 
    171     freq = freq * 1000;
    172 
    173 /*    ErrorF("freq: %lu\n", freq); */
    174 
    175     if (flags & RADEON_PLL_USE_REF_DIV)
    176 	min_ref_div = max_ref_div = pll->reference_div;
    177     else {
    178 	while (min_ref_div < max_ref_div-1) {
    179 	    uint32_t mid=(min_ref_div+max_ref_div)/2;
    180 	    uint32_t pll_in = pll->reference_freq / mid;
    181 	    if (pll_in < pll->pll_in_min)
    182 		max_ref_div = mid;
    183 	    else if (pll_in > pll->pll_in_max)
    184 		min_ref_div = mid;
    185 	    else break;
    186 	}
    187     }
    188 
    189     if (flags & RADEON_PLL_USE_POST_DIV)
    190 	min_post_div = max_post_div = pll->post_div;
    191 
    192     if (flags & RADEON_PLL_USE_FRAC_FB_DIV) {
    193 	min_fractional_feed_div = pll->min_frac_feedback_div;
    194 	max_fractional_feed_div = pll->max_frac_feedback_div;
    195     }
    196 
    197     for (post_div = min_post_div; post_div <= max_post_div; ++post_div) {
    198 	uint32_t ref_div;
    199 
    200 	if ((flags & RADEON_PLL_NO_ODD_POST_DIV) && (post_div & 1))
    201 	    continue;
    202 
    203 	/* legacy radeons only have a few post_divs */
    204 	if (flags & RADEON_PLL_LEGACY) {
    205 	    if ((post_div == 5) ||
    206 		(post_div == 7) ||
    207 		(post_div == 9) ||
    208 		(post_div == 10) ||
    209 		(post_div == 11))
    210 		continue;
    211 	}
    212 
    213 	for (ref_div = min_ref_div; ref_div <= max_ref_div; ++ref_div) {
    214 	    uint32_t feedback_div, current_freq = 0, error, vco_diff;
    215 	    uint32_t pll_in = pll->reference_freq / ref_div;
    216 	    uint32_t min_feed_div = pll->min_feedback_div;
    217 	    uint32_t max_feed_div = pll->max_feedback_div+1;
    218 
    219 	    if (pll_in < pll->pll_in_min || pll_in > pll->pll_in_max)
    220 		continue;
    221 
    222 	    while (min_feed_div < max_feed_div) {
    223 		uint32_t vco;
    224 		uint32_t min_frac_feed_div = min_fractional_feed_div;
    225 		uint32_t max_frac_feed_div = max_fractional_feed_div+1;
    226 		uint32_t frac_feedback_div;
    227 		CARD64 tmp;
    228 
    229 		feedback_div = (min_feed_div+max_feed_div)/2;
    230 
    231 		tmp = (CARD64)pll->reference_freq * feedback_div;
    232 		vco = RADEONDiv(tmp, ref_div);
    233 
    234 		if (vco < pll->pll_out_min) {
    235 		    min_feed_div = feedback_div+1;
    236 		    continue;
    237 		} else if(vco > pll->pll_out_max) {
    238 		    max_feed_div = feedback_div;
    239 		    continue;
    240 		}
    241 
    242 		while (min_frac_feed_div < max_frac_feed_div) {
    243 		    frac_feedback_div = (min_frac_feed_div+max_frac_feed_div)/2;
    244 		    tmp = (CARD64)pll->reference_freq * 10000 * feedback_div;
    245 		    tmp += (CARD64)pll->reference_freq * 1000 * frac_feedback_div;
    246 		    current_freq = RADEONDiv(tmp, ref_div * post_div);
    247 
    248 #define RD_ABS(a, b) ((a) > (b) ? (a) - (b) : (b) - (a))
    249 		    if (flags & RADEON_PLL_PREFER_CLOSEST_LOWER) {
    250 			error = freq - current_freq;
    251 			error = (int32_t)error < 0 ? 0xffffffff : error;
    252 		    } else
    253 			error = RD_ABS(current_freq, freq);
    254 		    vco_diff = RD_ABS(vco, best_vco);
    255 
    256 		    if ((best_vco == 0 && error < best_error) ||
    257 			(best_vco != 0 &&
    258 			 (error < best_error - 100 ||
    259 			  (RD_ABS(error, best_error) < 100 && vco_diff < best_vco_diff )))) {
    260 			best_post_div = post_div;
    261 			best_ref_div = ref_div;
    262 			best_feedback_div = feedback_div;
    263 			best_frac_feedback_div = frac_feedback_div;
    264 			best_freq = current_freq;
    265 			best_error = error;
    266 			best_vco_diff = vco_diff;
    267 		    } else if (current_freq == freq) {
    268 			if (best_freq == -1) {
    269 			    best_post_div = post_div;
    270 			    best_ref_div = ref_div;
    271 			    best_feedback_div = feedback_div;
    272 			    best_frac_feedback_div = frac_feedback_div;
    273 			    best_freq = current_freq;
    274 			    best_error = error;
    275 			    best_vco_diff = vco_diff;
    276 			} else if (((flags & RADEON_PLL_PREFER_LOW_REF_DIV) && (ref_div < best_ref_div)) ||
    277 				   ((flags & RADEON_PLL_PREFER_HIGH_REF_DIV) && (ref_div > best_ref_div)) ||
    278 				   ((flags & RADEON_PLL_PREFER_LOW_FB_DIV) && (feedback_div < best_feedback_div)) ||
    279 				   ((flags & RADEON_PLL_PREFER_HIGH_FB_DIV) && (feedback_div > best_feedback_div)) ||
    280 				   ((flags & RADEON_PLL_PREFER_LOW_POST_DIV) && (post_div < best_post_div)) ||
    281 				   ((flags & RADEON_PLL_PREFER_HIGH_POST_DIV) && (post_div > best_post_div))) {
    282 			    best_post_div = post_div;
    283 			    best_ref_div = ref_div;
    284 			    best_feedback_div = feedback_div;
    285 			    best_frac_feedback_div = frac_feedback_div;
    286 			    best_freq = current_freq;
    287 			    best_error = error;
    288 			    best_vco_diff = vco_diff;
    289 			}
    290 		    }
    291 		    if (current_freq < freq)
    292 			min_frac_feed_div = frac_feedback_div+1;
    293 		    else
    294 			max_frac_feed_div = frac_feedback_div;
    295 		}
    296 		if (current_freq < freq)
    297 		    min_feed_div = feedback_div+1;
    298 		else
    299 		    max_feed_div = feedback_div;
    300 	    }
    301 	}
    302     }
    303 
    304 /*
    305     ErrorF("best_freq: %u\n", (unsigned int)best_freq);
    306     ErrorF("best_feedback_div: %u\n", (unsigned int)best_feedback_div);
    307     ErrorF("best_frac_feedback_div: %u\n", (unsigned int)best_frac_feedback_div);
    308     ErrorF("best_ref_div: %u\n", (unsigned int)best_ref_div);
    309     ErrorF("best_post_div: %u\n", (unsigned int)best_post_div);
    310 */
    311 
    312     if (best_freq == -1)
    313 	FatalError("Couldn't find valid PLL dividers\n");
    314     *chosen_dot_clock_freq = best_freq / 10000;
    315     *chosen_feedback_div = best_feedback_div;
    316     *chosen_frac_feedback_div = best_frac_feedback_div;
    317     *chosen_reference_div = best_ref_div;
    318     *chosen_post_div = best_post_div;
    319 
    320 }
    321 
    322 static Bool
    323 calc_fb_div(RADEONPLLPtr pll,
    324             unsigned long freq,
    325             int flags,
    326             int post_div,
    327 	    int ref_div,
    328             int *fb_div,
    329             int *fb_div_frac)
    330 {
    331     float ffreq = freq / 10;
    332     float vco_freq = ffreq * post_div;
    333     float feedback_divider = vco_freq * ref_div / pll->reference_freq;
    334 
    335     if (flags & RADEON_PLL_USE_FRAC_FB_DIV) {
    336         feedback_divider = floor((feedback_divider * 10.0) + 0.5) * 0.1;
    337 
    338 	*fb_div = floor(feedback_divider);
    339         *fb_div_frac = fmod(feedback_divider, 1.0) * 10.0;
    340 
    341     } else {
    342         *fb_div = floor(feedback_divider + 0.5);
    343         *fb_div_frac = 0;
    344     }
    345     if ((*fb_div < pll->min_feedback_div) || (*fb_div > pll->max_feedback_div))
    346         return FALSE;
    347     else
    348         return TRUE;
    349 }
    350 
    351 static Bool
    352 calc_fb_ref_div(RADEONPLLPtr pll,
    353                 unsigned long freq,
    354                 int flags,
    355                 int post_div,
    356                 int *fb_div,
    357                 int *fb_div_frac,
    358                 int *ref_div)
    359 {
    360     float ffreq = freq / 10;
    361     float max_error = ffreq * 0.0025;
    362     float vco, error, pll_out;
    363 
    364     for ((*ref_div) = pll->min_ref_div; (*ref_div) < pll->max_ref_div; ++(*ref_div)) {
    365         if (calc_fb_div(pll, freq, flags, post_div, (*ref_div), fb_div, fb_div_frac)) {
    366             vco = pll->reference_freq * ((*fb_div) + ((*fb_div_frac) * 0.1)) / (*ref_div);
    367 
    368             if ((vco < pll->pll_out_min) || (vco > pll->pll_out_max))
    369                 continue;
    370 
    371             pll_out = vco / post_div;
    372 
    373             error = pll_out - ffreq;
    374             if ((fabs(error) <= max_error) && (error >= 0))
    375                 return TRUE;
    376         }
    377     }
    378     return FALSE;
    379 }
    380 
    381 static void
    382 RADEONComputePLL_new(RADEONPLLPtr pll,
    383 		     unsigned long freq,
    384 		     uint32_t *chosen_dot_clock_freq,
    385 		     uint32_t *chosen_feedback_div,
    386 		     uint32_t *chosen_frac_feedback_div,
    387 		     uint32_t *chosen_reference_div,
    388 		     uint32_t *chosen_post_div,
    389 		     int flags)
    390 {
    391     float ffreq = freq / 10;
    392     float vco_frequency;
    393     int fb_div = 0, fb_div_frac = 0, post_div = 0, ref_div = 0;
    394     uint32_t best_freq = 0;
    395 
    396     if (flags & RADEON_PLL_USE_POST_DIV) {
    397         post_div = pll->post_div;
    398         if ((post_div < pll->min_post_div) || (post_div > pll->max_post_div))
    399             goto done;
    400         vco_frequency = ffreq * post_div;
    401         if ((vco_frequency < pll->pll_out_min) || (vco_frequency > pll->pll_out_max))
    402             goto done;
    403 
    404         if (flags & RADEON_PLL_USE_REF_DIV) {
    405             ref_div = pll->reference_div;
    406             if ((ref_div < pll->min_ref_div) || (ref_div > pll->max_ref_div))
    407                 goto done;
    408             if (!calc_fb_div(pll, freq, flags, post_div, ref_div, &fb_div, &fb_div_frac))
    409                 goto done;
    410         }
    411     } else {
    412 	for (post_div = pll->max_post_div; post_div >= pll->min_post_div; --post_div) {
    413 	    if (flags & RADEON_PLL_LEGACY) {
    414 		if ((post_div == 5) ||
    415 		    (post_div == 7) ||
    416 		    (post_div == 9) ||
    417 		    (post_div == 10) ||
    418 		    (post_div == 11))
    419 		    continue;
    420 	    }
    421 	    if ((flags & RADEON_PLL_NO_ODD_POST_DIV) && (post_div & 1))
    422 		continue;
    423 
    424 	    vco_frequency = ffreq * post_div;
    425 	    if ((vco_frequency < pll->pll_out_min) || (vco_frequency > pll->pll_out_max))
    426 		continue;
    427 	    if (flags & RADEON_PLL_USE_REF_DIV) {
    428 		ref_div = pll->reference_div;
    429 		if ((ref_div < pll->min_ref_div) || (ref_div > pll->max_ref_div))
    430 		    goto done;
    431 		if (calc_fb_div(pll, freq, flags, post_div, ref_div, &fb_div, &fb_div_frac))
    432 		    break;
    433 	    } else {
    434 		if (calc_fb_ref_div(pll, freq, flags, post_div, &fb_div, &fb_div_frac, &ref_div))
    435 		    break;
    436 	    }
    437 	}
    438     }
    439 
    440     best_freq = pll->reference_freq * 10 * fb_div;
    441     best_freq += pll->reference_freq * fb_div_frac;
    442     best_freq = best_freq / (ref_div * post_div);
    443 
    444 /*
    445     ErrorF("best_freq: %u\n", (unsigned int)best_freq);
    446     ErrorF("best_feedback_div: %u\n", (unsigned int)fb_div);
    447     ErrorF("best_frac_feedback_div: %u\n", (unsigned int)fb_div_frac);
    448     ErrorF("best_ref_div: %u\n", (unsigned int)ref_div);
    449     ErrorF("best_post_div: %u\n", (unsigned int)post_div);
    450 */
    451 
    452 done:
    453     if (best_freq == 0)
    454 	FatalError("Couldn't find valid PLL dividers\n");
    455 
    456     *chosen_dot_clock_freq = best_freq;
    457     *chosen_feedback_div = fb_div;
    458     *chosen_frac_feedback_div = fb_div_frac;
    459     *chosen_reference_div = ref_div;
    460     *chosen_post_div = post_div;
    461 
    462 }
    463 
    464 void
    465 RADEONComputePLL(xf86CrtcPtr crtc,
    466 		 RADEONPLLPtr pll,
    467 		 unsigned long freq,
    468 		 uint32_t *chosen_dot_clock_freq,
    469 		 uint32_t *chosen_feedback_div,
    470 		 uint32_t *chosen_frac_feedback_div,
    471 		 uint32_t *chosen_reference_div,
    472 		 uint32_t *chosen_post_div,
    473 		 int flags)
    474 {
    475     RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
    476 
    477     switch (radeon_crtc->pll_algo) {
    478     case RADEON_PLL_OLD:
    479 	RADEONComputePLL_old(pll, freq, chosen_dot_clock_freq,
    480 			     chosen_feedback_div, chosen_frac_feedback_div,
    481 			     chosen_reference_div, chosen_post_div, flags);
    482 	break;
    483     case RADEON_PLL_NEW:
    484 	/* disable frac fb dividers */
    485 	flags &= ~RADEON_PLL_USE_FRAC_FB_DIV;
    486 	RADEONComputePLL_new(pll, freq, chosen_dot_clock_freq,
    487 			     chosen_feedback_div, chosen_frac_feedback_div,
    488 			     chosen_reference_div, chosen_post_div, flags);
    489 	break;
    490     }
    491 }
    492 
    493 static void
    494 radeon_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
    495 		     DisplayModePtr adjusted_mode, int x, int y)
    496 {
    497     ScrnInfoPtr pScrn = crtc->scrn;
    498     RADEONInfoPtr info = RADEONPTR(pScrn);
    499 
    500     if (IS_AVIVO_VARIANT || info->r4xx_atom) {
    501 	atombios_crtc_mode_set(crtc, mode, adjusted_mode, x, y);
    502     } else {
    503 	legacy_crtc_mode_set(crtc, mode, adjusted_mode, x, y);
    504     }
    505 }
    506 
    507 static void
    508 radeon_crtc_mode_commit(xf86CrtcPtr crtc)
    509 {
    510     if (crtc->scrn->pScreen != NULL)
    511 #ifdef HAVE_XF86_CURSOR_RESET_CURSOR
    512 	xf86CursorResetCursor(crtc->scrn->pScreen);
    513 #else
    514 	xf86_reload_cursors(crtc->scrn->pScreen);
    515 #endif
    516 }
    517 
    518 void
    519 radeon_crtc_load_lut(xf86CrtcPtr crtc)
    520 {
    521     ScrnInfoPtr pScrn = crtc->scrn;
    522     RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
    523     RADEONInfoPtr info = RADEONPTR(pScrn);
    524     unsigned char *RADEONMMIO = info->MMIO;
    525     int i;
    526 
    527     if (!crtc->enabled)
    528 	return;
    529 
    530     radeon_save_palette_on_demand(pScrn, radeon_crtc->crtc_id);
    531 
    532     if (IS_DCE4_VARIANT) {
    533 	OUTREG(EVERGREEN_DC_LUT_CONTROL + radeon_crtc->crtc_offset, 0);
    534 
    535 	OUTREG(EVERGREEN_DC_LUT_BLACK_OFFSET_BLUE + radeon_crtc->crtc_offset, 0);
    536 	OUTREG(EVERGREEN_DC_LUT_BLACK_OFFSET_GREEN + radeon_crtc->crtc_offset, 0);
    537 	OUTREG(EVERGREEN_DC_LUT_BLACK_OFFSET_RED + radeon_crtc->crtc_offset, 0);
    538 
    539 	OUTREG(EVERGREEN_DC_LUT_WHITE_OFFSET_BLUE + radeon_crtc->crtc_offset, 0x0000ffff);
    540 	OUTREG(EVERGREEN_DC_LUT_WHITE_OFFSET_GREEN + radeon_crtc->crtc_offset, 0x0000ffff);
    541 	OUTREG(EVERGREEN_DC_LUT_WHITE_OFFSET_RED + radeon_crtc->crtc_offset, 0x0000ffff);
    542 
    543 	OUTREG(EVERGREEN_DC_LUT_RW_MODE + radeon_crtc->crtc_offset, 0);
    544 	OUTREG(EVERGREEN_DC_LUT_WRITE_EN_MASK + radeon_crtc->crtc_offset, 0x00000007);
    545 
    546 	for (i = 0; i < 256; i++) {
    547 	    OUTREG(EVERGREEN_DC_LUT_RW_INDEX + radeon_crtc->crtc_offset, i);
    548 	    OUTREG(EVERGREEN_DC_LUT_30_COLOR + radeon_crtc->crtc_offset,
    549 		   (((radeon_crtc->lut_r[i]) << 20) |
    550 		    ((radeon_crtc->lut_g[i]) << 10) |
    551 		    (radeon_crtc->lut_b[i])));
    552 	}
    553     } else {
    554 	if (IS_AVIVO_VARIANT) {
    555 	    OUTREG(AVIVO_DC_LUTA_CONTROL + radeon_crtc->crtc_offset, 0);
    556 
    557 	    OUTREG(AVIVO_DC_LUTA_BLACK_OFFSET_BLUE + radeon_crtc->crtc_offset, 0);
    558 	    OUTREG(AVIVO_DC_LUTA_BLACK_OFFSET_GREEN + radeon_crtc->crtc_offset, 0);
    559 	    OUTREG(AVIVO_DC_LUTA_BLACK_OFFSET_RED + radeon_crtc->crtc_offset, 0);
    560 
    561 	    OUTREG(AVIVO_DC_LUTA_WHITE_OFFSET_BLUE + radeon_crtc->crtc_offset, 0x0000ffff);
    562 	    OUTREG(AVIVO_DC_LUTA_WHITE_OFFSET_GREEN + radeon_crtc->crtc_offset, 0x0000ffff);
    563 	    OUTREG(AVIVO_DC_LUTA_WHITE_OFFSET_RED + radeon_crtc->crtc_offset, 0x0000ffff);
    564 	}
    565 
    566 	PAL_SELECT(radeon_crtc->crtc_id);
    567 
    568 	if (IS_AVIVO_VARIANT) {
    569 	    OUTREG(AVIVO_DC_LUT_RW_MODE, 0);
    570 	    OUTREG(AVIVO_DC_LUT_WRITE_EN_MASK, 0x0000003f);
    571 	}
    572 
    573 	for (i = 0; i < 256; i++) {
    574 	    OUTPAL(i, radeon_crtc->lut_r[i], radeon_crtc->lut_g[i], radeon_crtc->lut_b[i]);
    575 	}
    576 
    577 	if (IS_AVIVO_VARIANT)
    578 	    OUTREG(AVIVO_D1GRPH_LUT_SEL + radeon_crtc->crtc_offset, radeon_crtc->crtc_id);
    579     }
    580 }
    581 
    582 static void
    583 radeon_crtc_gamma_set(xf86CrtcPtr crtc, uint16_t *red, uint16_t *green,
    584 		      uint16_t *blue, int size)
    585 {
    586     RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
    587     int i;
    588 
    589     for (i = 0; i < 256; i++) {
    590 	radeon_crtc->lut_r[i] = red[i] >> 6;
    591 	radeon_crtc->lut_g[i] = green[i] >> 6;
    592 	radeon_crtc->lut_b[i] = blue[i] >> 6;
    593     }
    594 
    595     radeon_crtc_load_lut(crtc);
    596 }
    597 
    598 static Bool
    599 radeon_crtc_lock(xf86CrtcPtr crtc)
    600 {
    601     ScrnInfoPtr		pScrn = crtc->scrn;
    602     RADEONInfoPtr  info = RADEONPTR(pScrn);
    603 
    604 #ifdef XF86DRI
    605     if (info->cp->CPStarted && pScrn->pScreen) {
    606 	DRILock(pScrn->pScreen, 0);
    607 	if (info->accelOn)
    608 	    RADEON_SYNC(info, pScrn);
    609 	return TRUE;
    610     }
    611 #endif
    612     if (info->accelOn)
    613         RADEON_SYNC(info, pScrn);
    614 
    615     return FALSE;
    616 
    617 }
    618 
    619 static void
    620 radeon_crtc_unlock(xf86CrtcPtr crtc)
    621 {
    622     ScrnInfoPtr		pScrn = crtc->scrn;
    623     RADEONInfoPtr  info = RADEONPTR(pScrn);
    624 
    625 #ifdef XF86DRI
    626 	if (info->cp->CPStarted && pScrn->pScreen) DRIUnlock(pScrn->pScreen);
    627 #endif
    628 
    629     if (info->accelOn)
    630         RADEON_SYNC(info, pScrn);
    631 }
    632 
    633 /**
    634  * Allocates memory for a locked-in-framebuffer shadow of the given
    635  * width and height for this CRTC's rotated shadow framebuffer.
    636  */
    637 
    638 static void *
    639 radeon_crtc_shadow_allocate (xf86CrtcPtr crtc, int width, int height)
    640 {
    641     ScrnInfoPtr pScrn = crtc->scrn;
    642     RADEONInfoPtr  info = RADEONPTR(pScrn);
    643     RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
    644     unsigned long rotate_pitch;
    645     unsigned long rotate_offset;
    646     int size;
    647     int cpp = pScrn->bitsPerPixel / 8;
    648 
    649     /* No rotation without accel */
    650     if (((info->ChipFamily >= CHIP_FAMILY_R600) && !info->directRenderingEnabled) ||
    651 	xf86ReturnOptValBool(info->Options, OPTION_NOACCEL, FALSE)) {
    652 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
    653 		   "Acceleration required for rotation\n");
    654 	return NULL;
    655     }
    656 
    657     rotate_pitch = pScrn->displayWidth * cpp;
    658     size = rotate_pitch * height;
    659 
    660     /* We could get close to what we want here by just creating a pixmap like
    661      * normal, but we have to lock it down in framebuffer, and there is no
    662      * setter for offscreen area locking in EXA currently.  So, we just
    663      * allocate offscreen memory and fake up a pixmap header for it.
    664      */
    665     rotate_offset = radeon_legacy_allocate_memory(pScrn, &radeon_crtc->crtc_rotate_mem,
    666 		    size, RADEON_GPU_PAGE_SIZE, RADEON_GEM_DOMAIN_VRAM);
    667     if (rotate_offset == 0)
    668 	return NULL;
    669 
    670     return info->FB + rotate_offset;
    671 }
    672 
    673 /**
    674  * Creates a pixmap for this CRTC's rotated shadow framebuffer.
    675  */
    676 static PixmapPtr
    677 radeon_crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height)
    678 {
    679     ScrnInfoPtr pScrn = crtc->scrn;
    680     unsigned long rotate_pitch;
    681     PixmapPtr rotate_pixmap;
    682     int cpp = pScrn->bitsPerPixel / 8;
    683 
    684     if (!data)
    685 	data = radeon_crtc_shadow_allocate(crtc, width, height);
    686 
    687     rotate_pitch = pScrn->displayWidth * cpp;
    688 
    689     rotate_pixmap = GetScratchPixmapHeader(pScrn->pScreen,
    690 					   width, height,
    691 					   pScrn->depth,
    692 					   pScrn->bitsPerPixel,
    693 					   rotate_pitch,
    694 					   data);
    695 
    696     if (rotate_pixmap == NULL) {
    697 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
    698 		   "Couldn't allocate shadow pixmap for rotated CRTC\n");
    699     }
    700 
    701     return rotate_pixmap;
    702 }
    703 
    704 static void
    705 radeon_crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data)
    706 {
    707     ScrnInfoPtr pScrn = crtc->scrn;
    708     RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
    709 
    710     if (rotate_pixmap)
    711 	FreeScratchPixmapHeader(rotate_pixmap);
    712 
    713     if (data) {
    714 	radeon_legacy_free_memory(pScrn, radeon_crtc->crtc_rotate_mem);
    715 	radeon_crtc->crtc_rotate_mem = NULL;
    716     }
    717 
    718 }
    719 
    720 #if XF86_CRTC_VERSION >= 2
    721 #include "radeon_atombios.h"
    722 
    723 extern AtomBiosResult
    724 atombios_lock_crtc(atomBiosHandlePtr atomBIOS, int crtc, int lock);
    725 extern void
    726 RADEONInitCrtcBase(xf86CrtcPtr crtc, RADEONSavePtr save,
    727 		   int x, int y);
    728 extern void
    729 RADEONInitCrtc2Base(xf86CrtcPtr crtc, RADEONSavePtr save,
    730 		    int x, int y);
    731 extern void
    732 RADEONRestoreCrtcBase(ScrnInfoPtr pScrn,
    733 		      RADEONSavePtr restore);
    734 extern void
    735 RADEONRestoreCrtc2Base(ScrnInfoPtr pScrn,
    736 		       RADEONSavePtr restore);
    737 
    738 static void
    739 radeon_crtc_set_origin(xf86CrtcPtr crtc, int x, int y)
    740 {
    741     ScrnInfoPtr pScrn = crtc->scrn;
    742     RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
    743     RADEONInfoPtr info = RADEONPTR(pScrn);
    744     unsigned char *RADEONMMIO = info->MMIO;
    745 
    746 
    747     if (IS_DCE4_VARIANT) {
    748 	x &= ~3;
    749 	y &= ~1;
    750 	atombios_lock_crtc(info->atomBIOS, radeon_crtc->crtc_id, 1);
    751 	OUTREG(EVERGREEN_VIEWPORT_START + radeon_crtc->crtc_offset, (x << 16) | y);
    752 	atombios_lock_crtc(info->atomBIOS, radeon_crtc->crtc_id, 0);
    753     } else if (IS_AVIVO_VARIANT) {
    754 	x &= ~3;
    755 	y &= ~1;
    756 	atombios_lock_crtc(info->atomBIOS, radeon_crtc->crtc_id, 1);
    757 	OUTREG(AVIVO_D1MODE_VIEWPORT_START + radeon_crtc->crtc_offset, (x << 16) | y);
    758 	atombios_lock_crtc(info->atomBIOS, radeon_crtc->crtc_id, 0);
    759     } else {
    760 	switch (radeon_crtc->crtc_id) {
    761 	case 0:
    762 	    RADEONInitCrtcBase(crtc, info->ModeReg, x, y);
    763 	    RADEONRestoreCrtcBase(pScrn, info->ModeReg);
    764 	    break;
    765 	case 1:
    766 	    RADEONInitCrtc2Base(crtc, info->ModeReg, x, y);
    767 	    RADEONRestoreCrtc2Base(pScrn, info->ModeReg);
    768 	    break;
    769 	default:
    770 	    break;
    771 	}
    772     }
    773 }
    774 #endif
    775 
    776 
    777 static xf86CrtcFuncsRec radeon_crtc_funcs = {
    778     .dpms = radeon_crtc_dpms,
    779     .save = NULL, /* XXX */
    780     .restore = NULL, /* XXX */
    781     .mode_fixup = radeon_crtc_mode_fixup,
    782     .prepare = radeon_crtc_mode_prepare,
    783     .mode_set = radeon_crtc_mode_set,
    784     .commit = radeon_crtc_mode_commit,
    785     .gamma_set = radeon_crtc_gamma_set,
    786     .lock = radeon_crtc_lock,
    787     .unlock = radeon_crtc_unlock,
    788     .shadow_create = radeon_crtc_shadow_create,
    789     .shadow_allocate = radeon_crtc_shadow_allocate,
    790     .shadow_destroy = radeon_crtc_shadow_destroy,
    791     .set_cursor_colors = radeon_crtc_set_cursor_colors,
    792     .set_cursor_position = radeon_crtc_set_cursor_position,
    793     .show_cursor = radeon_crtc_show_cursor,
    794     .hide_cursor = radeon_crtc_hide_cursor,
    795     .load_cursor_argb = radeon_crtc_load_cursor_argb,
    796     .destroy = NULL, /* XXX */
    797 #if XF86_CRTC_VERSION >= 2
    798     .set_origin = radeon_crtc_set_origin,
    799 #endif
    800 };
    801 
    802 void
    803 RADEONInitDispBandwidth(ScrnInfoPtr pScrn)
    804 {
    805     RADEONInfoPtr info = RADEONPTR(pScrn);
    806     xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
    807     DisplayModePtr mode1 = NULL, mode2 = NULL;
    808     int pixel_bytes1 = info->CurrentLayout.pixel_bytes;
    809     int pixel_bytes2 = info->CurrentLayout.pixel_bytes;
    810 
    811     /* XXX fix me */
    812     if (IS_DCE4_VARIANT)
    813 	return;
    814 
    815     if (xf86_config->num_crtc == 2) {
    816 	if (xf86_config->crtc[1]->enabled &&
    817 	    xf86_config->crtc[0]->enabled) {
    818 	    mode1 = &xf86_config->crtc[0]->mode;
    819 	    mode2 = &xf86_config->crtc[1]->mode;
    820 	} else if (xf86_config->crtc[0]->enabled) {
    821 	    mode1 = &xf86_config->crtc[0]->mode;
    822 	} else if (xf86_config->crtc[1]->enabled) {
    823 	    mode2 = &xf86_config->crtc[1]->mode;
    824 	} else
    825 	    return;
    826     } else {
    827 	if (info->IsPrimary)
    828 	    mode1 = &xf86_config->crtc[0]->mode;
    829 	else if (info->IsSecondary)
    830 	    mode2 = &xf86_config->crtc[0]->mode;
    831 	else if (xf86_config->crtc[0]->enabled)
    832 	    mode1 = &xf86_config->crtc[0]->mode;
    833 	else
    834 	    return;
    835     }
    836 
    837     if (IS_AVIVO_VARIANT)
    838 	RADEONInitDispBandwidthAVIVO(pScrn, mode1, pixel_bytes1, mode2, pixel_bytes2);
    839     else
    840 	RADEONInitDispBandwidthLegacy(pScrn, mode1, pixel_bytes1, mode2, pixel_bytes2);
    841 }
    842 
    843 Bool RADEONAllocateControllers(ScrnInfoPtr pScrn, int mask)
    844 {
    845     RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
    846     RADEONInfoPtr  info = RADEONPTR(pScrn);
    847     int i;
    848 
    849     if (!xf86ReturnOptValBool(info->Options, OPTION_NOACCEL, FALSE)) {
    850 	radeon_crtc_funcs.shadow_create = radeon_crtc_shadow_create;
    851 	radeon_crtc_funcs.shadow_allocate = radeon_crtc_shadow_allocate;
    852 	radeon_crtc_funcs.shadow_destroy = radeon_crtc_shadow_destroy;
    853     }
    854 
    855     if (mask & 1) {
    856 	if (pRADEONEnt->Controller[0])
    857 	    return TRUE;
    858 
    859 	pRADEONEnt->pCrtc[0] = xf86CrtcCreate(pScrn, &radeon_crtc_funcs);
    860 	if (!pRADEONEnt->pCrtc[0])
    861 	    return FALSE;
    862 
    863 	pRADEONEnt->Controller[0] = xnfcalloc(sizeof(RADEONCrtcPrivateRec), 1);
    864 	if (!pRADEONEnt->Controller[0])
    865 	    return FALSE;
    866 
    867 	pRADEONEnt->pCrtc[0]->driver_private = pRADEONEnt->Controller[0];
    868 	pRADEONEnt->Controller[0]->crtc_id = 0;
    869 	pRADEONEnt->Controller[0]->crtc_offset = 0;
    870 	pRADEONEnt->Controller[0]->initialized = FALSE;
    871 	if (info->allowColorTiling)
    872 	    pRADEONEnt->Controller[0]->can_tile = 1;
    873 	else
    874 	    pRADEONEnt->Controller[0]->can_tile = 0;
    875 	pRADEONEnt->Controller[0]->pll_id = -1;
    876     }
    877 
    878     if (mask & 2) {
    879 	if (!pRADEONEnt->HasCRTC2)
    880 	    return TRUE;
    881 
    882 	pRADEONEnt->pCrtc[1] = xf86CrtcCreate(pScrn, &radeon_crtc_funcs);
    883 	if (!pRADEONEnt->pCrtc[1])
    884 	    return FALSE;
    885 
    886 	pRADEONEnt->Controller[1] = xnfcalloc(sizeof(RADEONCrtcPrivateRec), 1);
    887 	if (!pRADEONEnt->Controller[1])
    888 	    {
    889 		free(pRADEONEnt->Controller[0]);
    890 		return FALSE;
    891 	    }
    892 
    893 	pRADEONEnt->pCrtc[1]->driver_private = pRADEONEnt->Controller[1];
    894 	pRADEONEnt->Controller[1]->crtc_id = 1;
    895 	if (IS_DCE4_VARIANT)
    896 	    pRADEONEnt->Controller[1]->crtc_offset = EVERGREEN_CRTC1_REGISTER_OFFSET;
    897 	else
    898 	    pRADEONEnt->Controller[1]->crtc_offset = AVIVO_D2CRTC_H_TOTAL - AVIVO_D1CRTC_H_TOTAL;
    899 	pRADEONEnt->Controller[1]->initialized = FALSE;
    900 	if (info->allowColorTiling)
    901 	    pRADEONEnt->Controller[1]->can_tile = 1;
    902 	else
    903 	    pRADEONEnt->Controller[1]->can_tile = 0;
    904 	pRADEONEnt->Controller[1]->pll_id = -1;
    905     }
    906 
    907     /* 6 crtcs on DCE4 chips */
    908     if (IS_DCE4_VARIANT && ((mask & 3) == 3) && !IS_DCE41_VARIANT) {
    909 	for (i = 2; i < RADEON_MAX_CRTC; i++) {
    910 	    pRADEONEnt->pCrtc[i] = xf86CrtcCreate(pScrn, &radeon_crtc_funcs);
    911 	    if (!pRADEONEnt->pCrtc[i])
    912 		return FALSE;
    913 
    914 	    pRADEONEnt->Controller[i] = xnfcalloc(sizeof(RADEONCrtcPrivateRec), 1);
    915 	    if (!pRADEONEnt->Controller[i])
    916 	    {
    917 		free(pRADEONEnt->Controller[i]);
    918 		return FALSE;
    919 	    }
    920 
    921 	    pRADEONEnt->pCrtc[i]->driver_private = pRADEONEnt->Controller[i];
    922 	    pRADEONEnt->Controller[i]->crtc_id = i;
    923 	    switch (i) {
    924 	    case 0:
    925 		pRADEONEnt->Controller[i]->crtc_offset = EVERGREEN_CRTC0_REGISTER_OFFSET;
    926 		break;
    927 	    case 1:
    928 		pRADEONEnt->Controller[i]->crtc_offset = EVERGREEN_CRTC1_REGISTER_OFFSET;
    929 		break;
    930 	    case 2:
    931 		pRADEONEnt->Controller[i]->crtc_offset = EVERGREEN_CRTC2_REGISTER_OFFSET;
    932 		break;
    933 	    case 3:
    934 		pRADEONEnt->Controller[i]->crtc_offset = EVERGREEN_CRTC3_REGISTER_OFFSET;
    935 		break;
    936 	    case 4:
    937 		pRADEONEnt->Controller[i]->crtc_offset = EVERGREEN_CRTC4_REGISTER_OFFSET;
    938 		break;
    939 	    case 5:
    940 		pRADEONEnt->Controller[i]->crtc_offset = EVERGREEN_CRTC5_REGISTER_OFFSET;
    941 		break;
    942 	    }
    943 	    pRADEONEnt->Controller[i]->initialized = FALSE;
    944 	    if (info->allowColorTiling)
    945 		pRADEONEnt->Controller[i]->can_tile = 1;
    946 	    else
    947 		pRADEONEnt->Controller[i]->can_tile = 0;
    948 	    pRADEONEnt->Controller[i]->pll_id = -1;
    949 	}
    950     }
    951 
    952     return TRUE;
    953 }
    954 
    955 /**
    956  * In the current world order, there are lists of modes per output, which may
    957  * or may not include the mode that was asked to be set by XFree86's mode
    958  * selection.  Find the closest one, in the following preference order:
    959  *
    960  * - Equality
    961  * - Closer in size to the requested mode, but no larger
    962  * - Closer in refresh rate to the requested mode.
    963  */
    964 DisplayModePtr
    965 RADEONCrtcFindClosestMode(xf86CrtcPtr crtc, DisplayModePtr pMode)
    966 {
    967     ScrnInfoPtr	pScrn = crtc->scrn;
    968     xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
    969     DisplayModePtr pBest = NULL, pScan = NULL;
    970     int i;
    971 
    972     /* Assume that there's only one output connected to the given CRTC. */
    973     for (i = 0; i < xf86_config->num_output; i++)
    974     {
    975 	xf86OutputPtr  output = xf86_config->output[i];
    976 	if (output->crtc == crtc && output->probed_modes != NULL)
    977 	{
    978 	    pScan = output->probed_modes;
    979 	    break;
    980 	}
    981     }
    982 
    983     /* If the pipe doesn't have any detected modes, just let the system try to
    984      * spam the desired mode in.
    985      */
    986     if (pScan == NULL) {
    987 	RADEONCrtcPrivatePtr  radeon_crtc = crtc->driver_private;
    988 	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
    989 		   "No crtc mode list for crtc %d,"
    990 		   "continuing with desired mode\n", radeon_crtc->crtc_id);
    991 	return pMode;
    992     }
    993 
    994     for (; pScan != NULL; pScan = pScan->next) {
    995 	assert(pScan->VRefresh != 0.0);
    996 
    997 	/* If there's an exact match, we're done. */
    998 	if (xf86ModesEqual(pScan, pMode)) {
    999 	    pBest = pMode;
   1000 	    break;
   1001 	}
   1002 
   1003 	/* Reject if it's larger than the desired mode. */
   1004 	if (pScan->HDisplay > pMode->HDisplay ||
   1005 	    pScan->VDisplay > pMode->VDisplay)
   1006 	{
   1007 	    continue;
   1008 	}
   1009 
   1010 	if (pBest == NULL) {
   1011 	    pBest = pScan;
   1012 	    continue;
   1013 	}
   1014 
   1015 	/* Find if it's closer to the right size than the current best
   1016 	 * option.
   1017 	 */
   1018 	if ((pScan->HDisplay > pBest->HDisplay &&
   1019 	     pScan->VDisplay >= pBest->VDisplay) ||
   1020 	    (pScan->HDisplay >= pBest->HDisplay &&
   1021 	     pScan->VDisplay > pBest->VDisplay))
   1022 	{
   1023 	    pBest = pScan;
   1024 	    continue;
   1025 	}
   1026 
   1027 	/* Find if it's still closer to the right refresh than the current
   1028 	 * best resolution.
   1029 	 */
   1030 	if (pScan->HDisplay == pBest->HDisplay &&
   1031 	    pScan->VDisplay == pBest->VDisplay &&
   1032 	    (fabs(pScan->VRefresh - pMode->VRefresh) <
   1033 	     fabs(pBest->VRefresh - pMode->VRefresh))) {
   1034 	    pBest = pScan;
   1035 	}
   1036     }
   1037 
   1038     if (pBest == NULL) {
   1039 	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
   1040 		   "No suitable mode found to program for the pipe.\n"
   1041 		   "	continuing with desired mode %dx%d@%.1f\n",
   1042 		   pMode->HDisplay, pMode->VDisplay, pMode->VRefresh);
   1043     } else if (!xf86ModesEqual(pBest, pMode)) {
   1044       RADEONCrtcPrivatePtr  radeon_crtc = crtc->driver_private;
   1045       int		    crtc = radeon_crtc->crtc_id;
   1046       xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
   1047 		   "Choosing pipe %d's mode %dx%d@%.1f instead of xf86 "
   1048 		   "mode %dx%d@%.1f\n", crtc,
   1049 		   pBest->HDisplay, pBest->VDisplay, pBest->VRefresh,
   1050 		   pMode->HDisplay, pMode->VDisplay, pMode->VRefresh);
   1051 	pMode = pBest;
   1052     }
   1053     return pMode;
   1054 }
   1055 
   1056 void
   1057 RADEONBlank(ScrnInfoPtr pScrn)
   1058 {
   1059     xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
   1060     xf86OutputPtr output;
   1061     xf86CrtcPtr crtc;
   1062     int o, c;
   1063 
   1064     for (c = 0; c < xf86_config->num_crtc; c++) {
   1065 	crtc = xf86_config->crtc[c];
   1066 	for (o = 0; o < xf86_config->num_output; o++) {
   1067 	    output = xf86_config->output[o];
   1068 	    if (output->crtc != crtc)
   1069 		continue;
   1070 
   1071 	    output->funcs->dpms(output, DPMSModeOff);
   1072 	}
   1073 	crtc->funcs->dpms(crtc, DPMSModeOff);
   1074     }
   1075 }
   1076 
   1077 void
   1078 RADEONUnblank(ScrnInfoPtr pScrn)
   1079 {
   1080     xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
   1081     xf86OutputPtr output;
   1082     xf86CrtcPtr crtc;
   1083     int o, c;
   1084 
   1085     for (c = 0; c < xf86_config->num_crtc; c++) {
   1086 	crtc = xf86_config->crtc[c];
   1087 	if(!crtc->enabled)
   1088 		continue;
   1089 	crtc->funcs->dpms(crtc, DPMSModeOn);
   1090 	for (o = 0; o < xf86_config->num_output; o++) {
   1091 	    output = xf86_config->output[o];
   1092 	    if (output->crtc != crtc)
   1093 		continue;
   1094 
   1095 	    output->funcs->dpms(output, DPMSModeOn);
   1096 	}
   1097     }
   1098 }
   1099 
   1100 Bool
   1101 RADEONSetTiling(ScrnInfoPtr pScrn)
   1102 {
   1103     xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
   1104     RADEONInfoPtr info = RADEONPTR(pScrn);
   1105     RADEONCrtcPrivatePtr radeon_crtc;
   1106     xf86CrtcPtr crtc;
   1107     int c;
   1108     int can_tile = 1;
   1109     Bool changed = FALSE;
   1110 
   1111     for (c = 0; c < xf86_config->num_crtc; c++) {
   1112 	crtc = xf86_config->crtc[c];
   1113 	radeon_crtc = crtc->driver_private;
   1114 
   1115 	if (crtc->enabled) {
   1116 	    if (!radeon_crtc->can_tile)
   1117 		can_tile = 0;
   1118 	}
   1119     }
   1120 
   1121     if (info->tilingEnabled != can_tile)
   1122 	changed = TRUE;
   1123 
   1124 #ifdef XF86DRI
   1125     if (info->directRenderingEnabled && (info->tilingEnabled != can_tile)) {
   1126 	drm_radeon_sarea_t *pSAREAPriv;
   1127 	if (RADEONDRISetParam(pScrn, RADEON_SETPARAM_SWITCH_TILING, (can_tile ? 1 : 0)) < 0)
   1128 	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
   1129 		       "[drm] failed changing tiling status\n");
   1130 	/* if this is called during ScreenInit() we don't have pScrn->pScreen yet */
   1131 	pSAREAPriv = DRIGetSAREAPrivate(xf86ScrnToScreen(pScrn));
   1132 	info->tilingEnabled = pSAREAPriv->tiling_enabled ? TRUE : FALSE;
   1133     }
   1134 #endif
   1135 
   1136     return changed;
   1137 }
   1138