Re: [PATCH] Dyna-Image AL3320A update, add AL3010 driver

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 03/06/16 09:35, Jonathan Cameron wrote:
> On 03/06/16 08:45, Daniel Baluta wrote:
>> Hi Rocky,
>>
>> Few bits inline, before I will take my time to do an in depth review.
>>
>> On Fri, Jun 3, 2016 at 7:02 AM, Rocky Hsiao <rocky.hsiao@xxxxxxxxxxxxxx> wrote:
>>> 1. Change al3320a.c to match light sensor test flow.
>>> 2. Add al3010.c to add new device AL3010.
>>>    original file copy from al3320a.c
>>
>> Please split this into several patches, each patch implementing one
>> single functionality.
>>
>> Can you add support for AL3010 inside al3320a.c. I don't know exactly
>> how different
>> this sensors are.
>>
>> Do you have a link to the datasheets?
>>
>>>
>>> Signed-off-by: Rocky Hsiao <rocky.hsiao@xxxxxxxxxxxxxx>
>>> ---
>>>  .../config/x86_64/chromiumos-x86_64.flavour.config |   2 +
>>
>> What tree are you using? Please use Jonathan's linux-iio git tree.
>>
>> https://git.kernel.org/cgit/linux/kernel/git/jic23/iio.git/?h=togreg
>>
>>>  drivers/iio/light/Kconfig                          |  10 +
>>>  drivers/iio/light/Makefile                         |   1 +
>>>  drivers/iio/light/al3010.c                         | 301 +++++++++++++++++++++
>>>  drivers/iio/light/al3320a.c                        |  73 ++++-
>>>  5 files changed, 378 insertions(+), 9 deletions(-)
>>>  create mode 100644 drivers/iio/light/al3010.c
>>>
>>> diff --git a/chromeos/config/x86_64/chromiumos-x86_64.flavour.config b/chromeos/config/x86_64/chromiumos-x86_64.flavour.config
>>> index 7d2bed4..7980a14 100644
>>> --- a/chromeos/config/x86_64/chromiumos-x86_64.flavour.config
>>> +++ b/chromeos/config/x86_64/chromiumos-x86_64.flavour.config
>>> @@ -2,6 +2,8 @@
>>>  # Config options generated by splitconfig
>>>  #
>>>  CONFIG_ACERHDF=m
>>> +CONFIG_AL3010=m
>>> +CONFIG_AL3320A=m
>>>  CONFIG_B43=m
>>>  CONFIG_B43_BCMA=y
>>>  CONFIG_B43_BCMA_PIO=y
>>
>> This is part of your distribution OS and it shouldn't be submitted here.
>>
>>> diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig
>>> index ca89b26..57a2a7e 100644
>>> --- a/drivers/iio/light/Kconfig
>>> +++ b/drivers/iio/light/Kconfig
>>> @@ -40,6 +40,16 @@ config AL3320A
>>>          To compile this driver as a module, choose M here: the
>>>          module will be called al3320a.
>>>
>>> +config AL3010
>>> +       tristate "AL3010 ambient light sensor"
>>> +       depends on I2C
>>> +       help
>>> +        Say Y here if you want to build a driver for the Dyna Image AL3010
>>> +        ambient light sensor.
>>> +
>>> +        To compile this driver as a module, choose M here: the
>>> +        module will be called al3010.
>>> +
>>>  config APDS9300
>>>         tristate "APDS9300 ambient light sensor"
>>>         depends on I2C
>>> diff --git a/drivers/iio/light/Makefile b/drivers/iio/light/Makefile
>>> index 5df1118..3f615d7 100644
>>> --- a/drivers/iio/light/Makefile
>>> +++ b/drivers/iio/light/Makefile
>>> @@ -5,6 +5,7 @@
>>>  # When adding new entries keep the list in alphabetical order
>>>  obj-$(CONFIG_ACPI_ALS)         += acpi-als.o
>>>  obj-$(CONFIG_ADJD_S311)                += adjd_s311.o
>>> +obj-$(CONFIG_AL3010)           += al3010.o
>>>  obj-$(CONFIG_AL3320A)          += al3320a.o
>>>  obj-$(CONFIG_APDS9300)         += apds9300.o
>>>  obj-$(CONFIG_APDS9960)         += apds9960.o
>>> diff --git a/drivers/iio/light/al3010.c b/drivers/iio/light/al3010.c
>>> new file mode 100644
>>> index 0000000..2df425b
>>> --- /dev/null
>>> +++ b/drivers/iio/light/al3010.c
>>> @@ -0,0 +1,301 @@
>>> +/*
>>> + * AL3010 - Dyna Image Ambient Light Sensor
>>> + *
>>> + * Copyright (C) 2016 Dyna-Image Corp.
>>> + *
>>> + * This software is licedsed under the terms of the GNU General Public
>>> + * License version 2, as published by the Free Software Foundation, and
>>> + * may be copied, distributed, and modified under those terms.
>>> + *
>>> + * Note about the original authors:
>>> + *
>>> + * This driver is based on the original driver for AL3320A that was distributed
>>> + * by Intel Corporation.
>>> + * The following is part of the header found in that file
>>> + *
>>> + * >> AL3320A - Dyna Image Ambient Light Sensor
>>> + *
>>> + * >> Copyright (c) 2014, Intel Corporation.
>>> + *
>>> + * >> This file is subject to the terms and conditions of version 2 of
>>> + * >> the GNU General Public License.  See the file COPYING in the main
>>> + * >> directory of this archive for more details.
>>> + *
>>> + * >> IIO driver for AL3010 (7-bit I2C slave address 0x1C).
>>> + *
>>> + * >> TODO: interrupt support, thresholds
>>> + *
>>> + * >> Author:Daniel Baluta <daniel.baluta@xxxxxxxxx>
>>> + *
>>> + * The kernel version is 4.4
>>
>> Again please rebase this on Jonathan latest sources as specified above.
> For a new driver it's almost always fine to base on the latest release
> mainline kernel if you would prefer.  Any tree wide reworks we can sort
> out when applying the patch.  Here, as you are modifying an existing
> driver you may want to check if there are any related series already
> under review or applied to my togreg branch at:
> https://git.kernel.org/cgit/linux/kernel/git/jic23/iio.git/log/?h=togreg
> 
> Rule of thumb for branches in that tree is that testing is the very
> latest stuff, but may well rebase so is not a good tree to use for
> new patches.  By the time it hits togreg it should be non rebasing and
> hence you should be safe that what you see there is what your patches
> will go on top of.
> 
> 
>>
>>> + */
>>> +
>>> +#include <linux/module.h>
>>> +#include <linux/init.h>
>>> +#include <linux/i2c.h>
>>> +
>>> +#include <linux/iio/iio.h>
>>> +#include <linux/iio/sysfs.h>
>>> +
>>> +#define AL3010_DRV_NAME "al3010"
>>> +
>>> +#define AL3010_REG_SYSTEM      0x00
>>> +#define        AL3010_REG_CONFIG       0x10
>>> +#define        AL3010_REG_DATA_LOW     0x0c
>>> +
>>> +#define        AL3010_GAIN_MASK        (BIT(6) | BIT(5) | BIT(4))
>>> +#define        AL3010_GAIN_SHIFT       4
>>> +
>>> +#define AL3010_CONFIG_DISABLE  0x00
>>> +#define AL3010_CONFIG_ENABLE   0x01
>>> +
>>> +#define AL3010_SCALE_AVAILABLE "1.1872 0.2968 0.0742 0.0186"
>>> +
>>> +enum al3010_range {
>>> +       AL3010_RANGE_1, /* 77806 lx */
>>> +       AL3010_RANGE_2, /* 19452 lx  */
>>> +       AL3010_RANGE_3, /* 4863  lx  */
>>> +       AL3010_RANGE_4  /* 1216  lx  */
>>> +};
>>> +
>>> +static const int al3010_scales[][2] = {
>>> +       {0, 1187200}, {0, 296800}, {0, 74200}, {0, 18600}
>>> +};
>>> +
>>> +struct al3010_data {
>>> +       struct i2c_client *client;
>>> +};
>>> +
>>> +static const struct iio_chan_spec al3010_channels[] = {
>>> +       {
>>> +               .type   = IIO_LIGHT,
>>> +               .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
>>> +                                     BIT(IIO_CHAN_INFO_SCALE),
>>> +       }
>>> +};
>>> +
>>> +static int al3010_set_gain(struct al3010_data *data, int gain)
>>> +{
>>> +       int ret;
>>> +
>>> +       ret = i2c_smbus_write_byte_data(data->client, AL3010_REG_CONFIG,
>>> +               (gain<<AL3010_GAIN_SHIFT)&AL3010_GAIN_MASK);
>>> +
>>> +       return ret;
>>> +}
>>> +
>>> +static int al3010_set_mode(struct al3010_data *data, int mode)
>>> +{
>>> +       int ret;
>>> +
>>> +       ret = i2c_smbus_write_byte_data(data->client, AL3010_REG_SYSTEM, mode);
>>> +
>>> +       return ret;
>>> +}
>>> +
>>> +static int al3010_get_mode(struct al3010_data *data)
>>> +{
>>> +       int ret;
>>> +
>>> +       ret = i2c_smbus_read_byte_data(data->client, AL3010_REG_SYSTEM);
>>> +
>>> +       return ret;
>>> +}
>>> +
>>> +static int al3010_get_adc_value(struct al3010_data *data)
>>> +{
>>> +       int ret;
>>> +
>>> +       ret = i2c_smbus_read_word_data(data->client, AL3010_REG_DATA_LOW);
>>> +
>>> +       return ret;
>>> +}
>>> +
>>> +static int al3010_get_lux(struct al3010_data *data)
>>> +{
>>> +       int ret;
>>> +       long int ret64;
>>> +
>>> +       ret = al3010_get_adc_value(data);
>>> +       ret64 = ret;
>>> +       ret64 = (ret64 * 74200) / 1000000;
>>> +       ret = ret64;
>>> +
>>> +       return ret;
>>> +}
>>> +
>>> +/* lux */
>>> +static ssize_t al3010_show_lux(struct device *dev,
>>> +                        struct device_attribute *attr, char *buf)
>>> +{
>>> +       struct al3010_data *data = iio_priv(dev_to_iio_dev(dev));
>>> +       int ret;
>>> +
>>> +       /* No LUX data if not operational */
>>> +       if (al3010_get_mode(data) != AL3010_CONFIG_ENABLE)
>>> +               return -EBUSY;
>>> +
>>> +       ret = al3010_get_lux(data);
>>> +
>>> +       return sprintf(buf, "%d\n", ret);
>>> +}
>>> +
>>> +static IIO_CONST_ATTR(in_illuminance_scale_available, AL3010_SCALE_AVAILABLE);
>>> +
>>> +static DEVICE_ATTR(illuminance0_input, S_IRUGO, al3010_show_lux, NULL);
>>> +
>>> +static struct attribute *al3010_attributes[] = {
>>> +       &dev_attr_illuminance0_input.attr,
>>> +       &iio_const_attr_in_illuminance_scale_available.dev_attr.attr,
>>> +       NULL,
>>> +};
>>> +
>>> +static const struct attribute_group al3010_attribute_group = {
>>> +       .attrs = al3010_attributes,
>>> +};
>>> +
>>> +static int al3010_init(struct al3010_data *data)
>>> +{
>>> +       int err = 0;
>>> +
>>> +       err = al3010_set_mode(data, AL3010_CONFIG_ENABLE);
>>> +       if (err) {
>>> +               dev_err(&data->client->dev,
>>> +                       "%s: al3010_set_mode returned error %d\n",
>>> +                       __func__, err);
>>> +               return err;
>>> +       }
>>> +
>>> +       /*
>>> +        * set sensor range to 4863 lux.
>>> +        * (If panel luminousness is 10% , the range of pad is 0 ~ 48630 lux.)
>>> +       */
>>> +       err = al3010_set_gain(data, AL3010_RANGE_3);
>>> +       if (err) {
>>> +               dev_err(&data->client->dev,
>>> +                       "%s: al3010_set_range returned error %d\n",
>>> +                       __func__, err);
>>> +               return err;
>>> +       }
>>> +
>>> +       return 0;
>>> +}
>>> +
>>> +static int al3010_read_raw(struct iio_dev *indio_dev,
>>> +               struct iio_chan_spec const *chan, int *val,
>>> +               int *val2, long mask)
>>> +{
>>> +       struct al3010_data *data = iio_priv(indio_dev);
>>> +       int ret;
>>> +
>>> +       switch (mask) {
>>> +       case IIO_CHAN_INFO_RAW:
>>> +               /*
>>> +                * ALS ADC value is stored in two adjacent registers:
>>> +                * - low byte of output is stored at AL3320A_REG_DATA_LOW
>>> +                * - high byte of output is stored at AL3320A_REG_DATA_LOW + 1
>>> +                */
>>> +               ret = i2c_smbus_read_word_data(data->client,
>>> +                               AL3010_REG_DATA_LOW);
>>> +               if (ret < 0)
>>> +                       return ret;
>>> +               *val = ret;
>>> +               return IIO_VAL_INT;
>>> +       case IIO_CHAN_INFO_SCALE:
>>> +               ret = i2c_smbus_read_byte_data(data->client,
>>> +                               AL3010_REG_CONFIG);
>>> +               if (ret < 0)
>>> +                       return ret;
>>> +
>>> +               ret = (ret & AL3010_GAIN_MASK) >> AL3010_GAIN_SHIFT;
>>> +               *val = al3010_scales[ret][0];
>>> +               *val2 = al3010_scales[ret][1];
>>> +
>>> +               return IIO_VAL_INT_PLUS_MICRO;
>>> +       }
>>> +       return -EINVAL;
>>> +}
>>> +
>>> +static int al3010_write_raw(struct iio_dev *indio_dev,
>>> +               struct iio_chan_spec const *chan, int val,
>>> +               int val2, long mask)
>>> +{
>>> +       struct al3010_data *data = iio_priv(indio_dev);
>>> +       int i;
>>> +
>>> +       switch (mask) {
>>> +       case IIO_CHAN_INFO_SCALE:
>>> +               for (i = 0; i < ARRAY_SIZE(al3010_scales); i++) {
>>> +                       if (val == al3010_scales[i][0] &&
>>> +                           val2 == al3010_scales[i][1])
>>> +                               return al3010_set_gain(data, i);
>>> +               }
>>> +               break;
>>> +       }
>>> +       return -EINVAL;
>>> +}
>>> +
>>> +static const struct iio_info al3010_info = {
>>> +       .driver_module  = THIS_MODULE,
>>> +       .read_raw       = al3010_read_raw,
>>> +       .write_raw      = al3010_write_raw,
>>> +       .attrs          = &al3010_attribute_group,
>>> +};
>>> +
>>> +static int al3010_probe(struct i2c_client *client,
>>> +                       const struct i2c_device_id *id)
>>> +{
>>> +       struct al3010_data *data;
>>> +       struct iio_dev *indio_dev;
>>> +       int ret;
>>> +
>>> +       indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
>>> +       if (!indio_dev)
>>> +               return -ENOMEM;
>>> +
>>> +       data = iio_priv(indio_dev);
>>> +       i2c_set_clientdata(client, indio_dev);
>>> +       data->client = client;
>>> +
>>> +       indio_dev->dev.parent = &client->dev;
>>> +       indio_dev->info = &al3010_info;
>>> +       indio_dev->name = AL3010_DRV_NAME;
>>> +       indio_dev->channels = al3010_channels;
>>> +       indio_dev->num_channels = ARRAY_SIZE(al3010_channels);
>>> +       indio_dev->modes = INDIO_DIRECT_MODE;
>>> +
>>> +       ret = al3010_init(data);
>>> +       if (ret < 0) {
>>> +               dev_err(&client->dev, "al3010 chip init failed\n");
>>> +               return ret;
>>> +       }
>>> +
>>> +       return devm_iio_device_register(&client->dev, indio_dev);
>>> +}
>>> +
>>> +static int al3010_remove(struct i2c_client *client)
>>> +{
>>> +       return i2c_smbus_write_byte_data(client, AL3010_REG_SYSTEM, 0x00);
>>> +}
>>> +
>>> +static const struct i2c_device_id al3010_id[] = {
>>> +       {"al3010", 0},
>>> +       {}
>>> +};
>>> +MODULE_DEVICE_TABLE(i2c, al3010_id);
>>> +
>>> +static struct i2c_driver al3010_driver = {
>>> +       .driver = {
>>> +               .name = AL3010_DRV_NAME,
>>> +       },
>>> +       .probe          = al3010_probe,
>>> +       .remove         = al3010_remove,
>>> +       .id_table       = al3010_id,
>>> +};
>>> +
>>> +module_i2c_driver(al3010_driver);
>>> +
>>> +MODULE_AUTHOR("Rocky Hsiao <rocky.hsiao@xxxxxxxxxxxxxx");
>>> +MODULE_DESCRIPTION("AL3010 Ambient Light Sensor driver");
>>> +MODULE_LICENSE("GPL v2");
>>
>> This looks pretty similar with al3320a. Can you try to implement the support for
>> al3010 inside al3320a.c file?
>>
>> Avoid duplicating code.
>>
>>> +
>>> diff --git a/drivers/iio/light/al3320a.c b/drivers/iio/light/al3320a.c
>>> index 6aac651..4212772 100644
>>> --- a/drivers/iio/light/al3320a.c
>>> +++ b/drivers/iio/light/al3320a.c
>>> @@ -1,16 +1,32 @@
>>>  /*
>>>   * AL3320A - Dyna Image Ambient Light Sensor
>>>   *
>>> - * Copyright (c) 2014, Intel Corporation.
>>> + * Copyright (C) 2016 Dyna Image Corp.
>>
>> Please don't remove the copyright from Intel. Just add your copyright notice.
>>
>>>   *
>>> - * This file is subject to the terms and conditions of version 2 of
>>> - * the GNU General Public License.  See the file COPYING in the main
>>> - * directory of this archive for more details.
>>> + * This software is licensed under the terms of the GNU General Public
>>> + * License version 2, as published by the Free Software Foundation, and
>>> + * may be copied, distributed, and modified under those terms.
>>>   *
>>> - * IIO driver for AL3320A (7-bit I2C slave address 0x1C).
>>> + * 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.
>>>   *
>>> - * TODO: interrupt support, thresholds
>>> + * Note about the original authors:
>>>   *
>>> + * >> Copyright (c) 2014, Intel Corporation.
>>> + *
>>> + * >> This file is subject to the terms and conditions of version 2 of
>>> + * >> the GNU General Public License.  See the file COPYING in the main
>>> + * >> directory of this archive for more details.
>>> + *
>>> + * >> IIO driver for AL3320A (7-bit I2C slave address 0x1C).
>>> + *
>>> + * >> TODO: interrupt support, thresholds
>>> + *
>>> + * >> Author:Daniel Baluta <daniel.baluta@xxxxxxxxx>
>>> + *
>>> + * The kernel version is 4.4
>>>   */
>>>
>>>  #include <linux/module.h>
>>> @@ -72,9 +88,47 @@ static const struct iio_chan_spec al3320a_channels[] = {
>>>         }
>>>  };
>>>
>>> +static int al3320a_get_adc_value(struct al3320a_data *data)
>>> +{
>>> +       int val;
>>> +
>>> +       val = i2c_smbus_read_word_data(data->client, AL3320A_REG_DATA_LOW);
>>> +
>>> +       return val;
>>> +}
>>> +
>>> +static int al3320a_get_lux(struct al3320a_data *data)
>>> +{
>>> +       int ret;
>>> +       long ret64;
>>> +
>>> +       ret = al3320a_get_adc_value(data);
>>> +       ret64 = ret;
>>> +       ret64 = (ret64 * 32000) / 1000000;
>>> +       ret = ret64;
>>> +
>>> +       return  ret;
>>> +}
>>> +
>>> +static ssize_t al3320a_lux_show(struct device *dev,
>>> +               struct device_attribute *attr,
>>> +               char *buf)
>>> +{
>>> +       struct al3320a_data *data = iio_priv(dev_to_iio_dev(dev));
>>> +       int val;
>>> +
>>> +       val = al3320a_get_lux(data);
>>> +
>>> +       return sprintf(buf, "%d\n", val);
>>> +}
>>> +
>>> +static IIO_DEVICE_ATTR(illuminance0_input, S_IRUGO,
>>> +               al3320a_lux_show, NULL, 0);
>>> +
>>>  static IIO_CONST_ATTR(in_illuminance_scale_available, AL3320A_SCALE_AVAILABLE);
>>>
>>>  static struct attribute *al3320a_attributes[] = {
>>> +       &iio_dev_attr_illuminance0_input.dev_attr.attr,
>>>         &iio_const_attr_in_illuminance_scale_available.dev_attr.attr,
>>>         NULL,
>>>  };
>>> @@ -125,8 +179,8 @@ static int al3320a_read_raw(struct iio_dev *indio_dev,
>>>                  * - low byte of output is stored at AL3320A_REG_DATA_LOW
>>>                  * - high byte of output is stored at AL3320A_REG_DATA_LOW + 1
>>>                  */
>>> -               ret = i2c_smbus_read_word_data(data->client,
>>> -                                              AL3320A_REG_DATA_LOW);
>>> +               ret = al3320a_get_adc_value(data);
>>> +
>>>                 if (ret < 0)
>>>                         return ret;
>>>                 *val = ret;
>>> @@ -201,6 +255,7 @@ static int al3320a_probe(struct i2c_client *client,
>>>                 dev_err(&client->dev, "al3320a chip init failed\n");
>>>                 return ret;
>>>         }!
>>> +
>>>         return devm_iio_device_register(&client->dev, indio_dev);
>>>  }
>>>
>>> @@ -227,6 +282,6 @@ static struct i2c_driver al3320a_driver = {
>>>
>>>  module_i2c_driver(al3320a_driver);
>>>
>>> -MODULE_AUTHOR("Daniel Baluta <daniel.baluta@xxxxxxxxx>");
>>> +MODULE_AUTHOR("Rocky Hsiao <rocky.hsiao@xxxxxxxxxxxxxx>");
>>
>> Again, mark your contribution here. Do not remove initial author :).
>>
>>>  MODULE_DESCRIPTION("AL3320A Ambient Light Sensor driver");
>>>  MODULE_LICENSE("GPL v2");
>>
>> I am happy to see Dyna Image starting to do upstream work on their sensors :).
> Seconded!  Always good to have direct support from the manufacturer where
> possible as normally you have better access to information :)
> 
> So welcome to IIO Rocky,
Just been browsing the Dyna Image website.  You guys have some very cool sensors.
*cross fingers that this is the start of mainline support for more devices*.

Not many datasheets though that I can immediately locate. 
Is dyna-image likely to be willing to release them to reviewers (more generally is
of course even better).  Makes review much easier / more thorough.  Note there
are structures set up to do NDAs etc if needed (though I'm sure we all prefer not!).

Jonathan
> 
> Thanks
> Jonathan
>>
>> thanks,
>> Daniel.
>>
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-iio" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

--
To unsubscribe from this list: send the line "unsubscribe linux-iio" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Input]     [Linux Kernel]     [Linux SCSI]     [X.org]

  Powered by Linux