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 	{ .compatible = "mediatek,mt8188-mdp3-rdma",
25 	  .data = &mt8188_mdp_driver_data,
26 	},
27 	{ .compatible = "mediatek,mt8195-mdp3-rdma",
28 	  .data = &mt8195_mdp_driver_data,
29 	},
30 	{ .compatible = "mediatek,mt8195-mdp3-wrot",
31 	  .data = &mt8195_mdp_driver_data,
32 	},
33 	{},
34 };
35 MODULE_DEVICE_TABLE(of, mdp_of_ids);
36 
__get_pdev_by_id(struct platform_device * pdev,struct platform_device * from,enum mdp_infra_id id)37 static struct platform_device *__get_pdev_by_id(struct platform_device *pdev,
38 						struct platform_device *from,
39 						enum mdp_infra_id id)
40 {
41 	struct device_node *node, *f = NULL;
42 	struct platform_device *mdp_pdev = NULL;
43 	const struct mtk_mdp_driver_data *mdp_data;
44 	const char *compat;
45 
46 	if (!pdev)
47 		return NULL;
48 
49 	if (id < MDP_INFRA_MMSYS || id >= MDP_INFRA_MAX) {
50 		dev_err(&pdev->dev, "Illegal infra id %d\n", id);
51 		return NULL;
52 	}
53 
54 	mdp_data = of_device_get_match_data(&pdev->dev);
55 	if (!mdp_data) {
56 		dev_err(&pdev->dev, "have no driver data to find node\n");
57 		return NULL;
58 	}
59 
60 	compat = mdp_data->mdp_probe_infra[id].compatible;
61 	if (strlen(compat) == 0)
62 		return NULL;
63 
64 	if (from)
65 		f = from->dev.of_node;
66 	node = of_find_compatible_node(f, NULL, compat);
67 	if (WARN_ON(!node)) {
68 		dev_err(&pdev->dev, "find node from id %d failed\n", id);
69 		return NULL;
70 	}
71 
72 	mdp_pdev = of_find_device_by_node(node);
73 	of_node_put(node);
74 	if (WARN_ON(!mdp_pdev)) {
75 		dev_err(&pdev->dev, "find pdev from id %d failed\n", id);
76 		return NULL;
77 	}
78 
79 	return mdp_pdev;
80 }
81 
mdp_get_plat_device(struct platform_device * pdev)82 struct platform_device *mdp_get_plat_device(struct platform_device *pdev)
83 {
84 	struct device *dev = &pdev->dev;
85 	struct device_node *mdp_node;
86 	struct platform_device *mdp_pdev;
87 
88 	mdp_node = of_parse_phandle(dev->of_node, MDP_PHANDLE_NAME, 0);
89 	if (!mdp_node) {
90 		dev_err(dev, "can't get node %s\n", MDP_PHANDLE_NAME);
91 		return NULL;
92 	}
93 
94 	mdp_pdev = of_find_device_by_node(mdp_node);
95 	of_node_put(mdp_node);
96 
97 	return mdp_pdev;
98 }
99 EXPORT_SYMBOL_GPL(mdp_get_plat_device);
100 
mdp_vpu_get_locked(struct mdp_dev * mdp)101 int mdp_vpu_get_locked(struct mdp_dev *mdp)
102 {
103 	int ret = 0;
104 
105 	if (mdp->vpu_count++ == 0) {
106 		ret = rproc_boot(mdp->rproc_handle);
107 		if (ret) {
108 			dev_err(&mdp->pdev->dev,
109 				"vpu_load_firmware failed %d\n", ret);
110 			goto err_load_vpu;
111 		}
112 		ret = mdp_vpu_register(mdp);
113 		if (ret) {
114 			dev_err(&mdp->pdev->dev,
115 				"mdp_vpu register failed %d\n", ret);
116 			goto err_reg_vpu;
117 		}
118 		ret = mdp_vpu_dev_init(&mdp->vpu, mdp->scp, &mdp->vpu_lock);
119 		if (ret) {
120 			dev_err(&mdp->pdev->dev,
121 				"mdp_vpu device init failed %d\n", ret);
122 			goto err_init_vpu;
123 		}
124 	}
125 	return 0;
126 
127 err_init_vpu:
128 	mdp_vpu_unregister(mdp);
129 err_reg_vpu:
130 err_load_vpu:
131 	mdp->vpu_count--;
132 	return ret;
133 }
134 
mdp_vpu_put_locked(struct mdp_dev * mdp)135 void mdp_vpu_put_locked(struct mdp_dev *mdp)
136 {
137 	if (--mdp->vpu_count == 0) {
138 		mdp_vpu_dev_deinit(&mdp->vpu);
139 		mdp_vpu_unregister(mdp);
140 	}
141 }
142 
mdp_video_device_release(struct video_device * vdev)143 void mdp_video_device_release(struct video_device *vdev)
144 {
145 	struct mdp_dev *mdp = (struct mdp_dev *)video_get_drvdata(vdev);
146 	int i;
147 
148 	for (i = 0; i < mdp->mdp_data->pp_used; i++)
149 		if (mdp->cmdq_clt[i])
150 			cmdq_mbox_destroy(mdp->cmdq_clt[i]);
151 
152 	scp_put(mdp->scp);
153 
154 	destroy_workqueue(mdp->job_wq);
155 	destroy_workqueue(mdp->clock_wq);
156 
157 	pm_runtime_disable(&mdp->pdev->dev);
158 
159 	vb2_dma_contig_clear_max_seg_size(&mdp->pdev->dev);
160 
161 	mdp_comp_destroy(mdp);
162 	for (i = 0; i < mdp->mdp_data->pipe_info_len; i++) {
163 		enum mdp_mm_subsys_id idx;
164 		struct mtk_mutex *m;
165 		u32 m_id;
166 
167 		idx = mdp->mdp_data->pipe_info[i].sub_id;
168 		m_id = mdp->mdp_data->pipe_info[i].mutex_id;
169 		m = mdp->mm_subsys[idx].mdp_mutex[m_id];
170 		if (!IS_ERR_OR_NULL(m))
171 			mtk_mutex_put(m);
172 	}
173 
174 	mdp_vpu_shared_mem_free(&mdp->vpu);
175 	v4l2_m2m_release(mdp->m2m_dev);
176 	kfree(mdp);
177 }
178 
mdp_mm_subsys_deploy(struct mdp_dev * mdp,enum mdp_infra_id id)179 static int mdp_mm_subsys_deploy(struct mdp_dev *mdp, enum mdp_infra_id id)
180 {
181 	struct platform_device *mm_pdev = NULL;
182 	struct device **dev;
183 	int i;
184 
185 	if (!mdp)
186 		return -EINVAL;
187 
188 	for (i = 0; i < MDP_MM_SUBSYS_MAX; i++) {
189 		const char *compat;
190 		enum mdp_infra_id sub_id = id + i;
191 
192 		switch (id) {
193 		case MDP_INFRA_MMSYS:
194 			dev = &mdp->mm_subsys[i].mmsys;
195 			break;
196 		case MDP_INFRA_MUTEX:
197 			dev = &mdp->mm_subsys[i].mutex;
198 			break;
199 		default:
200 			dev_err(&mdp->pdev->dev, "Unknown infra id %d", id);
201 			return -EINVAL;
202 		}
203 
204 		/*
205 		 * Not every chip has multiple multimedia subsystems, so
206 		 * the config may be null.
207 		 */
208 		compat = mdp->mdp_data->mdp_probe_infra[sub_id].compatible;
209 		if (strlen(compat) == 0)
210 			continue;
211 
212 		mm_pdev = __get_pdev_by_id(mdp->pdev, mm_pdev, sub_id);
213 		if (WARN_ON(!mm_pdev))
214 			return -ENODEV;
215 
216 		*dev = &mm_pdev->dev;
217 	}
218 
219 	return 0;
220 }
221 
mdp_probe(struct platform_device * pdev)222 static int mdp_probe(struct platform_device *pdev)
223 {
224 	struct device *dev = &pdev->dev;
225 	struct mdp_dev *mdp;
226 	struct platform_device *mm_pdev;
227 	struct resource *res;
228 	int ret, i, mutex_id;
229 
230 	mdp = kzalloc(sizeof(*mdp), GFP_KERNEL);
231 	if (!mdp) {
232 		ret = -ENOMEM;
233 		goto err_return;
234 	}
235 
236 	mdp->pdev = pdev;
237 	mdp->mdp_data = of_device_get_match_data(&pdev->dev);
238 
239 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
240 	if (res->start != mdp->mdp_data->mdp_con_res) {
241 		platform_set_drvdata(pdev, mdp);
242 		goto success_return;
243 	}
244 
245 	ret = mdp_mm_subsys_deploy(mdp, MDP_INFRA_MMSYS);
246 	if (ret)
247 		goto err_destroy_device;
248 
249 	ret = mdp_mm_subsys_deploy(mdp, MDP_INFRA_MUTEX);
250 	if (ret)
251 		goto err_destroy_device;
252 
253 	for (i = 0; i < mdp->mdp_data->pipe_info_len; i++) {
254 		enum mdp_mm_subsys_id idx;
255 		struct mtk_mutex **m;
256 
257 		idx = mdp->mdp_data->pipe_info[i].sub_id;
258 		mutex_id = mdp->mdp_data->pipe_info[i].mutex_id;
259 		m = &mdp->mm_subsys[idx].mdp_mutex[mutex_id];
260 
261 		if (!IS_ERR_OR_NULL(*m))
262 			continue;
263 
264 		*m = mtk_mutex_get(mdp->mm_subsys[idx].mutex);
265 		if (IS_ERR(*m)) {
266 			ret = PTR_ERR(*m);
267 			goto err_free_mutex;
268 		}
269 	}
270 
271 	ret = mdp_comp_config(mdp);
272 	if (ret) {
273 		dev_err(dev, "Failed to config mdp components\n");
274 		goto err_free_mutex;
275 	}
276 
277 	mdp->job_wq = alloc_workqueue(MDP_MODULE_NAME, WQ_FREEZABLE, 0);
278 	if (!mdp->job_wq) {
279 		dev_err(dev, "Unable to create job workqueue\n");
280 		ret = -ENOMEM;
281 		goto err_deinit_comp;
282 	}
283 
284 	mdp->clock_wq = alloc_workqueue(MDP_MODULE_NAME "-clock", WQ_FREEZABLE,
285 					0);
286 	if (!mdp->clock_wq) {
287 		dev_err(dev, "Unable to create clock workqueue\n");
288 		ret = -ENOMEM;
289 		goto err_destroy_job_wq;
290 	}
291 
292 	mdp->scp = scp_get(pdev);
293 	if (!mdp->scp) {
294 		mm_pdev = __get_pdev_by_id(pdev, NULL, MDP_INFRA_SCP);
295 		if (WARN_ON(!mm_pdev)) {
296 			dev_err(&pdev->dev, "Could not get scp device\n");
297 			ret = -ENODEV;
298 			goto err_destroy_clock_wq;
299 		}
300 		mdp->scp = platform_get_drvdata(mm_pdev);
301 	}
302 
303 	mdp->rproc_handle = scp_get_rproc(mdp->scp);
304 	dev_dbg(&pdev->dev, "MDP rproc_handle: %pK", mdp->rproc_handle);
305 
306 	mutex_init(&mdp->vpu_lock);
307 	mutex_init(&mdp->m2m_lock);
308 
309 	for (i = 0; i < mdp->mdp_data->pp_used; i++) {
310 		mdp->cmdq_clt[i] = cmdq_mbox_create(dev, i);
311 		if (IS_ERR(mdp->cmdq_clt[i])) {
312 			ret = PTR_ERR(mdp->cmdq_clt[i]);
313 			goto err_mbox_destroy;
314 		}
315 	}
316 
317 	init_waitqueue_head(&mdp->callback_wq);
318 	ida_init(&mdp->mdp_ida);
319 	platform_set_drvdata(pdev, mdp);
320 
321 	vb2_dma_contig_set_max_seg_size(&pdev->dev, DMA_BIT_MASK(32));
322 
323 	ret = v4l2_device_register(dev, &mdp->v4l2_dev);
324 	if (ret) {
325 		dev_err(dev, "Failed to register v4l2 device\n");
326 		ret = -EINVAL;
327 		goto err_mbox_destroy;
328 	}
329 
330 	ret = mdp_m2m_device_register(mdp);
331 	if (ret) {
332 		v4l2_err(&mdp->v4l2_dev, "Failed to register m2m device\n");
333 		goto err_unregister_device;
334 	}
335 
336 success_return:
337 	dev_dbg(dev, "mdp-%d registered successfully\n", pdev->id);
338 	return 0;
339 
340 err_unregister_device:
341 	v4l2_device_unregister(&mdp->v4l2_dev);
342 err_mbox_destroy:
343 	while (--i >= 0)
344 		cmdq_mbox_destroy(mdp->cmdq_clt[i]);
345 	scp_put(mdp->scp);
346 err_destroy_clock_wq:
347 	destroy_workqueue(mdp->clock_wq);
348 err_destroy_job_wq:
349 	destroy_workqueue(mdp->job_wq);
350 err_deinit_comp:
351 	mdp_comp_destroy(mdp);
352 err_free_mutex:
353 	for (i = 0; i < mdp->mdp_data->pipe_info_len; i++) {
354 		enum mdp_mm_subsys_id idx;
355 		struct mtk_mutex *m;
356 
357 		idx = mdp->mdp_data->pipe_info[i].sub_id;
358 		mutex_id = mdp->mdp_data->pipe_info[i].mutex_id;
359 		m = mdp->mm_subsys[idx].mdp_mutex[mutex_id];
360 		if (!IS_ERR_OR_NULL(m))
361 			mtk_mutex_put(m);
362 	}
363 err_destroy_device:
364 	kfree(mdp);
365 err_return:
366 	dev_dbg(dev, "Errno %d\n", ret);
367 	return ret;
368 }
369 
mdp_remove(struct platform_device * pdev)370 static void mdp_remove(struct platform_device *pdev)
371 {
372 	struct mdp_dev *mdp = platform_get_drvdata(pdev);
373 
374 	v4l2_device_unregister(&mdp->v4l2_dev);
375 
376 	dev_dbg(&pdev->dev, "%s driver unloaded\n", pdev->name);
377 }
378 
mdp_suspend(struct device * dev)379 static int __maybe_unused mdp_suspend(struct device *dev)
380 {
381 	struct mdp_dev *mdp = dev_get_drvdata(dev);
382 	int ret;
383 
384 	atomic_set(&mdp->suspended, 1);
385 
386 	if (refcount_read(&mdp->job_count)) {
387 		ret = wait_event_timeout(mdp->callback_wq,
388 					 !refcount_read(&mdp->job_count),
389 					 2 * HZ);
390 		if (ret == 0) {
391 			dev_err(dev,
392 				"%s:flushed cmdq task incomplete, count=%d\n",
393 				__func__, refcount_read(&mdp->job_count));
394 			return -EBUSY;
395 		}
396 	}
397 
398 	return 0;
399 }
400 
mdp_resume(struct device * dev)401 static int __maybe_unused mdp_resume(struct device *dev)
402 {
403 	struct mdp_dev *mdp = dev_get_drvdata(dev);
404 
405 	atomic_set(&mdp->suspended, 0);
406 
407 	return 0;
408 }
409 
410 static const struct dev_pm_ops mdp_pm_ops = {
411 	SET_SYSTEM_SLEEP_PM_OPS(mdp_suspend, mdp_resume)
412 };
413 
414 static struct platform_driver mdp_driver = {
415 	.probe		= mdp_probe,
416 	.remove_new	= mdp_remove,
417 	.driver = {
418 		.name	= MDP_MODULE_NAME,
419 		.pm	= &mdp_pm_ops,
420 		.of_match_table = mdp_of_ids,
421 	},
422 };
423 
424 module_platform_driver(mdp_driver);
425 
426 MODULE_AUTHOR("Ping-Hsun Wu <ping-hsun.wu@mediatek.com>");
427 MODULE_DESCRIPTION("MediaTek image processor 3 driver");
428 MODULE_LICENSE("GPL");
429