Fwd: svn commit: r270516 - head/sys/dev/drm2/i915
Hrant Dadivanyan
hrant at dadivanyan.net
Mon Aug 25 18:37:24 UTC 2014
> 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 at freebsd.org>
> Date: 24 August 2014 22:03
> Subject: svn commit: r270516 - head/sys/dev/drm2/i915
> To: src-committers at freebsd.org, svn-src-all at freebsd.org,
> svn-src-head at 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 at 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 at freebsd.org mailing list
> http://lists.freebsd.org/mailman/listinfo/freebsd-mobile
> To unsubscribe, send any mail to "freebsd-mobile-unsubscribe at freebsd.org"
--
Hrant Dadivanyan (aka Ran d'Adi) hrant(at)dadivanyan.net
/* "Feci quod potui, faciant meliora potentes." */ ran(at)psg.com
More information about the freebsd-mobile
mailing list