forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-05-13 9d77db3c730780c8ef5ccd4b66403ff5675cfe4e
kernel/drivers/gpu/drm/tegra/rgb.c
....@@ -1,16 +1,14 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Copyright (C) 2012 Avionic Design GmbH
34 * Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved.
4
- *
5
- * This program is free software; you can redistribute it and/or modify
6
- * it under the terms of the GNU General Public License version 2 as
7
- * published by the Free Software Foundation.
85 */
96
107 #include <linux/clk.h>
118
129 #include <drm/drm_atomic_helper.h>
13
-#include <drm/drm_panel.h>
10
+#include <drm/drm_bridge_connector.h>
11
+#include <drm/drm_simple_kms_helper.h>
1412
1513 #include "drm.h"
1614 #include "dc.h"
....@@ -87,49 +85,13 @@
8785 tegra_dc_writel(dc, table[i].value, table[i].offset);
8886 }
8987
90
-static const struct drm_connector_funcs tegra_rgb_connector_funcs = {
91
- .reset = drm_atomic_helper_connector_reset,
92
- .detect = tegra_output_connector_detect,
93
- .fill_modes = drm_helper_probe_single_connector_modes,
94
- .destroy = tegra_output_connector_destroy,
95
- .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
96
- .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
97
-};
98
-
99
-static enum drm_mode_status
100
-tegra_rgb_connector_mode_valid(struct drm_connector *connector,
101
- struct drm_display_mode *mode)
102
-{
103
- /*
104
- * FIXME: For now, always assume that the mode is okay. There are
105
- * unresolved issues with clk_round_rate(), which doesn't always
106
- * reliably report whether a frequency can be set or not.
107
- */
108
- return MODE_OK;
109
-}
110
-
111
-static const struct drm_connector_helper_funcs tegra_rgb_connector_helper_funcs = {
112
- .get_modes = tegra_output_connector_get_modes,
113
- .mode_valid = tegra_rgb_connector_mode_valid,
114
-};
115
-
116
-static const struct drm_encoder_funcs tegra_rgb_encoder_funcs = {
117
- .destroy = tegra_output_encoder_destroy,
118
-};
119
-
12088 static void tegra_rgb_encoder_disable(struct drm_encoder *encoder)
12189 {
12290 struct tegra_output *output = encoder_to_output(encoder);
12391 struct tegra_rgb *rgb = to_rgb(output);
12492
125
- if (output->panel)
126
- drm_panel_disable(output->panel);
127
-
12893 tegra_dc_write_regs(rgb->dc, rgb_disable, ARRAY_SIZE(rgb_disable));
12994 tegra_dc_commit(rgb->dc);
130
-
131
- if (output->panel)
132
- drm_panel_unprepare(output->panel);
13395 }
13496
13597 static void tegra_rgb_encoder_enable(struct drm_encoder *encoder)
....@@ -137,9 +99,6 @@
13799 struct tegra_output *output = encoder_to_output(encoder);
138100 struct tegra_rgb *rgb = to_rgb(output);
139101 u32 value;
140
-
141
- if (output->panel)
142
- drm_panel_prepare(output->panel);
143102
144103 tegra_dc_write_regs(rgb->dc, rgb_enable, ARRAY_SIZE(rgb_enable));
145104
....@@ -162,9 +121,6 @@
162121 tegra_dc_writel(rgb->dc, value, DC_DISP_SHIFT_CLOCK_OPTIONS);
163122
164123 tegra_dc_commit(rgb->dc);
165
-
166
- if (output->panel)
167
- drm_panel_enable(output->panel);
168124 }
169125
170126 static int
....@@ -273,25 +229,68 @@
273229 int tegra_dc_rgb_init(struct drm_device *drm, struct tegra_dc *dc)
274230 {
275231 struct tegra_output *output = dc->rgb;
232
+ struct drm_connector *connector;
276233 int err;
277234
278235 if (!dc->rgb)
279236 return -ENODEV;
280237
281
- drm_connector_init(drm, &output->connector, &tegra_rgb_connector_funcs,
282
- DRM_MODE_CONNECTOR_LVDS);
283
- drm_connector_helper_add(&output->connector,
284
- &tegra_rgb_connector_helper_funcs);
285
- output->connector.dpms = DRM_MODE_DPMS_OFF;
286
-
287
- drm_encoder_init(drm, &output->encoder, &tegra_rgb_encoder_funcs,
288
- DRM_MODE_ENCODER_LVDS, NULL);
238
+ drm_simple_encoder_init(drm, &output->encoder, DRM_MODE_ENCODER_LVDS);
289239 drm_encoder_helper_add(&output->encoder,
290240 &tegra_rgb_encoder_helper_funcs);
291241
292
- drm_connector_attach_encoder(&output->connector,
293
- &output->encoder);
294
- drm_connector_register(&output->connector);
242
+ /*
243
+ * Wrap directly-connected panel into DRM bridge in order to let
244
+ * DRM core to handle panel for us.
245
+ */
246
+ if (output->panel) {
247
+ output->bridge = devm_drm_panel_bridge_add(output->dev,
248
+ output->panel);
249
+ if (IS_ERR(output->bridge)) {
250
+ dev_err(output->dev,
251
+ "failed to wrap panel into bridge: %pe\n",
252
+ output->bridge);
253
+ return PTR_ERR(output->bridge);
254
+ }
255
+
256
+ output->panel = NULL;
257
+ }
258
+
259
+ /*
260
+ * Tegra devices that have LVDS panel utilize LVDS encoder bridge
261
+ * for converting up to 28 LCD LVTTL lanes into 5/4 LVDS lanes that
262
+ * go to display panel's receiver.
263
+ *
264
+ * Encoder usually have a power-down control which needs to be enabled
265
+ * in order to transmit data to the panel. Historically devices that
266
+ * use an older device-tree version didn't model the bridge, assuming
267
+ * that encoder is turned ON by default, while today's DRM allows us
268
+ * to model LVDS encoder properly.
269
+ *
270
+ * Newer device-trees utilize LVDS encoder bridge, which provides
271
+ * us with a connector and handles the display panel.
272
+ *
273
+ * For older device-trees we wrapped panel into the panel-bridge.
274
+ */
275
+ if (output->bridge) {
276
+ err = drm_bridge_attach(&output->encoder, output->bridge,
277
+ NULL, DRM_BRIDGE_ATTACH_NO_CONNECTOR);
278
+ if (err) {
279
+ dev_err(output->dev, "failed to attach bridge: %d\n",
280
+ err);
281
+ return err;
282
+ }
283
+
284
+ connector = drm_bridge_connector_init(drm, &output->encoder);
285
+ if (IS_ERR(connector)) {
286
+ dev_err(output->dev,
287
+ "failed to initialize bridge connector: %pe\n",
288
+ connector);
289
+ return PTR_ERR(connector);
290
+ }
291
+
292
+ drm_connector_attach_encoder(connector, &output->encoder);
293
+ }
295294
296295 err = tegra_output_init(drm, output);
297296 if (err < 0) {