Re: [PATCH v3 2/2] media: ak7375: Add ak7375 lens voice coil driver

2018-06-04 Thread Bing Bu Cao




On 20180605 08:23, Mani, Rajmohan wrote:

Hi Bingbu,

Please see a couple of comments below.


-Original Message-
From: Cao, Bingbu
Sent: Monday, June 04, 2018 2:00 AM
To: linux-media@vger.kernel.org
Cc: sakari.ai...@linux.intel.com; tf...@google.com; jac...@jmondi.org;
Mani, Rajmohan ; bingbu@linux.intel.com;
Qiu, Tian Shu ; Zheng, Jian Xu

Subject: [PATCH v3 2/2] media: ak7375: Add ak7375 lens voice coil driver

From: Bingbu Cao 

Add a v4l2 sub-device driver for the ak7375 lens voice coil.
This is a voice coil module using the i2c bus to control the focus position.

ak7375 can write multiple bytes of data at a time. If more data is received
instead of the stop condition after receiving one byte of data, the address
inside the chip is automatically incremented and the data is written into the
next address.

The ak7375 can control the position with 12 bits value and consists of two 8 bit
registers show as below:
register 0x00(AK7375_REG_POSITION):
 +---+---+---+---+---+---+---+---+
 |D11|D10|D09|D08|D07|D06|D05|D04|
 +---+---+---+---+---+---+---+---+
register 0x01:
 +---+---+---+---+---+---+---+---+
 |D03|D02|D01|D00|---|---|---|---|
 +---+---+---+---+---+---+---+---+

This driver support :
 - set ak7375 to standby mode once suspend and
   turn it back to active if resume
 - set the position via V4L2_CID_FOCUS_ABSOLUTE ctrl

Signed-off-by: Tianshu Qiu 
Signed-off-by: Bingbu Cao 

---
Changes from v1:
 - correct i2c write
 - add media_entity_pads_init() into probe
 - move the MAINTAINERs change into dt-bindings change
 - correct the compatible string
---
---
  drivers/media/i2c/Kconfig  |  10 ++
  drivers/media/i2c/Makefile |   1 +
  drivers/media/i2c/ak7375.c | 278
+
  3 files changed, 289 insertions(+)
  create mode 100644 drivers/media/i2c/ak7375.c

diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig index
341452fe98df..ff3cb5afb0e1 100644
--- a/drivers/media/i2c/Kconfig
+++ b/drivers/media/i2c/Kconfig
@@ -326,6 +326,16 @@ config VIDEO_AD5820
  This is a driver for the AD5820 camera lens voice coil.
  It is used for example in Nokia N900 (RX-51).

+config VIDEO_AK7375
+   tristate "AK7375 lens voice coil support"
+   depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER
+   depends on VIDEO_V4L2_SUBDEV_API
+   help
+ This is a driver for the AK7375 camera lens voice coil.
+ AK7375 is a 12 bit DAC with 120mA output current sink
+ capability. This is designed for linear control of
+ voice coil motors, controlled via I2C serial interface.
+
  config VIDEO_DW9714
tristate "DW9714 lens voice coil support"
depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER diff --git
a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile index
d679d57cd3b3..05b97e319ea9 100644
--- a/drivers/media/i2c/Makefile
+++ b/drivers/media/i2c/Makefile
@@ -23,6 +23,7 @@ obj-$(CONFIG_VIDEO_SAA7127) += saa7127.o
  obj-$(CONFIG_VIDEO_SAA7185) += saa7185.o
  obj-$(CONFIG_VIDEO_SAA6752HS) += saa6752hs.o
  obj-$(CONFIG_VIDEO_AD5820)  += ad5820.o
+obj-$(CONFIG_VIDEO_AK7375)  += ak7375.o
  obj-$(CONFIG_VIDEO_DW9714)  += dw9714.o
  obj-$(CONFIG_VIDEO_ADV7170) += adv7170.o
  obj-$(CONFIG_VIDEO_ADV7175) += adv7175.o diff --git
a/drivers/media/i2c/ak7375.c b/drivers/media/i2c/ak7375.c new file mode
100644 index ..94bcadae4258
--- /dev/null
+++ b/drivers/media/i2c/ak7375.c
@@ -0,0 +1,278 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Intel Corporation
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define AK7375_MAX_FOCUS_POS   4095
+/*
+ * This sets the minimum granularity for the focus positions.
+ * A value of 1 gives maximum accuracy for a desired focus position  */
+#define AK7375_FOCUS_STEPS 1
+/*
+ * This acts as the minimum granularity of lens movement.
+ * Keep this value power of 2, so the control steps can be
+ * uniformly adjusted for gradual lens movement, with desired
+ * number of control steps.
+ */
+#define AK7375_CTRL_STEPS  64
+#define AK7375_CTRL_DELAY_US   1000
+
+#define AK7375_REG_POSITION0x0
+#define AK7375_REG_CONT0x2
+#define AK7375_MODE_ACTIVE 0x0
+#define AK7375_MODE_STANDBY0x40
+
+/* ak7375 device structure */
+struct ak7375_device {
+   struct v4l2_ctrl_handler ctrls_vcm;
+   struct v4l2_subdev sd;
+   struct v4l2_ctrl *focus;
+};
+
+static inline struct ak7375_device *to_ak7375_vcm(struct v4l2_ctrl
+*ctrl) {
+   return container_of(ctrl->handler, struct ak7375_device, ctrls_vcm); }
+
+static inline struct ak7375_device *sd_to_ak7375_vcm(struct v4l2_subdev
+*subdev) {
+   return container_of(subdev, struct ak7375_device, sd); }
+
+static int ak7375_i2c_write(struct ak7375_device *ak7375,
+   u8 addr, u16 data, int size)
+{
+   struct i2c_client *client = v4l2_get_subdevdata(&ak7375->sd);
+   

[no subject]

2018-06-04 Thread Mavis Wanczyk



-- 
Good Day,

I, Mavis Wanczyk donates $ 5 Million Dollars from part of my Powerball
Jackpot Lottery of $ 758 Million Dollars, respond with your details
for claims.

I await your earliest response and God Bless you

Good luck.
Mavis Wanczyk


Re: [PATCH v2 01/10] media: imx-csi: Pass sink pad field to ipu_csi_init_interface

2018-06-04 Thread Krzysztof Hałasa
Steve Longerbeam  writes:

> I think you misunderstood me. Of course there is a first and second
> field. By first I am referring to the first field transmitted, which could
> be top or bottom.

Right. I was thinking the fields are even and odd, but that's not
actually the case (I mean, the numbering uses field 1 and 2 and not
E/O).

> Progressive sensors have no fields, the entire image is captured at
> once as you said.

There are progressive cameras with analog PAL/NTSC output. The signal
is obviously interlaced and consists of fields.
-- 
Krzysztof Halasa

Industrial Research Institute for Automation and Measurements PIAP
Al. Jerozolimskie 202, 02-486 Warsaw, Poland


cron job: media_tree daily build: OK

2018-06-04 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:   Tue Jun  5 05:00:18 CEST 2018
media-tree git hash:a00031c159748f322f771f3c1d5ed944cba4bd30
media_build git hash:   464ef972618cc9f845f07c1a4e8957ce2270cf91
v4l-utils git hash: 88f31856e566df6e4d38eaff94c422fbb536febb
gcc version:i686-linux-gcc (GCC) 8.1.0
sparse version: 0.5.2
smatch version: 0.5.1
host hardware:  x86_64
host os:4.16.0-1-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-2.6.36.4-i686: OK
linux-2.6.36.4-x86_64: OK
linux-2.6.37.6-i686: OK
linux-2.6.37.6-x86_64: OK
linux-2.6.38.8-i686: OK
linux-2.6.38.8-x86_64: OK
linux-2.6.39.4-i686: OK
linux-2.6.39.4-x86_64: OK
linux-3.0.101-i686: OK
linux-3.0.101-x86_64: OK
linux-3.1.10-i686: OK
linux-3.1.10-x86_64: OK
linux-3.2.101-i686: OK
linux-3.2.101-x86_64: OK
linux-3.3.8-i686: OK
linux-3.3.8-x86_64: OK
linux-3.4.113-i686: OK
linux-3.4.113-x86_64: OK
linux-3.5.7-i686: OK
linux-3.5.7-x86_64: OK
linux-3.6.11-i686: OK
linux-3.6.11-x86_64: OK
linux-3.7.10-i686: OK
linux-3.7.10-x86_64: OK
linux-3.8.13-i686: OK
linux-3.8.13-x86_64: OK
linux-3.9.11-i686: OK
linux-3.9.11-x86_64: 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.56-i686: OK
linux-3.16.56-x86_64: OK
linux-3.17.8-i686: OK
linux-3.17.8-x86_64: OK
linux-3.18.102-i686: OK
linux-3.18.102-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.51-i686: OK
linux-4.1.51-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.109-i686: OK
linux-4.4.109-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.91-i686: OK
linux-4.9.91-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.42-i686: OK
linux-4.14.42-x86_64: OK
linux-4.15.14-i686: OK
linux-4.15.14-x86_64: OK
linux-4.16.8-i686: OK
linux-4.16.8-x86_64: OK
linux-4.17-i686: OK
linux-4.17-x86_64: OK
apps: OK
spec-git: OK
sparse: WARNINGS

Detailed results are available here:

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

Full logs are available here:

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

The Media Infrastructure API from this daily build is here:

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


Re: [PATCH v2 04/10] media: imx: interweave only for sequential input/interlaced output fields

2018-06-04 Thread Steve Longerbeam




On 06/04/2018 01:27 AM, Philipp Zabel wrote:

On Mon, 2018-06-04 at 07:35 +0200, Krzysztof Hałasa wrote:

Philipp Zabel  writes:


This is ok in this patch, but we can't use this check in the following
TRY_FMT patch as there is no way to interweave
SEQ_TB -> INTERLACED_BT (because in SEQ_TB the B field is newer than T,
but in INTERLACED_BT it has to be older) or SEQ_BT -> INTERLACED_TB (the
other way around).

Actually we can do SEQ_TB -> INTERLACED_BT and SEQ_BT -> INTERLACED_TB
rather easily. We only need to skip a single field at start :-)
That's what CCIR_CODE_* registers do.

To be honest, SEQ_TB and SEQ_BT are precisely the same thing
(i.e., SEQUENTIAL). It's up to the user to say which field is the first.
There is the progressive sensor exception, though, and the TB/BT could
be a hint for downstream elements (i.e., setting the default field
order).

But I think we should be able to request INTERLACED_TB or INTERLACED_BT
(with any analog signal on input) and the CCIR_CODE registers should be
set accordingly. This should all magically work fine.

The CSI subdevice itself can't interweave at all, this is done in the
IDMAC.
In my opinion the CSI subdev should allow the following src -> sink
field transformations for BT.656:

none -> none
seq-tb -> seq-tb
seq-tb -> seq-bt
seq-bt -> seq-bt
seq-bt -> seq-tb
alternate -> seq-tb
alternate -> seq-bt
interlaced -> interlaced
interlaced-tb -> interlaced-tb
interlaced-bt -> interlaced-bt

The capture video device should then additionally allow selecting
the field order that can be produced by IDMAC interweaving:
INTERLACED_TB if the pad is seq-tb and INTERLACED_BT if the pad is seq-
bt, as that is what the IDMAC can convert.


Good idea. This is also in-line with how planar YUV is selected
at the capture interface instead of at the CSI/PRPENCVF source
pad.

Philipp, Krzysztof, please see branch fix-csi-interlaced.3 in my github
mediatree fork. I've implemented the above and it works great for
both NTSC and PAL sources to the ADV7180.



seq-tb -> seq-tb and seq-bt -> seq-bt should always capture field 0
first, as we currently do for PAL.
seq->tb -> seq-bt and seq-bt -> seq-tb should always capture field 1
first, as we currently do for NTSC.
alternate -> seq-tb and alternate -> seq-bt should match seq-tb -> * for
PAL and seq-bt -> * for NTSC.


Yes, I had already implemented this idea yesterday, I've added it
to branch fix-csi-interlaced.3. The CSI will swap field capture
(field 1 first, then field 2, by inverting F bit in CCIR registers) if
the field order input to the CSI is different from the requested
output field order.

Philipp, a word about the idea of using negative ILO line stride and
an extra line added to EBA start address, for interweaving. I believe
the result of this is to also invert field order when interweaving
'seq-bt/tb', which would produce 'interlaced-tb/bt' in memory.

I don't think this is necessary now, because field order swapping
can already be done earlier at the CSI sink->src using the CCIR registers.
For example here is a pipeline for an NTSC adv7180 source that swapped
NTSC 'seq-bt' (well assumed NTSC 'seq-bt' since adv7180 is 'alternate') to
'seq-tb' at the CSI source pad:

'adv7180 3-0021':0
        [fmt:UYVY8_2X8/720x480 field:alternate colorspace:smpte170m]
'ipu1_csi0_mux':1
        [fmt:UYVY8_2X8/720x480 field:alternate colorspace:smpte170m]
'ipu1_csi0_mux':2
        [fmt:UYVY8_2X8/720x480 field:alternate colorspace:smpte170m]
'ipu1_csi0':0
        [fmt:UYVY8_2X8/720x480@1/30 field:alternate ...]
         crop.bounds:(0,0)/720x480
         crop:(0,2)/720x480
         compose.bounds:(0,0)/720x480
         compose:(0,0)/720x480]
'ipu1_csi0':2
        [fmt:AYUV8_1X32/720x480@1/30 field:seq-tb ...]

And at the capture interface:

# v4l2-ctl -d4 -V
Format Video Capture:
    Width/Height  : 720/480
    Pixel Format  : 'YV12'
    Field : Interlaced Top-Bottom
    Bytes per Line    : 1440
    Size Image    : 691200
    Colorspace    : SMPTE 170M
    Transfer Function : Rec. 709
    YCbCr/HSV Encoding: ITU-R 601
    Quantization  : Limited Range
    Flags :

So we've accomplished 'seq-bt' -> 'interlaced-tb' without needing
to swap field order using the modified interweave idea.

I've run tests for both PAL and NTSC inputs to the adv7180 on SabreAuto,
and the results are consistent:

NTSC seq-bt -> interlaced-tb produces good interweave images as expected
NTSC seq-bt -> interlaced-bt produces interweave images with a "mauve" 
artifact as expected

PAL seq-tb -> interlaced-tb produces good interweave images as expected
PAL seq-tb -> interlaced-bt produces interweave images with a "mauve" 
artifact as expected


Steve



RE: [PATCH v3 2/2] media: ak7375: Add ak7375 lens voice coil driver

2018-06-04 Thread Mani, Rajmohan
Hi Bingbu,

Please see a couple of comments below.

> -Original Message-
> From: Cao, Bingbu
> Sent: Monday, June 04, 2018 2:00 AM
> To: linux-media@vger.kernel.org
> Cc: sakari.ai...@linux.intel.com; tf...@google.com; jac...@jmondi.org;
> Mani, Rajmohan ; bingbu@linux.intel.com;
> Qiu, Tian Shu ; Zheng, Jian Xu
> 
> Subject: [PATCH v3 2/2] media: ak7375: Add ak7375 lens voice coil driver
> 
> From: Bingbu Cao 
> 
> Add a v4l2 sub-device driver for the ak7375 lens voice coil.
> This is a voice coil module using the i2c bus to control the focus position.
> 
> ak7375 can write multiple bytes of data at a time. If more data is received
> instead of the stop condition after receiving one byte of data, the address
> inside the chip is automatically incremented and the data is written into the
> next address.
> 
> The ak7375 can control the position with 12 bits value and consists of two 8 
> bit
> registers show as below:
> register 0x00(AK7375_REG_POSITION):
> +---+---+---+---+---+---+---+---+
> |D11|D10|D09|D08|D07|D06|D05|D04|
> +---+---+---+---+---+---+---+---+
> register 0x01:
> +---+---+---+---+---+---+---+---+
> |D03|D02|D01|D00|---|---|---|---|
> +---+---+---+---+---+---+---+---+
> 
> This driver support :
> - set ak7375 to standby mode once suspend and
>   turn it back to active if resume
> - set the position via V4L2_CID_FOCUS_ABSOLUTE ctrl
> 
> Signed-off-by: Tianshu Qiu 
> Signed-off-by: Bingbu Cao 
> 
> ---
> Changes from v1:
> - correct i2c write
> - add media_entity_pads_init() into probe
> - move the MAINTAINERs change into dt-bindings change
> - correct the compatible string
> ---
> ---
>  drivers/media/i2c/Kconfig  |  10 ++
>  drivers/media/i2c/Makefile |   1 +
>  drivers/media/i2c/ak7375.c | 278
> +
>  3 files changed, 289 insertions(+)
>  create mode 100644 drivers/media/i2c/ak7375.c
> 
> diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig index
> 341452fe98df..ff3cb5afb0e1 100644
> --- a/drivers/media/i2c/Kconfig
> +++ b/drivers/media/i2c/Kconfig
> @@ -326,6 +326,16 @@ config VIDEO_AD5820
> This is a driver for the AD5820 camera lens voice coil.
> It is used for example in Nokia N900 (RX-51).
> 
> +config VIDEO_AK7375
> + tristate "AK7375 lens voice coil support"
> + depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER
> + depends on VIDEO_V4L2_SUBDEV_API
> + help
> +   This is a driver for the AK7375 camera lens voice coil.
> +   AK7375 is a 12 bit DAC with 120mA output current sink
> +   capability. This is designed for linear control of
> +   voice coil motors, controlled via I2C serial interface.
> +
>  config VIDEO_DW9714
>   tristate "DW9714 lens voice coil support"
>   depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER diff --git
> a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile index
> d679d57cd3b3..05b97e319ea9 100644
> --- a/drivers/media/i2c/Makefile
> +++ b/drivers/media/i2c/Makefile
> @@ -23,6 +23,7 @@ obj-$(CONFIG_VIDEO_SAA7127) += saa7127.o
>  obj-$(CONFIG_VIDEO_SAA7185) += saa7185.o
>  obj-$(CONFIG_VIDEO_SAA6752HS) += saa6752hs.o
>  obj-$(CONFIG_VIDEO_AD5820)  += ad5820.o
> +obj-$(CONFIG_VIDEO_AK7375)  += ak7375.o
>  obj-$(CONFIG_VIDEO_DW9714)  += dw9714.o
>  obj-$(CONFIG_VIDEO_ADV7170) += adv7170.o
>  obj-$(CONFIG_VIDEO_ADV7175) += adv7175.o diff --git
> a/drivers/media/i2c/ak7375.c b/drivers/media/i2c/ak7375.c new file mode
> 100644 index ..94bcadae4258
> --- /dev/null
> +++ b/drivers/media/i2c/ak7375.c
> @@ -0,0 +1,278 @@
> +// SPDX-License-Identifier: GPL-2.0
> +// Copyright (C) 2018 Intel Corporation
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +#define AK7375_MAX_FOCUS_POS 4095
> +/*
> + * This sets the minimum granularity for the focus positions.
> + * A value of 1 gives maximum accuracy for a desired focus position  */
> +#define AK7375_FOCUS_STEPS   1
> +/*
> + * This acts as the minimum granularity of lens movement.
> + * Keep this value power of 2, so the control steps can be
> + * uniformly adjusted for gradual lens movement, with desired
> + * number of control steps.
> + */
> +#define AK7375_CTRL_STEPS64
> +#define AK7375_CTRL_DELAY_US 1000
> +
> +#define AK7375_REG_POSITION  0x0
> +#define AK7375_REG_CONT  0x2
> +#define AK7375_MODE_ACTIVE   0x0
> +#define AK7375_MODE_STANDBY  0x40
> +
> +/* ak7375 device structure */
> +struct ak7375_device {
> + struct v4l2_ctrl_handler ctrls_vcm;
> + struct v4l2_subdev sd;
> + struct v4l2_ctrl *focus;
> +};
> +
> +static inline struct ak7375_device *to_ak7375_vcm(struct v4l2_ctrl
> +*ctrl) {
> + return container_of(ctrl->handler, struct ak7375_device, ctrls_vcm); }
> +
> +static inline struct ak7375_device *sd_to_ak7375_vcm(struct v4l2_subdev
> +*subdev) {
> + return container_of(subdev, struct ak7375_device, sd); }
> +
> +static int ak7375_i

Re: [PATCHv15 13/35] v4l2-ctrls: add core request support

