* complete pll_set for all AtomBIOS revisions

* add update of crtc encoder scratch registers
* rename id for more descriptive crtc_id
* encoder dpms, BL on/off on lcd


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@42828 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Alexander von Gluck IV
2011-10-12 17:24:15 +00:00
parent 14493b1ecb
commit 042bdcc0d2
3 changed files with 134 additions and 13 deletions
+69 -12
View File
@@ -37,7 +37,7 @@ union crtc_source_param {
void void
encoder_assign_crtc(uint8 id) encoder_assign_crtc(uint8 crtc_id)
{ {
int index = GetIndexIntoMasterTable(COMMAND, SelectCRTC_Source); int index = GetIndexIntoMasterTable(COMMAND, SelectCRTC_Source);
union crtc_source_param args; union crtc_source_param args;
@@ -50,7 +50,7 @@ encoder_assign_crtc(uint8 id)
!= B_OK) != B_OK)
return; return;
uint16 connector_index = gDisplay[id]->connector_index; uint16 connector_index = gDisplay[crtc_id]->connector_index;
uint16 encoder_id = gConnector[connector_index]->encoder.object_id; uint16 encoder_id = gConnector[connector_index]->encoder.object_id;
switch (frev) { switch (frev) {
@@ -58,7 +58,7 @@ encoder_assign_crtc(uint8 id)
switch (crev) { switch (crev) {
case 1: case 1:
default: default:
args.v1.ucCRTC = id; args.v1.ucCRTC = crtc_id;
switch (encoder_id) { switch (encoder_id) {
case ENCODER_OBJECT_ID_INTERNAL_TMDS1: case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
@@ -102,7 +102,7 @@ encoder_assign_crtc(uint8 id)
} }
break; break;
case 2: case 2:
args.v2.ucCRTC = id; args.v2.ucCRTC = crtc_id;
args.v2.ucEncodeMode args.v2.ucEncodeMode
= display_get_encoder_mode(connector_index); = display_get_encoder_mode(connector_index);
switch (encoder_id) { switch (encoder_id) {
@@ -168,7 +168,8 @@ encoder_assign_crtc(uint8 id)
atom_execute_table(gAtomContext, index, (uint32*)&args); atom_execute_table(gAtomContext, index, (uint32*)&args);
// TODO : encoder_crtc_scratch_regs? // update crtc encoder scratch register @ scratch 3
encoder_crtc_scratch(crtc_id);
} }
@@ -365,6 +366,55 @@ encoder_analog_setup(uint8 id, uint32 pixelClock, int command)
} }
void
encoder_crtc_scratch(uint8 crtc_id)
{
TRACE("%s\n", __func__);
uint32 connector_index = gDisplay[crtc_id]->connector_index;
uint32 encoder_flags = gConnector[connector_index]->encoder.flags;
// TODO : r500
uint32 bios_3_scratch = Read32(OUT, R600_BIOS_3_SCRATCH);
if (encoder_flags & ATOM_DEVICE_TV1_SUPPORT) {
bios_3_scratch &= ~ATOM_S3_TV1_CRTC_ACTIVE;
bios_3_scratch |= (crtc_id << 18);
}
if (encoder_flags & ATOM_DEVICE_CV_SUPPORT) {
bios_3_scratch &= ~ATOM_S3_CV_CRTC_ACTIVE;
bios_3_scratch |= (crtc_id << 24);
}
if (encoder_flags & ATOM_DEVICE_CRT1_SUPPORT) {
bios_3_scratch &= ~ATOM_S3_CRT1_CRTC_ACTIVE;
bios_3_scratch |= (crtc_id << 16);
}
if (encoder_flags & ATOM_DEVICE_CRT2_SUPPORT) {
bios_3_scratch &= ~ATOM_S3_CRT2_CRTC_ACTIVE;
bios_3_scratch |= (crtc_id << 20);
}
if (encoder_flags & ATOM_DEVICE_LCD1_SUPPORT) {
bios_3_scratch &= ~ATOM_S3_LCD1_CRTC_ACTIVE;
bios_3_scratch |= (crtc_id << 17);
}
if (encoder_flags & ATOM_DEVICE_DFP1_SUPPORT) {
bios_3_scratch &= ~ATOM_S3_DFP1_CRTC_ACTIVE;
bios_3_scratch |= (crtc_id << 19);
}
if (encoder_flags & ATOM_DEVICE_DFP2_SUPPORT) {
bios_3_scratch &= ~ATOM_S3_DFP2_CRTC_ACTIVE;
bios_3_scratch |= (crtc_id << 23);
}
if (encoder_flags & ATOM_DEVICE_DFP3_SUPPORT) {
bios_3_scratch &= ~ATOM_S3_DFP3_CRTC_ACTIVE;
bios_3_scratch |= (crtc_id << 25);
}
// TODO : r500
Write32(OUT, R600_BIOS_3_SCRATCH, bios_3_scratch);
}
void void
encoder_dpms_scratch(uint8 crtc_id, bool power) encoder_dpms_scratch(uint8 crtc_id, bool power)
{ {
@@ -448,6 +498,9 @@ encoder_dpms_set(uint8 crtc_id, uint8 encoder_id, int mode)
memset(&args, 0, sizeof(args)); memset(&args, 0, sizeof(args));
uint32 connector_index = gDisplay[crtc_id]->connector_index;
uint32 encoder_flags = gConnector[connector_index]->encoder.flags;
switch (encoder_id) { switch (encoder_id) {
case ENCODER_OBJECT_ID_INTERNAL_TMDS1: case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
@@ -474,9 +527,9 @@ encoder_dpms_set(uint8 crtc_id, uint8 encoder_id, int mode)
index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl); index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl);
break; break;
case ENCODER_OBJECT_ID_INTERNAL_LVTM1: case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
// TODO : Laptop LCD special cases dpms set if (encoder_flags & ATOM_DEVICE_LCD_SUPPORT)
// if ATOM_DEVICE_LCD_SUPPORT, LCD1OutputControl index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl);
// else... else
index = GetIndexIntoMasterTable(COMMAND, LVTMAOutputControl); index = GetIndexIntoMasterTable(COMMAND, LVTMAOutputControl);
break; break;
case ENCODER_OBJECT_ID_INTERNAL_DAC1: case ENCODER_OBJECT_ID_INTERNAL_DAC1:
@@ -503,8 +556,10 @@ encoder_dpms_set(uint8 crtc_id, uint8 encoder_id, int mode)
case B_DPMS_ON: case B_DPMS_ON:
args.ucAction = ATOM_ENABLE; args.ucAction = ATOM_ENABLE;
atom_execute_table(gAtomContext, index, (uint32*)&args); atom_execute_table(gAtomContext, index, (uint32*)&args);
// TODO : ATOM_DEVICE_LCD_SUPPORT : args.ucAction = ATOM_LCD_BLON; if (encoder_flags & ATOM_DEVICE_LCD_SUPPORT) {
// execute again args.ucAction = ATOM_LCD_BLON;
atom_execute_table(gAtomContext, index, (uint32*)&args);
}
encoder_dpms_scratch(crtc_id, true); encoder_dpms_scratch(crtc_id, true);
break; break;
case B_DPMS_STAND_BY: case B_DPMS_STAND_BY:
@@ -512,8 +567,10 @@ encoder_dpms_set(uint8 crtc_id, uint8 encoder_id, int mode)
case B_DPMS_OFF: case B_DPMS_OFF:
args.ucAction = ATOM_DISABLE; args.ucAction = ATOM_DISABLE;
atom_execute_table(gAtomContext, index, (uint32*)&args); atom_execute_table(gAtomContext, index, (uint32*)&args);
// TODO : ATOM_DEVICE_LCD_SUPPORT : args.ucAction = ATOM_LCD_BLOFF; if (encoder_flags & ATOM_DEVICE_LCD_SUPPORT) {
// execute again args.ucAction = ATOM_LCD_BLOFF;
atom_execute_table(gAtomContext, index, (uint32*)&args);
}
encoder_dpms_scratch(crtc_id, false); encoder_dpms_scratch(crtc_id, false);
break; break;
} }
@@ -14,6 +14,7 @@ void encoder_mode_set(uint8 id, uint32 pixelClock);
status_t encoder_digital_setup(uint8 id, uint32 pixelClock, int command); status_t encoder_digital_setup(uint8 id, uint32 pixelClock, int command);
status_t encoder_analog_setup(uint8 id, uint32 pixelClock, int command); status_t encoder_analog_setup(uint8 id, uint32 pixelClock, int command);
void encoder_output_lock(bool lock); void encoder_output_lock(bool lock);
void encoder_crtc_scratch(uint8 crtc_id);
void encoder_dpms_scratch(uint8 crtc_id, bool power); void encoder_dpms_scratch(uint8 crtc_id, bool power);
void encoder_dpms_set(uint8 crtc_id, uint8 encoder_id, int mode); void encoder_dpms_set(uint8 crtc_id, uint8 encoder_id, int mode);
+63
View File
@@ -267,12 +267,14 @@ pll_set(uint8 pll_id, uint32 pixelClock, uint8 crtc_id)
{ {
uint32 connector_index = gDisplay[crtc_id]->connector_index; uint32 connector_index = gDisplay[crtc_id]->connector_index;
pll_info *pll = &gConnector[connector_index]->encoder.pll; pll_info *pll = &gConnector[connector_index]->encoder.pll;
pll->pixel_clock = pixelClock; pll->pixel_clock = pixelClock;
pll->id = pll_id; pll->id = pll_id;
// get any needed clock adjustments, set reference/post dividers, set flags // get any needed clock adjustments, set reference/post dividers, set flags
uint32 adjustedClock = pll_adjust(pll, crtc_id); uint32 adjustedClock = pll_adjust(pll, crtc_id);
// compute dividers, set flags
pll_compute(pll); pll_compute(pll);
int index = GetIndexIntoMasterTable(COMMAND, SetPixelClock); int index = GetIndexIntoMasterTable(COMMAND, SetPixelClock);
@@ -283,6 +285,10 @@ pll_set(uint8 pll_id, uint32 pixelClock, uint8 crtc_id)
uint8 crev; uint8 crev;
atom_parse_cmd_header(gAtomContext, index, &frev, &crev); atom_parse_cmd_header(gAtomContext, index, &frev, &crev);
uint32 bpc = 8;
// TODO : BPC == Digital Depth, EDID 1.4+ on digital displays
// isn't in Haiku edid common code?
switch (crev) { switch (crev) {
case 1: case 1:
args.v1.usPixelClock = B_HOST_TO_LENDIAN_INT16(adjustedClock / 10); args.v1.usPixelClock = B_HOST_TO_LENDIAN_INT16(adjustedClock / 10);
@@ -318,6 +324,63 @@ pll_set(uint8 pll_id, uint32 pixelClock, uint8 crtc_id)
= gConnector[connector_index]->encoder.object_id; = gConnector[connector_index]->encoder.object_id;
args.v3.ucEncoderMode = display_get_encoder_mode(connector_index); args.v3.ucEncoderMode = display_get_encoder_mode(connector_index);
break; break;
case 5:
args.v5.ucCRTC = crtc_id;
args.v5.usPixelClock = B_HOST_TO_LENDIAN_INT16(adjustedClock / 10);
args.v5.ucRefDiv = pll->reference_div;
args.v5.usFbDiv = B_HOST_TO_LENDIAN_INT16(pll->feedback_div);
args.v5.ulFbDivDecFrac
= B_HOST_TO_LENDIAN_INT32(pll->feedback_div_frac * 100000);
args.v5.ucPostDiv = pll->post_div;
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 (bpc) {
case 8:
default:
args.v5.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_HDMI_24BPP;
break;
case 10:
args.v5.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_HDMI_30BPP;
break;
}
args.v5.ucTransmitterID
= gConnector[connector_index]->encoder.object_id;
args.v5.ucEncoderMode
= display_get_encoder_mode(connector_index);
args.v5.ucPpll = pll_id;
break;
case 6:
args.v6.ulDispEngClkFreq
= B_HOST_TO_LENDIAN_INT32(crtc_id << 24 | adjustedClock / 10);
args.v6.ucRefDiv = pll->reference_div;
args.v6.usFbDiv = B_HOST_TO_LENDIAN_INT16(pll->feedback_div);
args.v6.ulFbDivDecFrac
= B_HOST_TO_LENDIAN_INT32(pll->feedback_div_frac * 100000);
args.v6.ucPostDiv = pll->post_div;
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 (bpc) {
case 8:
default:
args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_24BPP;
break;
case 10:
args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_30BPP;
break;
case 12:
args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_36BPP;
break;
case 16:
args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_48BPP;
break;
}
args.v6.ucTransmitterID
= gConnector[connector_index]->encoder.object_id;
args.v6.ucEncoderMode = display_get_encoder_mode(connector_index);
args.v6.ucPpll = pll_id;
break;
default: default:
TRACE("%s: ERROR: table version %d.%d TODO\n", __func__, TRACE("%s: ERROR: table version %d.%d TODO\n", __func__,
frev, crev); frev, crev);