aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/omapdrm
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
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')
-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