From ed6a8088a598439e2cd5d1ab86389b658f19e465 Mon Sep 17 00:00:00 2001
From: Qiang Yu <yuq825@gmail.com>
Date: Wed, 15 Aug 2018 11:17:09 +0800
Subject: [PATCH 078/146] drm/lima: user can choose not to use dlbu on mali450

Signed-off-by: Qiang Yu <yuq825@gmail.com>
---
 drivers/gpu/drm/lima/lima_bcast.c  | 24 +++++-----
 drivers/gpu/drm/lima/lima_bcast.h  |  3 +-
 drivers/gpu/drm/lima/lima_device.c |  5 --
 drivers/gpu/drm/lima/lima_dlbu.c   |  4 +-
 drivers/gpu/drm/lima/lima_dlbu.h   |  2 +-
 drivers/gpu/drm/lima/lima_pp.c     | 75 ++++++++++++++++++------------
 include/uapi/drm/lima_drm.h        |  9 +++-
 7 files changed, 67 insertions(+), 55 deletions(-)

diff --git a/drivers/gpu/drm/lima/lima_bcast.c b/drivers/gpu/drm/lima/lima_bcast.c
index 6c2004dce648..63754f6465ea 100644
--- a/drivers/gpu/drm/lima/lima_bcast.c
+++ b/drivers/gpu/drm/lima/lima_bcast.c
@@ -11,31 +11,31 @@
 #define bcast_write(reg, data) writel(data, ip->iomem + LIMA_BCAST_##reg)
 #define bcast_read(reg) readl(ip->iomem + LIMA_BCAST_##reg)
 
