Loading drivers/gpu/drm/nouveau/dispnv50/disp.c +179 −98 Original line number Diff line number Diff line Loading @@ -340,57 +340,6 @@ nv50_chan_destroy(struct nv50_chan *chan) nvif_object_fini(&chan->user); } /****************************************************************************** * PIO EVO channel *****************************************************************************/ struct nv50_pioc { struct nv50_chan base; }; static void nv50_pioc_destroy(struct nv50_pioc *pioc) { nv50_chan_destroy(&pioc->base); } static int nv50_pioc_create(struct nvif_device *device, struct nvif_object *disp, const s32 *oclass, u8 head, void *data, u32 size, struct nv50_pioc *pioc) { return nv50_chan_create(device, disp, oclass, head, data, size, &pioc->base); } /****************************************************************************** * Overlay Immediate *****************************************************************************/ struct nv50_oimm { struct nv50_pioc base; }; static int nv50_oimm_create(struct nvif_device *device, struct nvif_object *disp, int head, struct nv50_oimm *oimm) { struct nv50_disp_cursor_v0 args = { .head = head, }; static const s32 oclass[] = { GK104_DISP_OVERLAY, GF110_DISP_OVERLAY, GT214_DISP_OVERLAY, G82_DISP_OVERLAY, NV50_DISP_OVERLAY, 0 }; return nv50_pioc_create(device, disp, oclass, head, &args, sizeof(args), &oimm->base); } /****************************************************************************** * DMA EVO channel *****************************************************************************/ Loading Loading @@ -541,43 +490,12 @@ nv50_base_create(struct nvif_device *device, struct nvif_object *disp, syncbuf, &base->base); } /****************************************************************************** * Overlay *****************************************************************************/ struct nv50_ovly { struct nv50_dmac base; }; static int nv50_ovly_create(struct nvif_device *device, struct nvif_object *disp, int head, u64 syncbuf, struct nv50_ovly *ovly) { struct nv50_disp_overlay_channel_dma_v0 args = { .head = head, }; static const s32 oclass[] = { GK104_DISP_OVERLAY_CONTROL_DMA, GF110_DISP_OVERLAY_CONTROL_DMA, GT214_DISP_OVERLAY_CHANNEL_DMA, GT200_DISP_OVERLAY_CHANNEL_DMA, G82_DISP_OVERLAY_CHANNEL_DMA, NV50_DISP_OVERLAY_CHANNEL_DMA, 0 }; return nv50_dmac_create(device, disp, oclass, head, &args, sizeof(args), syncbuf, &ovly->base); } struct nv50_head { struct nouveau_crtc base; struct { struct nouveau_bo *nvbo[2]; int next; } lut; struct nv50_ovly ovly; struct nv50_oimm oimm; }; #define nv50_head(c) ((struct nv50_head *)nouveau_crtc(c)) Loading Loading @@ -662,7 +580,9 @@ evo_kick(u32 *push, void *evoc) struct nv50_wndw { const struct nv50_wndw_func *func; const struct nv50_wimm_func *immd; struct nv50_dmac *dmac; int id; struct { struct nvif_object *parent; Loading @@ -671,6 +591,9 @@ struct nv50_wndw { struct drm_plane plane; struct nv50_dmac wndw; struct nv50_dmac wimm; struct nvif_notify notify; u16 ntfy; u16 sema; Loading Loading @@ -699,6 +622,9 @@ struct nv50_wndw_func { u32 (*update)(struct nv50_wndw *, u32 interlock); }; struct nv50_wimm_func { }; static void nv50_wndw_ctxdma_del(struct nv50_wndw_ctxdma *ctxdma) { Loading Loading @@ -1028,14 +954,17 @@ nv50_wndw_destroy(struct drm_plane *plane) { struct nv50_wndw *wndw = nv50_wndw(plane); struct nv50_wndw_ctxdma *ctxdma, *ctxtmp; void *data; void *data = wndw; list_for_each_entry_safe(ctxdma, ctxtmp, &wndw->ctxdma.list, head) { nv50_wndw_ctxdma_del(ctxdma); } nvif_notify_fini(&wndw->notify); if (wndw->func->dtor) data = wndw->func->dtor(wndw); nv50_dmac_destroy(&wndw->wimm); nv50_dmac_destroy(&wndw->wndw); drm_plane_cleanup(&wndw->plane); kfree(data); } Loading Loading @@ -1085,6 +1014,170 @@ nv50_wndw_ctor(const struct nv50_wndw_func *func, struct drm_device *dev, return 0; } static int nv50_wndw_new_(const struct nv50_wndw_func *func, struct drm_device *dev, enum drm_plane_type type, const char *name, int index, const u32 *format, struct nv50_wndw **pwndw) { struct nv50_wndw *wndw; int nformat; int ret; if (!(wndw = *pwndw = kzalloc(sizeof(*wndw), GFP_KERNEL))) return -ENOMEM; wndw->id = index; for (nformat = 0; format[nformat]; nformat++); ret = nv50_wndw_ctor(func, dev, type, name, index, &wndw->wndw, format, nformat, wndw); if (ret) { kfree(*pwndw); *pwndw = NULL; } return ret; } /****************************************************************************** * Overlay *****************************************************************************/ static const struct nv50_wimm_func oimm507b = { }; static int oimm507b_init_(const struct nv50_wimm_func *func, struct nouveau_drm *drm, s32 oclass, struct nv50_wndw *wndw) { struct nv50_disp_overlay_v0 args = { .head = wndw->id, }; struct nv50_disp *disp = nv50_disp(drm->dev); int ret; ret = nvif_object_init(&disp->disp->object, 0, oclass, &args, sizeof(args), &wndw->wimm.base.user); if (ret) { NV_ERROR(drm, "oimm%04x allocation failed: %d\n", oclass, ret); return ret; } nvif_object_map(&wndw->wimm.base.user, NULL, 0); wndw->immd = func; return 0; } static int oimm507b_init(struct nouveau_drm *drm, s32 oclass, struct nv50_wndw *wndw) { return oimm507b_init_(&oimm507b, drm, oclass, wndw); } static int nv50_oimm_init(struct nouveau_drm *drm, struct nv50_wndw *wndw) { static const struct { s32 oclass; int version; int (*init)(struct nouveau_drm *, s32, struct nv50_wndw *); } oimms[] = { { GK104_DISP_OVERLAY, 0, oimm507b_init }, { GF110_DISP_OVERLAY, 0, oimm507b_init }, { GT214_DISP_OVERLAY, 0, oimm507b_init }, { G82_DISP_OVERLAY, 0, oimm507b_init }, { NV50_DISP_OVERLAY, 0, oimm507b_init }, {} }; struct nv50_disp *disp = nv50_disp(drm->dev); int cid; cid = nvif_mclass(&disp->disp->object, oimms); if (cid < 0) { NV_ERROR(drm, "No supported overlay immediate class\n"); return cid; } return oimms[cid].init(drm, oimms[cid].oclass, wndw); } static const struct nv50_wndw_func ovly507e = { }; static const u32 ovly507e_format[] = { 0 }; static int ovly507e_new_(const struct nv50_wndw_func *func, const u32 *format, struct nouveau_drm *drm, int head, s32 oclass, struct nv50_wndw **pwndw) { struct nv50_disp_overlay_channel_dma_v0 args = { .head = head, }; struct nv50_disp *disp = nv50_disp(drm->dev); struct nv50_wndw *wndw; int ret; ret = nv50_wndw_new_(func, drm->dev, DRM_PLANE_TYPE_OVERLAY, "ovly", head, format, &wndw); if (*pwndw = wndw, ret) return ret; ret = nv50_dmac_create(&drm->client.device, &disp->disp->object, &oclass, 0, &args, sizeof(args), disp->sync->bo.offset, &wndw->wndw); if (ret) { NV_ERROR(drm, "ovly%04x allocation failed: %d\n", oclass, ret); return ret; } return 0; } static int ovly507e_new(struct nouveau_drm *drm, int head, s32 oclass, struct nv50_wndw **pwndw) { return ovly507e_new_(&ovly507e, ovly507e_format, drm, head, oclass, pwndw); } static int nv50_ovly_new(struct nouveau_drm *drm, int head, struct nv50_wndw **pwndw) { static const struct { s32 oclass; int version; int (*new)(struct nouveau_drm *, int, s32, struct nv50_wndw **); } ovlys[] = { { GK104_DISP_OVERLAY_CONTROL_DMA, 0, ovly507e_new }, { GF110_DISP_OVERLAY_CONTROL_DMA, 0, ovly507e_new }, { GT214_DISP_OVERLAY_CHANNEL_DMA, 0, ovly507e_new }, { GT200_DISP_OVERLAY_CHANNEL_DMA, 0, ovly507e_new }, { G82_DISP_OVERLAY_CHANNEL_DMA, 0, ovly507e_new }, { NV50_DISP_OVERLAY_CHANNEL_DMA, 0, ovly507e_new }, {} }; struct nv50_disp *disp = nv50_disp(drm->dev); int cid, ret; cid = nvif_mclass(&disp->disp->object, ovlys); if (cid < 0) { NV_ERROR(drm, "No supported overlay class\n"); return cid; } ret = ovlys[cid].new(drm, head, ovlys[cid].oclass, pwndw); if (ret) return ret; return nv50_oimm_init(drm, *pwndw); } /****************************************************************************** * Cursor plane *****************************************************************************/ Loading Loading @@ -2347,9 +2440,6 @@ nv50_head_destroy(struct drm_crtc *crtc) struct nv50_head *head = nv50_head(crtc); int i; nv50_dmac_destroy(&head->ovly.base); nv50_pioc_destroy(&head->oimm.base); for (i = 0; i < ARRAY_SIZE(head->lut.nvbo); i++) nouveau_bo_unmap_unpin_unref(&head->lut.nvbo[i]); Loading @@ -2372,11 +2462,10 @@ static int nv50_head_create(struct drm_device *dev, int index) { struct nouveau_drm *drm = nouveau_drm(dev); struct nvif_device *device = &drm->client.device; struct nv50_disp *disp = nv50_disp(dev); struct nv50_head *head; struct nv50_base *base; struct nv50_curs *curs; struct nv50_wndw *wndw; struct drm_crtc *crtc; int ret, i; Loading Loading @@ -2409,15 +2498,7 @@ nv50_head_create(struct drm_device *dev, int index) } /* allocate overlay resources */ ret = nv50_oimm_create(device, &disp->disp->object, index, &head->oimm); if (ret) goto out; ret = nv50_ovly_create(device, &disp->disp->object, index, disp->sync->bo.offset, &head->ovly); if (ret) goto out; ret = nv50_ovly_new(drm, head->base.index, &wndw); out: if (ret) nv50_head_destroy(crtc); Loading Loading
drivers/gpu/drm/nouveau/dispnv50/disp.c +179 −98 Original line number Diff line number Diff line Loading @@ -340,57 +340,6 @@ nv50_chan_destroy(struct nv50_chan *chan) nvif_object_fini(&chan->user); } /****************************************************************************** * PIO EVO channel *****************************************************************************/ struct nv50_pioc { struct nv50_chan base; }; static void nv50_pioc_destroy(struct nv50_pioc *pioc) { nv50_chan_destroy(&pioc->base); } static int nv50_pioc_create(struct nvif_device *device, struct nvif_object *disp, const s32 *oclass, u8 head, void *data, u32 size, struct nv50_pioc *pioc) { return nv50_chan_create(device, disp, oclass, head, data, size, &pioc->base); } /****************************************************************************** * Overlay Immediate *****************************************************************************/ struct nv50_oimm { struct nv50_pioc base; }; static int nv50_oimm_create(struct nvif_device *device, struct nvif_object *disp, int head, struct nv50_oimm *oimm) { struct nv50_disp_cursor_v0 args = { .head = head, }; static const s32 oclass[] = { GK104_DISP_OVERLAY, GF110_DISP_OVERLAY, GT214_DISP_OVERLAY, G82_DISP_OVERLAY, NV50_DISP_OVERLAY, 0 }; return nv50_pioc_create(device, disp, oclass, head, &args, sizeof(args), &oimm->base); } /****************************************************************************** * DMA EVO channel *****************************************************************************/ Loading Loading @@ -541,43 +490,12 @@ nv50_base_create(struct nvif_device *device, struct nvif_object *disp, syncbuf, &base->base); } /****************************************************************************** * Overlay *****************************************************************************/ struct nv50_ovly { struct nv50_dmac base; }; static int nv50_ovly_create(struct nvif_device *device, struct nvif_object *disp, int head, u64 syncbuf, struct nv50_ovly *ovly) { struct nv50_disp_overlay_channel_dma_v0 args = { .head = head, }; static const s32 oclass[] = { GK104_DISP_OVERLAY_CONTROL_DMA, GF110_DISP_OVERLAY_CONTROL_DMA, GT214_DISP_OVERLAY_CHANNEL_DMA, GT200_DISP_OVERLAY_CHANNEL_DMA, G82_DISP_OVERLAY_CHANNEL_DMA, NV50_DISP_OVERLAY_CHANNEL_DMA, 0 }; return nv50_dmac_create(device, disp, oclass, head, &args, sizeof(args), syncbuf, &ovly->base); } struct nv50_head { struct nouveau_crtc base; struct { struct nouveau_bo *nvbo[2]; int next; } lut; struct nv50_ovly ovly; struct nv50_oimm oimm; }; #define nv50_head(c) ((struct nv50_head *)nouveau_crtc(c)) Loading Loading @@ -662,7 +580,9 @@ evo_kick(u32 *push, void *evoc) struct nv50_wndw { const struct nv50_wndw_func *func; const struct nv50_wimm_func *immd; struct nv50_dmac *dmac; int id; struct { struct nvif_object *parent; Loading @@ -671,6 +591,9 @@ struct nv50_wndw { struct drm_plane plane; struct nv50_dmac wndw; struct nv50_dmac wimm; struct nvif_notify notify; u16 ntfy; u16 sema; Loading Loading @@ -699,6 +622,9 @@ struct nv50_wndw_func { u32 (*update)(struct nv50_wndw *, u32 interlock); }; struct nv50_wimm_func { }; static void nv50_wndw_ctxdma_del(struct nv50_wndw_ctxdma *ctxdma) { Loading Loading @@ -1028,14 +954,17 @@ nv50_wndw_destroy(struct drm_plane *plane) { struct nv50_wndw *wndw = nv50_wndw(plane); struct nv50_wndw_ctxdma *ctxdma, *ctxtmp; void *data; void *data = wndw; list_for_each_entry_safe(ctxdma, ctxtmp, &wndw->ctxdma.list, head) { nv50_wndw_ctxdma_del(ctxdma); } nvif_notify_fini(&wndw->notify); if (wndw->func->dtor) data = wndw->func->dtor(wndw); nv50_dmac_destroy(&wndw->wimm); nv50_dmac_destroy(&wndw->wndw); drm_plane_cleanup(&wndw->plane); kfree(data); } Loading Loading @@ -1085,6 +1014,170 @@ nv50_wndw_ctor(const struct nv50_wndw_func *func, struct drm_device *dev, return 0; } static int nv50_wndw_new_(const struct nv50_wndw_func *func, struct drm_device *dev, enum drm_plane_type type, const char *name, int index, const u32 *format, struct nv50_wndw **pwndw) { struct nv50_wndw *wndw; int nformat; int ret; if (!(wndw = *pwndw = kzalloc(sizeof(*wndw), GFP_KERNEL))) return -ENOMEM; wndw->id = index; for (nformat = 0; format[nformat]; nformat++); ret = nv50_wndw_ctor(func, dev, type, name, index, &wndw->wndw, format, nformat, wndw); if (ret) { kfree(*pwndw); *pwndw = NULL; } return ret; } /****************************************************************************** * Overlay *****************************************************************************/ static const struct nv50_wimm_func oimm507b = { }; static int oimm507b_init_(const struct nv50_wimm_func *func, struct nouveau_drm *drm, s32 oclass, struct nv50_wndw *wndw) { struct nv50_disp_overlay_v0 args = { .head = wndw->id, }; struct nv50_disp *disp = nv50_disp(drm->dev); int ret; ret = nvif_object_init(&disp->disp->object, 0, oclass, &args, sizeof(args), &wndw->wimm.base.user); if (ret) { NV_ERROR(drm, "oimm%04x allocation failed: %d\n", oclass, ret); return ret; } nvif_object_map(&wndw->wimm.base.user, NULL, 0); wndw->immd = func; return 0; } static int oimm507b_init(struct nouveau_drm *drm, s32 oclass, struct nv50_wndw *wndw) { return oimm507b_init_(&oimm507b, drm, oclass, wndw); } static int nv50_oimm_init(struct nouveau_drm *drm, struct nv50_wndw *wndw) { static const struct { s32 oclass; int version; int (*init)(struct nouveau_drm *, s32, struct nv50_wndw *); } oimms[] = { { GK104_DISP_OVERLAY, 0, oimm507b_init }, { GF110_DISP_OVERLAY, 0, oimm507b_init }, { GT214_DISP_OVERLAY, 0, oimm507b_init }, { G82_DISP_OVERLAY, 0, oimm507b_init }, { NV50_DISP_OVERLAY, 0, oimm507b_init }, {} }; struct nv50_disp *disp = nv50_disp(drm->dev); int cid; cid = nvif_mclass(&disp->disp->object, oimms); if (cid < 0) { NV_ERROR(drm, "No supported overlay immediate class\n"); return cid; } return oimms[cid].init(drm, oimms[cid].oclass, wndw); } static const struct nv50_wndw_func ovly507e = { }; static const u32 ovly507e_format[] = { 0 }; static int ovly507e_new_(const struct nv50_wndw_func *func, const u32 *format, struct nouveau_drm *drm, int head, s32 oclass, struct nv50_wndw **pwndw) { struct nv50_disp_overlay_channel_dma_v0 args = { .head = head, }; struct nv50_disp *disp = nv50_disp(drm->dev); struct nv50_wndw *wndw; int ret; ret = nv50_wndw_new_(func, drm->dev, DRM_PLANE_TYPE_OVERLAY, "ovly", head, format, &wndw); if (*pwndw = wndw, ret) return ret; ret = nv50_dmac_create(&drm->client.device, &disp->disp->object, &oclass, 0, &args, sizeof(args), disp->sync->bo.offset, &wndw->wndw); if (ret) { NV_ERROR(drm, "ovly%04x allocation failed: %d\n", oclass, ret); return ret; } return 0; } static int ovly507e_new(struct nouveau_drm *drm, int head, s32 oclass, struct nv50_wndw **pwndw) { return ovly507e_new_(&ovly507e, ovly507e_format, drm, head, oclass, pwndw); } static int nv50_ovly_new(struct nouveau_drm *drm, int head, struct nv50_wndw **pwndw) { static const struct { s32 oclass; int version; int (*new)(struct nouveau_drm *, int, s32, struct nv50_wndw **); } ovlys[] = { { GK104_DISP_OVERLAY_CONTROL_DMA, 0, ovly507e_new }, { GF110_DISP_OVERLAY_CONTROL_DMA, 0, ovly507e_new }, { GT214_DISP_OVERLAY_CHANNEL_DMA, 0, ovly507e_new }, { GT200_DISP_OVERLAY_CHANNEL_DMA, 0, ovly507e_new }, { G82_DISP_OVERLAY_CHANNEL_DMA, 0, ovly507e_new }, { NV50_DISP_OVERLAY_CHANNEL_DMA, 0, ovly507e_new }, {} }; struct nv50_disp *disp = nv50_disp(drm->dev); int cid, ret; cid = nvif_mclass(&disp->disp->object, ovlys); if (cid < 0) { NV_ERROR(drm, "No supported overlay class\n"); return cid; } ret = ovlys[cid].new(drm, head, ovlys[cid].oclass, pwndw); if (ret) return ret; return nv50_oimm_init(drm, *pwndw); } /****************************************************************************** * Cursor plane *****************************************************************************/ Loading Loading @@ -2347,9 +2440,6 @@ nv50_head_destroy(struct drm_crtc *crtc) struct nv50_head *head = nv50_head(crtc); int i; nv50_dmac_destroy(&head->ovly.base); nv50_pioc_destroy(&head->oimm.base); for (i = 0; i < ARRAY_SIZE(head->lut.nvbo); i++) nouveau_bo_unmap_unpin_unref(&head->lut.nvbo[i]); Loading @@ -2372,11 +2462,10 @@ static int nv50_head_create(struct drm_device *dev, int index) { struct nouveau_drm *drm = nouveau_drm(dev); struct nvif_device *device = &drm->client.device; struct nv50_disp *disp = nv50_disp(dev); struct nv50_head *head; struct nv50_base *base; struct nv50_curs *curs; struct nv50_wndw *wndw; struct drm_crtc *crtc; int ret, i; Loading Loading @@ -2409,15 +2498,7 @@ nv50_head_create(struct drm_device *dev, int index) } /* allocate overlay resources */ ret = nv50_oimm_create(device, &disp->disp->object, index, &head->oimm); if (ret) goto out; ret = nv50_ovly_create(device, &disp->disp->object, index, disp->sync->bo.offset, &head->ovly); if (ret) goto out; ret = nv50_ovly_new(drm, head->base.index, &wndw); out: if (ret) nv50_head_destroy(crtc); Loading