On Thu, Mar 24, 2011 at 11:02 PM, Andy Ross <andy.ross@xxxxxxxxxxxxx> wrote: > Ambient light sensor for Pegatron Lucid. ÂSupports pre-existing > ls_switch sysfs interface to en/disable automatic control, and exports > the brightness from the device as "ls_value". > > Signed-off-by: Andy Ross <andy.ross@xxxxxxxxxxxxx> > --- > Âdrivers/platform/x86/asus-laptop.c | Â 70 +++++++++++++++++++++++++++++++++--- > Â1 files changed, 65 insertions(+), 5 deletions(-) > > diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c > index ec46d71..6651d8c 100644 > --- a/drivers/platform/x86/asus-laptop.c > +++ b/drivers/platform/x86/asus-laptop.c > @@ -214,9 +214,15 @@ static char *display_get_paths[] = { > > Â/* For Pegatron Lucid tablet */ > Â#define DEVICE_NAME_PEGA Â Â Â "Lucid" > + > Â#define METHOD_PEGA_ENABLE Â Â "ENPR" > Â#define METHOD_PEGA_DISABLE Â Â"DAPR" > +#define PEGA_ALS Â Â Â 0x04 > +#define PEGA_ALS_POWER 0x05 > + > Â#define METHOD_PEGA_READ Â Â Â "RDLN" > +#define PEGA_READ_ALS_H Â Â Â Â0x02 > +#define PEGA_READ_ALS_L Â Â Â Â0x03 > > Â/* > Â* Define a specific led structure to keep the main structure clean > @@ -378,6 +384,12 @@ static bool asus_check_pega_lucid(struct asus_laptop *asus) > Â Â Â Â Â !acpi_check_handle(asus->handle, METHOD_PEGA_READ, NULL); > Â} > > +static int asus_pega_lucid_set(struct asus_laptop *asus, int unit, bool enable) > +{ > + Â Â Â char *method = enable ? METHOD_PEGA_ENABLE : METHOD_PEGA_DISABLE; > + Â Â Â return write_acpi_int(asus->handle, method, unit); > +} > + > Â/* Generic LED function */ > Âstatic int asus_led_set(struct asus_laptop *asus, const char *method, > Â Â Â Â Â Â Â Â Â Â Â Â int value) > @@ -1046,7 +1058,15 @@ static ssize_t store_disp(struct device *dev, struct device_attribute *attr, > Â*/ > Âstatic void asus_als_switch(struct asus_laptop *asus, int value) > Â{ > - Â Â Â if (write_acpi_int(asus->handle, METHOD_ALS_CONTROL, value)) > + Â Â Â int ret; > + Â Â Â if (asus->have_pega_lucid) { > + Â Â Â Â Â Â Â ret = asus_pega_lucid_set(asus, PEGA_ALS, value); > + Â Â Â Â Â Â Â if (!ret) > + Â Â Â Â Â Â Â Â Â Â Â ret = asus_pega_lucid_set(asus, PEGA_ALS_POWER, value); > + Â Â Â } else { > + Â Â Â Â Â Â Â ret = write_acpi_int(asus->handle, METHOD_ALS_CONTROL, value); > + Â Â Â } > + Â Â Â if (ret) > Â Â Â Â Â Â Â Âpr_warning("Error setting light sensor switch\n"); > Â Â Â Âasus->light_switch = value; > Â} > @@ -1103,6 +1123,35 @@ static ssize_t store_lslvl(struct device *dev, struct device_attribute *attr, > Â Â Â Âreturn rv; > Â} > > +static int pega_int_read(struct asus_laptop *asus, int arg, int *result) > +{ > + Â Â Â struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; > + Â Â Â int err = write_acpi_int_ret(asus->handle, METHOD_PEGA_READ, arg, > + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â&buffer); > + Â Â Â if (!err) { > + Â Â Â Â Â Â Â union acpi_object *obj = buffer.pointer; I think a kfree(buffer.pointer); is missing here. > + Â Â Â Â Â Â Â if (obj && obj->type == ACPI_TYPE_INTEGER) > + Â Â Â Â Â Â Â Â Â Â Â *result = obj->integer.value; > + Â Â Â Â Â Â Â else > + Â Â Â Â Â Â Â Â Â Â Â err = -EIO; > + Â Â Â } > + Â Â Â return err; > +} > + > +static ssize_t show_lsvalue(struct device *dev, > + Â Â Â Â Â Â Â Â Â Â Â Â Â struct device_attribute *attr, char *buf) > +{ > + Â Â Â struct asus_laptop *asus = dev_get_drvdata(dev); > + Â Â Â int err, hi, lo; > + > + Â Â Â err = pega_int_read(asus, PEGA_READ_ALS_H, &hi); > + Â Â Â if (!err) > + Â Â Â Â Â Â Â err = pega_int_read(asus, PEGA_READ_ALS_L, &lo); > + Â Â Â if (!err) > + Â Â Â Â Â Â Â return sprintf(buf, "%d\n", 10 * hi + lo); > + Â Â Â return err; > +} > + > Â/* > Â* GPS > Â*/ > @@ -1300,6 +1349,7 @@ static DEVICE_ATTR(wimax, S_IRUGO | S_IWUSR, show_wimax, store_wimax); > Âstatic DEVICE_ATTR(wwan, S_IRUGO | S_IWUSR, show_wwan, store_wwan); > Âstatic DEVICE_ATTR(display, S_IRUGO | S_IWUSR, show_disp, store_disp); > Âstatic DEVICE_ATTR(ledd, S_IRUGO | S_IWUSR, show_ledd, store_ledd); > +static DEVICE_ATTR(ls_value, S_IRUGO, show_lsvalue, NULL); Could you document that new file in Documentation/ABI/testing/sysfs-platform-asus-laptop ? > Âstatic DEVICE_ATTR(ls_level, S_IRUGO | S_IWUSR, show_lslvl, store_lslvl); > Âstatic DEVICE_ATTR(ls_switch, S_IRUGO | S_IWUSR, show_lssw, store_lssw); > Âstatic DEVICE_ATTR(gps, S_IRUGO | S_IWUSR, show_gps, store_gps); > @@ -1312,6 +1362,7 @@ static struct attribute *asus_attributes[] = { > Â Â Â Â&dev_attr_wwan.attr, > Â Â Â Â&dev_attr_display.attr, > Â Â Â Â&dev_attr_ledd.attr, > + Â Â Â &dev_attr_ls_value.attr, > Â Â Â Â&dev_attr_ls_level.attr, > Â Â Â Â&dev_attr_ls_switch.attr, > Â Â Â Â&dev_attr_gps.attr, > @@ -1349,8 +1400,15 @@ static mode_t asus_sysfs_is_visible(struct kobject *kobj, > > Â Â Â Â} else if (attr == &dev_attr_ls_switch.attr || > Â Â Â Â Â Â Â Â Â attr == &dev_attr_ls_level.attr) { > - Â Â Â Â Â Â Â supported = !acpi_check_handle(handle, METHOD_ALS_CONTROL, NULL) && > - Â Â Â Â Â Â Â Â Â Â Â Â Â !acpi_check_handle(handle, METHOD_ALS_LEVEL, NULL); > + Â Â Â Â Â Â Â if (asus->have_pega_lucid) { > + Â Â Â Â Â Â Â Â Â Â Â /* no ls_level interface on the Lucid */ > + Â Â Â Â Â Â Â Â Â Â Â supported = attr == &dev_attr_ls_switch.attr; > + Â Â Â Â Â Â Â } else { > + Â Â Â Â Â Â Â Â Â Â Â supported = !acpi_check_handle(handle, METHOD_ALS_CONTROL, NULL) && > + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â !acpi_check_handle(handle, METHOD_ALS_LEVEL, NULL); > + Â Â Â Â Â Â Â } > + Â Â Â } else if (attr == &dev_attr_ls_value.attr) { > + Â Â Â Â Â Â Â supported = asus->have_pega_lucid; > Â Â Â Â} else if (attr == &dev_attr_gps.attr) { > Â Â Â Â Â Â Â Âsupported = !acpi_check_handle(handle, METHOD_GPS_ON, NULL) && > Â Â Â Â Â Â Â Â Â Â Â Â Â Â!acpi_check_handle(handle, METHOD_GPS_OFF, NULL) && > @@ -1562,8 +1620,10 @@ static int __devinit asus_acpi_init(struct asus_laptop *asus) > Â Â Â Âasus->light_switch = 0; /* Default to light sensor disabled */ > Â Â Â Âasus->light_level = 5; Â/* level 5 for sensor sensitivity */ > > - Â Â Â if (!acpi_check_handle(asus->handle, METHOD_ALS_CONTROL, NULL) && > - Â Â Â Â Â !acpi_check_handle(asus->handle, METHOD_ALS_LEVEL, NULL)) { > + Â Â Â if (asus->have_pega_lucid) { > + Â Â Â Â Â Â Â asus_als_switch(asus, asus->light_switch); > + Â Â Â } else if (!acpi_check_handle(asus->handle, METHOD_ALS_CONTROL, NULL) && > + Â Â Â Â Â Â Â Â Â!acpi_check_handle(asus->handle, METHOD_ALS_LEVEL, NULL)) { > Â Â Â Â Â Â Â Âasus_als_switch(asus, asus->light_switch); > Â Â Â Â Â Â Â Âasus_als_level(asus, asus->light_level); > Â Â Â Â} > -- > 1.7.1 > > -- Corentin Chary http://xf.iksaif.net -- To unsubscribe from this list: send the line "unsubscribe platform-driver-x86" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html