diff options
Diffstat (limited to 'drivers/gpu/drm/omapdrm/omap_connector.c')
-rw-r--r-- | drivers/gpu/drm/omapdrm/omap_connector.c | 79 |
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 | ||
60 | static struct omap_dss_device * | ||
61 | omap_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 | |||
60 | static enum drm_connector_status omap_connector_detect( | 75 | static 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( | |||
96 | static void omap_connector_destroy(struct drm_connector *connector) | 109 | static 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 | ||