diff options
Diffstat (limited to 'drivers/gpu/drm/amd/display/amdgpu_dm')
| -rw-r--r-- | drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 119 | ||||
| -rw-r--r-- | drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 2 | 
2 files changed, 97 insertions, 24 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..868946dd7ef1 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); @@ -6026,8 +6098,6 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector,  	if (recalculate_timing)  		drm_mode_set_crtcinfo(&saved_mode, 0); -	else if (!old_stream) -		drm_mode_set_crtcinfo(&mode, 0);  	/*  	 * If scaling is enabled and refresh rate didn't change @@ -6589,6 +6659,8 @@ enum drm_mode_status amdgpu_dm_connector_mode_valid(struct drm_connector *connec  		goto fail;  	} +	drm_mode_set_crtcinfo(mode, 0); +  	stream = create_validate_stream_for_sink(aconnector, mode,  						 to_dm_connector_state(connector->state),  						 NULL); @@ -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;  }; |