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

Commit fb3d9e97 authored by Ilija Hadzic's avatar Ilija Hadzic Committed by Dave Airlie
Browse files

drm/radeon/kms: blit code commoning



factor out most of evergreen blit code and use the refactored code
from r600 that is now common for both r600 and evergreen

Signed-off-by: default avatarIlija Hadzic <ihadzic@research.bell-labs.com>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent b3530963
Loading
Loading
Loading
Loading
+2 −23
Original line number Diff line number Diff line
@@ -3087,7 +3087,7 @@ static int evergreen_startup(struct radeon_device *rdev)

	r = evergreen_blit_init(rdev);
	if (r) {
		evergreen_blit_fini(rdev);
		r600_blit_fini(rdev);
		rdev->asic->copy = NULL;
		dev_warn(rdev->dev, "failed blitter (%d) falling back to memcpy\n", r);
	}
@@ -3172,27 +3172,6 @@ int evergreen_suspend(struct radeon_device *rdev)
	return 0;
}

int evergreen_copy_blit(struct radeon_device *rdev,
			uint64_t src_offset, uint64_t dst_offset,
			unsigned num_pages, struct radeon_fence *fence)
{
	int r;

	mutex_lock(&rdev->r600_blit.mutex);
	rdev->r600_blit.vb_ib = NULL;
	r = evergreen_blit_prepare_copy(rdev, num_pages);
	if (r) {
		if (rdev->r600_blit.vb_ib)
			radeon_ib_free(rdev, &rdev->r600_blit.vb_ib);
		mutex_unlock(&rdev->r600_blit.mutex);
		return r;
	}
	evergreen_kms_blit_copy(rdev, src_offset, dst_offset, num_pages);
	evergreen_blit_done_copy(rdev, fence);
	mutex_unlock(&rdev->r600_blit.mutex);
	return 0;
}

/* Plan is to move initialization in that function and use
 * helper function so that radeon_device_init pretty much
 * do nothing more than calling asic specific function. This
@@ -3301,7 +3280,7 @@ int evergreen_init(struct radeon_device *rdev)

void evergreen_fini(struct radeon_device *rdev)
{
	evergreen_blit_fini(rdev);
	r600_blit_fini(rdev);
	r700_cp_fini(rdev);
	r600_irq_fini(rdev);
	radeon_wb_fini(rdev);
+18 −242
Original line number Diff line number Diff line
@@ -44,10 +44,6 @@
#define COLOR_5_6_5           0x8
#define COLOR_8_8_8_8         0x1a

#define RECT_UNIT_H           32
#define RECT_UNIT_W           (RADEON_GPU_PAGE_SIZE / 4 / RECT_UNIT_H)
#define MAX_RECT_DIM          16384

/* emits 17 */
static void
set_render_target(struct radeon_device *rdev, int format,
@@ -599,31 +595,6 @@ set_default_state(struct radeon_device *rdev)

}

static uint32_t i2f(uint32_t input)
{
	u32 result, i, exponent, fraction;

	if ((input & 0x3fff) == 0)
		result = 0; /* 0 is a special case */
	else {
		exponent = 140; /* exponent biased by 127; */
		fraction = (input & 0x3fff) << 10; /* cheat and only
						      handle numbers below 2^^15 */
		for (i = 0; i < 14; i++) {
			if (fraction & 0x800000)
				break;
			else {
				fraction = fraction << 1; /* keep
							     shifting left until top bit = 1 */
				exponent = exponent - 1;
			}
		}
		result = exponent << 23 | (fraction & 0x7fffff); /* mask
								    off top bit; assumed 1 */
	}
	return result;
}

