forked from ~ljy/RK356X_SDK_RELEASE

hc
2023-12-11 6778948f9de86c3cfaf36725a7c87dcff9ba247f
kernel/drivers/gpu/drm/omapdrm/dss/base.c
....@@ -1,36 +1,22 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * OMAP Display Subsystem Base
34 *
45 * Copyright (C) 2015-2017 Texas Instruments Incorporated - http://www.ti.com/
5
- *
6
- * This program is free software; you can redistribute it and/or modify
7
- * it under the terms of the GNU General Public License version 2 as
8
- * published by the Free Software Foundation.
9
- *
10
- * This program is distributed in the hope that it will be useful, but
11
- * WITHOUT ANY WARRANTY; without even the implied warranty of
12
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
- * General Public License for more details.
146 */
157
168 #include <linux/kernel.h>
9
+#include <linux/list.h>
1710 #include <linux/module.h>
11
+#include <linux/mutex.h>
1812 #include <linux/of.h>
1913 #include <linux/of_graph.h>
20
-#include <linux/list.h>
14
+#include <linux/platform_device.h>
2115
2216 #include "dss.h"
2317 #include "omapdss.h"
2418
2519 static struct dss_device *dss_device;
26
-
27
-static struct list_head omapdss_comp_list;
28
-
29
-struct omapdss_comp_node {
30
- struct list_head list;
31
- struct device_node *node;
32
- bool dss_core_component;
33
-};
3420
3521 struct dss_device *omapdss_get_dss(void)
3622 {
....@@ -56,6 +42,237 @@
5642 }
5743 EXPORT_SYMBOL(dispc_get_ops);
5844
45
+
46
+/* -----------------------------------------------------------------------------
47
+ * OMAP DSS Devices Handling
48
+ */
49
+
50
+static LIST_HEAD(omapdss_devices_list);
51
+static DEFINE_MUTEX(omapdss_devices_lock);
52
+
53
+void omapdss_device_register(struct omap_dss_device *dssdev)
54
+{
55
+ mutex_lock(&omapdss_devices_lock);
56
+ list_add_tail(&dssdev->list, &omapdss_devices_list);
57
+ mutex_unlock(&omapdss_devices_lock);
58
+}
59
+EXPORT_SYMBOL_GPL(omapdss_device_register);
60
+
61
+void omapdss_device_unregister(struct omap_dss_device *dssdev)
62
+{
63
+ mutex_lock(&omapdss_devices_lock);
64
+ list_del(&dssdev->list);
65
+ mutex_unlock(&omapdss_devices_lock);
66
+}
67
+EXPORT_SYMBOL_GPL(omapdss_device_unregister);
68
+
69
+static bool omapdss_device_is_registered(struct device_node *node)
70
+{
71
+ struct omap_dss_device *dssdev;
72
+ bool found = false;
73
+
74
+ mutex_lock(&omapdss_devices_lock);
75
+
76
+ list_for_each_entry(dssdev, &omapdss_devices_list, list) {
77
+ if (dssdev->dev->of_node == node) {
78
+ found = true;
79
+ break;
80
+ }
81
+ }
82
+
83
+ mutex_unlock(&omapdss_devices_lock);
84
+ return found;
85
+}
86
+
87
+struct omap_dss_device *omapdss_device_get(struct omap_dss_device *dssdev)
88
+{
89
+ if (!try_module_get(dssdev->owner))
90
+ return NULL;
91
+
92
+ if (get_device(dssdev->dev) == NULL) {
93
+ module_put(dssdev->owner);
94
+ return NULL;
95
+ }
96
+
97
+ return dssdev;
98
+}
99
+EXPORT_SYMBOL(omapdss_device_get);
100
+
101
+void omapdss_device_put(struct omap_dss_device *dssdev)
102
+{
103
+ put_device(dssdev->dev);
104
+ module_put(dssdev->owner);
105
+}
106
+EXPORT_SYMBOL(omapdss_device_put);
107
+
108
+struct omap_dss_device *omapdss_find_device_by_node(struct device_node *node)
109
+{
110
+ struct omap_dss_device *dssdev;
111
+
112
+ list_for_each_entry(dssdev, &omapdss_devices_list, list) {
113
+ if (dssdev->dev->of_node == node)
114
+ return omapdss_device_get(dssdev);
115
+ }
116
+
117
+ return NULL;
118
+}
119
+
120
+/*
121
+ * Search for the next output device starting at @from. Release the reference to
122
+ * the @from device, and acquire a reference to the returned device if found.
123
+ */
124
+struct omap_dss_device *omapdss_device_next_output(struct omap_dss_device *from)
125
+{
126
+ struct omap_dss_device *dssdev;
127
+ struct list_head *list;
128
+
129
+ mutex_lock(&omapdss_devices_lock);
130
+
131
+ if (list_empty(&omapdss_devices_list)) {
132
+ dssdev = NULL;
133
+ goto done;
134
+ }
135
+
136
+ /*
137
+ * Start from the from entry if given or from omapdss_devices_list
138
+ * otherwise.
139
+ */
140
+ list = from ? &from->list : &omapdss_devices_list;
141
+
142
+ list_for_each_entry(dssdev, list, list) {
143
+ /*
144
+ * Stop if we reach the omapdss_devices_list, that's the end of
145
+ * the list.
146
+ */
147
+ if (&dssdev->list == &omapdss_devices_list) {
148
+ dssdev = NULL;
149
+ goto done;
150
+ }
151
+
152
+ if (dssdev->id && (dssdev->next || dssdev->bridge))
153
+ goto done;
154
+ }
155
+
156
+ dssdev = NULL;
157
+
158
+done:
159
+ if (from)
160
+ omapdss_device_put(from);
161
+ if (dssdev)
162
+ omapdss_device_get(dssdev);
163
+
164
+ mutex_unlock(&omapdss_devices_lock);
165
+ return dssdev;
166
+}
167
+EXPORT_SYMBOL(omapdss_device_next_output);
168
+
169
+static bool omapdss_device_is_connected(struct omap_dss_device *dssdev)
170
+{
171
+ return dssdev->dss;
172
+}
173
+
174
+int omapdss_device_connect(struct dss_device *dss,
175
+ struct omap_dss_device *src,
176
+ struct omap_dss_device *dst)
177
+{
178
+ int ret;
179
+
180
+ dev_dbg(&dss->pdev->dev, "connect(%s, %s)\n",
181
+ src ? dev_name(src->dev) : "NULL",
182
+ dst ? dev_name(dst->dev) : "NULL");
183
+
184
+ if (!dst) {
185
+ /*
186
+ * The destination is NULL when the source is connected to a
187
+ * bridge instead of a DSS device. Stop here, we will attach
188
+ * the bridge later when we will have a DRM encoder.
189
+ */
190
+ return src && src->bridge ? 0 : -EINVAL;
191
+ }
192
+
193
+ if (omapdss_device_is_connected(dst))
194
+ return -EBUSY;
195
+
196
+ dst->dss = dss;
197
+
198
+ if (dst->ops && dst->ops->connect) {
199
+ ret = dst->ops->connect(src, dst);
200
+ if (ret < 0) {
201
+ dst->dss = NULL;
202
+ return ret;
203
+ }
204
+ }
205
+
206
+ return 0;
207
+}
208
+EXPORT_SYMBOL_GPL(omapdss_device_connect);
209
+
210
+void omapdss_device_disconnect(struct omap_dss_device *src,
211
+ struct omap_dss_device *dst)
212
+{
213
+ struct dss_device *dss = src ? src->dss : dst->dss;
214
+
215
+ dev_dbg(&dss->pdev->dev, "disconnect(%s, %s)\n",
216
+ src ? dev_name(src->dev) : "NULL",
217
+ dst ? dev_name(dst->dev) : "NULL");
218
+
219
+ if (!dst) {
220
+ WARN_ON(!src->bridge);
221
+ return;
222
+ }
223
+
224
+ if (!dst->id && !omapdss_device_is_connected(dst)) {
225
+ WARN_ON(!dst->display);
226
+ return;
227
+ }
228
+
229
+ WARN_ON(dst->state != OMAP_DSS_DISPLAY_DISABLED);
230
+
231
+ if (dst->ops && dst->ops->disconnect)
232
+ dst->ops->disconnect(src, dst);
233
+ dst->dss = NULL;
234
+}
235
+EXPORT_SYMBOL_GPL(omapdss_device_disconnect);
236
+
237
+void omapdss_device_enable(struct omap_dss_device *dssdev)
238
+{
239
+ if (!dssdev)
240
+ return;
241
+
242
+ if (dssdev->ops && dssdev->ops->enable)
243
+ dssdev->ops->enable(dssdev);
244
+
245
+ omapdss_device_enable(dssdev->next);
246
+
247
+ dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
248
+}
249
+EXPORT_SYMBOL_GPL(omapdss_device_enable);
250
+
251
+void omapdss_device_disable(struct omap_dss_device *dssdev)
252
+{
253
+ if (!dssdev)
254
+ return;
255
+
256
+ omapdss_device_disable(dssdev->next);
257
+
258
+ if (dssdev->ops && dssdev->ops->disable)
259
+ dssdev->ops->disable(dssdev);
260
+}
261
+EXPORT_SYMBOL_GPL(omapdss_device_disable);
262
+
263
+/* -----------------------------------------------------------------------------
264
+ * Components Handling
265
+ */
266
+
267
+static struct list_head omapdss_comp_list;
268
+
269
+struct omapdss_comp_node {
270
+ struct list_head list;
271
+ struct device_node *node;
272
+ bool dss_core_component;
273
+ const char *compat;
274
+};
275
+
59276 static bool omapdss_list_contains(const struct device_node *node)
60277 {
61278 struct omapdss_comp_node *comp;
....@@ -71,13 +288,20 @@
71288 static void omapdss_walk_device(struct device *dev, struct device_node *node,
72289 bool dss_core)
73290 {
291
+ struct omapdss_comp_node *comp;
74292 struct device_node *n;
75
- struct omapdss_comp_node *comp = devm_kzalloc(dev, sizeof(*comp),
76
- GFP_KERNEL);
293
+ const char *compat;
294
+ int ret;
77295
296
+ ret = of_property_read_string(node, "compatible", &compat);
297
+ if (ret < 0)
298
+ return;
299
+
300
+ comp = devm_kzalloc(dev, sizeof(*comp), GFP_KERNEL);
78301 if (comp) {
79302 comp->node = node;
80303 comp->dss_core_component = dss_core;
304
+ comp->compat = compat;
81305 list_add(&comp->list, &omapdss_comp_list);
82306 }
83307
....@@ -117,12 +341,8 @@
117341
118342 omapdss_walk_device(dev, dev->of_node, true);
119343
120
- for_each_available_child_of_node(dev->of_node, child) {
121
- if (!of_find_property(child, "compatible", NULL))
122
- continue;
123
-
344
+ for_each_available_child_of_node(dev->of_node, child)
124345 omapdss_walk_device(dev, child, true);
125
- }
126346 }
127347 EXPORT_SYMBOL(omapdss_gather_components);
128348
....@@ -130,9 +350,9 @@
130350 {
131351 if (comp->dss_core_component)
132352 return true;
133
- if (omapdss_component_is_display(comp->node))
353
+ if (!strstarts(comp->compat, "omapdss,"))
134354 return true;
135
- if (omapdss_component_is_output(comp->node))
355
+ if (omapdss_device_is_registered(comp->node))
136356 return true;
137357
138358 return false;