#include <nvif/unpack.h>
 
 static void
-nvkm_disp_vblank_fini(struct nvkm_event *event, int type, int head)
+nvkm_disp_vblank_fini(struct nvkm_event *event, int type, int id)
 {
        struct nvkm_disp *disp = container_of(event, typeof(*disp), vblank);
-       disp->func->head.vblank_fini(disp, head);
+       struct nvkm_head *head = nvkm_head_find(disp, id);
+       if (head)
+               head->func->vblank_put(head);
 }
 
 static void
-nvkm_disp_vblank_init(struct nvkm_event *event, int type, int head)
+nvkm_disp_vblank_init(struct nvkm_event *event, int type, int id)
 {
        struct nvkm_disp *disp = container_of(event, typeof(*disp), vblank);
-       disp->func->head.vblank_init(disp, head);
+       struct nvkm_head *head = nvkm_head_find(disp, id);
+       if (head)
+               head->func->vblank_get(head);
 }
 
 static int
 
        .super = nv50_disp_super,
        .root = &g84_disp_root_oclass,
        .head.new = nv50_head_new,
-       .head.vblank_init = nv50_disp_vblank_init,
-       .head.vblank_fini = nv50_disp_vblank_fini,
        .head.scanoutpos = nv50_disp_root_scanoutpos,
        .outp.internal.crt = nv50_dac_output_new,
        .outp.internal.tmds = nv50_sor_output_new,
 
        .super = nv50_disp_super,
        .root = &g94_disp_root_oclass,
        .head.new = nv50_head_new,
-       .head.vblank_init = nv50_disp_vblank_init,
-       .head.vblank_fini = nv50_disp_vblank_fini,
        .head.scanoutpos = nv50_disp_root_scanoutpos,
        .outp.internal.crt = nv50_dac_output_new,
        .outp.internal.tmds = nv50_sor_output_new,
 
 #include <subdev/bios/pll.h>
 #include <subdev/devinit.h>
 
