#include <drm_fourcc.h>
#include <gbm.h>
+#include <libbacklight.h>
#include "compositor.h"
#include "evdev.h"
struct wl_listener scanout_buffer_destroy_listener;
struct wl_buffer *pending_scanout_buffer;
struct wl_listener pending_scanout_buffer_destroy_listener;
+ struct backlight *backlight;
};
/*
drmModeCrtcPtr origcrtc = output->original_crtc;
int i;
+ if (output->backlight)
+ backlight_destroy(output->backlight);
+
/* Turn off hardware cursor */
drm_output_set_cursor(&output->base, NULL);
sprite->pending_surface = NULL;
}
+/* returns a value between 1-10 range, where higher is brighter */
+static uint32_t
+drm_get_backlight(struct drm_output *output)
+{
+ long brightness, max_brightness, norm;
+
+ brightness = backlight_get_brightness(output->backlight);
+ max_brightness = backlight_get_max_brightness(output->backlight);
+
+ /* convert it on a scale of 1 to 10 */
+ norm = 1 + ((brightness) * 9)/(max_brightness);
+
+ return (uint32_t) norm;
+}
+
+/* values accepted are between 1-10 range */
+static void
+drm_set_backlight(struct weston_output *output_base, uint32_t value)
+{
+ struct drm_output *output = (struct drm_output *) output_base;
+ long max_brightness, new_brightness;
+
+ if (!output->backlight)
+ return;
+
+ if (value < 1 || value > 10)
+ return;
+
+ max_brightness = backlight_get_max_brightness(output->backlight);
+
+ /* get denormalized value */
+ new_brightness = ((value - 1) * (max_brightness)) / 9;
+
+ backlight_set_brightness(output->backlight, new_brightness);
+}
+
+static drmModePropertyPtr
+drm_get_prop(int fd, drmModeConnectorPtr connector, const char *name)
+{
+ drmModePropertyPtr props;
+ int i;
+
+ for (i = 0; i < connector->count_props; i++) {
+ props = drmModeGetProperty(fd, connector->props[i]);
+ if (!props)
+ continue;
+
+ if (!strcmp(props->name, name))
+ return props;
+
+ drmModeFreeProperty(props);
+ }
+
+ return NULL;
+}
+
+static void
+drm_set_dpms(struct weston_output *output_base, enum dpms_enum level)
+{
+ struct drm_output *output = (struct drm_output *) output_base;
+ struct weston_compositor *ec = output_base->compositor;
+ struct drm_compositor *c = (struct drm_compositor *) ec;
+ drmModeConnectorPtr connector;
+ drmModePropertyPtr prop;
+
+ connector = drmModeGetConnector(c->drm.fd, output->connector_id);
+ if (!connector)
+ return;
+
+ prop = drm_get_prop(c->drm.fd, connector, "DPMS");
+ if (!prop) {
+ drmModeFreeConnector(connector);
+ return;
+ }
+
+ drmModeConnectorSetProperty(c->drm.fd, connector->connector_id,
+ prop->prop_id, level);
+ drmModeFreeProperty(prop);
+ drmModeFreeConnector(connector);
+}
+
static int
create_output_for_connector(struct drm_compositor *ec,
drmModeRes *resources,
drmModeConnector *connector,
- int x, int y)
+ int x, int y, struct udev_device *drm_device)
{
struct drm_output *output;
struct drm_mode *drm_mode, *next;
goto err_fb;
}
+ output->backlight = backlight_init(drm_device,
+ connector->connector_type);
+ if (output->backlight) {
+ output->base.set_backlight = drm_set_backlight;
+ output->base.backlight_current = drm_get_backlight(output);
+ }
+
weston_output_init(&output->base, &ec->base, x, y,
connector->mmWidth, connector->mmHeight, 0);
output->base.repaint = drm_output_repaint;
output->base.destroy = drm_output_destroy;
output->base.assign_planes = drm_assign_planes;
+ output->base.set_dpms = drm_set_dpms;
return 0;
}
static int
-create_outputs(struct drm_compositor *ec, int option_connector)
+create_outputs(struct drm_compositor *ec, int option_connector,
+ struct udev_device *drm_device)
{
drmModeConnector *connector;
drmModeRes *resources;
(option_connector == 0 ||
connector->connector_id == option_connector)) {
if (create_output_for_connector(ec, resources,
- connector, x, y) < 0) {
+ connector, x, y,
+ drm_device) < 0) {
drmModeFreeConnector(connector);
continue;
}
}
static void
-update_outputs(struct drm_compositor *ec)
+update_outputs(struct drm_compositor *ec, struct udev_device *drm_device)
{
drmModeConnector *connector;
drmModeRes *resources;
x = 0;
y = 0;
create_output_for_connector(ec, resources,
- connector, x, y);
+ connector, x, y,
+ drm_device);
printf("connector %d connected\n", connector_id);
}
event = udev_monitor_receive_device(ec->udev_monitor);
if (udev_event_is_hotplug(event))
- update_outputs(ec);
+ update_outputs(ec, event);
udev_device_unref(event);
return NULL;
}
- udev_device_unref(drm_device);
-
ec->base.destroy = drm_destroy;
ec->base.focus = 1;
wl_list_init(&ec->sprite_list);
create_sprites(ec);
- if (create_outputs(ec, connector) < 0) {
+ if (create_outputs(ec, connector, drm_device) < 0) {
fprintf(stderr, "failed to create output for %s\n", path);
return NULL;
}
+ udev_device_unref(drm_device);
udev_enumerate_unref(e);
path = NULL;
struct weston_surface *tmp;
struct weston_input_device *device;
struct shell_surface *shsurf;
+ struct weston_output *output;
uint32_t time;
- if (shell->locked)
+ if (shell->locked) {
+ wl_list_for_each(output, &shell->compositor->output_list, link)
+ /* TODO: find a way to jump to other DPMS levels */
+ if (output->set_dpms)
+ output->set_dpms(output, WESTON_DPMS_STANDBY);
return;
+ }
shell->locked = true;
}
static void
+backlight_binding(struct wl_input_device *device, uint32_t time,
+ uint32_t key, uint32_t button, uint32_t state, void *data)
+{
+ struct weston_compositor *compositor = data;
+ struct weston_output *output;
+
+ /* TODO: we're limiting to simple use cases, where we assume just
+ * control on the primary display. We'd have to extend later if we
+ * ever get support for setting backlights on random desktop LCD
+ * panels though */
+ output = get_default_output(compositor);
+ if (!output)
+ return;
+
+ if (!output->set_backlight)
+ return;
+
+ if ((key == KEY_F9 || key == KEY_BRIGHTNESSDOWN) &&
+ output->backlight_current > 1)
+ output->backlight_current--;
+ else if ((key == KEY_F10 || key == KEY_BRIGHTNESSUP) &&
+ output->backlight_current < 10)
+ output->backlight_current++;
+
+ output->set_backlight(output, output->backlight_current);
+}
+
+static void
shell_destroy(struct weston_shell *base)
{
struct wl_shell *shell = container_of(base, struct wl_shell, shell);
weston_compositor_add_binding(ec, 0, BTN_LEFT,
MODIFIER_SUPER | MODIFIER_ALT,
rotate_binding, NULL);
-
weston_compositor_add_binding(ec, KEY_TAB, 0, MODIFIER_SUPER,
switcher_binding, ec);
+ /* brightness */
+ weston_compositor_add_binding(ec, KEY_F9, 0, MODIFIER_CTRL,
+ backlight_binding, ec);
+ weston_compositor_add_binding(ec, KEY_BRIGHTNESSDOWN, 0, 0,
+ backlight_binding, ec);
+ weston_compositor_add_binding(ec, KEY_F10, 0, MODIFIER_CTRL,
+ backlight_binding, ec);
+ weston_compositor_add_binding(ec, KEY_BRIGHTNESSUP, 0, 0,
+ backlight_binding, ec);
+
ec->shell = &shell->shell;
return 0;