Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 78ae0ad4 authored by Ben Skeggs's avatar Ben Skeggs
Browse files

drm/nv04/disp: fix framebuffer pin refcounting



Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent 6ff8c76a
Loading
Loading
Loading
Loading
+43 −15
Original line number Original line Diff line number Diff line
@@ -606,6 +606,24 @@ nv_crtc_mode_set_regs(struct drm_crtc *crtc, struct drm_display_mode * mode)
	regp->ramdac_a34 = 0x1;
	regp->ramdac_a34 = 0x1;
}
}


static int
nv_crtc_swap_fbs(struct drm_crtc *crtc, struct drm_framebuffer *old_fb)
{
	struct nv04_display *disp = nv04_display(crtc->dev);
	struct nouveau_framebuffer *nvfb = nouveau_framebuffer(crtc->fb);
	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
	int ret;

	ret = nouveau_bo_pin(nvfb->nvbo, TTM_PL_FLAG_VRAM);
	if (ret == 0) {
		if (disp->image[nv_crtc->index])
			nouveau_bo_unpin(disp->image[nv_crtc->index]);
		nouveau_bo_ref(nvfb->nvbo, &disp->image[nv_crtc->index]);
	}

	return ret;
}

/**
/**
 * Sets up registers for the given mode/adjusted_mode pair.
 * Sets up registers for the given mode/adjusted_mode pair.
 *
 *
@@ -622,10 +640,15 @@ nv_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode,
	struct drm_device *dev = crtc->dev;
	struct drm_device *dev = crtc->dev;
	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
	struct nouveau_drm *drm = nouveau_drm(dev);
	struct nouveau_drm *drm = nouveau_drm(dev);
	int ret;


	NV_DEBUG(drm, "CTRC mode on CRTC %d:\n", nv_crtc->index);
	NV_DEBUG(drm, "CTRC mode on CRTC %d:\n", nv_crtc->index);
	drm_mode_debug_printmodeline(adjusted_mode);
	drm_mode_debug_printmodeline(adjusted_mode);


	ret = nv_crtc_swap_fbs(crtc, old_fb);
	if (ret)
		return ret;

	/* unlock must come after turning off FP_TG_CONTROL in output_prepare */
	/* unlock must come after turning off FP_TG_CONTROL in output_prepare */
	nv_lock_vga_crtc_shadow(dev, nv_crtc->index, -1);
	nv_lock_vga_crtc_shadow(dev, nv_crtc->index, -1);


@@ -722,6 +745,7 @@ static void nv_crtc_commit(struct drm_crtc *crtc)


static void nv_crtc_destroy(struct drm_crtc *crtc)
static void nv_crtc_destroy(struct drm_crtc *crtc)
{
{
	struct nv04_display *disp = nv04_display(crtc->dev);
	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);


	if (!nv_crtc)
	if (!nv_crtc)
@@ -729,6 +753,10 @@ static void nv_crtc_destroy(struct drm_crtc *crtc)


	drm_crtc_cleanup(crtc);
	drm_crtc_cleanup(crtc);


	if (disp->image[nv_crtc->index])
		nouveau_bo_unpin(disp->image[nv_crtc->index]);
	nouveau_bo_ref(NULL, &disp->image[nv_crtc->index]);

	nouveau_bo_unmap(nv_crtc->cursor.nvbo);
	nouveau_bo_unmap(nv_crtc->cursor.nvbo);
	nouveau_bo_unpin(nv_crtc->cursor.nvbo);
	nouveau_bo_unpin(nv_crtc->cursor.nvbo);
	nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo);
	nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo);
@@ -753,6 +781,16 @@ nv_crtc_gamma_load(struct drm_crtc *crtc)
	nouveau_hw_load_state_palette(dev, nv_crtc->index, &nv04_display(dev)->mode_reg);
	nouveau_hw_load_state_palette(dev, nv_crtc->index, &nv04_display(dev)->mode_reg);
}
}


static void
nv_crtc_disable(struct drm_crtc *crtc)
{
	struct nv04_display *disp = nv04_display(crtc->dev);
	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
	if (disp->image[nv_crtc->index])
		nouveau_bo_unpin(disp->image[nv_crtc->index]);
	nouveau_bo_ref(NULL, &disp->image[nv_crtc->index]);
}

