diff options
| author | Dave Airlie <airlied@redhat.com> | 2017-10-23 11:17:54 +1000 |
|---|---|---|
| committer | Dave Airlie <airlied@redhat.com> | 2017-10-23 11:17:54 +1000 |
| commit | af9111336071ee9378e1db70ac8f4c2b7fcd17a1 (patch) | |
| tree | 1e60c1bd032ba2bcb2e1b1d0b611195e66314bd8 /drivers/gpu | |
| parent | bd21a37d41c3b3088aeae59f54fd82de0ddb6fdd (diff) | |
| parent | 9b38bd1b8f5c874c3d1f330e0dcf4e7d84137477 (diff) | |
| download | linux-af9111336071ee9378e1db70ac8f4c2b7fcd17a1.tar.gz linux-af9111336071ee9378e1db70ac8f4c2b7fcd17a1.tar.bz2 linux-af9111336071ee9378e1db70ac8f4c2b7fcd17a1.zip | |
Merge branch 'drm-next-4.15-dc' of git://people.freedesktop.org/~agd5f/linux into drm-next
Last batch of new stuff for DC. Highlights:
- Fix some memory leaks
- S3 fixes
- Hotplug fixes
- Fix some CX multi-display issues
- MST fixes
- DML updates from the hw team
- Various code cleanups
- Misc bug fixes
* 'drm-next-4.15-dc' of git://people.freedesktop.org/~agd5f/linux: (155 commits)
drm/amd/display:: Fix NULL pointer in Raven hotplug
drm/amd/display: Fix memoryleak during S3 resume.
drm/amd/display: add hardware_planes_only to list of affected planes
drm/amd/display: Fix brace style
drm/amd/display: Remove needless cast in amdgpu_dm_connector_init()
drm/amd/display: Fix brace style in amdgpu_dm_connector_ddc_get_modes()
drm/amd/display: Tidy up dm_drm_plane_reset()
drm/amd/display: Fix indentation in create_eml_sink()
drm/amd/display: Replace block with strncpy() in fill_audio_info()
drm/amd/display: Fix brace style in amdgpu_dm_initialize_drm_device()
drm/amd/display: Simplify handle_hpd_rx_irq()
drm/amd/display: Fix brace style in dm_handle_hpd_rx_irq()
drm/amd/display: Fix brace style in amdgpu_dm_update_connector_after_detect()
drm/amd/display: Fix indentation in dm_resume()
drm/amd/display: Fix indentation in dm_suspend()
drm/amd/display: Simplify dm_late_init()
amdgpu/dc: inline dml_round_to_multiple
amdgpu/dc: drop dml_util_is_420
drm/amd/display: Add bunch of missing license headers in DML
amdgpu/dc: inline a bunch of the dml wrappers.
...
Diffstat (limited to 'drivers/gpu')
88 files changed, 13890 insertions, 6064 deletions
diff --git a/drivers/gpu/drm/amd/display/Kconfig b/drivers/gpu/drm/amd/display/Kconfig index 6d1086d0a277..ec3285f65517 100644 --- a/drivers/gpu/drm/amd/display/Kconfig +++ b/drivers/gpu/drm/amd/display/Kconfig @@ -17,6 +17,16 @@ config DRM_AMD_DC_PRE_VEGA by default. This includes Polaris, Carrizo, Tonga, Bonaire, and Hawaii. +config DRM_AMD_DC_FBC + bool "AMD FBC - Enable Frame Buffer Compression" + depends on DRM_AMD_DC + help + Choose this option if you want to use frame buffer compression + support. + This is a power optimisation feature, check its availability + on your hardware before enabling this option. + + config DRM_AMD_DC_DCN1_0 bool "DCN 1.0 Raven family" depends on DRM_AMD_DC && X86 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 8cc228ebdc9a..d0ee1b3b8b5c 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -538,9 +538,8 @@ static int detect_mst_link_for_all_connectors(struct drm_device *dev) static int dm_late_init(void *handle) { struct drm_device *dev = ((struct amdgpu_device *)handle)->ddev; - int r = detect_mst_link_for_all_connectors(dev); - return r; + return detect_mst_link_for_all_connectors(dev); } static void s3_handle_mst(struct drm_device *dev, bool suspend) @@ -599,10 +598,7 @@ static int dm_suspend(void *handle) WARN_ON(adev->dm.cached_state); adev->dm.cached_state = drm_atomic_helper_suspend(adev->ddev); - dc_set_power_state( - dm->dc, - DC_ACPI_CM_POWER_STATE_D3 - ); + dc_set_power_state(dm->dc, DC_ACPI_CM_POWER_STATE_D3); return ret; } @@ -632,10 +628,7 @@ static int dm_resume(void *handle) struct amdgpu_display_manager *dm = &adev->dm; /* power on hardware */ - dc_set_power_state( - dm->dc, - DC_ACPI_CM_POWER_STATE_D0 - ); + dc_set_power_state(dm->dc, DC_ACPI_CM_POWER_STATE_D0); return 0; } @@ -648,6 +641,11 @@ int amdgpu_dm_display_resume(struct amdgpu_device *adev) struct drm_connector *connector; struct drm_crtc *crtc; struct drm_crtc_state *new_crtc_state; + struct dm_crtc_state *dm_crtc_state; + struct drm_plane *plane; + struct drm_plane_state *plane_state; + struct dm_plane_state *dm_plane_state; + struct dm_atomic_state *cached_state; int ret = 0; int i; @@ -686,6 +684,34 @@ int amdgpu_dm_display_resume(struct amdgpu_device *adev) for_each_new_crtc_in_state(adev->dm.cached_state, crtc, new_crtc_state, i) new_crtc_state->active_changed = true; + cached_state = to_dm_atomic_state(adev->dm.cached_state); + + /* + * During suspend, the cached state is saved before all streams are + * disabled. Refresh cached state to match actual current state before + * restoring it. + */ + WARN_ON(kref_read(&cached_state->context->refcount) > 1); + dc_release_state(cached_state->context); + + for_each_new_crtc_in_state(adev->dm.cached_state, crtc, new_crtc_state, i) { + dm_crtc_state = to_dm_crtc_state(new_crtc_state); + if (dm_crtc_state->stream) { + WARN_ON(kref_read(&dm_crtc_state->stream->refcount) > 1); + dc_stream_release(dm_crtc_state->stream); + dm_crtc_state->stream = NULL; + } + } + + for_each_new_plane_in_state(adev->dm.cached_state, plane, plane_state, i) { + dm_plane_state = to_dm_plane_state(plane_state); + if (dm_plane_state->dc_state) { + WARN_ON(kref_read(&dm_plane_state->dc_state->refcount) > 1); + dc_plane_state_release(dm_plane_state->dc_state); + dm_plane_state->dc_state = NULL; + } + } + ret = drm_atomic_helper_resume(ddev, adev->dm.cached_state); drm_atomic_state_put(adev->dm.cached_state); @@ -860,9 +886,9 @@ amdgpu_dm_update_connector_after_detect(struct amdgpu_dm_connector *aconnector) connector); aconnector->dc_sink = sink; - if (sink->dc_edid.length == 0) + if (sink->dc_edid.length == 0) { aconnector->edid = NULL; - else { + } else { aconnector->edid = (struct edid *) sink->dc_edid.raw_edid; @@ -980,8 +1006,9 @@ static void dm_handle_hpd_rx_irq(struct amdgpu_dm_connector *aconnector) dpcd_bytes_to_read); new_irq_handled = false; - } else + } else { break; + } } if (process_count == max_process_count) @@ -993,20 +1020,20 @@ static void handle_hpd_rx_irq(void *param) struct amdgpu_dm_connector *aconnector = (struct amdgpu_dm_connector *)param; struct drm_connector *connector = &aconnector->base; struct drm_device *dev = connector->dev; - const struct dc_link *dc_link = aconnector->dc_link; + struct dc_link *dc_link = aconnector->dc_link; bool is_mst_root_connector = aconnector->mst_mgr.mst_state; /* TODO:Temporary add mutex to protect hpd interrupt not have a gpio * conflict, after implement i2c helper, this mutex should be * retired. */ - if (aconnector->dc_link->type != dc_connection_mst_branch) + if (dc_link->type != dc_connection_mst_branch) mutex_lock(&aconnector->hpd_lock); - if (dc_link_handle_hpd_rx_irq(aconnector->dc_link, NULL) && + if (dc_link_handle_hpd_rx_irq(dc_link, NULL) && !is_mst_root_connector) { /* Downstream Port status changed. */ - if (dc_link_detect(aconnector->dc_link, DETECT_REASON_HPDRX)) { + if (dc_link_detect(dc_link, DETECT_REASON_HPDRX)) { amdgpu_dm_update_connector_after_detect(aconnector); @@ -1018,10 +1045,10 @@ static void handle_hpd_rx_irq(void *param) } } if ((dc_link->cur_link_settings.lane_count != LANE_COUNT_UNKNOWN) || - (dc_link->type == dc_connection_mst_branch)) + (dc_link->type == dc_connection_mst_branch)) dm_handle_hpd_rx_irq(aconnector); - if (aconnector->dc_link->type != dc_connection_mst_branch) + if (dc_link->type != dc_connection_mst_branch) mutex_unlock(&aconnector->hpd_lock); } @@ -1381,9 +1408,8 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) goto fail_free_planes; aencoder = kzalloc(sizeof(*aencoder), GFP_KERNEL); - if (!aencoder) { + if (!aencoder) goto fail_free_connector; - } if (amdgpu_dm_encoder_init(dm->ddev, aencoder, i)) { DRM_ERROR("KMS: Failed to initialize encoder\n"); @@ -1754,7 +1780,9 @@ static int get_fb_info(const struct amdgpu_framebuffer *amdgpu_fb, int r = amdgpu_bo_reserve(rbo, false); if (unlikely(r)) { - DRM_ERROR("Unable to reserve buffer\n"); + // Don't show error msg. when return -ERESTARTSYS + if (r != -ERESTARTSYS) + DRM_ERROR("Unable to reserve buffer: %d\n", r); return r; } @@ -2206,11 +2234,9 @@ static void fill_audio_info(struct audio_info *audio_info, cea_revision = drm_connector->display_info.cea_rev; - while (i < AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS && - edid_caps->display_name[i]) { - audio_info->display_name[i] = edid_caps->display_name[i]; - i++; - } + strncpy(audio_info->display_name, + edid_caps->display_name, + AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS - 1); if (cea_revision >= 3) { audio_info->mode_count = edid_caps->audio_mode_count; @@ -2318,8 +2344,16 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector, drm_connector = &aconnector->base; - if (!aconnector->dc_sink) + if (!aconnector->dc_sink) { + /* + * Exclude MST from creating fake_sink + * TODO: need to enable MST into fake_sink feature + */ + if (aconnector->mst_port) + goto stream_create_fail; + create_fake_sink(aconnector); + } stream = dc_create_stream_for_sink(aconnector->dc_sink); @@ -2453,7 +2487,8 @@ amdgpu_dm_connector_detect(struct drm_connector *connector, bool force) * 2. This interface *is called* in context of user-mode ioctl. Which * makes it a bad place for *any* MST-related activit. */ - if (aconnector->base.force == DRM_FORCE_UNSPECIFIED) + if (aconnector->base.force == DRM_FORCE_UNSPECIFIED && + !aconnector->fake_enable) connected = (aconnector->dc_sink != NULL); else connected = (aconnector->base.force == DRM_FORCE_ON); @@ -2681,8 +2716,7 @@ static void create_eml_sink(struct amdgpu_dm_connector *aconnector) (edid->extensions + 1) * EDID_LENGTH, &init_params); - if (aconnector->base.force - == DRM_FORCE_ON) + if (aconnector->base.force == DRM_FORCE_ON) aconnector->dc_sink = aconnector->dc_link->local_sink ? aconnector->dc_link->local_sink : aconnector->dc_em_sink; @@ -2746,7 +2780,7 @@ int amdgpu_dm_connector_mode_valid(struct drm_connector *connector, stream->src.height = mode->vdisplay; |
