[haiku-commits] haiku: hrev45219 - src/add-ons/accelerants/radeon_hd headers/private/graphics/radeon_hd

  • From: kallisti5@xxxxxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Tue, 29 Jan 2013 20:31:21 +0100 (CET)

hrev45219 adds 2 changesets to branch 'master'
old head: 8317edb3504120db3ddff0c3270a7ae9a55719f6
new head: 00bc40ad588f4bd59cd7574788b5dc111b62198a
overview: http://cgit.haiku-os.org/haiku/log/?qt=range&q=00bc40a+%5E8317edb

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

7d9c1f3: radeon_hd: Add Northern Island registers

                                          [ Bill Randle <billr@xxxxxxxxxx> ]

00bc40a: radeon_hd: Fix DisplayPort link training
  
  * Original changes by Bill Randle
  * Includes a large number of modifications
    and cleanups.
  * Add a "currentMode" to the gDisplay to
    enable easier checking of intended changes.
    (we pass the display_mode around quite a
     bit, adding a "currentMode" allows code
     to know the intended display mode being set
     without passing the mode pointer around as
     much)

                          [ Alexander von Gluck IV <kallisti5@xxxxxxxxxxx> ]

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

14 files changed, 409 insertions(+), 102 deletions(-)
headers/private/graphics/radeon_hd/avivo_reg.h   |   4 +-
headers/private/graphics/radeon_hd/ni_reg.h      |  86 ++++++++
headers/private/graphics/radeon_hd/radeon_hd.h   |   3 +
src/add-ons/accelerants/radeon_hd/accelerant.h   |   1 +
src/add-ons/accelerants/radeon_hd/display.cpp    | 209 +++++++++++++++++--
src/add-ons/accelerants/radeon_hd/display.h      |   2 +
.../accelerants/radeon_hd/displayport.cpp        |  53 +++--
src/add-ons/accelerants/radeon_hd/displayport.h  |   7 +-
src/add-ons/accelerants/radeon_hd/encoder.cpp    |  25 ++-
src/add-ons/accelerants/radeon_hd/hooks.cpp      |   2 +-
src/add-ons/accelerants/radeon_hd/mode.cpp       |  64 +++---
src/add-ons/accelerants/radeon_hd/mode.h         |   3 +-
src/add-ons/accelerants/radeon_hd/pll.cpp        |  49 +++--
src/add-ons/accelerants/radeon_hd/pll.h          |   3 +

############################################################################

Commit:      7d9c1f30f19f7d5de848a8d0498b225056db37b3
URL:         http://cgit.haiku-os.org/haiku/commit/?id=7d9c1f3
Author:      Bill Randle <billr@xxxxxxxxxx>
Date:        Tue Jan 29 01:47:41 2013 UTC
Committer:   Alexander von Gluck IV <kallisti5@xxxxxxxxxxx>
Commit-Date: Tue Jan 29 18:29:06 2013 UTC

radeon_hd: Add Northern Island registers

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

diff --git a/headers/private/graphics/radeon_hd/avivo_reg.h 
b/headers/private/graphics/radeon_hd/avivo_reg.h
index 68e14ee..0276617 100644
--- a/headers/private/graphics/radeon_hd/avivo_reg.h
+++ b/headers/private/graphics/radeon_hd/avivo_reg.h
@@ -303,6 +303,8 @@
 
 #define AVIVO_DDIA_BIT_DEPTH_CONTROL                                           
0x7214
 
+#define AVIVO_DP_VID_STREAM_CNTL                                               
        0x770C
+
 #define AVIVO_DACA_ENABLE                                                      
                0x7800
 #define        AVIVO_DAC_ENABLE                                                
                (1 << 0)
 #define AVIVO_DACA_SOURCE_SELECT                                               
        0x7804
@@ -558,4 +560,4 @@
 #define        AVIVO_D2_VBLANK_INTERRUPT                                       
        (1 << 5)
 
 
-#endif /* __AVIVO_REG_H__ */
\ No newline at end of file
+#endif /* __AVIVO_REG_H__ */
diff --git a/headers/private/graphics/radeon_hd/ni_reg.h 
b/headers/private/graphics/radeon_hd/ni_reg.h
new file mode 100644
index 0000000..5db7b7d
--- /dev/null
+++ b/headers/private/graphics/radeon_hd/ni_reg.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2010 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Alex Deucher
+ */
+#ifndef __NI_REG_H__
+#define __NI_REG_H__
+
+/* northern islands - DCE5 */
+
+#define NI_INPUT_GAMMA_CONTROL                         0x6840
+#       define NI_GRPH_INPUT_GAMMA_MODE(x)             (((x) & 0x3) << 0)
+#       define NI_INPUT_GAMMA_USE_LUT                  0
+#       define NI_INPUT_GAMMA_BYPASS                   1
+#       define NI_INPUT_GAMMA_SRGB_24                  2
+#       define NI_INPUT_GAMMA_XVYCC_222                3
+#       define NI_OVL_INPUT_GAMMA_MODE(x)              (((x) & 0x3) << 4)
+
+#define NI_PRESCALE_GRPH_CONTROL                       0x68b4
+#       define NI_GRPH_PRESCALE_BYPASS                 (1 << 4)
+
+#define NI_PRESCALE_OVL_CONTROL                        0x68c4
+#       define NI_OVL_PRESCALE_BYPASS                  (1 << 4)
+
+#define NI_INPUT_CSC_CONTROL                           0x68d4
+#       define NI_INPUT_CSC_GRPH_MODE(x)               (((x) & 0x3) << 0)
+#       define NI_INPUT_CSC_BYPASS                     0
+#       define NI_INPUT_CSC_PROG_COEFF                 1
+#       define NI_INPUT_CSC_PROG_SHARED_MATRIXA        2
+#       define NI_INPUT_CSC_OVL_MODE(x)                (((x) & 0x3) << 4)
+
+#define NI_OUTPUT_CSC_CONTROL                          0x68f0
+#       define NI_OUTPUT_CSC_GRPH_MODE(x)              (((x) & 0x7) << 0)
+#       define NI_OUTPUT_CSC_BYPASS                    0
+#       define NI_OUTPUT_CSC_TV_RGB                    1
+#       define NI_OUTPUT_CSC_YCBCR_601                 2
+#       define NI_OUTPUT_CSC_YCBCR_709                 3
+#       define NI_OUTPUT_CSC_PROG_COEFF                4
+#       define NI_OUTPUT_CSC_PROG_SHARED_MATRIXB       5
+#       define NI_OUTPUT_CSC_OVL_MODE(x)               (((x) & 0x7) << 4)
+
+#define NI_DEGAMMA_CONTROL                             0x6960
+#       define NI_GRPH_DEGAMMA_MODE(x)                 (((x) & 0x3) << 0)
+#       define NI_DEGAMMA_BYPASS                       0
+#       define NI_DEGAMMA_SRGB_24                      1
+#       define NI_DEGAMMA_XVYCC_222                    2
+#       define NI_OVL_DEGAMMA_MODE(x)                  (((x) & 0x3) << 4)
+#       define NI_ICON_DEGAMMA_MODE(x)                 (((x) & 0x3) << 8)
+#       define NI_CURSOR_DEGAMMA_MODE(x)               (((x) & 0x3) << 12)
+
+#define NI_GAMUT_REMAP_CONTROL                         0x6964
+#       define NI_GRPH_GAMUT_REMAP_MODE(x)             (((x) & 0x3) << 0)
+#       define NI_GAMUT_REMAP_BYPASS                   0
+#       define NI_GAMUT_REMAP_PROG_COEFF               1
+#       define NI_GAMUT_REMAP_PROG_SHARED_MATRIXA      2
+#       define NI_GAMUT_REMAP_PROG_SHARED_MATRIXB      3
+#       define NI_OVL_GAMUT_REMAP_MODE(x)              (((x) & 0x3) << 4)
+
+#define NI_REGAMMA_CONTROL                             0x6a80
+#       define NI_GRPH_REGAMMA_MODE(x)                 (((x) & 0x7) << 0)
+#       define NI_REGAMMA_BYPASS                       0
+#       define NI_REGAMMA_SRGB_24                      1
+#       define NI_REGAMMA_XVYCC_222                    2
+#       define NI_REGAMMA_PROG_A                       3
+#       define NI_REGAMMA_PROG_B                       4
+#       define NI_OVL_REGAMMA_MODE(x)                  (((x) & 0x7) << 4)
+
+#endif
diff --git a/headers/private/graphics/radeon_hd/radeon_hd.h 
b/headers/private/graphics/radeon_hd/radeon_hd.h
index 952b16e..6ae08f9 100644
--- a/headers/private/graphics/radeon_hd/radeon_hd.h
+++ b/headers/private/graphics/radeon_hd/radeon_hd.h
@@ -20,6 +20,7 @@
 #include "r700_reg.h"
 #include "evergreen_reg.h"
 #include "si_reg.h"
