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