int evergreen_blit_init(struct radeon_device *rdev)
{
	u32 obj_size;
@@ -632,6 +603,24 @@ int evergreen_blit_init(struct radeon_device *rdev)
	u32 packet2s[16];
	int num_packet2s = 0;

	rdev->r600_blit.primitives.set_render_target = set_render_target;
	rdev->r600_blit.primitives.cp_set_surface_sync = cp_set_surface_sync;
	rdev->r600_blit.primitives.set_shaders = set_shaders;
	rdev->r600_blit.primitives.set_vtx_resource = set_vtx_resource;
	rdev->r600_blit.primitives.set_tex_resource = set_tex_resource;
	rdev->r600_blit.primitives.set_scissors = set_scissors;
	rdev->r600_blit.primitives.draw_auto = draw_auto;
	rdev->r600_blit.primitives.set_default_state = set_default_state;

	rdev->r600_blit.ring_size_common = 55; /* shaders + def state */
	rdev->r600_blit.ring_size_common += 10; /* fence emit for VB IB */
	rdev->r600_blit.ring_size_common += 5; /* done copy */
	rdev->r600_blit.ring_size_common += 10; /* fence emit for done copy */

	rdev->r600_blit.ring_size_per_loop = 74;

	rdev->r600_blit.max_dim = 16384;

	/* pin copy shader into vram if already initialized */
	if (rdev->r600_blit.shader_obj)
		goto done;
@@ -727,216 +716,3 @@ int evergreen_blit_init(struct radeon_device *rdev)
	radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size);
	return 0;
}

void evergreen_blit_fini(struct radeon_device *rdev)
{
	int r;

	radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size);
	if (rdev->r600_blit.shader_obj == NULL)
		return;
	/* If we can't reserve the bo, unref should be enough to destroy
	 * it when it becomes idle.
	 */
	r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false);
	if (!r) {
		radeon_bo_unpin(rdev->r600_blit.shader_obj);
		radeon_bo_unreserve(rdev->r600_blit.shader_obj);
	}
	radeon_bo_unref(&rdev->r600_blit.shader_obj);
}

static int evergreen_vb_ib_get(struct radeon_device *rdev)
{
	int r;
	r = radeon_ib_get(rdev, &rdev->r600_blit.vb_ib);
	if (r) {
		DRM_ERROR("failed to get IB for vertex buffer\n");
		return r;
	}

	rdev->r600_blit.vb_total = 64*1024;
	rdev->r600_blit.vb_used = 0;
	return 0;
}

static void evergreen_vb_ib_put(struct radeon_device *rdev)
{
	radeon_fence_emit(rdev, rdev->r600_blit.vb_ib->fence);
	radeon_ib_free(rdev, &rdev->r600_blit.vb_ib);
}


/* maps the rectangle to the buffer so that satisfies the following properties:
 *     - dimensions are less or equal to the hardware limit (MAX_RECT_DIM)
 *     - rectangle consists of integer number of pages
 *     - height is an integer multiple of RECT_UNIT_H
 *     - width is an integer multiple of RECT_UNIT_W
 *     - (the above three conditions also guarantee tile-aligned size)
 *     - it is as square as possible (sides ratio never greater than 2:1)
 *     - uses maximum number of pages that fit the above constraints
 *
 *  input:  buffer size, pointers to width/height variables
 *  return: number of pages that were successfully mapped to the rectangle
 *          width/height of the rectangle
 */
static unsigned evergreen_blit_create_rect(unsigned num_pages, int *width, int *height)
{
	unsigned max_pages;
	unsigned pages = num_pages;
	int w, h;

	if (num_pages == 0) {
		/* not supposed to be called with no pages, but just in case */
		h = 0;
		w = 0;
		pages = 0;
		WARN_ON(1);
	} else {
		int rect_order = 2;
		h = RECT_UNIT_H;
		while (num_pages / rect_order) {
			h *= 2;
			rect_order *= 4;
			if (h >= MAX_RECT_DIM) {
				h = MAX_RECT_DIM;
				break;
			}
		}
		max_pages = (MAX_RECT_DIM * h) / (RECT_UNIT_W * RECT_UNIT_H);
		if (pages > max_pages)
			pages = max_pages;
		w = (pages * RECT_UNIT_W * RECT_UNIT_H) / h;
		w = (w / RECT_UNIT_W) * RECT_UNIT_W;
		pages = (w * h) / (RECT_UNIT_W * RECT_UNIT_H);
		BUG_ON(pages == 0);
	}


	DRM_DEBUG("blit_rectangle: h=%d, w=%d, pages=%d\n", h, w, pages);

	/* return width and height only of the caller wants it */
	if (height)
		*height = h;
	if (width)
		*width = w;

	return pages;
}

