[haiku-commits] haiku: hrev44488 - src/add-ons/accelerants/radeon_hd

  • From: kallisti5@xxxxxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Tue, 7 Aug 2012 15:54:02 +0200 (CEST)

hrev44488 adds 1 changeset to branch 'master'
old head: 5f44fcce9fb1c01b24c6d828acb214f1610985f0
new head: 63624e404b5eb6fc11a503331e67ce29af074021

----------------------------------------------------------------------------

63624e4: radeon_hd: reorganize some pll code
  
  * Move DisplayPort external pixel clock out of pll
    as this frequency is card-wide.
  * Add new function to pull display clock frequency
    and other card-wide settings.
  * Set displayDefault frequency card-wide
  * My DisplayPort LVDS bridge laptop now kind of works
    (a clock somewhere seems a little off though)

                          [ Alexander von Gluck IV <kallisti5@xxxxxxxxxxx> ]

----------------------------------------------------------------------------

Revision:    hrev44488
Commit:      63624e404b5eb6fc11a503331e67ce29af074021
URL:         http://cgit.haiku-os.org/haiku/commit/?id=63624e4
Author:      Alexander von Gluck IV <kallisti5@xxxxxxxxxxx>
Date:        Tue Aug  7 13:53:34 2012 UTC

----------------------------------------------------------------------------

7 files changed, 153 insertions(+), 14 deletions(-)
src/add-ons/accelerants/radeon_hd/accelerant.cpp |    6 ++
src/add-ons/accelerants/radeon_hd/accelerant.h   |    4 +
src/add-ons/accelerants/radeon_hd/encoder.cpp    |    4 +-
src/add-ons/accelerants/radeon_hd/gpu.cpp        |   57 +++++++++++
src/add-ons/accelerants/radeon_hd/gpu.h          |    1 +
src/add-ons/accelerants/radeon_hd/pll.cpp        |   90 ++++++++++++++++--
src/add-ons/accelerants/radeon_hd/pll.h          |    5 +-

----------------------------------------------------------------------------

diff --git a/src/add-ons/accelerants/radeon_hd/accelerant.cpp 
b/src/add-ons/accelerants/radeon_hd/accelerant.cpp
index cf6bb2e..fa6b9c4 100644
--- a/src/add-ons/accelerants/radeon_hd/accelerant.cpp
+++ b/src/add-ons/accelerants/radeon_hd/accelerant.cpp
@@ -252,9 +252,15 @@ radeon_init_accelerant(int device)
 
        radeon_init_bios(gInfo->rom);
 
+       // probe firmware information
+       radeon_gpu_probe();
+
        // disable spread spectrum as it requires lots of extra calculations
        radeon_gpu_ss_disable();
 
+       // program external pll clock
+       pll_external_init();
+
        // find GPIO pins from AtomBIOS
        gpio_probe();
 
diff --git a/src/add-ons/accelerants/radeon_hd/accelerant.h 
b/src/add-ons/accelerants/radeon_hd/accelerant.h
index 05aa0b2..6b3d720 100644
--- a/src/add-ons/accelerants/radeon_hd/accelerant.h
+++ b/src/add-ons/accelerants/radeon_hd/accelerant.h
@@ -72,6 +72,10 @@ struct accelerant_info {
 
        volatile uint32 dpms_mode;              // current driver dpms mode
 
+       uint16                  maximumPixelClock;
+       uint32                  displayClockFrequency;
+       uint32                  dpExternalClock;
+
        RingQueue*              ringQueue[RADEON_QUEUE_MAX]; // Ring buffer 
command processor
 };
 