2018-06-04 Thread Ezequiel Garcia
On 4 June 2018 at 08:46, Hans Verkuil  wrote:
> From: Hans Verkuil 
>
> Integrate the request support. This adds the v4l2_ctrl_request_complete
> and v4l2_ctrl_request_setup functions to complete a request and (as a
> helper function) to apply a request to the hardware.
>
> It takes care of queuing requests and correctly chaining control values
> in the request queue.
>
> Note that when a request is marked completed it will copy control values
> to the internal request state. This can be optimized in the future since
> this is sub-optimal when dealing with large compound and/or array controls.
>
> For the initial 'stateless codec' use-case the current implementation is
> sufficient.
>
> Signed-off-by: Hans Verkuil 
> ---
>  drivers/media/v4l2-core/v4l2-ctrls.c | 331 ++-
>  include/media/v4l2-ctrls.h   |  51 +
>  2 files changed, 376 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c 
> b/drivers/media/v4l2-core/v4l2-ctrls.c
> index da4cc1485dc4..bd4818507486 100644
> --- a/drivers/media/v4l2-core/v4l2-ctrls.c
> +++ b/drivers/media/v4l2-core/v4l2-ctrls.c
> @@ -1647,6 +1647,13 @@ static int new_to_user(struct v4l2_ext_control *c,
> return ptr_to_user(c, ctrl, ctrl->p_new);
>  }
>
> +/* Helper function: copy the request value back to the caller */
> +static int req_to_user(struct v4l2_ext_control *c,
> +  struct v4l2_ctrl_ref *ref)
> +{
> +   return ptr_to_user(c, ref->ctrl, ref->p_req);
> +}
> +
>  /* Helper function: copy the initial control value back to the caller */
>  static int def_to_user(struct v4l2_ext_control *c, struct v4l2_ctrl *ctrl)
>  {
> @@ -1766,6 +1773,26 @@ static void cur_to_new(struct v4l2_ctrl *ctrl)
> ptr_to_ptr(ctrl, ctrl->p_cur, ctrl->p_new);
>  }
>
> +/* Copy the new value to the request value */
> +static void new_to_req(struct v4l2_ctrl_ref *ref)
> +{
> +   if (!ref)
> +   return;
> +   ptr_to_ptr(ref->ctrl, ref->ctrl->p_new, ref->p_req);
> +   ref->req = ref;
> +}
> +
> +/* Copy the request value to the new value */
> +static void req_to_new(struct v4l2_ctrl_ref *ref)
> +{
> +   if (!ref)
> +   return;
> +   if (ref->req)
> +   ptr_to_ptr(ref->ctrl, ref->req->p_req, ref->ctrl->p_new);
> +   else
> +   ptr_to_ptr(ref->ctrl, ref->ctrl->p_cur, ref->ctrl->p_new);
> +}
> +
>  /* Return non-zero if one or more of the controls in the cluster has a new
> value that differs from the current value. */
>  static int cluster_changed(struct v4l2_ctrl *master)
> @@ -1875,6 +1902,9 @@ int v4l2_ctrl_handler_init_class(struct 
> v4l2_ctrl_handler *hdl,
> lockdep_set_class_and_name(hdl->lock, key, name);
> INIT_LIST_HEAD(&hdl->ctrls);
> INIT_LIST_HEAD(&hdl->ctrl_refs);
> +   INIT_LIST_HEAD(&hdl->requests);
> +   INIT_LIST_HEAD(&hdl->requests_queued);
> +   hdl->request_is_queued = false;
> hdl->nr_of_buckets = 1 + nr_of_controls_hint / 8;
> hdl->buckets = kvmalloc_array(hdl->nr_of_buckets,
>   sizeof(hdl->buckets[0]),
> @@ -1895,6 +1925,14 @@ void v4l2_ctrl_handler_free(struct v4l2_ctrl_handler 
> *hdl)
> if (hdl == NULL || hdl->buckets == NULL)
> return;
>
> +   if (!hdl->req_obj.req && !list_empty(&hdl->requests)) {
> +   struct v4l2_ctrl_handler *req, *next_req;
> +
> +   list_for_each_entry_safe(req, next_req, &hdl->requests, 
> requests) {
> +   media_request_object_unbind(&req->req_obj);
> +   media_request_object_put(&req->req_obj);
> +   }
> +   }
> mutex_lock(hdl->lock);
> /* Free all nodes */
> list_for_each_entry_safe(ref, next_ref, &hdl->ctrl_refs, node) {
> @@ -2816,6 +2854,128 @@ int v4l2_querymenu(struct v4l2_ctrl_handler *hdl, 
> struct v4l2_querymenu *qm)
>  }
>  EXPORT_SYMBOL(v4l2_querymenu);
>
> +static int v4l2_ctrl_request_clone(struct v4l2_ctrl_handler *hdl,
> +  const struct v4l2_ctrl_handler *from)
> +{
> +   struct v4l2_ctrl_ref *ref;
> +   int err;
> +
> +   if (WARN_ON(!hdl || hdl == from))
> +   return -EINVAL;
> +
> +   if (hdl->error)
> +   return hdl->error;
> +
> +   WARN_ON(hdl->lock != &hdl->_lock);
> +
> +   mutex_lock(from->lock);
> +   list_for_each_entry(ref, &from->ctrl_refs, node) {
> +   struct v4l2_ctrl *ctrl = ref->ctrl;
> +   struct v4l2_ctrl_ref *new_ref;
> +
> +   /* Skip refs inherited from other devices */
> +   if (ref->from_other_dev)
> +   continue;
> +   /* And buttons */
> +   if (ctrl->type == V4L2_CTRL_TYPE_BUTTON)
> +   continue;
> +   err = handler_new_ref(hdl, ctrl, &new_ref, false, true);
> +   if (err) {
> +  

Re: [PATCHv15 32/35] vim2m: support requests

2018-06-04 Thread Ezequiel Garcia
On 4 June 2018 at 08:46, Hans Verkuil  wrote:
> From: Hans Verkuil 
>
> Add support for requests to vim2m.
>
> Signed-off-by: Hans Verkuil 
> ---
>  drivers/media/platform/vim2m.c | 26 ++
>  1 file changed, 26 insertions(+)
>
> diff --git a/drivers/media/platform/vim2m.c b/drivers/media/platform/vim2m.c
> index 5cb077294734..1efc8033320f 100644
> --- a/drivers/media/platform/vim2m.c
> +++ b/drivers/media/platform/vim2m.c
> @@ -380,8 +380,18 @@ static void device_run(void *priv)
> src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
> dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
>
> +   /* Apply request controls if needed */
> +   if (src_buf->vb2_buf.req_obj.req)

Nit: it seems we don't need this check?

> +   v4l2_ctrl_request_setup(src_buf->vb2_buf.req_obj.req,
> +   &ctx->hdl);
> +
> device_process(ctx, src_buf, dst_buf);
>
> +   /* Complete request controls if needed */
> +   if (src_buf->vb2_buf.req_obj.req)

Ditto.

> +   v4l2_ctrl_request_complete(src_buf->vb2_buf.req_obj.req,
> +   &ctx->hdl);
> +
> /* Run delayed work, which simulates a hardware irq  */
> schedule_delayed_work(&dev->work_run, 
> msecs_to_jiffies(ctx->transtime));
>  }


-- 
Ezequiel García, VanguardiaSur
www.vanguardiasur.com.ar


Re: [PATCHv15 09/35] v4l2-ctrls: v4l2_ctrl_add_handler: add from_other_dev

2018-06-04 Thread Ezequiel Garcia
On 4 June 2018 at 08:46, Hans Verkuil  wrote:
> From: Hans Verkuil 
>
> Add a 'bool from_other_dev' argument: set to true if the two
> handlers refer to different devices (e.g. it is true when
> inheriting controls from a subdev into a main v4l2 bridge
> driver).
>
> This will be used later when implementing support for the
> request API since we need to skip such controls.
>
> TODO: check drivers/staging/media/imx/imx-media-fim.c change.
>
> Signed-off-by: Hans Verkuil 
> Signed-off-by: Alexandre Courbot 
> ---
>  drivers/media/dvb-frontends/rtl2832_sdr.c |  5 +-
>  drivers/media/pci/bt8xx/bttv-driver.c |  2 +-
>  drivers/media/pci/cx23885/cx23885-417.c   |  2 +-
>  drivers/media/pci/cx88/cx88-blackbird.c   |  2 +-
>  drivers/media/pci/cx88/cx88-video.c   |  2 +-
>  drivers/media/pci/saa7134/saa7134-empress.c   |  4 +-
>  drivers/media/pci/saa7134/saa7134-video.c |  2 +-
>  .../media/platform/exynos4-is/fimc-capture.c  |  2 +-
>  drivers/media/platform/rcar-vin/rcar-core.c   |  2 +-
>  drivers/media/platform/rcar_drif.c|  2 +-
>  .../media/platform/soc_camera/soc_camera.c|  3 +-
>  drivers/media/platform/vivid/vivid-ctrls.c| 46 +--
>  drivers/media/usb/cx231xx/cx231xx-417.c   |  2 +-
>  drivers/media/usb/cx231xx/cx231xx-video.c |  4 +-
>  drivers/media/usb/msi2500/msi2500.c   |  2 +-
>  drivers/media/usb/tm6000/tm6000-video.c   |  2 +-
>  drivers/media/v4l2-core/v4l2-ctrls.c  | 11 +++--
>  drivers/media/v4l2-core/v4l2-device.c |  3 +-
>  drivers/staging/media/imx/imx-media-dev.c |  2 +-
>  drivers/staging/media/imx/imx-media-fim.c |  2 +-
>  include/media/v4l2-ctrls.h|  8 +++-
>  21 files changed, 61 insertions(+), 49 deletions(-)
>
> diff --git a/drivers/media/dvb-frontends/rtl2832_sdr.c 
> b/drivers/media/dvb-frontends/rtl2832_sdr.c
> index c6e78d870ccd..6064d28224e8 100644
> --- a/drivers/media/dvb-frontends/rtl2832_sdr.c
> +++ b/drivers/media/dvb-frontends/rtl2832_sdr.c
> @@ -1394,7 +1394,8 @@ static int rtl2832_sdr_probe(struct platform_device 
> *pdev)
> case RTL2832_SDR_TUNER_E4000:
> v4l2_ctrl_handler_init(&dev->hdl, 9);
> if (subdev)
> -   v4l2_ctrl_add_handler(&dev->hdl, 
> subdev->ctrl_handler, NULL);
> +   v4l2_ctrl_add_handler(&dev->hdl, subdev->ctrl_handler,
> + NULL, true);
> break;
> case RTL2832_SDR_TUNER_R820T:
> case RTL2832_SDR_TUNER_R828D:
> @@ -1423,7 +1424,7 @@ static int rtl2832_sdr_probe(struct platform_device 
> *pdev)
> v4l2_ctrl_handler_init(&dev->hdl, 2);
> if (subdev)
> v4l2_ctrl_add_handler(&dev->hdl, subdev->ctrl_handler,
> - NULL);
> + NULL, true);
> break;
> default:
> v4l2_ctrl_handler_init(&dev->hdl, 0);
> diff --git a/drivers/media/pci/bt8xx/bttv-driver.c 
> b/drivers/media/pci/bt8xx/bttv-driver.c
> index de3f44b8dec6..9341ef6e154f 100644
> --- a/drivers/media/pci/bt8xx/bttv-driver.c
> +++ b/drivers/media/pci/bt8xx/bttv-driver.c
> @@ -4211,7 +4211,7 @@ static int bttv_probe(struct pci_dev *dev, const struct 
> pci_device_id *pci_id)
> /* register video4linux + input */
> if (!bttv_tvcards[btv->c.type].no_video) {
> v4l2_ctrl_add_handler(&btv->radio_ctrl_handler, hdl,
> -   v4l2_ctrl_radio_filter);
> +   v4l2_ctrl_radio_filter, false);
> if (btv->radio_ctrl_handler.error) {
> result = btv->radio_ctrl_handler.error;
> goto fail2;
> diff --git a/drivers/media/pci/cx23885/cx23885-417.c 
> b/drivers/media/pci/cx23885/cx23885-417.c
> index a71f3c7569ce..762823871c78 100644
> --- a/drivers/media/pci/cx23885/cx23885-417.c
> +++ b/drivers/media/pci/cx23885/cx23885-417.c
> @@ -1527,7 +1527,7 @@ int cx23885_417_register(struct cx23885_dev *dev)
> dev->cxhdl.priv = dev;
> dev->cxhdl.func = cx23885_api_func;
> cx2341x_handler_set_50hz(&dev->cxhdl, tsport->height == 576);
> -   v4l2_ctrl_add_handler(&dev->ctrl_handler, &dev->cxhdl.hdl, NULL);
> +   v4l2_ctrl_add_handler(&dev->ctrl_handler, &dev->cxhdl.hdl, NULL, 
> false);
>
> /* Allocate and initialize V4L video device */
> dev->v4l_device = cx23885_video_dev_alloc(tsport,
> diff --git a/drivers/media/pci/cx88/cx88-blackbird.c 
> b/drivers/media/pci/cx88/cx88-blackbird.c
> index 7a4876cf9f08..722dd101c9b0 100644
> --- a/drivers/media/pci/cx88/cx88-blackbird.c
> +++ b/drivers/media/pci/cx88/cx88-blackbird.c
> @@ -1183,7 +1183,7 @@ static int cx8802_blackbird_probe(struct cx8802_driver 
> *drv)
> err = cx2341x_handler_init(&dev->cxhdl, 36);
> if (err)
>  

Re: [PATCH v2 01/10] media: imx-csi: Pass sink pad field to ipu_csi_init_interface

2018-06-04 Thread Steve Longerbeam




On 06/03/2018 10:25 PM, Krzysztof Hałasa wrote:

Steve Longerbeam  writes:


I think we should return to enforcing field order to userspace that
matches field order from the source, which is what I had implemented
previously. I agree with you that we should put off allowing inverting
field order.

There is no any particular field order at the source, most of the time.
The odd field is followed by the even field, and so on, sure. But there
is no "first" and "second" field, any field can be the "first".


I think you misunderstood me. Of course there is a first and second
field. By first I am referring to the first field transmitted, which could
be top or bottom.


The exception to this is a camera with a progressive sensor - both
"fields" are taken at the same time and transmitted one after the other,
so in this case the order is defined (by the camera, e.g. B-T on DV even
with PAL version). But this isn't exactly PAL/NTSC.


Progressive sensors have no fields, the entire image is captured at
once as you said.

Steve




Re: [PATCH v3 03/12] media: ov5640: Remove the clocks registers initialization

2018-06-04 Thread Maxime Ripard
Hi Sam,

On Fri, Jun 01, 2018 at 04:05:58PM -0700, Sam Bobrowicz wrote:
> >> On May 21, 2018, at 12:39 AM, Maxime Ripard  
> >> wrote:
> >>
> >>> On Fri, May 18, 2018 at 07:42:34PM -0700, Sam Bobrowicz wrote:
>  On Fri, May 18, 2018 at 3:35 AM, Daniel Mack  wrote:
>  On Thursday, May 17, 2018 10:53 AM, Maxime Ripard wrote:
> 
>  Part of the hardcoded initialization sequence is to set up the proper
>  clock
>  dividers. However, this is now done dynamically through proper code and 
>  as
>  such, the static one is now redundant.
> 
>  Let's remove it.
> 
>  Signed-off-by: Maxime Ripard 
>  ---
> >>>
> >>>
> >>> [...]
> >>>
>  @@ -625,8 +623,8 @@ static const struct reg_value
>  ov5640_setting_30fps_1080P_1920_1080[] = {
>    {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
>    {0x4001, 0x02, 0, 0}, {0x4004, 0x06, 0, 0}, {0x4713, 0x03, 0, 0},
>    {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
>  -   {0x3824, 0x02, 0, 0}, {0x5001, 0x83, 0, 0}, {0x3035, 0x11, 0, 0},
>  -   {0x3036, 0x54, 0, 0}, {0x3c07, 0x07, 0, 0}, {0x3c08, 0x00, 0, 0},
>  +   {0x3824, 0x02, 0, 0}, {0x5001, 0x83, 0, 0},
>  +   {0x3c07, 0x07, 0, 0}, {0x3c08, 0x00, 0, 0},
> >>>
> >>>
> >>> This is the mode that I'm testing with. Previously, the hard-coded 
> >>> registers
> >>> here were:
> >>>
> >>> OV5640_REG_SC_PLL_CTRL1 (0x3035) = 0x11
> >>> OV5640_REG_SC_PLL_CTRL2 (0x3036) = 0x54
> >>> OV5640_REG_SC_PLL_CTRL3 (0x3037) = 0x07
> >>>
> >>> Your new code that calculates the clock rates dynamically ends up with
> >>> different values however:
> >>>
> >>> OV5640_REG_SC_PLL_CTRL1 (0x3035) = 0x11
> >>> OV5640_REG_SC_PLL_CTRL2 (0x3036) = 0xa8
> >>> OV5640_REG_SC_PLL_CTRL3 (0x3037) = 0x03
> >>>
> >>> Interestingly, leaving the hard-coded values in the array *and* letting
> >>> ov5640_set_mipi_pclk() do its thing later still works. So again it seems
> >>> that writes to registers after 0x3035/0x3036/0x3037 seem to depend on the
> >>> values of these timing registers. You might need to leave these values as
> >>> dummies in the array. Confusing.
> >>>
> >>> Any idea?
> >>
> >> This set of patches is also not working for my MIPI platform (mine has
> >> a 12 MHz external clock). I am pretty sure is isn't working because it
> >> does not include the following, which my tests have found to be
> >> necessary:
> >>
> >> 1) Setting pclk period reg in order to correct DPHY timing.
> >> 2) Disabling of MIPI lanes when streaming not enabled.
> >> 3) setting mipi_div to 1 when the scaler is disabled
> >> 4) Doubling ADC clock on faster resolutions.
> >
> > Yeah, I left them out because I didn't think this was relevant to this
> > patchset but should come as future improvements. However, given that
> > it works with the parallel bus, maybe the two first are needed when
> > adjusting the rate.
> >
> I agree that 1-4 are separate improvements to MIPI mode that may not
> affect all modules. They do break mine, but that has been true since
> the driver was released (mainly because of my 12 MHz clock and more
> stringent CSI RX requirements). So it makes sense for me to address
> them in a follow-up series. But I do think that we should get the
> clock generation a little closer to what I know works for MIPI so we
> don't break things for people that do have MIPI working.

I guess it's already a bit too late for that :/

> > The mipi divider however seems to be a bit more complicated than you
> > report here. It is indeed set to 1 when the scaler is enabled (all
> > resolutions > 1280 * 960), but it's also set to 4 in some cases
> > (640x480@30, 320x240@30, 176x144@30). I couldn't really find any
> > relationship between the resolution/framerate and whether to use a
> > divider of 2 or 4.
> 
> I didn't notice the divide by 4, interesting. I have a theory
> though... it could be that the constraint of PCLK relative to SCLK is:
> 
> SCLK*(cpp/scaler ratio)<=PCLK<= ?
> cpp=Components/pixel (1 for JPEG, 2 for YUV, e.g.)
> 
> Since the scaler is in auto mode, the scaler ratio might automatically
> change depending on the resolution selected, something like (using int
> math):
> 
> (hTotal/hActive) * (vTotal/vActive) = scaler ratio
> 
> If SCLK is responsible for reading the data into the scaler, and PCLK
> is responsible for reading data out to the physical interface, this
> would make sense. It will require more experiments to verify any of
> this, though, and unfortunately I don't have a lot of time to put into
> this right now.

To be honest, I really couldn't find any correlation. Some have
different dividers for the two framerates (15 and 30), which wouldn't
make sense in your case, and doubling the resolution doesn't always
result in increasing that divider either.

> On my platform I have also run into an upper bound for PCLK, where it
> seems that PCLK must be <= SCLK when the scaler is enabled. I think
> this may

Re: [PATCHv15 09/35] v4l2-ctrls: v4l2_ctrl_add_handler: add from_other_dev

2018-06-04 Thread Hans Verkuil
Steve or Philipp,

Can one of you verify the imx-media-fim.c patch?

See the description of the change below:

On 06/04/2018 01:46 PM, Hans Verkuil wrote:
> From: Hans Verkuil 
> 
> Add a 'bool from_other_dev' argument: set to true if the two
> handlers refer to different devices (e.g. it is true when
> inheriting controls from a subdev into a main v4l2 bridge
> driver).
> 
> This will be used later when implementing support for the
> request API since we need to skip such controls.
> 
> TODO: check drivers/staging/media/imx/imx-media-fim.c change.

The basic idea is that while controls for a subdev can be
added ('inherited') to a handler for a another parent subdev or
video device, they should be marked as belonging to another device.

This is needed when the Request API is introduced since the request
should not have two copies of the same control (one belonging to the
subdev, one inherited by e.g. a video device).

However, I am not sure if I need to use true or false in the.
imx_media_fim_add_controls() case. Do the controls added here belong
to the same csi subdev or do they belong to another device?

BTW, with 'belongs to' I mean that that's the device driver that
implements the s_ctrl() call, i.e. actually sets up the hardware.

Regards,

Hans

> 
> Signed-off-by: Hans Verkuil 
> Signed-off-by: Alexandre Courbot 
> ---
>  drivers/media/dvb-frontends/rtl2832_sdr.c |  5 +-
>  drivers/media/pci/bt8xx/bttv-driver.c |  2 +-
>  drivers/media/pci/cx23885/cx23885-417.c   |  2 +-
>  drivers/media/pci/cx88/cx88-blackbird.c   |  2 +-
>  drivers/media/pci/cx88/cx88-video.c   |  2 +-
>  drivers/media/pci/saa7134/saa7134-empress.c   |  4 +-
>  drivers/media/pci/saa7134/saa7134-video.c |  2 +-
>  .../media/platform/exynos4-is/fimc-capture.c  |  2 +-
>  drivers/media/platform/rcar-vin/rcar-core.c   |  2 +-
>  drivers/media/platform/rcar_drif.c|  2 +-
>  .../media/platform/soc_camera/soc_camera.c|  3 +-
>  drivers/media/platform/vivid/vivid-ctrls.c| 46 +--
>  drivers/media/usb/cx231xx/cx231xx-417.c   |  2 +-
>  drivers/media/usb/cx231xx/cx231xx-video.c |  4 +-
>  drivers/media/usb/msi2500/msi2500.c   |  2 +-
>  drivers/media/usb/tm6000/tm6000-video.c   |  2 +-
>  drivers/media/v4l2-core/v4l2-ctrls.c  | 11 +++--
>  drivers/media/v4l2-core/v4l2-device.c |  3 +-
>  drivers/staging/media/imx/imx-media-dev.c |  2 +-
>  drivers/staging/media/imx/imx-media-fim.c |  2 +-
>  include/media/v4l2-ctrls.h|  8 +++-
>  21 files changed, 61 insertions(+), 49 deletions(-)
> 



> diff --git a/drivers/staging/media/imx/imx-media-dev.c 
> b/drivers/staging/media/imx/imx-media-dev.c
> index 289d775c4820..08799beaea42 100644
> --- a/drivers/staging/media/imx/imx-media-dev.c
> +++ b/drivers/staging/media/imx/imx-media-dev.c
> @@ -391,7 +391,7 @@ static int imx_media_inherit_controls(struct 
> imx_media_dev *imxmd,
>  
>   ret = v4l2_ctrl_add_handler(vfd->ctrl_handler,
>   sd->ctrl_handler,
> - NULL);
> + NULL, true);
>   if (ret)
>   return ret;
>   }
> diff --git a/drivers/staging/media/imx/imx-media-fim.c 
> b/drivers/staging/media/imx/imx-media-fim.c
> index 6df189135db8..8cf773eef9da 100644
> --- a/drivers/staging/media/imx/imx-media-fim.c
> +++ b/drivers/staging/media/imx/imx-media-fim.c
> @@ -463,7 +463,7 @@ int imx_media_fim_add_controls(struct imx_media_fim *fim)
>  {
>   /* add the FIM controls to the calling subdev ctrl handler */
>   return v4l2_ctrl_add_handler(fim->sd->ctrl_handler,
> -  &fim->ctrl_handler, NULL);
> +  &fim->ctrl_handler, NULL, false);
>  }
>  EXPORT_SYMBOL_GPL(imx_media_fim_add_controls);
>  


Re: [PATCH 0/2] rockchip/rga: A fix and a cleanup

2018-06-04 Thread Ezequiel Garcia
Ccing Jacob at the right address.

Perhaps we should fix the MAINTAINERS file.

On Fri, 2018-06-01 at 16:49 -0300, Ezequiel Garcia wrote:
> Decided to test v4l2transform filters and found these two
> issues.
> 
> Without the first commit, start_streaming fails. The second
> commit is just a cleanup, removing a seemingly redundant
> operation.
> 
> Tested on RK3288 Radxa Rock2 with these kind of pipelines:
> 
> gst-launch-1.0 videotestsrc ! video/x-
> raw,width=640,height=480,framerate=30/1,format=RGB !
> v4l2video0convert ! video/x-
> raw,width=1920,height=1080,framerate=30/1,format=NV16 ! fakesink
> 
> gst-launch-1.0 v4l2src device=/dev/video1 ! video/x-
> raw,width=640,height=480,framerate=30/1,format=RGB !
> v4l2video0convert ! video/x-
> raw,width=1920,height=1080,framerate=30/1,format=NV16 ! kmssink
> 
> Ezequiel Garcia (2):
>   rockchip/rga: Fix broken .start_streaming
>   rockchip/rga: Remove unrequired wait in .job_abort
> 
>  drivers/media/platform/rockchip/rga/rga-buf.c | 44 +--
> 
>  drivers/media/platform/rockchip/rga/rga.c | 13 +-
>  drivers/media/platform/rockchip/rga/rga.h |  2 -
>  3 files changed, 23 insertions(+), 36 deletions(-)
> 


Re: [ANN] Prague Media summit report October 2017

2018-06-04 Thread Mauro Carvalho Chehab
Em Tue, 16 Jan 2018 11:11:54 +0200
Sakari Ailus  escreveu:

> Hello everyone,
> 
> Here's the Prague Media summit report from 26th and 27th October 2017. It
> took long but finally it's here!

It took an even longer time, but I finally added it to our "news" and
added the group photo:
https://linuxtv.org/news.php?entry=2018-06-04-2.mchehab

I also added the announcement with the proposed agenda at:
https://linuxtv.org/news.php?entry=2018-06-04-1.mchehab

Thanks,
Mauro


[ANN v2] Complex Camera Workshop - Tokyo - Jun, 19

2018-06-04 Thread Mauro Carvalho Chehab
Hi all,

I consolidated hopefully all comments I receive on the past announcement
with regards to the complex camera workshop we're planning to happen in
Tokyo, just before the Open Source Summit in Japan.

The main focus of the workshop is to allow supporting devices with MC-based
hardware connected to a camera.

I'm enclosing a detailed description of the problem, in order to
allow the interested parties to be at the same page.

We need to work towards an agenda for the meeting.

From my side, I think we should have at least the following topics at
the agenda:

- a quick review about what's currently at libv4l2;
- a presentation about PipeWire solution;
- a discussion with the requirements for the new solution;
- a discussion about how we'll address - who will do what.

Comments? Suggestions?

Are there anyone else planning to either be there physically or via
Google Hangouts?

Tomaz,

Do you have any limit about the number of people that could join us
via Google Hangouts?


Regards,
Mauro

---

1. Introduction
===

1.1 V4L2 Kernel aspects
---

The media subsystem supports two types of devices:

- "traditional" media hardware, supported via V4L2 API. On such hardware, 
  opening a single device node (usually /dev/video0) is enough to control
  the entire device. We call it as devnode-based devices.
  An application sometimes may need to use multiple video nodes with 
  devnode-based drivers to capture multiple streams in parallel
  (when the hardware allows it of course). That's quite common for
  Analog TV devices, where both /dev/video0 and /dev/vbi0 are opened
  at the same time.

- Media-controller based devices. On those devices, there are typically
  several /dev/video? nodes and several /dev/v4l2-subdev? nodes, plus
  a media controller device node (usually /dev/media0).
  We call it as mc-based devices. Controlling the hardware require
  opening the media device (/dev/media0), setup the pipeline and adjust
  the sub-devices via /dev/v4l2-subdev?. Only streaming is controlled
  by /dev/video?.

In other words, both configuration and streaming go through the video
device node on devnode-based drivers, while video device nodes are used
used for streaming on mc-based drivers.

With devnode-based drivers, "standard" media applications, including open 
source ones (Camorama, Cheese, Xawtv, Firefox, Chromium, ...) and closed
source ones (Skype, Chrome, ...) support devnode-based devices[1]. Also,
when just one media device is connected, the streaming/control device
is typically /dev/video0.

[1] It should be noticed that closed-source applications tend to have 
various bugs that prevent them from working properly on many devnode-based
devices. Due to that, some additional blocks were requred at libv4l to
support some of them. Skype is a good example, as we had to include a
software scaler in libv4l to make it happy. So in practice not everything
works smoothly with closed-source applications with devnode-based drivers.
A few such adjustments were also made on some drivers and/or libv4l, in
order to fulfill some open-source app requirements.

Support for mc-based devices currently require an specialized application 
in order to prepare the device for its usage (setup pipelines, adjust
hardware controls, etc). Once pipeline is set, the streaming goes via
/dev/video?, although usually some /dev/v4l2-subdev? devnodes should also
be opened, in order to implement algorithms designed to make video quality
reasonable. On such devices, it is not uncommon that the device used by the
application to be a random number (on OMAP3 driver, typically, is either
/dev/video4 or /dev/video6).

One example of such hardware is at the OMAP3-based hardware:


http://www.infradead.org/~mchehab/mc-next-gen/omap3-igepv2-with-tvp5150.png

On the picture, there's a graph with the hardware blocks in blue/dark/blue
and the corresponding devnode interfaces in yellow.

The mc-based approach was taken when support for Nokia N9/N900 cameras 
was added (with has OMAP3 SoC). It is required because the camera hardware
on SoC comes with a media processor (ISP), with does a lot more than just
capturing, allowing complex algorithms to enhance image quality in runtime.
Those algorithms are known as 3A - an acronym for 3 other acronyms:

- AE (Auto Exposure);
- AF (Auto Focus);
- AWB (Auto White Balance).

The main reason that drove the MC design is that the 3A algorithms (that is 
the 3A control loop, and sometimes part of the image processing itself) often 
need to run, at least partially, on the CPU. As a kernel-space implementation
wasn't possible, we needed a lower-level UAPI.

Setting a camera with such ISPs are harder because the pipelines to be
set actually depends the requirements for those 3A algorithms to run.
Also, usually, the 3A algorithms use some chipset-specific userspace API,
that exports some image properties, calculated by the ISP, to speed up
the convergence of 

[GIT PULL FOR v4.18] Various regression fixes

2018-06-04 Thread Hans Verkuil
Various fixes, esp the v4l2-ioctl.c fix is critical.

All for 4.18.

Regards,

Hans

The following changes since commit a00031c159748f322f771f3c1d5ed944cba4bd30:

  media: ddbridge: conditionally enable fast TS for stv0910-equipped bridges 
(2018-05-28 17:47:05 -0400)

are available in the Git repository at:

  git://linuxtv.org/hverkuil/media_tree.git for-v4.18g

for you to fetch changes up to c735674fbb38fafafd8463202fd1b27f4cff3089:

  media/radio/Kconfig: add back RADIO_ISA (2018-06-04 14:52:34 +0200)


Akinobu Mita (1):
  media: pxa_camera: ignore -ENOIOCTLCMD from v4l2_subdev_call for s_power

Arnd Bergmann (3):
  media: marvel-ccic: allow ccic and mmp drivers to coexist
  media: omap2: fix compile-testing with FB_OMAP2=m
  media: marvel-ccic: mmp: select VIDEOBUF2_VMALLOC/DMA_CONTIG

Dmitry Osipenko (1):
  media: staging: tegra-vde: Reset VDE regardless of memory client 
resetting failure

Hans Verkuil (2):
  v4l2-ioctl.c: fix missing unlock in __video_do_ioctl()
  media/radio/Kconfig: add back RADIO_ISA

Jacopo Mondi (1):
  media: arch: sh: migor: Fix TW9910 PDN gpio

 arch/sh/boards/mach-migor/setup.c   |  2 +-
 drivers/media/platform/marvell-ccic/Kconfig |  2 ++
 drivers/media/platform/marvell-ccic/Makefile|  9 -
 drivers/media/platform/marvell-ccic/mcam-core.c |  9 -
 drivers/media/platform/omap/Kconfig |  2 +-
 drivers/media/platform/pxa_camera.c | 35 
+++
 drivers/media/radio/Kconfig |  1 +
 drivers/media/v4l2-core/v4l2-ioctl.c|  2 +-
 drivers/staging/media/tegra-vde/tegra-vde.c | 13 +
 9 files changed, 46 insertions(+), 29 deletions(-)


Re: qcom: add firmware file for Venus on SDM845

2018-06-04 Thread Josh Boyer
On Sat, May 26, 2018 at 4:18 AM Vikash Garodia  wrote:
>
> Hi Josh,
>
> On 2018-05-25 17:34, Josh Boyer wrote:
> > On Fri, May 25, 2018 at 7:03 AM Vikash Garodia
> > 
> > wrote:
> >
> >> This pull request adds firmware files for Venus h/w codec found on the
> > Qualcomm SDM845 chipset.
> >
> >> The following changes since commit
> > 2a9b2cf50fb32e36e4fc1586c2f6f1421913b553:
> >
> >>Merge branch 'for-upstreaming-v1.7.2' of
> > https://github.com/felix-cavium/linux-firmware (2018-05-18 08:35:22
> > -0400)
> >
> >> are available in the git repository at:
> >
> >
> >>https://github.com/vgarodia/linux-firmware master
> >
> >> for you to fetch changes up to
> >> d6088b9c9d7f49d3c6c43681190889eca0abdcce:
> >
> >>qcom: add venus firmware files for v5.2 (2018-05-25 15:16:43 +0530)
> >
> >> 
> >> Vikash Garodia (1):
> >>qcom: add venus firmware files for v5.2
> >
> >>   WHENCE   |   9 +
> >>   qcom/venus-5.2/venus.b00 | Bin 0 -> 212 bytes
> >>   qcom/venus-5.2/venus.b01 | Bin 0 -> 6600 bytes
> >>   qcom/venus-5.2/venus.b02 | Bin 0 -> 819552 bytes
> >>   qcom/venus-5.2/venus.b03 | Bin 0 -> 33536 bytes
> >>   qcom/venus-5.2/venus.b04 |   1 +
> >>   qcom/venus-5.2/venus.mbn | Bin 0 -> 865408 bytes
> >>   qcom/venus-5.2/venus.mdt | Bin 0 -> 6812 bytes
> >>   8 files changed, 10 insertions(+)
> >>   create mode 100644 qcom/venus-5.2/venus.b00
> >>   create mode 100644 qcom/venus-5.2/venus.b01
> >>   create mode 100644 qcom/venus-5.2/venus.b02
> >>   create mode 100644 qcom/venus-5.2/venus.b03
> >>   create mode 100644 qcom/venus-5.2/venus.b04
> >>   create mode 100644 qcom/venus-5.2/venus.mbn
> >>   create mode 100644 qcom/venus-5.2/venus.mdt
> >
> > The venus.mbn file isn't mentioned in WHENCE:
> >
> > [jwboyer@vader linux-firmware]$ ./check_whence.py
> > E: qcom/venus-5.2/venus.mbn not listed in WHENCE
> > [jwboyer@vader linux-firmware]$
> >
> > Can you fix that up and let me know when to re-pull?
> I have fixed the error and is ready to be re-pulled from the same git
> repository.
> I have noted the process to run check_whence.py before uploading the
> firmwares.
>
> Do i need to resend the pull request as the end commit is now changed to
> 7602644358157e4b89960472b6d59ffcc040ca52 ?

Nope.  Pulled and pushed out now.  Thanks.

josh


[PATCH for v4.18] media/radio/Kconfig: add back RADIO_ISA

2018-06-04 Thread Hans Verkuil
Patch 258c524bdaab inadvertently removed the 'select RADIO_ISA' line for
the RADIO_RTRACK.

Fixes: 258c524bdaab ("radio: allow building ISA drivers with COMPILE_TEST")
Reported-by: Randy Dunlap 
Signed-off-by: Hans Verkuil 
---
diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig
index 8fa403c7149e..39b04ad924c0 100644
--- a/drivers/media/radio/Kconfig
+++ b/drivers/media/radio/Kconfig
@@ -257,6 +257,7 @@ config RADIO_RTRACK
tristate "AIMSlab RadioTrack (aka RadioReveal) support"
depends on ISA || COMPILE_TEST
depends on VIDEO_V4L2
+   select RADIO_ISA
---help---
  Choose Y here if you have one of these FM radio cards, and then fill
  in the port address below.


[PATCHv15 07/35] v4l2-dev: lock req_queue_mutex

2018-06-04 Thread Hans Verkuil
From: Hans Verkuil 

We need to serialize streamon/off with queueing new requests.
These ioctls may trigger the cancellation of a streaming
operation, and that should not be mixed with queuing a new
request at the same time.

Finally close() needs this lock since that too can trigger the
cancellation of a streaming operation.

We take the req_queue_mutex here before any other locks since
it is a very high-level lock.

Signed-off-by: Hans Verkuil 
Signed-off-by: Sakari Ailus 
---
 drivers/media/v4l2-core/v4l2-dev.c   | 13 +
 drivers/media/v4l2-core/v4l2-ioctl.c | 22 +-
 2 files changed, 34 insertions(+), 1 deletion(-)

diff --git a/drivers/media/v4l2-core/v4l2-dev.c 
b/drivers/media/v4l2-core/v4l2-dev.c
index 4ffd7d60a901..d23e82ab1e27 100644
--- a/drivers/media/v4l2-core/v4l2-dev.c
+++ b/drivers/media/v4l2-core/v4l2-dev.c
@@ -444,8 +444,21 @@ static int v4l2_release(struct inode *inode, struct file 
*filp)
struct video_device *vdev = video_devdata(filp);
int ret = 0;
 
+   /*
+* We need to serialize the release() with queueing new requests.
+* The release() may trigger the cancellation of a streaming
+* operation, and that should not be mixed with queueing a new
+* request at the same time.
+*/
+   if (v4l2_device_supports_requests(vdev->v4l2_dev))
+   mutex_lock(&vdev->v4l2_dev->mdev->req_queue_mutex);
+
if (vdev->fops->release)
ret = vdev->fops->release(filp);
+
+   if (v4l2_device_supports_requests(vdev->v4l2_dev))
+   mutex_unlock(&vdev->v4l2_dev->mdev->req_queue_mutex);
+
if (vdev->dev_debug & V4L2_DEV_DEBUG_FOP)
dprintk("%s: release\n",
video_device_node_name(vdev));
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c 
b/drivers/media/v4l2-core/v4l2-ioctl.c
index 965fd301f617..27a893aa0664 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -2714,6 +2714,7 @@ static long __video_do_ioctl(struct file *file,
unsigned int cmd, void *arg)
 {
struct video_device *vfd = video_devdata(file);
+   struct mutex *req_queue_lock = NULL;
struct mutex *lock; /* ioctl serialization mutex */
const struct v4l2_ioctl_ops *ops = vfd->ioctl_ops;
bool write_only = false;
@@ -2733,10 +2734,27 @@ static long __video_do_ioctl(struct file *file,
if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags))
vfh = file->private_data;
 
+   /*
+* We need to serialize streamon/off with queueing new requests.
+* These ioctls may trigger the cancellation of a streaming
+* operation, and that should not be mixed with queueing a new
+* request at the same time.
+*/
+   if (v4l2_device_supports_requests(vfd->v4l2_dev) &&
+   (cmd == VIDIOC_STREAMON || cmd == VIDIOC_STREAMOFF)) {
+   req_queue_lock = &vfd->v4l2_dev->mdev->req_queue_mutex;
+
+   if (req_queue_lock && mutex_lock_interruptible(req_queue_lock))
+   return -ERESTARTSYS;
+   }
+
lock = v4l2_ioctl_get_lock(vfd, cmd);
 
-   if (lock && mutex_lock_interruptible(lock))
+   if (lock && mutex_lock_interruptible(lock)) {
+   if (req_queue_lock)
+   mutex_unlock(req_queue_lock);
return -ERESTARTSYS;
+   }
 
if (!video_is_registered(vfd)) {
ret = -ENODEV;
@@ -2795,6 +2813,8 @@ static long __video_do_ioctl(struct file *file,
 unlock:
if (lock)
mutex_unlock(lock);
+   if (req_queue_lock)
+   mutex_unlock(req_queue_lock);
return ret;
 }
 
-- 
2.17.0



[PATCHv15 03/35] media: doc: Add media-request.h header to documentation build

2018-06-04 Thread Hans Verkuil
From: Sakari Ailus 

media-request.h has been recently added; add it to the documentation build
as well.

Signed-off-by: Sakari Ailus 
Signed-off-by: Hans Verkuil 
---
 Documentation/media/kapi/mc-core.rst | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/media/kapi/mc-core.rst 
b/Documentation/media/kapi/mc-core.rst
index 0c05503eaf1f..69362b3135c2 100644
--- a/Documentation/media/kapi/mc-core.rst
+++ b/Documentation/media/kapi/mc-core.rst
@@ -262,3 +262,5 @@ in the end provide a way to use driver-specific callbacks.
 .. kernel-doc:: include/media/media-devnode.h
 
 .. kernel-doc:: include/media/media-entity.h
+
+.. kernel-doc:: include/media/media-request.h
-- 
2.17.0



[PATCHv15 06/35] v4l2-device.h: add v4l2_device_supports_requests() helper

2018-06-04 Thread Hans Verkuil
From: Hans Verkuil 

Add a simple helper function that tests if the driver supports
the request API.

Signed-off-by: Hans Verkuil 
---
 include/media/v4l2-device.h | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/include/media/v4l2-device.h b/include/media/v4l2-device.h
index b330e4a08a6b..ac7677a183ff 100644
--- a/include/media/v4l2-device.h
+++ b/include/media/v4l2-device.h
@@ -211,6 +211,17 @@ static inline void v4l2_subdev_notify(struct v4l2_subdev 
*sd,
sd->v4l2_dev->notify(sd, notification, arg);
 }
 
+/**
+ * v4l2_device_supports_requests - Test if requests are supported.
+ *
+ * @v4l2_dev: pointer to struct v4l2_device
+ */
+static inline bool v4l2_device_supports_requests(struct v4l2_device *v4l2_dev)
+{
+   return v4l2_dev->mdev && v4l2_dev->mdev->ops &&
+  v4l2_dev->mdev->ops->req_queue;
+}
+
 /* Helper macros to iterate over all subdevs. */
 
 /**
-- 
2.17.0



[PATCHv15 05/35] media-request: add media_request_object_find

2018-06-04 Thread Hans Verkuil
From: Hans Verkuil 

Add media_request_object_find to find a request object inside a
request based on ops and/or priv values.

Objects of the same type (vb2 buffer, control handler) will have
the same ops value. And objects that refer to the same 'parent'
object (e.g. the v4l2_ctrl_handler that has the current driver
state) will have the same priv value.

The caller has to call media_request_object_put() for the returned
object since this function increments the refcount.

Signed-off-by: Hans Verkuil 
Acked-by: Sakari Ailus 
---
 drivers/media/media-request.c | 25 +
 include/media/media-request.h | 28 
 2 files changed, 53 insertions(+)

diff --git a/drivers/media/media-request.c b/drivers/media/media-request.c
index b011f9911fbd..6b9a4fc0248b 100644
--- a/drivers/media/media-request.c
+++ b/drivers/media/media-request.c
@@ -342,6 +342,31 @@ static void media_request_object_release(struct kref *kref)
obj->ops->release(obj);
 }
 
+struct media_request_object *
+media_request_object_find(struct media_request *req,
+ const struct media_request_object_ops *ops,
+ void *priv)
+{
+   struct media_request_object *obj;
+   struct media_request_object *found = NULL;
+   unsigned long flags;
+
+   if (WARN_ON(!ops || !priv))
+   return NULL;
+
+   spin_lock_irqsave(&req->lock, flags);
+   list_for_each_entry(obj, &req->objects, list) {
+   if (obj->ops == ops && obj->priv == priv) {
+   media_request_object_get(obj);
+   found = obj;
+   break;
+   }
+   }
+   spin_unlock_irqrestore(&req->lock, flags);
+   return found;
+}
+EXPORT_SYMBOL_GPL(media_request_object_find);
+
 void media_request_object_put(struct media_request_object *obj)
 {
kref_put(&obj->kref, media_request_object_release);
diff --git a/include/media/media-request.h b/include/media/media-request.h
index d9931dddb3a8..2b458d4d8a65 100644
--- a/include/media/media-request.h
+++ b/include/media/media-request.h
@@ -252,6 +252,26 @@ static inline void media_request_object_get(struct 
media_request_object *obj)
  */
 void media_request_object_put(struct media_request_object *obj);
 
+/**
+ * media_request_object_find - Find an object in a request
+ *
+ * @req: The media request
+ * @ops: Find an object with this ops value
+ * @priv: Find an object with this priv value
+ *
+ * Both @ops and @priv must be non-NULL.
+ *
+ * Returns the object pointer or NULL if not found. The caller must
+ * call media_request_object_put() once it finished using the object.
+ *
+ * Since this function needs to walk the list of objects it takes
+ * the @req->lock spin lock to make this safe.
+ */
+struct media_request_object *
+media_request_object_find(struct media_request *req,
+ const struct media_request_object_ops *ops,
+ void *priv);
+
 /**
  * media_request_object_init - Initialise a media request object
  *
@@ -323,6 +343,14 @@ static inline void media_request_object_put(struct 
media_request_object *obj)
 {
 }
 
+static inline struct media_request_object *
+media_request_object_find(struct media_request *req,
+ const struct media_request_object_ops *ops,
+ void *priv)
+{
+   return NULL;
+}
+
 static inline void media_request_object_init(struct media_request_object *obj)
 {
obj->ops = NULL;
-- 
2.17.0



[PATCHv15 04/35] media-request: add media_request_get_by_fd

2018-06-04 Thread Hans Verkuil
From: Hans Verkuil 

Add media_request_get_by_fd() to find a request based on the file
descriptor.

The caller has to call media_request_put() for the returned
request since this function increments the refcount.

Signed-off-by: Hans Verkuil 
Acked-by: Sakari Ailus 
---
 drivers/media/media-request.c | 40 +++
 include/media/media-request.h | 24 +
 2 files changed, 64 insertions(+)

diff --git a/drivers/media/media-request.c b/drivers/media/media-request.c
index 09823235e4c8..b011f9911fbd 100644
--- a/drivers/media/media-request.c
+++ b/drivers/media/media-request.c
@@ -229,6 +229,46 @@ static const struct file_operations request_fops = {
.release = media_request_close,
 };
 
+struct media_request *
+media_request_get_by_fd(struct media_device *mdev, int request_fd)
+{
+   struct file *filp;
+   struct media_request *req;
+
+   if (!mdev || !mdev->ops ||
+   !mdev->ops->req_validate || !mdev->ops->req_queue)
+   return ERR_PTR(-EPERM);
+
+   filp = fget(request_fd);
+   if (!filp)
+   return ERR_PTR(-ENOENT);
+
+   if (filp->f_op != &request_fops)
+   goto err_fput;
+   req = filp->private_data;
+   if (req->mdev != mdev)
+   goto err_fput;
+
+   /*
+* Note: as long as someone has an open filehandle of the request,
+* the request can never be released. The fget() above ensures that
+* even if userspace closes the request filehandle, the release()
+* fop won't be called, so the media_request_get() always succeeds
+* and there is no race condition where the request was released
+* before media_request_get() is called.
+*/
+   media_request_get(req);
+   fput(filp);
+
+   return req;
+
+err_fput:
+   fput(filp);
+
+   return ERR_PTR(-ENOENT);
+}
+EXPORT_SYMBOL_GPL(media_request_get_by_fd);
+
 int media_request_alloc(struct media_device *mdev,
struct media_request_alloc *alloc)
 {
diff --git a/include/media/media-request.h b/include/media/media-request.h
index 8acd2627835c..d9931dddb3a8 100644
--- a/include/media/media-request.h
+++ b/include/media/media-request.h
@@ -142,6 +142,24 @@ static inline void media_request_get(struct media_request 
*req)
  */
 void media_request_put(struct media_request *req);
 
+/**
+ * media_request_get_by_fd - Get a media request by fd
+ *
+ * @mdev: Media device this request belongs to
+ * @request_fd: The file descriptor of the request
+ *
+ * Get the request represented by @request_fd that is owned
+ * by the media device.
+ *
+ * Return a -EPERM error pointer if requests are not supported
+ * by this driver. Return -ENOENT if the request was not found.
+ * Return the pointer to the request if found: the caller will
+ * have to call @media_request_put when it finished using the
+ * request.
+ */
+struct media_request *
+media_request_get_by_fd(struct media_device *mdev, int request_fd);
+
 /**
  * media_request_alloc - Allocate the media request
  *
@@ -163,6 +181,12 @@ static inline void media_request_put(struct media_request 
*req)
 {
 }
 
+static inline struct media_request *
+media_request_get_by_fd(struct media_device *mdev, int request_fd)
+{
+   return ERR_PTR(-EPERM);
+}
+
 #endif
 
 /**
-- 
2.17.0



[PATCHv15 23/35] videobuf2-core: add request helper functions

2018-06-04 Thread Hans Verkuil
From: Hans Verkuil 

Add a new helper function to tell if a request object is a buffer.

Add a new helper function that returns true if a media_request
contains at least one buffer.

Signed-off-by: Hans Verkuil 
---
 drivers/media/common/videobuf2/videobuf2-core.c | 17 +
 include/media/videobuf2-core.h  | 15 +++
 2 files changed, 32 insertions(+)

diff --git a/drivers/media/common/videobuf2/videobuf2-core.c 
b/drivers/media/common/videobuf2/videobuf2-core.c
index 049822bcdd02..697765e70fbe 100644
--- a/drivers/media/common/videobuf2/videobuf2-core.c
+++ b/drivers/media/common/videobuf2/videobuf2-core.c
@@ -1362,6 +1362,23 @@ static const struct media_request_object_ops 
vb2_core_req_ops = {
.release = vb2_req_release,
 };
 
+bool vb2_request_object_is_buffer(struct media_request_object *obj)
+{
+   return obj->ops == &vb2_core_req_ops;
+}
+EXPORT_SYMBOL_GPL(vb2_request_object_is_buffer);
+
+bool vb2_request_has_buffers(struct media_request *req)
+{
+   struct media_request_object *obj;
+
+   list_for_each_entry(obj, &req->objects, list)
+   if (vb2_request_object_is_buffer(obj))
+   return true;
+   return false;
+}
+EXPORT_SYMBOL_GPL(vb2_request_has_buffers);
+
 int vb2_core_prepare_buf(struct vb2_queue *q, unsigned int index, void *pb)
 {
struct vb2_buffer *vb;
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index 8a8d7732d182..cad712403d14 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -1168,4 +1168,19 @@ bool vb2_buffer_in_use(struct vb2_queue *q, struct 
vb2_buffer *vb);
  */
 int vb2_verify_memory_type(struct vb2_queue *q,
enum vb2_memory memory, unsigned int type);
+
+/**
+ * vb2_request_object_is_buffer() - return true if the object is a buffer
+ *
+ * @obj:   the request object.
+ */
+bool vb2_request_object_is_buffer(struct media_request_object *obj);
+
+/**
+ * vb2_request_has_buffers() - return true if the request contains buffers
+ *
+ * @req:   the request.
+ */
+bool vb2_request_has_buffers(struct media_request *req);
+
 #endif /* _MEDIA_VIDEOBUF2_CORE_H */
-- 
2.17.0



[PATCHv15 34/35] vivid: add request support

2018-06-04 Thread Hans Verkuil
From: Hans Verkuil 

Add support for requests to vivid.

Signed-off-by: Hans Verkuil 
---
 drivers/media/platform/vivid/vivid-core.c|  8 
 drivers/media/platform/vivid/vivid-kthread-cap.c | 12 
 drivers/media/platform/vivid/vivid-kthread-out.c | 12 
 drivers/media/platform/vivid/vivid-sdr-cap.c | 16 
 drivers/media/platform/vivid/vivid-vbi-cap.c | 10 ++
 drivers/media/platform/vivid/vivid-vbi-out.c | 10 ++
 drivers/media/platform/vivid/vivid-vid-cap.c | 10 ++
 drivers/media/platform/vivid/vivid-vid-out.c | 10 ++
 8 files changed, 88 insertions(+)

diff --git a/drivers/media/platform/vivid/vivid-core.c 
b/drivers/media/platform/vivid/vivid-core.c
index 69386b26d5dd..a84c7e37c22b 100644
--- a/drivers/media/platform/vivid/vivid-core.c
+++ b/drivers/media/platform/vivid/vivid-core.c
@@ -627,6 +627,13 @@ static void vivid_dev_release(struct v4l2_device *v4l2_dev)
kfree(dev);
 }
 
+#ifdef CONFIG_MEDIA_CONTROLLER
+static const struct media_device_ops vivid_media_ops = {
+   .req_validate = vb2_request_validate,
+   .req_queue = vb2_request_queue,
+};
+#endif
+
 static int vivid_create_instance(struct platform_device *pdev, int inst)
 {
static const struct v4l2_dv_timings def_dv_timings =
@@ -664,6 +671,7 @@ static int vivid_create_instance(struct platform_device 
*pdev, int inst)
strlcpy(dev->mdev.model, VIVID_MODULE_NAME, sizeof(dev->mdev.model));
dev->mdev.dev = &pdev->dev;
media_device_init(&dev->mdev);
+   dev->mdev.ops = &vivid_media_ops;
 #endif
 
/* register v4l2_device */
diff --git a/drivers/media/platform/vivid/vivid-kthread-cap.c 
b/drivers/media/platform/vivid/vivid-kthread-cap.c
index 3fdb280c36ca..c192b4b1b9de 100644
--- a/drivers/media/platform/vivid/vivid-kthread-cap.c
+++ b/drivers/media/platform/vivid/vivid-kthread-cap.c
@@ -703,6 +703,8 @@ static void vivid_thread_vid_cap_tick(struct vivid_dev 
*dev, int dropped_bufs)
goto update_mv;
 
if (vid_cap_buf) {
+   v4l2_ctrl_request_setup(vid_cap_buf->vb.vb2_buf.req_obj.req,
+   &dev->ctrl_hdl_vid_cap);
/* Fill buffer */
vivid_fillbuff(dev, vid_cap_buf);
dprintk(dev, 1, "filled buffer %d\n",
@@ -713,6 +715,8 @@ static void vivid_thread_vid_cap_tick(struct vivid_dev 
*dev, int dropped_bufs)
dev->fb_cap.fmt.pixelformat == dev->fmt_cap->fourcc)
vivid_overlay(dev, vid_cap_buf);
 
+   v4l2_ctrl_request_complete(vid_cap_buf->vb.vb2_buf.req_obj.req,
+  &dev->ctrl_hdl_vid_cap);
vb2_buffer_done(&vid_cap_buf->vb.vb2_buf, dev->dqbuf_error ?
VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
dprintk(dev, 2, "vid_cap buffer %d done\n",
@@ -720,10 +724,14 @@ static void vivid_thread_vid_cap_tick(struct vivid_dev 
*dev, int dropped_bufs)
}
 
if (vbi_cap_buf) {
+   v4l2_ctrl_request_setup(vbi_cap_buf->vb.vb2_buf.req_obj.req,
+   &dev->ctrl_hdl_vbi_cap);
if (dev->stream_sliced_vbi_cap)
vivid_sliced_vbi_cap_process(dev, vbi_cap_buf);
else
vivid_raw_vbi_cap_process(dev, vbi_cap_buf);
+   v4l2_ctrl_request_complete(vbi_cap_buf->vb.vb2_buf.req_obj.req,
+  &dev->ctrl_hdl_vbi_cap);
vb2_buffer_done(&vbi_cap_buf->vb.vb2_buf, dev->dqbuf_error ?
VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
dprintk(dev, 2, "vbi_cap %d done\n",
@@ -891,6 +899,8 @@ void vivid_stop_generating_vid_cap(struct vivid_dev *dev, 
bool *pstreaming)
buf = list_entry(dev->vid_cap_active.next,
 struct vivid_buffer, list);
list_del(&buf->list);
+   v4l2_ctrl_request_complete(buf->vb.vb2_buf.req_obj.req,
+  &dev->ctrl_hdl_vid_cap);
vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
dprintk(dev, 2, "vid_cap buffer %d done\n",
buf->vb.vb2_buf.index);
@@ -904,6 +914,8 @@ void vivid_stop_generating_vid_cap(struct vivid_dev *dev, 
bool *pstreaming)
buf = list_entry(dev->vbi_cap_active.next,
 struct vivid_buffer, list);
list_del(&buf->list);
+   v4l2_ctrl_request_complete(buf->vb.vb2_buf.req_obj.req,
+  &dev->ctrl_hdl_vbi_cap);
vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
dprintk(

[PATCHv15 31/35] vim2m: use workqueue

2018-06-04 Thread Hans Verkuil
From: Hans Verkuil 

v4l2_ctrl uses mutexes, so we can't setup a ctrl_handler in
interrupt context. Switch to a workqueue instead and drop the timer.

Signed-off-by: Hans Verkuil 
---
 drivers/media/platform/vim2m.c | 25 ++---
 1 file changed, 10 insertions(+), 15 deletions(-)

diff --git a/drivers/media/platform/vim2m.c b/drivers/media/platform/vim2m.c
index 9be4da3b8577..5cb077294734 100644
--- a/drivers/media/platform/vim2m.c
+++ b/drivers/media/platform/vim2m.c
@@ -3,7 +3,8 @@
  *
  * This is a virtual device driver for testing mem-to-mem videobuf framework.
  * It simulates a device that uses memory buffers for both source and
- * destination, processes the data and issues an "irq" (simulated by a timer).
+ * destination, processes the data and issues an "irq" (simulated by a delayed
+ * workqueue).
  * The device is capable of multi-instance, multi-buffer-per-transaction
  * operation (via the mem2mem framework).
  *
@@ -19,7 +20,6 @@
 #include 
 #include 
 #include 
-#include 
 #include 
 #include 
 
@@ -149,7 +149,7 @@ struct vim2m_dev {
struct mutexdev_mutex;
spinlock_t  irqlock;
 
-   struct timer_list   timer;
+   struct delayed_work work_run;
 
struct v4l2_m2m_dev *m2m_dev;
 };
@@ -337,12 +337,6 @@ static int device_process(struct vim2m_ctx *ctx,
return 0;
 }
 
-static void schedule_irq(struct vim2m_dev *dev, int msec_timeout)
-{
-   dprintk(dev, "Scheduling a simulated irq\n");
-   mod_timer(&dev->timer, jiffies + msecs_to_jiffies(msec_timeout));
-}
-
 /*
  * mem2mem callbacks
  */
@@ -388,13 +382,14 @@ static void device_run(void *priv)
 
device_process(ctx, src_buf, dst_buf);
 
-   /* Run a timer, which simulates a hardware irq  */
-   schedule_irq(dev, ctx->transtime);
+   /* Run delayed work, which simulates a hardware irq  */
+   schedule_delayed_work(&dev->work_run, msecs_to_jiffies(ctx->transtime));
 }
 
-static void device_isr(struct timer_list *t)
+static void device_work(struct work_struct *w)
 {
-   struct vim2m_dev *vim2m_dev = from_timer(vim2m_dev, t, timer);
+   struct vim2m_dev *vim2m_dev =
+   container_of(w, struct vim2m_dev, work_run.work);
struct vim2m_ctx *curr_ctx;
struct vb2_v4l2_buffer *src_vb, *dst_vb;
unsigned long flags;
@@ -806,6 +801,7 @@ static void vim2m_stop_streaming(struct vb2_queue *q)
struct vb2_v4l2_buffer *vbuf;
unsigned long flags;
 
+   flush_scheduled_work();
for (;;) {
if (V4L2_TYPE_IS_OUTPUT(q->type))
vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
@@ -1011,6 +1007,7 @@ static int vim2m_probe(struct platform_device *pdev)
vfd = &dev->vfd;
vfd->lock = &dev->dev_mutex;
vfd->v4l2_dev = &dev->v4l2_dev;
+   INIT_DELAYED_WORK(&dev->work_run, device_work);
 
 #ifdef CONFIG_MEDIA_CONTROLLER
dev->mdev.dev = &pdev->dev;
@@ -1039,7 +1036,6 @@ static int vim2m_probe(struct platform_device *pdev)
v4l2_info(&dev->v4l2_dev,
"Device registered as /dev/video%d\n", vfd->num);
 
-   timer_setup(&dev->timer, device_isr, 0);
platform_set_drvdata(pdev, dev);
 
dev->m2m_dev = v4l2_m2m_init(&m2m_ops);
@@ -1083,7 +1079,6 @@ static int vim2m_remove(struct platform_device *pdev)
 #endif
 
v4l2_m2m_release(dev->m2m_dev);
-   del_timer_sync(&dev->timer);
video_unregister_device(&dev->vfd);
v4l2_device_unregister(&dev->v4l2_dev);
 
-- 
2.17.0



[PATCHv15 35/35] RFC: media-requests: add debugfs node

2018-06-04 Thread Hans Verkuil
From: Hans Verkuil 

Keep track of the number of requests and request objects of a media
device. Helps to verify that all request-related memory is freed.

Signed-off-by: Hans Verkuil 
---
 drivers/media/media-device.c  | 41 +++
 drivers/media/media-devnode.c | 17 +++
 drivers/media/media-request.c |  5 +
 include/media/media-device.h  | 13 +--
 include/media/media-devnode.h |  4 
 include/media/media-request.h |  2 ++
 6 files changed, 80 insertions(+), 2 deletions(-)

diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c
index 1119c1058e73..cefa822f505f 100644
--- a/drivers/media/media-device.c
+++ b/drivers/media/media-device.c
@@ -681,6 +681,23 @@ void media_device_unregister_entity(struct media_entity 
*entity)
 }
 EXPORT_SYMBOL_GPL(media_device_unregister_entity);
 
+#ifdef CONFIG_DEBUG_FS
+/*
+ * Log the state of media requests.
+ * Very useful for debugging.
+ */
+static int media_device_requests(struct seq_file *file, void *priv)
+{
+   struct media_device *dev = dev_get_drvdata(file->private);
+
+   seq_printf(file, "number of requests: %d\n",
+  atomic_read(&dev->num_requests));
+   seq_printf(file, "number of request objects: %d\n",
+  atomic_read(&dev->num_request_objects));
+   return 0;
+}
+#endif
+
 /**
  * media_device_init() - initialize a media device
  * @mdev:  The media device
@@ -703,6 +720,9 @@ void media_device_init(struct media_device *mdev)
mutex_init(&mdev->graph_mutex);
ida_init(&mdev->entity_internal_idx);
 
+   atomic_set(&mdev->num_requests, 0);
+   atomic_set(&mdev->num_request_objects, 0);
+
dev_dbg(mdev->dev, "Media device initialized\n");
 }
 EXPORT_SYMBOL_GPL(media_device_init);
@@ -754,6 +774,26 @@ int __must_check __media_device_register(struct 
media_device *mdev,
 
dev_dbg(mdev->dev, "Media device registered\n");
 
+#ifdef CONFIG_DEBUG_FS
+   if (!media_top_dir)
+   return 0;
+
+   mdev->media_dir = debugfs_create_dir(dev_name(&devnode->dev),
+media_top_dir);
+   if (IS_ERR_OR_NULL(mdev->media_dir)) {
+   dev_warn(mdev->dev, "Failed to create debugfs dir\n");
+   return 0;
+   }
+   mdev->requests_file = debugfs_create_devm_seqfile(&devnode->dev,
+   "requests", mdev->media_dir, media_device_requests);
+   if (IS_ERR_OR_NULL(mdev->requests_file)) {
+   dev_warn(mdev->dev, "Failed to create requests file\n");
+   debugfs_remove_recursive(mdev->media_dir);
+   mdev->media_dir = NULL;
+   return 0;
+   }
+#endif
+
return 0;
 }
 EXPORT_SYMBOL_GPL(__media_device_register);
@@ -831,6 +871,7 @@ void media_device_unregister(struct media_device *mdev)
 
dev_dbg(mdev->dev, "Media device unregistered\n");
 
+   debugfs_remove_recursive(mdev->media_dir);
device_remove_file(&mdev->devnode->dev, &dev_attr_model);
media_devnode_unregister(mdev->devnode);
/* devnode free is handled in media_devnode_*() */
diff --git a/drivers/media/media-devnode.c b/drivers/media/media-devnode.c
index 6b87a721dc49..4358ed22f208 100644
--- a/drivers/media/media-devnode.c
+++ b/drivers/media/media-devnode.c
@@ -53,6 +53,12 @@ static dev_t media_dev_t;
 static DEFINE_MUTEX(media_devnode_lock);
 static DECLARE_BITMAP(media_devnode_nums, MEDIA_NUM_DEVICES);
 
+/*
+ * debugfs
+ */
+struct dentry *media_top_dir;
+
+
 /* Called when the last user of the media device exits. */
 static void media_devnode_release(struct device *cd)
 {
@@ -259,6 +265,8 @@ int __must_check media_devnode_register(struct media_device 
*mdev,
goto cdev_add_error;
}
 
+   dev_set_drvdata(&devnode->dev, mdev);
+
/* Part 4: Activate this minor. The char device can now be used. */
set_bit(MEDIA_FLAG_REGISTERED, &devnode->flags);
 
@@ -310,6 +318,14 @@ static int __init media_devnode_init(void)
return ret;
}
 
+#ifdef CONFIG_DEBUG_FS
+   media_top_dir = debugfs_create_dir("media", NULL);
+   if (IS_ERR_OR_NULL(media_top_dir)) {
+   pr_warn("Failed to create debugfs media dir\n");
+   media_top_dir = NULL;
+   }
+#endif
+
ret = bus_register(&media_bus_type);
if (ret < 0) {
unregister_chrdev_region(media_dev_t, MEDIA_NUM_DEVICES);
@@ -322,6 +338,7 @@ static int __init media_devnode_init(void)
 
 static void __exit media_devnode_exit(void)
 {
+   debugfs_remove_recursive(media_top_dir);
bus_unregister(&media_bus_type);
unregister_chrdev_region(media_dev_t, MEDIA_NUM_DEVICES);
 }
diff --git a/drivers/media/media-request.c b/drivers/media/media-request.c
index 6b9a4fc0248b..86b574cc350a 100644
--- a/drivers/media/media-request.c
+++ b/drivers/media/media-request.c
@@ -72,6 +72,7 @@ static void media_request_rele

[PATCHv15 18/35] videodev2.h: Add request_fd field to v4l2_buffer

2018-06-04 Thread Hans Verkuil
From: Hans Verkuil 

When queuing buffers allow for passing the request that should
be associated with this buffer.

If V4L2_BUF_FLAG_REQUEST_FD is set, then request_fd is used as
the file descriptor.

If a buffer is stored in a request, but not yet queued to the
driver, then V4L2_BUF_FLAG_IN_REQUEST is set.

Signed-off-by: Hans Verkuil 
---
 drivers/media/common/videobuf2/videobuf2-v4l2.c |  2 +-
 drivers/media/usb/cpia2/cpia2_v4l.c |  2 +-
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c   |  9 ++---
 drivers/media/v4l2-core/v4l2-ioctl.c|  4 ++--
 include/uapi/linux/videodev2.h  | 10 +-
 5 files changed, 19 insertions(+), 8 deletions(-)

diff --git a/drivers/media/common/videobuf2/videobuf2-v4l2.c 
b/drivers/media/common/videobuf2/videobuf2-v4l2.c
index a677e2c26247..64905d87465c 100644
--- a/drivers/media/common/videobuf2/videobuf2-v4l2.c
+++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c
@@ -384,7 +384,7 @@ static void __fill_v4l2_buffer(struct vb2_buffer *vb, void 
*pb)
b->timecode = vbuf->timecode;
b->sequence = vbuf->sequence;
b->reserved2 = 0;
-   b->reserved = 0;
+   b->request_fd = 0;
 
if (q->is_multiplanar) {
/*
diff --git a/drivers/media/usb/cpia2/cpia2_v4l.c 
b/drivers/media/usb/cpia2/cpia2_v4l.c
index 99f106b13280..13aee9f67d05 100644
--- a/drivers/media/usb/cpia2/cpia2_v4l.c
+++ b/drivers/media/usb/cpia2/cpia2_v4l.c
@@ -949,7 +949,7 @@ static int cpia2_dqbuf(struct file *file, void *fh, struct 
v4l2_buffer *buf)
buf->m.offset = cam->buffers[buf->index].data - cam->frame_buffer;
buf->length = cam->frame_size;
buf->reserved2 = 0;
-   buf->reserved = 0;
+   buf->request_fd = 0;
memset(&buf->timecode, 0, sizeof(buf->timecode));
 
DBG("DQBUF #%d status:%d seq:%d length:%d\n", buf->index,
diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c 
b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index dcce86c1fe40..633465d21d04 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -482,7 +482,7 @@ struct v4l2_buffer32 {
} m;
__u32   length;
__u32   reserved2;
-   __u32   reserved;
+   __s32   request_fd;
 };
 
 static int get_v4l2_plane32(struct v4l2_plane __user *p64,
@@ -581,6 +581,7 @@ static int get_v4l2_buffer32(struct v4l2_buffer __user *p64,
 {
u32 type;
u32 length;
+   s32 request_fd;
enum v4l2_memory memory;
struct v4l2_plane32 __user *uplane32;
struct v4l2_plane __user *uplane;
@@ -595,7 +596,9 @@ static int get_v4l2_buffer32(struct v4l2_buffer __user *p64,
get_user(memory, &p32->memory) ||
put_user(memory, &p64->memory) ||
get_user(length, &p32->length) ||
-   put_user(length, &p64->length))
+   put_user(length, &p64->length) ||
+   get_user(request_fd, &p32->request_fd) ||
+   put_user(request_fd, &p64->request_fd))
return -EFAULT;
 
if (V4L2_TYPE_IS_OUTPUT(type))
@@ -699,7 +702,7 @@ static int put_v4l2_buffer32(struct v4l2_buffer __user *p64,
copy_in_user(&p32->timecode, &p64->timecode, sizeof(p64->timecode)) 
||
assign_in_user(&p32->sequence, &p64->sequence) ||
assign_in_user(&p32->reserved2, &p64->reserved2) ||
-   assign_in_user(&p32->reserved, &p64->reserved) ||
+   assign_in_user(&p32->request_fd, &p64->request_fd) ||
get_user(length, &p64->length) ||
put_user(length, &p32->length))
return -EFAULT;
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c 
b/drivers/media/v4l2-core/v4l2-ioctl.c
index fd3ea7e504e3..eeae589b44ef 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -437,13 +437,13 @@ static void v4l_print_buffer(const void *arg, bool 
write_only)
const struct v4l2_plane *plane;
int i;
 
-   pr_cont("%02ld:%02d:%02d.%08ld index=%d, type=%s, flags=0x%08x, 
field=%s, sequence=%d, memory=%s",
+   pr_cont("%02ld:%02d:%02d.%08ld index=%d, type=%s, request_fd=%d, 
flags=0x%08x, field=%s, sequence=%d, memory=%s",
p->timestamp.tv_sec / 3600,
(int)(p->timestamp.tv_sec / 60) % 60,
(int)(p->timestamp.tv_sec % 60),
(long)p->timestamp.tv_usec,
p->index,
-   prt_names(p->type, v4l2_type_names),
+   prt_names(p->type, v4l2_type_names), p->request_fd,
p->flags, prt_names(p->field, v4l2_field_names),
p->sequence, prt_names(p->memory, v4l2_memory_names));
 
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index 16b53b82496c..1f6c4b52baae 100644
--- a/include/uapi/l

[PATCHv15 17/35] vb2: drop VB2_BUF_STATE_PREPARED, use bool prepared/synced instead

2018-06-04 Thread Hans Verkuil
From: Hans Verkuil 

The PREPARED state becomes a problem with the request API: a buffer
could be PREPARED but dequeued, or PREPARED and in state IN_REQUEST.

PREPARED is really not a state as such, but more a property of the
buffer. So make new 'prepared' and 'synced' bools instead to remember
whether the buffer is prepared and/or synced or not.

V4L2_BUF_FLAG_PREPARED is only set if the buffer is both synced and
prepared and in the DEQUEUED state.

Signed-off-by: Hans Verkuil 
---
 .../media/common/videobuf2/videobuf2-core.c   | 38 +--
 .../media/common/videobuf2/videobuf2-v4l2.c   | 16 +---
 include/media/videobuf2-core.h|  6 ++-
 3 files changed, 40 insertions(+), 20 deletions(-)

diff --git a/drivers/media/common/videobuf2/videobuf2-core.c 
b/drivers/media/common/videobuf2/videobuf2-core.c
index c25bad134ba3..997673b62afc 100644
--- a/drivers/media/common/videobuf2/videobuf2-core.c
+++ b/drivers/media/common/videobuf2/videobuf2-core.c
@@ -682,7 +682,7 @@ int vb2_core_reqbufs(struct vb2_queue *q, enum vb2_memory 
memory,
}
 
/*
-* Call queue_cancel to clean up any buffers in the PREPARED or
+* Call queue_cancel to clean up any buffers in the
 * QUEUED state which is possible if buffers were prepared or
 * queued without ever calling STREAMON.
 */
@@ -921,6 +921,7 @@ void vb2_buffer_done(struct vb2_buffer *vb, enum 
vb2_buffer_state state)
/* sync buffers */
for (plane = 0; plane < vb->num_planes; ++plane)
call_void_memop(vb, finish, vb->planes[plane].mem_priv);
+   vb->synced = false;
}
 
spin_lock_irqsave(&q->done_lock, flags);
@@ -1239,6 +1240,7 @@ static void __enqueue_in_driver(struct vb2_buffer *vb)
 static int __buf_prepare(struct vb2_buffer *vb)
 {
struct vb2_queue *q = vb->vb2_queue;
+   enum vb2_buffer_state orig_state = vb->state;
unsigned int plane;
int ret;
 
@@ -1247,6 +1249,10 @@ static int __buf_prepare(struct vb2_buffer *vb)
return -EIO;
}
 
+   if (vb->prepared)
+   return 0;
+   WARN_ON(vb->synced);
+
vb->state = VB2_BUF_STATE_PREPARING;
 
switch (q->memory) {
@@ -1262,11 +1268,12 @@ static int __buf_prepare(struct vb2_buffer *vb)
default:
WARN(1, "Invalid queue type\n");
ret = -EINVAL;
+   break;
}
 
if (ret) {
dprintk(1, "buffer preparation failed: %d\n", ret);
-   vb->state = VB2_BUF_STATE_DEQUEUED;
+   vb->state = orig_state;
return ret;
}
 
@@ -1274,7 +1281,9 @@ static int __buf_prepare(struct vb2_buffer *vb)
for (plane = 0; plane < vb->num_planes; ++plane)
call_void_memop(vb, prepare, vb->planes[plane].mem_priv);
 
-   vb->state = VB2_BUF_STATE_PREPARED;
+   vb->synced = true;
+   vb->prepared = true;
+   vb->state = orig_state;
 
return 0;
 }
@@ -1290,6 +1299,10 @@ int vb2_core_prepare_buf(struct vb2_queue *q, unsigned 
int index, void *pb)
vb->state);
return -EINVAL;
}
+   if (vb->prepared) {
+   dprintk(1, "buffer already prepared\n");
+   return -EINVAL;
+   }
 
ret = __buf_prepare(vb);
if (ret)
@@ -1376,11 +1389,11 @@ int vb2_core_qbuf(struct vb2_queue *q, unsigned int 
index, void *pb)
 
switch (vb->state) {
case VB2_BUF_STATE_DEQUEUED:
-   ret = __buf_prepare(vb);
-   if (ret)
-   return ret;
-   break;
-   case VB2_BUF_STATE_PREPARED:
+   if (!vb->prepared) {
+   ret = __buf_prepare(vb);
+   if (ret)
+   return ret;
+   }
break;
case VB2_BUF_STATE_PREPARING:
dprintk(1, "buffer still being prepared\n");
@@ -1606,6 +1619,7 @@ int vb2_core_dqbuf(struct vb2_queue *q, unsigned int 
*pindex, void *pb,
}
 
call_void_vb_qop(vb, buf_finish, vb);
+   vb->prepared = false;
 
if (pindex)
*pindex = vb->index;
@@ -1694,18 +1708,18 @@ static void __vb2_queue_cancel(struct vb2_queue *q)
for (i = 0; i < q->num_buffers; ++i) {
struct vb2_buffer *vb = q->bufs[i];
 
-   if (vb->state == VB2_BUF_STATE_PREPARED ||
-   vb->state == VB2_BUF_STATE_QUEUED) {
+   if (vb->synced) {
unsigned int plane;
 
for (plane = 0; plane < vb->num_planes; ++plane)
call_void_memop(vb, finish,
vb->planes[plane].mem_priv);
+   vb->synced = false;
}
 
-   

[PATCHv15 11/35] v4l2-ctrls: alloc memory for p_req

2018-06-04 Thread Hans Verkuil
From: Hans Verkuil 

To store request data the handler_new_ref() allocates memory
for it if needed.

Signed-off-by: Hans Verkuil 
---
 drivers/media/v4l2-core/v4l2-ctrls.c | 20 
 1 file changed, 16 insertions(+), 4 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c 
b/drivers/media/v4l2-core/v4l2-ctrls.c
index d09f49530d9e..3c1b00baa8d0 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
@@ -1997,13 +1997,18 @@ EXPORT_SYMBOL(v4l2_ctrl_find);
 /* Allocate a new v4l2_ctrl_ref and hook it into the handler. */
 static int handler_new_ref(struct v4l2_ctrl_handler *hdl,
   struct v4l2_ctrl *ctrl,
-  bool from_other_dev)
+  struct v4l2_ctrl_ref **ctrl_ref,
+  bool from_other_dev, bool allocate_req)
 {
struct v4l2_ctrl_ref *ref;
struct v4l2_ctrl_ref *new_ref;
u32 id = ctrl->id;
u32 class_ctrl = V4L2_CTRL_ID2WHICH(id) | 1;
int bucket = id % hdl->nr_of_buckets;   /* which bucket to use */
+   unsigned int sz_extra = 0;
+
+   if (ctrl_ref)
+   *ctrl_ref = NULL;
 
/*
 * Automatically add the control class if it is not yet present and
@@ -2017,11 +2022,16 @@ static int handler_new_ref(struct v4l2_ctrl_handler 
*hdl,
if (hdl->error)
return hdl->error;
 
-   new_ref = kzalloc(sizeof(*new_ref), GFP_KERNEL);
+   if (allocate_req)
+   sz_extra = ctrl->elems * ctrl->elem_size;
+   new_ref = kzalloc(sizeof(*new_ref) + sz_extra, GFP_KERNEL);
if (!new_ref)
return handler_set_err(hdl, -ENOMEM);
new_ref->ctrl = ctrl;
new_ref->from_other_dev = from_other_dev;
+   if (sz_extra)
+   new_ref->p_req.p = &new_ref[1];
+
if (ctrl->handler == hdl) {
/* By default each control starts in a cluster of its own.
   new_ref->ctrl is basically a cluster array with one
@@ -2061,6 +2071,8 @@ static int handler_new_ref(struct v4l2_ctrl_handler *hdl,
/* Insert the control node in the hash */
new_ref->next = hdl->buckets[bucket];
hdl->buckets[bucket] = new_ref;
+   if (ctrl_ref)
+   *ctrl_ref = new_ref;
 
 unlock:
mutex_unlock(hdl->lock);
@@ -2202,7 +2214,7 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct 
v4l2_ctrl_handler *hdl,
ctrl->type_ops->init(ctrl, idx, ctrl->p_new);
}
 
-   if (handler_new_ref(hdl, ctrl, false)) {
+   if (handler_new_ref(hdl, ctrl, NULL, false, false)) {
kvfree(ctrl);
return NULL;
}
@@ -2395,7 +2407,7 @@ int v4l2_ctrl_add_handler(struct v4l2_ctrl_handler *hdl,
/* Filter any unwanted controls */
if (filter && !filter(ctrl))
continue;
-   ret = handler_new_ref(hdl, ctrl, from_other_dev);
+   ret = handler_new_ref(hdl, ctrl, NULL, from_other_dev, false);
if (ret)
break;
}
-- 
2.17.0



[PATCHv15 25/35] videobuf2-core: add uses_requests flag

2018-06-04 Thread Hans Verkuil
From: Hans Verkuil 

Set the first time a buffer from a request is queued to vb2.
Cleared when the queue is canceled.

Signed-off-by: Hans Verkuil 
---
 drivers/media/common/videobuf2/videobuf2-core.c | 2 ++
 include/media/videobuf2-core.h  | 3 +++
 2 files changed, 5 insertions(+)

diff --git a/drivers/media/common/videobuf2/videobuf2-core.c 
b/drivers/media/common/videobuf2/videobuf2-core.c
index 697765e70fbe..ec76dcb130fe 100644
--- a/drivers/media/common/videobuf2/videobuf2-core.c
+++ b/drivers/media/common/videobuf2/videobuf2-core.c
@@ -1500,6 +1500,7 @@ int vb2_core_qbuf(struct vb2_queue *q, unsigned int 
index, void *pb,
if (ret)
return ret;
 
+   q->uses_requests = 1;
vb->state = VB2_BUF_STATE_IN_REQUEST;
/* Fill buffer information for the userspace */
if (pb) {
@@ -1813,6 +1814,7 @@ static void __vb2_queue_cancel(struct vb2_queue *q)
q->start_streaming_called = 0;
q->queued_count = 0;
q->error = 0;
+   q->uses_requests = 0;
 
/*
 * Remove all buffers from videobuf's list...
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index cad712403d14..67553180d98f 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -468,6 +468,8 @@ struct vb2_buf_ops {
  * @quirk_poll_must_check_waiting_for_buffers: Return %EPOLLERR at poll when 
QBUF
  *  has not been called. This is a vb1 idiom that has been adopted
  *  also by vb2.
+ * @uses_requests: requests are used for this queue. Set to 1 the first time
+ * a request is queued. Set to 0 when the queue is canceled.
  * @lock:  pointer to a mutex that protects the &struct vb2_queue. The
  * driver can set this to a mutex to let the v4l2 core serialize
  * the queuing ioctls. If the driver wants to handle locking
@@ -535,6 +537,7 @@ struct vb2_queue {
unsignedfileio_write_immediately:1;
unsignedallow_zero_bytesused:1;
unsigned   quirk_poll_must_check_waiting_for_buffers:1;
+   unsigneduses_requests:1;
 
struct mutex*lock;
void*owner;
-- 
2.17.0



[PATCHv15 10/35] v4l2-ctrls: prepare internal structs for request API

2018-06-04 Thread Hans Verkuil
From: Hans Verkuil 

Embed and initialize a media_request_object in struct v4l2_ctrl_handler.

Add a p_req field to struct v4l2_ctrl_ref that will store the
request value.

Signed-off-by: Hans Verkuil 
Signed-off-by: Alexandre Courbot 
---
 drivers/media/v4l2-core/v4l2-ctrls.c |  1 +
 include/media/v4l2-ctrls.h   | 10 ++
 2 files changed, 11 insertions(+)

diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c 
b/drivers/media/v4l2-core/v4l2-ctrls.c
index aa1dd2015e84..d09f49530d9e 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
@@ -1880,6 +1880,7 @@ int v4l2_ctrl_handler_init_class(struct v4l2_ctrl_handler 
*hdl,
  sizeof(hdl->buckets[0]),
  GFP_KERNEL | __GFP_ZERO);
hdl->error = hdl->buckets ? 0 : -ENOMEM;
+   media_request_object_init(&hdl->req_obj);
return hdl->error;
 }
 EXPORT_SYMBOL(v4l2_ctrl_handler_init_class);
diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h
index d26b8ddebb56..847d6f543e4a 100644
--- a/include/media/v4l2-ctrls.h
+++ b/include/media/v4l2-ctrls.h
@@ -20,6 +20,7 @@
 #include 
 #include 
 #include 
+#include 
 
 /* forward references */
 struct file;
@@ -249,6 +250,11 @@ struct v4l2_ctrl {
  * ``prepare_ext_ctrls`` function at ``v4l2-ctrl.c``.
  * @from_other_dev: If true, then @ctrl was defined in another
  * device than the &struct v4l2_ctrl_handler.
+ * @p_req: If the control handler containing this control reference
+ * is bound to a media request, then this points to the
+ * value of the control that should be applied when the request
+ * is executed, or to the value of the control at the time
+ * that the request was completed.
  *
  * Each control handler has a list of these refs. The list_head is used to
  * keep a sorted-by-control-ID list of all controls, while the next pointer
@@ -260,6 +266,7 @@ struct v4l2_ctrl_ref {
struct v4l2_ctrl *ctrl;
struct v4l2_ctrl_helper *helper;
bool from_other_dev;
+   union v4l2_ctrl_ptr p_req;
 };
 
 /**
@@ -283,6 +290,8 @@ struct v4l2_ctrl_ref {
  * @notify_priv: Passed as argument to the v4l2_ctrl notify callback.
  * @nr_of_buckets: Total number of buckets in the array.
  * @error: The error code of the first failed control addition.
+ * @req_obj:   The &struct media_request_object, used to link into a
+ * &struct media_request. This request object has a refcount.
  */
 struct v4l2_ctrl_handler {
struct mutex _lock;
@@ -295,6 +304,7 @@ struct v4l2_ctrl_handler {
void *notify_priv;
u16 nr_of_buckets;
int error;
+   struct media_request_object req_obj;
 };
 
 /**
-- 
2.17.0



[PATCHv15 28/35] v4l2-mem2mem: add vb2_m2m_request_queue

2018-06-04 Thread Hans Verkuil
From: Hans Verkuil 

For mem2mem devices we have to make sure that v4l2_m2m_try_schedule()
is called whenever a request is queued.

We do that by creating a vb2_m2m_request_queue() helper that should
be used instead of the 'normal' vb2_request_queue() helper. The m2m
helper function will call v4l2_m2m_try_schedule() as needed.

In addition we also avoid calling v4l2_m2m_try_schedule() when preparing
or queueing a buffer for a request since that is no longer needed.
Instead this helper function will do that when the request is actually
queued.

Signed-off-by: Hans Verkuil 
---
 drivers/media/v4l2-core/v4l2-mem2mem.c | 43 +-
 include/media/v4l2-mem2mem.h   |  4 +++
 2 files changed, 39 insertions(+), 8 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-mem2mem.c 
b/drivers/media/v4l2-core/v4l2-mem2mem.c
index 88f95b78e4d0..ec0f8924f5c7 100644
--- a/drivers/media/v4l2-core/v4l2-mem2mem.c
+++ b/drivers/media/v4l2-core/v4l2-mem2mem.c
@@ -304,7 +304,7 @@ static void v4l2_m2m_cancel_job(struct v4l2_m2m_ctx 
*m2m_ctx)
if (m2m_ctx->job_flags & TRANS_RUNNING) {
spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags);
m2m_dev->m2m_ops->job_abort(m2m_ctx->priv);
-   dprintk("m2m_ctx %p running, will wait to complete", m2m_ctx);
+   dprintk("m2m_ctx %p running, will wait to complete\n", m2m_ctx);
wait_event(m2m_ctx->finished,
!(m2m_ctx->job_flags & TRANS_RUNNING));
} else if (m2m_ctx->job_flags & TRANS_QUEUED) {
@@ -396,8 +396,14 @@ int v4l2_m2m_qbuf(struct file *file, struct v4l2_m2m_ctx 
*m2m_ctx,
int ret;
 
vq = v4l2_m2m_get_vq(m2m_ctx, buf->type);
+   if (!V4L2_TYPE_IS_OUTPUT(vq->type) &&
+   (buf->flags & V4L2_BUF_FLAG_REQUEST_FD)) {
+   dprintk("%s: requests cannot be used with capture buffers\n",
+   __func__);
+   return -EINVAL;
+   }
ret = vb2_qbuf(vq, vdev->v4l2_dev->mdev, buf);
-   if (!ret)
+   if (!ret && !(buf->flags & V4L2_BUF_FLAG_IN_REQUEST))
v4l2_m2m_try_schedule(m2m_ctx);
 
return ret;
@@ -419,14 +425,9 @@ int v4l2_m2m_prepare_buf(struct file *file, struct 
v4l2_m2m_ctx *m2m_ctx,
 {
struct video_device *vdev = video_devdata(file);
struct vb2_queue *vq;
-   int ret;
 
vq = v4l2_m2m_get_vq(m2m_ctx, buf->type);
-   ret = vb2_prepare_buf(vq, vdev->v4l2_dev->mdev, buf);
-   if (!ret)
-   v4l2_m2m_try_schedule(m2m_ctx);
-
-   return ret;
+   return vb2_prepare_buf(vq, vdev->v4l2_dev->mdev, buf);
 }
 EXPORT_SYMBOL_GPL(v4l2_m2m_prepare_buf);
 
@@ -703,6 +704,32 @@ void v4l2_m2m_buf_queue(struct v4l2_m2m_ctx *m2m_ctx,
 }
 EXPORT_SYMBOL_GPL(v4l2_m2m_buf_queue);
 
+void vb2_m2m_request_queue(struct media_request *req)
+{
+   struct media_request_object *obj;
+
+   list_for_each_entry(obj, &req->objects, list) {
+   struct v4l2_m2m_ctx *m2m_ctx;
+   struct vb2_buffer *vb;
+
+   if (!obj->ops->queue)
+   continue;
+
+   obj->ops->queue(obj);
+   if (!vb2_request_object_is_buffer(obj))
+   continue;
+
+   vb = container_of(obj, struct vb2_buffer, req_obj);
+   if (WARN_ON(!V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)))
+   continue;
+   m2m_ctx = container_of(vb->vb2_queue,
+  struct v4l2_m2m_ctx,
+  out_q_ctx.q);
+   v4l2_m2m_try_schedule(m2m_ctx);
+   }
+}
+EXPORT_SYMBOL_GPL(vb2_m2m_request_queue);
+
 /* Videobuf2 ioctl helpers */
 
 int v4l2_m2m_ioctl_reqbufs(struct file *file, void *priv,
diff --git a/include/media/v4l2-mem2mem.h b/include/media/v4l2-mem2mem.h
index 3d07ba3a8262..f01b3fc13b0e 100644
--- a/include/media/v4l2-mem2mem.h
+++ b/include/media/v4l2-mem2mem.h
@@ -580,6 +580,10 @@ v4l2_m2m_dst_buf_remove_by_idx(struct v4l2_m2m_ctx 
*m2m_ctx, unsigned int idx)
return v4l2_m2m_buf_remove_by_idx(&m2m_ctx->cap_q_ctx, idx);
 }
 
+/* v4l2 request helper */
+
+void vb2_m2m_request_queue(struct media_request *req);
+
 /* v4l2 ioctl helpers */
 
 int v4l2_m2m_ioctl_reqbufs(struct file *file, void *priv,
-- 
2.17.0



[PATCHv15 22/35] videobuf2-v4l2: integrate with media requests

2018-06-04 Thread Hans Verkuil
From: Hans Verkuil 

This implements the V4L2 part of the request support. The main
change is that vb2_qbuf and vb2_prepare_buf now have a new
media_device pointer. This required changes to several drivers
that did not use the vb2_ioctl_qbuf/prepare_buf helper functions.

Signed-off-by: Hans Verkuil 
---
 .../media/common/videobuf2/videobuf2-core.c   |  13 +-
 .../media/common/videobuf2/videobuf2-v4l2.c   | 112 --
 drivers/media/platform/omap3isp/ispvideo.c|   2 +-
 .../media/platform/s3c-camif/camif-capture.c  |   4 +-
 drivers/media/platform/s5p-mfc/s5p_mfc_dec.c  |   4 +-
 drivers/media/platform/s5p-mfc/s5p_mfc_enc.c  |   4 +-
 .../media/platform/soc_camera/soc_camera.c|   4 +-
 drivers/media/usb/uvc/uvc_queue.c |   5 +-
 drivers/media/usb/uvc/uvc_v4l2.c  |   3 +-
 drivers/media/usb/uvc/uvcvideo.h  |   1 +
 drivers/media/v4l2-core/v4l2-mem2mem.c|   7 +-
 .../staging/media/davinci_vpfe/vpfe_video.c   |   3 +-
 drivers/staging/media/omap4iss/iss_video.c|   3 +-
 drivers/usb/gadget/function/uvc_queue.c   |   2 +-
 include/media/videobuf2-v4l2.h|  14 ++-
 15 files changed, 149 insertions(+), 32 deletions(-)

diff --git a/drivers/media/common/videobuf2/videobuf2-core.c 
b/drivers/media/common/videobuf2/videobuf2-core.c
index 6d423bc5a1a1..049822bcdd02 100644
--- a/drivers/media/common/videobuf2/videobuf2-core.c
+++ b/drivers/media/common/videobuf2/videobuf2-core.c
@@ -1338,6 +1338,14 @@ static void vb2_req_queue(struct media_request_object 
*obj)
mutex_unlock(vb->vb2_queue->lock);
 }
 
+static void vb2_req_unbind(struct media_request_object *obj)
+{
+   struct vb2_buffer *vb = container_of(obj, struct vb2_buffer, req_obj);
+
+   if (vb->state == VB2_BUF_STATE_IN_REQUEST)
+   call_void_bufop(vb->vb2_queue, init_buffer, vb);
+}
+
 static void vb2_req_release(struct media_request_object *obj)
 {
struct vb2_buffer *vb = container_of(obj, struct vb2_buffer, req_obj);
@@ -1350,6 +1358,7 @@ static const struct media_request_object_ops 
vb2_core_req_ops = {
.prepare = vb2_req_prepare,
.unprepare = vb2_req_unprepare,
.queue = vb2_req_queue,
+   .unbind = vb2_req_unbind,
.release = vb2_req_release,
 };
 
@@ -1476,8 +1485,10 @@ int vb2_core_qbuf(struct vb2_queue *q, unsigned int 
index, void *pb,
 
vb->state = VB2_BUF_STATE_IN_REQUEST;
/* Fill buffer information for the userspace */
-   if (pb)
+   if (pb) {
+   call_void_bufop(q, copy_timestamp, vb, pb);
call_void_bufop(q, fill_user_buffer, vb, pb);
+   }
 
dprintk(2, "qbuf of buffer %d succeeded\n", vb->index);
return 0;
diff --git a/drivers/media/common/videobuf2/videobuf2-v4l2.c 
b/drivers/media/common/videobuf2/videobuf2-v4l2.c
index ea9db4b3f59a..9c652afa62ab 100644
--- a/drivers/media/common/videobuf2/videobuf2-v4l2.c
+++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c
@@ -25,6 +25,7 @@
 #include 
 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -40,10 +41,12 @@ module_param(debug, int, 0644);
pr_info("vb2-v4l2: %s: " fmt, __func__, ## arg); \
} while (0)
 
-/* Flags that are set by the vb2 core */
+/* Flags that are set by us */
 #define V4L2_BUFFER_MASK_FLAGS (V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_QUEUED | \
 V4L2_BUF_FLAG_DONE | V4L2_BUF_FLAG_ERROR | \
 V4L2_BUF_FLAG_PREPARED | \
+V4L2_BUF_FLAG_IN_REQUEST | \
+V4L2_BUF_FLAG_REQUEST_FD | \
 V4L2_BUF_FLAG_TIMESTAMP_MASK)
 /* Output buffer flags that should be passed on to the driver */
 #define V4L2_BUFFER_OUT_FLAGS  (V4L2_BUF_FLAG_PFRAME | V4L2_BUF_FLAG_BFRAME | \
@@ -118,6 +121,16 @@ static int __verify_length(struct vb2_buffer *vb, const 
struct v4l2_buffer *b)
return 0;
 }
 
+/*
+ * __init_v4l2_vb2_buffer() - initialize the v4l2_vb2_buffer struct
+ */
+static void __init_v4l2_vb2_buffer(struct vb2_buffer *vb)
+{
+   struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+
+   vbuf->request_fd = -1;
+}
+
 static void __copy_timestamp(struct vb2_buffer *vb, const void *pb)
 {
const struct v4l2_buffer *b = pb;
@@ -181,6 +194,7 @@ static int vb2_fill_vb2_v4l2_buffer(struct vb2_buffer *vb, 
struct v4l2_buffer *b
return -EINVAL;
}
vbuf->sequence = 0;
+   vbuf->request_fd = -1;
 
if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
switch (b->memory) {
@@ -318,9 +332,12 @@ static int vb2_fill_vb2_v4l2_buffer(struct vb2_buffer *vb, 
struct v4l2_buffer *b
return 0;
 }
 
-static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b,
-   const char *opname)
+static int vb2_queue_or_prepar

[PATCHv15 30/35] vim2m: add media device

2018-06-04 Thread Hans Verkuil
From: Hans Verkuil 

Request API requires a media node. Add one to the vim2m driver so we can
use requests with it.

This probably needs a bit more work to correctly represent m2m
hardware in the media topology.

Signed-off-by: Hans Verkuil 
---
 drivers/media/platform/vim2m.c | 42 ++
 1 file changed, 37 insertions(+), 5 deletions(-)

diff --git a/drivers/media/platform/vim2m.c b/drivers/media/platform/vim2m.c
index 065483e62db4..9be4da3b8577 100644
--- a/drivers/media/platform/vim2m.c
+++ b/drivers/media/platform/vim2m.c
@@ -140,6 +140,10 @@ static struct vim2m_fmt *find_format(struct v4l2_format *f)
 struct vim2m_dev {
struct v4l2_device  v4l2_dev;
struct video_device vfd;
+#ifdef CONFIG_MEDIA_CONTROLLER
+   struct media_device mdev;
+   struct media_padpad[2];
+#endif
 
atomic_tnum_inst;
struct mutexdev_mutex;
@@ -1000,11 +1004,6 @@ static int vim2m_probe(struct platform_device *pdev)
return -ENOMEM;
 
spin_lock_init(&dev->irqlock);
-
-   ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
-   if (ret)
-   return ret;
-
atomic_set(&dev->num_inst, 0);
mutex_init(&dev->dev_mutex);
 
@@ -1013,6 +1012,22 @@ static int vim2m_probe(struct platform_device *pdev)
vfd->lock = &dev->dev_mutex;
vfd->v4l2_dev = &dev->v4l2_dev;
 
+#ifdef CONFIG_MEDIA_CONTROLLER
+   dev->mdev.dev = &pdev->dev;
+   strlcpy(dev->mdev.model, "vim2m", sizeof(dev->mdev.model));
+   media_device_init(&dev->mdev);
+   dev->v4l2_dev.mdev = &dev->mdev;
+   dev->pad[0].flags = MEDIA_PAD_FL_SINK;
+   dev->pad[1].flags = MEDIA_PAD_FL_SOURCE;
+   ret = media_entity_pads_init(&vfd->entity, 2, dev->pad);
+   if (ret)
+   return ret;
+#endif
+
+   ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
+   if (ret)
+   goto unreg_media;
+
ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0);
if (ret) {
v4l2_err(&dev->v4l2_dev, "Failed to register video device\n");
@@ -1034,6 +1049,13 @@ static int vim2m_probe(struct platform_device *pdev)
goto err_m2m;
}
 
+#ifdef CONFIG_MEDIA_CONTROLLER
+   /* Register the media device node */
+   ret = media_device_register(&dev->mdev);
+   if (ret)
+   goto err_m2m;
+#endif
+
return 0;
 
 err_m2m:
@@ -1041,6 +1063,10 @@ static int vim2m_probe(struct platform_device *pdev)
video_unregister_device(&dev->vfd);
 unreg_dev:
v4l2_device_unregister(&dev->v4l2_dev);
+unreg_media:
+#ifdef CONFIG_MEDIA_CONTROLLER
+   media_device_unregister(&dev->mdev);
+#endif
 
return ret;
 }
@@ -1050,6 +1076,12 @@ static int vim2m_remove(struct platform_device *pdev)
struct vim2m_dev *dev = platform_get_drvdata(pdev);
 
v4l2_info(&dev->v4l2_dev, "Removing " MEM2MEM_NAME);
+
+#ifdef CONFIG_MEDIA_CONTROLLER
+   media_device_unregister(&dev->mdev);
+   media_device_cleanup(&dev->mdev);
+#endif
+
v4l2_m2m_release(dev->m2m_dev);
del_timer_sync(&dev->timer);
video_unregister_device(&dev->vfd);
-- 
2.17.0



[PATCHv15 32/35] vim2m: support requests

2018-06-04 Thread Hans Verkuil
From: Hans Verkuil 

Add support for requests to vim2m.

Signed-off-by: Hans Verkuil 
---
 drivers/media/platform/vim2m.c | 26 ++
 1 file changed, 26 insertions(+)

diff --git a/drivers/media/platform/vim2m.c b/drivers/media/platform/vim2m.c
index 5cb077294734..1efc8033320f 100644
--- a/drivers/media/platform/vim2m.c
+++ b/drivers/media/platform/vim2m.c
@@ -380,8 +380,18 @@ static void device_run(void *priv)
src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
 
+   /* Apply request controls if needed */
+   if (src_buf->vb2_buf.req_obj.req)
+   v4l2_ctrl_request_setup(src_buf->vb2_buf.req_obj.req,
+   &ctx->hdl);
+
device_process(ctx, src_buf, dst_buf);
 
+   /* Complete request controls if needed */
+   if (src_buf->vb2_buf.req_obj.req)
+   v4l2_ctrl_request_complete(src_buf->vb2_buf.req_obj.req,
+   &ctx->hdl);
+
/* Run delayed work, which simulates a hardware irq  */
schedule_delayed_work(&dev->work_run, msecs_to_jiffies(ctx->transtime));
 }
@@ -809,12 +819,21 @@ static void vim2m_stop_streaming(struct vb2_queue *q)
vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
if (vbuf == NULL)
return;
+   v4l2_ctrl_request_complete(vbuf->vb2_buf.req_obj.req,
+  &ctx->hdl);
spin_lock_irqsave(&ctx->dev->irqlock, flags);
v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR);
spin_unlock_irqrestore(&ctx->dev->irqlock, flags);
}
 }
 
+static void vim2m_buf_request_complete(struct vb2_buffer *vb)
+{
+   struct vim2m_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+
+   v4l2_ctrl_request_complete(vb->req_obj.req, &ctx->hdl);
+}
+
 static const struct vb2_ops vim2m_qops = {
.queue_setup = vim2m_queue_setup,
.buf_prepare = vim2m_buf_prepare,
@@ -823,6 +842,7 @@ static const struct vb2_ops vim2m_qops = {
.stop_streaming  = vim2m_stop_streaming,
.wait_prepare= vb2_ops_wait_prepare,
.wait_finish = vb2_ops_wait_finish,
+   .buf_request_complete = vim2m_buf_request_complete,
 };
 
 static int queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue 
*dst_vq)
@@ -989,6 +1009,11 @@ static const struct v4l2_m2m_ops m2m_ops = {
.job_abort  = job_abort,
 };
 
+static const struct media_device_ops m2m_media_ops = {
+   .req_validate = vb2_request_validate,
+   .req_queue = vb2_m2m_request_queue,
+};
+
 static int vim2m_probe(struct platform_device *pdev)
 {
struct vim2m_dev *dev;
@@ -1013,6 +1038,7 @@ static int vim2m_probe(struct platform_device *pdev)
dev->mdev.dev = &pdev->dev;
strlcpy(dev->mdev.model, "vim2m", sizeof(dev->mdev.model));
media_device_init(&dev->mdev);
+   dev->mdev.ops = &m2m_media_ops;
dev->v4l2_dev.mdev = &dev->mdev;
dev->pad[0].flags = MEDIA_PAD_FL_SINK;
dev->pad[1].flags = MEDIA_PAD_FL_SOURCE;
-- 
2.17.0



[PATCHv15 13/35] v4l2-ctrls: add core request support

2018-06-04 Thread Hans Verkuil
From: Hans Verkuil 

Integrate the request support. This adds the v4l2_ctrl_request_complete
and v4l2_ctrl_request_setup functions to complete a request and (as a
helper function) to apply a request to the hardware.

It takes care of queuing requests and correctly chaining control values
in the request queue.

Note that when a request is marked completed it will copy control values
to the internal request state. This can be optimized in the future since
this is sub-optimal when dealing with large compound and/or array controls.

For the initial 'stateless codec' use-case the current implementation is
sufficient.

Signed-off-by: Hans Verkuil 
---
 drivers/media/v4l2-core/v4l2-ctrls.c | 331 ++-
 include/media/v4l2-ctrls.h   |  51 +
 2 files changed, 376 insertions(+), 6 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c 
b/drivers/media/v4l2-core/v4l2-ctrls.c
index da4cc1485dc4..bd4818507486 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
@@ -1647,6 +1647,13 @@ static int new_to_user(struct v4l2_ext_control *c,
return ptr_to_user(c, ctrl, ctrl->p_new);
 }
 
+/* Helper function: copy the request value back to the caller */
+static int req_to_user(struct v4l2_ext_control *c,
+  struct v4l2_ctrl_ref *ref)
+{
+   return ptr_to_user(c, ref->ctrl, ref->p_req);
+}
+
 /* Helper function: copy the initial control value back to the caller */
 static int def_to_user(struct v4l2_ext_control *c, struct v4l2_ctrl *ctrl)
 {
@@ -1766,6 +1773,26 @@ static void cur_to_new(struct v4l2_ctrl *ctrl)
ptr_to_ptr(ctrl, ctrl->p_cur, ctrl->p_new);
 }
 
+/* Copy the new value to the request value */
+static void new_to_req(struct v4l2_ctrl_ref *ref)
+{
+   if (!ref)
+   return;
+   ptr_to_ptr(ref->ctrl, ref->ctrl->p_new, ref->p_req);
+   ref->req = ref;
+}
+
+/* Copy the request value to the new value */
+static void req_to_new(struct v4l2_ctrl_ref *ref)
+{
+   if (!ref)
+   return;
+   if (ref->req)
+   ptr_to_ptr(ref->ctrl, ref->req->p_req, ref->ctrl->p_new);
+   else
+   ptr_to_ptr(ref->ctrl, ref->ctrl->p_cur, ref->ctrl->p_new);
+}
+
 /* Return non-zero if one or more of the controls in the cluster has a new
value that differs from the current value. */
 static int cluster_changed(struct v4l2_ctrl *master)
@@ -1875,6 +1902,9 @@ int v4l2_ctrl_handler_init_class(struct v4l2_ctrl_handler 
*hdl,
lockdep_set_class_and_name(hdl->lock, key, name);
INIT_LIST_HEAD(&hdl->ctrls);
INIT_LIST_HEAD(&hdl->ctrl_refs);
+   INIT_LIST_HEAD(&hdl->requests);
+   INIT_LIST_HEAD(&hdl->requests_queued);
+   hdl->request_is_queued = false;
hdl->nr_of_buckets = 1 + nr_of_controls_hint / 8;
hdl->buckets = kvmalloc_array(hdl->nr_of_buckets,
  sizeof(hdl->buckets[0]),
@@ -1895,6 +1925,14 @@ void v4l2_ctrl_handler_free(struct v4l2_ctrl_handler 
*hdl)
if (hdl == NULL || hdl->buckets == NULL)
return;
 
+   if (!hdl->req_obj.req && !list_empty(&hdl->requests)) {
+   struct v4l2_ctrl_handler *req, *next_req;
+
+   list_for_each_entry_safe(req, next_req, &hdl->requests, 
requests) {
+   media_request_object_unbind(&req->req_obj);
+   media_request_object_put(&req->req_obj);
+   }
+   }
mutex_lock(hdl->lock);
/* Free all nodes */
list_for_each_entry_safe(ref, next_ref, &hdl->ctrl_refs, node) {
@@ -2816,6 +2854,128 @@ int v4l2_querymenu(struct v4l2_ctrl_handler *hdl, 
struct v4l2_querymenu *qm)
 }
 EXPORT_SYMBOL(v4l2_querymenu);
 
+static int v4l2_ctrl_request_clone(struct v4l2_ctrl_handler *hdl,
+  const struct v4l2_ctrl_handler *from)
+{
+   struct v4l2_ctrl_ref *ref;
+   int err;
+
+   if (WARN_ON(!hdl || hdl == from))
+   return -EINVAL;
+
+   if (hdl->error)
+   return hdl->error;
+
+   WARN_ON(hdl->lock != &hdl->_lock);
+
+   mutex_lock(from->lock);
+   list_for_each_entry(ref, &from->ctrl_refs, node) {
+   struct v4l2_ctrl *ctrl = ref->ctrl;
+   struct v4l2_ctrl_ref *new_ref;
+
+   /* Skip refs inherited from other devices */
+   if (ref->from_other_dev)
+   continue;
+   /* And buttons */
+   if (ctrl->type == V4L2_CTRL_TYPE_BUTTON)
+   continue;
+   err = handler_new_ref(hdl, ctrl, &new_ref, false, true);
+   if (err) {
+   printk("%s: handler_new_ref on control %x (%s) returned 
%d\n", __func__, ctrl->id, ctrl->name, err);
+   err = 0;
+   continue;
+   }
+   if (err)
+   break;
+   }
+   mutex_unlock(from->lock)

[PATCHv15 15/35] vb2: store userspace data in vb2_v4l2_buffer

2018-06-04 Thread Hans Verkuil
From: Hans Verkuil 

The userspace-provided plane data needs to be stored in
vb2_v4l2_buffer. Currently this information is applied by
__fill_vb2_buffer() which is called by the core prepare_buf
and qbuf functions, but when using requests these functions
aren't called yet since the buffer won't be prepared until
the media request is actually queued.

In the meantime this information has to be stored somewhere
and vb2_v4l2_buffer is a good place for it.

The __fill_vb2_buffer callback now just copies the relevant
information from vb2_v4l2_buffer into the planes array.

Signed-off-by: Hans Verkuil 
---
 .../media/common/videobuf2/videobuf2-core.c   |  43 +--
 .../media/common/videobuf2/videobuf2-v4l2.c   | 327 ++
 drivers/media/dvb-core/dvb_vb2.c  |   3 +-
 include/media/videobuf2-core.h|   3 +-
 include/media/videobuf2-v4l2.h|   2 +
 5 files changed, 209 insertions(+), 169 deletions(-)

diff --git a/drivers/media/common/videobuf2/videobuf2-core.c 
b/drivers/media/common/videobuf2/videobuf2-core.c
index f32ec7342ef0..c25bad134ba3 100644
--- a/drivers/media/common/videobuf2/videobuf2-core.c
+++ b/drivers/media/common/videobuf2/videobuf2-core.c
@@ -967,20 +967,19 @@ EXPORT_SYMBOL_GPL(vb2_discard_done);
 /*
  * __prepare_mmap() - prepare an MMAP buffer
  */
-static int __prepare_mmap(struct vb2_buffer *vb, const void *pb)
+static int __prepare_mmap(struct vb2_buffer *vb)
 {
int ret = 0;
 
-   if (pb)
-   ret = call_bufop(vb->vb2_queue, fill_vb2_buffer,
-vb, pb, vb->planes);
+   ret = call_bufop(vb->vb2_queue, fill_vb2_buffer,
+vb, vb->planes);
return ret ? ret : call_vb_qop(vb, buf_prepare, vb);
 }
 
 /*
  * __prepare_userptr() - prepare a USERPTR buffer
  */
-static int __prepare_userptr(struct vb2_buffer *vb, const void *pb)
+static int __prepare_userptr(struct vb2_buffer *vb)
 {
struct vb2_plane planes[VB2_MAX_PLANES];
struct vb2_queue *q = vb->vb2_queue;
@@ -991,12 +990,10 @@ static int __prepare_userptr(struct vb2_buffer *vb, const 
void *pb)
 
memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
/* Copy relevant information provided by the userspace */
-   if (pb) {
-   ret = call_bufop(vb->vb2_queue, fill_vb2_buffer,
-vb, pb, planes);
-   if (ret)
-   return ret;
-   }
+   ret = call_bufop(vb->vb2_queue, fill_vb2_buffer,
+vb, planes);
+   if (ret)
+   return ret;
 
for (plane = 0; plane < vb->num_planes; ++plane) {
/* Skip the plane if already verified */
@@ -1096,7 +1093,7 @@ static int __prepare_userptr(struct vb2_buffer *vb, const 
void *pb)
 /*
  * __prepare_dmabuf() - prepare a DMABUF buffer
  */
-static int __prepare_dmabuf(struct vb2_buffer *vb, const void *pb)
+static int __prepare_dmabuf(struct vb2_buffer *vb)
 {
struct vb2_plane planes[VB2_MAX_PLANES];
struct vb2_queue *q = vb->vb2_queue;
@@ -1107,12 +1104,10 @@ static int __prepare_dmabuf(struct vb2_buffer *vb, 
const void *pb)
 
memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
/* Copy relevant information provided by the userspace */
-   if (pb) {
-   ret = call_bufop(vb->vb2_queue, fill_vb2_buffer,
-vb, pb, planes);
-   if (ret)
-   return ret;
-   }
+   ret = call_bufop(vb->vb2_queue, fill_vb2_buffer,
+vb, planes);
+   if (ret)
+   return ret;
 
for (plane = 0; plane < vb->num_planes; ++plane) {
struct dma_buf *dbuf = dma_buf_get(planes[plane].m.fd);
@@ -1241,7 +1236,7 @@ static void __enqueue_in_driver(struct vb2_buffer *vb)
call_void_vb_qop(vb, buf_queue, vb);
 }
 
-static int __buf_prepare(struct vb2_buffer *vb, const void *pb)
+static int __buf_prepare(struct vb2_buffer *vb)
 {
struct vb2_queue *q = vb->vb2_queue;
unsigned int plane;
@@ -1256,13 +1251,13 @@ static int __buf_prepare(struct vb2_buffer *vb, const 
void *pb)
 
switch (q->memory) {
case VB2_MEMORY_MMAP:
-   ret = __prepare_mmap(vb, pb);
+   ret = __prepare_mmap(vb);
break;
case VB2_MEMORY_USERPTR:
-   ret = __prepare_userptr(vb, pb);
+   ret = __prepare_userptr(vb);
break;
case VB2_MEMORY_DMABUF:
-   ret = __prepare_dmabuf(vb, pb);
+   ret = __prepare_dmabuf(vb);
break;
default:
WARN(1, "Invalid queue type\n");
@@ -1296,7 +1291,7 @@ int vb2_core_prepare_buf(struct vb2_queue *q, unsigned 
int index, void *pb)
return -EINVAL;
}
 
-   ret = __buf_prepare(vb, pb);
+   ret = __buf_prepare(vb);
if (ret)
return r

[PATCHv15 09/35] v4l2-ctrls: v4l2_ctrl_add_handler: add from_other_dev

2018-06-04 Thread Hans Verkuil
From: Hans Verkuil 

Add a 'bool from_other_dev' argument: set to true if the two
handlers refer to different devices (e.g. it is true when
inheriting controls from a subdev into a main v4l2 bridge
driver).

This will be used later when implementing support for the
request API since we need to skip such controls.

TODO: check drivers/staging/media/imx/imx-media-fim.c change.

Signed-off-by: Hans Verkuil 
Signed-off-by: Alexandre Courbot 
---
 drivers/media/dvb-frontends/rtl2832_sdr.c |  5 +-
 drivers/media/pci/bt8xx/bttv-driver.c |  2 +-
 drivers/media/pci/cx23885/cx23885-417.c   |  2 +-
 drivers/media/pci/cx88/cx88-blackbird.c   |  2 +-
 drivers/media/pci/cx88/cx88-video.c   |  2 +-
 drivers/media/pci/saa7134/saa7134-empress.c   |  4 +-
 drivers/media/pci/saa7134/saa7134-video.c |  2 +-
 .../media/platform/exynos4-is/fimc-capture.c  |  2 +-
 drivers/media/platform/rcar-vin/rcar-core.c   |  2 +-
 drivers/media/platform/rcar_drif.c|  2 +-
 .../media/platform/soc_camera/soc_camera.c|  3 +-
 drivers/media/platform/vivid/vivid-ctrls.c| 46 +--
 drivers/media/usb/cx231xx/cx231xx-417.c   |  2 +-
 drivers/media/usb/cx231xx/cx231xx-video.c |  4 +-
 drivers/media/usb/msi2500/msi2500.c   |  2 +-
 drivers/media/usb/tm6000/tm6000-video.c   |  2 +-
 drivers/media/v4l2-core/v4l2-ctrls.c  | 11 +++--
 drivers/media/v4l2-core/v4l2-device.c |  3 +-
 drivers/staging/media/imx/imx-media-dev.c |  2 +-
 drivers/staging/media/imx/imx-media-fim.c |  2 +-
 include/media/v4l2-ctrls.h|  8 +++-
 21 files changed, 61 insertions(+), 49 deletions(-)

diff --git a/drivers/media/dvb-frontends/rtl2832_sdr.c 
b/drivers/media/dvb-frontends/rtl2832_sdr.c
index c6e78d870ccd..6064d28224e8 100644
--- a/drivers/media/dvb-frontends/rtl2832_sdr.c
+++ b/drivers/media/dvb-frontends/rtl2832_sdr.c
@@ -1394,7 +1394,8 @@ static int rtl2832_sdr_probe(struct platform_device *pdev)
case RTL2832_SDR_TUNER_E4000:
v4l2_ctrl_handler_init(&dev->hdl, 9);
if (subdev)
-   v4l2_ctrl_add_handler(&dev->hdl, subdev->ctrl_handler, 
NULL);
+   v4l2_ctrl_add_handler(&dev->hdl, subdev->ctrl_handler,
+ NULL, true);
break;
case RTL2832_SDR_TUNER_R820T:
case RTL2832_SDR_TUNER_R828D:
@@ -1423,7 +1424,7 @@ static int rtl2832_sdr_probe(struct platform_device *pdev)
v4l2_ctrl_handler_init(&dev->hdl, 2);
if (subdev)
v4l2_ctrl_add_handler(&dev->hdl, subdev->ctrl_handler,
- NULL);
+ NULL, true);
break;
default:
v4l2_ctrl_handler_init(&dev->hdl, 0);
diff --git a/drivers/media/pci/bt8xx/bttv-driver.c 
b/drivers/media/pci/bt8xx/bttv-driver.c
index de3f44b8dec6..9341ef6e154f 100644
--- a/drivers/media/pci/bt8xx/bttv-driver.c
+++ b/drivers/media/pci/bt8xx/bttv-driver.c
@@ -4211,7 +4211,7 @@ static int bttv_probe(struct pci_dev *dev, const struct 
pci_device_id *pci_id)
/* register video4linux + input */
if (!bttv_tvcards[btv->c.type].no_video) {
v4l2_ctrl_add_handler(&btv->radio_ctrl_handler, hdl,
-   v4l2_ctrl_radio_filter);
+   v4l2_ctrl_radio_filter, false);
if (btv->radio_ctrl_handler.error) {
result = btv->radio_ctrl_handler.error;
goto fail2;
diff --git a/drivers/media/pci/cx23885/cx23885-417.c 
b/drivers/media/pci/cx23885/cx23885-417.c
index a71f3c7569ce..762823871c78 100644
--- a/drivers/media/pci/cx23885/cx23885-417.c
+++ b/drivers/media/pci/cx23885/cx23885-417.c
@@ -1527,7 +1527,7 @@ int cx23885_417_register(struct cx23885_dev *dev)
dev->cxhdl.priv = dev;
dev->cxhdl.func = cx23885_api_func;
cx2341x_handler_set_50hz(&dev->cxhdl, tsport->height == 576);
-   v4l2_ctrl_add_handler(&dev->ctrl_handler, &dev->cxhdl.hdl, NULL);
+   v4l2_ctrl_add_handler(&dev->ctrl_handler, &dev->cxhdl.hdl, NULL, false);
 
/* Allocate and initialize V4L video device */
dev->v4l_device = cx23885_video_dev_alloc(tsport,
diff --git a/drivers/media/pci/cx88/cx88-blackbird.c 
b/drivers/media/pci/cx88/cx88-blackbird.c
index 7a4876cf9f08..722dd101c9b0 100644
--- a/drivers/media/pci/cx88/cx88-blackbird.c
+++ b/drivers/media/pci/cx88/cx88-blackbird.c
@@ -1183,7 +1183,7 @@ static int cx8802_blackbird_probe(struct cx8802_driver 
*drv)
err = cx2341x_handler_init(&dev->cxhdl, 36);
if (err)
goto fail_core;
-   v4l2_ctrl_add_handler(&dev->cxhdl.hdl, &core->video_hdl, NULL);
+   v4l2_ctrl_add_handler(&dev->cxhdl.hdl, &core->video_hdl, NULL, false);
 
/* blackbird stuff */
pr_info("cx23416 based mpeg encode

[PATCHv15 19/35] vb2: add init_buffer buffer op

2018-06-04 Thread Hans Verkuil
From: Hans Verkuil 

We need to initialize the request_fd field in struct vb2_v4l2_buffer
to -1 instead of the default of 0. So we need to add a new op that
is called when struct vb2_v4l2_buffer is allocated.

Signed-off-by: Hans Verkuil 
---
 drivers/media/common/videobuf2/videobuf2-core.c | 2 ++
 include/media/videobuf2-core.h  | 4 
 2 files changed, 6 insertions(+)

diff --git a/drivers/media/common/videobuf2/videobuf2-core.c 
b/drivers/media/common/videobuf2/videobuf2-core.c
index 997673b62afc..a9e958df8324 100644
--- a/drivers/media/common/videobuf2/videobuf2-core.c
+++ b/drivers/media/common/videobuf2/videobuf2-core.c
@@ -356,6 +356,8 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum 
vb2_memory memory,
vb->planes[plane].length = plane_sizes[plane];
vb->planes[plane].min_length = plane_sizes[plane];
}
+   call_void_bufop(q, init_buffer, vb);
+
q->bufs[vb->index] = vb;
 
/* Allocate video buffer memory for the MMAP type */
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index 5e760d5f280a..cbda3968d018 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -408,6 +408,9 @@ struct vb2_ops {
  * @verify_planes_array: Verify that a given user space structure contains
  * enough planes for the buffer. This is called
  * for each dequeued buffer.
+ * @init_buffer:   given a &vb2_buffer initialize the extra data after
+ * struct vb2_buffer.
+ * For V4L2 this is a &struct vb2_v4l2_buffer.
  * @fill_user_buffer:  given a &vb2_buffer fill in the userspace structure.
  * For V4L2 this is a &struct v4l2_buffer.
  * @fill_vb2_buffer:   given a userspace structure, fill in the &vb2_buffer.
@@ -418,6 +421,7 @@ struct vb2_ops {
  */
 struct vb2_buf_ops {
int (*verify_planes_array)(struct vb2_buffer *vb, const void *pb);
+   void (*init_buffer)(struct vb2_buffer *vb);
void (*fill_user_buffer)(struct vb2_buffer *vb, void *pb);
int (*fill_vb2_buffer)(struct vb2_buffer *vb, struct vb2_plane *planes);
void (*copy_timestamp)(struct vb2_buffer *vb, const void *pb);
-- 
2.17.0



[PATCHv15 33/35] vivid: add mc

2018-06-04 Thread Hans Verkuil
From: Hans Verkuil 

Add support for the media_device to vivid. This is a prerequisite
for request support.

Signed-off-by: Hans Verkuil 
---
 drivers/media/platform/vivid/vivid-core.c | 61 +++
 drivers/media/platform/vivid/vivid-core.h |  8 +++
 2 files changed, 69 insertions(+)

diff --git a/drivers/media/platform/vivid/vivid-core.c 
b/drivers/media/platform/vivid/vivid-core.c
index 82ec216f2ad8..69386b26d5dd 100644
--- a/drivers/media/platform/vivid/vivid-core.c
+++ b/drivers/media/platform/vivid/vivid-core.c
@@ -657,6 +657,15 @@ static int vivid_create_instance(struct platform_device 
*pdev, int inst)
 
dev->inst = inst;
 
+#ifdef CONFIG_MEDIA_CONTROLLER
+   dev->v4l2_dev.mdev = &dev->mdev;
+
+   /* Initialize media device */
+   strlcpy(dev->mdev.model, VIVID_MODULE_NAME, sizeof(dev->mdev.model));
+   dev->mdev.dev = &pdev->dev;
+   media_device_init(&dev->mdev);
+#endif
+
/* register v4l2_device */
snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name),
"%s-%03d", VIVID_MODULE_NAME, inst);
@@ -1173,6 +1182,13 @@ static int vivid_create_instance(struct platform_device 
*pdev, int inst)
vfd->lock = &dev->mutex;
video_set_drvdata(vfd, dev);
 
+#ifdef CONFIG_MEDIA_CONTROLLER
+   dev->vid_cap_pad.flags = MEDIA_PAD_FL_SINK;
+   ret = media_entity_pads_init(&vfd->entity, 1, 
&dev->vid_cap_pad);
+   if (ret)
+   goto unreg_dev;
+#endif
+
 #ifdef CONFIG_VIDEO_VIVID_CEC
if (in_type_counter[HDMI]) {
struct cec_adapter *adap;
@@ -1225,6 +1241,13 @@ static int vivid_create_instance(struct platform_device 
*pdev, int inst)
vfd->lock = &dev->mutex;
video_set_drvdata(vfd, dev);
 
+#ifdef CONFIG_MEDIA_CONTROLLER
+   dev->vid_out_pad.flags = MEDIA_PAD_FL_SOURCE;
+   ret = media_entity_pads_init(&vfd->entity, 1, 
&dev->vid_out_pad);
+   if (ret)
+   goto unreg_dev;
+#endif
+
 #ifdef CONFIG_VIDEO_VIVID_CEC
for (i = 0; i < dev->num_outputs; i++) {
struct cec_adapter *adap;
@@ -1274,6 +1297,13 @@ static int vivid_create_instance(struct platform_device 
*pdev, int inst)
vfd->tvnorms = tvnorms_cap;
video_set_drvdata(vfd, dev);
 
+#ifdef CONFIG_MEDIA_CONTROLLER
+   dev->vbi_cap_pad.flags = MEDIA_PAD_FL_SINK;
+   ret = media_entity_pads_init(&vfd->entity, 1, 
&dev->vbi_cap_pad);
+   if (ret)
+   goto unreg_dev;
+#endif
+
ret = video_register_device(vfd, VFL_TYPE_VBI, 
vbi_cap_nr[inst]);
if (ret < 0)
goto unreg_dev;
@@ -1299,6 +1329,13 @@ static int vivid_create_instance(struct platform_device 
*pdev, int inst)
vfd->tvnorms = tvnorms_out;
video_set_drvdata(vfd, dev);
 
+#ifdef CONFIG_MEDIA_CONTROLLER
+   dev->vbi_out_pad.flags = MEDIA_PAD_FL_SOURCE;
+   ret = media_entity_pads_init(&vfd->entity, 1, 
&dev->vbi_out_pad);
+   if (ret)
+   goto unreg_dev;
+#endif
+
ret = video_register_device(vfd, VFL_TYPE_VBI, 
vbi_out_nr[inst]);
if (ret < 0)
goto unreg_dev;
@@ -1322,6 +1359,13 @@ static int vivid_create_instance(struct platform_device 
*pdev, int inst)
vfd->lock = &dev->mutex;
video_set_drvdata(vfd, dev);
 
+#ifdef CONFIG_MEDIA_CONTROLLER
+   dev->sdr_cap_pad.flags = MEDIA_PAD_FL_SINK;
+   ret = media_entity_pads_init(&vfd->entity, 1, 
&dev->sdr_cap_pad);
+   if (ret)
+   goto unreg_dev;
+#endif
+
ret = video_register_device(vfd, VFL_TYPE_SDR, 
sdr_cap_nr[inst]);
if (ret < 0)
goto unreg_dev;
@@ -1368,12 +1412,25 @@ static int vivid_create_instance(struct platform_device 
*pdev, int inst)
  video_device_node_name(vfd));
}
 
+#ifdef CONFIG_MEDIA_CONTROLLER
+   /* Register the media device */
+   ret = media_device_register(&dev->mdev);
+   if (ret) {
+   dev_err(dev->mdev.dev,
+   "media device register failed (err=%d)\n", ret);
+   goto unreg_dev;
+   }
+#endif
+
/* Now that everything is fine, let's add it to device list */
vivid_devs[inst] = dev;
 
return 0;
 
 unreg_dev:
+#ifdef CONFIG_MEDIA_CONTROLLER
+   media_device_unregister(&dev->mdev);
+#endif
video_unregister_device(&dev->radio_tx_dev);
video_unregister_device(&dev->radio_rx_dev);
video_unregister_device(&dev->sdr_cap_dev);
@@ -1444,6 +1501,10 @@ static int vivid_remove(struct platform_device *pdev)
if (!dev)
c

[PATCHv15 20/35] videobuf2-core: embed media_request_object

2018-06-04 Thread Hans Verkuil
From: Hans Verkuil 

Make vb2_buffer a request object.

Signed-off-by: Hans Verkuil 
---
 include/media/videobuf2-core.h | 4 
 1 file changed, 4 insertions(+)

diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index cbda3968d018..df92dcdeabb3 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -17,6 +17,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #define VB2_MAX_FRAME  (32)
 #define VB2_MAX_PLANES (8)
@@ -236,6 +237,8 @@ struct vb2_queue;
  * @num_planes:number of planes in the buffer
  * on an internal driver queue.
  * @timestamp: frame timestamp in ns.
+ * @req_obj:   used to bind this buffer to a request. This
+ * request object has a refcount.
  */
 struct vb2_buffer {
struct vb2_queue*vb2_queue;
@@ -244,6 +247,7 @@ struct vb2_buffer {
unsigned intmemory;
unsigned intnum_planes;
u64 timestamp;
+   struct media_request_object req_obj;
 
/* private: internal use only
 *
-- 
2.17.0



[PATCHv15 14/35] v4l2-ctrls: support g/s_ext_ctrls for requests

2018-06-04 Thread Hans Verkuil
From: Hans Verkuil 

The v4l2_g/s_ext_ctrls functions now support control handlers that
represent requests.

The v4l2_ctrls_find_req_obj() function is responsible for finding the
request from the fd.

Signed-off-by: Hans Verkuil 
---
 drivers/media/platform/omap3isp/ispvideo.c |   2 +-
 drivers/media/v4l2-core/v4l2-ctrls.c   | 128 +++--
 drivers/media/v4l2-core/v4l2-ioctl.c   |  12 +-
 drivers/media/v4l2-core/v4l2-subdev.c  |   9 +-
 include/media/v4l2-ctrls.h |   7 +-
 5 files changed, 139 insertions(+), 19 deletions(-)

diff --git a/drivers/media/platform/omap3isp/ispvideo.c 
b/drivers/media/platform/omap3isp/ispvideo.c
index 9d228eac24ea..674e7fd3ad99 100644
--- a/drivers/media/platform/omap3isp/ispvideo.c
+++ b/drivers/media/platform/omap3isp/ispvideo.c
@@ -1028,7 +1028,7 @@ static int isp_video_check_external_subdevs(struct 
isp_video *video,
ctrls.count = 1;
ctrls.controls = &ctrl;
 
-   ret = v4l2_g_ext_ctrls(pipe->external->ctrl_handler, &ctrls);
+   ret = v4l2_g_ext_ctrls(pipe->external->ctrl_handler, NULL, &ctrls);
if (ret < 0) {
dev_warn(isp->dev, "no pixel rate control in subdev %s\n",
 pipe->external->name);
diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c 
b/drivers/media/v4l2-core/v4l2-ctrls.c
index bd4818507486..ab5e8827fde0 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
@@ -3124,7 +3124,8 @@ static int class_check(struct v4l2_ctrl_handler *hdl, u32 
which)
 }
 
 /* Get extended controls. Allocates the helpers array if needed. */
-int v4l2_g_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct v4l2_ext_controls 
*cs)
+int __v4l2_g_ext_ctrls(struct v4l2_ctrl_handler *hdl,
+  struct v4l2_ext_controls *cs)
 {
struct v4l2_ctrl_helper helper[4];
struct v4l2_ctrl_helper *helpers = helper;
@@ -3204,6 +3205,77 @@ int v4l2_g_ext_ctrls(struct v4l2_ctrl_handler *hdl, 
struct v4l2_ext_controls *cs
kvfree(helpers);
return ret;
 }
+
+static struct media_request_object *
+v4l2_ctrls_find_req_obj(struct v4l2_ctrl_handler *hdl,
+   struct media_request *req, bool set)
+{
+   struct media_request_object *obj;
+   struct v4l2_ctrl_handler *new_hdl;
+   int ret;
+
+   if (IS_ERR(req))
+   return ERR_CAST(req);
+
+   if (set && WARN_ON(req->state != MEDIA_REQUEST_STATE_UPDATING))
+   return ERR_PTR(-EBUSY);
+
+   obj = media_request_object_find(req, &req_ops, hdl);
+   if (obj)
+   return obj;
+   if (!set)
+   return ERR_PTR(-ENOENT);
+
+   new_hdl = kzalloc(sizeof(*new_hdl), GFP_KERNEL);
+   if (!new_hdl)
+   return ERR_PTR(-ENOMEM);
+
+   obj = &new_hdl->req_obj;
+   ret = v4l2_ctrl_handler_init(new_hdl, (hdl->nr_of_buckets - 1) * 8);
+   if (!ret)
+   ret = v4l2_ctrl_request_bind(req, new_hdl, hdl);
+   if (ret) {
+   kfree(new_hdl);
+
+   return ERR_PTR(ret);
+   }
+
+   media_request_object_get(obj);
+   return obj;
+}
+
+int v4l2_g_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct media_device *mdev,
+struct v4l2_ext_controls *cs)
+{
+   struct media_request_object *obj = NULL;
+   int ret;
+
+   if (cs->which == V4L2_CTRL_WHICH_REQUEST_VAL) {
+   struct media_request *req;
+
+   if (!mdev || cs->request_fd < 0)
+   return -EINVAL;
+
+   req = media_request_get_by_fd(mdev, cs->request_fd);
+   if (IS_ERR(req))
+   return PTR_ERR(req);
+
+   obj = v4l2_ctrls_find_req_obj(hdl, req, false);
+   /* Reference to the request held through obj */
+   media_request_put(req);
+   if (IS_ERR(obj))
+   return PTR_ERR(obj);
+
+   hdl = container_of(obj, struct v4l2_ctrl_handler,
+  req_obj);
+   }
+
+   ret = __v4l2_g_ext_ctrls(hdl, cs);
+
+   if (obj)
+   media_request_object_put(obj);
+   return ret;
+}
 EXPORT_SYMBOL(v4l2_g_ext_ctrls);
 
 /* Helper function to get a single control */
@@ -3379,9 +3451,9 @@ static void update_from_auto_cluster(struct v4l2_ctrl 
*master)
 }
 
 /* Try or try-and-set controls */
-static int try_set_ext_ctrls(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl,
-struct v4l2_ext_controls *cs,
-bool set)
+static int __try_set_ext_ctrls(struct v4l2_fh *fh,
+  struct v4l2_ctrl_handler *hdl,
+  struct v4l2_ext_controls *cs, bool set)
 {
struct v4l2_ctrl_helper helper[4];
struct v4l2_ctrl_helper *helpers = helper;
@@ -3494,16 +3566,56 @@ static int try_set_ext_ctrls(struct v4l2_fh *fh, struct 
v4l2_ctrl_handler *hdl,

[PATCHv15 16/35] davinci_vpfe: remove bogus vb2->state check

2018-06-04 Thread Hans Verkuil
From: Hans Verkuil 

There is no need to check the vb2 state in the buf_prepare
callback: it can never be wrong.

Since VB2_BUF_STATE_PREPARED will be removed in the next patch
we'll remove this unnecessary check (and use of that state) first.

Signed-off-by: Hans Verkuil 
---
 drivers/staging/media/davinci_vpfe/vpfe_video.c | 4 
 1 file changed, 4 deletions(-)

diff --git a/drivers/staging/media/davinci_vpfe/vpfe_video.c 
b/drivers/staging/media/davinci_vpfe/vpfe_video.c
index 390fc98d07dd..edcb07bf653c 100644
--- a/drivers/staging/media/davinci_vpfe/vpfe_video.c
+++ b/drivers/staging/media/davinci_vpfe/vpfe_video.c
@@ -1135,10 +1135,6 @@ static int vpfe_buffer_prepare(struct vb2_buffer *vb)
 
v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_buffer_prepare\n");
 
-   if (vb->state != VB2_BUF_STATE_ACTIVE &&
-   vb->state != VB2_BUF_STATE_PREPARED)
-   return 0;
-
/* Initialize buffer */
vb2_set_plane_payload(vb, 0, video->fmt.fmt.pix.sizeimage);
if (vb2_plane_vaddr(vb, 0) &&
-- 
2.17.0



[PATCHv15 27/35] v4l2-mem2mem: Simplify exiting the function in v4l2_m2m_try_schedule

2018-06-04 Thread Hans Verkuil
From: Sakari Ailus 

The v4l2_m2m_try_schedule function acquires and releases multiple
spinlocks; simplify unlocking the job lock by adding a label to unlock the
job lock and exit the function.

Signed-off-by: Sakari Ailus 
---
 drivers/media/v4l2-core/v4l2-mem2mem.c | 22 --
 1 file changed, 12 insertions(+), 10 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-mem2mem.c 
b/drivers/media/v4l2-core/v4l2-mem2mem.c
index 438f1b869319..88f95b78e4d0 100644
--- a/drivers/media/v4l2-core/v4l2-mem2mem.c
+++ b/drivers/media/v4l2-core/v4l2-mem2mem.c
@@ -231,15 +231,13 @@ void v4l2_m2m_try_schedule(struct v4l2_m2m_ctx *m2m_ctx)
 
/* If the context is aborted then don't schedule it */
if (m2m_ctx->job_flags & TRANS_ABORT) {
-   spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags_job);
dprintk("Aborted context\n");
-   return;
+   goto out_unlock;
}
 
if (m2m_ctx->job_flags & TRANS_QUEUED) {
-   spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags_job);
dprintk("On job queue already\n");
-   return;
+   goto out_unlock;
}
 
spin_lock_irqsave(&m2m_ctx->out_q_ctx.rdy_spinlock, flags_out);
@@ -247,9 +245,8 @@ void v4l2_m2m_try_schedule(struct v4l2_m2m_ctx *m2m_ctx)
&& !m2m_ctx->out_q_ctx.buffered) {
spin_unlock_irqrestore(&m2m_ctx->out_q_ctx.rdy_spinlock,
flags_out);
-   spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags_job);
dprintk("No input buffers available\n");
-   return;
+   goto out_unlock;
}
spin_lock_irqsave(&m2m_ctx->cap_q_ctx.rdy_spinlock, flags_cap);
if (list_empty(&m2m_ctx->cap_q_ctx.rdy_queue)
@@ -258,18 +255,16 @@ void v4l2_m2m_try_schedule(struct v4l2_m2m_ctx *m2m_ctx)
flags_cap);
spin_unlock_irqrestore(&m2m_ctx->out_q_ctx.rdy_spinlock,
flags_out);
-   spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags_job);
dprintk("No output buffers available\n");
-   return;
+   goto out_unlock;
}
spin_unlock_irqrestore(&m2m_ctx->cap_q_ctx.rdy_spinlock, flags_cap);
spin_unlock_irqrestore(&m2m_ctx->out_q_ctx.rdy_spinlock, flags_out);
 
if (m2m_dev->m2m_ops->job_ready
&& (!m2m_dev->m2m_ops->job_ready(m2m_ctx->priv))) {
-   spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags_job);
dprintk("Driver not ready\n");
-   return;
+   goto out_unlock;
}
 
list_add_tail(&m2m_ctx->queue, &m2m_dev->job_queue);
@@ -278,6 +273,13 @@ void v4l2_m2m_try_schedule(struct v4l2_m2m_ctx *m2m_ctx)
spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags_job);
 
v4l2_m2m_try_run(m2m_dev);
+
+   return;
+
+out_unlock:
+   spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags_job);
+
+   return;
 }
 EXPORT_SYMBOL_GPL(v4l2_m2m_try_schedule);
 
-- 
2.17.0



[PATCHv15 21/35] videobuf2-core: integrate with media requests

2018-06-04 Thread Hans Verkuil
From: Hans Verkuil 

Buffers can now be prepared or queued for a request.

A buffer is unbound from the request at vb2_buffer_done time or
when the queue is cancelled.

Signed-off-by: Hans Verkuil 
---
 .../media/common/videobuf2/videobuf2-core.c   | 133 +-
 .../media/common/videobuf2/videobuf2-v4l2.c   |   4 +-
 drivers/media/dvb-core/dvb_vb2.c  |   2 +-
 include/media/videobuf2-core.h|  18 ++-
 4 files changed, 147 insertions(+), 10 deletions(-)

diff --git a/drivers/media/common/videobuf2/videobuf2-core.c 
b/drivers/media/common/videobuf2/videobuf2-core.c
index a9e958df8324..6d423bc5a1a1 100644
--- a/drivers/media/common/videobuf2/videobuf2-core.c
+++ b/drivers/media/common/videobuf2/videobuf2-core.c
@@ -499,8 +499,9 @@ static int __vb2_queue_free(struct vb2_queue *q, unsigned 
int buffers)
pr_info(" buf_init: %u buf_cleanup: %u buf_prepare: 
%u buf_finish: %u\n",
vb->cnt_buf_init, vb->cnt_buf_cleanup,
vb->cnt_buf_prepare, vb->cnt_buf_finish);
-   pr_info(" buf_queue: %u buf_done: %u\n",
-   vb->cnt_buf_queue, vb->cnt_buf_done);
+   pr_info(" buf_queue: %u buf_done: %u 
buf_request_complete: %u\n",
+   vb->cnt_buf_queue, vb->cnt_buf_done,
+   vb->cnt_buf_request_complete);
pr_info(" alloc: %u put: %u prepare: %u finish: %u 
mmap: %u\n",
vb->cnt_mem_alloc, vb->cnt_mem_put,
vb->cnt_mem_prepare, vb->cnt_mem_finish,
@@ -936,6 +937,14 @@ void vb2_buffer_done(struct vb2_buffer *vb, enum 
vb2_buffer_state state)
vb->state = state;
}
atomic_dec(&q->owned_by_drv_count);
+
+   if (vb->req_obj.req) {
+   /* This is not supported at the moment */
+   WARN_ON(state == VB2_BUF_STATE_REQUEUEING);
+   media_request_object_unbind(&vb->req_obj);
+   media_request_object_put(&vb->req_obj);
+   }
+
spin_unlock_irqrestore(&q->done_lock, flags);
 
trace_vb2_buf_done(q, vb);
@@ -1290,6 +1299,60 @@ static int __buf_prepare(struct vb2_buffer *vb)
return 0;
 }
 
+static int vb2_req_prepare(struct media_request_object *obj)
+{
+   struct vb2_buffer *vb = container_of(obj, struct vb2_buffer, req_obj);
+   int ret;
+
+   if (WARN_ON(vb->state != VB2_BUF_STATE_IN_REQUEST))
+   return -EINVAL;
+
+   mutex_lock(vb->vb2_queue->lock);
+   ret = __buf_prepare(vb);
+   mutex_unlock(vb->vb2_queue->lock);
+   return ret;
+}
+
+static void __vb2_dqbuf(struct vb2_buffer *vb);
+
+static void vb2_req_unprepare(struct media_request_object *obj)
+{
+   struct vb2_buffer *vb = container_of(obj, struct vb2_buffer, req_obj);
+
+   mutex_lock(vb->vb2_queue->lock);
+   __vb2_dqbuf(vb);
+   vb->state = VB2_BUF_STATE_IN_REQUEST;
+   mutex_unlock(vb->vb2_queue->lock);
+   WARN_ON(!vb->req_obj.req);
+}
+
+int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb,
+ struct media_request *req);
+
+static void vb2_req_queue(struct media_request_object *obj)
+{
+   struct vb2_buffer *vb = container_of(obj, struct vb2_buffer, req_obj);
+
+   mutex_lock(vb->vb2_queue->lock);
+   vb2_core_qbuf(vb->vb2_queue, vb->index, NULL, NULL);
+   mutex_unlock(vb->vb2_queue->lock);
+}
+
+static void vb2_req_release(struct media_request_object *obj)
+{
+   struct vb2_buffer *vb = container_of(obj, struct vb2_buffer, req_obj);
+
+   if (vb->state == VB2_BUF_STATE_IN_REQUEST)
+   vb->state = VB2_BUF_STATE_DEQUEUED;
+}
+
+static const struct media_request_object_ops vb2_core_req_ops = {
+   .prepare = vb2_req_prepare,
+   .unprepare = vb2_req_unprepare,
+   .queue = vb2_req_queue,
+   .release = vb2_req_release,
+};
+
 int vb2_core_prepare_buf(struct vb2_queue *q, unsigned int index, void *pb)
 {
struct vb2_buffer *vb;
@@ -1315,7 +1378,7 @@ int vb2_core_prepare_buf(struct vb2_queue *q, unsigned 
int index, void *pb)
 
dprintk(2, "prepare of buffer %d succeeded\n", vb->index);
 
-   return ret;
+   return 0;
 }
 EXPORT_SYMBOL_GPL(vb2_core_prepare_buf);
 
@@ -1382,15 +1445,47 @@ static int vb2_start_streaming(struct vb2_queue *q)
return ret;
 }
 
-int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb)
+int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb,
+ struct media_request *req)
 {
struct vb2_buffer *vb;
int ret;
 
vb = q->bufs[index];
 
+   if (req) {
+   int ret;
+
+   if (vb->state != VB2_BUF_STATE_DEQUEUED) {
+   dprintk(1, "buffer %d not in dequeued state\n",
+   vb->index);
+  

[PATCHv15 29/35] Documentation: v4l: document request API

2018-06-04 Thread Hans Verkuil
From: Alexandre Courbot 

Document the request API for V4L2 devices, and amend the documentation
of system calls influenced by it.

Signed-off-by: Alexandre Courbot 
Signed-off-by: Hans Verkuil 
---
 .../media/uapi/mediactl/media-controller.rst  |   1 +
 .../media/uapi/mediactl/media-funcs.rst   |   3 +
 .../uapi/mediactl/media-ioc-request-alloc.rst |  71 ++
 .../uapi/mediactl/media-request-ioc-queue.rst |  50 
 .../mediactl/media-request-ioc-reinit.rst |  51 
 .../media/uapi/mediactl/request-api.rst   | 219 ++
 Documentation/media/uapi/v4l/buffer.rst   |  18 +-
 .../media/uapi/v4l/vidioc-g-ext-ctrls.rst |  28 ++-
 Documentation/media/uapi/v4l/vidioc-qbuf.rst  |  11 +
 .../media/videodev2.h.rst.exceptions  |   1 +
 10 files changed, 447 insertions(+), 6 deletions(-)
 create mode 100644 
Documentation/media/uapi/mediactl/media-ioc-request-alloc.rst
 create mode 100644 
Documentation/media/uapi/mediactl/media-request-ioc-queue.rst
 create mode 100644 
Documentation/media/uapi/mediactl/media-request-ioc-reinit.rst
 create mode 100644 Documentation/media/uapi/mediactl/request-api.rst

diff --git a/Documentation/media/uapi/mediactl/media-controller.rst 
b/Documentation/media/uapi/mediactl/media-controller.rst
index 0eea4f9a07d5..66aff38cd499 100644
--- a/Documentation/media/uapi/mediactl/media-controller.rst
+++ b/Documentation/media/uapi/mediactl/media-controller.rst
@@ -21,6 +21,7 @@ Part IV - Media Controller API
 media-controller-intro
 media-controller-model
 media-types
+request-api
 media-funcs
 media-header
 
diff --git a/Documentation/media/uapi/mediactl/media-funcs.rst 
b/Documentation/media/uapi/mediactl/media-funcs.rst
index 076856501cdb..f4da9b3e17ec 100644
--- a/Documentation/media/uapi/mediactl/media-funcs.rst
+++ b/Documentation/media/uapi/mediactl/media-funcs.rst
@@ -16,3 +16,6 @@ Function Reference
 media-ioc-enum-entities
 media-ioc-enum-links
 media-ioc-setup-link
+media-ioc-request-alloc
+media-request-ioc-queue
+media-request-ioc-reinit
diff --git a/Documentation/media/uapi/mediactl/media-ioc-request-alloc.rst 
b/Documentation/media/uapi/mediactl/media-ioc-request-alloc.rst
new file mode 100644
index ..d45a94c9e23c
--- /dev/null
+++ b/Documentation/media/uapi/mediactl/media-ioc-request-alloc.rst
@@ -0,0 +1,71 @@
+.. SPDX-License-Identifier: GPL-2.0-only
+
+.. _media_ioc_request_alloc:
+
+*
+ioctl MEDIA_IOC_REQUEST_ALLOC
+*
+
+Name
+
+
+MEDIA_IOC_REQUEST_ALLOC - Allocate a request
+
+
+Synopsis
+
+
+.. c:function:: int ioctl( int fd, MEDIA_IOC_REQUEST_ALLOC, struct 
media_request_alloc *argp )
+:name: MEDIA_IOC_REQUEST_ALLOC
+
+
+Arguments
+=
+
+``fd``
+File descriptor returned by :ref:`open() `.
+
+``argp``
+
+
+Description
+===
+
+If the media device supports :ref:`requests `, then
+this ioctl can be used to allocate a request. A request is accessed through
+a file descriptor that is returned in struct :c:type:`media_request_alloc`.
+
+If the request was successfully allocated, then the request file descriptor
+can be passed to :ref:`ioctl VIDIOC_QBUF `,
+:ref:`ioctl VIDIOC_G_EXT_CTRLS `,
+:ref:`ioctl VIDIOC_S_EXT_CTRLS ` and
+:ref:`ioctl VIDIOC_TRY_EXT_CTRLS `.
+
+In addition, the request can be queued by calling
+:ref:`MEDIA_REQUEST_IOC_QUEUE` and re-initialized by calling
+:ref:`MEDIA_REQUEST_IOC_REINIT`.
+
+Finally, the file descriptor can be polled to wait for the request to
+complete.
+
+To free the request the file descriptor has to be closed.
+
+.. c:type:: media_request_alloc
+
+.. tabularcolumns:: |p{4.4cm}|p{4.4cm}|p{8.7cm}|
+
+.. flat-table:: struct media_request_alloc
+:header-rows:  0
+:stub-columns: 0
+:widths:   1 1 2
+
+*  -  __s32
+   -  ``fd``
+   -  The file descriptor of the request.
+
+Return Value
+
+
+On success 0 is returned, on error -1 and the ``errno`` variable is set
+appropriately. The generic error codes are described at the
+:ref:`Generic Error Codes ` chapter.
diff --git a/Documentation/media/uapi/mediactl/media-request-ioc-queue.rst 
b/Documentation/media/uapi/mediactl/media-request-ioc-queue.rst
new file mode 100644
index ..d3bac7b70422
--- /dev/null
+++ b/Documentation/media/uapi/mediactl/media-request-ioc-queue.rst
@@ -0,0 +1,50 @@
+.. SPDX-License-Identifier: GPL-2.0-only
+
+.. _media_request_ioc_queue:
+
+*
+ioctl MEDIA_REQUEST_IOC_QUEUE
+*
+
+Name
+
+
+MEDIA_REQUEST_IOC_QUEUE - Queue a request
+
+
+Synopsis
+
+
+.. c:function:: int ioctl( int request_fd, MEDIA_REQUEST_IOC_QUEUE )
+:name: MEDIA_REQUEST_IOC_QUEUE
+
+
+Arguments
+=
+
+``request_fd``
+File descriptor returned by :ref:`MEDIA_IOC_REQUEST_ALLOC`.
+
+
+Description
+===
+
+If the media device supports :ref:`requests `, then
+this request ioctl ca

[PATCHv15 12/35] v4l2-ctrls: use ref in helper instead of ctrl

2018-06-04 Thread Hans Verkuil
From: Hans Verkuil 

The next patch needs the reference to a control instead of the
control itself, so change struct v4l2_ctrl_helper accordingly.

Signed-off-by: Hans Verkuil 
---
 drivers/media/v4l2-core/v4l2-ctrls.c | 18 +-
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c 
b/drivers/media/v4l2-core/v4l2-ctrls.c
index 3c1b00baa8d0..da4cc1485dc4 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
@@ -37,8 +37,8 @@
 struct v4l2_ctrl_helper {
/* Pointer to the control reference of the master control */
struct v4l2_ctrl_ref *mref;
-   /* The control corresponding to the v4l2_ext_control ID field. */
-   struct v4l2_ctrl *ctrl;
+   /* The control ref corresponding to the v4l2_ext_control ID field. */
+   struct v4l2_ctrl_ref *ref;
/* v4l2_ext_control index of the next control belonging to the
   same cluster, or 0 if there isn't any. */
u32 next;
@@ -2887,6 +2887,7 @@ static int prepare_ext_ctrls(struct v4l2_ctrl_handler 
*hdl,
ref = find_ref_lock(hdl, id);
if (ref == NULL)
return -EINVAL;
+   h->ref = ref;
ctrl = ref->ctrl;
if (ctrl->flags & V4L2_CTRL_FLAG_DISABLED)
return -EINVAL;
@@ -2909,7 +2910,6 @@ static int prepare_ext_ctrls(struct v4l2_ctrl_handler 
*hdl,
}
/* Store the ref to the master control of the cluster */
h->mref = ref;
-   h->ctrl = ctrl;
/* Initially set next to 0, meaning that there is no other
   control in this helper array belonging to the same
   cluster */
@@ -2994,7 +2994,7 @@ int v4l2_g_ext_ctrls(struct v4l2_ctrl_handler *hdl, 
struct v4l2_ext_controls *cs
cs->error_idx = cs->count;
 
for (i = 0; !ret && i < cs->count; i++)
-   if (helpers[i].ctrl->flags & V4L2_CTRL_FLAG_WRITE_ONLY)
+   if (helpers[i].ref->ctrl->flags & V4L2_CTRL_FLAG_WRITE_ONLY)
ret = -EACCES;
 
for (i = 0; !ret && i < cs->count; i++) {
@@ -3029,7 +3029,7 @@ int v4l2_g_ext_ctrls(struct v4l2_ctrl_handler *hdl, 
struct v4l2_ext_controls *cs
 
do {
ret = ctrl_to_user(cs->controls + idx,
-  helpers[idx].ctrl);
+  helpers[idx].ref->ctrl);
idx = helpers[idx].next;
} while (!ret && idx);
}
@@ -3168,7 +3168,7 @@ static int validate_ctrls(struct v4l2_ext_controls *cs,
 
cs->error_idx = cs->count;
for (i = 0; i < cs->count; i++) {
-   struct v4l2_ctrl *ctrl = helpers[i].ctrl;
+   struct v4l2_ctrl *ctrl = helpers[i].ref->ctrl;
union v4l2_ctrl_ptr p_new;
 
cs->error_idx = i;
@@ -3280,7 +3280,7 @@ static int try_set_ext_ctrls(struct v4l2_fh *fh, struct 
v4l2_ctrl_handler *hdl,
do {
/* Check if the auto control is part of the
   list, and remember the new value. */
-   if (helpers[tmp_idx].ctrl == master)
+   if (helpers[tmp_idx].ref->ctrl == master)
new_auto_val = 
cs->controls[tmp_idx].value;
tmp_idx = helpers[tmp_idx].next;
} while (tmp_idx);
@@ -3293,7 +3293,7 @@ static int try_set_ext_ctrls(struct v4l2_fh *fh, struct 
v4l2_ctrl_handler *hdl,
/* Copy the new caller-supplied control values.
   user_to_new() sets 'is_new' to 1. */
do {
-   struct v4l2_ctrl *ctrl = helpers[idx].ctrl;
+   struct v4l2_ctrl *ctrl = helpers[idx].ref->ctrl;
 
ret = user_to_new(cs->controls + idx, ctrl);
if (!ret && ctrl->is_ptr)
@@ -3309,7 +3309,7 @@ static int try_set_ext_ctrls(struct v4l2_fh *fh, struct 
v4l2_ctrl_handler *hdl,
idx = i;
do {
ret = new_to_user(cs->controls + idx,
-   helpers[idx].ctrl);
+   helpers[idx].ref->ctrl);
idx = helpers[idx].next;
} while (!ret && idx);
}
-- 
2.17.0



[PATCHv15 01/35] uapi/linux/media.h: add request API

2018-06-04 Thread Hans Verkuil
From: Hans Verkuil 

Define the public request API.

This adds the new MEDIA_IOC_REQUEST_ALLOC ioctl to allocate a request
and two ioctls that operate on a request in order to queue the
contents of the request to the driver and to re-initialize the
request.

Signed-off-by: Hans Verkuil 
Acked-by: Sakari Ailus 
Reviewed-by: Laurent Pinchart 
---
 include/uapi/linux/media.h | 12 
 1 file changed, 12 insertions(+)

diff --git a/include/uapi/linux/media.h b/include/uapi/linux/media.h
index c7e9a5cba24e..0f0117742fa7 100644
--- a/include/uapi/linux/media.h
+++ b/include/uapi/linux/media.h
@@ -342,11 +342,23 @@ struct media_v2_topology {
 
 /* ioctls */
 
+struct __attribute__ ((packed)) media_request_alloc {
+   __s32 fd;
+};
+
 #define MEDIA_IOC_DEVICE_INFO  _IOWR('|', 0x00, struct media_device_info)
 #define MEDIA_IOC_ENUM_ENTITIES_IOWR('|', 0x01, struct 
media_entity_desc)
 #define MEDIA_IOC_ENUM_LINKS   _IOWR('|', 0x02, struct media_links_enum)
 #define MEDIA_IOC_SETUP_LINK   _IOWR('|', 0x03, struct media_link_desc)
 #define MEDIA_IOC_G_TOPOLOGY   _IOWR('|', 0x04, struct media_v2_topology)
+#define MEDIA_IOC_REQUEST_ALLOC_IOWR('|', 0x05, struct 
media_request_alloc)
+
+/*
+ * These ioctls are called on the request file descriptor as returned
+ * by MEDIA_IOC_REQUEST_ALLOC.
+ */
+#define MEDIA_REQUEST_IOC_QUEUE_IO('|',  0x80)
+#define MEDIA_REQUEST_IOC_REINIT   _IO('|',  0x81)
 
 #if !defined(__KERNEL__) || defined(__NEED_MEDIA_LEGACY_API)
 
-- 
2.17.0



[PATCHv15 08/35] videodev2.h: add request_fd field to v4l2_ext_controls

2018-06-04 Thread Hans Verkuil
From: Alexandre Courbot 

If 'which' is V4L2_CTRL_WHICH_REQUEST_VAL, then the 'request_fd' field
can be used to specify a request for the G/S/TRY_EXT_CTRLS ioctls.

Signed-off-by: Alexandre Courbot 
Signed-off-by: Hans Verkuil 
---
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 5 -
 drivers/media/v4l2-core/v4l2-ioctl.c  | 6 +++---
 include/uapi/linux/videodev2.h| 4 +++-
 3 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c 
b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index 6481212fda77..dcce86c1fe40 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -834,7 +834,8 @@ struct v4l2_ext_controls32 {
__u32 which;
__u32 count;
__u32 error_idx;
-   __u32 reserved[2];
+   __s32 request_fd;
+   __u32 reserved[1];
compat_caddr_t controls; /* actually struct v4l2_ext_control32 * */
 };
 
@@ -909,6 +910,7 @@ static int get_v4l2_ext_controls32(struct file *file,
get_user(count, &p32->count) ||
put_user(count, &p64->count) ||
assign_in_user(&p64->error_idx, &p32->error_idx) ||
+   assign_in_user(&p64->request_fd, &p32->request_fd) ||
copy_in_user(p64->reserved, p32->reserved, sizeof(p64->reserved)))
return -EFAULT;
 
@@ -974,6 +976,7 @@ static int put_v4l2_ext_controls32(struct file *file,
get_user(count, &p64->count) ||
put_user(count, &p32->count) ||
assign_in_user(&p32->error_idx, &p64->error_idx) ||
+   assign_in_user(&p32->request_fd, &p64->request_fd) ||
copy_in_user(p32->reserved, p64->reserved, sizeof(p32->reserved)) ||
get_user(kcontrols, &p64->controls))
return -EFAULT;
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c 
b/drivers/media/v4l2-core/v4l2-ioctl.c
index 27a893aa0664..3fa66103ffd0 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -553,8 +553,8 @@ static void v4l_print_ext_controls(const void *arg, bool 
write_only)
const struct v4l2_ext_controls *p = arg;
int i;
 
-   pr_cont("which=0x%x, count=%d, error_idx=%d",
-   p->which, p->count, p->error_idx);
+   pr_cont("which=0x%x, count=%d, error_idx=%d, request_fd=%d",
+   p->which, p->count, p->error_idx, p->request_fd);
for (i = 0; i < p->count; i++) {
if (!p->controls[i].size)
pr_cont(", id/val=0x%x/0x%x",
@@ -870,7 +870,7 @@ static int check_ext_ctrls(struct v4l2_ext_controls *c, int 
allow_priv)
__u32 i;
 
/* zero the reserved fields */
-   c->reserved[0] = c->reserved[1] = 0;
+   c->reserved[0] = 0;
for (i = 0; i < c->count; i++)
c->controls[i].reserved2[0] = 0;
 
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index 600877be5c22..16b53b82496c 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -1592,7 +1592,8 @@ struct v4l2_ext_controls {
};
__u32 count;
__u32 error_idx;
-   __u32 reserved[2];
+   __s32 request_fd;
+   __u32 reserved[1];
struct v4l2_ext_control *controls;
 };
 
@@ -1605,6 +1606,7 @@ struct v4l2_ext_controls {
 #define V4L2_CTRL_MAX_DIMS   (4)
 #define V4L2_CTRL_WHICH_CUR_VAL   0
 #define V4L2_CTRL_WHICH_DEF_VAL   0x0f00
+#define V4L2_CTRL_WHICH_REQUEST_VAL 0x0f01
 
 enum v4l2_ctrl_type {
V4L2_CTRL_TYPE_INTEGER   = 1,
-- 
2.17.0



[PATCHv15 26/35] videobuf2-v4l2: refuse qbuf if queue uses requests

2018-06-04 Thread Hans Verkuil
From: Hans Verkuil 

Check if the vb2 queue uses requests, and if so refuse to
add buffers that are not part of a request.

We might relax this in the future, but for now just return
-EBUSY in that case.

Signed-off-by: Hans Verkuil 
---
 drivers/media/common/videobuf2/videobuf2-v4l2.c | 7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/media/common/videobuf2/videobuf2-v4l2.c 
b/drivers/media/common/videobuf2/videobuf2-v4l2.c
index 499b2ab3d1fa..05004b26a705 100644
--- a/drivers/media/common/videobuf2/videobuf2-v4l2.c
+++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c
@@ -378,8 +378,13 @@ static int vb2_queue_or_prepare_buf(struct vb2_queue *q, 
struct media_device *md
return ret;
}
 
-   if (!(b->flags & V4L2_BUF_FLAG_REQUEST_FD))
+   if (!(b->flags & V4L2_BUF_FLAG_REQUEST_FD)) {
+   if (q->uses_requests) {
+   dprintk(1, "%s: queue uses requests\n", opname);
+   return -EBUSY;
+   }
return 0;
+   }
 
/*
 * For proper locking when queueing a request you need to be able
-- 
2.17.0



[PATCHv15 00/35] Request API

2018-06-04 Thread Hans Verkuil
From: Hans Verkuil 

Hi all,

This is version 15 of the Request API series.

The main changes compared to v14 are:

- Squashed various patches from v14 together where applicable.

- All comments to v13/v14 patches have been processed and code
  adapted where applicable.

- Added new init_buffer vb2 buffer op to initialize struct
  vb2_v4l2_buffer (the request_fd field should be inited to -1).

- The vb2 internal state PREPARED has been removed. Instead two
  new bool fields 'synced' and 'prepared' keep track of whether
  buffers are synced and/or prepared. This simplifies vb2 when it
  comes to keeping track of the buffer state and this is especially
  important when buffers can be in a request, but not yet queued.

- After dequeueing a buffer that was part of a request the request_fd
  is filled in correctly, but it is also cleared (init_buffer) internally.
  So calling querybuf after the dqbuf will not have an associated
  request anymore. This makes sense since the buffer has no longer any
  relationship with a request after dqbuf was called.

- Once you start queueing buffers in a request it is no longer allowed
  to queue buffers directly (i.e. without a request) until the queue
  is cancelled. This might be relaxed in the future, but for now this
  prevents mixing request and non-request buffers.

- vim2m now uses delayed work instead of a timer.

- It is no longer allowed to use requests for capture buffers of a
  memory-to-memory device. See this discussion:
  https://www.mail-archive.com/linux-media@vger.kernel.org/msg132202.html

This series has been tested extensively with v4l2-compliance (modified
to test requests) and the vim2m and vivid drivers.

Regarding locking:

There are two request locks used: req_queue_mutex (part of media_device)
ensures high-level serialization of queueing/reiniting and canceling
requests. It serializes STREAMON/OFF, close() and MEDIA_REQUEST_IOC_QUEUE.
This is the top-level lock and should be taken before any others.

The 'lock' spin_lock in struct media_request protects that structure and
should be held for a short time only.

When MEDIA_REQUEST_IOC_QUEUE is called it will validate and queue both
control handlers and vb2 buffers. For control handlers the control handler
lock will be taken, for vb2 buffers the vb2_queue lock will be taken.
This requires that the lock field in vb2_queue is set, which is checked in
videobuf2-v4l2.c.

TODO:

vim2m: the media topology is a bit bogus, this needs to be fixed
(i.e. a proper HW entity should be added). But for now it is
good enough for testing.

Everything seemed to slip nicely into place while working on this,
so I hope this is finally an implementation that we can proceed to
upstream and build upon for complex camera pipelines in the future.

This patch series is also available here:

https://git.linuxtv.org/hverkuil/media_tree.git/log/?h=reqv15

The patched v4l2-compliance is available here:

https://git.linuxtv.org/hverkuil/v4l-utils.git/log/?h=request

Regards,

Hans

Alexandre Courbot (2):
  videodev2.h: add request_fd field to v4l2_ext_controls
  Documentation: v4l: document request API

Hans Verkuil (31):
  uapi/linux/media.h: add request API
  media-request: implement media requests
  media-request: add media_request_get_by_fd
  media-request: add media_request_object_find
  v4l2-device.h: add v4l2_device_supports_requests() helper
  v4l2-dev: lock req_queue_mutex
  v4l2-ctrls: v4l2_ctrl_add_handler: add from_other_dev
  v4l2-ctrls: prepare internal structs for request API
  v4l2-ctrls: alloc memory for p_req
  v4l2-ctrls: use ref in helper instead of ctrl
  v4l2-ctrls: add core request support
  v4l2-ctrls: support g/s_ext_ctrls for requests
  vb2: store userspace data in vb2_v4l2_buffer
  davinci_vpfe: remove bogus vb2->state check
  vb2: drop VB2_BUF_STATE_PREPARED, use bool prepared/synced instead
  videodev2.h: Add request_fd field to v4l2_buffer
  vb2: add init_buffer buffer op
  videobuf2-core: embed media_request_object
  videobuf2-core: integrate with media requests
  videobuf2-v4l2: integrate with media requests
  videobuf2-core: add request helper functions
  videobuf2-v4l2: add vb2_request_queue/validate helpers
  videobuf2-core: add uses_requests flag
  videobuf2-v4l2: refuse qbuf if queue uses requests
  v4l2-mem2mem: add vb2_m2m_request_queue
  vim2m: add media device
  vim2m: use workqueue
  vim2m: support requests
  vivid: add mc
  vivid: add request support
  RFC: media-requests: add debugfs node

Sakari Ailus (2):
  media: doc: Add media-request.h header to documentation build
  v4l2-mem2mem: Simplify exiting the function in v4l2_m2m_try_schedule

 Documentation/media/kapi/mc-core.rst  |   2 +
 .../media/uapi/mediactl/media-controller.rst  |   1 +
 .../media/uapi/mediactl/media-funcs.rst   |   3 +
 .../uapi/mediactl/media-ioc-request-alloc.rst |  71 +++
 .../uapi/mediactl/media-request-ioc-queue.rst |  50 ++
 .../mediactl/media-request-ioc-reinit.rst |  51 ++
 .../media/ua

[PATCHv15 02/35] media-request: implement media requests

2018-06-04 Thread Hans Verkuil
From: Hans Verkuil 

Add initial media request support:

1) Add MEDIA_IOC_REQUEST_ALLOC ioctl support to media-device.c
2) Add struct media_request to store request objects.
3) Add struct media_request_object to represent a request object.
4) Add MEDIA_REQUEST_IOC_QUEUE/REINIT ioctl support.

Basic lifecycle: the application allocates a request, adds
objects to it, queues the request, polls until it is completed
and can then read the final values of the objects at the time
of completion. When it closes the file descriptor the request
memory will be freed (actually, when the last user of that request
releases the request).

Drivers will bind an object to a request (the 'adds objects to it'
phase), when MEDIA_REQUEST_IOC_QUEUE is called the request is
validated (req_validate op), then queued (the req_queue op).

When done with an object it can either be unbound from the request
(e.g. when the driver has finished with a vb2 buffer) or marked as
completed (e.g. for controls associated with a buffer). When all
objects in the request are completed (or unbound), then the request
fd will signal an exception (poll).

Signed-off-by: Hans Verkuil 
Co-developed-by: Sakari Ailus 
Signed-off-by: Sakari Ailus 
Co-developed-by: Laurent Pinchart 
Co-developed-by: Alexandre Courbot 
---
 drivers/media/Makefile|   3 +-
 drivers/media/media-device.c  |  14 ++
 drivers/media/media-request.c | 421 ++
 include/media/media-device.h  |  24 ++
 include/media/media-request.h | 326 ++
 5 files changed, 787 insertions(+), 1 deletion(-)
 create mode 100644 drivers/media/media-request.c
 create mode 100644 include/media/media-request.h

diff --git a/drivers/media/Makefile b/drivers/media/Makefile
index 594b462ddf0e..985d35ec6b29 100644
--- a/drivers/media/Makefile
+++ b/drivers/media/Makefile
@@ -3,7 +3,8 @@
 # Makefile for the kernel multimedia device drivers.
 #
 
-media-objs := media-device.o media-devnode.o media-entity.o
+media-objs := media-device.o media-devnode.o media-entity.o \
+  media-request.o
 
 #
 # I2C drivers should come before other drivers, otherwise they'll fail
diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c
index ae59c3177555..1119c1058e73 100644
--- a/drivers/media/media-device.c
+++ b/drivers/media/media-device.c
@@ -32,6 +32,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #ifdef CONFIG_MEDIA_CONTROLLER
 
@@ -367,6 +368,15 @@ static long media_device_get_topology(struct media_device 
*mdev, void *arg)
return ret;
 }
 
+static long media_device_request_alloc(struct media_device *mdev,
+  struct media_request_alloc *alloc)
+{
+   if (!mdev->ops || !mdev->ops->req_validate || !mdev->ops->req_queue)
+   return -ENOTTY;
+
+   return media_request_alloc(mdev, alloc);
+}
+
 static long copy_arg_from_user(void *karg, void __user *uarg, unsigned int cmd)
 {
/* All media IOCTLs are _IOWR() */
@@ -415,6 +425,7 @@ static const struct media_ioctl_info ioctl_info[] = {
MEDIA_IOC(ENUM_LINKS, media_device_enum_links, 
MEDIA_IOC_FL_GRAPH_MUTEX),
MEDIA_IOC(SETUP_LINK, media_device_setup_link, 
MEDIA_IOC_FL_GRAPH_MUTEX),
MEDIA_IOC(G_TOPOLOGY, media_device_get_topology, 
MEDIA_IOC_FL_GRAPH_MUTEX),
+   MEDIA_IOC(REQUEST_ALLOC, media_device_request_alloc, 0),
 };
 
 static long media_device_ioctl(struct file *filp, unsigned int cmd,
@@ -687,6 +698,8 @@ void media_device_init(struct media_device *mdev)
INIT_LIST_HEAD(&mdev->pads);
INIT_LIST_HEAD(&mdev->links);
INIT_LIST_HEAD(&mdev->entity_notify);
+
+   mutex_init(&mdev->req_queue_mutex);
mutex_init(&mdev->graph_mutex);
ida_init(&mdev->entity_internal_idx);
 
@@ -700,6 +713,7 @@ void media_device_cleanup(struct media_device *mdev)
mdev->entity_internal_idx_max = 0;
media_graph_walk_cleanup(&mdev->pm_count_walk);
mutex_destroy(&mdev->graph_mutex);
+   mutex_destroy(&mdev->req_queue_mutex);
 }
 EXPORT_SYMBOL_GPL(media_device_cleanup);
 
diff --git a/drivers/media/media-request.c b/drivers/media/media-request.c
new file mode 100644
index ..09823235e4c8
--- /dev/null
+++ b/drivers/media/media-request.c
@@ -0,0 +1,421 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Media device request objects
+ *
+ * Copyright 2018 Cisco Systems, Inc. and/or its affiliates. All rights 
reserved.
+ * Copyright (C) 2018 Intel Corporation
+ * Copyright (C) 2018 Google, Inc.
+ *
+ * Author: Hans Verkuil 
+ * Author: Sakari Ailus 
+ */
+
+#include 
+#include 
+#include 
+
+#include 
+#include 
+
+static const char * const request_state[] = {
+   [MEDIA_REQUEST_STATE_IDLE]   = "idle",
+   [MEDIA_REQUEST_STATE_VALIDATING] = "validating",
+   [MEDIA_REQUEST_STATE_QUEUED] = "queued",
+   [MEDIA_REQUEST_STATE_COMPLETE]   = "complete",
+   [MEDIA_REQUEST_STATE_CLEANING]   = "cleaning",
+  

[PATCHv15 24/35] videobuf2-v4l2: add vb2_request_queue/validate helpers

2018-06-04 Thread Hans Verkuil
From: Hans Verkuil 

The generic vb2_request_validate helper function checks if
there are buffers in the request and if so, prepares (validates)
all objects in the request.

The generic vb2_request_queue helper function queues all buffer
objects in the validated request.

Signed-off-by: Hans Verkuil 
---
 .../media/common/videobuf2/videobuf2-v4l2.c   | 38 +++
 include/media/videobuf2-v4l2.h|  4 ++
 2 files changed, 42 insertions(+)

diff --git a/drivers/media/common/videobuf2/videobuf2-v4l2.c 
b/drivers/media/common/videobuf2/videobuf2-v4l2.c
index 9c652afa62ab..499b2ab3d1fa 100644
--- a/drivers/media/common/videobuf2/videobuf2-v4l2.c
+++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c
@@ -1100,6 +1100,44 @@ void vb2_ops_wait_finish(struct vb2_queue *vq)
 }
 EXPORT_SYMBOL_GPL(vb2_ops_wait_finish);
 
+int vb2_request_validate(struct media_request *req)
+{
+   struct media_request_object *obj;
+   int ret = 0;
+
+   if (!vb2_request_has_buffers(req))
+   return -ENOENT;
+
+   list_for_each_entry(obj, &req->objects, list) {
+   if (!obj->ops->prepare)
+   continue;
+
+   ret = obj->ops->prepare(obj);
+   if (ret)
+   break;
+   }
+
+   if (ret) {
+   list_for_each_entry_continue_reverse(obj, &req->objects, list)
+   if (obj->ops->unprepare)
+   obj->ops->unprepare(obj);
+   return ret;
+   }
+   return 0;
+}
+EXPORT_SYMBOL_GPL(vb2_request_validate);
+
+void vb2_request_queue(struct media_request *req)
+{
+   struct media_request_object *obj;
+
+   list_for_each_entry(obj, &req->objects, list) {
+   if (obj->ops->queue)
+   obj->ops->queue(obj);
+   }
+}
+EXPORT_SYMBOL_GPL(vb2_request_queue);
+
 MODULE_DESCRIPTION("Driver helper framework for Video for Linux 2");
 MODULE_AUTHOR("Pawel Osciak , Marek Szyprowski");
 MODULE_LICENSE("GPL");
diff --git a/include/media/videobuf2-v4l2.h b/include/media/videobuf2-v4l2.h
index 91a2b3e1a642..727855463838 100644
--- a/include/media/videobuf2-v4l2.h
+++ b/include/media/videobuf2-v4l2.h
@@ -303,4 +303,8 @@ void vb2_ops_wait_prepare(struct vb2_queue *vq);
  */
 void vb2_ops_wait_finish(struct vb2_queue *vq);
 
+struct media_request;
+int vb2_request_validate(struct media_request *req);
+void vb2_request_queue(struct media_request *req);
+
 #endif /* _MEDIA_VIDEOBUF2_V4L2_H */
-- 
2.17.0



Re: RFC: Request API and memory-to-memory devices

2018-06-04 Thread Hans Verkuil
On 05/25/2018 05:26 PM, Hans Verkuil wrote:
> On 25/05/18 16:16, Sakari Ailus wrote:
>> Hi Hans,
>>
>> On Thu, May 24, 2018 at 10:44:13AM +0200, Hans Verkuil wrote:
>>> Memory-to-memory devices have one video node, one internal control handler
>>> but two vb2_queues (DMA engines). While often there is one buffer produced
>>> for every buffer consumed, but this is by no means standard. E.g. 
>>> deinterlacers
>>> will produce on buffer for every two buffers consumed. Codecs that receive
>>> a bit stream and can parse it to discover the framing may have no relation
>>> between the number of buffers consumed and the number of buffers produced.
>>
>> Do you have examples of such devices? I presume they're not supported in
>> the current m2m API either, are they?
>>
>>>
>>> This poses a few problems for the Request API. Requiring that a request
>>> contains the buffers for both output and capture queue will be difficult
>>> to implement, especially in the latter case where there is no relationship
>>> between the number of consumed and produced buffers.
>>>
>>> In addition, userspace can make two requests: one for the capture queue,
>>> one for the output queue, each with associated controls. But since the
>>> controls are shared between capture and output there is an issue of
>>> what to do when the same control is set in both requests.
>>
>> As I commented on v13, the two requests need to be handled separately in
>> this case. Mem-to-mem devices are rather special in this respect; there's
>> an established practice of matching buffers in the order they arrive from
>> the queues, but that's not how the request API is intended to work: the
>> buffers are associated to the request, and a request is processed
>> independently of other requests.
>>
>> While that approach might work for mem-to-mem devices at least in some use
>> cases, it is not a feasible approach for other devices. As a consequence,
>> will have different API semantics between mem2mem devices and the rest. I'd
>> like to avoid that if possible: this will be similarly visible in the user
>> applications as well.
>>
>>>
>>> I propose to restrict the usage of requests for m2m drivers to the output
>>> queue only. This keeps things simple for both kernel and userspace and
>>> avoids complex solutions.
>>
>> If there's a convincing reason to use different API semantics, such as the
>> relationship between different buffers being unknown to the user, then
>> there very likely is a need to associate non-request data with
>> request-bound data in the driver. But it'd be better to limit it to where
>> it's really needed.
>>
>>>
>>> Requests only make sense if there is actually configuration you can apply
>>> for each buffer, and while that's true for the output queue, on the capture
>>> queue you just capture the result of whatever the device delivers. I don't
>>> believe there is much if anything you can or want to control per-buffer.
>>
>> May there be controls associated with the capture queue buffers?
>>
> 
> In theory that could happen for m2m devices, but those controls would be 
> different
> from controls associated with the output queue.
> 
> The core problem is that if there is no clear relationship between capture
> and output buffers, then you cannot add a capture and an output buffer to
> the same request. That simply wouldn't work.
> 
> How to signal this to the user? For m2m devices we could just specify that
> in the spec and check this in the core. As Tomasz said, m2m devices are
> already sufficiently special that I don't think this is a problem. But in
> the more generic case (complex pipelines) I cannot off-hand think of something
> elegant.
> 
> I guess I would have to sleep on this a bit.

After thinking this over I believe that the only way this can be exposed to
userspace is via the media controller. How exactly I do not know, but since this
depends on the topology the MC is the only place you can provide such 
information
to the user.

For now I will just disable the use of requests for the capture queue of an m2m
device. This can always be relaxed in the future once we figured out how to
present this in the MC.

Regards,

Hans


[PATCH for v4.18] v4l2-ioctl.c: fix missing unlock in __video_do_ioctl()

2018-06-04 Thread Hans Verkuil
If dev_debug was active, then the code could return without unlocking the
core mutex. Replace the return with a 'goto unlock' to ensure proper unlocking.

Fixes: 73a110623e7b ("v4l2-core: push taking ioctl mutex down to ioctl handler")
Signed-off-by: Hans Verkuil 
---
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c 
b/drivers/media/v4l2-core/v4l2-ioctl.c
index 965fd301f617..dd210067151f 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -2777,7 +2777,7 @@ static long __video_do_ioctl(struct file *file,
if (dev_debug & (V4L2_DEV_DEBUG_IOCTL | V4L2_DEV_DEBUG_IOCTL_ARG)) {
if (!(dev_debug & V4L2_DEV_DEBUG_STREAMING) &&
(cmd == VIDIOC_QBUF || cmd == VIDIOC_DQBUF))
-   return ret;
+   goto unlock;

v4l_printk_ioctl(video_device_node_name(vfd), cmd);
if (ret < 0)


Re: i.MX6 IPU CSI analog video input on Ventana

2018-06-04 Thread Krzysztof Hałasa
I've just tested the PAL setup: in currect situation (v4.17 + Steve's
fix-csi-interlaced.2 + "media: adv7180: fix field type" + a small cheap
PAL camera) the following produces bottom-first interlaced frames:

media-ctl -r -l '"adv7180 2-0020":0->"ipu2_csi1_mux":1[1],
 "ipu2_csi1_mux":2->"ipu2_csi1":0[1],
 "ipu2_csi1":2->"ipu2_csi1 capture":0[1]'

media-ctl -V "'adv7180 2-0020':0 [fmt:UYVY2X8/720x576 field:alternate]"
media-ctl -V "'ipu2_csi1_mux':2 [fmt:UYVY2X8/720x576]"
media-ctl -V "'ipu2_csi1':2 [fmt:AYUV32/720x576 field:interlaced]"

"adv7180 2-0020":0 [fmt:UYVY2X8/720x576 field:alternate]
"ipu2_csi1_mux":1  [fmt:UYVY2X8/720x576 field:alternate]
"ipu2_csi1_mux":2  [fmt:UYVY2X8/720x576 field:alternate]
"ipu2_csi1":0  [fmt:UYVY2X8/720x576 field:alternate]
"ipu2_csi1":2  [fmt:AYUV32/720x576 field:interlaced]

I think it would be great if these changes make their way upstream.
The details could be refined then.
-- 
Krzysztof Halasa
Industrial Research Institute for Automation and Measurements PIAP
Al. Jerozolimskie 202, 02-486 Warsaw, Poland


[PATCH v3 1/2] dt-bindings: Add bindings for AKM ak7375 voice coil lens

2018-06-04 Thread bingbu . cao
From: Bingbu Cao 

Add device tree bindings for asahi-kasei ak7375 voice coil lens
driver. This chip is used to drive a lens in a camera module.

Signed-off-by: Tianshu Qiu 
Signed-off-by: Bingbu Cao 

---
Changes since v1:
- add the MAINTAINERS change
- correct the vendor prefix from akm to asahi-kasei
---
---
 Documentation/devicetree/bindings/media/i2c/ak7375.txt | 8 
 MAINTAINERS| 8 
 2 files changed, 16 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/media/i2c/ak7375.txt

diff --git a/Documentation/devicetree/bindings/media/i2c/ak7375.txt 
b/Documentation/devicetree/bindings/media/i2c/ak7375.txt
new file mode 100644
index ..aa3e24b41241
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/i2c/ak7375.txt
@@ -0,0 +1,8 @@
+Asahi Kasei Microdevices AK7375 voice coil lens driver
+
+AK7375 is a camera voice coil lens.
+
+Mandatory properties:
+
+- compatible: "asahi-kasei,ak7375"
+- reg: I2C slave address
diff --git a/MAINTAINERS b/MAINTAINERS
index ea362219c4aa..ad68d75abc84 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2258,6 +2258,14 @@ L:   linux-l...@vger.kernel.org
 S: Maintained
 F: drivers/leds/leds-as3645a.c
 
+ASAHI KASEI AK7375 LENS VOICE COIL DRIVER
+M: Tianshu Qiu 
+L: linux-media@vger.kernel.org
+T: git git://linuxtv.org/media_tree.git
+S: Maintained
+F: drivers/media/i2c/ak7375.c
+F: Documentation/devicetree/bindings/media/i2c/ak7375.txt
+
 ASAHI KASEI AK8974 DRIVER
 M: Linus Walleij 
 L: linux-...@vger.kernel.org
-- 
1.9.1



[PATCH v3 2/2] media: ak7375: Add ak7375 lens voice coil driver

2018-06-04 Thread bingbu . cao
From: Bingbu Cao 

Add a v4l2 sub-device driver for the ak7375 lens voice coil.
This is a voice coil module using the i2c bus to control the
focus position.

ak7375 can write multiple bytes of data at a time. If more
data is received instead of the stop condition after receiving
one byte of data, the address inside the chip is automatically
incremented and the data is written into the next address.

The ak7375 can control the position with 12 bits value and
consists of two 8 bit registers show as below:
register 0x00(AK7375_REG_POSITION):
+---+---+---+---+---+---+---+---+
|D11|D10|D09|D08|D07|D06|D05|D04|
+---+---+---+---+---+---+---+---+
register 0x01:
+---+---+---+---+---+---+---+---+
|D03|D02|D01|D00|---|---|---|---|
+---+---+---+---+---+---+---+---+

This driver support :
- set ak7375 to standby mode once suspend and
  turn it back to active if resume
- set the position via V4L2_CID_FOCUS_ABSOLUTE ctrl

Signed-off-by: Tianshu Qiu 
Signed-off-by: Bingbu Cao 

---
Changes from v1:
- correct i2c write
- add media_entity_pads_init() into probe
- move the MAINTAINERs change into dt-bindings change
- correct the compatible string
---
---
 drivers/media/i2c/Kconfig  |  10 ++
 drivers/media/i2c/Makefile |   1 +
 drivers/media/i2c/ak7375.c | 278 +
 3 files changed, 289 insertions(+)
 create mode 100644 drivers/media/i2c/ak7375.c

diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
index 341452fe98df..ff3cb5afb0e1 100644
--- a/drivers/media/i2c/Kconfig
+++ b/drivers/media/i2c/Kconfig
@@ -326,6 +326,16 @@ config VIDEO_AD5820
  This is a driver for the AD5820 camera lens voice coil.
  It is used for example in Nokia N900 (RX-51).
 
+config VIDEO_AK7375
+   tristate "AK7375 lens voice coil support"
+   depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER
+   depends on VIDEO_V4L2_SUBDEV_API
+   help
+ This is a driver for the AK7375 camera lens voice coil.
+ AK7375 is a 12 bit DAC with 120mA output current sink
+ capability. This is designed for linear control of
+ voice coil motors, controlled via I2C serial interface.
+
 config VIDEO_DW9714
tristate "DW9714 lens voice coil support"
depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER
diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile
index d679d57cd3b3..05b97e319ea9 100644
--- a/drivers/media/i2c/Makefile
+++ b/drivers/media/i2c/Makefile
@@ -23,6 +23,7 @@ obj-$(CONFIG_VIDEO_SAA7127) += saa7127.o
 obj-$(CONFIG_VIDEO_SAA7185) += saa7185.o
 obj-$(CONFIG_VIDEO_SAA6752HS) += saa6752hs.o
 obj-$(CONFIG_VIDEO_AD5820)  += ad5820.o
+obj-$(CONFIG_VIDEO_AK7375)  += ak7375.o
 obj-$(CONFIG_VIDEO_DW9714)  += dw9714.o
 obj-$(CONFIG_VIDEO_ADV7170) += adv7170.o
 obj-$(CONFIG_VIDEO_ADV7175) += adv7175.o
diff --git a/drivers/media/i2c/ak7375.c b/drivers/media/i2c/ak7375.c
new file mode 100644
index ..94bcadae4258
--- /dev/null
+++ b/drivers/media/i2c/ak7375.c
@@ -0,0 +1,278 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Intel Corporation
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define AK7375_MAX_FOCUS_POS   4095
+/*
+ * This sets the minimum granularity for the focus positions.
+ * A value of 1 gives maximum accuracy for a desired focus position
+ */
+#define AK7375_FOCUS_STEPS 1
+/*
+ * This acts as the minimum granularity of lens movement.
+ * Keep this value power of 2, so the control steps can be
+ * uniformly adjusted for gradual lens movement, with desired
+ * number of control steps.
+ */
+#define AK7375_CTRL_STEPS  64
+#define AK7375_CTRL_DELAY_US   1000
+
+#define AK7375_REG_POSITION0x0
+#define AK7375_REG_CONT0x2
+#define AK7375_MODE_ACTIVE 0x0
+#define AK7375_MODE_STANDBY0x40
+
+/* ak7375 device structure */
+struct ak7375_device {
+   struct v4l2_ctrl_handler ctrls_vcm;
+   struct v4l2_subdev sd;
+   struct v4l2_ctrl *focus;
+};
+
+static inline struct ak7375_device *to_ak7375_vcm(struct v4l2_ctrl *ctrl)
+{
+   return container_of(ctrl->handler, struct ak7375_device, ctrls_vcm);
+}
+
+static inline struct ak7375_device *sd_to_ak7375_vcm(struct v4l2_subdev 
*subdev)
+{
+   return container_of(subdev, struct ak7375_device, sd);
+}
+
+static int ak7375_i2c_write(struct ak7375_device *ak7375,
+   u8 addr, u16 data, int size)
+{
+   struct i2c_client *client = v4l2_get_subdevdata(&ak7375->sd);
+   int ret;
+   u8 buf[3];
+
+   if (size != 1 && size != 2)
+   return -EINVAL;
+   buf[0] = addr;
+   buf[size] = data & 0xff;
+   if (size == 2)
+   buf[1] = (data >> 8) & 0xff;
+   ret = i2c_master_send(client, (const char *)buf, size + 1);
+   if (ret < 0)
+   return ret;
+   if (ret != size + 1)
+   return -EIO;
+   return 0;
+}
+
+static int ak7375_set_ctrl(struct

Re: i.MX6 IPU CSI analog video input on Ventana

2018-06-04 Thread Philipp Zabel
On Sat, 2018-06-02 at 10:45 -0700, Steve Longerbeam wrote:
> 
> On 06/01/2018 06:13 AM, Philipp Zabel wrote:
> > Hi Krzysztof,
> > 
> > On Fri, 2018-06-01 at 12:02 +0200, Krzysztof Hałasa wrote:
> > > Steve Longerbeam  writes:
> > > 
> > > > I tend to agree, I've found conflicting info out there regarding
> > > > PAL vs. NTSC field order. And I've never liked having to guess
> > > > at input analog standard based on input # lines. I will go ahead
> > > > and remove the field order override code.
> > > 
> > > I've merged your current fix-csi-interlaced.2 branch (2018-06-01
> > > 00:06:45 UTC 22ad9f30454b6e46979edf6f8122243591910a3e) along with
> > > "media: adv7180: fix field type" commit and NTSC camera:
> > > 
> > > media-ctl -V "'adv7180 2-0020':0 [fmt:UYVY2X8/720x480 field:alternate]"
> > > media-ctl -V "'ipu2_csi1_mux':2 [fmt:UYVY2X8/720x480]"
> > > media-ctl -V "'ipu2_csi1':2 [fmt:AYUV32/720x480 field:interlaced/-bt/-tb]"
> > > 
> > > correctly sets:
> > > 
> > > "adv7180 2-0020":0 [fmt:UYVY2X8/720x480 field:alternate]
> > > "ipu2_csi1_mux":1  [fmt:UYVY2X8/720x480 field:alternate]
> > > "ipu2_csi1_mux":2  [fmt:UYVY2X8/720x480 field:alternate]
> > > "ipu2_csi1":0  [fmt:UYVY2X8/720x480 field:alternate]
> > > "ipu2_csi1":2  [fmt:AYUV32/720x480 field:interlaced/-bt/-tb]
> > > 
> > > but all 3 cases seem to produce top-first interlaced frames.
> > > The CCIR_CODE_* register dump shows no differences:
> > > 2a38014: 010D07DF 00040596 00FF
> > > 
> > > ...it's because the code in drivers/gpu/ipu-v3/ipu-csi.c still sets the
> > > registers depending on the height of the image.
> > 
> > Exactly.
> > 
> > >   Hovewer, I'm using 480
> > > lines here, so it should be B-T instead.
> > 
> > My understanding is that the CCIR codes for height == 480 (NTSC)
> > currently capture the second field (top) first, assuming that for NTSC
> > the EAV/SAV codes are bottom-field-first.
> > 
> > So the CSI captures SEQ_TB for both PAL and NTSC: The three-bit values
> > in CCIR_CODE_2/3 are in H,V,F order, and the NTSC case has F=1 for the
> > field that is captured first, where F=1 is the field that is marked as
> > second field on the wire, so top. Which means that the captured frame
> > has two fields captured across frame boundaries, which might be
> > problematic if the source data was originally progressive.
> 
> I agree, for NTSC the CSI will drop the first B field and start capturing
> at the T field, and then capture fields across frame boundaries. At
> least, that is if we understand how these CCIR registers work: the
> CSI will look for H-S-V codes for the start and end of active and blanking
> lines, that match the codes written to CCIR_CODE_1/2 for fields 0/1.
> 
> I think this must be legacy code from a Freescale BSP requirement
> that the CSI must always capture in T-B order. We should remove this
> code, so that the CSI always captures field 0 followed by field 1, 
> irrespective
> of field affinity, as in:
> 
> diff --git a/drivers/gpu/ipu-v3/ipu-csi.c b/drivers/gpu/ipu-v3/ipu-csi.c
> index 5450a2d..b8b9b6d 100644
> --- a/drivers/gpu/ipu-v3/ipu-csi.c
> +++ b/drivers/gpu/ipu-v3/ipu-csi.c
> @@ -398,41 +398,20 @@ int ipu_csi_init_interface(struct ipu_csi *csi,
>      break;
>      case IPU_CSI_CLK_MODE_CCIR656_INTERLACED:
>      if (mbus_fmt->width == 720 && mbus_fmt->height == 576) {
> -   /*
> -    * PAL case
> -    *
> -    * Field0BlankEnd = 0x6, Field0BlankStart = 0x2,
> -    * Field0ActiveEnd = 0x4, Field0ActiveStart = 0
> -    * Field1BlankEnd = 0x7, Field1BlankStart = 0x3,
> -    * Field1ActiveEnd = 0x5, Field1ActiveStart = 0x1
> -    */
>      height = 625; /* framelines for PAL */
> -
> -   ipu_csi_write(csi, 0x40596 | CSI_CCIR_ERR_DET_EN,
> - CSI_CCIR_CODE_1);
> -   ipu_csi_write(csi, 0xD07DF, CSI_CCIR_CODE_2);
> -   ipu_csi_write(csi, 0xFF, CSI_CCIR_CODE_3);
>      } else if (mbus_fmt->width == 720 && mbus_fmt->height 
> == 480) {
> -   /*
> -    * NTSC case
> -    *
> -    * Field0BlankEnd = 0x7, Field0BlankStart = 0x3,
> -    * Field0ActiveEnd = 0x5, Field0ActiveStart = 0x1
> -    * Field1BlankEnd = 0x6, Field1BlankStart = 0x2,
> -    * Field1ActiveEnd = 0x4, Field1ActiveStart = 0
> -    */
>      height = 525; /* framelines for NTSC */
> -
> -   ipu_csi_write(csi, 0xD07DF | CSI_CCIR_ERR_DET_EN,
> - CSI_CCIR_CODE_1);
> -   ipu_csi_write(csi, 0x40596, CSI_CCIR_CODE_2);
> -   ipu_csi_write(csi, 0xFF0

Re: i.MX6 IPU CSI analog video input on Ventana

2018-06-04 Thread Philipp Zabel
On Sat, 2018-06-02 at 10:33 -0700, Steve Longerbeam wrote:
[...]
> As I said in the other thread, I think we should put this off to some
> other time, and remove the code in ipu_csi_init_interface() that
> inverts field order according to frame size. This way, CSI will not
> be lying to userspace when we tell it the order is BT but the CSI
> has actually inverted that to TB.
> 
> Also I have concerns about the CSI capturing field 1 _before_ field
> 0 for NTSC. Doesn't that mean the CSI will drop the B-field in the
> first captured frame on stream on, and thereafter mix fields from
> different adjacent frames?

Yes, that is only a problem for 29.97 Hz progressive source material.
For real 59.94 Hz interlaced source material it does not matter which
two consecutive fields are displayed together as long as we get the
top/bottom ordering right.

regards
Philipp


Re: [PATCH v2 10/10] media: imx.rst: Update doc to reflect fixes to interlaced capture

2018-06-04 Thread Philipp Zabel
On Sat, 2018-06-02 at 11:44 -0700, Steve Longerbeam wrote:
> 
> On 06/01/2018 06:44 AM, Philipp Zabel wrote:
> > On Thu, 2018-05-31 at 17:30 -0700, Steve Longerbeam wrote:
> > 
> > > +
> > > +.. code-block:: none
> > > +
> > > +   # Setup links
> > > +   media-ctl -l "'adv7180 3-0021':0 -> 'ipu1_csi0_mux':1[1]"
> > > +   media-ctl -l "'ipu1_csi0_mux':2 -> 'ipu1_csi0':0[1]"
> > > +   media-ctl -l "'ipu1_csi0':2 -> 'ipu1_csi0 capture':0[1]"
> > > +   # Configure pads
> > > +   media-ctl -V "'adv7180 3-0021':0 [fmt:UYVY2X8/720x480 field:seq-bt]"
> > > +   media-ctl -V "'ipu1_csi0_mux':2 [fmt:UYVY2X8/720x480]"
> > > +   media-ctl -V "'ipu1_csi0':2 [fmt:AYUV32/720x480 field:interlaced]"
> > 
> > Could the example suggest using interlaced-bt to be explicit here?
> > Actually, I don't think we should allow interlaced on the CSI src pads
> > at all in this case. Technically it always writes either seq-tb or seq-
> > bt into the smfc, never interlaced (unless the input is already
> > interlaced).
> > 
> 
> Hmm, if the sink is 'alternate', and the requested source is
> 'interlaced*', perhaps we should allow the source to be
> 'interlaced*' and not override it. For example, if requested
> is 'interlaced-tb', let it be that. IOW assume user knows something
> we don't about the original field order, or is experimenting
> with finding the correct field order.

If the source material is really interlaced and not alternate, shouldn't
the sink pad be set to interlaced?

regards
Philipp


Re: [PATCH v2 01/10] media: imx-csi: Pass sink pad field to ipu_csi_init_interface

2018-06-04 Thread Philipp Zabel
On Mon, 2018-06-04 at 07:25 +0200, Krzysztof Hałasa wrote:
> Steve Longerbeam  writes:
> 
> > I think we should return to enforcing field order to userspace that
> > matches field order from the source, which is what I had implemented
> > previously. I agree with you that we should put off allowing inverting
> > field order.
> 
> There is no any particular field order at the source, most of the time.
> The odd field is followed by the even field, and so on, sure. But there
> is no "first" and "second" field, any field can be the "first".

There is no particular field order in the data itself. But for BT.656
there is a specific field order, defined by the F flag in the SAV/EAV
codes. For PAL usually F=0 is the top field and F=1 is the bottom field.
For NTSC it usually is the other way around.

> The exception to this is a camera with a progressive sensor - both
> "fields" are taken at the same time and transmitted one after the other,
> so in this case the order is defined (by the camera, e.g. B-T on DV even
> with PAL version). But this isn't exactly PAL/NTSC.

That's why I'd like to make it obvious to the user when the field order
is switched. Whoever selects seq-bt -> seq-tb or seq-tb -> seq-bt
transformation for progressive sources can expect combing artifacts.

regards
Philipp


Re: [PATCH v2 04/10] media: imx: interweave only for sequential input/interlaced output fields

2018-06-04 Thread Philipp Zabel
On Mon, 2018-06-04 at 07:35 +0200, Krzysztof Hałasa wrote:
> Philipp Zabel  writes:
> 
> > This is ok in this patch, but we can't use this check in the following
> > TRY_FMT patch as there is no way to interweave
> > SEQ_TB -> INTERLACED_BT (because in SEQ_TB the B field is newer than T,
> > but in INTERLACED_BT it has to be older) or SEQ_BT -> INTERLACED_TB (the
> > other way around).
> 
> Actually we can do SEQ_TB -> INTERLACED_BT and SEQ_BT -> INTERLACED_TB
> rather easily. We only need to skip a single field at start :-)
> That's what CCIR_CODE_* registers do.
> 
> To be honest, SEQ_TB and SEQ_BT are precisely the same thing
> (i.e., SEQUENTIAL). It's up to the user to say which field is the first.
> There is the progressive sensor exception, though, and the TB/BT could
> be a hint for downstream elements (i.e., setting the default field
> order).
> 
> But I think we should be able to request INTERLACED_TB or INTERLACED_BT
> (with any analog signal on input) and the CCIR_CODE registers should be
> set accordingly. This should all magically work fine.

The CSI subdevice itself can't interweave at all, this is done in the
IDMAC.
In my opinion the CSI subdev should allow the following src -> sink
field transformations for BT.656:

none -> none
seq-tb -> seq-tb
seq-tb -> seq-bt
seq-bt -> seq-bt
seq-bt -> seq-tb
alternate -> seq-tb
alternate -> seq-bt
interlaced -> interlaced
interlaced-tb -> interlaced-tb
interlaced-bt -> interlaced-bt

The capture video device should then additionally allow selecting
the field order that can be produced by IDMAC interweaving:
INTERLACED_TB if the pad is seq-tb and INTERLACED_BT if the pad is seq-
bt, as that is what the IDMAC can convert.

seq-tb -> seq-tb and seq-bt -> seq-bt should always capture field 0
first, as we currently do for PAL.
seq->tb -> seq-bt and seq-bt -> seq-tb should always capture field 1
first, as we currently do for NTSC.
alternate -> seq-tb and alternate -> seq-bt should match seq-tb -> * for
PAL and seq-bt -> * for NTSC.
The interlaced* -> interlaced* would be handled as progressive.

regards
Philipp


[no subject]

2018-06-04 Thread Shane Missler



Mein Name ist SHANE MISSLER. Ich habe im Januar 2018 den $ 451 Millionen 
American Lotto Jackpot gewonnen. Ich habe eine Spende von € 2.100.000,00 für 
Sie. Ich spende Ihnen diese Spende wegen der Liebe, die ich für die Menschheit 
und die Bedürftigen in der Gesellschaft habe. Bitte kontaktieren Sie mich für 
weitere Informationen. 



Re: i.MX6 IPU CSI analog video input on Ventana

2018-06-04 Thread Krzysztof Hałasa
Steve Longerbeam  writes:

> I think this must be legacy code from a Freescale BSP requirement
> that the CSI must always capture in T-B order. We should remove this
> code, so that the CSI always captures field 0 followed by field 1,
> irrespective
> of field affinity,

Well it now seems we could do just that.
-- 
Krzysztof Halasa

Industrial Research Institute for Automation and Measurements PIAP
Al. Jerozolimskie 202, 02-486 Warsaw, Poland


Re: i.MX6 IPU CSI analog video input on Ventana

2018-06-04 Thread Krzysztof Hałasa
Hi Philipp,

Philipp Zabel  writes:

> My understanding is that the CCIR codes for height == 480 (NTSC)
> currently capture the second field (top) first, assuming that for NTSC
> the EAV/SAV codes are bottom-field-first.

2a38014: 010D07DF 00040596

SA  EA SB  EB  SB  EB
D07DF: 001 101 () 011 111 011 111 (field 0)
40596: 000 100 () 010 110 010 110 (field 1)

The codes apparently are 1=EAV (0=SAV), field#, 1=blanking.
Now BT.656 doesn't say a word about top and bottom fields. There are
just fields 1 and 2. So yes, the CCIR_CODE* registers currently seem to
swap the fields. It also depends on the ADV7180 sending correct codes
based on the even/odd analog fields. Interesting.

> So the CSI captures SEQ_TB for both PAL and NTSC: The three-bit values
> in CCIR_CODE_2/3 are in H,V,F order, and the NTSC case has F=1 for the
> field that is captured first, where F=1 is the field that is marked as
> second field on the wire, so top. Which means that the captured frame
> has two fields captured across frame boundaries, which might be
> problematic if the source data was originally progressive.

Exactly.
Especially if the complete frame is then passed straight to the display,
with the user treating it as progressive (which it isn't anymore).

>>  My guess is the CSI is skipping
>> the first incomplete line (half-line - the first visible line has full
>> length) and BT becomes TB.
>
> That wouldn't make BT TB though, if we'd still capture the bottom field
> (minus its first half line) first?

Well, the entire frame would shift up a line, the bottom "field" would
become top and vice versa. This would effectively make BT->TB and TB->BT.

>> It seems writing to the CCIR_CODE_[12] registers does the trick, though
>> (the captured frames aren't correct and have the lines swapped in pairs
>> because t/b field pointers aren't correctly set).
>
> What are you writing exactly? 0x01040596 to CCIR_CODE_1 and 0x000d07df
> to CCIR_CODE_2?

Yes.

> That is what I would expect to capture SEQ_BT for NTSC
> data, and the IPU could interweave this into INTERLACED_BT, correctly if
> we fix ipu_cpmem_interlaced_scan to allow negative offsets.

Exactly.
-- 
Krzysztof Halasa

Industrial Research Institute for Automation and Measurements PIAP
Al. Jerozolimskie 202, 02-486 Warsaw, Poland