cron job: media_tree daily build: OK

2018-09-23 Thread Hans Verkuil
This message is generated daily by a cron job that builds media_tree for
the kernels and architectures in the list below.

Results of the daily build of media_tree:

date:   Mon Sep 24 04:00:16 CEST 2018
media-tree git hash:985cdcb08a0488558d1005139596b64d73bee267
media_build git hash:   44385b9c61ecc27059a651885895c8ea09cd4179
v4l-utils git hash: e03a5fe118de918b0778fea4a227db3cb18eda1c
edid-decode git hash:   5eeb151a748788666534d6ea3da07f90400d24c2
gcc version:i686-linux-gcc (GCC) 8.2.0
sparse version: 0.5.2
smatch version: 0.5.1
host hardware:  x86_64
host os:4.17.0-3-amd64

linux-git-arm-at91: OK
linux-git-arm-davinci: OK
linux-git-arm-multi: OK
linux-git-arm-pxa: OK
linux-git-arm-stm32: OK
linux-git-arm64: OK
linux-git-i686: OK
linux-git-mips: OK
linux-git-powerpc64: OK
linux-git-sh: OK
linux-git-x86_64: OK
Check COMPILE_TEST: OK
linux-3.10.108-i686: OK
linux-3.10.108-x86_64: OK
linux-3.11.10-i686: OK
linux-3.11.10-x86_64: OK
linux-3.12.74-i686: OK
linux-3.12.74-x86_64: OK
linux-3.13.11-i686: OK
linux-3.13.11-x86_64: OK
linux-3.14.79-i686: OK
linux-3.14.79-x86_64: OK
linux-3.15.10-i686: OK
linux-3.15.10-x86_64: OK
linux-3.16.57-i686: OK
linux-3.16.57-x86_64: OK
linux-3.17.8-i686: OK
linux-3.17.8-x86_64: OK
linux-3.18.119-i686: OK
linux-3.18.119-x86_64: OK
linux-3.19.8-i686: OK
linux-3.19.8-x86_64: OK
linux-4.0.9-i686: OK
linux-4.0.9-x86_64: OK
linux-4.1.52-i686: OK
linux-4.1.52-x86_64: OK
linux-4.2.8-i686: OK
linux-4.2.8-x86_64: OK
linux-4.3.6-i686: OK
linux-4.3.6-x86_64: OK
linux-4.4.152-i686: OK
linux-4.4.152-x86_64: OK
linux-4.5.7-i686: OK
linux-4.5.7-x86_64: OK
linux-4.6.7-i686: OK
linux-4.6.7-x86_64: OK
linux-4.7.10-i686: OK
linux-4.7.10-x86_64: OK
linux-4.8.17-i686: OK
linux-4.8.17-x86_64: OK
linux-4.9.124-i686: OK
linux-4.9.124-x86_64: OK
linux-4.10.17-i686: OK
linux-4.10.17-x86_64: OK
linux-4.11.12-i686: OK
linux-4.11.12-x86_64: OK
linux-4.12.14-i686: OK
linux-4.12.14-x86_64: OK
linux-4.13.16-i686: OK
linux-4.13.16-x86_64: OK
linux-4.14.67-i686: OK
linux-4.14.67-x86_64: OK
linux-4.15.18-i686: OK
linux-4.15.18-x86_64: OK
linux-4.16.18-i686: OK
linux-4.16.18-x86_64: OK
linux-4.17.19-i686: OK
linux-4.17.19-x86_64: OK
linux-4.18.5-i686: OK
linux-4.18.5-x86_64: OK
linux-4.19-rc1-i686: OK
linux-4.19-rc1-x86_64: OK
apps: OK
spec-git: OK
sparse: WARNINGS

Detailed results are available here:

http://www.xs4all.nl/~hverkuil/logs/Monday.log

Full logs are available here:

http://www.xs4all.nl/~hverkuil/logs/Monday.tar.bz2

The Media Infrastructure API from this daily build is here:

http://www.xs4all.nl/~hverkuil/spec/index.html


Re: [PATCH v2 2/6] media: video-i2c: use i2c regmap

2018-09-23 Thread Matt Ranostay
On Mon, Sep 24, 2018 at 12:35 AM Akinobu Mita  wrote:
>
> Use regmap for i2c register access.  This simplifies register accesses and
> chooses suitable access commands based on the functionality that the
> adapter supports.
>
> Cc: Matt Ranostay 
> Cc: Sakari Ailus 
> Cc: Hans Verkuil 
> Cc: Mauro Carvalho Chehab 
> Signed-off-by: Akinobu Mita 

Acked-by: Matt Ranostay 

