GNU Linux-libre 6.7.9-gnu
[releases.git] / drivers / media / platform / mediatek / mdp3 / mtk-mdp3-core.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/clk.h>
8 #include <linux/module.h>
9 #include <linux/of_platform.h>
10 #include <linux/platform_device.h>
11 #include <linux/pm_runtime.h>
12 #include <linux/remoteproc.h>
13 #include <linux/remoteproc/mtk_scp.h>
14 #include <media/videobuf2-dma-contig.h>
15
16 #include "mtk-mdp3-core.h"
17 #include "mtk-mdp3-cfg.h"
18 #include "mtk-mdp3-m2m.h"
19
20 static const struct of_device_id mdp_of_ids[] = {
21         { .compatible = "mediatek,mt8183-mdp3-rdma",
22           .data = &mt8183_mdp_driver_data,
23         },
24         {},
25 };
26 MODULE_DEVICE_TABLE(of, mdp_of_ids);
27
28 static struct platform_device *__get_pdev_by_id(struct platform_device *pdev,
29                                                 enum mdp_infra_id id)
30 {
31         struct device_node *node;
32         struct platform_device *mdp_pdev = NULL;
33         const struct mtk_mdp_driver_data *mdp_data;
34         const char *compat;
35
36         if (!pdev)
37                 return NULL;
38
39         if (id < MDP_INFRA_MMSYS || id >= MDP_INFRA_MAX) {
40                 dev_err(&pdev->dev, "Illegal infra id %d\n", id);
41                 return NULL;
42         }
43
44         mdp_data = of_device_get_match_data(&pdev->dev);
45         if (!mdp_data) {
46                 dev_err(&pdev->dev, "have no driver data to find node\n");
47                 return NULL;
48         }
49         compat = mdp_data->mdp_probe_infra[id].compatible;
50
51         node = of_find_compatible_node(NULL, NULL, compat);
52         if (WARN_ON(!node)) {
53                 dev_err(&pdev->dev, "find node from id %d failed\n", id);
54                 return NULL;
55         }
56
57         mdp_pdev = of_find_device_by_node(node);
58         of_node_put(node);
59         if (WARN_ON(!mdp_pdev)) {
60                 dev_err(&pdev->dev, "find pdev from id %d failed\n", id);
61                 return NULL;
62         }
63
64         return mdp_pdev;
65 }
66
67 struct platform_device *mdp_get_plat_device(struct platform_device *pdev)
68 {
69         struct device *dev = &pdev->dev;
70         struct device_node *mdp_node;
71         struct platform_device *mdp_pdev;
72
73         mdp_node = of_parse_phandle(dev->of_node, MDP_PHANDLE_NAME, 0);
74         if (!mdp_node) {
75                 dev_err(dev, "can't get node %s\n", MDP_PHANDLE_NAME);
76                 return NULL;
77         }
78
79         mdp_pdev = of_find_device_by_node(mdp_node);
80         of_node_put(mdp_node);
81
82         return mdp_pdev;
83 }
84 EXPORT_SYMBOL_GPL(mdp_get_plat_device);
85
86 int mdp_vpu_get_locked(struct mdp_dev *mdp)
87 {
88         int ret = 0;
89
90         if (mdp->vpu_count++ == 0) {
91                 ret = rproc_boot(mdp->rproc_handle);
92                 if (ret) {
93                         dev_err(&mdp->pdev->dev,
94                                 "vpu_load_firmware failed %d\n", ret);
95                         goto err_load_vpu;
96                 }
97                 ret = mdp_vpu_register(mdp);
98                 if (ret) {
99                         dev_err(&mdp->pdev->dev,
100                                 "mdp_vpu register failed %d\n", ret);
101                         goto err_reg_vpu;
102                 }
103                 ret = mdp_vpu_dev_init(&mdp->vpu, mdp->scp, &mdp->vpu_lock);
104                 if (ret) {
105                         dev_err(&mdp->pdev->dev,
106                                 "mdp_vpu device init failed %d\n", ret);
107                         goto err_init_vpu;
108                 }
109         }
110         return 0;
111
112 err_init_vpu:
113         mdp_vpu_unregister(mdp);
114 err_reg_vpu:
115 err_load_vpu:
116         mdp->vpu_count--;
117         return ret;
118 }
119
120 void mdp_vpu_put_locked(struct mdp_dev *mdp)
121 {
122         if (--mdp->vpu_count == 0) {
123                 mdp_vpu_dev_deinit(&mdp->vpu);
124                 mdp_vpu_unregister(mdp);
125         }
126 }
127
128 void mdp_video_device_release(struct video_device *vdev)
129 {
130         struct mdp_dev *mdp = (struct mdp_dev *)video_get_drvdata(vdev);
131         int i;
132
133         scp_put(mdp->scp);
134
135         destroy_workqueue(mdp->job_wq);
136         destroy_workqueue(mdp->clock_wq);
137
138         pm_runtime_disable(&mdp->pdev->dev);
139
140         vb2_dma_contig_clear_max_seg_size(&mdp->pdev->dev);
141
142         mdp_comp_destroy(mdp);
143         for (i = 0; i < MDP_PIPE_MAX; i++)
144                 mtk_mutex_put(mdp->mdp_mutex[i]);
145
146         mdp_vpu_shared_mem_free(&mdp->vpu);
147         v4l2_m2m_release(mdp->m2m_dev);
148         kfree(mdp);
149 }
150
151 static int mdp_probe(struct platform_device *pdev)
152 {
153         struct device *dev = &pdev->dev;
154         struct mdp_dev *mdp;
155         struct platform_device *mm_pdev;
156         int ret, i, mutex_id;
157
158         mdp = kzalloc(sizeof(*mdp), GFP_KERNEL);
159         if (!mdp) {
160                 ret = -ENOMEM;
161                 goto err_return;
162         }
163
164         mdp->pdev = pdev;
165         mdp->mdp_data = of_device_get_match_data(&pdev->dev);
166
167         mm_pdev = __get_pdev_by_id(pdev, MDP_INFRA_MMSYS);
168         if (!mm_pdev) {
169                 ret = -ENODEV;
170                 goto err_destroy_device;
171         }
172         mdp->mdp_mmsys = &mm_pdev->dev;
173
174         mm_pdev = __get_pdev_by_id(pdev, MDP_INFRA_MUTEX);
175         if (WARN_ON(!mm_pdev)) {
176                 ret = -ENODEV;
177                 goto err_destroy_device;
178         }
179         for (i = 0; i < mdp->mdp_data->pipe_info_len; i++) {
180                 mutex_id = mdp->mdp_data->pipe_info[i].mutex_id;
181                 if (!IS_ERR_OR_NULL(mdp->mdp_mutex[mutex_id]))
182                         continue;
183                 mdp->mdp_mutex[mutex_id] = mtk_mutex_get(&mm_pdev->dev);
184                 if (IS_ERR(mdp->mdp_mutex[mutex_id])) {
185                         ret = PTR_ERR(mdp->mdp_mutex[mutex_id]);
186                         goto err_free_mutex;
187                 }
188         }
189
190         ret = mdp_comp_config(mdp);
191         if (ret) {
192                 dev_err(dev, "Failed to config mdp components\n");
193                 goto err_free_mutex;
194         }
195
196         mdp->job_wq = alloc_workqueue(MDP_MODULE_NAME, WQ_FREEZABLE, 0);
197         if (!mdp->job_wq) {
198                 dev_err(dev, "Unable to create job workqueue\n");
199                 ret = -ENOMEM;
200                 goto err_deinit_comp;
201         }
202
203         mdp->clock_wq = alloc_workqueue(MDP_MODULE_NAME "-clock", WQ_FREEZABLE,
204                                         0);
205         if (!mdp->clock_wq) {
206                 dev_err(dev, "Unable to create clock workqueue\n");
207                 ret = -ENOMEM;
208                 goto err_destroy_job_wq;
209         }
210
211         mm_pdev = __get_pdev_by_id(pdev, MDP_INFRA_SCP);
212         if (WARN_ON(!mm_pdev)) {
213                 dev_err(&pdev->dev, "Could not get scp device\n");
214                 ret = -ENODEV;
215                 goto err_destroy_clock_wq;
216         }
217         mdp->scp = platform_get_drvdata(mm_pdev);
218         mdp->rproc_handle = scp_get_rproc(mdp->scp);
219         dev_dbg(&pdev->dev, "MDP rproc_handle: %pK", mdp->rproc_handle);
220
221         mutex_init(&mdp->vpu_lock);
222         mutex_init(&mdp->m2m_lock);
223
224         mdp->cmdq_clt = cmdq_mbox_create(dev, 0);
225         if (IS_ERR(mdp->cmdq_clt)) {
226                 ret = PTR_ERR(mdp->cmdq_clt);
227                 goto err_put_scp;
228         }
229
230         init_waitqueue_head(&mdp->callback_wq);
231         ida_init(&mdp->mdp_ida);
232         platform_set_drvdata(pdev, mdp);
233
234         vb2_dma_contig_set_max_seg_size(&pdev->dev, DMA_BIT_MASK(32));
235
236         ret = v4l2_device_register(dev, &mdp->v4l2_dev);
237         if (ret) {
238                 dev_err(dev, "Failed to register v4l2 device\n");
239                 ret = -EINVAL;
240                 goto err_mbox_destroy;
241         }
242
243         ret = mdp_m2m_device_register(mdp);
244         if (ret) {
245                 v4l2_err(&mdp->v4l2_dev, "Failed to register m2m device\n");
246                 goto err_unregister_device;
247         }
248
249         dev_dbg(dev, "mdp-%d registered successfully\n", pdev->id);
250         return 0;
251
252 err_unregister_device:
253         v4l2_device_unregister(&mdp->v4l2_dev);
254 err_mbox_destroy:
255         cmdq_mbox_destroy(mdp->cmdq_clt);
256 err_put_scp:
257         scp_put(mdp->scp);
258 err_destroy_clock_wq:
259         destroy_workqueue(mdp->clock_wq);
260 err_destroy_job_wq:
261         destroy_workqueue(mdp->job_wq);
262 err_deinit_comp:
263         mdp_comp_destroy(mdp);
264 err_free_mutex:
265         for (i = 0; i < mdp->mdp_data->pipe_info_len; i++)
266                 if (!IS_ERR_OR_NULL(mdp->mdp_mutex[i]))
267                         mtk_mutex_put(mdp->mdp_mutex[i]);
268 err_destroy_device:
269         kfree(mdp);
270 err_return:
271         dev_dbg(dev, "Errno %d\n", ret);
272         return ret;
273 }
274
275 static void mdp_remove(struct platform_device *pdev)
276 {
277         struct mdp_dev *mdp = platform_get_drvdata(pdev);
278
279         v4l2_device_unregister(&mdp->v4l2_dev);
280
281         dev_dbg(&pdev->dev, "%s driver unloaded\n", pdev->name);
282 }
283
284 static int __maybe_unused mdp_suspend(struct device *dev)
285 {
286         struct mdp_dev *mdp = dev_get_drvdata(dev);
287         int ret;
288
289         atomic_set(&mdp->suspended, 1);
290
291         if (atomic_read(&mdp->job_count)) {
292                 ret = wait_event_timeout(mdp->callback_wq,
293                                          !atomic_read(&mdp->job_count),
294                                          2 * HZ);
295                 if (ret == 0) {
296                         dev_err(dev,
297                                 "%s:flushed cmdq task incomplete, count=%d\n",
298                                 __func__, atomic_read(&mdp->job_count));
299                         return -EBUSY;
300                 }
301         }
302
303         return 0;
304 }
305
306 static int __maybe_unused mdp_resume(struct device *dev)
307 {
308         struct mdp_dev *mdp = dev_get_drvdata(dev);
309
310         atomic_set(&mdp->suspended, 0);
311
312         return 0;
313 }
314
315 static const struct dev_pm_ops mdp_pm_ops = {
316         SET_SYSTEM_SLEEP_PM_OPS(mdp_suspend, mdp_resume)
317 };
318
319 static struct platform_driver mdp_driver = {
320         .probe          = mdp_probe,
321         .remove_new     = mdp_remove,
322         .driver = {
323                 .name   = MDP_MODULE_NAME,
324                 .pm     = &mdp_pm_ops,
325                 .of_match_table = mdp_of_ids,
326         },
327 };
328
329 module_platform_driver(mdp_driver);
330
331 MODULE_AUTHOR("Ping-Hsun Wu <ping-hsun.wu@mediatek.com>");
332 MODULE_DESCRIPTION("MediaTek image processor 3 driver");
333 MODULE_LICENSE("GPL");