From f70c0b0d07c60b286d39ab64adba19df67094f97 Mon Sep 17 00:00:00 2001 From: Chris Park Date: Mon, 30 Nov 2015 17:04:12 -0500 Subject: [PATCH 0549/1110] drm/amd/dal: Register offset cleanup on Link and Stream Encoder Signed-off-by: Harry Wentland Acked-by: Harry Wentland --- drivers/gpu/drm/amd/dal/dc/core/dc_link.c | 4 +- drivers/gpu/drm/amd/dal/dc/core/dc_resource.c | 4 +- drivers/gpu/drm/amd/dal/dc/dc_types.h | 8 + .../drm/amd/dal/dc/dce110/dce110_hw_sequencer.c | 2 - .../drm/amd/dal/dc/dce110/dce110_link_encoder.c | 801 +++++++++++---------- .../drm/amd/dal/dc/dce110/dce110_link_encoder.h | 35 +- .../gpu/drm/amd/dal/dc/dce110/dce110_resource.c | 10 +- .../drm/amd/dal/dc/dce110/dce110_stream_encoder.c | 441 ++++++------ .../drm/amd/dal/dc/dce110/dce110_stream_encoder.h | 21 +- drivers/gpu/drm/amd/dal/dc/inc/core_types.h | 2 +- drivers/gpu/drm/amd/dal/dc/inc/hw_sequencer.h | 8 +- drivers/gpu/drm/amd/dal/dc/inc/link_encoder.h | 28 + drivers/gpu/drm/amd/dal/dc/inc/stream_encoder.h | 18 + drivers/gpu/drm/amd/dal/include/encoder_types.h | 10 + .../gpu/drm/amd/dal/include/link_encoder_types.h | 32 - .../gpu/drm/amd/dal/include/stream_encoder_types.h | 16 - 16 files changed, 753 insertions(+), 687 deletions(-) create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/link_encoder.h create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/stream_encoder.h delete mode 100644 drivers/gpu/drm/amd/dal/include/link_encoder_types.h delete mode 100644 drivers/gpu/drm/amd/dal/include/stream_encoder_types.h diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc_link.c b/drivers/gpu/drm/amd/dal/dc/core/dc_link.c index bffd561..0af5005 100644 --- a/drivers/gpu/drm/amd/dal/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/dal/dc/core/dc_link.c @@ -35,8 +35,8 @@ #include "core_status.h" #include "dc_link_dp.h" #include "link_hwss.h" -#include "stream_encoder_types.h" -#include "link_encoder_types.h" +#include "stream_encoder.h" +#include "link_encoder.h" #include "hw_sequencer.h" diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc_resource.c b/drivers/gpu/drm/amd/dal/dc/core/dc_resource.c index f1f7347..7d90532 100644 --- a/drivers/gpu/drm/amd/dal/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/dal/dc/core/dc_resource.c @@ -26,8 +26,8 @@ #include "resource.h" #include "include/irq_service_interface.h" -#include "link_encoder_types.h" -#include "stream_encoder_types.h" +#include "link_encoder.h" +#include "stream_encoder.h" void unreference_clock_source( diff --git a/drivers/gpu/drm/amd/dal/dc/dc_types.h b/drivers/gpu/drm/amd/dal/dc/dc_types.h index b6526e9..db7608e 100644 --- a/drivers/gpu/drm/amd/dal/dc/dc_types.h +++ b/drivers/gpu/drm/amd/dal/dc/dc_types.h @@ -672,6 +672,14 @@ struct dc_csc_adjustments { struct fixed31_32 hue; }; +enum dc_encoder_result { + ENCODER_RESULT_OK, + ENCODER_RESULT_ERROR, + ENCODER_RESULT_NOBANDWIDTH, + ENCODER_RESULT_SINKCONNECTIVITYCHANGED +#endif +}; + #include "dc_temp.h" #endif /* DC_TYPES_H_ */ diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.c index 29e7b80..9c0bcbb 100644 --- a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.c @@ -34,8 +34,6 @@ #include "dce110/dce110_timing_generator.h" #include "dce110/dce110_link_encoder.h" #include "dce110/dce110_stream_encoder.h" -#include "stream_encoder_types.h" -#include "link_encoder_types.h" #include "dce110/dce110_mem_input.h" #include "dce110/dce110_ipp.h" #include "dce110/dce110_transform.h" diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_link_encoder.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_link_encoder.c index 91796ac..4381a94 100644 --- a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_link_encoder.c +++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_link_encoder.c @@ -25,8 +25,8 @@ #include "dal_services.h" #include "core_types.h" -#include "link_encoder_types.h" -#include "stream_encoder_types.h" +#include "link_encoder.h" +#include "stream_encoder.h" #include "dce110_link_encoder.h" #include "i2caux_interface.h" #include "dce/dce_11_0_d.h" @@ -83,12 +83,26 @@ enum { #endif -static const uint32_t fe_engine_offsets[] = { - mmDIG0_DIG_FE_CNTL - mmDIG0_DIG_FE_CNTL, - mmDIG1_DIG_FE_CNTL - mmDIG0_DIG_FE_CNTL, - mmDIG2_DIG_FE_CNTL - mmDIG0_DIG_FE_CNTL, -}; +#define DIG_REG(reg)\ + (reg + enc110->offsets.dig_offset) + +#define DP_REG(reg)\ + (reg + enc110->offsets.dp_offset) +static const struct dce110_link_enc_offsets reg_offsets[] = { +{ + .dig_offset = (mmDIG0_DIG_FE_CNTL - mmDIG0_DIG_FE_CNTL), + .dp_offset = (mmDP0_DP_SEC_CNTL - mmDP0_DP_SEC_CNTL) +}, +{ + .dig_offset = (mmDIG1_DIG_FE_CNTL - mmDIG0_DIG_FE_CNTL), + .dp_offset = (mmDP1_DP_SEC_CNTL - mmDP0_DP_SEC_CNTL) +}, +{ + .dig_offset = (mmDIG2_DIG_FE_CNTL - mmDIG0_DIG_FE_CNTL), + .dp_offset = (mmDP1_DP_SEC_CNTL - mmDP0_DP_SEC_CNTL) +} +}; static enum transmitter translate_encoder_to_transmitter( struct graphics_object_id encoder) @@ -156,14 +170,14 @@ static enum transmitter translate_encoder_to_transmitter( } static void enable_phy_bypass_mode( - struct dc_context *ctx, - const int32_t be_addr_offset, + struct dce110_link_encoder *enc110, bool enable) { /* This register resides in DP back end block; * transmitter is used for the offset */ + struct dc_context *ctx = enc110->base.ctx; - const uint32_t addr = mmDP_DPHY_CNTL + be_addr_offset; + const uint32_t addr = DP_REG(mmDP_DPHY_CNTL); uint32_t value = dal_read_reg(ctx, addr); @@ -173,14 +187,14 @@ static void enable_phy_bypass_mode( } static void disable_prbs_symbols( - struct dc_context *ctx, - const int32_t be_addr_offset, + struct dce110_link_encoder *enc110, bool disable) { /* This register resides in DP back end block; * transmitter is used for the offset */ + struct dc_context *ctx = enc110->base.ctx; - const uint32_t addr = mmDP_DPHY_CNTL + be_addr_offset; + const uint32_t addr = DP_REG(mmDP_DPHY_CNTL); uint32_t value = dal_read_reg(ctx, addr); @@ -200,13 +214,13 @@ static void disable_prbs_symbols( } static void disable_prbs_mode( - struct dc_context *ctx, - const int32_t be_addr_offset) + struct dce110_link_encoder *enc110) { /* This register resides in DP back end block; * transmitter is used for the offset */ + struct dc_context *ctx = enc110->base.ctx; - const uint32_t addr = mmDP_DPHY_PRBS_CNTL + be_addr_offset; + const uint32_t addr = DP_REG(mmDP_DPHY_PRBS_CNTL); uint32_t value; value = dal_read_reg(ctx, addr); @@ -217,17 +231,17 @@ static void disable_prbs_mode( } static void program_pattern_symbols( - struct dc_context *ctx, - const int32_t be_addr_offset, + struct dce110_link_encoder *enc110, uint16_t pattern_symbols[8]) { + struct dc_context *ctx = enc110->base.ctx; uint32_t addr; uint32_t value; /* This register resides in DP back end block; * transmitter is used for the offset */ - addr = mmDP_DPHY_SYM0 + be_addr_offset; + addr = DP_REG(mmDP_DPHY_SYM0); value = 0; set_reg_field_value(value, pattern_symbols[0], @@ -241,7 +255,7 @@ static void program_pattern_symbols( /* This register resides in DP back end block; * transmitter is used for the offset */ - addr = mmDP_DPHY_SYM1 + be_addr_offset; + addr = DP_REG(mmDP_DPHY_SYM1); value = 0; set_reg_field_value(value, pattern_symbols[3], @@ -254,7 +268,7 @@ static void program_pattern_symbols( /* This register resides in DP back end block; * transmitter is used for the offset */ - addr = mmDP_DPHY_SYM2 + be_addr_offset; + addr = DP_REG(mmDP_DPHY_SYM2); value = 0; set_reg_field_value(value, pattern_symbols[6], DP_DPHY_SYM2, DPHY_SYM7); @@ -265,24 +279,22 @@ static void program_pattern_symbols( } static void set_dp_phy_pattern_d102( - struct dc_context *ctx, - const int32_t be_addr_offset) + struct dce110_link_encoder *enc110) { /* Disable PHY Bypass mode to setup the test pattern */ - - enable_phy_bypass_mode(ctx, be_addr_offset, false); + enable_phy_bypass_mode(enc110, false); /* For 10-bit PRBS or debug symbols * please use the following sequence: */ /* Enable debug symbols on the lanes */ - disable_prbs_symbols(ctx, be_addr_offset, true); + disable_prbs_symbols(enc110, true); /* Disable PRBS mode, * make sure DPHY_PRBS_CNTL.DPHY_PRBS_EN=0 */ - disable_prbs_mode(ctx, be_addr_offset); + disable_prbs_mode(enc110); /* Program debug symbols to be output */ { @@ -291,25 +303,22 @@ static void set_dp_phy_pattern_d102( 0x2AA, 0x2AA, 0x2AA, 0x2AA }; - program_pattern_symbols(ctx, - be_addr_offset, pattern_symbols); + program_pattern_symbols(enc110, pattern_symbols); } /* Enable phy bypass mode to enable the test pattern */ - enable_phy_bypass_mode(ctx, be_addr_offset, true); + enable_phy_bypass_mode(enc110, true); } static void set_link_training_complete( - struct dc_context *ctx, - const int32_t be_addr_offset, + struct dce110_link_encoder *enc110, bool complete) { /* This register resides in DP back end block; * transmitter is used for the offset */ - - const uint32_t addr = mmDP_LINK_CNTL + be_addr_offset; - + struct dc_context *ctx = enc110->base.ctx; + const uint32_t addr = DP_REG(mmDP_LINK_CNTL); uint32_t value = dal_read_reg(ctx, addr); set_reg_field_value(value, complete, @@ -319,40 +328,40 @@ static void set_link_training_complete( } static void set_dp_phy_pattern_training_pattern( - struct dc_context *ctx, - const int32_t be_addr_offset, + struct dce110_link_encoder *enc110, uint32_t index) { /* Write Training Pattern */ + struct dc_context *ctx = enc110->base.ctx; + uint32_t addr = DP_REG(mmDP_DPHY_TRAINING_PATTERN_SEL); - dal_write_reg(ctx, - mmDP_DPHY_TRAINING_PATTERN_SEL + be_addr_offset, index); + dal_write_reg(ctx, addr, index); /* Set HW Register Training Complete to false */ - set_link_training_complete(ctx, be_addr_offset, false); + set_link_training_complete(enc110, false); /* Disable PHY Bypass mode to output Training Pattern */ - enable_phy_bypass_mode(ctx, be_addr_offset, false); + enable_phy_bypass_mode(enc110, false); /* Disable PRBS mode, * make sure DPHY_PRBS_CNTL.DPHY_PRBS_EN=0 */ - disable_prbs_mode(ctx, be_addr_offset); + disable_prbs_mode(enc110); } static void set_dp_phy_pattern_symbol_error( - struct dc_context *ctx, - const int32_t addr_offset) + struct dce110_link_encoder *enc110) { /* Disable PHY Bypass mode to setup the test pattern */ + struct dc_context *ctx = enc110->base.ctx; - enable_phy_bypass_mode(ctx, addr_offset, false); + enable_phy_bypass_mode(enc110, false); /* program correct panel mode*/ { - const uint32_t addr = mmDP_DPHY_INTERNAL_CTRL + addr_offset; + const uint32_t addr = DP_REG(mmDP_DPHY_INTERNAL_CTRL); uint32_t value = 0x0; dal_write_reg(ctx, addr, value); } @@ -361,11 +370,11 @@ static void set_dp_phy_pattern_symbol_error( /* Enable PRBS symbols on the lanes */ - disable_prbs_symbols(ctx, addr_offset, false); + disable_prbs_symbols(enc110, false); /* For PRBS23 Set bit DPHY_PRBS_SEL=1 and Set bit DPHY_PRBS_EN=1 */ { - const uint32_t addr = mmDP_DPHY_PRBS_CNTL + addr_offset; + const uint32_t addr = DP_REG(mmDP_DPHY_PRBS_CNTL); uint32_t value = dal_read_reg(ctx, addr); set_reg_field_value(value, 1, @@ -377,26 +386,26 @@ static void set_dp_phy_pattern_symbol_error( /* Enable phy bypass mode to enable the test pattern */ - enable_phy_bypass_mode(ctx, addr_offset, true); + enable_phy_bypass_mode(enc110, true); } static void set_dp_phy_pattern_prbs7( - struct dc_context *ctx, - const int32_t addr_offset) + struct dce110_link_encoder *enc110) { /* Disable PHY Bypass mode to setup the test pattern */ + struct dc_context *ctx = enc110->base.ctx; - enable_phy_bypass_mode(ctx, addr_offset, false); + enable_phy_bypass_mode(enc110, false); /* A PRBS7 pattern is used for most DP electrical measurements. */ /* Enable PRBS symbols on the lanes */ - disable_prbs_symbols(ctx, addr_offset, false); + disable_prbs_symbols(enc110, false); /* For PRBS7 Set bit DPHY_PRBS_SEL=0 and Set bit DPHY_PRBS_EN=1 */ { - const uint32_t addr = mmDP_DPHY_PRBS_CNTL + addr_offset; + const uint32_t addr = DP_REG(mmDP_DPHY_PRBS_CNTL); uint32_t value = dal_read_reg(ctx, addr); @@ -411,26 +420,24 @@ static void set_dp_phy_pattern_prbs7( /* Enable phy bypass mode to enable the test pattern */ - enable_phy_bypass_mode(ctx, addr_offset, true); + enable_phy_bypass_mode(enc110, true); } static void set_dp_phy_pattern_80bit_custom( - struct dc_context *ctx, - const int32_t be_addr_offset, + struct dce110_link_encoder *enc110, const uint8_t *pattern) { /* Disable PHY Bypass mode to setup the test pattern */ - - enable_phy_bypass_mode(ctx, be_addr_offset, false); + enable_phy_bypass_mode(enc110, false); /* Enable debug symbols on the lanes */ - disable_prbs_symbols(ctx, be_addr_offset, true); + disable_prbs_symbols(enc110, true); /* Enable PHY bypass mode to enable the test pattern */ /* TODO is it really needed ? */ - enable_phy_bypass_mode(ctx, be_addr_offset, true); + enable_phy_bypass_mode(enc110, true); /* Program 80 bit custom pattern */ { @@ -453,22 +460,18 @@ static void set_dp_phy_pattern_80bit_custom( pattern_symbols[7] = (pattern[9] << 2) | ((pattern[8] >> 6) & 0x03); - program_pattern_symbols(ctx, - be_addr_offset, pattern_symbols); + program_pattern_symbols(enc110, pattern_symbols); } /* Enable phy bypass mode to enable the test pattern */ - enable_phy_bypass_mode(ctx, be_addr_offset, true); + enable_phy_bypass_mode(enc110, true); } static void set_dp_phy_pattern_hbr2_compliance( - struct link_encoder *enc, - const int32_t be_addr_offset) + struct dce110_link_encoder *enc110) { - /*const int32_t fe_addr_offset = fe_engine_offsets[param->engine]; - const int32_t be_addr_offset = enc->be_engine_offset;*/ - + struct dc_context *ctx = enc110->base.ctx; uint32_t addr; uint32_t value; @@ -482,17 +485,17 @@ static void set_dp_phy_pattern_hbr2_compliance( /* Disable PHY Bypass mode to setup the test pattern */ - enable_phy_bypass_mode(enc->ctx, be_addr_offset, false); + enable_phy_bypass_mode(enc110, false); /* Setup DIG encoder in DP SST mode */ - dce110_link_encoder_setup(enc, SIGNAL_TYPE_DISPLAY_PORT); + dce110_link_encoder_setup(&enc110->base, SIGNAL_TYPE_DISPLAY_PORT); /* program correct panel mode*/ { - const uint32_t addr = mmDP_DPHY_INTERNAL_CTRL + be_addr_offset; + const uint32_t addr = DP_REG(mmDP_DPHY_INTERNAL_CTRL); uint32_t value = 0x0; - dal_write_reg(enc->ctx, addr, value); + dal_write_reg(ctx, addr, value); } /* no vbid after BS (SR) @@ -508,7 +511,7 @@ static void set_dp_phy_pattern_hbr2_compliance( /* TODO: do we still need this, find out at compliance test addr = mmDP_LINK_FRAMING_CNTL + fe_addr_offset; - value = dal_read_reg(enc->ctx, addr); + value = dal_read_reg(ctx, addr); set_reg_field_value(value, 0xFC, DP_LINK_FRAMING_CNTL, DP_IDLE_BS_INTERVAL); @@ -517,7 +520,7 @@ static void set_dp_phy_pattern_hbr2_compliance( set_reg_field_value(value, 1, DP_LINK_FRAMING_CNTL, DP_VID_ENHANCED_FRAME_MODE); - dal_write_reg(enc->ctx, addr, value); + dal_write_reg(ctx, addr, value); */ /*TODO add support for this test pattern @@ -525,30 +528,30 @@ static void set_dp_phy_pattern_hbr2_compliance( */ /* set link training complete */ - set_link_training_complete(enc->ctx, be_addr_offset, true); + set_link_training_complete(enc110, true); /* do not enable video stream */ - addr = mmDP_VID_STREAM_CNTL + be_addr_offset; + addr = DP_REG(mmDP_VID_STREAM_CNTL); - value = dal_read_reg(enc->ctx, addr); + value = dal_read_reg(ctx, addr); set_reg_field_value(value, 0, DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE); - dal_write_reg(enc->ctx, addr, value); + dal_write_reg(ctx, addr, value); /* Disable PHY Bypass mode to setup the test pattern */ - enable_phy_bypass_mode(enc->ctx, be_addr_offset, false); + enable_phy_bypass_mode(enc110, false); } static void set_dp_phy_pattern_passthrough_mode( - struct dc_context *ctx, - const int32_t be_addr_offset, + struct dce110_link_encoder *enc110, enum dp_panel_mode panel_mode) { + struct dc_context *ctx = enc110->base.ctx; /* program correct panel mode */ { - const uint32_t addr = mmDP_DPHY_INTERNAL_CTRL + be_addr_offset; + const uint32_t addr = DP_REG(mmDP_DPHY_INTERNAL_CTRL); uint32_t value; @@ -571,146 +574,16 @@ static void set_dp_phy_pattern_passthrough_mode( /* set link training complete */ - set_link_training_complete(ctx, be_addr_offset, true); + set_link_training_complete(enc110, true); /* Disable PHY Bypass mode to setup the test pattern */ - enable_phy_bypass_mode(ctx, be_addr_offset, false); + enable_phy_bypass_mode(enc110, false); /* Disable PRBS mode, * make sure DPHY_PRBS_CNTL.DPHY_PRBS_EN=0 */ - disable_prbs_mode(ctx, be_addr_offset); -} - -static void construct( - struct link_encoder *enc, - const struct encoder_init_data *init_data) -{ - struct graphics_object_encoder_cap_info enc_cap_info = {0}; - - enc->ctx = init_data->ctx; - enc->id = init_data->encoder; - - enc->hpd_source = init_data->hpd_source; - enc->connector = init_data->connector; - enc->input_signals = SIGNAL_TYPE_ALL; - - enc->adapter_service = init_data->adapter_service; - - enc->preferred_engine = ENGINE_ID_UNKNOWN; - - enc->features.flags.raw = 0; - - enc->transmitter = translate_encoder_to_transmitter( - init_data->encoder); - - enc->features.flags.bits.IS_AUDIO_CAPABLE = true; - - enc->features.max_pixel_clock = DCE11_UNIPHY_MAX_PIXEL_CLK_IN_KHZ; - - /* set the flag to indicate whether driver poll the I2C data pin - * while doing the DP sink detect */ - - if (dal_adapter_service_is_feature_supported( - FEATURE_DP_SINK_DETECT_POLL_DATA_PIN)) - enc->features.flags.bits.DP_SINK_DETECT_POLL_DATA_PIN = true; - - enc->output_signals = - SIGNAL_TYPE_DVI_SINGLE_LINK | - SIGNAL_TYPE_DVI_DUAL_LINK | - SIGNAL_TYPE_LVDS | - SIGNAL_TYPE_DISPLAY_PORT | - SIGNAL_TYPE_DISPLAY_PORT_MST | - SIGNAL_TYPE_EDP | - SIGNAL_TYPE_HDMI_TYPE_A; - - /* For DCE 8.0 and 8.1, by design, UNIPHY is hardwired to DIG_BE. - * SW always assign DIG_FE 1:1 mapped to DIG_FE for non-MST UNIPHY. - * SW assign DIG_FE to non-MST UNIPHY first and MST last. So prefer - * DIG is per UNIPHY and used by SST DP, eDP, HDMI, DVI and LVDS. - * Prefer DIG assignment is decided by board design. - * For DCE 8.0, there are only max 6 UNIPHYs, we assume board design - * and VBIOS will filter out 7 UNIPHY for DCE 8.0. - * By this, adding DIGG should not hurt DCE 8.0. - * This will let DCE 8.1 share DCE 8.0 as much as possible */ - - switch (enc->transmitter) { - case TRANSMITTER_UNIPHY_A: - enc->preferred_engine = ENGINE_ID_DIGA; - enc->transmitter_offset = 0; - enc->be_engine_offset = 0; - break; - case TRANSMITTER_UNIPHY_B: - enc->preferred_engine = ENGINE_ID_DIGB; - - enc->transmitter_offset = - mmBPHYC_UNIPHY1_UNIPHY_TX_CONTROL1 - - mmBPHYC_UNIPHY0_UNIPHY_TX_CONTROL1; - enc->be_engine_offset = - mmDIG1_DIG_BE_CNTL - mmDIG0_DIG_BE_CNTL; - break; - case TRANSMITTER_UNIPHY_C: - enc->preferred_engine = ENGINE_ID_DIGC; - enc->transmitter_offset = - mmBPHYC_UNIPHY2_UNIPHY_TX_CONTROL1 - - mmBPHYC_UNIPHY0_UNIPHY_TX_CONTROL1; - enc->be_engine_offset = - mmDIG2_DIG_BE_CNTL - mmDIG0_DIG_BE_CNTL; - break; - default: - ASSERT_CRITICAL(false); - enc->preferred_engine = ENGINE_ID_UNKNOWN; - enc->transmitter_offset = 0; - enc->be_engine_offset = 0; - } - - dal_logger_write(init_data->ctx->logger, - LOG_MAJOR_I2C_AUX, - LOG_MINOR_I2C_AUX_CFG, - "Using channel: %s [%d]\n", - DECODE_CHANNEL_ID(init_data->channel), - init_data->channel); - - switch (init_data->channel) { - case CHANNEL_ID_DDC1: - enc->aux_channel_offset = 0; - break; - case CHANNEL_ID_DDC2: - enc->aux_channel_offset = - mmDP_AUX1_AUX_CONTROL - mmDP_AUX0_AUX_CONTROL; - break; - case CHANNEL_ID_DDC3: - enc->aux_channel_offset = - mmDP_AUX2_AUX_CONTROL - mmDP_AUX0_AUX_CONTROL; - break; - default: - /* check BIOS object table ! */ - dal_logger_write(init_data->ctx->logger, - LOG_MAJOR_WARNING, - LOG_MINOR_COMPONENT_ENCODER, - "%s: Invalid channel ID\n", - __func__); - enc->aux_channel_offset = 0; - } - - /* Override features with DCE-specific values */ - if (dal_adapter_service_get_encoder_cap_info(enc->adapter_service, - enc->id, &enc_cap_info)) - enc->features.flags.bits.IS_HBR2_CAPABLE = - enc_cap_info.dp_hbr2_cap; - - /* test pattern 3 support */ - enc->features.flags.bits.IS_TPS3_CAPABLE = true; - enc->features.max_deep_color = COLOR_DEPTH_121212; - - enc->features.flags.bits.IS_Y_ONLY_CAPABLE = - dal_adapter_service_is_feature_supported( - FEATURE_SUPPORT_DP_Y_ONLY); - - enc->features.flags.bits.IS_YCBCR_CAPABLE = - dal_adapter_service_is_feature_supported( - FEATURE_SUPPORT_DP_YUV); + disable_prbs_mode(enc110); } /* return value is bit-vector */ @@ -731,28 +604,30 @@ static uint8_t get_frontend_source( } static void configure_encoder( - struct link_encoder *enc, + struct dce110_link_encoder *enc110, enum engine_id engine, const struct link_settings *link_settings) { + struct dc_context *ctx = enc110->base.ctx; uint32_t addr; uint32_t value; /* set number of lanes */ - addr = mmDP_CONFIG + enc->be_engine_offset; - value = dal_read_reg(enc->ctx, addr); + addr = DP_REG(mmDP_CONFIG); + value = dal_read_reg(ctx, addr); set_reg_field_value(value, link_settings->lane_count - LANE_COUNT_ONE, DP_CONFIG, DP_UDI_LANES); - dal_write_reg(enc->ctx, addr, value); + dal_write_reg(ctx, addr, value); } -static bool is_panel_powered_on(struct link_encoder *link_enc) +static bool is_panel_powered_on(struct dce110_link_encoder *enc110) { + struct dc_context *ctx = enc110->base.ctx; uint32_t value; bool ret; - value = dal_read_reg(link_enc->ctx, + value = dal_read_reg(ctx, mmLVTMA_PWRSEQ_STATE); ret = get_reg_field_value(value, @@ -765,25 +640,26 @@ static bool is_panel_powered_on(struct link_encoder *link_enc) * @brief * eDP only. Control the power of the eDP panel. */ -static enum encoder_result link_encoder_edp_power_control( - struct link_encoder *link_enc, +static enum dc_encoder_result link_encoder_edp_power_control( + struct dce110_link_encoder *enc110, bool power_up) { + struct dc_context *ctx = enc110->base.ctx; struct bp_transmitter_control cntl = { 0 }; enum bp_result bp_result; - if (dal_graphics_object_id_get_connector_id(link_enc->connector) != + if (dal_graphics_object_id_get_connector_id(enc110->base.connector) != CONNECTOR_ID_EDP) { BREAK_TO_DEBUGGER(); return ENCODER_RESULT_ERROR; } - if ((power_up && !is_panel_powered_on(link_enc)) || - (!power_up && is_panel_powered_on(link_enc))) { + if ((power_up && !is_panel_powered_on(enc110)) || + (!power_up && is_panel_powered_on(enc110))) { /* Send VBIOS command to prompt eDP panel power */ - dal_logger_write(link_enc->ctx->logger, + dal_logger_write(ctx->logger, LOG_MAJOR_HW_TRACE, LOG_MINOR_HW_TRACE_RESUME_S3, "%s: Panel Power action: %s\n", @@ -792,26 +668,26 @@ static enum encoder_result link_encoder_edp_power_control( cntl.action = power_up ? TRANSMITTER_CONTROL_POWER_ON : TRANSMITTER_CONTROL_POWER_OFF; - cntl.transmitter = link_enc->transmitter; - cntl.connector_obj_id = link_enc->connector; + cntl.transmitter = enc110->base.transmitter; + cntl.connector_obj_id = enc110->base.connector; cntl.coherent = false; cntl.lanes_number = LANE_COUNT_FOUR; - cntl.hpd_sel = link_enc->hpd_source; + cntl.hpd_sel = enc110->base.hpd_source; bp_result = dal_bios_parser_transmitter_control( dal_adapter_service_get_bios_parser( - link_enc->adapter_service), &cntl); + enc110->base.adapter_service), &cntl); if (BP_RESULT_OK != bp_result) { - dal_logger_write(link_enc->ctx->logger, + dal_logger_write(ctx->logger, LOG_MAJOR_ERROR, LOG_MINOR_HW_TRACE_RESUME_S3, "%s: Panel Power bp_result: %d\n", __func__, bp_result); } } else { - dal_logger_write(link_enc->ctx->logger, + dal_logger_write(ctx->logger, LOG_MAJOR_HW_TRACE, LOG_MINOR_HW_TRACE_RESUME_S3, "%s: Skipping Panel Power action: %s\n", @@ -826,11 +702,12 @@ static enum encoder_result link_encoder_edp_power_control( * eDP only. */ static void link_encoder_edp_wait_for_hpd_ready( - struct link_encoder *link_enc, - struct graphics_object_id connector, + struct dce110_link_encoder *enc110, bool power_up) { - struct adapter_service *as = link_enc->adapter_service; + struct dc_context *ctx = enc110->base.ctx; + struct adapter_service *as = enc110->base.adapter_service; + struct graphics_object_id connector = enc110->base.connector; struct irq *hpd; bool edp_hpd_high = false; uint32_t time_elapsed = 0; @@ -875,7 +752,7 @@ static void link_encoder_edp_wait_for_hpd_ready( break; } - dc_service_sleep_in_milliseconds(link_enc->ctx, HPD_CHECK_INTERVAL); + dc_service_sleep_in_milliseconds(ctx, HPD_CHECK_INTERVAL); time_elapsed += HPD_CHECK_INTERVAL; } while (time_elapsed < timeout); @@ -885,7 +762,7 @@ static void link_encoder_edp_wait_for_hpd_ready( dal_adapter_service_release_irq(as, hpd); if (false == edp_hpd_high) { - dal_logger_write(link_enc->ctx->logger, + dal_logger_write(ctx->logger, LOG_MAJOR_ERROR, LOG_MINOR_HW_TRACE_RESUME_S3, "%s: wait timed out!\n", __func__); @@ -893,35 +770,37 @@ static void link_encoder_edp_wait_for_hpd_ready( } static void aux_initialize( - struct link_encoder *link_enc, - enum hpd_source_id hpd_source) + struct dce110_link_encoder *enc110) { - uint32_t addr = mmAUX_CONTROL + link_enc->aux_channel_offset; - - uint32_t value = dal_read_reg(link_enc->ctx, addr); + struct dc_context *ctx = enc110->base.ctx; + enum hpd_source_id hpd_source = enc110->base.hpd_source; + uint32_t addr = mmAUX_CONTROL + enc110->base.aux_channel_offset; + uint32_t value = dal_read_reg(ctx, addr); set_reg_field_value(value, hpd_source, AUX_CONTROL, AUX_HPD_SEL); set_reg_field_value(value, 0, AUX_CONTROL, AUX_LS_READ_EN); - dal_write_reg(link_enc->ctx, addr, value); + dal_write_reg(ctx, addr, value); - addr = mmAUX_DPHY_RX_CONTROL0 + link_enc->aux_channel_offset; - value = dal_read_reg(link_enc->ctx, addr); + addr = mmAUX_DPHY_RX_CONTROL0 + enc110->base.aux_channel_offset; + value = dal_read_reg(ctx, addr); /* 1/4 window (the maximum allowed) */ set_reg_field_value(value, 1, AUX_DPHY_RX_CONTROL0, AUX_RX_RECEIVE_WINDOW); - dal_write_reg(link_enc->ctx, - mmAUX_DPHY_RX_CONTROL0 + link_enc->aux_channel_offset, + dal_write_reg(ctx, + mmAUX_DPHY_RX_CONTROL0 + + enc110->base.aux_channel_offset, value); } /*todo: cloned in stream enc, fix*/ -static bool is_panel_backlight_on(struct link_encoder *link_enc) +static bool is_panel_backlight_on(struct dce110_link_encoder *enc110) { + struct dc_context *ctx = enc110->base.ctx; uint32_t value; - value = dal_read_reg(link_enc->ctx, mmLVTMA_PWRSEQ_CNTL); + value = dal_read_reg(ctx, mmLVTMA_PWRSEQ_CNTL); return get_reg_field_value(value, LVTMA_PWRSEQ_CNTL, LVTMA_BLON); } @@ -931,20 +810,21 @@ static bool is_panel_backlight_on(struct link_encoder *link_enc) * @brief * eDP only. Control the backlight of the eDP panel */ -static enum encoder_result link_encoder_edp_backlight_control( - struct link_encoder *link_enc, +static enum dc_encoder_result link_encoder_edp_backlight_control( + struct dce110_link_encoder *enc110, bool enable) { + struct dc_context *ctx = enc110->base.ctx; struct bp_transmitter_control cntl = { 0 }; - if (dal_graphics_object_id_get_connector_id(link_enc->connector) + if (dal_graphics_object_id_get_connector_id(enc110->base.connector) != CONNECTOR_ID_EDP) { BREAK_TO_DEBUGGER(); return ENCODER_RESULT_ERROR; } - if (enable && is_panel_backlight_on(link_enc)) { - dal_logger_write(link_enc->ctx->logger, + if (enable && is_panel_backlight_on(enc110)) { + dal_logger_write(ctx->logger, LOG_MAJOR_HW_TRACE, LOG_MINOR_HW_TRACE_RESUME_S3, "%s: panel already powered up. Do nothing.\n", @@ -952,8 +832,8 @@ static enum encoder_result link_encoder_edp_backlight_control( return ENCODER_RESULT_OK; } - if (!enable && !is_panel_powered_on(link_enc)) { - dal_logger_write(link_enc->ctx->logger, + if (!enable && !is_panel_powered_on(enc110)) { + dal_logger_write(ctx->logger, LOG_MAJOR_HW_TRACE, LOG_MINOR_HW_TRACE_RESUME_S3, "%s: panel already powered down. Do nothing.\n", @@ -963,7 +843,7 @@ static enum encoder_result link_encoder_edp_backlight_control( /* Send VBIOS command to control eDP panel backlight */ - dal_logger_write(link_enc->ctx->logger, + dal_logger_write(ctx->logger, LOG_MAJOR_HW_TRACE, LOG_MINOR_HW_TRACE_RESUME_S3, "%s: backlight action: %s\n", @@ -973,11 +853,11 @@ static enum encoder_result link_encoder_edp_backlight_control( TRANSMITTER_CONTROL_BACKLIGHT_ON : TRANSMITTER_CONTROL_BACKLIGHT_OFF; /*cntl.engine_id = ctx->engine;*/ - cntl.transmitter = link_enc->transmitter; - cntl.connector_obj_id = link_enc->connector; + cntl.transmitter = enc110->base.transmitter; + cntl.connector_obj_id = enc110->base.connector; /*todo: unhardcode*/ cntl.lanes_number = LANE_COUNT_FOUR; - cntl.hpd_sel = link_enc->hpd_source; + cntl.hpd_sel = enc110->base.hpd_source; /* For eDP, the following delays might need to be considered * after link training completed: @@ -993,68 +873,70 @@ static enum encoder_result link_encoder_edp_backlight_control( dal_bios_parser_transmitter_control( dal_adapter_service_get_bios_parser( - link_enc->adapter_service), &cntl); + enc110->base.adapter_service), &cntl); return ENCODER_RESULT_OK; } -static bool is_dig_enabled(const struct link_encoder *link_enc) +static bool is_dig_enabled(const struct dce110_link_encoder *enc110) { + struct dc_context *ctx = enc110->base.ctx; uint32_t value; - value = dal_read_reg(link_enc->ctx, - mmDIG_BE_EN_CNTL + link_enc->be_engine_offset); + value = dal_read_reg(ctx, DIG_REG(mmDIG_BE_EN_CNTL)); return get_reg_field_value(value, DIG_BE_EN_CNTL, DIG_ENABLE); } -static void link_encoder_disable(struct link_encoder *link_enc) +static void link_encoder_disable(struct dce110_link_encoder *enc110) { + struct dc_context *ctx = enc110->base.ctx; uint32_t addr; uint32_t value; /* reset training pattern */ - addr = mmDP_DPHY_TRAINING_PATTERN_SEL + link_enc->be_engine_offset; - value = dal_read_reg(link_enc->ctx, addr); + addr = DP_REG(mmDP_DPHY_TRAINING_PATTERN_SEL); + value = dal_read_reg(ctx, addr); set_reg_field_value(value, 0, DP_DPHY_TRAINING_PATTERN_SEL, DPHY_TRAINING_PATTERN_SEL); - dal_write_reg(link_enc->ctx, addr, value); + dal_write_reg(ctx, addr, value); /* reset training complete */ - addr = mmDP_LINK_CNTL + link_enc->be_engine_offset; - value = dal_read_reg(link_enc->ctx, addr); + addr = DP_REG(mmDP_LINK_CNTL); + value = dal_read_reg(ctx, addr); set_reg_field_value(value, 0, DP_LINK_CNTL, DP_LINK_TRAINING_COMPLETE); - dal_write_reg(link_enc->ctx, addr, value); + dal_write_reg(ctx, addr, value); /* reset panel mode */ - addr = mmDP_DPHY_INTERNAL_CTRL + link_enc->be_engine_offset; + addr = DP_REG(mmDP_DPHY_INTERNAL_CTRL); value = 0; - dal_write_reg(link_enc->ctx, addr, value); + dal_write_reg(ctx, addr, value); } static void hpd_initialize( - struct link_encoder *enc, - enum hpd_source_id hpd_source) + struct dce110_link_encoder *enc110) { /* Associate HPD with DIG_BE */ - const uint32_t addr = mmDIG_BE_CNTL + enc->be_engine_offset; - uint32_t value = dal_read_reg(enc->ctx, addr); + struct dc_context *ctx = enc110->base.ctx; + enum hpd_source_id hpd_source = enc110->base.hpd_source; + const uint32_t addr = DIG_REG(mmDIG_BE_CNTL); + uint32_t value = dal_read_reg(ctx, addr); set_reg_field_value(value, hpd_source, DIG_BE_CNTL, DIG_HPD_SELECT); - dal_write_reg(enc->ctx, addr, value); + dal_write_reg(ctx, addr, value); } static bool validate_dvi_output( - const struct link_encoder *enc, + const struct dce110_link_encoder *enc110, enum signal_type connector_signal, enum signal_type signal, const struct dc_crtc_timing *crtc_timing) { uint32_t max_pixel_clock = TMDS_MAX_PIXEL_CLOCK; - if (enc->features.max_pixel_clock < TMDS_MAX_PIXEL_CLOCK) - max_pixel_clock = enc->features.max_pixel_clock; + if (enc110->base.features.max_pixel_clock < TMDS_MAX_PIXEL_CLOCK) + max_pixel_clock = enc110->base.features.max_pixel_clock; if (signal == SIGNAL_TYPE_DVI_DUAL_LINK) max_pixel_clock <<= 1; @@ -1064,7 +946,7 @@ static bool validate_dvi_output( */ if (connector_signal != SIGNAL_TYPE_DVI_DUAL_LINK && connector_signal != SIGNAL_TYPE_DVI_SINGLE_LINK) - max_pixel_clock = enc->features.max_pixel_clock; + max_pixel_clock = enc110->base.features.max_pixel_clock; /* DVI only support RGB pixel encoding */ if (crtc_timing->pixel_encoding != PIXEL_ENCODING_RGB) @@ -1094,7 +976,7 @@ static bool validate_dvi_output( } static bool validate_hdmi_output( - const struct link_encoder *enc, + const struct dce110_link_encoder *enc110, const struct dc_crtc_timing *crtc_timing, uint32_t max_tmds_clk_from_edid_in_mhz, enum dc_color_depth max_hdmi_deep_color, @@ -1105,8 +987,8 @@ static bool validate_hdmi_output( /* expressed in KHz */ uint32_t pixel_clock = 0; - if (max_deep_color > enc->features.max_deep_color) - max_deep_color = enc->features.max_deep_color; + if (max_deep_color > enc110->base.features.max_deep_color) + max_deep_color = enc110->base.features.max_deep_color; if (max_deep_color < crtc_timing->display_color_depth) return false; @@ -1140,7 +1022,7 @@ static bool validate_hdmi_output( if ((pixel_clock == 0) || (pixel_clock > max_hdmi_pixel_clock) || - (pixel_clock > enc->features.max_pixel_clock)) + (pixel_clock > enc110->base.features.max_pixel_clock)) return false; /* @@ -1160,10 +1042,10 @@ static bool validate_hdmi_output( } static bool validate_rgb_output( - const struct link_encoder *enc, + const struct dce110_link_encoder *enc110, const struct dc_crtc_timing *crtc_timing) { - if (crtc_timing->pix_clk_khz > enc->features.max_pixel_clock) + if (crtc_timing->pix_clk_khz > enc110->base.features.max_pixel_clock) return false; if (crtc_timing->pixel_encoding != PIXEL_ENCODING_RGB) @@ -1173,23 +1055,23 @@ static bool validate_rgb_output( } static bool validate_dp_output( - const struct link_encoder *enc, + const struct dce110_link_encoder *enc110, const struct dc_crtc_timing *crtc_timing) { - if (crtc_timing->pix_clk_khz > enc->features.max_pixel_clock) + if (crtc_timing->pix_clk_khz > enc110->base.features.max_pixel_clock) return false; /* default RGB only */ if (crtc_timing->pixel_encoding == PIXEL_ENCODING_RGB) return true; - if (enc->features.flags.bits.IS_YCBCR_CAPABLE) + if (enc110->base.features.flags.bits.IS_YCBCR_CAPABLE) return true; /* for DCE 8.x or later DP Y-only feature, * we need ASIC cap + FeatureSupportDPYonly, not support 666 */ if (crtc_timing->flags.Y_ONLY && - enc->features.flags.bits.IS_YCBCR_CAPABLE && + enc110->base.features.flags.bits.IS_YCBCR_CAPABLE && crtc_timing->display_color_depth != COLOR_DEPTH_666) return true; @@ -1197,10 +1079,10 @@ static bool validate_dp_output( } static bool validate_wireless_output( - const struct link_encoder *enc, + const struct dce110_link_encoder *enc110, const struct dc_crtc_timing *crtc_timing) { - if (crtc_timing->pix_clk_khz > enc->features.max_pixel_clock) + if (crtc_timing->pix_clk_khz > enc110->base.features.max_pixel_clock) return false; /* Wireless only supports YCbCr444 */ @@ -1211,49 +1093,171 @@ static bool validate_wireless_output( return false; } +bool dce110_link_encoder_construct( + struct dce110_link_encoder *enc110, + const struct encoder_init_data *init_data) +{ + struct graphics_object_encoder_cap_info enc_cap_info = {0}; + + enc110->base.ctx = init_data->ctx; + enc110->base.id = init_data->encoder; + + enc110->base.hpd_source = init_data->hpd_source; + enc110->base.connector = init_data->connector; + enc110->base.input_signals = SIGNAL_TYPE_ALL; + + enc110->base.adapter_service = init_data->adapter_service; + + enc110->base.preferred_engine = ENGINE_ID_UNKNOWN; + + enc110->base.features.flags.raw = 0; + + enc110->base.transmitter = translate_encoder_to_transmitter( + init_data->encoder); + + enc110->base.features.flags.bits.IS_AUDIO_CAPABLE = true; + + enc110->base.features.max_pixel_clock = + DCE11_UNIPHY_MAX_PIXEL_CLK_IN_KHZ; + + /* set the flag to indicate whether driver poll the I2C data pin + * while doing the DP sink detect + */ + + if (dal_adapter_service_is_feature_supported( + FEATURE_DP_SINK_DETECT_POLL_DATA_PIN)) + enc110->base.features.flags.bits. + DP_SINK_DETECT_POLL_DATA_PIN = true; + + enc110->base.output_signals = + SIGNAL_TYPE_DVI_SINGLE_LINK | + SIGNAL_TYPE_DVI_DUAL_LINK | + SIGNAL_TYPE_LVDS | + SIGNAL_TYPE_DISPLAY_PORT | + SIGNAL_TYPE_DISPLAY_PORT_MST | + SIGNAL_TYPE_EDP | + SIGNAL_TYPE_HDMI_TYPE_A; + + /* For DCE 8.0 and 8.1, by design, UNIPHY is hardwired to DIG_BE. + * SW always assign DIG_FE 1:1 mapped to DIG_FE for non-MST UNIPHY. + * SW assign DIG_FE to non-MST UNIPHY first and MST last. So prefer + * DIG is per UNIPHY and used by SST DP, eDP, HDMI, DVI and LVDS. + * Prefer DIG assignment is decided by board design. + * For DCE 8.0, there are only max 6 UNIPHYs, we assume board design + * and VBIOS will filter out 7 UNIPHY for DCE 8.0. + * By this, adding DIGG should not hurt DCE 8.0. + * This will let DCE 8.1 share DCE 8.0 as much as possible + */ + + switch (enc110->base.transmitter) { + case TRANSMITTER_UNIPHY_A: + enc110->base.preferred_engine = ENGINE_ID_DIGA; + break; + case TRANSMITTER_UNIPHY_B: + enc110->base.preferred_engine = ENGINE_ID_DIGB; + break; + case TRANSMITTER_UNIPHY_C: + enc110->base.preferred_engine = ENGINE_ID_DIGC; + break; + default: + ASSERT_CRITICAL(false); + enc110->base.preferred_engine = ENGINE_ID_UNKNOWN; + } + + enc110->offsets = reg_offsets[enc110->base.transmitter]; + + dal_logger_write(init_data->ctx->logger, + LOG_MAJOR_I2C_AUX, + LOG_MINOR_I2C_AUX_CFG, + "Using channel: %s [%d]\n", + DECODE_CHANNEL_ID(init_data->channel), + init_data->channel); + + switch (init_data->channel) { + case CHANNEL_ID_DDC1: + enc110->base.aux_channel_offset = 0; + break; + case CHANNEL_ID_DDC2: + enc110->base.aux_channel_offset = + mmDP_AUX1_AUX_CONTROL - mmDP_AUX0_AUX_CONTROL; + break; + case CHANNEL_ID_DDC3: + enc110->base.aux_channel_offset = + mmDP_AUX2_AUX_CONTROL - mmDP_AUX0_AUX_CONTROL; + break; + default: + /* check BIOS object table ! */ + dal_logger_write(init_data->ctx->logger, + LOG_MAJOR_WARNING, + LOG_MINOR_COMPONENT_ENCODER, + "%s: Invalid channel ID\n", + __func__); + enc110->base.aux_channel_offset = 0; + } + + /* Override features with DCE-specific values */ + if (dal_adapter_service_get_encoder_cap_info( + enc110->base.adapter_service, + enc110->base.id, &enc_cap_info)) + enc110->base.features.flags.bits.IS_HBR2_CAPABLE = + enc_cap_info.dp_hbr2_cap; + + /* test pattern 3 support */ + enc110->base.features.flags.bits.IS_TPS3_CAPABLE = true; + enc110->base.features.max_deep_color = COLOR_DEPTH_121212; + + enc110->base.features.flags.bits.IS_Y_ONLY_CAPABLE = + dal_adapter_service_is_feature_supported( + FEATURE_SUPPORT_DP_Y_ONLY); + + enc110->base.features.flags.bits.IS_YCBCR_CAPABLE = + dal_adapter_service_is_feature_supported( + FEATURE_SUPPORT_DP_YUV); + return true; +} + struct link_encoder *dce110_link_encoder_create( const struct encoder_init_data *init) { - struct link_encoder *enc = - dc_service_alloc(init->ctx, sizeof(struct link_encoder)); - - if (!enc) - goto enc_create_fail; + struct dce110_link_encoder *enc110 = + dc_service_alloc(init->ctx, sizeof(struct dce110_link_encoder)); - construct(enc, init); + if (!enc110) + return NULL; - return enc; + if (dce110_link_encoder_construct(enc110, init)) + return &enc110->base; -enc_create_fail: + BREAK_TO_DEBUGGER(); + dc_service_free(init->ctx, enc110); return NULL; } void dce110_link_encoder_destroy(struct link_encoder **enc) { - struct link_encoder *encoder = *enc; - - dc_service_free(encoder->ctx, encoder); + dc_service_free((*enc)->ctx, TO_DCE110_LINK_ENC(*enc)); *enc = NULL; } -enum encoder_result dce110_link_encoder_validate_output_with_stream( +enum dc_encoder_result dce110_link_encoder_validate_output_with_stream( struct link_encoder *enc, const struct core_stream *stream) { + struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); bool is_valid; switch (stream->signal) { case SIGNAL_TYPE_DVI_SINGLE_LINK: case SIGNAL_TYPE_DVI_DUAL_LINK: is_valid = validate_dvi_output( - enc, + enc110, stream->sink->link->public.connector_signal, stream->signal, &stream->public.timing); break; case SIGNAL_TYPE_HDMI_TYPE_A: is_valid = validate_hdmi_output( - enc, + enc110, &stream->public.timing, stream->max_tmds_clk_from_edid_in_mhz, stream->max_hdmi_deep_color, @@ -1261,17 +1265,17 @@ enum encoder_result dce110_link_encoder_validate_output_with_stream( break; case SIGNAL_TYPE_RGB: is_valid = validate_rgb_output( - enc, &stream->public.timing); + enc110, &stream->public.timing); break; case SIGNAL_TYPE_DISPLAY_PORT: case SIGNAL_TYPE_DISPLAY_PORT_MST: case SIGNAL_TYPE_EDP: is_valid = validate_dp_output( - enc, &stream->public.timing); + enc110, &stream->public.timing); break; case SIGNAL_TYPE_WIRELESS: is_valid = validate_wireless_output( - enc, &stream->public.timing); + enc110, &stream->public.timing); break; default: is_valid = true; @@ -1281,28 +1285,30 @@ enum encoder_result dce110_link_encoder_validate_output_with_stream( return is_valid ? ENCODER_RESULT_OK : ENCODER_RESULT_ERROR; } -enum encoder_result dce110_link_encoder_power_up( +enum dc_encoder_result dce110_link_encoder_power_up( struct link_encoder *enc) { + struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); + struct dc_context *ctx = enc110->base.ctx; struct bp_transmitter_control cntl = { 0 }; enum bp_result result; cntl.action = TRANSMITTER_CONTROL_INIT; cntl.engine_id = ENGINE_ID_UNKNOWN; - cntl.transmitter = enc->transmitter; - cntl.connector_obj_id = enc->connector; + cntl.transmitter = enc110->base.transmitter; + cntl.connector_obj_id = enc110->base.connector; cntl.lanes_number = LANE_COUNT_FOUR; cntl.coherent = false; - cntl.hpd_sel = enc->hpd_source; + cntl.hpd_sel = enc110->base.hpd_source; result = dal_bios_parser_transmitter_control( dal_adapter_service_get_bios_parser( - enc->adapter_service), + enc110->base.adapter_service), &cntl); if (result != BP_RESULT_OK) { - dal_logger_write(enc->ctx->logger, + dal_logger_write(ctx->logger, LOG_MAJOR_ERROR, LOG_MINOR_COMPONENT_ENCODER, "%s: Failed to execute VBIOS command table!\n", @@ -1311,30 +1317,30 @@ enum encoder_result dce110_link_encoder_power_up( return ENCODER_RESULT_ERROR; } - if (enc->connector.id == CONNECTOR_ID_LVDS) { + if (enc110->base.connector.id == CONNECTOR_ID_LVDS) { cntl.action = TRANSMITTER_CONTROL_BACKLIGHT_BRIGHTNESS; result = dal_bios_parser_transmitter_control( dal_adapter_service_get_bios_parser( - enc->adapter_service), + enc110->base.adapter_service), &cntl); ASSERT(result == BP_RESULT_OK); - } else if (enc->connector.id == CONNECTOR_ID_EDP) { - link_encoder_edp_power_control(enc, true); + } else if (enc110->base.connector.id == CONNECTOR_ID_EDP) { + link_encoder_edp_power_control(enc110, true); link_encoder_edp_wait_for_hpd_ready( - enc, enc->connector, true); + enc110, true); } - aux_initialize(enc, enc->hpd_source); + aux_initialize(enc110); /* reinitialize HPD. * hpd_initialize() will pass DIG_FE id to HW context. * All other routine within HW context will use fe_engine_offset * as DIG_FE id even caller pass DIG_FE id. * So this routine must be called first. */ - hpd_initialize(enc, enc->hpd_source); + hpd_initialize(enc110); return ENCODER_RESULT_OK; } @@ -1343,8 +1349,10 @@ void dce110_link_encoder_setup( struct link_encoder *enc, enum signal_type signal) { - const uint32_t addr = mmDIG_BE_CNTL + enc->be_engine_offset; - uint32_t value = dal_read_reg(enc->ctx, addr); + struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); + struct dc_context *ctx = enc110->base.ctx; + const uint32_t addr = DIG_REG(mmDIG_BE_CNTL); + uint32_t value = dal_read_reg(ctx, addr); switch (signal) { case SIGNAL_TYPE_EDP: @@ -1375,10 +1383,10 @@ void dce110_link_encoder_setup( break; } - dal_write_reg(enc->ctx, addr, value); + dal_write_reg(ctx, addr, value); } -enum encoder_result dce110_link_encoder_enable_tmds_output( +enum dc_encoder_result dce110_link_encoder_enable_tmds_output( struct link_encoder *enc, enum clock_source_id clock_source, enum dc_color_depth color_depth, @@ -1387,7 +1395,7 @@ enum encoder_result dce110_link_encoder_enable_tmds_output( return ENCODER_RESULT_OK; } -enum encoder_result dce110_link_encoder_enable_dual_link_tmds_output( +enum dc_encoder_result dce110_link_encoder_enable_dual_link_tmds_output( struct link_encoder *enc, enum clock_source_id clock_source, enum dc_color_depth color_depth, @@ -1397,7 +1405,7 @@ enum encoder_result dce110_link_encoder_enable_dual_link_tmds_output( } /* enables DP PHY output */ -enum encoder_result dce110_link_encoder_enable_dp_output( +enum dc_encoder_result dce110_link_encoder_enable_dp_output( struct link_encoder *enc, const struct link_settings *link_settings, enum clock_source_id clock_source) @@ -1406,7 +1414,7 @@ enum encoder_result dce110_link_encoder_enable_dp_output( } /* enables DP PHY output in MST mode */ -enum encoder_result dce110_link_encoder_enable_dp_mst_output( +enum dc_encoder_result dce110_link_encoder_enable_dp_mst_output( struct link_encoder *enc, const struct link_settings *link_settings, enum clock_source_id clock_source) @@ -1418,22 +1426,24 @@ enum encoder_result dce110_link_encoder_enable_dp_mst_output( * @brief * Disable transmitter and its encoder */ -enum encoder_result dce110_link_encoder_disable_output( - struct link_encoder *link_enc, +enum dc_encoder_result dce110_link_encoder_disable_output( + struct link_encoder *enc, enum signal_type signal) { + struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); struct bp_transmitter_control cntl = { 0 }; - if (link_enc->connector.id == CONNECTOR_ID_EDP) { + if (enc110->base.connector.id == CONNECTOR_ID_EDP) { /* have to turn off the backlight * before power down eDP panel */ link_encoder_edp_backlight_control( - link_enc, false); + enc110, false); } - if (!is_dig_enabled(link_enc) && - dal_adapter_service_should_optimize(link_enc->adapter_service, - OF_SKIP_POWER_DOWN_INACTIVE_ENCODER)) { + if (!is_dig_enabled(enc110) && + dal_adapter_service_should_optimize( + enc110->base.adapter_service, + OF_SKIP_POWER_DOWN_INACTIVE_ENCODER)) { return ENCODER_RESULT_OK; } /* Power-down RX and disable GPU PHY should be paired. @@ -1448,20 +1458,20 @@ enum encoder_result dce110_link_encoder_disable_output( /* disable transmitter */ cntl.action = TRANSMITTER_CONTROL_DISABLE; - cntl.transmitter = link_enc->transmitter; - cntl.hpd_sel = link_enc->hpd_source; + cntl.transmitter = enc110->base.transmitter; + cntl.hpd_sel = enc110->base.hpd_source; cntl.signal = signal; - cntl.connector_obj_id = link_enc->connector; + cntl.connector_obj_id = enc110->base.connector; dal_bios_parser_transmitter_control( dal_adapter_service_get_bios_parser( - link_enc->adapter_service), &cntl); + enc110->base.adapter_service), &cntl); /* disable encoder */ if (dc_is_dp_signal(signal)) - link_encoder_disable(link_enc); + link_encoder_disable(enc110); - if (link_enc->connector.id == CONNECTOR_ID_EDP) { + if (enc110->base.connector.id == CONNECTOR_ID_EDP) { /* power down eDP panel */ /* TODO: Power control cause regression, we should implement * it properly, for now just comment it. @@ -1478,14 +1488,13 @@ enum encoder_result dce110_link_encoder_disable_output( return ENCODER_RESULT_OK; } -enum encoder_result dce110_link_encoder_dp_set_lane_settings( +enum dc_encoder_result dce110_link_encoder_dp_set_lane_settings( struct link_encoder *enc, const struct link_training_settings *link_settings) { + struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); union dpcd_training_lane_set training_lane_set = { { 0 } }; - int32_t lane = 0; - struct bp_transmitter_control cntl = { 0 }; if (!link_settings) { @@ -1494,10 +1503,10 @@ enum encoder_result dce110_link_encoder_dp_set_lane_settings( } cntl.action = TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS; - cntl.transmitter = enc->transmitter; - cntl.connector_obj_id = enc->connector; + cntl.transmitter = enc110->base.transmitter; + cntl.connector_obj_id = enc110->base.connector; cntl.lanes_number = link_settings->link_settings.lane_count; - cntl.hpd_sel = enc->hpd_source; + cntl.hpd_sel = enc110->base.hpd_source; cntl.pixel_clock = link_settings->link_settings.link_rate * LINK_RATE_REF_FREQ_IN_KHZ; @@ -1525,7 +1534,7 @@ enum encoder_result dce110_link_encoder_dp_set_lane_settings( dal_bios_parser_transmitter_control( dal_adapter_service_get_bios_parser( - enc->adapter_service), &cntl); + enc110->base.adapter_service), &cntl); } return ENCODER_RESULT_OK; @@ -1536,49 +1545,40 @@ void dce110_link_encoder_set_dp_phy_pattern( struct link_encoder *enc, const struct encoder_set_dp_phy_pattern_param *param) { - const int32_t offset = enc->be_engine_offset; - + struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); switch (param->dp_phy_pattern) { case DP_TEST_PATTERN_TRAINING_PATTERN1: - set_dp_phy_pattern_training_pattern(enc->ctx, - offset, 0); + set_dp_phy_pattern_training_pattern(enc110, 0); break; case DP_TEST_PATTERN_TRAINING_PATTERN2: - set_dp_phy_pattern_training_pattern(enc->ctx, - offset, 1); + set_dp_phy_pattern_training_pattern(enc110, 1); break; case DP_TEST_PATTERN_TRAINING_PATTERN3: - set_dp_phy_pattern_training_pattern(enc->ctx, - offset, 2); + set_dp_phy_pattern_training_pattern(enc110, 2); break; case DP_TEST_PATTERN_D102: - set_dp_phy_pattern_d102(enc->ctx, offset); + set_dp_phy_pattern_d102(enc110); break; case DP_TEST_PATTERN_SYMBOL_ERROR: - set_dp_phy_pattern_symbol_error(enc->ctx, offset); + set_dp_phy_pattern_symbol_error(enc110); break; case DP_TEST_PATTERN_PRBS7: - set_dp_phy_pattern_prbs7(enc->ctx, offset); + set_dp_phy_pattern_prbs7(enc110); break; case DP_TEST_PATTERN_80BIT_CUSTOM: set_dp_phy_pattern_80bit_custom( - enc->ctx, - offset, param->custom_pattern); + enc110, param->custom_pattern); break; case DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE: - set_dp_phy_pattern_hbr2_compliance( - enc, offset); + set_dp_phy_pattern_hbr2_compliance(enc110); break; case DP_TEST_PATTERN_VIDEO_MODE: { set_dp_phy_pattern_passthrough_mode( - enc->ctx, - offset, - param->dp_panel_mode); + enc110, param->dp_panel_mode); break; } - default: /* invalid phy pattern */ ASSERT_CRITICAL(false); @@ -1591,7 +1591,8 @@ void dce110_link_encoder_update_mst_stream_allocation_table( struct link_encoder *enc, const struct dp_mst_stream_allocation_table *table) { - int32_t addr_offset = enc->be_engine_offset; + struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); + struct dc_context *ctx = enc110->base.ctx; uint32_t value0; uint32_t value1; uint32_t retries = 0; @@ -1603,8 +1604,8 @@ void dce110_link_encoder_update_mst_stream_allocation_table( * Setup VC Payload Table on Tx Side, * Issue allocation change trigger * to commit payload on both tx and rx side */ - value0 = dal_read_reg(enc->ctx, mmDP_MSE_SAT0 + addr_offset); - value1 = dal_read_reg(enc->ctx, mmDP_MSE_SAT1 + addr_offset); + value0 = dal_read_reg(ctx, DP_REG(mmDP_MSE_SAT0)); + value1 = dal_read_reg(ctx, DP_REG(mmDP_MSE_SAT1)); if (table->stream_count >= 1) { core_stream = DC_STREAM_TO_CORE(table->stream_allocations[0].engine); @@ -1655,8 +1656,8 @@ void dce110_link_encoder_update_mst_stream_allocation_table( } /* update ASIC MSE stream allocation table */ - dal_write_reg(enc->ctx, mmDP_MSE_SAT0 + addr_offset, value0); - dal_write_reg(enc->ctx, mmDP_MSE_SAT1 + addr_offset, value1); + dal_write_reg(ctx, DP_REG(mmDP_MSE_SAT0), value0); + dal_write_reg(ctx, DP_REG(mmDP_MSE_SAT1), value1); /* --- wait for transaction finish */ @@ -1665,7 +1666,7 @@ void dce110_link_encoder_update_mst_stream_allocation_table( * then double buffers the SAT into the hardware * making the new allocation active on the DP MST mode link */ - value0 = dal_read_reg(enc->ctx, mmDP_MSE_SAT_UPDATE + addr_offset); + value0 = dal_read_reg(ctx, DP_REG(mmDP_MSE_SAT_UPDATE)); /* DP_MSE_SAT_UPDATE: * 0 - No Action @@ -1678,7 +1679,7 @@ void dce110_link_encoder_update_mst_stream_allocation_table( DP_MSE_SAT_UPDATE, DP_MSE_SAT_UPDATE); - dal_write_reg(enc->ctx, mmDP_MSE_SAT_UPDATE + addr_offset, value0); + dal_write_reg(ctx, DP_REG(mmDP_MSE_SAT_UPDATE), value0); /* wait for update to complete * (i.e. DP_MSE_SAT_UPDATE field is reset to 0) @@ -1691,10 +1692,10 @@ void dce110_link_encoder_update_mst_stream_allocation_table( * after this bit is cleared */ do { - dc_service_delay_in_microseconds(enc->ctx, 10); + dc_service_delay_in_microseconds(ctx, 10); - value0 = dal_read_reg(enc->ctx, - mmDP_MSE_SAT_UPDATE + addr_offset); + value0 = dal_read_reg(ctx, + DP_REG(mmDP_MSE_SAT_UPDATE)); value1 = get_reg_field_value( value0, @@ -1713,7 +1714,8 @@ void dce110_link_encoder_set_lcd_backlight_level( struct link_encoder *enc, uint32_t level) { - struct dc_context *ctx = enc->ctx; + struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); + struct dc_context *ctx = enc110->base.ctx; const uint32_t backlight_update_pending_max_retry = 1000; @@ -1846,7 +1848,7 @@ void dce110_link_encoder_set_lcd_backlight_level( * Configure digital transmitter and enable both encoder and transmitter * Actual output will be available after calling unblank() */ -enum encoder_result dce110_link_encoder_enable_output( +enum dc_encoder_result dce110_link_encoder_enable_output( struct link_encoder *enc, const struct link_settings *link_settings, enum engine_id engine, @@ -1855,21 +1857,20 @@ enum encoder_result dce110_link_encoder_enable_output( enum dc_color_depth color_depth, uint32_t pixel_clock) { + struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); + struct dc_context *ctx = enc110->base.ctx; struct bp_transmitter_control cntl = { 0 }; - if (enc->connector.id == CONNECTOR_ID_EDP) { + if (enc110->base.connector.id == CONNECTOR_ID_EDP) { /* power up eDP panel */ - link_encoder_edp_power_control( - enc, true); + link_encoder_edp_power_control(enc110, true); - link_encoder_edp_wait_for_hpd_ready( - enc, enc->connector, true); + link_encoder_edp_wait_for_hpd_ready(enc110, true); /* have to turn off the backlight * before power down eDP panel */ - link_encoder_edp_backlight_control( - enc, true); + link_encoder_edp_backlight_control(enc110, true); } /* Enable the PHY */ @@ -1878,15 +1879,15 @@ enum encoder_result dce110_link_encoder_enable_output( * but it's not passed to asic_control. * We need to set number of lanes manually. */ if (dc_is_dp_signal(signal)) - configure_encoder(enc, engine, link_settings); + configure_encoder(enc110, engine, link_settings); cntl.action = TRANSMITTER_CONTROL_ENABLE; cntl.engine_id = engine; - cntl.transmitter = enc->transmitter; + cntl.transmitter = enc110->base.transmitter; cntl.pll_id = clock_source; cntl.signal = signal; cntl.lanes_number = link_settings->lane_count; - cntl.hpd_sel = enc->hpd_source; + cntl.hpd_sel = enc110->base.hpd_source; if (dc_is_dp_signal(signal)) cntl.pixel_clock = link_settings->link_rate * LINK_RATE_REF_FREQ_IN_KHZ; @@ -1896,12 +1897,12 @@ enum encoder_result dce110_link_encoder_enable_output( if (DELAY_AFTER_PIXEL_FORMAT_CHANGE) dc_service_sleep_in_milliseconds( - enc->ctx, + ctx, DELAY_AFTER_PIXEL_FORMAT_CHANGE); dal_bios_parser_transmitter_control( dal_adapter_service_get_bios_parser( - enc->adapter_service), + enc110->base.adapter_service), &cntl); return ENCODER_RESULT_OK; @@ -1912,13 +1913,15 @@ void dce110_link_encoder_connect_dig_be_to_fe( enum engine_id engine, bool connect) { + struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); + struct dc_context *ctx = enc110->base.ctx; uint32_t addr; uint32_t value; uint32_t field; if (engine != ENGINE_ID_UNKNOWN) { - addr = mmDIG_BE_CNTL + enc->be_engine_offset; - value = dal_read_reg(enc->ctx, addr); + addr = DIG_REG(mmDIG_BE_CNTL); + value = dal_read_reg(ctx, addr); field = get_reg_field_value( value, @@ -1935,7 +1938,7 @@ void dce110_link_encoder_connect_dig_be_to_fe( field, DIG_BE_CNTL, DIG_FE_SOURCE_SELECT); - dal_write_reg(enc->ctx, addr, value); + dal_write_reg(ctx, addr, value); } } diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_link_encoder.h b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_link_encoder.h index 1032228..064e50c 100644 --- a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_link_encoder.h +++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_link_encoder.h @@ -26,19 +26,34 @@ #ifndef __DC_LINK_ENCODER__DCE110_H__ #define __DC_LINK_ENCODER__DCE110_H__ +#include "inc/link_encoder.h" + +#define TO_DCE110_LINK_ENC(link_encoder)\ + container_of(link_encoder, struct dce110_link_encoder, base) + +struct dce110_link_enc_offsets { + uint32_t dig_offset; + uint32_t dp_offset; +}; + +struct dce110_link_encoder { + struct link_encoder base; + struct dce110_link_enc_offsets offsets; +}; + struct link_encoder *dce110_link_encoder_create( const struct encoder_init_data *init); void dce110_link_encoder_destroy(struct link_encoder **enc); -enum encoder_result dce110_link_encoder_validate_output_with_stream( +enum dc_encoder_result dce110_link_encoder_validate_output_with_stream( struct link_encoder *enc, const struct core_stream *stream); /****************** HW programming ************************/ /* initialize HW */ /* why do we initialze aux in here? */ -enum encoder_result dce110_link_encoder_power_up(struct link_encoder *enc); +enum dc_encoder_result dce110_link_encoder_power_up(struct link_encoder *enc); /* program DIG_MODE in DIG_BE */ /* TODO can this be combined with enable_output? */ @@ -48,7 +63,7 @@ void dce110_link_encoder_setup( /* enables TMDS PHY output */ /* TODO: still need depth or just pass in adjusted pixel clock? */ -enum encoder_result dce110_link_encoder_enable_tmds_output( +enum dc_encoder_result dce110_link_encoder_enable_tmds_output( struct link_encoder *enc, enum clock_source_id clock_source, enum dc_color_depth color_depth, @@ -56,31 +71,31 @@ enum encoder_result dce110_link_encoder_enable_tmds_output( /* enables TMDS PHY output */ /* TODO: still need this or just pass in adjusted pixel clock? */ -enum encoder_result dce110_link_encoder_enable_dual_link_tmds_output( +enum dc_encoder_result dce110_link_encoder_enable_dual_link_tmds_output( struct link_encoder *enc, enum clock_source_id clock_source, enum dc_color_depth color_depth, uint32_t pixel_clock); /* enables DP PHY output */ -enum encoder_result dce110_link_encoder_enable_dp_output( +enum dc_encoder_result dce110_link_encoder_enable_dp_output( struct link_encoder *enc, const struct link_settings *link_settings, enum clock_source_id clock_source); /* enables DP PHY output in MST mode */ -enum encoder_result dce110_link_encoder_enable_dp_mst_output( +enum dc_encoder_result dce110_link_encoder_enable_dp_mst_output( struct link_encoder *enc, const struct link_settings *link_settings, enum clock_source_id clock_source); /* disable PHY output */ -enum encoder_result dce110_link_encoder_disable_output( - struct link_encoder *link_enc, +enum dc_encoder_result dce110_link_encoder_disable_output( + struct link_encoder *enc, enum signal_type signal); /* set DP lane settings */ -enum encoder_result dce110_link_encoder_dp_set_lane_settings( +enum dc_encoder_result dce110_link_encoder_dp_set_lane_settings( struct link_encoder *enc, const struct link_training_settings *link_settings); @@ -97,7 +112,7 @@ void dce110_link_encoder_set_lcd_backlight_level( struct link_encoder *enc, uint32_t level); -enum encoder_result dce110_link_encoder_enable_output( +enum dc_encoder_result dce110_link_encoder_enable_output( struct link_encoder *enc, const struct link_settings *link_settings, enum engine_id engine, diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_resource.c index 7e69dd5..77fbbe4 100644 --- a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_resource.c @@ -196,16 +196,12 @@ bool dce110_construct_resource_pool( } for (i = 0; i < pool->stream_enc_count; i++) { - struct stream_enc_init_data enc_init_data = { 0 }; - enc_init_data.stream_engine_id = i; - enc_init_data.ctx = dc->ctx; - enc_init_data.bp = dal_adapter_service_get_bios_parser( - adapter_serv); /* TODO: rework fragile code*/ if (pool->stream_engines.u_all & 1 << i) { pool->stream_enc[i] = dce110_stream_encoder_create( - &enc_init_data); - + i, dc->ctx, + dal_adapter_service_get_bios_parser( + adapter_serv)); if (pool->stream_enc[i] == NULL) { BREAK_TO_DEBUGGER(); dal_error("DC: failed to create stream_encoder!\n"); diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_stream_encoder.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_stream_encoder.c index 95dbc35..8f5560a 100644 --- a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_stream_encoder.c +++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_stream_encoder.c @@ -24,16 +24,30 @@ */ #include "dal_services.h" -#include "stream_encoder_types.h" #include "dce110_stream_encoder.h" #include "dce/dce_11_0_d.h" #include "dce/dce_11_0_sh_mask.h" #include "dce/dce_11_0_enum.h" -static const uint32_t fe_engine_offsets[] = { - mmDIG0_DIG_FE_CNTL - mmDIG0_DIG_FE_CNTL, - mmDIG1_DIG_FE_CNTL - mmDIG0_DIG_FE_CNTL, - mmDIG2_DIG_FE_CNTL - mmDIG0_DIG_FE_CNTL, +#define DIG_REG(reg)\ + (reg + enc110->offsets.dig_offset) + +#define DP_REG(reg)\ + (reg + enc110->offsets.dp_offset) + +static const struct dce110_stream_enc_offsets reg_offsets[] = { +{ + .dig_offset = (mmDIG0_DIG_FE_CNTL - mmDIG0_DIG_FE_CNTL), + .dp_offset = (mmDP0_DP_SEC_CNTL - mmDP0_DP_SEC_CNTL) +}, +{ + .dig_offset = (mmDIG1_DIG_FE_CNTL - mmDIG0_DIG_FE_CNTL), + .dp_offset = (mmDP1_DP_SEC_CNTL - mmDP0_DP_SEC_CNTL) +}, +{ + .dig_offset = (mmDIG2_DIG_FE_CNTL - mmDIG0_DIG_FE_CNTL), + .dp_offset = (mmDP1_DP_SEC_CNTL - mmDP0_DP_SEC_CNTL) +} }; #define VBI_LINE_0 0 @@ -49,21 +63,11 @@ enum { DP_MST_UPDATE_MAX_RETRY = 50 }; -static void construct( - struct stream_encoder *enc, - struct stream_enc_init_data *init) -{ - enc->ctx = init->ctx; - enc->id = init->stream_engine_id; - enc->bp = init->bp; -} - static void update_avi_info_packet( - struct stream_encoder *enc, + struct dce110_stream_encoder *enc110, const struct encoder_info_packet *info_packet) { - enum engine_id engine = enc->id; - const int32_t offset = fe_engine_offsets[engine]; + struct dc_context *ctx = enc110->base.ctx; uint32_t regval; uint32_t addr; uint32_t control0val; @@ -73,49 +77,44 @@ static void update_avi_info_packet( const uint32_t *content = (const uint32_t *) &info_packet->sb[0]; - { - regval = content[0]; - - dal_write_reg( - enc->ctx, - mmAFMT_AVI_INFO0 + offset, - regval); - } - { - regval = content[1]; - - dal_write_reg( - enc->ctx, - mmAFMT_AVI_INFO1 + offset, - regval); - } - { - regval = content[2]; - - dal_write_reg( - enc->ctx, - mmAFMT_AVI_INFO2 + offset, - regval); - } - { - regval = content[3]; - - /* move version to AVI_INFO3 */ - set_reg_field_value( - regval, - info_packet->hb1, - AFMT_AVI_INFO3, - AFMT_AVI_INFO_VERSION); + addr = DIG_REG(mmAFMT_AVI_INFO0); + regval = content[0]; + dal_write_reg( + ctx, + addr, + regval); + regval = content[1]; + + addr = DIG_REG(mmAFMT_AVI_INFO1); + dal_write_reg( + ctx, + addr, + regval); + regval = content[2]; + + addr = DIG_REG(mmAFMT_AVI_INFO2); + dal_write_reg( + ctx, + addr, + regval); + regval = content[3]; + + /* move version to AVI_INFO3 */ + addr = DIG_REG(mmAFMT_AVI_INFO3); + set_reg_field_value( + regval, + info_packet->hb1, + AFMT_AVI_INFO3, + AFMT_AVI_INFO_VERSION); - dal_write_reg( - enc->ctx, - mmAFMT_AVI_INFO3 + offset, - regval); - } + dal_write_reg( + ctx, + addr, + regval); - addr = mmHDMI_INFOFRAME_CONTROL0 + offset; + addr = DIG_REG(mmHDMI_INFOFRAME_CONTROL0); - control0val = dal_read_reg(enc->ctx, addr); + control0val = dal_read_reg(ctx, addr); set_reg_field_value( control0val, @@ -129,11 +128,11 @@ static void update_avi_info_packet( HDMI_INFOFRAME_CONTROL0, HDMI_AVI_INFO_CONT); - dal_write_reg(enc->ctx, addr, control0val); + dal_write_reg(ctx, addr, control0val); - addr = mmHDMI_INFOFRAME_CONTROL1 + offset; + addr = DIG_REG(mmHDMI_INFOFRAME_CONTROL1); - control1val = dal_read_reg(enc->ctx, addr); + control1val = dal_read_reg(ctx, addr); set_reg_field_value( control1val, @@ -141,11 +140,11 @@ static void update_avi_info_packet( HDMI_INFOFRAME_CONTROL1, HDMI_AVI_INFO_LINE); - dal_write_reg(enc->ctx, addr, control1val); + dal_write_reg(ctx, addr, control1val); } else { - addr = mmHDMI_INFOFRAME_CONTROL0 + offset; + addr = DIG_REG(mmHDMI_INFOFRAME_CONTROL0); - regval = dal_read_reg(enc->ctx, addr); + regval = dal_read_reg(ctx, addr); set_reg_field_value( regval, @@ -159,23 +158,23 @@ static void update_avi_info_packet( HDMI_INFOFRAME_CONTROL0, HDMI_AVI_INFO_CONT); - dal_write_reg(enc->ctx, addr, regval); + dal_write_reg(ctx, addr, regval); } } static void update_generic_info_packet( - struct stream_encoder *enc, + struct dce110_stream_encoder *enc110, uint32_t packet_index, const struct encoder_info_packet *info_packet) { - enum engine_id engine = enc->id; + struct dc_context *ctx = enc110->base.ctx; uint32_t addr; uint32_t regval; /* choose which generic packet to use */ { - addr = mmAFMT_VBI_PACKET_CONTROL + fe_engine_offsets[engine]; + addr = DIG_REG(mmAFMT_VBI_PACKET_CONTROL); - regval = dal_read_reg(enc->ctx, addr); + regval = dal_read_reg(ctx, addr); set_reg_field_value( regval, @@ -183,13 +182,13 @@ static void update_generic_info_packet( AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_INDEX); - dal_write_reg(enc->ctx, addr, regval); + dal_write_reg(ctx, addr, regval); } /* write generic packet header * (4th byte is for GENERIC0 only) */ { - addr = mmAFMT_GENERIC_HDR + fe_engine_offsets[engine]; + addr = DIG_REG(mmAFMT_GENERIC_HDR); regval = 0; @@ -217,7 +216,7 @@ static void update_generic_info_packet( AFMT_GENERIC_HDR, AFMT_GENERIC_HB3); - dal_write_reg(enc->ctx, addr, regval); + dal_write_reg(ctx, addr, regval); } /* write generic packet contents @@ -229,25 +228,27 @@ static void update_generic_info_packet( uint32_t counter = 0; - addr = mmAFMT_GENERIC_0 + fe_engine_offsets[engine]; + addr = DIG_REG(mmAFMT_GENERIC_0); do { - dal_write_reg(enc->ctx, addr++, *content++); + dal_write_reg(ctx, addr++, *content++); ++counter; } while (counter < 7); } + addr = DIG_REG(mmAFMT_GENERIC_7); + dal_write_reg( - enc->ctx, - mmAFMT_GENERIC_7 + fe_engine_offsets[engine], + ctx, + addr, 0); /* force double-buffered packet update */ { - addr = mmAFMT_VBI_PACKET_CONTROL + fe_engine_offsets[engine]; + addr = DIG_REG(mmAFMT_VBI_PACKET_CONTROL); - regval = dal_read_reg(enc->ctx, addr); + regval = dal_read_reg(ctx, addr); set_reg_field_value( regval, @@ -261,23 +262,23 @@ static void update_generic_info_packet( AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC2_UPDATE); - dal_write_reg(enc->ctx, addr, regval); + dal_write_reg(ctx, addr, regval); } } static void update_hdmi_info_packet( - struct stream_encoder *enc, + struct dce110_stream_encoder *enc110, uint32_t packet_index, const struct encoder_info_packet *info_packet) { - enum engine_id engine = enc->id; + struct dc_context *ctx = enc110->base.ctx; uint32_t cont, send, line; - uint32_t addr = fe_engine_offsets[engine]; + uint32_t addr; uint32_t regval; if (info_packet->valid) { update_generic_info_packet( - enc, + enc110, packet_index, info_packet); @@ -299,24 +300,24 @@ static void update_hdmi_info_packet( switch (packet_index) { case 0: case 1: - addr += mmHDMI_GENERIC_PACKET_CONTROL0; + addr = DIG_REG(mmHDMI_GENERIC_PACKET_CONTROL0); break; case 2: case 3: - addr += mmHDMI_GENERIC_PACKET_CONTROL1; + addr = DIG_REG(mmHDMI_GENERIC_PACKET_CONTROL1); break; default: /* invalid HW packet index */ dal_logger_write( - enc->ctx->logger, + ctx->logger, LOG_MAJOR_WARNING, LOG_MINOR_COMPONENT_ENCODER, "Invalid HW packet index: %s()\n", __func__); - break; + return; } - regval = dal_read_reg(enc->ctx, addr); + regval = dal_read_reg(ctx, addr); switch (packet_index) { case 0: @@ -358,37 +359,37 @@ static void update_hdmi_info_packet( default: /* invalid HW packet index */ dal_logger_write( - enc->ctx->logger, + ctx->logger, LOG_MAJOR_WARNING, LOG_MINOR_COMPONENT_ENCODER, "Invalid HW packet index: %s()\n", __func__); - break; + return; } - dal_write_reg(enc->ctx, addr, regval); + dal_write_reg(ctx, addr, regval); } static void update_dp_info_packet( - struct stream_encoder *enc, + struct dce110_stream_encoder *enc110, uint32_t packet_index, const struct encoder_info_packet *info_packet) { - enum engine_id engine = enc->id; - const uint32_t addr = mmDP_SEC_CNTL + fe_engine_offsets[engine]; + struct dc_context *ctx = enc110->base.ctx; + uint32_t addr = DP_REG(mmDP_SEC_CNTL); uint32_t value; if (info_packet->valid) update_generic_info_packet( - enc, + enc110, packet_index, info_packet); /* enable/disable transmission of packet(s). * If enabled, packet transmission begins on the next frame */ - value = dal_read_reg(enc->ctx, addr); + value = dal_read_reg(ctx, addr); switch (packet_index) { case 0: @@ -439,16 +440,15 @@ static void update_dp_info_packet( DP_SEC_CNTL, DP_SEC_STREAM_ENABLE); - dal_write_reg(enc->ctx, addr, value); + dal_write_reg(ctx, addr, value); } static void dp_steer_fifo_reset( - struct stream_encoder *enc, + struct dce110_stream_encoder *enc110, bool reset) { - struct dc_context *ctx = enc->ctx; - enum engine_id engine = enc->id; - const uint32_t addr = mmDP_STEER_FIFO + fe_engine_offsets[engine]; + struct dc_context *ctx = enc110->base.ctx; + const uint32_t addr = DP_REG(mmDP_STEER_FIFO); uint32_t value = dal_read_reg(ctx, addr); @@ -458,24 +458,24 @@ static void dp_steer_fifo_reset( } static void unblank_dp_output( - struct stream_encoder *enc) + struct dce110_stream_encoder *enc110) { - enum engine_id engine = enc->id; + struct dc_context *ctx = enc110->base.ctx; uint32_t addr; uint32_t value; /* set DIG_START to 0x1 to resync FIFO */ - addr = mmDIG_FE_CNTL + fe_engine_offsets[engine]; - value = dal_read_reg(enc->ctx, addr); + addr = DIG_REG(mmDIG_FE_CNTL); + value = dal_read_reg(ctx, addr); set_reg_field_value(value, 1, DIG_FE_CNTL, DIG_START); - dal_write_reg(enc->ctx, addr, value); + dal_write_reg(ctx, addr, value); /* switch DP encoder to CRTC data */ - dp_steer_fifo_reset(enc, false); + dp_steer_fifo_reset(enc110, false); /* wait 100us for DIG/DP logic to prime * (i.e. a few video lines) */ - dc_service_delay_in_microseconds(enc->ctx, 100); + dc_service_delay_in_microseconds(ctx, 100); /* the hardware would start sending video at the start of the next DP * frame (i.e. rising edge of the vblank). @@ -483,59 +483,59 @@ static void unblank_dp_output( * register has no effect on enable transition! HW always guarantees * VID_STREAM enable at start of next frame, and this is not * programmable */ - addr = mmDP_VID_STREAM_CNTL + fe_engine_offsets[engine]; - value = dal_read_reg(enc->ctx, addr); + addr = DP_REG(mmDP_VID_STREAM_CNTL); + value = dal_read_reg(ctx, addr); set_reg_field_value( value, true, DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE); - dal_write_reg(enc->ctx, addr, value); + dal_write_reg(ctx, addr, value); } static void setup_vid_stream( - struct stream_encoder *enc, + struct dce110_stream_encoder *enc110, uint32_t m_vid, uint32_t n_vid) { - enum engine_id engine = enc->id; + struct dc_context *ctx = enc110->base.ctx; uint32_t addr; uint32_t value; /* enable auto measurement */ - addr = mmDP_VID_TIMING + fe_engine_offsets[engine]; - value = dal_read_reg(enc->ctx, addr); + addr = DP_REG(mmDP_VID_TIMING); + value = dal_read_reg(ctx, addr); set_reg_field_value(value, 0, DP_VID_TIMING, DP_VID_M_N_GEN_EN); - dal_write_reg(enc->ctx, addr, value); + dal_write_reg(ctx, addr, value); /* auto measurement need 1 full 0x8000 symbol cycle to kick in, * therefore program initial value for Mvid and Nvid */ - addr = mmDP_VID_N + fe_engine_offsets[engine]; - value = dal_read_reg(enc->ctx, addr); + addr = DP_REG(mmDP_VID_N); + value = dal_read_reg(ctx, addr); set_reg_field_value(value, n_vid, DP_VID_N, DP_VID_N); - dal_write_reg(enc->ctx, addr, value); + dal_write_reg(ctx, addr, value); - addr = mmDP_VID_M + fe_engine_offsets[engine]; - value = dal_read_reg(enc->ctx, addr); + addr = DP_REG(mmDP_VID_M); + value = dal_read_reg(ctx, addr); set_reg_field_value(value, m_vid, DP_VID_M, DP_VID_M); - dal_write_reg(enc->ctx, addr, value); + dal_write_reg(ctx, addr, value); - addr = mmDP_VID_TIMING + fe_engine_offsets[engine]; - value = dal_read_reg(enc->ctx, addr); + addr = DP_REG(mmDP_VID_TIMING); + value = dal_read_reg(ctx, addr); set_reg_field_value(value, 1, DP_VID_TIMING, DP_VID_M_N_GEN_EN); - dal_write_reg(enc->ctx, addr, value); + dal_write_reg(ctx, addr, value); } static void set_tmds_stream_attributes( - struct stream_encoder *enc, + struct dce110_stream_encoder *enc110, const struct dc_crtc_timing *timing, bool is_dvi ) { - enum engine_id engine = enc->id; - uint32_t addr = mmDIG_FE_CNTL + fe_engine_offsets[engine]; - uint32_t value = dal_read_reg(enc->ctx, addr); + struct dc_context *ctx = enc110->base.ctx; + uint32_t addr = DIG_REG(mmDIG_FE_CNTL); + uint32_t value = dal_read_reg(ctx, addr); switch (timing->pixel_encoding) { case PIXEL_ENCODING_YCBCR422: @@ -566,16 +566,16 @@ static void set_tmds_stream_attributes( set_reg_field_value(value, 0, DIG_FE_CNTL, TMDS_COLOR_FORMAT); break; } - dal_write_reg(enc->ctx, addr, value); + dal_write_reg(ctx, addr, value); } static void set_dp_stream_attributes( - struct stream_encoder *enc, + struct dce110_stream_encoder *enc110, const struct dc_crtc_timing *timing) { - enum engine_id engine = enc->id; - const uint32_t addr = mmDP_PIXEL_FORMAT + fe_engine_offsets[engine]; - uint32_t value = dal_read_reg(enc->ctx, addr); + struct dc_context *ctx = enc110->base.ctx; + const uint32_t addr = DP_REG(mmDP_PIXEL_FORMAT); + uint32_t value = dal_read_reg(ctx, addr); /* set pixel encoding */ switch (timing->pixel_encoding) { @@ -654,20 +654,20 @@ static void set_dp_stream_attributes( set_reg_field_value(value, 0, DP_PIXEL_FORMAT, DP_DYN_RANGE); set_reg_field_value(value, 0, DP_PIXEL_FORMAT, DP_YCBCR_RANGE); - dal_write_reg(enc->ctx, addr, value); + dal_write_reg(ctx, addr, value); } static void setup_hdmi( - struct stream_encoder *enc, + struct dce110_stream_encoder *enc110, const struct dc_crtc_timing *timing) { - enum engine_id engine = enc->id; + struct dc_context *ctx = enc110->base.ctx; uint32_t output_pixel_clock = timing->pix_clk_khz; uint32_t value; uint32_t addr; - addr = mmHDMI_CONTROL + fe_engine_offsets[engine]; - value = dal_read_reg(enc->ctx, addr); + addr = DIG_REG(mmHDMI_CONTROL); + value = dal_read_reg(ctx, addr); set_reg_field_value(value, 1, HDMI_CONTROL, HDMI_PACKET_GEN_VERSION); set_reg_field_value(value, 1, HDMI_CONTROL, HDMI_KEEPOUT_MODE); set_reg_field_value(value, 0, HDMI_CONTROL, HDMI_DEEP_COLOR_ENABLE); @@ -761,71 +761,89 @@ static void setup_hdmi( HDMI_CLOCK_CHANNEL_RATE); } - dal_write_reg(enc->ctx, addr, value); + dal_write_reg(ctx, addr, value); - addr = mmHDMI_VBI_PACKET_CONTROL + fe_engine_offsets[engine]; - value = dal_read_reg(enc->ctx, addr); + addr = DIG_REG(mmHDMI_VBI_PACKET_CONTROL); + value = dal_read_reg(ctx, addr); set_reg_field_value(value, 1, HDMI_VBI_PACKET_CONTROL, HDMI_GC_CONT); set_reg_field_value(value, 1, HDMI_VBI_PACKET_CONTROL, HDMI_GC_SEND); set_reg_field_value(value, 1, HDMI_VBI_PACKET_CONTROL, HDMI_NULL_SEND); - dal_write_reg(enc->ctx, addr, value); + dal_write_reg(ctx, addr, value); /* following belongs to audio */ - addr = mmHDMI_INFOFRAME_CONTROL0 + fe_engine_offsets[engine]; - value = dal_read_reg(enc->ctx, addr); + addr = DIG_REG(mmHDMI_INFOFRAME_CONTROL0); + value = dal_read_reg(ctx, addr); set_reg_field_value( value, 1, HDMI_INFOFRAME_CONTROL0, HDMI_AUDIO_INFO_SEND); - dal_write_reg(enc->ctx, addr, value); + dal_write_reg(ctx, addr, value); - addr = mmAFMT_INFOFRAME_CONTROL0 + fe_engine_offsets[engine]; - value = dal_read_reg(enc->ctx, addr); + addr = DIG_REG(mmAFMT_INFOFRAME_CONTROL0); + value = dal_read_reg(ctx, addr); set_reg_field_value( value, 1, AFMT_INFOFRAME_CONTROL0, AFMT_AUDIO_INFO_UPDATE); - dal_write_reg(enc->ctx, addr, value); + dal_write_reg(ctx, addr, value); - addr = mmHDMI_INFOFRAME_CONTROL1 + fe_engine_offsets[engine]; - value = dal_read_reg(enc->ctx, addr); + addr = DIG_REG(mmHDMI_INFOFRAME_CONTROL1); + value = dal_read_reg(ctx, addr); set_reg_field_value( value, VBI_LINE_0 + 2, HDMI_INFOFRAME_CONTROL1, HDMI_AUDIO_INFO_LINE); - dal_write_reg(enc->ctx, addr, value); + dal_write_reg(ctx, addr, value); - addr = mmHDMI_GC + fe_engine_offsets[engine]; - value = dal_read_reg(enc->ctx, addr); + addr = DIG_REG(mmHDMI_GC); + value = dal_read_reg(ctx, addr); set_reg_field_value(value, 0, HDMI_GC, HDMI_GC_AVMUTE); - dal_write_reg(enc->ctx, addr, value); + dal_write_reg(ctx, addr, value); } -struct stream_encoder *dce110_stream_encoder_create( - struct stream_enc_init_data *init) +bool dce110_stream_encoder_construct( + struct dce110_stream_encoder *enc110, + struct dc_context *ctx, + struct bios_parser *bp, + enum engine_id eng_id) { - struct stream_encoder *enc = - dc_service_alloc(init->ctx, sizeof(struct stream_encoder)); + if (eng_id > ARRAY_SIZE(reg_offsets)) + return false; + + enc110->base.ctx = ctx; + enc110->base.id = eng_id; + enc110->base.bp = bp; + enc110->offsets = reg_offsets[eng_id]; - if (!enc) - goto enc_create_fail; + return true; +} - construct(enc, init); +struct stream_encoder *dce110_stream_encoder_create( + enum engine_id eng_id, + struct dc_context *ctx, + struct bios_parser *bp) +{ + struct dce110_stream_encoder *enc110 = + dc_service_alloc(ctx, sizeof(struct dce110_stream_encoder)); - return enc; + if (!enc110) + return NULL; + if (dce110_stream_encoder_construct(enc110, ctx, bp, eng_id)) + return &enc110->base; -enc_create_fail: + BREAK_TO_DEBUGGER(); + dc_service_free(ctx, enc110); return NULL; } void dce110_stream_encoder_destroy(struct stream_encoder **enc) { - dc_service_free((*enc)->ctx, *enc); + dc_service_free((*enc)->ctx, TO_DCE110_STREAM_ENC(*enc)); *enc = NULL; } @@ -834,7 +852,9 @@ void dce110_stream_encoder_dp_set_stream_attribute( struct stream_encoder *enc, struct dc_crtc_timing *crtc_timing) { - set_dp_stream_attributes(enc, crtc_timing); + struct dce110_stream_encoder *enc110 = TO_DCE110_STREAM_ENC(enc); + + set_dp_stream_attributes(enc110, crtc_timing); } /* setup stream encoder in hdmi mode */ @@ -843,10 +863,11 @@ void dce110_stream_encoder_hdmi_set_stream_attribute( struct dc_crtc_timing *crtc_timing, bool enable_audio) { + struct dce110_stream_encoder *enc110 = TO_DCE110_STREAM_ENC(enc); struct bp_encoder_control cntl = {0}; cntl.action = ENCODER_CONTROL_SETUP; - cntl.engine_id = enc->id; + cntl.engine_id = enc110->base.id; cntl.signal = SIGNAL_TYPE_HDMI_TYPE_A; cntl.enable_dp_audio = enable_audio; cntl.pixel_clock = crtc_timing->pix_clk_khz; @@ -858,10 +879,10 @@ void dce110_stream_encoder_hdmi_set_stream_attribute( return; - set_tmds_stream_attributes(enc, crtc_timing, false); + set_tmds_stream_attributes(enc110, crtc_timing, false); /* setup HDMI engine */ - setup_hdmi(enc, crtc_timing); + setup_hdmi(enc110, crtc_timing); } /* setup stream encoder in dvi mode */ @@ -870,10 +891,11 @@ void dce110_stream_encoder_dvi_set_stream_attribute( struct dc_crtc_timing *crtc_timing, bool is_dual_link) { + struct dce110_stream_encoder *enc110 = TO_DCE110_STREAM_ENC(enc); struct bp_encoder_control cntl = {0}; cntl.action = ENCODER_CONTROL_SETUP; - cntl.engine_id = enc->id; + cntl.engine_id = enc110->base.id; cntl.signal = is_dual_link ? SIGNAL_TYPE_DVI_DUAL_LINK : SIGNAL_TYPE_DVI_SINGLE_LINK; @@ -884,31 +906,34 @@ void dce110_stream_encoder_dvi_set_stream_attribute( cntl.color_depth = crtc_timing->display_color_depth; if (dal_bios_parser_encoder_control( - enc->bp, &cntl) != BP_RESULT_OK) + enc110->base.bp, &cntl) != BP_RESULT_OK) return; - set_tmds_stream_attributes(enc, crtc_timing, true); + set_tmds_stream_attributes(enc110, crtc_timing, true); } void dce110_stream_encoder_set_mst_bandwidth( struct stream_encoder *enc, struct fixed31_32 avg_time_slots_per_mtp) { + struct dce110_stream_encoder *enc110 = TO_DCE110_STREAM_ENC(enc); + struct dc_context *ctx = enc110->base.ctx; + uint32_t addr; + uint32_t field; + uint32_t value; + uint32_t retries = 0; uint32_t x = dal_fixed31_32_floor( avg_time_slots_per_mtp); - uint32_t y = dal_fixed31_32_ceil( dal_fixed31_32_shl( dal_fixed31_32_sub_int( avg_time_slots_per_mtp, x), 26)); - enum engine_id engine = enc->id; { - const uint32_t addr = mmDP_MSE_RATE_CNTL + - fe_engine_offsets[engine]; - uint32_t value = dal_read_reg(enc->ctx, addr); + addr = DP_REG(mmDP_MSE_RATE_CNTL); + value = dal_read_reg(ctx, addr); set_reg_field_value( value, @@ -922,20 +947,17 @@ void dce110_stream_encoder_set_mst_bandwidth( DP_MSE_RATE_CNTL, DP_MSE_RATE_Y); - dal_write_reg(enc->ctx, addr, value); + dal_write_reg(ctx, addr, value); } /* wait for update to be completed on the link */ /* i.e. DP_MSE_RATE_UPDATE_PENDING field (read only) */ /* is reset to 0 (not pending) */ { - const uint32_t addr = mmDP_MSE_RATE_UPDATE + - fe_engine_offsets[engine]; - uint32_t value, field; - uint32_t retries = 0; + addr = DP_REG(mmDP_MSE_RATE_UPDATE); do { - value = dal_read_reg(enc->ctx, addr); + value = dal_read_reg(ctx, addr); field = get_reg_field_value( value, @@ -946,7 +968,7 @@ void dce110_stream_encoder_set_mst_bandwidth( DP_MSE_RATE_UPDATE__DP_MSE_RATE_UPDATE_PENDING_MASK)) break; - dc_service_delay_in_microseconds(enc->ctx, 10); + dc_service_delay_in_microseconds(ctx, 10); ++retries; } while (retries < DP_MST_UPDATE_MAX_RETRY); @@ -957,25 +979,26 @@ void dce110_stream_encoder_update_hdmi_info_packets( struct stream_encoder *enc, const struct encoder_info_frame *info_frame) { + struct dce110_stream_encoder *enc110 = TO_DCE110_STREAM_ENC(enc); + update_avi_info_packet( - enc, + enc110, &info_frame->avi); - update_hdmi_info_packet(enc, 0, &info_frame->vendor); - update_hdmi_info_packet(enc, 1, &info_frame->gamut); - update_hdmi_info_packet(enc, 2, &info_frame->spd); + update_hdmi_info_packet(enc110, 0, &info_frame->vendor); + update_hdmi_info_packet(enc110, 1, &info_frame->gamut); + update_hdmi_info_packet(enc110, 2, &info_frame->spd); } void dce110_stream_encoder_stop_hdmi_info_packets( struct stream_encoder *enc) { - struct dc_context *ctx = enc->ctx; - enum engine_id engine = enc->id; + struct dce110_stream_encoder *enc110 = TO_DCE110_STREAM_ENC(enc); + struct dc_context *ctx = enc110->base.ctx; uint32_t addr = 0; uint32_t value = 0; - uint32_t offset = fe_engine_offsets[engine]; /* stop generic packets 0 & 1 on HDMI */ - addr = mmHDMI_GENERIC_PACKET_CONTROL0 + offset; + addr = DIG_REG(mmHDMI_GENERIC_PACKET_CONTROL0); value = dal_read_reg(ctx, addr); @@ -1013,7 +1036,7 @@ void dce110_stream_encoder_stop_hdmi_info_packets( dal_write_reg(ctx, addr, value); /* stop generic packets 2 & 3 on HDMI */ - addr = mmHDMI_GENERIC_PACKET_CONTROL1 + offset; + addr = DIG_REG(mmHDMI_GENERIC_PACKET_CONTROL1); value = dal_read_reg(ctx, addr); @@ -1051,7 +1074,7 @@ void dce110_stream_encoder_stop_hdmi_info_packets( dal_write_reg(ctx, addr, value); /* stop AVI packet on HDMI */ - addr = mmHDMI_INFOFRAME_CONTROL0 + offset; + addr = DIG_REG(mmHDMI_INFOFRAME_CONTROL0); value = dal_read_reg(ctx, addr); @@ -1072,17 +1095,18 @@ void dce110_stream_encoder_update_dp_info_packets( struct stream_encoder *enc, const struct encoder_info_frame *info_frame) { - update_dp_info_packet(enc, 0, &info_frame->vsc); + struct dce110_stream_encoder *enc110 = TO_DCE110_STREAM_ENC(enc); + + update_dp_info_packet(enc110, 0, &info_frame->vsc); } void dce110_stream_encoder_stop_dp_info_packets( struct stream_encoder *enc) { /* stop generic packets on DP */ - struct dc_context *ctx = enc->ctx; - enum engine_id engine = enc->id; - uint32_t offset = fe_engine_offsets[engine]; - const uint32_t addr = mmDP_SEC_CNTL + offset; + struct dce110_stream_encoder *enc110 = TO_DCE110_STREAM_ENC(enc); + struct dc_context *ctx = enc110->base.ctx; + uint32_t addr = DP_REG(mmDP_SEC_CNTL); uint32_t value = dal_read_reg(ctx, addr); set_reg_field_value(value, 0, DP_SEC_CNTL, DP_SEC_GSP0_ENABLE); @@ -1110,9 +1134,10 @@ void dce110_stream_encoder_stop_dp_info_packets( void dce110_stream_encoder_dp_blank( struct stream_encoder *enc) { - enum engine_id engine = enc->id; - const uint32_t addr = mmDP_VID_STREAM_CNTL + fe_engine_offsets[engine]; - uint32_t value = dal_read_reg(enc->ctx, addr); + struct dce110_stream_encoder *enc110 = TO_DCE110_STREAM_ENC(enc); + struct dc_context *ctx = enc110->base.ctx; + uint32_t addr = DP_REG(mmDP_VID_STREAM_CNTL); + uint32_t value = dal_read_reg(ctx, addr); uint32_t retries = 0; uint32_t max_retries = DP_BLANK_MAX_RETRY * 10; @@ -1137,14 +1162,14 @@ void dce110_stream_encoder_dp_blank( /* disable DP stream */ set_reg_field_value(value, 0, DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE); - dal_write_reg(enc->ctx, addr, value); + dal_write_reg(ctx, addr, value); /* the encoder stops sending the video stream * at the start of the vertical blanking. * Poll for DP_VID_STREAM_STATUS == 0 */ do { - value = dal_read_reg(enc->ctx, addr); + value = dal_read_reg(ctx, addr); if (!get_reg_field_value( value, @@ -1152,7 +1177,7 @@ void dce110_stream_encoder_dp_blank( DP_VID_STREAM_STATUS)) break; - dc_service_delay_in_microseconds(enc->ctx, 10); + dc_service_delay_in_microseconds(ctx, 10); ++retries; } while (retries < max_retries); @@ -1163,7 +1188,7 @@ void dce110_stream_encoder_dp_blank( * the polling. If we set DP_STEER_FIFO_RESET before DP stream blank is * complete, stream status will be stuck in video stream enabled state, * i.e. DP_VID_STREAM_STATUS stuck at 1. */ - dp_steer_fifo_reset(enc, true); + dp_steer_fifo_reset(enc110, true); } /* output video stream to link encoder */ @@ -1171,6 +1196,8 @@ void dce110_stream_encoder_dp_unblank( struct stream_encoder *enc, const struct encoder_unblank_param *param) { + struct dce110_stream_encoder *enc110 = TO_DCE110_STREAM_ENC(enc); + if (param->link_settings.link_rate != LINK_RATE_UNKNOWN) { uint32_t n_vid = 0x8000; uint32_t m_vid; @@ -1187,9 +1214,9 @@ void dce110_stream_encoder_dp_unblank( m_vid = (uint32_t) m_vid_l; - setup_vid_stream(enc, m_vid, n_vid); + setup_vid_stream(enc110, m_vid, n_vid); } - unblank_dp_output(enc); + unblank_dp_output(enc110); } diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_stream_encoder.h b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_stream_encoder.h index a520691..8d859a9 100644 --- a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_stream_encoder.h +++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_stream_encoder.h @@ -26,14 +26,25 @@ #ifndef __DC_STREAM_ENCODER_DCE110_H__ #define __DC_STREAM_ENCODER_DCE110_H__ -struct stream_enc_init_data { - enum engine_id stream_engine_id; - struct bios_parser *bp; - struct dc_context *ctx; +#include "inc/stream_encoder.h" + +#define TO_DCE110_STREAM_ENC(stream_encoder)\ + container_of(stream_encoder, struct dce110_stream_encoder, base) + +struct dce110_stream_enc_offsets { + uint32_t dig_offset; + uint32_t dp_offset; +}; + +struct dce110_stream_encoder { + struct stream_encoder base; + struct dce110_stream_enc_offsets offsets; }; struct stream_encoder *dce110_stream_encoder_create( - struct stream_enc_init_data *init); + enum engine_id eng_id, + struct dc_context *ctx, + struct bios_parser *bp); void dce110_stream_encoder_destroy(struct stream_encoder **enc); diff --git a/drivers/gpu/drm/amd/dal/dc/inc/core_types.h b/drivers/gpu/drm/amd/dal/dc/inc/core_types.h index b636a9c..ecc1cdc 100644 --- a/drivers/gpu/drm/amd/dal/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/dal/dc/inc/core_types.h @@ -64,7 +64,7 @@ void enable_surface_flip_reporting(struct dc_surface *dc_surface, /********* core_stream ************/ #include "grph_object_id.h" -#include "encoder_interface.h" +#include "encoder_types.h" #include "clock_source_interface.h" #include "audio_interface.h" diff --git a/drivers/gpu/drm/amd/dal/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/dal/dc/inc/hw_sequencer.h index 99a0458..c4151c1 100644 --- a/drivers/gpu/drm/amd/dal/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/dal/dc/inc/hw_sequencer.h @@ -90,10 +90,10 @@ struct hw_sequencer_funcs { void (*encoder_destroy)(struct link_encoder **enc); - enum encoder_result (*encoder_power_up)( + enum dc_encoder_result (*encoder_power_up)( struct link_encoder *enc); - enum encoder_result (*encoder_enable_output)( + enum dc_encoder_result (*encoder_enable_output)( struct link_encoder *enc, const struct link_settings *link_settings, enum engine_id engine, @@ -102,7 +102,7 @@ struct hw_sequencer_funcs { enum dc_color_depth color_depth, uint32_t pixel_clock); - enum encoder_result (*encoder_disable_output)( + enum dc_encoder_result (*encoder_disable_output)( struct link_encoder *enc, enum signal_type signal); @@ -110,7 +110,7 @@ struct hw_sequencer_funcs { struct link_encoder *enc, const struct encoder_set_dp_phy_pattern_param *param); - enum encoder_result (*encoder_dp_set_lane_settings)( + enum dc_encoder_result (*encoder_dp_set_lane_settings)( struct link_encoder *enc, const struct link_training_settings *link_settings); diff --git a/drivers/gpu/drm/amd/dal/dc/inc/link_encoder.h b/drivers/gpu/drm/amd/dal/dc/inc/link_encoder.h new file mode 100644 index 0000000..8b19b00 --- /dev/null +++ b/drivers/gpu/drm/amd/dal/dc/inc/link_encoder.h @@ -0,0 +1,28 @@ +/* + * link_encoder.h + * + * Created on: Oct 6, 2015 + * Author: yonsun + */ + +#ifndef LINK_ENCODER_H_ +#define LINK_ENCODER_H_ + +struct link_enc_status { + int dummy; /*TODO*/ +}; +struct link_encoder { + struct adapter_service *adapter_service; + int32_t aux_channel_offset; + struct dc_context *ctx; + struct graphics_object_id id; + struct graphics_object_id connector; + uint32_t input_signals; + uint32_t output_signals; + enum engine_id preferred_engine; + struct encoder_feature_support features; + enum transmitter transmitter; + enum hpd_source_id hpd_source; +}; + +#endif /* LINK_ENCODER_H_ */ diff --git a/drivers/gpu/drm/amd/dal/dc/inc/stream_encoder.h b/drivers/gpu/drm/amd/dal/dc/inc/stream_encoder.h new file mode 100644 index 0000000..d2da14a --- /dev/null +++ b/drivers/gpu/drm/amd/dal/dc/inc/stream_encoder.h @@ -0,0 +1,18 @@ +/* + * stream_encoder.h + * + */ + +#ifndef STREAM_ENCODER_H_ +#define STREAM_ENCODER_H_ + +#include "include/encoder_types.h" +#include "include/bios_parser_interface.h" + +struct stream_encoder { + struct dc_context *ctx; + struct bios_parser *bp; + enum engine_id id; +}; + +#endif /* STREAM_ENCODER_H_ */ diff --git a/drivers/gpu/drm/amd/dal/include/encoder_types.h b/drivers/gpu/drm/amd/dal/include/encoder_types.h index e32498d..c267d30 100644 --- a/drivers/gpu/drm/amd/dal/include/encoder_types.h +++ b/drivers/gpu/drm/amd/dal/include/encoder_types.h @@ -31,6 +31,16 @@ #include "hw_sequencer_types.h" #include "link_service_types.h" +struct encoder_init_data { + struct adapter_service *adapter_service; + enum channel_id channel; + struct graphics_object_id connector; + enum hpd_source_id hpd_source; + /* TODO: in DAL2, here was pointer to EventManagerInterface */ + struct graphics_object_id encoder; + struct dc_context *ctx; +}; + struct encoder_context { /* * HW programming context diff --git a/drivers/gpu/drm/amd/dal/include/link_encoder_types.h b/drivers/gpu/drm/amd/dal/include/link_encoder_types.h deleted file mode 100644 index 2a59902..0000000 --- a/drivers/gpu/drm/amd/dal/include/link_encoder_types.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * link_encoder_types.h - * - * Created on: Oct 6, 2015 - * Author: yonsun - */ - -#ifndef DRIVERS_GPU_DRM_AMD_DAL_DEV_INCLUDE_LINK_ENCODER_TYPES_H_ -#define DRIVERS_GPU_DRM_AMD_DAL_DEV_INCLUDE_LINK_ENCODER_TYPES_H_ - -#include "encoder_interface.h" - -struct link_enc_status { - int dummy; /*TODO*/ -}; -struct link_encoder { - struct adapter_service *adapter_service; - int32_t be_engine_offset; - int32_t aux_channel_offset; - int32_t transmitter_offset; - struct dc_context *ctx; - struct graphics_object_id id; - struct graphics_object_id connector; - uint32_t input_signals; - uint32_t output_signals; - enum engine_id preferred_engine; - struct encoder_feature_support features; - enum transmitter transmitter; - enum hpd_source_id hpd_source; -}; - -#endif /* DRIVERS_GPU_DRM_AMD_DAL_DEV_INCLUDE_LINK_ENCODER_TYPES_H_ */ diff --git a/drivers/gpu/drm/amd/dal/include/stream_encoder_types.h b/drivers/gpu/drm/amd/dal/include/stream_encoder_types.h deleted file mode 100644 index c0bc656..0000000 --- a/drivers/gpu/drm/amd/dal/include/stream_encoder_types.h +++ /dev/null @@ -1,16 +0,0 @@ -/* - * stream_encoder_types.h - * - */ -#include "encoder_interface.h" - -#ifndef STREAM_ENCODER_TYPES_H_ -#define STREAM_ENCODER_TYPES_H_ - -struct stream_encoder { - enum engine_id id; - struct bios_parser *bp; - struct dc_context *ctx; -}; - -#endif /* STREAM_ENCODER_TYPES_H_ */ -- 2.7.4