hc
2023-12-06 08f87f769b595151be1afeff53e144f543faa614
kernel/drivers/gpu/drm/bridge/panel.c
....@@ -1,21 +1,17 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * Copyright (C) 2016 Laurent Pinchart <laurent.pinchart@ideasonboard.com>
34 * Copyright (C) 2017 Broadcom
4
- *
5
- * This program is free software; you can redistribute it and/or
6
- * modify it under the terms of the GNU General Public License as
7
- * published by the Free Software Foundation; either version 2 of
8
- * the License, or (at your option) any later version.
95 */
106
11
-#include <drm/drmP.h>
12
-#include <drm/drm_panel.h>
137 #include <drm/drm_atomic_helper.h>
8
+#include <drm/drm_bridge.h>
149 #include <drm/drm_connector.h>
15
-#include <drm/drm_crtc_helper.h>
1610 #include <drm/drm_encoder.h>
1711 #include <drm/drm_modeset_helper_vtables.h>
1812 #include <drm/drm_panel.h>
13
+#include <drm/drm_print.h>
14
+#include <drm/drm_probe_helper.h>
1915
2016 struct panel_bridge {
2117 struct drm_bridge bridge;
....@@ -41,7 +37,7 @@
4137 struct panel_bridge *panel_bridge =
4238 drm_connector_to_panel_bridge(connector);
4339
44
- return drm_panel_get_modes(panel_bridge->panel);
40
+ return drm_panel_get_modes(panel_bridge->panel, connector);
4541 }
4642
4743 static const struct drm_connector_helper_funcs
....@@ -57,11 +53,15 @@
5753 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
5854 };
5955
60
-static int panel_bridge_attach(struct drm_bridge *bridge)
56
+static int panel_bridge_attach(struct drm_bridge *bridge,
57
+ enum drm_bridge_attach_flags flags)
6158 {
6259 struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
6360 struct drm_connector *connector = &panel_bridge->connector;
6461 int ret;
62
+
63
+ if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
64
+ return 0;
6565
6666 if (!bridge->encoder) {
6767 DRM_ERROR("Missing encoder\n");
....@@ -82,18 +82,23 @@
8282 drm_connector_attach_encoder(&panel_bridge->connector,
8383 bridge->encoder);
8484
85
- ret = drm_panel_attach(panel_bridge->panel, &panel_bridge->connector);
86
- if (ret < 0)
87
- return ret;
88
-
8985 return 0;
9086 }
9187
9288 static void panel_bridge_detach(struct drm_bridge *bridge)
9389 {
9490 struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
91
+ struct drm_connector *connector = &panel_bridge->connector;
9592
96
- drm_panel_detach(panel_bridge->panel);
93
+ /*
94
+ * Cleanup the connector if we know it was initialized.
95
+ *
96
+ * FIXME: This wouldn't be needed if the panel_bridge structure was
97
+ * allocated with drmm_kzalloc(). This might be tricky since the
98
+ * drm_device pointer can only be retrieved when the bridge is attached.
99
+ */
100
+ if (connector->dev)
101
+ drm_connector_cleanup(connector);
97102 }
98103
99104 static void panel_bridge_pre_enable(struct drm_bridge *bridge)
....@@ -124,6 +129,14 @@
124129 drm_panel_unprepare(panel_bridge->panel);
125130 }
126131
132
+static int panel_bridge_get_modes(struct drm_bridge *bridge,
133
+ struct drm_connector *connector)
134
+{
135
+ struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
136
+
137
+ return drm_panel_get_modes(panel_bridge->panel, connector);
138
+}
139
+
127140 static const struct drm_bridge_funcs panel_bridge_bridge_funcs = {
128141 .attach = panel_bridge_attach,
129142 .detach = panel_bridge_detach,
....@@ -131,15 +144,18 @@
131144 .enable = panel_bridge_enable,
132145 .disable = panel_bridge_disable,
133146 .post_disable = panel_bridge_post_disable,
147
+ .get_modes = panel_bridge_get_modes,
148
+ .atomic_reset = drm_atomic_helper_bridge_reset,
149
+ .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
150
+ .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
151
+ .atomic_get_input_bus_fmts = drm_atomic_helper_bridge_propagate_bus_fmt,
134152 };
135153
136154 /**
137
- * drm_panel_bridge_add - Creates a drm_bridge and drm_connector that
138
- * just calls the appropriate functions from drm_panel.
155
+ * drm_panel_bridge_add - Creates a &drm_bridge and &drm_connector that
156
+ * just calls the appropriate functions from &drm_panel.
139157 *
140158 * @panel: The drm_panel being wrapped. Must be non-NULL.
141
- * @connector_type: The DRM_MODE_CONNECTOR_* for the connector to be
142
- * created.
143159 *
144160 * For drivers converting from directly using drm_panel: The expected
145161 * usage pattern is that during either encoder module probe or DSI
....@@ -149,12 +165,41 @@
149165 * passed to drm_bridge_attach(). The drm_panel_prepare() and related
150166 * functions can be dropped from the encoder driver (they're now
151167 * called by the KMS helpers before calling into the encoder), along
152
- * with connector creation. When done with the bridge,
153
- * drm_bridge_detach() should be called as normal, then
168
+ * with connector creation. When done with the bridge (after
169
+ * drm_mode_config_cleanup() if the bridge has already been attached), then
154170 * drm_panel_bridge_remove() to free it.
171
+ *
172
+ * The connector type is set to @panel->connector_type, which must be set to a
173
+ * known type. Calling this function with a panel whose connector type is
174
+ * DRM_MODE_CONNECTOR_Unknown will return ERR_PTR(-EINVAL).
175
+ *
176
+ * See devm_drm_panel_bridge_add() for an automatically managed version of this
177
+ * function.
155178 */
156
-struct drm_bridge *drm_panel_bridge_add(struct drm_panel *panel,
157
- u32 connector_type)
179
+struct drm_bridge *drm_panel_bridge_add(struct drm_panel *panel)
180
+{
181
+ if (WARN_ON(panel->connector_type == DRM_MODE_CONNECTOR_Unknown))
182
+ return ERR_PTR(-EINVAL);
183
+
184
+ return drm_panel_bridge_add_typed(panel, panel->connector_type);
185
+}
186
+EXPORT_SYMBOL(drm_panel_bridge_add);
187
+
188
+/**
189
+ * drm_panel_bridge_add_typed - Creates a &drm_bridge and &drm_connector with
190
+ * an explicit connector type.
191
+ * @panel: The drm_panel being wrapped. Must be non-NULL.
192
+ * @connector_type: The connector type (DRM_MODE_CONNECTOR_*)
193
+ *
194
+ * This is just like drm_panel_bridge_add(), but forces the connector type to
195
+ * @connector_type instead of infering it from the panel.
196
+ *
197
+ * This function is deprecated and should not be used in new drivers. Use
198
+ * drm_panel_bridge_add() instead, and fix panel drivers as necessary if they
199
+ * don't report a connector type.
200
+ */
201
+struct drm_bridge *drm_panel_bridge_add_typed(struct drm_panel *panel,
202
+ u32 connector_type)
158203 {
159204 struct panel_bridge *panel_bridge;
160205
....@@ -173,12 +218,14 @@
173218 #ifdef CONFIG_OF
174219 panel_bridge->bridge.of_node = panel->dev->of_node;
175220 #endif
221
+ panel_bridge->bridge.ops = DRM_BRIDGE_OP_MODES;
222
+ panel_bridge->bridge.type = connector_type;
176223
177224 drm_bridge_add(&panel_bridge->bridge);
178225
179226 return &panel_bridge->bridge;
180227 }
181
-EXPORT_SYMBOL(drm_panel_bridge_add);
228
+EXPORT_SYMBOL(drm_panel_bridge_add_typed);
182229
183230 /**
184231 * drm_panel_bridge_remove - Unregisters and frees a drm_bridge
....@@ -210,9 +257,43 @@
210257 drm_panel_bridge_remove(*bridge);
211258 }
212259
260
+/**
261
+ * devm_drm_panel_bridge_add - Creates a managed &drm_bridge and &drm_connector
262
+ * that just calls the appropriate functions from &drm_panel.
263
+ * @dev: device to tie the bridge lifetime to
264
+ * @panel: The drm_panel being wrapped. Must be non-NULL.
265
+ *
266
+ * This is the managed version of drm_panel_bridge_add() which automatically
267
+ * calls drm_panel_bridge_remove() when @dev is unbound.
268
+ */
213269 struct drm_bridge *devm_drm_panel_bridge_add(struct device *dev,
214
- struct drm_panel *panel,
215
- u32 connector_type)
270
+ struct drm_panel *panel)
271
+{
272
+ if (WARN_ON(panel->connector_type == DRM_MODE_CONNECTOR_Unknown))
273
+ return ERR_PTR(-EINVAL);
274
+
275
+ return devm_drm_panel_bridge_add_typed(dev, panel,
276
+ panel->connector_type);
277
+}
278
+EXPORT_SYMBOL(devm_drm_panel_bridge_add);
279
+
280
+/**
281
+ * devm_drm_panel_bridge_add_typed - Creates a managed &drm_bridge and
282
+ * &drm_connector with an explicit connector type.
283
+ * @dev: device to tie the bridge lifetime to
284
+ * @panel: The drm_panel being wrapped. Must be non-NULL.
285
+ * @connector_type: The connector type (DRM_MODE_CONNECTOR_*)
286
+ *
287
+ * This is just like devm_drm_panel_bridge_add(), but forces the connector type
288
+ * to @connector_type instead of infering it from the panel.
289
+ *
290
+ * This function is deprecated and should not be used in new drivers. Use
291
+ * devm_drm_panel_bridge_add() instead, and fix panel drivers as necessary if
292
+ * they don't report a connector type.
293
+ */
294
+struct drm_bridge *devm_drm_panel_bridge_add_typed(struct device *dev,
295
+ struct drm_panel *panel,
296
+ u32 connector_type)
216297 {
217298 struct drm_bridge **ptr, *bridge;
218299
....@@ -221,7 +302,7 @@
221302 if (!ptr)
222303 return ERR_PTR(-ENOMEM);
223304
224
- bridge = drm_panel_bridge_add(panel, connector_type);
305
+ bridge = drm_panel_bridge_add_typed(panel, connector_type);
225306 if (!IS_ERR(bridge)) {
226307 *ptr = bridge;
227308 devres_add(dev, ptr);
....@@ -231,4 +312,23 @@
231312
232313 return bridge;
233314 }
234
-EXPORT_SYMBOL(devm_drm_panel_bridge_add);
315
+EXPORT_SYMBOL(devm_drm_panel_bridge_add_typed);
316
+
317
+/**
318
+ * drm_panel_bridge_connector - return the connector for the panel bridge
319
+ * @bridge: The drm_bridge.
320
+ *
321
+ * drm_panel_bridge creates the connector.
322
+ * This function gives external access to the connector.
323
+ *
324
+ * Returns: Pointer to drm_connector
325
+ */
326
+struct drm_connector *drm_panel_bridge_connector(struct drm_bridge *bridge)
327
+{
328
+ struct panel_bridge *panel_bridge;
329
+
330
+ panel_bridge = drm_bridge_to_panel_bridge(bridge);
331
+
332
+ return &panel_bridge->connector;
333
+}
334
+EXPORT_SYMBOL(drm_panel_bridge_connector);