+#include "ni_reg.h"
 
 #include <Accelerant.h>
 #include <Drivers.h>
@@ -170,6 +171,8 @@ struct radeon_shared_info {
        uint32                  chipsetFlags;
        uint8                   dceMajor;
        uint8                   dceMinor;
+
+       uint16                  color_data[3 * 256];    // colour lookup table
 };
 
 //----------------- ioctl() interface ----------------

############################################################################

Revision:    hrev45219
Commit:      00bc40ad588f4bd59cd7574788b5dc111b62198a
URL:         http://cgit.haiku-os.org/haiku/commit/?id=00bc40a
Author:      Alexander von Gluck IV <kallisti5@xxxxxxxxxxx>
Date:        Tue Jan 29 05:26:57 2013 UTC

radeon_hd: Fix DisplayPort link training

* Original changes by Bill Randle
* Includes a large number of modifications
  and cleanups.
* Add a "currentMode" to the gDisplay to
  enable easier checking of intended changes.
  (we pass the display_mode around quite a
   bit, adding a "currentMode" allows code
   to know the intended display mode being set
   without passing the mode pointer around as
   much)

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

diff --git a/src/add-ons/accelerants/radeon_hd/accelerant.h 
b/src/add-ons/accelerants/radeon_hd/accelerant.h
index 4f5379a..29651fa 100644
--- a/src/add-ons/accelerants/radeon_hd/accelerant.h
+++ b/src/add-ons/accelerants/radeon_hd/accelerant.h
@@ -172,6 +172,7 @@ typedef struct {
        uint32                  hfreqMin;
        edid1_info              edidData;
        display_mode    preferredMode;
+       display_mode    currentMode;
 } display_info;
 
 
diff --git a/src/add-ons/accelerants/radeon_hd/display.cpp 
b/src/add-ons/accelerants/radeon_hd/display.cpp
index 7b212ee..3400f08 100644
--- a/src/add-ons/accelerants/radeon_hd/display.cpp
+++ b/src/add-ons/accelerants/radeon_hd/display.cpp
@@ -3,7 +3,8 @@
  * Distributed under the terms of the MIT License.
  *
  * Authors:
- *      Alexander von Gluck, kallisti5@xxxxxxxxxxx
+ *     Alexander von Gluck, kallisti5@xxxxxxxxxxx
+ *     Bill Randle, billr@xxxxxxxxxx
  */
 
 /*
@@ -240,6 +241,29 @@ detect_crt_ranges(uint32 crtid)
 }
 
 
+static void
+remove_dup_displays(uint32 displayIndex, uint32 id)
+{
+       /* hack for both digital and analog interfaces active */
+       if ((displayIndex > 0) && gDisplay[displayIndex]->attached) {
+               if (gConnector[id-1]->encoder.type == VIDEO_ENCODER_TMDS) {
+                       int gpioID1 = gConnector[id-1]->gpioID;
+                       int gpioID2 = gConnector[id]->gpioID;
+                       edid1_info* edid = &gDisplay[displayIndex-1]->edidData;
+
+                       if ((gGPIOInfo[gpioID1]->hwPin == 
gGPIOInfo[gpioID2]->hwPin) &&
+                                       edid->display.input_type)
+                               // give preference to digital display when both 
are present
+                               // and other display indicates it is digital
+                               TRACE("%s: skipping connector %" B_PRIu32
+                                               ": giving preference to digital 
"
+                                               "connector %d\n", __func__, id, 
id-1);
+                               gDisplay[displayIndex]->attached = 0;
+               }
+       }
+}
+
+
 status_t
 detect_displays()
 {
@@ -264,19 +288,18 @@ detect_displays()
                }
 
                if (gConnector[id]->type == VIDEO_CONNECTOR_DP) {
-                       edid1_info* edid = &gDisplay[displayIndex]->edidData;
-
                        TRACE("%s: connector(%" B_PRIu32 "): Checking DP.\n", 
__func__, id);
-                       status_t dpHasEDID = ddc2_dp_read_edid1(id, edid);
+
+                       edid1_info* edid = &gDisplay[displayIndex]->edidData;
                        gDisplay[displayIndex]->attached
-                               = (dpHasEDID == B_OK ? true : false);
+                               = ddc2_dp_read_edid1(id, edid);
+                               
                        if (gDisplay[displayIndex]->attached) {
                                TRACE("%s: connector(%" B_PRIu32 "): Found 
DisplayPort EDID!\n",
                                        __func__);
                        }
                }
-
-               // TODO: As DP aux transactions don't work yet, just use LVDS 
as a hack
+               // TODO: Handle external DP brides - ??
                #if 0
                if (gConnector[id]->encoderExternal.isDPBridge == true) {
                        // If this is a DisplayPort Bridge, setup ddc on bus
@@ -287,11 +310,9 @@ detect_displays()
                        gDisplay[displayIndex]->attached = true;
 
                        // TODO: DDC Router switching for DisplayPort (and 
others?)
-               } else if (gConnector[id]->type == VIDEO_CONNECTOR_LVDS) {
+               }
                #endif
-
-               if (gDisplay[displayIndex]->attached == false
-                       && gConnector[id]->type == VIDEO_CONNECTOR_LVDS) {
+               if (gConnector[id]->type == VIDEO_CONNECTOR_LVDS) {
                        // If plain (non-DP) laptop LVDS, read mode info from 
AtomBIOS
                        //TRACE("%s: non-DP laptop LVDS detected\n", __func__);
                        gDisplay[displayIndex]->attached = 
connector_read_mode_lvds(id,
@@ -313,7 +334,7 @@ detect_displays()
 
                        // Since DVI-I shows up as two connectors, and there is 
only one
                        // edid channel, we have to make *sure* the edid data 
received is
-                       // valid for te connector.
+                       // valid for the connector.
 
                        // Found EDID data?
                        if (gDisplay[displayIndex]->attached) {
@@ -331,6 +352,7 @@ detect_displays()
                                                "and a analog encoder.\n", 
__func__, id);
                                        gDisplay[displayIndex]->attached
                                                = 
encoder_analog_load_detect(id);
+                                       remove_dup_displays(displayIndex, id);
                                } else if (edid->display.input_type && 
!analogEncoder) {
                                        // If EDID is digital, we make an 
assumption here.
                                        TRACE("%s: connector(%" B_PRIu32 "): 
has digital EDID "
@@ -339,9 +361,16 @@ detect_displays()
                                        // This generally means the monitor is 
of poor design
                                        // Since we *know* there is no load on 
the analog encoder
                                        // we assume that it is a digital 
display.
+                                       // This can also occur when a display 
has both DVI and VGA
+                                       // inputs and the graphics board has a 
DVI-I connector
+                                       // (reported as both digital and analog 
connectors) and the
+                                       // analog connection is the one in use. 
In that case, we
+                                       // get here when checking the digital 
connector and want
+                                       // to disable that display in favor of 
the analog one.
                                        TRACE("%s: connector(%" B_PRIu32 "): 
Warning: monitor has "
                                                "false digital EDID flag + 
unloaded analog encoder!\n",
                                                __func__, id);
+                                       gDisplay[displayIndex]->attached = 
false;
                                }
                        }
                }
