drm_kms_helper_hotplug_event(dev);
}
-#ifdef ENABLE_FBC
+#if defined(CONFIG_DRM_AMD_DC_FBC)
#include "dal_asic_id.h"
/* Allocate memory for FBC compressed data */
/* TODO: Dynamic allocation */
else
init_data.log_mask = DC_MIN_LOG_MASK;
-#ifdef ENABLE_FBC
+#if defined(CONFIG_DRM_AMD_DC_FBC)
if (adev->family == FAMILY_CZ)
amdgpu_dm_initialize_fbc(adev);
init_data.fbc_gpu_addr = adev->dm.compressor.gpu_addr;
/* Display Core create. */
adev->dm.dc = dc_create(&init_data);
- if (adev->dm.dc)
+ if (adev->dm.dc) {
DRM_INFO("Display Core initialized!\n");
- else
+ } else {
DRM_INFO("Display Core failed to initialize!\n");
+ goto error;
+ }
INIT_WORK(&adev->dm.mst_hotplug_work, hotplug_notify_work_func);
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
aconnector = to_amdgpu_dm_connector(connector);
- if (aconnector->dc_link->type == dc_connection_mst_branch) {
+ if (aconnector->dc_link->type == dc_connection_mst_branch &&
+ aconnector->mst_mgr.aux) {
DRM_DEBUG_DRIVER("DM_MST: starting TM on aconnector: %p [id: %d]\n",
aconnector, aconnector->base.base.id);
struct drm_connector *connector;
struct drm_crtc *crtc;
struct drm_crtc_state *new_crtc_state;
+ struct dm_crtc_state *dm_new_crtc_state;
+ struct drm_plane *plane;
+ struct drm_plane_state *new_plane_state;
+ struct dm_plane_state *dm_new_plane_state;
+
int ret = 0;
int i;
mutex_lock(&aconnector->hpd_lock);
dc_link_detect(aconnector->dc_link, DETECT_REASON_HPD);
+
+ if (aconnector->fake_enable && aconnector->dc_link->local_sink)
+ aconnector->fake_enable = false;
+
aconnector->dc_sink = NULL;
amdgpu_dm_update_connector_after_detect(aconnector);
mutex_unlock(&aconnector->hpd_lock);
for_each_new_crtc_in_state(adev->dm.cached_state, crtc, new_crtc_state, i)
new_crtc_state->active_changed = true;
+ /*
+ * atomic_check is expected to create the dc states. We need to release
+ * them here, since they were duplicated as part of the suspend
+ * procedure.
+ */
+ for_each_new_crtc_in_state(adev->dm.cached_state, crtc, new_crtc_state, i) {
+ dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
+ if (dm_new_crtc_state->stream) {
+ WARN_ON(kref_read(&dm_new_crtc_state->stream->refcount) > 1);
+ dc_stream_release(dm_new_crtc_state->stream);
+ dm_new_crtc_state->stream = NULL;
+ }
+ }
+
+ for_each_new_plane_in_state(adev->dm.cached_state, plane, new_plane_state, i) {
+ dm_new_plane_state = to_dm_plane_state(new_plane_state);
+ if (dm_new_plane_state->dc_state) {
+ WARN_ON(kref_read(&dm_new_plane_state->dc_state->refcount) > 1);
+ dc_plane_state_release(dm_new_plane_state->dc_state);
+ dm_new_plane_state->dc_state = NULL;
+ }
+ }
+
ret = drm_atomic_helper_resume(ddev, adev->dm.cached_state);
- drm_atomic_state_put(adev->dm.cached_state);
adev->dm.cached_state = NULL;
amdgpu_dm_irq_resume_late(adev);
}
}
-static void create_fake_sink(struct amdgpu_dm_connector *aconnector)
+static int create_fake_sink(struct amdgpu_dm_connector *aconnector)
{
struct dc_sink *sink = NULL;
struct dc_sink_init_data sink_init_data = { 0 };
sink_init_data.sink_signal = aconnector->dc_link->connector_signal;
sink = dc_sink_create(&sink_init_data);
- if (!sink)
+ if (!sink) {
DRM_ERROR("Failed to create sink!\n");
+ return -ENOMEM;
+ }
sink->sink_signal = SIGNAL_TYPE_VIRTUAL;
aconnector->fake_enable = true;
aconnector->dc_sink = sink;
aconnector->dc_link->local_sink = sink;
+
+ return 0;
}
static struct dc_stream_state *
if (aconnector->mst_port)
goto stream_create_fail;
- create_fake_sink(aconnector);
+ if (create_fake_sink(aconnector))
+ goto stream_create_fail;
}
stream = dc_create_stream_for_sink(aconnector->dc_sink);
return NULL;
state = kzalloc(sizeof(*state), GFP_KERNEL);
+ if (!state)
+ return NULL;
__drm_atomic_helper_crtc_duplicate_state(crtc, &state->base);
.link = aconnector->dc_link,
.sink_signal = SIGNAL_TYPE_VIRTUAL
};
- struct edid *edid = (struct edid *) aconnector->base.edid_blob_ptr->data;
+ struct edid *edid;
if (!aconnector->base.edid_blob_ptr ||
!aconnector->base.edid_blob_ptr->data) {
return;
}
+ edid = (struct edid *) aconnector->base.edid_blob_ptr->data;
+
aconnector->edid = edid;
aconnector->dc_em_sink = dc_link_add_remote_sink(
amdgpu_dm_connector->num_modes =
drm_add_edid_modes(connector, edid);
- drm_edid_to_eld(connector, edid);
-
amdgpu_dm_get_native_mode(connector);
} else {
amdgpu_dm_connector->num_modes = 0;
struct amdgpu_i2c_adapter *i2c;
i2c = kzalloc(sizeof(struct amdgpu_i2c_adapter), GFP_KERNEL);
+ if (!i2c)
+ return NULL;
i2c->base.owner = THIS_MODULE;
i2c->base.class = I2C_CLASS_DDC;
i2c->base.dev.parent = &adev->pdev->dev;
DRM_DEBUG_DRIVER("%s()\n", __func__);
i2c = create_i2c(link->ddc, link->link_index, &res);
+ if (!i2c) {
+ DRM_ERROR("Failed to create i2c adapter data\n");
+ return -ENOMEM;
+ }
+
aconnector->i2c = i2c;
res = i2c_add_adapter(&i2c->base);
DRM_ERROR("%s: acrtc %d, already busy\n",
__func__,
acrtc_attach->crtc_id);
- spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
/* In commit tail framework this cannot happen */
WARN_ON(1);
}
update_stream_scaling_settings(&dm_new_con_state->base.crtc->mode,
dm_new_con_state, (struct dc_stream_state *)dm_new_crtc_state->stream);
+ if (!dm_new_crtc_state->stream)
+ continue;
+
status = dc_stream_get_status(dm_new_crtc_state->stream);
WARN_ON(!status);
WARN_ON(!status->plane_count);
- if (!dm_new_crtc_state->stream)
- continue;
-
/*TODO How it works with MPO ?*/
if (!dc_commit_planes_to_stream(
dm->dc,
drm_atomic_helper_commit_hw_done(state);
if (wait_for_vblank)
- drm_atomic_helper_wait_for_vblanks(dev, state);
+ drm_atomic_helper_wait_for_flip_done(dev, state);
drm_atomic_helper_cleanup_planes(dev, state);
}
return;
disconnected_acrtc = to_amdgpu_crtc(connector->encoder->crtc);
- acrtc_state = to_dm_crtc_state(disconnected_acrtc->base.state);
+ if (!disconnected_acrtc)
+ return;
- if (!disconnected_acrtc || !acrtc_state->stream)
+ acrtc_state = to_dm_crtc_state(disconnected_acrtc->base.state);
+ if (!acrtc_state->stream)
return;
/*
}
}
- if (dc_is_stream_unchanged(new_stream, dm_old_crtc_state->stream) &&
+ if (enable && 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;
bool lock_and_validation_needed = false;
ret = drm_atomic_helper_check_modeset(dev, state);
- if (ret) {
- DRM_ERROR("Atomic state validation failed with error :%d !\n", ret);
- return ret;
- }
+ if (ret)
+ goto fail;
/*
* legacy_cursor_update should be made false for SoC's having
}
} else {
for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
- if (!drm_atomic_crtc_needs_modeset(new_crtc_state))
+ if (!drm_atomic_crtc_needs_modeset(new_crtc_state) &&
+ !new_crtc_state->color_mgmt_changed)
continue;
if (!new_crtc_state->enable)
fail:
if (ret == -EDEADLK)
- DRM_DEBUG_DRIVER("Atomic check stopped due to to deadlock.\n");
+ DRM_DEBUG_DRIVER("Atomic check stopped to avoid deadlock.\n");
else if (ret == -EINTR || ret == -EAGAIN || ret == -ERESTARTSYS)
- DRM_DEBUG_DRIVER("Atomic check stopped due to to signal.\n");
+ DRM_DEBUG_DRIVER("Atomic check stopped due to signal.\n");
else
- DRM_ERROR("Atomic check failed with err: %d \n", ret);
+ DRM_DEBUG_DRIVER("Atomic check failed with err: %d \n", ret);
return ret;
}