xref: /linux/drivers/gpu/drm/rockchip/rockchip_drm_drv.c (revision 3f1c07fc21c68bd3bd2df9d2c9441f6485e934d9)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (C) Rockchip Electronics Co., Ltd.
4  * Author:Mark Yao <mark.yao@rock-chips.com>
5  *
6  * based on exynos_drm_drv.c
7  */
8 
9 #include <linux/aperture.h>
10 #include <linux/dma-mapping.h>
11 #include <linux/platform_device.h>
12 #include <linux/pm_runtime.h>
13 #include <linux/module.h>
14 #include <linux/of_graph.h>
15 #include <linux/of_platform.h>
16 #include <linux/component.h>
17 #include <linux/console.h>
18 #include <linux/iommu.h>
19 
20 #include <drm/clients/drm_client_setup.h>
21 #include <drm/drm_drv.h>
22 #include <drm/drm_fbdev_dma.h>
23 #include <drm/drm_gem_dma_helper.h>
24 #include <drm/drm_of.h>
25 #include <drm/drm_print.h>
26 #include <drm/drm_probe_helper.h>
27 #include <drm/drm_vblank.h>
28 
29 #if defined(CONFIG_ARM_DMA_USE_IOMMU)
30 #include <asm/dma-iommu.h>
31 #else
32 #define arm_iommu_detach_device(...)	({ })
33 #define arm_iommu_release_mapping(...)	({ })
34 #define to_dma_iommu_mapping(dev) NULL
35 #endif
36 
37 #include "rockchip_drm_drv.h"
38 #include "rockchip_drm_fb.h"
39 #include "rockchip_drm_gem.h"
40 
41 #define DRIVER_NAME	"rockchip"
42 #define DRIVER_DESC	"RockChip Soc DRM"
43 #define DRIVER_MAJOR	1
44 #define DRIVER_MINOR	0
45 
46 static const struct drm_driver rockchip_drm_driver;
47 
48 /*
49  * Attach a (component) device to the shared drm dma mapping from master drm
50  * device.  This is used by the VOPs to map GEM buffers to a common DMA
51  * mapping.
52  */
rockchip_drm_dma_attach_device(struct drm_device * drm_dev,struct device * dev)53 int rockchip_drm_dma_attach_device(struct drm_device *drm_dev,
54 				   struct device *dev)
55 {
56 	struct rockchip_drm_private *private = drm_dev->dev_private;
57 	int ret;
58 
59 	if (!private->domain)
60 		return 0;
61 
62 	if (IS_ENABLED(CONFIG_ARM_DMA_USE_IOMMU)) {
63 		struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev);
64 
65 		if (mapping) {
66 			arm_iommu_detach_device(dev);
67 			arm_iommu_release_mapping(mapping);
68 		}
69 	}
70 
71 	ret = iommu_attach_device(private->domain, dev);
72 	if (ret) {
73 		DRM_DEV_ERROR(dev, "Failed to attach iommu device\n");
74 		return ret;
75 	}
76 
77 	return 0;
78 }
79 
rockchip_drm_dma_detach_device(struct drm_device * drm_dev,struct device * dev)80 void rockchip_drm_dma_detach_device(struct drm_device *drm_dev,
81 				    struct device *dev)
82 {
83 	struct rockchip_drm_private *private = drm_dev->dev_private;
84 
85 	if (!private->domain)
86 		return;
87 
88 	iommu_detach_device(private->domain, dev);
89 }
90 
rockchip_drm_dma_init_device(struct drm_device * drm_dev,struct device * dev)91 void rockchip_drm_dma_init_device(struct drm_device *drm_dev,
92 				  struct device *dev)
93 {
94 	struct rockchip_drm_private *private = drm_dev->dev_private;
95 
96 	if (!device_iommu_mapped(dev))
97 		private->iommu_dev = ERR_PTR(-ENODEV);
98 	else if (!private->iommu_dev)
99 		private->iommu_dev = dev;
100 
101 	if (!IS_ERR(private->iommu_dev))
102 		drm_dev_set_dma_dev(drm_dev, private->iommu_dev);
103 }
104 
rockchip_drm_init_iommu(struct drm_device * drm_dev)105 static int rockchip_drm_init_iommu(struct drm_device *drm_dev)
106 {
107 	struct rockchip_drm_private *private = drm_dev->dev_private;
108 	struct iommu_domain_geometry *geometry;
109 	u64 start, end;
110 	int ret;
111 
112 	if (IS_ERR_OR_NULL(private->iommu_dev))
113 		return 0;
114 
115 	private->domain = iommu_paging_domain_alloc(private->iommu_dev);
116 	if (IS_ERR(private->domain)) {
117 		ret = PTR_ERR(private->domain);
118 		private->domain = NULL;
119 		return ret;
120 	}
121 
122 	geometry = &private->domain->geometry;
123 	start = geometry->aperture_start;
124 	end = geometry->aperture_end;
125 
126 	DRM_DEBUG("IOMMU context initialized (aperture: %#llx-%#llx)\n",
127 		  start, end);
128 	drm_mm_init(&private->mm, start, end - start + 1);
129 	mutex_init(&private->mm_lock);
130 
131 	return 0;
132 }
133 
rockchip_iommu_cleanup(struct drm_device * drm_dev)134 static void rockchip_iommu_cleanup(struct drm_device *drm_dev)
135 {
136 	struct rockchip_drm_private *private = drm_dev->dev_private;
137 
138 	if (!private->domain)
139 		return;
140 
141 	drm_mm_takedown(&private->mm);
142 	iommu_domain_free(private->domain);
143 }
144 
rockchip_drm_bind(struct device * dev)145 static int rockchip_drm_bind(struct device *dev)
146 {
147 	struct drm_device *drm_dev;
148 	struct rockchip_drm_private *private;
149 	int ret;
150 
151 	/* Remove existing drivers that may own the framebuffer memory. */
152 	ret = aperture_remove_all_conflicting_devices(rockchip_drm_driver.name);
153 	if (ret) {
154 		DRM_DEV_ERROR(dev,
155 			      "Failed to remove existing framebuffers - %d.\n",
156 			      ret);
157 		return ret;
158 	}
159 
160 	drm_dev = drm_dev_alloc(&rockchip_drm_driver, dev);
161 	if (IS_ERR(drm_dev))
162 		return PTR_ERR(drm_dev);
163 
164 	dev_set_drvdata(dev, drm_dev);
165 
166 	private = devm_kzalloc(drm_dev->dev, sizeof(*private), GFP_KERNEL);
167 	if (!private) {
168 		ret = -ENOMEM;
169 		goto err_free;
170 	}
171 
172 	drm_dev->dev_private = private;
173 
174 	ret = drmm_mode_config_init(drm_dev);
175 	if (ret)
176 		goto err_free;
177 
178 	rockchip_drm_mode_config_init(drm_dev);
179 
180 	/* Try to bind all sub drivers. */
181 	ret = component_bind_all(dev, drm_dev);
182 	if (ret)
183 		goto err_free;
184 
185 	ret = rockchip_drm_init_iommu(drm_dev);
186 	if (ret)
187 		goto err_unbind_all;
188 
189 	ret = drm_vblank_init(drm_dev, drm_dev->mode_config.num_crtc);
190 	if (ret)
191 		goto err_iommu_cleanup;
192 
193 	drm_mode_config_reset(drm_dev);
194 
195 	/* init kms poll for handling hpd */
196 	drm_kms_helper_poll_init(drm_dev);
197 
198 	ret = drm_dev_register(drm_dev, 0);
199 	if (ret)
200 		goto err_kms_helper_poll_fini;
201 
202 	drm_client_setup(drm_dev, NULL);
203 
204 	return 0;
205 err_kms_helper_poll_fini:
206 	drm_kms_helper_poll_fini(drm_dev);
207 err_iommu_cleanup:
208 	rockchip_iommu_cleanup(drm_dev);
209 err_unbind_all:
210 	component_unbind_all(dev, drm_dev);
211 err_free:
212 	drm_dev_put(drm_dev);
213 	return ret;
214 }
215 
rockchip_drm_unbind(struct device * dev)216 static void rockchip_drm_unbind(struct device *dev)
217 {
218 	struct drm_device *drm_dev = dev_get_drvdata(dev);
219 
220 	drm_dev_unregister(drm_dev);
221 
222 	drm_kms_helper_poll_fini(drm_dev);
223 
224 	drm_atomic_helper_shutdown(drm_dev);
225 	component_unbind_all(dev, drm_dev);
226 	rockchip_iommu_cleanup(drm_dev);
227 
228 	drm_dev_put(drm_dev);
229 }
230 
231 DEFINE_DRM_GEM_FOPS(rockchip_drm_driver_fops);
232 
233 static const struct drm_driver rockchip_drm_driver = {
234 	.driver_features	= DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC,
235 	.dumb_create		= rockchip_gem_dumb_create,
236 	.gem_prime_import_sg_table	= rockchip_gem_prime_import_sg_table,
237 	DRM_FBDEV_DMA_DRIVER_OPS,
238 	.fops			= &rockchip_drm_driver_fops,
239 	.name	= DRIVER_NAME,
240 	.desc	= DRIVER_DESC,
241 	.major	= DRIVER_MAJOR,
242 	.minor	= DRIVER_MINOR,
243 };
244 
245 #ifdef CONFIG_PM_SLEEP
rockchip_drm_sys_suspend(struct device * dev)246 static int rockchip_drm_sys_suspend(struct device *dev)
247 {
248 	struct drm_device *drm = dev_get_drvdata(dev);
249 
250 	return drm_mode_config_helper_suspend(drm);
251 }
252 
rockchip_drm_sys_resume(struct device * dev)253 static int rockchip_drm_sys_resume(struct device *dev)
254 {
255 	struct drm_device *drm = dev_get_drvdata(dev);
256 
257 	return drm_mode_config_helper_resume(drm);
258 }
259 #endif
260 
261 static const struct dev_pm_ops rockchip_drm_pm_ops = {
262 	SET_SYSTEM_SLEEP_PM_OPS(rockchip_drm_sys_suspend,
263 				rockchip_drm_sys_resume)
264 };
265 
266 #define MAX_ROCKCHIP_SUB_DRIVERS 16
267 static struct platform_driver *rockchip_sub_drivers[MAX_ROCKCHIP_SUB_DRIVERS];
268 static int num_rockchip_sub_drivers;
269 
270 /*
271  * Get the endpoint id of the remote endpoint of the given encoder. This
272  * information is used by the VOP2 driver to identify the encoder.
273  *
274  * @rkencoder: The encoder to get the remote endpoint id from
275  * @np: The encoder device node
276  * @port: The number of the port leading to the VOP2
277  * @reg: The endpoint number leading to the VOP2
278  */
rockchip_drm_encoder_set_crtc_endpoint_id(struct rockchip_encoder * rkencoder,struct device_node * np,int port,int reg)279 int rockchip_drm_encoder_set_crtc_endpoint_id(struct rockchip_encoder *rkencoder,
280 					      struct device_node *np, int port, int reg)
281 {
282 	struct of_endpoint ep;
283 	struct device_node *en, *ren;
284 	int ret;
285 
286 	en = of_graph_get_endpoint_by_regs(np, port, reg);
287 	if (!en)
288 		return -ENOENT;
289 
290 	ren = of_graph_get_remote_endpoint(en);
291 	if (!ren)
292 		return -ENOENT;
293 
294 	ret = of_graph_parse_endpoint(ren, &ep);
295 	if (ret)
296 		return ret;
297 
298 	rkencoder->crtc_endpoint_id = ep.id;
299 
300 	return 0;
301 }
302 
303 /*
304  * Check if a vop endpoint is leading to a rockchip subdriver or bridge.
305  * Should be called from the component bind stage of the drivers
306  * to ensure that all subdrivers are probed.
307  *
308  * @ep: endpoint of a rockchip vop
309  *
310  * returns true if subdriver, false if external bridge and -ENODEV
311  * if remote port does not contain a device.
312  */
rockchip_drm_endpoint_is_subdriver(struct device_node * ep)313 int rockchip_drm_endpoint_is_subdriver(struct device_node *ep)
314 {
315 	struct device_node *node = of_graph_get_remote_port_parent(ep);
316 	struct platform_device *pdev;
317 	struct device_driver *drv;
318 	int i;
319 
320 	if (!node)
321 		return -ENODEV;
322 
323 	/* status disabled will prevent creation of platform-devices */
324 	if (!of_device_is_available(node)) {
325 		of_node_put(node);
326 		return -ENODEV;
327 	}
328 
329 	pdev = of_find_device_by_node(node);
330 	of_node_put(node);
331 
332 	/* enabled non-platform-devices can immediately return here */
333 	if (!pdev)
334 		return false;
335 
336 	/*
337 	 * All rockchip subdrivers have probed at this point, so
338 	 * any device not having a driver now is an external bridge.
339 	 */
340 	drv = pdev->dev.driver;
341 	if (!drv) {
342 		platform_device_put(pdev);
343 		return false;
344 	}
345 
346 	for (i = 0; i < num_rockchip_sub_drivers; i++) {
347 		if (rockchip_sub_drivers[i] == to_platform_driver(drv)) {
348 			platform_device_put(pdev);
349 			return true;
350 		}
351 	}
352 
353 	platform_device_put(pdev);
354 	return false;
355 }
356 
rockchip_drm_match_remove(struct device * dev)357 static void rockchip_drm_match_remove(struct device *dev)
358 {
359 	struct device_link *link;
360 
361 	list_for_each_entry(link, &dev->links.consumers, s_node)
362 		device_link_del(link);
363 }
364 
365 /* list of preferred vop devices */
366 static const char *const rockchip_drm_match_preferred[] = {
367 	"rockchip,rk3399-vop-big",
368 	NULL,
369 };
370 
rockchip_drm_match_add(struct device * dev)371 static struct component_match *rockchip_drm_match_add(struct device *dev)
372 {
373 	struct component_match *match = NULL;
374 	struct device_node *port;
375 	int i;
376 
377 	/* add preferred vop device match before adding driver device matches */
378 	for (i = 0; ; i++) {
379 		port = of_parse_phandle(dev->of_node, "ports", i);
380 		if (!port)
381 			break;
382 
383 		if (of_device_is_available(port->parent) &&
384 		    of_device_compatible_match(port->parent,
385 					       rockchip_drm_match_preferred))
386 			drm_of_component_match_add(dev, &match,
387 						   component_compare_of,
388 						   port->parent);
389 
390 		of_node_put(port);
391 	}
392 
393 	for (i = 0; i < num_rockchip_sub_drivers; i++) {
394 		struct platform_driver *drv = rockchip_sub_drivers[i];
395 		struct device *p = NULL, *d;
396 
397 		do {
398 			d = platform_find_device_by_driver(p, &drv->driver);
399 			put_device(p);
400 			p = d;
401 
402 			if (!d)
403 				break;
404 
405 			device_link_add(dev, d, DL_FLAG_STATELESS);
406 			component_match_add(dev, &match, component_compare_dev, d);
407 		} while (true);
408 	}
409 
410 	if (IS_ERR(match))
411 		rockchip_drm_match_remove(dev);
412 
413 	return match ?: ERR_PTR(-ENODEV);
414 }
415 
416 static const struct component_master_ops rockchip_drm_ops = {
417 	.bind = rockchip_drm_bind,
418 	.unbind = rockchip_drm_unbind,
419 };
420 
rockchip_drm_platform_of_probe(struct device * dev)421 static int rockchip_drm_platform_of_probe(struct device *dev)
422 {
423 	struct device_node *np = dev->of_node;
424 	struct device_node *port;
425 	bool found = false;
426 	int i;
427 
428 	if (!np)
429 		return -ENODEV;
430 
431 	for (i = 0;; i++) {
432 		port = of_parse_phandle(np, "ports", i);
433 		if (!port)
434 			break;
435 
436 		if (!of_device_is_available(port->parent)) {
437 			of_node_put(port);
438 			continue;
439 		}
440 
441 		found = true;
442 		of_node_put(port);
443 	}
444 
445 	if (i == 0) {
446 		DRM_DEV_ERROR(dev, "missing 'ports' property\n");
447 		return -ENODEV;
448 	}
449 
450 	if (!found) {
451 		DRM_DEV_ERROR(dev,
452 			      "No available vop found for display-subsystem.\n");
453 		return -ENODEV;
454 	}
455 
456 	return 0;
457 }
458 
rockchip_drm_platform_probe(struct platform_device * pdev)459 static int rockchip_drm_platform_probe(struct platform_device *pdev)
460 {
461 	struct device *dev = &pdev->dev;
462 	struct component_match *match = NULL;
463 	int ret;
464 
465 	ret = rockchip_drm_platform_of_probe(dev);
466 	if (ret)
467 		return ret;
468 
469 	match = rockchip_drm_match_add(dev);
470 	if (IS_ERR(match))
471 		return PTR_ERR(match);
472 
473 	ret = component_master_add_with_match(dev, &rockchip_drm_ops, match);
474 	if (ret < 0) {
475 		rockchip_drm_match_remove(dev);
476 		return ret;
477 	}
478 
479 	return 0;
480 }
481 
rockchip_drm_platform_remove(struct platform_device * pdev)482 static void rockchip_drm_platform_remove(struct platform_device *pdev)
483 {
484 	component_master_del(&pdev->dev, &rockchip_drm_ops);
485 
486 	rockchip_drm_match_remove(&pdev->dev);
487 }
488 
rockchip_drm_platform_shutdown(struct platform_device * pdev)489 static void rockchip_drm_platform_shutdown(struct platform_device *pdev)
490 {
491 	if (component_master_is_bound(&pdev->dev, &rockchip_drm_ops)) {
492 		struct drm_device *drm = platform_get_drvdata(pdev);
493 
494 		drm_atomic_helper_shutdown(drm);
495 	}
496 }
497 
498 static const struct of_device_id rockchip_drm_dt_ids[] = {
499 	{ .compatible = "rockchip,display-subsystem", },
500 	{ /* sentinel */ },
501 };
502 MODULE_DEVICE_TABLE(of, rockchip_drm_dt_ids);
503 
504 static struct platform_driver rockchip_drm_platform_driver = {
505 	.probe = rockchip_drm_platform_probe,
506 	.remove = rockchip_drm_platform_remove,
507 	.shutdown = rockchip_drm_platform_shutdown,
508 	.driver = {
509 		.name = "rockchip-drm",
510 		.of_match_table = rockchip_drm_dt_ids,
511 		.pm = &rockchip_drm_pm_ops,
512 	},
513 };
514 
515 #define ADD_ROCKCHIP_SUB_DRIVER(drv, cond) { \
516 	if (IS_ENABLED(cond) && \
517 	    !WARN_ON(num_rockchip_sub_drivers >= MAX_ROCKCHIP_SUB_DRIVERS)) \
518 		rockchip_sub_drivers[num_rockchip_sub_drivers++] = &drv; \
519 }
520 
rockchip_drm_init(void)521 static int __init rockchip_drm_init(void)
522 {
523 	int ret;
524 
525 	if (drm_firmware_drivers_only())
526 		return -ENODEV;
527 
528 	num_rockchip_sub_drivers = 0;
529 	ADD_ROCKCHIP_SUB_DRIVER(vop_platform_driver, CONFIG_ROCKCHIP_VOP);
530 	ADD_ROCKCHIP_SUB_DRIVER(vop2_platform_driver, CONFIG_ROCKCHIP_VOP2);
531 	ADD_ROCKCHIP_SUB_DRIVER(rockchip_lvds_driver,
532 				CONFIG_ROCKCHIP_LVDS);
533 	ADD_ROCKCHIP_SUB_DRIVER(rockchip_dp_driver,
534 				CONFIG_ROCKCHIP_ANALOGIX_DP);
535 	ADD_ROCKCHIP_SUB_DRIVER(cdn_dp_driver, CONFIG_ROCKCHIP_CDN_DP);
536 	ADD_ROCKCHIP_SUB_DRIVER(dw_dp_driver, CONFIG_ROCKCHIP_DW_DP);
537 	ADD_ROCKCHIP_SUB_DRIVER(dw_hdmi_rockchip_pltfm_driver,
538 				CONFIG_ROCKCHIP_DW_HDMI);
539 	ADD_ROCKCHIP_SUB_DRIVER(dw_hdmi_qp_rockchip_pltfm_driver,
540 				CONFIG_ROCKCHIP_DW_HDMI_QP);
541 	ADD_ROCKCHIP_SUB_DRIVER(dw_mipi_dsi_rockchip_driver,
542 				CONFIG_ROCKCHIP_DW_MIPI_DSI);
543 	ADD_ROCKCHIP_SUB_DRIVER(dw_mipi_dsi2_rockchip_driver,
544 				CONFIG_ROCKCHIP_DW_MIPI_DSI2);
545 	ADD_ROCKCHIP_SUB_DRIVER(inno_hdmi_driver, CONFIG_ROCKCHIP_INNO_HDMI);
546 	ADD_ROCKCHIP_SUB_DRIVER(rk3066_hdmi_driver,
547 				CONFIG_ROCKCHIP_RK3066_HDMI);
548 
549 	ret = platform_register_drivers(rockchip_sub_drivers,
550 					num_rockchip_sub_drivers);
551 	if (ret)
552 		return ret;
553 
554 	ret = platform_driver_register(&rockchip_drm_platform_driver);
555 	if (ret)
556 		goto err_unreg_drivers;
557 
558 	return 0;
559 
560 err_unreg_drivers:
561 	platform_unregister_drivers(rockchip_sub_drivers,
562 				    num_rockchip_sub_drivers);
563 	return ret;
564 }
565 
rockchip_drm_fini(void)566 static void __exit rockchip_drm_fini(void)
567 {
568 	platform_driver_unregister(&rockchip_drm_platform_driver);
569 
570 	platform_unregister_drivers(rockchip_sub_drivers,
571 				    num_rockchip_sub_drivers);
572 }
573 
574 module_init(rockchip_drm_init);
575 module_exit(rockchip_drm_fini);
576 
577 MODULE_AUTHOR("Mark Yao <mark.yao@rock-chips.com>");
578 MODULE_DESCRIPTION("ROCKCHIP DRM Driver");
579 MODULE_LICENSE("GPL v2");
580