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_connector.h"
  43. #include "rhd_output.h"
  44. #include "rhd_crtc.h"
  45. #include "rhd_regs.h"
  46. #if defined (ATOM_BIOS) && defined (ATOM_BIOS_PARSER)
  47. # include "rhd_atombios.h"
  48. # include "rhd_biosscratch.h"
  49.  
  50. struct atomPLLPrivate {
  51.     enum atomPxclk Pxclk;
  52.     struct atomPixelClockConfig Config;
  53.     struct atomCodeTableVersion Version;
  54.  
  55.     CARD32 StoreFBDivFrac;
  56.     enum atomDevice StoreDevice;
  57.     enum rhdConnectorType StoreConnectorType;
  58.     enum rhdOutputType StoreOutputType;
  59.     int StoreCrtc;
  60. };
  61.  
  62. /*
  63.  *
  64.  */
  65. static void
  66. getSetPixelClockParameters(struct rhdPLL *PLL, struct atomPixelClockConfig *Config,
  67.                            enum rhdConnectorType ct, enum rhdOutputType ot, enum atomDevice device)
  68. {
  69.     RHDPtr rhdPtr = RHDPTRI(PLL);
  70.     struct atomPLLPrivate *Private = (struct atomPLLPrivate *)PLL->Private;
  71.  
  72.     switch (Private->Version.cref) {
  73.         case 1:
  74.             break;
  75.         case 2:
  76.             Config->u.v2.Device = device;
  77.             Config->u.v2.Force = TRUE;
  78.             break;
  79.         case 3:
  80.             switch (ct) {
  81.                 case RHD_CONNECTOR_VGA:
  82.                     Config->u.v3.EncoderMode = atomNoEncoder;
  83.                     break;
  84.                 case RHD_CONNECTOR_DVI:
  85.                 case RHD_CONNECTOR_DVI_SINGLE:
  86.                     Config->u.v3.EncoderMode = atomDVI;
  87.                     break;
  88.                 case RHD_CONNECTOR_PANEL:
  89.                     Config->u.v3.EncoderMode = atomLVDS;
  90.                     break;
  91. #if 0
  92.                 case RHD_CONNECTOR_DP:
  93.                 case RHD_CONNECTOR_DP_DUAL:
  94.                     Config->u.v3.EncoderMode = atomDP;
  95.                     break;
  96.                 case RHD_CONNECTOR_HDMI_A:
  97.                 case RHD_CONNECTOR_HDMI_B:
  98.                     Config->u.v3.EncoderMode = atomHDMI;
  99.                     break;
  100. #endif
  101.                 default:
  102.                     xf86DrvMsg(rhdPtr->scrnIndex, X_ERROR, "%s: Unknown connector type: 0x%x\n",__func__,ct);
  103.             }
  104.             switch (ot) {
  105.                 case RHD_OUTPUT_DACA:
  106.                     Config->u.v3.OutputType = atomOutputDacA;
  107.                     break;
  108.                 case RHD_OUTPUT_DACB:
  109.                     Config->u.v3.OutputType = atomOutputDacB;
  110.                     break;
  111.                 case RHD_OUTPUT_KLDSKP_LVTMA:
  112.                     Config->u.v3.OutputType = atomOutputKldskpLvtma;
  113.                     break;
  114.                 case RHD_OUTPUT_UNIPHYA:
  115.                     Config->u.v3.OutputType = atomOutputUniphyA;
  116.                     break;
  117.                 case RHD_OUTPUT_UNIPHYB:
  118.                     Config->u.v3.OutputType = atomOutputUniphyB;
  119.                     break;
  120.                 case RHD_OUTPUT_UNIPHYC:
  121.                     Config->u.v3.OutputType = atomOutputUniphyC;
  122.                     break;
  123.                 case RHD_OUTPUT_UNIPHYD:
  124.                     Config->u.v3.OutputType = atomOutputUniphyD;
  125.                     break;
  126.                 case RHD_OUTPUT_UNIPHYE:
  127.                     Config->u.v3.OutputType = atomOutputUniphyE;
  128.                     break;
  129.                 case RHD_OUTPUT_UNIPHYF:
  130.                     Config->u.v3.OutputType = atomOutputUniphyF;
  131.                     break;
  132.                 case RHD_OUTPUT_DVO:
  133.                     Config->u.v3.OutputType = atomOutputDvo;
  134.                     break;
  135.                 default:
  136.                     xf86DrvMsg(rhdPtr->scrnIndex, X_ERROR, "%s: Unhandled ouptut type\n",__func__);
  137.                     break;
  138.             }
  139.             Config->u.v3.Force = TRUE;
  140.             Config->u.v3.UsePpll = FALSE;
  141.             break;
  142.         default:
  143.             xf86DrvMsg(rhdPtr->scrnIndex, X_ERROR, "Unsupported SelectPixelClock version: %i\n",Private->Version.cref);
  144.             break;
  145.     }
  146. }
  147.  
  148. /*
  149.  *
  150.  */
  151. static void
  152. rhdAtomPLLSave(struct rhdPLL *PLL, CARD32 PllCntl, CARD32 OwnerVal)
  153. {
  154.     RHDPtr rhdPtr = RHDPTRI(PLL);
  155.     struct atomPLLPrivate *Private = (struct atomPLLPrivate *)PLL->Private;
  156.     CARD32 Crtc1Cntl, Crtc2Cntl;
  157.     enum atomCrtc owner;
  158.  
  159.     RHDFUNC(PLL);
  160.  
  161.     Crtc1Cntl = RHDRegRead(PLL, PCLK_CRTC1_CNTL);
  162.     Crtc2Cntl = RHDRegRead(PLL, PCLK_CRTC2_CNTL);
  163.  
  164.     if (PllCntl & 0x2)
  165.         PLL->StoreActive = FALSE;
  166.     else
  167.         PLL->StoreActive = TRUE;
  168.  
  169.     if ((Crtc1Cntl & 0x00010000) == OwnerVal)
  170.         owner = atomCrtc1;
  171.     else if ((Crtc2Cntl & 0x00010000) == OwnerVal)
  172.         owner = atomCrtc2;
  173.     else {
  174.         owner = atomCrtc1; /* whatever... */
  175.         PLL->StoreActive = FALSE;
  176.     }
  177.  
  178.     Private->StoreCrtc = owner;
  179.     Private->StoreDevice = RHDGetDeviceOnCrtc(rhdPtr, owner);
  180.  
  181.     if (Private->StoreDevice != atomNone)
  182.         RHDFindConnectorAndOutputTypesForDevice(rhdPtr, Private->StoreDevice,
  183.                                                 &Private->StoreOutputType, &Private->StoreConnectorType);
  184.     else
  185.         PLL->StoreActive = FALSE;
  186.  
  187.     RHDDebug(PLL->scrnIndex, "Saving PLL %i on CRTC: %i %s active - device: 0x%x\n",
  188.              (PLL->Id == PLL_ID_PLL1) ? 1 : 2,
  189.              (owner == atomCrtc1) ? 1 : 2,
  190.              (PLL->StoreActive) ? "" : "not",
  191.              Private->StoreDevice);
  192.  
  193.     PLL->Stored = TRUE;
  194.  
  195.     /* Set parameters found at startup for shutdownInactive(). This is somewhat ugly... */
  196.     Private->Config.Crtc = Private->StoreCrtc;
  197.     Private->Config.Enable = PLL->StoreActive;
  198.     if (Private->StoreDevice != atomNone)
  199.         getSetPixelClockParameters(PLL, &Private->Config, Private->StoreConnectorType,
  200.                                    Private->StoreOutputType, Private->StoreDevice);
  201. }
  202.  
  203. /*
  204.  *
  205.  */
  206. static void
  207. rhdAtomPLL1Save(struct rhdPLL *PLL)
  208. {
  209.     struct atomPLLPrivate *Private = (struct atomPLLPrivate *)PLL->Private;
  210.     CARD32 PllCntl;
  211.  
  212.     RHDFUNC(PLL);
  213.  
  214.     PLL->StoreSpreadSpectrum = RHDRegRead(PLL, P1PLL_INT_SS_CNTL);
  215.     PLL->StoreRefDiv   = RHDRegRead(PLL, EXT1_PPLL_REF_DIV) & 0x1FF;
  216.     PLL->StoreFBDiv    = (RHDRegRead(PLL, EXT1_PPLL_FB_DIV) >> 16) & 0x7FF;
  217.     Private->StoreFBDivFrac = RHDRegRead(PLL, EXT1_PPLL_FB_DIV) & 0x7;
  218.     PLL->StorePostDiv  = RHDRegRead(PLL, EXT1_PPLL_POST_DIV) & 0x3F;
  219.     PllCntl = RHDRegRead(PLL, P1PLL_CNTL);
  220.     RHDDebug(PLL->scrnIndex, "Saving %i kHz clock on PLL1\n",
  221.              ((PLL->StoreFBDiv * PLL->RefClock * 10)
  222.               / (PLL->StorePostDiv * PLL->StoreRefDiv)));
  223.  
  224.     rhdAtomPLLSave(PLL, PllCntl, 0x00000000);
  225. }
  226.  
  227.  
  228. /*
  229.  *
  230.  */
  231. static void
  232. rhdAtomPLL2Save(struct rhdPLL *PLL)
  233. {
  234.     struct atomPLLPrivate *Private = (struct atomPLLPrivate *)PLL->Private;
  235.     CARD32 PllCntl;
  236.  
  237.     RHDFUNC(PLL);
  238.  
  239.     PLL->StoreSpreadSpectrum = RHDRegRead(PLL, P2PLL_INT_SS_CNTL);
  240.     PLL->StoreRefDiv   = RHDRegRead(PLL, EXT2_PPLL_REF_DIV) & 0x1FF;
  241.     PLL->StoreFBDiv    = (RHDRegRead(PLL, EXT2_PPLL_FB_DIV) >> 16) & 0x7FF;
  242.     Private->StoreFBDivFrac = RHDRegRead(PLL, EXT2_PPLL_FB_DIV) & 0x7;
  243.     PLL->StorePostDiv  = RHDRegRead(PLL, EXT2_PPLL_POST_DIV) & 0x3F;
  244.     PllCntl = RHDRegRead(PLL, P2PLL_CNTL);
  245.     RHDDebug(PLL->scrnIndex, "Saving %i kHz clock on PLL2\n",
  246.              ((PLL->StoreFBDiv * PLL->RefClock * 10)
  247.               / (PLL->StorePostDiv * PLL->StoreRefDiv)));
  248.  
  249.     rhdAtomPLLSave(PLL, PllCntl, 0x00010000);
  250. }
  251.  
  252. /*
  253.  *
  254.  */
  255. static void
  256. rhdAtomPLLRestore(struct rhdPLL *PLL)
  257. {
  258.     RHDPtr rhdPtr = RHDPTRI(PLL);
  259.     struct atomPixelClockConfig Config;
  260.     struct atomPLLPrivate *Private = (struct atomPLLPrivate *)PLL->Private;
  261.  
  262.     RHDFUNC(PLL);
  263.  
  264.     if (!PLL->Stored) {
  265.         xf86DrvMsg(PLL->scrnIndex, X_ERROR, "%s: %s: trying to restore "
  266.                    "uninitialized values.\n", __func__, PLL->Name);
  267.         return;
  268.     }
  269.     Config.PixelClock = PLL->StoreActive
  270.         ? ((PLL->StoreFBDiv * PLL->RefClock * 10) / (PLL->StorePostDiv * PLL->StoreRefDiv))
  271.         : 0;
  272.  
  273.     Config.Enable = PLL->StoreActive;
  274.     Config.RefDiv = PLL->StoreRefDiv;
  275.     Config.FbDiv = PLL->StoreFBDiv;
  276.     Config.PostDiv = PLL->StorePostDiv;
  277.     Config.FracFbDiv = Private->StoreFBDivFrac;
  278.     Config.Crtc = Private->StoreCrtc;
  279.  
  280.     if (Private->StoreDevice != atomNone)
  281.         getSetPixelClockParameters(PLL, &Config, Private->StoreConnectorType,
  282.                                    Private->StoreOutputType, Private->StoreDevice);
  283.     RHDDebug(PLL->scrnIndex, "Restoring PixelClock %i with %i kHz, (%i * %i) / ( %i * %i )"
  284.              " on CRTC %i device: %x\n",
  285.              Private->Pxclk, Config.PixelClock, PLL->RefClock, PLL->StoreFBDiv, PLL->StorePostDiv,
  286.              PLL->StoreRefDiv, (Config.Crtc == atomCrtc1) ? 1 : 2, Config.u.v2.Device);
  287.  
  288.     /* Restore spread spectrum: AtomBIOS doesn't handle this for us */
  289.     RHDRegWrite(PLL, (PLL->Id == PLL_ID_PLL1) ? P1PLL_INT_SS_CNTL : P2PLL_INT_SS_CNTL, PLL->StoreSpreadSpectrum);
  290.  
  291.     rhdAtomSetPixelClock(rhdPtr->atomBIOS, Private->Pxclk, &Config);
  292. }
  293.  
  294. /*
  295.  *
  296.  */
  297. static void
  298. rhdAtomPLLPower(struct rhdPLL *PLL, int Power)
  299. {
  300.     RHDPtr rhdPtr = RHDPTRI(PLL);
  301.     struct atomPLLPrivate *Private = (struct atomPLLPrivate *)PLL->Private;
  302.     struct atomPixelClockConfig *config = &Private->Config;
  303.  
  304.     RHDFUNC(PLL);
  305.  
  306.     switch (Power) {
  307.         case RHD_POWER_ON:
  308.             if (config->PixelClock > 0)
  309.                 config->Enable = TRUE;
  310.             else {
  311.                 xf86DrvMsg(rhdPtr->scrnIndex, X_ERROR,
  312.                            "%s: cannot enable pixel clock without frequency set\n",__func__);
  313.                 config->Enable = FALSE;
  314.             }
  315.             break;
  316.         case RHD_POWER_RESET:
  317.         case RHD_POWER_SHUTDOWN:
  318.             return;
  319.             config->Enable = FALSE;
  320.         default:
  321.             break;
  322.     }
  323.     rhdAtomSetPixelClock(rhdPtr->atomBIOS, Private->Pxclk, config);
  324. }
  325.  
  326. /*
  327.  *
  328.  */
  329. static void
  330. rhdAtomPLLSet(struct rhdPLL *PLL, int PixelClock, CARD16 ReferenceDivider,
  331.             CARD16 FeedbackDivider, CARD8 PostDivider)
  332. {
  333.     RHDPtr rhdPtr = RHDPTRI(PLL);
  334.     struct atomPLLPrivate *Private = (struct atomPLLPrivate *)PLL->Private;
  335.     struct rhdCrtc *Crtc = NULL;
  336.  
  337.     RHDFUNC(PLL);
  338.     RHDDebug(rhdPtr->scrnIndex, "%s: %i kHz RefDiv: %x FeedbackDiv: %x PostDiv: %x\n",
  339.              __func__, PixelClock, ReferenceDivider, FeedbackDivider, PostDivider);
  340.  
  341.     Private->Config.PixelClock = PixelClock;
  342.     Private->Config.RefDiv = ReferenceDivider;
  343.     Private->Config.FbDiv = FeedbackDivider;
  344.     Private->Config.PostDiv = PostDivider;
  345.     Private->Config.FracFbDiv = 0;
  346.     if (rhdPtr->Crtc[0]->PLL == PLL) {
  347.         Private->Config.Crtc = atomCrtc1;
  348.         Crtc = rhdPtr->Crtc[0];
  349.     } else if (rhdPtr->Crtc[1]->PLL == PLL) {
  350.         Private->Config.Crtc = atomCrtc2;
  351.         Crtc = rhdPtr->Crtc[1];
  352.     } else
  353.         xf86DrvMsg(rhdPtr->scrnIndex, X_ERROR, "Trying to set an unassigned PLL\n");
  354.  
  355.     if (Crtc && Private->Version.cref > 1) {
  356.         struct rhdOutput *Output;
  357.         for (Output = rhdPtr->Outputs; Output; Output = Output->Next) {
  358.             if (Output->Crtc == Crtc)
  359.                 break;
  360.         }
  361.         if (Output)
  362.             getSetPixelClockParameters(PLL, &Private->Config,
  363.                                       Output->Connector->Type, Output->Id,
  364.                                       Output->OutputDriverPrivate->Device);
  365.     }
  366.  
  367.     /* Disable spread spectrum. AtomBIOS doesn't do this for us */
  368.     RHDRegMask(PLL, (PLL->Id == PLL_ID_PLL1) ? P1PLL_INT_SS_CNTL : P2PLL_INT_SS_CNTL, 0, 0x00000001);
  369.  
  370.     Private->Config.Enable = TRUE;
  371.     rhdAtomSetPixelClock(rhdPtr->atomBIOS, Private->Pxclk, &Private->Config);
  372. }
  373.  
  374. /*
  375.  *
  376.  */
  377. Bool
  378. RHDAtomPLLsInit(RHDPtr rhdPtr)
  379. {
  380.     struct rhdPLL *PLL;
  381.     struct atomPLLPrivate *Private;
  382.     CARD32 RefClock, IntMin, IntMax, PixMin, PixMax;
  383.     int i;
  384.  
  385.     RHDFUNC(rhdPtr);
  386.  
  387.     RHDSetupLimits(rhdPtr, &RefClock, &IntMin, &IntMax, &PixMin, &PixMax);
  388.  
  389.     for (i = 0; i < 2; i++) {
  390.  
  391.         PLL = (struct rhdPLL *) xnfcalloc(sizeof(struct rhdPLL), 1);
  392.         Private = (struct atomPLLPrivate *) xnfcalloc(sizeof(struct atomPLLPrivate),1);
  393.         PLL->Private = Private;
  394.  
  395.         Private->Version = rhdAtomSetPixelClockVersion(rhdPtr->atomBIOS);
  396.         if (Private->Version.cref > 3) {
  397.             xf86DrvMsg(rhdPtr->scrnIndex, X_ERROR, "Unsupported SelectPixelClock version; %i\n",
  398.                        Private->Version.cref);
  399.             xfree(PLL->Private);
  400.             xfree(PLL);
  401.             return FALSE;
  402.         }
  403.  
  404.         PLL->scrnIndex = rhdPtr->scrnIndex;
  405.         if (i == 0) {
  406.             PLL->Name = PLL_NAME_PLL1;
  407.             PLL->Id = PLL_ID_PLL1;
  408.             PLL->Save = rhdAtomPLL1Save;
  409.             Private->Pxclk = atomPclk1;
  410.         } else {
  411.             PLL->Name = PLL_NAME_PLL2;
  412.             PLL->Id = PLL_ID_PLL2;
  413.             PLL->Save = rhdAtomPLL2Save;
  414.             Private->Pxclk = atomPclk2;
  415.         }
  416.  
  417.         PLL->RefClock = RefClock;
  418.         PLL->IntMin = IntMin;
  419.         PLL->IntMax = IntMax;
  420.         PLL->PixMin = PixMin;
  421.         PLL->PixMax = PixMax;
  422.  
  423.         PLL->Valid = NULL;
  424.  
  425.         PLL->Set = rhdAtomPLLSet;
  426.         PLL->Power = rhdAtomPLLPower;
  427.         PLL->Restore = rhdAtomPLLRestore;
  428.  
  429.         rhdPtr->PLLs[i] = PLL;
  430.     }
  431.  
  432.  
  433.     return TRUE;
  434. }
  435.  
  436. #endif /* ATOM_BIOS && ATOM_BIOS_PARSER */
  437.