Subversion Repositories Kolibri OS

Rev

Go to most recent revision | 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. /*
  27.  * MC idling:
  28.  *
  29.  * For SetupFBLocation and Restore, we require a fully idle MC as we might lock up
  30.  * otherwise. Both calls now check whether the MC is Idle before attempting
  31.  * to set up the MC, and complain loudly when this fails.
  32.  *
  33.  * Likely suspect registers for when the Idle fails:
  34.  *   DxVGA_CONTROL & D1VGA_MODE_ENABLE (run RHDVGADisable beforehand)
  35.  *   DxCRTC_CONTROL & 0x1 (run DxCRTCDisable beforehand)
  36.  *   (... Add more here...)
  37.  *
  38.  *
  39.  * MC addressing:
  40.  *
  41.  * On R600 and up the MC can use a larger than 32bit card internal address for
  42.  * its framebuffer. This is why the Address used inside the MC code is a
  43.  * CARD64.
  44.  *
  45.  * rhdPtr->FbIntAddress is kept as a CARD32 for the time being. This is still
  46.  * valid, as this makes the R500 code simpler, and since we pick FbIntAddress
  47.  * from a 32bit register anyway on R600. FbIntAddress will also correctly cast
  48.  * to a CARD64 when passed to the likes of the SetupFBLocation callback.
  49.  */
  50.  
  51. #ifdef HAVE_CONFIG_H
  52. #include "config.h"
  53. #endif
  54.  
  55. #if HAVE_XF86_ANSIC_H
  56. # include "xf86_ansic.h"
  57. #else
  58. # include <unistd.h>
  59. #endif
  60.  
  61. #include "xf86.h"
  62.  
  63. #include "rhd.h"
  64. #include "rhd_regs.h"
  65. #include "rhd_crtc.h" /* for definition of Crtc->Id */
  66.  
  67. struct rhdMC {
  68.     int scrnIndex;
  69.  
  70.     CARD32 FbLocation;
  71.     CARD32 HdpFbAddress;
  72.     CARD32 MiscLatencyTimer;
  73.     Bool Stored;
  74.     void (*Save)(struct rhdMC *MC);
  75.     void (*Restore)(struct rhdMC *MC);
  76.     Bool (*Idle)(struct rhdMC *MC);
  77.     CARD64 (*GetFBLocation)(struct rhdMC *MC, CARD32 *size);
  78.     void (*SetupFBLocation)(struct rhdMC *MC, CARD64 Address, CARD32 Size);
  79.     void (*TuneAccessForDisplay)(struct rhdMC *MC, int crtc,
  80.                                    DisplayModePtr Mode, DisplayModePtr ScaledToMode);
  81. };
  82.  
  83. /*
  84.  * Some common FB location calculations.
  85.  */
  86. /*
  87.  * Applicable for all R5xx and RS600, RS690, RS740
  88.  */
  89. static CARD64
  90. R5xxMCGetFBLocation(CARD32 Value, CARD32 *Size)
  91. {
  92.     *Size = (Value & 0xFFFF0000) - ((Value & 0xFFFF) << 16);
  93.     return  (Value & 0xFFFF) << 16;
  94. }
  95.  
  96. #define R5XX_FB_LOCATION(address, size) \
  97.     ((((address) + (size)) & 0xFFFF0000) | (((address) >> 16) & 0xFFFF))
  98. #define R5XX_HDP_LOCATION(address) \
  99.     (((address) >> 16) & 0xFFFF)
  100.  
  101. /*
  102.  * Applicable for all R6xx and R7xx, and RS780/RS790
  103.  */
  104. static CARD64
  105. R6xxMCGetFBLocation(CARD32 Value, CARD32 *Size)
  106. {
  107.     *Size = (((Value & 0xFFFF0000) - ((Value & 0xFFFF) << 16))) << 8;
  108.     return (Value & 0xFFFF) << 24;
  109. }
  110.  
  111. #define R6XX_FB_LOCATION(address, size) \
  112.     (((((address) + (size)) >> 8) & 0xFFFF0000) | (((address) >> 24) & 0xFFFF))
  113. #define R6XX_HDP_LOCATION(address) \
  114.     ((((address) >> 8) & 0x00FF0000))
  115.  
  116. /*
  117.  *
  118.  */
  119. static void
  120. RV515MCSave(struct rhdMC *MC)
  121. {
  122.     MC->FbLocation = RHDReadMC(MC, MC_IND_ALL | RV515_MC_FB_LOCATION);
  123.     MC->MiscLatencyTimer = RHDReadMC(MC, MC_IND_ALL | RV515_MC_MISC_LAT_TIMER);
  124.     MC->HdpFbAddress = RHDRegRead(MC, HDP_FB_LOCATION);
  125. }
  126.  
  127. /*
  128.  *
  129.  */
  130. static void
  131. RV515MCRestore(struct rhdMC *MC)
  132. {
  133.     RHDWriteMC(MC, MC_IND_ALL | RV515_MC_FB_LOCATION, MC->FbLocation);
  134.     RHDWriteMC(MC, MC_IND_ALL | RV515_MC_MISC_LAT_TIMER, MC->MiscLatencyTimer);
  135.     RHDRegWrite(MC, HDP_FB_LOCATION, MC->HdpFbAddress);
  136. }
  137.  
  138. /*
  139.  *
  140.  */
  141. static Bool
  142. RV515MCWaitIdle(struct rhdMC *MC)
  143. {
  144.     if (RHDReadMC(MC, MC_IND_ALL | RV515_MC_STATUS) & RV515_MC_IDLE)
  145.         return TRUE;
  146.     return FALSE;
  147. }
  148.  
  149. /*
  150.  *
  151.  */
  152. static CARD64
  153. RV515MCGetFBLocation(struct rhdMC *MC, CARD32 *Size)
  154. {
  155.     return R5xxMCGetFBLocation(RHDReadMC(MC, RV515_MC_FB_LOCATION | MC_IND_ALL), Size);
  156. }
  157.  
  158. /*
  159.  *
  160.  */
  161. static void
  162. RV515MCSetupFBLocation(struct rhdMC *MC, CARD64 Address, CARD32 Size)
  163. {
  164.     RHDWriteMC(MC, RV515_MC_FB_LOCATION | MC_IND_ALL,
  165.                R5XX_FB_LOCATION(Address, Size));
  166.     RHDRegWrite(MC, HDP_FB_LOCATION, R5XX_HDP_LOCATION(Address));
  167. }
  168.  
  169. /*
  170.  *
  171.  */
  172. static void
  173. RV515MCTuneMCAccessForDisplay(struct rhdMC *MC, int Crtc,
  174.                     DisplayModePtr Mode, DisplayModePtr ScaledToMode)
  175. {
  176.     CARD32 value, setting = 0x1;
  177.  
  178.     value = RHDReadMC(MC, RV515_MC_MISC_LAT_TIMER);
  179.  
  180.     if (Crtc == RHD_CRTC_1) {
  181.         value &= ~(0x0F << MC_DISP0R_INIT_LAT_SHIFT);
  182.         value |= setting << MC_DISP0R_INIT_LAT_SHIFT;
  183.     } else { /* RHD_CRTC_2 */
  184.         value &= ~(0x0F << MC_DISP1R_INIT_LAT_SHIFT);
  185.         value |= setting << MC_DISP1R_INIT_LAT_SHIFT;
  186.     }
  187.  
  188.     RHDWriteMC(MC, RV515_MC_MISC_LAT_TIMER, value);
  189. }
  190.  
  191. /*
  192.  *
  193.  */
  194. static void
  195. R500MCSave(struct rhdMC *MC)
  196. {
  197.     MC->FbLocation = RHDReadMC(MC, MC_IND_ALL | R5XX_MC_FB_LOCATION);
  198.     MC->HdpFbAddress = RHDRegRead(MC, HDP_FB_LOCATION);
  199. }
  200.  
  201. /*
  202.  *
  203.  */
  204. static void
  205. R500MCRestore(struct rhdMC *MC)
  206. {
  207.     RHDWriteMC(MC, MC_IND_ALL | R5XX_MC_FB_LOCATION, MC->FbLocation);
  208.     RHDRegWrite(MC, HDP_FB_LOCATION, MC->HdpFbAddress);
  209. }
  210.  
  211. /*
  212.  *
  213.  */
  214. static Bool
  215. R500MCWaitIdle(struct rhdMC *MC)
  216. {
  217.     if (RHDReadMC(MC, MC_IND_ALL | R5XX_MC_STATUS) & R5XX_MC_IDLE)
  218.         return TRUE;
  219.     return FALSE;
  220. }
  221.  
  222. /*
  223.  *
  224.  */
  225. static CARD64
  226. R500MCGetFBLocation(struct rhdMC *MC, CARD32 *Size)
  227. {
  228.     return R5xxMCGetFBLocation(RHDReadMC(MC, R5XX_MC_FB_LOCATION | MC_IND_ALL), Size);
  229. }
  230.  
  231. /*
  232.  *
  233.  */
  234. static void
  235. R500MCSetupFBLocation(struct rhdMC *MC, CARD64 Address, CARD32 Size)
  236. {
  237.     RHDWriteMC(MC, R5XX_MC_FB_LOCATION | MC_IND_ALL,
  238.                R5XX_FB_LOCATION(Address, Size));
  239.     RHDRegWrite(MC, HDP_FB_LOCATION, R5XX_HDP_LOCATION(Address));
  240. }
  241.  
  242. /*
  243.  *
  244.  */
  245. static void
  246. RS600MCSave(struct rhdMC *MC)
  247. {
  248.     MC->FbLocation = RHDReadMC(MC, RS60_NB_FB_LOCATION);
  249.     MC->HdpFbAddress = RHDRegRead(MC, HDP_FB_LOCATION);
  250. }
  251.  
  252. /*
  253.  *
  254.  */
  255. static void
  256. RS600MCRestore(struct rhdMC *MC)
  257. {
  258.     RHDWriteMC(MC, RS60_NB_FB_LOCATION, MC->FbLocation);
  259.     RHDRegWrite(MC, HDP_FB_LOCATION, MC->HdpFbAddress);
  260. }
  261.  
  262. /*
  263.  *
  264.  */
  265. static Bool
  266. RS600MCWaitIdle(struct rhdMC *MC)
  267. {
  268.     if (RHDReadMC(MC, RS60_MC_SYSTEM_STATUS) & RS6X_MC_SEQUENCER_IDLE)
  269.         return TRUE;
  270.     return FALSE;
  271. }
  272.  
  273. /*
  274.  *
  275.  */
  276. static CARD64
  277. RS600MCGetFBLocation(struct rhdMC *MC, CARD32 *Size)
  278. {
  279.     return R5xxMCGetFBLocation(RHDReadMC(MC, RS60_NB_FB_LOCATION), Size);
  280. }
  281.  
  282. /*
  283.  *
  284.  */
  285. static void
  286. RS600MCSetupFBLocation(struct rhdMC *MC, CARD64 Address, CARD32 Size)
  287. {
  288.     RHDWriteMC(MC, RS60_NB_FB_LOCATION, R5XX_FB_LOCATION(Address, Size));
  289.     RHDRegWrite(MC, HDP_FB_LOCATION, R5XX_HDP_LOCATION(Address));
  290. }
  291.  
  292. /*
  293.  *
  294.  */
  295. static void
  296. RS690MCSave(struct rhdMC *MC)
  297. {
  298.     MC->FbLocation = RHDReadMC(MC, RS69_MCCFG_FB_LOCATION);
  299.     MC->HdpFbAddress = RHDRegRead(MC, HDP_FB_LOCATION);
  300.     MC->MiscLatencyTimer = RHDReadMC(MC, RS69_MC_INIT_MISC_LAT_TIMER);
  301.  
  302. }
  303.  
  304. /*
  305.  *
  306.  */
  307. static void
  308. RS690MCRestore(struct rhdMC *MC)
  309. {
  310.     RHDWriteMC(MC, RS69_MCCFG_FB_LOCATION, MC->FbLocation);
  311.     RHDRegWrite(MC, HDP_FB_LOCATION, MC->HdpFbAddress);
  312.     RHDWriteMC(MC, RS69_MC_INIT_MISC_LAT_TIMER, MC->MiscLatencyTimer);
  313. }
  314.  
  315. /*
  316.  *
  317.  */
  318. static Bool
  319. RS690MCWaitIdle(struct rhdMC *MC)
  320. {
  321.     if (RHDReadMC(MC, RS69_MC_SYSTEM_STATUS) & RS6X_MC_SEQUENCER_IDLE)
  322.         return TRUE;
  323.     return FALSE;
  324. }
  325.  
  326. /*
  327.  *
  328.  */
  329. static CARD64
  330. RS690MCGetFBLocation(struct rhdMC *MC, CARD32 *Size)
  331. {
  332.     return R5xxMCGetFBLocation(RHDReadMC(MC, RS69_MCCFG_FB_LOCATION), Size);
  333. }
  334.  
  335. /*
  336.  *
  337.  */
  338. static void
  339. RS690MCSetupFBLocation(struct rhdMC *MC, CARD64 Address, CARD32 Size)
  340. {
  341.     RHDWriteMC(MC, RS69_MCCFG_FB_LOCATION, R5XX_FB_LOCATION(Address, Size));
  342.     RHDRegWrite(MC, HDP_FB_LOCATION, R5XX_HDP_LOCATION(Address));
  343. }
  344.  
  345. /*
  346.  *
  347.  */
  348. static void
  349. RS690MCTuneMCAccessForDisplay(struct rhdMC *MC, int Crtc,
  350.                       DisplayModePtr Mode, DisplayModePtr ScaledToMode)
  351. {
  352.     CARD32 value, setting = 0x1;
  353.  
  354.     value = RHDReadMC(MC, RS69_MC_INIT_MISC_LAT_TIMER);
  355.  
  356.     if (Crtc == RHD_CRTC_1) {
  357.         value &= ~(0x0F << MC_DISP0R_INIT_LAT_SHIFT);
  358.         value |= setting << MC_DISP0R_INIT_LAT_SHIFT;
  359.     } else { /* RHD_CRTC_2 */
  360.         value &= ~(0x0F << MC_DISP1R_INIT_LAT_SHIFT);
  361.         value |= setting << MC_DISP1R_INIT_LAT_SHIFT;
  362.     }
  363.  
  364.     RHDWriteMC(MC, RS69_MC_INIT_MISC_LAT_TIMER, value);
  365. }
  366.  
  367. /*
  368.  *
  369.  */
  370. static void
  371. R600MCSave(struct rhdMC *MC)
  372. {
  373.     MC->FbLocation = RHDRegRead(MC, R6XX_MC_VM_FB_LOCATION);
  374.     MC->HdpFbAddress = RHDRegRead(MC, R6XX_HDP_NONSURFACE_BASE);
  375. }
  376.  
  377. /*
  378.  *
  379.  */
  380. static void
  381. R600MCRestore(struct rhdMC *MC)
  382. {
  383.     RHDRegWrite(MC, R6XX_MC_VM_FB_LOCATION, MC->FbLocation);
  384.     RHDRegWrite(MC, R6XX_HDP_NONSURFACE_BASE, MC->HdpFbAddress);
  385. }
  386.  
  387. /*
  388.  *
  389.  */
  390. static Bool
  391. R600MCWaitIdle(struct rhdMC *MC)
  392. {
  393.     if (!(RHDRegRead(MC, SRBM_STATUS) & 0x3f00))
  394.         return TRUE;
  395.     return FALSE;
  396. }
  397.  
  398.  
  399. /*
  400.  *
  401.  */
  402. static CARD64
  403. R600MCGetFBLocation(struct rhdMC *MC, CARD32 *Size)
  404. {
  405.     return R6xxMCGetFBLocation(RHDRegRead(MC, R6XX_MC_VM_FB_LOCATION), Size);
  406. }
  407.  
  408. /*
  409.  *
  410.  */
  411. static void
  412. R600MCSetupFBLocation(struct rhdMC *MC, CARD64 Address, CARD32 Size)
  413. {
  414.     RHDRegWrite(MC, R6XX_MC_VM_FB_LOCATION, R6XX_FB_LOCATION(Address, Size));
  415.     RHDRegWrite(MC, R6XX_HDP_NONSURFACE_BASE, R6XX_HDP_LOCATION(Address));
  416. }
  417.  
  418. /*
  419.  *
  420.  */
  421. #ifdef NOTYET
  422.  
  423. /*
  424.  *
  425.  */
  426. static void
  427. RS780MCSave(struct rhdMC *MC)
  428. {
  429.     MC->FbLocation = RHDReadMC(MC, RS78_MC_FB_LOCATION);
  430.     MC->HdpFbAddress = RHDRegRead(MC, R6XX_HDP_NONSURFACE_BASE);
  431. }
  432.  
  433. /*
  434.  *
  435.  */
  436. static void
  437. RS780MCRestore(struct rhdMC *MC)
  438. {
  439.     RHDWriteMC(MC, RS78_MC_FB_LOCATION, MC->FbLocation);
  440.     RHDRegWrite(MC, R6XX_HDP_NONSURFACE_BASE, MC->HdpFbAddress);
  441. }
  442.  
  443. /*
  444.  *
  445.  */
  446. static Bool
  447. RS780MCWaitIdle(struct rhdMC *MC)
  448. {
  449.     if (RHDReadMC(MC, RS78_MC_SYSTEM_STATUS) & RS78_MC_SEQUENCER_IDLE)
  450.         return TRUE;
  451.     return FALSE;
  452. }
  453.  
  454. /*
  455.  *
  456.  */
  457. static CARD64
  458. RS780MCGetFBLocation(struct rhdMC *MC, CARD32 *Size)
  459. {
  460.     /* is this correct? */
  461.  
  462.     return R5xxMCGetFBLocation(RHDReadMC(MC, RS78_MC_FB_LOCATION), Size);
  463. }
  464.  
  465. /*
  466.  *
  467.  */
  468. static void
  469. RS780MCSetupFBLocation(struct rhdMC *MC, CARD64 Address, CARD32 Size)
  470. {
  471.     /* is this correct? */
  472.     RHDWriteMC(MC, RS78_MC_FB_LOCATION, R5XX_FB_LOCATION(Address, Size));
  473.     RHDRegWrite(MC, R6XX_HDP_NONSURFACE_BASE, R6XX_HDP_LOCATION(Address));
  474. }
  475. #endif /* NOTYET */
  476.  
  477. /*
  478.  *
  479.  */
  480. static void
  481. R700MCSave(struct rhdMC *MC)
  482. {
  483.     MC->FbLocation = RHDRegRead(MC, R7XX_MC_VM_FB_LOCATION);
  484.     MC->HdpFbAddress = RHDRegRead(MC, R6XX_HDP_NONSURFACE_BASE);
  485. }
  486.  
  487. /*
  488.  *
  489.  */
  490. static void
  491. R700MCRestore(struct rhdMC *MC)
  492. {
  493.     RHDFUNC(MC);
  494.  
  495.     RHDRegWrite(MC, R7XX_MC_VM_FB_LOCATION, MC->FbLocation);
  496.     RHDRegWrite(MC, R6XX_HDP_NONSURFACE_BASE, MC->HdpFbAddress);
  497. }
  498.  
  499. /*
  500.  * Idle is the R600 one...
  501.  */
  502.  
  503. /*
  504.  *
  505.  */
  506. static CARD64
  507. R700MCGetFBLocation(struct rhdMC *MC, CARD32 *Size)
  508. {
  509.     return R6xxMCGetFBLocation(RHDRegRead(MC, R7XX_MC_VM_FB_LOCATION), Size);
  510. }
  511.  
  512. /*
  513.  *
  514.  */
  515. static void
  516. R700MCSetupFBLocation(struct rhdMC *MC, CARD64 Address, CARD32 Size)
  517. {
  518.     RHDRegWrite(MC, R7XX_MC_VM_FB_LOCATION, R6XX_FB_LOCATION(Address, Size));
  519.     RHDRegWrite(MC, R6XX_HDP_NONSURFACE_BASE, R6XX_HDP_LOCATION(Address));
  520. }
  521.  
  522.  
  523. /*
  524.  *
  525.  */
  526. void
  527. RHDMCInit(RHDPtr rhdPtr)
  528. {
  529.     struct rhdMC *MC;
  530.  
  531.     RHDFUNC(rhdPtr);
  532.  
  533.     /* These devices have an internal address reference, which some other
  534.      * address registers in there also use. This can be different from the
  535.      * address in the BAR.
  536.      *
  537.      * We read out the address here from some known location. This address
  538.      * is as good a guess as any, we just need to pick one, but then make
  539.      * sure that it is made consistent in MCSetupFBLocation and the various MC
  540.      * accessing subsystems.
  541.      */
  542.  
  543.     RHDDebug(rhdPtr->scrnIndex, "MC FB Address: 0x%08X.\n",
  544.              rhdPtr->FbIntAddress);
  545.  
  546.     MC = xnfcalloc(1, sizeof(struct rhdMC));
  547.     MC->scrnIndex = rhdPtr->scrnIndex;
  548.  
  549.     if (rhdPtr->ChipSet < RHD_RS600) {
  550.         switch(rhdPtr->ChipSet) {
  551.         case RHD_RV515:
  552.         case RHD_RV505:
  553.         case RHD_RV516:
  554.         case RHD_RV550:
  555.         case RHD_M52:
  556.         case RHD_M54:
  557.         case RHD_M62:
  558.         case RHD_M64:
  559.         case RHD_M71:
  560.             MC->Save = RV515MCSave;
  561.             MC->Restore = RV515MCRestore;
  562.             MC->SetupFBLocation = RV515MCSetupFBLocation;
  563.             MC->GetFBLocation = RV515MCGetFBLocation;
  564.             MC->Idle = RV515MCWaitIdle;
  565.             MC->TuneAccessForDisplay = RV515MCTuneMCAccessForDisplay;
  566.             break;
  567.         default:
  568.             MC->Save = R500MCSave;
  569.             MC->Restore = R500MCRestore;
  570.             MC->SetupFBLocation = R500MCSetupFBLocation;
  571.             MC->GetFBLocation = R500MCGetFBLocation;
  572.             MC->Idle = R500MCWaitIdle;
  573.             break;
  574.         }
  575.  
  576.     } else if (rhdPtr->ChipSet == RHD_RS600) {
  577.         MC->Save = RS600MCSave;
  578.         MC->Restore = RS600MCRestore;
  579.         MC->SetupFBLocation = RS600MCSetupFBLocation;
  580.         MC->Idle = RS600MCWaitIdle;
  581.         MC->GetFBLocation = RS600MCGetFBLocation;
  582.     } else if (rhdPtr->ChipSet < RHD_R600) {
  583.         MC->Save = RS690MCSave;
  584.         MC->Restore = RS690MCRestore;
  585.         MC->SetupFBLocation = RS690MCSetupFBLocation;
  586.         MC->Idle = RS690MCWaitIdle;
  587.         MC->GetFBLocation = RS690MCGetFBLocation;
  588.         MC->TuneAccessForDisplay = RS690MCTuneMCAccessForDisplay;
  589.     } else if (rhdPtr->ChipSet <= RHD_RS780) {
  590.         MC->Save = R600MCSave;
  591.         MC->Restore = R600MCRestore;
  592.         MC->SetupFBLocation = R600MCSetupFBLocation;
  593.         MC->Idle = R600MCWaitIdle;
  594.         MC->GetFBLocation = R600MCGetFBLocation;
  595.     }
  596. #ifdef NOTYET
  597.     else if (rhdPtr->ChipSet == RHD_RS780) {
  598.         MC->Save = RS780MCSave;
  599.         MC->Restore = RS780MCRestore;
  600.         MC->SetupFBLocation = RS780MCSetupFBLocation;
  601.         MC->Idle = RS780MCWaitIdle;
  602.         MC->GetFBLocation = RS780MCGetFBLocation;
  603.     }
  604. #endif /* NOTYET */
  605.     else if (rhdPtr->ChipSet >= RHD_RV770) {
  606.         MC->Save = R700MCSave;
  607.         MC->Restore = R700MCRestore;
  608.         MC->SetupFBLocation = R700MCSetupFBLocation;
  609.         MC->Idle = R600MCWaitIdle;
  610.         MC->GetFBLocation = R700MCGetFBLocation;
  611.     } else {
  612.         xf86DrvMsg(rhdPtr->scrnIndex, X_ERROR, "I don't know anything about MC on this chipset\n");
  613.         xfree(MC);
  614.         return;
  615.     }
  616.     if (rhdPtr->ChipSet < RHD_R600)
  617.         rhdPtr->FbIntAddress = RHDRegRead(rhdPtr, HDP_FB_LOCATION) << 16;
  618.     else
  619.         rhdPtr->FbIntAddress = RHDRegRead(rhdPtr, R6XX_CONFIG_FB_BASE);
  620.     MC->GetFBLocation(MC, &rhdPtr->FbIntSize);
  621.  
  622.     rhdPtr->MC = MC;
  623.  
  624. }
  625.  
  626. /*
  627.  * Free structure.
  628.  */
  629. void
  630. RHDMCDestroy(RHDPtr rhdPtr)
  631. {
  632.     RHDFUNC(rhdPtr);
  633.  
  634.     if (!rhdPtr->MC)
  635.         return;
  636.  
  637.     xfree(rhdPtr->MC);
  638.     rhdPtr->MC = NULL;
  639. }
  640.  
  641. /*
  642.  *
  643.  */
  644. void
  645. RHDMCSave(RHDPtr rhdPtr)
  646. {
  647.     struct rhdMC *MC = rhdPtr->MC;
  648.  
  649.     ASSERT(MC);
  650.  
  651.     RHDFUNC(rhdPtr);
  652.  
  653.     MC->Save(MC);
  654.  
  655.     MC->Stored = TRUE;
  656. }
  657.  
  658. /*
  659.  * Make sure that nothing is accessing memory anymore before calling this.
  660.  */
  661. void
  662. RHDMCRestore(RHDPtr rhdPtr)
  663. {
  664.     struct rhdMC *MC = rhdPtr->MC;
  665.  
  666.  //   ASSERT(MC);
  667.  //   RHD_UNSETDEBUGFLAG(rhdPtr, MC_SETUP);
  668.  
  669.     RHDFUNC(rhdPtr);
  670.  
  671.     if (!MC->Stored) {
  672.         xf86DrvMsg(rhdPtr->scrnIndex, X_ERROR,
  673.                    "%s: trying to restore uninitialized values.\n",__func__);
  674.         return;
  675.     }
  676.  
  677.     if (MC->Idle(MC))
  678.         MC->Restore(MC);
  679.     else
  680.         xf86DrvMsg(rhdPtr->scrnIndex, X_ERROR,
  681.                    "%s: MC is still not idle!!!\n", __func__);
  682. }
  683.  
  684. /*
  685.  *
  686.  */
  687. Bool
  688. RHDMCIdleWait(RHDPtr rhdPtr, CARD32 count)
  689. {
  690.     struct rhdMC *MC = rhdPtr->MC;
  691.  
  692.     RHDFUNC(rhdPtr);
  693.  
  694.     ASSERT(MC);
  695.  
  696.     do {
  697.         if (MC->Idle(MC))
  698.             return TRUE;
  699.     usleep(100);
  700.     } while (count--);
  701.  
  702.     RHDDebug(rhdPtr->scrnIndex, "%s: MC not idle\n",__func__);
  703.  
  704.     return FALSE;
  705. }
  706.  
  707. /*
  708.  * Get FB location and size.
  709.  */
  710. CARD64
  711. RHDMCGetFBLocation(RHDPtr rhdPtr, CARD32 *size)
  712. {
  713.     struct rhdMC *MC = rhdPtr->MC;
  714.  
  715.  //   ASSERT(MC);
  716.  //   ASSERT(size);
  717.  
  718.     RHDFUNC(rhdPtr);
  719.  
  720.     return MC->GetFBLocation(MC, size);
  721. }
  722.  
  723. /*
  724.  * Make sure that nothing is accessing memory anymore before calling this.
  725.  */
  726. Bool
  727. RHDMCSetupFBLocation(RHDPtr rhdPtr, CARD64 Address, CARD32 Size)
  728. {
  729.     struct rhdMC *MC = rhdPtr->MC;
  730.     CARD64 OldAddress;
  731.     CARD32 OldSize;
  732.  
  733.  //   ASSERT(MC);
  734.  //   RHD_SETDEBUGFLAG(rhdPtr, MC_SETUP);
  735.  
  736.     RHDFUNC(rhdPtr);
  737.  
  738.     if (!MC->Idle(MC)) {
  739.         xf86DrvMsg(rhdPtr->scrnIndex, X_ERROR,
  740.                    "%s: Cannot setup MC: not idle!!!\n", __func__);
  741.         return FALSE;
  742.     }
  743.  
  744.     OldAddress = MC->GetFBLocation(MC, &OldSize);
  745.     if (OldAddress == Address && OldSize == Size)
  746.         return TRUE;
  747.  
  748.     /* If this ever occurs, we might have issues */
  749.     if (OldAddress >> 32)
  750.         xf86DrvMsg(rhdPtr->scrnIndex, X_WARNING, "%s: Board claims to use a "
  751.                    "higher than 32bit address for its FB\n", __func__);
  752.  
  753.     RHDDebug(rhdPtr->scrnIndex,
  754.              "Setting MC from 0x%08X to 0x%08X [Size 0x%08X]\n",
  755.              OldAddress, rhdPtr->FbIntAddress, Size);
  756.  
  757.     MC->SetupFBLocation(MC, Address, Size);
  758.  
  759.     return TRUE;
  760. }
  761.  
  762. /*
  763.  *
  764.  */
  765. void
  766. RHDMCTuneAccessForDisplay(RHDPtr rhdPtr, int Crtc,
  767.                     DisplayModePtr Mode, DisplayModePtr ScaledToMode)
  768. {
  769.     struct rhdMC *MC = rhdPtr->MC;
  770.  
  771.     ASSERT(MC);
  772.  
  773.     RHDFUNC(rhdPtr);
  774.  
  775.     if (MC->TuneAccessForDisplay)
  776.         MC->TuneAccessForDisplay(MC, Crtc, Mode, ScaledToMode);
  777. }
  778.  
  779. /*
  780.  *
  781.  */
  782. Bool
  783. RHD_MC_IGP_SideportMemoryPresent(RHDPtr rhdPtr)
  784. {
  785.     Bool Present = FALSE;
  786.  
  787.     RHDFUNC(rhdPtr);
  788.  
  789.     switch (rhdPtr->ChipSet) {
  790.         case RHD_RS690:
  791.         case RHD_RS740:
  792.             Present = (RHDReadMC(rhdPtr, RS69_MC_MISC_UMA_CNTL) & RS69_SIDE_PORT_PRESENT_R) != 0;
  793.             break;
  794.         case RHD_RS780:
  795.             Present = (RHDReadMC(rhdPtr, RS78_MC_MISC_UMA_CNTL) & RS78_SIDE_PORT_PRESENT_R) != 0;
  796.             break;
  797.         default:
  798.             break;
  799.     }
  800.     xf86DrvMsg(rhdPtr->scrnIndex, X_INFO, "IGP sideport memory %s present.\n", Present ? "" : "not");
  801.  
  802.     return Present;
  803. }
  804.