Revert "drm/amd/display: disable SubVP + DRR to prevent underflow"
[linux-block.git] / drivers / gpu / drm / amd / display / amdgpu_dm / amdgpu_dm.c
index 57a5fbdab8908462ae948db9be0a8b08e7d222b5..dd56e1512b0ae964f4c68c4fdb276105612c7170 100644 (file)
@@ -1646,11 +1646,6 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
        if (amdgpu_dc_feature_mask & DC_DISABLE_LTTPR_DP2_0)
                init_data.flags.allow_lttpr_non_transparent_mode.bits.DP2_0 = true;
 
-       /* Disable SubVP + DRR config by default */
-       init_data.flags.disable_subvp_drr = true;
-       if (amdgpu_dc_feature_mask & DC_ENABLE_SUBVP_DRR)
-               init_data.flags.disable_subvp_drr = false;
-
        init_data.flags.seamless_boot_edp_requested = false;
 
        if (check_seamless_boot_capability(adev)) {
@@ -1776,12 +1771,6 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
 
                dc_init_callbacks(adev->dm.dc, &init_params);
        }
-#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
-       adev->dm.secure_display_ctxs = amdgpu_dm_crtc_secure_display_create_contexts(adev);
-       if (!adev->dm.secure_display_ctxs) {
-               DRM_ERROR("amdgpu: failed to initialize secure_display_ctxs.\n");
-       }
-#endif
        if (dc_is_dmub_outbox_supported(adev->dm.dc)) {
                init_completion(&adev->dm.dmub_aux_transfer_done);
                adev->dm.dmub_notify = kzalloc(sizeof(struct dmub_notification), GFP_KERNEL);
@@ -1840,6 +1829,11 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
                goto error;
        }
 
+#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
+       adev->dm.secure_display_ctxs = amdgpu_dm_crtc_secure_display_create_contexts(adev);
+       if (!adev->dm.secure_display_ctxs)
+               DRM_ERROR("amdgpu: failed to initialize secure display contexts.\n");
+#endif
 
        DRM_DEBUG_DRIVER("KMS initialized.\n");
 
@@ -1890,7 +1884,8 @@ static void amdgpu_dm_fini(struct amdgpu_device *adev)
        if (adev->dm.dc)
                dc_deinit_callbacks(adev->dm.dc);
 
