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 
     36 #include "xf86.h"
     37 #include "xf86Modes.h"
     38 
     39 #ifdef HAVE_XEXTPROTO_71
     40 #include "X11/extensions/dpmsconst.h"
     41 #else
     42 #define DPMS_SERVER
     43 #include "X11/extensions/dpms.h"
     44 #endif
     45 
     46 #include "r128.h"
     47 #include "r128_probe.h"
     48 #include "r128_reg.h"
     49 
     50 
     51 #ifndef MAX
     52 #define MAX(a,b) ((a)>(b)?(a):(b))
     53 #endif
     54 
     55 
     56 /* Define CRTC registers for requested video mode. */
     57 static Bool
     58 R128InitCrtcRegisters(xf86CrtcPtr crtc, R128SavePtr save, DisplayModePtr mode)
     59 {
     60     ScrnInfoPtr pScrn = crtc->scrn;
     61     R128InfoPtr info  = R128PTR(pScrn);
     62     xf86OutputPtr output = R128FirstOutput(crtc);
     63     R128OutputPrivatePtr r128_output = output->driver_private;
     64 
     65     int    format;
     66     int    hsync_start;
     67     int    hsync_wid;
     68     int    hsync_fudge;
     69     int    vsync_wid;
     70     int    hsync_fudge_default[] = { 0x00, 0x12, 0x09, 0x09, 0x06, 0x05 };
     71     int    hsync_fudge_fp[]      = { 0x12, 0x11, 0x09, 0x09, 0x05, 0x05 };
     72 //   int    hsync_fudge_fp_crt[]  = { 0x12, 0x10, 0x08, 0x08, 0x04, 0x04 };
     73 
     74     switch (info->CurrentLayout.pixel_code) {
     75     case 4:  format = 1; break;
     76     case 8:  format = 2; break;
     77     case 15: format = 3; break;      /*  555 */
     78     case 16: format = 4; break;      /*  565 */
     79     case 24: format = 5; break;      /*  RGB */
     80     case 32: format = 6; break;      /* xRGB */
     81     default:
     82     xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
     83            "Unsupported pixel depth (%d)\n",
     84            info->CurrentLayout.bitsPerPixel);
     85     return FALSE;
     86     }
     87 
     88     if (r128_output->MonType == MT_LCD || r128_output->MonType == MT_DFP)
     89     hsync_fudge = hsync_fudge_fp[format-1];
     90     else
     91         hsync_fudge = hsync_fudge_default[format-1];
     92 
     93     save->crtc_gen_cntl = (R128_CRTC_EXT_DISP_EN
     94               | R128_CRTC_EN
     95               | (format << 8)
     96               | ((mode->Flags & V_DBLSCAN)
     97                  ? R128_CRTC_DBL_SCAN_EN
     98                  : 0)
     99               | ((mode->Flags & V_INTERLACE)
    100                  ? R128_CRTC_INTERLACE_EN
    101                  : 0)
    102               | ((mode->Flags & V_CSYNC)
    103                  ? R128_CRTC_CSYNC_EN
    104                  : 0));
    105 
    106     if (r128_output->MonType == MT_LCD || r128_output->MonType == MT_DFP)
    107         save->crtc_gen_cntl &= ~(R128_CRTC_DBL_SCAN_EN | R128_CRTC_INTERLACE_EN);
    108 
    109     save->crtc_ext_cntl |= R128_VGA_ATI_LINEAR | R128_XCRT_CNT_EN;
    110 
    111     save->crtc_h_total_disp = ((((mode->CrtcHTotal / 8) - 1) & 0xffff)
    112                   | (((mode->CrtcHDisplay / 8) - 1) << 16));
    113 
    114     hsync_wid = (mode->CrtcHSyncEnd - mode->CrtcHSyncStart) / 8;
    115     if (!hsync_wid)       hsync_wid = 1;
    116     if (hsync_wid > 0x3f) hsync_wid = 0x3f;
    117 
    118     hsync_start = mode->CrtcHSyncStart - 8 + hsync_fudge;
    119 
    120     save->crtc_h_sync_strt_wid = ((hsync_start & 0xfff)
    121                  | (hsync_wid << 16)
    122                  | ((mode->Flags & V_NHSYNC)
    123                     ? R128_CRTC_H_SYNC_POL
    124                     : 0));
    125 
    126 #if 1
    127                 /* This works for double scan mode. */
    128     save->crtc_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff)
    129                   | ((mode->CrtcVDisplay - 1) << 16));
    130 #else
    131                 /* This is what cce/nbmode.c example code
    132                    does -- is this correct? */
    133     save->crtc_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff)
    134                   | ((mode->CrtcVDisplay
    135                   * ((mode->Flags & V_DBLSCAN) ? 2 : 1) - 1)
    136                  << 16));
    137 #endif
    138 
    139     vsync_wid = mode->CrtcVSyncEnd - mode->CrtcVSyncStart;
    140     if (!vsync_wid)       vsync_wid = 1;
    141     if (vsync_wid > 0x1f) vsync_wid = 0x1f;
    142 
    143     save->crtc_v_sync_strt_wid = (((mode->CrtcVSyncStart - 1) & 0xfff)
    144                  | (vsync_wid << 16)
    145                  | ((mode->Flags & V_NVSYNC)
    146                     ? R128_CRTC_V_SYNC_POL
    147                     : 0));
    148     save->crtc_pitch       = info->CurrentLayout.displayWidth / 8;
    149 
    150     DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
    151                         "Pitch = %d bytes (virtualX = %d, "
    152                         "displayWidth = %d)\n",
    153                         save->crtc_pitch, pScrn->virtualX,
    154                         info->CurrentLayout.displayWidth));
    155 
    156 #if X_BYTE_ORDER == X_BIG_ENDIAN
    157     /* Change the endianness of the aperture */
    158     switch (info->CurrentLayout.pixel_code) {
    159     case 15:
    160     case 16: save->config_cntl |= APER_0_BIG_ENDIAN_16BPP_SWAP; break;
    161     case 32: save->config_cntl |= APER_0_BIG_ENDIAN_32BPP_SWAP; break;
    162     default: break;
    163     }
    164 #endif
    165 
    166     return TRUE;
    167 }
    168 
    169 /* Define CRTC2 registers for requested video mode. */
    170 static Bool
    171 R128InitCrtc2Registers(xf86CrtcPtr crtc, R128SavePtr save, DisplayModePtr mode)
    172 {
    173     ScrnInfoPtr pScrn = crtc->scrn;
    174     R128InfoPtr info  = R128PTR(pScrn);
    175 
    176     int    format;
    177     int    hsync_start;
    178     int    hsync_wid;
    179     int    hsync_fudge;
    180     int    vsync_wid;
    181     int    hsync_fudge_default[] = { 0x00, 0x12, 0x09, 0x09, 0x06, 0x05 };
    182 
    183     switch (info->CurrentLayout.pixel_code) {
    184     case 4:  format = 1; break;
    185     case 8:  format = 2; break;
    186     case 15: format = 3; break;      /*  555 */
    187     case 16: format = 4; break;      /*  565 */
    188     case 24: format = 5; break;      /*  RGB */
    189     case 32: format = 6; break;      /* xRGB */
    190     default:
    191     xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
    192            "Unsupported pixel depth (%d)\n", info->CurrentLayout.bitsPerPixel);
    193     return FALSE;
    194     }
    195 
    196     hsync_fudge = hsync_fudge_default[format-1];
    197 
    198     save->crtc2_gen_cntl = (R128_CRTC2_EN
    199               | (format << 8)
    200               | ((mode->Flags & V_DBLSCAN)
    201                  ? R128_CRTC2_DBL_SCAN_EN
    202                  : 0));
    203 /*
    204     save->crtc2_gen_cntl &= ~R128_CRTC_EXT_DISP_EN;
    205     save->crtc2_gen_cntl |= (1 << 21);
    206 */
    207     save->crtc2_h_total_disp = ((((mode->CrtcHTotal / 8) - 1) & 0xffff)
    208                   | (((mode->CrtcHDisplay / 8) - 1) << 16));
    209 
    210     hsync_wid = (mode->CrtcHSyncEnd - mode->CrtcHSyncStart) / 8;
    211     if (!hsync_wid)       hsync_wid = 1;
    212     if (hsync_wid > 0x3f) hsync_wid = 0x3f;
    213 
    214     hsync_start = mode->CrtcHSyncStart - 8 + hsync_fudge;
    215 
    216     save->crtc2_h_sync_strt_wid = ((hsync_start & 0xfff)
    217                  | (hsync_wid << 16)
    218                  | ((mode->Flags & V_NHSYNC)
    219                     ? R128_CRTC2_H_SYNC_POL
    220                     : 0));
    221 
    222 #if 1
    223                 /* This works for double scan mode. */
    224     save->crtc2_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff)
    225                   | ((mode->CrtcVDisplay - 1) << 16));
    226 #else
    227                 /* This is what cce/nbmode.c example code
    228                    does -- is this correct? */
    229     save->crtc2_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff)
    230                   | ((mode->CrtcVDisplay
    231                   * ((mode->Flags & V_DBLSCAN) ? 2 : 1) - 1)
    232                  << 16));
    233 #endif
    234 
    235     vsync_wid = mode->CrtcVSyncEnd - mode->CrtcVSyncStart;
    236     if (!vsync_wid)       vsync_wid = 1;
    237     if (vsync_wid > 0x1f) vsync_wid = 0x1f;
    238 
    239     save->crtc2_v_sync_strt_wid = (((mode->CrtcVSyncStart - 1) & 0xfff)
    240                  | (vsync_wid << 16)
    241                  | ((mode->Flags & V_NVSYNC)
    242                     ? R128_CRTC2_V_SYNC_POL
    243                     : 0));
    244     save->crtc2_pitch       = info->CurrentLayout.displayWidth / 8;
    245 
    246     DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
    247                         "Pitch = %d bytes (virtualX = %d, "
    248                         "displayWidth = %d)\n",
    249                         save->crtc2_pitch, pScrn->virtualX,
    250                         info->CurrentLayout.displayWidth));
    251     return TRUE;
    252 }
    253 
    254 /* Write CRTC registers. */
    255 void R128RestoreCrtcRegisters(ScrnInfoPtr pScrn, R128SavePtr restore)
    256 {
    257     R128InfoPtr   info      = R128PTR(pScrn);
    258     unsigned char *R128MMIO = info->MMIO;
    259 
    260     OUTREG(R128_CRTC_GEN_CNTL,        restore->crtc_gen_cntl);
    261 
    262     OUTREGP(R128_CRTC_EXT_CNTL, restore->crtc_ext_cntl,
    263         R128_CRTC_VSYNC_DIS | R128_CRTC_HSYNC_DIS | R128_CRTC_DISPLAY_DIS);
    264 
    265     OUTREG(R128_CRTC_H_TOTAL_DISP,    restore->crtc_h_total_disp);
    266     OUTREG(R128_CRTC_H_SYNC_STRT_WID, restore->crtc_h_sync_strt_wid);
    267     OUTREG(R128_CRTC_V_TOTAL_DISP,    restore->crtc_v_total_disp);
    268     OUTREG(R128_CRTC_V_SYNC_STRT_WID, restore->crtc_v_sync_strt_wid);
    269     OUTREG(R128_CRTC_OFFSET,          restore->crtc_offset);
    270     OUTREG(R128_CRTC_OFFSET_CNTL,     restore->crtc_offset_cntl);
    271     OUTREG(R128_CRTC_PITCH,           restore->crtc_pitch);
    272 }
    273 
    274 /* Write CRTC2 registers. */
    275 void R128RestoreCrtc2Registers(ScrnInfoPtr pScrn, R128SavePtr restore)
    276 {
    277     R128InfoPtr info        = R128PTR(pScrn);
    278     unsigned char *R128MMIO = info->MMIO;
    279 
    280     OUTREGP(R128_CRTC2_GEN_CNTL, restore->crtc2_gen_cntl,
    281         R128_CRTC2_DISP_DIS);
    282 
    283     OUTREG(R128_CRTC2_H_TOTAL_DISP,    restore->crtc2_h_total_disp);
    284     OUTREG(R128_CRTC2_H_SYNC_STRT_WID, restore->crtc2_h_sync_strt_wid);
    285     OUTREG(R128_CRTC2_V_TOTAL_DISP,    restore->crtc2_v_total_disp);
    286     OUTREG(R128_CRTC2_V_SYNC_STRT_WID, restore->crtc2_v_sync_strt_wid);
    287     OUTREG(R128_CRTC2_OFFSET,          restore->crtc2_offset);
    288     OUTREG(R128_CRTC2_OFFSET_CNTL,     restore->crtc2_offset_cntl);
    289     OUTREG(R128_CRTC2_PITCH,           restore->crtc2_pitch);
    290 }
    291 
    292 static Bool R128InitCrtcBase(xf86CrtcPtr crtc, R128SavePtr save, int x, int y)
    293 {
    294     ScrnInfoPtr pScrn = crtc->scrn;
    295     R128InfoPtr info  = R128PTR(pScrn);
    296     int offset = y * info->CurrentLayout.displayWidth + x;
    297     int Base = pScrn->fbOffset;
    298 
    299     switch (info->CurrentLayout.pixel_code) {
    300     case 15:
    301     case 16: offset *= 2; break;
    302     case 24: offset *= 3; break;
    303     case 32: offset *= 4; break;
    304     }
    305     Base += offset;
    306 
    307     if (crtc->rotatedData != NULL)
    308         Base = pScrn->fbOffset + (char *)crtc->rotatedData - (char *)info->FB;
    309 
    310     Base &= ~7;                 /* 3 lower bits are always 0 */
    311     if (info->CurrentLayout.pixel_code == 24)
    312     Base += 8 * (Base % 3); /* Must be multiple of 8 and 3 */
    313 
    314     save->crtc_offset = Base;
    315     save->crtc_offset_cntl = 0;
    316 
    317     return TRUE;
    318 }
    319 
    320 static Bool R128InitCrtc2Base(xf86CrtcPtr crtc, R128SavePtr save, int x, int y)
    321 {
    322     ScrnInfoPtr pScrn = crtc->scrn;
    323     R128InfoPtr info  = R128PTR(pScrn);
    324     int offset = y * info->CurrentLayout.displayWidth + x;
    325     int Base = pScrn->fbOffset;
    326 
    327     switch (info->CurrentLayout.pixel_code) {
    328     case 15:
    329     case 16: offset *= 2; break;
    330     case 24: offset *= 3; break;
    331     case 32: offset *= 4; break;
    332     }
    333     Base += offset;
    334 
    335     if (crtc->rotatedData != NULL)
    336         Base = pScrn->fbOffset + (char *)crtc->rotatedData - (char *)info->FB;
    337 
    338     Base &= ~7;                 /* 3 lower bits are always 0 */
    339     if (info->CurrentLayout.pixel_code == 24)
    340     Base += 8 * (Base % 3); /* Must be multiple of 8 and 3 */
    341 
    342     save->crtc2_offset = Base;
    343     save->crtc2_offset_cntl = 0;
    344 
    345     return TRUE;
    346 }
    347 
    348 /* Define PLL registers for requested video mode. */
    349 static void R128InitPLLRegisters(xf86CrtcPtr crtc, R128SavePtr save,
    350                 R128PLLPtr pll, double dot_clock)
    351 {
    352 #if R128_DEBUG
    353     ScrnInfoPtr pScrn  = crtc->scrn;
    354 #endif
    355     unsigned long freq = dot_clock * 100;
    356     struct {
    357     int divider;
    358     int bitvalue;
    359     } *post_div,
    360       post_divs[]   = {
    361                 /* From RAGE 128 VR/RAGE 128 GL Register
    362                    Reference Manual (Technical Reference
    363                    Manual P/N RRG-G04100-C Rev. 0.04), page
    364                    3-17 (PLL_DIV_[3:0]).  */
    365     {  1, 0 },              /* VCLK_SRC                 */
    366     {  2, 1 },              /* VCLK_SRC/2               */
    367     {  4, 2 },              /* VCLK_SRC/4               */
    368     {  8, 3 },              /* VCLK_SRC/8               */
    369 
    370     {  3, 4 },              /* VCLK_SRC/3               */
    371                 /* bitvalue = 5 is reserved */
    372     {  6, 6 },              /* VCLK_SRC/6               */
    373     { 12, 7 },              /* VCLK_SRC/12              */
    374     {  0, 0 }
    375     };
    376 
    377     if (freq > pll->max_pll_freq)      freq = pll->max_pll_freq;
    378     if (freq * 12 < pll->min_pll_freq) freq = pll->min_pll_freq / 12;
    379 
    380     for (post_div = &post_divs[0]; post_div->divider; ++post_div) {
    381     save->pll_output_freq = post_div->divider * freq;
    382     if (save->pll_output_freq >= pll->min_pll_freq
    383         && save->pll_output_freq <= pll->max_pll_freq) break;
    384     }
    385 
    386     save->dot_clock_freq = freq;
    387     save->feedback_div   = R128Div(pll->reference_div * save->pll_output_freq,
    388                    pll->reference_freq);
    389     save->post_div       = post_div->divider;
    390 
    391     DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
    392                         "dc=%d, of=%d, fd=%d, pd=%d\n",
    393                         save->dot_clock_freq,
    394                         save->pll_output_freq,
    395                         save->feedback_div,
    396                         save->post_div));
    397 
    398     save->ppll_ref_div   = pll->reference_div;
    399     save->ppll_div_3     = (save->feedback_div | (post_div->bitvalue << 16));
    400     save->htotal_cntl    = 0;
    401 
    402 }
    403 
    404 /* Define PLL2 registers for requested video mode. */
    405 static void
    406 R128InitPLL2Registers(xf86CrtcPtr crtc, R128SavePtr save,
    407                       R128PLLPtr pll, double dot_clock)
    408 {
    409 #if R128_DEBUG
    410     ScrnInfoPtr pScrn  = crtc->scrn;
    411 #endif
    412     unsigned long freq = dot_clock * 100;
    413     struct {
    414     int divider;
    415     int bitvalue;
    416     } *post_div,
    417       post_divs[]   = {
    418                 /* From RAGE 128 VR/RAGE 128 GL Register
    419                    Reference Manual (Technical Reference
    420                    Manual P/N RRG-G04100-C Rev. 0.04), page
    421                    3-17 (PLL_DIV_[3:0]).  */
    422     {  1, 0 },              /* VCLK_SRC                 */
    423     {  2, 1 },              /* VCLK_SRC/2               */
    424     {  4, 2 },              /* VCLK_SRC/4               */
    425     {  8, 3 },              /* VCLK_SRC/8               */
    426 
    427     {  3, 4 },              /* VCLK_SRC/3               */
    428                 /* bitvalue = 5 is reserved */
    429     {  6, 6 },              /* VCLK_SRC/6               */
    430     { 12, 7 },              /* VCLK_SRC/12              */
    431     {  0, 0 }
    432     };
    433 
    434     if (freq > pll->max_pll_freq)      freq = pll->max_pll_freq;
    435     if (freq * 12 < pll->min_pll_freq) freq = pll->min_pll_freq / 12;
    436 
    437     for (post_div = &post_divs[0]; post_div->divider; ++post_div) {
    438     save->pll_output_freq_2 = post_div->divider * freq;
    439     if (save->pll_output_freq_2 >= pll->min_pll_freq
    440         && save->pll_output_freq_2 <= pll->max_pll_freq) break;
    441     }
    442 
    443     save->dot_clock_freq_2 = freq;
    444     save->feedback_div_2   = R128Div(pll->reference_div
    445                      * save->pll_output_freq_2,
    446                      pll->reference_freq);
    447     save->post_div_2       = post_div->divider;
    448 
    449     DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
    450                         "dc=%d, of=%d, fd=%d, pd=%d\n",
    451                         save->dot_clock_freq_2,
    452                         save->pll_output_freq_2,
    453                         save->feedback_div_2,
    454                         save->post_div_2));
    455 
    456     save->p2pll_ref_div   = pll->reference_div;
    457     save->p2pll_div_0    = (save->feedback_div_2 | (post_div->bitvalue<<16));
    458     save->htotal_cntl2    = 0;
    459 }
    460 
    461 static void R128PLLWaitForReadUpdateComplete(ScrnInfoPtr pScrn)
    462 {
    463     while (INPLL(pScrn, R128_PPLL_REF_DIV) & R128_PPLL_ATOMIC_UPDATE_R);
    464 }
    465 
    466 static void R128PLLWriteUpdate(ScrnInfoPtr pScrn)
    467 {
    468     R128InfoPtr   info      = R128PTR(pScrn);
    469     unsigned char *R128MMIO = info->MMIO;
    470 
    471     while (INPLL(pScrn, R128_PPLL_REF_DIV) & R128_PPLL_ATOMIC_UPDATE_R);
    472 
    473     OUTPLLP(pScrn, R128_PPLL_REF_DIV, R128_PPLL_ATOMIC_UPDATE_W,
    474         ~R128_PPLL_ATOMIC_UPDATE_W);
    475 
    476 }
    477 
    478 static void R128PLL2WaitForReadUpdateComplete(ScrnInfoPtr pScrn)
    479 {
    480     while (INPLL(pScrn, R128_P2PLL_REF_DIV) & R128_P2PLL_ATOMIC_UPDATE_R);
    481 }
    482 
    483 static void R128PLL2WriteUpdate(ScrnInfoPtr pScrn)
    484 {
    485     R128InfoPtr  info       = R128PTR(pScrn);
    486     unsigned char *R128MMIO = info->MMIO;
    487 
    488     while (INPLL(pScrn, R128_P2PLL_REF_DIV) & R128_P2PLL_ATOMIC_UPDATE_R);
    489 
    490     OUTPLLP(pScrn, R128_P2PLL_REF_DIV,
    491         R128_P2PLL_ATOMIC_UPDATE_W,
    492         ~(R128_P2PLL_ATOMIC_UPDATE_W));
    493 }
    494 
    495 /* Write PLL registers. */
    496 void R128RestorePLLRegisters(ScrnInfoPtr pScrn, R128SavePtr restore)
    497 {
    498     R128InfoPtr   info      = R128PTR(pScrn);
    499     unsigned char *R128MMIO = info->MMIO;
    500 
    501 
    502     OUTPLLP(pScrn, R128_VCLK_ECP_CNTL,
    503         R128_VCLK_SRC_SEL_CPUCLK,
    504         ~(R128_VCLK_SRC_SEL_MASK));
    505 
    506     OUTPLLP(pScrn,
    507         R128_PPLL_CNTL,
    508         R128_PPLL_RESET
    509         | R128_PPLL_ATOMIC_UPDATE_EN
    510         | R128_PPLL_VGA_ATOMIC_UPDATE_EN,
    511         ~(R128_PPLL_RESET
    512           | R128_PPLL_ATOMIC_UPDATE_EN
    513           | R128_PPLL_VGA_ATOMIC_UPDATE_EN));
    514 
    515     OUTREGP(R128_CLOCK_CNTL_INDEX, R128_PLL_DIV_SEL, ~(R128_PLL_DIV_SEL));
    516 
    517 /*        R128PLLWaitForReadUpdateComplete(pScrn);*/
    518     OUTPLLP(pScrn, R128_PPLL_REF_DIV,
    519         restore->ppll_ref_div, ~R128_PPLL_REF_DIV_MASK);
    520 /*        R128PLLWriteUpdate(pScrn);
    521 
    522         R128PLLWaitForReadUpdateComplete(pScrn);*/
    523     OUTPLLP(pScrn, R128_PPLL_DIV_3,
    524         restore->ppll_div_3, ~R128_PPLL_FB3_DIV_MASK);
    525 /*    R128PLLWriteUpdate(pScrn);*/
    526     OUTPLLP(pScrn, R128_PPLL_DIV_3,
    527         restore->ppll_div_3, ~R128_PPLL_POST3_DIV_MASK);
    528 
    529     R128PLLWriteUpdate(pScrn);
    530     R128PLLWaitForReadUpdateComplete(pScrn);
    531 
    532     OUTPLLP(pScrn, R128_PPLL_DIV_0,
    533         restore->ppll_div_0, ~R128_PPLL_FB0_DIV_MASK);
    534 /*    R128PLLWriteUpdate(pScrn);*/
    535     OUTPLLP(pScrn, R128_PPLL_DIV_0,
    536         restore->ppll_div_0, ~R128_PPLL_POST0_DIV_MASK);
    537 
    538     R128PLLWriteUpdate(pScrn);
    539     R128PLLWaitForReadUpdateComplete(pScrn);
    540 
    541     OUTPLL(R128_HTOTAL_CNTL, restore->htotal_cntl);
    542 /*    R128PLLWriteUpdate(pScrn);*/
    543 
    544     OUTPLLP(pScrn, R128_PPLL_CNTL, 0, ~(R128_PPLL_RESET
    545                     | R128_PPLL_SLEEP
    546                     | R128_PPLL_ATOMIC_UPDATE_EN
    547                     | R128_PPLL_VGA_ATOMIC_UPDATE_EN));
    548 
    549     DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
    550                         "Wrote: 0x%08x 0x%08x 0x%08x (0x%08x)\n",
    551                         restore->ppll_ref_div,
    552                         restore->ppll_div_3,
    553                         restore->htotal_cntl,
    554                         INPLL(pScrn, R128_PPLL_CNTL)));
    555     DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
    556                         "Wrote: rd=%d, fd=%d, pd=%d\n",
    557                         restore->ppll_ref_div & R128_PPLL_REF_DIV_MASK,
    558                         restore->ppll_div_3 & R128_PPLL_FB3_DIV_MASK,
    559                         (restore->ppll_div_3 &
    560                                 R128_PPLL_POST3_DIV_MASK) >> 16));
    561 
    562     usleep(5000); /* let the clock lock */
    563 
    564     OUTPLLP(pScrn, R128_VCLK_ECP_CNTL,
    565         R128_VCLK_SRC_SEL_PPLLCLK,
    566         ~(R128_VCLK_SRC_SEL_MASK));
    567 
    568 }
    569 
    570 /* Write PLL2 registers. */
    571 void R128RestorePLL2Registers(ScrnInfoPtr pScrn, R128SavePtr restore)
    572 {
    573     R128InfoPtr info        = R128PTR(pScrn);
    574     unsigned char *R128MMIO = info->MMIO;
    575 
    576     OUTPLLP(pScrn, R128_V2CLK_VCLKTV_CNTL,
    577         R128_V2CLK_SRC_SEL_CPUCLK,
    578         ~R128_V2CLK_SRC_SEL_MASK);
    579 
    580     OUTPLLP(pScrn,
    581         R128_P2PLL_CNTL,
    582         R128_P2PLL_RESET
    583         | R128_P2PLL_ATOMIC_UPDATE_EN
    584         | R128_P2PLL_VGA_ATOMIC_UPDATE_EN,
    585         ~(R128_P2PLL_RESET
    586           | R128_P2PLL_ATOMIC_UPDATE_EN
    587           | R128_P2PLL_VGA_ATOMIC_UPDATE_EN));
    588 
    589 #if 1
    590     OUTREGP(R128_CLOCK_CNTL_INDEX, 0, R128_PLL2_DIV_SEL_MASK);
    591 #endif
    592 
    593         /*R128PLL2WaitForReadUpdateComplete(pScrn);*/
    594 
    595     OUTPLLP(pScrn, R128_P2PLL_REF_DIV, restore->p2pll_ref_div, ~R128_P2PLL_REF_DIV_MASK);
    596 
    597 /*        R128PLL2WriteUpdate(pScrn);
    598     R128PLL2WaitForReadUpdateComplete(pScrn);*/
    599 
    600     OUTPLLP(pScrn, R128_P2PLL_DIV_0,
    601             restore->p2pll_div_0, ~R128_P2PLL_FB0_DIV_MASK);
    602 
    603 /*    R128PLL2WriteUpdate(pScrn);
    604     R128PLL2WaitForReadUpdateComplete(pScrn);*/
    605 
    606     OUTPLLP(pScrn, R128_P2PLL_DIV_0,
    607             restore->p2pll_div_0, ~R128_P2PLL_POST0_DIV_MASK);
    608 
    609     R128PLL2WriteUpdate(pScrn);
    610     R128PLL2WaitForReadUpdateComplete(pScrn);
    611 
    612     OUTPLL(R128_HTOTAL2_CNTL, restore->htotal_cntl2);
    613 
    614 /*        R128PLL2WriteUpdate(pScrn);*/
    615 
    616     OUTPLLP(pScrn, R128_P2PLL_CNTL, 0, ~(R128_P2PLL_RESET
    617                     | R128_P2PLL_SLEEP
    618                     | R128_P2PLL_ATOMIC_UPDATE_EN
    619                     | R128_P2PLL_VGA_ATOMIC_UPDATE_EN));
    620 
    621     DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
    622                         "Wrote: 0x%08x 0x%08x 0x%08x (0x%08x)\n",
    623                         restore->p2pll_ref_div,
    624                         restore->p2pll_div_0,
    625                         restore->htotal_cntl2,
    626                         INPLL(pScrn, R128_P2PLL_CNTL)));
    627     DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
    628                         "Wrote: rd=%d, fd=%d, pd=%d\n",
    629                         restore->p2pll_ref_div & R128_P2PLL_REF_DIV_MASK,
    630                         restore->p2pll_div_0 & R128_P2PLL_FB0_DIV_MASK,
    631                         (restore->p2pll_div_0 &
    632                                 R128_P2PLL_POST0_DIV_MASK) >>16));
    633 
    634     usleep(5000); /* Let the clock to lock */
    635 
    636     OUTPLLP(pScrn, R128_V2CLK_VCLKTV_CNTL,
    637         R128_V2CLK_SRC_SEL_P2PLLCLK,
    638         ~R128_V2CLK_SRC_SEL_MASK);
    639 
    640 }
    641 
    642 /* Define DDA registers for requested video mode. */
    643 static Bool
    644 R128InitDDARegisters(xf86CrtcPtr crtc, R128SavePtr save,
    645                      R128PLLPtr pll, DisplayModePtr mode)
    646 {
    647     ScrnInfoPtr pScrn = crtc->scrn;
    648     R128InfoPtr info  = R128PTR(pScrn);
    649     xf86OutputPtr output = R128FirstOutput(crtc);
    650     R128OutputPrivatePtr r128_output = output->driver_private;
    651 
    652     int         DisplayFifoWidth = 128;
    653     int         DisplayFifoDepth = 32;
    654     int         XclkFreq;
    655     int         VclkFreq;
    656     int         XclksPerTransfer;
    657     int         XclksPerTransferPrecise;
    658     int         UseablePrecision;
    659     int         Roff;
    660     int         Ron;
    661 
    662     XclkFreq = pll->xclk;
    663 
    664     VclkFreq = R128Div(pll->reference_freq * save->feedback_div,
    665                pll->reference_div * save->post_div);
    666 
    667     if (info->isDFP && !info->isPro2 && r128_output->PanelXRes > 0) {
    668         if (r128_output->PanelXRes != mode->CrtcHDisplay)
    669             VclkFreq = (VclkFreq * mode->CrtcHDisplay) / r128_output->PanelXRes;
    670     }
    671 
    672     XclksPerTransfer = R128Div(XclkFreq * DisplayFifoWidth,
    673                    VclkFreq * (info->CurrentLayout.pixel_bytes * 8));
    674 
    675     UseablePrecision = R128MinBits(XclksPerTransfer) + 1;
    676 
    677     XclksPerTransferPrecise = R128Div((XclkFreq * DisplayFifoWidth)
    678                       << (11 - UseablePrecision),
    679                       VclkFreq * (info->CurrentLayout.pixel_bytes * 8));
    680 
    681     Roff  = XclksPerTransferPrecise * (DisplayFifoDepth - 4);
    682 
    683     Ron   = (4 * info->ram->MB
    684          + 3 * MAX(info->ram->Trcd - 2, 0)
    685          + 2 * info->ram->Trp
    686          + info->ram->Twr
    687          + info->ram->CL
    688          + info->ram->Tr2w
    689          + XclksPerTransfer) << (11 - UseablePrecision);
    690 
    691     if (Ron + info->ram->Rloop >= Roff) {
    692     xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
    693            "(Ron = %d) + (Rloop = %d) >= (Roff = %d)\n",
    694            Ron, info->ram->Rloop, Roff);
    695     return FALSE;
    696     }
    697 
    698     save->dda_config = (XclksPerTransferPrecise
    699             | (UseablePrecision << 16)
    700             | (info->ram->Rloop << 20));
    701 
    702     save->dda_on_off = (Ron << 16) | Roff;
    703 
    704     DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
    705                         "XclkFreq = %d; VclkFreq = %d; "
    706                         "per = %d, %d (usable = %d)\n",
    707                         XclkFreq,
    708                         VclkFreq,
    709                         XclksPerTransfer,
    710                         XclksPerTransferPrecise,
    711                         UseablePrecision));
    712     DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
    713                         "Roff = %d, Ron = %d, Rloop = %d\n",
    714                         Roff, Ron, info->ram->Rloop));
    715 
    716     return TRUE;
    717 }
    718 
    719 /* Define DDA2 registers for requested video mode. */
    720 static Bool
    721 R128InitDDA2Registers(xf86CrtcPtr crtc, R128SavePtr save,
    722                       R128PLLPtr pll, DisplayModePtr mode)
    723 {
    724     ScrnInfoPtr pScrn = crtc->scrn;
    725     R128InfoPtr info  = R128PTR(pScrn);
    726     xf86OutputPtr output = R128FirstOutput(crtc);
    727     R128OutputPrivatePtr r128_output = output->driver_private;
    728 
    729     int         DisplayFifoWidth = 128;
    730     int         DisplayFifoDepth = 32;
    731     int         XclkFreq;
    732     int         VclkFreq;
    733     int         XclksPerTransfer;
    734     int         XclksPerTransferPrecise;
    735     int         UseablePrecision;
    736     int         Roff;
    737     int         Ron;
    738 
    739     XclkFreq = pll->xclk;
    740 
    741     VclkFreq = R128Div(pll->reference_freq * save->feedback_div_2,
    742                pll->reference_div * save->post_div_2);
    743 
    744     if (info->isDFP && !info->isPro2 && r128_output->PanelXRes > 0) {
    745         if (r128_output->PanelXRes != mode->CrtcHDisplay)
    746             VclkFreq = (VclkFreq * mode->CrtcHDisplay) / r128_output->PanelXRes;
    747     }
    748 
    749     XclksPerTransfer = R128Div(XclkFreq * DisplayFifoWidth,
    750                    VclkFreq * (info->CurrentLayout.pixel_bytes * 8));
    751 
    752     UseablePrecision = R128MinBits(XclksPerTransfer) + 1;
    753 
    754     XclksPerTransferPrecise = R128Div((XclkFreq * DisplayFifoWidth)
    755                       << (11 - UseablePrecision),
    756                       VclkFreq * (info->CurrentLayout.pixel_bytes * 8));
    757 
    758     Roff  = XclksPerTransferPrecise * (DisplayFifoDepth - 4);
    759 
    760     Ron   = (4 * info->ram->MB
    761          + 3 * MAX(info->ram->Trcd - 2, 0)
    762          + 2 * info->ram->Trp
    763          + info->ram->Twr
    764          + info->ram->CL
    765          + info->ram->Tr2w
    766          + XclksPerTransfer) << (11 - UseablePrecision);
    767 
    768 
    769     if (Ron + info->ram->Rloop >= Roff) {
    770     xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
    771            "(Ron = %d) + (Rloop = %d) >= (Roff = %d)\n",
    772            Ron, info->ram->Rloop, Roff);
    773     return FALSE;
    774     }
    775 
    776     save->dda2_config = (XclksPerTransferPrecise
    777             | (UseablePrecision << 16)
    778             | (info->ram->Rloop << 20));
    779 
    780     /*save->dda2_on_off = (Ron << 16) | Roff;*/
    781     /* shift most be 18 otherwise there's corruption on crtc2 */
    782     save->dda2_on_off = (Ron << 18) | Roff;
    783 
    784     DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
    785                         "XclkFreq = %d; VclkFreq = %d; "
    786                         "per = %d, %d (usable = %d)\n",
    787                         XclkFreq,
    788                         VclkFreq,
    789                         XclksPerTransfer,
    790                         XclksPerTransferPrecise,
    791                         UseablePrecision));
    792     DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
    793                         "Roff = %d, Ron = %d, Rloop = %d\n",
    794                         Roff, Ron, info->ram->Rloop));
    795 
    796     return TRUE;
    797 }
    798 
    799 static void r128_crtc_load_lut(xf86CrtcPtr crtc);
    800 
    801 static void r128_crtc_dpms(xf86CrtcPtr crtc, int mode)
    802 {
    803     int mask;
    804     ScrnInfoPtr pScrn = crtc->scrn;
    805     R128InfoPtr info = R128PTR(pScrn);
    806     unsigned char *R128MMIO = info->MMIO;
    807     R128CrtcPrivatePtr r128_crtc = crtc->driver_private;
    808 
    809     /* XXX: The HSYNC and VSYNC bits for CRTC2 don't exist on the r128? */
    810     mask = r128_crtc->crtc_id ? R128_CRTC2_DISP_DIS : (R128_CRTC_DISPLAY_DIS | R128_CRTC_HSYNC_DIS | R128_CRTC_VSYNC_DIS);
    811 
    812     switch (mode) {
    813     case DPMSModeOn:
    814         if (r128_crtc->crtc_id) {
    815             OUTREGP(R128_CRTC2_GEN_CNTL, 0, ~mask);
    816         } else {
    817             OUTREGP(R128_CRTC_EXT_CNTL, 0, ~mask);
    818         }
    819         break;
    820     case DPMSModeStandby:
    821         if (r128_crtc->crtc_id) {
    822             OUTREGP(R128_CRTC2_GEN_CNTL, R128_CRTC2_DISP_DIS, ~mask);
    823         } else {
    824             OUTREGP(R128_CRTC_EXT_CNTL, (R128_CRTC_DISPLAY_DIS | R128_CRTC_HSYNC_DIS), ~mask);
    825         }
    826         break;
    827     case DPMSModeSuspend:
    828         if (r128_crtc->crtc_id) {
    829             OUTREGP(R128_CRTC2_GEN_CNTL, R128_CRTC2_DISP_DIS, ~mask);
    830         } else {
    831             OUTREGP(R128_CRTC_EXT_CNTL, (R128_CRTC_DISPLAY_DIS | R128_CRTC_VSYNC_DIS), ~mask);
    832         }
    833         break;
    834     case DPMSModeOff:
    835         if (r128_crtc->crtc_id) {
    836             OUTREGP(R128_CRTC2_GEN_CNTL, mask, ~mask);
    837         } else {
    838             OUTREGP(R128_CRTC_EXT_CNTL, mask, ~mask);
    839         }
    840         break;
    841     }
    842 
    843     if (mode != DPMSModeOn) {
    844         if (r128_crtc->crtc_id) {
    845             OUTREGP(R128_CRTC2_GEN_CNTL, 0, ~R128_CRTC2_EN);
    846         } else {
    847             OUTREGP(R128_CRTC_GEN_CNTL, 0, ~R128_CRTC_EN);
    848         }
    849     } else {
    850         if (r128_crtc->crtc_id) {
    851             OUTREGP(R128_CRTC2_GEN_CNTL, R128_CRTC2_EN, ~R128_CRTC2_EN);
    852         } else {
    853             OUTREGP(R128_CRTC_GEN_CNTL, R128_CRTC_EN, ~R128_CRTC_EN);
    854         }
    855     }
    856 
    857     if (mode != DPMSModeOff)
    858         r128_crtc_load_lut(crtc);
    859 }
    860 
    861 void r128_crtc_load_lut(xf86CrtcPtr crtc)
    862 {
    863     ScrnInfoPtr pScrn = crtc->scrn;
    864     R128InfoPtr info = R128PTR(pScrn);
    865     unsigned char *R128MMIO = info->MMIO;
    866     R128CrtcPrivatePtr r128_crtc = crtc->driver_private;
    867     int i;
    868 
    869     if (!crtc->enabled)
    870         return;
    871 
    872     PAL_SELECT(r128_crtc->crtc_id);
    873 
    874     for (i = 0; i < 256; i++) {
    875         OUTPAL(i, r128_crtc->lut_r[i], r128_crtc->lut_g[i], r128_crtc->lut_b[i]);
    876     }
    877 }
    878 
    879 static Bool r128_crtc_mode_fixup(xf86CrtcPtr crtc, DisplayModePtr mode, DisplayModePtr adjusted_mode)
    880 {
    881     return TRUE;
    882 }
    883 
    884 static void r128_crtc_mode_prepare(xf86CrtcPtr crtc)
    885 {
    886     r128_crtc_dpms(crtc, DPMSModeOff);
    887 }
    888 
    889 static void r128_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode, DisplayModePtr adjusted_mode, int x, int y)
    890 {
    891     ScrnInfoPtr pScrn = crtc->scrn;
    892     R128CrtcPrivatePtr r128_crtc = crtc->driver_private;
    893     R128InfoPtr info = R128PTR(pScrn);
    894     double dot_clock = adjusted_mode->Clock / 1000.0;
    895 
    896     if (r128_crtc->cursor_offset) r128_crtc_hide_cursor(crtc);
    897     xf86PrintModeline(pScrn->scrnIndex, adjusted_mode);
    898     R128InitCommonRegisters(&info->ModeReg, info);
    899 
    900     switch (r128_crtc->crtc_id) {
    901     case 0:
    902         R128InitCrtcRegisters(crtc, &info->ModeReg, adjusted_mode);
    903 	R128InitCrtcBase(crtc, &info->ModeReg, x, y);
    904         if (dot_clock) {
    905             R128InitPLLRegisters(crtc, &info->ModeReg, &info->pll, dot_clock);
    906             R128InitDDARegisters(crtc, &info->ModeReg, &info->pll, adjusted_mode);
    907         } else {
    908             info->ModeReg.ppll_ref_div         = info->SavedReg.ppll_ref_div;
    909             info->ModeReg.ppll_div_3           = info->SavedReg.ppll_div_3;
    910             info->ModeReg.htotal_cntl          = info->SavedReg.htotal_cntl;
    911             info->ModeReg.dda_config           = info->SavedReg.dda_config;
    912             info->ModeReg.dda_on_off           = info->SavedReg.dda_on_off;
    913         }
    914         break;
    915     case 1:
    916         R128InitCrtc2Registers(crtc, &info->ModeReg, adjusted_mode);
    917 	R128InitCrtc2Base(crtc, &info->ModeReg, x, y);
    918         if (dot_clock) {
    919             R128InitPLL2Registers(crtc, &info->ModeReg, &info->pll, dot_clock);
    920             R128InitDDA2Registers(crtc, &info->ModeReg, &info->pll, adjusted_mode);
    921         }
    922         break;
    923     }
    924 
    925     R128RestoreCommonRegisters(pScrn, &info->ModeReg);
    926 
    927     switch (r128_crtc->crtc_id) {
    928     case 0:
    929         R128RestoreDDARegisters(pScrn, &info->ModeReg);
    930         R128RestoreCrtcRegisters(pScrn, &info->ModeReg);
    931         R128RestorePLLRegisters(pScrn, &info->ModeReg);
    932         break;
    933     case 1:
    934         R128RestoreDDA2Registers(pScrn, &info->ModeReg);
    935         R128RestoreCrtc2Registers(pScrn, &info->ModeReg);
    936         R128RestorePLL2Registers(pScrn, &info->ModeReg);
    937 	break;
    938     }
    939 
    940     if (r128_crtc->cursor_offset) r128_crtc_show_cursor(crtc);
    941 }
    942 
    943 static void r128_crtc_mode_commit(xf86CrtcPtr crtc)
    944 {
    945     r128_crtc_dpms(crtc, DPMSModeOn);
    946 }
    947 
    948 static void r128_crtc_gamma_set(xf86CrtcPtr crtc, uint16_t *red, uint16_t *green, uint16_t *blue, int size)
    949 {
    950     R128CrtcPrivatePtr r128_crtc = crtc->driver_private;
    951     int i;
    952 
    953     for (i = 0; i < 256; i++) {
    954         r128_crtc->lut_r[i] = red[i] >> 8;
    955         r128_crtc->lut_g[i] = green[i] >> 8;
    956         r128_crtc->lut_b[i] = blue[i] >> 8;
    957     }
    958 
    959     r128_crtc_load_lut(crtc);
    960 }
    961 
    962 static Bool r128_crtc_lock(xf86CrtcPtr crtc)
    963 {
    964     ScrnInfoPtr   pScrn   = crtc->scrn;
    965     ScreenPtr     pScreen = xf86ScrnToScreen(pScrn);
    966     R128InfoPtr   info    = R128PTR(pScrn);
    967 
    968 #ifdef USE_EXA
    969     if (info->ExaDriver) exaWaitSync(pScreen);
    970 #endif
    971 
    972     return FALSE;
    973 }
    974 
    975 static void r128_crtc_unlock(xf86CrtcPtr crtc)
    976 {
    977     ScrnInfoPtr   pScrn   = crtc->scrn;
    978     ScreenPtr     pScreen = xf86ScrnToScreen(pScrn);
    979     R128InfoPtr   info    = R128PTR(pScrn);
    980 
    981 #ifdef USE_EXA
    982     if (info->ExaDriver) exaWaitSync(pScreen);
    983 #endif
    984 }
    985 
    986 static void *r128_crtc_shadow_allocate(xf86CrtcPtr crtc, int width, int height)
    987 {
    988     ScrnInfoPtr   pScrn   = crtc->scrn;
    989     R128InfoPtr   info    = R128PTR(pScrn);
    990 
    991     R128CrtcPrivatePtr r128_crtc = crtc->driver_private;
    992     unsigned long rotate_offset = 0;
    993     unsigned long rotate_pitch;
    994     int cpp = pScrn->bitsPerPixel / 8;
    995     int align = 4096;
    996     int size;
    997 
    998     rotate_pitch = pScrn->displayWidth * cpp;
    999     size = rotate_pitch * height;
   1000     rotate_offset = R128AllocateMemory(pScrn, &(r128_crtc->rotate_mem), size, align, TRUE);
   1001 
   1002     /* If allocations failed or if there was no accel. */
   1003     if (rotate_offset == 0)
   1004         return NULL;
   1005 
   1006     return info->FB + rotate_offset;
   1007 }
   1008 
   1009 static PixmapPtr r128_crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height)
   1010 {
   1011     ScrnInfoPtr pScrn = crtc->scrn;
   1012     PixmapPtr rotate_pixmap;
   1013     unsigned long rotate_pitch;
   1014     int cpp = pScrn->bitsPerPixel / 8;
   1015 
   1016     if (!data) data = r128_crtc_shadow_allocate(crtc, width, height);
   1017 
   1018     rotate_pitch = pScrn->displayWidth * cpp;
   1019     rotate_pixmap = GetScratchPixmapHeader(xf86ScrnToScreen(pScrn),
   1020                                            width, height,
   1021                                            pScrn->depth,
   1022                                            pScrn->bitsPerPixel,
   1023                                            rotate_pitch,
   1024                                            data);
   1025 
   1026     if (rotate_pixmap == NULL) {
   1027         xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
   1028                    "Couldn't allocate shadow memory for rotated CRTC\n");
   1029         return NULL;
   1030     }
   1031 
   1032     return rotate_pixmap;
   1033 }
   1034 
   1035 static void r128_crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data)
   1036 {
   1037     ScrnInfoPtr   pScrn   = crtc->scrn;
   1038     ScreenPtr     pScreen = xf86ScrnToScreen(pScrn);
   1039     R128InfoPtr   info    = R128PTR(pScrn);
   1040 
   1041     R128CrtcPrivatePtr r128_crtc = crtc->driver_private;
   1042 
   1043     if (rotate_pixmap) FreeScratchPixmapHeader(rotate_pixmap);
   1044 
   1045     if (data && r128_crtc->rotate_mem != NULL) {
   1046 #ifdef USE_EXA
   1047         if (info->ExaDriver)
   1048             exaOffscreenFree(pScreen, (ExaOffscreenArea *) r128_crtc->rotate_mem);
   1049 #endif
   1050         r128_crtc->rotate_mem = NULL;
   1051     }
   1052 }
   1053 
   1054 static const xf86CrtcFuncsRec r128_crtc_funcs = {
   1055     .dpms = r128_crtc_dpms,
   1056     .save = NULL,
   1057     .restore = NULL,
   1058     .mode_fixup = r128_crtc_mode_fixup,
   1059     .prepare = r128_crtc_mode_prepare,
   1060     .mode_set = r128_crtc_mode_set,
   1061     .commit = r128_crtc_mode_commit,
   1062     .gamma_set = r128_crtc_gamma_set,
   1063     .lock = r128_crtc_lock,
   1064     .unlock = r128_crtc_unlock,
   1065     .shadow_create = r128_crtc_shadow_create,
   1066     .shadow_allocate = r128_crtc_shadow_allocate,
   1067     .shadow_destroy = r128_crtc_shadow_destroy,
   1068     .set_cursor_colors = r128_crtc_set_cursor_colors,
   1069     .set_cursor_position = r128_crtc_set_cursor_position,
   1070     .show_cursor = r128_crtc_show_cursor,
   1071     .hide_cursor = r128_crtc_hide_cursor,
   1072     .load_cursor_image = r128_crtc_load_cursor_image,
   1073     .destroy = NULL,
   1074 };
   1075 
   1076 Bool R128AllocateControllers(ScrnInfoPtr pScrn)
   1077 {
   1078     R128EntPtr pR128Ent = R128EntPriv(pScrn);
   1079 
   1080     if (pR128Ent->Controller[0])
   1081         return TRUE;
   1082 
   1083     pR128Ent->pCrtc[0] = xf86CrtcCreate(pScrn, &r128_crtc_funcs);
   1084     if (!pR128Ent->pCrtc[0])
   1085         return FALSE;
   1086 
   1087     pR128Ent->Controller[0] = XNFcallocarray(1, sizeof(R128CrtcPrivateRec));
   1088     if (!pR128Ent->Controller[0])
   1089         return FALSE;
   1090 
   1091     pR128Ent->pCrtc[0]->driver_private = pR128Ent->Controller[0];
   1092     pR128Ent->Controller[0]->crtc_id = 0;
   1093 
   1094     if (!pR128Ent->HasCRTC2)
   1095         return TRUE;
   1096 
   1097     pR128Ent->pCrtc[1] = xf86CrtcCreate(pScrn, &r128_crtc_funcs);
   1098     if (!pR128Ent->pCrtc[1])
   1099         return FALSE;
   1100 
   1101     pR128Ent->Controller[1] = XNFcallocarray(1, sizeof(R128CrtcPrivateRec));
   1102     if (!pR128Ent->Controller[1]) {
   1103         free(pR128Ent->Controller[0]);
   1104         return FALSE;
   1105     }
   1106 
   1107     pR128Ent->pCrtc[1]->driver_private = pR128Ent->Controller[1];
   1108     pR128Ent->Controller[1]->crtc_id = 1;
   1109 
   1110     return TRUE;
   1111 }
   1112 
   1113 void R128Blank(ScrnInfoPtr pScrn)
   1114 {
   1115     xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
   1116     xf86OutputPtr output;
   1117     xf86CrtcPtr crtc;
   1118     int o, c;
   1119 
   1120     for (c = 0; c < xf86_config->num_crtc; c++) {
   1121         crtc = xf86_config->crtc[c];
   1122         for (o = 0; o < xf86_config->num_output; o++) {
   1123             output = xf86_config->output[o];
   1124             if (output->crtc != crtc)
   1125                 continue;
   1126 
   1127             output->funcs->dpms(output, DPMSModeOff);
   1128         }
   1129         crtc->funcs->dpms(crtc, DPMSModeOff);
   1130     }
   1131 }
   1132 
   1133 void R128Unblank(ScrnInfoPtr pScrn)
   1134 {
   1135     xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
   1136     xf86OutputPtr output;
   1137     xf86CrtcPtr crtc;
   1138     int o, c;
   1139 
   1140     for (c = 0; c < xf86_config->num_crtc; c++) {
   1141         crtc = xf86_config->crtc[c];
   1142         if (!crtc->enabled)
   1143             continue;
   1144         crtc->funcs->dpms(crtc, DPMSModeOn);
   1145         for (o = 0; o < xf86_config->num_output; o++) {
   1146             output = xf86_config->output[o];
   1147             if (output->crtc != crtc)
   1148                 continue;
   1149 
   1150             output->funcs->dpms(output, DPMSModeOn);
   1151         }
   1152     }
   1153 }
   1154