Date: Mon, 25 Aug 2014 22:37:19 +0400 (AMT) From: Hrant Dadivanyan <hrant@dadivanyan.net> To: Adrian Chadd <adrian@freebsd.org> Cc: "freebsd-mobile@freebsd.org" <freebsd-mobile@freebsd.org> Subject: Re: Fwd: svn commit: r270516 - head/sys/dev/drm2/i915 Message-ID: <E1XLz8p-000LdV-6g@pandora.amnic.net> In-Reply-To: <CAJ-Vmonw6WRDU5qqa1ogOkbb_gj%2BHjMO7ANbWt4dnkxdNV8hMg@mail.gmail.com>
next in thread | previous in thread | raw e-mail | index | archive | help
> This fixes the brightness on a Lenovo X230. The buttons don't yet work > - they end up setting the value +1 or -1 from the current setting, but > no further. > The same on Lenovo X1 Carbon with 10-STABLE - buttons do +1 or -1 only, but hw.acpi.video.lcd0.brightness accepts any value. Not all values actually changes the brightness, but some do - all tenths for example. hw.acpi.video.lcd0.fullpower and .economy are also ignored, but custom entry on /etc/devd.conf solves this by setting .brightness directly, depending on AC status. Finally can enjoy long battery life, thank you very much ! Hrant > But, I can at least now control the brightness on this damned thing! > > > -a > > > ---------- Forwarded message ---------- > From: Adrian Chadd <adrian@freebsd.org> > Date: 24 August 2014 22:03 > Subject: svn commit: r270516 - head/sys/dev/drm2/i915 > To: src-committers@freebsd.org, svn-src-all@freebsd.org, > svn-src-head@freebsd.org > > > Author: adrian > Date: Mon Aug 25 05:03:10 2014 > New Revision: 270516 > URL: http://svnweb.freebsd.org/changeset/base/270516 > > Log: > i915 driver - enable opregion handle; program CADL. > > add opregion handling for drm2 - which exposes some ACPI video configuration > pieces that some Lenovo laptop models use to flesh out which video device > to speak to. This enables the brightness control in ACPI to work > these models. > > The CADL bits are also important - it's used to figure out which ACPI > events to hook the brightness buttons into. It doesn't yet seem to work > for me, but it does for the OP. > > Tested: > > * Lenovo X230 (mine) > * OP: ASUS UX51VZ > > PR: 190186 > Submitted by: Henry Hu <henry.hu.sh@gmail.com> > Reviewed by: dumbbell > > Modified: > head/sys/dev/drm2/i915/i915_drv.h > head/sys/dev/drm2/i915/i915_irq.c > head/sys/dev/drm2/i915/intel_opregion.c > > Modified: head/sys/dev/drm2/i915/i915_drv.h > ============================================================================== > --- head/sys/dev/drm2/i915/i915_drv.h Mon Aug 25 03:02:38 2014 > (r270515) > +++ head/sys/dev/drm2/i915/i915_drv.h Mon Aug 25 05:03:10 2014 > (r270516) > @@ -1242,10 +1242,11 @@ extern void intel_iic_reset(struct drm_d > > /* intel_opregion.c */ > int intel_opregion_setup(struct drm_device *dev); > -extern int intel_opregion_init(struct drm_device *dev); > +extern void intel_opregion_init(struct drm_device *dev); > extern void intel_opregion_fini(struct drm_device *dev); > -extern void opregion_asle_intr(struct drm_device *dev); > -extern void opregion_enable_asle(struct drm_device *dev); > +extern void intel_opregion_asle_intr(struct drm_device *dev); > +extern void intel_opregion_gse_intr(struct drm_device *dev); > +extern void intel_opregion_enable_asle(struct drm_device *dev); > > /* i915_gem_gtt.c */ > int i915_gem_init_aliasing_ppgtt(struct drm_device *dev); > > Modified: head/sys/dev/drm2/i915/i915_irq.c > ============================================================================== > --- head/sys/dev/drm2/i915/i915_irq.c Mon Aug 25 03:02:38 2014 > (r270515) > +++ head/sys/dev/drm2/i915/i915_irq.c Mon Aug 25 05:03:10 2014 > (r270516) > @@ -537,11 +537,7 @@ ivybridge_irq_handler(void *arg) > notify_ring(dev, &dev_priv->rings[BCS]); > > if (de_iir & DE_GSE_IVB) { > -#if 1 > - KIB_NOTYET(); > -#else > intel_opregion_gse_intr(dev); > -#endif > } > > if (de_iir & DE_PLANEA_FLIP_DONE_IVB) { > @@ -649,11 +645,7 @@ ironlake_irq_handler(void *arg) > notify_ring(dev, &dev_priv->rings[BCS]); > > if (de_iir & DE_GSE) { > -#if 1 > - KIB_NOTYET(); > -#else > intel_opregion_gse_intr(dev); > -#endif > } > > if (de_iir & DE_PLANEA_FLIP_DONE) { > @@ -1055,11 +1047,7 @@ i915_driver_irq_handler(void *arg) > > > if (blc_event || (iir & I915_ASLE_INTERRUPT)) { > -#if 1 > - KIB_NOTYET(); > -#else > intel_opregion_asle_intr(dev); > -#endif > } > > /* With MSI, interrupts are only generated when iir > @@ -1781,11 +1769,7 @@ i915_driver_irq_postinstall(struct drm_d > I915_WRITE(PORT_HOTPLUG_EN, hotplug_en); > } > > -#if 1 > - KIB_NOTYET(); > -#else > intel_opregion_enable_asle(dev); > -#endif > > return 0; > } > > Modified: head/sys/dev/drm2/i915/intel_opregion.c > ============================================================================== > --- head/sys/dev/drm2/i915/intel_opregion.c Mon Aug 25 03:02:38 > 2014 (r270515) > +++ head/sys/dev/drm2/i915/intel_opregion.c Mon Aug 25 05:03:10 > 2014 (r270516) > @@ -32,6 +32,9 @@ __FBSDID("$FreeBSD$"); > #include <dev/drm2/i915/i915_drm.h> > #include <dev/drm2/i915/i915_drv.h> > #include <dev/drm2/i915/intel_drv.h> > +#include <contrib/dev/acpica/include/acpi.h> > +#include <contrib/dev/acpica/include/accommon.h> > +#include <dev/acpica/acpivar.h> > > #define PCI_ASLE 0xe4 > #define PCI_ASLS 0xfc > @@ -144,7 +147,7 @@ struct opregion_asle { > #define ACPI_DIGITAL_OUTPUT (3<<8) > #define ACPI_LVDS_OUTPUT (4<<8) > > -#ifdef CONFIG_ACPI > +#if 1 > static u32 asle_set_backlight(struct drm_device *dev, u32 bclp) > { > struct drm_i915_private *dev_priv = dev->dev_private; > @@ -289,6 +292,7 @@ void intel_opregion_enable_asle(struct d > > static struct intel_opregion *system_opregion; > > +#if 0 > static int intel_opregion_video_event(struct notifier_block *nb, > unsigned long val, void *data) > { > @@ -319,6 +323,7 @@ static int intel_opregion_video_event(st > static struct notifier_block intel_opregion_notifier = { > .notifier_call = intel_opregion_video_event, > }; > +#endif > > /* > * Initialise the DIDL field in opregion. This passes a list of devices to > @@ -326,37 +331,72 @@ static struct notifier_block intel_opreg > * (version 3) > */ > > +static int acpi_is_video_device(ACPI_HANDLE devh) { > + ACPI_HANDLE h; > + if (ACPI_FAILURE(AcpiGetHandle(devh, "_DOD", &h)) || > + ACPI_FAILURE(AcpiGetHandle(devh, "_DOS", &h))) { > + return 0; > + } > + return 1; > +} > + > static void intel_didl_outputs(struct drm_device *dev) > { > struct drm_i915_private *dev_priv = dev->dev_private; > struct intel_opregion *opregion = &dev_priv->opregion; > struct drm_connector *connector; > - acpi_handle handle; > - struct acpi_device *acpi_dev, *acpi_cdev, *acpi_video_bus = NULL; > - unsigned long long device_id; > - acpi_status status; > + u32 device_id; > + ACPI_HANDLE handle, acpi_video_bus, acpi_cdev; > + ACPI_STATUS status; > int i = 0; > > - handle = DEVICE_ACPI_HANDLE(&dev->pdev->dev); > - if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &acpi_dev))) > + handle = acpi_get_handle(dev->device); > + if (!handle) > return; > > - if (acpi_is_video_device(acpi_dev)) > - acpi_video_bus = acpi_dev; > + if (acpi_is_video_device(handle)) > + acpi_video_bus = handle; > else { > + acpi_cdev = NULL; > + acpi_video_bus = NULL; > + while (AcpiGetNextObject(ACPI_TYPE_DEVICE, handle, acpi_cdev, > + &acpi_cdev) != AE_NOT_FOUND) { > + if (acpi_is_video_device(acpi_cdev)) { > + acpi_video_bus = acpi_cdev; > + break; > + } > + } > +#if 0 > list_for_each_entry(acpi_cdev, &acpi_dev->children, node) { > if (acpi_is_video_device(acpi_cdev)) { > acpi_video_bus = acpi_cdev; > break; > } > } > +#endif > } > > if (!acpi_video_bus) { > - printk(KERN_WARNING "No ACPI video bus found\n"); > + device_printf(dev->device, "No ACPI video bus found\n"); > return; > } > > + acpi_cdev = NULL; > + while (AcpiGetNextObject(ACPI_TYPE_DEVICE, acpi_video_bus, acpi_cdev, > + &acpi_cdev) != AE_NOT_FOUND) { > + if (i >= 8) { > + device_printf(dev->device, "More than 8 > outputs detected\n"); > + return; > + } > + status = acpi_GetInteger(acpi_cdev, "_ADR", &device_id); > + if (ACPI_SUCCESS(status)) { > + if (!device_id) > + goto blind_set; > + opregion->acpi->didl[i] = (u32)(device_id & 0x0f0f); > + i++; > + } > + } > +#if 0 > list_for_each_entry(acpi_cdev, &acpi_video_bus->children, node) { > if (i >= 8) { > dev_printk(KERN_ERR, &dev->pdev->dev, > @@ -373,6 +413,7 @@ static void intel_didl_outputs(struct dr > i++; > } > } > +#endif > > end: > /* If fewer than 8 outputs, the list must be null terminated */ > @@ -417,6 +458,25 @@ blind_set: > goto end; > } > > +static void intel_setup_cadls(struct drm_device *dev) > +{ > + struct drm_i915_private *dev_priv = dev->dev_private; > + struct intel_opregion *opregion = &dev_priv->opregion; > + int i = 0; > + u32 disp_id; > + > + /* Initialize the CADL field by duplicating the DIDL values. > + * Technically, this is not always correct as display outputs may exist, > + * but not active. This initialization is necessary for some Clevo > + * laptops that check this field before processing the brightness and > + * display switching hotkeys. Just like DIDL, CADL is NULL-terminated if > + * there are less than eight devices. */ > + do { > + disp_id = opregion->acpi->didl[i]; > + opregion->acpi->cadl[i] = disp_id; > + } while (++i < 8 && disp_id != 0); > +} > + > void intel_opregion_init(struct drm_device *dev) > { > struct drm_i915_private *dev_priv = dev->dev_private; > @@ -426,8 +486,10 @@ void intel_opregion_init(struct drm_devi > return; > > if (opregion->acpi) { > - if (drm_core_check_feature(dev, DRIVER_MODESET)) > + if (drm_core_check_feature(dev, DRIVER_MODESET)) { > intel_didl_outputs(dev); > + intel_setup_cadls(dev); > + } > > /* Notify BIOS we are ready to handle ACPI video ext notifs. > * Right now, all the events are handled by the ACPI > video module. > @@ -436,7 +498,9 @@ void intel_opregion_init(struct drm_devi > opregion->acpi->drdy = 1; > > system_opregion = opregion; > +#if 0 > register_acpi_notifier(&intel_opregion_notifier); > +#endif > } > > if (opregion->asle) > @@ -455,11 +519,13 @@ void intel_opregion_fini(struct drm_devi > opregion->acpi->drdy = 0; > > system_opregion = NULL; > +#if 0 > unregister_acpi_notifier(&intel_opregion_notifier); > +#endif > } > > /* just clear all opregion memory pointers now */ > - iounmap(opregion->header); > + pmap_unmapdev((vm_offset_t)opregion->header, OPREGION_SIZE); > opregion->header = NULL; > opregion->acpi = NULL; > opregion->swsci = NULL; > _______________________________________________ > freebsd-mobile@freebsd.org mailing list > http://lists.freebsd.org/mailman/listinfo/freebsd-mobile > To unsubscribe, send any mail to "freebsd-mobile-unsubscribe@freebsd.org" -- Hrant Dadivanyan (aka Ran d'Adi) hrant(at)dadivanyan.net /* "Feci quod potui, faciant meliora potentes." */ ran(at)psg.com
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?E1XLz8p-000LdV-6g>