Merge branch 'drm-next-4.19' of git://people.freedesktop.org/~agd5f/linux into drm...
[sfrench/cifs-2.6.git] / drivers / gpu / drm / amd / display / amdgpu_dm / amdgpu_dm.c
index 3a8d6356afc2f5ed3b6306243ff1b02df4d4ce88..5fc13e71a3b514e1696e6d8e2b1a957d65b7db1b 100644 (file)
@@ -39,6 +39,9 @@
 #include "dm_helpers.h"
 #include "dm_services_types.h"
 #include "amdgpu_dm_mst_types.h"
+#if defined(CONFIG_DEBUG_FS)
+#include "amdgpu_dm_debugfs.h"
+#endif
 
 #include "ivsrcid/ivsrcid_vislands30.h"
 
@@ -57,7 +60,7 @@
 
 #include "modules/inc/mod_freesync.h"
 
-#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
+#ifdef CONFIG_X86
 #include "ivsrcid/irqsrcs_dcn_1_0.h"
 
 #include "dcn/dcn_1_0_offset.h"
@@ -347,7 +350,6 @@ static void hotplug_notify_work_func(struct work_struct *work)
        drm_kms_helper_hotplug_event(dev);
 }
 
-#if defined(CONFIG_DRM_AMD_DC_FBC)
 /* Allocate memory for FBC compressed data  */
 static void amdgpu_dm_fbc_init(struct drm_connector *connector)
 {
@@ -388,7 +390,6 @@ static void amdgpu_dm_fbc_init(struct drm_connector *connector)
        }
 
 }
-#endif
 
 
 /* Init display KMS
@@ -902,14 +903,14 @@ amdgpu_dm_update_connector_after_detect(struct amdgpu_dm_connector *aconnector)
                                (struct edid *) sink->dc_edid.raw_edid;
 
 
-                       drm_mode_connector_update_edid_property(connector,
+                       drm_connector_update_edid_property(connector,
                                        aconnector->edid);
                }
                amdgpu_dm_add_sink_to_freesync_module(connector, aconnector->edid);
 
        } else {
                amdgpu_dm_remove_sink_from_freesync_module(connector);
-               drm_mode_connector_update_edid_property(connector, NULL);
+               drm_connector_update_edid_property(connector, NULL);
                aconnector->num_modes = 0;
                aconnector->dc_sink = NULL;
                aconnector->edid = NULL;
@@ -1040,7 +1041,7 @@ static void handle_hpd_rx_irq(void *param)
        if (dc_link->type != dc_connection_mst_branch)
                mutex_lock(&aconnector->hpd_lock);
 
-       if (dc_link_handle_hpd_rx_irq(dc_link, NULL) &&
+       if (dc_link_handle_hpd_rx_irq(dc_link, NULL, NULL) &&
                        !is_mst_root_connector) {
                /* Downstream Port status changed. */
                if (dc_link_detect(dc_link, DETECT_REASON_HPDRX)) {
@@ -1191,7 +1192,7 @@ static int dce110_register_irq_handlers(struct amdgpu_device *adev)
        return 0;
 }
 
-#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
+#ifdef CONFIG_X86
 /* Register IRQ sources and initialize IRQ callbacks */
 static int dcn10_register_irq_handlers(struct amdgpu_device *adev)
 {
@@ -1525,7 +1526,7 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
                        goto fail;
                }
                break;
-#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
+#ifdef CONFIG_X86
        case CHIP_RAVEN:
                if (dcn10_register_irq_handlers(dm->adev)) {
                        DRM_ERROR("DM: Failed to initialize IRQ\n");
@@ -1534,7 +1535,7 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
                /*
                 * Temporary disable until pplib/smu interaction is implemented
                 */
-               dm->dc->debug.disable_stutter = true;
+               dm->dc->debug.disable_stutter = amdgpu_pp_feature_mask & PP_STUTTER_MODE ? false : true;
                break;
 #endif
        default:
@@ -1724,7 +1725,7 @@ static int dm_early_init(void *handle)
                adev->mode_info.num_dig = 6;
                adev->mode_info.plane_type = dm_plane_type_default;
                break;
-#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
+#ifdef CONFIG_X86
        case CHIP_RAVEN:
                adev->mode_info.num_crtc = 4;
                adev->mode_info.num_hpd = 4;
@@ -2175,6 +2176,46 @@ get_output_color_space(const struct dc_crtc_timing *dc_crtc_timing)
        return color_space;
 }
 