@@ -558,7 +587,6 @@ display_crtc_scale(uint8 crtcID, display_mode* mode)
 void
 display_crtc_dpms(uint8 crtcID, int mode)
 {
-
        radeon_shared_info &info = *gInfo->shared_info;
 
        switch (mode) {
@@ -566,8 +594,8 @@ display_crtc_dpms(uint8 crtcID, int mode)
                        TRACE("%s: crtc %" B_PRIu8 " dpms powerup\n", __func__, 
crtcID);
                        if (gDisplay[crtcID]->attached == false)
                                return;
-                       gDisplay[crtcID]->powered = true;
                        display_crtc_power(crtcID, ATOM_ENABLE);
+                       gDisplay[crtcID]->powered = true;
                        if (info.dceMajor >= 3)
                                display_crtc_memreq(crtcID, ATOM_ENABLE);
                        display_crtc_blank(crtcID, ATOM_BLANKING_OFF);
@@ -589,11 +617,120 @@ display_crtc_dpms(uint8 crtcID, int mode)
 
 
 void
+display_dce45_crtc_load_lut(uint8 crtcID)
+{
+       radeon_shared_info &info = *gInfo->shared_info;
+       register_info* regs = gDisplay[crtcID]->regs;
+
+       TRACE("%s: crtcID %" B_PRIu8 "\n", __func__, crtcID);
+
+       uint16* r = info.color_data;
+       uint16* g = r + 256;
+       uint16* b = r + 512;
+
+       if (info.dceMajor >= 5) {
+               Write32(OUT, NI_INPUT_CSC_CONTROL + regs->crtcOffset,
+                  (NI_INPUT_CSC_GRPH_MODE(NI_INPUT_CSC_BYPASS) |
+                  NI_INPUT_CSC_OVL_MODE(NI_INPUT_CSC_BYPASS)));
+               Write32(OUT, NI_PRESCALE_GRPH_CONTROL + regs->crtcOffset,
+                       NI_GRPH_PRESCALE_BYPASS);
+               Write32(OUT, NI_PRESCALE_OVL_CONTROL + regs->crtcOffset,
+                       NI_OVL_PRESCALE_BYPASS);
+               Write32(OUT, NI_INPUT_GAMMA_CONTROL + regs->crtcOffset,
+                       (NI_GRPH_INPUT_GAMMA_MODE(NI_INPUT_GAMMA_USE_LUT) |
+                       NI_OVL_INPUT_GAMMA_MODE(NI_INPUT_GAMMA_USE_LUT)));
+       }
+
+       Write32(OUT, EVERGREEN_DC_LUT_CONTROL + regs->crtcOffset, 0);
+
+       Write32(OUT, EVERGREEN_DC_LUT_BLACK_OFFSET_BLUE + regs->crtcOffset, 0);
+       Write32(OUT, EVERGREEN_DC_LUT_BLACK_OFFSET_GREEN + regs->crtcOffset, 0);
+       Write32(OUT, EVERGREEN_DC_LUT_BLACK_OFFSET_RED + regs->crtcOffset, 0);
+
+       Write32(OUT, EVERGREEN_DC_LUT_WHITE_OFFSET_BLUE + regs->crtcOffset, 
0xffff);
+       Write32(OUT, EVERGREEN_DC_LUT_WHITE_OFFSET_GREEN + regs->crtcOffset, 
0xffff);
+       Write32(OUT, EVERGREEN_DC_LUT_WHITE_OFFSET_RED + regs->crtcOffset, 
0xffff);
+
+       Write32(OUT, EVERGREEN_DC_LUT_RW_MODE, 0);
+       Write32(OUT, EVERGREEN_DC_LUT_WRITE_EN_MASK, 0x00000007);
+
+       Write32(OUT, EVERGREEN_DC_LUT_RW_INDEX, 0);
+       for (int i = 0; i < 256; i++) {
+               Write32(OUT, EVERGREEN_DC_LUT_30_COLOR + regs->crtcOffset,
+                        (r[i] << 20) |
+                        (g[i] << 10) |
+                        (b[i] << 0));
+       }
+
+       if (info.dceMajor >= 5) {
+               Write32(OUT, NI_DEGAMMA_CONTROL + regs->crtcOffset,
+                  (NI_GRPH_DEGAMMA_MODE(NI_DEGAMMA_BYPASS) |
+                  NI_OVL_DEGAMMA_MODE(NI_DEGAMMA_BYPASS) |
+                  NI_ICON_DEGAMMA_MODE(NI_DEGAMMA_BYPASS) |
+                  NI_CURSOR_DEGAMMA_MODE(NI_DEGAMMA_BYPASS)));
+               Write32(OUT, NI_GAMUT_REMAP_CONTROL + regs->crtcOffset,
+                       (NI_GRPH_GAMUT_REMAP_MODE(NI_GAMUT_REMAP_BYPASS) |
+                       NI_OVL_GAMUT_REMAP_MODE(NI_GAMUT_REMAP_BYPASS)));
+               Write32(OUT, NI_REGAMMA_CONTROL + regs->crtcOffset,
+                       (NI_GRPH_REGAMMA_MODE(NI_REGAMMA_BYPASS) |
+                       NI_OVL_REGAMMA_MODE(NI_REGAMMA_BYPASS)));
+               Write32(OUT, NI_OUTPUT_CSC_CONTROL + regs->crtcOffset,
+                       (NI_OUTPUT_CSC_GRPH_MODE(NI_OUTPUT_CSC_BYPASS) |
+                       NI_OUTPUT_CSC_OVL_MODE(NI_OUTPUT_CSC_BYPASS)));
+               /* XXX match this to the depth of the crtc fmt block, move to 
modeset? */
+               Write32(OUT, 0x6940 + regs->crtcOffset, 0);
+       }
+}
+
+
+void
+display_avivo_crtc_load_lut(uint8 crtcID)
+{
+       radeon_shared_info &info = *gInfo->shared_info;
+       register_info* regs = gDisplay[crtcID]->regs;
+
+       TRACE("%s: crtcID %" B_PRIu8 "\n", __func__, crtcID);
+
+       uint16* r = info.color_data;
+       uint16* g = r + 256;
+       uint16* b = r + 512;
+
+       Write32(OUT, AVIVO_DC_LUTA_CONTROL + regs->crtcOffset, 0);
+
+       Write32(OUT, AVIVO_DC_LUTA_BLACK_OFFSET_BLUE + regs->crtcOffset, 0);
+       Write32(OUT, AVIVO_DC_LUTA_BLACK_OFFSET_GREEN + regs->crtcOffset, 0);
+       Write32(OUT, AVIVO_DC_LUTA_BLACK_OFFSET_RED + regs->crtcOffset, 0);
+
+       Write32(OUT, AVIVO_DC_LUTA_WHITE_OFFSET_BLUE + regs->crtcOffset, 
0xffff);
+       Write32(OUT, AVIVO_DC_LUTA_WHITE_OFFSET_GREEN + regs->crtcOffset, 
0xffff);
+       Write32(OUT, AVIVO_DC_LUTA_WHITE_OFFSET_RED + regs->crtcOffset, 0xffff);
+
+       Write32(OUT, AVIVO_DC_LUT_RW_SELECT, crtcID);
+       Write32(OUT, AVIVO_DC_LUT_RW_MODE, 0);
+       Write32(OUT, AVIVO_DC_LUT_WRITE_EN_MASK, 0x0000003f);
+
+       Write32(OUT, AVIVO_DC_LUT_RW_INDEX, 0);
+       for (int i = 0; i < 256; i++) {
+               Write32(OUT, AVIVO_DC_LUT_30_COLOR,
+                        (r[i] << 20) |
+                        (g[i] << 10) |
+                        (b[i] << 0));
+       }
+
+       Write32(OUT, AVIVO_D1GRPH_LUT_SEL + regs->crtcOffset, crtcID);
+}
+
+
+void
 display_crtc_fb_set(uint8 crtcID, display_mode* mode)
 {
        radeon_shared_info &info = *gInfo->shared_info;
        register_info* regs = gDisplay[crtcID]->regs;
 
+       uint16* r = info.color_data;
+       uint16* g = r + 256;
+       uint16* b = r + 512;
+
        uint32 fbSwap;
        if (info.dceMajor >= 4)
                fbSwap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_NONE);
@@ -616,6 +753,7 @@ display_crtc_fb_set(uint8 crtcID, display_mode* mode)
                                fbFormat = AVIVO_D1GRPH_CONTROL_DEPTH_8BPP
                                        | AVIVO_D1GRPH_CONTROL_8BPP_INDEXED;
                        }
+                       // TODO: copy system color map into shared info
                        break;
                case B_RGB15_LITTLE:
                        bytesPerPixel = 2;
@@ -646,6 +784,17 @@ display_crtc_fb_set(uint8 crtcID, display_mode* mode)
                                fbSwap = R600_D1GRPH_SWAP_ENDIAN_16BIT;
                                #endif
                        }
