linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2] mba6x_bl: Backlight driver for mid 2013 MacBook Air
@ 2014-04-29 14:21 Patrik Jakobsson
  2014-04-30  8:19 ` Hans de Goede
  2014-05-05 14:49 ` Patrik Jakobsson
  0 siblings, 2 replies; 5+ messages in thread
From: Patrik Jakobsson @ 2014-04-29 14:21 UTC (permalink / raw)
  To: platform-driver-x86; +Cc: linux-kernel, hdegoede, matthew.garrett

This driver takes control over the LP8550 backlight driver chip found
in the mid 2013 and newer MacBook Air (6,1 and 6,2). The i915 GPU driver
cannot properly restore the backlight after resume, but with this driver
we can hijack the LP8550 and get fully functional backlight support.

v2: - Dropped "if ACPI" in Kconfig since we already depend on it
    - Added comment about brightness mapping
    - Removed lp8550_init() from set_brightness()
    - Always write to dev_ctl when setting brightness
    - Change %Ld to standard C %lld
    - Constify the backlight_ops struct

Signed-off-by: Patrik Jakobsson <patrik.r.jakobsson@gmail.com>
---
 MAINTAINERS                     |   6 +
 drivers/platform/x86/Kconfig    |  13 ++
 drivers/platform/x86/Makefile   |   1 +
 drivers/platform/x86/mba6x_bl.c | 353 ++++++++++++++++++++++++++++++++++++++++
 4 files changed, 373 insertions(+)
 create mode 100644 drivers/platform/x86/mba6x_bl.c

diff --git a/MAINTAINERS b/MAINTAINERS
index e67ea24..cad3e82 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5576,6 +5576,12 @@ T:	git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git
 S:	Maintained
 F:	net/mac80211/rc80211_pid*
 
+MACBOOK AIR 6,X BACKLIGHT DRIVER
+M:	Patrik Jakobsson <patrik.r.jakobsson@gmail.com>
+L:	platform-driver-x86@vger.kernel.org
+S:	Maintained
+F:	drivers/platform/x86/mba6x_bl.c
+
 MACVLAN DRIVER
 M:	Patrick McHardy <kaber@trash.net>
 L:	netdev@vger.kernel.org
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index 27df2c5..10ac918 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -795,6 +795,19 @@ config APPLE_GMUX
 	  graphics as well as the backlight. Currently only backlight
 	  control is supported by the driver.
 
+config MBA6X_BL
+	tristate "MacBook Air 6,x backlight driver"
+	depends on ACPI
+	depends on BACKLIGHT_CLASS_DEVICE
+	select ACPI_VIDEO
+	help
+	 This driver takes control over the LP8550 backlight driver found in
+	 some MacBook Air models. Say Y here if you have a MacBook Air from mid
+	 2013 or newer.
+
+	 To compile this driver as a module, choose M here: the module will
+	 be called mba6x_bl.
+
 config INTEL_RST
         tristate "Intel Rapid Start Technology Driver"
 	depends on ACPI
diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile
index 1a2eafc..9a182fe 100644
--- a/drivers/platform/x86/Makefile
+++ b/drivers/platform/x86/Makefile
@@ -56,3 +56,4 @@ obj-$(CONFIG_INTEL_SMARTCONNECT)	+= intel-smartconnect.o
 
 obj-$(CONFIG_PVPANIC)           += pvpanic.o
 obj-$(CONFIG_ALIENWARE_WMI)	+= alienware-wmi.o
