xref: /linux/drivers/media/platform/mediatek/mdp3/mtk-mdp3-vpu.c (revision e65e175b07bef5974045cc42238de99057669ca7)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) 2022 MediaTek Inc.
4  * Author: Ping-Hsun Wu <ping-hsun.wu@mediatek.com>
5  */
6 
7 #include <linux/remoteproc.h>
8 #include <linux/remoteproc/mtk_scp.h>
9 #include "mtk-mdp3-vpu.h"
10 #include "mtk-mdp3-core.h"
11 
12 #define MDP_VPU_MESSAGE_TIMEOUT 500U
13 #define vpu_alloc_size		0x600000
14 
15 static inline struct mdp_dev *vpu_to_mdp(struct mdp_vpu_dev *vpu)
16 {
17 	return container_of(vpu, struct mdp_dev, vpu);
18 }
19 
20 static int mdp_vpu_shared_mem_alloc(struct mdp_vpu_dev *vpu)
21 {
22 	if (vpu->work && vpu->work_addr)
23 		return 0;
24 
25 	vpu->work = dma_alloc_coherent(scp_get_device(vpu->scp), vpu_alloc_size,
26 				       &vpu->work_addr, GFP_KERNEL);
27 
28 	if (!vpu->work)
29 		return -ENOMEM;
30 	else
31 		return 0;
32 }
33 
34 void mdp_vpu_shared_mem_free(struct mdp_vpu_dev *vpu)
35 {
36 	if (vpu->work && vpu->work_addr)
37 		dma_free_coherent(scp_get_device(vpu->scp), vpu_alloc_size,
38 				  vpu->work, vpu->work_addr);
39 }
40 
41 static void mdp_vpu_ipi_handle_init_ack(void *data, unsigned int len,
42 					void *priv)
43 {
44 	struct mdp_ipi_init_msg *msg = (struct mdp_ipi_init_msg *)data;
45 	struct mdp_vpu_dev *vpu =
46 		(struct mdp_vpu_dev *)(unsigned long)msg->drv_data;
47 
48 	if (!vpu->work_size)
49 		vpu->work_size = msg->work_size;
50 
51 	vpu->status = msg->status;
52 	complete(&vpu->ipi_acked);
53 }
54 
55 static void mdp_vpu_ipi_handle_deinit_ack(void *data, unsigned int len,
56 					  void *priv)
57 {
58 	struct mdp_ipi_deinit_msg *msg = (struct mdp_ipi_deinit_msg *)data;
59 	struct mdp_vpu_dev *vpu =
60 		(struct mdp_vpu_dev *)(unsigned long)msg->drv_data;
61 
62 	vpu->status = msg->status;
63 	complete(&vpu->ipi_acked);
64 }
65 
66 static void mdp_vpu_ipi_handle_frame_ack(void *data, unsigned int len,
67 					 void *priv)
68 {
69 	struct img_sw_addr *addr = (struct img_sw_addr *)data;
70 	struct img_ipi_frameparam *param =
71 		(struct img_ipi_frameparam *)(unsigned long)addr->va;
72 	struct mdp_vpu_ctx *ctx =
73 		(struct mdp_vpu_ctx *)(unsigned long)param->drv_data;
74 
75 	if (param->state) {
76 		struct mdp_dev *mdp = vpu_to_mdp(ctx->vpu_dev);
77 
78 		dev_err(&mdp->pdev->dev, "VPU MDP failure:%d\n", param->state);
79 	}
80 	ctx->vpu_dev->status = param->state;
81 	complete(&ctx->vpu_dev->ipi_acked);
82 }
83 
84 int mdp_vpu_register(struct mdp_dev *mdp)
85 {
86 	int err;
87 	struct mtk_scp *scp = mdp->scp;
88 	struct device *dev = &mdp->pdev->dev;
89 
90 	err = scp_ipi_register(scp, SCP_IPI_MDP_INIT,
91 			       mdp_vpu_ipi_handle_init_ack, NULL);
92 	if (err) {
93 		dev_err(dev, "scp_ipi_register failed %d\n", err);
94 		goto err_ipi_init;
95 	}
96 	err = scp_ipi_register(scp, SCP_IPI_MDP_DEINIT,
97 			       mdp_vpu_ipi_handle_deinit_ack, NULL);
98 	if (err) {
99 		dev_err(dev, "scp_ipi_register failed %d\n", err);
100 		goto err_ipi_deinit;
101 	}
102 	err = scp_ipi_register(scp, SCP_IPI_MDP_FRAME,
103 			       mdp_vpu_ipi_handle_frame_ack, NULL);
104 	if (err) {
105 		dev_err(dev, "scp_ipi_register failed %d\n", err);
106 		goto err_ipi_frame;
107 	}
108 	return 0;
109 
110 err_ipi_frame:
111 	scp_ipi_unregister(scp, SCP_IPI_MDP_DEINIT);
112 err_ipi_deinit:
113 	scp_ipi_unregister(scp, SCP_IPI_MDP_INIT);
114 err_ipi_init:
115 
116 	return err;
117 }
118 
119 void mdp_vpu_unregister(struct mdp_dev *mdp)
120 {
121 	scp_ipi_unregister(mdp->scp, SCP_IPI_MDP_INIT);
122 	scp_ipi_unregister(mdp->scp, SCP_IPI_MDP_DEINIT);
123 	scp_ipi_unregister(mdp->scp, SCP_IPI_MDP_FRAME);
124 }
125 
126 static int mdp_vpu_sendmsg(struct mdp_vpu_dev *vpu, enum scp_ipi_id id,
127 			   void *buf, unsigned int len)
128 {
129 	struct mdp_dev *mdp = vpu_to_mdp(vpu);
130 	unsigned int t = MDP_VPU_MESSAGE_TIMEOUT;
131 	int ret;
132 
133 	if (!vpu->scp) {
134 		dev_dbg(&mdp->pdev->dev, "vpu scp is NULL");
135 		return -EINVAL;
136 	}
137 	ret = scp_ipi_send(vpu->scp, id, buf, len, 2000);
138 
139 	if (ret) {
140 		dev_err(&mdp->pdev->dev, "scp_ipi_send failed %d\n", ret);
141 		return -EPERM;
142 	}
143 	ret = wait_for_completion_timeout(&vpu->ipi_acked,
144 					  msecs_to_jiffies(t));
145 	if (!ret)
146 		ret = -ETIME;
147 	else if (vpu->status)
148 		ret = -EINVAL;
149 	else
150 		ret = 0;
151 	return ret;
152 }
153 
154 int mdp_vpu_dev_init(struct mdp_vpu_dev *vpu, struct mtk_scp *scp,
155 		     struct mutex *lock)
156 {
157 	struct mdp_ipi_init_msg msg = {
158 		.drv_data = (unsigned long)vpu,
159 	};
160 	size_t mem_size;
161 	phys_addr_t pool;
162 	const size_t pool_size = sizeof(struct mdp_config_pool);
163 	struct mdp_dev *mdp = vpu_to_mdp(vpu);
164 	int err;
165 
166 	init_completion(&vpu->ipi_acked);
167 	vpu->scp = scp;
168 	vpu->lock = lock;
169 	vpu->work_size = 0;
170 	err = mdp_vpu_sendmsg(vpu, SCP_IPI_MDP_INIT, &msg, sizeof(msg));
171 	if (err)
172 		goto err_work_size;
173 	/* vpu work_size was set in mdp_vpu_ipi_handle_init_ack */
174 
175 	mem_size = vpu_alloc_size;
176 	err = mdp_vpu_shared_mem_alloc(vpu);
177 	if (err) {
178 		dev_err(&mdp->pdev->dev, "VPU memory alloc fail!");
179 		goto err_mem_alloc;
180 	}
181 
182 	pool = ALIGN((uintptr_t)vpu->work + vpu->work_size, 8);
183 	if (pool + pool_size - (uintptr_t)vpu->work > mem_size) {
184 		dev_err(&mdp->pdev->dev,
185 			"VPU memory insufficient: %zx + %zx > %zx",
186 			vpu->work_size, pool_size, mem_size);
187 		err = -ENOMEM;
188 		goto err_mem_size;
189 	}
190 
191 	dev_dbg(&mdp->pdev->dev,
192 		"VPU work:%pK pa:%pad sz:%zx pool:%pa sz:%zx (mem sz:%zx)",
193 		vpu->work, &vpu->work_addr, vpu->work_size,
194 		&pool, pool_size, mem_size);
195 	vpu->pool = (struct mdp_config_pool *)(uintptr_t)pool;
196 	msg.work_addr = vpu->work_addr;
197 	msg.work_size = vpu->work_size;
198 	err = mdp_vpu_sendmsg(vpu, SCP_IPI_MDP_INIT, &msg, sizeof(msg));
199 	if (err)
200 		goto err_work_size;
201 
202 	memset(vpu->pool, 0, sizeof(*vpu->pool));
203 	return 0;
204 
205 err_work_size:
206 	switch (vpu->status) {
207 	case -MDP_IPI_EBUSY:
208 		err = -EBUSY;
209 		break;
210 	case -MDP_IPI_ENOMEM:
211 		err = -ENOSPC;	/* -ENOMEM */
212 		break;
213 	}
214 	return err;
215 err_mem_size:
216 err_mem_alloc:
217 	return err;
218 }
219 
220 int mdp_vpu_dev_deinit(struct mdp_vpu_dev *vpu)
221 {
222 	struct mdp_ipi_deinit_msg msg = {
223 		.drv_data = (unsigned long)vpu,
224 		.work_addr = vpu->work_addr,
225 	};
226 
227 	return mdp_vpu_sendmsg(vpu, SCP_IPI_MDP_DEINIT, &msg, sizeof(msg));
228 }
229 
230 static struct img_config *mdp_config_get(struct mdp_vpu_dev *vpu,
231 					 enum mdp_config_id id, uint32_t *addr)
232 {
233 	struct img_config *config;
234 
235 	if (id < 0 || id >= MDP_CONFIG_POOL_SIZE)
236 		return ERR_PTR(-EINVAL);
237 
238 	mutex_lock(vpu->lock);
239 	vpu->pool->cfg_count[id]++;
240 	config = &vpu->pool->configs[id];
241 	*addr = vpu->work_addr + ((uintptr_t)config - (uintptr_t)vpu->work);
242 	mutex_unlock(vpu->lock);
243 
244 	return config;
245 }
246 
247 static int mdp_config_put(struct mdp_vpu_dev *vpu,
248 			  enum mdp_config_id id,
249 			  const struct img_config *config)
250 {
251 	int err = 0;
252 
253 	if (id < 0 || id >= MDP_CONFIG_POOL_SIZE)
254 		return -EINVAL;
255 	if (vpu->lock)
256 		mutex_lock(vpu->lock);
257 	if (!vpu->pool->cfg_count[id] || config != &vpu->pool->configs[id])
258 		err = -EINVAL;
259 	else
260 		vpu->pool->cfg_count[id]--;
261 	if (vpu->lock)
262 		mutex_unlock(vpu->lock);
263 	return err;
264 }
265 
266 int mdp_vpu_ctx_init(struct mdp_vpu_ctx *ctx, struct mdp_vpu_dev *vpu,
267 		     enum mdp_config_id id)
268 {
269 	ctx->config = mdp_config_get(vpu, id, &ctx->inst_addr);
270 	if (IS_ERR(ctx->config)) {
271 		int err = PTR_ERR(ctx->config);
272 
273 		ctx->config = NULL;
274 		return err;
275 	}
276 	ctx->config_id = id;
277 	ctx->vpu_dev = vpu;
278 	return 0;
279 }
280 
281 int mdp_vpu_ctx_deinit(struct mdp_vpu_ctx *ctx)
282 {
283 	int err = mdp_config_put(ctx->vpu_dev, ctx->config_id, ctx->config);
284 
285 	ctx->config_id = 0;
286 	ctx->config = NULL;
287 	ctx->inst_addr = 0;
288 	return err;
289 }
290 
291 int mdp_vpu_process(struct mdp_vpu_ctx *ctx, struct img_ipi_frameparam *param)
292 {
293 	struct mdp_vpu_dev *vpu = ctx->vpu_dev;
294 	struct mdp_dev *mdp = vpu_to_mdp(vpu);
295 	struct img_sw_addr addr;
296 
297 	if (!ctx->vpu_dev->work || !ctx->vpu_dev->work_addr) {
298 		if (mdp_vpu_shared_mem_alloc(vpu)) {
299 			dev_err(&mdp->pdev->dev, "VPU memory alloc fail!");
300 			return -ENOMEM;
301 		}
302 	}
303 	memset((void *)ctx->vpu_dev->work, 0, ctx->vpu_dev->work_size);
304 	memset(ctx->config, 0, sizeof(*ctx->config));
305 	param->config_data.va = (unsigned long)ctx->config;
306 	param->config_data.pa = ctx->inst_addr;
307 	param->drv_data = (unsigned long)ctx;
308 
309 	memcpy((void *)ctx->vpu_dev->work, param, sizeof(*param));
310 	addr.pa = ctx->vpu_dev->work_addr;
311 	addr.va = (uintptr_t)ctx->vpu_dev->work;
312 	return mdp_vpu_sendmsg(ctx->vpu_dev, SCP_IPI_MDP_FRAME,
313 		&addr, sizeof(addr));
314 }
315