hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/drivers/gpu/drm/omapdrm/omap_connector.c
....@@ -1,23 +1,12 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
34 * Author: Rob Clark <rob@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 <drm/drm_atomic_helper.h>
198 #include <drm/drm_crtc.h>
20
-#include <drm/drm_crtc_helper.h>
9
+#include <drm/drm_probe_helper.h>
2110
2211 #include "omap_drv.h"
2312
....@@ -29,204 +18,95 @@
2918
3019 struct omap_connector {
3120 struct drm_connector base;
32
- struct omap_dss_device *dssdev;
33
- bool hdmi_mode;
21
+ struct omap_dss_device *output;
3422 };
35
-
36
-static void omap_connector_hpd_cb(void *cb_data,
37
- enum drm_connector_status status)
38
-{
39
- struct omap_connector *omap_connector = cb_data;
40
- struct drm_connector *connector = &omap_connector->base;
41
- struct drm_device *dev = connector->dev;
42
- enum drm_connector_status old_status;
43
-
44
- mutex_lock(&dev->mode_config.mutex);
45
- old_status = connector->status;
46
- connector->status = status;
47
- mutex_unlock(&dev->mode_config.mutex);
48
-
49
- if (old_status != status)
50
- drm_kms_helper_hotplug_event(dev);
51
-}
52
-
53
-bool omap_connector_get_hdmi_mode(struct drm_connector *connector)
54
-{
55
- struct omap_connector *omap_connector = to_omap_connector(connector);
56
-
57
- return omap_connector->hdmi_mode;
58
-}
5923
6024 static enum drm_connector_status omap_connector_detect(
6125 struct drm_connector *connector, bool force)
6226 {
63
- struct omap_connector *omap_connector = to_omap_connector(connector);
64
- struct omap_dss_device *dssdev = omap_connector->dssdev;
65
- struct omap_dss_driver *dssdrv = dssdev->driver;
66
- enum drm_connector_status ret;
67
-
68
- if (dssdrv->detect) {
69
- if (dssdrv->detect(dssdev))
70
- ret = connector_status_connected;
71
- else
72
- ret = connector_status_disconnected;
73
- } else if (dssdev->type == OMAP_DISPLAY_TYPE_DPI ||
74
- dssdev->type == OMAP_DISPLAY_TYPE_DBI ||
75
- dssdev->type == OMAP_DISPLAY_TYPE_SDI ||
76
- dssdev->type == OMAP_DISPLAY_TYPE_DSI) {
77
- ret = connector_status_connected;
78
- } else {
79
- ret = connector_status_unknown;
80
- }
81
-
82
- VERB("%s: %d (force=%d)", omap_connector->dssdev->name, ret, force);
83
-
84
- return ret;
27
+ return connector_status_connected;
8528 }
8629
8730 static void omap_connector_destroy(struct drm_connector *connector)
8831 {
8932 struct omap_connector *omap_connector = to_omap_connector(connector);
90
- struct omap_dss_device *dssdev = omap_connector->dssdev;
9133
92
- DBG("%s", omap_connector->dssdev->name);
93
- if (connector->polled == DRM_CONNECTOR_POLL_HPD &&
94
- dssdev->driver->unregister_hpd_cb) {
95
- dssdev->driver->unregister_hpd_cb(dssdev);
96
- }
34
+ DBG("%s", connector->name);
35
+
9736 drm_connector_unregister(connector);
9837 drm_connector_cleanup(connector);
38
+
39
+ omapdss_device_put(omap_connector->output);
40
+
9941 kfree(omap_connector);
100
-
101
- omap_dss_put_device(dssdev);
10242 }
103
-
104
-#define MAX_EDID 512
10543
10644 static int omap_connector_get_modes(struct drm_connector *connector)
10745 {
10846 struct omap_connector *omap_connector = to_omap_connector(connector);
109
- struct omap_dss_device *dssdev = omap_connector->dssdev;
110
- struct omap_dss_driver *dssdrv = dssdev->driver;
111
- struct drm_device *dev = connector->dev;
112
- int n = 0;
47
+ struct omap_dss_device *dssdev = NULL;
48
+ struct omap_dss_device *d;
11349
114
- DBG("%s", omap_connector->dssdev->name);
50
+ DBG("%s", connector->name);
11551
116
- /* if display exposes EDID, then we parse that in the normal way to
117
- * build table of supported modes.. otherwise (ie. fixed resolution
118
- * LCD panels) we just return a single mode corresponding to the
119
- * currently configured timings:
52
+ /*
53
+ * If the display pipeline reports modes (e.g. with a fixed resolution
54
+ * panel or an analog TV output), query it.
12055 */
121
- if (dssdrv->read_edid) {
122
- void *edid = kzalloc(MAX_EDID, GFP_KERNEL);
123
-
124
- if (!edid)
125
- return 0;
126
-
127
- if ((dssdrv->read_edid(dssdev, edid, MAX_EDID) > 0) &&
128
- drm_edid_is_valid(edid)) {
129
- drm_connector_update_edid_property(
130
- connector, edid);
131
- n = drm_add_edid_modes(connector, edid);
132
-
133
- omap_connector->hdmi_mode =
134
- drm_detect_hdmi_monitor(edid);
135
- } else {
136
- drm_connector_update_edid_property(
137
- connector, NULL);
138
- }
139
-
140
- kfree(edid);
141
- } else {
142
- struct drm_display_mode *mode = drm_mode_create(dev);
143
- struct videomode vm = {0};
144
-
145
- if (!mode)
146
- return 0;
147
-
148
- dssdrv->get_timings(dssdev, &vm);
149
-
150
- drm_display_mode_from_videomode(&vm, mode);
151
-
152
- mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
153
- drm_mode_set_name(mode);
154
- drm_mode_probed_add(connector, mode);
155
-
156
- if (dssdrv->get_size) {
157
- dssdrv->get_size(dssdev,
158
- &connector->display_info.width_mm,
159
- &connector->display_info.height_mm);
160
- }
161
-
162
- n = 1;
56
+ for (d = omap_connector->output; d; d = d->next) {
57
+ if (d->ops_flags & OMAP_DSS_DEVICE_OP_MODES)
58
+ dssdev = d;
16359 }
16460
165
- return n;
61
+ if (dssdev)
62
+ return dssdev->ops->get_modes(dssdev, connector);
63
+
64
+ /* We can't retrieve modes. The KMS core will add the default modes. */
65
+ return 0;
16666 }
16767
168
-static int omap_connector_mode_valid(struct drm_connector *connector,
68
+enum drm_mode_status omap_connector_mode_fixup(struct omap_dss_device *dssdev,
69
+ const struct drm_display_mode *mode,
70
+ struct drm_display_mode *adjusted_mode)
71
+{
72
+ int ret;
73
+
74
+ drm_mode_copy(adjusted_mode, mode);
75
+
76
+ for (; dssdev; dssdev = dssdev->next) {
77
+ if (!dssdev->ops || !dssdev->ops->check_timings)
78
+ continue;
79
+
80
+ ret = dssdev->ops->check_timings(dssdev, adjusted_mode);
81
+ if (ret)
82
+ return MODE_BAD;
83
+ }
84
+
85
+ return MODE_OK;
86
+}
87
+
88
+static enum drm_mode_status omap_connector_mode_valid(struct drm_connector *connector,
16989 struct drm_display_mode *mode)
17090 {
17191 struct omap_connector *omap_connector = to_omap_connector(connector);
172
- struct omap_dss_device *dssdev = omap_connector->dssdev;
173
- struct omap_dss_driver *dssdrv = dssdev->driver;
174
- struct videomode vm = {0};
175
- struct drm_device *dev = connector->dev;
176
- struct drm_display_mode *new_mode;
177
- int r, ret = MODE_BAD;
92
+ struct drm_display_mode new_mode = {};
93
+ enum drm_mode_status status;
17894
179
- drm_display_mode_to_videomode(mode, &vm);
180
- mode->vrefresh = drm_mode_vrefresh(mode);
95
+ status = omap_connector_mode_fixup(omap_connector->output, mode,
96
+ &new_mode);
97
+ if (status != MODE_OK)
98
+ goto done;
18199
182
- /*
183
- * if the panel driver doesn't have a check_timings, it's most likely
184
- * a fixed resolution panel, check if the timings match with the
185
- * panel's timings
186
- */
187
- if (dssdrv->check_timings) {
188
- r = dssdrv->check_timings(dssdev, &vm);
189
- } else {
190
- struct videomode t = {0};
100
+ /* Check if vrefresh is still valid. */
101
+ if (drm_mode_vrefresh(mode) != drm_mode_vrefresh(&new_mode))
102
+ status = MODE_NOCLOCK;
191103
192
- dssdrv->get_timings(dssdev, &t);
104
+done:
105
+ DBG("connector: mode %s: " DRM_MODE_FMT,
106
+ (status == MODE_OK) ? "valid" : "invalid",
107
+ DRM_MODE_ARG(mode));
193108
194
- /*
195
- * Ignore the flags, as we don't get them from
196
- * drm_display_mode_to_videomode.
197
- */
198
- t.flags = 0;
199
-
200
- if (memcmp(&vm, &t, sizeof(vm)))
201
- r = -EINVAL;
202
- else
203
- r = 0;
204
- }
205
-
206
- if (!r) {
207
- /* check if vrefresh is still valid */
208
- new_mode = drm_mode_duplicate(dev, mode);
209
-
210
- if (!new_mode)
211
- return MODE_BAD;
212
-
213
- new_mode->clock = vm.pixelclock / 1000;
214
- new_mode->vrefresh = 0;
215
- if (mode->vrefresh == drm_mode_vrefresh(new_mode))
216
- ret = MODE_OK;
217
- drm_mode_destroy(dev, new_mode);
218
- }
219
-
220
- DBG("connector: mode %s: "
221
- "%d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x",
222
- (ret == MODE_OK) ? "valid" : "invalid",
223
- mode->base.id, mode->name, mode->vrefresh, mode->clock,
224
- mode->hdisplay, mode->hsync_start,
225
- mode->hsync_end, mode->htotal,
226
- mode->vdisplay, mode->vsync_start,
227
- mode->vsync_end, mode->vtotal, mode->type, mode->flags);
228
-
229
- return ret;
109
+ return status;
230110 }
231111
232112 static const struct drm_connector_funcs omap_connector_funcs = {
....@@ -245,51 +125,28 @@
245125
246126 /* initialize connector */
247127 struct drm_connector *omap_connector_init(struct drm_device *dev,
248
- int connector_type, struct omap_dss_device *dssdev,
249
- struct drm_encoder *encoder)
128
+ struct omap_dss_device *output,
129
+ struct drm_encoder *encoder)
250130 {
251131 struct drm_connector *connector = NULL;
252132 struct omap_connector *omap_connector;
253
- bool hpd_supported = false;
254133
255
- DBG("%s", dssdev->name);
256
-
257
- omap_dss_get_device(dssdev);
134
+ DBG("%s", output->name);
258135
259136 omap_connector = kzalloc(sizeof(*omap_connector), GFP_KERNEL);
260137 if (!omap_connector)
261138 goto fail;
262139
263
- omap_connector->dssdev = dssdev;
140
+ omap_connector->output = omapdss_device_get(output);
264141
265142 connector = &omap_connector->base;
266
-
267
- drm_connector_init(dev, connector, &omap_connector_funcs,
268
- connector_type);
269
- drm_connector_helper_add(connector, &omap_connector_helper_funcs);
270
-
271
- if (dssdev->driver->register_hpd_cb) {
272
- int ret = dssdev->driver->register_hpd_cb(dssdev,
273
- omap_connector_hpd_cb,
274
- omap_connector);
275
- if (!ret)
276
- hpd_supported = true;
277
- else if (ret != -ENOTSUPP)
278
- DBG("%s: Failed to register HPD callback (%d).",
279
- dssdev->name, ret);
280
- }
281
-
282
- if (hpd_supported)
283
- connector->polled = DRM_CONNECTOR_POLL_HPD;
284
- else if (dssdev->driver->detect)
285
- connector->polled = DRM_CONNECTOR_POLL_CONNECT |
286
- DRM_CONNECTOR_POLL_DISCONNECT;
287
- else
288
- connector->polled = 0;
289
-
290143 connector->interlace_allowed = 1;
291144 connector->doublescan_allowed = 0;
292145
146
+ drm_connector_init(dev, connector, &omap_connector_funcs,
147
+ DRM_MODE_CONNECTOR_DSI);
148
+ drm_connector_helper_add(connector, &omap_connector_helper_funcs);
149
+
293150 return connector;
294151
295152 fail: