aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/omapdrm/omap_connector.c
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>2018-05-30 11:49:48 -0400
committerTomi Valkeinen <tomi.valkeinen@ti.com>2018-09-03 09:13:29 -0400
commit949ea2ef3fed4e1d0f9b80ec21ed81a9833ac248 (patch)
tree8ff15fc93638323033366a6571c04c72d441e1ff /drivers/gpu/drm/omapdrm/omap_connector.c
parentf2ea55775e0591aa292e2e8d9707d0196df73d61 (diff)
drm/omap: Don't call HPD registration operations recursively
Instead of calling the hot-plug detection callback registration operations (.register_hpd_cb() and .unregister_hpd_cb()) recursively from the display device back to the first device that provides hot plug detection support, iterate over the devices manually in the DRM connector code. This moves the complexity to a single central location and simplifies the logic in omap_dss_device drivers. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Sebastian Reichel <sebastian.reichel@collabora.co.uk> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Diffstat (limited to 'drivers/gpu/drm/omapdrm/omap_connector.c')
-rw-r--r--drivers/gpu/drm/omapdrm/omap_connector.c79
1 files changed, 50 insertions, 29 deletions
diff --git a/drivers/gpu/drm/omapdrm/omap_connector.c b/drivers/gpu/drm/omapdrm/omap_connector.c
index 4729af395156..05734c908aae 100644
--- a/drivers/gpu/drm/omapdrm/omap_connector.c
+++ b/drivers/gpu/drm/omapdrm/omap_connector.c
@@ -57,6 +57,21 @@ bool omap_connector_get_hdmi_mode(struct drm_connector *connector)
57 return omap_connector->hdmi_mode; 57 return omap_connector->hdmi_mode;
58} 58}
59 59
60static struct omap_dss_device *
61omap_connector_find_device(struct drm_connector *connector,
62 enum omap_dss_device_ops_flag op)
63{
64 struct omap_connector *omap_connector = to_omap_connector(connector);
65 struct omap_dss_device *dssdev;
66
67 for (dssdev = omap_connector->dssdev; dssdev; dssdev = dssdev->src) {
68 if (dssdev->ops_flags & op)
69 return dssdev;
70 }
71
72 return NULL;
73}
74
60static enum drm_connector_status omap_connector_detect( 75static enum drm_connector_status omap_connector_detect(
61 struct drm_connector *connector, bool force) 76 struct drm_connector *connector, bool force)
62{ 77{
@@ -64,10 +79,8 @@ static enum drm_connector_status omap_connector_detect(
64 struct omap_dss_device *dssdev; 79 struct omap_dss_device *dssdev;
65 enum drm_connector_status status; 80 enum drm_connector_status status;
66 81
67 for (dssdev = omap_connector->dssdev; dssdev; dssdev = dssdev->src) { 82 dssdev = omap_connector_find_device(connector,
68 if (dssdev->ops_flags & OMAP_DSS_DEVICE_OP_DETECT) 83 OMAP_DSS_DEVICE_OP_DETECT);
69 break;
70 }
71 84
72 if (dssdev) { 85 if (dssdev) {
73 if (dssdev->ops->detect(dssdev)) 86 if (dssdev->ops->detect(dssdev))
@@ -96,18 +109,21 @@ static enum drm_connector_status omap_connector_detect(
96static void omap_connector_destroy(struct drm_connector *connector) 109static void omap_connector_destroy(struct drm_connector *connector)
97{ 110{
98 struct omap_connector *omap_connector = to_omap_connector(connector); 111 struct omap_connector *omap_connector = to_omap_connector(connector);
99 struct omap_dss_device *dssdev = omap_connector->dssdev; 112 struct omap_dss_device *dssdev;
100 113
101 DBG("%s", omap_connector->dssdev->name); 114 DBG("%s", omap_connector->dssdev->name);
102 if (connector->polled == DRM_CONNECTOR_POLL_HPD && 115
103 dssdev->ops->unregister_hpd_cb) { 116 if (connector->polled == DRM_CONNECTOR_POLL_HPD) {
117 dssdev = omap_connector_find_device(connector,
118 OMAP_DSS_DEVICE_OP_HPD);
104 dssdev->ops->unregister_hpd_cb(dssdev); 119 dssdev->ops->unregister_hpd_cb(dssdev);
105 } 120 }
121
106 drm_connector_unregister(connector); 122 drm_connector_unregister(connector);
107 drm_connector_cleanup(connector); 123 drm_connector_cleanup(connector);
108 kfree(omap_connector); 124 kfree(omap_connector);
109 125
110 omapdss_device_put(dssdev); 126 omapdss_device_put(omap_connector->dssdev);
111} 127}
112 128
113#define MAX_EDID 512 129#define MAX_EDID 512
@@ -257,45 +273,50 @@ struct drm_connector *omap_connector_init(struct drm_device *dev,
257{ 273{
258 struct drm_connector *connector = NULL; 274 struct drm_connector *connector = NULL;
259 struct omap_connector *omap_connector; 275 struct omap_connector *omap_connector;
260 bool hpd_supported = false;
261 276
262 DBG("%s", dssdev->name); 277 DBG("%s", dssdev->name);
263 278
264 omapdss_device_get(dssdev);
265
266 omap_connector = kzalloc(sizeof(*omap_connector), GFP_KERNEL); 279 omap_connector = kzalloc(sizeof(*omap_connector), GFP_KERNEL);
267 if (!omap_connector) 280 if (!omap_connector)
268 goto fail; 281 goto fail;
269 282
270 omap_connector->dssdev = dssdev; 283 omap_connector->dssdev = omapdss_device_get(dssdev);
271 284
272 connector = &omap_connector->base; 285 connector = &omap_connector->base;
286 connector->interlace_allowed = 1;
287 connector->doublescan_allowed = 0;
273 288
274 drm_connector_init(dev, connector, &omap_connector_funcs, 289 drm_connector_init(dev, connector, &omap_connector_funcs,
275 connector_type); 290 connector_type);
276 drm_connector_helper_add(connector, &omap_connector_helper_funcs); 291 drm_connector_helper_add(connector, &omap_connector_helper_funcs);
277 292
278 if (dssdev->ops->register_hpd_cb) { 293 /*
279 int ret = dssdev->ops->register_hpd_cb(dssdev, 294 * Initialize connector status handling. First try to find a device that
280 omap_connector_hpd_cb, 295 * supports hot-plug reporting. If it fails, fall back to a device that
281 omap_connector); 296 * support polling. If that fails too, we don't support hot-plug
282 if (!ret) 297 * detection at all.
283 hpd_supported = true; 298 */
284 else if (ret != -ENOTSUPP) 299 dssdev = omap_connector_find_device(connector, OMAP_DSS_DEVICE_OP_HPD);
300 if (dssdev) {
301 int ret;
302
303 ret = dssdev->ops->register_hpd_cb(dssdev,
304 omap_connector_hpd_cb,
305 omap_connector);
306 if (ret < 0)
285 DBG("%s: Failed to register HPD callback (%d).", 307 DBG("%s: Failed to register HPD callback (%d).",
286 dssdev->name, ret); 308 dssdev->name, ret);
309 else
310 connector->polled = DRM_CONNECTOR_POLL_HPD;
287 } 311 }
288 312
289 if (hpd_supported) 313 if (!connector->polled) {
290 connector->polled = DRM_CONNECTOR_POLL_HPD; 314 dssdev = omap_connector_find_device(connector,
291 else if (dssdev->ops->detect) 315 OMAP_DSS_DEVICE_OP_DETECT);
292 connector->polled = DRM_CONNECTOR_POLL_CONNECT | 316 if (dssdev)
293 DRM_CONNECTOR_POLL_DISCONNECT; 317 connector->polled = DRM_CONNECTOR_POLL_CONNECT |
294 else 318 DRM_CONNECTOR_POLL_DISCONNECT;
295 connector->polled = 0; 319 }
296
297 connector->interlace_allowed = 1;
298 connector->doublescan_allowed = 0;
299 320
300 return connector; 321 return connector;
301 322