int evergreen_blit_prepare_copy(struct radeon_device *rdev, unsigned num_pages)
{
	int r;
	int ring_size;
	/* loops of emits + fence emit possible */
	int dwords_per_loop = 74, num_loops = 0;

	r = evergreen_vb_ib_get(rdev);
	if (r)
		return r;

	/* num loops */
	while (num_pages) {
		num_pages -= evergreen_blit_create_rect(num_pages, NULL, NULL);
		num_loops++;
	}
	/* calculate number of loops correctly */
	ring_size = num_loops * dwords_per_loop;
	/* set default  + shaders */
	ring_size += 55; /* shaders + def state */
	ring_size += 10; /* fence emit for VB IB */
	ring_size += 5; /* done copy */
	ring_size += 10; /* fence emit for done copy */
	r = radeon_ring_lock(rdev, ring_size);
	if (r)
		return r;

	set_default_state(rdev); /* 36 */
	set_shaders(rdev); /* 16 */
	return 0;
}

void evergreen_blit_done_copy(struct radeon_device *rdev, struct radeon_fence *fence)
{
	int r;

	if (rdev->r600_blit.vb_ib)
		evergreen_vb_ib_put(rdev);

	if (fence)
		r = radeon_fence_emit(rdev, fence);

	radeon_ring_unlock_commit(rdev);
}

void evergreen_kms_blit_copy(struct radeon_device *rdev,
			     u64 src_gpu_addr, u64 dst_gpu_addr,
			     unsigned num_pages)
{
	u64 vb_gpu_addr;
	u32 *vb;

	DRM_DEBUG("emitting copy %16llx %16llx %d %d\n", src_gpu_addr, dst_gpu_addr,
		  num_pages, rdev->r600_blit.vb_used);
	vb = (u32 *)(rdev->r600_blit.vb_ib->ptr + rdev->r600_blit.vb_used);

	while (num_pages) {
		int w, h;
		unsigned size_in_bytes;
		unsigned pages_per_loop = evergreen_blit_create_rect(num_pages, &w, &h);

		size_in_bytes = pages_per_loop * RADEON_GPU_PAGE_SIZE;
		DRM_DEBUG("rectangle w=%d h=%d\n", w, h);

		if ((rdev->r600_blit.vb_used + 48) > rdev->r600_blit.vb_total) {
			WARN_ON(1);
		}

		vb[0] = 0;
		vb[1] = 0;
		vb[2] = 0;
		vb[3] = 0;

		vb[4] = 0;
		vb[5] = i2f(h);
		vb[6] = 0;
		vb[7] = i2f(h);

		vb[8] = i2f(w);
		vb[9] = i2f(h);
		vb[10] = i2f(w);
		vb[11] = i2f(h);

		/* src 10 */
		set_tex_resource(rdev, FMT_8_8_8_8, w, h, w, src_gpu_addr);

		/* 5 */
		cp_set_surface_sync(rdev,
				    PACKET3_TC_ACTION_ENA, size_in_bytes, src_gpu_addr);

		/* dst 17 */
		set_render_target(rdev, COLOR_8_8_8_8, w, h, dst_gpu_addr);

		/* scissors 12  */
		set_scissors(rdev, 0, 0, w, h);

		/* Vertex buffer setup 15 */
		vb_gpu_addr = rdev->r600_blit.vb_ib->gpu_addr + rdev->r600_blit.vb_used;
		set_vtx_resource(rdev, vb_gpu_addr);

		/* draw 10 */
		draw_auto(rdev);

		/* 5 */
		cp_set_surface_sync(rdev,
				    PACKET3_CB_ACTION_ENA | PACKET3_CB0_DEST_BASE_ENA,
				    size_in_bytes, dst_gpu_addr);

		/* 74 ring dwords per loop */
		vb += 12;
		rdev->r600_blit.vb_used += 4*12;
		src_gpu_addr += size_in_bytes;
		dst_gpu_addr += size_in_bytes;
		num_pages -= pages_per_loop;
	}
}
+2 −2
Original line number Diff line number Diff line
@@ -1401,7 +1401,7 @@ static int cayman_startup(struct radeon_device *rdev)

	r = evergreen_blit_init(rdev);
	if (r) {
		evergreen_blit_fini(rdev);
		r600_blit_fini(rdev);
		rdev->asic->copy = NULL;
		dev_warn(rdev->dev, "failed blitter (%d) falling back to memcpy\n", r);
	}
@@ -1589,7 +1589,7 @@ int cayman_init(struct radeon_device *rdev)

