.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * Copyright (C) 2012 Russell King |
---|
3 | | - * |
---|
4 | | - * This program is free software; you can redistribute it and/or modify |
---|
5 | | - * it under the terms of the GNU General Public License version 2 as |
---|
6 | | - * published by the Free Software Foundation. |
---|
7 | 4 | */ |
---|
| 5 | + |
---|
8 | 6 | #include <linux/clk.h> |
---|
9 | 7 | #include <linux/component.h> |
---|
10 | 8 | #include <linux/module.h> |
---|
11 | 9 | #include <linux/of_graph.h> |
---|
| 10 | +#include <linux/platform_device.h> |
---|
| 11 | + |
---|
12 | 12 | #include <drm/drm_atomic_helper.h> |
---|
13 | | -#include <drm/drm_crtc_helper.h> |
---|
| 13 | +#include <drm/drm_drv.h> |
---|
| 14 | +#include <drm/drm_ioctl.h> |
---|
| 15 | +#include <drm/drm_managed.h> |
---|
| 16 | +#include <drm/drm_prime.h> |
---|
| 17 | +#include <drm/drm_probe_helper.h> |
---|
14 | 18 | #include <drm/drm_fb_helper.h> |
---|
15 | 19 | #include <drm/drm_of.h> |
---|
| 20 | +#include <drm/drm_vblank.h> |
---|
| 21 | + |
---|
16 | 22 | #include "armada_crtc.h" |
---|
17 | 23 | #include "armada_drm.h" |
---|
18 | 24 | #include "armada_gem.h" |
---|
.. | .. |
---|
43 | 49 | .name = "armada-drm", |
---|
44 | 50 | .desc = "Armada SoC DRM", |
---|
45 | 51 | .date = "20120730", |
---|
46 | | - .driver_features = DRIVER_GEM | DRIVER_MODESET | |
---|
47 | | - DRIVER_PRIME | DRIVER_ATOMIC, |
---|
| 52 | + .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, |
---|
48 | 53 | .ioctls = armada_ioctls, |
---|
49 | 54 | .fops = &armada_drm_fops, |
---|
50 | 55 | }; |
---|
.. | .. |
---|
82 | 87 | "armada-drm")) |
---|
83 | 88 | return -EBUSY; |
---|
84 | 89 | |
---|
85 | | - priv = kzalloc(sizeof(*priv), GFP_KERNEL); |
---|
86 | | - if (!priv) |
---|
87 | | - return -ENOMEM; |
---|
| 90 | + priv = devm_drm_dev_alloc(dev, &armada_drm_driver, |
---|
| 91 | + struct armada_private, drm); |
---|
| 92 | + if (IS_ERR(priv)) { |
---|
| 93 | + dev_err(dev, "[" DRM_NAME ":%s] devm_drm_dev_alloc failed: %li\n", |
---|
| 94 | + __func__, PTR_ERR(priv)); |
---|
| 95 | + return PTR_ERR(priv); |
---|
| 96 | + } |
---|
88 | 97 | |
---|
89 | | - /* |
---|
90 | | - * The drm_device structure must be at the start of |
---|
91 | | - * armada_private for drm_dev_put() to work correctly. |
---|
92 | | - */ |
---|
93 | | - BUILD_BUG_ON(offsetof(struct armada_private, drm) != 0); |
---|
94 | | - |
---|
95 | | - ret = drm_dev_init(&priv->drm, &armada_drm_driver, dev); |
---|
| 98 | + /* Remove early framebuffers */ |
---|
| 99 | + ret = drm_fb_helper_remove_conflicting_framebuffers(NULL, |
---|
| 100 | + "armada-drm-fb", |
---|
| 101 | + false); |
---|
96 | 102 | if (ret) { |
---|
97 | | - dev_err(dev, "[" DRM_NAME ":%s] drm_dev_init failed: %d\n", |
---|
| 103 | + dev_err(dev, "[" DRM_NAME ":%s] can't kick out simple-fb: %d\n", |
---|
98 | 104 | __func__, ret); |
---|
99 | 105 | kfree(priv); |
---|
100 | 106 | return ret; |
---|
101 | 107 | } |
---|
102 | | - |
---|
103 | | - priv->drm.dev_private = priv; |
---|
104 | 108 | |
---|
105 | 109 | dev_set_drvdata(dev, &priv->drm); |
---|
106 | 110 | |
---|
.. | .. |
---|
157 | 161 | err_kms: |
---|
158 | 162 | drm_mode_config_cleanup(&priv->drm); |
---|
159 | 163 | drm_mm_takedown(&priv->linear); |
---|
160 | | - drm_dev_put(&priv->drm); |
---|
161 | 164 | return ret; |
---|
162 | 165 | } |
---|
163 | 166 | |
---|
164 | 167 | static void armada_drm_unbind(struct device *dev) |
---|
165 | 168 | { |
---|
166 | 169 | struct drm_device *drm = dev_get_drvdata(dev); |
---|
167 | | - struct armada_private *priv = drm->dev_private; |
---|
| 170 | + struct armada_private *priv = drm_to_armada_dev(drm); |
---|
168 | 171 | |
---|
169 | 172 | drm_kms_helper_poll_fini(&priv->drm); |
---|
170 | 173 | armada_fbdev_fini(&priv->drm); |
---|
171 | 174 | |
---|
172 | 175 | drm_dev_unregister(&priv->drm); |
---|
173 | 176 | |
---|
| 177 | + drm_atomic_helper_shutdown(&priv->drm); |
---|
| 178 | + |
---|
174 | 179 | component_unbind_all(dev, &priv->drm); |
---|
175 | 180 | |
---|
176 | 181 | drm_mode_config_cleanup(&priv->drm); |
---|
177 | 182 | drm_mm_takedown(&priv->linear); |
---|
178 | | - |
---|
179 | | - drm_dev_put(&priv->drm); |
---|
180 | 183 | } |
---|
181 | 184 | |
---|
182 | 185 | static int compare_of(struct device *dev, void *data) |
---|
.. | .. |
---|
191 | 194 | } |
---|
192 | 195 | |
---|
193 | 196 | static void armada_add_endpoints(struct device *dev, |
---|
194 | | - struct component_match **match, struct device_node *port) |
---|
| 197 | + struct component_match **match, struct device_node *dev_node) |
---|
195 | 198 | { |
---|
196 | 199 | struct device_node *ep, *remote; |
---|
197 | 200 | |
---|
198 | | - for_each_child_of_node(port, ep) { |
---|
| 201 | + for_each_endpoint_of_node(dev_node, ep) { |
---|
199 | 202 | remote = of_graph_get_remote_port_parent(ep); |
---|
200 | | - if (!remote || !of_device_is_available(remote)) { |
---|
201 | | - of_node_put(remote); |
---|
202 | | - continue; |
---|
203 | | - } else if (!of_device_is_available(remote->parent)) { |
---|
204 | | - dev_warn(dev, "parent device of %pOF is not available\n", |
---|
205 | | - remote); |
---|
206 | | - of_node_put(remote); |
---|
207 | | - continue; |
---|
208 | | - } |
---|
209 | | - |
---|
210 | | - drm_of_component_match_add(dev, match, compare_of, remote); |
---|
| 203 | + if (remote && of_device_is_available(remote)) |
---|
| 204 | + drm_of_component_match_add(dev, match, compare_of, |
---|
| 205 | + remote); |
---|
211 | 206 | of_node_put(remote); |
---|
212 | 207 | } |
---|
213 | 208 | } |
---|
.. | .. |
---|
229 | 224 | |
---|
230 | 225 | if (dev->platform_data) { |
---|
231 | 226 | char **devices = dev->platform_data; |
---|
232 | | - struct device_node *port; |
---|
233 | 227 | struct device *d; |
---|
234 | 228 | int i; |
---|
235 | 229 | |
---|
.. | .. |
---|
245 | 239 | for (i = 0; devices[i]; i++) { |
---|
246 | 240 | d = bus_find_device_by_name(&platform_bus_type, NULL, |
---|
247 | 241 | devices[i]); |
---|
248 | | - if (d && d->of_node) { |
---|
249 | | - for_each_child_of_node(d->of_node, port) |
---|
250 | | - armada_add_endpoints(dev, &match, port); |
---|
251 | | - } |
---|
| 242 | + if (d && d->of_node) |
---|
| 243 | + armada_add_endpoints(dev, &match, d->of_node); |
---|
252 | 244 | put_device(d); |
---|
253 | 245 | } |
---|
254 | 246 | } |
---|
.. | .. |
---|
305 | 297 | } |
---|
306 | 298 | module_exit(armada_drm_exit); |
---|
307 | 299 | |
---|
308 | | -MODULE_AUTHOR("Russell King <rmk+kernel@arm.linux.org.uk>"); |
---|
| 300 | +MODULE_AUTHOR("Russell King <rmk+kernel@armlinux.org.uk>"); |
---|
309 | 301 | MODULE_DESCRIPTION("Armada DRM Driver"); |
---|
310 | 302 | MODULE_LICENSE("GPL"); |
---|
311 | 303 | MODULE_ALIAS("platform:armada-drm"); |
---|