nouveau: add vblank methods on newer cards
Subsystems (3)
PATCH 3/3 nouveau: add vblank methods on newer cards
Allow the software channel to be created now, since methods for vblanking have been implemented.
The instmem flush seems to be needed on fermi to prevent a race, but I enabled it on earlier cards too since they seem to be susceptible to the same race.
Signed-off-by Maarten Lankhorst <[email protected]>
--- drivers/gpu/drm/nouveau/nouveau_abi16.c | 9 ---- drivers/gpu/drm/nouveau/nouveau_display.c | 8 +++- drivers/gpu/drm/nouveau/nouveau_drv.h | 1 drivers/gpu/drm/nouveau/nv50_display.c | 25 ++++++++---- drivers/gpu/drm/nouveau/nv50_software.c | 2 - drivers/gpu/drm/nouveau/nvc0_software.c | 63 +++++++++++++++++++++++++++++ drivers/gpu/drm/nouveau/nvd0_display.c | 5 ++ 7 files changed, 95 insertions(+), 18 deletions(-)
drivers/gpu/drm/nouveau/nouveau_abi16.c +1 -8
@@ -173,15 +173,8 @@ nouveau_abi16_ioctl_grobj_alloc(ABI16_IOCTL_ARGS)return -EINVAL ;/* compatibility with userspace that assumes 506e for all chipsets */ -if (init->class ==0x506e ) { +if (init->class ==0x506e ) init->class =nouveau_software_class (dev); -if (init->class ==0x906e ) -return 0 ; - }else -if (init->class ==0x906e ) { -NV_ERROR (dev,"906e not supported yet\n" ); -return -EINVAL ; - } chan =nouveau_channel_get (file_priv, init->channel);if (IS_ERR (chan))
drivers/gpu/drm/nouveau/nouveau_display.c +6 -2
@@ -364,7 +364,9 @@ nouveau_vblank_enable(struct drm_device *dev, int crtc) {struct drm_nouveau_private *dev_priv = dev->dev_private; -if (dev_priv->card_type >=NV_50 ) +if (dev_priv->card_type >=NV_D0 ) +nv_mask (dev,0x6100c0 + (crtc *0x800 ),0x5 ,0x5 ); +else if (dev_priv->card_type >=NV_50 )nv_mask (dev,NV50_PDISPLAY_INTR_EN_1 ,0 ,NV50_PDISPLAY_INTR_EN_1_VBLANK_CRTC_ (crtc));else
@@ -379,7 +381,9 @@ nouveau_vblank_disable(struct drm_device *dev, int crtc) {struct drm_nouveau_private *dev_priv = dev->dev_private; -if (dev_priv->card_type >=NV_50 ) +if (dev_priv->card_type >=NV_D0 ) +nv_mask (dev,0x6100c0 + (crtc *0x800 ),0x5 ,0 ); +else if (dev_priv->card_type >=NV_50 )nv_mask (dev,NV50_PDISPLAY_INTR_EN_1 ,NV50_PDISPLAY_INTR_EN_1_VBLANK_CRTC_ (crtc),0 );else
drivers/gpu/drm/nouveau/nouveau_drv.h +1 -0
@@ -1374,6 +1374,7 @@ int nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, struct drm_pending_vblank_event *event);int nouveau_finish_page_flip (struct nouveau_channel *,struct nouveau_page_flip_state *); +void nv50_display_vblank_crtc_handler (struct drm_device *dev,int crtc);int nouveau_display_dumb_create (struct drm_file *,struct drm_device *,struct drm_mode_create_dumb *args); int nouveau_display_dumb_map_offset(struct drm_file *, struct drm_device *,
drivers/gpu/drm/nouveau/nv50_display.c +18 -7
@@ -643,7 +643,7 @@ nv50_display_script_select(struct drm_device *dev, struct dcb_entry *dcb,return script; } -static void +void nv50_display_vblank_crtc_handler (struct drm_device *dev,int crtc) {struct drm_nouveau_private *dev_priv = dev->dev_private;
@@ -655,18 +655,29 @@ nv50_display_vblank_crtc_handler(struct drm_device *dev, int crtc)continue ;spin_lock (&psw->peephole_lock); -nv_wr32 (dev,0x001704 , pch->vblank.channel); -nv_wr32 (dev,0x001710 ,0x80000000 | pch->vblank.ctxdma); -if (dev_priv->chipset ==0x50 ) { -nv_wr32 (dev,0x001570 , pch->vblank.offset); -nv_wr32 (dev,0x001574 , pch->vblank.value); +if (dev_priv->chipset <0xc0 ) { +nv_wr32 (dev,0x001704 , pch->vblank.channel); +nv_wr32 (dev,0x001710 ,0x80000000 | pch->vblank.ctxdma); + dev_priv->engine.instmem.flush (dev); + +if (dev_priv->chipset ==0x50 ) { +nv_wr32 (dev,0x001570 , pch->vblank.offset); +nv_wr32 (dev,0x001574 , pch->vblank.value); + }else { +nv_wr32 (dev,0x060010 , pch->vblank.offset); +nv_wr32 (dev,0x060014 , pch->vblank.value); + } }else { +nv_wr32 (dev,0x001718 ,0x80000000 | pch->vblank.channel); + dev_priv->engine.instmem.flush (dev); + +nv_wr32 (dev,0x06000c , pch->vblank.ctxdma);nv_wr32 (dev,0x060010 , pch->vblank.offset);nv_wr32 (dev,0x060014 , pch->vblank.value); }spin_unlock (&psw->peephole_lock); -list_del (&pch->vblank.list); +list_del_init (&pch->vblank.list);drm_vblank_put (dev, crtc); }
drivers/gpu/drm/nouveau/nv50_software.c +1 -1
@@ -75,7 +75,7 @@ mthd_vblsem_release(struct nouveau_channel *chan, u32 class, u32 mthd, u32 data)struct nv50_software_chan *pch = chan->engctx[NVOBJ_ENGINE_SW ];struct drm_device *dev = chan->dev; -if (data >1 ) +if (data >1 || !list_empty (&pch->base.vblank.list))return -EINVAL ;drm_vblank_get (dev, data);
drivers/gpu/drm/nouveau/nvc0_software.c +63 -0
80 lines not on this page · raw message
drivers/gpu/drm/nouveau/nvd0_display.c +5 -0
@@ -1836,6 +1836,11 @@ nvd0_display_intr(struct drm_device *dev)u32 stat =nv_rd32 (dev,0x6100bc + (i *0x800 ));nv_wr32 (dev,0x6100bc + (i *0x800 ), stat); intr &= ~mask; +nv50_display_vblank_crtc_handler (dev, i); + +/* This read seems to be required for vblank to work +* correctly a second time on nvd9 */ +nv_rd32 (dev,0x6100c0 + (i *0x800 )); } }