hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Driver for MegaChips STDP4028 with GE B850v3 firmware (LVDS-DP)
34 * Driver for MegaChips STDP2690 with GE B850v3 firmware (DP-DP++)
....@@ -5,17 +6,6 @@
56 * Copyright (c) 2017, Collabora Ltd.
67 * Copyright (c) 2017, General Electric Company
78
8
- * This program is free software; you can redistribute it and/or modify it
9
- * under the terms and conditions of the GNU General Public License,
10
- * version 2, as published by the Free Software Foundation.
11
-
12
- * This program is distributed in the hope it will be useful, but WITHOUT
13
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15
- * more details.
16
-
17
- * You should have received a copy of the GNU General Public License
18
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
199
2010 * This driver creates a drm_bridge and a drm_connector for the LVDS to DP++
2111 * display bridge of the GE B850v3. There are two physical bridges on the video
....@@ -27,18 +17,18 @@
2717 * signal pipeline is as follows:
2818 *
2919 * Host -> LVDS|--(STDP4028)--|DP -> DP|--(STDP2690)--|DP++ -> Video output
30
- *
3120 */
3221
33
-#include <linux/gpio.h>
3422 #include <linux/i2c.h>
3523 #include <linux/module.h>
3624 #include <linux/of.h>
25
+
3726 #include <drm/drm_atomic.h>
3827 #include <drm/drm_atomic_helper.h>
39
-#include <drm/drm_crtc_helper.h>
28
+#include <drm/drm_bridge.h>
4029 #include <drm/drm_edid.h>
41
-#include <drm/drmP.h>
30
+#include <drm/drm_print.h>
31
+#include <drm/drm_probe_helper.h>
4232
4333 #define EDID_EXT_BLOCK_CNT 0x7E
4434
....@@ -71,7 +61,6 @@
7161 struct drm_bridge bridge;
7262 struct i2c_client *stdp4028_i2c;
7363 struct i2c_client *stdp2690_i2c;
74
- struct edid *edid;
7564 };
7665
7766 static struct ge_b850v3_lvds *ge_b850v3_lvds_ptr;
....@@ -141,22 +130,26 @@
141130 return NULL;
142131 }
143132
144
-static int ge_b850v3_lvds_get_modes(struct drm_connector *connector)
133
+static struct edid *ge_b850v3_lvds_get_edid(struct drm_bridge *bridge,
134
+ struct drm_connector *connector)
145135 {
146136 struct i2c_client *client;
147
- int num_modes = 0;
148137
149138 client = ge_b850v3_lvds_ptr->stdp2690_i2c;
150139
151
- kfree(ge_b850v3_lvds_ptr->edid);
152
- ge_b850v3_lvds_ptr->edid = (struct edid *)stdp2690_get_edid(client);
140
+ return (struct edid *)stdp2690_get_edid(client);
141
+}
153142
154
- if (ge_b850v3_lvds_ptr->edid) {
155
- drm_connector_update_edid_property(connector,
156
- ge_b850v3_lvds_ptr->edid);
157
- num_modes = drm_add_edid_modes(connector,
158
- ge_b850v3_lvds_ptr->edid);
159
- }
143
+static int ge_b850v3_lvds_get_modes(struct drm_connector *connector)
144
+{
145
+ struct edid *edid;
146
+ int num_modes;
147
+
148
+ edid = ge_b850v3_lvds_get_edid(&ge_b850v3_lvds_ptr->bridge, connector);
149
+
150
+ drm_connector_update_edid_property(connector, edid);
151
+ num_modes = drm_add_edid_modes(connector, edid);
152
+ kfree(edid);
160153
161154 return num_modes;
162155 }
....@@ -173,8 +166,7 @@
173166 .mode_valid = ge_b850v3_lvds_mode_valid,
174167 };
175168
176
-static enum drm_connector_status ge_b850v3_lvds_detect(
177
- struct drm_connector *connector, bool force)
169
+static enum drm_connector_status ge_b850v3_lvds_bridge_detect(struct drm_bridge *bridge)
178170 {
179171 struct i2c_client *stdp4028_i2c =
180172 ge_b850v3_lvds_ptr->stdp4028_i2c;
....@@ -192,6 +184,12 @@
192184 return connector_status_unknown;
193185 }
194186
187
+static enum drm_connector_status ge_b850v3_lvds_detect(struct drm_connector *connector,
188
+ bool force)
189
+{
190
+ return ge_b850v3_lvds_bridge_detect(&ge_b850v3_lvds_ptr->bridge);
191
+}
192
+
195193 static const struct drm_connector_funcs ge_b850v3_lvds_connector_funcs = {
196194 .fill_modes = drm_helper_probe_single_connector_modes,
197195 .detect = ge_b850v3_lvds_detect,
....@@ -201,26 +199,9 @@
201199 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
202200 };
203201
204
-static irqreturn_t ge_b850v3_lvds_irq_handler(int irq, void *dev_id)
205
-{
206
- struct i2c_client *stdp4028_i2c
207
- = ge_b850v3_lvds_ptr->stdp4028_i2c;
208
-
209
- i2c_smbus_write_word_data(stdp4028_i2c,
210
- STDP4028_DPTX_IRQ_STS_REG,
211
- STDP4028_DPTX_IRQ_CLEAR);
212
-
213
- if (ge_b850v3_lvds_ptr->connector.dev)
214
- drm_kms_helper_hotplug_event(ge_b850v3_lvds_ptr->connector.dev);
215
-
216
- return IRQ_HANDLED;
217
-}
218
-
219
-static int ge_b850v3_lvds_attach(struct drm_bridge *bridge)
202
+static int ge_b850v3_lvds_create_connector(struct drm_bridge *bridge)
220203 {
221204 struct drm_connector *connector = &ge_b850v3_lvds_ptr->connector;
222
- struct i2c_client *stdp4028_i2c
223
- = ge_b850v3_lvds_ptr->stdp4028_i2c;
224205 int ret;
225206
226207 if (!bridge->encoder) {
....@@ -241,9 +222,29 @@
241222 return ret;
242223 }
243224
244
- ret = drm_connector_attach_encoder(connector, bridge->encoder);
245
- if (ret)
246
- return ret;
225
+ return drm_connector_attach_encoder(connector, bridge->encoder);
226
+}
227
+
228
+static irqreturn_t ge_b850v3_lvds_irq_handler(int irq, void *dev_id)
229
+{
230
+ struct i2c_client *stdp4028_i2c
231
+ = ge_b850v3_lvds_ptr->stdp4028_i2c;
232
+
233
+ i2c_smbus_write_word_data(stdp4028_i2c,
234
+ STDP4028_DPTX_IRQ_STS_REG,
235
+ STDP4028_DPTX_IRQ_CLEAR);
236
+
237
+ if (ge_b850v3_lvds_ptr->bridge.dev)
238
+ drm_kms_helper_hotplug_event(ge_b850v3_lvds_ptr->bridge.dev);
239
+
240
+ return IRQ_HANDLED;
241
+}
242
+
243
+static int ge_b850v3_lvds_attach(struct drm_bridge *bridge,
244
+ enum drm_bridge_attach_flags flags)
245
+{
246
+ struct i2c_client *stdp4028_i2c
247
+ = ge_b850v3_lvds_ptr->stdp4028_i2c;
247248
248249 /* Configures the bridge to re-enable interrupts after each ack. */
249250 i2c_smbus_write_word_data(stdp4028_i2c,
....@@ -255,11 +256,16 @@
255256 STDP4028_DPTX_IRQ_EN_REG,
256257 STDP4028_DPTX_IRQ_CONFIG);
257258
258
- return 0;
259
+ if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
260
+ return 0;
261
+
262
+ return ge_b850v3_lvds_create_connector(bridge);
259263 }
260264
261265 static const struct drm_bridge_funcs ge_b850v3_lvds_funcs = {
262266 .attach = ge_b850v3_lvds_attach,
267
+ .detect = ge_b850v3_lvds_bridge_detect,
268
+ .get_edid = ge_b850v3_lvds_get_edid,
263269 };
264270
265271 static int ge_b850v3_lvds_init(struct device *dev)
....@@ -290,12 +296,12 @@
290296 * This check is to avoid both the drivers
291297 * removing the bridge in their remove() function
292298 */
293
- if (!ge_b850v3_lvds_ptr)
299
+ if (!ge_b850v3_lvds_ptr ||
300
+ !ge_b850v3_lvds_ptr->stdp2690_i2c ||
301
+ !ge_b850v3_lvds_ptr->stdp4028_i2c)
294302 goto out;
295303
296304 drm_bridge_remove(&ge_b850v3_lvds_ptr->bridge);
297
-
298
- kfree(ge_b850v3_lvds_ptr->edid);
299305
300306 ge_b850v3_lvds_ptr = NULL;
301307 out:
....@@ -309,6 +315,9 @@
309315
310316 /* drm bridge initialization */
311317 ge_b850v3_lvds_ptr->bridge.funcs = &ge_b850v3_lvds_funcs;
318
+ ge_b850v3_lvds_ptr->bridge.ops = DRM_BRIDGE_OP_DETECT |
319
+ DRM_BRIDGE_OP_EDID;
320
+ ge_b850v3_lvds_ptr->bridge.type = DRM_MODE_CONNECTOR_DisplayPort;
312321 ge_b850v3_lvds_ptr->bridge.of_node = dev->of_node;
313322 drm_bridge_add(&ge_b850v3_lvds_ptr->bridge);
314323
....@@ -435,7 +444,11 @@
435444 if (ret)
436445 return ret;
437446
438
- return i2c_add_driver(&stdp2690_ge_b850v3_fw_driver);
447
+ ret = i2c_add_driver(&stdp2690_ge_b850v3_fw_driver);
448
+ if (ret)
449
+ i2c_del_driver(&stdp4028_ge_b850v3_fw_driver);
450
+
451
+ return ret;
439452 }
440453 module_init(stdpxxxx_ge_b850v3_init);
441454