diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2017-07-12 20:12:20 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2017-07-12 20:12:20 +0000 |
commit | 2053b3486507d89f1f0a3ed7db4b8829c844989c (patch) | |
tree | 6f79c3713f982eb150d1a308ed4f08a312e4640d /sys/dev | |
parent | 26ab0089e07ff2c4bdb037b73410fb6a177012bf (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.c | 23 | ||||
-rw-r--r-- | sys/dev/pci/drm/drm_crtc.h | 5 | ||||
-rw-r--r-- | sys/dev/pci/drm/drm_linux.c | 16 | ||||
-rw-r--r-- | sys/dev/pci/drm/drm_linux.h | 10 | ||||
-rw-r--r-- | sys/dev/pci/drm/i915/i915_drv.c | 120 |
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) { |