Working towards DP connector support
* Lots of new DisplayPort functions * Call DP link training during mode set * Rename dp_info variables to be less redundant * Make encoder_pick_dig accept connector ID and then check parent display * Encode/Decode DP link speed functions * Calculate DP lanes * Rewrite encoder_dig_setup * Correct bitsPerChannel to bitsPerColor * My TRAVIS DisplayPort -> LVDS bridge now works
This commit is contained in:
@@ -130,10 +130,10 @@ typedef struct {
|
||||
typedef struct {
|
||||
bool valid;
|
||||
|
||||
uint8 dpConfig[8]; // DP configuration data
|
||||
uint8 dpSinkType;
|
||||
uint8 dpClock;
|
||||
int dpLaneCount;
|
||||
uint8 config[8]; // DP configuration data
|
||||
uint8 sinkType;
|
||||
uint8 clock;
|
||||
int laneCount;
|
||||
bool eDPOn;
|
||||
} dp_info;
|
||||
|
||||
|
||||
@@ -713,6 +713,18 @@ connector_probe()
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
connector_is_dp(uint32 connectorIndex)
|
||||
{
|
||||
if (gConnector[connectorIndex]->type == VIDEO_CONNECTOR_DP
|
||||
|| gConnector[connectorIndex]->type != VIDEO_CONNECTOR_EDP
|
||||
|| gConnector[connectorIndex]->encoder.isDPBridge == false) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
debug_connectors()
|
||||
{
|
||||
|
||||
@@ -65,6 +65,7 @@ status_t connector_attach_gpio(uint32 id, uint8 hwPin);
|
||||
bool connector_read_edid(uint32 connector, edid1_info* edid);
|
||||
status_t connector_probe();
|
||||
status_t connector_probe_legacy();
|
||||
bool connector_is_dp(uint32 connectorIndex);
|
||||
void debug_connectors();
|
||||
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
#include "accelerant.h"
|
||||
#include "accelerant_protos.h"
|
||||
#include "displayport_reg.h"
|
||||
#include "connector.h"
|
||||
|
||||
|
||||
#undef TRACE
|
||||
@@ -333,6 +333,58 @@ dp_get_link_clock(uint32 connectorIndex)
|
||||
}
|
||||
|
||||
|
||||
uint32
|
||||
dp_get_link_clock_encode(uint32 dpLinkClock)
|
||||
{
|
||||
switch (dpLinkClock) {
|
||||
case 270000:
|
||||
return DP_LINK_BW_2_7;
|
||||
case 540000:
|
||||
return DP_LINK_BW_5_4;
|
||||
}
|
||||
|
||||
return DP_LINK_BW_1_62;
|
||||
}
|
||||
|
||||
|
||||
uint32
|
||||
dp_get_link_clock_decode(uint32 dpLinkClock)
|
||||
{
|
||||
switch (dpLinkClock) {
|
||||
case DP_LINK_BW_2_7:
|
||||
return 270000;
|
||||
case DP_LINK_BW_5_4:
|
||||
return 540000;
|
||||
}
|
||||
return 162000;
|
||||
}
|
||||
|
||||
|
||||
static uint32
|
||||
dp_get_lane_count(uint32 connectorIndex, uint32 pixelClock)
|
||||
{
|
||||
// TODO: bpp hardcoded
|
||||
uint32 bitsPerPixel = 32;
|
||||
|
||||
uint32 maxLaneCount = gDPInfo[connectorIndex]->config[DP_MAX_LANE_COUNT]
|
||||
& DP_MAX_LANE_COUNT_MASK;
|
||||
|
||||
uint32 maxLinkRate = dp_get_link_clock_decode(
|
||||
gDPInfo[connectorIndex]->config[DP_MAX_LINK_RATE]);
|
||||
|
||||
uint32 lane;
|
||||
for (lane = 1; lane < maxLaneCount; lane <<= 1) {
|
||||
uint32 maxDPPixelClock = (maxLinkRate * lane * 8) / bitsPerPixel;
|
||||
if (pixelClock <= maxDPPixelClock)
|
||||
break;
|
||||
}
|
||||
TRACE("%s: connector: %" B_PRIu32 ", lanes: %" B_PRIu32 "\n", __func__,
|
||||
connectorIndex, lane);
|
||||
|
||||
return lane;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
dp_setup_connectors()
|
||||
{
|
||||
@@ -341,14 +393,12 @@ dp_setup_connectors()
|
||||
for (uint32 index = 0; index < ATOM_MAX_SUPPORTED_DEVICE; index++) {
|
||||
gDPInfo[index]->valid = false;
|
||||
if (gConnector[index]->valid == false) {
|
||||
gDPInfo[index]->dpConfig[0] = 0;
|
||||
gDPInfo[index]->config[0] = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (gConnector[index]->type != VIDEO_CONNECTOR_DP
|
||||
&& gConnector[index]->type != VIDEO_CONNECTOR_EDP
|
||||
&& gConnector[index]->encoder.isDPBridge == false) {
|
||||
gDPInfo[index]->dpConfig[0] = 0;
|
||||
if (connector_is_dp(index) == false) {
|
||||
gDPInfo[index]->config[0] = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -357,23 +407,18 @@ dp_setup_connectors()
|
||||
|
||||
uint8 auxMessage[25];
|
||||
int result;
|
||||
int i;
|
||||
|
||||
result = dp_aux_read(hwPin, DP_DPCD_REV, auxMessage, 8, 0);
|
||||
if (result > 0) {
|
||||
memcpy(gDPInfo[index]->dpConfig, auxMessage, 8);
|
||||
TRACE("%s: connector #%" B_PRIu32 " DP Config:\n", __func__, index);
|
||||
for (i = 0; i < 8; i++)
|
||||
TRACE("%s: %02x\n", __func__, auxMessage[i]);
|
||||
|
||||
gDPInfo[index]->valid = true;
|
||||
memcpy(gDPInfo[index]->config, auxMessage, 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
dp_link_train(uint8 crtcID)
|
||||
dp_link_train(uint8 crtcID, display_mode* mode)
|
||||
{
|
||||
TRACE("%s\n", __func__);
|
||||
|
||||
@@ -384,6 +429,10 @@ dp_link_train(uint8 crtcID)
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
gDPInfo[connectorIndex]->clock = dp_get_link_clock(connectorIndex);
|
||||
gDPInfo[connectorIndex]->laneCount
|
||||
= dp_get_lane_count(connectorIndex, mode->timing.pixel_clock);
|
||||
|
||||
int index = GetIndexIntoMasterTable(COMMAND, DPEncoderService);
|
||||
// Table version
|
||||
uint8 tableMajor;
|
||||
@@ -405,7 +454,7 @@ dp_link_train(uint8 crtcID)
|
||||
uint32 hwPin = gGPIOInfo[gpioID]->hwPin;
|
||||
|
||||
uint32 dpEncoderID = 0;
|
||||
if (encoder_pick_dig(crtcID) > 0)
|
||||
if (encoder_pick_dig(connectorIndex) > 0)
|
||||
dpEncoderID |= ATOM_DP_CONFIG_DIG2_ENCODER;
|
||||
else
|
||||
dpEncoderID |= ATOM_DP_CONFIG_DIG1_ENCODER;
|
||||
@@ -415,22 +464,66 @@ dp_link_train(uint8 crtcID)
|
||||
dpEncoderID |= ATOM_DP_CONFIG_LINK_A;
|
||||
|
||||
//uint8 dpReadInterval = dpcd_reg_read(hwPin, DP_TRAINING_AUX_RD_INTERVAL);
|
||||
uint8 dpMaxLanes = dpcd_reg_read(hwPin, DP_MAX_LANE_COUNT);
|
||||
uint8 sandbox = dpcd_reg_read(hwPin, DP_MAX_LANE_COUNT);
|
||||
|
||||
radeon_shared_info &info = *gInfo->shared_info;
|
||||
bool dpTPS3Supported = false;
|
||||
if (info.dceMajor >= 5 && (dpMaxLanes & DP_TPS3_SUPPORTED) != 0)
|
||||
if (info.dceMajor >= 5 && (sandbox & DP_TPS3_SUPPORTED) != 0)
|
||||
dpTPS3Supported = true;
|
||||
|
||||
// power up the DP sink
|
||||
if (gDPInfo[connectorIndex]->dpConfig[0] >= 0x11)
|
||||
// DisplayPort training initialization
|
||||
|
||||
// Power up the DP sink
|
||||
if (gDPInfo[connectorIndex]->config[0] >= 0x11)
|
||||
dpcd_reg_write(hwPin, DP_SET_POWER, DP_SET_POWER_D0);
|
||||
|
||||
// possibly enable downspread on the sink
|
||||
if (gDPInfo[connectorIndex]->dpConfig[3] & 0x1)
|
||||
// Possibly enable downspread on the sink
|
||||
if ((gDPInfo[connectorIndex]->config[3] & 0x1) != 0)
|
||||
dpcd_reg_write(hwPin, DP_DOWNSPREAD_CTRL, DP_SPREAD_AMP_0_5);
|
||||
else
|
||||
dpcd_reg_write(hwPin, DP_DOWNSPREAD_CTRL, 0);
|
||||
|
||||
encoder_dig_setup(connectorIndex, 0,
|
||||
ATOM_ENCODER_CMD_SETUP_PANEL_MODE);
|
||||
|
||||
if (gDPInfo[connectorIndex]->config[0] >= 0x11)
|
||||
sandbox |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
|
||||
dpcd_reg_write(hwPin, DP_LANE_COUNT_SET, sandbox);
|
||||
|
||||
// Set the link rate on the DP sink
|
||||
sandbox = dp_get_link_clock_encode(gDPInfo[connectorIndex]->clock);
|
||||
dpcd_reg_write(hwPin, DP_LINK_BW_SET, sandbox);
|
||||
|
||||
// Start link training on source
|
||||
if (info.dceMajor >= 4 || !dpUseEncoder) {
|
||||
encoder_dig_setup(connectorIndex, 0,
|
||||
ATOM_ENCODER_CMD_DP_LINK_TRAINING_START);
|
||||
} else {
|
||||
ERROR("%s: TODO: cannot use AtomBIOS DPEncoderService on card!\n",
|
||||
__func__);
|
||||
}
|
||||
|
||||
/* disable the training pattern on the sink */
|
||||
dpcd_reg_write(hwPin, DP_TRAINING_PATTERN_SET,
|
||||
DP_TRAINING_PATTERN_DISABLE);
|
||||
|
||||
// TODO: dp_link_train_cr
|
||||
// TODO: dp_link_train_ce
|
||||
|
||||
snooze(400);
|
||||
|
||||
/* disable the training pattern on the sink */
|
||||
dpcd_reg_write(hwPin, DP_TRAINING_PATTERN_SET,
|
||||
DP_TRAINING_PATTERN_DISABLE);
|
||||
|
||||
/* disable the training pattern on the source */
|
||||
if (info.dceMajor >= 4 || !dpUseEncoder) {
|
||||
encoder_dig_setup(connectorIndex, 0,
|
||||
ATOM_ENCODER_CMD_DP_LINK_TRAINING_COMPLETE);
|
||||
} else {
|
||||
ERROR("%s: TODO: cannot use AtomBIOS DPEncoderService on card!\n",
|
||||
__func__);
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@@ -9,9 +9,12 @@
|
||||
#define RADEON_HD_DISPLAYPORT_H
|
||||
|
||||
|
||||
#include <create_display_modes.h>
|
||||
#include <stdint.h>
|
||||
#include <SupportDefs.h>
|
||||
|
||||
#include "displayport_reg.h"
|
||||
|
||||
|
||||
int dp_aux_write(uint32 hwPin, uint16 address, uint8* send,
|
||||
uint8 sendBytes, uint8 delay);
|
||||
@@ -23,8 +26,11 @@ status_t dp_aux_get_i2c_byte(uint32 hwPin, uint16 address,
|
||||
uint8* data, bool end);
|
||||
|
||||
uint32 dp_get_link_clock(uint32 connectorIndex);
|
||||
uint32 dp_get_link_clock_encode(uint32 dpLinkClock);
|
||||
uint32 dp_get_link_clock_decode(uint32 dpLinkClock);
|
||||
|
||||
void dp_setup_connectors();
|
||||
status_t dp_link_train(uint32 connectorIndex);
|
||||
status_t dp_link_train(uint8 crtcID, display_mode* mode);
|
||||
|
||||
|
||||
#endif /* RADEON_HD_DISPLAYPORT_H */
|
||||
|
||||
@@ -17,7 +17,9 @@
|
||||
#include "accelerant.h"
|
||||
#include "accelerant_protos.h"
|
||||
#include "bios.h"
|
||||
#include "connector.h"
|
||||
#include "display.h"
|
||||
#include "displayport.h"
|
||||
#include "utility.h"
|
||||
|
||||
|
||||
@@ -113,7 +115,7 @@ encoder_assign_crtc(uint8 crtcID)
|
||||
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
|
||||
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
|
||||
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
|
||||
switch (encoder_pick_dig(crtcID)) {
|
||||
switch (encoder_pick_dig(connectorIndex)) {
|
||||
case 0:
|
||||
args.v2.ucEncoderID
|
||||
= ASIC_INT_DIG1_ENCODER_ID;
|
||||
@@ -178,13 +180,21 @@ encoder_assign_crtc(uint8 crtcID)
|
||||
|
||||
|
||||
uint32
|
||||
encoder_pick_dig(uint8 crtcID)
|
||||
encoder_pick_dig(uint32 connectorIndex)
|
||||
{
|
||||
TRACE("%s\n", __func__);
|
||||
radeon_shared_info &info = *gInfo->shared_info;
|
||||
uint32 connectorIndex = gDisplay[crtcID]->connectorIndex;
|
||||
uint32 encoderID = gConnector[connectorIndex]->encoder.objectID;
|
||||
|
||||
// obtain assigned CRT
|
||||
uint32 crtcID;
|
||||
for (crtcID = 0; crtcID < MAX_DISPLAY; crtcID++) {
|
||||
if (gDisplay[crtcID]->active != true)
|
||||
continue;
|
||||
if (gDisplay[crtcID]->connectorIndex == connectorIndex)
|
||||
break;
|
||||
}
|
||||
|
||||
bool linkB = gConnector[connectorIndex]->encoder.linkEnumeration
|
||||
== GRAPH_OBJECT_ENUM_ID2 ? true : false;
|
||||
|
||||
@@ -405,6 +415,9 @@ encoder_digital_setup(uint32 connectorIndex, uint32 pixelClock, int command)
|
||||
union lvdsEncoderControl args;
|
||||
memset(&args, 0, sizeof(args));
|
||||
|
||||
TRACE("%s: table %" B_PRIu8 ".%" B_PRIu8 "\n", __func__,
|
||||
tableMajor, tableMinor);
|
||||
|
||||
switch (tableMajor) {
|
||||
case 1:
|
||||
case 2:
|
||||
@@ -499,10 +512,10 @@ encoder_dig_setup(uint32 connectorIndex, uint32 pixelClock, int command)
|
||||
if (info.dceMajor > 4)
|
||||
index = GetIndexIntoMasterTable(COMMAND, DIGxEncoderControl);
|
||||
else {
|
||||
if (1) // TODO: pick dig encoder
|
||||
index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl);
|
||||
else
|
||||
if (encoder_pick_dig(connectorIndex))
|
||||
index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl);
|
||||
else
|
||||
index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl);
|
||||
}
|
||||
|
||||
// Table verson
|
||||
@@ -525,124 +538,140 @@ encoder_dig_setup(uint32 connectorIndex, uint32 pixelClock, int command)
|
||||
union digEncoderControl args;
|
||||
memset(&args, 0, sizeof(args));
|
||||
|
||||
args.v1.ucAction = command;
|
||||
args.v1.usPixelClock = B_HOST_TO_LENDIAN_INT16(pixelClock / 10);
|
||||
|
||||
uint32 encoderID = gConnector[connectorIndex]->encoder.objectID;
|
||||
bool isDPBridge = gConnector[connectorIndex]->encoder.isDPBridge;
|
||||
|
||||
bool linkB = gConnector[connectorIndex]->encoder.linkEnumeration
|
||||
== GRAPH_OBJECT_ENUM_ID2 ? true : false;
|
||||
|
||||
// determine DP panel mode
|
||||
uint32 panelMode;
|
||||
if (info.dceMajor >= 4 && isDPBridge) {
|
||||
if (encoderID == ENCODER_OBJECT_ID_NUTMEG)
|
||||
panelMode = DP_PANEL_MODE_INTERNAL_DP1_MODE;
|
||||
else {
|
||||
// aka ENCODER_OBJECT_ID_TRAVIS or VIDEO_CONNECTOR_EDP
|
||||
panelMode = DP_PANEL_MODE_INTERNAL_DP2_MODE;
|
||||
}
|
||||
} else
|
||||
panelMode = DP_PANEL_MODE_EXTERNAL_DP_MODE;
|
||||
|
||||
#if 0
|
||||
if (command == ATOM_ENCODER_CMD_SETUP_PANEL_MODE) {
|
||||
if (info.dceMajor >= 4 && 0) // TODO: 0 == if DP bridge
|
||||
args.v3.ucPanelMode = DP_PANEL_MODE_INTERNAL_DP1_MODE;
|
||||
else
|
||||
args.v3.ucPanelMode = DP_PANEL_MODE_EXTERNAL_DP_MODE;
|
||||
} else {
|
||||
args.v1.ucEncoderMode = display_get_encoder_mode(connectorIndex);
|
||||
|
||||
if (args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP
|
||||
|| args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP_MST) {
|
||||
args.v1.ucLaneNum = dp_lane_count;
|
||||
} else if (pixelClock > 165000)
|
||||
args.v1.ucLaneNum = 8;
|
||||
else
|
||||
args.v1.ucLaneNum = 4;
|
||||
|
||||
if (info.dceMajor >= 5) {
|
||||
if (args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP
|
||||
|| args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP_MST) {
|
||||
if (dpClock == 270000) {
|
||||
args.v1.ucConfig
|
||||
|= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_2_70GHZ;
|
||||
} else if (dpClock == 540000) {
|
||||
args.v1.ucConfig
|
||||
|= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_5_40GHZ;
|
||||
}
|
||||
}
|
||||
args.v4.acConfig.ucDigSel = dig->dig_encoder;
|
||||
switch (bpc) {
|
||||
case 0:
|
||||
args.v4.ucBitPerColor = PANEL_BPC_UNDEFINE;
|
||||
break;
|
||||
case 6:
|
||||
args.v4.ucBitPerColor = PANEL_6BIT_PER_COLOR;
|
||||
break;
|
||||
case 8:
|
||||
default:
|
||||
args.v4.ucBitPerColor = PANEL_8BIT_PER_COLOR;
|
||||
break;
|
||||
case 10:
|
||||
args.v4.ucBitPerColor = PANEL_10BIT_PER_COLOR;
|
||||
break;
|
||||
case 12:
|
||||
args.v4.ucBitPerColor = PANEL_12BIT_PER_COLOR;
|
||||
break;
|
||||
case 16:
|
||||
args.v4.ucBitPerColor = PANEL_16BIT_PER_COLOR;
|
||||
break;
|
||||
}
|
||||
|
||||
//if (hpdID == RADEON_HPD_NONE)
|
||||
if (1)
|
||||
args.v4.ucHPD_ID = 0;
|
||||
else
|
||||
args.v4.ucHPD_ID = hpd_id + 1;
|
||||
|
||||
} else if (info.dceMajor >= 4) {
|
||||
if (args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP
|
||||
&& dp_clock == 270000) {
|
||||
args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V3_DPLINKRATE_2_70GHZ;
|
||||
}
|
||||
|
||||
args.v3.acConfig.ucDigSel = dig->dig_encoder;
|
||||
switch (bpc) {
|
||||
case 0:
|
||||
args.v3.ucBitPerColor = PANEL_BPC_UNDEFINE;
|
||||
break;
|
||||
case 6:
|
||||
args.v3.ucBitPerColor = PANEL_6BIT_PER_COLOR;
|
||||
break;
|
||||
case 8:
|
||||
default:
|
||||
args.v3.ucBitPerColor = PANEL_8BIT_PER_COLOR;
|
||||
break;
|
||||
case 10:
|
||||
args.v3.ucBitPerColor = PANEL_10BIT_PER_COLOR;
|
||||
break;
|
||||
case 12:
|
||||
args.v3.ucBitPerColor = PANEL_12BIT_PER_COLOR;
|
||||
break;
|
||||
case 16:
|
||||
args.v3.ucBitPerColor = PANEL_16BIT_PER_COLOR;
|
||||
break;
|
||||
}
|
||||
|
||||
} else {
|
||||
if (args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP
|
||||
&& dp_clock == 270000) {
|
||||
args.v1.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ;
|
||||
}
|
||||
#endif
|
||||
switch (encoderID) {
|
||||
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
|
||||
args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER1;
|
||||
break;
|
||||
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
|
||||
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
|
||||
args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER2;
|
||||
break;
|
||||
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
|
||||
args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER3;
|
||||
break;
|
||||
}
|
||||
#if 0
|
||||
if (dig->linkb)
|
||||
args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKB;
|
||||
else
|
||||
args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKA;
|
||||
uint32 encoderID = gConnector[connectorIndex]->encoder.objectID;
|
||||
if (gConnector[connectorIndex]->type == VIDEO_CONNECTOR_EDP) {
|
||||
uint8 temp = dpcd_read_reg(hwPin, DP_EDP_CONFIGURATION_CAP);
|
||||
if ((temp & 1) != 0)
|
||||
panelMode = DP_PANEL_MODE_INTERNAL_DP2_MODE;
|
||||
}
|
||||
#endif
|
||||
|
||||
return atom_execute_table(gAtomContext, index, (uint32*)&args);
|
||||
TRACE("%s: table %" B_PRIu8 ".%" B_PRIu8 "\n", __func__,
|
||||
tableMajor, tableMinor);
|
||||
|
||||
uint32 dpClock = dp_get_link_clock(connectorIndex);
|
||||
switch (tableMinor) {
|
||||
case 1:
|
||||
args.v1.ucAction = command;
|
||||
args.v1.usPixelClock = B_HOST_TO_LENDIAN_INT16(pixelClock / 10);
|
||||
|
||||
if (command == ATOM_ENCODER_CMD_SETUP_PANEL_MODE)
|
||||
args.v3.ucPanelMode = panelMode;
|
||||
else {
|
||||
args.v1.ucEncoderMode
|
||||
= display_get_encoder_mode(connectorIndex);
|
||||
}
|
||||
|
||||
if ((args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP
|
||||
|| args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP_MST)
|
||||
&& dpClock == 270000) {
|
||||
args.v1.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ;
|
||||
}
|
||||
|
||||
switch (encoderID) {
|
||||
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
|
||||
args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER1;
|
||||
break;
|
||||
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
|
||||
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
|
||||
args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER2;
|
||||
break;
|
||||
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
|
||||
args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER3;
|
||||
break;
|
||||
}
|
||||
|
||||
if (linkB)
|
||||
args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKB;
|
||||
else
|
||||
args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKA;
|
||||
break;
|
||||
case 2:
|
||||
case 3:
|
||||
args.v1.ucAction = command;
|
||||
args.v1.usPixelClock = B_HOST_TO_LENDIAN_INT16(pixelClock / 10);
|
||||
|
||||
if (command == ATOM_ENCODER_CMD_SETUP_PANEL_MODE)
|
||||
args.v3.ucPanelMode = panelMode;
|
||||
else {
|
||||
args.v3.ucEncoderMode
|
||||
= display_get_encoder_mode(connectorIndex);
|
||||
}
|
||||
|
||||
if (args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP
|
||||
|| args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP_MST) {
|
||||
args.v1.ucLaneNum = gDPInfo[connectorIndex]->laneCount;
|
||||
} else if (pixelClock > 165000)
|
||||
args.v1.ucLaneNum = 8;
|
||||
else
|
||||
args.v1.ucLaneNum = 4;
|
||||
|
||||
if ((args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP
|
||||
|| args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP_MST)
|
||||
&& dpClock == 270000) {
|
||||
args.v1.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ;
|
||||
}
|
||||
|
||||
args.v3.acConfig.ucDigSel = encoder_pick_dig(connectorIndex);
|
||||
|
||||
// TODO: get BPC
|
||||
switch (8) {
|
||||
case 0:
|
||||
args.v4.ucBitPerColor = PANEL_BPC_UNDEFINE;
|
||||
break;
|
||||
case 6:
|
||||
args.v4.ucBitPerColor = PANEL_6BIT_PER_COLOR;
|
||||
break;
|
||||
case 8:
|
||||
default:
|
||||
args.v4.ucBitPerColor = PANEL_8BIT_PER_COLOR;
|
||||
break;
|
||||
case 10:
|
||||
args.v4.ucBitPerColor = PANEL_10BIT_PER_COLOR;
|
||||
break;
|
||||
case 12:
|
||||
args.v4.ucBitPerColor = PANEL_12BIT_PER_COLOR;
|
||||
break;
|
||||
case 16:
|
||||
args.v4.ucBitPerColor = PANEL_16BIT_PER_COLOR;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
args.v4.ucHPD_ID = 0;
|
||||
ERROR("%s: tableMinor 4 TODO!\n", __func__);
|
||||
break;
|
||||
}
|
||||
|
||||
status_t result = atom_execute_table(gAtomContext, index, (uint32*)&args);
|
||||
|
||||
#if 0
|
||||
if (gConnector[connectorIndex]->type == VIDEO_CONNECTOR_EDP
|
||||
&& panelMode == DP_PANEL_MODE_INTERNAL_DP2_MODE) {
|
||||
dpcd_write_reg(hwPin, DP_EDP_CONFIGURATION_SET, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -673,6 +702,8 @@ encoder_external_setup(uint32 connectorIndex, uint32 pixelClock, int command)
|
||||
= (gConnector[connectorIndex]->objectID & OBJECT_ID_MASK)
|
||||
>> OBJECT_ID_SHIFT;
|
||||
|
||||
TRACE("%s: table %" B_PRIu8 ".%" B_PRIu8 "\n", __func__,
|
||||
tableMajor, tableMinor);
|
||||
switch (tableMajor) {
|
||||
case 1:
|
||||
// no options needed on table 1.x
|
||||
@@ -1053,7 +1084,7 @@ encoder_dpms_scratch(uint8 crtcID, bool power)
|
||||
void
|
||||
encoder_dpms_set(uint8 crtcID, uint8 encoderID, int mode)
|
||||
{
|
||||
int index = 0;
|
||||
int index = -1;
|
||||
radeon_shared_info &info = *gInfo->shared_info;
|
||||
|
||||
DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION args;
|
||||
@@ -1116,29 +1147,25 @@ encoder_dpms_set(uint8 crtcID, uint8 encoderID, int mode)
|
||||
switch (mode) {
|
||||
case B_DPMS_ON:
|
||||
args.ucAction = ATOM_ENABLE;
|
||||
atom_execute_table(gAtomContext, index, (uint32*)&args);
|
||||
if (info.dceMajor < 5) {
|
||||
if ((encoderFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) {
|
||||
args.ucAction = ATOM_LCD_BLON;
|
||||
atom_execute_table(gAtomContext, index, (uint32*)&args);
|
||||
}
|
||||
encoder_dpms_scratch(crtcID, true);
|
||||
}
|
||||
break;
|
||||
case B_DPMS_STAND_BY:
|
||||
case B_DPMS_SUSPEND:
|
||||
case B_DPMS_OFF:
|
||||
args.ucAction = ATOM_DISABLE;
|
||||
atom_execute_table(gAtomContext, index, (uint32*)&args);
|
||||
if (info.dceMajor < 5) {
|
||||
if ((encoderFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) {
|
||||
args.ucAction = ATOM_LCD_BLOFF;
|
||||
atom_execute_table(gAtomContext, index, (uint32*)&args);
|
||||
}
|
||||
encoder_dpms_scratch(crtcID, false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (index >= 0) {
|
||||
atom_execute_table(gAtomContext, index, (uint32*)&args);
|
||||
if (info.dceMajor < 5) {
|
||||
if ((encoderFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) {
|
||||
args.ucAction = args.ucAction == ATOM_DISABLE
|
||||
? ATOM_LCD_BLOFF : ATOM_LCD_BLON;
|
||||
atom_execute_table(gAtomContext, index, (uint32*)&args);
|
||||
}
|
||||
encoder_dpms_scratch(crtcID, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
|
||||
void encoder_assign_crtc(uint8 crtcID);
|
||||
uint32 encoder_pick_dig(uint8 crtcID);
|
||||
uint32 encoder_pick_dig(uint32 connectorIndex);
|
||||
|
||||
void encoder_apply_quirks(uint8 crtcID);
|
||||
void encoder_mode_set(uint8 id, uint32 pixelClock);
|
||||
|
||||
@@ -21,7 +21,9 @@
|
||||
#include "accelerant.h"
|
||||
#include "accelerant_protos.h"
|
||||
#include "bios.h"
|
||||
#include "connector.h"
|
||||
#include "display.h"
|
||||
#include "displayport.h"
|
||||
#include "encoder.h"
|
||||
#include "pll.h"
|
||||
#include "utility.h"
|
||||
@@ -204,8 +206,23 @@ radeon_set_display_mode(display_mode* mode)
|
||||
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(id, mode);
|
||||
|
||||
if (info.dceMajor >= 4)
|
||||
encoder_dig_setup(connectorIndex,
|
||||
ATOM_ENCODER_CMD_DP_VIDEO_ON, 0);
|
||||
}
|
||||
|
||||
encoder_dpms_set(id, gConnector[connectorIndex]->encoder.objectID,
|
||||
B_DPMS_ON);
|
||||
|
||||
encoder_output_lock(false);
|
||||
}
|
||||
|
||||
|
||||
@@ -492,7 +492,7 @@ pll_set(uint8 pllID, uint32 pixelClock, uint8 crtcID)
|
||||
int index = GetIndexIntoMasterTable(COMMAND, SetPixelClock);
|
||||
atom_parse_cmd_header(gAtomContext, index, &tableMajor, &tableMinor);
|
||||
|
||||
uint32 bitsPerChannel = 8;
|
||||
uint32 bitsPerColor = 8;
|
||||
// TODO: Digital Depth, EDID 1.4+ on digital displays
|
||||
// isn't in Haiku edid common code?
|
||||
|
||||
@@ -558,7 +558,7 @@ pll_set(uint8 pllID, uint32 pixelClock, uint8 crtcID)
|
||||
args.v5.ucMiscInfo = 0; /* HDMI depth, etc. */
|
||||
// if (ss_enabled && (ss->type & ATOM_EXTERNAL_SS_MASK))
|
||||
// args.v5.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_REF_DIV_SRC;
|
||||
switch (bitsPerChannel) {
|
||||
switch (bitsPerColor) {
|
||||
case 8:
|
||||
default:
|
||||
args.v5.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_HDMI_24BPP;
|
||||
@@ -584,7 +584,7 @@ pll_set(uint8 pllID, uint32 pixelClock, uint8 crtcID)
|
||||
args.v6.ucMiscInfo = 0; /* HDMI depth, etc. */
|
||||
// if (ss_enabled && (ss->type & ATOM_EXTERNAL_SS_MASK))
|
||||
// args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_REF_DIV_SRC;
|
||||
switch (bitsPerChannel) {
|
||||
switch (bitsPerColor) {
|
||||
case 8:
|
||||
default:
|
||||
args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_24BPP;
|
||||
|
||||
Reference in New Issue
Block a user