+obj-$(CONFIG_MBA6X_BL)		+= mba6x_bl.o
diff --git a/drivers/platform/x86/mba6x_bl.c b/drivers/platform/x86/mba6x_bl.c
new file mode 100644
index 0000000..c549667
--- /dev/null
+++ b/drivers/platform/x86/mba6x_bl.c
@@ -0,0 +1,353 @@
+/*
+ * MacBook Air 6,1 and 6,2 (mid 2013) backlight driver
+ *
+ * Copyright (C) 2014 Patrik Jakobsson (patrik.r.jakobsson@gmail.com)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/backlight.h>
+#include <linux/acpi.h>
+#include <acpi/acpi.h>
+#include <acpi/video.h>
+
+#define LP8550_SMBUS_ADDR	(0x58 >> 1)
+#define LP8550_REG_BRIGHTNESS	0
+#define LP8550_REG_DEV_CTL	1
+#define LP8550_REG_FAULT	2
+#define LP8550_REG_IDENT	3
+#define LP8550_REG_DIRECT_CTL	4
+#define LP8550_REG_TEMP_MSB	5 /* Must be read before TEMP_LSB */
+#define LP8550_REG_TEMP_LSB	6
+
+#define INIT_BRIGHTNESS		150
+
+static struct {
+	u8 brightness;	/* Brightness control */
+	u8 dev_ctl;	/* Device control */
+	u8 fault;	/* Fault indication */
+	u8 ident;	/* Identification */
+	u8 direct_ctl;	/* Direct control */
+	u8 temp_msb;	/* Temperature MSB  */
+	u8 temp_lsb;	/* Temperature LSB */
+} lp8550_regs;
+
+static struct platform_device *platform_device;
+static struct backlight_device *backlight_device;
+
+static int lp8550_reg_read(u8 reg, u8 *val)
+{
+	acpi_status status;
+	acpi_handle handle;
+	struct acpi_object_list arg_list;
+	struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
+	union acpi_object args[2];
+	union acpi_object *result;
+	int ret = 0;
+
+	status = acpi_get_handle(NULL, "\\_SB.PCI0.SBUS.SRDB", &handle);
+	if (ACPI_FAILURE(status)) {
+		pr_debug("mba6x_bl: Failed to get acpi handle\n");
+		ret = -ENODEV;
+		goto out;
+	}
+
+	args[0].type = ACPI_TYPE_INTEGER;
+	args[0].integer.value = (LP8550_SMBUS_ADDR << 1) | 1;
+
+	args[1].type = ACPI_TYPE_INTEGER;
+	args[1].integer.value = reg;
+
+	arg_list.count = 2;
+	arg_list.pointer = args;
+
+	status = acpi_evaluate_object(handle, NULL, &arg_list, &buffer);
+	if (ACPI_FAILURE(status)) {
+		pr_debug("mba6x_bl: Failed to read reg: 0x%x\n", reg);
+		ret = -ENODEV;
+		goto out;
+	}
+
+	result = buffer.pointer;
+
+	if (result->type != ACPI_TYPE_INTEGER) {
+		pr_debug("mba6x_bl: Invalid response in reg: 0x%x (len: %Ld)\n",
+			 reg, buffer.length);
+		ret = -EINVAL;
+		goto out;
+	}
+
+	*val = (u8)result->integer.value;
+out:
+	kfree(buffer.pointer);
+	return ret;
+}
+
+static int lp8550_reg_write(u8 reg, u8 val)
+{
+	acpi_status status;
+	acpi_handle handle;
+	struct acpi_object_list arg_list;
+	struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
+	union acpi_object args[3];
+	union acpi_object *result;
+	int ret = 0;
+
+	status = acpi_get_handle(NULL, "\\_SB.PCI0.SBUS.SWRB", &handle);
+	if (ACPI_FAILURE(status)) {
+		pr_debug("mba6x_bl: Failed to get acpi handle\n");
+		ret = -ENODEV;
+		goto out;
+	}
+
+	args[0].type = ACPI_TYPE_INTEGER;
+	args[0].integer.value = (LP8550_SMBUS_ADDR << 1) & ~1;
+
+	args[1].type = ACPI_TYPE_INTEGER;
+	args[1].integer.value = reg;
+
+	args[2].type = ACPI_TYPE_INTEGER;
+	args[2].integer.value = val;
+
+	arg_list.count = 3;
+	arg_list.pointer = args;
+
+	status = acpi_evaluate_object(handle, NULL, &arg_list, &buffer);
+	if (ACPI_FAILURE(status)) {
+		pr_debug("mba6x_bl: Failed to write reg: 0x%x\n", reg);
+		ret = -ENODEV;
+		goto out;
+	}
+
+	result = buffer.pointer;
+
+	if (result->type != ACPI_TYPE_INTEGER || result->integer.value != 1) {
+		pr_debug("mba6x_bl: Invalid response at reg: 0x%x (len: %lld)\n",
+			 reg, buffer.length);
+		ret = -EINVAL;
+		goto out;
+	}
+
+out:
+	kfree(buffer.pointer);
+	return ret;
+}
+
+/*
+ * Map the brightness value to an exponential curve. This makes the perceived
+ * brightness more linear and allows to make better use of the available
+ * brightness range.
+ */
+static inline int map_brightness(int b)
+{
+	return ((b * b + 254) / 255);
+}
+
+static int set_brightness(int brightness)
+{
+	int ret;
+
+	if (brightness < 0 || brightness > 255)
+		return -EINVAL;
+
+	brightness = map_brightness(brightness);
+	ret = lp8550_reg_write(LP8550_REG_BRIGHTNESS, (u8)brightness);
+	if (ret)
+		return ret;
+
+	ret = lp8550_reg_write(LP8550_REG_DEV_CTL, 0x05);
+	return ret;
+}
+
+static int get_brightness(struct backlight_device *bdev)
+{
+	return bdev->props.brightness;
+}
+
+static int update_status(struct backlight_device *bdev)
+{
+	return set_brightness(bdev->props.brightness);
+}
+
+static int lp8550_probe(void)
+{
+	u8 val;
+	int ret;
+
+	ret = lp8550_reg_read(LP8550_REG_IDENT, &val);
+	if (ret)
+		return ret;
+
+	if (val != 0xfc)
+		return -ENODEV;
+
+	pr_info("mba6x_bl: Found LP8550 backlight driver\n");
+	return 0;
+}
+
+static int lp8550_save(void)
+{
+	int ret;
+
+	ret = lp8550_reg_read(LP8550_REG_DEV_CTL, &lp8550_regs.dev_ctl);
+	if (ret)
+		return ret;
+
+	ret = lp8550_reg_read(LP8550_REG_BRIGHTNESS, &lp8550_regs.brightness);
+	return ret;
+}
+
+
+static int lp8550_restore(void)
+{
+	int ret;
+
+	ret = lp8550_reg_write(LP8550_REG_BRIGHTNESS, lp8550_regs.brightness);
+	if (ret)
+		return ret;
+
+	ret = lp8550_reg_write(LP8550_REG_DEV_CTL, lp8550_regs.dev_ctl);
+	return ret;
+}
+
+static int lp8550_init(void)
+{
+	int ret, i;
+
+	for (i = 0; i < 10; i++) {
+		ret = lp8550_reg_write(LP8550_REG_BRIGHTNESS, INIT_BRIGHTNESS);
+		if (!ret)
+			break;
+	}
+
+	if (i > 0)
+		pr_err("mba6x_bl: Init retries: %d\n", i);
+
+	if (ret)
+		return ret;
+
+	ret = lp8550_reg_write(LP8550_REG_DEV_CTL, 0x05);
+	return ret;
+}
+
+static const struct backlight_ops backlight_ops = {
+	.update_status = update_status,
+	.get_brightness = get_brightness,
+};
+
+static struct platform_driver drv;
+
+static int platform_probe(struct platform_device *dev)
+{
+	struct backlight_properties props;
+	int ret;
+
+	ret = lp8550_probe();
+	if (ret)
+		return ret;
+
+	ret = lp8550_save();
+	if (ret)
+		return ret;
+
+	ret = lp8550_init();
+	if (ret)
+		return ret;
+
+	memset(&props, 0, sizeof(struct backlight_properties));
+	props.max_brightness = 255;
+	props.brightness = INIT_BRIGHTNESS;
+	props.type = BACKLIGHT_FIRMWARE;
+
+	backlight_device = backlight_device_register("mba6x_backlight",
+						     NULL, NULL,
+						     &backlight_ops, &props);
+	if (IS_ERR(backlight_device)) {
+		pr_err("mba6x_bl: Failed to register backlight device\n");
+		return PTR_ERR(backlight_device);
+	}
+
+	acpi_video_dmi_promote_vendor();
+	acpi_video_unregister();
+
+	backlight_update_status(backlight_device);
+
+	return 0;
+}
+
+static int platform_remove(struct platform_device *dev)
+{
+	backlight_device_unregister(backlight_device);
+	lp8550_restore();
+	pr_info("mba6x_bl: Restored old configuration\n");
+
+	return 0;
+}
+
+static int platform_resume(struct platform_device *dev)
+{
+	/*
+	 * Firmware restores the LP8550 for us but we might need some tweaking
+	 * in the future if firmware behaviour is changed.
+	 */
+	return 0;
+}
+
+static void platform_shutdown(struct platform_device *dev)
+{
+	/* We must restore or screen might go black on reboot */
+	lp8550_restore();
+}
+
+static struct platform_driver drv = {
+	.probe		= platform_probe,
+	.remove		= platform_remove,
+	.resume		= platform_resume,
+	.shutdown	= platform_shutdown,
+	.driver	= {
+		.name = "mba6x_bl",
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init mba6x_bl_init(void)
+{
+	int ret;
+
+	ret = platform_driver_register(&drv);
+	if (ret) {
+		pr_err("Failed to register platform driver\n");
+		return ret;
+	}
+
+	platform_device = platform_device_register_simple("mba6x_bl", -1, NULL,
+							  0);
+	return 0;
+}
+
+static void __exit mba6x_bl_exit(void)
+{
+	platform_device_unregister(platform_device);
+	platform_driver_unregister(&drv);
+}
+
+module_init(mba6x_bl_init);
+module_exit(mba6x_bl_exit);
+
+MODULE_AUTHOR("Patrik Jakobsson <patrik.r.jakobsson@gmail.com>");
+MODULE_DESCRIPTION("MacBook Air 6,1 and 6,2 backlight driver");
+MODULE_LICENSE("GPL");
+
+MODULE_ALIAS("dmi:*:pnMacBookAir6*");
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH v2] mba6x_bl: Backlight driver for mid 2013 MacBook Air
  2014-04-29 14:21 [PATCH v2] mba6x_bl: Backlight driver for mid 2013 MacBook Air Patrik Jakobsson
@ 2014-04-30  8:19 ` Hans de Goede
  2014-05-05 14:49 ` Patrik Jakobsson
  1 sibling, 0 replies; 5+ messages in thread
From: Hans de Goede @ 2014-04-30  8:19 UTC (permalink / raw)
  To: Patrik Jakobsson, platform-driver-x86; +Cc: linux-kernel, matthew.garrett

Hi,

On 04/29/2014 04:21 PM, Patrik Jakobsson wrote:
> This driver takes control over the LP8550 backlight driver chip found
> in the mid 2013 and newer MacBook Air (6,1 and 6,2). The i915 GPU driver
> cannot properly restore the backlight after resume, but with this driver
> we can hijack the LP8550 and get fully functional backlight support.
> 
> v2: - Dropped "if ACPI" in Kconfig since we already depend on it
>     - Added comment about brightness mapping
>     - Removed lp8550_init() from set_brightness()
>     - Always write to dev_ctl when setting brightness
>     - Change %Ld to standard C %lld
>     - Constify the backlight_ops struct
> 
> Signed-off-by: Patrik Jakobsson <patrik.r.jakobsson@gmail.com>

Thanks for working on this, looks good:

Reviewed-by: Hans de Goede <hdegoede@redhat.com>

Regards,

Hans


> ---
>  MAINTAINERS                     |   6 +
>  drivers/platform/x86/Kconfig    |  13 ++
>  drivers/platform/x86/Makefile   |   1 +
>  drivers/platform/x86/mba6x_bl.c | 353 ++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 373 insertions(+)
>  create mode 100644 drivers/platform/x86/mba6x_bl.c
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index e67ea24..cad3e82 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -5576,6 +5576,12 @@ T:	git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git
>  S:	Maintained
>  F:	net/mac80211/rc80211_pid*
>  
> +MACBOOK AIR 6,X BACKLIGHT DRIVER
> +M:	Patrik Jakobsson <patrik.r.jakobsson@gmail.com>
> +L:	platform-driver-x86@vger.kernel.org
> +S:	Maintained
> +F:	drivers/platform/x86/mba6x_bl.c
> +
>  MACVLAN DRIVER
>  M:	Patrick McHardy <kaber@trash.net>
>  L:	netdev@vger.kernel.org
> diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
> index 27df2c5..10ac918 100644
> --- a/drivers/platform/x86/Kconfig
> +++ b/drivers/platform/x86/Kconfig
> @@ -795,6 +795,19 @@ config APPLE_GMUX
>  	  graphics as well as the backlight. Currently only backlight
>  	  control is supported by the driver.
>  
> +config MBA6X_BL
> +	tristate "MacBook Air 6,x backlight driver"
> +	depends on ACPI
> +	depends on BACKLIGHT_CLASS_DEVICE
> +	select ACPI_VIDEO
> +	help
> +	 This driver takes control over the LP8550 backlight driver found in
> +	 some MacBook Air models. Say Y here if you have a MacBook Air from mid
> +	 2013 or newer.
> +
> +	 To compile this driver as a module, choose M here: the module will
> +	 be called mba6x_bl.
> +
>  config INTEL_RST
>          tristate "Intel Rapid Start Technology Driver"
>  	depends on ACPI
> diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile
> index 1a2eafc..9a182fe 100644
> --- a/drivers/platform/x86/Makefile
> +++ b/drivers/platform/x86/Makefile
> @@ -56,3 +56,4 @@ obj-$(CONFIG_INTEL_SMARTCONNECT)	+= intel-smartconnect.o
>  
>  obj-$(CONFIG_PVPANIC)           += pvpanic.o
>  obj-$(CONFIG_ALIENWARE_WMI)	+= alienware-wmi.o
> +obj-$(CONFIG_MBA6X_BL)		+= mba6x_bl.o
> diff --git a/drivers/platform/x86/mba6x_bl.c b/drivers/platform/x86/mba6x_bl.c
> new file mode 100644
> index 0000000..c549667
> --- /dev/null
> +++ b/drivers/platform/x86/mba6x_bl.c
> @@ -0,0 +1,353 @@
> +/*
> + * MacBook Air 6,1 and 6,2 (mid 2013) backlight driver
> + *
> + * Copyright (C) 2014 Patrik Jakobsson (patrik.r.jakobsson@gmail.com)
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License version 2 as published by
> + * the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/init.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/backlight.h>
> +#include <linux/acpi.h>
> +#include <acpi/acpi.h>
> +#include <acpi/video.h>
> +
> +#define LP8550_SMBUS_ADDR	(0x58 >> 1)
> +#define LP8550_REG_BRIGHTNESS	0
> +#define LP8550_REG_DEV_CTL	1
> +#define LP8550_REG_FAULT	2
> +#define LP8550_REG_IDENT	3
> +#define LP8550_REG_DIRECT_CTL	4
> +#define LP8550_REG_TEMP_MSB	5 /* Must be read before TEMP_LSB */
> +#define LP8550_REG_TEMP_LSB	6
> +
> +#define INIT_BRIGHTNESS		150
> +
> +static struct {
> +	u8 brightness;	/* Brightness control */
> +	u8 dev_ctl;	/* Device control */
> +	u8 fault;	/* Fault indication */
> +	u8 ident;	/* Identification */
> +	u8 direct_ctl;	/* Direct control */
> +	u8 temp_msb;	/* Temperature MSB  */
> +	u8 temp_lsb;	/* Temperature LSB */
> +} lp8550_regs;
> +
> +static struct platform_device *platform_device;
> +static struct backlight_device *backlight_device;
> +
> +static int lp8550_reg_read(u8 reg, u8 *val)
> +{
> +	acpi_status status;
> +	acpi_handle handle;
> +	struct acpi_object_list arg_list;
> +	struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
> +	union acpi_object args[2];
> +	union acpi_object *result;
> +	int ret = 0;
> +
> +	status = acpi_get_handle(NULL, "\\_SB.PCI0.SBUS.SRDB", &handle);
> +	if (ACPI_FAILURE(status)) {
> +		pr_debug("mba6x_bl: Failed to get acpi handle\n");
> +		ret = -ENODEV;
> +		goto out;
> +	}
> +
> +	args[0].type = ACPI_TYPE_INTEGER;
> +	args[0].integer.value = (LP8550_SMBUS_ADDR << 1) | 1;
> +
> +	args[1].type = ACPI_TYPE_INTEGER;
> +	args[1].integer.value = reg;
> +
> +	arg_list.count = 2;
> +	arg_list.pointer = args;
> +
> +	status = acpi_evaluate_object(handle, NULL, &arg_list, &buffer);
> +	if (ACPI_FAILURE(status)) {
> +		pr_debug("mba6x_bl: Failed to read reg: 0x%x\n", reg);
> +		ret = -ENODEV;
> +		goto out;
> +	}
> +
> +	result = buffer.pointer;
> +
> +	if (result->type != ACPI_TYPE_INTEGER) {
> +		pr_debug("mba6x_bl: Invalid response in reg: 0x%x (len: %Ld)\n",
> +			 reg, buffer.length);
> +		ret = -EINVAL;
> +		goto out;
> +	}
> +
> +	*val = (u8)result->integer.value;
> +out:
> +	kfree(buffer.pointer);
> +	return ret;
> +}
> +
> +static int lp8550_reg_write(u8 reg, u8 val)
> +{
> +	acpi_status status;
> +	acpi_handle handle;
> +	struct acpi_object_list arg_list;
> +	struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
> +	union acpi_object args[3];
> +	union acpi_object *result;
> +	int ret = 0;
> +
> +	status = acpi_get_handle(NULL, "\\_SB.PCI0.SBUS.SWRB", &handle);
> +	if (ACPI_FAILURE(status)) {
> +		pr_debug("mba6x_bl: Failed to get acpi handle\n");
> +		ret = -ENODEV;
> +		goto out;
> +	}
> +
> +	args[0].type = ACPI_TYPE_INTEGER;
> +	args[0].integer.value = (LP8550_SMBUS_ADDR << 1) & ~1;
> +
> +	args[1].type = ACPI_TYPE_INTEGER;
> +	args[1].integer.value = reg;
> +
> +	args[2].type = ACPI_TYPE_INTEGER;
> +	args[2].integer.value = val;
> +
> +	arg_list.count = 3;
> +	arg_list.pointer = args;
> +
> +	status = acpi_evaluate_object(handle, NULL, &arg_list, &buffer);
> +	if (ACPI_FAILURE(status)) {
> +		pr_debug("mba6x_bl: Failed to write reg: 0x%x\n", reg);
> +		ret = -ENODEV;
> +		goto out;
> +	}
> +
> +	result = buffer.pointer;
> +
> +	if (result->type != ACPI_TYPE_INTEGER || result->integer.value != 1) {
> +		pr_debug("mba6x_bl: Invalid response at reg: 0x%x (len: %lld)\n",
> +			 reg, buffer.length);
> +		ret = -EINVAL;
> +		goto out;
> +	}
> +
> +out:
> +	kfree(buffer.pointer);
> +	return ret;
> +}
> +
> +/*
> + * Map the brightness value to an exponential curve. This makes the perceived
> + * brightness more linear and allows to make better use of the available
> + * brightness range.
> + */
> +static inline int map_brightness(int b)
> +{
> +	return ((b * b + 254) / 255);
> +}
> +
> +static int set_brightness(int brightness)
> +{
> +	int ret;
> +
> +	if (brightness < 0 || brightness > 255)
> +		return -EINVAL;
> +
> +	brightness = map_brightness(brightness);
> +	ret = lp8550_reg_write(LP8550_REG_BRIGHTNESS, (u8)brightness);
> +	if (ret)
> +		return ret;
> +
> +	ret = lp8550_reg_write(LP8550_REG_DEV_CTL, 0x05);
> +	return ret;
> +}
> +
> +static int get_brightness(struct backlight_device *bdev)
> +{
> +	return bdev->props.brightness;
> +}
> +
> +static int update_status(struct backlight_device *bdev)
> +{
> +	return set_brightness(bdev->props.brightness);
> +}
> +
> +static int lp8550_probe(void)
> +{
> +	u8 val;
> +	int ret;
> +
> +	ret = lp8550_reg_read(LP8550_REG_IDENT, &val);
> +	if (ret)
> +		return ret;
> +
> +	if (val != 0xfc)
> +		return -ENODEV;
> +
> +	pr_info("mba6x_bl: Found LP8550 backlight driver\n");
> +	return 0;
> +}
> +
> +static int lp8550_save(void)
> +{
> +	int ret;
> +
> +	ret = lp8550_reg_read(LP8550_REG_DEV_CTL, &lp8550_regs.dev_ctl);
> +	if (ret)
> +		return ret;
> +
> +	ret = lp8550_reg_read(LP8550_REG_BRIGHTNESS, &lp8550_regs.brightness);
> +	return ret;
> +}
> +
> +
> +static int lp8550_restore(void)
> +{
> +	int ret;
> +
> +	ret = lp8550_reg_write(LP8550_REG_BRIGHTNESS, lp8550_regs.brightness);
> +	if (ret)
> +		return ret;
> +
> +	ret = lp8550_reg_write(LP8550_REG_DEV_CTL, lp8550_regs.dev_ctl);
> +	return ret;
> +}
> +
> +static int lp8550_init(void)
> +{
> +	int ret, i;
> +
> +	for (i = 0; i < 10; i++) {
> +		ret = lp8550_reg_write(LP8550_REG_BRIGHTNESS, INIT_BRIGHTNESS);
> +		if (!ret)
> +			break;
> +	}
> +
> +	if (i > 0)
> +		pr_err("mba6x_bl: Init retries: %d\n", i);
> +
> +	if (ret)
> +		return ret;
> +
> +	ret = lp8550_reg_write(LP8550_REG_DEV_CTL, 0x05);
> +	return ret;
> +}
> +
> +static const struct backlight_ops backlight_ops = {
> +	.update_status = update_status,
> +	.get_brightness = get_brightness,
> +};
> +
> +static struct platform_driver drv;
> +
> +static int platform_probe(struct platform_device *dev)
> +{
> +	struct backlight_properties props;
> +	int ret;
> +
> +	ret = lp8550_probe();
> +	if (ret)
> +		return ret;
> +
> +	ret = lp8550_save();
> +	if (ret)
> +		return ret;
> +
> +	ret = lp8550_init();
> +	if (ret)
> +		return ret;
> +
> +	memset(&props, 0, sizeof(struct backlight_properties));
> +	props.max_brightness = 255;
> +	props.brightness = INIT_BRIGHTNESS;
> +	props.type = BACKLIGHT_FIRMWARE;
> +
> +	backlight_device = backlight_device_register("mba6x_backlight",
> +						     NULL, NULL,
> +						     &backlight_ops, &props);
> +	if (IS_ERR(backlight_device)) {
> +		pr_err("mba6x_bl: Failed to register backlight device\n");
> +		return PTR_ERR(backlight_device);
> +	}
> +
> +	acpi_video_dmi_promote_vendor();
> +	acpi_video_unregister();
> +
> +	backlight_update_status(backlight_device);
> +
> +	return 0;
> +}
> +
> +static int platform_remove(struct platform_device *dev)
> +{
> +	backlight_device_unregister(backlight_device);
> +	lp8550_restore();
> +	pr_info("mba6x_bl: Restored old configuration\n");
> +
> +	return 0;
> +}
> +
> +static int platform_resume(struct platform_device *dev)
> +{
> +	/*
> +	 * Firmware restores the LP8550 for us but we might need some tweaking
> +	 * in the future if firmware behaviour is changed.
> +	 */
> +	return 0;
> +}
> +
> +static void platform_shutdown(struct platform_device *dev)
> +{
> +	/* We must restore or screen might go black on reboot */
> +	lp8550_restore();
> +}
> +
> +static struct platform_driver drv = {
> +	.probe		= platform_probe,
> +	.remove		= platform_remove,
> +	.resume		= platform_resume,
> +	.shutdown	= platform_shutdown,
> +	.driver	= {
> +		.name = "mba6x_bl",
> +		.owner = THIS_MODULE,
> +	},
> +};
> +
> +static int __init mba6x_bl_init(void)
> +{
> +	int ret;
> +
> +	ret = platform_driver_register(&drv);
> +	if (ret) {
> +		pr_err("Failed to register platform driver\n");
> +		return ret;
> +	}
> +
> +	platform_device = platform_device_register_simple("mba6x_bl", -1, NULL,
> +							  0);
> +	return 0;
> +}
> +
> +static void __exit mba6x_bl_exit(void)
> +{
> +	platform_device_unregister(platform_device);
> +	platform_driver_unregister(&drv);
> +}
> +
> +module_init(mba6x_bl_init);
> +module_exit(mba6x_bl_exit);
> +
> +MODULE_AUTHOR("Patrik Jakobsson <patrik.r.jakobsson@gmail.com>");
> +MODULE_DESCRIPTION("MacBook Air 6,1 and 6,2 backlight driver");
> +MODULE_LICENSE("GPL");
> +
> +MODULE_ALIAS("dmi:*:pnMacBookAir6*");
> 

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH v2] mba6x_bl: Backlight driver for mid 2013 MacBook Air
  2014-04-29 14:21 [PATCH v2] mba6x_bl: Backlight driver for mid 2013 MacBook Air Patrik Jakobsson
  2014-04-30  8:19 ` Hans de Goede
@ 2014-05-05 14:49 ` Patrik Jakobsson
  2014-05-05 18:28   ` Matthew Garrett
  1 sibling, 1 reply; 5+ messages in thread
From: Patrik Jakobsson @ 2014-05-05 14:49 UTC (permalink / raw)
  To: matthew.garrett; +Cc: linux-kernel, Hans de Goede, platform-driver-x86

Hi Matthew,

This seems to be in good shape. Do you have anything to add?
If not, can you pick this patch up through platform-drivers-x86?

Thanks
Patrik

On Tue, Apr 29, 2014 at 4:21 PM, Patrik Jakobsson
<patrik.r.jakobsson@gmail.com> wrote:
> This driver takes control over the LP8550 backlight driver chip found
> in the mid 2013 and newer MacBook Air (6,1 and 6,2). The i915 GPU driver
> cannot properly restore the backlight after resume, but with this driver
> we can hijack the LP8550 and get fully functional backlight support.
>
> v2: - Dropped "if ACPI" in Kconfig since we already depend on it
>     - Added comment about brightness mapping
>     - Removed lp8550_init() from set_brightness()
>     - Always write to dev_ctl when setting brightness
>     - Change %Ld to standard C %lld
>     - Constify the backlight_ops struct
>
> Signed-off-by: Patrik Jakobsson <patrik.r.jakobsson@gmail.com>
> ---
>  MAINTAINERS                     |   6 +
>  drivers/platform/x86/Kconfig    |  13 ++
>  drivers/platform/x86/Makefile   |   1 +
>  drivers/platform/x86/mba6x_bl.c | 353 ++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 373 insertions(+)
>  create mode 100644 drivers/platform/x86/mba6x_bl.c
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index e67ea24..cad3e82 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -5576,6 +5576,12 @@ T:       git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git
>  S:     Maintained
>  F:     net/mac80211/rc80211_pid*
>
> +MACBOOK AIR 6,X BACKLIGHT DRIVER
> +M:     Patrik Jakobsson <patrik.r.jakobsson@gmail.com>
> +L:     platform-driver-x86@vger.kernel.org
> +S:     Maintained
> +F:     drivers/platform/x86/mba6x_bl.c
> +
>  MACVLAN DRIVER
>  M:     Patrick McHardy <kaber@trash.net>
>  L:     netdev@vger.kernel.org
> diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
> index 27df2c5..10ac918 100644
> --- a/drivers/platform/x86/Kconfig
> +++ b/drivers/platform/x86/Kconfig
> @@ -795,6 +795,19 @@ config APPLE_GMUX
>           graphics as well as the backlight. Currently only backlight
>           control is supported by the driver.
>
> +config MBA6X_BL
> +       tristate "MacBook Air 6,x backlight driver"
> +       depends on ACPI
> +       depends on BACKLIGHT_CLASS_DEVICE
> +       select ACPI_VIDEO
> +       help
> +        This driver takes control over the LP8550 backlight driver found in
> +        some MacBook Air models. Say Y here if you have a MacBook Air from mid
> +        2013 or newer.
> +
> +        To compile this driver as a module, choose M here: the module will
> +        be called mba6x_bl.
> +
>  config INTEL_RST
>          tristate "Intel Rapid Start Technology Driver"
>         depends on ACPI
> diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile
> index 1a2eafc..9a182fe 100644
> --- a/drivers/platform/x86/Makefile
> +++ b/drivers/platform/x86/Makefile
> @@ -56,3 +56,4 @@ obj-$(CONFIG_INTEL_SMARTCONNECT)      += intel-smartconnect.o
>
>  obj-$(CONFIG_PVPANIC)           += pvpanic.o
>  obj-$(CONFIG_ALIENWARE_WMI)    += alienware-wmi.o
> +obj-$(CONFIG_MBA6X_BL)         += mba6x_bl.o
> diff --git a/drivers/platform/x86/mba6x_bl.c b/drivers/platform/x86/mba6x_bl.c
> new file mode 100644
> index 0000000..c549667
> --- /dev/null
> +++ b/drivers/platform/x86/mba6x_bl.c
> @@ -0,0 +1,353 @@
> +/*
> + * MacBook Air 6,1 and 6,2 (mid 2013) backlight driver
> + *
> + * Copyright (C) 2014 Patrik Jakobsson (patrik.r.jakobsson@gmail.com)
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License version 2 as published by
> + * the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/init.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/backlight.h>
> +#include <linux/acpi.h>
> +#include <acpi/acpi.h>
> +#include <acpi/video.h>
> +
> +#define LP8550_SMBUS_ADDR      (0x58 >> 1)
> +#define LP8550_REG_BRIGHTNESS  0
> +#define LP8550_REG_DEV_CTL     1
> +#define LP8550_REG_FAULT       2
> +#define LP8550_REG_IDENT       3
> +#define LP8550_REG_DIRECT_CTL  4
> +#define LP8550_REG_TEMP_MSB    5 /* Must be read before TEMP_LSB */
> +#define LP8550_REG_TEMP_LSB    6
> +
> +#define INIT_BRIGHTNESS                150
> +
> +static struct {
> +       u8 brightness;  /* Brightness control */
> +       u8 dev_ctl;     /* Device control */
> +       u8 fault;       /* Fault indication */
> +       u8 ident;       /* Identification */
> +       u8 direct_ctl;  /* Direct control */
> +       u8 temp_msb;    /* Temperature MSB  */
> +       u8 temp_lsb;    /* Temperature LSB */
> +} lp8550_regs;
> +
> +static struct platform_device *platform_device;
> +static struct backlight_device *backlight_device;
> +
> +static int lp8550_reg_read(u8 reg, u8 *val)
> +{
> +       acpi_status status;
> +       acpi_handle handle;
> +       struct acpi_object_list arg_list;
> +       struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
> +       union acpi_object args[2];
> +       union acpi_object *result;
> +       int ret = 0;
> +
> +       status = acpi_get_handle(NULL, "\\_SB.PCI0.SBUS.SRDB", &handle);
> +       if (ACPI_FAILURE(status)) {
> +               pr_debug("mba6x_bl: Failed to get acpi handle\n");
> +               ret = -ENODEV;
> +               goto out;
> +       }
> +
> +       args[0].type = ACPI_TYPE_INTEGER;
> +       args[0].integer.value = (LP8550_SMBUS_ADDR << 1) | 1;
> +
> +       args[1].type = ACPI_TYPE_INTEGER;
> +       args[1].integer.value = reg;
> +
> +       arg_list.count = 2;
> +       arg_list.pointer = args;
> +
> +       status = acpi_evaluate_object(handle, NULL, &arg_list, &buffer);
> +       if (ACPI_FAILURE(status)) {
> +               pr_debug("mba6x_bl: Failed to read reg: 0x%x\n", reg);
> +               ret = -ENODEV;
> +               goto out;
> +       }
> +
> +       result = buffer.pointer;
> +
> +       if (result->type != ACPI_TYPE_INTEGER) {
> +               pr_debug("mba6x_bl: Invalid response in reg: 0x%x (len: %Ld)\n",
> +                        reg, buffer.length);
> +               ret = -EINVAL;
> +               goto out;
> +       }
> +
> +       *val = (u8)result->integer.value;
> +out:
> +       kfree(buffer.pointer);
> +       return ret;
> +}
> +
> +static int lp8550_reg_write(u8 reg, u8 val)
> +{
> +       acpi_status status;
> +       acpi_handle handle;
> +       struct acpi_object_list arg_list;
> +       struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
> +       union acpi_object args[3];
> +       union acpi_object *result;
> +       int ret = 0;
> +
> +       status = acpi_get_handle(NULL, "\\_SB.PCI0.SBUS.SWRB", &handle);
> +       if (ACPI_FAILURE(status)) {
> +               pr_debug("mba6x_bl: Failed to get acpi handle\n");
> +               ret = -ENODEV;
> +               goto out;
> +       }
> +
> +       args[0].type = ACPI_TYPE_INTEGER;
> +       args[0].integer.value = (LP8550_SMBUS_ADDR << 1) & ~1;
> +
> +       args[1].type = ACPI_TYPE_INTEGER;
> +       args[1].integer.value = reg;
> +
> +       args[2].type = ACPI_TYPE_INTEGER;
> +       args[2].integer.value = val;
> +
> +       arg_list.count = 3;
> +       arg_list.pointer = args;
> +
> +       status = acpi_evaluate_object(handle, NULL, &arg_list, &buffer);
> +       if (ACPI_FAILURE(status)) {
> +               pr_debug("mba6x_bl: Failed to write reg: 0x%x\n", reg);
> +               ret = -ENODEV;
> +               goto out;
> +       }
> +
> +       result = buffer.pointer;
> +
> +       if (result->type != ACPI_TYPE_INTEGER || result->integer.value != 1) {
> +               pr_debug("mba6x_bl: Invalid response at reg: 0x%x (len: %lld)\n",
> +                        reg, buffer.length);
> +               ret = -EINVAL;
> +               goto out;
> +       }
> +
> +out:
> +       kfree(buffer.pointer);
> +       return ret;
> +}
> +
> +/*
> + * Map the brightness value to an exponential curve. This makes the perceived
> + * brightness more linear and allows to make better use of the available
> + * brightness range.
> + */
> +static inline int map_brightness(int b)
> +{
> +       return ((b * b + 254) / 255);
> +}
> +
> +static int set_brightness(int brightness)
> +{
> +       int ret;
> +
> +       if (brightness < 0 || brightness > 255)
> +               return -EINVAL;
> +
> +       brightness = map_brightness(brightness);
> +       ret = lp8550_reg_write(LP8550_REG_BRIGHTNESS, (u8)brightness);
> +       if (ret)
> +               return ret;
> +
> +       ret = lp8550_reg_write(LP8550_REG_DEV_CTL, 0x05);
> +       return ret;
> +}
> +
> +static int get_brightness(struct backlight_device *bdev)
> +{
> +       return bdev->props.brightness;
> +}
> +
> +static int update_status(struct backlight_device *bdev)
> +{
> +       return set_brightness(bdev->props.brightness);
> +}
> +
> +static int lp8550_probe(void)
> +{
> +       u8 val;
> +       int ret;
> +
> +       ret = lp8550_reg_read(LP8550_REG_IDENT, &val);
> +       if (ret)
> +               return ret;
> +
> +       if (val != 0xfc)
> +               return -ENODEV;
> +
> +       pr_info("mba6x_bl: Found LP8550 backlight driver\n");
> +       return 0;
> +}
> +
> +static int lp8550_save(void)
> +{
> +       int ret;
> +
> +       ret = lp8550_reg_read(LP8550_REG_DEV_CTL, &lp8550_regs.dev_ctl);
> +       if (ret)
> +               return ret;
> +
> +       ret = lp8550_reg_read(LP8550_REG_BRIGHTNESS, &lp8550_regs.brightness);
> +       return ret;
> +}
> +
> +
> +static int lp8550_restore(void)
> +{
> +       int ret;
> +
> +       ret = lp8550_reg_write(LP8550_REG_BRIGHTNESS, lp8550_regs.brightness);
> +       if (ret)
> +               return ret;
> +
> +       ret = lp8550_reg_write(LP8550_REG_DEV_CTL, lp8550_regs.dev_ctl);
> +       return ret;
> +}
> +
> +static int lp8550_init(void)
> +{
> +       int ret, i;
> +
> +       for (i = 0; i < 10; i++) {
> +               ret = lp8550_reg_write(LP8550_REG_BRIGHTNESS, INIT_BRIGHTNESS);
> +               if (!ret)
> +                       break;
> +       }
> +
> +       if (i > 0)
> +               pr_err("mba6x_bl: Init retries: %d\n", i);
> +
> +       if (ret)
> +               return ret;
> +
> +       ret = lp8550_reg_write(LP8550_REG_DEV_CTL, 0x05);
> +       return ret;
> +}
> +
> +static const struct backlight_ops backlight_ops = {
> +       .update_status = update_status,
> +       .get_brightness = get_brightness,
> +};
> +
> +static struct platform_driver drv;
> +
> +static int platform_probe(struct platform_device *dev)
> +{
> +       struct backlight_properties props;
> +       int ret;
> +
> +       ret = lp8550_probe();
> +       if (ret)
> +               return ret;
> +
> +       ret = lp8550_save();
> +       if (ret)
> +               return ret;
> +
> +       ret = lp8550_init();
> +       if (ret)
> +               return ret;
> +
> +       memset(&props, 0, sizeof(struct backlight_properties));
> +       props.max_brightness = 255;
> +       props.brightness = INIT_BRIGHTNESS;
> +       props.type = BACKLIGHT_FIRMWARE;
> +
> +       backlight_device = backlight_device_register("mba6x_backlight",
> +                                                    NULL, NULL,
> +                                                    &backlight_ops, &props);
> +       if (IS_ERR(backlight_device)) {
> +               pr_err("mba6x_bl: Failed to register backlight device\n");
> +               return PTR_ERR(backlight_device);
> +       }
> +
> +       acpi_video_dmi_promote_vendor();
> +       acpi_video_unregister();
> +
> +       backlight_update_status(backlight_device);
> +
> +       return 0;
> +}
> +
> +static int platform_remove(struct platform_device *dev)
> +{
> +       backlight_device_unregister(backlight_device);
> +       lp8550_restore();
> +       pr_info("mba6x_bl: Restored old configuration\n");
> +
> +       return 0;
> +}
> +
> +static int platform_resume(struct platform_device *dev)
> +{
> +       /*
> +        * Firmware restores the LP8550 for us but we might need some tweaking
> +        * in the future if firmware behaviour is changed.
> +        */
> +       return 0;
> +}
> +
> +static void platform_shutdown(struct platform_device *dev)
> +{
> +       /* We must restore or screen might go black on reboot */
> +       lp8550_restore();
> +}
> +
> +static struct platform_driver drv = {
> +       .probe          = platform_probe,
> +       .remove         = platform_remove,
> +       .resume         = platform_resume,
> +       .shutdown       = platform_shutdown,
> +       .driver = {
> +               .name = "mba6x_bl",
> +               .owner = THIS_MODULE,
> +       },
> +};
> +
> +static int __init mba6x_bl_init(void)
> +{
> +       int ret;
> +
> +       ret = platform_driver_register(&drv);
> +       if (ret) {
> +               pr_err("Failed to register platform driver\n");
> +               return ret;
> +       }
> +
> +       platform_device = platform_device_register_simple("mba6x_bl", -1, NULL,
> +                                                         0);
> +       return 0;
> +}
> +
> +static void __exit mba6x_bl_exit(void)
> +{
> +       platform_device_unregister(platform_device);
> +       platform_driver_unregister(&drv);
> +}
> +
> +module_init(mba6x_bl_init);
> +module_exit(mba6x_bl_exit);
> +
> +MODULE_AUTHOR("Patrik Jakobsson <patrik.r.jakobsson@gmail.com>");
> +MODULE_DESCRIPTION("MacBook Air 6,1 and 6,2 backlight driver");
> +MODULE_LICENSE("GPL");
> +
> +MODULE_ALIAS("dmi:*:pnMacBookAir6*");
> --
> 1.9.1
>

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH v2] mba6x_bl: Backlight driver for mid 2013 MacBook Air
  2014-05-05 14:49 ` Patrik Jakobsson
