Subversion Repositories Kolibri OS

Rev

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

  1. /*
  2.  * Copyright 2007  Luc Verhaegen <lverhaegen@novell.com>
  3.  * Copyright 2007  Matthias Hopf <mhopf@novell.com>
  4.  * Copyright 2007  Egbert Eich   <eich@novell.com>
  5.  * Copyright 2007  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. #if HAVE_XF86_ANSIC_H
  31. # include "xf86_ansic.h"
  32. #else
  33. # include <unistd.h>
  34. #endif
  35.  
  36. #include "xf86.h"
  37.  
  38. #include "rhd.h"
  39. #include "rhd_regs.h"
  40.  
  41. Bool RHDMCIdle(RHDPtr rhdPtr, CARD32 count);
  42.  
  43. Bool RHDMCIdle(RHDPtr rhdPtr, CARD32 count);
  44.  
  45. struct rhdMC {
  46.     CARD32 FbLocation;
  47.     CARD32 HdpFbBase;
  48.     CARD32 MiscLatencyTimer;
  49.     Bool Stored;
  50.     void (*SaveMC)(RHDPtr rhdPtr);
  51.     void (*RestoreMC)(RHDPtr rhdPtr);
  52.     void (*SetupMC)(RHDPtr rhdPtr);
  53.     Bool (*MCIdle)(RHDPtr rhdPtr);
  54.     CARD32 (*GetFBLocation)(RHDPtr rhdPtr, CARD32 *size);
  55.     void (*TuneMCAccessForDisplay)(RHDPtr rhdPtr, int crtc,
  56.                                    DisplayModePtr Mode, DisplayModePtr ScaledToMode);
  57.     Bool RV515Variant;
  58. };
  59.  
  60. /*
  61.  * Save MC_VM state.
  62.  */
  63. static void
  64. rs600SaveMC(RHDPtr rhdPtr)
  65. {
  66.     struct rhdMC *MC = rhdPtr->MC;
  67.  
  68.     RHDFUNC(rhdPtr);
  69.  
  70.     MC->FbLocation = RHDReadMC(rhdPtr, RS60_NB_FB_LOCATION);
  71.     MC->HdpFbBase = RHDRegRead(rhdPtr, HDP_FB_LOCATION);
  72. }
  73.  
  74. /*
  75.  *
  76.  */
  77. static void
  78. rs690SaveMC(RHDPtr rhdPtr)
  79. {
  80.     struct rhdMC *MC = rhdPtr->MC;
  81.  
  82.     RHDFUNC(rhdPtr);
  83.  
  84.     MC->FbLocation = RHDReadMC(rhdPtr, RS69_MCCFG_FB_LOCATION);
  85.     MC->HdpFbBase = RHDRegRead(rhdPtr, HDP_FB_LOCATION);
  86.     MC->MiscLatencyTimer = RHDReadMC(rhdPtr, RS69_MC_INIT_MISC_LAT_TIMER);
  87. }
  88.  
  89. /*
  90.  *
  91.  */
  92. static void
  93. r6xxSaveMC(RHDPtr rhdPtr)
  94. {
  95.     struct rhdMC *MC = rhdPtr->MC;
  96.  
  97.     RHDFUNC(rhdPtr);
  98.  
  99.     MC->FbLocation = RHDRegRead(rhdPtr, R6XX_MC_VM_FB_LOCATION);
  100.     MC->HdpFbBase = RHDRegRead(rhdPtr, R6XX_HDP_NONSURFACE_BASE);
  101. }
  102.  
  103. /*
  104.  *
  105.  */
  106. #ifdef NOTYET
  107. static void
  108. rs780SaveMC(RHDPtr rhdPtr)
  109. {
  110.     struct rhdMC *MC = rhdPtr->MC;
  111.  
  112.     RHDFUNC(rhdPtr);
  113.  
  114.     MC->FbLocation = RHDReadMC(rhdPtr, RS78_MC_FB_LOCATION);
  115.     /* RS780 uses the same register as R6xx */
  116.     MC->HdpFbBase = RHDRegRead(rhdPtr, R6XX_HDP_NONSURFACE_BASE);
  117. }
  118. #endif
  119.  
  120. /*
  121.  *
  122.  */
  123. static void
  124. r7xxSaveMC(RHDPtr rhdPtr)
  125. {
  126.     struct rhdMC *MC = rhdPtr->MC;
  127.  
  128.     RHDFUNC(rhdPtr);
  129.  
  130.     MC->FbLocation = RHDRegRead(rhdPtr, R7XX_MC_VM_FB_LOCATION);
  131.     MC->HdpFbBase = RHDRegRead(rhdPtr, R6XX_HDP_NONSURFACE_BASE);
  132. }
  133.  
  134. /*
  135.  *
  136.  */
  137. static void
  138. r5xxRestoreMC(RHDPtr rhdPtr)
  139. {
  140.     struct rhdMC *MC = rhdPtr->MC;
  141.  
  142.     RHDFUNC(rhdPtr);
  143.  
  144.     if (MC->RV515Variant) {
  145.         RHDWriteMC(rhdPtr, MC_IND_ALL |  RV515_MC_FB_LOCATION,
  146.                    MC->FbLocation);
  147.         RHDWriteMC(rhdPtr, MC_IND_ALL |  RV515_MC_MISC_LAT_TIMER,
  148.                    MC->MiscLatencyTimer);
  149.     } else
  150.         RHDWriteMC(rhdPtr, MC_IND_ALL | R5XX_MC_FB_LOCATION,
  151.                    MC->FbLocation);
  152.     RHDRegWrite(rhdPtr, HDP_FB_LOCATION, MC->HdpFbBase);
  153. }
  154.  
  155. /*
  156.  *
  157.  */
  158. static void
  159. rs600RestoreMC(RHDPtr rhdPtr)
  160. {
  161.     struct rhdMC *MC = rhdPtr->MC;
  162.  
  163.     RHDFUNC(rhdPtr);
  164.  
  165.     RHDWriteMC(rhdPtr, RS60_NB_FB_LOCATION, MC->FbLocation);
  166.     RHDRegWrite(rhdPtr, HDP_FB_LOCATION, MC->HdpFbBase);
  167. }
  168.  
  169. /*
  170.  *
  171.  */
  172. static void
  173. rs690RestoreMC(RHDPtr rhdPtr)
  174. {
  175.     struct rhdMC *MC = rhdPtr->MC;
  176.  
  177.     RHDFUNC(rhdPtr);
  178.  
  179.     RHDWriteMC(rhdPtr,  RS69_MCCFG_FB_LOCATION, MC->FbLocation);
  180.     RHDRegWrite(rhdPtr, HDP_FB_LOCATION, MC->HdpFbBase);
  181.     RHDWriteMC(rhdPtr,  RS69_MC_INIT_MISC_LAT_TIMER, MC->MiscLatencyTimer);
  182. }
  183.  
  184. /*
  185.  *
  186.  */
  187. static void
  188. r6xxRestoreMC(RHDPtr rhdPtr)
  189. {
  190.     struct rhdMC *MC = rhdPtr->MC;
  191.  
  192.     RHDFUNC(rhdPtr);
  193.  
  194.     RHDRegWrite(rhdPtr, R6XX_MC_VM_FB_LOCATION, MC->FbLocation);
  195.     RHDRegWrite(rhdPtr, R6XX_HDP_NONSURFACE_BASE, MC->HdpFbBase);
  196. }
  197.  
  198. /*
  199.  *
  200.  */
  201. #ifdef NOTYET
  202. static void
  203. rs780RestoreMC(RHDPtr rhdPtr)
  204. {
  205.     struct rhdMC *MC = rhdPtr->MC;
  206.  
  207.     RHDFUNC(rhdPtr);
  208.  
  209.     RHDWriteMC(rhdPtr, RS78_MC_FB_LOCATION, MC->FbLocation);
  210.     /* RS780 uses the same register as R6xx */
  211.     RHDRegWrite(rhdPtr, R6XX_HDP_NONSURFACE_BASE, MC->HdpFbBase);
  212. }
  213. #endif
  214.  
  215. /*
  216.  *
  217.  */
  218. static void
  219. r7xxRestoreMC(RHDPtr rhdPtr)
  220. {
  221.     struct rhdMC *MC = rhdPtr->MC;
  222.  
  223.     RHDFUNC(rhdPtr);
  224.  
  225.     RHDRegWrite(rhdPtr, R7XX_MC_VM_FB_LOCATION, MC->FbLocation);
  226.     RHDRegWrite(rhdPtr, R6XX_HDP_NONSURFACE_BASE, MC->HdpFbBase);
  227. }
  228.  
  229. /*
  230.  * Setup the MC
  231.  */
  232.  
  233. /*
  234.  *
  235.  */
  236. static void
  237. r5xxSetupMC(RHDPtr rhdPtr)
  238. {
  239.     struct rhdMC *MC = rhdPtr->MC;
  240.     CARD32 fb_location, fb_location_tmp;
  241.     CARD16 fb_size;
  242.     unsigned int reg;
  243.  
  244.     RHDFUNC(rhdPtr);
  245.  
  246.  
  247.     if (MC->RV515Variant)
  248.         reg = RV515_MC_FB_LOCATION | MC_IND_ALL;
  249.     else
  250.         reg = R5XX_MC_FB_LOCATION | MC_IND_ALL;
  251.  
  252.     fb_location = RHDReadMC(rhdPtr, reg);
  253.     fb_size = (fb_location >> 16) - (fb_location & 0xFFFF);
  254.     fb_location_tmp = rhdPtr->FbIntAddress >> 16;
  255.     fb_location_tmp |= (fb_location_tmp + fb_size) << 16;
  256.  
  257.     RHDDebug(rhdPtr->scrnIndex, "%s: fb_location: 0x%08X "
  258.              "[fb_size: 0x%04X] -> fb_location: 0x%08X\n",
  259.              __func__, (unsigned int)fb_location,
  260.              fb_size,(unsigned int)fb_location_tmp);
  261.     RHDWriteMC(rhdPtr, reg, fb_location_tmp);
  262.     RHDRegWrite(rhdPtr, HDP_FB_LOCATION, fb_location_tmp & 0xFFFF);
  263. }
  264.  
  265. /*
  266.  *
  267.  */
  268. static void
  269. rs600SetupMC(RHDPtr rhdPtr)
  270. {
  271.     CARD32 fb_location, fb_location_tmp;
  272.     CARD16 fb_size;
  273.  
  274.     RHDFUNC(rhdPtr);
  275.  
  276.     fb_location = RHDReadMC(rhdPtr, RS60_NB_FB_LOCATION);
  277.     fb_size = (fb_location >> 16) - (fb_location & 0xFFFF);
  278.     fb_location_tmp = rhdPtr->FbIntAddress >> 16;
  279.     fb_location_tmp |= (fb_location_tmp + fb_size) << 16;
  280.  
  281.     RHDDebug(rhdPtr->scrnIndex, "%s: fb_location: 0x%08X "
  282.              "[fb_size: 0x%04X] -> fb_location: 0x%08X\n",
  283.              __func__, (unsigned int)fb_location,
  284.              fb_size,(unsigned int)fb_location_tmp);
  285.     RHDWriteMC(rhdPtr, RS60_NB_FB_LOCATION, fb_location_tmp);
  286.     RHDRegWrite(rhdPtr, HDP_FB_LOCATION, fb_location_tmp & 0xFFFF); /* same ;) */
  287. }
  288.  
  289. /*
  290.  *
  291.  */
  292. static void
  293. rs690SetupMC(RHDPtr rhdPtr)
  294. {
  295.     CARD32 fb_location, fb_location_tmp;
  296.     CARD16 fb_size;
  297.  
  298.     RHDFUNC(rhdPtr);
  299.  
  300.     fb_location = RHDReadMC(rhdPtr, RS69_MCCFG_FB_LOCATION);
  301.     fb_size = (fb_location >> 16) - (fb_location & 0xFFFF);
  302.     fb_location_tmp = rhdPtr->FbIntAddress >> 16;
  303.     fb_location_tmp |= (fb_location_tmp + fb_size) << 16;
  304.  
  305.     RHDDebug(rhdPtr->scrnIndex, "%s: fb_location: 0x%08X "
  306.              "[fb_size: 0x%04X] -> fb_location: 0x%08X\n",
  307.              __func__, (unsigned int)fb_location,
  308.              fb_size,(unsigned int)fb_location_tmp);
  309.     RHDWriteMC(rhdPtr, RS69_MCCFG_FB_LOCATION, fb_location_tmp);
  310.     RHDRegWrite(rhdPtr, HDP_FB_LOCATION, fb_location_tmp & 0xFFFF);
  311. }
  312.  
  313. /*
  314.  *
  315.  */
  316. static void
  317. r6xxSetupMC(RHDPtr rhdPtr)
  318. {
  319.     CARD32 fb_location, fb_location_tmp, hdp_fbbase_tmp;
  320.     CARD16 fb_size;
  321.  
  322.     RHDFUNC(rhdPtr);
  323.  
  324.     fb_location = RHDRegRead(rhdPtr, R6XX_MC_VM_FB_LOCATION);
  325.     fb_size = (fb_location >> 16) - (fb_location & 0xFFFF);
  326.     fb_location_tmp = rhdPtr->FbIntAddress >> 24;
  327.     fb_location_tmp |= (fb_location_tmp + fb_size) << 16;
  328.     hdp_fbbase_tmp = (rhdPtr->FbIntAddress >> 8) & 0xff0000;
  329.  
  330.     RHDDebug(rhdPtr->scrnIndex, "%s: fb_location: 0x%08X "
  331.              "fb_offset: 0x%08X [fb_size: 0x%04X] -> fb_location: 0x%08X "
  332.              "fb_offset: 0x%08X\n",
  333.              __func__, (unsigned int)fb_location,
  334.              RHDRegRead(rhdPtr,R6XX_HDP_NONSURFACE_BASE), fb_size,
  335.              (unsigned int)fb_location_tmp, (unsigned int)hdp_fbbase_tmp);
  336.  
  337.     RHDRegWrite(rhdPtr, R6XX_MC_VM_FB_LOCATION, fb_location_tmp);
  338.     RHDRegWrite(rhdPtr, R6XX_HDP_NONSURFACE_BASE, hdp_fbbase_tmp);
  339. }
  340.  
  341. /*
  342.  *
  343.  */
  344. #ifdef NOTYET
  345. static void
  346. rs780SetupMC(RHDPtr rhdPtr)
  347. {
  348.     CARD32 fb_location, fb_location_tmp, hdp_fbbase_tmp;
  349.     CARD16 fb_size;
  350.  
  351.     RHDFUNC(rhdPtr);
  352.  
  353.     fb_location = RHDReadMC(rhdPtr, RS78_MC_FB_LOCATION);
  354.     fb_size = (fb_location >> 16) - (fb_location & 0xFFFF);
  355.     fb_location_tmp = rhdPtr->FbIntAddress >> 16;
  356.     fb_location_tmp |= (fb_location_tmp + fb_size) << 16;
  357.     hdp_fbbase_tmp = (rhdPtr->FbIntAddress >> 8) & 0xff0000;
  358.  
  359.     RHDDebug(rhdPtr->scrnIndex, "%s: fb_location: 0x%08X "
  360.              "[fb_size: 0x%04X] -> fb_location: 0x%08X\n",
  361.              __func__, (unsigned int)fb_location,
  362.              fb_size,(unsigned int)fb_location_tmp);
  363.     RHDWriteMC(rhdPtr, RS78_MC_FB_LOCATION, fb_location_tmp);
  364.     /* RS780 uses the same register as R6xx */
  365.     RHDRegWrite(rhdPtr, R6XX_HDP_NONSURFACE_BASE, hdp_fbbase_tmp);
  366. }
  367. #endif
  368.  
  369. /*
  370.  *
  371.  */
  372. static void
  373. r7xxSetupMC(RHDPtr rhdPtr)
  374. {
  375.     CARD32 fb_location, fb_location_tmp, hdp_fbbase_tmp;
  376.     CARD16 fb_size;
  377.  
  378.     RHDFUNC(rhdPtr);
  379.  
  380.     fb_location = RHDRegRead(rhdPtr, R7XX_MC_VM_FB_LOCATION);
  381.     fb_size = (fb_location >> 16) - (fb_location & 0xFFFF);
  382.     fb_location_tmp = rhdPtr->FbIntAddress >> 24;
  383.     fb_location_tmp |= (fb_location_tmp + fb_size) << 16;
  384.     hdp_fbbase_tmp = (rhdPtr->FbIntAddress >> 8) & 0xff0000;
  385.  
  386.     RHDDebug(rhdPtr->scrnIndex, "%s: fb_location: 0x%08X "
  387.              "fb_offset: 0x%08X [fb_size: 0x%04X] -> fb_location: 0x%08X "
  388.              "fb_offset: 0x%08X\n",
  389.              __func__, (unsigned int)fb_location,
  390.              RHDRegRead(rhdPtr,R6XX_HDP_NONSURFACE_BASE), fb_size,
  391.              (unsigned int)fb_location_tmp, (unsigned int)hdp_fbbase_tmp);
  392.  
  393.     RHDRegWrite(rhdPtr, R7XX_MC_VM_FB_LOCATION, fb_location_tmp);
  394.     RHDRegWrite(rhdPtr, R6XX_HDP_NONSURFACE_BASE, hdp_fbbase_tmp);
  395. }
  396.  
  397. /*
  398.  *
  399.  */
  400. void
  401. RHDMCSetup(RHDPtr rhdPtr)
  402. {
  403.     struct rhdMC *MC = rhdPtr->MC;
  404.     RHDFUNC(rhdPtr);
  405.  
  406.     if (!MC)
  407.         return;
  408.     /*
  409.      * make sure the hw is in a state such that we can update
  410.      * the MC - ie no subsystem is currently accessing memory.
  411.      */
  412.     ASSERT((RHDRegRead(rhdPtr, D1VGA_CONTROL) & D1VGA_MODE_ENABLE) != D1VGA_MODE_ENABLE);
  413.     ASSERT((RHDRegRead(rhdPtr, D2VGA_CONTROL) & D2VGA_MODE_ENABLE) != D2VGA_MODE_ENABLE);
  414.     ASSERT((RHDRegRead(rhdPtr, D1CRTC_CONTROL) & 0x1) != 0x1);
  415.     ASSERT((RHDRegRead(rhdPtr, D2CRTC_CONTROL) & 0x1) != 0x1);
  416.     ASSERT(RHDMCIdle(rhdPtr, 1));
  417.  
  418.     MC->SetupMC(rhdPtr);
  419. }
  420.  
  421. /*
  422.  * Get FB location and size.
  423.  */
  424. static CARD32
  425. r5xxGetFBLocation(RHDPtr rhdPtr, CARD32 *size)
  426. {
  427.     struct rhdMC *MC = rhdPtr->MC;
  428.     CARD32 val;
  429.     CARD32 reg;
  430.  
  431.     if (MC->RV515Variant)
  432.         reg = RV515_MC_FB_LOCATION | MC_IND_ALL;
  433.     else
  434.         reg = R5XX_MC_FB_LOCATION | MC_IND_ALL;
  435.  
  436.         val = RHDReadMC(rhdPtr, reg);
  437.  
  438.     if (size) *size = ((val >> 16) - (val & 0xFFFF)) << 16;
  439.  
  440.     return (val & 0xFFFF) << 16;
  441. }
  442.  
  443. /*
  444.  *
  445.  */
  446. static CARD32
  447. rs600GetFBLocation(RHDPtr rhdPtr, CARD32 *size)
  448. {
  449.     CARD32 val = RHDReadMC(rhdPtr, RS60_NB_FB_LOCATION);
  450.  
  451.     if (size) *size = ((val >> 16) - (val & 0xFFFF)) << 16;
  452.  
  453.     return (val & 0xFFFF) << 16;
  454. }
  455.  
  456. /*
  457.  *
  458.  */
  459. static CARD32
  460. rs690GetFBLocation(RHDPtr rhdPtr, CARD32 *size)
  461. {
  462.     CARD32 val = RHDReadMC(rhdPtr, RS69_MCCFG_FB_LOCATION);
  463.  
  464.     if (size) *size = ((val >> 16) - (val & 0xFFFF)) << 16;
  465.  
  466.     return (val & 0xFFFF) << 16;
  467. }
  468.  
  469. /*
  470.  *
  471.  */
  472. static CARD32
  473. r6xxGetFBLocation(RHDPtr rhdPtr, CARD32 *size)
  474. {
  475.     CARD32 val = RHDRegRead(rhdPtr, R6XX_MC_VM_FB_LOCATION);
  476.  
  477.     if (size) *size = ((val >> 16) - (val & 0xFFFF)) << 24;
  478.  
  479.     return (val & 0xFFFF) << 24;
  480. }
  481.  
  482. /*
  483.  *
  484.  */
  485. #ifdef NOTYET
  486. static CARD32
  487. rs780GetFBLocation(RHDPtr rhdPtr, CARD32 *size)
  488. {
  489.     CARD32 val = RHDReadMC(rhdPtr, RS78_MC_FB_LOCATION);
  490.     if (size) *size = ((val >> 16) - (val & 0xFFFF)) << 16;
  491.  
  492.     return (val & 0xFFFF) << 16;
  493. }
  494. #endif
  495.  
  496. /*
  497.  *
  498.  */
  499. static CARD32
  500. r7xxGetFBLocation(RHDPtr rhdPtr, CARD32 *size)
  501. {
  502.     CARD32 val = RHDRegRead(rhdPtr, R7XX_MC_VM_FB_LOCATION);
  503.  
  504.     if (size) *size = ((val >> 16) - (val & 0xFFFF)) << 24;
  505.  
  506.     return (val & 0xFFFF) << 24;
  507. }
  508.  
  509. /*
  510.  *
  511.  */
  512. CARD32
  513. RHDGetFBLocation(RHDPtr rhdPtr, CARD32 *size)
  514. {
  515.     struct rhdMC *MC = rhdPtr->MC;
  516.     RHDFUNC(rhdPtr);
  517.  
  518.     if (!MC) {
  519.         if (size) *size = 0;
  520.         return 0;
  521.     }
  522.  
  523.     return MC->GetFBLocation(rhdPtr, size);
  524. }
  525.  
  526. /*
  527.  *
  528.  */
  529. static Bool
  530. rv515MCIdle(RHDPtr rhdPtr)
  531. {
  532.     RHDFUNC(rhdPtr);
  533.  
  534.     if (RHDReadMC(rhdPtr, MC_IND_ALL | RV515_MC_STATUS) & RV515_MC_IDLE)
  535.         return TRUE;
  536.     return FALSE;
  537. }
  538.  
  539.  
  540. /*
  541.  *
  542.  */
  543. static Bool
  544. r5xxMCIdle(RHDPtr rhdPtr)
  545. {
  546.     RHDFUNC(rhdPtr);
  547.  
  548.     if (RHDReadMC(rhdPtr, MC_IND_ALL | R5XX_MC_STATUS) & R5XX_MC_IDLE)
  549.         return TRUE;
  550.     return FALSE;
  551. }
  552.  
  553. /*
  554.  *
  555.  */
  556. static Bool
  557. rs600MCIdle(RHDPtr rhdPtr)
  558. {
  559.     RHDFUNC(rhdPtr);
  560.  
  561.     if (RHDReadMC(rhdPtr, RS60_MC_SYSTEM_STATUS) & RS6X_MC_SEQUENCER_IDLE)
  562.         return TRUE;
  563.     return FALSE;
  564. }
  565.  
  566. /*
  567.  *
  568.  */
  569. static Bool
  570. rs690MCIdle(RHDPtr rhdPtr)
  571. {
  572.     RHDFUNC(rhdPtr);
  573.  
  574.     if (RHDReadMC(rhdPtr, RS69_MC_SYSTEM_STATUS) & RS6X_MC_SEQUENCER_IDLE)
  575.         return TRUE;
  576.     return FALSE;
  577. }
  578.  
  579. /*
  580.  *
  581.  */
  582. static Bool
  583. r6xxMCIdle(RHDPtr rhdPtr)
  584. {
  585.     RHDFUNC(rhdPtr);
  586.  
  587.     if (!(RHDRegRead(rhdPtr, SRBM_STATUS) & 0x3f00))
  588.         return TRUE;
  589.     return FALSE;
  590. }
  591.  
  592. /*
  593.  *
  594.  */
  595. #ifdef NOTYET
  596. static Bool
  597. rs780MCIdle(RHDPtr rhdPtr)
  598. {
  599.     RHDFUNC(rhdPtr);
  600.  
  601.     if (RHDReadMC(rhdPtr, RS78_MC_SYSTEM_STATUS) & RS78_MC_SEQUENCER_IDLE)
  602.         return TRUE;
  603.     return FALSE;
  604. }
  605. #endif
  606.  
  607. /*
  608.  *
  609.  */
  610. Bool
  611. RHDMCIdle(RHDPtr rhdPtr, CARD32 count)
  612. {
  613.     struct rhdMC *MC = rhdPtr->MC;
  614.     RHDFUNC(rhdPtr);
  615.  
  616.     if (!MC)
  617.         return TRUE;
  618.  
  619.     do {
  620.         if (MC->MCIdle(rhdPtr))
  621.             return TRUE;
  622.         usleep(10);
  623.     } while (count--);
  624.  
  625.     RHDDebug(rhdPtr->scrnIndex, "%s: MC not idle\n",__func__);
  626.  
  627.     return FALSE;
  628. }
  629.  
  630. /*
  631.  *
  632.  */
  633. void
  634. RHDSaveMC(RHDPtr rhdPtr)
  635. {
  636.     struct rhdMC *MC = rhdPtr->MC;
  637.     RHDFUNC(rhdPtr);
  638.  
  639.     if (!MC)
  640.         return;
  641.  
  642.     MC->SaveMC(rhdPtr);
  643.  
  644.     MC->Stored = TRUE;
  645. }
  646.  
  647. /*
  648.  * Restore MC VM state.
  649.  */
  650. void
  651. RHDRestoreMC(RHDPtr rhdPtr)
  652. {
  653.     struct rhdMC *MC = rhdPtr->MC;
  654.     RHDFUNC(rhdPtr);
  655.  
  656.     if (!MC)
  657.         return;
  658.  
  659.     if (!MC->Stored) {
  660.         xf86DrvMsg(rhdPtr->scrnIndex, X_ERROR,
  661.                    "%s: trying to restore uninitialized values.\n",__func__);
  662.         return;
  663.     }
  664.     /*
  665.      * make sure the hw is in a state such that we can update
  666.      * the MC - ie no subsystem is currently accessing memory.
  667.      */
  668.     ASSERT((RHDRegRead(rhdPtr, D1VGA_CONTROL) & D1VGA_MODE_ENABLE) != D1VGA_MODE_ENABLE);
  669.     ASSERT((RHDRegRead(rhdPtr, D2VGA_CONTROL) & D2VGA_MODE_ENABLE) != D2VGA_MODE_ENABLE);
  670.     ASSERT((RHDRegRead(rhdPtr, D1CRTC_CONTROL) & 0x1) != 0x1);
  671.     ASSERT((RHDRegRead(rhdPtr, D2CRTC_CONTROL) & 0x1) != 0x1);
  672.     ASSERT(RHDMCIdle(rhdPtr, 1));
  673.  
  674.     MC->RestoreMC(rhdPtr);
  675. }
  676.  
  677. /*
  678.  *
  679.  */
  680. static void
  681. r5xxSaveMC(RHDPtr rhdPtr)
  682. {
  683.     struct rhdMC *MC = rhdPtr->MC;
  684.  
  685.     RHDFUNC(rhdPtr);
  686.  
  687.     if (MC->RV515Variant) {
  688.         MC->FbLocation = RHDReadMC(rhdPtr, MC_IND_ALL | RV515_MC_FB_LOCATION);
  689.         MC->MiscLatencyTimer = RHDReadMC(rhdPtr, MC_IND_ALL | RV515_MC_MISC_LAT_TIMER);
  690.     } else
  691.         MC->FbLocation = RHDReadMC(rhdPtr, MC_IND_ALL | R5XX_MC_FB_LOCATION);
  692.     MC->HdpFbBase = RHDRegRead(rhdPtr, HDP_FB_LOCATION);
  693. }
  694.  
  695. /*
  696.  *
  697.  */
  698. static void
  699. rv515TuneMCAccessForDisplay(RHDPtr rhdPtr, int crtc,
  700.                                    DisplayModePtr Mode, DisplayModePtr ScaledToMode)
  701. {
  702.     CARD32 value, setting = 0x1;
  703.  
  704.     RHDFUNC(rhdPtr);
  705.  
  706.     value = RHDReadMC(rhdPtr,  RV515_MC_MISC_LAT_TIMER);
  707.  
  708.     value |= (setting << (crtc ? MC_DISP1R_INIT_LAT_SHIFT : MC_DISP0R_INIT_LAT_SHIFT));
  709.     RHDWriteMC(rhdPtr,  RV515_MC_MISC_LAT_TIMER, value);
  710. }
  711.  
  712. /*
  713.  *
  714.  */
  715. static void
  716. rs690TuneMCAccessForDisplay(RHDPtr rhdPtr, int crtc,
  717.                                    DisplayModePtr Mode, DisplayModePtr ScaledToMode)
  718. {
  719.     CARD32 value, setting = 0x1;
  720.  
  721.     RHDFUNC(rhdPtr);
  722.  
  723.     value = RHDReadMC(rhdPtr,  RS69_MC_INIT_MISC_LAT_TIMER);
  724.     value |= setting << (crtc ? MC_DISP1R_INIT_LAT_SHIFT : MC_DISP0R_INIT_LAT_SHIFT);
  725.     RHDWriteMC(rhdPtr,  RS69_MC_INIT_MISC_LAT_TIMER, value);
  726. }
  727.  
  728. /*
  729.  *
  730.  */
  731. void
  732. RHDTuneMCAccessForDisplay(RHDPtr rhdPtr, int crtc,
  733.                                    DisplayModePtr Mode, DisplayModePtr ScaledToMode)
  734. {
  735.     struct rhdMC *MC = rhdPtr->MC;
  736.  
  737.     RHDFUNC(rhdPtr);
  738.  
  739.     if (MC->TuneMCAccessForDisplay)
  740.         MC->TuneMCAccessForDisplay(rhdPtr, crtc, Mode, ScaledToMode);
  741. }
  742.  
  743. /*
  744.  *
  745.  */
  746. void
  747. RHDMCInit(RHDPtr rhdPtr)
  748. {
  749.     struct rhdMC *MC;
  750.  
  751.     RHDFUNC(rhdPtr);
  752.  
  753.     /* These devices have an internal address reference, which some other
  754.      * address registers in there also use. This can be different from the
  755.      * address in the BAR.
  756.      *
  757.      * We read out the address here from some known location. This address
  758.      * is as good a guess as any, we just need to pick one, but then make
  759.      * sure that it is made consistent in MCSetup and the various MC
  760.      * accessing subsystems.
  761.      */
  762.     if (rhdPtr->ChipSet < RHD_R600)
  763.         rhdPtr->FbIntAddress = RHDRegRead(rhdPtr, HDP_FB_LOCATION) << 16;
  764.     else
  765.         rhdPtr->FbIntAddress = RHDRegRead(rhdPtr, R6XX_CONFIG_FB_BASE);
  766.  
  767.     RHDDebug(rhdPtr->scrnIndex, "MC FB Address: 0x%08X.\n",
  768.              rhdPtr->FbIntAddress);
  769.  
  770.     MC = xnfcalloc(1, sizeof(struct rhdMC));
  771.     MC->Stored = FALSE;
  772.  
  773.     if (rhdPtr->ChipSet < RHD_RS600) {
  774.         MC->SaveMC = r5xxSaveMC;
  775.         MC->RestoreMC = r5xxRestoreMC;
  776.         MC->SetupMC = r5xxSetupMC;
  777.         MC->GetFBLocation = r5xxGetFBLocation;
  778.  
  779.         if (rhdPtr->ChipSet == RHD_RV515
  780.             || rhdPtr->ChipSet == RHD_RV505
  781.             || rhdPtr->ChipSet == RHD_RV516
  782.             || rhdPtr->ChipSet == RHD_RV550
  783.             || rhdPtr->ChipSet == RHD_M52
  784.             || rhdPtr->ChipSet == RHD_M54
  785.             || rhdPtr->ChipSet == RHD_M62
  786.             || rhdPtr->ChipSet == RHD_M64
  787.             || rhdPtr->ChipSet == RHD_M71) {
  788.  
  789.             MC->RV515Variant = TRUE;
  790.             MC->MCIdle = rv515MCIdle;
  791.             MC->TuneMCAccessForDisplay = rv515TuneMCAccessForDisplay;
  792.         } else {
  793.  
  794.             MC->RV515Variant = FALSE;
  795.             MC->MCIdle = r5xxMCIdle;
  796.  
  797.         }
  798.  
  799.     } else if (rhdPtr->ChipSet == RHD_RS600) {
  800.         MC->SaveMC = rs600SaveMC;
  801.         MC->RestoreMC = rs600RestoreMC;
  802.         MC->SetupMC = rs600SetupMC;
  803.         MC->MCIdle = rs600MCIdle;
  804.         MC->GetFBLocation = rs600GetFBLocation;
  805.     } else if (rhdPtr->ChipSet < RHD_R600) {
  806.         MC->SaveMC = rs690SaveMC;
  807.         MC->RestoreMC = rs690RestoreMC;
  808.         MC->SetupMC = rs690SetupMC;
  809.         MC->MCIdle = rs690MCIdle;
  810.         MC->GetFBLocation = rs690GetFBLocation;
  811.         MC->TuneMCAccessForDisplay = rs690TuneMCAccessForDisplay;
  812.     } else if (rhdPtr->ChipSet <= RHD_RS780) {
  813.         MC->SaveMC = r6xxSaveMC;
  814.         MC->RestoreMC = r6xxRestoreMC;
  815.         MC->SetupMC = r6xxSetupMC;
  816.         MC->MCIdle = r6xxMCIdle;
  817.         MC->GetFBLocation = r6xxGetFBLocation;
  818.     }
  819. #if 0
  820.     else if (rhdPtr->ChipSet == RHD_RS780) {
  821.         MC->SaveMC = rs780SaveMC;
  822.         MC->RestoreMC = rs780RestoreMC;
  823.         MC->SetupMC = rs780SetupMC;
  824.         MC->MCIdle = rs780MCIdle;
  825.         MC->GetFBLocation = rs780GetFBLocation;
  826.     }
  827. #endif
  828.     else if (rhdPtr->ChipSet >= RHD_RV770) {
  829.         MC->SaveMC = r7xxSaveMC;
  830.         MC->RestoreMC = r7xxRestoreMC;
  831.         MC->SetupMC = r7xxSetupMC;
  832.         MC->MCIdle = r6xxMCIdle;
  833.         MC->GetFBLocation = r7xxGetFBLocation;
  834.     } else {
  835.         xf86DrvMsg(rhdPtr->scrnIndex, X_ERROR, "I don't know anything about MC on this chipset\n");
  836.         xfree(MC);
  837.         return;
  838.     }
  839.     rhdPtr->MC = MC;
  840.  
  841. }
  842.  
  843. /*
  844.  * Free structure.
  845.  */
  846. void
  847. RHDMCDestroy(RHDPtr rhdPtr)
  848. {
  849.     RHDFUNC(rhdPtr);
  850.  
  851.     if (!rhdPtr->MC)
  852.         return;
  853.  
  854.     xfree(rhdPtr->MC);
  855.     rhdPtr->MC = NULL;
  856. }
  857.  
  858. /*
  859.  *
  860.  */
  861. Bool
  862. RHD_MC_IGP_SideportMemoryPresent(RHDPtr rhdPtr)
  863. {
  864.     Bool Present = FALSE;
  865.  
  866.     RHDFUNC(rhdPtr);
  867.  
  868.     switch (rhdPtr->ChipSet) {
  869.         case RHD_RS690:
  870.         case RHD_RS740:
  871.             Present = (RHDReadMC(rhdPtr, RS69_MC_MISC_UMA_CNTL) & RS69_SIDE_PORT_PRESENT_R) != 0;
  872.             break;
  873.         case RHD_RS780:
  874.             Present = (RHDReadMC(rhdPtr, RS78_MC_MISC_UMA_CNTL) & RS78_SIDE_PORT_PRESENT_R) != 0;
  875.             break;
  876.         default:
  877.             break;
  878.     }
  879.     xf86DrvMsg(rhdPtr->scrnIndex, X_INFO, "IPG sideport memory %s present.\n", Present ? "" : "not");
  880.  
  881.     return Present;
  882. }
  883.