drm: msm: add support for a custom hotplug event
Add support for a custom hotplug event that is triggered when the
status of the connector has changed. The event string of the
custom event will be in the following format:
"name=<connector name> status=<connector status>"
For example, when the DisplayPort connector has its status
updated to connected then the event string that is used as part
of the hotplug event will be as follows:
"name=DP-1 status=connected"
If the connector name is not known or is invalid at the time that
the event is triggered then the name will be reported as "unknown".
CRs-Fixed: 2056566
Change-Id: I5d6164d1e8e651cb05527733d68fa86fefb9e6ce
Signed-off-by: Tatenda Chipeperekwa <tatendac@codeaurora.org>
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index f75be8a..962087c 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -59,12 +59,68 @@
#define TEARDOWN_DEADLOCK_RETRY_MAX 5
+static void msm_drm_helper_hotplug_event(struct drm_device *dev)
+{
+ struct drm_connector *connector;
+ char *event_string;
+ char const *connector_name;
+ char *envp[2];
+
+ if (!dev) {
+ DRM_ERROR("hotplug_event failed, invalid input\n");
+ return;
+ }
+
+ if (!dev->mode_config.poll_enabled)
+ return;
+
+ event_string = kzalloc(SZ_4K, GFP_KERNEL);
+ if (!event_string) {
+ DRM_ERROR("failed to allocate event string\n");
+ return;
+ }
+
+ mutex_lock(&dev->mode_config.mutex);
+ drm_for_each_connector(connector, dev) {
+ /* Only handle HPD capable connectors. */
+ if (!(connector->polled & DRM_CONNECTOR_POLL_HPD))
+ continue;
+
+ connector->status = connector->funcs->detect(connector, false);
+
+ if (connector->name)
+ connector_name = connector->name;
+ else
+ connector_name = "unknown";
+
+ snprintf(event_string, SZ_4K, "name=%s status=%s\n",
+ connector_name,
+ drm_get_connector_status_name(connector->status));
+ DRM_DEBUG("generating hotplug event [%s]\n", event_string);
+ envp[0] = event_string;
+ envp[1] = NULL;
+ kobject_uevent_env(&dev->primary->kdev->kobj, KOBJ_CHANGE,
+ envp);
+ }
+ mutex_unlock(&dev->mode_config.mutex);
+ kfree(event_string);
+}
+
static void msm_fb_output_poll_changed(struct drm_device *dev)
{
- struct msm_drm_private *priv = dev->dev_private;
+ struct msm_drm_private *priv = NULL;
+
+ if (!dev) {
+ DRM_ERROR("output_poll_changed failed, invalid input\n");
+ return;
+ }
+
+ priv = dev->dev_private;
if (priv->fbdev)
drm_fb_helper_hotplug_event(priv->fbdev);
+ else
+ msm_drm_helper_hotplug_event(dev);
}
int msm_atomic_check(struct drm_device *dev,