@ 2014-05-05 18:28   ` Matthew Garrett
  2014-05-05 20:26     ` Patrik Jakobsson
  0 siblings, 1 reply; 5+ messages in thread
From: Matthew Garrett @ 2014-05-05 18:28 UTC (permalink / raw)
  To: patrik.r.jakobsson; +Cc: hdegoede, linux-kernel, platform-driver-x86

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="utf-8", Size: 561 bytes --]

On Mon, 2014-05-05 at 16:49 +0200, Patrik Jakobsson wrote:
> Hi Matthew,
> 
> This seems to be in good shape. Do you have anything to add?
> If not, can you pick this patch up through platform-drivers-x86?

I'm a bit reluctant. Do we have any evidence that this is the way OS X
behaves? What's the actual difference in state before and after suspend?

-- 
Matthew Garrett <matthew.garrett@nebula.com>
ÿôèº{.nÇ+‰·Ÿ®‰­†+%ŠËÿ±éݶ\x17¥Šwÿº{.nÇ+‰·¥Š{±þG«éÿŠ{ayº\x1dʇڙë,j\a­¢f£¢·hšïêÿ‘êçz_è®\x03(­éšŽŠÝ¢j"ú\x1a¶^[m§ÿÿ¾\a«þG«éÿ¢¸?™¨è­Ú&£ø§~á¶iO•æ¬z·švØ^\x14\x04\x1a¶^[m§ÿÿÃ\fÿ¶ìÿ¢¸?–I¥

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH v2] mba6x_bl: Backlight driver for mid 2013 MacBook Air
  2014-05-05 18:28   ` Matthew Garrett
@ 2014-05-05 20:26     ` Patrik Jakobsson
  0 siblings, 0 replies; 5+ messages in thread
From: Patrik Jakobsson @ 2014-05-05 20:26 UTC (permalink / raw)
  To: Matthew Garrett; +Cc: hdegoede, linux-kernel, platform-driver-x86

On Mon, May 5, 2014 at 8:28 PM, Matthew Garrett
<matthew.garrett@nebula.com> wrote:
> On Mon, 2014-05-05 at 16:49 +0200, Patrik Jakobsson wrote:
>> Hi Matthew,
>>
>> This seems to be in good shape. Do you have anything to add?
>> If not, can you pick this patch up through platform-drivers-x86?
>
> I'm a bit reluctant. Do we have any evidence that this is the way OS X
> behaves? What's the actual difference in state before and after suspend?

I cannot see any change in state on either the LP8550 or on the Intel GPU side.
Both me and Jani have twisted our heads around this but cannot see anything
wrong. The ACPI methods only trigger the opregion so that's a dead end as well.
My guess is that OSX is quirking this in the GPU driver which is something that
doesn't belong in i915.

So unfortunately, this is the best approach I can come up with without probing
the signal or reversing the OSX GPU driver.

Thanks
Patrik

> --
> Matthew Garrett <matthew.garrett@nebula.com>

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2014-05-05 20:26 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-04-29 14:21 [PATCH v2] mba6x_bl: Backlight driver for mid 2013 MacBook Air Patrik Jakobsson
2014-04-30  8:19 ` Hans de Goede
2014-05-05 14:49 ` Patrik Jakobsson
2014-05-05 18:28   ` Matthew Garrett
2014-05-05 20:26     ` Patrik Jakobsson

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).