Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright 2007, 2008  Egbert Eich   <eich@novell.com>
  3.  * Copyright 2007, 2008  Luc Verhaegen <lverhaegen@novell.com>
  4.  * Copyright 2007, 2008  Matthias Hopf <mhopf@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. #ifdef ATOM_BIOS
  31. # include "xf86.h"
  32. #include "rhd.h"
  33.  
  34. # include "edid.h"
  35.  
  36. # include "xf86DDC.h"
  37.  
  38. # if HAVE_XF86_ANSIC_H
  39. #  include "xf86_ansic.h"
  40. # else
  41. #  include <unistd.h>
  42. #  include <string.h>
  43. #  include <stdio.h>
  44. # endif
  45.  
  46.  
  47.  
  48. # include "rhd_atombios.h"
  49.  
  50. # include "rhd_connector.h"
  51. # include "rhd_output.h"
  52. # include "rhd_biosscratch.h"
  53. # include "rhd_crtc.h"
  54. # include "rhd_card.h"
  55.  
  56. # ifdef ATOM_BIOS_PARSER
  57. #  define INT8 INT8
  58. #  define INT16 INT16
  59. #  define INT32 INT32
  60. #  include "CD_Common_Types.h"
  61. # else
  62. #  ifndef ULONG
  63. typedef unsigned int ULONG;
  64. #   define ULONG ULONG
  65. #  endif
  66. #  ifndef UCHAR
  67. typedef unsigned char UCHAR;
  68. #   define UCHAR UCHAR
  69. #  endif
  70. #  ifndef USHORT
  71. typedef unsigned short USHORT;
  72. #   define USHORT USHORT
  73. #  endif
  74. # endif
  75.  
  76. # include "atombios.h"
  77.  
  78. struct rhdOutputDevices {
  79.     enum atomDevice DeviceId;
  80.     enum rhdConnectorType ConnectorType;
  81. };
  82.  
  83. #if defined (ATOM_BIOS_PARSER)
  84. /*
  85.  *
  86.  */
  87. static enum rhdSensedOutput
  88. rhdAtomBIOSScratchDACSenseResults(struct rhdOutput *Output, enum atomDAC DAC, enum atomDevice Device)
  89. {
  90.     RHDPtr rhdPtr = RHDPTRI(Output);
  91.     CARD32 BIOS_0;
  92.     Bool TV = FALSE;
  93.  
  94.     RHDFUNC(Output);
  95.  
  96.     if (rhdPtr->ChipSet < RHD_R600)
  97.         BIOS_0 = RHDRegRead(Output, 0x10);
  98.     else
  99.         BIOS_0 = RHDRegRead(Output, 0x1724);
  100.  
  101.     switch (Device) {
  102.         case atomNone:
  103.         case atomCRT2:
  104.         case atomCRT1:
  105.         case atomLCD1:
  106.         case atomLCD2:
  107.         case atomDFP1:
  108.         case atomDFP2:
  109.         case atomDFP3:
  110.         case atomDFP4:
  111.         case atomDFP5:
  112.             TV = FALSE;
  113.             break;
  114.         case atomTV1:
  115.         case atomTV2:
  116.         case atomCV:
  117.             TV = TRUE;
  118.             break;
  119.     }
  120.  
  121.     RHDDebug(Output->scrnIndex, "BIOSScratch_0: 0x%4.4x\n",BIOS_0);
  122.  
  123.     switch (DAC) {
  124.         case atomDACA:
  125.             break;
  126.         case atomDACB:
  127.             BIOS_0 >>= 8;
  128.             break;
  129.         case atomDACExt:
  130.             return RHD_SENSED_NONE;
  131.     }
  132.  
  133.     if (!TV) {
  134.         if (BIOS_0 & ATOM_S0_CRT1_MASK) {
  135.             RHDDebug(Output->scrnIndex, "%s sensed RHD_SENSED_VGA\n",__func__);
  136.             return RHD_SENSED_VGA;
  137.         }
  138.     } else {
  139.         if (BIOS_0 & ATOM_S0_TV1_COMPOSITE_A) {
  140.             RHDDebug(Output->scrnIndex, "%s: RHD_SENSED_TV_COMPOSITE\n",__func__);
  141.             return RHD_SENSED_TV_COMPOSITE;
  142.         } else if (BIOS_0 & ATOM_S0_TV1_SVIDEO_A) {
  143.             RHDDebug(Output->scrnIndex, "%s: RHD_SENSED_TV_SVIDE\n",__func__);
  144.             return RHD_SENSED_TV_SVIDEO;
  145.         } else if (BIOS_0 & ATOM_S0_CV_MASK_A) {
  146.             RHDDebug(Output->scrnIndex, "%s: RHD_SENSED_TV_COMPONENT\n",__func__);
  147.             return RHD_SENSED_TV_COMPONENT;
  148.         }
  149.     }
  150.  
  151.     RHDDebug(Output->scrnIndex, "%s: RHD_SENSED_NONE\n",__func__);
  152.     return RHD_SENSED_NONE;
  153. }
  154.  
  155. /*
  156.  *
  157.  */
  158. enum rhdSensedOutput
  159. RHDBIOSScratchDACSense(struct rhdOutput *Output, struct rhdConnector *Connector)
  160. {
  161.     RHDPtr rhdPtr = RHDPTRI(Output);
  162.     enum atomDAC DAC;
  163.     Bool ret;
  164.     Bool TV;
  165.     enum atomDevice Device;
  166.     enum rhdSensedOutput retVal;
  167.     int i = 0;
  168.  
  169.     RHDFUNC(Output);
  170.  
  171.     if (!Output->OutputDriverPrivate)
  172.         return RHD_SENSED_NONE;
  173.  
  174.     switch (Output->Id) {
  175.         case RHD_OUTPUT_DACA:
  176.             RHDDebug(Output->scrnIndex, "Sensing DACA on Output %s\n",Output->Name);
  177.             DAC = atomDACA;
  178.             break;
  179.         case RHD_OUTPUT_DACB:
  180.             RHDDebug(Output->scrnIndex, "Sensing DACB on Output %s\n",Output->Name);
  181.             DAC = atomDACB;
  182.             break;
  183.         default:
  184.             return FALSE;
  185.     }
  186.  
  187.     switch (Connector->Type) {
  188.         case RHD_CONNECTOR_DVI:
  189.         case RHD_CONNECTOR_DVI_SINGLE:
  190.         case RHD_CONNECTOR_VGA:
  191.             TV = FALSE;
  192.             break;
  193.         default:
  194.             TV = TRUE;
  195.     }
  196.  
  197.     while ((Device = Output->OutputDriverPrivate->OutputDevices[i++].DeviceId) != atomNone) {
  198.         switch (Device) {
  199.             case atomCRT1:
  200.             case atomCRT2:
  201.                 if (TV)
  202.                     continue;
  203.                 break;
  204.             case atomTV1:
  205.             case atomTV2:
  206.             case atomCV:
  207.                 if (!TV)
  208.                     continue;
  209.                 break;
  210.             default: /* should not get here */
  211.                 return RHD_SENSED_NONE;
  212.         }
  213.  
  214.         ret = AtomDACLoadDetection(rhdPtr->atomBIOS, Device, DAC);
  215.  
  216.         if (!ret)
  217.             continue;
  218.  
  219.         if ((retVal =  rhdAtomBIOSScratchDACSenseResults(Output, DAC, Device)) != RHD_SENSED_NONE)
  220.             return retVal;
  221.     }
  222.     return RHD_SENSED_NONE;
  223. }
  224. # endif /* ATOM_BIOS_PARSER */
  225. /*
  226.  *
  227.  */
  228. static void
  229. rhdAtomBIOSScratchUpdateAttachedState(RHDPtr rhdPtr, enum atomDevice dev, Bool attached)
  230. {
  231.     CARD32 BIOS_0;
  232.     CARD32 Addr;
  233.     CARD32 Mask;
  234.  
  235.     RHDFUNC(rhdPtr);
  236.  
  237.     if (rhdPtr->ChipSet < RHD_R600)
  238.         Addr = 0x10;
  239.     else
  240.         Addr = 0x1724;
  241.  
  242.     BIOS_0 = RHDRegRead(rhdPtr, Addr);
  243.  
  244.     switch (dev) {
  245.         case atomDFP1:
  246.             Mask = ATOM_S0_DFP1;
  247.             break;
  248.         case atomDFP2:
  249.             Mask = ATOM_S0_DFP2;
  250.             break;
  251.         case atomLCD1:
  252.             Mask = ATOM_S0_LCD1;
  253.             break;
  254.         case atomLCD2:
  255.             Mask = ATOM_S0_LCD2;
  256.             break;
  257.         case atomTV2:
  258.             Mask = ATOM_S0_TV2;
  259.             break;
  260.         case atomDFP3:
  261.             Mask = ATOM_S0_DFP3;
  262.             break;
  263.         case atomDFP4:
  264.             Mask = ATOM_S0_DFP4;
  265.             break;
  266.         case atomDFP5:
  267.             Mask = ATOM_S0_DFP5;
  268.             break;
  269.         default:
  270.             return;
  271.     }
  272.     if (attached)
  273.         BIOS_0 |= Mask;
  274.     else
  275.         BIOS_0 &= ~Mask;
  276.  
  277.     RHDRegWrite(rhdPtr, Addr, BIOS_0);
  278. }
  279.  
  280. /*
  281.  *
  282.  */
  283. static void
  284. rhdAtomBIOSScratchUpdateOnState(RHDPtr rhdPtr, enum atomDevice dev, Bool on)
  285. {
  286.     CARD32 BIOS_3;
  287.     CARD32 Addr;
  288.     CARD32 Mask = 0;
  289.  
  290.     RHDFUNC(rhdPtr);
  291.  
  292.     if (rhdPtr->ChipSet < RHD_R600)
  293.         Addr = 0x1C;
  294.     else
  295.         Addr = 0x1730;
  296.  
  297.     BIOS_3 = RHDRegRead(rhdPtr, Addr);
  298.  
  299.     switch (dev) {
  300.         case atomCRT1:
  301.             Mask = ATOM_S3_CRT1_ACTIVE;
  302.             break;
  303.         case atomLCD1:
  304.             Mask = ATOM_S3_LCD1_ACTIVE;
  305.             break;
  306.         case atomTV1:
  307.             Mask = ATOM_S3_TV1_ACTIVE;
  308.             break;
  309.         case atomDFP1:
  310.             Mask =  ATOM_S3_DFP1_ACTIVE;
  311.             break;
  312.         case atomCRT2:
  313.             Mask = ATOM_S3_CRT2_ACTIVE;
  314.             break;
  315.         case atomLCD2:
  316.             Mask = ATOM_S3_LCD2_ACTIVE;
  317.             break;
  318.         case atomTV2:
  319.             Mask = ATOM_S3_TV2_ACTIVE;
  320.             break;
  321.         case atomDFP2:
  322.             Mask = ATOM_S3_DFP2_ACTIVE;
  323.             break;
  324.         case  atomCV:
  325.             Mask = ATOM_S3_CV_ACTIVE;
  326.             break;
  327.         case atomDFP3:
  328.             Mask = ATOM_S3_DFP3_ACTIVE;
  329.             break;
  330.         case atomDFP4:
  331.             Mask = ATOM_S3_DFP4_ACTIVE;
  332.             break;
  333.         case atomDFP5:
  334.             Mask = ATOM_S3_DFP5_ACTIVE;
  335.             break;
  336.         case atomNone:
  337.             return;
  338.     }
  339.     if (on)
  340.         BIOS_3 |= Mask;
  341.     else
  342.         BIOS_3 &= ~Mask;
  343.  
  344.     RHDRegWrite(rhdPtr, Addr, BIOS_3);
  345. }
  346.  
  347. /*
  348.  *
  349.  */
  350. void
  351. RHDAtomBIOSScratchSetAccelratorMode(RHDPtr rhdPtr, Bool on)
  352. {
  353.     CARD32 Addr;
  354.     CARD32 Mask = ATOM_S6_ACC_MODE | ATOM_S6_ACC_BLOCK_DISPLAY_SWITCH;
  355.  
  356.     if (rhdPtr->ChipSet < RHD_R600)
  357.         Addr = 0x10 + (6 << 2);
  358.     else
  359.         Addr = 0x1724 + (6 << 2);
  360.  
  361.     RHDRegMask(rhdPtr, Addr, on ? Mask : 0, Mask);
  362. }
  363.  
  364. /*
  365.  *
  366.  */
  367. static void
  368. rhdAtomBIOSScratchSetAcceleratorModeForDevice(RHDPtr rhdPtr,
  369.                                               enum atomDevice Device, Bool on)
  370. {
  371.     CARD32 Addr;
  372.     CARD32 Mask = 0;
  373.  
  374.     if (rhdPtr->ChipSet < RHD_R600)
  375.         Addr = 0x10 + (6 << 2);
  376.     else
  377.         Addr = 0x1724 + (6 << 2);
  378.  
  379.     switch (Device) {
  380.         case atomCRT1:
  381.             Mask = ATOM_S6_ACC_REQ_CRT1;
  382.             break;
  383.         case atomLCD1:
  384.             Mask = ATOM_S6_ACC_REQ_LCD1;
  385.             break;
  386.         case atomTV1:
  387.             Mask = ATOM_S6_ACC_REQ_TV1;
  388.             break;
  389.         case atomDFP1:
  390.             Mask = ATOM_S6_ACC_REQ_DFP1;
  391.             break;
  392.         case atomCRT2:
  393.             Mask = ATOM_S6_ACC_REQ_CRT2;
  394.             break;
  395.         case atomLCD2:
  396.             Mask = ATOM_S6_ACC_REQ_LCD2;
  397.             break;
  398.         case atomTV2:
  399.             Mask = ATOM_S6_ACC_REQ_TV2;
  400.             break;
  401.         case atomDFP2:
  402.             Mask = ATOM_S6_ACC_REQ_DFP2;
  403.             break;
  404.         case  atomCV:
  405.             Mask = ATOM_S6_ACC_REQ_CV;
  406.             break;
  407.         case atomDFP3:
  408.             Mask = ATOM_S6_ACC_REQ_DFP3;
  409.             break;
  410.         case atomDFP4:
  411.             Mask = ATOM_S6_ACC_REQ_DFP4;
  412.             break;
  413.         case atomDFP5:
  414.             Mask = ATOM_S6_ACC_REQ_DFP5;
  415.             break;
  416.         case atomNone:
  417.             return;
  418.     }
  419.     RHDRegMask(rhdPtr, Addr, on ? Mask : 0, Mask);
  420. }
  421.  
  422. /*
  423.  *
  424.  */
  425. static void
  426. rhdAtomBIOSScratchSetCrtcState(RHDPtr rhdPtr, enum atomDevice dev, enum atomCrtc Crtc)
  427. {
  428.     CARD32 BIOS_3;
  429.     CARD32 Addr;
  430.     CARD32 Mask = 0;
  431.  
  432.     RHDFUNC(rhdPtr);
  433.  
  434.     if (rhdPtr->ChipSet < RHD_R600)
  435.         Addr = 0x1C;
  436.     else
  437.         Addr = 0x1730;
  438.  
  439.     BIOS_3 = RHDRegRead(rhdPtr, Addr);
  440.  
  441.     switch (dev) {
  442.         case atomCRT1:
  443.             Mask = ATOM_S3_CRT1_CRTC_ACTIVE;
  444.             break;
  445.         case atomLCD1:
  446.             Mask = ATOM_S3_LCD1_CRTC_ACTIVE;
  447.             break;
  448.         case atomTV1:
  449.             Mask = ATOM_S3_TV1_CRTC_ACTIVE;
  450.             break;
  451.         case atomDFP1:
  452.             Mask =  ATOM_S3_DFP1_CRTC_ACTIVE;
  453.             break;
  454.         case atomCRT2:
  455.             Mask = ATOM_S3_CRT2_CRTC_ACTIVE;
  456.             break;
  457.         case atomLCD2:
  458.             Mask = ATOM_S3_LCD2_CRTC_ACTIVE;
  459.             break;
  460.         case atomTV2:
  461.             Mask = ATOM_S3_TV2_CRTC_ACTIVE;
  462.             break;
  463.         case atomDFP2:
  464.             Mask = ATOM_S3_DFP2_CRTC_ACTIVE;
  465.             break;
  466.         case  atomCV:
  467.             Mask = ATOM_S3_CV_CRTC_ACTIVE;
  468.             break;
  469.         case atomDFP3:
  470.             Mask = ATOM_S3_DFP3_CRTC_ACTIVE;
  471.             break;
  472.         case atomDFP4:
  473.             Mask = ATOM_S3_DFP4_CRTC_ACTIVE;
  474.             break;
  475.         case atomDFP5:
  476.             Mask = ATOM_S3_DFP5_CRTC_ACTIVE;
  477.             break;
  478.         case atomNone:
  479.             return;
  480.     }
  481.     if (Crtc == atomCrtc2)
  482.         BIOS_3 |= Mask;
  483.     else
  484.         BIOS_3 &= ~Mask;
  485.  
  486.     RHDRegWrite(rhdPtr, Addr, BIOS_3);
  487. }
  488.  
  489. /*
  490.  *
  491.  */
  492. void
  493. RHDAtomBIOSScratchPMState(RHDPtr rhdPtr, struct rhdOutput *Output, int PowerManagementMode)
  494. {
  495.     CARD32 Addr;
  496.     CARD32 Mask = 0, Mask1;
  497.     enum atomDevice Device = Output->OutputDriverPrivate->Device;
  498.  
  499.     if (rhdPtr->ChipSet < RHD_R600)
  500.         Addr = 0x10 + (2 << 2);
  501.     else
  502.         Addr = 0x1724 + (2 << 2);
  503.  
  504.     switch (Device) {
  505.         case atomCRT1:
  506.             Mask = ATOM_S2_CRT1_DPMS_STATE;
  507.             break;
  508.         case atomLCD1:
  509.             Mask = ATOM_S2_LCD1_DPMS_STATE;
  510.             break;
  511.         case atomTV1:
  512.             Mask = ATOM_S2_TV1_DPMS_STATE;
  513.             break;
  514.         case atomDFP1:
  515.             Mask = ATOM_S2_DFP1_DPMS_STATE;
  516.             break;
  517.         case atomCRT2:
  518.             Mask = ATOM_S2_CRT2_DPMS_STATE;
  519.             break;
  520.         case atomLCD2:
  521.             Mask = ATOM_S2_LCD2_DPMS_STATE;
  522.             break;
  523.         case atomTV2:
  524.             Mask = ATOM_S2_TV2_DPMS_STATE;
  525.             break;
  526.         case atomDFP2:
  527.             Mask = ATOM_S2_DFP2_DPMS_STATE;
  528.             break;
  529.         case  atomCV:
  530.             Mask = ATOM_S2_CV_DPMS_STATE;
  531.             break;
  532.         case atomDFP3:
  533.             Mask = ATOM_S2_DFP3_DPMS_STATE;
  534.             break;
  535.         case atomDFP4:
  536.             Mask = ATOM_S2_DFP4_DPMS_STATE;
  537.             break;
  538.         case atomDFP5:
  539.             Mask = ATOM_S2_DFP5_DPMS_STATE;
  540.             break;
  541.         case atomNone:
  542.             return;
  543.     }
  544.     switch (PowerManagementMode) {
  545.         case DPMSModeOn:
  546.             Mask1 = 0;
  547.             break;
  548.         case DPMSModeStandby:
  549.         case DPMSModeSuspend:
  550.         case DPMSModeOff:
  551.         default:
  552.             Mask1 = Mask;
  553.             break;
  554.     }
  555.  
  556.     RHDRegMask(rhdPtr, Addr, Mask1, Mask);
  557. }
  558.  
  559. /*
  560.  *
  561.  */
  562. void
  563. RHDAtomBIOSScratchBlLevel(RHDPtr rhdPtr, enum rhdBIOSScratchBlAction action, int *val)
  564. {
  565.     CARD32 Addr;
  566.  
  567.     RHDFUNC(rhdPtr);
  568.  
  569.     if (rhdPtr->ChipSet < RHD_R600)
  570.         Addr = 0x18;
  571.     else
  572.         Addr = 0x172C;
  573.  
  574.     switch (action) {
  575.         case rhdBIOSScratchBlGet:
  576.             *val = (RHDRegRead(rhdPtr, Addr) >> 8) & 0xFF;
  577.             RHDDebug(rhdPtr->scrnIndex, "Get BL level: 0x%x\n",*val);
  578.             break;
  579.         case rhdBIOSScratchBlSet:
  580.             RHDDebug(rhdPtr->scrnIndex, "Set BL level: 0x%x\n",*val);
  581.             RHDRegMask(rhdPtr, Addr, (*val) << 8, 0xFF00);
  582.             break;
  583.     }
  584. }
  585.  
  586. /*
  587.  * This function finds the AtomBIOS device ID of the device that we currently
  588.  * want to drive with a specific output. It contains a logic to deal with CRTC vs. TV
  589.  * on DACs.
  590.  * This function preferrably gets called from within the function that also updates
  591.  * the BIOS scratch registers.
  592.  */
  593. static enum atomDevice
  594. rhdBIOSScratchSetDeviceForOutput(struct rhdOutput *Output)
  595. {
  596.     int i = 0;
  597.  
  598.     RHDFUNC(Output);
  599.  
  600.     if (!Output->Connector) {
  601.         RHDDebug(Output->scrnIndex,"%s: No connector assigned to output %s\n",__func__,Output->Name);
  602.         return atomNone;
  603.     }
  604.  
  605.     if (!Output->OutputDriverPrivate) {
  606.         RHDDebug(Output->scrnIndex,"%s: Output %s has no DriverPrivate\n",__func__,Output->Name);
  607.         return atomNone;
  608.     }
  609.  
  610.     while (Output->OutputDriverPrivate->OutputDevices[i].DeviceId != atomNone) {
  611.         if (Output->OutputDriverPrivate->OutputDevices[i].ConnectorType == Output->Connector->Type){
  612.  
  613.             switch (Output->OutputDriverPrivate->OutputDevices[i].DeviceId) {
  614.                 case atomCrtc1:
  615.                 case atomCrtc2:
  616.                     if (Output->SensedType == RHD_SENSED_VGA
  617.                         || Output->SensedType == RHD_SENSED_NONE) /* if nothing was sensed default to VGA */
  618.                         break;
  619.                     i++;
  620.                     continue;
  621.                 case atomTV1:
  622.                 case atomTV2:
  623.                     if (Output->SensedType == RHD_SENSED_TV_SVIDEO
  624.                         || Output->SensedType == RHD_SENSED_TV_COMPOSITE)
  625.                         break;
  626.                     i++;
  627.                     continue;
  628.                 case atomCV:
  629.                     if (Output->SensedType == RHD_SENSED_TV_COMPONENT)
  630.                         break;
  631.                     i++;
  632.                     continue;
  633.                 default:
  634.                     break;
  635.             }
  636.             Output->OutputDriverPrivate->Device = Output->OutputDriverPrivate->OutputDevices[i].DeviceId;
  637.  
  638.             return Output->OutputDriverPrivate->Device;
  639.         }
  640.         i++;
  641.     }
  642.     RHDDebugVerb(Output->scrnIndex,1,"%s: No device found: ConnectorType: %2.2x SensedType: %2.2x\n",
  643.              __func__, Output->Connector->Type, Output->SensedType);
  644.     return atomNone;
  645. }
  646.  
  647. /*
  648.  * This function is public as it is used from within other outputs, too.
  649.  */
  650. static enum atomDevice
  651. rhdBIOSScratchUpdateBIOSScratchForOutput(struct rhdOutput *Output)
  652. {
  653.     RHDPtr rhdPtr = RHDPTRI(Output);
  654.     struct rhdOutputDevices *devList;
  655.     enum atomDevice Device;
  656.     int i = 0;
  657.  
  658.     RHDFUNC(Output);
  659.  
  660.     if (!Output->OutputDriverPrivate) {
  661.         RHDDebug(Output->scrnIndex,"%s: no output driver private present\n",__func__);
  662.         return atomNone;
  663.     }
  664.     devList = Output->OutputDriverPrivate->OutputDevices;
  665.  
  666.     if (Output->Connector) {
  667.         /* connected - enable */
  668.         Device = rhdBIOSScratchSetDeviceForOutput(Output);
  669.  
  670.     if (Device == atomNone && rhdPtr->Card->ConnectorInfo[0].Type != RHD_CONNECTOR_NONE) {
  671.         xf86DrvMsg(Output->scrnIndex, X_WARNING, "%s: AtomBIOS DeviceID unknown\n",__func__);
  672.         return Device;
  673.     }
  674.  
  675.         ASSERT(Device != atomNone);
  676.  
  677.         if (Output->Crtc)
  678.             rhdAtomBIOSScratchSetCrtcState(rhdPtr, Device,
  679.                                            Output->Crtc->Id == 1 ? atomCrtc2 : atomCrtc1);
  680.         rhdAtomBIOSScratchUpdateOnState(rhdPtr, Device, Output->Active);
  681.         rhdAtomBIOSScratchSetAcceleratorModeForDevice(rhdPtr, Device, Output->Active);
  682.         rhdAtomBIOSScratchUpdateAttachedState(rhdPtr, Device, TRUE);
  683.  
  684.         while (devList[i].DeviceId != atomNone) {
  685.             if (devList[i].DeviceId != Device)
  686.                 rhdAtomBIOSScratchUpdateOnState(rhdPtr, devList[i].DeviceId, FALSE);
  687.                 i++;
  688.         }
  689.  
  690.     } else {
  691.         /* not connected - just disable everything */
  692.         Device = atomNone;
  693.         Output->OutputDriverPrivate->Device = Device;
  694.  
  695.         while (devList[i].DeviceId != atomNone) {
  696.             rhdAtomBIOSScratchUpdateOnState(rhdPtr, devList[i].DeviceId, FALSE);
  697.             rhdAtomBIOSScratchSetAcceleratorModeForDevice(rhdPtr,
  698.                                                           devList[i].DeviceId, FALSE);
  699.             rhdAtomBIOSScratchUpdateAttachedState(rhdPtr, devList[i].DeviceId, FALSE);
  700.             i++;
  701.         }
  702.     }
  703.  
  704.     return Device;
  705. }
  706.  
  707. /*
  708.  *
  709.  */
  710. static void
  711. rhdBIOSScratchPower(struct rhdOutput *Output, int Power)
  712. {
  713.     rhdBIOSScratchUpdateBIOSScratchForOutput(Output);
  714.     Output->OutputDriverPrivate->Power(Output, Power);
  715. }
  716.  
  717. /*
  718.  *
  719.  */
  720. static void
  721. rhdBIOSScratchMode(struct rhdOutput *Output, DisplayModePtr Mode)
  722. {
  723.     rhdBIOSScratchUpdateBIOSScratchForOutput(Output);
  724.     Output->OutputDriverPrivate->Mode(Output, Mode);
  725. }
  726.  
  727. /*
  728.  * This destroys the privates again. It is implemented as an output destroy wrapper.
  729.  */
  730. static void
  731. rhdBIOSScratchDestroyOutputDriverPrivate(struct rhdOutput *Output)
  732. {
  733.     RHDFUNC(Output);
  734.  
  735.     if (Output->OutputDriverPrivate) {
  736.         void (*Destroy) (struct rhdOutput *Output) = Output->OutputDriverPrivate->Destroy;
  737.  
  738.         xfree(Output->OutputDriverPrivate->OutputDevices);
  739.         xfree(Output->OutputDriverPrivate);
  740.         Output->OutputDriverPrivate = NULL;
  741.         if (Destroy)
  742.             Destroy(Output);
  743.     }
  744. }
  745.  
  746. /*
  747.  * This sets up the AtomBIOS driver output private.
  748.  * It allocates the data structure and sets up the list of devices
  749.  * including the connector they are associated with.
  750.  */
  751. Bool
  752. RHDAtomSetupOutputDriverPrivate(struct rhdAtomOutputDeviceList *Devices, struct rhdOutput *Output)
  753. {
  754.     struct rhdOutputDevices *od = NULL;
  755.     struct BIOSScratchOutputPrivate *OutputDriverPrivate;
  756.     int i = 0, cnt = 0;
  757.  
  758.     RHDFUNC(Output);
  759.  
  760.     if (!Devices) {
  761.         RHDDebug(Output->scrnIndex, "%s: Device list doesn't exist.\n");
  762.         return FALSE;
  763.     }
  764.  
  765.     RHDDebugVerb(Output->scrnIndex, 1, " Output: %s[0x%2.2x] - adding devices:\n", Output->Name, Output->Id);
  766.  
  767.     while (Devices[i].DeviceId != atomNone) {
  768.         RHDDebugVerb(Output->scrnIndex,1," Looking at DeviceID: 0x%2.2x OutputType: 0x%2.2x ConnectorType: 0x%2.2x\n",
  769.                      Devices[i].DeviceId,Devices[i].OutputType,Devices[i].ConnectorType);
  770.         if (Devices[i].OutputType == Output->Id) {
  771.             if (!(od = (struct rhdOutputDevices *)xrealloc(od, sizeof(struct rhdOutputDevices) * (cnt + 1))))
  772.                 return FALSE;
  773.             RHDDebugVerb(Output->scrnIndex,1,"  >> 0x%2.2x\n", Devices[i].DeviceId);
  774.             od[cnt].DeviceId = Devices[i].DeviceId;
  775.             od[cnt].ConnectorType = Devices[i].ConnectorType;
  776.             cnt++;
  777.         }
  778.         i++;
  779.     }
  780.     if (!(od = (struct rhdOutputDevices *)xrealloc(od, sizeof(struct rhdOutputDevices) * (cnt + 1))))
  781.         return FALSE;
  782.     od[cnt].DeviceId = atomNone;
  783.  
  784.     if (!(OutputDriverPrivate = (struct BIOSScratchOutputPrivate *)xalloc(sizeof(struct BIOSScratchOutputPrivate)))) {
  785.         xfree(od);
  786.         return FALSE;
  787.     }
  788.     OutputDriverPrivate->OutputDevices = od;
  789.     OutputDriverPrivate->Destroy = Output->Destroy;
  790.     Output->Destroy = rhdBIOSScratchDestroyOutputDriverPrivate;
  791.     OutputDriverPrivate->Power = Output->Power;
  792.     Output->Power = rhdBIOSScratchPower;
  793.     OutputDriverPrivate->Mode = Output->Mode;
  794.     Output->Mode = rhdBIOSScratchMode;
  795.     Output->OutputDriverPrivate = OutputDriverPrivate;
  796.  
  797.     return TRUE;
  798. }
  799.  
  800. /*
  801.  * Find the connector and output type for a specific atom device.
  802.  * This information is kept in the output lists.
  803.  */
  804. Bool
  805. RHDFindConnectorAndOutputTypesForDevice(RHDPtr rhdPtr, enum atomDevice Device, enum rhdOutputType *ot, enum rhdConnectorType *ct)
  806. {
  807.     struct rhdOutput *Output;
  808.  
  809.     *ot = RHD_OUTPUT_NONE;
  810.     *ct = RHD_CONNECTOR_NONE;
  811.  
  812.     for (Output = rhdPtr->Outputs; Output; Output = Output->Next) {
  813.         struct rhdOutputDevices *DeviceList;
  814.         int i = 0;
  815.  
  816.         if (!Output->OutputDriverPrivate)
  817.             continue;
  818.  
  819.         DeviceList = Output->OutputDriverPrivate->OutputDevices;
  820.         while (DeviceList[i].DeviceId != atomNone) {
  821.             if (DeviceList[i].DeviceId == Device) {
  822.                 *ot = Output->Id;
  823.                 *ct = DeviceList[i].ConnectorType;
  824.                 return TRUE;
  825.             }
  826.             i++;
  827.         }
  828.     }
  829.  
  830.     return FALSE;
  831. }
  832.  
  833. /*
  834.  *
  835.  */
  836. enum atomDevice
  837. RHDGetDeviceOnCrtc(RHDPtr rhdPtr, enum atomCrtc Crtc)
  838. {
  839.     CARD32 BIOS_3;
  840.     CARD32 Addr;
  841.     CARD32 Mask = 0;
  842.  
  843.     RHDFUNC(rhdPtr);
  844.  
  845.     if (rhdPtr->ChipSet < RHD_R600)
  846.         Addr = 0x1C;
  847.     else
  848.         Addr = 0x1730;
  849.  
  850.     if (Crtc == atomCrtc1)
  851.         Mask = ~Mask;
  852.  
  853.     BIOS_3 = RHDRegRead(rhdPtr, Addr);
  854.     RHDDebug(rhdPtr->scrnIndex, "%s: BIOS_3 = 0x%x\n",__func__,BIOS_3);
  855.  
  856.     if (BIOS_3 & ATOM_S3_CRT1_ACTIVE
  857.         && ((BIOS_3 ^ Mask) & ATOM_S3_CRT1_CRTC_ACTIVE))
  858.         return atomCRT1;
  859.     else if (BIOS_3 & ATOM_S3_LCD1_ACTIVE
  860.              && ((BIOS_3 ^ Mask) & ATOM_S3_LCD1_CRTC_ACTIVE))
  861.         return atomLCD1;
  862.     else if (BIOS_3 & ATOM_S3_DFP1_ACTIVE
  863.              && ((BIOS_3 ^ Mask) & ATOM_S3_DFP1_CRTC_ACTIVE))
  864.         return atomDFP1;
  865.     else if (BIOS_3 & ATOM_S3_CRT2_ACTIVE
  866.              && ((BIOS_3 ^ Mask) & ATOM_S3_CRT2_CRTC_ACTIVE))
  867.         return atomCRT2;
  868.     else if (BIOS_3 & ATOM_S3_LCD2_ACTIVE
  869.              && ((BIOS_3 ^ Mask) & ATOM_S3_LCD2_CRTC_ACTIVE))
  870.         return atomLCD2;
  871.     else if (BIOS_3 & ATOM_S3_TV2_ACTIVE
  872.              && ((BIOS_3 ^ Mask) & ATOM_S3_TV2_CRTC_ACTIVE))
  873.         return atomTV2;
  874.     else if (BIOS_3 & ATOM_S3_DFP2_ACTIVE
  875.              && ((BIOS_3 ^ Mask) & ATOM_S3_DFP2_CRTC_ACTIVE))
  876.         return atomDFP2;
  877.     else if (BIOS_3 & ATOM_S3_CV_ACTIVE
  878.              && ((BIOS_3 ^ Mask) & ATOM_S3_CV_CRTC_ACTIVE))
  879.         return atomCV;
  880.     else if (BIOS_3 & ATOM_S3_DFP3_ACTIVE
  881.              && ((BIOS_3 ^ Mask) & ATOM_S3_DFP3_CRTC_ACTIVE))
  882.         return atomDFP3;
  883.     else if (BIOS_3 & ATOM_S3_DFP4_ACTIVE
  884.              && ((BIOS_3 ^ Mask) & ATOM_S3_DFP4_CRTC_ACTIVE))
  885.         return atomDFP4;
  886.     else if (BIOS_3 & ATOM_S3_DFP5_ACTIVE
  887.              && ((BIOS_3 ^ Mask) & ATOM_S3_DFP5_CRTC_ACTIVE))
  888.         return atomDFP5;
  889.     else
  890.         return atomNone;
  891. }
  892.  
  893. struct rhdBiosScratchRegisters {
  894.     CARD32 Scratch0;
  895.     CARD32 Scratch2;
  896.     CARD32 Scratch3;
  897.     CARD32 Scratch6;
  898. };
  899.  
  900. struct rhdBiosScratchRegisters *
  901. RHDSaveBiosScratchRegisters(RHDPtr rhdPtr)
  902. {
  903.     struct rhdBiosScratchRegisters *regs;
  904.     CARD32 S0Addr, S2Addr, S3Addr, S6Addr;
  905.  
  906.     RHDFUNC(rhdPtr);
  907.  
  908.     if (!(regs = (struct rhdBiosScratchRegisters *)xalloc(sizeof(struct rhdBiosScratchRegisters))))
  909.         return NULL;
  910.  
  911.     if (rhdPtr->ChipSet < RHD_R600) {
  912.         S0Addr = 0x10;
  913.         S2Addr = 0x18;
  914.         S3Addr = 0x1C;
  915.         S6Addr = 0x10 + (6 << 2);
  916.     } else {
  917.         S0Addr = 0x1724;
  918.         S2Addr = 0x172C;
  919.         S3Addr = 0x1730;
  920.         S6Addr = 0x1724 + (6 << 2);
  921.     }
  922.     regs->Scratch0 = RHDRegRead(rhdPtr, S0Addr);
  923.     regs->Scratch2 = RHDRegRead(rhdPtr, S2Addr);
  924.     regs->Scratch3 = RHDRegRead(rhdPtr, S3Addr);
  925.     regs->Scratch6 = RHDRegRead(rhdPtr, S6Addr);
  926.  
  927.     return regs;
  928. }
  929.  
  930. void
  931. RHDRestoreBiosScratchRegisters(RHDPtr rhdPtr, struct rhdBiosScratchRegisters *regs)
  932. {
  933.     CARD32 S0Addr, S2Addr, S3Addr, S6Addr;
  934.  
  935.     RHDFUNC(rhdPtr);
  936.  
  937.     if (!regs)
  938.         return;
  939.  
  940.     if (rhdPtr->ChipSet < RHD_R600) {
  941.         S0Addr = 0x10;
  942.         S2Addr = 0x18;
  943.         S3Addr = 0x1C;
  944.         S6Addr = 0x10 + (6 << 2);
  945.     } else {
  946.         S0Addr = 0x1724;
  947.         S2Addr = 0x172C;
  948.         S3Addr = 0x1730;
  949.         S6Addr = 0x1724 + (6 << 2);
  950.     }
  951.     RHDRegWrite(rhdPtr, S0Addr, regs->Scratch0);
  952.     RHDRegWrite(rhdPtr, S2Addr, regs->Scratch2);
  953.     RHDRegWrite(rhdPtr, S3Addr, regs->Scratch3);
  954.     RHDRegWrite(rhdPtr, S6Addr, regs->Scratch6);
  955.  
  956.     xfree(regs);
  957. }
  958.  
  959. #endif /* ATOM_BIOS */
  960.  
  961.