Diff below publishes a "Backlight" property that can be used to get
and set the backlight associated with a particular output.  This
property can easily be exported by the X11 graphics drivers trough the
RandR protocol.  A future diff will let the "modesetting" driver do
this and make xbacklight(1) work.

The diff is a it tricky because tjere are some locking issues that
need to be worked around.  That is why the backlight is updated
asynchronously, and "raw" backlight devices return the cached value
instead of querying the hardware.

ok?


Index: dev/pci/drm/drm_crtc.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/drm/drm_crtc.c,v
retrieving revision 1.25
diff -u -p -r1.25 drm_crtc.c
--- dev/pci/drm/drm_crtc.c      1 Jul 2017 16:00:25 -0000       1.25
+++ dev/pci/drm/drm_crtc.c      9 Jul 2017 21:32:53 -0000
@@ -4049,6 +4049,23 @@ int drm_object_property_get_value(struct
 {
        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_pr
                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);
 
Index: dev/pci/drm/drm_crtc.h
===================================================================
RCS file: /cvs/src/sys/dev/pci/drm/drm_crtc.h,v
retrieving revision 1.10
diff -u -p -r1.10 drm_crtc.h
--- dev/pci/drm/drm_crtc.h      1 Jul 2017 16:00:25 -0000       1.10
+++ dev/pci/drm/drm_crtc.h      9 Jul 2017 21:32:54 -0000
@@ -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
 };
 
 /**
Index: dev/pci/drm/drm_linux.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/drm/drm_linux.c,v
retrieving revision 1.14
diff -u -p -r1.14 drm_linux.c
--- dev/pci/drm/drm_linux.c     5 Jul 2017 20:30:13 -0000       1.14
+++ dev/pci/drm/drm_linux.c     9 Jul 2017 21:32:54 -0000
@@ -697,6 +697,12 @@ acpi_get_table_with_size(const char *sig
 
 #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 *na
        bd->ops = ops;
        bd->props = *props;
        bd->data = data;
+
+       task_set(&bd->task, backlight_do_update_status, bd);
        
        return bd;
 }
@@ -715,4 +723,10 @@ void
 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);
 }
Index: dev/pci/drm/drm_linux.h
===================================================================
RCS file: /cvs/src/sys/dev/pci/drm/drm_linux.h,v
retrieving revision 1.53
diff -u -p -r1.53 drm_linux.h
--- dev/pci/drm/drm_linux.h     5 Jul 2017 20:30:13 -0000       1.53
+++ dev/pci/drm/drm_linux.h     9 Jul 2017 21:32:54 -0000
@@ -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
Index: dev/pci/drm/i915/i915_drv.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/drm/i915/i915_drv.c,v
retrieving revision 1.104
diff -u -p -r1.104 i915_drv.c
--- dev/pci/drm/i915/i915_drv.c 5 Jul 2017 20:30:13 -0000       1.104
+++ dev/pci/drm/i915/i915_drv.c 9 Jul 2017 21:32:54 -0000
@@ -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, s
        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, s
 
        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;
@@ -2327,6 +2342,85 @@ inteldrm_activate(struct device *self, i
        }
 
        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

Reply via email to