提交 f6c7aba4 编写于 作者: M Michel Dänzer 提交者: Alex Deucher

drm/amdgpu: Keep the pflip interrupts always enabled v7

This fixes flickering issues caused by prematurely firing pflip
interrupts.

v2 (chk): add commit message, fix DCE V10/V11 and DM as well
v3: Re-enable pflip interrupt wherever we re-enable a CRTC
v4: Enable pflip interrupt in DAL as well
v5: drop DAL changes for upstream
v6: (agd): only enable interrupts on crtcs that exist
v7: (agd): integrate suggestions from Michel
Signed-off-by: NMichel Dänzer <michel.daenzer@amd.com>
Signed-off-by: NChristian König <christian.koenig@amd.com>
Reviewed-by: NAlex Deucher <alexander.deucher@amd.com>
Cc: stable@vger.kernel.org
上级 80c083c5
...@@ -85,8 +85,6 @@ static void amdgpu_flip_work_func(struct work_struct *__work) ...@@ -85,8 +85,6 @@ static void amdgpu_flip_work_func(struct work_struct *__work)
/* We borrow the event spin lock for protecting flip_status */ /* We borrow the event spin lock for protecting flip_status */
spin_lock_irqsave(&crtc->dev->event_lock, flags); spin_lock_irqsave(&crtc->dev->event_lock, flags);
/* set the proper interrupt */
amdgpu_irq_get(adev, &adev->pageflip_irq, work->crtc_id);
/* do the flip (mmio) */ /* do the flip (mmio) */
adev->mode_info.funcs->page_flip(adev, work->crtc_id, work->base); adev->mode_info.funcs->page_flip(adev, work->crtc_id, work->base);
/* set the flip status */ /* set the flip status */
......
...@@ -255,6 +255,24 @@ static u32 dce_v10_0_vblank_get_counter(struct amdgpu_device *adev, int crtc) ...@@ -255,6 +255,24 @@ static u32 dce_v10_0_vblank_get_counter(struct amdgpu_device *adev, int crtc)
return RREG32(mmCRTC_STATUS_FRAME_COUNT + crtc_offsets[crtc]); return RREG32(mmCRTC_STATUS_FRAME_COUNT + crtc_offsets[crtc]);
} }
static void dce_v10_0_pageflip_interrupt_init(struct amdgpu_device *adev)
{
unsigned i;
/* Enable pflip interrupts */
for (i = 0; i < adev->mode_info.num_crtc; i++)
amdgpu_irq_get(adev, &adev->pageflip_irq, i);
}
static void dce_v10_0_pageflip_interrupt_fini(struct amdgpu_device *adev)
{
unsigned i;
/* Disable pflip interrupts */
for (i = 0; i < adev->mode_info.num_crtc; i++)
amdgpu_irq_put(adev, &adev->pageflip_irq, i);
}
/** /**
* dce_v10_0_page_flip - pageflip callback. * dce_v10_0_page_flip - pageflip callback.
* *
...@@ -2663,9 +2681,10 @@ static void dce_v10_0_crtc_dpms(struct drm_crtc *crtc, int mode) ...@@ -2663,9 +2681,10 @@ static void dce_v10_0_crtc_dpms(struct drm_crtc *crtc, int mode)
dce_v10_0_vga_enable(crtc, true); dce_v10_0_vga_enable(crtc, true);
amdgpu_atombios_crtc_blank(crtc, ATOM_DISABLE); amdgpu_atombios_crtc_blank(crtc, ATOM_DISABLE);
dce_v10_0_vga_enable(crtc, false); dce_v10_0_vga_enable(crtc, false);
/* Make sure VBLANK interrupt is still enabled */ /* Make sure VBLANK and PFLIP interrupts are still enabled */
type = amdgpu_crtc_idx_to_irq_type(adev, amdgpu_crtc->crtc_id); type = amdgpu_crtc_idx_to_irq_type(adev, amdgpu_crtc->crtc_id);
amdgpu_irq_update(adev, &adev->crtc_irq, type); amdgpu_irq_update(adev, &adev->crtc_irq, type);
amdgpu_irq_update(adev, &adev->pageflip_irq, type);
drm_vblank_post_modeset(dev, amdgpu_crtc->crtc_id); drm_vblank_post_modeset(dev, amdgpu_crtc->crtc_id);
dce_v10_0_crtc_load_lut(crtc); dce_v10_0_crtc_load_lut(crtc);
break; break;
...@@ -3025,6 +3044,8 @@ static int dce_v10_0_hw_init(void *handle) ...@@ -3025,6 +3044,8 @@ static int dce_v10_0_hw_init(void *handle)
dce_v10_0_audio_enable(adev, &adev->mode_info.audio.pin[i], false); dce_v10_0_audio_enable(adev, &adev->mode_info.audio.pin[i], false);
} }
dce_v10_0_pageflip_interrupt_init(adev);
return 0; return 0;
} }
...@@ -3039,6 +3060,8 @@ static int dce_v10_0_hw_fini(void *handle) ...@@ -3039,6 +3060,8 @@ static int dce_v10_0_hw_fini(void *handle)
dce_v10_0_audio_enable(adev, &adev->mode_info.audio.pin[i], false); dce_v10_0_audio_enable(adev, &adev->mode_info.audio.pin[i], false);
} }
dce_v10_0_pageflip_interrupt_fini(adev);
return 0; return 0;
} }
...@@ -3050,6 +3073,8 @@ static int dce_v10_0_suspend(void *handle) ...@@ -3050,6 +3073,8 @@ static int dce_v10_0_suspend(void *handle)
dce_v10_0_hpd_fini(adev); dce_v10_0_hpd_fini(adev);
dce_v10_0_pageflip_interrupt_fini(adev);
return 0; return 0;
} }
...@@ -3075,6 +3100,8 @@ static int dce_v10_0_resume(void *handle) ...@@ -3075,6 +3100,8 @@ static int dce_v10_0_resume(void *handle)
/* initialize hpd */ /* initialize hpd */
dce_v10_0_hpd_init(adev); dce_v10_0_hpd_init(adev);
dce_v10_0_pageflip_interrupt_init(adev);
return 0; return 0;
} }
...@@ -3369,7 +3396,6 @@ static int dce_v10_0_pageflip_irq(struct amdgpu_device *adev, ...@@ -3369,7 +3396,6 @@ static int dce_v10_0_pageflip_irq(struct amdgpu_device *adev,
spin_unlock_irqrestore(&adev->ddev->event_lock, flags); spin_unlock_irqrestore(&adev->ddev->event_lock, flags);
drm_vblank_put(adev->ddev, amdgpu_crtc->crtc_id); drm_vblank_put(adev->ddev, amdgpu_crtc->crtc_id);
amdgpu_irq_put(adev, &adev->pageflip_irq, crtc_id);
queue_work(amdgpu_crtc->pflip_queue, &works->unpin_work); queue_work(amdgpu_crtc->pflip_queue, &works->unpin_work);
return 0; return 0;
......
...@@ -233,6 +233,24 @@ static u32 dce_v11_0_vblank_get_counter(struct amdgpu_device *adev, int crtc) ...@@ -233,6 +233,24 @@ static u32 dce_v11_0_vblank_get_counter(struct amdgpu_device *adev, int crtc)
return RREG32(mmCRTC_STATUS_FRAME_COUNT + crtc_offsets[crtc]); return RREG32(mmCRTC_STATUS_FRAME_COUNT + crtc_offsets[crtc]);
} }
static void dce_v11_0_pageflip_interrupt_init(struct amdgpu_device *adev)
{
unsigned i;
/* Enable pflip interrupts */
for (i = 0; i < adev->mode_info.num_crtc; i++)
amdgpu_irq_get(adev, &adev->pageflip_irq, i);
}
static void dce_v11_0_pageflip_interrupt_fini(struct amdgpu_device *adev)
{
unsigned i;
/* Disable pflip interrupts */
for (i = 0; i < adev->mode_info.num_crtc; i++)
amdgpu_irq_put(adev, &adev->pageflip_irq, i);
}
/** /**
* dce_v11_0_page_flip - pageflip callback. * dce_v11_0_page_flip - pageflip callback.
* *
...@@ -2640,9 +2658,10 @@ static void dce_v11_0_crtc_dpms(struct drm_crtc *crtc, int mode) ...@@ -2640,9 +2658,10 @@ static void dce_v11_0_crtc_dpms(struct drm_crtc *crtc, int mode)
dce_v11_0_vga_enable(crtc, true); dce_v11_0_vga_enable(crtc, true);
amdgpu_atombios_crtc_blank(crtc, ATOM_DISABLE); amdgpu_atombios_crtc_blank(crtc, ATOM_DISABLE);
dce_v11_0_vga_enable(crtc, false); dce_v11_0_vga_enable(crtc, false);
/* Make sure VBLANK interrupt is still enabled */ /* Make sure VBLANK and PFLIP interrupts are still enabled */
type = amdgpu_crtc_idx_to_irq_type(adev, amdgpu_crtc->crtc_id); type = amdgpu_crtc_idx_to_irq_type(adev, amdgpu_crtc->crtc_id);
amdgpu_irq_update(adev, &adev->crtc_irq, type); amdgpu_irq_update(adev, &adev->crtc_irq, type);
amdgpu_irq_update(adev, &adev->pageflip_irq, type);
drm_vblank_post_modeset(dev, amdgpu_crtc->crtc_id); drm_vblank_post_modeset(dev, amdgpu_crtc->crtc_id);
dce_v11_0_crtc_load_lut(crtc); dce_v11_0_crtc_load_lut(crtc);
break; break;
...@@ -3000,6 +3019,8 @@ static int dce_v11_0_hw_init(void *handle) ...@@ -3000,6 +3019,8 @@ static int dce_v11_0_hw_init(void *handle)
dce_v11_0_audio_enable(adev, &adev->mode_info.audio.pin[i], false); dce_v11_0_audio_enable(adev, &adev->mode_info.audio.pin[i], false);
} }
dce_v11_0_pageflip_interrupt_init(adev);
return 0; return 0;
} }
...@@ -3014,6 +3035,8 @@ static int dce_v11_0_hw_fini(void *handle) ...@@ -3014,6 +3035,8 @@ static int dce_v11_0_hw_fini(void *handle)
dce_v11_0_audio_enable(adev, &adev->mode_info.audio.pin[i], false); dce_v11_0_audio_enable(adev, &adev->mode_info.audio.pin[i], false);
} }
dce_v11_0_pageflip_interrupt_fini(adev);
return 0; return 0;
} }
...@@ -3025,6 +3048,8 @@ static int dce_v11_0_suspend(void *handle) ...@@ -3025,6 +3048,8 @@ static int dce_v11_0_suspend(void *handle)
dce_v11_0_hpd_fini(adev); dce_v11_0_hpd_fini(adev);
dce_v11_0_pageflip_interrupt_fini(adev);
return 0; return 0;
} }
...@@ -3051,6 +3076,8 @@ static int dce_v11_0_resume(void *handle) ...@@ -3051,6 +3076,8 @@ static int dce_v11_0_resume(void *handle)
/* initialize hpd */ /* initialize hpd */
dce_v11_0_hpd_init(adev); dce_v11_0_hpd_init(adev);
dce_v11_0_pageflip_interrupt_init(adev);
return 0; return 0;
} }
...@@ -3345,7 +3372,6 @@ static int dce_v11_0_pageflip_irq(struct amdgpu_device *adev, ...@@ -3345,7 +3372,6 @@ static int dce_v11_0_pageflip_irq(struct amdgpu_device *adev,
spin_unlock_irqrestore(&adev->ddev->event_lock, flags); spin_unlock_irqrestore(&adev->ddev->event_lock, flags);
drm_vblank_put(adev->ddev, amdgpu_crtc->crtc_id); drm_vblank_put(adev->ddev, amdgpu_crtc->crtc_id);
amdgpu_irq_put(adev, &adev->pageflip_irq, crtc_id);
queue_work(amdgpu_crtc->pflip_queue, &works->unpin_work); queue_work(amdgpu_crtc->pflip_queue, &works->unpin_work);
return 0; return 0;
......
...@@ -204,6 +204,24 @@ static u32 dce_v8_0_vblank_get_counter(struct amdgpu_device *adev, int crtc) ...@@ -204,6 +204,24 @@ static u32 dce_v8_0_vblank_get_counter(struct amdgpu_device *adev, int crtc)
return RREG32(mmCRTC_STATUS_FRAME_COUNT + crtc_offsets[crtc]); return RREG32(mmCRTC_STATUS_FRAME_COUNT + crtc_offsets[crtc]);
} }
static void dce_v8_0_pageflip_interrupt_init(struct amdgpu_device *adev)
{
unsigned i;
/* Enable pflip interrupts */
for (i = 0; i < adev->mode_info.num_crtc; i++)
amdgpu_irq_get(adev, &adev->pageflip_irq, i);
}
static void dce_v8_0_pageflip_interrupt_fini(struct amdgpu_device *adev)
{
unsigned i;
/* Disable pflip interrupts */
for (i = 0; i < adev->mode_info.num_crtc; i++)
amdgpu_irq_put(adev, &adev->pageflip_irq, i);
}
/** /**
* dce_v8_0_page_flip - pageflip callback. * dce_v8_0_page_flip - pageflip callback.
* *
...@@ -2575,9 +2593,10 @@ static void dce_v8_0_crtc_dpms(struct drm_crtc *crtc, int mode) ...@@ -2575,9 +2593,10 @@ static void dce_v8_0_crtc_dpms(struct drm_crtc *crtc, int mode)
dce_v8_0_vga_enable(crtc, true); dce_v8_0_vga_enable(crtc, true);
amdgpu_atombios_crtc_blank(crtc, ATOM_DISABLE); amdgpu_atombios_crtc_blank(crtc, ATOM_DISABLE);
dce_v8_0_vga_enable(crtc, false); dce_v8_0_vga_enable(crtc, false);
/* Make sure VBLANK interrupt is still enabled */ /* Make sure VBLANK and PFLIP interrupts are still enabled */
type = amdgpu_crtc_idx_to_irq_type(adev, amdgpu_crtc->crtc_id); type = amdgpu_crtc_idx_to_irq_type(adev, amdgpu_crtc->crtc_id);
amdgpu_irq_update(adev, &adev->crtc_irq, type); amdgpu_irq_update(adev, &adev->crtc_irq, type);
amdgpu_irq_update(adev, &adev->pageflip_irq, type);
drm_vblank_post_modeset(dev, amdgpu_crtc->crtc_id); drm_vblank_post_modeset(dev, amdgpu_crtc->crtc_id);
dce_v8_0_crtc_load_lut(crtc); dce_v8_0_crtc_load_lut(crtc);
break; break;
...@@ -2933,6 +2952,8 @@ static int dce_v8_0_hw_init(void *handle) ...@@ -2933,6 +2952,8 @@ static int dce_v8_0_hw_init(void *handle)
dce_v8_0_audio_enable(adev, &adev->mode_info.audio.pin[i], false); dce_v8_0_audio_enable(adev, &adev->mode_info.audio.pin[i], false);
} }
dce_v8_0_pageflip_interrupt_init(adev);
return 0; return 0;
} }
...@@ -2947,6 +2968,8 @@ static int dce_v8_0_hw_fini(void *handle) ...@@ -2947,6 +2968,8 @@ static int dce_v8_0_hw_fini(void *handle)
dce_v8_0_audio_enable(adev, &adev->mode_info.audio.pin[i], false); dce_v8_0_audio_enable(adev, &adev->mode_info.audio.pin[i], false);
} }
dce_v8_0_pageflip_interrupt_fini(adev);
return 0; return 0;
} }
...@@ -2958,6 +2981,8 @@ static int dce_v8_0_suspend(void *handle) ...@@ -2958,6 +2981,8 @@ static int dce_v8_0_suspend(void *handle)
dce_v8_0_hpd_fini(adev); dce_v8_0_hpd_fini(adev);
dce_v8_0_pageflip_interrupt_fini(adev);
return 0; return 0;
} }
...@@ -2981,6 +3006,8 @@ static int dce_v8_0_resume(void *handle) ...@@ -2981,6 +3006,8 @@ static int dce_v8_0_resume(void *handle)
/* initialize hpd */ /* initialize hpd */
dce_v8_0_hpd_init(adev); dce_v8_0_hpd_init(adev);
dce_v8_0_pageflip_interrupt_init(adev);
return 0; return 0;
} }
...@@ -3376,7 +3403,6 @@ static int dce_v8_0_pageflip_irq(struct amdgpu_device *adev, ...@@ -3376,7 +3403,6 @@ static int dce_v8_0_pageflip_irq(struct amdgpu_device *adev,
spin_unlock_irqrestore(&adev->ddev->event_lock, flags); spin_unlock_irqrestore(&adev->ddev->event_lock, flags);
drm_vblank_put(adev->ddev, amdgpu_crtc->crtc_id); drm_vblank_put(adev->ddev, amdgpu_crtc->crtc_id);
amdgpu_irq_put(adev, &adev->pageflip_irq, crtc_id);
queue_work(amdgpu_crtc->pflip_queue, &works->unpin_work); queue_work(amdgpu_crtc->pflip_queue, &works->unpin_work);
return 0; return 0;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册