diff options
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/drm/omapdrm/dss/omapdss.h | 17 | ||||
-rw-r--r-- | drivers/gpu/drm/omapdrm/omap_connector.c | 37 | ||||
-rw-r--r-- | drivers/gpu/drm/omapdrm/omap_drv.c | 29 |
3 files changed, 82 insertions, 1 deletions
diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss.h b/drivers/gpu/drm/omapdrm/dss/omapdss.h index 85953a0bc7c2..b9b0bb27069a 100644 --- a/drivers/gpu/drm/omapdrm/dss/omapdss.h +++ b/drivers/gpu/drm/omapdrm/dss/omapdss.h @@ -25,6 +25,7 @@ #include <video/videomode.h> #include <linux/platform_data/omapdss.h> #include <uapi/drm/drm_mode.h> +#include <drm/drm_crtc.h> #define DISPC_IRQ_FRAMEDONE (1 << 0) #define DISPC_IRQ_VSYNC (1 << 1) @@ -403,6 +404,14 @@ struct omapdss_hdmi_ops { int (*read_edid)(struct omap_dss_device *dssdev, u8 *buf, int len); bool (*detect)(struct omap_dss_device *dssdev); + int (*register_hpd_cb)(struct omap_dss_device *dssdev, + void (*cb)(void *cb_data, + enum drm_connector_status status), + void *cb_data); + void (*unregister_hpd_cb)(struct omap_dss_device *dssdev); + void (*enable_hpd)(struct omap_dss_device *dssdev); + void (*disable_hpd)(struct omap_dss_device *dssdev); + int (*set_hdmi_mode)(struct omap_dss_device *dssdev, bool hdmi_mode); int (*set_infoframe)(struct omap_dss_device *dssdev, const struct hdmi_avi_infoframe *avi); @@ -567,6 +576,14 @@ struct omap_dss_driver { int (*read_edid)(struct omap_dss_device *dssdev, u8 *buf, int len); bool (*detect)(struct omap_dss_device *dssdev); + int (*register_hpd_cb)(struct omap_dss_device *dssdev, + void (*cb)(void *cb_data, + enum drm_connector_status status), + void *cb_data); + void (*unregister_hpd_cb)(struct omap_dss_device *dssdev); + void (*enable_hpd)(struct omap_dss_device *dssdev); + void (*disable_hpd)(struct omap_dss_device *dssdev); + int (*set_hdmi_mode)(struct omap_dss_device *dssdev, bool hdmi_mode); int (*set_hdmi_infoframe)(struct omap_dss_device *dssdev, const struct hdmi_avi_infoframe *avi); diff --git a/drivers/gpu/drm/omapdrm/omap_connector.c b/drivers/gpu/drm/omapdrm/omap_connector.c index d1ec76ef5cc6..aa5ba9ae2191 100644 --- a/drivers/gpu/drm/omapdrm/omap_connector.c +++ b/drivers/gpu/drm/omapdrm/omap_connector.c @@ -35,6 +35,23 @@ struct omap_connector { bool hdmi_mode; }; +static void omap_connector_hpd_cb(void *cb_data, + enum drm_connector_status status) +{ + struct omap_connector *omap_connector = cb_data; + struct drm_connector *connector = &omap_connector->base; + struct drm_device *dev = connector->dev; + enum drm_connector_status old_status; + + mutex_lock(&dev->mode_config.mutex); + old_status = connector->status; + connector->status = status; + mutex_unlock(&dev->mode_config.mutex); + + if (old_status != status) + drm_kms_helper_hotplug_event(dev); +} + bool omap_connector_get_hdmi_mode(struct drm_connector *connector) { struct omap_connector *omap_connector = to_omap_connector(connector); @@ -75,6 +92,10 @@ static void omap_connector_destroy(struct drm_connector *connector) struct omap_dss_device *dssdev = omap_connector->dssdev; DBG("%s", omap_connector->dssdev->name); + if (connector->polled == DRM_CONNECTOR_POLL_HPD && + dssdev->driver->unregister_hpd_cb) { + dssdev->driver->unregister_hpd_cb(dssdev); + } drm_connector_unregister(connector); drm_connector_cleanup(connector); kfree(omap_connector); @@ -215,6 +236,7 @@ struct drm_connector *omap_connector_init(struct drm_device *dev, { struct drm_connector *connector = NULL; struct omap_connector *omap_connector; + bool hpd_supported = false; DBG("%s", dssdev->name); @@ -232,7 +254,20 @@ struct drm_connector *omap_connector_init(struct drm_device *dev, connector_type); drm_connector_helper_add(connector, &omap_connector_helper_funcs); - if (dssdev->driver->detect) + if (dssdev->driver->register_hpd_cb) { + int ret = dssdev->driver->register_hpd_cb(dssdev, + omap_connector_hpd_cb, + omap_connector); + if (!ret) + hpd_supported = true; + else if (ret != -ENOTSUPP) + DBG("%s: Failed to register HPD callback (%d).", + dssdev->name, ret); + } + + if (hpd_supported) + connector->polled = DRM_CONNECTOR_POLL_HPD; + else if (dssdev->driver->detect) connector->polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT; else diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c index 721a358531b0..10e24ca928f2 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.c +++ b/drivers/gpu/drm/omapdrm/omap_drv.c @@ -324,6 +324,32 @@ static int omap_modeset_init(struct drm_device *dev) } /* + * Enable the HPD in external components if supported + */ +static void omap_modeset_enable_external_hpd(void) +{ + struct omap_dss_device *dssdev = NULL; + + for_each_dss_dev(dssdev) { + if (dssdev->driver->enable_hpd) + dssdev->driver->enable_hpd(dssdev); + } +} + +/* + * Disable the HPD in external components if supported + */ +static void omap_modeset_disable_external_hpd(void) +{ + struct omap_dss_device *dssdev = NULL; + + for_each_dss_dev(dssdev) { + if (dssdev->driver->disable_hpd) + dssdev->driver->disable_hpd(dssdev); + } +} + +/* * drm ioctl funcs */ @@ -602,6 +628,7 @@ static int pdev_probe(struct platform_device *pdev) priv->fbdev = omap_fbdev_init(ddev); drm_kms_helper_poll_init(ddev); + omap_modeset_enable_external_hpd(); /* * Register the DRM device with the core and the connectors with @@ -614,6 +641,7 @@ static int pdev_probe(struct platform_device *pdev) return 0; err_cleanup_helpers: + omap_modeset_disable_external_hpd(); drm_kms_helper_poll_fini(ddev); if (priv->fbdev) omap_fbdev_free(ddev); @@ -642,6 +670,7 @@ static int pdev_remove(struct platform_device *pdev) drm_dev_unregister(ddev); + omap_modeset_disable_external_hpd(); drm_kms_helper_poll_fini(ddev); if (priv->fbdev) |