diff options
Diffstat (limited to 'drivers/gpu/drm/amd')
55 files changed, 552 insertions, 371 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index d5a2eefd6c3e..74edba18b159 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -1156,7 +1156,7 @@ static inline void amdgpu_set_ib_value(struct amdgpu_cs_parser *p,  /*   * Writeback   */ -#define AMDGPU_MAX_WB 512	/* Reserve at most 512 WB slots for amdgpu-owned rings. */ +#define AMDGPU_MAX_WB 128	/* Reserve at most 128 WB slots for amdgpu-owned rings. */  struct amdgpu_wb {  	struct amdgpu_bo	*wb_obj; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c index 57afad79f55d..8fa850a070e0 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c @@ -540,6 +540,9 @@ int amdgpu_acpi_pcie_performance_request(struct amdgpu_device *adev,  	size_t size;  	u32 retry = 3; +	if (amdgpu_acpi_pcie_notify_device_ready(adev)) +		return -EINVAL; +  	/* Get the device handle */  	handle = ACPI_HANDLE(&adev->pdev->dev);  	if (!handle) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c index e2c3c5ec42d1..c53095b3b0fb 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c @@ -568,6 +568,7 @@ static const struct amdgpu_px_quirk amdgpu_px_quirk_list[] = {  	/* HG _PR3 doesn't seem to work on this A+A weston board */  	{ 0x1002, 0x6900, 0x1002, 0x0124, AMDGPU_PX_QUIRK_FORCE_ATPX },  	{ 0x1002, 0x6900, 0x1028, 0x0812, AMDGPU_PX_QUIRK_FORCE_ATPX }, +	{ 0x1002, 0x6900, 0x1028, 0x0813, AMDGPU_PX_QUIRK_FORCE_ATPX },  	{ 0, 0, 0, 0, 0 },  }; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c index 8ca3783f2deb..7a073ac5f9c6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c @@ -69,25 +69,18 @@ void amdgpu_connector_hotplug(struct drm_connector *connector)  		/* don't do anything if sink is not display port, i.e.,  		 * passive dp->(dvi|hdmi) adaptor  		 */ -		if (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) { -			int saved_dpms = connector->dpms; -			/* Only turn off the display if it's physically disconnected */ -			if (!amdgpu_display_hpd_sense(adev, amdgpu_connector->hpd.hpd)) { -				drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF); -			} else if (amdgpu_atombios_dp_needs_link_train(amdgpu_connector)) { -				/* Don't try to start link training before we -				 * have the dpcd */ -				if (amdgpu_atombios_dp_get_dpcd(amdgpu_connector)) -					return; - -				/* set it to OFF so that drm_helper_connector_dpms() -				 * won't return immediately since the current state -				 * is ON at this point. -				 */ -				connector->dpms = DRM_MODE_DPMS_OFF; -				drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON); -			} -			connector->dpms = saved_dpms; +		if (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT && +		    amdgpu_display_hpd_sense(adev, amdgpu_connector->hpd.hpd) && +		    amdgpu_atombios_dp_needs_link_train(amdgpu_connector)) { +			/* Don't start link training before we have the DPCD */ +			if (amdgpu_atombios_dp_get_dpcd(amdgpu_connector)) +				return; + +			/* Turn the connector off and back on immediately, which +			 * will trigger link training +			 */ +			drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF); +			drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON);  		}  	}  } @@ -736,9 +729,11 @@ amdgpu_connector_lvds_detect(struct drm_connector *connector, bool force)  	enum drm_connector_status ret = connector_status_disconnected;  	int r; -	r = pm_runtime_get_sync(connector->dev->dev); -	if (r < 0) -		return connector_status_disconnected; +	if (!drm_kms_helper_is_poll_worker()) { +		r = pm_runtime_get_sync(connector->dev->dev); +		if (r < 0) +			return connector_status_disconnected; +	}  	if (encoder) {  		struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); @@ -757,8 +752,12 @@ amdgpu_connector_lvds_detect(struct drm_connector *connector, bool force)  	/* check acpi lid status ??? */  	amdgpu_connector_update_scratch_regs(connector, ret); -	pm_runtime_mark_last_busy(connector->dev->dev); -	pm_runtime_put_autosuspend(connector->dev->dev); + +	if (!drm_kms_helper_is_poll_worker()) { +		pm_runtime_mark_last_busy(connector->dev->dev); +		pm_runtime_put_autosuspend(connector->dev->dev); +	} +  	return ret;  } @@ -868,9 +867,11 @@ amdgpu_connector_vga_detect(struct drm_connector *connector, bool force)  	enum drm_connector_status ret = connector_status_disconnected;  	int r; -	r = pm_runtime_get_sync(connector->dev->dev); -	if (r < 0) -		return connector_status_disconnected; +	if (!drm_kms_helper_is_poll_worker()) { +		r = pm_runtime_get_sync(connector->dev->dev); +		if (r < 0) +			return connector_status_disconnected; +	}  	encoder = amdgpu_connector_best_single_encoder(connector);  	if (!encoder) @@ -924,8 +925,10 @@ amdgpu_connector_vga_detect(struct drm_connector *connector, bool force)  	amdgpu_connector_update_scratch_regs(connector, ret);  out: -	pm_runtime_mark_last_busy(connector->dev->dev); -	pm_runtime_put_autosuspend(connector->dev->dev); +	if (!drm_kms_helper_is_poll_worker()) { +		pm_runtime_mark_last_busy(connector->dev->dev); +		pm_runtime_put_autosuspend(connector->dev->dev); +	}  	return ret;  } @@ -988,9 +991,11 @@ amdgpu_connector_dvi_detect(struct drm_connector *connector, bool force)  	enum drm_connector_status ret = connector_status_disconnected;  	bool dret = false, broken_edid = false; -	r = pm_runtime_get_sync(connector->dev->dev); -	if (r < 0) -		return connector_status_disconnected; +	if (!drm_kms_helper_is_poll_worker()) { +		r = pm_runtime_get_sync(connector->dev->dev); +		if (r < 0) +			return connector_status_disconnected; +	}  	if (!force && amdgpu_connector_check_hpd_status_unchanged(connector)) {  		ret = connector->status; @@ -1115,8 +1120,10 @@ out:  	amdgpu_connector_update_scratch_regs(connector, ret);  exit: -	pm_runtime_mark_last_busy(connector->dev->dev); -	pm_runtime_put_autosuspend(connector->dev->dev); +	if (!drm_kms_helper_is_poll_worker()) { +		pm_runtime_mark_last_busy(connector->dev->dev); +		pm_runtime_put_autosuspend(connector->dev->dev); +	}  	return ret;  } @@ -1359,9 +1366,11 @@ amdgpu_connector_dp_detect(struct drm_connector *connector, bool force)  	struct drm_encoder *encoder = amdgpu_connector_best_single_encoder(connector);  	int r; -	r = pm_runtime_get_sync(connector->dev->dev); -	if (r < 0) -		return connector_status_disconnected; +	if (!drm_kms_helper_is_poll_worker()) { +		r = pm_runtime_get_sync(connector->dev->dev); +		if (r < 0) +			return connector_status_disconnected; +	}  	if (!force && amdgpu_connector_check_hpd_status_unchanged(connector)) {  		ret = connector->status; @@ -1429,8 +1438,10 @@ amdgpu_connector_dp_detect(struct drm_connector *connector, bool force)  	amdgpu_connector_update_scratch_regs(connector, ret);  out: -	pm_runtime_mark_last_busy(connector->dev->dev); -	pm_runtime_put_autosuspend(connector->dev->dev); +	if (!drm_kms_helper_is_poll_worker()) { +		pm_runtime_mark_last_busy(connector->dev->dev); +		pm_runtime_put_autosuspend(connector->dev->dev); +	}  	return ret;  } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 00a50cc5ec9a..66cb10cdc7c3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -492,7 +492,7 @@ static int amdgpu_device_wb_init(struct amdgpu_device *adev)  		memset(&adev->wb.used, 0, sizeof(adev->wb.used));  		/* clear wb memory */ -		memset((char *)adev->wb.wb, 0, AMDGPU_MAX_WB * sizeof(uint32_t)); +		memset((char *)adev->wb.wb, 0, AMDGPU_MAX_WB * sizeof(uint32_t) * 8);  	}  	return 0; @@ -530,8 +530,9 @@ int amdgpu_device_wb_get(struct amdgpu_device *adev, u32 *wb)   */  void amdgpu_device_wb_free(struct amdgpu_device *adev, u32 wb)  { +	wb >>= 3;  	if (wb < adev->wb.num_wb) -		__clear_bit(wb >> 3, adev->wb.used); +		__clear_bit(wb, adev->wb.used);  }  /** @@ -1455,11 +1456,6 @@ static int amdgpu_device_ip_fini(struct amdgpu_device *adev)  	for (i = adev->num_ip_blocks - 1; i >= 0; i--) {  		if (!adev->ip_blocks[i].status.hw)  			continue; -		if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GMC) { -			amdgpu_free_static_csa(adev); -			amdgpu_device_wb_fini(adev); -			amdgpu_device_vram_scratch_fini(adev); -		}  		if (adev->ip_blocks[i].version->type != AMD_IP_BLOCK_TYPE_UVD &&  			adev->ip_blocks[i].version->type != AMD_IP_BLOCK_TYPE_VCE) { @@ -1486,6 +1482,13 @@ static int amdgpu_device_ip_fini(struct amdgpu_device *adev)  	for (i = adev->num_ip_blocks - 1; i >= 0; i--) {  		if (!adev->ip_blocks[i].status.sw)  			continue; + +		if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GMC) { +			amdgpu_free_static_csa(adev); +			amdgpu_device_wb_fini(adev); +			amdgpu_device_vram_scratch_fini(adev); +		} +  		r = adev->ip_blocks[i].version->funcs->sw_fini((void *)adev);  		/* XXX handle errors */  		if (r) { @@ -2060,9 +2063,12 @@ void amdgpu_device_fini(struct amdgpu_device *adev)  	DRM_INFO("amdgpu: finishing device.\n");  	adev->shutdown = true; -	if (adev->mode_info.mode_config_initialized) -		drm_crtc_force_disable_all(adev->ddev); - +	if (adev->mode_info.mode_config_initialized){ +		if (!amdgpu_device_has_dc_support(adev)) +			drm_crtc_force_disable_all(adev->ddev); +		else +			drm_atomic_helper_shutdown(adev->ddev); +	}  	amdgpu_ib_pool_fini(adev);  	amdgpu_fence_driver_fini(adev);  	amdgpu_fbdev_fini(adev); @@ -2284,14 +2290,6 @@ int amdgpu_device_resume(struct drm_device *dev, bool resume, bool fbcon)  				drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON);  			}  			drm_modeset_unlock_all(dev); -		} else { -			/* -			 * There is no equivalent atomic helper to turn on -			 * display, so we defined our own function for this, -			 * once suspend resume is supported by the atomic -			 * framework this will be reworked -			 */ -			amdgpu_dm_display_resume(adev);  		}  	} @@ -2726,7 +2724,6 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,  	if (amdgpu_device_has_dc_support(adev)) {  		if (drm_atomic_helper_resume(adev->ddev, state))  			dev_info(adev->dev, "drm resume failed:%d\n", r); -		amdgpu_dm_display_resume(adev);  	} else {  		drm_helper_resume_force_mode(adev->ddev);  	} diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c index e48b4ec88c8c..ca6c931dabfa 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c @@ -36,8 +36,6 @@ void amdgpu_gem_object_free(struct drm_gem_object *gobj)  	struct amdgpu_bo *robj = gem_to_amdgpu_bo(gobj);  	if (robj) { -		if (robj->gem_base.import_attach) -			drm_prime_gem_destroy(&robj->gem_base, robj->tbo.sg);  		amdgpu_mn_unregister(robj);  		amdgpu_bo_unref(&robj);  	} diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c index e14ab34d8262..7c2be32c5aea 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c @@ -75,7 +75,7 @@ static int amdgpu_gtt_mgr_init(struct ttm_mem_type_manager *man,  static int amdgpu_gtt_mgr_fini(struct ttm_mem_type_manager *man)  {  	struct amdgpu_gtt_mgr *mgr = man->priv; - +	spin_lock(&mgr->lock);  	drm_mm_takedown(&mgr->mm);  	spin_unlock(&mgr->lock);  	kfree(mgr); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c index 56bcd59c3399..36483e0d3c97 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c @@ -257,7 +257,8 @@ int amdgpu_irq_init(struct amdgpu_device *adev)  	r = drm_irq_install(adev->ddev, adev->ddev->pdev->irq);  	if (r) {  		adev->irq.installed = false; -		flush_work(&adev->hotplug_work); +		if (!amdgpu_device_has_dc_support(adev)) +			flush_work(&adev->hotplug_work);  		cancel_work_sync(&adev->reset_work);  		return r;  	} @@ -282,7 +283,8 @@ void amdgpu_irq_fini(struct amdgpu_device *adev)  		adev->irq.installed = false;  		if (adev->irq.msi_enabled)  			pci_disable_msi(adev->pdev); -		flush_work(&adev->hotplug_work); +		if (!amdgpu_device_has_dc_support(adev)) +			flush_work(&adev->hotplug_work);  		cancel_work_sync(&adev->reset_work);  	} diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h index 54f06c959340..2264c5c97009 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h @@ -352,6 +352,7 @@ struct amdgpu_mode_info {  	u16 firmware_flags;  	/* pointer to backlight encoder */  	struct amdgpu_encoder *bl_encoder; +	u8 bl_level; /* saved backlight level */  	struct amdgpu_audio	audio; /* audio stuff */  	int			num_crtc; /* number of crtcs */  	int			num_hpd; /* number of hpd pins */ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index 5c4c3e0d527b..1220322c1680 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -56,6 +56,8 @@ static void amdgpu_ttm_bo_destroy(struct ttm_buffer_object *tbo)  	amdgpu_bo_kunmap(bo); +	if (bo->gem_base.import_attach) +		drm_prime_gem_destroy(&bo->gem_base, bo->tbo.sg);  	drm_gem_object_release(&bo->gem_base);  	amdgpu_bo_unref(&bo->parent);  	if (!list_empty(&bo->shadow_list)) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c index 13044e66dcaf..561d3312af32 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c @@ -481,7 +481,7 @@ static ssize_t amdgpu_debugfs_ring_read(struct file *f, char __user *buf,  	result = 0;  	if (*pos < 12) { -		early[0] = amdgpu_ring_get_rptr(ring); +		early[0] = amdgpu_ring_get_rptr(ring) & ring->buf_mask;  		early[1] = amdgpu_ring_get_wptr(ring) & ring->buf_mask;  		early[2] = ring->wptr & ring->buf_mask;  		for (i = *pos / 4; i < 3 && size; i++) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c index b2eae86bf906..5c26a8e806b9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c @@ -299,12 +299,15 @@ int amdgpu_uvd_suspend(struct amdgpu_device *adev)  	cancel_delayed_work_sync(&adev->uvd.idle_work); -	for (i = 0; i < adev->uvd.max_handles; ++i) -		if (atomic_read(&adev->uvd.handles[i])) -			break; +	/* only valid for physical mode */ +	if (adev->asic_type < CHIP_POLARIS10) { +		for (i = 0; i < adev->uvd.max_handles; ++i) +			if (atomic_read(&adev->uvd.handles[i])) +				break; -	if (i == AMDGPU_MAX_UVD_HANDLES) -		return 0; +		if (i == adev->uvd.max_handles) +			return 0; +	}  	size = amdgpu_bo_size(adev->uvd.vcpu_bo);  	ptr = adev->uvd.cpu_addr; diff --git a/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c b/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c index 2af26d2da127..d702fb8e3427 100644 --- a/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c +++ b/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c @@ -34,7 +34,7 @@  #include <linux/backlight.h>  #include "bif/bif_4_1_d.h" -static u8 +u8  amdgpu_atombios_encoder_get_backlight_level_from_reg(struct amdgpu_device *adev)  {  	u8 backlight_level; @@ -48,7 +48,7 @@ amdgpu_atombios_encoder_get_backlight_level_from_reg(struct amdgpu_device *adev)  	return backlight_level;  } -static void +void  amdgpu_atombios_encoder_set_backlight_level_to_reg(struct amdgpu_device *adev,  					    u8 backlight_level)  { diff --git a/drivers/gpu/drm/amd/amdgpu/atombios_encoders.h b/drivers/gpu/drm/amd/amdgpu/atombios_encoders.h index 2bdec40515ce..f77cbdef679e 100644 --- a/drivers/gpu/drm/amd/amdgpu/atombios_encoders.h +++ b/drivers/gpu/drm/amd/amdgpu/atombios_encoders.h @@ -25,6 +25,11 @@  #define __ATOMBIOS_ENCODER_H__  u8 +amdgpu_atombios_encoder_get_backlight_level_from_reg(struct amdgpu_device *adev); +void +amdgpu_atombios_encoder_set_backlight_level_to_reg(struct amdgpu_device *adev, +						   u8 backlight_level); +u8  amdgpu_atombios_encoder_get_backlight_level(struct amdgpu_encoder *amdgpu_encoder);  void  amdgpu_atombios_encoder_set_backlight_level(struct amdgpu_encoder *amdgpu_encoder, diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c index f34bc68aadfb..022f303463fc 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c @@ -2921,6 +2921,11 @@ static int dce_v10_0_hw_fini(void *handle)  static int dce_v10_0_suspend(void *handle)  { +	struct amdgpu_device *adev = (struct amdgpu_device *)handle; + +	adev->mode_info.bl_level = +		amdgpu_atombios_encoder_get_backlight_level_from_reg(adev); +  	return dce_v10_0_hw_fini(handle);  } @@ -2929,6 +2934,9 @@ static int dce_v10_0_resume(void *handle)  	struct amdgpu_device *adev = (struct amdgpu_device *)handle;  	int ret; +	amdgpu_atombios_encoder_set_backlight_level_to_reg(adev, +							   adev->mode_info.bl_level); +  	ret = dce_v10_0_hw_init(handle);  	/* turn on the BL */ diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c index 26378bd6aba4..800a9f36ab4f 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c @@ -3047,6 +3047,11 @@ static int dce_v11_0_hw_fini(void *handle)  static int dce_v11_0_suspend(void *handle)  { +	struct amdgpu_device *adev = (struct amdgpu_device *)handle; + +	adev->mode_info.bl_level = +		amdgpu_atombios_encoder_get_backlight_level_from_reg(adev); +  	return dce_v11_0_hw_fini(handle);  } @@ -3055,6 +3060,9 @@ static int dce_v11_0_resume(void *handle)  	struct amdgpu_device *adev = (struct amdgpu_device *)handle;  	int ret; +	amdgpu_atombios_encoder_set_backlight_level_to_reg(adev, +							   adev->mode_info.bl_level); +  	ret = dce_v11_0_hw_init(handle);  	/* turn on the BL */ diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c index bd2c4f727df6..b8368f69ce1f 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c @@ -2787,6 +2787,11 @@ static int dce_v6_0_hw_fini(void *handle)  static int dce_v6_0_suspend(void *handle)  { +	struct amdgpu_device *adev = (struct amdgpu_device *)handle; + +	adev->mode_info.bl_level = +		amdgpu_atombios_encoder_get_backlight_level_from_reg(adev); +  	return dce_v6_0_hw_fini(handle);  } @@ -2795,6 +2800,9 @@ static int dce_v6_0_resume(void *handle)  	struct amdgpu_device *adev = (struct amdgpu_device *)handle;  	int ret; +	amdgpu_atombios_encoder_set_backlight_level_to_reg(adev, +							   adev->mode_info.bl_level); +  	ret = dce_v6_0_hw_init(handle);  	/* turn on the BL */ @@ -3093,7 +3101,7 @@ static int dce_v6_0_hpd_irq(struct amdgpu_device *adev,  		tmp |= DC_HPD1_INT_CONTROL__DC_HPD1_INT_ACK_MASK;  		WREG32(mmDC_HPD1_INT_CONTROL + hpd_offsets[hpd], tmp);  		schedule_work(&adev->hotplug_work); -		DRM_INFO("IH: HPD%d\n", hpd + 1); +		DRM_DEBUG("IH: HPD%d\n", hpd + 1);  	}  	return 0; diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c index c008dc030687..012e0a9ae0ff 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c @@ -2819,6 +2819,11 @@ static int dce_v8_0_hw_fini(void *handle)  static int dce_v8_0_suspend(void *handle)  { +	struct amdgpu_device *adev = (struct amdgpu_device *)handle; + +	adev->mode_info.bl_level = +		amdgpu_atombios_encoder_get_backlight_level_from_reg(adev); +  	return dce_v8_0_hw_fini(handle);  } @@ -2827,6 +2832,9 @@ static int dce_v8_0_resume(void *handle)  	struct amdgpu_device *adev = (struct amdgpu_device *)handle;  	int ret; +	amdgpu_atombios_encoder_set_backlight_level_to_reg(adev, +							   adev->mode_info.bl_level); +  	ret = dce_v8_0_hw_init(handle);  	/* turn on the BL */ diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c index a066c5eda135..a4309698e76c 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c @@ -4384,34 +4384,8 @@ static void gfx_v7_0_gpu_early_init(struct amdgpu_device *adev)  	case CHIP_KAVERI:  		adev->gfx.config.max_shader_engines = 1;  		adev->gfx.config.max_tile_pipes = 4; -		if ((adev->pdev->device == 0x1304) || -		    (adev->pdev->device == 0x1305) || -		    (adev->pdev->device == 0x130C) || -		    (adev->pdev->device == 0x130F) || -		    (adev->pdev->device == 0x1310) || -		    (adev->pdev->device == 0x1311) || -		    (adev->pdev->device == 0x131C)) { -			adev->gfx.config.max_cu_per_sh = 8; -			adev->gfx.config.max_backends_per_se = 2; -		} else if ((adev->pdev->device == 0x1309) || -			   (adev->pdev->device == 0x130A) || -			   (adev->pdev->device == 0x130D) || -			   (adev->pdev->device == 0x1313) || -			   (adev->pdev->device == 0x131D)) { -			adev->gfx.config.max_cu_per_sh = 6; -			adev->gfx.config.max_backends_per_se = 2; -		} else if ((adev->pdev->device == 0x1306) || -			   (adev->pdev->device == 0x1307) || -			   (adev->pdev->device == 0x130B) || -			   (adev->pdev->device == 0x130E) || -			   (adev->pdev->device == 0x1315) || -			   (adev->pdev->device == 0x131B)) { -			adev->gfx.config.max_cu_per_sh = 4; -			adev->gfx.config.max_backends_per_se = 1; -		} else { -			adev->gfx.config.max_cu_per_sh = 3; -			adev->gfx.config.max_backends_per_se = 1; -		} +		adev->gfx.config.max_cu_per_sh = 8; +		adev->gfx.config.max_backends_per_se = 2;  		adev->gfx.config.max_sh_per_se = 1;  		adev->gfx.config.max_texture_channel_caches = 4;  		adev->gfx.config.max_gprs = 256; diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c index 2719937e09d6..3b7e7af09ead 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c @@ -634,7 +634,7 @@ static int gmc_v9_0_late_init(void *handle)  	for(i = 0; i < AMDGPU_MAX_VMHUBS; ++i)  		BUG_ON(vm_inv_eng[i] > 16); -	if (adev->asic_type == CHIP_VEGA10) { +	if (adev->asic_type == CHIP_VEGA10 && !amdgpu_sriov_vf(adev)) {  		r = gmc_v9_0_ecc_available(adev);  		if (r == 1) {  			DRM_INFO("ECC is active.\n"); @@ -682,7 +682,10 @@ static int gmc_v9_0_mc_init(struct amdgpu_device *adev)  	adev->mc.vram_width = amdgpu_atomfirmware_get_vram_width(adev);  	if (!adev->mc.vram_width) {  		/* hbm memory channel size */ -		chansize = 128; +		if (adev->flags & AMD_IS_APU) +			chansize = 64; +		else +			chansize = 128;  		tmp = RREG32_SOC15(DF, 0, mmDF_CS_AON0_DramBaseAddress0);  		tmp &= DF_CS_AON0_DramBaseAddress0__IntLvNumChan_MASK; diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c index e92fb372bc99..91cf95a8c39c 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c @@ -238,31 +238,27 @@ static uint64_t sdma_v4_0_ring_get_rptr(struct amdgpu_ring *ring)  static uint64_t sdma_v4_0_ring_get_wptr(struct amdgpu_ring *ring)  {  	struct amdgpu_device *adev = ring->adev; -	u64 *wptr = NULL; -	uint64_t local_wptr = 0; +	u64 wptr;  	if (ring->use_doorbell) {  		/* XXX check if swapping is necessary on BE */ -		wptr = ((u64 *)&adev->wb.wb[ring->wptr_offs]); -		DRM_DEBUG("wptr/doorbell before shift == 0x%016llx\n", *wptr); -		*wptr = (*wptr) >> 2; -		DRM_DEBUG("wptr/doorbell after shift == 0x%016llx\n", *wptr); +		wptr = READ_ONCE(*((u64 *)&adev->wb.wb[ring->wptr_offs])); +		DRM_DEBUG("wptr/doorbell before shift == 0x%016llx\n", wptr);  	} else {  		u32 lowbit, highbit;  		int me = (ring == &adev->sdma.instance[0].ring) ? 0 : 1; -		wptr = &local_wptr;  		lowbit = RREG32(sdma_v4_0_get_reg_offset(adev, me, mmSDMA0_GFX_RB_WPTR)) >> 2;  		highbit = RREG32(sdma_v4_0_get_reg_offset(adev, me, mmSDMA0_GFX_RB_WPTR_HI)) >> 2;  		DRM_DEBUG("wptr [%i]high== 0x%08x low==0x%08x\n",  				me, highbit, lowbit); -		*wptr = highbit; -		*wptr = (*wptr) << 32; -		*wptr |= lowbit; +		wptr = highbit; +		wptr = wptr << 32; +		wptr |= lowbit;  	} -	return *wptr; +	return wptr >> 2;  }  /** diff --git a/drivers/gpu/drm/amd/amdgpu/si.c b/drivers/gpu/drm/amd/amdgpu/si.c index 543101d5a5ed..2095173aaabf 100644 --- a/drivers/gpu/drm/amd/amdgpu/si.c +++ b/drivers/gpu/drm/amd/amdgpu/si.c @@ -31,6 +31,7 @@  #include "amdgpu_uvd.h"  #include "amdgpu_vce.h"  #include "atom.h" +#include "amd_pcie.h"  #include "amdgpu_powerplay.h"  #include "sid.h"  #include "si_ih.h" @@ -1461,8 +1462,8 @@ static void si_pcie_gen3_enable(struct amdgpu_device *adev)  {  	struct pci_dev *root = adev->pdev->bus->self;  	int bridge_pos, gpu_pos; -	u32 speed_cntl, mask, current_data_rate; -	int ret, i; +	u32 speed_cntl, current_data_rate; +	int i;  	u16 tmp16;  	if (pci_is_root_bus(adev->pdev->bus)) @@ -1474,23 +1475,20 @@ static void si_pcie_gen3_enable(struct amdgpu_device *adev)  	if (adev->flags & AMD_IS_APU)  		return; -	ret = drm_pcie_get_speed_cap_mask(adev->ddev, &mask); -	if (ret != 0) -		return; - -	if (!(mask & (DRM_PCIE_SPEED_50 | DRM_PCIE_SPEED_80))) +	if (!(adev->pm.pcie_gen_mask & (CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2 | +					CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3)))  		return;  	speed_cntl = RREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL);  	current_data_rate = (speed_cntl & LC_CURRENT_DATA_RATE_MASK) >>  		LC_CURRENT_DATA_RATE_SHIFT; -	if (mask & DRM_PCIE_SPEED_80) { +	if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3) {  		if (current_data_rate == 2) {  			DRM_INFO("PCIE gen 3 link speeds already enabled\n");  			return;  		}  		DRM_INFO("enabling PCIE gen 3 link speeds, disable with amdgpu.pcie_gen2=0\n"); -	} else if (mask & DRM_PCIE_SPEED_50) { +	} else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2) {  		if (current_data_rate == 1) {  			DRM_INFO("PCIE gen 2 link speeds already enabled\n");  			return; @@ -1506,7 +1504,7 @@ static void si_pcie_gen3_enable(struct amdgpu_device *adev)  	if (!gpu_pos)  		return; -	if (mask & DRM_PCIE_SPEED_80) { +	if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3) {  		if (current_data_rate != 2) {  			u16 bridge_cfg, gpu_cfg;  			u16 bridge_cfg2, gpu_cfg2; @@ -1589,9 +1587,9 @@ static void si_pcie_gen3_enable(struct amdgpu_device *adev)  	pci_read_config_word(adev->pdev, gpu_pos + PCI_EXP_LNKCTL2, &tmp16);  	tmp16 &= ~0xf; -	if (mask & DRM_PCIE_SPEED_80) +	if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3)  		tmp16 |= 3; -	else if (mask & DRM_PCIE_SPEED_50) +	else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2)  		tmp16 |= 2;  	else  		tmp16 |= 1; diff --git a/drivers/gpu/drm/amd/amdgpu/si_dpm.c b/drivers/gpu/drm/amd/amdgpu/si_dpm.c index ce675a7f179a..22f0b7ff3ac9 100644 --- a/drivers/gpu/drm/amd/amdgpu/si_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/si_dpm.c @@ -26,6 +26,7 @@  #include "amdgpu_pm.h"  #include "amdgpu_dpm.h"  #include "amdgpu_atombios.h" +#include "amd_pcie.h"  #include "sid.h"  #include "r600_dpm.h"  #include "si_dpm.h" @@ -3331,29 +3332,6 @@ static void btc_apply_voltage_delta_rules(struct amdgpu_device *adev,  	}  } -static enum amdgpu_pcie_gen r600_get_pcie_gen_support(struct amdgpu_device *adev, -					       u32 sys_mask, -					       enum amdgpu_pcie_gen asic_gen, -					       enum amdgpu_pcie_gen default_gen) -{ -	switch (asic_gen) { -	case AMDGPU_PCIE_GEN1: -		return AMDGPU_PCIE_GEN1; -	case AMDGPU_PCIE_GEN2: -		return AMDGPU_PCIE_GEN2; -	case AMDGPU_PCIE_GEN3: -		return AMDGPU_PCIE_GEN3; -	default: -		if ((sys_mask & DRM_PCIE_SPEED_80) && (default_gen == AMDGPU_PCIE_GEN3)) -			return AMDGPU_PCIE_GEN3; -		else if ((sys_mask & DRM_PCIE_SPEED_50) && (default_gen == AMDGPU_PCIE_GEN2)) -			return AMDGPU_PCIE_GEN2; -		else -			return AMDGPU_PCIE_GEN1; -	} -	return AMDGPU_PCIE_GEN1; -} -  static void r600_calculate_u_and_p(u32 i, u32 r_c, u32 p_b,  			    u32 *p, u32 *u)  { @@ -5028,10 +5006,11 @@ static int si_populate_smc_acpi_state(struct amdgpu_device *adev,  							      table->ACPIState.levels[0].vddc.index,  							      &table->ACPIState.levels[0].std_vddc);  		} -		table->ACPIState.levels[0].gen2PCIE = (u8)r600_get_pcie_gen_support(adev, -										    si_pi->sys_pcie_mask, -										    si_pi->boot_pcie_gen, -										    AMDGPU_PCIE_GEN1); +		table->ACPIState.levels[0].gen2PCIE = +			(u8)amdgpu_get_pcie_gen_support(adev, +							si_pi->sys_pcie_mask, +							si_pi->boot_pcie_gen, +							AMDGPU_PCIE_GEN1);  		if (si_pi->vddc_phase_shed_control)  			si_populate_phase_shedding_value(adev, @@ -7168,10 +7147,10 @@ static void si_parse_pplib_clock_info(struct amdgpu_device *adev,  	pl->vddc = le16_to_cpu(clock_info->si.usVDDC);  	pl->vddci = le16_to_cpu(clock_info->si.usVDDCI);  	pl->flags = le32_to_cpu(clock_info->si.ulFlags); -	pl->pcie_gen = r600_get_pcie_gen_support(adev, -						 si_pi->sys_pcie_mask, -						 si_pi->boot_pcie_gen, -						 clock_info->si.ucPCIEGen); +	pl->pcie_gen = amdgpu_get_pcie_gen_support(adev, +						   si_pi->sys_pcie_mask, +						   si_pi->boot_pcie_gen, +						   clock_info->si.ucPCIEGen);  	/* patch up vddc if necessary */  	ret = si_get_leakage_voltage_from_leakage_index(adev, pl->vddc, @@ -7326,7 +7305,6 @@ static int si_dpm_init(struct amdgpu_device *adev)  	struct si_power_info *si_pi;  	struct atom_clock_dividers dividers;  	int ret; -	u32 mask;  	si_pi = kzalloc(sizeof(struct si_power_info), GFP_KERNEL);  	if (si_pi == NULL) @@ -7336,11 +7314,9 @@ static int si_dpm_init(struct amdgpu_device *adev)  	eg_pi = &ni_pi->eg;  	pi = &eg_pi->rv7xx; -	ret = drm_pcie_get_speed_cap_mask(adev->ddev, &mask); -	if (ret) -		si_pi->sys_pcie_mask = 0; -	else -		si_pi->sys_pcie_mask = mask; +	si_pi->sys_pcie_mask = +		(adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_MASK) >> +		CAIL_PCIE_LINK_SPEED_SUPPORT_SHIFT;  	si_pi->force_pcie_gen = AMDGPU_PCIE_GEN_INVALID;  	si_pi->boot_pcie_gen = si_get_current_pcie_speed(adev); diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c index b2bfedaf57f1..9bab4842cd44 100644 --- a/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c @@ -1618,7 +1618,7 @@ static const struct amdgpu_ring_funcs uvd_v6_0_enc_ring_vm_funcs = {  	.set_wptr = uvd_v6_0_enc_ring_set_wptr,  	.emit_frame_size =  		4 + /* uvd_v6_0_enc_ring_emit_pipeline_sync */ -		6 + /* uvd_v6_0_enc_ring_emit_vm_flush */ +		5 + /* uvd_v6_0_enc_ring_emit_vm_flush */  		5 + 5 + /* uvd_v6_0_enc_ring_emit_fence x2 vm fence */  		1, /* uvd_v6_0_enc_ring_insert_end */  	.emit_ib_size = 5, /* uvd_v6_0_enc_ring_emit_ib */ 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 1ce4c98385e3..63c67346d316 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -629,11 +629,13 @@ static int dm_resume(void *handle)  {  	struct amdgpu_device *adev = handle;  	struct amdgpu_display_manager *dm = &adev->dm; +	int ret = 0;  	/* power on hardware */  	dc_set_power_state(dm->dc, DC_ACPI_CM_POWER_STATE_D0); -	return 0; +	ret = amdgpu_dm_display_resume(adev); +	return ret;  }  int amdgpu_dm_display_resume(struct amdgpu_device *adev) @@ -1035,6 +1037,10 @@ static void handle_hpd_rx_irq(void *param)  			!is_mst_root_connector) {  		/* Downstream Port status changed. */  		if (dc_link_detect(dc_link, DETECT_REASON_HPDRX)) { + +			if (aconnector->fake_enable) +				aconnector->fake_enable = false; +  			amdgpu_dm_update_connector_after_detect(aconnector); @@ -2010,30 +2016,32 @@ static void update_stream_scaling_settings(const struct drm_display_mode *mode,  	dst.width = stream->timing.h_addressable;  	dst.height = stream->timing.v_addressable; -	rmx_type = dm_state->scaling; -	if (rmx_type == RMX_ASPECT || rmx_type == RMX_OFF) { -		if (src.width * dst.height < -				src.height * dst.width) { -			/* height needs less upscaling/more downscaling */ -			dst.width = src.width * -					dst.height / src.height; -		} else { -			/* width needs less upscaling/more downscaling */ -			dst.height = src.height * -					dst.width / src.width; +	if (dm_state) { +		rmx_type = dm_state->scaling; +		if (rmx_type == RMX_ASPECT || rmx_type == RMX_OFF) { +			if (src.width * dst.height < +					src.height * dst.width) { +				/* height needs less upscaling/more downscaling */ +				dst.width = src.width * +						dst.height / src.height; +			} else { +				/* width needs less upscaling/more downscaling */ +				dst.height = src.height * +						dst.width / src.width; +			} +		} else if (rmx_type == RMX_CENTER) { +			dst = src;  		} -	} else if (rmx_type == RMX_CENTER) { -		dst = src; -	} -	dst.x = (stream->timing.h_addressable - dst.width) / 2; -	dst.y = (stream->timing.v_addressable - dst.height) / 2; +		dst.x = (stream->timing.h_addressable - dst.width) / 2; +		dst.y = (stream->timing.v_addressable - dst.height) / 2; -	if (dm_state->underscan_enable) { -		dst.x += dm_state->underscan_hborder / 2; -		dst.y += dm_state->underscan_vborder / 2; -		dst.width -= dm_state->underscan_hborder; -		dst.height -= dm_state->underscan_vborder; +		if (dm_state->underscan_enable) { +			dst.x += dm_state->underscan_hborder / 2; +			dst.y += dm_state->underscan_vborder / 2; +			dst.width -= dm_state->underscan_hborder; +			dst.height -= dm_state->underscan_vborder; +		}  	}  	stream->src = src; @@ -2358,12 +2366,7 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector,  	if (aconnector == NULL) {  		DRM_ERROR("aconnector is NULL!\n"); -		goto drm_connector_null; -	} - -	if (dm_state == NULL) { -		DRM_ERROR("dm_state is NULL!\n"); -		goto dm_state_null; +		return stream;  	}  	drm_connector = &aconnector->base; @@ -2375,18 +2378,18 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector,  		 */  		if (aconnector->mst_port) {  			dm_dp_mst_dc_sink_create(drm_connector); -			goto mst_dc_sink_create_done; +			return stream;  		}  		if (create_fake_sink(aconnector)) -			goto stream_create_fail; +			return stream;  	}  	stream = dc_create_stream_for_sink(aconnector->dc_sink);  	if (stream == NULL) {  		DRM_ERROR("Failed to create stream for sink!\n"); -		goto stream_create_fail; +		return stream;  	}  	list_for_each_entry(preferred_mode, &aconnector->base.modes, head) { @@ -2412,9 +2415,12 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector,  	} else {  		decide_crtc_timing_for_drm_display_mode(  				&mode, preferred_mode, -				dm_state->scaling != RMX_OFF); +				dm_state ? (dm_state->scaling != RMX_OFF) : false);  	} +	if (!dm_state) +		drm_mode_set_crtcinfo(&mode, 0); +  	fill_stream_properties_from_drm_display_mode(stream,  			&mode, &aconnector->base);  	update_stream_scaling_settings(&mode, dm_state, stream); @@ -2424,10 +2430,8 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector,  		drm_connector,  		aconnector->dc_sink); -stream_create_fail: -dm_state_null: -drm_connector_null: -mst_dc_sink_create_done: +	update_stream_signal(stream); +  	return stream;  } @@ -2495,6 +2499,27 @@ dm_crtc_duplicate_state(struct drm_crtc *crtc)  	return &state->base;  } + +static inline int dm_set_vblank(struct drm_crtc *crtc, bool enable) +{ +	enum dc_irq_source irq_source; +	struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); +	struct amdgpu_device *adev = crtc->dev->dev_private; + +	irq_source = IRQ_TYPE_VBLANK + acrtc->otg_inst; +	return dc_interrupt_set(adev->dm.dc, irq_source, enable) ? 0 : -EBUSY; +} + +static int dm_enable_vblank(struct drm_crtc *crtc) +{ +	return dm_set_vblank(crtc, true); +} + +static void dm_disable_vblank(struct drm_crtc *crtc) +{ +	dm_set_vblank(crtc, false); +} +  /* Implemented only the options currently availible for the driver */  static const struct drm_crtc_funcs amdgpu_dm_crtc_funcs = {  	.reset = dm_crtc_reset_state, @@ -2504,6 +2529,8 @@ static const struct drm_crtc_funcs amdgpu_dm_crtc_funcs = {  	.page_flip = drm_atomic_helper_page_flip,  	.atomic_duplicate_state = dm_crtc_duplicate_state,  	.atomic_destroy_state = dm_crtc_destroy_state, +	.enable_vblank = dm_enable_vblank, +	.disable_vblank = dm_disable_vblank,  };  static enum drm_connector_status @@ -2798,7 +2825,7 @@ int amdgpu_dm_connector_mode_valid(struct drm_connector *connector,  		goto fail;  	} -	stream = dc_create_stream_for_sink(dc_sink); +	stream = create_stream_for_sink(aconnector, mode, NULL);  	if (stream == NULL) {  		DRM_ERROR("Failed to create stream for sink!\n");  		goto fail; @@ -3058,6 +3085,9 @@ static int dm_plane_atomic_check(struct drm_plane *plane,  	if (!dm_plane_state->dc_state)  		return 0; +	if (!fill_rects_from_plane_state(state, dm_plane_state->dc_state)) +		return -EINVAL; +  	if (dc_validate_plane(dc, dm_plane_state->dc_state) == DC_OK)  		return 0; @@ -3104,8 +3134,6 @@ static int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm,  	switch (aplane->base.type) {  	case DRM_PLANE_TYPE_PRIMARY: -		aplane->base.format_default = true; -  		res = drm_universal_plane_init(  				dm->adev->ddev,  				&aplane->base, @@ -4630,8 +4658,6 @@ static int dm_update_planes_state(struct dc *dc,  	bool pflip_needed  = !state->allow_modeset;  	int ret = 0; -	if (pflip_needed) -		return ret;  	/* Add new planes */  	for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, i) { @@ -4646,6 +4672,8 @@ static int dm_update_planes_state(struct dc *dc,  		/* Remove any changed/removed planes */  		if (!enable) { +			if (pflip_needed) +				continue;  			if (!old_plane_crtc)  				continue; @@ -4677,6 +4705,7 @@ static int dm_update_planes_state(struct dc *dc,  			*lock_and_validation_needed = true;  		} else { /* Add new planes */ +			struct dc_plane_state *dc_new_plane_state;  			if (drm_atomic_plane_disabling(plane->state, new_plane_state))  				continue; @@ -4690,38 +4719,50 @@ static int dm_update_planes_state(struct dc *dc,  			if (!dm_new_crtc_state->stream)  				continue; +			if (pflip_needed) +				continue;  			WARN_ON(dm_new_plane_state->dc_state); -			dm_new_plane_state->dc_state = dc_create_plane_state(dc); - -			DRM_DEBUG_DRIVER("Enabling DRM plane: %d on DRM crtc %d\n", -					plane->base.id, new_plane_crtc->base.id); - -			if (!dm_new_plane_state->dc_state) { +			dc_new_plane_state = dc_create_plane_state(dc); +			if (!dc_new_plane_state) {  				ret = -EINVAL;  				return ret;  			} +			DRM_DEBUG_DRIVER("Enabling DRM plane: %d on DRM crtc %d\n", +					plane->base.id, new_plane_crtc->base.id); +  			ret = fill_plane_attributes(  				new_plane_crtc->dev->dev_private, -				dm_new_plane_state->dc_state, +				dc_new_plane_state,  				new_plane_state,  				new_crtc_state); -			if (ret) +			if (ret) { +				dc_plane_state_release(dc_new_plane_state);  				return ret; +			} - +			/* +			 * Any atomic check errors that occur after this will +			 * not need a release. The plane state will be attached +			 * to the stream, and therefore part of the atomic +			 * state. It'll be released when the atomic state is +			 * cleaned. +			 */  			if (!dc_add_plane_to_context(  					dc,  					dm_new_crtc_state->stream, -					dm_new_plane_state->dc_state, +					dc_new_plane_state,  					dm_state->context)) { +				dc_plane_state_release(dc_new_plane_state);  				ret = -EINVAL;  				return ret;  			} +			dm_new_plane_state->dc_state = dc_new_plane_state; +  			/* Tell DC to do a full surface update every time there  			 * is a plane change. Inefficient, but works for now.  			 */ @@ -4735,6 +4776,33 @@ static int dm_update_planes_state(struct dc *dc,  	return ret;  } +static int dm_atomic_check_plane_state_fb(struct drm_atomic_state *state, +					  struct drm_crtc *crtc) +{ +	struct drm_plane *plane; +	struct drm_crtc_state *crtc_state; + +	WARN_ON(!drm_atomic_get_new_crtc_state(state, crtc)); + +	drm_for_each_plane_mask(plane, state->dev, crtc->state->plane_mask) { +		struct drm_plane_state *plane_state = +			drm_atomic_get_plane_state(state, plane); + +		if (IS_ERR(plane_state)) +			return -EDEADLK; + +		crtc_state = drm_atomic_get_crtc_state(plane_state->state, crtc); +		if (IS_ERR(crtc_state)) +			return PTR_ERR(crtc_state); + +		if (crtc->primary == plane && crtc_state->active) { +			if (!plane_state->fb) +				return -EINVAL; +		} +	} +	return 0; +} +  static int amdgpu_dm_atomic_check(struct drm_device *dev,  				  struct drm_atomic_state *state)  { @@ -4758,6 +4826,10 @@ 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) { +		ret = dm_atomic_check_plane_state_fb(state, crtc); +		if (ret) +			goto fail; +  		if (!drm_atomic_crtc_needs_modeset(new_crtc_state) &&  		    !new_crtc_state->color_mgmt_changed)  			continue; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c index 9bd142f65f9b..e1acc10e35a2 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c @@ -109,7 +109,7 @@ enum dc_edid_status dm_helpers_parse_edid_caps(  		struct cea_sad *sad = &sads[i];  		edid_caps->audio_modes[i].format_code = sad->format; -		edid_caps->audio_modes[i].channel_count = sad->channels; +		edid_caps->audio_modes[i].channel_count = sad->channels + 1;  		edid_caps->audio_modes[i].sample_rate = sad->freq;  		edid_caps->audio_modes[i].sample_size = sad->byte2;  	} diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c index 1874b6cee6af..422055080df4 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c @@ -683,10 +683,8 @@ static const struct amdgpu_irq_src_funcs dm_hpd_irq_funcs = {  void amdgpu_dm_set_irq_funcs(struct amdgpu_device *adev)  { -	if (adev->mode_info.num_crtc > 0) -		adev->crtc_irq.num_types = AMDGPU_CRTC_IRQ_VLINE1 + adev->mode_info.num_crtc; -	else -		adev->crtc_irq.num_types = 0; + +	adev->crtc_irq.num_types = adev->mode_info.num_crtc;  	adev->crtc_irq.funcs = &dm_crtc_irq_funcs;  	adev->pageflip_irq.num_types = adev->mode_info.num_crtc; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index f3d87f418d2e..93421dad21bd 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -189,6 +189,12 @@ void dm_dp_mst_dc_sink_create(struct drm_connector *connector)  			.link = aconnector->dc_link,  			.sink_signal = SIGNAL_TYPE_DISPLAY_PORT_MST }; +	/* +	 * TODO: Need to further figure out why ddc.algo is NULL while MST port exists +	 */ +	if (!aconnector->port || !aconnector->port->aux.ddc.algo) +		return; +  	edid = drm_dp_mst_get_edid(connector, &aconnector->mst_port->mst_mgr, aconnector->port);  	if (!edid) { diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 35e84ed031de..12868c769606 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1358,13 +1358,13 @@ enum dc_irq_source dc_interrupt_to_irq_source(  	return dal_irq_service_to_irq_source(dc->res_pool->irqs, src_id, ext_id);  } -void dc_interrupt_set(struct dc *dc, enum dc_irq_source src, bool enable) +bool dc_interrupt_set(struct dc *dc, enum dc_irq_source src, bool enable)  {  	if (dc == NULL) -		return; +		return false; -	dal_irq_service_set(dc->res_pool->irqs, src, enable); +	return dal_irq_service_set(dc->res_pool->irqs, src, enable);  }  void dc_interrupt_ack(struct dc *dc, enum dc_irq_source src) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index a37428271573..be5546181fa8 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1749,8 +1749,7 @@ static void enable_link_hdmi(struct pipe_ctx *pipe_ctx)  			link->link_enc,  			pipe_ctx->clock_source->id,  			display_color_depth, -			pipe_ctx->stream->signal == SIGNAL_TYPE_HDMI_TYPE_A, -			pipe_ctx->stream->signal == SIGNAL_TYPE_DVI_DUAL_LINK, +			pipe_ctx->stream->signal,  			stream->phy_pix_clk);  	if (pipe_ctx->stream->signal == SIGNAL_TYPE_HDMI_TYPE_A) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 61e8c3e02d16..639421a00ab6 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -718,7 +718,7 @@ static enum link_training_result perform_channel_equalization_sequence(  	uint32_t retries_ch_eq;  	enum dc_lane_count lane_count = lt_settings->link_settings.lane_count;  	union lane_align_status_updated dpcd_lane_status_updated = {{0}}; -	union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = {{{0}}};; +	union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = {{{0}}};  	hw_tr_pattern = get_supported_tp(link); @@ -1465,7 +1465,7 @@ void decide_link_settings(struct dc_stream_state *stream,  	/* MST doesn't perform link training for now  	 * TODO: add MST specific link training routine  	 */ -	if (is_mst_supported(link)) { +	if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {  		*link_setting = link->verified_link_cap;  		return;  	} diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 95b8dd0e53c6..4d07ffebfd31 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1360,9 +1360,6 @@ bool dc_is_stream_scaling_unchanged(  	return true;  } -/* Maximum TMDS single link pixel clock 165MHz */ -#define TMDS_MAX_PIXEL_CLOCK_IN_KHZ 165000 -  static void update_stream_engine_usage(  		struct resource_context *res_ctx,  		const struct resource_pool *pool, diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 261811e0c094..cd5819789d76 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -33,8 +33,7 @@  /*******************************************************************************   * Private functions   ******************************************************************************/ -#define TMDS_MAX_PIXEL_CLOCK_IN_KHZ_UPMOST 297000 -static void update_stream_signal(struct dc_stream_state *stream) +void update_stream_signal(struct dc_stream_state *stream)  {  	struct dc_sink *dc_sink = stream->sink; @@ -45,8 +44,9 @@ static void update_stream_signal(struct dc_stream_state *stream)  		stream->signal = dc_sink->sink_signal;  	if (dc_is_dvi_signal(stream->signal)) { -		if (stream->timing.pix_clk_khz > TMDS_MAX_PIXEL_CLOCK_IN_KHZ_UPMOST && -			stream->sink->sink_signal != SIGNAL_TYPE_DVI_SINGLE_LINK) +		if (stream->ctx->dc->caps.dual_link_dvi && +		    stream->timing.pix_clk_khz > TMDS_MAX_PIXEL_CLOCK && +		    stream->sink->sink_signal != SIGNAL_TYPE_DVI_SINGLE_LINK)  			stream->signal = SIGNAL_TYPE_DVI_DUAL_LINK;  		else  			stream->signal = SIGNAL_TYPE_DVI_SINGLE_LINK; @@ -193,44 +193,20 @@ bool dc_stream_set_cursor_attributes(  	core_dc = stream->ctx->dc;  	res_ctx = &core_dc->current_state->res_ctx; +	stream->cursor_attributes = *attributes;  	for (i = 0; i < MAX_PIPES; i++) {  		struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; -		if (pipe_ctx->stream != stream || (!pipe_ctx->plane_res.xfm && !pipe_ctx->plane_res.dpp)) +		if (pipe_ctx->stream != stream || (!pipe_ctx->plane_res.xfm && +		    !pipe_ctx->plane_res.dpp) || !pipe_ctx->plane_res.ipp)  			continue;  		if (pipe_ctx->top_pipe && pipe_ctx->plane_state != pipe_ctx->top_pipe->plane_state)  			continue; -		if (pipe_ctx->plane_res.ipp->funcs->ipp_cursor_set_attributes != NULL) -			pipe_ctx->plane_res.ipp->funcs->ipp_cursor_set_attributes( -						pipe_ctx->plane_res.ipp, attributes); - -		if (pipe_ctx->plane_res.hubp != NULL && -				pipe_ctx->plane_res.hubp->funcs->set_cursor_attributes != NULL) -			pipe_ctx->plane_res.hubp->funcs->set_cursor_attributes( -					pipe_ctx->plane_res.hubp, attributes); - -		if (pipe_ctx->plane_res.mi != NULL && -				pipe_ctx->plane_res.mi->funcs->set_cursor_attributes != NULL) -			pipe_ctx->plane_res.mi->funcs->set_cursor_attributes( -					pipe_ctx->plane_res.mi, attributes); - - -		if (pipe_ctx->plane_res.xfm != NULL && -				pipe_ctx->plane_res.xfm->funcs->set_cursor_attributes != NULL) -			pipe_ctx->plane_res.xfm->funcs->set_cursor_attributes( -				pipe_ctx->plane_res.xfm, attributes); - -		if (pipe_ctx->plane_res.dpp != NULL && -				pipe_ctx->plane_res.dpp->funcs->set_cursor_attributes != NULL) -			pipe_ctx->plane_res.dpp->funcs->set_cursor_attributes( -				pipe_ctx->plane_res.dpp, attributes->color_format); +		core_dc->hwss.set_cursor_attribute(pipe_ctx);  	} - -	stream->cursor_attributes = *attributes; -  	return true;  } @@ -254,55 +230,21 @@ bool dc_stream_set_cursor_position(  	core_dc = stream->ctx->dc;  	res_ctx = &core_dc->current_state->res_ctx; +	stream->cursor_position = *position;  	for (i = 0; i < MAX_PIPES; i++) {  		struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; -		struct input_pixel_processor *ipp = pipe_ctx->plane_res.ipp; -		struct mem_input *mi = pipe_ctx->plane_res.mi; -		struct hubp *hubp = pipe_ctx->plane_res.hubp; -		struct dpp *dpp = pipe_ctx->plane_res.dpp; -		struct dc_cursor_position pos_cpy = *position; -		struct dc_cursor_mi_param param = { -			.pixel_clk_khz = stream->timing.pix_clk_khz, -			.ref_clk_khz = core_dc->res_pool->ref_clock_inKhz, -			.viewport_x_start = pipe_ctx->plane_res.scl_data.viewport.x, -			.viewport_width = pipe_ctx->plane_res.scl_data.viewport.width, -			.h_scale_ratio = pipe_ctx->plane_res.scl_data.ratios.horz -		};  		if (pipe_ctx->stream != stream ||  				(!pipe_ctx->plane_res.mi  && !pipe_ctx->plane_res.hubp) ||  				!pipe_ctx->plane_state || -				(!pipe_ctx->plane_res.xfm && !pipe_ctx->plane_res.dpp)) -			continue; - -		if (pipe_ctx->plane_state->address.type -				== PLN_ADDR_TYPE_VIDEO_PROGRESSIVE) -			pos_cpy.enable = false; - -		if (pipe_ctx->top_pipe && pipe_ctx->plane_state != pipe_ctx->top_pipe->plane_state) -			pos_cpy.enable = false; - - -		if (ipp != NULL && ipp->funcs->ipp_cursor_set_position != NULL) -			ipp->funcs->ipp_cursor_set_position(ipp, &pos_cpy, ¶m); - -		if (mi != NULL && mi->funcs->set_cursor_position != NULL) -			mi->funcs->set_cursor_position(mi, &pos_cpy, ¶m); - -		if (!hubp) +				(!pipe_ctx->plane_res.xfm && !pipe_ctx->plane_res.dpp) || +				!pipe_ctx->plane_res.ipp)  			continue; -		if (hubp->funcs->set_cursor_position != NULL) -			hubp->funcs->set_cursor_position(hubp, &pos_cpy, ¶m); - -		if (dpp != NULL && dpp->funcs->set_cursor_position != NULL) -			dpp->funcs->set_cursor_position(dpp, &pos_cpy, ¶m, hubp->curs_attr.width); - +		core_dc->hwss.set_cursor_position(pipe_ctx);  	} -	stream->cursor_position = *position; -  	return true;  } diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index e2e3c9df79ea..d6d56611604e 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -62,6 +62,7 @@ struct dc_caps {  	bool dcc_const_color;  	bool dynamic_audio;  	bool is_apu; +	bool dual_link_dvi;  };  struct dc_dcc_surface_param { @@ -672,7 +673,7 @@ enum dc_irq_source dc_interrupt_to_irq_source(  		struct dc *dc,  		uint32_t src_id,  		uint32_t ext_id); -void dc_interrupt_set(struct dc *dc, enum dc_irq_source src, bool enable); +bool dc_interrupt_set(struct dc *dc, enum dc_irq_source src, bool enable);  void dc_interrupt_ack(struct dc *dc, enum dc_irq_source src);  enum dc_irq_source dc_get_hpd_irq_source_at_index(  		struct dc *dc, uint32_t link_index); diff --git a/drivers/gpu/drm/amd/display/dc/dc_stream.h b/drivers/gpu/drm/amd/display/dc/dc_stream.h index 01c60f11b2bd..456e4d29eadd 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_stream.h +++ b/drivers/gpu/drm/amd/display/dc/dc_stream.h @@ -237,6 +237,8 @@ enum surface_update_type dc_check_update_surfaces_for_stream(   */  struct dc_stream_state *dc_create_stream_for_sink(struct dc_sink *dc_sink); +void update_stream_signal(struct dc_stream_state *stream); +  void dc_stream_retain(struct dc_stream_state *dc_stream);  void dc_stream_release(struct dc_stream_state *dc_stream); diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h index b73db9e78437..f11f17fe08f9 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h @@ -236,6 +236,7 @@  	SR(D2VGA_CONTROL), \  	SR(D3VGA_CONTROL), \  	SR(D4VGA_CONTROL), \ +	SR(VGA_TEST_CONTROL), \  	SR(DC_IP_REQUEST_CNTL), \  	BL_REG_LIST() @@ -337,6 +338,7 @@ struct dce_hwseq_registers {  	uint32_t D2VGA_CONTROL;  	uint32_t D3VGA_CONTROL;  	uint32_t D4VGA_CONTROL; +	uint32_t VGA_TEST_CONTROL;  	/* MMHUB registers. read only. temporary hack */  	uint32_t VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32;  	uint32_t VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32; @@ -493,6 +495,12 @@ struct dce_hwseq_registers {  	HWS_SF(, DOMAIN6_PG_STATUS, DOMAIN6_PGFSM_PWR_STATUS, mask_sh), \  	HWS_SF(, DOMAIN7_PG_STATUS, DOMAIN7_PGFSM_PWR_STATUS, mask_sh), \  	HWS_SF(, DC_IP_REQUEST_CNTL, IP_REQUEST_EN, mask_sh), \ +	HWS_SF(, D1VGA_CONTROL, D1VGA_MODE_ENABLE, mask_sh),\ +	HWS_SF(, D2VGA_CONTROL, D2VGA_MODE_ENABLE, mask_sh),\ +	HWS_SF(, D3VGA_CONTROL, D3VGA_MODE_ENABLE, mask_sh),\ +	HWS_SF(, D4VGA_CONTROL, D4VGA_MODE_ENABLE, mask_sh),\ +	HWS_SF(, VGA_TEST_CONTROL, VGA_TEST_ENABLE, mask_sh),\ +	HWS_SF(, VGA_TEST_CONTROL, VGA_TEST_RENDER_START, mask_sh),\  	HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh), \  	HWS_SF(, LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, mask_sh) @@ -583,7 +591,13 @@ struct dce_hwseq_registers {  	type DCFCLK_GATE_DIS; \  	type DCHUBBUB_GLOBAL_TIMER_REFDIV; \  	type DENTIST_DPPCLK_WDIVIDER; \ -	type DENTIST_DISPCLK_WDIVIDER; +	type DENTIST_DISPCLK_WDIVIDER; \ +	type VGA_TEST_ENABLE; \ +	type VGA_TEST_RENDER_START; \ +	type D1VGA_MODE_ENABLE; \ +	type D2VGA_MODE_ENABLE; \ +	type D3VGA_MODE_ENABLE; \ +	type D4VGA_MODE_ENABLE;  struct dce_hwseq_shift {  	HWSEQ_REG_FIELD_LIST(uint8_t) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index a266e3f5e75f..e4741f1a2b01 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -82,13 +82,6 @@  #define DCE110_DIG_FE_SOURCE_SELECT_DIGF 0x20  #define DCE110_DIG_FE_SOURCE_SELECT_DIGG 0x40 -/* Minimum pixel clock, in KHz. For TMDS signal is 25.00 MHz */ -#define TMDS_MIN_PIXEL_CLOCK 25000 -/* Maximum pixel clock, in KHz. For TMDS signal is 165.00 MHz */ -#define TMDS_MAX_PIXEL_CLOCK 165000 -/* For current ASICs pixel clock - 600MHz */ -#define MAX_ENCODER_CLOCK 600000 -  enum {  	DP_MST_UPDATE_MAX_RETRY = 50  }; @@ -683,6 +676,7 @@ void dce110_link_encoder_construct(  {  	struct bp_encoder_cap_info bp_cap_info = {0};  	const struct dc_vbios_funcs *bp_funcs = init_data->ctx->dc_bios->funcs; +	enum bp_result result = BP_RESULT_OK;  	enc110->base.funcs = &dce110_lnk_enc_funcs;  	enc110->base.ctx = init_data->ctx; @@ -757,15 +751,24 @@ void dce110_link_encoder_construct(  		enc110->base.preferred_engine = ENGINE_ID_UNKNOWN;  	} +	/* default to one to mirror Windows behavior */ +	enc110->base.features.flags.bits.HDMI_6GB_EN = 1; + +	result = bp_funcs->get_encoder_cap_info(enc110->base.ctx->dc_bios, +						enc110->base.id, &bp_cap_info); +  	/* Override features with DCE-specific values */ -	if (BP_RESULT_OK == bp_funcs->get_encoder_cap_info( -			enc110->base.ctx->dc_bios, enc110->base.id, -			&bp_cap_info)) { +	if (BP_RESULT_OK == result) {  		enc110->base.features.flags.bits.IS_HBR2_CAPABLE =  				bp_cap_info.DP_HBR2_EN;  		enc110->base.features.flags.bits.IS_HBR3_CAPABLE =  				bp_cap_info.DP_HBR3_EN;  		enc110->base.features.flags.bits.HDMI_6GB_EN = bp_cap_info.HDMI_6GB_EN; +	} else { +		dm_logger_write(enc110->base.ctx->logger, LOG_WARNING, +				"%s: Failed to get encoder_cap_info from VBIOS with error code %d!\n", +				__func__, +				result);  	}  } @@ -904,8 +907,7 @@ void dce110_link_encoder_enable_tmds_output(  	struct link_encoder *enc,  	enum clock_source_id clock_source,  	enum dc_color_depth color_depth, -	bool hdmi, -	bool dual_link, +	enum signal_type signal,  	uint32_t pixel_clock)  {  	struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); @@ -919,16 +921,12 @@ void dce110_link_encoder_enable_tmds_output(  	cntl.engine_id = enc->preferred_engine;  	cntl.transmitter = enc110->base.transmitter;  	cntl.pll_id = clock_source; -	if (hdmi) { -		cntl.signal = SIGNAL_TYPE_HDMI_TYPE_A; -		cntl.lanes_number = 4; -	} else if (dual_link) { -		cntl.signal = SIGNAL_TYPE_DVI_DUAL_LINK; +	cntl.signal = signal; +	if (cntl.signal == SIGNAL_TYPE_DVI_DUAL_LINK)  		cntl.lanes_number = 8; -	} else { -		cntl.signal = SIGNAL_TYPE_DVI_SINGLE_LINK; +	else  		cntl.lanes_number = 4; -	} +  	cntl.hpd_sel = enc110->base.hpd_source;  	cntl.pixel_clock = pixel_clock; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h index 8ca9afe47a2b..0ec3433d34b6 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h @@ -210,8 +210,7 @@ void dce110_link_encoder_enable_tmds_output(  	struct link_encoder *enc,  	enum clock_source_id clock_source,  	enum dc_color_depth color_depth, -	bool hdmi, -	bool dual_link, +	enum signal_type signal,  	uint32_t pixel_clock);  /* enables DP PHY output */ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c index 3931412ab6d3..87093894ea9e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c @@ -128,23 +128,22 @@ static void set_truncation(  		return;  	}  	/* on other format-to do */ -	if (params->flags.TRUNCATE_ENABLED == 0 || -			params->flags.TRUNCATE_DEPTH == 2) +	if (params->flags.TRUNCATE_ENABLED == 0)  		return;  	/*Set truncation depth and Enable truncation*/  	REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,  				FMT_TRUNCATE_EN, 1,  				FMT_TRUNCATE_DEPTH, -				params->flags.TRUNCATE_MODE, +				params->flags.TRUNCATE_DEPTH,  				FMT_TRUNCATE_MODE, -				params->flags.TRUNCATE_DEPTH); +				params->flags.TRUNCATE_MODE);  }  /**   *	set_spatial_dither   *	1) set spatial dithering mode: pattern of seed - *	2) set spatical dithering depth: 0 for 18bpp or 1 for 24bpp + *	2) set spatial dithering depth: 0 for 18bpp or 1 for 24bpp   *	3) set random seed   *	4) set random mode   *		lfsr is reset every frame or not reset diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index 3ea43e2a9450..442dd2d93618 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -852,6 +852,7 @@ static bool construct(  	dc->caps.max_downscale_ratio = 200;  	dc->caps.i2c_speed_in_khz = 40;  	dc->caps.max_cursor_size = 128; +	dc->caps.dual_link_dvi = true;  	for (i = 0; i < pool->base.pipe_count; i++) {  		pool->base.timing_generators[i] = 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 86cdd7b4811f..6f382a3ac90f 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 @@ -688,15 +688,22 @@ void dce110_enable_stream(struct pipe_ctx *pipe_ctx)  	struct dc_crtc_timing *timing = &pipe_ctx->stream->timing;  	struct dc_link *link = pipe_ctx->stream->sink->link; -	/* 1. update AVI info frame (HDMI, DP) -	 * we always need to update info frame -	*/ +  	uint32_t active_total_with_borders;  	uint32_t early_control = 0;  	struct timing_generator *tg = pipe_ctx->stream_res.tg; -	/* TODOFPGA may change to hwss.update_info_frame */ +	/* For MST, there are multiply stream go to only one link. +	 * connect DIG back_end to front_end while enable_stream and +	 * disconnect them during disable_stream +	 * BY this, it is logic clean to separate stream and link */ +	link->link_enc->funcs->connect_dig_be_to_fe(link->link_enc, +						    pipe_ctx->stream_res.stream_enc->id, true); + +	/* update AVI info frame (HDMI, DP)*/ +	/* TODO: FPGA may change to hwss.update_info_frame */  	dce110_update_info_frame(pipe_ctx); +  	/* enable early control to avoid corruption on DP monitor*/  	active_total_with_borders =  			timing->h_addressable @@ -717,12 +724,8 @@ void dce110_enable_stream(struct pipe_ctx *pipe_ctx)  			pipe_ctx->stream_res.stream_enc->funcs->dp_audio_enable(pipe_ctx->stream_res.stream_enc);  	} -	/* For MST, there are multiply stream go to only one link. -	 * connect DIG back_end to front_end while enable_stream and -	 * disconnect them during disable_stream -	 * BY this, it is logic clean to separate stream and link */ -	link->link_enc->funcs->connect_dig_be_to_fe(link->link_enc, -						    pipe_ctx->stream_res.stream_enc->id, true); + +  } @@ -1690,9 +1693,13 @@ static void apply_min_clocks(   *  Check if FBC can be enabled   */  static bool should_enable_fbc(struct dc *dc, -			      struct dc_state *context) +			      struct dc_state *context, +			      uint32_t *pipe_idx)  { -	struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[0]; +	uint32_t i; +	struct pipe_ctx *pipe_ctx = NULL; +	struct resource_context *res_ctx = &context->res_ctx; +  	ASSERT(dc->fbc_compressor); @@ -1704,6 +1711,14 @@ static bool should_enable_fbc(struct dc *dc,  	if (context->stream_count != 1)  		return false; +	for (i = 0; i < dc->res_pool->pipe_count; i++) { +		if (res_ctx->pipe_ctx[i].stream) { +			pipe_ctx = &res_ctx->pipe_ctx[i]; +			*pipe_idx = i; +			break; +		} +	} +  	/* Only supports eDP */  	if (pipe_ctx->stream->sink->link->connector_signal != SIGNAL_TYPE_EDP)  		return false; @@ -1729,11 +1744,14 @@ static bool should_enable_fbc(struct dc *dc,  static void enable_fbc(struct dc *dc,  		       struct dc_state *context)  { -	if (should_enable_fbc(dc, context)) { +	uint32_t pipe_idx = 0; + +	if (should_enable_fbc(dc, context, &pipe_idx)) {  		/* Program GRPH COMPRESSED ADDRESS and PITCH */  		struct compr_addr_and_pitch_params params = {0, 0, 0};  		struct compressor *compr = dc->fbc_compressor; -		struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[0]; +		struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[pipe_idx]; +  		params.source_view_width = pipe_ctx->stream->timing.h_addressable;  		params.source_view_height = pipe_ctx->stream->timing.v_addressable; @@ -2915,6 +2933,49 @@ static void program_csc_matrix(struct pipe_ctx *pipe_ctx,  	}  } +void dce110_set_cursor_position(struct pipe_ctx *pipe_ctx) +{ +	struct dc_cursor_position pos_cpy = pipe_ctx->stream->cursor_position; +	struct input_pixel_processor *ipp = pipe_ctx->plane_res.ipp; +	struct mem_input *mi = pipe_ctx->plane_res.mi; +	struct dc_cursor_mi_param param = { +		.pixel_clk_khz = pipe_ctx->stream->timing.pix_clk_khz, +		.ref_clk_khz = pipe_ctx->stream->ctx->dc->res_pool->ref_clock_inKhz, +		.viewport_x_start = pipe_ctx->plane_res.scl_data.viewport.x, +		.viewport_width = pipe_ctx->plane_res.scl_data.viewport.width, +		.h_scale_ratio = pipe_ctx->plane_res.scl_data.ratios.horz +	}; + +	if (pipe_ctx->plane_state->address.type +			== PLN_ADDR_TYPE_VIDEO_PROGRESSIVE) +		pos_cpy.enable = false; + +	if (pipe_ctx->top_pipe && pipe_ctx->plane_state != pipe_ctx->top_pipe->plane_state) +		pos_cpy.enable = false; + +	if (ipp->funcs->ipp_cursor_set_position) +		ipp->funcs->ipp_cursor_set_position(ipp, &pos_cpy, ¶m); +	if (mi->funcs->set_cursor_position) +		mi->funcs->set_cursor_position(mi, &pos_cpy, ¶m); +} + +void dce110_set_cursor_attribute(struct pipe_ctx *pipe_ctx) +{ +	struct dc_cursor_attributes *attributes = &pipe_ctx->stream->cursor_attributes; + +	if (pipe_ctx->plane_res.ipp->funcs->ipp_cursor_set_attributes) +		pipe_ctx->plane_res.ipp->funcs->ipp_cursor_set_attributes( +				pipe_ctx->plane_res.ipp, attributes); + +	if (pipe_ctx->plane_res.mi->funcs->set_cursor_attributes) +		pipe_ctx->plane_res.mi->funcs->set_cursor_attributes( +				pipe_ctx->plane_res.mi, attributes); + +	if (pipe_ctx->plane_res.xfm->funcs->set_cursor_attributes) +		pipe_ctx->plane_res.xfm->funcs->set_cursor_attributes( +				pipe_ctx->plane_res.xfm, attributes); +} +  static void ready_shared_resources(struct dc *dc, struct dc_state *context) {}  static void optimize_shared_resources(struct dc *dc) {} @@ -2957,6 +3018,8 @@ static const struct hw_sequencer_funcs dce110_funcs = {  	.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, +	.set_cursor_position = dce110_set_cursor_position, +	.set_cursor_attribute = dce110_set_cursor_attribute  };  void dce110_hw_sequencer_construct(struct dc *dc) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 7c4779578fb7..00f18c485e1e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -846,6 +846,16 @@ static bool dce110_validate_bandwidth(  	return result;  } +enum dc_status dce110_validate_plane(const struct dc_plane_state *plane_state, +				     struct dc_caps *caps) +{ +	if (((plane_state->dst_rect.width * 2) < plane_state->src_rect.width) || +	    ((plane_state->dst_rect.height * 2) < plane_state->src_rect.height)) +		return DC_FAIL_SURFACE_VALIDATE; + +	return DC_OK; +} +  static bool dce110_validate_surface_sets(  		struct dc_state *context)  { @@ -869,6 +879,13 @@ static bool dce110_validate_surface_sets(  					plane->src_rect.height > 1080))  					return false; +				/* we don't have the logic to support underlay +				 * only yet so block the use case where we get +				 * NV12 plane as top layer +				 */ +				if (j == 0) +					return false; +  				/* irrespective of plane format,  				 * stream should be RGB encoded  				 */ @@ -1021,6 +1038,7 @@ static const struct resource_funcs dce110_res_pool_funcs = {  	.link_enc_create = dce110_link_encoder_create,  	.validate_guaranteed = dce110_validate_guaranteed,  	.validate_bandwidth = dce110_validate_bandwidth, +	.validate_plane = dce110_validate_plane,  	.acquire_idle_pipe_for_layer = dce110_acquire_underlay,  	.add_stream_to_ctx = dce110_add_stream_to_ctx,  	.validate_global = dce110_validate_global diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index 663e0a047a4b..98d9cd0109e1 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -1103,6 +1103,8 @@ static bool construct(  	dc->caps.max_downscale_ratio = 200;  	dc->caps.i2c_speed_in_khz = 100;  	dc->caps.max_cursor_size = 128; +	dc->caps.dual_link_dvi = true; +  	/*************************************************  	 *  Create resources                             * diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c index 57cd67359567..5aab01db28ee 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c @@ -835,6 +835,8 @@ static bool construct(  	dc->caps.max_downscale_ratio = 200;  	dc->caps.i2c_speed_in_khz = 100;  	dc->caps.max_cursor_size = 128; +	dc->caps.dual_link_dvi = true; +  	dc->debug = debug_defaults;  	/************************************************* diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index 8f2bd56f3461..25d7eb1567ae 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -793,6 +793,7 @@ static bool dce80_construct(  	dc->caps.max_downscale_ratio = 200;  	dc->caps.i2c_speed_in_khz = 40;  	dc->caps.max_cursor_size = 128; +	dc->caps.dual_link_dvi = true;  	/*************************************************  	 *  Create resources                             * 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 82572863acab..dc1e010725c1 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 @@ -238,10 +238,34 @@ static void enable_power_gating_plane(  static void disable_vga(  	struct dce_hwseq *hws)  { +	unsigned int in_vga1_mode = 0; +	unsigned int in_vga2_mode = 0; +	unsigned int in_vga3_mode = 0; +	unsigned int in_vga4_mode = 0; + +	REG_GET(D1VGA_CONTROL, D1VGA_MODE_ENABLE, &in_vga1_mode); +	REG_GET(D2VGA_CONTROL, D2VGA_MODE_ENABLE, &in_vga2_mode); +	REG_GET(D3VGA_CONTROL, D3VGA_MODE_ENABLE, &in_vga3_mode); +	REG_GET(D4VGA_CONTROL, D4VGA_MODE_ENABLE, &in_vga4_mode); + +	if (in_vga1_mode == 0 && in_vga2_mode == 0 && +			in_vga3_mode == 0 && in_vga4_mode == 0) +		return; +  	REG_WRITE(D1VGA_CONTROL, 0);  	REG_WRITE(D2VGA_CONTROL, 0);  	REG_WRITE(D3VGA_CONTROL, 0);  	REG_WRITE(D4VGA_CONTROL, 0); + +	/* HW Engineer's Notes: +	 *  During switch from vga->extended, if we set the VGA_TEST_ENABLE and +	 *  then hit the VGA_TEST_RENDER_START, then the DCHUBP timing gets updated correctly. +	 * +	 *  Then vBIOS will have it poll for the VGA_TEST_RENDER_DONE and unset +	 *  VGA_TEST_ENABLE, to leave it in the same state as before. +	 */ +	REG_UPDATE(VGA_TEST_CONTROL, VGA_TEST_ENABLE, 1); +	REG_UPDATE(VGA_TEST_CONTROL, VGA_TEST_RENDER_START, 1);  }  static void dpp_pg_control( @@ -1761,6 +1785,11 @@ static void update_dchubp_dpp(  			&pipe_ctx->plane_res.scl_data.viewport_c);  	} +	if (pipe_ctx->stream->cursor_attributes.address.quad_part != 0) { +		dc->hwss.set_cursor_position(pipe_ctx); +		dc->hwss.set_cursor_attribute(pipe_ctx); +	} +  	if (plane_state->update_flags.bits.full_update) {  		/*gamut remap*/  		program_gamut_remap(pipe_ctx); @@ -2296,7 +2325,7 @@ static bool dcn10_dummy_display_power_gating(  	return true;  } -void dcn10_update_pending_status(struct pipe_ctx *pipe_ctx) +static void dcn10_update_pending_status(struct pipe_ctx *pipe_ctx)  {  	struct dc_plane_state *plane_state = pipe_ctx->plane_state;  	struct timing_generator *tg = pipe_ctx->stream_res.tg; @@ -2316,12 +2345,46 @@ void dcn10_update_pending_status(struct pipe_ctx *pipe_ctx)  	}  } -void dcn10_update_dchub(struct dce_hwseq *hws, struct dchub_init_data *dh_data) +static void dcn10_update_dchub(struct dce_hwseq *hws, struct dchub_init_data *dh_data)  {  	if (hws->ctx->dc->res_pool->hubbub != NULL)  		hubbub1_update_dchub(hws->ctx->dc->res_pool->hubbub, dh_data);  } +static void dcn10_set_cursor_position(struct pipe_ctx *pipe_ctx) +{ +	struct dc_cursor_position pos_cpy = pipe_ctx->stream->cursor_position; +	struct hubp *hubp = pipe_ctx->plane_res.hubp; +	struct dpp *dpp = pipe_ctx->plane_res.dpp; +	struct dc_cursor_mi_param param = { +		.pixel_clk_khz = pipe_ctx->stream->timing.pix_clk_khz, +		.ref_clk_khz = pipe_ctx->stream->ctx->dc->res_pool->ref_clock_inKhz, +		.viewport_x_start = pipe_ctx->plane_res.scl_data.viewport.x, +		.viewport_width = pipe_ctx->plane_res.scl_data.viewport.width, +		.h_scale_ratio = pipe_ctx->plane_res.scl_data.ratios.horz +	}; + +	if (pipe_ctx->plane_state->address.type +			== PLN_ADDR_TYPE_VIDEO_PROGRESSIVE) +		pos_cpy.enable = false; + +	if (pipe_ctx->top_pipe && pipe_ctx->plane_state != pipe_ctx->top_pipe->plane_state) +		pos_cpy.enable = false; + +	hubp->funcs->set_cursor_position(hubp, &pos_cpy, ¶m); +	dpp->funcs->set_cursor_position(dpp, &pos_cpy, ¶m, hubp->curs_attr.width); +} + +static void dcn10_set_cursor_attribute(struct pipe_ctx *pipe_ctx) +{ +	struct dc_cursor_attributes *attributes = &pipe_ctx->stream->cursor_attributes; + +	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); +} +  static const struct hw_sequencer_funcs dcn10_funcs = {  	.program_gamut_remap = program_gamut_remap,  	.program_csc_matrix = program_csc_matrix, @@ -2362,6 +2425,8 @@ static const struct hw_sequencer_funcs dcn10_funcs = {  	.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, +	.set_cursor_position = dcn10_set_cursor_position, +	.set_cursor_attribute = dcn10_set_cursor_attribute  }; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h index 0fd329deacd8..54d8a1386142 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h @@ -123,8 +123,7 @@ struct link_encoder_funcs {  	void (*enable_tmds_output)(struct link_encoder *enc,  		enum clock_source_id clock_source,  		enum dc_color_depth color_depth, -		bool hdmi, -		bool dual_link, +		enum signal_type signal,  		uint32_t pixel_clock);  	void (*enable_dp_output)(struct link_encoder *enc,  		const struct dc_link_settings *link_settings, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 4c0aa56f7bae..379c6ecd271a 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -198,6 +198,9 @@ struct hw_sequencer_funcs {  			bool enable);  	void (*edp_wait_for_hpd_ready)(struct dc_link *link, bool power_up); +	void (*set_cursor_position)(struct pipe_ctx *pipe); +	void (*set_cursor_attribute)(struct pipe_ctx *pipe); +  };  void color_space_to_black_color( diff --git a/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c b/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c index f7e40b292dfb..d3e1923b01a8 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c @@ -217,7 +217,7 @@ bool dce110_vblank_set(  			core_dc->current_state->res_ctx.pipe_ctx[pipe_offset].stream_res.tg;  	if (enable) { -		if (!tg->funcs->arm_vert_intr(tg, 2)) { +		if (!tg || !tg->funcs->arm_vert_intr(tg, 2)) {  			DC_ERROR("Failed to get VBLANK!\n");  			return false;  		} diff --git a/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c b/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c index 57a54a7b89e5..1c079ba37c30 100644 --- a/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c @@ -42,8 +42,7 @@ static void virtual_link_encoder_enable_tmds_output(  	struct link_encoder *enc,  	enum clock_source_id clock_source,  	enum dc_color_depth color_depth, -	bool hdmi, -	bool dual_link, +	enum signal_type signal,  	uint32_t pixel_clock) {}  static void virtual_link_encoder_enable_dp_output( diff --git a/drivers/gpu/drm/amd/display/include/grph_object_ctrl_defs.h b/drivers/gpu/drm/amd/display/include/grph_object_ctrl_defs.h index 7a9b43f84a31..36bbad594267 100644 --- a/drivers/gpu/drm/amd/display/include/grph_object_ctrl_defs.h +++ b/drivers/gpu/drm/amd/display/include/grph_object_ctrl_defs.h @@ -419,11 +419,6 @@ struct bios_event_info {  	bool backlight_changed;  }; -enum { -	HDMI_PIXEL_CLOCK_IN_KHZ_297 = 297000, -	TMDS_PIXEL_CLOCK_IN_KHZ_165 = 165000 -}; -  /*   * DFS-bypass flag   */ diff --git a/drivers/gpu/drm/amd/display/include/signal_types.h b/drivers/gpu/drm/amd/display/include/signal_types.h index b5ebde642207..199c5db67cbc 100644 --- a/drivers/gpu/drm/amd/display/include/signal_types.h +++ b/drivers/gpu/drm/amd/display/include/signal_types.h @@ -26,6 +26,11 @@  #ifndef __DC_SIGNAL_TYPES_H__  #define __DC_SIGNAL_TYPES_H__ +/* Minimum pixel clock, in KHz. For TMDS signal is 25.00 MHz */ +#define TMDS_MIN_PIXEL_CLOCK 25000 +/* Maximum pixel clock, in KHz. For TMDS signal is 165.00 MHz */ +#define TMDS_MAX_PIXEL_CLOCK 165000 +  enum signal_type {  	SIGNAL_TYPE_NONE		= 0L,		/* no signal */  	SIGNAL_TYPE_DVI_SINGLE_LINK	= (1 << 0), diff --git a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c index 4c3223a4d62b..adb6e7b9280c 100644 --- a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c +++ b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c @@ -162,7 +162,7 @@ static int pp_hw_init(void *handle)  		if(hwmgr->smumgr_funcs->start_smu(pp_handle->hwmgr)) {  			pr_err("smc start failed\n");  			hwmgr->smumgr_funcs->smu_fini(pp_handle->hwmgr); -			return -EINVAL;; +			return -EINVAL;  		}  		if (ret == PP_DPM_DISABLED)  			goto exit; diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c index 41e42beff213..08e8a793714f 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c @@ -2756,10 +2756,13 @@ static int smu7_apply_state_adjust_rules(struct pp_hwmgr *hwmgr,  				    PHM_PlatformCaps_DisableMclkSwitchingForFrameLock); -	disable_mclk_switching = ((1 < info.display_count) || -				  disable_mclk_switching_for_frame_lock || -				  smu7_vblank_too_short(hwmgr, mode_info.vblank_time_us) || -				  (mode_info.refresh_rate > 120)); +	if (info.display_count == 0) +		disable_mclk_switching = false; +	else +		disable_mclk_switching = ((1 < info.display_count) || +					  disable_mclk_switching_for_frame_lock || +					  smu7_vblank_too_short(hwmgr, mode_info.vblank_time_us) || +					  (mode_info.refresh_rate > 120));  	sclk = smu7_ps->performance_levels[0].engine_clock;  	mclk = smu7_ps->performance_levels[0].memory_clock; @@ -4534,13 +4537,6 @@ static int smu7_set_power_profile_state(struct pp_hwmgr *hwmgr,  	int tmp_result, result = 0;  	uint32_t sclk_mask = 0, mclk_mask = 0; -	if (hwmgr->chip_id == CHIP_FIJI) { -		if (request->type == AMD_PP_GFX_PROFILE) -			smu7_enable_power_containment(hwmgr); -		else if (request->type == AMD_PP_COMPUTE_PROFILE) -			smu7_disable_power_containment(hwmgr); -	} -  	if (hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_AUTO)  		return -EINVAL; diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c index 2d55dabc77d4..5f9c3efb532f 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c @@ -3168,10 +3168,13 @@ static int vega10_apply_state_adjust_rules(struct pp_hwmgr *hwmgr,  	disable_mclk_switching_for_vr = PP_CAP(PHM_PlatformCaps_DisableMclkSwitchForVR);  	force_mclk_high = PP_CAP(PHM_PlatformCaps_ForceMclkHigh); -	disable_mclk_switching = (info.display_count > 1) || -				    disable_mclk_switching_for_frame_lock || -				    disable_mclk_switching_for_vr || -				    force_mclk_high; +	if (info.display_count == 0) +		disable_mclk_switching = false; +	else +		disable_mclk_switching = (info.display_count > 1) || +			disable_mclk_switching_for_frame_lock || +			disable_mclk_switching_for_vr || +			force_mclk_high;  	sclk = vega10_ps->performance_levels[0].gfx_clock;  	mclk = vega10_ps->performance_levels[0].mem_clock;  | 

