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

  • From: kallisti5@xxxxxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Mon, 7 Jan 2013 03:42:47 +0100 (CET)

hrev45135 adds 1 changeset to branch 'master'
old head: 45f77dcd7029914ccd99178dfb333eb68c7af9e5
new head: 042344329e6368d53eaa40aed1cc22aac4ecf6b7
overview: http://cgit.haiku-os.org/haiku/log/?qt=range&q=0423443+%5E45f77dc

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

0423443: radeon_hd: Improve displayport support
  
  * Modified patch submitted by Bill Randle.
  * DisplayPort aux communications now working.
  * DP Link Training still not functioning properly.
  * The DP edid data isn't used yet as we still use
    the vesa edid during the mode setting.

                          [ Alexander von Gluck IV <kallisti5@xxxxxxxxxxx> ]

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

Revision:    hrev45135
Commit:      042344329e6368d53eaa40aed1cc22aac4ecf6b7
URL:         http://cgit.haiku-os.org/haiku/commit/?id=0423443
Author:      Alexander von Gluck IV <kallisti5@xxxxxxxxxxx>
Date:        Mon Jan  7 02:17:02 2013 UTC

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

3 files changed, 131 insertions(+), 26 deletions(-)
src/add-ons/accelerants/radeon_hd/display.cpp    | 48 ++++++----
.../accelerants/radeon_hd/displayport.cpp        | 95 ++++++++++++++++++--
src/add-ons/accelerants/radeon_hd/displayport.h  | 14 ++-

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

diff --git a/src/add-ons/accelerants/radeon_hd/display.cpp 
b/src/add-ons/accelerants/radeon_hd/display.cpp
index d09bd8f..7b212ee 100644
--- a/src/add-ons/accelerants/radeon_hd/display.cpp
+++ b/src/add-ons/accelerants/radeon_hd/display.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.
  *
  * Authors:
@@ -21,6 +21,7 @@
 #include "accelerant_protos.h"
 #include "bios.h"
 #include "connector.h"
+#include "displayport.h"
 #include "encoder.h"
 
 
@@ -225,8 +226,7 @@ detect_crt_ranges(uint32 crtid)
                edid1_detailed_monitor* monitor
                        = &edid->detailed_monitor[index];
 
