[PATCH v2 2/4] iio: add LM3533 ambient light sensor driver

Jonathan Cameron jic23 at cam.ac.uk
Tue May 8 13:47:19 UTC 2012


On 5/3/2012 5:36 PM, Johan Hovold wrote:
> On Thu, May 03, 2012 at 12:40:10PM +0100, Jonathan Cameron wrote:
>> On 5/3/2012 11:26 AM, Johan Hovold wrote:
>>> Add sub-driver for the ambient light sensor interface on National
>>> Semiconductor / TI LM3533 lighting power chips.
>>>
>>> The sensor interface can be used to control the LEDs and backlights of
>>> the chip through defining five light zones and three sets of
>>> corresponding brightness target levels.
>>>
>>> The driver provides raw and mean adc readings along with the current
>>> light zone through sysfs. A threshold event can be generated on zone
>>> changes.
>> Code is fine.  Pretty much all my comments are to do with the interface.
> [...]
>
>>> diff --git a/drivers/staging/iio/Documentation/sysfs-bus-iio-light-lm3533-als b/drivers/staging/iio/Documentation/sysfs-bus-iio-light-lm3533-als
>>> new file mode 100644
>>> index 0000000..9849d14
>>> --- /dev/null
>>> +++ b/drivers/staging/iio/Documentation/sysfs-bus-iio-light-lm3533-als
>>> @@ -0,0 +1,62 @@
>>> +What:		/sys/bus/iio/devices/iio:deviceX/gain
>>> +Date:		April 2012
>>> +KernelVersion:	3.5
>>> +Contact:	Johan Hovold<jhovold at gmail.com>
>>> +Description:
>>> +		Set the ALS gain-resistor setting (0..127) for analog input
>>> +		mode, where
>>> +
>>> +		0000000 - ALS input is high impedance
>>> +		0000001 - 200kOhm (10uA at 2V full-scale)
>>> +		0000010 - 100kOhm (20uA at 2V full-scale)
>>> +		...
>>> +		1111110 - 1.587kOhm (1.26mA at 2V full-scale)
>>> +		1111111 - 1.575kOhm (1.27mA at 2V full-scale)
>>> +
>>> +		R_als = 2V / (10uA * gain)	(gain>   0)
>> Firstly, no magic numbers.  These are definitely magic.
> Not that magic as they're clearly documented (in code and public
> datasheets), right? What would you prefer instead?
The numbers on the right of the - look good to me though then this isn't
a gain.  (200kohm) and the infinite element is annoying.  Why not
compute the actual gains?
Gain = (Rals*10e-6)/2  and use those values?  Yes you will have to do
a bit of fixed point maths in the driver but the advantage is you'll
have real values that are standardizable across multiple devices
and hence allow your device to be operated by generic userspace
code.  Welcome to standardising interfaces - my favourite occupation ;)
>
>> Secondly see
>> in_illuminance0_scale for a suitable existing attribute.
> I didn't consider scale to be appropriate given the following
> documentation (e.g, for in_voltageY_scale):
sorry  I just did this to someone else in another review (so I'm 
consistently
wrong!)

