diff options
Diffstat (limited to 'drivers/gpu')
| -rw-r--r-- | drivers/gpu/drm/omapdrm/displays/connector-dvi.c | 8 | ||||
| -rw-r--r-- | drivers/gpu/drm/omapdrm/displays/connector-hdmi.c | 67 | ||||
| -rw-r--r-- | drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c | 3 | ||||
| -rw-r--r-- | drivers/gpu/drm/omapdrm/omap_connector.c | 79 |
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 | ||
| 171 | static void hdmic_unregister_hpd_cb(struct omap_dss_device *dssdev) | 168 | static 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 | ||
| 186 | static void hdmic_enable_hpd(struct omap_dss_device *dssdev) | 181 | static 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 | ||
| 200 | static void hdmic_disable_hpd(struct omap_dss_device *dssdev) | 193 | static 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 | ||
| 214 | static int hdmic_set_hdmi_mode(struct omap_dss_device *dssdev, bool hdmi_mode) | 205 | static 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 | ||
| 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 | ||