void cayman_fini(struct radeon_device *rdev)
{
	evergreen_blit_fini(rdev);
	r600_blit_fini(rdev);
	cayman_cp_fini(rdev);
	r600_irq_fini(rdev);
	radeon_wb_fini(rdev);
+8 −8
Original line number Diff line number Diff line
@@ -765,9 +765,9 @@ static struct radeon_asic evergreen_asic = {
	.get_vblank_counter = &evergreen_get_vblank_counter,
	.fence_ring_emit = &r600_fence_ring_emit,
	.cs_parse = &evergreen_cs_parse,
	.copy_blit = &evergreen_copy_blit,
	.copy_blit = &r600_copy_blit,
	.copy_dma = NULL,
	.copy = &evergreen_copy_blit,
	.copy = &r600_copy_blit,
	.get_engine_clock = &radeon_atom_get_engine_clock,
	.set_engine_clock = &radeon_atom_set_engine_clock,
	.get_memory_clock = &radeon_atom_get_memory_clock,
@@ -812,9 +812,9 @@ static struct radeon_asic sumo_asic = {
	.get_vblank_counter = &evergreen_get_vblank_counter,
	.fence_ring_emit = &r600_fence_ring_emit,
	.cs_parse = &evergreen_cs_parse,
	.copy_blit = &evergreen_copy_blit,
	.copy_blit = &r600_copy_blit,
	.copy_dma = NULL,
	.copy = &evergreen_copy_blit,
	.copy = &r600_copy_blit,
	.get_engine_clock = &radeon_atom_get_engine_clock,
	.set_engine_clock = &radeon_atom_set_engine_clock,
	.get_memory_clock = NULL,
@@ -859,9 +859,9 @@ static struct radeon_asic btc_asic = {
	.get_vblank_counter = &evergreen_get_vblank_counter,
	.fence_ring_emit = &r600_fence_ring_emit,
	.cs_parse = &evergreen_cs_parse,
	.copy_blit = &evergreen_copy_blit,
	.copy_blit = &r600_copy_blit,
	.copy_dma = NULL,
	.copy = &evergreen_copy_blit,
	.copy = &r600_copy_blit,
	.get_engine_clock = &radeon_atom_get_engine_clock,
	.set_engine_clock = &radeon_atom_set_engine_clock,
	.get_memory_clock = &radeon_atom_get_memory_clock,
@@ -906,9 +906,9 @@ static struct radeon_asic cayman_asic = {
	.get_vblank_counter = &evergreen_get_vblank_counter,
	.fence_ring_emit = &r600_fence_ring_emit,
	.cs_parse = &evergreen_cs_parse,
	.copy_blit = &evergreen_copy_blit,
	.copy_blit = &r600_copy_blit,
	.copy_dma = NULL,
	.copy = &evergreen_copy_blit,
	.copy = &r600_copy_blit,
	.get_engine_clock = &radeon_atom_get_engine_clock,
	.set_engine_clock = &radeon_atom_set_engine_clock,
	.get_memory_clock = &radeon_atom_get_memory_clock,
+0 −10
Original line number Diff line number Diff line
@@ -401,9 +401,6 @@ bool evergreen_gpu_is_lockup(struct radeon_device *rdev);
int evergreen_asic_reset(struct radeon_device *rdev);
void evergreen_bandwidth_update(struct radeon_device *rdev);
void evergreen_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib);
int evergreen_copy_blit(struct radeon_device *rdev,
			uint64_t src_offset, uint64_t dst_offset,
			unsigned num_pages, struct radeon_fence *fence);
void evergreen_hpd_init(struct radeon_device *rdev);
void evergreen_hpd_fini(struct radeon_device *rdev);
bool evergreen_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd);
@@ -421,13 +418,6 @@ extern u32 evergreen_page_flip(struct radeon_device *rdev, int crtc, u64 crtc_ba
extern void evergreen_post_page_flip(struct radeon_device *rdev, int crtc);
void evergreen_disable_interrupt_state(struct radeon_device *rdev);
int evergreen_blit_init(struct radeon_device *rdev);
void evergreen_blit_fini(struct radeon_device *rdev);
/* evergreen blit */
int evergreen_blit_prepare_copy(struct radeon_device *rdev, unsigned num_pages);
void evergreen_blit_done_copy(struct radeon_device *rdev, struct radeon_fence *fence);
void evergreen_kms_blit_copy(struct radeon_device *rdev,
			     u64 src_gpu_addr, u64 dst_gpu_addr,
			     unsigned num_pages);

/*
 * cayman