diff options
Diffstat (limited to 'drivers/gpu/drm/amd/display/dc/dcn10')
18 files changed, 692 insertions, 192 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c index 7469333a2c8a..01c7e30b9ce1 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c @@ -343,8 +343,8 @@ bool cm_helper_translate_curve_to_hw_format( region_start = -MAX_LOW_POINT; region_end = NUMBER_REGIONS - MAX_LOW_POINT; } else { - /* 10 segments - * segment is from 2^-10 to 2^0 + /* 11 segments + * segment is from 2^-10 to 2^1 * There are less than 256 points, for optimization */ seg_distr[0] = 3; @@ -357,9 +357,10 @@ bool cm_helper_translate_curve_to_hw_format( seg_distr[7] = 4; seg_distr[8] = 4; seg_distr[9] = 4; + seg_distr[10] = 1; region_start = -10; - region_end = 0; + region_end = 1; } for (i = region_end - region_start; i < MAX_REGIONS_NUMBER ; i++) 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 b95ec73fcae3..d8b2da18db39 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c @@ -426,8 +426,9 @@ void dpp1_cnv_setup ( void dpp1_set_cursor_attributes( struct dpp *dpp_base, - enum dc_cursor_color_format color_format) + struct dc_cursor_attributes *cursor_attributes) { + enum dc_cursor_color_format color_format = cursor_attributes->color_format; struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); REG_UPDATE_2(CURSOR0_CONTROL, @@ -456,6 +457,19 @@ void dpp1_set_cursor_position( int src_y_offset = pos->y - pos->y_hotspot - param->viewport.y; uint32_t cur_en = pos->enable ? 1 : 0; + // Cursor width/height and hotspots need to be rotated for offset calculation + if (param->rotation == ROTATION_ANGLE_90 || param->rotation == ROTATION_ANGLE_270) { + swap(width, height); + if (param->rotation == ROTATION_ANGLE_90) { + src_x_offset = pos->x - pos->y_hotspot - param->viewport.x; + src_y_offset = pos->y - pos->x_hotspot - param->viewport.y; + } + } else if (param->rotation == ROTATION_ANGLE_180) { + src_x_offset = pos->x - param->viewport.x; + src_y_offset = pos->y - param->viewport.y; + } + + if (src_x_offset >= (int)param->viewport.width) cur_en = 0; /* not visible beyond right edge*/ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h index 8a5517eebb7c..e2c613611ac9 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h @@ -1368,7 +1368,7 @@ enum dcn10_input_csc_select { void dpp1_set_cursor_attributes( struct dpp *dpp_base, - enum dc_cursor_color_format color_format); + struct dc_cursor_attributes *cursor_attributes); void dpp1_set_cursor_position( struct dpp *dpp_base, 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 a780057e2dbc..a02c10e23e0d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c @@ -104,7 +104,7 @@ void hubbub1_allow_self_refresh_control(struct hubbub *hubbub, bool allow) DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE, !allow); } -bool hububu1_is_allow_self_refresh_enabled(struct hubbub *hubbub) +bool hubbub1_is_allow_self_refresh_enabled(struct hubbub *hubbub) { struct dcn10_hubbub *hubbub1 = TO_DCN10_HUBBUB(hubbub); uint32_t enable = 0; @@ -945,6 +945,8 @@ static const struct hubbub_funcs hubbub1_funcs = { .get_dcc_compression_cap = hubbub1_get_dcc_compression_cap, .wm_read_state = hubbub1_wm_read_state, .program_watermarks = hubbub1_program_watermarks, + .is_allow_self_refresh_enabled = hubbub1_is_allow_self_refresh_enabled, + .allow_self_refresh_control = hubbub1_allow_self_refresh_control, }; void hubbub1_construct(struct hubbub *hubbub, 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 7c2559c9ae23..69d903d68661 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.h @@ -119,6 +119,28 @@ struct dcn_hubbub_registers { uint32_t DCN_VM_AGP_BOT; uint32_t DCN_VM_AGP_TOP; uint32_t DCN_VM_AGP_BASE; + uint32_t DCN_VM_PROTECTION_FAULT_DEFAULT_ADDR_MSB; + uint32_t DCN_VM_PROTECTION_FAULT_DEFAULT_ADDR_LSB; +#if defined(CONFIG_DRM_AMD_DC_DCN2_1) + uint32_t DCHUBBUB_ARB_FRAC_URG_BW_NOM_A; + uint32_t DCHUBBUB_ARB_FRAC_URG_BW_NOM_B; + uint32_t DCHUBBUB_ARB_FRAC_URG_BW_NOM_C; + uint32_t DCHUBBUB_ARB_FRAC_URG_BW_NOM_D; + uint32_t DCHUBBUB_ARB_FRAC_URG_BW_FLIP_A; + uint32_t DCHUBBUB_ARB_FRAC_URG_BW_FLIP_B; + uint32_t DCHUBBUB_ARB_FRAC_URG_BW_FLIP_C; + uint32_t DCHUBBUB_ARB_FRAC_URG_BW_FLIP_D; + uint32_t DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_A; + uint32_t DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_B; + uint32_t DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_C; + uint32_t DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_D; + uint32_t DCHUBBUB_ARB_HOSTVM_CNTL; + uint32_t DCHVM_CTRL0; + uint32_t DCHVM_MEM_CTRL; + uint32_t DCHVM_CLK_CTRL; + uint32_t DCHVM_RIOMMU_CTRL0; + uint32_t DCHVM_RIOMMU_STAT0; +#endif }; /* set field name */ @@ -196,7 +218,9 @@ struct dcn_hubbub_registers { type DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A;\ type DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B;\ type DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C;\ - type DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D + type DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D;\ + type DCN_VM_PROTECTION_FAULT_DEFAULT_ADDR_MSB;\ + type DCN_VM_PROTECTION_FAULT_DEFAULT_ADDR_LSB #define HUBBUB_STUTTER_REG_FIELD_LIST(type) \ type DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A;\ @@ -208,15 +232,68 @@ struct dcn_hubbub_registers { type DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C;\ type DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D +#if defined(CONFIG_DRM_AMD_DC_DCN2_1) +#define HUBBUB_HVM_REG_FIELD_LIST(type) \ + type DCHUBBUB_ARB_MIN_REQ_OUTSTAND_COMMIT_THRESHOLD;\ + type DCHUBBUB_ARB_VM_ROW_URGENCY_WATERMARK_A;\ + type DCHUBBUB_ARB_VM_ROW_URGENCY_WATERMARK_B;\ + type DCHUBBUB_ARB_VM_ROW_URGENCY_WATERMARK_C;\ + type DCHUBBUB_ARB_VM_ROW_URGENCY_WATERMARK_D;\ + type DCHUBBUB_ARB_VM_ROW_ALLOW_SR_ENTER_WATERMARK_A;\ + type DCHUBBUB_ARB_VM_ROW_ALLOW_SR_ENTER_WATERMARK_B;\ + type DCHUBBUB_ARB_VM_ROW_ALLOW_SR_ENTER_WATERMARK_C;\ + type DCHUBBUB_ARB_VM_ROW_ALLOW_SR_ENTER_WATERMARK_D;\ + type DCHUBBUB_ARB_VM_ROW_ALLOW_SR_EXIT_WATERMARK_A;\ + type DCHUBBUB_ARB_VM_ROW_ALLOW_SR_EXIT_WATERMARK_B;\ + type DCHUBBUB_ARB_VM_ROW_ALLOW_SR_EXIT_WATERMARK_C;\ + type DCHUBBUB_ARB_VM_ROW_ALLOW_SR_EXIT_WATERMARK_D;\ + type DCHUBBUB_ARB_VM_ROW_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A;\ + type DCHUBBUB_ARB_VM_ROW_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B;\ + type DCHUBBUB_ARB_VM_ROW_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C;\ + type DCHUBBUB_ARB_VM_ROW_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D;\ + type DCHUBBUB_ARB_FRAC_URG_BW_NOM_A;\ + type DCHUBBUB_ARB_FRAC_URG_BW_NOM_B;\ + type DCHUBBUB_ARB_FRAC_URG_BW_NOM_C;\ + type DCHUBBUB_ARB_FRAC_URG_BW_NOM_D;\ + type DCHUBBUB_ARB_FRAC_URG_BW_FLIP_A;\ + type DCHUBBUB_ARB_FRAC_URG_BW_FLIP_B;\ + type DCHUBBUB_ARB_FRAC_URG_BW_FLIP_C;\ + type DCHUBBUB_ARB_FRAC_URG_BW_FLIP_D;\ + type DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_A;\ + type DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_B;\ + type DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_C;\ + type DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_D;\ + type DCHUBBUB_ARB_MAX_QOS_COMMIT_THRESHOLD;\ + type HOSTVM_INIT_REQ; \ + type HVM_GPUVMRET_PWR_REQ_DIS; \ + type HVM_GPUVMRET_FORCE_REQ; \ + type HVM_GPUVMRET_POWER_STATUS; \ + type HVM_DISPCLK_R_GATE_DIS; \ + type HVM_DISPCLK_G_GATE_DIS; \ + type HVM_DCFCLK_R_GATE_DIS; \ + type HVM_DCFCLK_G_GATE_DIS; \ + type TR_REQ_REQCLKREQ_MODE; \ + type TW_RSP_COMPCLKREQ_MODE; \ + type HOSTVM_PREFETCH_REQ; \ + type HOSTVM_POWERSTATUS; \ + type RIOMMU_ACTIVE; \ + type HOSTVM_PREFETCH_DONE +#endif struct dcn_hubbub_shift { DCN_HUBBUB_REG_FIELD_LIST(uint8_t); HUBBUB_STUTTER_REG_FIELD_LIST(uint8_t); +#if defined(CONFIG_DRM_AMD_DC_DCN2_1) + HUBBUB_HVM_REG_FIELD_LIST(uint8_t); +#endif }; struct dcn_hubbub_mask { DCN_HUBBUB_REG_FIELD_LIST(uint32_t); HUBBUB_STUTTER_REG_FIELD_LIST(uint32_t); +#if defined(CONFIG_DRM_AMD_DC_DCN2_1) + HUBBUB_HVM_REG_FIELD_LIST(uint32_t); +#endif }; struct dc; @@ -247,7 +324,7 @@ void hubbub1_program_watermarks( void hubbub1_allow_self_refresh_control(struct hubbub *hubbub, bool allow); -bool hububu1_is_allow_self_refresh_enabled(struct hubbub *hubub); +bool hubbub1_is_allow_self_refresh_enabled(struct hubbub *hubub); void hubbub1_toggle_watermark_change_req( struct hubbub *hubbub); 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 934bacc0c6ad..001db49e4bb2 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c @@ -163,7 +163,7 @@ void hubp1_program_tiling( void hubp1_program_size( struct hubp *hubp, enum surface_pixel_format format, - const union plane_size *plane_size, + const struct plane_size *plane_size, struct dc_plane_dcc_param *dcc) { struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); @@ -173,16 +173,16 @@ void hubp1_program_size( * 444 or 420 luma */ if (format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN && format < SURFACE_PIXEL_FORMAT_SUBSAMPLE_END) { - ASSERT(plane_size->video.chroma_pitch != 0); + ASSERT(plane_size->chroma_pitch != 0); /* Chroma pitch zero can cause system hang! */ - pitch = plane_size->video.luma_pitch - 1; - meta_pitch = dcc->video.meta_pitch_l - 1; - pitch_c = plane_size->video.chroma_pitch - 1; - meta_pitch_c = dcc->video.meta_pitch_c - 1; + pitch = plane_size->surface_pitch - 1; + meta_pitch = dcc->meta_pitch - 1; + pitch_c = plane_size->chroma_pitch - 1; + meta_pitch_c = dcc->meta_pitch_c - 1; } else { - pitch = plane_size->grph.surface_pitch - 1; - meta_pitch = dcc->grph.meta_pitch - 1; + pitch = plane_size->surface_pitch - 1; + meta_pitch = dcc->meta_pitch - 1; pitch_c = 0; meta_pitch_c = 0; } @@ -509,7 +509,7 @@ bool hubp1_program_surface_flip_and_addr( } void hubp1_dcc_control(struct hubp *hubp, bool enable, - bool independent_64b_blks) + enum hubp_ind_block_size independent_64b_blks) { uint32_t dcc_en = enable ? 1 : 0; uint32_t dcc_ind_64b_blk = independent_64b_blks ? 1 : 0; @@ -526,13 +526,13 @@ void hubp1_program_surface_config( struct hubp *hubp, enum surface_pixel_format format, union dc_tiling_info *tiling_info, - union plane_size *plane_size, + struct plane_size *plane_size, enum dc_rotation_angle rotation, struct dc_plane_dcc_param *dcc, bool horizontal_mirror, unsigned int compat_level) { - hubp1_dcc_control(hubp, dcc->enable, dcc->grph.independent_64b_blks); + hubp1_dcc_control(hubp, dcc->enable, dcc->independent_64b_blks); hubp1_program_tiling(hubp, tiling_info, format); hubp1_program_size(hubp, format, plane_size, dcc); hubp1_program_rotation(hubp, rotation, horizontal_mirror); @@ -843,7 +843,7 @@ void min_set_viewport( PRI_VIEWPORT_Y_START_C, viewport_c->y); } -void hubp1_read_state(struct hubp *hubp) +void hubp1_read_state_common(struct hubp *hubp) { struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); struct dcn_hubp_state *s = &hubp1->state; @@ -859,24 +859,6 @@ void hubp1_read_state(struct hubp *hubp) PRQ_EXPANSION_MODE, &rq_regs->prq_expansion_mode, MRQ_EXPANSION_MODE, &rq_regs->mrq_expansion_mode, CRQ_EXPANSION_MODE, &rq_regs->crq_expansion_mode); - REG_GET_8(DCHUBP_REQ_SIZE_CONFIG, - CHUNK_SIZE, &rq_regs->rq_regs_l.chunk_size, - MIN_CHUNK_SIZE, &rq_regs->rq_regs_l.min_chunk_size, - META_CHUNK_SIZE, &rq_regs->rq_regs_l.meta_chunk_size, - MIN_META_CHUNK_SIZE, &rq_regs->rq_regs_l.min_meta_chunk_size, - DPTE_GROUP_SIZE, &rq_regs->rq_regs_l.dpte_group_size, - MPTE_GROUP_SIZE, &rq_regs->rq_regs_l.mpte_group_size, - SWATH_HEIGHT, &rq_regs->rq_regs_l.swath_height, - PTE_ROW_HEIGHT_LINEAR, &rq_regs->rq_regs_l.pte_row_height_linear); - REG_GET_8(DCHUBP_REQ_SIZE_CONFIG_C, - CHUNK_SIZE_C, &rq_regs->rq_regs_c.chunk_size, - MIN_CHUNK_SIZE_C, &rq_regs->rq_regs_c.min_chunk_size, - META_CHUNK_SIZE_C, &rq_regs->rq_regs_c.meta_chunk_size, - MIN_META_CHUNK_SIZE_C, &rq_regs->rq_regs_c.min_meta_chunk_size, - DPTE_GROUP_SIZE_C, &rq_regs->rq_regs_c.dpte_group_size, - MPTE_GROUP_SIZE_C, &rq_regs->rq_regs_c.mpte_group_size, - SWATH_HEIGHT_C, &rq_regs->rq_regs_c.swath_height, - PTE_ROW_HEIGHT_LINEAR_C, &rq_regs->rq_regs_c.pte_row_height_linear); /* DLG - Per hubp */ REG_GET_2(BLANK_OFFSET_0, @@ -1030,8 +1012,38 @@ void hubp1_read_state(struct hubp *hubp) REG_GET_2(DCN_TTU_QOS_WM, QoS_LEVEL_LOW_WM, &s->qos_level_low_wm, QoS_LEVEL_HIGH_WM, &s->qos_level_high_wm); + } +void hubp1_read_state(struct hubp *hubp) +{ + struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); + struct dcn_hubp_state *s = &hubp1->state; + struct _vcs_dpi_display_rq_regs_st *rq_regs = &s->rq_regs; + + hubp1_read_state_common(hubp); + + REG_GET_8(DCHUBP_REQ_SIZE_CONFIG, + CHUNK_SIZE, &rq_regs->rq_regs_l.chunk_size, + MIN_CHUNK_SIZE, &rq_regs->rq_regs_l.min_chunk_size, + META_CHUNK_SIZE, &rq_regs->rq_regs_l.meta_chunk_size, + MIN_META_CHUNK_SIZE, &rq_regs->rq_regs_l.min_meta_chunk_size, + DPTE_GROUP_SIZE, &rq_regs->rq_regs_l.dpte_group_size, + MPTE_GROUP_SIZE, &rq_regs->rq_regs_l.mpte_group_size, + SWATH_HEIGHT, &rq_regs->rq_regs_l.swath_height, + PTE_ROW_HEIGHT_LINEAR, &rq_regs->rq_regs_l.pte_row_height_linear); + + REG_GET_8(DCHUBP_REQ_SIZE_CONFIG_C, + CHUNK_SIZE_C, &rq_regs->rq_regs_c.chunk_size, + MIN_CHUNK_SIZE_C, &rq_regs->rq_regs_c.min_chunk_size, + META_CHUNK_SIZE_C, &rq_regs->rq_regs_c.meta_chunk_size, + MIN_META_CHUNK_SIZE_C, &rq_regs->rq_regs_c.min_meta_chunk_size, + DPTE_GROUP_SIZE_C, &rq_regs->rq_regs_c.dpte_group_size, + MPTE_GROUP_SIZE_C, &rq_regs->rq_regs_c.mpte_group_size, + SWATH_HEIGHT_C, &rq_regs->rq_regs_c.swath_height, + PTE_ROW_HEIGHT_LINEAR_C, &rq_regs->rq_regs_c.pte_row_height_linear); + +} enum cursor_pitch hubp1_get_cursor_pitch(unsigned int pitch) { enum cursor_pitch hw_pitch; 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 31c8fdd3206c..cb20d10288c0 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.h @@ -125,8 +125,6 @@ SRI(DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, HUBPREQ, id),\ SRI(DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, HUBPREQ, id),\ SRI(DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, HUBPREQ, id),\ - SR(DCHUBBUB_SDPIF_FB_BASE),\ - SR(DCHUBBUB_SDPIF_FB_OFFSET),\ SRI(CURSOR_SETTINS, HUBPREQ, id), \ SRI(CURSOR_SURFACE_ADDRESS_HIGH, CURSOR, id), \ SRI(CURSOR_SURFACE_ADDRESS, CURSOR, id), \ @@ -226,14 +224,6 @@ uint32_t DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB; \ uint32_t DCN_VM_SYSTEM_APERTURE_LOW_ADDR; \ uint32_t DCN_VM_SYSTEM_APERTURE_HIGH_ADDR; \ - uint32_t DCHUBBUB_SDPIF_FB_BASE; \ - uint32_t DCHUBBUB_SDPIF_FB_OFFSET; \ - uint32_t DCN_VM_FB_LOCATION_TOP; \ - uint32_t DCN_VM_FB_LOCATION_BASE; \ - uint32_t DCN_VM_FB_OFFSET; \ - uint32_t DCN_VM_AGP_BASE; \ - uint32_t DCN_VM_AGP_BOT; \ - uint32_t DCN_VM_AGP_TOP; \ uint32_t CURSOR_SETTINS; \ uint32_t CURSOR_SETTINGS; \ uint32_t CURSOR_SURFACE_ADDRESS_HIGH; \ @@ -249,7 +239,8 @@ .field_name = reg_name ## __ ## field_name ## post_fix /* Mask/shift struct generation macro for all ASICs (including those with reduced functionality) */ -#define HUBP_MASK_SH_LIST_DCN_COMMON(mask_sh)\ +/*1.x, 2.x, and 3.x*/ +#define HUBP_MASK_SH_LIST_DCN_SHARE_COMMON(mask_sh)\ HUBP_SF(HUBP0_DCHUBP_CNTL, HUBP_BLANK_EN, mask_sh),\ HUBP_SF(HUBP0_DCHUBP_CNTL, HUBP_TTU_DISABLE, mask_sh),\ HUBP_SF(HUBP0_DCHUBP_CNTL, HUBP_UNDERFLOW_STATUS, mask_sh),\ @@ -265,7 +256,6 @@ HUBP_SF(HUBP0_DCSURF_ADDR_CONFIG, MAX_COMPRESSED_FRAGS, mask_sh),\ HUBP_SF(HUBP0_DCSURF_TILING_CONFIG, SW_MODE, mask_sh),\ HUBP_SF(HUBP0_DCSURF_TILING_CONFIG, META_LINEAR, mask_sh),\ - HUBP_SF(HUBP0_DCSURF_TILING_CONFIG, RB_ALIGNED, mask_sh),\ HUBP_SF(HUBP0_DCSURF_TILING_CONFIG, PIPE_ALIGNED, mask_sh),\ HUBP_SF(HUBPREQ0_DCSURF_SURFACE_PITCH, PITCH, mask_sh),\ HUBP_SF(HUBPREQ0_DCSURF_SURFACE_PITCH, META_PITCH, mask_sh),\ @@ -372,12 +362,17 @@ HUBP_SF(HUBPREQ0_DCN_SURF0_TTU_CNTL0, QoS_RAMP_DISABLE, mask_sh),\ HUBP_SF(HUBPREQ0_DCN_SURF0_TTU_CNTL1, REFCYC_PER_REQ_DELIVERY_PRE, mask_sh),\ HUBP_SF(HUBP0_HUBP_CLK_CNTL, HUBP_CLOCK_ENABLE, mask_sh) - -#define HUBP_MASK_SH_LIST_DCN(mask_sh)\ - HUBP_MASK_SH_LIST_DCN_COMMON(mask_sh),\ +/*2.x and 1.x only*/ +#define HUBP_MASK_SH_LIST_DCN_COMMON(mask_sh)\ + HUBP_MASK_SH_LIST_DCN_SHARE_COMMON(mask_sh),\ + HUBP_SF(HUBP0_DCSURF_TILING_CONFIG, RB_ALIGNED, mask_sh),\ HUBP_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG, MPTE_GROUP_SIZE, mask_sh),\ HUBP_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG_C, MPTE_GROUP_SIZE_C, mask_sh) +/*2.x and 1.x only*/ +#define HUBP_MASK_SH_LIST_DCN(mask_sh)\ + HUBP_MASK_SH_LIST_DCN_COMMON(mask_sh) + /* Mask/shift struct generation macro for ASICs with VM */ #define HUBP_MASK_SH_LIST_DCN_VM(mask_sh)\ HUBP_SF(HUBPREQ0_NOM_PARAMETERS_0, DST_Y_PER_PTE_ROW_NOM_L, mask_sh),\ @@ -412,8 +407,6 @@ HUBP_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, MC_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, mask_sh),\ HUBP_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, MC_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, mask_sh),\ HUBP_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, MC_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, mask_sh),\ - HUBP_SF(DCHUBBUB_SDPIF_FB_BASE, SDPIF_FB_BASE, mask_sh),\ - HUBP_SF(DCHUBBUB_SDPIF_FB_OFFSET, SDPIF_FB_OFFSET, mask_sh),\ HUBP_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, MC_VM_SYSTEM_APERTURE_DEFAULT_SYSTEM, mask_sh),\ HUBP_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, mask_sh),\ HUBP_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, mask_sh),\ @@ -434,7 +427,7 @@ HUBP_SF(CURSOR0_CURSOR_HOT_SPOT, CURSOR_HOT_SPOT_Y, mask_sh), \ HUBP_SF(CURSOR0_CURSOR_DST_OFFSET, CURSOR_DST_X_OFFSET, mask_sh) -#define DCN_HUBP_REG_FIELD_LIST(type) \ +#define DCN_HUBP_REG_FIELD_BASE_LIST(type) \ type HUBP_BLANK_EN;\ type HUBP_DISABLE;\ type HUBP_TTU_DISABLE;\ @@ -459,7 +452,6 @@ type ROTATION_ANGLE;\ type H_MIRROR_EN;\ type SURFACE_PIXEL_FORMAT;\ - type ALPHA_PLANE_EN;\ type SURFACE_FLIP_TYPE;\ type SURFACE_FLIP_MODE_FOR_STEREOSYNC;\ type SURFACE_FLIP_IN_STEREOSYNC;\ @@ -589,18 +581,6 @@ type MC_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB;\ type MC_VM_SYSTEM_APERTURE_LOW_ADDR;\ type MC_VM_SYSTEM_APERTURE_HIGH_ADDR;\ - type SDPIF_FB_TOP;\ - type SDPIF_FB_BASE;\ - type SDPIF_FB_OFFSET;\ - type SDPIF_AGP_BASE;\ - type SDPIF_AGP_BOT;\ - type SDPIF_AGP_TOP;\ - type FB_TOP;\ - type FB_BASE;\ - type FB_OFFSET;\ - type AGP_BASE;\ - type AGP_BOT;\ - type AGP_TOP;\ type DCN_VM_SYSTEM_APERTURE_DEFAULT_SYSTEM;\ type DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB;\ type DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB;\ @@ -632,6 +612,10 @@ type CURSOR_DST_X_OFFSET; \ type OUTPUT_FP +#define DCN_HUBP_REG_FIELD_LIST(type) \ + DCN_HUBP_REG_FIELD_BASE_LIST(type);\ + type ALPHA_PLANE_EN + struct dcn_mi_registers { HUBP_COMMON_REG_VARIABLE_LIST; }; @@ -677,7 +661,7 @@ void hubp1_program_surface_config( struct hubp *hubp, enum surface_pixel_format format, union dc_tiling_info *tiling_info, - union plane_size *plane_size, + struct plane_size *plane_size, enum dc_rotation_angle rotation, struct dc_plane_dcc_param *dcc, bool horizontal_mirror, @@ -699,7 +683,7 @@ void hubp1_program_pixel_format( void hubp1_program_size( struct hubp *hubp, enum surface_pixel_format format, - const union plane_size *plane_size, + const struct plane_size *plane_size, struct dc_plane_dcc_param *dcc); void hubp1_program_rotation( @@ -714,7 +698,7 @@ void hubp1_program_tiling( void hubp1_dcc_control(struct hubp *hubp, bool enable, - bool independent_64b_blks); + enum hubp_ind_block_size independent_64b_blks); #ifdef CONFIG_DRM_AMD_DC_DCN2_0 bool hubp1_program_surface_flip_and_addr( @@ -760,5 +744,6 @@ void hubp1_vready_workaround(struct hubp *hubp, struct _vcs_dpi_display_pipe_dest_params_st *pipe_dest); void hubp1_init(struct hubp *hubp); +void hubp1_read_state_common(struct hubp *hubp); #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 2118ea21d7e9..60123db7ba02 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 @@ -438,7 +438,7 @@ bool dcn10_did_underflow_occur(struct dc *dc, struct pipe_ctx *pipe_ctx) return false; } -static void enable_power_gating_plane( +static void dcn10_enable_power_gating_plane( struct dce_hwseq *hws, bool enable) { @@ -460,7 +460,7 @@ static void enable_power_gating_plane( REG_UPDATE(DOMAIN7_PG_CONFIG, DOMAIN7_POWER_FORCEON, force_on); } -static void disable_vga( +static void dcn10_disable_vga( struct dce_hwseq *hws) { unsigned int in_vga1_mode = 0; @@ -493,7 +493,7 @@ static void disable_vga( REG_UPDATE(VGA_TEST_CONTROL, VGA_TEST_RENDER_START, 1); } -static void dpp_pg_control( +static void dcn10_dpp_pg_control( struct dce_hwseq *hws, unsigned int dpp_inst, bool power_on) @@ -545,7 +545,7 @@ static void dpp_pg_control( } } -static void hubp_pg_control( +static void dcn10_hubp_pg_control( struct dce_hwseq *hws, unsigned int hubp_inst, bool power_on) @@ -605,8 +605,8 @@ static void power_on_plane( if (REG(DC_IP_REQUEST_CNTL)) { REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1); - dpp_pg_control(hws, plane_id, true); - hubp_pg_control(hws, plane_id, true); + hws->ctx->dc->hwss.dpp_pg_control(hws, plane_id, true); + hws->ctx->dc->hwss.hubp_pg_control(hws, plane_id, true); REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 0); DC_LOG_DEBUG( @@ -627,7 +627,7 @@ static void undo_DEGVIDCN10_253_wa(struct dc *dc) REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1); - hubp_pg_control(hws, 0, false); + dc->hwss.hubp_pg_control(hws, 0, false); REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 0); @@ -656,7 +656,7 @@ static void apply_DEGVIDCN10_253_wa(struct dc *dc) REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1); - hubp_pg_control(hws, 0, true); + dc->hwss.hubp_pg_control(hws, 0, true); REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 0); @@ -664,10 +664,23 @@ static void apply_DEGVIDCN10_253_wa(struct dc *dc) hws->wa_state.DEGVIDCN10_253_applied = true; } -static void bios_golden_init(struct dc *dc) +static void dcn10_bios_golden_init(struct dc *dc) { struct dc_bios *bp = dc->ctx->dc_bios; int i; + bool allow_self_fresh_force_enable = true; + + if (dc->res_pool->hubbub->funcs->is_allow_self_refresh_enabled) + allow_self_fresh_force_enable = + dc->res_pool->hubbub->funcs->is_allow_self_refresh_enabled(dc->res_pool->hubbub); + + + /* WA for making DF sleep when idle after resume from S0i3. + * DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE is set to 1 by + * command table, if DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE = 0 + * before calling command table and it changed to 1 after, + * it should be set back to 0. + */ /* initialize dcn global */ bp->funcs->enable_disp_power_gating(bp, @@ -678,6 +691,12 @@ static void bios_golden_init(struct dc *dc) bp->funcs->enable_disp_power_gating(bp, CONTROLLER_ID_D0 + i, ASIC_PIPE_DISABLE); } + + if (dc->res_pool->hubbub->funcs->allow_self_refresh_control) + if (allow_self_fresh_force_enable == false && + dc->res_pool->hubbub->funcs->is_allow_self_refresh_enabled(dc->res_pool->hubbub)) + dc->res_pool->hubbub->funcs->allow_self_refresh_control(dc->res_pool->hubbub, true); + } static void false_optc_underflow_wa( @@ -702,7 +721,8 @@ static void false_optc_underflow_wa( dc->hwss.wait_for_mpcc_disconnect(dc, dc->res_pool, old_pipe_ctx); } - tg->funcs->set_blank_data_double_buffer(tg, true); + if (tg->funcs->set_blank_data_double_buffer) + tg->funcs->set_blank_data_double_buffer(tg, true); if (tg->funcs->is_optc_underflow_occurred(tg) && !underflow) tg->funcs->clear_optc_underflow(tg); @@ -808,11 +828,23 @@ static void dcn10_reset_back_end_for_pipe( if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { /* DPMS may already disable */ if (!pipe_ctx->stream->dpms_off) - core_link_disable_stream(pipe_ctx, FREE_ACQUIRED_RESOURCE); - else if (pipe_ctx->stream_res.audio) { - dc->hwss.disable_audio_stream(pipe_ctx, FREE_ACQUIRED_RESOURCE); + core_link_disable_stream(pipe_ctx); + else if (pipe_ctx->stream_res.audio) + dc->hwss.disable_audio_stream(pipe_ctx); + + if (pipe_ctx->stream_res.audio) { + /*disable az_endpoint*/ + pipe_ctx->stream_res.audio->funcs->az_disable(pipe_ctx->stream_res.audio); + + /*free audio*/ + if (dc->caps.dynamic_audio == true) { + /*we have to dynamic arbitrate the audio endpoints*/ + /*we free the resource, need reset is_audio_acquired*/ + update_audio_usage(&dc->current_state->res_ctx, dc->res_pool, + pipe_ctx->stream_res.audio, false); + pipe_ctx->stream_res.audio = NULL; + } } - } /* by upper caller loop, parent pipe: pipe0, will be reset last. @@ -823,6 +855,9 @@ static void dcn10_reset_back_end_for_pipe( pipe_ctx->stream_res.tg->funcs->disable_crtc(pipe_ctx->stream_res.tg); pipe_ctx->stream_res.tg->funcs->enable_optc_clock(pipe_ctx->stream_res.tg, false); + if (pipe_ctx->stream_res.tg->funcs->set_drr) + pipe_ctx->stream_res.tg->funcs->set_drr( + pipe_ctx->stream_res.tg, NULL); } for (i = 0; i < dc->res_pool->pipe_count; i++) @@ -968,7 +1003,7 @@ void hwss1_plane_atomic_disconnect(struct dc *dc, struct pipe_ctx *pipe_ctx) dcn10_verify_allow_pstate_change_high(dc); } -static void plane_atomic_power_down(struct dc *dc, +static void dcn10_plane_atomic_power_down(struct dc *dc, struct dpp *dpp, struct hubp *hubp) { @@ -978,8 +1013,8 @@ static void plane_atomic_power_down(struct dc *dc, if (REG(DC_IP_REQUEST_CNTL)) { REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1); - dpp_pg_control(hws, dpp->inst, false); - hubp_pg_control(hws, hubp->inst, false); + dc->hwss.dpp_pg_control(hws, dpp->inst, false); + dc->hwss.hubp_pg_control(hws, hubp->inst, false); dpp->funcs->dpp_reset(dpp); REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 0); @@ -991,7 +1026,7 @@ static void plane_atomic_power_down(struct dc *dc, /* disable HW used by plane. * note: cannot disable until disconnect is complete */ -static void plane_atomic_disable(struct dc *dc, struct pipe_ctx *pipe_ctx) +static void dcn10_plane_atomic_disable(struct dc *dc, struct pipe_ctx *pipe_ctx) { struct hubp *hubp = pipe_ctx->plane_res.hubp; struct dpp *dpp = pipe_ctx->plane_res.dpp; @@ -1011,7 +1046,7 @@ static void plane_atomic_disable(struct dc *dc, struct pipe_ctx *pipe_ctx) hubp->power_gated = true; dc->optimized_required = false; /* We're powering off, no need to optimize */ - plane_atomic_power_down(dc, + dc->hwss.plane_atomic_power_down(dc, pipe_ctx->plane_res.dpp, pipe_ctx->plane_res.hubp); @@ -1030,7 +1065,7 @@ static void dcn10_disable_plane(struct dc *dc, struct pipe_ctx *pipe_ctx) if (!pipe_ctx->plane_res.hubp || pipe_ctx->plane_res.hubp->power_gated) return; - plane_atomic_disable(dc, pipe_ctx); + dc->hwss.plane_atomic_disable(dc, pipe_ctx); apply_DEGVIDCN10_253_wa(dc); @@ -1065,15 +1100,27 @@ static void dcn10_init_pipes(struct dc *dc, struct dc_state *context) * command table. */ if (tg->funcs->is_tg_enabled(tg)) { - tg->funcs->lock(tg); - tg->funcs->set_blank(tg, true); - hwss_wait_for_blank_complete(tg); + if (dc->hwss.init_blank != NULL) { + dc->hwss.init_blank(dc, tg); + tg->funcs->lock(tg); + } else { + tg->funcs->lock(tg); + tg->funcs->set_blank(tg, true); + hwss_wait_for_blank_complete(tg); + } } } - /* Cannot reset the MPC mux if seamless boot */ - if (!can_apply_seamless_boot) - dc->res_pool->mpc->funcs->mpc_init(dc->res_pool->mpc); + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; + + /* Cannot reset the MPC mux if seamless boot */ + if (pipe_ctx->stream != NULL && can_apply_seamless_boot) + continue; + + dc->res_pool->mpc->funcs->mpc_init_single_inst( + dc->res_pool->mpc, i); + } for (i = 0; i < dc->res_pool->pipe_count; i++) { struct timing_generator *tg = dc->res_pool->timing_generators[i]; @@ -1111,12 +1158,12 @@ static void dcn10_init_pipes(struct dc *dc, struct dc_state *context) dc->res_pool->opps[i]->mpcc_disconnect_pending[pipe_ctx->plane_res.mpcc_inst] = true; pipe_ctx->stream_res.opp = dc->res_pool->opps[i]; - hwss1_plane_atomic_disconnect(dc, pipe_ctx); + dc->hwss.plane_atomic_disconnect(dc, pipe_ctx); if (tg->funcs->is_tg_enabled(tg)) tg->funcs->unlock(tg); - dcn10_disable_plane(dc, pipe_ctx); + dc->hwss.disable_plane(dc, pipe_ctx); pipe_ctx->stream_res.tg = NULL; pipe_ctx->plane_res.hubp = NULL; @@ -1132,8 +1179,17 @@ static void dcn10_init_hw(struct dc *dc) struct dmcu *dmcu = dc->res_pool->dmcu; struct dce_hwseq *hws = dc->hwseq; struct dc_bios *dcb = dc->ctx->dc_bios; + struct resource_pool *res_pool = dc->res_pool; + + if (dc->clk_mgr && dc->clk_mgr->funcs->init_clocks) + dc->clk_mgr->funcs->init_clocks(dc->clk_mgr); + + // Initialize the dccg + if (dc->res_pool->dccg && dc->res_pool->dccg->funcs->dccg_init) + dc->res_pool->dccg->funcs->dccg_init(res_pool->dccg); if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { + REG_WRITE(REFCLK_CNTL, 0); REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, 1); REG_WRITE(DIO_MEM_PWR_CTRL, 0); @@ -1147,31 +1203,40 @@ static void dcn10_init_hw(struct dc *dc) REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0); } - enable_power_gating_plane(dc->hwseq, true); + //Enable ability to power gate / don't force power on permanently + dc->hwss.enable_power_gating_plane(hws, true); - /* end of FPGA. Below if real ASIC */ return; } - if (!dcb->funcs->is_accelerated_mode(dcb)) { - bool allow_self_fresh_force_enable = - hububu1_is_allow_self_refresh_enabled( - dc->res_pool->hubbub); + if (!dcb->funcs->is_accelerated_mode(dcb)) + dc->hwss.disable_vga(dc->hwseq); - bios_golden_init(dc); + dc->hwss.bios_golden_init(dc); + if (dc->ctx->dc_bios->fw_info_valid) { + res_pool->ref_clocks.xtalin_clock_inKhz = + dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency; - /* WA for making DF sleep when idle after resume from S0i3. - * DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE is set to 1 by - * command table, if DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE = 0 - * before calling command table and it changed to 1 after, - * it should be set back to 0. - */ - if (allow_self_fresh_force_enable == false && - hububu1_is_allow_self_refresh_enabled(dc->res_pool->hubbub)) - hubbub1_allow_self_refresh_control(dc->res_pool->hubbub, true); + if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { + if (res_pool->dccg && res_pool->hubbub) { - disable_vga(dc->hwseq); - } + (res_pool->dccg->funcs->get_dccg_ref_freq)(res_pool->dccg, + dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency, + &res_pool->ref_clocks.dccg_ref_clock_inKhz); + + (res_pool->hubbub->funcs->get_dchub_ref_freq)(res_pool->hubbub, + res_pool->ref_clocks.dccg_ref_clock_inKhz, + &res_pool->ref_clocks.dchub_ref_clock_inKhz); + } else { + // Not all ASICs have DCCG sw component + res_pool->ref_clocks.dccg_ref_clock_inKhz = + res_pool->ref_clocks.xtalin_clock_inKhz; + res_pool->ref_clocks.dchub_ref_clock_inKhz = + res_pool->ref_clocks.xtalin_clock_inKhz; + } + } + } else + ASSERT_CRITICAL(false); for (i = 0; i < dc->link_count; i++) { /* Power up AND update implementation according to the @@ -1188,6 +1253,13 @@ static void dcn10_init_hw(struct dc *dc) link->link_status.link_active = true; } + /* Power gate DSCs */ +#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT + for (i = 0; i < res_pool->res_cap->num_dsc; i++) + if (dc->hwss.dsc_pg_control != NULL) + dc->hwss.dsc_pg_control(hws, res_pool->dscs[i]->inst, false); +#endif + /* If taking control over from VBIOS, we may want to optimize our first * mode set, so we need to skip powering down pipes until we know which * pipes we want to use. @@ -1198,8 +1270,8 @@ static void dcn10_init_hw(struct dc *dc) dc->hwss.init_pipes(dc, dc->current_state); } - for (i = 0; i < dc->res_pool->audio_count; i++) { - struct audio *audio = dc->res_pool->audios[i]; + for (i = 0; i < res_pool->audio_count; i++) { + struct audio *audio = res_pool->audios[i]; audio->funcs->hw_init(audio); } @@ -1227,9 +1299,7 @@ static void dcn10_init_hw(struct dc *dc) REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0); } - enable_power_gating_plane(dc->hwseq, true); - - memset(&dc->clk_mgr->clks, 0, sizeof(dc->clk_mgr->clks)); + dc->hwss.enable_power_gating_plane(dc->hwseq, true); } static void dcn10_reset_hw_ctx_wrap( @@ -1366,6 +1436,34 @@ static bool dcn10_set_input_transfer_func(struct pipe_ctx *pipe_ctx, return result; } +#define MAX_NUM_HW_POINTS 0x200 + +static void log_tf(struct dc_context *ctx, + struct dc_transfer_func *tf, uint32_t hw_points_num) +{ + // DC_LOG_GAMMA is default logging of all hw points + // DC_LOG_ALL_GAMMA logs all points, not only hw points + // DC_LOG_ALL_TF_POINTS logs all channels of the tf + int i = 0; + + DC_LOGGER_INIT(ctx->logger); + DC_LOG_GAMMA("Gamma Correction TF"); + DC_LOG_ALL_GAMMA("Logging all tf points..."); + DC_LOG_ALL_TF_CHANNELS("Logging all channels..."); + + for (i = 0; i < hw_points_num; i++) { + DC_LOG_GAMMA("R\t%d\t%llu\n", i, tf->tf_pts.red[i].value); + DC_LOG_ALL_TF_CHANNELS("G\t%d\t%llu\n", i, tf->tf_pts.green[i].value); + DC_LOG_ALL_TF_CHANNELS("B\t%d\t%llu\n", i, tf->tf_pts.blue[i].value); + } + + for (i = hw_points_num; i < MAX_NUM_HW_POINTS; i++) { + DC_LOG_ALL_GAMMA("R\t%d\t%llu\n", i, tf->tf_pts.red[i].value); + DC_LOG_ALL_TF_CHANNELS("G\t%d\t%llu\n", i, tf->tf_pts.green[i].value); + DC_LOG_ALL_TF_CHANNELS("B\t%d\t%llu\n", i, tf->tf_pts.blue[i].value); + } +} + static bool dcn10_set_output_transfer_func(struct pipe_ctx *pipe_ctx, const struct dc_stream_state *stream) @@ -1394,6 +1492,13 @@ dcn10_set_output_transfer_func(struct pipe_ctx *pipe_ctx, } else dpp->funcs->dpp_program_regamma_pwl(dpp, NULL, OPP_REGAMMA_BYPASS); + if (stream != NULL && stream->ctx != NULL && + stream->out_transfer_func != NULL) { + log_tf(stream->ctx, + stream->out_transfer_func, + dpp->regamma_params.hw_points_num); + } + return true; } @@ -1786,7 +1891,7 @@ static void dcn10_enable_plane( } } -static void program_gamut_remap(struct pipe_ctx *pipe_ctx) +static void dcn10_program_gamut_remap(struct pipe_ctx *pipe_ctx) { int i = 0; struct dpp_grph_csc_adjustment adjust; @@ -1804,6 +1909,36 @@ static void program_gamut_remap(struct pipe_ctx *pipe_ctx) pipe_ctx->plane_res.dpp->funcs->dpp_set_gamut_remap(pipe_ctx->plane_res.dpp, &adjust); } + +static bool dcn10_is_rear_mpo_fix_required(struct pipe_ctx *pipe_ctx, enum dc_color_space colorspace) +{ + if (pipe_ctx->plane_state && pipe_ctx->plane_state->layer_index > 0 && is_rgb_cspace(colorspace)) { + if (pipe_ctx->top_pipe) { + struct pipe_ctx *top = pipe_ctx->top_pipe; + + while (top->top_pipe) + top = top->top_pipe; // Traverse to top pipe_ctx + if (top->plane_state && top->plane_state->layer_index == 0) + return true; // Front MPO plane not hidden + } + } + return false; +} + +static void dcn10_set_csc_adjustment_rgb_mpo_fix(struct pipe_ctx *pipe_ctx, uint16_t *matrix) +{ + // Override rear plane RGB bias to fix MPO brightness + uint16_t rgb_bias = matrix[3]; + + matrix[3] = 0; + matrix[7] = 0; + matrix[11] = 0; + pipe_ctx->plane_res.dpp->funcs->dpp_set_csc_adjustment(pipe_ctx->plane_res.dpp, matrix); + matrix[3] = rgb_bias; + matrix[7] = rgb_bias; + matrix[11] = rgb_bias; +} + static void dcn10_program_output_csc(struct dc *dc, struct pipe_ctx *pipe_ctx, enum dc_color_space colorspace, @@ -1811,8 +1946,25 @@ static void dcn10_program_output_csc(struct dc *dc, int opp_id) { if (pipe_ctx->stream->csc_color_matrix.enable_adjustment == true) { - if (pipe_ctx->plane_res.dpp->funcs->dpp_set_csc_adjustment != NULL) - pipe_ctx->plane_res.dpp->funcs->dpp_set_csc_adjustment(pipe_ctx->plane_res.dpp, matrix); + if (pipe_ctx->plane_res.dpp->funcs->dpp_set_csc_adjustment != NULL) { + + /* MPO is broken with RGB colorspaces when OCSC matrix + * brightness offset >= 0 on DCN1 due to OCSC before MPC + * Blending adds offsets from front + rear to rear plane + * + * Fix is to set RGB bias to 0 on rear plane, top plane + * black value pixels add offset instead of rear + front + */ + + int16_t rgb_bias = matrix[3]; + // matrix[3/7/11] are all the same offset value + + if (rgb_bias > 0 && dcn10_is_rear_mpo_fix_required(pipe_ctx, colorspace)) { + dcn10_set_csc_adjustment_rgb_mpo_fix(pipe_ctx, matrix); + } else { + pipe_ctx->plane_res.dpp->funcs->dpp_set_csc_adjustment(pipe_ctx->plane_res.dpp, matrix); + } + } } else { if (pipe_ctx->plane_res.dpp->funcs->dpp_set_csc_default != NULL) pipe_ctx->plane_res.dpp->funcs->dpp_set_csc_default(pipe_ctx->plane_res.dpp, colorspace); @@ -2132,7 +2284,7 @@ void update_dchubp_dpp( struct hubp *hubp = pipe_ctx->plane_res.hubp; struct dpp *dpp = pipe_ctx->plane_res.dpp; struct dc_plane_state *plane_state = pipe_ctx->plane_state; - union plane_size size = plane_state->plane_size; + struct plane_size size = plane_state->plane_size; unsigned int compat_level = 0; /* depends on DML calculation, DPP clock value may change dynamically */ @@ -2152,7 +2304,8 @@ void update_dchubp_dpp( dc->res_pool->dccg->funcs->update_dpp_dto( dc->res_pool->dccg, dpp->inst, - pipe_ctx->plane_res.bw.dppclk_khz); + pipe_ctx->plane_res.bw.dppclk_khz, + false); else dc->clk_mgr->clks.dppclk_khz = should_divided_by_2 ? dc->clk_mgr->clks.dispclk_khz / 2 : @@ -2178,7 +2331,7 @@ void update_dchubp_dpp( &pipe_ctx->ttu_regs); } - size.grph.surface_size = pipe_ctx->plane_res.scl_data.viewport; + size.surface_size = pipe_ctx->plane_res.scl_data.viewport; if (plane_state->update_flags.bits.full_update || plane_state->update_flags.bits.bpp_change) @@ -2216,7 +2369,7 @@ void update_dchubp_dpp( if (plane_state->update_flags.bits.full_update) { /*gamut remap*/ - program_gamut_remap(pipe_ctx); + dc->hwss.program_gamut_remap(pipe_ctx); dc->hwss.program_output_csc(dc, pipe_ctx, @@ -2388,7 +2541,7 @@ struct pipe_ctx *find_top_pipe_for_stream( if (pipe_ctx->stream != stream) continue; - if (!pipe_ctx->top_pipe) + if (!pipe_ctx->top_pipe && !pipe_ctx->prev_odm_pipe) return pipe_ctx; } return NULL; @@ -2453,7 +2606,7 @@ static void dcn10_apply_ctx_for_surface( if (old_pipe_ctx->stream_res.tg == tg && old_pipe_ctx->plane_res.hubp && old_pipe_ctx->plane_res.hubp->opp_id != OPP_ID_INVALID) - dcn10_disable_plane(dc, old_pipe_ctx); + dc->hwss.disable_plane(dc, old_pipe_ctx); } if ((!pipe_ctx->plane_state || @@ -2501,7 +2654,7 @@ static void dcn10_apply_ctx_for_surface( for (i = 0; i < dc->res_pool->pipe_count; i++) if (removed_pipe[i]) - dcn10_disable_plane(dc, &dc->current_state->res_ctx.pipe_ctx[i]); + dc->hwss.disable_plane(dc, &dc->current_state->res_ctx.pipe_ctx[i]); for (i = 0; i < dc->res_pool->pipe_count; i++) if (removed_pipe[i]) { @@ -2593,8 +2746,9 @@ static void dcn10_optimize_bandwidth( dcn10_verify_allow_pstate_change_high(dc); } -static void set_drr(struct pipe_ctx **pipe_ctx, - int num_pipes, int vmin, int vmax) +static void dcn10_set_drr(struct pipe_ctx **pipe_ctx, + int num_pipes, unsigned int vmin, unsigned int vmax, + unsigned int vmid, unsigned int vmid_frame_number) { int i = 0; struct drr_params params = {0}; @@ -2603,6 +2757,8 @@ static void set_drr(struct pipe_ctx **pipe_ctx, params.vertical_total_max = vmax; params.vertical_total_min = vmin; + params.vertical_total_mid = vmid; + params.vertical_total_mid_frame_num = vmid_frame_number; /* TODO: If multiple pipes are to be supported, you need * some GSL stuff. Static screen triggers may be programmed differently @@ -2618,7 +2774,7 @@ static void set_drr(struct pipe_ctx **pipe_ctx, } } -static void get_position(struct pipe_ctx **pipe_ctx, +static void dcn10_get_position(struct pipe_ctx **pipe_ctx, int num_pipes, struct crtc_position *position) { @@ -2630,7 +2786,7 @@ static void get_position(struct pipe_ctx **pipe_ctx, pipe_ctx[i]->stream_res.tg->funcs->get_position(pipe_ctx[i]->stream_res.tg, position); } -static void set_static_screen_control(struct pipe_ctx **pipe_ctx, +static void dcn10_set_static_screen_control(struct pipe_ctx **pipe_ctx, int num_pipes, const struct dc_static_screen_events *events) { unsigned int i; @@ -2692,6 +2848,13 @@ static void dcn10_setup_stereo(struct pipe_ctx *pipe_ctx, struct dc *dc) dcn10_config_stereo_parameters(stream, &flags); + if (stream->timing.timing_3d_format == TIMING_3D_FORMAT_SIDEBAND_FA) { + if (!dc_set_generic_gpio_for_stereo(true, dc->ctx->gpio_service)) + dc_set_generic_gpio_for_stereo(false, dc->ctx->gpio_service); + } else { + dc_set_generic_gpio_for_stereo(false, dc->ctx->gpio_service); + } + pipe_ctx->stream_res.opp->funcs->opp_program_stereo( pipe_ctx->stream_res.opp, flags.PROGRAM_STEREO == 1 ? true:false, @@ -2782,14 +2945,10 @@ static void dcn10_update_pending_status(struct pipe_ctx *pipe_ctx) static void dcn10_update_dchub(struct dce_hwseq *hws, struct dchub_init_data *dh_data) { - if (hws->ctx->dc->res_pool->hubbub != NULL) { - struct hubp *hubp = hws->ctx->dc->res_pool->hubps[0]; + struct hubbub *hubbub = hws->ctx->dc->res_pool->hubbub; - if (hubp->funcs->hubp_update_dchub) - hubp->funcs->hubp_update_dchub(hubp, dh_data); - else - hubbub1_update_dchub(hws->ctx->dc->res_pool->hubbub, dh_data); - } + /* In DCN, this programming sequence is owned by the hubbub */ + hubbub->funcs->update_dchub(hubbub, dh_data); } static void dcn10_set_cursor_position(struct pipe_ctx *pipe_ctx) @@ -2820,6 +2979,40 @@ static void dcn10_set_cursor_position(struct pipe_ctx *pipe_ctx) == PLN_ADDR_TYPE_VIDEO_PROGRESSIVE) pos_cpy.enable = false; + // Swap axis and mirror horizontally + if (param.rotation == ROTATION_ANGLE_90) { + uint32_t temp_x = pos_cpy.x; + pos_cpy.x = pipe_ctx->plane_res.scl_data.viewport.width - + (pos_cpy.y - pipe_ctx->plane_res.scl_data.viewport.x) + pipe_ctx->plane_res.scl_data.viewport.x; + pos_cpy.y = temp_x; + } + // Swap axis and mirror vertically + else if (param.rotation == ROTATION_ANGLE_270) { + uint32_t temp_y = pos_cpy.y; + if (pos_cpy.x > pipe_ctx->plane_res.scl_data.viewport.height) { + pos_cpy.x = pos_cpy.x - pipe_ctx->plane_res.scl_data.viewport.height; + pos_cpy.y = pipe_ctx->plane_res.scl_data.viewport.height - pos_cpy.x; + } else { + pos_cpy.y = 2 * pipe_ctx->plane_res.scl_data.viewport.height - pos_cpy.x; + } + pos_cpy.x = temp_y; + } + // Mirror horizontally and vertically + else if (param.rotation == ROTATION_ANGLE_180) { + if (pos_cpy.x >= pipe_ctx->plane_res.scl_data.viewport.width + pipe_ctx->plane_res.scl_data.viewport.x) { + pos_cpy.x = 2 * pipe_ctx->plane_res.scl_data.viewport.width + - pos_cpy.x + 2 * pipe_ctx->plane_res.scl_data.viewport.x; + } else { + uint32_t temp_x = pos_cpy.x; + pos_cpy.x = 2 * pipe_ctx->plane_res.scl_data.viewport.x - pos_cpy.x; + if (temp_x >= pipe_ctx->plane_res.scl_data.viewport.x + (int)hubp->curs_attr.width + || pos_cpy.x <= (int)hubp->curs_attr.width + pipe_ctx->plane_state->src_rect.x) { + pos_cpy.x = temp_x + pipe_ctx->plane_res.scl_data.viewport.width; + } + } + pos_cpy.y = pipe_ctx->plane_res.scl_data.viewport.height - pos_cpy.y; + } + hubp->funcs->set_cursor_position(hubp, &pos_cpy, ¶m); dpp->funcs->set_cursor_position(dpp, &pos_cpy, ¶m, hubp->curs_attr.width, hubp->curs_attr.height); } @@ -2831,7 +3024,7 @@ static void dcn10_set_cursor_attribute(struct pipe_ctx *pipe_ctx) pipe_ctx->plane_res.hubp->funcs->set_cursor_attributes( pipe_ctx->plane_res.hubp, attributes); pipe_ctx->plane_res.dpp->funcs->set_cursor_attributes( - pipe_ctx->plane_res.dpp, attributes->color_format); + pipe_ctx->plane_res.dpp, attributes); } static void dcn10_set_cursor_sdr_white_level(struct pipe_ctx *pipe_ctx) @@ -3062,9 +3255,59 @@ static void dcn10_send_immediate_sdp_message(struct pipe_ctx *pipe_ctx, sdp_message_size); } } +static enum dc_status dcn10_set_clock(struct dc *dc, + enum dc_clock_type clock_type, + uint32_t clk_khz, + uint32_t stepping) +{ + struct dc_state *context = dc->current_state; + struct dc_clock_config clock_cfg = {0}; + struct dc_clocks *current_clocks = &context->bw_ctx.bw.dcn.clk; + + if (dc->clk_mgr && dc->clk_mgr->funcs->get_clock) + dc->clk_mgr->funcs->get_clock(dc->clk_mgr, + context, clock_type, &clock_cfg); + + if (!dc->clk_mgr->funcs->get_clock) + return DC_FAIL_UNSUPPORTED_1; + + if (clk_khz > clock_cfg.max_clock_khz) + return DC_FAIL_CLK_EXCEED_MAX; + + if (clk_khz < clock_cfg.min_clock_khz) + return DC_FAIL_CLK_BELOW_MIN; + + if (clk_khz < clock_cfg.bw_requirequired_clock_khz) + return DC_FAIL_CLK_BELOW_CFG_REQUIRED; + + /*update internal request clock for update clock use*/ + if (clock_type == DC_CLOCK_TYPE_DISPCLK) + current_clocks->dispclk_khz = clk_khz; + else if (clock_type == DC_CLOCK_TYPE_DPPCLK) + current_clocks->dppclk_khz = clk_khz; + else + return DC_ERROR_UNEXPECTED; + + if (dc->clk_mgr && dc->clk_mgr->funcs->update_clocks) + dc->clk_mgr->funcs->update_clocks(dc->clk_mgr, + context, true); + return DC_OK; + +} + +static void dcn10_get_clock(struct dc *dc, + enum dc_clock_type clock_type, + struct dc_clock_config *clock_cfg) +{ + struct dc_state *context = dc->current_state; + + if (dc->clk_mgr && dc->clk_mgr->funcs->get_clock) + dc->clk_mgr->funcs->get_clock(dc->clk_mgr, context, clock_type, clock_cfg); + +} static const struct hw_sequencer_funcs dcn10_funcs = { - .program_gamut_remap = program_gamut_remap, + .program_gamut_remap = dcn10_program_gamut_remap, .init_hw = dcn10_init_hw, .init_pipes = dcn10_init_pipes, .apply_ctx_to_hw = dce110_apply_ctx_to_hw, @@ -3097,18 +3340,18 @@ static const struct hw_sequencer_funcs dcn10_funcs = { .optimize_bandwidth = dcn10_optimize_bandwidth, .reset_hw_ctx_wrap = dcn10_reset_hw_ctx_wrap, .enable_stream_timing = dcn10_enable_stream_timing, - .set_drr = set_drr, - .get_position = get_position, - .set_static_screen_control = set_static_screen_control, + .set_drr = dcn10_set_drr, + .get_position = dcn10_get_position, + .set_static_screen_control = dcn10_set_static_screen_control, .setup_stereo = dcn10_setup_stereo, .set_avmute = dce110_set_avmute, .log_hw_state = dcn10_log_hw_state, .get_hw_state = dcn10_get_hw_state, .clear_status_bits = dcn10_clear_status_bits, .wait_for_mpcc_disconnect = dcn10_wait_for_mpcc_disconnect, - .edp_backlight_control = hwss_edp_backlight_control, - .edp_power_control = hwss_edp_power_control, - .edp_wait_for_hpd_ready = hwss_edp_wait_for_hpd_ready, + .edp_backlight_control = dce110_edp_backlight_control, + .edp_power_control = dce110_edp_power_control, + .edp_wait_for_hpd_ready = dce110_edp_wait_for_hpd_ready, .set_cursor_position = dcn10_set_cursor_position, .set_cursor_attribute = dcn10_set_cursor_attribute, .set_cursor_sdr_white_level = dcn10_set_cursor_sdr_white_level, @@ -3116,7 +3359,18 @@ static const struct hw_sequencer_funcs dcn10_funcs = { .enable_stream_gating = NULL, .setup_periodic_interrupt = dcn10_setup_periodic_interrupt, .setup_vupdate_interrupt = dcn10_setup_vupdate_interrupt, - .did_underflow_occur = dcn10_did_underflow_occur + .set_clock = dcn10_set_clock, + .get_clock = dcn10_get_clock, + .did_underflow_occur = dcn10_did_underflow_occur, + .init_blank = NULL, + .disable_vga = dcn10_disable_vga, + .bios_golden_init = dcn10_bios_golden_init, + .plane_atomic_disable = dcn10_plane_atomic_disable, + .plane_atomic_power_down = dcn10_plane_atomic_power_down, + .enable_power_gating_plane = dcn10_enable_power_gating_plane, + .dpp_pg_control = dcn10_dpp_pg_control, + .hubp_pg_control = dcn10_hubp_pg_control, + .dsc_pg_control = NULL, }; 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 6e47444109d7..7f4766e45dff 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 @@ -45,7 +45,7 @@ #include "dcn10_cm_common.h" #include "clk_mgr.h" -static unsigned int snprintf_count(char *pBuf, unsigned int bufSize, char *fmt, ...) +unsigned int snprintf_count(char *pBuf, unsigned int bufSize, char *fmt, ...) { unsigned int ret_vsnprintf; unsigned int 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 549d423a01f6..1a37c90e9d43 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 @@ -89,6 +89,7 @@ static const struct link_encoder_funcs dcn10_lnk_enc_funcs = { .disable_hpd = dcn10_link_encoder_disable_hpd, .is_dig_enabled = dcn10_is_dig_enabled, .get_dig_frontend = dcn10_get_dig_frontend, + .get_dig_mode = dcn10_get_dig_mode, .destroy = dcn10_link_encoder_destroy }; @@ -446,6 +447,46 @@ static uint8_t get_frontend_source( } } +unsigned int dcn10_get_dig_frontend(struct link_encoder *enc) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + int32_t value; + enum engine_id result; + + REG_GET(DIG_BE_CNTL, DIG_FE_SOURCE_SELECT, &value); + + switch (value) { + case DCN10_DIG_FE_SOURCE_SELECT_DIGA: + result = ENGINE_ID_DIGA; + break; + case DCN10_DIG_FE_SOURCE_SELECT_DIGB: + result = ENGINE_ID_DIGB; + break; + case DCN10_DIG_FE_SOURCE_SELECT_DIGC: + result = ENGINE_ID_DIGC; + break; + case DCN10_DIG_FE_SOURCE_SELECT_DIGD: + result = ENGINE_ID_DIGD; + break; + case DCN10_DIG_FE_SOURCE_SELECT_DIGE: + result = ENGINE_ID_DIGE; + break; + case DCN10_DIG_FE_SOURCE_SELECT_DIGF: + result = ENGINE_ID_DIGF; + break; + case DCN10_DIG_FE_SOURCE_SELECT_DIGG: + result = ENGINE_ID_DIGG; + break; + default: + // invalid source select DIG + ASSERT(false); + result = ENGINE_ID_UNKNOWN; + } + + return result; + +} + void enc1_configure_encoder( struct dcn10_link_encoder *enc10, const struct dc_link_settings *link_settings) @@ -501,15 +542,6 @@ bool dcn10_is_dig_enabled(struct link_encoder *enc) return value; } -unsigned int dcn10_get_dig_frontend(struct link_encoder *enc) -{ - struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - uint32_t value; - - REG_GET(DIG_BE_CNTL, DIG_FE_SOURCE_SELECT, &value); - return value; -} - static void link_encoder_disable(struct dcn10_link_encoder *enc10) { /* reset training pattern */ @@ -1366,3 +1398,25 @@ void dcn10_aux_initialize(struct dcn10_link_encoder *enc10) AUX_REG_UPDATE(AUX_DPHY_RX_CONTROL0, AUX_RX_RECEIVE_WINDOW, 0); } + +enum signal_type dcn10_get_dig_mode( + struct link_encoder *enc) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + uint32_t value; + REG_GET(DIG_BE_CNTL, DIG_MODE, &value); + switch (value) { + case 1: + return SIGNAL_TYPE_DISPLAY_PORT; + case 2: + return SIGNAL_TYPE_DVI_SINGLE_LINK; + case 3: + return SIGNAL_TYPE_HDMI_TYPE_A; + case 5: + return SIGNAL_TYPE_DISPLAY_PORT_MST; + default: + return SIGNAL_TYPE_NONE; + } + return SIGNAL_TYPE_NONE; +} + 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 33b2af1a181c..8bf5f0f2301d 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 @@ -337,6 +337,7 @@ struct dcn10_link_enc_registers { type RDPCS_TX_FIFO_ERROR_MASK;\ type RDPCS_DPALT_DISABLE_TOGGLE_MASK;\ type RDPCS_DPALT_4LANE_TOGGLE_MASK;\ + type RDPCS_PHY_DPALT_DISABLE;\ type RDPCS_PHY_DPALT_DISABLE_ACK;\ type RDPCS_PHY_DP_MPLLB_V2I;\ type RDPCS_PHY_DP_MPLLB_FREQ_VCO;\ @@ -514,4 +515,6 @@ unsigned int dcn10_get_dig_frontend(struct link_encoder *enc); void dcn10_aux_initialize(struct dcn10_link_encoder *enc10); +enum signal_type dcn10_get_dig_mode( + struct link_encoder *enc); #endif /* __DC_LINK_ENCODER__DCN10_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c index 0bca011ed7c9..8b2f29f6dabd 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c @@ -211,7 +211,7 @@ struct mpcc *mpc1_insert_plane( } else { new_mpcc->mpcc_bot = NULL; REG_SET(MPCC_BOT_SEL[mpcc_id], 0, MPCC_BOT_SEL, 0xf); - REG_UPDATE(MPCC_CONTROL[mpcc_id], MPCC_MODE, MPCC_BLEND_MODE_TOP_LAYER_PASSTHROUGH); + REG_UPDATE(MPCC_CONTROL[mpcc_id], MPCC_MODE, MPCC_BLEND_MODE_TOP_LAYER_ONLY); } REG_SET(MPCC_TOP_SEL[mpcc_id], 0, MPCC_TOP_SEL, dpp_id); REG_SET(MPCC_OPP_ID[mpcc_id], 0, MPCC_OPP_ID, tree->opp_id); @@ -364,6 +364,24 @@ void mpc1_mpc_init(struct mpc *mpc) } } +void mpc1_mpc_init_single_inst(struct mpc *mpc, unsigned int mpcc_id) +{ + struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc); + int opp_id; + + REG_GET(MPCC_OPP_ID[mpcc_id], MPCC_OPP_ID, &opp_id); + + REG_SET(MPCC_TOP_SEL[mpcc_id], 0, MPCC_TOP_SEL, 0xf); + REG_SET(MPCC_BOT_SEL[mpcc_id], 0, MPCC_BOT_SEL, 0xf); + REG_SET(MPCC_OPP_ID[mpcc_id], 0, MPCC_OPP_ID, 0xf); + + mpc1_init_mpcc(&(mpc->mpcc_array[mpcc_id]), mpcc_id); + + if (opp_id < MAX_OPP && REG(MUX[opp_id])) + REG_UPDATE(MUX[opp_id], MPC_OUT_MUX, 0xf); +} + + void mpc1_init_mpcc_list_from_hw( struct mpc *mpc, struct mpc_tree *tree) @@ -433,6 +451,7 @@ static const struct mpc_funcs dcn10_mpc_funcs = { .insert_plane = mpc1_insert_plane, .remove_mpcc = mpc1_remove_mpcc, .mpc_init = mpc1_mpc_init, + .mpc_init_single_inst = mpc1_mpc_init_single_inst, .get_mpcc_for_dpp = mpc1_get_mpcc_for_dpp, .wait_for_idle = mpc1_assert_idle_mpcc, .assert_mpcc_idle_before_connect = mpc1_assert_mpcc_idle_before_connect, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h index d3d16c4cbea3..962a68e322ee 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h @@ -149,6 +149,10 @@ void mpc1_remove_mpcc( void mpc1_mpc_init( struct mpc *mpc); +void mpc1_mpc_init_single_inst( + struct mpc *mpc, + unsigned int mpcc_id); + void mpc1_assert_idle_mpcc( struct mpc *mpc, int id); 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 a546c2bc9129..e74a07d03fde 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c @@ -154,7 +154,7 @@ void optc1_program_timing( uint32_t h_sync_polarity, v_sync_polarity; uint32_t start_point = 0; uint32_t field_num = 0; - uint32_t h_div_2; + enum h_timing_div_mode h_div = H_TIMING_NO_DIV; struct optc *optc1 = DCN10TG_FROM_TG(optc); @@ -285,10 +285,11 @@ void optc1_program_timing( * of stereo handled in explicit call */ - h_div_2 = optc1_is_two_pixels_per_containter(&patched_crtc_timing); - REG_UPDATE(OTG_H_TIMING_CNTL, - OTG_H_TIMING_DIV_BY2, h_div_2 || optc1->comb_opp_id != 0xf); + if (optc1_is_two_pixels_per_containter(&patched_crtc_timing) || optc1->opp_count == 2) + h_div = H_TIMING_DIV_BY2; + REG_UPDATE(OTG_H_TIMING_CNTL, + OTG_H_TIMING_DIV_BY2, h_div); } void optc1_set_vtg_params(struct timing_generator *optc, @@ -824,6 +825,9 @@ void optc1_program_manual_trigger(struct timing_generator *optc) REG_SET(OTG_MANUAL_FLOW_CONTROL, 0, MANUAL_FLOW_CONTROL, 1); + + REG_SET(OTG_MANUAL_FLOW_CONTROL, 0, + MANUAL_FLOW_CONTROL, 0); } @@ -846,6 +850,18 @@ void optc1_set_drr( params->vertical_total_max > 0 && params->vertical_total_min > 0) { + if (params->vertical_total_mid != 0) { + + REG_SET(OTG_V_TOTAL_MID, 0, + OTG_V_TOTAL_MID, params->vertical_total_mid - 1); + + REG_UPDATE_2(OTG_V_TOTAL_CONTROL, + OTG_VTOTAL_MID_REPLACING_MAX_EN, 1, + OTG_VTOTAL_MID_FRAME_NUM, + (uint8_t)params->vertical_total_mid_frame_num); + + } + REG_SET(OTG_V_TOTAL_MAX, 0, OTG_V_TOTAL_MAX, params->vertical_total_max - 1); @@ -1513,7 +1529,6 @@ void dcn10_timing_generator_init(struct optc *optc1) optc1->min_v_blank_interlace = 5; optc1->min_h_sync_width = 8; optc1->min_v_sync_width = 1; - optc1->comb_opp_id = 0xf; } #ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h index 02599eb92ca6..83575599672e 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h @@ -54,6 +54,7 @@ SRI(OTG_3D_STRUCTURE_CONTROL, OTG, inst),\ SRI(OTG_STEREO_STATUS, OTG, inst),\ SRI(OTG_V_TOTAL_MAX, OTG, inst),\ + SRI(OTG_V_TOTAL_MID, OTG, inst),\ SRI(OTG_V_TOTAL_MIN, OTG, inst),\ SRI(OTG_V_TOTAL_CONTROL, OTG, inst),\ SRI(OTG_TRIGA_CNTL, OTG, inst),\ @@ -125,6 +126,7 @@ struct dcn_optc_registers { uint32_t OTG_3D_STRUCTURE_CONTROL; uint32_t OTG_STEREO_STATUS; uint32_t OTG_V_TOTAL_MAX; + uint32_t OTG_V_TOTAL_MID; uint32_t OTG_V_TOTAL_MIN; uint32_t OTG_V_TOTAL_CONTROL; uint32_t OTG_TRIGA_CNTL; @@ -214,12 +216,15 @@ struct dcn_optc_registers { SF(OTG0_OTG_3D_STRUCTURE_CONTROL, OTG_3D_STRUCTURE_V_UPDATE_MODE, mask_sh),\ SF(OTG0_OTG_3D_STRUCTURE_CONTROL, OTG_3D_STRUCTURE_STEREO_SEL_OVR, mask_sh),\ SF(OTG0_OTG_V_TOTAL_MAX, OTG_V_TOTAL_MAX, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_MID, OTG_V_TOTAL_MID, mask_sh),\ SF(OTG0_OTG_V_TOTAL_MIN, OTG_V_TOTAL_MIN, mask_sh),\ SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_V_TOTAL_MIN_SEL, mask_sh),\ SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_V_TOTAL_MAX_SEL, mask_sh),\ SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_FORCE_LOCK_ON_EVENT, mask_sh),\ SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_SET_V_TOTAL_MIN_MASK_EN, mask_sh),\ SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_SET_V_TOTAL_MIN_MASK, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_VTOTAL_MID_REPLACING_MAX_EN, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_VTOTAL_MID_FRAME_NUM, mask_sh),\ SF(OTG0_OTG_FORCE_COUNT_NOW_CNTL, OTG_FORCE_COUNT_NOW_CLEAR, mask_sh),\ SF(OTG0_OTG_FORCE_COUNT_NOW_CNTL, OTG_FORCE_COUNT_NOW_MODE, mask_sh),\ SF(OTG0_OTG_FORCE_COUNT_NOW_CNTL, OTG_FORCE_COUNT_NOW_OCCURRED, mask_sh),\ @@ -348,9 +353,12 @@ struct dcn_optc_registers { type OTG_3D_STRUCTURE_V_UPDATE_MODE;\ type OTG_3D_STRUCTURE_STEREO_SEL_OVR;\ type OTG_V_TOTAL_MAX;\ + type OTG_V_TOTAL_MID;\ type OTG_V_TOTAL_MIN;\ type OTG_V_TOTAL_MIN_SEL;\ type OTG_V_TOTAL_MAX_SEL;\ + type OTG_VTOTAL_MID_REPLACING_MAX_EN;\ + type OTG_VTOTAL_MID_FRAME_NUM;\ type OTG_FORCE_LOCK_ON_EVENT;\ type OTG_SET_V_TOTAL_MIN_MASK_EN;\ type OTG_SET_V_TOTAL_MIN_MASK;\ @@ -494,7 +502,7 @@ struct optc { const struct dcn_optc_shift *tg_shift; const struct dcn_optc_mask *tg_mask; - int comb_opp_id; + int opp_count; uint32_t max_h_total; uint32_t max_v_total; @@ -539,6 +547,10 @@ struct dcn_otg_state { void optc1_read_otg_state(struct optc *optc1, struct dcn_otg_state *s); +bool optc1_is_matching_timing( + struct timing_generator *tg, + const struct dc_crtc_timing *otg_timing); + bool optc1_validate_timing( struct timing_generator *optc, const struct dc_crtc_timing *timing); 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 a12530a3ab9c..59305e411a66 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -270,7 +270,7 @@ static const struct dce_audio_shift audio_shift = { DCE120_AUD_COMMON_MASK_SH_LIST(__SHIFT) }; -static const struct dce_aduio_mask audio_mask = { +static const struct dce_audio_mask audio_mask = { DCE120_AUD_COMMON_MASK_SH_LIST(_MASK) }; @@ -1416,6 +1416,14 @@ static bool construct( pool->base.pp_smu = dcn10_pp_smu_create(ctx); + /* + * Right now SMU/PPLIB and DAL all have the AZ D3 force PME notification * + * implemented. So AZ D3 should work.For issue 197007. * + */ + if (pool->base.pp_smu != NULL + && pool->base.pp_smu->rv_funcs.set_pme_wa_enable != NULL) + dc->debug.az_endpoint_mute_only = false; + if (!dc->debug.disable_pplib_clock_request) dcn_bw_update_from_pplib(dc); dcn_bw_sync_calcs_and_dml(dc); @@ -1562,6 +1570,7 @@ struct resource_pool *dcn10_create_resource_pool( if (construct(init_data->num_virtual_links, dc, pool)) return &pool->base; + kfree(pool); BREAK_TO_DEBUGGER(); return NULL; } 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 b9ffbf6b58ff..9aa258f3550b 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 @@ -512,11 +512,12 @@ void enc1_stream_encoder_hdmi_set_stream_attribute( enc1_stream_encoder_set_stream_attribute_helper(enc1, crtc_timing); /* setup HDMI engine */ - REG_UPDATE_5(HDMI_CONTROL, + REG_UPDATE_6(HDMI_CONTROL, HDMI_PACKET_GEN_VERSION, 1, HDMI_KEEPOUT_MODE, 1, HDMI_DEEP_COLOR_ENABLE, 0, HDMI_DATA_SCRAMBLE_EN, 0, + HDMI_NO_EXTRA_NULL_PACKET_FILLED, 1, HDMI_CLOCK_CHANNEL_RATE, 0); @@ -1003,6 +1004,19 @@ void enc1_stream_encoder_set_avmute( REG_UPDATE(HDMI_GC, HDMI_GC_AVMUTE, value); } +void enc1_reset_hdmi_stream_attribute( + struct stream_encoder *enc) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + REG_UPDATE_5(HDMI_CONTROL, + HDMI_PACKET_GEN_VERSION, 1, + HDMI_KEEPOUT_MODE, 1, + HDMI_DEEP_COLOR_ENABLE, 0, + HDMI_DATA_SCRAMBLE_EN, 0, + HDMI_CLOCK_CHANNEL_RATE, 0); +} + #define DP_SEC_AUD_N__DP_SEC_AUD_N__DEFAULT 0x8000 #define DP_SEC_TIMESTAMP__DP_SEC_TIMESTAMP_MODE__AUTO_CALC 1 @@ -1196,13 +1210,13 @@ static union audio_cea_channels speakers_to_channels( void get_audio_clock_info( enum dc_color_depth color_depth, - uint32_t crtc_pixel_clock_in_khz, - uint32_t actual_pixel_clock_in_khz, + uint32_t crtc_pixel_clock_100Hz, + uint32_t actual_pixel_clock_100Hz, struct audio_clock_info *audio_clock_info) { const struct audio_clock_info *clock_info; uint32_t index; - uint32_t crtc_pixel_clock_in_10khz = crtc_pixel_clock_in_khz / 10; + uint32_t crtc_pixel_clock_in_10khz = crtc_pixel_clock_100Hz / 100; uint32_t audio_array_size; switch (color_depth) { @@ -1239,16 +1253,16 @@ void get_audio_clock_info( } /* not found */ - if (actual_pixel_clock_in_khz == 0) - actual_pixel_clock_in_khz = crtc_pixel_clock_in_khz; + if (actual_pixel_clock_100Hz == 0) + actual_pixel_clock_100Hz = crtc_pixel_clock_100Hz; /* See HDMI spec the table entry under * pixel clock of "Other". */ audio_clock_info->pixel_clock_in_10khz = - actual_pixel_clock_in_khz / 10; - audio_clock_info->cts_32khz = actual_pixel_clock_in_khz; - audio_clock_info->cts_44khz = actual_pixel_clock_in_khz; - audio_clock_info->cts_48khz = actual_pixel_clock_in_khz; + actual_pixel_clock_100Hz / 100; + audio_clock_info->cts_32khz = actual_pixel_clock_100Hz / 10; + audio_clock_info->cts_44khz = actual_pixel_clock_100Hz / 10; + audio_clock_info->cts_48khz = actual_pixel_clock_100Hz / 10; audio_clock_info->n_32khz = 4096; audio_clock_info->n_44khz = 6272; @@ -1308,14 +1322,14 @@ static void enc1_se_setup_hdmi_audio( /* Program audio clock sample/regeneration parameters */ get_audio_clock_info(crtc_info->color_depth, - crtc_info->requested_pixel_clock, - crtc_info->calculated_pixel_clock, + crtc_info->requested_pixel_clock_100Hz, + crtc_info->calculated_pixel_clock_100Hz, &audio_clock_info); DC_LOG_HW_AUDIO( - "\n%s:Input::requested_pixel_clock = %d" \ - "calculated_pixel_clock = %d \n", __func__, \ - crtc_info->requested_pixel_clock, \ - crtc_info->calculated_pixel_clock); + "\n%s:Input::requested_pixel_clock_100Hz = %d" \ + "calculated_pixel_clock_100Hz = %d \n", __func__, \ + crtc_info->requested_pixel_clock_100Hz, \ + crtc_info->calculated_pixel_clock_100Hz); /* HDMI_ACR_32_0__HDMI_ACR_CTS_32_MASK */ REG_UPDATE(HDMI_ACR_32_0, HDMI_ACR_CTS_32, audio_clock_info.cts_32khz); @@ -1528,6 +1542,17 @@ void enc1_dig_connect_to_otg( REG_UPDATE(DIG_FE_CNTL, DIG_SOURCE_SELECT, tg_inst); } +unsigned int enc1_dig_source_otg( + struct stream_encoder *enc) +{ + uint32_t tg_inst = 0; + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + REG_GET(DIG_FE_CNTL, DIG_SOURCE_SELECT, &tg_inst); + + return tg_inst; +} + static const struct stream_encoder_funcs dcn10_str_enc_funcs = { .dp_set_stream_attribute = enc1_stream_encoder_dp_set_stream_attribute, @@ -1562,6 +1587,8 @@ static const struct stream_encoder_funcs dcn10_str_enc_funcs = { .setup_stereo_sync = enc1_setup_stereo_sync, .set_avmute = enc1_stream_encoder_set_avmute, .dig_connect_to_otg = enc1_dig_connect_to_otg, + .hdmi_reset_stream_attribute = enc1_reset_hdmi_stream_attribute, + .dig_source_otg = enc1_dig_source_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 bc2b4af9543b..a512cbea00d1 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 @@ -89,7 +89,8 @@ SRI(DP_VID_STREAM_CNTL, DP, id), \ SRI(DP_VID_TIMING, DP, id), \ SRI(DP_SEC_AUD_N, DP, id), \ - SRI(DP_SEC_TIMESTAMP, DP, id) + SRI(DP_SEC_TIMESTAMP, DP, id), \ + SRI(DIG_CLOCK_PATTERN, DIG, id) #define SE_DCN_REG_LIST(id)\ SE_COMMON_DCN_REG_LIST(id) @@ -170,6 +171,7 @@ struct dcn10_stream_enc_registers { uint32_t HDMI_METADATA_PACKET_CONTROL; uint32_t DP_SEC_FRAMING4; #endif + uint32_t DIG_CLOCK_PATTERN; }; @@ -189,6 +191,7 @@ struct dcn10_stream_enc_registers { SE_SF(DIG0_HDMI_CONTROL, HDMI_DEEP_COLOR_ENABLE, mask_sh),\ SE_SF(DIG0_HDMI_CONTROL, HDMI_DEEP_COLOR_DEPTH, mask_sh),\ SE_SF(DIG0_HDMI_CONTROL, HDMI_DATA_SCRAMBLE_EN, mask_sh),\ + SE_SF(DIG0_HDMI_CONTROL, HDMI_NO_EXTRA_NULL_PACKET_FILLED, mask_sh),\ SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_GC_CONT, mask_sh),\ SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_GC_SEND, mask_sh),\ SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_NULL_SEND, mask_sh),\ @@ -297,7 +300,8 @@ struct dcn10_stream_enc_registers { 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(DIG0_DIG_FE_CNTL, DIG_SOURCE_SELECT, mask_sh) + SE_SF(DIG0_DIG_FE_CNTL, DIG_SOURCE_SELECT, mask_sh),\ + SE_SF(DIG0_DIG_CLOCK_PATTERN, DIG_CLOCK_PATTERN, mask_sh) #define SE_COMMON_MASK_SH_LIST_SOC(mask_sh)\ SE_COMMON_MASK_SH_LIST_SOC_BASE(mask_sh) @@ -374,6 +378,7 @@ struct dcn10_stream_enc_registers { type HDMI_GC_SEND;\ type HDMI_NULL_SEND;\ type HDMI_DATA_SCRAMBLE_EN;\ + type HDMI_NO_EXTRA_NULL_PACKET_FILLED;\ type HDMI_AUDIO_INFO_SEND;\ type AFMT_AUDIO_INFO_UPDATE;\ type HDMI_AUDIO_INFO_LINE;\ @@ -458,7 +463,8 @@ struct dcn10_stream_enc_registers { type HDMI_DB_DISABLE;\ type DP_VID_N_MUL;\ type DP_VID_M_DOUBLE_VALUE_EN;\ - type DIG_SOURCE_SELECT + type DIG_SOURCE_SELECT;\ + type DIG_CLOCK_PATTERN #if defined(CONFIG_DRM_AMD_DC_DCN2_0) #define SE_REG_FIELD_LIST_DCN2_0(type) \ @@ -592,6 +598,9 @@ void enc1_dig_connect_to_otg( struct stream_encoder *enc, int tg_inst); +unsigned int enc1_dig_source_otg( + struct stream_encoder *enc); + void enc1_stream_encoder_set_stream_attribute_helper( struct dcn10_stream_encoder *enc1, struct dc_crtc_timing *crtc_timing); @@ -605,8 +614,11 @@ void enc1_se_enable_dp_audio( void get_audio_clock_info( enum dc_color_depth color_depth, - uint32_t crtc_pixel_clock_in_khz, - uint32_t actual_pixel_clock_in_khz, + uint32_t crtc_pixel_clock_100Hz, + uint32_t actual_pixel_clock_100Hz, struct audio_clock_info *audio_clock_info); +void enc1_reset_hdmi_stream_attribute( + struct stream_encoder *enc); + #endif /* __DC_STREAM_ENCODER_DCN10_H__ */ |