static void
static void
nv_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b, uint32_t start,
nv_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b, uint32_t start,
		  uint32_t size)
		  uint32_t size)
@@ -791,7 +829,6 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc,
	struct drm_framebuffer *drm_fb;
	struct drm_framebuffer *drm_fb;
	struct nouveau_framebuffer *fb;
	struct nouveau_framebuffer *fb;
	int arb_burst, arb_lwm;
	int arb_burst, arb_lwm;
	int ret;


	NV_DEBUG(drm, "index %d\n", nv_crtc->index);
	NV_DEBUG(drm, "index %d\n", nv_crtc->index);


@@ -801,10 +838,8 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc,
		return 0;
		return 0;
	}
	}



	/* If atomic, we want to switch to the fb we were passed, so
	/* If atomic, we want to switch to the fb we were passed, so
	 * now we update pointers to do that.  (We don't pin; just
	 * now we update pointers to do that.
	 * assume we're already pinned and update the base address.)
	 */
	 */
	if (atomic) {
	if (atomic) {
		drm_fb = passed_fb;
		drm_fb = passed_fb;
@@ -812,17 +847,6 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc,
	} else {
	} else {
		drm_fb = crtc->fb;
		drm_fb = crtc->fb;
		fb = nouveau_framebuffer(crtc->fb);
		fb = nouveau_framebuffer(crtc->fb);
		/* If not atomic, we can go ahead and pin, and unpin the
		 * old fb we were passed.
		 */
		ret = nouveau_bo_pin(fb->nvbo, TTM_PL_FLAG_VRAM);
		if (ret)
			return ret;

		if (passed_fb) {
			struct nouveau_framebuffer *ofb = nouveau_framebuffer(passed_fb);
			nouveau_bo_unpin(ofb->nvbo);
		}
	}
	}


	nv_crtc->fb.offset = fb->nvbo->bo.offset;
	nv_crtc->fb.offset = fb->nvbo->bo.offset;
@@ -877,6 +901,9 @@ static int
nv04_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
nv04_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
			struct drm_framebuffer *old_fb)
			struct drm_framebuffer *old_fb)
{
{
	int ret = nv_crtc_swap_fbs(crtc, old_fb);
	if (ret)
		return ret;
	return nv04_crtc_do_mode_set_base(crtc, old_fb, x, y, false);
	return nv04_crtc_do_mode_set_base(crtc, old_fb, x, y, false);
}
}


@@ -1027,6 +1054,7 @@ static const struct drm_crtc_helper_funcs nv04_crtc_helper_funcs = {
	.mode_set_base = nv04_crtc_mode_set_base,
	.mode_set_base = nv04_crtc_mode_set_base,
	.mode_set_base_atomic = nv04_crtc_mode_set_base_atomic,
	.mode_set_base_atomic = nv04_crtc_mode_set_base_atomic,
	.load_lut = nv_crtc_gamma_load,
	.load_lut = nv_crtc_gamma_load,
	.disable = nv_crtc_disable,
};
};


int
int
+1 −0
Original line number Original line Diff line number Diff line
@@ -81,6 +81,7 @@ struct nv04_display {
	uint32_t saved_vga_font[4][16384];
	uint32_t saved_vga_font[4][16384];
	uint32_t dac_users[4];
	uint32_t dac_users[4];
	struct nouveau_object *core;
	struct nouveau_object *core;
	struct nouveau_bo *image[2];
};
};


static inline struct nv04_display *
static inline struct nv04_display *
+3 −0
Original line number Original line Diff line number Diff line
@@ -577,6 +577,9 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
		ret = nv50_display_flip_next(crtc, fb, chan, 0);
		ret = nv50_display_flip_next(crtc, fb, chan, 0);
		if (ret)
		if (ret)
			goto fail_unreserve;
			goto fail_unreserve;
	} else {
		struct nv04_display *dispnv04 = nv04_display(dev);
		nouveau_bo_ref(new_bo, &dispnv04->image[nouveau_crtc(crtc)->index]);
	}
	}


	ret = nouveau_page_flip_emit(chan, old_bo, new_bo, s, &fence);
	ret = nouveau_page_flip_emit(chan, old_bo, new_bo, s, &fence);