aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/omapdrm/omap_connector.c
diff options
context:
space:
mode:
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