Module Name: src Committed By: riastradh Date: Tue Jul 1 20:03:21 UTC 2014
Modified Files: src/sys/external/bsd/drm2/i915drm: i915_pci.c Log Message: Implement i915drmkms wsdisplay blank/backlight/brightness controls. To generate a diff of this commit: cvs rdiff -u -r1.8 -r1.9 src/sys/external/bsd/drm2/i915drm/i915_pci.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/external/bsd/drm2/i915drm/i915_pci.c diff -u src/sys/external/bsd/drm2/i915drm/i915_pci.c:1.8 src/sys/external/bsd/drm2/i915drm/i915_pci.c:1.9 --- src/sys/external/bsd/drm2/i915drm/i915_pci.c:1.8 Fri Apr 25 19:02:51 2014 +++ src/sys/external/bsd/drm2/i915drm/i915_pci.c Tue Jul 1 20:03:21 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: i915_pci.c,v 1.8 2014/04/25 19:02:51 riastradh Exp $ */ +/* $NetBSD: i915_pci.c,v 1.9 2014/07/01 20:03:21 riastradh Exp $ */ /*- * Copyright (c) 2013 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: i915_pci.c,v 1.8 2014/04/25 19:02:51 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: i915_pci.c,v 1.9 2014/07/01 20:03:21 riastradh Exp $"); #ifdef _KERNEL_OPT #include "vga.h" @@ -73,6 +73,8 @@ struct i915drm_softc { struct drm_i915_gem_object *sc_fb_obj; bus_space_handle_t sc_fb_bsh; struct genfb_softc sc_genfb; + struct genfb_parameter_callback sc_genfb_backlight_callback; + struct genfb_parameter_callback sc_genfb_brightness_callback; struct list_head sc_fb_list; /* XXX Kludge! */ bool sc_console; }; @@ -97,10 +99,19 @@ static int i915drm_fb_create_handle(stru struct drm_file *, unsigned int *); static void i915drm_fb_destroy(struct drm_framebuffer *); +static int i915drm_fb_dpms(struct i915drm_softc *, int); + static int i915drm_genfb_ioctl(void *, void *, unsigned long, void *, int, struct lwp *); static paddr_t i915drm_genfb_mmap(void *, void *, off_t, int); +static int i915drm_genfb_get_backlight(void *, int *); +static int i915drm_genfb_set_backlight(void *, int); +static int i915drm_genfb_upd_backlight(void *, int); +static int i915drm_genfb_get_brightness(void *, int *); +static int i915drm_genfb_set_brightness(void *, int); +static int i915drm_genfb_upd_brightness(void *, int); + CFATTACH_DECL_NEW(i915drmkms, sizeof(struct i915drm_softc), i915drm_match, i915drm_attach, i915drm_detach, NULL); @@ -467,6 +478,25 @@ i915drm_fb_probe(struct drm_fb_helper *f CTASSERT(sizeof(uintptr_t) <= sizeof(uint64_t)); prop_dictionary_set_uint64(dict, "virtual_address", (uint64_t)(uintptr_t)bus_space_vaddr(dev->bst, sc->sc_fb_bsh)); + + sc->sc_genfb_backlight_callback = (struct genfb_parameter_callback) { + .gpc_cookie = sc, + .gpc_get_parameter = &i915drm_genfb_get_backlight, + .gpc_set_parameter = &i915drm_genfb_set_backlight, + .gpc_upd_parameter = &i915drm_genfb_upd_backlight, + }; + prop_dictionary_set_uint64(dict, "backlight_callback", + (uint64_t)(uintptr_t)&sc->sc_genfb_backlight_callback); + + sc->sc_genfb_brightness_callback = (struct genfb_parameter_callback) { + .gpc_cookie = sc, + .gpc_get_parameter = &i915drm_genfb_get_brightness, + .gpc_set_parameter = &i915drm_genfb_set_brightness, + .gpc_upd_parameter = &i915drm_genfb_upd_brightness, + }; + prop_dictionary_set_uint64(dict, "brightness_callback", + (uint64_t)(uintptr_t)&sc->sc_genfb_brightness_callback); + sc->sc_genfb.sc_dev = sc->sc_dev; genfb_init(&sc->sc_genfb); @@ -494,6 +524,28 @@ fail0: KASSERT(ret < 0); return ret; } +static int +i915drm_fb_dpms(struct i915drm_softc *sc, int dpms_mode) +{ + struct drm_device *const dev = &sc->sc_drm_dev; + struct drm_i915_private *const dev_priv = dev->dev_private; + /* XXX What guarantees dev_priv->fbdev stays around? */ + struct drm_fb_helper *const fb_helper = &dev_priv->fbdev->helper; + unsigned i; + + mutex_lock(&dev->mode_config.mutex); + for (i = 0; i < fb_helper->connector_count; i++) { + struct drm_connector *const connector = + fb_helper->connector_info[i]->connector; + (*connector->funcs->dpms)(connector, dpms_mode); + drm_object_property_set_value(&connector->base, + dev->mode_config.dpms_property, dpms_mode); + } + mutex_unlock(&dev->mode_config.mutex); + + return 0; +} + static void i915drm_fb_detach(struct drm_fb_helper *fb_helper) { @@ -549,6 +601,29 @@ i915drm_genfb_ioctl(void *v, void *vs, u return wsdisplayio_busid_pci(genfb->sc_dev, pa->pa_pc, pa->pa_tag, data); + /* + * Screen blanking ioctls. Not to be confused with backlight + * (can be disabled while stuff is still drawn on the screen), + * brightness, or contrast (which we don't support). Backlight + * and brightness are done through WSDISPLAYIO_{GET,SET}PARAM. + * This toggles between DPMS ON and DPMS OFF; backlight toggles + * between DPMS ON and DPMS SUSPEND. + */ + case WSDISPLAYIO_GVIDEO: { + int *onp = (int *)data; + + /* XXX Can't really determine a single answer here. */ + *onp = 1; + return 0; + } + + case WSDISPLAYIO_SVIDEO: { + const int on = *(const int *)data; + + return i915drm_fb_dpms(sc, + on? DRM_MODE_DPMS_ON : DRM_MODE_DPMS_OFF); + } + default: return EPASSTHROUGH; } @@ -613,3 +688,69 @@ i915drm_genfb_mmap(void *v, void *vs, of /* Failure! */ return -1; } + +static int +i915drm_genfb_get_backlight(void *cookie, int *enablep) +{ + struct i915drm_softc *const sc = cookie; + struct drm_device *const dev = &sc->sc_drm_dev; + struct drm_i915_private *const dev_priv = dev->dev_private; + + *enablep = dev_priv->backlight_enabled; + + return 0; +} + +static int +i915drm_genfb_set_backlight(void *cookie, int enable) +{ + struct i915drm_softc *const sc = cookie; + + return i915drm_fb_dpms(sc, + enable? DRM_MODE_DPMS_ON : DRM_MODE_DPMS_SUSPEND); +} + +static int +i915drm_genfb_upd_backlight(void *cookie __unused, int step __unused) +{ + + panic("can't update i915drm backlight"); +} + +static int +i915drm_genfb_get_brightness(void *cookie, int *brightnessp) +{ + struct i915drm_softc *const sc = cookie; + struct drm_device *const dev = &sc->sc_drm_dev; + struct drm_i915_private *const dev_priv = dev->dev_private; + + *brightnessp = dev_priv->backlight_level; + + return 0; +} + +static int +i915drm_genfb_set_brightness(void *cookie, int brightness) +{ + struct i915drm_softc *const sc = cookie; + struct drm_device *const dev = &sc->sc_drm_dev; + + intel_panel_set_backlight(dev, + MIN(brightness, intel_panel_get_max_backlight(dev))); + + return 0; +} + +static int +i915drm_genfb_upd_brightness(void *cookie, int delta) +{ + struct i915drm_softc *const sc = cookie; + struct drm_device *const dev = &sc->sc_drm_dev; + struct drm_i915_private *const dev_priv = dev->dev_private; + + intel_panel_set_backlight(dev, + MIN(dev_priv->backlight_level + delta, + intel_panel_get_max_backlight(dev))); + + return 0; +}