+static void reduce_mode_colour_depth(struct dc_crtc_timing *timing_out)
+{
+       if (timing_out->display_color_depth <= COLOR_DEPTH_888)
+               return;
+
+       timing_out->display_color_depth--;
+}
+
+static void adjust_colour_depth_from_display_info(struct dc_crtc_timing *timing_out,
+                                               const struct drm_display_info *info)
+{
+       int normalized_clk;
+       if (timing_out->display_color_depth <= COLOR_DEPTH_888)
+               return;
+       do {
+               normalized_clk = timing_out->pix_clk_khz;
+               /* YCbCr 4:2:0 requires additional adjustment of 1/2 */
+               if (timing_out->pixel_encoding == PIXEL_ENCODING_YCBCR420)
+                       normalized_clk /= 2;
+               /* Adjusting pix clock following on HDMI spec based on colour depth */
+               switch (timing_out->display_color_depth) {
+               case COLOR_DEPTH_101010:
+                       normalized_clk = (normalized_clk * 30) / 24;
+                       break;
+               case COLOR_DEPTH_121212:
+                       normalized_clk = (normalized_clk * 36) / 24;
+                       break;
+               case COLOR_DEPTH_161616:
+                       normalized_clk = (normalized_clk * 48) / 24;
+                       break;
+               default:
+                       return;
+               }
+               if (normalized_clk <= info->max_tmds_clock)
+                       return;
+               reduce_mode_colour_depth(timing_out);
+
+       } while (timing_out->display_color_depth > COLOR_DEPTH_888);
+
+}
 /*****************************************************************************/
 
 static void
