The omap_dss_device .enable_hpd() and .disable_hpd() are used to enable
and disable hot-plug detection at omapdrm probe and remove time. This is
required to avoid reporting hot-plug detection events before the DRM
infrastructure is ready to accept them, as that could result in crashes
or other malfunction.
Hot-plug event reporting is conditioned by both HPD being enabled
through the .enable_hpd() operation and by the HPD callback being
registered though the .register_hpd_cb() operation. We thus don't need a
separate enable operation if we can guarantee that callbacks won't be
registered too early.
HPD callbacks are registered at connector initialization time, which is
too early to start reporting HPD events. There's however nothing
blocking a move of callback registration to a later time when the
omapdrm driver calls the HPD enable operations. Do so, and remove the
HPD enable operation completely from 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>
mutex_unlock(&ddata->hpd_lock);
}
mutex_unlock(&ddata->hpd_lock);
}
-static void dvic_enable_hpd(struct omap_dss_device *dssdev)
-{
- struct panel_drv_data *ddata = to_panel_data(dssdev);
-
- if (!ddata->hpd_gpio)
- return;
-
- mutex_lock(&ddata->hpd_lock);
- ddata->hpd_enabled = true;
- mutex_unlock(&ddata->hpd_lock);
-}
-
-static void dvic_disable_hpd(struct omap_dss_device *dssdev)
-{
- struct panel_drv_data *ddata = to_panel_data(dssdev);
-
- if (!ddata->hpd_gpio)
- return;
-
- mutex_lock(&ddata->hpd_lock);
- ddata->hpd_enabled = false;
- mutex_unlock(&ddata->hpd_lock);
-}
-
static const struct omap_dss_device_ops dvic_ops = {
.connect = dvic_connect,
.disconnect = dvic_disconnect,
static const struct omap_dss_device_ops dvic_ops = {
.connect = dvic_connect,
.disconnect = dvic_disconnect,
.register_hpd_cb = dvic_register_hpd_cb,
.unregister_hpd_cb = dvic_unregister_hpd_cb,
.register_hpd_cb = dvic_register_hpd_cb,
.unregister_hpd_cb = dvic_unregister_hpd_cb,
- .enable_hpd = dvic_enable_hpd,
- .disable_hpd = dvic_disable_hpd,
};
static irqreturn_t dvic_hpd_isr(int irq, void *data)
};
static irqreturn_t dvic_hpd_isr(int irq, void *data)
struct omap_dss_device dssdev;
void (*hpd_cb)(void *cb_data, enum drm_connector_status status);
void *hpd_cb_data;
struct omap_dss_device dssdev;
void (*hpd_cb)(void *cb_data, enum drm_connector_status status);
void *hpd_cb_data;
struct mutex hpd_lock;
struct device *dev;
struct mutex hpd_lock;
struct device *dev;
mutex_unlock(&ddata->hpd_lock);
}
mutex_unlock(&ddata->hpd_lock);
}
-static void hdmic_enable_hpd(struct omap_dss_device *dssdev)
-{
- struct panel_drv_data *ddata = to_panel_data(dssdev);
-
- if (!ddata->hpd_gpio)
- return;
-
- mutex_lock(&ddata->hpd_lock);
- ddata->hpd_enabled = true;
- mutex_unlock(&ddata->hpd_lock);
-}
-
-static void hdmic_disable_hpd(struct omap_dss_device *dssdev)
-{
- struct panel_drv_data *ddata = to_panel_data(dssdev);
-
- if (!ddata->hpd_gpio)
- return;
-
- mutex_lock(&ddata->hpd_lock);
- ddata->hpd_enabled = false;
- mutex_unlock(&ddata->hpd_lock);
-}
-
static int hdmic_set_hdmi_mode(struct omap_dss_device *dssdev, bool hdmi_mode)
{
struct omap_dss_device *src = dssdev->src;
static int hdmic_set_hdmi_mode(struct omap_dss_device *dssdev, bool hdmi_mode)
{
struct omap_dss_device *src = dssdev->src;
.detect = hdmic_detect,
.register_hpd_cb = hdmic_register_hpd_cb,
.unregister_hpd_cb = hdmic_unregister_hpd_cb,
.detect = hdmic_detect,
.register_hpd_cb = hdmic_register_hpd_cb,
.unregister_hpd_cb = hdmic_unregister_hpd_cb,
- .enable_hpd = hdmic_enable_hpd,
- .disable_hpd = hdmic_disable_hpd,
.hdmi = {
.set_hdmi_mode = hdmic_set_hdmi_mode,
.hdmi = {
.set_hdmi_mode = hdmic_set_hdmi_mode,
struct panel_drv_data *ddata = data;
mutex_lock(&ddata->hpd_lock);
struct panel_drv_data *ddata = data;
mutex_lock(&ddata->hpd_lock);
- if (ddata->hpd_enabled && ddata->hpd_cb) {
enum drm_connector_status status;
if (hdmic_detect(&ddata->dssdev))
enum drm_connector_status status;
if (hdmic_detect(&ddata->dssdev))
struct omap_dss_device dssdev;
void (*hpd_cb)(void *cb_data, enum drm_connector_status status);
void *hpd_cb_data;
struct omap_dss_device dssdev;
void (*hpd_cb)(void *cb_data, enum drm_connector_status status);
void *hpd_cb_data;
struct mutex hpd_lock;
struct gpio_desc *ct_cp_hpd_gpio;
struct mutex hpd_lock;
struct gpio_desc *ct_cp_hpd_gpio;
mutex_unlock(&ddata->hpd_lock);
}
mutex_unlock(&ddata->hpd_lock);
}
-static void tpd_enable_hpd(struct omap_dss_device *dssdev)
-{
- struct panel_drv_data *ddata = to_panel_data(dssdev);
-
- mutex_lock(&ddata->hpd_lock);
- ddata->hpd_enabled = true;
- mutex_unlock(&ddata->hpd_lock);
-}
-
-static void tpd_disable_hpd(struct omap_dss_device *dssdev)
-{
- struct panel_drv_data *ddata = to_panel_data(dssdev);
-
- mutex_lock(&ddata->hpd_lock);
- ddata->hpd_enabled = false;
- mutex_unlock(&ddata->hpd_lock);
-}
-
static int tpd_set_infoframe(struct omap_dss_device *dssdev,
const struct hdmi_avi_infoframe *avi)
{
static int tpd_set_infoframe(struct omap_dss_device *dssdev,
const struct hdmi_avi_infoframe *avi)
{
.detect = tpd_detect,
.register_hpd_cb = tpd_register_hpd_cb,
.unregister_hpd_cb = tpd_unregister_hpd_cb,
.detect = tpd_detect,
.register_hpd_cb = tpd_register_hpd_cb,
.unregister_hpd_cb = tpd_unregister_hpd_cb,
- .enable_hpd = tpd_enable_hpd,
- .disable_hpd = tpd_disable_hpd,
.hdmi = {
.set_infoframe = tpd_set_infoframe,
.hdmi = {
.set_infoframe = tpd_set_infoframe,
struct panel_drv_data *ddata = data;
mutex_lock(&ddata->hpd_lock);
struct panel_drv_data *ddata = data;
mutex_lock(&ddata->hpd_lock);
- if (ddata->hpd_enabled && ddata->hpd_cb) {
enum drm_connector_status status;
if (tpd_detect(&ddata->dssdev))
enum drm_connector_status status;
if (tpd_detect(&ddata->dssdev))
enum drm_connector_status status),
void *cb_data);
void (*unregister_hpd_cb)(struct omap_dss_device *dssdev);
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 (*read_edid)(struct omap_dss_device *dssdev, u8 *buf, int len);
int (*read_edid)(struct omap_dss_device *dssdev, u8 *buf, int len);
struct omap_connector {
struct drm_connector base;
struct omap_dss_device *dssdev;
struct omap_connector {
struct drm_connector base;
struct omap_dss_device *dssdev;
+ struct omap_dss_device *hpd;
drm_kms_helper_hotplug_event(dev);
}
drm_kms_helper_hotplug_event(dev);
}
+void omap_connector_enable_hpd(struct drm_connector *connector)
+{
+ struct omap_connector *omap_connector = to_omap_connector(connector);
+ struct omap_dss_device *hpd = omap_connector->hpd;
+
+ if (hpd)
+ hpd->ops->register_hpd_cb(hpd, omap_connector_hpd_cb,
+ omap_connector);
+}
+
+void omap_connector_disable_hpd(struct drm_connector *connector)
+{
+ struct omap_connector *omap_connector = to_omap_connector(connector);
+ struct omap_dss_device *hpd = omap_connector->hpd;
+
+ if (hpd)
+ hpd->ops->unregister_hpd_cb(hpd);
+}
+
bool omap_connector_get_hdmi_mode(struct drm_connector *connector)
{
struct omap_connector *omap_connector = to_omap_connector(connector);
bool omap_connector_get_hdmi_mode(struct drm_connector *connector)
{
struct omap_connector *omap_connector = to_omap_connector(connector);
static void omap_connector_destroy(struct drm_connector *connector)
{
struct omap_connector *omap_connector = to_omap_connector(connector);
static void omap_connector_destroy(struct drm_connector *connector)
{
struct omap_connector *omap_connector = to_omap_connector(connector);
- struct omap_dss_device *dssdev;
DBG("%s", omap_connector->dssdev->name);
DBG("%s", omap_connector->dssdev->name);
- if (connector->polled == DRM_CONNECTOR_POLL_HPD) {
- dssdev = omap_connector_find_device(connector,
- OMAP_DSS_DEVICE_OP_HPD);
- dssdev->ops->unregister_hpd_cb(dssdev);
+ if (omap_connector->hpd) {
+ struct omap_dss_device *hpd = omap_connector->hpd;
+
+ hpd->ops->unregister_hpd_cb(hpd);
+ omapdss_device_put(hpd);
+ omap_connector->hpd = NULL;
}
drm_connector_unregister(connector);
}
drm_connector_unregister(connector);
*/
dssdev = omap_connector_find_device(connector, OMAP_DSS_DEVICE_OP_HPD);
if (dssdev) {
*/
dssdev = omap_connector_find_device(connector, OMAP_DSS_DEVICE_OP_HPD);
if (dssdev) {
- dssdev->ops->register_hpd_cb(dssdev, omap_connector_hpd_cb,
- omap_connector);
+ omap_connector->hpd = omapdss_device_get(dssdev);
connector->polled = DRM_CONNECTOR_POLL_HPD;
} else {
dssdev = omap_connector_find_device(connector,
connector->polled = DRM_CONNECTOR_POLL_HPD;
} else {
dssdev = omap_connector_find_device(connector,
struct drm_encoder *omap_connector_attached_encoder(
struct drm_connector *connector);
bool omap_connector_get_hdmi_mode(struct drm_connector *connector);
struct drm_encoder *omap_connector_attached_encoder(
struct drm_connector *connector);
bool omap_connector_get_hdmi_mode(struct drm_connector *connector);
+void omap_connector_enable_hpd(struct drm_connector *connector);
+void omap_connector_disable_hpd(struct drm_connector *connector);
#endif /* __OMAPDRM_CONNECTOR_H__ */
#endif /* __OMAPDRM_CONNECTOR_H__ */
struct omap_drm_private *priv = ddev->dev_private;
int i;
struct omap_drm_private *priv = ddev->dev_private;
int i;
- for (i = 0; i < priv->num_pipes; i++) {
- struct omap_dss_device *display = priv->pipes[i].display;
-
- if (display->ops->enable_hpd)
- display->ops->enable_hpd(display);
- }
+ for (i = 0; i < priv->num_pipes; i++)
+ omap_connector_enable_hpd(priv->pipes[i].connector);
struct omap_drm_private *priv = ddev->dev_private;
int i;
struct omap_drm_private *priv = ddev->dev_private;
int i;
- for (i = 0; i < priv->num_pipes; i++) {
- struct omap_dss_device *display = priv->pipes[i].display;
-
- if (display->ops->disable_hpd)
- display->ops->disable_hpd(display);
- }
+ for (i = 0; i < priv->num_pipes; i++)
+ omap_connector_disable_hpd(priv->pipes[i].connector);