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

drm/nouveau/kms/nv50: separate out lut commit



This commit separates the calculation of EVO state from the commit, in
order to make the same code useful for atomic modesetting.

The legacy interfaces have been wrapped on top of them.

Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent ad633619
Loading
Loading
Loading
Loading
+70 −51
Original line number Diff line number Diff line
@@ -91,6 +91,11 @@ struct nv50_head_atom {
		} v;
	} mode;

	struct {
		u32 handle;
		u64 offset:40;
	} lut;

	struct {
		bool visible;
		u32 handle;
@@ -770,7 +775,6 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb,
/******************************************************************************
 * Head
 *****************************************************************************/

static void
nv50_head_core_clr(struct nv50_head *head)
{
@@ -835,6 +839,61 @@ nv50_head_core_set(struct nv50_head *head, struct nv50_head_atom *asyh)
	}
}

static void
nv50_head_lut_clr(struct nv50_head *head)
{
	struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->mast.base;
	u32 *push;
	if ((push = evo_wait(core, 4))) {
		if (core->base.user.oclass < G82_DISP_CORE_CHANNEL_DMA) {
			evo_mthd(push, 0x0840 + (head->base.index * 0x400), 1);
			evo_data(push, 0x40000000);
		} else
		if (core->base.user.oclass < GF110_DISP_CORE_CHANNEL_DMA) {
			evo_mthd(push, 0x0840 + (head->base.index * 0x400), 1);
			evo_data(push, 0x40000000);
			evo_mthd(push, 0x085c + (head->base.index * 0x400), 1);
			evo_data(push, 0x00000000);
		} else {
			evo_mthd(push, 0x0440 + (head->base.index * 0x300), 1);
			evo_data(push, 0x03000000);
			evo_mthd(push, 0x045c + (head->base.index * 0x300), 1);
			evo_data(push, 0x00000000);
		}
		evo_kick(push, core);
	}
}

static void
nv50_head_lut_set(struct nv50_head *head, struct nv50_head_atom *asyh)
{
	struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->mast.base;
	u32 *push;
	if ((push = evo_wait(core, 7))) {
		if (core->base.user.oclass < G82_DISP_CORE_CHANNEL_DMA) {
			evo_mthd(push, 0x0840 + (head->base.index * 0x400), 2);
			evo_data(push, 0xc0000000);
			evo_data(push, asyh->lut.offset >> 8);
		} else
		if (core->base.user.oclass < GF110_DISP_CORE_CHANNEL_DMA) {
			evo_mthd(push, 0x0840 + (head->base.index * 0x400), 2);
			evo_data(push, 0xc0000000);
			evo_data(push, asyh->lut.offset >> 8);
			evo_mthd(push, 0x085c + (head->base.index * 0x400), 1);
			evo_data(push, asyh->lut.handle);
		} else {
			evo_mthd(push, 0x0440 + (head->base.index * 0x300), 4);
			evo_data(push, 0x83000000);
			evo_data(push, asyh->lut.offset >> 8);
			evo_data(push, 0x00000000);
			evo_data(push, 0x00000000);
			evo_mthd(push, 0x045c + (head->base.index * 0x300), 1);
			evo_data(push, asyh->lut.handle);
		}
		evo_kick(push, core);
	}
}

static void
nv50_head_mode(struct nv50_head *head, struct nv50_head_atom *asyh)
{
@@ -878,6 +937,8 @@ nv50_head_mode(struct nv50_head *head, struct nv50_head_atom *asyh)
static void
nv50_head_flush_clr(struct nv50_head *head, struct nv50_head_atom *asyh, bool y)
{
	if (asyh->clr.core && (!asyh->set.core || y))
		nv50_head_lut_clr(head);
	if (asyh->clr.core && (!asyh->set.core || y))
		nv50_head_core_clr(head);
}
@@ -886,6 +947,7 @@ static void
nv50_head_flush_set(struct nv50_head *head, struct nv50_head_atom *asyh)
{
	if (asyh->set.mode   ) nv50_head_mode    (head, asyh);
	if (asyh->set.core   ) nv50_head_lut_set (head, asyh);
	if (asyh->set.core   ) nv50_head_core_set(head, asyh);
}

@@ -973,6 +1035,8 @@ nv50_head_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *state)
		asyh->core.layout = 1;
		asyh->core.block = 0;
		asyh->core.pitch = ALIGN(asyh->core.w, 64) * 4;
		asyh->lut.handle = disp->mast.base.vram.handle;
		asyh->lut.offset = head->base.lut.nvbo->bo.offset;
	} else {
		asyh->core.visible = false;
	}
