diff options
author | Dave Airlie <airlied@gmail.com> | 2015-12-05 01:15:38 -0500 |
---|---|---|
committer | Dave Airlie <airlied@gmail.com> | 2015-12-05 01:15:38 -0500 |
commit | df4d4aa96d1db1657e14b848a341fc614c8d61eb (patch) | |
tree | 2adc46d577b369551e4f94252b48f07d9e7f6dd7 /drivers/gpu/drm/radeon/radeon_display.c | |
parent | bbc8764f80eb872d2b36302882ddfc9882de4b16 (diff) | |
parent | 8e36f9d33c134d5c6448ad65b423a9fd94e045cf (diff) |
Merge branch 'drm-fixes-4.4' of git://people.freedesktop.org/~agd5f/linux into drm-next
A few more last minute fixes for 4.4 on top of my pull request from
earlier this week. The big change here is a vblank regression fix due to
commit 4dfd6486 "drm: Use vblank timestamps to guesstimate how many vblanks
were missed". Beyond that, a hotplug fix and a few VM fixes.
* 'drm-fixes-4.4' of git://people.freedesktop.org/~agd5f/linux:
drm/amdgpu: Fixup hw vblank counter/ts for new drm_update_vblank_count() (v3)
drm/radeon: Fixup hw vblank counter/ts for new drm_update_vblank_count() (v2)
drm/radeon: Retry DDC probing on DVI on failure if we got an HPD interrupt
drm/amdgpu: add spin lock to protect freed list in vm (v2)
drm/amdgpu: partially revert "drm/amdgpu: fix VM_CONTEXT*_PAGE_TABLE_END_ADDR" v2
drm/amdgpu: take a BO reference for the user fence
drm/amdgpu: take a BO reference in the display code
drm/amdgpu: set snooped flags only on system addresses v2
drm/amdgpu: fix race condition in amd_sched_entity_push_job
drm/amdgpu: add err check for pin userptr
add blacklist for thinkpad T40p
drm/amdgpu: fix VM page table reference counting
drm/amdgpu: fix userptr flags check
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_display.c')
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_display.c | 106 |
1 files changed, 79 insertions, 27 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index a8d9927ed9eb..1eca0acac016 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c | |||
@@ -322,7 +322,9 @@ void radeon_crtc_handle_vblank(struct radeon_device *rdev, int crtc_id) | |||
322 | * to complete in this vblank? | 322 | * to complete in this vblank? |
323 | */ | 323 | */ |
324 | if (update_pending && | 324 | if (update_pending && |
325 | (DRM_SCANOUTPOS_VALID & radeon_get_crtc_scanoutpos(rdev->ddev, crtc_id, 0, | 325 | (DRM_SCANOUTPOS_VALID & radeon_get_crtc_scanoutpos(rdev->ddev, |
326 | crtc_id, | ||
327 | USE_REAL_VBLANKSTART, | ||
326 | &vpos, &hpos, NULL, NULL, | 328 | &vpos, &hpos, NULL, NULL, |
327 | &rdev->mode_info.crtcs[crtc_id]->base.hwmode)) && | 329 | &rdev->mode_info.crtcs[crtc_id]->base.hwmode)) && |
328 | ((vpos >= (99 * rdev->mode_info.crtcs[crtc_id]->base.hwmode.crtc_vdisplay)/100) || | 330 | ((vpos >= (99 * rdev->mode_info.crtcs[crtc_id]->base.hwmode.crtc_vdisplay)/100) || |
@@ -401,6 +403,8 @@ static void radeon_flip_work_func(struct work_struct *__work) | |||
401 | struct drm_crtc *crtc = &radeon_crtc->base; | 403 | struct drm_crtc *crtc = &radeon_crtc->base; |
402 | unsigned long flags; | 404 | unsigned long flags; |
403 | int r; | 405 | int r; |
406 | int vpos, hpos, stat, min_udelay; | ||
407 | struct drm_vblank_crtc *vblank = &crtc->dev->vblank[work->crtc_id]; | ||
404 | 408 | ||
405 | down_read(&rdev->exclusive_lock); | 409 | down_read(&rdev->exclusive_lock); |
406 | if (work->fence) { | 410 | if (work->fence) { |
@@ -437,6 +441,41 @@ static void radeon_flip_work_func(struct work_struct *__work) | |||
437 | /* set the proper interrupt */ | 441 | /* set the proper interrupt */ |
438 | radeon_irq_kms_pflip_irq_get(rdev, radeon_crtc->crtc_id); | 442 | radeon_irq_kms_pflip_irq_get(rdev, radeon_crtc->crtc_id); |
439 | 443 | ||
444 | /* If this happens to execute within the "virtually extended" vblank | ||
445 | * interval before the start of the real vblank interval then it needs | ||
446 | * to delay programming the mmio flip until the real vblank is entered. | ||
447 | * This prevents completing a flip too early due to the way we fudge | ||
448 | * our vblank counter and vblank timestamps in order to work around the | ||
449 | * problem that the hw fires vblank interrupts before actual start of | ||
450 | * vblank (when line buffer refilling is done for a frame). It | ||
451 | * complements the fudging logic in radeon_get_crtc_scanoutpos() for | ||
452 | * timestamping and radeon_get_vblank_counter_kms() for vblank counts. | ||
453 | * | ||
454 | * In practice this won't execute very often unless on very fast | ||
455 | * machines because the time window for this to happen is very small. | ||
456 | */ | ||
457 | for (;;) { | ||
458 | /* GET_DISTANCE_TO_VBLANKSTART returns distance to real vblank | ||
459 | * start in hpos, and to the "fudged earlier" vblank start in | ||
460 | * vpos. | ||
461 | */ | ||
462 | stat = radeon_get_crtc_scanoutpos(rdev->ddev, work->crtc_id, | ||
463 | GET_DISTANCE_TO_VBLANKSTART, | ||
464 | &vpos, &hpos, NULL, NULL, | ||
465 | &crtc->hwmode); | ||
466 | |||
467 | if ((stat & (DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_ACCURATE)) != | ||
468 | (DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_ACCURATE) || | ||
469 | !(vpos >= 0 && hpos <= 0)) | ||
470 | break; | ||
471 | |||
472 | /* Sleep at least until estimated real start of hw vblank */ | ||
473 | spin_unlock_irqrestore(&crtc->dev->event_lock, flags); | ||
474 | min_udelay = (-hpos + 1) * max(vblank->linedur_ns / 1000, 5); | ||
475 | usleep_range(min_udelay, 2 * min_udelay); | ||
476 | spin_lock_irqsave(&crtc->dev->event_lock, flags); | ||
477 | }; | ||
478 | |||
440 | /* do the flip (mmio) */ | 479 | /* do the flip (mmio) */ |
441 | radeon_page_flip(rdev, radeon_crtc->crtc_id, work->base); | 480 | radeon_page_flip(rdev, radeon_crtc->crtc_id, work->base); |
442 | 481 | ||
@@ -1768,6 +1807,15 @@ bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc, | |||
1768 | * \param dev Device to query. | 1807 | * \param dev Device to query. |
1769 | * \param crtc Crtc to query. | 1808 | * \param crtc Crtc to query. |
1770 | * \param flags Flags from caller (DRM_CALLED_FROM_VBLIRQ or 0). | 1809 | * \param flags Flags from caller (DRM_CALLED_FROM_VBLIRQ or 0). |
1810 | * For driver internal use only also supports these flags: | ||
1811 | * | ||
1812 | * USE_REAL_VBLANKSTART to use the real start of vblank instead | ||
1813 | * of a fudged earlier start of vblank. | ||
1814 | * | ||
1815 | * GET_DISTANCE_TO_VBLANKSTART to return distance to the | ||
1816 | * fudged earlier start of vblank in *vpos and the distance | ||
1817 | * to true start of vblank in *hpos. | ||
1818 | * | ||
1771 | * \param *vpos Location where vertical scanout position should be stored. | 1819 | * \param *vpos Location where vertical scanout position should be stored. |
1772 | * \param *hpos Location where horizontal scanout position should go. | 1820 | * \param *hpos Location where horizontal scanout position should go. |
1773 | * \param *stime Target location for timestamp taken immediately before | 1821 | * \param *stime Target location for timestamp taken immediately before |
@@ -1911,10 +1959,40 @@ int radeon_get_crtc_scanoutpos(struct drm_device *dev, unsigned int pipe, | |||
1911 | vbl_end = 0; | 1959 | vbl_end = 0; |
1912 | } | 1960 | } |
1913 | 1961 | ||
1962 | /* Called from driver internal vblank counter query code? */ | ||
1963 | if (flags & GET_DISTANCE_TO_VBLANKSTART) { | ||
1964 | /* Caller wants distance from real vbl_start in *hpos */ | ||
1965 | *hpos = *vpos - vbl_start; | ||
1966 | } | ||
1967 | |||
1968 | /* Fudge vblank to start a few scanlines earlier to handle the | ||
1969 | * problem that vblank irqs fire a few scanlines before start | ||
1970 | * of vblank. Some driver internal callers need the true vblank | ||
1971 | * start to be used and signal this via the USE_REAL_VBLANKSTART flag. | ||
1972 | * | ||
1973 | * The cause of the "early" vblank irq is that the irq is triggered | ||
1974 | * by the line buffer logic when the line buffer read position enters | ||
1975 | * the vblank, whereas our crtc scanout position naturally lags the | ||
1976 | * line buffer read position. | ||
1977 | */ | ||
1978 | if (!(flags & USE_REAL_VBLANKSTART)) | ||
1979 | vbl_start -= rdev->mode_info.crtcs[pipe]->lb_vblank_lead_lines; | ||
1980 | |||
1914 | /* Test scanout position against vblank region. */ | 1981 | /* Test scanout position against vblank region. */ |
1915 | if ((*vpos < vbl_start) && (*vpos >= vbl_end)) | 1982 | if ((*vpos < vbl_start) && (*vpos >= vbl_end)) |
1916 | in_vbl = false; | 1983 | in_vbl = false; |
1917 | 1984 | ||
1985 | /* In vblank? */ | ||
1986 | if (in_vbl) | ||
1987 | ret |= DRM_SCANOUTPOS_IN_VBLANK; | ||
1988 | |||
1989 | /* Called from driver internal vblank counter query code? */ | ||
1990 | if (flags & GET_DISTANCE_TO_VBLANKSTART) { | ||
1991 | /* Caller wants distance from fudged earlier vbl_start */ | ||
1992 | *vpos -= vbl_start; | ||
1993 | return ret; | ||
1994 | } | ||
1995 | |||
1918 | /* Check if inside vblank area and apply corrective offsets: | 1996 | /* Check if inside vblank area and apply corrective offsets: |
1919 | * vpos will then be >=0 in video scanout area, but negative | 1997 | * vpos will then be >=0 in video scanout area, but negative |
1920 | * within vblank area, counting down the number of lines until | 1998 | * within vblank area, counting down the number of lines until |
@@ -1930,31 +2008,5 @@ int radeon_get_crtc_scanoutpos(struct drm_device *dev, unsigned int pipe, | |||
1930 | /* Correct for shifted end of vbl at vbl_end. */ | 2008 | /* Correct for shifted end of vbl at vbl_end. */ |
1931 | *vpos = *vpos - vbl_end; | 2009 | *vpos = *vpos - vbl_end; |
1932 | 2010 | ||
1933 | /* In vblank? */ | ||
1934 | if (in_vbl) | ||
1935 | ret |= DRM_SCANOUTPOS_IN_VBLANK; | ||
1936 | |||
1937 | /* Is vpos outside nominal vblank area, but less than | ||
1938 | * 1/100 of a frame height away from start of vblank? | ||
1939 | * If so, assume this isn't a massively delayed vblank | ||
1940 | * interrupt, but a vblank interrupt that fired a few | ||
1941 | * microseconds before true start of vblank. Compensate | ||
1942 | * by adding a full frame duration to the final timestamp. | ||
1943 | * Happens, e.g., on ATI R500, R600. | ||
1944 | * | ||
1945 | * We only do this if DRM_CALLED_FROM_VBLIRQ. | ||
1946 | */ | ||
1947 | if ((flags & DRM_CALLED_FROM_VBLIRQ) && !in_vbl) { | ||
1948 | vbl_start = mode->crtc_vdisplay; | ||
1949 | vtotal = mode->crtc_vtotal; | ||
1950 | |||
1951 | if (vbl_start - *vpos < vtotal / 100) { | ||
1952 | *vpos -= vtotal; | ||
1953 | |||
1954 | /* Signal this correction as "applied". */ | ||
1955 | ret |= 0x8; | ||
1956 | } | ||
1957 | } | ||
1958 | |||
1959 | return ret; | 2011 | return ret; |
1960 | } | 2012 | } |