diff options
Diffstat (limited to 'drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c')
| -rw-r--r-- | drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 774 | 
1 files changed, 522 insertions, 252 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 6903fe6c894b..e224f23e2215 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -30,6 +30,7 @@  #include "vid.h"  #include "amdgpu.h"  #include "amdgpu_display.h" +#include "amdgpu_ucode.h"  #include "atom.h"  #include "amdgpu_dm.h"  #include "amdgpu_pm.h" @@ -50,6 +51,7 @@  #include <linux/version.h>  #include <linux/types.h>  #include <linux/pm_runtime.h> +#include <linux/firmware.h>  #include <drm/drmP.h>  #include <drm/drm_atomic.h> @@ -71,13 +73,15 @@  #include "modules/inc/mod_freesync.h" -#include "i2caux_interface.h" +#define FIRMWARE_RAVEN_DMCU		"amdgpu/raven_dmcu.bin" +MODULE_FIRMWARE(FIRMWARE_RAVEN_DMCU);  /* basic init/fini API */  static int amdgpu_dm_init(struct amdgpu_device *adev);  static void amdgpu_dm_fini(struct amdgpu_device *adev); -/* initializes drm_device display related structures, based on the information +/* + * initializes drm_device display related structures, based on the information   * provided by DAL. The drm strcutures are: drm_crtc, drm_connector,   * drm_encoder, drm_mode_config   * @@ -239,10 +243,6 @@ get_crtc_by_otg_inst(struct amdgpu_device *adev,  	struct drm_crtc *crtc;  	struct amdgpu_crtc *amdgpu_crtc; -	/* -	 * following if is check inherited from both functions where this one is -	 * used now. Need to be checked why it could happen. -	 */  	if (otg_inst == -1) {  		WARN_ON(1);  		return adev->mode_info.crtcs[0]; @@ -268,7 +268,7 @@ static void dm_pflip_high_irq(void *interrupt_params)  	amdgpu_crtc = get_crtc_by_otg_inst(adev, irq_params->irq_src - IRQ_TYPE_PFLIP);  	/* IRQ could occur when in initial stage */ -	/*TODO work and BO cleanup */ +	/* TODO work and BO cleanup */  	if (amdgpu_crtc == NULL) {  		DRM_DEBUG_DRIVER("CRTC is null, returning.\n");  		return; @@ -287,9 +287,9 @@ static void dm_pflip_high_irq(void *interrupt_params)  	} -	/* wakeup usersapce */ +	/* wake up userspace */  	if (amdgpu_crtc->event) { -		/* Update to correct count/ts if racing with vblank irq */ +		/* Update to correct count(s) if racing with vblank irq */  		drm_crtc_accurate_vblank_count(&amdgpu_crtc->base);  		drm_crtc_send_vblank_event(&amdgpu_crtc->base, amdgpu_crtc->event); @@ -313,16 +313,14 @@ static void dm_crtc_high_irq(void *interrupt_params)  {  	struct common_irq_params *irq_params = interrupt_params;  	struct amdgpu_device *adev = irq_params->adev; -	uint8_t crtc_index = 0;  	struct amdgpu_crtc *acrtc;  	acrtc = get_crtc_by_otg_inst(adev, irq_params->irq_src - IRQ_TYPE_VBLANK); -	if (acrtc) -		crtc_index = acrtc->crtc_id; - -	drm_handle_vblank(adev->ddev, crtc_index); -	amdgpu_dm_crtc_handle_crc_irq(&acrtc->base); +	if (acrtc) { +		drm_crtc_handle_vblank(&acrtc->base); +		amdgpu_dm_crtc_handle_crc_irq(&acrtc->base); +	}  }  static int dm_set_clockgating_state(void *handle, @@ -340,14 +338,6 @@ static int dm_set_powergating_state(void *handle,  /* Prototypes of private functions */  static int dm_early_init(void* handle); -static void hotplug_notify_work_func(struct work_struct *work) -{ -	struct amdgpu_display_manager *dm = container_of(work, struct amdgpu_display_manager, mst_hotplug_work); -	struct drm_device *dev = dm->ddev; - -	drm_kms_helper_hotplug_event(dev); -} -  /* Allocate memory for FBC compressed data  */  static void amdgpu_dm_fbc_init(struct drm_connector *connector)  { @@ -389,8 +379,8 @@ static void amdgpu_dm_fbc_init(struct drm_connector *connector)  } - -/* Init display KMS +/* + * Init display KMS   *   * Returns 0 on success   */ @@ -429,8 +419,6 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)  	init_data.cgs_device = adev->dm.cgs_device; -	adev->dm.dal = NULL; -  	init_data.dce_environment = DCE_ENV_PRODUCTION_DRV;  	/* @@ -451,8 +439,6 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)  		goto error;  	} -	INIT_WORK(&adev->dm.mst_hotplug_work, hotplug_notify_work_func); -  	adev->dm.freesync_module = mod_freesync_create(adev->dm.dc);  	if (!adev->dm.freesync_module) {  		DRM_ERROR( @@ -484,13 +470,18 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)  		goto error;  	} +#if defined(CONFIG_DEBUG_FS) +	if (dtn_debugfs_init(adev)) +		DRM_ERROR("amdgpu: failed initialize dtn debugfs support.\n"); +#endif +  	DRM_DEBUG_DRIVER("KMS initialized.\n");  	return 0;  error:  	amdgpu_dm_fini(adev); -	return -1; +	return -EINVAL;  }  static void amdgpu_dm_fini(struct amdgpu_device *adev) @@ -516,13 +507,99 @@ static void amdgpu_dm_fini(struct amdgpu_device *adev)  	return;  } -static int dm_sw_init(void *handle) +static int load_dmcu_fw(struct amdgpu_device *adev)  { +	const char *fw_name_dmcu; +	int r; +	const struct dmcu_firmware_header_v1_0 *hdr; + +	switch(adev->asic_type) { +	case CHIP_BONAIRE: +	case CHIP_HAWAII: +	case CHIP_KAVERI: +	case CHIP_KABINI: +	case CHIP_MULLINS: +	case CHIP_TONGA: +	case CHIP_FIJI: +	case CHIP_CARRIZO: +	case CHIP_STONEY: +	case CHIP_POLARIS11: +	case CHIP_POLARIS10: +	case CHIP_POLARIS12: +	case CHIP_VEGAM: +	case CHIP_VEGA10: +	case CHIP_VEGA12: +	case CHIP_VEGA20: +		return 0; +	case CHIP_RAVEN: +		fw_name_dmcu = FIRMWARE_RAVEN_DMCU; +		break; +	default: +		DRM_ERROR("Unsupported ASIC type: 0x%X\n", adev->asic_type); +		return -EINVAL; +	} + +	if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) { +		DRM_DEBUG_KMS("dm: DMCU firmware not supported on direct or SMU loading\n"); +		return 0; +	} + +	r = request_firmware_direct(&adev->dm.fw_dmcu, fw_name_dmcu, adev->dev); +	if (r == -ENOENT) { +		/* DMCU firmware is not necessary, so don't raise a fuss if it's missing */ +		DRM_DEBUG_KMS("dm: DMCU firmware not found\n"); +		adev->dm.fw_dmcu = NULL; +		return 0; +	} +	if (r) { +		dev_err(adev->dev, "amdgpu_dm: Can't load firmware \"%s\"\n", +			fw_name_dmcu); +		return r; +	} + +	r = amdgpu_ucode_validate(adev->dm.fw_dmcu); +	if (r) { +		dev_err(adev->dev, "amdgpu_dm: Can't validate firmware \"%s\"\n", +			fw_name_dmcu); +		release_firmware(adev->dm.fw_dmcu); +		adev->dm.fw_dmcu = NULL; +		return r; +	} + +	hdr = (const struct dmcu_firmware_header_v1_0 *)adev->dm.fw_dmcu->data; +	adev->firmware.ucode[AMDGPU_UCODE_ID_DMCU_ERAM].ucode_id = AMDGPU_UCODE_ID_DMCU_ERAM; +	adev->firmware.ucode[AMDGPU_UCODE_ID_DMCU_ERAM].fw = adev->dm.fw_dmcu; +	adev->firmware.fw_size += +		ALIGN(le32_to_cpu(hdr->header.ucode_size_bytes) - le32_to_cpu(hdr->intv_size_bytes), PAGE_SIZE); + +	adev->firmware.ucode[AMDGPU_UCODE_ID_DMCU_INTV].ucode_id = AMDGPU_UCODE_ID_DMCU_INTV; +	adev->firmware.ucode[AMDGPU_UCODE_ID_DMCU_INTV].fw = adev->dm.fw_dmcu; +	adev->firmware.fw_size += +		ALIGN(le32_to_cpu(hdr->intv_size_bytes), PAGE_SIZE); + +	adev->dm.dmcu_fw_version = le32_to_cpu(hdr->header.ucode_version); + +	DRM_DEBUG_KMS("PSP loading DMCU firmware\n"); +  	return 0;  } +static int dm_sw_init(void *handle) +{ +	struct amdgpu_device *adev = (struct amdgpu_device *)handle; + +	return load_dmcu_fw(adev); +} +  static int dm_sw_fini(void *handle)  { +	struct amdgpu_device *adev = (struct amdgpu_device *)handle; + +	if(adev->dm.fw_dmcu) { +		release_firmware(adev->dm.fw_dmcu); +		adev->dm.fw_dmcu = NULL; +	} +  	return 0;  } @@ -782,7 +859,7 @@ static int dm_resume(void *handle)  		mutex_unlock(&aconnector->hpd_lock);  	} -	/* Force mode set in atomic comit */ +	/* Force mode set in atomic commit */  	for_each_new_crtc_in_state(dm->cached_state, crtc, new_crtc_state, i)  		new_crtc_state->active_changed = true; @@ -913,35 +990,37 @@ amdgpu_dm_update_connector_after_detect(struct amdgpu_dm_connector *aconnector)  	sink = aconnector->dc_link->local_sink; -	/* Edid mgmt connector gets first update only in mode_valid hook and then +	/* +	 * Edid mgmt connector gets first update only in mode_valid hook and then  	 * the connector sink is set to either fake or physical sink depends on link status. -	 * don't do it here if u are during boot +	 * Skip if already done during boot.  	 */  	if (aconnector->base.force != DRM_FORCE_UNSPECIFIED  			&& aconnector->dc_em_sink) { -		/* For S3 resume with headless use eml_sink to fake stream -		 * because on resume connecotr->sink is set ti NULL +		/* +		 * For S3 resume with headless use eml_sink to fake stream +		 * because on resume connector->sink is set to NULL  		 */  		mutex_lock(&dev->mode_config.mutex);  		if (sink) {  			if (aconnector->dc_sink) { -				amdgpu_dm_remove_sink_from_freesync_module( -								connector); -				/* retain and release bellow are used for -				 * bump up refcount for sink because the link don't point -				 * to it anymore after disconnect so on next crtc to connector +				amdgpu_dm_update_freesync_caps(connector, NULL); +				/* +				 * retain and release below are used to +				 * bump up refcount for sink because the link doesn't point +				 * to it anymore after disconnect, so on next crtc to connector  				 * reshuffle by UMD we will get into unwanted dc_sink release  				 */  				if (aconnector->dc_sink != aconnector->dc_em_sink)  					dc_sink_release(aconnector->dc_sink);  			}  			aconnector->dc_sink = sink; -			amdgpu_dm_add_sink_to_freesync_module( -						connector, aconnector->edid); +			amdgpu_dm_update_freesync_caps(connector, +					aconnector->edid);  		} else { -			amdgpu_dm_remove_sink_from_freesync_module(connector); +			amdgpu_dm_update_freesync_caps(connector, NULL);  			if (!aconnector->dc_sink)  				aconnector->dc_sink = aconnector->dc_em_sink;  			else if (aconnector->dc_sink != aconnector->dc_em_sink) @@ -960,8 +1039,10 @@ amdgpu_dm_update_connector_after_detect(struct amdgpu_dm_connector *aconnector)  		return;  	if (aconnector->dc_sink == sink) { -		/* We got a DP short pulse (Link Loss, DP CTS, etc...). -		 * Do nothing!! */ +		/* +		 * We got a DP short pulse (Link Loss, DP CTS, etc...). +		 * Do nothing!! +		 */  		DRM_DEBUG_DRIVER("DCHPD: connector_id=%d: dc_sink didn't change.\n",  				aconnector->connector_id);  		return; @@ -972,18 +1053,22 @@ amdgpu_dm_update_connector_after_detect(struct amdgpu_dm_connector *aconnector)  	mutex_lock(&dev->mode_config.mutex); -	/* 1. Update status of the drm connector -	 * 2. Send an event and let userspace tell us what to do */ +	/* +	 * 1. Update status of the drm connector +	 * 2. Send an event and let userspace tell us what to do +	 */  	if (sink) { -		/* TODO: check if we still need the S3 mode update workaround. -		 * If yes, put it here. */ +		/* +		 * TODO: check if we still need the S3 mode update workaround. +		 * If yes, put it here. +		 */  		if (aconnector->dc_sink) -			amdgpu_dm_remove_sink_from_freesync_module( -							connector); +			amdgpu_dm_update_freesync_caps(connector, NULL);  		aconnector->dc_sink = sink;  		if (sink->dc_edid.length == 0) {  			aconnector->edid = NULL; +			drm_dp_cec_unset_edid(&aconnector->dm_dp_aux.aux);  		} else {  			aconnector->edid =  				(struct edid *) sink->dc_edid.raw_edid; @@ -991,11 +1076,14 @@ amdgpu_dm_update_connector_after_detect(struct amdgpu_dm_connector *aconnector)  			drm_connector_update_edid_property(connector,  					aconnector->edid); +			drm_dp_cec_set_edid(&aconnector->dm_dp_aux.aux, +					    aconnector->edid);  		} -		amdgpu_dm_add_sink_to_freesync_module(connector, aconnector->edid); +		amdgpu_dm_update_freesync_caps(connector, aconnector->edid);  	} else { -		amdgpu_dm_remove_sink_from_freesync_module(connector); +		drm_dp_cec_unset_edid(&aconnector->dm_dp_aux.aux); +		amdgpu_dm_update_freesync_caps(connector, NULL);  		drm_connector_update_edid_property(connector, NULL);  		aconnector->num_modes = 0;  		aconnector->dc_sink = NULL; @@ -1012,8 +1100,9 @@ static void handle_hpd_irq(void *param)  	struct drm_device *dev = connector->dev;  	enum dc_connection_type new_connection_type = dc_connection_none; -	/* In case of failure or MST no need to update connector status or notify the OS -	 * since (for MST case) MST does this in it's own context. +	/* +	 * In case of failure or MST no need to update connector status or notify the OS +	 * since (for MST case) MST does this in its own context.  	 */  	mutex_lock(&aconnector->hpd_lock); @@ -1110,7 +1199,7 @@ static void dm_handle_hpd_rx_irq(struct amdgpu_dm_connector *aconnector)  					break;  			} -			/* check if there is new irq to be handle */ +			/* check if there is new irq to be handled */  			dret = drm_dp_dpcd_read(  				&aconnector->dm_dp_aux.aux,  				dpcd_addr, @@ -1136,7 +1225,8 @@ static void handle_hpd_rx_irq(void *param)  	bool is_mst_root_connector = aconnector->mst_mgr.mst_state;  	enum dc_connection_type new_connection_type = dc_connection_none; -	/* TODO:Temporary add mutex to protect hpd interrupt not have a gpio +	/* +	 * TODO:Temporary add mutex to protect hpd interrupt not have a gpio  	 * conflict, after implement i2c helper, this mutex should be  	 * retired.  	 */ @@ -1182,8 +1272,10 @@ static void handle_hpd_rx_irq(void *param)  	    (dc_link->type == dc_connection_mst_branch))  		dm_handle_hpd_rx_irq(aconnector); -	if (dc_link->type != dc_connection_mst_branch) +	if (dc_link->type != dc_connection_mst_branch) { +		drm_dp_cec_irq(&aconnector->dm_dp_aux.aux);  		mutex_unlock(&aconnector->hpd_lock); +	}  }  static void register_hpd_handlers(struct amdgpu_device *adev) @@ -1233,7 +1325,7 @@ static int dce110_register_irq_handlers(struct amdgpu_device *adev)  	struct dc_interrupt_params int_params = {0};  	int r;  	int i; -	unsigned client_id = AMDGPU_IH_CLIENTID_LEGACY; +	unsigned client_id = AMDGPU_IRQ_CLIENTID_LEGACY;  	if (adev->asic_type == CHIP_VEGA10 ||  	    adev->asic_type == CHIP_VEGA12 || @@ -1244,7 +1336,8 @@ static int dce110_register_irq_handlers(struct amdgpu_device *adev)  	int_params.requested_polarity = INTERRUPT_POLARITY_DEFAULT;  	int_params.current_polarity = INTERRUPT_POLARITY_DEFAULT; -	/* Actions of amdgpu_irq_add_id(): +	/* +	 * Actions of amdgpu_irq_add_id():  	 * 1. Register a set() function with base driver.  	 *    Base driver will call set() function to enable/disable an  	 *    interrupt in DC hardware. @@ -1324,7 +1417,8 @@ static int dcn10_register_irq_handlers(struct amdgpu_device *adev)  	int_params.requested_polarity = INTERRUPT_POLARITY_DEFAULT;  	int_params.current_polarity = INTERRUPT_POLARITY_DEFAULT; -	/* Actions of amdgpu_irq_add_id(): +	/* +	 * Actions of amdgpu_irq_add_id():  	 * 1. Register a set() function with base driver.  	 *    Base driver will call set() function to enable/disable an  	 *    interrupt in DC hardware. @@ -1333,7 +1427,7 @@ static int dcn10_register_irq_handlers(struct amdgpu_device *adev)  	 *    coming from DC hardware.  	 *    amdgpu_dm_irq_handler() will re-direct the interrupt to DC  	 *    for acknowledging and handling. -	 * */ +	 */  	/* Use VSTARTUP interrupt */  	for (i = DCN_1_0__SRCID__DC_D1_OTG_VSTARTUP; @@ -1411,7 +1505,7 @@ static int amdgpu_dm_mode_config_init(struct amdgpu_device *adev)  	adev->ddev->mode_config.preferred_depth = 24;  	adev->ddev->mode_config.prefer_shadow = 1; -	/* indicate support of immediate flip */ +	/* indicates support for immediate flip */  	adev->ddev->mode_config.async_page_flip = true;  	adev->ddev->mode_config.fb_base = adev->gmc.aper_base; @@ -1497,7 +1591,7 @@ static int initialize_plane(struct amdgpu_display_manager *dm,  	plane->base.type = mode_info->plane_type[plane_id];  	/* -	 * HACK: IGT tests expect that each plane can only have one +	 * HACK: IGT tests expect that each plane can only have  	 * one possible CRTC. For now, set one CRTC for each  	 * plane that is not an underlay, but still allow multiple  	 * CRTCs for underlay planes. @@ -1525,7 +1619,8 @@ static void register_backlight_device(struct amdgpu_display_manager *dm,  	if ((link->connector_signal & (SIGNAL_TYPE_EDP | SIGNAL_TYPE_LVDS)) &&  	    link->type != dc_connection_none) { -		/* Event if registration failed, we should continue with +		/* +		 * Event if registration failed, we should continue with  		 * DM initialization because not having a backlight control  		 * is better then a black screen.  		 */ @@ -1538,7 +1633,8 @@ static void register_backlight_device(struct amdgpu_display_manager *dm,  } -/* In this architecture, the association +/* + * In this architecture, the association   * connector -> encoder -> crtc   * id not really requried. The crtc and connector will hold the   * display_index as an abstraction to use with DAL component @@ -1559,7 +1655,7 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)  	link_cnt = dm->dc->caps.max_links;  	if (amdgpu_dm_mode_config_init(dm->adev)) {  		DRM_ERROR("DM: Failed to initialize mode config\n"); -		return -1; +		return -EINVAL;  	}  	/* Identify the number of planes to be initialized */ @@ -1681,7 +1777,7 @@ fail:  	kfree(aconnector);  	for (i = 0; i < dm->dc->caps.max_planes; i++)  		kfree(mode_info->planes[i]); -	return -1; +	return -EINVAL;  }  static void amdgpu_dm_destroy_drm_device(struct amdgpu_display_manager *dm) @@ -1694,7 +1790,7 @@ static void amdgpu_dm_destroy_drm_device(struct amdgpu_display_manager *dm)   * amdgpu_display_funcs functions   *****************************************************************************/ -/** +/*   * dm_bandwidth_update - program display watermarks   *   * @adev: amdgpu_device pointer @@ -1709,26 +1805,68 @@ static void dm_bandwidth_update(struct amdgpu_device *adev)  static int amdgpu_notify_freesync(struct drm_device *dev, void *data,  				struct drm_file *filp)  { -	struct mod_freesync_params freesync_params; -	uint8_t num_streams; +	struct drm_atomic_state *state; +	struct drm_modeset_acquire_ctx ctx; +	struct drm_crtc *crtc; +	struct drm_connector *connector; +	struct drm_connector_state *old_con_state, *new_con_state; +	int ret = 0;  	uint8_t i; +	bool enable = false; -	struct amdgpu_device *adev = dev->dev_private; -	int r = 0; +	drm_modeset_acquire_init(&ctx, 0); + +	state = drm_atomic_state_alloc(dev); +	if (!state) { +		ret = -ENOMEM; +		goto out; +	} +	state->acquire_ctx = &ctx; + +retry: +	drm_for_each_crtc(crtc, dev) { +		ret = drm_atomic_add_affected_connectors(state, crtc); +		if (ret) +			goto fail; + +		/* TODO rework amdgpu_dm_commit_planes so we don't need this */ +		ret = drm_atomic_add_affected_planes(state, crtc); +		if (ret) +			goto fail; +	} + +	for_each_oldnew_connector_in_state(state, connector, old_con_state, new_con_state, i) { +		struct dm_connector_state *dm_new_con_state = to_dm_connector_state(new_con_state); +		struct drm_crtc_state *new_crtc_state; +		struct amdgpu_crtc *acrtc = to_amdgpu_crtc(dm_new_con_state->base.crtc); +		struct dm_crtc_state *dm_new_crtc_state; + +		if (!acrtc) { +			ASSERT(0); +			continue; +		} -	/* Get freesync enable flag from DRM */ +		new_crtc_state = drm_atomic_get_new_crtc_state(state, &acrtc->base); +		dm_new_crtc_state = to_dm_crtc_state(new_crtc_state); -	num_streams = dc_get_current_stream_count(adev->dm.dc); +		dm_new_crtc_state->freesync_enabled = enable; +	} -	for (i = 0; i < num_streams; i++) { -		struct dc_stream_state *stream; -		stream = dc_get_stream_at_index(adev->dm.dc, i); +	ret = drm_atomic_commit(state); -		mod_freesync_update_state(adev->dm.freesync_module, -					  &stream, 1, &freesync_params); +fail: +	if (ret == -EDEADLK) { +		drm_atomic_state_clear(state); +		drm_modeset_backoff(&ctx); +		goto retry;  	} -	return r; +	drm_atomic_state_put(state); + +out: +	drm_modeset_drop_locks(&ctx); +	drm_modeset_acquire_fini(&ctx); +	return ret;  }  static const struct amdgpu_display_funcs dm_display_funcs = { @@ -1861,9 +1999,11 @@ static int dm_early_init(void *handle)  	if (adev->mode_info.funcs == NULL)  		adev->mode_info.funcs = &dm_display_funcs; -	/* Note: Do NOT change adev->audio_endpt_rreg and +	/* +	 * Note: Do NOT change adev->audio_endpt_rreg and  	 * adev->audio_endpt_wreg because they are initialised in -	 * amdgpu_device_init() */ +	 * amdgpu_device_init() +	 */  #if defined(CONFIG_DEBUG_KERNEL_DC)  	device_create_file(  		adev->ddev->dev, @@ -1909,7 +2049,7 @@ static bool fill_rects_from_plane_state(const struct drm_plane_state *state,  {  	plane_state->src_rect.x = state->src_x >> 16;  	plane_state->src_rect.y = state->src_y >> 16; -	/*we ignore for now mantissa and do not to deal with floating pixels :(*/ +	/* we ignore the mantissa for now and do not deal with floating pixels :( */  	plane_state->src_rect.width = state->src_w >> 16;  	if (plane_state->src_rect.width == 0) @@ -1961,7 +2101,7 @@ static int get_fb_info(const struct amdgpu_framebuffer *amdgpu_fb,  	int r = amdgpu_bo_reserve(rbo, false);  	if (unlikely(r)) { -		// Don't show error msg. when return -ERESTARTSYS +		/* Don't show error message when returning -ERESTARTSYS */  		if (r != -ERESTARTSYS)  			DRM_ERROR("Unable to reserve buffer: %d\n", r);  		return r; @@ -2011,6 +2151,10 @@ static int fill_plane_attributes_from_fb(struct amdgpu_device *adev,  	case DRM_FORMAT_ABGR2101010:  		plane_state->format = SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010;  		break; +	case DRM_FORMAT_XBGR8888: +	case DRM_FORMAT_ABGR8888: +		plane_state->format = SURFACE_PIXEL_FORMAT_GRPH_ABGR8888; +		break;  	case DRM_FORMAT_NV21:  		plane_state->format = SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr;  		break; @@ -2153,8 +2297,6 @@ static int fill_plane_attributes(struct amdgpu_device *adev,  	return ret;  } -/*****************************************************************************/ -  static void update_stream_scaling_settings(const struct drm_display_mode *mode,  					   const struct dm_connector_state *dm_state,  					   struct dc_stream_state *stream) @@ -2217,7 +2359,8 @@ convert_color_depth_from_display_info(const struct drm_connector *connector)  	switch (bpc) {  	case 0: -		/* Temporary Work around, DRM don't parse color depth for +		/* +		 * Temporary Work around, DRM doesn't parse color depth for  		 * EDID revision before 1.4  		 * TODO: Fix edid parsing  		 */ @@ -2329,7 +2472,6 @@ static void adjust_colour_depth_from_display_info(struct dc_crtc_timing *timing_  	} while (timing_out->display_color_depth > COLOR_DEPTH_888);  } -/*****************************************************************************/  static void  fill_stream_properties_from_drm_display_mode(struct dc_stream_state *stream, @@ -2529,9 +2671,10 @@ static void dm_enable_per_frame_crtc_master_sync(struct dc_state *context)  	for (i = 0; i < context->stream_count ; i++) {  		if (!context->streams[i])  			continue; -		/* TODO: add a function to read AMD VSDB bits and will set +		/* +		 * TODO: add a function to read AMD VSDB bits and set  		 * crtc_sync_master.multi_sync_enabled flag -		 * For now its set to false +		 * For now it's set to false  		 */  		set_multisync_trigger_params(context->streams[i]);  	} @@ -2594,7 +2737,8 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector,  				head);  	if (preferred_mode == NULL) { -		/* This may not be an error, the use case is when we we have no +		/* +		 * This may not be an error, the use case is when we have no  		 * usermode calls to reset and set mode upon hotplug. In this  		 * case, we call set mode ourselves to restore the previous mode  		 * and the modelist may not be filled in in time. @@ -2688,6 +2832,10 @@ dm_crtc_duplicate_state(struct drm_crtc *crtc)  		dc_stream_retain(state->stream);  	} +	state->adjust = cur->adjust; +	state->vrr_infopacket = cur->vrr_infopacket; +	state->freesync_enabled = cur->freesync_enabled; +  	/* TODO Duplicate dc_stream after objects are stream object is flattened */  	return &state->base; @@ -2724,6 +2872,7 @@ static const struct drm_crtc_funcs amdgpu_dm_crtc_funcs = {  	.atomic_duplicate_state = dm_crtc_duplicate_state,  	.atomic_destroy_state = dm_crtc_destroy_state,  	.set_crc_source = amdgpu_dm_crtc_set_crc_source, +	.verify_crc_source = amdgpu_dm_crtc_verify_crc_source,  	.enable_vblank = dm_enable_vblank,  	.disable_vblank = dm_disable_vblank,  }; @@ -2734,10 +2883,12 @@ amdgpu_dm_connector_detect(struct drm_connector *connector, bool force)  	bool connected;  	struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); -	/* Notes: +	/* +	 * Notes:  	 * 1. This interface is NOT called in context of HPD irq.  	 * 2. This interface *is called* in context of user-mode ioctl. Which -	 * makes it a bad place for *any* MST-related activit. */ +	 * makes it a bad place for *any* MST-related activity. +	 */  	if (aconnector->base.force == DRM_FORCE_UNSPECIFIED &&  	    !aconnector->fake_enable) @@ -2859,6 +3010,7 @@ static void amdgpu_dm_connector_destroy(struct drm_connector *connector)  		dm->backlight_dev = NULL;  	}  #endif +	drm_dp_cec_unregister_connector(&aconnector->dm_dp_aux.aux);  	drm_connector_unregister(connector);  	drm_connector_cleanup(connector);  	kfree(connector); @@ -2895,13 +3047,15 @@ amdgpu_dm_connector_atomic_duplicate_state(struct drm_connector *connector)  	struct dm_connector_state *new_state =  			kmemdup(state, sizeof(*state), GFP_KERNEL); -	if (new_state) { -		__drm_atomic_helper_connector_duplicate_state(connector, -							      &new_state->base); -		return &new_state->base; -	} +	if (!new_state) +		return NULL; -	return NULL; +	__drm_atomic_helper_connector_duplicate_state(connector, &new_state->base); + +	new_state->freesync_capable = state->freesync_capable; +	new_state->freesync_enable = state->freesync_enable; + +	return &new_state->base;  }  static const struct drm_connector_funcs amdgpu_dm_connector_funcs = { @@ -2915,28 +3069,6 @@ static const struct drm_connector_funcs amdgpu_dm_connector_funcs = {  	.atomic_get_property = amdgpu_dm_connector_atomic_get_property  }; -static struct drm_encoder *best_encoder(struct drm_connector *connector) -{ -	int enc_id = connector->encoder_ids[0]; -	struct drm_mode_object *obj; -	struct drm_encoder *encoder; - -	DRM_DEBUG_DRIVER("Finding the best encoder\n"); - -	/* pick the encoder ids */ -	if (enc_id) { -		obj = drm_mode_object_find(connector->dev, NULL, enc_id, DRM_MODE_OBJECT_ENCODER); -		if (!obj) { -			DRM_ERROR("Couldn't find a matching encoder for our connector\n"); -			return NULL; -		} -		encoder = obj_to_encoder(obj); -		return encoder; -	} -	DRM_ERROR("No encoder id\n"); -	return NULL; -} -  static int get_modes(struct drm_connector *connector)  {  	return amdgpu_dm_connector_get_modes(connector); @@ -2979,7 +3111,8 @@ static void handle_edid_mgmt(struct amdgpu_dm_connector *aconnector)  {  	struct dc_link *link = (struct dc_link *)aconnector->dc_link; -	/* In case of headless boot with force on for DP managed connector +	/* +	 * In case of headless boot with force on for DP managed connector  	 * Those settings have to be != 0 to get initial modeset  	 */  	if (link->connector_signal == SIGNAL_TYPE_DISPLAY_PORT) { @@ -3007,7 +3140,8 @@ enum drm_mode_status amdgpu_dm_connector_mode_valid(struct drm_connector *connec  			(mode->flags & DRM_MODE_FLAG_DBLSCAN))  		return result; -	/* Only run this the first time mode_valid is called to initilialize +	/* +	 * Only run this the first time mode_valid is called to initilialize  	 * EDID mgmt  	 */  	if (aconnector->base.force != DRM_FORCE_UNSPECIFIED && @@ -3048,14 +3182,14 @@ fail:  static const struct drm_connector_helper_funcs  amdgpu_dm_connector_helper_funcs = {  	/* -	 * If hotplug a second bigger display in FB Con mode, bigger resolution +	 * If hotplugging a second bigger display in FB Con mode, bigger resolution  	 * modes will be filtered by drm_mode_validate_size(), and those modes -	 * is missing after user start lightdm. So we need to renew modes list. +	 * are missing after user start lightdm. So we need to renew modes list.  	 * in get_modes call back, not just return the modes count  	 */  	.get_modes = get_modes,  	.mode_valid = amdgpu_dm_connector_mode_valid, -	.best_encoder = best_encoder +	.best_encoder = drm_atomic_helper_best_encoder  };  static void dm_crtc_helper_disable(struct drm_crtc *crtc) @@ -3076,7 +3210,7 @@ static int dm_crtc_helper_atomic_check(struct drm_crtc *crtc,  		return ret;  	} -	/* In some use cases, like reset, no stream  is attached */ +	/* In some use cases, like reset, no stream is attached */  	if (!dm_crtc_state->stream)  		return 0; @@ -3125,7 +3259,7 @@ static void dm_drm_plane_reset(struct drm_plane *plane)  	amdgpu_state = kzalloc(sizeof(*amdgpu_state), GFP_KERNEL);  	WARN_ON(amdgpu_state == NULL); -	 +  	if (amdgpu_state) {  		plane->state = &amdgpu_state->base;  		plane->state->plane = plane; @@ -3303,7 +3437,7 @@ static const struct drm_plane_helper_funcs dm_plane_helper_funcs = {   * TODO: these are currently initialized to rgb formats only.   * For future use cases we should either initialize them dynamically based on   * plane capabilities, or initialize this array to all formats, so internal drm - * check will succeed, and let DC to implement proper check + * check will succeed, and let DC implement proper check   */  static const uint32_t rgb_formats[] = {  	DRM_FORMAT_RGB888, @@ -3314,6 +3448,8 @@ static const uint32_t rgb_formats[] = {  	DRM_FORMAT_XBGR2101010,  	DRM_FORMAT_ARGB2101010,  	DRM_FORMAT_ABGR2101010, +	DRM_FORMAT_XBGR8888, +	DRM_FORMAT_ABGR8888,  };  static const uint32_t yuv_formats[] = { @@ -3415,6 +3551,7 @@ static int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm,  	acrtc->crtc_id = crtc_index;  	acrtc->base.enabled = false; +	acrtc->otg_inst = -1;  	dm->adev->mode_info.crtcs[crtc_index] = acrtc;  	drm_crtc_enable_color_mgmt(&acrtc->base, MAX_COLOR_LUT_ENTRIES, @@ -3437,6 +3574,8 @@ static int to_drm_connector_type(enum signal_type st)  		return DRM_MODE_CONNECTOR_HDMIA;  	case SIGNAL_TYPE_EDP:  		return DRM_MODE_CONNECTOR_eDP; +	case SIGNAL_TYPE_LVDS: +		return DRM_MODE_CONNECTOR_LVDS;  	case SIGNAL_TYPE_RGB:  		return DRM_MODE_CONNECTOR_VGA;  	case SIGNAL_TYPE_DISPLAY_PORT: @@ -3597,7 +3736,8 @@ static int amdgpu_dm_connector_get_modes(struct drm_connector *connector)  	encoder = helper->best_encoder(connector);  	if (!edid || !drm_edid_is_valid(edid)) { -		drm_add_modes_noedid(connector, 640, 480); +		amdgpu_dm_connector->num_modes = +				drm_add_modes_noedid(connector, 640, 480);  	} else {  		amdgpu_dm_connector_ddc_get_modes(connector, edid);  		amdgpu_dm_connector_add_common_modes(encoder, connector); @@ -3624,7 +3764,8 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm,  	aconnector->hpd.hpd = AMDGPU_HPD_NONE; /* not used */  	mutex_init(&aconnector->hpd_lock); -	/* configure support HPD hot plug connector_>polled default value is 0 +	/* +	 * configure support HPD hot plug connector_>polled default value is 0  	 * which means HPD hot plug not supported  	 */  	switch (connector_type) { @@ -3686,9 +3827,9 @@ static int amdgpu_dm_i2c_xfer(struct i2c_adapter *i2c_adap,  		cmd.payloads[i].data = msgs[i].buf;  	} -	if (dal_i2caux_submit_i2c_command( -			ddc_service->ctx->i2caux, -			ddc_service->ddc_pin, +	if (dc_submit_i2c( +			ddc_service->ctx->dc, +			ddc_service->ddc_pin->hw_info.ddc_channel,  			&cmd))  		result = num; @@ -3724,12 +3865,14 @@ create_i2c(struct ddc_service *ddc_service,  	snprintf(i2c->base.name, sizeof(i2c->base.name), "AMDGPU DM i2c hw bus %d", link_index);  	i2c_set_adapdata(&i2c->base, i2c);  	i2c->ddc_service = ddc_service; +	i2c->ddc_service->ddc_pin->hw_info.ddc_channel = link_index;  	return i2c;  } -/* Note: this function assumes that dc_link_detect() was called for the +/* + * Note: this function assumes that dc_link_detect() was called for the   * dc_link which will be represented by this aconnector.   */  static int amdgpu_dm_connector_init(struct amdgpu_display_manager *dm, @@ -3908,8 +4051,6 @@ static void remove_stream(struct amdgpu_device *adev,  			  struct dc_stream_state *stream)  {  	/* this is the update mode case */ -	if (adev->dm.freesync_module) -		mod_freesync_remove_stream(adev->dm.freesync_module, stream);  	acrtc->otg_inst = -1;  	acrtc->enabled = false; @@ -4057,13 +4198,15 @@ static void amdgpu_dm_do_flip(struct drm_crtc *crtc,  	/* TODO eliminate or rename surface_update */  	struct dc_surface_update surface_updates[1] = { {0} };  	struct dm_crtc_state *acrtc_state = to_dm_crtc_state(crtc->state); +	struct dc_stream_status *stream_status;  	/* Prepare wait for target vblank early - before the fence-waits */  	target_vblank = target - (uint32_t)drm_crtc_vblank_count(crtc) +  			amdgpu_get_vblank_counter_kms(crtc->dev, acrtc->crtc_id); -	/* TODO This might fail and hence better not used, wait +	/* +	 * TODO This might fail and hence better not used, wait  	 * explicitly on fences instead  	 * and in general should be called for  	 * blocking commit to as per framework helpers @@ -4080,7 +4223,8 @@ static void amdgpu_dm_do_flip(struct drm_crtc *crtc,  	amdgpu_bo_unreserve(abo); -	/* Wait until we're out of the vertical blank period before the one +	/* +	 * Wait until we're out of the vertical blank period before the one  	 * targeted by the flip  	 */  	while ((acrtc->enabled && @@ -4110,7 +4254,19 @@ static void amdgpu_dm_do_flip(struct drm_crtc *crtc,  	spin_unlock_irqrestore(&crtc->dev->event_lock, flags); -	surface_updates->surface = dc_stream_get_status(acrtc_state->stream)->plane_states[0]; +	stream_status = dc_stream_get_status(acrtc_state->stream); +	if (!stream_status) { +		DRM_ERROR("No stream status for CRTC: id=%d\n", +			acrtc->crtc_id); +		return; +	} + +	surface_updates->surface = stream_status->plane_states[0]; +	if (!surface_updates->surface) { +		DRM_ERROR("No surface for CRTC: id=%d\n", +			acrtc->crtc_id); +		return; +	}  	surface_updates->flip_addr = &addr;  	dc_commit_updates_for_stream(adev->dm.dc, @@ -4177,6 +4333,11 @@ static bool commit_planes_to_stream(  	stream_update->dst = dc_stream->dst;  	stream_update->out_transfer_func = dc_stream->out_transfer_func; +	if (dm_new_crtc_state->freesync_enabled != dm_old_crtc_state->freesync_enabled) { +		stream_update->vrr_infopacket = &dc_stream->vrr_infopacket; +		stream_update->adjust = &dc_stream->adjust; +	} +  	for (i = 0; i < new_plane_count; i++) {  		updates[i].surface = plane_states[i];  		updates[i].gamma = @@ -4312,6 +4473,8 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,  			spin_unlock_irqrestore(&pcrtc->dev->event_lock, flags);  		} +		dc_stream_attach->adjust = acrtc_state->adjust; +		dc_stream_attach->vrr_infopacket = acrtc_state->vrr_infopacket;  		if (false == commit_planes_to_stream(dm->dc,  							plane_states_constructed, @@ -4325,7 +4488,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,  	}  } -/** +/*   * amdgpu_dm_crtc_copy_transient_flags - copy mirrored flags from DRM to DC   * @crtc_state: the DRM CRTC state   * @stream_state: the DC stream state. @@ -4362,8 +4525,10 @@ static int amdgpu_dm_atomic_commit(struct drm_device *dev,  		if (drm_atomic_crtc_needs_modeset(new_crtc_state) && dm_old_crtc_state->stream)  			manage_dm_interrupts(adev, acrtc, false);  	} -	/* Add check here for SoC's that support hardware cursor plane, to -	 * unset legacy_cursor_update */ +	/* +	 * Add check here for SoC's that support hardware cursor plane, to +	 * unset legacy_cursor_update +	 */  	return drm_atomic_helper_commit(dev, state, nonblock); @@ -4428,8 +4593,8 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)  				 * this could happen because of issues with  				 * userspace notifications delivery.  				 * In this case userspace tries to set mode on -				 * display which is disconnect in fact. -				 * dc_sink in NULL in this case on aconnector. +				 * display which is disconnected in fact. +				 * dc_sink is NULL in this case on aconnector.  				 * We expect reset mode will come soon.  				 *  				 * This can also happen when unplug is done @@ -4461,62 +4626,6 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)  		}  	} /* for_each_crtc_in_state() */ -	/* -	 * Add streams after required streams from new and replaced streams -	 * are removed from freesync module -	 */ -	if (adev->dm.freesync_module) { -		for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, -					      new_crtc_state, i) { -			struct amdgpu_dm_connector *aconnector = NULL; -			struct dm_connector_state *dm_new_con_state = NULL; -			struct amdgpu_crtc *acrtc = NULL; -			bool modeset_needed; - -			dm_new_crtc_state = to_dm_crtc_state(new_crtc_state); -			dm_old_crtc_state = to_dm_crtc_state(old_crtc_state); -			modeset_needed = modeset_required( -					new_crtc_state, -					dm_new_crtc_state->stream, -					dm_old_crtc_state->stream); -			/* We add stream to freesync if: -			 * 1. Said stream is not null, and -			 * 2. A modeset is requested. This means that the -			 *    stream was removed previously, and needs to be -			 *    replaced. -			 */ -			if (dm_new_crtc_state->stream == NULL || -					!modeset_needed) -				continue; - -			acrtc = to_amdgpu_crtc(crtc); - -			aconnector = -				amdgpu_dm_find_first_crtc_matching_connector( -					state, crtc); -			if (!aconnector) { -				DRM_DEBUG_DRIVER("Atomic commit: Failed to " -						 "find connector for acrtc " -						 "id:%d skipping freesync " -						 "init\n", -						 acrtc->crtc_id); -				continue; -			} - -			mod_freesync_add_stream(adev->dm.freesync_module, -						dm_new_crtc_state->stream, -						&aconnector->caps); -			new_con_state = drm_atomic_get_new_connector_state( -					state, &aconnector->base); -			dm_new_con_state = to_dm_connector_state(new_con_state); - -			mod_freesync_set_user_enable(adev->dm.freesync_module, -						     &dm_new_crtc_state->stream, -						     1, -						     &dm_new_con_state->user_enable); -		} -	} -  	if (dm_state->context) {  		dm_enable_per_frame_crtc_master_sync(dm_state->context);  		WARN_ON(!dc_commit_state(dm->dc, dm_state->context)); @@ -4554,7 +4663,7 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)  		if (!acrtc || drm_atomic_crtc_needs_modeset(new_crtc_state))  			continue; -		/* Skip any thing not scale or underscan changes */ +		/* Skip anything that is not scaling or underscan changes */  		if (!is_scaling_state_different(dm_new_con_state, dm_old_con_state))  			continue; @@ -4570,6 +4679,9 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)  		WARN_ON(!status);  		WARN_ON(!status->plane_count); +		dm_new_crtc_state->stream->adjust = dm_new_crtc_state->adjust; +		dm_new_crtc_state->stream->vrr_infopacket = dm_new_crtc_state->vrr_infopacket; +  		/*TODO How it works with MPO ?*/  		if (!commit_planes_to_stream(  				dm->dc, @@ -4602,11 +4714,6 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)  		if (dm_new_crtc_state->stream == NULL || !modeset_needed)  			continue; -		if (adev->dm.freesync_module) -			mod_freesync_notify_mode_change( -				adev->dm.freesync_module, -				&dm_new_crtc_state->stream, 1); -  		manage_dm_interrupts(adev, acrtc, true);  	} @@ -4647,7 +4754,8 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)  	drm_atomic_helper_cleanup_planes(dev, state); -	/* Finally, drop a runtime PM reference for each newly disabled CRTC, +	/* +	 * Finally, drop a runtime PM reference for each newly disabled CRTC,  	 * so we can put the GPU into runtime suspend if we're not driving any  	 * displays anymore  	 */ @@ -4715,9 +4823,9 @@ err:  }  /* - * This functions handle all cases when set mode does not come upon hotplug. - * This include when the same display is unplugged then plugged back into the - * same port and when we are running without usermode desktop manager supprot + * This function handles all cases when set mode does not come upon hotplug. + * This includes when a display is unplugged then plugged back into the + * same port and when running without usermode desktop manager supprot   */  void dm_restore_drm_connector_state(struct drm_device *dev,  				    struct drm_connector *connector) @@ -4746,7 +4854,7 @@ void dm_restore_drm_connector_state(struct drm_device *dev,  		dm_force_atomic_commit(&aconnector->base);  } -/*` +/*   * Grabs all modesetting locks to serialize against any blocking commits,   * Waits for completion of all non blocking commits.   */ @@ -4757,7 +4865,8 @@ static int do_aquire_global_lock(struct drm_device *dev,  	struct drm_crtc_commit *commit;  	long ret; -	/* Adding all modeset locks to aquire_ctx will +	/* +	 * Adding all modeset locks to aquire_ctx will  	 * ensure that when the framework release it the  	 * extra locks we are locking here will get released to  	 */ @@ -4776,7 +4885,8 @@ static int do_aquire_global_lock(struct drm_device *dev,  		if (!commit)  			continue; -		/* Make sure all pending HW programming completed and +		/* +		 * Make sure all pending HW programming completed and  		 * page flips done  		 */  		ret = wait_for_completion_interruptible_timeout(&commit->hw_done, 10*HZ); @@ -4795,7 +4905,45 @@ static int do_aquire_global_lock(struct drm_device *dev,  	return ret < 0 ? ret : 0;  } -static int dm_update_crtcs_state(struct dc *dc, +void set_freesync_on_stream(struct amdgpu_display_manager *dm, +			    struct dm_crtc_state *new_crtc_state, +			    struct dm_connector_state *new_con_state, +			    struct dc_stream_state *new_stream) +{ +	struct mod_freesync_config config = {0}; +	struct mod_vrr_params vrr = {0}; +	struct dc_info_packet vrr_infopacket = {0}; +	struct amdgpu_dm_connector *aconnector = +			to_amdgpu_dm_connector(new_con_state->base.connector); + +	if (new_con_state->freesync_capable && +	    new_con_state->freesync_enable) { +		config.state = new_crtc_state->freesync_enabled ? +				VRR_STATE_ACTIVE_VARIABLE : +				VRR_STATE_INACTIVE; +		config.min_refresh_in_uhz = +				aconnector->min_vfreq * 1000000; +		config.max_refresh_in_uhz = +				aconnector->max_vfreq * 1000000; +		config.vsif_supported = true; +	} + +	mod_freesync_build_vrr_params(dm->freesync_module, +				      new_stream, +				      &config, &vrr); + +	mod_freesync_build_vrr_infopacket(dm->freesync_module, +					  new_stream, +					  &vrr, +					  packet_type_fs1, +					  NULL, +					  &vrr_infopacket); + +	new_crtc_state->adjust = vrr.adjust; +	new_crtc_state->vrr_infopacket = vrr_infopacket; +} + +static int dm_update_crtcs_state(struct amdgpu_display_manager *dm,  				 struct drm_atomic_state *state,  				 bool enable,  				 bool *lock_and_validation_needed) @@ -4808,8 +4956,10 @@ static int dm_update_crtcs_state(struct dc *dc,  	struct dc_stream_state *new_stream;  	int ret = 0; -	/*TODO Move this code into dm_crtc_atomic_check once we get rid of dc_validation_set */ -	/* update changed items */ +	/* +	 * TODO Move this code into dm_crtc_atomic_check once we get rid of dc_validation_set +	 * update changed items +	 */  	for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {  		struct amdgpu_crtc *acrtc = NULL;  		struct amdgpu_dm_connector *aconnector = NULL; @@ -4834,7 +4984,7 @@ static int dm_update_crtcs_state(struct dc *dc,  		/* TODO This hack should go away */  		if (aconnector && enable) { -			// Make sure fake sink is created in plug-in scenario +			/* Make sure fake sink is created in plug-in scenario */  			drm_new_conn_state = drm_atomic_get_new_connector_state(state,   								    &aconnector->base);  			drm_old_conn_state = drm_atomic_get_old_connector_state(state, @@ -4854,9 +5004,9 @@ static int dm_update_crtcs_state(struct dc *dc,  			/*  			 * we can have no stream on ACTION_SET if a display -			 * was disconnected during S3, in this case it not and +			 * was disconnected during S3, in this case it is not an  			 * error, the OS will be updated after detection, and -			 * do the right thing on next atomic commit +			 * will do the right thing on next atomic commit  			 */  			if (!new_stream) { @@ -4865,6 +5015,9 @@ static int dm_update_crtcs_state(struct dc *dc,  				break;  			} +			set_freesync_on_stream(dm, dm_new_crtc_state, +					       dm_new_conn_state, new_stream); +  			if (dc_is_stream_unchanged(new_stream, dm_old_crtc_state->stream) &&  			    dc_is_stream_scaling_unchanged(new_stream, dm_old_crtc_state->stream)) {  				new_crtc_state->mode_changed = false; @@ -4873,6 +5026,9 @@ static int dm_update_crtcs_state(struct dc *dc,  			}  		} +		if (dm_old_crtc_state->freesync_enabled != dm_new_crtc_state->freesync_enabled) +			new_crtc_state->mode_changed = true; +  		if (!drm_atomic_crtc_needs_modeset(new_crtc_state))  			goto next_crtc; @@ -4899,7 +5055,7 @@ static int dm_update_crtcs_state(struct dc *dc,  			/* i.e. reset mode */  			if (dc_remove_stream_from_ctx( -					dc, +					dm->dc,  					dm_state->context,  					dm_old_crtc_state->stream) != DC_OK) {  				ret = -EINVAL; @@ -4936,7 +5092,7 @@ static int dm_update_crtcs_state(struct dc *dc,  							crtc->base.id);  				if (dc_add_stream_to_ctx( -						dc, +						dm->dc,  						dm_state->context,  						dm_new_crtc_state->stream) != DC_OK) {  					ret = -EINVAL; @@ -4985,6 +5141,8 @@ next_crtc:  				goto fail;  			amdgpu_dm_set_ctm(dm_new_crtc_state);  		} + +  	}  	return ret; @@ -5128,6 +5286,100 @@ static int dm_update_planes_state(struct dc *dc,  	return ret;  } +enum surface_update_type dm_determine_update_type_for_commit(struct dc *dc, struct drm_atomic_state *state) +{ + + +	int i, j, num_plane; +	struct drm_plane_state *old_plane_state, *new_plane_state; +	struct dm_plane_state *new_dm_plane_state, *old_dm_plane_state; +	struct drm_crtc *new_plane_crtc, *old_plane_crtc; +	struct drm_plane *plane; + +	struct drm_crtc *crtc; +	struct drm_crtc_state *new_crtc_state, *old_crtc_state; +	struct dm_crtc_state *new_dm_crtc_state, *old_dm_crtc_state; +	struct dc_stream_status *status = NULL; + +	struct dc_surface_update *updates = kzalloc(MAX_SURFACES * sizeof(struct dc_surface_update), GFP_KERNEL); +	struct dc_plane_state *surface = kzalloc(MAX_SURFACES * sizeof(struct dc_plane_state), GFP_KERNEL); +	struct dc_stream_update stream_update; +	enum surface_update_type update_type = UPDATE_TYPE_FAST; + + +	for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { +		new_dm_crtc_state = to_dm_crtc_state(new_crtc_state); +		old_dm_crtc_state = to_dm_crtc_state(old_crtc_state); +		num_plane = 0; + +		if (new_dm_crtc_state->stream) { + +			for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, j) { +				new_plane_crtc = new_plane_state->crtc; +				old_plane_crtc = old_plane_state->crtc; +				new_dm_plane_state = to_dm_plane_state(new_plane_state); +				old_dm_plane_state = to_dm_plane_state(old_plane_state); + +				if (plane->type == DRM_PLANE_TYPE_CURSOR) +					continue; + +				if (!state->allow_modeset) +					continue; + +				if (crtc == new_plane_crtc) { +					updates[num_plane].surface = &surface[num_plane]; + +					if (new_crtc_state->mode_changed) { +						updates[num_plane].surface->src_rect = +									new_dm_plane_state->dc_state->src_rect; +						updates[num_plane].surface->dst_rect = +									new_dm_plane_state->dc_state->dst_rect; +						updates[num_plane].surface->rotation = +									new_dm_plane_state->dc_state->rotation; +						updates[num_plane].surface->in_transfer_func = +									new_dm_plane_state->dc_state->in_transfer_func; +						stream_update.dst = new_dm_crtc_state->stream->dst; +						stream_update.src = new_dm_crtc_state->stream->src; +					} + +					if (new_crtc_state->color_mgmt_changed) { +						updates[num_plane].gamma = +								new_dm_plane_state->dc_state->gamma_correction; +						updates[num_plane].in_transfer_func = +								new_dm_plane_state->dc_state->in_transfer_func; +						stream_update.gamut_remap = +								&new_dm_crtc_state->stream->gamut_remap_matrix; +						stream_update.out_transfer_func = +								new_dm_crtc_state->stream->out_transfer_func; +					} + +					num_plane++; +				} +			} + +			if (num_plane > 0) { +				status = dc_stream_get_status(new_dm_crtc_state->stream); +				update_type = dc_check_update_surfaces_for_stream(dc, updates, num_plane, +										  &stream_update, status); + +				if (update_type > UPDATE_TYPE_MED) { +					update_type = UPDATE_TYPE_FULL; +					goto ret; +				} +			} + +		} else if (!new_dm_crtc_state->stream && old_dm_crtc_state->stream) { +			update_type = UPDATE_TYPE_FULL; +			goto ret; +		} +	} + +ret: +	kfree(updates); +	kfree(surface); + +	return update_type; +}  static int amdgpu_dm_atomic_check(struct drm_device *dev,  				  struct drm_atomic_state *state) @@ -5139,6 +5391,9 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,  	struct drm_connector_state *old_con_state, *new_con_state;  	struct drm_crtc *crtc;  	struct drm_crtc_state *old_crtc_state, *new_crtc_state; +	enum surface_update_type update_type = UPDATE_TYPE_FAST; +	enum surface_update_type overall_update_type = UPDATE_TYPE_FAST; +  	int ret, i;  	/* @@ -5152,8 +5407,12 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,  		goto fail;  	for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { +		struct dm_crtc_state *dm_new_crtc_state = to_dm_crtc_state(new_crtc_state); +		struct dm_crtc_state *dm_old_crtc_state  = to_dm_crtc_state(old_crtc_state); +  		if (!drm_atomic_crtc_needs_modeset(new_crtc_state) && -		    !new_crtc_state->color_mgmt_changed) +		    !new_crtc_state->color_mgmt_changed && +		    (dm_old_crtc_state->freesync_enabled == dm_new_crtc_state->freesync_enabled))  			continue;  		if (!new_crtc_state->enable) @@ -5179,13 +5438,13 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,  	}  	/* Disable all crtcs which require disable */ -	ret = dm_update_crtcs_state(dc, state, false, &lock_and_validation_needed); +	ret = dm_update_crtcs_state(&adev->dm, state, false, &lock_and_validation_needed);  	if (ret) {  		goto fail;  	}  	/* Enable all crtcs which require enable */ -	ret = dm_update_crtcs_state(dc, state, true, &lock_and_validation_needed); +	ret = dm_update_crtcs_state(&adev->dm, state, true, &lock_and_validation_needed);  	if (ret) {  		goto fail;  	} @@ -5202,7 +5461,7 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,  		goto fail;  	/* Check scaling and underscan changes*/ -	/*TODO Removed scaling changes validation due to inability to commit +	/* TODO Removed scaling changes validation due to inability to commit  	 * new stream into context w\o causing full reset. Need to  	 * decide how to handle.  	 */ @@ -5220,20 +5479,37 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,  		if (!is_scaling_state_different(dm_new_con_state, dm_old_con_state))  			continue; +		overall_update_type = UPDATE_TYPE_FULL;  		lock_and_validation_needed = true;  	}  	/*  	 * For full updates case when -	 * removing/adding/updating  streams on once CRTC while flipping +	 * removing/adding/updating streams on one CRTC while flipping  	 * on another CRTC,  	 * acquiring global lock  will guarantee that any such full  	 * update commit  	 * will wait for completion of any outstanding flip using DRMs  	 * synchronization events.  	 */ +	update_type = dm_determine_update_type_for_commit(dc, state); + +	if (overall_update_type < update_type) +		overall_update_type = update_type; + +	/* +	 * lock_and_validation_needed was an old way to determine if we need to set +	 * the global lock. Leaving it in to check if we broke any corner cases +	 * lock_and_validation_needed true = UPDATE_TYPE_FULL or UPDATE_TYPE_MED +	 * lock_and_validation_needed false = UPDATE_TYPE_FAST +	 */ +	if (lock_and_validation_needed && overall_update_type <= UPDATE_TYPE_FAST) +		WARN(1, "Global lock should be Set, overall_update_type should be UPDATE_TYPE_MED or UPDATE_TYPE_FULL"); +	else if (!lock_and_validation_needed && overall_update_type > UPDATE_TYPE_FAST) +		WARN(1, "Global lock should NOT be set, overall_update_type should be UPDATE_TYPE_FAST"); + -	if (lock_and_validation_needed) { +	if (overall_update_type > UPDATE_TYPE_FAST) {  		ret = do_aquire_global_lock(dev, state);  		if (ret) @@ -5278,8 +5554,8 @@ static bool is_dp_capable_without_timing_msa(struct dc *dc,  	return capable;  } -void amdgpu_dm_add_sink_to_freesync_module(struct drm_connector *connector, -					   struct edid *edid) +void amdgpu_dm_update_freesync_caps(struct drm_connector *connector, +					struct edid *edid)  {  	int i;  	bool edid_check_required; @@ -5298,6 +5574,18 @@ void amdgpu_dm_add_sink_to_freesync_module(struct drm_connector *connector,  		return;  	} +	if (!edid) { +		dm_con_state = to_dm_connector_state(connector->state); + +		amdgpu_dm_connector->min_vfreq = 0; +		amdgpu_dm_connector->max_vfreq = 0; +		amdgpu_dm_connector->pixel_clock_mhz = 0; + +		dm_con_state->freesync_capable = false; +		dm_con_state->freesync_enable = false; +		return; +	} +  	dm_con_state = to_dm_connector_state(connector->state);  	edid_check_required = false; @@ -5348,28 +5636,10 @@ void amdgpu_dm_add_sink_to_freesync_module(struct drm_connector *connector,  		}  		if (amdgpu_dm_connector->max_vfreq - -				amdgpu_dm_connector->min_vfreq > 10) { -			amdgpu_dm_connector->caps.supported = true; -			amdgpu_dm_connector->caps.min_refresh_in_micro_hz = -					amdgpu_dm_connector->min_vfreq * 1000000; -			amdgpu_dm_connector->caps.max_refresh_in_micro_hz = -					amdgpu_dm_connector->max_vfreq * 1000000; +		    amdgpu_dm_connector->min_vfreq > 10) { +  			dm_con_state->freesync_capable = true;  		}  	} - -	/* -	 * TODO figure out how to notify user-mode or DRM of freesync caps -	 * once we figure out how to deal with freesync in an upstreamable -	 * fashion -	 */ -  } -void amdgpu_dm_remove_sink_from_freesync_module(struct drm_connector *connector) -{ -	/* -	 * TODO fill in once we figure out how to deal with freesync in -	 * an upstreamable fashion -	 */ -}  | 