@@ -1320,10 +1384,8 @@ static void
nv50_crtc_prepare(struct drm_crtc *crtc)
{
	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
	struct nv50_mast *mast = nv50_mast(crtc->dev);
	struct nv50_head *head = nv50_head(crtc);
	struct nv50_head_atom *asyh = &head->asy;
	u32 *push;

	nv50_display_flip_stop(crtc);

@@ -1331,27 +1393,6 @@ nv50_crtc_prepare(struct drm_crtc *crtc)
	nv50_head_atomic_check(&head->base.base, &asyh->state);
	nv50_head_flush_clr(head, asyh, false);

	push = evo_wait(mast, 6);
	if (push) {
		if (nv50_vers(mast) < G82_DISP_CORE_CHANNEL_DMA) {
			evo_mthd(push, 0x0840 + (nv_crtc->index * 0x400), 1);
			evo_data(push, 0x40000000);
		} else
		if (nv50_vers(mast) <  GF110_DISP_CORE_CHANNEL_DMA) {
			evo_mthd(push, 0x0840 + (nv_crtc->index * 0x400), 1);
			evo_data(push, 0x40000000);
			evo_mthd(push, 0x085c + (nv_crtc->index * 0x400), 1);
			evo_data(push, 0x00000000);
		} else {
			evo_mthd(push, 0x0440 + (nv_crtc->index * 0x300), 1);
			evo_data(push, 0x03000000);
			evo_mthd(push, 0x045c + (nv_crtc->index * 0x300), 1);
			evo_data(push, 0x00000000);
		}

		evo_kick(push, mast);
	}

	nv50_crtc_cursor_show_hide(nv_crtc, false, false);
}

@@ -1359,34 +1400,12 @@ static void
nv50_crtc_commit(struct drm_crtc *crtc)
{
	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
	struct nv50_mast *mast = nv50_mast(crtc->dev);
	u32 *push;

	push = evo_wait(mast, 32);
	if (push) {
		if (nv50_vers(mast) < G82_DISP_CORE_CHANNEL_DMA) {
			evo_mthd(push, 0x0840 + (nv_crtc->index * 0x400), 2);
			evo_data(push, 0xc0000000);
			evo_data(push, nv_crtc->lut.nvbo->bo.offset >> 8);
		} else
		if (nv50_vers(mast) < GF110_DISP_CORE_CHANNEL_DMA) {
			evo_mthd(push, 0x0840 + (nv_crtc->index * 0x400), 2);
			evo_data(push, 0xc0000000);
			evo_data(push, nv_crtc->lut.nvbo->bo.offset >> 8);
			evo_mthd(push, 0x085c + (nv_crtc->index * 0x400), 1);
			evo_data(push, mast->base.vram.handle);
		} else {
			evo_mthd(push, 0x0440 + (nv_crtc->index * 0x300), 4);
			evo_data(push, 0x83000000);
			evo_data(push, nv_crtc->lut.nvbo->bo.offset >> 8);
			evo_data(push, 0x00000000);
			evo_data(push, 0x00000000);
			evo_mthd(push, 0x045c + (nv_crtc->index * 0x300), 1);
			evo_data(push, mast->base.vram.handle);
		}
	struct nv50_head *head = nv50_head(crtc);
	struct nv50_head_atom *asyh = &head->asy;

		evo_kick(push, mast);
	}
	asyh->state.active = true;
	nv50_head_atomic_check(&head->base.base, &asyh->state);
	nv50_head_flush_set(head, asyh);

	nv50_crtc_cursor_show_hide(nv_crtc, true, true);
	nv50_display_flip_next(crtc, crtc->primary->fb, NULL, 1);