From dd180f650831f7702a27378d59c96d3bd5cb1e87 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 24 Apr 2019 16:14:59 -0600 Subject: [PATCH] Fix compilation of color keyboard file, add lpc command to enable camera toggle --- lpc.c | 62 +++++++++++++++++++++++++++++++++++++++++++++ system76-coreboot.c | 33 ++++++++++++++++-------- 2 files changed, 85 insertions(+), 10 deletions(-) create mode 100644 lpc.c diff --git a/lpc.c b/lpc.c new file mode 100644 index 0000000..2698b24 --- /dev/null +++ b/lpc.c @@ -0,0 +1,62 @@ +struct Lpc { + u16 data_port; + u16 cmd_port; +}; + +static struct Lpc lpc_new(void) { + struct Lpc lpc = { + .data_port = 0x62, + .cmd_port = 0x66, + }; + return lpc; +} + +static u8 lpc_sts(struct Lpc * lpc) { + return inb(lpc->cmd_port); +} + +static bool lpc_can_read(struct Lpc * lpc) { + return (lpc_sts(lpc) & 1) == 1; +} + +static int lpc_wait_read(struct Lpc * lpc, int timeout) { + while (! lpc_can_read(lpc) && timeout > 0) { + timeout -= 1; + } + return timeout; +} + +static bool lpc_can_write(struct Lpc * lpc) { + return (lpc_sts(lpc) & 2) == 0; +} + +static int lpc_wait_write(struct Lpc * lpc, int timeout) { + while (! lpc_can_write(lpc) && timeout > 0) { + timeout -= 1; + } + return timeout; +} + +static int lpc_cmd(struct Lpc * lpc, u8 data, int timeout) { + timeout = lpc_wait_write(lpc, timeout); + if (timeout > 0) { + outb(lpc->cmd_port, data); + } + return timeout; +} + +static int lpc_read(struct Lpc * lpc, u8 * data, int timeout) { + timeout = lpc_wait_read(lpc, timeout); + if (timeout > 0) { + *data = inb(lpc->data_port); + } + return timeout; +} + +static int lpc_write(struct Lpc * lpc, u8 data, int timeout) { + timeout = lpc_wait_write(lpc, timeout); + if (timeout > 0) { + outb(lpc->data_port, data); + } + return timeout; +} diff --git a/system76-coreboot.c b/system76-coreboot.c index df9f04e..b400746 100644 --- a/system76-coreboot.c +++ b/system76-coreboot.c @@ -16,6 +16,8 @@ #include #include +#include "lpc.c" + struct system76_data { struct acpi_device * acpi_dev; struct led_classdev ap_led; @@ -111,18 +113,18 @@ static void kb_led_set(struct led_classdev * led, enum led_brightness value) { system76_set(data, "SKBL", (int)data->kb_brightness); } -static ssize_t kb_led_color_show(struct device * dev, char *buf) { - struct led_clasdev * led = container_of(dev, struct led_classdev, dev); +static ssize_t kb_led_color_show(struct device * dev, struct device_attribute * dev_attr, char *buf) { + struct led_classdev * led = (struct led_classdev *)dev->driver_data; struct system76_data * data = container_of(led, struct system76_data, kb_led); return sprintf(buf, "%06X\n", data->kb_color); } -static ssize_t kb_led_color_store(struct device * dev, const char *buf, size_t size) { +static ssize_t kb_led_color_store(struct device * dev, struct device_attribute * dev_attr, const char *buf, size_t size) { unsigned int val; int ret; - struct led_clasdev * led = container_of(dev, struct led_classdev, dev); + struct led_classdev * led = (struct led_classdev *)dev->driver_data; struct system76_data * data = container_of(led, struct system76_data, kb_led); ret = kstrtouint(buf, 16, &val); @@ -130,7 +132,7 @@ static ssize_t kb_led_color_store(struct device * dev, const char *buf, size_t s return ret; } - if val > 0xFFFFFF { + if (val > 0xFFFFFF) { return -EINVAL; } @@ -140,7 +142,7 @@ static ssize_t kb_led_color_store(struct device * dev, const char *buf, size_t s return size; } -static const struct device_attribute kb_led_color_extra_dev_attr = { +static const struct device_attribute kb_led_color_dev_attr = { .attr = { .name = "color", .mode = 0644, @@ -256,9 +258,20 @@ static int system76_add(struct acpi_device *acpi_dev) { if (err) { return err; } - err = device_create_file(data->kb_led.dev, &kb_led_color_dev_attr); - if (err) { - return err; + if (data->kb_color >= 0) { + err = device_create_file(data->kb_led.dev, &kb_led_color_dev_attr); + if (err) { + return err; + } + } + + // Enable camera toggle + struct Lpc lpc = lpc_new(); + if (lpc_cmd(&lpc, 0xA8, 1000000)) { + u8 data = 0; + if (lpc_read(&lpc, &data, 1000000)) { + printk("system76 ec devices: 0x%x\n", data); + } } return 0; @@ -268,7 +281,7 @@ static int system76_remove(struct acpi_device *acpi_dev) { struct system76_data *data = acpi_driver_data(acpi_dev); if (data->kb_color >= 0) { - device_remove_file(kb_led.dev, &kb_led_color_dev_attr); + device_remove_file(data->kb_led.dev, &kb_led_color_dev_attr); } devm_led_classdev_unregister(&acpi_dev->dev, &data->ap_led);