-void
-gf119_disp_vblank_init(struct nv50_disp *disp, int head)
-{
-       struct nvkm_device *device = disp->base.engine.subdev.device;
-       nvkm_mask(device, 0x6100c0 + (head * 0x800), 0x00000001, 0x00000001);
-}
-
-void
-gf119_disp_vblank_fini(struct nv50_disp *disp, int head)
-{
-       struct nvkm_device *device = disp->base.engine.subdev.device;
-       nvkm_mask(device, 0x6100c0 + (head * 0x800), 0x00000001, 0x00000000);
-}
-
 static struct nvkm_output *
 exec_lookup(struct nv50_disp *disp, int head, int or, u32 ctrl,
            u32 *data, u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
        .super = gf119_disp_super,
        .root = &gf119_disp_root_oclass,
        .head.new = gf119_head_new,
-       .head.vblank_init = gf119_disp_vblank_init,
-       .head.vblank_fini = gf119_disp_vblank_fini,
        .head.scanoutpos = gf119_disp_root_scanoutpos,
        .outp.internal.crt = nv50_dac_output_new,
        .outp.internal.tmds = nv50_sor_output_new,
 
        .super = gf119_disp_super,
        .root = &gk104_disp_root_oclass,
        .head.new = gf119_head_new,
-       .head.vblank_init = gf119_disp_vblank_init,
-       .head.vblank_fini = gf119_disp_vblank_fini,
        .head.scanoutpos = gf119_disp_root_scanoutpos,
        .outp.internal.crt = nv50_dac_output_new,
        .outp.internal.tmds = nv50_sor_output_new,
 
        .super = gf119_disp_super,
        .root = &gk110_disp_root_oclass,
        .head.new = gf119_head_new,
-       .head.vblank_init = gf119_disp_vblank_init,
-       .head.vblank_fini = gf119_disp_vblank_fini,
        .head.scanoutpos = gf119_disp_root_scanoutpos,
        .outp.internal.crt = nv50_dac_output_new,
        .outp.internal.tmds = nv50_sor_output_new,
 
        .super = gf119_disp_super,
        .root = &gm107_disp_root_oclass,
        .head.new = gf119_head_new,
-       .head.vblank_init = gf119_disp_vblank_init,
-       .head.vblank_fini = gf119_disp_vblank_fini,
        .head.scanoutpos = gf119_disp_root_scanoutpos,
        .outp.internal.crt = nv50_dac_output_new,
        .outp.internal.tmds = nv50_sor_output_new,
 
        .super = gf119_disp_super,
        .root = &gm200_disp_root_oclass,
        .head.new = gf119_head_new,
-       .head.vblank_init = gf119_disp_vblank_init,
-       .head.vblank_fini = gf119_disp_vblank_fini,
        .head.scanoutpos = gf119_disp_root_scanoutpos,
        .outp.internal.crt = nv50_dac_output_new,
        .outp.internal.tmds = nv50_sor_output_new,
 
        .super = gf119_disp_super,
        .root = &gp100_disp_root_oclass,
        .head.new = gf119_head_new,
-       .head.vblank_init = gf119_disp_vblank_init,
-       .head.vblank_fini = gf119_disp_vblank_fini,
        .head.scanoutpos = gf119_disp_root_scanoutpos,
        .outp.internal.crt = nv50_dac_output_new,
        .outp.internal.tmds = nv50_sor_output_new,
 
        .super = gf119_disp_super,
        .root = &gp102_disp_root_oclass,
        .head.new = gf119_head_new,
-       .head.vblank_init = gf119_disp_vblank_init,
-       .head.vblank_fini = gf119_disp_vblank_fini,
        .head.scanoutpos = gf119_disp_root_scanoutpos,
        .outp.internal.crt = nv50_dac_output_new,
        .outp.internal.tmds = nv50_sor_output_new,
 
        .super = nv50_disp_super,
        .root = >200_disp_root_oclass,
        .head.new = nv50_head_new,
-       .head.vblank_init = nv50_disp_vblank_init,
-       .head.vblank_fini = nv50_disp_vblank_fini,
        .head.scanoutpos = nv50_disp_root_scanoutpos,
        .outp.internal.crt = nv50_dac_output_new,
        .outp.internal.tmds = nv50_sor_output_new,
 
        .super = nv50_disp_super,
        .root = >215_disp_root_oclass,
        .head.new = nv50_head_new,
-       .head.vblank_init = nv50_disp_vblank_init,
-       .head.vblank_fini = nv50_disp_vblank_fini,
        .head.scanoutpos = nv50_disp_root_scanoutpos,
        .outp.internal.crt = nv50_dac_output_new,
        .outp.internal.tmds = nv50_sor_output_new,
 
 struct nvkm_head *nvkm_head_find(struct nvkm_disp *, int id);
 
 struct nvkm_head_func {
+       void (*vblank_get)(struct nvkm_head *);
+       void (*vblank_put)(struct nvkm_head *);
 };
 
 #define HEAD_MSG(h,l,f,a...) do {                                              \
 
  */
 #include "head.h"
 
+static void
+gf119_head_vblank_put(struct nvkm_head *head)
+{
+       struct nvkm_device *device = head->disp->engine.subdev.device;
+       const u32 hoff = head->id * 0x800;
+       nvkm_mask(device, 0x6100c0 + hoff, 0x00000001, 0x00000000);
+}
+
+static void
+gf119_head_vblank_get(struct nvkm_head *head)
+{
+       struct nvkm_device *device = head->disp->engine.subdev.device;
+       const u32 hoff = head->id * 0x800;
+       nvkm_mask(device, 0x6100c0 + hoff, 0x00000001, 0x00000001);
+}
+
 static const struct nvkm_head_func
 gf119_head = {
+       .vblank_get = gf119_head_vblank_get,
+       .vblank_put = gf119_head_vblank_put,
 };
 
 int
 
  */
 #include "head.h"
 
+static void
+nv04_head_vblank_put(struct nvkm_head *head)
+{
+       struct nvkm_device *device = head->disp->engine.subdev.device;
+       nvkm_wr32(device, 0x600140 + (head->id * 0x2000) , 0x00000000);
+}
+
+static void
+nv04_head_vblank_get(struct nvkm_head *head)
+{
+       struct nvkm_device *device = head->disp->engine.subdev.device;
+       nvkm_wr32(device, 0x600140 + (head->id * 0x2000) , 0x00000001);
+}
+
 static const struct nvkm_head_func
 nv04_head = {
+       .vblank_get = nv04_head_vblank_get,
+       .vblank_put = nv04_head_vblank_put,
 };
 
 int
 
  */
 #include "head.h"
 
+static void
+nv50_head_vblank_put(struct nvkm_head *head)
+{
+       struct nvkm_device *device = head->disp->engine.subdev.device;
+       nvkm_mask(device, 0x61002c, (4 << head->id), 0);
+}
+
+static void
+nv50_head_vblank_get(struct nvkm_head *head)
+{
+       struct nvkm_device *device = head->disp->engine.subdev.device;
+       nvkm_mask(device, 0x61002c, (4 << head->id), (4 << head->id));
+}
+
 static const struct nvkm_head_func
 nv50_head = {
+       .vblank_get = nv50_head_vblank_get,
+       .vblank_put = nv50_head_vblank_put,
 };
 
 int
 
        return &nv04_disp_root_oclass;
 }
 