in_voltageY_calibscale is what I should have said.  That one applies a 
scaling
before the raw reading is generated (so in hardware).
>
> "If known for a device, scale to be applied to<type>Y[_name]_raw post
> addition of<type>[Y][_name]_offset in order to obtain the measured
> value in<type>  units as specified in<type>[Y][_name]_raw
> documentation."
>
> That is, the gain setting has nothing to do with scaling the raw adc
> reading to SI-units or such, it's simply a setup dependent gain setting
> (which affects the raw readings as well). [And as such, should probably
> go into to the platform data eventually as well.]
>
>>> +
>>> +What:		/sys/bus/iio/devices/iio:deviceX/illuminance_zone
>>> +Date:		April 2012
>>> +KernelVersion:	3.5
>>> +Contact:	Johan Hovold<jhovold at gmail.com>
>>> +Description:
>>> +		Get the current light zone (0..4) as defined by the
>>> +		in_illuminance_thresh[n]_{falling,rising} thresholds.
>> Hmm.. definitely have an in prefix, beyond that I'm not sure what the
>> cleanest
> Thanks for catching this, it's a typo in the sysfs document -- the in_
> prefix is in the code.
>
>> interface will be for this.   Could extend the event codes to deal with the
>> zone index.  Slightly tricky as the channel could already be modified so
>> chan2 isn't necesarily available.
>>
>>> +
>>> +What:		/sys/.../events/in_illuminance_thresh_either_en
>>> +Date:		April 2012
>>> +KernelVersion:	3.5
>>> +Contact:	Johan Hovold<jhovold at gmail.com>
>>> +Description:
>>> +		Event generated when channel passes one of the four threshold
>>> +		in either direction (rising|falling) and a zone change occurs.
>>> +		The corresponding light zone can be read from
>>> +		illuminance_zone.
>>> +
>>> +What:		/sys/.../events/illuminance_thresh0_falling_value
>> hmm.. every time you think you are making progress a new and exciting
>> device comes
>> along requiring the abi to be extended.
> Exciting isn't it. :)
humph.
>
>> in_illuminanceX_threshY_rising_value
>> in_illuminanceX_threshY_falling_value
>> should do with appropriate description.
> Ok.
>
>>> +What:		/sys/.../events/illuminance_thresh0_raising_value
>>> +What:		/sys/.../events/illuminance_thresh1_falling_value
>>> +What:		/sys/.../events/illuminance_thresh1_raising_value
>>> +What:		/sys/.../events/illuminance_thresh2_falling_value
>>> +What:		/sys/.../events/illuminance_thresh2_raising_value
>>> +What:		/sys/.../events/illuminance_thresh3_falling_value
>>> +What:		/sys/.../events/illuminance_thresh3_raising_value
>>> +Date:		April 2012
>>> +KernelVersion:	3.5
>>> +Contact:	Johan Hovold<jhovold at gmail.com>
>>> +Description:
>>> +		Specifies the value of threshold that the device is comparing
>>> +		against for the events enabled by
>>> +		in_illuminance_thresh_either_en, and defines the
>>> +		the five light zones.
>>> +
>>> +		These thresholds correspond to the eight zone-boundary
>>> +		registers (boundary[n]_{low,high}).
>>> +
>> This interface is going to take some thought.  We have
>> in_illuminance0_target at the
>> moment, so I guess we can add a zoning concept to that...
> But target isn't really related, as far as I understand. That's another
> calibration setting right? While zone is derived from the average adc
> readings. (More below.)
True enough. I'd missunderstood this.
>
>>> +What:		/sys/bus/iio/devices/iio:deviceX/target[m]_[n]
>>> +Date:		April 2012
>>> +KernelVersion:	3.5
>>> +Contact:	Johan Hovold<jhovold at gmail.com>
>>> +Description:
>>> +		Set the target brightness for ALS-mapper m in light zone n
>>> +		(0..255), where m in 1..3 and n in 0..4.
>> Don't suppose you could do a quick summary of what these zones are and
>> why there
>> are 3 ALS-mappers?  I'm not getting terribly far on a quick look at the
>> datasheet!
> Of course. The average adc readings are mapped to five light zones using
> eight zone boundary registers (4 boundaries with hysteresis) and a set
> of rules.
This is going to be fun.  We'll need the boundaries and attached 
hysteresis attributes
to fully specify these (nothing would indicate that hysterisis is 
involved otherwise).
>
> To simplify somewhat (by ignoring some of the rules): If the average
> adc input drops below boundary0_low, the zone register reads 0; if it
> drops below boundary1_low, it reads 1, and so on. If the input it
> increases over boundary3_high, the zone register return 4; if it
> increases passed boundary2_high, it returns zone 3, etc.
>
> That is, roughly something like (we get 8-bits of input from the ADC):
>
> 	zone 0
>
> boundary0_low	51
> boundary0_high	53
>
> 	zone 1
>
> boundary1_low	102
> boundary1_high	106
>
> 	zone 2
>
> boundary2_low	153
> boundary2_high	161
>
> 	zone 3
>
> boundary3_low	204
> boundary3_high	220
>
> 	zone 4
>
> [ Figure 6 on page 20 in the datasheets should make it clear. ]
>
> The ALS interface and it's zone concept can then be used to control the
> LEDs and backlights of the chip, by determining the target brightness for
> each zone, e.g., set brightness to 52 when in zone 0.
>
> To complicate things further (and it is complicated), there are three
> such sets of target brightness values: ALSM1, ALSM2, ALSM3.
>
> So for each LED or backlight you can set ALS-input control mode, by
> saying that the device should get it's brightness levels from target set
> 1, 2, or 3.
>
> [ And it gets even more complicated, as ALSM1 can only control
>    backlight0, where as ALSM2 and ALSM3 can control any of the remaining
>    devices, but that's irrelevant here. ]
>
> Initially, I thought this interface to be too esoteric to be worth
> generalising, but it sort of fits with event thresholds so I gave it a
> try.
Glad you did and it pretty much fits, be it with a few extensions being 
necessary.
> The biggest conceptual problem, I think, is that the zone
> boundaries can be used to control the other devices, even when the event
> is not enabled (or even an irq line not configured). That is, I find it
> a bit awkward that the event thresholds also defines the zones (a sort of
> discrete scaling factor).
That is indeed awkward. I'm not sure how we handle this either.  If we 
need to control
these from the other devices (e.g. the back light driver) then we'll 
have to get them
into chan_spec and use the inkernel interfaces to do it.  Not infeasible but
I was hoping to avoid that until we have had a few months to see what 
similar
devices show up (on basis nothing in this world is a one off for long ;)
>
>
> Perhaps simply keeping the attributes outside of events (e.g. named
> boundary[n]_{low,high}) and having a custom event enabled (e.g.
> in_illuminance_zone_change_en) is the best solution?
Maybe, but it's ugly and as you have said, they do correspond pretty well to
thresholds so I'd rather you went with that.
The core stuff for registering events clearly needs a rethink.... For 
now doing
it as you describe above (with the addition fo hysteresis attributes) should
be fine.  Just document the 'quirks'.
>
> [...]
>
>>> diff --git a/drivers/staging/iio/light/lm3533-als.c b/drivers/staging/iio/light/lm3533-als.c
>>> new file mode 100644
>>> index 0000000..e2c9be6
>>> --- /dev/null
>>> +++ b/drivers/staging/iio/light/lm3533-als.c
>>> @@ -0,0 +1,617 @@
>>> +/*
>>> + * lm3533-als.c -- LM3533 Ambient Light Sensor driver
>>> + *
>>> + * Copyright (C) 2011-2012 Texas Instruments
>>> + *
>>> + * Author: Johan Hovold<jhovold at gmail.com>
>>> + *
>>> + * This program is free software; you can redistribute it and/or modify it
>>> + * under  the terms of the GNU General  Public License as published by the
>>> + * Free Software Foundation;  either version 2 of the License, or (at your
>>> + * option) any later version.
>>> + */
>>> +
>>> +#include<linux/atomic.h>
>>> +#include<linux/fs.h>
>>> +#include<linux/interrupt.h>
>>> +#include<linux/io.h>
>>> +#include<linux/module.h>
>>> +#include<linux/mfd/core.h>
>>> +#include<linux/platform_device.h>
>>> +#include<linux/slab.h>
>>> +#include<linux/uaccess.h>
>>> +
>>> +#include<linux/mfd/lm3533.h>
>>> +
>>> +#include "../events.h"
>>> +#include "../iio.h"
>> This will need to go through the staging-next tree.  In there these
>> headers have moved.
> I'm aware of the move. Should the different sub-drivers go in through
> each tree respectively? Right now the four patches are all against rc5.
They will probably have to.  Typically mfd bit goes in first, then the 
rest get added
in a random order after that.
>
> [...]
>
>>> +static const struct iio_chan_spec lm3533_als_channels[] = {
>>> +	{
>>> +		.type = IIO_LIGHT,
>>> +		.info_mask = IIO_CHAN_INFO_AVERAGE_RAW_SEPARATE_BIT,
>>> +		.channel = 0,
>> channel doesn't get used unless you also set indexed = 1.
> So, you mean I could drop channel as well? Or should I add indexed, as I
> use channel 0 when reporting the event?
Either option is valid.  I personally tend to set indexed = 1 but we 
decided that
it didn't matter either way.  Userspace code that uses the abi right 
should allow
for either.
>
> [...]
>
>>> +static int lm3533_als_set_int_mode(struct iio_dev *indio_dev, int enable)
>>> +{
>>> +	struct lm3533_als *als = iio_priv(indio_dev);
>>> +	u8 mask = LM3533_ALS_INT_ENABLE_MASK;
>>> +	u8 val;
>>> +	int ret;
>>> +
>>> +	if (enable)
>>> +		val = mask;
>>> +	else
>>> +		val = 0;
>>> +
>>> +	ret = lm3533_update(als->lm3533, LM3533_REG_ALS_ZONE_INFO, val, mask);
>>> +	if (ret) {
>>> +		dev_err(&indio_dev->dev, "failed to set int mode %d\n",
>>> +								enable);
>> extra brackets.
> I prefer the brackets for multi-line (single) statements even though
> they are not required. (Especially if the single statement spans
> several lines -- but I try to be consistent.) If you have a strong
> opinion about this, I'll drop them.
I don't care either way.
>
>>> +	}
>>> +
>>> +	return ret;
>>> +}
>>> +
> Thanks,
> Johan




More information about the devel mailing list