hrev43368 adds 1 changeset to branch 'master' old head: fc111138a9ca143e42ba94add2a3a2053b743b0c new head: b394b1d2bb311256614713abe6a9184b440e3c30 ---------------------------------------------------------------------------- 2 files changed, 184 insertions(+), 2 deletions(-) src/add-ons/accelerants/radeon_hd/encoder.cpp | 183 ++++++++++++++++++++- src/add-ons/accelerants/radeon_hd/encoder.h | 3 +- ############################################################################ Revision: hrev43368 Commit: b394b1d2bb311256614713abe6a9184b440e3c30 URL: http://cgit.haiku-os.org/haiku/commit/?id=b394b1d Author: Alexander von Gluck IV <kallisti5@xxxxxxxxxxx> Date: Wed Nov 30 02:58:30 2011 UTC Add early support for external encoders * detect and attempt setup on external encoders * improve encoder tracing ---------------------------------------------------------------------------- diff --git a/src/add-ons/accelerants/radeon_hd/encoder.cpp b/src/add-ons/accelerants/radeon_hd/encoder.cpp index a09654f..4eb33d5 100644 --- a/src/add-ons/accelerants/radeon_hd/encoder.cpp +++ b/src/add-ons/accelerants/radeon_hd/encoder.cpp @@ -39,6 +39,7 @@ union crtc_source_param { void encoder_assign_crtc(uint8 crtcID) { + TRACE("%s\n", __func__); int index = GetIndexIntoMasterTable(COMMAND, SelectCRTC_Source); union crtc_source_param args; @@ -176,6 +177,7 @@ encoder_assign_crtc(uint8 crtcID) void encoder_apply_quirks(uint8 crtcID) { + TRACE("%s\n", __func__); radeon_shared_info &info = *gInfo->shared_info; register_info* regs = gDisplay[crtcID]->regs; uint32 connectorIndex = gDisplay[crtcID]->connectorIndex; @@ -194,6 +196,7 @@ encoder_apply_quirks(uint8 crtcID) void encoder_mode_set(uint8 id, uint32 pixelClock) { + TRACE("%s\n", __func__); radeon_shared_info &info = *gInfo->shared_info; uint32 connectorIndex = gDisplay[id]->connectorIndex; uint16 encoderFlags = gConnector[connectorIndex]->encoder.flags; @@ -256,6 +259,23 @@ encoder_mode_set(uint8 id, uint32 pixelClock) case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: TRACE("%s: TODO for DVO encoder setup\n", __func__); break; + case ENCODER_OBJECT_ID_SI170B: + case ENCODER_OBJECT_ID_CH7303: + case ENCODER_OBJECT_ID_EXTERNAL_SDVOA: + case ENCODER_OBJECT_ID_EXTERNAL_SDVOB: + case ENCODER_OBJECT_ID_TITFP513: + case ENCODER_OBJECT_ID_VT1623: + case ENCODER_OBJECT_ID_HDMI_SI1930: + case ENCODER_OBJECT_ID_TRAVIS: + case ENCODER_OBJECT_ID_NUTMEG: + if (info.dceMajor >= 4 && info.dceMinor >= 1) { + encoder_external_setup(id, pixelClock, + EXTERNAL_ENCODER_ACTION_V3_ENCODER_SETUP); + } else { + encoder_external_setup(id, pixelClock, + ATOM_ENABLE); + } + break; default: TRACE("%s: TODO for unknown encoder setup!\n", __func__); } @@ -330,8 +350,10 @@ encoder_digital_setup(uint8 id, uint32 pixelClock, int command) uint8 tableMinor; if (atom_parse_cmd_header(gAtomContext, index, &tableMajor, &tableMinor) - != B_OK) + != B_OK) { + ERROR("%s: cannot parse command table\n", __func__); return B_ERROR; + } switch (tableMajor) { case 1: @@ -437,6 +459,7 @@ encoder_dig_setup(uint8 id, uint32 pixelClock, int command) union dig_encoder_control args; int index = 0; + // Table verson uint8 tableMajor; uint8 tableMinor; @@ -576,6 +599,164 @@ encoder_dig_setup(uint8 id, uint32 pixelClock, int command) } +union external_encoder_control { + EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION v1; + EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION_V3 v3; +}; + + +status_t +encoder_external_setup(uint8 id, uint32 pixelClock, int command) +{ + TRACE("%s\n", __func__); + + int index = GetIndexIntoMasterTable(COMMAND, ExternalEncoderControl); + union external_encoder_control args; + memset(&args, 0, sizeof(args)); + + uint32 connectorIndex = gDisplay[id]->connectorIndex; + int connectorObjectID + = (gConnector[connectorIndex]->objectID & OBJECT_ID_MASK) + >> OBJECT_ID_SHIFT; + + uint8 tableMajor; + uint8 tableMinor; + + if (atom_parse_cmd_header(gAtomContext, index, &tableMajor, &tableMinor) + != B_OK) { + ERROR("%s: Error parsing ExternalEncoderControl table\n", __func__); + return B_ERROR; + } + + switch (tableMajor) { + case 1: + // no options needed on table 1.x + break; + case 2: + switch (tableMinor) { + case 1: + case 2: + args.v1.sDigEncoder.ucAction = command; + args.v1.sDigEncoder.usPixelClock + = B_HOST_TO_LENDIAN_INT16(pixelClock / 10); + args.v1.sDigEncoder.ucEncoderMode + = display_get_encoder_mode(connectorIndex); + #if 0 + if (0) { // ENCODER_MODE_IS_DP(v1.sDigEncoder.ucEncoderMode) + if (dp_clock == 270000) { + args.v1.sDigEncoder.ucConfig + |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ; + } + args.v1.sDigEncoder.ucLaneNum = dp_lane_count; + } else if (pixelClock > 165000) { + #endif + if (pixelClock > 165000) { + args.v1.sDigEncoder.ucLaneNum = 8; + } else { + args.v1.sDigEncoder.ucLaneNum = 4; + } + break; + case 3: + { + args.v3.sExtEncoder.ucAction = command; + if (command == EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT) { + args.v3.sExtEncoder.usConnectorId + = B_HOST_TO_LENDIAN_INT16(connectorObjectID); + } else { + args.v3.sExtEncoder.usPixelClock + = B_HOST_TO_LENDIAN_INT16(pixelClock / 10); + } + + args.v3.sExtEncoder.ucEncoderMode + = display_get_encoder_mode(connectorIndex); + + #if 0 + if (ENCODER_MODE_IS_DP(args.v3.sExtEncoder.ucEncoderMode)) { + if (dp_clock == 270000) { + args.v3.sExtEncoder.ucConfig + |=EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_2_70GHZ; + } else if (dp_clock == 540000) { + args.v3.sExtEncoder.ucConfig + |=EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_5_40GHZ; + } + args.v3.sExtEncoder.ucLaneNum = dp_lane_count; + } else if (pixelClock > 165000) { + #endif + if (pixelClock > 165000) { + args.v3.sExtEncoder.ucLaneNum = 8; + } else { + args.v3.sExtEncoder.ucLaneNum = 4; + } + + uint16 encoderFlags + = gConnector[connectorIndex]->encoder.flags; + switch ((encoderFlags & ENUM_ID_MASK) >> ENUM_ID_SHIFT) { + case GRAPH_OBJECT_ENUM_ID1: + TRACE("%s: external encoder 1\n", __func__); + args.v3.sExtEncoder.ucConfig + |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER1; + break; + case GRAPH_OBJECT_ENUM_ID2: + TRACE("%s: external encoder 2\n", __func__); + args.v3.sExtEncoder.ucConfig + |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER2; + break; + case GRAPH_OBJECT_ENUM_ID3: + TRACE("%s: external encoder 3\n", __func__); + args.v3.sExtEncoder.ucConfig + |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER3; + break; + } + + // TODO: don't set statically + uint32 bitsPerColor = 8; + switch (bitsPerColor) { + case 0: + args.v3.sExtEncoder.ucBitPerColor + = PANEL_BPC_UNDEFINE; + break; + case 6: + args.v3.sExtEncoder.ucBitPerColor + = PANEL_6BIT_PER_COLOR; + break; + case 8: + default: + args.v3.sExtEncoder.ucBitPerColor + = PANEL_8BIT_PER_COLOR; + break; + case 10: + args.v3.sExtEncoder.ucBitPerColor + = PANEL_10BIT_PER_COLOR; + break; + case 12: + args.v3.sExtEncoder.ucBitPerColor + = PANEL_12BIT_PER_COLOR; + break; + case 16: + args.v3.sExtEncoder.ucBitPerColor + = PANEL_16BIT_PER_COLOR; + break; + } + break; + } + default: + ERROR("%s: Unknown table minor version: " + "%" B_PRIu8 ".%" B_PRIu8 "\n", __func__, + tableMajor, tableMinor); + return B_ERROR; + } + break; + default: + ERROR("%s: Unknown table major version: " + "%" B_PRIu8 ".%" B_PRIu8 "\n", __func__, + tableMajor, tableMinor); + return B_ERROR; + } + + return atom_execute_table(gAtomContext, index, (uint32*)&args); +} + + status_t encoder_analog_setup(uint8 id, uint32 pixelClock, int command) { diff --git a/src/add-ons/accelerants/radeon_hd/encoder.h b/src/add-ons/accelerants/radeon_hd/encoder.h index fb39070..abe6b61 100644 --- a/src/add-ons/accelerants/radeon_hd/encoder.h +++ b/src/add-ons/accelerants/radeon_hd/encoder.h @@ -12,9 +12,10 @@ void encoder_assign_crtc(uint8 crt_id); void encoder_apply_quirks(uint8 crtcID); 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); +status_t encoder_digital_setup(uint8 id, uint32 pixelClock, int command); status_t encoder_dig_setup(uint8 id, uint32 pixelClock, int command); +status_t encoder_external_setup(uint8 id, uint32 pixelClock, int command); status_t encoder_tv_setup(uint8 id, uint32 pixelClock, int command); bool encoder_analog_load_detect(uint8 connectorIndex); void encoder_output_lock(bool lock);