aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/omapdrm/displays/connector-dvi.c8
-rw-r--r--drivers/gpu/drm/omapdrm/displays/connector-hdmi.c67
-rw-r--r--drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c3
-rw-r--r--drivers/gpu/drm/omapdrm/omap_connector.c79
4 files changed, 88 insertions, 69 deletions
diff --git a/drivers/gpu/drm/omapdrm/displays/connector-dvi.c b/drivers/gpu/drm/omapdrm/displays/connector-dvi.c
index f1674b3eee50..e9353e4cd297 100644
--- a/drivers/gpu/drm/omapdrm/displays/connector-dvi.c
+++ b/drivers/gpu/drm/omapdrm/displays/connector-dvi.c
@@ -372,8 +372,12 @@ static int dvic_probe(struct platform_device *pdev)
372 dssdev->type = OMAP_DISPLAY_TYPE_DVI; 372 dssdev->type = OMAP_DISPLAY_TYPE_DVI;
373 dssdev->owner = THIS_MODULE; 373 dssdev->owner = THIS_MODULE;
374 dssdev->of_ports = BIT(0); 374 dssdev->of_ports = BIT(0);
375 dssdev->ops_flags = ddata->hpd_gpio || ddata->i2c_adapter 375
376 ? OMAP_DSS_DEVICE_OP_DETECT : 0; 376 if (ddata->hpd_gpio)
377 dssdev->ops_flags = OMAP_DSS_DEVICE_OP_DETECT
378 | OMAP_DSS_DEVICE_OP_HPD;
379 else if (ddata->i2c_adapter)
380 dssdev->ops_flags = OMAP_DSS_DEVICE_OP_DETECT;
377 381
378 omapdss_display_init(dssdev); 382 omapdss_display_init(dssdev);
379 omapdss_device_register(dssdev); 383 omapdss_device_register(dssdev);
diff --git a/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c b/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c
index 0d22d7004c98..8eae973474dd 100644
--- a/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c
+++ b/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c
@@ -153,62 +153,53 @@ static int hdmic_register_hpd_cb(struct omap_dss_device *dssdev,
153 void *cb_data) 153 void *cb_data)
154{ 154{
155 struct panel_drv_data *ddata = to_panel_data(dssdev); 155 struct panel_drv_data *ddata = to_panel_data(dssdev);
156 struct omap_dss_device *src = dssdev->src;
157 156
158 if (ddata->hpd_gpio) { 157 if (!ddata->hpd_gpio)
159 mutex_lock(&ddata->hpd_lock); 158 return -ENOTSUPP;
160 ddata->hpd_cb = cb;
161 ddata->hpd_cb_data = cb_data;
162 mutex_unlock(&ddata->hpd_lock);
163 return 0;
164 } else if (src->ops->register_hpd_cb) {
165 return src->ops->register_hpd_cb(src, cb, cb_data);
166 }
167 159
168 return -ENOTSUPP; 160 mutex_lock(&ddata->hpd_lock);
161 ddata->hpd_cb = cb;
162 ddata->hpd_cb_data = cb_data;
163 mutex_unlock(&ddata->hpd_lock);
164
165 return 0;
169} 166}
170 167
171static void hdmic_unregister_hpd_cb(struct omap_dss_device *dssdev) 168static void hdmic_unregister_hpd_cb(struct omap_dss_device *dssdev)
172{ 169{
173 struct panel_drv_data *ddata = to_panel_data(dssdev); 170 struct panel_drv_data *ddata = to_panel_data(dssdev);
174 struct omap_dss_device *src = dssdev->src;
175 171
176 if (ddata->hpd_gpio) { 172 if (!ddata->hpd_gpio)
177 mutex_lock(&ddata->hpd_lock); 173 return;
178 ddata->hpd_cb = NULL; 174
179 ddata->hpd_cb_data = NULL; 175 mutex_lock(&ddata->hpd_lock);
180 mutex_unlock(&ddata->hpd_lock); 176 ddata->hpd_cb = NULL;
181 } else if (src->ops->unregister_hpd_cb) { 177 ddata->hpd_cb_data = NULL;
182 src->ops->unregister_hpd_cb(src); 178 mutex_unlock(&ddata->hpd_lock);
183 }
184} 179}
185 180
186static void hdmic_enable_hpd(struct omap_dss_device *dssdev) 181static void hdmic_enable_hpd(struct omap_dss_device *dssdev)
187{ 182{
188 struct panel_drv_data *ddata = to_panel_data(dssdev); 183 struct panel_drv_data *ddata = to_panel_data(dssdev);
189 struct omap_dss_device *src = dssdev->src;
190 184
191 if (ddata->hpd_gpio) { 185 if (!ddata->hpd_gpio)
192 mutex_lock(&ddata->hpd_lock); 186 return;
193 ddata->hpd_enabled = true; 187
194 mutex_unlock(&ddata->hpd_lock); 188 mutex_lock(&ddata->hpd_lock);
195 } else if (src->ops->enable_hpd) { 189 ddata->hpd_enabled = true;
196 src->ops->enable_hpd(src); 190 mutex_unlock(&ddata->hpd_lock);
197 }
198} 191}
199 192
200static void hdmic_disable_hpd(struct omap_dss_device *dssdev) 193static void hdmic_disable_hpd(struct omap_dss_device *dssdev)
201{ 194{
202 struct panel_drv_data *ddata = to_panel_data(dssdev); 195 struct panel_drv_data *ddata = to_panel_data(dssdev);
203 struct omap_dss_device *src = dssdev->src;
204 196
205 if (ddata->hpd_gpio) { 197 if (!ddata->hpd_gpio)
206 mutex_lock(&ddata->hpd_lock); 198 return;
207 ddata->hpd_enabled = false; 199
208 mutex_unlock(&ddata->hpd_lock); 200 mutex_lock(&ddata->hpd_lock);
209 } else if (src->ops->disable_hpd) { 201 ddata->hpd_enabled = false;
210 src->ops->disable_hpd(src); 202 mutex_unlock(&ddata->hpd_lock);
211 }
212} 203}
213 204
214static int hdmic_set_hdmi_mode(struct omap_dss_device *dssdev, bool hdmi_mode) 205static int hdmic_set_hdmi_mode(struct omap_dss_device *dssdev, bool hdmi_mode)
@@ -314,7 +305,9 @@ static int hdmic_probe(struct platform_device *pdev)
314 dssdev->type = OMAP_DISPLAY_TYPE_HDMI; 305 dssdev->type = OMAP_DISPLAY_TYPE_HDMI;
315 dssdev->owner = THIS_MODULE; 306 dssdev->owner = THIS_MODULE;
316 dssdev->of_ports = BIT(0); 307 dssdev->of_ports = BIT(0);
317 dssdev->ops_flags = ddata->hpd_gpio ? OMAP_DSS_DEVICE_OP_DETECT : 0; 308 dssdev->ops_flags = ddata->hpd_gpio
309 ? OMAP_DSS_DEVICE_OP_DETECT | OMAP_DSS_DEVICE_OP_HPD
310 : 0;
318 311
319 omapdss_display_init(dssdev); 312 omapdss_display_init(dssdev);
320 omapdss_device_register(dssdev); 313 omapdss_device_register(dssdev);
diff --git a/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c b/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c
index e30ead0cacb7..f6d4f90f2c08 100644
--- a/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c
+++ b/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c
@@ -289,7 +289,8 @@ static int tpd_probe(struct platform_device *pdev)
289 dssdev->output_type = OMAP_DISPLAY_TYPE_HDMI; 289 dssdev->output_type = OMAP_DISPLAY_TYPE_HDMI;
290 dssdev->owner = THIS_MODULE; 290 dssdev->owner = THIS_MODULE;
291 dssdev->of_ports = BIT(1) | BIT(0); 291 dssdev->of_ports = BIT(1) | BIT(0);
292 dssdev->ops_flags = OMAP_DSS_DEVICE_OP_DETECT; 292 dssdev->ops_flags = OMAP_DSS_DEVICE_OP_DETECT
293 | OMAP_DSS_DEVICE_OP_HPD;
293 294
294 dssdev->next = omapdss_of_find_connected_device(pdev->dev.of_node, 1); 295 dssdev->next = omapdss_of_find_connected_device(pdev->dev.of_node, 1);
295 if (IS_ERR(dssdev->next)) { 296 if (IS_ERR(dssdev->next)) {
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