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