aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2016-10-11 16:07:38 -0400
committerDave Airlie <airlied@redhat.com>2016-10-11 16:07:38 -0400
commit69405d3da98b48633b78a49403e4f9cdb7c6a0f5 (patch)
treed2826882487ef3add220661cacad6885a3a3d7c3
parent28da9ed6574d43e78b89d9a6990cf65047b9deae (diff)
parenta5bd451b6e6ece69be07a425381c4f3438eadba0 (diff)
Merge tag 'topic/drm-misc-2016-10-11' of git://anongit.freedesktop.org/drm-intel into drm-next
Just flushing out my -misc queue. Slightly important are the prime refcount/unload fixes from Chris. There's also the reservation stuff from Chris still pending, and Sumits hasn't landed that yet. Might get another pull for that, but pls don't hold up the main pull for it ;-) * tag 'topic/drm-misc-2016-10-11' of git://anongit.freedesktop.org/drm-intel: drm/crtc: constify drm_crtc_index parameter drm: use the right function name in documentation drm: Release resources with a safer function drm: Fix up kerneldoc for new drm_gem_dmabuf_export() drm/bridge: Drop drm_connector_unregister and call drm_connector_cleanup directly drm/fb-helper: fix sphinx markup for DRM_FB_HELPER_DEFAULT_OPS drm/bridge: Add RGB to VGA bridge support drm/prime: Take a ref on the drm_dev when exporting a dma_buf drm/prime: Pass the right module owner through to dma_buf_export() drm/bridge: Call drm_connector_cleanup directly drm: simple_kms_helper: Add prepare_fb and cleanup_fb hooks drm: Release resources with a safer function
-rw-r--r--Documentation/devicetree/bindings/display/bridge/dumb-vga-dac.txt48
-rw-r--r--drivers/gpu/drm/armada/armada_gem.c2
-rw-r--r--drivers/gpu/drm/bridge/Kconfig7
-rw-r--r--drivers/gpu/drm/bridge/Makefile1
-rw-r--r--drivers/gpu/drm/bridge/analogix-anx78xx.c7
-rw-r--r--drivers/gpu/drm/bridge/analogix/analogix_dp_core.c9
-rw-r--r--drivers/gpu/drm/bridge/dumb-vga-dac.c223
-rw-r--r--drivers/gpu/drm/bridge/dw-hdmi.c8
-rw-r--r--drivers/gpu/drm/bridge/nxp-ptn3460.c7
-rw-r--r--drivers/gpu/drm/bridge/parade-ps8622.c7
-rw-r--r--drivers/gpu/drm/bridge/tc358767.c8
-rw-r--r--drivers/gpu/drm/drm_connector.c12
-rw-r--r--drivers/gpu/drm/drm_prime.c48
-rw-r--r--drivers/gpu/drm/drm_simple_kms_helper.c26
-rw-r--r--drivers/gpu/drm/i915/i915_gem_dmabuf.c2
-rw-r--r--drivers/gpu/drm/tegra/gem.c2
-rw-r--r--drivers/gpu/drm/udl/udl_dmabuf.c2
-rw-r--r--include/drm/drmP.h7
-rw-r--r--include/drm/drm_connector.h4
-rw-r--r--include/drm/drm_crtc.h2
-rw-r--r--include/drm/drm_fb_helper.h2
-rw-r--r--include/drm/drm_simple_kms_helper.h20
22 files changed, 391 insertions, 63 deletions
diff --git a/Documentation/devicetree/bindings/display/bridge/dumb-vga-dac.txt b/Documentation/devicetree/bindings/display/bridge/dumb-vga-dac.txt
new file mode 100644
index 000000000000..003bc246a270
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/bridge/dumb-vga-dac.txt
@@ -0,0 +1,48 @@
1Dumb RGB to VGA DAC bridge
2---------------------------
3
4This binding is aimed for dumb RGB to VGA DAC based bridges that do not require
5any configuration.
6
7Required properties:
8
9- compatible: Must be "dumb-vga-dac"
10
11Required nodes:
12
13This device has two video ports. Their connections are modelled using the OF
14graph bindings specified in Documentation/devicetree/bindings/graph.txt.
15
16- Video port 0 for RGB input
17- Video port 1 for VGA output
18
19
20Example
21-------
22
23bridge {
24 compatible = "dumb-vga-dac";
25 #address-cells = <1>;
26 #size-cells = <0>;
27
28 ports {
29 #address-cells = <1>;
30 #size-cells = <0>;
31
32 port@0 {
33 reg = <0>;
34
35 vga_bridge_in: endpoint {
36 remote-endpoint = <&tcon0_out_vga>;
37 };
38 };
39
40 port@1 {
41 reg = <1>;
42
43 vga_bridge_out: endpoint {
44 remote-endpoint = <&vga_con_in>;
45 };
46 };
47 };
48};
diff --git a/drivers/gpu/drm/armada/armada_gem.c b/drivers/gpu/drm/armada/armada_gem.c
index cb8f0347b934..a5e428d27d2f 100644
--- a/drivers/gpu/drm/armada/armada_gem.c
+++ b/drivers/gpu/drm/armada/armada_gem.c
@@ -547,7 +547,7 @@ armada_gem_prime_export(struct drm_device *dev, struct drm_gem_object *obj,
547 exp_info.flags = O_RDWR; 547 exp_info.flags = O_RDWR;
548 exp_info.priv = obj; 548 exp_info.priv = obj;
549 549
550 return dma_buf_export(&exp_info); 550 return drm_gem_dmabuf_export(dev, &exp_info);
551} 551}
552 552
553struct drm_gem_object * 553struct drm_gem_object *
diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
index b590e678052d..10e12e74fc9f 100644
--- a/drivers/gpu/drm/bridge/Kconfig
+++ b/drivers/gpu/drm/bridge/Kconfig
@@ -17,6 +17,13 @@ config DRM_ANALOGIX_ANX78XX
17 the HDMI output of an application processor to MyDP 17 the HDMI output of an application processor to MyDP
18 or DisplayPort. 18 or DisplayPort.
19 19
20config DRM_DUMB_VGA_DAC
21 tristate "Dumb VGA DAC Bridge support"
22 depends on OF
23 select DRM_KMS_HELPER
24 help
25 Support for RGB to VGA DAC based bridges
26
20config DRM_DW_HDMI 27config DRM_DW_HDMI
21 tristate 28 tristate
22 select DRM_KMS_HELPER 29 select DRM_KMS_HELPER
diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile
index efdb07e878f5..cdf3a3cf765d 100644
--- a/drivers/gpu/drm/bridge/Makefile
+++ b/drivers/gpu/drm/bridge/Makefile
@@ -1,6 +1,7 @@
1ccflags-y := -Iinclude/drm 1ccflags-y := -Iinclude/drm
2 2
3obj-$(CONFIG_DRM_ANALOGIX_ANX78XX) += analogix-anx78xx.o 3obj-$(CONFIG_DRM_ANALOGIX_ANX78XX) += analogix-anx78xx.o
4obj-$(CONFIG_DRM_DUMB_VGA_DAC) += dumb-vga-dac.o
4obj-$(CONFIG_DRM_DW_HDMI) += dw-hdmi.o 5obj-$(CONFIG_DRM_DW_HDMI) += dw-hdmi.o
5obj-$(CONFIG_DRM_DW_HDMI_AHB_AUDIO) += dw-hdmi-ahb-audio.o 6obj-$(CONFIG_DRM_DW_HDMI_AHB_AUDIO) += dw-hdmi-ahb-audio.o
6obj-$(CONFIG_DRM_NXP_PTN3460) += nxp-ptn3460.o 7obj-$(CONFIG_DRM_NXP_PTN3460) += nxp-ptn3460.o
diff --git a/drivers/gpu/drm/bridge/analogix-anx78xx.c b/drivers/gpu/drm/bridge/analogix-anx78xx.c
index f9f03bcba0af..a2a82366a771 100644
--- a/drivers/gpu/drm/bridge/analogix-anx78xx.c
+++ b/drivers/gpu/drm/bridge/analogix-anx78xx.c
@@ -1001,16 +1001,11 @@ static enum drm_connector_status anx78xx_detect(struct drm_connector *connector,
1001 return connector_status_connected; 1001 return connector_status_connected;
1002} 1002}
1003 1003
1004static void anx78xx_connector_destroy(struct drm_connector *connector)
1005{
1006 drm_connector_cleanup(connector);
1007}
1008
1009static const struct drm_connector_funcs anx78xx_connector_funcs = { 1004static const struct drm_connector_funcs anx78xx_connector_funcs = {
1010 .dpms = drm_atomic_helper_connector_dpms, 1005 .dpms = drm_atomic_helper_connector_dpms,
1011 .fill_modes = drm_helper_probe_single_connector_modes, 1006 .fill_modes = drm_helper_probe_single_connector_modes,
1012 .detect = anx78xx_detect, 1007 .detect = anx78xx_detect,
1013 .destroy = anx78xx_connector_destroy, 1008 .destroy = drm_connector_cleanup,
1014 .reset = drm_atomic_helper_connector_reset, 1009 .reset = drm_atomic_helper_connector_reset,
1015 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, 1010 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
1016 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, 1011 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
index 001b075e171b..6e0447f329a2 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
@@ -999,18 +999,11 @@ analogix_dp_detect(struct drm_connector *connector, bool force)
999 return status; 999 return status;
1000} 1000}
1001 1001
1002static void analogix_dp_connector_destroy(struct drm_connector *connector)
1003{
1004 drm_connector_unregister(connector);
1005 drm_connector_cleanup(connector);
1006
1007}
1008
1009static const struct drm_connector_funcs analogix_dp_connector_funcs = { 1002static const struct drm_connector_funcs analogix_dp_connector_funcs = {
1010 .dpms = drm_atomic_helper_connector_dpms, 1003 .dpms = drm_atomic_helper_connector_dpms,
1011 .fill_modes = drm_helper_probe_single_connector_modes, 1004 .fill_modes = drm_helper_probe_single_connector_modes,
1012 .detect = analogix_dp_detect, 1005 .detect = analogix_dp_detect,
1013 .destroy = analogix_dp_connector_destroy, 1006 .destroy = drm_connector_cleanup,
1014 .reset = drm_atomic_helper_connector_reset, 1007 .reset = drm_atomic_helper_connector_reset,
1015 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, 1008 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
1016 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, 1009 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
diff --git a/drivers/gpu/drm/bridge/dumb-vga-dac.c b/drivers/gpu/drm/bridge/dumb-vga-dac.c
new file mode 100644
index 000000000000..afec232185a7
--- /dev/null
+++ b/drivers/gpu/drm/bridge/dumb-vga-dac.c
@@ -0,0 +1,223 @@
1/*
2 * Copyright (C) 2015-2016 Free Electrons
3 * Copyright (C) 2015-2016 NextThing Co
4 *
5 * Maxime Ripard <maxime.ripard@free-electrons.com>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 of
10 * the License, or (at your option) any later version.
11 */
12
13#include <linux/module.h>
14#include <linux/of_graph.h>
15
16#include <drm/drmP.h>
17#include <drm/drm_atomic_helper.h>
18#include <drm/drm_crtc.h>
19#include <drm/drm_crtc_helper.h>
20
21struct dumb_vga {
22 struct drm_bridge bridge;
23 struct drm_connector connector;
24
25 struct i2c_adapter *ddc;
26};
27
28static inline struct dumb_vga *
29drm_bridge_to_dumb_vga(struct drm_bridge *bridge)
30{
31 return container_of(bridge, struct dumb_vga, bridge);
32}
33
34static inline struct dumb_vga *
35drm_connector_to_dumb_vga(struct drm_connector *connector)
36{
37 return container_of(connector, struct dumb_vga, connector);
38}
39
40static int dumb_vga_get_modes(struct drm_connector *connector)
41{
42 struct dumb_vga *vga = drm_connector_to_dumb_vga(connector);
43 struct edid *edid;
44 int ret;
45
46 if (IS_ERR(vga->ddc))
47 goto fallback;
48
49 edid = drm_get_edid(connector, vga->ddc);
50 if (!edid) {
51 DRM_INFO("EDID readout failed, falling back to standard modes\n");
52 goto fallback;
53 }
54
55 drm_mode_connector_update_edid_property(connector, edid);
56 return drm_add_edid_modes(connector, edid);
57
58fallback:
59 /*
60 * In case we cannot retrieve the EDIDs (broken or missing i2c
61 * bus), fallback on the XGA standards
62 */
63 ret = drm_add_modes_noedid(connector, 1920, 1200);
64
65 /* And prefer a mode pretty much anyone can handle */
66 drm_set_preferred_mode(connector, 1024, 768);
67
68 return ret;
69}
70
71static const struct drm_connector_helper_funcs dumb_vga_con_helper_funcs = {
72 .get_modes = dumb_vga_get_modes,
73};
74
75static enum drm_connector_status
76dumb_vga_connector_detect(struct drm_connector *connector, bool force)
77{
78 struct dumb_vga *vga = drm_connector_to_dumb_vga(connector);
79
80 /*
81 * Even if we have an I2C bus, we can't assume that the cable
82 * is disconnected if drm_probe_ddc fails. Some cables don't
83 * wire the DDC pins, or the I2C bus might not be working at
84 * all.
85 */
86 if (!IS_ERR(vga->ddc) && drm_probe_ddc(vga->ddc))
87 return connector_status_connected;
88
89 return connector_status_unknown;
90}
91
92static const struct drm_connector_funcs dumb_vga_con_funcs = {
93 .dpms = drm_atomic_helper_connector_dpms,
94 .detect = dumb_vga_connector_detect,
95 .fill_modes = drm_helper_probe_single_connector_modes,
96 .destroy = drm_connector_cleanup,
97 .reset = drm_atomic_helper_connector_reset,
98 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
99 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
100};
101
102static int dumb_vga_attach(struct drm_bridge *bridge)
103{
104 struct dumb_vga *vga = drm_bridge_to_dumb_vga(bridge);
105 int ret;
106
107 if (!bridge->encoder) {
108 DRM_ERROR("Missing encoder\n");
109 return -ENODEV;
110 }
111
112 drm_connector_helper_add(&vga->connector,
113 &dumb_vga_con_helper_funcs);
114 ret = drm_connector_init(bridge->dev, &vga->connector,
115 &dumb_vga_con_funcs, DRM_MODE_CONNECTOR_VGA);
116 if (ret) {
117 DRM_ERROR("Failed to initialize connector\n");
118 return ret;
119 }
120
121 drm_mode_connector_attach_encoder(&vga->connector,
122 bridge->encoder);
123
124 return 0;
125}
126
127static const struct drm_bridge_funcs dumb_vga_bridge_funcs = {
128 .attach = dumb_vga_attach,
129};
130
131static struct i2c_adapter *dumb_vga_retrieve_ddc(struct device *dev)
132{
133 struct device_node *end_node, *phandle, *remote;
134 struct i2c_adapter *ddc;
135
136 end_node = of_graph_get_endpoint_by_regs(dev->of_node, 1, -1);
137 if (!end_node) {
138 dev_err(dev, "Missing connector endpoint\n");
139 return ERR_PTR(-ENODEV);
140 }
141
142 remote = of_graph_get_remote_port_parent(end_node);
143 of_node_put(end_node);
144 if (!remote) {
145 dev_err(dev, "Enable to parse remote node\n");
146 return ERR_PTR(-EINVAL);
147 }
148
149 phandle = of_parse_phandle(remote, "ddc-i2c-bus", 0);
150 of_node_put(remote);
151 if (!phandle)
152 return ERR_PTR(-ENODEV);
153
154 ddc = of_get_i2c_adapter_by_node(phandle);
155 of_node_put(phandle);
156 if (!ddc)
157 return ERR_PTR(-EPROBE_DEFER);
158
159 return ddc;
160}
161
162static int dumb_vga_probe(struct platform_device *pdev)
163{
164 struct dumb_vga *vga;
165 int ret;
166
167 vga = devm_kzalloc(&pdev->dev, sizeof(*vga), GFP_KERNEL);
168 if (!vga)
169 return -ENOMEM;
170 platform_set_drvdata(pdev, vga);
171
172 vga->ddc = dumb_vga_retrieve_ddc(&pdev->dev);
173 if (IS_ERR(vga->ddc)) {
174 if (PTR_ERR(vga->ddc) == -ENODEV) {
175 dev_dbg(&pdev->dev,
176 "No i2c bus specified. Disabling EDID readout\n");
177 } else {
178 dev_err(&pdev->dev, "Couldn't retrieve i2c bus\n");
179 return PTR_ERR(vga->ddc);
180 }
181 }
182
183 vga->bridge.funcs = &dumb_vga_bridge_funcs;
184 vga->bridge.of_node = pdev->dev.of_node;
185
186 ret = drm_bridge_add(&vga->bridge);
187 if (ret && !IS_ERR(vga->ddc))
188 i2c_put_adapter(vga->ddc);
189
190 return ret;
191}
192
193static int dumb_vga_remove(struct platform_device *pdev)
194{
195 struct dumb_vga *vga = platform_get_drvdata(pdev);
196
197 drm_bridge_remove(&vga->bridge);
198
199 if (!IS_ERR(vga->ddc))
200 i2c_put_adapter(vga->ddc);
201
202 return 0;
203}
204
205static const struct of_device_id dumb_vga_match[] = {
206 { .compatible = "dumb-vga-dac" },
207 {},
208};
209MODULE_DEVICE_TABLE(of, dumb_vga_match);
210
211static struct platform_driver dumb_vga_driver = {
212 .probe = dumb_vga_probe,
213 .remove = dumb_vga_remove,
214 .driver = {
215 .name = "dumb-vga-dac",
216 .of_match_table = dumb_vga_match,
217 },
218};
219module_platform_driver(dumb_vga_driver);
220
221MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
222MODULE_DESCRIPTION("Dumb VGA DAC bridge driver");
223MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
index 66ad8e6fb11e..ab7023e5dfde 100644
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
@@ -1477,12 +1477,6 @@ dw_hdmi_connector_mode_valid(struct drm_connector *connector,
1477 return mode_status; 1477 return mode_status;
1478} 1478}
1479 1479
1480static void dw_hdmi_connector_destroy(struct drm_connector *connector)
1481{
1482 drm_connector_unregister(connector);
1483 drm_connector_cleanup(connector);
1484}
1485
1486static void dw_hdmi_connector_force(struct drm_connector *connector) 1480static void dw_hdmi_connector_force(struct drm_connector *connector)
1487{ 1481{
1488 struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi, 1482 struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi,
@@ -1499,7 +1493,7 @@ static const struct drm_connector_funcs dw_hdmi_connector_funcs = {
1499 .dpms = drm_atomic_helper_connector_dpms, 1493 .dpms = drm_atomic_helper_connector_dpms,
1500 .fill_modes = drm_helper_probe_single_connector_modes, 1494 .fill_modes = drm_helper_probe_single_connector_modes,
1501 .detect = dw_hdmi_connector_detect, 1495 .detect = dw_hdmi_connector_detect,
1502 .destroy = dw_hdmi_connector_destroy, 1496 .destroy = drm_connector_cleanup,
1503 .force = dw_hdmi_connector_force, 1497 .force = dw_hdmi_connector_force,
1504 .reset = drm_atomic_helper_connector_reset, 1498 .reset = drm_atomic_helper_connector_reset,
1505 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, 1499 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
diff --git a/drivers/gpu/drm/bridge/nxp-ptn3460.c b/drivers/gpu/drm/bridge/nxp-ptn3460.c
index 93f3dacf9e27..f1a99938e924 100644
--- a/drivers/gpu/drm/bridge/nxp-ptn3460.c
+++ b/drivers/gpu/drm/bridge/nxp-ptn3460.c
@@ -245,16 +245,11 @@ static enum drm_connector_status ptn3460_detect(struct drm_connector *connector,
245 return connector_status_connected; 245 return connector_status_connected;
246} 246}
247 247
248static void ptn3460_connector_destroy(struct drm_connector *connector)
249{
250 drm_connector_cleanup(connector);
251}
252
253static const struct drm_connector_funcs ptn3460_connector_funcs = { 248static const struct drm_connector_funcs ptn3460_connector_funcs = {
254 .dpms = drm_atomic_helper_connector_dpms, 249 .dpms = drm_atomic_helper_connector_dpms,
255 .fill_modes = drm_helper_probe_single_connector_modes, 250 .fill_modes = drm_helper_probe_single_connector_modes,
256 .detect = ptn3460_detect, 251 .detect = ptn3460_detect,
257 .destroy = ptn3460_connector_destroy, 252 .destroy = drm_connector_cleanup,
258 .reset = drm_atomic_helper_connector_reset, 253 .reset = drm_atomic_helper_connector_reset,
259 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, 254 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
260 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, 255 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
diff --git a/drivers/gpu/drm/bridge/parade-ps8622.c b/drivers/gpu/drm/bridge/parade-ps8622.c
index f1b39a2645cc..6f7c2f9860d2 100644
--- a/drivers/gpu/drm/bridge/parade-ps8622.c
+++ b/drivers/gpu/drm/bridge/parade-ps8622.c
@@ -483,16 +483,11 @@ static enum drm_connector_status ps8622_detect(struct drm_connector *connector,
483 return connector_status_connected; 483 return connector_status_connected;
484} 484}
485 485
486static void ps8622_connector_destroy(struct drm_connector *connector)
487{
488 drm_connector_cleanup(connector);
489}
490
491static const struct drm_connector_funcs ps8622_connector_funcs = { 486static const struct drm_connector_funcs ps8622_connector_funcs = {
492 .dpms = drm_atomic_helper_connector_dpms, 487 .dpms = drm_atomic_helper_connector_dpms,
493 .fill_modes = drm_helper_probe_single_connector_modes, 488 .fill_modes = drm_helper_probe_single_connector_modes,
494 .detect = ps8622_detect, 489 .detect = ps8622_detect,
495 .destroy = ps8622_connector_destroy, 490 .destroy = drm_connector_cleanup,
496 .reset = drm_atomic_helper_connector_reset, 491 .reset = drm_atomic_helper_connector_reset,
497 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, 492 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
498 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, 493 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
diff --git a/drivers/gpu/drm/bridge/tc358767.c b/drivers/gpu/drm/bridge/tc358767.c
index a09825d8c94a..44d476ea6d2e 100644
--- a/drivers/gpu/drm/bridge/tc358767.c
+++ b/drivers/gpu/drm/bridge/tc358767.c
@@ -1165,17 +1165,11 @@ static const struct drm_connector_helper_funcs tc_connector_helper_funcs = {
1165 .best_encoder = tc_connector_best_encoder, 1165 .best_encoder = tc_connector_best_encoder,
1166}; 1166};
1167 1167
1168static void tc_connector_destroy(struct drm_connector *connector)
1169{
1170 drm_connector_unregister(connector);
1171 drm_connector_cleanup(connector);
1172}
1173
1174static const struct drm_connector_funcs tc_connector_funcs = { 1168static const struct drm_connector_funcs tc_connector_funcs = {
1175 .dpms = drm_atomic_helper_connector_dpms, 1169 .dpms = drm_atomic_helper_connector_dpms,
1176 .fill_modes = drm_helper_probe_single_connector_modes, 1170 .fill_modes = drm_helper_probe_single_connector_modes,
1177 .detect = tc_connector_detect, 1171 .detect = tc_connector_detect,
1178 .destroy = tc_connector_destroy, 1172 .destroy = drm_connector_cleanup,
1179 .reset = drm_atomic_helper_connector_reset, 1173 .reset = drm_atomic_helper_connector_reset,
1180 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, 1174 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
1181 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, 1175 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index 26bb78c76481..2db7fb510b6c 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -250,10 +250,10 @@ int drm_connector_init(struct drm_device *dev,
250 connector->debugfs_entry = NULL; 250 connector->debugfs_entry = NULL;
251out_put_type_id: 251out_put_type_id:
252 if (ret) 252 if (ret)
253 ida_remove(connector_ida, connector->connector_type_id); 253 ida_simple_remove(connector_ida, connector->connector_type_id);
254out_put_id: 254out_put_id:
255 if (ret) 255 if (ret)
256 ida_remove(&config->connector_ida, connector->index); 256 ida_simple_remove(&config->connector_ida, connector->index);
257out_put: 257out_put:
258 if (ret) 258 if (ret)
259 drm_mode_object_unregister(dev, &connector->base); 259 drm_mode_object_unregister(dev, &connector->base);
@@ -341,11 +341,11 @@ void drm_connector_cleanup(struct drm_connector *connector)
341 list_for_each_entry_safe(mode, t, &connector->modes, head) 341 list_for_each_entry_safe(mode, t, &connector->modes, head)
342 drm_mode_remove(connector, mode); 342 drm_mode_remove(connector, mode);
343 343
344 ida_remove(&drm_connector_enum_list[connector->connector_type].ida, 344 ida_simple_remove(&drm_connector_enum_list[connector->connector_type].ida,
345 connector->connector_type_id); 345 connector->connector_type_id);
346 346
347 ida_remove(&dev->mode_config.connector_ida, 347 ida_simple_remove(&dev->mode_config.connector_ida,
348 connector->index); 348 connector->index);
349 349
350 kfree(connector->display_info.bus_formats); 350 kfree(connector->display_info.bus_formats);
351 drm_mode_object_unregister(dev, &connector->base); 351 drm_mode_object_unregister(dev, &connector->base);
diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c
index 57201d68cf61..b22a94dd7b53 100644
--- a/drivers/gpu/drm/drm_prime.c
+++ b/drivers/gpu/drm/drm_prime.c
@@ -284,18 +284,47 @@ static void drm_gem_unmap_dma_buf(struct dma_buf_attachment *attach,
284} 284}
285 285
286/** 286/**
287 * drm_gem_dmabuf_export - dma_buf export implementation for GEM
288 * @dev: parent device for the exported dmabuf
289 * @exp_info: the export information used by dma_buf_export()
290 *
291 * This wraps dma_buf_export() for use by generic GEM drivers that are using
292 * drm_gem_dmabuf_release(). In addition to calling dma_buf_export(), we take
293 * a reference to the drm_device which is released by drm_gem_dmabuf_release().
294 *
295 * Returns the new dmabuf.
296 */
297struct dma_buf *drm_gem_dmabuf_export(struct drm_device *dev,
298 struct dma_buf_export_info *exp_info)
299{
300 struct dma_buf *dma_buf;
301
302 dma_buf = dma_buf_export(exp_info);
303 if (!IS_ERR(dma_buf))
304 drm_dev_ref(dev);
305
306 return dma_buf;
307}
308EXPORT_SYMBOL(drm_gem_dmabuf_export);
309
310/**
287 * drm_gem_dmabuf_release - dma_buf release implementation for GEM 311 * drm_gem_dmabuf_release - dma_buf release implementation for GEM
288 * @dma_buf: buffer to be released 312 * @dma_buf: buffer to be released
289 * 313 *
290 * Generic release function for dma_bufs exported as PRIME buffers. GEM drivers 314 * Generic release function for dma_bufs exported as PRIME buffers. GEM drivers
291 * must use this in their dma_buf ops structure as the release callback. 315 * must use this in their dma_buf ops structure as the release callback.
316 * drm_gem_dmabuf_release() should be used in conjunction with
317 * drm_gem_dmabuf_export().
292 */ 318 */
293void drm_gem_dmabuf_release(struct dma_buf *dma_buf) 319void drm_gem_dmabuf_release(struct dma_buf *dma_buf)
294{ 320{
295 struct drm_gem_object *obj = dma_buf->priv; 321 struct drm_gem_object *obj = dma_buf->priv;
322 struct drm_device *dev = obj->dev;
296 323
297 /* drop the reference on the export fd holds */ 324 /* drop the reference on the export fd holds */
298 drm_gem_object_unreference_unlocked(obj); 325 drm_gem_object_unreference_unlocked(obj);
326
327 drm_dev_unref(dev);
299} 328}
300EXPORT_SYMBOL(drm_gem_dmabuf_release); 329EXPORT_SYMBOL(drm_gem_dmabuf_release);
301 330
@@ -397,19 +426,22 @@ static const struct dma_buf_ops drm_gem_prime_dmabuf_ops = {
397 * using the PRIME helpers. 426 * using the PRIME helpers.
398 */ 427 */
399struct dma_buf *drm_gem_prime_export(struct drm_device *dev, 428struct dma_buf *drm_gem_prime_export(struct drm_device *dev,
400 struct drm_gem_object *obj, int flags) 429 struct drm_gem_object *obj,
430 int flags)
401{ 431{
402 DEFINE_DMA_BUF_EXPORT_INFO(exp_info); 432 struct dma_buf_export_info exp_info = {
403 433 .exp_name = KBUILD_MODNAME, /* white lie for debug */
404 exp_info.ops = &drm_gem_prime_dmabuf_ops; 434 .owner = dev->driver->fops->owner,
405 exp_info.size = obj->size; 435 .ops = &drm_gem_prime_dmabuf_ops,
406 exp_info.flags = flags; 436 .size = obj->size,
407 exp_info.priv = obj; 437 .flags = flags,
438 .priv = obj,
439 };
408 440
409 if (dev->driver->gem_prime_res_obj) 441 if (dev->driver->gem_prime_res_obj)
410 exp_info.resv = dev->driver->gem_prime_res_obj(obj); 442 exp_info.resv = dev->driver->gem_prime_res_obj(obj);
411 443
412 return dma_buf_export(&exp_info); 444 return drm_gem_dmabuf_export(dev, &exp_info);
413} 445}
414EXPORT_SYMBOL(drm_gem_prime_export); 446EXPORT_SYMBOL(drm_gem_prime_export);
415 447
diff --git a/drivers/gpu/drm/drm_simple_kms_helper.c b/drivers/gpu/drm/drm_simple_kms_helper.c
index 7b6d26e64977..7bae08c2bf0a 100644
--- a/drivers/gpu/drm/drm_simple_kms_helper.c
+++ b/drivers/gpu/drm/drm_simple_kms_helper.c
@@ -125,7 +125,33 @@ static void drm_simple_kms_plane_atomic_update(struct drm_plane *plane,
125 pipe->funcs->update(pipe, pstate); 125 pipe->funcs->update(pipe, pstate);
126} 126}
127 127
128static int drm_simple_kms_plane_prepare_fb(struct drm_plane *plane,
129 struct drm_plane_state *state)
130{
131 struct drm_simple_display_pipe *pipe;
132
133 pipe = container_of(plane, struct drm_simple_display_pipe, plane);
134 if (!pipe->funcs || !pipe->funcs->prepare_fb)
135 return 0;
136
137 return pipe->funcs->prepare_fb(pipe, state);
138}
139
140static void drm_simple_kms_plane_cleanup_fb(struct drm_plane *plane,
141 struct drm_plane_state *state)
142{
143 struct drm_simple_display_pipe *pipe;
144
145 pipe = container_of(plane, struct drm_simple_display_pipe, plane);
146 if (!pipe->funcs || !pipe->funcs->cleanup_fb)
147 return;
148
149 pipe->funcs->cleanup_fb(pipe, state);
150}
151
128static const struct drm_plane_helper_funcs drm_simple_kms_plane_helper_funcs = { 152static const struct drm_plane_helper_funcs drm_simple_kms_plane_helper_funcs = {
153 .prepare_fb = drm_simple_kms_plane_prepare_fb,
154 .cleanup_fb = drm_simple_kms_plane_cleanup_fb,
129 .atomic_check = drm_simple_kms_plane_atomic_check, 155 .atomic_check = drm_simple_kms_plane_atomic_check,
130 .atomic_update = drm_simple_kms_plane_atomic_update, 156 .atomic_update = drm_simple_kms_plane_atomic_update,
131}; 157};
diff --git a/drivers/gpu/drm/i915/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/i915_gem_dmabuf.c
index 10265bb35604..97c9d68b45df 100644
--- a/drivers/gpu/drm/i915/i915_gem_dmabuf.c
+++ b/drivers/gpu/drm/i915/i915_gem_dmabuf.c
@@ -283,7 +283,7 @@ struct dma_buf *i915_gem_prime_export(struct drm_device *dev,
283 return ERR_PTR(ret); 283 return ERR_PTR(ret);
284 } 284 }
285 285
286 dma_buf = dma_buf_export(&exp_info); 286 dma_buf = drm_gem_dmabuf_export(dev, &exp_info);
287 if (IS_ERR(dma_buf)) 287 if (IS_ERR(dma_buf))
288 return dma_buf; 288 return dma_buf;
289 289
diff --git a/drivers/gpu/drm/tegra/gem.c b/drivers/gpu/drm/tegra/gem.c
index aa60d9909ea2..95e622e31931 100644
--- a/drivers/gpu/drm/tegra/gem.c
+++ b/drivers/gpu/drm/tegra/gem.c
@@ -613,7 +613,7 @@ struct dma_buf *tegra_gem_prime_export(struct drm_device *drm,
613 exp_info.flags = flags; 613 exp_info.flags = flags;
614 exp_info.priv = gem; 614 exp_info.priv = gem;
615 615
616 return dma_buf_export(&exp_info); 616 return drm_gem_dmabuf_export(drm, &exp_info);
617} 617}
618 618
619struct drm_gem_object *tegra_gem_prime_import(struct drm_device *drm, 619struct drm_gem_object *tegra_gem_prime_import(struct drm_device *drm,
diff --git a/drivers/gpu/drm/udl/udl_dmabuf.c b/drivers/gpu/drm/udl/udl_dmabuf.c
index e2243edd1ce3..ac90ffdb5912 100644
--- a/drivers/gpu/drm/udl/udl_dmabuf.c
+++ b/drivers/gpu/drm/udl/udl_dmabuf.c
@@ -209,7 +209,7 @@ struct dma_buf *udl_gem_prime_export(struct drm_device *dev,
209 exp_info.flags = flags; 209 exp_info.flags = flags;
210 exp_info.priv = obj; 210 exp_info.priv = obj;
211 211
212 return dma_buf_export(&exp_info); 212 return drm_gem_dmabuf_export(dev, &exp_info);
213} 213}
214 214
215static int udl_prime_create(struct drm_device *dev, 215static int udl_prime_create(struct drm_device *dev,
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 0e99669159c1..672644031bd5 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -1011,8 +1011,11 @@ static inline int drm_debugfs_remove_files(const struct drm_info_list *files,
1011} 1011}
1012#endif 1012#endif
1013 1013
1014struct dma_buf_export_info;
1015
1014extern struct dma_buf *drm_gem_prime_export(struct drm_device *dev, 1016extern struct dma_buf *drm_gem_prime_export(struct drm_device *dev,
1015 struct drm_gem_object *obj, int flags); 1017 struct drm_gem_object *obj,
1018 int flags);
1016extern int drm_gem_prime_handle_to_fd(struct drm_device *dev, 1019extern int drm_gem_prime_handle_to_fd(struct drm_device *dev,
1017 struct drm_file *file_priv, uint32_t handle, uint32_t flags, 1020 struct drm_file *file_priv, uint32_t handle, uint32_t flags,
1018 int *prime_fd); 1021 int *prime_fd);
@@ -1020,6 +1023,8 @@ extern struct drm_gem_object *drm_gem_prime_import(struct drm_device *dev,
1020 struct dma_buf *dma_buf); 1023 struct dma_buf *dma_buf);
1021extern int drm_gem_prime_fd_to_handle(struct drm_device *dev, 1024extern int drm_gem_prime_fd_to_handle(struct drm_device *dev,
1022 struct drm_file *file_priv, int prime_fd, uint32_t *handle); 1025 struct drm_file *file_priv, int prime_fd, uint32_t *handle);
1026struct dma_buf *drm_gem_dmabuf_export(struct drm_device *dev,
1027 struct dma_buf_export_info *exp_info);
1023extern void drm_gem_dmabuf_release(struct dma_buf *dma_buf); 1028extern void drm_gem_dmabuf_release(struct dma_buf *dma_buf);
1024 1029
1025extern int drm_prime_sg_to_page_addr_arrays(struct sg_table *sgt, struct page **pages, 1030extern int drm_prime_sg_to_page_addr_arrays(struct sg_table *sgt, struct page **pages,
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index 287a610f464e..ac9d7d8e0e43 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -356,7 +356,7 @@ struct drm_connector_funcs {
356 * 356 *
357 * This optional hook should be used to unregister the additional 357 * This optional hook should be used to unregister the additional
358 * userspace interfaces attached to the connector from 358 * userspace interfaces attached to the connector from
359 * late_unregister(). It is called from drm_connector_unregister(), 359 * late_register(). It is called from drm_connector_unregister(),
360 * early in the driver unload sequence to disable userspace access 360 * early in the driver unload sequence to disable userspace access
361 * before data structures are torndown. 361 * before data structures are torndown.
362 */ 362 */
@@ -376,7 +376,7 @@ struct drm_connector_funcs {
376 * @atomic_duplicate_state: 376 * @atomic_duplicate_state:
377 * 377 *
378 * Duplicate the current atomic state for this connector and return it. 378 * Duplicate the current atomic state for this connector and return it.
379 * The core and helpers gurantee that any atomic state duplicated with 379 * The core and helpers guarantee that any atomic state duplicated with
380 * this hook and still owned by the caller (i.e. not transferred to the 380 * this hook and still owned by the caller (i.e. not transferred to the
381 * driver by calling ->atomic_commit() from struct 381 * driver by calling ->atomic_commit() from struct
382 * &drm_mode_config_funcs) will be cleaned up by calling the 382 * &drm_mode_config_funcs) will be cleaned up by calling the
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 61932f55f788..0aa292526567 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -1342,7 +1342,7 @@ extern void drm_crtc_cleanup(struct drm_crtc *crtc);
1342 * Given a registered CRTC, return the index of that CRTC within a DRM 1342 * Given a registered CRTC, return the index of that CRTC within a DRM
1343 * device's list of CRTCs. 1343 * device's list of CRTCs.
1344 */ 1344 */
1345static inline unsigned int drm_crtc_index(struct drm_crtc *crtc) 1345static inline unsigned int drm_crtc_index(const struct drm_crtc *crtc)
1346{ 1346{
1347 return crtc->index; 1347 return crtc->index;
1348} 1348}
diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h
index 3c5f5992b96a..ed8edfef75b2 100644
--- a/include/drm/drm_fb_helper.h
+++ b/include/drm/drm_fb_helper.h
@@ -218,7 +218,7 @@ struct drm_fb_helper {
218}; 218};
219 219
220/** 220/**
221 * @DRM_FB_HELPER_DEFAULT_OPS: 221 * define DRM_FB_HELPER_DEFAULT_OPS - helper define for drm drivers
222 * 222 *
223 * Helper define to register default implementations of drm_fb_helper 223 * Helper define to register default implementations of drm_fb_helper
224 * functions. To be used in struct fb_ops of drm drivers. 224 * functions. To be used in struct fb_ops of drm drivers.
diff --git a/include/drm/drm_simple_kms_helper.h b/include/drm/drm_simple_kms_helper.h
index 5d112f75e04c..01a8436ccb0a 100644
--- a/include/drm/drm_simple_kms_helper.h
+++ b/include/drm/drm_simple_kms_helper.h
@@ -69,6 +69,26 @@ struct drm_simple_display_pipe_funcs {
69 */ 69 */
70 void (*update)(struct drm_simple_display_pipe *pipe, 70 void (*update)(struct drm_simple_display_pipe *pipe,
71 struct drm_plane_state *plane_state); 71 struct drm_plane_state *plane_state);
72
73 /**
74 * @prepare_fb:
75 *
76 * Optional, called by struct &drm_plane_helper_funcs ->prepare_fb .
77 * Please read the documentation for the ->prepare_fb hook in
78 * struct &drm_plane_helper_funcs for more details.
79 */
80 int (*prepare_fb)(struct drm_simple_display_pipe *pipe,
81 struct drm_plane_state *plane_state);
82
83 /**
84 * @cleanup_fb:
85 *
86 * Optional, called by struct &drm_plane_helper_funcs ->cleanup_fb .
87 * Please read the documentation for the ->cleanup_fb hook in
88 * struct &drm_plane_helper_funcs for more details.
89 */
90 void (*cleanup_fb)(struct drm_simple_display_pipe *pipe,
91 struct drm_plane_state *plane_state);
72}; 92};
73 93
74/** 94/**