GNU Linux-libre 6.7.9-gnu
[releases.git] / drivers / media / platform / mediatek / mdp3 / mtk-mdp3-vpu.c
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 }