> ---
> * v2
> - Add thermistor and termperature register address definisions
>
>  drivers/media/i2c/video-i2c.c | 60 
> ---
>  1 file changed, 34 insertions(+), 26 deletions(-)
>
> diff --git a/drivers/media/i2c/video-i2c.c b/drivers/media/i2c/video-i2c.c
> index b7a2af9..fb8509e 100644
> --- a/drivers/media/i2c/video-i2c.c
> +++ b/drivers/media/i2c/video-i2c.c
> @@ -17,6 +17,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -38,7 +39,7 @@ struct video_i2c_buffer {
>  };
>
>  struct video_i2c_data {
> -   struct i2c_client *client;
> +   struct regmap *regmap;
> const struct video_i2c_chip *chip;
> struct mutex lock;
> spinlock_t slock;
> @@ -62,6 +63,12 @@ static const struct v4l2_frmsize_discrete amg88xx_size = {
> .height = 8,
>  };
>
> +static const struct regmap_config amg88xx_regmap_config = {
> +   .reg_bits = 8,
> +   .val_bits = 8,
> +   .max_register = 0xff
> +};
> +
>  struct video_i2c_chip {
> /* video dimensions */
> const struct v4l2_fmtdesc *format;
> @@ -76,6 +83,8 @@ struct video_i2c_chip {
> /* pixel size in bits */
> unsigned int bpp;
>
> +   const struct regmap_config *regmap_config;
> +
> /* xfer function */
> int (*xfer)(struct video_i2c_data *data, char *buf);
>
> @@ -83,26 +92,16 @@ struct video_i2c_chip {
> int (*hwmon_init)(struct video_i2c_data *data);
>  };
>
> -static int amg88xx_xfer(struct video_i2c_data *data, char *buf)
> -{
> -   struct i2c_client *client = data->client;
> -   struct i2c_msg msg[2];
> -   u8 reg = 0x80;
> -   int ret;
> -
> -   msg[0].addr = client->addr;
> -   msg[0].flags = 0;
> -   msg[0].len = 1;
> -   msg[0].buf  = (char *)
> -
> -   msg[1].addr = client->addr;
> -   msg[1].flags = I2C_M_RD;
> -   msg[1].len = data->chip->buffer_size;
> -   msg[1].buf = (char *)buf;
> +/* Thermistor register */
> +#define AMG88XX_REG_TTHL   0x0e
>
> -   ret = i2c_transfer(client->adapter, msg, 2);
> +/* Temperature register */
> +#define AMG88XX_REG_T01L   0x80
>
> -   return (ret == 2) ? 0 : -EIO;
> +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);
>  }
>
>  #if IS_ENABLED(CONFIG_HWMON)
> @@ -133,12 +132,15 @@ static int amg88xx_read(struct device *dev, enum 
> hwmon_sensor_types type,
> u32 attr, int channel, long *val)
>  {
> struct video_i2c_data *data = dev_get_drvdata(dev);
> -   struct i2c_client *client = data->client;
> -   int tmp = i2c_smbus_read_word_data(client, 0x0e);
> +   __le16 buf;
> +   int tmp;
>
> -   if (tmp < 0)
> +   tmp = regmap_bulk_read(data->regmap, AMG88XX_REG_TTHL, , 2);
> +   if (tmp)
> return tmp;
>
> +   tmp = le16_to_cpu(buf);
> +
> /*
>  * Check for sign bit, this isn't a two's complement value but an
>  * absolute temperature that needs to be inverted in the case of being
> @@ -164,8 +166,9 @@ static const struct hwmon_chip_info amg88xx_chip_info = {
>
>  static int amg88xx_hwmon_init(struct video_i2c_data *data)
>  {
> -   void *hwmon = devm_hwmon_device_register_with_info(>client->dev,
> -   "amg88xx", data, _chip_info, NULL);
> +   struct device *dev = regmap_get_device(data->regmap);
> +   void *hwmon = devm_hwmon_device_register_with_info(dev, "amg88xx", 
> data,
> +   _chip_info, NULL);
>
> return PTR_ERR_OR_ZERO(hwmon);
>  }
> @@ -182,6 +185,7 @@ static const struct video_i2c_chip video_i2c_chip[] = {
> .max_fps= 10,
> .buffer_size= 128,
> .bpp= 16,
> +   .regmap_config  = _regmap_config,
> .xfer   = _xfer,
> .hwmon_init = amg88xx_hwmon_init,
> },
> @@ -350,7 +354,8 @@ static int video_i2c_querycap(struct file *file, void  
> *priv,
> struct v4l2_capability *vcap)
>  {
> struct video_i2c_data *data = video_drvdata(file);
> -   struct i2c_client *client = data->client;
> +   struct device *dev = regmap_get_device(data->regmap);
> +   struct i2c_client *client = to_i2c_client(dev);
>
> strlcpy(vcap->driver, data->v4l2_dev.name, sizeof(vcap->driver));
> 

[PATCH v2 1/6] media: video-i2c: avoid accessing released memory area when removing driver

2018-09-23 Thread Akinobu Mita
The video_i2c_data is allocated by kzalloc and released by the video
device's release callback.  The release callback is called when
video_unregister_device() is called, but it will still be accessed after
calling video_unregister_device().

Fix the use after free by allocating video_i2c_data by devm_kzalloc() with
i2c_client->dev so that it will automatically be released when the i2c
driver is removed.

Fixes: 5cebaac60974 ("media: video-i2c: add video-i2c driver")
Cc: Matt Ranostay 
Cc: Sakari Ailus 
Cc: Hans Verkuil 
Cc: Mauro Carvalho Chehab 
Acked-by: Matt Ranostay 
Signed-off-by: Akinobu Mita 
---
* v2
- Update commit log to clarify the use after free
- Add Acked-by tag

 drivers/media/i2c/video-i2c.c | 18 +-
 1 file changed, 5 insertions(+), 13 deletions(-)

diff --git a/drivers/media/i2c/video-i2c.c b/drivers/media/i2c/video-i2c.c
index 06d29d8..b7a2af9 100644
--- a/drivers/media/i2c/video-i2c.c
+++ b/drivers/media/i2c/video-i2c.c
@@ -508,20 +508,15 @@ static const struct v4l2_ioctl_ops video_i2c_ioctl_ops = {
.vidioc_streamoff   = vb2_ioctl_streamoff,
 };
 
-static void video_i2c_release(struct video_device *vdev)
-{
-   kfree(video_get_drvdata(vdev));
-}
-
 static int video_i2c_probe(struct i2c_client *client,
 const struct i2c_device_id *id)
 {
struct video_i2c_data *data;
struct v4l2_device *v4l2_dev;
struct vb2_queue *queue;
-   int ret = -ENODEV;
+   int ret;
 
-   data = kzalloc(sizeof(*data), GFP_KERNEL);
+   data = devm_kzalloc(>dev, sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
 
@@ -530,7 +525,7 @@ static int video_i2c_probe(struct i2c_client *client,
else if (id)
data->chip = _i2c_chip[id->driver_data];
else
-   goto error_free_device;
+   return -ENODEV;
 
data->client = client;
v4l2_dev = >v4l2_dev;
@@ -538,7 +533,7 @@ static int video_i2c_probe(struct i2c_client *client,
 
ret = v4l2_device_register(>dev, v4l2_dev);
if (ret < 0)
-   goto error_free_device;
+   return ret;
 
mutex_init(>lock);
mutex_init(>queue_lock);
@@ -568,7 +563,7 @@ static int video_i2c_probe(struct i2c_client *client,
data->vdev.fops = _i2c_fops;
data->vdev.lock = >lock;
data->vdev.ioctl_ops = _i2c_ioctl_ops;
-   data->vdev.release = video_i2c_release;
+   data->vdev.release = video_device_release_empty;
data->vdev.device_caps = V4L2_CAP_VIDEO_CAPTURE |
 V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;
 
@@ -597,9 +592,6 @@ static int video_i2c_probe(struct i2c_client *client,
mutex_destroy(>lock);
mutex_destroy(>queue_lock);
 
-error_free_device:
-   kfree(data);
-
return ret;
 }
 
-- 
2.7.4



[PATCH v2 0/6] media: video-i2c: support changing frame interval and runtime PM

2018-09-23 Thread Akinobu Mita
This patchset adds support for changing frame interval and runtime PM for
video-i2c driver.  This also adds an helper macro to v4l2 common
internal API that is used to to find a suitable frame interval.

There are a couple of unrelated changes that are included for simplifying
driver initialization code and register accesses.

* v2
- Add Acked-by and Reviewed-by tags
- Update commit log to clarify the use after free
- Add thermistor and termperature register address definisions
- Stop adding v4l2_find_closest_fract() in v4l2 common internal API
- Add V4L2_FRACT_COMPARE() macro in v4l2 common internal API
- Use V4L2_FRACT_COMPARE() to find suitable frame interval instead of
  v4l2_find_closest_fract()
- Add comment for register address definisions

Akinobu Mita (6):
  media: video-i2c: avoid accessing released memory area when removing
driver
  media: video-i2c: use i2c regmap
  media: v4l2-common: add V4L2_FRACT_COMPARE
  media: vivid: use V4L2_FRACT_COMPARE
  media: video-i2c: support changing frame interval
  media: video-i2c: support runtime PM

 drivers/media/i2c/video-i2c.c| 286 ++-
 drivers/media/platform/vivid/vivid-vid-cap.c |   9 +-
 include/media/v4l2-common.h  |   5 +
 3 files changed, 247 insertions(+), 53 deletions(-)

Cc: Matt Ranostay 
Cc: Sakari Ailus 
Cc: Hans Verkuil 
Cc: Mauro Carvalho Chehab 
-- 
2.7.4



[PATCH v2 3/6] media: v4l2-common: add V4L2_FRACT_COMPARE

2018-09-23 Thread Akinobu Mita
Add macro to compare two v4l2_fract values in v4l2 common internal API.
The same macro FRACT_CMP() is used by vivid and bcm2835-camera.  This just
renames it to V4L2_FRACT_COMPARE in order to avoid namespace collision.

Cc: Matt Ranostay 
Cc: Sakari Ailus 
Cc: Hans Verkuil 
Cc: Mauro Carvalho Chehab 
Signed-off-by: Akinobu Mita 
---
* v2
- New patch

 include/media/v4l2-common.h | 5 +
 1 file changed, 5 insertions(+)

diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h
index cdc87ec..eafb8a3 100644
--- a/include/media/v4l2-common.h
+++ b/include/media/v4l2-common.h
@@ -384,4 +384,9 @@ int v4l2_g_parm_cap(struct video_device *vdev,
 int v4l2_s_parm_cap(struct video_device *vdev,
struct v4l2_subdev *sd, struct v4l2_streamparm *a);
 
+/* Compare two v4l2_fract structs */
+#define V4L2_FRACT_COMPARE(a, OP, b)   \
+   ((u64)(a).numerator * (b).denominator OP\
+   (u64)(b).numerator * (a).denominator)
+
 #endif /* V4L2_COMMON_H_ */
-- 
2.7.4



[PATCH v2 6/6] media: video-i2c: support runtime PM

2018-09-23 Thread Akinobu Mita
AMG88xx has a register for setting operating mode.  This adds support
runtime PM by changing the operating mode.

The instruction for changing sleep mode to normal mode is from the
reference specifications.

https://docid81hrs3j1.cloudfront.net/medialibrary/2017/11/PANA-S-A0002141979-1.pdf

Cc: Matt Ranostay 
Cc: Sakari Ailus 
Cc: Hans Verkuil 
Cc: Mauro Carvalho Chehab 
Reviewed-by: Matt Ranostay 
Signed-off-by: Akinobu Mita 
---
* v2
- Add Reviewed-by tag
- Add comment for register address definisions

 drivers/media/i2c/video-i2c.c | 142 +-
 1 file changed, 140 insertions(+), 2 deletions(-)

diff --git a/drivers/media/i2c/video-i2c.c b/drivers/media/i2c/video-i2c.c
index 6dd1929..f7058cf 100644
--- a/drivers/media/i2c/video-i2c.c
+++ b/drivers/media/i2c/video-i2c.c
@@ -17,6 +17,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -94,10 +95,23 @@ struct video_i2c_chip {
/* xfer function */
int (*xfer)(struct video_i2c_data *data, char *buf);
 
+   /* power control function */
+   int (*set_power)(struct video_i2c_data *data, bool on);
+
/* hwmon init function */
int (*hwmon_init)(struct video_i2c_data *data);
 };
 
+/* Power control register */
+#define AMG88XX_REG_PCTL   0x00
+#define AMG88XX_PCTL_NORMAL0x00
+#define AMG88XX_PCTL_SLEEP 0x10
+
+/* Reset register */
+#define AMG88XX_REG_RST0x01
+#define AMG88XX_RST_FLAG   0x30
+#define AMG88XX_RST_INIT   0x3f
+
 /* Frame rate register */
 #define AMG88XX_REG_FPSC   0x02
 #define AMG88XX_FPSC_1FPS  BIT(0)
@@ -127,6 +141,59 @@ static int amg88xx_setup(struct video_i2c_data *data)
return regmap_update_bits(data->regmap, AMG88XX_REG_FPSC, mask, val);
 }
 
+static int amg88xx_set_power_on(struct video_i2c_data *data)
+{
+   int ret;
+
+   ret = regmap_write(data->regmap, AMG88XX_REG_PCTL, AMG88XX_PCTL_NORMAL);
+   if (ret)
+   return ret;
+
+   msleep(50);
+
+   ret = regmap_write(data->regmap, AMG88XX_REG_RST, AMG88XX_RST_INIT);
+   if (ret)
+   return ret;
+
+   msleep(2);
+
+   ret = regmap_write(data->regmap, AMG88XX_REG_RST, AMG88XX_RST_FLAG);
+   if (ret)
+   return ret;
+
+   /*
+* Wait two frames before reading thermistor and temperature registers
+*/
+   msleep(200);
+
+   return 0;
+}
+
+static int amg88xx_set_power_off(struct video_i2c_data *data)
+{
+   int ret;
+
+   ret = regmap_write(data->regmap, AMG88XX_REG_PCTL, AMG88XX_PCTL_SLEEP);
+   if (ret)
+   return ret;
+   /*
+* Wait for a while to avoid resuming normal mode immediately after
+* entering sleep mode, otherwise the device occasionally goes wrong
+* (thermistor and temperature registers are not updated at all)
+*/
+   msleep(100);
+
+   return 0;
+}
+
+static int amg88xx_set_power(struct video_i2c_data *data, bool on)
+{
+   if (on)
+   return amg88xx_set_power_on(data);
+
+   return amg88xx_set_power_off(data);
+}
+
 #if IS_ENABLED(CONFIG_HWMON)
 
 static const u32 amg88xx_temp_config[] = {
@@ -158,7 +225,15 @@ static int amg88xx_read(struct device *dev, enum 
hwmon_sensor_types type,
__le16 buf;
int tmp;
 
+   tmp = pm_runtime_get_sync(regmap_get_device(data->regmap));
+   if (tmp < 0) {
+   pm_runtime_put_noidle(regmap_get_device(data->regmap));
+   return tmp;
+   }
+
tmp = regmap_bulk_read(data->regmap, AMG88XX_REG_TTHL, , 2);
+   pm_runtime_mark_last_busy(regmap_get_device(data->regmap));
+   pm_runtime_put_autosuspend(regmap_get_device(data->regmap));
if (tmp)
return tmp;
 
@@ -217,6 +292,7 @@ static const struct video_i2c_chip video_i2c_chip[] = {
.regmap_config  = _regmap_config,
.setup  = _setup,
.xfer   = _xfer,
+   .set_power  = amg88xx_set_power,
.hwmon_init = amg88xx_hwmon_init,
},
 };
@@ -343,14 +419,21 @@ static void video_i2c_del_list(struct vb2_queue *vq, enum 
vb2_buffer_state state
 static int start_streaming(struct vb2_queue *vq, unsigned int count)
 {
struct video_i2c_data *data = vb2_get_drv_priv(vq);
+   struct device *dev = regmap_get_device(data->regmap);
int ret;
 
if (data->kthread_vid_cap)
return 0;
 
+   ret = pm_runtime_get_sync(dev);
+   if (ret < 0) {
+   pm_runtime_put_noidle(dev);
+   goto error_del_list;
+   }
+
ret = data->chip->setup(data);
if (ret)
-   goto error_del_list;
+   goto error_rpm_put;
 
data->sequence = 0;
data->kthread_vid_cap = kthread_run(video_i2c_thread_vid_cap, data,
@@ -359,6 +442,9 @@ static int 

[PATCH v2 5/6] media: video-i2c: support changing frame interval

2018-09-23 Thread Akinobu Mita
AMG88xx has a register for setting frame rate 1 or 10 FPS.
This adds support changing frame interval.

Reference specifications:
https://docid81hrs3j1.cloudfront.net/medialibrary/2017/11/PANA-S-A0002141979-1.pdf

Cc: Matt Ranostay 
Cc: Sakari Ailus 
Cc: Hans Verkuil 
Cc: Mauro Carvalho Chehab 
Acked-by: Matt Ranostay 
Signed-off-by: Akinobu Mita 
---
* v2
- Add Acked-by tag
- Add comment for frame rate register address definision
- Use V4L2_FRACT_COMPARE() to find suitable frame interval

 drivers/media/i2c/video-i2c.c | 78 ---
 1 file changed, 66 insertions(+), 12 deletions(-)

diff --git a/drivers/media/i2c/video-i2c.c b/drivers/media/i2c/video-i2c.c
index fb8509e..6dd1929 100644
--- a/drivers/media/i2c/video-i2c.c
+++ b/drivers/media/i2c/video-i2c.c
@@ -52,6 +52,8 @@ struct video_i2c_data {
 
struct task_struct *kthread_vid_cap;
struct list_head vid_cap_active;
+
+   struct v4l2_fract frame_interval;
 };
 
 static const struct v4l2_fmtdesc amg88xx_format = {
@@ -74,8 +76,9 @@ struct video_i2c_chip {
const struct v4l2_fmtdesc *format;
const struct v4l2_frmsize_discrete *size;
 
-   /* max frames per second */
-   unsigned int max_fps;
+   /* available frame intervals */
+   const struct v4l2_fract *frame_intervals;
+   unsigned int num_frame_intervals;
 
/* pixel buffer size */
unsigned int buffer_size;
@@ -85,6 +88,9 @@ struct video_i2c_chip {
 
const struct regmap_config *regmap_config;
 
+   /* setup function */
+   int (*setup)(struct video_i2c_data *data);
+
/* xfer function */
int (*xfer)(struct video_i2c_data *data, char *buf);
 
@@ -92,6 +98,10 @@ struct video_i2c_chip {
int (*hwmon_init)(struct video_i2c_data *data);
 };
 
+/* Frame rate register */
+#define AMG88XX_REG_FPSC   0x02
+#define AMG88XX_FPSC_1FPS  BIT(0)
+
 /* Thermistor register */
 #define AMG88XX_REG_TTHL   0x0e
 
@@ -104,6 +114,19 @@ static int amg88xx_xfer(struct video_i2c_data *data, char 
*buf)
data->chip->buffer_size);
 }
 
+static int amg88xx_setup(struct video_i2c_data *data)
+{
+   unsigned int mask = AMG88XX_FPSC_1FPS;
+   unsigned int val;
+
+   if (data->frame_interval.numerator == data->frame_interval.denominator)
+   val = mask;
+   else
+   val = 0;
+
+   return regmap_update_bits(data->regmap, AMG88XX_REG_FPSC, mask, val);
+}
+
 #if IS_ENABLED(CONFIG_HWMON)
 
 static const u32 amg88xx_temp_config[] = {
@@ -178,14 +201,21 @@ static int amg88xx_hwmon_init(struct video_i2c_data *data)
 
 #define AMG88XX0
 
+static const struct v4l2_fract amg88xx_frame_intervals[] = {
+   { 1, 10 },
+   { 1, 1 },
+};
+
 static const struct video_i2c_chip video_i2c_chip[] = {
[AMG88XX] = {
.size   = _size,
.format = _format,
-   .max_fps= 10,
+   .frame_intervals= amg88xx_frame_intervals,
+   .num_frame_intervals= ARRAY_SIZE(amg88xx_frame_intervals),
.buffer_size= 128,
.bpp= 16,
.regmap_config  = _regmap_config,
+   .setup  = _setup,
.xfer   = _xfer,
.hwmon_init = amg88xx_hwmon_init,
},
@@ -250,7 +280,8 @@ static void buffer_queue(struct vb2_buffer *vb)
 static int video_i2c_thread_vid_cap(void *priv)
 {
struct video_i2c_data *data = priv;
-   unsigned int delay = msecs_to_jiffies(1000 / data->chip->max_fps);
+   unsigned int delay = mult_frac(HZ, data->frame_interval.numerator,
+  data->frame_interval.denominator);
 
set_freezable();
 
@@ -312,19 +343,26 @@ static void video_i2c_del_list(struct vb2_queue *vq, enum 
vb2_buffer_state state
 static int start_streaming(struct vb2_queue *vq, unsigned int count)
 {
struct video_i2c_data *data = vb2_get_drv_priv(vq);
+   int ret;
 
if (data->kthread_vid_cap)
return 0;
 
+   ret = data->chip->setup(data);
+   if (ret)
+   goto error_del_list;
+
data->sequence = 0;
data->kthread_vid_cap = kthread_run(video_i2c_thread_vid_cap, data,
"%s-vid-cap", data->v4l2_dev.name);
-   if (!IS_ERR(data->kthread_vid_cap))
+   ret = PTR_ERR_OR_ZERO(data->kthread_vid_cap);
+   if (!ret)
return 0;
 
+error_del_list:
video_i2c_del_list(vq, VB2_BUF_STATE_QUEUED);
 
-   return PTR_ERR(data->kthread_vid_cap);
+   return ret;
 }
 
 static void stop_streaming(struct vb2_queue *vq)
@@ -431,15 +469,14 @@ static int video_i2c_enum_frameintervals(struct file 
*file, void *priv,
const struct video_i2c_data *data = video_drvdata(file);
const struct v4l2_frmsize_discrete *size = 

[PATCH v2 4/6] media: vivid: use V4L2_FRACT_COMPARE

2018-09-23 Thread Akinobu Mita
Now the equivalent of FRACT_CMP() is added in v4l2 common internal API
header.

Cc: Matt Ranostay 
Cc: Sakari Ailus 
Cc: Hans Verkuil 
Cc: Mauro Carvalho Chehab 
Signed-off-by: Akinobu Mita 
---
* v2
- New patch

 drivers/media/platform/vivid/vivid-vid-cap.c | 9 +++--
 1 file changed, 3 insertions(+), 6 deletions(-)

diff --git a/drivers/media/platform/vivid/vivid-vid-cap.c 
b/drivers/media/platform/vivid/vivid-vid-cap.c
index 1599159..f19c701 100644
--- a/drivers/media/platform/vivid/vivid-vid-cap.c
+++ b/drivers/media/platform/vivid/vivid-vid-cap.c
@@ -1824,9 +1824,6 @@ int vivid_vid_cap_g_parm(struct file *file, void *priv,
return 0;
 }
 
-#define FRACT_CMP(a, OP, b)\
-   ((u64)(a).numerator * (b).denominator  OP  (u64)(b).numerator * 
(a).denominator)
-
 int vivid_vid_cap_s_parm(struct file *file, void *priv,
  struct v4l2_streamparm *parm)
 {
@@ -1847,14 +1844,14 @@ int vivid_vid_cap_s_parm(struct file *file, void *priv,
if (tpf.denominator == 0)
tpf = webcam_intervals[ival_sz - 1];
for (i = 0; i < ival_sz; i++)
-   if (FRACT_CMP(tpf, >=, webcam_intervals[i]))
+   if (V4L2_FRACT_COMPARE(tpf, >=, webcam_intervals[i]))
break;
if (i == ival_sz)
i = ival_sz - 1;
dev->webcam_ival_idx = i;
tpf = webcam_intervals[dev->webcam_ival_idx];
-   tpf = FRACT_CMP(tpf, <, tpf_min) ? tpf_min : tpf;
-   tpf = FRACT_CMP(tpf, >, tpf_max) ? tpf_max : tpf;
+   tpf = V4L2_FRACT_COMPARE(tpf, <, tpf_min) ? tpf_min : tpf;
+   tpf = V4L2_FRACT_COMPARE(tpf, >, tpf_max) ? tpf_max : tpf;
 
/* resync the thread's timings */
dev->cap_seq_resync = true;
-- 
2.7.4



[PATCH v2 2/6] media: video-i2c: use i2c regmap

2018-09-23 Thread Akinobu Mita
Use regmap for i2c register access.  This simplifies register accesses and
chooses suitable access commands based on the functionality that the
adapter supports.

Cc: Matt Ranostay 
Cc: Sakari Ailus 
Cc: Hans Verkuil 
Cc: Mauro Carvalho Chehab 
Signed-off-by: Akinobu Mita 
---
* v2
- Add thermistor and termperature register address definisions

 drivers/media/i2c/video-i2c.c | 60 ---
 1 file changed, 34 insertions(+), 26 deletions(-)

diff --git a/drivers/media/i2c/video-i2c.c b/drivers/media/i2c/video-i2c.c
index b7a2af9..fb8509e 100644
--- a/drivers/media/i2c/video-i2c.c
+++ b/drivers/media/i2c/video-i2c.c
@@ -17,6 +17,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -38,7 +39,7 @@ struct video_i2c_buffer {
 };
 
 struct video_i2c_data {
-   struct i2c_client *client;
+   struct regmap *regmap;
const struct video_i2c_chip *chip;
struct mutex lock;
spinlock_t slock;
@@ -62,6 +63,12 @@ static const struct v4l2_frmsize_discrete amg88xx_size = {
.height = 8,
 };
 
+static const struct regmap_config amg88xx_regmap_config = {
+   .reg_bits = 8,
+   .val_bits = 8,
+   .max_register = 0xff
+};
+
 struct video_i2c_chip {
/* video dimensions */
const struct v4l2_fmtdesc *format;
@@ -76,6 +83,8 @@ struct video_i2c_chip {
/* pixel size in bits */
unsigned int bpp;
 
+   const struct regmap_config *regmap_config;
+
/* xfer function */
int (*xfer)(struct video_i2c_data *data, char *buf);
 
@@ -83,26 +92,16 @@ struct video_i2c_chip {
int (*hwmon_init)(struct video_i2c_data *data);
 };
 
-static int amg88xx_xfer(struct video_i2c_data *data, char *buf)
-{
-   struct i2c_client *client = data->client;
-   struct i2c_msg msg[2];
-   u8 reg = 0x80;
-   int ret;
-
-   msg[0].addr = client->addr;
-   msg[0].flags = 0;
-   msg[0].len = 1;
-   msg[0].buf  = (char *)
-
-   msg[1].addr = client->addr;
-   msg[1].flags = I2C_M_RD;
-   msg[1].len = data->chip->buffer_size;
-   msg[1].buf = (char *)buf;
+/* Thermistor register */
+#define AMG88XX_REG_TTHL   0x0e
 
-   ret = i2c_transfer(client->adapter, msg, 2);
+/* Temperature register */
+#define AMG88XX_REG_T01L   0x80
 
-   return (ret == 2) ? 0 : -EIO;
+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);
 }
 
 #if IS_ENABLED(CONFIG_HWMON)
@@ -133,12 +132,15 @@ static int amg88xx_read(struct device *dev, enum 
hwmon_sensor_types type,
u32 attr, int channel, long *val)
 {
struct video_i2c_data *data = dev_get_drvdata(dev);
-   struct i2c_client *client = data->client;
-   int tmp = i2c_smbus_read_word_data(client, 0x0e);
+   __le16 buf;
+   int tmp;
 
-   if (tmp < 0)
+   tmp = regmap_bulk_read(data->regmap, AMG88XX_REG_TTHL, , 2);
+   if (tmp)
return tmp;
 
+   tmp = le16_to_cpu(buf);
+
/*
 * Check for sign bit, this isn't a two's complement value but an
 * absolute temperature that needs to be inverted in the case of being
@@ -164,8 +166,9 @@ static const struct hwmon_chip_info amg88xx_chip_info = {
 
 static int amg88xx_hwmon_init(struct video_i2c_data *data)
 {
-   void *hwmon = devm_hwmon_device_register_with_info(>client->dev,
-   "amg88xx", data, _chip_info, NULL);
+   struct device *dev = regmap_get_device(data->regmap);
+   void *hwmon = devm_hwmon_device_register_with_info(dev, "amg88xx", data,
+   _chip_info, NULL);
 
return PTR_ERR_OR_ZERO(hwmon);
 }
@@ -182,6 +185,7 @@ static const struct video_i2c_chip video_i2c_chip[] = {
.max_fps= 10,
.buffer_size= 128,
.bpp= 16,
+   .regmap_config  = _regmap_config,
.xfer   = _xfer,
.hwmon_init = amg88xx_hwmon_init,
},
@@ -350,7 +354,8 @@ static int video_i2c_querycap(struct file *file, void  
*priv,
struct v4l2_capability *vcap)
 {
struct video_i2c_data *data = video_drvdata(file);
-   struct i2c_client *client = data->client;
+   struct device *dev = regmap_get_device(data->regmap);
+   struct i2c_client *client = to_i2c_client(dev);
 
strlcpy(vcap->driver, data->v4l2_dev.name, sizeof(vcap->driver));
strlcpy(vcap->card, data->vdev.name, sizeof(vcap->card));
@@ -527,7 +532,10 @@ static int video_i2c_probe(struct i2c_client *client,
else
return -ENODEV;
 
-   data->client = client;
+   data->regmap = devm_regmap_init_i2c(client, data->chip->regmap_config);
+   if (IS_ERR(data->regmap))
+   return 

Re: [PATCH v2] libv4l: Add support for BAYER10P format conversion

2018-09-23 Thread Hans de Goede

Hi,

On 21-09-18 11:04, Ricardo Ribalda Delgado wrote:

Add support for 10 bit packet Bayer formats:
-V4L2_PIX_FMT_SBGGR10P
-V4L2_PIX_FMT_SGBRG10P
-V4L2_PIX_FMT_SGRBG10P
-V4L2_PIX_FMT_SRGGB10P

These formats pack the 2 LSBs for every 4 pixels in an indeppendent
byte.

Signed-off-by: Ricardo Ribalda Delgado 


Patch looks good to me now:

Acked-by: Hans de Goede 

Regards,

Hans




---
  lib/libv4lconvert/bayer.c  | 21 
  lib/libv4lconvert/libv4lconvert-priv.h |  4 +++
  lib/libv4lconvert/libv4lconvert.c  | 35 ++
  3 files changed, 60 insertions(+)

diff --git a/lib/libv4lconvert/bayer.c b/lib/libv4lconvert/bayer.c
index 4b70ddd9..11af6543 100644
--- a/lib/libv4lconvert/bayer.c
+++ b/lib/libv4lconvert/bayer.c
@@ -631,3 +631,24 @@ void v4lconvert_bayer_to_yuv420(const unsigned char 
*bayer, unsigned char *yuv,
v4lconvert_border_bayer_line_to_y(bayer + stride, bayer, ydst, width,
!start_with_green, !blue_line);
  }
+
+void v4lconvert_bayer10p_to_bayer8(unsigned char *bayer10p,
+   unsigned char *bayer8, int width, int height)
+{
+   unsigned long i;
+   unsigned long len = width * height;
+
+   for (i = 0; i < len ; i += 4) {
+   /*
+* Do not use a second loop, hoping that
+* a clever compiler with understand the
+* pattern and will optimize it.
+*/
+   bayer8[0] = bayer10p[0];
+   bayer8[1] = bayer10p[1];
+   bayer8[2] = bayer10p[2];
+   bayer8[3] = bayer10p[3];
+   bayer10p += 5;
+   bayer8 += 4;
+   }
+}
diff --git a/lib/libv4lconvert/libv4lconvert-priv.h 
b/lib/libv4lconvert/libv4lconvert-priv.h
index 9a467e10..3020a39e 100644
--- a/lib/libv4lconvert/libv4lconvert-priv.h
+++ b/lib/libv4lconvert/libv4lconvert-priv.h
@@ -264,6 +264,10 @@ void v4lconvert_bayer_to_bgr24(const unsigned char *bayer,
  void v4lconvert_bayer_to_yuv420(const unsigned char *bayer, unsigned char 
*yuv,
int width, int height, const unsigned int stride, unsigned int 
src_pixfmt, int yvu);
  
+

+void v4lconvert_bayer10p_to_bayer8(unsigned char *bayer10p,
+   unsigned char *bayer8, int width, int height);
+
  void v4lconvert_hm12_to_rgb24(const unsigned char *src,
unsigned char *dst, int width, int height);
  
diff --git a/lib/libv4lconvert/libv4lconvert.c b/lib/libv4lconvert/libv4lconvert.c

index d666bd97..b3dbf5a0 100644
--- a/lib/libv4lconvert/libv4lconvert.c
+++ b/lib/libv4lconvert/libv4lconvert.c
@@ -133,6 +133,10 @@ static const struct v4lconvert_pixfmt 
supported_src_pixfmts[] = {
{ V4L2_PIX_FMT_SRGGB8,   8,  8,  8, 0 },
{ V4L2_PIX_FMT_STV0680,  8,  8,  8, 1 },
{ V4L2_PIX_FMT_SGRBG10, 16,  8,  8, 1 },
+   { V4L2_PIX_FMT_SBGGR10P,10,  8,  8, 1 },
+   { V4L2_PIX_FMT_SGBRG10P,10,  8,  8, 1 },
+   { V4L2_PIX_FMT_SGRBG10P,10,  8,  8, 1 },
+   { V4L2_PIX_FMT_SRGGB10P,10,  8,  8, 1 },
/* compressed bayer */
{ V4L2_PIX_FMT_SPCA561,  0,  9,  9, 1 },
{ V4L2_PIX_FMT_SN9C10X,  0,  9,  9, 1 },
@@ -687,6 +691,10 @@ static int v4lconvert_processing_needs_double_conversion(
case V4L2_PIX_FMT_SGBRG8:
case V4L2_PIX_FMT_SGRBG8:
case V4L2_PIX_FMT_SRGGB8:
+   case V4L2_PIX_FMT_SBGGR10P:
+   case V4L2_PIX_FMT_SGBRG10P:
+   case V4L2_PIX_FMT_SGRBG10P:
+   case V4L2_PIX_FMT_SRGGB10P:
case V4L2_PIX_FMT_STV0680:
return 0;
}
@@ -979,6 +987,33 @@ static int v4lconvert_convert_pixfmt(struct 
v4lconvert_data *data,
}
  
  		/* Raw bayer formats */

+   case V4L2_PIX_FMT_SBGGR10P:
+   case V4L2_PIX_FMT_SGBRG10P:
+   case V4L2_PIX_FMT_SGRBG10P:
+   case V4L2_PIX_FMT_SRGGB10P:
+   if (src_size < ((width * height * 10)/8)) {
+   V4LCONVERT_ERR("short raw bayer10 data frame\n");
+   errno = EPIPE;
+   result = -1;
+   }
+   switch (src_pix_fmt) {
+   case V4L2_PIX_FMT_SBGGR10P:
+   src_pix_fmt = V4L2_PIX_FMT_SBGGR8;
+   break;
+   case V4L2_PIX_FMT_SGBRG10P:
+   src_pix_fmt = V4L2_PIX_FMT_SGBRG8;
+   break;
+   case V4L2_PIX_FMT_SGRBG10P:
+   src_pix_fmt = V4L2_PIX_FMT_SGRBG8;
+   break;
+   case V4L2_PIX_FMT_SRGGB10P:
+   src_pix_fmt = V4L2_PIX_FMT_SRGGB8;
+   break;
+   }
+   v4lconvert_bayer10p_to_bayer8(src, src, width, height);
+   bytesperline = width;
+
+   /* Fall-through*/