* 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
+70 -13
View File
@@ -37,7 +37,7 @@ union crtc_source_param {
void
encoder_assign_crtc(uint8 id)
encoder_assign_crtc(uint8 crtc_id)
{
int index = GetIndexIntoMasterTable(COMMAND, SelectCRTC_Source);
union crtc_source_param args;
@@ -50,7 +50,7 @@ encoder_assign_crtc(uint8 id)
!= B_OK)
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;
switch (frev) {
@@ -58,7 +58,7 @@ encoder_assign_crtc(uint8 id)
switch (crev) {
case 1:
default:
args.v1.ucCRTC = id;
args.v1.ucCRTC = crtc_id;
switch (encoder_id) {
case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
@@ -102,7 +102,7 @@ encoder_assign_crtc(uint8 id)
}
break;
case 2:
args.v2.ucCRTC = id;
args.v2.ucCRTC = crtc_id;
args.v2.ucEncodeMode
= display_get_encoder_mode(connector_index);
switch (encoder_id) {
@@ -168,7 +168,8 @@ encoder_assign_crtc(uint8 id)
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
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));
uint32 connector_index = gDisplay[crtc_id]->connector_index;
uint32 encoder_flags = gConnector[connector_index]->encoder.flags;
switch (encoder_id) {
case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
@@ -474,10 +527,10 @@ encoder_dpms_set(uint8 crtc_id, uint8 encoder_id, int mode)
index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl);
break;
case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
// TODO : Laptop LCD special cases dpms set
// if ATOM_DEVICE_LCD_SUPPORT, LCD1OutputControl
// else...
index = GetIndexIntoMasterTable(COMMAND, LVTMAOutputControl);
if (encoder_flags & ATOM_DEVICE_LCD_SUPPORT)
index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl);
else
index = GetIndexIntoMasterTable(COMMAND, LVTMAOutputControl);
break;
case ENCODER_OBJECT_ID_INTERNAL_DAC1:
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
@@ -503,8 +556,10 @@ encoder_dpms_set(uint8 crtc_id, uint8 encoder_id, int mode)
case B_DPMS_ON:
args.ucAction = ATOM_ENABLE;
atom_execute_table(gAtomContext, index, (uint32*)&args);
// TODO : ATOM_DEVICE_LCD_SUPPORT : args.ucAction = ATOM_LCD_BLON;
// execute again
if (encoder_flags & ATOM_DEVICE_LCD_SUPPORT) {
args.ucAction = ATOM_LCD_BLON;
atom_execute_table(gAtomContext, index, (uint32*)&args);
}
encoder_dpms_scratch(crtc_id, true);
break;
case B_DPMS_STAND_BY:
@@ -512,8 +567,10 @@ encoder_dpms_set(uint8 crtc_id, uint8 encoder_id, int mode)
case B_DPMS_OFF:
args.ucAction = ATOM_DISABLE;
atom_execute_table(gAtomContext, index, (uint32*)&args);
// TODO : ATOM_DEVICE_LCD_SUPPORT : args.ucAction = ATOM_LCD_BLOFF;
// execute again
if (encoder_flags & ATOM_DEVICE_LCD_SUPPORT) {
args.ucAction = ATOM_LCD_BLOFF;
atom_execute_table(gAtomContext, index, (uint32*)&args);
}
encoder_dpms_scratch(crtc_id, false);
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_analog_setup(uint8 id, uint32 pixelClock, int command);
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_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;
pll_info *pll = &gConnector[connector_index]->encoder.pll;
pll->pixel_clock = pixelClock;
pll->id = pll_id;
// get any needed clock adjustments, set reference/post dividers, set flags
uint32 adjustedClock = pll_adjust(pll, crtc_id);
// compute dividers, set flags
pll_compute(pll);
int index = GetIndexIntoMasterTable(COMMAND, SetPixelClock);
@@ -283,6 +285,10 @@ pll_set(uint8 pll_id, uint32 pixelClock, uint8 crtc_id)
uint8 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) {
case 1:
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;
args.v3.ucEncoderMode = display_get_encoder_mode(connector_index);
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:
TRACE("%s: ERROR: table version %d.%d TODO\n", __func__,
frev, crev);