-               if (monitor->monitor_desc_type
-                       == EDID1_MONITOR_RANGES) {
+               if (monitor->monitor_desc_type == EDID1_MONITOR_RANGES) {
                        edid1_monitor_range range = monitor->data.monitor_range;
                        gDisplay[crtid]->vfreqMin = range.min_v;   /* in Hz */
                        gDisplay[crtid]->vfreqMax = range.max_v;
@@ -258,11 +258,24 @@ detect_displays()
                        continue;
 
                if (gConnector[id]->type == VIDEO_CONNECTOR_9DIN) {
-                       TRACE("%s: Skipping 9DIN connector (not yet 
supported)\n",
-                               __func__);
+                       TRACE("%s: connector(%" B_PRIu32 "): Skipping 9DIN 
connector "
+                               "(not yet supported)\n", __func__, id);
                        continue;
                }
 
+               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);
+                       gDisplay[displayIndex]->attached
+                               = (dpHasEDID == B_OK ? true : false);
+                       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
                #if 0
                if (gConnector[id]->encoderExternal.isDPBridge == true) {
@@ -276,17 +289,22 @@ detect_displays()
                        // TODO: DDC Router switching for DisplayPort (and 
others?)
                } else if (gConnector[id]->type == VIDEO_CONNECTOR_LVDS) {
                #endif
-               if (gConnector[id]->type == VIDEO_CONNECTOR_LVDS) {
+
+               if (gDisplay[displayIndex]->attached == false
+                       && 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,
-                                       &gDisplay[displayIndex]->preferredMode);
+                       gDisplay[displayIndex]->attached = 
connector_read_mode_lvds(id,
+                               &gDisplay[displayIndex]->preferredMode);
+                       if (gDisplay[displayIndex]->attached) {
+                               TRACE("%s: connector(%" B_PRIu32 "): found LVDS 
preferred "
+                                       "mode\n", __func__, id);
+                       }
                }
 
                // If no display found yet, try more standard detection methods
                if (gDisplay[displayIndex]->attached == false) {
-                       TRACE("%s: bit-banging ddc for EDID on connector %" 
B_PRIu32 "\n",
+                       TRACE("%s: connector(%" B_PRIu32 "): bit-banging ddc 
for EDID.\n",
                                __func__, id);
 
                        // Lets try bit-banging edid from connector
@@ -299,7 +317,7 @@ detect_displays()
 
                        // Found EDID data?
                        if (gDisplay[displayIndex]->attached) {
-                               TRACE("%s: found EDID data on connector %" 
B_PRIu32 "\n",
+                               TRACE("%s: connector(%" B_PRIu32 "): found EDID 
data.\n",
                                        __func__, id);
 
                                bool analogEncoder
@@ -309,20 +327,20 @@ detect_displays()
                                edid1_info* edid = 
&gDisplay[displayIndex]->edidData;
                                if (!edid->display.input_type && analogEncoder) 
{
                                        // If non-digital EDID + the encoder is 
analog...
-                                       TRACE("%s: connector %" B_PRIu32 " has 
non-digital EDID "
+                                       TRACE("%s: connector(%" B_PRIu32 "): 
has non-digital EDID "
                                                "and a analog encoder.\n", 
__func__, id);
                                        gDisplay[displayIndex]->attached
                                                = 
encoder_analog_load_detect(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 "
+                                       TRACE("%s: connector(%" B_PRIu32 "): 
has digital EDID "
                                                "and is not a analog 
encoder.\n", __func__, id);
                                } else {
                                        // 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.
-                                       TRACE("%s: Warning: monitor on 
connector %" B_PRIu32 " has "
-                                               "false digital EDID flag and 
unloaded analog encoder!\n",
+                                       TRACE("%s: connector(%" B_PRIu32 "): 
Warning: monitor has "
+                                               "false digital EDID flag + 
unloaded analog encoder!\n",
                                                __func__, id);
                                }
                        }
diff --git a/src/add-ons/accelerants/radeon_hd/displayport.cpp 
b/src/add-ons/accelerants/radeon_hd/displayport.cpp
index 2aff239..3acd66d 100644
--- a/src/add-ons/accelerants/radeon_hd/displayport.cpp
+++ b/src/add-ons/accelerants/radeon_hd/displayport.cpp
@@ -1,9 +1,10 @@
 /*
- * Copyright 2011, Haiku, Inc. All Rights Reserved.
+ * Copyright 2011-2013, Haiku, Inc. All Rights Reserved.
  * Distributed under the terms of the MIT License.
  *
  * Authors:
  *             Alexander von Gluck IV, kallisti5@xxxxxxxxxxx
+ *             Bill Randle, billr@xxxxxxxxxx
  */
 
 
@@ -178,14 +179,14 @@ dpcd_reg_read(uint32 hwPin, uint16 address)
 
 
 status_t
-dp_aux_get_i2c_byte(uint32 hwPin, uint16 address, uint8* data, bool end)
+dp_aux_get_i2c_byte(uint32 hwPin, uint16 address, uint8* data, bool start, 
bool stop)
 {
        uint8 auxMessage[5];
        int auxMessageBytes = 4; // 4 for read
 
        /* Set up the command byte */
        auxMessage[2] = AUX_I2C_READ << 4;
-       if (end == false)
+       if (stop == false)
                auxMessage[2] |= AUX_I2C_MOT << 4;
 
        auxMessage[0] = address;
@@ -193,6 +194,12 @@ dp_aux_get_i2c_byte(uint32 hwPin, uint16 address, uint8* 
data, bool end)
 
        auxMessage[3] = auxMessageBytes << 4;
 
+       /* special case for sending the START or STOP */
+       if (start || stop) {
+               auxMessage[3] = 3 << 4;
+               auxMessageBytes = 4;
+       }
+
        int retry;
        for (retry = 0; retry < 4; retry++) {
                uint8 ack;
@@ -249,14 +256,14 @@ dp_aux_get_i2c_byte(uint32 hwPin, uint16 address, uint8* 
data, bool end)
 
 
 status_t
-dp_aux_set_i2c_byte(uint32 hwPin, uint16 address, uint8* data, bool end)
+dp_aux_set_i2c_byte(uint32 hwPin, uint16 address, uint8* data, bool start, 
bool stop)
 {
        uint8 auxMessage[5];
        int auxMessageBytes = 5; // 5 for write
 
        /* Set up the command byte */
        auxMessage[2] = AUX_I2C_WRITE << 4;
-       if (end == false)
+       if (stop == false)
                auxMessage[2] |= AUX_I2C_MOT << 4;
 
        auxMessage[0] = address;
@@ -265,6 +272,12 @@ dp_aux_set_i2c_byte(uint32 hwPin, uint16 address, uint8* 
data, bool end)
        auxMessage[3] = auxMessageBytes << 4;
        auxMessage[4] = *data;
 
+       /* special case for sending the START or STOP */
+       if (start || stop) {
+               auxMessage[3] = 3 << 4;
+               auxMessageBytes = 4;
+       }
+
        int retry;
        for (retry = 0; retry < 4; retry++) {
                uint8 ack;
@@ -328,7 +341,7 @@ dp_get_lane_count(uint32 connectorIndex, display_mode* mode)
 
        size_t pixelChunk;
        size_t pixelsPerChunk;
-       status_t result = get_pixel_size_for((color_space)mode->space, 
&pixelChunk,
+       status_t result = dp_get_pixel_size_for((color_space)mode->space, 
&pixelChunk,
                NULL, &pixelsPerChunk);
 
        if (result != B_OK) {
@@ -367,7 +380,7 @@ dp_get_link_rate(uint32 connectorIndex, display_mode* mode)
 
        size_t pixelChunk;
        size_t pixelsPerChunk;
-       status_t result = get_pixel_size_for((color_space)mode->space, 
&pixelChunk,
+       status_t result = dp_get_pixel_size_for((color_space)mode->space, 
&pixelChunk,
                NULL, &pixelsPerChunk);
 
        if (result != B_OK) {
@@ -859,6 +872,74 @@ dp_link_train(uint32 connectorIndex, display_mode* mode)
 }
 
 
+status_t
+ddc2_dp_read_edid1(uint32 connectorIndex, edid1_info* edid)
+{
+       TRACE("%s\n", __func__);
+
+       dp_info* dpInfo = &gConnector[connectorIndex]->dpInfo;
+
+       if (!dpInfo->valid)
+               return B_ERROR;
+
+       edid1_raw raw;
+       uint8* rdata = (uint8_t*)&raw;
+       uint8 sdata = 0;
+
+       // The following sequence is from a trace of the Linux kernel
+       // radeon code; not sure if the initial writes to address 0 are
+       // requried.
+       dp_aux_set_i2c_byte(dpInfo->auxPin, 0x00, &sdata, true, false);
+       dp_aux_set_i2c_byte(dpInfo->auxPin, 0x00, &sdata, false, true);
+
+       dp_aux_set_i2c_byte(dpInfo->auxPin, 0x50, &sdata, true, false);
+       dp_aux_set_i2c_byte(dpInfo->auxPin, 0x50, &sdata, false, false);
+       dp_aux_get_i2c_byte(dpInfo->auxPin, 0x50, rdata, true, false);
+       dp_aux_get_i2c_byte(dpInfo->auxPin, 0x50, rdata, false, false);
+       dp_aux_get_i2c_byte(dpInfo->auxPin, 0x50, rdata, false, true);
+       dp_aux_set_i2c_byte(dpInfo->auxPin, 0x50, &sdata, true, false);
+       dp_aux_set_i2c_byte(dpInfo->auxPin, 0x50, &sdata, false, false);
+       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);
+                       dp_aux_get_i2c_byte(dpInfo->auxPin, 0x50, &sdata, 
false, true);
+                       return B_ERROR;
+               }
+       }
+       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;
+       }
+
+       edid_decode(edid, &raw);
+
+       return B_OK;
+}
+
+
+status_t
+dp_get_pixel_size_for(color_space space, size_t *pixelChunk,
+       size_t *rowAlignment, size_t *pixelsPerChunk)
+{
+       status_t result = get_pixel_size_for(space, pixelChunk, NULL,
+               pixelsPerChunk);
+
+       if ((space == B_RGB32) || (space == B_RGBA32) || (space == B_RGB32_BIG)
+               || (space == B_RGBA32_BIG)) {
+               *pixelChunk = 3;
+       }
+
+       return result;
+}
+
+
 void
 debug_dp_info()
 {
diff --git a/src/add-ons/accelerants/radeon_hd/displayport.h 
b/src/add-ons/accelerants/radeon_hd/displayport.h
index fa06dc6..ae484d0 100644
--- a/src/add-ons/accelerants/radeon_hd/displayport.h
+++ b/src/add-ons/accelerants/radeon_hd/displayport.h
@@ -1,9 +1,10 @@
 /*
- * Copyright 2011, Haiku, Inc. All Rights Reserved.
+ * Copyright 2011-2013, Haiku, Inc. All Rights Reserved.
  * Distributed under the terms of the MIT License.
  *
  * Authors:
  *             Alexander von Gluck IV, kallisti5@xxxxxxxxxxx
+ *             Bill Randle, billr@xxxxxxxxxx
  */
 #ifndef RADEON_HD_DISPLAYPORT_H
 #define RADEON_HD_DISPLAYPORT_H
@@ -30,9 +31,9 @@ int dp_aux_write(uint32 hwPin, uint16 address, uint8* send,
 int dp_aux_read(uint32 hwPin, uint16 address, uint8* recv,
        int recvBytes, uint8 delay);
 status_t dp_aux_set_i2c_byte(uint32 hwPin, uint16 address,
-       uint8* data, bool end);
+       uint8* data, bool start, bool stop);
 status_t dp_aux_get_i2c_byte(uint32 hwPin, uint16 address,
-       uint8* data, bool end);
+       uint8* data, bool start, bool stop);
 
 uint32 dp_get_link_rate(uint32 connectorIndex, display_mode* mode);
 uint32 dp_get_lane_count(uint32 connectorIndex, display_mode* mode);
@@ -45,4 +46,9 @@ status_t dp_link_train_ce(uint32 connectorIndex);
 
 void debug_dp_info();
 
-#endif /* RADEON_HD_DISPLAYPORT_H */
+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);
+
+
+#endif /* RADEON_HD_DISPLAYPORT_H */
\ No newline at end of file


Other related posts:

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