From aac53d5048b530a59209d6731b64d5f80069d726 Mon Sep 17 00:00:00 2001 From: Jennifer Temkin Date: Mon, 11 Jan 2016 09:54:48 -0500 Subject: [PATCH] Add DPMS support to DRM plugin, and add according RPC. [OXT-47] --- libsurfman/src/surfman-head.h.in | 10 +++++++ libsurfman/version-micro | 2 +- plugins/drm/src/drm-plugin.c | 51 ++++++++++++++++++++++++++++++++ plugins/drm/src/monitor.c | 33 +++++++++++++++++---- plugins/drm/src/prototypes.h | 2 ++ surfman/src/dbus.c | 2 ++ surfman/src/dbus_glue.c | 18 +++++++++++ surfman/src/plugin.c | 26 ++++++++++++++++ surfman/src/prototypes.h | 4 +++ surfman/version-micro | 2 +- 10 files changed, 143 insertions(+), 7 deletions(-) diff --git a/libsurfman/src/surfman-head.h.in b/libsurfman/src/surfman-head.h.in index efcb2d9..d825dc2 100644 --- a/libsurfman/src/surfman-head.h.in +++ b/libsurfman/src/surfman-head.h.in @@ -611,4 +611,14 @@ extern "C" */ void (*restore_brightness)(struct surfman_plugin *plugin); + /* + * dpms_on : power screen on + */ + void (*dpms_on)(struct surfman_plugin *plugin); + + /* + * dpms_off : power screen off + */ + void (*dpms_off)(struct surfman_plugin *plugin); + } surfman_plugin_t; diff --git a/libsurfman/version-micro b/libsurfman/version-micro index d00491f..0cfbf08 100644 --- a/libsurfman/version-micro +++ b/libsurfman/version-micro @@ -1 +1 @@ -1 +2 diff --git a/plugins/drm/src/drm-plugin.c b/plugins/drm/src/drm-plugin.c index 8b8d416..58fed36 100644 --- a/plugins/drm/src/drm-plugin.c +++ b/plugins/drm/src/drm-plugin.c @@ -470,6 +470,52 @@ INTERNAL void drmp_restore_brightness(surfman_plugin_t *plugin) backlight_restore(backlight); } +INTERNAL void drmp_dpms_on(surfman_plugin_t *plugin) +{ + (void) plugin; + struct drm_device *d; + struct drm_monitor *m; + int rc; + + DRM_DBG("%s, dpms on", __FUNCTION__); + + list_for_each_entry(d, &devices, l) { + drm_device_set_master(d); + list_for_each_entry(m, &(d->monitors), l_dev) { + rc = drm_monitor_dpms_on(m); + if (rc) { + DRM_DBG("%s, dpms on failed for monitor at conn=%d, enc=%d, " + "crtc=%d - %s", __FUNCTION__, m->connector, m->encoder, + m->crtc, strerror(rc)); + } + } + drm_device_drop_master(d); + } +} + +INTERNAL void drmp_dpms_off(surfman_plugin_t *plugin) +{ + (void) plugin; + struct drm_device *d; + struct drm_monitor *m; + int rc; + + DRM_DBG("%s, dpms off", __FUNCTION__); + + list_for_each_entry(d, &devices, l) { + drm_device_set_master(d); + list_for_each_entry(m, &(d->monitors), l_dev) { + rc = drm_monitor_dpms_off(m); + if (rc) { + DRM_DBG("%s, dpms off failed for monitor at conn=%d, enc=%d, " + "crtc=%d - %s", __FUNCTION__, m->connector, m->encoder, + m->crtc, strerror(rc)); + } + } + drm_device_drop_master(d); + } +} + #define OPTIONAL (NULL) #define REQUIRED ((void*)0xDEADBEEF) /* Surfman plugin interface. */ @@ -504,6 +550,11 @@ surfman_plugin_t surfman_plugin = { .increase_brightness = drmp_increase_brightness, .decrease_brightness = drmp_decrease_brightness, .restore_brightness = drmp_restore_brightness, + + /* DPMS mode management. */ + .dpms_on = drmp_dpms_on, + .dpms_off = drmp_dpms_off, + .options = { 64, /* libDRM requires a 64 bytes alignment (not 64bit ;). */ 0 /* TODO: SURFMAN_FEATURE_NEED_REFRESH triggers a cache-incohrency with xenfb2 diff --git a/plugins/drm/src/monitor.c b/plugins/drm/src/monitor.c index 56d2957..b1d0c7a 100644 --- a/plugins/drm/src/monitor.c +++ b/plugins/drm/src/monitor.c @@ -161,6 +161,19 @@ static int drmModeSetDpmsProp(int fd, drmModeConnector *connector, int value) } static int drm_monitor_disable_dpms(struct drm_monitor *monitor) +{ + /* TODO for now, set DPMS to On for each monitor as it is initialized. I believe + * this will disable the default power saving timeout. It may end up that this is + * the best place to initially set DPMS state to On in the end and we manage timing + * it out into power saving states with xenmgr. + */ + return drm_monitor_dpms_on(monitor); +} + +/* + * Set the DPMS mode of a monitor for power saving purposes. + */ +int drm_monitor_dpms_on(struct drm_monitor *monitor) { drmModeConnector *c; int rc; @@ -170,16 +183,26 @@ static int drm_monitor_disable_dpms(struct drm_monitor *monitor) return -errno; } - /* TODO for now, set DPMS to On for each monitor as it is initialized. I believe - * this will disable the default power saving timeout. It may end up that this is - * the best place to initially set DPMS state to On in the end and we manage timing - * it out into power saving states with xenmgr. - */ rc = drmModeSetDpmsProp(monitor->device->fd, c, DRM_MODE_DPMS_ON); drmModeFreeConnector(c); return rc; } +int drm_monitor_dpms_off(struct drm_monitor *monitor) +{ + drmModeConnector *c; + int rc; + + c = drmModeGetConnector(monitor->device->fd, monitor->connector); + if (!c) { + return -errno; + } + + rc = drmModeSetDpmsProp(monitor->device->fd, c, DRM_MODE_DPMS_OFF); + drmModeFreeConnector(c); + return rc; +} + /* * Check that default connector configuration is suitable for this monitor. */ diff --git a/plugins/drm/src/prototypes.h b/plugins/drm/src/prototypes.h index d1f8971..5fbd399 100644 --- a/plugins/drm/src/prototypes.h +++ b/plugins/drm/src/prototypes.h @@ -62,6 +62,8 @@ extern const struct drm_framebuffer_ops framebuffer_foreign_ops; extern void drm_monitor_info(const struct drm_monitor *m); extern int drm_monitors_scan(struct drm_device *device); extern int drm_monitor_init(struct drm_monitor *monitor); +extern int drm_monitor_dpms_on(struct drm_monitor *monitor); +extern int drm_monitor_dpms_off(struct drm_monitor *monitor); /* udev.c */ extern int udev_process_subsystem(struct udev *udev, const char *subsystem, void *(*action)(struct udev *, struct udev_device *)); extern void udev_settle(struct udev *udev, unsigned int timeout); diff --git a/surfman/src/dbus.c b/surfman/src/dbus.c index b8b7d5a..a200f78 100644 --- a/surfman/src/dbus.c +++ b/surfman/src/dbus.c @@ -34,6 +34,8 @@ static const struct { "dump_all_screens", dbus_dump_all_screens }, { "increase_brightness", dbus_increase_brightness }, { "decrease_brightness", dbus_decrease_brightness }, + { "dpms_on", dbus_dpms_on }, + { "dpms_off", dbus_dpms_off }, { "pre_s3", dbus_pre_s3 }, { "post_s3", dbus_post_s3 }, { "display_image", dbus_display_image }, diff --git a/surfman/src/dbus_glue.c b/surfman/src/dbus_glue.c index 3e3f81f..263665d 100644 --- a/surfman/src/dbus_glue.c +++ b/surfman/src/dbus_glue.c @@ -105,6 +105,24 @@ dbus_decrease_brightness (DBusMessage *msg, DBusMessage *reply) return TRUE; } +dbus_bool_t +dbus_dpms_on (DBusMessage *msg, DBusMessage *reply) +{ + plugin_dpms_on (); + + //Re-display the most recently displayed domain. + domain_set_visible(NULL, false); + return TRUE; +} + +dbus_bool_t +dbus_dpms_off (DBusMessage *msg, DBusMessage *reply) +{ + plugin_dpms_off (); + + return TRUE; +} + dbus_bool_t dbus_pre_s3 (DBusMessage *msg, DBusMessage *reply) { diff --git a/surfman/src/plugin.c b/surfman/src/plugin.c index 1db9a6b..b0cb4ce 100644 --- a/surfman/src/plugin.c +++ b/surfman/src/plugin.c @@ -426,6 +426,32 @@ void plugin_restore_brightness (void) } } +void plugin_dpms_on (void) +{ + struct plugin *p; + + LIST_FOREACH (p, &plugin_list, link) + { + /* dpms_on has been implemented from 2.1.2 */ + if (PLUGIN_CHECK_VERSION(p, 2, 1, 2) + && PLUGIN_HAS_METHOD (p, dpms_on)) + PLUGIN_CALL (p, dpms_on); + } +} + +void plugin_dpms_off (void) +{ + struct plugin *p; + + LIST_FOREACH (p, &plugin_list, link) + { + /* dpms_off has been implemented from 2.1.2 */ + if (PLUGIN_CHECK_VERSION(p, 2, 1, 2) + && PLUGIN_HAS_METHOD (p, dpms_off)) + PLUGIN_CALL (p, dpms_off); + } +} + #if 0 void plugin_set_guest_resolution (unsigned int domid) diff --git a/surfman/src/prototypes.h b/surfman/src/prototypes.h index 6ef37ec..e37e70e 100644 --- a/surfman/src/prototypes.h +++ b/surfman/src/prototypes.h @@ -36,6 +36,8 @@ extern dbus_bool_t dbus_display_image(DBusMessage *msg, DBusMessage *reply); extern dbus_bool_t dbus_dump_all_screens(DBusMessage *msg, DBusMessage *reply); extern dbus_bool_t dbus_increase_brightness(DBusMessage *msg, DBusMessage *reply); extern dbus_bool_t dbus_decrease_brightness(DBusMessage *msg, DBusMessage *reply); +extern dbus_bool_t dbus_dpms_on(DBusMessage *msg, DBusMessage *reply); +extern dbus_bool_t dbus_dpms_off(DBusMessage *msg, DBusMessage *reply); extern dbus_bool_t dbus_pre_s3(DBusMessage *msg, DBusMessage *reply); extern dbus_bool_t dbus_post_s3(DBusMessage *msg, DBusMessage *reply); extern dbus_bool_t dbus_set_pv_display(DBusMessage *msg, DBusMessage *reply); @@ -114,6 +116,8 @@ extern void plugin_pre_s3(void); extern void plugin_post_s3(void); extern void plugin_increase_brightness(void); extern void plugin_decrease_brightness(void); +extern void plugin_dpms_on(void); +extern void plugin_dpms_off(void); extern void plugin_restore_brightness(void); extern unsigned int plugin_stride_align(void); extern int plugin_need_refresh(struct plugin *p); diff --git a/surfman/version-micro b/surfman/version-micro index d00491f..0cfbf08 100644 --- a/surfman/version-micro +++ b/surfman/version-micro @@ -1 +1 @@ -1 +2