drm/nouveau/kms/nv50-: modify overlay allocation so the code can be split
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
This commit is contained in:
parent
5bca1621c0
commit
a97c530eb9
@ -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
|
||||
*****************************************************************************/
|
||||
@ -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))
|
||||
@ -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;
|
||||
@ -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;
|
||||
@ -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)
|
||||
{
|
||||
@ -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);
|
||||
data = wndw->func->dtor(wndw);
|
||||
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);
|
||||
}
|
||||
@ -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
|
||||
*****************************************************************************/
|
||||
@ -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]);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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…
x
Reference in New Issue
Block a user