diff mbox

[v2,1/2] drm/sysfs: Provide per connector control of DRM KMS polling

Message ID 1285125616.2518.20.camel@morgan.silverblock.net (mailing list archive)
State New, archived
Headers show

Commit Message

Andy Walls Sept. 22, 2010, 3:20 a.m. UTC
None
diff mbox

Patch

diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c
index 86118a7..8e0807d 100644
--- a/drivers/gpu/drm/drm_sysfs.c
+++ b/drivers/gpu/drm/drm_sysfs.c
@@ -318,11 +318,80 @@  static ssize_t select_subconnector_show(struct device *device,
                        drm_get_dvi_i_select_name((int)subconnector));
 }
 
+static const struct {
+       uint8_t mask;
+       const char *name;
+} polled_bit_names[] = {
+       { DRM_CONNECTOR_POLL_HPD,        "hotplug_detectable" },
+       { DRM_CONNECTOR_POLL_CONNECT,    "connect"            },
+       { DRM_CONNECTOR_POLL_DISCONNECT, "disconnect"         },
+};
+
+/*
+ * Return the decoded contents of connector->polled, using the names of the
+ * all the bit masks.  Bits that are set, have their names enclosed in brackets.
+ */
+static ssize_t polled_show(struct device *dev, struct device_attribute *attr,
+                          char *buf)
+{
+       struct drm_connector *connector = to_drm_connector(dev);
+       char *tmp;
+       int i;
+
+       tmp = buf;
+       for (i = 0; i < ARRAY_SIZE(polled_bit_names); i++) {
+               if (connector->polled & polled_bit_names[i].mask)
+                       tmp += sprintf(tmp, "[%s] ", polled_bit_names[i].name);
+               else
+                       tmp += sprintf(tmp, "%s ", polled_bit_names[i].name);
+       }
+
+       if (tmp != buf)
+               *(tmp - 1) = '\n';
+       return tmp - buf;
+}
+
+/*
+ * Change the state of connector->polled, given input bit-mask name-strings
+ * that are separated by space or newline.
+ */
+static ssize_t polled_store(struct device *dev, struct device_attribute *attr,
+                           const char *buf, size_t count)
+{
+       struct drm_connector *connector = to_drm_connector(dev);
+       const char *tmp;
+       int i;
+       uint8_t polled;
+
+       /* Polling of this connector will cease, if no match is made below */
+       polled = 0;
+
+       /* Incrementally split and parse the input */
+       while ((tmp = strsep((char **) &buf, " \n")) != NULL) {
+
+               /* Don't waste effort on multiple adjacent separators */
+               if (*tmp == '\0')
+                       continue;
+
+               /* Check for a match with a connector poll type name */
+               for (i = 0; i < ARRAY_SIZE(polled_bit_names); i++) {
+                       if (!strncasecmp(tmp, polled_bit_names[i].name,
+                                        strlen(polled_bit_names[i].name))) {
+                               polled |= polled_bit_names[i].mask;
+                               break;
+                       }
+               }
+       }
+       connector->polled = polled;
+       return count;
+}
+
 static struct device_attribute connector_attrs[] = {
        __ATTR_RO(status),
        __ATTR_RO(enabled),
        __ATTR_RO(dpms),
        __ATTR_RO(modes),
+       __ATTR(polled, 0644, polled_show, polled_store),
 };
 
 /* These attributes are for both DVI-I connectors and all types of tv-out. */