-void lima_bcast_enable(struct lima_device *dev)
+void lima_bcast_enable(struct lima_device *dev, int num_pp)
 {
 	struct lima_sched_pipe *pipe = dev->pipe + lima_pipe_pp;
 	struct lima_ip *ip = dev->ip + lima_ip_bcast;
-	int i, mask = 0;
+	int i, mask = bcast_read(BROADCAST_MASK) & 0xffff0000;
 
-	for (i = 0; i < pipe->num_processor; i++) {
+	for (i = 0; i < num_pp; i++) {
 		struct lima_ip *pp = pipe->processor[i];
 		mask |= 1 << (pp->id - lima_ip_pp0);
 	}
 
-	bcast_write(BROADCAST_MASK, (mask << 16) | mask);
-	bcast_write(INTERRUPT_MASK, mask);
+	bcast_write(BROADCAST_MASK, mask);
 }
 
-void lima_bcast_disable(struct lima_device *dev)
+int lima_bcast_init(struct lima_ip *ip)
 {
-	struct lima_ip *ip = dev->ip + lima_ip_bcast;
+	int i, mask = 0;
 
-	bcast_write(BROADCAST_MASK, 0);
-	bcast_write(INTERRUPT_MASK, 0);
-}
+	for (i = lima_ip_pp0; i <= lima_ip_pp7; i++) {
+		if (ip->dev->ip[i].present)
+			mask |= 1 << (i - lima_ip_pp0);
+	}
 
-int lima_bcast_init(struct lima_ip *ip)
-{
+	bcast_write(BROADCAST_MASK, mask << 16);
+	bcast_write(INTERRUPT_MASK, mask);
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/lima/lima_bcast.h b/drivers/gpu/drm/lima/lima_bcast.h
index fb8e1f318c5c..345e3e809860 100644
--- a/drivers/gpu/drm/lima/lima_bcast.h
+++ b/drivers/gpu/drm/lima/lima_bcast.h
@@ -9,7 +9,6 @@ struct lima_ip;
 int lima_bcast_init(struct lima_ip *ip);
 void lima_bcast_fini(struct lima_ip *ip);
 
-void lima_bcast_enable(struct lima_device *dev);
-void lima_bcast_disable(struct lima_device *dev);
+void lima_bcast_enable(struct lima_device *dev, int num_pp);
 
 #endif
diff --git a/drivers/gpu/drm/lima/lima_device.c b/drivers/gpu/drm/lima/lima_device.c
index c85196af8830..b88c84d796fc 100644
--- a/drivers/gpu/drm/lima/lima_device.c
+++ b/drivers/gpu/drm/lima/lima_device.c
@@ -338,11 +338,6 @@ int lima_device_init(struct lima_device *ldev)
 	if (err)
 		goto err_out6;
 
-	if (ldev->id == lima_gpu_mali450) {
-		lima_dlbu_enable(ldev);
-		lima_bcast_enable(ldev);
-	}
-
 	return 0;
 
 err_out6:
diff --git a/drivers/gpu/drm/lima/lima_dlbu.c b/drivers/gpu/drm/lima/lima_dlbu.c
index 444a74348d5e..6697d4ddd887 100644
--- a/drivers/gpu/drm/lima/lima_dlbu.c
+++ b/drivers/gpu/drm/lima/lima_dlbu.c
@@ -12,13 +12,13 @@
 #define dlbu_write(reg, data) writel(data, ip->iomem + LIMA_DLBU_##reg)
 #define dlbu_read(reg) readl(ip->iomem + LIMA_DLBU_##reg)
 
-void lima_dlbu_enable(struct lima_device *dev)
+void lima_dlbu_enable(struct lima_device *dev, int num_pp)
 {
 	struct lima_sched_pipe *pipe = dev->pipe + lima_pipe_pp;
 	struct lima_ip *ip = dev->ip + lima_ip_dlbu;
 	int i, mask = 0;
 
-	for (i = 0; i < pipe->num_processor; i++) {
+	for (i = 0; i < num_pp; i++) {
 		struct lima_ip *pp = pipe->processor[i];
 		mask |= 1 << (pp->id - lima_ip_pp0);
 	}
diff --git a/drivers/gpu/drm/lima/lima_dlbu.h b/drivers/gpu/drm/lima/lima_dlbu.h
index 6d85403fa410..60cba387cf30 100644
--- a/drivers/gpu/drm/lima/lima_dlbu.h
+++ b/drivers/gpu/drm/lima/lima_dlbu.h
@@ -7,7 +7,7 @@
 struct lima_ip;
 struct lima_device;
 
-void lima_dlbu_enable(struct lima_device *dev);
+void lima_dlbu_enable(struct lima_device *dev, int num_pp);
 void lima_dlbu_disable(struct lima_device *dev);
 
 void lima_dlbu_set_reg(struct lima_ip *ip, u32 *reg);
diff --git a/drivers/gpu/drm/lima/lima_pp.c b/drivers/gpu/drm/lima/lima_pp.c
index 29e3ddfb394b..3355895ceeba 100644
--- a/drivers/gpu/drm/lima/lima_pp.c
+++ b/drivers/gpu/drm/lima/lima_pp.c
@@ -64,8 +64,9 @@ static irqreturn_t lima_pp_bcast_irq_handler(int irq, void *data)
 	struct lima_ip *pp_bcast = data;
 	struct lima_device *dev = pp_bcast->dev;
 	struct lima_sched_pipe *pipe = dev->pipe + lima_pipe_pp;
+	struct drm_lima_m450_pp_frame *frame = pipe->current_task->frame;
 
-	for (i = 0; i < pipe->num_processor; i++) {
+	for (i = 0; i < frame->num_pp; i++) {
 		struct lima_ip *ip = pipe->processor[i];
 		u32 status, state;
 
@@ -135,7 +136,9 @@ static int lima_pp_soft_reset_async_wait(struct lima_ip *ip)
 	if (ip->id == lima_ip_pp_bcast) {
 		struct lima_device *dev = ip->dev;
 		struct lima_sched_pipe *pipe = dev->pipe + lima_pipe_pp;
-		for (i = 0; i < pipe->num_processor; i++)
+		struct drm_lima_m450_pp_frame *frame = pipe->current_task->frame;
+
+		for (i = 0; i < frame->num_pp; i++)
 			err |= lima_pp_soft_reset_async_wait_one(pipe->processor[i]);
 	}
 	else
@@ -145,24 +148,17 @@ static int lima_pp_soft_reset_async_wait(struct lima_ip *ip)
 	return err;
 }
 
-static void lima_pp_start_task(struct lima_ip *ip, u32 *frame, u32 *wb,
-			       bool skip_stack_addr)
+static void lima_pp_write_frame(struct lima_ip *ip, u32 *frame, u32 *wb)
 {
 	int i, j, n = 0;
 
-	for (i = 0; i < LIMA_PP_FRAME_REG_NUM; i++) {
-		if (skip_stack_addr && i * 4 == LIMA_PP_STACK)
-			continue;
-
+	for (i = 0; i < LIMA_PP_FRAME_REG_NUM; i++)
 		writel(frame[i], ip->iomem + LIMA_PP_FRAME + i * 4);
-	}
 
 	for (i = 0; i < 3; i++) {
 		for (j = 0; j < LIMA_PP_WB_REG_NUM; j++)
 			writel(wb[n++], ip->iomem + LIMA_PP_WB(i) + j * 4);
 	}
-
-	pp_write(CTRL, LIMA_PP_CTRL_START_RENDERING);
 }
 
 static int lima_pp_hard_reset(struct lima_ip *ip)
@@ -271,13 +267,20 @@ void lima_pp_bcast_fini(struct lima_ip *ip)
 static int lima_pp_task_validate(struct lima_sched_pipe *pipe,
 				 struct lima_sched_task *task)
 {
-	if (!pipe->bcast_processor) {
-		struct drm_lima_m400_pp_frame *f = task->frame;
+	u32 num_pp;
 
-		if (f->num_pp > pipe->num_processor)
-			return -EINVAL;
+	if (pipe->bcast_processor) {
+		struct drm_lima_m450_pp_frame *f = task->frame;
+	        num_pp = f->num_pp;
+	}
+	else {
+		struct drm_lima_m400_pp_frame *f = task->frame;
+		num_pp = f->num_pp;
 	}
 
+	if (num_pp == 0 || num_pp > pipe->num_processor)
+		return -EINVAL;
+
 	return 0;
 }
 
@@ -287,23 +290,36 @@ static void lima_pp_task_run(struct lima_sched_pipe *pipe,
 	if (pipe->bcast_processor) {
 		struct drm_lima_m450_pp_frame *frame = task->frame;
 		struct lima_device *dev = pipe->bcast_processor->dev;
+		struct lima_ip *ip = pipe->bcast_processor;
 		int i;
 
 		pipe->done = 0;
-		atomic_set(&pipe->task, pipe->num_processor);
+		atomic_set(&pipe->task, frame->num_pp);
 
-		frame->frame[LIMA_PP_FRAME >> 2] = LIMA_VA_RESERVE_DLBU;
-		lima_dlbu_set_reg(dev->ip + lima_ip_dlbu, frame->dlbu_regs);
+		if (frame->use_dlbu) {
+			lima_dlbu_enable(dev, frame->num_pp);
 
-		lima_pp_soft_reset_async_wait(pipe->bcast_processor);
+		        frame->frame[LIMA_PP_FRAME >> 2] = LIMA_VA_RESERVE_DLBU;
+			lima_dlbu_set_reg(dev->ip + lima_ip_dlbu, frame->dlbu_regs);
+		}
+		else
+			lima_dlbu_disable(dev);
+
+		lima_bcast_enable(dev, frame->num_pp);
+
+		lima_pp_soft_reset_async_wait(ip);
+
+	        lima_pp_write_frame(ip, frame->frame, frame->wb);
 
-		for (i = 0; i < pipe->num_processor; i++) {
+		for (i = 0; i < frame->num_pp; i++) {
 			struct lima_ip *ip = pipe->processor[i];
+
 			pp_write(STACK, frame->fragment_stack_address[i]);
+			if (!frame->use_dlbu)
+				pp_write(FRAME, frame->plbu_array_address[i]);
 		}
 
-		lima_pp_start_task(pipe->bcast_processor, frame->frame,
-				   frame->wb, true);
+		pp_write(CTRL, LIMA_PP_CTRL_START_RENDERING);
 	}
 	else {
 		struct drm_lima_m400_pp_frame *frame = task->frame;
@@ -312,15 +328,18 @@ static void lima_pp_task_run(struct lima_sched_pipe *pipe,
 		atomic_set(&pipe->task, frame->num_pp);
 
 		for (i = 0; i < frame->num_pp; i++) {
+			struct lima_ip *ip = pipe->processor[i];
+
 			frame->frame[LIMA_PP_FRAME >> 2] =
 				frame->plbu_array_address[i];
 			frame->frame[LIMA_PP_STACK >> 2] =
 				frame->fragment_stack_address[i];
 
-			lima_pp_soft_reset_async_wait(pipe->processor[i]);
+			lima_pp_soft_reset_async_wait(ip);
+
+		        lima_pp_write_frame(ip, frame->frame, frame->wb);
 
-			lima_pp_start_task(pipe->processor[i], frame->frame,
-					   frame->wb, false);
+			pp_write(CTRL, LIMA_PP_CTRL_START_RENDERING);
 		}
 	}
 }
@@ -340,14 +359,8 @@ static void lima_pp_task_error(struct lima_sched_pipe *pipe)
 {
 	int i;
 
-	if (pipe->bcast_processor)
-		lima_bcast_disable(pipe->bcast_processor->dev);
-
 	for (i = 0; i < pipe->num_processor; i++)
 		lima_pp_hard_reset(pipe->processor[i]);
-
-	if (pipe->bcast_processor)
-		lima_bcast_enable(pipe->bcast_processor->dev);
 }
 
 static void lima_pp_task_mmu_error(struct lima_sched_pipe *pipe)
diff --git a/include/uapi/drm/lima_drm.h b/include/uapi/drm/lima_drm.h
index 77cb39af1a45..0c17bf693184 100644
--- a/include/uapi/drm/lima_drm.h
+++ b/include/uapi/drm/lima_drm.h
@@ -91,9 +91,14 @@ struct drm_lima_m400_pp_frame {
 
 struct drm_lima_m450_pp_frame {
 	__u32 frame[LIMA_PP_FRAME_REG_NUM];
-	__u32 _pad;
+	__u32 num_pp;
 	__u32 wb[3 * LIMA_PP_WB_REG_NUM];
-	__u32 dlbu_regs[4];
+	__u32 use_dlbu;
+	__u32 _pad;
+	union {
+		__u32 plbu_array_address[8];
+		__u32 dlbu_regs[4];
+	};
 	__u32 fragment_stack_address[8];
 };
 
-- 
2.17.1

