Merge tag 'drm-misc-next-2017-11-30' of git://anongit.freedesktop.org/drm/drm-misc...
[sfrench/cifs-2.6.git] / drivers / gpu / drm / amd / display / amdgpu_dm / amdgpu_dm.c
index ad98885222e690cddeca3ee11dbdd9ce2faee0bd..c324c3b76facb4d1ba3fc75a22a107df9fc353af 100644 (file)
@@ -344,7 +344,7 @@ static void hotplug_notify_work_func(struct work_struct *work)
        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 */
@@ -422,7 +422,7 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
        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;
@@ -430,10 +430,12 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
        /* 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);
 
@@ -518,7 +520,8 @@ static int detect_mst_link_for_all_connectors(struct drm_device *dev)
 
        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);
 
@@ -641,6 +644,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_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;
 
@@ -670,6 +678,10 @@ int amdgpu_dm_display_resume(struct amdgpu_device *adev)
 
                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);
@@ -679,9 +691,31 @@ 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;
 
+       /*
+        * 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);
@@ -2273,7 +2307,7 @@ decide_crtc_timing_for_drm_display_mode(struct drm_display_mode *drm_mode,
        }
 }
 
-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 };
@@ -2282,14 +2316,18 @@ static void create_fake_sink(struct amdgpu_dm_connector *aconnector)
        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 *
@@ -2323,7 +2361,8 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector,
                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);
@@ -2423,6 +2462,8 @@ dm_crtc_duplicate_state(struct drm_crtc *crtc)
                return NULL;
 
        state = kzalloc(sizeof(*state), GFP_KERNEL);
+       if (!state)
+               return NULL;
 
        __drm_atomic_helper_crtc_duplicate_state(crtc, &state->base);
 
@@ -2667,7 +2708,7 @@ static void create_eml_sink(struct amdgpu_dm_connector *aconnector)
                        .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) {
@@ -2679,6 +2720,8 @@ static void create_eml_sink(struct amdgpu_dm_connector *aconnector)
                return;
        }
 
+       edid = (struct edid *) aconnector->base.edid_blob_ptr->data;
+
        aconnector->edid = edid;
 
        aconnector->dc_em_sink = dc_link_add_remote_sink(
@@ -3290,8 +3333,6 @@ static void amdgpu_dm_connector_ddc_get_modes(struct drm_connector *connector,
                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;
@@ -3419,6 +3460,8 @@ create_i2c(struct ddc_service *ddc_service,
        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;
@@ -3449,6 +3492,11 @@ static int amdgpu_dm_connector_init(struct amdgpu_display_manager *dm,
        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);
 
@@ -3888,7 +3936,6 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
                        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);
                }
@@ -4150,13 +4197,13 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
                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,
@@ -4210,7 +4257,7 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
        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);
 }
@@ -4289,9 +4336,11 @@ void dm_restore_drm_connector_state(struct drm_device *dev,
                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;
 
        /*
@@ -4412,7 +4461,7 @@ static int dm_update_crtcs_state(struct dc *dc,
                        }
                }
 
-               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;
@@ -4647,10 +4696,8 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
        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
@@ -4668,7 +4715,8 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
                }
        } 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)
@@ -4767,11 +4815,11 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
 
 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;
 }