-       dc_dmub_srv_destroy(&adev->dm.dc->ctx->dmub_srv);
+       if (adev->dm.dc)
+               dc_dmub_srv_destroy(&adev->dm.dc->ctx->dmub_srv);
 
        if (dc_enable_dmub_notifications(adev->dm.dc)) {
                kfree(adev->dm.dmub_notify);
@@ -2299,9 +2294,9 @@ static int dm_late_init(void *handle)
         */
        params.min_abm_backlight = 0x28F;
        /* In the case where abm is implemented on dmcub,
-       * dmcu object will be null.
-       * ABM 2.4 and up are implemented on dmcub.
-       */
+        * dmcu object will be null.
+        * ABM 2.4 and up are implemented on dmcub.
+        */
        if (dmcu) {
                if (!dmcu_load_iram(dmcu, params))
                        return -EINVAL;
@@ -2975,30 +2970,18 @@ static struct drm_mode_config_helper_funcs amdgpu_dm_mode_config_helperfuncs = {
 static void update_connector_ext_caps(struct amdgpu_dm_connector *aconnector)
 {
        struct amdgpu_dm_backlight_caps *caps;
-       struct amdgpu_display_manager *dm;
        struct drm_connector *conn_base;
        struct amdgpu_device *adev;
-       struct dc_link *link = NULL;
        struct drm_luminance_range_info *luminance_range;
-       int i;
-
-       if (!aconnector || !aconnector->dc_link)
-               return;
 
-       link = aconnector->dc_link;
-       if (link->connector_signal != SIGNAL_TYPE_EDP)
+       if (aconnector->bl_idx == -1 ||
+           aconnector->dc_link->connector_signal != SIGNAL_TYPE_EDP)
                return;
 
        conn_base = &aconnector->base;
        adev = drm_to_adev(conn_base->dev);
-       dm = &adev->dm;
-       for (i = 0; i < dm->num_of_edps; i++) {
-               if (link == dm->backlight_link[i])
-                       break;
-       }
-       if (i >= dm->num_of_edps)
-               return;
-       caps = &dm->backlight_caps[i];
+
+       caps = &adev->dm.backlight_caps[aconnector->bl_idx];
        caps->ext_caps = &aconnector->dc_link->dpcd_sink_ext_caps;
        caps->aux_support = false;
 
@@ -3139,9 +3122,12 @@ void amdgpu_dm_update_connector_after_detect(
                                                    aconnector->edid);
                }
 
-               aconnector->timing_requested = kzalloc(sizeof(struct dc_crtc_timing), GFP_KERNEL);
-               if (!aconnector->timing_requested)
-                       dm_error("%s: failed to create aconnector->requested_timing\n", __func__);
+               if (!aconnector->timing_requested) {
+                       aconnector->timing_requested =
+                               kzalloc(sizeof(struct dc_crtc_timing), GFP_KERNEL);
+                       if (!aconnector->timing_requested)
+                               dm_error("failed to create aconnector->requested_timing\n");
+               }
 
                drm_connector_update_edid_property(connector, aconnector->edid);
                amdgpu_dm_update_freesync_caps(connector, aconnector->edid);
@@ -4189,16 +4175,18 @@ static const struct backlight_ops amdgpu_dm_backlight_ops = {
 };
 
 static void
-amdgpu_dm_register_backlight_device(struct amdgpu_display_manager *dm)
+amdgpu_dm_register_backlight_device(struct amdgpu_dm_connector *aconnector)
 {
-       char bl_name[16];
+       struct drm_device *drm = aconnector->base.dev;
+       struct amdgpu_display_manager *dm = &drm_to_adev(drm)->dm;
        struct backlight_properties props = { 0 };
+       char bl_name[16];
 
-       amdgpu_dm_update_backlight_caps(dm, dm->num_of_edps);
-       dm->brightness[dm->num_of_edps] = AMDGPU_MAX_BL_LEVEL;
+       if (aconnector->bl_idx == -1)
+               return;
 
        if (!acpi_video_backlight_use_native()) {
-               drm_info(adev_to_drm(dm->adev), "Skipping amdgpu DM backlight registration\n");
+               drm_info(drm, "Skipping amdgpu DM backlight registration\n");
                /* Try registering an ACPI video backlight device instead. */
                acpi_video_register_backlight();
                return;
@@ -4209,17 +4197,15 @@ amdgpu_dm_register_backlight_device(struct amdgpu_display_manager *dm)
        props.type = BACKLIGHT_RAW;
 
        snprintf(bl_name, sizeof(bl_name), "amdgpu_bl%d",
-                adev_to_drm(dm->adev)->primary->index + dm->num_of_edps);
+                drm->primary->index + aconnector->bl_idx);
 
-       dm->backlight_dev[dm->num_of_edps] = backlight_device_register(bl_name,
-                                                                      adev_to_drm(dm->adev)->dev,
-                                                                      dm,
-                                                                      &amdgpu_dm_backlight_ops,
-                                                                      &props);
+       dm->backlight_dev[aconnector->bl_idx] =
+               backlight_device_register(bl_name, aconnector->base.kdev, dm,
+                                         &amdgpu_dm_backlight_ops, &props);
 
-       if (IS_ERR(dm->backlight_dev[dm->num_of_edps])) {
+       if (IS_ERR(dm->backlight_dev[aconnector->bl_idx])) {
                DRM_ERROR("DM: Backlight registration failed!\n");
-               dm->backlight_dev[dm->num_of_edps] = NULL;
+               dm->backlight_dev[aconnector->bl_idx] = NULL;
        } else
                DRM_DEBUG_DRIVER("DM: Registered Backlight device: %s\n", bl_name);
 }
@@ -4265,9 +4251,10 @@ static int initialize_plane(struct amdgpu_display_manager *dm,
 }
 
 
-static void register_backlight_device(struct amdgpu_display_manager *dm,
-                                     struct dc_link *link)
+static void setup_backlight_device(struct amdgpu_display_manager *dm,
+                                  struct amdgpu_dm_connector *aconnector)
 {
+       struct dc_link *link = aconnector->dc_link;
        int bl_idx = dm->num_of_edps;
 
        if (!(link->connector_signal & (SIGNAL_TYPE_EDP | SIGNAL_TYPE_LVDS)) ||
@@ -4279,12 +4266,14 @@ static void register_backlight_device(struct amdgpu_display_manager *dm,
                return;
        }
 
-       amdgpu_dm_register_backlight_device(dm);
-       if (!dm->backlight_dev[bl_idx])
-               return;
+       aconnector->bl_idx = bl_idx;
 
+       amdgpu_dm_update_backlight_caps(dm, bl_idx);
+       dm->brightness[bl_idx] = AMDGPU_MAX_BL_LEVEL;
        dm->backlight_link[bl_idx] = link;
        dm->num_of_edps++;
+
+       update_connector_ext_caps(aconnector);
 }
 
 static void amdgpu_set_panel_orientation(struct drm_connector *connector);
@@ -4464,10 +4453,7 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
 
                        if (ret) {
                                amdgpu_dm_update_connector_after_detect(aconnector);
-                               register_backlight_device(dm, link);
-
-                               if (dm->num_of_edps)
-                                       update_connector_ext_caps(aconnector);
+                               setup_backlight_device(dm, aconnector);
 
                                if (psr_feature_enabled)
                                        amdgpu_dm_set_psr_caps(link);
@@ -6243,10 +6229,8 @@ static void amdgpu_dm_connector_unregister(struct drm_connector *connector)
 static void amdgpu_dm_connector_destroy(struct drm_connector *connector)
 {
        struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);
-       const struct dc_link *link = aconnector->dc_link;
        struct amdgpu_device *adev = drm_to_adev(connector->dev);
        struct amdgpu_display_manager *dm = &adev->dm;
-       int i;
 
        /*
         * Call only if mst_mgr was initialized before since it's not done
@@ -6255,11 +6239,9 @@ static void amdgpu_dm_connector_destroy(struct drm_connector *connector)
        if (aconnector->mst_mgr.dev)
                drm_dp_mst_topology_mgr_destroy(&aconnector->mst_mgr);
 
-       for (i = 0; i < dm->num_of_edps; i++) {
-               if ((link == dm->backlight_link[i]) && dm->backlight_dev[i]) {
-                       backlight_device_unregister(dm->backlight_dev[i]);
-                       dm->backlight_dev[i] = NULL;
-               }
+       if (aconnector->bl_idx != -1) {
+               backlight_device_unregister(dm->backlight_dev[aconnector->bl_idx]);
+               dm->backlight_dev[aconnector->bl_idx] = NULL;
        }
 
        if (aconnector->dc_em_sink)
@@ -6341,6 +6323,8 @@ amdgpu_dm_connector_late_register(struct drm_connector *connector)
                to_amdgpu_dm_connector(connector);
        int r;
 
+       amdgpu_dm_register_backlight_device(amdgpu_dm_connector);
+
        if ((connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort) ||
            (connector->connector_type == DRM_MODE_CONNECTOR_eDP)) {
                amdgpu_dm_connector->dm_dp_aux.aux.dev = connector->kdev;
@@ -6356,6 +6340,31 @@ amdgpu_dm_connector_late_register(struct drm_connector *connector)
        return 0;
 }
 
+void amdgpu_dm_connector_funcs_force(struct drm_connector *connector)
+{
+       struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);
+       struct dc_link *dc_link = aconnector->dc_link;
+       struct dc_sink *dc_em_sink = aconnector->dc_em_sink;
+       struct edid *edid;
+
+       if (!connector->edid_override)
+               return;
+
+       drm_edid_override_connector_update(&aconnector->base);
+       edid = aconnector->base.edid_blob_ptr->data;
+       aconnector->edid = edid;
+
+       /* Update emulated (virtual) sink's EDID */
+       if (dc_em_sink && dc_link) {
+               memset(&dc_em_sink->edid_caps, 0, sizeof(struct dc_edid_caps));
+               memmove(dc_em_sink->dc_edid.raw_edid, edid, (edid->extensions + 1) * EDID_LENGTH);
+               dm_helpers_parse_edid_caps(
+                       dc_link,
+                       &dc_em_sink->dc_edid,
+                       &dc_em_sink->edid_caps);
+       }
+}
+
 static const struct drm_connector_funcs amdgpu_dm_connector_funcs = {
        .reset = amdgpu_dm_connector_funcs_reset,
        .detect = amdgpu_dm_connector_detect,
@@ -6366,7 +6375,8 @@ static const struct drm_connector_funcs amdgpu_dm_connector_funcs = {
        .atomic_set_property = amdgpu_dm_connector_atomic_set_property,
        .atomic_get_property = amdgpu_dm_connector_atomic_get_property,
        .late_register = amdgpu_dm_connector_late_register,
-       .early_unregister = amdgpu_dm_connector_unregister
+       .early_unregister = amdgpu_dm_connector_unregister,
+       .force = amdgpu_dm_connector_funcs_force
 };
 
 static int get_modes(struct drm_connector *connector)
@@ -6383,11 +6393,20 @@ static void create_eml_sink(struct amdgpu_dm_connector *aconnector)
        struct edid *edid;
 
        if (!aconnector->base.edid_blob_ptr) {
-               DRM_ERROR("No EDID firmware found on connector: %s ,forcing to OFF!\n",
-                               aconnector->base.name);
+               /* if connector->edid_override valid, pass
+                * it to edid_override to edid_blob_ptr
+                */
+               int count;
 
-               aconnector->base.force = DRM_FORCE_OFF;
-               return;
+               count = drm_edid_override_connector_update(&aconnector->base);
+
+               if (!aconnector->base.edid_blob_ptr) {
+                       DRM_ERROR("No EDID firmware found on connector: %s ,forcing to OFF!\n",
+                                       aconnector->base.name);
+
+                       aconnector->base.force = DRM_FORCE_OFF;
+                       return;
+               }
        }
 
        edid = (struct edid *) aconnector->base.edid_blob_ptr->data;
@@ -7105,13 +7124,13 @@ static uint add_fs_modes(struct amdgpu_dm_connector *aconnector)
        /* Standard FPS values
         *
         * 23.976       - TV/NTSC
-        * 24           - Cinema
-        * 25           - TV/PAL
+        * 24           - Cinema
+        * 25           - TV/PAL
         * 29.97        - TV/NTSC
-        * 30           - TV/NTSC
-        * 48           - Cinema HFR
-        * 50           - TV/PAL
-        * 60           - Commonly used
+        * 30           - TV/NTSC
+        * 48           - Cinema HFR
+        * 50           - TV/PAL
+        * 60           - Commonly used
         * 48,72,96,120 - Multiples of 24
         */
        static const u32 common_rates[] = {
@@ -7229,6 +7248,7 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm,
                aconnector->base.funcs->reset(&aconnector->base);
 
        aconnector->connector_id = link_index;
+       aconnector->bl_idx = -1;
        aconnector->dc_link = link;
        aconnector->base.interlace_allowed = false;
        aconnector->base.doublescan_allowed = false;
@@ -7739,7 +7759,7 @@ static void update_freesync_state_on_stream(
                return;
 
        spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags);
-        vrr_params = acrtc->dm_irq_params.vrr_params;
+       vrr_params = acrtc->dm_irq_params.vrr_params;
 
        if (surface) {
                mod_freesync_handle_preflip(
@@ -7910,6 +7930,13 @@ static void amdgpu_dm_commit_cursors(struct drm_atomic_state *state)
                        amdgpu_dm_plane_handle_cursor_update(plane, old_plane_state);
 }
 
+static inline uint32_t get_mem_type(struct drm_framebuffer *fb)
+{
+       struct amdgpu_bo *abo = gem_to_amdgpu_bo(fb->obj[0]);
+
+       return abo->tbo.resource ? abo->tbo.resource->mem_type : 0;
+}
+
 static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
                                    struct dc_state *dc_state,
                                    struct drm_device *dev,
@@ -7984,6 +8011,8 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
                        continue;
 
                dc_plane = dm_new_plane_state->dc_state;
+               if (!dc_plane)
+                       continue;
 
                bundle->surface_updates[planes_count].surface = dc_plane;
                if (new_pcrtc_state->color_mgmt_changed) {
@@ -8050,11 +8079,13 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
 
                /*
                 * Only allow immediate flips for fast updates that don't
-                * change FB pitch, DCC state, rotation or mirroing.
+                * change memory domain, FB pitch, DCC state, rotation or
+                * mirroring.
                 */
                bundle->flip_addrs[planes_count].flip_immediate =
                        crtc->state->async_flip &&
-                       acrtc_state->update_type == UPDATE_TYPE_FAST;
+                       acrtc_state->update_type == UPDATE_TYPE_FAST &&
+                       get_mem_type(old_plane_state->fb) == get_mem_type(fb);
 
                timestamp_ns = ktime_get_ns();
                bundle->flip_addrs[planes_count].flip_timestamp_in_us = div_u64(timestamp_ns, 1000);
@@ -8320,7 +8351,7 @@ static void amdgpu_dm_commit_audio(struct drm_device *dev,
                if (!drm_atomic_crtc_needs_modeset(new_crtc_state))
                        continue;
 
-       notify:
+notify:
                aconnector = to_amdgpu_dm_connector(connector);
 
                mutex_lock(&adev->dm.audio_lock);
@@ -8566,6 +8597,9 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
                struct amdgpu_crtc *acrtc = to_amdgpu_crtc(dm_new_con_state->base.crtc);
                struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);
 
+               if (!adev->dm.hdcp_workqueue)
+                       continue;
+
                pr_debug("[HDCP_DM] -------------- i : %x ----------\n", i);
 
                if (!connector)
@@ -8614,6 +8648,9 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
                struct amdgpu_crtc *acrtc = to_amdgpu_crtc(dm_new_con_state->base.crtc);
                struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);
 
+               if (!adev->dm.hdcp_workqueue)
+                       continue;
+
                new_crtc_state = NULL;
                old_crtc_state = NULL;
 
@@ -9336,7 +9373,7 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm,
 skip_modeset:
        /* Release extra reference */
        if (new_stream)
-                dc_stream_release(new_stream);
+               dc_stream_release(new_stream);
 
        /*
         * We want to do dc stream updates that do not require a
@@ -9632,8 +9669,9 @@ static int dm_update_plane_state(struct dc *dc,
                        return -EINVAL;
                }
 
+               if (dm_old_plane_state->dc_state)
+                       dc_plane_state_release(dm_old_plane_state->dc_state);
 
-               dc_plane_state_release(dm_old_plane_state->dc_state);
                dm_new_plane_state->dc_state = NULL;
 
                *lock_and_validation_needed = true;
@@ -10170,6 +10208,7 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
                ret = compute_mst_dsc_configs_for_state(state, dm_state->context, vars);
                if (ret) {
                        DRM_DEBUG_DRIVER("compute_mst_dsc_configs_for_state() failed\n");
+                       ret = -EINVAL;
                        goto fail;
                }
 
@@ -10317,7 +10356,7 @@ static bool dm_edid_parser_send_cea(struct amdgpu_display_manager *dm,
        input->cea_total_length = total_length;
        memcpy(input->payload, data, length);
 
-       res = dc_dmub_srv_cmd_with_reply_data(dm->dc->ctx->dmub_srv, &cmd);
+       res = dm_execute_dmub_cmd(dm->dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY);
        if (!res) {
                DRM_ERROR("EDID CEA parser failed\n");
                return false;
@@ -10670,7 +10709,7 @@ int amdgpu_dm_process_dmub_aux_transfer_sync(
        if (!dc_process_dmub_aux_transfer_async(ctx->dc, link_index, payload)) {
                *operation_result = AUX_RET_ERROR_ENGINE_ACQUIRE;
                goto out;
-       }
+       }
 
        if (!wait_for_completion_timeout(&adev->dm.dmub_aux_transfer_done, 10 * HZ)) {
                DRM_ERROR("wait_for_completion_timeout timeout!");
@@ -10767,3 +10806,13 @@ bool check_seamless_boot_capability(struct amdgpu_device *adev)
 
        return false;
 }
+
+bool dm_execute_dmub_cmd(const struct dc_context *ctx, union dmub_rb_cmd *cmd, enum dm_dmub_wait_type wait_type)
+{
+       return dc_dmub_srv_cmd_run(ctx->dmub_srv, cmd, wait_type);
+}
+
+bool dm_execute_dmub_cmd_list(const struct dc_context *ctx, unsigned int count, union dmub_rb_cmd *cmd, enum dm_dmub_wait_type wait_type)
+{
+       return dc_dmub_srv_cmd_run_list(ctx->dmub_srv, count, cmd, wait_type);
+}