Commit a97c530e authored by Ben Skeggs's avatar Ben Skeggs
Browse files

drm/nouveau/kms/nv50-: modify overlay allocation so the code can be split



Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent 5bca1621
Loading
Loading
Loading
Loading
+179 −98
Original line number Original line Diff line number Diff line
@@ -340,57 +340,6 @@ nv50_chan_destroy(struct nv50_chan *chan)
	nvif_object_fini(&chan->user);
	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
 * DMA EVO channel
 *****************************************************************************/
 *****************************************************************************/
@@ -541,43 +490,12 @@ nv50_base_create(struct nvif_device *device, struct nvif_object *disp,
				syncbuf, &base->base);
				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 nv50_head {
	struct nouveau_crtc base;
	struct nouveau_crtc base;
	struct {
	struct {
		struct nouveau_bo *nvbo[2];
		struct nouveau_bo *nvbo[2];
		int next;
		int next;
	} lut;
	} lut;
	struct nv50_ovly ovly;
	struct nv50_oimm oimm;
};
};


#define nv50_head(c) ((struct nv50_head *)nouveau_crtc(c))
#define nv50_head(c) ((struct nv50_head *)nouveau_crtc(c))
@@ -662,7 +580,9 @@ evo_kick(u32 *push, void *evoc)


struct nv50_wndw {
struct nv50_wndw {
	const struct nv50_wndw_func *func;
	const struct nv50_wndw_func *func;
	const struct nv50_wimm_func *immd;
	struct nv50_dmac *dmac;
	struct nv50_dmac *dmac;
	int id;


	struct {
	struct {
		struct nvif_object *parent;
		struct nvif_object *parent;
@@ -671,6 +591,9 @@ struct nv50_wndw {


	struct drm_plane plane;
	struct drm_plane plane;


	struct nv50_dmac wndw;
	struct nv50_dmac wimm;

	struct nvif_notify notify;
	struct nvif_notify notify;
	u16 ntfy;
	u16 ntfy;
	u16 sema;
	u16 sema;
@@ -699,6 +622,9 @@ struct nv50_wndw_func {
	u32 (*update)(struct nv50_wndw *, u32 interlock);
	u32 (*update)(struct nv50_wndw *, u32 interlock);
};
};


struct nv50_wimm_func {
};

static void
static void
nv50_wndw_ctxdma_del(struct nv50_wndw_ctxdma *ctxdma)
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 *wndw = nv50_wndw(plane);
	struct nv50_wndw_ctxdma *ctxdma, *ctxtmp;
	struct nv50_wndw_ctxdma *ctxdma, *ctxtmp;
	void *data;
	void *data = wndw;


	list_for_each_entry_safe(ctxdma, ctxtmp, &wndw->ctxdma.list, head) {
	list_for_each_entry_safe(ctxdma, ctxtmp, &wndw->ctxdma.list, head) {
		nv50_wndw_ctxdma_del(ctxdma);
		nv50_wndw_ctxdma_del(ctxdma);
	}
	}


	nvif_notify_fini(&wndw->notify);
	nvif_notify_fini(&wndw->notify);
	if (wndw->func->dtor)
		data = wndw->func->dtor(wndw);
		data = wndw->func->dtor(wndw);
	nv50_dmac_destroy(&wndw->wimm);
	nv50_dmac_destroy(&wndw->wndw);
	drm_plane_cleanup(&wndw->plane);
	drm_plane_cleanup(&wndw->plane);
	kfree(data);
	kfree(data);
}
}
@@ -1085,6 +1014,170 @@ nv50_wndw_ctor(const struct nv50_wndw_func *func, struct drm_device *dev,
	return 0;
	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
 * Cursor plane
 *****************************************************************************/
 *****************************************************************************/
@@ -2347,9 +2440,6 @@ nv50_head_destroy(struct drm_crtc *crtc)
	struct nv50_head *head = nv50_head(crtc);
	struct nv50_head *head = nv50_head(crtc);
	int i;
	int i;


	nv50_dmac_destroy(&head->ovly.base);
	nv50_pioc_destroy(&head->oimm.base);

	for (i = 0; i < ARRAY_SIZE(head->lut.nvbo); i++)
	for (i = 0; i < ARRAY_SIZE(head->lut.nvbo); i++)
		nouveau_bo_unmap_unpin_unref(&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)
nv50_head_create(struct drm_device *dev, int index)
{
{
	struct nouveau_drm *drm = nouveau_drm(dev);
	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_head *head;
	struct nv50_base *base;
	struct nv50_base *base;
	struct nv50_curs *curs;
	struct nv50_curs *curs;
	struct nv50_wndw *wndw;
	struct drm_crtc *crtc;
	struct drm_crtc *crtc;
	int ret, i;
	int ret, i;


@@ -2409,15 +2498,7 @@ nv50_head_create(struct drm_device *dev, int index)
	}
	}


	/* allocate overlay resources */
	/* allocate overlay resources */
	ret = nv50_oimm_create(device, &disp->disp->object, index, &head->oimm);
	ret = nv50_ovly_new(drm, head->base.index, &wndw);
	if (ret)
		goto out;

	ret = nv50_ovly_create(device, &disp->disp->object, index,
			       disp->sync->bo.offset, &head->ovly);
	if (ret)
		goto out;

out:
out:
	if (ret)
	if (ret)
		nv50_head_destroy(crtc);
		nv50_head_destroy(crtc);