Skip to content

Commit

Permalink
drm: Lighten sysfs connector 'status'
Browse files Browse the repository at this point in the history
Since the beginning, sysfs/connector/status has done a heavyweight
detection of the current connector status. But no user, such as upowerd
or logind, has ever desired to initiate a probe. Move the probing into a
new attribute so that existing readers get the behaviour they desire.

v2: David Herrmann suggested using "echo detect > /sys/.../status" to
trigger the probing, which is a fine idea. This extends that to also
allow the user to apply the force detection overrides at runtime.

v3: Now with airlied's email address fixed! Requires sysfs_streq()

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: David Herrmann <dh.herrmann@gmail.com>
Cc: Dave Airlie <airlied@redhat.com>
Cc: Alex Deucher <alexdeucher@gmail.com>
Reviewed-by: David Herrmann <dh.herrmann@gmail.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
  • Loading branch information
Chris Wilson authored and Daniel Vetter committed Mar 10, 2015
1 parent 3461b30 commit c484f02
Showing 1 changed file with 53 additions and 8 deletions.
61 changes: 53 additions & 8 deletions drivers/gpu/drm/drm_sysfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -166,23 +166,68 @@ void drm_sysfs_destroy(void)
/*
* Connector properties
*/
static ssize_t status_show(struct device *device,
static ssize_t status_store(struct device *device,
struct device_attribute *attr,
char *buf)
const char *buf, size_t count)
{
struct drm_connector *connector = to_drm_connector(device);
enum drm_connector_status status;
struct drm_device *dev = connector->dev;
enum drm_connector_status old_status;
int ret;

ret = mutex_lock_interruptible(&connector->dev->mode_config.mutex);
ret = mutex_lock_interruptible(&dev->mode_config.mutex);
if (ret)
return ret;

status = connector->funcs->detect(connector, true);
mutex_unlock(&connector->dev->mode_config.mutex);
old_status = connector->status;

if (sysfs_streq(buf, "detect")) {
connector->force = 0;
connector->status = connector->funcs->detect(connector, true);
} else if (sysfs_streq(buf, "on")) {
connector->force = DRM_FORCE_ON;
} else if (sysfs_streq(buf, "on-digital")) {
connector->force = DRM_FORCE_ON_DIGITAL;
} else if (sysfs_streq(buf, "off")) {
connector->force = DRM_FORCE_OFF;
} else
ret = -EINVAL;

if (ret == 0 && connector->force) {
if (connector->force == DRM_FORCE_ON ||
connector->force == DRM_FORCE_ON_DIGITAL)
connector->status = connector_status_connected;
else
connector->status = connector_status_disconnected;
if (connector->funcs->force)
connector->funcs->force(connector);
}

if (old_status != connector->status) {
DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %d to %d\n",
connector->base.id,
connector->name,
old_status, connector->status);

dev->mode_config.delayed_event = true;
if (dev->mode_config.poll_enabled)
schedule_delayed_work(&dev->mode_config.output_poll_work,
0);
}

mutex_unlock(&dev->mode_config.mutex);

return ret;
}

static ssize_t status_show(struct device *device,
struct device_attribute *attr,
char *buf)
{
struct drm_connector *connector = to_drm_connector(device);

return snprintf(buf, PAGE_SIZE, "%s\n",
drm_get_connector_status_name(status));
drm_get_connector_status_name(connector->status));
}

static ssize_t dpms_show(struct device *device,
Expand Down Expand Up @@ -339,7 +384,7 @@ static ssize_t select_subconnector_show(struct device *device,
drm_get_dvi_i_select_name((int)subconnector));
}

static DEVICE_ATTR_RO(status);
static DEVICE_ATTR_RW(status);
static DEVICE_ATTR_RO(enabled);
static DEVICE_ATTR_RO(dpms);
static DEVICE_ATTR_RO(modes);
Expand Down

0 comments on commit c484f02

Please sign in to comment.