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)
This commit is contained in:
parent
7d9c1f30f1
commit
00bc40ad58
@ -172,6 +172,7 @@ typedef struct {
|
||||
uint32 hfreqMin;
|
||||
edid1_info edidData;
|
||||
display_mode preferredMode;
|
||||
display_mode currentMode;
|
||||
} display_info;
|
||||
|
||||
|
||||
|
@ -3,7 +3,8 @@
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Alexander von Gluck, kallisti5@unixzen.com
|
||||
* Alexander von Gluck, kallisti5@unixzen.com
|
||||
* Bill Randle, billr@neocat.org
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -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);
|
||||
@ -588,12 +616,121 @@ 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
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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 */
|
||||
#endif /* RADEON_HD_DISPLAYPORT_H */
|
||||
|
@ -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) {
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user