xref: /OK3568_Linux_fs/kernel/drivers/video/rockchip/mpp/mpp_service.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 // SPDX-License-Identifier: (GPL-2.0+ OR MIT)
2 /*
3  * Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd
4  *
5  * author:
6  *	Alpha Lin, alpha.lin@rock-chips.com
7  *	Randy Li, randy.li@rock-chips.com
8  *	Ding Wei, leo.ding@rock-chips.com
9  *
10  */
11 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
12 
13 #include <linux/completion.h>
14 #include <linux/delay.h>
15 #include <linux/module.h>
16 #include <linux/of_platform.h>
17 #include <linux/proc_fs.h>
18 #include <linux/seq_file.h>
19 #include <linux/slab.h>
20 #include <linux/nospec.h>
21 #include <linux/mfd/syscon.h>
22 
23 #include "mpp_debug.h"
24 #include "mpp_common.h"
25 #include "mpp_iommu.h"
26 
27 #define MPP_CLASS_NAME		"mpp_class"
28 #define MPP_SERVICE_NAME	"mpp_service"
29 
30 #define HAS_RKVDEC	IS_ENABLED(CONFIG_ROCKCHIP_MPP_RKVDEC)
31 #define HAS_RKVENC	IS_ENABLED(CONFIG_ROCKCHIP_MPP_RKVENC)
32 #define HAS_VDPU1	IS_ENABLED(CONFIG_ROCKCHIP_MPP_VDPU1)
33 #define HAS_VEPU1	IS_ENABLED(CONFIG_ROCKCHIP_MPP_VEPU1)
34 #define HAS_VDPU2	IS_ENABLED(CONFIG_ROCKCHIP_MPP_VDPU2)
35 #define HAS_VEPU2	IS_ENABLED(CONFIG_ROCKCHIP_MPP_VEPU2)
36 #define HAS_VEPU22	IS_ENABLED(CONFIG_ROCKCHIP_MPP_VEPU22)
37 #define HAS_IEP2	IS_ENABLED(CONFIG_ROCKCHIP_MPP_IEP2)
38 #define HAS_JPGDEC	IS_ENABLED(CONFIG_ROCKCHIP_MPP_JPGDEC)
39 #define HAS_RKVDEC2	IS_ENABLED(CONFIG_ROCKCHIP_MPP_RKVDEC2)
40 #define HAS_RKVENC2	IS_ENABLED(CONFIG_ROCKCHIP_MPP_RKVENC2)
41 #define HAS_AV1DEC	IS_ENABLED(CONFIG_ROCKCHIP_MPP_AV1DEC)
42 #define HAS_VDPP	IS_ENABLED(CONFIG_ROCKCHIP_MPP_VDPP)
43 
44 #define MPP_REGISTER_DRIVER(srv, flag, X, x) {\
45 	if (flag)\
46 		mpp_add_driver(srv, MPP_DRIVER_##X, &rockchip_##x##_driver, "grf_"#x);\
47 	}
48 
49 unsigned int mpp_dev_debug;
50 module_param(mpp_dev_debug, uint, 0644);
51 MODULE_PARM_DESC(mpp_dev_debug, "bit switch for mpp debug information");
52 
53 static const char mpp_version[] = MPP_VERSION;
54 
mpp_init_grf(struct device_node * np,struct mpp_grf_info * grf_info,const char * grf_name)55 static int mpp_init_grf(struct device_node *np,
56 			struct mpp_grf_info *grf_info,
57 			const char *grf_name)
58 {
59 	int ret;
60 	int index;
61 	u32 grf_offset = 0;
62 	u32 grf_value = 0;
63 	struct regmap *grf;
64 
65 	grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
66 	if (IS_ERR_OR_NULL(grf))
67 		return -EINVAL;
68 
69 	ret = of_property_read_u32(np, "rockchip,grf-offset", &grf_offset);
70 	if (ret)
71 		return -ENODATA;
72 
73 	index = of_property_match_string(np, "rockchip,grf-names", grf_name);
74 	if (index < 0)
75 		return -ENODATA;
76 
77 	ret = of_property_read_u32_index(np, "rockchip,grf-values",
78 					 index, &grf_value);
79 	if (ret)
80 		return -ENODATA;
81 
82 	grf_info->grf = grf;
83 	grf_info->offset = grf_offset;
84 	grf_info->val = grf_value;
85 
86 	mpp_set_grf(grf_info);
87 
88 	return 0;
89 }
90 
mpp_add_driver(struct mpp_service * srv,enum MPP_DRIVER_TYPE type,struct platform_driver * driver,const char * grf_name)91 static int mpp_add_driver(struct mpp_service *srv,
92 			  enum MPP_DRIVER_TYPE type,
93 			  struct platform_driver *driver,
94 			  const char *grf_name)
95 {
96 	int ret;
97 
98 	mpp_init_grf(srv->dev->of_node,
99 		     &srv->grf_infos[type],
100 		     grf_name);
101 
102 	if (IS_ENABLED(CONFIG_ROCKCHIP_MPP_AV1DEC) && type == MPP_DRIVER_AV1DEC)
103 		ret = av1dec_driver_register(driver);
104 	else
105 		ret = platform_driver_register(driver);
106 	if (ret)
107 		return ret;
108 
109 	srv->sub_drivers[type] = driver;
110 
111 	return 0;
112 }
113 
mpp_remove_driver(struct mpp_service * srv,int i)114 static int mpp_remove_driver(struct mpp_service *srv, int i)
115 {
116 	if (srv && srv->sub_drivers[i]) {
117 		if (i != MPP_DRIVER_AV1DEC) {
118 			mpp_set_grf(&srv->grf_infos[i]);
119 			platform_driver_unregister(srv->sub_drivers[i]);
120 		} else if (IS_ENABLED(CONFIG_ROCKCHIP_MPP_AV1DEC)) {
121 			av1dec_driver_unregister(srv->sub_drivers[i]);
122 		}
123 		srv->sub_drivers[i] = NULL;
124 	}
125 
126 	return 0;
127 }
128 
mpp_register_service(struct mpp_service * srv,const char * service_name)129 static int mpp_register_service(struct mpp_service *srv,
130 				const char *service_name)
131 {
132 	int ret;
133 	struct device *dev = srv->dev;
134 
135 	/* create a device */
136 	ret = alloc_chrdev_region(&srv->dev_id, 0, 1, service_name);
137 	if (ret) {
138 		dev_err(dev, "alloc dev_t failed\n");
139 		return ret;
140 	}
141 
142 	cdev_init(&srv->mpp_cdev, &rockchip_mpp_fops);
143 	srv->mpp_cdev.owner = THIS_MODULE;
144 	srv->mpp_cdev.ops = &rockchip_mpp_fops;
145 
146 	ret = cdev_add(&srv->mpp_cdev, srv->dev_id, 1);
147 	if (ret) {
148 		unregister_chrdev_region(srv->dev_id, 1);
149 		dev_err(dev, "add device failed\n");
150 		return ret;
151 	}
152 
153 	srv->child_dev = device_create(srv->cls, dev, srv->dev_id,
154 				       NULL, "%s", service_name);
155 
156 	return 0;
157 }
158 
mpp_remove_service(struct mpp_service * srv)159 static int mpp_remove_service(struct mpp_service *srv)
160 {
161 	device_destroy(srv->cls, srv->dev_id);
162 	cdev_del(&srv->mpp_cdev);
163 	unregister_chrdev_region(srv->dev_id, 1);
164 
165 	return 0;
166 }
167 
168 #ifdef CONFIG_ROCKCHIP_MPP_PROC_FS
mpp_procfs_remove(struct mpp_service * srv)169 static int mpp_procfs_remove(struct mpp_service *srv)
170 {
171 	if (srv->procfs) {
172 		proc_remove(srv->procfs);
173 		srv->procfs = NULL;
174 	}
175 
176 	return 0;
177 }
178 
mpp_show_version(struct seq_file * seq,void * offset)179 static int mpp_show_version(struct seq_file *seq, void *offset)
180 {
181 	seq_printf(seq, "%s\n", mpp_version);
182 
183 	return 0;
184 }
185 
mpp_dump_session(struct mpp_session * session,struct seq_file * s)186 static int mpp_dump_session(struct mpp_session *session, struct seq_file *s)
187 {
188 	struct mpp_dma_session *dma = session->dma;
189 	struct mpp_dma_buffer *n;
190 	struct mpp_dma_buffer *buffer;
191 	phys_addr_t end;
192 	unsigned long z = 0, t = 0;
193 	int i = 0;
194 #define K(size) ((unsigned long)((size) >> 10))
195 
196 	if (!dma)
197 		return 0;
198 
199 	seq_puts(s, "session iova range dump:\n");
200 
201 	mutex_lock(&dma->list_mutex);
202 	list_for_each_entry_safe(buffer, n, &dma->used_list, link) {
203 		end = buffer->iova + buffer->size - 1;
204 		z = (unsigned long)buffer->size;
205 		t += z;
206 
207 		seq_printf(s, "%4d: ", i++);
208 		seq_printf(s, "%pa..%pa (%10lu %s)\n", &buffer->iova, &end,
209 			   (z >= 1024) ? (K(z)) : z,
210 			   (z >= 1024) ? "KiB" : "Bytes");
211 	}
212 	i = 0;
213 	list_for_each_entry_safe(buffer, n, &dma->unused_list, link) {
214 		if (!buffer->dmabuf)
215 			continue;
216 
217 		end = buffer->iova + buffer->size - 1;
218 		z = (unsigned long)buffer->size;
219 		t += z;
220 
221 		seq_printf(s, "%4d: ", i++);
222 		seq_printf(s, "%pa..%pa (%10lu %s)\n", &buffer->iova, &end,
223 			   (z >= 1024) ? (K(z)) : z,
224 			   (z >= 1024) ? "KiB" : "Bytes");
225 	}
226 
227 	mutex_unlock(&dma->list_mutex);
228 	seq_printf(s, "session: pid=%d index=%d\n", session->pid, session->index);
229 	seq_printf(s, " device: %s\n", dev_name(session->mpp->dev));
230 	seq_printf(s, " memory: %lu MiB\n", K(K(t)));
231 
232 	return 0;
233 }
234 
mpp_show_session_summary(struct seq_file * seq,void * offset)235 static int mpp_show_session_summary(struct seq_file *seq, void *offset)
236 {
237 	struct mpp_session *session = NULL, *n;
238 	struct mpp_service *srv = seq->private;
239 
240 	mutex_lock(&srv->session_lock);
241 	list_for_each_entry_safe(session, n,
242 				 &srv->session_list,
243 				 service_link) {
244 		struct  mpp_dev *mpp;
245 
246 		if (!session->priv)
247 			continue;
248 
249 		if (!session->mpp)
250 			continue;
251 		mpp = session->mpp;
252 
253 		mpp_dump_session(session, seq);
254 
255 		if (mpp->dev_ops->dump_session)
256 			mpp->dev_ops->dump_session(session, seq);
257 	}
258 	mutex_unlock(&srv->session_lock);
259 
260 	return 0;
261 }
262 
mpp_show_support_cmd(struct seq_file * file,void * v)263 static int mpp_show_support_cmd(struct seq_file *file, void *v)
264 {
265 	seq_puts(file, "------------- SUPPORT CMD -------------\n");
266 	seq_printf(file, "QUERY_HW_SUPPORT:     0x%08x\n", MPP_CMD_QUERY_HW_SUPPORT);
267 	seq_printf(file, "QUERY_HW_ID:          0x%08x\n", MPP_CMD_QUERY_HW_ID);
268 	seq_printf(file, "QUERY_CMD_SUPPORT:    0x%08x\n", MPP_CMD_QUERY_CMD_SUPPORT);
269 	seq_printf(file, "QUERY_BUTT:           0x%08x\n", MPP_CMD_QUERY_BUTT);
270 	seq_puts(file, "----\n");
271 	seq_printf(file, "INIT_CLIENT_TYPE:     0x%08x\n", MPP_CMD_INIT_CLIENT_TYPE);
272 	seq_printf(file, "INIT_TRANS_TABLE:     0x%08x\n", MPP_CMD_INIT_TRANS_TABLE);
273 	seq_printf(file, "INIT_BUTT:            0x%08x\n", MPP_CMD_INIT_BUTT);
274 	seq_puts(file, "----\n");
275 	seq_printf(file, "SET_REG_WRITE:        0x%08x\n", MPP_CMD_SET_REG_WRITE);
276 	seq_printf(file, "SET_REG_READ:         0x%08x\n", MPP_CMD_SET_REG_READ);
277 	seq_printf(file, "SET_REG_ADDR_OFFSET:  0x%08x\n", MPP_CMD_SET_REG_ADDR_OFFSET);
278 	seq_printf(file, "SEND_BUTT:            0x%08x\n", MPP_CMD_SEND_BUTT);
279 	seq_puts(file, "----\n");
280 	seq_printf(file, "POLL_HW_FINISH:       0x%08x\n", MPP_CMD_POLL_HW_FINISH);
281 	seq_printf(file, "POLL_BUTT:            0x%08x\n", MPP_CMD_POLL_BUTT);
282 	seq_puts(file, "----\n");
283 	seq_printf(file, "RESET_SESSION:        0x%08x\n", MPP_CMD_RESET_SESSION);
284 	seq_printf(file, "TRANS_FD_TO_IOVA:     0x%08x\n", MPP_CMD_TRANS_FD_TO_IOVA);
285 	seq_printf(file, "RELEASE_FD:           0x%08x\n", MPP_CMD_RELEASE_FD);
286 	seq_printf(file, "SEND_CODEC_INFO:      0x%08x\n", MPP_CMD_SEND_CODEC_INFO);
287 	seq_printf(file, "CONTROL_BUTT:         0x%08x\n", MPP_CMD_CONTROL_BUTT);
288 
289 	return 0;
290 }
291 
mpp_show_support_device(struct seq_file * file,void * v)292 static int mpp_show_support_device(struct seq_file *file, void *v)
293 {
294 	u32 i;
295 	struct mpp_service *srv = file->private;
296 
297 	seq_puts(file, "---- SUPPORT DEVICES ----\n");
298 	for (i = 0; i < MPP_DEVICE_BUTT; i++) {
299 		struct mpp_dev *mpp;
300 		struct mpp_hw_info *hw_info;
301 
302 		if (test_bit(i, &srv->hw_support)) {
303 			mpp = srv->sub_devices[array_index_nospec(i, MPP_DEVICE_BUTT)];
304 			if (!mpp)
305 				continue;
306 
307 			seq_printf(file, "DEVICE[%2d]:%-10s", i, mpp_device_name[i]);
308 			hw_info = mpp->var->hw_info;
309 			if (hw_info->hw_id)
310 				seq_printf(file, "HW_ID:0x%08x", hw_info->hw_id);
311 			seq_puts(file, "\n");
312 		}
313 	}
314 
315 	return 0;
316 }
317 
mpp_procfs_init(struct mpp_service * srv)318 static int mpp_procfs_init(struct mpp_service *srv)
319 {
320 	srv->procfs = proc_mkdir(MPP_SERVICE_NAME, NULL);
321 	if (IS_ERR_OR_NULL(srv->procfs)) {
322 		mpp_err("failed on mkdir /proc/%s\n", MPP_SERVICE_NAME);
323 		srv->procfs = NULL;
324 		return -EIO;
325 	}
326 	/* show version */
327 	proc_create_single("version", 0444, srv->procfs, mpp_show_version);
328 	/* for show session info */
329 	proc_create_single_data("sessions-summary", 0444,
330 				srv->procfs, mpp_show_session_summary, srv);
331 	/* show support dev cmd */
332 	proc_create_single("supports-cmd", 0444, srv->procfs, mpp_show_support_cmd);
333 	/* show support devices */
334 	proc_create_single_data("supports-device", 0444,
335 				srv->procfs, mpp_show_support_device, srv);
336 	mpp_procfs_create_u32("timing_en", 0644, srv->procfs, &srv->timing_en);
337 
338 	return 0;
339 }
340 #else
mpp_procfs_remove(struct mpp_service * srv)341 static inline int mpp_procfs_remove(struct mpp_service *srv)
342 {
343 	return 0;
344 }
345 
mpp_procfs_init(struct mpp_service * srv)346 static inline int mpp_procfs_init(struct mpp_service *srv)
347 {
348 	return 0;
349 }
350 #endif
351 
mpp_service_probe(struct platform_device * pdev)352 static int mpp_service_probe(struct platform_device *pdev)
353 {
354 	int ret, i;
355 	struct mpp_service *srv = NULL;
356 	struct mpp_taskqueue *queue;
357 	struct device *dev = &pdev->dev;
358 	struct device_node *np = dev->of_node;
359 
360 	dev_info(dev, "%s\n", mpp_version);
361 	dev_info(dev, "probe start\n");
362 	srv = devm_kzalloc(dev, sizeof(*srv), GFP_KERNEL);
363 	if (!srv)
364 		return -ENOMEM;
365 
366 	srv->dev = dev;
367 	atomic_set(&srv->shutdown_request, 0);
368 	platform_set_drvdata(pdev, srv);
369 
370 	srv->cls = class_create(THIS_MODULE, MPP_CLASS_NAME);
371 	if (PTR_ERR_OR_ZERO(srv->cls))
372 		return PTR_ERR(srv->cls);
373 
374 	of_property_read_u32(np, "rockchip,taskqueue-count",
375 			     &srv->taskqueue_cnt);
376 	if (srv->taskqueue_cnt > MPP_DEVICE_BUTT) {
377 		dev_err(dev, "rockchip,taskqueue-count %d must less than %d\n",
378 			srv->taskqueue_cnt, MPP_DEVICE_BUTT);
379 		return -EINVAL;
380 	}
381 
382 	for (i = 0; i < srv->taskqueue_cnt; i++) {
383 		queue = mpp_taskqueue_init(dev);
384 		if (!queue)
385 			continue;
386 
387 		kthread_init_worker(&queue->worker);
388 		queue->kworker_task = kthread_run(kthread_worker_fn, &queue->worker,
389 						  "queue_work%d", i);
390 		srv->task_queues[i] = queue;
391 	}
392 
393 	of_property_read_u32(np, "rockchip,resetgroup-count",
394 			     &srv->reset_group_cnt);
395 	if (srv->reset_group_cnt > MPP_DEVICE_BUTT) {
396 		dev_err(dev, "rockchip,resetgroup-count %d must less than %d\n",
397 			srv->reset_group_cnt, MPP_DEVICE_BUTT);
398 		return -EINVAL;
399 	}
400 
401 	if (srv->reset_group_cnt) {
402 		u32 i = 0;
403 		struct mpp_reset_group *group;
404 
405 		for (i = 0; i < srv->reset_group_cnt; i++) {
406 			group = devm_kzalloc(dev, sizeof(*group), GFP_KERNEL);
407 			if (!group)
408 				continue;
409 
410 			init_rwsem(&group->rw_sem);
411 			srv->reset_groups[i] = group;
412 		}
413 	}
414 
415 	ret = mpp_register_service(srv, MPP_SERVICE_NAME);
416 	if (ret) {
417 		dev_err(dev, "register %s device\n", MPP_SERVICE_NAME);
418 		goto fail_register;
419 	}
420 	mutex_init(&srv->session_lock);
421 	INIT_LIST_HEAD(&srv->session_list);
422 	mpp_procfs_init(srv);
423 
424 	/* register sub drivers */
425 	MPP_REGISTER_DRIVER(srv, HAS_RKVDEC, RKVDEC, rkvdec);
426 	MPP_REGISTER_DRIVER(srv, HAS_RKVENC, RKVENC, rkvenc);
427 	MPP_REGISTER_DRIVER(srv, HAS_VDPU1, VDPU1, vdpu1);
428 	MPP_REGISTER_DRIVER(srv, HAS_VEPU1, VEPU1, vepu1);
429 	MPP_REGISTER_DRIVER(srv, HAS_VDPU2, VDPU2, vdpu2);
430 	MPP_REGISTER_DRIVER(srv, HAS_VEPU2, VEPU2, vepu2);
431 	MPP_REGISTER_DRIVER(srv, HAS_VEPU22, VEPU22, vepu22);
432 	MPP_REGISTER_DRIVER(srv, HAS_IEP2, IEP2, iep2);
433 	MPP_REGISTER_DRIVER(srv, HAS_JPGDEC, JPGDEC, jpgdec);
434 	MPP_REGISTER_DRIVER(srv, HAS_RKVDEC2, RKVDEC2, rkvdec2);
435 	MPP_REGISTER_DRIVER(srv, HAS_RKVENC2, RKVENC2, rkvenc2);
436 	MPP_REGISTER_DRIVER(srv, HAS_AV1DEC, AV1DEC, av1dec);
437 	MPP_REGISTER_DRIVER(srv, HAS_VDPP, VDPP, vdpp);
438 
439 	dev_info(dev, "probe success\n");
440 
441 	return 0;
442 
443 fail_register:
444 	class_destroy(srv->cls);
445 
446 	return ret;
447 }
448 
mpp_service_remove(struct platform_device * pdev)449 static int mpp_service_remove(struct platform_device *pdev)
450 {
451 	struct mpp_taskqueue *queue;
452 	struct device *dev = &pdev->dev;
453 	struct mpp_service *srv = platform_get_drvdata(pdev);
454 	int i;
455 
456 	dev_info(dev, "remove device\n");
457 
458 	for (i = 0; i < srv->taskqueue_cnt; i++) {
459 		queue = srv->task_queues[i];
460 		if (queue && queue->kworker_task) {
461 			kthread_flush_worker(&queue->worker);
462 			kthread_stop(queue->kworker_task);
463 			queue->kworker_task = NULL;
464 		}
465 	}
466 
467 	/* remove sub drivers */
468 	for (i = 0; i < MPP_DRIVER_BUTT; i++)
469 		mpp_remove_driver(srv, i);
470 
471 	mpp_remove_service(srv);
472 	class_destroy(srv->cls);
473 	mpp_procfs_remove(srv);
474 
475 	return 0;
476 }
477 
478 static const struct of_device_id mpp_dt_ids[] = {
479 	{
480 		.compatible = "rockchip,mpp-service",
481 	},
482 	{ },
483 };
484 
485 static struct platform_driver mpp_service_driver = {
486 	.probe = mpp_service_probe,
487 	.remove = mpp_service_remove,
488 	.driver = {
489 		.name = "mpp_service",
490 		.of_match_table = of_match_ptr(mpp_dt_ids),
491 	},
492 };
493 
494 module_platform_driver(mpp_service_driver);
495 
496 MODULE_LICENSE("Dual MIT/GPL");
497 MODULE_VERSION(MPP_VERSION);
498 MODULE_AUTHOR("Ding Wei leo.ding@rock-chips.com");
499 MODULE_DESCRIPTION("Rockchip mpp service driver");
500