@@ -2183,6 +2224,7 @@ fill_stream_properties_from_drm_display_mode(struct dc_stream_state *stream,
                                             const struct drm_connector *connector)
 {
        struct dc_crtc_timing *timing_out = &stream->timing;
+       const struct drm_display_info *info = &connector->display_info;
 
        memset(timing_out, 0, sizeof(struct dc_crtc_timing));
 
@@ -2191,8 +2233,10 @@ fill_stream_properties_from_drm_display_mode(struct dc_stream_state *stream,
        timing_out->v_border_top = 0;
        timing_out->v_border_bottom = 0;
        /* TODO: un-hardcode */
-
-       if ((connector->display_info.color_formats & DRM_COLOR_FORMAT_YCRCB444)
+       if (drm_mode_is_420_only(info, mode_in)
+                       && stream->sink->sink_signal == SIGNAL_TYPE_HDMI_TYPE_A)
+               timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR420;
+       else if ((connector->display_info.color_formats & DRM_COLOR_FORMAT_YCRCB444)
                        && stream->sink->sink_signal == SIGNAL_TYPE_HDMI_TYPE_A)
                timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR444;
        else
@@ -2228,6 +2272,8 @@ fill_stream_properties_from_drm_display_mode(struct dc_stream_state *stream,
 
        stream->out_transfer_func->type = TF_TYPE_PREDEFINED;
        stream->out_transfer_func->tf = TRANSFER_FUNCTION_SRGB;
+       if (stream->sink->sink_signal == SIGNAL_TYPE_HDMI_TYPE_A)
+               adjust_colour_depth_from_display_info(timing_out, info);
 }
 
 static void fill_audio_info(struct audio_info *audio_info,
@@ -3048,15 +3094,25 @@ static int dm_plane_helper_prepare_fb(struct drm_plane *plane,
        else
                domain = AMDGPU_GEM_DOMAIN_VRAM;
 
-       r = amdgpu_bo_pin(rbo, domain, &afb->address);
-       amdgpu_bo_unreserve(rbo);
-
+       r = amdgpu_bo_pin(rbo, domain);
        if (unlikely(r != 0)) {
                if (r != -ERESTARTSYS)
                        DRM_ERROR("Failed to pin framebuffer with error %d\n", r);
+               amdgpu_bo_unreserve(rbo);
                return r;
        }
 
+       r = amdgpu_ttm_alloc_gart(&rbo->tbo);
+       if (unlikely(r != 0)) {
+               amdgpu_bo_unpin(rbo);
+               amdgpu_bo_unreserve(rbo);
+               DRM_ERROR("%p bind failed\n", rbo);
+               return r;
+       }
+       amdgpu_bo_unreserve(rbo);
+
+       afb->address = amdgpu_bo_gpu_offset(rbo);
+
        amdgpu_bo_ref(rbo);
 
        if (dm_plane_state_new->dc_state &&
@@ -3426,12 +3482,15 @@ static int amdgpu_dm_connector_get_modes(struct drm_connector *connector)
        struct edid *edid = amdgpu_dm_connector->edid;
 
        encoder = helper->best_encoder(connector);
-       amdgpu_dm_connector_ddc_get_modes(connector, edid);
-       amdgpu_dm_connector_add_common_modes(encoder, connector);
 
-#if defined(CONFIG_DRM_AMD_DC_FBC)
+       if (!edid || !drm_edid_is_valid(edid)) {
+               drm_add_modes_noedid(connector, 640, 480);
+       } else {
+               amdgpu_dm_connector_ddc_get_modes(connector, edid);
+               amdgpu_dm_connector_add_common_modes(encoder, connector);
+       }
        amdgpu_dm_fbc_init(connector);
-#endif
+
        return amdgpu_dm_connector->num_modes;
 }
 
@@ -3450,7 +3509,6 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm,
        aconnector->base.stereo_allowed = false;
        aconnector->base.dpms = DRM_MODE_DPMS_OFF;
        aconnector->hpd.hpd = AMDGPU_HPD_NONE; /* not used */
-
        mutex_init(&aconnector->hpd_lock);
 
        /* configure support HPD hot plug connector_>polled default value is 0
@@ -3459,9 +3517,13 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm,
        switch (connector_type) {
        case DRM_MODE_CONNECTOR_HDMIA:
                aconnector->base.polled = DRM_CONNECTOR_POLL_HPD;
+               aconnector->base.ycbcr_420_allowed =
+                       link->link_enc->features.ycbcr420_supported ? true : false;
                break;
        case DRM_MODE_CONNECTOR_DisplayPort:
                aconnector->base.polled = DRM_CONNECTOR_POLL_HPD;
+               aconnector->base.ycbcr_420_allowed =
+                       link->link_enc->features.ycbcr420_supported ? true : false;
                break;
        case DRM_MODE_CONNECTOR_DVID:
                aconnector->base.polled = DRM_CONNECTOR_POLL_HPD;
@@ -3614,10 +3676,17 @@ static int amdgpu_dm_connector_init(struct amdgpu_display_manager *dm,
                link,
                link_index);
 
-       drm_mode_connector_attach_encoder(
+       drm_connector_attach_encoder(
                &aconnector->base, &aencoder->base);
 
        drm_connector_register(&aconnector->base);
+#if defined(CONFIG_DEBUG_FS)
+       res = connector_debugfs_init(aconnector);
+       if (res) {
+               DRM_ERROR("Failed to create debugfs for connector");
+               goto out_free;
+       }
+#endif
 
        if (connector_type == DRM_MODE_CONNECTOR_DisplayPort
                || connector_type == DRM_MODE_CONNECTOR_eDP)
@@ -3914,8 +3983,6 @@ static void amdgpu_dm_do_flip(struct drm_crtc *crtc,
 
        /* Flip */
        spin_lock_irqsave(&crtc->dev->event_lock, flags);
-       /* update crtc fb */
-       crtc->primary->fb = fb;
 
        WARN_ON(acrtc->pflip_status != AMDGPU_FLIP_NONE);
        WARN_ON(!acrtc_state->stream);