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 
__get_pdev_by_id(struct platform_device * pdev,enum mdp_infra_id id)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 
mdp_get_plat_device(struct platform_device * pdev)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 
mdp_vpu_get_locked(struct mdp_dev * mdp)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 
mdp_vpu_put_locked(struct mdp_dev * mdp)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 
mdp_video_device_release(struct video_device * vdev)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 
mdp_probe(struct platform_device * pdev)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 	mdp->scp = scp_get(pdev);
212 	if (!mdp->scp) {
213 		mm_pdev = __get_pdev_by_id(pdev, MDP_INFRA_SCP);
214 		if (WARN_ON(!mm_pdev)) {
215 			dev_err(&pdev->dev, "Could not get scp device\n");
216 			ret = -ENODEV;
217 			goto err_destroy_clock_wq;
218 		}
219 		mdp->scp = platform_get_drvdata(mm_pdev);
220 	}
221 
222 	mdp->rproc_handle = scp_get_rproc(mdp->scp);
223 	dev_dbg(&pdev->dev, "MDP rproc_handle: %pK", mdp->rproc_handle);
224 
225 	mutex_init(&mdp->vpu_lock);
226 	mutex_init(&mdp->m2m_lock);
227 
228 	mdp->cmdq_clt = cmdq_mbox_create(dev, 0);
229 	if (IS_ERR(mdp->cmdq_clt)) {
230 		ret = PTR_ERR(mdp->cmdq_clt);
231 		goto err_put_scp;
232 	}
233 
234 	init_waitqueue_head(&mdp->callback_wq);
235 	ida_init(&mdp->mdp_ida);
236 	platform_set_drvdata(pdev, mdp);
237 
238 	vb2_dma_contig_set_max_seg_size(&pdev->dev, DMA_BIT_MASK(32));
239 
240 	ret = v4l2_device_register(dev, &mdp->v4l2_dev);
241 	if (ret) {
242 		dev_err(dev, "Failed to register v4l2 device\n");
243 		ret = -EINVAL;
244 		goto err_mbox_destroy;
245 	}
246 
247 	ret = mdp_m2m_device_register(mdp);
248 	if (ret) {
249 		v4l2_err(&mdp->v4l2_dev, "Failed to register m2m device\n");
250 		goto err_unregister_device;
251 	}
252 
253 	dev_dbg(dev, "mdp-%d registered successfully\n", pdev->id);
254 	return 0;
255 
256 err_unregister_device:
257 	v4l2_device_unregister(&mdp->v4l2_dev);
258 err_mbox_destroy:
259 	cmdq_mbox_destroy(mdp->cmdq_clt);
260 err_put_scp:
261 	scp_put(mdp->scp);
262 err_destroy_clock_wq:
263 	destroy_workqueue(mdp->clock_wq);
264 err_destroy_job_wq:
265 	destroy_workqueue(mdp->job_wq);
266 err_deinit_comp:
267 	mdp_comp_destroy(mdp);
268 err_free_mutex:
269 	for (i = 0; i < mdp->mdp_data->pipe_info_len; i++)
270 		if (!IS_ERR_OR_NULL(mdp->mdp_mutex[i]))
271 			mtk_mutex_put(mdp->mdp_mutex[i]);
272 err_destroy_device:
273 	kfree(mdp);
274 err_return:
275 	dev_dbg(dev, "Errno %d\n", ret);
276 	return ret;
277 }
278 
mdp_remove(struct platform_device * pdev)279 static void mdp_remove(struct platform_device *pdev)
280 {
281 	struct mdp_dev *mdp = platform_get_drvdata(pdev);
282 
283 	v4l2_device_unregister(&mdp->v4l2_dev);
284 
285 	dev_dbg(&pdev->dev, "%s driver unloaded\n", pdev->name);
286 }
287 
mdp_suspend(struct device * dev)288 static int __maybe_unused mdp_suspend(struct device *dev)
289 {
290 	struct mdp_dev *mdp = dev_get_drvdata(dev);
291 	int ret;
292 
293 	atomic_set(&mdp->suspended, 1);
294 
295 	if (atomic_read(&mdp->job_count)) {
296 		ret = wait_event_timeout(mdp->callback_wq,
297 					 !atomic_read(&mdp->job_count),
298 					 2 * HZ);
299 		if (ret == 0) {
300 			dev_err(dev,
301 				"%s:flushed cmdq task incomplete, count=%d\n",
302 				__func__, atomic_read(&mdp->job_count));
303 			return -EBUSY;
304 		}
305 	}
306 
307 	return 0;
308 }
309 
mdp_resume(struct device * dev)310 static int __maybe_unused mdp_resume(struct device *dev)
311 {
312 	struct mdp_dev *mdp = dev_get_drvdata(dev);
313 
314 	atomic_set(&mdp->suspended, 0);
315 
316 	return 0;
317 }
318 
319 static const struct dev_pm_ops mdp_pm_ops = {
320 	SET_SYSTEM_SLEEP_PM_OPS(mdp_suspend, mdp_resume)
321 };
322 
323 static struct platform_driver mdp_driver = {
324 	.probe		= mdp_probe,
325 	.remove_new	= mdp_remove,
326 	.driver = {
327 		.name	= MDP_MODULE_NAME,
328 		.pm	= &mdp_pm_ops,
329 		.of_match_table = mdp_of_ids,
330 	},
331 };
332 
333 module_platform_driver(mdp_driver);
334 
335 MODULE_AUTHOR("Ping-Hsun Wu <ping-hsun.wu@mediatek.com>");
336 MODULE_DESCRIPTION("MediaTek image processor 3 driver");
337 MODULE_LICENSE("GPL");
338