-static void
-nv04_disp_vblank_init(struct nvkm_disp *disp, int head)
-{
-       struct nvkm_device *device = disp->engine.subdev.device;
-       nvkm_wr32(device, 0x600140 + (head * 0x2000) , 0x00000001);
-}
-
-static void
-nv04_disp_vblank_fini(struct nvkm_disp *disp, int head)
-{
-       struct nvkm_device *device = disp->engine.subdev.device;
-       nvkm_wr32(device, 0x600140 + (head * 0x2000) , 0x00000000);
-}
-
 static void
 nv04_disp_intr(struct nvkm_disp *disp)
 {
 nv04_disp = {
        .intr = nv04_disp_intr,
        .root = nv04_disp_root,
-       .head.vblank_init = nv04_disp_vblank_init,
-       .head.vblank_fini = nv04_disp_vblank_fini,
 };
 
 int
 
        return -ENODEV;
 }
 
-static void
-nv50_disp_vblank_fini_(struct nvkm_disp *base, int head)
-{
-       struct nv50_disp *disp = nv50_disp(base);
-       disp->func->head.vblank_fini(disp, head);
-}
-
-static void
-nv50_disp_vblank_init_(struct nvkm_disp *base, int head)
-{
-       struct nv50_disp *disp = nv50_disp(base);
-       disp->func->head.vblank_init(disp, head);
-}
-
 static void
 nv50_disp_intr_(struct nvkm_disp *base)
 {
        .outp.internal.dp = nv50_disp_outp_internal_dp_,
        .outp.external.tmds = nv50_disp_outp_external_tmds_,
        .outp.external.dp = nv50_disp_outp_external_dp_,
-       .head.vblank_init = nv50_disp_vblank_init_,
-       .head.vblank_fini = nv50_disp_vblank_fini_,
 };
 
 int
        return nvkm_event_init(func->uevent, 1, 1 + (heads * 4), &disp->uevent);
 }
 
-void
-nv50_disp_vblank_fini(struct nv50_disp *disp, int head)
-{
-       struct nvkm_device *device = disp->base.engine.subdev.device;
-       nvkm_mask(device, 0x61002c, (4 << head), 0);
-}
-
-void
-nv50_disp_vblank_init(struct nv50_disp *disp, int head)
-{
-       struct nvkm_device *device = disp->base.engine.subdev.device;
-       nvkm_mask(device, 0x61002c, (4 << head), (4 << head));
-}
-
 static struct nvkm_output *
 exec_lookup(struct nv50_disp *disp, int head, int or, u32 ctrl,
            u32 *data, u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
        .super = nv50_disp_super,
        .root = &nv50_disp_root_oclass,
        .head.new = nv50_head_new,
-       .head.vblank_init = nv50_disp_vblank_init,
-       .head.vblank_fini = nv50_disp_vblank_fini,
        .head.scanoutpos = nv50_disp_root_scanoutpos,
        .outp.internal.crt = nv50_dac_output_new,
        .outp.internal.tmds = nv50_sor_output_new,
 
 
        struct {
                int (*new)(struct nvkm_disp *, int id);
-               void (*vblank_init)(struct nv50_disp *, int head);
-               void (*vblank_fini)(struct nv50_disp *, int head);
                int (*scanoutpos)(NV50_DISP_MTHD_V0);
        } head;
 
        } pior;
 };
 
-void nv50_disp_vblank_init(struct nv50_disp *, int);
-void nv50_disp_vblank_fini(struct nv50_disp *, int);
 void nv50_disp_intr(struct nv50_disp *);
 void nv50_disp_super(struct work_struct *);
 
-void gf119_disp_vblank_init(struct nv50_disp *, int);
-void gf119_disp_vblank_fini(struct nv50_disp *, int);
 void gf119_disp_intr(struct nv50_disp *);
 void gf119_disp_super(struct work_struct *);
 void gf119_disp_intr_error(struct nv50_disp *, int);
 
 
        const struct nvkm_disp_oclass *(*root)(struct nvkm_disp *);
 
-       struct {
-               void (*vblank_init)(struct nvkm_disp *, int head);
-               void (*vblank_fini)(struct nvkm_disp *, int head);
-       } head;
-
        struct {
                const struct nvkm_disp_func_outp internal;
                const struct nvkm_disp_func_outp external;