diff options
Diffstat (limited to 'drivers/gpu/drm/amd/display')
8 files changed, 155 insertions, 30 deletions
| diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 88ba8b66de1f..c6fd34bab358 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1274,11 +1274,15 @@ static void mmhub_read_system_context(struct amdgpu_device *adev, struct dc_phy_  	pt_base = amdgpu_gmc_pd_addr(adev->gart.bo); -	page_table_start.high_part = (u32)(adev->gmc.gart_start >> 44) & 0xF; -	page_table_start.low_part = (u32)(adev->gmc.gart_start >> 12); -	page_table_end.high_part = (u32)(adev->gmc.gart_end >> 44) & 0xF; -	page_table_end.low_part = (u32)(adev->gmc.gart_end >> 12); -	page_table_base.high_part = upper_32_bits(pt_base) & 0xF; +	page_table_start.high_part = upper_32_bits(adev->gmc.gart_start >> +						   AMDGPU_GPU_PAGE_SHIFT); +	page_table_start.low_part = lower_32_bits(adev->gmc.gart_start >> +						  AMDGPU_GPU_PAGE_SHIFT); +	page_table_end.high_part = upper_32_bits(adev->gmc.gart_end >> +						 AMDGPU_GPU_PAGE_SHIFT); +	page_table_end.low_part = lower_32_bits(adev->gmc.gart_end >> +						AMDGPU_GPU_PAGE_SHIFT); +	page_table_base.high_part = upper_32_bits(pt_base);  	page_table_base.low_part = lower_32_bits(pt_base);  	pa_config->system_aperture.start_addr = (uint64_t)logical_addr_low << 18; @@ -1640,8 +1644,9 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)  		}  		break;  	} -	if (init_data.flags.gpu_vm_support) -		init_data.flags.gpu_vm_support = amdgpu_sg_display_supported(adev); +	if (init_data.flags.gpu_vm_support && +	    (amdgpu_sg_display == 0)) +		init_data.flags.gpu_vm_support = false;  	if (init_data.flags.gpu_vm_support)  		adev->mode_info.gpu_vm_support = true; @@ -2335,14 +2340,62 @@ static int dm_late_init(void *handle)  	return detect_mst_link_for_all_connectors(adev_to_drm(adev));  } +static void resume_mst_branch_status(struct drm_dp_mst_topology_mgr *mgr) +{ +	int ret; +	u8 guid[16]; +	u64 tmp64; + +	mutex_lock(&mgr->lock); +	if (!mgr->mst_primary) +		goto out_fail; + +	if (drm_dp_read_dpcd_caps(mgr->aux, mgr->dpcd) < 0) { +		drm_dbg_kms(mgr->dev, "dpcd read failed - undocked during suspend?\n"); +		goto out_fail; +	} + +	ret = drm_dp_dpcd_writeb(mgr->aux, DP_MSTM_CTRL, +				 DP_MST_EN | +				 DP_UP_REQ_EN | +				 DP_UPSTREAM_IS_SRC); +	if (ret < 0) { +		drm_dbg_kms(mgr->dev, "mst write failed - undocked during suspend?\n"); +		goto out_fail; +	} + +	/* Some hubs forget their guids after they resume */ +	ret = drm_dp_dpcd_read(mgr->aux, DP_GUID, guid, 16); +	if (ret != 16) { +		drm_dbg_kms(mgr->dev, "dpcd read failed - undocked during suspend?\n"); +		goto out_fail; +	} + +	if (memchr_inv(guid, 0, 16) == NULL) { +		tmp64 = get_jiffies_64(); +		memcpy(&guid[0], &tmp64, sizeof(u64)); +		memcpy(&guid[8], &tmp64, sizeof(u64)); + +		ret = drm_dp_dpcd_write(mgr->aux, DP_GUID, guid, 16); + +		if (ret != 16) { +			drm_dbg_kms(mgr->dev, "check mstb guid failed - undocked during suspend?\n"); +			goto out_fail; +		} +	} + +	memcpy(mgr->mst_primary->guid, guid, 16); + +out_fail: +	mutex_unlock(&mgr->lock); +} +  static void s3_handle_mst(struct drm_device *dev, bool suspend)  {  	struct amdgpu_dm_connector *aconnector;  	struct drm_connector *connector;  	struct drm_connector_list_iter iter;  	struct drm_dp_mst_topology_mgr *mgr; -	int ret; -	bool need_hotplug = false;  	drm_connector_list_iter_begin(dev, &iter);  	drm_for_each_connector_iter(connector, &iter) { @@ -2364,18 +2417,15 @@ static void s3_handle_mst(struct drm_device *dev, bool suspend)  			if (!dp_is_lttpr_present(aconnector->dc_link))  				try_to_configure_aux_timeout(aconnector->dc_link->ddc, LINK_AUX_DEFAULT_TIMEOUT_PERIOD); -			ret = drm_dp_mst_topology_mgr_resume(mgr, true); -			if (ret < 0) { -				dm_helpers_dp_mst_stop_top_mgr(aconnector->dc_link->ctx, -					aconnector->dc_link); -				need_hotplug = true; -			} +			/* TODO: move resume_mst_branch_status() into drm mst resume again +			 * once topology probing work is pulled out from mst resume into mst +			 * resume 2nd step. mst resume 2nd step should be called after old +			 * state getting restored (i.e. drm_atomic_helper_resume()). +			 */ +			resume_mst_branch_status(mgr);  		}  	}  	drm_connector_list_iter_end(&iter); - -	if (need_hotplug) -		drm_kms_helper_hotplug_event(dev);  }  static int amdgpu_dm_smu_write_watermarks_table(struct amdgpu_device *adev) @@ -2769,7 +2819,8 @@ static int dm_resume(void *handle)  	struct dm_atomic_state *dm_state = to_dm_atomic_state(dm->atomic_obj.state);  	enum dc_connection_type new_connection_type = dc_connection_none;  	struct dc_state *dc_state; -	int i, r, j; +	int i, r, j, ret; +	bool need_hotplug = false;  	if (amdgpu_in_reset(adev)) {  		dc_state = dm->cached_dc_state; @@ -2867,7 +2918,7 @@ static int dm_resume(void *handle)  			continue;  		/* -		 * this is the case when traversing through already created +		 * this is the case when traversing through already created end sink  		 * MST connectors, should be skipped  		 */  		if (aconnector && aconnector->mst_root) @@ -2927,6 +2978,27 @@ static int dm_resume(void *handle)  	dm->cached_state = NULL; +	/* Do mst topology probing after resuming cached state*/ +	drm_connector_list_iter_begin(ddev, &iter); +	drm_for_each_connector_iter(connector, &iter) { +		aconnector = to_amdgpu_dm_connector(connector); +		if (aconnector->dc_link->type != dc_connection_mst_branch || +		    aconnector->mst_root) +			continue; + +		ret = drm_dp_mst_topology_mgr_resume(&aconnector->mst_mgr, true); + +		if (ret < 0) { +			dm_helpers_dp_mst_stop_top_mgr(aconnector->dc_link->ctx, +					aconnector->dc_link); +			need_hotplug = true; +		} +	} +	drm_connector_list_iter_end(&iter); + +	if (need_hotplug) +		drm_kms_helper_hotplug_event(ddev); +  	amdgpu_dm_irq_resume_late(adev);  	amdgpu_dm_smu_write_watermarks_table(adev); @@ -8073,7 +8145,8 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,  		bundle->surface_updates[planes_count].plane_info =  			&bundle->plane_infos[planes_count]; -		if (acrtc_state->stream->link->psr_settings.psr_feature_enabled) { +		if (acrtc_state->stream->link->psr_settings.psr_feature_enabled || +		    acrtc_state->stream->link->replay_settings.replay_feature_enabled) {  			fill_dc_dirty_rects(plane, old_plane_state,  					    new_plane_state, new_crtc_state,  					    &bundle->flip_addrs[planes_count], diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h index a2d34be82613..9e4cc5eeda76 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -620,7 +620,7 @@ struct amdgpu_hdmi_vsdb_info {  	unsigned int max_refresh_rate_hz;  	/** -	 * @replay mode: Replay supported +	 * @replay_mode: Replay supported  	 */  	bool replay_mode;  }; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_enc_cfg.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_enc_cfg.c index 30c0644d4418..be5a6d008b29 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_enc_cfg.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_enc_cfg.c @@ -169,11 +169,23 @@ static void add_link_enc_assignment(  /* Return first available DIG link encoder. */  static enum engine_id find_first_avail_link_enc(  		const struct dc_context *ctx, -		const struct dc_state *state) +		const struct dc_state *state, +		enum engine_id eng_id_requested)  {  	enum engine_id eng_id = ENGINE_ID_UNKNOWN;  	int i; +	if (eng_id_requested != ENGINE_ID_UNKNOWN) { + +		for (i = 0; i < ctx->dc->res_pool->res_cap->num_dig_link_enc; i++) { +			eng_id = state->res_ctx.link_enc_cfg_ctx.link_enc_avail[i]; +			if (eng_id == eng_id_requested) +				return eng_id; +		} +	} + +	eng_id = ENGINE_ID_UNKNOWN; +  	for (i = 0; i < ctx->dc->res_pool->res_cap->num_dig_link_enc; i++) {  		eng_id = state->res_ctx.link_enc_cfg_ctx.link_enc_avail[i];  		if (eng_id != ENGINE_ID_UNKNOWN) @@ -287,7 +299,7 @@ void link_enc_cfg_link_encs_assign(  		struct dc_stream_state *streams[],  		uint8_t stream_count)  { -	enum engine_id eng_id = ENGINE_ID_UNKNOWN; +	enum engine_id eng_id = ENGINE_ID_UNKNOWN, eng_id_req = ENGINE_ID_UNKNOWN;  	int i;  	int j; @@ -377,8 +389,14 @@ void link_enc_cfg_link_encs_assign(  		 * assigned to that endpoint.  		 */  		link_enc = get_link_enc_used_by_link(state, stream->link); -		if (link_enc == NULL) -			eng_id = find_first_avail_link_enc(stream->ctx, state); +		if (link_enc == NULL) { + +			if (stream->link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA && +					stream->link->dpia_preferred_eng_id != ENGINE_ID_UNKNOWN) +				eng_id_req = stream->link->dpia_preferred_eng_id; + +			eng_id = find_first_avail_link_enc(stream->ctx, state, eng_id_req); +		}  		else  			eng_id =  link_enc->preferred_engine; @@ -402,7 +420,9 @@ void link_enc_cfg_link_encs_assign(  			DC_LOG_DEBUG("%s: CUR %s(%d) - enc_id(%d)\n",  					__func__,  					assignment.ep_id.ep_type == DISPLAY_ENDPOINT_PHY ? "PHY" : "DPIA", -					assignment.ep_id.link_id.enum_id - 1, +					assignment.ep_id.ep_type == DISPLAY_ENDPOINT_PHY ? +							assignment.ep_id.link_id.enum_id : +							assignment.ep_id.link_id.enum_id - 1,  					assignment.eng_id);  	}  	for (i = 0; i < MAX_PIPES; i++) { @@ -413,7 +433,9 @@ void link_enc_cfg_link_encs_assign(  			DC_LOG_DEBUG("%s: NEW %s(%d) - enc_id(%d)\n",  					__func__,  					assignment.ep_id.ep_type == DISPLAY_ENDPOINT_PHY ? "PHY" : "DPIA", -					assignment.ep_id.link_id.enum_id - 1, +					assignment.ep_id.ep_type == DISPLAY_ENDPOINT_PHY ? +							assignment.ep_id.link_id.enum_id : +							assignment.ep_id.link_id.enum_id - 1,  					assignment.eng_id);  	} @@ -478,7 +500,6 @@ struct dc_link *link_enc_cfg_get_link_using_link_enc(  	if (stream)  		link = stream->link; -	// dm_output_to_console("%s: No link using DIG(%d).\n", __func__, eng_id);  	return link;  } diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 0d0bef8eb331..31e3183497a7 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -1496,6 +1496,7 @@ struct dc_link {  	 * object creation.  	 */  	enum engine_id eng_id; +	enum engine_id dpia_preferred_eng_id;  	bool test_pattern_enabled;  	enum dp_test_pattern current_test_pattern; 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 ad967b58d7be..478281f2a5ba 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 @@ -964,7 +964,9 @@ void dce110_edp_backlight_control(  		return;  	} -	if (link->panel_cntl) { +	if (link->panel_cntl && !(link->dpcd_sink_ext_caps.bits.oled || +		link->dpcd_sink_ext_caps.bits.hdr_aux_backlight_control == 1 || +		link->dpcd_sink_ext_caps.bits.sdr_aux_backlight_control == 1)) {  		bool is_backlight_on = link->panel_cntl->funcs->is_panel_backlight_on(link->panel_cntl);  		if ((enable && is_backlight_on) || (!enable && !is_backlight_on)) { diff --git a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c index 1c1fb2fa0822..004beed9bd44 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c @@ -1032,6 +1032,28 @@ static const struct dce_i2c_mask i2c_masks = {  		I2C_COMMON_MASK_SH_LIST_DCN30(_MASK)  }; +/* ========================================================== */ + +/* + * DPIA index | Preferred Encoder     |    Host Router + *   0        |      C                |       0 + *   1        |      First Available  |       0 + *   2        |      D                |       1 + *   3        |      First Available  |       1 + */ +/* ========================================================== */ +static const enum engine_id dpia_to_preferred_enc_id_table[] = { +		ENGINE_ID_DIGC, +		ENGINE_ID_DIGC, +		ENGINE_ID_DIGD, +		ENGINE_ID_DIGD +}; + +static enum engine_id dcn314_get_preferred_eng_id_dpia(unsigned int dpia_index) +{ +	return dpia_to_preferred_enc_id_table[dpia_index]; +} +  static struct dce_i2c_hw *dcn31_i2c_hw_create(  	struct dc_context *ctx,  	uint32_t inst) @@ -1785,6 +1807,7 @@ static struct resource_funcs dcn314_res_pool_funcs = {  	.update_bw_bounding_box = dcn314_update_bw_bounding_box,  	.patch_unknown_plane_state = dcn20_patch_unknown_plane_state,  	.get_panel_config_defaults = dcn314_get_panel_config_defaults, +	.get_preferred_eng_id_dpia = dcn314_get_preferred_eng_id_dpia,  };  static struct clock_source *dcn30_clock_source_create( 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 027aec70c070..eaad1260bfd1 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -65,6 +65,7 @@ struct resource_context;  struct clk_bw_params;  struct resource_funcs { +	enum engine_id (*get_preferred_eng_id_dpia)(unsigned int dpia_index);  	void (*destroy)(struct resource_pool **pool);  	void (*link_init)(struct dc_link *link);  	struct panel_cntl*(*panel_cntl_create)( diff --git a/drivers/gpu/drm/amd/display/dc/link/link_factory.c b/drivers/gpu/drm/amd/display/dc/link/link_factory.c index 195ca9e52eda..0895742a3102 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_factory.c +++ b/drivers/gpu/drm/amd/display/dc/link/link_factory.c @@ -791,6 +791,10 @@ static bool construct_dpia(struct dc_link *link,  	/* Set dpia port index : 0 to number of dpia ports */  	link->ddc_hw_inst = init_params->connector_index; +	// Assign Dpia preferred eng_id +	if (link->dc->res_pool->funcs->get_preferred_eng_id_dpia) +		link->dpia_preferred_eng_id = link->dc->res_pool->funcs->get_preferred_eng_id_dpia(link->ddc_hw_inst); +  	/* TODO: Create link encoder */  	link->psr_settings.psr_version = DC_PSR_VERSION_UNSUPPORTED; |