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. # include <string.h>
  38. # include <stdio.h>
  39. #endif
  40.  
  41. #include "rhd.h"
  42. #include "edid.h"
  43. #include "rhd_connector.h"
  44. #include "rhd_output.h"
  45. #include "rhd_crtc.h"
  46. #include "rhd_atombios.h"
  47. #include "rhd_atomout.h"
  48. #include "rhd_biosscratch.h"
  49. #include "rhd_hdmi.h"
  50.  
  51. #if defined (ATOM_BIOS) && defined (ATOM_BIOS_PARSER)
  52. struct rhdAtomOutputPrivate {
  53.     Bool Stored;
  54.  
  55.     struct atomCodeTableVersion EncoderVersion;
  56.     struct atomCodeTableVersion CrtcSourceVersion;
  57.     struct atomEncoderConfig EncoderConfig;
  58.     enum atomEncoder EncoderId;
  59.  
  60.     struct atomTransmitterConfig TransmitterConfig;
  61.     enum atomTransmitter TransmitterId;
  62.  
  63.     enum atomOutput OutputControlId;
  64.  
  65.     Bool   RunDualLink;
  66.     int    PixelClock;
  67.  
  68.     void  *Save;
  69.  
  70.     CARD16 PowerDigToDE;
  71.     CARD16 PowerDEToBL;
  72.     CARD16 OffDelay;
  73.     Bool   TemporalDither;
  74.     Bool   SpatialDither;
  75.     int    GreyLevel;
  76.     Bool   DualLink;
  77.     Bool   LVDS24Bit;
  78.     Bool   FPDI;
  79.  
  80.     Bool   Coherent;
  81.     DisplayModePtr Mode;
  82.     struct rhdHdmi *Hdmi;
  83.  
  84.     int    BlLevel;
  85. };
  86.  
  87. #define ERROR_MSG(x)    xf86DrvMsg(Output->scrnIndex, X_ERROR, "%s: %s failed.\n", __func__, x)
  88.  
  89. /*
  90.  *
  91.  */
  92. static inline void
  93. rhdSetEncoderTransmitterConfig(struct rhdOutput *Output, int PixelClock)
  94. {
  95.     RHDPtr rhdPtr = RHDPTRI(Output);
  96.     struct rhdAtomOutputPrivate *Private = (struct rhdAtomOutputPrivate *) Output->Private;
  97.     struct atomEncoderConfig *EncoderConfig = &Private->EncoderConfig;
  98.     struct atomTransmitterConfig *TransmitterConfig = &Private->TransmitterConfig;
  99.  
  100.     RHDFUNC(Output);
  101.  
  102.     EncoderConfig->PixelClock = TransmitterConfig->PixelClock = PixelClock;
  103.  
  104.     switch (Output->Id) {
  105.         case RHD_OUTPUT_NONE:
  106.             break;
  107.         case RHD_OUTPUT_DVO:
  108.  
  109.             EncoderConfig->u.dvo.DvoDeviceType = Output->OutputDriverPrivate->Device;
  110.             switch (EncoderConfig->u.dvo.DvoDeviceType) {
  111.                 case atomCRT1:
  112.                 case atomCRT2:
  113.                     EncoderConfig->u.dvo.digital = FALSE;
  114.                 break;
  115.                 case atomTV1:
  116.                 case atomTV2:
  117.                 case atomCV:
  118.                     EncoderConfig->u.dvo.digital = FALSE;
  119.                     EncoderConfig->u.dvo.u.TVMode = rhdPtr->tvMode;
  120.                 break;
  121.                 case atomLCD1:
  122.                 case atomDFP1:
  123.                 case atomDFP2:
  124.                 case atomLCD2:
  125.                 case atomDFP3:
  126.                 case atomDFP4:
  127.                 case atomDFP5:
  128.                     EncoderConfig->u.dvo.digital = TRUE;
  129.                     /* @@@ no digital attributes, yet */
  130.                 break;
  131.                 case atomNone:
  132.                     break;
  133.             }
  134.             break;
  135.         case RHD_OUTPUT_DACA:
  136.         case RHD_OUTPUT_DACB:
  137.             switch (Output->SensedType) {
  138.                 case RHD_SENSED_VGA:
  139.                     EncoderConfig->u.dac.DacStandard = atomDAC_VGA;
  140.                     break;
  141.                 case RHD_SENSED_TV_COMPONENT:
  142.                     EncoderConfig->u.dac.DacStandard = atomDAC_CV;
  143.                     break;
  144.                 case RHD_SENSED_TV_SVIDEO:
  145.                 case RHD_SENSED_TV_COMPOSITE:
  146.                     switch (rhdPtr->tvMode) {
  147.                         case RHD_TV_NTSC:
  148.                         case RHD_TV_NTSCJ:
  149.                             EncoderConfig->u.dac.DacStandard = atomDAC_NTSC;
  150.                             /* NTSC */
  151.                             break;
  152.                         case RHD_TV_PAL:
  153.                         case RHD_TV_PALN:
  154.                         case RHD_TV_PALCN:
  155.                         case RHD_TV_PAL60:
  156.                         default:
  157.                             EncoderConfig->u.dac.DacStandard = atomDAC_PAL;
  158.                             /* PAL */
  159.                             break;
  160.                     }
  161.                     break;
  162.                 case RHD_SENSED_NONE:
  163.                     EncoderConfig->u.dac.DacStandard = atomDAC_VGA;
  164.                     break;
  165.                 default:
  166.                     xf86DrvMsg(Output->scrnIndex, X_ERROR, "Sensed incompatible output for DAC\n");
  167.                     EncoderConfig->u.dac.DacStandard = atomDAC_VGA;
  168.                     break;
  169.             }
  170.             break;
  171.  
  172.         case RHD_OUTPUT_TMDSA:
  173.         case RHD_OUTPUT_LVTMA:
  174.             if (Output->Connector && PixelClock > 0) {
  175.                 if (Output->Connector->Type == RHD_CONNECTOR_DVI
  176. #if 0
  177.                     || Output->Connector->Type == RHD_CONNECTOR_HDMI_B
  178. #endif
  179.                     )
  180.                     Private->RunDualLink = (PixelClock > 165000) ? TRUE : FALSE;
  181.                 else
  182.                     Private->RunDualLink = FALSE;
  183.             } else
  184.                 /* only get here for power down: thus power down both channels to be save */
  185.                 Private->RunDualLink = TRUE;
  186.  
  187.             switch (Private->EncoderVersion.cref) {
  188.                 case 1:
  189.                     if (Private->RunDualLink)
  190.                         EncoderConfig->u.lvds.LinkCnt = atomDualLink;
  191.                     else
  192.                         EncoderConfig->u.lvds.LinkCnt = atomSingleLink;
  193.                     break;
  194.                 case 2:
  195.                 case 3:
  196.                     if (Private->RunDualLink)
  197.                         EncoderConfig->u.lvds2.LinkCnt = atomDualLink;
  198.                     else
  199.                         EncoderConfig->u.lvds2.LinkCnt = atomSingleLink;
  200.                     if (Private->Coherent)
  201.                         EncoderConfig->u.lvds2.Coherent = TRUE;
  202.                     else
  203.                         EncoderConfig->u.lvds2.Coherent = FALSE;
  204.                     break;
  205.             }
  206.             break;
  207.  
  208.         case RHD_OUTPUT_KLDSKP_LVTMA:
  209.         case RHD_OUTPUT_UNIPHYA:
  210.         case RHD_OUTPUT_UNIPHYB:
  211.         case RHD_OUTPUT_UNIPHYC:
  212.         case RHD_OUTPUT_UNIPHYD:
  213.         case RHD_OUTPUT_UNIPHYE:
  214.         case RHD_OUTPUT_UNIPHYF:
  215.             if (Output->Connector && PixelClock > 0) {
  216.                 if (Output->Connector->Type == RHD_CONNECTOR_DVI
  217. #if 0
  218.                     || Output->Connector->Type == RHD_CONNECTOR_DP_DUAL
  219.                     || Output->Connector->Type == RHD_CONNECTOR_HDMI_B
  220. #endif
  221.                     )
  222.                     Private->RunDualLink = (PixelClock > 165000) ? TRUE : FALSE;
  223.                 else
  224.                     Private->RunDualLink = FALSE;
  225.             } else
  226.                 /* only get here for power down: thus power down both channels to be save */
  227.                     Private->RunDualLink = TRUE;
  228.  
  229.             if (Private->RunDualLink) {
  230.                 TransmitterConfig->LinkCnt = EncoderConfig->u.dig.LinkCnt = atomDualLink;
  231.                 if (TransmitterConfig->Link == atomTransLinkA)
  232.                     TransmitterConfig->Link = atomTransLinkAB;
  233.                 else if (TransmitterConfig->Link == atomTransLinkB)
  234.                     TransmitterConfig->Link = atomTransLinkBA;
  235.             } else {
  236.                 TransmitterConfig->LinkCnt = EncoderConfig->u.dig.LinkCnt = atomSingleLink;
  237.                 if (TransmitterConfig->Link == atomTransLinkAB)
  238.                     TransmitterConfig->Link = atomTransLinkA;
  239.                 else if (TransmitterConfig->Link == atomTransLinkBA)
  240.                     TransmitterConfig->Link = atomTransLinkB;
  241.             }
  242.             TransmitterConfig->Coherent = Private->Coherent;
  243.             break;
  244.     }
  245. }
  246.  
  247. /*
  248.  *
  249.  */
  250. static void
  251. atomSetBacklightFromBIOSScratch(struct rhdOutput *Output)
  252. {
  253.     RHDPtr rhdPtr = RHDPTRI(Output);
  254.     struct rhdAtomOutputPrivate *Private = (struct rhdAtomOutputPrivate *) Output->Private;
  255.  
  256.     RHDFUNC(Output);
  257.  
  258.     switch (Output->Id) {
  259.         case RHD_OUTPUT_KLDSKP_LVTMA:
  260.         case RHD_OUTPUT_UNIPHYA:
  261.         case RHD_OUTPUT_UNIPHYB:
  262.         case RHD_OUTPUT_UNIPHYC:
  263.         case RHD_OUTPUT_UNIPHYD:
  264.         case RHD_OUTPUT_UNIPHYE:
  265.         case RHD_OUTPUT_UNIPHYF:
  266.             rhdSetEncoderTransmitterConfig(Output, Private->PixelClock);
  267.             if (!rhdAtomDigTransmitterControl(rhdPtr->atomBIOS, Private->TransmitterId,
  268.                                               atomTransLcdBlBrightness, &Private->TransmitterConfig))
  269.                 ERROR_MSG("rhdAtomDigTransmitterControl(atomTransEnable)");
  270.             break;
  271.         default:
  272.             if (!rhdAtomOutputControl(rhdPtr->atomBIOS, Private->OutputControlId, atomOutputLcdBrightnessControl))
  273.                 ERROR_MSG("rhdAtomOutputControl(atomOutputLcdBrightnessControl)");
  274.             break;
  275.     }
  276. }
  277.  
  278. /*
  279.  *
  280.  */
  281. static void
  282. atomSetBacklight(struct rhdOutput *Output, int value)
  283. {
  284.     RHDPtr rhdPtr = RHDPTRI(Output);
  285.  
  286.     RHDFUNC(Output);
  287.  
  288.     RHDAtomBIOSScratchBlLevel(rhdPtr, rhdBIOSScratchBlSet, &value);
  289.  
  290.     atomSetBacklightFromBIOSScratch(Output);
  291. }
  292.  
  293. /*
  294.  *
  295.  */
  296. static inline void
  297. rhdAtomOutputSet(struct rhdOutput *Output, DisplayModePtr Mode)
  298. {
  299.     RHDPtr rhdPtr = RHDPTRI(Output);
  300.     struct rhdAtomOutputPrivate *Private = (struct rhdAtomOutputPrivate *) Output->Private;
  301.     struct atomEncoderConfig *EncoderConfig = &Private->EncoderConfig;
  302.     struct atomCrtcSourceConfig CrtcSourceConfig;
  303.     union AtomBiosArg data;
  304.  
  305.     RHDFUNC(Output);
  306.  
  307.     Private->Mode = Mode;
  308.  
  309.     data.Address = &Private->Save;
  310.     RHDAtomBiosFunc(Output->scrnIndex, rhdPtr->atomBIOS, ATOM_SET_REGISTER_LIST_LOCATION, &data);
  311.  
  312.     Private->PixelClock = Mode->SynthClock;
  313.     rhdSetEncoderTransmitterConfig(Output, Private->PixelClock);
  314.  
  315.     switch ( Private->CrtcSourceVersion.cref){
  316.         case 1:
  317.             CrtcSourceConfig.u.Device = Output->OutputDriverPrivate->Device;
  318.             break;
  319.         case 2:
  320.             CrtcSourceConfig.u.crtc2.Encoder = Private->EncoderId;
  321.             CrtcSourceConfig.u.crtc2.Mode = EncoderConfig->u.dig.EncoderMode;
  322.             break;
  323.         default:
  324.             xf86DrvMsg(Output->scrnIndex, X_ERROR,
  325.                        "Unknown version of SelectCrtcSource code table: %i\n",Private->CrtcSourceVersion.cref);
  326.             return;
  327.     }
  328.     switch (Output->Id) {
  329.         case RHD_OUTPUT_UNIPHYA:
  330.         case RHD_OUTPUT_UNIPHYB:
  331.         case RHD_OUTPUT_UNIPHYC:
  332.         case RHD_OUTPUT_UNIPHYD:
  333.         case RHD_OUTPUT_UNIPHYE:
  334.         case RHD_OUTPUT_UNIPHYF:
  335. #if 1
  336.             rhdAtomDigTransmitterControl(rhdPtr->atomBIOS, Private->TransmitterId, atomTransInit,
  337.                                          &Private->TransmitterConfig);
  338. #endif
  339.         case RHD_OUTPUT_KLDSKP_LVTMA:
  340.             rhdAtomDigTransmitterControl(rhdPtr->atomBIOS, Private->TransmitterId, atomTransSetup,
  341.                                          &Private->TransmitterConfig);
  342.             break;
  343.         default:
  344.             break;
  345.     }
  346.  
  347.     rhdAtomSelectCrtcSource(rhdPtr->atomBIOS, Output->Crtc->Id ? atomCrtc2 : atomCrtc1, &CrtcSourceConfig);
  348.     data.Address = NULL;
  349.     RHDAtomBiosFunc(Output->scrnIndex, rhdPtr->atomBIOS, ATOM_SET_REGISTER_LIST_LOCATION, &data);
  350.     RHDHdmiSetMode(Private->Hdmi, Mode);
  351. }
  352.  
  353. /*
  354.  *
  355.  */
  356. static inline void
  357. rhdAtomOutputPower(struct rhdOutput *Output, int Power)
  358. {
  359.     RHDPtr rhdPtr = RHDPTRI(Output);
  360.     struct rhdAtomOutputPrivate *Private = (struct rhdAtomOutputPrivate *) Output->Private;
  361.     struct atomEncoderConfig *EncoderConfig = &Private->EncoderConfig;
  362.     union AtomBiosArg data;
  363.     Bool enableHDMI = FALSE;
  364.  
  365.     RHDFUNC(Output);
  366.  
  367.     if(Output->Connector != NULL) {
  368.         enableHDMI = RHDConnectorEnableHDMI(Output->Connector);
  369.         switch(Output->Id) {
  370.             case RHD_OUTPUT_TMDSA:
  371.             case RHD_OUTPUT_LVTMA:
  372.                 if(enableHDMI && !Private->EncoderConfig.u.lvds2.Hdmi)
  373.                     Private->EncoderConfig.u.lvds2.Hdmi = TRUE;
  374.                 else if(!enableHDMI && Private->EncoderConfig.u.lvds2.Hdmi)
  375.                     Private->EncoderConfig.u.lvds2.Hdmi = FALSE;
  376.                 break;
  377.  
  378.             case RHD_OUTPUT_UNIPHYA:
  379.             case RHD_OUTPUT_UNIPHYB:
  380.             case RHD_OUTPUT_KLDSKP_LVTMA:
  381.                 if(enableHDMI && Private->TransmitterConfig.Mode == atomDVI) {
  382.                     Private->TransmitterConfig.Mode = atomHDMI;
  383.                     Private->EncoderConfig.u.dig.EncoderMode = atomHDMI;
  384.  
  385.                 } else if(!enableHDMI && Private->TransmitterConfig.Mode == atomHDMI) {
  386.                     Private->TransmitterConfig.Mode = atomDVI;
  387.                     Private->EncoderConfig.u.dig.EncoderMode = atomDVI;
  388.                 }
  389.                 break;
  390.  
  391.             default:
  392.                 break;
  393.         }
  394.     }
  395.  
  396.     data.Address = &Private->Save;
  397.     RHDAtomBiosFunc(Output->scrnIndex, rhdPtr->atomBIOS, ATOM_SET_REGISTER_LIST_LOCATION, &data);
  398.  
  399.     rhdSetEncoderTransmitterConfig(Output, Private->PixelClock);
  400.  
  401.     switch (Power) {
  402.         case RHD_POWER_ON:
  403.             RHDDebug(Output->scrnIndex, "RHD_POWER_ON\n");
  404.             rhdAtomEncoderControl(rhdPtr->atomBIOS,  Private->EncoderId, atomEncoderOn, EncoderConfig);
  405.             switch (Output->Id) {
  406.                 case RHD_OUTPUT_KLDSKP_LVTMA:
  407.                 case RHD_OUTPUT_UNIPHYA:
  408.                 case RHD_OUTPUT_UNIPHYB:
  409.                 case RHD_OUTPUT_UNIPHYC:
  410.                 case RHD_OUTPUT_UNIPHYD:
  411.                 case RHD_OUTPUT_UNIPHYE:
  412.                 case RHD_OUTPUT_UNIPHYF:
  413.                     if (!rhdAtomDigTransmitterControl(rhdPtr->atomBIOS, Private->TransmitterId,
  414.                                                       atomTransEnable, &Private->TransmitterConfig)) {
  415.                         ERROR_MSG("rhdAtomDigTransmitterControl(atomTransEnable)");
  416.                         break;
  417.                     }
  418.                     if (!rhdAtomDigTransmitterControl(rhdPtr->atomBIOS, Private->TransmitterId,
  419.                                                       atomTransEnableOutput, &Private->TransmitterConfig))
  420.                         ERROR_MSG("rhdAtomDigTransmitterControl(atomTransEnableOutput)");
  421.                     break;
  422.                 default:
  423.                     if (!rhdAtomOutputControl(rhdPtr->atomBIOS, Private->OutputControlId, atomOutputEnable))
  424.                         ERROR_MSG("rhdAtomOutputControl(atomOutputEnable)");
  425.                     break;
  426.             }
  427.             RHDHdmiEnable(Private->Hdmi, enableHDMI);
  428.             break;
  429.         case RHD_POWER_RESET:
  430.             RHDDebug(Output->scrnIndex, "RHD_POWER_RESET\n");
  431.             switch (Output->Id) {
  432.                 case RHD_OUTPUT_KLDSKP_LVTMA:
  433.                 case RHD_OUTPUT_UNIPHYA:
  434.                 case RHD_OUTPUT_UNIPHYB:
  435.                 case RHD_OUTPUT_UNIPHYC:
  436.                 case RHD_OUTPUT_UNIPHYD:
  437.                 case RHD_OUTPUT_UNIPHYE:
  438.                 case RHD_OUTPUT_UNIPHYF:
  439.                     if (!rhdAtomDigTransmitterControl(rhdPtr->atomBIOS, Private->TransmitterId,
  440.                                                       atomTransDisableOutput, &Private->TransmitterConfig))
  441.                         ERROR_MSG("rhdAtomDigTransmitterControl(atomTransDisableOutput)");
  442.                     break;
  443.                 default:
  444.                     if (!rhdAtomOutputControl(rhdPtr->atomBIOS, Private->OutputControlId, atomOutputDisable))
  445.                         ERROR_MSG("rhdAtomOutputControl(atomOutputDisable)");
  446.                     break;
  447.             }
  448.             break;
  449.         case RHD_POWER_SHUTDOWN:
  450.             RHDDebug(Output->scrnIndex, "RHD_POWER_SHUTDOWN\n");
  451.             switch (Output->Id) {
  452.                 case RHD_OUTPUT_KLDSKP_LVTMA:
  453.                 case RHD_OUTPUT_UNIPHYA:
  454.                 case RHD_OUTPUT_UNIPHYB:
  455.                 case RHD_OUTPUT_UNIPHYC:
  456.                 case RHD_OUTPUT_UNIPHYD:
  457.                 case RHD_OUTPUT_UNIPHYE:
  458.                 case RHD_OUTPUT_UNIPHYF:
  459.                     if (Private->EncoderId == atomEncoderNone)
  460.                         break;
  461.                     if (!rhdAtomDigTransmitterControl(rhdPtr->atomBIOS, Private->TransmitterId,
  462.                                                       atomTransDisableOutput, &Private->TransmitterConfig)) {
  463.                         ERROR_MSG("rhdAtomDigTransmitterControl(atomTransDisableOutput)");
  464.                         break;
  465.                     }
  466.                     if (!rhdAtomDigTransmitterControl(rhdPtr->atomBIOS, Private->TransmitterId,
  467.                                                       atomTransDisable, &Private->TransmitterConfig))
  468.                         ERROR_MSG("rhdAtomDigTransmitterControl(atomTransDisable)");
  469.                     break;
  470.                 default:
  471.                     if (!rhdAtomOutputControl(rhdPtr->atomBIOS, Private->OutputControlId, atomOutputDisable))
  472.                         ERROR_MSG("rhdAtomOutputControl(atomOutputDisable)");
  473.                     break;
  474.             }
  475.             if (Private->EncoderId != atomEncoderNone)
  476.             if (!rhdAtomEncoderControl(rhdPtr->atomBIOS, Private->EncoderId, atomEncoderOff, &Private->EncoderConfig))
  477.                 ERROR_MSG("rhdAtomEncoderControl(atomEncoderOff)");
  478.             RHDHdmiEnable(Private->Hdmi, FALSE);
  479.             break;
  480.     }
  481.  
  482.     data.Address = NULL;
  483.     RHDAtomBiosFunc(Output->scrnIndex, rhdPtr->atomBIOS, ATOM_SET_REGISTER_LIST_LOCATION, &data);
  484. }
  485.  
  486. /*
  487.  *
  488.  */
  489. static inline void
  490. rhdAtomOutputSave(struct rhdOutput *Output)
  491. {
  492.      struct rhdAtomOutputPrivate *Private = (struct rhdAtomOutputPrivate *) Output->Private;
  493.      RHDHdmiSave(Private->Hdmi);
  494. }
  495.  
  496. /*
  497.  *
  498.  */
  499. static void
  500. rhdAtomOutputRestore(struct rhdOutput *Output)
  501. {
  502.      struct rhdAtomOutputPrivate *Private = (struct rhdAtomOutputPrivate *) Output->Private;
  503.      RHDPtr rhdPtr = RHDPTRI(Output);
  504.      union AtomBiosArg data;
  505.  
  506.      data.Address = &Private->Save;
  507.      RHDAtomBiosFunc(Output->scrnIndex, rhdPtr->atomBIOS, ATOM_RESTORE_REGISTERS, &data);
  508.      if (Output->Connector && Output->Connector->Type == RHD_CONNECTOR_PANEL)
  509.          atomSetBacklightFromBIOSScratch(Output);
  510.      RHDHdmiRestore(Private->Hdmi);
  511. }
  512.  
  513. /*
  514.  *
  515.  */
  516. static ModeStatus
  517. rhdAtomOutputModeValid(struct rhdOutput *Output, DisplayModePtr Mode)
  518. {
  519.     RHDFUNC(Output);
  520.  
  521.     if (Mode->Flags & V_INTERLACE)
  522.         return MODE_NO_INTERLACE;
  523.  
  524.     if (Mode->Clock < 25000)
  525.         return MODE_CLOCK_LOW;
  526.  
  527.  
  528.     if (Output->Connector->Type == RHD_CONNECTOR_DVI_SINGLE
  529. #if 0
  530.                 || Output->Connector->Type == RHD_CONNECTOR_DP_DUAL
  531.                 || Output->Connector->Type == RHD_CONNECTOR_HDMI_B
  532. #endif
  533.         ) {
  534.         if (Mode->Clock > 165000)
  535.             return MODE_CLOCK_HIGH;
  536.     }
  537.     else if (Output->Connector->Type == RHD_CONNECTOR_DVI) {
  538.         if (Mode->Clock > 330000) /* could go higher still */
  539.             return MODE_CLOCK_HIGH;
  540.     }
  541.  
  542.     return MODE_OK;
  543. }
  544.  
  545.  
  546. /*
  547.  *
  548.  */
  549. static Bool
  550. LVDSInfoRetrieve(RHDPtr rhdPtr, struct rhdAtomOutputPrivate *Private)
  551. {
  552.     AtomBiosArgRec data;
  553.  
  554.     if (RHDAtomBiosFunc(rhdPtr->scrnIndex, rhdPtr->atomBIOS,
  555.                         ATOM_LVDS_SEQ_DIG_ONTO_DE, &data) != ATOM_SUCCESS)
  556.         return FALSE;
  557.     Private->PowerDigToDE = data.val;
  558.  
  559.     if (RHDAtomBiosFunc(rhdPtr->scrnIndex, rhdPtr->atomBIOS,
  560.                         ATOM_LVDS_SEQ_DE_TO_BL, &data) != ATOM_SUCCESS)
  561.         return FALSE;
  562.     Private->PowerDEToBL = data.val;
  563.  
  564.     if (RHDAtomBiosFunc(rhdPtr->scrnIndex, rhdPtr->atomBIOS,
  565.                         ATOM_LVDS_OFF_DELAY, &data) != ATOM_SUCCESS)
  566.         return FALSE;
  567.     Private->OffDelay = data.val;
  568.  
  569.     if (RHDAtomBiosFunc(rhdPtr->scrnIndex, rhdPtr->atomBIOS,
  570.                         ATOM_LVDS_DUALLINK, &data) != ATOM_SUCCESS)
  571.         return FALSE;
  572.     Private->DualLink = data.val;
  573.  
  574.     if (RHDAtomBiosFunc(rhdPtr->scrnIndex, rhdPtr->atomBIOS,
  575.                         ATOM_LVDS_24BIT, &data) != ATOM_SUCCESS)
  576.         return FALSE;
  577.     Private->LVDS24Bit = data.val;
  578.  
  579.     if (RHDAtomBiosFunc(rhdPtr->scrnIndex, rhdPtr->atomBIOS,
  580.                         ATOM_LVDS_FPDI, &data) != ATOM_SUCCESS)
  581.         return FALSE;
  582.     Private->FPDI = data.val;
  583.  
  584.     if (RHDAtomBiosFunc(rhdPtr->scrnIndex, rhdPtr->atomBIOS,
  585.                         ATOM_LVDS_TEMPORAL_DITHER, &data) != ATOM_SUCCESS)
  586.         return FALSE;
  587.     Private->TemporalDither = data.val;
  588.  
  589.     if (RHDAtomBiosFunc(rhdPtr->scrnIndex, rhdPtr->atomBIOS,
  590.                         ATOM_LVDS_SPATIAL_DITHER, &data) != ATOM_SUCCESS)
  591.         return FALSE;
  592.     Private->SpatialDither = data.val;
  593.  
  594.     if (RHDAtomBiosFunc(rhdPtr->scrnIndex, rhdPtr->atomBIOS,
  595.                         ATOM_LVDS_GREYLVL, &data) != ATOM_SUCCESS)
  596.         return FALSE;
  597.     {
  598.         Private->GreyLevel = data.val;
  599.         xf86DrvMsg(rhdPtr->scrnIndex, X_ERROR, "AtomBIOS returned %i Grey Levels\n",
  600.                    Private->GreyLevel);
  601.     }
  602.     Private->Coherent = FALSE;
  603.  
  604.     RHDAtomBIOSScratchBlLevel(rhdPtr, rhdBIOSScratchBlGet, &Private->BlLevel);
  605.  
  606.     return TRUE;
  607. }
  608.  
  609. /*
  610.  * TMDSInfoRetrieve() - interface to set TMDS (DVI) parameters.
  611.  */
  612. static Bool
  613. TMDSInfoRetrieve(RHDPtr rhdPtr, struct rhdAtomOutputPrivate *Private)
  614. {
  615.     Private->FPDI = FALSE;
  616.     Private->TemporalDither = FALSE;
  617.     Private->SpatialDither = FALSE;
  618.     Private->GreyLevel = 0;
  619.     Private->BlLevel = -1;
  620.  
  621.     return TRUE;
  622. }
  623.  
  624. /*
  625.  *
  626.  */
  627. static Bool
  628. atomLVDSPropertyControl(struct rhdOutput *Output,
  629.              enum rhdPropertyAction Action, enum rhdOutputProperty Property, union rhdPropertyData *val)
  630. {
  631.     struct rhdAtomOutputPrivate *Private = (struct rhdAtomOutputPrivate *) Output->Private;
  632.  
  633.     RHDFUNC(Output);
  634.     switch (Action) {
  635.         case rhdPropertyCheck:
  636.             if (Private->BlLevel < 0)
  637.                 return FALSE;
  638.         switch (Property) {
  639.             case RHD_OUTPUT_BACKLIGHT:
  640.                     return TRUE;
  641.             default:
  642.                 return FALSE;
  643.         }
  644.         case rhdPropertyGet:
  645.             if (Private->BlLevel < 0)
  646.                 return FALSE;
  647.             switch (Property) {
  648.                 case RHD_OUTPUT_BACKLIGHT:
  649.                     val->integer = Private->BlLevel;
  650.                     return TRUE;
  651.                 default:
  652.                     return FALSE;
  653.             }
  654.             break;
  655.         case rhdPropertySet:
  656.             if (Private->BlLevel < 0)
  657.                 return FALSE;
  658.             switch (Property) {
  659.                 case RHD_OUTPUT_BACKLIGHT:
  660.                     atomSetBacklight(Output, val->integer);
  661.                     return TRUE;
  662.                 default:
  663.                     return FALSE;
  664.             }
  665.             break;
  666.     }
  667.     return TRUE;
  668. }
  669.  
  670. /*
  671.  *
  672.  */
  673. static Bool
  674. atomTMDSPropertyControl(struct rhdOutput *Output,
  675.              enum rhdPropertyAction Action, enum rhdOutputProperty Property, union rhdPropertyData *val)
  676. {
  677.     struct rhdAtomOutputPrivate *Private = (struct rhdAtomOutputPrivate *) Output->Private;
  678.  
  679.     RHDFUNC(Output);
  680.     switch (Action) {
  681.         case rhdPropertyCheck:
  682.         switch (Property) {
  683.             case RHD_OUTPUT_COHERENT:
  684.                     return TRUE;
  685.             default:
  686.                 return FALSE;
  687.         }
  688.         case rhdPropertyGet:
  689.             switch (Property) {
  690.                 case RHD_OUTPUT_COHERENT:
  691.                     val->Bool =  Private->Coherent;
  692.                     return TRUE;
  693.                 default:
  694.                     return FALSE;
  695.             }
  696.             break;
  697.         case rhdPropertySet:
  698.             switch (Property) {
  699.                 case RHD_OUTPUT_COHERENT:
  700.                     Private->Coherent = val->Bool;
  701.                     Output->Mode(Output, Private->Mode);
  702.                     Output->Power(Output, RHD_POWER_ON);
  703.                     break;
  704.                 default:
  705.                     return FALSE;
  706.             }
  707.             break;
  708.     }
  709.     return TRUE;
  710. }
  711.  
  712. /*
  713.  *
  714.  */
  715. static void
  716. rhdAtomOutputDestroy(struct rhdOutput *Output)
  717. {
  718.     struct rhdAtomOutputPrivate *Private = (struct rhdAtomOutputPrivate *) Output->Private;
  719.     RHDFUNC(Output);
  720.     if (Private->Save)
  721.         xfree(Private->Save);
  722.     RHDHdmiDestroy(Private->Hdmi);
  723.  
  724.     if (Private)
  725.         xfree(Private);
  726.     Output->Private = NULL;
  727.     xfree(Output->Name);
  728. }
  729.  
  730. /*
  731.  *
  732.  */
  733. static Bool
  734. RHDAtomOutputAllocFree(struct rhdOutput *Output, enum rhdOutputAllocation Alloc)
  735. {
  736.     struct rhdAtomOutputPrivate *Private = (struct rhdAtomOutputPrivate *) Output->Private;
  737.     struct atomTransmitterConfig *TransmitterConfig = &Private->TransmitterConfig;
  738.     RHDPtr rhdPtr = RHDPTRI(Output);
  739.     char *TransmitterName;
  740.  
  741.     RHDFUNC(rhdPtr);
  742.  
  743.     switch (Output->Id) {
  744.         case RHD_OUTPUT_KLDSKP_LVTMA:
  745.             TransmitterName = "KLDSKP_LVTMA";
  746.             break;
  747.         case RHD_OUTPUT_UNIPHYA:
  748.             TransmitterName = "KLDSKP_UNIPHYA";
  749.             break;
  750.         case RHD_OUTPUT_UNIPHYB:
  751.             TransmitterName = "KLDSKP_UNIPHYB";
  752.             break;
  753.         case RHD_OUTPUT_UNIPHYC:
  754.             TransmitterName = "KLDSKP_UNIPHYC";
  755.             break;
  756.         case RHD_OUTPUT_UNIPHYD:
  757.             TransmitterName = "KLDSKP_UNIPHYD";
  758.             break;
  759.         case RHD_OUTPUT_UNIPHYE:
  760.             TransmitterName = "KLDSKP_UNIPHYE";
  761.             break;
  762.         case RHD_OUTPUT_UNIPHYF:
  763.             TransmitterName = "KLDSKP_UNIPHYF";
  764.             break;
  765.         default:
  766.             return TRUE;
  767.     }
  768.  
  769.     switch (Alloc) {
  770.         case RHD_OUTPUT_ALLOC:
  771.             /*
  772.              * LVTMA can only use DIG2. Thus exclude
  773.              * DIG1 for LVTMA and prefer it for the
  774.              * UNIPHYs.
  775.              */
  776.             if (Private->EncoderId != atomEncoderNone)
  777.                 return TRUE;
  778.             if (Output->Id != RHD_OUTPUT_KLDSKP_LVTMA
  779.                 && !rhdPtr->DigEncoderOutput[0]) {
  780.                 rhdPtr->DigEncoderOutput[0] = Output;
  781.                 TransmitterConfig->Encoder = Private->EncoderId = atomEncoderDIG1;
  782.                 xf86DrvMsg(Output->scrnIndex, X_INFO, "Mapping DIG1 encoder to %s\n",TransmitterName);
  783.                 return TRUE;
  784.             } else if (!rhdPtr->DigEncoderOutput[1]) {
  785.                 rhdPtr->DigEncoderOutput[1] = Output;
  786.                 TransmitterConfig->Encoder = Private->EncoderId = atomEncoderDIG2;
  787.                 xf86DrvMsg(Output->scrnIndex, X_INFO, "Mapping DIG2 encoder to %s\n",TransmitterName);
  788.                 return TRUE;
  789.             } else
  790.                 return FALSE;
  791.         case RHD_OUTPUT_FREE:
  792.                 TransmitterConfig->Encoder = Private->EncoderId = atomEncoderNone;
  793.             if (rhdPtr->DigEncoderOutput[0] == Output) {
  794.                 rhdPtr->DigEncoderOutput[0] = NULL;
  795.                 return TRUE;
  796.             } else if (rhdPtr->DigEncoderOutput[1] == Output) {
  797.                 rhdPtr->DigEncoderOutput[1] = NULL;
  798.                 return TRUE;
  799.             } else
  800.                 return FALSE;
  801.             break;
  802.         default:
  803.             return FALSE;
  804.     }
  805. }
  806.  
  807. /*
  808.  *
  809.  */
  810. struct rhdOutput *
  811. RHDAtomOutputInit(RHDPtr rhdPtr, rhdConnectorType ConnectorType,
  812.                   rhdOutputType OutputType)
  813. {
  814.     struct rhdOutput *Output;
  815.     struct rhdAtomOutputPrivate *Private;
  816.     struct atomEncoderConfig *EncoderConfig;
  817.     struct atomTransmitterConfig *TransmitterConfig;
  818.     char *OutputName = NULL;
  819.  
  820.     RHDFUNC(rhdPtr);
  821.  
  822.     switch (OutputType) {
  823.         case RHD_OUTPUT_NONE:
  824.             return NULL;
  825.         case  RHD_OUTPUT_DACA:
  826.             OutputName = "DACA";
  827.             break;
  828.         case RHD_OUTPUT_DACB:
  829.             OutputName = "DACB";
  830.             break;
  831.         case RHD_OUTPUT_TMDSA:
  832.             OutputName = "TMDSA";
  833.             break;
  834.         case RHD_OUTPUT_LVTMA:
  835.             OutputName = "LVTMA";
  836.             break;
  837.         case RHD_OUTPUT_DVO:
  838.             OutputName = "DVO";
  839.             break;
  840.         case RHD_OUTPUT_KLDSKP_LVTMA:
  841.             OutputName = "KldskpLvtma";
  842.             break;
  843.         case RHD_OUTPUT_UNIPHYA:
  844.             OutputName = "UniphyA";
  845.             break;
  846.         case RHD_OUTPUT_UNIPHYB:
  847.             OutputName = "UniphyB";
  848.             break;
  849.         case RHD_OUTPUT_UNIPHYC:
  850.             OutputName = "UniphyC";
  851.             break;
  852.         case RHD_OUTPUT_UNIPHYD:
  853.             OutputName = "UniphyD";
  854.             break;
  855.         case RHD_OUTPUT_UNIPHYE:
  856.             OutputName = "UniphyE";
  857.             break;
  858.         case RHD_OUTPUT_UNIPHYF:
  859.             OutputName = "UniphyF";
  860.             break;
  861.     }
  862.  
  863.     Output = xnfcalloc(sizeof(struct rhdOutput), 1);
  864.     Output->scrnIndex = rhdPtr->scrnIndex;
  865.  
  866.     Output->Name = RhdAppendString(NULL, "AtomOutput");
  867.     Output->Name = RhdAppendString(Output->Name, OutputName);
  868.  
  869.     Output->Id = OutputType;
  870.     Output->Sense = NULL;
  871.     Private = xnfcalloc(sizeof(struct rhdAtomOutputPrivate), 1);
  872.     Output->Private = Private;
  873.     Output->OutputDriverPrivate = NULL;
  874.  
  875.     EncoderConfig = &Private->EncoderConfig;
  876.     Private->PixelClock = 0;
  877.  
  878.     switch (OutputType) {
  879.         case RHD_OUTPUT_NONE:
  880.             xfree(Output);
  881.             xfree(Private);
  882.             return NULL;
  883.         case RHD_OUTPUT_DACA:
  884.             Output->Sense = RHDBIOSScratchDACSense;
  885.             Private->EncoderId = atomEncoderDACA;
  886.             Private->OutputControlId = atomDAC1Output;
  887.             Private->Hdmi = NULL;
  888.             break;
  889.         case RHD_OUTPUT_DACB:
  890.             Output->Sense = RHDBIOSScratchDACSense;
  891.             Private->EncoderId = atomEncoderDACB;
  892.             Private->OutputControlId = atomDAC2Output;
  893.             Private->Hdmi = NULL;
  894.             break;
  895.         case RHD_OUTPUT_TMDSA:
  896.         case RHD_OUTPUT_LVTMA:
  897.             if (OutputType == RHD_OUTPUT_LVTMA) {
  898.                 if (ConnectorType == RHD_CONNECTOR_PANEL) {
  899.                     Private->OutputControlId = atomLCDOutput;
  900.                     LVDSInfoRetrieve(rhdPtr, Private);
  901.                     Private->RunDualLink = Private->DualLink;
  902.                     Private->EncoderId = atomEncoderLVDS;
  903.                 } else {
  904.                     TMDSInfoRetrieve(rhdPtr, Private);
  905.                     Private->OutputControlId = atomLVTMAOutput;
  906.                     Private->EncoderId = atomEncoderTMDS2;
  907.                 }
  908.             } else {
  909.                 TMDSInfoRetrieve(rhdPtr, Private);
  910.                 Private->OutputControlId = atomTMDSAOutput;
  911.                 Private->EncoderId = atomEncoderTMDS1;
  912.             }
  913.  
  914.             if (OutputType == RHD_CONNECTOR_DVI)
  915.                 Private->DualLink = TRUE;
  916.             else
  917.                 Private->DualLink = FALSE;
  918.  
  919.             if (ConnectorType != RHD_CONNECTOR_PANEL)
  920.                 Private->Hdmi = RHDHdmiInit(rhdPtr, Output);
  921.             else
  922.                 Private->Hdmi = NULL;
  923.  
  924.             Private->EncoderVersion = rhdAtomEncoderControlVersion(rhdPtr->atomBIOS, Private->EncoderId);
  925.             switch (Private->EncoderVersion.cref) {
  926.                 case 1:
  927.                     EncoderConfig->u.lvds.Is24bit = Private->LVDS24Bit;
  928.                     break;
  929.                 case 2:
  930.                 case 3:
  931.                     EncoderConfig->u.lvds2.Is24bit = Private->LVDS24Bit;
  932.                     EncoderConfig->u.lvds2.SpatialDither = Private->SpatialDither;
  933.                     EncoderConfig->u.lvds2.LinkB = 0; /* @@@ */
  934.                     EncoderConfig->u.lvds2.Hdmi = FALSE;
  935. #if 0
  936.                     if (ConnectorType == RHD_CONNECTOR_HDMI_B
  937.                         || ConnectorType == RHD_CONNECTOR_HDMI_A)
  938.                         EncoderConfig->u.lvds2.hdmi = TRUE;
  939. #endif
  940.                     switch (Private->GreyLevel) {
  941.                         case 2:
  942.                             EncoderConfig->u.lvds2.TemporalGrey = atomTemporalDither2;
  943.                             break;
  944.                         case 4:
  945.                             EncoderConfig->u.lvds2.TemporalGrey = atomTemporalDither4;
  946.                             break;
  947.                         case 0:
  948.                         default:
  949.                             EncoderConfig->u.lvds2.TemporalGrey = atomTemporalDither0;
  950.                     }
  951.                     if (Private->SpatialDither)
  952.                         EncoderConfig->u.lvds2.SpatialDither = TRUE;
  953.                     else
  954.                         EncoderConfig->u.lvds2.SpatialDither = FALSE;
  955.                     EncoderConfig->u.lvds2.Coherent = Private->Coherent;
  956.                     break;
  957.             }
  958.             break;
  959.         case RHD_OUTPUT_DVO:
  960.             Private->EncoderId = atomEncoderDVO;
  961.             Private->EncoderVersion = rhdAtomEncoderControlVersion(rhdPtr->atomBIOS,
  962.                                                                    Private->EncoderId);
  963.             switch (Private->EncoderVersion.cref) {
  964.                 case 1:
  965.                 case 2:
  966.                     /* Output->OutputDriverPrivate->Device not set yet. */
  967.                     break;
  968.                 case 3:  /* @@@ still to be handled */
  969.                     xfree(Output);
  970.                     xfree(Private);
  971.                     return NULL;
  972.             }
  973.             {
  974.                 struct atomCodeTableVersion version = rhdAtomOutputControlVersion(rhdPtr->atomBIOS, atomDVOOutput);
  975.                 switch (version.cref) {
  976.                     case 1:
  977.                     case 2:
  978.                         Private->OutputControlId = atomDVOOutput;
  979.                         break;
  980.                     case 3:
  981. #if 0
  982.                         Private->TransmitterId = atomTransmitterDVO;    /* @@@ check how to handle this one */
  983.                         break;
  984. #else
  985.                         xfree(Output);
  986.                         xfree(Private);
  987.                         return NULL;
  988. #endif
  989.                 }
  990.             }
  991.             break;
  992.         case RHD_OUTPUT_KLDSKP_LVTMA:
  993.             Private->EncoderVersion = rhdAtomEncoderControlVersion(rhdPtr->atomBIOS,
  994.                                                                    Private->EncoderId);
  995.             Output->AllocFree = RHDAtomOutputAllocFree;
  996.             EncoderConfig->u.dig.Link = atomTransLinkA;
  997.             EncoderConfig->u.dig.Transmitter = Private->TransmitterId = atomTransmitterLVTMA;
  998.  
  999.             TransmitterConfig = &Private->TransmitterConfig;
  1000.             TransmitterConfig->Link = atomTransLinkA;
  1001.             TransmitterConfig->Encoder =  Private->TransmitterId;
  1002.  
  1003.             if (ConnectorType == RHD_CONNECTOR_PANEL) {
  1004.                 TransmitterConfig->Mode = EncoderConfig->u.dig.EncoderMode = atomLVDS;
  1005.                 LVDSInfoRetrieve(rhdPtr, Private);
  1006.                 Private->Hdmi = NULL;
  1007.             } else {
  1008.                 TransmitterConfig->Mode = EncoderConfig->u.dig.EncoderMode = atomDVI;
  1009.                 TMDSInfoRetrieve(rhdPtr, Private);
  1010.                         Private->Coherent = FALSE;
  1011.                 Private->Hdmi = RHDHdmiInit(rhdPtr, Output);
  1012.             }
  1013.             break;
  1014.  
  1015.         case RHD_OUTPUT_UNIPHYA:
  1016.         case RHD_OUTPUT_UNIPHYB:
  1017.         case RHD_OUTPUT_UNIPHYC:
  1018.         case RHD_OUTPUT_UNIPHYD:
  1019.         case RHD_OUTPUT_UNIPHYE:
  1020.         case RHD_OUTPUT_UNIPHYF:
  1021.             Output->AllocFree = RHDAtomOutputAllocFree;
  1022.             if (RHDIsIGP(rhdPtr->ChipSet))
  1023.                 EncoderConfig->u.dig.Transmitter = Private->TransmitterId = atomTransmitterPCIEPHY;
  1024.             else {
  1025.                 switch (OutputType) {
  1026.                     case RHD_OUTPUT_UNIPHYA:
  1027.                     case RHD_OUTPUT_UNIPHYB:
  1028.                 EncoderConfig->u.dig.Transmitter = Private->TransmitterId = atomTransmitterUNIPHY;
  1029.                         break;
  1030.                     case RHD_OUTPUT_UNIPHYC:
  1031.                     case RHD_OUTPUT_UNIPHYD:
  1032.                         EncoderConfig->u.dig.Transmitter = Private->TransmitterId = atomTransmitterUNIPHY1;
  1033.                         break;
  1034.                     case RHD_OUTPUT_UNIPHYE:
  1035.                     case RHD_OUTPUT_UNIPHYF:
  1036.                         EncoderConfig->u.dig.Transmitter = Private->TransmitterId = atomTransmitterUNIPHY2;
  1037.                         break;
  1038.                     default:
  1039.                     xfree(Private);
  1040.                     xfree(Output);
  1041.                     return NULL;
  1042.                 }
  1043.             }
  1044.  
  1045.             TransmitterConfig = &Private->TransmitterConfig;
  1046.             TransmitterConfig->Encoder =  Private->EncoderId = atomEncoderNone;
  1047.             switch (OutputType) {
  1048.                 case RHD_OUTPUT_UNIPHYA:
  1049.                 case RHD_OUTPUT_UNIPHYC:
  1050.                 case RHD_OUTPUT_UNIPHYE:
  1051.                     TransmitterConfig->Link = EncoderConfig->u.dig.Link = atomTransLinkA;
  1052.                     break;
  1053.                 case RHD_OUTPUT_UNIPHYB:
  1054.                 case RHD_OUTPUT_UNIPHYD:
  1055.                 case RHD_OUTPUT_UNIPHYF:
  1056.                     TransmitterConfig->Link = EncoderConfig->u.dig.Link = atomTransLinkB;
  1057.                     break;
  1058.                 default:
  1059.                     xfree(Private);
  1060.                     xfree(Output);
  1061.                     return NULL;
  1062.             }
  1063.  
  1064.             if (RHDIsIGP(rhdPtr->ChipSet)) {
  1065.                 AtomBiosArgRec data;
  1066.                 data.val = 1;
  1067.                 if (RHDAtomBiosFunc(rhdPtr->scrnIndex, rhdPtr->atomBIOS, ATOM_GET_PCIE_LANES,
  1068.                                     &data) == ATOM_SUCCESS)
  1069.                     TransmitterConfig->Lanes = data.pcieLanes.Chassis;
  1070.                 /* only do 'chassis' for now */
  1071.                 else {
  1072.                     xfree(Private);
  1073.                     xfree(Output);
  1074.                     return NULL;
  1075.                 }
  1076.             }
  1077.  
  1078.             if (ConnectorType == RHD_CONNECTOR_PANEL)
  1079.                 LVDSInfoRetrieve(rhdPtr, Private);
  1080.             else
  1081.                 TMDSInfoRetrieve(rhdPtr, Private);
  1082.  
  1083.             switch (ConnectorType) {
  1084.                 case RHD_CONNECTOR_DVI:
  1085.                 case RHD_CONNECTOR_DVI_SINGLE:
  1086.                     TransmitterConfig->Mode = EncoderConfig->u.dig.EncoderMode = atomDVI;
  1087.                     Private->Hdmi = RHDHdmiInit(rhdPtr, Output);
  1088.                     break;
  1089.                 case RHD_CONNECTOR_PANEL:
  1090.                     TransmitterConfig->Mode = EncoderConfig->u.dig.EncoderMode = atomLVDS;
  1091.                     break;
  1092. #if 0
  1093.                 case RHD_CONNECTOR_DP:
  1094.                 case RHD_CONNECTOR_DP_DUAL:
  1095.                     TransmitterConfig->Mode = EncoderConfig->u.dig.EncoderMode = atomDP;
  1096.                     break;
  1097.                 case RHD_CONNECTOR_HDMI_A:
  1098.                 case RHD_CONNECTOR_HDMI_B:
  1099.                     TransmitterConfig->Mode = EncoderConfig->u.dig.EncoderMode = atomHDMI;
  1100.                     break;
  1101. #endif
  1102.                 default:
  1103.                     xf86DrvMsg(rhdPtr->scrnIndex, X_ERROR, "%s: Unknown connector type\n",__func__);
  1104.                     xfree(Output);
  1105.                     xfree(Private);
  1106.                     return NULL;
  1107.             }
  1108.             break;
  1109.         default:
  1110.             xf86DrvMsg(rhdPtr->scrnIndex, X_ERROR, "Unknown output type\n");
  1111.             xfree(Output);
  1112.             xfree(Private);
  1113.             return NULL;
  1114.     }
  1115.     if (ConnectorType == RHD_CONNECTOR_PANEL) {
  1116.         Output->Property = atomLVDSPropertyControl;
  1117.         LVDSInfoRetrieve(rhdPtr, Private);
  1118.     } else {
  1119.         Output->Property = atomTMDSPropertyControl;
  1120.         TMDSInfoRetrieve(rhdPtr, Private);
  1121.     }
  1122.  
  1123.  
  1124.     Output->Mode = rhdAtomOutputSet;
  1125.     Output->Power = rhdAtomOutputPower;
  1126.     Output->Save = rhdAtomOutputSave;
  1127.     Output->Restore = rhdAtomOutputRestore;
  1128.     Output->ModeValid = rhdAtomOutputModeValid;
  1129.     Output->Destroy = rhdAtomOutputDestroy;
  1130.     Private->CrtcSourceVersion = rhdAtomSelectCrtcSourceVersion(rhdPtr->atomBIOS);
  1131.  
  1132.     return Output;
  1133. }
  1134.  
  1135. /*
  1136.  * This sets up AtomBIOS based BL control if we need to use a non-standard method to control BL.
  1137.  */
  1138. int
  1139. RhdAtomSetupBacklightControlProperty(struct rhdOutput *Output,
  1140.                                      Bool (**PropertyFunc)(struct rhdOutput *Output,
  1141.                                                            enum rhdPropertyAction Action,
  1142.                                                            enum rhdOutputProperty Property,
  1143.                                                            union rhdPropertyData *val), void **PrivatePtr)
  1144. {
  1145.     RHDPtr rhdPtr = RHDPTRI(Output);
  1146.     int BlLevel;
  1147.     struct rhdAtomOutputPrivate *Private;
  1148.     struct atomTransmitterConfig *TransmitterConfig;
  1149.  
  1150.     RHDFUNC(Output);
  1151.  
  1152.     Private = xnfcalloc(sizeof(struct rhdAtomOutputPrivate), 1);
  1153.  
  1154.     switch (Output->Id) {
  1155.         case RHD_OUTPUT_KLDSKP_LVTMA:
  1156.         case RHD_OUTPUT_UNIPHYE:
  1157.         case RHD_OUTPUT_UNIPHYF:
  1158.             /* We set up a those parameters although they may never be needed for BL control */
  1159.             TransmitterConfig = &Private->TransmitterConfig;
  1160.             switch (Output->Id) {
  1161.                 case RHD_OUTPUT_KLDSKP_LVTMA:
  1162.                     Private->TransmitterId = atomTransmitterLVTMA;
  1163.                     break;
  1164.                 case RHD_OUTPUT_UNIPHYE:
  1165.                     Private->TransmitterId = atomTransmitterUNIPHY2;
  1166.                     TransmitterConfig->Link = atomTransLinkA;
  1167.                     break;
  1168.                 case RHD_OUTPUT_UNIPHYF:
  1169.                     Private->TransmitterId = atomTransmitterUNIPHY2;
  1170.                     TransmitterConfig->Link = atomTransLinkB;
  1171.                     break;
  1172.                 default:
  1173.                     return 0;  /* never get here */
  1174.             }
  1175.             TransmitterConfig = &Private->TransmitterConfig;
  1176.             TransmitterConfig->Mode = atomLVDS;
  1177.             if (rhdPtr->DigEncoderOutput[0] == Output)
  1178.                 TransmitterConfig->Encoder =  Private->EncoderId = atomEncoderDIG1;
  1179.             else if (rhdPtr->DigEncoderOutput[1] == Output)
  1180.                 TransmitterConfig->Encoder =  Private->EncoderId = atomEncoderDIG2;
  1181.             else
  1182.                 TransmitterConfig->Encoder =  Private->EncoderId = atomEncoderNone;
  1183.             LVDSInfoRetrieve(rhdPtr, Private);
  1184.             Private->PixelClock = 0;
  1185.             Private->Hdmi = NULL;
  1186.             break;
  1187.         case RHD_OUTPUT_LVTMA:
  1188.             Private->OutputControlId = atomLCDOutput;
  1189.             break;
  1190.         default:
  1191.             xfree(Private);
  1192.             return 0;
  1193.     }
  1194.     *PropertyFunc = atomLVDSPropertyControl;
  1195.     *PrivatePtr = Private;
  1196.     RHDAtomBIOSScratchBlLevel(rhdPtr, rhdBIOSScratchBlGet, &BlLevel);
  1197.  
  1198.     return BlLevel;
  1199. }
  1200.  
  1201. void
  1202. RhdAtomDestroyBacklightControlProperty(struct rhdOutput *Output, void *PrivatePtr)
  1203. {
  1204.     if (PrivatePtr)
  1205.         xfree(PrivatePtr);
  1206. }
  1207.  
  1208. #endif /* ATOM_BIOS && ATOM_BIOS_PARSER */
  1209.