cron job: media_tree daily build: OK
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
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
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
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
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
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
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
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
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
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*/