Author: kallisti5 Date: 2011-10-12 19:24:15 +0200 (Wed, 12 Oct 2011) New Revision: 42828 Changeset: https://dev.haiku-os.org/changeset/42828 Modified: haiku/trunk/src/add-ons/accelerants/radeon_hd/encoder.cpp haiku/trunk/src/add-ons/accelerants/radeon_hd/encoder.h haiku/trunk/src/add-ons/accelerants/radeon_hd/pll.cpp Log: * 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 Modified: haiku/trunk/src/add-ons/accelerants/radeon_hd/encoder.cpp =================================================================== --- haiku/trunk/src/add-ons/accelerants/radeon_hd/encoder.cpp 2011-10-11 22:32:45 UTC (rev 42827) +++ haiku/trunk/src/add-ons/accelerants/radeon_hd/encoder.cpp 2011-10-12 17:24:15 UTC (rev 42828) @@ -37,7 +37,7 @@ 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 @@ != 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 @@ 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 @@ } 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 @@ atom_execute_table(gAtomContext, index, (uint32*)&args); - // TODO : encoder_crtc_scratch_regs? + // update crtc encoder scratch register @ scratch 3 + encoder_crtc_scratch(crtc_id); } @@ -366,6 +367,55 @@ 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) { TRACE("%s: power: %s\n", __func__, power ? "true" : "false"); @@ -448,6 +498,9 @@ 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 @@ 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 @@ 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 @@ 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; } Modified: haiku/trunk/src/add-ons/accelerants/radeon_hd/encoder.h =================================================================== --- haiku/trunk/src/add-ons/accelerants/radeon_hd/encoder.h 2011-10-11 22:32:45 UTC (rev 42827) +++ haiku/trunk/src/add-ons/accelerants/radeon_hd/encoder.h 2011-10-12 17:24:15 UTC (rev 42828) @@ -14,6 +14,7 @@ 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); Modified: haiku/trunk/src/add-ons/accelerants/radeon_hd/pll.cpp =================================================================== --- haiku/trunk/src/add-ons/accelerants/radeon_hd/pll.cpp 2011-10-11 22:32:45 UTC (rev 42827) +++ haiku/trunk/src/add-ons/accelerants/radeon_hd/pll.cpp 2011-10-12 17:24:15 UTC (rev 42828) @@ -267,12 +267,14 @@ { 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 @@ 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 @@ = 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);