aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/amd
diff options
context:
space:
mode:
authorAlex Deucher <alexander.deucher@amd.com>2016-05-05 16:03:57 -0400
committerAlex Deucher <alexander.deucher@amd.com>2016-05-11 12:31:25 -0400
commitcb9e59d7e999c68b79f23d6016b08fc5d0bb8a8d (patch)
treeb6a3f9e2d470c1f3cc259f6ddac599fbe58b5b94 /drivers/gpu/drm/amd
parenta71dd897599c94d38eb1c4d6c8d9f8e3275e82ce (diff)
drm/amdgpu: Support DRM_MODE_PAGE_FLIP_ASYNC (v2)
When this flag is set, we program the hardware to execute the flip during horizontal blank (i.e. for the next scanline) instead of during vertical blank (i.e. for the next frame). Ported from radeon commit: drm/radeon: Support DRM_MODE_PAGE_FLIP_ASYNC v2: drop DAL change for upstream Reviewed-by: Michel Dänzer <michel.daenzer@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd')
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu.h3
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_display.c3
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/dce_v10_0.c25
-rw-r--r--drivers/gpu/drm/amd/amdgpu/dce_v11_0.c26
-rw-r--r--drivers/gpu/drm/amd/amdgpu/dce_v8_0.c20
6 files changed, 52 insertions, 27 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index 6589d43bd094..ac26b13678b1 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -727,6 +727,7 @@ struct amdgpu_flip_work {
727 unsigned shared_count; 727 unsigned shared_count;
728 struct fence **shared; 728 struct fence **shared;
729 struct fence_cb cb; 729 struct fence_cb cb;
730 bool async;
730}; 731};
731 732
732 733
@@ -2243,7 +2244,7 @@ amdgpu_get_sdma_instance(struct amdgpu_ring *ring)
2243#define amdgpu_display_hpd_set_polarity(adev, h) (adev)->mode_info.funcs->hpd_set_polarity((adev), (h)) 2244#define amdgpu_display_hpd_set_polarity(adev, h) (adev)->mode_info.funcs->hpd_set_polarity((adev), (h))
2244#define amdgpu_display_hpd_get_gpio_reg(adev) (adev)->mode_info.funcs->hpd_get_gpio_reg((adev)) 2245#define amdgpu_display_hpd_get_gpio_reg(adev) (adev)->mode_info.funcs->hpd_get_gpio_reg((adev))
2245#define amdgpu_display_bandwidth_update(adev) (adev)->mode_info.funcs->bandwidth_update((adev)) 2246#define amdgpu_display_bandwidth_update(adev) (adev)->mode_info.funcs->bandwidth_update((adev))
2246#define amdgpu_display_page_flip(adev, crtc, base) (adev)->mode_info.funcs->page_flip((adev), (crtc), (base)) 2247#define amdgpu_display_page_flip(adev, crtc, base, async) (adev)->mode_info.funcs->page_flip((adev), (crtc), (base), (async))
2247#define amdgpu_display_page_flip_get_scanoutpos(adev, crtc, vbl, pos) (adev)->mode_info.funcs->page_flip_get_scanoutpos((adev), (crtc), (vbl), (pos)) 2248#define amdgpu_display_page_flip_get_scanoutpos(adev, crtc, vbl, pos) (adev)->mode_info.funcs->page_flip_get_scanoutpos((adev), (crtc), (vbl), (pos))
2248#define amdgpu_display_add_encoder(adev, e, s, c) (adev)->mode_info.funcs->add_encoder((adev), (e), (s), (c)) 2249#define amdgpu_display_add_encoder(adev, e, s, c) (adev)->mode_info.funcs->add_encoder((adev), (e), (s), (c))
2249#define amdgpu_display_add_connector(adev, ci, sd, ct, ib, coi, h, r) (adev)->mode_info.funcs->add_connector((adev), (ci), (sd), (ct), (ib), (coi), (h), (r)) 2250#define amdgpu_display_add_connector(adev, ci, sd, ct, ib, coi, h, r) (adev)->mode_info.funcs->add_connector((adev), (ci), (sd), (ct), (ib), (coi), (h), (r))
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
index c835abe65df3..726803069fef 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
@@ -132,7 +132,7 @@ static void amdgpu_flip_work_func(struct work_struct *__work)
132 vblank->linedur_ns / 1000, stat, vpos, hpos); 132 vblank->linedur_ns / 1000, stat, vpos, hpos);
133 133
134 /* Do the flip (mmio) */ 134 /* Do the flip (mmio) */
135 adev->mode_info.funcs->page_flip(adev, work->crtc_id, work->base); 135 adev->mode_info.funcs->page_flip(adev, work->crtc_id, work->base, work->async);
136 136
137 /* Set the flip status */ 137 /* Set the flip status */
138 amdgpuCrtc->pflip_status = AMDGPU_FLIP_SUBMITTED; 138 amdgpuCrtc->pflip_status = AMDGPU_FLIP_SUBMITTED;
@@ -197,6 +197,7 @@ int amdgpu_crtc_page_flip(struct drm_crtc *crtc,
197 work->event = event; 197 work->event = event;
198 work->adev = adev; 198 work->adev = adev;
199 work->crtc_id = amdgpu_crtc->crtc_id; 199 work->crtc_id = amdgpu_crtc->crtc_id;
200 work->async = (page_flip_flags & DRM_MODE_PAGE_FLIP_ASYNC) != 0;
200 201
201 /* schedule unpin of the old buffer */ 202 /* schedule unpin of the old buffer */
202 old_amdgpu_fb = to_amdgpu_framebuffer(crtc->primary->fb); 203 old_amdgpu_fb = to_amdgpu_framebuffer(crtc->primary->fb);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
index 8a253aa0b551..6b1d7d306564 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
@@ -283,7 +283,7 @@ struct amdgpu_display_funcs {
283 u32 (*hpd_get_gpio_reg)(struct amdgpu_device *adev); 283 u32 (*hpd_get_gpio_reg)(struct amdgpu_device *adev);
284 /* pageflipping */ 284 /* pageflipping */
285 void (*page_flip)(struct amdgpu_device *adev, 285 void (*page_flip)(struct amdgpu_device *adev,
286 int crtc_id, u64 crtc_base); 286 int crtc_id, u64 crtc_base, bool async);
287 int (*page_flip_get_scanoutpos)(struct amdgpu_device *adev, int crtc, 287 int (*page_flip_get_scanoutpos)(struct amdgpu_device *adev, int crtc,
288 u32 *vbl, u32 *position); 288 u32 *vbl, u32 *position);
289 /* display topology setup */ 289 /* display topology setup */
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
index 8af5fbc60e5b..578328860396 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
@@ -284,10 +284,16 @@ static void dce_v10_0_pageflip_interrupt_fini(struct amdgpu_device *adev)
284 * surface base address. 284 * surface base address.
285 */ 285 */
286static void dce_v10_0_page_flip(struct amdgpu_device *adev, 286static void dce_v10_0_page_flip(struct amdgpu_device *adev,
287 int crtc_id, u64 crtc_base) 287 int crtc_id, u64 crtc_base, bool async)
288{ 288{
289 struct amdgpu_crtc *amdgpu_crtc = adev->mode_info.crtcs[crtc_id]; 289 struct amdgpu_crtc *amdgpu_crtc = adev->mode_info.crtcs[crtc_id];
290 u32 tmp;
290 291
292 /* flip at hsync for async, default is vsync */
293 tmp = RREG32(mmGRPH_FLIP_CONTROL + amdgpu_crtc->crtc_offset);
294 tmp = REG_SET_FIELD(tmp, GRPH_FLIP_CONTROL,
295 GRPH_SURFACE_UPDATE_H_RETRACE_EN, async ? 1 : 0);
296 WREG32(mmGRPH_FLIP_CONTROL + amdgpu_crtc->crtc_offset, tmp);
291 /* update the primary scanout address */ 297 /* update the primary scanout address */
292 WREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset, 298 WREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset,
293 upper_32_bits(crtc_base)); 299 upper_32_bits(crtc_base));
@@ -2211,6 +2217,14 @@ static int dce_v10_0_crtc_do_set_base(struct drm_crtc *crtc,
2211 2217
2212 dce_v10_0_vga_enable(crtc, false); 2218 dce_v10_0_vga_enable(crtc, false);
2213 2219
2220 /* Make sure surface address is updated at vertical blank rather than
2221 * horizontal blank
2222 */
2223 tmp = RREG32(mmGRPH_FLIP_CONTROL + amdgpu_crtc->crtc_offset);
2224 tmp = REG_SET_FIELD(tmp, GRPH_FLIP_CONTROL,
2225 GRPH_SURFACE_UPDATE_H_RETRACE_EN, 0);
2226 WREG32(mmGRPH_FLIP_CONTROL + amdgpu_crtc->crtc_offset, tmp);
2227
2214 WREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset, 2228 WREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset,
2215 upper_32_bits(fb_location)); 2229 upper_32_bits(fb_location));
2216 WREG32(mmGRPH_SECONDARY_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset, 2230 WREG32(mmGRPH_SECONDARY_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset,
@@ -2261,13 +2275,6 @@ static int dce_v10_0_crtc_do_set_base(struct drm_crtc *crtc,
2261 WREG32(mmVIEWPORT_SIZE + amdgpu_crtc->crtc_offset, 2275 WREG32(mmVIEWPORT_SIZE + amdgpu_crtc->crtc_offset,
2262 (viewport_w << 16) | viewport_h); 2276 (viewport_w << 16) | viewport_h);
2263 2277
2264 /* pageflip setup */
2265 /* make sure flip is at vb rather than hb */
2266 tmp = RREG32(mmGRPH_FLIP_CONTROL + amdgpu_crtc->crtc_offset);
2267 tmp = REG_SET_FIELD(tmp, GRPH_FLIP_CONTROL,
2268 GRPH_SURFACE_UPDATE_H_RETRACE_EN, 0);
2269 WREG32(mmGRPH_FLIP_CONTROL + amdgpu_crtc->crtc_offset, tmp);
2270
2271 /* set pageflip to happen only at start of vblank interval (front porch) */ 2278 /* set pageflip to happen only at start of vblank interval (front porch) */
2272 WREG32(mmMASTER_UPDATE_MODE + amdgpu_crtc->crtc_offset, 3); 2279 WREG32(mmMASTER_UPDATE_MODE + amdgpu_crtc->crtc_offset, 3);
2273 2280
@@ -2992,6 +2999,8 @@ static int dce_v10_0_sw_init(void *handle)
2992 2999
2993 adev->ddev->mode_config.funcs = &amdgpu_mode_funcs; 3000 adev->ddev->mode_config.funcs = &amdgpu_mode_funcs;
2994 3001
3002 adev->ddev->mode_config.async_page_flip = true;
3003
2995 adev->ddev->mode_config.max_width = 16384; 3004 adev->ddev->mode_config.max_width = 16384;
2996 adev->ddev->mode_config.max_height = 16384; 3005 adev->ddev->mode_config.max_height = 16384;
2997 3006
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
index e7b951f00421..60bfeb1b956e 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
@@ -302,10 +302,17 @@ static void dce_v11_0_pageflip_interrupt_fini(struct amdgpu_device *adev)
302 * surface base address. 302 * surface base address.
303 */ 303 */
304static void dce_v11_0_page_flip(struct amdgpu_device *adev, 304static void dce_v11_0_page_flip(struct amdgpu_device *adev,
305 int crtc_id, u64 crtc_base) 305 int crtc_id, u64 crtc_base, bool async)
306{ 306{
307 struct amdgpu_crtc *amdgpu_crtc = adev->mode_info.crtcs[crtc_id]; 307 struct amdgpu_crtc *amdgpu_crtc = adev->mode_info.crtcs[crtc_id];
308 u32 tmp;
308 309
310 /* flip at hsync for async, default is vsync */
311 /* use UPDATE_IMMEDIATE_EN instead for async? */
312 tmp = RREG32(mmGRPH_FLIP_CONTROL + amdgpu_crtc->crtc_offset);
313 tmp = REG_SET_FIELD(tmp, GRPH_FLIP_CONTROL,
314 GRPH_SURFACE_UPDATE_H_RETRACE_EN, async ? 1 : 0);
315 WREG32(mmGRPH_FLIP_CONTROL + amdgpu_crtc->crtc_offset, tmp);
309 /* update the scanout addresses */ 316 /* update the scanout addresses */
310 WREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset, 317 WREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset,
311 upper_32_bits(crtc_base)); 318 upper_32_bits(crtc_base));
@@ -2185,6 +2192,14 @@ static int dce_v11_0_crtc_do_set_base(struct drm_crtc *crtc,
2185 2192
2186 dce_v11_0_vga_enable(crtc, false); 2193 dce_v11_0_vga_enable(crtc, false);
2187 2194
2195 /* Make sure surface address is updated at vertical blank rather than
2196 * horizontal blank
2197 */
2198 tmp = RREG32(mmGRPH_FLIP_CONTROL + amdgpu_crtc->crtc_offset);
2199 tmp = REG_SET_FIELD(tmp, GRPH_FLIP_CONTROL,
2200 GRPH_SURFACE_UPDATE_H_RETRACE_EN, 0);
2201 WREG32(mmGRPH_FLIP_CONTROL + amdgpu_crtc->crtc_offset, tmp);
2202
2188 WREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset, 2203 WREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset,
2189 upper_32_bits(fb_location)); 2204 upper_32_bits(fb_location));
2190 WREG32(mmGRPH_SECONDARY_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset, 2205 WREG32(mmGRPH_SECONDARY_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset,
@@ -2235,13 +2250,6 @@ static int dce_v11_0_crtc_do_set_base(struct drm_crtc *crtc,
2235 WREG32(mmVIEWPORT_SIZE + amdgpu_crtc->crtc_offset, 2250 WREG32(mmVIEWPORT_SIZE + amdgpu_crtc->crtc_offset,
2236 (viewport_w << 16) | viewport_h); 2251 (viewport_w << 16) | viewport_h);
2237 2252
2238 /* pageflip setup */
2239 /* make sure flip is at vb rather than hb */
2240 tmp = RREG32(mmGRPH_FLIP_CONTROL + amdgpu_crtc->crtc_offset);
2241 tmp = REG_SET_FIELD(tmp, GRPH_FLIP_CONTROL,
2242 GRPH_SURFACE_UPDATE_H_RETRACE_EN, 0);
2243 WREG32(mmGRPH_FLIP_CONTROL + amdgpu_crtc->crtc_offset, tmp);
2244
2245 /* set pageflip to happen only at start of vblank interval (front porch) */ 2253 /* set pageflip to happen only at start of vblank interval (front porch) */
2246 WREG32(mmCRTC_MASTER_UPDATE_MODE + amdgpu_crtc->crtc_offset, 3); 2254 WREG32(mmCRTC_MASTER_UPDATE_MODE + amdgpu_crtc->crtc_offset, 3);
2247 2255
@@ -3042,6 +3050,8 @@ static int dce_v11_0_sw_init(void *handle)
3042 3050
3043 adev->ddev->mode_config.funcs = &amdgpu_mode_funcs; 3051 adev->ddev->mode_config.funcs = &amdgpu_mode_funcs;
3044 3052
3053 adev->ddev->mode_config.async_page_flip = true;
3054
3045 adev->ddev->mode_config.max_width = 16384; 3055 adev->ddev->mode_config.max_width = 16384;
3046 adev->ddev->mode_config.max_height = 16384; 3056 adev->ddev->mode_config.max_height = 16384;
3047 3057
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
index 25e6af03c406..c73993472059 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
@@ -233,10 +233,13 @@ static void dce_v8_0_pageflip_interrupt_fini(struct amdgpu_device *adev)
233 * surface base address. 233 * surface base address.
234 */ 234 */
235static void dce_v8_0_page_flip(struct amdgpu_device *adev, 235static void dce_v8_0_page_flip(struct amdgpu_device *adev,
236 int crtc_id, u64 crtc_base) 236 int crtc_id, u64 crtc_base, bool async)
237{ 237{
238 struct amdgpu_crtc *amdgpu_crtc = adev->mode_info.crtcs[crtc_id]; 238 struct amdgpu_crtc *amdgpu_crtc = adev->mode_info.crtcs[crtc_id];
239 239
240 /* flip at hsync for async, default is vsync */
241 WREG32(mmGRPH_FLIP_CONTROL + amdgpu_crtc->crtc_offset, async ?
242 GRPH_FLIP_CONTROL__GRPH_SURFACE_UPDATE_H_RETRACE_EN_MASK : 0);
240 /* update the primary scanout addresses */ 243 /* update the primary scanout addresses */
241 WREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset, 244 WREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset,
242 upper_32_bits(crtc_base)); 245 upper_32_bits(crtc_base));
@@ -1999,7 +2002,7 @@ static int dce_v8_0_crtc_do_set_base(struct drm_crtc *crtc,
1999 uint32_t fb_format, fb_pitch_pixels; 2002 uint32_t fb_format, fb_pitch_pixels;
2000 u32 fb_swap = (GRPH_ENDIAN_NONE << GRPH_SWAP_CNTL__GRPH_ENDIAN_SWAP__SHIFT); 2003 u32 fb_swap = (GRPH_ENDIAN_NONE << GRPH_SWAP_CNTL__GRPH_ENDIAN_SWAP__SHIFT);
2001 u32 pipe_config; 2004 u32 pipe_config;
2002 u32 tmp, viewport_w, viewport_h; 2005 u32 viewport_w, viewport_h;
2003 int r; 2006 int r;
2004 bool bypass_lut = false; 2007 bool bypass_lut = false;
2005 2008
@@ -2135,6 +2138,11 @@ static int dce_v8_0_crtc_do_set_base(struct drm_crtc *crtc,
2135 2138
2136 dce_v8_0_vga_enable(crtc, false); 2139 dce_v8_0_vga_enable(crtc, false);
2137 2140
2141 /* Make sure surface address is updated at vertical blank rather than
2142 * horizontal blank
2143 */
2144 WREG32(mmGRPH_FLIP_CONTROL + amdgpu_crtc->crtc_offset, 0);
2145
2138 WREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset, 2146 WREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset,
2139 upper_32_bits(fb_location)); 2147 upper_32_bits(fb_location));
2140 WREG32(mmGRPH_SECONDARY_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset, 2148 WREG32(mmGRPH_SECONDARY_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset,
@@ -2182,12 +2190,6 @@ static int dce_v8_0_crtc_do_set_base(struct drm_crtc *crtc,
2182 WREG32(mmVIEWPORT_SIZE + amdgpu_crtc->crtc_offset, 2190 WREG32(mmVIEWPORT_SIZE + amdgpu_crtc->crtc_offset,
2183 (viewport_w << 16) | viewport_h); 2191 (viewport_w << 16) | viewport_h);
2184 2192
2185 /* pageflip setup */
2186 /* make sure flip is at vb rather than hb */
2187 tmp = RREG32(mmGRPH_FLIP_CONTROL + amdgpu_crtc->crtc_offset);
2188 tmp &= ~GRPH_FLIP_CONTROL__GRPH_SURFACE_UPDATE_H_RETRACE_EN_MASK;
2189 WREG32(mmGRPH_FLIP_CONTROL + amdgpu_crtc->crtc_offset, tmp);
2190
2191 /* set pageflip to happen only at start of vblank interval (front porch) */ 2193 /* set pageflip to happen only at start of vblank interval (front porch) */
2192 WREG32(mmMASTER_UPDATE_MODE + amdgpu_crtc->crtc_offset, 3); 2194 WREG32(mmMASTER_UPDATE_MODE + amdgpu_crtc->crtc_offset, 3);
2193 2195
@@ -2902,6 +2904,8 @@ static int dce_v8_0_sw_init(void *handle)
2902 2904
2903 adev->ddev->mode_config.funcs = &amdgpu_mode_funcs; 2905 adev->ddev->mode_config.funcs = &amdgpu_mode_funcs;
2904 2906
2907 adev->ddev->mode_config.async_page_flip = true;
2908
2905 adev->ddev->mode_config.max_width = 16384; 2909 adev->ddev->mode_config.max_width = 16384;
2906 adev->ddev->mode_config.max_height = 16384; 2910 adev->ddev->mode_config.max_height = 16384;
2907 2911