diff options
Diffstat (limited to 'drivers/gpu/drm/radeon')
30 files changed, 196 insertions, 181 deletions
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 1dcf39084555..74f99bac08b1 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -1156,6 +1156,7 @@ static int dce4_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) { @@ -1259,8 +1260,9 @@ static int dce4_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; } @@ -1435,8 +1437,8 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc, WREG32(EVERGREEN_VIEWPORT_SIZE + radeon_crtc->crtc_offset, (viewport_w << 16) | viewport_h); - /* set pageflip to happen only at start of vblank interval (front porch) */ - WREG32(EVERGREEN_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 3); + /* set pageflip to happen anywhere in vblank interval */ + WREG32(EVERGREEN_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 0); if (!atomic && fb && fb != crtc->primary->fb) { radeon_fb = to_radeon_framebuffer(fb); @@ -1471,6 +1473,7 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc, u32 viewport_w, viewport_h; int r; bool bypass_lut = false; + char *format_name; /* no fb bound */ if (!atomic && !crtc->primary->fb) { @@ -1560,8 +1563,9 @@ static int avivo_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; } diff --git a/drivers/gpu/drm/radeon/atombios_dp.c b/drivers/gpu/drm/radeon/atombios_dp.c index cead089a9e7d..432cb46f6a34 100644 --- a/drivers/gpu/drm/radeon/atombios_dp.c +++ b/drivers/gpu/drm/radeon/atombios_dp.c @@ -389,22 +389,21 @@ bool radeon_dp_getdpcd(struct radeon_connector *radeon_connector) { struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv; u8 msg[DP_DPCD_SIZE]; - int ret, i; + int ret; - for (i = 0; i < 7; i++) { - ret = drm_dp_dpcd_read(&radeon_connector->ddc_bus->aux, DP_DPCD_REV, msg, - DP_DPCD_SIZE); - if (ret == DP_DPCD_SIZE) { - memcpy(dig_connector->dpcd, msg, DP_DPCD_SIZE); + ret = drm_dp_dpcd_read(&radeon_connector->ddc_bus->aux, DP_DPCD_REV, msg, + DP_DPCD_SIZE); + if (ret == DP_DPCD_SIZE) { + memcpy(dig_connector->dpcd, msg, DP_DPCD_SIZE); - DRM_DEBUG_KMS("DPCD: %*ph\n", (int)sizeof(dig_connector->dpcd), - dig_connector->dpcd); + DRM_DEBUG_KMS("DPCD: %*ph\n", (int)sizeof(dig_connector->dpcd), + dig_connector->dpcd); - radeon_dp_probe_oui(radeon_connector); + radeon_dp_probe_oui(radeon_connector); - return true; - } + return true; } + dig_connector->dpcd[0] = 0; return false; } diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index 0c1b9ff433af..f6ff41a0eed6 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c @@ -1871,7 +1871,7 @@ int ci_mc_load_microcode(struct radeon_device *rdev) { const __be32 *fw_data = NULL; const __le32 *new_fw_data = NULL; - u32 running, blackout = 0, tmp; + u32 running, tmp; u32 *io_mc_regs = NULL; const __le32 *new_io_mc_regs = NULL; int i, regs_size, ucode_size; @@ -1912,11 +1912,6 @@ int ci_mc_load_microcode(struct radeon_device *rdev) running = RREG32(MC_SEQ_SUP_CNTL) & RUN_MASK; if (running == 0) { - if (running) { - blackout = RREG32(MC_SHARED_BLACKOUT_CNTL); - WREG32(MC_SHARED_BLACKOUT_CNTL, blackout | 1); - } - /* reset the engine and set to writable */ WREG32(MC_SEQ_SUP_CNTL, 0x00000008); WREG32(MC_SEQ_SUP_CNTL, 0x00000010); @@ -1964,9 +1959,6 @@ int ci_mc_load_microcode(struct radeon_device *rdev) break; udelay(1); } - - if (running) - WREG32(MC_SHARED_BLACKOUT_CNTL, blackout); } return 0; @@ -4201,11 +4193,7 @@ u32 cik_gfx_get_rptr(struct radeon_device *rdev, u32 cik_gfx_get_wptr(struct radeon_device *rdev, struct radeon_ring *ring) { - u32 wptr; - - wptr = RREG32(CP_RB0_WPTR); - - return wptr; + return RREG32(CP_RB0_WPTR); } void cik_gfx_set_wptr(struct radeon_device *rdev, @@ -8215,7 +8203,7 @@ static void cik_uvd_resume(struct radeon_device *rdev) return; ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX]; - r = radeon_ring_init(rdev, ring, ring->ring_size, 0, RADEON_CP_PACKET2); + r = radeon_ring_init(rdev, ring, ring->ring_size, 0, PACKET0(UVD_NO_OP, 0)); if (r) { dev_err(rdev->dev, "failed initializing UVD ring (%d).\n", r); return; diff --git a/drivers/gpu/drm/radeon/cikd.h b/drivers/gpu/drm/radeon/cikd.h index cead2284fd79..48db93577c1d 100644 --- a/drivers/gpu/drm/radeon/cikd.h +++ b/drivers/gpu/drm/radeon/cikd.h @@ -2069,6 +2069,7 @@ #define UVD_UDEC_ADDR_CONFIG 0xef4c #define UVD_UDEC_DB_ADDR_CONFIG 0xef50 #define UVD_UDEC_DBW_ADDR_CONFIG 0xef54 +#define UVD_NO_OP 0xeffc #define UVD_LMI_EXT40_ADDR 0xf498 #define UVD_GP_SCRATCH4 0xf4e0 diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index db275b7ed34a..0b6b5766216f 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -2878,9 +2878,8 @@ void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *s for (i = 0; i < rdev->num_crtc; i++) { if (save->crtc_enabled[i]) { tmp = RREG32(EVERGREEN_MASTER_UPDATE_MODE + crtc_offsets[i]); - if ((tmp & 0x7) != 3) { + if ((tmp & 0x7) != 0) { tmp &= ~0x7; - tmp |= 0x3; WREG32(EVERGREEN_MASTER_UPDATE_MODE + crtc_offsets[i], tmp); } tmp = RREG32(EVERGREEN_GRPH_UPDATE + crtc_offsets[i]); @@ -5580,7 +5579,7 @@ static void evergreen_uvd_resume(struct radeon_device *rdev) return; ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX]; - r = radeon_ring_init(rdev, ring, ring->ring_size, 0, RADEON_CP_PACKET2); + r = radeon_ring_init(rdev, ring, ring->ring_size, 0, PACKET0(UVD_NO_OP, 0)); if (r) { dev_err(rdev->dev, "failed initializing UVD ring (%d).\n", r); return; diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h index c8e3d394cde7..f3d88ca2aa8f 100644 --- a/drivers/gpu/drm/radeon/evergreend.h +++ b/drivers/gpu/drm/radeon/evergreend.h @@ -1523,6 +1523,7 @@ #define UVD_UDEC_ADDR_CONFIG 0xef4c #define UVD_UDEC_DB_ADDR_CONFIG 0xef50 #define UVD_UDEC_DBW_ADDR_CONFIG 0xef54 +#define UVD_NO_OP 0xeffc #define UVD_RBC_RB_RPTR 0xf690 #define UVD_RBC_RB_WPTR 0xf694 #define UVD_STATUS 0xf6bc diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c index 4a3d7cab83f7..103fc8650197 100644 --- a/drivers/gpu/drm/radeon/ni.c +++ b/drivers/gpu/drm/radeon/ni.c @@ -2062,7 +2062,7 @@ static void cayman_uvd_resume(struct radeon_device *rdev) return; ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX]; - r = radeon_ring_init(rdev, ring, ring->ring_size, 0, RADEON_CP_PACKET2); + r = radeon_ring_init(rdev, ring, ring->ring_size, 0, PACKET0(UVD_NO_OP, 0)); if (r) { dev_err(rdev->dev, "failed initializing UVD ring (%d).\n", r); return; diff --git a/drivers/gpu/drm/radeon/nid.h b/drivers/gpu/drm/radeon/nid.h index 47eb49b77d32..3c9fec88ea44 100644 --- a/drivers/gpu/drm/radeon/nid.h +++ b/drivers/gpu/drm/radeon/nid.h @@ -1137,6 +1137,7 @@ #define UVD_UDEC_ADDR_CONFIG 0xEF4C #define UVD_UDEC_DB_ADDR_CONFIG 0xEF50 #define UVD_UDEC_DBW_ADDR_CONFIG 0xEF54 +#define UVD_NO_OP 0xEFFC #define UVD_RBC_RB_RPTR 0xF690 #define UVD_RBC_RB_WPTR 0xF694 #define UVD_STATUS 0xf6bc diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index f25994b3afa6..f5e84f4b58e6 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -1071,11 +1071,7 @@ u32 r100_gfx_get_rptr(struct radeon_device *rdev, u32 r100_gfx_get_wptr(struct radeon_device *rdev, struct radeon_ring *ring) { - u32 wptr; - - wptr = RREG32(RADEON_CP_RB_WPTR); - - return wptr; + return RREG32(RADEON_CP_RB_WPTR); } void r100_gfx_set_wptr(struct radeon_device *rdev, diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 9247e7d207fe..a951881c2a50 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -2631,11 +2631,7 @@ u32 r600_gfx_get_rptr(struct radeon_device *rdev, u32 r600_gfx_get_wptr(struct radeon_device *rdev, struct radeon_ring *ring) { - u32 wptr; - - wptr = RREG32(R600_CP_RB_WPTR); - - return wptr; + return RREG32(R600_CP_RB_WPTR); } void r600_gfx_set_wptr(struct radeon_device *rdev, @@ -3097,7 +3093,7 @@ static void r600_uvd_resume(struct radeon_device *rdev) return; ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX]; - r = radeon_ring_init(rdev, ring, ring->ring_size, 0, RADEON_CP_PACKET2); + r = radeon_ring_init(rdev, ring, ring->ring_size, 0, PACKET0(UVD_NO_OP, 0)); if (r) { dev_err(rdev->dev, "failed initializing UVD ring (%d).\n", r); return; diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h index 1e8495cca41e..2e00a5287bd2 100644 --- a/drivers/gpu/drm/radeon/r600d.h +++ b/drivers/gpu/drm/radeon/r600d.h @@ -1490,6 +1490,7 @@ #define UVD_GPCOM_VCPU_DATA0 0xef10 #define UVD_GPCOM_VCPU_DATA1 0xef14 #define UVD_ENGINE_CNTL 0xef18 +#define UVD_NO_OP 0xeffc #define UVD_SEMA_CNTL 0xf400 #define UVD_RB_ARB_CTRL 0xf480 diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 5633ee3eb46e..1b0dcad916b0 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -742,6 +742,7 @@ struct radeon_flip_work { struct work_struct unpin_work; struct radeon_device *rdev; int crtc_id; + u32 target_vblank; uint64_t base; struct drm_pending_vblank_event *event; struct radeon_bo *old_rbo; diff --git a/drivers/gpu/drm/radeon/radeon_acpi.c b/drivers/gpu/drm/radeon/radeon_acpi.c index 31c9a92d6a1b..6efbd65c929e 100644 --- a/drivers/gpu/drm/radeon/radeon_acpi.c +++ b/drivers/gpu/drm/radeon/radeon_acpi.c @@ -25,6 +25,7 @@ #include <linux/acpi.h> #include <linux/slab.h> #include <linux/power_supply.h> +#include <linux/pm_runtime.h> #include <acpi/video.h> #include <drm/drmP.h> #include <drm/drm_crtc_helper.h> @@ -32,6 +33,12 @@ #include "radeon_acpi.h" #include "atom.h" +#if defined(CONFIG_VGA_SWITCHEROO) +bool radeon_atpx_dgpu_req_power_for_displays(void); +#else +static inline bool radeon_atpx_dgpu_req_power_for_displays(void) { return false; } +#endif + #define ACPI_AC_CLASS "ac_adapter" extern void radeon_pm_acpi_event_handler(struct radeon_device *rdev); @@ -394,6 +401,16 @@ int radeon_atif_handler(struct radeon_device *rdev, #endif } } + if (req.pending & ATIF_DGPU_DISPLAY_EVENT) { + if ((rdev->flags & RADEON_IS_PX) && + radeon_atpx_dgpu_req_power_for_displays()) { + pm_runtime_get_sync(rdev->ddev->dev); + /* Just fire off a uevent and let userspace tell us what to do */ + drm_helper_hpd_irq_event(rdev->ddev); + pm_runtime_mark_last_busy(rdev->ddev->dev); + pm_runtime_put_autosuspend(rdev->ddev->dev); + } + } /* TODO: check other events */ /* We've handled the event, stop the notifier chain. The ACPI interface diff --git a/drivers/gpu/drm/radeon/radeon_atpx_handler.c b/drivers/gpu/drm/radeon/radeon_atpx_handler.c index ddef0d494084..2fdcd04bc93f 100644 --- a/drivers/gpu/drm/radeon/radeon_atpx_handler.c +++ b/drivers/gpu/drm/radeon/radeon_atpx_handler.c @@ -29,6 +29,7 @@ struct radeon_atpx { acpi_handle handle; struct radeon_atpx_functions functions; bool is_hybrid; + bool dgpu_req_power_for_displays; }; static struct radeon_atpx_priv { @@ -72,6 +73,10 @@ bool radeon_is_atpx_hybrid(void) { return radeon_atpx_priv.atpx.is_hybrid; } +bool radeon_atpx_dgpu_req_power_for_displays(void) { + return radeon_atpx_priv.atpx.dgpu_req_power_for_displays; +} + /** * radeon_atpx_call - call an ATPX method * diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index b79f3b002471..50e96d2c593d 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -198,12 +198,12 @@ int radeon_get_monitor_bpc(struct drm_connector *connector) } /* Any defined maximum tmds clock limit we must not exceed? */ - if (connector->max_tmds_clock > 0) { + if (connector->display_info.max_tmds_clock > 0) { /* mode_clock is clock in kHz for mode to be modeset on this connector */ mode_clock = radeon_connector->pixelclock_for_modeset; /* Maximum allowable input clock in kHz */ - max_tmds_clock = connector->max_tmds_clock * 1000; + max_tmds_clock = connector->display_info.max_tmds_clock; DRM_DEBUG("%s: hdmi mode dotclock %d kHz, max tmds input clock %d kHz.\n", connector->name, mode_clock, max_tmds_clock); diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index a00dd2f74527..eb92aef46e3c 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -639,7 +639,7 @@ void radeon_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc) * Used at driver startup. * Returns true if virtual or false if not. */ -static bool radeon_device_is_virtual(void) +bool radeon_device_is_virtual(void) { #ifdef CONFIG_X86 return boot_cpu_has(X86_FEATURE_HYPERVISOR); @@ -661,8 +661,9 @@ bool radeon_card_posted(struct radeon_device *rdev) { uint32_t reg; - /* for pass through, always force asic_init */ - if (radeon_device_is_virtual()) + /* for pass through, always force asic_init for CI */ + if (rdev->family >= CHIP_BONAIRE && + radeon_device_is_virtual()) return false; /* required for EFI mode on macbook2,1 which uses an r5xx asic */ @@ -1956,14 +1957,3 @@ static void radeon_debugfs_remove_files(struct radeon_device *rdev) } #endif } - -#if defined(CONFIG_DEBUG_FS) -int radeon_debugfs_init(struct drm_minor *minor) -{ - return 0; -} - -void radeon_debugfs_cleanup(struct drm_minor *minor) -{ -} -#endif diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index c3206fb8f4cf..b8ab30a7dd6d 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -321,16 +321,30 @@ void radeon_crtc_handle_vblank(struct radeon_device *rdev, int crtc_id) update_pending = radeon_page_flip_pending(rdev, crtc_id); /* Has the pageflip already completed in crtc, or is it certain - * to complete in this vblank? + * to complete in this vblank? GET_DISTANCE_TO_VBLANKSTART provides + * distance to start of "fudged earlier" vblank in vpos, distance to + * start of real vblank in hpos. vpos >= 0 && hpos < 0 means we are in + * the last few scanlines before start of real vblank, where the vblank + * irq can fire, so we have sampled update_pending a bit too early and + * know the flip will complete at leading edge of the upcoming real + * vblank. On pre-AVIVO hardware, flips also complete inside the real + * vblank, not only at leading edge, so if update_pending for hpos >= 0 + * == inside real vblank, the flip will complete almost immediately. + * Note that this method of completion handling is still not 100% race + * free, as we could execute before the radeon_flip_work_func managed + * to run and set the RADEON_FLIP_SUBMITTED status, thereby we no-op, + * but the flip still gets programmed into hw and completed during + * vblank, leading to a delayed emission of the flip completion event. + * This applies at least to pre-AVIVO hardware, where flips are always + * completing inside vblank, not only at leading edge of vblank. */ if (update_pending && - (DRM_SCANOUTPOS_VALID & radeon_get_crtc_scanoutpos(rdev->ddev, - crtc_id, - USE_REAL_VBLANKSTART, - &vpos, &hpos, NULL, NULL, - &rdev->mode_info.crtcs[crtc_id]->base.hwmode)) && - ((vpos >= (99 * rdev->mode_info.crtcs[crtc_id]->base.hwmode.crtc_vdisplay)/100) || - (vpos < 0 && !ASIC_IS_AVIVO(rdev)))) { + (DRM_SCANOUTPOS_VALID & + radeon_get_crtc_scanoutpos(rdev->ddev, crtc_id, + GET_DISTANCE_TO_VBLANKSTART, + &vpos, &hpos, NULL, NULL, + &rdev->mode_info.crtcs[crtc_id]->base.hwmode)) && + ((vpos >= 0 && hpos < 0) || (hpos >= 0 && !ASIC_IS_AVIVO(rdev)))) { /* crtc didn't flip in this target vblank interval, * but flip is pending in crtc. Based on the current * scanout position we know that the current frame is @@ -400,14 +414,13 @@ static void radeon_flip_work_func(struct work_struct *__work) struct radeon_flip_work *work = container_of(__work, struct radeon_flip_work, flip_work); struct radeon_device *rdev = work->rdev; + struct drm_device *dev = rdev->ddev; struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[work->crtc_id]; struct drm_crtc *crtc = &radeon_crtc->base; unsigned long flags; int r; - int vpos, hpos, stat, min_udelay = 0; - unsigned repcnt = 4; - struct drm_vblank_crtc *vblank = &crtc->dev->vblank[work->crtc_id]; + int vpos, hpos; down_read(&rdev->exclusive_lock); if (work->fence) { @@ -438,59 +451,28 @@ static void radeon_flip_work_func(struct work_struct *__work) work->fence = NULL; } + /* Wait until we're out of the vertical blank period before the one + * targeted by the flip. Always wait on pre DCE4 to avoid races with + * flip completion handling from vblank irq, as these old asics don't + * have reliable pageflip completion interrupts. + */ + while (radeon_crtc->enabled && + (radeon_get_crtc_scanoutpos(dev, work->crtc_id, 0, + &vpos, &hpos, NULL, NULL, + &crtc->hwmode) + & (DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_IN_VBLANK)) == + (DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_IN_VBLANK) && + (!ASIC_IS_AVIVO(rdev) || + ((int) (work->target_vblank - + dev->driver->get_vblank_counter(dev, work->crtc_id)) > 0))) + usleep_range(1000, 2000); + /* We borrow the event spin lock for protecting flip_status */ spin_lock_irqsave(&crtc->dev->event_lock, flags); /* set the proper interrupt */ radeon_irq_kms_pflip_irq_get(rdev, radeon_crtc->crtc_id); - /* If this happens to execute within the "virtually extended" vblank - * interval before the start of the real vblank interval then it needs - * to delay programming the mmio flip until the real vblank is entered. - * This prevents completing a flip too early due to the way we fudge - * our vblank counter and vblank timestamps in order to work around the - * problem that the hw fires vblank interrupts before actual start of - * vblank (when line buffer refilling is done for a frame). It - * complements the fudging logic in radeon_get_crtc_scanoutpos() for - * timestamping and radeon_get_vblank_counter_kms() for vblank counts. - * - * In practice this won't execute very often unless on very fast - * machines because the time window for this to happen is very small. - */ - while (radeon_crtc->enabled && --repcnt) { - /* GET_DISTANCE_TO_VBLANKSTART returns distance to real vblank - * start in hpos, and to the "fudged earlier" vblank start in - * vpos. - */ - stat = radeon_get_crtc_scanoutpos(rdev->ddev, work->crtc_id, - GET_DISTANCE_TO_VBLANKSTART, - &vpos, &hpos, NULL, NULL, - &crtc->hwmode); - - if ((stat & (DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_ACCURATE)) != - (DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_ACCURATE) || - !(vpos >= 0 && hpos <= 0)) - break; - - /* Sleep at least until estimated real start of hw vblank */ - min_udelay = (-hpos + 1) * max(vblank->linedur_ns / 1000, 5); - if (min_udelay > vblank->framedur_ns / 2000) { - /* Don't wait ridiculously long - something is wrong */ - repcnt = 0; - break; - } - spin_unlock_irqrestore(&crtc->dev->event_lock, flags); - usleep_range(min_udelay, 2 * min_udelay); - spin_lock_irqsave(&crtc->dev->event_lock, flags); - }; - - if (!repcnt) - DRM_DEBUG_DRIVER("Delay problem on crtc %d: min_udelay %d, " - "framedur %d, linedur %d, stat %d, vpos %d, " - "hpos %d\n", work->crtc_id, min_udelay, - vblank->framedur_ns / 1000, - vblank->linedur_ns / 1000, stat, vpos, hpos); - /* do the flip (mmio) */ radeon_page_flip(rdev, radeon_crtc->crtc_id, work->base, work->async); @@ -499,10 +481,11 @@ static void radeon_flip_work_func(struct work_struct *__work) up_read(&rdev->exclusive_lock); } -static int radeon_crtc_page_flip(struct drm_crtc *crtc, - struct drm_framebuffer *fb, - struct drm_pending_vblank_event *event, - uint32_t page_flip_flags) +static int radeon_crtc_page_flip_target(struct drm_crtc *crtc, + struct drm_framebuffer *fb, + struct drm_pending_vblank_event *event, + uint32_t page_flip_flags, + uint32_t target) { struct drm_device *dev = crtc->dev; struct radeon_device *rdev = dev->dev_private; @@ -599,12 +582,8 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc, base &= ~7; } work->base = base; - - r = drm_crtc_vblank_get(crtc); - if (r) { - DRM_ERROR("failed to get vblank before flip\n"); - goto pflip_cleanup; - } + work->target_vblank = target - drm_crtc_vblank_count(crtc) + + dev->driver->get_vblank_counter(dev, work->crtc_id); /* We borrow the event spin lock for protecting flip_work */ spin_lock_irqsave(&crtc->dev->event_lock, flags); @@ -613,7 +592,7 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc, DRM_DEBUG_DRIVER("flip queue: crtc already busy\n"); spin_unlock_irqrestore(&crtc->dev->event_lock, flags); r = -EBUSY; - goto vblank_cleanup; + goto pflip_cleanup; } radeon_crtc->flip_status = RADEON_FLIP_PENDING; radeon_crtc->flip_work = work; @@ -626,9 +605,6 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc, queue_work(radeon_crtc->flip_queue, &work->flip_work); return 0; -vblank_cleanup: - drm_crtc_vblank_put(crtc); - pflip_cleanup: if (unlikely(radeon_bo_reserve(new_rbo, false) != 0)) { DRM_ERROR("failed to reserve new rbo in error path\n"); @@ -697,7 +673,7 @@ static const struct drm_crtc_funcs radeon_crtc_funcs = { .gamma_set = radeon_crtc_gamma_set, .set_config = radeon_crtc_set_config, .destroy = radeon_crtc_destroy, - .page_flip = radeon_crtc_page_flip, + .page_flip_target = radeon_crtc_page_flip_target, }; static void radeon_crtc_init(struct drm_device *dev, int index) diff --git a/drivers/gpu/drm/radeon/radeon_dp_auxch.c b/drivers/gpu/drm/radeon/radeon_dp_auxch.c index db64e0062689..2d465648856a 100644 --- a/drivers/gpu/drm/radeon/radeon_dp_auxch.c +++ b/drivers/gpu/drm/radeon/radeon_dp_auxch.c @@ -164,7 +164,6 @@ radeon_dp_aux_transfer_native(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg } if (tmp & AUX_SW_RX_TIMEOUT) { - DRM_DEBUG_KMS("dp_aux_ch timed out\n"); ret = -ETIMEDOUT; goto done; } diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index c01a7c6abb49..91c8f4339566 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -39,6 +39,7 @@ #include <linux/pm_runtime.h> #include <linux/vga_switcheroo.h> #include <drm/drm_gem.h> +#include <drm/drm_fb_helper.h> #include "drm_crtc_helper.h" #include "radeon_kfd.h" @@ -94,9 +95,10 @@ * 2.44.0 - SET_APPEND_CNT packet3 support * 2.45.0 - Allow setting shader registers using DMA/COPY packet3 on SI * 2.46.0 - Add PFP_SYNC_ME support on evergreen + * 2.47.0 - Add UVD_NO_OP register support */ #define KMS_DRIVER_MAJOR 2 -#define KMS_DRIVER_MINOR 46 +#define KMS_DRIVER_MINOR 47 #define KMS_DRIVER_PATCHLEVEL 0 int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags); int radeon_driver_unload_kms(struct drm_device *dev); @@ -154,11 +156,6 @@ void radeon_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr); extern long radeon_kms_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); -#if defined(CONFIG_DEBUG_FS) -int radeon_debugfs_init(struct drm_minor *minor); -void radeon_debugfs_cleanup(struct drm_minor *minor); -#endif - /* atpx handler */ #if defined(CONFIG_VGA_SWITCHEROO) void radeon_register_atpx_handler(void); @@ -309,6 +306,8 @@ MODULE_DEVICE_TABLE(pci, pciidlist); static struct drm_driver kms_driver; +bool radeon_device_is_virtual(void); + static int radeon_kick_out_firmware_fb(struct pci_dev *pdev) { struct apertures_struct *ap; @@ -324,7 +323,7 @@ static int radeon_kick_out_firmware_fb(struct pci_dev *pdev) #ifdef CONFIG_X86 primary = pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW; #endif - remove_conflicting_framebuffers(ap, "radeondrmfb", primary); + drm_fb_helper_remove_conflicting_framebuffers(ap, "radeondrmfb", primary); kfree(ap); return 0; @@ -362,6 +361,17 @@ radeon_pci_remove(struct pci_dev *pdev) drm_put_dev(dev); } +static void +radeon_pci_shutdown(struct pci_dev *pdev) +{ + /* if we are running in a VM, make sure the device + * torn down properly on reboot/shutdown. + * unfortunately we can't detect certain + * hypervisors so just do this all the time. + */ + radeon_pci_remove(pdev); +} + static int radeon_pmops_suspend(struct device *dev) { struct pci_dev *pdev = to_pci_dev(dev); @@ -373,6 +383,14 @@ static int radeon_pmops_resume(struct device *dev) { struct pci_dev *pdev = to_pci_dev(dev); struct drm_device *drm_dev = pci_get_drvdata(pdev); + + /* GPU comes up enabled by the bios on resume */ + if (radeon_is_px(drm_dev)) { + pm_runtime_disable(dev); + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + } + return radeon_resume_kms(drm_dev, true, true); } @@ -529,10 +547,6 @@ static struct drm_driver kms_driver = { .disable_vblank = radeon_disable_vblank_kms, .get_vblank_timestamp = radeon_get_vblank_timestamp_kms, .get_scanout_position = radeon_get_crtc_scanoutpos, -#if defined(CONFIG_DEBUG_FS) - .debugfs_init = radeon_debugfs_init, - .debugfs_cleanup = radeon_debugfs_cleanup, -#endif .irq_preinstall = radeon_driver_irq_preinstall_kms, .irq_postinstall = radeon_driver_irq_postinstall_kms, .irq_uninstall = radeon_driver_irq_uninstall_kms, @@ -574,6 +588,7 @@ static struct pci_driver radeon_kms_pci_driver = { .id_table = pciidlist, .probe = radeon_pci_probe, .remove = radeon_pci_remove, + .shutdown = radeon_pci_shutdown, .driver.pm = &radeon_pm_ops, }; diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c index 0e3143acb565..0daad446d2c7 100644 --- a/drivers/gpu/drm/radeon/radeon_fb.c +++ b/drivers/gpu/drm/radeon/radeon_fb.c @@ -25,7 +25,7 @@ */ #include <linux/module.h> #include <linux/slab.h> -#include <linux/fb.h> +#include <linux/pm_runtime.h> #include <drm/drmP.h> #include <drm/drm_crtc.h> @@ -47,8 +47,35 @@ struct radeon_fbdev { struct radeon_device *rdev; }; +static int +radeonfb_open(struct fb_info *info, int user) +{ + struct radeon_fbdev *rfbdev = info->par; + struct radeon_device *rdev = rfbdev->rdev; + int ret = pm_runtime_get_sync(rdev->ddev->dev); + if (ret < 0 && ret != -EACCES) { + pm_runtime_mark_last_busy(rdev->ddev->dev); + pm_runtime_put_autosuspend(rdev->ddev->dev); + return ret; + } + return 0; +} + +static int +radeonfb_release(struct fb_info *info, int user) +{ + struct radeon_fbdev *rfbdev = info->par; + struct radeon_device *rdev = rfbdev->rdev; + + pm_runtime_mark_last_busy(rdev->ddev->dev); + pm_runtime_put_autosuspend(rdev->ddev->dev); + return 0; +} + static struct fb_ops radeonfb_ops = { .owner = THIS_MODULE, + .fb_open = radeonfb_open, + .fb_release = radeonfb_release, .fb_check_var = drm_fb_helper_check_var, .fb_set_par = drm_fb_helper_set_par, .fb_fillrect = drm_fb_helper_cfb_fillrect, @@ -383,7 +410,7 @@ void radeon_fbdev_fini(struct radeon_device *rdev) void radeon_fbdev_set_suspend(struct radeon_device *rdev, int state) { if (rdev->mode_info.rfbdev) - fb_set_suspend(rdev->mode_info.rfbdev->helper.fbdev, state); + drm_fb_helper_set_suspend(&rdev->mode_info.rfbdev->helper, state); } bool radeon_fbdev_robj_is_fb(struct radeon_device *rdev, struct radeon_bo *robj) diff --git a/drivers/gpu/drm/radeon/radeon_i2c.c b/drivers/gpu/drm/radeon/radeon_i2c.c index 9590bcd321c0..021aa005623f 100644 --- a/drivers/gpu/drm/radeon/radeon_i2c.c +++ b/drivers/gpu/drm/radeon/radeon_i2c.c @@ -938,10 +938,8 @@ struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev, "Radeon i2c hw bus %s", name); i2c->adapter.algo = &radeon_i2c_algo; ret = i2c_add_adapter(&i2c->adapter); - if (ret) { - DRM_ERROR("Failed to register hw i2c %s\n", name); + if (ret) goto out_free; - } } else if (rec->hw_capable && radeon_hw_i2c && ASIC_IS_DCE3(rdev)) { @@ -950,10 +948,8 @@ struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev, "Radeon i2c hw bus %s", name); i2c->adapter.algo = &radeon_atom_i2c_algo; ret = i2c_add_adapter(&i2c->adapter); - if (ret) { - DRM_ERROR("Failed to register hw i2c %s\n", name); + if (ret) goto out_free; - } } else { /* set the radeon bit adapter */ snprintf(i2c->adapter.name, sizeof(i2c->adapter.name), diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c index 835563c1f0ed..4388ddeec8d2 100644 --- a/drivers/gpu/drm/radeon/radeon_kms.c +++ b/drivers/gpu/drm/radeon/radeon_kms.c @@ -641,11 +641,11 @@ int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv) if (rdev->family >= CHIP_CAYMAN) { struct radeon_fpriv *fpriv; struct radeon_vm *vm; - int r; fpriv = kzalloc(sizeof(*fpriv), GFP_KERNEL); if (unlikely(!fpriv)) { - return -ENOMEM; + r = -ENOMEM; + goto out_suspend; } if (rdev->accel_working) { @@ -653,14 +653,14 @@ int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv) r = radeon_vm_init(rdev, vm); if (r) { kfree(fpriv); - return r; + goto out_suspend; } r = radeon_bo_reserve(rdev->ring_tmp_bo.bo, false); if (r) { radeon_vm_fini(rdev, vm); kfree(fpriv); - return r; + goto out_suspend; } /* map the ib pool buffer read only into @@ -674,15 +674,16 @@ int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv) if (r) { radeon_vm_fini(rdev, vm); kfree(fpriv); - return r; + goto out_suspend; } } file_priv->driver_priv = fpriv; } +out_suspend: pm_runtime_mark_last_busy(dev->dev); pm_runtime_put_autosuspend(dev->dev); - return 0; + return r; } /** @@ -717,6 +718,8 @@ void radeon_driver_postclose_kms(struct drm_device *dev, kfree(fpriv); file_priv->driver_priv = NULL; } + pm_runtime_mark_last_busy(dev->dev); + pm_runtime_put_autosuspend(dev->dev); } /** @@ -733,6 +736,8 @@ void radeon_driver_preclose_kms(struct drm_device *dev, { struct radeon_device *rdev = dev->dev_private; + pm_runtime_get_sync(dev->dev); + mutex_lock(&rdev->gem.mutex); if (rdev->hyperz_filp == file_priv) rdev->hyperz_filp = NULL; diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index c2e0a1ccdfbc..455268214b89 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -237,7 +237,8 @@ static int radeon_verify_access(struct ttm_buffer_object *bo, struct file *filp) if (radeon_ttm_tt_has_userptr(bo->ttm)) return -EPERM; - return drm_vma_node_verify_access(&rbo->gem_base.vma_node, filp); + return drm_vma_node_verify_access(&rbo->gem_base.vma_node, + filp->private_data); } static void radeon_move_null(struct ttm_buffer_object *bo, @@ -346,7 +347,7 @@ static int radeon_move_vram_ram(struct ttm_buffer_object *bo, if (unlikely(r)) { goto out_cleanup; } - r = ttm_bo_move_ttm(bo, true, interruptible, no_wait_gpu, new_mem); + r = ttm_bo_move_ttm(bo, interruptible, no_wait_gpu, new_mem); out_cleanup: ttm_bo_mem_put(bo, &tmp_mem); return r; @@ -379,7 +380,7 @@ static int radeon_move_ram_vram(struct ttm_buffer_object *bo, if (unlikely(r)) { return r; } - r = ttm_bo_move_ttm(bo, true, interruptible, no_wait_gpu, &tmp_mem); + r = ttm_bo_move_ttm(bo, interruptible, no_wait_gpu, &tmp_mem); if (unlikely(r)) { goto out_cleanup; } @@ -444,8 +445,7 @@ static int radeon_bo_move(struct ttm_buffer_object *bo, if (r) { memcpy: - r = ttm_bo_move_memcpy(bo, evict, interruptible, - no_wait_gpu, new_mem); + r = ttm_bo_move_memcpy(bo, interruptible, no_wait_gpu, new_mem); if (r) { return r; } diff --git a/drivers/gpu/drm/radeon/radeon_uvd.c b/drivers/gpu/drm/radeon/radeon_uvd.c index 73dfe01435ea..0cd0e7bdee55 100644 --- a/drivers/gpu/drm/radeon/radeon_uvd.c +++ b/drivers/gpu/drm/radeon/radeon_uvd.c @@ -669,6 +669,7 @@ static int radeon_uvd_cs_reg(struct radeon_cs_parser *p, return r; break; case UVD_ENGINE_CNTL: + case UVD_NO_OP: break; default: DRM_ERROR("Invalid reg 0x%X!\n", @@ -753,8 +754,10 @@ static int radeon_uvd_send_msg(struct radeon_device *rdev, ib.ptr[3] = addr >> 32; ib.ptr[4] = PACKET0(UVD_GPCOM_VCPU_CMD, 0); ib.ptr[5] = 0; - for (i = 6; i < 16; ++i) - ib.ptr[i] = PACKET2(0); + for (i = 6; i < 16; i += 2) { + ib.ptr[i] = PACKET0(UVD_NO_OP, 0); + ib.ptr[i+1] = 0; + } ib.length_dw = 16; r = radeon_ib_schedule(rdev, &ib, NULL, false); diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index 1c120a4c3c97..729ae588c970 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c @@ -1738,7 +1738,7 @@ static void rv770_uvd_resume(struct radeon_device *rdev) return; ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX]; - r = radeon_ring_init(rdev, ring, ring->ring_size, 0, RADEON_CP_PACKET2); + r = radeon_ring_init(rdev, ring, ring->ring_size, 0, PACKET0(UVD_NO_OP, 0)); if (r) { dev_err(rdev->dev, "failed initializing UVD ring (%d).\n", r); return; diff --git a/drivers/gpu/drm/radeon/rv770d.h b/drivers/gpu/drm/radeon/rv770d.h index 9ef2064b1c9c..0271f4c559ae 100644 --- a/drivers/gpu/drm/radeon/rv770d.h +++ b/drivers/gpu/drm/radeon/rv770d.h @@ -387,6 +387,7 @@ #define UVD_UDEC_TILING_CONFIG 0xef40 #define UVD_UDEC_DB_TILING_CONFIG 0xef44 #define UVD_UDEC_DBW_TILING_CONFIG 0xef48 +#define UVD_NO_OP 0xeffc #define GC_USER_SHADER_PIPE_CONFIG 0x8954 #define INACTIVE_QD_PIPES(x) ((x) << 8) diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index 2523ca96c6c7..7ee9aafbdf74 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -1547,7 +1547,7 @@ int si_mc_load_microcode(struct radeon_device *rdev) { const __be32 *fw_data = NULL; const __le32 *new_fw_data = NULL; - u32 running, blackout = 0; + u32 running; u32 *io_mc_regs = NULL; const __le32 *new_io_mc_regs = NULL; int i, regs_size, ucode_size; @@ -1598,11 +1598,6 @@ int si_mc_load_microcode(struct radeon_device *rdev) running = RREG32(MC_SEQ_SUP_CNTL) & RUN_MASK; if (running == 0) { - if (running) { - blackout = RREG32(MC_SHARED_BLACKOUT_CNTL); - WREG32(MC_SHARED_BLACKOUT_CNTL, blackout | 1); - } - /* reset the engine and set to writable */ WREG32(MC_SEQ_SUP_CNTL, 0x00000008); WREG32(MC_SEQ_SUP_CNTL, 0x00000010); @@ -1641,9 +1636,6 @@ int si_mc_load_microcode(struct radeon_device *rdev) break; udelay(1); } - - if (running) - WREG32(MC_SHARED_BLACKOUT_CNTL, blackout); } return 0; @@ -6928,7 +6920,7 @@ static void si_uvd_resume(struct radeon_device *rdev) return; ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX]; - r = radeon_ring_init(rdev, ring, ring->ring_size, 0, RADEON_CP_PACKET2); + r = radeon_ring_init(rdev, ring, ring->ring_size, 0, PACKET0(UVD_NO_OP, 0)); if (r) { dev_err(rdev->dev, "failed initializing UVD ring (%d).\n", r); return; diff --git a/drivers/gpu/drm/radeon/si_dpm.c b/drivers/gpu/drm/radeon/si_dpm.c index 1f78ec2548ec..89bdf20344ae 100644 --- a/drivers/gpu/drm/radeon/si_dpm.c +++ b/drivers/gpu/drm/radeon/si_dpm.c @@ -4112,7 +4112,7 @@ static int si_populate_smc_voltage_tables(struct radeon_device *rdev, &rdev->pm.dpm.dyn_state.phase_shedding_limits_table)) { si_populate_smc_voltage_table(rdev, &si_pi->vddc_phase_shed_table, table); - table->phaseMaskTable.lowMask[SISLANDS_SMC_VOLTAGEMASK_VDDC] = + table->phaseMaskTable.lowMask[SISLANDS_SMC_VOLTAGEMASK_VDDC_PHASE_SHEDDING] = cpu_to_be32(si_pi->vddc_phase_shed_table.mask_low); si_write_smc_soft_register(rdev, SI_SMC_SOFT_REGISTER_phase_shedding_delay, diff --git a/drivers/gpu/drm/radeon/sid.h b/drivers/gpu/drm/radeon/sid.h index d1a7b58dd291..eb220eecba78 100644 --- a/drivers/gpu/drm/radeon/sid.h +++ b/drivers/gpu/drm/radeon/sid.h @@ -1559,6 +1559,7 @@ #define UVD_UDEC_ADDR_CONFIG 0xEF4C #define UVD_UDEC_DB_ADDR_CONFIG 0xEF50 #define UVD_UDEC_DBW_ADDR_CONFIG 0xEF54 +#define UVD_NO_OP 0xEFFC #define UVD_RBC_RB_RPTR 0xF690 #define UVD_RBC_RB_WPTR 0xF694 #define UVD_STATUS 0xf6bc diff --git a/drivers/gpu/drm/radeon/sislands_smc.h b/drivers/gpu/drm/radeon/sislands_smc.h index 3c779838d9ab..966e3a556011 100644 --- a/drivers/gpu/drm/radeon/sislands_smc.h +++ b/drivers/gpu/drm/radeon/sislands_smc.h @@ -194,6 +194,7 @@ typedef struct SISLANDS_SMC_SWSTATE SISLANDS_SMC_SWSTATE; #define SISLANDS_SMC_VOLTAGEMASK_VDDC 0 #define SISLANDS_SMC_VOLTAGEMASK_MVDD 1 #define SISLANDS_SMC_VOLTAGEMASK_VDDCI 2 +#define SISLANDS_SMC_VOLTAGEMASK_VDDC_PHASE_SHEDDING 3 #define SISLANDS_SMC_VOLTAGEMASK_MAX 4 struct SISLANDS_SMC_VOLTAGEMASKTABLE |