#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)
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);
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);
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);
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);
{
struct drm_connector *connector = NULL;
struct omap_connector *omap_connector;
+ bool hpd_supported = false;
DBG("%s", dssdev->name);
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
return 0;
}
+/*
+ * 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
*/
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
return 0;
err_cleanup_helpers:
+ omap_modeset_disable_external_hpd();
drm_kms_helper_poll_fini(ddev);
if (priv->fbdev)
omap_fbdev_free(ddev);
drm_dev_unregister(ddev);
+ omap_modeset_disable_external_hpd();
drm_kms_helper_poll_fini(ddev);
if (priv->fbdev)