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 
vpu_to_mdp(struct mdp_vpu_dev * vpu)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 
mdp_vpu_shared_mem_alloc(struct mdp_vpu_dev * vpu)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 
mdp_vpu_shared_mem_free(struct mdp_vpu_dev * vpu)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 
mdp_vpu_ipi_handle_init_ack(void * data,unsigned int len,void * priv)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 
mdp_vpu_ipi_handle_deinit_ack(void * data,unsigned int len,void * priv)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 
mdp_vpu_ipi_handle_frame_ack(void * data,unsigned int len,void * priv)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 
mdp_vpu_register(struct mdp_dev * mdp)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 
mdp_vpu_unregister(struct mdp_dev * mdp)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 
mdp_vpu_sendmsg(struct mdp_vpu_dev * vpu,enum scp_ipi_id id,void * buf,unsigned int len)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 
mdp_vpu_dev_init(struct mdp_vpu_dev * vpu,struct mtk_scp * scp,struct mutex * lock)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 	u8 pp_num = mdp->mdp_data->pp_used;
202 
203 	init_completion(&vpu->ipi_acked);
204 	vpu->scp = scp;
205 	vpu->lock = lock;
206 	vpu->work_size = 0;
207 	err = mdp_vpu_sendmsg(vpu, SCP_IPI_MDP_INIT, &msg, sizeof(msg));
208 	if (err)
209 		goto err_work_size;
210 	/* vpu work_size was set in mdp_vpu_ipi_handle_init_ack */
211 
212 	mutex_lock(vpu->lock);
213 	vpu->work_size = ALIGN(vpu->work_size, 64);
214 	vpu->param_size = ALIGN(sizeof(struct img_ipi_frameparam), 64);
215 	vpu->config_size = ALIGN(sizeof(struct img_config) * pp_num, 64);
216 	err = mdp_vpu_shared_mem_alloc(vpu);
217 	mutex_unlock(vpu->lock);
218 	if (err) {
219 		dev_err(&mdp->pdev->dev, "VPU memory alloc fail!");
220 		goto err_mem_alloc;
221 	}
222 
223 	dev_dbg(&mdp->pdev->dev,
224 		"VPU param:%pK pa:%pad sz:%zx, work:%pK pa:%pad sz:%zx, config:%pK pa:%pad sz:%zx",
225 		vpu->param, &vpu->param_addr, vpu->param_size,
226 		vpu->work, &vpu->work_addr, vpu->work_size,
227 		vpu->config, &vpu->config_addr, vpu->config_size);
228 
229 	msg.work_addr = vpu->work_addr;
230 	msg.work_size = vpu->work_size;
231 	err = mdp_vpu_sendmsg(vpu, SCP_IPI_MDP_INIT, &msg, sizeof(msg));
232 	if (err)
233 		goto err_work_size;
234 
235 	return 0;
236 
237 err_work_size:
238 	switch (vpu->status) {
239 	case -MDP_IPI_EBUSY:
240 		err = -EBUSY;
241 		break;
242 	case -MDP_IPI_ENOMEM:
243 		err = -ENOSPC;	/* -ENOMEM */
244 		break;
245 	}
246 	return err;
247 err_mem_alloc:
248 	return err;
249 }
250 
mdp_vpu_dev_deinit(struct mdp_vpu_dev * vpu)251 int mdp_vpu_dev_deinit(struct mdp_vpu_dev *vpu)
252 {
253 	struct mdp_ipi_deinit_msg msg = {
254 		.drv_data = (unsigned long)vpu,
255 		.work_addr = vpu->work_addr,
256 	};
257 
258 	return mdp_vpu_sendmsg(vpu, SCP_IPI_MDP_DEINIT, &msg, sizeof(msg));
259 }
260 
mdp_vpu_process(struct mdp_vpu_dev * vpu,struct img_ipi_frameparam * param)261 int mdp_vpu_process(struct mdp_vpu_dev *vpu, struct img_ipi_frameparam *param)
262 {
263 	struct mdp_dev *mdp = vpu_to_mdp(vpu);
264 	struct img_sw_addr addr;
265 
266 	mutex_lock(vpu->lock);
267 	if (mdp_vpu_shared_mem_alloc(vpu)) {
268 		dev_err(&mdp->pdev->dev, "VPU memory alloc fail!");
269 		mutex_unlock(vpu->lock);
270 		return -ENOMEM;
271 	}
272 
273 	memset(vpu->param, 0, vpu->param_size);
274 	memset(vpu->work, 0, vpu->work_size);
275 	memset(vpu->config, 0, vpu->config_size);
276 
277 	param->self_data.va = (unsigned long)vpu->work;
278 	param->self_data.pa = vpu->work_addr;
279 	param->config_data.va = (unsigned long)vpu->config;
280 	param->config_data.pa = vpu->config_addr;
281 	param->drv_data = (unsigned long)vpu;
282 	memcpy(vpu->param, param, sizeof(*param));
283 
284 	addr.pa = vpu->param_addr;
285 	addr.va = (unsigned long)vpu->param;
286 	mutex_unlock(vpu->lock);
287 	return mdp_vpu_sendmsg(vpu, SCP_IPI_MDP_FRAME, &addr, sizeof(addr));
288 }
289