hc
2024-05-10 cde9070d9970eef1f7ec2360586c802a16230ad8
kernel/drivers/gpu/drm/omapdrm/dss/output.c
....@@ -1,18 +1,7 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
34 * Author: Archit Taneja <archit@ti.com>
4
- *
5
- * This program is free software; you can redistribute it and/or modify it
6
- * under the terms of the GNU General Public License version 2 as published by
7
- * the Free Software Foundation.
8
- *
9
- * This program is distributed in the hope that it will be useful, but WITHOUT
10
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12
- * more details.
13
- *
14
- * You should have received a copy of the GNU General Public License along with
15
- * this program. If not, see <http://www.gnu.org/licenses/>.
165 */
176
187 #include <linux/kernel.h>
....@@ -20,239 +9,167 @@
209 #include <linux/platform_device.h>
2110 #include <linux/slab.h>
2211 #include <linux/of.h>
12
+#include <linux/of_graph.h>
2313
14
+#include <drm/drm_bridge.h>
15
+#include <drm/drm_panel.h>
16
+
17
+#include "dss.h"
2418 #include "omapdss.h"
2519
26
-static LIST_HEAD(output_list);
27
-static DEFINE_MUTEX(output_lock);
28
-
29
-int omapdss_output_set_device(struct omap_dss_device *out,
30
- struct omap_dss_device *dssdev)
20
+int omapdss_device_init_output(struct omap_dss_device *out,
21
+ struct drm_bridge *local_bridge)
3122 {
32
- int r;
23
+ struct device_node *remote_node;
24
+ int ret;
3325
34
- mutex_lock(&output_lock);
35
-
36
- if (out->dst) {
37
- dev_err(out->dev,
38
- "output already has device %s connected to it\n",
39
- out->dst->name);
40
- r = -EINVAL;
41
- goto err;
26
+ remote_node = of_graph_get_remote_node(out->dev->of_node,
27
+ out->of_port, 0);
28
+ if (!remote_node) {
29
+ dev_dbg(out->dev, "failed to find video sink\n");
30
+ return 0;
4231 }
4332
44
- if (out->output_type != dssdev->type) {
33
+ out->next = omapdss_find_device_by_node(remote_node);
34
+ out->bridge = of_drm_find_bridge(remote_node);
35
+ out->panel = of_drm_find_panel(remote_node);
36
+ if (IS_ERR(out->panel))
37
+ out->panel = NULL;
38
+
39
+ of_node_put(remote_node);
40
+
41
+ if (out->next && out->type != out->next->type) {
4542 dev_err(out->dev, "output type and display type don't match\n");
46
- r = -EINVAL;
47
- goto err;
43
+ ret = -EINVAL;
44
+ goto error;
4845 }
4946
50
- out->dst = dssdev;
51
- dssdev->src = out;
47
+ if (out->panel) {
48
+ struct drm_bridge *bridge;
5249
53
- mutex_unlock(&output_lock);
54
-
55
- return 0;
56
-err:
57
- mutex_unlock(&output_lock);
58
-
59
- return r;
60
-}
61
-EXPORT_SYMBOL(omapdss_output_set_device);
62
-
63
-int omapdss_output_unset_device(struct omap_dss_device *out)
64
-{
65
- int r;
66
-
67
- mutex_lock(&output_lock);
68
-
69
- if (!out->dst) {
70
- dev_err(out->dev,
71
- "output doesn't have a device connected to it\n");
72
- r = -EINVAL;
73
- goto err;
74
- }
75
-
76
- if (out->dst->state != OMAP_DSS_DISPLAY_DISABLED) {
77
- dev_err(out->dev,
78
- "device %s is not disabled, cannot unset device\n",
79
- out->dst->name);
80
- r = -EINVAL;
81
- goto err;
82
- }
83
-
84
- out->dst->src = NULL;
85
- out->dst = NULL;
86
-
87
- mutex_unlock(&output_lock);
88
-
89
- return 0;
90
-err:
91
- mutex_unlock(&output_lock);
92
-
93
- return r;
94
-}
95
-EXPORT_SYMBOL(omapdss_output_unset_device);
96
-
97
-int omapdss_register_output(struct omap_dss_device *out)
98
-{
99
- list_add_tail(&out->list, &output_list);
100
- return 0;
101
-}
102
-EXPORT_SYMBOL(omapdss_register_output);
103
-
104
-void omapdss_unregister_output(struct omap_dss_device *out)
105
-{
106
- list_del(&out->list);
107
-}
108
-EXPORT_SYMBOL(omapdss_unregister_output);
109
-
110
-bool omapdss_component_is_output(struct device_node *node)
111
-{
112
- struct omap_dss_device *out;
113
-
114
- list_for_each_entry(out, &output_list, list) {
115
- if (out->dev->of_node == node)
116
- return true;
117
- }
118
-
119
- return false;
120
-}
121
-EXPORT_SYMBOL(omapdss_component_is_output);
122
-
123
-struct omap_dss_device *omap_dss_get_output(enum omap_dss_output_id id)
124
-{
125
- struct omap_dss_device *out;
126
-
127
- list_for_each_entry(out, &output_list, list) {
128
- if (out->id == id)
129
- return out;
130
- }
131
-
132
- return NULL;
133
-}
134
-EXPORT_SYMBOL(omap_dss_get_output);
135
-
136
-struct omap_dss_device *omap_dss_find_output_by_port_node(struct device_node *port)
137
-{
138
- struct device_node *src_node;
139
- struct omap_dss_device *out;
140
- u32 reg;
141
-
142
- src_node = dss_of_port_get_parent_device(port);
143
- if (!src_node)
144
- return NULL;
145
-
146
- reg = dss_of_port_get_port_number(port);
147
-
148
- list_for_each_entry(out, &output_list, list) {
149
- if (out->dev->of_node == src_node && out->port_num == reg) {
150
- of_node_put(src_node);
151
- return omap_dss_get_device(out);
50
+ bridge = drm_panel_bridge_add(out->panel);
51
+ if (IS_ERR(bridge)) {
52
+ dev_err(out->dev,
53
+ "unable to create panel bridge (%ld)\n",
54
+ PTR_ERR(bridge));
55
+ ret = PTR_ERR(bridge);
56
+ goto error;
15257 }
58
+
59
+ out->bridge = bridge;
15360 }
15461
155
- of_node_put(src_node);
62
+ if (local_bridge) {
63
+ if (!out->bridge) {
64
+ ret = -EPROBE_DEFER;
65
+ goto error;
66
+ }
15667
157
- return NULL;
68
+ out->next_bridge = out->bridge;
69
+ out->bridge = local_bridge;
70
+ }
71
+
72
+ if (!out->next && !out->bridge) {
73
+ ret = -EPROBE_DEFER;
74
+ goto error;
75
+ }
76
+
77
+ return 0;
78
+
79
+error:
80
+ omapdss_device_cleanup_output(out);
81
+ out->next = NULL;
82
+ return ret;
15883 }
84
+EXPORT_SYMBOL(omapdss_device_init_output);
15985
160
-struct omap_dss_device *omapdss_find_output_from_display(struct omap_dss_device *dssdev)
86
+void omapdss_device_cleanup_output(struct omap_dss_device *out)
16187 {
162
- while (dssdev->src)
163
- dssdev = dssdev->src;
88
+ if (out->bridge && out->panel)
89
+ drm_panel_bridge_remove(out->next_bridge ?
90
+ out->next_bridge : out->bridge);
16491
165
- if (dssdev->id != 0)
166
- return omap_dss_get_device(dssdev);
167
-
168
- return NULL;
92
+ if (out->next)
93
+ omapdss_device_put(out->next);
16994 }
170
-EXPORT_SYMBOL(omapdss_find_output_from_display);
95
+EXPORT_SYMBOL(omapdss_device_cleanup_output);
17196
172
-static const struct dss_mgr_ops *dss_mgr_ops;
173
-static struct omap_drm_private *dss_mgr_ops_priv;
174
-
175
-int dss_install_mgr_ops(const struct dss_mgr_ops *mgr_ops,
97
+int dss_install_mgr_ops(struct dss_device *dss,
98
+ const struct dss_mgr_ops *mgr_ops,
17699 struct omap_drm_private *priv)
177100 {
178
- if (dss_mgr_ops)
101
+ if (dss->mgr_ops)
179102 return -EBUSY;
180103
181
- dss_mgr_ops = mgr_ops;
182
- dss_mgr_ops_priv = priv;
104
+ dss->mgr_ops = mgr_ops;
105
+ dss->mgr_ops_priv = priv;
183106
184107 return 0;
185108 }
186109 EXPORT_SYMBOL(dss_install_mgr_ops);
187110
188
-void dss_uninstall_mgr_ops(void)
111
+void dss_uninstall_mgr_ops(struct dss_device *dss)
189112 {
190
- dss_mgr_ops = NULL;
191
- dss_mgr_ops_priv = NULL;
113
+ dss->mgr_ops = NULL;
114
+ dss->mgr_ops_priv = NULL;
192115 }
193116 EXPORT_SYMBOL(dss_uninstall_mgr_ops);
194
-
195
-int dss_mgr_connect(struct omap_dss_device *dssdev, struct omap_dss_device *dst)
196
-{
197
- return dss_mgr_ops->connect(dss_mgr_ops_priv,
198
- dssdev->dispc_channel, dst);
199
-}
200
-EXPORT_SYMBOL(dss_mgr_connect);
201
-
202
-void dss_mgr_disconnect(struct omap_dss_device *dssdev,
203
- struct omap_dss_device *dst)
204
-{
205
- dss_mgr_ops->disconnect(dss_mgr_ops_priv, dssdev->dispc_channel, dst);
206
-}
207
-EXPORT_SYMBOL(dss_mgr_disconnect);
208117
209118 void dss_mgr_set_timings(struct omap_dss_device *dssdev,
210119 const struct videomode *vm)
211120 {
212
- dss_mgr_ops->set_timings(dss_mgr_ops_priv, dssdev->dispc_channel, vm);
121
+ dssdev->dss->mgr_ops->set_timings(dssdev->dss->mgr_ops_priv,
122
+ dssdev->dispc_channel, vm);
213123 }
214124 EXPORT_SYMBOL(dss_mgr_set_timings);
215125
216126 void dss_mgr_set_lcd_config(struct omap_dss_device *dssdev,
217127 const struct dss_lcd_mgr_config *config)
218128 {
219
- dss_mgr_ops->set_lcd_config(dss_mgr_ops_priv,
220
- dssdev->dispc_channel, config);
129
+ dssdev->dss->mgr_ops->set_lcd_config(dssdev->dss->mgr_ops_priv,
130
+ dssdev->dispc_channel, config);
221131 }
222132 EXPORT_SYMBOL(dss_mgr_set_lcd_config);
223133
224134 int dss_mgr_enable(struct omap_dss_device *dssdev)
225135 {
226
- return dss_mgr_ops->enable(dss_mgr_ops_priv, dssdev->dispc_channel);
136
+ return dssdev->dss->mgr_ops->enable(dssdev->dss->mgr_ops_priv,
137
+ dssdev->dispc_channel);
227138 }
228139 EXPORT_SYMBOL(dss_mgr_enable);
229140
230141 void dss_mgr_disable(struct omap_dss_device *dssdev)
231142 {
232
- dss_mgr_ops->disable(dss_mgr_ops_priv, dssdev->dispc_channel);
143
+ dssdev->dss->mgr_ops->disable(dssdev->dss->mgr_ops_priv,
144
+ dssdev->dispc_channel);
233145 }
234146 EXPORT_SYMBOL(dss_mgr_disable);
235147
236148 void dss_mgr_start_update(struct omap_dss_device *dssdev)
237149 {
238
- dss_mgr_ops->start_update(dss_mgr_ops_priv, dssdev->dispc_channel);
150
+ dssdev->dss->mgr_ops->start_update(dssdev->dss->mgr_ops_priv,
151
+ dssdev->dispc_channel);
239152 }
240153 EXPORT_SYMBOL(dss_mgr_start_update);
241154
242155 int dss_mgr_register_framedone_handler(struct omap_dss_device *dssdev,
243156 void (*handler)(void *), void *data)
244157 {
245
- return dss_mgr_ops->register_framedone_handler(dss_mgr_ops_priv,
246
- dssdev->dispc_channel,
247
- handler, data);
158
+ struct dss_device *dss = dssdev->dss;
159
+
160
+ return dss->mgr_ops->register_framedone_handler(dss->mgr_ops_priv,
161
+ dssdev->dispc_channel,
162
+ handler, data);
248163 }
249164 EXPORT_SYMBOL(dss_mgr_register_framedone_handler);
250165
251166 void dss_mgr_unregister_framedone_handler(struct omap_dss_device *dssdev,
252167 void (*handler)(void *), void *data)
253168 {
254
- dss_mgr_ops->unregister_framedone_handler(dss_mgr_ops_priv,
255
- dssdev->dispc_channel,
256
- handler, data);
169
+ struct dss_device *dss = dssdev->dss;
170
+
171
+ dss->mgr_ops->unregister_framedone_handler(dss->mgr_ops_priv,
172
+ dssdev->dispc_channel,
173
+ handler, data);
257174 }
258175 EXPORT_SYMBOL(dss_mgr_unregister_framedone_handler);