Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright 2007, 2008  Luc Verhaegen <lverhaegen@novell.com>
  3.  * Copyright 2007, 2008  Matthias Hopf <mhopf@novell.com>
  4.  * Copyright 2007, 2008  Egbert Eich   <eich@novell.com>
  5.  * Copyright 2007, 2008  Advanced Micro Devices, Inc.
  6.  *
  7.  * Permission is hereby granted, free of charge, to any person obtaining a
  8.  * copy of this software and associated documentation files (the "Software"),
  9.  * to deal in the Software without restriction, including without limitation
  10.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  11.  * and/or sell copies of the Software, and to permit persons to whom the
  12.  * Software is furnished to do so, subject to the following conditions:
  13.  *
  14.  * The above copyright notice and this permission notice shall be included in
  15.  * all copies or substantial portions of the Software.
  16.  *
  17.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  20.  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
  21.  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  22.  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  23.  * OTHER DEALINGS IN THE SOFTWARE.
  24.  */
  25.  
  26. #ifdef HAVE_CONFIG_H
  27. #include "config.h"
  28. #endif
  29.  
  30. #include "xf86.h"
  31.  
  32. /* for usleep */
  33. #if HAVE_XF86_ANSIC_H
  34. # include "xf86_ansic.h"
  35. #else
  36. # include <unistd.h>
  37. #endif
  38.  
  39. #include "rhd.h"
  40. #include "rhd_crtc.h"
  41. #include "rhd_pll.h"
  42. #include "rhd_lut.h"
  43. #include "rhd_regs.h"
  44. #include "rhd_modes.h"
  45. #include "rhd_mc.h"
  46. #ifdef ATOM_BIOS
  47. # include "rhd_atombios.h"
  48. #endif
  49.  
  50. #define D1_REG_OFFSET 0x0000
  51. #define D2_REG_OFFSET 0x0800
  52. #define FMT1_REG_OFFSET 0x0000
  53. #define FMT2_REG_OFFSET 0x800
  54.  
  55. struct rhdCrtcFMTPrivate {
  56.     CARD32 StoreControl;
  57.     CARD32 StoreBitDepthControl;
  58.     CARD32 StoreClampCntl;
  59. };
  60.  
  61. struct rhdCrtcFBPrivate {
  62.     CARD32 StoreGrphEnable;
  63.     CARD32 StoreGrphControl;
  64.     CARD32 StoreGrphXStart;
  65.     CARD32 StoreGrphYStart;
  66.     CARD32 StoreGrphXEnd;
  67.     CARD32 StoreGrphYEnd;
  68.     CARD32 StoreGrphSwap;
  69.     CARD32 StoreGrphPrimarySurfaceAddress;
  70.     CARD32 StoreGrphSurfaceOffsetX;
  71.     CARD32 StoreGrphSurfaceOffsetY;
  72.     CARD32 StoreGrphPitch;
  73.     CARD32 StoreModeDesktopHeight;
  74. };
  75.  
  76. struct rhdCrtcLUTPrivate {
  77.     CARD32 StoreGrphLutSel;
  78. };
  79.  
  80. struct rhdCrtcScalePrivate {
  81.     CARD32 StoreModeViewPortSize;
  82.  
  83.     CARD32 StoreModeOverScanH;
  84.     CARD32 StoreModeOverScanV;
  85.  
  86.     CARD32 StoreModeViewPortStart;
  87.     CARD32 StoreScaleEnable;
  88.     CARD32 StoreScaleTapControl;
  89.     CARD32 StoreModeCenter;
  90.     CARD32 StoreScaleHV;
  91.     CARD32 StoreScaleHFilter;
  92.     CARD32 StoreScaleVFilter;
  93.     CARD32 StoreScaleDither;
  94. };
  95.  
  96. struct rhdCrtcModePrivate {
  97.     CARD32 StoreCrtcControl;
  98.  
  99.     CARD32 StoreCrtcHTotal;
  100.     CARD32 StoreCrtcHBlankStartEnd;
  101.     CARD32 StoreCrtcHSyncA;
  102.     CARD32 StoreCrtcHSyncACntl;
  103.     CARD32 StoreCrtcHSyncB;
  104.     CARD32 StoreCrtcHSyncBCntl;
  105.  
  106.     CARD32 StoreCrtcVTotal;
  107.     CARD32 StoreCrtcVBlankStartEnd;
  108.     CARD32 StoreCrtcVSyncA;
  109.     CARD32 StoreCrtcVSyncACntl;
  110.     CARD32 StoreCrtcVSyncB;
  111.     CARD32 StoreCrtcVSyncBCntl;
  112.     CARD32 StoreCrtcCountControl;
  113.  
  114.     CARD32 StoreModeDataFormat;
  115.     CARD32 StoreCrtcInterlaceControl;
  116.  
  117.     CARD32 StoreCrtcBlackColor;
  118.     CARD32 StoreCrtcBlankControl;
  119. };
  120.  
  121. /*
  122.  * Checks whether Width, Height are within boundaries.
  123.  * If MODE_OK is returned and pPitch is not NULL, it is set.
  124.  */
  125. static ModeStatus
  126. DxFBValid(struct rhdCrtc *Crtc, CARD16 Width, CARD16 Height, int bpp,
  127.           CARD32 Offset, CARD32 Size, CARD32 *pPitch)
  128. {
  129.     RHDPtr rhdPtr = RHDPTRI(Crtc);
  130.     ScrnInfoPtr pScrn = rhdPtr->pScrn;
  131.  
  132.     CARD16 Pitch;
  133.     unsigned int BytesPerPixel;
  134.     CARD8 PitchMask = 0xFF;
  135.  
  136.     RHDDebug(Crtc->scrnIndex, "FUNCTION: %s: %s\n", __func__, Crtc->Name);
  137.  
  138.     /* If we hit this, then the memory claimed so far is not properly aligned */
  139.     if (Offset & 0xFFF) {
  140.         xf86DrvMsg(Crtc->scrnIndex, X_ERROR, "%s: Offset (0x%08X) is invalid!\n",
  141.                    __func__, (int) Offset);
  142.       return MODE_ERROR;
  143.     }
  144.  
  145.     switch (pScrn->bitsPerPixel) {
  146.       case 8:
  147.         BytesPerPixel = 1;
  148.         break;
  149.       case 15:
  150.       case 16:
  151.         BytesPerPixel = 2;
  152.         PitchMask /= BytesPerPixel;
  153.         break;
  154.      case 24:
  155.      case 32:
  156.        BytesPerPixel = 4;
  157.        PitchMask /= BytesPerPixel;
  158.        break;
  159.      default:
  160.         xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "%s: %dbpp is not implemented!\n",
  161.                    __func__, pScrn->bitsPerPixel);
  162.        return MODE_BAD;
  163.     }
  164.  
  165.     if((Width==720)&&(Height==400))    //skip textmode
  166.       return MODE_BAD;
  167.  
  168.      /* Be reasonable */
  169.     if (Width < 640)
  170.       return MODE_H_ILLEGAL;
  171.     if (Height < 480)
  172.       return MODE_V_ILLEGAL;
  173.  
  174.     /* D1GRPH_X_START is 14bits while D1_MODE_VIEWPORT_X_START is only 13 bits.
  175.      * Since it is reasonable to assume that modes will be at least 1x1
  176.      * limit at 13bits + 1 */
  177.     if (Width > 0x2000)
  178.       return MODE_VIRTUAL_X;
  179.  
  180.     /* D1GRPH_Y_START is 14bits while D1_MODE_VIEWPORT_Y_START is only 13 bits.
  181.      * Since it is reasonable to assume that modes will be at least 1x1
  182.      * limit at 13bits + 1 */
  183.     if (Height > 0x2000)
  184.       return MODE_VIRTUAL_Y;
  185.  
  186.     Pitch = (Width + PitchMask) & ~PitchMask;
  187.     /* D1_PITCH limit: should never happen after clamping Width to 0x2000 */
  188.     if (Pitch >= 0x4000)
  189.       return MODE_VIRTUAL_X;
  190.  
  191.     if ((Pitch * BytesPerPixel * Height) > Size)
  192.       return MODE_MEM_VIRT;
  193.  
  194.     if (pPitch)
  195.       *pPitch = Pitch;
  196.     return MODE_OK;
  197. }
  198.  
  199. /*
  200.  *
  201.  */
  202. static void
  203. DxFBSet(struct rhdCrtc *Crtc, CARD16 Pitch, CARD16 Width, CARD16 Height,
  204.         int bpp, CARD32 Offset)
  205. {
  206.     RHDPtr rhdPtr = RHDPTRI(Crtc);
  207.     CARD16 RegOff;
  208.  
  209.     RHDDebug(Crtc->scrnIndex, "FUNCTION: %s: %s (%i[%i]x%i@%ibpp)  +0x%x )\n",
  210.              __func__, Crtc->Name, Width, Pitch, Height, bpp, Offset);
  211.  
  212.     if (Crtc->Id == RHD_CRTC_1)
  213.       RegOff = D1_REG_OFFSET;
  214.     else
  215.       RegOff = D2_REG_OFFSET;
  216.  
  217.     RHDRegMask(Crtc, RegOff + D1GRPH_ENABLE, 1, 0x00000001);
  218.  
  219.     /* disable R/B swap, disable tiling, disable 16bit alpha, etc. */
  220.     RHDRegWrite(Crtc, RegOff + D1GRPH_CONTROL, 0);
  221.  
  222.     switch (bpp) {
  223.       case 8:
  224.         RHDRegMask(Crtc, RegOff + D1GRPH_CONTROL, 0, 0x00000703);
  225.         break;
  226.       case 15:
  227.         RHDRegMask(Crtc, RegOff + D1GRPH_CONTROL, 0x000001, 0x00000703);
  228.         break;
  229.       case 16:
  230.         RHDRegMask(Crtc, RegOff + D1GRPH_CONTROL, 0x000101, 0x00000703);
  231.         break;
  232.       case 24:
  233.       case 32:
  234.         default:
  235.         RHDRegMask(Crtc, RegOff + D1GRPH_CONTROL, 0x000002, 0x00000703);
  236.         break;
  237.     /* TODO: 64bpp ;p */
  238.     }
  239.  
  240.     /* Make sure that we are not swapping colours around */
  241.     if (rhdPtr->ChipSet > RHD_R600)
  242.       RHDRegWrite(Crtc, RegOff + D1GRPH_SWAP_CNTL, 0);
  243.     /* R5xx - RS690 case is GRPH_CONTROL bit 16 */
  244.  
  245.     RHDRegWrite(Crtc, RegOff + D1GRPH_PRIMARY_SURFACE_ADDRESS,
  246.                 rhdPtr->FbIntAddress + Offset);
  247.     RHDRegWrite(Crtc, RegOff + D1GRPH_PITCH, Pitch);
  248.     RHDRegWrite(Crtc, RegOff + D1GRPH_SURFACE_OFFSET_X, 0);
  249.     RHDRegWrite(Crtc, RegOff + D1GRPH_SURFACE_OFFSET_Y, 0);
  250.     RHDRegWrite(Crtc, RegOff + D1GRPH_X_START, 0);
  251.     RHDRegWrite(Crtc, RegOff + D1GRPH_Y_START, 0);
  252.     RHDRegWrite(Crtc, RegOff + D1GRPH_X_END, Width);
  253.     RHDRegWrite(Crtc, RegOff + D1GRPH_Y_END, Height);
  254.  
  255.     /* D1Mode registers */
  256.     RHDRegWrite(Crtc, RegOff + D1MODE_DESKTOP_HEIGHT, Height);
  257.  
  258.     Crtc->Pitch = Pitch;
  259.     Crtc->Width = Width;
  260.     Crtc->Height = Height;
  261.     Crtc->bpp = bpp;
  262.     Crtc->Offset = Offset;
  263. }
  264.  
  265. /*
  266.  *
  267.  */
  268. static void
  269. DxFBSave(struct rhdCrtc *Crtc)
  270. {
  271.     struct rhdCrtcFBPrivate *FBPriv;
  272.     CARD32 RegOff;
  273.  
  274.     if (!Crtc->FBPriv)
  275.         FBPriv = xnfcalloc(1, sizeof(struct rhdCrtcFBPrivate));
  276.     else
  277.         FBPriv = Crtc->FBPriv;
  278.  
  279.     if (Crtc->Id == RHD_CRTC_1)
  280.         RegOff = D1_REG_OFFSET;
  281.     else
  282.         RegOff = D2_REG_OFFSET;
  283.  
  284.     FBPriv->StoreGrphEnable = RHDRegRead(Crtc, RegOff + D1GRPH_ENABLE);
  285.     FBPriv->StoreGrphControl = RHDRegRead(Crtc, RegOff + D1GRPH_CONTROL);
  286.     FBPriv->StoreGrphXStart = RHDRegRead(Crtc, RegOff + D1GRPH_X_START);
  287.     FBPriv->StoreGrphYStart = RHDRegRead(Crtc, RegOff + D1GRPH_Y_START);
  288.     FBPriv->StoreGrphXEnd = RHDRegRead(Crtc, RegOff + D1GRPH_X_END);
  289.     FBPriv->StoreGrphYEnd = RHDRegRead(Crtc, RegOff + D1GRPH_Y_END);
  290.     if (RHDPTRI(Crtc)->ChipSet >= RHD_R600)
  291.         FBPriv->StoreGrphSwap = RHDRegRead(Crtc, RegOff + D1GRPH_SWAP_CNTL);
  292.     FBPriv->StoreGrphPrimarySurfaceAddress =
  293.         RHDRegRead(Crtc, RegOff + D1GRPH_PRIMARY_SURFACE_ADDRESS);
  294.     FBPriv->StoreGrphSurfaceOffsetX =
  295.         RHDRegRead(Crtc, RegOff + D1GRPH_SURFACE_OFFSET_X);
  296.     FBPriv->StoreGrphSurfaceOffsetY =
  297.         RHDRegRead(Crtc, RegOff + D1GRPH_SURFACE_OFFSET_Y);
  298.     FBPriv->StoreGrphPitch = RHDRegRead(Crtc, RegOff + D1GRPH_PITCH);
  299.     FBPriv->StoreModeDesktopHeight = RHDRegRead(Crtc, RegOff + D1MODE_DESKTOP_HEIGHT);
  300.  
  301.     Crtc->FBPriv = FBPriv;
  302. }
  303.  
  304. /*
  305.  *
  306.  */
  307. static void
  308. DxFBRestore(struct rhdCrtc *Crtc)
  309. {
  310.     struct rhdCrtcFBPrivate *FBPriv = Crtc->FBPriv;
  311.     CARD32 RegOff;
  312.  
  313.     if (!FBPriv) {
  314.         xf86DrvMsg(Crtc->scrnIndex, X_ERROR, "%s: no registers stored!\n",
  315.                    __func__);
  316.         return;
  317.     }
  318.  
  319.     if (Crtc->Id == RHD_CRTC_1)
  320.         RegOff = D1_REG_OFFSET;
  321.     else
  322.         RegOff = D2_REG_OFFSET;
  323.  
  324.     /* FBSet */
  325.     RHDRegWrite(Crtc, RegOff + D1GRPH_CONTROL, FBPriv->StoreGrphControl);
  326.     RHDRegWrite(Crtc, RegOff + D1GRPH_X_START, FBPriv->StoreGrphXStart);
  327.     RHDRegWrite(Crtc, RegOff + D1GRPH_Y_START, FBPriv->StoreGrphYStart);
  328.     RHDRegWrite(Crtc, RegOff + D1GRPH_X_END, FBPriv->StoreGrphXEnd);
  329.     RHDRegWrite(Crtc, RegOff + D1GRPH_Y_END, FBPriv->StoreGrphYEnd);
  330.     if (RHDPTRI(Crtc)->ChipSet >= RHD_R600)
  331.         RHDRegWrite(Crtc, RegOff + D1GRPH_SWAP_CNTL, FBPriv->StoreGrphSwap);
  332.  
  333.     /* disable read requests */
  334.     RHDRegMask(Crtc, RegOff + D1CRTC_CONTROL, 0x01000000, 0x01000000);
  335.     RHDRegMask(Crtc, RegOff + D1GRPH_ENABLE, 0, 0x00000001);
  336.     usleep (10);
  337.  
  338.     RHDRegWrite(Crtc, RegOff + D1GRPH_PRIMARY_SURFACE_ADDRESS,
  339.                 FBPriv->StoreGrphPrimarySurfaceAddress);
  340.     usleep(10);
  341.  
  342.     RHDRegWrite(Crtc, RegOff + D1GRPH_ENABLE, FBPriv->StoreGrphEnable);
  343.  
  344.     RHDRegWrite(Crtc, RegOff + D1GRPH_SURFACE_OFFSET_X,
  345.                 FBPriv->StoreGrphSurfaceOffsetX);
  346.     RHDRegWrite(Crtc, RegOff + D1GRPH_SURFACE_OFFSET_Y,
  347.                 FBPriv->StoreGrphSurfaceOffsetY);
  348.  
  349.     RHDRegWrite(Crtc, RegOff + D1GRPH_PITCH, FBPriv->StoreGrphPitch);
  350.     RHDRegWrite(Crtc, RegOff + D1MODE_DESKTOP_HEIGHT, FBPriv->StoreModeDesktopHeight);
  351. }
  352.  
  353. /*
  354.  *
  355.  */
  356. static void
  357. DxFBDestroy(struct rhdCrtc *Crtc)
  358. {
  359.     if (Crtc->FBPriv)
  360.         xfree(Crtc->FBPriv);
  361.     Crtc->FBPriv = NULL;
  362. }
  363.  
  364. /*
  365.  *
  366.  */
  367. static ModeStatus
  368. DxModeValid(struct rhdCrtc *Crtc, DisplayModePtr Mode)
  369. {
  370.   CARD32 tmp;
  371.  
  372.     RHDDebug(Crtc->scrnIndex, "%s: %s\n", __func__, Crtc->Name);
  373.  
  374.     /* Work around HW bug: need at least 2 lines of front porch
  375.        for interlaced mode */
  376.     if ((Mode->Flags & V_INTERLACE)
  377.         && (Mode->CrtcVSyncStart < (Mode->CrtcVDisplay + 2))) {
  378.         Mode->CrtcVSyncStart = Mode->CrtcVDisplay + 2;
  379.         Mode->CrtcVAdjusted = TRUE;
  380.     }
  381.  
  382.     /* D1CRTC_H_TOTAL - 1 : 13bits */
  383.   if (Mode->CrtcHTotal > 0x2000)
  384.     return MODE_BAD_HVALUE;
  385.  
  386.   tmp = Mode->CrtcHTotal + Mode->CrtcHBlankStart - Mode->CrtcHSyncStart;
  387.     /* D1CRTC_H_BLANK_START: 13bits */
  388.   if (tmp >= 0x2000)
  389.     return MODE_BAD_HVALUE;
  390.  
  391.   tmp = Mode->CrtcHBlankEnd - Mode->CrtcHSyncStart;
  392.     /* D1CRTC_H_BLANK_END: 13bits */
  393.   if (tmp >= 0x2000)
  394.     return MODE_BAD_HVALUE;
  395.  
  396.   tmp = Mode->CrtcHSyncEnd - Mode->CrtcHSyncStart;
  397.     /* D1CRTC_H_SYNC_A_END: 13bits */
  398.   if (tmp >= 0x2000)
  399.     return MODE_HSYNC_WIDE;
  400.  
  401.     /* D1CRTC_V_TOTAL - 1 : 13bits */
  402.   if (Mode->CrtcVTotal > 0x2000)
  403.     return MODE_BAD_VVALUE;
  404.  
  405.   tmp = Mode->CrtcVTotal + Mode->CrtcVBlankStart - Mode->CrtcVSyncStart;
  406.     /* D1CRTC_V_BLANK_START: 13bits */
  407.   if (tmp >= 0x2000)
  408.     return MODE_BAD_VVALUE;
  409.  
  410.   tmp = Mode->CrtcVBlankEnd - Mode->CrtcVSyncStart;
  411.     /* D1CRTC_V_BLANK_END: 13bits */
  412.   if (tmp >= 0x2000)
  413.     return MODE_BAD_VVALUE;
  414.  
  415.   tmp = Mode->CrtcVSyncEnd - Mode->CrtcVSyncStart;
  416.     /* D1CRTC_V_SYNC_A_END: 13bits */
  417.   if (tmp >= 0x2000)
  418.     return MODE_VSYNC_WIDE;
  419.  
  420.   return MODE_OK;
  421. }
  422.  
  423. /*
  424.  *
  425.  */
  426. static void
  427. DxModeSet(struct rhdCrtc *Crtc, DisplayModePtr Mode)
  428. {
  429.     RHDPtr rhdPtr = RHDPTRI(Crtc);
  430.   CARD16 BlankStart, BlankEnd;
  431.   CARD16 RegOff;
  432.  
  433.     RHDDebug(Crtc->scrnIndex, "FUNCTION: %s: %s\n", __func__, Crtc->Name);
  434.  
  435.     if (rhdPtr->verbosity > 6) {
  436.         xf86DrvMsg(Crtc->scrnIndex, X_INFO, "%s: Setting ",__func__);
  437.         RHDPrintModeline(Mode);
  438.     }
  439.  
  440.   if (Crtc->Id == RHD_CRTC_1)
  441.     RegOff = D1_REG_OFFSET;
  442.   else
  443.     RegOff = D2_REG_OFFSET;
  444.  
  445.     /* enable read requests */
  446.   RHDRegMask(Crtc, RegOff + D1CRTC_CONTROL, 0, 0x01000000);
  447.  
  448.     /* Horizontal */
  449.   RHDRegWrite(Crtc, RegOff + D1CRTC_H_TOTAL, Mode->CrtcHTotal - 1);
  450.  
  451.   BlankStart = Mode->CrtcHTotal + Mode->CrtcHBlankStart - Mode->CrtcHSyncStart;
  452.   BlankEnd = Mode->CrtcHBlankEnd - Mode->CrtcHSyncStart;
  453.   RHDRegWrite(Crtc, RegOff + D1CRTC_H_BLANK_START_END,
  454.   BlankStart | (BlankEnd << 16));
  455.  
  456.   RHDRegWrite(Crtc, RegOff + D1CRTC_H_SYNC_A,
  457.              (Mode->CrtcHSyncEnd - Mode->CrtcHSyncStart) << 16);
  458.   RHDRegWrite(Crtc, RegOff + D1CRTC_H_SYNC_A_CNTL, Mode->Flags & V_NHSYNC);
  459.  
  460.     /* Vertical */
  461.   RHDRegWrite(Crtc, RegOff + D1CRTC_V_TOTAL, Mode->CrtcVTotal - 1);
  462.  
  463.   BlankStart = Mode->CrtcVTotal + Mode->CrtcVBlankStart - Mode->CrtcVSyncStart;
  464.   BlankEnd = Mode->CrtcVBlankEnd - Mode->CrtcVSyncStart;
  465.   RHDRegWrite(Crtc, RegOff + D1CRTC_V_BLANK_START_END,
  466.               BlankStart | (BlankEnd << 16));
  467.  
  468.     /* set interlaced */
  469.     if (Mode->Flags & V_INTERLACE) {
  470.         RHDRegWrite(Crtc, RegOff + D1CRTC_INTERLACE_CONTROL, 0x1);
  471.         RHDRegWrite(Crtc, RegOff + D1MODE_DATA_FORMAT, 0x1);
  472.     } else {
  473.         RHDRegWrite(Crtc, RegOff + D1CRTC_INTERLACE_CONTROL, 0x0);
  474.         RHDRegWrite(Crtc, RegOff + D1MODE_DATA_FORMAT, 0x0);
  475.     }
  476.  
  477.   RHDRegWrite(Crtc, RegOff + D1CRTC_V_SYNC_A,
  478.              (Mode->CrtcVSyncEnd - Mode->CrtcVSyncStart) << 16);
  479.   RHDRegWrite(Crtc, RegOff + D1CRTC_V_SYNC_A_CNTL, Mode->Flags & V_NVSYNC);
  480.  
  481.     /* set D1CRTC_HORZ_COUNT_BY2_EN to 0; should only be set to 1 on 30bpp DVI modes */
  482.     RHDRegMask(Crtc, RegOff + D1CRTC_COUNT_CONTROL, 0x0, 0x1);
  483.  
  484.   Crtc->CurrentMode = Mode;
  485. }
  486.  
  487. /*
  488.  *
  489.  */
  490. static void
  491. DxModeSave(struct rhdCrtc *Crtc)
  492. {
  493.     struct rhdCrtcModePrivate *ModePriv;
  494.     CARD32 RegOff;
  495.  
  496.     if (!Crtc->ModePriv)
  497.         ModePriv = xnfcalloc(1, sizeof(struct rhdCrtcModePrivate));
  498.     else
  499.         ModePriv = Crtc->ModePriv;
  500.  
  501.     if (Crtc->Id == RHD_CRTC_1)
  502.         RegOff = D1_REG_OFFSET;
  503.     else
  504.         RegOff = D2_REG_OFFSET;
  505.  
  506.     ModePriv->StoreCrtcControl = RHDRegRead(Crtc, RegOff + D1CRTC_CONTROL);
  507.  
  508.     ModePriv->StoreCrtcHTotal = RHDRegRead(Crtc, RegOff + D1CRTC_H_TOTAL);
  509.     ModePriv->StoreCrtcHBlankStartEnd =
  510.         RHDRegRead(Crtc, RegOff + D1CRTC_H_BLANK_START_END);
  511.     ModePriv->StoreCrtcHSyncA = RHDRegRead(Crtc, RegOff + D1CRTC_H_SYNC_A);
  512.     ModePriv->StoreCrtcHSyncACntl = RHDRegRead(Crtc, RegOff + D1CRTC_H_SYNC_A_CNTL);
  513.     ModePriv->StoreCrtcHSyncB = RHDRegRead(Crtc, RegOff + D1CRTC_H_SYNC_B);
  514.     ModePriv->StoreCrtcHSyncBCntl = RHDRegRead(Crtc, RegOff + D1CRTC_H_SYNC_B_CNTL);
  515.  
  516.     ModePriv->StoreModeDataFormat = RHDRegRead(Crtc, RegOff + D1MODE_DATA_FORMAT);
  517.     ModePriv->StoreCrtcInterlaceControl = RHDRegRead(Crtc, RegOff + D1CRTC_INTERLACE_CONTROL);
  518.  
  519.     ModePriv->StoreCrtcVTotal = RHDRegRead(Crtc, RegOff + D1CRTC_V_TOTAL);
  520.     ModePriv->StoreCrtcVBlankStartEnd =
  521.         RHDRegRead(Crtc, RegOff + D1CRTC_V_BLANK_START_END);
  522.     ModePriv->StoreCrtcVSyncA = RHDRegRead(Crtc, RegOff + D1CRTC_V_SYNC_A);
  523.     ModePriv->StoreCrtcVSyncACntl = RHDRegRead(Crtc, RegOff + D1CRTC_V_SYNC_A_CNTL);
  524.     ModePriv->StoreCrtcVSyncB = RHDRegRead(Crtc, RegOff + D1CRTC_V_SYNC_B);
  525.     ModePriv->StoreCrtcVSyncBCntl = RHDRegRead(Crtc, RegOff + D1CRTC_V_SYNC_B_CNTL);
  526.  
  527.     ModePriv->StoreCrtcBlackColor = RHDRegRead(Crtc, RegOff + D1CRTC_BLACK_COLOR);
  528.     ModePriv->StoreCrtcBlankControl = RHDRegRead(Crtc, RegOff + D1CRTC_BLANK_CONTROL);
  529.  
  530.     ModePriv->StoreCrtcCountControl = RHDRegRead(Crtc, RegOff + D1CRTC_COUNT_CONTROL);
  531.     RHDDebug(Crtc->scrnIndex, "Saved CrtcCountControl[%i] = 0x%8.8x\n",
  532.              Crtc->Id,ModePriv->StoreCrtcCountControl);
  533.  
  534.     Crtc->ModePriv = ModePriv;
  535. }
  536.  
  537. /*
  538.  *
  539.  */
  540. static void
  541. DxModeRestore(struct rhdCrtc *Crtc)
  542. {
  543.     struct rhdCrtcModePrivate *ModePriv = Crtc->ModePriv;
  544.     CARD32 RegOff;
  545.  
  546.     if (!ModePriv) {
  547.         xf86DrvMsg(Crtc->scrnIndex, X_ERROR, "%s: no registers stored!\n",
  548.                    __func__);
  549.         return;
  550.     }
  551.  
  552.     if (Crtc->Id == RHD_CRTC_1)
  553.         RegOff = D1_REG_OFFSET;
  554.     else
  555.         RegOff = D2_REG_OFFSET;
  556.  
  557.     /* ModeSet */
  558.     RHDRegWrite(Crtc, RegOff + D1CRTC_CONTROL, ModePriv->StoreCrtcControl);
  559.  
  560.     RHDRegWrite(Crtc, RegOff + D1CRTC_H_TOTAL, ModePriv->StoreCrtcHTotal);
  561.     RHDRegWrite(Crtc, RegOff + D1CRTC_H_BLANK_START_END,
  562.                 ModePriv->StoreCrtcHBlankStartEnd);
  563.     RHDRegWrite(Crtc, RegOff + D1CRTC_H_SYNC_A, ModePriv->StoreCrtcHSyncA);
  564.     RHDRegWrite(Crtc, RegOff + D1CRTC_H_SYNC_A_CNTL, ModePriv->StoreCrtcHSyncACntl);
  565.     RHDRegWrite(Crtc, RegOff + D1CRTC_H_SYNC_B, ModePriv->StoreCrtcHSyncB);
  566.     RHDRegWrite(Crtc, RegOff + D1CRTC_H_SYNC_B_CNTL, ModePriv->StoreCrtcHSyncBCntl);
  567.  
  568.     RHDRegWrite(Crtc, RegOff + D1MODE_DATA_FORMAT, ModePriv->StoreModeDataFormat);
  569.     RHDRegWrite(Crtc, RegOff + D1CRTC_INTERLACE_CONTROL, ModePriv->StoreCrtcInterlaceControl);
  570.  
  571.     RHDRegWrite(Crtc, RegOff + D1CRTC_V_TOTAL, ModePriv->StoreCrtcVTotal);
  572.     RHDRegWrite(Crtc, RegOff + D1CRTC_V_BLANK_START_END,
  573.                 ModePriv->StoreCrtcVBlankStartEnd);
  574.     RHDRegWrite(Crtc, RegOff + D1CRTC_V_SYNC_A, ModePriv->StoreCrtcVSyncA);
  575.     RHDRegWrite(Crtc, RegOff + D1CRTC_V_SYNC_A_CNTL, ModePriv->StoreCrtcVSyncACntl);
  576.     RHDRegWrite(Crtc, RegOff + D1CRTC_V_SYNC_B, ModePriv->StoreCrtcVSyncB);
  577.     RHDRegWrite(Crtc, RegOff + D1CRTC_V_SYNC_B_CNTL, ModePriv->StoreCrtcVSyncBCntl);
  578.  
  579.     RHDRegWrite(Crtc, RegOff + D1CRTC_COUNT_CONTROL, ModePriv->StoreCrtcCountControl);
  580.  
  581.     /* Blank */
  582.     RHDRegWrite(Crtc, RegOff + D1CRTC_BLACK_COLOR, ModePriv->StoreCrtcBlackColor);
  583.     RHDRegWrite(Crtc, RegOff + D1CRTC_BLANK_CONTROL, ModePriv->StoreCrtcBlankControl);
  584.  
  585.     /* When VGA is enabled, it imposes its timing on us, so our CRTC SYNC
  586.      * timing can be set to 0. This doesn't always restore properly...
  587.      * Workaround is to set a valid sync length for a bit so VGA can
  588.      * latch in. */
  589.     if (!ModePriv->StoreCrtcVSyncA && (ModePriv->StoreCrtcControl & 0x00000001)) {
  590.         RHDRegWrite(Crtc, RegOff + D1CRTC_V_SYNC_A, 0x00040000);
  591.         usleep(300000); /* seems a reliable timeout here */
  592.         RHDRegWrite(Crtc, RegOff + D1CRTC_V_SYNC_A, ModePriv->StoreCrtcVSyncA);
  593.     }
  594. }
  595.  
  596. /*
  597.  *
  598.  */
  599. static void
  600. DxModeDestroy(struct rhdCrtc *Crtc)
  601. {
  602.     RHDFUNC(Crtc);
  603.  
  604.     if (Crtc->ModePriv)
  605.         xfree(Crtc->ModePriv);
  606.     Crtc->ModePriv = NULL;
  607. }
  608.  
  609. /*
  610.  *
  611.  */
  612. struct rhdScalerOverscan
  613. rhdCalculateOverscan(DisplayModePtr Mode, DisplayModePtr ScaledToMode, enum rhdCrtcScaleType Type)
  614. {
  615.     struct rhdScalerOverscan Overscan;
  616.     int tmp;
  617.  
  618.     Overscan.OverscanTop = Overscan.OverscanBottom = Overscan.OverscanLeft = Overscan.OverscanRight = 0;
  619.     Overscan.Type = Type;
  620.  
  621.     if (ScaledToMode) {
  622.         Overscan.OverscanTop = ScaledToMode->CrtcVDisplay - Mode->CrtcVDisplay;
  623.         Overscan.OverscanLeft = ScaledToMode->CrtcHDisplay - Mode->CrtcHDisplay;
  624.  
  625.         if (!Overscan.OverscanTop && !Overscan.OverscanLeft)
  626.             Overscan.Type = RHD_CRTC_SCALE_TYPE_NONE;
  627.  
  628.         /* handle down scaling */
  629.         if (Overscan.OverscanTop < 0) {
  630.             Overscan.Type = RHD_CRTC_SCALE_TYPE_SCALE;
  631.             Overscan.OverscanTop = 0;
  632.         }
  633.         if (Overscan.OverscanLeft < 0) {
  634.             Overscan.Type = RHD_CRTC_SCALE_TYPE_SCALE;
  635.             Overscan.OverscanLeft = 0;
  636.         }
  637.     }
  638.  
  639.     switch (Type) {
  640.         case RHD_CRTC_SCALE_TYPE_NONE:
  641.             break;
  642.  
  643.         case RHD_CRTC_SCALE_TYPE_CENTER:
  644.             tmp = Overscan.OverscanTop;
  645.             Overscan.OverscanTop >>= 1;
  646.             Overscan.OverscanBottom = tmp - Overscan.OverscanTop;
  647.             tmp = Overscan.OverscanLeft;
  648.             Overscan.OverscanLeft >>= 1;
  649.             Overscan.OverscanRight = tmp - Overscan.OverscanLeft;
  650.             break;
  651.  
  652.         case RHD_CRTC_SCALE_TYPE_SCALE:
  653.             Overscan.OverscanLeft = Overscan.OverscanRight = Overscan.OverscanTop = Overscan.OverscanBottom = 0;
  654.             break;
  655.         case RHD_CRTC_SCALE_TYPE_SCALE_KEEP_ASPECT_RATIO:
  656.         {
  657.             int p1, p2, tmp;
  658.             Overscan.OverscanLeft = Overscan.OverscanRight = Overscan.OverscanTop = Overscan.OverscanBottom = 0;
  659.             p1 = Mode->CrtcVDisplay * ScaledToMode->CrtcHDisplay;
  660.             p2 = ScaledToMode->CrtcVDisplay * Mode->CrtcHDisplay;
  661.             if (p1 == p2) {
  662.                 Overscan.Type = RHD_CRTC_SCALE_TYPE_SCALE;
  663.             } else if (p1 > p2) {
  664.                 tmp = (p2 / Mode->CrtcVDisplay);
  665.                 tmp = ScaledToMode->CrtcHDisplay - tmp;
  666.                 Overscan.OverscanLeft = tmp >> 1;
  667.                 Overscan.OverscanRight = tmp - Overscan.OverscanLeft;
  668.                 ErrorF("HScale %i %i\n", Overscan.OverscanLeft, Overscan.OverscanRight);
  669.             } else {
  670.                 tmp = (p1 / Mode->CrtcHDisplay);
  671.                 tmp = ScaledToMode->CrtcVDisplay - tmp;
  672.                 Overscan.OverscanTop = tmp >> 1;
  673.                 Overscan.OverscanBottom = tmp - Overscan.OverscanTop;
  674.                 ErrorF("VScale %i %i\n", Overscan.OverscanTop, Overscan.OverscanBottom);
  675.             }
  676.             break;
  677.         }
  678.     }
  679.  
  680.     return Overscan;
  681. }
  682.  
  683. /*
  684.  *
  685.  */
  686. static ModeStatus
  687. DxScaleValid(struct rhdCrtc *Crtc, enum rhdCrtcScaleType Type,
  688.              DisplayModePtr Mode, DisplayModePtr ScaledToMode)
  689. {
  690.     struct rhdScalerOverscan Overscan;
  691.  
  692.     /* D1_MODE_VIEWPORT_WIDTH: 14bits */
  693.     if (Mode->CrtcHDisplay >= 0x4000)
  694.         return MODE_BAD_HVALUE;
  695.  
  696.     /* D1_MODE_VIEWPORT_HEIGHT: 14bits */
  697.     if (Mode->CrtcVDisplay >= 0x4000)
  698.         return MODE_BAD_VVALUE;
  699.  
  700.     Overscan = rhdCalculateOverscan(Mode, ScaledToMode, Type);
  701.  
  702.     if (Overscan.OverscanLeft >= 4096 || Overscan.OverscanRight >= 4096)
  703.         return MODE_HBLANK_WIDE;
  704.  
  705.     if (Overscan.OverscanTop >= 4096 || Overscan.OverscanBottom >= 4096)
  706.         return MODE_VBLANK_WIDE;
  707.  
  708.     if ((Type == RHD_CRTC_SCALE_TYPE_SCALE
  709.          || Type == RHD_CRTC_SCALE_TYPE_SCALE_KEEP_ASPECT_RATIO)
  710.         && (Mode->Flags & V_INTERLACE))
  711.         return MODE_NO_INTERLACE;
  712.  
  713.     /* should we also fail of Type != Overscan.Type? */
  714.  
  715.     return MODE_OK;
  716. }
  717.  
  718. /*
  719.  *
  720.  */
  721. static void
  722. DxScaleSet(struct rhdCrtc *Crtc, enum rhdCrtcScaleType Type,
  723.            DisplayModePtr Mode, DisplayModePtr ScaledToMode)
  724. {
  725.     RHDPtr rhdPtr = RHDPTRI(Crtc);
  726.     CARD16 RegOff;
  727.     struct rhdScalerOverscan Overscan;
  728.  
  729.     RHDDebug(Crtc->scrnIndex, "FUNCTION: %s: %s viewport: %ix%i\n", __func__, Crtc->Name,
  730.              Mode->CrtcHDisplay, Mode->CrtcVDisplay);
  731.  
  732.     if (Crtc->Id == RHD_CRTC_1)
  733.         RegOff = D1_REG_OFFSET;
  734.     else
  735.         RegOff = D2_REG_OFFSET;
  736.  
  737.     Overscan = rhdCalculateOverscan(Mode, ScaledToMode, Type);
  738.     Type = Overscan.Type;
  739.  
  740.     RHDDebug(Crtc->scrnIndex, "FUNCTION: %s: %s viewport: %ix%i - OverScan: T: %i B: %i R: %i L: %i\n",
  741.              __func__, Crtc->Name, Mode->CrtcHDisplay, Mode->CrtcVDisplay,
  742.              Overscan.OverscanTop, Overscan.OverscanBottom,
  743.              Overscan.OverscanLeft, Overscan.OverscanRight);
  744.  
  745.     /* D1Mode registers */
  746.     RHDRegWrite(Crtc, RegOff + D1MODE_VIEWPORT_SIZE,
  747.                 Mode->CrtcVDisplay | (Mode->CrtcHDisplay << 16));
  748.     RHDRegWrite(Crtc, RegOff + D1MODE_VIEWPORT_START, 0);
  749.  
  750.     RHDRegWrite(Crtc, RegOff + D1MODE_EXT_OVERSCAN_LEFT_RIGHT,
  751.                 (Overscan.OverscanLeft << 16) | Overscan.OverscanRight);
  752.     RHDRegWrite(Crtc, RegOff + D1MODE_EXT_OVERSCAN_TOP_BOTTOM,
  753.                 (Overscan.OverscanTop << 16) | Overscan.OverscanBottom);
  754.  
  755.     switch (Type) {
  756.         case RHD_CRTC_SCALE_TYPE_NONE:  /* No scaling whatsoever */
  757.             ErrorF("None\n");
  758.             RHDRegWrite(Crtc, RegOff + D1SCL_ENABLE, 0);
  759.             RHDRegWrite(Crtc, RegOff + D1SCL_TAP_CONTROL, 0);
  760.             RHDRegWrite(Crtc, RegOff + D1MODE_CENTER, 0);
  761.             break;
  762.         case RHD_CRTC_SCALE_TYPE_CENTER: /* center of the actual mode */
  763.             ErrorF("Center\n");
  764.             RHDRegWrite(Crtc, RegOff + D1SCL_ENABLE, 0);
  765.             RHDRegWrite(Crtc, RegOff + D1SCL_TAP_CONTROL, 0);
  766.             RHDRegWrite(Crtc, RegOff + D1MODE_CENTER, 1);
  767.             break;
  768.         case RHD_CRTC_SCALE_TYPE_SCALE_KEEP_ASPECT_RATIO: /* scaled to fullscreen */
  769.         case RHD_CRTC_SCALE_TYPE_SCALE: /* scaled to fullscreen */
  770.             ErrorF("Full\n");
  771.             if (Type == RHD_CRTC_SCALE_TYPE_SCALE_KEEP_ASPECT_RATIO)
  772.                 RHDRegWrite(Crtc, RegOff + D1MODE_CENTER, 1);
  773.             else
  774.                 RHDRegWrite(Crtc, RegOff + D1MODE_CENTER, 0);
  775.  
  776.             RHDRegWrite(Crtc, RegOff + D1SCL_UPDATE, 0);
  777.             RHDRegWrite(Crtc, RegOff + D1SCL_DITHER, 0);
  778.  
  779.             RHDRegWrite(Crtc, RegOff + D1SCL_ENABLE, 1);
  780.             RHDRegWrite(Crtc, RegOff + D1SCL_HVSCALE, 0x00010001); /* both h/v */
  781.  
  782.             RHDRegWrite(Crtc, RegOff + D1SCL_TAP_CONTROL, 0x00000101);
  783.  
  784.             RHDRegWrite(Crtc, RegOff + D1SCL_HFILTER, 0x00030100);
  785.             RHDRegWrite(Crtc, RegOff + D1SCL_VFILTER, 0x00030100);
  786.  
  787.             RHDRegWrite(Crtc, RegOff + D1SCL_DITHER, 0x00001010);
  788.             break;
  789.     }
  790.     RHDMCTuneAccessForDisplay(rhdPtr, Crtc->Id, Mode,
  791.                               ScaledToMode ? ScaledToMode : Mode);
  792. }
  793.  
  794. /*
  795.  *
  796.  */
  797. static void
  798. DxScaleSave(struct rhdCrtc *Crtc)
  799. {
  800.     struct rhdCrtcScalePrivate *ScalePriv;
  801.     CARD32 RegOff;
  802.  
  803.     if (!Crtc->ScalePriv)
  804.         ScalePriv =  xnfcalloc(1, sizeof(struct rhdCrtcScalePrivate));
  805.     else
  806.         ScalePriv = Crtc->ScalePriv;
  807.  
  808.     if (Crtc->Id == RHD_CRTC_1)
  809.         RegOff = D1_REG_OFFSET;
  810.     else
  811.         RegOff = D2_REG_OFFSET;
  812.  
  813.     ScalePriv->StoreModeViewPortSize = RHDRegRead(Crtc, RegOff + D1MODE_VIEWPORT_SIZE);
  814.     ScalePriv->StoreModeViewPortStart = RHDRegRead(Crtc, RegOff + D1MODE_VIEWPORT_START);
  815.     ScalePriv->StoreModeOverScanH =
  816.         RHDRegRead(Crtc, RegOff + D1MODE_EXT_OVERSCAN_LEFT_RIGHT);
  817.     ScalePriv->StoreModeOverScanV =
  818.         RHDRegRead(Crtc, RegOff + D1MODE_EXT_OVERSCAN_TOP_BOTTOM);
  819.  
  820.     ScalePriv->StoreScaleEnable = RHDRegRead(Crtc, RegOff + D1SCL_ENABLE);
  821.     ScalePriv->StoreScaleTapControl = RHDRegRead(Crtc, RegOff + D1SCL_TAP_CONTROL);
  822.     ScalePriv->StoreModeCenter = RHDRegRead(Crtc, RegOff + D1MODE_CENTER);
  823.     ScalePriv->StoreScaleHV = RHDRegRead(Crtc, RegOff + D1SCL_HVSCALE);
  824.     ScalePriv->StoreScaleHFilter = RHDRegRead(Crtc, RegOff + D1SCL_HFILTER);
  825.     ScalePriv->StoreScaleVFilter = RHDRegRead(Crtc, RegOff + D1SCL_VFILTER);
  826.     ScalePriv->StoreScaleDither = RHDRegRead(Crtc, RegOff + D1SCL_DITHER);
  827.  
  828.     Crtc->ScalePriv = ScalePriv;
  829. }
  830.  
  831. /*
  832.  *
  833.  */
  834. static void
  835. DxScaleRestore(struct rhdCrtc *Crtc)
  836. {
  837.     struct rhdCrtcScalePrivate *ScalePriv = Crtc->ScalePriv;
  838.     CARD32 RegOff;
  839.  
  840.     if (!ScalePriv) {
  841.         xf86DrvMsg(Crtc->scrnIndex, X_ERROR, "%s: no registers stored!\n",
  842.                    __func__);
  843.         return;
  844.     }
  845.  
  846.     if (Crtc->Id == RHD_CRTC_1)
  847.         RegOff = D1_REG_OFFSET;
  848.     else
  849.         RegOff = D2_REG_OFFSET;
  850.  
  851.     /* ScaleSet */
  852.     RHDRegWrite(Crtc, RegOff + D1MODE_VIEWPORT_SIZE, ScalePriv->StoreModeViewPortSize);
  853.  
  854.     /* ScaleSet/ViewPortStart */
  855.     RHDRegWrite(Crtc, RegOff + D1MODE_VIEWPORT_START, ScalePriv->StoreModeViewPortStart);
  856.  
  857.     /* ScaleSet */
  858.     RHDRegWrite(Crtc, RegOff + D1MODE_EXT_OVERSCAN_LEFT_RIGHT,
  859.                 ScalePriv->StoreModeOverScanH);
  860.     RHDRegWrite(Crtc, RegOff + D1MODE_EXT_OVERSCAN_TOP_BOTTOM,
  861.                 ScalePriv->StoreModeOverScanV);
  862.  
  863.     RHDRegWrite(Crtc, RegOff + D1SCL_ENABLE, ScalePriv->StoreScaleEnable);
  864.     RHDRegWrite(Crtc, RegOff + D1SCL_TAP_CONTROL, ScalePriv->StoreScaleTapControl);
  865.     RHDRegWrite(Crtc, RegOff + D1MODE_CENTER, ScalePriv->StoreModeCenter);
  866.     RHDRegWrite(Crtc, RegOff + D1SCL_HVSCALE, ScalePriv->StoreScaleHV);
  867.     RHDRegWrite(Crtc, RegOff + D1SCL_HFILTER, ScalePriv->StoreScaleHFilter);
  868.     RHDRegWrite(Crtc, RegOff + D1SCL_VFILTER, ScalePriv->StoreScaleVFilter);
  869.     RHDRegWrite(Crtc, RegOff + D1SCL_DITHER, ScalePriv->StoreScaleDither);
  870. }
  871.  
  872. /*
  873.  *
  874.  */
  875. static void
  876. DxScaleDestroy(struct rhdCrtc *Crtc)
  877. {
  878.     RHDFUNC(Crtc);
  879.  
  880.     if (Crtc->ScalePriv)
  881.         xfree(Crtc->ScalePriv);
  882.     Crtc->ScalePriv = NULL;
  883. }
  884.  
  885. /*
  886.  *
  887.  */
  888. static void
  889. D1LUTSelect(struct rhdCrtc *Crtc, struct rhdLUT *LUT)
  890. {
  891.     RHDFUNC(Crtc);
  892.  
  893.     RHDRegWrite(Crtc, D1GRPH_LUT_SEL, LUT->Id & 1);
  894.     Crtc->LUT = LUT;
  895. }
  896.  
  897. /*
  898.  *
  899.  */
  900. static void
  901. D2LUTSelect(struct rhdCrtc *Crtc, struct rhdLUT *LUT)
  902. {
  903.     RHDFUNC(Crtc);
  904.  
  905.     RHDRegWrite(Crtc, D2GRPH_LUT_SEL, LUT->Id & 1);
  906.     Crtc->LUT = LUT;
  907. }
  908.  
  909. /*
  910.  *
  911.  */
  912. static void
  913. DxLUTSave(struct rhdCrtc *Crtc)
  914. {
  915.     struct rhdCrtcLUTPrivate *LUTPriv;
  916.     CARD32 RegOff;
  917.  
  918.     if (!Crtc->LUTPriv)
  919.         LUTPriv =  xnfcalloc(1, sizeof(struct rhdCrtcLUTPrivate));
  920.     else
  921.         LUTPriv = Crtc->LUTPriv;
  922.  
  923.     if (Crtc->Id == RHD_CRTC_1)
  924.         RegOff = D1_REG_OFFSET;
  925.     else
  926.         RegOff = D2_REG_OFFSET;
  927.  
  928.     LUTPriv->StoreGrphLutSel = RHDRegRead(Crtc, RegOff + D1GRPH_LUT_SEL);
  929.  
  930.     Crtc->LUTPriv = LUTPriv;
  931. }
  932.  
  933. /*
  934.  *
  935.  */
  936. static void
  937. DxLUTRestore(struct rhdCrtc *Crtc)
  938. {
  939.     struct rhdCrtcLUTPrivate *LUTPriv = Crtc->LUTPriv;
  940.     CARD32 RegOff;
  941.  
  942.     if (!LUTPriv) {
  943.         xf86DrvMsg(Crtc->scrnIndex, X_ERROR, "%s: no registers stored!\n",
  944.                    __func__);
  945.         return;
  946.     }
  947.  
  948.     if (Crtc->Id == RHD_CRTC_1)
  949.         RegOff = D1_REG_OFFSET;
  950.     else
  951.         RegOff = D2_REG_OFFSET;
  952.  
  953.     /* LUTSelect */
  954.     RHDRegWrite(Crtc, RegOff + D1GRPH_LUT_SEL, LUTPriv->StoreGrphLutSel);
  955. }
  956.  
  957. /*
  958.  *
  959.  */
  960. static void
  961. DxLUTDestroy(struct rhdCrtc *Crtc)
  962. {
  963.     RHDFUNC(Crtc);
  964.  
  965.     if (Crtc->LUTPriv)
  966.         xfree(Crtc->LUTPriv);
  967.     Crtc->LUTPriv = NULL;
  968. }
  969.  
  970. /*
  971.  *
  972.  */
  973. static void
  974. D1ViewPortStart(struct rhdCrtc *Crtc, CARD16 X, CARD16 Y)
  975. {
  976.     RHDFUNC(Crtc);
  977.  
  978.     /* not as granular as docs make it seem to be.
  979.      * if the lower two bits are set the line buffer might screw up, requiring
  980.      * a power cycle. */
  981.     X = (X + 0x02) & ~0x03;
  982.     Y &= ~0x01;
  983.  
  984.     RHDRegMask(Crtc, D1SCL_UPDATE, 0x00010000, 0x0001000);
  985.     RHDRegWrite(Crtc, D1MODE_VIEWPORT_START, (X << 16) | Y);
  986.     RHDRegMask(Crtc, D1SCL_UPDATE, 0, 0x0001000);
  987.  
  988.     Crtc->X = X;
  989.     Crtc->Y = Y;
  990. }
  991.  
  992. /*
  993.  *
  994.  */
  995. static void
  996. D2ViewPortStart(struct rhdCrtc *Crtc, CARD16 X, CARD16 Y)
  997. {
  998.     RHDFUNC(Crtc);
  999.  
  1000.     /* not as granular as docs make it seem to be. */
  1001.     X = (X + 0x02) & ~0x03;
  1002.     Y &= ~0x01;
  1003.  
  1004.     RHDRegMask(Crtc, D2SCL_UPDATE, 0x00010000, 0x0001000);
  1005.     RHDRegWrite(Crtc, D2MODE_VIEWPORT_START, (X << 16) | Y);
  1006.     RHDRegMask(Crtc, D2SCL_UPDATE, 0, 0x0001000);
  1007.  
  1008.     Crtc->X = X;
  1009.     Crtc->Y = Y;
  1010. }
  1011.  
  1012. #define CRTC_SYNC_WAIT 0x100000
  1013. /*
  1014.  *
  1015.  */
  1016. static Bool
  1017. D1CRTCDisable(struct rhdCrtc *Crtc)
  1018. {
  1019.     if (RHDRegRead(Crtc, D1CRTC_CONTROL) & 0x00000001) {
  1020.     CARD32 Control = RHDRegRead(Crtc, D1CRTC_CONTROL);
  1021.     int i;
  1022.  
  1023.         RHDRegMask(Crtc, D1CRTC_CONTROL, 0, 0x00000301);
  1024.         (void)RHDRegRead(Crtc, D1CRTC_CONTROL);
  1025.  
  1026.     for (i = 0; i < CRTC_SYNC_WAIT; i++)
  1027.             if (!(RHDRegRead(Crtc, D1CRTC_CONTROL) & 0x00010000)) {
  1028.                 RHDDebug(Crtc->scrnIndex, "%s: %d loops\n", __func__, i);
  1029.                 RHDRegMask(Crtc, D1CRTC_CONTROL, Control, 0x00000300);
  1030.                 return TRUE;
  1031.             }
  1032.         xf86DrvMsg(Crtc->scrnIndex, X_ERROR,
  1033.                    "%s: Failed to Unsync %s\n", __func__, Crtc->Name);
  1034.         RHDRegMask(Crtc, D1CRTC_CONTROL, Control, 0x00000300);
  1035.         return FALSE;
  1036.     }
  1037.     return TRUE;
  1038. }
  1039.  
  1040. /*
  1041.  *
  1042.  */
  1043. static Bool
  1044. D2CRTCDisable(struct rhdCrtc *Crtc)
  1045. {
  1046.     if (RHDRegRead(Crtc, D2CRTC_CONTROL) & 0x00000001) {
  1047.     CARD32 Control = RHDRegRead(Crtc, D2CRTC_CONTROL);
  1048.     int i;
  1049.  
  1050.         RHDRegMask(Crtc, D2CRTC_CONTROL, 0, 0x00000301);
  1051.         (void)RHDRegRead(Crtc, D2CRTC_CONTROL);
  1052.  
  1053.     for (i = 0; i < CRTC_SYNC_WAIT; i++)
  1054.             if (!(RHDRegRead(Crtc, D2CRTC_CONTROL) & 0x00010000)) {
  1055.                 RHDDebug(Crtc->scrnIndex, "%s: %d loops\n", __func__, i);
  1056.                 RHDRegMask(Crtc, D2CRTC_CONTROL, Control, 0x00000300);
  1057.                 return TRUE;
  1058.             }
  1059.         xf86DrvMsg(Crtc->scrnIndex, X_ERROR,
  1060.                    "%s: Failed to Unsync %s\n", __func__, Crtc->Name);
  1061.         RHDRegMask(Crtc, D2CRTC_CONTROL, Control, 0x00000300);
  1062.         return FALSE;
  1063.     }
  1064.     return TRUE;
  1065. }
  1066.  
  1067. /*
  1068.  *
  1069.  */
  1070. static Bool
  1071. D1Power(struct rhdCrtc *Crtc, int Power)
  1072. {
  1073.     Bool ret;
  1074.     RHDFUNC(Crtc);
  1075.  
  1076.     switch (Power) {
  1077.     case RHD_POWER_ON:
  1078.         RHDRegMask(Crtc, D1GRPH_ENABLE, 0x00000001, 0x00000001);
  1079.         usleep(2);
  1080.         RHDRegMask(Crtc, D1CRTC_CONTROL, 0, 0x01000000); /* enable read requests */
  1081.         RHDRegMask(Crtc, D1CRTC_CONTROL, 1, 1);
  1082.         return TRUE;
  1083.     case RHD_POWER_RESET:
  1084.         RHDRegMask(Crtc, D1CRTC_CONTROL, 0x01000000, 0x01000000); /* disable read requests */
  1085.         return D1CRTCDisable(Crtc);
  1086.     case RHD_POWER_SHUTDOWN:
  1087.     default:
  1088.         RHDRegMask(Crtc, D1CRTC_CONTROL, 0x01000000, 0x01000000); /* disable read requests */
  1089.         ret = D1CRTCDisable(Crtc);
  1090.         RHDRegMask(Crtc, D1GRPH_ENABLE, 0, 0x00000001);
  1091.         return ret;
  1092.     }
  1093. }
  1094.  
  1095. /*
  1096.  *
  1097.  */
  1098. static Bool
  1099. D2Power(struct rhdCrtc *Crtc, int Power)
  1100. {
  1101.     Bool ret;
  1102.     RHDFUNC(Crtc);
  1103.  
  1104.     switch (Power) {
  1105.     case RHD_POWER_ON:
  1106.         RHDRegMask(Crtc, D2GRPH_ENABLE, 0x00000001, 0x00000001);
  1107.         usleep(2);
  1108.         RHDRegMask(Crtc, D2CRTC_CONTROL, 0, 0x01000000); /* enable read requests */
  1109.         RHDRegMask(Crtc, D2CRTC_CONTROL, 1, 1);
  1110.         return TRUE;
  1111.     case RHD_POWER_RESET:
  1112.         RHDRegMask(Crtc, D2CRTC_CONTROL, 0x01000000, 0x01000000); /* disable read requests */
  1113.         return D2CRTCDisable(Crtc);
  1114.     case RHD_POWER_SHUTDOWN:
  1115.     default:
  1116.         RHDRegMask(Crtc, D2CRTC_CONTROL, 0x01000000, 0x01000000); /* disable read requests */
  1117.         ret = D2CRTCDisable(Crtc);
  1118.         RHDRegMask(Crtc, D2GRPH_ENABLE, 0, 0x00000001);
  1119.         return ret;
  1120.     }
  1121. }
  1122.  
  1123. /*
  1124.  * This is quite different from Power. Power disables and enables things,
  1125.  * this here makes the hw send out black, and can switch back and forth
  1126.  * immediately. Useful for covering up a framebuffer that is not filled
  1127.  * in yet.
  1128.  */
  1129. static void
  1130. D1Blank(struct rhdCrtc *Crtc, Bool Blank)
  1131. {
  1132.     RHDFUNC(Crtc);
  1133.  
  1134.     RHDRegWrite(Crtc, D1CRTC_BLACK_COLOR, 0);
  1135.     if (Blank)
  1136.         RHDRegMask(Crtc, D1CRTC_BLANK_CONTROL, 0x00000100, 0x00000100);
  1137.     else
  1138.         RHDRegMask(Crtc, D1CRTC_BLANK_CONTROL, 0, 0x00000100);
  1139. }
  1140.  
  1141. /*
  1142.  *
  1143.  */
  1144. static void
  1145. D2Blank(struct rhdCrtc *Crtc, Bool Blank)
  1146. {
  1147.     RHDFUNC(Crtc);
  1148.  
  1149.     RHDRegWrite(Crtc, D2CRTC_BLACK_COLOR, 0);
  1150.     if (Blank)
  1151.         RHDRegMask(Crtc, D2CRTC_BLANK_CONTROL, 0x00000100, 0x00000100);
  1152.     else
  1153.         RHDRegMask(Crtc, D2CRTC_BLANK_CONTROL, 0, 0x00000100);
  1154. }
  1155.  
  1156. /*
  1157.  *
  1158.  */
  1159. static void
  1160. DxFMTSet(struct rhdCrtc *Crtc, struct rhdFMTDither *FMTDither)
  1161. {
  1162.     CARD32 RegOff;
  1163.     CARD32 fmt_cntl = 0;
  1164.  
  1165.     RHDFUNC(Crtc);
  1166.  
  1167.     if (Crtc->Id == RHD_CRTC_1)
  1168.         RegOff = FMT1_REG_OFFSET;
  1169.     else
  1170.         RegOff = FMT2_REG_OFFSET;
  1171.  
  1172.     if (FMTDither) {
  1173.  
  1174.         /* set dither depth to 18/24 */
  1175.         fmt_cntl = FMTDither->LVDS24Bit
  1176.             ? (RV62_FMT_SPATIAL_DITHER_DEPTH | RV62_FMT_TEMPORAL_DITHER_DEPTH)
  1177.             : 0;
  1178.         RHDRegMask(Crtc, RegOff + RV620_FMT1_BIT_DEPTH_CONTROL, fmt_cntl,
  1179.                RV62_FMT_SPATIAL_DITHER_DEPTH | RV62_FMT_TEMPORAL_DITHER_DEPTH);
  1180.  
  1181.         /* set temporal dither */
  1182.         if (FMTDither->LVDSTemporalDither) {
  1183.             fmt_cntl = FMTDither->LVDSGreyLevel ? RV62_FMT_TEMPORAL_LEVEL : 0x0;
  1184.             /* grey level */
  1185.             RHDRegMask(Crtc, RegOff + RV620_FMT1_BIT_DEPTH_CONTROL,
  1186.                        fmt_cntl, RV62_FMT_TEMPORAL_LEVEL);
  1187.             /* turn on temporal dither and reset */
  1188.             RHDRegMask(Crtc, RegOff + RV620_FMT1_BIT_DEPTH_CONTROL,
  1189.                        RV62_FMT_TEMPORAL_DITHER_EN | RV62_FMT_TEMPORAL_DITHER_RESET,
  1190.                        RV62_FMT_TEMPORAL_DITHER_EN | RV62_FMT_TEMPORAL_DITHER_RESET);
  1191.             usleep(20);
  1192.             /* turn off reset */
  1193.             RHDRegMask(Crtc, RegOff + RV620_FMT1_BIT_DEPTH_CONTROL, 0x0,
  1194.                        RV62_FMT_TEMPORAL_DITHER_RESET);
  1195.         }
  1196.         /* spatial dither */
  1197.         RHDRegMask(Crtc, RegOff + RV620_FMT1_BIT_DEPTH_CONTROL,
  1198.                    FMTDither->LVDSSpatialDither ? RV62_FMT_SPATIAL_DITHER_EN : 0,
  1199.                    RV62_FMT_SPATIAL_DITHER_EN);
  1200.     } else
  1201.         RHDRegWrite(Crtc, RegOff + RV620_FMT1_BIT_DEPTH_CONTROL, 0);
  1202.  
  1203.     /* 4:4:4 encoding */
  1204.     RHDRegMask(Crtc,  RegOff + RV620_FMT1_CONTROL, 0, RV62_FMT_PIXEL_ENCODING);
  1205.     /* disable color clamping */
  1206.     RHDRegWrite(Crtc, RegOff + RV620_FMT1_CLAMP_CNTL, 0);
  1207. }
  1208.  
  1209. /*
  1210.  *
  1211.  */
  1212. static void
  1213. DxFMTSave(struct rhdCrtc *Crtc)
  1214. {
  1215.     struct rhdCrtcFMTPrivate *FMTPrivate;
  1216.     CARD32 RegOff;
  1217.  
  1218.     RHDFUNC(Crtc);
  1219.  
  1220.     if (!Crtc->FMTPriv)
  1221.         FMTPrivate = xnfcalloc(sizeof (struct rhdCrtcFMTPrivate),1);
  1222.     else
  1223.         FMTPrivate = Crtc->FMTPriv;
  1224.  
  1225.     if (Crtc->Id == RHD_CRTC_1)
  1226.         RegOff = FMT1_REG_OFFSET;
  1227.     else
  1228.         RegOff = FMT2_REG_OFFSET;
  1229.  
  1230.     FMTPrivate->StoreControl         = RHDRegRead(Crtc, RegOff + RV620_FMT1_CONTROL);
  1231.     FMTPrivate->StoreBitDepthControl = RHDRegRead(Crtc, RegOff + RV620_FMT1_BIT_DEPTH_CONTROL);
  1232.     FMTPrivate->StoreClampCntl       = RHDRegRead(Crtc, RegOff + RV620_FMT1_CLAMP_CNTL);
  1233.  
  1234.     Crtc->FMTPriv = FMTPrivate;
  1235. }
  1236.  
  1237. /*
  1238.  *
  1239.  */
  1240. static void
  1241. DxFMTRestore(struct rhdCrtc *Crtc)
  1242. {
  1243.     struct rhdCrtcFMTPrivate *FMTPrivate = Crtc->FMTPriv;
  1244.     CARD32 RegOff;
  1245.  
  1246.     RHDFUNC(Crtc);
  1247.  
  1248.     if (!FMTPrivate)
  1249.         return;
  1250.  
  1251.     if (Crtc->Id == RHD_CRTC_1)
  1252.         RegOff = FMT1_REG_OFFSET;
  1253.     else
  1254.         RegOff = FMT2_REG_OFFSET;
  1255.  
  1256.     RHDRegWrite(Crtc, RegOff + RV620_FMT1_CONTROL, FMTPrivate->StoreControl);
  1257.     RHDRegWrite(Crtc, RegOff + RV620_FMT1_BIT_DEPTH_CONTROL, FMTPrivate->StoreBitDepthControl);
  1258.     RHDRegWrite(Crtc, RegOff + RV620_FMT1_CLAMP_CNTL, FMTPrivate->StoreClampCntl);
  1259. }
  1260.  
  1261. /*
  1262.  *
  1263.  */
  1264. static void
  1265. DxFMTDestroy(struct rhdCrtc *Crtc)
  1266. {
  1267.     RHDFUNC(Crtc);
  1268.  
  1269.     if (Crtc->FMTPriv)
  1270.         xfree(Crtc->FMTPriv);
  1271.     Crtc->FMTPriv = NULL;
  1272. }
  1273.  
  1274. /*
  1275.  *
  1276.  */
  1277. static enum rhdCrtcScaleType
  1278. rhdInitScaleType(RHDPtr rhdPtr)
  1279. {
  1280.     RHDFUNC(rhdPtr);
  1281. /*
  1282.     if (rhdPtr->scaleTypeOpt.set) {
  1283.         if (!strcasecmp(rhdPtr->scaleTypeOpt.val.string, "none"))
  1284.             return RHD_CRTC_SCALE_TYPE_NONE;
  1285.         else if (!strcasecmp(rhdPtr->scaleTypeOpt.val.string, "center"))
  1286.             return RHD_CRTC_SCALE_TYPE_CENTER;
  1287.         else if (!strcasecmp(rhdPtr->scaleTypeOpt.val.string, "scale"))
  1288.             return RHD_CRTC_SCALE_TYPE_SCALE;
  1289.         else if (!strcasecmp(rhdPtr->scaleTypeOpt.val.string, "scale_keep_aspect_ratio"))
  1290.             return RHD_CRTC_SCALE_TYPE_SCALE_KEEP_ASPECT_RATIO;
  1291.         else if (!strcasecmp(rhdPtr->scaleTypeOpt.val.string, "default"))
  1292.             return RHD_CRTC_SCALE_TYPE_DEFAULT;
  1293.         else {
  1294.             xf86DrvMsgVerb(rhdPtr->scrnIndex, X_ERROR, 0,
  1295.                            "Unknown scale type: %s\n", rhdPtr->scaleTypeOpt.val.string);
  1296.             return RHD_CRTC_SCALE_TYPE_DEFAULT;
  1297.         }
  1298.     } else  */
  1299.   return RHD_CRTC_SCALE_TYPE_SCALE;
  1300. }
  1301.  
  1302. /*
  1303.  *
  1304.  */
  1305. Bool
  1306. RHDCrtcsInit(RHDPtr rhdPtr)
  1307. {
  1308.     struct rhdCrtc *Crtc;
  1309.     enum rhdCrtcScaleType ScaleType;
  1310.     Bool useAtom;
  1311.  
  1312.     RHDFUNC(rhdPtr);
  1313.  
  1314.     useAtom = RHDUseAtom(rhdPtr, NULL, atomUsageCrtc);
  1315.  
  1316.     ScaleType = rhdInitScaleType(rhdPtr);
  1317.  
  1318.     Crtc = xnfcalloc(sizeof(struct rhdCrtc), 1);
  1319.     Crtc->scrnIndex = rhdPtr->scrnIndex;
  1320.     Crtc->Name = "CRTC 1";
  1321.     Crtc->Id = RHD_CRTC_1;
  1322.  
  1323.     Crtc->ScaleType = ScaleType;
  1324.  
  1325.     if (rhdPtr->ChipSet >= RHD_RV620) {
  1326.         Crtc->FMTDestroy = DxFMTDestroy;
  1327.         Crtc->FMTSave = DxFMTSave;
  1328.         Crtc->FMTRestore = DxFMTRestore;
  1329.         Crtc->FMTModeSet = DxFMTSet;
  1330.     }
  1331.     Crtc->FMTPriv = NULL;
  1332.  
  1333.     Crtc->FBValid   = DxFBValid;
  1334.     Crtc->FBSet     = DxFBSet;
  1335.     Crtc->FBSave = DxFBSave;
  1336.     Crtc->FBRestore = DxFBRestore;
  1337.     Crtc->FBDestroy = DxFBDestroy;
  1338.  
  1339.     Crtc->ModeValid = DxModeValid;
  1340.     Crtc->ModeSet   = DxModeSet;
  1341.     Crtc->ModeSave = DxModeSave;
  1342.     Crtc->ModeRestore = DxModeRestore;
  1343.     Crtc->ModeDestroy = DxModeDestroy;
  1344.     Crtc->ModePriv = NULL;
  1345.  
  1346.     Crtc->ScaleValid = DxScaleValid;
  1347.     Crtc->ScaleSet = DxScaleSet;
  1348.     Crtc->ScaleSave = DxScaleSave;
  1349.     Crtc->ScaleRestore = DxScaleRestore;
  1350.     Crtc->ScaleDestroy = DxScaleDestroy;
  1351.     Crtc->ScalePriv = NULL;
  1352.  
  1353.     Crtc->LUTSelect = D1LUTSelect;
  1354.     Crtc->LUTSave = DxLUTSave;
  1355.     Crtc->LUTRestore = DxLUTRestore;
  1356.     Crtc->LUTDestroy = DxLUTDestroy;
  1357.     Crtc->LUTPriv = NULL;
  1358.  
  1359.     Crtc->FrameSet  = D1ViewPortStart;
  1360.  
  1361.     Crtc->Power     = D1Power;
  1362.     Crtc->Blank     = D1Blank;
  1363.  
  1364.     rhdPtr->Crtc[0] = Crtc;
  1365.  
  1366.     Crtc = xnfcalloc(sizeof(struct rhdCrtc), 1);
  1367.     Crtc->scrnIndex = rhdPtr->scrnIndex;
  1368.     Crtc->Name      = "CRTC 2";
  1369.     Crtc->Id        = RHD_CRTC_2;
  1370.  
  1371.     Crtc->ScaleType = ScaleType;
  1372.  
  1373.     if (rhdPtr->ChipSet >= RHD_RV620) {
  1374.         Crtc->FMTDestroy = DxFMTDestroy;
  1375.         Crtc->FMTSave = DxFMTSave;
  1376.         Crtc->FMTRestore = DxFMTRestore;
  1377.         Crtc->FMTModeSet = DxFMTSet;
  1378.     }
  1379.     Crtc->FMTPriv = NULL;
  1380.  
  1381.     Crtc->FBValid   = DxFBValid;
  1382.     Crtc->FBSet     = DxFBSet;
  1383.     Crtc->FBSave = DxFBSave;
  1384.     Crtc->FBRestore = DxFBRestore;
  1385.     Crtc->FBDestroy = DxFBDestroy;
  1386.  
  1387.     Crtc->ModeValid = DxModeValid;
  1388.     Crtc->ModeSet   = DxModeSet;
  1389.     Crtc->ModeSave = DxModeSave;
  1390.     Crtc->ModeRestore = DxModeRestore;
  1391.     Crtc->ModeDestroy = DxModeDestroy;
  1392.     Crtc->ModePriv = NULL;
  1393.  
  1394.     Crtc->ScaleValid = DxScaleValid;
  1395.     Crtc->ScaleSet = DxScaleSet;
  1396.     Crtc->ScaleSave = DxScaleSave;
  1397.     Crtc->ScaleRestore = DxScaleRestore;
  1398.     Crtc->ScaleDestroy = DxScaleDestroy;
  1399.     Crtc->ScalePriv = NULL;
  1400.  
  1401.     Crtc->LUTSelect = D2LUTSelect;
  1402.     Crtc->LUTSave = DxLUTSave;
  1403.     Crtc->LUTRestore = DxLUTRestore;
  1404.     Crtc->LUTDestroy = DxLUTDestroy;
  1405.     Crtc->LUTPriv = NULL;
  1406.  
  1407.     Crtc->FrameSet  = D2ViewPortStart;
  1408.  
  1409.     Crtc->Power     = D2Power;
  1410.     Crtc->Blank     = D2Blank;
  1411.  
  1412.     rhdPtr->Crtc[1] = Crtc;
  1413.  
  1414.     return !useAtom;
  1415. }
  1416.  
  1417. /*
  1418.  *
  1419.  */
  1420. void
  1421. RHDCrtcsDestroy(RHDPtr rhdPtr)
  1422. {
  1423.     struct rhdCrtc *Crtc;
  1424.     int i;
  1425.  
  1426.     RHDFUNC(rhdPtr);
  1427.  
  1428.     for (i = 0; i < 2; i++) {
  1429.         Crtc = rhdPtr->Crtc[i];
  1430.     if (Crtc) {
  1431.             if (Crtc->FMTDestroy)
  1432.                 Crtc->FMTDestroy(Crtc);
  1433.  
  1434.             if (Crtc->LUTDestroy)
  1435.                 Crtc->LUTDestroy(Crtc);
  1436.  
  1437.             if (Crtc->FBDestroy)
  1438.                 Crtc->FBDestroy(Crtc);
  1439.  
  1440.             if (Crtc->ScaleDestroy)
  1441.                 Crtc->ScaleDestroy(Crtc);
  1442.  
  1443.             if (Crtc->ModeDestroy)
  1444.                 Crtc->ModeDestroy(Crtc);
  1445.  
  1446.             xfree(Crtc);
  1447.             rhdPtr->Crtc[i] = NULL;
  1448.         }
  1449.     }
  1450. }
  1451.  
  1452.  
  1453. /*
  1454.  *
  1455.  */
  1456. void
  1457. RHDCrtcSave(struct rhdCrtc *Crtc)
  1458. {
  1459.     RHDDebug(Crtc->scrnIndex, "%s: %s\n", __func__, Crtc->Name);
  1460.  
  1461.     if (Crtc->FMTSave)
  1462.         Crtc->FMTSave(Crtc);
  1463.  
  1464.     if (Crtc->FBSave)
  1465.         Crtc->FBSave(Crtc);
  1466.  
  1467.     if (Crtc->LUTSave)
  1468.         Crtc->LUTSave(Crtc);
  1469.  
  1470.     if (Crtc->ScaleSave)
  1471.         Crtc->ScaleSave(Crtc);
  1472.  
  1473.     if (Crtc->ModeSave)
  1474.         Crtc->ModeSave(Crtc);
  1475. }
  1476.  
  1477. /*
  1478.  *
  1479.  */
  1480. void
  1481. RHDCrtcRestore(struct rhdCrtc *Crtc)
  1482. {
  1483.  
  1484.     RHDDebug(Crtc->scrnIndex, "%s: %s\n", __func__, Crtc->Name);
  1485.  
  1486.     if (Crtc->FMTRestore)
  1487.         Crtc->FMTRestore(Crtc);
  1488.  
  1489.     if (Crtc->FBRestore)
  1490.         Crtc->FBRestore(Crtc);
  1491.  
  1492.     if (Crtc->LUTRestore)
  1493.         Crtc->LUTRestore(Crtc);
  1494.  
  1495.     if (Crtc->ScaleRestore)
  1496.         Crtc->ScaleRestore(Crtc);
  1497.  
  1498.     if (Crtc->ModeRestore)
  1499.         Crtc->ModeRestore(Crtc);
  1500. }
  1501.