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