Merge tag 'usb-4.9-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
[cascardo/linux.git] / drivers / gpu / drm / amd / amdgpu / dce_v10_0.c
index c1b04e9..4108c68 100644 (file)
@@ -221,7 +221,7 @@ static bool dce_v10_0_is_counter_moving(struct amdgpu_device *adev, int crtc)
  */
 static void dce_v10_0_vblank_wait(struct amdgpu_device *adev, int crtc)
 {
-       unsigned i = 0;
+       unsigned i = 100;
 
        if (crtc >= adev->mode_info.num_crtc)
                return;
@@ -233,14 +233,16 @@ static void dce_v10_0_vblank_wait(struct amdgpu_device *adev, int crtc)
         * wait for another frame.
         */
        while (dce_v10_0_is_in_vblank(adev, crtc)) {
-               if (i++ % 100 == 0) {
+               if (i++ == 100) {
+                       i = 0;
                        if (!dce_v10_0_is_counter_moving(adev, crtc))
                                break;
                }
        }
 
        while (!dce_v10_0_is_in_vblank(adev, crtc)) {
-               if (i++ % 100 == 0) {
+               if (i++ == 100) {
+                       i = 0;
                        if (!dce_v10_0_is_counter_moving(adev, crtc))
                                break;
                }
@@ -425,16 +427,6 @@ static void dce_v10_0_hpd_init(struct amdgpu_device *adev)
        list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
                struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
 
-               if (connector->connector_type == DRM_MODE_CONNECTOR_eDP ||
-                   connector->connector_type == DRM_MODE_CONNECTOR_LVDS) {
-                       /* don't try to enable hpd on eDP or LVDS avoid breaking the
-                        * aux dp channel on imac and help (but not completely fix)
-                        * https://bugzilla.redhat.com/show_bug.cgi?id=726143
-                        * also avoid interrupt storms during dpms.
-                        */
-                       continue;
-               }
-
                switch (amdgpu_connector->hpd.hpd) {
                case AMDGPU_HPD_1:
                        idx = 0;
@@ -458,6 +450,19 @@ static void dce_v10_0_hpd_init(struct amdgpu_device *adev)
                        continue;
                }
 
+               if (connector->connector_type == DRM_MODE_CONNECTOR_eDP ||
+                   connector->connector_type == DRM_MODE_CONNECTOR_LVDS) {
+                       /* don't try to enable hpd on eDP or LVDS avoid breaking the
+                        * aux dp channel on imac and help (but not completely fix)
+                        * https://bugzilla.redhat.com/show_bug.cgi?id=726143
+                        * also avoid interrupt storms during dpms.
+                        */
+                       tmp = RREG32(mmDC_HPD_INT_CONTROL + hpd_offsets[idx]);
+                       tmp = REG_SET_FIELD(tmp, DC_HPD_INT_CONTROL, DC_HPD_INT_EN, 0);
+                       WREG32(mmDC_HPD_INT_CONTROL + hpd_offsets[idx], tmp);
+                       continue;
+               }
+
                tmp = RREG32(mmDC_HPD_CONTROL + hpd_offsets[idx]);
                tmp = REG_SET_FIELD(tmp, DC_HPD_CONTROL, DC_HPD_EN, 1);
                WREG32(mmDC_HPD_CONTROL + hpd_offsets[idx], tmp);
@@ -646,8 +651,8 @@ static void dce_v10_0_resume_mc_access(struct amdgpu_device *adev,
 
                if (save->crtc_enabled[i]) {
                        tmp = RREG32(mmMASTER_UPDATE_MODE + crtc_offsets[i]);
-                       if (REG_GET_FIELD(tmp, MASTER_UPDATE_MODE, MASTER_UPDATE_MODE) != 3) {
-                               tmp = REG_SET_FIELD(tmp, MASTER_UPDATE_MODE, MASTER_UPDATE_MODE, 3);
+                       if (REG_GET_FIELD(tmp, MASTER_UPDATE_MODE, MASTER_UPDATE_MODE) != 0) {
+                               tmp = REG_SET_FIELD(tmp, MASTER_UPDATE_MODE, MASTER_UPDATE_MODE, 0);
                                WREG32(mmMASTER_UPDATE_MODE + crtc_offsets[i], tmp);
                        }
                        tmp = RREG32(mmGRPH_UPDATE + crtc_offsets[i]);
@@ -712,6 +717,45 @@ static void dce_v10_0_set_vga_render_state(struct amdgpu_device *adev,
        WREG32(mmVGA_RENDER_CONTROL, tmp);
 }
 
+static int dce_v10_0_get_num_crtc(struct amdgpu_device *adev)
+{
+       int num_crtc = 0;
+
+       switch (adev->asic_type) {
+       case CHIP_FIJI:
+       case CHIP_TONGA:
+               num_crtc = 6;
+               break;
+       default:
+               num_crtc = 0;
+       }
+       return num_crtc;
+}
+
+void dce_v10_0_disable_dce(struct amdgpu_device *adev)
+{
+       /*Disable VGA render and enabled crtc, if has DCE engine*/
+       if (amdgpu_atombios_has_dce_engine_info(adev)) {
+               u32 tmp;
+               int crtc_enabled, i;
+
+               dce_v10_0_set_vga_render_state(adev, false);
+
+               /*Disable crtc*/
+               for (i = 0; i < dce_v10_0_get_num_crtc(adev); i++) {
+                       crtc_enabled = REG_GET_FIELD(RREG32(mmCRTC_CONTROL + crtc_offsets[i]),
+                                                                        CRTC_CONTROL, CRTC_MASTER_EN);
+                       if (crtc_enabled) {
+                               WREG32(mmCRTC_UPDATE_LOCK + crtc_offsets[i], 1);
+                               tmp = RREG32(mmCRTC_CONTROL + crtc_offsets[i]);
+                               tmp = REG_SET_FIELD(tmp, CRTC_CONTROL, CRTC_MASTER_EN, 0);
+                               WREG32(mmCRTC_CONTROL + crtc_offsets[i], tmp);
+                               WREG32(mmCRTC_UPDATE_LOCK + crtc_offsets[i], 0);
+                       }
+               }
+       }
+}
+
 static void dce_v10_0_program_fmt(struct drm_encoder *encoder)
 {
        struct drm_device *dev = encoder->dev;
@@ -2063,7 +2107,7 @@ static int dce_v10_0_crtc_do_set_base(struct drm_crtc *crtc,
        struct amdgpu_framebuffer *amdgpu_fb;
        struct drm_framebuffer *target_fb;
        struct drm_gem_object *obj;
-       struct amdgpu_bo *rbo;
+       struct amdgpu_bo *abo;
        uint64_t fb_location, tiling_flags;
        uint32_t fb_format, fb_pitch_pixels;
        u32 fb_swap = REG_SET_FIELD(0, GRPH_SWAP_CNTL, GRPH_ENDIAN_SWAP, ENDIAN_NONE);
@@ -2071,6 +2115,7 @@ static int dce_v10_0_crtc_do_set_base(struct drm_crtc *crtc,
        u32 tmp, viewport_w, viewport_h;
        int r;
        bool bypass_lut = false;
+       char *format_name;
 
        /* no fb bound */
        if (!atomic && !crtc->primary->fb) {
@@ -2090,23 +2135,23 @@ static int dce_v10_0_crtc_do_set_base(struct drm_crtc *crtc,
         * just update base pointers
         */
        obj = amdgpu_fb->obj;
-       rbo = gem_to_amdgpu_bo(obj);
-       r = amdgpu_bo_reserve(rbo, false);
+       abo = gem_to_amdgpu_bo(obj);
+       r = amdgpu_bo_reserve(abo, false);
        if (unlikely(r != 0))
                return r;
 
        if (atomic) {
-               fb_location = amdgpu_bo_gpu_offset(rbo);
+               fb_location = amdgpu_bo_gpu_offset(abo);
        } else {
-               r = amdgpu_bo_pin(rbo, AMDGPU_GEM_DOMAIN_VRAM, &fb_location);
+               r = amdgpu_bo_pin(abo, AMDGPU_GEM_DOMAIN_VRAM, &fb_location);
                if (unlikely(r != 0)) {
-                       amdgpu_bo_unreserve(rbo);
+                       amdgpu_bo_unreserve(abo);
                        return -EINVAL;
                }
        }
 
-       amdgpu_bo_get_tiling_flags(rbo, &tiling_flags);
-       amdgpu_bo_unreserve(rbo);
+       amdgpu_bo_get_tiling_flags(abo, &tiling_flags);
+       amdgpu_bo_unreserve(abo);
 
        pipe_config = AMDGPU_TILING_GET(tiling_flags, PIPE_CONFIG);
 
@@ -2182,8 +2227,9 @@ static int dce_v10_0_crtc_do_set_base(struct drm_crtc *crtc,
                bypass_lut = true;
                break;
        default:
-               DRM_ERROR("Unsupported screen format %s\n",
-                       drm_get_format_name(target_fb->pixel_format));
+               format_name = drm_get_format_name(target_fb->pixel_format);
+               DRM_ERROR("Unsupported screen format %s\n", format_name);
+               kfree(format_name);
                return -EINVAL;
        }
 
@@ -2275,17 +2321,17 @@ static int dce_v10_0_crtc_do_set_base(struct drm_crtc *crtc,
        WREG32(mmVIEWPORT_SIZE + amdgpu_crtc->crtc_offset,
               (viewport_w << 16) | viewport_h);
 
-       /* set pageflip to happen only at start of vblank interval (front porch) */
-       WREG32(mmMASTER_UPDATE_MODE + amdgpu_crtc->crtc_offset, 3);
+       /* set pageflip to happen anywhere in vblank interval */
+       WREG32(mmMASTER_UPDATE_MODE + amdgpu_crtc->crtc_offset, 0);
 
        if (!atomic && fb && fb != crtc->primary->fb) {
                amdgpu_fb = to_amdgpu_framebuffer(fb);
-               rbo = gem_to_amdgpu_bo(amdgpu_fb->obj);
-               r = amdgpu_bo_reserve(rbo, false);
+               abo = gem_to_amdgpu_bo(amdgpu_fb->obj);
+               r = amdgpu_bo_reserve(abo, false);
                if (unlikely(r != 0))
                        return r;
-               amdgpu_bo_unpin(rbo);
-               amdgpu_bo_unreserve(rbo);
+               amdgpu_bo_unpin(abo);
+               amdgpu_bo_unreserve(abo);
        }
 
        /* Bytes per pixel may have changed */
@@ -2698,7 +2744,7 @@ static const struct drm_crtc_funcs dce_v10_0_crtc_funcs = {
        .gamma_set = dce_v10_0_crtc_gamma_set,
        .set_config = amdgpu_crtc_set_config,
        .destroy = dce_v10_0_crtc_destroy,
-       .page_flip = amdgpu_crtc_page_flip,
+       .page_flip_target = amdgpu_crtc_page_flip_target,
 };
 
 static void dce_v10_0_crtc_dpms(struct drm_crtc *crtc, int mode)
@@ -2765,16 +2811,16 @@ static void dce_v10_0_crtc_disable(struct drm_crtc *crtc)
        if (crtc->primary->fb) {
                int r;
                struct amdgpu_framebuffer *amdgpu_fb;
-               struct amdgpu_bo *rbo;
+               struct amdgpu_bo *abo;
 
                amdgpu_fb = to_amdgpu_framebuffer(crtc->primary->fb);
-               rbo = gem_to_amdgpu_bo(amdgpu_fb->obj);
-               r = amdgpu_bo_reserve(rbo, false);
+               abo = gem_to_amdgpu_bo(amdgpu_fb->obj);
+               r = amdgpu_bo_reserve(abo, false);
                if (unlikely(r))
-                       DRM_ERROR("failed to reserve rbo before unpin\n");
+                       DRM_ERROR("failed to reserve abo before unpin\n");
                else {
-                       amdgpu_bo_unpin(rbo);
-                       amdgpu_bo_unreserve(rbo);
+                       amdgpu_bo_unpin(abo);
+                       amdgpu_bo_unreserve(abo);
                }
        }
        /* disable the GRPH */
@@ -2962,10 +3008,11 @@ static int dce_v10_0_early_init(void *handle)
        dce_v10_0_set_display_funcs(adev);
        dce_v10_0_set_irq_funcs(adev);
 
+       adev->mode_info.num_crtc = dce_v10_0_get_num_crtc(adev);
+
        switch (adev->asic_type) {
        case CHIP_FIJI:
        case CHIP_TONGA:
-               adev->mode_info.num_crtc = 6; /* XXX 7??? */
                adev->mode_info.num_hpd = 6;
                adev->mode_info.num_dig = 7;
                break;
@@ -3141,6 +3188,13 @@ static int dce_v10_0_wait_for_idle(void *handle)
        return 0;
 }
 
+static bool dce_v10_0_check_soft_reset(void *handle)
+{
+       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+       return dce_v10_0_is_display_hung(adev);
+}
+
 static int dce_v10_0_soft_reset(void *handle)
 {
        u32 srbm_soft_reset = 0, tmp;
@@ -3512,6 +3566,7 @@ const struct amd_ip_funcs dce_v10_0_ip_funcs = {
        .resume = dce_v10_0_resume,
        .is_idle = dce_v10_0_is_idle,
        .wait_for_idle = dce_v10_0_wait_for_idle,
+       .check_soft_reset = dce_v10_0_check_soft_reset,
        .soft_reset = dce_v10_0_soft_reset,
        .set_clockgating_state = dce_v10_0_set_clockgating_state,
        .set_powergating_state = dce_v10_0_set_powergating_state,