+
+                       {
+                               // default gamma table
+                               uint16 gamma = 0;
+                               for (int i = 0; i < 256; i++) {
+                                       r[i] = gamma;
+                                       g[i] = gamma;
+                                       b[i] = gamma;
+                                       gamma += 4;
+                               }
+                       }
                        break;
                case B_RGB24_LITTLE:
                case B_RGB32_LITTLE:
@@ -666,6 +815,17 @@ display_crtc_fb_set(uint8 crtcID, display_mode* mode)
                                fbSwap = R600_D1GRPH_SWAP_ENDIAN_32BIT;
                                #endif
                        }
+
+                       {
+                               // default gamma table
+                               uint16 gamma = 0;
+                               for (int i = 0; i < 256; i++) {
+                                       r[i] = gamma;
+                                       g[i] = gamma;
+                                       b[i] = gamma;
+                                       gamma += 4;
+                               }
+                       }
                        break;
        }
 
@@ -685,7 +845,7 @@ display_crtc_fb_set(uint8 crtcID, display_mode* mode)
                        (fbAddress >> 32) & 0xf);
        }
 
-       TRACE("%s: Set SurfaceAddress: 0x%" B_PRIX32 "\n",
+       TRACE("%s: Set SurfaceAddress: 0x%" B_PRIX64 "\n",
                __func__, (fbAddress & 0xFFFFFFFF));
 
        Write32(OUT, regs->grphPrimarySurfaceAddr, (fbAddress & 0xFFFFFFFF));
@@ -700,16 +860,17 @@ display_crtc_fb_set(uint8 crtcID, display_mode* mode)
        uint32 widthAligned = mode->virtual_width;
        uint32 pitchMask = 0;
 
+       // assume micro-linear/macro-linear mode (i.e., not tiled)
        switch (bytesPerPixel) {
                case 1:
-                       pitchMask = 255;
+                       pitchMask = 63;
                        break;
                case 2:
-                       pitchMask = 127;
+                       pitchMask = 31;
                        break;
                case 3:
                case 4:
-                       pitchMask = 63;
+                       pitchMask = 31;
                        break;
        }
        widthAligned += pitchMask;
@@ -718,7 +879,7 @@ display_crtc_fb_set(uint8 crtcID, display_mode* mode)
        TRACE("%s: fb: %" B_PRIu32 "x%" B_PRIu32 " (%" B_PRIu32 " bpp)\n", 
__func__,
                mode->virtual_width, mode->virtual_height, bitsPerPixel);
        TRACE("%s: fb pitch: %" B_PRIu32 " \n", __func__,
-               widthAligned * bytesPerPixel / 4);
+               widthAligned);
        TRACE("%s: fb width aligned: %" B_PRIu32 "\n", __func__,
                widthAligned);
 
@@ -728,7 +889,7 @@ display_crtc_fb_set(uint8 crtcID, display_mode* mode)
        Write32(CRT, regs->grphYStart, 0);
        Write32(CRT, regs->grphXEnd, mode->virtual_width);
        Write32(CRT, regs->grphYEnd, mode->virtual_height);
-       Write32(CRT, regs->grphPitch, widthAligned * bytesPerPixel / 4);
+       Write32(CRT, regs->grphPitch, widthAligned);
 
        Write32(CRT, regs->grphEnable, 1);
                // Enable Frame buffer
@@ -751,7 +912,7 @@ display_crtc_fb_set(uint8 crtcID, display_mode* mode)
 
                Write32(OUT, EVERGREEN_MASTER_UPDATE_MODE + regs->crtcOffset, 
0);
                        // Pageflip to happen anywhere in vblank
-
+               display_dce45_crtc_load_lut(crtcID);
        } else {
                uint32 tmp = Read32(OUT, AVIVO_D1GRPH_FLIP_CONTROL + 
regs->crtcOffset);
                tmp &= ~AVIVO_D1GRPH_SURFACE_UPDATE_H_RETRACE_EN;
@@ -759,6 +920,7 @@ display_crtc_fb_set(uint8 crtcID, display_mode* mode)
 
                Write32(OUT, AVIVO_D1MODE_MASTER_UPDATE_MODE + 
regs->crtcOffset, 0);
                        // Pageflip to happen anywhere in vblank
+               display_avivo_crtc_load_lut(crtcID);
        }
 
        // update shared info