diff --git a/src/add-ons/accelerants/radeon_hd/encoder.cpp 
b/src/add-ons/accelerants/radeon_hd/encoder.cpp
index 9a0d0b4..bccae25 100644
--- a/src/add-ons/accelerants/radeon_hd/encoder.cpp
+++ b/src/add-ons/accelerants/radeon_hd/encoder.cpp
@@ -1351,7 +1351,7 @@ transmitter_dig_setup(uint32 connectorIndex, uint32 
pixelClock,
 
                                        // Select the PLL for the PHY
                                        // DP PHY to be clocked from external 
src if possible
-                                       if (isDP && pll->dpExternalClock) {
+                                       if (isDP && gInfo->dpExternalClock) {
                                                // use external clock source
                                                args.v3.acConfig.ucRefClkSource 
= ATOM_DCPLL;
                                        } else
@@ -1418,7 +1418,7 @@ transmitter_dig_setup(uint32 connectorIndex, uint32 
pixelClock,
                                        // Select the PLL for the PHY
                                        // DP PHY to be clocked from external 
src if possible
                                        if (isDP) {
-                                               if (pll->dpExternalClock > 0) {
+                                               if (gInfo->dpExternalClock > 0) 
{
                                                        
args.v4.acConfig.ucRefClkSource
                                                                = 
ENCODER_REFCLK_SRC_EXTCLK;
                                                } else {
diff --git a/src/add-ons/accelerants/radeon_hd/gpu.cpp 
b/src/add-ons/accelerants/radeon_hd/gpu.cpp
index b835d2e..85c50ca 100644
--- a/src/add-ons/accelerants/radeon_hd/gpu.cpp
+++ b/src/add-ons/accelerants/radeon_hd/gpu.cpp
@@ -14,6 +14,7 @@
 
 #include "accelerant_protos.h"
 #include "accelerant.h"
+#include "atom.h"
 #include "bios.h"
 #include "utility.h"
 
@@ -31,6 +32,62 @@
 
 
 status_t
+radeon_gpu_probe()
+{
+       uint8 tableMajor;
+       uint8 tableMinor;
+       uint16 tableOffset;
+
+       gInfo->displayClockFrequency = 0;
+       gInfo->dpExternalClock = 0;
+
+       int index = GetIndexIntoMasterTable(DATA, FirmwareInfo);
+       if (atom_parse_data_header(gAtomContext, index, NULL,
+               &tableMajor, &tableMinor, &tableOffset) != B_OK) {
+               ERROR("%s: Couldn't parse data header\n", __func__);
+               return B_ERROR;
+       }
+
+       TRACE("%s: table %" B_PRIu8 ".%" B_PRIu8 "\n", __func__,
+               tableMajor, tableMinor);
+
+       union atomFirmwareInfo {
+               ATOM_FIRMWARE_INFO info;
+               ATOM_FIRMWARE_INFO_V1_2 info_12;
+               ATOM_FIRMWARE_INFO_V1_3 info_13;
+               ATOM_FIRMWARE_INFO_V1_4 info_14;
+               ATOM_FIRMWARE_INFO_V2_1 info_21;
+               ATOM_FIRMWARE_INFO_V2_2 info_22;
+       };
+       union atomFirmwareInfo* firmwareInfo
+               = (union atomFirmwareInfo*)(gAtomContext->bios + tableOffset);
+
+       radeon_shared_info &info = *gInfo->shared_info;
+
+       if (info.dceMajor >= 4) {
+               gInfo->displayClockFrequency = B_LENDIAN_TO_HOST_INT32(
+                       firmwareInfo->info_21.ulDefaultDispEngineClkFreq);
+               if (gInfo->displayClockFrequency == 0) {
+                       if (info.dceMajor >= 5)
+                               gInfo->displayClockFrequency = 54000;
+                       else
+                               gInfo->displayClockFrequency = 60000;
+               }
+               gInfo->dpExternalClock = B_LENDIAN_TO_HOST_INT16(
+                       firmwareInfo->info_21.usUniphyDPModeExtClkFreq);
+       }
+
+       gInfo->maximumPixelClock = B_LENDIAN_TO_HOST_INT16(
+               firmwareInfo->info.usMaxPixelClock);
+
+       if (gInfo->maximumPixelClock == 0)
+               gInfo->maximumPixelClock = 40000;
+
+       return B_OK;
+}
+
+
+status_t
 radeon_gpu_reset()
 {
        radeon_shared_info &info = *gInfo->shared_info;
diff --git a/src/add-ons/accelerants/radeon_hd/gpu.h 
b/src/add-ons/accelerants/radeon_hd/gpu.h
index d9586c9..f0c0fb6 100644
--- a/src/add-ons/accelerants/radeon_hd/gpu.h
+++ b/src/add-ons/accelerants/radeon_hd/gpu.h
@@ -164,6 +164,7 @@
 #define                SOFT_RESET_IA                   (1 << 15)
 
 
+status_t radeon_gpu_probe();
 status_t radeon_gpu_reset();
 void radeon_gpu_mc_halt(struct gpu_state *gpuState);
 void radeon_gpu_mc_resume(struct gpu_state *gpuState);
diff --git a/src/add-ons/accelerants/radeon_hd/pll.cpp 
b/src/add-ons/accelerants/radeon_hd/pll.cpp
index 3ea2577..79b0cb7 100644
--- a/src/add-ons/accelerants/radeon_hd/pll.cpp
+++ b/src/add-ons/accelerants/radeon_hd/pll.cpp
@@ -38,8 +38,6 @@ extern "C" void _sPrintf(const char* format, ...);
 status_t
 pll_limit_probe(pll_info* pll)
 {
-       radeon_shared_info &info = *gInfo->shared_info;
-
        uint8 tableMajor;
        uint8 tableMinor;
        uint16 tableOffset;
@@ -120,12 +118,6 @@ pll_limit_probe(pll_info* pll)
        pll->pllInMax = B_LENDIAN_TO_HOST_INT16(
                firmwareInfo->info.usMaxPixelClockPLL_Input) * 10;
 
-       if (info.dceMajor >= 4) {
-               pll->dpExternalClock = B_LENDIAN_TO_HOST_INT16(
-                       firmwareInfo->info_21.usUniphyDPModeExtClkFreq);
-       } else
-               pll->dpExternalClock = 0;
-
        TRACE("%s: referenceFreq: %" B_PRIu16 "; pllOutMin: %" B_PRIu16 "; "
                " pllOutMax: %" B_PRIu16 "; pllInMin: %" B_PRIu16 ";"
                "pllInMax: %" B_PRIu16 "\n", __func__, pll->referenceFreq,
@@ -811,6 +803,86 @@ pll_set(display_mode* mode, uint8 crtcID)
 
 
 status_t
+pll_external_set(uint32 clock)
+{
+       TRACE("%s: set external pll clock to %" B_PRIu32 "\n", __func__, clock);
+
+       if (clock == 0)
+               ERROR("%s: Warning: default display clock is 0?\n", __func__);
+
+       // also known as PLL display engineering
+       uint8 tableMajor;
+       uint8 tableMinor;
+
+       int index = GetIndexIntoMasterTable(COMMAND, SetPixelClock);
+       atom_parse_cmd_header(gAtomContext, index, &tableMajor, &tableMinor);
+
+       TRACE("%s: table %" B_PRIu8 ".%" B_PRIu8 "\n", __func__,
+               tableMajor, tableMinor);
+
+       union setPixelClock {
+               SET_PIXEL_CLOCK_PS_ALLOCATION base;
+               PIXEL_CLOCK_PARAMETERS v1;
+               PIXEL_CLOCK_PARAMETERS_V2 v2;
+               PIXEL_CLOCK_PARAMETERS_V3 v3;
+               PIXEL_CLOCK_PARAMETERS_V5 v5;
+               PIXEL_CLOCK_PARAMETERS_V6 v6;
+       };
+       union setPixelClock args;
+       memset(&args, 0, sizeof(args));
+
+       radeon_shared_info &info = *gInfo->shared_info;
+       uint32 dceVersion = (info.dceMajor * 100) + info.dceMinor;
+       switch (tableMajor) {
+               case 1:
+                       switch(tableMinor) {
+                               case 5:
+                                       // If the default DC PLL clock is 
specified,
+                                       // SetPixelClock provides the dividers.
+                                       args.v5.ucCRTC = ATOM_CRTC_INVALID;
+                                       args.v5.usPixelClock = 
B_HOST_TO_LENDIAN_INT16(clock);
+                                       args.v5.ucPpll = ATOM_DCPLL;
+                                       break;
+                               case 6:
+                                       // If the default DC PLL clock is 
specified,
+                                       // SetPixelClock provides the dividers.
+                                       args.v6.ulDispEngClkFreq = 
B_HOST_TO_LENDIAN_INT32(clock);
+                                       if (dceVersion == 601)
+                                               args.v6.ucPpll = ATOM_EXT_PLL1;
+                                       else if (dceVersion >= 600)
+                                               args.v6.ucPpll = ATOM_PPLL0;
+                                       else
+                                               args.v6.ucPpll = ATOM_DCPLL;
+                                       break;
+                               default:
+                                       ERROR("%s: Unknown table version %" 
B_PRIu8
+                                               ".%" B_PRIu8 "\n", __func__, 
tableMajor, tableMinor);
+                       }
+                       break;
+               default:
+                       ERROR("%s: Unknown table version %" B_PRIu8
+                                               ".%" B_PRIu8 "\n", __func__, 
tableMajor, tableMinor);
+       }
+       return B_OK;
+}
+
+
+void
+pll_external_init()
+{
+       radeon_shared_info &info = *gInfo->shared_info;
+
+       if (info.dceMajor >= 6) {
+               pll_external_set(gInfo->displayClockFrequency);
+       } else if (info.dceMajor >= 4) {
+               // TODO: SS enabled? disable
+               pll_external_set(gInfo->displayClockFrequency);
+               // TODO: SS enabled? enable
+       }
+}
+
+
+status_t
 pll_pick(uint32 connectorIndex)
 {
        pll_info* pll = &gConnector[connectorIndex]->encoder.pll;
@@ -837,7 +909,7 @@ pll_pick(uint32 connectorIndex)
                        } else if (info.dceMajor >= 5) {
                                pll->id = ATOM_DCPLL;
                                return B_OK;
-                       } else if (pll->dpExternalClock) {
+                       } else if (gInfo->dpExternalClock) {
                                pll->id = ATOM_PPLL_INVALID;
                                return B_OK;
                        }
diff --git a/src/add-ons/accelerants/radeon_hd/pll.h 
b/src/add-ons/accelerants/radeon_hd/pll.h
index 2be6e97..c04f042 100644
--- a/src/add-ons/accelerants/radeon_hd/pll.h
+++ b/src/add-ons/accelerants/radeon_hd/pll.h
@@ -49,9 +49,6 @@ struct pll_info {
        /* pixel clock to be programmed (kHz)*/
        uint32 pixelClock;
 
-       /* external DisplayPort clock freq */
-       uint32 dpExternalClock;
-
        /* flags for the current clock */
        uint32 flags;
 
@@ -100,6 +97,8 @@ struct pll_info {
 };
 
 
+void pll_external_init();
+status_t pll_external_set(uint32 clock);
 status_t pll_adjust(pll_info* pll, display_mode* mode, uint8 crtcID);
 status_t pll_compute(pll_info* pll);
 void pll_setup_flags(pll_info* pll, uint8 crtcID);


Other related posts:

  • » [haiku-commits] haiku: hrev44488 - src/add-ons/accelerants/radeon_hd - kallisti5