summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2017-07-12 20:12:20 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2017-07-12 20:12:20 +0000
commit2053b3486507d89f1f0a3ed7db4b8829c844989c (patch)
tree6f79c3713f982eb150d1a308ed4f08a312e4640d /sys/dev
parent26ab0089e07ff2c4bdb037b73410fb6a177012bf (diff)
Add a "Backlight" property to connectors with an associated backlight
controller for the inteldrm(4) driver. If wscons(4) provides backlight control, prefer ir over raw hardware control and attach it to LVDS, eDP and DSI connectors which are the connector types typically connected to laptop screens.
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/pci/drm/drm_crtc.c23
-rw-r--r--sys/dev/pci/drm/drm_crtc.h5
-rw-r--r--sys/dev/pci/drm/drm_linux.c16
-rw-r--r--sys/dev/pci/drm/drm_linux.h10
-rw-r--r--sys/dev/pci/drm/i915/i915_drv.c120
5 files changed, 157 insertions, 17 deletions
diff --git a/sys/dev/pci/drm/drm_crtc.c b/sys/dev/pci/drm/drm_crtc.c
index db3ececb00c..874388fdd23 100644
--- a/sys/dev/pci/drm/drm_crtc.c
+++ b/sys/dev/pci/drm/drm_crtc.c
@@ -4049,6 +4049,23 @@ int drm_object_property_get_value(struct drm_mode_object *obj,
{
int i;
+#ifdef __OpenBSD__
+ if (obj->type == DRM_MODE_OBJECT_CONNECTOR) {
+ struct drm_connector *connector = obj_to_connector(obj);
+
+ if (property == connector->backlight_property) {
+ struct backlight_device *bd =
+ connector->backlight_device;
+
+ if (bd->props.type == BACKLIGHT_FIRMWARE)
+ *val = bd->ops->get_brightness(bd);
+ else
+ *val = bd->props.brightness;
+ return 0;
+ }
+ }
+#endif
+
/* read-only properties bypass atomic mechanism and still store
* their value in obj->properties->values[].. mostly to avoid
* having to deal w/ EDID and similar props in atomic paths:
@@ -4840,6 +4857,12 @@ static int drm_mode_connector_set_obj_prop(struct drm_mode_object *obj,
ret = 0;
if (connector->funcs->dpms)
ret = (*connector->funcs->dpms)(connector, (int)value);
+#ifdef __OpenBSD__
+ } else if (property == connector->backlight_property) {
+ ret = 0;
+ connector->backlight_device->props.brightness = value;
+ backlight_schedule_update_status(connector->backlight_device);
+#endif
} else if (connector->funcs->set_property)
ret = connector->funcs->set_property(connector, property, value);
diff --git a/sys/dev/pci/drm/drm_crtc.h b/sys/dev/pci/drm/drm_crtc.h
index 978643ad1e5..bc5474cb422 100644
--- a/sys/dev/pci/drm/drm_crtc.h
+++ b/sys/dev/pci/drm/drm_crtc.h
@@ -741,6 +741,11 @@ struct drm_connector {
uint8_t num_h_tile, num_v_tile;
uint8_t tile_h_loc, tile_v_loc;
uint16_t tile_h_size, tile_v_size;
+
+#ifdef __OpenBSD__
+ struct backlight_device *backlight_device;
+ struct drm_property *backlight_property;
+#endif
};
/**
diff --git a/sys/dev/pci/drm/drm_linux.c b/sys/dev/pci/drm/drm_linux.c
index 6cf08ca251f..03ada0f9750 100644
--- a/sys/dev/pci/drm/drm_linux.c
+++ b/sys/dev/pci/drm/drm_linux.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: drm_linux.c,v 1.14 2017/07/05 20:30:13 kettenis Exp $ */
+/* $OpenBSD: drm_linux.c,v 1.15 2017/07/12 20:12:19 kettenis Exp $ */
/*
* Copyright (c) 2013 Jonathan Gray <jsg@openbsd.org>
* Copyright (c) 2015, 2016 Mark Kettenis <kettenis@openbsd.org>
@@ -697,6 +697,12 @@ acpi_get_table_with_size(const char *sig, int instance,
#endif
+void
+backlight_do_update_status(void *arg)
+{
+ backlight_update_status(arg);
+}
+
struct backlight_device *
backlight_device_register(const char *name, void *kdev, void *data,
const struct backlight_ops *ops, struct backlight_properties *props)
@@ -707,6 +713,8 @@ backlight_device_register(const char *name, void *kdev, void *data,
bd->ops = ops;
bd->props = *props;
bd->data = data;
+
+ task_set(&bd->task, backlight_do_update_status, bd);
return bd;
}
@@ -716,3 +724,9 @@ backlight_device_unregister(struct backlight_device *bd)
{
free(bd, M_DRM, sizeof(*bd));
}
+
+void
+backlight_schedule_update_status(struct backlight_device *bd)
+{
+ task_add(systq, &bd->task);
+}
diff --git a/sys/dev/pci/drm/drm_linux.h b/sys/dev/pci/drm/drm_linux.h
index 099d4710788..1d6c739b151 100644
--- a/sys/dev/pci/drm/drm_linux.h
+++ b/sys/dev/pci/drm/drm_linux.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: drm_linux.h,v 1.54 2017/07/07 18:06:51 kettenis Exp $ */
+/* $OpenBSD: drm_linux.h,v 1.55 2017/07/12 20:12:19 kettenis Exp $ */
/*
* Copyright (c) 2013, 2014, 2015 Mark Kettenis
*
@@ -1917,12 +1917,14 @@ struct backlight_ops {
struct backlight_device {
const struct backlight_ops *ops;
struct backlight_properties props;
+ struct task task;
void *data;
};
#define bl_get_data(bd) (bd)->data
-#define BACKLIGHT_RAW 0
+#define BACKLIGHT_RAW 0
+#define BACKLIGHT_FIRMWARE 1
struct backlight_device *backlight_device_register(const char *, void *,
void *, const struct backlight_ops *, struct backlight_properties *);
@@ -1932,7 +1934,9 @@ static inline void
backlight_update_status(struct backlight_device *bd)
{
bd->ops->update_status(bd);
-};
+}
+
+void backlight_schedule_update_status(struct backlight_device *);
#define MIPI_DSI_V_SYNC_START 0x01
#define MIPI_DSI_V_SYNC_END 0x11
diff --git a/sys/dev/pci/drm/i915/i915_drv.c b/sys/dev/pci/drm/i915/i915_drv.c
index 1e51de3a754..327b17e7737 100644
--- a/sys/dev/pci/drm/i915/i915_drv.c
+++ b/sys/dev/pci/drm/i915/i915_drv.c
@@ -2092,6 +2092,32 @@ inteldrm_burner_cb(void *arg1)
drm_fb_helper_blank(dev_priv->burner_fblank, helper->fbdev);
}
+int
+inteldrm_backlight_update_status(struct backlight_device *bd)
+{
+ struct wsdisplay_param dp;
+
+ dp.param = WSDISPLAYIO_PARAM_BRIGHTNESS;
+ dp.curval = bd->props.brightness;
+ ws_set_param(&dp);
+ return 0;
+}
+
+int
+inteldrm_backlight_get_brightness(struct backlight_device *bd)
+{
+ struct wsdisplay_param dp;
+
+ dp.param = WSDISPLAYIO_PARAM_BRIGHTNESS;
+ ws_get_param(&dp);
+ return dp.curval;
+}
+
+const struct backlight_ops inteldrm_backlight_ops = {
+ .update_status = inteldrm_backlight_update_status,
+ .get_brightness = inteldrm_backlight_get_brightness
+};
+
int inteldrm_match(struct device *, void *, void *);
void inteldrm_attach(struct device *, struct device *, void *);
int inteldrm_detach(struct device *, int);
@@ -2106,6 +2132,7 @@ struct cfdriver inteldrm_cd = {
0, "inteldrm", DV_DULL
};
+void inteldrm_init_backlight(struct inteldrm_softc *);
int inteldrm_intr(void *);
int
@@ -2126,7 +2153,6 @@ inteldrm_attach(struct device *parent, struct device *self, void *aux)
struct pci_attach_args *pa = aux;
const struct drm_pcidev *id;
struct intel_device_info *info, *device_info;
- struct intel_connector *intel_connector;
struct rasops_info *ri = &dev_priv->ro;
struct wsemuldisplaydev_attach_args aa;
extern int vga_console_attached;
@@ -2242,18 +2268,7 @@ inteldrm_attach(struct device *parent, struct device *self, void *aux)
intel_fbdev_restore_mode(dev);
- /* Grab backlight from the first connector that has one. */
- drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
- list_for_each_entry(intel_connector, &dev->mode_config.connector_list,
- base.head) {
- struct intel_panel *panel = &intel_connector->panel;
-
- if (panel->backlight.present) {
- dev_priv->backlight = panel->backlight.device;
- break;
- }
- }
- drm_modeset_unlock(&dev->mode_config.connection_mutex);
+ inteldrm_init_backlight(dev_priv);
ri->ri_flg = RI_CENTER | RI_WRONLY | RI_VCONS | RI_CLEAR;
ri->ri_hw = dev_priv;
@@ -2329,6 +2344,85 @@ inteldrm_activate(struct device *self, int act)
return (rv);
}
+void
+inteldrm_native_backlight(struct inteldrm_softc *dev_priv)
+{
+ struct drm_device *dev = dev_priv->dev;
+ struct intel_connector *intel_connector;
+
+ list_for_each_entry(intel_connector,
+ &dev->mode_config.connector_list, base.head) {
+ struct drm_connector *connector = &intel_connector->base;
+ struct intel_panel *panel = &intel_connector->panel;
+ struct backlight_device *bd = panel->backlight.device;
+
+ if (!panel->backlight.present)
+ continue;
+
+ connector->backlight_device = bd;
+ connector->backlight_property = drm_property_create_range(dev,
+ 0, "Backlight", 0, bd->props.max_brightness);
+ drm_object_attach_property(&connector->base,
+ connector->backlight_property, bd->props.brightness);
+
+ /*
+ * Use backlight from the first connector that has one
+ * for wscons(4).
+ */
+ if (dev_priv->backlight == NULL)
+ dev_priv->backlight = bd;
+ }
+}
+
+void
+inteldrm_firmware_backlight(struct inteldrm_softc *dev_priv,
+ struct wsdisplay_param *dp)
+{
+ struct drm_device *dev = dev_priv->dev;
+ struct intel_connector *intel_connector;
+ struct backlight_properties props;
+ struct backlight_device *bd;
+
+ memset(&props, 0, sizeof(props));
+ props.type = BACKLIGHT_FIRMWARE;
+ props.brightness = dp->curval;
+ bd = backlight_device_register(dev->device.dv_xname, NULL, NULL,
+ &inteldrm_backlight_ops, &props);
+
+ list_for_each_entry(intel_connector,
+ &dev->mode_config.connector_list, base.head) {
+ struct drm_connector *connector = &intel_connector->base;
+
+ if (connector->connector_type != DRM_MODE_CONNECTOR_LVDS &&
+ connector->connector_type != DRM_MODE_CONNECTOR_eDP &&
+ connector->connector_type != DRM_MODE_CONNECTOR_DSI)
+ continue;
+
+ connector->backlight_device = bd;
+ connector->backlight_property = drm_property_create_range(dev,
+ 0, "Backlight", dp->min, dp->max);
+ drm_object_attach_property(&connector->base,
+ connector->backlight_property, dp->curval);
+ }
+}
+
+void
+inteldrm_init_backlight(struct inteldrm_softc *dev_priv)
+{
+ struct drm_device *dev = dev_priv->dev;
+ struct wsdisplay_param dp;
+
+ drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
+
+ dp.param = WSDISPLAYIO_PARAM_BRIGHTNESS;
+ if (ws_get_param && ws_get_param(&dp) == 0)
+ inteldrm_firmware_backlight(dev_priv, &dp);
+ else
+ inteldrm_native_backlight(dev_priv);
+
+ drm_modeset_unlock(&dev->mode_config.connection_mutex);
+}
+
int
inteldrm_intr(void *arg)
{