@@ -816,8 +978,8 @@ display_crtc_set_dtd(uint8 crtcID, display_mode* mode)
 {
        display_timing& displayTiming = mode->timing;
 
-       TRACE("%s called to do %dx%d\n",
-               __func__, displayTiming.h_display, displayTiming.v_display);
+       TRACE("%s called to do %dx%d\n", __func__,
+               displayTiming.h_display, displayTiming.v_display);
 
        SET_CRTC_USING_DTD_TIMING_PARAMETERS args;
        int index = GetIndexIntoMasterTable(COMMAND, SetCRTC_UsingDTDTiming);
@@ -825,6 +987,7 @@ display_crtc_set_dtd(uint8 crtcID, display_mode* mode)
 
        memset(&args, 0, sizeof(args));
 
+       // Note: the code below assumes H & V borders are both zero
        uint16 blankStart
                = MIN(displayTiming.h_sync_start, displayTiming.h_display);
        uint16 blankEnd
diff --git a/src/add-ons/accelerants/radeon_hd/display.h 
b/src/add-ons/accelerants/radeon_hd/display.h
index 93c25e1..5676bbd 100644
--- a/src/add-ons/accelerants/radeon_hd/display.h
+++ b/src/add-ons/accelerants/radeon_hd/display.h
@@ -31,6 +31,8 @@ void display_crtc_set(uint8 crtcID, display_mode* mode);
 void display_crtc_set_dtd(uint8 crtcID, display_mode* mode);
 void display_crtc_power(uint8 crtcID, int command);
 void display_crtc_memreq(uint8 crtcID, int command);
+void display_avivo_crtc_load_lut(uint8 crtcID);
+void display_dce45_crtc_load_lut(uint8 crtcID);
 
 
 #endif /* RADEON_HD_DISPLAY_H */
diff --git a/src/add-ons/accelerants/radeon_hd/displayport.cpp 
b/src/add-ons/accelerants/radeon_hd/displayport.cpp
index 3acd66d..a2421a5 100644
--- a/src/add-ons/accelerants/radeon_hd/displayport.cpp
+++ b/src/add-ons/accelerants/radeon_hd/displayport.cpp
@@ -15,6 +15,7 @@
 #include "accelerant_protos.h"
 #include "connector.h"
 #include "mode.h"
+#include "edid.h"
 
 
 #undef TRACE
@@ -341,8 +342,8 @@ dp_get_lane_count(uint32 connectorIndex, display_mode* mode)
 
        size_t pixelChunk;
        size_t pixelsPerChunk;
-       status_t result = dp_get_pixel_size_for((color_space)mode->space, 
&pixelChunk,
-               NULL, &pixelsPerChunk);
+       status_t result = dp_get_pixel_size_for((color_space)mode->space,
+               &pixelChunk, NULL, &pixelsPerChunk);
 
        if (result != B_OK) {
                TRACE("%s: Invalid color space!\n", __func__);
@@ -355,7 +356,8 @@ dp_get_lane_count(uint32 connectorIndex, display_mode* mode)
        uint32 dpMaxLaneCount = dp_get_lane_count_max(dpInfo);
 
        uint32 lane;
-       for (lane = 1; lane < dpMaxLaneCount; lane <<= 1) {
+       // don't go below 2 lanes or display is jittery
+       for (lane = 2; lane < dpMaxLaneCount; lane <<= 1) {
                uint32 maxPixelClock = dp_get_pixel_clock_max(dpMaxLinkRate, 
lane,
                        bitsPerPixel);
                if (mode->timing.pixel_clock <= maxPixelClock)
@@ -380,8 +382,8 @@ dp_get_link_rate(uint32 connectorIndex, display_mode* mode)
 
        size_t pixelChunk;
        size_t pixelsPerChunk;
-       status_t result = dp_get_pixel_size_for((color_space)mode->space, 
&pixelChunk,
-               NULL, &pixelsPerChunk);
+       status_t result = dp_get_pixel_size_for((color_space)mode->space,
+               &pixelChunk, NULL, &pixelsPerChunk);
 
        if (result != B_OK) {
                TRACE("%s: Invalid color space!\n", __func__);
@@ -430,6 +432,8 @@ dp_setup_connectors()
                        continue;
                }
 
+               TRACE("%s: found dp connector on index %" B_PRIu32 "\n",
+                       __func__, index);
                uint32 gpioID = gConnector[index]->gpioID;
 
                uint32 auxPin = gGPIOInfo[gpioID]->hwPin;
@@ -655,6 +659,7 @@ dp_link_train_cr(uint32 connectorIndex)
        dp_set_tp(connectorIndex, DP_TRAIN_PATTERN_1);
        memset(dp->trainingSet, 0, 4);
        dp_update_vs_emph(connectorIndex);
+       snooze(400);
 
        while (1) {
                if (dp->trainingReadInterval == 0)
@@ -763,11 +768,13 @@ dp_link_train_ce(uint32 connectorIndex)
 
 
 status_t
-dp_link_train(uint32 connectorIndex, display_mode* mode)
+dp_link_train(uint8 crtcID)
 {
        TRACE("%s\n", __func__);
 
+        uint32 connectorIndex = gDisplay[crtcID]->connectorIndex;
        dp_info* dp = &gConnector[connectorIndex]->dpInfo;
+       display_mode* mode = &gDisplay[crtcID]->currentMode;
 
        if (dp->valid != true) {
                ERROR("%s: started on invalid DisplayPort connector #%" 
B_PRIu32 "\n",
@@ -830,7 +837,10 @@ dp_link_train(uint32 connectorIndex, display_mode* mode)
        encoder_dig_setup(connectorIndex, mode->timing.pixel_clock,
                ATOM_ENCODER_CMD_SETUP_PANEL_MODE);
 
-       if (dp->config[0] >= DP_DPCD_REV_11)
+       // TODO: Doesn't this overwrite important dpcd info?
+       sandbox = dp->laneCount;
+       if ((dp->config[0] >= DP_DPCD_REV_11)
+               && (dp->config[2] & DP_ENHANCED_FRAME_CAP_EN))
                sandbox |= DP_ENHANCED_FRAME_EN;
        dpcd_reg_write(hwPin, DP_LANE_COUNT, sandbox);
 
@@ -872,7 +882,7 @@ dp_link_train(uint32 connectorIndex, display_mode* mode)
 }
 
 
-status_t
+bool
 ddc2_dp_read_edid1(uint32 connectorIndex, edid1_info* edid)
 {
        TRACE("%s\n", __func__);
@@ -880,15 +890,16 @@ ddc2_dp_read_edid1(uint32 connectorIndex, edid1_info* 
edid)
        dp_info* dpInfo = &gConnector[connectorIndex]->dpInfo;
 
        if (!dpInfo->valid)
-               return B_ERROR;
-
-       edid1_raw raw;
-       uint8* rdata = (uint8_t*)&raw;
-       uint8 sdata = 0;
+               return false;
 
        // The following sequence is from a trace of the Linux kernel
        // radeon code; not sure if the initial writes to address 0 are
        // requried.
+
+       // TODO: This surely cane be cleaned up
+       edid1_raw raw;
+       uint8* rdata = (uint8*)&raw;
+       uint8 sdata = 0;
        dp_aux_set_i2c_byte(dpInfo->auxPin, 0x00, &sdata, true, false);
        dp_aux_set_i2c_byte(dpInfo->auxPin, 0x00, &sdata, false, true);
 
@@ -902,25 +913,25 @@ ddc2_dp_read_edid1(uint32 connectorIndex, edid1_info* 
edid)
        dp_aux_get_i2c_byte(dpInfo->auxPin, 0x50, rdata, true, false);
 
        for (uint32 i = 0; i < sizeof(raw); i++) {
-               status_t result = dp_aux_get_i2c_byte(dpInfo->auxPin, 0x50, 
rdata++,
-                       false, false);
-               if (result) {
-                       ERROR("%s: error reading EDID data at index %" B_PRIu32 
"\n",
-                               __func__, i);
+               status_t ret = dp_aux_get_i2c_byte(dpInfo->auxPin, 0x50,
+                       rdata++, false, false);
+               if (ret) {
+                       TRACE("%s: error reading EDID data at index %d, ret = 
%d\n",
+                                       __func__, i, ret);
                        dp_aux_get_i2c_byte(dpInfo->auxPin, 0x50, &sdata, 
false, true);
-                       return B_ERROR;
+                       return false;
                }
        }
        dp_aux_get_i2c_byte(dpInfo->auxPin, 0x50, &sdata, false, true);
 
        if (raw.version.version != 1 || raw.version.revision > 4) {
                ERROR("%s: EDID version or revision out of range\n", __func__);
-               return B_ERROR;
+               return false;
        }
 
        edid_decode(edid, &raw);
 
-       return B_OK;
+       return true;
 }
 
 
diff --git a/src/add-ons/accelerants/radeon_hd/displayport.h 
b/src/add-ons/accelerants/radeon_hd/displayport.h
index ae484d0..46c97fa 100644
--- a/src/add-ons/accelerants/radeon_hd/displayport.h
+++ b/src/add-ons/accelerants/radeon_hd/displayport.h
@@ -40,7 +40,7 @@ uint32 dp_get_lane_count(uint32 connectorIndex, display_mode* 
mode);
 
 void dp_setup_connectors();
 
-status_t dp_link_train(uint32 connectorIndex, display_mode* mode);
+status_t dp_link_train(uint8 crtcID);
 status_t dp_link_train_cr(uint32 connectorIndex);
 status_t dp_link_train_ce(uint32 connectorIndex);
 
@@ -48,7 +48,8 @@ void debug_dp_info();
 
 status_t dp_get_pixel_size_for(color_space space, size_t *pixelChunk,
        size_t *rowAlignment, size_t *pixelsPerChunk);
-status_t ddc2_dp_read_edid1(uint32 connectorIndex, edid1_info *edid);
 
+bool ddc2_dp_read_edid1(uint32 connectorIndex, edid1_info *edid);
 
-#endif /* RADEON_HD_DISPLAYPORT_H */
\ No newline at end of file
+
+#endif /* RADEON_HD_DISPLAYPORT_H */
diff --git a/src/add-ons/accelerants/radeon_hd/encoder.cpp 
b/src/add-ons/accelerants/radeon_hd/encoder.cpp
index 314bb4e..4064d2c 100644
--- a/src/add-ons/accelerants/radeon_hd/encoder.cpp
+++ b/src/add-ons/accelerants/radeon_hd/encoder.cpp
@@ -294,7 +294,7 @@ encoder_mode_set(uint8 crtcID)
        uint16 encoderFlags = gConnector[connectorIndex]->encoder.flags;
        pll_info* pll = &gConnector[connectorIndex]->encoder.pll;
 
-       // Adjusted pixel clock (*NOT* original mode pixel clock)
+       // TODO: Should this be the adjusted pll or the original?
        uint32 pixelClock = pll->pixelClock;
 
        switch (gConnector[connectorIndex]->encoder.objectID) {
@@ -324,6 +324,9 @@ encoder_mode_set(uint8 crtcID)
                case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
                case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
                case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
+                       // already handled by virue of setting DPMS_OFF before
+                       // getting here
+#if 0
                        if ((info.chipsetFlags & CHIP_APU) != 0
                                || info.dceMajor >= 5) {
                                // Setup DIG encoder
@@ -356,6 +359,7 @@ encoder_mode_set(uint8 crtcID)
                                transmitter_dig_setup(connectorIndex, 
pixelClock, 0, 0,
                                        ATOM_TRANSMITTER_ACTION_ENABLE);
                        }
+#endif
                        break;
                case ENCODER_OBJECT_ID_INTERNAL_DDI:
                case ENCODER_OBJECT_ID_INTERNAL_DVO1:
@@ -1828,8 +1832,17 @@ encoder_dpms_set_dig(uint8 crtcID, int mode)
                                        transmitter_dig_setup(connectorIndex, 
pll->pixelClock, 0, 0,
                                                ATOM_ENCODER_CMD_SETUP);
                                }
+                               encoder_dig_setup(connectorIndex, 
pll->pixelClock, ATOM_ENABLE);
+                               transmitter_dig_setup(connectorIndex, 
pll->pixelClock, 0, 0,
+                                       ATOM_TRANSMITTER_ACTION_SETUP);
                                transmitter_dig_setup(connectorIndex, 
pll->pixelClock, 0, 0,
                                        ATOM_TRANSMITTER_ACTION_ENABLE);
+                               /* some early dce3.2 boards have a bug in their 
transmitter
+                                  control table */
+                               if (info.chipsetID != RADEON_RV710
+                                       && info.chipsetID != RADEON_RV730)
+                                       transmitter_dig_setup(connectorIndex, 
pll->pixelClock, 0, 0,
+                                               
ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT);
                        } else {
                                transmitter_dig_setup(connectorIndex, 
pll->pixelClock, 0, 0,
                                        ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT);
@@ -1845,12 +1858,15 @@ encoder_dpms_set_dig(uint8 crtcID, int mode)
                                        encoder_dig_setup(connectorIndex, 
pll->pixelClock,
                                                ATOM_ENCODER_CMD_DP_VIDEO_OFF);
                                }
-                               // TODO: dp link train here
-                               //radeon_dp_link_train(encoder, connector);
+                               // dp link train
+                               dp_link_train(crtcID);
                                if (info.dceMajor >= 4) {
                                        encoder_dig_setup(connectorIndex, 
pll->pixelClock,
                                                ATOM_ENCODER_CMD_DP_VIDEO_ON);
                                }
+                               // not sure what AtomBIOS table/command sets 
this
+                               // register, but it's required to get the video 
output
+                               Write32(OUT, AVIVO_DP_VID_STREAM_CNTL, 0x201);
                        }
                        if ((encoderFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) {
                                transmitter_dig_setup(connectorIndex, 
pll->pixelClock,
@@ -1866,6 +1882,9 @@ encoder_dpms_set_dig(uint8 crtcID, int mode)
                        } else {
                                transmitter_dig_setup(connectorIndex, 
pll->pixelClock, 0, 0,
                                        ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT);
+                               transmitter_dig_setup(connectorIndex, 
pll->pixelClock, 0, 0,
+                                       ATOM_TRANSMITTER_ACTION_DISABLE);
+                               encoder_dig_setup(connectorIndex, 
pll->pixelClock, ATOM_DISABLE);
                        }
                        if (connector_is_dp(connectorIndex)) {
                                if (info.dceMajor >= 4) {
diff --git a/src/add-ons/accelerants/radeon_hd/hooks.cpp 
b/src/add-ons/accelerants/radeon_hd/hooks.cpp
index d57bb73..238c962 100644
--- a/src/add-ons/accelerants/radeon_hd/hooks.cpp
+++ b/src/add-ons/accelerants/radeon_hd/hooks.cpp
@@ -39,7 +39,7 @@ get_accelerant_hook(uint32 feature, void* data)
                case B_DPMS_MODE:
                        return (void*)radeon_dpms_mode;
                case B_SET_DPMS_MODE:
-                       return (void*)radeon_dpms_set;
+                       return (void*)radeon_dpms_set_hook;
 
                /* mode configuration */
                case B_ACCELERANT_MODE_COUNT:
diff --git a/src/add-ons/accelerants/radeon_hd/mode.cpp 
b/src/add-ons/accelerants/radeon_hd/mode.cpp
index d272965..815d52f 100644
--- a/src/add-ons/accelerants/radeon_hd/mode.cpp
+++ b/src/add-ons/accelerants/radeon_hd/mode.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright 2006-2011, Haiku, Inc. All Rights Reserved.
+ * Copyright 2006-2013, Haiku, Inc. All Rights Reserved.
  * Distributed under the terms of the MIT License.
  *
  * Support for i915 chipset and up based on the X driver,
@@ -69,6 +69,7 @@ uint32
 radeon_accelerant_mode_count(void)
 {
        TRACE("%s\n", __func__);
+       // TODO: multi-monitor?  we need crtcid here
 
        return gInfo->shared_info->mode_count;
 }
@@ -78,6 +79,7 @@ status_t
 radeon_get_mode_list(display_mode* modeList)
 {
        TRACE("%s\n", __func__);
+       // TODO: multi-monitor?  we need crtcid here
        memcpy(modeList, gInfo->mode_list,
                gInfo->shared_info->mode_count * sizeof(display_mode));
        return B_OK;
@@ -88,8 +90,8 @@ status_t
 radeon_get_preferred_mode(display_mode* preferredMode)
 {
        TRACE("%s\n", __func__);
+       // TODO: multi-monitor?  we need crtcid here
 
-       // TODO: Argh!  Which display? :)
        uint8_t crtc = 0;
 
        if (gDisplay[crtc]->preferredMode.virtual_width > 0
@@ -119,7 +121,7 @@ radeon_get_edid_info(void* info, size_t size, uint32* 
edid_version)
        memcpy(info, &gInfo->shared_info->edid_info, sizeof(struct edid1_info));
                // VESA
        //memcpy(info, &gDisplay[0]->edidData, sizeof(struct edid1_info));
-               // BitBanged display 0
+               // Display 0
 
        *edid_version = EDID_VERSION_1;
 
@@ -145,27 +147,46 @@ radeon_dpms_mode(void)
 
 
 void
-radeon_dpms_set(int mode)
+radeon_dpms_set(uint8 id, int mode)
 {
-       for (uint8 id = 0; id < MAX_DISPLAY; id++) {
+       if (mode == B_DPMS_ON) {
+               display_crtc_dpms(id, mode);
+               encoder_dpms_set(id, mode);
+       } else {
                encoder_dpms_set(id, mode);
                display_crtc_dpms(id, mode);
        }
-
        gInfo->dpms_mode = mode;
 }
 
 
+void
+radeon_dpms_set_hook(int mode)
+{
+       // TODO: multi-monitor?  for now we use VESA edid
+
+       // As the accelerant hook doesn't pass crtc id
+       for (uint8 id = 0; id < MAX_DISPLAY; id++) {
+               radeon_dpms_set(id, mode);
+       }
+}
+
+
 status_t
 radeon_set_display_mode(display_mode* mode)
 {
-       radeon_shared_info &info = *gInfo->shared_info;
+       // TODO: multi-monitor? For now we set the mode on
+       // all displays (this is very incorrect). This also
+       // causes a lot of problems on DisplayPort devices
 
        // Set mode on each display
        for (uint8 id = 0; id < MAX_DISPLAY; id++) {
                if (gDisplay[id]->attached == false)
                        continue;
 
+               // Copy this display mode into the "current mode" for the 
display
+               memcpy(&gDisplay[id]->currentMode, mode, sizeof(display_mode));
+
                uint32 connectorIndex = gDisplay[id]->connectorIndex;
 
                // Determine DP lanes if DP
@@ -177,9 +198,8 @@ radeon_set_display_mode(display_mode* mode)
 
                // *** crtc and encoder prep
                encoder_output_lock(true);
-               encoder_dpms_set(id, B_DPMS_OFF);
                display_crtc_lock(id, ATOM_ENABLE);
-               display_crtc_dpms(id, B_DPMS_OFF);
+               radeon_dpms_set(id, B_DPMS_OFF);
 
                // *** Set up encoder -> crtc routing
                encoder_assign_crtc(id);
@@ -201,31 +221,15 @@ radeon_set_display_mode(display_mode* mode)
                // *** encoder mode set
                encoder_mode_set(id);
 
-               // *** CRT controler commit
-               display_crtc_dpms(id, B_DPMS_ON);
+               // *** encoder and CRT controller commit
+               radeon_dpms_set(id, B_DPMS_ON);
                display_crtc_lock(id, ATOM_DISABLE);
-
-               // *** encoder commit
-
-               // handle DisplayPort link training
-               if (connector_is_dp(connectorIndex)) {
-                       if (info.dceMajor >= 4)
-                               encoder_dig_setup(connectorIndex,
-                                       ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0);
-
-                       dp_link_train(connectorIndex, mode);
-
-                       if (info.dceMajor >= 4)
-                               encoder_dig_setup(connectorIndex,
-                                       ATOM_ENCODER_CMD_DP_VIDEO_ON, 0);
-               }
-
-               encoder_dpms_set(id, B_DPMS_ON);
                encoder_output_lock(false);
        }
 
+       #ifdef TRACE_MODE
        // for debugging
-       // debug_dp_info();
+       debug_dp_info();
 
        TRACE("D1CRTC_STATUS        Value: 0x%X\n",
                Read32(CRT, AVIVO_D1CRTC_STATUS));
@@ -247,6 +251,7 @@ radeon_set_display_mode(display_mode* mode)
                Read32(CRT, AVIVO_D1CRTC_BLANK_CONTROL));
        TRACE("D2CRTC_BLANK_CONTROL Value: 0x%X\n",
                Read32(CRT, AVIVO_D1CRTC_BLANK_CONTROL));
+       #endif
 
        return B_OK;
 }
@@ -258,6 +263,7 @@ radeon_get_display_mode(display_mode* _currentMode)
        TRACE("%s\n", __func__);
 
        *_currentMode = gInfo->shared_info->current_mode;
+       //*_currentMode = gDisplay[X]->currentMode;
        return B_OK;
 }
 
diff --git a/src/add-ons/accelerants/radeon_hd/mode.h 
b/src/add-ons/accelerants/radeon_hd/mode.h
index 59a5ce1..db98aec 100644
--- a/src/add-ons/accelerants/radeon_hd/mode.h
+++ b/src/add-ons/accelerants/radeon_hd/mode.h
@@ -32,7 +32,8 @@ bool is_mode_supported(display_mode* mode);
 status_t is_mode_sane(display_mode* mode);
 uint32 radeon_dpms_capabilities(void);
 uint32 radeon_dpms_mode(void);
-void radeon_dpms_set(int mode);
+void radeon_dpms_set(uint8 id, int mode);
+void radeon_dpms_set_hook(int mode);
 uint32 get_mode_bpp(display_mode* mode);
 
 
diff --git a/src/add-ons/accelerants/radeon_hd/pll.cpp 
b/src/add-ons/accelerants/radeon_hd/pll.cpp
index 9ee2695..4a614d4 100644
--- a/src/add-ons/accelerants/radeon_hd/pll.cpp
+++ b/src/add-ons/accelerants/radeon_hd/pll.cpp
@@ -301,7 +301,7 @@ pll_compute_post_divider(pll_info* pll)
                if ((pll->flags & PLL_IS_LCD) != 0)
                        vco = pll->lcdPllOutMin;
                else
-                       vco = pll->pllOutMin;
+                       vco = pll->pllOutMax;
        } else {
                if ((pll->flags & PLL_IS_LCD) != 0)
                        vco = pll->lcdPllOutMax;
@@ -311,8 +311,8 @@ pll_compute_post_divider(pll_info* pll)
 
        TRACE("%s: vco = %" B_PRIu32 "\n", __func__, vco);
 
-       uint32 postDivider = vco / pll->pixelClock;
-       uint32 tmp = vco % pll->pixelClock;
+       uint32 postDivider = vco / pll->adjustedClock;
+       uint32 tmp = vco % pll->adjustedClock;
 
        if ((pll->flags & PLL_PREFER_MINM_OVER_MAXP) != 0) {
                if (tmp)
@@ -337,7 +337,7 @@ pll_compute(pll_info* pll)
 {
        pll_compute_post_divider(pll);
 
-       uint32 targetClock = pll->pixelClock;
+       uint32 targetClock = pll->adjustedClock;
 
        pll->feedbackDiv = 0;
        pll->feedbackDivFrac = 0;
@@ -364,7 +364,7 @@ pll_compute(pll_info* pll)
                        pll->feedbackDiv = pll->minFeedbackDiv;
 
                pll->feedbackDivFrac
-                       = (100 * pll->feedbackDivFrac) / pll->referenceFreq;
+                       = (1000 * pll->feedbackDivFrac) / pll->referenceFreq;
 
                if (pll->feedbackDivFrac >= 5) {
                        pll->feedbackDivFrac -= 5;
@@ -436,12 +436,12 @@ pll_compute(pll_info* pll)
        TRACE("%s: pixel clock: %" B_PRIu32 " gives:"
                " feedbackDivider = %" B_PRIu32 ".%" B_PRIu32
                "; referenceDivider = %" B_PRIu32 "; postDivider = %" B_PRIu32 
"\n",
-               __func__, pll->pixelClock, pll->feedbackDiv, 
pll->feedbackDivFrac,
+               __func__, pll->adjustedClock, pll->feedbackDiv, 
pll->feedbackDivFrac,
                pll->referenceDiv, pll->postDiv);
 
-       if (pll->pixelClock != calculatedClock) {
+       if (pll->adjustedClock != calculatedClock) {
                TRACE("%s: pixel clock %" B_PRIu32 " was changed to %" B_PRIu32 
"\n",
-                       __func__, pll->pixelClock, calculatedClock);
+                       __func__, pll->adjustedClock, calculatedClock);
                pll->pixelClock = calculatedClock;
        }
 
@@ -515,6 +515,7 @@ pll_adjust(pll_info* pll, display_mode* mode, uint8 crtcID)
        uint32 encoderFlags = connector->encoder.flags;
 
        uint32 externalEncoderID = 0;
+       pll->adjustedClock = pll->pixelClock;
        if (connector->encoderExternal.isDPBridge)
                externalEncoderID = connector->encoderExternal.objectID;
 
@@ -557,9 +558,9 @@ pll_adjust(pll_info* pll, display_mode* mode, uint8 crtcID)
 
                                                
atom_execute_table(gAtomContext, index, (uint32*)&args);
                                                // get returned adjusted clock
-                                               pll->pixelClock
+                                               pll->adjustedClock
                                                        = 
B_LENDIAN_TO_HOST_INT16(args.v1.usPixelClock);
-                                               pll->pixelClock *= 10;
+                                               pll->adjustedClock *= 10;
                                                break;
                                        case 3:
                                                args.v3.sInput.usPixelClock
@@ -607,10 +608,10 @@ pll_adjust(pll_info* pll, display_mode* mode, uint8 
crtcID)
                                                
atom_execute_table(gAtomContext, index, (uint32*)&args);
 
                                                // get returned adjusted clock
-                                               pll->pixelClock
+                                               pll->adjustedClock
                                                        = 
B_LENDIAN_TO_HOST_INT32(
                                                                
args.v3.sOutput.ulDispPllFreq);
-                                               pll->pixelClock *= 10;
+                                               pll->adjustedClock *= 10;
                                                        // convert to kHz for 
storage
 
                                                if (args.v3.sOutput.ucRefDiv) {
@@ -638,7 +639,7 @@ pll_adjust(pll_info* pll, display_mode* mode, uint8 crtcID)
        }
 
        TRACE("%s: was: %" B_PRIu32 ", now: %" B_PRIu32 "\n", __func__,
-               pixelClock, pll->pixelClock);
+               pixelClock, pll->adjustedClock);
 
        return B_OK;
 }
@@ -649,6 +650,8 @@ pll_set(display_mode* mode, uint8 crtcID)
 {
        uint32 connectorIndex = gDisplay[crtcID]->connectorIndex;
        pll_info* pll = &gConnector[connectorIndex]->encoder.pll;
+       uint32 dp_clock = gConnector[connectorIndex]->dpInfo.linkRate / 10;
+       bool ssEnabled = false;
 
        pll->pixelClock = mode->timing.pixel_clock;
 
@@ -668,23 +671,28 @@ pll_set(display_mode* mode, uint8 crtcID)
                        if (info.dceMajor >= 4)
                                pll_asic_ss_probe(pll, ASIC_INTERNAL_SS_ON_DP);
                        else {
-                               // TODO: DP Clock == 1.62Ghz?
-                               pll_ppll_ss_probe(pll, ATOM_DP_SS_ID1);
+                               if (dp_clock == 16200) {
+                                       ssEnabled = pll_ppll_ss_probe(pll, 
ATOM_DP_SS_ID2);
+                                       if (!ssEnabled)
+                                               // id2 failed, try id1
+                                               ssEnabled = 
pll_ppll_ss_probe(pll, ATOM_DP_SS_ID1);
+                               } else
+                                       ssEnabled = pll_ppll_ss_probe(pll, 
ATOM_DP_SS_ID1);
                        }
                        break;
                case ATOM_ENCODER_MODE_LVDS:
                        if (info.dceMajor >= 4)
-                               pll_asic_ss_probe(pll, 
gInfo->lvdsSpreadSpectrumID);
+                               ssEnabled = pll_asic_ss_probe(pll, 
gInfo->lvdsSpreadSpectrumID);
                        else
-                               pll_ppll_ss_probe(pll, 
gInfo->lvdsSpreadSpectrumID);
+                               ssEnabled = pll_ppll_ss_probe(pll, 
gInfo->lvdsSpreadSpectrumID);
                        break;
                case ATOM_ENCODER_MODE_DVI:
                        if (info.dceMajor >= 4)
-                               pll_asic_ss_probe(pll, 
ASIC_INTERNAL_SS_ON_TMDS);
+                               ssEnabled = pll_asic_ss_probe(pll, 
ASIC_INTERNAL_SS_ON_TMDS);
                        break;
                case ATOM_ENCODER_MODE_HDMI:
                        if (info.dceMajor >= 4)
-                               pll_asic_ss_probe(pll, 
ASIC_INTERNAL_SS_ON_HDMI);
+                               ssEnabled = pll_asic_ss_probe(pll, 
ASIC_INTERNAL_SS_ON_HDMI);
                        break;
        }
 
@@ -836,7 +844,8 @@ pll_set(display_mode* mode, uint8 crtcID)
 
        status_t result = atom_execute_table(gAtomContext, index, 
(uint32*)&args);
 
-       display_crtc_ss(pll, ATOM_ENABLE);
+       if (ssEnabled)
+               display_crtc_ss(pll, ATOM_ENABLE);
 
        return result;
 }
diff --git a/src/add-ons/accelerants/radeon_hd/pll.h 
b/src/add-ons/accelerants/radeon_hd/pll.h
index 3a5cbba..1a29381 100644
--- a/src/add-ons/accelerants/radeon_hd/pll.h
+++ b/src/add-ons/accelerants/radeon_hd/pll.h
@@ -93,6 +93,9 @@ struct pll_info {
        /* asic spread spectrum */
        uint16 ssRate;
        uint16 ssAmount;
+
+       /* pixel clock to be used in pll calculations (kHz) */
+       uint32 adjustedClock;
 };
 
 


Other related posts: