diff mbox

drm/sysfs: Provide per connector control of DRM KMS polling

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

Commit Message

Andy Walls Sept. 20, 2010, 12:59 p.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. */