Re: [PATCH 2/2] media: video-i2c: add Melexis MLX90640 thermal camera support

2018-11-20 Thread Hans Verkuil
On 11/19/2018 09:54 PM, Matt Ranostay wrote:
> On Mon, Nov 19, 2018 at 6:26 AM Hans Verkuil  wrote:
>>
>> On 11/01/2018 05:15 AM, Matt Ranostay wrote:
>>> Add initial support for MLX90640 thermal cameras which output an 32x24
>>> greyscale pixel image along with 2 rows of coefficent data.
>>>
>>> Because of this the data outputed is really 32x26 and needs the two rows
>>> removed after using the coefficent information to generate processed
>>> images in userspace.
>>>
>>> Signed-off-by: Matt Ranostay 
>>> ---
>>>  drivers/media/i2c/Kconfig |   1 +
>>>  drivers/media/i2c/video-i2c.c | 110 +-
>>>  2 files changed, 110 insertions(+), 1 deletion(-)
>>
>>
>>
>>>
>>> diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
>>> index 704af210e270..4bfb2c66d192 100644
>>> --- a/drivers/media/i2c/Kconfig
>>> +++ b/drivers/media/i2c/Kconfig
>>> @@ -1085,6 +1085,7 @@ config VIDEO_I2C
>>> Enable the I2C transport video support which supports the
>>> following:
>>>  * Panasonic AMG88xx Grid-Eye Sensors
>>> +* Melexis MLX90640 Thermal Cameras
>>>
>>> To compile this driver as a module, choose M here: the
>>> module will be called video-i2c
>>> diff --git a/drivers/media/i2c/video-i2c.c b/drivers/media/i2c/video-i2c.c
>>> index 6d3b6df0b634..38ade8cb7656 100644
>>> --- a/drivers/media/i2c/video-i2c.c
>>> +++ b/drivers/media/i2c/video-i2c.c
>>> @@ -6,6 +6,7 @@
>>>   *
>>>   * Supported:
>>>   * - Panasonic AMG88xx Grid-Eye Sensors
>>> + * - Melexis MLX90640 Thermal Cameras
>>>   */
>>>
>>>  #include 
>>> @@ -18,6 +19,7 @@
>>>  #include 
>>>  #include 
>>>  #include 
>>> +#include 
>>>  #include 
>>>  #include 
>>>  #include 
>>> @@ -66,12 +68,26 @@ static const struct v4l2_frmsize_discrete amg88xx_size 
>>> = {
>>>   .height = 8,
>>>  };
>>>
>>> +static const struct v4l2_fmtdesc mlx90640_format = {
>>> + .pixelformat = V4L2_PIX_FMT_Y16_BE,
>>> +};
>>> +
>>> +static const struct v4l2_frmsize_discrete mlx90640_size = {
>>> + .width = 32,
>>> + .height = 26, /* 24 lines of pixel data + 2 lines of processing data 
>>> */
>>> +};
>>> +
>>>  static const struct regmap_config amg88xx_regmap_config = {
>>>   .reg_bits = 8,
>>>   .val_bits = 8,
>>>   .max_register = 0xff
>>>  };
>>>
>>> +static const struct regmap_config mlx90640_regmap_config = {
>>> + .reg_bits = 16,
>>> + .val_bits = 16,
>>> +};
>>> +
>>>  struct video_i2c_chip {
>>>   /* video dimensions */
>>>   const struct v4l2_fmtdesc *format;
>>> @@ -88,6 +104,7 @@ struct video_i2c_chip {
>>>   unsigned int bpp;
>>>
>>>   const struct regmap_config *regmap_config;
>>> + struct nvmem_config *nvmem_config;
>>>
>>>   /* setup function */
>>>   int (*setup)(struct video_i2c_data *data);
>>> @@ -102,6 +119,22 @@ struct video_i2c_chip {
>>>   int (*hwmon_init)(struct video_i2c_data *data);
>>>  };
>>>
>>> +static int mlx90640_nvram_read(void *priv, unsigned int offset, void *val,
>>> +  size_t bytes)
>>> +{
>>> + struct video_i2c_data *data = priv;
>>> +
>>> + return regmap_bulk_read(data->regmap, 0x2400 + offset, val, bytes);
>>> +}
>>> +
>>> +static struct nvmem_config mlx90640_nvram_config = {
>>> + .name = "mlx90640_nvram",
>>> + .word_size = 2,
>>> + .stride = 1,
>>> + .size = 1664,
>>> + .reg_read = mlx90640_nvram_read,
>>> +};
>>> +
>>>  /* Power control register */
>>>  #define AMG88XX_REG_PCTL 0x00
>>>  #define AMG88XX_PCTL_NORMAL  0x00
>>> @@ -122,12 +155,23 @@ struct video_i2c_chip {
>>>  /* Temperature register */
>>>  #define AMG88XX_REG_T01L 0x80
>>>
>>> +/* Control register */
>>> +#define MLX90640_REG_CTL10x800d
>>> +#define MLX90640_REG_CTL1_MASK   0x0380
>>> +#define MLX90640_REG_CTL1_MASK_SHIFT 7
>>> +
>>>  static int amg88xx_xfer(struct video_i2c_data *data, char *buf)
>>>  {
>>>   return regmap_bulk_read(data->regmap, AMG88XX_REG_T01L, buf,
>>>   data->chip->buffer_size);
>>>  }
>>>
>>> +static int mlx90640_xfer(struct video_i2c_data *data, char *buf)
>>> +{
>>> + return regmap_bulk_read(data->regmap, 0x400, buf,
>>> + data->chip->buffer_size);
>>> +}
>>> +
>>>  static int amg88xx_setup(struct video_i2c_data *data)
>>>  {
>>>   unsigned int mask = AMG88XX_FPSC_1FPS;
>>> @@ -141,6 +185,27 @@ static int amg88xx_setup(struct video_i2c_data *data)
>>>   return regmap_update_bits(data->regmap, AMG88XX_REG_FPSC, mask, val);
>>>  }
>>>
>>> +static int mlx90640_setup(struct video_i2c_data *data)
>>> +{
>>> + unsigned int n, idx;
>>> +
>>> + for (n = 0; n < data->chip->num_frame_intervals - 1; n++) {
>>> + if (data->frame_interval.numerator
>>> + != data->chip->frame_intervals[n].numerator)
>>> + continue;
>>> +
>>> + if (data->frame_interval.denominator
>>> +

Re: [PATCH 2/2] media: video-i2c: add Melexis MLX90640 thermal camera support

2018-11-19 Thread Matt Ranostay
On Mon, Nov 19, 2018 at 6:26 AM Hans Verkuil  wrote:
>
> On 11/01/2018 05:15 AM, Matt Ranostay wrote:
> > Add initial support for MLX90640 thermal cameras which output an 32x24
> > greyscale pixel image along with 2 rows of coefficent data.
> >
> > Because of this the data outputed is really 32x26 and needs the two rows
> > removed after using the coefficent information to generate processed
> > images in userspace.
> >
> > Signed-off-by: Matt Ranostay 
> > ---
> >  drivers/media/i2c/Kconfig |   1 +
> >  drivers/media/i2c/video-i2c.c | 110 +-
> >  2 files changed, 110 insertions(+), 1 deletion(-)
>
>
>
> >
> > diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
> > index 704af210e270..4bfb2c66d192 100644
> > --- a/drivers/media/i2c/Kconfig
> > +++ b/drivers/media/i2c/Kconfig
> > @@ -1085,6 +1085,7 @@ config VIDEO_I2C
> > Enable the I2C transport video support which supports the
> > following:
> >  * Panasonic AMG88xx Grid-Eye Sensors
> > +* Melexis MLX90640 Thermal Cameras
> >
> > To compile this driver as a module, choose M here: the
> > module will be called video-i2c
> > diff --git a/drivers/media/i2c/video-i2c.c b/drivers/media/i2c/video-i2c.c
> > index 6d3b6df0b634..38ade8cb7656 100644
> > --- a/drivers/media/i2c/video-i2c.c
> > +++ b/drivers/media/i2c/video-i2c.c
> > @@ -6,6 +6,7 @@
> >   *
> >   * Supported:
> >   * - Panasonic AMG88xx Grid-Eye Sensors
> > + * - Melexis MLX90640 Thermal Cameras
> >   */
> >
> >  #include 
> > @@ -18,6 +19,7 @@
> >  #include 
> >  #include 
> >  #include 
> > +#include 
> >  #include 
> >  #include 
> >  #include 
> > @@ -66,12 +68,26 @@ static const struct v4l2_frmsize_discrete amg88xx_size 
> > = {
> >   .height = 8,
> >  };
> >
> > +static const struct v4l2_fmtdesc mlx90640_format = {
> > + .pixelformat = V4L2_PIX_FMT_Y16_BE,
> > +};
> > +
> > +static const struct v4l2_frmsize_discrete mlx90640_size = {
> > + .width = 32,
> > + .height = 26, /* 24 lines of pixel data + 2 lines of processing data 
> > */
> > +};
> > +
> >  static const struct regmap_config amg88xx_regmap_config = {
> >   .reg_bits = 8,
> >   .val_bits = 8,
> >   .max_register = 0xff
> >  };
> >
> > +static const struct regmap_config mlx90640_regmap_config = {
> > + .reg_bits = 16,
> > + .val_bits = 16,
> > +};
> > +
> >  struct video_i2c_chip {
> >   /* video dimensions */
> >   const struct v4l2_fmtdesc *format;
> > @@ -88,6 +104,7 @@ struct video_i2c_chip {
> >   unsigned int bpp;
> >
> >   const struct regmap_config *regmap_config;
> > + struct nvmem_config *nvmem_config;
> >
> >   /* setup function */
> >   int (*setup)(struct video_i2c_data *data);
> > @@ -102,6 +119,22 @@ struct video_i2c_chip {
> >   int (*hwmon_init)(struct video_i2c_data *data);
> >  };
> >
> > +static int mlx90640_nvram_read(void *priv, unsigned int offset, void *val,
> > +  size_t bytes)
> > +{
> > + struct video_i2c_data *data = priv;
> > +
> > + return regmap_bulk_read(data->regmap, 0x2400 + offset, val, bytes);
> > +}
> > +
> > +static struct nvmem_config mlx90640_nvram_config = {
> > + .name = "mlx90640_nvram",
> > + .word_size = 2,
> > + .stride = 1,
> > + .size = 1664,
> > + .reg_read = mlx90640_nvram_read,
> > +};
> > +
> >  /* Power control register */
> >  #define AMG88XX_REG_PCTL 0x00
> >  #define AMG88XX_PCTL_NORMAL  0x00
> > @@ -122,12 +155,23 @@ struct video_i2c_chip {
> >  /* Temperature register */
> >  #define AMG88XX_REG_T01L 0x80
> >
> > +/* Control register */
> > +#define MLX90640_REG_CTL10x800d
> > +#define MLX90640_REG_CTL1_MASK   0x0380
> > +#define MLX90640_REG_CTL1_MASK_SHIFT 7
> > +
> >  static int amg88xx_xfer(struct video_i2c_data *data, char *buf)
> >  {
> >   return regmap_bulk_read(data->regmap, AMG88XX_REG_T01L, buf,
> >   data->chip->buffer_size);
> >  }
> >
> > +static int mlx90640_xfer(struct video_i2c_data *data, char *buf)
> > +{
> > + return regmap_bulk_read(data->regmap, 0x400, buf,
> > + data->chip->buffer_size);
> > +}
> > +
> >  static int amg88xx_setup(struct video_i2c_data *data)
> >  {
> >   unsigned int mask = AMG88XX_FPSC_1FPS;
> > @@ -141,6 +185,27 @@ static int amg88xx_setup(struct video_i2c_data *data)
> >   return regmap_update_bits(data->regmap, AMG88XX_REG_FPSC, mask, val);
> >  }
> >
> > +static int mlx90640_setup(struct video_i2c_data *data)
> > +{
> > + unsigned int n, idx;
> > +
> > + for (n = 0; n < data->chip->num_frame_intervals - 1; n++) {
> > + if (data->frame_interval.numerator
> > + != data->chip->frame_intervals[n].numerator)
> > + continue;
> > +
> > + if (data->frame_interval.denominator
> > + == data->chip->frame_intervals[

Re: [PATCH 2/2] media: video-i2c: add Melexis MLX90640 thermal camera support

2018-11-19 Thread Hans Verkuil
On 11/01/2018 05:15 AM, Matt Ranostay wrote:
> Add initial support for MLX90640 thermal cameras which output an 32x24
> greyscale pixel image along with 2 rows of coefficent data.
> 
> Because of this the data outputed is really 32x26 and needs the two rows
> removed after using the coefficent information to generate processed
> images in userspace.
> 
> Signed-off-by: Matt Ranostay 
> ---
>  drivers/media/i2c/Kconfig |   1 +
>  drivers/media/i2c/video-i2c.c | 110 +-
>  2 files changed, 110 insertions(+), 1 deletion(-)



> 
> diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
> index 704af210e270..4bfb2c66d192 100644
> --- a/drivers/media/i2c/Kconfig
> +++ b/drivers/media/i2c/Kconfig
> @@ -1085,6 +1085,7 @@ config VIDEO_I2C
> Enable the I2C transport video support which supports the
> following:
>  * Panasonic AMG88xx Grid-Eye Sensors
> +* Melexis MLX90640 Thermal Cameras
>  
> To compile this driver as a module, choose M here: the
> module will be called video-i2c
> diff --git a/drivers/media/i2c/video-i2c.c b/drivers/media/i2c/video-i2c.c
> index 6d3b6df0b634..38ade8cb7656 100644
> --- a/drivers/media/i2c/video-i2c.c
> +++ b/drivers/media/i2c/video-i2c.c
> @@ -6,6 +6,7 @@
>   *
>   * Supported:
>   * - Panasonic AMG88xx Grid-Eye Sensors
> + * - Melexis MLX90640 Thermal Cameras
>   */
>  
>  #include 
> @@ -18,6 +19,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -66,12 +68,26 @@ static const struct v4l2_frmsize_discrete amg88xx_size = {
>   .height = 8,
>  };
>  
> +static const struct v4l2_fmtdesc mlx90640_format = {
> + .pixelformat = V4L2_PIX_FMT_Y16_BE,
> +};
> +
> +static const struct v4l2_frmsize_discrete mlx90640_size = {
> + .width = 32,
> + .height = 26, /* 24 lines of pixel data + 2 lines of processing data */
> +};
> +
>  static const struct regmap_config amg88xx_regmap_config = {
>   .reg_bits = 8,
>   .val_bits = 8,
>   .max_register = 0xff
>  };
>  
> +static const struct regmap_config mlx90640_regmap_config = {
> + .reg_bits = 16,
> + .val_bits = 16,
> +};
> +
>  struct video_i2c_chip {
>   /* video dimensions */
>   const struct v4l2_fmtdesc *format;
> @@ -88,6 +104,7 @@ struct video_i2c_chip {
>   unsigned int bpp;
>  
>   const struct regmap_config *regmap_config;
> + struct nvmem_config *nvmem_config;
>  
>   /* setup function */
>   int (*setup)(struct video_i2c_data *data);
> @@ -102,6 +119,22 @@ struct video_i2c_chip {
>   int (*hwmon_init)(struct video_i2c_data *data);
>  };
>  
> +static int mlx90640_nvram_read(void *priv, unsigned int offset, void *val,
> +  size_t bytes)
> +{
> + struct video_i2c_data *data = priv;
> +
> + return regmap_bulk_read(data->regmap, 0x2400 + offset, val, bytes);
> +}
> +
> +static struct nvmem_config mlx90640_nvram_config = {
> + .name = "mlx90640_nvram",
> + .word_size = 2,
> + .stride = 1,
> + .size = 1664,
> + .reg_read = mlx90640_nvram_read,
> +};
> +
>  /* Power control register */
>  #define AMG88XX_REG_PCTL 0x00
>  #define AMG88XX_PCTL_NORMAL  0x00
> @@ -122,12 +155,23 @@ struct video_i2c_chip {
>  /* Temperature register */
>  #define AMG88XX_REG_T01L 0x80
>  
> +/* Control register */
> +#define MLX90640_REG_CTL10x800d
> +#define MLX90640_REG_CTL1_MASK   0x0380
> +#define MLX90640_REG_CTL1_MASK_SHIFT 7
> +
>  static int amg88xx_xfer(struct video_i2c_data *data, char *buf)
>  {
>   return regmap_bulk_read(data->regmap, AMG88XX_REG_T01L, buf,
>   data->chip->buffer_size);
>  }
>  
> +static int mlx90640_xfer(struct video_i2c_data *data, char *buf)
> +{
> + return regmap_bulk_read(data->regmap, 0x400, buf,
> + data->chip->buffer_size);
> +}
> +
>  static int amg88xx_setup(struct video_i2c_data *data)
>  {
>   unsigned int mask = AMG88XX_FPSC_1FPS;
> @@ -141,6 +185,27 @@ static int amg88xx_setup(struct video_i2c_data *data)
>   return regmap_update_bits(data->regmap, AMG88XX_REG_FPSC, mask, val);
>  }
>  
> +static int mlx90640_setup(struct video_i2c_data *data)
> +{
> + unsigned int n, idx;
> +
> + for (n = 0; n < data->chip->num_frame_intervals - 1; n++) {
> + if (data->frame_interval.numerator
> + != data->chip->frame_intervals[n].numerator)
> + continue;
> +
> + if (data->frame_interval.denominator
> + == data->chip->frame_intervals[n].denominator)
> + break;
> + }
> +
> + idx = data->chip->num_frame_intervals - n - 1;
> +
> + return regmap_update_bits(data->regmap, MLX90640_REG_CTL1,
> +   MLX90640_REG_CTL1_MASK,
> +   idx << MLX90640_REG_CTL1_MASK_SHIFT);
> +}
> +
>  st

[PATCH 2/2] media: video-i2c: add Melexis MLX90640 thermal camera support

2018-10-31 Thread Matt Ranostay
Add initial support for MLX90640 thermal cameras which output an 32x24
greyscale pixel image along with 2 rows of coefficent data.

Because of this the data outputed is really 32x26 and needs the two rows
removed after using the coefficent information to generate processed
images in userspace.

Signed-off-by: Matt Ranostay 
---
 drivers/media/i2c/Kconfig |   1 +
 drivers/media/i2c/video-i2c.c | 110 +-
 2 files changed, 110 insertions(+), 1 deletion(-)

diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
index 704af210e270..4bfb2c66d192 100644
--- a/drivers/media/i2c/Kconfig
+++ b/drivers/media/i2c/Kconfig
@@ -1085,6 +1085,7 @@ config VIDEO_I2C
  Enable the I2C transport video support which supports the
  following:
   * Panasonic AMG88xx Grid-Eye Sensors
+  * Melexis MLX90640 Thermal Cameras
 
  To compile this driver as a module, choose M here: the
  module will be called video-i2c
diff --git a/drivers/media/i2c/video-i2c.c b/drivers/media/i2c/video-i2c.c
index 6d3b6df0b634..38ade8cb7656 100644
--- a/drivers/media/i2c/video-i2c.c
+++ b/drivers/media/i2c/video-i2c.c
@@ -6,6 +6,7 @@
  *
  * Supported:
  * - Panasonic AMG88xx Grid-Eye Sensors
+ * - Melexis MLX90640 Thermal Cameras
  */
 
 #include 
@@ -18,6 +19,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -66,12 +68,26 @@ static const struct v4l2_frmsize_discrete amg88xx_size = {
.height = 8,
 };
 
+static const struct v4l2_fmtdesc mlx90640_format = {
+   .pixelformat = V4L2_PIX_FMT_Y16_BE,
+};
+
+static const struct v4l2_frmsize_discrete mlx90640_size = {
+   .width = 32,
+   .height = 26, /* 24 lines of pixel data + 2 lines of processing data */
+};
+
 static const struct regmap_config amg88xx_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = 0xff
 };
 
+static const struct regmap_config mlx90640_regmap_config = {
+   .reg_bits = 16,
+   .val_bits = 16,
+};
+
 struct video_i2c_chip {
/* video dimensions */
const struct v4l2_fmtdesc *format;
@@ -88,6 +104,7 @@ struct video_i2c_chip {
unsigned int bpp;
 
const struct regmap_config *regmap_config;
+   struct nvmem_config *nvmem_config;
 
/* setup function */
int (*setup)(struct video_i2c_data *data);
@@ -102,6 +119,22 @@ struct video_i2c_chip {
int (*hwmon_init)(struct video_i2c_data *data);
 };
 
+static int mlx90640_nvram_read(void *priv, unsigned int offset, void *val,
+size_t bytes)
+{
+   struct video_i2c_data *data = priv;
+
+   return regmap_bulk_read(data->regmap, 0x2400 + offset, val, bytes);
+}
+
+static struct nvmem_config mlx90640_nvram_config = {
+   .name = "mlx90640_nvram",
+   .word_size = 2,
+   .stride = 1,
+   .size = 1664,
+   .reg_read = mlx90640_nvram_read,
+};
+
 /* Power control register */
 #define AMG88XX_REG_PCTL   0x00
 #define AMG88XX_PCTL_NORMAL0x00
@@ -122,12 +155,23 @@ struct video_i2c_chip {
 /* Temperature register */
 #define AMG88XX_REG_T01L   0x80
 
+/* Control register */
+#define MLX90640_REG_CTL1  0x800d
+#define MLX90640_REG_CTL1_MASK 0x0380
+#define MLX90640_REG_CTL1_MASK_SHIFT   7
+
 static int amg88xx_xfer(struct video_i2c_data *data, char *buf)
 {
return regmap_bulk_read(data->regmap, AMG88XX_REG_T01L, buf,
data->chip->buffer_size);
 }
 
+static int mlx90640_xfer(struct video_i2c_data *data, char *buf)
+{
+   return regmap_bulk_read(data->regmap, 0x400, buf,
+   data->chip->buffer_size);
+}
+
 static int amg88xx_setup(struct video_i2c_data *data)
 {
unsigned int mask = AMG88XX_FPSC_1FPS;
@@ -141,6 +185,27 @@ static int amg88xx_setup(struct video_i2c_data *data)
return regmap_update_bits(data->regmap, AMG88XX_REG_FPSC, mask, val);
 }
 
+static int mlx90640_setup(struct video_i2c_data *data)
+{
+   unsigned int n, idx;
+
+   for (n = 0; n < data->chip->num_frame_intervals - 1; n++) {
+   if (data->frame_interval.numerator
+   != data->chip->frame_intervals[n].numerator)
+   continue;
+
+   if (data->frame_interval.denominator
+   == data->chip->frame_intervals[n].denominator)
+   break;
+   }
+
+   idx = data->chip->num_frame_intervals - n - 1;
+
+   return regmap_update_bits(data->regmap, MLX90640_REG_CTL1,
+ MLX90640_REG_CTL1_MASK,
+ idx << MLX90640_REG_CTL1_MASK_SHIFT);
+}
+
 static int amg88xx_set_power_on(struct video_i2c_data *data)
 {
int ret;
@@ -274,13 +339,27 @@ static int amg88xx_hwmon_init(struct video_i2c_data *data)
 #defineamg88xx_hwmon_init  NULL
 #endif
 
-#define AMG88XX0
+