xref: /linux/drivers/media/platform/mediatek/mdp3/mtk-mdp3-vpu.c (revision 9e56ff53b4115875667760445b028357848b4748)
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 
14 static inline struct mdp_dev *vpu_to_mdp(struct mdp_vpu_dev *vpu)
15 {
16 	return container_of(vpu, struct mdp_dev, vpu);
17 }
18 
19 static int mdp_vpu_shared_mem_alloc(struct mdp_vpu_dev *vpu)
20 {
21 	struct device *dev;
22 
23 	if (IS_ERR_OR_NULL(vpu))
24 		goto err_return;
25 
26 	dev = scp_get_device(vpu->scp);
27 
28 	if (!vpu->param) {
29 		vpu->param = dma_alloc_wc(dev, vpu->param_size,
30 					  &vpu->param_addr, GFP_KERNEL);
31 		if (!vpu->param)
32 			goto err_return;
33 	}
34 
35 	if (!vpu->work) {
36 		vpu->work = dma_alloc_wc(dev, vpu->work_size,
37 					 &vpu->work_addr, GFP_KERNEL);
38 		if (!vpu->work)
39 			goto err_free_param;
40 	}
41 
42 	if (!vpu->config) {
43 		vpu->config = dma_alloc_wc(dev, vpu->config_size,
44 					   &vpu->config_addr, GFP_KERNEL);
45 		if (!vpu->config)
46 			goto err_free_work;
47 	}
48 
49 	return 0;
50 
51 err_free_work:
52 	dma_free_wc(dev, vpu->work_size, vpu->work, vpu->work_addr);
53 	vpu->work = NULL;
54 err_free_param:
55 	dma_free_wc(dev, vpu->param_size, vpu->param, vpu->param_addr);
56 	vpu->param = NULL;
57 err_return:
58 	return -ENOMEM;
59 }
60 
61 void mdp_vpu_shared_mem_free(struct mdp_vpu_dev *vpu)
62 {
63 	struct device *dev;
64 
65 	if (IS_ERR_OR_NULL(vpu))
66 		return;
67 
68 	dev = scp_get_device(vpu->scp);
69 
70 	if (vpu->param && vpu->param_addr)
71 		dma_free_wc(dev, vpu->param_size, vpu->param, vpu->param_addr);
72 
73 	if (vpu->work && vpu->work_addr)
74 		dma_free_wc(dev, vpu->work_size, vpu->work, vpu->work_addr);
75 
76 	if (vpu->config && vpu->config_addr)
77 		dma_free_wc(dev, vpu->config_size, vpu->config, vpu->config_addr);
78 }
79 
80 static void mdp_vpu_ipi_handle_init_ack(void *data, unsigned int len,
81 					void *priv)
82 {
83 	struct mdp_ipi_init_msg *msg = (struct mdp_ipi_init_msg *)data;
84 	struct mdp_vpu_dev *vpu =
85 		(struct mdp_vpu_dev *)(unsigned long)msg->drv_data;
86 
87 	if (!vpu->work_size)
88 		vpu->work_size = msg->work_size;
89 
90 	vpu->status = msg->status;
91 	complete(&vpu->ipi_acked);
92 }
93 
94 static void mdp_vpu_ipi_handle_deinit_ack(void *data, unsigned int len,
95 					  void *priv)
96 {
97 	struct mdp_ipi_deinit_msg *msg = (struct mdp_ipi_deinit_msg *)data;
98 	struct mdp_vpu_dev *vpu =
99 		(struct mdp_vpu_dev *)(unsigned long)msg->drv_data;
100 
101 	vpu->status = msg->status;
102 	complete(&vpu->ipi_acked);
103 }
104 
105 static void mdp_vpu_ipi_handle_frame_ack(void *data, unsigned int len,
106 					 void *priv)
107 {
108 	struct img_sw_addr *addr = (struct img_sw_addr *)data;
109 	struct img_ipi_frameparam *param =
110 		(struct img_ipi_frameparam *)(unsigned long)addr->va;
111 	struct mdp_vpu_dev *vpu =
112 		(struct mdp_vpu_dev *)(unsigned long)param->drv_data;
113 
114 	if (param->state) {
115 		struct mdp_dev *mdp = vpu_to_mdp(vpu);
116 
117 		dev_err(&mdp->pdev->dev, "VPU MDP failure:%d\n", param->state);
118 	}
119 	vpu->status = param->state;
120 	complete(&vpu->ipi_acked);
121 }
122 
123 int mdp_vpu_register(struct mdp_dev *mdp)
124 {
125 	int err;
126 	struct mtk_scp *scp = mdp->scp;
127 	struct device *dev = &mdp->pdev->dev;
128 
129 	err = scp_ipi_register(scp, SCP_IPI_MDP_INIT,
130 			       mdp_vpu_ipi_handle_init_ack, NULL);
131 	if (err) {
132 		dev_err(dev, "scp_ipi_register failed %d\n", err);
133 		goto err_ipi_init;
134 	}
135 	err = scp_ipi_register(scp, SCP_IPI_MDP_DEINIT,
136 			       mdp_vpu_ipi_handle_deinit_ack, NULL);
137 	if (err) {
138 		dev_err(dev, "scp_ipi_register failed %d\n", err);
139 		goto err_ipi_deinit;
140 	}
141 	err = scp_ipi_register(scp, SCP_IPI_MDP_FRAME,
142 			       mdp_vpu_ipi_handle_frame_ack, NULL);
143 	if (err) {
144 		dev_err(dev, "scp_ipi_register failed %d\n", err);
145 		goto err_ipi_frame;
146 	}
147 	return 0;
148 
149 err_ipi_frame:
150 	scp_ipi_unregister(scp, SCP_IPI_MDP_DEINIT);
151 err_ipi_deinit:
152 	scp_ipi_unregister(scp, SCP_IPI_MDP_INIT);
153 err_ipi_init:
154 
155 	return err;
156 }
157 
158 void mdp_vpu_unregister(struct mdp_dev *mdp)
159 {
160 	scp_ipi_unregister(mdp->scp, SCP_IPI_MDP_INIT);
161 	scp_ipi_unregister(mdp->scp, SCP_IPI_MDP_DEINIT);
162 	scp_ipi_unregister(mdp->scp, SCP_IPI_MDP_FRAME);
163 }
164 
165 static int mdp_vpu_sendmsg(struct mdp_vpu_dev *vpu, enum scp_ipi_id id,
166 			   void *buf, unsigned int len)
167 {
168 	struct mdp_dev *mdp = vpu_to_mdp(vpu);
169 	unsigned int t = MDP_VPU_MESSAGE_TIMEOUT;
170 	int ret;
171 
172 	if (!vpu->scp) {
173 		dev_dbg(&mdp->pdev->dev, "vpu scp is NULL");
174 		return -EINVAL;
175 	}
176 	ret = scp_ipi_send(vpu->scp, id, buf, len, 2000);
177 
178 	if (ret) {
179 		dev_err(&mdp->pdev->dev, "scp_ipi_send failed %d\n", ret);
180 		return -EPERM;
181 	}
182 	ret = wait_for_completion_timeout(&vpu->ipi_acked,
183 					  msecs_to_jiffies(t));
184 	if (!ret)
185 		ret = -ETIME;
186 	else if (vpu->status)
187 		ret = -EINVAL;
188 	else
189 		ret = 0;
190 	return ret;
191 }
192 
193 int mdp_vpu_dev_init(struct mdp_vpu_dev *vpu, struct mtk_scp *scp,
194 		     struct mutex *lock)
195 {
196 	struct mdp_ipi_init_msg msg = {
197 		.drv_data = (unsigned long)vpu,
198 	};
199 	struct mdp_dev *mdp = vpu_to_mdp(vpu);
200 	int err;
201 
202 	init_completion(&vpu->ipi_acked);
203 	vpu->scp = scp;
204 	vpu->lock = lock;
205 	vpu->work_size = 0;
206 	err = mdp_vpu_sendmsg(vpu, SCP_IPI_MDP_INIT, &msg, sizeof(msg));
207 	if (err)
208 		goto err_work_size;
209 	/* vpu work_size was set in mdp_vpu_ipi_handle_init_ack */
210 
211 	mutex_lock(vpu->lock);
212 	vpu->work_size = ALIGN(vpu->work_size, 64);
213 	vpu->param_size = ALIGN(sizeof(struct img_ipi_frameparam), 64);
214 	vpu->config_size = ALIGN(sizeof(struct img_config), 64);
215 	err = mdp_vpu_shared_mem_alloc(vpu);
216 	mutex_unlock(vpu->lock);
217 	if (err) {
218 		dev_err(&mdp->pdev->dev, "VPU memory alloc fail!");
219 		goto err_mem_alloc;
220 	}
221 
222 	dev_dbg(&mdp->pdev->dev,
223 		"VPU param:%pK pa:%pad sz:%zx, work:%pK pa:%pad sz:%zx, config:%pK pa:%pad sz:%zx",
224 		vpu->param, &vpu->param_addr, vpu->param_size,
225 		vpu->work, &vpu->work_addr, vpu->work_size,
226 		vpu->config, &vpu->config_addr, vpu->config_size);
227 
228 	msg.work_addr = vpu->work_addr;
229 	msg.work_size = vpu->work_size;
230 	err = mdp_vpu_sendmsg(vpu, SCP_IPI_MDP_INIT, &msg, sizeof(msg));
231 	if (err)
232 		goto err_work_size;
233 
234 	return 0;
235 
236 err_work_size:
237 	switch (vpu->status) {
238 	case -MDP_IPI_EBUSY:
239 		err = -EBUSY;
240 		break;
241 	case -MDP_IPI_ENOMEM:
242 		err = -ENOSPC;	/* -ENOMEM */
243 		break;
244 	}
245 	return err;
246 err_mem_alloc:
247 	return err;
248 }
249 
250 int mdp_vpu_dev_deinit(struct mdp_vpu_dev *vpu)
251 {
252 	struct mdp_ipi_deinit_msg msg = {
253 		.drv_data = (unsigned long)vpu,
254 		.work_addr = vpu->work_addr,
255 	};
256 
257 	return mdp_vpu_sendmsg(vpu, SCP_IPI_MDP_DEINIT, &msg, sizeof(msg));
258 }
259 
260 int mdp_vpu_process(struct mdp_vpu_dev *vpu, struct img_ipi_frameparam *param)
261 {
262 	struct mdp_dev *mdp = vpu_to_mdp(vpu);
263 	struct img_sw_addr addr;
264 
265 	mutex_lock(vpu->lock);
266 	if (mdp_vpu_shared_mem_alloc(vpu)) {
267 		dev_err(&mdp->pdev->dev, "VPU memory alloc fail!");
268 		mutex_unlock(vpu->lock);
269 		return -ENOMEM;
270 	}
271 
272 	memset(vpu->param, 0, vpu->param_size);
273 	memset(vpu->work, 0, vpu->work_size);
274 	memset(vpu->config, 0, vpu->config_size);
275 
276 	param->self_data.va = (unsigned long)vpu->work;
277 	param->self_data.pa = vpu->work_addr;
278 	param->config_data.va = (unsigned long)vpu->config;
279 	param->config_data.pa = vpu->config_addr;
280 	param->drv_data = (unsigned long)vpu;
281 	memcpy(vpu->param, param, sizeof(*param));
282 
283 	addr.pa = vpu->param_addr;
284 	addr.va = (unsigned long)vpu->param;
285 	mutex_unlock(vpu->lock);
286 	return mdp_vpu_sendmsg(vpu, SCP_IPI_MDP_FRAME, &addr, sizeof(addr));
287 }
288