summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
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)
{