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
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
mdp_vpu_dev_deinit(struct mdp_vpu_dev * vpu)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
mdp_vpu_process(struct mdp_vpu_dev * vpu,struct img_ipi_frameparam * param)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