diff options
author | Dave Airlie <airlied@redhat.com> | 2019-01-31 14:19:45 +1000 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2019-02-01 09:34:20 +1000 |
commit | e09191d360ab54c7ac7a9b09287dcab81c30d8e3 (patch) | |
tree | be0c0a0ed2f0603ecaa430bd09811484adc04ee6 /drivers/gpu/drm/amd/display/dc | |
parent | f91168f48556486743392b8838e20afbd84b7b7a (diff) | |
parent | 10117450735c7a7c0858095fb46a860e7037cb9a (diff) |
Merge branch 'drm-next-5.1' of git://people.freedesktop.org/~agd5f/linux into drm-next
New stuff for 5.1.
amdgpu:
- DC bandwidth formula updates
- Support for DCC on scanout surfaces
- Support for multiple IH rings on soc15 asics
- Fix xgmi locking
- Add sysfs interface to get pcie usage stats
- Simplify DC i2c/aux code
- Initial support for BACO on vega10/20
- New runtime SMU feature debug interface
- Expand existing sysfs power interfaces to new clock domains
- Handle kexec properly
- Simplify IH programming
- Rework doorbell handling across asics
- Drop old CI DPM implementation
- DC page flipping fixes
- Misc SR-IOV fixes
amdkfd:
- Simplify the interfaces between amdkfd and amdgpu
ttm:
- Add a callback to notify the driver when the lru changes
sched:
- Refactor mirror list handling
- Rework hw fence processing
Signed-off-by: Dave Airlie <airlied@redhat.com>
From: Alex Deucher <alexdeucher@gmail.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20190125231517.26268-1-alexander.deucher@amd.com
Diffstat (limited to 'drivers/gpu/drm/amd/display/dc')
123 files changed, 1771 insertions, 9315 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/Makefile b/drivers/gpu/drm/amd/display/dc/Makefile index aed538a4d1ba..b8ddb4acccdb 100644 --- a/drivers/gpu/drm/amd/display/dc/Makefile +++ b/drivers/gpu/drm/amd/display/dc/Makefile @@ -23,7 +23,7 @@ # Makefile for Display Core (dc) component. # -DC_LIBS = basics bios calcs dce gpio i2caux irq virtual +DC_LIBS = basics bios calcs dce gpio irq virtual ifdef CONFIG_DRM_AMD_DC_DCN1_0 DC_LIBS += dcn10 dml @@ -41,7 +41,8 @@ AMD_DC = $(addsuffix /Makefile, $(addprefix $(FULL_AMD_DISPLAY_PATH)/dc/,$(DC_LI include $(AMD_DC) DISPLAY_CORE = dc.o dc_link.o dc_resource.o dc_hw_sequencer.o dc_sink.o \ -dc_surface.o dc_link_hwss.o dc_link_dp.o dc_link_ddc.o dc_debug.o dc_stream.o +dc_surface.o dc_link_hwss.o dc_link_dp.o dc_link_ddc.o dc_debug.o dc_stream.o \ +dc_vm_helper.o AMD_DISPLAY_CORE = $(addprefix $(AMDDALPATH)/dc/core/,$(DISPLAY_CORE)) diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c index c2ab026aee91..a4c97d32e751 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c @@ -835,18 +835,6 @@ static enum bp_result bios_parser_enable_crtc( return bp->cmd_tbl.enable_crtc(bp, id, enable); } -static enum bp_result bios_parser_crtc_source_select( - struct dc_bios *dcb, - struct bp_crtc_source_select *bp_params) -{ - struct bios_parser *bp = BP_FROM_DCB(dcb); - - if (!bp->cmd_tbl.select_crtc_source) - return BP_RESULT_FAILURE; - - return bp->cmd_tbl.select_crtc_source(bp, bp_params); -} - static enum bp_result bios_parser_enable_disp_power_gating( struct dc_bios *dcb, enum controller_id controller_id, @@ -2842,8 +2830,6 @@ static const struct dc_vbios_funcs vbios_funcs = { .program_crtc_timing = bios_parser_program_crtc_timing, /* still use. should probably retire and program directly */ - .crtc_source_select = bios_parser_crtc_source_select, /* still use. should probably retire and program directly */ - .program_display_engine_pll = bios_parser_program_display_engine_pll, .enable_disp_power_gating = bios_parser_enable_disp_power_gating, diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c index c513ab6f3843..a1c56f29cfeb 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c @@ -1083,18 +1083,6 @@ static enum bp_result bios_parser_enable_crtc( return bp->cmd_tbl.enable_crtc(bp, id, enable); } -static enum bp_result bios_parser_crtc_source_select( - struct dc_bios *dcb, - struct bp_crtc_source_select *bp_params) -{ - struct bios_parser *bp = BP_FROM_DCB(dcb); - - if (!bp->cmd_tbl.select_crtc_source) - return BP_RESULT_FAILURE; - - return bp->cmd_tbl.select_crtc_source(bp, bp_params); -} - static enum bp_result bios_parser_enable_disp_power_gating( struct dc_bios *dcb, enum controller_id controller_id, @@ -1899,8 +1887,6 @@ static const struct dc_vbios_funcs vbios_funcs = { .is_accelerated_mode = bios_parser_is_accelerated_mode, - .is_active_display = bios_is_active_display, - .set_scratch_critical_state = bios_parser_set_scratch_critical_state, @@ -1917,8 +1903,6 @@ static const struct dc_vbios_funcs vbios_funcs = { .program_crtc_timing = bios_parser_program_crtc_timing, - .crtc_source_select = bios_parser_crtc_source_select, - .enable_disp_power_gating = bios_parser_enable_disp_power_gating, .bios_parser_destroy = firmware_parser_destroy, diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.c index fdda8aa8e303..fce46ab54c54 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.c @@ -83,101 +83,7 @@ uint32_t bios_get_vga_enabled_displays( { uint32_t active_disp = 1; - if (bios->regs->BIOS_SCRATCH_3) /*follow up with other asic, todo*/ - active_disp = REG_READ(BIOS_SCRATCH_3) & 0XFFFF; + active_disp = REG_READ(BIOS_SCRATCH_3) & 0XFFFF; return active_disp; } -bool bios_is_active_display( - struct dc_bios *bios, - enum signal_type signal, - const struct connector_device_tag_info *device_tag) -{ - uint32_t active = 0; - uint32_t connected = 0; - uint32_t bios_scratch_0 = 0; - uint32_t bios_scratch_3 = 0; - - switch (signal) { - case SIGNAL_TYPE_DVI_SINGLE_LINK: - case SIGNAL_TYPE_DVI_DUAL_LINK: - case SIGNAL_TYPE_HDMI_TYPE_A: - case SIGNAL_TYPE_DISPLAY_PORT: - case SIGNAL_TYPE_DISPLAY_PORT_MST: - { - if (device_tag->dev_id.device_type == DEVICE_TYPE_DFP) { - switch (device_tag->dev_id.enum_id) { - case 1: - { - active = ATOM_S3_DFP1_ACTIVE; - connected = 0x0008; //ATOM_DISPLAY_DFP1_CONNECT - } - break; - - case 2: - { - active = ATOM_S3_DFP2_ACTIVE; - connected = 0x0080; //ATOM_DISPLAY_DFP2_CONNECT - } - break; - - case 3: - { - active = ATOM_S3_DFP3_ACTIVE; - connected = 0x0200; //ATOM_DISPLAY_DFP3_CONNECT - } - break; - - case 4: - { - active = ATOM_S3_DFP4_ACTIVE; - connected = 0x0400; //ATOM_DISPLAY_DFP4_CONNECT - } - break; - - case 5: - { - active = ATOM_S3_DFP5_ACTIVE; - connected = 0x0800; //ATOM_DISPLAY_DFP5_CONNECT - } - break; - - case 6: - { - active = ATOM_S3_DFP6_ACTIVE; - connected = 0x0040; //ATOM_DISPLAY_DFP6_CONNECT - } - break; - - default: - break; - } - } - } - break; - - case SIGNAL_TYPE_LVDS: - case SIGNAL_TYPE_EDP: - { - active = ATOM_S3_LCD1_ACTIVE; - connected = 0x0002; //ATOM_DISPLAY_LCD1_CONNECT - } - break; - - default: - break; - } - - - if (bios->regs->BIOS_SCRATCH_0) /*follow up with other asic, todo*/ - bios_scratch_0 = REG_READ(BIOS_SCRATCH_0); - if (bios->regs->BIOS_SCRATCH_3) /*follow up with other asic, todo*/ - bios_scratch_3 = REG_READ(BIOS_SCRATCH_3); - - bios_scratch_3 &= ATOM_S3_DEVICE_ACTIVE_MASK; - if ((active & bios_scratch_3) && (connected & bios_scratch_0)) - return true; - - return false; -} - diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.h b/drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.h index f33cac2147e3..75a29e68fb27 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.h +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.h @@ -35,10 +35,6 @@ bool bios_is_accelerated_mode(struct dc_bios *bios); void bios_set_scratch_acc_mode_change(struct dc_bios *bios); void bios_set_scratch_critical_state(struct dc_bios *bios, bool state); uint32_t bios_get_vga_enabled_displays(struct dc_bios *bios); -bool bios_is_active_display( - struct dc_bios *bios, - enum signal_type signal, - const struct connector_device_tag_info *device_tag); #define GET_IMAGE(type, offset) ((type *) bios_get_image(&bp->base, offset, sizeof(type))) diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table.c b/drivers/gpu/drm/amd/display/dc/bios/command_table.c index 2bd7cd97e00d..5815983caaf8 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table.c +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table.c @@ -55,7 +55,6 @@ static void init_adjust_display_pll(struct bios_parser *bp); static void init_dac_encoder_control(struct bios_parser *bp); static void init_dac_output_control(struct bios_parser *bp); static void init_set_crtc_timing(struct bios_parser *bp); -static void init_select_crtc_source(struct bios_parser *bp); static void init_enable_crtc(struct bios_parser *bp); static void init_enable_crtc_mem_req(struct bios_parser *bp); static void init_external_encoder_control(struct bios_parser *bp); @@ -73,7 +72,6 @@ void dal_bios_parser_init_cmd_tbl(struct bios_parser *bp) init_dac_encoder_control(bp); init_dac_output_control(bp); init_set_crtc_timing(bp); - init_select_crtc_source(bp); init_enable_crtc(bp); init_enable_crtc_mem_req(bp); init_program_clock(bp); @@ -964,9 +962,9 @@ static enum bp_result set_pixel_clock_v3( allocation.sPCLKInput.ucPostDiv = (uint8_t)bp_params->pixel_clock_post_divider; - /* We need to convert from KHz units into 10KHz units */ + /* We need to convert from 100Hz units into 10KHz units */ allocation.sPCLKInput.usPixelClock = - cpu_to_le16((uint16_t)(bp_params->target_pixel_clock / 10)); + cpu_to_le16((uint16_t)(bp_params->target_pixel_clock_100hz / 100)); params = (PIXEL_CLOCK_PARAMETERS_V3 *)&allocation.sPCLKInput; params->ucTransmitterId = @@ -1042,9 +1040,9 @@ static enum bp_result set_pixel_clock_v5( (uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom( bp_params->signal_type, false); - /* We need to convert from KHz units into 10KHz units */ + /* We need to convert from 100Hz units into 10KHz units */ clk.sPCLKInput.usPixelClock = - cpu_to_le16((uint16_t)(bp_params->target_pixel_clock / 10)); + cpu_to_le16((uint16_t)(bp_params->target_pixel_clock_100hz / 100)); if (bp_params->flags.FORCE_PROGRAMMING_OF_PLL) clk.sPCLKInput.ucMiscInfo |= @@ -1118,9 +1116,9 @@ static enum bp_result set_pixel_clock_v6( (uint8_t) bp->cmd_helper->encoder_mode_bp_to_atom( bp_params->signal_type, false); - /* We need to convert from KHz units into 10KHz units */ + /* We need to convert from 100 Hz units into 10KHz units */ clk.sPCLKInput.ulCrtcPclkFreq.ulPixelClock = - cpu_to_le32(bp_params->target_pixel_clock / 10); + cpu_to_le32(bp_params->target_pixel_clock_100hz / 100); if (bp_params->flags.FORCE_PROGRAMMING_OF_PLL) { clk.sPCLKInput.ucMiscInfo |= @@ -1182,8 +1180,7 @@ static enum bp_result set_pixel_clock_v7( clk.ucTransmitterID = bp->cmd_helper->encoder_id_to_atom(dal_graphics_object_id_get_encoder_id(bp_params->encoder_object_id)); clk.ucEncoderMode = (uint8_t) bp->cmd_helper->encoder_mode_bp_to_atom(bp_params->signal_type, false); - /* We need to convert from KHz units into 10KHz units */ - clk.ulPixelClock = cpu_to_le32(bp_params->target_pixel_clock * 10); + clk.ulPixelClock = cpu_to_le32(bp_params->target_pixel_clock_100hz); clk.ucDeepColorRatio = (uint8_t) bp->cmd_helper->transmitter_color_depth_to_atom(bp_params->color_depth); @@ -1899,120 +1896,6 @@ static enum bp_result set_crtc_using_dtd_timing_v3( /******************************************************************************* ******************************************************************************** ** - ** SELECT CRTC SOURCE - ** - ******************************************************************************** - *******************************************************************************/ - -static enum bp_result select_crtc_source_v2( - struct bios_parser *bp, - struct bp_crtc_source_select *bp_params); -static enum bp_result select_crtc_source_v3( - struct bios_parser *bp, - struct bp_crtc_source_select *bp_params); - -static void init_select_crtc_source(struct bios_parser *bp) -{ - switch (BIOS_CMD_TABLE_PARA_REVISION(SelectCRTC_Source)) { - case 2: - bp->cmd_tbl.select_crtc_source = select_crtc_source_v2; - break; - case 3: - bp->cmd_tbl.select_crtc_source = select_crtc_source_v3; - break; - default: - dm_output_to_console("Don't select_crtc_source enable_crtc for v%d\n", - BIOS_CMD_TABLE_PARA_REVISION(SelectCRTC_Source)); - bp->cmd_tbl.select_crtc_source = NULL; - break; - } -} - -static enum bp_result select_crtc_source_v2( - struct bios_parser *bp, - struct bp_crtc_source_select *bp_params) -{ - enum bp_result result = BP_RESULT_FAILURE; - SELECT_CRTC_SOURCE_PARAMETERS_V2 params; - uint8_t atom_controller_id; - uint32_t atom_engine_id; - enum signal_type s = bp_params->signal; - - memset(¶ms, 0, sizeof(params)); - - /* set controller id */ - if (bp->cmd_helper->controller_id_to_atom( - bp_params->controller_id, &atom_controller_id)) - params.ucCRTC = atom_controller_id; - else - return BP_RESULT_FAILURE; - - /* set encoder id */ - if (bp->cmd_helper->engine_bp_to_atom( - bp_params->engine_id, &atom_engine_id)) - params.ucEncoderID = (uint8_t)atom_engine_id; - else - return BP_RESULT_FAILURE; - - if (SIGNAL_TYPE_EDP == s || - (SIGNAL_TYPE_DISPLAY_PORT == s && - SIGNAL_TYPE_LVDS == bp_params->sink_signal)) - s = SIGNAL_TYPE_LVDS; - - params.ucEncodeMode = - (uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom( - s, bp_params->enable_dp_audio); - - if (EXEC_BIOS_CMD_TABLE(SelectCRTC_Source, params)) - result = BP_RESULT_OK; - - return result; -} - -static enum bp_result select_crtc_source_v3( - struct bios_parser *bp, - struct bp_crtc_source_select *bp_params) -{ - bool result = BP_RESULT_FAILURE; - SELECT_CRTC_SOURCE_PARAMETERS_V3 params; - uint8_t atom_controller_id; - uint32_t atom_engine_id; - enum signal_type s = bp_params->signal; - - memset(¶ms, 0, sizeof(params)); - - if (bp->cmd_helper->controller_id_to_atom(bp_params->controller_id, - &atom_controller_id)) - params.ucCRTC = atom_controller_id; - else - return result; - - if (bp->cmd_helper->engine_bp_to_atom(bp_params->engine_id, - &atom_engine_id)) - params.ucEncoderID = (uint8_t)atom_engine_id; - else - return result; - - if (SIGNAL_TYPE_EDP == s || - (SIGNAL_TYPE_DISPLAY_PORT == s && - SIGNAL_TYPE_LVDS == bp_params->sink_signal)) - s = SIGNAL_TYPE_LVDS; - - params.ucEncodeMode = - bp->cmd_helper->encoder_mode_bp_to_atom( - s, bp_params->enable_dp_audio); - /* Needed for VBIOS Random Spatial Dithering feature */ - params.ucDstBpc = (uint8_t)(bp_params->display_output_bit_depth); - - if (EXEC_BIOS_CMD_TABLE(SelectCRTC_Source, params)) - result = BP_RESULT_OK; - - return result; -} - -/******************************************************************************* - ******************************************************************************** - ** ** ENABLE CRTC ** ******************************************************************************** @@ -2164,7 +2047,7 @@ static enum bp_result program_clock_v5( /* We need to convert from KHz units into 10KHz units */ params.sPCLKInput.ucPpll = (uint8_t) atom_pll_id; params.sPCLKInput.usPixelClock = - cpu_to_le16((uint16_t) (bp_params->target_pixel_clock / 10)); + cpu_to_le16((uint16_t) (bp_params->target_pixel_clock_100hz / 100)); params.sPCLKInput.ucCRTC = (uint8_t) ATOM_CRTC_INVALID; if (bp_params->flags.SET_EXTERNAL_REF_DIV_SRC) @@ -2196,7 +2079,7 @@ static enum bp_result program_clock_v6( /* We need to convert from KHz units into 10KHz units */ params.sPCLKInput.ucPpll = (uint8_t)atom_pll_id; params.sPCLKInput.ulDispEngClkFreq = - cpu_to_le32(bp_params->target_pixel_clock / 10); + cpu_to_le32(bp_params->target_pixel_clock_100hz / 100); if (bp_params->flags.SET_EXTERNAL_REF_DIV_SRC) params.sPCLKInput.ucMiscInfo |= PIXEL_CLOCK_MISC_REF_DIV_SRC; diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table.h b/drivers/gpu/drm/amd/display/dc/bios/command_table.h index 94f3d43a7471..ad533775e724 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table.h +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table.h @@ -71,9 +71,6 @@ struct cmd_tbl { enum bp_result (*set_crtc_timing)( struct bios_parser *bp, struct bp_hw_crtc_timing_parameters *bp_params); - enum bp_result (*select_crtc_source)( - struct bios_parser *bp, - struct bp_crtc_source_select *bp_params); enum bp_result (*enable_crtc)( struct bios_parser *bp, enum controller_id controller_id, diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c index 2b5dc499a35e..bb2e8105e6ab 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c @@ -301,17 +301,17 @@ static enum bp_result set_pixel_clock_v7( cmd_helper->encoder_mode_bp_to_atom( bp_params->signal_type, false); - /* We need to convert from KHz units into 10KHz units */ - clk.pixclk_100hz = cpu_to_le32(bp_params->target_pixel_clock * - 10); + clk.pixclk_100hz = cpu_to_le32(bp_params->target_pixel_clock_100hz); clk.deep_color_ratio = (uint8_t) bp->cmd_helper-> transmitter_color_depth_to_atom( bp_params->color_depth); - DC_LOG_BIOS("%s:program display clock = %d"\ - "colorDepth = %d\n", __func__,\ - bp_params->target_pixel_clock, bp_params->color_depth); + + DC_LOG_BIOS("%s:program display clock = %d, tg = %d, pll = %d, "\ + "colorDepth = %d\n", __func__, + bp_params->target_pixel_clock_100hz, (int)controller_id, + pll_id, bp_params->color_depth); if (bp_params->flags.FORCE_PROGRAMMING_OF_PLL) clk.miscinfo |= PIXEL_CLOCK_V7_MISC_FORCE_PROG_PPLL; @@ -463,75 +463,6 @@ static enum bp_result set_crtc_using_dtd_timing_v3( /****************************************************************************** ****************************************************************************** ** - ** SELECT CRTC SOURCE - ** - ****************************************************************************** - *****************************************************************************/ - - -static enum bp_result select_crtc_source_v3( - struct bios_parser *bp, - struct bp_crtc_source_select *bp_params); - -static void init_select_crtc_source(struct bios_parser *bp) -{ - switch (BIOS_CMD_TABLE_PARA_REVISION(selectcrtc_source)) { - case 3: - bp->cmd_tbl.select_crtc_source = select_crtc_source_v3; - break; - default: - dm_output_to_console("Don't select_crtc_source enable_crtc for v%d\n", - BIOS_CMD_TABLE_PARA_REVISION(selectcrtc_source)); - bp->cmd_tbl.select_crtc_source = NULL; - break; - } -} - - -static enum bp_result select_crtc_source_v3( - struct bios_parser *bp, - struct bp_crtc_source_select *bp_params) -{ - bool result = BP_RESULT_FAILURE; - struct select_crtc_source_parameters_v2_3 params; - uint8_t atom_controller_id; - uint32_t atom_engine_id; - enum signal_type s = bp_params->signal; - - memset(¶ms, 0, sizeof(params)); - - if (bp->cmd_helper->controller_id_to_atom(bp_params->controller_id, - &atom_controller_id)) - params.crtc_id = atom_controller_id; - else - return result; - - if (bp->cmd_helper->engine_bp_to_atom(bp_params->engine_id, - &atom_engine_id)) - params.encoder_id = (uint8_t)atom_engine_id; - else - return result; - - if (s == SIGNAL_TYPE_EDP || - (s == SIGNAL_TYPE_DISPLAY_PORT && bp_params->sink_signal == - SIGNAL_TYPE_LVDS)) - s = SIGNAL_TYPE_LVDS; - - params.encode_mode = - bp->cmd_helper->encoder_mode_bp_to_atom( - s, bp_params->enable_dp_audio); - /* Needed for VBIOS Random Spatial Dithering feature */ - params.dst_bpc = (uint8_t)(bp_params->display_output_bit_depth); - - if (EXEC_BIOS_CMD_TABLE(selectcrtc_source, params)) - result = BP_RESULT_OK; - - return result; -} - -/****************************************************************************** - ****************************************************************************** - ** ** ENABLE CRTC ** ****************************************************************************** @@ -808,7 +739,6 @@ void dal_firmware_parser_init_cmd_tbl(struct bios_parser *bp) init_set_crtc_timing(bp); - init_select_crtc_source(bp); init_enable_crtc(bp); init_external_encoder_control(bp); diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table2.h b/drivers/gpu/drm/amd/display/dc/bios/command_table2.h index ec1c0c9f3f1d..7a2af24dfe60 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table2.h +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table2.h @@ -71,9 +71,6 @@ struct cmd_tbl { enum bp_result (*set_crtc_timing)( struct bios_parser *bp, struct bp_hw_crtc_timing_parameters *bp_params); - enum bp_result (*select_crtc_source)( - struct bios_parser *bp, - struct bp_crtc_source_select *bp_params); enum bp_result (*enable_crtc)( struct bios_parser *bp, enum controller_id controller_id, diff --git a/drivers/gpu/drm/amd/display/dc/calcs/Makefile b/drivers/gpu/drm/amd/display/dc/calcs/Makefile index 95f332ee3e7e..dc85a3c088af 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/Makefile +++ b/drivers/gpu/drm/amd/display/dc/calcs/Makefile @@ -30,7 +30,7 @@ else ifneq ($(call cc-option, -mstack-alignment=16),) cc_stack_align := -mstack-alignment=16 endif -calcs_ccflags := -mhard-float -msse $(cc_stack_align) +calcs_ccflags := -mhard-float -msse -msse2 $(cc_stack_align) CFLAGS_dcn_calcs.o := $(calcs_ccflags) CFLAGS_dcn_calc_auto.o := $(calcs_ccflags) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c index 9ebe30ba4dab..f3aa7b53d2aa 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c @@ -2792,7 +2792,7 @@ static void populate_initial_data( data->lpt_en[num_displays + 4] = false; data->h_total[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->timing.h_total); data->v_total[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->timing.v_total); - data->pixel_rate[num_displays + 4] = bw_frc_to_fixed(pipe[i].stream->timing.pix_clk_khz, 1000); + data->pixel_rate[num_displays + 4] = bw_frc_to_fixed(pipe[i].stream->timing.pix_clk_100hz, 10000); data->src_width[num_displays + 4] = bw_int_to_fixed(pipe[i].plane_res.scl_data.viewport.width); data->pitch_in_pixels[num_displays + 4] = data->src_width[num_displays + 4]; data->src_height[num_displays + 4] = bw_int_to_fixed(pipe[i].plane_res.scl_data.viewport.height); @@ -2881,7 +2881,7 @@ static void populate_initial_data( /* Pipes without underlay after */ for (i = 0; i < pipe_count; i++) { - unsigned int pixel_clock_khz; + unsigned int pixel_clock_100hz; if (!pipe[i].stream || pipe[i].bottom_pipe) continue; @@ -2890,10 +2890,10 @@ static void populate_initial_data( data->lpt_en[num_displays + 4] = false; data->h_total[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->timing.h_total); data->v_total[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->timing.v_total); - pixel_clock_khz = pipe[i].stream->timing.pix_clk_khz; + pixel_clock_100hz = pipe[i].stream->timing.pix_clk_100hz; if (pipe[i].stream->timing.timing_3d_format == TIMING_3D_FORMAT_HW_FRAME_PACKING) - pixel_clock_khz *= 2; - data->pixel_rate[num_displays + 4] = bw_frc_to_fixed(pixel_clock_khz, 1000); + pixel_clock_100hz *= 2; + data->pixel_rate[num_displays + 4] = bw_frc_to_fixed(pixel_clock_100hz, 10000); if (pipe[i].plane_state) { data->src_width[num_displays + 4] = bw_int_to_fixed(pipe[i].plane_res.scl_data.viewport.width); data->pitch_in_pixels[num_displays + 4] = data->src_width[num_displays + 4]; diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.c index d0fc54f8fb1c..7d102ac0d61b 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.c @@ -797,9 +797,40 @@ void mode_support_and_system_configuration(struct dcn_bw_internal_vars *v) else { v->maximum_vstartup = v->v_sync_plus_back_porch[k] - 1.0; } - v->line_times_for_prefetch[k] = v->maximum_vstartup - v->urgent_latency / (v->htotal[k] / v->pixel_clock[k]) - (v->time_calc + v->time_setup) / (v->htotal[k] / v->pixel_clock[k]) - (v->dst_y_after_scaler + v->dst_x_after_scaler / v->htotal[k]); - v->line_times_for_prefetch[k] =dcn_bw_floor2(4.0 * (v->line_times_for_prefetch[k] + 0.125), 1.0) / 4; - v->prefetch_bw[k] = (v->meta_pte_bytes_per_frame[k] + 2.0 * v->meta_row_bytes[k] + 2.0 * v->dpte_bytes_per_row[k] + v->prefetch_lines_y[k] * v->swath_width_yper_state[i][j][k] *dcn_bw_ceil2(v->byte_per_pixel_in_dety[k], 1.0) + v->prefetch_lines_c[k] * v->swath_width_yper_state[i][j][k] / 2.0 *dcn_bw_ceil2(v->byte_per_pixel_in_detc[k], 2.0)) / (v->line_times_for_prefetch[k] * v->htotal[k] / v->pixel_clock[k]); + + do { + v->line_times_for_prefetch[k] = v->maximum_vstartup - v->urgent_latency / (v->htotal[k] / v->pixel_clock[k]) - (v->time_calc + v->time_setup) / (v->htotal[k] / v->pixel_clock[k]) - (v->dst_y_after_scaler + v->dst_x_after_scaler / v->htotal[k]); + v->line_times_for_prefetch[k] =dcn_bw_floor2(4.0 * (v->line_times_for_prefetch[k] + 0.125), 1.0) / 4; + v->prefetch_bw[k] = (v->meta_pte_bytes_per_frame[k] + 2.0 * v->meta_row_bytes[k] + 2.0 * v->dpte_bytes_per_row[k] + v->prefetch_lines_y[k] * v->swath_width_yper_state[i][j][k] *dcn_bw_ceil2(v->byte_per_pixel_in_dety[k], 1.0) + v->prefetch_lines_c[k] * v->swath_width_yper_state[i][j][k] / 2.0 *dcn_bw_ceil2(v->byte_per_pixel_in_detc[k], 2.0)) / (v->line_times_for_prefetch[k] * v->htotal[k] / v->pixel_clock[k]); + + if (v->pte_enable == dcn_bw_yes && v->dcc_enable[k] == dcn_bw_yes) { + v->time_for_meta_pte_without_immediate_flip = dcn_bw_max3( + v->meta_pte_bytes_frame[k] / v->prefetch_bandwidth[k], + v->extra_latency, + v->htotal[k] / v->pixel_clock[k] / 4.0); + } else { + v->time_for_meta_pte_without_immediate_flip = v->htotal[k] / v->pixel_clock[k] / 4.0; + } + + if (v->pte_enable == dcn_bw_yes || v->dcc_enable[k] == dcn_bw_yes) { + v->time_for_meta_and_dpte_row_without_immediate_flip = dcn_bw_max3(( + v->meta_row_bytes[k] + v->dpte_bytes_per_row[k]) / v->prefetch_bandwidth[k], + v->htotal[k] / v->pixel_clock[k] - v->time_for_meta_pte_without_immediate_flip, + v->extra_latency); + } else { + v->time_for_meta_and_dpte_row_without_immediate_flip = dcn_bw_max2( + v->htotal[k] / v->pixel_clock[k] - v->time_for_meta_pte_without_immediate_flip, + v->extra_latency - v->time_for_meta_pte_with_immediate_flip); + } + + v->lines_for_meta_pte_without_immediate_flip[k] =dcn_bw_floor2(4.0 * (v->time_for_meta_pte_without_immediate_flip / (v->htotal[k] / v->pixel_clock[k]) + 0.125), 1.0) / 4; + v->lines_for_meta_and_dpte_row_without_immediate_flip[k] =dcn_bw_floor2(4.0 * (v->time_for_meta_and_dpte_row_without_immediate_flip / (v->htotal[k] / v->pixel_clock[k]) + 0.125), 1.0) / 4; + v->maximum_vstartup = v->maximum_vstartup - 1; + + if (v->lines_for_meta_pte_without_immediate_flip[k] < 8.0 && v->lines_for_meta_and_dpte_row_without_immediate_flip[k] < 16.0) + break; + + } while(1); } v->bw_available_for_immediate_flip = v->return_bw_per_state[i]; for (k = 0; k <= v->number_of_active_planes - 1; k++) { @@ -814,24 +845,18 @@ void mode_support_and_system_configuration(struct dcn_bw_internal_vars *v) for (k = 0; k <= v->number_of_active_planes - 1; k++) { if (v->pte_enable == dcn_bw_yes && v->dcc_enable[k] == dcn_bw_yes) { v->time_for_meta_pte_with_immediate_flip =dcn_bw_max5(v->meta_pte_bytes_per_frame[k] / v->prefetch_bw[k], v->meta_pte_bytes_per_frame[k] * v->total_immediate_flip_bytes[k] / (v->bw_available_for_immediate_flip * (v->meta_pte_bytes_per_frame[k] + v->meta_row_bytes[k] + v->dpte_bytes_per_row[k])), v->extra_latency, v->urgent_latency, v->htotal[k] / v->pixel_clock[k] / 4.0); - v->time_for_meta_pte_without_immediate_flip =dcn_bw_max3(v->meta_pte_bytes_per_frame[k] / v->prefetch_bw[k], v->extra_latency, v->htotal[k] / v->pixel_clock[k] / 4.0); } else { v->time_for_meta_pte_with_immediate_flip = v->htotal[k] / v->pixel_clock[k] / 4.0; - v->time_for_meta_pte_without_immediate_flip = v->htotal[k] / v->pixel_clock[k] / 4.0; } if (v->pte_enable == dcn_bw_yes || v->dcc_enable[k] == dcn_bw_yes) { v->time_for_meta_and_dpte_row_with_immediate_flip =dcn_bw_max5((v->meta_row_bytes[k] + v->dpte_bytes_per_row[k]) / v->prefetch_bw[k], (v->meta_row_bytes[k] + v->dpte_bytes_per_row[k]) * v->total_immediate_flip_bytes[k] / (v->bw_available_for_immediate_flip * (v->meta_pte_bytes_per_frame[k] + v->meta_row_bytes[k] + v->dpte_bytes_per_row[k])), v->htotal[k] / v->pixel_clock[k] - v->time_for_meta_pte_with_immediate_flip, v->extra_latency, 2.0 * v->urgent_latency); - v->time_for_meta_and_dpte_row_without_immediate_flip =dcn_bw_max3((v->meta_row_bytes[k] + v->dpte_bytes_per_row[k]) / v->prefetch_bw[k], v->htotal[k] / v->pixel_clock[k] - v->time_for_meta_pte_without_immediate_flip, v->extra_latency); } else { v->time_for_meta_and_dpte_row_with_immediate_flip =dcn_bw_max2(v->htotal[k] / v->pixel_clock[k] - v->time_for_meta_pte_with_immediate_flip, v->extra_latency - v->time_for_meta_pte_with_immediate_flip); - v->time_for_meta_and_dpte_row_without_immediate_flip =dcn_bw_max2(v->htotal[k] / v->pixel_clock[k] - v->time_for_meta_pte_without_immediate_flip, v->extra_latency - v->time_for_meta_pte_without_immediate_flip); } v->lines_for_meta_pte_with_immediate_flip[k] =dcn_bw_floor2(4.0 * (v->time_for_meta_pte_with_immediate_flip / (v->htotal[k] / v->pixel_clock[k]) + 0.125), 1.0) / 4; - v->lines_for_meta_pte_without_immediate_flip[k] =dcn_bw_floor2(4.0 * (v->time_for_meta_pte_without_immediate_flip / (v->htotal[k] / v->pixel_clock[k]) + 0.125), 1.0) / 4; v->lines_for_meta_and_dpte_row_with_immediate_flip[k] =dcn_bw_floor2(4.0 * (v->time_for_meta_and_dpte_row_with_immediate_flip / (v->htotal[k] / v->pixel_clock[k]) + 0.125), 1.0) / 4; - v->lines_for_meta_and_dpte_row_without_immediate_flip[k] =dcn_bw_floor2(4.0 * (v->time_for_meta_and_dpte_row_without_immediate_flip / (v->htotal[k] / v->pixel_clock[k]) + 0.125), 1.0) / 4; v->line_times_to_request_prefetch_pixel_data_with_immediate_flip = v->line_times_for_prefetch[k] - v->lines_for_meta_pte_with_immediate_flip[k] - v->lines_for_meta_and_dpte_row_with_immediate_flip[k]; v->line_times_to_request_prefetch_pixel_data_without_immediate_flip = v->line_times_for_prefetch[k] - v->lines_for_meta_pte_without_immediate_flip[k] - v->lines_for_meta_and_dpte_row_without_immediate_flip[k]; if (v->line_times_to_request_prefetch_pixel_data_with_immediate_flip > 0.0) { diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index 43e4a2be0fa6..12d1842079ae 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -290,41 +290,34 @@ static void pipe_ctx_to_e2e_pipe_params ( switch (pipe->plane_state->tiling_info.gfx9.swizzle) { /* for 4/8/16 high tiles */ case DC_SW_LINEAR: - input->src.is_display_sw = 1; input->src.macro_tile_size = dm_4k_tile; break; case DC_SW_4KB_S: case DC_SW_4KB_S_X: - input->src.is_display_sw = 0; input->src.macro_tile_size = dm_4k_tile; break; case DC_SW_64KB_S: case DC_SW_64KB_S_X: case DC_SW_64KB_S_T: - input->src.is_display_sw = 0; input->src.macro_tile_size = dm_64k_tile; break; case DC_SW_VAR_S: case DC_SW_VAR_S_X: - input->src.is_display_sw = 0; input->src.macro_tile_size = dm_256k_tile; break; /* For 64bpp 2 high tiles */ case DC_SW_4KB_D: case DC_SW_4KB_D_X: - input->src.is_display_sw = 1; input->src.macro_tile_size = dm_4k_tile; break; case DC_SW_64KB_D: case DC_SW_64KB_D_X: case DC_SW_64KB_D_T: - input->src.is_display_sw = 1; input->src.macro_tile_size = dm_64k_tile; break; case DC_SW_VAR_D: case DC_SW_VAR_D_X: - input->src.is_display_sw = 1; input->src.macro_tile_size = dm_256k_tile; break; @@ -423,7 +416,7 @@ static void pipe_ctx_to_e2e_pipe_params ( - pipe->stream->timing.v_addressable - pipe->stream->timing.v_border_bottom - pipe->stream->timing.v_border_top; - input->dest.pixel_rate_mhz = pipe->stream->timing.pix_clk_khz/1000.0; + input->dest.pixel_rate_mhz = pipe->stream->timing.pix_clk_100hz/10000.0; input->dest.vstartup_start = pipe->pipe_dlg_param.vstartup_start; input->dest.vupdate_offset = pipe->pipe_dlg_param.vupdate_offset; input->dest.vupdate_offset = pipe->pipe_dlg_param.vupdate_offset; @@ -670,9 +663,9 @@ static void hack_disable_optional_pipe_split(struct dcn_bw_internal_vars *v) } static void hack_force_pipe_split(struct dcn_bw_internal_vars *v, - unsigned int pixel_rate_khz) + unsigned int pixel_rate_100hz) { - float pixel_rate_mhz = pixel_rate_khz / 1000; + float pixel_rate_mhz = pixel_rate_100hz / 10000; /* * force enabling pipe split by lower dpp clock for DPM0 to just @@ -695,7 +688,7 @@ static void hack_bounding_box(struct dcn_bw_internal_vars *v, if (context->stream_count == 1 && dbg->force_single_disp_pipe_split) - hack_force_pipe_split(v, context->streams[0]->timing.pix_clk_khz); + hack_force_pipe_split(v, context->streams[0]->timing.pix_clk_100hz); } bool dcn_validate_bandwidth( @@ -852,7 +845,7 @@ bool dcn_validate_bandwidth( v->v_sync_plus_back_porch[input_idx] = pipe->stream->timing.v_total - v->vactive[input_idx] - pipe->stream->timing.v_front_porch; - v->pixel_clock[input_idx] = pipe->stream->timing.pix_clk_khz/1000.0; + v->pixel_clock[input_idx] = pipe->stream->timing.pix_clk_100hz/10000.0; if (pipe->stream->timing.timing_3d_format == TIMING_3D_FORMAT_HW_FRAME_PACKING) v->pixel_clock[input_idx] *= 2; if (!pipe->plane_state) { @@ -961,7 +954,7 @@ bool dcn_validate_bandwidth( v->dcc_rate[input_idx] = 1; /*TODO: Worst case? does this change?*/ v->output_format[input_idx] = pipe->stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420 ? dcn_bw_420 : dcn_bw_444; - v->output[input_idx] = pipe->stream->sink->sink_signal == + v->output[input_idx] = pipe->stream->signal == SIGNAL_TYPE_HDMI_TYPE_A ? dcn_bw_hdmi : dcn_bw_dp; v->output_deep_color[input_idx] = dcn_bw_encoder_8bpc; if (v->output[input_idx] == dcn_bw_hdmi) { diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 5fd52094d459..1dabafc12cfe 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -384,7 +384,7 @@ void dc_stream_set_dither_option(struct dc_stream_state *stream, enum dc_dither_option option) { struct bit_depth_reduction_params params; - struct dc_link *link = stream->sink->link; + struct dc_link *link = stream->link; struct pipe_ctx *pipes = NULL; int i; @@ -451,7 +451,7 @@ bool dc_stream_program_csc_matrix(struct dc *dc, struct dc_stream_state *stream) pipes, stream->output_color_space, stream->csc_color_matrix.matrix, - pipes->plane_res.hubp->opp_id); + pipes->plane_res.hubp ? pipes->plane_res.hubp->opp_id : 0); ret = true; } } @@ -526,9 +526,8 @@ void dc_link_set_preferred_link_settings(struct dc *dc, for (i = 0; i < MAX_PIPES; i++) { pipe = &dc->current_state->res_ctx.pipe_ctx[i]; - if (pipe->stream && pipe->stream->sink - && pipe->stream->sink->link) { - if (pipe->stream->sink->link == link) + if (pipe->stream && pipe->stream->link) { + if (pipe->stream->link == link) break; } } @@ -586,9 +585,6 @@ static void destruct(struct dc *dc) if (dc->ctx->gpio_service) dal_gpio_service_destroy(&dc->ctx->gpio_service); - if (dc->ctx->i2caux) - dal_i2caux_destroy(&dc->ctx->i2caux); - if (dc->ctx->created_bios) dal_bios_parser_destroy(&dc->ctx->dc_bios); @@ -670,6 +666,7 @@ static bool construct(struct dc *dc, dc_ctx->dc = dc; dc_ctx->asic_id = init_params->asic_id; dc_ctx->dc_sink_id_count = 0; + dc_ctx->dc_stream_id_count = 0; dc->ctx = dc_ctx; dc->current_state = dc_create_state(); @@ -709,14 +706,6 @@ static bool construct(struct dc *dc, dc_ctx->created_bios = true; } - /* Create I2C AUX */ - dc_ctx->i2caux = dal_i2caux_create(dc_ctx); - - if (!dc_ctx->i2caux) { - ASSERT_CRITICAL(false); - goto fail; - } - dc_ctx->perf_trace = dc_perf_trace_create(); if (!dc_ctx->perf_trace) { ASSERT_CRITICAL(false); @@ -840,6 +829,11 @@ alloc_fail: return NULL; } +void dc_init_callbacks(struct dc *dc, + const struct dc_callback_init *init_params) +{ +} + void dc_destroy(struct dc **dc) { destruct(*dc); @@ -1040,7 +1034,8 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c /* Program all planes within new context*/ for (i = 0; i < context->stream_count; i++) { - const struct dc_sink *sink = context->streams[i]->sink; + const struct dc_link *link = context->streams[i]->link; + struct dc_stream_status *status; if (!context->streams[i]->mode_changed) continue; @@ -1065,12 +1060,15 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c } } - CONN_MSG_MODE(sink->link, "{%dx%d, %dx%d@%dKhz}", + status = dc_stream_get_status_from_state(context, context->streams[i]); + context->streams[i]->out.otg_offset = status->primary_otg_inst; + + CONN_MSG_MODE(link, "{%dx%d, %dx%d@%dKhz}", context->streams[i]->timing.h_addressable, context->streams[i]->timing.v_addressable, context->streams[i]->timing.h_total, context->streams[i]->timing.v_total, - context->streams[i]->timing.pix_clk_khz); + context->streams[i]->timing.pix_clk_100hz / 10); } dc_enable_stereo(dc, context, dc_streams, context->stream_count); @@ -1215,6 +1213,12 @@ static enum surface_update_type get_plane_info_update_type(const struct dc_surfa */ update_flags->bits.bpp_change = 1; + if (u->plane_info->plane_size.grph.surface_pitch != u->surface->plane_size.grph.surface_pitch + || u->plane_info->plane_size.video.luma_pitch != u->surface->plane_size.video.luma_pitch + || u->plane_info->plane_size.video.chroma_pitch != u->surface->plane_size.video.chroma_pitch) + update_flags->bits.plane_size_change = 1; + + if (memcmp(&u->plane_info->tiling_info, &u->surface->tiling_info, sizeof(union dc_tiling_info)) != 0) { update_flags->bits.swizzle_change = 1; @@ -1236,7 +1240,7 @@ static enum surface_update_type get_plane_info_update_type(const struct dc_surfa || update_flags->bits.output_tf_change) return UPDATE_TYPE_FULL; - return UPDATE_TYPE_MED; + return update_flags->raw ? UPDATE_TYPE_MED : UPDATE_TYPE_FAST; } static enum surface_update_type get_scaling_info_update_type( @@ -1605,7 +1609,6 @@ void dc_commit_updates_for_stream(struct dc *dc, int surface_count, struct dc_stream_state *stream, struct dc_stream_update *stream_update, - struct dc_plane_state **plane_states, struct dc_state *state) { const struct dc_stream_status *stream_status; @@ -1764,6 +1767,26 @@ void dc_resume(struct dc *dc) core_link_resume(dc->links[i]); } +unsigned int dc_get_current_backlight_pwm(struct dc *dc) +{ + struct abm *abm = dc->res_pool->abm; + + if (abm) + return abm->funcs->get_current_backlight(abm); + + return 0; +} + +unsigned int dc_get_target_backlight_pwm(struct dc *dc) +{ + struct abm *abm = dc->res_pool->abm; + + if (abm) + return abm->funcs->get_target_backlight(abm); + + return 0; +} + bool dc_is_dmcu_initialized(struct dc *dc) { struct dmcu *dmcu = dc->res_pool->dmcu; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 52deacf39841..3dd5f2717b53 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -43,10 +43,6 @@ #include "dpcd_defs.h" #include "dmcu.h" -#include "dce/dce_11_0_d.h" -#include "dce/dce_11_0_enum.h" -#include "dce/dce_11_0_sh_mask.h" - #define DC_LOGGER_INIT(logger) @@ -789,7 +785,7 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason) return false; } - sink->dongle_max_pix_clk = sink_caps.max_hdmi_pixel_clock; + sink->link->dongle_max_pix_clk = sink_caps.max_hdmi_pixel_clock; sink->converter_disable_audio = converter_disable_audio; link->local_sink = sink; @@ -1372,7 +1368,7 @@ static void dpcd_configure_panel_mode( static void enable_stream_features(struct pipe_ctx *pipe_ctx) { struct dc_stream_state *stream = pipe_ctx->stream; - struct dc_link *link = stream->sink->link; + struct dc_link *link = stream->link; union down_spread_ctrl old_downspread; union down_spread_ctrl new_downspread; @@ -1397,7 +1393,7 @@ static enum dc_status enable_link_dp( struct dc_stream_state *stream = pipe_ctx->stream; enum dc_status status; bool skip_video_pattern; - struct dc_link *link = stream->sink->link; + struct dc_link *link = stream->link; struct dc_link_settings link_settings = {0}; enum dp_panel_mode panel_mode; @@ -1414,8 +1410,8 @@ static enum dc_status enable_link_dp( pipe_ctx->clock_source->id, &link_settings); - if (stream->sink->edid_caps.panel_patch.dppowerup_delay > 0) { - int delay_dp_power_up_in_ms = stream->sink->edid_caps.panel_patch.dppowerup_delay; + if (stream->sink_patches.dppowerup_delay > 0) { + int delay_dp_power_up_in_ms = stream->sink_patches.dppowerup_delay; msleep(delay_dp_power_up_in_ms); } @@ -1448,7 +1444,7 @@ static enum dc_status enable_link_edp( { enum dc_status status; struct dc_stream_state *stream = pipe_ctx->stream; - struct dc_link *link = stream->sink->link; + struct dc_link *link = stream->link; /*in case it is not on*/ link->dc->hwss.edp_power_control(link, true); link->dc->hwss.edp_wait_for_hpd_ready(link, true); @@ -1463,7 +1459,7 @@ static enum dc_status enable_link_dp_mst( struct dc_state *state, struct pipe_ctx *pipe_ctx) { - struct dc_link *link = pipe_ctx->stream->sink->link; + struct dc_link *link = pipe_ctx->stream->link; /* sink signal type after MST branch is MST. Multiple MST sinks * share one link. Link DP PHY is enable or training only once. @@ -1597,7 +1593,7 @@ static bool i2c_write(struct pipe_ctx *pipe_ctx, cmd.payloads = &payload; if (dm_helpers_submit_i2c(pipe_ctx->stream->ctx, - pipe_ctx->stream->sink->link, &cmd)) + pipe_ctx->stream->link, &cmd)) return true; return false; @@ -1651,7 +1647,7 @@ static void write_i2c_retimer_setting( else { i2c_success = dal_ddc_service_query_ddc_data( - pipe_ctx->stream->sink->link->ddc, + pipe_ctx->stream->link->ddc, slave_address, &offset, 1, &value, 1); if (!i2c_success) /* Write failure */ @@ -1704,7 +1700,7 @@ static void write_i2c_retimer_setting( else { i2c_success = dal_ddc_service_query_ddc_data( - pipe_ctx->stream->sink->link->ddc, + pipe_ctx->stream->link->ddc, slave_address, &offset, 1, &value, 1); if (!i2c_success) /* Write failure */ @@ -1929,7 +1925,7 @@ static void write_i2c_redriver_setting( static void enable_link_hdmi(struct pipe_ctx *pipe_ctx) { struct dc_stream_state *stream = pipe_ctx->stream; - struct dc_link *link = stream->sink->link; + struct dc_link *link = stream->link; enum dc_color_depth display_color_depth; enum engine_id eng_id; struct ext_hdmi_settings settings = {0}; @@ -1938,12 +1934,12 @@ static void enable_link_hdmi(struct pipe_ctx *pipe_ctx) && (stream->timing.v_addressable == 480); if (stream->phy_pix_clk == 0) - stream->phy_pix_clk = stream->timing.pix_clk_khz; + stream->phy_pix_clk = stream->timing.pix_clk_100hz / 10; if (stream->phy_pix_clk > 340000) is_over_340mhz = true; if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) { - unsigned short masked_chip_caps = pipe_ctx->stream->sink->link->chip_caps & + unsigned short masked_chip_caps = pipe_ctx->stream->link->chip_caps & EXT_DISPLAY_PATH_CAPS__EXT_CHIP_MASK; if (masked_chip_caps == EXT_DISPLAY_PATH_CAPS__HDMI20_TISN65DP159RSBT) { /* DP159, Retimer settings */ @@ -1964,11 +1960,11 @@ static void enable_link_hdmi(struct pipe_ctx *pipe_ctx) if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) dal_ddc_service_write_scdc_data( - stream->sink->link->ddc, + stream->link->ddc, stream->phy_pix_clk, stream->timing.flags.LTE_340MCSC_SCRAMBLE); - memset(&stream->sink->link->cur_link_settings, 0, + memset(&stream->link->cur_link_settings, 0, sizeof(struct dc_link_settings)); display_color_depth = stream->timing.display_color_depth; @@ -1989,12 +1985,12 @@ static void enable_link_hdmi(struct pipe_ctx *pipe_ctx) static void enable_link_lvds(struct pipe_ctx *pipe_ctx) { struct dc_stream_state *stream = pipe_ctx->stream; - struct dc_link *link = stream->sink->link; + struct dc_link *link = stream->link; if (stream->phy_pix_clk == 0) - stream->phy_pix_clk = stream->timing.pix_clk_khz; + stream->phy_pix_clk = stream->timing.pix_clk_100hz / 10; - memset(&stream->sink->link->cur_link_settings, 0, + memset(&stream->link->cur_link_settings, 0, sizeof(struct dc_link_settings)); link->link_enc->funcs->enable_lvds_output( @@ -2067,7 +2063,7 @@ static bool dp_active_dongle_validate_timing( const struct dc_crtc_timing *timing, const struct dpcd_caps *dpcd_caps) { - unsigned int required_pix_clk = timing->pix_clk_khz; + unsigned int required_pix_clk_100hz = timing->pix_clk_100hz; const struct dc_dongle_caps *dongle_caps = &dpcd_caps->dongle_caps; switch (dpcd_caps->dongle_type) { @@ -2107,9 +2103,9 @@ static bool dp_active_dongle_validate_timing( /* Check Color Depth and Pixel Clock */ if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) - required_pix_clk /= 2; + required_pix_clk_100hz /= 2; else if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) - required_pix_clk = required_pix_clk * 2 / 3; + required_pix_clk_100hz = required_pix_clk_100hz * 2 / 3; switch (timing->display_color_depth) { case COLOR_DEPTH_666: @@ -2119,12 +2115,12 @@ static bool dp_active_dongle_validate_timing( case COLOR_DEPTH_101010: if (dongle_caps->dp_hdmi_max_bpc < 10) return false; - required_pix_clk = required_pix_clk * 10 / 8; + required_pix_clk_100hz = required_pix_clk_100hz * 10 / 8; break; case COLOR_DEPTH_121212: if (dongle_caps->dp_hdmi_max_bpc < 12) return false; - required_pix_clk = required_pix_clk * 12 / 8; + required_pix_clk_100hz = required_pix_clk_100hz * 12 / 8; break; case COLOR_DEPTH_141414: @@ -2134,7 +2130,7 @@ static bool dp_active_dongle_validate_timing( return false; } - if (required_pix_clk > dongle_caps->dp_hdmi_max_pixel_clk) + if (required_pix_clk_100hz > (dongle_caps->dp_hdmi_max_pixel_clk * 10)) return false; return true; @@ -2145,7 +2141,7 @@ enum dc_status dc_link_validate_mode_timing( struct dc_link *link, const struct dc_crtc_timing *timing) { - uint32_t max_pix_clk = stream->sink->dongle_max_pix_clk; + uint32_t max_pix_clk = stream->link->dongle_max_pix_clk * 10; struct dpcd_caps *dpcd_caps = &link->dpcd_caps; /* A hack to avoid failing any modes for EDID override feature on @@ -2155,7 +2151,7 @@ enum dc_status dc_link_validate_mode_timing( return DC_OK; /* Passive Dongle */ - if (0 != max_pix_clk && timing->pix_clk_khz > max_pix_clk) + if (0 != max_pix_clk && timing->pix_clk_100hz > max_pix_clk) return DC_EXCEED_DONGLE_CAP; /* Active Dongle*/ @@ -2190,8 +2186,7 @@ int dc_link_get_backlight_level(const struct dc_link *link) bool dc_link_set_backlight_level(const struct dc_link *link, uint32_t backlight_pwm_u16_16, - uint32_t frame_ramp, - const struct dc_stream_state *stream) + uint32_t frame_ramp) { struct dc *core_dc = link->ctx->dc; struct abm *abm = core_dc->res_pool->abm; @@ -2206,10 +2201,6 @@ bool dc_link_set_backlight_level(const struct dc_link *link, (abm->funcs->set_backlight_level_pwm == NULL)) return false; - if (stream) - ((struct dc_stream_state *)stream)->bl_pwm_level = - backlight_pwm_u16_16; - use_smooth_brightness = dmcu->funcs->is_dmcu_initialized(dmcu); DC_LOG_BACKLIGHT("New Backlight level: %d (0x%X)\n", @@ -2219,7 +2210,7 @@ bool dc_link_set_backlight_level(const struct dc_link *link, for (i = 0; i < MAX_PIPES; i++) { if (core_dc->current_state->res_ctx.pipe_ctx[i].stream) { if (core_dc->current_state->res_ctx. - pipe_ctx[i].stream->sink->link + pipe_ctx[i].stream->link == link) /* DMCU -1 for all controller id values, * therefore +1 here @@ -2279,7 +2270,7 @@ void core_link_resume(struct dc_link *link) static struct fixed31_32 get_pbn_per_slot(struct dc_stream_state *stream) { struct dc_link_settings *link_settings = - &stream->sink->link->cur_link_settings; + &stream->link->cur_link_settings; uint32_t link_rate_in_mbps = link_settings->link_rate * LINK_RATE_REF_FREQ_IN_MHZ; struct fixed31_32 mbps = dc_fixpt_from_int( @@ -2310,7 +2301,7 @@ static struct fixed31_32 get_pbn_from_timing(struct pipe_ctx *pipe_ctx) uint32_t denominator; bpc = get_color_depth(pipe_ctx->stream_res.pix_clk_params.color_depth); - kbps = pipe_ctx->stream_res.pix_clk_params.requested_pix_clk * bpc * 3; + kbps = pipe_ctx->stream_res.pix_clk_params.requested_pix_clk_100hz / 10 * bpc * 3; /* * margin 5300ppm + 300ppm ~ 0.6% as per spec, factor is 1.006 @@ -2386,7 +2377,7 @@ static void update_mst_stream_alloc_table( static enum dc_status allocate_mst_payload(struct pipe_ctx *pipe_ctx) { struct dc_stream_state *stream = pipe_ctx->stream; - struct dc_link *link = stream->sink->link; + struct dc_link *link = stream->link; struct link_encoder *link_encoder = link->link_enc; struct stream_encoder *stream_encoder = pipe_ctx->stream_res.stream_enc; struct dp_mst_stream_allocation_table proposed_table = {0}; @@ -2466,7 +2457,7 @@ static enum dc_status allocate_mst_payload(struct pipe_ctx *pipe_ctx) static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx) { struct dc_stream_state *stream = pipe_ctx->stream; - struct dc_link *link = stream->sink->link; + struct dc_link *link = stream->link; struct link_encoder *link_encoder = link->link_enc; struct stream_encoder *stream_encoder = pipe_ctx->stream_res.stream_enc; struct dp_mst_stream_allocation_table proposed_table = {0}; @@ -2551,8 +2542,8 @@ void core_link_enable_stream( DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger); if (pipe_ctx->stream->signal != SIGNAL_TYPE_VIRTUAL) { - stream->sink->link->link_enc->funcs->setup( - stream->sink->link->link_enc, + stream->link->link_enc->funcs->setup( + stream->link->link_enc, pipe_ctx->stream->signal); pipe_ctx->stream_res.stream_enc->funcs->setup_stereo_sync( pipe_ctx->stream_res.stream_enc, @@ -2604,7 +2595,7 @@ void core_link_enable_stream( if (status != DC_OK) { DC_LOG_WARNING("enabling link %u failed: %d\n", - pipe_ctx->stream->sink->link->link_index, + pipe_ctx->stream->link->link_index, status); /* Abort stream enable *unless* the failure was due to @@ -2633,15 +2624,10 @@ void core_link_enable_stream( allocate_mst_payload(pipe_ctx); core_dc->hwss.unblank_stream(pipe_ctx, - &pipe_ctx->stream->sink->link->cur_link_settings); + &pipe_ctx->stream->link->cur_link_settings); if (dc_is_dp_signal(pipe_ctx->stream->signal)) enable_stream_features(pipe_ctx); - - dc_link_set_backlight_level(pipe_ctx->stream->sink->link, - pipe_ctx->stream->bl_pwm_level, - 0, - pipe_ctx->stream); } } @@ -2657,7 +2643,7 @@ void core_link_disable_stream(struct pipe_ctx *pipe_ctx, int option) core_dc->hwss.disable_stream(pipe_ctx, option); - disable_link(pipe_ctx->stream->sink->link, pipe_ctx->stream->signal); + disable_link(pipe_ctx->stream->link, pipe_ctx->stream->signal); } void core_link_set_avmute(struct pipe_ctx *pipe_ctx, bool enable) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c index 506a97e16956..b7ee63cd8dc7 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c @@ -33,7 +33,7 @@ #include "include/vector.h" #include "core_types.h" #include "dc_link_ddc.h" -#include "aux_engine.h" +#include "dce/dce_aux.h" #define AUX_POWER_UP_WA_DELAY 500 #define I2C_OVER_AUX_DEFER_WA_DELAY 70 @@ -42,7 +42,6 @@ #define CV_SMART_DONGLE_ADDRESS 0x20 /* DVI-HDMI dongle slave address for retrieving dongle signature*/ #define DVI_HDMI_DONGLE_ADDRESS 0x68 -static const int8_t dvi_hdmi_dongle_signature_str[] = "6140063500G"; struct dvi_hdmi_dongle_signature_data { int8_t vendor[3];/* "AMD" */ uint8_t version[2]; @@ -165,43 +164,6 @@ static void dal_ddc_i2c_payloads_destroy(struct i2c_payloads **p) } -static struct aux_payloads *dal_ddc_aux_payloads_create(struct dc_context *ctx, uint32_t count) -{ - struct aux_payloads *payloads; - - payloads = kzalloc(sizeof(struct aux_payloads), GFP_KERNEL); - - if (!payloads) - return NULL; - - if (dal_vector_construct( - &payloads->payloads, ctx, count, sizeof(struct aux_payload))) - return payloads; - - kfree(payloads); - return NULL; -} - -static struct aux_payload *dal_ddc_aux_payloads_get(struct aux_payloads *p) -{ - return (struct aux_payload *)p->payloads.container; -} - -static uint32_t dal_ddc_aux_payloads_get_count(struct aux_payloads *p) -{ - return p->payloads.count; -} - -static void dal_ddc_aux_payloads_destroy(struct aux_payloads **p) -{ - if (!p || !*p) - return; - - dal_vector_destruct(&(*p)->payloads); - kfree(*p); - *p = NULL; -} - #define DDC_MIN(a, b) (((a) < (b)) ? (a) : (b)) void dal_ddc_i2c_payloads_add( @@ -225,27 +187,6 @@ void dal_ddc_i2c_payloads_add( } -void dal_ddc_aux_payloads_add( - struct aux_payloads *payloads, - uint32_t address, - uint32_t len, - uint8_t *data, - bool write) -{ - uint32_t payload_size = DEFAULT_AUX_MAX_DATA_SIZE; - uint32_t pos; - - for (pos = 0; pos < len; pos += payload_size) { - struct aux_payload payload = { - .i2c_over_aux = true, - .write = write, - .address = address, - .length = DDC_MIN(payload_size, len - pos), - .data = data + pos }; - dal_vector_append(&payloads->payloads, &payload); - } -} - static void construct( struct ddc_service *ddc_service, struct ddc_service_init_data *init_data) @@ -574,32 +515,34 @@ bool dal_ddc_service_query_ddc_data( /*TODO: len of payload data for i2c and aux is uint8!!!!, * but we want to read 256 over i2c!!!!*/ if (dal_ddc_service_is_in_aux_transaction_mode(ddc)) { - - struct aux_payloads *payloads = - dal_ddc_aux_payloads_create(ddc->ctx, payloads_num); - - struct aux_command command = { - .payloads = dal_ddc_aux_payloads_get(payloads), - .number_of_payloads = 0, + struct aux_payload write_payload = { + .i2c_over_aux = true, + .write = true, + .mot = true, + .address = address, + .length = write_size, + .data = write_buf, + .reply = NULL, .defer_delay = get_defer_delay(ddc), - .max_defer_write_retry = 0 }; + }; - dal_ddc_aux_payloads_add( - payloads, address, write_size, write_buf, true); - - dal_ddc_aux_payloads_add( - payloads, address, read_size, read_buf, false); - - command.number_of_payloads = - dal_ddc_aux_payloads_get_count(payloads); + struct aux_payload read_payload = { + .i2c_over_aux = true, + .write = false, + .mot = false, + .address = address, + .length = read_size, + .data = read_buf, + .reply = NULL, + .defer_delay = get_defer_delay(ddc), + }; - ret = dal_i2caux_submit_aux_command( - ddc->ctx->i2caux, - ddc->ddc_pin, - &command); + ret = dc_link_aux_transfer_with_retries(ddc, &write_payload); - dal_ddc_aux_payloads_destroy(&payloads); + if (!ret) + return false; + ret = dc_link_aux_transfer_with_retries(ddc, &read_payload); } else { struct i2c_payloads *payloads = dal_ddc_i2c_payloads_create(ddc->ctx, payloads_num); @@ -631,56 +574,15 @@ bool dal_ddc_service_query_ddc_data( } int dc_link_aux_transfer(struct ddc_service *ddc, - unsigned int address, - uint8_t *reply, - void *buffer, - unsigned int size, - enum aux_transaction_type type, - enum i2caux_transaction_action action) + struct aux_payload *payload) { - struct ddc *ddc_pin = ddc->ddc_pin; - struct aux_engine *aux_engine; - enum aux_channel_operation_result operation_result; - struct aux_request_transaction_data aux_req; - struct aux_reply_transaction_data aux_rep; - uint8_t returned_bytes = 0; - int res = -1; - uint32_t status; - - memset(&aux_req, 0, sizeof(aux_req)); - memset(&aux_rep, 0, sizeof(aux_rep)); - - aux_engine = ddc->ctx->dc->res_pool->engines[ddc_pin->pin_data->en]; - aux_engine->funcs->acquire(aux_engine, ddc_pin); - - aux_req.type = type; - aux_req.action = action; - - aux_req.address = address; - aux_req.delay = 0; - aux_req.length = size; - aux_req.data = buffer; - - aux_engine->funcs->submit_channel_request(aux_engine, &aux_req); - operation_result = aux_engine->funcs->get_channel_status(aux_engine, &returned_bytes); - - switch (operation_result) { - case AUX_CHANNEL_OPERATION_SUCCEEDED: - res = aux_engine->funcs->read_channel_reply(aux_engine, size, - buffer, reply, - &status); - break; - case AUX_CHANNEL_OPERATION_FAILED_HPD_DISCON: - res = 0; - break; - case AUX_CHANNEL_OPERATION_FAILED_REASON_UNKNOWN: - case AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY: - case AUX_CHANNEL_OPERATION_FAILED_TIMEOUT: - res = -1; - break; - } - aux_engine->funcs->release_engine(aux_engine); - return res; + return dce_aux_transfer(ddc, payload); +} + +bool dc_link_aux_transfer_with_retries(struct ddc_service *ddc, + struct aux_payload *payload) +{ + return dce_aux_transfer_with_retries(ddc, payload); } /*test only function*/ diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 0caacb60b02f..92f565ca1260 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -47,7 +47,7 @@ static void wait_for_training_aux_rd_interval( struct dc_link *link, uint32_t default_wait_in_micro_secs) { - union training_aux_rd_interval training_rd_interval; + union training_aux_rd_interval training_rd_interval = {0}; /* overwrite the delay if rev > 1.1*/ if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_12) { @@ -117,6 +117,13 @@ static void dpcd_set_link_settings( core_link_write_dpcd(link, DP_DOWNSPREAD_CTRL, &downspread.raw, sizeof(downspread)); + if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_14 && + (link->dpcd_caps.link_rate_set >= 1 && + link->dpcd_caps.link_rate_set <= 8)) { + core_link_write_dpcd(link, DP_LINK_RATE_SET, + &link->dpcd_caps.link_rate_set, 1); + } + DC_LOG_HW_LINK_TRAINING("%s\n %x rate = %x\n %x lane = %x\n %x spread = %x\n", __func__, DP_LINK_BW_SET, @@ -1542,7 +1549,7 @@ static uint32_t bandwidth_in_kbps_from_timing( ASSERT(bits_per_channel != 0); - kbps = timing->pix_clk_khz; + kbps = timing->pix_clk_100hz / 10; kbps *= bits_per_channel; if (timing->flags.Y_ONLY != 1) { @@ -1584,7 +1591,7 @@ bool dp_validate_mode_timing( const struct dc_link_settings *link_setting; /*always DP fail safe mode*/ - if (timing->pix_clk_khz == (uint32_t) 25175 && + if ((timing->pix_clk_100hz / 10) == (uint32_t) 25175 && timing->h_addressable == (uint32_t) 640 && timing->v_addressable == (uint32_t) 480) return true; @@ -1634,7 +1641,7 @@ void decide_link_settings(struct dc_stream_state *stream, req_bw = bandwidth_in_kbps_from_timing(&stream->timing); - link = stream->sink->link; + link = stream->link; /* if preferred is specified through AMDDP, use it, if it's enough * to drive the mode @@ -1656,7 +1663,7 @@ void decide_link_settings(struct dc_stream_state *stream, } /* EDP use the link cap setting */ - if (stream->sink->sink_signal == SIGNAL_TYPE_EDP) { + if (link->connector_signal == SIGNAL_TYPE_EDP) { *link_setting = link->verified_link_cap; return; } @@ -2002,11 +2009,7 @@ static void handle_automated_test(struct dc_link *link) dp_test_send_phy_test_pattern(link); test_response.bits.ACK = 1; } - if (!test_request.raw) - /* no requests, revert all test signals - * TODO: revert all test signals - */ - test_response.bits.ACK = 1; + /* send request acknowledgment */ if (test_response.bits.ACK) core_link_write_dpcd( @@ -2493,13 +2496,105 @@ bool detect_dp_sink_caps(struct dc_link *link) /* TODO save sink caps in link->sink */ } +enum dc_link_rate linkRateInKHzToLinkRateMultiplier(uint32_t link_rate_in_khz) +{ + enum dc_link_rate link_rate; + // LinkRate is normally stored as a multiplier of 0.27 Gbps per lane. Do the translation. + switch (link_rate_in_khz) { + case 1620000: + link_rate = LINK_RATE_LOW; // Rate_1 (RBR) - 1.62 Gbps/Lane + break; + case 2160000: + link_rate = LINK_RATE_RATE_2; // Rate_2 - 2.16 Gbps/Lane + break; + case 2430000: + link_rate = LINK_RATE_RATE_3; // Rate_3 - 2.43 Gbps/Lane + break; + case 2700000: + link_rate = LINK_RATE_HIGH; // Rate_4 (HBR) - 2.70 Gbps/Lane + break; + case 3240000: + link_rate = LINK_RATE_RBR2; // Rate_5 (RBR2) - 3.24 Gbps/Lane + break; + case 4320000: + link_rate = LINK_RATE_RATE_6; // Rate_6 - 4.32 Gbps/Lane + break; + case 5400000: + link_rate = LINK_RATE_HIGH2; // Rate_7 (HBR2) - 5.40 Gbps/Lane + break; + case 8100000: + link_rate = LINK_RATE_HIGH3; // Rate_8 (HBR3) - 8.10 Gbps/Lane + break; + default: + link_rate = LINK_RATE_UNKNOWN; + break; + } + return link_rate; +} + void detect_edp_sink_caps(struct dc_link *link) { - retrieve_link_cap(link); + uint8_t supported_link_rates[16] = {0}; + uint32_t entry; + uint32_t link_rate_in_khz; + enum dc_link_rate link_rate = LINK_RATE_UNKNOWN; + uint8_t link_rate_set = 0; - if (link->reported_link_cap.link_rate == LINK_RATE_UNKNOWN) - link->reported_link_cap.link_rate = LINK_RATE_HIGH2; + retrieve_link_cap(link); + if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_14) { + // Read DPCD 00010h - 0001Fh 16 bytes at one shot + core_link_read_dpcd(link, DP_SUPPORTED_LINK_RATES, + supported_link_rates, sizeof(supported_link_rates)); + + link->dpcd_caps.link_rate_set = 0; + for (entry = 0; entry < 16; entry += 2) { + // DPCD register reports per-lane link rate = 16-bit link rate capability + // value X 200 kHz. Need multipler to find link rate in kHz. + link_rate_in_khz = (supported_link_rates[entry+1] * 0x100 + + supported_link_rates[entry]) * 200; + + if (link_rate_in_khz != 0) { + link_rate = linkRateInKHzToLinkRateMultiplier(link_rate_in_khz); + if (link->reported_link_cap.link_rate < link_rate) { + link->reported_link_cap.link_rate = link_rate; + + switch (link_rate) { + case LINK_RATE_LOW: + link_rate_set = 1; + break; + case LINK_RATE_RATE_2: + link_rate_set = 2; + break; + case LINK_RATE_RATE_3: + link_rate_set = 3; + break; + case LINK_RATE_HIGH: + link_rate_set = 4; + break; + case LINK_RATE_RBR2: + link_rate_set = 5; + break; + case LINK_RATE_RATE_6: + link_rate_set = 6; + break; + case LINK_RATE_HIGH2: + link_rate_set = 7; + break; + case LINK_RATE_HIGH3: + link_rate_set = 8; + break; + default: + link_rate_set = 0; + break; + } + + if (link->dpcd_caps.link_rate_set < link_rate_set) + link->dpcd_caps.link_rate_set = link_rate_set; + } + } + } + } link->verified_link_cap = link->reported_link_cap; } @@ -2621,7 +2716,7 @@ bool dc_link_dp_set_test_pattern( memset(&training_pattern, 0, sizeof(training_pattern)); for (i = 0; i < MAX_PIPES; i++) { - if (pipes[i].stream->sink->link == link) { + if (pipes[i].stream->link == link) { pipe_ctx = &pipes[i]; break; } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index 0065ec7d5330..16d441d3af8a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -70,13 +70,12 @@ void dp_enable_link_phy( */ for (i = 0; i < MAX_PIPES; i++) { if (pipes[i].stream != NULL && - pipes[i].stream->sink != NULL && - pipes[i].stream->sink->link == link) { + pipes[i].stream->link == link) { if (pipes[i].clock_source != NULL && pipes[i].clock_source->id != CLOCK_SOURCE_ID_DP_DTO) { pipes[i].clock_source = dp_cs; - pipes[i].stream_res.pix_clk_params.requested_pix_clk = - pipes[i].stream->timing.pix_clk_khz; + pipes[i].stream_res.pix_clk_params.requested_pix_clk_100hz = + pipes[i].stream->timing.pix_clk_100hz; pipes[i].clock_source->funcs->program_pix_clk( pipes[i].clock_source, &pipes[i].stream_res.pix_clk_params, @@ -279,10 +278,8 @@ void dp_retrain_link_dp_test(struct dc_link *link, for (i = 0; i < MAX_PIPES; i++) { if (pipes[i].stream != NULL && !pipes[i].top_pipe && - pipes[i].stream->sink != NULL && - pipes[i].stream->sink->link != NULL && - pipes[i].stream_res.stream_enc != NULL && - pipes[i].stream->sink->link == link) { + pipes[i].stream->link != NULL && + pipes[i].stream_res.stream_enc != NULL) { udelay(100); pipes[i].stream_res.stream_enc->funcs->dp_blank( diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 76137df74a53..9888bc7659f3 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -355,8 +355,8 @@ bool resource_are_streams_timing_synchronizable( != stream2->timing.v_addressable) return false; - if (stream1->timing.pix_clk_khz - != stream2->timing.pix_clk_khz) + if (stream1->timing.pix_clk_100hz + != stream2->timing.pix_clk_100hz) return false; if (stream1->clamping.c_depth != stream2->clamping.c_depth) @@ -1559,7 +1559,7 @@ static struct stream_encoder *find_first_free_match_stream_enc_for_link( { int i; int j = -1; - struct dc_link *link = stream->sink->link; + struct dc_link *link = stream->link; for (i = 0; i < pool->stream_enc_count; i++) { if (!res_ctx->is_stream_enc_acquired[i] && @@ -1748,7 +1748,7 @@ static struct dc_stream_state *find_pll_sharable_stream( if (resource_are_streams_timing_synchronizable( stream_needs_pll, stream_has_pll) && !dc_is_dp_signal(stream_has_pll->signal) - && stream_has_pll->sink->link->connector_signal + && stream_has_pll->link->connector_signal != SIGNAL_TYPE_VIRTUAL) return stream_has_pll; @@ -1759,7 +1759,7 @@ static struct dc_stream_state *find_pll_sharable_stream( static int get_norm_pix_clk(const struct dc_crtc_timing *timing) { - uint32_t pix_clk = timing->pix_clk_khz; + uint32_t pix_clk = timing->pix_clk_100hz; uint32_t normalized_pix_clk = pix_clk; if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) @@ -1791,10 +1791,10 @@ static void calculate_phy_pix_clks(struct dc_stream_state *stream) /* update actual pixel clock on all streams */ if (dc_is_hdmi_signal(stream->signal)) stream->phy_pix_clk = get_norm_pix_clk( - &stream->timing); + &stream->timing) / 10; else stream->phy_pix_clk = - stream->timing.pix_clk_khz; + stream->timing.pix_clk_100hz / 10; if (stream->timing.timing_3d_format == TIMING_3D_FORMAT_HW_FRAME_PACKING) stream->phy_pix_clk *= 2; @@ -1842,7 +1842,7 @@ enum dc_status resource_map_pool_resources( &context->res_ctx, pool, stream); if (!pipe_ctx->stream_res.stream_enc) - return DC_NO_STREAM_ENG_RESOURCE; + return DC_NO_STREAM_ENC_RESOURCE; update_stream_engine_usage( &context->res_ctx, pool, @@ -1850,7 +1850,7 @@ enum dc_status resource_map_pool_resources( true); /* TODO: Add check if ASIC support and EDID audio */ - if (!stream->sink->converter_disable_audio && + if (!stream->converter_disable_audio && dc_is_audio_capable_signal(pipe_ctx->stream->signal) && stream->audio_info.mode_count) { pipe_ctx->stream_res.audio = find_first_free_audio( @@ -2112,7 +2112,7 @@ static void set_avi_info_frame( itc = true; itc_value = 1; - support = stream->sink->edid_caps.content_support; + support = stream->content_support; if (itc) { if (!support.bits.valid_content_type) { @@ -2151,8 +2151,8 @@ static void set_avi_info_frame( /* TODO : We should handle YCC quantization */ /* but we do not have matrix calculation */ - if (stream->sink->edid_caps.qs_bit == 1 && - stream->sink->edid_caps.qy_bit == 1) { + if (stream->qs_bit == 1 && + stream->qy_bit == 1) { if (color_space == COLOR_SPACE_SRGB || color_space == COLOR_SPACE_2020_RGB_FULLRANGE) { hdmi_info.bits.Q0_Q1 = RGB_QUANTIZATION_FULL_RANGE; @@ -2596,7 +2596,7 @@ void resource_build_bit_depth_reduction_params(struct dc_stream_state *stream, enum dc_status dc_validate_stream(struct dc *dc, struct dc_stream_state *stream) { struct dc *core_dc = dc; - struct dc_link *link = stream->sink->link; + struct dc_link *link = stream->link; struct timing_generator *tg = core_dc->res_pool->timing_generators[0]; enum dc_status res = DC_OK; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 66e5c4623a49..996298c35f42 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -35,20 +35,17 @@ /******************************************************************************* * Private functions ******************************************************************************/ -void update_stream_signal(struct dc_stream_state *stream) +void update_stream_signal(struct dc_stream_state *stream, struct dc_sink *sink) { - - struct dc_sink *dc_sink = stream->sink; - - if (dc_sink->sink_signal == SIGNAL_TYPE_NONE) - stream->signal = stream->sink->link->connector_signal; + if (sink->sink_signal == SIGNAL_TYPE_NONE) + stream->signal = stream->link->connector_signal; else - stream->signal = dc_sink->sink_signal; + stream->signal = sink->sink_signal; if (dc_is_dvi_signal(stream->signal)) { if (stream->ctx->dc->caps.dual_link_dvi && - stream->timing.pix_clk_khz > TMDS_MAX_PIXEL_CLOCK && - stream->sink->sink_signal != SIGNAL_TYPE_DVI_SINGLE_LINK) + (stream->timing.pix_clk_100hz / 10) > TMDS_MAX_PIXEL_CLOCK && + sink->sink_signal != SIGNAL_TYPE_DVI_SINGLE_LINK) stream->signal = SIGNAL_TYPE_DVI_DUAL_LINK; else stream->signal = SIGNAL_TYPE_DVI_SINGLE_LINK; @@ -61,10 +58,15 @@ static void construct(struct dc_stream_state *stream, uint32_t i = 0; stream->sink = dc_sink_data; - stream->ctx = stream->sink->ctx; - dc_sink_retain(dc_sink_data); + stream->ctx = dc_sink_data->ctx; + stream->link = dc_sink_data->link; + stream->sink_patches = dc_sink_data->edid_caps.panel_patch; + stream->converter_disable_audio = dc_sink_data->converter_disable_audio; + stream->qs_bit = dc_sink_data->edid_caps.qs_bit; + stream->qy_bit = dc_sink_data->edid_caps.qy_bit; + /* Copy audio modes */ /* TODO - Remove this translation */ for (i = 0; i < (dc_sink_data->edid_caps.audio_mode_count); i++) @@ -100,11 +102,14 @@ static void construct(struct dc_stream_state *stream, /* EDID CAP translation for HDMI 2.0 */ stream->timing.flags.LTE_340MCSC_SCRAMBLE = dc_sink_data->edid_caps.lte_340mcsc_scramble; - update_stream_signal(stream); + update_stream_signal(stream, dc_sink_data); stream->out_transfer_func = dc_create_transfer_func(); stream->out_transfer_func->type = TF_TYPE_BYPASS; stream->out_transfer_func->ctx = stream->ctx; + + stream->stream_id = stream->ctx->dc_stream_id_count; + stream->ctx->dc_stream_id_count++; } static void destruct(struct dc_stream_state *stream) @@ -155,21 +160,43 @@ struct dc_stream_state *dc_create_stream_for_sink( return stream; } -struct dc_stream_status *dc_stream_get_status( +/** + * dc_stream_get_status_from_state - Get stream status from given dc state + * @state: DC state to find the stream status in + * @stream: The stream to get the stream status for + * + * The given stream is expected to exist in the given dc state. Otherwise, NULL + * will be returned. + */ +struct dc_stream_status *dc_stream_get_status_from_state( + struct dc_state *state, struct dc_stream_state *stream) { uint8_t i; - struct dc *dc = stream->ctx->dc; - for (i = 0; i < dc->current_state->stream_count; i++) { - if (stream == dc->current_state->streams[i]) - return &dc->current_state->stream_status[i]; + for (i = 0; i < state->stream_count; i++) { + if (stream == state->streams[i]) + return &state->stream_status[i]; } return NULL; } /** + * dc_stream_get_status() - Get current stream status of the given stream state + * @stream: The stream to get the stream status for. + * + * The given stream is expected to exist in dc->current_state. Otherwise, NULL + * will be returned. + */ +struct dc_stream_status *dc_stream_get_status( + struct dc_stream_state *stream) +{ + struct dc *dc = stream->ctx->dc; + return dc_stream_get_status_from_state(dc->current_state, stream); +} + +/** * dc_stream_set_cursor_attributes() - Update cursor attributes and set cursor surface address */ bool dc_stream_set_cursor_attributes( @@ -334,16 +361,12 @@ void dc_stream_log(const struct dc *dc, const struct dc_stream_state *stream) stream->output_color_space); DC_LOG_DC( "\tpix_clk_khz: %d, h_total: %d, v_total: %d, pixelencoder:%d, displaycolorDepth:%d\n", - stream->timing.pix_clk_khz, + stream->timing.pix_clk_100hz / 10, stream->timing.h_total, stream->timing.v_total, stream->timing.pixel_encoding, stream->timing.display_color_depth); DC_LOG_DC( - "\tsink name: %s, serial: %d\n", - stream->sink->edid_caps.display_name, - stream->sink->edid_caps.serial_number); - DC_LOG_DC( "\tlink: %d\n", - stream->sink->link->link_index); + stream->link->link_index); } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c index c60c9b4c3075..ee6bd50f60b8 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c @@ -40,11 +40,14 @@ static void construct(struct dc_context *ctx, struct dc_plane_state *plane_state plane_state->ctx = ctx; plane_state->gamma_correction = dc_create_gamma(); - plane_state->gamma_correction->is_identity = true; + if (plane_state->gamma_correction != NULL) + plane_state->gamma_correction->is_identity = true; plane_state->in_transfer_func = dc_create_transfer_func(); - plane_state->in_transfer_func->type = TF_TYPE_BYPASS; - plane_state->in_transfer_func->ctx = ctx; + if (plane_state->in_transfer_func != NULL) { + plane_state->in_transfer_func->type = TF_TYPE_BYPASS; + plane_state->in_transfer_func->ctx = ctx; + } } static void destruct(struct dc_plane_state *plane_state) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_vm_helper.c b/drivers/gpu/drm/amd/display/dc/core/dc_vm_helper.c new file mode 100644 index 000000000000..e54b8ac339b2 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/core/dc_vm_helper.c @@ -0,0 +1,127 @@ +/* + * Copyright 2018 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "vm_helper.h" + +static void mark_vmid_used(struct vm_helper *vm_helper, unsigned int pos, uint8_t hubp_idx) +{ + struct vmid_usage vmids = vm_helper->hubp_vmid_usage[hubp_idx]; + + vmids.vmid_usage[0] = vmids.vmid_usage[1]; + vmids.vmid_usage[1] = 1 << pos; +} + +static void add_ptb_to_table(struct vm_helper *vm_helper, unsigned int vmid, uint64_t ptb) +{ + vm_helper->ptb_assigned_to_vmid[vmid] = ptb; + vm_helper->num_vmids_available--; +} + +static void clear_entry_from_vmid_table(struct vm_helper *vm_helper, unsigned int vmid) +{ + vm_helper->ptb_assigned_to_vmid[vmid] = 0; + vm_helper->num_vmids_available++; +} + +static void evict_vmids(struct vm_helper *vm_helper) +{ + int i; + uint16_t ord = 0; + + for (i = 0; i < vm_helper->num_vmid; i++) + ord |= vm_helper->hubp_vmid_usage[i].vmid_usage[0] | vm_helper->hubp_vmid_usage[i].vmid_usage[1]; + + // At this point any positions with value 0 are unused vmids, evict them + for (i = 1; i < vm_helper->num_vmid; i++) { + if (ord & (1u << i)) + clear_entry_from_vmid_table(vm_helper, i); + } +} + +// Return value of -1 indicates vmid table unitialized or ptb dne in the table +static int get_existing_vmid_for_ptb(struct vm_helper *vm_helper, uint64_t ptb) +{ + int i; + + for (i = 0; i < vm_helper->num_vmid; i++) { + if (vm_helper->ptb_assigned_to_vmid[i] == ptb) + return i; + } + + return -1; +} + +// Expected to be called only when there's an available vmid +static int get_next_available_vmid(struct vm_helper *vm_helper) +{ + int i; + + for (i = 1; i < vm_helper->num_vmid; i++) { + if (vm_helper->ptb_assigned_to_vmid[i] == 0) + return i; + } + + return -1; +} + +uint8_t get_vmid_for_ptb(struct vm_helper *vm_helper, int64_t ptb, uint8_t hubp_idx) +{ + unsigned int vmid = 0; + int vmid_exists = -1; + + // Physical address gets vmid 0 + if (ptb == 0) + return 0; + + vmid_exists = get_existing_vmid_for_ptb(vm_helper, ptb); + + if (vmid_exists != -1) { + mark_vmid_used(vm_helper, vmid_exists, hubp_idx); + vmid = vmid_exists; + } else { + if (vm_helper->num_vmids_available == 0) + evict_vmids(vm_helper); + + vmid = get_next_available_vmid(vm_helper); + mark_vmid_used(vm_helper, vmid, hubp_idx); + add_ptb_to_table(vm_helper, vmid, ptb); + } + + return vmid; +} + +struct vm_helper init_vm_helper(unsigned int num_vmid, unsigned int num_hubp) +{ + static uint64_t ptb_assigned_to_vmid[MAX_VMID]; + static struct vmid_usage hubp_vmid_usage[MAX_HUBP]; + + return (struct vm_helper){ + .num_vmid = num_vmid, + .num_hubp = num_hubp, + .num_vmids_available = num_vmid - 1, + .ptb_assigned_to_vmid = ptb_assigned_to_vmid, + .hubp_vmid_usage = hubp_vmid_usage + }; +} diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 4b5bbb13ce7f..8391bc39b7a9 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -39,7 +39,7 @@ #include "inc/hw/dmcu.h" #include "dml/display_mode_lib.h" -#define DC_VER "3.2.08" +#define DC_VER "3.2.15" #define MAX_SURFACES 3 #define MAX_STREAMS 6 @@ -255,6 +255,7 @@ struct dc_debug_options { bool scl_reset_length10; bool hdmi20_disable; bool skip_detection_link_training; + unsigned int force_fclk_khz; }; struct dc_debug_data { @@ -339,8 +340,13 @@ struct dc_init_data { uint32_t log_mask; }; -struct dc *dc_create(const struct dc_init_data *init_params); +struct dc_callback_init { + uint8_t reserved; +}; +struct dc *dc_create(const struct dc_init_data *init_params); +void dc_init_callbacks(struct dc *dc, + const struct dc_callback_init *init_params); void dc_destroy(struct dc **dc); /******************************************************************************* @@ -440,6 +446,7 @@ union surface_update_flags { uint32_t coeff_reduction_change:1; uint32_t output_tf_change:1; uint32_t pixel_format_change:1; + uint32_t plane_size_change:1; /* Full updates */ uint32_t new_plane:1; @@ -652,6 +659,7 @@ struct dpcd_caps { int8_t branch_dev_name[6]; int8_t branch_hw_revision; int8_t branch_fw_revision[2]; + uint8_t link_rate_set; bool allow_invalid_MSA_timing_param; bool panel_mode_edp; @@ -742,6 +750,9 @@ void dc_set_power_state( struct dc *dc, enum dc_acpi_cm_power_state power_state); void dc_resume(struct dc *dc); +unsigned int dc_get_current_backlight_pwm(struct dc *dc); +unsigned int dc_get_target_backlight_pwm(struct dc *dc); + bool dc_is_dmcu_initialized(struct dc *dc); #endif /* DC_INTERFACE_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dc_bios_types.h b/drivers/gpu/drm/amd/display/dc/dc_bios_types.h index a8b3cedf9431..78c3b300ec45 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_bios_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_bios_types.h @@ -86,10 +86,6 @@ struct dc_vbios_funcs { bool (*is_accelerated_mode)( struct dc_bios *bios); - bool (*is_active_display)( - struct dc_bios *bios, - enum signal_type signal, - const struct connector_device_tag_info *device_tag); void (*set_scratch_critical_state)( struct dc_bios *bios, bool state); @@ -125,10 +121,6 @@ struct dc_vbios_funcs { enum bp_result (*program_crtc_timing)( struct dc_bios *bios, struct bp_hw_crtc_timing_parameters *bp_params); - - enum bp_result (*crtc_source_select)( - struct dc_bios *bios, - struct bp_crtc_source_select *bp_params); enum bp_result (*program_display_engine_pll)( struct dc_bios *bios, struct bp_pixel_clock_parameters *bp_params); @@ -145,7 +137,6 @@ struct dc_vbios_funcs { }; struct bios_registers { - uint32_t BIOS_SCRATCH_0; uint32_t BIOS_SCRATCH_3; uint32_t BIOS_SCRATCH_6; }; diff --git a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h index da93ab43f2d8..d4eab33c453b 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h @@ -46,11 +46,14 @@ enum dc_lane_count { */ enum dc_link_rate { LINK_RATE_UNKNOWN = 0, - LINK_RATE_LOW = 0x06, - LINK_RATE_HIGH = 0x0A, - LINK_RATE_RBR2 = 0x0C, - LINK_RATE_HIGH2 = 0x14, - LINK_RATE_HIGH3 = 0x1E + LINK_RATE_LOW = 0x06, // Rate_1 (RBR) - 1.62 Gbps/Lane + LINK_RATE_RATE_2 = 0x08, // Rate_2 - 2.16 Gbps/Lane + LINK_RATE_RATE_3 = 0x09, // Rate_3 - 2.43 Gbps/Lane + LINK_RATE_HIGH = 0x0A, // Rate_4 (HBR) - 2.70 Gbps/Lane + LINK_RATE_RBR2 = 0x0C, // Rate_5 (RBR2)- 3.24 Gbps/Lane + LINK_RATE_RATE_6 = 0x10, // Rate_6 - 4.32 Gbps/Lane + LINK_RATE_HIGH2 = 0x14, // Rate_7 (HBR2)- 5.40 Gbps/Lane + LINK_RATE_HIGH3 = 0x1E // Rate_8 (HBR3)- 8.10 Gbps/Lane }; enum dc_link_spread { diff --git a/drivers/gpu/drm/amd/display/dc/dc_helper.c b/drivers/gpu/drm/amd/display/dc/dc_helper.c index 4842d2378bbf..597d38393379 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_helper.c +++ b/drivers/gpu/drm/amd/display/dc/dc_helper.c @@ -29,31 +29,59 @@ #include "dm_services.h" #include <stdarg.h> +struct dc_reg_value_masks { + uint32_t value; + uint32_t mask; +}; + +struct dc_reg_sequence { + uint32_t addr; + struct dc_reg_value_masks value_masks; +}; + +static inline void set_reg_field_value_masks( + struct dc_reg_value_masks *field_value_mask, + uint32_t value, + uint32_t mask, + uint8_t shift) +{ + ASSERT(mask != 0); + + field_value_mask->value = (field_value_mask->value & ~mask) | (mask & (value << shift)); + field_value_mask->mask = field_value_mask->mask | mask; +} + uint32_t generic_reg_update_ex(const struct dc_context *ctx, uint32_t addr, uint32_t reg_val, int n, uint8_t shift1, uint32_t mask1, uint32_t field_value1, ...) { + struct dc_reg_value_masks field_value_mask = {0}; uint32_t shift, mask, field_value; int i = 1; va_list ap; va_start(ap, field_value1); - reg_val = set_reg_field_value_ex(reg_val, field_value1, mask1, shift1); + /* gather all bits value/mask getting updated in this register */ + set_reg_field_value_masks(&field_value_mask, + field_value1, mask1, shift1); while (i < n) { shift = va_arg(ap, uint32_t); mask = va_arg(ap, uint32_t); field_value = va_arg(ap, uint32_t); - reg_val = set_reg_field_value_ex(reg_val, field_value, mask, shift); + set_reg_field_value_masks(&field_value_mask, + field_value, mask, shift); i++; } - - dm_write_reg(ctx, addr, reg_val); va_end(ap); + + /* mmio write directly */ + reg_val = (reg_val & ~field_value_mask.mask) | field_value_mask.value; + dm_write_reg(ctx, addr, reg_val); return reg_val; } diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h index e72fce4eca65..da55d623647a 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h @@ -97,6 +97,8 @@ struct dc_plane_address { union large_integer chroma_dcc_const_color; } video_progressive; }; + + union large_integer page_table_base; }; struct dc_size { @@ -730,7 +732,7 @@ struct dc_crtc_timing { uint32_t v_front_porch; uint32_t v_sync_width; - uint32_t pix_clk_khz; + uint32_t pix_clk_100hz; uint32_t vic; uint32_t hdmi_vic; diff --git a/drivers/gpu/drm/amd/display/dc/dc_link.h b/drivers/gpu/drm/amd/display/dc/dc_link.h index 29f19d57ff7a..f249ff9be2a7 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_link.h +++ b/drivers/gpu/drm/amd/display/dc/dc_link.h @@ -110,6 +110,7 @@ struct dc_link { union ddi_channel_mapping ddi_channel_mapping; struct connector_device_tag_info device_tag; struct dpcd_caps dpcd_caps; + uint32_t dongle_max_pix_clk; unsigned short chip_caps; unsigned int dpcd_sink_count; enum edp_revision edp_revision; @@ -146,8 +147,7 @@ static inline struct dc_link *dc_get_link_at_index(struct dc *dc, uint32_t link_ */ bool dc_link_set_backlight_level(const struct dc_link *dc_link, uint32_t backlight_pwm_u16_16, - uint32_t frame_ramp, - const struct dc_stream_state *stream); + uint32_t frame_ramp); int dc_link_get_backlight_level(const struct dc_link *dc_link); diff --git a/drivers/gpu/drm/amd/display/dc/dc_stream.h b/drivers/gpu/drm/amd/display/dc/dc_stream.h index be34d638e15d..7bb1da18c1ba 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_stream.h +++ b/drivers/gpu/drm/amd/display/dc/dc_stream.h @@ -38,11 +38,6 @@ struct dc_stream_status { int stream_enc_inst; int plane_count; struct dc_plane_state *plane_states[MAX_SURFACE_NUM]; - - /* - * link this stream passes through - */ - struct dc_link *link; }; // TODO: References to this needs to be removed.. @@ -51,7 +46,13 @@ struct freesync_context { }; struct dc_stream_state { + // sink is deprecated, new code should not reference + // this pointer struct dc_sink *sink; + + struct dc_link *link; + struct dc_panel_patch sink_patches; + union display_content_support content_support; struct dc_crtc_timing timing; struct dc_crtc_timing_adjust adjust; struct dc_info_packet vrr_infopacket; @@ -80,6 +81,9 @@ struct dc_stream_state { enum view_3d_format view_format; bool ignore_msa_timing_param; + bool converter_disable_audio; + uint8_t qs_bit; + uint8_t qy_bit; unsigned long long periodic_fn_vsync_delta; @@ -91,7 +95,6 @@ struct dc_stream_state { /* DMCU info */ unsigned int abm_level; - unsigned int bl_pwm_level; /* from core_stream struct */ struct dc_context *ctx; @@ -105,6 +108,8 @@ struct dc_stream_state { bool dpms_off; bool apply_edp_fast_boot_optimization; + void *dm_stream_context; + struct dc_cursor_attributes cursor_attributes; struct dc_cursor_position cursor_position; uint32_t sdr_white_level; // for boosting (SDR) cursor in HDR mode @@ -117,6 +122,18 @@ struct dc_stream_state { /* Computed state bits */ bool mode_changed : 1; + /* Output from DC when stream state is committed or altered + * DC may only access these values during: + * dc_commit_state, dc_commit_state_no_check, dc_commit_streams + * values may not change outside of those calls + */ + struct { + // For interrupt management, some hardware instance + // offsets need to be exposed to DM + uint8_t otg_offset; + } out; + + uint32_t stream_id; }; struct dc_stream_update { @@ -163,7 +180,6 @@ void dc_commit_updates_for_stream(struct dc *dc, int surface_count, struct dc_stream_state *stream, struct dc_stream_update *stream_update, - struct dc_plane_state **plane_states, struct dc_state *state); /* * Log the current stream state. @@ -256,11 +272,14 @@ enum surface_update_type dc_check_update_surfaces_for_stream( */ struct dc_stream_state *dc_create_stream_for_sink(struct dc_sink *dc_sink); -void update_stream_signal(struct dc_stream_state *stream); +void update_stream_signal(struct dc_stream_state *stream, struct dc_sink *sink); void dc_stream_retain(struct dc_stream_state *dc_stream); void dc_stream_release(struct dc_stream_state *dc_stream); +struct dc_stream_status *dc_stream_get_status_from_state( + struct dc_state *state, + struct dc_stream_state *stream); struct dc_stream_status *dc_stream_get_status( struct dc_stream_state *dc_stream); diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index 0b20ae23f169..56e7f3dab15a 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -97,8 +97,8 @@ struct dc_context { struct dc_bios *dc_bios; bool created_bios; struct gpio_service *gpio_service; - struct i2caux *i2caux; uint32_t dc_sink_id_count; + uint32_t dc_stream_id_count; uint64_t fbc_gpu_addr; }; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c b/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c index aaeb7faac0c4..adbb22224e1a 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c @@ -24,6 +24,7 @@ */ #include "dm_services.h" +#include "core_types.h" #include "dce_aux.h" #include "dce/dce_11_0_sh_mask.h" @@ -41,17 +42,17 @@ container_of((ptr), struct aux_engine_dce110, base) #define FROM_ENGINE(ptr) \ - FROM_AUX_ENGINE(container_of((ptr), struct aux_engine, base)) + FROM_AUX_ENGINE(container_of((ptr), struct dce_aux, base)) #define FROM_AUX_ENGINE_ENGINE(ptr) \ - container_of((ptr), struct aux_engine, base) + container_of((ptr), struct dce_aux, base) enum { AUX_INVALID_REPLY_RETRY_COUNTER = 1, AUX_TIMED_OUT_RETRY_COUNTER = 2, AUX_DEFER_RETRY_COUNTER = 6 }; static void release_engine( - struct aux_engine *engine) + struct dce_aux *engine) { struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine); @@ -66,7 +67,7 @@ static void release_engine( #define DMCU_CAN_ACCESS_AUX 2 static bool is_engine_available( - struct aux_engine *engine) + struct dce_aux *engine) { struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine); @@ -79,7 +80,7 @@ static bool is_engine_available( return (field != DMCU_CAN_ACCESS_AUX); } static bool acquire_engine( - struct aux_engine *engine) + struct dce_aux *engine) { struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine); @@ -155,7 +156,7 @@ static bool acquire_engine( (0xFF & (address)) static void submit_channel_request( - struct aux_engine *engine, + struct dce_aux *engine, struct aux_request_transaction_data *request) { struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine); @@ -247,7 +248,7 @@ static void submit_channel_request( REG_UPDATE(AUX_SW_CONTROL, AUX_SW_GO, 1); } -static int read_channel_reply(struct aux_engine *engine, uint32_t size, +static int read_channel_reply(struct dce_aux *engine, uint32_t size, uint8_t *buffer, uint8_t *reply_result, uint32_t *sw_status) { @@ -273,7 +274,8 @@ static int read_channel_reply(struct aux_engine *engine, uint32_t size, REG_GET(AUX_SW_DATA, AUX_SW_DATA, &reply_result_32); reply_result_32 = reply_result_32 >> 4; - *reply_result = (uint8_t)reply_result_32; + if (reply_result != NULL) + *reply_result = (uint8_t)reply_result_32; if (reply_result_32 == 0) { /* ACK */ uint32_t i = 0; @@ -299,61 +301,8 @@ static int read_channel_reply(struct aux_engine *engine, uint32_t size, return 0; } -static void process_channel_reply( - struct aux_engine *engine, - struct aux_reply_transaction_data *reply) -{ - int bytes_replied; - uint8_t reply_result; - uint32_t sw_status; - - bytes_replied = read_channel_reply(engine, reply->length, reply->data, - &reply_result, &sw_status); - - /* in case HPD is LOW, exit AUX transaction */ - if ((sw_status & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK)) { - reply->status = AUX_TRANSACTION_REPLY_HPD_DISCON; - return; - } - - if (bytes_replied < 0) { - /* Need to handle an error case... - * Hopefully, upper layer function won't call this function if - * the number of bytes in the reply was 0, because there was - * surely an error that was asserted that should have been - * handled for hot plug case, this could happens - */ - if (!(sw_status & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK)) { - reply->status = AUX_TRANSACTION_REPLY_INVALID; - ASSERT_CRITICAL(false); - return; - } - } else { - - switch (reply_result) { - case 0: /* ACK */ - reply->status = AUX_TRANSACTION_REPLY_AUX_ACK; - break; - case 1: /* NACK */ - reply->status = AUX_TRANSACTION_REPLY_AUX_NACK; - break; - case 2: /* DEFER */ - reply->status = AUX_TRANSACTION_REPLY_AUX_DEFER; - break; - case 4: /* AUX ACK / I2C NACK */ - reply->status = AUX_TRANSACTION_REPLY_I2C_NACK; - break; - case 8: /* AUX ACK / I2C DEFER */ - reply->status = AUX_TRANSACTION_REPLY_I2C_DEFER; - break; - default: - reply->status = AUX_TRANSACTION_REPLY_INVALID; - } - } -} - static enum aux_channel_operation_result get_channel_status( - struct aux_engine *engine, + struct dce_aux *engine, uint8_t *returned_bytes) { struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine); @@ -414,469 +363,22 @@ static enum aux_channel_operation_result get_channel_status( return AUX_CHANNEL_OPERATION_FAILED_TIMEOUT; } } -static void process_read_reply( - struct aux_engine *engine, - struct read_command_context *ctx) -{ - engine->funcs->process_channel_reply(engine, &ctx->reply); - - switch (ctx->reply.status) { - case AUX_TRANSACTION_REPLY_AUX_ACK: - ctx->defer_retry_aux = 0; - if (ctx->returned_byte > ctx->current_read_length) { - ctx->status = - I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR; - ctx->operation_succeeded = false; - } else if (ctx->returned_byte < ctx->current_read_length) { - ctx->current_read_length -= ctx->returned_byte; - - ctx->offset += ctx->returned_byte; - - ++ctx->invalid_reply_retry_aux_on_ack; - - if (ctx->invalid_reply_retry_aux_on_ack > - AUX_INVALID_REPLY_RETRY_COUNTER) { - ctx->status = - I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR; - ctx->operation_succeeded = false; - } - } else { - ctx->status = I2CAUX_TRANSACTION_STATUS_SUCCEEDED; - ctx->transaction_complete = true; - ctx->operation_succeeded = true; - } - break; - case AUX_TRANSACTION_REPLY_AUX_NACK: - ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_NACK; - ctx->operation_succeeded = false; - break; - case AUX_TRANSACTION_REPLY_AUX_DEFER: - ++ctx->defer_retry_aux; - - if (ctx->defer_retry_aux > AUX_DEFER_RETRY_COUNTER) { - ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT; - ctx->operation_succeeded = false; - } - break; - case AUX_TRANSACTION_REPLY_I2C_DEFER: - ctx->defer_retry_aux = 0; - - ++ctx->defer_retry_i2c; - - if (ctx->defer_retry_i2c > AUX_DEFER_RETRY_COUNTER) { - ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT; - ctx->operation_succeeded = false; - } - break; - case AUX_TRANSACTION_REPLY_HPD_DISCON: - ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_HPD_DISCON; - ctx->operation_succeeded = false; - break; - default: - ctx->status = I2CAUX_TRANSACTION_STATUS_UNKNOWN; - ctx->operation_succeeded = false; - } -} -static void process_read_request( - struct aux_engine *engine, - struct read_command_context *ctx) -{ - enum aux_channel_operation_result operation_result; - engine->funcs->submit_channel_request(engine, &ctx->request); - - operation_result = engine->funcs->get_channel_status( - engine, &ctx->returned_byte); - - switch (operation_result) { - case AUX_CHANNEL_OPERATION_SUCCEEDED: - if (ctx->returned_byte > ctx->current_read_length) { - ctx->status = - I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR; - ctx->operation_succeeded = false; - } else { - ctx->timed_out_retry_aux = 0; - ctx->invalid_reply_retry_aux = 0; - - ctx->reply.length = ctx->returned_byte; - ctx->reply.data = ctx->buffer; - - process_read_reply(engine, ctx); - } - break; - case AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY: - ++ctx->invalid_reply_retry_aux; - - if (ctx->invalid_reply_retry_aux > - AUX_INVALID_REPLY_RETRY_COUNTER) { - ctx->status = - I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR; - ctx->operation_succeeded = false; - } else - udelay(400); - break; - case AUX_CHANNEL_OPERATION_FAILED_TIMEOUT: - ++ctx->timed_out_retry_aux; - - if (ctx->timed_out_retry_aux > AUX_TIMED_OUT_RETRY_COUNTER) { - ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT; - ctx->operation_succeeded = false; - } else { - /* DP 1.2a, table 2-58: - * "S3: AUX Request CMD PENDING: - * retry 3 times, with 400usec wait on each" - * The HW timeout is set to 550usec, - * so we should not wait here - */ - } - break; - case AUX_CHANNEL_OPERATION_FAILED_HPD_DISCON: - ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_HPD_DISCON; - ctx->operation_succeeded = false; - break; - default: - ctx->status = I2CAUX_TRANSACTION_STATUS_UNKNOWN; - ctx->operation_succeeded = false; - } -} -static bool read_command( - struct aux_engine *engine, - struct i2caux_transaction_request *request, - bool middle_of_transaction) -{ - struct read_command_context ctx; - - ctx.buffer = request->payload.data; - ctx.current_read_length = request->payload.length; - ctx.offset = 0; - ctx.timed_out_retry_aux = 0; - ctx.invalid_reply_retry_aux = 0; - ctx.defer_retry_aux = 0; - ctx.defer_retry_i2c = 0; - ctx.invalid_reply_retry_aux_on_ack = 0; - ctx.transaction_complete = false; - ctx.operation_succeeded = true; - - if (request->payload.address_space == - I2CAUX_TRANSACTION_ADDRESS_SPACE_DPCD) { - ctx.request.type = AUX_TRANSACTION_TYPE_DP; - ctx.request.action = I2CAUX_TRANSACTION_ACTION_DP_READ; - ctx.request.address = request->payload.address; - } else if (request->payload.address_space == - I2CAUX_TRANSACTION_ADDRESS_SPACE_I2C) { - ctx.request.type = AUX_TRANSACTION_TYPE_I2C; - ctx.request.action = middle_of_transaction ? - I2CAUX_TRANSACTION_ACTION_I2C_READ_MOT : - I2CAUX_TRANSACTION_ACTION_I2C_READ; - ctx.request.address = request->payload.address >> 1; - } else { - /* in DAL2, there was no return in such case */ - BREAK_TO_DEBUGGER(); - return false; - } - - ctx.request.delay = 0; - - do { - memset(ctx.buffer + ctx.offset, 0, ctx.current_read_length); - - ctx.request.data = ctx.buffer + ctx.offset; - ctx.request.length = ctx.current_read_length; - - process_read_request(engine, &ctx); - - request->status = ctx.status; - - if (ctx.operation_succeeded && !ctx.transaction_complete) - if (ctx.request.type == AUX_TRANSACTION_TYPE_I2C) - msleep(engine->delay); - } while (ctx.operation_succeeded && !ctx.transaction_complete); - - if (request->payload.address_space == - I2CAUX_TRANSACTION_ADDRESS_SPACE_DPCD) { - DC_LOG_I2C_AUX("READ: addr:0x%x value:0x%x Result:%d", - request->payload.address, - request->payload.data[0], - ctx.operation_succeeded); - } - - return ctx.operation_succeeded; -} - -static void process_write_reply( - struct aux_engine *engine, - struct write_command_context *ctx) -{ - engine->funcs->process_channel_reply(engine, &ctx->reply); - - switch (ctx->reply.status) { - case AUX_TRANSACTION_REPLY_AUX_ACK: - ctx->operation_succeeded = true; - - if (ctx->returned_byte) { - ctx->request.action = ctx->mot ? - I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST_MOT : - I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST; - - ctx->current_write_length = 0; - - ++ctx->ack_m_retry; - - if (ctx->ack_m_retry > AUX_DEFER_RETRY_COUNTER) { - ctx->status = - I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT; - ctx->operation_succeeded = false; - } else - udelay(300); - } else { - ctx->status = I2CAUX_TRANSACTION_STATUS_SUCCEEDED; - ctx->defer_retry_aux = 0; - ctx->ack_m_retry = 0; - ctx->transaction_complete = true; - } - break; - case AUX_TRANSACTION_REPLY_AUX_NACK: - ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_NACK; - ctx->operation_succeeded = false; - break; - case AUX_TRANSACTION_REPLY_AUX_DEFER: - ++ctx->defer_retry_aux; - - if (ctx->defer_retry_aux > ctx->max_defer_retry) { - ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT; - ctx->operation_succeeded = false; - } - break; - case AUX_TRANSACTION_REPLY_I2C_DEFER: - ctx->defer_retry_aux = 0; - ctx->current_write_length = 0; - - ctx->request.action = ctx->mot ? - I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST_MOT : - I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST; - - ++ctx->defer_retry_i2c; - - if (ctx->defer_retry_i2c > ctx->max_defer_retry) { - ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT; - ctx->operation_succeeded = false; - } - break; - case AUX_TRANSACTION_REPLY_HPD_DISCON: - ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_HPD_DISCON; - ctx->operation_succeeded = false; - break; - default: - ctx->status = I2CAUX_TRANSACTION_STATUS_UNKNOWN; - ctx->operation_succeeded = false; - } -} -static void process_write_request( - struct aux_engine *engine, - struct write_command_context *ctx) -{ - enum aux_channel_operation_result operation_result; - - engine->funcs->submit_channel_request(engine, &ctx->request); - - operation_result = engine->funcs->get_channel_status( - engine, &ctx->returned_byte); - - switch (operation_result) { - case AUX_CHANNEL_OPERATION_SUCCEEDED: - ctx->timed_out_retry_aux = 0; - ctx->invalid_reply_retry_aux = 0; - - ctx->reply.length = ctx->returned_byte; - ctx->reply.data = ctx->reply_data; - - process_write_reply(engine, ctx); - break; - case AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY: - ++ctx->invalid_reply_retry_aux; - - if (ctx->invalid_reply_retry_aux > - AUX_INVALID_REPLY_RETRY_COUNTER) { - ctx->status = - I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR; - ctx->operation_succeeded = false; - } else - udelay(400); - break; - case AUX_CHANNEL_OPERATION_FAILED_TIMEOUT: - ++ctx->timed_out_retry_aux; - - if (ctx->timed_out_retry_aux > AUX_TIMED_OUT_RETRY_COUNTER) { - ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT; - ctx->operation_succeeded = false; - } else { - /* DP 1.2a, table 2-58: - * "S3: AUX Request CMD PENDING: - * retry 3 times, with 400usec wait on each" - * The HW timeout is set to 550usec, - * so we should not wait here - */ - } - break; - case AUX_CHANNEL_OPERATION_FAILED_HPD_DISCON: - ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_HPD_DISCON; - ctx->operation_succeeded = false; - break; - default: - ctx->status = I2CAUX_TRANSACTION_STATUS_UNKNOWN; - ctx->operation_succeeded = false; - } -} -static bool write_command( - struct aux_engine *engine, - struct i2caux_transaction_request *request, - bool middle_of_transaction) -{ - struct write_command_context ctx; - - ctx.mot = middle_of_transaction; - ctx.buffer = request->payload.data; - ctx.current_write_length = request->payload.length; - ctx.timed_out_retry_aux = 0; - ctx.invalid_reply_retry_aux = 0; - ctx.defer_retry_aux = 0; - ctx.defer_retry_i2c = 0; - ctx.ack_m_retry = 0; - ctx.transaction_complete = false; - ctx.operation_succeeded = true; - - if (request->payload.address_space == - I2CAUX_TRANSACTION_ADDRESS_SPACE_DPCD) { - ctx.request.type = AUX_TRANSACTION_TYPE_DP; - ctx.request.action = I2CAUX_TRANSACTION_ACTION_DP_WRITE; - ctx.request.address = request->payload.address; - } else if (request->payload.address_space == - I2CAUX_TRANSACTION_ADDRESS_SPACE_I2C) { - ctx.request.type = AUX_TRANSACTION_TYPE_I2C; - ctx.request.action = middle_of_transaction ? - I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT : - I2CAUX_TRANSACTION_ACTION_I2C_WRITE; - ctx.request.address = request->payload.address >> 1; - } else { - /* in DAL2, there was no return in such case */ - BREAK_TO_DEBUGGER(); - return false; - } - - ctx.request.delay = 0; - - ctx.max_defer_retry = - (engine->max_defer_write_retry > AUX_DEFER_RETRY_COUNTER) ? - engine->max_defer_write_retry : AUX_DEFER_RETRY_COUNTER; - - do { - ctx.request.data = ctx.buffer; - ctx.request.length = ctx.current_write_length; - - process_write_request(engine, &ctx); - - request->status = ctx.status; - - if (ctx.operation_succeeded && !ctx.transaction_complete) - if (ctx.request.type == AUX_TRANSACTION_TYPE_I2C) - msleep(engine->delay); - } while (ctx.operation_succeeded && !ctx.transaction_complete); - - if (request->payload.address_space == - I2CAUX_TRANSACTION_ADDRESS_SPACE_DPCD) { - DC_LOG_I2C_AUX("WRITE: addr:0x%x value:0x%x Result:%d", - request->payload.address, - request->payload.data[0], - ctx.operation_succeeded); - } - - return ctx.operation_succeeded; -} -static bool end_of_transaction_command( - struct aux_engine *engine, - struct i2caux_transaction_request *request) -{ - struct i2caux_transaction_request dummy_request; - uint8_t dummy_data; - - /* [tcheng] We only need to send the stop (read with MOT = 0) - * for I2C-over-Aux, not native AUX - */ - - if (request->payload.address_space != - I2CAUX_TRANSACTION_ADDRESS_SPACE_I2C) - return false; - - dummy_request.operation = request->operation; - dummy_request.payload.address_space = request->payload.address_space; - dummy_request.payload.address = request->payload.address; - - /* - * Add a dummy byte due to some receiver quirk - * where one byte is sent along with MOT = 0. - * Ideally this should be 0. - */ - - dummy_request.payload.length = 0; - dummy_request.payload.data = &dummy_data; - - if (request->operation == I2CAUX_TRANSACTION_READ) - return read_command(engine, &dummy_request, false); - else - return write_command(engine, &dummy_request, false); - - /* according Syed, it does not need now DoDummyMOT */ -} -static bool submit_request( - struct aux_engine *engine, - struct i2caux_transaction_request *request, - bool middle_of_transaction) -{ - - bool result; - bool mot_used = true; - - switch (request->operation) { - case I2CAUX_TRANSACTION_READ: - result = read_command(engine, request, mot_used); - break; - case I2CAUX_TRANSACTION_WRITE: - result = write_command(engine, request, mot_used); - break; - default: - result = false; - } - - /* [tcheng] - * need to send stop for the last transaction to free up the AUX - * if the above command fails, this would be the last transaction - */ - - if (!middle_of_transaction || !result) - end_of_transaction_command(engine, request); - - /* mask AUX interrupt */ - - return result; -} enum i2caux_engine_type get_engine_type( - const struct aux_engine *engine) + const struct dce_aux *engine) { return I2CAUX_ENGINE_TYPE_AUX; } static bool acquire( - struct aux_engine *engine, + struct dce_aux *engine, struct ddc *ddc) { enum gpio_result result; - if (engine->funcs->is_engine_available) { - /*check whether SW could use the engine*/ - if (!engine->funcs->is_engine_available(engine)) - return false; - } + if (!is_engine_available(engine)) + return false; result = dal_ddc_open(ddc, GPIO_MODE_HARDWARE, GPIO_DDC_CONFIG_TYPE_MODE_AUX); @@ -884,7 +386,7 @@ static bool acquire( if (result != GPIO_RESULT_OK) return false; - if (!engine->funcs->acquire_engine(engine)) { + if (!acquire_engine(engine)) { dal_ddc_close(ddc); return false; } @@ -894,21 +396,7 @@ static bool acquire( return true; } -static const struct aux_engine_funcs aux_engine_funcs = { - .acquire_engine = acquire_engine, - .submit_channel_request = submit_channel_request, - .process_channel_reply = process_channel_reply, - .read_channel_reply = read_channel_reply, - .get_channel_status = get_channel_status, - .is_engine_available = is_engine_available, - .release_engine = release_engine, - .destroy_engine = dce110_engine_destroy, - .submit_request = submit_request, - .get_engine_type = get_engine_type, - .acquire = acquire, -}; - -void dce110_engine_destroy(struct aux_engine **engine) +void dce110_engine_destroy(struct dce_aux **engine) { struct aux_engine_dce110 *engine110 = FROM_AUX_ENGINE(*engine); @@ -917,7 +405,7 @@ void dce110_engine_destroy(struct aux_engine **engine) *engine = NULL; } -struct aux_engine *dce110_aux_engine_construct(struct aux_engine_dce110 *aux_engine110, +struct dce_aux *dce110_aux_engine_construct(struct aux_engine_dce110 *aux_engine110, struct dc_context *ctx, uint32_t inst, uint32_t timeout_period, @@ -927,7 +415,6 @@ struct aux_engine *dce110_aux_engine_construct(struct aux_engine_dce110 *aux_eng aux_engine110->base.ctx = ctx; aux_engine110->base.delay = 0; aux_engine110->base.max_defer_write_retry = 0; - aux_engine110->base.funcs = &aux_engine_funcs; aux_engine110->base.inst = inst; aux_engine110->timeout_period = timeout_period; aux_engine110->regs = regs; @@ -935,3 +422,101 @@ struct aux_engine *dce110_aux_engine_construct(struct aux_engine_dce110 *aux_eng return &aux_engine110->base; } +static enum i2caux_transaction_action i2caux_action_from_payload(struct aux_payload *payload) +{ + if (payload->i2c_over_aux) { + if (payload->write) { + if (payload->mot) + return I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT; + return I2CAUX_TRANSACTION_ACTION_I2C_WRITE; + } + if (payload->mot) + return I2CAUX_TRANSACTION_ACTION_I2C_READ_MOT; + return I2CAUX_TRANSACTION_ACTION_I2C_READ; + } + if (payload->write) + return I2CAUX_TRANSACTION_ACTION_DP_WRITE; + return I2CAUX_TRANSACTION_ACTION_DP_READ; +} + +int dce_aux_transfer(struct ddc_service *ddc, + struct aux_payload *payload) +{ + struct ddc *ddc_pin = ddc->ddc_pin; + struct dce_aux *aux_engine; + enum aux_channel_operation_result operation_result; + struct aux_request_transaction_data aux_req; + struct aux_reply_transaction_data aux_rep; + uint8_t returned_bytes = 0; + int res = -1; + uint32_t status; + + memset(&aux_req, 0, sizeof(aux_req)); + memset(&aux_rep, 0, sizeof(aux_rep)); + + aux_engine = ddc->ctx->dc->res_pool->engines[ddc_pin->pin_data->en]; + acquire(aux_engine, ddc_pin); + + if (payload->i2c_over_aux) + aux_req.type = AUX_TRANSACTION_TYPE_I2C; + else + aux_req.type = AUX_TRANSACTION_TYPE_DP; + + aux_req.action = i2caux_action_from_payload(payload); + + aux_req.address = payload->address; + aux_req.delay = payload->defer_delay * 10; + aux_req.length = payload->length; + aux_req.data = payload->data; + + submit_channel_request(aux_engine, &aux_req); + operation_result = get_channel_status(aux_engine, &returned_bytes); + + switch (operation_result) { + case AUX_CHANNEL_OPERATION_SUCCEEDED: + res = read_channel_reply(aux_engine, payload->length, + payload->data, payload->reply, + &status); + break; + case AUX_CHANNEL_OPERATION_FAILED_HPD_DISCON: + res = 0; + break; + case AUX_CHANNEL_OPERATION_FAILED_REASON_UNKNOWN: + case AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY: + case AUX_CHANNEL_OPERATION_FAILED_TIMEOUT: + res = -1; + break; + } + release_engine(aux_engine); + return res; +} + +#define AUX_RETRY_MAX 7 + +bool dce_aux_transfer_with_retries(struct ddc_service *ddc, + struct aux_payload *payload) +{ + int i, ret = 0; + uint8_t reply; + bool payload_reply = true; + + if (!payload->reply) { + payload_reply = false; + payload->reply = &reply; + } + + for (i = 0; i < AUX_RETRY_MAX; i++) { + ret = dce_aux_transfer(ddc, payload); + + if (ret >= 0) { + if (*payload->reply == 0) { + if (!payload_reply) + payload->reply = NULL; + return true; + } + } + + msleep(1); + } + return false; +} diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_aux.h b/drivers/gpu/drm/amd/display/dc/dce/dce_aux.h index f7caab85dc80..d27f22c05e4b 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_aux.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_aux.h @@ -25,7 +25,9 @@ #ifndef __DAL_AUX_ENGINE_DCE110_H__ #define __DAL_AUX_ENGINE_DCE110_H__ -#include "aux_engine.h" + +#include "i2caux_interface.h" +#include "inc/hw/aux_engine.h" #define AUX_COMMON_REG_LIST(id)\ SRI(AUX_CONTROL, DP_AUX, id), \ @@ -75,8 +77,20 @@ enum { /* This is the timeout as defined in DP 1.2a, */ SW_AUX_TIMEOUT_PERIOD_MULTIPLIER = 4 }; + +struct dce_aux { + uint32_t inst; + struct ddc *ddc; + struct dc_context *ctx; + /* following values are expressed in milliseconds */ + uint32_t delay; + uint32_t max_defer_write_retry; + + bool acquire_reset; +}; + struct aux_engine_dce110 { - struct aux_engine base; + struct dce_aux base; const struct dce110_aux_registers *regs; struct { uint32_t aux_control; @@ -96,16 +110,22 @@ struct aux_engine_dce110_init_data { const struct dce110_aux_registers *regs; }; -struct aux_engine *dce110_aux_engine_construct( +struct dce_aux *dce110_aux_engine_construct( struct aux_engine_dce110 *aux_engine110, struct dc_context *ctx, uint32_t inst, uint32_t timeout_period, const struct dce110_aux_registers *regs); -void dce110_engine_destroy(struct aux_engine **engine); +void dce110_engine_destroy(struct dce_aux **engine); bool dce110_aux_engine_acquire( - struct aux_engine *aux_engine, + struct dce_aux *aux_engine, struct ddc *ddc); + +int dce_aux_transfer(struct ddc_service *ddc, + struct aux_payload *cmd); + +bool dce_aux_transfer_with_retries(struct ddc_service *ddc, + struct aux_payload *cmd); #endif diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clk_mgr.c index afd287f08bc9..3c52a4fc921d 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clk_mgr.c @@ -194,8 +194,8 @@ static uint32_t get_max_pixel_clock_for_all_paths(struct dc_state *context) if (pipe_ctx->top_pipe) continue; - if (pipe_ctx->stream_res.pix_clk_params.requested_pix_clk > max_pix_clk) - max_pix_clk = pipe_ctx->stream_res.pix_clk_params.requested_pix_clk; + if (pipe_ctx->stream_res.pix_clk_params.requested_pix_clk_100hz / 10 > max_pix_clk) + max_pix_clk = pipe_ctx->stream_res.pix_clk_params.requested_pix_clk_100hz / 10; /* raise clock state for HBR3/2 if required. Confirmed with HW DCE/DPCS * logic for HBR3 still needs Nominal (0.8V) on VDDC rail @@ -257,7 +257,7 @@ static int dce_set_clock( clk_mgr_dce->dentist_vco_freq_khz / 64); /* Prepare to program display clock*/ - pxl_clk_params.target_pixel_clock = requested_clk_khz; + pxl_clk_params.target_pixel_clock_100hz = requested_clk_khz * 10; pxl_clk_params.pll_id = CLOCK_SOURCE_ID_DFS; if (clk_mgr_dce->dfs_bypass_active) @@ -450,6 +450,42 @@ void dce_clock_read_ss_info(struct dce_clk_mgr *clk_mgr_dce) } } +/** + * dce121_clock_patch_xgmi_ss_info() - Save XGMI spread spectrum info + * @clk_mgr: clock manager base structure + * + * Reads from VBIOS the XGMI spread spectrum info and saves it within + * the dce clock manager. This operation will overwrite the existing dprefclk + * SS values if the vBIOS query succeeds. Otherwise, it does nothing. It also + * sets the ->xgmi_enabled flag. + */ +void dce121_clock_patch_xgmi_ss_info(struct clk_mgr *clk_mgr) +{ + struct dce_clk_mgr *clk_mgr_dce = TO_DCE_CLK_MGR(clk_mgr); + enum bp_result result; + struct spread_spectrum_info info = { { 0 } }; + struct dc_bios *bp = clk_mgr_dce->base.ctx->dc_bios; + + clk_mgr_dce->xgmi_enabled = false; + + result = bp->funcs->get_spread_spectrum_info(bp, AS_SIGNAL_TYPE_XGMI, + 0, &info); + if (result == BP_RESULT_OK && info.spread_spectrum_percentage != 0) { + clk_mgr_dce->xgmi_enabled = true; + clk_mgr_dce->ss_on_dprefclk = true; + clk_mgr_dce->dprefclk_ss_divider = + info.spread_percentage_divider; + + if (info.type.CENTER_MODE == 0) { + /* Currently for DP Reference clock we + * need only SS percentage for + * downspread */ + clk_mgr_dce->dprefclk_ss_percentage = + info.spread_spectrum_percentage; + } + } +} + void dce110_fill_display_configs( const struct dc_state *context, struct dm_pp_display_configuration *pp_display_cfg) @@ -483,18 +519,18 @@ void dce110_fill_display_configs( cfg->src_height = stream->src.height; cfg->src_width = stream->src.width; cfg->ddi_channel_mapping = - stream->sink->link->ddi_channel_mapping.raw; + stream->link->ddi_channel_mapping.raw; cfg->transmitter = - stream->sink->link->link_enc->transmitter; + stream->link->link_enc->transmitter; cfg->link_settings.lane_count = - stream->sink->link->cur_link_settings.lane_count; + stream->link->cur_link_settings.lane_count; cfg->link_settings.link_rate = - stream->sink->link->cur_link_settings.link_rate; + stream->link->cur_link_settings.link_rate; cfg->link_settings.link_spread = - stream->sink->link->cur_link_settings.link_spread; + stream->link->cur_link_settings.link_spread; cfg->sym_clock = stream->phy_pix_clk; /* Round v_refresh*/ - cfg->v_refresh = stream->timing.pix_clk_khz * 1000; + cfg->v_refresh = stream->timing.pix_clk_100hz * 100; cfg->v_refresh /= stream->timing.h_total; cfg->v_refresh = (cfg->v_refresh + stream->timing.v_total / 2) / stream->timing.v_total; @@ -518,7 +554,7 @@ static uint32_t dce110_get_min_vblank_time_us(const struct dc_state *context) - stream->timing.v_addressable); vertical_blank_time = vertical_blank_in_pixels - * 1000 / stream->timing.pix_clk_khz; + * 10000 / stream->timing.pix_clk_100hz; if (min_vertical_blank_time > vertical_blank_time) min_vertical_blank_time = vertical_blank_time; @@ -612,7 +648,7 @@ static void dce11_pplib_apply_display_requirements( pp_display_cfg->crtc_index = pp_display_cfg->disp_configs[0].pipe_idx; - pp_display_cfg->line_time_in_us = timing->h_total * 1000 / timing->pix_clk_khz; + pp_display_cfg->line_time_in_us = timing->h_total * 10000 / timing->pix_clk_100hz; } if (memcmp(&dc->current_state->pp_display_cfg, pp_display_cfg, sizeof(*pp_display_cfg)) != 0) @@ -625,11 +661,11 @@ static void dce_update_clocks(struct clk_mgr *clk_mgr, { struct dce_clk_mgr *clk_mgr_dce = TO_DCE_CLK_MGR(clk_mgr); struct dm_pp_power_level_change_request level_change_req; - int unpatched_disp_clk = context->bw.dce.dispclk_khz; + int patched_disp_clk = context->bw.dce.dispclk_khz; /*TODO: W/A for dal3 linux, investigate why this works */ if (!clk_mgr_dce->dfs_bypass_active) - context->bw.dce.dispclk_khz = context->bw.dce.dispclk_khz * 115 / 100; + patched_disp_clk = patched_disp_clk * 115 / 100; level_change_req.power_level = dce_get_required_clocks_state(clk_mgr, context); /* get max clock state from PPLIB */ @@ -639,13 +675,11 @@ static void dce_update_clocks(struct clk_mgr *clk_mgr, clk_mgr_dce->cur_min_clks_state = level_change_req.power_level; } - if (should_set_clock(safe_to_lower, context->bw.dce.dispclk_khz, clk_mgr->clks.dispclk_khz)) { - context->bw.dce.dispclk_khz = dce_set_clock(clk_mgr, context->bw.dce.dispclk_khz); - clk_mgr->clks.dispclk_khz = context->bw.dce.dispclk_khz; + if (should_set_clock(safe_to_lower, patched_disp_clk, clk_mgr->clks.dispclk_khz)) { + patched_disp_clk = dce_set_clock(clk_mgr, patched_disp_clk); + clk_mgr->clks.dispclk_khz = patched_disp_clk; } dce_pplib_apply_display_requirements(clk_mgr->ctx->dc, context); - - context->bw.dce.dispclk_khz = unpatched_disp_clk; } static void dce11_update_clocks(struct clk_mgr *clk_mgr, @@ -676,11 +710,11 @@ static void dce112_update_clocks(struct clk_mgr *clk_mgr, { struct dce_clk_mgr *clk_mgr_dce = TO_DCE_CLK_MGR(clk_mgr); struct dm_pp_power_level_change_request level_change_req; - int unpatched_disp_clk = context->bw.dce.dispclk_khz; + int patched_disp_clk = context->bw.dce.dispclk_khz; /*TODO: W/A for dal3 linux, investigate why this works */ if (!clk_mgr_dce->dfs_bypass_active) - context->bw.dce.dispclk_khz = context->bw.dce.dispclk_khz * 115 / 100; + patched_disp_clk = patched_disp_clk * 115 / 100; level_change_req.power_level = dce_get_required_clocks_state(clk_mgr, context); /* get max clock state from PPLIB */ @@ -690,13 +724,11 @@ static void dce112_update_clocks(struct clk_mgr *clk_mgr, clk_mgr_dce->cur_min_clks_state = level_change_req.power_level; } - if (should_set_clock(safe_to_lower, context->bw.dce.dispclk_khz, clk_mgr->clks.dispclk_khz)) { - context->bw.dce.dispclk_khz = dce112_set_clock(clk_mgr, context->bw.dce.dispclk_khz); - clk_mgr->clks.dispclk_khz = context->bw.dce.dispclk_khz; + if (should_set_clock(safe_to_lower, patched_disp_clk, clk_mgr->clks.dispclk_khz)) { + patched_disp_clk = dce112_set_clock(clk_mgr, patched_disp_clk); + clk_mgr->clks.dispclk_khz = patched_disp_clk; } dce11_pplib_apply_display_requirements(clk_mgr->ctx->dc, context); - - context->bw.dce.dispclk_khz = unpatched_disp_clk; } static void dce12_update_clocks(struct clk_mgr *clk_mgr, @@ -706,17 +738,23 @@ static void dce12_update_clocks(struct clk_mgr *clk_mgr, struct dce_clk_mgr *clk_mgr_dce = TO_DCE_CLK_MGR(clk_mgr); struct dm_pp_clock_for_voltage_req clock_voltage_req = {0}; int max_pix_clk = get_max_pixel_clock_for_all_paths(context); - int unpatched_disp_clk = context->bw.dce.dispclk_khz; + int patched_disp_clk = context->bw.dce.dispclk_khz; /*TODO: W/A for dal3 linux, investigate why this works */ if (!clk_mgr_dce->dfs_bypass_active) - context->bw.dce.dispclk_khz = context->bw.dce.dispclk_khz * 115 / 100; + patched_disp_clk = patched_disp_clk * 115 / 100; - if (should_set_clock(safe_to_lower, context->bw.dce.dispclk_khz, clk_mgr->clks.dispclk_khz)) { + if (should_set_clock(safe_to_lower, patched_disp_clk, clk_mgr->clks.dispclk_khz)) { clock_voltage_req.clk_type = DM_PP_CLOCK_TYPE_DISPLAY_CLK; - clock_voltage_req.clocks_in_khz = context->bw.dce.dispclk_khz; - context->bw.dce.dispclk_khz = dce112_set_clock(clk_mgr, context->bw.dce.dispclk_khz); - clk_mgr->clks.dispclk_khz = context->bw.dce.dispclk_khz; + /* + * When xGMI is enabled, the display clk needs to be adjusted + * with the WAFL link's SS percentage. + */ + if (clk_mgr_dce->xgmi_enabled) + patched_disp_clk = clk_mgr_adjust_dp_ref_freq_for_ss( + clk_mgr_dce, patched_disp_clk); + clock_voltage_req.clocks_in_khz = patched_disp_clk; + clk_mgr->clks.dispclk_khz = dce112_set_clock(clk_mgr, patched_disp_clk); dm_pp_apply_clock_for_voltage_request(clk_mgr->ctx, &clock_voltage_req); } @@ -729,8 +767,6 @@ static void dce12_update_clocks(struct clk_mgr *clk_mgr, dm_pp_apply_clock_for_voltage_request(clk_mgr->ctx, &clock_voltage_req); } dce11_pplib_apply_display_requirements(clk_mgr->ctx->dc, context); - - context->bw.dce.dispclk_khz = unpatched_disp_clk; } static const struct clk_mgr_funcs dce120_funcs = { @@ -882,6 +918,27 @@ struct clk_mgr *dce120_clk_mgr_create(struct dc_context *ctx) return &clk_mgr_dce->base; } +struct clk_mgr *dce121_clk_mgr_create(struct dc_context *ctx) +{ + struct dce_clk_mgr *clk_mgr_dce = kzalloc(sizeof(*clk_mgr_dce), + GFP_KERNEL); + + if (clk_mgr_dce == NULL) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + memcpy(clk_mgr_dce->max_clks_by_state, dce120_max_clks_by_state, + sizeof(dce120_max_clks_by_state)); + + dce_clk_mgr_construct(clk_mgr_dce, ctx, NULL, NULL, NULL); + + clk_mgr_dce->dprefclk_khz = 625000; + clk_mgr_dce->base.funcs = &dce120_funcs; + + return &clk_mgr_dce->base; +} + void dce_clk_mgr_destroy(struct clk_mgr **clk_mgr) { struct dce_clk_mgr *clk_mgr_dce = TO_DCE_CLK_MGR(*clk_mgr); diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clk_mgr.h b/drivers/gpu/drm/amd/display/dc/dce/dce_clk_mgr.h index 3bceb31d910d..c8f8c442142a 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clk_mgr.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clk_mgr.h @@ -94,11 +94,37 @@ struct dce_clk_mgr { * This is basically "Crystal Frequency In KHz" (XTALIN) frequency */ int dfs_bypass_disp_clk; - /* Flag for Enabled SS on DPREFCLK */ + /** + * @ss_on_dprefclk: + * + * True if spread spectrum is enabled on the DP ref clock. + */ bool ss_on_dprefclk; - /* DPREFCLK SS percentage (if down-spread enabled) */ + + /** + * @xgmi_enabled: + * + * True if xGMI is enabled. On VG20, both audio and display clocks need + * to be adjusted with the WAFL link's SS info if xGMI is enabled. + */ + bool xgmi_enabled; + + /** + * @dprefclk_ss_percentage: + * + * DPREFCLK SS percentage (if down-spread enabled). + * + * Note that if XGMI is enabled, the SS info (percentage and divider) + * from the WAFL link is used instead. This is decided during + * dce_clk_mgr initialization. + */ int dprefclk_ss_percentage; - /* DPREFCLK SS percentage Divider (100 or 1000) */ + + /** + * @dprefclk_ss_divider: + * + * DPREFCLK SS percentage Divider (100 or 1000). + */ int dprefclk_ss_divider; int dprefclk_khz; @@ -163,6 +189,9 @@ struct clk_mgr *dce112_clk_mgr_create( struct clk_mgr *dce120_clk_mgr_create(struct dc_context *ctx); +struct clk_mgr *dce121_clk_mgr_create(struct dc_context *ctx); +void dce121_clock_patch_xgmi_ss_info(struct clk_mgr *clk_mgr); + void dce_clk_mgr_destroy(struct clk_mgr **clk_mgr); int dentist_get_divider_from_did(int did); diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c index 723ce80ed89c..c67e90e5c339 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c @@ -108,28 +108,28 @@ static const struct spread_spectrum_data *get_ss_data_entry( } /** -* Function: calculate_fb_and_fractional_fb_divider -* -* * DESCRIPTION: Calculates feedback and fractional feedback dividers values -* -*PARAMETERS: -* targetPixelClock Desired frequency in 10 KHz -* ref_divider Reference divider (already known) -* postDivider Post Divider (already known) -* feedback_divider_param Pointer where to store -* calculated feedback divider value -* fract_feedback_divider_param Pointer where to store -* calculated fract feedback divider value -* -*RETURNS: -* It fills the locations pointed by feedback_divider_param -* and fract_feedback_divider_param -* It returns - true if feedback divider not 0 -* - false should never happen) -*/ + * Function: calculate_fb_and_fractional_fb_divider + * + * * DESCRIPTION: Calculates feedback and fractional feedback dividers values + * + *PARAMETERS: + * targetPixelClock Desired frequency in 100 Hz + * ref_divider Reference divider (already known) + * postDivider Post Divider (already known) + * feedback_divider_param Pointer where to store + * calculated feedback divider value + * fract_feedback_divider_param Pointer where to store + * calculated fract feedback divider value + * + *RETURNS: + * It fills the locations pointed by feedback_divider_param + * and fract_feedback_divider_param + * It returns - true if feedback divider not 0 + * - false should never happen) + */ static bool calculate_fb_and_fractional_fb_divider( struct calc_pll_clock_source *calc_pll_cs, - uint32_t target_pix_clk_khz, + uint32_t target_pix_clk_100hz, uint32_t ref_divider, uint32_t post_divider, uint32_t *feedback_divider_param, @@ -138,11 +138,11 @@ static bool calculate_fb_and_fractional_fb_divider( uint64_t feedback_divider; feedback_divider = - (uint64_t)target_pix_clk_khz * ref_divider * post_divider; + (uint64_t)target_pix_clk_100hz * ref_divider * post_divider; feedback_divider *= 10; /* additional factor, since we divide by 10 afterwards */ feedback_divider *= (uint64_t)(calc_pll_cs->fract_fb_divider_factor); - feedback_divider = div_u64(feedback_divider, calc_pll_cs->ref_freq_khz); + feedback_divider = div_u64(feedback_divider, calc_pll_cs->ref_freq_khz * 10ull); /*Round to the number of precision * The following code replace the old code (ullfeedbackDivider + 5)/10 @@ -195,36 +195,36 @@ static bool calc_fb_divider_checking_tolerance( { uint32_t feedback_divider; uint32_t fract_feedback_divider; - uint32_t actual_calculated_clock_khz; + uint32_t actual_calculated_clock_100hz; uint32_t abs_err; - uint64_t actual_calc_clk_khz; + uint64_t actual_calc_clk_100hz; calculate_fb_and_fractional_fb_divider( calc_pll_cs, - pll_settings->adjusted_pix_clk, + pll_settings->adjusted_pix_clk_100hz, ref_divider, post_divider, &feedback_divider, &fract_feedback_divider); /*Actual calculated value*/ - actual_calc_clk_khz = (uint64_t)feedback_divider * + actual_calc_clk_100hz = (uint64_t)feedback_divider * calc_pll_cs->fract_fb_divider_factor + fract_feedback_divider; - actual_calc_clk_khz *= calc_pll_cs->ref_freq_khz; - actual_calc_clk_khz = - div_u64(actual_calc_clk_khz, + actual_calc_clk_100hz *= calc_pll_cs->ref_freq_khz * 10; + actual_calc_clk_100hz = + div_u64(actual_calc_clk_100hz, ref_divider * post_divider * calc_pll_cs->fract_fb_divider_factor); - actual_calculated_clock_khz = (uint32_t)(actual_calc_clk_khz); + actual_calculated_clock_100hz = (uint32_t)(actual_calc_clk_100hz); - abs_err = (actual_calculated_clock_khz > - pll_settings->adjusted_pix_clk) - ? actual_calculated_clock_khz - - pll_settings->adjusted_pix_clk - : pll_settings->adjusted_pix_clk - - actual_calculated_clock_khz; + abs_err = (actual_calculated_clock_100hz > + pll_settings->adjusted_pix_clk_100hz) + ? actual_calculated_clock_100hz - + pll_settings->adjusted_pix_clk_100hz + : pll_settings->adjusted_pix_clk_100hz - + actual_calculated_clock_100hz; if (abs_err <= tolerance) { /*found good values*/ @@ -233,10 +233,10 @@ static bool calc_fb_divider_checking_tolerance( pll_settings->feedback_divider = feedback_divider; pll_settings->fract_feedback_divider = fract_feedback_divider; pll_settings->pix_clk_post_divider = post_divider; - pll_settings->calculated_pix_clk = - actual_calculated_clock_khz; + pll_settings->calculated_pix_clk_100hz = + actual_calculated_clock_100hz; pll_settings->vco_freq = - actual_calculated_clock_khz * post_divider; + actual_calculated_clock_100hz * post_divider / 10; return true; } return false; @@ -257,8 +257,8 @@ static bool calc_pll_dividers_in_range( /* This is err_tolerance / 10000 = 0.0025 - acceptable error of 0.25% * This is errorTolerance / 10000 = 0.0001 - acceptable error of 0.01%*/ - tolerance = (pll_settings->adjusted_pix_clk * err_tolerance) / - 10000; + tolerance = (pll_settings->adjusted_pix_clk_100hz * err_tolerance) / + 100000; if (tolerance < CALC_PLL_CLK_SRC_ERR_TOLERANCE) tolerance = CALC_PLL_CLK_SRC_ERR_TOLERANCE; @@ -294,7 +294,7 @@ static uint32_t calculate_pixel_clock_pll_dividers( uint32_t min_ref_divider; uint32_t max_ref_divider; - if (pll_settings->adjusted_pix_clk == 0) { + if (pll_settings->adjusted_pix_clk_100hz == 0) { DC_LOG_ERROR( "%s Bad requested pixel clock", __func__); return MAX_PLL_CALC_ERROR; @@ -306,21 +306,21 @@ static uint32_t calculate_pixel_clock_pll_dividers( max_post_divider = pll_settings->pix_clk_post_divider; } else { min_post_divider = calc_pll_cs->min_pix_clock_pll_post_divider; - if (min_post_divider * pll_settings->adjusted_pix_clk < - calc_pll_cs->min_vco_khz) { - min_post_divider = calc_pll_cs->min_vco_khz / - pll_settings->adjusted_pix_clk; + if (min_post_divider * pll_settings->adjusted_pix_clk_100hz < + calc_pll_cs->min_vco_khz * 10) { + min_post_divider = calc_pll_cs->min_vco_khz * 10 / + pll_settings->adjusted_pix_clk_100hz; if ((min_post_divider * - pll_settings->adjusted_pix_clk) < - calc_pll_cs->min_vco_khz) + pll_settings->adjusted_pix_clk_100hz) < + calc_pll_cs->min_vco_khz * 10) min_post_divider++; } max_post_divider = calc_pll_cs->max_pix_clock_pll_post_divider; - if (max_post_divider * pll_settings->adjusted_pix_clk - > calc_pll_cs->max_vco_khz) - max_post_divider = calc_pll_cs->max_vco_khz / - pll_settings->adjusted_pix_clk; + if (max_post_divider * pll_settings->adjusted_pix_clk_100hz + > calc_pll_cs->max_vco_khz * 10) + max_post_divider = calc_pll_cs->max_vco_khz * 10 / + pll_settings->adjusted_pix_clk_100hz; } /* 2) Find Reference divider ranges @@ -392,47 +392,47 @@ static bool pll_adjust_pix_clk( struct pixel_clk_params *pix_clk_params, struct pll_settings *pll_settings) { - uint32_t actual_pix_clk_khz = 0; - uint32_t requested_clk_khz = 0; + uint32_t actual_pix_clk_100hz = 0; + uint32_t requested_clk_100hz = 0; struct bp_adjust_pixel_clock_parameters bp_adjust_pixel_clock_params = { 0 }; enum bp_result bp_result; switch (pix_clk_params->signal_type) { case SIGNAL_TYPE_HDMI_TYPE_A: { - requested_clk_khz = pix_clk_params->requested_pix_clk; + requested_clk_100hz = pix_clk_params->requested_pix_clk_100hz; if (pix_clk_params->pixel_encoding != PIXEL_ENCODING_YCBCR422) { switch (pix_clk_params->color_depth) { case COLOR_DEPTH_101010: - requested_clk_khz = (requested_clk_khz * 5) >> 2; + requested_clk_100hz = (requested_clk_100hz * 5) >> 2; break; /* x1.25*/ case COLOR_DEPTH_121212: - requested_clk_khz = (requested_clk_khz * 6) >> 2; + requested_clk_100hz = (requested_clk_100hz * 6) >> 2; break; /* x1.5*/ case COLOR_DEPTH_161616: - requested_clk_khz = requested_clk_khz * 2; + requested_clk_100hz = requested_clk_100hz * 2; break; /* x2.0*/ default: break; } } - actual_pix_clk_khz = requested_clk_khz; + actual_pix_clk_100hz = requested_clk_100hz; } break; case SIGNAL_TYPE_DISPLAY_PORT: case SIGNAL_TYPE_DISPLAY_PORT_MST: case SIGNAL_TYPE_EDP: - requested_clk_khz = pix_clk_params->requested_sym_clk; - actual_pix_clk_khz = pix_clk_params->requested_pix_clk; + requested_clk_100hz = pix_clk_params->requested_sym_clk * 10; + actual_pix_clk_100hz = pix_clk_params->requested_pix_clk_100hz; break; default: - requested_clk_khz = pix_clk_params->requested_pix_clk; - actual_pix_clk_khz = pix_clk_params->requested_pix_clk; + requested_clk_100hz = pix_clk_params->requested_pix_clk_100hz; + actual_pix_clk_100hz = pix_clk_params->requested_pix_clk_100hz; break; } - bp_adjust_pixel_clock_params.pixel_clock = requested_clk_khz; + bp_adjust_pixel_clock_params.pixel_clock = requested_clk_100hz / 10; bp_adjust_pixel_clock_params. encoder_object_id = pix_clk_params->encoder_object_id; bp_adjust_pixel_clock_params.signal_type = pix_clk_params->signal_type; @@ -441,9 +441,9 @@ static bool pll_adjust_pix_clk( bp_result = clk_src->bios->funcs->adjust_pixel_clock( clk_src->bios, &bp_adjust_pixel_clock_params); if (bp_result == BP_RESULT_OK) { - pll_settings->actual_pix_clk = actual_pix_clk_khz; - pll_settings->adjusted_pix_clk = - bp_adjust_pixel_clock_params.adjusted_pixel_clock; + pll_settings->actual_pix_clk_100hz = actual_pix_clk_100hz; + pll_settings->adjusted_pix_clk_100hz = + bp_adjust_pixel_clock_params.adjusted_pixel_clock * 10; pll_settings->reference_divider = bp_adjust_pixel_clock_params.reference_divider; pll_settings->pix_clk_post_divider = @@ -490,7 +490,7 @@ static uint32_t dce110_get_pix_clk_dividers_helper ( const struct spread_spectrum_data *ss_data = get_ss_data_entry( clk_src, pix_clk_params->signal_type, - pll_settings->adjusted_pix_clk); + pll_settings->adjusted_pix_clk_100hz / 10); if (NULL != ss_data) pll_settings->ss_percentage = ss_data->percentage; @@ -502,13 +502,13 @@ static uint32_t dce110_get_pix_clk_dividers_helper ( * to continue. */ DC_LOG_ERROR( "%s: Failed to adjust pixel clock!!", __func__); - pll_settings->actual_pix_clk = - pix_clk_params->requested_pix_clk; - pll_settings->adjusted_pix_clk = - pix_clk_params->requested_pix_clk; + pll_settings->actual_pix_clk_100hz = + pix_clk_params->requested_pix_clk_100hz; + pll_settings->adjusted_pix_clk_100hz = + pix_clk_params->requested_pix_clk_100hz; if (dc_is_dp_signal(pix_clk_params->signal_type)) - pll_settings->adjusted_pix_clk = 100000; + pll_settings->adjusted_pix_clk_100hz = 1000000; } /* Calculate Dividers */ @@ -533,28 +533,28 @@ static void dce112_get_pix_clk_dividers_helper ( struct pll_settings *pll_settings, struct pixel_clk_params *pix_clk_params) { - uint32_t actualPixelClockInKHz; + uint32_t actual_pixel_clock_100hz; - actualPixelClockInKHz = pix_clk_params->requested_pix_clk; + actual_pixel_clock_100hz = pix_clk_params->requested_pix_clk_100hz; /* Calculate Dividers */ if (pix_clk_params->signal_type == SIGNAL_TYPE_HDMI_TYPE_A) { switch (pix_clk_params->color_depth) { case COLOR_DEPTH_101010: - actualPixelClockInKHz = (actualPixelClockInKHz * 5) >> 2; + actual_pixel_clock_100hz = (actual_pixel_clock_100hz * 5) >> 2; break; case COLOR_DEPTH_121212: - actualPixelClockInKHz = (actualPixelClockInKHz * 6) >> 2; + actual_pixel_clock_100hz = (actual_pixel_clock_100hz * 6) >> 2; break; case COLOR_DEPTH_161616: - actualPixelClockInKHz = actualPixelClockInKHz * 2; + actual_pixel_clock_100hz = actual_pixel_clock_100hz * 2; break; default: break; } } - pll_settings->actual_pix_clk = actualPixelClockInKHz; - pll_settings->adjusted_pix_clk = actualPixelClockInKHz; - pll_settings->calculated_pix_clk = pix_clk_params->requested_pix_clk; + pll_settings->actual_pix_clk_100hz = actual_pixel_clock_100hz; + pll_settings->adjusted_pix_clk_100hz = actual_pixel_clock_100hz; + pll_settings->calculated_pix_clk_100hz = pix_clk_params->requested_pix_clk_100hz; } static uint32_t dce110_get_pix_clk_dividers( @@ -567,7 +567,7 @@ static uint32_t dce110_get_pix_clk_dividers( DC_LOGGER_INIT(); if (pix_clk_params == NULL || pll_settings == NULL - || pix_clk_params->requested_pix_clk == 0) { + || pix_clk_params->requested_pix_clk_100hz == 0) { DC_LOG_ERROR( "%s: Invalid parameters!!\n", __func__); return pll_calc_error; @@ -577,10 +577,10 @@ static uint32_t dce110_get_pix_clk_dividers( if (cs->id == CLOCK_SOURCE_ID_DP_DTO || cs->id == CLOCK_SOURCE_ID_EXTERNAL) { - pll_settings->adjusted_pix_clk = clk_src->ext_clk_khz; - pll_settings->calculated_pix_clk = clk_src->ext_clk_khz; - pll_settings->actual_pix_clk = - pix_clk_params->requested_pix_clk; + pll_settings->adjusted_pix_clk_100hz = clk_src->ext_clk_khz * 10; + pll_settings->calculated_pix_clk_100hz = clk_src->ext_clk_khz * 10; + pll_settings->actual_pix_clk_100hz = + pix_clk_params->requested_pix_clk_100hz; return 0; } @@ -599,7 +599,7 @@ static uint32_t dce112_get_pix_clk_dividers( DC_LOGGER_INIT(); if (pix_clk_params == NULL || pll_settings == NULL - || pix_clk_params->requested_pix_clk == 0) { + || pix_clk_params->requested_pix_clk_100hz == 0) { DC_LOG_ERROR( "%s: Invalid parameters!!\n", __func__); return -1; @@ -609,10 +609,10 @@ static uint32_t dce112_get_pix_clk_dividers( if (cs->id == CLOCK_SOURCE_ID_DP_DTO || cs->id == CLOCK_SOURCE_ID_EXTERNAL) { - pll_settings->adjusted_pix_clk = clk_src->ext_clk_khz; - pll_settings->calculated_pix_clk = clk_src->ext_clk_khz; - pll_settings->actual_pix_clk = - pix_clk_params->requested_pix_clk; + pll_settings->adjusted_pix_clk_100hz = clk_src->ext_clk_khz * 10; + pll_settings->calculated_pix_clk_100hz = clk_src->ext_clk_khz * 10; + pll_settings->actual_pix_clk_100hz = + pix_clk_params->requested_pix_clk_100hz; return -1; } @@ -714,7 +714,7 @@ static bool enable_spread_spectrum( ss_data = get_ss_data_entry( clk_src, signal, - pll_settings->calculated_pix_clk); + pll_settings->calculated_pix_clk_100hz / 10); /* Pixel clock PLL has been programmed to generate desired pixel clock, * now enable SS on pixel clock */ @@ -853,7 +853,7 @@ static bool dce110_program_pix_clk( /*ATOMBIOS expects pixel rate adjusted by deep color ratio)*/ bp_pc_params.controller_id = pix_clk_params->controller_id; bp_pc_params.pll_id = clock_source->id; - bp_pc_params.target_pixel_clock = pll_settings->actual_pix_clk; + bp_pc_params.target_pixel_clock_100hz = pll_settings->actual_pix_clk_100hz; bp_pc_params.encoder_object_id = pix_clk_params->encoder_object_id; bp_pc_params.signal_type = pix_clk_params->signal_type; @@ -903,12 +903,12 @@ static bool dce112_program_pix_clk( #if defined(CONFIG_DRM_AMD_DC_DCN1_0) if (IS_FPGA_MAXIMUS_DC(clock_source->ctx->dce_environment)) { unsigned int inst = pix_clk_params->controller_id - CONTROLLER_ID_D0; - unsigned dp_dto_ref_kHz = 700000; - unsigned clock_kHz = pll_settings->actual_pix_clk; + unsigned dp_dto_ref_100hz = 7000000; + unsigned clock_100hz = pll_settings->actual_pix_clk_100hz; /* Set DTO values: phase = target clock, modulo = reference clock */ - REG_WRITE(PHASE[inst], clock_kHz); - REG_WRITE(MODULO[inst], dp_dto_ref_kHz); + REG_WRITE(PHASE[inst], clock_100hz); + REG_WRITE(MODULO[inst], dp_dto_ref_100hz); /* Enable DTO */ REG_UPDATE(PIXEL_RATE_CNTL[inst], DP_DTO0_ENABLE, 1); @@ -927,7 +927,7 @@ static bool dce112_program_pix_clk( /*ATOMBIOS expects pixel rate adjusted by deep color ratio)*/ bp_pc_params.controller_id = pix_clk_params->controller_id; bp_pc_params.pll_id = clock_source->id; - bp_pc_params.target_pixel_clock = pll_settings->actual_pix_clk; + bp_pc_params.target_pixel_clock_100hz = pll_settings->actual_pix_clk_100hz; bp_pc_params.encoder_object_id = pix_clk_params->encoder_object_id; bp_pc_params.signal_type = pix_clk_params->signal_type; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c index dea40b322191..c2926cf19dee 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c @@ -51,7 +51,6 @@ #define PSR_SET_WAITLOOP 0x31 #define MCP_INIT_DMCU 0x88 #define MCP_INIT_IRAM 0x89 -#define MCP_DMCU_VERSION 0x90 #define MASTER_COMM_CNTL_REG__MASTER_COMM_INTERRUPT_MASK 0x00000001L static bool dce_dmcu_init(struct dmcu *dmcu) @@ -317,38 +316,11 @@ static void dce_get_psr_wait_loop( } #if defined(CONFIG_DRM_AMD_DC_DCN1_0) -static void dcn10_get_dmcu_state(struct dmcu *dmcu) -{ - struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu); - uint32_t dmcu_state_offset = 0xf6; - - /* Enable write access to IRAM */ - REG_UPDATE_2(DMCU_RAM_ACCESS_CTRL, - IRAM_HOST_ACCESS_EN, 1, - IRAM_RD_ADDR_AUTO_INC, 1); - - REG_WAIT(DMU_MEM_PWR_CNTL, DMCU_IRAM_MEM_PWR_STATE, 0, 2, 10); - - /* Write address to IRAM_RD_ADDR in DMCU_IRAM_RD_CTRL */ - REG_WRITE(DMCU_IRAM_RD_CTRL, dmcu_state_offset); - - /* Read data from IRAM_RD_DATA in DMCU_IRAM_RD_DATA*/ - dmcu->dmcu_state = REG_READ(DMCU_IRAM_RD_DATA); - - /* Disable write access to IRAM to allow dynamic sleep state */ - REG_UPDATE_2(DMCU_RAM_ACCESS_CTRL, - IRAM_HOST_ACCESS_EN, 0, - IRAM_RD_ADDR_AUTO_INC, 0); -} - static void dcn10_get_dmcu_version(struct dmcu *dmcu) { struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu); uint32_t dmcu_version_offset = 0xf1; - /* Clear scratch */ - REG_WRITE(DC_DMCU_SCRATCH, 0); - /* Enable write access to IRAM */ REG_UPDATE_2(DMCU_RAM_ACCESS_CTRL, IRAM_HOST_ACCESS_EN, 1, @@ -359,85 +331,74 @@ static void dcn10_get_dmcu_version(struct dmcu *dmcu) /* Write address to IRAM_RD_ADDR and read from DATA register */ REG_WRITE(DMCU_IRAM_RD_CTRL, dmcu_version_offset); dmcu->dmcu_version.interface_version = REG_READ(DMCU_IRAM_RD_DATA); - dmcu->dmcu_version.year = ((REG_READ(DMCU_IRAM_RD_DATA) << 8) | + dmcu->dmcu_version.abm_version = REG_READ(DMCU_IRAM_RD_DATA); + dmcu->dmcu_version.psr_version = REG_READ(DMCU_IRAM_RD_DATA); + dmcu->dmcu_version.build_version = ((REG_READ(DMCU_IRAM_RD_DATA) << 8) | REG_READ(DMCU_IRAM_RD_DATA)); - dmcu->dmcu_version.month = REG_READ(DMCU_IRAM_RD_DATA); - dmcu->dmcu_version.date = REG_READ(DMCU_IRAM_RD_DATA); /* Disable write access to IRAM to allow dynamic sleep state */ REG_UPDATE_2(DMCU_RAM_ACCESS_CTRL, IRAM_HOST_ACCESS_EN, 0, IRAM_RD_ADDR_AUTO_INC, 0); - - /* Send MCP command message to DMCU to get version reply from FW. - * We expect this version should match the one in IRAM, otherwise - * something is wrong with DMCU and we should fail and disable UC. - */ - REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, 100, 800); - - /* Set command to get DMCU version from microcontroller */ - REG_UPDATE(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, - MCP_DMCU_VERSION); - - /* Notify microcontroller of new command */ - REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); - - /* Ensure command has been executed before continuing */ - REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, 100, 800); - - /* Somehow version does not match, so fail and return version 0 */ - if (dmcu->dmcu_version.interface_version != REG_READ(DC_DMCU_SCRATCH)) - dmcu->dmcu_version.interface_version = 0; } static bool dcn10_dmcu_init(struct dmcu *dmcu) { struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu); + bool status = false; - /* DMCU FW should populate the scratch register if running */ - if (REG_READ(DC_DMCU_SCRATCH) == 0) - return false; - - /* Check state is uninitialized */ - dcn10_get_dmcu_state(dmcu); - - /* If microcontroller is already initialized, do nothing */ - if (dmcu->dmcu_state == DMCU_RUNNING) - return true; - - /* Retrieve and cache the DMCU firmware version. */ - dcn10_get_dmcu_version(dmcu); - - /* Check interface version to confirm firmware is loaded and running */ - if (dmcu->dmcu_version.interface_version == 0) - return false; + /* Definition of DC_DMCU_SCRATCH + * 0 : firmare not loaded + * 1 : PSP load DMCU FW but not initialized + * 2 : Firmware already initialized + */ + dmcu->dmcu_state = REG_READ(DC_DMCU_SCRATCH); - /* Wait until microcontroller is ready to process interrupt */ - REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, 100, 800); + switch (dmcu->dmcu_state) { + case DMCU_UNLOADED: + status = false; + break; + case DMCU_LOADED_UNINITIALIZED: + /* Wait until microcontroller is ready to process interrupt */ + REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, 100, 800); - /* Set initialized ramping boundary value */ - REG_WRITE(MASTER_COMM_DATA_REG1, 0xFFFF); + /* Set initialized ramping boundary value */ + REG_WRITE(MASTER_COMM_DATA_REG1, 0xFFFF); - /* Set command to initialize microcontroller */ - REG_UPDATE(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, + /* Set command to initialize microcontroller */ + REG_UPDATE(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, MCP_INIT_DMCU); - /* Notify microcontroller of new command */ - REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); + /* Notify microcontroller of new command */ + REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); - /* Ensure command has been executed before continuing */ - REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, 100, 800); + /* Ensure command has been executed before continuing */ + REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, 100, 800); - // Check state is initialized - dcn10_get_dmcu_state(dmcu); + // Check state is initialized + dmcu->dmcu_state = REG_READ(DC_DMCU_SCRATCH); - // If microcontroller is not in running state, fail - if (dmcu->dmcu_state != DMCU_RUNNING) - return false; + // If microcontroller is not in running state, fail + if (dmcu->dmcu_state == DMCU_RUNNING) { + /* Retrieve and cache the DMCU firmware version. */ + dcn10_get_dmcu_version(dmcu); + status = true; + } else + status = false; - return true; + break; + case DMCU_RUNNING: + status = true; + break; + default: + status = false; + break; + } + + return status; } + static bool dcn10_dmcu_load_iram(struct dmcu *dmcu, unsigned int start_offset, const char *src, diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h index c83a7f05f14c..956bdf14503f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h @@ -133,6 +133,10 @@ SR(DCHUB_AGP_TOP), \ BL_REG_LIST() +#define HWSEQ_VG20_REG_LIST() \ + HWSEQ_DCE120_REG_LIST(),\ + MMHUB_SR(MC_VM_XGMI_LFB_CNTL) + #define HWSEQ_DCE112_REG_LIST() \ HWSEQ_DCE10_REG_LIST(), \ HWSEQ_PIXEL_RATE_REG_LIST(CRTC), \ @@ -298,6 +302,7 @@ struct dce_hwseq_registers { uint32_t MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB; uint32_t MC_VM_SYSTEM_APERTURE_LOW_ADDR; uint32_t MC_VM_SYSTEM_APERTURE_HIGH_ADDR; + uint32_t MC_VM_XGMI_LFB_CNTL; uint32_t AZALIA_AUDIO_DTO; uint32_t AZALIA_CONTROLLER_CLOCK_GATING; }; @@ -382,6 +387,11 @@ struct dce_hwseq_registers { HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh), \ HWS_SF(, LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, mask_sh) +#define HWSEQ_VG20_MASK_SH_LIST(mask_sh)\ + HWSEQ_DCE12_MASK_SH_LIST(mask_sh),\ + HWS_SF(, MC_VM_XGMI_LFB_CNTL, PF_LFB_REGION, mask_sh),\ + HWS_SF(, MC_VM_XGMI_LFB_CNTL, PF_MAX_REGION, mask_sh) + #define HWSEQ_DCN_MASK_SH_LIST(mask_sh)\ HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, OTG0_),\ HWS_SF1(OTG0_, PHYPLL_PIXEL_RATE_CNTL, PHYPLL_PIXEL_RATE_SOURCE, mask_sh), \ @@ -470,6 +480,8 @@ struct dce_hwseq_registers { type PHYSICAL_PAGE_NUMBER_MSB;\ type PHYSICAL_PAGE_NUMBER_LSB;\ type LOGICAL_ADDR; \ + type PF_LFB_REGION;\ + type PF_MAX_REGION;\ type ENABLE_L1_TLB;\ type SYSTEM_ACCESS_MODE;\ type LVTMA_BLON;\ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index 3e18ea84b1f9..314c04a915d2 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -599,12 +599,12 @@ bool dce110_link_encoder_validate_dvi_output( if ((connector_signal == SIGNAL_TYPE_DVI_SINGLE_LINK || connector_signal == SIGNAL_TYPE_HDMI_TYPE_A) && signal != SIGNAL_TYPE_HDMI_TYPE_A && - crtc_timing->pix_clk_khz > TMDS_MAX_PIXEL_CLOCK) + crtc_timing->pix_clk_100hz > (TMDS_MAX_PIXEL_CLOCK * 10)) return false; - if (crtc_timing->pix_clk_khz < TMDS_MIN_PIXEL_CLOCK) + if (crtc_timing->pix_clk_100hz < (TMDS_MIN_PIXEL_CLOCK * 10)) return false; - if (crtc_timing->pix_clk_khz > max_pixel_clock) + if (crtc_timing->pix_clk_100hz > (max_pixel_clock * 10)) return false; /* DVI supports 6/8bpp single-link and 10/16bpp dual-link */ @@ -788,7 +788,7 @@ bool dce110_link_encoder_validate_output_with_stream( case SIGNAL_TYPE_DVI_DUAL_LINK: is_valid = dce110_link_encoder_validate_dvi_output( enc110, - stream->sink->link->connector_signal, + stream->link->connector_signal, stream->signal, &stream->timing); break; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c index cce0d18f91da..1fa2d4fd7a35 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c @@ -288,9 +288,18 @@ static void dce110_stream_encoder_dp_set_stream_attribute( #endif struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc); - + struct dc_crtc_timing hw_crtc_timing = *crtc_timing; + if (hw_crtc_timing.flags.INTERLACE) { + /*the input timing is in VESA spec format with Interlace flag =1*/ + hw_crtc_timing.v_total /= 2; + hw_crtc_timing.v_border_top /= 2; + hw_crtc_timing.v_addressable /= 2; + hw_crtc_timing.v_border_bottom /= 2; + hw_crtc_timing.v_front_porch /= 2; + hw_crtc_timing.v_sync_width /= 2; + } /* set pixel encoding */ - switch (crtc_timing->pixel_encoding) { + switch (hw_crtc_timing.pixel_encoding) { case PIXEL_ENCODING_YCBCR422: REG_UPDATE(DP_PIXEL_FORMAT, DP_PIXEL_ENCODING, DP_PIXEL_ENCODING_TYPE_YCBCR422); @@ -299,8 +308,8 @@ static void dce110_stream_encoder_dp_set_stream_attribute( REG_UPDATE(DP_PIXEL_FORMAT, DP_PIXEL_ENCODING, DP_PIXEL_ENCODING_TYPE_YCBCR444); - if (crtc_timing->flags.Y_ONLY) - if (crtc_timing->display_color_depth != COLOR_DEPTH_666) + if (hw_crtc_timing.flags.Y_ONLY) + if (hw_crtc_timing.display_color_depth != COLOR_DEPTH_666) /* HW testing only, no use case yet. * Color depth of Y-only could be * 8, 10, 12, 16 bits */ @@ -335,7 +344,7 @@ static void dce110_stream_encoder_dp_set_stream_attribute( /* set color depth */ - switch (crtc_timing->display_color_depth) { + switch (hw_crtc_timing.display_color_depth) { case COLOR_DEPTH_666: REG_UPDATE(DP_PIXEL_FORMAT, DP_COMPONENT_DEPTH, 0); @@ -363,7 +372,7 @@ static void dce110_stream_encoder_dp_set_stream_attribute( #if defined(CONFIG_DRM_AMD_DC_DCN1_0) - switch (crtc_timing->display_color_depth) { + switch (hw_crtc_timing.display_color_depth) { case COLOR_DEPTH_666: colorimetry_bpc = 0; break; @@ -401,9 +410,9 @@ static void dce110_stream_encoder_dp_set_stream_attribute( misc0 = misc0 | 0x8; /* bit3=1, bit4=0 */ misc1 = misc1 & ~0x80; /* bit7 = 0*/ dynamic_range_ycbcr = 0; /*bt601*/ - if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) + if (hw_crtc_timing.pixel_encoding == PIXEL_ENCODING_YCBCR422) misc0 = misc0 | 0x2; /* bit2=0, bit1=1 */ - else if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR444) + else if (hw_crtc_timing.pixel_encoding == PIXEL_ENCODING_YCBCR444) misc0 = misc0 | 0x4; /* bit2=1, bit1=0 */ break; case COLOR_SPACE_YCBCR709: @@ -411,9 +420,9 @@ static void dce110_stream_encoder_dp_set_stream_attribute( misc0 = misc0 | 0x18; /* bit3=1, bit4=1 */ misc1 = misc1 & ~0x80; /* bit7 = 0*/ dynamic_range_ycbcr = 1; /*bt709*/ - if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) + if (hw_crtc_timing.pixel_encoding == PIXEL_ENCODING_YCBCR422) misc0 = misc0 | 0x2; /* bit2=0, bit1=1 */ - else if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR444) + else if (hw_crtc_timing.pixel_encoding == PIXEL_ENCODING_YCBCR444) misc0 = misc0 | 0x4; /* bit2=1, bit1=0 */ break; case COLOR_SPACE_2020_RGB_LIMITEDRANGE: @@ -453,27 +462,27 @@ static void dce110_stream_encoder_dp_set_stream_attribute( */ if (REG(DP_MSA_TIMING_PARAM1)) REG_SET_2(DP_MSA_TIMING_PARAM1, 0, - DP_MSA_HTOTAL, crtc_timing->h_total, - DP_MSA_VTOTAL, crtc_timing->v_total); + DP_MSA_HTOTAL, hw_crtc_timing.h_total, + DP_MSA_VTOTAL, hw_crtc_timing.v_total); #endif /* calcuate from vesa timing parameters * h_active_start related to leading edge of sync */ - h_blank = crtc_timing->h_total - crtc_timing->h_border_left - - crtc_timing->h_addressable - crtc_timing->h_border_right; + h_blank = hw_crtc_timing.h_total - hw_crtc_timing.h_border_left - + hw_crtc_timing.h_addressable - hw_crtc_timing.h_border_right; - h_back_porch = h_blank - crtc_timing->h_front_porch - - crtc_timing->h_sync_width; + h_back_porch = h_blank - hw_crtc_timing.h_front_porch - + hw_crtc_timing.h_sync_width; /* start at begining of left border */ - h_active_start = crtc_timing->h_sync_width + h_back_porch; + h_active_start = hw_crtc_timing.h_sync_width + h_back_porch; - v_active_start = crtc_timing->v_total - crtc_timing->v_border_top - - crtc_timing->v_addressable - crtc_timing->v_border_bottom - - crtc_timing->v_front_porch; + v_active_start = hw_crtc_timing.v_total - hw_crtc_timing.v_border_top - + hw_crtc_timing.v_addressable - hw_crtc_timing.v_border_bottom - + hw_crtc_timing.v_front_porch; #if defined(CONFIG_DRM_AMD_DC_DCN1_0) @@ -486,21 +495,21 @@ static void dce110_stream_encoder_dp_set_stream_attribute( if (REG(DP_MSA_TIMING_PARAM3)) REG_SET_4(DP_MSA_TIMING_PARAM3, 0, DP_MSA_HSYNCWIDTH, - crtc_timing->h_sync_width, + hw_crtc_timing.h_sync_width, DP_MSA_HSYNCPOLARITY, - !crtc_timing->flags.HSYNC_POSITIVE_POLARITY, + !hw_crtc_timing.flags.HSYNC_POSITIVE_POLARITY, DP_MSA_VSYNCWIDTH, - crtc_timing->v_sync_width, + hw_crtc_timing.v_sync_width, DP_MSA_VSYNCPOLARITY, - !crtc_timing->flags.VSYNC_POSITIVE_POLARITY); + !hw_crtc_timing.flags.VSYNC_POSITIVE_POLARITY); /* HWDITH include border or overscan */ if (REG(DP_MSA_TIMING_PARAM4)) REG_SET_2(DP_MSA_TIMING_PARAM4, 0, - DP_MSA_HWIDTH, crtc_timing->h_border_left + - crtc_timing->h_addressable + crtc_timing->h_border_right, - DP_MSA_VHEIGHT, crtc_timing->v_border_top + - crtc_timing->v_addressable + crtc_timing->v_border_bottom); + DP_MSA_HWIDTH, hw_crtc_timing.h_border_left + + hw_crtc_timing.h_addressable + hw_crtc_timing.h_border_right, + DP_MSA_VHEIGHT, hw_crtc_timing.v_border_top + + hw_crtc_timing.v_addressable + hw_crtc_timing.v_border_bottom); #endif } #endif @@ -662,7 +671,7 @@ static void dce110_stream_encoder_dvi_set_stream_attribute( cntl.signal = is_dual_link ? SIGNAL_TYPE_DVI_DUAL_LINK : SIGNAL_TYPE_DVI_SINGLE_LINK; cntl.enable_dp_audio = false; - cntl.pixel_clock = crtc_timing->pix_clk_khz; + cntl.pixel_clock = crtc_timing->pix_clk_100hz / 10; cntl.lanes_number = (is_dual_link) ? LANE_COUNT_EIGHT : LANE_COUNT_FOUR; if (enc110->base.bp->funcs->encoder_control( @@ -686,7 +695,7 @@ static void dce110_stream_encoder_lvds_set_stream_attribute( cntl.engine_id = enc110->base.id; cntl.signal = SIGNAL_TYPE_LVDS; cntl.enable_dp_audio = false; - cntl.pixel_clock = crtc_timing->pix_clk_khz; + cntl.pixel_clock = crtc_timing->pix_clk_100hz / 10; cntl.lanes_number = LANE_COUNT_FOUR; if (enc110->base.bp->funcs->encoder_control( @@ -1575,6 +1584,14 @@ static void setup_stereo_sync( REG_UPDATE(DIG_FE_CNTL, DIG_STEREOSYNC_GATE_EN, !enable); } +static void dig_connect_to_otg( + struct stream_encoder *enc, + int tg_inst) +{ + struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc); + + REG_UPDATE(DIG_FE_CNTL, DIG_SOURCE_SELECT, tg_inst); +} static const struct stream_encoder_funcs dce110_str_enc_funcs = { .dp_set_stream_attribute = @@ -1609,7 +1626,7 @@ static const struct stream_encoder_funcs dce110_str_enc_funcs = { .hdmi_audio_disable = dce110_se_hdmi_audio_disable, .setup_stereo_sync = setup_stereo_sync, .set_avmute = dce110_stream_encoder_set_avmute, - + .dig_connect_to_otg = dig_connect_to_otg, }; void dce110_stream_encoder_construct( diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.h index 6c28229c76eb..f9cdf2b5242c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.h @@ -199,7 +199,8 @@ SE_SF(DP_SEC_CNTL, DP_SEC_ATP_ENABLE, mask_sh),\ SE_SF(DP_SEC_CNTL, DP_SEC_AIP_ENABLE, mask_sh),\ SE_SF(DP_SEC_CNTL, DP_SEC_ACM_ENABLE, mask_sh),\ - SE_SF(AFMT_AUDIO_PACKET_CONTROL, AFMT_AUDIO_SAMPLE_SEND, mask_sh) + SE_SF(AFMT_AUDIO_PACKET_CONTROL, AFMT_AUDIO_SAMPLE_SEND, mask_sh),\ + SE_SF(DIG_FE_CNTL, DIG_SOURCE_SELECT, mask_sh) #define SE_COMMON_MASK_SH_LIST_DCE_COMMON(mask_sh)\ SE_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh) @@ -284,7 +285,8 @@ SE_SF(DIG0_DIG_FE_CNTL, TMDS_PIXEL_ENCODING, mask_sh),\ SE_SF(DIG0_DIG_FE_CNTL, TMDS_COLOR_FORMAT, mask_sh),\ SE_SF(DIG0_DIG_FE_CNTL, DIG_STEREOSYNC_SELECT, mask_sh),\ - SE_SF(DIG0_DIG_FE_CNTL, DIG_STEREOSYNC_GATE_EN, mask_sh) + SE_SF(DIG0_DIG_FE_CNTL, DIG_STEREOSYNC_GATE_EN, mask_sh),\ + SE_SF(DIG0_DIG_FE_CNTL, DIG_SOURCE_SELECT, mask_sh) #define SE_COMMON_MASK_SH_LIST_SOC(mask_sh)\ SE_COMMON_MASK_SH_LIST_SOC_BASE(mask_sh) @@ -494,6 +496,7 @@ struct dce_stream_encoder_shift { uint8_t HDMI_DB_DISABLE; uint8_t DP_VID_N_MUL; uint8_t DP_VID_M_DOUBLE_VALUE_EN; + uint8_t DIG_SOURCE_SELECT; }; struct dce_stream_encoder_mask { @@ -624,6 +627,7 @@ struct dce_stream_encoder_mask { uint32_t HDMI_DB_DISABLE; uint32_t DP_VID_N_MUL; uint32_t DP_VID_M_DOUBLE_VALUE_EN; + uint32_t DIG_SOURCE_SELECT; }; struct dce110_stream_enc_registers { diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index 6ae51a5dfc04..23044e6723e8 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -76,6 +76,7 @@ #ifndef mmBIOS_SCRATCH_2 #define mmBIOS_SCRATCH_2 0x05CB + #define mmBIOS_SCRATCH_3 0x05CC #define mmBIOS_SCRATCH_6 0x05CF #endif @@ -365,6 +366,7 @@ static const struct dce_abm_mask abm_mask = { #define DCFE_MEM_PWR_CTRL_REG_BASE 0x1b03 static const struct bios_registers bios_regs = { + .BIOS_SCRATCH_3 = mmBIOS_SCRATCH_3, .BIOS_SCRATCH_6 = mmBIOS_SCRATCH_6 }; @@ -587,7 +589,7 @@ struct output_pixel_processor *dce100_opp_create( return &opp->base; } -struct aux_engine *dce100_aux_engine_create( +struct dce_aux *dce100_aux_engine_create( struct dc_context *ctx, uint32_t inst) { diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c index 52d50e24a995..7b23239d33fe 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c @@ -62,8 +62,6 @@ static const struct dce110_compressor_reg_offsets reg_offsets[] = { } }; -static const uint32_t dce11_one_lpt_channel_max_resolution = 2560 * 1600; - static uint32_t align_to_chunks_number_per_line(uint32_t pixels) { return 256 * ((pixels + 255) / 256); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 4bf24758217f..db0ef41eb91c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -614,55 +614,6 @@ dce110_set_output_transfer_func(struct pipe_ctx *pipe_ctx, return true; } -static enum dc_status bios_parser_crtc_source_select( - struct pipe_ctx *pipe_ctx) -{ - struct dc_bios *dcb; - /* call VBIOS table to set CRTC source for the HW - * encoder block - * note: video bios clears all FMT setting here. */ - struct bp_crtc_source_select crtc_source_select = {0}; - const struct dc_sink *sink = pipe_ctx->stream->sink; - - crtc_source_select.engine_id = pipe_ctx->stream_res.stream_enc->id; - crtc_source_select.controller_id = pipe_ctx->stream_res.tg->inst + 1; - /*TODO: Need to un-hardcode color depth, dp_audio and account for - * the case where signal and sink signal is different (translator - * encoder)*/ - crtc_source_select.signal = pipe_ctx->stream->signal; - crtc_source_select.enable_dp_audio = false; - crtc_source_select.sink_signal = pipe_ctx->stream->signal; - - switch (pipe_ctx->stream->timing.display_color_depth) { - case COLOR_DEPTH_666: - crtc_source_select.display_output_bit_depth = PANEL_6BIT_COLOR; - break; - case COLOR_DEPTH_888: - crtc_source_select.display_output_bit_depth = PANEL_8BIT_COLOR; - break; - case COLOR_DEPTH_101010: - crtc_source_select.display_output_bit_depth = PANEL_10BIT_COLOR; - break; - case COLOR_DEPTH_121212: - crtc_source_select.display_output_bit_depth = PANEL_12BIT_COLOR; - break; - default: - BREAK_TO_DEBUGGER(); - crtc_source_select.display_output_bit_depth = PANEL_8BIT_COLOR; - break; - } - - dcb = sink->ctx->dc_bios; - - if (BP_RESULT_OK != dcb->funcs->crtc_source_select( - dcb, - &crtc_source_select)) { - return DC_ERROR_UNEXPECTED; - } - - return DC_OK; -} - void dce110_update_info_frame(struct pipe_ctx *pipe_ctx) { bool is_hdmi; @@ -692,10 +643,10 @@ void dce110_update_info_frame(struct pipe_ctx *pipe_ctx) void dce110_enable_stream(struct pipe_ctx *pipe_ctx) { enum dc_lane_count lane_count = - pipe_ctx->stream->sink->link->cur_link_settings.lane_count; + pipe_ctx->stream->link->cur_link_settings.lane_count; struct dc_crtc_timing *timing = &pipe_ctx->stream->timing; - struct dc_link *link = pipe_ctx->stream->sink->link; + struct dc_link *link = pipe_ctx->stream->link; uint32_t active_total_with_borders; @@ -1000,7 +951,7 @@ void dce110_enable_audio_stream(struct pipe_ctx *pipe_ctx) pipe_ctx->stream_res.audio->funcs->az_enable(pipe_ctx->stream_res.audio); - if (num_audio == 1 && pp_smu != NULL && pp_smu->set_pme_wa_enable != NULL) + if (num_audio >= 1 && pp_smu != NULL && pp_smu->set_pme_wa_enable != NULL) /*this is the first audio. apply the PME w/a in order to wake AZ from D3*/ pp_smu->set_pme_wa_enable(&pp_smu->pp_smu); /* un-mute audio */ @@ -1017,6 +968,8 @@ void dce110_disable_audio_stream(struct pipe_ctx *pipe_ctx, int option) pipe_ctx->stream_res.stream_enc->funcs->audio_mute_control( pipe_ctx->stream_res.stream_enc, true); if (pipe_ctx->stream_res.audio) { + struct pp_smu_funcs_rv *pp_smu = dc->res_pool->pp_smu; + if (option != KEEP_ACQUIRED_RESOURCE || !dc->debug.az_endpoint_mute_only) { /*only disalbe az_endpoint if power down or free*/ @@ -1036,6 +989,9 @@ void dce110_disable_audio_stream(struct pipe_ctx *pipe_ctx, int option) update_audio_usage(&dc->current_state->res_ctx, dc->res_pool, pipe_ctx->stream_res.audio, false); pipe_ctx->stream_res.audio = NULL; } + if (pp_smu != NULL && pp_smu->set_pme_wa_enable != NULL) + /*this is the first audio. apply the PME w/a in order to wake AZ from D3*/ + pp_smu->set_pme_wa_enable(&pp_smu->pp_smu); /* TODO: notify audio driver for if audio modes list changed * add audio mode list change flag */ @@ -1048,7 +1004,7 @@ void dce110_disable_audio_stream(struct pipe_ctx *pipe_ctx, int option) void dce110_disable_stream(struct pipe_ctx *pipe_ctx, int option) { struct dc_stream_state *stream = pipe_ctx->stream; - struct dc_link *link = stream->sink->link; + struct dc_link *link = stream->link; struct dc *dc = pipe_ctx->stream->ctx->dc; if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) @@ -1073,11 +1029,11 @@ void dce110_unblank_stream(struct pipe_ctx *pipe_ctx, { struct encoder_unblank_param params = { { 0 } }; struct dc_stream_state *stream = pipe_ctx->stream; - struct dc_link *link = stream->sink->link; + struct dc_link *link = stream->link; /* only 3 items below are used by unblank */ params.pixel_clk_khz = - pipe_ctx->stream->timing.pix_clk_khz; + pipe_ctx->stream->timing.pix_clk_100hz / 10; params.link_settings.link_rate = link_settings->link_rate; if (dc_is_dp_signal(pipe_ctx->stream->signal)) @@ -1090,7 +1046,7 @@ void dce110_unblank_stream(struct pipe_ctx *pipe_ctx, void dce110_blank_stream(struct pipe_ctx *pipe_ctx) { struct dc_stream_state *stream = pipe_ctx->stream; - struct dc_link *link = stream->sink->link; + struct dc_link *link = stream->link; if (link->local_sink && link->local_sink->sink_signal == SIGNAL_TYPE_EDP) { link->dc->hwss.edp_backlight_control(link, false); @@ -1163,27 +1119,27 @@ static void build_audio_output( stream->timing.flags.INTERLACE; audio_output->crtc_info.refresh_rate = - (stream->timing.pix_clk_khz*1000)/ + (stream->timing.pix_clk_100hz*10000)/ (stream->timing.h_total*stream->timing.v_total); audio_output->crtc_info.color_depth = stream->timing.display_color_depth; audio_output->crtc_info.requested_pixel_clock = - pipe_ctx->stream_res.pix_clk_params.requested_pix_clk; + pipe_ctx->stream_res.pix_clk_params.requested_pix_clk_100hz / 10; audio_output->crtc_info.calculated_pixel_clock = - pipe_ctx->stream_res.pix_clk_params.requested_pix_clk; + pipe_ctx->stream_res.pix_clk_params.requested_pix_clk_100hz / 10; /*for HDMI, audio ACR is with deep color ratio factor*/ if (dc_is_hdmi_signal(pipe_ctx->stream->signal) && audio_output->crtc_info.requested_pixel_clock == - stream->timing.pix_clk_khz) { + (stream->timing.pix_clk_100hz / 10)) { if (pipe_ctx->stream_res.pix_clk_params.pixel_encoding == PIXEL_ENCODING_YCBCR420) { audio_output->crtc_info.requested_pixel_clock = audio_output->crtc_info.requested_pixel_clock/2; audio_output->crtc_info.calculated_pixel_clock = - pipe_ctx->stream_res.pix_clk_params.requested_pix_clk/2; + pipe_ctx->stream_res.pix_clk_params.requested_pix_clk_100hz/20; } } @@ -1385,12 +1341,10 @@ static enum dc_status apply_single_controller_ctx_to_hw( /* */ dc->hwss.enable_stream_timing(pipe_ctx, context, dc); - /* TODO: move to stream encoder */ if (pipe_ctx->stream->signal != SIGNAL_TYPE_VIRTUAL) - if (DC_OK != bios_parser_crtc_source_select(pipe_ctx)) { - BREAK_TO_DEBUGGER(); - return DC_ERROR_UNEXPECTED; - } + pipe_ctx->stream_res.stream_enc->funcs->dig_connect_to_otg( + pipe_ctx->stream_res.stream_enc, + pipe_ctx->stream_res.tg->inst); pipe_ctx->stream_res.opp->funcs->opp_set_dyn_expansion( pipe_ctx->stream_res.opp, @@ -1408,7 +1362,7 @@ static enum dc_status apply_single_controller_ctx_to_hw( pipe_ctx->plane_res.scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0; - pipe_ctx->stream->sink->link->psr_enabled = false; + pipe_ctx->stream->link->psr_enabled = false; return DC_OK; } @@ -1518,7 +1472,7 @@ static struct dc_link *get_link_for_edp(struct dc *dc) return NULL; } -static struct dc_link *get_link_for_edp_not_in_use( +static struct dc_link *get_link_for_edp_to_turn_off( struct dc *dc, struct dc_state *context) { @@ -1527,8 +1481,12 @@ static struct dc_link *get_link_for_edp_not_in_use( /* check if eDP panel is suppose to be set mode, if yes, no need to disable */ for (i = 0; i < context->stream_count; i++) { - if (context->streams[i]->signal == SIGNAL_TYPE_EDP) - return NULL; + if (context->streams[i]->signal == SIGNAL_TYPE_EDP) { + if (context->streams[i]->dpms_off == true) + return context->streams[i]->sink->link; + else + return NULL; + } } /* check if there is an eDP panel not in use */ @@ -1555,7 +1513,6 @@ void dce110_enable_accelerated_mode(struct dc *dc, struct dc_state *context) int i; struct dc_link *edp_link_to_turnoff = NULL; struct dc_link *edp_link = get_link_for_edp(dc); - struct dc_bios *bios = dc->ctx->dc_bios; bool can_edp_fast_boot_optimize = false; bool apply_edp_fast_boot_optimization = false; @@ -1571,7 +1528,7 @@ void dce110_enable_accelerated_mode(struct dc *dc, struct dc_state *context) } if (can_edp_fast_boot_optimize) - edp_link_to_turnoff = get_link_for_edp_not_in_use(dc, context); + edp_link_to_turnoff = get_link_for_edp_to_turn_off(dc, context); /* if OS doesn't light up eDP and eDP link is available, we want to disable * If resume from S4/S5, should optimization. @@ -1582,20 +1539,6 @@ void dce110_enable_accelerated_mode(struct dc *dc, struct dc_state *context) if (context->streams[i]->signal == SIGNAL_TYPE_EDP) { context->streams[i]->apply_edp_fast_boot_optimization = true; apply_edp_fast_boot_optimization = true; - - /* When after S4 and S5, vbios may post edp and previous dpms_off - * doesn't make sense. - * Update dpms_off state to align hw and sw state via check - * vBios scratch register. - */ - if (bios->funcs->is_active_display) { - const struct connector_device_tag_info *device_tag = &(edp_link->device_tag); - - if (bios->funcs->is_active_display(bios, - context->streams[i]->signal, - device_tag)) - context->streams[i]->dpms_off = false; - } } } } @@ -1624,8 +1567,8 @@ static uint32_t compute_pstate_blackout_duration( pstate_blackout_duration_ns = 1000 * blackout_duration.value >> 24; total_dest_line_time_ns = 1000000UL * - stream->timing.h_total / - stream->timing.pix_clk_khz + + (stream->timing.h_total * 10) / + stream->timing.pix_clk_100hz + pstate_blackout_duration_ns; return total_dest_line_time_ns; @@ -1813,18 +1756,15 @@ static bool should_enable_fbc(struct dc *dc, if (i == dc->res_pool->pipe_count) return false; - if (!pipe_ctx->stream->sink) - return false; - - if (!pipe_ctx->stream->sink->link) + if (!pipe_ctx->stream->link) return false; /* Only supports eDP */ - if (pipe_ctx->stream->sink->link->connector_signal != SIGNAL_TYPE_EDP) + if (pipe_ctx->stream->link->connector_signal != SIGNAL_TYPE_EDP) return false; /* PSR should not be enabled */ - if (pipe_ctx->stream->sink->link->psr_enabled) + if (pipe_ctx->stream->link->psr_enabled) return false; /* Nothing to compress */ @@ -2573,7 +2513,7 @@ static void dce110_apply_ctx_for_surface( pipe_ctx->plane_res.mi, pipe_ctx->stream->timing.h_total, pipe_ctx->stream->timing.v_total, - pipe_ctx->stream->timing.pix_clk_khz, + pipe_ctx->stream->timing.pix_clk_100hz / 10, context->stream_count); dce110_program_front_end_for_pipe(dc, pipe_ctx); @@ -2622,13 +2562,35 @@ static void dce110_wait_for_mpcc_disconnect( /* do nothing*/ } +static void program_output_csc(struct dc *dc, + struct pipe_ctx *pipe_ctx, + enum dc_color_space colorspace, + uint16_t *matrix, + int opp_id) +{ + int i; + struct out_csc_color_matrix tbl_entry; + + if (pipe_ctx->stream->csc_color_matrix.enable_adjustment == true) { + enum dc_color_space color_space = pipe_ctx->stream->output_color_space; + + for (i = 0; i < 12; i++) + tbl_entry.regval[i] = pipe_ctx->stream->csc_color_matrix.matrix[i]; + + tbl_entry.color_space = color_space; + + pipe_ctx->plane_res.xfm->funcs->opp_set_csc_adjustment( + pipe_ctx->plane_res.xfm, &tbl_entry); + } +} + void dce110_set_cursor_position(struct pipe_ctx *pipe_ctx) { struct dc_cursor_position pos_cpy = pipe_ctx->stream->cursor_position; struct input_pixel_processor *ipp = pipe_ctx->plane_res.ipp; struct mem_input *mi = pipe_ctx->plane_res.mi; struct dc_cursor_mi_param param = { - .pixel_clk_khz = pipe_ctx->stream->timing.pix_clk_khz, + .pixel_clk_khz = pipe_ctx->stream->timing.pix_clk_100hz / 10, .ref_clk_khz = pipe_ctx->stream->ctx->dc->res_pool->ref_clock_inKhz, .viewport = pipe_ctx->plane_res.scl_data.viewport, .h_scale_ratio = pipe_ctx->plane_res.scl_data.ratios.horz, @@ -2672,6 +2634,7 @@ void dce110_set_cursor_attribute(struct pipe_ctx *pipe_ctx) static const struct hw_sequencer_funcs dce110_funcs = { .program_gamut_remap = program_gamut_remap, + .program_output_csc = program_output_csc, .init_hw = init_hw, .apply_ctx_to_hw = dce110_apply_ctx_to_hw, .apply_ctx_for_surface = dce110_apply_ctx_for_surface, diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index e33d11785b1f..7549adaa1542 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -84,6 +84,7 @@ #ifndef mmBIOS_SCRATCH_2 #define mmBIOS_SCRATCH_2 0x05CB + #define mmBIOS_SCRATCH_3 0x05CC #define mmBIOS_SCRATCH_6 0x05CF #endif @@ -369,6 +370,7 @@ static const struct dce110_clk_src_mask cs_mask = { }; static const struct bios_registers bios_regs = { + .BIOS_SCRATCH_3 = mmBIOS_SCRATCH_3, .BIOS_SCRATCH_6 = mmBIOS_SCRATCH_6 }; @@ -606,7 +608,7 @@ static struct output_pixel_processor *dce110_opp_create( return &opp->base; } -struct aux_engine *dce110_aux_engine_create( +struct dce_aux *dce110_aux_engine_create( struct dc_context *ctx, uint32_t inst) { @@ -779,8 +781,8 @@ static void get_pixel_clock_parameters( * the pixel clock normalization for hdmi up to here instead of doing it * in pll_adjust_pix_clk */ - pixel_clk_params->requested_pix_clk = stream->timing.pix_clk_khz; - pixel_clk_params->encoder_object_id = stream->sink->link->link_enc->id; + pixel_clk_params->requested_pix_clk_100hz = stream->timing.pix_clk_100hz; + pixel_clk_params->encoder_object_id = stream->link->link_enc->id; pixel_clk_params->signal_type = pipe_ctx->stream->signal; pixel_clk_params->controller_id = pipe_ctx->stream_res.tg->inst + 1; /* TODO: un-hardcode*/ @@ -797,10 +799,10 @@ static void get_pixel_clock_parameters( pixel_clk_params->color_depth = COLOR_DEPTH_888; } if (stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420) { - pixel_clk_params->requested_pix_clk = pixel_clk_params->requested_pix_clk / 2; + pixel_clk_params->requested_pix_clk_100hz = pixel_clk_params->requested_pix_clk_100hz / 2; } if (stream->timing.timing_3d_format == TIMING_3D_FORMAT_HW_FRAME_PACKING) - pixel_clk_params->requested_pix_clk *= 2; + pixel_clk_params->requested_pix_clk_100hz *= 2; } @@ -874,7 +876,7 @@ static bool dce110_validate_bandwidth( __func__, context->streams[0]->timing.h_addressable, context->streams[0]->timing.v_addressable, - context->streams[0]->timing.pix_clk_khz); + context->streams[0]->timing.pix_clk_100hz / 10); if (memcmp(&dc->current_state->bw.dce, &context->bw.dce, sizeof(context->bw.dce))) { @@ -1055,7 +1057,7 @@ static struct pipe_ctx *dce110_acquire_underlay( pipe_ctx->plane_res.mi->funcs->allocate_mem_input(pipe_ctx->plane_res.mi, stream->timing.h_total, stream->timing.v_total, - stream->timing.pix_clk_khz, + stream->timing.pix_clk_100hz / 10, context->stream_count); color_space_to_black_color(dc, diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index 969d4e72dc94..ea3065d63372 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -76,6 +76,7 @@ #ifndef mmBIOS_SCRATCH_2 #define mmBIOS_SCRATCH_2 0x05CB + #define mmBIOS_SCRATCH_3 0x05CC #define mmBIOS_SCRATCH_6 0x05CF #endif @@ -376,6 +377,7 @@ static const struct dce110_clk_src_mask cs_mask = { }; static const struct bios_registers bios_regs = { + .BIOS_SCRATCH_3 = mmBIOS_SCRATCH_3, .BIOS_SCRATCH_6 = mmBIOS_SCRATCH_6 }; @@ -607,7 +609,7 @@ struct output_pixel_processor *dce112_opp_create( return &opp->base; } -struct aux_engine *dce112_aux_engine_create( +struct dce_aux *dce112_aux_engine_create( struct dc_context *ctx, uint32_t inst) { @@ -763,7 +765,7 @@ static struct clock_source *find_matching_pll( const struct resource_pool *pool, const struct dc_stream_state *const stream) { - switch (stream->sink->link->link_enc->transmitter) { + switch (stream->link->link_enc->transmitter) { case TRANSMITTER_UNIPHY_A: return pool->clock_sources[DCE112_CLK_SRC_PLL0]; case TRANSMITTER_UNIPHY_B: diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.c index eb0f5f9a973b..1ca30928025e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.c @@ -244,6 +244,21 @@ static void dce120_update_dchub( dh_data->dchub_info_valid = false; } +/** + * dce121_xgmi_enabled() - Check if xGMI is enabled + * @hws: DCE hardware sequencer object + * + * Return true if xGMI is enabled. False otherwise. + */ +bool dce121_xgmi_enabled(struct dce_hwseq *hws) +{ + uint32_t pf_max_region; + + REG_GET(MC_VM_XGMI_LFB_CNTL, PF_MAX_REGION, &pf_max_region); + /* PF_MAX_REGION == 0 means xgmi is disabled */ + return !!pf_max_region; +} + void dce120_hw_sequencer_construct(struct dc *dc) { /* All registers used by dce11.2 match those in dce11 in offset and diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.h index 77a6b86d7606..c51afbd0b012 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.h @@ -30,6 +30,7 @@ struct dc; +bool dce121_xgmi_enabled(struct dce_hwseq *hws); void dce120_hw_sequencer_construct(struct dc *dc); #endif /* __DC_HWSS_DCE112_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c index f12696674eb0..312a0aebf91f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c @@ -62,6 +62,8 @@ #include "soc15_hw_ip.h" #include "vega10_ip_offset.h" #include "nbio/nbio_6_1_offset.h" +#include "mmhub/mmhub_9_4_0_offset.h" +#include "mmhub/mmhub_9_4_0_sh_mask.h" #include "reg_helper.h" #include "dce100/dce100_resource.h" @@ -139,6 +141,17 @@ static const struct dce110_timing_generator_offsets dce120_tg_offsets[] = { .reg_name = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ mm ## block ## id ## _ ## reg_name +/* MMHUB */ +#define MMHUB_BASE_INNER(seg) \ + MMHUB_BASE__INST0_SEG ## seg + +#define MMHUB_BASE(seg) \ + MMHUB_BASE_INNER(seg) + +#define MMHUB_SR(reg_name)\ + .reg_name = MMHUB_BASE(mm ## reg_name ## _BASE_IDX) + \ + mm ## reg_name + /* macros to expend register list macro defined in HW object header file * end *********************/ @@ -378,7 +391,7 @@ struct output_pixel_processor *dce120_opp_create( ctx, inst, &opp_regs[inst], &opp_shift, &opp_mask); return &opp->base; } -struct aux_engine *dce120_aux_engine_create( +struct dce_aux *dce120_aux_engine_create( struct dc_context *ctx, uint32_t inst) { @@ -429,6 +442,7 @@ struct dce_i2c_hw *dce120_i2c_hw_create( return dce_i2c_hw; } static const struct bios_registers bios_regs = { + .BIOS_SCRATCH_3 = mmBIOS_SCRATCH_3 + NBIO_BASE(mmBIOS_SCRATCH_3_BASE_IDX), .BIOS_SCRATCH_6 = mmBIOS_SCRATCH_6 + NBIO_BASE(mmBIOS_SCRATCH_6_BASE_IDX) }; @@ -681,6 +695,19 @@ static const struct dce_hwseq_mask hwseq_mask = { HWSEQ_DCE12_MASK_SH_LIST(_MASK) }; +/* HWSEQ regs for VG20 */ +static const struct dce_hwseq_registers dce121_hwseq_reg = { + HWSEQ_VG20_REG_LIST() +}; + +static const struct dce_hwseq_shift dce121_hwseq_shift = { + HWSEQ_VG20_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_hwseq_mask dce121_hwseq_mask = { + HWSEQ_VG20_MASK_SH_LIST(_MASK) +}; + static struct dce_hwseq *dce120_hwseq_create( struct dc_context *ctx) { @@ -695,6 +722,20 @@ static struct dce_hwseq *dce120_hwseq_create( return hws; } +static struct dce_hwseq *dce121_hwseq_create( + struct dc_context *ctx) +{ + struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL); + + if (hws) { + hws->ctx = ctx; + hws->regs = &dce121_hwseq_reg; + hws->shifts = &dce121_hwseq_shift; + hws->masks = &dce121_hwseq_mask; + } + return hws; +} + static const struct resource_create_funcs res_create_funcs = { .read_dce_straps = read_dce_straps, .create_audio = create_audio, @@ -702,6 +743,14 @@ static const struct resource_create_funcs res_create_funcs = { .create_hwseq = dce120_hwseq_create, }; +static const struct resource_create_funcs dce121_res_create_funcs = { + .read_dce_straps = read_dce_straps, + .create_audio = create_audio, + .create_stream_encoder = dce120_stream_encoder_create, + .create_hwseq = dce121_hwseq_create, +}; + + #define mi_inst_regs(id) { MI_DCE12_REG_LIST(id) } static const struct dce_mem_input_registers mi_regs[] = { mi_inst_regs(0), @@ -911,7 +960,8 @@ static bool construct( int j; struct dc_context *ctx = dc->ctx; struct irq_service_init_data irq_init_data; - bool harvest_enabled = ASICREV_IS_VEGA20_P(ctx->asic_id.hw_internal_rev); + static const struct resource_create_funcs *res_funcs; + bool is_vg20 = ASICREV_IS_VEGA20_P(ctx->asic_id.hw_internal_rev); uint32_t pipe_fuses; ctx->dc_bios->regs = &bios_regs; @@ -975,7 +1025,11 @@ static bool construct( } } - pool->base.clk_mgr = dce120_clk_mgr_create(ctx); + if (is_vg20) + pool->base.clk_mgr = dce121_clk_mgr_create(ctx); + else + pool->base.clk_mgr = dce120_clk_mgr_create(ctx); + if (pool->base.clk_mgr == NULL) { dm_error("DC: failed to create display clock!\n"); BREAK_TO_DEBUGGER(); @@ -1008,14 +1062,14 @@ static bool construct( if (!pool->base.irqs) goto irqs_create_fail; - /* retrieve valid pipe fuses */ - if (harvest_enabled) + /* VG20: Pipe harvesting enabled, retrieve valid pipe fuses */ + if (is_vg20) pipe_fuses = read_pipe_fuses(ctx); /* index to valid pipe resource */ j = 0; for (i = 0; i < pool->base.pipe_count; i++) { - if (harvest_enabled) { + if (is_vg20) { if ((pipe_fuses & (1 << i)) != 0) { dm_error("DC: skip invalid pipe %d!\n", i); continue; @@ -1093,10 +1147,24 @@ static bool construct( pool->base.pipe_count = j; pool->base.timing_generator_count = j; - if (!resource_construct(num_virtual_links, dc, &pool->base, - &res_create_funcs)) + if (is_vg20) + res_funcs = &dce121_res_create_funcs; + else + res_funcs = &res_create_funcs; + + if (!resource_construct(num_virtual_links, dc, &pool->base, res_funcs)) goto res_create_fail; + /* + * This is a bit of a hack. The xGMI enabled info is used to determine + * if audio and display clocks need to be adjusted with the WAFL link's + * SS info. This is a responsiblity of the clk_mgr. But since MMHUB is + * under hwseq, and the relevant register is in MMHUB, we have to do it + * here. + */ + if (is_vg20 && dce121_xgmi_enabled(dc->hwseq)) + dce121_clock_patch_xgmi_ss_info(pool->base.clk_mgr); + /* Create hardware sequencer */ if (!dce120_hw_sequencer_create(dc)) goto controller_create_fail; diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index cdd1d6b7b9f2..2eca81b5cf2f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -77,6 +77,7 @@ #ifndef mmBIOS_SCRATCH_2 #define mmBIOS_SCRATCH_2 0x05CB + #define mmBIOS_SCRATCH_3 0x05CC #define mmBIOS_SCRATCH_6 0x05CF #endif @@ -358,6 +359,7 @@ static const struct dce110_clk_src_mask cs_mask = { }; static const struct bios_registers bios_regs = { + .BIOS_SCRATCH_3 = mmBIOS_SCRATCH_3, .BIOS_SCRATCH_6 = mmBIOS_SCRATCH_6 }; @@ -467,7 +469,7 @@ static struct output_pixel_processor *dce80_opp_create( return &opp->base; } -struct aux_engine *dce80_aux_engine_create( +struct dce_aux *dce80_aux_engine_create( struct dc_context *ctx, uint32_t inst) { diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c index 3ba4712a35ab..8b5ce557ee71 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c @@ -84,17 +84,17 @@ static const struct dce110_timing_generator_offsets reg_offsets[] = { #define DCP_REG(reg) (reg + tg110->offsets.dcp) #define DMIF_REG(reg) (reg + tg110->offsets.dmif) -static void program_pix_dur(struct timing_generator *tg, uint32_t pix_clk_khz) +static void program_pix_dur(struct timing_generator *tg, uint32_t pix_clk_100hz) { uint64_t pix_dur; uint32_t addr = mmDMIF_PG0_DPG_PIPE_ARBITRATION_CONTROL1 + DCE110TG_FROM_TG(tg)->offsets.dmif; uint32_t value = dm_read_reg(tg->ctx, addr); - if (pix_clk_khz == 0) + if (pix_clk_100hz == 0) return; - pix_dur = 1000000000 / pix_clk_khz; + pix_dur = div_u64(10000000000ull, pix_clk_100hz); set_reg_field_value( value, @@ -110,7 +110,7 @@ static void program_timing(struct timing_generator *tg, bool use_vbios) { if (!use_vbios) - program_pix_dur(tg, timing->pix_clk_khz); + program_pix_dur(tg, timing->pix_clk_100hz); dce110_tg_program_timing(tg, timing, use_vbios); } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_clk_mgr.c index 54abedbf1b43..afe8c42211cd 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_clk_mgr.c @@ -161,69 +161,17 @@ static int get_active_display_cnt( return display_count; } -static void notify_deep_sleep_dcfclk_to_smu( - struct pp_smu_funcs_rv *pp_smu, int min_dcef_deep_sleep_clk_khz) -{ - int min_dcef_deep_sleep_clk_mhz; //minimum required DCEF Deep Sleep clock in mhz - /* - * if function pointer not set up, this message is - * sent as part of pplib_apply_display_requirements. - * So just return. - */ - if (!pp_smu || !pp_smu->set_min_deep_sleep_dcfclk) - return; - - min_dcef_deep_sleep_clk_mhz = (min_dcef_deep_sleep_clk_khz + 999) / 1000; //Round up - pp_smu->set_min_deep_sleep_dcfclk(&pp_smu->pp_smu, min_dcef_deep_sleep_clk_mhz); -} - -static void notify_hard_min_dcfclk_to_smu( - struct pp_smu_funcs_rv *pp_smu, int min_dcf_clk_khz) -{ - int min_dcf_clk_mhz; //minimum required DCF clock in mhz - - /* - * if function pointer not set up, this message is - * sent as part of pplib_apply_display_requirements. - * So just return. - */ - if (!pp_smu || !pp_smu->set_hard_min_dcfclk_by_freq) - return; - - min_dcf_clk_mhz = min_dcf_clk_khz / 1000; - - pp_smu->set_hard_min_dcfclk_by_freq(&pp_smu->pp_smu, min_dcf_clk_mhz); -} - -static void notify_hard_min_fclk_to_smu( - struct pp_smu_funcs_rv *pp_smu, int min_f_clk_khz) -{ - int min_f_clk_mhz; //minimum required F clock in mhz - - /* - * if function pointer not set up, this message is - * sent as part of pplib_apply_display_requirements. - * So just return. - */ - if (!pp_smu || !pp_smu->set_hard_min_fclk_by_freq) - return; - - min_f_clk_mhz = min_f_clk_khz / 1000; - - pp_smu->set_hard_min_fclk_by_freq(&pp_smu->pp_smu, min_f_clk_mhz); -} - static void dcn1_update_clocks(struct clk_mgr *clk_mgr, struct dc_state *context, bool safe_to_lower) { struct dc *dc = clk_mgr->ctx->dc; + struct dc_debug_options *debug = &dc->debug; struct dc_clocks *new_clocks = &context->bw.dcn.clk; struct pp_smu_display_requirement_rv *smu_req_cur = &dc->res_pool->pp_smu_req; struct pp_smu_display_requirement_rv smu_req = *smu_req_cur; struct pp_smu_funcs_rv *pp_smu = dc->res_pool->pp_smu; - uint32_t requested_dcf_clock_in_khz = 0; bool send_request_to_increase = false; bool send_request_to_lower = false; int display_count; @@ -243,9 +191,8 @@ static void dcn1_update_clocks(struct clk_mgr *clk_mgr, */ if (pp_smu->set_display_count) pp_smu->set_display_count(&pp_smu->pp_smu, display_count); - else - smu_req.display_count = display_count; + smu_req.display_count = display_count; } if (new_clocks->dispclk_khz > clk_mgr->clks.dispclk_khz @@ -261,12 +208,13 @@ static void dcn1_update_clocks(struct clk_mgr *clk_mgr, } // F Clock + if (debug->force_fclk_khz != 0) + new_clocks->fclk_khz = debug->force_fclk_khz; + if (should_set_clock(safe_to_lower, new_clocks->fclk_khz, clk_mgr->clks.fclk_khz)) { clk_mgr->clks.fclk_khz = new_clocks->fclk_khz; smu_req.hard_min_fclk_mhz = new_clocks->fclk_khz / 1000; - notify_hard_min_fclk_to_smu(pp_smu, new_clocks->fclk_khz); - send_request_to_lower = true; } @@ -281,7 +229,7 @@ static void dcn1_update_clocks(struct clk_mgr *clk_mgr, if (should_set_clock(safe_to_lower, new_clocks->dcfclk_deep_sleep_khz, clk_mgr->clks.dcfclk_deep_sleep_khz)) { clk_mgr->clks.dcfclk_deep_sleep_khz = new_clocks->dcfclk_deep_sleep_khz; - smu_req.min_deep_sleep_dcefclk_mhz = new_clocks->dcfclk_deep_sleep_khz / 1000; + smu_req.min_deep_sleep_dcefclk_mhz = (new_clocks->dcfclk_deep_sleep_khz + 999) / 1000; send_request_to_lower = true; } @@ -291,15 +239,18 @@ static void dcn1_update_clocks(struct clk_mgr *clk_mgr, */ if (send_request_to_increase) { /*use dcfclk to request voltage*/ - requested_dcf_clock_in_khz = dcn_find_dcfclk_suits_all(dc, new_clocks); - - notify_hard_min_dcfclk_to_smu(pp_smu, requested_dcf_clock_in_khz); - - if (pp_smu->set_display_requirement) - pp_smu->set_display_requirement(&pp_smu->pp_smu, &smu_req); - - notify_deep_sleep_dcfclk_to_smu(pp_smu, clk_mgr->clks.dcfclk_deep_sleep_khz); - dcn1_pplib_apply_display_requirements(dc, context); + if (pp_smu->set_hard_min_fclk_by_freq && + pp_smu->set_hard_min_dcfclk_by_freq && + pp_smu->set_min_deep_sleep_dcfclk) { + + pp_smu->set_hard_min_fclk_by_freq(&pp_smu->pp_smu, smu_req.hard_min_fclk_mhz); + pp_smu->set_hard_min_dcfclk_by_freq(&pp_smu->pp_smu, smu_req.hard_min_dcefclk_mhz); + pp_smu->set_min_deep_sleep_dcfclk(&pp_smu->pp_smu, smu_req.min_deep_sleep_dcefclk_mhz); + } else { + if (pp_smu->set_display_requirement) + pp_smu->set_display_requirement(&pp_smu->pp_smu, &smu_req); + dcn1_pplib_apply_display_requirements(dc, context); + } } /* dcn1 dppclk is tied to dispclk */ @@ -314,18 +265,20 @@ static void dcn1_update_clocks(struct clk_mgr *clk_mgr, if (!send_request_to_increase && send_request_to_lower) { /*use dcfclk to request voltage*/ - requested_dcf_clock_in_khz = dcn_find_dcfclk_suits_all(dc, new_clocks); - - notify_hard_min_dcfclk_to_smu(pp_smu, requested_dcf_clock_in_khz); - - if (pp_smu->set_display_requirement) - pp_smu->set_display_requirement(&pp_smu->pp_smu, &smu_req); - - notify_deep_sleep_dcfclk_to_smu(pp_smu, clk_mgr->clks.dcfclk_deep_sleep_khz); - dcn1_pplib_apply_display_requirements(dc, context); + if (pp_smu->set_hard_min_fclk_by_freq && + pp_smu->set_hard_min_dcfclk_by_freq && + pp_smu->set_min_deep_sleep_dcfclk) { + + pp_smu->set_hard_min_fclk_by_freq(&pp_smu->pp_smu, smu_req.hard_min_fclk_mhz); + pp_smu->set_hard_min_dcfclk_by_freq(&pp_smu->pp_smu, smu_req.hard_min_dcefclk_mhz); + pp_smu->set_min_deep_sleep_dcfclk(&pp_smu->pp_smu, smu_req.min_deep_sleep_dcefclk_mhz); + } else { + if (pp_smu->set_display_requirement) + pp_smu->set_display_requirement(&pp_smu->pp_smu, &smu_req); + dcn1_pplib_apply_display_requirements(dc, context); + } } - *smu_req_cur = smu_req; } static const struct clk_mgr_funcs dcn1_funcs = { diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c index dcb3c5530236..cd1ebe57ed59 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c @@ -463,7 +463,7 @@ void dpp1_set_cursor_position( if (src_y_offset >= (int)param->viewport.height) cur_en = 0; /* not visible beyond bottom edge*/ - if (src_y_offset < 0) + if (src_y_offset + (int)height <= 0) cur_en = 0; /* not visible beyond top edge*/ REG_UPDATE(CURSOR0_CONTROL, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c index 116977eb24e2..41f0f4c912e7 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c @@ -51,10 +51,6 @@ #define NUM_ELEMENTS(a) (sizeof(a) / sizeof((a)[0])) -struct dcn10_input_csc_matrix { - enum dc_color_space color_space; - uint16_t regval[12]; -}; enum dcn10_coef_filter_type_sel { SCL_COEF_LUMA_VERT_FILTER = 0, @@ -99,7 +95,7 @@ enum gamut_remap_select { GAMUT_REMAP_COMB_COEFF }; -static const struct dcn10_input_csc_matrix dcn10_input_csc_matrix[] = { +static const struct dpp_input_csc_matrix dpp_input_csc_matrix[] = { {COLOR_SPACE_SRGB, {0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} }, {COLOR_SPACE_SRGB_LIMITED, @@ -454,7 +450,7 @@ void dpp1_program_input_csc( { struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); int i; - int arr_size = sizeof(dcn10_input_csc_matrix)/sizeof(struct dcn10_input_csc_matrix); + int arr_size = sizeof(dpp_input_csc_matrix)/sizeof(struct dpp_input_csc_matrix); const uint16_t *regval = NULL; uint32_t cur_select = 0; enum dcn10_input_csc_select select; @@ -467,8 +463,8 @@ void dpp1_program_input_csc( if (tbl_entry == NULL) { for (i = 0; i < arr_size; i++) - if (dcn10_input_csc_matrix[i].color_space == color_space) { - regval = dcn10_input_csc_matrix[i].regval; + if (dpp_input_csc_matrix[i].color_space == color_space) { + regval = dpp_input_csc_matrix[i].regval; break; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c index 4a863a5dab41..c7642e748297 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c @@ -597,11 +597,13 @@ static void dpp1_dscl_set_manual_ratio_init( SCL_V_INIT_FRAC, init_frac, SCL_V_INIT_INT, init_int); - init_frac = dc_fixpt_u0d19(data->inits.v_bot) << 5; - init_int = dc_fixpt_floor(data->inits.v_bot); - REG_SET_2(SCL_VERT_FILTER_INIT_BOT, 0, - SCL_V_INIT_FRAC_BOT, init_frac, - SCL_V_INIT_INT_BOT, init_int); + if (REG(SCL_VERT_FILTER_INIT_BOT)) { + init_frac = dc_fixpt_u0d19(data->inits.v_bot) << 5; + init_int = dc_fixpt_floor(data->inits.v_bot); + REG_SET_2(SCL_VERT_FILTER_INIT_BOT, 0, + SCL_V_INIT_FRAC_BOT, init_frac, + SCL_V_INIT_INT_BOT, init_int); + } init_frac = dc_fixpt_u0d19(data->inits.v_c) << 5; init_int = dc_fixpt_floor(data->inits.v_c); @@ -609,11 +611,13 @@ static void dpp1_dscl_set_manual_ratio_init( SCL_V_INIT_FRAC_C, init_frac, SCL_V_INIT_INT_C, init_int); - init_frac = dc_fixpt_u0d19(data->inits.v_c_bot) << 5; - init_int = dc_fixpt_floor(data->inits.v_c_bot); - REG_SET_2(SCL_VERT_FILTER_INIT_BOT_C, 0, - SCL_V_INIT_FRAC_BOT_C, init_frac, - SCL_V_INIT_INT_BOT_C, init_int); + if (REG(SCL_VERT_FILTER_INIT_BOT_C)) { + init_frac = dc_fixpt_u0d19(data->inits.v_c_bot) << 5; + init_int = dc_fixpt_floor(data->inits.v_c_bot); + REG_SET_2(SCL_VERT_FILTER_INIT_BOT_C, 0, + SCL_V_INIT_FRAC_BOT_C, init_frac, + SCL_V_INIT_INT_BOT_C, init_int); + } } @@ -688,15 +692,17 @@ void dpp1_dscl_set_scaler_manual_scale( return; /* Black offsets */ - if (ycbcr) - REG_SET_2(SCL_BLACK_OFFSET, 0, - SCL_BLACK_OFFSET_RGB_Y, BLACK_OFFSET_RGB_Y, - SCL_BLACK_OFFSET_CBCR, BLACK_OFFSET_CBCR); - else + if (REG(SCL_BLACK_OFFSET)) { + if (ycbcr) + REG_SET_2(SCL_BLACK_OFFSET, 0, + SCL_BLACK_OFFSET_RGB_Y, BLACK_OFFSET_RGB_Y, + SCL_BLACK_OFFSET_CBCR, BLACK_OFFSET_CBCR); + else - REG_SET_2(SCL_BLACK_OFFSET, 0, - SCL_BLACK_OFFSET_RGB_Y, BLACK_OFFSET_RGB_Y, - SCL_BLACK_OFFSET_CBCR, BLACK_OFFSET_RGB_Y); + REG_SET_2(SCL_BLACK_OFFSET, 0, + SCL_BLACK_OFFSET_RGB_Y, BLACK_OFFSET_RGB_Y, + SCL_BLACK_OFFSET_CBCR, BLACK_OFFSET_RGB_Y); + } /* Manually calculate scale ratio and init values */ dpp1_dscl_set_manual_ratio_init(dpp, scl_data); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c index c7d1e678ebf5..5a4614c371bc 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c @@ -29,19 +29,20 @@ #include "reg_helper.h" #define CTX \ - hubbub->ctx + hubbub1->base.ctx #define DC_LOGGER \ - hubbub->ctx->logger + hubbub1->base.ctx->logger #define REG(reg)\ - hubbub->regs->reg + hubbub1->regs->reg #undef FN #define FN(reg_name, field_name) \ - hubbub->shifts->field_name, hubbub->masks->field_name + hubbub1->shifts->field_name, hubbub1->masks->field_name void hubbub1_wm_read_state(struct hubbub *hubbub, struct dcn_hubbub_wm *wm) { + struct dcn10_hubbub *hubbub1 = TO_DCN10_HUBBUB(hubbub); struct dcn_hubbub_wm_set *s; memset(wm, 0, sizeof(struct dcn_hubbub_wm)); @@ -89,12 +90,14 @@ void hubbub1_wm_read_state(struct hubbub *hubbub, void hubbub1_disable_allow_self_refresh(struct hubbub *hubbub) { + struct dcn10_hubbub *hubbub1 = TO_DCN10_HUBBUB(hubbub); REG_UPDATE(DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE, 0); } bool hububu1_is_allow_self_refresh_enabled(struct hubbub *hubbub) { + struct dcn10_hubbub *hubbub1 = TO_DCN10_HUBBUB(hubbub); uint32_t enable = 0; REG_GET(DCHUBBUB_ARB_DRAM_STATE_CNTL, @@ -107,6 +110,8 @@ bool hububu1_is_allow_self_refresh_enabled(struct hubbub *hubbub) bool hubbub1_verify_allow_pstate_change_high( struct hubbub *hubbub) { + struct dcn10_hubbub *hubbub1 = TO_DCN10_HUBBUB(hubbub); + /* pstate latency is ~20us so if we wait over 40us and pstate allow * still not asserted, we are probably stuck and going to hang * @@ -193,7 +198,7 @@ bool hubbub1_verify_allow_pstate_change_high( * 31: SOC pstate change request */ - REG_WRITE(DCHUBBUB_TEST_DEBUG_INDEX, hubbub->debug_test_index_pstate); + REG_WRITE(DCHUBBUB_TEST_DEBUG_INDEX, hubbub1->debug_test_index_pstate); for (i = 0; i < pstate_wait_timeout_us; i++) { debug_data = REG_READ(DCHUBBUB_TEST_DEBUG_DATA); @@ -244,6 +249,8 @@ static uint32_t convert_and_clamp( void hubbub1_wm_change_req_wa(struct hubbub *hubbub) { + struct dcn10_hubbub *hubbub1 = TO_DCN10_HUBBUB(hubbub); + REG_UPDATE_SEQ(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, 0, 1); } @@ -254,7 +261,9 @@ void hubbub1_program_watermarks( unsigned int refclk_mhz, bool safe_to_lower) { - uint32_t force_en = hubbub->ctx->dc->debug.disable_stutter ? 1 : 0; + struct dcn10_hubbub *hubbub1 = TO_DCN10_HUBBUB(hubbub); + + uint32_t force_en = hubbub1->base.ctx->dc->debug.disable_stutter ? 1 : 0; /* * Need to clamp to max of the register values (i.e. no wrap) * for dcn1, all wm registers are 21-bit wide @@ -264,8 +273,8 @@ void hubbub1_program_watermarks( /* Repeat for water mark set A, B, C and D. */ /* clock state A */ - if (safe_to_lower || watermarks->a.urgent_ns > hubbub->watermarks.a.urgent_ns) { - hubbub->watermarks.a.urgent_ns = watermarks->a.urgent_ns; + if (safe_to_lower || watermarks->a.urgent_ns > hubbub1->watermarks.a.urgent_ns) { + hubbub1->watermarks.a.urgent_ns = watermarks->a.urgent_ns; prog_wm_value = convert_and_clamp(watermarks->a.urgent_ns, refclk_mhz, 0x1fffff); REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, prog_wm_value); @@ -275,20 +284,22 @@ void hubbub1_program_watermarks( watermarks->a.urgent_ns, prog_wm_value); } - if (safe_to_lower || watermarks->a.pte_meta_urgent_ns > hubbub->watermarks.a.pte_meta_urgent_ns) { - hubbub->watermarks.a.pte_meta_urgent_ns = watermarks->a.pte_meta_urgent_ns; - prog_wm_value = convert_and_clamp(watermarks->a.pte_meta_urgent_ns, - refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_A, prog_wm_value); - DC_LOG_BANDWIDTH_CALCS("PTE_META_URGENCY_WATERMARK_A calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->a.pte_meta_urgent_ns, prog_wm_value); + if (REG(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_A)) { + if (safe_to_lower || watermarks->a.pte_meta_urgent_ns > hubbub1->watermarks.a.pte_meta_urgent_ns) { + hubbub1->watermarks.a.pte_meta_urgent_ns = watermarks->a.pte_meta_urgent_ns; + prog_wm_value = convert_and_clamp(watermarks->a.pte_meta_urgent_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_A, prog_wm_value); + DC_LOG_BANDWIDTH_CALCS("PTE_META_URGENCY_WATERMARK_A calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->a.pte_meta_urgent_ns, prog_wm_value); + } } if (REG(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A)) { if (safe_to_lower || watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns - > hubbub->watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns) { - hubbub->watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns = + > hubbub1->watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns) { + hubbub1->watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns = watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns; prog_wm_value = convert_and_clamp( watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns, @@ -300,8 +311,8 @@ void hubbub1_program_watermarks( } if (safe_to_lower || watermarks->a.cstate_pstate.cstate_exit_ns - > hubbub->watermarks.a.cstate_pstate.cstate_exit_ns) { - hubbub->watermarks.a.cstate_pstate.cstate_exit_ns = + > hubbub1->watermarks.a.cstate_pstate.cstate_exit_ns) { + hubbub1->watermarks.a.cstate_pstate.cstate_exit_ns = watermarks->a.cstate_pstate.cstate_exit_ns; prog_wm_value = convert_and_clamp( watermarks->a.cstate_pstate.cstate_exit_ns, @@ -314,8 +325,8 @@ void hubbub1_program_watermarks( } if (safe_to_lower || watermarks->a.cstate_pstate.pstate_change_ns - > hubbub->watermarks.a.cstate_pstate.pstate_change_ns) { - hubbub->watermarks.a.cstate_pstate.pstate_change_ns = + > hubbub1->watermarks.a.cstate_pstate.pstate_change_ns) { + hubbub1->watermarks.a.cstate_pstate.pstate_change_ns = watermarks->a.cstate_pstate.pstate_change_ns; prog_wm_value = convert_and_clamp( watermarks->a.cstate_pstate.pstate_change_ns, @@ -327,8 +338,8 @@ void hubbub1_program_watermarks( } /* clock state B */ - if (safe_to_lower || watermarks->b.urgent_ns > hubbub->watermarks.b.urgent_ns) { - hubbub->watermarks.b.urgent_ns = watermarks->b.urgent_ns; + if (safe_to_lower || watermarks->b.urgent_ns > hubbub1->watermarks.b.urgent_ns) { + hubbub1->watermarks.b.urgent_ns = watermarks->b.urgent_ns; prog_wm_value = convert_and_clamp(watermarks->b.urgent_ns, refclk_mhz, 0x1fffff); REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, prog_wm_value); @@ -338,20 +349,22 @@ void hubbub1_program_watermarks( watermarks->b.urgent_ns, prog_wm_value); } - if (safe_to_lower || watermarks->b.pte_meta_urgent_ns > hubbub->watermarks.b.pte_meta_urgent_ns) { - hubbub->watermarks.b.pte_meta_urgent_ns = watermarks->b.pte_meta_urgent_ns; - prog_wm_value = convert_and_clamp(watermarks->b.pte_meta_urgent_ns, - refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_B, prog_wm_value); - DC_LOG_BANDWIDTH_CALCS("PTE_META_URGENCY_WATERMARK_B calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->b.pte_meta_urgent_ns, prog_wm_value); + if (REG(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_B)) { + if (safe_to_lower || watermarks->b.pte_meta_urgent_ns > hubbub1->watermarks.b.pte_meta_urgent_ns) { + hubbub1->watermarks.b.pte_meta_urgent_ns = watermarks->b.pte_meta_urgent_ns; + prog_wm_value = convert_and_clamp(watermarks->b.pte_meta_urgent_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_B, prog_wm_value); + DC_LOG_BANDWIDTH_CALCS("PTE_META_URGENCY_WATERMARK_B calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->b.pte_meta_urgent_ns, prog_wm_value); + } } if (REG(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B)) { if (safe_to_lower || watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns - > hubbub->watermarks.b.cstate_pstate.cstate_enter_plus_exit_ns) { - hubbub->watermarks.b.cstate_pstate.cstate_enter_plus_exit_ns = + > hubbub1->watermarks.b.cstate_pstate.cstate_enter_plus_exit_ns) { + hubbub1->watermarks.b.cstate_pstate.cstate_enter_plus_exit_ns = watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns; prog_wm_value = convert_and_clamp( watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns, @@ -363,8 +376,8 @@ void hubbub1_program_watermarks( } if (safe_to_lower || watermarks->b.cstate_pstate.cstate_exit_ns - > hubbub->watermarks.b.cstate_pstate.cstate_exit_ns) { - hubbub->watermarks.b.cstate_pstate.cstate_exit_ns = + > hubbub1->watermarks.b.cstate_pstate.cstate_exit_ns) { + hubbub1->watermarks.b.cstate_pstate.cstate_exit_ns = watermarks->b.cstate_pstate.cstate_exit_ns; prog_wm_value = convert_and_clamp( watermarks->b.cstate_pstate.cstate_exit_ns, @@ -377,8 +390,8 @@ void hubbub1_program_watermarks( } if (safe_to_lower || watermarks->b.cstate_pstate.pstate_change_ns - > hubbub->watermarks.b.cstate_pstate.pstate_change_ns) { - hubbub->watermarks.b.cstate_pstate.pstate_change_ns = + > hubbub1->watermarks.b.cstate_pstate.pstate_change_ns) { + hubbub1->watermarks.b.cstate_pstate.pstate_change_ns = watermarks->b.cstate_pstate.pstate_change_ns; prog_wm_value = convert_and_clamp( watermarks->b.cstate_pstate.pstate_change_ns, @@ -390,8 +403,8 @@ void hubbub1_program_watermarks( } /* clock state C */ - if (safe_to_lower || watermarks->c.urgent_ns > hubbub->watermarks.c.urgent_ns) { - hubbub->watermarks.c.urgent_ns = watermarks->c.urgent_ns; + if (safe_to_lower || watermarks->c.urgent_ns > hubbub1->watermarks.c.urgent_ns) { + hubbub1->watermarks.c.urgent_ns = watermarks->c.urgent_ns; prog_wm_value = convert_and_clamp(watermarks->c.urgent_ns, refclk_mhz, 0x1fffff); REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, prog_wm_value); @@ -401,20 +414,22 @@ void hubbub1_program_watermarks( watermarks->c.urgent_ns, prog_wm_value); } - if (safe_to_lower || watermarks->c.pte_meta_urgent_ns > hubbub->watermarks.c.pte_meta_urgent_ns) { - hubbub->watermarks.c.pte_meta_urgent_ns = watermarks->c.pte_meta_urgent_ns; - prog_wm_value = convert_and_clamp(watermarks->c.pte_meta_urgent_ns, - refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_C, prog_wm_value); - DC_LOG_BANDWIDTH_CALCS("PTE_META_URGENCY_WATERMARK_C calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->c.pte_meta_urgent_ns, prog_wm_value); + if (REG(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_C)) { + if (safe_to_lower || watermarks->c.pte_meta_urgent_ns > hubbub1->watermarks.c.pte_meta_urgent_ns) { + hubbub1->watermarks.c.pte_meta_urgent_ns = watermarks->c.pte_meta_urgent_ns; + prog_wm_value = convert_and_clamp(watermarks->c.pte_meta_urgent_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_C, prog_wm_value); + DC_LOG_BANDWIDTH_CALCS("PTE_META_URGENCY_WATERMARK_C calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->c.pte_meta_urgent_ns, prog_wm_value); + } } if (REG(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C)) { if (safe_to_lower || watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns - > hubbub->watermarks.c.cstate_pstate.cstate_enter_plus_exit_ns) { - hubbub->watermarks.c.cstate_pstate.cstate_enter_plus_exit_ns = + > hubbub1->watermarks.c.cstate_pstate.cstate_enter_plus_exit_ns) { + hubbub1->watermarks.c.cstate_pstate.cstate_enter_plus_exit_ns = watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns; prog_wm_value = convert_and_clamp( watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns, @@ -426,8 +441,8 @@ void hubbub1_program_watermarks( } if (safe_to_lower || watermarks->c.cstate_pstate.cstate_exit_ns - > hubbub->watermarks.c.cstate_pstate.cstate_exit_ns) { - hubbub->watermarks.c.cstate_pstate.cstate_exit_ns = + > hubbub1->watermarks.c.cstate_pstate.cstate_exit_ns) { + hubbub1->watermarks.c.cstate_pstate.cstate_exit_ns = watermarks->c.cstate_pstate.cstate_exit_ns; prog_wm_value = convert_and_clamp( watermarks->c.cstate_pstate.cstate_exit_ns, @@ -440,8 +455,8 @@ void hubbub1_program_watermarks( } if (safe_to_lower || watermarks->c.cstate_pstate.pstate_change_ns - > hubbub->watermarks.c.cstate_pstate.pstate_change_ns) { - hubbub->watermarks.c.cstate_pstate.pstate_change_ns = + > hubbub1->watermarks.c.cstate_pstate.pstate_change_ns) { + hubbub1->watermarks.c.cstate_pstate.pstate_change_ns = watermarks->c.cstate_pstate.pstate_change_ns; prog_wm_value = convert_and_clamp( watermarks->c.cstate_pstate.pstate_change_ns, @@ -453,8 +468,8 @@ void hubbub1_program_watermarks( } /* clock state D */ - if (safe_to_lower || watermarks->d.urgent_ns > hubbub->watermarks.d.urgent_ns) { - hubbub->watermarks.d.urgent_ns = watermarks->d.urgent_ns; + if (safe_to_lower || watermarks->d.urgent_ns > hubbub1->watermarks.d.urgent_ns) { + hubbub1->watermarks.d.urgent_ns = watermarks->d.urgent_ns; prog_wm_value = convert_and_clamp(watermarks->d.urgent_ns, refclk_mhz, 0x1fffff); REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, prog_wm_value); @@ -464,20 +479,22 @@ void hubbub1_program_watermarks( watermarks->d.urgent_ns, prog_wm_value); } - if (safe_to_lower || watermarks->d.pte_meta_urgent_ns > hubbub->watermarks.d.pte_meta_urgent_ns) { - hubbub->watermarks.d.pte_meta_urgent_ns = watermarks->d.pte_meta_urgent_ns; - prog_wm_value = convert_and_clamp(watermarks->d.pte_meta_urgent_ns, - refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_D, prog_wm_value); - DC_LOG_BANDWIDTH_CALCS("PTE_META_URGENCY_WATERMARK_D calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->d.pte_meta_urgent_ns, prog_wm_value); + if (REG(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_D)) { + if (safe_to_lower || watermarks->d.pte_meta_urgent_ns > hubbub1->watermarks.d.pte_meta_urgent_ns) { + hubbub1->watermarks.d.pte_meta_urgent_ns = watermarks->d.pte_meta_urgent_ns; + prog_wm_value = convert_and_clamp(watermarks->d.pte_meta_urgent_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_D, prog_wm_value); + DC_LOG_BANDWIDTH_CALCS("PTE_META_URGENCY_WATERMARK_D calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->d.pte_meta_urgent_ns, prog_wm_value); + } } if (REG(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D)) { if (safe_to_lower || watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns - > hubbub->watermarks.d.cstate_pstate.cstate_enter_plus_exit_ns) { - hubbub->watermarks.d.cstate_pstate.cstate_enter_plus_exit_ns = + > hubbub1->watermarks.d.cstate_pstate.cstate_enter_plus_exit_ns) { + hubbub1->watermarks.d.cstate_pstate.cstate_enter_plus_exit_ns = watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns; prog_wm_value = convert_and_clamp( watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns, @@ -489,8 +506,8 @@ void hubbub1_program_watermarks( } if (safe_to_lower || watermarks->d.cstate_pstate.cstate_exit_ns - > hubbub->watermarks.d.cstate_pstate.cstate_exit_ns) { - hubbub->watermarks.d.cstate_pstate.cstate_exit_ns = + > hubbub1->watermarks.d.cstate_pstate.cstate_exit_ns) { + hubbub1->watermarks.d.cstate_pstate.cstate_exit_ns = watermarks->d.cstate_pstate.cstate_exit_ns; prog_wm_value = convert_and_clamp( watermarks->d.cstate_pstate.cstate_exit_ns, @@ -503,8 +520,8 @@ void hubbub1_program_watermarks( } if (safe_to_lower || watermarks->d.cstate_pstate.pstate_change_ns - > hubbub->watermarks.d.cstate_pstate.pstate_change_ns) { - hubbub->watermarks.d.cstate_pstate.pstate_change_ns = + > hubbub1->watermarks.d.cstate_pstate.pstate_change_ns) { + hubbub1->watermarks.d.cstate_pstate.pstate_change_ns = watermarks->d.cstate_pstate.pstate_change_ns; prog_wm_value = convert_and_clamp( watermarks->d.cstate_pstate.pstate_change_ns, @@ -535,6 +552,8 @@ void hubbub1_update_dchub( struct hubbub *hubbub, struct dchub_init_data *dh_data) { + struct dcn10_hubbub *hubbub1 = TO_DCN10_HUBBUB(hubbub); + if (REG(DCHUBBUB_SDPIF_FB_TOP) == 0) { ASSERT(false); /*should not come here*/ @@ -594,6 +613,8 @@ void hubbub1_update_dchub( void hubbub1_toggle_watermark_change_req(struct hubbub *hubbub) { + struct dcn10_hubbub *hubbub1 = TO_DCN10_HUBBUB(hubbub); + uint32_t watermark_change_req; REG_GET(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, @@ -610,6 +631,8 @@ void hubbub1_toggle_watermark_change_req(struct hubbub *hubbub) void hubbub1_soft_reset(struct hubbub *hubbub, bool reset) { + struct dcn10_hubbub *hubbub1 = TO_DCN10_HUBBUB(hubbub); + uint32_t reset_en = reset ? 1 : 0; REG_UPDATE(DCHUBBUB_SOFT_RESET, @@ -752,7 +775,9 @@ static bool hubbub1_get_dcc_compression_cap(struct hubbub *hubbub, const struct dc_dcc_surface_param *input, struct dc_surface_dcc_cap *output) { - struct dc *dc = hubbub->ctx->dc; + struct dcn10_hubbub *hubbub1 = TO_DCN10_HUBBUB(hubbub); + struct dc *dc = hubbub1->base.ctx->dc; + /* implement section 1.6.2.1 of DCN1_Programming_Guide.docx */ enum dcc_control dcc_control; unsigned int bpe; @@ -764,10 +789,10 @@ static bool hubbub1_get_dcc_compression_cap(struct hubbub *hubbub, if (dc->debug.disable_dcc == DCC_DISABLE) return false; - if (!hubbub->funcs->dcc_support_pixel_format(input->format, &bpe)) + if (!hubbub1->base.funcs->dcc_support_pixel_format(input->format, &bpe)) return false; - if (!hubbub->funcs->dcc_support_swizzle(input->swizzle_mode, bpe, + if (!hubbub1->base.funcs->dcc_support_swizzle(input->swizzle_mode, bpe, &segment_order_horz, &segment_order_vert)) return false; @@ -837,6 +862,7 @@ static const struct hubbub_funcs hubbub1_funcs = { .dcc_support_swizzle = hubbub1_dcc_support_swizzle, .dcc_support_pixel_format = hubbub1_dcc_support_pixel_format, .get_dcc_compression_cap = hubbub1_get_dcc_compression_cap, + .wm_read_state = hubbub1_wm_read_state, }; void hubbub1_construct(struct hubbub *hubbub, @@ -845,18 +871,20 @@ void hubbub1_construct(struct hubbub *hubbub, const struct dcn_hubbub_shift *hubbub_shift, const struct dcn_hubbub_mask *hubbub_mask) { - hubbub->ctx = ctx; + struct dcn10_hubbub *hubbub1 = TO_DCN10_HUBBUB(hubbub); + + hubbub1->base.ctx = ctx; - hubbub->funcs = &hubbub1_funcs; + hubbub1->base.funcs = &hubbub1_funcs; - hubbub->regs = hubbub_regs; - hubbub->shifts = hubbub_shift; - hubbub->masks = hubbub_mask; + hubbub1->regs = hubbub_regs; + hubbub1->shifts = hubbub_shift; + hubbub1->masks = hubbub_mask; - hubbub->debug_test_index_pstate = 0x7; + hubbub1->debug_test_index_pstate = 0x7; #if defined(CONFIG_DRM_AMD_DC_DCN1_01) if (ctx->dce_version == DCN_VERSION_1_01) - hubbub->debug_test_index_pstate = 0xB; + hubbub1->debug_test_index_pstate = 0xB; #endif } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.h index d0f03d152913..c681e1cc9290 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.h @@ -29,6 +29,9 @@ #include "core_types.h" #include "dchubbub.h" +#define TO_DCN10_HUBBUB(hubbub)\ + container_of(hubbub, struct dcn10_hubbub, base) + #define HUBHUB_REG_LIST_DCN()\ SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A),\ SR(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_A),\ @@ -107,6 +110,12 @@ struct dcn_hubbub_registers { uint32_t DCHUBBUB_SDPIF_AGP_TOP; uint32_t DCHUBBUB_CRC_CTRL; uint32_t DCHUBBUB_SOFT_RESET; + uint32_t DCN_VM_FB_LOCATION_BASE; + uint32_t DCN_VM_FB_LOCATION_TOP; + uint32_t DCN_VM_FB_OFFSET; + uint32_t DCN_VM_AGP_BOT; + uint32_t DCN_VM_AGP_TOP; + uint32_t DCN_VM_AGP_BASE; }; /* set field name */ @@ -152,7 +161,13 @@ struct dcn_hubbub_registers { type SDPIF_FB_OFFSET;\ type SDPIF_AGP_BASE;\ type SDPIF_AGP_BOT;\ - type SDPIF_AGP_TOP + type SDPIF_AGP_TOP;\ + type FB_BASE;\ + type FB_TOP;\ + type FB_OFFSET;\ + type AGP_BOT;\ + type AGP_TOP;\ + type AGP_BASE struct dcn_hubbub_shift { @@ -165,22 +180,8 @@ struct dcn_hubbub_mask { struct dc; -struct dcn_hubbub_wm_set { - uint32_t wm_set; - uint32_t data_urgent; - uint32_t pte_meta_urgent; - uint32_t sr_enter; - uint32_t sr_exit; - uint32_t dram_clk_chanage; -}; - -struct dcn_hubbub_wm { - struct dcn_hubbub_wm_set sets[4]; -}; - -struct hubbub { - const struct hubbub_funcs *funcs; - struct dc_context *ctx; +struct dcn10_hubbub { + struct hubbub base; const struct dcn_hubbub_registers *regs; const struct dcn_hubbub_shift *shifts; const struct dcn_hubbub_mask *masks; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c index 345af015d061..0ba68d41b9c3 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c @@ -115,7 +115,7 @@ static void hubp1_set_hubp_blank_en(struct hubp *hubp, bool blank) REG_UPDATE(DCHUBP_CNTL, HUBP_BLANK_EN, blank_en); } -static void hubp1_vready_workaround(struct hubp *hubp, +void hubp1_vready_workaround(struct hubp *hubp, struct _vcs_dpi_display_pipe_dest_params_st *pipe_dest) { uint32_t value = 0; @@ -317,7 +317,8 @@ void hubp1_program_pixel_format( bool hubp1_program_surface_flip_and_addr( struct hubp *hubp, const struct dc_plane_address *address, - bool flip_immediate) + bool flip_immediate, + uint8_t vmid) { struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); @@ -1140,7 +1141,7 @@ void hubp1_cursor_set_position( if (src_y_offset >= (int)param->viewport.height) cur_en = 0; /* not visible beyond bottom edge*/ - if (src_y_offset < 0) //+ (int)hubp->curs_attr.height + if (src_y_offset + (int)hubp->curs_attr.height <= 0) cur_en = 0; /* not visible beyond top edge*/ if (cur_en && REG_READ(CURSOR_SURFACE_ADDRESS) == 0) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.h index 62d4232e7796..a6d6dfe00617 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.h @@ -707,11 +707,6 @@ void hubp1_dcc_control(struct hubp *hubp, bool enable, bool independent_64b_blks); -bool hubp1_program_surface_flip_and_addr( - struct hubp *hubp, - const struct dc_plane_address *address, - bool flip_immediate); - bool hubp1_is_flip_pending(struct hubp *hubp); void hubp1_cursor_set_attributes( @@ -745,5 +740,7 @@ void hubp1_clear_underflow(struct hubp *hubp); enum cursor_pitch hubp1_get_cursor_pitch(unsigned int pitch); +void hubp1_vready_workaround(struct hubp *hubp, + struct _vcs_dpi_display_pipe_dest_params_st *pipe_dest); #endif diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 91e015e14355..9cde24dbdac8 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -40,7 +40,6 @@ #include "ipp.h" #include "mpc.h" #include "reg_helper.h" -#include "custom_float.h" #include "dcn10_hubp.h" #include "dcn10_hubbub.h" #include "dcn10_cm_common.h" @@ -92,10 +91,11 @@ static void log_mpc_crc(struct dc *dc, void dcn10_log_hubbub_state(struct dc *dc, struct dc_log_buffer_ctx *log_ctx) { struct dc_context *dc_ctx = dc->ctx; - struct dcn_hubbub_wm wm = {0}; + struct dcn_hubbub_wm wm; int i; - hubbub1_wm_read_state(dc->res_pool->hubbub, &wm); + memset(&wm, 0, sizeof(struct dcn_hubbub_wm)); + dc->res_pool->hubbub->funcs->wm_read_state(dc->res_pool->hubbub, &wm); DTN_INFO("HUBBUB WM: data_urgent pte_meta_urgent" " sr_enter sr_exit dram_clk_change\n"); @@ -1202,7 +1202,8 @@ static void dcn10_update_plane_addr(const struct dc *dc, struct pipe_ctx *pipe_c pipe_ctx->plane_res.hubp->funcs->hubp_program_surface_flip_and_addr( pipe_ctx->plane_res.hubp, &plane_state->address, - plane_state->flip_immediate); + plane_state->flip_immediate, + 0); plane_state->status.requested_address = plane_state->address; @@ -2048,7 +2049,7 @@ void update_dchubp_dpp( dc->res_pool->dccg->funcs->update_dpp_dto( dc->res_pool->dccg, dpp->inst, - pipe_ctx->plane_res.bw.calc.dppclk_khz); + pipe_ctx->plane_res.bw.dppclk_khz); else dc->res_pool->clk_mgr->clks.dppclk_khz = should_divided_by_2 ? dc->res_pool->clk_mgr->clks.dispclk_khz / 2 : @@ -2125,7 +2126,8 @@ void update_dchubp_dpp( plane_state->update_flags.bits.swizzle_change || plane_state->update_flags.bits.dcc_change || plane_state->update_flags.bits.bpp_change || - plane_state->update_flags.bits.scaling_change) { + plane_state->update_flags.bits.scaling_change || + plane_state->update_flags.bits.plane_size_change) { hubp->funcs->hubp_program_surface_config( hubp, plane_state->format, @@ -2252,13 +2254,11 @@ static void program_all_pipe_in_tree( } - if (pipe_ctx->plane_state != NULL) { + if (pipe_ctx->plane_state != NULL) dcn10_program_pipe(dc, pipe_ctx, context); - } - if (pipe_ctx->bottom_pipe != NULL && pipe_ctx->bottom_pipe != pipe_ctx) { + if (pipe_ctx->bottom_pipe != NULL && pipe_ctx->bottom_pipe != pipe_ctx) program_all_pipe_in_tree(dc, pipe_ctx->bottom_pipe, context); - } } struct pipe_ctx *find_top_pipe_for_stream( @@ -2355,29 +2355,22 @@ static void dcn10_apply_ctx_for_surface( top_pipe_to_program->plane_state->update_flags.bits.full_update) for (i = 0; i < dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; - + tg = pipe_ctx->stream_res.tg; /* Skip inactive pipes and ones already updated */ if (!pipe_ctx->stream || pipe_ctx->stream == stream - || !pipe_ctx->plane_state) + || !pipe_ctx->plane_state + || !tg->funcs->is_tg_enabled(tg)) continue; - pipe_ctx->stream_res.tg->funcs->lock(pipe_ctx->stream_res.tg); + tg->funcs->lock(tg); pipe_ctx->plane_res.hubp->funcs->hubp_setup_interdependent( pipe_ctx->plane_res.hubp, &pipe_ctx->dlg_regs, &pipe_ctx->ttu_regs); - } - for (i = 0; i < dc->res_pool->pipe_count; i++) { - struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; - - if (!pipe_ctx->stream || pipe_ctx->stream == stream - || !pipe_ctx->plane_state) - continue; - - dcn10_pipe_control_lock(dc, pipe_ctx, false); - } + tg->funcs->unlock(tg); + } if (num_planes == 0) false_optc_underflow_wa(dc, stream, tg); @@ -2525,7 +2518,7 @@ static void dcn10_config_stereo_parameters( timing_3d_format == TIMING_3D_FORMAT_DP_HDMI_INBAND_FA || timing_3d_format == TIMING_3D_FORMAT_SIDEBAND_FA) { enum display_dongle_type dongle = \ - stream->sink->link->ddc->dongle_type; + stream->link->ddc->dongle_type; if (dongle == DISPLAY_DONGLE_DP_VGA_CONVERTER || dongle == DISPLAY_DONGLE_DP_DVI_CONVERTER || dongle == DISPLAY_DONGLE_DP_HDMI_CONVERTER) @@ -2656,7 +2649,7 @@ static void dcn10_set_cursor_position(struct pipe_ctx *pipe_ctx) struct hubp *hubp = pipe_ctx->plane_res.hubp; struct dpp *dpp = pipe_ctx->plane_res.dpp; struct dc_cursor_mi_param param = { - .pixel_clk_khz = pipe_ctx->stream->timing.pix_clk_khz, + .pixel_clk_khz = pipe_ctx->stream->timing.pix_clk_100hz / 10, .ref_clk_khz = pipe_ctx->stream->ctx->dc->res_pool->ref_clock_inKhz, .viewport = pipe_ctx->plane_res.scl_data.viewport, .h_scale_ratio = pipe_ctx->plane_res.scl_data.ratios.horz, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer_debug.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer_debug.c index cd469014baa3..98f41d250978 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer_debug.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer_debug.c @@ -40,7 +40,6 @@ #include "ipp.h" #include "mpc.h" #include "reg_helper.h" -#include "custom_float.h" #include "dcn10_hubp.h" #include "dcn10_hubbub.h" #include "dcn10_cm_common.h" @@ -72,7 +71,7 @@ static unsigned int snprintf_count(char *pBuf, unsigned int bufSize, char *fmt, static unsigned int dcn10_get_hubbub_state(struct dc *dc, char *pBuf, unsigned int bufSize) { struct dc_context *dc_ctx = dc->ctx; - struct dcn_hubbub_wm wm = {0}; + struct dcn_hubbub_wm wm; int i; unsigned int chars_printed = 0; @@ -81,7 +80,8 @@ static unsigned int dcn10_get_hubbub_state(struct dc *dc, char *pBuf, unsigned i const uint32_t ref_clk_mhz = dc_ctx->dc->res_pool->ref_clock_inKhz / 1000; static const unsigned int frac = 1000; - hubbub1_wm_read_state(dc->res_pool->hubbub, &wm); + memset(&wm, 0, sizeof(struct dcn_hubbub_wm)); + dc->res_pool->hubbub->funcs->wm_read_state(dc->res_pool->hubbub, &wm); chars_printed = snprintf_count(pBuf, remaining_buffer, "wm_set_index,data_urgent,pte_meta_urgent,sr_enter,sr_exit,dram_clk_chanage\n"); remaining_buffer -= chars_printed; @@ -419,20 +419,22 @@ static unsigned int dcn10_get_otg_states(struct dc *dc, char *pBuf, unsigned int unsigned int remaining_buffer = bufSize; chars_printed = snprintf_count(pBuf, remaining_buffer, "instance,v_bs,v_be,v_ss,v_se,vpol,vmax,vmin,vmax_sel,vmin_sel," - "h_bs,h_be,h_ss,h_se,hpol,htot,vtot,underflow\n"); + "h_bs,h_be,h_ss,h_se,hpol,htot,vtot,underflow,pixelclk[khz]\n"); remaining_buffer -= chars_printed; pBuf += chars_printed; for (i = 0; i < pool->timing_generator_count; i++) { struct timing_generator *tg = pool->timing_generators[i]; struct dcn_otg_state s = {0}; + int pix_clk = 0; optc1_read_otg_state(DCN10TG_FROM_TG(tg), &s); + pix_clk = dc->current_state->res_ctx.pipe_ctx[i].stream_res.pix_clk_params.requested_pix_clk_100hz / 10; //only print if OTG master is enabled if (s.otg_enabled & 1) { chars_printed = snprintf_count(pBuf, remaining_buffer, "%x,%d,%d,%d,%d,%d,%d,%d,%d,%d," - "%d,%d,%d,%d,%d,%d,%d,%d" + "%d,%d,%d,%d,%d,%d,%d,%d,%d" "\n", tg->inst, s.v_blank_start, @@ -451,7 +453,8 @@ static unsigned int dcn10_get_otg_states(struct dc *dc, char *pBuf, unsigned int s.h_sync_a_pol, s.h_total, s.v_total, - s.underflow_occurred_status); + s.underflow_occurred_status, + pix_clk); remaining_buffer -= chars_printed; pBuf += chars_printed; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.c index 477ab9222216..771449f8984f 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.c @@ -440,7 +440,7 @@ static uint8_t get_frontend_source( } } -void configure_encoder( +void enc1_configure_encoder( struct dcn10_link_encoder *enc10, const struct dc_link_settings *link_settings) { @@ -543,12 +543,12 @@ bool dcn10_link_encoder_validate_dvi_output( if ((connector_signal == SIGNAL_TYPE_DVI_SINGLE_LINK || connector_signal == SIGNAL_TYPE_HDMI_TYPE_A) && signal != SIGNAL_TYPE_HDMI_TYPE_A && - crtc_timing->pix_clk_khz > TMDS_MAX_PIXEL_CLOCK) + crtc_timing->pix_clk_100hz > (TMDS_MAX_PIXEL_CLOCK * 10)) return false; - if (crtc_timing->pix_clk_khz < TMDS_MIN_PIXEL_CLOCK) + if (crtc_timing->pix_clk_100hz < (TMDS_MIN_PIXEL_CLOCK * 10)) return false; - if (crtc_timing->pix_clk_khz > max_pixel_clock) + if (crtc_timing->pix_clk_100hz > (max_pixel_clock * 10)) return false; /* DVI supports 6/8bpp single-link and 10/16bpp dual-link */ @@ -571,7 +571,7 @@ bool dcn10_link_encoder_validate_dvi_output( static bool dcn10_link_encoder_validate_hdmi_output( const struct dcn10_link_encoder *enc10, const struct dc_crtc_timing *crtc_timing, - int adjusted_pix_clk_khz) + int adjusted_pix_clk_100hz) { enum dc_color_depth max_deep_color = enc10->base.features.max_hdmi_deep_color; @@ -581,11 +581,11 @@ static bool dcn10_link_encoder_validate_hdmi_output( if (crtc_timing->display_color_depth < COLOR_DEPTH_888) return false; - if (adjusted_pix_clk_khz < TMDS_MIN_PIXEL_CLOCK) + if (adjusted_pix_clk_100hz < (TMDS_MIN_PIXEL_CLOCK * 10)) return false; - if ((adjusted_pix_clk_khz == 0) || - (adjusted_pix_clk_khz > enc10->base.features.max_hdmi_pixel_clock)) + if ((adjusted_pix_clk_100hz == 0) || + (adjusted_pix_clk_100hz > (enc10->base.features.max_hdmi_pixel_clock * 10))) return false; /* DCE11 HW does not support 420 */ @@ -594,7 +594,7 @@ static bool dcn10_link_encoder_validate_hdmi_output( return false; if (!enc10->base.features.flags.bits.HDMI_6GB_EN && - adjusted_pix_clk_khz >= 300000) + adjusted_pix_clk_100hz >= 3000000) return false; if (enc10->base.ctx->dc->debug.hdmi20_disable && crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) @@ -738,7 +738,7 @@ bool dcn10_link_encoder_validate_output_with_stream( case SIGNAL_TYPE_DVI_DUAL_LINK: is_valid = dcn10_link_encoder_validate_dvi_output( enc10, - stream->sink->link->connector_signal, + stream->link->connector_signal, stream->signal, &stream->timing); break; @@ -746,7 +746,7 @@ bool dcn10_link_encoder_validate_output_with_stream( is_valid = dcn10_link_encoder_validate_hdmi_output( enc10, &stream->timing, - stream->phy_pix_clk); + stream->phy_pix_clk * 10); break; case SIGNAL_TYPE_DISPLAY_PORT: case SIGNAL_TYPE_DISPLAY_PORT_MST: @@ -910,7 +910,7 @@ void dcn10_link_encoder_enable_dp_output( * but it's not passed to asic_control. * We need to set number of lanes manually. */ - configure_encoder(enc10, link_settings); + enc1_configure_encoder(enc10, link_settings); cntl.action = TRANSMITTER_CONTROL_ENABLE; cntl.engine_id = enc->preferred_engine; @@ -949,7 +949,7 @@ void dcn10_link_encoder_enable_dp_mst_output( * but it's not passed to asic_control. * We need to set number of lanes manually. */ - configure_encoder(enc10, link_settings); + enc1_configure_encoder(enc10, link_settings); cntl.action = TRANSMITTER_CONTROL_ENABLE; cntl.engine_id = ENGINE_ID_UNKNOWN; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.h index 49ead12b2532..670b46e887ed 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.h @@ -271,7 +271,7 @@ void dcn10_link_encoder_setup( struct link_encoder *enc, enum signal_type signal); -void configure_encoder( +void enc1_configure_encoder( struct dcn10_link_encoder *enc10, const struct dc_link_settings *link_settings); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c index 7c138615f17d..eb019d404928 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c @@ -102,14 +102,6 @@ static uint32_t get_start_vline(struct timing_generator *optc, const struct dc_c patched_crtc_timing = *dc_crtc_timing; optc1_apply_front_porch_workaround(optc, &patched_crtc_timing); - vesa_sync_start = patched_crtc_timing.h_addressable + - patched_crtc_timing.h_border_right + - patched_crtc_timing.h_front_porch; - - asic_blank_end = patched_crtc_timing.h_total - - vesa_sync_start - - patched_crtc_timing.h_border_left; - vesa_sync_start = patched_crtc_timing.v_addressable + patched_crtc_timing.v_border_bottom + patched_crtc_timing.v_front_porch; @@ -119,10 +111,8 @@ static uint32_t get_start_vline(struct timing_generator *optc, const struct dc_c patched_crtc_timing.v_border_top); vertical_line_start = asic_blank_end - optc->dlg_otg_param.vstartup_start + 1; - if (vertical_line_start < 0) { - ASSERT(0); + if (vertical_line_start < 0) vertical_line_start = 0; - } return vertical_line_start; } @@ -136,14 +126,14 @@ void optc1_program_vline_interrupt( struct optc *optc1 = DCN10TG_FROM_TG(optc); unsigned long long req_delta_tens_of_usec = div64_u64((vsync_delta + 9999), 10000); - unsigned long long pix_clk_hundreds_khz = div64_u64((dc_crtc_timing->pix_clk_khz + 99), 100); + unsigned long long pix_clk_hundreds_khz = div64_u64((dc_crtc_timing->pix_clk_100hz + 999), 1000); uint32_t req_delta_lines = (uint32_t) div64_u64( (req_delta_tens_of_usec * pix_clk_hundreds_khz + dc_crtc_timing->h_total - 1), dc_crtc_timing->h_total); uint32_t vsync_line = get_start_vline(optc, dc_crtc_timing); uint32_t start_line = 0; - uint32_t endLine = 0; + uint32_t end_line = 0; if (req_delta_lines != 0) req_delta_lines--; @@ -153,14 +143,17 @@ void optc1_program_vline_interrupt( else start_line = vsync_line - req_delta_lines; - endLine = start_line + 2; + end_line = start_line + 2; - if (endLine >= dc_crtc_timing->v_total) - endLine = 2; + if (start_line >= dc_crtc_timing->v_total) + start_line = start_line % dc_crtc_timing->v_total; + + if (end_line >= dc_crtc_timing->v_total) + end_line = end_line % dc_crtc_timing->v_total; REG_SET_2(OTG_VERTICAL_INTERRUPT0_POSITION, 0, OTG_VERTICAL_INTERRUPT0_LINE_START, start_line, - OTG_VERTICAL_INTERRUPT0_LINE_END, endLine); + OTG_VERTICAL_INTERRUPT0_LINE_END, end_line); } /** @@ -299,16 +292,17 @@ void optc1_program_timing( } /* Interlace */ - if (patched_crtc_timing.flags.INTERLACE == 1) { - REG_UPDATE(OTG_INTERLACE_CONTROL, - OTG_INTERLACE_ENABLE, 1); - v_init = v_init / 2; - if ((optc->dlg_otg_param.vstartup_start/2)*2 > asic_blank_end) - v_fp2 = v_fp2 / 2; - } else - REG_UPDATE(OTG_INTERLACE_CONTROL, - OTG_INTERLACE_ENABLE, 0); - + if (REG(OTG_INTERLACE_CONTROL)) { + if (patched_crtc_timing.flags.INTERLACE == 1) { + REG_UPDATE(OTG_INTERLACE_CONTROL, + OTG_INTERLACE_ENABLE, 1); + v_init = v_init / 2; + if ((optc->dlg_otg_param.vstartup_start/2)*2 > asic_blank_end) + v_fp2 = v_fp2 / 2; + } else + REG_UPDATE(OTG_INTERLACE_CONTROL, + OTG_INTERLACE_ENABLE, 0); + } /* VTG enable set to 0 first VInit */ REG_UPDATE(CONTROL, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 5d4772dec0ba..09d74070a49b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -70,7 +70,7 @@ const struct _vcs_dpi_ip_params_st dcn1_0_ip = { .rob_buffer_size_kbytes = 64, .det_buffer_size_kbytes = 164, - .dpte_buffer_size_in_pte_reqs = 42, + .dpte_buffer_size_in_pte_reqs_luma = 42, .dpp_output_buffer_pixels = 2560, .opp_output_buffer_lines = 1, .pixel_chunk_size_kbytes = 8, @@ -436,7 +436,6 @@ static const struct dcn_optc_mask tg_mask = { }; static const struct bios_registers bios_regs = { - NBIO_SR(BIOS_SCRATCH_0), NBIO_SR(BIOS_SCRATCH_3), NBIO_SR(BIOS_SCRATCH_6) }; @@ -609,7 +608,7 @@ static struct output_pixel_processor *dcn10_opp_create( return &opp->base; } -struct aux_engine *dcn10_aux_engine_create( +struct dce_aux *dcn10_aux_engine_create( struct dc_context *ctx, uint32_t inst) { @@ -678,18 +677,18 @@ static struct mpc *dcn10_mpc_create(struct dc_context *ctx) static struct hubbub *dcn10_hubbub_create(struct dc_context *ctx) { - struct hubbub *hubbub = kzalloc(sizeof(struct hubbub), + struct dcn10_hubbub *dcn10_hubbub = kzalloc(sizeof(struct dcn10_hubbub), GFP_KERNEL); - if (!hubbub) + if (!dcn10_hubbub) return NULL; - hubbub1_construct(hubbub, ctx, + hubbub1_construct(&dcn10_hubbub->base, ctx, &hubbub_reg, &hubbub_shift, &hubbub_mask); - return hubbub; + return &dcn10_hubbub->base; } static struct timing_generator *dcn10_timing_generator_create( @@ -911,7 +910,7 @@ static void destruct(struct dcn10_resource_pool *pool) for (i = 0; i < pool->base.res_cap->num_ddc; i++) { if (pool->base.engines[i] != NULL) - pool->base.engines[i]->funcs->destroy_engine(&pool->base.engines[i]); + dce110_engine_destroy(&pool->base.engines[i]); if (pool->base.hw_i2cs[i] != NULL) { kfree(pool->base.hw_i2cs[i]); pool->base.hw_i2cs[i] = NULL; @@ -974,8 +973,8 @@ static void get_pixel_clock_parameters( struct pixel_clk_params *pixel_clk_params) { const struct dc_stream_state *stream = pipe_ctx->stream; - pixel_clk_params->requested_pix_clk = stream->timing.pix_clk_khz; - pixel_clk_params->encoder_object_id = stream->sink->link->link_enc->id; + pixel_clk_params->requested_pix_clk_100hz = stream->timing.pix_clk_100hz; + pixel_clk_params->encoder_object_id = stream->link->link_enc->id; pixel_clk_params->signal_type = pipe_ctx->stream->signal; pixel_clk_params->controller_id = pipe_ctx->stream_res.tg->inst + 1; /* TODO: un-hardcode*/ @@ -991,9 +990,9 @@ static void get_pixel_clock_parameters( pixel_clk_params->color_depth = COLOR_DEPTH_888; if (stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420) - pixel_clk_params->requested_pix_clk /= 2; + pixel_clk_params->requested_pix_clk_100hz /= 2; if (stream->timing.timing_3d_format == TIMING_3D_FORMAT_HW_FRAME_PACKING) - pixel_clk_params->requested_pix_clk *= 2; + pixel_clk_params->requested_pix_clk_100hz *= 2; } @@ -1131,6 +1130,56 @@ static enum dc_status dcn10_validate_plane(const struct dc_plane_state *plane_st return DC_OK; } +static enum dc_status dcn10_validate_global(struct dc *dc, struct dc_state *context) +{ + int i, j; + bool video_down_scaled = false; + bool video_large = false; + bool desktop_large = false; + bool dcc_disabled = false; + + for (i = 0; i < context->stream_count; i++) { + if (context->stream_status[i].plane_count == 0) + continue; + + if (context->stream_status[i].plane_count > 2) + return false; + + for (j = 0; j < context->stream_status[i].plane_count; j++) { + struct dc_plane_state *plane = + context->stream_status[i].plane_states[j]; + + + if (plane->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) { + + if (plane->src_rect.width > plane->dst_rect.width || + plane->src_rect.height > plane->dst_rect.height) + video_down_scaled = true; + + if (plane->src_rect.width >= 3840) + video_large = true; + + } else { + if (plane->src_rect.width >= 3840) + desktop_large = true; + if (!plane->dcc.enable) + dcc_disabled = true; + } + } + } + + /* + * Workaround: On DCN10 there is UMC issue that causes underflow when + * playing 4k video on 4k desktop with video downscaled and single channel + * memory + */ + if (video_large && desktop_large && video_down_scaled && dcc_disabled && + dc->dcn_soc->number_of_channels == 1) + return DC_FAIL_SURFACE_VALIDATE; + + return DC_OK; +} + static enum dc_status dcn10_get_default_swizzle_mode(struct dc_plane_state *plane_state) { enum dc_status result = DC_OK; @@ -1159,6 +1208,7 @@ static const struct resource_funcs dcn10_res_pool_funcs = { .validate_bandwidth = dcn_validate_bandwidth, .acquire_idle_pipe_for_layer = dcn10_acquire_idle_pipe_for_layer, .validate_plane = dcn10_validate_plane, + .validate_global = dcn10_validate_global, .add_stream_to_ctx = dcn10_add_stream_to_ctx, .get_default_swizzle_mode = dcn10_get_default_swizzle_mode }; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c index b8b5525a389a..b08254121251 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c @@ -261,17 +261,29 @@ void enc1_stream_encoder_dp_set_stream_attribute( uint8_t dp_component_depth = 0; struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + struct dc_crtc_timing hw_crtc_timing = *crtc_timing; + + if (hw_crtc_timing.flags.INTERLACE) { + /*the input timing is in VESA spec format with Interlace flag =1*/ + hw_crtc_timing.v_total /= 2; + hw_crtc_timing.v_border_top /= 2; + hw_crtc_timing.v_addressable /= 2; + hw_crtc_timing.v_border_bottom /= 2; + hw_crtc_timing.v_front_porch /= 2; + hw_crtc_timing.v_sync_width /= 2; + } + /* set pixel encoding */ - switch (crtc_timing->pixel_encoding) { + switch (hw_crtc_timing.pixel_encoding) { case PIXEL_ENCODING_YCBCR422: dp_pixel_encoding = DP_PIXEL_ENCODING_TYPE_YCBCR422; break; case PIXEL_ENCODING_YCBCR444: dp_pixel_encoding = DP_PIXEL_ENCODING_TYPE_YCBCR444; - if (crtc_timing->flags.Y_ONLY) - if (crtc_timing->display_color_depth != COLOR_DEPTH_666) + if (hw_crtc_timing.flags.Y_ONLY) + if (hw_crtc_timing.display_color_depth != COLOR_DEPTH_666) /* HW testing only, no use case yet. * Color depth of Y-only could be * 8, 10, 12, 16 bits @@ -299,7 +311,7 @@ void enc1_stream_encoder_dp_set_stream_attribute( * Pixel Encoding/Colorimetry Format and that a Sink device shall ignore MISC1, bit 7, * and MISC0, bits 7:1 (MISC1, bit 7, and MISC0, bits 7:1, become "don't care"). */ - if ((crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) || + if ((hw_crtc_timing.pixel_encoding == PIXEL_ENCODING_YCBCR420) || (output_color_space == COLOR_SPACE_2020_YCBCR) || (output_color_space == COLOR_SPACE_2020_RGB_FULLRANGE) || (output_color_space == COLOR_SPACE_2020_RGB_LIMITEDRANGE)) @@ -308,7 +320,7 @@ void enc1_stream_encoder_dp_set_stream_attribute( misc1 = misc1 & ~0x40; /* set color depth */ - switch (crtc_timing->display_color_depth) { + switch (hw_crtc_timing.display_color_depth) { case COLOR_DEPTH_666: dp_component_depth = DP_COMPONENT_PIXEL_DEPTH_6BPC; break; @@ -336,7 +348,7 @@ void enc1_stream_encoder_dp_set_stream_attribute( /* set dynamic range and YCbCr range */ - switch (crtc_timing->display_color_depth) { + switch (hw_crtc_timing.display_color_depth) { case COLOR_DEPTH_666: colorimetry_bpc = 0; break; @@ -372,9 +384,9 @@ void enc1_stream_encoder_dp_set_stream_attribute( misc0 = misc0 | 0x8; /* bit3=1, bit4=0 */ misc1 = misc1 & ~0x80; /* bit7 = 0*/ dynamic_range_ycbcr = 0; /*bt601*/ - if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) + if (hw_crtc_timing.pixel_encoding == PIXEL_ENCODING_YCBCR422) misc0 = misc0 | 0x2; /* bit2=0, bit1=1 */ - else if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR444) + else if (hw_crtc_timing.pixel_encoding == PIXEL_ENCODING_YCBCR444) misc0 = misc0 | 0x4; /* bit2=1, bit1=0 */ break; case COLOR_SPACE_YCBCR709: @@ -382,9 +394,9 @@ void enc1_stream_encoder_dp_set_stream_attribute( misc0 = misc0 | 0x18; /* bit3=1, bit4=1 */ misc1 = misc1 & ~0x80; /* bit7 = 0*/ dynamic_range_ycbcr = 1; /*bt709*/ - if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) + if (hw_crtc_timing.pixel_encoding == PIXEL_ENCODING_YCBCR422) misc0 = misc0 | 0x2; /* bit2=0, bit1=1 */ - else if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR444) + else if (hw_crtc_timing.pixel_encoding == PIXEL_ENCODING_YCBCR444) misc0 = misc0 | 0x4; /* bit2=1, bit1=0 */ break; case COLOR_SPACE_2020_RGB_LIMITEDRANGE: @@ -414,26 +426,26 @@ void enc1_stream_encoder_dp_set_stream_attribute( * dc_crtc_timing is vesa dmt struct. data from edid */ REG_SET_2(DP_MSA_TIMING_PARAM1, 0, - DP_MSA_HTOTAL, crtc_timing->h_total, - DP_MSA_VTOTAL, crtc_timing->v_total); + DP_MSA_HTOTAL, hw_crtc_timing.h_total, + DP_MSA_VTOTAL, hw_crtc_timing.v_total); /* calculate from vesa timing parameters * h_active_start related to leading edge of sync */ - h_blank = crtc_timing->h_total - crtc_timing->h_border_left - - crtc_timing->h_addressable - crtc_timing->h_border_right; + h_blank = hw_crtc_timing.h_total - hw_crtc_timing.h_border_left - + hw_crtc_timing.h_addressable - hw_crtc_timing.h_border_right; - h_back_porch = h_blank - crtc_timing->h_front_porch - - crtc_timing->h_sync_width; + h_back_porch = h_blank - hw_crtc_timing.h_front_porch - + hw_crtc_timing.h_sync_width; /* start at beginning of left border */ - h_active_start = crtc_timing->h_sync_width + h_back_porch; + h_active_start = hw_crtc_timing.h_sync_width + h_back_porch; - v_active_start = crtc_timing->v_total - crtc_timing->v_border_top - - crtc_timing->v_addressable - crtc_timing->v_border_bottom - - crtc_timing->v_front_porch; + v_active_start = hw_crtc_timing.v_total - hw_crtc_timing.v_border_top - + hw_crtc_timing.v_addressable - hw_crtc_timing.v_border_bottom - + hw_crtc_timing.v_front_porch; /* start at beginning of left border */ @@ -443,20 +455,20 @@ void enc1_stream_encoder_dp_set_stream_attribute( REG_SET_4(DP_MSA_TIMING_PARAM3, 0, DP_MSA_HSYNCWIDTH, - crtc_timing->h_sync_width, + hw_crtc_timing.h_sync_width, DP_MSA_HSYNCPOLARITY, - !crtc_timing->flags.HSYNC_POSITIVE_POLARITY, + !hw_crtc_timing.flags.HSYNC_POSITIVE_POLARITY, DP_MSA_VSYNCWIDTH, - crtc_timing->v_sync_width, + hw_crtc_timing.v_sync_width, DP_MSA_VSYNCPOLARITY, - !crtc_timing->flags.VSYNC_POSITIVE_POLARITY); + !hw_crtc_timing.flags.VSYNC_POSITIVE_POLARITY); /* HWDITH include border or overscan */ REG_SET_2(DP_MSA_TIMING_PARAM4, 0, - DP_MSA_HWIDTH, crtc_timing->h_border_left + - crtc_timing->h_addressable + crtc_timing->h_border_right, - DP_MSA_VHEIGHT, crtc_timing->v_border_top + - crtc_timing->v_addressable + crtc_timing->v_border_bottom); + DP_MSA_HWIDTH, hw_crtc_timing.h_border_left + + hw_crtc_timing.h_addressable + hw_crtc_timing.h_border_right, + DP_MSA_VHEIGHT, hw_crtc_timing.v_border_top + + hw_crtc_timing.v_addressable + hw_crtc_timing.v_border_bottom); } static void enc1_stream_encoder_set_stream_attribute_helper( @@ -594,7 +606,7 @@ void enc1_stream_encoder_dvi_set_stream_attribute( cntl.signal = is_dual_link ? SIGNAL_TYPE_DVI_DUAL_LINK : SIGNAL_TYPE_DVI_SINGLE_LINK; cntl.enable_dp_audio = false; - cntl.pixel_clock = crtc_timing->pix_clk_khz; + cntl.pixel_clock = crtc_timing->pix_clk_100hz / 10; cntl.lanes_number = (is_dual_link) ? LANE_COUNT_EIGHT : LANE_COUNT_FOUR; if (enc1->base.bp->funcs->encoder_control( @@ -1413,6 +1425,14 @@ void enc1_setup_stereo_sync( REG_UPDATE(DIG_FE_CNTL, DIG_STEREOSYNC_GATE_EN, !enable); } +void enc1_dig_connect_to_otg( + struct stream_encoder *enc, + int tg_inst) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + REG_UPDATE(DIG_FE_CNTL, DIG_SOURCE_SELECT, tg_inst); +} static const struct stream_encoder_funcs dcn10_str_enc_funcs = { .dp_set_stream_attribute = @@ -1445,6 +1465,7 @@ static const struct stream_encoder_funcs dcn10_str_enc_funcs = { .hdmi_audio_disable = enc1_se_hdmi_audio_disable, .setup_stereo_sync = enc1_setup_stereo_sync, .set_avmute = enc1_stream_encoder_set_avmute, + .dig_connect_to_otg = enc1_dig_connect_to_otg, }; void dcn10_stream_encoder_construct( diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.h index 67f3e4dd95c1..b7c800e10a32 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.h @@ -274,7 +274,8 @@ struct dcn10_stream_enc_registers { SE_SF(DP0_DP_MSA_TIMING_PARAM4, DP_MSA_HWIDTH, mask_sh),\ SE_SF(DP0_DP_MSA_TIMING_PARAM4, DP_MSA_VHEIGHT, mask_sh),\ SE_SF(DIG0_HDMI_DB_CONTROL, HDMI_DB_DISABLE, mask_sh),\ - SE_SF(DP0_DP_VID_TIMING, DP_VID_N_MUL, mask_sh) + SE_SF(DP0_DP_VID_TIMING, DP_VID_N_MUL, mask_sh),\ + SE_SF(DIG0_DIG_FE_CNTL, DIG_SOURCE_SELECT, mask_sh) #define SE_COMMON_MASK_SH_LIST_SOC(mask_sh)\ SE_COMMON_MASK_SH_LIST_SOC_BASE(mask_sh) @@ -426,7 +427,8 @@ struct dcn10_stream_enc_registers { type DP_MSA_VHEIGHT;\ type HDMI_DB_DISABLE;\ type DP_VID_N_MUL;\ - type DP_VID_M_DOUBLE_VALUE_EN + type DP_VID_M_DOUBLE_VALUE_EN;\ + type DIG_SOURCE_SELECT struct dcn10_stream_encoder_shift { SE_REG_FIELD_LIST_DCN1_0(uint8_t); @@ -523,4 +525,8 @@ void enc1_se_hdmi_audio_setup( void enc1_se_hdmi_audio_disable( struct stream_encoder *enc); +void enc1_dig_connect_to_otg( + struct stream_encoder *enc, + int tg_inst); + #endif /* __DC_STREAM_ENCODER_DCN10_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dm_pp_smu.h b/drivers/gpu/drm/amd/display/dc/dm_pp_smu.h index 0029a39efb1c..14bed5b1fa97 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_pp_smu.h +++ b/drivers/gpu/drm/amd/display/dc/dm_pp_smu.h @@ -38,7 +38,8 @@ enum pp_smu_ver { * of interface sharing between families of ASIcs. */ PP_SMU_UNSUPPORTED, - PP_SMU_VER_RV + PP_SMU_VER_RV, + PP_SMU_VER_MAX }; struct pp_smu { diff --git a/drivers/gpu/drm/amd/display/dc/dm_services_types.h b/drivers/gpu/drm/amd/display/dc/dm_services_types.h index 1af8c777b3ac..77200711abbe 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_services_types.h +++ b/drivers/gpu/drm/amd/display/dc/dm_services_types.h @@ -82,9 +82,17 @@ enum dm_pp_clock_type { #define DC_DECODE_PP_CLOCK_TYPE(clk_type) \ (clk_type) == DM_PP_CLOCK_TYPE_DISPLAY_CLK ? "Display" : \ (clk_type) == DM_PP_CLOCK_TYPE_ENGINE_CLK ? "Engine" : \ - (clk_type) == DM_PP_CLOCK_TYPE_MEMORY_CLK ? "Memory" : "Invalid" - -#define DM_PP_MAX_CLOCK_LEVELS 8 + (clk_type) == DM_PP_CLOCK_TYPE_MEMORY_CLK ? "Memory" : \ + (clk_type) == DM_PP_CLOCK_TYPE_DCFCLK ? "DCF" : \ + (clk_type) == DM_PP_CLOCK_TYPE_DCEFCLK ? "DCEF" : \ + (clk_type) == DM_PP_CLOCK_TYPE_SOCCLK ? "SoC" : \ + (clk_type) == DM_PP_CLOCK_TYPE_PIXELCLK ? "Pixel" : \ + (clk_type) == DM_PP_CLOCK_TYPE_DISPLAYPHYCLK ? "Display PHY" : \ + (clk_type) == DM_PP_CLOCK_TYPE_DPPCLK ? "DPP" : \ + (clk_type) == DM_PP_CLOCK_TYPE_FCLK ? "F" : \ + "Invalid" + +#define DM_PP_MAX_CLOCK_LEVELS 16 struct dm_pp_clock_levels { uint32_t num_levels; diff --git a/drivers/gpu/drm/amd/display/dc/dml/Makefile b/drivers/gpu/drm/amd/display/dc/dml/Makefile index d97ca6528f9d..33c7d7588712 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dml/Makefile @@ -30,7 +30,7 @@ else ifneq ($(call cc-option, -mstack-alignment=16),) cc_stack_align := -mstack-alignment=16 endif -dml_ccflags := -mhard-float -msse $(cc_stack_align) +dml_ccflags := -mhard-float -msse -msse2 $(cc_stack_align) CFLAGS_display_mode_lib.o := $(dml_ccflags) CFLAGS_display_pipe_clocks.o := $(dml_ccflags) diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_enums.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_enums.h index bea4e61b94c7..c59e582c1f40 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_enums.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_enums.h @@ -121,4 +121,30 @@ enum self_refresh_affinity { dm_neither_self_refresh_nor_mclk_switch }; +enum dm_validation_status { + DML_VALIDATION_OK, + DML_FAIL_SCALE_RATIO_TAP, + DML_FAIL_SOURCE_PIXEL_FORMAT, + DML_FAIL_VIEWPORT_SIZE, + DML_FAIL_TOTAL_V_ACTIVE_BW, + DML_FAIL_DIO_SUPPORT, + DML_FAIL_NOT_ENOUGH_DSC, + DML_FAIL_DSC_CLK_REQUIRED, + DML_FAIL_URGENT_LATENCY, + DML_FAIL_REORDERING_BUFFER, + DML_FAIL_DISPCLK_DPPCLK, + DML_FAIL_TOTAL_AVAILABLE_PIPES, + DML_FAIL_NUM_OTG, + DML_FAIL_WRITEBACK_MODE, + DML_FAIL_WRITEBACK_LATENCY, + DML_FAIL_WRITEBACK_SCALE_RATIO_TAP, + DML_FAIL_CURSOR_SUPPORT, + DML_FAIL_PITCH_SUPPORT, + DML_FAIL_PTE_BUFFER_SIZE, + DML_FAIL_HOST_VM_IMMEDIATE_FLIP, + DML_FAIL_DSC_INPUT_BPC, + DML_FAIL_PREFETCH_SUPPORT, + DML_FAIL_V_RATIO_PREFETCH, +}; + #endif diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.c b/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.c index dddeb0d4db8f..d303b789adfe 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.c +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.c @@ -62,3 +62,31 @@ void dml_init_instance(struct display_mode_lib *lib, enum dml_project project) } } +const char *dml_get_status_message(enum dm_validation_status status) +{ + switch (status) { + case DML_VALIDATION_OK: return "Validation OK"; + case DML_FAIL_SCALE_RATIO_TAP: return "Scale ratio/tap"; + case DML_FAIL_SOURCE_PIXEL_FORMAT: return "Source pixel format"; + case DML_FAIL_VIEWPORT_SIZE: return "Viewport size"; + case DML_FAIL_TOTAL_V_ACTIVE_BW: return "Total vertical active bandwidth"; + case DML_FAIL_DIO_SUPPORT: return "DIO support"; + case DML_FAIL_NOT_ENOUGH_DSC: return "Not enough DSC Units"; + case DML_FAIL_DSC_CLK_REQUIRED: return "DSC clock required"; + case DML_FAIL_URGENT_LATENCY: return "Urgent latency"; + case DML_FAIL_REORDERING_BUFFER: return "Re-ordering buffer"; + case DML_FAIL_DISPCLK_DPPCLK: return "Dispclk and Dppclk"; + case DML_FAIL_TOTAL_AVAILABLE_PIPES: return "Total available pipes"; + case DML_FAIL_NUM_OTG: return "Number of OTG"; + case DML_FAIL_WRITEBACK_MODE: return "Writeback mode"; + case DML_FAIL_WRITEBACK_LATENCY: return "Writeback latency"; + case DML_FAIL_WRITEBACK_SCALE_RATIO_TAP: return "Writeback scale ratio/tap"; + case DML_FAIL_CURSOR_SUPPORT: return "Cursor support"; + case DML_FAIL_PITCH_SUPPORT: return "Pitch support"; + case DML_FAIL_PTE_BUFFER_SIZE: return "PTE buffer size"; + case DML_FAIL_DSC_INPUT_BPC: return "DSC input bpc"; + case DML_FAIL_PREFETCH_SUPPORT: return "Prefetch support"; + case DML_FAIL_V_RATIO_PREFETCH: return "Vertical ratio prefetch"; + default: return "Unknown Status"; + } +} diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h index 635206248889..a730e0209c05 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h @@ -43,4 +43,6 @@ struct display_mode_lib { void dml_init_instance(struct display_mode_lib *lib, enum dml_project project); +const char *dml_get_status_message(enum dm_validation_status status); + #endif diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h index 5dd04520ceca..391183e3428f 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h @@ -30,22 +30,15 @@ typedef struct _vcs_dpi_soc_bounding_box_st soc_bounding_box_st; typedef struct _vcs_dpi_ip_params_st ip_params_st; typedef struct _vcs_dpi_display_pipe_source_params_st display_pipe_source_params_st; typedef struct _vcs_dpi_display_output_params_st display_output_params_st; -typedef struct _vcs_dpi_display_bandwidth_st display_bandwidth_st; typedef struct _vcs_dpi_scaler_ratio_depth_st scaler_ratio_depth_st; typedef struct _vcs_dpi_scaler_taps_st scaler_taps_st; typedef struct _vcs_dpi_display_pipe_dest_params_st display_pipe_dest_params_st; typedef struct _vcs_dpi_display_pipe_params_st display_pipe_params_st; typedef struct _vcs_dpi_display_clocks_and_cfg_st display_clocks_and_cfg_st; typedef struct _vcs_dpi_display_e2e_pipe_params_st display_e2e_pipe_params_st; -typedef struct _vcs_dpi_dchub_buffer_sizing_st dchub_buffer_sizing_st; -typedef struct _vcs_dpi_watermarks_perf_st watermarks_perf_st; -typedef struct _vcs_dpi_cstate_pstate_watermarks_st cstate_pstate_watermarks_st; -typedef struct _vcs_dpi_wm_calc_pipe_params_st wm_calc_pipe_params_st; -typedef struct _vcs_dpi_vratio_pre_st vratio_pre_st; typedef struct _vcs_dpi_display_data_rq_misc_params_st display_data_rq_misc_params_st; typedef struct _vcs_dpi_display_data_rq_sizing_params_st display_data_rq_sizing_params_st; typedef struct _vcs_dpi_display_data_rq_dlg_params_st display_data_rq_dlg_params_st; -typedef struct _vcs_dpi_display_cur_rq_dlg_params_st display_cur_rq_dlg_params_st; typedef struct _vcs_dpi_display_rq_dlg_params_st display_rq_dlg_params_st; typedef struct _vcs_dpi_display_rq_sizing_params_st display_rq_sizing_params_st; typedef struct _vcs_dpi_display_rq_misc_params_st display_rq_misc_params_st; @@ -55,8 +48,6 @@ typedef struct _vcs_dpi_display_ttu_regs_st display_ttu_regs_st; typedef struct _vcs_dpi_display_data_rq_regs_st display_data_rq_regs_st; typedef struct _vcs_dpi_display_rq_regs_st display_rq_regs_st; typedef struct _vcs_dpi_display_dlg_sys_params_st display_dlg_sys_params_st; -typedef struct _vcs_dpi_display_dlg_prefetch_param_st display_dlg_prefetch_param_st; -typedef struct _vcs_dpi_display_pipe_clock_st display_pipe_clock_st; typedef struct _vcs_dpi_display_arb_params_st display_arb_params_st; struct _vcs_dpi_voltage_scaling_st { @@ -111,8 +102,6 @@ struct _vcs_dpi_soc_bounding_box_st { double xfc_bus_transport_time_us; double xfc_xbuf_latency_tolerance_us; int use_urgent_burst_bw; - double max_hscl_ratio; - double max_vscl_ratio; unsigned int num_states; struct _vcs_dpi_voltage_scaling_st clock_limits[8]; }; @@ -129,7 +118,8 @@ struct _vcs_dpi_ip_params_st { unsigned int odm_capable; unsigned int rob_buffer_size_kbytes; unsigned int det_buffer_size_kbytes; - unsigned int dpte_buffer_size_in_pte_reqs; + unsigned int dpte_buffer_size_in_pte_reqs_luma; + unsigned int dpte_buffer_size_in_pte_reqs_chroma; unsigned int pde_proc_buffer_size_64k_reqs; unsigned int dpp_output_buffer_pixels; unsigned int opp_output_buffer_lines; @@ -192,7 +182,6 @@ struct _vcs_dpi_display_xfc_params_st { struct _vcs_dpi_display_pipe_source_params_st { int source_format; unsigned char dcc; - unsigned int dcc_override; unsigned int dcc_rate; unsigned char dcc_use_global; unsigned char vm; @@ -205,7 +194,6 @@ struct _vcs_dpi_display_pipe_source_params_st { int source_scan; int sw_mode; int macro_tile_size; - unsigned char is_display_sw; unsigned int viewport_width; unsigned int viewport_height; unsigned int viewport_y_y; @@ -252,16 +240,10 @@ struct _vcs_dpi_display_output_params_st { int output_bpc; int output_type; int output_format; - int output_standard; int dsc_slices; struct writeback_st wb; }; -struct _vcs_dpi_display_bandwidth_st { - double total_bw_consumed_gbps; - double guaranteed_urgent_return_bw_gbps; -}; - struct _vcs_dpi_scaler_ratio_depth_st { double hscl_ratio; double vscl_ratio; @@ -300,11 +282,9 @@ struct _vcs_dpi_display_pipe_dest_params_st { unsigned int vupdate_width; unsigned int vready_offset; unsigned char interlaced; - unsigned char underscan; double pixel_rate_mhz; unsigned char synchronized_vblank_all_planes; unsigned char otg_inst; - unsigned char odm_split_cnt; unsigned char odm_combine; unsigned char use_maximum_vstartup; }; @@ -331,65 +311,6 @@ struct _vcs_dpi_display_e2e_pipe_params_st { display_clocks_and_cfg_st clks_cfg; }; -struct _vcs_dpi_dchub_buffer_sizing_st { - unsigned int swath_width_y; - unsigned int swath_height_y; - unsigned int swath_height_c; - unsigned int detail_buffer_size_y; -}; - -struct _vcs_dpi_watermarks_perf_st { - double stutter_eff_in_active_region_percent; - double urgent_latency_supported_us; - double non_urgent_latency_supported_us; - double dram_clock_change_margin_us; - double dram_access_eff_percent; -}; - -struct _vcs_dpi_cstate_pstate_watermarks_st { - double cstate_exit_us; - double cstate_enter_plus_exit_us; - double pstate_change_us; -}; - -struct _vcs_dpi_wm_calc_pipe_params_st { - unsigned int num_dpp; - int voltage; - int output_type; - double dcfclk_mhz; - double socclk_mhz; - double dppclk_mhz; - double pixclk_mhz; - unsigned char interlace_en; - unsigned char pte_enable; - unsigned char dcc_enable; - double dcc_rate; - double bytes_per_pixel_c; - double bytes_per_pixel_y; - unsigned int swath_width_y; - unsigned int swath_height_y; - unsigned int swath_height_c; - unsigned int det_buffer_size_y; - double h_ratio; - double v_ratio; - unsigned int h_taps; - unsigned int h_total; - unsigned int v_total; - unsigned int v_active; - unsigned int e2e_index; - double display_pipe_line_delivery_time; - double read_bw; - unsigned int lines_in_det_y; - unsigned int lines_in_det_y_rounded_down_to_swath; - double full_det_buffering_time; - double dcfclk_deepsleep_mhz_per_plane; -}; - -struct _vcs_dpi_vratio_pre_st { - double vratio_pre_l; - double vratio_pre_c; -}; - struct _vcs_dpi_display_data_rq_misc_params_st { unsigned int full_swath_bytes; unsigned int stored_swath_bytes; @@ -423,16 +344,9 @@ struct _vcs_dpi_display_data_rq_dlg_params_st { unsigned int meta_bytes_per_row_ub; }; -struct _vcs_dpi_display_cur_rq_dlg_params_st { - unsigned char enable; - unsigned int swath_height; - unsigned int req_per_line; -}; - struct _vcs_dpi_display_rq_dlg_params_st { display_data_rq_dlg_params_st rq_l; display_data_rq_dlg_params_st rq_c; - display_cur_rq_dlg_params_st rq_cur0; }; struct _vcs_dpi_display_rq_sizing_params_st { @@ -498,6 +412,10 @@ struct _vcs_dpi_display_dlg_regs_st { unsigned int xfc_reg_remote_surface_flip_latency; unsigned int xfc_reg_prefetch_margin; unsigned int dst_y_delta_drq_limit; + unsigned int refcyc_per_vm_group_vblank; + unsigned int refcyc_per_vm_group_flip; + unsigned int refcyc_per_vm_req_vblank; + unsigned int refcyc_per_vm_req_flip; }; struct _vcs_dpi_display_ttu_regs_st { @@ -556,19 +474,6 @@ struct _vcs_dpi_display_dlg_sys_params_st { unsigned int total_flip_bytes; }; -struct _vcs_dpi_display_dlg_prefetch_param_st { - double prefetch_bw; - unsigned int flip_bytes; -}; - -struct _vcs_dpi_display_pipe_clock_st { - double dcfclk_mhz; - double dispclk_mhz; - double socclk_mhz; - double dscclk_mhz[6]; - double dppclk_mhz[6]; -}; - struct _vcs_dpi_display_arb_params_st { int max_req_outstanding; int min_req_outstanding; diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c b/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c index c2037daa8e66..ad8571f5a142 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c @@ -459,7 +459,7 @@ static void dml1_rq_dlg_get_row_heights( /* dpte */ /* ------ */ log2_vmpg_bytes = dml_log2(mode_lib->soc.vmm_page_size_bytes); - dpte_buf_in_pte_reqs = mode_lib->ip.dpte_buffer_size_in_pte_reqs; + dpte_buf_in_pte_reqs = mode_lib->ip.dpte_buffer_size_in_pte_reqs_luma; log2_vmpg_height = 0; log2_vmpg_width = 0; @@ -776,7 +776,7 @@ static void get_surf_rq_param( /* dpte */ /* ------ */ log2_vmpg_bytes = dml_log2(mode_lib->soc.vmm_page_size_bytes); - dpte_buf_in_pte_reqs = mode_lib->ip.dpte_buffer_size_in_pte_reqs; + dpte_buf_in_pte_reqs = mode_lib->ip.dpte_buffer_size_in_pte_reqs_luma; log2_vmpg_height = 0; log2_vmpg_width = 0; @@ -881,7 +881,7 @@ static void get_surf_rq_param( /* the dpte_group_bytes is reduced for the specific case of vertical * access of a tile surface that has dpte request of 8x1 ptes. */ - if (!surf_linear & (log2_dpte_req_height_ptes == 0) & surf_vert) /*reduced, in this case, will have page fault within a group */ + if (!surf_linear && (log2_dpte_req_height_ptes == 0) && surf_vert) /*reduced, in this case, will have page fault within a group */ rq_sizing_param->dpte_group_bytes = 512; else /*full size */ diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/Makefile b/drivers/gpu/drm/amd/display/dc/i2caux/Makefile deleted file mode 100644 index 352885cb4d07..000000000000 --- a/drivers/gpu/drm/amd/display/dc/i2caux/Makefile +++ /dev/null @@ -1,99 +0,0 @@ -# -# Copyright 2017 Advanced Micro Devices, Inc. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the "Software"), -# to deal in the Software without restriction, including without limitation -# the rights to use, copy, modify, merge, publish, distribute, sublicense, -# and/or sell copies of the Software, and to permit persons to whom the -# Software is furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -# THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -# OTHER DEALINGS IN THE SOFTWARE. -# -# -# Makefile for the 'i2c' sub-component of DAL. -# It provides the control and status of HW i2c engine of the adapter. - -I2CAUX = aux_engine.o engine_base.o i2caux.o i2c_engine.o \ - i2c_generic_hw_engine.o i2c_hw_engine.o i2c_sw_engine.o - -AMD_DAL_I2CAUX = $(addprefix $(AMDDALPATH)/dc/i2caux/,$(I2CAUX)) - -AMD_DISPLAY_FILES += $(AMD_DAL_I2CAUX) - -############################################################################### -# DCE 8x family -############################################################################### -I2CAUX_DCE80 = i2caux_dce80.o i2c_hw_engine_dce80.o \ - i2c_sw_engine_dce80.o - -AMD_DAL_I2CAUX_DCE80 = $(addprefix $(AMDDALPATH)/dc/i2caux/dce80/,$(I2CAUX_DCE80)) - -AMD_DISPLAY_FILES += $(AMD_DAL_I2CAUX_DCE80) - -############################################################################### -# DCE 100 family -############################################################################### -I2CAUX_DCE100 = i2caux_dce100.o - -AMD_DAL_I2CAUX_DCE100 = $(addprefix $(AMDDALPATH)/dc/i2caux/dce100/,$(I2CAUX_DCE100)) - -AMD_DISPLAY_FILES += $(AMD_DAL_I2CAUX_DCE100) - -############################################################################### -# DCE 110 family -############################################################################### -I2CAUX_DCE110 = i2caux_dce110.o i2c_sw_engine_dce110.o i2c_hw_engine_dce110.o \ - aux_engine_dce110.o - -AMD_DAL_I2CAUX_DCE110 = $(addprefix $(AMDDALPATH)/dc/i2caux/dce110/,$(I2CAUX_DCE110)) - -AMD_DISPLAY_FILES += $(AMD_DAL_I2CAUX_DCE110) - -############################################################################### -# DCE 112 family -############################################################################### -I2CAUX_DCE112 = i2caux_dce112.o - -AMD_DAL_I2CAUX_DCE112 = $(addprefix $(AMDDALPATH)/dc/i2caux/dce112/,$(I2CAUX_DCE112)) - -AMD_DISPLAY_FILES += $(AMD_DAL_I2CAUX_DCE112) - -############################################################################### -# DCN 1.0 family -############################################################################### -ifdef CONFIG_DRM_AMD_DC_DCN1_0 -I2CAUX_DCN1 = i2caux_dcn10.o - -AMD_DAL_I2CAUX_DCN1 = $(addprefix $(AMDDALPATH)/dc/i2caux/dcn10/,$(I2CAUX_DCN1)) - -AMD_DISPLAY_FILES += $(AMD_DAL_I2CAUX_DCN1) -endif - -############################################################################### -# DCE 120 family -############################################################################### -I2CAUX_DCE120 = i2caux_dce120.o - -AMD_DAL_I2CAUX_DCE120 = $(addprefix $(AMDDALPATH)/dc/i2caux/dce120/,$(I2CAUX_DCE120)) - -AMD_DISPLAY_FILES += $(AMD_DAL_I2CAUX_DCE120) - -############################################################################### -# Diagnostics on FPGA -############################################################################### -I2CAUX_DIAG = i2caux_diag.o - -AMD_DAL_I2CAUX_DIAG = $(addprefix $(AMDDALPATH)/dc/i2caux/diagnostics/,$(I2CAUX_DIAG)) - -AMD_DISPLAY_FILES += $(AMD_DAL_I2CAUX_DIAG) - diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.c b/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.c deleted file mode 100644 index 8cbf38b2470d..000000000000 --- a/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.c +++ /dev/null @@ -1,606 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" -#include "dm_event_log.h" - -/* - * Pre-requisites: headers required by header of this unit - */ -#include "include/i2caux_interface.h" -#include "engine.h" - -/* - * Header of this unit - */ - -#include "aux_engine.h" - -/* - * Post-requisites: headers required by this unit - */ - -#include "include/link_service_types.h" - -/* - * This unit - */ - -enum { - AUX_INVALID_REPLY_RETRY_COUNTER = 1, - AUX_TIMED_OUT_RETRY_COUNTER = 2, - AUX_DEFER_RETRY_COUNTER = 6 -}; - -#define FROM_ENGINE(ptr) \ - container_of((ptr), struct aux_engine, base) -#define DC_LOGGER \ - engine->base.ctx->logger - -enum i2caux_engine_type dal_aux_engine_get_engine_type( - const struct engine *engine) -{ - return I2CAUX_ENGINE_TYPE_AUX; -} - -bool dal_aux_engine_acquire( - struct engine *engine, - struct ddc *ddc) -{ - struct aux_engine *aux_engine = FROM_ENGINE(engine); - - enum gpio_result result; - if (aux_engine->funcs->is_engine_available) { - /*check whether SW could use the engine*/ - if (!aux_engine->funcs->is_engine_available(aux_engine)) { - return false; - } - } - - result = dal_ddc_open(ddc, GPIO_MODE_HARDWARE, - GPIO_DDC_CONFIG_TYPE_MODE_AUX); - - if (result != GPIO_RESULT_OK) - return false; - - if (!aux_engine->funcs->acquire_engine(aux_engine)) { - dal_ddc_close(ddc); - return false; - } - - engine->ddc = ddc; - - return true; -} - -struct read_command_context { - uint8_t *buffer; - uint32_t current_read_length; - uint32_t offset; - enum i2caux_transaction_status status; - - struct aux_request_transaction_data request; - struct aux_reply_transaction_data reply; - - uint8_t returned_byte; - - uint32_t timed_out_retry_aux; - uint32_t invalid_reply_retry_aux; - uint32_t defer_retry_aux; - uint32_t defer_retry_i2c; - uint32_t invalid_reply_retry_aux_on_ack; - - bool transaction_complete; - bool operation_succeeded; -}; - -static void process_read_reply( - struct aux_engine *engine, - struct read_command_context *ctx) -{ - engine->funcs->process_channel_reply(engine, &ctx->reply); - - switch (ctx->reply.status) { - case AUX_TRANSACTION_REPLY_AUX_ACK: - ctx->defer_retry_aux = 0; - if (ctx->returned_byte > ctx->current_read_length) { - ctx->status = - I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR; - ctx->operation_succeeded = false; - } else if (ctx->returned_byte < ctx->current_read_length) { - ctx->current_read_length -= ctx->returned_byte; - - ctx->offset += ctx->returned_byte; - - ++ctx->invalid_reply_retry_aux_on_ack; - - if (ctx->invalid_reply_retry_aux_on_ack > - AUX_INVALID_REPLY_RETRY_COUNTER) { - ctx->status = - I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR; - ctx->operation_succeeded = false; - } - } else { - ctx->status = I2CAUX_TRANSACTION_STATUS_SUCCEEDED; - ctx->transaction_complete = true; - ctx->operation_succeeded = true; - } - break; - case AUX_TRANSACTION_REPLY_AUX_NACK: - ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_NACK; - ctx->operation_succeeded = false; - break; - case AUX_TRANSACTION_REPLY_AUX_DEFER: - ++ctx->defer_retry_aux; - - if (ctx->defer_retry_aux > AUX_DEFER_RETRY_COUNTER) { - ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT; - ctx->operation_succeeded = false; - } - break; - case AUX_TRANSACTION_REPLY_I2C_DEFER: - ctx->defer_retry_aux = 0; - - ++ctx->defer_retry_i2c; - - if (ctx->defer_retry_i2c > AUX_DEFER_RETRY_COUNTER) { - ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT; - ctx->operation_succeeded = false; - } - break; - case AUX_TRANSACTION_REPLY_HPD_DISCON: - ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_HPD_DISCON; - ctx->operation_succeeded = false; - break; - default: - ctx->status = I2CAUX_TRANSACTION_STATUS_UNKNOWN; - ctx->operation_succeeded = false; - } -} - -static void process_read_request( - struct aux_engine *engine, - struct read_command_context *ctx) -{ - enum aux_channel_operation_result operation_result; - - engine->funcs->submit_channel_request(engine, &ctx->request); - - operation_result = engine->funcs->get_channel_status( - engine, &ctx->returned_byte); - - switch (operation_result) { - case AUX_CHANNEL_OPERATION_SUCCEEDED: - if (ctx->returned_byte > ctx->current_read_length) { - ctx->status = - I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR; - ctx->operation_succeeded = false; - } else { - ctx->timed_out_retry_aux = 0; - ctx->invalid_reply_retry_aux = 0; - - ctx->reply.length = ctx->returned_byte; - ctx->reply.data = ctx->buffer; - - process_read_reply(engine, ctx); - } - break; - case AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY: - ++ctx->invalid_reply_retry_aux; - - if (ctx->invalid_reply_retry_aux > - AUX_INVALID_REPLY_RETRY_COUNTER) { - ctx->status = - I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR; - ctx->operation_succeeded = false; - } else - udelay(400); - break; - case AUX_CHANNEL_OPERATION_FAILED_TIMEOUT: - ++ctx->timed_out_retry_aux; - - if (ctx->timed_out_retry_aux > AUX_TIMED_OUT_RETRY_COUNTER) { - ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT; - ctx->operation_succeeded = false; - } else { - /* DP 1.2a, table 2-58: - * "S3: AUX Request CMD PENDING: - * retry 3 times, with 400usec wait on each" - * The HW timeout is set to 550usec, - * so we should not wait here */ - } - break; - case AUX_CHANNEL_OPERATION_FAILED_HPD_DISCON: - ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_HPD_DISCON; - ctx->operation_succeeded = false; - break; - default: - ctx->status = I2CAUX_TRANSACTION_STATUS_UNKNOWN; - ctx->operation_succeeded = false; - } -} - -static bool read_command( - struct aux_engine *engine, - struct i2caux_transaction_request *request, - bool middle_of_transaction) -{ - struct read_command_context ctx; - - ctx.buffer = request->payload.data; - ctx.current_read_length = request->payload.length; - ctx.offset = 0; - ctx.timed_out_retry_aux = 0; - ctx.invalid_reply_retry_aux = 0; - ctx.defer_retry_aux = 0; - ctx.defer_retry_i2c = 0; - ctx.invalid_reply_retry_aux_on_ack = 0; - ctx.transaction_complete = false; - ctx.operation_succeeded = true; - - if (request->payload.address_space == - I2CAUX_TRANSACTION_ADDRESS_SPACE_DPCD) { - ctx.request.type = AUX_TRANSACTION_TYPE_DP; - ctx.request.action = I2CAUX_TRANSACTION_ACTION_DP_READ; - ctx.request.address = request->payload.address; - } else if (request->payload.address_space == - I2CAUX_TRANSACTION_ADDRESS_SPACE_I2C) { - ctx.request.type = AUX_TRANSACTION_TYPE_I2C; - ctx.request.action = middle_of_transaction ? - I2CAUX_TRANSACTION_ACTION_I2C_READ_MOT : - I2CAUX_TRANSACTION_ACTION_I2C_READ; - ctx.request.address = request->payload.address >> 1; - } else { - /* in DAL2, there was no return in such case */ - BREAK_TO_DEBUGGER(); - return false; - } - - ctx.request.delay = 0; - - do { - memset(ctx.buffer + ctx.offset, 0, ctx.current_read_length); - - ctx.request.data = ctx.buffer + ctx.offset; - ctx.request.length = ctx.current_read_length; - - process_read_request(engine, &ctx); - - request->status = ctx.status; - - if (ctx.operation_succeeded && !ctx.transaction_complete) - if (ctx.request.type == AUX_TRANSACTION_TYPE_I2C) - msleep(engine->delay); - } while (ctx.operation_succeeded && !ctx.transaction_complete); - - if (request->payload.address_space == - I2CAUX_TRANSACTION_ADDRESS_SPACE_DPCD) { - DC_LOG_I2C_AUX("READ: addr:0x%x value:0x%x Result:%d", - request->payload.address, - request->payload.data[0], - ctx.operation_succeeded); - } - - return ctx.operation_succeeded; -} - -struct write_command_context { - bool mot; - - uint8_t *buffer; - uint32_t current_write_length; - enum i2caux_transaction_status status; - - struct aux_request_transaction_data request; - struct aux_reply_transaction_data reply; - - uint8_t returned_byte; - - uint32_t timed_out_retry_aux; - uint32_t invalid_reply_retry_aux; - uint32_t defer_retry_aux; - uint32_t defer_retry_i2c; - uint32_t max_defer_retry; - uint32_t ack_m_retry; - - uint8_t reply_data[DEFAULT_AUX_MAX_DATA_SIZE]; - - bool transaction_complete; - bool operation_succeeded; -}; - -static void process_write_reply( - struct aux_engine *engine, - struct write_command_context *ctx) -{ - engine->funcs->process_channel_reply(engine, &ctx->reply); - - switch (ctx->reply.status) { - case AUX_TRANSACTION_REPLY_AUX_ACK: - ctx->operation_succeeded = true; - - if (ctx->returned_byte) { - ctx->request.action = ctx->mot ? - I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST_MOT : - I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST; - - ctx->current_write_length = 0; - - ++ctx->ack_m_retry; - - if (ctx->ack_m_retry > AUX_DEFER_RETRY_COUNTER) { - ctx->status = - I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT; - ctx->operation_succeeded = false; - } else - udelay(300); - } else { - ctx->status = I2CAUX_TRANSACTION_STATUS_SUCCEEDED; - ctx->defer_retry_aux = 0; - ctx->ack_m_retry = 0; - ctx->transaction_complete = true; - } - break; - case AUX_TRANSACTION_REPLY_AUX_NACK: - ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_NACK; - ctx->operation_succeeded = false; - break; - case AUX_TRANSACTION_REPLY_AUX_DEFER: - ++ctx->defer_retry_aux; - - if (ctx->defer_retry_aux > ctx->max_defer_retry) { - ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT; - ctx->operation_succeeded = false; - } - break; - case AUX_TRANSACTION_REPLY_I2C_DEFER: - ctx->defer_retry_aux = 0; - ctx->current_write_length = 0; - - ctx->request.action = ctx->mot ? - I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST_MOT : - I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST; - - ++ctx->defer_retry_i2c; - - if (ctx->defer_retry_i2c > ctx->max_defer_retry) { - ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT; - ctx->operation_succeeded = false; - } - break; - case AUX_TRANSACTION_REPLY_HPD_DISCON: - ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_HPD_DISCON; - ctx->operation_succeeded = false; - break; - default: - ctx->status = I2CAUX_TRANSACTION_STATUS_UNKNOWN; - ctx->operation_succeeded = false; - } -} - -static void process_write_request( - struct aux_engine *engine, - struct write_command_context *ctx) -{ - enum aux_channel_operation_result operation_result; - - engine->funcs->submit_channel_request(engine, &ctx->request); - - operation_result = engine->funcs->get_channel_status( - engine, &ctx->returned_byte); - - switch (operation_result) { - case AUX_CHANNEL_OPERATION_SUCCEEDED: - ctx->timed_out_retry_aux = 0; - ctx->invalid_reply_retry_aux = 0; - - ctx->reply.length = ctx->returned_byte; - ctx->reply.data = ctx->reply_data; - - process_write_reply(engine, ctx); - break; - case AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY: - ++ctx->invalid_reply_retry_aux; - - if (ctx->invalid_reply_retry_aux > - AUX_INVALID_REPLY_RETRY_COUNTER) { - ctx->status = - I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR; - ctx->operation_succeeded = false; - } else - udelay(400); - break; - case AUX_CHANNEL_OPERATION_FAILED_TIMEOUT: - ++ctx->timed_out_retry_aux; - - if (ctx->timed_out_retry_aux > AUX_TIMED_OUT_RETRY_COUNTER) { - ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT; - ctx->operation_succeeded = false; - } else { - /* DP 1.2a, table 2-58: - * "S3: AUX Request CMD PENDING: - * retry 3 times, with 400usec wait on each" - * The HW timeout is set to 550usec, - * so we should not wait here */ - } - break; - case AUX_CHANNEL_OPERATION_FAILED_HPD_DISCON: - ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_HPD_DISCON; - ctx->operation_succeeded = false; - break; - default: - ctx->status = I2CAUX_TRANSACTION_STATUS_UNKNOWN; - ctx->operation_succeeded = false; - } -} - -static bool write_command( - struct aux_engine *engine, - struct i2caux_transaction_request *request, - bool middle_of_transaction) -{ - struct write_command_context ctx; - - ctx.mot = middle_of_transaction; - ctx.buffer = request->payload.data; - ctx.current_write_length = request->payload.length; - ctx.timed_out_retry_aux = 0; - ctx.invalid_reply_retry_aux = 0; - ctx.defer_retry_aux = 0; - ctx.defer_retry_i2c = 0; - ctx.ack_m_retry = 0; - ctx.transaction_complete = false; - ctx.operation_succeeded = true; - - if (request->payload.address_space == - I2CAUX_TRANSACTION_ADDRESS_SPACE_DPCD) { - ctx.request.type = AUX_TRANSACTION_TYPE_DP; - ctx.request.action = I2CAUX_TRANSACTION_ACTION_DP_WRITE; - ctx.request.address = request->payload.address; - } else if (request->payload.address_space == - I2CAUX_TRANSACTION_ADDRESS_SPACE_I2C) { - ctx.request.type = AUX_TRANSACTION_TYPE_I2C; - ctx.request.action = middle_of_transaction ? - I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT : - I2CAUX_TRANSACTION_ACTION_I2C_WRITE; - ctx.request.address = request->payload.address >> 1; - } else { - /* in DAL2, there was no return in such case */ - BREAK_TO_DEBUGGER(); - return false; - } - - ctx.request.delay = 0; - - ctx.max_defer_retry = - (engine->max_defer_write_retry > AUX_DEFER_RETRY_COUNTER) ? - engine->max_defer_write_retry : AUX_DEFER_RETRY_COUNTER; - - do { - ctx.request.data = ctx.buffer; - ctx.request.length = ctx.current_write_length; - - process_write_request(engine, &ctx); - - request->status = ctx.status; - - if (ctx.operation_succeeded && !ctx.transaction_complete) - if (ctx.request.type == AUX_TRANSACTION_TYPE_I2C) - msleep(engine->delay); - } while (ctx.operation_succeeded && !ctx.transaction_complete); - - if (request->payload.address_space == - I2CAUX_TRANSACTION_ADDRESS_SPACE_DPCD) { - DC_LOG_I2C_AUX("WRITE: addr:0x%x value:0x%x Result:%d", - request->payload.address, - request->payload.data[0], - ctx.operation_succeeded); - } - - return ctx.operation_succeeded; -} - -static bool end_of_transaction_command( - struct aux_engine *engine, - struct i2caux_transaction_request *request) -{ - struct i2caux_transaction_request dummy_request; - uint8_t dummy_data; - - /* [tcheng] We only need to send the stop (read with MOT = 0) - * for I2C-over-Aux, not native AUX */ - - if (request->payload.address_space != - I2CAUX_TRANSACTION_ADDRESS_SPACE_I2C) - return false; - - dummy_request.operation = request->operation; - dummy_request.payload.address_space = request->payload.address_space; - dummy_request.payload.address = request->payload.address; - - /* - * Add a dummy byte due to some receiver quirk - * where one byte is sent along with MOT = 0. - * Ideally this should be 0. - */ - - dummy_request.payload.length = 0; - dummy_request.payload.data = &dummy_data; - - if (request->operation == I2CAUX_TRANSACTION_READ) - return read_command(engine, &dummy_request, false); - else - return write_command(engine, &dummy_request, false); - - /* according Syed, it does not need now DoDummyMOT */ -} - -bool dal_aux_engine_submit_request( - struct engine *engine, - struct i2caux_transaction_request *request, - bool middle_of_transaction) -{ - struct aux_engine *aux_engine = FROM_ENGINE(engine); - - bool result; - bool mot_used = true; - - switch (request->operation) { - case I2CAUX_TRANSACTION_READ: - result = read_command(aux_engine, request, mot_used); - break; - case I2CAUX_TRANSACTION_WRITE: - result = write_command(aux_engine, request, mot_used); - break; - default: - result = false; - } - - /* [tcheng] - * need to send stop for the last transaction to free up the AUX - * if the above command fails, this would be the last transaction */ - - if (!middle_of_transaction || !result) - end_of_transaction_command(aux_engine, request); - - /* mask AUX interrupt */ - - return result; -} - -void dal_aux_engine_construct( - struct aux_engine *engine, - struct dc_context *ctx) -{ - dal_i2caux_construct_engine(&engine->base, ctx); - engine->delay = 0; - engine->max_defer_write_retry = 0; -} - -void dal_aux_engine_destruct( - struct aux_engine *engine) -{ - dal_i2caux_destruct_engine(&engine->base); -} diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.h b/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.h deleted file mode 100644 index c33a2898d967..000000000000 --- a/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#ifndef __DAL_AUX_ENGINE_H__ -#define __DAL_AUX_ENGINE_H__ - -#include "dc_ddc_types.h" - -struct aux_engine; - -struct aux_engine_funcs { - void (*destroy)( - struct aux_engine **ptr); - bool (*acquire_engine)( - struct aux_engine *engine); - void (*configure)( - struct aux_engine *engine, - union aux_config cfg); - void (*submit_channel_request)( - struct aux_engine *engine, - struct aux_request_transaction_data *request); - void (*process_channel_reply)( - struct aux_engine *engine, - struct aux_reply_transaction_data *reply); - int (*read_channel_reply)( - struct aux_engine *engine, - uint32_t size, - uint8_t *buffer, - uint8_t *reply_result, - uint32_t *sw_status); - enum aux_channel_operation_result (*get_channel_status)( - struct aux_engine *engine, - uint8_t *returned_bytes); - bool (*is_engine_available) ( - struct aux_engine *engine); -}; - -struct aux_engine { - struct engine base; - const struct aux_engine_funcs *funcs; - /* following values are expressed in milliseconds */ - uint32_t delay; - uint32_t max_defer_write_retry; - - bool acquire_reset; -}; - -void dal_aux_engine_construct( - struct aux_engine *engine, - struct dc_context *ctx); - -void dal_aux_engine_destruct( - struct aux_engine *engine); -bool dal_aux_engine_submit_request( - struct engine *ptr, - struct i2caux_transaction_request *request, - bool middle_of_transaction); -bool dal_aux_engine_acquire( - struct engine *ptr, - struct ddc *ddc); -enum i2caux_engine_type dal_aux_engine_get_engine_type( - const struct engine *engine); - -#endif diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce100/i2caux_dce100.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce100/i2caux_dce100.c deleted file mode 100644 index 8b704ab0471c..000000000000 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dce100/i2caux_dce100.c +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" - -#include "include/i2caux_interface.h" -#include "../i2caux.h" -#include "../engine.h" -#include "../i2c_engine.h" -#include "../i2c_sw_engine.h" -#include "../i2c_hw_engine.h" - -#include "../dce110/aux_engine_dce110.h" -#include "../dce110/i2c_hw_engine_dce110.h" -#include "../dce110/i2caux_dce110.h" - -#include "dce/dce_10_0_d.h" -#include "dce/dce_10_0_sh_mask.h" - -/* set register offset */ -#define SR(reg_name)\ - .reg_name = mm ## reg_name - -/* set register offset with instance */ -#define SRI(reg_name, block, id)\ - .reg_name = mm ## block ## id ## _ ## reg_name - -#define aux_regs(id)\ -[id] = {\ - AUX_COMMON_REG_LIST(id), \ - .AUX_RESET_MASK = 0 \ -} - -#define hw_engine_regs(id)\ -{\ - I2C_HW_ENGINE_COMMON_REG_LIST(id) \ -} - -static const struct dce110_aux_registers dce100_aux_regs[] = { - aux_regs(0), - aux_regs(1), - aux_regs(2), - aux_regs(3), - aux_regs(4), - aux_regs(5), -}; - -static const struct dce110_i2c_hw_engine_registers dce100_hw_engine_regs[] = { - hw_engine_regs(1), - hw_engine_regs(2), - hw_engine_regs(3), - hw_engine_regs(4), - hw_engine_regs(5), - hw_engine_regs(6) -}; - -static const struct dce110_i2c_hw_engine_shift i2c_shift = { - I2C_COMMON_MASK_SH_LIST_DCE100(__SHIFT) -}; - -static const struct dce110_i2c_hw_engine_mask i2c_mask = { - I2C_COMMON_MASK_SH_LIST_DCE100(_MASK) -}; - -struct i2caux *dal_i2caux_dce100_create( - struct dc_context *ctx) -{ - struct i2caux_dce110 *i2caux_dce110 = - kzalloc(sizeof(struct i2caux_dce110), GFP_KERNEL); - - if (!i2caux_dce110) { - ASSERT_CRITICAL(false); - return NULL; - } - - dal_i2caux_dce110_construct(i2caux_dce110, - ctx, - ARRAY_SIZE(dce100_aux_regs), - dce100_aux_regs, - dce100_hw_engine_regs, - &i2c_shift, - &i2c_mask); - return &i2caux_dce110->base; -} diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce100/i2caux_dce100.h b/drivers/gpu/drm/amd/display/dc/i2caux/dce100/i2caux_dce100.h deleted file mode 100644 index 2b508d3e0ef4..000000000000 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dce100/i2caux_dce100.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#ifndef __DAL_I2C_AUX_DCE100_H__ -#define __DAL_I2C_AUX_DCE100_H__ - -struct i2caux *dal_i2caux_dce100_create( - struct dc_context *ctx); - -#endif /* __DAL_I2C_AUX_DCE100_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.c deleted file mode 100644 index 59c3ed43d609..000000000000 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.c +++ /dev/null @@ -1,505 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" -#include "dm_event_log.h" - -/* - * Pre-requisites: headers required by header of this unit - */ -#include "include/i2caux_interface.h" -#include "../engine.h" -#include "../aux_engine.h" - -/* - * Header of this unit - */ - -#include "aux_engine_dce110.h" - -/* - * Post-requisites: headers required by this unit - */ -#include "dce/dce_11_0_sh_mask.h" - -#define CTX \ - aux110->base.base.ctx -#define REG(reg_name)\ - (aux110->regs->reg_name) -#include "reg_helper.h" - -/* - * This unit - */ - -/* - * @brief - * Cast 'struct aux_engine *' - * to 'struct aux_engine_dce110 *' - */ -#define FROM_AUX_ENGINE(ptr) \ - container_of((ptr), struct aux_engine_dce110, base) - -/* - * @brief - * Cast 'struct engine *' - * to 'struct aux_engine_dce110 *' - */ -#define FROM_ENGINE(ptr) \ - FROM_AUX_ENGINE(container_of((ptr), struct aux_engine, base)) - -static void release_engine( - struct engine *engine) -{ - struct aux_engine_dce110 *aux110 = FROM_ENGINE(engine); - - REG_UPDATE(AUX_ARB_CONTROL, AUX_SW_DONE_USING_AUX_REG, 1); -} - -static void destruct( - struct aux_engine_dce110 *engine); - -static void destroy( - struct aux_engine **aux_engine) -{ - struct aux_engine_dce110 *engine = FROM_AUX_ENGINE(*aux_engine); - - destruct(engine); - - kfree(engine); - - *aux_engine = NULL; -} - -#define SW_CAN_ACCESS_AUX 1 -#define DMCU_CAN_ACCESS_AUX 2 - -static bool is_engine_available( - struct aux_engine *engine) -{ - struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine); - - uint32_t value = REG_READ(AUX_ARB_CONTROL); - uint32_t field = get_reg_field_value( - value, - AUX_ARB_CONTROL, - AUX_REG_RW_CNTL_STATUS); - - return (field != DMCU_CAN_ACCESS_AUX); -} -static bool acquire_engine( - struct aux_engine *engine) -{ - struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine); - - uint32_t value = REG_READ(AUX_ARB_CONTROL); - uint32_t field = get_reg_field_value( - value, - AUX_ARB_CONTROL, - AUX_REG_RW_CNTL_STATUS); - if (field == DMCU_CAN_ACCESS_AUX) - return false; - /* enable AUX before request SW to access AUX */ - value = REG_READ(AUX_CONTROL); - field = get_reg_field_value(value, - AUX_CONTROL, - AUX_EN); - - if (field == 0) { - set_reg_field_value( - value, - 1, - AUX_CONTROL, - AUX_EN); - - if (REG(AUX_RESET_MASK)) { - /*DP_AUX block as part of the enable sequence*/ - set_reg_field_value( - value, - 1, - AUX_CONTROL, - AUX_RESET); - } - - REG_WRITE(AUX_CONTROL, value); - - if (REG(AUX_RESET_MASK)) { - /*poll HW to make sure reset it done*/ - - REG_WAIT(AUX_CONTROL, AUX_RESET_DONE, 1, - 1, 11); - - set_reg_field_value( - value, - 0, - AUX_CONTROL, - AUX_RESET); - - REG_WRITE(AUX_CONTROL, value); - - REG_WAIT(AUX_CONTROL, AUX_RESET_DONE, 0, - 1, 11); - } - } /*if (field)*/ - - /* request SW to access AUX */ - REG_UPDATE(AUX_ARB_CONTROL, AUX_SW_USE_AUX_REG_REQ, 1); - - value = REG_READ(AUX_ARB_CONTROL); - field = get_reg_field_value( - value, - AUX_ARB_CONTROL, - AUX_REG_RW_CNTL_STATUS); - - return (field == SW_CAN_ACCESS_AUX); -} - -#define COMPOSE_AUX_SW_DATA_16_20(command, address) \ - ((command) | ((0xF0000 & (address)) >> 16)) - -#define COMPOSE_AUX_SW_DATA_8_15(address) \ - ((0xFF00 & (address)) >> 8) - -#define COMPOSE_AUX_SW_DATA_0_7(address) \ - (0xFF & (address)) - -static void submit_channel_request( - struct aux_engine *engine, - struct aux_request_transaction_data *request) -{ - struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine); - uint32_t value; - uint32_t length; - - bool is_write = - ((request->type == AUX_TRANSACTION_TYPE_DP) && - (request->action == I2CAUX_TRANSACTION_ACTION_DP_WRITE)) || - ((request->type == AUX_TRANSACTION_TYPE_I2C) && - ((request->action == I2CAUX_TRANSACTION_ACTION_I2C_WRITE) || - (request->action == I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT))); - if (REG(AUXN_IMPCAL)) { - /* clear_aux_error */ - REG_UPDATE_SEQ(AUXN_IMPCAL, AUXN_CALOUT_ERROR_AK, - 1, - 0); - - REG_UPDATE_SEQ(AUXP_IMPCAL, AUXP_CALOUT_ERROR_AK, - 1, - 0); - - /* force_default_calibrate */ - REG_UPDATE_1BY1_2(AUXN_IMPCAL, - AUXN_IMPCAL_ENABLE, 1, - AUXN_IMPCAL_OVERRIDE_ENABLE, 0); - - /* bug? why AUXN update EN and OVERRIDE_EN 1 by 1 while AUX P toggles OVERRIDE? */ - - REG_UPDATE_SEQ(AUXP_IMPCAL, AUXP_IMPCAL_OVERRIDE_ENABLE, - 1, - 0); - } - /* set the delay and the number of bytes to write */ - - /* The length include - * the 4 bit header and the 20 bit address - * (that is 3 byte). - * If the requested length is non zero this means - * an addition byte specifying the length is required. */ - - length = request->length ? 4 : 3; - if (is_write) - length += request->length; - - REG_UPDATE_2(AUX_SW_CONTROL, - AUX_SW_START_DELAY, request->delay, - AUX_SW_WR_BYTES, length); - - /* program action and address and payload data (if 'is_write') */ - value = REG_UPDATE_4(AUX_SW_DATA, - AUX_SW_INDEX, 0, - AUX_SW_DATA_RW, 0, - AUX_SW_AUTOINCREMENT_DISABLE, 1, - AUX_SW_DATA, COMPOSE_AUX_SW_DATA_16_20(request->action, request->address)); - - value = REG_SET_2(AUX_SW_DATA, value, - AUX_SW_AUTOINCREMENT_DISABLE, 0, - AUX_SW_DATA, COMPOSE_AUX_SW_DATA_8_15(request->address)); - - value = REG_SET(AUX_SW_DATA, value, - AUX_SW_DATA, COMPOSE_AUX_SW_DATA_0_7(request->address)); - - if (request->length) { - value = REG_SET(AUX_SW_DATA, value, - AUX_SW_DATA, request->length - 1); - } - - if (is_write) { - /* Load the HW buffer with the Data to be sent. - * This is relevant for write operation. - * For read, the data recived data will be - * processed in process_channel_reply(). */ - uint32_t i = 0; - - while (i < request->length) { - value = REG_SET(AUX_SW_DATA, value, - AUX_SW_DATA, request->data[i]); - - ++i; - } - } - - REG_UPDATE(AUX_INTERRUPT_CONTROL, AUX_SW_DONE_ACK, 1); - REG_WAIT(AUX_SW_STATUS, AUX_SW_DONE, 0, - 10, aux110->timeout_period/10); - REG_UPDATE(AUX_SW_CONTROL, AUX_SW_GO, 1); - EVENT_LOG_AUX_REQ(engine->base.ddc->pin_data->en, EVENT_LOG_AUX_ORIGIN_NATIVE, - request->action, request->address, request->length, request->data); -} - -static int read_channel_reply(struct aux_engine *engine, uint32_t size, - uint8_t *buffer, uint8_t *reply_result, - uint32_t *sw_status) -{ - struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine); - uint32_t bytes_replied; - uint32_t reply_result_32; - - *sw_status = REG_GET(AUX_SW_STATUS, AUX_SW_REPLY_BYTE_COUNT, - &bytes_replied); - - /* In case HPD is LOW, exit AUX transaction */ - if ((*sw_status & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK)) - return -1; - - /* Need at least the status byte */ - if (!bytes_replied) - return -1; - - REG_UPDATE_1BY1_3(AUX_SW_DATA, - AUX_SW_INDEX, 0, - AUX_SW_AUTOINCREMENT_DISABLE, 1, - AUX_SW_DATA_RW, 1); - - REG_GET(AUX_SW_DATA, AUX_SW_DATA, &reply_result_32); - reply_result_32 = reply_result_32 >> 4; - *reply_result = (uint8_t)reply_result_32; - - if (reply_result_32 == 0) { /* ACK */ - uint32_t i = 0; - - /* First byte was already used to get the command status */ - --bytes_replied; - - /* Do not overflow buffer */ - if (bytes_replied > size) - return -1; - - while (i < bytes_replied) { - uint32_t aux_sw_data_val; - - REG_GET(AUX_SW_DATA, AUX_SW_DATA, &aux_sw_data_val); - buffer[i] = aux_sw_data_val; - ++i; - } - - return i; - } - - return 0; -} - -static void process_channel_reply( - struct aux_engine *engine, - struct aux_reply_transaction_data *reply) -{ - int bytes_replied; - uint8_t reply_result; - uint32_t sw_status; - - bytes_replied = read_channel_reply(engine, reply->length, reply->data, - &reply_result, &sw_status); - EVENT_LOG_AUX_REP(engine->base.ddc->pin_data->en, - EVENT_LOG_AUX_ORIGIN_NATIVE, reply_result, - bytes_replied, reply->data); - - /* in case HPD is LOW, exit AUX transaction */ - if ((sw_status & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK)) { - reply->status = AUX_TRANSACTION_REPLY_HPD_DISCON; - return; - } - - if (bytes_replied < 0) { - /* Need to handle an error case... - * Hopefully, upper layer function won't call this function if - * the number of bytes in the reply was 0, because there was - * surely an error that was asserted that should have been - * handled for hot plug case, this could happens - */ - if (!(sw_status & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK)) { - reply->status = AUX_TRANSACTION_REPLY_INVALID; - ASSERT_CRITICAL(false); - return; - } - } else { - - switch (reply_result) { - case 0: /* ACK */ - reply->status = AUX_TRANSACTION_REPLY_AUX_ACK; - break; - case 1: /* NACK */ - reply->status = AUX_TRANSACTION_REPLY_AUX_NACK; - break; - case 2: /* DEFER */ - reply->status = AUX_TRANSACTION_REPLY_AUX_DEFER; - break; - case 4: /* AUX ACK / I2C NACK */ - reply->status = AUX_TRANSACTION_REPLY_I2C_NACK; - break; - case 8: /* AUX ACK / I2C DEFER */ - reply->status = AUX_TRANSACTION_REPLY_I2C_DEFER; - break; - default: - reply->status = AUX_TRANSACTION_REPLY_INVALID; - } - } -} - -static enum aux_channel_operation_result get_channel_status( - struct aux_engine *engine, - uint8_t *returned_bytes) -{ - struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine); - - uint32_t value; - - if (returned_bytes == NULL) { - /*caller pass NULL pointer*/ - ASSERT_CRITICAL(false); - return AUX_CHANNEL_OPERATION_FAILED_REASON_UNKNOWN; - } - *returned_bytes = 0; - - /* poll to make sure that SW_DONE is asserted */ - value = REG_WAIT(AUX_SW_STATUS, AUX_SW_DONE, 1, - 10, aux110->timeout_period/10); - - /* in case HPD is LOW, exit AUX transaction */ - if ((value & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK)) - return AUX_CHANNEL_OPERATION_FAILED_HPD_DISCON; - - /* Note that the following bits are set in 'status.bits' - * during CTS 4.2.1.2 (FW 3.3.1): - * AUX_SW_RX_MIN_COUNT_VIOL, AUX_SW_RX_INVALID_STOP, - * AUX_SW_RX_RECV_NO_DET, AUX_SW_RX_RECV_INVALID_H. - * - * AUX_SW_RX_MIN_COUNT_VIOL is an internal, - * HW debugging bit and should be ignored. */ - if (value & AUX_SW_STATUS__AUX_SW_DONE_MASK) { - if ((value & AUX_SW_STATUS__AUX_SW_RX_TIMEOUT_STATE_MASK) || - (value & AUX_SW_STATUS__AUX_SW_RX_TIMEOUT_MASK)) - return AUX_CHANNEL_OPERATION_FAILED_TIMEOUT; - - else if ((value & AUX_SW_STATUS__AUX_SW_RX_INVALID_STOP_MASK) || - (value & AUX_SW_STATUS__AUX_SW_RX_RECV_NO_DET_MASK) || - (value & - AUX_SW_STATUS__AUX_SW_RX_RECV_INVALID_H_MASK) || - (value & AUX_SW_STATUS__AUX_SW_RX_RECV_INVALID_L_MASK)) - return AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY; - - *returned_bytes = get_reg_field_value(value, - AUX_SW_STATUS, - AUX_SW_REPLY_BYTE_COUNT); - - if (*returned_bytes == 0) - return - AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY; - else { - *returned_bytes -= 1; - return AUX_CHANNEL_OPERATION_SUCCEEDED; - } - } else { - /*time_elapsed >= aux_engine->timeout_period - * AUX_SW_STATUS__AUX_SW_HPD_DISCON = at this point - */ - ASSERT_CRITICAL(false); - return AUX_CHANNEL_OPERATION_FAILED_TIMEOUT; - } -} - -static const struct aux_engine_funcs aux_engine_funcs = { - .destroy = destroy, - .acquire_engine = acquire_engine, - .submit_channel_request = submit_channel_request, - .process_channel_reply = process_channel_reply, - .read_channel_reply = read_channel_reply, - .get_channel_status = get_channel_status, - .is_engine_available = is_engine_available, -}; - -static const struct engine_funcs engine_funcs = { - .release_engine = release_engine, - .submit_request = dal_aux_engine_submit_request, - .get_engine_type = dal_aux_engine_get_engine_type, - .acquire = dal_aux_engine_acquire, -}; - -static void construct( - struct aux_engine_dce110 *engine, - const struct aux_engine_dce110_init_data *aux_init_data) -{ - dal_aux_engine_construct(&engine->base, aux_init_data->ctx); - engine->base.base.funcs = &engine_funcs; - engine->base.funcs = &aux_engine_funcs; - - engine->timeout_period = aux_init_data->timeout_period; - engine->regs = aux_init_data->regs; -} - -static void destruct( - struct aux_engine_dce110 *engine) -{ - dal_aux_engine_destruct(&engine->base); -} - -struct aux_engine *dal_aux_engine_dce110_create( - const struct aux_engine_dce110_init_data *aux_init_data) -{ - struct aux_engine_dce110 *engine; - - if (!aux_init_data) { - ASSERT_CRITICAL(false); - return NULL; - } - - engine = kzalloc(sizeof(*engine), GFP_KERNEL); - - if (!engine) { - ASSERT_CRITICAL(false); - return NULL; - } - - construct(engine, aux_init_data); - return &engine->base; -} diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.h b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.h deleted file mode 100644 index 85ee82162590..000000000000 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#ifndef __DAL_AUX_ENGINE_DCE110_H__ -#define __DAL_AUX_ENGINE_DCE110_H__ - -#include "../aux_engine.h" - -#define AUX_COMMON_REG_LIST(id)\ - SRI(AUX_CONTROL, DP_AUX, id), \ - SRI(AUX_ARB_CONTROL, DP_AUX, id), \ - SRI(AUX_SW_DATA, DP_AUX, id), \ - SRI(AUX_SW_CONTROL, DP_AUX, id), \ - SRI(AUX_INTERRUPT_CONTROL, DP_AUX, id), \ - SRI(AUX_SW_STATUS, DP_AUX, id), \ - SR(AUXN_IMPCAL), \ - SR(AUXP_IMPCAL) - -struct dce110_aux_registers { - uint32_t AUX_CONTROL; - uint32_t AUX_ARB_CONTROL; - uint32_t AUX_SW_DATA; - uint32_t AUX_SW_CONTROL; - uint32_t AUX_INTERRUPT_CONTROL; - uint32_t AUX_SW_STATUS; - uint32_t AUXN_IMPCAL; - uint32_t AUXP_IMPCAL; - - uint32_t AUX_RESET_MASK; -}; - -struct aux_engine_dce110 { - struct aux_engine base; - const struct dce110_aux_registers *regs; - struct { - uint32_t aux_control; - uint32_t aux_arb_control; - uint32_t aux_sw_data; - uint32_t aux_sw_control; - uint32_t aux_interrupt_control; - uint32_t aux_sw_status; - } addr; - uint32_t timeout_period; -}; - -struct aux_engine_dce110_init_data { - uint32_t engine_id; - uint32_t timeout_period; - struct dc_context *ctx; - const struct dce110_aux_registers *regs; -}; - -struct aux_engine *dal_aux_engine_dce110_create( - const struct aux_engine_dce110_init_data *aux_init_data); - -#endif diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_hw_engine_dce110.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_hw_engine_dce110.c deleted file mode 100644 index 9cbe1a7a6bcb..000000000000 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_hw_engine_dce110.c +++ /dev/null @@ -1,574 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" -#include "include/logger_interface.h" -/* - * Pre-requisites: headers required by header of this unit - */ - -#include "include/i2caux_interface.h" -#include "../engine.h" -#include "../i2c_engine.h" -#include "../i2c_hw_engine.h" -#include "../i2c_generic_hw_engine.h" -/* - * Header of this unit - */ - -#include "i2c_hw_engine_dce110.h" - -/* - * Post-requisites: headers required by this unit - */ -#include "reg_helper.h" - -/* - * This unit - */ -#define DC_LOGGER \ - hw_engine->base.base.base.ctx->logger - -enum dc_i2c_status { - DC_I2C_STATUS__DC_I2C_STATUS_IDLE, - DC_I2C_STATUS__DC_I2C_STATUS_USED_BY_SW, - DC_I2C_STATUS__DC_I2C_STATUS_USED_BY_HW -}; - -enum dc_i2c_arbitration { - DC_I2C_ARBITRATION__DC_I2C_SW_PRIORITY_NORMAL, - DC_I2C_ARBITRATION__DC_I2C_SW_PRIORITY_HIGH -}; - - - -/* - * @brief - * Cast pointer to 'struct i2c_hw_engine *' - * to pointer 'struct i2c_hw_engine_dce110 *' - */ -#define FROM_I2C_HW_ENGINE(ptr) \ - container_of((ptr), struct i2c_hw_engine_dce110, base) -/* - * @brief - * Cast pointer to 'struct i2c_engine *' - * to pointer to 'struct i2c_hw_engine_dce110 *' - */ -#define FROM_I2C_ENGINE(ptr) \ - FROM_I2C_HW_ENGINE(container_of((ptr), struct i2c_hw_engine, base)) - -/* - * @brief - * Cast pointer to 'struct engine *' - * to 'pointer to struct i2c_hw_engine_dce110 *' - */ -#define FROM_ENGINE(ptr) \ - FROM_I2C_ENGINE(container_of((ptr), struct i2c_engine, base)) - -#define CTX \ - hw_engine->base.base.base.ctx - -#define REG(reg_name)\ - (hw_engine->regs->reg_name) - -#undef FN -#define FN(reg_name, field_name) \ - hw_engine->i2c_shift->field_name, hw_engine->i2c_mask->field_name - -#include "reg_helper.h" - -static void disable_i2c_hw_engine( - struct i2c_hw_engine_dce110 *hw_engine) -{ - REG_UPDATE_N(SETUP, 1, FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_ENABLE), 0); -} - -static void release_engine( - struct engine *engine) -{ - struct i2c_hw_engine_dce110 *hw_engine = FROM_ENGINE(engine); - - struct i2c_engine *base = NULL; - bool safe_to_reset; - - base = &hw_engine->base.base; - - /* Restore original HW engine speed */ - - base->funcs->set_speed(base, hw_engine->base.original_speed); - - /* Release I2C */ - REG_UPDATE(DC_I2C_ARBITRATION, DC_I2C_SW_DONE_USING_I2C_REG, 1); - - /* Reset HW engine */ - { - uint32_t i2c_sw_status = 0; - REG_GET(DC_I2C_SW_STATUS, DC_I2C_SW_STATUS, &i2c_sw_status); - /* if used by SW, safe to reset */ - safe_to_reset = (i2c_sw_status == 1); - } - - if (safe_to_reset) - REG_UPDATE_2( - DC_I2C_CONTROL, - DC_I2C_SOFT_RESET, 1, - DC_I2C_SW_STATUS_RESET, 1); - else - REG_UPDATE(DC_I2C_CONTROL, DC_I2C_SW_STATUS_RESET, 1); - - /* HW I2c engine - clock gating feature */ - if (!hw_engine->engine_keep_power_up_count) - disable_i2c_hw_engine(hw_engine); -} - -static bool setup_engine( - struct i2c_engine *i2c_engine) -{ - struct i2c_hw_engine_dce110 *hw_engine = FROM_I2C_ENGINE(i2c_engine); - uint32_t i2c_setup_limit = I2C_SETUP_TIME_LIMIT_DCE; - uint32_t reset_length = 0; - - if (hw_engine->base.base.setup_limit != 0) - i2c_setup_limit = hw_engine->base.base.setup_limit; - - /* Program pin select */ - REG_UPDATE_6( - DC_I2C_CONTROL, - DC_I2C_GO, 0, - DC_I2C_SOFT_RESET, 0, - DC_I2C_SEND_RESET, 0, - DC_I2C_SW_STATUS_RESET, 1, - DC_I2C_TRANSACTION_COUNT, 0, - DC_I2C_DDC_SELECT, hw_engine->engine_id); - - /* Program time limit */ - if (hw_engine->base.base.send_reset_length == 0) { - /*pre-dcn*/ - REG_UPDATE_N( - SETUP, 2, - FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_TIME_LIMIT), i2c_setup_limit, - FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_ENABLE), 1); - } else { - reset_length = hw_engine->base.base.send_reset_length; - } - /* Program HW priority - * set to High - interrupt software I2C at any time - * Enable restart of SW I2C that was interrupted by HW - * disable queuing of software while I2C is in use by HW */ - REG_UPDATE_2( - DC_I2C_ARBITRATION, - DC_I2C_NO_QUEUED_SW_GO, 0, - DC_I2C_SW_PRIORITY, DC_I2C_ARBITRATION__DC_I2C_SW_PRIORITY_NORMAL); - - return true; -} - -static uint32_t get_speed( - const struct i2c_engine *i2c_engine) -{ - const struct i2c_hw_engine_dce110 *hw_engine = FROM_I2C_ENGINE(i2c_engine); - uint32_t pre_scale = 0; - - REG_GET(SPEED, DC_I2C_DDC1_PRESCALE, &pre_scale); - - /* [anaumov] it seems following is unnecessary */ - /*ASSERT(value.bits.DC_I2C_DDC1_PRESCALE);*/ - return pre_scale ? - hw_engine->reference_frequency / pre_scale : - hw_engine->base.default_speed; -} - -static void set_speed( - struct i2c_engine *i2c_engine, - uint32_t speed) -{ - struct i2c_hw_engine_dce110 *hw_engine = FROM_I2C_ENGINE(i2c_engine); - - if (speed) { - if (hw_engine->i2c_mask->DC_I2C_DDC1_START_STOP_TIMING_CNTL) - REG_UPDATE_N( - SPEED, 3, - FN(DC_I2C_DDC1_SPEED, DC_I2C_DDC1_PRESCALE), hw_engine->reference_frequency / speed, - FN(DC_I2C_DDC1_SPEED, DC_I2C_DDC1_THRESHOLD), 2, - FN(DC_I2C_DDC1_SPEED, DC_I2C_DDC1_START_STOP_TIMING_CNTL), speed > 50 ? 2:1); - else - REG_UPDATE_N( - SPEED, 2, - FN(DC_I2C_DDC1_SPEED, DC_I2C_DDC1_PRESCALE), hw_engine->reference_frequency / speed, - FN(DC_I2C_DDC1_SPEED, DC_I2C_DDC1_THRESHOLD), 2); - } -} - -static inline void reset_hw_engine(struct engine *engine) -{ - struct i2c_hw_engine_dce110 *hw_engine = FROM_ENGINE(engine); - - REG_UPDATE_2( - DC_I2C_CONTROL, - DC_I2C_SW_STATUS_RESET, 1, - DC_I2C_SW_STATUS_RESET, 1); -} - -static bool is_hw_busy(struct engine *engine) -{ - struct i2c_hw_engine_dce110 *hw_engine = FROM_ENGINE(engine); - uint32_t i2c_sw_status = 0; - - REG_GET(DC_I2C_SW_STATUS, DC_I2C_SW_STATUS, &i2c_sw_status); - if (i2c_sw_status == DC_I2C_STATUS__DC_I2C_STATUS_IDLE) - return false; - - reset_hw_engine(engine); - - REG_GET(DC_I2C_SW_STATUS, DC_I2C_SW_STATUS, &i2c_sw_status); - return i2c_sw_status != DC_I2C_STATUS__DC_I2C_STATUS_IDLE; -} - - -#define STOP_TRANS_PREDICAT \ - ((hw_engine->transaction_count == 3) || \ - (request->action == I2CAUX_TRANSACTION_ACTION_I2C_WRITE) || \ - (request->action & I2CAUX_TRANSACTION_ACTION_I2C_READ)) - -#define SET_I2C_TRANSACTION(id) \ - do { \ - REG_UPDATE_N(DC_I2C_TRANSACTION##id, 5, \ - FN(DC_I2C_TRANSACTION0, DC_I2C_STOP_ON_NACK0), 1, \ - FN(DC_I2C_TRANSACTION0, DC_I2C_START0), 1, \ - FN(DC_I2C_TRANSACTION0, DC_I2C_STOP0), STOP_TRANS_PREDICAT ? 1:0, \ - FN(DC_I2C_TRANSACTION0, DC_I2C_RW0), (0 != (request->action & I2CAUX_TRANSACTION_ACTION_I2C_READ)), \ - FN(DC_I2C_TRANSACTION0, DC_I2C_COUNT0), length); \ - if (STOP_TRANS_PREDICAT) \ - last_transaction = true; \ - } while (false) - - -static bool process_transaction( - struct i2c_hw_engine_dce110 *hw_engine, - struct i2c_request_transaction_data *request) -{ - uint32_t length = request->length; - uint8_t *buffer = request->data; - uint32_t value = 0; - - bool last_transaction = false; - - struct dc_context *ctx = NULL; - - ctx = hw_engine->base.base.base.ctx; - - - - switch (hw_engine->transaction_count) { - case 0: - SET_I2C_TRANSACTION(0); - break; - case 1: - SET_I2C_TRANSACTION(1); - break; - case 2: - SET_I2C_TRANSACTION(2); - break; - case 3: - SET_I2C_TRANSACTION(3); - break; - default: - /* TODO Warning ? */ - break; - } - - - /* Write the I2C address and I2C data - * into the hardware circular buffer, one byte per entry. - * As an example, the 7-bit I2C slave address for CRT monitor - * for reading DDC/EDID information is 0b1010001. - * For an I2C send operation, the LSB must be programmed to 0; - * for I2C receive operation, the LSB must be programmed to 1. */ - if (hw_engine->transaction_count == 0) { - value = REG_SET_4(DC_I2C_DATA, 0, - DC_I2C_DATA_RW, false, - DC_I2C_DATA, request->address, - DC_I2C_INDEX, 0, - DC_I2C_INDEX_WRITE, 1); - hw_engine->buffer_used_write = 0; - } else - value = REG_SET_2(DC_I2C_DATA, 0, - DC_I2C_DATA_RW, false, - DC_I2C_DATA, request->address); - - hw_engine->buffer_used_write++; - - if (!(request->action & I2CAUX_TRANSACTION_ACTION_I2C_READ)) { - while (length) { - REG_SET_2(DC_I2C_DATA, value, - DC_I2C_INDEX_WRITE, 0, - DC_I2C_DATA, *buffer++); - hw_engine->buffer_used_write++; - --length; - } - } - - ++hw_engine->transaction_count; - hw_engine->buffer_used_bytes += length + 1; - - return last_transaction; -} - -static void execute_transaction( - struct i2c_hw_engine_dce110 *hw_engine) -{ - REG_UPDATE_N(SETUP, 5, - FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_DATA_DRIVE_EN), 0, - FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_CLK_DRIVE_EN), 0, - FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_DATA_DRIVE_SEL), 0, - FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_INTRA_TRANSACTION_DELAY), 0, - FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_INTRA_BYTE_DELAY), 0); - - - REG_UPDATE_5(DC_I2C_CONTROL, - DC_I2C_SOFT_RESET, 0, - DC_I2C_SW_STATUS_RESET, 0, - DC_I2C_SEND_RESET, 0, - DC_I2C_GO, 0, - DC_I2C_TRANSACTION_COUNT, hw_engine->transaction_count - 1); - - /* start I2C transfer */ - REG_UPDATE(DC_I2C_CONTROL, DC_I2C_GO, 1); - - /* all transactions were executed and HW buffer became empty - * (even though it actually happens when status becomes DONE) */ - hw_engine->transaction_count = 0; - hw_engine->buffer_used_bytes = 0; -} - -static void submit_channel_request( - struct i2c_engine *engine, - struct i2c_request_transaction_data *request) -{ - request->status = I2C_CHANNEL_OPERATION_SUCCEEDED; - - if (!process_transaction(FROM_I2C_ENGINE(engine), request)) - return; - - if (is_hw_busy(&engine->base)) { - request->status = I2C_CHANNEL_OPERATION_ENGINE_BUSY; - return; - } - - execute_transaction(FROM_I2C_ENGINE(engine)); -} - -static void process_channel_reply( - struct i2c_engine *engine, - struct i2c_reply_transaction_data *reply) -{ - uint32_t length = reply->length; - uint8_t *buffer = reply->data; - - struct i2c_hw_engine_dce110 *hw_engine = - FROM_I2C_ENGINE(engine); - - - REG_SET_3(DC_I2C_DATA, 0, - DC_I2C_INDEX, hw_engine->buffer_used_write, - DC_I2C_DATA_RW, 1, - DC_I2C_INDEX_WRITE, 1); - - while (length) { - /* after reading the status, - * if the I2C operation executed successfully - * (i.e. DC_I2C_STATUS_DONE = 1) then the I2C controller - * should read data bytes from I2C circular data buffer */ - - uint32_t i2c_data; - - REG_GET(DC_I2C_DATA, DC_I2C_DATA, &i2c_data); - *buffer++ = i2c_data; - - --length; - } -} - -static enum i2c_channel_operation_result get_channel_status( - struct i2c_engine *i2c_engine, - uint8_t *returned_bytes) -{ - uint32_t i2c_sw_status = 0; - struct i2c_hw_engine_dce110 *hw_engine = FROM_I2C_ENGINE(i2c_engine); - uint32_t value = - REG_GET(DC_I2C_SW_STATUS, DC_I2C_SW_STATUS, &i2c_sw_status); - - if (i2c_sw_status == DC_I2C_STATUS__DC_I2C_STATUS_USED_BY_SW) - return I2C_CHANNEL_OPERATION_ENGINE_BUSY; - else if (value & hw_engine->i2c_mask->DC_I2C_SW_STOPPED_ON_NACK) - return I2C_CHANNEL_OPERATION_NO_RESPONSE; - else if (value & hw_engine->i2c_mask->DC_I2C_SW_TIMEOUT) - return I2C_CHANNEL_OPERATION_TIMEOUT; - else if (value & hw_engine->i2c_mask->DC_I2C_SW_ABORTED) - return I2C_CHANNEL_OPERATION_FAILED; - else if (value & hw_engine->i2c_mask->DC_I2C_SW_DONE) - return I2C_CHANNEL_OPERATION_SUCCEEDED; - - /* - * this is the case when HW used for communication, I2C_SW_STATUS - * could be zero - */ - return I2C_CHANNEL_OPERATION_SUCCEEDED; -} - -static uint32_t get_hw_buffer_available_size( - const struct i2c_hw_engine *engine) -{ - return I2C_HW_BUFFER_SIZE - - FROM_I2C_HW_ENGINE(engine)->buffer_used_bytes; -} - -static uint32_t get_transaction_timeout( - const struct i2c_hw_engine *engine, - uint32_t length) -{ - uint32_t speed = engine->base.funcs->get_speed(&engine->base); - - uint32_t period_timeout; - uint32_t num_of_clock_stretches; - - if (!speed) - return 0; - - period_timeout = (1000 * TRANSACTION_TIMEOUT_IN_I2C_CLOCKS) / speed; - - num_of_clock_stretches = 1 + (length << 3) + 1; - num_of_clock_stretches += - (FROM_I2C_HW_ENGINE(engine)->buffer_used_bytes << 3) + - (FROM_I2C_HW_ENGINE(engine)->transaction_count << 1); - - return period_timeout * num_of_clock_stretches; -} - -static void destroy( - struct i2c_engine **i2c_engine) -{ - struct i2c_hw_engine_dce110 *engine_dce110 = - FROM_I2C_ENGINE(*i2c_engine); - - dal_i2c_hw_engine_destruct(&engine_dce110->base); - - kfree(engine_dce110); - - *i2c_engine = NULL; -} - -static const struct i2c_engine_funcs i2c_engine_funcs = { - .destroy = destroy, - .get_speed = get_speed, - .set_speed = set_speed, - .setup_engine = setup_engine, - .submit_channel_request = submit_channel_request, - .process_channel_reply = process_channel_reply, - .get_channel_status = get_channel_status, - .acquire_engine = dal_i2c_hw_engine_acquire_engine, -}; - -static const struct engine_funcs engine_funcs = { - .release_engine = release_engine, - .get_engine_type = dal_i2c_hw_engine_get_engine_type, - .acquire = dal_i2c_engine_acquire, - .submit_request = dal_i2c_hw_engine_submit_request, -}; - -static const struct i2c_hw_engine_funcs i2c_hw_engine_funcs = { - .get_hw_buffer_available_size = get_hw_buffer_available_size, - .get_transaction_timeout = get_transaction_timeout, - .wait_on_operation_result = dal_i2c_hw_engine_wait_on_operation_result, -}; - -static void construct( - struct i2c_hw_engine_dce110 *hw_engine, - const struct i2c_hw_engine_dce110_create_arg *arg) -{ - uint32_t xtal_ref_div = 0; - - dal_i2c_hw_engine_construct(&hw_engine->base, arg->ctx); - - hw_engine->base.base.base.funcs = &engine_funcs; - hw_engine->base.base.funcs = &i2c_engine_funcs; - hw_engine->base.funcs = &i2c_hw_engine_funcs; - hw_engine->base.default_speed = arg->default_speed; - - hw_engine->regs = arg->regs; - hw_engine->i2c_shift = arg->i2c_shift; - hw_engine->i2c_mask = arg->i2c_mask; - - hw_engine->engine_id = arg->engine_id; - - hw_engine->buffer_used_bytes = 0; - hw_engine->transaction_count = 0; - hw_engine->engine_keep_power_up_count = 1; - - - REG_GET(MICROSECOND_TIME_BASE_DIV, XTAL_REF_DIV, &xtal_ref_div); - - if (xtal_ref_div == 0) { - DC_LOG_WARNING("Invalid base timer divider [%s]\n", - __func__); - xtal_ref_div = 2; - } - - /*Calculating Reference Clock by divding original frequency by - * XTAL_REF_DIV. - * At upper level, uint32_t reference_frequency = - * dal_i2caux_get_reference_clock(as) >> 1 - * which already divided by 2. So we need x2 to get original - * reference clock from ppll_info - */ - hw_engine->reference_frequency = - (arg->reference_frequency * 2) / xtal_ref_div; -} - -struct i2c_engine *dal_i2c_hw_engine_dce110_create( - const struct i2c_hw_engine_dce110_create_arg *arg) -{ - struct i2c_hw_engine_dce110 *engine_dce10; - - if (!arg) { - ASSERT_CRITICAL(false); - return NULL; - } - if (!arg->reference_frequency) { - ASSERT_CRITICAL(false); - return NULL; - } - - engine_dce10 = kzalloc(sizeof(struct i2c_hw_engine_dce110), - GFP_KERNEL); - - if (!engine_dce10) { - ASSERT_CRITICAL(false); - return NULL; - } - - construct(engine_dce10, arg); - return &engine_dce10->base.base; -} diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_hw_engine_dce110.h b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_hw_engine_dce110.h deleted file mode 100644 index fea2946906ed..000000000000 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_hw_engine_dce110.h +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#ifndef __DAL_I2C_HW_ENGINE_DCE110_H__ -#define __DAL_I2C_HW_ENGINE_DCE110_H__ - -#define I2C_HW_ENGINE_COMMON_REG_LIST(id)\ - SRI(SETUP, DC_I2C_DDC, id),\ - SRI(SPEED, DC_I2C_DDC, id),\ - SR(DC_I2C_ARBITRATION),\ - SR(DC_I2C_CONTROL),\ - SR(DC_I2C_SW_STATUS),\ - SR(DC_I2C_TRANSACTION0),\ - SR(DC_I2C_TRANSACTION1),\ - SR(DC_I2C_TRANSACTION2),\ - SR(DC_I2C_TRANSACTION3),\ - SR(DC_I2C_DATA),\ - SR(MICROSECOND_TIME_BASE_DIV) - -#define I2C_SF(reg_name, field_name, post_fix)\ - .field_name = reg_name ## __ ## field_name ## post_fix - -#define I2C_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh)\ - I2C_SF(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_ENABLE, mask_sh),\ - I2C_SF(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_TIME_LIMIT, mask_sh),\ - I2C_SF(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_DATA_DRIVE_EN, mask_sh),\ - I2C_SF(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_CLK_DRIVE_EN, mask_sh),\ - I2C_SF(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_DATA_DRIVE_SEL, mask_sh),\ - I2C_SF(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_INTRA_TRANSACTION_DELAY, mask_sh),\ - I2C_SF(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_INTRA_BYTE_DELAY, mask_sh),\ - I2C_SF(DC_I2C_ARBITRATION, DC_I2C_SW_DONE_USING_I2C_REG, mask_sh),\ - I2C_SF(DC_I2C_ARBITRATION, DC_I2C_NO_QUEUED_SW_GO, mask_sh),\ - I2C_SF(DC_I2C_ARBITRATION, DC_I2C_SW_PRIORITY, mask_sh),\ - I2C_SF(DC_I2C_CONTROL, DC_I2C_SOFT_RESET, mask_sh),\ - I2C_SF(DC_I2C_CONTROL, DC_I2C_SW_STATUS_RESET, mask_sh),\ - I2C_SF(DC_I2C_CONTROL, DC_I2C_GO, mask_sh),\ - I2C_SF(DC_I2C_CONTROL, DC_I2C_SEND_RESET, mask_sh),\ - I2C_SF(DC_I2C_CONTROL, DC_I2C_TRANSACTION_COUNT, mask_sh),\ - I2C_SF(DC_I2C_CONTROL, DC_I2C_DDC_SELECT, mask_sh),\ - I2C_SF(DC_I2C_DDC1_SPEED, DC_I2C_DDC1_PRESCALE, mask_sh),\ - I2C_SF(DC_I2C_DDC1_SPEED, DC_I2C_DDC1_THRESHOLD, mask_sh),\ - I2C_SF(DC_I2C_SW_STATUS, DC_I2C_SW_STOPPED_ON_NACK, mask_sh),\ - I2C_SF(DC_I2C_SW_STATUS, DC_I2C_SW_TIMEOUT, mask_sh),\ - I2C_SF(DC_I2C_SW_STATUS, DC_I2C_SW_ABORTED, mask_sh),\ - I2C_SF(DC_I2C_SW_STATUS, DC_I2C_SW_DONE, mask_sh),\ - I2C_SF(DC_I2C_SW_STATUS, DC_I2C_SW_STATUS, mask_sh),\ - I2C_SF(DC_I2C_TRANSACTION0, DC_I2C_STOP_ON_NACK0, mask_sh),\ - I2C_SF(DC_I2C_TRANSACTION0, DC_I2C_START0, mask_sh),\ - I2C_SF(DC_I2C_TRANSACTION0, DC_I2C_RW0, mask_sh),\ - I2C_SF(DC_I2C_TRANSACTION0, DC_I2C_STOP0, mask_sh),\ - I2C_SF(DC_I2C_TRANSACTION0, DC_I2C_COUNT0, mask_sh),\ - I2C_SF(DC_I2C_DATA, DC_I2C_DATA_RW, mask_sh),\ - I2C_SF(DC_I2C_DATA, DC_I2C_DATA, mask_sh),\ - I2C_SF(DC_I2C_DATA, DC_I2C_INDEX, mask_sh),\ - I2C_SF(DC_I2C_DATA, DC_I2C_INDEX_WRITE, mask_sh),\ - I2C_SF(MICROSECOND_TIME_BASE_DIV, XTAL_REF_DIV, mask_sh) - -#define I2C_COMMON_MASK_SH_LIST_DCE100(mask_sh)\ - I2C_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh) - -#define I2C_COMMON_MASK_SH_LIST_DCE110(mask_sh)\ - I2C_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh),\ - I2C_SF(DC_I2C_DDC1_SPEED, DC_I2C_DDC1_START_STOP_TIMING_CNTL, mask_sh) - -struct dce110_i2c_hw_engine_shift { - uint8_t DC_I2C_DDC1_ENABLE; - uint8_t DC_I2C_DDC1_TIME_LIMIT; - uint8_t DC_I2C_DDC1_DATA_DRIVE_EN; - uint8_t DC_I2C_DDC1_CLK_DRIVE_EN; - uint8_t DC_I2C_DDC1_DATA_DRIVE_SEL; - uint8_t DC_I2C_DDC1_INTRA_TRANSACTION_DELAY; - uint8_t DC_I2C_DDC1_INTRA_BYTE_DELAY; - uint8_t DC_I2C_SW_DONE_USING_I2C_REG; - uint8_t DC_I2C_NO_QUEUED_SW_GO; - uint8_t DC_I2C_SW_PRIORITY; - uint8_t DC_I2C_SOFT_RESET; - uint8_t DC_I2C_SW_STATUS_RESET; - uint8_t DC_I2C_GO; - uint8_t DC_I2C_SEND_RESET; - uint8_t DC_I2C_TRANSACTION_COUNT; - uint8_t DC_I2C_DDC_SELECT; - uint8_t DC_I2C_DDC1_PRESCALE; - uint8_t DC_I2C_DDC1_THRESHOLD; - uint8_t DC_I2C_DDC1_START_STOP_TIMING_CNTL; - uint8_t DC_I2C_SW_STOPPED_ON_NACK; - uint8_t DC_I2C_SW_TIMEOUT; - uint8_t DC_I2C_SW_ABORTED; - uint8_t DC_I2C_SW_DONE; - uint8_t DC_I2C_SW_STATUS; - uint8_t DC_I2C_STOP_ON_NACK0; - uint8_t DC_I2C_START0; - uint8_t DC_I2C_RW0; - uint8_t DC_I2C_STOP0; - uint8_t DC_I2C_COUNT0; - uint8_t DC_I2C_DATA_RW; - uint8_t DC_I2C_DATA; - uint8_t DC_I2C_INDEX; - uint8_t DC_I2C_INDEX_WRITE; - uint8_t XTAL_REF_DIV; -}; - -struct dce110_i2c_hw_engine_mask { - uint32_t DC_I2C_DDC1_ENABLE; - uint32_t DC_I2C_DDC1_TIME_LIMIT; - uint32_t DC_I2C_DDC1_DATA_DRIVE_EN; - uint32_t DC_I2C_DDC1_CLK_DRIVE_EN; - uint32_t DC_I2C_DDC1_DATA_DRIVE_SEL; - uint32_t DC_I2C_DDC1_INTRA_TRANSACTION_DELAY; - uint32_t DC_I2C_DDC1_INTRA_BYTE_DELAY; - uint32_t DC_I2C_SW_DONE_USING_I2C_REG; - uint32_t DC_I2C_NO_QUEUED_SW_GO; - uint32_t DC_I2C_SW_PRIORITY; - uint32_t DC_I2C_SOFT_RESET; - uint32_t DC_I2C_SW_STATUS_RESET; - uint32_t DC_I2C_GO; - uint32_t DC_I2C_SEND_RESET; - uint32_t DC_I2C_TRANSACTION_COUNT; - uint32_t DC_I2C_DDC_SELECT; - uint32_t DC_I2C_DDC1_PRESCALE; - uint32_t DC_I2C_DDC1_THRESHOLD; - uint32_t DC_I2C_DDC1_START_STOP_TIMING_CNTL; - uint32_t DC_I2C_SW_STOPPED_ON_NACK; - uint32_t DC_I2C_SW_TIMEOUT; - uint32_t DC_I2C_SW_ABORTED; - uint32_t DC_I2C_SW_DONE; - uint32_t DC_I2C_SW_STATUS; - uint32_t DC_I2C_STOP_ON_NACK0; - uint32_t DC_I2C_START0; - uint32_t DC_I2C_RW0; - uint32_t DC_I2C_STOP0; - uint32_t DC_I2C_COUNT0; - uint32_t DC_I2C_DATA_RW; - uint32_t DC_I2C_DATA; - uint32_t DC_I2C_INDEX; - uint32_t DC_I2C_INDEX_WRITE; - uint32_t XTAL_REF_DIV; -}; - -struct dce110_i2c_hw_engine_registers { - uint32_t SETUP; - uint32_t SPEED; - uint32_t DC_I2C_ARBITRATION; - uint32_t DC_I2C_CONTROL; - uint32_t DC_I2C_SW_STATUS; - uint32_t DC_I2C_TRANSACTION0; - uint32_t DC_I2C_TRANSACTION1; - uint32_t DC_I2C_TRANSACTION2; - uint32_t DC_I2C_TRANSACTION3; - uint32_t DC_I2C_DATA; - uint32_t MICROSECOND_TIME_BASE_DIV; -}; - -struct i2c_hw_engine_dce110 { - struct i2c_hw_engine base; - const struct dce110_i2c_hw_engine_registers *regs; - const struct dce110_i2c_hw_engine_shift *i2c_shift; - const struct dce110_i2c_hw_engine_mask *i2c_mask; - struct { - uint32_t DC_I2C_DDCX_SETUP; - uint32_t DC_I2C_DDCX_SPEED; - } addr; - uint32_t engine_id; - /* expressed in kilohertz */ - uint32_t reference_frequency; - /* number of bytes currently used in HW buffer */ - uint32_t buffer_used_bytes; - /* number of bytes used for write transaction in HW buffer - * - this will be used as the index to read from*/ - uint32_t buffer_used_write; - /* number of pending transactions (before GO) */ - uint32_t transaction_count; - uint32_t engine_keep_power_up_count; - uint32_t i2_setup_time_limit; -}; - -struct i2c_hw_engine_dce110_create_arg { - uint32_t engine_id; - uint32_t reference_frequency; - uint32_t default_speed; - struct dc_context *ctx; - const struct dce110_i2c_hw_engine_registers *regs; - const struct dce110_i2c_hw_engine_shift *i2c_shift; - const struct dce110_i2c_hw_engine_mask *i2c_mask; -}; - -struct i2c_engine *dal_i2c_hw_engine_dce110_create( - const struct i2c_hw_engine_dce110_create_arg *arg); - -enum { - I2C_SETUP_TIME_LIMIT_DCE = 255, - I2C_SETUP_TIME_LIMIT_DCN = 3, - I2C_HW_BUFFER_SIZE = 538, - I2C_SEND_RESET_LENGTH_9 = 9, - I2C_SEND_RESET_LENGTH_10 = 10, -}; -#endif diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_sw_engine_dce110.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_sw_engine_dce110.c deleted file mode 100644 index 3aa7f791e523..000000000000 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_sw_engine_dce110.c +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" - -/* - * Pre-requisites: headers required by header of this unit - */ -#include "include/i2caux_interface.h" -#include "../engine.h" -#include "../i2c_engine.h" -#include "../i2c_sw_engine.h" - -/* - * Header of this unit - */ - -#include "i2c_sw_engine_dce110.h" - -/* - * Post-requisites: headers required by this unit - */ - -/* - * This unit - */ - -/* - * @brief - * Cast 'struct i2c_sw_engine *' - * to 'struct i2c_sw_engine_dce110 *' - */ -#define FROM_I2C_SW_ENGINE(ptr) \ - container_of((ptr), struct i2c_sw_engine_dce110, base) -/* - * @brief - * Cast 'struct i2c_engine *' - * to 'struct i2c_sw_engine_dce80 *' - */ -#define FROM_I2C_ENGINE(ptr) \ - FROM_I2C_SW_ENGINE(container_of((ptr), struct i2c_sw_engine, base)) - -/* - * @brief - * Cast 'struct engine *' - * to 'struct i2c_sw_engine_dce80 *' - */ -#define FROM_ENGINE(ptr) \ - FROM_I2C_ENGINE(container_of((ptr), struct i2c_engine, base)) - -static void release_engine( - struct engine *engine) -{ -} - -static void destruct( - struct i2c_sw_engine_dce110 *engine) -{ - dal_i2c_sw_engine_destruct(&engine->base); -} - -static void destroy( - struct i2c_engine **engine) -{ - struct i2c_sw_engine_dce110 *sw_engine = FROM_I2C_ENGINE(*engine); - - destruct(sw_engine); - - kfree(sw_engine); - - *engine = NULL; -} - -static bool acquire_engine( - struct i2c_engine *engine, - struct ddc *ddc_handle) -{ - return dal_i2caux_i2c_sw_engine_acquire_engine(engine, ddc_handle); -} - -static const struct i2c_engine_funcs i2c_engine_funcs = { - .acquire_engine = acquire_engine, - .destroy = destroy, - .get_speed = dal_i2c_sw_engine_get_speed, - .set_speed = dal_i2c_sw_engine_set_speed, - .setup_engine = dal_i2c_engine_setup_i2c_engine, - .submit_channel_request = dal_i2c_sw_engine_submit_channel_request, - .process_channel_reply = dal_i2c_engine_process_channel_reply, - .get_channel_status = dal_i2c_sw_engine_get_channel_status, -}; - -static const struct engine_funcs engine_funcs = { - .release_engine = release_engine, - .get_engine_type = dal_i2c_sw_engine_get_engine_type, - .acquire = dal_i2c_engine_acquire, - .submit_request = dal_i2c_sw_engine_submit_request, -}; - -static void construct( - struct i2c_sw_engine_dce110 *engine_dce110, - const struct i2c_sw_engine_dce110_create_arg *arg_dce110) -{ - struct i2c_sw_engine_create_arg arg_base; - - arg_base.ctx = arg_dce110->ctx; - arg_base.default_speed = arg_dce110->default_speed; - - dal_i2c_sw_engine_construct(&engine_dce110->base, &arg_base); - - /*struct engine struct engine_funcs*/ - engine_dce110->base.base.base.funcs = &engine_funcs; - /*struct i2c_engine struct i2c_engine_funcs*/ - engine_dce110->base.base.funcs = &i2c_engine_funcs; - engine_dce110->base.default_speed = arg_dce110->default_speed; - engine_dce110->engine_id = arg_dce110->engine_id; -} - -struct i2c_engine *dal_i2c_sw_engine_dce110_create( - const struct i2c_sw_engine_dce110_create_arg *arg) -{ - struct i2c_sw_engine_dce110 *engine_dce110; - - if (!arg) { - ASSERT_CRITICAL(false); - return NULL; - } - - engine_dce110 = kzalloc(sizeof(struct i2c_sw_engine_dce110), - GFP_KERNEL); - - if (!engine_dce110) { - ASSERT_CRITICAL(false); - return NULL; - } - - construct(engine_dce110, arg); - return &engine_dce110->base.base; -} diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2caux_dce110.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2caux_dce110.c deleted file mode 100644 index 1d748ac1d6d6..000000000000 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2caux_dce110.c +++ /dev/null @@ -1,329 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" - -/* - * Pre-requisites: headers required by header of this unit - */ -#include "include/i2caux_interface.h" -#include "../i2caux.h" -#include "../engine.h" -#include "../i2c_engine.h" -#include "../i2c_sw_engine.h" -#include "../i2c_hw_engine.h" - -/* - * Header of this unit - */ -#include "i2caux_dce110.h" - -#include "i2c_sw_engine_dce110.h" -#include "i2c_hw_engine_dce110.h" -#include "aux_engine_dce110.h" -#include "../../dc.h" -#include "dc_types.h" - - -/* - * Post-requisites: headers required by this unit - */ - -/* - * This unit - */ -/*cast pointer to struct i2caux TO pointer to struct i2caux_dce110*/ -#define FROM_I2C_AUX(ptr) \ - container_of((ptr), struct i2caux_dce110, base) - -static void destruct( - struct i2caux_dce110 *i2caux_dce110) -{ - dal_i2caux_destruct(&i2caux_dce110->base); -} - -static void destroy( - struct i2caux **i2c_engine) -{ - struct i2caux_dce110 *i2caux_dce110 = FROM_I2C_AUX(*i2c_engine); - - destruct(i2caux_dce110); - - kfree(i2caux_dce110); - - *i2c_engine = NULL; -} - -static struct i2c_engine *acquire_i2c_hw_engine( - struct i2caux *i2caux, - struct ddc *ddc) -{ - struct i2caux_dce110 *i2caux_dce110 = FROM_I2C_AUX(i2caux); - - struct i2c_engine *engine = NULL; - /* generic hw engine is not used for EDID read - * It may be needed for external i2c device, like thermal chip, - * TODO will be implemented when needed. - * check dce80 bool non_generic for generic hw engine; - */ - - if (!ddc) - return NULL; - - if (ddc->hw_info.hw_supported) { - enum gpio_ddc_line line = dal_ddc_get_line(ddc); - - if (line < GPIO_DDC_LINE_COUNT) - engine = i2caux->i2c_hw_engines[line]; - } - - if (!engine) - return NULL; - - if (!i2caux_dce110->i2c_hw_buffer_in_use && - engine->base.funcs->acquire(&engine->base, ddc)) { - i2caux_dce110->i2c_hw_buffer_in_use = true; - return engine; - } - - return NULL; -} - -static void release_engine( - struct i2caux *i2caux, - struct engine *engine) -{ - struct i2caux_dce110 *i2caux_dce110 = FROM_I2C_AUX(i2caux); - - if (engine->funcs->get_engine_type(engine) == - I2CAUX_ENGINE_TYPE_I2C_DDC_HW) - i2caux_dce110->i2c_hw_buffer_in_use = false; - - dal_i2caux_release_engine(i2caux, engine); -} - -static const enum gpio_ddc_line hw_ddc_lines[] = { - GPIO_DDC_LINE_DDC1, - GPIO_DDC_LINE_DDC2, - GPIO_DDC_LINE_DDC3, - GPIO_DDC_LINE_DDC4, - GPIO_DDC_LINE_DDC5, - GPIO_DDC_LINE_DDC6, -}; - -static const enum gpio_ddc_line hw_aux_lines[] = { - GPIO_DDC_LINE_DDC1, - GPIO_DDC_LINE_DDC2, - GPIO_DDC_LINE_DDC3, - GPIO_DDC_LINE_DDC4, - GPIO_DDC_LINE_DDC5, - GPIO_DDC_LINE_DDC6, -}; - -/* function table */ -static const struct i2caux_funcs i2caux_funcs = { - .destroy = destroy, - .acquire_i2c_hw_engine = acquire_i2c_hw_engine, - .release_engine = release_engine, - .acquire_i2c_sw_engine = dal_i2caux_acquire_i2c_sw_engine, - .acquire_aux_engine = dal_i2caux_acquire_aux_engine, -}; - -#include "dce/dce_11_0_d.h" -#include "dce/dce_11_0_sh_mask.h" - -/* set register offset */ -#define SR(reg_name)\ - .reg_name = mm ## reg_name - -/* set register offset with instance */ -#define SRI(reg_name, block, id)\ - .reg_name = mm ## block ## id ## _ ## reg_name - -#define aux_regs(id)\ -[id] = {\ - AUX_COMMON_REG_LIST(id), \ - .AUX_RESET_MASK = AUX_CONTROL__AUX_RESET_MASK \ -} - -#define hw_engine_regs(id)\ -{\ - I2C_HW_ENGINE_COMMON_REG_LIST(id) \ -} - -static const struct dce110_aux_registers dce110_aux_regs[] = { - aux_regs(0), - aux_regs(1), - aux_regs(2), - aux_regs(3), - aux_regs(4), - aux_regs(5) -}; - -static const struct dce110_i2c_hw_engine_registers i2c_hw_engine_regs[] = { - hw_engine_regs(1), - hw_engine_regs(2), - hw_engine_regs(3), - hw_engine_regs(4), - hw_engine_regs(5), - hw_engine_regs(6) -}; - -static const struct dce110_i2c_hw_engine_shift i2c_shift = { - I2C_COMMON_MASK_SH_LIST_DCE110(__SHIFT) -}; - -static const struct dce110_i2c_hw_engine_mask i2c_mask = { - I2C_COMMON_MASK_SH_LIST_DCE110(_MASK) -}; - -void dal_i2caux_dce110_construct( - struct i2caux_dce110 *i2caux_dce110, - struct dc_context *ctx, - unsigned int num_i2caux_inst, - const struct dce110_aux_registers aux_regs[], - const struct dce110_i2c_hw_engine_registers i2c_hw_engine_regs[], - const struct dce110_i2c_hw_engine_shift *i2c_shift, - const struct dce110_i2c_hw_engine_mask *i2c_mask) -{ - uint32_t i = 0; - uint32_t reference_frequency = 0; - bool use_i2c_sw_engine = false; - struct i2caux *base = NULL; - /*TODO: For CZ bring up, if dal_i2caux_get_reference_clock - * does not return 48KHz, we need hard coded for 48Khz. - * Some BIOS setting incorrect cause this - * For production, we always get value from BIOS*/ - reference_frequency = - dal_i2caux_get_reference_clock(ctx->dc_bios) >> 1; - - base = &i2caux_dce110->base; - - dal_i2caux_construct(base, ctx); - - i2caux_dce110->base.funcs = &i2caux_funcs; - i2caux_dce110->i2c_hw_buffer_in_use = false; - /* Create I2C engines (DDC lines per connector) - * different I2C/AUX usage cases, DDC, Generic GPIO, AUX. - */ - do { - enum gpio_ddc_line line_id = hw_ddc_lines[i]; - - struct i2c_hw_engine_dce110_create_arg hw_arg_dce110; - - if (use_i2c_sw_engine) { - struct i2c_sw_engine_dce110_create_arg sw_arg; - - sw_arg.engine_id = i; - sw_arg.default_speed = base->default_i2c_sw_speed; - sw_arg.ctx = ctx; - base->i2c_sw_engines[line_id] = - dal_i2c_sw_engine_dce110_create(&sw_arg); - } - - hw_arg_dce110.engine_id = i; - hw_arg_dce110.reference_frequency = reference_frequency; - hw_arg_dce110.default_speed = base->default_i2c_hw_speed; - hw_arg_dce110.ctx = ctx; - hw_arg_dce110.regs = &i2c_hw_engine_regs[i]; - hw_arg_dce110.i2c_shift = i2c_shift; - hw_arg_dce110.i2c_mask = i2c_mask; - - base->i2c_hw_engines[line_id] = - dal_i2c_hw_engine_dce110_create(&hw_arg_dce110); - if (base->i2c_hw_engines[line_id] != NULL) { - switch (ctx->dce_version) { - case DCN_VERSION_1_0: - base->i2c_hw_engines[line_id]->setup_limit = - I2C_SETUP_TIME_LIMIT_DCN; - base->i2c_hw_engines[line_id]->send_reset_length = 0; - break; - default: - base->i2c_hw_engines[line_id]->setup_limit = - I2C_SETUP_TIME_LIMIT_DCE; - base->i2c_hw_engines[line_id]->send_reset_length = 0; - break; - } - } - ++i; - } while (i < num_i2caux_inst); - - /* Create AUX engines for all lines which has assisted HW AUX - * 'i' (loop counter) used as DDC/AUX engine_id */ - - i = 0; - - do { - enum gpio_ddc_line line_id = hw_aux_lines[i]; - - struct aux_engine_dce110_init_data aux_init_data; - - aux_init_data.engine_id = i; - aux_init_data.timeout_period = base->aux_timeout_period; - aux_init_data.ctx = ctx; - aux_init_data.regs = &aux_regs[i]; - - base->aux_engines[line_id] = - dal_aux_engine_dce110_create(&aux_init_data); - - ++i; - } while (i < num_i2caux_inst); - - /*TODO Generic I2C SW and HW*/ -} - -/* - * dal_i2caux_dce110_create - * - * @brief - * public interface to allocate memory for DCE11 I2CAUX - * - * @param - * struct adapter_service *as - [in] - * struct dc_context *ctx - [in] - * - * @return - * pointer to the base struct of DCE11 I2CAUX - */ -struct i2caux *dal_i2caux_dce110_create( - struct dc_context *ctx) -{ - struct i2caux_dce110 *i2caux_dce110 = - kzalloc(sizeof(struct i2caux_dce110), GFP_KERNEL); - - if (!i2caux_dce110) { - ASSERT_CRITICAL(false); - return NULL; - } - - dal_i2caux_dce110_construct(i2caux_dce110, - ctx, - ARRAY_SIZE(dce110_aux_regs), - dce110_aux_regs, - i2c_hw_engine_regs, - &i2c_shift, - &i2c_mask); - return &i2caux_dce110->base; -} diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2caux_dce110.h b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2caux_dce110.h deleted file mode 100644 index d3d8cc58666a..000000000000 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2caux_dce110.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#ifndef __DAL_I2C_AUX_DCE110_H__ -#define __DAL_I2C_AUX_DCE110_H__ - -#include "../i2caux.h" - -struct i2caux_dce110 { - struct i2caux base; - /* indicate the I2C HW circular buffer is in use */ - bool i2c_hw_buffer_in_use; -}; - -struct dce110_aux_registers; -struct dce110_i2c_hw_engine_registers; -struct dce110_i2c_hw_engine_shift; -struct dce110_i2c_hw_engine_mask; - -struct i2caux *dal_i2caux_dce110_create( - struct dc_context *ctx); - -void dal_i2caux_dce110_construct( - struct i2caux_dce110 *i2caux_dce110, - struct dc_context *ctx, - unsigned int num_i2caux_inst, - const struct dce110_aux_registers *aux_regs, - const struct dce110_i2c_hw_engine_registers *i2c_hw_engine_regs, - const struct dce110_i2c_hw_engine_shift *i2c_shift, - const struct dce110_i2c_hw_engine_mask *i2c_mask); - -#endif /* __DAL_I2C_AUX_DCE110_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce112/i2caux_dce112.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce112/i2caux_dce112.c deleted file mode 100644 index a9db04738724..000000000000 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dce112/i2caux_dce112.c +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" - -#include "include/i2caux_interface.h" -#include "../i2caux.h" -#include "../engine.h" -#include "../i2c_engine.h" -#include "../i2c_sw_engine.h" -#include "../i2c_hw_engine.h" - -#include "../dce110/i2caux_dce110.h" -#include "i2caux_dce112.h" - -#include "../dce110/aux_engine_dce110.h" - -#include "../dce110/i2c_hw_engine_dce110.h" - -#include "dce/dce_11_2_d.h" -#include "dce/dce_11_2_sh_mask.h" - -/* set register offset */ -#define SR(reg_name)\ - .reg_name = mm ## reg_name - -/* set register offset with instance */ -#define SRI(reg_name, block, id)\ - .reg_name = mm ## block ## id ## _ ## reg_name - -#define aux_regs(id)\ -[id] = {\ - AUX_COMMON_REG_LIST(id), \ - .AUX_RESET_MASK = AUX_CONTROL__AUX_RESET_MASK \ -} - -#define hw_engine_regs(id)\ -{\ - I2C_HW_ENGINE_COMMON_REG_LIST(id) \ -} - -static const struct dce110_aux_registers dce112_aux_regs[] = { - aux_regs(0), - aux_regs(1), - aux_regs(2), - aux_regs(3), - aux_regs(4), - aux_regs(5), -}; - -static const struct dce110_i2c_hw_engine_registers dce112_hw_engine_regs[] = { - hw_engine_regs(1), - hw_engine_regs(2), - hw_engine_regs(3), - hw_engine_regs(4), - hw_engine_regs(5), - hw_engine_regs(6) -}; - -static const struct dce110_i2c_hw_engine_shift i2c_shift = { - I2C_COMMON_MASK_SH_LIST_DCE110(__SHIFT) -}; - -static const struct dce110_i2c_hw_engine_mask i2c_mask = { - I2C_COMMON_MASK_SH_LIST_DCE110(_MASK) -}; - -static void construct( - struct i2caux_dce110 *i2caux_dce110, - struct dc_context *ctx) -{ - dal_i2caux_dce110_construct(i2caux_dce110, - ctx, - ARRAY_SIZE(dce112_aux_regs), - dce112_aux_regs, - dce112_hw_engine_regs, - &i2c_shift, - &i2c_mask); -} - -/* - * dal_i2caux_dce110_create - * - * @brief - * public interface to allocate memory for DCE11 I2CAUX - * - * @param - * struct adapter_service *as - [in] - * struct dc_context *ctx - [in] - * - * @return - * pointer to the base struct of DCE11 I2CAUX - */ -struct i2caux *dal_i2caux_dce112_create( - struct dc_context *ctx) -{ - struct i2caux_dce110 *i2caux_dce110 = - kzalloc(sizeof(struct i2caux_dce110), GFP_KERNEL); - - if (!i2caux_dce110) { - ASSERT_CRITICAL(false); - return NULL; - } - - construct(i2caux_dce110, ctx); - return &i2caux_dce110->base; -} diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce112/i2caux_dce112.h b/drivers/gpu/drm/amd/display/dc/i2caux/dce112/i2caux_dce112.h deleted file mode 100644 index 8d35453c25b6..000000000000 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dce112/i2caux_dce112.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#ifndef __DAL_I2C_AUX_DCE112_H__ -#define __DAL_I2C_AUX_DCE112_H__ - -struct i2caux *dal_i2caux_dce112_create( - struct dc_context *ctx); - -#endif /* __DAL_I2C_AUX_DCE112_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce120/i2caux_dce120.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce120/i2caux_dce120.c deleted file mode 100644 index 6a4f344c1db4..000000000000 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dce120/i2caux_dce120.c +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright 2012-16 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" - -#include "include/i2caux_interface.h" -#include "../i2caux.h" -#include "../engine.h" -#include "../i2c_engine.h" -#include "../i2c_sw_engine.h" -#include "../i2c_hw_engine.h" - -#include "../dce110/i2c_hw_engine_dce110.h" -#include "../dce110/aux_engine_dce110.h" -#include "../dce110/i2caux_dce110.h" - -#include "dce/dce_12_0_offset.h" -#include "dce/dce_12_0_sh_mask.h" -#include "soc15_hw_ip.h" -#include "vega10_ip_offset.h" - -/* begin ********************* - * macros to expend register list macro defined in HW object header file */ - -#define BASE_INNER(seg) \ - DCE_BASE__INST0_SEG ## seg - -/* compile time expand base address. */ -#define BASE(seg) \ - BASE_INNER(seg) - -#define SR(reg_name)\ - .reg_name = BASE(mm ## reg_name ## _BASE_IDX) + \ - mm ## reg_name - -#define SRI(reg_name, block, id)\ - .reg_name = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - mm ## block ## id ## _ ## reg_name -/* macros to expend register list macro defined in HW object header file - * end *********************/ - -#define aux_regs(id)\ -[id] = {\ - AUX_COMMON_REG_LIST(id), \ - .AUX_RESET_MASK = DP_AUX0_AUX_CONTROL__AUX_RESET_MASK \ -} - -static const struct dce110_aux_registers dce120_aux_regs[] = { - aux_regs(0), - aux_regs(1), - aux_regs(2), - aux_regs(3), - aux_regs(4), - aux_regs(5), -}; - -#define hw_engine_regs(id)\ -{\ - I2C_HW_ENGINE_COMMON_REG_LIST(id) \ -} - -static const struct dce110_i2c_hw_engine_registers dce120_hw_engine_regs[] = { - hw_engine_regs(1), - hw_engine_regs(2), - hw_engine_regs(3), - hw_engine_regs(4), - hw_engine_regs(5), - hw_engine_regs(6) -}; - -static const struct dce110_i2c_hw_engine_shift i2c_shift = { - I2C_COMMON_MASK_SH_LIST_DCE110(__SHIFT) -}; - -static const struct dce110_i2c_hw_engine_mask i2c_mask = { - I2C_COMMON_MASK_SH_LIST_DCE110(_MASK) -}; - -struct i2caux *dal_i2caux_dce120_create( - struct dc_context *ctx) -{ - struct i2caux_dce110 *i2caux_dce110 = - kzalloc(sizeof(struct i2caux_dce110), GFP_KERNEL); - - if (!i2caux_dce110) { - ASSERT_CRITICAL(false); - return NULL; - } - - dal_i2caux_dce110_construct(i2caux_dce110, - ctx, - ARRAY_SIZE(dce120_aux_regs), - dce120_aux_regs, - dce120_hw_engine_regs, - &i2c_shift, - &i2c_mask); - return &i2caux_dce110->base; -} diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce120/i2caux_dce120.h b/drivers/gpu/drm/amd/display/dc/i2caux/dce120/i2caux_dce120.h deleted file mode 100644 index b6ac47617c70..000000000000 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dce120/i2caux_dce120.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2012-16 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#ifndef __DAL_I2C_AUX_DCE120_H__ -#define __DAL_I2C_AUX_DCE120_H__ - -struct i2caux *dal_i2caux_dce120_create( - struct dc_context *ctx); - -#endif /* __DAL_I2C_AUX_DCE120_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_hw_engine_dce80.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_hw_engine_dce80.c deleted file mode 100644 index fd0832dd2c75..000000000000 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_hw_engine_dce80.c +++ /dev/null @@ -1,875 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" - -/* - * Pre-requisites: headers required by header of this unit - */ -#include "include/i2caux_interface.h" -#include "../engine.h" -#include "../i2c_engine.h" -#include "../i2c_hw_engine.h" -#include "../i2c_generic_hw_engine.h" -/* - * Header of this unit - */ - -#include "i2c_hw_engine_dce80.h" - -/* - * Post-requisites: headers required by this unit - */ - -#include "dce/dce_8_0_d.h" -#include "dce/dce_8_0_sh_mask.h" -/* - * This unit - */ - -enum dc_i2c_status { - DC_I2C_STATUS__DC_I2C_STATUS_IDLE, - DC_I2C_STATUS__DC_I2C_STATUS_USED_BY_SW, - DC_I2C_STATUS__DC_I2C_STATUS_USED_BY_HW -}; - -enum dc_i2c_arbitration { - DC_I2C_ARBITRATION__DC_I2C_SW_PRIORITY_NORMAL, - DC_I2C_ARBITRATION__DC_I2C_SW_PRIORITY_HIGH -}; - -enum { - /* No timeout in HW - * (timeout implemented in SW by querying status) */ - I2C_SETUP_TIME_LIMIT = 255, - I2C_HW_BUFFER_SIZE = 144 -}; - -/* - * @brief - * Cast 'struct i2c_hw_engine *' - * to 'struct i2c_hw_engine_dce80 *' - */ -#define FROM_I2C_HW_ENGINE(ptr) \ - container_of((ptr), struct i2c_hw_engine_dce80, base) - -/* - * @brief - * Cast pointer to 'struct i2c_engine *' - * to pointer to 'struct i2c_hw_engine_dce80 *' - */ -#define FROM_I2C_ENGINE(ptr) \ - FROM_I2C_HW_ENGINE(container_of((ptr), struct i2c_hw_engine, base)) - -/* - * @brief - * Cast pointer to 'struct engine *' - * to 'pointer to struct i2c_hw_engine_dce80 *' - */ -#define FROM_ENGINE(ptr) \ - FROM_I2C_ENGINE(container_of((ptr), struct i2c_engine, base)) - -static void disable_i2c_hw_engine( - struct i2c_hw_engine_dce80 *engine) -{ - const uint32_t addr = engine->addr.DC_I2C_DDCX_SETUP; - uint32_t value = 0; - - struct dc_context *ctx = NULL; - - ctx = engine->base.base.base.ctx; - - value = dm_read_reg(ctx, addr); - - set_reg_field_value( - value, - 0, - DC_I2C_DDC1_SETUP, - DC_I2C_DDC1_ENABLE); - - dm_write_reg(ctx, addr, value); -} - -static void release_engine( - struct engine *engine) -{ - struct i2c_hw_engine_dce80 *hw_engine = FROM_ENGINE(engine); - - struct i2c_engine *base = NULL; - bool safe_to_reset; - uint32_t value = 0; - - base = &hw_engine->base.base; - - /* Restore original HW engine speed */ - - base->funcs->set_speed(base, hw_engine->base.original_speed); - - /* Release I2C */ - { - value = dm_read_reg(engine->ctx, mmDC_I2C_ARBITRATION); - - set_reg_field_value( - value, - 1, - DC_I2C_ARBITRATION, - DC_I2C_SW_DONE_USING_I2C_REG); - - dm_write_reg(engine->ctx, mmDC_I2C_ARBITRATION, value); - } - - /* Reset HW engine */ - { - uint32_t i2c_sw_status = 0; - - value = dm_read_reg(engine->ctx, mmDC_I2C_SW_STATUS); - - i2c_sw_status = get_reg_field_value( - value, - DC_I2C_SW_STATUS, - DC_I2C_SW_STATUS); - /* if used by SW, safe to reset */ - safe_to_reset = (i2c_sw_status == 1); - } - { - value = dm_read_reg(engine->ctx, mmDC_I2C_CONTROL); - - if (safe_to_reset) - set_reg_field_value( - value, - 1, - DC_I2C_CONTROL, - DC_I2C_SOFT_RESET); - - set_reg_field_value( - value, - 1, - DC_I2C_CONTROL, - DC_I2C_SW_STATUS_RESET); - - dm_write_reg(engine->ctx, mmDC_I2C_CONTROL, value); - } - - /* HW I2c engine - clock gating feature */ - if (!hw_engine->engine_keep_power_up_count) - disable_i2c_hw_engine(hw_engine); -} - -static void destruct( - struct i2c_hw_engine_dce80 *engine) -{ - dal_i2c_hw_engine_destruct(&engine->base); -} - -static void destroy( - struct i2c_engine **i2c_engine) -{ - struct i2c_hw_engine_dce80 *engine = FROM_I2C_ENGINE(*i2c_engine); - - destruct(engine); - - kfree(engine); - - *i2c_engine = NULL; -} - -static bool setup_engine( - struct i2c_engine *i2c_engine) -{ - uint32_t value = 0; - struct i2c_hw_engine_dce80 *engine = FROM_I2C_ENGINE(i2c_engine); - - /* Program pin select */ - { - const uint32_t addr = mmDC_I2C_CONTROL; - - value = dm_read_reg(i2c_engine->base.ctx, addr); - - set_reg_field_value( - value, - 0, - DC_I2C_CONTROL, - DC_I2C_GO); - - set_reg_field_value( - value, - 0, - DC_I2C_CONTROL, - DC_I2C_SOFT_RESET); - - set_reg_field_value( - value, - 0, - DC_I2C_CONTROL, - DC_I2C_SEND_RESET); - - set_reg_field_value( - value, - 0, - DC_I2C_CONTROL, - DC_I2C_SW_STATUS_RESET); - - set_reg_field_value( - value, - 0, - DC_I2C_CONTROL, - DC_I2C_TRANSACTION_COUNT); - - set_reg_field_value( - value, - engine->engine_id, - DC_I2C_CONTROL, - DC_I2C_DDC_SELECT); - - dm_write_reg(i2c_engine->base.ctx, addr, value); - } - - /* Program time limit */ - { - const uint32_t addr = engine->addr.DC_I2C_DDCX_SETUP; - - value = dm_read_reg(i2c_engine->base.ctx, addr); - - set_reg_field_value( - value, - I2C_SETUP_TIME_LIMIT, - DC_I2C_DDC1_SETUP, - DC_I2C_DDC1_TIME_LIMIT); - - set_reg_field_value( - value, - 1, - DC_I2C_DDC1_SETUP, - DC_I2C_DDC1_ENABLE); - - dm_write_reg(i2c_engine->base.ctx, addr, value); - } - - /* Program HW priority - * set to High - interrupt software I2C at any time - * Enable restart of SW I2C that was interrupted by HW - * disable queuing of software while I2C is in use by HW */ - { - value = dm_read_reg(i2c_engine->base.ctx, - mmDC_I2C_ARBITRATION); - - set_reg_field_value( - value, - 0, - DC_I2C_ARBITRATION, - DC_I2C_NO_QUEUED_SW_GO); - - set_reg_field_value( - value, - DC_I2C_ARBITRATION__DC_I2C_SW_PRIORITY_NORMAL, - DC_I2C_ARBITRATION, - DC_I2C_SW_PRIORITY); - - dm_write_reg(i2c_engine->base.ctx, - mmDC_I2C_ARBITRATION, value); - } - - return true; -} - -static uint32_t get_speed( - const struct i2c_engine *i2c_engine) -{ - const struct i2c_hw_engine_dce80 *engine = FROM_I2C_ENGINE(i2c_engine); - - const uint32_t addr = engine->addr.DC_I2C_DDCX_SPEED; - - uint32_t pre_scale = 0; - - uint32_t value = dm_read_reg(i2c_engine->base.ctx, addr); - - pre_scale = get_reg_field_value( - value, - DC_I2C_DDC1_SPEED, - DC_I2C_DDC1_PRESCALE); - - /* [anaumov] it seems following is unnecessary */ - /*ASSERT(value.bits.DC_I2C_DDC1_PRESCALE);*/ - - return pre_scale ? - engine->reference_frequency / pre_scale : - engine->base.default_speed; -} - -static void set_speed( - struct i2c_engine *i2c_engine, - uint32_t speed) -{ - struct i2c_hw_engine_dce80 *engine = FROM_I2C_ENGINE(i2c_engine); - - if (speed) { - const uint32_t addr = engine->addr.DC_I2C_DDCX_SPEED; - - uint32_t value = dm_read_reg(i2c_engine->base.ctx, addr); - - set_reg_field_value( - value, - engine->reference_frequency / speed, - DC_I2C_DDC1_SPEED, - DC_I2C_DDC1_PRESCALE); - - set_reg_field_value( - value, - 2, - DC_I2C_DDC1_SPEED, - DC_I2C_DDC1_THRESHOLD); - - dm_write_reg(i2c_engine->base.ctx, addr, value); - } -} - -static inline void reset_hw_engine(struct engine *engine) -{ - uint32_t value = dm_read_reg(engine->ctx, mmDC_I2C_CONTROL); - - set_reg_field_value( - value, - 1, - DC_I2C_CONTROL, - DC_I2C_SOFT_RESET); - - set_reg_field_value( - value, - 1, - DC_I2C_CONTROL, - DC_I2C_SW_STATUS_RESET); - - dm_write_reg(engine->ctx, mmDC_I2C_CONTROL, value); -} - -static bool is_hw_busy(struct engine *engine) -{ - uint32_t i2c_sw_status = 0; - - uint32_t value = dm_read_reg(engine->ctx, mmDC_I2C_SW_STATUS); - - i2c_sw_status = get_reg_field_value( - value, - DC_I2C_SW_STATUS, - DC_I2C_SW_STATUS); - - if (i2c_sw_status == DC_I2C_STATUS__DC_I2C_STATUS_IDLE) - return false; - - reset_hw_engine(engine); - - value = dm_read_reg(engine->ctx, mmDC_I2C_SW_STATUS); - - i2c_sw_status = get_reg_field_value( - value, - DC_I2C_SW_STATUS, - DC_I2C_SW_STATUS); - - return i2c_sw_status != DC_I2C_STATUS__DC_I2C_STATUS_IDLE; -} - -/* - * @brief - * DC_GPIO_DDC MM register offsets - */ -static const uint32_t transaction_addr[] = { - mmDC_I2C_TRANSACTION0, - mmDC_I2C_TRANSACTION1, - mmDC_I2C_TRANSACTION2, - mmDC_I2C_TRANSACTION3 -}; - -static bool process_transaction( - struct i2c_hw_engine_dce80 *engine, - struct i2c_request_transaction_data *request) -{ - uint32_t length = request->length; - uint8_t *buffer = request->data; - - bool last_transaction = false; - uint32_t value = 0; - - struct dc_context *ctx = NULL; - - ctx = engine->base.base.base.ctx; - - { - const uint32_t addr = - transaction_addr[engine->transaction_count]; - - value = dm_read_reg(ctx, addr); - - set_reg_field_value( - value, - 1, - DC_I2C_TRANSACTION0, - DC_I2C_STOP_ON_NACK0); - - set_reg_field_value( - value, - 1, - DC_I2C_TRANSACTION0, - DC_I2C_START0); - - if ((engine->transaction_count == 3) || - (request->action == I2CAUX_TRANSACTION_ACTION_I2C_WRITE) || - (request->action & I2CAUX_TRANSACTION_ACTION_I2C_READ)) { - - set_reg_field_value( - value, - 1, - DC_I2C_TRANSACTION0, - DC_I2C_STOP0); - - last_transaction = true; - } else - set_reg_field_value( - value, - 0, - DC_I2C_TRANSACTION0, - DC_I2C_STOP0); - - set_reg_field_value( - value, - (0 != (request->action & - I2CAUX_TRANSACTION_ACTION_I2C_READ)), - DC_I2C_TRANSACTION0, - DC_I2C_RW0); - - set_reg_field_value( - value, - length, - DC_I2C_TRANSACTION0, - DC_I2C_COUNT0); - - dm_write_reg(ctx, addr, value); - } - - /* Write the I2C address and I2C data - * into the hardware circular buffer, one byte per entry. - * As an example, the 7-bit I2C slave address for CRT monitor - * for reading DDC/EDID information is 0b1010001. - * For an I2C send operation, the LSB must be programmed to 0; - * for I2C receive operation, the LSB must be programmed to 1. */ - - { - value = 0; - - set_reg_field_value( - value, - false, - DC_I2C_DATA, - DC_I2C_DATA_RW); - - set_reg_field_value( - value, - request->address, - DC_I2C_DATA, - DC_I2C_DATA); - - if (engine->transaction_count == 0) { - set_reg_field_value( - value, - 0, - DC_I2C_DATA, - DC_I2C_INDEX); - - /*enable index write*/ - set_reg_field_value( - value, - 1, - DC_I2C_DATA, - DC_I2C_INDEX_WRITE); - } - - dm_write_reg(ctx, mmDC_I2C_DATA, value); - - if (!(request->action & I2CAUX_TRANSACTION_ACTION_I2C_READ)) { - - set_reg_field_value( - value, - 0, - DC_I2C_DATA, - DC_I2C_INDEX_WRITE); - - while (length) { - - set_reg_field_value( - value, - *buffer++, - DC_I2C_DATA, - DC_I2C_DATA); - - dm_write_reg(ctx, mmDC_I2C_DATA, value); - --length; - } - } - } - - ++engine->transaction_count; - engine->buffer_used_bytes += length + 1; - - return last_transaction; -} - -static void execute_transaction( - struct i2c_hw_engine_dce80 *engine) -{ - uint32_t value = 0; - struct dc_context *ctx = NULL; - - ctx = engine->base.base.base.ctx; - - { - const uint32_t addr = engine->addr.DC_I2C_DDCX_SETUP; - - value = dm_read_reg(ctx, addr); - - set_reg_field_value( - value, - 0, - DC_I2C_DDC1_SETUP, - DC_I2C_DDC1_DATA_DRIVE_EN); - - set_reg_field_value( - value, - 0, - DC_I2C_DDC1_SETUP, - DC_I2C_DDC1_CLK_DRIVE_EN); - - set_reg_field_value( - value, - 0, - DC_I2C_DDC1_SETUP, - DC_I2C_DDC1_DATA_DRIVE_SEL); - - set_reg_field_value( - value, - 0, - DC_I2C_DDC1_SETUP, - DC_I2C_DDC1_INTRA_TRANSACTION_DELAY); - - set_reg_field_value( - value, - 0, - DC_I2C_DDC1_SETUP, - DC_I2C_DDC1_INTRA_BYTE_DELAY); - - dm_write_reg(ctx, addr, value); - } - - { - const uint32_t addr = mmDC_I2C_CONTROL; - - value = dm_read_reg(ctx, addr); - - set_reg_field_value( - value, - 0, - DC_I2C_CONTROL, - DC_I2C_SOFT_RESET); - - set_reg_field_value( - value, - 0, - DC_I2C_CONTROL, - DC_I2C_SW_STATUS_RESET); - - set_reg_field_value( - value, - 0, - DC_I2C_CONTROL, - DC_I2C_SEND_RESET); - - set_reg_field_value( - value, - 0, - DC_I2C_CONTROL, - DC_I2C_GO); - - set_reg_field_value( - value, - engine->transaction_count - 1, - DC_I2C_CONTROL, - DC_I2C_TRANSACTION_COUNT); - - dm_write_reg(ctx, addr, value); - } - - /* start I2C transfer */ - { - const uint32_t addr = mmDC_I2C_CONTROL; - - value = dm_read_reg(ctx, addr); - - set_reg_field_value( - value, - 1, - DC_I2C_CONTROL, - DC_I2C_GO); - - dm_write_reg(ctx, addr, value); - } - - /* all transactions were executed and HW buffer became empty - * (even though it actually happens when status becomes DONE) */ - engine->transaction_count = 0; - engine->buffer_used_bytes = 0; -} - -static void submit_channel_request( - struct i2c_engine *engine, - struct i2c_request_transaction_data *request) -{ - request->status = I2C_CHANNEL_OPERATION_SUCCEEDED; - - if (!process_transaction(FROM_I2C_ENGINE(engine), request)) - return; - - if (is_hw_busy(&engine->base)) { - request->status = I2C_CHANNEL_OPERATION_ENGINE_BUSY; - return; - } - - execute_transaction(FROM_I2C_ENGINE(engine)); -} - -static void process_channel_reply( - struct i2c_engine *engine, - struct i2c_reply_transaction_data *reply) -{ - uint32_t length = reply->length; - uint8_t *buffer = reply->data; - - uint32_t value = 0; - - /*set index*/ - set_reg_field_value( - value, - length - 1, - DC_I2C_DATA, - DC_I2C_INDEX); - - set_reg_field_value( - value, - 1, - DC_I2C_DATA, - DC_I2C_DATA_RW); - - set_reg_field_value( - value, - 1, - DC_I2C_DATA, - DC_I2C_INDEX_WRITE); - - dm_write_reg(engine->base.ctx, mmDC_I2C_DATA, value); - - while (length) { - /* after reading the status, - * if the I2C operation executed successfully - * (i.e. DC_I2C_STATUS_DONE = 1) then the I2C controller - * should read data bytes from I2C circular data buffer */ - - value = dm_read_reg(engine->base.ctx, mmDC_I2C_DATA); - - *buffer++ = get_reg_field_value( - value, - DC_I2C_DATA, - DC_I2C_DATA); - - --length; - } -} - -static enum i2c_channel_operation_result get_channel_status( - struct i2c_engine *engine, - uint8_t *returned_bytes) -{ - uint32_t i2c_sw_status = 0; - uint32_t value = dm_read_reg(engine->base.ctx, mmDC_I2C_SW_STATUS); - - i2c_sw_status = get_reg_field_value( - value, - DC_I2C_SW_STATUS, - DC_I2C_SW_STATUS); - - if (i2c_sw_status == DC_I2C_STATUS__DC_I2C_STATUS_USED_BY_SW) - return I2C_CHANNEL_OPERATION_ENGINE_BUSY; - else if (value & DC_I2C_SW_STATUS__DC_I2C_SW_STOPPED_ON_NACK_MASK) - return I2C_CHANNEL_OPERATION_NO_RESPONSE; - else if (value & DC_I2C_SW_STATUS__DC_I2C_SW_TIMEOUT_MASK) - return I2C_CHANNEL_OPERATION_TIMEOUT; - else if (value & DC_I2C_SW_STATUS__DC_I2C_SW_ABORTED_MASK) - return I2C_CHANNEL_OPERATION_FAILED; - else if (value & DC_I2C_SW_STATUS__DC_I2C_SW_DONE_MASK) - return I2C_CHANNEL_OPERATION_SUCCEEDED; - - /* - * this is the case when HW used for communication, I2C_SW_STATUS - * could be zero - */ - return I2C_CHANNEL_OPERATION_SUCCEEDED; -} - -static uint32_t get_hw_buffer_available_size( - const struct i2c_hw_engine *engine) -{ - return I2C_HW_BUFFER_SIZE - - FROM_I2C_HW_ENGINE(engine)->buffer_used_bytes; -} - -static uint32_t get_transaction_timeout( - const struct i2c_hw_engine *engine, - uint32_t length) -{ - uint32_t speed = engine->base.funcs->get_speed(&engine->base); - - uint32_t period_timeout; - uint32_t num_of_clock_stretches; - - if (!speed) - return 0; - - period_timeout = (1000 * TRANSACTION_TIMEOUT_IN_I2C_CLOCKS) / speed; - - num_of_clock_stretches = 1 + (length << 3) + 1; - num_of_clock_stretches += - (FROM_I2C_HW_ENGINE(engine)->buffer_used_bytes << 3) + - (FROM_I2C_HW_ENGINE(engine)->transaction_count << 1); - - return period_timeout * num_of_clock_stretches; -} - -/* - * @brief - * DC_I2C_DDC1_SETUP MM register offsets - * - * @note - * The indices of this offset array are DDC engine IDs - */ -static const int32_t ddc_setup_offset[] = { - - mmDC_I2C_DDC1_SETUP - mmDC_I2C_DDC1_SETUP, /* DDC Engine 1 */ - mmDC_I2C_DDC2_SETUP - mmDC_I2C_DDC1_SETUP, /* DDC Engine 2 */ - mmDC_I2C_DDC3_SETUP - mmDC_I2C_DDC1_SETUP, /* DDC Engine 3 */ - mmDC_I2C_DDC4_SETUP - mmDC_I2C_DDC1_SETUP, /* DDC Engine 4 */ - mmDC_I2C_DDC5_SETUP - mmDC_I2C_DDC1_SETUP, /* DDC Engine 5 */ - mmDC_I2C_DDC6_SETUP - mmDC_I2C_DDC1_SETUP, /* DDC Engine 6 */ - mmDC_I2C_DDCVGA_SETUP - mmDC_I2C_DDC1_SETUP /* DDC Engine 7 */ -}; - -/* - * @brief - * DC_I2C_DDC1_SPEED MM register offsets - * - * @note - * The indices of this offset array are DDC engine IDs - */ -static const int32_t ddc_speed_offset[] = { - mmDC_I2C_DDC1_SPEED - mmDC_I2C_DDC1_SPEED, /* DDC Engine 1 */ - mmDC_I2C_DDC2_SPEED - mmDC_I2C_DDC1_SPEED, /* DDC Engine 2 */ - mmDC_I2C_DDC3_SPEED - mmDC_I2C_DDC1_SPEED, /* DDC Engine 3 */ - mmDC_I2C_DDC4_SPEED - mmDC_I2C_DDC1_SPEED, /* DDC Engine 4 */ - mmDC_I2C_DDC5_SPEED - mmDC_I2C_DDC1_SPEED, /* DDC Engine 5 */ - mmDC_I2C_DDC6_SPEED - mmDC_I2C_DDC1_SPEED, /* DDC Engine 6 */ - mmDC_I2C_DDCVGA_SPEED - mmDC_I2C_DDC1_SPEED /* DDC Engine 7 */ -}; - -static const struct i2c_engine_funcs i2c_engine_funcs = { - .destroy = destroy, - .get_speed = get_speed, - .set_speed = set_speed, - .setup_engine = setup_engine, - .submit_channel_request = submit_channel_request, - .process_channel_reply = process_channel_reply, - .get_channel_status = get_channel_status, - .acquire_engine = dal_i2c_hw_engine_acquire_engine, -}; - -static const struct engine_funcs engine_funcs = { - .release_engine = release_engine, - .get_engine_type = dal_i2c_hw_engine_get_engine_type, - .acquire = dal_i2c_engine_acquire, - .submit_request = dal_i2c_hw_engine_submit_request, -}; - -static const struct i2c_hw_engine_funcs i2c_hw_engine_funcs = { - .get_hw_buffer_available_size = - get_hw_buffer_available_size, - .get_transaction_timeout = - get_transaction_timeout, - .wait_on_operation_result = - dal_i2c_hw_engine_wait_on_operation_result, -}; - -static void construct( - struct i2c_hw_engine_dce80 *engine, - const struct i2c_hw_engine_dce80_create_arg *arg) -{ - dal_i2c_hw_engine_construct(&engine->base, arg->ctx); - - engine->base.base.base.funcs = &engine_funcs; - engine->base.base.funcs = &i2c_engine_funcs; - engine->base.funcs = &i2c_hw_engine_funcs; - engine->base.default_speed = arg->default_speed; - engine->addr.DC_I2C_DDCX_SETUP = - mmDC_I2C_DDC1_SETUP + ddc_setup_offset[arg->engine_id]; - engine->addr.DC_I2C_DDCX_SPEED = - mmDC_I2C_DDC1_SPEED + ddc_speed_offset[arg->engine_id]; - - engine->engine_id = arg->engine_id; - engine->reference_frequency = arg->reference_frequency; - engine->buffer_used_bytes = 0; - engine->transaction_count = 0; - engine->engine_keep_power_up_count = 1; -} - -struct i2c_engine *dal_i2c_hw_engine_dce80_create( - const struct i2c_hw_engine_dce80_create_arg *arg) -{ - struct i2c_hw_engine_dce80 *engine; - - if (!arg) { - BREAK_TO_DEBUGGER(); - return NULL; - } - - if ((arg->engine_id >= sizeof(ddc_setup_offset) / sizeof(int32_t)) || - (arg->engine_id >= sizeof(ddc_speed_offset) / sizeof(int32_t)) || - !arg->reference_frequency) { - BREAK_TO_DEBUGGER(); - return NULL; - } - - engine = kzalloc(sizeof(struct i2c_hw_engine_dce80), GFP_KERNEL); - - if (!engine) { - BREAK_TO_DEBUGGER(); - return NULL; - } - - construct(engine, arg); - return &engine->base.base; -} diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_hw_engine_dce80.h b/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_hw_engine_dce80.h deleted file mode 100644 index 5c6116fb5479..000000000000 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_hw_engine_dce80.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#ifndef __DAL_I2C_HW_ENGINE_DCE80_H__ -#define __DAL_I2C_HW_ENGINE_DCE80_H__ - -struct i2c_hw_engine_dce80 { - struct i2c_hw_engine base; - struct { - uint32_t DC_I2C_DDCX_SETUP; - uint32_t DC_I2C_DDCX_SPEED; - } addr; - uint32_t engine_id; - /* expressed in kilohertz */ - uint32_t reference_frequency; - /* number of bytes currently used in HW buffer */ - uint32_t buffer_used_bytes; - /* number of pending transactions (before GO) */ - uint32_t transaction_count; - uint32_t engine_keep_power_up_count; -}; - -struct i2c_hw_engine_dce80_create_arg { - uint32_t engine_id; - uint32_t reference_frequency; - uint32_t default_speed; - struct dc_context *ctx; -}; - -struct i2c_engine *dal_i2c_hw_engine_dce80_create( - const struct i2c_hw_engine_dce80_create_arg *arg); -#endif diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_sw_engine_dce80.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_sw_engine_dce80.c deleted file mode 100644 index 4853ee26096a..000000000000 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_sw_engine_dce80.c +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" - -/* - * Pre-requisites: headers required by header of this unit - */ -#include "include/i2caux_interface.h" -#include "../engine.h" -#include "../i2c_engine.h" -#include "../i2c_sw_engine.h" - -/* - * Header of this unit - */ - -#include "i2c_sw_engine_dce80.h" - -/* - * Post-requisites: headers required by this unit - */ - -#include "dce/dce_8_0_d.h" -#include "dce/dce_8_0_sh_mask.h" - -/* - * This unit - */ - -static const uint32_t ddc_hw_status_addr[] = { - mmDC_I2C_DDC1_HW_STATUS, - mmDC_I2C_DDC2_HW_STATUS, - mmDC_I2C_DDC3_HW_STATUS, - mmDC_I2C_DDC4_HW_STATUS, - mmDC_I2C_DDC5_HW_STATUS, - mmDC_I2C_DDC6_HW_STATUS, - mmDC_I2C_DDCVGA_HW_STATUS -}; - -/* - * @brief - * Cast 'struct i2c_sw_engine *' - * to 'struct i2c_sw_engine_dce80 *' - */ -#define FROM_I2C_SW_ENGINE(ptr) \ - container_of((ptr), struct i2c_sw_engine_dce80, base) - -/* - * @brief - * Cast 'struct i2c_engine *' - * to 'struct i2c_sw_engine_dce80 *' - */ -#define FROM_I2C_ENGINE(ptr) \ - FROM_I2C_SW_ENGINE(container_of((ptr), struct i2c_sw_engine, base)) - -/* - * @brief - * Cast 'struct engine *' - * to 'struct i2c_sw_engine_dce80 *' - */ -#define FROM_ENGINE(ptr) \ - FROM_I2C_ENGINE(container_of((ptr), struct i2c_engine, base)) - -static void release_engine( - struct engine *engine) -{ - -} - -static void destruct( - struct i2c_sw_engine_dce80 *engine) -{ - dal_i2c_sw_engine_destruct(&engine->base); -} - -static void destroy( - struct i2c_engine **engine) -{ - struct i2c_sw_engine_dce80 *sw_engine = FROM_I2C_ENGINE(*engine); - - destruct(sw_engine); - - kfree(sw_engine); - - *engine = NULL; -} - -static bool acquire_engine( - struct i2c_engine *engine, - struct ddc *ddc_handle) -{ - return dal_i2caux_i2c_sw_engine_acquire_engine(engine, ddc_handle); -} - -static const struct i2c_engine_funcs i2c_engine_funcs = { - .acquire_engine = acquire_engine, - .destroy = destroy, - .get_speed = dal_i2c_sw_engine_get_speed, - .set_speed = dal_i2c_sw_engine_set_speed, - .setup_engine = dal_i2c_engine_setup_i2c_engine, - .submit_channel_request = dal_i2c_sw_engine_submit_channel_request, - .process_channel_reply = dal_i2c_engine_process_channel_reply, - .get_channel_status = dal_i2c_sw_engine_get_channel_status, -}; - -static const struct engine_funcs engine_funcs = { - .release_engine = release_engine, - .get_engine_type = dal_i2c_sw_engine_get_engine_type, - .acquire = dal_i2c_engine_acquire, - .submit_request = dal_i2c_sw_engine_submit_request, -}; - -static void construct( - struct i2c_sw_engine_dce80 *engine, - const struct i2c_sw_engine_dce80_create_arg *arg) -{ - struct i2c_sw_engine_create_arg arg_base; - - arg_base.ctx = arg->ctx; - arg_base.default_speed = arg->default_speed; - - dal_i2c_sw_engine_construct(&engine->base, &arg_base); - - engine->base.base.base.funcs = &engine_funcs; - engine->base.base.funcs = &i2c_engine_funcs; - engine->base.default_speed = arg->default_speed; - engine->engine_id = arg->engine_id; -} - -struct i2c_engine *dal_i2c_sw_engine_dce80_create( - const struct i2c_sw_engine_dce80_create_arg *arg) -{ - struct i2c_sw_engine_dce80 *engine; - - if (!arg) { - BREAK_TO_DEBUGGER(); - return NULL; - } - - engine = kzalloc(sizeof(struct i2c_sw_engine_dce80), GFP_KERNEL); - - if (!engine) { - BREAK_TO_DEBUGGER(); - return NULL; - } - - construct(engine, arg); - return &engine->base.base; -} - diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2caux_dce80.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2caux_dce80.c deleted file mode 100644 index ed48596dd2a5..000000000000 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2caux_dce80.c +++ /dev/null @@ -1,284 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" - -/* - * Pre-requisites: headers required by header of this unit - */ -#include "include/i2caux_interface.h" -#include "../i2caux.h" - -/* - * Header of this unit - */ - -#include "i2caux_dce80.h" - -/* - * Post-requisites: headers required by this unit - */ - -#include "../engine.h" -#include "../i2c_engine.h" -#include "../i2c_sw_engine.h" -#include "i2c_sw_engine_dce80.h" -#include "../i2c_hw_engine.h" -#include "i2c_hw_engine_dce80.h" -#include "../i2c_generic_hw_engine.h" -#include "../aux_engine.h" - - -#include "../dce110/aux_engine_dce110.h" -#include "../dce110/i2caux_dce110.h" - -#include "dce/dce_8_0_d.h" -#include "dce/dce_8_0_sh_mask.h" - - -/* set register offset */ -#define SR(reg_name)\ - .reg_name = mm ## reg_name - -/* set register offset with instance */ -#define SRI(reg_name, block, id)\ - .reg_name = mm ## block ## id ## _ ## reg_name - -#define aux_regs(id)\ -[id] = {\ - AUX_COMMON_REG_LIST(id), \ - .AUX_RESET_MASK = 0 \ -} - -static const struct dce110_aux_registers dce80_aux_regs[] = { - aux_regs(0), - aux_regs(1), - aux_regs(2), - aux_regs(3), - aux_regs(4), - aux_regs(5) -}; - -/* - * This unit - */ - -#define FROM_I2C_AUX(ptr) \ - container_of((ptr), struct i2caux_dce80, base) - -static void destruct( - struct i2caux_dce80 *i2caux_dce80) -{ - dal_i2caux_destruct(&i2caux_dce80->base); -} - -static void destroy( - struct i2caux **i2c_engine) -{ - struct i2caux_dce80 *i2caux_dce80 = FROM_I2C_AUX(*i2c_engine); - - destruct(i2caux_dce80); - - kfree(i2caux_dce80); - - *i2c_engine = NULL; -} - -static struct i2c_engine *acquire_i2c_hw_engine( - struct i2caux *i2caux, - struct ddc *ddc) -{ - struct i2caux_dce80 *i2caux_dce80 = FROM_I2C_AUX(i2caux); - - struct i2c_engine *engine = NULL; - bool non_generic; - - if (!ddc) - return NULL; - - if (ddc->hw_info.hw_supported) { - enum gpio_ddc_line line = dal_ddc_get_line(ddc); - - if (line < GPIO_DDC_LINE_COUNT) { - non_generic = true; - engine = i2caux->i2c_hw_engines[line]; - } - } - - if (!engine) { - non_generic = false; - engine = i2caux->i2c_generic_hw_engine; - } - - if (!engine) - return NULL; - - if (non_generic) { - if (!i2caux_dce80->i2c_hw_buffer_in_use && - engine->base.funcs->acquire(&engine->base, ddc)) { - i2caux_dce80->i2c_hw_buffer_in_use = true; - return engine; - } - } else { - if (engine->base.funcs->acquire(&engine->base, ddc)) - return engine; - } - - return NULL; -} - -static void release_engine( - struct i2caux *i2caux, - struct engine *engine) -{ - if (engine->funcs->get_engine_type(engine) == - I2CAUX_ENGINE_TYPE_I2C_DDC_HW) - FROM_I2C_AUX(i2caux)->i2c_hw_buffer_in_use = false; - - dal_i2caux_release_engine(i2caux, engine); -} - -static const enum gpio_ddc_line hw_ddc_lines[] = { - GPIO_DDC_LINE_DDC1, - GPIO_DDC_LINE_DDC2, - GPIO_DDC_LINE_DDC3, - GPIO_DDC_LINE_DDC4, - GPIO_DDC_LINE_DDC5, - GPIO_DDC_LINE_DDC6, - GPIO_DDC_LINE_DDC_VGA -}; - -static const enum gpio_ddc_line hw_aux_lines[] = { - GPIO_DDC_LINE_DDC1, - GPIO_DDC_LINE_DDC2, - GPIO_DDC_LINE_DDC3, - GPIO_DDC_LINE_DDC4, - GPIO_DDC_LINE_DDC5, - GPIO_DDC_LINE_DDC6 -}; - -static const struct i2caux_funcs i2caux_funcs = { - .destroy = destroy, - .acquire_i2c_hw_engine = acquire_i2c_hw_engine, - .release_engine = release_engine, - .acquire_i2c_sw_engine = dal_i2caux_acquire_i2c_sw_engine, - .acquire_aux_engine = dal_i2caux_acquire_aux_engine, -}; - -static void construct( - struct i2caux_dce80 *i2caux_dce80, - struct dc_context *ctx) -{ - /* Entire family have I2C engine reference clock frequency - * changed from XTALIN (27) to XTALIN/2 (13.5) */ - - struct i2caux *base = &i2caux_dce80->base; - - uint32_t reference_frequency = - dal_i2caux_get_reference_clock(ctx->dc_bios) >> 1; - - /*bool use_i2c_sw_engine = dal_adapter_service_is_feature_supported(as, - FEATURE_RESTORE_USAGE_I2C_SW_ENGINE);*/ - - /* Use SWI2C for dce8 currently, sicne we have bug with hwi2c */ - bool use_i2c_sw_engine = true; - - uint32_t i; - - dal_i2caux_construct(base, ctx); - - i2caux_dce80->base.funcs = &i2caux_funcs; - i2caux_dce80->i2c_hw_buffer_in_use = false; - - /* Create I2C HW engines (HW + SW pairs) - * for all lines which has assisted HW DDC - * 'i' (loop counter) used as DDC/AUX engine_id */ - - i = 0; - - do { - enum gpio_ddc_line line_id = hw_ddc_lines[i]; - - struct i2c_hw_engine_dce80_create_arg hw_arg; - - if (use_i2c_sw_engine) { - struct i2c_sw_engine_dce80_create_arg sw_arg; - - sw_arg.engine_id = i; - sw_arg.default_speed = base->default_i2c_sw_speed; - sw_arg.ctx = ctx; - base->i2c_sw_engines[line_id] = - dal_i2c_sw_engine_dce80_create(&sw_arg); - } - - hw_arg.engine_id = i; - hw_arg.reference_frequency = reference_frequency; - hw_arg.default_speed = base->default_i2c_hw_speed; - hw_arg.ctx = ctx; - - base->i2c_hw_engines[line_id] = - dal_i2c_hw_engine_dce80_create(&hw_arg); - - ++i; - } while (i < ARRAY_SIZE(hw_ddc_lines)); - - /* Create AUX engines for all lines which has assisted HW AUX - * 'i' (loop counter) used as DDC/AUX engine_id */ - - i = 0; - - do { - enum gpio_ddc_line line_id = hw_aux_lines[i]; - - struct aux_engine_dce110_init_data arg; - - arg.engine_id = i; - arg.timeout_period = base->aux_timeout_period; - arg.ctx = ctx; - arg.regs = &dce80_aux_regs[i]; - - base->aux_engines[line_id] = - dal_aux_engine_dce110_create(&arg); - - ++i; - } while (i < ARRAY_SIZE(hw_aux_lines)); - - /* TODO Generic I2C SW and HW */ -} - -struct i2caux *dal_i2caux_dce80_create( - struct dc_context *ctx) -{ - struct i2caux_dce80 *i2caux_dce80 = - kzalloc(sizeof(struct i2caux_dce80), GFP_KERNEL); - - if (!i2caux_dce80) { - BREAK_TO_DEBUGGER(); - return NULL; - } - - construct(i2caux_dce80, ctx); - return &i2caux_dce80->base; -} diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2caux_dce80.h b/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2caux_dce80.h deleted file mode 100644 index 21908629e973..000000000000 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2caux_dce80.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#ifndef __DAL_I2C_AUX_DCE80_H__ -#define __DAL_I2C_AUX_DCE80_H__ - -struct i2caux_dce80 { - struct i2caux base; - /* indicate the I2C HW circular buffer is in use */ - bool i2c_hw_buffer_in_use; -}; - -struct i2caux *dal_i2caux_dce80_create( - struct dc_context *ctx); - -#endif diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dcn10/i2caux_dcn10.c b/drivers/gpu/drm/amd/display/dc/i2caux/dcn10/i2caux_dcn10.c deleted file mode 100644 index a59c1f50c1e8..000000000000 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dcn10/i2caux_dcn10.c +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" - -#include "include/i2caux_interface.h" -#include "../i2caux.h" -#include "../engine.h" -#include "../i2c_engine.h" -#include "../i2c_sw_engine.h" -#include "../i2c_hw_engine.h" - -#include "../dce110/aux_engine_dce110.h" -#include "../dce110/i2c_hw_engine_dce110.h" -#include "../dce110/i2caux_dce110.h" - -#include "dcn/dcn_1_0_offset.h" -#include "dcn/dcn_1_0_sh_mask.h" -#include "soc15_hw_ip.h" -#include "vega10_ip_offset.h" - -/* begin ********************* - * macros to expend register list macro defined in HW object header file */ - -#define BASE_INNER(seg) \ - DCE_BASE__INST0_SEG ## seg - -/* compile time expand base address. */ -#define BASE(seg) \ - BASE_INNER(seg) - -#define SR(reg_name)\ - .reg_name = BASE(mm ## reg_name ## _BASE_IDX) + \ - mm ## reg_name - -#define SRI(reg_name, block, id)\ - .reg_name = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - mm ## block ## id ## _ ## reg_name -/* macros to expend register list macro defined in HW object header file - * end *********************/ - -#define aux_regs(id)\ -[id] = {\ - AUX_COMMON_REG_LIST(id), \ - .AUX_RESET_MASK = DP_AUX0_AUX_CONTROL__AUX_RESET_MASK \ -} - -#define hw_engine_regs(id)\ -{\ - I2C_HW_ENGINE_COMMON_REG_LIST(id) \ -} - -static const struct dce110_aux_registers dcn10_aux_regs[] = { - aux_regs(0), - aux_regs(1), - aux_regs(2), - aux_regs(3), - aux_regs(4), - aux_regs(5), -}; - -static const struct dce110_i2c_hw_engine_registers dcn10_hw_engine_regs[] = { - hw_engine_regs(1), - hw_engine_regs(2), - hw_engine_regs(3), - hw_engine_regs(4), - hw_engine_regs(5), - hw_engine_regs(6) -}; - -static const struct dce110_i2c_hw_engine_shift i2c_shift = { - I2C_COMMON_MASK_SH_LIST_DCE110(__SHIFT) -}; - -static const struct dce110_i2c_hw_engine_mask i2c_mask = { - I2C_COMMON_MASK_SH_LIST_DCE110(_MASK) -}; - -struct i2caux *dal_i2caux_dcn10_create( - struct dc_context *ctx) -{ - struct i2caux_dce110 *i2caux_dce110 = - kzalloc(sizeof(struct i2caux_dce110), GFP_KERNEL); - - if (!i2caux_dce110) { - ASSERT_CRITICAL(false); - return NULL; - } - - dal_i2caux_dce110_construct(i2caux_dce110, - ctx, - ARRAY_SIZE(dcn10_aux_regs), - dcn10_aux_regs, - dcn10_hw_engine_regs, - &i2c_shift, - &i2c_mask); - return &i2caux_dce110->base; -} diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dcn10/i2caux_dcn10.h b/drivers/gpu/drm/amd/display/dc/i2caux/dcn10/i2caux_dcn10.h deleted file mode 100644 index aeb4a86463d4..000000000000 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dcn10/i2caux_dcn10.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#ifndef __DAL_I2C_AUX_DCN10_H__ -#define __DAL_I2C_AUX_DCN10_H__ - -struct i2caux *dal_i2caux_dcn10_create( - struct dc_context *ctx); - -#endif /* __DAL_I2C_AUX_DCN10_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/diagnostics/i2caux_diag.c b/drivers/gpu/drm/amd/display/dc/i2caux/diagnostics/i2caux_diag.c deleted file mode 100644 index e6408f644086..000000000000 --- a/drivers/gpu/drm/amd/display/dc/i2caux/diagnostics/i2caux_diag.c +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright 2012-16 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" - -/* - * Pre-requisites: headers required by header of this unit - */ -#include "include/i2caux_interface.h" -#include "../i2caux.h" -#include "../engine.h" -#include "../i2c_engine.h" -#include "../i2c_sw_engine.h" -#include "../i2c_hw_engine.h" - -/* - * Header of this unit - */ -#include "i2caux_diag.h" - -/* - * Post-requisites: headers required by this unit - */ - -/* - * This unit - */ - -static void destruct( - struct i2caux *i2caux) -{ - dal_i2caux_destruct(i2caux); -} - -static void destroy( - struct i2caux **i2c_engine) -{ - destruct(*i2c_engine); - - kfree(*i2c_engine); - - *i2c_engine = NULL; -} - -/* function table */ -static const struct i2caux_funcs i2caux_funcs = { - .destroy = destroy, - .acquire_i2c_hw_engine = NULL, - .release_engine = NULL, - .acquire_i2c_sw_engine = NULL, - .acquire_aux_engine = NULL, -}; - -static void construct( - struct i2caux *i2caux, - struct dc_context *ctx) -{ - dal_i2caux_construct(i2caux, ctx); - i2caux->funcs = &i2caux_funcs; -} - -struct i2caux *dal_i2caux_diag_fpga_create( - struct dc_context *ctx) -{ - struct i2caux *i2caux = kzalloc(sizeof(struct i2caux), - GFP_KERNEL); - - if (!i2caux) { - ASSERT_CRITICAL(false); - return NULL; - } - - construct(i2caux, ctx); - return i2caux; -} diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/diagnostics/i2caux_diag.h b/drivers/gpu/drm/amd/display/dc/i2caux/diagnostics/i2caux_diag.h deleted file mode 100644 index a83eeb748283..000000000000 --- a/drivers/gpu/drm/amd/display/dc/i2caux/diagnostics/i2caux_diag.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2012-16 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#ifndef __DAL_I2C_AUX_DIAG_FPGA_H__ -#define __DAL_I2C_AUX_DIAG_FPGA_H__ - -struct i2caux *dal_i2caux_diag_fpga_create( - struct dc_context *ctx); - -#endif /* __DAL_I2C_AUX_DIAG_FPGA_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/engine.h b/drivers/gpu/drm/amd/display/dc/i2caux/engine.h deleted file mode 100644 index b16fb1ff687d..000000000000 --- a/drivers/gpu/drm/amd/display/dc/i2caux/engine.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#ifndef __DAL_ENGINE_H__ -#define __DAL_ENGINE_H__ - -#include "dc_ddc_types.h" - -enum i2caux_transaction_operation { - I2CAUX_TRANSACTION_READ, - I2CAUX_TRANSACTION_WRITE -}; - -enum i2caux_transaction_address_space { - I2CAUX_TRANSACTION_ADDRESS_SPACE_I2C = 1, - I2CAUX_TRANSACTION_ADDRESS_SPACE_DPCD -}; - -struct i2caux_transaction_payload { - enum i2caux_transaction_address_space address_space; - uint32_t address; - uint32_t length; - uint8_t *data; -}; - -enum i2caux_transaction_status { - I2CAUX_TRANSACTION_STATUS_UNKNOWN = (-1L), - I2CAUX_TRANSACTION_STATUS_SUCCEEDED, - I2CAUX_TRANSACTION_STATUS_FAILED_CHANNEL_BUSY, - I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT, - I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR, - I2CAUX_TRANSACTION_STATUS_FAILED_NACK, - I2CAUX_TRANSACTION_STATUS_FAILED_INCOMPLETE, - I2CAUX_TRANSACTION_STATUS_FAILED_OPERATION, - I2CAUX_TRANSACTION_STATUS_FAILED_INVALID_OPERATION, - I2CAUX_TRANSACTION_STATUS_FAILED_BUFFER_OVERFLOW, - I2CAUX_TRANSACTION_STATUS_FAILED_HPD_DISCON -}; - -struct i2caux_transaction_request { - enum i2caux_transaction_operation operation; - struct i2caux_transaction_payload payload; - enum i2caux_transaction_status status; -}; - -enum i2caux_engine_type { - I2CAUX_ENGINE_TYPE_UNKNOWN = (-1L), - I2CAUX_ENGINE_TYPE_AUX, - I2CAUX_ENGINE_TYPE_I2C_DDC_HW, - I2CAUX_ENGINE_TYPE_I2C_GENERIC_HW, - I2CAUX_ENGINE_TYPE_I2C_SW -}; - -enum i2c_default_speed { - I2CAUX_DEFAULT_I2C_HW_SPEED = 50, - I2CAUX_DEFAULT_I2C_SW_SPEED = 50 -}; - -struct engine; - -struct engine_funcs { - enum i2caux_engine_type (*get_engine_type)( - const struct engine *engine); - bool (*acquire)( - struct engine *engine, - struct ddc *ddc); - bool (*submit_request)( - struct engine *engine, - struct i2caux_transaction_request *request, - bool middle_of_transaction); - void (*release_engine)( - struct engine *engine); -}; - -struct engine { - const struct engine_funcs *funcs; - uint32_t inst; - struct ddc *ddc; - struct dc_context *ctx; -}; - -void dal_i2caux_construct_engine( - struct engine *engine, - struct dc_context *ctx); - -void dal_i2caux_destruct_engine( - struct engine *engine); - -#endif diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/engine_base.c b/drivers/gpu/drm/amd/display/dc/i2caux/engine_base.c deleted file mode 100644 index 5d155d36d353..000000000000 --- a/drivers/gpu/drm/amd/display/dc/i2caux/engine_base.c +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" - -/* - * Pre-requisites: headers required by header of this unit - */ -#include "include/i2caux_interface.h" - -/* - * Header of this unit - */ - -#include "engine.h" - -void dal_i2caux_construct_engine( - struct engine *engine, - struct dc_context *ctx) -{ - engine->ddc = NULL; - engine->ctx = ctx; -} - -void dal_i2caux_destruct_engine( - struct engine *engine) -{ - /* nothing to do */ -} - diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_engine.c b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_engine.c deleted file mode 100644 index 70e20bd47ce4..000000000000 --- a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_engine.c +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" - -/* - * Pre-requisites: headers required by header of this unit - */ -#include "include/i2caux_interface.h" -#include "engine.h" - -/* - * Header of this unit - */ - -#include "i2c_engine.h" - -/* - * Post-requisites: headers required by this unit - */ - -/* - * This unit - */ - -#define FROM_ENGINE(ptr) \ - container_of((ptr), struct i2c_engine, base) - -bool dal_i2c_engine_acquire( - struct engine *engine, - struct ddc *ddc_handle) -{ - struct i2c_engine *i2c_engine = FROM_ENGINE(engine); - - uint32_t counter = 0; - bool result; - - do { - result = i2c_engine->funcs->acquire_engine( - i2c_engine, ddc_handle); - - if (result) - break; - - /* i2c_engine is busy by VBios, lets wait and retry */ - - udelay(10); - - ++counter; - } while (counter < 2); - - if (result) { - if (!i2c_engine->funcs->setup_engine(i2c_engine)) { - engine->funcs->release_engine(engine); - result = false; - } - } - - return result; -} - -bool dal_i2c_engine_setup_i2c_engine( - struct i2c_engine *engine) -{ - /* Derivative classes do not have to override this */ - - return true; -} - -void dal_i2c_engine_submit_channel_request( - struct i2c_engine *engine, - struct i2c_request_transaction_data *request) -{ - -} - -void dal_i2c_engine_process_channel_reply( - struct i2c_engine *engine, - struct i2c_reply_transaction_data *reply) -{ - -} - -void dal_i2c_engine_construct( - struct i2c_engine *engine, - struct dc_context *ctx) -{ - dal_i2caux_construct_engine(&engine->base, ctx); - engine->timeout_delay = 0; -} - -void dal_i2c_engine_destruct( - struct i2c_engine *engine) -{ - dal_i2caux_destruct_engine(&engine->base); -} diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_engine.h b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_engine.h deleted file mode 100644 index ded6ea34b714..000000000000 --- a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_engine.h +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#ifndef __DAL_I2C_ENGINE_H__ -#define __DAL_I2C_ENGINE_H__ - -enum i2c_channel_operation_result { - I2C_CHANNEL_OPERATION_SUCCEEDED, - I2C_CHANNEL_OPERATION_FAILED, - I2C_CHANNEL_OPERATION_NOT_GRANTED, - I2C_CHANNEL_OPERATION_IS_BUSY, - I2C_CHANNEL_OPERATION_NO_HANDLE_PROVIDED, - I2C_CHANNEL_OPERATION_CHANNEL_IN_USE, - I2C_CHANNEL_OPERATION_CHANNEL_CLIENT_MAX_ALLOWED, - I2C_CHANNEL_OPERATION_ENGINE_BUSY, - I2C_CHANNEL_OPERATION_TIMEOUT, - I2C_CHANNEL_OPERATION_NO_RESPONSE, - I2C_CHANNEL_OPERATION_HW_REQUEST_I2C_BUS, - I2C_CHANNEL_OPERATION_WRONG_PARAMETER, - I2C_CHANNEL_OPERATION_OUT_NB_OF_RETRIES, - I2C_CHANNEL_OPERATION_NOT_STARTED -}; - -struct i2c_request_transaction_data { - enum i2caux_transaction_action action; - enum i2c_channel_operation_result status; - uint8_t address; - uint32_t length; - uint8_t *data; -}; - -struct i2c_reply_transaction_data { - uint32_t length; - uint8_t *data; -}; - -struct i2c_engine; - -struct i2c_engine_funcs { - void (*destroy)( - struct i2c_engine **ptr); - uint32_t (*get_speed)( - const struct i2c_engine *engine); - void (*set_speed)( - struct i2c_engine *engine, - uint32_t speed); - bool (*acquire_engine)( - struct i2c_engine *engine, - struct ddc *ddc); - bool (*setup_engine)( - struct i2c_engine *engine); - void (*submit_channel_request)( - struct i2c_engine *engine, - struct i2c_request_transaction_data *request); - void (*process_channel_reply)( - struct i2c_engine *engine, - struct i2c_reply_transaction_data *reply); - enum i2c_channel_operation_result (*get_channel_status)( - struct i2c_engine *engine, - uint8_t *returned_bytes); -}; - -struct i2c_engine { - struct engine base; - const struct i2c_engine_funcs *funcs; - uint32_t timeout_delay; - uint32_t setup_limit; - uint32_t send_reset_length; -}; - -void dal_i2c_engine_construct( - struct i2c_engine *engine, - struct dc_context *ctx); - -void dal_i2c_engine_destruct( - struct i2c_engine *engine); - -bool dal_i2c_engine_setup_i2c_engine( - struct i2c_engine *engine); - -void dal_i2c_engine_submit_channel_request( - struct i2c_engine *engine, - struct i2c_request_transaction_data *request); - -void dal_i2c_engine_process_channel_reply( - struct i2c_engine *engine, - struct i2c_reply_transaction_data *reply); - -bool dal_i2c_engine_acquire( - struct engine *ptr, - struct ddc *ddc_handle); - -#endif diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_generic_hw_engine.c b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_generic_hw_engine.c deleted file mode 100644 index 5a4295e0fae5..000000000000 --- a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_generic_hw_engine.c +++ /dev/null @@ -1,284 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" - -/* - * Pre-requisites: headers required by header of this unit - */ -#include "include/i2caux_interface.h" -#include "engine.h" -#include "i2c_engine.h" -#include "i2c_hw_engine.h" - -/* - * Header of this unit - */ - -#include "i2c_generic_hw_engine.h" - -/* - * Post-requisites: headers required by this unit - */ - -/* - * This unit - */ - -/* - * @brief - * Cast 'struct i2c_hw_engine *' - * to 'struct i2c_generic_hw_engine *' - */ -#define FROM_I2C_HW_ENGINE(ptr) \ - container_of((ptr), struct i2c_generic_hw_engine, base) - -/* - * @brief - * Cast 'struct i2c_engine *' - * to 'struct i2c_generic_hw_engine *' - */ -#define FROM_I2C_ENGINE(ptr) \ - FROM_I2C_HW_ENGINE(container_of((ptr), struct i2c_hw_engine, base)) - -/* - * @brief - * Cast 'struct engine *' - * to 'struct i2c_generic_hw_engine *' - */ -#define FROM_ENGINE(ptr) \ - FROM_I2C_ENGINE(container_of((ptr), struct i2c_engine, base)) - -enum i2caux_engine_type dal_i2c_generic_hw_engine_get_engine_type( - const struct engine *engine) -{ - return I2CAUX_ENGINE_TYPE_I2C_GENERIC_HW; -} - -/* - * @brief - * Single transaction handling. - * Since transaction may be bigger than HW buffer size, - * it divides transaction to sub-transactions - * and uses batch transaction feature of the engine. - */ -bool dal_i2c_generic_hw_engine_submit_request( - struct engine *engine, - struct i2caux_transaction_request *i2caux_request, - bool middle_of_transaction) -{ - struct i2c_generic_hw_engine *hw_engine = FROM_ENGINE(engine); - - struct i2c_hw_engine *base = &hw_engine->base; - - uint32_t max_payload_size = - base->funcs->get_hw_buffer_available_size(base); - - bool initial_stop_bit = !middle_of_transaction; - - struct i2c_generic_transaction_attributes attributes; - - enum i2c_channel_operation_result operation_result = - I2C_CHANNEL_OPERATION_FAILED; - - bool result = false; - - /* setup transaction initial properties */ - - uint8_t address = i2caux_request->payload.address; - uint8_t *current_payload = i2caux_request->payload.data; - uint32_t remaining_payload_size = i2caux_request->payload.length; - - bool first_iteration = true; - - if (i2caux_request->operation == I2CAUX_TRANSACTION_READ) - attributes.action = I2CAUX_TRANSACTION_ACTION_I2C_READ; - else if (i2caux_request->operation == I2CAUX_TRANSACTION_WRITE) - attributes.action = I2CAUX_TRANSACTION_ACTION_I2C_WRITE; - else { - i2caux_request->status = - I2CAUX_TRANSACTION_STATUS_FAILED_INVALID_OPERATION; - return false; - } - - /* Do batch transaction. - * Divide read/write data into payloads which fit HW buffer size. - * 1. Single transaction: - * start_bit = 1, stop_bit depends on session state, ack_on_read = 0; - * 2. Start of batch transaction: - * start_bit = 1, stop_bit = 0, ack_on_read = 1; - * 3. Middle of batch transaction: - * start_bit = 0, stop_bit = 0, ack_on_read = 1; - * 4. End of batch transaction: - * start_bit = 0, stop_bit depends on session state, ack_on_read = 0. - * Session stop bit is set if 'middle_of_transaction' = 0. */ - - while (remaining_payload_size) { - uint32_t current_transaction_size; - uint32_t current_payload_size; - - bool last_iteration; - bool stop_bit; - - /* Calculate current transaction size and payload size. - * Transaction size = total number of bytes in transaction, - * including slave's address; - * Payload size = number of data bytes in transaction. */ - - if (first_iteration) { - /* In the first sub-transaction we send slave's address - * thus we need to reserve one byte for it */ - current_transaction_size = - (remaining_payload_size > max_payload_size - 1) ? - max_payload_size : - remaining_payload_size + 1; - - current_payload_size = current_transaction_size - 1; - } else { - /* Second and further sub-transactions will have - * entire buffer reserved for data */ - current_transaction_size = - (remaining_payload_size > max_payload_size) ? - max_payload_size : - remaining_payload_size; - - current_payload_size = current_transaction_size; - } - - last_iteration = - (remaining_payload_size == current_payload_size); - - stop_bit = last_iteration ? initial_stop_bit : false; - - /* write slave device address */ - - if (first_iteration) - hw_engine->funcs->write_address(hw_engine, address); - - /* write current portion of data, if requested */ - - if (i2caux_request->operation == I2CAUX_TRANSACTION_WRITE) - hw_engine->funcs->write_data( - hw_engine, - current_payload, - current_payload_size); - - /* execute transaction */ - - attributes.start_bit = first_iteration; - attributes.stop_bit = stop_bit; - attributes.last_read = last_iteration; - attributes.transaction_size = current_transaction_size; - - hw_engine->funcs->execute_transaction(hw_engine, &attributes); - - /* wait until transaction is processed; if it fails - quit */ - - operation_result = base->funcs->wait_on_operation_result( - base, - base->funcs->get_transaction_timeout( - base, current_transaction_size), - I2C_CHANNEL_OPERATION_ENGINE_BUSY); - - if (operation_result != I2C_CHANNEL_OPERATION_SUCCEEDED) - break; - - /* read current portion of data, if requested */ - - /* the read offset should be 1 for first sub-transaction, - * and 0 for any next one */ - - if (i2caux_request->operation == I2CAUX_TRANSACTION_READ) - hw_engine->funcs->read_data(hw_engine, current_payload, - current_payload_size, first_iteration ? 1 : 0); - - /* update loop variables */ - - first_iteration = false; - current_payload += current_payload_size; - remaining_payload_size -= current_payload_size; - } - - /* update transaction status */ - - switch (operation_result) { - case I2C_CHANNEL_OPERATION_SUCCEEDED: - i2caux_request->status = - I2CAUX_TRANSACTION_STATUS_SUCCEEDED; - result = true; - break; - case I2C_CHANNEL_OPERATION_NO_RESPONSE: - i2caux_request->status = - I2CAUX_TRANSACTION_STATUS_FAILED_NACK; - break; - case I2C_CHANNEL_OPERATION_TIMEOUT: - i2caux_request->status = - I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT; - break; - case I2C_CHANNEL_OPERATION_FAILED: - i2caux_request->status = - I2CAUX_TRANSACTION_STATUS_FAILED_INCOMPLETE; - break; - default: - i2caux_request->status = - I2CAUX_TRANSACTION_STATUS_FAILED_OPERATION; - } - - return result; -} - -/* - * @brief - * Returns number of microseconds to wait until timeout to be considered - */ -uint32_t dal_i2c_generic_hw_engine_get_transaction_timeout( - const struct i2c_hw_engine *engine, - uint32_t length) -{ - const struct i2c_engine *base = &engine->base; - - uint32_t speed = base->funcs->get_speed(base); - - if (!speed) - return 0; - - /* total timeout = period_timeout * (start + data bits count + stop) */ - - return ((1000 * TRANSACTION_TIMEOUT_IN_I2C_CLOCKS) / speed) * - (1 + (length << 3) + 1); -} - -void dal_i2c_generic_hw_engine_construct( - struct i2c_generic_hw_engine *engine, - struct dc_context *ctx) -{ - dal_i2c_hw_engine_construct(&engine->base, ctx); -} - -void dal_i2c_generic_hw_engine_destruct( - struct i2c_generic_hw_engine *engine) -{ - dal_i2c_hw_engine_destruct(&engine->base); -} diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_generic_hw_engine.h b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_generic_hw_engine.h deleted file mode 100644 index 1da0397b04a2..000000000000 --- a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_generic_hw_engine.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#ifndef __DAL_I2C_GENERIC_HW_ENGINE_H__ -#define __DAL_I2C_GENERIC_HW_ENGINE_H__ - -struct i2c_generic_transaction_attributes { - enum i2caux_transaction_action action; - uint32_t transaction_size; - bool start_bit; - bool stop_bit; - bool last_read; -}; - -struct i2c_generic_hw_engine; - -struct i2c_generic_hw_engine_funcs { - void (*write_address)( - struct i2c_generic_hw_engine *engine, - uint8_t address); - void (*write_data)( - struct i2c_generic_hw_engine *engine, - const uint8_t *buffer, - uint32_t length); - void (*read_data)( - struct i2c_generic_hw_engine *engine, - uint8_t *buffer, - uint32_t length, - uint32_t offset); - void (*execute_transaction)( - struct i2c_generic_hw_engine *engine, - struct i2c_generic_transaction_attributes *attributes); -}; - -struct i2c_generic_hw_engine { - struct i2c_hw_engine base; - const struct i2c_generic_hw_engine_funcs *funcs; -}; - -void dal_i2c_generic_hw_engine_construct( - struct i2c_generic_hw_engine *engine, - struct dc_context *ctx); - -void dal_i2c_generic_hw_engine_destruct( - struct i2c_generic_hw_engine *engine); -enum i2caux_engine_type dal_i2c_generic_hw_engine_get_engine_type( - const struct engine *engine); -bool dal_i2c_generic_hw_engine_submit_request( - struct engine *ptr, - struct i2caux_transaction_request *i2caux_request, - bool middle_of_transaction); -uint32_t dal_i2c_generic_hw_engine_get_transaction_timeout( - const struct i2c_hw_engine *engine, - uint32_t length); -#endif diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_hw_engine.c b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_hw_engine.c deleted file mode 100644 index 141898533e8e..000000000000 --- a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_hw_engine.c +++ /dev/null @@ -1,251 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" -#include "dm_event_log.h" - -/* - * Pre-requisites: headers required by header of this unit - */ -#include "include/i2caux_interface.h" -#include "engine.h" -#include "i2c_engine.h" - -/* - * Header of this unit - */ - -#include "i2c_hw_engine.h" - -/* - * Post-requisites: headers required by this unit - */ - -/* - * This unit - */ - -/* - * @brief - * Cast 'struct i2c_engine *' - * to 'struct i2c_hw_engine *' - */ -#define FROM_I2C_ENGINE(ptr) \ - container_of((ptr), struct i2c_hw_engine, base) - -/* - * @brief - * Cast 'struct engine *' - * to 'struct i2c_hw_engine *' - */ -#define FROM_ENGINE(ptr) \ - FROM_I2C_ENGINE(container_of((ptr), struct i2c_engine, base)) - -enum i2caux_engine_type dal_i2c_hw_engine_get_engine_type( - const struct engine *engine) -{ - return I2CAUX_ENGINE_TYPE_I2C_DDC_HW; -} - -bool dal_i2c_hw_engine_submit_request( - struct engine *engine, - struct i2caux_transaction_request *i2caux_request, - bool middle_of_transaction) -{ - struct i2c_hw_engine *hw_engine = FROM_ENGINE(engine); - - struct i2c_request_transaction_data request; - - uint32_t transaction_timeout; - - enum i2c_channel_operation_result operation_result; - - bool result = false; - - /* We need following: - * transaction length will not exceed - * the number of free bytes in HW buffer (minus one for address)*/ - - if (i2caux_request->payload.length >= - hw_engine->funcs->get_hw_buffer_available_size(hw_engine)) { - i2caux_request->status = - I2CAUX_TRANSACTION_STATUS_FAILED_BUFFER_OVERFLOW; - return false; - } - - if (i2caux_request->operation == I2CAUX_TRANSACTION_READ) - request.action = middle_of_transaction ? - I2CAUX_TRANSACTION_ACTION_I2C_READ_MOT : - I2CAUX_TRANSACTION_ACTION_I2C_READ; - else if (i2caux_request->operation == I2CAUX_TRANSACTION_WRITE) - request.action = middle_of_transaction ? - I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT : - I2CAUX_TRANSACTION_ACTION_I2C_WRITE; - else { - i2caux_request->status = - I2CAUX_TRANSACTION_STATUS_FAILED_INVALID_OPERATION; - /* [anaumov] in DAL2, there was no "return false" */ - return false; - } - - request.address = (uint8_t)i2caux_request->payload.address; - request.length = i2caux_request->payload.length; - request.data = i2caux_request->payload.data; - - /* obtain timeout value before submitting request */ - - transaction_timeout = hw_engine->funcs->get_transaction_timeout( - hw_engine, i2caux_request->payload.length + 1); - - hw_engine->base.funcs->submit_channel_request( - &hw_engine->base, &request); - /* EVENT_LOG_AUX_REQ(engine->ddc->pin_data->en, EVENT_LOG_AUX_ORIGIN_I2C, */ - /* request.action, request.address, request.length, request.data); */ - - if ((request.status == I2C_CHANNEL_OPERATION_FAILED) || - (request.status == I2C_CHANNEL_OPERATION_ENGINE_BUSY)) { - i2caux_request->status = - I2CAUX_TRANSACTION_STATUS_FAILED_CHANNEL_BUSY; - return false; - } - - /* wait until transaction proceed */ - - operation_result = hw_engine->funcs->wait_on_operation_result( - hw_engine, - transaction_timeout, - I2C_CHANNEL_OPERATION_ENGINE_BUSY); - - /* update transaction status */ - - switch (operation_result) { - case I2C_CHANNEL_OPERATION_SUCCEEDED: - i2caux_request->status = - I2CAUX_TRANSACTION_STATUS_SUCCEEDED; - result = true; - break; - case I2C_CHANNEL_OPERATION_NO_RESPONSE: - i2caux_request->status = - I2CAUX_TRANSACTION_STATUS_FAILED_NACK; - break; - case I2C_CHANNEL_OPERATION_TIMEOUT: - i2caux_request->status = - I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT; - break; - case I2C_CHANNEL_OPERATION_FAILED: - i2caux_request->status = - I2CAUX_TRANSACTION_STATUS_FAILED_INCOMPLETE; - break; - default: - i2caux_request->status = - I2CAUX_TRANSACTION_STATUS_FAILED_OPERATION; - } - - if (result && (i2caux_request->operation == I2CAUX_TRANSACTION_READ)) { - struct i2c_reply_transaction_data reply; - - reply.data = i2caux_request->payload.data; - reply.length = i2caux_request->payload.length; - - hw_engine->base.funcs-> - process_channel_reply(&hw_engine->base, &reply); - /* EVENT_LOG_AUX_REP(engine->ddc->pin_data->en, EVENT_LOG_AUX_ORIGIN_I2C, */ - /* AUX_TRANSACTION_REPLY_I2C_ACK, reply.length, reply.data); */ - } - - - - return result; -} - -bool dal_i2c_hw_engine_acquire_engine( - struct i2c_engine *engine, - struct ddc *ddc) -{ - enum gpio_result result; - uint32_t current_speed; - - result = dal_ddc_open(ddc, GPIO_MODE_HARDWARE, - GPIO_DDC_CONFIG_TYPE_MODE_I2C); - - if (result != GPIO_RESULT_OK) - return false; - - engine->base.ddc = ddc; - - current_speed = engine->funcs->get_speed(engine); - - if (current_speed) - FROM_I2C_ENGINE(engine)->original_speed = current_speed; - - return true; -} -/* - * @brief - * Queries in a loop for current engine status - * until retrieved status matches 'expected_result', or timeout occurs. - * Timeout given in microseconds - * and the status query frequency is also one per microsecond. - */ -enum i2c_channel_operation_result dal_i2c_hw_engine_wait_on_operation_result( - struct i2c_hw_engine *engine, - uint32_t timeout, - enum i2c_channel_operation_result expected_result) -{ - enum i2c_channel_operation_result result; - uint32_t i = 0; - - if (!timeout) - return I2C_CHANNEL_OPERATION_SUCCEEDED; - - do { - result = engine->base.funcs->get_channel_status( - &engine->base, NULL); - - if (result != expected_result) - break; - - udelay(1); - - ++i; - } while (i < timeout); - - return result; -} - -void dal_i2c_hw_engine_construct( - struct i2c_hw_engine *engine, - struct dc_context *ctx) -{ - dal_i2c_engine_construct(&engine->base, ctx); - engine->original_speed = I2CAUX_DEFAULT_I2C_HW_SPEED; - engine->default_speed = I2CAUX_DEFAULT_I2C_HW_SPEED; -} - -void dal_i2c_hw_engine_destruct( - struct i2c_hw_engine *engine) -{ - dal_i2c_engine_destruct(&engine->base); -} diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_hw_engine.h b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_hw_engine.h deleted file mode 100644 index 8936a994804a..000000000000 --- a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_hw_engine.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#ifndef __DAL_I2C_HW_ENGINE_H__ -#define __DAL_I2C_HW_ENGINE_H__ - -enum { - TRANSACTION_TIMEOUT_IN_I2C_CLOCKS = 32 -}; - -struct i2c_hw_engine; - -struct i2c_hw_engine_funcs { - uint32_t (*get_hw_buffer_available_size)( - const struct i2c_hw_engine *engine); - enum i2c_channel_operation_result (*wait_on_operation_result)( - struct i2c_hw_engine *engine, - uint32_t timeout, - enum i2c_channel_operation_result expected_result); - uint32_t (*get_transaction_timeout)( - const struct i2c_hw_engine *engine, - uint32_t length); -}; - -struct i2c_hw_engine { - struct i2c_engine base; - const struct i2c_hw_engine_funcs *funcs; - - /* Values below are in kilohertz */ - uint32_t original_speed; - uint32_t default_speed; -}; - -void dal_i2c_hw_engine_construct( - struct i2c_hw_engine *engine, - struct dc_context *ctx); - -void dal_i2c_hw_engine_destruct( - struct i2c_hw_engine *engine); - -enum i2c_channel_operation_result dal_i2c_hw_engine_wait_on_operation_result( - struct i2c_hw_engine *engine, - uint32_t timeout, - enum i2c_channel_operation_result expected_result); - -bool dal_i2c_hw_engine_acquire_engine( - struct i2c_engine *engine, - struct ddc *ddc); - -bool dal_i2c_hw_engine_submit_request( - struct engine *ptr, - struct i2caux_transaction_request *i2caux_request, - bool middle_of_transaction); - -enum i2caux_engine_type dal_i2c_hw_engine_get_engine_type( - const struct engine *engine); - -#endif diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_sw_engine.c b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_sw_engine.c deleted file mode 100644 index 8e19bb629394..000000000000 --- a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_sw_engine.c +++ /dev/null @@ -1,601 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" - -/* - * Pre-requisites: headers required by header of this unit - */ -#include "include/i2caux_interface.h" -#include "engine.h" -#include "i2c_engine.h" - -/* - * Header of this unit - */ - -#include "i2c_sw_engine.h" - -/* - * Post-requisites: headers required by this unit - */ - -/* - * This unit - */ - -#define SCL false -#define SDA true - -static inline bool read_bit_from_ddc( - struct ddc *ddc, - bool data_nor_clock) -{ - uint32_t value = 0; - - if (data_nor_clock) - dal_gpio_get_value(ddc->pin_data, &value); - else - dal_gpio_get_value(ddc->pin_clock, &value); - - return (value != 0); -} - -static inline void write_bit_to_ddc( - struct ddc *ddc, - bool data_nor_clock, - bool bit) -{ - uint32_t value = bit ? 1 : 0; - - if (data_nor_clock) - dal_gpio_set_value(ddc->pin_data, value); - else - dal_gpio_set_value(ddc->pin_clock, value); -} - -static bool wait_for_scl_high( - struct dc_context *ctx, - struct ddc *ddc, - uint16_t clock_delay_div_4) -{ - uint32_t scl_retry = 0; - uint32_t scl_retry_max = I2C_SW_TIMEOUT_DELAY / clock_delay_div_4; - - udelay(clock_delay_div_4); - - /* 3 milliseconds delay - * to wake up some displays from "low power" state. - */ - - do { - if (read_bit_from_ddc(ddc, SCL)) - return true; - - udelay(clock_delay_div_4); - - ++scl_retry; - } while (scl_retry <= scl_retry_max); - - return false; -} - -static bool start_sync( - struct dc_context *ctx, - struct ddc *ddc_handle, - uint16_t clock_delay_div_4) -{ - uint32_t retry = 0; - - /* The I2C communications start signal is: - * the SDA going low from high, while the SCL is high. */ - - write_bit_to_ddc(ddc_handle, SCL, true); - - udelay(clock_delay_div_4); - - do { - write_bit_to_ddc(ddc_handle, SDA, true); - - if (!read_bit_from_ddc(ddc_handle, SDA)) { - ++retry; - continue; - } - - udelay(clock_delay_div_4); - - write_bit_to_ddc(ddc_handle, SCL, true); - - if (!wait_for_scl_high(ctx, ddc_handle, clock_delay_div_4)) - break; - - write_bit_to_ddc(ddc_handle, SDA, false); - - udelay(clock_delay_div_4); - - write_bit_to_ddc(ddc_handle, SCL, false); - - udelay(clock_delay_div_4); - - return true; - } while (retry <= I2C_SW_RETRIES); - - return false; -} - -static bool stop_sync( - struct dc_context *ctx, - struct ddc *ddc_handle, - uint16_t clock_delay_div_4) -{ - uint32_t retry = 0; - - /* The I2C communications stop signal is: - * the SDA going high from low, while the SCL is high. */ - - write_bit_to_ddc(ddc_handle, SCL, false); - - udelay(clock_delay_div_4); - - write_bit_to_ddc(ddc_handle, SDA, false); - - udelay(clock_delay_div_4); - - write_bit_to_ddc(ddc_handle, SCL, true); - - if (!wait_for_scl_high(ctx, ddc_handle, clock_delay_div_4)) - return false; - - write_bit_to_ddc(ddc_handle, SDA, true); - - do { - udelay(clock_delay_div_4); - - if (read_bit_from_ddc(ddc_handle, SDA)) - return true; - - ++retry; - } while (retry <= 2); - - return false; -} - -static bool write_byte( - struct dc_context *ctx, - struct ddc *ddc_handle, - uint16_t clock_delay_div_4, - uint8_t byte) -{ - int32_t shift = 7; - bool ack; - - /* bits are transmitted serially, starting from MSB */ - - do { - udelay(clock_delay_div_4); - - write_bit_to_ddc(ddc_handle, SDA, (byte >> shift) & 1); - - udelay(clock_delay_div_4); - - write_bit_to_ddc(ddc_handle, SCL, true); - - if (!wait_for_scl_high(ctx, ddc_handle, clock_delay_div_4)) - return false; - - write_bit_to_ddc(ddc_handle, SCL, false); - - --shift; - } while (shift >= 0); - - /* The display sends ACK by preventing the SDA from going high - * after the SCL pulse we use to send our last data bit. - * If the SDA goes high after that bit, it's a NACK */ - - udelay(clock_delay_div_4); - - write_bit_to_ddc(ddc_handle, SDA, true); - - udelay(clock_delay_div_4); - - write_bit_to_ddc(ddc_handle, SCL, true); - - if (!wait_for_scl_high(ctx, ddc_handle, clock_delay_div_4)) - return false; - - /* read ACK bit */ - - ack = !read_bit_from_ddc(ddc_handle, SDA); - - udelay(clock_delay_div_4 << 1); - - write_bit_to_ddc(ddc_handle, SCL, false); - - udelay(clock_delay_div_4 << 1); - - return ack; -} - -static bool read_byte( - struct dc_context *ctx, - struct ddc *ddc_handle, - uint16_t clock_delay_div_4, - uint8_t *byte, - bool more) -{ - int32_t shift = 7; - - uint8_t data = 0; - - /* The data bits are read from MSB to LSB; - * bit is read while SCL is high */ - - do { - write_bit_to_ddc(ddc_handle, SCL, true); - - if (!wait_for_scl_high(ctx, ddc_handle, clock_delay_div_4)) - return false; - - if (read_bit_from_ddc(ddc_handle, SDA)) - data |= (1 << shift); - - write_bit_to_ddc(ddc_handle, SCL, false); - - udelay(clock_delay_div_4 << 1); - - --shift; - } while (shift >= 0); - - /* read only whole byte */ - - *byte = data; - - udelay(clock_delay_div_4); - - /* send the acknowledge bit: - * SDA low means ACK, SDA high means NACK */ - - write_bit_to_ddc(ddc_handle, SDA, !more); - - udelay(clock_delay_div_4); - - write_bit_to_ddc(ddc_handle, SCL, true); - - if (!wait_for_scl_high(ctx, ddc_handle, clock_delay_div_4)) - return false; - - write_bit_to_ddc(ddc_handle, SCL, false); - - udelay(clock_delay_div_4); - - write_bit_to_ddc(ddc_handle, SDA, true); - - udelay(clock_delay_div_4); - - return true; -} - -static bool i2c_write( - struct dc_context *ctx, - struct ddc *ddc_handle, - uint16_t clock_delay_div_4, - uint8_t address, - uint32_t length, - const uint8_t *data) -{ - uint32_t i = 0; - - if (!write_byte(ctx, ddc_handle, clock_delay_div_4, address)) - return false; - - while (i < length) { - if (!write_byte(ctx, ddc_handle, clock_delay_div_4, data[i])) - return false; - ++i; - } - - return true; -} - -static bool i2c_read( - struct dc_context *ctx, - struct ddc *ddc_handle, - uint16_t clock_delay_div_4, - uint8_t address, - uint32_t length, - uint8_t *data) -{ - uint32_t i = 0; - - if (!write_byte(ctx, ddc_handle, clock_delay_div_4, address)) - return false; - - while (i < length) { - if (!read_byte(ctx, ddc_handle, clock_delay_div_4, data + i, - i < length - 1)) - return false; - ++i; - } - - return true; -} - -/* - * @brief - * Cast 'struct i2c_engine *' - * to 'struct i2c_sw_engine *' - */ -#define FROM_I2C_ENGINE(ptr) \ - container_of((ptr), struct i2c_sw_engine, base) - -/* - * @brief - * Cast 'struct engine *' - * to 'struct i2c_sw_engine *' - */ -#define FROM_ENGINE(ptr) \ - FROM_I2C_ENGINE(container_of((ptr), struct i2c_engine, base)) - -enum i2caux_engine_type dal_i2c_sw_engine_get_engine_type( - const struct engine *engine) -{ - return I2CAUX_ENGINE_TYPE_I2C_SW; -} - -bool dal_i2c_sw_engine_submit_request( - struct engine *engine, - struct i2caux_transaction_request *i2caux_request, - bool middle_of_transaction) -{ - struct i2c_sw_engine *sw_engine = FROM_ENGINE(engine); - - struct i2c_engine *base = &sw_engine->base; - - struct i2c_request_transaction_data request; - bool operation_succeeded = false; - - if (i2caux_request->operation == I2CAUX_TRANSACTION_READ) - request.action = middle_of_transaction ? - I2CAUX_TRANSACTION_ACTION_I2C_READ_MOT : - I2CAUX_TRANSACTION_ACTION_I2C_READ; - else if (i2caux_request->operation == I2CAUX_TRANSACTION_WRITE) - request.action = middle_of_transaction ? - I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT : - I2CAUX_TRANSACTION_ACTION_I2C_WRITE; - else { - i2caux_request->status = - I2CAUX_TRANSACTION_STATUS_FAILED_INVALID_OPERATION; - /* in DAL2, there was no "return false" */ - return false; - } - - request.address = (uint8_t)i2caux_request->payload.address; - request.length = i2caux_request->payload.length; - request.data = i2caux_request->payload.data; - - base->funcs->submit_channel_request(base, &request); - - if ((request.status == I2C_CHANNEL_OPERATION_ENGINE_BUSY) || - (request.status == I2C_CHANNEL_OPERATION_FAILED)) - i2caux_request->status = - I2CAUX_TRANSACTION_STATUS_FAILED_CHANNEL_BUSY; - else { - enum i2c_channel_operation_result operation_result; - - do { - operation_result = - base->funcs->get_channel_status(base, NULL); - - switch (operation_result) { - case I2C_CHANNEL_OPERATION_SUCCEEDED: - i2caux_request->status = - I2CAUX_TRANSACTION_STATUS_SUCCEEDED; - operation_succeeded = true; - break; - case I2C_CHANNEL_OPERATION_NO_RESPONSE: - i2caux_request->status = - I2CAUX_TRANSACTION_STATUS_FAILED_NACK; - break; - case I2C_CHANNEL_OPERATION_TIMEOUT: - i2caux_request->status = - I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT; - break; - case I2C_CHANNEL_OPERATION_FAILED: - i2caux_request->status = - I2CAUX_TRANSACTION_STATUS_FAILED_INCOMPLETE; - break; - default: - i2caux_request->status = - I2CAUX_TRANSACTION_STATUS_FAILED_OPERATION; - break; - } - } while (operation_result == I2C_CHANNEL_OPERATION_ENGINE_BUSY); - } - - return operation_succeeded; -} - -uint32_t dal_i2c_sw_engine_get_speed( - const struct i2c_engine *engine) -{ - return FROM_I2C_ENGINE(engine)->speed; -} - -void dal_i2c_sw_engine_set_speed( - struct i2c_engine *engine, - uint32_t speed) -{ - struct i2c_sw_engine *sw_engine = FROM_I2C_ENGINE(engine); - - ASSERT(speed); - - sw_engine->speed = speed ? speed : I2CAUX_DEFAULT_I2C_SW_SPEED; - - sw_engine->clock_delay = 1000 / sw_engine->speed; - - if (sw_engine->clock_delay < 12) - sw_engine->clock_delay = 12; -} - -bool dal_i2caux_i2c_sw_engine_acquire_engine( - struct i2c_engine *engine, - struct ddc *ddc) -{ - enum gpio_result result; - - result = dal_ddc_open(ddc, GPIO_MODE_FAST_OUTPUT, - GPIO_DDC_CONFIG_TYPE_MODE_I2C); - - if (result != GPIO_RESULT_OK) - return false; - - engine->base.ddc = ddc; - - return true; -} - -void dal_i2c_sw_engine_submit_channel_request( - struct i2c_engine *engine, - struct i2c_request_transaction_data *req) -{ - struct i2c_sw_engine *sw_engine = FROM_I2C_ENGINE(engine); - - struct ddc *ddc = engine->base.ddc; - uint16_t clock_delay_div_4 = sw_engine->clock_delay >> 2; - - /* send sync (start / repeated start) */ - - bool result = start_sync(engine->base.ctx, ddc, clock_delay_div_4); - - /* process payload */ - - if (result) { - switch (req->action) { - case I2CAUX_TRANSACTION_ACTION_I2C_WRITE: - case I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT: - result = i2c_write(engine->base.ctx, ddc, clock_delay_div_4, - req->address, req->length, req->data); - break; - case I2CAUX_TRANSACTION_ACTION_I2C_READ: - case I2CAUX_TRANSACTION_ACTION_I2C_READ_MOT: - result = i2c_read(engine->base.ctx, ddc, clock_delay_div_4, - req->address, req->length, req->data); - break; - default: - result = false; - break; - } - } - - /* send stop if not 'mot' or operation failed */ - - if (!result || - (req->action == I2CAUX_TRANSACTION_ACTION_I2C_WRITE) || - (req->action == I2CAUX_TRANSACTION_ACTION_I2C_READ)) - if (!stop_sync(engine->base.ctx, ddc, clock_delay_div_4)) - result = false; - - req->status = result ? - I2C_CHANNEL_OPERATION_SUCCEEDED : - I2C_CHANNEL_OPERATION_FAILED; -} - -enum i2c_channel_operation_result dal_i2c_sw_engine_get_channel_status( - struct i2c_engine *engine, - uint8_t *returned_bytes) -{ - /* No arbitration with VBIOS is performed since DCE 6.0 */ - return I2C_CHANNEL_OPERATION_SUCCEEDED; -} - -void dal_i2c_sw_engine_destruct( - struct i2c_sw_engine *engine) -{ - dal_i2c_engine_destruct(&engine->base); -} - -static void destroy( - struct i2c_engine **ptr) -{ - dal_i2c_sw_engine_destruct(FROM_I2C_ENGINE(*ptr)); - - kfree(*ptr); - *ptr = NULL; -} - -static const struct i2c_engine_funcs i2c_engine_funcs = { - .acquire_engine = dal_i2caux_i2c_sw_engine_acquire_engine, - .destroy = destroy, - .get_speed = dal_i2c_sw_engine_get_speed, - .set_speed = dal_i2c_sw_engine_set_speed, - .setup_engine = dal_i2c_engine_setup_i2c_engine, - .submit_channel_request = dal_i2c_sw_engine_submit_channel_request, - .process_channel_reply = dal_i2c_engine_process_channel_reply, - .get_channel_status = dal_i2c_sw_engine_get_channel_status, -}; - -static void release_engine( - struct engine *engine) -{ - -} - -static const struct engine_funcs engine_funcs = { - .release_engine = release_engine, - .get_engine_type = dal_i2c_sw_engine_get_engine_type, - .acquire = dal_i2c_engine_acquire, - .submit_request = dal_i2c_sw_engine_submit_request, -}; - -void dal_i2c_sw_engine_construct( - struct i2c_sw_engine *engine, - const struct i2c_sw_engine_create_arg *arg) -{ - dal_i2c_engine_construct(&engine->base, arg->ctx); - dal_i2c_sw_engine_set_speed(&engine->base, arg->default_speed); - engine->base.funcs = &i2c_engine_funcs; - engine->base.base.funcs = &engine_funcs; -} - -struct i2c_engine *dal_i2c_sw_engine_create( - const struct i2c_sw_engine_create_arg *arg) -{ - struct i2c_sw_engine *engine; - - if (!arg) { - BREAK_TO_DEBUGGER(); - return NULL; - } - - engine = kzalloc(sizeof(struct i2c_sw_engine), GFP_KERNEL); - - if (!engine) { - BREAK_TO_DEBUGGER(); - return NULL; - } - - dal_i2c_sw_engine_construct(engine, arg); - return &engine->base; -} diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_sw_engine.h b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_sw_engine.h deleted file mode 100644 index 546f15b0d3f1..000000000000 --- a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_sw_engine.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#ifndef __DAL_I2C_SW_ENGINE_H__ -#define __DAL_I2C_SW_ENGINE_H__ - -enum { - I2C_SW_RETRIES = 10, - I2C_SW_SCL_READ_RETRIES = 128, - /* following value is in microseconds */ - I2C_SW_TIMEOUT_DELAY = 3000 -}; - -struct i2c_sw_engine; - -struct i2c_sw_engine { - struct i2c_engine base; - uint32_t clock_delay; - /* Values below are in KHz */ - uint32_t speed; - uint32_t default_speed; -}; - -struct i2c_sw_engine_create_arg { - uint32_t default_speed; - struct dc_context *ctx; -}; - -void dal_i2c_sw_engine_construct( - struct i2c_sw_engine *engine, - const struct i2c_sw_engine_create_arg *arg); - -bool dal_i2caux_i2c_sw_engine_acquire_engine( - struct i2c_engine *engine, - struct ddc *ddc_handle); - -void dal_i2c_sw_engine_destruct( - struct i2c_sw_engine *engine); - -struct i2c_engine *dal_i2c_sw_engine_create( - const struct i2c_sw_engine_create_arg *arg); -enum i2caux_engine_type dal_i2c_sw_engine_get_engine_type( - const struct engine *engine); -bool dal_i2c_sw_engine_submit_request( - struct engine *ptr, - struct i2caux_transaction_request *i2caux_request, - bool middle_of_transaction); -uint32_t dal_i2c_sw_engine_get_speed( - const struct i2c_engine *engine); -void dal_i2c_sw_engine_set_speed( - struct i2c_engine *ptr, - uint32_t speed); -void dal_i2c_sw_engine_submit_channel_request( - struct i2c_engine *ptr, - struct i2c_request_transaction_data *req); -enum i2c_channel_operation_result dal_i2c_sw_engine_get_channel_status( - struct i2c_engine *engine, - uint8_t *returned_bytes); -#endif diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c b/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c deleted file mode 100644 index 1ad6e49102ff..000000000000 --- a/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c +++ /dev/null @@ -1,491 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" - -/* - * Pre-requisites: headers required by header of this unit - */ -#include "include/i2caux_interface.h" -#include "dc_bios_types.h" - -/* - * Header of this unit - */ - -#include "i2caux.h" - -/* - * Post-requisites: headers required by this unit - */ - -#include "engine.h" -#include "i2c_engine.h" -#include "aux_engine.h" - -/* - * This unit - */ - -#include "dce80/i2caux_dce80.h" - -#include "dce100/i2caux_dce100.h" - -#include "dce110/i2caux_dce110.h" - -#include "dce112/i2caux_dce112.h" - -#include "dce120/i2caux_dce120.h" - -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) -#include "dcn10/i2caux_dcn10.h" -#endif - -#include "diagnostics/i2caux_diag.h" - -/* - * @brief - * Plain API, available publicly - */ - -struct i2caux *dal_i2caux_create( - struct dc_context *ctx) -{ - if (IS_FPGA_MAXIMUS_DC(ctx->dce_environment)) { - return dal_i2caux_diag_fpga_create(ctx); - } - - switch (ctx->dce_version) { - case DCE_VERSION_8_0: - case DCE_VERSION_8_1: - case DCE_VERSION_8_3: - return dal_i2caux_dce80_create(ctx); - case DCE_VERSION_11_2: - case DCE_VERSION_11_22: - return dal_i2caux_dce112_create(ctx); - case DCE_VERSION_11_0: - return dal_i2caux_dce110_create(ctx); - case DCE_VERSION_10_0: - return dal_i2caux_dce100_create(ctx); - case DCE_VERSION_12_0: - case DCE_VERSION_12_1: - return dal_i2caux_dce120_create(ctx); -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) - case DCN_VERSION_1_0: - return dal_i2caux_dcn10_create(ctx); -#endif - -#if defined(CONFIG_DRM_AMD_DC_DCN1_01) - case DCN_VERSION_1_01: - return dal_i2caux_dcn10_create(ctx); -#endif - default: - BREAK_TO_DEBUGGER(); - return NULL; - } -} - -bool dal_i2caux_submit_i2c_command( - struct i2caux *i2caux, - struct ddc *ddc, - struct i2c_command *cmd) -{ - struct i2c_engine *engine; - uint8_t index_of_payload = 0; - bool result; - - if (!ddc) { - BREAK_TO_DEBUGGER(); - return false; - } - - if (!cmd) { - BREAK_TO_DEBUGGER(); - return false; - } - - /* - * default will be SW, however there is a feature flag in adapter - * service that determines whether SW i2c_engine will be available or - * not, if sw i2c is not available we will fallback to hw. This feature - * flag is set to not creating sw i2c engine for every dce except dce80 - * currently - */ - switch (cmd->engine) { - case I2C_COMMAND_ENGINE_DEFAULT: - case I2C_COMMAND_ENGINE_SW: - /* try to acquire SW engine first, - * acquire HW engine if SW engine not available */ - engine = i2caux->funcs->acquire_i2c_sw_engine(i2caux, ddc); - - if (!engine) - engine = i2caux->funcs->acquire_i2c_hw_engine( - i2caux, ddc); - break; - case I2C_COMMAND_ENGINE_HW: - default: - /* try to acquire HW engine first, - * acquire SW engine if HW engine not available */ - engine = i2caux->funcs->acquire_i2c_hw_engine(i2caux, ddc); - - if (!engine) - engine = i2caux->funcs->acquire_i2c_sw_engine( - i2caux, ddc); - } - - if (!engine) - return false; - - engine->funcs->set_speed(engine, cmd->speed); - - result = true; - - while (index_of_payload < cmd->number_of_payloads) { - bool mot = (index_of_payload != cmd->number_of_payloads - 1); - - struct i2c_payload *payload = cmd->payloads + index_of_payload; - - struct i2caux_transaction_request request = { 0 }; - - request.operation = payload->write ? - I2CAUX_TRANSACTION_WRITE : - I2CAUX_TRANSACTION_READ; - - request.payload.address_space = - I2CAUX_TRANSACTION_ADDRESS_SPACE_I2C; - request.payload.address = (payload->address << 1) | - !payload->write; - request.payload.length = payload->length; - request.payload.data = payload->data; - - if (!engine->base.funcs->submit_request( - &engine->base, &request, mot)) { - result = false; - break; - } - - ++index_of_payload; - } - - i2caux->funcs->release_engine(i2caux, &engine->base); - - return result; -} - -bool dal_i2caux_submit_aux_command( - struct i2caux *i2caux, - struct ddc *ddc, - struct aux_command *cmd) -{ - struct aux_engine *engine; - uint8_t index_of_payload = 0; - bool result; - bool mot; - - if (!ddc) { - BREAK_TO_DEBUGGER(); - return false; - } - - if (!cmd) { - BREAK_TO_DEBUGGER(); - return false; - } - - engine = i2caux->funcs->acquire_aux_engine(i2caux, ddc); - - if (!engine) - return false; - - engine->delay = cmd->defer_delay; - engine->max_defer_write_retry = cmd->max_defer_write_retry; - - result = true; - - while (index_of_payload < cmd->number_of_payloads) { - struct aux_payload *payload = cmd->payloads + index_of_payload; - struct i2caux_transaction_request request = { 0 }; - - if (cmd->mot == I2C_MOT_UNDEF) - mot = (index_of_payload != cmd->number_of_payloads - 1); - else - mot = (cmd->mot == I2C_MOT_TRUE); - - request.operation = payload->write ? - I2CAUX_TRANSACTION_WRITE : - I2CAUX_TRANSACTION_READ; - - if (payload->i2c_over_aux) { - request.payload.address_space = - I2CAUX_TRANSACTION_ADDRESS_SPACE_I2C; - - request.payload.address = (payload->address << 1) | - !payload->write; - } else { - request.payload.address_space = - I2CAUX_TRANSACTION_ADDRESS_SPACE_DPCD; - - request.payload.address = payload->address; - } - - request.payload.length = payload->length; - request.payload.data = payload->data; - - if (!engine->base.funcs->submit_request( - &engine->base, &request, mot)) { - result = false; - break; - } - - ++index_of_payload; - } - - i2caux->funcs->release_engine(i2caux, &engine->base); - - return result; -} - -static bool get_hw_supported_ddc_line( - struct ddc *ddc, - enum gpio_ddc_line *line) -{ - enum gpio_ddc_line line_found; - - *line = GPIO_DDC_LINE_UNKNOWN; - - if (!ddc) { - BREAK_TO_DEBUGGER(); - return false; - } - - if (!ddc->hw_info.hw_supported) - return false; - - line_found = dal_ddc_get_line(ddc); - - if (line_found >= GPIO_DDC_LINE_COUNT) - return false; - - *line = line_found; - - return true; -} - -void dal_i2caux_configure_aux( - struct i2caux *i2caux, - struct ddc *ddc, - union aux_config cfg) -{ - struct aux_engine *engine = - i2caux->funcs->acquire_aux_engine(i2caux, ddc); - - if (!engine) - return; - - engine->funcs->configure(engine, cfg); - - i2caux->funcs->release_engine(i2caux, &engine->base); -} - -void dal_i2caux_destroy( - struct i2caux **i2caux) -{ - if (!i2caux || !*i2caux) { - BREAK_TO_DEBUGGER(); - return; - } - - (*i2caux)->funcs->destroy(i2caux); - - *i2caux = NULL; -} - -/* - * @brief - * An utility function used by 'struct i2caux' and its descendants - */ - -uint32_t dal_i2caux_get_reference_clock( - struct dc_bios *bios) -{ - struct dc_firmware_info info = { { 0 } }; - - if (bios->funcs->get_firmware_info(bios, &info) != BP_RESULT_OK) - return 0; - - return info.pll_info.crystal_frequency; -} - -/* - * @brief - * i2caux - */ - -enum { - /* following are expressed in KHz */ - DEFAULT_I2C_SW_SPEED = 50, - DEFAULT_I2C_HW_SPEED = 50, - - DEFAULT_I2C_SW_SPEED_100KHZ = 100, - DEFAULT_I2C_HW_SPEED_100KHZ = 100, - - /* This is the timeout as defined in DP 1.2a, - * 2.3.4 "Detailed uPacket TX AUX CH State Description". */ - AUX_TIMEOUT_PERIOD = 400, - - /* Ideally, the SW timeout should be just above 550usec - * which is programmed in HW. - * But the SW timeout of 600usec is not reliable, - * because on some systems, delay_in_microseconds() - * returns faster than it should. - * EPR #379763: by trial-and-error on different systems, - * 700usec is the minimum reliable SW timeout for polling - * the AUX_SW_STATUS.AUX_SW_DONE bit. - * This timeout expires *only* when there is - * AUX Error or AUX Timeout conditions - not during normal operation. - * During normal operation, AUX_SW_STATUS.AUX_SW_DONE bit is set - * at most within ~240usec. That means, - * increasing this timeout will not affect normal operation, - * and we'll timeout after - * SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD = 1600usec. - * This timeout is especially important for - * resume from S3 and CTS. */ - SW_AUX_TIMEOUT_PERIOD_MULTIPLIER = 4 -}; - -struct i2c_engine *dal_i2caux_acquire_i2c_sw_engine( - struct i2caux *i2caux, - struct ddc *ddc) -{ - enum gpio_ddc_line line; - struct i2c_engine *engine = NULL; - - if (get_hw_supported_ddc_line(ddc, &line)) - engine = i2caux->i2c_sw_engines[line]; - - if (!engine) - engine = i2caux->i2c_generic_sw_engine; - - if (!engine) - return NULL; - - if (!engine->base.funcs->acquire(&engine->base, ddc)) - return NULL; - - return engine; -} - -struct aux_engine *dal_i2caux_acquire_aux_engine( - struct i2caux *i2caux, - struct ddc *ddc) -{ - enum gpio_ddc_line line; - struct aux_engine *engine; - - if (!get_hw_supported_ddc_line(ddc, &line)) - return NULL; - - engine = i2caux->aux_engines[line]; - - if (!engine) - return NULL; - - if (!engine->base.funcs->acquire(&engine->base, ddc)) - return NULL; - - return engine; -} - -void dal_i2caux_release_engine( - struct i2caux *i2caux, - struct engine *engine) -{ - engine->funcs->release_engine(engine); - - dal_ddc_close(engine->ddc); - - engine->ddc = NULL; -} - -void dal_i2caux_construct( - struct i2caux *i2caux, - struct dc_context *ctx) -{ - uint32_t i = 0; - - i2caux->ctx = ctx; - do { - i2caux->i2c_sw_engines[i] = NULL; - i2caux->i2c_hw_engines[i] = NULL; - i2caux->aux_engines[i] = NULL; - - ++i; - } while (i < GPIO_DDC_LINE_COUNT); - - i2caux->i2c_generic_sw_engine = NULL; - i2caux->i2c_generic_hw_engine = NULL; - - i2caux->aux_timeout_period = - SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD; - - if (ctx->dce_version >= DCE_VERSION_11_2) { - i2caux->default_i2c_hw_speed = DEFAULT_I2C_HW_SPEED_100KHZ; - i2caux->default_i2c_sw_speed = DEFAULT_I2C_SW_SPEED_100KHZ; - } else { - i2caux->default_i2c_hw_speed = DEFAULT_I2C_HW_SPEED; - i2caux->default_i2c_sw_speed = DEFAULT_I2C_SW_SPEED; - } -} - -void dal_i2caux_destruct( - struct i2caux *i2caux) -{ - uint32_t i = 0; - - if (i2caux->i2c_generic_hw_engine) - i2caux->i2c_generic_hw_engine->funcs->destroy( - &i2caux->i2c_generic_hw_engine); - - if (i2caux->i2c_generic_sw_engine) - i2caux->i2c_generic_sw_engine->funcs->destroy( - &i2caux->i2c_generic_sw_engine); - - do { - if (i2caux->aux_engines[i]) - i2caux->aux_engines[i]->funcs->destroy( - &i2caux->aux_engines[i]); - - if (i2caux->i2c_hw_engines[i]) - i2caux->i2c_hw_engines[i]->funcs->destroy( - &i2caux->i2c_hw_engines[i]); - - if (i2caux->i2c_sw_engines[i]) - i2caux->i2c_sw_engines[i]->funcs->destroy( - &i2caux->i2c_sw_engines[i]); - - ++i; - } while (i < GPIO_DDC_LINE_COUNT); -} - diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.h b/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.h deleted file mode 100644 index 64f51bb06915..000000000000 --- a/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.h +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#ifndef __DAL_I2C_AUX_H__ -#define __DAL_I2C_AUX_H__ - -uint32_t dal_i2caux_get_reference_clock( - struct dc_bios *bios); - -struct i2caux; - -struct engine; - -struct i2caux_funcs { - void (*destroy)(struct i2caux **ptr); - struct i2c_engine * (*acquire_i2c_sw_engine)( - struct i2caux *i2caux, - struct ddc *ddc); - struct i2c_engine * (*acquire_i2c_hw_engine)( - struct i2caux *i2caux, - struct ddc *ddc); - struct aux_engine * (*acquire_aux_engine)( - struct i2caux *i2caux, - struct ddc *ddc); - void (*release_engine)( - struct i2caux *i2caux, - struct engine *engine); -}; - -struct i2c_engine; -struct aux_engine; - -struct i2caux { - struct dc_context *ctx; - const struct i2caux_funcs *funcs; - /* On ASIC we have certain amount of lines with HW DDC engine - * (4, 6, or maybe more in the future). - * For every such line, we create separate HW DDC engine - * (since we have these engines in HW) and separate SW DDC engine - * (to allow concurrent use of few lines). - * In similar way we have AUX engines. */ - - /* I2C SW engines, per DDC line. - * Only lines with HW DDC support will be initialized */ - struct i2c_engine *i2c_sw_engines[GPIO_DDC_LINE_COUNT]; - - /* I2C HW engines, per DDC line. - * Only lines with HW DDC support will be initialized */ - struct i2c_engine *i2c_hw_engines[GPIO_DDC_LINE_COUNT]; - - /* AUX engines, per DDC line. - * Only lines with HW AUX support will be initialized */ - struct aux_engine *aux_engines[GPIO_DDC_LINE_COUNT]; - - /* For all other lines, we can use - * single instance of generic I2C HW engine - * (since in HW, there is single instance of it) - * or single instance of generic I2C SW engine. - * AUX is not supported for other lines. */ - - /* General-purpose I2C SW engine. - * Can be assigned dynamically to any line per transaction */ - struct i2c_engine *i2c_generic_sw_engine; - - /* General-purpose I2C generic HW engine. - * Can be assigned dynamically to almost any line per transaction */ - struct i2c_engine *i2c_generic_hw_engine; - - /* [anaumov] in DAL2, there is a Mutex */ - - uint32_t aux_timeout_period; - - /* expressed in KHz */ - uint32_t default_i2c_sw_speed; - uint32_t default_i2c_hw_speed; -}; - -void dal_i2caux_construct( - struct i2caux *i2caux, - struct dc_context *ctx); - -void dal_i2caux_release_engine( - struct i2caux *i2caux, - struct engine *engine); - -void dal_i2caux_destruct( - struct i2caux *i2caux); - -void dal_i2caux_destroy( - struct i2caux **ptr); - -struct i2c_engine *dal_i2caux_acquire_i2c_sw_engine( - struct i2caux *i2caux, - struct ddc *ddc); - -struct aux_engine *dal_i2caux_acquire_aux_engine( - struct i2caux *i2caux, - struct ddc *ddc); - -#endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/clock_source.h b/drivers/gpu/drm/amd/display/dc/inc/clock_source.h index 47ef90495376..43d1fbd8ace5 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/clock_source.h +++ b/drivers/gpu/drm/amd/display/dc/inc/clock_source.h @@ -78,7 +78,7 @@ struct csdp_ref_clk_ds_params { }; struct pixel_clk_params { - uint32_t requested_pix_clk; /* in KHz */ + uint32_t requested_pix_clk_100hz; /*> Requested Pixel Clock * (based on Video Timing standard used for requested mode)*/ uint32_t requested_sym_clk; /* in KHz */ @@ -104,9 +104,9 @@ struct pixel_clk_params { * with actually calculated Clock and reference Crystal frequency */ struct pll_settings { - uint32_t actual_pix_clk; - uint32_t adjusted_pix_clk; - uint32_t calculated_pix_clk; + uint32_t actual_pix_clk_100hz; + uint32_t adjusted_pix_clk_100hz; + uint32_t calculated_pix_clk_100hz; uint32_t vco_freq; uint32_t reference_freq; uint32_t reference_divider; diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_status.h b/drivers/gpu/drm/amd/display/dc/inc/core_status.h index 94fc31080fda..2e61a22ef4b2 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_status.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_status.h @@ -30,7 +30,7 @@ enum dc_status { DC_OK = 1, DC_NO_CONTROLLER_RESOURCE = 2, - DC_NO_STREAM_ENG_RESOURCE = 3, + DC_NO_STREAM_ENC_RESOURCE = 3, DC_NO_CLOCK_SOURCE_RESOURCE = 4, DC_FAIL_CONTROLLER_VALIDATE = 5, DC_FAIL_ENC_VALIDATE = 6, diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index b168a5e9dd9d..986ed1728644 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -146,7 +146,7 @@ struct resource_pool { struct mpc *mpc; struct pp_smu_funcs_rv *pp_smu; struct pp_smu_display_requirement_rv pp_smu_req; - struct aux_engine *engines[MAX_PIPES]; + struct dce_aux *engines[MAX_PIPES]; struct dce_i2c_hw *hw_i2cs[MAX_PIPES]; struct dce_i2c_sw *sw_i2cs[MAX_PIPES]; bool i2c_hw_buffer_in_use; @@ -180,13 +180,8 @@ struct resource_pool { const struct resource_caps *res_cap; }; -struct dcn_fe_clocks { - int dppclk_khz; -}; - struct dcn_fe_bandwidth { - struct dcn_fe_clocks calc; - struct dcn_fe_clocks cur; + int dppclk_khz; }; struct stream_resource { diff --git a/drivers/gpu/drm/amd/display/dc/inc/dc_link_ddc.h b/drivers/gpu/drm/amd/display/dc/inc/dc_link_ddc.h index 538b83303b86..16fd4dc6c4dd 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/dc_link_ddc.h +++ b/drivers/gpu/drm/amd/display/dc/inc/dc_link_ddc.h @@ -64,13 +64,6 @@ void dal_ddc_i2c_payloads_add( uint8_t *data, bool write); -void dal_ddc_aux_payloads_add( - struct aux_payloads *payloads, - uint32_t address, - uint32_t len, - uint8_t *data, - bool write); - struct ddc_service_init_data { struct graphics_object_id id; struct dc_context *ctx; @@ -103,12 +96,10 @@ bool dal_ddc_service_query_ddc_data( uint32_t read_size); int dc_link_aux_transfer(struct ddc_service *ddc, - unsigned int address, - uint8_t *reply, - void *buffer, - unsigned int size, - enum aux_transaction_type type, - enum i2caux_transaction_action action); + struct aux_payload *payload); + +bool dc_link_aux_transfer_with_retries(struct ddc_service *ddc, + struct aux_payload *payload); void dal_ddc_service_write_scdc_data( struct ddc_service *ddc_service, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h index 02f757dd70d4..9d2d8e51306c 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h @@ -39,6 +39,18 @@ enum segment_order { segment_order__non_contiguous, }; +struct dcn_hubbub_wm_set { + uint32_t wm_set; + uint32_t data_urgent; + uint32_t pte_meta_urgent; + uint32_t sr_enter; + uint32_t sr_exit; + uint32_t dram_clk_chanage; +}; + +struct dcn_hubbub_wm { + struct dcn_hubbub_wm_set sets[4]; +}; struct hubbub_funcs { void (*update_dchub)( @@ -58,7 +70,14 @@ struct hubbub_funcs { bool (*dcc_support_pixel_format)( enum surface_pixel_format format, unsigned int *bytes_per_element); + + void (*wm_read_state)(struct hubbub *hubbub, + struct dcn_hubbub_wm *wm); }; +struct hubbub { + const struct hubbub_funcs *funcs; + struct dc_context *ctx; +}; #endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h index cb85eaa9857f..cbaa43853611 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h @@ -27,16 +27,22 @@ #include "dm_services_types.h" +/* If HW itself ever powered down it will be 0. + * fwDmcuInit will write to 1. + * Driver will only call MCP init if current state is 1, + * and the MCP command will transition this to 2. + */ enum dmcu_state { - DMCU_NOT_INITIALIZED = 0, - DMCU_RUNNING = 1 + DMCU_UNLOADED = 0, + DMCU_LOADED_UNINITIALIZED = 1, + DMCU_RUNNING = 2, }; struct dmcu_version { - unsigned int date; - unsigned int month; - unsigned int year; unsigned int interface_version; + unsigned int abm_version; + unsigned int psr_version; + unsigned int build_version; }; struct dmcu { diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h index e894e649ce5a..fb7967b39edb 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h @@ -39,6 +39,11 @@ struct dpp { }; +struct dpp_input_csc_matrix { + enum dc_color_space color_space; + uint16_t regval[12]; +}; + struct dpp_grph_csc_adjustment { struct fixed31_32 temperature_matrix[CSC_TEMPERATURE_MATRIX_SIZE]; enum graphics_gamut_adjust_type gamut_adjust_type; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h index 04c6989aac58..1cd07e94ee63 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h @@ -78,7 +78,8 @@ struct hubp_funcs { bool (*hubp_program_surface_flip_and_addr)( struct hubp *hubp, const struct dc_plane_address *address, - bool flip_immediate); + bool flip_immediate, + uint8_t vmid); void (*hubp_program_pte_vm)( struct hubp *hubp, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h index 06df02ddff6a..da89c2edb07c 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h @@ -31,7 +31,7 @@ #include "dml/display_mode_structs.h" struct dchub_init_data; -struct cstate_pstate_watermarks_st1 { +struct cstate_pstate_watermarks_st { uint32_t cstate_exit_ns; uint32_t cstate_enter_plus_exit_ns; uint32_t pstate_change_ns; @@ -40,7 +40,7 @@ struct cstate_pstate_watermarks_st1 { struct dcn_watermarks { uint32_t pte_meta_urgent_ns; uint32_t urgent_ns; - struct cstate_pstate_watermarks_st1 cstate_pstate; + struct cstate_pstate_watermarks_st cstate_pstate; }; struct dcn_watermark_set { diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h index 53a9b64df11a..4051493557bc 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h @@ -161,6 +161,10 @@ struct stream_encoder_funcs { void (*set_avmute)( struct stream_encoder *enc, bool enable); + void (*dig_connect_to_otg)( + struct stream_encoder *enc, + int tg_inst); + }; #endif /* STREAM_ENCODER_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_sw_engine_dce110.h b/drivers/gpu/drm/amd/display/dc/inc/hw/vmid.h index c48c61f540a8..037beb0a2a27 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_sw_engine_dce110.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/vmid.h @@ -1,5 +1,5 @@ /* - * Copyright 2012-15 Advanced Micro Devices, Inc. + * Copyright 2018 Advanced Micro Devices, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -23,21 +23,27 @@ * */ -#ifndef __DAL_I2C_SW_ENGINE_DCE110_H__ -#define __DAL_I2C_SW_ENGINE_DCE110_H__ +#ifndef DAL_DC_INC_HW_VMID_H_ +#define DAL_DC_INC_HW_VMID_H_ -struct i2c_sw_engine_dce110 { - struct i2c_sw_engine base; - uint32_t engine_id; -}; +#include "core_types.h" +#include "dchubbub.h" -struct i2c_sw_engine_dce110_create_arg { - uint32_t engine_id; - uint32_t default_speed; - struct dc_context *ctx; +struct dcn_vmid_registers { + uint32_t CNTL; + uint32_t PAGE_TABLE_BASE_ADDR_HI32; + uint32_t PAGE_TABLE_BASE_ADDR_LO32; + uint32_t PAGE_TABLE_START_ADDR_HI32; + uint32_t PAGE_TABLE_START_ADDR_LO32; + uint32_t PAGE_TABLE_END_ADDR_HI32; + uint32_t PAGE_TABLE_END_ADDR_LO32; }; -struct i2c_engine *dal_i2c_sw_engine_dce110_create( - const struct i2c_sw_engine_dce110_create_arg *arg); +struct dcn_vmid_page_table_config { + uint64_t page_table_start_addr; + uint64_t page_table_end_addr; + enum dcn_hubbub_page_table_depth depth; + enum dcn_hubbub_page_table_block_size block_size; +}; -#endif +#endif /* DAL_DC_INC_HW_VMID_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_sw_engine_dce80.h b/drivers/gpu/drm/amd/display/dc/inc/vm_helper.h index 26355c088746..a202206e22a3 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_sw_engine_dce80.h +++ b/drivers/gpu/drm/amd/display/dc/inc/vm_helper.h @@ -1,5 +1,5 @@ /* - * Copyright 2012-15 Advanced Micro Devices, Inc. + * Copyright 2018 Advanced Micro Devices, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -23,21 +23,33 @@ * */ -#ifndef __DAL_I2C_SW_ENGINE_DCE80_H__ -#define __DAL_I2C_SW_ENGINE_DCE80_H__ +#ifndef DC_INC_VM_HELPER_H_ +#define DC_INC_VM_HELPER_H_ -struct i2c_sw_engine_dce80 { - struct i2c_sw_engine base; - uint32_t engine_id; +#include "dc_types.h" + +#define MAX_VMID 16 +#define MAX_HUBP 6 + +struct vmid_usage { + uint16_t vmid_usage[2]; }; -struct i2c_sw_engine_dce80_create_arg { - uint32_t engine_id; - uint32_t default_speed; - struct dc_context *ctx; +struct vm_helper { + unsigned int num_vmid; + unsigned int num_hubp; + unsigned int num_vmids_available; + uint64_t *ptb_assigned_to_vmid; + struct vmid_usage *hubp_vmid_usage; }; -struct i2c_engine *dal_i2c_sw_engine_dce80_create( - const struct i2c_sw_engine_dce80_create_arg *arg); +uint8_t get_vmid_for_ptb( + struct vm_helper *vm_helper, + int64_t ptb, + uint8_t pipe_idx); + +struct vm_helper init_vm_helper( + unsigned int num_vmid, + unsigned int num_hubp); -#endif +#endif /* DC_INC_VM_HELPER_H_ */ |