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. #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_connector.h"
  42. #include "rhd_output.h"
  43. #include "rhd_regs.h"
  44. #include "rhd_hdmi.h"
  45. #ifdef ATOM_BIOS
  46. #include "rhd_atombios.h"
  47. #include "rhd_atomout.h"
  48. #endif
  49.  
  50. #define FMT2_OFFSET 0x800
  51. #define DIG1_OFFSET 0x000
  52. #define DIG2_OFFSET 0x400
  53.  
  54. /*
  55.  * Transmitter
  56.  */
  57. struct transmitter {
  58.     enum rhdSensedOutput (*Sense) (struct rhdOutput *Output,
  59.                                    enum rhdConnectorType Type);
  60.     ModeStatus (*ModeValid) (struct rhdOutput *Output, DisplayModePtr Mode);
  61.     void (*Mode) (struct rhdOutput *Output, struct rhdCrtc *Crtc, DisplayModePtr Mode);
  62.     void (*Power) (struct rhdOutput *Output, int Power);
  63.     void (*Save) (struct rhdOutput *Output);
  64.     void (*Restore) (struct rhdOutput *Output);
  65.     void (*Destroy) (struct rhdOutput *Output);
  66.     Bool (*Property) (struct rhdOutput *Output,
  67.                       enum rhdPropertyAction Action, enum rhdOutputProperty Property, union rhdPropertyData *val);
  68. #ifdef NOT_YET
  69.     Bool (*WrappedPropertyCallback) (struct rhdOutput *Output,
  70.                       enum rhdPropertyAction Action, enum rhdOutputProperty Property, union rhdPropertyData *val);
  71.     void *PropertyPrivate;
  72. #endif
  73.     void *Private;
  74. };
  75.  
  76. /*
  77.  * Encoder
  78.  */
  79. struct encoder {
  80.     ModeStatus (*ModeValid) (struct rhdOutput *Output, DisplayModePtr Mode);
  81.     void (*Mode) (struct rhdOutput *Output, struct rhdCrtc *Crtc, DisplayModePtr Mode);
  82.     void (*Power) (struct rhdOutput *Output, int Power);
  83.     void (*Save) (struct rhdOutput *Output);
  84.     void (*Restore) (struct rhdOutput *Output);
  85.     void (*Destroy) (struct rhdOutput *Output);
  86.     void *Private;
  87. };
  88.  
  89. /*
  90.  *
  91.  */
  92. enum encoderMode {
  93.     DISPLAYPORT = 0,
  94.     LVDS = 1,
  95.     TMDS_DVI = 2,
  96.     TMDS_HDMI = 3,
  97.     SDVO = 4
  98. };
  99.  
  100. enum encoderID {
  101.     ENCODER_NONE,
  102.     ENCODER_DIG1,
  103.     ENCODER_DIG2
  104. };
  105.  
  106. struct DIGPrivate
  107. {
  108.     struct encoder Encoder;
  109.     struct transmitter Transmitter;
  110.     enum encoderID EncoderID;
  111.     enum encoderMode EncoderMode;
  112.     Bool Coherent;
  113.     Bool RunDualLink;
  114.     DisplayModePtr Mode;
  115.     struct rhdHdmi *Hdmi;
  116.  
  117.     /* LVDS */
  118.     Bool FPDI;
  119.     CARD32 PowerSequenceDe2Bl;
  120.     CARD32 PowerSequenceDig2De;
  121.     CARD32 OffDelay;
  122.     struct rhdFMTDither FMTDither;
  123.     int BlLevel;
  124. };
  125.  
  126. /*
  127.  * LVTMA Transmitter
  128.  */
  129.  
  130. struct LVTMATransmitterPrivate
  131. {
  132.     Bool Stored;
  133.  
  134.     CARD32 StoredTransmitterControl;
  135.     CARD32 StoredTransmitterAdjust;
  136.     CARD32 StoredPreemphasisControl;
  137.     CARD32 StoredMacroControl;
  138.     CARD32 StoredLVTMADataSynchronization;
  139.     CARD32 StoredTransmiterEnable;
  140.     CARD32 StoredPwrSeqCntl;
  141.     CARD32 StoredPwrSeqRevDiv;
  142.     CARD32 StoredPwrSeqDelay1;
  143.     CARD32 StoredPwrSeqDelay2;
  144. };
  145.  
  146. /*
  147.  *
  148.  */
  149. static ModeStatus
  150. LVTMATransmitterModeValid(struct rhdOutput *Output, DisplayModePtr Mode)
  151. {
  152.     RHDFUNC(Output);
  153.  
  154.     if (Mode->Flags & V_INTERLACE)
  155.         return MODE_NO_INTERLACE;
  156.  
  157.     if (Output->Connector->Type == RHD_CONNECTOR_DVI_SINGLE
  158.         && Mode->SynthClock > 165000)
  159.         return MODE_CLOCK_HIGH;
  160.  
  161.     return MODE_OK;
  162. }
  163.  
  164. static void
  165. LVDSSetBacklight(struct rhdOutput *Output, int level)
  166. {
  167.     struct DIGPrivate *Private = (struct DIGPrivate *) Output->Private;
  168.  
  169.     RHDFUNC(Output);
  170.  
  171.     Private->BlLevel = level;
  172.  
  173.     RHDRegMask(Output, RV620_LVTMA_PWRSEQ_REF_DIV,
  174.                0x144 << LVTMA_BL_MOD_REF_DI_SHIFT,
  175.                0x7ff << LVTMA_BL_MOD_REF_DI_SHIFT);
  176.     RHDRegWrite(Output, RV620_LVTMA_BL_MOD_CNTL,
  177.                 0xff << LVTMA_BL_MOD_RES_SHIFT
  178.                 | level << LVTMA_BL_MOD_LEVEL_SHIFT
  179.                 | LVTMA_BL_MOD_EN);
  180. }
  181.  
  182. /*
  183.  *
  184.  */
  185. static Bool
  186. LVDSTransmitterPropertyControl(struct rhdOutput *Output,
  187.              enum rhdPropertyAction Action, enum rhdOutputProperty Property, union rhdPropertyData *val)
  188. {
  189.     struct DIGPrivate *Private = (struct DIGPrivate *) Output->Private;
  190.  
  191.     RHDFUNC(Output);
  192.     switch (Action) {
  193.         case rhdPropertyCheck:
  194.             if (Private->BlLevel < 0)
  195.                 return FALSE;
  196.         switch (Property) {
  197.             case RHD_OUTPUT_BACKLIGHT:
  198.                     return TRUE;
  199.             default:
  200.                 return FALSE;
  201.         }
  202.         case rhdPropertyGet:
  203.             if (Private->BlLevel < 0)
  204.                 return FALSE;
  205.             switch (Property) {
  206.                 case RHD_OUTPUT_BACKLIGHT:
  207.                     val->integer = Private->BlLevel;
  208.                     return TRUE;
  209.                 default:
  210.                     return FALSE;
  211.             }
  212.             break;
  213.         case rhdPropertySet:
  214.             if (Private->BlLevel < 0)
  215.                 return FALSE;
  216.             switch (Property) {
  217.                 case RHD_OUTPUT_BACKLIGHT:
  218.                     LVDSSetBacklight(Output, val->integer);
  219.                     return TRUE;
  220.                 default:
  221.                     return FALSE;
  222.             }
  223.             break;
  224.     }
  225.     return TRUE;
  226. }
  227.  
  228. /*
  229.  *
  230.  */
  231. static Bool
  232. TMDSTransmitterPropertyControl(struct rhdOutput *Output,
  233.              enum rhdPropertyAction Action, enum rhdOutputProperty Property, union rhdPropertyData *val)
  234. {
  235.     struct DIGPrivate *Private = (struct DIGPrivate *) Output->Private;
  236.  
  237.     RHDFUNC(Output);
  238.     switch (Action) {
  239.         case rhdPropertyCheck:
  240.         switch (Property) {
  241.             case RHD_OUTPUT_COHERENT:
  242.                     return TRUE;
  243.             default:
  244.                 return FALSE;
  245.         }
  246.         case rhdPropertyGet:
  247.             switch (Property) {
  248.                 case RHD_OUTPUT_COHERENT:
  249.                     val->Bool =  Private->Coherent;
  250.                     return TRUE;
  251.                 default:
  252.                     return FALSE;
  253.             }
  254.             break;
  255.         case rhdPropertySet:
  256.             switch (Property) {
  257.                 case RHD_OUTPUT_COHERENT:
  258.                     Private->Coherent = val->Bool;
  259.                     Output->Mode(Output, Private->Mode);
  260.                     Output->Power(Output, RHD_POWER_ON);
  261.                     break;
  262.                 default:
  263.                     return FALSE;
  264.             }
  265.             break;
  266.     }
  267.     return TRUE;
  268. }
  269.  
  270. /*
  271.  *
  272.  */
  273. static void
  274. LVTMATransmitterSet(struct rhdOutput *Output, struct rhdCrtc *Crtc, DisplayModePtr Mode)
  275. {
  276.     struct DIGPrivate *Private = (struct DIGPrivate *)Output->Private;
  277.     CARD32 value = 0;
  278. #ifdef ATOM_BIOS
  279.     AtomBiosArgRec data;
  280. #endif
  281.     RHDPtr rhdPtr = RHDPTRI(Output);
  282.     Bool doCoherent = Private->Coherent;
  283.     RHDFUNC(Output);
  284.  
  285.     /* set coherent / not coherent mode; whatever that is */
  286.     if (Output->Connector->Type != RHD_CONNECTOR_PANEL)
  287.         RHDRegMask(Output, RV620_LVTMA_TRANSMITTER_CONTROL,
  288.                    doCoherent ? 0 : RV62_LVTMA_BYPASS_PLL, RV62_LVTMA_BYPASS_PLL);
  289.  
  290.     Private->Mode = Mode;
  291. #ifdef ATOM_BIOS
  292.     RHDDebug(Output->scrnIndex, "%s: SynthClock: %i Hex: %x EncoderMode: %x\n",__func__,
  293.              (Mode->SynthClock),(Mode->SynthClock / 10), Private->EncoderMode);
  294.  
  295.     /* Set up magic value that's used for list lookup */
  296.     value = ((Mode->SynthClock / 10 / ((Private->RunDualLink) ? 2 : 1)) & 0xffff)
  297.         | (Private->EncoderMode << 16)
  298.         | ((doCoherent ? 0x2 : 0) << 24);
  299.  
  300.     RHDDebug(Output->scrnIndex, "%s: GetConditionalGoldenSettings for: %x\n", __func__, value);
  301.  
  302.     /* Get data from DIG2TransmitterControl table */
  303.     data.val = 0x4d;
  304.     if (RHDAtomBiosFunc(rhdPtr, rhdPtr->atomBIOS, ATOMBIOS_GET_CODE_DATA_TABLE,
  305.                         &data) == ATOM_SUCCESS) {
  306.         AtomBiosArgRec data1;
  307.         CARD32 *d_p = NULL;
  308.  
  309.         data1.GoldenSettings.BIOSPtr = data.CommandDataTable.loc;
  310.         data1.GoldenSettings.End = data1.GoldenSettings.BIOSPtr + data.CommandDataTable.size;
  311.         data1.GoldenSettings.value = value;
  312.  
  313.         /* now find pointer */
  314.     if (RHDAtomBiosFunc(rhdPtr, rhdPtr->atomBIOS,
  315.                             ATOM_GET_CONDITIONAL_GOLDEN_SETTINGS, &data1) == ATOM_SUCCESS) {
  316.             d_p = (CARD32*)data1.GoldenSettings.BIOSPtr;
  317.         } else {
  318.             /* nothing found, now try toggling the coherent setting */
  319.             doCoherent = !doCoherent;
  320.             value = (value & ~(0x2 << 24)) | ((doCoherent ? 0x2 : 0) << 24);
  321.             data1.GoldenSettings.value = value;
  322.  
  323.         if (RHDAtomBiosFunc(rhdPtr, rhdPtr->atomBIOS,
  324.                             ATOM_GET_CONDITIONAL_GOLDEN_SETTINGS, &data1) == ATOM_SUCCESS) {
  325.                 d_p = (CARD32*)data1.GoldenSettings.BIOSPtr;
  326.                 /* set coherent / not coherent mode; whatever that is */
  327.                 xf86DrvMsg(Output->scrnIndex, X_INFO, "%s: %soherent Mode not supported, switching to %soherent.\n",
  328.                            __func__, doCoherent ? "Inc" : "C", doCoherent ? "C" : "Inc");
  329.                 if (Output->Connector->Type != RHD_CONNECTOR_PANEL)
  330.                     RHDRegMask(Output, RV620_LVTMA_TRANSMITTER_CONTROL,
  331.                                doCoherent ? 0 : RV62_LVTMA_BYPASS_PLL, RV62_LVTMA_BYPASS_PLL);
  332.             } else
  333.                 doCoherent = Private->Coherent; /* reset old value if nothing found either */
  334.         }
  335.         if (d_p) {
  336.             RHDDebug(Output->scrnIndex, "TransmitterAdjust: 0x%8.8x\n",d_p[0]);
  337.             RHDRegWrite(Output, RV620_LVTMA_TRANSMITTER_ADJUST, d_p[0]);
  338.  
  339.             RHDDebug(Output->scrnIndex, "PreemphasisControl: 0x%8.8x\n",d_p[1]);
  340.             RHDRegWrite(Output, RV620_LVTMA_PREEMPHASIS_CONTROL, d_p[1]);
  341.  
  342.             RHDDebug(Output->scrnIndex, "MacroControl: 0x%8.8x\n",d_p[2]);
  343.             RHDRegWrite(Output, RV620_LVTMA_MACRO_CONTROL, d_p[2]);
  344.         } else
  345.             xf86DrvMsg(Output->scrnIndex, X_WARNING, "%s: cannot get golden settings\n",__func__);
  346.     } else
  347. #endif
  348.     {
  349.         xf86DrvMsg(Output->scrnIndex, X_WARNING, "%s: No AtomBIOS supplied "
  350.                    "electrical parameters available\n", __func__);
  351.     }
  352. }
  353.  
  354. /*
  355.  *
  356.  */
  357. static void
  358. LVTMATransmitterSave(struct rhdOutput *Output)
  359. {
  360.     struct DIGPrivate *digPrivate = (struct DIGPrivate *)Output->Private;
  361.     struct LVTMATransmitterPrivate *Private = (struct LVTMATransmitterPrivate*)digPrivate->Transmitter.Private;
  362.  
  363.     Private->StoredTransmitterControl       = RHDRegRead(Output, RV620_LVTMA_TRANSMITTER_CONTROL);
  364.     Private->StoredTransmitterAdjust        = RHDRegRead(Output, RV620_LVTMA_TRANSMITTER_ADJUST);
  365.     Private->StoredPreemphasisControl       = RHDRegRead(Output, RV620_LVTMA_PREEMPHASIS_CONTROL);
  366.     Private->StoredMacroControl             = RHDRegRead(Output, RV620_LVTMA_MACRO_CONTROL);
  367.     Private->StoredLVTMADataSynchronization = RHDRegRead(Output, RV620_LVTMA_DATA_SYNCHRONIZATION);
  368.     Private->StoredTransmiterEnable         = RHDRegRead(Output, RV620_LVTMA_TRANSMITTER_ENABLE);
  369. }
  370.  
  371. /*
  372.  *
  373.  */
  374. static void
  375. LVTMATransmitterRestore(struct rhdOutput *Output)
  376. {
  377.     struct DIGPrivate *digPrivate = (struct DIGPrivate *)Output->Private;
  378.     struct LVTMATransmitterPrivate *Private = (struct LVTMATransmitterPrivate*)digPrivate->Transmitter.Private;
  379.  
  380.     RHDFUNC(Output);
  381.  
  382.     /* write control values back */
  383.     RHDRegWrite(Output, RV620_LVTMA_TRANSMITTER_CONTROL,Private->StoredTransmitterControl);
  384.     usleep (14);
  385.     /* reset PLL */
  386.     RHDRegWrite(Output, RV620_LVTMA_TRANSMITTER_CONTROL,Private->StoredTransmitterControl
  387.                 | RV62_LVTMA_PLL_RESET);
  388.     usleep (10);
  389.     /* unreset PLL */
  390.     RHDRegWrite(Output, RV620_LVTMA_TRANSMITTER_CONTROL,Private->StoredTransmitterControl);
  391.     usleep(1000);
  392.     RHDRegWrite(Output, RV620_LVTMA_TRANSMITTER_ADJUST, Private->StoredTransmitterAdjust);
  393.     RHDRegWrite(Output, RV620_LVTMA_PREEMPHASIS_CONTROL, Private->StoredPreemphasisControl);
  394.     RHDRegWrite(Output, RV620_LVTMA_MACRO_CONTROL, Private->StoredMacroControl);
  395.     /* start data synchronization */
  396.     RHDRegWrite(Output, RV620_LVTMA_DATA_SYNCHRONIZATION, (Private->StoredLVTMADataSynchronization
  397.                                                            & ~(CARD32)RV62_LVTMA_DSYNSEL)
  398.                 | RV62_LVTMA_PFREQCHG);
  399.     usleep (1);
  400.     RHDRegWrite(Output, RV620_LVTMA_DATA_SYNCHRONIZATION, Private->StoredLVTMADataSynchronization);
  401.     usleep(10);
  402.     RHDRegWrite(Output, RV620_LVTMA_DATA_SYNCHRONIZATION, Private->StoredLVTMADataSynchronization);
  403.     RHDRegWrite(Output, RV620_LVTMA_TRANSMITTER_ENABLE, Private->StoredTransmiterEnable);
  404. }
  405.  
  406. /*
  407.  *
  408.  */
  409. static void
  410. LVTMA_TMDSTransmitterSet(struct rhdOutput *Output, struct rhdCrtc *Crtc, DisplayModePtr Mode)
  411. {
  412.     RHDFUNC(Output);
  413.  
  414.     /* TMDS Mode */
  415.     RHDRegMask(Output, RV620_LVTMA_TRANSMITTER_CONTROL,
  416.                RV62_LVTMA_USE_CLK_DATA, RV62_LVTMA_USE_CLK_DATA);
  417.  
  418.     LVTMATransmitterSet(Output, Crtc, Mode);
  419.  
  420.     /* use differential post divider input */
  421.     RHDRegMask(Output, RV620_LVTMA_TRANSMITTER_CONTROL,
  422.                RV62_LVTMA_IDSCKSEL, RV62_LVTMA_IDSCKSEL);
  423. }
  424.  
  425. /*
  426.  *
  427.  */
  428. static void
  429. LVTMA_TMDSTransmitterPower(struct rhdOutput *Output, int Power)
  430. {
  431.     struct DIGPrivate *Private = (struct DIGPrivate *)Output->Private;
  432.  
  433.     RHDFUNC(Output);
  434.  
  435.     switch (Power) {
  436.         case RHD_POWER_ON:
  437.             /* enable PLL */
  438.             RHDRegMask(Output, RV620_LVTMA_TRANSMITTER_CONTROL,
  439.                        RV62_LVTMA_PLL_ENABLE, RV62_LVTMA_PLL_ENABLE);
  440.             usleep(14);
  441.             /* PLL reset on */
  442.             RHDRegMask(Output, RV620_LVTMA_TRANSMITTER_CONTROL,
  443.                        RV62_LVTMA_PLL_RESET, RV62_LVTMA_PLL_RESET);
  444.             usleep(10);
  445.             /* PLL reset off */
  446.             RHDRegMask(Output, RV620_LVTMA_TRANSMITTER_CONTROL,
  447.                        0, RV62_LVTMA_PLL_RESET);
  448.             usleep(1000);
  449.             /* start data synchronization */
  450.             RHDRegMask(Output, RV620_LVTMA_DATA_SYNCHRONIZATION,
  451.                        RV62_LVTMA_PFREQCHG, RV62_LVTMA_PFREQCHG);
  452.             usleep(1);
  453.             /* restart write address logic */
  454.             RHDRegMask(Output, RV620_LVTMA_DATA_SYNCHRONIZATION,
  455.                        RV62_LVTMA_DSYNSEL, RV62_LVTMA_DSYNSEL);
  456. #if 1
  457.             /* TMDS Mode ?? */
  458.             RHDRegMask(Output, RV620_LVTMA_TRANSMITTER_CONTROL,
  459.                        RV62_LVTMA_MODE, RV62_LVTMA_MODE);
  460. #endif
  461.             /* enable lower link */
  462.             RHDRegMask(Output, RV620_LVTMA_TRANSMITTER_ENABLE,
  463.                        RV62_LVTMA_LNKL,
  464.                        RV62_LVTMA_LNK_ALL);
  465.             if (Private->RunDualLink) {
  466.                 usleep (28);
  467.                 /* enable upper link */
  468.                 RHDRegMask(Output, RV620_LVTMA_TRANSMITTER_ENABLE,
  469.                            RV62_LVTMA_LNKU,
  470.                            RV62_LVTMA_LNKU);
  471.             }
  472.             return;
  473.         case RHD_POWER_RESET:
  474.             /* disable all links */
  475.             RHDRegMask(Output, RV620_LVTMA_TRANSMITTER_ENABLE,
  476.                        0, RV62_LVTMA_LNK_ALL);
  477.             return;
  478.         case RHD_POWER_SHUTDOWN:
  479.         default:
  480.             /* disable transmitter */
  481.             RHDRegMask(Output, RV620_LVTMA_TRANSMITTER_ENABLE,
  482.                        0, RV62_LVTMA_LNK_ALL);
  483.             /* PLL reset */
  484.             RHDRegMask(Output, RV620_LVTMA_TRANSMITTER_CONTROL,
  485.                        RV62_LVTMA_PLL_RESET, RV62_LVTMA_PLL_RESET);
  486.             usleep(10);
  487.             /* end PLL reset */
  488.             RHDRegMask(Output, RV620_LVTMA_TRANSMITTER_CONTROL,
  489.                        0, RV62_LVTMA_PLL_RESET);
  490.             /* disable data synchronization */
  491.             RHDRegMask(Output, RV620_LVTMA_DATA_SYNCHRONIZATION,
  492.                        0, RV62_LVTMA_DSYNSEL);
  493.             /* reset macro control */
  494.             RHDRegWrite(Output, RV620_LVTMA_TRANSMITTER_ADJUST, 0);
  495.  
  496.             return;
  497.     }
  498. }
  499.  
  500. /*
  501.  *
  502.  */
  503. static void
  504. LVTMA_TMDSTransmitterSave(struct rhdOutput *Output)
  505. {
  506.     struct DIGPrivate *digPrivate = (struct DIGPrivate *)Output->Private;
  507.     struct LVTMATransmitterPrivate *Private = (struct LVTMATransmitterPrivate*)digPrivate->Transmitter.Private;
  508.  
  509.     RHDFUNC(Output);
  510.  
  511.     LVTMATransmitterSave(Output);
  512.  
  513.     Private->Stored = TRUE;
  514. }
  515.  
  516. /*
  517.  *
  518.  */
  519. static void
  520. LVTMA_TMDSTransmitterRestore(struct rhdOutput *Output)
  521. {
  522.     struct DIGPrivate *digPrivate = (struct DIGPrivate *)Output->Private;
  523.     struct LVTMATransmitterPrivate *Private = (struct LVTMATransmitterPrivate*)digPrivate->Transmitter.Private;
  524.  
  525.     RHDFUNC(Output);
  526.  
  527.     if (!Private->Stored) {
  528.         xf86DrvMsg(Output->scrnIndex, X_ERROR,
  529.                    "%s: No registers stored.\n", __func__);
  530.         return;
  531.     }
  532.  
  533.     LVTMATransmitterRestore(Output);
  534. }
  535.  
  536. /*
  537.  *
  538.  */
  539. static void
  540. LVTMA_LVDSTransmitterSet(struct rhdOutput *Output, struct rhdCrtc *Crtc, DisplayModePtr Mode)
  541. {
  542.     RHDFUNC(Output);
  543.  
  544.     /* LVDS Mode */
  545.     RHDRegMask(Output, RV620_LVTMA_TRANSMITTER_CONTROL,
  546.                0, RV62_LVTMA_USE_CLK_DATA);
  547.  
  548.     LVTMATransmitterSet(Output, Crtc, Mode);
  549.  
  550.     /* use IDCLK */
  551.     RHDRegMask(Output, RV620_LVTMA_TRANSMITTER_CONTROL, RV62_LVTMA_IDSCKSEL, RV62_LVTMA_IDSCKSEL);
  552.     /* enable pwrseq, pwrseq overwrite PPL enable, reset */
  553.     RHDRegMask(Output,  RV620_LVTMA_PWRSEQ_CNTL,
  554.                RV62_LVTMA_PWRSEQ_EN
  555.                | RV62_LVTMA_PLL_ENABLE_PWRSEQ_MASK
  556.                | RV62_LVTMA_PLL_RESET_PWRSEQ_MASK,
  557.                RV62_LVTMA_PWRSEQ_EN
  558.                | RV62_LVTMA_PLL_ENABLE_PWRSEQ_MASK
  559.                | RV62_LVTMA_PLL_RESET_PWRSEQ_MASK
  560.         );
  561.  
  562. }
  563.  
  564. /*
  565.  *
  566.  */
  567. static void
  568. LVTMA_LVDSTransmitterPower(struct rhdOutput *Output, int Power)
  569. {
  570.     struct DIGPrivate *Private = (struct DIGPrivate *)Output->Private;
  571.     CARD32 tmp, tmp1;
  572.     int i;
  573.  
  574.     RHDFUNC(Output);
  575.  
  576.     switch (Power) {
  577.         case RHD_POWER_ON:
  578.             /* enable PLL */
  579.             RHDRegMask(Output, RV620_LVTMA_TRANSMITTER_CONTROL,
  580.                        RV62_LVTMA_PLL_ENABLE, RV62_LVTMA_PLL_ENABLE);
  581.             usleep(14);
  582.             /* PLL reset on */
  583.             RHDRegMask(Output, RV620_LVTMA_TRANSMITTER_CONTROL,
  584.                        RV62_LVTMA_PLL_RESET, RV62_LVTMA_PLL_RESET);
  585.             usleep(10);
  586.             /* PLL reset off */
  587.             RHDRegMask(Output, RV620_LVTMA_TRANSMITTER_CONTROL,
  588.                        0, RV62_LVTMA_PLL_RESET);
  589.             usleep(1000);
  590.             /* start data synchronization */
  591.             RHDRegMask(Output, RV620_LVTMA_DATA_SYNCHRONIZATION,
  592.                        RV62_LVTMA_PFREQCHG, RV62_LVTMA_PFREQCHG);
  593.             usleep(1);
  594.             /* restart write address logic */
  595.             RHDRegMask(Output, RV620_LVTMA_DATA_SYNCHRONIZATION,
  596.                        RV62_LVTMA_DSYNSEL, RV62_LVTMA_DSYNSEL);
  597.             /* SYNCEN disables pwrseq ?? */
  598.             RHDRegMask(Output, RV620_LVTMA_PWRSEQ_CNTL,
  599.                        RV62_LVTMA_PWRSEQ_DISABLE_SYNCEN_CONTROL_OF_TX_EN,
  600.                        RV62_LVTMA_PWRSEQ_DISABLE_SYNCEN_CONTROL_OF_TX_EN);
  601.             /* LVDS Mode ?? */
  602.             RHDRegMask(Output, RV620_LVTMA_TRANSMITTER_CONTROL,
  603.                        0, RV62_LVTMA_MODE);
  604.             /* enable links */
  605.             if (Private->RunDualLink) {
  606.                 if (Private->FMTDither.LVDS24Bit)
  607.                     RHDRegMask(Output, RV620_LVTMA_TRANSMITTER_ENABLE, 0x3ff, 0x3ff);
  608.                 else
  609.                     RHDRegMask(Output, RV620_LVTMA_TRANSMITTER_ENABLE, 0x1ef, 0x3ff);
  610.                     } else {
  611.                 if (Private->FMTDither.LVDS24Bit)
  612.                     RHDRegMask(Output, RV620_LVTMA_TRANSMITTER_ENABLE, 0x1f, 0x3ff);
  613.                 else
  614.                     RHDRegMask(Output, RV620_LVTMA_TRANSMITTER_ENABLE, 0x0f, 0x3ff);
  615.             }
  616.             RHDRegMask(Output, RV620_LVTMA_PWRSEQ_CNTL, 0,
  617.                        RV62_LVTMA_DIGON_OVRD | RV62_LVTMA_BLON_OVRD);
  618.             RHDRegMask(Output, RV620_LVTMA_PWRSEQ_REF_DIV, 3999, 0xffff); /* 4000 - 1 */
  619.             tmp = Private->PowerSequenceDe2Bl * 10 / 4;
  620.             tmp1 = Private->PowerSequenceDig2De * 10 / 4;
  621.             /* power sequencing delay for on / off between DIGON and SYNCEN, and SYNCEN and BLON */
  622.             RHDRegWrite(Output, RV620_LVTMA_PWRSEQ_DELAY1, (tmp1 << 24) | tmp1 | (tmp << 8) | (tmp << 16));
  623.             RHDRegWrite(Output, RV620_LVTMA_PWRSEQ_DELAY2, Private->OffDelay / 4);
  624.             RHDRegMask(Output, RV620_LVTMA_PWRSEQ_CNTL, 0, RV62_LVTMA_PWRSEQ_DISABLE_SYNCEN_CONTROL_OF_TX_EN);
  625.             for (i = 0; i < 500; i++) {
  626.                 CARD32 tmp;
  627.  
  628.                 usleep(1000);
  629.                 tmp = RHDRegRead(Output, RV620_LVTMA_PWRSEQ_STATE);
  630.                 tmp >>= RV62_LVTMA_PWRSEQ_STATE_SHIFT;
  631.                 tmp &= 0xff;
  632.                 if (tmp <= RV62_POWERUP_DONE)
  633.                     break;
  634.                 if (tmp >= RV62_POWERDOWN_DONE)
  635.                     break;
  636.             }
  637.             /* LCD on */
  638.             RHDRegMask(Output, RV620_LVTMA_PWRSEQ_CNTL, RV62_LVTMA_PWRSEQ_TARGET_STATE,
  639.                        RV62_LVTMA_PWRSEQ_TARGET_STATE);
  640.             return;
  641.  
  642.         case RHD_POWER_RESET:
  643.             /* Disable LCD and BL */
  644.             RHDRegMask(Output, RV620_LVTMA_PWRSEQ_CNTL, 0,
  645.                        RV62_LVTMA_PWRSEQ_TARGET_STATE
  646.                        | RV62_LVTMA_DIGON_OVRD
  647.                        | RV62_LVTMA_BLON_OVRD);
  648.             for (i = 0; i < 500; i++) {
  649.                 CARD32 tmp;
  650.  
  651.                 usleep(1000);
  652.                 tmp = RHDRegRead(Output, RV620_LVTMA_PWRSEQ_STATE);
  653.                 tmp >>= RV62_LVTMA_PWRSEQ_STATE_SHIFT;
  654.                 tmp &= 0xff;
  655.                 if (tmp >= RV62_POWERDOWN_DONE)
  656.                     break;
  657.             }
  658.             return;
  659.         case RHD_POWER_SHUTDOWN:
  660.             LVTMA_LVDSTransmitterPower(Output, RHD_POWER_RESET);
  661.             /* op-amp down, bias current for output driver down, shunt resistor down */
  662.             RHDRegWrite(Output, RV620_LVTMA_TRANSMITTER_ADJUST, 0x00e00000);
  663.             /* set macro control */
  664.             RHDRegWrite(Output, RV620_LVTMA_MACRO_CONTROL, 0x07430408);
  665.         default:
  666.             return;
  667.     }
  668. }
  669.  
  670. /*
  671.  *
  672.  */
  673. static void
  674. LVTMA_LVDSTransmitterSave(struct rhdOutput *Output)
  675. {
  676.     struct DIGPrivate *digPrivate = (struct DIGPrivate *)Output->Private;
  677.     struct LVTMATransmitterPrivate *Private = (struct LVTMATransmitterPrivate*)digPrivate->Transmitter.Private;
  678.  
  679.     RHDFUNC(Output);
  680.  
  681.     LVTMATransmitterSave(Output);
  682.  
  683.     Private->StoredPwrSeqCntl               = RHDRegRead(Output, RV620_LVTMA_PWRSEQ_CNTL);
  684.     Private->StoredPwrSeqRevDiv             = RHDRegRead(Output, RV620_LVTMA_PWRSEQ_REF_DIV);
  685.     Private->StoredPwrSeqDelay1             = RHDRegRead(Output, RV620_LVTMA_PWRSEQ_DELAY1);
  686.     Private->StoredPwrSeqDelay2             = RHDRegRead(Output, RV620_LVTMA_PWRSEQ_DELAY2);
  687.  
  688.     Private->Stored = TRUE;
  689. }
  690.  
  691. /*
  692.  *
  693.  */
  694. static void
  695. LVTMA_LVDSTransmitterRestore(struct rhdOutput *Output)
  696. {
  697.     struct DIGPrivate *digPrivate = (struct DIGPrivate *)Output->Private;
  698.     struct LVTMATransmitterPrivate *Private = (struct LVTMATransmitterPrivate*)digPrivate->Transmitter.Private;
  699.  
  700.     RHDFUNC(Output);
  701.  
  702.     if (!Private->Stored) {
  703.         xf86DrvMsg(Output->scrnIndex, X_ERROR,
  704.                    "%s: No registers stored.\n", __func__);
  705.         return;
  706.     }
  707.  
  708.     LVTMATransmitterRestore(Output);
  709.  
  710.     RHDRegWrite(Output, RV620_LVTMA_PWRSEQ_REF_DIV, Private->StoredPwrSeqRevDiv);
  711.     RHDRegWrite(Output, RV620_LVTMA_PWRSEQ_DELAY1, Private->StoredPwrSeqDelay1);
  712.     RHDRegWrite(Output, RV620_LVTMA_PWRSEQ_DELAY2, Private->StoredPwrSeqDelay2);
  713.     RHDRegWrite(Output, RV620_LVTMA_PWRSEQ_CNTL, Private->StoredPwrSeqCntl);
  714. }
  715.  
  716. /*
  717.  *
  718.  */
  719. static void
  720. LVTMATransmitterDestroy(struct rhdOutput *Output)
  721. {
  722.     struct DIGPrivate *digPrivate = (struct DIGPrivate *)Output->Private;
  723.  
  724.     RHDFUNC(Output);
  725.  
  726.     if (!digPrivate)
  727.         return;
  728.  
  729.     xfree(digPrivate->Transmitter.Private);
  730. }
  731.  
  732. #if defined(ATOM_BIOS) && defined(ATOM_BIOS_PARSER)
  733.  
  734. struct ATOMTransmitterPrivate
  735. {
  736.     struct atomTransmitterConfig atomTransmitterConfig;
  737.     enum atomTransmitter atomTransmitterID;
  738. };
  739.  
  740. /*
  741.  *
  742.  */
  743. static ModeStatus
  744. ATOMTransmitterModeValid(struct rhdOutput *Output, DisplayModePtr Mode)
  745. {
  746.  
  747.     RHDFUNC(Output);
  748.  
  749.     if (Output->Connector->Type == RHD_CONNECTOR_DVI_SINGLE
  750.         && Mode->SynthClock > 165000)
  751.         return MODE_CLOCK_HIGH;
  752.  
  753.     return MODE_OK;
  754. }
  755.  
  756. /*
  757.  *
  758.  */
  759. void
  760. rhdPrintDigDebug(RHDPtr rhdPtr, const char *name)
  761. {
  762.     xf86DrvMsgVerb(rhdPtr->scrnIndex, X_INFO, 7, "%s: DIGn_CNTL: n=1: 0x%x n=2: 0x%x\n",
  763.            name, RHDRegRead(rhdPtr, RV620_DIG1_CNTL),
  764.            RHDRegRead(rhdPtr, DIG2_OFFSET + RV620_DIG1_CNTL));
  765. }
  766.  
  767. /*
  768.  *
  769.  */
  770. static void
  771. ATOMTransmitterSet(struct rhdOutput *Output, struct rhdCrtc *Crtc, DisplayModePtr Mode)
  772. {
  773.     RHDPtr rhdPtr = RHDPTRI(Output);
  774.     struct DIGPrivate *Private = (struct DIGPrivate *)Output->Private;
  775.     struct ATOMTransmitterPrivate *transPrivate
  776.         = (struct ATOMTransmitterPrivate*) Private->Transmitter.Private;
  777.     struct atomTransmitterConfig *atc = &transPrivate->atomTransmitterConfig;
  778.  
  779.     RHDFUNC(Output);
  780.  
  781.     atc->Coherent = Private->Coherent;
  782.     atc->PixelClock = Mode->SynthClock;
  783.  
  784.     rhdPrintDigDebug(rhdPtr,__func__);
  785.  
  786.     if (Private->RunDualLink) {
  787.         atc->Mode = atomDualLink;
  788.  
  789.         if (atc->Link == atomTransLinkA)
  790.             atc->Link = atomTransLinkAB;
  791.         else if (atc->Link == atomTransLinkB)
  792.             atc->Link = atomTransLinkBA;
  793.  
  794.     } else {
  795.         atc->Mode = atomSingleLink;
  796.  
  797.         if (atc->Link == atomTransLinkAB)
  798.             atc->Link = atomTransLinkA;
  799.         else if (atc->Link == atomTransLinkBA)
  800.             atc->Link = atomTransLinkB;
  801.  
  802.     }
  803.  
  804.     atc->PixelClock = Mode->SynthClock;
  805.  
  806.     rhdAtomDigTransmitterControl(rhdPtr->atomBIOS, transPrivate->atomTransmitterID,
  807.                                  atomTransSetup, atc);
  808.     rhdPrintDigDebug(rhdPtr,__func__);
  809. }
  810.  
  811. /*
  812.  *
  813.  */
  814. static CARD32
  815. digProbeEncoder(struct rhdOutput *Output)
  816. {
  817.     if (Output->Id == RHD_OUTPUT_KLDSKP_LVTMA) {
  818.         return ENCODER_DIG2;
  819.     } else {
  820.         Bool swap = (RHDRegRead(Output, RV620_DCIO_LINK_STEER_CNTL)
  821.                      & RV62_LINK_STEER_SWAP) == RV62_LINK_STEER_SWAP;
  822.  
  823.         switch (Output->Id) {
  824.             case RHD_OUTPUT_UNIPHYA:
  825.                 if (swap) {
  826.                     RHDDebug(Output->scrnIndex, "%s: detected ENCODER_DIG2 for UNIPHYA\n",__func__);
  827.                     return ENCODER_DIG2;
  828.                 } else {
  829.                     RHDDebug(Output->scrnIndex, "%s: detected ENCODER_DIG1 for UNIPHYA\n",__func__);
  830.                     return ENCODER_DIG1;
  831.                 }
  832.                 break;
  833.             case RHD_OUTPUT_UNIPHYB:
  834.                 if (swap) {
  835.                     RHDDebug(Output->scrnIndex, "%s: detected ENCODER_DIG1 for UNIPHYB\n",__func__);
  836.                     return ENCODER_DIG1;
  837.                 } else {
  838.                     RHDDebug(Output->scrnIndex, "%s: detected ENCODER_DIG2 for UNIPHYB\n",__func__);
  839.                     return ENCODER_DIG2;
  840.                 }
  841.                 break;
  842.             default:
  843.                 return ENCODER_NONE; /* should not get here */
  844.         }
  845.     }
  846.     return ENCODER_NONE;
  847. }
  848.  
  849. /*
  850.  *
  851.  */
  852. static void
  853. ATOMTransmitterPower(struct rhdOutput *Output, int Power)
  854. {
  855.     RHDPtr rhdPtr = RHDPTRI(Output);
  856.     struct DIGPrivate *Private = (struct DIGPrivate *)Output->Private;
  857.     struct ATOMTransmitterPrivate *transPrivate
  858.         = (struct ATOMTransmitterPrivate*) Private->Transmitter.Private;
  859.     struct atomTransmitterConfig *atc = &transPrivate->atomTransmitterConfig;
  860.  
  861.     RHDFUNC(Output);
  862.  
  863.     rhdPrintDigDebug(rhdPtr,__func__);
  864.  
  865.     if (Private->RunDualLink)
  866.         atc->LinkCnt = atomDualLink;
  867.     else
  868.         atc->LinkCnt = atomSingleLink;
  869.  
  870.     atc->Coherent = Private->Coherent;
  871.  
  872.     if (atc->Encoder == atomEncoderNone) {
  873.         switch (digProbeEncoder(Output)) {
  874.             case ENCODER_DIG1:
  875.                 if (rhdPtr->DigEncoderOutput[0]) {
  876.                     RHDDebug(Output->scrnIndex,"%s: DIG1 for %s already taken\n",__func__,Output->Name);
  877.                     return;
  878.                 }
  879.                 atc->Encoder = atomEncoderDIG1;
  880.                 break;
  881.             case ENCODER_DIG2:
  882.                 if (rhdPtr->DigEncoderOutput[1]) {
  883.                     RHDDebug(Output->scrnIndex,"%s: DIG2 for %s already taken\n",__func__,Output->Name);
  884.                     return;
  885.                 }
  886.                 atc->Encoder = atomEncoderDIG2;
  887.                 break;
  888.             default:
  889.                 return;
  890.         }
  891.     }
  892.  
  893.     switch (Power) {
  894.         case RHD_POWER_ON:
  895.             rhdAtomDigTransmitterControl(rhdPtr->atomBIOS, transPrivate->atomTransmitterID,
  896.                                          atomTransEnable, atc);
  897.             rhdAtomDigTransmitterControl(rhdPtr->atomBIOS, transPrivate->atomTransmitterID,
  898.                                          atomTransEnableOutput, atc);
  899.             break;
  900.         case RHD_POWER_RESET:
  901.             rhdAtomDigTransmitterControl(rhdPtr->atomBIOS, transPrivate->atomTransmitterID,
  902.                                          atomTransDisableOutput, atc);
  903.             break;
  904.         case RHD_POWER_SHUTDOWN:
  905.             if (!Output->Connector || Output->Connector->Type == RHD_CONNECTOR_DVI)
  906.                 atc->Mode = atomDVI;
  907.  
  908.             rhdAtomDigTransmitterControl(rhdPtr->atomBIOS, transPrivate->atomTransmitterID,
  909.                                          atomTransDisableOutput, atc);
  910.             rhdAtomDigTransmitterControl(rhdPtr->atomBIOS, transPrivate->atomTransmitterID,
  911.                                          atomTransDisable, atc);
  912.             break;
  913.     }
  914.     rhdPrintDigDebug(rhdPtr,__func__);
  915. }
  916.  
  917. /*
  918.  *
  919.  */
  920. static void
  921. ATOMTransmitterSave(struct rhdOutput *Output)
  922. {
  923.     RHDFUNC(Output);
  924. }
  925.  
  926. /*
  927.  *
  928.  */
  929. static void
  930. ATOMTransmitterRestore(struct rhdOutput *Output)
  931. {
  932.     RHDFUNC(Output);
  933. }
  934.  
  935. /*
  936.  *
  937.  */
  938. static void
  939. ATOMTransmitterDestroy(struct rhdOutput *Output)
  940. {
  941.     struct DIGPrivate *digPrivate = (struct DIGPrivate *)Output->Private;
  942.  
  943.     RHDFUNC(Output);
  944.  
  945.     if (!digPrivate)
  946.         return;
  947.  
  948.     xfree(digPrivate->Transmitter.Private);
  949. }
  950.  
  951. #endif /* ATOM_BIOS && ATOM_BIOS_PASER */
  952.  
  953. /*
  954.  *  Encoder
  955.  */
  956.  
  957. struct DIGEncoder
  958. {
  959.     Bool Stored;
  960.  
  961.     CARD32 StoredOff;
  962.  
  963.     CARD32 StoredRegExt1DiffPostDivCntl;
  964.     CARD32 StoredRegExt2DiffPostDivCntl;
  965.     CARD32 StoredDIGClockPattern;
  966.     CARD32 StoredLVDSDataCntl;
  967.     CARD32 StoredTMDSPixelEncoding;
  968.     CARD32 StoredTMDSCntl;
  969.     CARD32 StoredDIGCntl;
  970.     CARD32 StoredDIGMisc1;
  971.     CARD32 StoredDIGMisc2;
  972.     CARD32 StoredDIGMisc3;
  973.     CARD32 StoredDCCGPclkDigCntl;
  974.     CARD32 StoredDCCGSymclkCntl;
  975.     CARD32 StoredDCIOLinkSteerCntl;
  976.     CARD32 StoredBlModCntl;
  977. };
  978.  
  979. /*
  980.  *
  981.  */
  982. static ModeStatus
  983. EncoderModeValid(struct rhdOutput *Output, DisplayModePtr Mode)
  984. {
  985.     RHDFUNC(Output);
  986.  
  987.     return MODE_OK;
  988. }
  989.  
  990. /*
  991.  *
  992.  */
  993. static void
  994. LVDSEncoder(struct rhdOutput *Output)
  995. {
  996.     struct DIGPrivate *Private = (struct DIGPrivate *)Output->Private;
  997.     CARD32 off;
  998.  
  999.     RHDFUNC(Output);
  1000.  
  1001.  
  1002.     off = (Private->EncoderID == ENCODER_DIG2) ? DIG2_OFFSET : DIG1_OFFSET;
  1003.     /* Clock pattern ? */
  1004.     RHDRegMask(Output, off + RV620_DIG1_CLOCK_PATTERN, 0x0063, 0xFFFF);
  1005.     /* set panel type: 18/24 bit mode */
  1006.     RHDRegMask(Output, off + RV620_LVDS1_DATA_CNTL,
  1007.                (Private->FMTDither.LVDS24Bit ? RV62_LVDS_24BIT_ENABLE : 0)
  1008.                | (Private->FPDI ? RV62_LVDS_24BIT_FORMAT : 0),
  1009.                RV62_LVDS_24BIT_ENABLE | RV62_LVDS_24BIT_FORMAT);
  1010.  
  1011.     Output->Crtc->FMTModeSet(Output->Crtc, &Private->FMTDither);
  1012. }
  1013.  
  1014. /*
  1015.  *
  1016.  */
  1017. static void
  1018. TMDSEncoder(struct rhdOutput *Output)
  1019. {
  1020.     struct DIGPrivate *Private = (struct DIGPrivate *)Output->Private;
  1021.     CARD32 off;
  1022.  
  1023.     RHDFUNC(Output);
  1024.  
  1025.     off = (Private->EncoderID == ENCODER_DIG2) ? DIG2_OFFSET : DIG1_OFFSET;
  1026.     /* clock pattern ? */
  1027.     RHDRegMask(Output, off + RV620_DIG1_CLOCK_PATTERN, 0x001F, 0xFFFF);
  1028.     /* color format RGB - normal color format 24bpp, Twin-Single 30bpp or Dual 48bpp*/
  1029.     RHDRegMask(Output, off + RV620_TMDS1_CNTL, 0x0,
  1030.                RV62_TMDS_PIXEL_ENCODING | RV62_TMDS_COLOR_FORMAT);
  1031.     /* no dithering */
  1032.     Output->Crtc->FMTModeSet(Output->Crtc, NULL);
  1033. }
  1034.  
  1035. /*
  1036.  *
  1037.  */
  1038. static void
  1039. EncoderSet(struct rhdOutput *Output, struct rhdCrtc *Crtc, DisplayModePtr Mode)
  1040. {
  1041.     struct DIGPrivate *Private = (struct DIGPrivate *)Output->Private;
  1042.     RHDPtr rhdPtr = RHDPTRI(Output);
  1043.     CARD32 off;
  1044.  
  1045.     RHDFUNC(Output);
  1046.  
  1047.     off = (Private->EncoderID == ENCODER_DIG2) ? DIG2_OFFSET : DIG1_OFFSET;
  1048.  
  1049.     rhdPrintDigDebug(rhdPtr,__func__);
  1050.  
  1051.     RHDRegMask(Output, off + RV620_DIG1_CNTL, Output->Crtc->Id,
  1052.                RV62_DIG_SOURCE_SELECT);
  1053.  
  1054.     if (Output->Id == RHD_OUTPUT_UNIPHYA) {
  1055.         /* select LinkA ?? */
  1056.         RHDRegMask(Output, RV620_DCIO_LINK_STEER_CNTL,
  1057.                    ((Private->EncoderID == ENCODER_DIG2)
  1058.                     ? RV62_LINK_STEER_SWAP
  1059.                     : 0), RV62_LINK_STEER_SWAP); /* swap if DIG2 */
  1060.         if (!Private->RunDualLink) {
  1061.             RHDRegMask(Output, off + RV620_DIG1_CNTL,
  1062.                        0,
  1063.                        RV62_DIG_SWAP |RV62_DIG_DUAL_LINK_ENABLE);
  1064.         } else {
  1065.             RHDRegMask(Output, off + RV620_DIG1_CNTL,
  1066.                        RV62_DIG_DUAL_LINK_ENABLE,
  1067.                        RV62_DIG_SWAP | RV62_DIG_DUAL_LINK_ENABLE);
  1068.         }
  1069.     } else if (Output->Id == RHD_OUTPUT_UNIPHYB) {
  1070.         /* select LinkB ?? */
  1071.         RHDRegMask(Output, RV620_DCIO_LINK_STEER_CNTL,
  1072.                    ((Private->EncoderID == ENCODER_DIG2)
  1073.                     ? 0
  1074.                     : RV62_LINK_STEER_SWAP), RV62_LINK_STEER_SWAP);
  1075.         if (!Private->RunDualLink)
  1076.             RHDRegMask(Output, off + RV620_DIG1_CNTL,
  1077.                        0,
  1078.                        RV62_DIG_SWAP |  RV62_DIG_DUAL_LINK_ENABLE);
  1079.          else
  1080.             RHDRegMask(Output, off + RV620_DIG1_CNTL,
  1081.                        RV62_DIG_SWAP | RV62_DIG_DUAL_LINK_ENABLE,
  1082.                        RV62_DIG_SWAP | RV62_DIG_DUAL_LINK_ENABLE);
  1083.     } else { /* LVTMA */
  1084.         RHDRegMask(Output, RV620_EXT2_DIFF_POST_DIV_CNTL, 0, RV62_EXT2_DIFF_DRIVER_ENABLE);
  1085.     }
  1086.  
  1087.     if (Private->EncoderMode == LVDS)
  1088.         LVDSEncoder(Output);
  1089.     else if (Private->EncoderMode == DISPLAYPORT)
  1090.       dbgprintf("No displayport support yet!",__FILE__, __LINE__, __func__);  /* bugger ! */
  1091.     else
  1092.         TMDSEncoder(Output);
  1093.  
  1094.     /* Start DIG, set links, disable stereo sync, select FMT source */
  1095.     RHDRegMask(Output, off + RV620_DIG1_CNTL,
  1096.                (Private->EncoderMode & 0x7) << 8
  1097.                | RV62_DIG_START
  1098.                | (Private->RunDualLink ? RV62_DIG_DUAL_LINK_ENABLE : 0)
  1099.                | Output->Crtc->Id,
  1100.                RV62_DIG_MODE
  1101.                | RV62_DIG_START
  1102.                | RV62_DIG_DUAL_LINK_ENABLE
  1103.                | RV62_DIG_STEREOSYNC_SELECT
  1104.                | RV62_DIG_SOURCE_SELECT);
  1105.     rhdPrintDigDebug(rhdPtr,__func__);
  1106. }
  1107.  
  1108. /*
  1109.  *
  1110.  */
  1111. static void
  1112. EncoderPower(struct rhdOutput *Output, int Power)
  1113. {
  1114.     struct DIGPrivate *Private = (struct DIGPrivate *)Output->Private;
  1115.     CARD32 off;
  1116.     enum encoderID EncoderID = Private->EncoderID;
  1117.     RHDPtr rhdPtr = Output->rhdPtr;
  1118.  
  1119.     RHDFUNC(Output);
  1120.  
  1121.     if (EncoderID == ENCODER_NONE) {
  1122.         EncoderID = digProbeEncoder(Output);
  1123.         switch (EncoderID) {
  1124.             case ENCODER_DIG1:
  1125.                 if (rhdPtr->DigEncoderOutput[0]) {
  1126.                     RHDDebug(Output->scrnIndex,"%s: DIG1 for %s already taken\n",__func__,Output->Name);
  1127.                     return;
  1128.                 }
  1129.                 break;
  1130.             case ENCODER_DIG2:
  1131.                 if (rhdPtr->DigEncoderOutput[1]) {
  1132.                     RHDDebug(Output->scrnIndex,"%s: DIG2 for %s already taken\n",__func__,Output->Name);
  1133.                     return;
  1134.                 }
  1135.                 break;
  1136.             default:
  1137.                 return;
  1138.         }
  1139.     }
  1140.  
  1141.     off = (EncoderID == ENCODER_DIG2) ? DIG2_OFFSET : DIG1_OFFSET;
  1142.  
  1143.     /* clock src is pixel PLL */
  1144.     RHDRegMask(Output, RV620_DCCG_SYMCLK_CNTL, 0x0,
  1145.                0x3 << ((EncoderID == ENCODER_DIG2)
  1146.                        ? RV62_SYMCLKB_SRC_SHIFT
  1147.                        : RV62_SYMCLKA_SRC_SHIFT));
  1148.  
  1149.     rhdPrintDigDebug(rhdPtr,__func__);
  1150.     switch (Power) {
  1151.         case RHD_POWER_ON:
  1152.             RHDDebug(Output->scrnIndex,"%s(RHD_POWER_ON, %i)\n",__func__,
  1153.                      EncoderID);
  1154.             /* enable DIG */
  1155.             RHDRegMask(Output, off + RV620_DIG1_CNTL, 0x10, 0x10);
  1156.             RHDRegMask(Output, (EncoderID == ENCODER_DIG2)
  1157.                        ? RV620_DCCG_PCLK_DIGB_CNTL
  1158.                        : RV620_DCCG_PCLK_DIGA_CNTL,
  1159.                        RV62_PCLK_DIGA_ON, RV62_PCLK_DIGA_ON); /* @@@ */
  1160.             rhdPrintDigDebug(rhdPtr,__func__);
  1161.             return;
  1162.         case RHD_POWER_RESET:
  1163.         case RHD_POWER_SHUTDOWN:
  1164.         default:
  1165.             RHDDebug(Output->scrnIndex,"%s(RHD_POWER_SHUTDOWN, %i)\n",__func__,
  1166.                      EncoderID);
  1167.             /* disable differential clock driver */
  1168.             if (EncoderID == ENCODER_DIG1)
  1169.                 RHDRegMask(Output, RV620_EXT1_DIFF_POST_DIV_CNTL,
  1170.                            0,
  1171.                            RV62_EXT1_DIFF_DRIVER_ENABLE);
  1172.             else
  1173.                 RHDRegMask(Output, RV620_EXT2_DIFF_POST_DIV_CNTL,
  1174.                            0,
  1175.                            RV62_EXT2_DIFF_DRIVER_ENABLE);
  1176.             /* disable DIG */
  1177.             RHDRegMask(Output, off + RV620_DIG1_CNTL, 0x0, 0x10);
  1178.             RHDRegMask(Output, (EncoderID == ENCODER_DIG2)
  1179.                        ? RV620_DCCG_PCLK_DIGB_CNTL
  1180.                        : RV620_DCCG_PCLK_DIGA_CNTL,
  1181.                        0, RV62_PCLK_DIGA_ON); /* @@@ */
  1182.             rhdPrintDigDebug(rhdPtr,__func__);
  1183.             return;
  1184.     }
  1185. }
  1186.  
  1187. /*
  1188.  *
  1189.  */
  1190. static void
  1191. EncoderSave(struct rhdOutput *Output)
  1192. {
  1193.     struct DIGPrivate *digPrivate = (struct DIGPrivate *)Output->Private;
  1194.     struct DIGEncoder *Private = (struct DIGEncoder *)(digPrivate->Encoder.Private);
  1195.     CARD32 off;
  1196.     enum encoderID EncoderID;
  1197.  
  1198.     RHDFUNC(Output);
  1199.  
  1200.     EncoderID = digProbeEncoder(Output);
  1201.     off = (EncoderID == ENCODER_DIG2) ? DIG2_OFFSET : DIG1_OFFSET;
  1202.     Private->StoredOff = off;
  1203.  
  1204.     Private->StoredRegExt1DiffPostDivCntl          = RHDRegRead(Output, off + RV620_EXT1_DIFF_POST_DIV_CNTL);
  1205.     Private->StoredRegExt2DiffPostDivCntl          = RHDRegRead(Output, off + RV620_EXT2_DIFF_POST_DIV_CNTL);
  1206.     Private->StoredDIGClockPattern = RHDRegRead(Output, off + RV620_DIG1_CLOCK_PATTERN);
  1207.     Private->StoredLVDSDataCntl    = RHDRegRead(Output, off + RV620_LVDS1_DATA_CNTL);
  1208.     Private->StoredDIGCntl         = RHDRegRead(Output, off + RV620_DIG1_CNTL);
  1209.     Private->StoredTMDSCntl        = RHDRegRead(Output, off + RV620_TMDS1_CNTL);
  1210.     Private->StoredDCIOLinkSteerCntl = RHDRegRead(Output, RV620_DCIO_LINK_STEER_CNTL);
  1211.     Private->StoredDCCGPclkDigCntl    = RHDRegRead(Output,
  1212.                                                    (off == DIG2_OFFSET)
  1213.                                                    ? RV620_DCCG_PCLK_DIGB_CNTL
  1214.                                                    : RV620_DCCG_PCLK_DIGA_CNTL);
  1215.     Private->StoredDCCGSymclkCntl     = RHDRegRead(Output, RV620_DCCG_SYMCLK_CNTL);
  1216.     Private->StoredBlModCntl          = RHDRegRead(Output, RV620_LVTMA_BL_MOD_CNTL);
  1217.  
  1218.     Private->Stored = TRUE;
  1219. }
  1220.  
  1221. /*
  1222.  *
  1223.  */
  1224. static void
  1225. EncoderRestore(struct rhdOutput *Output)
  1226. {
  1227.     struct DIGPrivate *digPrivate = (struct DIGPrivate *)Output->Private;
  1228.     struct DIGEncoder *Private = (struct DIGEncoder *)(digPrivate->Encoder.Private);
  1229.     CARD32 off;
  1230.  
  1231.     RHDFUNC(Output);
  1232.  
  1233.     if (!Private->Stored) {
  1234.         xf86DrvMsg(Output->scrnIndex, X_ERROR,
  1235.                    "%s: No registers stored.\n", __func__);
  1236.         return;
  1237.     }
  1238.     off = Private->StoredOff;
  1239.  
  1240.     RHDRegWrite(Output, off + RV620_EXT1_DIFF_POST_DIV_CNTL, Private->StoredRegExt1DiffPostDivCntl);
  1241.     RHDRegWrite(Output, off + RV620_EXT2_DIFF_POST_DIV_CNTL, Private->StoredRegExt2DiffPostDivCntl);
  1242.     /* reprogram all values but don't start the encoder, yet */
  1243.     RHDRegWrite(Output, off + RV620_DIG1_CNTL, Private->StoredDIGCntl & ~(CARD32)RV62_DIG_START);
  1244.     RHDRegWrite(Output, RV620_DCIO_LINK_STEER_CNTL, Private->StoredDCIOLinkSteerCntl);
  1245.     RHDRegWrite(Output, off + RV620_DIG1_CLOCK_PATTERN, Private->StoredDIGClockPattern);
  1246.     RHDRegWrite(Output, off + RV620_LVDS1_DATA_CNTL, Private->StoredLVDSDataCntl);
  1247.     RHDRegWrite(Output, off + RV620_TMDS1_CNTL, Private->StoredTMDSCntl);
  1248.     RHDRegWrite(Output, (off == DIG2_OFFSET)
  1249.                 ? RV620_DCCG_PCLK_DIGB_CNTL
  1250.                 : RV620_DCCG_PCLK_DIGA_CNTL,
  1251.                 Private->StoredDCCGPclkDigCntl);
  1252.     /* now enable the encoder */
  1253.     RHDRegWrite(Output, off + RV620_DIG1_CNTL, Private->StoredDIGCntl);
  1254.     RHDRegWrite(Output, RV620_DCCG_SYMCLK_CNTL, Private->StoredDCCGSymclkCntl);
  1255.     RHDRegWrite(Output, RV620_LVTMA_BL_MOD_CNTL, Private->StoredBlModCntl);
  1256. }
  1257.  
  1258. /*
  1259.  *
  1260.  */
  1261. static void
  1262. EncoderDestroy(struct rhdOutput *Output)
  1263. {
  1264.     struct DIGPrivate *digPrivate = (struct DIGPrivate *)Output->Private;
  1265.  
  1266.     RHDFUNC(Output);
  1267.  
  1268.     if (!digPrivate || !digPrivate->Encoder.Private)
  1269.         return;
  1270.  
  1271.     xfree(digPrivate->Encoder.Private);
  1272. }
  1273.  
  1274. /*
  1275.  * Housekeeping
  1276.  */
  1277. void
  1278. GetLVDSInfo(RHDPtr rhdPtr, struct DIGPrivate *Private)
  1279. {
  1280.     CARD32 off = (Private->EncoderID == ENCODER_DIG2) ? DIG2_OFFSET : DIG1_OFFSET;
  1281.     CARD32 tmp;
  1282.  
  1283.     RHDFUNC(rhdPtr);
  1284.  
  1285.     Private->FPDI = ((RHDRegRead(rhdPtr, off + RV620_LVDS1_DATA_CNTL)
  1286.                                  & RV62_LVDS_24BIT_FORMAT) != 0);
  1287.     Private->RunDualLink = ((RHDRegRead(rhdPtr, off + RV620_DIG1_CNTL)
  1288.                                  & RV62_DIG_DUAL_LINK_ENABLE) != 0);
  1289.     Private->FMTDither.LVDS24Bit = ((RHDRegRead(rhdPtr, off  + RV620_LVDS1_DATA_CNTL)
  1290.                            & RV62_LVDS_24BIT_ENABLE) != 0);
  1291.  
  1292.     tmp = RHDRegRead(rhdPtr, RV620_LVTMA_BL_MOD_CNTL);
  1293.     if (tmp & 0x1)
  1294.         Private->BlLevel = ( tmp >> LVTMA_BL_MOD_LEVEL_SHIFT )  & 0xff;
  1295.     else
  1296.         Private->BlLevel = -1;
  1297.  
  1298.     tmp = RHDRegRead(rhdPtr, RV620_LVTMA_PWRSEQ_REF_DIV);
  1299.     tmp &= 0xffff;
  1300.     tmp += 1;
  1301.     tmp /= 1000;
  1302.     Private->PowerSequenceDig2De = Private->PowerSequenceDe2Bl =
  1303.         RHDRegRead(rhdPtr, RV620_LVTMA_PWRSEQ_REF_DIV);
  1304.     Private->PowerSequenceDig2De = ((Private->PowerSequenceDig2De & 0xff) * tmp) / 10;
  1305.     Private->PowerSequenceDe2Bl = (((Private->PowerSequenceDe2Bl >> 8) & 0xff) * tmp) / 10;
  1306.     Private->OffDelay = RHDRegRead(rhdPtr, RV620_LVTMA_PWRSEQ_DELAY2);
  1307.     Private->OffDelay *= tmp;
  1308.  
  1309.     /* This is really ugly! */
  1310.     {
  1311.         CARD32 fmt_offset;
  1312.  
  1313.         tmp = RHDRegRead(rhdPtr, off + RV620_DIG1_CNTL);
  1314.         fmt_offset = (tmp & RV62_DIG_SOURCE_SELECT) ? FMT2_OFFSET :0;
  1315.         tmp = RHDRegRead(rhdPtr, fmt_offset + RV620_FMT1_BIT_DEPTH_CONTROL);
  1316.         Private->FMTDither.LVDSSpatialDither = ((tmp & 0x100) != 0);
  1317.         Private->FMTDither.LVDSGreyLevel = ((tmp & 0x10000) != 0);
  1318.         Private->FMTDither.LVDSTemporalDither
  1319.             = (Private->FMTDither.LVDSGreyLevel > 0) || ((tmp & 0x1000000) != 0);
  1320.     }
  1321.  
  1322. #ifdef ATOM_BIOS
  1323.     {
  1324.         AtomBiosArgRec data;
  1325.  
  1326.     if (RHDAtomBiosFunc(rhdPtr, rhdPtr->atomBIOS,
  1327.                                  ATOM_LVDS_FPDI, &data) == ATOM_SUCCESS)
  1328.             Private->FPDI = data.val;
  1329.  
  1330.     if (RHDAtomBiosFunc(rhdPtr, rhdPtr->atomBIOS,
  1331.                             ATOM_LVDS_DUALLINK, &data) == ATOM_SUCCESS)
  1332.             Private->RunDualLink = data.val;
  1333.  
  1334.     if (RHDAtomBiosFunc(rhdPtr, rhdPtr->atomBIOS,
  1335.                             ATOM_LVDS_GREYLVL, &data) == ATOM_SUCCESS)
  1336.             Private->FMTDither.LVDSGreyLevel = data.val;
  1337.  
  1338.     if (RHDAtomBiosFunc(rhdPtr, rhdPtr->atomBIOS,
  1339.                             ATOM_LVDS_SEQ_DIG_ONTO_DE, &data) == ATOM_SUCCESS)
  1340.             Private->PowerSequenceDig2De = data.val;
  1341.  
  1342.     if (RHDAtomBiosFunc(rhdPtr, rhdPtr->atomBIOS,
  1343.                             ATOM_LVDS_SEQ_DE_TO_BL, &data) == ATOM_SUCCESS)
  1344.             Private->PowerSequenceDe2Bl = data.val;
  1345.  
  1346.     if (RHDAtomBiosFunc(rhdPtr, rhdPtr->atomBIOS,
  1347.                             ATOM_LVDS_OFF_DELAY, &data) == ATOM_SUCCESS)
  1348.             Private->OffDelay = data.val;
  1349.  
  1350.     if (RHDAtomBiosFunc(rhdPtr, rhdPtr->atomBIOS,
  1351.                             ATOM_LVDS_24BIT, &data) == ATOM_SUCCESS)
  1352.             Private->FMTDither.LVDS24Bit = data.val;
  1353.  
  1354.     if (RHDAtomBiosFunc(rhdPtr, rhdPtr->atomBIOS,
  1355.                             ATOM_LVDS_SPATIAL_DITHER, &data) == ATOM_SUCCESS)
  1356.             Private->FMTDither.LVDSSpatialDither = data.val;
  1357.  
  1358.     if (RHDAtomBiosFunc(rhdPtr, rhdPtr->atomBIOS,
  1359.                             ATOM_LVDS_TEMPORAL_DITHER, &data) == ATOM_SUCCESS)
  1360.             Private->FMTDither.LVDSTemporalDither = data.val;
  1361.  
  1362.         Private->PowerSequenceDe2Bl = data.val;
  1363.  
  1364.     }
  1365. #endif
  1366.  
  1367. }
  1368.  
  1369. /*
  1370.  * Infrastructure
  1371.  */
  1372.  
  1373. static ModeStatus
  1374. DigModeValid(struct rhdOutput *Output, DisplayModePtr Mode)
  1375. {
  1376.     struct DIGPrivate *Private = (struct DIGPrivate *)Output->Private;
  1377.     struct transmitter *Transmitter = &Private->Transmitter;
  1378.     struct encoder *Encoder = &Private->Encoder;
  1379.     ModeStatus Status;
  1380.  
  1381.     RHDFUNC(Output);
  1382.  
  1383.     if ((Status = Transmitter->ModeValid(Output, Mode)) == MODE_OK)
  1384.         return ((Encoder->ModeValid(Output, Mode)));
  1385.     else
  1386.         return Status;
  1387. }
  1388.  
  1389. /*
  1390.  *
  1391.  */
  1392. static void
  1393. DigPower(struct rhdOutput *Output, int Power)
  1394. {
  1395.     struct DIGPrivate *Private = (struct DIGPrivate *)Output->Private;
  1396.     struct transmitter *Transmitter = &Private->Transmitter;
  1397.     struct encoder *Encoder = &Private->Encoder;
  1398.     Bool enableHDMI;
  1399.  
  1400.     RHDDebug(Output->scrnIndex, "%s(%s,%s)\n",__func__,Output->Name,
  1401.              rhdPowerString[Power]);
  1402.  
  1403.     if(Output->Connector != NULL) {
  1404.         /* check if attached monitor supports HDMI */
  1405.         enableHDMI = RHDConnectorEnableHDMI(Output->Connector);
  1406.         if (enableHDMI && Private->EncoderMode == TMDS_DVI)
  1407.             Private->EncoderMode = TMDS_HDMI;
  1408.         else if (!enableHDMI && Private->EncoderMode == TMDS_HDMI)
  1409.             Private->EncoderMode = TMDS_DVI;
  1410.     }
  1411.  
  1412.     switch (Power) {
  1413.         case RHD_POWER_ON:
  1414.             Encoder->Power(Output, Power);
  1415.             Transmitter->Power(Output, Power);
  1416.             RHDHdmiEnable(Private->Hdmi, Private->EncoderMode == TMDS_HDMI);
  1417.             return;
  1418.         case RHD_POWER_RESET:
  1419.             Transmitter->Power(Output, Power);
  1420.             Encoder->Power(Output, Power);
  1421.             return;
  1422.         case RHD_POWER_SHUTDOWN:
  1423.         default:
  1424.             Transmitter->Power(Output, Power);
  1425.             Encoder->Power(Output, Power);
  1426.             RHDHdmiEnable(Private->Hdmi, FALSE);
  1427.             return;
  1428.     }
  1429. }
  1430.  
  1431. /*
  1432.  *
  1433.  */
  1434. static Bool
  1435. DigPropertyControl(struct rhdOutput *Output,
  1436.                               enum rhdPropertyAction Action, enum rhdOutputProperty Property, union rhdPropertyData *val)
  1437. {
  1438.     struct DIGPrivate *Private = (struct DIGPrivate *)Output->Private;
  1439.  
  1440.     RHDFUNC(Output);
  1441.  
  1442.     switch(Property) {
  1443.         case RHD_OUTPUT_COHERENT:
  1444.         case RHD_OUTPUT_BACKLIGHT:
  1445.         {
  1446.             if (!Private->Transmitter.Property)
  1447.                 return FALSE;
  1448.             Private->Transmitter.Property(Output, Action, Property, val);
  1449.             break;
  1450.         }
  1451.         default:
  1452.             return FALSE;
  1453.     }
  1454.     return TRUE;
  1455. }
  1456.  
  1457.  
  1458. /*
  1459.  *
  1460.  */
  1461. static void
  1462. DigMode(struct rhdOutput *Output, DisplayModePtr Mode)
  1463. {
  1464.     struct DIGPrivate *Private = (struct DIGPrivate *)Output->Private;
  1465.     struct transmitter *Transmitter = &Private->Transmitter;
  1466.     struct encoder *Encoder = &Private->Encoder;
  1467.     struct rhdCrtc *Crtc = Output->Crtc;
  1468.  
  1469.     RHDFUNC(Output);
  1470.  
  1471.     /*
  1472.      * For dual link capable DVI we need to decide from the pix clock if we are dual link.
  1473.      * Do it here as it is convenient.
  1474.      */
  1475.     if (Output->Connector->Type == RHD_CONNECTOR_DVI)
  1476.         Private->RunDualLink = (Mode->SynthClock > 165000) ? TRUE : FALSE;
  1477.  
  1478.     Encoder->Mode(Output, Crtc, Mode);
  1479.     Transmitter->Mode(Output, Crtc, Mode);
  1480.     RHDHdmiSetMode(Private->Hdmi, Mode);
  1481. }
  1482.  
  1483. /*
  1484.  *
  1485.  */
  1486. static void
  1487. DigSave(struct rhdOutput *Output)
  1488. {
  1489.     struct DIGPrivate *Private = (struct DIGPrivate *)Output->Private;
  1490.     struct transmitter *Transmitter = &Private->Transmitter;
  1491.     struct encoder *Encoder = &Private->Encoder;
  1492.  
  1493.     RHDFUNC(Output);
  1494.  
  1495.     Encoder->Save(Output);
  1496.     Transmitter->Save(Output);
  1497.     RHDHdmiSave(Private->Hdmi);
  1498. }
  1499.  
  1500. /*
  1501.  *
  1502.  */
  1503. static void
  1504. DigRestore(struct rhdOutput *Output)
  1505. {
  1506.     struct DIGPrivate *Private = (struct DIGPrivate *)Output->Private;
  1507.     struct transmitter *Transmitter = &Private->Transmitter;
  1508.     struct encoder *Encoder = &Private->Encoder;
  1509.  
  1510.     RHDFUNC(Output);
  1511.  
  1512.     Encoder->Restore(Output);
  1513.     Transmitter->Restore(Output);
  1514.     RHDHdmiRestore(Private->Hdmi);
  1515. }
  1516.  
  1517. /*
  1518.  *
  1519.  */
  1520. static void
  1521. DigDestroy(struct rhdOutput *Output)
  1522. {
  1523.     struct DIGPrivate *Private = (struct DIGPrivate *)Output->Private;
  1524.     struct transmitter *Transmitter = &Private->Transmitter;
  1525.     struct encoder *Encoder = &Private->Encoder;
  1526.  
  1527.     RHDFUNC(Output);
  1528.  
  1529.     Encoder->Destroy(Output);
  1530.     Transmitter->Destroy(Output);
  1531.     RHDHdmiDestroy(Private->Hdmi);
  1532. #ifdef NOT_YET
  1533.     if (Transmitter->PropertyPrivate)
  1534.         RhdAtomDestroyBacklightControlProperty(Output, Transmitter->PropertyPrivate);
  1535. #endif
  1536.     xfree(Private);
  1537.     Output->Private = NULL;
  1538. }
  1539.  
  1540. /*
  1541.  *
  1542.  */
  1543. static Bool
  1544. DigAllocFree(struct rhdOutput *Output, enum rhdOutputAllocation Alloc)
  1545. {
  1546.     struct DIGPrivate *Private = (struct DIGPrivate *)Output->Private;
  1547.     RHDPtr rhdPtr = RHDPTRI(Output);
  1548.     char *TransmitterName;
  1549.  
  1550.     RHDFUNC(rhdPtr);
  1551.  
  1552.     switch (Output->Id) {
  1553.         case RHD_OUTPUT_KLDSKP_LVTMA:
  1554.             TransmitterName = "KLDSKP_LVTMA";
  1555.             break;
  1556.         case RHD_OUTPUT_UNIPHYA:
  1557.             TransmitterName = "UNIPHYA";
  1558.             break;
  1559.         case RHD_OUTPUT_UNIPHYB:
  1560.             TransmitterName = "UNIPHYB";
  1561.             break;
  1562.         default:
  1563.             return FALSE;
  1564.     }
  1565.     switch (Alloc) {
  1566.         case RHD_OUTPUT_ALLOC:
  1567.  
  1568.             if (Private->EncoderID != ENCODER_NONE)
  1569.                 return TRUE;
  1570.  
  1571.             /*
  1572.              * LVTMA can only use DIG2. Thus exclude
  1573.              * DIG1 for LVTMA and prefer it for the
  1574.              * UNIPHYs.
  1575.              */
  1576.             if (Output->Id == RHD_OUTPUT_KLDSKP_LVTMA) {
  1577.                 if (!rhdPtr->DigEncoderOutput[1]) {
  1578.                     rhdPtr->DigEncoderOutput[1] = Output;
  1579.                     Private->EncoderID = ENCODER_DIG2;
  1580.                     xf86DrvMsg(Output->scrnIndex, X_INFO,
  1581.                                "Mapping DIG2 encoder to %s\n",TransmitterName);
  1582.                 return TRUE;
  1583.                 } else
  1584.                     return FALSE;
  1585.             } else {
  1586.                 struct ATOMTransmitterPrivate *transPrivate =
  1587.                     (struct ATOMTransmitterPrivate *)Private->Transmitter.Private;
  1588.                 struct atomTransmitterConfig *atc = &transPrivate->atomTransmitterConfig;
  1589.                 if (!rhdPtr->DigEncoderOutput[0]) {
  1590.                     rhdPtr->DigEncoderOutput[0] = Output;
  1591.                     Private->EncoderID = ENCODER_DIG1;
  1592.                     atc->Encoder = atomEncoderDIG1;
  1593.                     xf86DrvMsg(Output->scrnIndex, X_INFO,
  1594.                                "Mapping DIG1 encoder to %s\n",TransmitterName);
  1595.                     return TRUE;
  1596.                 } else if (!rhdPtr->DigEncoderOutput[1]) {
  1597.                     rhdPtr->DigEncoderOutput[1] = Output;
  1598.                     Private->EncoderID = ENCODER_DIG2;
  1599.                     atc->Encoder = atomEncoderDIG2;
  1600.                     xf86DrvMsg(Output->scrnIndex, X_INFO,
  1601.                                "Mapping DIG2 encoder to %s\n",TransmitterName);
  1602.                     return TRUE;
  1603.                 } else
  1604.                     return FALSE;
  1605.             }
  1606.  
  1607.         case RHD_OUTPUT_FREE:
  1608.                 Private->EncoderID = ENCODER_NONE;
  1609.             if (rhdPtr->DigEncoderOutput[0] == Output) {
  1610.                 rhdPtr->DigEncoderOutput[0] = NULL;
  1611.                 return TRUE;
  1612.             } else if (rhdPtr->DigEncoderOutput[1] == Output) {
  1613.                 rhdPtr->DigEncoderOutput[1] = NULL;
  1614.                 return TRUE;
  1615.             } else
  1616.                 return FALSE;
  1617.             break;
  1618.         default:
  1619.             return FALSE;
  1620.     }
  1621. }
  1622.  
  1623. /*
  1624.  *
  1625.  */
  1626. static Bool
  1627. rhdDIGSetCoherent(RHDPtr rhdPtr,struct rhdOutput *Output)
  1628. {
  1629.     Bool coherent = FALSE;
  1630. //    int  from = X_CONFIG;
  1631.  
  1632. //    switch (RhdParseBooleanOption(&rhdPtr->coherent, Output->Name)) {
  1633. //    case RHD_OPTION_NOT_SET:
  1634. //    case RHD_OPTION_DEFAULT:
  1635. //        from = X_DEFAULT;
  1636. //        coherent = FALSE;
  1637. //        break;
  1638. //    case RHD_OPTION_ON:
  1639. //        coherent = TRUE;
  1640. //        break;
  1641. //    case RHD_OPTION_OFF:
  1642. //        coherent = FALSE;
  1643. //        break;
  1644. //    }
  1645. //    xf86DrvMsg(rhdPtr->scrnIndex,from,"Setting %s to %scoherent\n",
  1646. //           Output->Name,coherent ? "" : "in");
  1647.  
  1648.     return coherent;
  1649. }
  1650.  
  1651. /*
  1652.  *
  1653.  */
  1654. #ifdef NOT_YET
  1655. static Bool
  1656. digTransmitterPropertyWrapper(struct rhdOutput *Output,
  1657.                               enum rhdPropertyAction Action,
  1658.                               enum rhdOutputProperty Property,
  1659.                               union rhdPropertyData *val)
  1660. {
  1661.     struct DIGPrivate *Private = (struct DIGPrivate *)Output->Private;
  1662.     void *storePrivate = Output->Private;
  1663.     Bool (*func)(struct rhdOutput *,enum rhdPropertyAction, enum rhdOutputProperty,
  1664.                   union rhdPropertyData *) = Private->Transmitter.WrappedPropertyCallback;
  1665.     Bool ret;
  1666.  
  1667.     Output->Private = Private->Transmitter.PropertyPrivate;
  1668.     ret = func(Output, Action, Property, val);
  1669.     Output->Private = storePrivate;
  1670.  
  1671.     return ret;
  1672. }
  1673. #endif
  1674.  
  1675. /*
  1676.  *
  1677.  */
  1678. struct rhdOutput *
  1679. RHDDIGInit(RHDPtr rhdPtr,  enum rhdOutputType outputType, CARD8 ConnectorType)
  1680. {
  1681.     struct rhdOutput *Output;
  1682.     struct DIGPrivate *Private;
  1683.     struct DIGEncoder *Encoder;
  1684.  
  1685.     RHDFUNC(rhdPtr);
  1686.  
  1687.     Output = xnfcalloc(sizeof(struct rhdOutput), 1);
  1688.  
  1689.     Output->scrnIndex = rhdPtr->scrnIndex;
  1690.     Output->Id = outputType;
  1691.  
  1692.     Output->Sense = NULL;
  1693.     Output->ModeValid = DigModeValid;
  1694.     Output->Mode = DigMode;
  1695.     Output->Power = DigPower;
  1696.     Output->Save = DigSave;
  1697.     Output->Restore = DigRestore;
  1698.     Output->Destroy = DigDestroy;
  1699.     Output->Property = DigPropertyControl;
  1700.     Output->AllocFree = DigAllocFree;
  1701.  
  1702.     Private = xnfcalloc(sizeof(struct DIGPrivate), 1);
  1703.     Output->Private = Private;
  1704.  
  1705.     Private->EncoderID = ENCODER_NONE;
  1706.  
  1707.     switch (outputType) {
  1708.         case RHD_OUTPUT_UNIPHYA:
  1709. #if defined (ATOM_BIOS) && defined (ATOM_BIOS_PARSER)
  1710.             Output->Name = "UNIPHY_A";
  1711.             Private->Transmitter.Private =
  1712.                 (struct ATOMTransmitterPrivate *)xnfcalloc(sizeof (struct ATOMTransmitterPrivate), 1);
  1713.  
  1714.             Private->Transmitter.Sense = NULL;
  1715.             Private->Transmitter.ModeValid = ATOMTransmitterModeValid;
  1716.             Private->Transmitter.Mode = ATOMTransmitterSet;
  1717.             Private->Transmitter.Power = ATOMTransmitterPower;
  1718.             Private->Transmitter.Save = ATOMTransmitterSave;
  1719.             Private->Transmitter.Restore = ATOMTransmitterRestore;
  1720.             Private->Transmitter.Destroy = ATOMTransmitterDestroy;
  1721.             Private->Transmitter.Property = TMDSTransmitterPropertyControl;
  1722.             {
  1723.                 struct ATOMTransmitterPrivate *transPrivate =
  1724.                     (struct ATOMTransmitterPrivate *)Private->Transmitter.Private;
  1725.                 struct atomTransmitterConfig *atc = &transPrivate->atomTransmitterConfig;
  1726.                 atc->Coherent = Private->Coherent = rhdDIGSetCoherent(rhdPtr, Output);
  1727.                 atc->Link = atomTransLinkA;
  1728.                 atc->Encoder = atomEncoderNone;
  1729.                 if (RHDIsIGP(rhdPtr->ChipSet)) {
  1730.                     AtomBiosArgRec data;
  1731.                     data.val = 1;
  1732.             if (RHDAtomBiosFunc(rhdPtr, rhdPtr->atomBIOS, ATOM_GET_PCIE_LANES,
  1733.                                         &data) == ATOM_SUCCESS)
  1734.                         atc->Lanes = data.pcieLanes.Chassis; /* only do 'chassis' for now */
  1735.                     else {
  1736.                         xfree(Private);
  1737.                         xfree(Output);
  1738.                         return NULL;
  1739.                     }
  1740.                 }
  1741.                 if (RHDIsIGP(rhdPtr->ChipSet))
  1742.                     transPrivate->atomTransmitterID = atomTransmitterPCIEPHY;
  1743.                 else
  1744.                     transPrivate->atomTransmitterID = atomTransmitterUNIPHY;
  1745.             }
  1746.             break;
  1747. #else
  1748.             xfree(Private);
  1749.             xfree(Output);
  1750.             return NULL;
  1751. #endif /* ATOM_BIOS && ATOM_BIOS_PARSER */
  1752.  
  1753.         case RHD_OUTPUT_UNIPHYB:
  1754. #if defined (ATOM_BIOS) && defined (ATOM_BIOS_PARSER)
  1755.             Output->Name = "UNIPHY_B";
  1756.             Private->Transmitter.Private =
  1757.                 (struct atomTransmitterPrivate *)xnfcalloc(sizeof (struct ATOMTransmitterPrivate), 1);
  1758.  
  1759.             Private->Transmitter.Sense = NULL;
  1760.             Private->Transmitter.ModeValid = ATOMTransmitterModeValid;
  1761.             Private->Transmitter.Mode = ATOMTransmitterSet;
  1762.             Private->Transmitter.Power = ATOMTransmitterPower;
  1763.             Private->Transmitter.Save = ATOMTransmitterSave;
  1764.             Private->Transmitter.Restore = ATOMTransmitterRestore;
  1765.             Private->Transmitter.Destroy = ATOMTransmitterDestroy;
  1766.             Private->Transmitter.Property = TMDSTransmitterPropertyControl;
  1767.             {
  1768.                 struct ATOMTransmitterPrivate *transPrivate =
  1769.                     (struct ATOMTransmitterPrivate *)Private->Transmitter.Private;
  1770.                 struct atomTransmitterConfig *atc = &transPrivate->atomTransmitterConfig;
  1771.                 atc->Coherent = Private->Coherent = rhdDIGSetCoherent(rhdPtr, Output);
  1772.                 atc->Link = atomTransLinkB;
  1773.                 atc->Encoder = atomEncoderNone;
  1774.                 if (RHDIsIGP(rhdPtr->ChipSet)) {
  1775.                     AtomBiosArgRec data;
  1776.                     data.val = 2;
  1777.                     if (RHDAtomBiosFunc(rhdPtr->scrnIndex, rhdPtr->atomBIOS, ATOM_GET_PCIE_LANES,
  1778.                                         &data) == ATOM_SUCCESS)
  1779.                         atc->Lanes = data.pcieLanes.Chassis; /* only do 'chassis' for now */
  1780.                     else {
  1781.                         xfree(Private);
  1782.                         xfree(Output);
  1783.                         return NULL;
  1784.                     }
  1785.                 }
  1786.                 if (RHDIsIGP(rhdPtr->ChipSet))
  1787.                     transPrivate->atomTransmitterID = atomTransmitterPCIEPHY;
  1788.                 else
  1789.                     transPrivate->atomTransmitterID = atomTransmitterUNIPHY;
  1790.             }
  1791.             break;
  1792. #else
  1793.             xfree(Private);
  1794.             xfree(Output);
  1795.             return NULL;
  1796. #endif /* ATOM_BIOS && ATOM_BIOS_PARSER */
  1797.  
  1798.         case RHD_OUTPUT_KLDSKP_LVTMA:
  1799.             Output->Name = "UNIPHY_KLDSKP_LVTMA";
  1800.             Private->Coherent = rhdDIGSetCoherent(rhdPtr, Output);
  1801.             Private->Transmitter.Private =
  1802.                 (struct LVTMATransmitterPrivate *)xnfcalloc(sizeof (struct LVTMATransmitterPrivate), 1);
  1803.  
  1804.             Private->Transmitter.Sense = NULL;
  1805.             Private->Transmitter.ModeValid = LVTMATransmitterModeValid;
  1806.             if (ConnectorType != RHD_CONNECTOR_PANEL) {
  1807.                 Private->Transmitter.Mode = LVTMA_TMDSTransmitterSet;
  1808.                 Private->Transmitter.Power = LVTMA_TMDSTransmitterPower;
  1809.                 Private->Transmitter.Save = LVTMA_TMDSTransmitterSave;
  1810.                 Private->Transmitter.Restore = LVTMA_TMDSTransmitterRestore;
  1811.             } else {
  1812.                 Private->Transmitter.Mode = LVTMA_LVDSTransmitterSet;
  1813.                 Private->Transmitter.Power = LVTMA_LVDSTransmitterPower;
  1814.                 Private->Transmitter.Save = LVTMA_LVDSTransmitterSave;
  1815.                 Private->Transmitter.Restore = LVTMA_LVDSTransmitterRestore;
  1816.             }
  1817.             Private->Transmitter.Destroy = LVTMATransmitterDestroy;
  1818.             if (ConnectorType == RHD_CONNECTOR_PANEL)
  1819.                 Private->Transmitter.Property = LVDSTransmitterPropertyControl;
  1820.             else
  1821.                 Private->Transmitter.Property = TMDSTransmitterPropertyControl;
  1822.             break;
  1823.  
  1824.         default:
  1825.             xfree(Private);
  1826.             xfree(Output);
  1827.             return NULL;
  1828.     }
  1829.  
  1830.     Encoder = (struct DIGEncoder *)(xnfcalloc(sizeof (struct DIGEncoder),1));
  1831.     Private->Encoder.Private = Encoder;
  1832.     Private->Encoder.ModeValid = EncoderModeValid;
  1833.     Private->Encoder.Mode = EncoderSet;
  1834.     Private->Encoder.Power = EncoderPower;
  1835.     Private->Encoder.Save = EncoderSave;
  1836.     Private->Encoder.Restore = EncoderRestore;
  1837.     Private->Encoder.Destroy = EncoderDestroy;
  1838.  
  1839.     switch (ConnectorType) {
  1840.         case RHD_CONNECTOR_PANEL:
  1841.             Private->EncoderMode = LVDS;
  1842.             GetLVDSInfo(rhdPtr, Private);
  1843. #ifdef ATOM_BIOS
  1844. #ifdef NOT_YET
  1845.             if (Private->BlLevel < 0) {
  1846.                 Private->BlLevel = RhdAtomSetupBacklightControlProperty(Output,
  1847.                                                                         &Private->Transmitter.WrappedPropertyCallback,
  1848.                                                                         &Private->Transmitter.PropertyPrivate);
  1849.                 if (Private->Transmitter.PropertyPrivate)
  1850.                     Private->Transmitter.Property = digTransmitterPropertyWrapper;
  1851.             }
  1852. #endif
  1853. #endif
  1854.             Private->Hdmi = NULL;
  1855.             break;
  1856.         case RHD_CONNECTOR_DVI:
  1857.             Private->RunDualLink = FALSE; /* will be set later acc to pxclk */
  1858.             Private->EncoderMode = TMDS_DVI;
  1859.             Private->Hdmi = RHDHdmiInit(rhdPtr, Output);
  1860.             break;
  1861.         case RHD_CONNECTOR_DVI_SINGLE:
  1862.             Private->RunDualLink = FALSE;
  1863.             Private->EncoderMode = TMDS_DVI; /* changed later to HDMI if aplicateable */
  1864.             Private->Hdmi = RHDHdmiInit(rhdPtr, Output);
  1865.             break;
  1866.     }
  1867.  
  1868.     return Output;
  1869. }
  1870.