Index: i915/i915_debug.c =================================================================== --- i915/i915_debug.c (revision 277875) +++ i915/i915_debug.c (working copy) @@ -724,7 +724,7 @@ for (i = 0; i < DRM_ARRAY_SIZE(error->ring); i++) { struct drm_i915_error_object *obj; - + if ((obj = error->ring[i].batchbuffer)) { sbuf_printf(m, "%s --- gtt_offset = 0x%08x\n", dev_priv->rings[i].name, @@ -1590,6 +1590,38 @@ return (0); } +// NB - only works when y != 0! +#define U_CEIL_DIV(x, y) ((x) + (y) - 1) / (y) + +static int +i915_backlight(SYSCTL_HANDLER_ARGS) +{ + struct drm_device *dev; + drm_i915_private_t *dev_priv; + int error; + u32 val, max; + + dev = arg1; + dev_priv = dev->dev_private; + if(dev_priv == NULL) + return (EBUSY); + DRM_LOCK(dev); + val = intel_panel_get_backlight(dev); + max = intel_panel_get_max_backlight(dev); + DRM_UNLOCK(dev); + + // XXX specific devices, works fine on ivy bridge though + val = (val * 100) / max; + error = sysctl_handle_int(oidp, &val, 0, req); + if (error || !req->newptr) + return (error); + val = U_CEIL_DIV(max * val, 100); + DRM_LOCK(dev); + intel_panel_set_backlight(dev, val); + DRM_UNLOCK(dev); + return (0); +} + static struct i915_info_sysctl_list { const char *name; int (*ptr)(struct drm_device *dev, struct sbuf *m, void *data); @@ -1753,6 +1785,11 @@ CTLFLAG_RW, &i915_intr_pf, 0, NULL); if (oid == NULL) return (ENOMEM); + oid = SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(top), OID_AUTO, + "i915_backlight", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, dev, + 0, i915_backlight, "I", NULL); + if (oid == NULL) + return (ENOMEM); error = drm_add_busid_modesetting(dev, ctx, top); if (error != 0) @@ -1764,6 +1801,5 @@ void i915_sysctl_cleanup(struct drm_device *dev) { - free(dev->sysctl_private, DRM_MEM_DRIVER); }