All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v10 00/30] rcar-vin: Add Gen3 with media controller
@ 2018-01-29 16:34 Niklas Söderlund
  2018-01-29 16:34 ` [PATCH v10 01/30] rcar-vin: add Gen3 devicetree bindings documentation Niklas Söderlund
                   ` (29 more replies)
  0 siblings, 30 replies; 65+ messages in thread
From: Niklas Söderlund @ 2018-01-29 16:34 UTC (permalink / raw)
  To: Laurent Pinchart, Hans Verkuil, linux-media
  Cc: linux-renesas-soc, tomoharu.fukawa.eb, Kieran Bingham,
	Niklas Söderlund

Hi,

This series adds Gen3 VIN support to rcar-vin driver for Renesas r8a7795,
r8a7796 and r8a77970. It is based on the media-tree and depends on 
Fabrizio Castro patches as they touches the order of the compatible 
strings in the documentation to reduce merge conflicts. The dependencies 
are:

[PATCH v2 1/4] dt-bindings: media: rcar_vin: Reverse SoC part number list
[PATCH v2 2/4] dt-bindings: media: rcar_vin: add device tree support for r8a774[35]

The driver is tested on Renesas H3 (r8a7795, ES2.0),
M3-W (r8a7796) together with the rcar-csi2 driver (posted separately and
not yet upstream) and the Salvator-X onboard ADV7482. It is also tested 
on the V3M (r8a77970) on the Eagle board together with its expansion 
board with a ADV7482 and out of tree patches for GMSL capture using the 
max9286 and rdacm20 drivers.

It is possible to capture both CVBS and HDMI video streams,
v4l2-compliance passes with no errors and media-ctl can be used to
change the routing and formats for the different entities in the media
graph.

Gen2 compatibility is verified on Koelsch and no problems where found,
video can be captured just like before and v4l2-compliance passes
without errors or warnings just like before this series.

I have started on a very basic test suite for the VIN driver at:

  https://git.ragnatech.se/vin-tests

And as before the state of the driver and information about how to test
it can be found on the elinux wiki:

  http://elinux.org/R-Car/Tests:rcar-vin

* Changes since v9
- Fixed mistakes in the device tree description pointed out by  Laurent.
    - GenX -> GenX platforms
    - portX -> port X
    - Explicitly state the on Gen3 platforms port 0 can only describe 
      one endpoint and that only VIN instances connected to external 
      pins should have a port 0 node.
    - s/which is/connected to/ in he endpoint description for Gen3 
      platforms.
- Update some poorly written commit messages.
- Moved the digital subdevice attach and detach code to two separate 
  functions to increase readability.
- Rename the struct rvin_info member chip to model to better describe 
  its purpose.
- Change the video name from "rcar_vin e6ef0000.video" to "VINx output" 
  where x is the VIN id.
- Dropped patch 'rcar-vin: do not allow changing scaling and composing 
  while streaming' as it removed Gen2 functionality which is valid as 
  pointed out by Laurent.
- Rename rvin_get_sd_format() to rvin_get_source_format() and change its 
  parameter from struct v4l2_pix_format* to struct v4l2_mbus_framefmt*.
- Clarified commit message and add a few move comments to 'rcar-vin: fix 
  handling of single field frames (top, bottom and alternate fields'.
- Update documentation for struct rvin_dev fields mbus_cfg and code.
- Fix argument in VNCSI_IFMD_CSI_CHSEL macro.
- Renamed rvin_set_chsel() to rvin_set_channel_routing().
- Restore the VNMC register after changing CHSEL setting.
- Broke patch 'rcar-vin: break out format alignment and checking' into 
  three parts to ease review.
- Add new patch to introduce a default field.
- Only include media/v4l2-mc.h in the .c files that needs it and not in 
  rcar-vin.h.
- Rename rvin_group_allocate() rvin_group_get()
- Rename rvin_group_delete() rvin_group_put()
- Updated error message "VIN number %d already occupied\n" to "Duplicate 
  renesas,id property value %u\n".
- Removed dev_dbg messages which only where useful during development.
- Dropped patch '[PATCH v9 10/28] rcar-vin: do not reset crop and 
  compose when setting format' as it introduces a regression on Gen2.
- Inline rvin_group_read_id() and rvin_group_add_vin() into 
  rvin_group_get().
- Define static variables at the top of rcar-core.c.
- Fix potential deadlock in rvin_group_get().
- Set media device model name to the VIN module name.
- Set media device model to matched complicity string.
- Do not use a 2 dimensional sparse array for chsel values in struct 
  rvin_info, instead use a flat array and store VIN and CHSEL value 
  inside each array item.
- Reworked DT parsing code to make use of the new 
  v4l2_async_notifier_parse_fwnode_endpoints_by_port() helper removing a 
  lot of iffy custom parsing code.
- Rework how CHSEL value is calculated in the link notifier callback.
  Using a bitmap of possible values instead of looping over an array 
  turned out great reducing both LoC and increasing readability of the 
  code which was a bit difficult before. It also reduced to memory 
  needed to contain the static routing information.
- Verify the media bus pixel code when starting a stream.
- Take the media device graph lock when figuring out and starting a 
  stream so not to race between simultaneous stream start from multiple 
  rcar-vin instances as they might share common subdevices.
- Added review tags from Laurent.
- Dropped tags from patches that where changed more then just correcting 
  spelling or other gramma errors.

* Changes since v8
- Fixed issue in rvin_group_init() where rvin_group_update_links() was 
  called, but after moving the video device registration to the 
  complete() callback this is now invalid.
- Fixed spelling in commit messages.
- Added review and acks from Hans, Kieran and Rob.

* Changes since v7
- Dropped '[PATCH v7 02/25] rcar-vin: register the video device at probe time'
- Add patch which renames four badly name functions. Some of the 
  renaming was in v7 part of the dropped patch 02/25. Make it a own 
  patch and rename all badly named functions in one patch.
- Add patch to replace part of the functionality of the dropped patch v7 
  02/25. The new patch keeps the subdevice (un)registration calls in the 
  async callbacks bind() and unbind() but moves the direct subdevice 
  initialization which only is used on Gen2 from the Gen2 and Gen3 
  shared rvin_v4l2_register().
- Add patch to enable Renesas V3M (r8a77970)
- Patch 'rcar-vin: parse Gen3 OF and setup media graph' have had code 
  additions since v7 since it now registers the video devices in the 
  async complete() callback instead of at probe time as an effect of 
  dropping v7 02/25.
  - The complete() callback now register all video devices.
  - The unbind() callback now unregister all video devices.
  - A new member '*notifier' is added to struct rvin_group which keeps 
    track of which rcar-vin instance have registered its notifier on the 
    groups behalf.
  For the reason above all Reviewed-by tags have been dropped for this 
  patch.
- Replaced all kernel messages which used of_node_full_name() as now 
  only returns the basename and not till full path, thanks Geert.

    printk("%s", of_node_full_name(ep)); -> printk("%pOF", ep);

- Added Reviewed-by tags from Hans, big thanks!

* Changes since v6
- Rebase ontop of latest media-tree which brings in the use of the
  fwnode async helpers for Gen2.
- Updated DT binding documentation, thanks Laurent for very helpful
  input!
- Removed help text which where copied in from v4l2_ctrl_handler_init()
  documentation when moving that code block, this was a residue from the
  soc_camera conversion and should have been removed at that time.
- Removed bad check of tvnorms which disables IOCTLs if it's not set,
  this was a residue from soc_camera conversion and have use in the
  current driver.
- Moved all subdevice initialization from complete to bound handler
  while improving the unbind handler. With this move all operations of
  the ctrl_handler from the subdevice is handled in either bound or
  unbind removing races pointed out by Laurent.
- Renamed rvin_v4l2_probe() -> rvin_v4l2_register() and
  rvin_v4l2_remove() -> rvin_v4l2_unregister().
- Fold rvin_mbus_supported() into its only caller.
- Sort compatible string entries in ascending order.
- Improved documentation for struct rvin_group_chsel.
- Clarify comment in rvin_group_csi_pad_to_chan().
- Make use of of_device_get_match_data() as suggested by Geert.
- Fixed spelling mistakes.
- Added review tags from Hans.

* Changes since v5
- Extract and make use of common format checking for both Gen2 and Gen3.
- Assign pad at declaration time in rvin_get_sd_format()
- Always call pm_runtime_{get_sync,put}() and v4l2_pipeline_pm_use()
  when opening/closing a video device, remove the check of
  v4l2_fh_is_singular_file().
- Make rvin_set_chsel() return void instead of int since it always
  return 0.
- Simplify the VIN group allocator functions.
- Make the group notifier callbacks and setup more robust.
- Moved the video device registration back to probe time.
- Add H3 ES2.0 support.
- Fix handling of single field formats (top, bottom, alternate) as this
  was obviously wrong before but hidden by the Gen2 scaler support.
- Added review tags from Kieran.

* Changes since v4 (Not posted to ML)
- Updated to the new fwnode functions.
- Moved the registration of the video devices to the async notification
  callback.

* Changes since v3
- Only add neighboring subdevices to the async notifier. Instead of
  parsing the whole OF graph depend on incremental async subnotifier to
  discover the whole pipeline. This is needed to support arbitrarily
  long graphs and support the new ADV7482 prototype driver which Kieran
  is working on.
- Fix warning from lockdep, reported by Kieran.
- Fix commit messages from feedback from Sergei, thanks.
- Fix chip info an OF device ids sorting order, thanks Geert.
- Use subdev->of_node instead of subdev->dev->of_node, thanks Kieran.

* Changes since v2
- Do not try to control the subdevices in the media graph from the rcar-vin
  driver. Have user-space configure to format in the pipeline instead.
- Add link validation before starting the stream.
- Rework on how the subdevices are and the video node behave by defining
  specific V4L2 operations for the MC mode of operation, this simplified
  the driver quit a bit, thanks Laurent!
- Add a new 'renesas,id' DT property which is needed to to be able to
  keep the VIN to CSI-2 routing table inside the driver. Previously this
  information was taken from the CSI-2 DT node which is obviously the
  wrong way to do things. Thanks Laurent for pointing this out.
- Fixed a memory leek in the group allocator function.
- Return -EMLINK instead of -EBUSY if a MC link is not possible given
  the current routing setup.
- Add comments to clarify that the 4 channels from the CSI-2 node is not
  directly related to CSI-2 virtual channels, the CSI-2 node can output
  any VC on any of its output channels.

* Changes since v1
- Remove unneeded casts as pointed out by Geert.
- Fix spelling and DT documentation as pointed out by Geert and Sergei,
  thanks!
- Refresh patch 2/32 with an updated version, thanks Sakari for pointing
  this out.
- Add Sakaris Ack to patch 1/32.
- Rebase on top of v4.9-rc1 instead of v4.9-rc3 to ease integration
  testing together with renesas-drivers tree.


Niklas Söderlund (30):
  rcar-vin: add Gen3 devicetree bindings documentation
  rcar-vin: rename poorly named initialize and cleanup functions
  rcar-vin: unregister video device on driver removal
  rcar-vin: move subdevice handling to async callbacks
  rcar-vin: move model information to own struct
  rcar-vin: move max width and height information to chip information
  rcar-vin: move functions regarding scaling
  rcar-vin: all Gen2 boards can scale simplify logic
  rcar-vin: read subdevice format for crop only when needed
  rcar-vin: fix handling of single field frames (top, bottom and
    alternate fields)
  rcar-vin: move media bus configuration to struct rvin_info
  rcar-vin: enable Gen3 hardware configuration
  rcar-vin: add function to manipulate Gen3 chsel value
  rcar-vin: add flag to switch to media controller mode
  rcar-vin: break out format alignment and checking
  rcar-vin: update bytesperline and sizeimage calculation
  rcar-vin: update pixelformat check for M1
  rcar-vin: add check for colorspace
  rcar-vin: set a default field to fallback on
  rcar-vin: use different v4l2 operations in media controller mode
  rcar-vin: prepare for media controller mode initialization
  rcar-vin: add group allocator functions
  rcar-vin: change name of video device
  rcar-vin: add chsel information to rvin_info
  rcar-vin: parse Gen3 OF and setup media graph
  rcar-vin: add link notify for Gen3
  rcar-vin: extend {start,stop}_streaming to work with media controller
  rcar-vin: enable support for r8a7795
  rcar-vin: enable support for r8a7796
  rcar-vin: enable support for r8a77970

 .../devicetree/bindings/media/rcar_vin.txt         | 118 ++-
 drivers/media/platform/rcar-vin/Kconfig            |   2 +-
 drivers/media/platform/rcar-vin/rcar-core.c        | 945 +++++++++++++++++++--
 drivers/media/platform/rcar-vin/rcar-dma.c         | 844 ++++++++++--------
 drivers/media/platform/rcar-vin/rcar-v4l2.c        | 483 +++++++----
 drivers/media/platform/rcar-vin/rcar-vin.h         | 130 ++-
 6 files changed, 1898 insertions(+), 624 deletions(-)

-- 
2.16.1

^ permalink raw reply	[flat|nested] 65+ messages in thread

* [PATCH v10 01/30] rcar-vin: add Gen3 devicetree bindings documentation
  2018-01-29 16:34 [PATCH v10 00/30] rcar-vin: Add Gen3 with media controller Niklas Söderlund
@ 2018-01-29 16:34 ` Niklas Söderlund
  2018-02-13 15:24   ` Laurent Pinchart
  2018-01-29 16:34 ` [PATCH v10 02/30] rcar-vin: rename poorly named initialize and cleanup functions Niklas Söderlund
                   ` (28 subsequent siblings)
  29 siblings, 1 reply; 65+ messages in thread
From: Niklas Söderlund @ 2018-01-29 16:34 UTC (permalink / raw)
  To: Laurent Pinchart, Hans Verkuil, linux-media
  Cc: linux-renesas-soc, tomoharu.fukawa.eb, Kieran Bingham,
	Niklas Söderlund

Document the devicetree bindings for the CSI-2 inputs available on Gen3.

There is a need to add a custom property 'renesas,id' and to define
which CSI-2 input is described in which endpoint under the port@1 node.
This information is needed since there are a set of predefined routes
between each VIN and CSI-2 block. This routing table will be kept
inside the driver but in order for it to act on it it must know which
VIN and CSI-2 is which.

Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
Acked-by: Rob Herring <robh@kernel.org>
---
 .../devicetree/bindings/media/rcar_vin.txt         | 118 ++++++++++++++++++---
 1 file changed, 106 insertions(+), 12 deletions(-)

diff --git a/Documentation/devicetree/bindings/media/rcar_vin.txt b/Documentation/devicetree/bindings/media/rcar_vin.txt
index c60e6b0a89b67a8c..90d92836284b7f68 100644
--- a/Documentation/devicetree/bindings/media/rcar_vin.txt
+++ b/Documentation/devicetree/bindings/media/rcar_vin.txt
@@ -2,8 +2,12 @@ Renesas R-Car Video Input driver (rcar_vin)
 -------------------------------------------
 
 The rcar_vin device provides video input capabilities for the Renesas R-Car
-family of devices. The current blocks are always slaves and suppot one input
-channel which can be either RGB, YUYV or BT656.
+family of devices.
+
+Each VIN instance has a single parallel input that supports RGB and YUV video,
+with both external synchronization and BT.656 synchronization for the latter.
+Depending on the instance the VIN input is connected to external SoC pins, or
+on Gen3 platforms to a CSI-2 receiver.
 
  - compatible: Must be one or more of the following
    - "renesas,vin-r8a7743" for the R8A7743 device
@@ -16,6 +20,8 @@ channel which can be either RGB, YUYV or BT656.
    - "renesas,vin-r8a7793" for the R8A7793 device
    - "renesas,vin-r8a7794" for the R8A7794 device
    - "renesas,vin-r8a7795" for the R8A7795 device
+   - "renesas,vin-r8a7796" for the R8A7796 device
+   - "renesas,vin-r8a77970" for the R8A77970 device
    - "renesas,rcar-gen2-vin" for a generic R-Car Gen2 or RZ/G1 compatible
      device.
    - "renesas,rcar-gen3-vin" for a generic R-Car Gen3 compatible device.
@@ -31,21 +37,38 @@ channel which can be either RGB, YUYV or BT656.
 Additionally, an alias named vinX will need to be created to specify
 which video input device this is.
 
-The per-board settings:
+The per-board settings Gen2 platforms:
  - port sub-node describing a single endpoint connected to the vin
    as described in video-interfaces.txt[1]. Only the first one will
    be considered as each vin interface has one input port.
 
-   These settings are used to work out video input format and widths
-   into the system.
+The per-board settings Gen3 platforms:
 
+Gen3 platforms can support both a single connected parallel input source
+from external SoC pins (port0) and/or multiple parallel input sources
+from local SoC CSI-2 receivers (port1) depending on SoC.
 
-Device node example
--------------------
+- renesas,id - ID number of the VIN, VINx in the documentation.
+- ports
+    - port 0 - sub-node describing a single endpoint connected to the VIN
+      from external SoC pins described in video-interfaces.txt[1].
+      Describing more then one endpoint in port 0 is invalid. Only VIN
+      instances that are connected to external pins should have port 0.
+    - port 1 - sub-nodes describing one or more endpoints connected to
+      the VIN from local SoC CSI-2 receivers. The endpoint numbers must
+      use the following schema.
 
-	aliases {
-	       vin0 = &vin0;
-	};
+        - Endpoint 0 - sub-node describing the endpoint connected to CSI20
+        - Endpoint 1 - sub-node describing the endpoint connected to CSI21
+        - Endpoint 2 - sub-node describing the endpoint connected to CSI40
+        - Endpoint 3 - sub-node describing the endpoint connected to CSI41
+
+Device node example for Gen2 platforms
+--------------------------------------
+
+        aliases {
+                vin0 = &vin0;
+        };
 
         vin0: vin@e6ef0000 {
                 compatible = "renesas,vin-r8a7790", "renesas,rcar-gen2-vin";
@@ -55,8 +78,8 @@ Device node example
                 status = "disabled";
         };
 
-Board setup example (vin1 composite video input)
-------------------------------------------------
+Board setup example for Gen2 platforms (vin1 composite video input)
+-------------------------------------------------------------------
 
 &i2c2   {
         status = "ok";
@@ -95,6 +118,77 @@ Board setup example (vin1 composite video input)
         };
 };
 
+Device node example for Gen3 platforms
+--------------------------------------
 
+        vin0: video@e6ef0000 {
+                compatible = "renesas,vin-r8a7795";
+                reg = <0 0xe6ef0000 0 0x1000>;
+                interrupts = <GIC_SPI 188 IRQ_TYPE_LEVEL_HIGH>;
+                clocks = <&cpg CPG_MOD 811>;
+                power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                resets = <&cpg 811>;
+                renesas,id = <0>;
+
+                ports {
+                        #address-cells = <1>;
+                        #size-cells = <0>;
+
+                        port@1 {
+                                #address-cells = <1>;
+                                #size-cells = <0>;
+
+                                reg = <1>;
+
+                                vin0csi20: endpoint@0 {
+                                        reg = <0>;
+                                        remote-endpoint= <&csi20vin0>;
+                                };
+                                vin0csi21: endpoint@1 {
+                                        reg = <1>;
+                                        remote-endpoint= <&csi21vin0>;
+                                };
+                                vin0csi40: endpoint@2 {
+                                        reg = <2>;
+                                        remote-endpoint= <&csi40vin0>;
+                                };
+                        };
+                };
+        };
+
+        csi20: csi2@fea80000 {
+                compatible = "renesas,r8a7795-csi2";
+                reg = <0 0xfea80000 0 0x10000>;
+                interrupts = <GIC_SPI 184 IRQ_TYPE_LEVEL_HIGH>;
+                clocks = <&cpg CPG_MOD 714>;
+                power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                resets = <&cpg 714>;
+
+                ports {
+                        #address-cells = <1>;
+                        #size-cells = <0>;
+
+                        port@0 {
+                                reg = <0>;
+                                csi20_in: endpoint {
+                                        clock-lanes = <0>;
+                                        data-lanes = <1>;
+                                        remote-endpoint = <&adv7482_txb>;
+                                };
+                        };
+
+                        port@1 {
+                                #address-cells = <1>;
+                                #size-cells = <0>;
+
+                                reg = <1>;
+
+                                csi20vin0: endpoint@0 {
+                                        reg = <0>;
+                                        remote-endpoint = <&vin0csi20>;
+                                };
+                        };
+                };
+        };
 
 [1] video-interfaces.txt common video media interface
-- 
2.16.1

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v10 02/30] rcar-vin: rename poorly named initialize and cleanup functions
  2018-01-29 16:34 [PATCH v10 00/30] rcar-vin: Add Gen3 with media controller Niklas Söderlund
  2018-01-29 16:34 ` [PATCH v10 01/30] rcar-vin: add Gen3 devicetree bindings documentation Niklas Söderlund
@ 2018-01-29 16:34 ` Niklas Söderlund
  2018-01-29 16:34 ` [PATCH v10 03/30] rcar-vin: unregister video device on driver removal Niklas Söderlund
                   ` (27 subsequent siblings)
  29 siblings, 0 replies; 65+ messages in thread
From: Niklas Söderlund @ 2018-01-29 16:34 UTC (permalink / raw)
  To: Laurent Pinchart, Hans Verkuil, linux-media
  Cc: linux-renesas-soc, tomoharu.fukawa.eb, Kieran Bingham,
	Niklas Söderlund

The functions to register and unregister the hardware and video device
where poorly named from the start. Rename them to better describe their
intended function.

Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/rcar-vin/rcar-core.c | 10 +++++-----
 drivers/media/platform/rcar-vin/rcar-dma.c  |  6 +++---
 drivers/media/platform/rcar-vin/rcar-v4l2.c |  4 ++--
 drivers/media/platform/rcar-vin/rcar-vin.h  |  8 ++++----
 4 files changed, 14 insertions(+), 14 deletions(-)

diff --git a/drivers/media/platform/rcar-vin/rcar-core.c b/drivers/media/platform/rcar-vin/rcar-core.c
index f1fc7978d6d1523d..2bedf20abcf3ca07 100644
--- a/drivers/media/platform/rcar-vin/rcar-core.c
+++ b/drivers/media/platform/rcar-vin/rcar-core.c
@@ -93,7 +93,7 @@ static int rvin_digital_notify_complete(struct v4l2_async_notifier *notifier)
 		return ret;
 	}
 
-	return rvin_v4l2_probe(vin);
+	return rvin_v4l2_register(vin);
 }
 
 static void rvin_digital_notify_unbind(struct v4l2_async_notifier *notifier,
@@ -103,7 +103,7 @@ static void rvin_digital_notify_unbind(struct v4l2_async_notifier *notifier,
 	struct rvin_dev *vin = notifier_to_vin(notifier);
 
 	vin_dbg(vin, "unbind digital subdev %s\n", subdev->name);
-	rvin_v4l2_remove(vin);
+	rvin_v4l2_unregister(vin);
 	vin->digital->subdev = NULL;
 }
 
@@ -245,7 +245,7 @@ static int rcar_vin_probe(struct platform_device *pdev)
 	if (irq < 0)
 		return irq;
 
-	ret = rvin_dma_probe(vin, irq);
+	ret = rvin_dma_register(vin, irq);
 	if (ret)
 		return ret;
 
@@ -260,7 +260,7 @@ static int rcar_vin_probe(struct platform_device *pdev)
 
 	return 0;
 error:
-	rvin_dma_remove(vin);
+	rvin_dma_unregister(vin);
 	v4l2_async_notifier_cleanup(&vin->notifier);
 
 	return ret;
@@ -275,7 +275,7 @@ static int rcar_vin_remove(struct platform_device *pdev)
 	v4l2_async_notifier_unregister(&vin->notifier);
 	v4l2_async_notifier_cleanup(&vin->notifier);
 
-	rvin_dma_remove(vin);
+	rvin_dma_unregister(vin);
 
 	return 0;
 }
diff --git a/drivers/media/platform/rcar-vin/rcar-dma.c b/drivers/media/platform/rcar-vin/rcar-dma.c
index 23fdff7a7370842e..d701b52d198243b5 100644
--- a/drivers/media/platform/rcar-vin/rcar-dma.c
+++ b/drivers/media/platform/rcar-vin/rcar-dma.c
@@ -1153,14 +1153,14 @@ static const struct vb2_ops rvin_qops = {
 	.wait_finish		= vb2_ops_wait_finish,
 };
 
-void rvin_dma_remove(struct rvin_dev *vin)
+void rvin_dma_unregister(struct rvin_dev *vin)
 {
 	mutex_destroy(&vin->lock);
 
 	v4l2_device_unregister(&vin->v4l2_dev);
 }
 
-int rvin_dma_probe(struct rvin_dev *vin, int irq)
+int rvin_dma_register(struct rvin_dev *vin, int irq)
 {
 	struct vb2_queue *q = &vin->queue;
 	int i, ret;
@@ -1208,7 +1208,7 @@ int rvin_dma_probe(struct rvin_dev *vin, int irq)
 
 	return 0;
 error:
-	rvin_dma_remove(vin);
+	rvin_dma_unregister(vin);
 
 	return ret;
 }
diff --git a/drivers/media/platform/rcar-vin/rcar-v4l2.c b/drivers/media/platform/rcar-vin/rcar-v4l2.c
index b479b882da12f62d..178aecc94962abe2 100644
--- a/drivers/media/platform/rcar-vin/rcar-v4l2.c
+++ b/drivers/media/platform/rcar-vin/rcar-v4l2.c
@@ -839,7 +839,7 @@ static const struct v4l2_file_operations rvin_fops = {
 	.read		= vb2_fop_read,
 };
 
-void rvin_v4l2_remove(struct rvin_dev *vin)
+void rvin_v4l2_unregister(struct rvin_dev *vin)
 {
 	v4l2_info(&vin->v4l2_dev, "Removing %s\n",
 		  video_device_node_name(&vin->vdev));
@@ -866,7 +866,7 @@ static void rvin_notify(struct v4l2_subdev *sd,
 	}
 }
 
-int rvin_v4l2_probe(struct rvin_dev *vin)
+int rvin_v4l2_register(struct rvin_dev *vin)
 {
 	struct video_device *vdev = &vin->vdev;
 	struct v4l2_subdev *sd = vin_to_source(vin);
diff --git a/drivers/media/platform/rcar-vin/rcar-vin.h b/drivers/media/platform/rcar-vin/rcar-vin.h
index 5382078143fb3869..85cb7ec53d2b08b5 100644
--- a/drivers/media/platform/rcar-vin/rcar-vin.h
+++ b/drivers/media/platform/rcar-vin/rcar-vin.h
@@ -153,11 +153,11 @@ struct rvin_dev {
 #define vin_warn(d, fmt, arg...)	dev_warn(d->dev, fmt, ##arg)
 #define vin_err(d, fmt, arg...)		dev_err(d->dev, fmt, ##arg)
 
-int rvin_dma_probe(struct rvin_dev *vin, int irq);
-void rvin_dma_remove(struct rvin_dev *vin);
+int rvin_dma_register(struct rvin_dev *vin, int irq);
+void rvin_dma_unregister(struct rvin_dev *vin);
 
-int rvin_v4l2_probe(struct rvin_dev *vin);
-void rvin_v4l2_remove(struct rvin_dev *vin);
+int rvin_v4l2_register(struct rvin_dev *vin);
+void rvin_v4l2_unregister(struct rvin_dev *vin);
 
 const struct rvin_video_format *rvin_format_from_pixel(u32 pixelformat);
 
-- 
2.16.1

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v10 03/30] rcar-vin: unregister video device on driver removal
  2018-01-29 16:34 [PATCH v10 00/30] rcar-vin: Add Gen3 with media controller Niklas Söderlund
  2018-01-29 16:34 ` [PATCH v10 01/30] rcar-vin: add Gen3 devicetree bindings documentation Niklas Söderlund
  2018-01-29 16:34 ` [PATCH v10 02/30] rcar-vin: rename poorly named initialize and cleanup functions Niklas Söderlund
@ 2018-01-29 16:34 ` Niklas Söderlund
  2018-01-29 16:34 ` [PATCH v10 04/30] rcar-vin: move subdevice handling to async callbacks Niklas Söderlund
                   ` (26 subsequent siblings)
  29 siblings, 0 replies; 65+ messages in thread
From: Niklas Söderlund @ 2018-01-29 16:34 UTC (permalink / raw)
  To: Laurent Pinchart, Hans Verkuil, linux-media
  Cc: linux-renesas-soc, tomoharu.fukawa.eb, Kieran Bingham,
	Niklas Söderlund

If the video device was registered by the complete() callback it should
be unregistered when a device is unbound from the driver. Protect from
printing an uninitialized video device node name by adding a check in
rvin_v4l2_unregister() to identify that the video device is registered.

Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/rcar-vin/rcar-core.c | 2 ++
 drivers/media/platform/rcar-vin/rcar-v4l2.c | 3 +++
 2 files changed, 5 insertions(+)

diff --git a/drivers/media/platform/rcar-vin/rcar-core.c b/drivers/media/platform/rcar-vin/rcar-core.c
index 2bedf20abcf3ca07..47f06acde2e698f2 100644
--- a/drivers/media/platform/rcar-vin/rcar-core.c
+++ b/drivers/media/platform/rcar-vin/rcar-core.c
@@ -272,6 +272,8 @@ static int rcar_vin_remove(struct platform_device *pdev)
 
 	pm_runtime_disable(&pdev->dev);
 
+	rvin_v4l2_unregister(vin);
+
 	v4l2_async_notifier_unregister(&vin->notifier);
 	v4l2_async_notifier_cleanup(&vin->notifier);
 
diff --git a/drivers/media/platform/rcar-vin/rcar-v4l2.c b/drivers/media/platform/rcar-vin/rcar-v4l2.c
index 178aecc94962abe2..32a658214f48fa49 100644
--- a/drivers/media/platform/rcar-vin/rcar-v4l2.c
+++ b/drivers/media/platform/rcar-vin/rcar-v4l2.c
@@ -841,6 +841,9 @@ static const struct v4l2_file_operations rvin_fops = {
 
 void rvin_v4l2_unregister(struct rvin_dev *vin)
 {
+	if (!video_is_registered(&vin->vdev))
+		return;
+
 	v4l2_info(&vin->v4l2_dev, "Removing %s\n",
 		  video_device_node_name(&vin->vdev));
 
-- 
2.16.1

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v10 04/30] rcar-vin: move subdevice handling to async callbacks
  2018-01-29 16:34 [PATCH v10 00/30] rcar-vin: Add Gen3 with media controller Niklas Söderlund
                   ` (2 preceding siblings ...)
  2018-01-29 16:34 ` [PATCH v10 03/30] rcar-vin: unregister video device on driver removal Niklas Söderlund
@ 2018-01-29 16:34 ` Niklas Söderlund
  2018-02-13 15:47   ` Laurent Pinchart
  2018-01-29 16:34 ` [PATCH v10 05/30] rcar-vin: move model information to own struct Niklas Söderlund
                   ` (25 subsequent siblings)
  29 siblings, 1 reply; 65+ messages in thread
From: Niklas Söderlund @ 2018-01-29 16:34 UTC (permalink / raw)
  To: Laurent Pinchart, Hans Verkuil, linux-media
  Cc: linux-renesas-soc, tomoharu.fukawa.eb, Kieran Bingham,
	Niklas Söderlund

In preparation for Gen3 support move the subdevice initialization and
clean up from rvin_v4l2_{register,unregister}() directly to the async
callbacks. This simplifies the addition of Gen3 support as the
rvin_v4l2_register() can be shared for both Gen2 and Gen3 while direct
subdevice control are only used on Gen2.

While moving this code drop a large comment which is copied from the
framework documentation and fold rvin_mbus_supported() into its only
caller. Also move the initialization and cleanup code to separate
functions to increase readability.

Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
---
 drivers/media/platform/rcar-vin/rcar-core.c | 108 +++++++++++++++++++---------
 drivers/media/platform/rcar-vin/rcar-v4l2.c |  35 ---------
 2 files changed, 74 insertions(+), 69 deletions(-)

diff --git a/drivers/media/platform/rcar-vin/rcar-core.c b/drivers/media/platform/rcar-vin/rcar-core.c
index 47f06acde2e698f2..663309ca9c04f208 100644
--- a/drivers/media/platform/rcar-vin/rcar-core.c
+++ b/drivers/media/platform/rcar-vin/rcar-core.c
@@ -46,46 +46,88 @@ static int rvin_find_pad(struct v4l2_subdev *sd, int direction)
 	return -EINVAL;
 }
 
-static bool rvin_mbus_supported(struct rvin_graph_entity *entity)
+/* The vin lock shuld be held when calling the subdevice attach and detach */
+static int rvin_digital_subdevice_attach(struct rvin_dev *vin,
+					 struct v4l2_subdev *subdev)
 {
-	struct v4l2_subdev *sd = entity->subdev;
 	struct v4l2_subdev_mbus_code_enum code = {
 		.which = V4L2_SUBDEV_FORMAT_ACTIVE,
 	};
+	int ret;
 
+	/* Find source and sink pad of remote subdevice */
+	ret = rvin_find_pad(subdev, MEDIA_PAD_FL_SOURCE);
+	if (ret < 0)
+		return ret;
+	vin->digital->source_pad = ret;
+
+	ret = rvin_find_pad(subdev, MEDIA_PAD_FL_SINK);
+	vin->digital->sink_pad = ret < 0 ? 0 : ret;
+
+	/* Find compatible subdevices mbus format */
+	vin->digital->code = 0;
 	code.index = 0;
-	code.pad = entity->source_pad;
-	while (!v4l2_subdev_call(sd, pad, enum_mbus_code, NULL, &code)) {
+	code.pad = vin->digital->source_pad;
+	while (!vin->digital->code &&
+	       !v4l2_subdev_call(subdev, pad, enum_mbus_code, NULL, &code)) {
 		code.index++;
 		switch (code.code) {
 		case MEDIA_BUS_FMT_YUYV8_1X16:
 		case MEDIA_BUS_FMT_UYVY8_2X8:
 		case MEDIA_BUS_FMT_UYVY10_2X10:
 		case MEDIA_BUS_FMT_RGB888_1X24:
-			entity->code = code.code;
-			return true;
+			vin->digital->code = code.code;
+			vin_dbg(vin, "Found media bus format for %s: %d\n",
+				subdev->name, vin->digital->code);
+			break;
 		default:
 			break;
 		}
 	}
 
-	return false;
-}
-
-static int rvin_digital_notify_complete(struct v4l2_async_notifier *notifier)
-{
-	struct rvin_dev *vin = notifier_to_vin(notifier);
-	int ret;
-
-	/* Verify subdevices mbus format */
-	if (!rvin_mbus_supported(vin->digital)) {
+	if (!vin->digital->code) {
 		vin_err(vin, "Unsupported media bus format for %s\n",
-			vin->digital->subdev->name);
+			subdev->name);
 		return -EINVAL;
 	}
 
-	vin_dbg(vin, "Found media bus format for %s: %d\n",
-		vin->digital->subdev->name, vin->digital->code);
+	/* Read tvnorms */
+	ret = v4l2_subdev_call(subdev, video, g_tvnorms, &vin->vdev.tvnorms);
+	if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV)
+		return ret;
+
+	/* Add the controls */
+	ret = v4l2_ctrl_handler_init(&vin->ctrl_handler, 16);
+	if (ret < 0)
+		return ret;
+
+	ret = v4l2_ctrl_add_handler(&vin->ctrl_handler, subdev->ctrl_handler,
+				    NULL);
+	if (ret < 0) {
+		v4l2_ctrl_handler_free(&vin->ctrl_handler);
+		return ret;
+	}
+
+	vin->vdev.ctrl_handler = &vin->ctrl_handler;
+
+	vin->digital->subdev = subdev;
+
+	return 0;
+}
+
+static void rvin_digital_subdevice_detach(struct rvin_dev *vin)
+{
+	rvin_v4l2_unregister(vin);
+	v4l2_ctrl_handler_free(&vin->ctrl_handler);
+
+	vin->vdev.ctrl_handler = NULL;
+	vin->digital->subdev = NULL;
+}
+
+static int rvin_digital_notify_complete(struct v4l2_async_notifier *notifier)
+{
+	struct rvin_dev *vin = notifier_to_vin(notifier);
+	int ret;
 
 	ret = v4l2_device_register_subdev_nodes(&vin->v4l2_dev);
 	if (ret < 0) {
@@ -103,8 +145,10 @@ static void rvin_digital_notify_unbind(struct v4l2_async_notifier *notifier,
 	struct rvin_dev *vin = notifier_to_vin(notifier);
 
 	vin_dbg(vin, "unbind digital subdev %s\n", subdev->name);
-	rvin_v4l2_unregister(vin);
-	vin->digital->subdev = NULL;
+
+	mutex_lock(&vin->lock);
+	rvin_digital_subdevice_detach(vin);
+	mutex_unlock(&vin->lock);
 }
 
 static int rvin_digital_notify_bound(struct v4l2_async_notifier *notifier,
@@ -114,33 +158,27 @@ static int rvin_digital_notify_bound(struct v4l2_async_notifier *notifier,
 	struct rvin_dev *vin = notifier_to_vin(notifier);
 	int ret;
 
+	mutex_lock(&vin->lock);
+	ret = rvin_digital_subdevice_attach(vin, subdev);
+	mutex_unlock(&vin->lock);
+	if (ret)
+		return ret;
+
 	v4l2_set_subdev_hostdata(subdev, vin);
 
-	/* Find source and sink pad of remote subdevice */
-
-	ret = rvin_find_pad(subdev, MEDIA_PAD_FL_SOURCE);
-	if (ret < 0)
-		return ret;
-	vin->digital->source_pad = ret;
-
-	ret = rvin_find_pad(subdev, MEDIA_PAD_FL_SINK);
-	vin->digital->sink_pad = ret < 0 ? 0 : ret;
-
-	vin->digital->subdev = subdev;
-
 	vin_dbg(vin, "bound subdev %s source pad: %u sink pad: %u\n",
 		subdev->name, vin->digital->source_pad,
 		vin->digital->sink_pad);
 
 	return 0;
 }
+
 static const struct v4l2_async_notifier_operations rvin_digital_notify_ops = {
 	.bound = rvin_digital_notify_bound,
 	.unbind = rvin_digital_notify_unbind,
 	.complete = rvin_digital_notify_complete,
 };
 
-
 static int rvin_digital_parse_v4l2(struct device *dev,
 				   struct v4l2_fwnode_endpoint *vep,
 				   struct v4l2_async_subdev *asd)
@@ -277,6 +315,8 @@ static int rcar_vin_remove(struct platform_device *pdev)
 	v4l2_async_notifier_unregister(&vin->notifier);
 	v4l2_async_notifier_cleanup(&vin->notifier);
 
+	v4l2_ctrl_handler_free(&vin->ctrl_handler);
+
 	rvin_dma_unregister(vin);
 
 	return 0;
diff --git a/drivers/media/platform/rcar-vin/rcar-v4l2.c b/drivers/media/platform/rcar-vin/rcar-v4l2.c
index 32a658214f48fa49..4a0610a6b4503501 100644
--- a/drivers/media/platform/rcar-vin/rcar-v4l2.c
+++ b/drivers/media/platform/rcar-vin/rcar-v4l2.c
@@ -847,9 +847,6 @@ void rvin_v4l2_unregister(struct rvin_dev *vin)
 	v4l2_info(&vin->v4l2_dev, "Removing %s\n",
 		  video_device_node_name(&vin->vdev));
 
-	/* Checks internaly if handlers have been init or not */
-	v4l2_ctrl_handler_free(&vin->ctrl_handler);
-
 	/* Checks internaly if vdev have been init or not */
 	video_unregister_device(&vin->vdev);
 }
@@ -872,41 +869,10 @@ static void rvin_notify(struct v4l2_subdev *sd,
 int rvin_v4l2_register(struct rvin_dev *vin)
 {
 	struct video_device *vdev = &vin->vdev;
-	struct v4l2_subdev *sd = vin_to_source(vin);
 	int ret;
 
-	v4l2_set_subdev_hostdata(sd, vin);
-
 	vin->v4l2_dev.notify = rvin_notify;
 
-	ret = v4l2_subdev_call(sd, video, g_tvnorms, &vin->vdev.tvnorms);
-	if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV)
-		return ret;
-
-	if (vin->vdev.tvnorms == 0) {
-		/* Disable the STD API if there are no tvnorms defined */
-		v4l2_disable_ioctl(&vin->vdev, VIDIOC_G_STD);
-		v4l2_disable_ioctl(&vin->vdev, VIDIOC_S_STD);
-		v4l2_disable_ioctl(&vin->vdev, VIDIOC_QUERYSTD);
-		v4l2_disable_ioctl(&vin->vdev, VIDIOC_ENUMSTD);
-	}
-
-	/* Add the controls */
-	/*
-	 * Currently the subdev with the largest number of controls (13) is
-	 * ov6550. So let's pick 16 as a hint for the control handler. Note
-	 * that this is a hint only: too large and you waste some memory, too
-	 * small and there is a (very) small performance hit when looking up
-	 * controls in the internal hash.
-	 */
-	ret = v4l2_ctrl_handler_init(&vin->ctrl_handler, 16);
-	if (ret < 0)
-		return ret;
-
-	ret = v4l2_ctrl_add_handler(&vin->ctrl_handler, sd->ctrl_handler, NULL);
-	if (ret < 0)
-		return ret;
-
 	/* video node */
 	vdev->fops = &rvin_fops;
 	vdev->v4l2_dev = &vin->v4l2_dev;
@@ -915,7 +881,6 @@ int rvin_v4l2_register(struct rvin_dev *vin)
 	vdev->release = video_device_release_empty;
 	vdev->ioctl_ops = &rvin_ioctl_ops;
 	vdev->lock = &vin->lock;
-	vdev->ctrl_handler = &vin->ctrl_handler;
 	vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING |
 		V4L2_CAP_READWRITE;
 
-- 
2.16.1

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v10 05/30] rcar-vin: move model information to own struct
  2018-01-29 16:34 [PATCH v10 00/30] rcar-vin: Add Gen3 with media controller Niklas Söderlund
                   ` (3 preceding siblings ...)
  2018-01-29 16:34 ` [PATCH v10 04/30] rcar-vin: move subdevice handling to async callbacks Niklas Söderlund
@ 2018-01-29 16:34 ` Niklas Söderlund
  2018-01-29 16:34 ` [PATCH v10 06/30] rcar-vin: move max width and height information to chip information Niklas Söderlund
                   ` (24 subsequent siblings)
  29 siblings, 0 replies; 65+ messages in thread
From: Niklas Söderlund @ 2018-01-29 16:34 UTC (permalink / raw)
  To: Laurent Pinchart, Hans Verkuil, linux-media
  Cc: linux-renesas-soc, tomoharu.fukawa.eb, Kieran Bingham,
	Niklas Söderlund

When Gen3 support is added to the driver more than model ID will be
different for the different SoCs. To avoid a lot of if statements in the
code create a struct rvin_info to store this information.

While we are at it rename the poorly chosen enum which contains the
different model IDs from chip_id to model_id. Also sort the compatible
string entries and make use of of_device_get_match_data() which will
always work as the driver is DT only, so there's always a valid match.

Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/rcar-vin/rcar-core.c | 56 +++++++++++++++++++++--------
 drivers/media/platform/rcar-vin/rcar-v4l2.c |  3 +-
 drivers/media/platform/rcar-vin/rcar-vin.h  | 14 ++++++--
 3 files changed, 55 insertions(+), 18 deletions(-)

diff --git a/drivers/media/platform/rcar-vin/rcar-core.c b/drivers/media/platform/rcar-vin/rcar-core.c
index 663309ca9c04f208..d2b27ccff690cede 100644
--- a/drivers/media/platform/rcar-vin/rcar-core.c
+++ b/drivers/media/platform/rcar-vin/rcar-core.c
@@ -241,21 +241,53 @@ static int rvin_digital_graph_init(struct rvin_dev *vin)
  * Platform Device Driver
  */
 
+static const struct rvin_info rcar_info_h1 = {
+	.model = RCAR_H1,
+};
+
+static const struct rvin_info rcar_info_m1 = {
+	.model = RCAR_M1,
+};
+
+static const struct rvin_info rcar_info_gen2 = {
+	.model = RCAR_GEN2,
+};
+
 static const struct of_device_id rvin_of_id_table[] = {
-	{ .compatible = "renesas,vin-r8a7794", .data = (void *)RCAR_GEN2 },
-	{ .compatible = "renesas,vin-r8a7793", .data = (void *)RCAR_GEN2 },
-	{ .compatible = "renesas,vin-r8a7791", .data = (void *)RCAR_GEN2 },
-	{ .compatible = "renesas,vin-r8a7790", .data = (void *)RCAR_GEN2 },
-	{ .compatible = "renesas,vin-r8a7779", .data = (void *)RCAR_H1 },
-	{ .compatible = "renesas,vin-r8a7778", .data = (void *)RCAR_M1 },
-	{ .compatible = "renesas,rcar-gen2-vin", .data = (void *)RCAR_GEN2 },
-	{ },
+	{
+		.compatible = "renesas,vin-r8a7778",
+		.data = &rcar_info_m1,
+	},
+	{
+		.compatible = "renesas,vin-r8a7779",
+		.data = &rcar_info_h1,
+	},
+	{
+		.compatible = "renesas,vin-r8a7790",
+		.data = &rcar_info_gen2,
+	},
+	{
+		.compatible = "renesas,vin-r8a7791",
+		.data = &rcar_info_gen2,
+	},
+	{
+		.compatible = "renesas,vin-r8a7793",
+		.data = &rcar_info_gen2,
+	},
+	{
+		.compatible = "renesas,vin-r8a7794",
+		.data = &rcar_info_gen2,
+	},
+	{
+		.compatible = "renesas,rcar-gen2-vin",
+		.data = &rcar_info_gen2,
+	},
+	{ /* Sentinel */ },
 };
 MODULE_DEVICE_TABLE(of, rvin_of_id_table);
 
 static int rcar_vin_probe(struct platform_device *pdev)
 {
-	const struct of_device_id *match;
 	struct rvin_dev *vin;
 	struct resource *mem;
 	int irq, ret;
@@ -264,12 +296,8 @@ static int rcar_vin_probe(struct platform_device *pdev)
 	if (!vin)
 		return -ENOMEM;
 
-	match = of_match_device(of_match_ptr(rvin_of_id_table), &pdev->dev);
-	if (!match)
-		return -ENODEV;
-
 	vin->dev = &pdev->dev;
-	vin->chip = (enum chip_id)match->data;
+	vin->info = of_device_get_match_data(&pdev->dev);
 
 	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (mem == NULL)
diff --git a/drivers/media/platform/rcar-vin/rcar-v4l2.c b/drivers/media/platform/rcar-vin/rcar-v4l2.c
index 4a0610a6b4503501..0a035667c0b0e93f 100644
--- a/drivers/media/platform/rcar-vin/rcar-v4l2.c
+++ b/drivers/media/platform/rcar-vin/rcar-v4l2.c
@@ -266,7 +266,8 @@ static int __rvin_try_format(struct rvin_dev *vin,
 	pix->sizeimage = max_t(u32, pix->sizeimage,
 			       rvin_format_sizeimage(pix));
 
-	if (vin->chip == RCAR_M1 && pix->pixelformat == V4L2_PIX_FMT_XBGR32) {
+	if (vin->info->model == RCAR_M1 &&
+	    pix->pixelformat == V4L2_PIX_FMT_XBGR32) {
 		vin_err(vin, "pixel format XBGR32 not supported on M1\n");
 		return -EINVAL;
 	}
diff --git a/drivers/media/platform/rcar-vin/rcar-vin.h b/drivers/media/platform/rcar-vin/rcar-vin.h
index 85cb7ec53d2b08b5..3f49d2f2d6b88471 100644
--- a/drivers/media/platform/rcar-vin/rcar-vin.h
+++ b/drivers/media/platform/rcar-vin/rcar-vin.h
@@ -29,7 +29,7 @@
 /* Address alignment mask for HW buffers */
 #define HW_BUFFER_MASK 0x7f
 
-enum chip_id {
+enum model_id {
 	RCAR_H1,
 	RCAR_M1,
 	RCAR_GEN2,
@@ -88,11 +88,19 @@ struct rvin_graph_entity {
 	unsigned int sink_pad;
 };
 
+/**
+ * struct rvin_info - Information about the particular VIN implementation
+ * @model:		VIN model
+ */
+struct rvin_info {
+	enum model_id model;
+};
+
 /**
  * struct rvin_dev - Renesas VIN device structure
  * @dev:		(OF) device
  * @base:		device I/O register space remapped to virtual memory
- * @chip:		type of VIN chip
+ * @info:		info about VIN instance
  *
  * @vdev:		V4L2 video device associated with VIN
  * @v4l2_dev:		V4L2 device
@@ -120,7 +128,7 @@ struct rvin_graph_entity {
 struct rvin_dev {
 	struct device *dev;
 	void __iomem *base;
-	enum chip_id chip;
+	const struct rvin_info *info;
 
 	struct video_device vdev;
 	struct v4l2_device v4l2_dev;
-- 
2.16.1

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v10 06/30] rcar-vin: move max width and height information to chip information
  2018-01-29 16:34 [PATCH v10 00/30] rcar-vin: Add Gen3 with media controller Niklas Söderlund
                   ` (4 preceding siblings ...)
  2018-01-29 16:34 ` [PATCH v10 05/30] rcar-vin: move model information to own struct Niklas Söderlund
@ 2018-01-29 16:34 ` Niklas Söderlund
  2018-01-29 16:34 ` [PATCH v10 07/30] rcar-vin: move functions regarding scaling Niklas Söderlund
                   ` (23 subsequent siblings)
  29 siblings, 0 replies; 65+ messages in thread
From: Niklas Söderlund @ 2018-01-29 16:34 UTC (permalink / raw)
  To: Laurent Pinchart, Hans Verkuil, linux-media
  Cc: linux-renesas-soc, tomoharu.fukawa.eb, Kieran Bingham,
	Niklas Söderlund

On Gen3 the max supported width and height will be different from Gen2.
Move the limits to the struct rvin_info to prepare for Gen3 support.

Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/rcar-vin/rcar-core.c | 6 ++++++
 drivers/media/platform/rcar-vin/rcar-v4l2.c | 6 ++----
 drivers/media/platform/rcar-vin/rcar-vin.h  | 5 +++++
 3 files changed, 13 insertions(+), 4 deletions(-)

diff --git a/drivers/media/platform/rcar-vin/rcar-core.c b/drivers/media/platform/rcar-vin/rcar-core.c
index d2b27ccff690cede..cc863e4ec9a4d4b3 100644
--- a/drivers/media/platform/rcar-vin/rcar-core.c
+++ b/drivers/media/platform/rcar-vin/rcar-core.c
@@ -243,14 +243,20 @@ static int rvin_digital_graph_init(struct rvin_dev *vin)
 
 static const struct rvin_info rcar_info_h1 = {
 	.model = RCAR_H1,
+	.max_width = 2048,
+	.max_height = 2048,
 };
 
 static const struct rvin_info rcar_info_m1 = {
 	.model = RCAR_M1,
+	.max_width = 2048,
+	.max_height = 2048,
 };
 
 static const struct rvin_info rcar_info_gen2 = {
 	.model = RCAR_GEN2,
+	.max_width = 2048,
+	.max_height = 2048,
 };
 
 static const struct of_device_id rvin_of_id_table[] = {
diff --git a/drivers/media/platform/rcar-vin/rcar-v4l2.c b/drivers/media/platform/rcar-vin/rcar-v4l2.c
index 0a035667c0b0e93f..8805d7911a761019 100644
--- a/drivers/media/platform/rcar-vin/rcar-v4l2.c
+++ b/drivers/media/platform/rcar-vin/rcar-v4l2.c
@@ -23,8 +23,6 @@
 #include "rcar-vin.h"
 
 #define RVIN_DEFAULT_FORMAT	V4L2_PIX_FMT_YUYV
-#define RVIN_MAX_WIDTH		2048
-#define RVIN_MAX_HEIGHT		2048
 
 /* -----------------------------------------------------------------------------
  * Format Conversions
@@ -258,8 +256,8 @@ static int __rvin_try_format(struct rvin_dev *vin,
 	walign = vin->format.pixelformat == V4L2_PIX_FMT_NV16 ? 5 : 1;
 
 	/* Limit to VIN capabilities */
-	v4l_bound_align_image(&pix->width, 2, RVIN_MAX_WIDTH, walign,
-			      &pix->height, 4, RVIN_MAX_HEIGHT, 2, 0);
+	v4l_bound_align_image(&pix->width, 2, vin->info->max_width, walign,
+			      &pix->height, 4, vin->info->max_height, 2, 0);
 
 	pix->bytesperline = max_t(u32, pix->bytesperline,
 				  rvin_format_bytesperline(pix));
diff --git a/drivers/media/platform/rcar-vin/rcar-vin.h b/drivers/media/platform/rcar-vin/rcar-vin.h
index 3f49d2f2d6b88471..f195d174eeacda10 100644
--- a/drivers/media/platform/rcar-vin/rcar-vin.h
+++ b/drivers/media/platform/rcar-vin/rcar-vin.h
@@ -91,9 +91,14 @@ struct rvin_graph_entity {
 /**
  * struct rvin_info - Information about the particular VIN implementation
  * @model:		VIN model
+ * @max_width:		max input width the VIN supports
+ * @max_height:		max input height the VIN supports
  */
 struct rvin_info {
 	enum model_id model;
+
+	unsigned int max_width;
+	unsigned int max_height;
 };
 
 /**
-- 
2.16.1

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v10 07/30] rcar-vin: move functions regarding scaling
  2018-01-29 16:34 [PATCH v10 00/30] rcar-vin: Add Gen3 with media controller Niklas Söderlund
                   ` (5 preceding siblings ...)
  2018-01-29 16:34 ` [PATCH v10 06/30] rcar-vin: move max width and height information to chip information Niklas Söderlund
@ 2018-01-29 16:34 ` Niklas Söderlund
  2018-01-29 16:34 ` [PATCH v10 08/30] rcar-vin: all Gen2 boards can scale simplify logic Niklas Söderlund
                   ` (22 subsequent siblings)
  29 siblings, 0 replies; 65+ messages in thread
From: Niklas Söderlund @ 2018-01-29 16:34 UTC (permalink / raw)
  To: Laurent Pinchart, Hans Verkuil, linux-media
  Cc: linux-renesas-soc, tomoharu.fukawa.eb, Kieran Bingham,
	Niklas Söderlund

In preparation of refactoring the scaling code move the code regarding
scaling to to the top of the file to avoid the need to add forward
declarations. No code is changed in this commit only whole functions
moved inside the same file.

Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/rcar-vin/rcar-dma.c | 602 +++++++++++++++--------------
 1 file changed, 303 insertions(+), 299 deletions(-)

diff --git a/drivers/media/platform/rcar-vin/rcar-dma.c b/drivers/media/platform/rcar-vin/rcar-dma.c
index d701b52d198243b5..a7cda3922cb74baa 100644
--- a/drivers/media/platform/rcar-vin/rcar-dma.c
+++ b/drivers/media/platform/rcar-vin/rcar-dma.c
@@ -138,305 +138,6 @@ static u32 rvin_read(struct rvin_dev *vin, u32 offset)
 	return ioread32(vin->base + offset);
 }
 
-static int rvin_setup(struct rvin_dev *vin)
-{
-	u32 vnmc, dmr, dmr2, interrupts;
-	v4l2_std_id std;
-	bool progressive = false, output_is_yuv = false, input_is_yuv = false;
-
-	switch (vin->format.field) {
-	case V4L2_FIELD_TOP:
-		vnmc = VNMC_IM_ODD;
-		break;
-	case V4L2_FIELD_BOTTOM:
-		vnmc = VNMC_IM_EVEN;
-		break;
-	case V4L2_FIELD_INTERLACED:
-		/* Default to TB */
-		vnmc = VNMC_IM_FULL;
-		/* Use BT if video standard can be read and is 60 Hz format */
-		if (!v4l2_subdev_call(vin_to_source(vin), video, g_std, &std)) {
-			if (std & V4L2_STD_525_60)
-				vnmc = VNMC_IM_FULL | VNMC_FOC;
-		}
-		break;
-	case V4L2_FIELD_INTERLACED_TB:
-		vnmc = VNMC_IM_FULL;
-		break;
-	case V4L2_FIELD_INTERLACED_BT:
-		vnmc = VNMC_IM_FULL | VNMC_FOC;
-		break;
-	case V4L2_FIELD_ALTERNATE:
-	case V4L2_FIELD_NONE:
-		if (vin->continuous) {
-			vnmc = VNMC_IM_ODD_EVEN;
-			progressive = true;
-		} else {
-			vnmc = VNMC_IM_ODD;
-		}
-		break;
-	default:
-		vnmc = VNMC_IM_ODD;
-		break;
-	}
-
-	/*
-	 * Input interface
-	 */
-	switch (vin->digital->code) {
-	case MEDIA_BUS_FMT_YUYV8_1X16:
-		/* BT.601/BT.1358 16bit YCbCr422 */
-		vnmc |= VNMC_INF_YUV16;
-		input_is_yuv = true;
-		break;
-	case MEDIA_BUS_FMT_UYVY8_2X8:
-		/* BT.656 8bit YCbCr422 or BT.601 8bit YCbCr422 */
-		vnmc |= vin->digital->mbus_cfg.type == V4L2_MBUS_BT656 ?
-			VNMC_INF_YUV8_BT656 : VNMC_INF_YUV8_BT601;
-		input_is_yuv = true;
-		break;
-	case MEDIA_BUS_FMT_RGB888_1X24:
-		vnmc |= VNMC_INF_RGB888;
-		break;
-	case MEDIA_BUS_FMT_UYVY10_2X10:
-		/* BT.656 10bit YCbCr422 or BT.601 10bit YCbCr422 */
-		vnmc |= vin->digital->mbus_cfg.type == V4L2_MBUS_BT656 ?
-			VNMC_INF_YUV10_BT656 : VNMC_INF_YUV10_BT601;
-		input_is_yuv = true;
-		break;
-	default:
-		break;
-	}
-
-	/* Enable VSYNC Field Toogle mode after one VSYNC input */
-	dmr2 = VNDMR2_FTEV | VNDMR2_VLV(1);
-
-	/* Hsync Signal Polarity Select */
-	if (!(vin->digital->mbus_cfg.flags & V4L2_MBUS_HSYNC_ACTIVE_LOW))
-		dmr2 |= VNDMR2_HPS;
-
-	/* Vsync Signal Polarity Select */
-	if (!(vin->digital->mbus_cfg.flags & V4L2_MBUS_VSYNC_ACTIVE_LOW))
-		dmr2 |= VNDMR2_VPS;
-
-	/*
-	 * Output format
-	 */
-	switch (vin->format.pixelformat) {
-	case V4L2_PIX_FMT_NV16:
-		rvin_write(vin,
-			   ALIGN(vin->format.width * vin->format.height, 0x80),
-			   VNUVAOF_REG);
-		dmr = VNDMR_DTMD_YCSEP;
-		output_is_yuv = true;
-		break;
-	case V4L2_PIX_FMT_YUYV:
-		dmr = VNDMR_BPSM;
-		output_is_yuv = true;
-		break;
-	case V4L2_PIX_FMT_UYVY:
-		dmr = 0;
-		output_is_yuv = true;
-		break;
-	case V4L2_PIX_FMT_XRGB555:
-		dmr = VNDMR_DTMD_ARGB1555;
-		break;
-	case V4L2_PIX_FMT_RGB565:
-		dmr = 0;
-		break;
-	case V4L2_PIX_FMT_XBGR32:
-		/* Note: not supported on M1 */
-		dmr = VNDMR_EXRGB;
-		break;
-	default:
-		vin_err(vin, "Invalid pixelformat (0x%x)\n",
-			vin->format.pixelformat);
-		return -EINVAL;
-	}
-
-	/* Always update on field change */
-	vnmc |= VNMC_VUP;
-
-	/* If input and output use the same colorspace, use bypass mode */
-	if (input_is_yuv == output_is_yuv)
-		vnmc |= VNMC_BPS;
-
-	/* Progressive or interlaced mode */
-	interrupts = progressive ? VNIE_FIE : VNIE_EFE;
-
-	/* Ack interrupts */
-	rvin_write(vin, interrupts, VNINTS_REG);
-	/* Enable interrupts */
-	rvin_write(vin, interrupts, VNIE_REG);
-	/* Start capturing */
-	rvin_write(vin, dmr, VNDMR_REG);
-	rvin_write(vin, dmr2, VNDMR2_REG);
-
-	/* Enable module */
-	rvin_write(vin, vnmc | VNMC_ME, VNMC_REG);
-
-	return 0;
-}
-
-static void rvin_disable_interrupts(struct rvin_dev *vin)
-{
-	rvin_write(vin, 0, VNIE_REG);
-}
-
-static u32 rvin_get_interrupt_status(struct rvin_dev *vin)
-{
-	return rvin_read(vin, VNINTS_REG);
-}
-
-static void rvin_ack_interrupt(struct rvin_dev *vin)
-{
-	rvin_write(vin, rvin_read(vin, VNINTS_REG), VNINTS_REG);
-}
-
-static bool rvin_capture_active(struct rvin_dev *vin)
-{
-	return rvin_read(vin, VNMS_REG) & VNMS_CA;
-}
-
-static int rvin_get_active_slot(struct rvin_dev *vin, u32 vnms)
-{
-	if (vin->continuous)
-		return (vnms & VNMS_FBS_MASK) >> VNMS_FBS_SHIFT;
-
-	return 0;
-}
-
-static enum v4l2_field rvin_get_active_field(struct rvin_dev *vin, u32 vnms)
-{
-	if (vin->format.field == V4L2_FIELD_ALTERNATE) {
-		/* If FS is set it's a Even field */
-		if (vnms & VNMS_FS)
-			return V4L2_FIELD_BOTTOM;
-		return V4L2_FIELD_TOP;
-	}
-
-	return vin->format.field;
-}
-
-static void rvin_set_slot_addr(struct rvin_dev *vin, int slot, dma_addr_t addr)
-{
-	const struct rvin_video_format *fmt;
-	int offsetx, offsety;
-	dma_addr_t offset;
-
-	fmt = rvin_format_from_pixel(vin->format.pixelformat);
-
-	/*
-	 * There is no HW support for composition do the beast we can
-	 * by modifying the buffer offset
-	 */
-	offsetx = vin->compose.left * fmt->bpp;
-	offsety = vin->compose.top * vin->format.bytesperline;
-	offset = addr + offsetx + offsety;
-
-	/*
-	 * The address needs to be 128 bytes aligned. Driver should never accept
-	 * settings that do not satisfy this in the first place...
-	 */
-	if (WARN_ON((offsetx | offsety | offset) & HW_BUFFER_MASK))
-		return;
-
-	rvin_write(vin, offset, VNMB_REG(slot));
-}
-
-/* Moves a buffer from the queue to the HW slots */
-static bool rvin_fill_hw_slot(struct rvin_dev *vin, int slot)
-{
-	struct rvin_buffer *buf;
-	struct vb2_v4l2_buffer *vbuf;
-	dma_addr_t phys_addr_top;
-
-	if (vin->queue_buf[slot] != NULL)
-		return true;
-
-	if (list_empty(&vin->buf_list))
-		return false;
-
-	vin_dbg(vin, "Filling HW slot: %d\n", slot);
-
-	/* Keep track of buffer we give to HW */
-	buf = list_entry(vin->buf_list.next, struct rvin_buffer, list);
-	vbuf = &buf->vb;
-	list_del_init(to_buf_list(vbuf));
-	vin->queue_buf[slot] = vbuf;
-
-	/* Setup DMA */
-	phys_addr_top = vb2_dma_contig_plane_dma_addr(&vbuf->vb2_buf, 0);
-	rvin_set_slot_addr(vin, slot, phys_addr_top);
-
-	return true;
-}
-
-static bool rvin_fill_hw(struct rvin_dev *vin)
-{
-	int slot, limit;
-
-	limit = vin->continuous ? HW_BUFFER_NUM : 1;
-
-	for (slot = 0; slot < limit; slot++)
-		if (!rvin_fill_hw_slot(vin, slot))
-			return false;
-	return true;
-}
-
-static void rvin_capture_on(struct rvin_dev *vin)
-{
-	vin_dbg(vin, "Capture on in %s mode\n",
-		vin->continuous ? "continuous" : "single");
-
-	if (vin->continuous)
-		/* Continuous Frame Capture Mode */
-		rvin_write(vin, VNFC_C_FRAME, VNFC_REG);
-	else
-		/* Single Frame Capture Mode */
-		rvin_write(vin, VNFC_S_FRAME, VNFC_REG);
-}
-
-static int rvin_capture_start(struct rvin_dev *vin)
-{
-	struct rvin_buffer *buf, *node;
-	int bufs, ret;
-
-	/* Count number of free buffers */
-	bufs = 0;
-	list_for_each_entry_safe(buf, node, &vin->buf_list, list)
-		bufs++;
-
-	/* Continuous capture requires more buffers then there are HW slots */
-	vin->continuous = bufs > HW_BUFFER_NUM;
-
-	if (!rvin_fill_hw(vin)) {
-		vin_err(vin, "HW not ready to start, not enough buffers available\n");
-		return -EINVAL;
-	}
-
-	rvin_crop_scale_comp(vin);
-
-	ret = rvin_setup(vin);
-	if (ret)
-		return ret;
-
-	rvin_capture_on(vin);
-
-	vin->state = RUNNING;
-
-	return 0;
-}
-
-static void rvin_capture_stop(struct rvin_dev *vin)
-{
-	/* Set continuous & single transfer off */
-	rvin_write(vin, 0, VNFC_REG);
-
-	/* Disable module */
-	rvin_write(vin, rvin_read(vin, VNMC_REG) & ~VNMC_ME, VNMC_REG);
-}
-
 /* -----------------------------------------------------------------------------
  * Crop and Scaling Gen2
  */
@@ -892,6 +593,309 @@ void rvin_scale_try(struct rvin_dev *vin, struct v4l2_pix_format *pix,
 	pix->height = height;
 }
 
+/* -----------------------------------------------------------------------------
+ * Hardware setup
+ */
+
+static int rvin_setup(struct rvin_dev *vin)
+{
+	u32 vnmc, dmr, dmr2, interrupts;
+	v4l2_std_id std;
+	bool progressive = false, output_is_yuv = false, input_is_yuv = false;
+
+	switch (vin->format.field) {
+	case V4L2_FIELD_TOP:
+		vnmc = VNMC_IM_ODD;
+		break;
+	case V4L2_FIELD_BOTTOM:
+		vnmc = VNMC_IM_EVEN;
+		break;
+	case V4L2_FIELD_INTERLACED:
+		/* Default to TB */
+		vnmc = VNMC_IM_FULL;
+		/* Use BT if video standard can be read and is 60 Hz format */
+		if (!v4l2_subdev_call(vin_to_source(vin), video, g_std, &std)) {
+			if (std & V4L2_STD_525_60)
+				vnmc = VNMC_IM_FULL | VNMC_FOC;
+		}
+		break;
+	case V4L2_FIELD_INTERLACED_TB:
+		vnmc = VNMC_IM_FULL;
+		break;
+	case V4L2_FIELD_INTERLACED_BT:
+		vnmc = VNMC_IM_FULL | VNMC_FOC;
+		break;
+	case V4L2_FIELD_ALTERNATE:
+	case V4L2_FIELD_NONE:
+		if (vin->continuous) {
+			vnmc = VNMC_IM_ODD_EVEN;
+			progressive = true;
+		} else {
+			vnmc = VNMC_IM_ODD;
+		}
+		break;
+	default:
+		vnmc = VNMC_IM_ODD;
+		break;
+	}
+
+	/*
+	 * Input interface
+	 */
+	switch (vin->digital->code) {
+	case MEDIA_BUS_FMT_YUYV8_1X16:
+		/* BT.601/BT.1358 16bit YCbCr422 */
+		vnmc |= VNMC_INF_YUV16;
+		input_is_yuv = true;
+		break;
+	case MEDIA_BUS_FMT_UYVY8_2X8:
+		/* BT.656 8bit YCbCr422 or BT.601 8bit YCbCr422 */
+		vnmc |= vin->digital->mbus_cfg.type == V4L2_MBUS_BT656 ?
+			VNMC_INF_YUV8_BT656 : VNMC_INF_YUV8_BT601;
+		input_is_yuv = true;
+		break;
+	case MEDIA_BUS_FMT_RGB888_1X24:
+		vnmc |= VNMC_INF_RGB888;
+		break;
+	case MEDIA_BUS_FMT_UYVY10_2X10:
+		/* BT.656 10bit YCbCr422 or BT.601 10bit YCbCr422 */
+		vnmc |= vin->digital->mbus_cfg.type == V4L2_MBUS_BT656 ?
+			VNMC_INF_YUV10_BT656 : VNMC_INF_YUV10_BT601;
+		input_is_yuv = true;
+		break;
+	default:
+		break;
+	}
+
+	/* Enable VSYNC Field Toogle mode after one VSYNC input */
+	dmr2 = VNDMR2_FTEV | VNDMR2_VLV(1);
+
+	/* Hsync Signal Polarity Select */
+	if (!(vin->digital->mbus_cfg.flags & V4L2_MBUS_HSYNC_ACTIVE_LOW))
+		dmr2 |= VNDMR2_HPS;
+
+	/* Vsync Signal Polarity Select */
+	if (!(vin->digital->mbus_cfg.flags & V4L2_MBUS_VSYNC_ACTIVE_LOW))
+		dmr2 |= VNDMR2_VPS;
+
+	/*
+	 * Output format
+	 */
+	switch (vin->format.pixelformat) {
+	case V4L2_PIX_FMT_NV16:
+		rvin_write(vin,
+			   ALIGN(vin->format.width * vin->format.height, 0x80),
+			   VNUVAOF_REG);
+		dmr = VNDMR_DTMD_YCSEP;
+		output_is_yuv = true;
+		break;
+	case V4L2_PIX_FMT_YUYV:
+		dmr = VNDMR_BPSM;
+		output_is_yuv = true;
+		break;
+	case V4L2_PIX_FMT_UYVY:
+		dmr = 0;
+		output_is_yuv = true;
+		break;
+	case V4L2_PIX_FMT_XRGB555:
+		dmr = VNDMR_DTMD_ARGB1555;
+		break;
+	case V4L2_PIX_FMT_RGB565:
+		dmr = 0;
+		break;
+	case V4L2_PIX_FMT_XBGR32:
+		/* Note: not supported on M1 */
+		dmr = VNDMR_EXRGB;
+		break;
+	default:
+		vin_err(vin, "Invalid pixelformat (0x%x)\n",
+			vin->format.pixelformat);
+		return -EINVAL;
+	}
+
+	/* Always update on field change */
+	vnmc |= VNMC_VUP;
+
+	/* If input and output use the same colorspace, use bypass mode */
+	if (input_is_yuv == output_is_yuv)
+		vnmc |= VNMC_BPS;
+
+	/* Progressive or interlaced mode */
+	interrupts = progressive ? VNIE_FIE : VNIE_EFE;
+
+	/* Ack interrupts */
+	rvin_write(vin, interrupts, VNINTS_REG);
+	/* Enable interrupts */
+	rvin_write(vin, interrupts, VNIE_REG);
+	/* Start capturing */
+	rvin_write(vin, dmr, VNDMR_REG);
+	rvin_write(vin, dmr2, VNDMR2_REG);
+
+	/* Enable module */
+	rvin_write(vin, vnmc | VNMC_ME, VNMC_REG);
+
+	return 0;
+}
+
+static void rvin_disable_interrupts(struct rvin_dev *vin)
+{
+	rvin_write(vin, 0, VNIE_REG);
+}
+
+static u32 rvin_get_interrupt_status(struct rvin_dev *vin)
+{
+	return rvin_read(vin, VNINTS_REG);
+}
+
+static void rvin_ack_interrupt(struct rvin_dev *vin)
+{
+	rvin_write(vin, rvin_read(vin, VNINTS_REG), VNINTS_REG);
+}
+
+static bool rvin_capture_active(struct rvin_dev *vin)
+{
+	return rvin_read(vin, VNMS_REG) & VNMS_CA;
+}
+
+static int rvin_get_active_slot(struct rvin_dev *vin, u32 vnms)
+{
+	if (vin->continuous)
+		return (vnms & VNMS_FBS_MASK) >> VNMS_FBS_SHIFT;
+
+	return 0;
+}
+
+static enum v4l2_field rvin_get_active_field(struct rvin_dev *vin, u32 vnms)
+{
+	if (vin->format.field == V4L2_FIELD_ALTERNATE) {
+		/* If FS is set it's a Even field */
+		if (vnms & VNMS_FS)
+			return V4L2_FIELD_BOTTOM;
+		return V4L2_FIELD_TOP;
+	}
+
+	return vin->format.field;
+}
+
+static void rvin_set_slot_addr(struct rvin_dev *vin, int slot, dma_addr_t addr)
+{
+	const struct rvin_video_format *fmt;
+	int offsetx, offsety;
+	dma_addr_t offset;
+
+	fmt = rvin_format_from_pixel(vin->format.pixelformat);
+
+	/*
+	 * There is no HW support for composition do the beast we can
+	 * by modifying the buffer offset
+	 */
+	offsetx = vin->compose.left * fmt->bpp;
+	offsety = vin->compose.top * vin->format.bytesperline;
+	offset = addr + offsetx + offsety;
+
+	/*
+	 * The address needs to be 128 bytes aligned. Driver should never accept
+	 * settings that do not satisfy this in the first place...
+	 */
+	if (WARN_ON((offsetx | offsety | offset) & HW_BUFFER_MASK))
+		return;
+
+	rvin_write(vin, offset, VNMB_REG(slot));
+}
+
+/* Moves a buffer from the queue to the HW slots */
+static bool rvin_fill_hw_slot(struct rvin_dev *vin, int slot)
+{
+	struct rvin_buffer *buf;
+	struct vb2_v4l2_buffer *vbuf;
+	dma_addr_t phys_addr_top;
+
+	if (vin->queue_buf[slot] != NULL)
+		return true;
+
+	if (list_empty(&vin->buf_list))
+		return false;
+
+	vin_dbg(vin, "Filling HW slot: %d\n", slot);
+
+	/* Keep track of buffer we give to HW */
+	buf = list_entry(vin->buf_list.next, struct rvin_buffer, list);
+	vbuf = &buf->vb;
+	list_del_init(to_buf_list(vbuf));
+	vin->queue_buf[slot] = vbuf;
+
+	/* Setup DMA */
+	phys_addr_top = vb2_dma_contig_plane_dma_addr(&vbuf->vb2_buf, 0);
+	rvin_set_slot_addr(vin, slot, phys_addr_top);
+
+	return true;
+}
+
+static bool rvin_fill_hw(struct rvin_dev *vin)
+{
+	int slot, limit;
+
+	limit = vin->continuous ? HW_BUFFER_NUM : 1;
+
+	for (slot = 0; slot < limit; slot++)
+		if (!rvin_fill_hw_slot(vin, slot))
+			return false;
+	return true;
+}
+
+static void rvin_capture_on(struct rvin_dev *vin)
+{
+	vin_dbg(vin, "Capture on in %s mode\n",
+		vin->continuous ? "continuous" : "single");
+
+	if (vin->continuous)
+		/* Continuous Frame Capture Mode */
+		rvin_write(vin, VNFC_C_FRAME, VNFC_REG);
+	else
+		/* Single Frame Capture Mode */
+		rvin_write(vin, VNFC_S_FRAME, VNFC_REG);
+}
+
+static int rvin_capture_start(struct rvin_dev *vin)
+{
+	struct rvin_buffer *buf, *node;
+	int bufs, ret;
+
+	/* Count number of free buffers */
+	bufs = 0;
+	list_for_each_entry_safe(buf, node, &vin->buf_list, list)
+		bufs++;
+
+	/* Continuous capture requires more buffers then there are HW slots */
+	vin->continuous = bufs > HW_BUFFER_NUM;
+
+	if (!rvin_fill_hw(vin)) {
+		vin_err(vin, "HW not ready to start, not enough buffers available\n");
+		return -EINVAL;
+	}
+
+	rvin_crop_scale_comp(vin);
+
+	ret = rvin_setup(vin);
+	if (ret)
+		return ret;
+
+	rvin_capture_on(vin);
+
+	vin->state = RUNNING;
+
+	return 0;
+}
+
+static void rvin_capture_stop(struct rvin_dev *vin)
+{
+	/* Set continuous & single transfer off */
+	rvin_write(vin, 0, VNFC_REG);
+
+	/* Disable module */
+	rvin_write(vin, rvin_read(vin, VNMC_REG) & ~VNMC_ME, VNMC_REG);
+}
+
 /* -----------------------------------------------------------------------------
  * DMA Functions
  */
-- 
2.16.1

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v10 08/30] rcar-vin: all Gen2 boards can scale simplify logic
  2018-01-29 16:34 [PATCH v10 00/30] rcar-vin: Add Gen3 with media controller Niklas Söderlund
                   ` (6 preceding siblings ...)
  2018-01-29 16:34 ` [PATCH v10 07/30] rcar-vin: move functions regarding scaling Niklas Söderlund
@ 2018-01-29 16:34 ` Niklas Söderlund
  2018-01-29 16:34 ` [PATCH v10 09/30] rcar-vin: read subdevice format for crop only when needed Niklas Söderlund
                   ` (21 subsequent siblings)
  29 siblings, 0 replies; 65+ messages in thread
From: Niklas Söderlund @ 2018-01-29 16:34 UTC (permalink / raw)
  To: Laurent Pinchart, Hans Verkuil, linux-media
  Cc: linux-renesas-soc, tomoharu.fukawa.eb, Kieran Bingham,
	Niklas Söderlund

The logic to preserve the requested format width and height are too
complex and come from a premature optimization for Gen3. All Gen2 SoC
can scale and the Gen3 implementation will not use these functions at
all so simply preserve the width and height when interacting with the
subdevice much like the field is preserved simplifies the logic quite a
bit.

Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/rcar-vin/rcar-dma.c  |  8 --------
 drivers/media/platform/rcar-vin/rcar-v4l2.c | 25 +++++++++++--------------
 drivers/media/platform/rcar-vin/rcar-vin.h  |  2 --
 3 files changed, 11 insertions(+), 24 deletions(-)

diff --git a/drivers/media/platform/rcar-vin/rcar-dma.c b/drivers/media/platform/rcar-vin/rcar-dma.c
index a7cda3922cb74baa..fd14be20a6604d7a 100644
--- a/drivers/media/platform/rcar-vin/rcar-dma.c
+++ b/drivers/media/platform/rcar-vin/rcar-dma.c
@@ -585,14 +585,6 @@ void rvin_crop_scale_comp(struct rvin_dev *vin)
 		0, 0);
 }
 
-void rvin_scale_try(struct rvin_dev *vin, struct v4l2_pix_format *pix,
-		    u32 width, u32 height)
-{
-	/* All VIN channels on Gen2 have scalers */
-	pix->width = width;
-	pix->height = height;
-}
-
 /* -----------------------------------------------------------------------------
  * Hardware setup
  */
diff --git a/drivers/media/platform/rcar-vin/rcar-v4l2.c b/drivers/media/platform/rcar-vin/rcar-v4l2.c
index 8805d7911a761019..c2265324c7c96308 100644
--- a/drivers/media/platform/rcar-vin/rcar-v4l2.c
+++ b/drivers/media/platform/rcar-vin/rcar-v4l2.c
@@ -166,6 +166,7 @@ static int __rvin_try_format_source(struct rvin_dev *vin,
 		.which = which,
 	};
 	enum v4l2_field field;
+	u32 width, height;
 	int ret;
 
 	sd = vin_to_source(vin);
@@ -178,7 +179,10 @@ static int __rvin_try_format_source(struct rvin_dev *vin,
 
 	format.pad = vin->digital->source_pad;
 
+	/* Allow the video device to override field and to scale */
 	field = pix->field;
+	width = pix->width;
+	height = pix->height;
 
 	ret = v4l2_subdev_call(sd, pad, set_fmt, pad_cfg, &format);
 	if (ret < 0 && ret != -ENOIOCTLCMD)
@@ -186,11 +190,13 @@ static int __rvin_try_format_source(struct rvin_dev *vin,
 
 	v4l2_fill_pix_format(pix, &format.format);
 
-	pix->field = field;
-
 	source->width = pix->width;
 	source->height = pix->height;
 
+	pix->field = field;
+	pix->width = width;
+	pix->height = height;
+
 	vin_dbg(vin, "Source resolution: %ux%u\n", source->width,
 		source->height);
 
@@ -204,13 +210,9 @@ static int __rvin_try_format(struct rvin_dev *vin,
 			     struct v4l2_pix_format *pix,
 			     struct rvin_source_fmt *source)
 {
-	u32 rwidth, rheight, walign;
+	u32 walign;
 	int ret;
 
-	/* Requested */
-	rwidth = pix->width;
-	rheight = pix->height;
-
 	/* Keep current field if no specific one is asked for */
 	if (pix->field == V4L2_FIELD_ANY)
 		pix->field = vin->format.field;
@@ -248,10 +250,6 @@ static int __rvin_try_format(struct rvin_dev *vin,
 		break;
 	}
 
-	/* If source can't match format try if VIN can scale */
-	if (source->width != rwidth || source->height != rheight)
-		rvin_scale_try(vin, pix, rwidth, rheight);
-
 	/* HW limit width to a multiple of 32 (2^5) for NV16 else 2 (2^1) */
 	walign = vin->format.pixelformat == V4L2_PIX_FMT_NV16 ? 5 : 1;
 
@@ -270,9 +268,8 @@ static int __rvin_try_format(struct rvin_dev *vin,
 		return -EINVAL;
 	}
 
-	vin_dbg(vin, "Requested %ux%u Got %ux%u bpl: %d size: %d\n",
-		rwidth, rheight, pix->width, pix->height,
-		pix->bytesperline, pix->sizeimage);
+	vin_dbg(vin, "Format %ux%u bpl: %d size: %d\n",
+		pix->width, pix->height, pix->bytesperline, pix->sizeimage);
 
 	return 0;
 }
diff --git a/drivers/media/platform/rcar-vin/rcar-vin.h b/drivers/media/platform/rcar-vin/rcar-vin.h
index f195d174eeacda10..8daba9db0e927a49 100644
--- a/drivers/media/platform/rcar-vin/rcar-vin.h
+++ b/drivers/media/platform/rcar-vin/rcar-vin.h
@@ -175,8 +175,6 @@ void rvin_v4l2_unregister(struct rvin_dev *vin);
 const struct rvin_video_format *rvin_format_from_pixel(u32 pixelformat);
 
 /* Cropping, composing and scaling */
-void rvin_scale_try(struct rvin_dev *vin, struct v4l2_pix_format *pix,
-		    u32 width, u32 height);
 void rvin_crop_scale_comp(struct rvin_dev *vin);
 
 #endif
-- 
2.16.1

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v10 09/30] rcar-vin: read subdevice format for crop only when needed
  2018-01-29 16:34 [PATCH v10 00/30] rcar-vin: Add Gen3 with media controller Niklas Söderlund
                   ` (7 preceding siblings ...)
  2018-01-29 16:34 ` [PATCH v10 08/30] rcar-vin: all Gen2 boards can scale simplify logic Niklas Söderlund
@ 2018-01-29 16:34 ` Niklas Söderlund
  2018-02-13 16:14   ` Laurent Pinchart
  2018-01-29 16:34 ` [PATCH v10 10/30] rcar-vin: fix handling of single field frames (top, bottom and alternate fields) Niklas Söderlund
                   ` (20 subsequent siblings)
  29 siblings, 1 reply; 65+ messages in thread
From: Niklas Söderlund @ 2018-01-29 16:34 UTC (permalink / raw)
  To: Laurent Pinchart, Hans Verkuil, linux-media
  Cc: linux-renesas-soc, tomoharu.fukawa.eb, Kieran Bingham,
	Niklas Söderlund

Instead of caching the subdevice format each time the video device
format is set read it directly when it's needed. As it turns out the
format is only needed when figuring out the max rectangle for cropping.

This simplifies the code and makes it clearer what the source format is
used for.

Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
---
 drivers/media/platform/rcar-vin/rcar-v4l2.c | 112 +++++++++++++++-------------
 drivers/media/platform/rcar-vin/rcar-vin.h  |  12 ---
 2 files changed, 61 insertions(+), 63 deletions(-)

diff --git a/drivers/media/platform/rcar-vin/rcar-v4l2.c b/drivers/media/platform/rcar-vin/rcar-v4l2.c
index c2265324c7c96308..4d5be2d0c79c9c9a 100644
--- a/drivers/media/platform/rcar-vin/rcar-v4l2.c
+++ b/drivers/media/platform/rcar-vin/rcar-v4l2.c
@@ -90,35 +90,54 @@ static u32 rvin_format_sizeimage(struct v4l2_pix_format *pix)
  * V4L2
  */
 
-static void rvin_reset_crop_compose(struct rvin_dev *vin)
+static int rvin_get_source_format(struct rvin_dev *vin,
+				  struct v4l2_mbus_framefmt *mbus_fmt)
 {
+	struct v4l2_subdev_format fmt = {
+		.which = V4L2_SUBDEV_FORMAT_ACTIVE,
+		.pad = vin->digital->source_pad,
+	};
+	int ret;
+
+	ret = v4l2_subdev_call(vin_to_source(vin), pad, get_fmt, NULL, &fmt);
+	if (ret)
+		return ret;
+
+	memcpy(mbus_fmt, &fmt.format, sizeof(*mbus_fmt));
+
+	return 0;
+}
+
+static int rvin_reset_crop_compose(struct rvin_dev *vin)
+{
+	struct v4l2_mbus_framefmt source_fmt;
+	int ret;
+
+	ret = rvin_get_source_format(vin, &source_fmt);
+	if (ret)
+		return ret;
+
 	vin->crop.top = vin->crop.left = 0;
-	vin->crop.width = vin->source.width;
-	vin->crop.height = vin->source.height;
+	vin->crop.width = source_fmt.width;
+	vin->crop.height = source_fmt.height;
 
 	vin->compose.top = vin->compose.left = 0;
 	vin->compose.width = vin->format.width;
 	vin->compose.height = vin->format.height;
+
+	return 0;
 }
 
 static int rvin_reset_format(struct rvin_dev *vin)
 {
-	struct v4l2_subdev_format fmt = {
-		.which = V4L2_SUBDEV_FORMAT_ACTIVE,
-	};
-	struct v4l2_mbus_framefmt *mf = &fmt.format;
+	struct v4l2_mbus_framefmt source_fmt;
 	int ret;
 
-	fmt.pad = vin->digital->source_pad;
-
-	ret = v4l2_subdev_call(vin_to_source(vin), pad, get_fmt, NULL, &fmt);
+	ret = rvin_get_source_format(vin, &source_fmt);
 	if (ret)
 		return ret;
 
-	vin->format.width	= mf->width;
-	vin->format.height	= mf->height;
-	vin->format.colorspace	= mf->colorspace;
-	vin->format.field	= mf->field;
+	v4l2_fill_pix_format(&vin->format, &source_fmt);
 
 	/*
 	 * If the subdevice uses ALTERNATE field mode and G_STD is
@@ -147,7 +166,9 @@ static int rvin_reset_format(struct rvin_dev *vin)
 		break;
 	}
 
-	rvin_reset_crop_compose(vin);
+	ret = rvin_reset_crop_compose(vin);
+	if (ret)
+		return ret;
 
 	vin->format.bytesperline = rvin_format_bytesperline(&vin->format);
 	vin->format.sizeimage = rvin_format_sizeimage(&vin->format);
@@ -156,9 +177,7 @@ static int rvin_reset_format(struct rvin_dev *vin)
 }
 
 static int __rvin_try_format_source(struct rvin_dev *vin,
-				    u32 which,
-				    struct v4l2_pix_format *pix,
-				    struct rvin_source_fmt *source)
+				    u32 which, struct v4l2_pix_format *pix)
 {
 	struct v4l2_subdev *sd;
 	struct v4l2_subdev_pad_config *pad_cfg;
@@ -190,25 +209,16 @@ static int __rvin_try_format_source(struct rvin_dev *vin,
 
 	v4l2_fill_pix_format(pix, &format.format);
 
-	source->width = pix->width;
-	source->height = pix->height;
-
 	pix->field = field;
 	pix->width = width;
 	pix->height = height;
-
-	vin_dbg(vin, "Source resolution: %ux%u\n", source->width,
-		source->height);
-
 done:
 	v4l2_subdev_free_pad_config(pad_cfg);
 	return ret;
 }
 
 static int __rvin_try_format(struct rvin_dev *vin,
-			     u32 which,
-			     struct v4l2_pix_format *pix,
-			     struct rvin_source_fmt *source)
+			     u32 which, struct v4l2_pix_format *pix)
 {
 	u32 walign;
 	int ret;
@@ -229,7 +239,7 @@ static int __rvin_try_format(struct rvin_dev *vin,
 	pix->sizeimage = 0;
 
 	/* Limit to source capabilities */
-	ret = __rvin_try_format_source(vin, which, pix, source);
+	ret = __rvin_try_format_source(vin, which, pix);
 	if (ret)
 		return ret;
 
@@ -238,7 +248,6 @@ static int __rvin_try_format(struct rvin_dev *vin,
 	case V4L2_FIELD_BOTTOM:
 	case V4L2_FIELD_ALTERNATE:
 		pix->height /= 2;
-		source->height /= 2;
 		break;
 	case V4L2_FIELD_NONE:
 	case V4L2_FIELD_INTERLACED_TB:
@@ -290,35 +299,26 @@ static int rvin_try_fmt_vid_cap(struct file *file, void *priv,
 				struct v4l2_format *f)
 {
 	struct rvin_dev *vin = video_drvdata(file);
-	struct rvin_source_fmt source;
 
-	return __rvin_try_format(vin, V4L2_SUBDEV_FORMAT_TRY, &f->fmt.pix,
-				 &source);
+	return __rvin_try_format(vin, V4L2_SUBDEV_FORMAT_TRY, &f->fmt.pix);
 }
 
 static int rvin_s_fmt_vid_cap(struct file *file, void *priv,
 			      struct v4l2_format *f)
 {
 	struct rvin_dev *vin = video_drvdata(file);
-	struct rvin_source_fmt source;
 	int ret;
 
 	if (vb2_is_busy(&vin->queue))
 		return -EBUSY;
 
-	ret = __rvin_try_format(vin, V4L2_SUBDEV_FORMAT_ACTIVE, &f->fmt.pix,
-				&source);
+	ret = __rvin_try_format(vin, V4L2_SUBDEV_FORMAT_ACTIVE, &f->fmt.pix);
 	if (ret)
 		return ret;
 
-	vin->source.width = source.width;
-	vin->source.height = source.height;
-
 	vin->format = f->fmt.pix;
 
-	rvin_reset_crop_compose(vin);
-
-	return 0;
+	return rvin_reset_crop_compose(vin);
 }
 
 static int rvin_g_fmt_vid_cap(struct file *file, void *priv,
@@ -346,6 +346,8 @@ static int rvin_g_selection(struct file *file, void *fh,
 			    struct v4l2_selection *s)
 {
 	struct rvin_dev *vin = video_drvdata(file);
+	struct v4l2_mbus_framefmt source_fmt;
+	int ret;
 
 	if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
 		return -EINVAL;
@@ -353,9 +355,12 @@ static int rvin_g_selection(struct file *file, void *fh,
 	switch (s->target) {
 	case V4L2_SEL_TGT_CROP_BOUNDS:
 	case V4L2_SEL_TGT_CROP_DEFAULT:
+		ret = rvin_get_source_format(vin, &source_fmt);
+		if (ret)
+			return ret;
 		s->r.left = s->r.top = 0;
-		s->r.width = vin->source.width;
-		s->r.height = vin->source.height;
+		s->r.width = source_fmt.width;
+		s->r.height = source_fmt.height;
 		break;
 	case V4L2_SEL_TGT_CROP:
 		s->r = vin->crop;
@@ -380,6 +385,7 @@ static int rvin_s_selection(struct file *file, void *fh,
 			    struct v4l2_selection *s)
 {
 	struct rvin_dev *vin = video_drvdata(file);
+	struct v4l2_mbus_framefmt source_fmt;
 	const struct rvin_video_format *fmt;
 	struct v4l2_rect r = s->r;
 	struct v4l2_rect max_rect;
@@ -387,6 +393,7 @@ static int rvin_s_selection(struct file *file, void *fh,
 		.width = 6,
 		.height = 2,
 	};
+	int ret;
 
 	if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
 		return -EINVAL;
@@ -396,22 +403,25 @@ static int rvin_s_selection(struct file *file, void *fh,
 	switch (s->target) {
 	case V4L2_SEL_TGT_CROP:
 		/* Can't crop outside of source input */
+		ret = rvin_get_source_format(vin, &source_fmt);
+		if (ret)
+			return ret;
 		max_rect.top = max_rect.left = 0;
-		max_rect.width = vin->source.width;
-		max_rect.height = vin->source.height;
+		max_rect.width = source_fmt.width;
+		max_rect.height = source_fmt.height;
 		v4l2_rect_map_inside(&r, &max_rect);
 
-		v4l_bound_align_image(&r.width, 2, vin->source.width, 1,
-				      &r.height, 4, vin->source.height, 2, 0);
+		v4l_bound_align_image(&r.width, 2, source_fmt.width, 1,
+				      &r.height, 4, source_fmt.height, 2, 0);
 
-		r.top  = clamp_t(s32, r.top, 0, vin->source.height - r.height);
-		r.left = clamp_t(s32, r.left, 0, vin->source.width - r.width);
+		r.top  = clamp_t(s32, r.top, 0, source_fmt.height - r.height);
+		r.left = clamp_t(s32, r.left, 0, source_fmt.width - r.width);
 
 		vin->crop = s->r = r;
 
 		vin_dbg(vin, "Cropped %dx%d@%d:%d of %dx%d\n",
 			r.width, r.height, r.left, r.top,
-			vin->source.width, vin->source.height);
+			source_fmt.width, source_fmt.height);
 		break;
 	case V4L2_SEL_TGT_COMPOSE:
 		/* Make sure compose rect fits inside output format */
diff --git a/drivers/media/platform/rcar-vin/rcar-vin.h b/drivers/media/platform/rcar-vin/rcar-vin.h
index 8daba9db0e927a49..39051da31650bd79 100644
--- a/drivers/media/platform/rcar-vin/rcar-vin.h
+++ b/drivers/media/platform/rcar-vin/rcar-vin.h
@@ -48,16 +48,6 @@ enum rvin_dma_state {
 	STOPPING,
 };
 
-/**
- * struct rvin_source_fmt - Source information
- * @width:	Width from source
- * @height:	Height from source
- */
-struct rvin_source_fmt {
-	u32 width;
-	u32 height;
-};
-
 /**
  * struct rvin_video_format - Data format stored in memory
  * @fourcc:	Pixelformat
@@ -124,7 +114,6 @@ struct rvin_info {
  * @sequence:		V4L2 buffers sequence number
  * @state:		keeps track of operation state
  *
- * @source:		active format from the video source
  * @format:		active V4L2 pixel format
  *
  * @crop:		active cropping
@@ -151,7 +140,6 @@ struct rvin_dev {
 	unsigned int sequence;
 	enum rvin_dma_state state;
 
-	struct rvin_source_fmt source;
 	struct v4l2_pix_format format;
 
 	struct v4l2_rect crop;
-- 
2.16.1

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v10 10/30] rcar-vin: fix handling of single field frames (top, bottom and alternate fields)
  2018-01-29 16:34 [PATCH v10 00/30] rcar-vin: Add Gen3 with media controller Niklas Söderlund
                   ` (8 preceding siblings ...)
  2018-01-29 16:34 ` [PATCH v10 09/30] rcar-vin: read subdevice format for crop only when needed Niklas Söderlund
@ 2018-01-29 16:34 ` Niklas Söderlund
  2018-02-13 16:26   ` Laurent Pinchart
  2018-01-29 16:34 ` [PATCH v10 11/30] rcar-vin: move media bus configuration to struct rvin_info Niklas Söderlund
                   ` (19 subsequent siblings)
  29 siblings, 1 reply; 65+ messages in thread
From: Niklas Söderlund @ 2018-01-29 16:34 UTC (permalink / raw)
  To: Laurent Pinchart, Hans Verkuil, linux-media
  Cc: linux-renesas-soc, tomoharu.fukawa.eb, Kieran Bingham,
	Niklas Söderlund

There was never proper support in the VIN driver to deliver ALTERNATING
field format to user-space, remove this field option. The problem is
that ALTERNATING filed order requires the sequence numbers of buffers
returned to userspace to reflect if fields where dropped or not,
something which is not possible with the VIN drivers capture logic.

The VIN driver can still capture from a video source which delivers
frames in ALTERNATING field order, but needs to combine them using the
VIN hardware into INTERLACED field order. Before this change if a source
was delivering fields using ALTERNATE the driver would default to
combining them using this hardware feature. Only if the user explicitly
requested ALTERNATE filed order would incorrect frames be delivered.

The height should not be cut in half for the format for TOP or BOTTOM
fields settings. This was a mistake and it was made visible by the
scaling refactoring. Correct behavior is that the user should request a
frame size that fits the half height frame reflected in the field
setting. If not the VIN will do its best to scale the top or bottom to
the requested format and cropping and scaling do not work as expected.

Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/platform/rcar-vin/rcar-dma.c  | 15 +-------
 drivers/media/platform/rcar-vin/rcar-v4l2.c | 53 +++++++++++++----------------
 2 files changed, 24 insertions(+), 44 deletions(-)

diff --git a/drivers/media/platform/rcar-vin/rcar-dma.c b/drivers/media/platform/rcar-vin/rcar-dma.c
index fd14be20a6604d7a..c8831e189d362c8b 100644
--- a/drivers/media/platform/rcar-vin/rcar-dma.c
+++ b/drivers/media/platform/rcar-vin/rcar-dma.c
@@ -617,7 +617,6 @@ static int rvin_setup(struct rvin_dev *vin)
 	case V4L2_FIELD_INTERLACED_BT:
 		vnmc = VNMC_IM_FULL | VNMC_FOC;
 		break;
-	case V4L2_FIELD_ALTERNATE:
 	case V4L2_FIELD_NONE:
 		if (vin->continuous) {
 			vnmc = VNMC_IM_ODD_EVEN;
@@ -757,18 +756,6 @@ static int rvin_get_active_slot(struct rvin_dev *vin, u32 vnms)
 	return 0;
 }
 
-static enum v4l2_field rvin_get_active_field(struct rvin_dev *vin, u32 vnms)
-{
-	if (vin->format.field == V4L2_FIELD_ALTERNATE) {
-		/* If FS is set it's a Even field */
-		if (vnms & VNMS_FS)
-			return V4L2_FIELD_BOTTOM;
-		return V4L2_FIELD_TOP;
-	}
-
-	return vin->format.field;
-}
-
 static void rvin_set_slot_addr(struct rvin_dev *vin, int slot, dma_addr_t addr)
 {
 	const struct rvin_video_format *fmt;
@@ -941,7 +928,7 @@ static irqreturn_t rvin_irq(int irq, void *data)
 		goto done;
 
 	/* Capture frame */
-	vin->queue_buf[slot]->field = rvin_get_active_field(vin, vnms);
+	vin->queue_buf[slot]->field = vin->format.field;
 	vin->queue_buf[slot]->sequence = sequence;
 	vin->queue_buf[slot]->vb2_buf.timestamp = ktime_get_ns();
 	vb2_buffer_done(&vin->queue_buf[slot]->vb2_buf, VB2_BUF_STATE_DONE);
diff --git a/drivers/media/platform/rcar-vin/rcar-v4l2.c b/drivers/media/platform/rcar-vin/rcar-v4l2.c
index 4d5be2d0c79c9c9a..9f7902d29c62e205 100644
--- a/drivers/media/platform/rcar-vin/rcar-v4l2.c
+++ b/drivers/media/platform/rcar-vin/rcar-v4l2.c
@@ -103,6 +103,28 @@ static int rvin_get_source_format(struct rvin_dev *vin,
 	if (ret)
 		return ret;
 
+	switch (fmt.format.field) {
+	case V4L2_FIELD_TOP:
+	case V4L2_FIELD_BOTTOM:
+	case V4L2_FIELD_NONE:
+	case V4L2_FIELD_INTERLACED_TB:
+	case V4L2_FIELD_INTERLACED_BT:
+	case V4L2_FIELD_INTERLACED:
+		break;
+	case V4L2_FIELD_ALTERNATE:
+		/*
+		 * Driver do not (yet) support outputting ALTERNATE to a
+		 * userspace. It dose support outputting INTERLACED so use
+		 * the VIN hardware to combine the two fields.
+		 */
+		fmt.format.field = V4L2_FIELD_INTERLACED;
+		fmt.format.height *= 2;
+		break;
+	default:
+		vin->format.field = V4L2_FIELD_NONE;
+		break;
+	}
+
 	memcpy(mbus_fmt, &fmt.format, sizeof(*mbus_fmt));
 
 	return 0;
@@ -139,33 +161,6 @@ static int rvin_reset_format(struct rvin_dev *vin)
 
 	v4l2_fill_pix_format(&vin->format, &source_fmt);
 
-	/*
-	 * If the subdevice uses ALTERNATE field mode and G_STD is
-	 * implemented use the VIN HW to combine the two fields to
-	 * one INTERLACED frame. The ALTERNATE field mode can still
-	 * be requested in S_FMT and be respected, this is just the
-	 * default which is applied at probing or when S_STD is called.
-	 */
-	if (vin->format.field == V4L2_FIELD_ALTERNATE &&
-	    v4l2_subdev_has_op(vin_to_source(vin), video, g_std))
-		vin->format.field = V4L2_FIELD_INTERLACED;
-
-	switch (vin->format.field) {
-	case V4L2_FIELD_TOP:
-	case V4L2_FIELD_BOTTOM:
-	case V4L2_FIELD_ALTERNATE:
-		vin->format.height /= 2;
-		break;
-	case V4L2_FIELD_NONE:
-	case V4L2_FIELD_INTERLACED_TB:
-	case V4L2_FIELD_INTERLACED_BT:
-	case V4L2_FIELD_INTERLACED:
-		break;
-	default:
-		vin->format.field = V4L2_FIELD_NONE;
-		break;
-	}
-
 	ret = rvin_reset_crop_compose(vin);
 	if (ret)
 		return ret;
@@ -243,12 +238,10 @@ static int __rvin_try_format(struct rvin_dev *vin,
 	if (ret)
 		return ret;
 
+	/* Reject ALTERNATE  until support is added to the driver */
 	switch (pix->field) {
 	case V4L2_FIELD_TOP:
 	case V4L2_FIELD_BOTTOM:
-	case V4L2_FIELD_ALTERNATE:
-		pix->height /= 2;
-		break;
 	case V4L2_FIELD_NONE:
 	case V4L2_FIELD_INTERLACED_TB:
 	case V4L2_FIELD_INTERLACED_BT:
-- 
2.16.1

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v10 11/30] rcar-vin: move media bus configuration to struct rvin_info
  2018-01-29 16:34 [PATCH v10 00/30] rcar-vin: Add Gen3 with media controller Niklas Söderlund
                   ` (9 preceding siblings ...)
  2018-01-29 16:34 ` [PATCH v10 10/30] rcar-vin: fix handling of single field frames (top, bottom and alternate fields) Niklas Söderlund
@ 2018-01-29 16:34 ` Niklas Söderlund
  2018-02-13 16:37   ` Laurent Pinchart
  2018-01-29 16:34 ` [PATCH v10 12/30] rcar-vin: enable Gen3 hardware configuration Niklas Söderlund
                   ` (18 subsequent siblings)
  29 siblings, 1 reply; 65+ messages in thread
From: Niklas Söderlund @ 2018-01-29 16:34 UTC (permalink / raw)
  To: Laurent Pinchart, Hans Verkuil, linux-media
  Cc: linux-renesas-soc, tomoharu.fukawa.eb, Kieran Bingham,
	Niklas Söderlund

Bus configuration will once the driver is extended to support Gen3
contain information not specific to only the directly connected parallel
subdevice. Move it to struct rvin_dev to show it's not always coupled
to the parallel subdevice.

Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/platform/rcar-vin/rcar-core.c | 18 +++++++++---------
 drivers/media/platform/rcar-vin/rcar-dma.c  | 11 ++++++-----
 drivers/media/platform/rcar-vin/rcar-v4l2.c |  2 +-
 drivers/media/platform/rcar-vin/rcar-vin.h  |  9 ++++-----
 4 files changed, 20 insertions(+), 20 deletions(-)

diff --git a/drivers/media/platform/rcar-vin/rcar-core.c b/drivers/media/platform/rcar-vin/rcar-core.c
index cc863e4ec9a4d4b3..ce1c90405c6002eb 100644
--- a/drivers/media/platform/rcar-vin/rcar-core.c
+++ b/drivers/media/platform/rcar-vin/rcar-core.c
@@ -65,10 +65,10 @@ static int rvin_digital_subdevice_attach(struct rvin_dev *vin,
 	vin->digital->sink_pad = ret < 0 ? 0 : ret;
 
 	/* Find compatible subdevices mbus format */
-	vin->digital->code = 0;
+	vin->code = 0;
 	code.index = 0;
 	code.pad = vin->digital->source_pad;
-	while (!vin->digital->code &&
+	while (!vin->code &&
 	       !v4l2_subdev_call(subdev, pad, enum_mbus_code, NULL, &code)) {
 		code.index++;
 		switch (code.code) {
@@ -76,16 +76,16 @@ static int rvin_digital_subdevice_attach(struct rvin_dev *vin,
 		case MEDIA_BUS_FMT_UYVY8_2X8:
 		case MEDIA_BUS_FMT_UYVY10_2X10:
 		case MEDIA_BUS_FMT_RGB888_1X24:
-			vin->digital->code = code.code;
+			vin->code = code.code;
 			vin_dbg(vin, "Found media bus format for %s: %d\n",
-				subdev->name, vin->digital->code);
+				subdev->name, vin->code);
 			break;
 		default:
 			break;
 		}
 	}
 
-	if (!vin->digital->code) {
+	if (!vin->code) {
 		vin_err(vin, "Unsupported media bus format for %s\n",
 			subdev->name);
 		return -EINVAL;
@@ -190,16 +190,16 @@ static int rvin_digital_parse_v4l2(struct device *dev,
 	if (vep->base.port || vep->base.id)
 		return -ENOTCONN;
 
-	rvge->mbus_cfg.type = vep->bus_type;
+	vin->mbus_cfg.type = vep->bus_type;
 
-	switch (rvge->mbus_cfg.type) {
+	switch (vin->mbus_cfg.type) {
 	case V4L2_MBUS_PARALLEL:
 		vin_dbg(vin, "Found PARALLEL media bus\n");
-		rvge->mbus_cfg.flags = vep->bus.parallel.flags;
+		vin->mbus_cfg.flags = vep->bus.parallel.flags;
 		break;
 	case V4L2_MBUS_BT656:
 		vin_dbg(vin, "Found BT656 media bus\n");
-		rvge->mbus_cfg.flags = 0;
+		vin->mbus_cfg.flags = 0;
 		break;
 	default:
 		vin_err(vin, "Unknown media bus type\n");
diff --git a/drivers/media/platform/rcar-vin/rcar-dma.c b/drivers/media/platform/rcar-vin/rcar-dma.c
index c8831e189d362c8b..561500f65cfa2e74 100644
--- a/drivers/media/platform/rcar-vin/rcar-dma.c
+++ b/drivers/media/platform/rcar-vin/rcar-dma.c
@@ -633,7 +633,7 @@ static int rvin_setup(struct rvin_dev *vin)
 	/*
 	 * Input interface
 	 */
-	switch (vin->digital->code) {
+	switch (vin->code) {
 	case MEDIA_BUS_FMT_YUYV8_1X16:
 		/* BT.601/BT.1358 16bit YCbCr422 */
 		vnmc |= VNMC_INF_YUV16;
@@ -641,7 +641,7 @@ static int rvin_setup(struct rvin_dev *vin)
 		break;
 	case MEDIA_BUS_FMT_UYVY8_2X8:
 		/* BT.656 8bit YCbCr422 or BT.601 8bit YCbCr422 */
-		vnmc |= vin->digital->mbus_cfg.type == V4L2_MBUS_BT656 ?
+		vnmc |= vin->mbus_cfg.type == V4L2_MBUS_BT656 ?
 			VNMC_INF_YUV8_BT656 : VNMC_INF_YUV8_BT601;
 		input_is_yuv = true;
 		break;
@@ -650,7 +650,7 @@ static int rvin_setup(struct rvin_dev *vin)
 		break;
 	case MEDIA_BUS_FMT_UYVY10_2X10:
 		/* BT.656 10bit YCbCr422 or BT.601 10bit YCbCr422 */
-		vnmc |= vin->digital->mbus_cfg.type == V4L2_MBUS_BT656 ?
+		vnmc |= vin->mbus_cfg.type == V4L2_MBUS_BT656 ?
 			VNMC_INF_YUV10_BT656 : VNMC_INF_YUV10_BT601;
 		input_is_yuv = true;
 		break;
@@ -662,11 +662,11 @@ static int rvin_setup(struct rvin_dev *vin)
 	dmr2 = VNDMR2_FTEV | VNDMR2_VLV(1);
 
 	/* Hsync Signal Polarity Select */
-	if (!(vin->digital->mbus_cfg.flags & V4L2_MBUS_HSYNC_ACTIVE_LOW))
+	if (!(vin->mbus_cfg.flags & V4L2_MBUS_HSYNC_ACTIVE_LOW))
 		dmr2 |= VNDMR2_HPS;
 
 	/* Vsync Signal Polarity Select */
-	if (!(vin->digital->mbus_cfg.flags & V4L2_MBUS_VSYNC_ACTIVE_LOW))
+	if (!(vin->mbus_cfg.flags & V4L2_MBUS_VSYNC_ACTIVE_LOW))
 		dmr2 |= VNDMR2_VPS;
 
 	/*
@@ -875,6 +875,7 @@ static void rvin_capture_stop(struct rvin_dev *vin)
 	rvin_write(vin, rvin_read(vin, VNMC_REG) & ~VNMC_ME, VNMC_REG);
 }
 
+
 /* -----------------------------------------------------------------------------
  * DMA Functions
  */
diff --git a/drivers/media/platform/rcar-vin/rcar-v4l2.c b/drivers/media/platform/rcar-vin/rcar-v4l2.c
index 9f7902d29c62e205..c606942e59b5d934 100644
--- a/drivers/media/platform/rcar-vin/rcar-v4l2.c
+++ b/drivers/media/platform/rcar-vin/rcar-v4l2.c
@@ -185,7 +185,7 @@ static int __rvin_try_format_source(struct rvin_dev *vin,
 
 	sd = vin_to_source(vin);
 
-	v4l2_fill_mbus_format(&format.format, pix, vin->digital->code);
+	v4l2_fill_mbus_format(&format.format, pix, vin->code);
 
 	pad_cfg = v4l2_subdev_alloc_pad_config(sd);
 	if (pad_cfg == NULL)
diff --git a/drivers/media/platform/rcar-vin/rcar-vin.h b/drivers/media/platform/rcar-vin/rcar-vin.h
index 39051da31650bd79..b852e7f4fa3db017 100644
--- a/drivers/media/platform/rcar-vin/rcar-vin.h
+++ b/drivers/media/platform/rcar-vin/rcar-vin.h
@@ -62,8 +62,6 @@ struct rvin_video_format {
  * struct rvin_graph_entity - Video endpoint from async framework
  * @asd:	sub-device descriptor for async framework
  * @subdev:	subdevice matched using async framework
- * @code:	Media bus format from source
- * @mbus_cfg:	Media bus format from DT
  * @source_pad:	source pad of remote subdevice
  * @sink_pad:	sink pad of remote subdevice
  */
@@ -71,9 +69,6 @@ struct rvin_graph_entity {
 	struct v4l2_async_subdev asd;
 	struct v4l2_subdev *subdev;
 
-	u32 code;
-	struct v4l2_mbus_config mbus_cfg;
-
 	unsigned int source_pad;
 	unsigned int sink_pad;
 };
@@ -114,6 +109,8 @@ struct rvin_info {
  * @sequence:		V4L2 buffers sequence number
  * @state:		keeps track of operation state
  *
+ * @mbus_cfg:		media bus configuration from DT
+ * @code:		media bus format code
  * @format:		active V4L2 pixel format
  *
  * @crop:		active cropping
@@ -140,6 +137,8 @@ struct rvin_dev {
 	unsigned int sequence;
 	enum rvin_dma_state state;
 
+	struct v4l2_mbus_config mbus_cfg;
+	u32 code;
 	struct v4l2_pix_format format;
 
 	struct v4l2_rect crop;
-- 
2.16.1

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v10 12/30] rcar-vin: enable Gen3 hardware configuration
  2018-01-29 16:34 [PATCH v10 00/30] rcar-vin: Add Gen3 with media controller Niklas Söderlund
                   ` (10 preceding siblings ...)
  2018-01-29 16:34 ` [PATCH v10 11/30] rcar-vin: move media bus configuration to struct rvin_info Niklas Söderlund
@ 2018-01-29 16:34 ` Niklas Söderlund
  2018-01-29 16:34 ` [PATCH v10 13/30] rcar-vin: add function to manipulate Gen3 chsel value Niklas Söderlund
                   ` (17 subsequent siblings)
  29 siblings, 0 replies; 65+ messages in thread
From: Niklas Söderlund @ 2018-01-29 16:34 UTC (permalink / raw)
  To: Laurent Pinchart, Hans Verkuil, linux-media
  Cc: linux-renesas-soc, tomoharu.fukawa.eb, Kieran Bingham,
	Niklas Söderlund

Add the register needed to work with Gen3 hardware. This patch adds
the logic for how to work with the Gen3 hardware. More work is required
to enable the subdevice structure needed to configure capturing.

Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/rcar-vin/rcar-dma.c | 94 ++++++++++++++++++++----------
 drivers/media/platform/rcar-vin/rcar-vin.h |  1 +
 2 files changed, 64 insertions(+), 31 deletions(-)

diff --git a/drivers/media/platform/rcar-vin/rcar-dma.c b/drivers/media/platform/rcar-vin/rcar-dma.c
index 561500f65cfa2e74..2f9ad1bec1c8a92f 100644
--- a/drivers/media/platform/rcar-vin/rcar-dma.c
+++ b/drivers/media/platform/rcar-vin/rcar-dma.c
@@ -33,21 +33,23 @@
 #define VNELPRC_REG	0x10	/* Video n End Line Pre-Clip Register */
 #define VNSPPRC_REG	0x14	/* Video n Start Pixel Pre-Clip Register */
 #define VNEPPRC_REG	0x18	/* Video n End Pixel Pre-Clip Register */
-#define VNSLPOC_REG	0x1C	/* Video n Start Line Post-Clip Register */
-#define VNELPOC_REG	0x20	/* Video n End Line Post-Clip Register */
-#define VNSPPOC_REG	0x24	/* Video n Start Pixel Post-Clip Register */
-#define VNEPPOC_REG	0x28	/* Video n End Pixel Post-Clip Register */
 #define VNIS_REG	0x2C	/* Video n Image Stride Register */
 #define VNMB_REG(m)	(0x30 + ((m) << 2)) /* Video n Memory Base m Register */
 #define VNIE_REG	0x40	/* Video n Interrupt Enable Register */
 #define VNINTS_REG	0x44	/* Video n Interrupt Status Register */
 #define VNSI_REG	0x48	/* Video n Scanline Interrupt Register */
 #define VNMTC_REG	0x4C	/* Video n Memory Transfer Control Register */
-#define VNYS_REG	0x50	/* Video n Y Scale Register */
-#define VNXS_REG	0x54	/* Video n X Scale Register */
 #define VNDMR_REG	0x58	/* Video n Data Mode Register */
 #define VNDMR2_REG	0x5C	/* Video n Data Mode Register 2 */
 #define VNUVAOF_REG	0x60	/* Video n UV Address Offset Register */
+
+/* Register offsets specific for Gen2 */
+#define VNSLPOC_REG	0x1C	/* Video n Start Line Post-Clip Register */
+#define VNELPOC_REG	0x20	/* Video n End Line Post-Clip Register */
+#define VNSPPOC_REG	0x24	/* Video n Start Pixel Post-Clip Register */
+#define VNEPPOC_REG	0x28	/* Video n End Pixel Post-Clip Register */
+#define VNYS_REG	0x50	/* Video n Y Scale Register */
+#define VNXS_REG	0x54	/* Video n X Scale Register */
 #define VNC1A_REG	0x80	/* Video n Coefficient Set C1A Register */
 #define VNC1B_REG	0x84	/* Video n Coefficient Set C1B Register */
 #define VNC1C_REG	0x88	/* Video n Coefficient Set C1C Register */
@@ -73,9 +75,13 @@
 #define VNC8B_REG	0xF4	/* Video n Coefficient Set C8B Register */
 #define VNC8C_REG	0xF8	/* Video n Coefficient Set C8C Register */
 
+/* Register offsets specific for Gen3 */
+#define VNCSI_IFMD_REG		0x20 /* Video n CSI2 Interface Mode Register */
 
 /* Register bit fields for R-Car VIN */
 /* Video n Main Control Register bits */
+#define VNMC_DPINE		(1 << 27) /* Gen3 specific */
+#define VNMC_SCLE		(1 << 26) /* Gen3 specific */
 #define VNMC_FOC		(1 << 21)
 #define VNMC_YCAL		(1 << 19)
 #define VNMC_INF_YUV8_BT656	(0 << 16)
@@ -119,6 +125,13 @@
 #define VNDMR2_FTEV		(1 << 17)
 #define VNDMR2_VLV(n)		((n & 0xf) << 12)
 
+/* Video n CSI2 Interface Mode Register (Gen3) */
+#define VNCSI_IFMD_DES2		(1 << 27)
+#define VNCSI_IFMD_DES1		(1 << 26)
+#define VNCSI_IFMD_DES0		(1 << 25)
+#define VNCSI_IFMD_CSI_CHSEL(n) (((n) & 0xf) << 0)
+#define VNCSI_IFMD_CSI_CHSEL_MASK 0xf
+
 struct rvin_buffer {
 	struct vb2_v4l2_buffer vb;
 	struct list_head list;
@@ -514,28 +527,10 @@ static void rvin_set_coeff(struct rvin_dev *vin, unsigned short xs)
 	rvin_write(vin, p_set->coeff_set[23], VNC8C_REG);
 }
 
-void rvin_crop_scale_comp(struct rvin_dev *vin)
+static void rvin_crop_scale_comp_gen2(struct rvin_dev *vin)
 {
 	u32 xs, ys;
 
-	/* Set Start/End Pixel/Line Pre-Clip */
-	rvin_write(vin, vin->crop.left, VNSPPRC_REG);
-	rvin_write(vin, vin->crop.left + vin->crop.width - 1, VNEPPRC_REG);
-	switch (vin->format.field) {
-	case V4L2_FIELD_INTERLACED:
-	case V4L2_FIELD_INTERLACED_TB:
-	case V4L2_FIELD_INTERLACED_BT:
-		rvin_write(vin, vin->crop.top / 2, VNSLPRC_REG);
-		rvin_write(vin, (vin->crop.top + vin->crop.height) / 2 - 1,
-			   VNELPRC_REG);
-		break;
-	default:
-		rvin_write(vin, vin->crop.top, VNSLPRC_REG);
-		rvin_write(vin, vin->crop.top + vin->crop.height - 1,
-			   VNELPRC_REG);
-		break;
-	}
-
 	/* Set scaling coefficient */
 	ys = 0;
 	if (vin->crop.height != vin->compose.height)
@@ -573,11 +568,6 @@ void rvin_crop_scale_comp(struct rvin_dev *vin)
 		break;
 	}
 
-	if (vin->format.pixelformat == V4L2_PIX_FMT_NV16)
-		rvin_write(vin, ALIGN(vin->format.width, 0x20), VNIS_REG);
-	else
-		rvin_write(vin, ALIGN(vin->format.width, 0x10), VNIS_REG);
-
 	vin_dbg(vin,
 		"Pre-Clip: %ux%u@%u:%u YS: %d XS: %d Post-Clip: %ux%u@%u:%u\n",
 		vin->crop.width, vin->crop.height, vin->crop.left,
@@ -585,6 +575,37 @@ void rvin_crop_scale_comp(struct rvin_dev *vin)
 		0, 0);
 }
 
+void rvin_crop_scale_comp(struct rvin_dev *vin)
+{
+	/* Set Start/End Pixel/Line Pre-Clip */
+	rvin_write(vin, vin->crop.left, VNSPPRC_REG);
+	rvin_write(vin, vin->crop.left + vin->crop.width - 1, VNEPPRC_REG);
+
+	switch (vin->format.field) {
+	case V4L2_FIELD_INTERLACED:
+	case V4L2_FIELD_INTERLACED_TB:
+	case V4L2_FIELD_INTERLACED_BT:
+		rvin_write(vin, vin->crop.top / 2, VNSLPRC_REG);
+		rvin_write(vin, (vin->crop.top + vin->crop.height) / 2 - 1,
+			   VNELPRC_REG);
+		break;
+	default:
+		rvin_write(vin, vin->crop.top, VNSLPRC_REG);
+		rvin_write(vin, vin->crop.top + vin->crop.height - 1,
+			   VNELPRC_REG);
+		break;
+	}
+
+	/* TODO: Add support for the UDS scaler. */
+	if (vin->info->model != RCAR_GEN3)
+		rvin_crop_scale_comp_gen2(vin);
+
+	if (vin->format.pixelformat == V4L2_PIX_FMT_NV16)
+		rvin_write(vin, ALIGN(vin->format.width, 0x20), VNIS_REG);
+	else
+		rvin_write(vin, ALIGN(vin->format.width, 0x10), VNIS_REG);
+}
+
 /* -----------------------------------------------------------------------------
  * Hardware setup
  */
@@ -659,7 +680,10 @@ static int rvin_setup(struct rvin_dev *vin)
 	}
 
 	/* Enable VSYNC Field Toogle mode after one VSYNC input */
-	dmr2 = VNDMR2_FTEV | VNDMR2_VLV(1);
+	if (vin->info->model == RCAR_GEN3)
+		dmr2 = VNDMR2_FTEV;
+	else
+		dmr2 = VNDMR2_FTEV | VNDMR2_VLV(1);
 
 	/* Hsync Signal Polarity Select */
 	if (!(vin->mbus_cfg.flags & V4L2_MBUS_HSYNC_ACTIVE_LOW))
@@ -711,6 +735,14 @@ static int rvin_setup(struct rvin_dev *vin)
 	if (input_is_yuv == output_is_yuv)
 		vnmc |= VNMC_BPS;
 
+	if (vin->info->model == RCAR_GEN3) {
+		/* Select between CSI-2 and Digital input */
+		if (vin->mbus_cfg.type == V4L2_MBUS_CSI2)
+			vnmc &= ~VNMC_DPINE;
+		else
+			vnmc |= VNMC_DPINE;
+	}
+
 	/* Progressive or interlaced mode */
 	interrupts = progressive ? VNIE_FIE : VNIE_EFE;
 
diff --git a/drivers/media/platform/rcar-vin/rcar-vin.h b/drivers/media/platform/rcar-vin/rcar-vin.h
index b852e7f4fa3db017..146683142e6533fa 100644
--- a/drivers/media/platform/rcar-vin/rcar-vin.h
+++ b/drivers/media/platform/rcar-vin/rcar-vin.h
@@ -33,6 +33,7 @@ enum model_id {
 	RCAR_H1,
 	RCAR_M1,
 	RCAR_GEN2,
+	RCAR_GEN3,
 };
 
 /**
-- 
2.16.1

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v10 13/30] rcar-vin: add function to manipulate Gen3 chsel value
  2018-01-29 16:34 [PATCH v10 00/30] rcar-vin: Add Gen3 with media controller Niklas Söderlund
                   ` (11 preceding siblings ...)
  2018-01-29 16:34 ` [PATCH v10 12/30] rcar-vin: enable Gen3 hardware configuration Niklas Söderlund
@ 2018-01-29 16:34 ` Niklas Söderlund
  2018-02-13 16:41   ` Laurent Pinchart
  2018-01-29 16:34 ` [PATCH v10 14/30] rcar-vin: add flag to switch to media controller mode Niklas Söderlund
                   ` (16 subsequent siblings)
  29 siblings, 1 reply; 65+ messages in thread
From: Niklas Söderlund @ 2018-01-29 16:34 UTC (permalink / raw)
  To: Laurent Pinchart, Hans Verkuil, linux-media
  Cc: linux-renesas-soc, tomoharu.fukawa.eb, Kieran Bingham,
	Niklas Söderlund

On Gen3 the CSI-2 routing is controlled by the VnCSI_IFMD register. One
feature of this register is that it's only present in the VIN0 and VIN4
instances. The register in VIN0 controls the routing for VIN0-3 and the
register in VIN4 controls routing for VIN4-7.

To be able to control routing from a media device this function is need
to control runtime PM for the subgroup master (VIN0 and VIN4). The
subgroup master must be switched on before the register is manipulated,
once the operation is complete it's safe to switch the master off and
the new routing will still be in effect.

Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
---
 drivers/media/platform/rcar-vin/rcar-dma.c | 28 ++++++++++++++++++++++++++++
 drivers/media/platform/rcar-vin/rcar-vin.h |  2 ++
 2 files changed, 30 insertions(+)

diff --git a/drivers/media/platform/rcar-vin/rcar-dma.c b/drivers/media/platform/rcar-vin/rcar-dma.c
index 2f9ad1bec1c8a92f..ae286742f15a3ab5 100644
--- a/drivers/media/platform/rcar-vin/rcar-dma.c
+++ b/drivers/media/platform/rcar-vin/rcar-dma.c
@@ -16,6 +16,7 @@
 
 #include <linux/delay.h>
 #include <linux/interrupt.h>
+#include <linux/pm_runtime.h>
 
 #include <media/videobuf2-dma-contig.h>
 
@@ -1228,3 +1229,30 @@ int rvin_dma_register(struct rvin_dev *vin, int irq)
 
 	return ret;
 }
+
+/* -----------------------------------------------------------------------------
+ * Gen3 CHSEL manipulation
+ */
+
+void rvin_set_channel_routing(struct rvin_dev *vin, u8 chsel)
+{
+	u32 ifmd, vnmc;
+
+	pm_runtime_get_sync(vin->dev);
+
+	/* Make register writes take effect immediately */
+	vnmc = rvin_read(vin, VNMC_REG);
+	rvin_write(vin, vnmc & ~VNMC_VUP, VNMC_REG);
+
+	ifmd = VNCSI_IFMD_DES2 | VNCSI_IFMD_DES1 | VNCSI_IFMD_DES0 |
+		VNCSI_IFMD_CSI_CHSEL(chsel);
+
+	rvin_write(vin, ifmd, VNCSI_IFMD_REG);
+
+	vin_dbg(vin, "Set IFMD 0x%x\n", ifmd);
+
+	/* Restore VNMC */
+	rvin_write(vin, vnmc, VNMC_REG);
+
+	pm_runtime_put(vin->dev);
+}
diff --git a/drivers/media/platform/rcar-vin/rcar-vin.h b/drivers/media/platform/rcar-vin/rcar-vin.h
index 146683142e6533fa..a5dae5b5e9cb704b 100644
--- a/drivers/media/platform/rcar-vin/rcar-vin.h
+++ b/drivers/media/platform/rcar-vin/rcar-vin.h
@@ -165,4 +165,6 @@ const struct rvin_video_format *rvin_format_from_pixel(u32 pixelformat);
 /* Cropping, composing and scaling */
 void rvin_crop_scale_comp(struct rvin_dev *vin);
 
+void rvin_set_channel_routing(struct rvin_dev *vin, u8 chsel);
+
 #endif
-- 
2.16.1

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v10 14/30] rcar-vin: add flag to switch to media controller mode
  2018-01-29 16:34 [PATCH v10 00/30] rcar-vin: Add Gen3 with media controller Niklas Söderlund
                   ` (12 preceding siblings ...)
  2018-01-29 16:34 ` [PATCH v10 13/30] rcar-vin: add function to manipulate Gen3 chsel value Niklas Söderlund
@ 2018-01-29 16:34 ` Niklas Söderlund
  2018-01-29 16:34 ` [PATCH v10 15/30] rcar-vin: break out format alignment and checking Niklas Söderlund
                   ` (15 subsequent siblings)
  29 siblings, 0 replies; 65+ messages in thread
From: Niklas Söderlund @ 2018-01-29 16:34 UTC (permalink / raw)
  To: Laurent Pinchart, Hans Verkuil, linux-media
  Cc: linux-renesas-soc, tomoharu.fukawa.eb, Kieran Bingham,
	Niklas Söderlund

On Gen3 a media controller API needs to be used to allow userspace to
configure the subdevices in the pipeline instead of directly controlling
a single source subdevice, which is and will continue to be the mode of
operation on Gen2.

Prepare for these two modes of operation by adding a flag to struct
rvin_info which will control which mode to use.

Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/rcar-vin/rcar-core.c | 6 +++++-
 drivers/media/platform/rcar-vin/rcar-vin.h  | 2 ++
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/media/platform/rcar-vin/rcar-core.c b/drivers/media/platform/rcar-vin/rcar-core.c
index ce1c90405c6002eb..64034c96f384b3ed 100644
--- a/drivers/media/platform/rcar-vin/rcar-core.c
+++ b/drivers/media/platform/rcar-vin/rcar-core.c
@@ -243,18 +243,21 @@ static int rvin_digital_graph_init(struct rvin_dev *vin)
 
 static const struct rvin_info rcar_info_h1 = {
 	.model = RCAR_H1,
+	.use_mc = false,
 	.max_width = 2048,
 	.max_height = 2048,
 };
 
 static const struct rvin_info rcar_info_m1 = {
 	.model = RCAR_M1,
+	.use_mc = false,
 	.max_width = 2048,
 	.max_height = 2048,
 };
 
 static const struct rvin_info rcar_info_gen2 = {
 	.model = RCAR_GEN2,
+	.use_mc = false,
 	.max_width = 2048,
 	.max_height = 2048,
 };
@@ -349,7 +352,8 @@ static int rcar_vin_remove(struct platform_device *pdev)
 	v4l2_async_notifier_unregister(&vin->notifier);
 	v4l2_async_notifier_cleanup(&vin->notifier);
 
-	v4l2_ctrl_handler_free(&vin->ctrl_handler);
+	if (!vin->info->use_mc)
+		v4l2_ctrl_handler_free(&vin->ctrl_handler);
 
 	rvin_dma_unregister(vin);
 
diff --git a/drivers/media/platform/rcar-vin/rcar-vin.h b/drivers/media/platform/rcar-vin/rcar-vin.h
index a5dae5b5e9cb704b..64476bc5c8abc6d0 100644
--- a/drivers/media/platform/rcar-vin/rcar-vin.h
+++ b/drivers/media/platform/rcar-vin/rcar-vin.h
@@ -77,11 +77,13 @@ struct rvin_graph_entity {
 /**
  * struct rvin_info - Information about the particular VIN implementation
  * @model:		VIN model
+ * @use_mc:		use media controller instead of controlling subdevice
  * @max_width:		max input width the VIN supports
  * @max_height:		max input height the VIN supports
  */
 struct rvin_info {
 	enum model_id model;
+	bool use_mc;
 
 	unsigned int max_width;
 	unsigned int max_height;
-- 
2.16.1

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v10 15/30] rcar-vin: break out format alignment and checking
  2018-01-29 16:34 [PATCH v10 00/30] rcar-vin: Add Gen3 with media controller Niklas Söderlund
                   ` (13 preceding siblings ...)
  2018-01-29 16:34 ` [PATCH v10 14/30] rcar-vin: add flag to switch to media controller mode Niklas Söderlund
@ 2018-01-29 16:34 ` Niklas Söderlund
  2018-02-13 16:56   ` Laurent Pinchart
  2018-01-29 16:34 ` [PATCH v10 16/30] rcar-vin: update bytesperline and sizeimage calculation Niklas Söderlund
                   ` (14 subsequent siblings)
  29 siblings, 1 reply; 65+ messages in thread
From: Niklas Söderlund @ 2018-01-29 16:34 UTC (permalink / raw)
  To: Laurent Pinchart, Hans Verkuil, linux-media
  Cc: linux-renesas-soc, tomoharu.fukawa.eb, Kieran Bingham,
	Niklas Söderlund

Part of the format alignment and checking can be shared with the Gen3
format handling. Break that part out to a separate function.

Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
---
 drivers/media/platform/rcar-vin/rcar-v4l2.c | 93 ++++++++++++++++-------------
 1 file changed, 50 insertions(+), 43 deletions(-)

diff --git a/drivers/media/platform/rcar-vin/rcar-v4l2.c b/drivers/media/platform/rcar-vin/rcar-v4l2.c
index c606942e59b5d934..1169e6a279ecfb55 100644
--- a/drivers/media/platform/rcar-vin/rcar-v4l2.c
+++ b/drivers/media/platform/rcar-vin/rcar-v4l2.c
@@ -86,6 +86,55 @@ static u32 rvin_format_sizeimage(struct v4l2_pix_format *pix)
 	return pix->bytesperline * pix->height;
 }
 
+static int rvin_format_align(struct rvin_dev *vin, struct v4l2_pix_format *pix)
+{
+	u32 walign;
+
+	/* If requested format is not supported fallback to the default */
+	if (!rvin_format_from_pixel(pix->pixelformat)) {
+		vin_dbg(vin, "Format 0x%x not found, using default 0x%x\n",
+			pix->pixelformat, RVIN_DEFAULT_FORMAT);
+		pix->pixelformat = RVIN_DEFAULT_FORMAT;
+	}
+
+	/* Reject ALTERNATE  until support is added to the driver */
+	switch (pix->field) {
+	case V4L2_FIELD_TOP:
+	case V4L2_FIELD_BOTTOM:
+	case V4L2_FIELD_NONE:
+	case V4L2_FIELD_INTERLACED_TB:
+	case V4L2_FIELD_INTERLACED_BT:
+	case V4L2_FIELD_INTERLACED:
+		break;
+	default:
+		pix->field = V4L2_FIELD_NONE;
+		break;
+	}
+
+	/* HW limit width to a multiple of 32 (2^5) for NV16 else 2 (2^1) */
+	walign = vin->format.pixelformat == V4L2_PIX_FMT_NV16 ? 5 : 1;
+
+	/* Limit to VIN capabilities */
+	v4l_bound_align_image(&pix->width, 2, vin->info->max_width, walign,
+			      &pix->height, 4, vin->info->max_height, 2, 0);
+
+	pix->bytesperline = max_t(u32, pix->bytesperline,
+				  rvin_format_bytesperline(pix));
+	pix->sizeimage = max_t(u32, pix->sizeimage,
+			       rvin_format_sizeimage(pix));
+
+	if (vin->info->model == RCAR_M1 &&
+	    pix->pixelformat == V4L2_PIX_FMT_XBGR32) {
+		vin_err(vin, "pixel format XBGR32 not supported on M1\n");
+		return -EINVAL;
+	}
+
+	vin_dbg(vin, "Format %ux%u bpl: %d size: %d\n",
+		pix->width, pix->height, pix->bytesperline, pix->sizeimage);
+
+	return 0;
+}
+
 /* -----------------------------------------------------------------------------
  * V4L2
  */
@@ -215,19 +264,12 @@ static int __rvin_try_format_source(struct rvin_dev *vin,
 static int __rvin_try_format(struct rvin_dev *vin,
 			     u32 which, struct v4l2_pix_format *pix)
 {
-	u32 walign;
 	int ret;
 
 	/* Keep current field if no specific one is asked for */
 	if (pix->field == V4L2_FIELD_ANY)
 		pix->field = vin->format.field;
 
-	/* If requested format is not supported fallback to the default */
-	if (!rvin_format_from_pixel(pix->pixelformat)) {
-		vin_dbg(vin, "Format 0x%x not found, using default 0x%x\n",
-			pix->pixelformat, RVIN_DEFAULT_FORMAT);
-		pix->pixelformat = RVIN_DEFAULT_FORMAT;
-	}
 
 	/* Always recalculate */
 	pix->bytesperline = 0;
@@ -238,42 +280,7 @@ static int __rvin_try_format(struct rvin_dev *vin,
 	if (ret)
 		return ret;
 
-	/* Reject ALTERNATE  until support is added to the driver */
-	switch (pix->field) {
-	case V4L2_FIELD_TOP:
-	case V4L2_FIELD_BOTTOM:
-	case V4L2_FIELD_NONE:
-	case V4L2_FIELD_INTERLACED_TB:
-	case V4L2_FIELD_INTERLACED_BT:
-	case V4L2_FIELD_INTERLACED:
-		break;
-	default:
-		pix->field = V4L2_FIELD_NONE;
-		break;
-	}
-
-	/* HW limit width to a multiple of 32 (2^5) for NV16 else 2 (2^1) */
-	walign = vin->format.pixelformat == V4L2_PIX_FMT_NV16 ? 5 : 1;
-
-	/* Limit to VIN capabilities */
-	v4l_bound_align_image(&pix->width, 2, vin->info->max_width, walign,
-			      &pix->height, 4, vin->info->max_height, 2, 0);
-
-	pix->bytesperline = max_t(u32, pix->bytesperline,
-				  rvin_format_bytesperline(pix));
-	pix->sizeimage = max_t(u32, pix->sizeimage,
-			       rvin_format_sizeimage(pix));
-
-	if (vin->info->model == RCAR_M1 &&
-	    pix->pixelformat == V4L2_PIX_FMT_XBGR32) {
-		vin_err(vin, "pixel format XBGR32 not supported on M1\n");
-		return -EINVAL;
-	}
-
-	vin_dbg(vin, "Format %ux%u bpl: %d size: %d\n",
-		pix->width, pix->height, pix->bytesperline, pix->sizeimage);
-
-	return 0;
+	return rvin_format_align(vin, pix);
 }
 
 static int rvin_querycap(struct file *file, void *priv,
-- 
2.16.1

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v10 16/30] rcar-vin: update bytesperline and sizeimage calculation
  2018-01-29 16:34 [PATCH v10 00/30] rcar-vin: Add Gen3 with media controller Niklas Söderlund
                   ` (14 preceding siblings ...)
  2018-01-29 16:34 ` [PATCH v10 15/30] rcar-vin: break out format alignment and checking Niklas Söderlund
@ 2018-01-29 16:34 ` Niklas Söderlund
  2018-02-13 16:58   ` Laurent Pinchart
  2018-01-29 16:34 ` [PATCH v10 17/30] rcar-vin: update pixelformat check for M1 Niklas Söderlund
                   ` (13 subsequent siblings)
  29 siblings, 1 reply; 65+ messages in thread
From: Niklas Söderlund @ 2018-01-29 16:34 UTC (permalink / raw)
  To: Laurent Pinchart, Hans Verkuil, linux-media
  Cc: linux-renesas-soc, tomoharu.fukawa.eb, Kieran Bingham,
	Niklas Söderlund

Remove over complicated logic to calculate the value for bytesperline
and sizeimage that was carried over from the soc_camera port. Update the
calculations to match how other drivers are doing it.

Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
---
 drivers/media/platform/rcar-vin/rcar-v4l2.c | 11 ++---------
 1 file changed, 2 insertions(+), 9 deletions(-)

diff --git a/drivers/media/platform/rcar-vin/rcar-v4l2.c b/drivers/media/platform/rcar-vin/rcar-v4l2.c
index 1169e6a279ecfb55..bca6e204a574772f 100644
--- a/drivers/media/platform/rcar-vin/rcar-v4l2.c
+++ b/drivers/media/platform/rcar-vin/rcar-v4l2.c
@@ -118,10 +118,8 @@ static int rvin_format_align(struct rvin_dev *vin, struct v4l2_pix_format *pix)
 	v4l_bound_align_image(&pix->width, 2, vin->info->max_width, walign,
 			      &pix->height, 4, vin->info->max_height, 2, 0);
 
-	pix->bytesperline = max_t(u32, pix->bytesperline,
-				  rvin_format_bytesperline(pix));
-	pix->sizeimage = max_t(u32, pix->sizeimage,
-			       rvin_format_sizeimage(pix));
+	pix->bytesperline = rvin_format_bytesperline(pix);
+	pix->sizeimage = rvin_format_sizeimage(pix);
 
 	if (vin->info->model == RCAR_M1 &&
 	    pix->pixelformat == V4L2_PIX_FMT_XBGR32) {
@@ -270,11 +268,6 @@ static int __rvin_try_format(struct rvin_dev *vin,
 	if (pix->field == V4L2_FIELD_ANY)
 		pix->field = vin->format.field;
 
-
-	/* Always recalculate */
-	pix->bytesperline = 0;
-	pix->sizeimage = 0;
-
 	/* Limit to source capabilities */
 	ret = __rvin_try_format_source(vin, which, pix);
 	if (ret)
-- 
2.16.1

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v10 17/30] rcar-vin: update pixelformat check for M1
  2018-01-29 16:34 [PATCH v10 00/30] rcar-vin: Add Gen3 with media controller Niklas Söderlund
                   ` (15 preceding siblings ...)
  2018-01-29 16:34 ` [PATCH v10 16/30] rcar-vin: update bytesperline and sizeimage calculation Niklas Söderlund
@ 2018-01-29 16:34 ` Niklas Söderlund
  2018-02-13 17:03   ` Laurent Pinchart
  2018-01-29 16:34 ` [PATCH v10 18/30] rcar-vin: add check for colorspace Niklas Söderlund
                   ` (12 subsequent siblings)
  29 siblings, 1 reply; 65+ messages in thread
From: Niklas Söderlund @ 2018-01-29 16:34 UTC (permalink / raw)
  To: Laurent Pinchart, Hans Verkuil, linux-media
  Cc: linux-renesas-soc, tomoharu.fukawa.eb, Kieran Bingham,
	Niklas Söderlund

If the pixelformat is not supported it should not fail but be set to
something that works. While we are at it move the check together with
other pixelformat checks of this function.

Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
---
 drivers/media/platform/rcar-vin/rcar-v4l2.c | 10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/drivers/media/platform/rcar-vin/rcar-v4l2.c b/drivers/media/platform/rcar-vin/rcar-v4l2.c
index bca6e204a574772f..841d62ca27e026d7 100644
--- a/drivers/media/platform/rcar-vin/rcar-v4l2.c
+++ b/drivers/media/platform/rcar-vin/rcar-v4l2.c
@@ -97,6 +97,10 @@ static int rvin_format_align(struct rvin_dev *vin, struct v4l2_pix_format *pix)
 		pix->pixelformat = RVIN_DEFAULT_FORMAT;
 	}
 
+	if (vin->info->model == RCAR_M1 &&
+	    pix->pixelformat == V4L2_PIX_FMT_XBGR32)
+		pix->pixelformat = RVIN_DEFAULT_FORMAT;
+
 	/* Reject ALTERNATE  until support is added to the driver */
 	switch (pix->field) {
 	case V4L2_FIELD_TOP:
@@ -121,12 +125,6 @@ static int rvin_format_align(struct rvin_dev *vin, struct v4l2_pix_format *pix)
 	pix->bytesperline = rvin_format_bytesperline(pix);
 	pix->sizeimage = rvin_format_sizeimage(pix);
 
-	if (vin->info->model == RCAR_M1 &&
-	    pix->pixelformat == V4L2_PIX_FMT_XBGR32) {
-		vin_err(vin, "pixel format XBGR32 not supported on M1\n");
-		return -EINVAL;
-	}
-
 	vin_dbg(vin, "Format %ux%u bpl: %d size: %d\n",
 		pix->width, pix->height, pix->bytesperline, pix->sizeimage);
 
-- 
2.16.1

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v10 18/30] rcar-vin: add check for colorspace
  2018-01-29 16:34 [PATCH v10 00/30] rcar-vin: Add Gen3 with media controller Niklas Söderlund
                   ` (16 preceding siblings ...)
  2018-01-29 16:34 ` [PATCH v10 17/30] rcar-vin: update pixelformat check for M1 Niklas Söderlund
@ 2018-01-29 16:34 ` Niklas Söderlund
  2018-02-13 17:08   ` Laurent Pinchart
  2018-01-29 16:34 ` [PATCH v10 19/30] rcar-vin: set a default field to fallback on Niklas Söderlund
                   ` (11 subsequent siblings)
  29 siblings, 1 reply; 65+ messages in thread
From: Niklas Söderlund @ 2018-01-29 16:34 UTC (permalink / raw)
  To: Laurent Pinchart, Hans Verkuil, linux-media
  Cc: linux-renesas-soc, tomoharu.fukawa.eb, Kieran Bingham,
	Niklas Söderlund

Add a check to ensure the colorspace from user-space is good. On Gen2 it
works without this change as the sensor sets the colorspace but on Gen3
this can fail if the colorspace provided by the user is not good. The
values to check for comes from v4l2-compliance sources which is the tool
that found this error. If this check is not preformed v4l2-compliance
fails when it tests colorspace.

Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
---
 drivers/media/platform/rcar-vin/rcar-v4l2.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/media/platform/rcar-vin/rcar-v4l2.c b/drivers/media/platform/rcar-vin/rcar-v4l2.c
index 841d62ca27e026d7..6403650aff22a2ed 100644
--- a/drivers/media/platform/rcar-vin/rcar-v4l2.c
+++ b/drivers/media/platform/rcar-vin/rcar-v4l2.c
@@ -23,6 +23,7 @@
 #include "rcar-vin.h"
 
 #define RVIN_DEFAULT_FORMAT	V4L2_PIX_FMT_YUYV
+#define RVIN_DEFAULT_COLORSPACE	V4L2_COLORSPACE_SRGB
 
 /* -----------------------------------------------------------------------------
  * Format Conversions
@@ -115,6 +116,10 @@ static int rvin_format_align(struct rvin_dev *vin, struct v4l2_pix_format *pix)
 		break;
 	}
 
+	/* Check that colorspace is reasonable */
+	if (!pix->colorspace || pix->colorspace >= 0xff)
+		pix->colorspace = RVIN_DEFAULT_COLORSPACE;
+
 	/* HW limit width to a multiple of 32 (2^5) for NV16 else 2 (2^1) */
 	walign = vin->format.pixelformat == V4L2_PIX_FMT_NV16 ? 5 : 1;
 
-- 
2.16.1

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v10 19/30] rcar-vin: set a default field to fallback on
  2018-01-29 16:34 [PATCH v10 00/30] rcar-vin: Add Gen3 with media controller Niklas Söderlund
                   ` (17 preceding siblings ...)
  2018-01-29 16:34 ` [PATCH v10 18/30] rcar-vin: add check for colorspace Niklas Söderlund
@ 2018-01-29 16:34 ` Niklas Söderlund
  2018-02-13 17:51   ` Laurent Pinchart
  2018-01-29 16:34 ` [PATCH v10 20/30] rcar-vin: use different v4l2 operations in media controller mode Niklas Söderlund
                   ` (10 subsequent siblings)
  29 siblings, 1 reply; 65+ messages in thread
From: Niklas Söderlund @ 2018-01-29 16:34 UTC (permalink / raw)
  To: Laurent Pinchart, Hans Verkuil, linux-media
  Cc: linux-renesas-soc, tomoharu.fukawa.eb, Kieran Bingham,
	Niklas Söderlund

If the field is not supported by the driver it should not try to keep
the current field. Instead it should set it to a default fallback. Since
trying a format should always result in the same state regardless of the
current state of the device.

Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
---
 drivers/media/platform/rcar-vin/rcar-v4l2.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/media/platform/rcar-vin/rcar-v4l2.c b/drivers/media/platform/rcar-vin/rcar-v4l2.c
index 6403650aff22a2ed..f69ae76b3fda50c7 100644
--- a/drivers/media/platform/rcar-vin/rcar-v4l2.c
+++ b/drivers/media/platform/rcar-vin/rcar-v4l2.c
@@ -23,6 +23,7 @@
 #include "rcar-vin.h"
 
 #define RVIN_DEFAULT_FORMAT	V4L2_PIX_FMT_YUYV
+#define RVIN_DEFAULT_FIELD	V4L2_FIELD_NONE
 #define RVIN_DEFAULT_COLORSPACE	V4L2_COLORSPACE_SRGB
 
 /* -----------------------------------------------------------------------------
@@ -171,7 +172,7 @@ static int rvin_get_source_format(struct rvin_dev *vin,
 		fmt.format.height *= 2;
 		break;
 	default:
-		vin->format.field = V4L2_FIELD_NONE;
+		vin->format.field = RVIN_DEFAULT_FIELD;
 		break;
 	}
 
@@ -267,9 +268,8 @@ static int __rvin_try_format(struct rvin_dev *vin,
 {
 	int ret;
 
-	/* Keep current field if no specific one is asked for */
 	if (pix->field == V4L2_FIELD_ANY)
-		pix->field = vin->format.field;
+		pix->field = RVIN_DEFAULT_FIELD;
 
 	/* Limit to source capabilities */
 	ret = __rvin_try_format_source(vin, which, pix);
-- 
2.16.1

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v10 20/30] rcar-vin: use different v4l2 operations in media controller mode
  2018-01-29 16:34 [PATCH v10 00/30] rcar-vin: Add Gen3 with media controller Niklas Söderlund
                   ` (18 preceding siblings ...)
  2018-01-29 16:34 ` [PATCH v10 19/30] rcar-vin: set a default field to fallback on Niklas Söderlund
@ 2018-01-29 16:34 ` Niklas Söderlund
  2018-02-13 19:42   ` Laurent Pinchart
  2018-01-29 16:34 ` [PATCH v10 21/30] rcar-vin: prepare for media controller mode initialization Niklas Söderlund
                   ` (9 subsequent siblings)
  29 siblings, 1 reply; 65+ messages in thread
From: Niklas Söderlund @ 2018-01-29 16:34 UTC (permalink / raw)
  To: Laurent Pinchart, Hans Verkuil, linux-media
  Cc: linux-renesas-soc, tomoharu.fukawa.eb, Kieran Bingham,
	Niklas Söderlund

When the driver runs in media controller mode it should not directly
control the subdevice instead userspace will be responsible for
configuring the pipeline. To be able to run in this mode a different set
of v4l2 operations needs to be used.

Add a new set of v4l2 operations to support operation without directly
interacting with the source subdevice.

Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/platform/rcar-vin/rcar-dma.c  |   3 +-
 drivers/media/platform/rcar-vin/rcar-v4l2.c | 155 +++++++++++++++++++++++++++-
 2 files changed, 154 insertions(+), 4 deletions(-)

diff --git a/drivers/media/platform/rcar-vin/rcar-dma.c b/drivers/media/platform/rcar-vin/rcar-dma.c
index ae286742f15a3ab5..811d8f8638d21200 100644
--- a/drivers/media/platform/rcar-vin/rcar-dma.c
+++ b/drivers/media/platform/rcar-vin/rcar-dma.c
@@ -628,7 +628,8 @@ static int rvin_setup(struct rvin_dev *vin)
 		/* Default to TB */
 		vnmc = VNMC_IM_FULL;
 		/* Use BT if video standard can be read and is 60 Hz format */
-		if (!v4l2_subdev_call(vin_to_source(vin), video, g_std, &std)) {
+		if (!vin->info->use_mc &&
+		    !v4l2_subdev_call(vin_to_source(vin), video, g_std, &std)) {
 			if (std & V4L2_STD_525_60)
 				vnmc = VNMC_IM_FULL | VNMC_FOC;
 		}
diff --git a/drivers/media/platform/rcar-vin/rcar-v4l2.c b/drivers/media/platform/rcar-vin/rcar-v4l2.c
index f69ae76b3fda50c7..292e1f22a4be36c7 100644
--- a/drivers/media/platform/rcar-vin/rcar-v4l2.c
+++ b/drivers/media/platform/rcar-vin/rcar-v4l2.c
@@ -18,11 +18,14 @@
 
 #include <media/v4l2-event.h>
 #include <media/v4l2-ioctl.h>
+#include <media/v4l2-mc.h>
 #include <media/v4l2-rect.h>
 
 #include "rcar-vin.h"
 
 #define RVIN_DEFAULT_FORMAT	V4L2_PIX_FMT_YUYV
+#define RVIN_DEFAULT_WIDTH	800
+#define RVIN_DEFAULT_HEIGHT	600
 #define RVIN_DEFAULT_FIELD	V4L2_FIELD_NONE
 #define RVIN_DEFAULT_COLORSPACE	V4L2_COLORSPACE_SRGB
 
@@ -698,6 +701,83 @@ static const struct v4l2_ioctl_ops rvin_ioctl_ops = {
 	.vidioc_unsubscribe_event	= v4l2_event_unsubscribe,
 };
 
+/* -----------------------------------------------------------------------------
+ * V4L2 Media Controller
+ */
+
+static int __rvin_mc_try_format(struct rvin_dev *vin,
+				struct v4l2_pix_format *pix)
+{
+	if (pix->field == V4L2_FIELD_ANY)
+		pix->field = RVIN_DEFAULT_FIELD;
+
+	return rvin_format_align(vin, pix);
+}
+
+static int rvin_mc_try_fmt_vid_cap(struct file *file, void *priv,
+				   struct v4l2_format *f)
+{
+	struct rvin_dev *vin = video_drvdata(file);
+
+	return __rvin_mc_try_format(vin, &f->fmt.pix);
+}
+
+static int rvin_mc_s_fmt_vid_cap(struct file *file, void *priv,
+				 struct v4l2_format *f)
+{
+	struct rvin_dev *vin = video_drvdata(file);
+	int ret;
+
+	if (vb2_is_busy(&vin->queue))
+		return -EBUSY;
+
+	ret = __rvin_mc_try_format(vin, &f->fmt.pix);
+	if (ret)
+		return ret;
+
+	vin->format = f->fmt.pix;
+
+	return 0;
+}
+
+static int rvin_mc_enum_input(struct file *file, void *priv,
+			      struct v4l2_input *i)
+{
+	if (i->index != 0)
+		return -EINVAL;
+
+	i->type = V4L2_INPUT_TYPE_CAMERA;
+	strlcpy(i->name, "Camera", sizeof(i->name));
+
+	return 0;
+}
+
+static const struct v4l2_ioctl_ops rvin_mc_ioctl_ops = {
+	.vidioc_querycap		= rvin_querycap,
+	.vidioc_try_fmt_vid_cap		= rvin_mc_try_fmt_vid_cap,
+	.vidioc_g_fmt_vid_cap		= rvin_g_fmt_vid_cap,
+	.vidioc_s_fmt_vid_cap		= rvin_mc_s_fmt_vid_cap,
+	.vidioc_enum_fmt_vid_cap	= rvin_enum_fmt_vid_cap,
+
+	.vidioc_enum_input		= rvin_mc_enum_input,
+	.vidioc_g_input			= rvin_g_input,
+	.vidioc_s_input			= rvin_s_input,
+
+	.vidioc_reqbufs			= vb2_ioctl_reqbufs,
+	.vidioc_create_bufs		= vb2_ioctl_create_bufs,
+	.vidioc_querybuf		= vb2_ioctl_querybuf,
+	.vidioc_qbuf			= vb2_ioctl_qbuf,
+	.vidioc_dqbuf			= vb2_ioctl_dqbuf,
+	.vidioc_expbuf			= vb2_ioctl_expbuf,
+	.vidioc_prepare_buf		= vb2_ioctl_prepare_buf,
+	.vidioc_streamon		= vb2_ioctl_streamon,
+	.vidioc_streamoff		= vb2_ioctl_streamoff,
+
+	.vidioc_log_status		= v4l2_ctrl_log_status,
+	.vidioc_subscribe_event		= rvin_subscribe_event,
+	.vidioc_unsubscribe_event	= v4l2_event_unsubscribe,
+};
+
 /* -----------------------------------------------------------------------------
  * File Operations
  */
@@ -841,6 +921,60 @@ static const struct v4l2_file_operations rvin_fops = {
 	.read		= vb2_fop_read,
 };
 
+/* -----------------------------------------------------------------------------
+ * Media controller file operations
+ */
+
+static int rvin_mc_open(struct file *file)
+{
+	struct rvin_dev *vin = video_drvdata(file);
+	int ret;
+
+	mutex_lock(&vin->lock);
+
+	file->private_data = vin;
+
+	ret = v4l2_fh_open(file);
+	if (ret)
+		goto unlock;
+
+	pm_runtime_get_sync(vin->dev);
+	v4l2_pipeline_pm_use(&vin->vdev.entity, 1);
+
+unlock:
+	mutex_unlock(&vin->lock);
+
+	return ret;
+}
+
+static int rvin_mc_release(struct file *file)
+{
+	struct rvin_dev *vin = video_drvdata(file);
+	int ret;
+
+	mutex_lock(&vin->lock);
+
+	/* the release helper will cleanup any on-going streaming */
+	ret = _vb2_fop_release(file, NULL);
+
+	v4l2_pipeline_pm_use(&vin->vdev.entity, 0);
+	pm_runtime_put(vin->dev);
+
+	mutex_unlock(&vin->lock);
+
+	return ret;
+}
+
+static const struct v4l2_file_operations rvin_mc_fops = {
+	.owner		= THIS_MODULE,
+	.unlocked_ioctl	= video_ioctl2,
+	.open		= rvin_mc_open,
+	.release	= rvin_mc_release,
+	.poll		= vb2_fop_poll,
+	.mmap		= vb2_fop_mmap,
+	.read		= vb2_fop_read,
+};
+
 void rvin_v4l2_unregister(struct rvin_dev *vin)
 {
 	if (!video_is_registered(&vin->vdev))
@@ -876,18 +1010,33 @@ int rvin_v4l2_register(struct rvin_dev *vin)
 	vin->v4l2_dev.notify = rvin_notify;
 
 	/* video node */
-	vdev->fops = &rvin_fops;
 	vdev->v4l2_dev = &vin->v4l2_dev;
 	vdev->queue = &vin->queue;
 	strlcpy(vdev->name, KBUILD_MODNAME, sizeof(vdev->name));
 	vdev->release = video_device_release_empty;
-	vdev->ioctl_ops = &rvin_ioctl_ops;
 	vdev->lock = &vin->lock;
 	vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING |
 		V4L2_CAP_READWRITE;
 
+	/* Set a default format */
 	vin->format.pixelformat	= RVIN_DEFAULT_FORMAT;
-	rvin_reset_format(vin);
+	vin->format.width = RVIN_DEFAULT_WIDTH;
+	vin->format.height = RVIN_DEFAULT_HEIGHT;
+	vin->format.field = RVIN_DEFAULT_FIELD;
+	vin->format.colorspace = RVIN_DEFAULT_COLORSPACE;
+
+	if (vin->info->use_mc) {
+		vdev->fops = &rvin_mc_fops;
+		vdev->ioctl_ops = &rvin_mc_ioctl_ops;
+	} else {
+		vdev->fops = &rvin_fops;
+		vdev->ioctl_ops = &rvin_ioctl_ops;
+		rvin_reset_format(vin);
+	}
+
+	ret = rvin_format_align(vin, &vin->format);
+	if (ret)
+		return ret;
 
 	ret = video_register_device(&vin->vdev, VFL_TYPE_GRABBER, -1);
 	if (ret) {
-- 
2.16.1

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v10 21/30] rcar-vin: prepare for media controller mode initialization
  2018-01-29 16:34 [PATCH v10 00/30] rcar-vin: Add Gen3 with media controller Niklas Söderlund
                   ` (19 preceding siblings ...)
  2018-01-29 16:34 ` [PATCH v10 20/30] rcar-vin: use different v4l2 operations in media controller mode Niklas Söderlund
@ 2018-01-29 16:34 ` Niklas Söderlund
  2018-02-13 19:47   ` Laurent Pinchart
  2018-01-29 16:34 ` [PATCH v10 22/30] rcar-vin: add group allocator functions Niklas Söderlund
                   ` (8 subsequent siblings)
  29 siblings, 1 reply; 65+ messages in thread
From: Niklas Söderlund @ 2018-01-29 16:34 UTC (permalink / raw)
  To: Laurent Pinchart, Hans Verkuil, linux-media
  Cc: linux-renesas-soc, tomoharu.fukawa.eb, Kieran Bingham,
	Niklas Söderlund

Prepare for media controller by calling a different initialization then
for when running in device centric mode. Add trivial configuration of
the mbus and creation of the media pad for the video device entity.

While we are at it clearly mark the digital device centric notifier
functions with a comment.

Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/platform/rcar-vin/rcar-core.c | 20 ++++++++++++++++++--
 drivers/media/platform/rcar-vin/rcar-vin.h  |  4 ++++
 2 files changed, 22 insertions(+), 2 deletions(-)

diff --git a/drivers/media/platform/rcar-vin/rcar-core.c b/drivers/media/platform/rcar-vin/rcar-core.c
index 64034c96f384b3ed..0c6960756c33f86c 100644
--- a/drivers/media/platform/rcar-vin/rcar-core.c
+++ b/drivers/media/platform/rcar-vin/rcar-core.c
@@ -46,6 +46,10 @@ static int rvin_find_pad(struct v4l2_subdev *sd, int direction)
 	return -EINVAL;
 }
 
+/* -----------------------------------------------------------------------------
+ * Digital async notifier
+ */
+
 /* The vin lock shuld be held when calling the subdevice attach and detach */
 static int rvin_digital_subdevice_attach(struct rvin_dev *vin,
 					 struct v4l2_subdev *subdev)
@@ -237,6 +241,16 @@ static int rvin_digital_graph_init(struct rvin_dev *vin)
 	return 0;
 }
 
+static int rvin_mc_init(struct rvin_dev *vin)
+{
+	/* All our sources are CSI-2 */
+	vin->mbus_cfg.type = V4L2_MBUS_CSI2;
+	vin->mbus_cfg.flags = 0;
+
+	vin->pad.flags = MEDIA_PAD_FL_SINK;
+	return media_entity_pads_init(&vin->vdev.entity, 1, &vin->pad);
+}
+
 /* -----------------------------------------------------------------------------
  * Platform Device Driver
  */
@@ -325,8 +339,10 @@ static int rcar_vin_probe(struct platform_device *pdev)
 		return ret;
 
 	platform_set_drvdata(pdev, vin);
-
-	ret = rvin_digital_graph_init(vin);
+	if (vin->info->use_mc)
+		ret = rvin_mc_init(vin);
+	else
+		ret = rvin_digital_graph_init(vin);
 	if (ret < 0)
 		goto error;
 
diff --git a/drivers/media/platform/rcar-vin/rcar-vin.h b/drivers/media/platform/rcar-vin/rcar-vin.h
index 64476bc5c8abc6d0..4caef7193db09c5b 100644
--- a/drivers/media/platform/rcar-vin/rcar-vin.h
+++ b/drivers/media/platform/rcar-vin/rcar-vin.h
@@ -101,6 +101,8 @@ struct rvin_info {
  * @notifier:		V4L2 asynchronous subdevs notifier
  * @digital:		entity in the DT for local digital subdevice
  *
+ * @pad:		media pad for the video device entity
+ *
  * @lock:		protects @queue
  * @queue:		vb2 buffers queue
  *
@@ -130,6 +132,8 @@ struct rvin_dev {
 	struct v4l2_async_notifier notifier;
 	struct rvin_graph_entity *digital;
 
+	struct media_pad pad;
+
 	struct mutex lock;
 	struct vb2_queue queue;
 
-- 
2.16.1

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v10 22/30] rcar-vin: add group allocator functions
  2018-01-29 16:34 [PATCH v10 00/30] rcar-vin: Add Gen3 with media controller Niklas Söderlund
                   ` (20 preceding siblings ...)
  2018-01-29 16:34 ` [PATCH v10 21/30] rcar-vin: prepare for media controller mode initialization Niklas Söderlund
@ 2018-01-29 16:34 ` Niklas Söderlund
  2018-02-13 20:09   ` Laurent Pinchart
  2018-01-29 16:34 ` [PATCH v10 23/30] rcar-vin: change name of video device Niklas Söderlund
                   ` (7 subsequent siblings)
  29 siblings, 1 reply; 65+ messages in thread
From: Niklas Söderlund @ 2018-01-29 16:34 UTC (permalink / raw)
  To: Laurent Pinchart, Hans Verkuil, linux-media
  Cc: linux-renesas-soc, tomoharu.fukawa.eb, Kieran Bingham,
	Niklas Söderlund

In media controller mode all VIN instances needs to be part of the same
media graph. There is also a need for each VIN instance to know about
and in some cases be able to communicate with other VIN instances.

Add an allocator framework where the first VIN instance to be probed
creates a shared data structure and registers a media device.
Consecutive VINs insert themself into the global group.

Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
---
 drivers/media/platform/rcar-vin/rcar-core.c | 177 +++++++++++++++++++++++++++-
 drivers/media/platform/rcar-vin/rcar-vin.h  |  31 +++++
 2 files changed, 206 insertions(+), 2 deletions(-)

diff --git a/drivers/media/platform/rcar-vin/rcar-core.c b/drivers/media/platform/rcar-vin/rcar-core.c
index 0c6960756c33f86c..4a64df5019ce45f7 100644
--- a/drivers/media/platform/rcar-vin/rcar-core.c
+++ b/drivers/media/platform/rcar-vin/rcar-core.c
@@ -20,12 +20,177 @@
 #include <linux/of_graph.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
+#include <linux/slab.h>
 
 #include <media/v4l2-async.h>
 #include <media/v4l2-fwnode.h>
 
 #include "rcar-vin.h"
 
+/* -----------------------------------------------------------------------------
+ * Gen3 CSI2 Group Allocator
+ */
+
+/* FIXME:  This should if we find a system that supports more
+ * then one group for the whole system be replaced with a linked
+ * list of groups. And eventually all of this should be replaced
+ * with a global device allocator API.
+ *
+ * But for now this works as on all supported systems there will
+ * be only one group for all instances.
+ */
+
+static DEFINE_MUTEX(rvin_group_lock);
+static struct rvin_group *rvin_group_data;
+
+static void rvin_group_cleanup(struct rvin_group *group)
+{
+	media_device_unregister(&group->mdev);
+	media_device_cleanup(&group->mdev);
+	mutex_destroy(&group->lock);
+}
+
+static int rvin_group_init(struct rvin_group *group, struct rvin_dev *vin)
+{
+	struct media_device *mdev = &group->mdev;
+	const struct of_device_id *match;
+	struct device_node *np;
+	int ret;
+
+	mutex_init(&group->lock);
+
+	/* Count number of VINs in the system */
+	group->count = 0;
+	for_each_matching_node(np, vin->dev->driver->of_match_table)
+		if (of_device_is_available(np))
+			group->count++;
+
+	vin_dbg(vin, "found %u enabled VIN's in DT", group->count);
+
+	mdev->dev = vin->dev;
+
+	match = of_match_node(vin->dev->driver->of_match_table,
+			      vin->dev->of_node);
+
+	strlcpy(mdev->driver_name, KBUILD_MODNAME, sizeof(mdev->driver_name));
+	strlcpy(mdev->model, match->compatible, sizeof(mdev->model));
+	snprintf(mdev->bus_info, sizeof(mdev->bus_info), "platform:%s",
+		 dev_name(mdev->dev));
+
+	media_device_init(mdev);
+
+	ret = media_device_register(&group->mdev);
+	if (ret)
+		rvin_group_cleanup(group);
+
+	return ret;
+}
+
+static void rvin_group_release(struct kref *kref)
+{
+	struct rvin_group *group =
+		container_of(kref, struct rvin_group, refcount);
+
+	mutex_lock(&rvin_group_lock);
+
+	rvin_group_data = NULL;
+
+	rvin_group_cleanup(group);
+
+	kfree(group);
+
+	mutex_unlock(&rvin_group_lock);
+}
+
+static int rvin_group_get(struct rvin_dev *vin)
+{
+	struct rvin_group *group;
+	u32 id;
+	int ret;
+
+	/* Make sure VIN id is present and sane */
+	ret = of_property_read_u32(vin->dev->of_node, "renesas,id", &id);
+	if (ret) {
+		vin_err(vin, "%pOF: No renesas,id property found\n",
+			vin->dev->of_node);
+		return -EINVAL;
+	}
+
+	if (id >= RCAR_VIN_NUM) {
+		vin_err(vin, "%pOF: Invalid renesas,id '%u'\n",
+			vin->dev->of_node, id);
+		return -EINVAL;
+	}
+
+	/* Join or create a VIN group */
+	mutex_lock(&rvin_group_lock);
+	if (rvin_group_data) {
+		group = rvin_group_data;
+		kref_get(&group->refcount);
+	} else {
+		group = kzalloc(sizeof(*group), GFP_KERNEL);
+		if (!group) {
+			ret = -ENOMEM;
+			goto err_group;
+		}
+
+		ret = rvin_group_init(group, vin);
+		if (ret) {
+			kfree(group);
+			vin_err(vin, "Failed to initialize group\n");
+			goto err_group;
+		}
+
+		kref_init(&group->refcount);
+
+		rvin_group_data = group;
+	}
+	mutex_unlock(&rvin_group_lock);
+
+	/* Add VIN to group */
+	mutex_lock(&group->lock);
+
+	if (group->vin[id]) {
+		vin_err(vin, "Duplicate renesas,id property value %u\n", id);
+		ret = -EINVAL;
+		goto err_vin;
+	}
+
+	group->vin[id] = vin;
+
+	vin->id = id;
+	vin->group = group;
+	vin->v4l2_dev.mdev = &group->mdev;
+
+	mutex_unlock(&group->lock);
+
+	return 0;
+err_group:
+	mutex_unlock(&rvin_group_lock);
+	return ret;
+err_vin:
+	mutex_unlock(&group->lock);
+	kref_put(&group->refcount, rvin_group_release);
+	return ret;
+}
+
+static void rvin_group_put(struct rvin_dev *vin)
+{
+	mutex_lock(&vin->group->lock);
+
+	vin->group = NULL;
+	vin->v4l2_dev.mdev = NULL;
+
+	if (WARN_ON(vin->group->vin[vin->id] != vin))
+		goto out;
+
+	vin->group->vin[vin->id] = NULL;
+out:
+	mutex_unlock(&vin->group->lock);
+
+	kref_put(&vin->group->refcount, rvin_group_release);
+}
+
 /* -----------------------------------------------------------------------------
  * Async notifier
  */
@@ -243,12 +408,18 @@ static int rvin_digital_graph_init(struct rvin_dev *vin)
 
 static int rvin_mc_init(struct rvin_dev *vin)
 {
+	int ret;
+
 	/* All our sources are CSI-2 */
 	vin->mbus_cfg.type = V4L2_MBUS_CSI2;
 	vin->mbus_cfg.flags = 0;
 
 	vin->pad.flags = MEDIA_PAD_FL_SINK;
-	return media_entity_pads_init(&vin->vdev.entity, 1, &vin->pad);
+	ret = media_entity_pads_init(&vin->vdev.entity, 1, &vin->pad);
+	if (ret)
+		return ret;
+
+	return rvin_group_get(vin);
 }
 
 /* -----------------------------------------------------------------------------
@@ -368,7 +539,9 @@ static int rcar_vin_remove(struct platform_device *pdev)
 	v4l2_async_notifier_unregister(&vin->notifier);
 	v4l2_async_notifier_cleanup(&vin->notifier);
 
-	if (!vin->info->use_mc)
+	if (vin->info->use_mc)
+		rvin_group_put(vin);
+	else
 		v4l2_ctrl_handler_free(&vin->ctrl_handler);
 
 	rvin_dma_unregister(vin);
diff --git a/drivers/media/platform/rcar-vin/rcar-vin.h b/drivers/media/platform/rcar-vin/rcar-vin.h
index 4caef7193db09c5b..903d8fb8426a7860 100644
--- a/drivers/media/platform/rcar-vin/rcar-vin.h
+++ b/drivers/media/platform/rcar-vin/rcar-vin.h
@@ -17,6 +17,8 @@
 #ifndef __RCAR_VIN__
 #define __RCAR_VIN__
 
+#include <linux/kref.h>
+
 #include <media/v4l2-async.h>
 #include <media/v4l2-ctrls.h>
 #include <media/v4l2-dev.h>
@@ -29,6 +31,11 @@
 /* Address alignment mask for HW buffers */
 #define HW_BUFFER_MASK 0x7f
 
+/* Max number on VIN instances that can be in a system */
+#define RCAR_VIN_NUM 8
+
+struct rvin_group;
+
 enum model_id {
 	RCAR_H1,
 	RCAR_M1,
@@ -101,6 +108,8 @@ struct rvin_info {
  * @notifier:		V4L2 asynchronous subdevs notifier
  * @digital:		entity in the DT for local digital subdevice
  *
+ * @group:		Gen3 CSI group
+ * @id:			Gen3 group id for this VIN
  * @pad:		media pad for the video device entity
  *
  * @lock:		protects @queue
@@ -132,6 +141,8 @@ struct rvin_dev {
 	struct v4l2_async_notifier notifier;
 	struct rvin_graph_entity *digital;
 
+	struct rvin_group *group;
+	unsigned char id;
 	struct media_pad pad;
 
 	struct mutex lock;
@@ -160,6 +171,26 @@ struct rvin_dev {
 #define vin_warn(d, fmt, arg...)	dev_warn(d->dev, fmt, ##arg)
 #define vin_err(d, fmt, arg...)		dev_err(d->dev, fmt, ##arg)
 
+/**
+ * struct rvin_group - VIN CSI2 group information
+ * @refcount:		number of VIN instances using the group
+ *
+ * @mdev:		media device which represents the group
+ *
+ * @lock:		protects the count and vin members
+ * @count:		number of enabled VIN instances found in DT
+ * @vin:		VIN instances which are part of the group
+ */
+struct rvin_group {
+	struct kref refcount;
+
+	struct media_device mdev;
+
+	struct mutex lock;
+	unsigned int count;
+	struct rvin_dev *vin[RCAR_VIN_NUM];
+};
+
 int rvin_dma_register(struct rvin_dev *vin, int irq);
 void rvin_dma_unregister(struct rvin_dev *vin);
 
-- 
2.16.1

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v10 23/30] rcar-vin: change name of video device
  2018-01-29 16:34 [PATCH v10 00/30] rcar-vin: Add Gen3 with media controller Niklas Söderlund
                   ` (21 preceding siblings ...)
  2018-01-29 16:34 ` [PATCH v10 22/30] rcar-vin: add group allocator functions Niklas Söderlund
@ 2018-01-29 16:34 ` Niklas Söderlund
  2018-02-13 20:10   ` Laurent Pinchart
  2018-01-29 16:34 ` [PATCH v10 24/30] rcar-vin: add chsel information to rvin_info Niklas Söderlund
                   ` (6 subsequent siblings)
  29 siblings, 1 reply; 65+ messages in thread
From: Niklas Söderlund @ 2018-01-29 16:34 UTC (permalink / raw)
  To: Laurent Pinchart, Hans Verkuil, linux-media
  Cc: linux-renesas-soc, tomoharu.fukawa.eb, Kieran Bingham,
	Niklas Söderlund

The rcar-vin driver needs to be part of a media controller to support
Gen3. Give each VIN instance a unique name so it can be referenced from
userspace.

Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
---
 drivers/media/platform/rcar-vin/rcar-v4l2.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/media/platform/rcar-vin/rcar-v4l2.c b/drivers/media/platform/rcar-vin/rcar-v4l2.c
index 292e1f22a4be36c7..3ac6cdcb18ce4a21 100644
--- a/drivers/media/platform/rcar-vin/rcar-v4l2.c
+++ b/drivers/media/platform/rcar-vin/rcar-v4l2.c
@@ -1012,7 +1012,7 @@ int rvin_v4l2_register(struct rvin_dev *vin)
 	/* video node */
 	vdev->v4l2_dev = &vin->v4l2_dev;
 	vdev->queue = &vin->queue;
-	strlcpy(vdev->name, KBUILD_MODNAME, sizeof(vdev->name));
+	snprintf(vdev->name, sizeof(vdev->name), "VIN%u output", vin->id);
 	vdev->release = video_device_release_empty;
 	vdev->lock = &vin->lock;
 	vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING |
-- 
2.16.1

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v10 24/30] rcar-vin: add chsel information to rvin_info
  2018-01-29 16:34 [PATCH v10 00/30] rcar-vin: Add Gen3 with media controller Niklas Söderlund
                   ` (22 preceding siblings ...)
  2018-01-29 16:34 ` [PATCH v10 23/30] rcar-vin: change name of video device Niklas Söderlund
@ 2018-01-29 16:34 ` Niklas Söderlund
  2018-02-13 20:19   ` Laurent Pinchart
  2018-01-29 16:34 ` [PATCH v10 25/30] rcar-vin: parse Gen3 OF and setup media graph Niklas Söderlund
                   ` (5 subsequent siblings)
  29 siblings, 1 reply; 65+ messages in thread
From: Niklas Söderlund @ 2018-01-29 16:34 UTC (permalink / raw)
  To: Laurent Pinchart, Hans Verkuil, linux-media
  Cc: linux-renesas-soc, tomoharu.fukawa.eb, Kieran Bingham,
	Niklas Söderlund

Each Gen3 SoC has a limited set of predefined routing possibilities for
which CSI-2 device and virtual channel can be routed to which VIN
instance. Prepare to store this information in the struct rvin_info.

Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
---
 drivers/media/platform/rcar-vin/rcar-vin.h | 30 ++++++++++++++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/drivers/media/platform/rcar-vin/rcar-vin.h b/drivers/media/platform/rcar-vin/rcar-vin.h
index 903d8fb8426a7860..ca2c2a23cef8506c 100644
--- a/drivers/media/platform/rcar-vin/rcar-vin.h
+++ b/drivers/media/platform/rcar-vin/rcar-vin.h
@@ -43,6 +43,14 @@ enum model_id {
 	RCAR_GEN3,
 };
 
+enum rvin_csi_id {
+	RVIN_CSI20,
+	RVIN_CSI21,
+	RVIN_CSI40,
+	RVIN_CSI41,
+	RVIN_CSI_MAX,
+};
+
 /**
  * STOPPED  - No operation in progress
  * RUNNING  - Operation in progress have buffers
@@ -81,12 +89,33 @@ struct rvin_graph_entity {
 	unsigned int sink_pad;
 };
 
+/** struct rvin_group_route - Map a CSI-2 receiver and channel to a CHSEL
+ * @vin:		Which VIN the CSI-2 and VC describes
+ * @csi:		VIN internal number for CSI-2 device
+ * @chan:		Output channel of the CSI-2 receiver. Each R-Car CSI-2
+ *			receiver has four output channels facing the VIN
+ *			devices, each channel can carry one CSI-2 Virtual
+ *			Channel (VC) and there are no correlation between
+ *			output channel number and CSI-2 VC. It's up to the
+ *			CSI-2 receiver driver to configure which VC is
+ *			outputted on which channel, the VIN devices only
+ *			cares about output channels.
+ * @mask:		Bitmask of chsel values which accommodates route
+ */
+struct rvin_group_route {
+	unsigned int vin;
+	enum rvin_csi_id csi;
+	unsigned char chan;
+	unsigned int mask;
+};
+
 /**
  * struct rvin_info - Information about the particular VIN implementation
  * @model:		VIN model
  * @use_mc:		use media controller instead of controlling subdevice
  * @max_width:		max input width the VIN supports
  * @max_height:		max input height the VIN supports
+ * @routes:		routing table VIN <-> CSI-2 for the chsel values
  */
 struct rvin_info {
 	enum model_id model;
@@ -94,6 +123,7 @@ struct rvin_info {
 
 	unsigned int max_width;
 	unsigned int max_height;
+	const struct rvin_group_route *routes;
 };
 
 /**
-- 
2.16.1

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v10 25/30] rcar-vin: parse Gen3 OF and setup media graph
  2018-01-29 16:34 [PATCH v10 00/30] rcar-vin: Add Gen3 with media controller Niklas Söderlund
                   ` (23 preceding siblings ...)
  2018-01-29 16:34 ` [PATCH v10 24/30] rcar-vin: add chsel information to rvin_info Niklas Söderlund
@ 2018-01-29 16:34 ` Niklas Söderlund
  2018-02-13 21:01   ` Laurent Pinchart
  2018-01-29 16:34 ` [PATCH v10 26/30] rcar-vin: add link notify for Gen3 Niklas Söderlund
                   ` (4 subsequent siblings)
  29 siblings, 1 reply; 65+ messages in thread
From: Niklas Söderlund @ 2018-01-29 16:34 UTC (permalink / raw)
  To: Laurent Pinchart, Hans Verkuil, linux-media
  Cc: linux-renesas-soc, tomoharu.fukawa.eb, Kieran Bingham,
	Niklas Söderlund

The parsing and registering CSI-2 subdevices with the v4l2 async
framework is a collaborative effort shared between the VIN instances
which are part of the group. When the last VIN in the group is probed it
asks all other VINs to parse its share of OF and record the async
subdevices it finds in the notifier belonging to the last probed VIN.

Once all CSI-2 subdevices in this notifier are bound proceed to register
all VIN video devices of the group and crate media device links between
all CSI-2 and VIN entities according to the SoC specific routing
configuration.

Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
---
 drivers/media/platform/rcar-vin/rcar-core.c | 250 +++++++++++++++++++++++++++-
 drivers/media/platform/rcar-vin/rcar-vin.h  |  12 +-
 2 files changed, 258 insertions(+), 4 deletions(-)

diff --git a/drivers/media/platform/rcar-vin/rcar-core.c b/drivers/media/platform/rcar-vin/rcar-core.c
index 4a64df5019ce45f7..f08277a0dc11f477 100644
--- a/drivers/media/platform/rcar-vin/rcar-core.c
+++ b/drivers/media/platform/rcar-vin/rcar-core.c
@@ -27,6 +27,23 @@
 
 #include "rcar-vin.h"
 
+/*
+ * The companion CSI-2 receiver driver (rcar-csi2) is known
+ * and we know it have one source pad (pad 0) and four sink
+ * pads (pad 1-4). So to translate a pad on the remote
+ * CSI-2 receiver to/from the VIN internal channel number simply
+ * subtract/add or one from the pad/chan number.
+ */
+#define rvin_group_csi_pad_to_chan(pad) ((pad) - 1)
+#define rvin_group_csi_chan_to_pad(chan) ((chan) + 1)
+
+/*
+ * Not all VINs are created equal, master VINs control the
+ * routing for other VIN's. We can figure out which VIN is
+ * master by looking at a VINs id
+ */
+#define rvin_group_id_to_master(vin) ((vin) < 4 ? 0 : 4)
+
 /* -----------------------------------------------------------------------------
  * Gen3 CSI2 Group Allocator
  */
@@ -77,6 +94,8 @@ static int rvin_group_init(struct rvin_group *group, struct rvin_dev *vin)
 	snprintf(mdev->bus_info, sizeof(mdev->bus_info), "platform:%s",
 		 dev_name(mdev->dev));
 
+	group->notifier = NULL;
+
 	media_device_init(mdev);
 
 	ret = media_device_register(&group->mdev);
@@ -406,6 +425,218 @@ static int rvin_digital_graph_init(struct rvin_dev *vin)
 	return 0;
 }
 
+/* -----------------------------------------------------------------------------
+ * Group async notifier
+ */
+
+static int rvin_group_notify_complete(struct v4l2_async_notifier *notifier)
+{
+	struct rvin_dev *vin = notifier_to_vin(notifier);
+	const struct rvin_group_route *route;
+	unsigned int i;
+	int ret;
+
+	ret = v4l2_device_register_subdev_nodes(&vin->v4l2_dev);
+	if (ret) {
+		vin_err(vin, "Failed to register subdev nodes\n");
+		return ret;
+	}
+
+	/* Register all video nodes for the group */
+	for (i = 0; i < RCAR_VIN_NUM; i++) {
+		if (vin->group->vin[i]) {
+			ret = rvin_v4l2_register(vin->group->vin[i]);
+			if (ret)
+				return ret;
+		}
+	}
+
+	/* Create all media device links between VINs and CSI-2's */
+	mutex_lock(&vin->group->lock);
+	for (route = vin->info->routes; route->mask; route++) {
+		struct media_pad *source_pad, *sink_pad;
+		struct media_entity *source, *sink;
+		unsigned int source_idx;
+
+		/* Check that VIN is part of the group */
+		if (!vin->group->vin[route->vin])
+			continue;
+
+		/* Check that VIN' master is part of the group */
+		if (!vin->group->vin[rvin_group_id_to_master(route->vin)])
+			continue;
+
+		/* Check that CSI-2 is part of the group */
+		if (!vin->group->csi[route->csi].subdev)
+			continue;
+
+		source = &vin->group->csi[route->csi].subdev->entity;
+		source_idx = rvin_group_csi_chan_to_pad(route->chan);
+		source_pad = &source->pads[source_idx];
+
+		sink = &vin->group->vin[route->vin]->vdev.entity;
+		sink_pad = &sink->pads[0];
+
+		/* Skip if link already exists */
+		if (media_entity_find_link(source_pad, sink_pad))
+			continue;
+
+		ret = media_create_pad_link(source, source_idx, sink, 0, 0);
+		if (ret) {
+			vin_err(vin, "Error adding link from %s to %s\n",
+				source->name, sink->name);
+			break;
+		}
+	}
+	mutex_unlock(&vin->group->lock);
+
+	return ret;
+}
+
+static void rvin_group_notify_unbind(struct v4l2_async_notifier *notifier,
+				     struct v4l2_subdev *subdev,
+				     struct v4l2_async_subdev *asd)
+{
+	struct rvin_dev *vin = notifier_to_vin(notifier);
+	unsigned int i;
+
+	for (i = 0; i < RCAR_VIN_NUM; i++)
+		if (vin->group->vin[i])
+			rvin_v4l2_unregister(vin->group->vin[i]);
+
+	mutex_lock(&vin->group->lock);
+
+	for (i = 0; i < RVIN_CSI_MAX; i++) {
+		if (vin->group->csi[i].fwnode != asd->match.fwnode)
+			continue;
+		vin->group->csi[i].subdev = NULL;
+		vin_dbg(vin, "Unbind CSI-2 %s from slot %u\n", subdev->name, i);
+		break;
+	}
+
+	mutex_unlock(&vin->group->lock);
+}
+
+static int rvin_group_notify_bound(struct v4l2_async_notifier *notifier,
+				   struct v4l2_subdev *subdev,
+				   struct v4l2_async_subdev *asd)
+{
+	struct rvin_dev *vin = notifier_to_vin(notifier);
+	unsigned int i;
+
+	mutex_lock(&vin->group->lock);
+
+	for (i = 0; i < RVIN_CSI_MAX; i++) {
+		if (vin->group->csi[i].fwnode != asd->match.fwnode)
+			continue;
+		vin->group->csi[i].subdev = subdev;
+		vin_dbg(vin, "Bound CSI-2 %s to slot %u\n", subdev->name, i);
+		break;
+	}
+
+	mutex_unlock(&vin->group->lock);
+
+	return 0;
+}
+
+static const struct v4l2_async_notifier_operations rvin_group_notify_ops = {
+	.bound = rvin_group_notify_bound,
+	.unbind = rvin_group_notify_unbind,
+	.complete = rvin_group_notify_complete,
+};
+
+static int rvin_mc_parse_v4l2(struct device *dev,
+				   struct v4l2_fwnode_endpoint *vep,
+				   struct v4l2_async_subdev *asd)
+{
+	struct rvin_dev *vin = dev_get_drvdata(dev);
+	struct v4l2_async_notifier *notifier = vin->group->notifier;
+	unsigned int i;
+
+	if (vep->base.port != 1 || vep->base.id >= RVIN_CSI_MAX)
+		return -EINVAL;
+
+	if (!of_device_is_available(to_of_node(asd->match.fwnode))) {
+		vin_dbg(vin, "Subdevice %pOF disabled, ignoring\n",
+			to_of_node(asd->match.fwnode));
+		return -ENOTCONN;
+
+	}
+
+	for (i = 0; i < notifier->num_subdevs; i++) {
+		if (notifier->subdevs[i]->match.fwnode == asd->match.fwnode) {
+			vin_dbg(vin, "Subdevice %pOF already handled\n",
+				to_of_node(asd->match.fwnode));
+			return -ENOTCONN;
+		}
+	}
+
+	vin->group->csi[vep->base.id].fwnode = asd->match.fwnode;
+
+	vin_dbg(vin, "Add group subdevice %pOF to slot %u\n",
+		to_of_node(asd->match.fwnode), vep->base.id);
+
+	return 0;
+}
+
+static int rvin_mc_try_parse(struct rvin_dev *vin)
+{
+	unsigned int i, count = 0;
+	int ret;
+
+	mutex_lock(&vin->group->lock);
+
+	/* If there already is a notifier something have gone wrong, bail */
+	if (WARN_ON(vin->group->notifier)) {
+		mutex_unlock(&vin->group->lock);
+		return -EINVAL;
+	}
+
+	/* If not all VIN's are registered don't register the notifier */
+	for (i = 0; i < RCAR_VIN_NUM; i++)
+		if (vin->group->vin[i])
+			count++;
+
+	if (vin->group->count != count) {
+		mutex_unlock(&vin->group->lock);
+		return 0;
+	}
+
+	/*
+	 * Have all VIN's look for subdevices. Some subdevices will overlap
+	 * but the parser function can handle it, so each subdevice will
+	 * only be registered once with the notifier
+	 */
+
+	vin->group->notifier = &vin->notifier;
+
+	for (i = 0; i < RCAR_VIN_NUM; i++) {
+		if (!vin->group->vin[i])
+			continue;
+
+		ret = v4l2_async_notifier_parse_fwnode_endpoints_by_port(
+				vin->group->vin[i]->dev, vin->group->notifier,
+				sizeof(struct v4l2_async_subdev), 1,
+				rvin_mc_parse_v4l2);
+		if (ret) {
+			mutex_unlock(&vin->group->lock);
+			return ret;
+		}
+	}
+
+	mutex_unlock(&vin->group->lock);
+
+	vin->group->notifier->ops = &rvin_group_notify_ops;
+
+	ret = v4l2_async_notifier_register(&vin->v4l2_dev, &vin->notifier);
+	if (ret < 0) {
+		vin_err(vin, "Notifier registration failed\n");
+		return ret;
+	}
+
+	return 0;
+}
+
 static int rvin_mc_init(struct rvin_dev *vin)
 {
 	int ret;
@@ -419,7 +650,15 @@ static int rvin_mc_init(struct rvin_dev *vin)
 	if (ret)
 		return ret;
 
-	return rvin_group_get(vin);
+	ret = rvin_group_get(vin);
+	if (ret)
+		return ret;
+
+	ret = rvin_mc_try_parse(vin);
+	if (ret)
+		rvin_group_put(vin);
+
+	return ret;
 }
 
 /* -----------------------------------------------------------------------------
@@ -539,10 +778,15 @@ static int rcar_vin_remove(struct platform_device *pdev)
 	v4l2_async_notifier_unregister(&vin->notifier);
 	v4l2_async_notifier_cleanup(&vin->notifier);
 
-	if (vin->info->use_mc)
+	if (vin->info->use_mc) {
+		mutex_lock(&vin->group->lock);
+		if (vin->group->notifier == &vin->notifier)
+			vin->group->notifier = NULL;
+		mutex_unlock(&vin->group->lock);
 		rvin_group_put(vin);
-	else
+	} else {
 		v4l2_ctrl_handler_free(&vin->ctrl_handler);
+	}
 
 	rvin_dma_unregister(vin);
 
diff --git a/drivers/media/platform/rcar-vin/rcar-vin.h b/drivers/media/platform/rcar-vin/rcar-vin.h
index ca2c2a23cef8506c..6cef78df42047c8c 100644
--- a/drivers/media/platform/rcar-vin/rcar-vin.h
+++ b/drivers/media/platform/rcar-vin/rcar-vin.h
@@ -207,9 +207,13 @@ struct rvin_dev {
  *
  * @mdev:		media device which represents the group
  *
- * @lock:		protects the count and vin members
+ * @lock:		protects the count, notifier, vin and csi members
  * @count:		number of enabled VIN instances found in DT
+ * @notifier:		pointer to the notifier of a VIN which handles the
+ *			groups async sub-devices.
  * @vin:		VIN instances which are part of the group
+ * @csi:		array of pairs of fwnode and subdev pointers
+ *			to all CSI-2 subdevices.
  */
 struct rvin_group {
 	struct kref refcount;
@@ -218,7 +222,13 @@ struct rvin_group {
 
 	struct mutex lock;
 	unsigned int count;
+	struct v4l2_async_notifier *notifier;
 	struct rvin_dev *vin[RCAR_VIN_NUM];
+
+	struct {
+		struct fwnode_handle *fwnode;
+		struct v4l2_subdev *subdev;
+	} csi[RVIN_CSI_MAX];
 };
 
 int rvin_dma_register(struct rvin_dev *vin, int irq);
-- 
2.16.1

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v10 26/30] rcar-vin: add link notify for Gen3
  2018-01-29 16:34 [PATCH v10 00/30] rcar-vin: Add Gen3 with media controller Niklas Söderlund
                   ` (24 preceding siblings ...)
  2018-01-29 16:34 ` [PATCH v10 25/30] rcar-vin: parse Gen3 OF and setup media graph Niklas Söderlund
@ 2018-01-29 16:34 ` Niklas Söderlund
  2018-02-13 21:17   ` Laurent Pinchart
  2018-01-29 16:34 ` [PATCH v10 27/30] rcar-vin: extend {start,stop}_streaming to work with media controller Niklas Söderlund
                   ` (3 subsequent siblings)
  29 siblings, 1 reply; 65+ messages in thread
From: Niklas Söderlund @ 2018-01-29 16:34 UTC (permalink / raw)
  To: Laurent Pinchart, Hans Verkuil, linux-media
  Cc: linux-renesas-soc, tomoharu.fukawa.eb, Kieran Bingham,
	Niklas Söderlund

Add the ability to process media device link change request. Link
enabling is a bit complicated on Gen3, whether or not it's possible to
enable a link depends on what other links already are enabled. On Gen3
the 8 VINs are split into two subgroup's (VIN0-3 and VIN4-7) and from a
routing perspective these two groups are independent of each other.
Each subgroup's routing is controlled by the subgroup VIN master
instance (VIN0 and VIN4).

There are a limited number of possible route setups available for each
subgroup and the configuration of each setup is dictated by the
hardware. On H3 for example there are 6 possible route setups for each
subgroup to choose from.

This leads to the media device link notification code being rather large
since it will find the best routing configuration to try and accommodate
as many links as possible. When it's not possible to enable a new link
due to hardware constrains the link_notifier callback will return
-EMLINK.

Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
---
 drivers/media/platform/rcar-vin/rcar-core.c | 129 ++++++++++++++++++++++++++++
 1 file changed, 129 insertions(+)

diff --git a/drivers/media/platform/rcar-vin/rcar-core.c b/drivers/media/platform/rcar-vin/rcar-core.c
index f08277a0dc11f477..7ceff0de40078580 100644
--- a/drivers/media/platform/rcar-vin/rcar-core.c
+++ b/drivers/media/platform/rcar-vin/rcar-core.c
@@ -24,6 +24,7 @@
 
 #include <media/v4l2-async.h>
 #include <media/v4l2-fwnode.h>
+#include <media/v4l2-mc.h>
 
 #include "rcar-vin.h"
 
@@ -44,6 +45,133 @@
  */
 #define rvin_group_id_to_master(vin) ((vin) < 4 ? 0 : 4)
 
+/* -----------------------------------------------------------------------------
+ * Media Controller link notification
+ */
+
+/* group lock should be held when calling this function */
+static int rvin_group_entity_to_csi_id(struct rvin_group *group,
+					struct media_entity *entity)
+{
+	struct v4l2_subdev *sd;
+	int i;
+
+	if (!is_media_entity_v4l2_subdev(entity))
+		return -ENODEV;
+
+	sd = media_entity_to_v4l2_subdev(entity);
+
+	for (i = 0; i < RVIN_CSI_MAX; i++)
+		if (group->csi[i].subdev == sd)
+			return i;
+
+	return -ENODEV;
+}
+
+static unsigned int rvin_group_get_mask(struct rvin_dev *vin,
+					enum rvin_csi_id csi_id,
+					unsigned char chan)
+{
+	const struct rvin_group_route *route;
+	unsigned int mask = 0;
+
+	for (route = vin->info->routes; route->mask; route++) {
+		if (route->vin == vin->id &&
+		    route->csi == csi_id &&
+		    route->chan == chan) {
+			vin_dbg(vin, "Adding route: vin: %d csi: %d chan: %d\n",
+				route->vin, route->csi, route->chan);
+			mask |= route->mask;
+		}
+	}
+
+	return mask;
+}
+
+static int rvin_group_link_notify(struct media_link *link, u32 flags,
+				  unsigned int notification)
+{
+	struct rvin_group *group = container_of(link->graph_obj.mdev,
+						struct rvin_group, mdev);
+	unsigned int i, master_id, chan, mask_new, mask = ~0;
+	struct media_entity *entity;
+	struct video_device *vdev;
+	struct media_pad *csi_pad;
+	struct rvin_dev *vin = NULL;
+	int csi_id, ret;
+
+	ret = v4l2_pipeline_link_notify(link, flags, notification);
+	if (ret)
+		return ret;
+
+	/* Only care about link enablement for VIN nodes */
+	if (!(flags & MEDIA_LNK_FL_ENABLED) ||
+	    !is_media_entity_v4l2_video_device(link->sink->entity))
+		return 0;
+
+	/* If any entity are in use don't allow link changes */
+	media_device_for_each_entity(entity, &group->mdev)
+		if (entity->use_count)
+			return -EBUSY;
+
+	mutex_lock(&group->lock);
+
+	/* Find VIN and its master for which the link */
+	entity = link->sink->entity;
+	vdev = media_entity_to_video_device(entity);
+	for (i = 0; i < RCAR_VIN_NUM; i++) {
+		if (group->vin[i] && &group->vin[i]->vdev == vdev) {
+			vin = group->vin[i];
+			master_id = rvin_group_id_to_master(vin->id);
+			break;
+		}
+	}
+	if (WARN_ON(!vin || !group->vin[master_id])) {
+		ret = -ENODEV;
+		goto out;
+	}
+
+	/* Build a mask for already enabled links */
+	for (i = master_id; i < master_id + 4; i++) {
+		if (!group->vin[i])
+			continue;
+
+		/* Get remote CSI-2, if any */
+		csi_pad = media_entity_remote_pad(
+				&group->vin[i]->vdev.entity.pads[0]);
+		if (!csi_pad)
+			continue;
+
+		csi_id = rvin_group_entity_to_csi_id(group, csi_pad->entity);
+		chan = rvin_group_csi_pad_to_chan(csi_pad->index);
+
+		mask &= rvin_group_get_mask(group->vin[i], csi_id, chan);
+	}
+
+	/* Add the new link to the existing mask and check if it works */
+	csi_id = rvin_group_entity_to_csi_id(group, link->source->entity);
+	chan = rvin_group_csi_pad_to_chan(link->source->index);
+	mask_new = mask & rvin_group_get_mask(vin, csi_id, chan);
+
+	vin_dbg(vin, "Try link change mask: 0x%x new: 0x%x\n", mask, mask_new);
+
+	if (!mask_new) {
+		ret = -EMLINK;
+		goto out;
+	}
+
+	/* New valid CHSEL found, set the new value */
+	rvin_set_channel_routing(group->vin[master_id], __ffs(mask_new));
+out:
+	mutex_unlock(&group->lock);
+
+	return ret;
+}
+
+static const struct media_device_ops rvin_media_ops = {
+	.link_notify = rvin_group_link_notify,
+};
+
 /* -----------------------------------------------------------------------------
  * Gen3 CSI2 Group Allocator
  */
@@ -85,6 +213,7 @@ static int rvin_group_init(struct rvin_group *group, struct rvin_dev *vin)
 	vin_dbg(vin, "found %u enabled VIN's in DT", group->count);
 
 	mdev->dev = vin->dev;
+	mdev->ops = &rvin_media_ops;
 
 	match = of_match_node(vin->dev->driver->of_match_table,
 			      vin->dev->of_node);
-- 
2.16.1

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v10 27/30] rcar-vin: extend {start,stop}_streaming to work with media controller
  2018-01-29 16:34 [PATCH v10 00/30] rcar-vin: Add Gen3 with media controller Niklas Söderlund
                   ` (25 preceding siblings ...)
  2018-01-29 16:34 ` [PATCH v10 26/30] rcar-vin: add link notify for Gen3 Niklas Söderlund
@ 2018-01-29 16:34 ` Niklas Söderlund
  2018-02-13 21:31   ` Laurent Pinchart
  2018-01-29 16:34 ` [PATCH v10 28/30] rcar-vin: enable support for r8a7795 Niklas Söderlund
                   ` (2 subsequent siblings)
  29 siblings, 1 reply; 65+ messages in thread
From: Niklas Söderlund @ 2018-01-29 16:34 UTC (permalink / raw)
  To: Laurent Pinchart, Hans Verkuil, linux-media
  Cc: linux-renesas-soc, tomoharu.fukawa.eb, Kieran Bingham,
	Niklas Söderlund

The procedure to start or stop streaming using the non-MC single
subdevice and the MC graph and multiple subdevices are quite different.
Create a new function to abstract which method is used based on which
mode the driver is running in and add logic to start the MC graph.

Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
---
 drivers/media/platform/rcar-vin/rcar-dma.c | 123 +++++++++++++++++++++++++++--
 1 file changed, 116 insertions(+), 7 deletions(-)

diff --git a/drivers/media/platform/rcar-vin/rcar-dma.c b/drivers/media/platform/rcar-vin/rcar-dma.c
index 811d8f8638d21200..6784e7eb3d96e1c0 100644
--- a/drivers/media/platform/rcar-vin/rcar-dma.c
+++ b/drivers/media/platform/rcar-vin/rcar-dma.c
@@ -1087,15 +1087,126 @@ static void rvin_buffer_queue(struct vb2_buffer *vb)
 	spin_unlock_irqrestore(&vin->qlock, flags);
 }
 
+static int rvin_set_stream(struct rvin_dev *vin, int on)
+{
+	struct v4l2_subdev_format fmt = {
+		.which = V4L2_SUBDEV_FORMAT_ACTIVE,
+	};
+	struct media_pipeline *pipe;
+	struct media_device *mdev;
+	struct  v4l2_subdev *sd;
+	struct media_pad *pad;
+	int ret;
+
+	/* No media controller used, simply pass operation to subdevice */
+	if (!vin->info->use_mc) {
+		ret = v4l2_subdev_call(vin->digital->subdev, video, s_stream,
+				       on);
+
+		return ret == -ENOIOCTLCMD ? 0 : ret;
+	}
+
+	pad = media_entity_remote_pad(&vin->pad);
+	if (!pad)
+		return -EPIPE;
+
+	sd = media_entity_to_v4l2_subdev(pad->entity);
+
+	if (!on) {
+		media_pipeline_stop(&vin->vdev.entity);
+		return v4l2_subdev_call(sd, video, s_stream, 0);
+	}
+
+	fmt.pad = pad->index;
+	if (v4l2_subdev_call(sd, pad, get_fmt, NULL, &fmt))
+		return -EPIPE;
+
+	switch (fmt.format.code) {
+	case MEDIA_BUS_FMT_YUYV8_1X16:
+	case MEDIA_BUS_FMT_UYVY8_2X8:
+	case MEDIA_BUS_FMT_UYVY10_2X10:
+	case MEDIA_BUS_FMT_RGB888_1X24:
+		vin->code = fmt.format.code;
+		break;
+	default:
+		return -EPIPE;
+	}
+
+	switch (fmt.format.field) {
+	case V4L2_FIELD_TOP:
+	case V4L2_FIELD_BOTTOM:
+	case V4L2_FIELD_NONE:
+	case V4L2_FIELD_INTERLACED_TB:
+	case V4L2_FIELD_INTERLACED_BT:
+	case V4L2_FIELD_INTERLACED:
+	case V4L2_FIELD_SEQ_TB:
+	case V4L2_FIELD_SEQ_BT:
+		/* Supported natively */
+		break;
+	case V4L2_FIELD_ALTERNATE:
+		switch (vin->format.field) {
+		case V4L2_FIELD_TOP:
+		case V4L2_FIELD_BOTTOM:
+		case V4L2_FIELD_NONE:
+			break;
+		case V4L2_FIELD_INTERLACED_TB:
+		case V4L2_FIELD_INTERLACED_BT:
+		case V4L2_FIELD_INTERLACED:
+		case V4L2_FIELD_SEQ_TB:
+		case V4L2_FIELD_SEQ_BT:
+			/* Use VIN hardware to combine the two fields */
+			fmt.format.height *= 2;
+			break;
+		default:
+			return -EPIPE;
+		}
+		break;
+	default:
+		return -EPIPE;
+	}
+
+	if (fmt.format.width != vin->format.width ||
+	    fmt.format.height != vin->format.height ||
+	    fmt.format.code != vin->code)
+		return -EPIPE;
+
+	mdev = vin->vdev.entity.graph_obj.mdev;
+
+	/*
+	 * The graph lock needs to be taken to protect concurrent
+	 * starts of multiple VIN instances as they might share
+	 * a common subdevice down the line and then should use
+	 * the same pipe.
+	 */
+	mutex_lock(&mdev->graph_mutex);
+	pipe = sd->entity.pipe ? sd->entity.pipe : &vin->vdev.pipe;
+	ret = __media_pipeline_start(&vin->vdev.entity, pipe);
+	mutex_unlock(&mdev->graph_mutex);
+	if (ret)
+		return ret;
+
+	ret = v4l2_subdev_call(sd, video, s_stream, 1);
+	if (ret == -ENOIOCTLCMD)
+		ret = 0;
+	if (ret)
+		media_pipeline_stop(&vin->vdev.entity);
+
+	return ret;
+}
+
 static int rvin_start_streaming(struct vb2_queue *vq, unsigned int count)
 {
 	struct rvin_dev *vin = vb2_get_drv_priv(vq);
-	struct v4l2_subdev *sd;
 	unsigned long flags;
 	int ret;
 
-	sd = vin_to_source(vin);
-	v4l2_subdev_call(sd, video, s_stream, 1);
+	ret = rvin_set_stream(vin, 1);
+	if (ret) {
+		spin_lock_irqsave(&vin->qlock, flags);
+		return_all_buffers(vin, VB2_BUF_STATE_QUEUED);
+		spin_unlock_irqrestore(&vin->qlock, flags);
+		return ret;
+	}
 
 	spin_lock_irqsave(&vin->qlock, flags);
 
@@ -1104,7 +1215,7 @@ static int rvin_start_streaming(struct vb2_queue *vq, unsigned int count)
 	ret = rvin_capture_start(vin);
 	if (ret) {
 		return_all_buffers(vin, VB2_BUF_STATE_QUEUED);
-		v4l2_subdev_call(sd, video, s_stream, 0);
+		rvin_set_stream(vin, 0);
 	}
 
 	spin_unlock_irqrestore(&vin->qlock, flags);
@@ -1115,7 +1226,6 @@ static int rvin_start_streaming(struct vb2_queue *vq, unsigned int count)
 static void rvin_stop_streaming(struct vb2_queue *vq)
 {
 	struct rvin_dev *vin = vb2_get_drv_priv(vq);
-	struct v4l2_subdev *sd;
 	unsigned long flags;
 	int retries = 0;
 
@@ -1154,8 +1264,7 @@ static void rvin_stop_streaming(struct vb2_queue *vq)
 
 	spin_unlock_irqrestore(&vin->qlock, flags);
 
-	sd = vin_to_source(vin);
-	v4l2_subdev_call(sd, video, s_stream, 0);
+	rvin_set_stream(vin, 0);
 
 	/* disable interrupts */
 	rvin_disable_interrupts(vin);
-- 
2.16.1

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v10 28/30] rcar-vin: enable support for r8a7795
  2018-01-29 16:34 [PATCH v10 00/30] rcar-vin: Add Gen3 with media controller Niklas Söderlund
                   ` (26 preceding siblings ...)
  2018-01-29 16:34 ` [PATCH v10 27/30] rcar-vin: extend {start,stop}_streaming to work with media controller Niklas Söderlund
@ 2018-01-29 16:34 ` Niklas Söderlund
  2018-02-13 21:52   ` Laurent Pinchart
  2018-01-29 16:34 ` [PATCH v10 29/30] rcar-vin: enable support for r8a7796 Niklas Söderlund
  2018-01-29 16:34 ` [PATCH v10 30/30] rcar-vin: enable support for r8a77970 Niklas Söderlund
  29 siblings, 1 reply; 65+ messages in thread
From: Niklas Söderlund @ 2018-01-29 16:34 UTC (permalink / raw)
  To: Laurent Pinchart, Hans Verkuil, linux-media
  Cc: linux-renesas-soc, tomoharu.fukawa.eb, Kieran Bingham,
	Niklas Söderlund

Add the SoC specific information for Renesas r8a7795 ES1.x and ES2.0.

Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
---
 drivers/media/platform/rcar-vin/Kconfig     |   2 +-
 drivers/media/platform/rcar-vin/rcar-core.c | 120 ++++++++++++++++++++++++++++
 2 files changed, 121 insertions(+), 1 deletion(-)

diff --git a/drivers/media/platform/rcar-vin/Kconfig b/drivers/media/platform/rcar-vin/Kconfig
index af4c98b44d2e22cb..8fa7ee468c63afb9 100644
--- a/drivers/media/platform/rcar-vin/Kconfig
+++ b/drivers/media/platform/rcar-vin/Kconfig
@@ -6,7 +6,7 @@ config VIDEO_RCAR_VIN
 	select V4L2_FWNODE
 	---help---
 	  Support for Renesas R-Car Video Input (VIN) driver.
-	  Supports R-Car Gen2 SoCs.
+	  Supports R-Car Gen2 and Gen3 SoCs.
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called rcar-vin.
diff --git a/drivers/media/platform/rcar-vin/rcar-core.c b/drivers/media/platform/rcar-vin/rcar-core.c
index 7ceff0de40078580..43d2fa83875817f0 100644
--- a/drivers/media/platform/rcar-vin/rcar-core.c
+++ b/drivers/media/platform/rcar-vin/rcar-core.c
@@ -21,6 +21,7 @@
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/slab.h>
+#include <linux/sys_soc.h>
 
 #include <media/v4l2-async.h>
 #include <media/v4l2-fwnode.h>
@@ -815,6 +816,104 @@ static const struct rvin_info rcar_info_gen2 = {
 	.max_height = 2048,
 };
 
+static const struct rvin_group_route rcar_info_r8a7795_routes[] = {
+	{ .vin = 0, .csi = RVIN_CSI40, .chan = 0, .mask = BIT(0) | BIT(3) },
+	{ .vin = 0, .csi = RVIN_CSI20, .chan = 0, .mask = BIT(1) | BIT(4) },
+	{ .vin = 0, .csi = RVIN_CSI40, .chan = 1, .mask = BIT(2) },
+	{ .vin = 1, .csi = RVIN_CSI20, .chan = 0, .mask = BIT(0) },
+	{ .vin = 1, .csi = RVIN_CSI40, .chan = 1, .mask = BIT(1) | BIT(3) },
+	{ .vin = 1, .csi = RVIN_CSI40, .chan = 0, .mask = BIT(2) },
+	{ .vin = 1, .csi = RVIN_CSI20, .chan = 1, .mask = BIT(4) },
+	{ .vin = 2, .csi = RVIN_CSI20, .chan = 1, .mask = BIT(0) },
+	{ .vin = 2, .csi = RVIN_CSI40, .chan = 0, .mask = BIT(1) },
+	{ .vin = 2, .csi = RVIN_CSI20, .chan = 0, .mask = BIT(2) },
+	{ .vin = 2, .csi = RVIN_CSI40, .chan = 2, .mask = BIT(3) },
+	{ .vin = 2, .csi = RVIN_CSI20, .chan = 2, .mask = BIT(4) },
+	{ .vin = 3, .csi = RVIN_CSI40, .chan = 1, .mask = BIT(0) },
+	{ .vin = 3, .csi = RVIN_CSI20, .chan = 1, .mask = BIT(1) | BIT(2) },
+	{ .vin = 3, .csi = RVIN_CSI40, .chan = 3, .mask = BIT(3) },
+	{ .vin = 3, .csi = RVIN_CSI20, .chan = 3, .mask = BIT(4) },
+	{ .vin = 4, .csi = RVIN_CSI41, .chan = 0, .mask = BIT(0) | BIT(3) },
+	{ .vin = 4, .csi = RVIN_CSI20, .chan = 0, .mask = BIT(1) | BIT(4) },
+	{ .vin = 4, .csi = RVIN_CSI41, .chan = 1, .mask = BIT(2) },
+	{ .vin = 5, .csi = RVIN_CSI20, .chan = 0, .mask = BIT(0) },
+	{ .vin = 5, .csi = RVIN_CSI41, .chan = 1, .mask = BIT(1) | BIT(3) },
+	{ .vin = 5, .csi = RVIN_CSI41, .chan = 0, .mask = BIT(2) },
+	{ .vin = 5, .csi = RVIN_CSI20, .chan = 1, .mask = BIT(4) },
+	{ .vin = 6, .csi = RVIN_CSI20, .chan = 1, .mask = BIT(0) },
+	{ .vin = 6, .csi = RVIN_CSI41, .chan = 0, .mask = BIT(1) },
+	{ .vin = 6, .csi = RVIN_CSI20, .chan = 0, .mask = BIT(2) },
+	{ .vin = 6, .csi = RVIN_CSI41, .chan = 2, .mask = BIT(3) },
+	{ .vin = 6, .csi = RVIN_CSI20, .chan = 2, .mask = BIT(4) },
+	{ .vin = 7, .csi = RVIN_CSI41, .chan = 1, .mask = BIT(0) },
+	{ .vin = 7, .csi = RVIN_CSI20, .chan = 1, .mask = BIT(1) | BIT(2) },
+	{ .vin = 7, .csi = RVIN_CSI41, .chan = 3, .mask = BIT(3) },
+	{ .vin = 7, .csi = RVIN_CSI20, .chan = 3, .mask = BIT(4) },
+	{ /* Sentinel */ }
+};
+
+static const struct rvin_info rcar_info_r8a7795 = {
+	.model = RCAR_GEN3,
+	.use_mc = true,
+	.max_width = 4096,
+	.max_height = 4096,
+	.routes = rcar_info_r8a7795_routes,
+};
+
+static const struct rvin_group_route rcar_info_r8a7795es1_routes[] = {
+	{ .vin = 0, .csi = RVIN_CSI40, .chan = 0, .mask = BIT(0) | BIT(3) },
+	{ .vin = 0, .csi = RVIN_CSI20, .chan = 0, .mask = BIT(1) | BIT(4) },
+	{ .vin = 0, .csi = RVIN_CSI21, .chan = 0, .mask = BIT(2) | BIT(5) },
+	{ .vin = 1, .csi = RVIN_CSI20, .chan = 0, .mask = BIT(0) },
+	{ .vin = 1, .csi = RVIN_CSI21, .chan = 0, .mask = BIT(1) },
+	{ .vin = 1, .csi = RVIN_CSI40, .chan = 0, .mask = BIT(2) },
+	{ .vin = 1, .csi = RVIN_CSI40, .chan = 1, .mask = BIT(3) },
+	{ .vin = 1, .csi = RVIN_CSI20, .chan = 1, .mask = BIT(4) },
+	{ .vin = 1, .csi = RVIN_CSI21, .chan = 1, .mask = BIT(5) },
+	{ .vin = 2, .csi = RVIN_CSI21, .chan = 0, .mask = BIT(0) },
+	{ .vin = 2, .csi = RVIN_CSI40, .chan = 0, .mask = BIT(1) },
+	{ .vin = 2, .csi = RVIN_CSI20, .chan = 0, .mask = BIT(2) },
+	{ .vin = 2, .csi = RVIN_CSI40, .chan = 2, .mask = BIT(3) },
+	{ .vin = 2, .csi = RVIN_CSI20, .chan = 2, .mask = BIT(4) },
+	{ .vin = 2, .csi = RVIN_CSI21, .chan = 2, .mask = BIT(5) },
+	{ .vin = 3, .csi = RVIN_CSI40, .chan = 1, .mask = BIT(0) },
+	{ .vin = 3, .csi = RVIN_CSI20, .chan = 1, .mask = BIT(1) },
+	{ .vin = 3, .csi = RVIN_CSI21, .chan = 1, .mask = BIT(2) },
+	{ .vin = 3, .csi = RVIN_CSI40, .chan = 3, .mask = BIT(3) },
+	{ .vin = 3, .csi = RVIN_CSI20, .chan = 3, .mask = BIT(4) },
+	{ .vin = 3, .csi = RVIN_CSI21, .chan = 3, .mask = BIT(5) },
+	{ .vin = 4, .csi = RVIN_CSI41, .chan = 0, .mask = BIT(0) | BIT(3) },
+	{ .vin = 4, .csi = RVIN_CSI20, .chan = 0, .mask = BIT(1) | BIT(4) },
+	{ .vin = 4, .csi = RVIN_CSI21, .chan = 0, .mask = BIT(2) | BIT(5) },
+	{ .vin = 5, .csi = RVIN_CSI20, .chan = 0, .mask = BIT(0) },
+	{ .vin = 5, .csi = RVIN_CSI21, .chan = 0, .mask = BIT(1) },
+	{ .vin = 5, .csi = RVIN_CSI41, .chan = 0, .mask = BIT(2) },
+	{ .vin = 5, .csi = RVIN_CSI41, .chan = 1, .mask = BIT(3) },
+	{ .vin = 5, .csi = RVIN_CSI20, .chan = 1, .mask = BIT(4) },
+	{ .vin = 5, .csi = RVIN_CSI21, .chan = 1, .mask = BIT(5) },
+	{ .vin = 6, .csi = RVIN_CSI21, .chan = 0, .mask = BIT(0) },
+	{ .vin = 6, .csi = RVIN_CSI41, .chan = 0, .mask = BIT(1) },
+	{ .vin = 6, .csi = RVIN_CSI20, .chan = 0, .mask = BIT(2) },
+	{ .vin = 6, .csi = RVIN_CSI41, .chan = 2, .mask = BIT(3) },
+	{ .vin = 6, .csi = RVIN_CSI20, .chan = 2, .mask = BIT(4) },
+	{ .vin = 6, .csi = RVIN_CSI21, .chan = 2, .mask = BIT(5) },
+	{ .vin = 7, .csi = RVIN_CSI41, .chan = 1, .mask = BIT(0) },
+	{ .vin = 7, .csi = RVIN_CSI20, .chan = 1, .mask = BIT(1) },
+	{ .vin = 7, .csi = RVIN_CSI21, .chan = 1, .mask = BIT(2) },
+	{ .vin = 7, .csi = RVIN_CSI41, .chan = 3, .mask = BIT(3) },
+	{ .vin = 7, .csi = RVIN_CSI20, .chan = 3, .mask = BIT(4) },
+	{ .vin = 7, .csi = RVIN_CSI21, .chan = 3, .mask = BIT(5) },
+	{ /* Sentinel */ }
+};
+
+static const struct rvin_info rcar_info_r8a7795es1 = {
+	.model = RCAR_GEN3,
+	.use_mc = true,
+	.max_width = 4096,
+	.max_height = 4096,
+	.routes = rcar_info_r8a7795es1_routes,
+};
+
 static const struct of_device_id rvin_of_id_table[] = {
 	{
 		.compatible = "renesas,vin-r8a7778",
@@ -844,12 +943,25 @@ static const struct of_device_id rvin_of_id_table[] = {
 		.compatible = "renesas,rcar-gen2-vin",
 		.data = &rcar_info_gen2,
 	},
+	{
+		.compatible = "renesas,vin-r8a7795",
+		.data = &rcar_info_r8a7795,
+	},
 	{ /* Sentinel */ },
 };
 MODULE_DEVICE_TABLE(of, rvin_of_id_table);
 
+static const struct soc_device_attribute r8a7795es1[] = {
+	{
+		.soc_id = "r8a7795", .revision = "ES1.*",
+		.data = &rcar_info_r8a7795es1,
+	},
+	{ /* Sentinel */ }
+};
+
 static int rcar_vin_probe(struct platform_device *pdev)
 {
+	const struct soc_device_attribute *attr;
 	struct rvin_dev *vin;
 	struct resource *mem;
 	int irq, ret;
@@ -861,6 +973,14 @@ static int rcar_vin_probe(struct platform_device *pdev)
 	vin->dev = &pdev->dev;
 	vin->info = of_device_get_match_data(&pdev->dev);
 
+	/*
+	 * Special care is needed on r8a7795 ES1.x since it
+	 * uses different routing than r8a7795 ES2.0.
+	 */
+	attr = soc_device_match(r8a7795es1);
+	if (attr)
+		vin->info = attr->data;
+
 	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (mem == NULL)
 		return -EINVAL;
-- 
2.16.1

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v10 29/30] rcar-vin: enable support for r8a7796
  2018-01-29 16:34 [PATCH v10 00/30] rcar-vin: Add Gen3 with media controller Niklas Söderlund
                   ` (27 preceding siblings ...)
  2018-01-29 16:34 ` [PATCH v10 28/30] rcar-vin: enable support for r8a7795 Niklas Söderlund
@ 2018-01-29 16:34 ` Niklas Söderlund
  2018-02-13 21:54   ` Laurent Pinchart
  2018-01-29 16:34 ` [PATCH v10 30/30] rcar-vin: enable support for r8a77970 Niklas Söderlund
  29 siblings, 1 reply; 65+ messages in thread
From: Niklas Söderlund @ 2018-01-29 16:34 UTC (permalink / raw)
  To: Laurent Pinchart, Hans Verkuil, linux-media
  Cc: linux-renesas-soc, tomoharu.fukawa.eb, Kieran Bingham,
	Niklas Söderlund

Add the SoC specific information for Renesas r8a7796.

Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
---
 drivers/media/platform/rcar-vin/rcar-core.c | 44 +++++++++++++++++++++++++++++
 1 file changed, 44 insertions(+)

diff --git a/drivers/media/platform/rcar-vin/rcar-core.c b/drivers/media/platform/rcar-vin/rcar-core.c
index 43d2fa83875817f0..2305fedd293db241 100644
--- a/drivers/media/platform/rcar-vin/rcar-core.c
+++ b/drivers/media/platform/rcar-vin/rcar-core.c
@@ -914,6 +914,46 @@ static const struct rvin_info rcar_info_r8a7795es1 = {
 	.routes = rcar_info_r8a7795es1_routes,
 };
 
+static const struct rvin_group_route rcar_info_r8a7796_routes[] = {
+	{ .vin = 0, .csi = RVIN_CSI40, .chan = 0, .mask = BIT(0) | BIT(3) },
+	{ .vin = 0, .csi = RVIN_CSI20, .chan = 0, .mask = BIT(1) | BIT(4) },
+	{ .vin = 1, .csi = RVIN_CSI20, .chan = 0, .mask = BIT(0) },
+	{ .vin = 1, .csi = RVIN_CSI40, .chan = 0, .mask = BIT(2) },
+	{ .vin = 1, .csi = RVIN_CSI40, .chan = 1, .mask = BIT(3) },
+	{ .vin = 1, .csi = RVIN_CSI20, .chan = 1, .mask = BIT(4) },
+	{ .vin = 2, .csi = RVIN_CSI40, .chan = 0, .mask = BIT(1) },
+	{ .vin = 2, .csi = RVIN_CSI20, .chan = 0, .mask = BIT(2) },
+	{ .vin = 2, .csi = RVIN_CSI40, .chan = 2, .mask = BIT(3) },
+	{ .vin = 2, .csi = RVIN_CSI20, .chan = 2, .mask = BIT(4) },
+	{ .vin = 3, .csi = RVIN_CSI40, .chan = 1, .mask = BIT(0) },
+	{ .vin = 3, .csi = RVIN_CSI20, .chan = 1, .mask = BIT(1) },
+	{ .vin = 3, .csi = RVIN_CSI40, .chan = 3, .mask = BIT(3) },
+	{ .vin = 3, .csi = RVIN_CSI20, .chan = 3, .mask = BIT(4) },
+	{ .vin = 4, .csi = RVIN_CSI40, .chan = 0, .mask = BIT(0) | BIT(3) },
+	{ .vin = 4, .csi = RVIN_CSI20, .chan = 0, .mask = BIT(1) | BIT(4) },
+	{ .vin = 5, .csi = RVIN_CSI20, .chan = 0, .mask = BIT(0) },
+	{ .vin = 5, .csi = RVIN_CSI40, .chan = 0, .mask = BIT(2) },
+	{ .vin = 5, .csi = RVIN_CSI40, .chan = 1, .mask = BIT(3) },
+	{ .vin = 5, .csi = RVIN_CSI20, .chan = 1, .mask = BIT(4) },
+	{ .vin = 6, .csi = RVIN_CSI40, .chan = 0, .mask = BIT(1) },
+	{ .vin = 6, .csi = RVIN_CSI20, .chan = 0, .mask = BIT(2) },
+	{ .vin = 6, .csi = RVIN_CSI40, .chan = 2, .mask = BIT(3) },
+	{ .vin = 6, .csi = RVIN_CSI20, .chan = 2, .mask = BIT(4) },
+	{ .vin = 7, .csi = RVIN_CSI40, .chan = 1, .mask = BIT(0) },
+	{ .vin = 7, .csi = RVIN_CSI20, .chan = 1, .mask = BIT(1) },
+	{ .vin = 7, .csi = RVIN_CSI40, .chan = 3, .mask = BIT(3) },
+	{ .vin = 7, .csi = RVIN_CSI20, .chan = 3, .mask = BIT(4) },
+	{ /* Sentinel */ }
+};
+
+static const struct rvin_info rcar_info_r8a7796 = {
+	.model = RCAR_GEN3,
+	.use_mc = true,
+	.max_width = 4096,
+	.max_height = 4096,
+	.routes = rcar_info_r8a7796_routes,
+};
+
 static const struct of_device_id rvin_of_id_table[] = {
 	{
 		.compatible = "renesas,vin-r8a7778",
@@ -947,6 +987,10 @@ static const struct of_device_id rvin_of_id_table[] = {
 		.compatible = "renesas,vin-r8a7795",
 		.data = &rcar_info_r8a7795,
 	},
+	{
+		.compatible = "renesas,vin-r8a7796",
+		.data = &rcar_info_r8a7796,
+	},
 	{ /* Sentinel */ },
 };
 MODULE_DEVICE_TABLE(of, rvin_of_id_table);
-- 
2.16.1

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v10 30/30] rcar-vin: enable support for r8a77970
  2018-01-29 16:34 [PATCH v10 00/30] rcar-vin: Add Gen3 with media controller Niklas Söderlund
                   ` (28 preceding siblings ...)
  2018-01-29 16:34 ` [PATCH v10 29/30] rcar-vin: enable support for r8a7796 Niklas Söderlund
@ 2018-01-29 16:34 ` Niklas Söderlund
  2018-02-13 21:56   ` Laurent Pinchart
  29 siblings, 1 reply; 65+ messages in thread
From: Niklas Söderlund @ 2018-01-29 16:34 UTC (permalink / raw)
  To: Laurent Pinchart, Hans Verkuil, linux-media
  Cc: linux-renesas-soc, tomoharu.fukawa.eb, Kieran Bingham,
	Niklas Söderlund

Add the SoC specific information for Renesas r8a77970.

Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
---
 drivers/media/platform/rcar-vin/rcar-core.c | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/drivers/media/platform/rcar-vin/rcar-core.c b/drivers/media/platform/rcar-vin/rcar-core.c
index 2305fedd293db241..496b7d2189d73d37 100644
--- a/drivers/media/platform/rcar-vin/rcar-core.c
+++ b/drivers/media/platform/rcar-vin/rcar-core.c
@@ -954,6 +954,25 @@ static const struct rvin_info rcar_info_r8a7796 = {
 	.routes = rcar_info_r8a7796_routes,
 };
 
+static const struct rvin_group_route _rcar_info_r8a77970_routes[] = {
+	{ .vin = 0, .csi = RVIN_CSI40, .chan = 0, .mask = BIT(0) | BIT(3) },
+	{ .vin = 1, .csi = RVIN_CSI40, .chan = 0, .mask = BIT(2) },
+	{ .vin = 1, .csi = RVIN_CSI40, .chan = 1, .mask = BIT(3) },
+	{ .vin = 2, .csi = RVIN_CSI40, .chan = 0, .mask = BIT(1) },
+	{ .vin = 2, .csi = RVIN_CSI40, .chan = 2, .mask = BIT(3) },
+	{ .vin = 3, .csi = RVIN_CSI40, .chan = 1, .mask = BIT(0) },
+	{ .vin = 3, .csi = RVIN_CSI40, .chan = 3, .mask = BIT(3) },
+	{ /* Sentinel */ }
+};
+
+static const struct rvin_info rcar_info_r8a77970 = {
+	.model = RCAR_GEN3,
+	.use_mc = true,
+	.max_width = 4096,
+	.max_height = 4096,
+	.routes = _rcar_info_r8a77970_routes,
+};
+
 static const struct of_device_id rvin_of_id_table[] = {
 	{
 		.compatible = "renesas,vin-r8a7778",
@@ -991,6 +1010,10 @@ static const struct of_device_id rvin_of_id_table[] = {
 		.compatible = "renesas,vin-r8a7796",
 		.data = &rcar_info_r8a7796,
 	},
+	{
+		.compatible = "renesas,vin-r8a77970",
+		.data = &rcar_info_r8a77970,
+	},
 	{ /* Sentinel */ },
 };
 MODULE_DEVICE_TABLE(of, rvin_of_id_table);
-- 
2.16.1

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* Re: [PATCH v10 01/30] rcar-vin: add Gen3 devicetree bindings documentation
  2018-01-29 16:34 ` [PATCH v10 01/30] rcar-vin: add Gen3 devicetree bindings documentation Niklas Söderlund
@ 2018-02-13 15:24   ` Laurent Pinchart
  0 siblings, 0 replies; 65+ messages in thread
From: Laurent Pinchart @ 2018-02-13 15:24 UTC (permalink / raw)
  To: Niklas Söderlund
  Cc: Hans Verkuil, linux-media, linux-renesas-soc, tomoharu.fukawa.eb,
	Kieran Bingham

Hi Niklas,

Thank you for the patch.

On Monday, 29 January 2018 18:34:06 EET Niklas Söderlund wrote:
> Document the devicetree bindings for the CSI-2 inputs available on Gen3.
> 
> There is a need to add a custom property 'renesas,id' and to define
> which CSI-2 input is described in which endpoint under the port@1 node.
> This information is needed since there are a set of predefined routes
> between each VIN and CSI-2 block. This routing table will be kept
> inside the driver but in order for it to act on it it must know which
> VIN and CSI-2 is which.
> 
> Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
> Acked-by: Rob Herring <robh@kernel.org>

Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

> ---
>  .../devicetree/bindings/media/rcar_vin.txt         | 118 +++++++++++++++---
>  1 file changed, 106 insertions(+), 12 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/media/rcar_vin.txt
> b/Documentation/devicetree/bindings/media/rcar_vin.txt index
> c60e6b0a89b67a8c..90d92836284b7f68 100644
> --- a/Documentation/devicetree/bindings/media/rcar_vin.txt
> +++ b/Documentation/devicetree/bindings/media/rcar_vin.txt
> @@ -2,8 +2,12 @@ Renesas R-Car Video Input driver (rcar_vin)
>  -------------------------------------------
> 
>  The rcar_vin device provides video input capabilities for the Renesas R-Car
> -family of devices. The current blocks are always slaves and suppot one
> input -channel which can be either RGB, YUYV or BT656.
> +family of devices.
> +
> +Each VIN instance has a single parallel input that supports RGB and YUV
> video, +with both external synchronization and BT.656 synchronization for
> the latter. +Depending on the instance the VIN input is connected to
> external SoC pins, or +on Gen3 platforms to a CSI-2 receiver.
> 
>   - compatible: Must be one or more of the following
>     - "renesas,vin-r8a7743" for the R8A7743 device
> @@ -16,6 +20,8 @@ channel which can be either RGB, YUYV or BT656.
>     - "renesas,vin-r8a7793" for the R8A7793 device
>     - "renesas,vin-r8a7794" for the R8A7794 device
>     - "renesas,vin-r8a7795" for the R8A7795 device
> +   - "renesas,vin-r8a7796" for the R8A7796 device
> +   - "renesas,vin-r8a77970" for the R8A77970 device
>     - "renesas,rcar-gen2-vin" for a generic R-Car Gen2 or RZ/G1 compatible
>       device.
>     - "renesas,rcar-gen3-vin" for a generic R-Car Gen3 compatible device.
> @@ -31,21 +37,38 @@ channel which can be either RGB, YUYV or BT656.
>  Additionally, an alias named vinX will need to be created to specify
>  which video input device this is.
> 
> -The per-board settings:
> +The per-board settings Gen2 platforms:
>   - port sub-node describing a single endpoint connected to the vin
>     as described in video-interfaces.txt[1]. Only the first one will
>     be considered as each vin interface has one input port.
> 
> -   These settings are used to work out video input format and widths
> -   into the system.
> +The per-board settings Gen3 platforms:
> 
> +Gen3 platforms can support both a single connected parallel input source
> +from external SoC pins (port0) and/or multiple parallel input sources
> +from local SoC CSI-2 receivers (port1) depending on SoC.
> 
> -Device node example
> --------------------
> +- renesas,id - ID number of the VIN, VINx in the documentation.
> +- ports
> +    - port 0 - sub-node describing a single endpoint connected to the VIN
> +      from external SoC pins described in video-interfaces.txt[1].
> +      Describing more then one endpoint in port 0 is invalid. Only VIN
> +      instances that are connected to external pins should have port 0.
> +    - port 1 - sub-nodes describing one or more endpoints connected to
> +      the VIN from local SoC CSI-2 receivers. The endpoint numbers must
> +      use the following schema.
> 
> -	aliases {
> -	       vin0 = &vin0;
> -	};
> +        - Endpoint 0 - sub-node describing the endpoint connected to CSI20
> +        - Endpoint 1 - sub-node describing the endpoint connected to CSI21
> +        - Endpoint 2 - sub-node describing the endpoint connected to CSI40
> +        - Endpoint 3 - sub-node describing the endpoint connected to CSI41
> +
> +Device node example for Gen2 platforms
> +--------------------------------------
> +
> +        aliases {
> +                vin0 = &vin0;
> +        };
> 
>          vin0: vin@e6ef0000 {
>                  compatible = "renesas,vin-r8a7790",
> "renesas,rcar-gen2-vin"; @@ -55,8 +78,8 @@ Device node example
>                  status = "disabled";
>          };
> 
> -Board setup example (vin1 composite video input)
> -------------------------------------------------
> +Board setup example for Gen2 platforms (vin1 composite video input)
> +-------------------------------------------------------------------
> 
>  &i2c2   {
>          status = "ok";
> @@ -95,6 +118,77 @@ Board setup example (vin1 composite video input)
>          };
>  };
> 
> +Device node example for Gen3 platforms
> +--------------------------------------
> 
> +        vin0: video@e6ef0000 {
> +                compatible = "renesas,vin-r8a7795";
> +                reg = <0 0xe6ef0000 0 0x1000>;
> +                interrupts = <GIC_SPI 188 IRQ_TYPE_LEVEL_HIGH>;
> +                clocks = <&cpg CPG_MOD 811>;
> +                power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
> +                resets = <&cpg 811>;
> +                renesas,id = <0>;
> +
> +                ports {
> +                        #address-cells = <1>;
> +                        #size-cells = <0>;
> +
> +                        port@1 {
> +                                #address-cells = <1>;
> +                                #size-cells = <0>;
> +
> +                                reg = <1>;
> +
> +                                vin0csi20: endpoint@0 {
> +                                        reg = <0>;
> +                                        remote-endpoint= <&csi20vin0>;
> +                                };
> +                                vin0csi21: endpoint@1 {
> +                                        reg = <1>;
> +                                        remote-endpoint= <&csi21vin0>;
> +                                };
> +                                vin0csi40: endpoint@2 {
> +                                        reg = <2>;
> +                                        remote-endpoint= <&csi40vin0>;
> +                                };
> +                        };
> +                };
> +        };
> +
> +        csi20: csi2@fea80000 {
> +                compatible = "renesas,r8a7795-csi2";
> +                reg = <0 0xfea80000 0 0x10000>;
> +                interrupts = <GIC_SPI 184 IRQ_TYPE_LEVEL_HIGH>;
> +                clocks = <&cpg CPG_MOD 714>;
> +                power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
> +                resets = <&cpg 714>;
> +
> +                ports {
> +                        #address-cells = <1>;
> +                        #size-cells = <0>;
> +
> +                        port@0 {
> +                                reg = <0>;
> +                                csi20_in: endpoint {
> +                                        clock-lanes = <0>;
> +                                        data-lanes = <1>;
> +                                        remote-endpoint = <&adv7482_txb>;
> +                                };
> +                        };
> +
> +                        port@1 {
> +                                #address-cells = <1>;
> +                                #size-cells = <0>;
> +
> +                                reg = <1>;
> +
> +                                csi20vin0: endpoint@0 {
> +                                        reg = <0>;
> +                                        remote-endpoint = <&vin0csi20>;
> +                                };
> +                        };
> +                };
> +        };
> 
>  [1] video-interfaces.txt common video media interface


-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v10 04/30] rcar-vin: move subdevice handling to async callbacks
  2018-01-29 16:34 ` [PATCH v10 04/30] rcar-vin: move subdevice handling to async callbacks Niklas Söderlund
@ 2018-02-13 15:47   ` Laurent Pinchart
  0 siblings, 0 replies; 65+ messages in thread
From: Laurent Pinchart @ 2018-02-13 15:47 UTC (permalink / raw)
  To: Niklas Söderlund
  Cc: Hans Verkuil, linux-media, linux-renesas-soc, tomoharu.fukawa.eb,
	Kieran Bingham

Hi Niklas,

Thank you for the patch.

On Monday, 29 January 2018 18:34:09 EET Niklas Söderlund wrote:
> In preparation for Gen3 support move the subdevice initialization and
> clean up from rvin_v4l2_{register,unregister}() directly to the async
> callbacks. This simplifies the addition of Gen3 support as the
> rvin_v4l2_register() can be shared for both Gen2 and Gen3 while direct
> subdevice control are only used on Gen2.
> 
> While moving this code drop a large comment which is copied from the
> framework documentation and fold rvin_mbus_supported() into its only
> caller. Also move the initialization and cleanup code to separate
> functions to increase readability.
> 
> Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>

Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

> ---
>  drivers/media/platform/rcar-vin/rcar-core.c | 108 ++++++++++++++++++------
>  drivers/media/platform/rcar-vin/rcar-v4l2.c |  35 ---------
>  2 files changed, 74 insertions(+), 69 deletions(-)
> 
> diff --git a/drivers/media/platform/rcar-vin/rcar-core.c
> b/drivers/media/platform/rcar-vin/rcar-core.c index
> 47f06acde2e698f2..663309ca9c04f208 100644
> --- a/drivers/media/platform/rcar-vin/rcar-core.c
> +++ b/drivers/media/platform/rcar-vin/rcar-core.c
> @@ -46,46 +46,88 @@ static int rvin_find_pad(struct v4l2_subdev *sd, int
> direction) return -EINVAL;
>  }
> 
> -static bool rvin_mbus_supported(struct rvin_graph_entity *entity)
> +/* The vin lock shuld be held when calling the subdevice attach and detach
> */ +static int rvin_digital_subdevice_attach(struct rvin_dev *vin,
> +					 struct v4l2_subdev *subdev)
>  {
> -	struct v4l2_subdev *sd = entity->subdev;
>  	struct v4l2_subdev_mbus_code_enum code = {
>  		.which = V4L2_SUBDEV_FORMAT_ACTIVE,
>  	};
> +	int ret;
> 
> +	/* Find source and sink pad of remote subdevice */
> +	ret = rvin_find_pad(subdev, MEDIA_PAD_FL_SOURCE);
> +	if (ret < 0)
> +		return ret;
> +	vin->digital->source_pad = ret;
> +
> +	ret = rvin_find_pad(subdev, MEDIA_PAD_FL_SINK);
> +	vin->digital->sink_pad = ret < 0 ? 0 : ret;
> +
> +	/* Find compatible subdevices mbus format */
> +	vin->digital->code = 0;
>  	code.index = 0;
> -	code.pad = entity->source_pad;
> -	while (!v4l2_subdev_call(sd, pad, enum_mbus_code, NULL, &code)) {
> +	code.pad = vin->digital->source_pad;
> +	while (!vin->digital->code &&
> +	       !v4l2_subdev_call(subdev, pad, enum_mbus_code, NULL, &code)) {
>  		code.index++;
>  		switch (code.code) {
>  		case MEDIA_BUS_FMT_YUYV8_1X16:
>  		case MEDIA_BUS_FMT_UYVY8_2X8:
>  		case MEDIA_BUS_FMT_UYVY10_2X10:
>  		case MEDIA_BUS_FMT_RGB888_1X24:
> -			entity->code = code.code;
> -			return true;
> +			vin->digital->code = code.code;
> +			vin_dbg(vin, "Found media bus format for %s: %d\n",
> +				subdev->name, vin->digital->code);
> +			break;
>  		default:
>  			break;
>  		}
>  	}
> 
> -	return false;
> -}
> -
> -static int rvin_digital_notify_complete(struct v4l2_async_notifier
> *notifier) -{
> -	struct rvin_dev *vin = notifier_to_vin(notifier);
> -	int ret;
> -
> -	/* Verify subdevices mbus format */
> -	if (!rvin_mbus_supported(vin->digital)) {
> +	if (!vin->digital->code) {
>  		vin_err(vin, "Unsupported media bus format for %s\n",
> -			vin->digital->subdev->name);
> +			subdev->name);
>  		return -EINVAL;
>  	}
> 
> -	vin_dbg(vin, "Found media bus format for %s: %d\n",
> -		vin->digital->subdev->name, vin->digital->code);
> +	/* Read tvnorms */
> +	ret = v4l2_subdev_call(subdev, video, g_tvnorms, &vin->vdev.tvnorms);
> +	if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV)
> +		return ret;
> +
> +	/* Add the controls */
> +	ret = v4l2_ctrl_handler_init(&vin->ctrl_handler, 16);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = v4l2_ctrl_add_handler(&vin->ctrl_handler, subdev->ctrl_handler,
> +				    NULL);
> +	if (ret < 0) {
> +		v4l2_ctrl_handler_free(&vin->ctrl_handler);
> +		return ret;
> +	}
> +
> +	vin->vdev.ctrl_handler = &vin->ctrl_handler;
> +
> +	vin->digital->subdev = subdev;
> +
> +	return 0;
> +}
> +
> +static void rvin_digital_subdevice_detach(struct rvin_dev *vin)
> +{
> +	rvin_v4l2_unregister(vin);
> +	v4l2_ctrl_handler_free(&vin->ctrl_handler);
> +
> +	vin->vdev.ctrl_handler = NULL;
> +	vin->digital->subdev = NULL;
> +}
> +
> +static int rvin_digital_notify_complete(struct v4l2_async_notifier
> *notifier) +{
> +	struct rvin_dev *vin = notifier_to_vin(notifier);
> +	int ret;
> 
>  	ret = v4l2_device_register_subdev_nodes(&vin->v4l2_dev);
>  	if (ret < 0) {
> @@ -103,8 +145,10 @@ static void rvin_digital_notify_unbind(struct
> v4l2_async_notifier *notifier, struct rvin_dev *vin =
> notifier_to_vin(notifier);
> 
>  	vin_dbg(vin, "unbind digital subdev %s\n", subdev->name);
> -	rvin_v4l2_unregister(vin);
> -	vin->digital->subdev = NULL;
> +
> +	mutex_lock(&vin->lock);
> +	rvin_digital_subdevice_detach(vin);
> +	mutex_unlock(&vin->lock);
>  }
> 
>  static int rvin_digital_notify_bound(struct v4l2_async_notifier *notifier,
> @@ -114,33 +158,27 @@ static int rvin_digital_notify_bound(struct
> v4l2_async_notifier *notifier, struct rvin_dev *vin =
> notifier_to_vin(notifier);
>  	int ret;
> 
> +	mutex_lock(&vin->lock);
> +	ret = rvin_digital_subdevice_attach(vin, subdev);
> +	mutex_unlock(&vin->lock);
> +	if (ret)
> +		return ret;
> +
>  	v4l2_set_subdev_hostdata(subdev, vin);
> 
> -	/* Find source and sink pad of remote subdevice */
> -
> -	ret = rvin_find_pad(subdev, MEDIA_PAD_FL_SOURCE);
> -	if (ret < 0)
> -		return ret;
> -	vin->digital->source_pad = ret;
> -
> -	ret = rvin_find_pad(subdev, MEDIA_PAD_FL_SINK);
> -	vin->digital->sink_pad = ret < 0 ? 0 : ret;
> -
> -	vin->digital->subdev = subdev;
> -
>  	vin_dbg(vin, "bound subdev %s source pad: %u sink pad: %u\n",
>  		subdev->name, vin->digital->source_pad,
>  		vin->digital->sink_pad);
> 
>  	return 0;
>  }
> +
>  static const struct v4l2_async_notifier_operations rvin_digital_notify_ops
> = { .bound = rvin_digital_notify_bound,
>  	.unbind = rvin_digital_notify_unbind,
>  	.complete = rvin_digital_notify_complete,
>  };
> 
> -
>  static int rvin_digital_parse_v4l2(struct device *dev,
>  				   struct v4l2_fwnode_endpoint *vep,
>  				   struct v4l2_async_subdev *asd)
> @@ -277,6 +315,8 @@ static int rcar_vin_remove(struct platform_device *pdev)
> v4l2_async_notifier_unregister(&vin->notifier);
>  	v4l2_async_notifier_cleanup(&vin->notifier);
> 
> +	v4l2_ctrl_handler_free(&vin->ctrl_handler);
> +
>  	rvin_dma_unregister(vin);
> 
>  	return 0;
> diff --git a/drivers/media/platform/rcar-vin/rcar-v4l2.c
> b/drivers/media/platform/rcar-vin/rcar-v4l2.c index
> 32a658214f48fa49..4a0610a6b4503501 100644
> --- a/drivers/media/platform/rcar-vin/rcar-v4l2.c
> +++ b/drivers/media/platform/rcar-vin/rcar-v4l2.c
> @@ -847,9 +847,6 @@ void rvin_v4l2_unregister(struct rvin_dev *vin)
>  	v4l2_info(&vin->v4l2_dev, "Removing %s\n",
>  		  video_device_node_name(&vin->vdev));
> 
> -	/* Checks internaly if handlers have been init or not */
> -	v4l2_ctrl_handler_free(&vin->ctrl_handler);
> -
>  	/* Checks internaly if vdev have been init or not */
>  	video_unregister_device(&vin->vdev);
>  }
> @@ -872,41 +869,10 @@ static void rvin_notify(struct v4l2_subdev *sd,
>  int rvin_v4l2_register(struct rvin_dev *vin)
>  {
>  	struct video_device *vdev = &vin->vdev;
> -	struct v4l2_subdev *sd = vin_to_source(vin);
>  	int ret;
> 
> -	v4l2_set_subdev_hostdata(sd, vin);
> -
>  	vin->v4l2_dev.notify = rvin_notify;
> 
> -	ret = v4l2_subdev_call(sd, video, g_tvnorms, &vin->vdev.tvnorms);
> -	if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV)
> -		return ret;
> -
> -	if (vin->vdev.tvnorms == 0) {
> -		/* Disable the STD API if there are no tvnorms defined */
> -		v4l2_disable_ioctl(&vin->vdev, VIDIOC_G_STD);
> -		v4l2_disable_ioctl(&vin->vdev, VIDIOC_S_STD);
> -		v4l2_disable_ioctl(&vin->vdev, VIDIOC_QUERYSTD);
> -		v4l2_disable_ioctl(&vin->vdev, VIDIOC_ENUMSTD);
> -	}
> -
> -	/* Add the controls */
> -	/*
> -	 * Currently the subdev with the largest number of controls (13) is
> -	 * ov6550. So let's pick 16 as a hint for the control handler. Note
> -	 * that this is a hint only: too large and you waste some memory, too
> -	 * small and there is a (very) small performance hit when looking up
> -	 * controls in the internal hash.
> -	 */
> -	ret = v4l2_ctrl_handler_init(&vin->ctrl_handler, 16);
> -	if (ret < 0)
> -		return ret;
> -
> -	ret = v4l2_ctrl_add_handler(&vin->ctrl_handler, sd->ctrl_handler, NULL);
> -	if (ret < 0)
> -		return ret;
> -
>  	/* video node */
>  	vdev->fops = &rvin_fops;
>  	vdev->v4l2_dev = &vin->v4l2_dev;
> @@ -915,7 +881,6 @@ int rvin_v4l2_register(struct rvin_dev *vin)
>  	vdev->release = video_device_release_empty;
>  	vdev->ioctl_ops = &rvin_ioctl_ops;
>  	vdev->lock = &vin->lock;
> -	vdev->ctrl_handler = &vin->ctrl_handler;
>  	vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING |
>  		V4L2_CAP_READWRITE;


-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v10 09/30] rcar-vin: read subdevice format for crop only when needed
  2018-01-29 16:34 ` [PATCH v10 09/30] rcar-vin: read subdevice format for crop only when needed Niklas Söderlund
@ 2018-02-13 16:14   ` Laurent Pinchart
  0 siblings, 0 replies; 65+ messages in thread
From: Laurent Pinchart @ 2018-02-13 16:14 UTC (permalink / raw)
  To: Niklas Söderlund
  Cc: Hans Verkuil, linux-media, linux-renesas-soc, tomoharu.fukawa.eb,
	Kieran Bingham

Hi Niklas,

Thank you for the patch.

On Monday, 29 January 2018 18:34:14 EET Niklas Söderlund wrote:
> Instead of caching the subdevice format each time the video device
> format is set read it directly when it's needed. As it turns out the
> format is only needed when figuring out the max rectangle for cropping.
> 
> This simplifies the code and makes it clearer what the source format is
> used for.
> 
> Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
> ---
>  drivers/media/platform/rcar-vin/rcar-v4l2.c | 112 +++++++++++++-----------
>  drivers/media/platform/rcar-vin/rcar-vin.h  |  12 ---
>  2 files changed, 61 insertions(+), 63 deletions(-)
> 
> diff --git a/drivers/media/platform/rcar-vin/rcar-v4l2.c
> b/drivers/media/platform/rcar-vin/rcar-v4l2.c index
> c2265324c7c96308..4d5be2d0c79c9c9a 100644
> --- a/drivers/media/platform/rcar-vin/rcar-v4l2.c
> +++ b/drivers/media/platform/rcar-vin/rcar-v4l2.c
> @@ -90,35 +90,54 @@ static u32 rvin_format_sizeimage(struct v4l2_pix_format
> *pix) * V4L2
>   */
> 
> -static void rvin_reset_crop_compose(struct rvin_dev *vin)
> +static int rvin_get_source_format(struct rvin_dev *vin,
> +				  struct v4l2_mbus_framefmt *mbus_fmt)
>  {
> +	struct v4l2_subdev_format fmt = {
> +		.which = V4L2_SUBDEV_FORMAT_ACTIVE,
> +		.pad = vin->digital->source_pad,
> +	};
> +	int ret;
> +
> +	ret = v4l2_subdev_call(vin_to_source(vin), pad, get_fmt, NULL, &fmt);
> +	if (ret)
> +		return ret;
> +
> +	memcpy(mbus_fmt, &fmt.format, sizeof(*mbus_fmt));

You can use

	*mbus_fmt = fmt.format;

That way the compiler will catch more mistakes, for instance incompatible 
types between the two arguments.

> +
> +	return 0;
> +}
> +
> +static int rvin_reset_crop_compose(struct rvin_dev *vin)
> +{
> +	struct v4l2_mbus_framefmt source_fmt;
> +	int ret;
> +
> +	ret = rvin_get_source_format(vin, &source_fmt);
> +	if (ret)
> +		return ret;
> +
>  	vin->crop.top = vin->crop.left = 0;
> -	vin->crop.width = vin->source.width;
> -	vin->crop.height = vin->source.height;
> +	vin->crop.width = source_fmt.width;
> +	vin->crop.height = source_fmt.height;
> 
>  	vin->compose.top = vin->compose.left = 0;
>  	vin->compose.width = vin->format.width;
>  	vin->compose.height = vin->format.height;
> +
> +	return 0;
>  }
> 
>  static int rvin_reset_format(struct rvin_dev *vin)
>  {
> -	struct v4l2_subdev_format fmt = {
> -		.which = V4L2_SUBDEV_FORMAT_ACTIVE,
> -	};
> -	struct v4l2_mbus_framefmt *mf = &fmt.format;
> +	struct v4l2_mbus_framefmt source_fmt;
>  	int ret;
> 
> -	fmt.pad = vin->digital->source_pad;
> -
> -	ret = v4l2_subdev_call(vin_to_source(vin), pad, get_fmt, NULL, &fmt);
> +	ret = rvin_get_source_format(vin, &source_fmt);
>  	if (ret)
>  		return ret;

You retrieve the source format once here...

> -	vin->format.width	= mf->width;
> -	vin->format.height	= mf->height;
> -	vin->format.colorspace	= mf->colorspace;
> -	vin->format.field	= mf->field;
> +	v4l2_fill_pix_format(&vin->format, &source_fmt);
> 
>  	/*
>  	 * If the subdevice uses ALTERNATE field mode and G_STD is
> @@ -147,7 +166,9 @@ static int rvin_reset_format(struct rvin_dev *vin)
>  		break;
>  	}
> 
> -	rvin_reset_crop_compose(vin);
> +	ret = rvin_reset_crop_compose(vin);

... and this function then retrieves it a second time. Can't you pass it to 
rvin_reset_crop_compose() ? If the source changes its format autonomously 
between the two calls you'll end up with an inconsistent result otherwise.

> +	if (ret)
> +		return ret;
> 
>  	vin->format.bytesperline = rvin_format_bytesperline(&vin->format);
>  	vin->format.sizeimage = rvin_format_sizeimage(&vin->format);
> @@ -156,9 +177,7 @@ static int rvin_reset_format(struct rvin_dev *vin)
>  }
> 
>  static int __rvin_try_format_source(struct rvin_dev *vin,
> -				    u32 which,
> -				    struct v4l2_pix_format *pix,
> -				    struct rvin_source_fmt *source)
> +				    u32 which, struct v4l2_pix_format *pix)
>  {
>  	struct v4l2_subdev *sd;
>  	struct v4l2_subdev_pad_config *pad_cfg;
> @@ -190,25 +209,16 @@ static int __rvin_try_format_source(struct rvin_dev
> *vin,
> 
>  	v4l2_fill_pix_format(pix, &format.format);
> 
> -	source->width = pix->width;
> -	source->height = pix->height;
> -
>  	pix->field = field;
>  	pix->width = width;
>  	pix->height = height;
> -
> -	vin_dbg(vin, "Source resolution: %ux%u\n", source->width,
> -		source->height);
> -
>  done:
>  	v4l2_subdev_free_pad_config(pad_cfg);
>  	return ret;
>  }
> 
>  static int __rvin_try_format(struct rvin_dev *vin,
> -			     u32 which,
> -			     struct v4l2_pix_format *pix,
> -			     struct rvin_source_fmt *source)
> +			     u32 which, struct v4l2_pix_format *pix)
>  {
>  	u32 walign;
>  	int ret;
> @@ -229,7 +239,7 @@ static int __rvin_try_format(struct rvin_dev *vin,
>  	pix->sizeimage = 0;
> 
>  	/* Limit to source capabilities */
> -	ret = __rvin_try_format_source(vin, which, pix, source);
> +	ret = __rvin_try_format_source(vin, which, pix);
>  	if (ret)
>  		return ret;
> 
> @@ -238,7 +248,6 @@ static int __rvin_try_format(struct rvin_dev *vin,
>  	case V4L2_FIELD_BOTTOM:
>  	case V4L2_FIELD_ALTERNATE:
>  		pix->height /= 2;
> -		source->height /= 2;
>  		break;
>  	case V4L2_FIELD_NONE:
>  	case V4L2_FIELD_INTERLACED_TB:
> @@ -290,35 +299,26 @@ static int rvin_try_fmt_vid_cap(struct file *file,
> void *priv, struct v4l2_format *f)
>  {
>  	struct rvin_dev *vin = video_drvdata(file);
> -	struct rvin_source_fmt source;
> 
> -	return __rvin_try_format(vin, V4L2_SUBDEV_FORMAT_TRY, &f->fmt.pix,
> -				 &source);
> +	return __rvin_try_format(vin, V4L2_SUBDEV_FORMAT_TRY, &f->fmt.pix);
>  }
> 
>  static int rvin_s_fmt_vid_cap(struct file *file, void *priv,
>  			      struct v4l2_format *f)
>  {
>  	struct rvin_dev *vin = video_drvdata(file);
> -	struct rvin_source_fmt source;
>  	int ret;
> 
>  	if (vb2_is_busy(&vin->queue))
>  		return -EBUSY;
> 
> -	ret = __rvin_try_format(vin, V4L2_SUBDEV_FORMAT_ACTIVE, &f->fmt.pix,
> -				&source);
> +	ret = __rvin_try_format(vin, V4L2_SUBDEV_FORMAT_ACTIVE, &f->fmt.pix);
>  	if (ret)
>  		return ret;
> 
> -	vin->source.width = source.width;
> -	vin->source.height = source.height;
> -
>  	vin->format = f->fmt.pix;
> 
> -	rvin_reset_crop_compose(vin);
> -
> -	return 0;
> +	return rvin_reset_crop_compose(vin);

Same here, I think you should pass the format that has been retrieved by 
__rvin_try_format().

If you want to get rid of the rvin_source_fmt structure (and I think we 
should) then I wouldn't mind if you used v4l2_rect. Another option would be to 
propose a v4l2_size, but that would be one additional dependency.

>  }
> 
>  static int rvin_g_fmt_vid_cap(struct file *file, void *priv,
> @@ -346,6 +346,8 @@ static int rvin_g_selection(struct file *file, void *fh,
> struct v4l2_selection *s)
>  {
>  	struct rvin_dev *vin = video_drvdata(file);
> +	struct v4l2_mbus_framefmt source_fmt;
> +	int ret;
> 
>  	if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
>  		return -EINVAL;
> @@ -353,9 +355,12 @@ static int rvin_g_selection(struct file *file, void
> *fh, switch (s->target) {
>  	case V4L2_SEL_TGT_CROP_BOUNDS:
>  	case V4L2_SEL_TGT_CROP_DEFAULT:
> +		ret = rvin_get_source_format(vin, &source_fmt);
> +		if (ret)
> +			return ret;
>  		s->r.left = s->r.top = 0;
> -		s->r.width = vin->source.width;
> -		s->r.height = vin->source.height;
> +		s->r.width = source_fmt.width;
> +		s->r.height = source_fmt.height;
>  		break;
>  	case V4L2_SEL_TGT_CROP:
>  		s->r = vin->crop;
> @@ -380,6 +385,7 @@ static int rvin_s_selection(struct file *file, void *fh,
> struct v4l2_selection *s)
>  {
>  	struct rvin_dev *vin = video_drvdata(file);
> +	struct v4l2_mbus_framefmt source_fmt;
>  	const struct rvin_video_format *fmt;
>  	struct v4l2_rect r = s->r;
>  	struct v4l2_rect max_rect;
> @@ -387,6 +393,7 @@ static int rvin_s_selection(struct file *file, void *fh,
> .width = 6,
>  		.height = 2,
>  	};
> +	int ret;
> 
>  	if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
>  		return -EINVAL;
> @@ -396,22 +403,25 @@ static int rvin_s_selection(struct file *file, void
> *fh, switch (s->target) {
>  	case V4L2_SEL_TGT_CROP:
>  		/* Can't crop outside of source input */
> +		ret = rvin_get_source_format(vin, &source_fmt);
> +		if (ret)
> +			return ret;

If you stop caching the source format you'll end up validating the crop 
rectangle against the current source format. What will happen if the format 
changed since the last VIDIOC_S_FMT call ?

And thinking about it, are sources allowed to change their format autonomously 
? They surely can detect format changes, but can they update the format 
without notifying anyone ? Looking at the adv7180 driver for instance, the 
format depends on the TV standard, but the driver doesn't change it. It only 
reports newly detected standards and relies on someone then calling the s_std 
operation.

>  		max_rect.top = max_rect.left = 0;
> -		max_rect.width = vin->source.width;
> -		max_rect.height = vin->source.height;
> +		max_rect.width = source_fmt.width;
> +		max_rect.height = source_fmt.height;
>  		v4l2_rect_map_inside(&r, &max_rect);
> 
> -		v4l_bound_align_image(&r.width, 2, vin->source.width, 1,
> -				      &r.height, 4, vin->source.height, 2, 0);
> +		v4l_bound_align_image(&r.width, 2, source_fmt.width, 1,
> +				      &r.height, 4, source_fmt.height, 2, 0);
> 
> -		r.top  = clamp_t(s32, r.top, 0, vin->source.height - r.height);
> -		r.left = clamp_t(s32, r.left, 0, vin->source.width - r.width);
> +		r.top  = clamp_t(s32, r.top, 0, source_fmt.height - r.height);
> +		r.left = clamp_t(s32, r.left, 0, source_fmt.width - r.width);
> 
>  		vin->crop = s->r = r;
> 
>  		vin_dbg(vin, "Cropped %dx%d@%d:%d of %dx%d\n",
>  			r.width, r.height, r.left, r.top,
> -			vin->source.width, vin->source.height);
> +			source_fmt.width, source_fmt.height);
>  		break;
>  	case V4L2_SEL_TGT_COMPOSE:
>  		/* Make sure compose rect fits inside output format */
> diff --git a/drivers/media/platform/rcar-vin/rcar-vin.h
> b/drivers/media/platform/rcar-vin/rcar-vin.h index
> 8daba9db0e927a49..39051da31650bd79 100644
> --- a/drivers/media/platform/rcar-vin/rcar-vin.h
> +++ b/drivers/media/platform/rcar-vin/rcar-vin.h
> @@ -48,16 +48,6 @@ enum rvin_dma_state {
>  	STOPPING,
>  };
> 
> -/**
> - * struct rvin_source_fmt - Source information
> - * @width:	Width from source
> - * @height:	Height from source
> - */
> -struct rvin_source_fmt {
> -	u32 width;
> -	u32 height;
> -};
> -
>  /**
>   * struct rvin_video_format - Data format stored in memory
>   * @fourcc:	Pixelformat
> @@ -124,7 +114,6 @@ struct rvin_info {
>   * @sequence:		V4L2 buffers sequence number
>   * @state:		keeps track of operation state
>   *
> - * @source:		active format from the video source
>   * @format:		active V4L2 pixel format
>   *
>   * @crop:		active cropping
> @@ -151,7 +140,6 @@ struct rvin_dev {
>  	unsigned int sequence;
>  	enum rvin_dma_state state;
> 
> -	struct rvin_source_fmt source;
>  	struct v4l2_pix_format format;
> 
>  	struct v4l2_rect crop;

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v10 10/30] rcar-vin: fix handling of single field frames (top, bottom and alternate fields)
  2018-01-29 16:34 ` [PATCH v10 10/30] rcar-vin: fix handling of single field frames (top, bottom and alternate fields) Niklas Söderlund
@ 2018-02-13 16:26   ` Laurent Pinchart
  2018-02-13 16:47       ` Niklas Söderlund
  0 siblings, 1 reply; 65+ messages in thread
From: Laurent Pinchart @ 2018-02-13 16:26 UTC (permalink / raw)
  To: Niklas Söderlund
  Cc: Hans Verkuil, linux-media, linux-renesas-soc, tomoharu.fukawa.eb,
	Kieran Bingham

Hi Niklas,

Thank you for the patch.

On Monday, 29 January 2018 18:34:15 EET Niklas Söderlund wrote:
> There was never proper support in the VIN driver to deliver ALTERNATING
> field format to user-space, remove this field option. The problem is
> that ALTERNATING filed order requires the sequence numbers of buffers
> returned to userspace to reflect if fields where dropped or not,
> something which is not possible with the VIN drivers capture logic.
> 
> The VIN driver can still capture from a video source which delivers
> frames in ALTERNATING field order, but needs to combine them using the
> VIN hardware into INTERLACED field order. Before this change if a source
> was delivering fields using ALTERNATE the driver would default to
> combining them using this hardware feature. Only if the user explicitly
> requested ALTERNATE filed order would incorrect frames be delivered.
> 
> The height should not be cut in half for the format for TOP or BOTTOM
> fields settings. This was a mistake and it was made visible by the
> scaling refactoring. Correct behavior is that the user should request a
> frame size that fits the half height frame reflected in the field
> setting. If not the VIN will do its best to scale the top or bottom to
> the requested format and cropping and scaling do not work as expected.
> 
> Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
> Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
> ---
>  drivers/media/platform/rcar-vin/rcar-dma.c  | 15 +-------
>  drivers/media/platform/rcar-vin/rcar-v4l2.c | 53 ++++++++++++--------------
>  2 files changed, 24 insertions(+), 44 deletions(-)
> 
> diff --git a/drivers/media/platform/rcar-vin/rcar-dma.c
> b/drivers/media/platform/rcar-vin/rcar-dma.c index
> fd14be20a6604d7a..c8831e189d362c8b 100644
> --- a/drivers/media/platform/rcar-vin/rcar-dma.c
> +++ b/drivers/media/platform/rcar-vin/rcar-dma.c
> @@ -617,7 +617,6 @@ static int rvin_setup(struct rvin_dev *vin)
>  	case V4L2_FIELD_INTERLACED_BT:
>  		vnmc = VNMC_IM_FULL | VNMC_FOC;
>  		break;
> -	case V4L2_FIELD_ALTERNATE:
>  	case V4L2_FIELD_NONE:
>  		if (vin->continuous) {
>  			vnmc = VNMC_IM_ODD_EVEN;
> @@ -757,18 +756,6 @@ static int rvin_get_active_slot(struct rvin_dev *vin,
> u32 vnms) return 0;
>  }
> 
> -static enum v4l2_field rvin_get_active_field(struct rvin_dev *vin, u32
> vnms)
> -{
> -	if (vin->format.field == V4L2_FIELD_ALTERNATE) {
> -		/* If FS is set it's a Even field */
> -		if (vnms & VNMS_FS)
> -			return V4L2_FIELD_BOTTOM;
> -		return V4L2_FIELD_TOP;
> -	}
> -
> -	return vin->format.field;
> -}
> -
>  static void rvin_set_slot_addr(struct rvin_dev *vin, int slot, dma_addr_t
> addr) {
>  	const struct rvin_video_format *fmt;
> @@ -941,7 +928,7 @@ static irqreturn_t rvin_irq(int irq, void *data)
>  		goto done;
> 
>  	/* Capture frame */
> -	vin->queue_buf[slot]->field = rvin_get_active_field(vin, vnms);
> +	vin->queue_buf[slot]->field = vin->format.field;
>  	vin->queue_buf[slot]->sequence = sequence;
>  	vin->queue_buf[slot]->vb2_buf.timestamp = ktime_get_ns();
>  	vb2_buffer_done(&vin->queue_buf[slot]->vb2_buf, VB2_BUF_STATE_DONE);
> diff --git a/drivers/media/platform/rcar-vin/rcar-v4l2.c
> b/drivers/media/platform/rcar-vin/rcar-v4l2.c index
> 4d5be2d0c79c9c9a..9f7902d29c62e205 100644
> --- a/drivers/media/platform/rcar-vin/rcar-v4l2.c
> +++ b/drivers/media/platform/rcar-vin/rcar-v4l2.c
> @@ -103,6 +103,28 @@ static int rvin_get_source_format(struct rvin_dev *vin,
> if (ret)
>  		return ret;
> 
> +	switch (fmt.format.field) {
> +	case V4L2_FIELD_TOP:
> +	case V4L2_FIELD_BOTTOM:
> +	case V4L2_FIELD_NONE:
> +	case V4L2_FIELD_INTERLACED_TB:
> +	case V4L2_FIELD_INTERLACED_BT:
> +	case V4L2_FIELD_INTERLACED:
> +		break;
> +	case V4L2_FIELD_ALTERNATE:
> +		/*
> +		 * Driver do not (yet) support outputting ALTERNATE to a
> +		 * userspace. It dose support outputting INTERLACED so use

s/dose/does/

> +		 * the VIN hardware to combine the two fields.
> +		 */
> +		fmt.format.field = V4L2_FIELD_INTERLACED;
> +		fmt.format.height *= 2;
> +		break;

I don't like this much. The rvin_get_source_format() function is supposed to 
return the media bus format for the bus between the source and the VIN. It's 
the caller that should take the field limitations into account, otherwise you 
end up with a mix of source and VIN data in the same structure.

> +	default:
> +		vin->format.field = V4L2_FIELD_NONE;
> +		break;
> +	}
> +
>  	memcpy(mbus_fmt, &fmt.format, sizeof(*mbus_fmt));
> 
>  	return 0;
> @@ -139,33 +161,6 @@ static int rvin_reset_format(struct rvin_dev *vin)
> 
>  	v4l2_fill_pix_format(&vin->format, &source_fmt);
> 
> -	/*
> -	 * If the subdevice uses ALTERNATE field mode and G_STD is
> -	 * implemented use the VIN HW to combine the two fields to
> -	 * one INTERLACED frame. The ALTERNATE field mode can still
> -	 * be requested in S_FMT and be respected, this is just the
> -	 * default which is applied at probing or when S_STD is called.
> -	 */
> -	if (vin->format.field == V4L2_FIELD_ALTERNATE &&
> -	    v4l2_subdev_has_op(vin_to_source(vin), video, g_std))
> -		vin->format.field = V4L2_FIELD_INTERLACED;
> -
> -	switch (vin->format.field) {
> -	case V4L2_FIELD_TOP:
> -	case V4L2_FIELD_BOTTOM:
> -	case V4L2_FIELD_ALTERNATE:
> -		vin->format.height /= 2;
> -		break;
> -	case V4L2_FIELD_NONE:
> -	case V4L2_FIELD_INTERLACED_TB:
> -	case V4L2_FIELD_INTERLACED_BT:
> -	case V4L2_FIELD_INTERLACED:
> -		break;
> -	default:
> -		vin->format.field = V4L2_FIELD_NONE;
> -		break;
> -	}
> -
>  	ret = rvin_reset_crop_compose(vin);
>  	if (ret)
>  		return ret;
> @@ -243,12 +238,10 @@ static int __rvin_try_format(struct rvin_dev *vin,
>  	if (ret)
>  		return ret;
> 
> +	/* Reject ALTERNATE  until support is added to the driver */
>  	switch (pix->field) {
>  	case V4L2_FIELD_TOP:
>  	case V4L2_FIELD_BOTTOM:
> -	case V4L2_FIELD_ALTERNATE:
> -		pix->height /= 2;
> -		break;
>  	case V4L2_FIELD_NONE:
>  	case V4L2_FIELD_INTERLACED_TB:
>  	case V4L2_FIELD_INTERLACED_BT:

You will then set the field to V4L2_FIELD_NONE, but the source will still 
provide V4L2_FIELD_ALTERNATE. What will happen in the VIN, what will it 
produce ?

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v10 11/30] rcar-vin: move media bus configuration to struct rvin_info
  2018-01-29 16:34 ` [PATCH v10 11/30] rcar-vin: move media bus configuration to struct rvin_info Niklas Söderlund
@ 2018-02-13 16:37   ` Laurent Pinchart
  0 siblings, 0 replies; 65+ messages in thread
From: Laurent Pinchart @ 2018-02-13 16:37 UTC (permalink / raw)
  To: Niklas Söderlund
  Cc: Hans Verkuil, linux-media, linux-renesas-soc, tomoharu.fukawa.eb,
	Kieran Bingham

Hi Niklas,

Thank you for the patch.

On Monday, 29 January 2018 18:34:16 EET Niklas Söderlund wrote:
> Bus configuration will once the driver is extended to support Gen3
> contain information not specific to only the directly connected parallel
> subdevice. Move it to struct rvin_dev to show it's not always coupled
> to the parallel subdevice.

The subject line still mentions rvin_info instead of rvin_dev.

> Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
> Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
> ---
>  drivers/media/platform/rcar-vin/rcar-core.c | 18 +++++++++---------
>  drivers/media/platform/rcar-vin/rcar-dma.c  | 11 ++++++-----
>  drivers/media/platform/rcar-vin/rcar-v4l2.c |  2 +-
>  drivers/media/platform/rcar-vin/rcar-vin.h  |  9 ++++-----
>  4 files changed, 20 insertions(+), 20 deletions(-)
> 
> diff --git a/drivers/media/platform/rcar-vin/rcar-core.c
> b/drivers/media/platform/rcar-vin/rcar-core.c index
> cc863e4ec9a4d4b3..ce1c90405c6002eb 100644
> --- a/drivers/media/platform/rcar-vin/rcar-core.c
> +++ b/drivers/media/platform/rcar-vin/rcar-core.c
> @@ -65,10 +65,10 @@ static int rvin_digital_subdevice_attach(struct rvin_dev
> *vin, vin->digital->sink_pad = ret < 0 ? 0 : ret;
> 
>  	/* Find compatible subdevices mbus format */
> -	vin->digital->code = 0;
> +	vin->code = 0;
>  	code.index = 0;
>  	code.pad = vin->digital->source_pad;
> -	while (!vin->digital->code &&
> +	while (!vin->code &&
>  	       !v4l2_subdev_call(subdev, pad, enum_mbus_code, NULL, &code)) {
>  		code.index++;
>  		switch (code.code) {
> @@ -76,16 +76,16 @@ static int rvin_digital_subdevice_attach(struct rvin_dev
> *vin, case MEDIA_BUS_FMT_UYVY8_2X8:
>  		case MEDIA_BUS_FMT_UYVY10_2X10:
>  		case MEDIA_BUS_FMT_RGB888_1X24:
> -			vin->digital->code = code.code;
> +			vin->code = code.code;
>  			vin_dbg(vin, "Found media bus format for %s: %d\n",
> -				subdev->name, vin->digital->code);
> +				subdev->name, vin->code);
>  			break;
>  		default:
>  			break;
>  		}
>  	}
> 
> -	if (!vin->digital->code) {
> +	if (!vin->code) {
>  		vin_err(vin, "Unsupported media bus format for %s\n",
>  			subdev->name);
>  		return -EINVAL;
> @@ -190,16 +190,16 @@ static int rvin_digital_parse_v4l2(struct device *dev,
> if (vep->base.port || vep->base.id)
>  		return -ENOTCONN;
> 
> -	rvge->mbus_cfg.type = vep->bus_type;
> +	vin->mbus_cfg.type = vep->bus_type;
> 
> -	switch (rvge->mbus_cfg.type) {
> +	switch (vin->mbus_cfg.type) {
>  	case V4L2_MBUS_PARALLEL:
>  		vin_dbg(vin, "Found PARALLEL media bus\n");
> -		rvge->mbus_cfg.flags = vep->bus.parallel.flags;
> +		vin->mbus_cfg.flags = vep->bus.parallel.flags;
>  		break;
>  	case V4L2_MBUS_BT656:
>  		vin_dbg(vin, "Found BT656 media bus\n");
> -		rvge->mbus_cfg.flags = 0;
> +		vin->mbus_cfg.flags = 0;
>  		break;
>  	default:
>  		vin_err(vin, "Unknown media bus type\n");
> diff --git a/drivers/media/platform/rcar-vin/rcar-dma.c
> b/drivers/media/platform/rcar-vin/rcar-dma.c index
> c8831e189d362c8b..561500f65cfa2e74 100644
> --- a/drivers/media/platform/rcar-vin/rcar-dma.c
> +++ b/drivers/media/platform/rcar-vin/rcar-dma.c
> @@ -633,7 +633,7 @@ static int rvin_setup(struct rvin_dev *vin)
>  	/*
>  	 * Input interface
>  	 */
> -	switch (vin->digital->code) {
> +	switch (vin->code) {
>  	case MEDIA_BUS_FMT_YUYV8_1X16:
>  		/* BT.601/BT.1358 16bit YCbCr422 */
>  		vnmc |= VNMC_INF_YUV16;
> @@ -641,7 +641,7 @@ static int rvin_setup(struct rvin_dev *vin)
>  		break;
>  	case MEDIA_BUS_FMT_UYVY8_2X8:
>  		/* BT.656 8bit YCbCr422 or BT.601 8bit YCbCr422 */
> -		vnmc |= vin->digital->mbus_cfg.type == V4L2_MBUS_BT656 ?
> +		vnmc |= vin->mbus_cfg.type == V4L2_MBUS_BT656 ?
>  			VNMC_INF_YUV8_BT656 : VNMC_INF_YUV8_BT601;
>  		input_is_yuv = true;
>  		break;
> @@ -650,7 +650,7 @@ static int rvin_setup(struct rvin_dev *vin)
>  		break;
>  	case MEDIA_BUS_FMT_UYVY10_2X10:
>  		/* BT.656 10bit YCbCr422 or BT.601 10bit YCbCr422 */
> -		vnmc |= vin->digital->mbus_cfg.type == V4L2_MBUS_BT656 ?
> +		vnmc |= vin->mbus_cfg.type == V4L2_MBUS_BT656 ?
>  			VNMC_INF_YUV10_BT656 : VNMC_INF_YUV10_BT601;
>  		input_is_yuv = true;
>  		break;
> @@ -662,11 +662,11 @@ static int rvin_setup(struct rvin_dev *vin)
>  	dmr2 = VNDMR2_FTEV | VNDMR2_VLV(1);
> 
>  	/* Hsync Signal Polarity Select */
> -	if (!(vin->digital->mbus_cfg.flags & V4L2_MBUS_HSYNC_ACTIVE_LOW))
> +	if (!(vin->mbus_cfg.flags & V4L2_MBUS_HSYNC_ACTIVE_LOW))
>  		dmr2 |= VNDMR2_HPS;
> 
>  	/* Vsync Signal Polarity Select */
> -	if (!(vin->digital->mbus_cfg.flags & V4L2_MBUS_VSYNC_ACTIVE_LOW))
> +	if (!(vin->mbus_cfg.flags & V4L2_MBUS_VSYNC_ACTIVE_LOW))
>  		dmr2 |= VNDMR2_VPS;
> 
>  	/*
> @@ -875,6 +875,7 @@ static void rvin_capture_stop(struct rvin_dev *vin)
>  	rvin_write(vin, rvin_read(vin, VNMC_REG) & ~VNMC_ME, VNMC_REG);
>  }
> 
> +
>  /*
> ---------------------------------------------------------------------------
> -- * DMA Functions
>   */
> diff --git a/drivers/media/platform/rcar-vin/rcar-v4l2.c
> b/drivers/media/platform/rcar-vin/rcar-v4l2.c index
> 9f7902d29c62e205..c606942e59b5d934 100644
> --- a/drivers/media/platform/rcar-vin/rcar-v4l2.c
> +++ b/drivers/media/platform/rcar-vin/rcar-v4l2.c
> @@ -185,7 +185,7 @@ static int __rvin_try_format_source(struct rvin_dev
> *vin,
> 
>  	sd = vin_to_source(vin);
> 
> -	v4l2_fill_mbus_format(&format.format, pix, vin->digital->code);
> +	v4l2_fill_mbus_format(&format.format, pix, vin->code);
> 
>  	pad_cfg = v4l2_subdev_alloc_pad_config(sd);
>  	if (pad_cfg == NULL)
> diff --git a/drivers/media/platform/rcar-vin/rcar-vin.h
> b/drivers/media/platform/rcar-vin/rcar-vin.h index
> 39051da31650bd79..b852e7f4fa3db017 100644
> --- a/drivers/media/platform/rcar-vin/rcar-vin.h
> +++ b/drivers/media/platform/rcar-vin/rcar-vin.h
> @@ -62,8 +62,6 @@ struct rvin_video_format {
>   * struct rvin_graph_entity - Video endpoint from async framework
>   * @asd:	sub-device descriptor for async framework
>   * @subdev:	subdevice matched using async framework
> - * @code:	Media bus format from source
> - * @mbus_cfg:	Media bus format from DT
>   * @source_pad:	source pad of remote subdevice
>   * @sink_pad:	sink pad of remote subdevice
>   */
> @@ -71,9 +69,6 @@ struct rvin_graph_entity {
>  	struct v4l2_async_subdev asd;
>  	struct v4l2_subdev *subdev;
> 
> -	u32 code;
> -	struct v4l2_mbus_config mbus_cfg;
> -
>  	unsigned int source_pad;
>  	unsigned int sink_pad;
>  };
> @@ -114,6 +109,8 @@ struct rvin_info {
>   * @sequence:		V4L2 buffers sequence number
>   * @state:		keeps track of operation state
>   *
> + * @mbus_cfg:		media bus configuration from DT
> + * @code:		media bus format code

In a global context those field names are confusing, especially the code 
field. It's not clear what code it refers to. Furthermore it's interesting how 
you dropped the cached source format in a previous patch, and now cache the 
source pixel code in the same structure :-)

>   * @format:		active V4L2 pixel format
>   *
>   * @crop:		active cropping
> @@ -140,6 +137,8 @@ struct rvin_dev {
>  	unsigned int sequence;
>  	enum rvin_dma_state state;
> 
> +	struct v4l2_mbus_config mbus_cfg;
> +	u32 code;
>  	struct v4l2_pix_format format;
> 
>  	struct v4l2_rect crop;

The pixel code and bus config are specific to a source, and yet you move them 
from rvin_graph_entity, which is source-specific, to rvin_dev, which is 
global. Am I missing something ?

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v10 13/30] rcar-vin: add function to manipulate Gen3 chsel value
  2018-01-29 16:34 ` [PATCH v10 13/30] rcar-vin: add function to manipulate Gen3 chsel value Niklas Söderlund
@ 2018-02-13 16:41   ` Laurent Pinchart
  2018-02-13 16:58       ` Niklas Söderlund
  0 siblings, 1 reply; 65+ messages in thread
From: Laurent Pinchart @ 2018-02-13 16:41 UTC (permalink / raw)
  To: Niklas Söderlund
  Cc: Hans Verkuil, linux-media, linux-renesas-soc, tomoharu.fukawa.eb,
	Kieran Bingham

Hi Niklas,

Thank you for the patch.

On Monday, 29 January 2018 18:34:18 EET Niklas Söderlund wrote:
> On Gen3 the CSI-2 routing is controlled by the VnCSI_IFMD register. One
> feature of this register is that it's only present in the VIN0 and VIN4
> instances. The register in VIN0 controls the routing for VIN0-3 and the
> register in VIN4 controls routing for VIN4-7.
> 
> To be able to control routing from a media device this function is need
> to control runtime PM for the subgroup master (VIN0 and VIN4). The
> subgroup master must be switched on before the register is manipulated,
> once the operation is complete it's safe to switch the master off and
> the new routing will still be in effect.
> 
> Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
> ---
>  drivers/media/platform/rcar-vin/rcar-dma.c | 28 +++++++++++++++++++++++++++
>  drivers/media/platform/rcar-vin/rcar-vin.h |  2 ++
>  2 files changed, 30 insertions(+)
> 
> diff --git a/drivers/media/platform/rcar-vin/rcar-dma.c
> b/drivers/media/platform/rcar-vin/rcar-dma.c index
> 2f9ad1bec1c8a92f..ae286742f15a3ab5 100644
> --- a/drivers/media/platform/rcar-vin/rcar-dma.c
> +++ b/drivers/media/platform/rcar-vin/rcar-dma.c
> @@ -16,6 +16,7 @@
> 
>  #include <linux/delay.h>
>  #include <linux/interrupt.h>
> +#include <linux/pm_runtime.h>
> 
>  #include <media/videobuf2-dma-contig.h>
> 
> @@ -1228,3 +1229,30 @@ int rvin_dma_register(struct rvin_dev *vin, int irq)
> 
>  	return ret;
>  }
> +
> +/* ------------------------------------------------------------------------
> + * Gen3 CHSEL manipulation
> + */
> +
> +void rvin_set_channel_routing(struct rvin_dev *vin, u8 chsel)
> +{
> +	u32 ifmd, vnmc;
> +
> +	pm_runtime_get_sync(vin->dev);

No need to check for errors ?

> +
> +	/* Make register writes take effect immediately */
> +	vnmc = rvin_read(vin, VNMC_REG);
> +	rvin_write(vin, vnmc & ~VNMC_VUP, VNMC_REG);
> +
> +	ifmd = VNCSI_IFMD_DES2 | VNCSI_IFMD_DES1 | VNCSI_IFMD_DES0 |
> +		VNCSI_IFMD_CSI_CHSEL(chsel);
> +
> +	rvin_write(vin, ifmd, VNCSI_IFMD_REG);
> +
> +	vin_dbg(vin, "Set IFMD 0x%x\n", ifmd);
> +
> +	/* Restore VNMC */
> +	rvin_write(vin, vnmc, VNMC_REG);

No need for locking around all this ? What happens if this VIN instance 
decides to write to another VIN register (for instance due to a userpace call) 
when this function has disabled VNMC_VUP ?

> +	pm_runtime_put(vin->dev);
> +}
> diff --git a/drivers/media/platform/rcar-vin/rcar-vin.h
> b/drivers/media/platform/rcar-vin/rcar-vin.h index
> 146683142e6533fa..a5dae5b5e9cb704b 100644
> --- a/drivers/media/platform/rcar-vin/rcar-vin.h
> +++ b/drivers/media/platform/rcar-vin/rcar-vin.h
> @@ -165,4 +165,6 @@ const struct rvin_video_format
> *rvin_format_from_pixel(u32 pixelformat); /* Cropping, composing and
> scaling */
>  void rvin_crop_scale_comp(struct rvin_dev *vin);
> 
> +void rvin_set_channel_routing(struct rvin_dev *vin, u8 chsel);
> +
>  #endif

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v10 10/30] rcar-vin: fix handling of single field frames (top, bottom and alternate fields)
  2018-02-13 16:26   ` Laurent Pinchart
@ 2018-02-13 16:47       ` Niklas Söderlund
  0 siblings, 0 replies; 65+ messages in thread
From: Niklas Söderlund @ 2018-02-13 16:47 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Hans Verkuil, linux-media, linux-renesas-soc, tomoharu.fukawa.eb,
	Kieran Bingham

Hi Laurent,

On 2018-02-13 18:26:34 +0200, Laurent Pinchart wrote:
> Hi Niklas,
> 
> Thank you for the patch.

Thanks for your comments.

> 
> On Monday, 29 January 2018 18:34:15 EET Niklas Söderlund wrote:
> > There was never proper support in the VIN driver to deliver ALTERNATING
> > field format to user-space, remove this field option. The problem is
> > that ALTERNATING filed order requires the sequence numbers of buffers
> > returned to userspace to reflect if fields where dropped or not,
> > something which is not possible with the VIN drivers capture logic.
> > 
> > The VIN driver can still capture from a video source which delivers
> > frames in ALTERNATING field order, but needs to combine them using the
> > VIN hardware into INTERLACED field order. Before this change if a source
> > was delivering fields using ALTERNATE the driver would default to
> > combining them using this hardware feature. Only if the user explicitly
> > requested ALTERNATE filed order would incorrect frames be delivered.
> > 
> > The height should not be cut in half for the format for TOP or BOTTOM
> > fields settings. This was a mistake and it was made visible by the
> > scaling refactoring. Correct behavior is that the user should request a
> > frame size that fits the half height frame reflected in the field
> > setting. If not the VIN will do its best to scale the top or bottom to
> > the requested format and cropping and scaling do not work as expected.
> > 
> > Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
> > Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
> > ---
> >  drivers/media/platform/rcar-vin/rcar-dma.c  | 15 +-------
> >  drivers/media/platform/rcar-vin/rcar-v4l2.c | 53 ++++++++++++--------------
> >  2 files changed, 24 insertions(+), 44 deletions(-)
> > 
> > diff --git a/drivers/media/platform/rcar-vin/rcar-dma.c
> > b/drivers/media/platform/rcar-vin/rcar-dma.c index
> > fd14be20a6604d7a..c8831e189d362c8b 100644
> > --- a/drivers/media/platform/rcar-vin/rcar-dma.c
> > +++ b/drivers/media/platform/rcar-vin/rcar-dma.c
> > @@ -617,7 +617,6 @@ static int rvin_setup(struct rvin_dev *vin)
> >  	case V4L2_FIELD_INTERLACED_BT:
> >  		vnmc = VNMC_IM_FULL | VNMC_FOC;
> >  		break;
> > -	case V4L2_FIELD_ALTERNATE:
> >  	case V4L2_FIELD_NONE:
> >  		if (vin->continuous) {
> >  			vnmc = VNMC_IM_ODD_EVEN;
> > @@ -757,18 +756,6 @@ static int rvin_get_active_slot(struct rvin_dev *vin,
> > u32 vnms) return 0;
> >  }
> > 
> > -static enum v4l2_field rvin_get_active_field(struct rvin_dev *vin, u32
> > vnms)
> > -{
> > -	if (vin->format.field == V4L2_FIELD_ALTERNATE) {
> > -		/* If FS is set it's a Even field */
> > -		if (vnms & VNMS_FS)
> > -			return V4L2_FIELD_BOTTOM;
> > -		return V4L2_FIELD_TOP;
> > -	}
> > -
> > -	return vin->format.field;
> > -}
> > -
> >  static void rvin_set_slot_addr(struct rvin_dev *vin, int slot, dma_addr_t
> > addr) {
> >  	const struct rvin_video_format *fmt;
> > @@ -941,7 +928,7 @@ static irqreturn_t rvin_irq(int irq, void *data)
> >  		goto done;
> > 
> >  	/* Capture frame */
> > -	vin->queue_buf[slot]->field = rvin_get_active_field(vin, vnms);
> > +	vin->queue_buf[slot]->field = vin->format.field;
> >  	vin->queue_buf[slot]->sequence = sequence;
> >  	vin->queue_buf[slot]->vb2_buf.timestamp = ktime_get_ns();
> >  	vb2_buffer_done(&vin->queue_buf[slot]->vb2_buf, VB2_BUF_STATE_DONE);
> > diff --git a/drivers/media/platform/rcar-vin/rcar-v4l2.c
> > b/drivers/media/platform/rcar-vin/rcar-v4l2.c index
> > 4d5be2d0c79c9c9a..9f7902d29c62e205 100644
> > --- a/drivers/media/platform/rcar-vin/rcar-v4l2.c
> > +++ b/drivers/media/platform/rcar-vin/rcar-v4l2.c
> > @@ -103,6 +103,28 @@ static int rvin_get_source_format(struct rvin_dev *vin,
> > if (ret)
> >  		return ret;
> > 
> > +	switch (fmt.format.field) {
> > +	case V4L2_FIELD_TOP:
> > +	case V4L2_FIELD_BOTTOM:
> > +	case V4L2_FIELD_NONE:
> > +	case V4L2_FIELD_INTERLACED_TB:
> > +	case V4L2_FIELD_INTERLACED_BT:
> > +	case V4L2_FIELD_INTERLACED:
> > +		break;
> > +	case V4L2_FIELD_ALTERNATE:
> > +		/*
> > +		 * Driver do not (yet) support outputting ALTERNATE to a
> > +		 * userspace. It dose support outputting INTERLACED so use
> 
> s/dose/does/
> 
> > +		 * the VIN hardware to combine the two fields.
> > +		 */
> > +		fmt.format.field = V4L2_FIELD_INTERLACED;
> > +		fmt.format.height *= 2;
> > +		break;
> 
> I don't like this much. The rvin_get_source_format() function is supposed to 
> return the media bus format for the bus between the source and the VIN. It's 
> the caller that should take the field limitations into account, otherwise you 
> end up with a mix of source and VIN data in the same structure.

When I read your comments I understand your argument better. And I 
understand this function is perhaps poorly named. Maybe it should be 
renamed to rvin_get_vin_format_from_source().

The source format is fetched at s_stream() time in order to do format 
validation. At this time the field is also taken into account once more 
to validate that the VIN format (calculated here) still is valid. It 
also handles the question you ask later at s_stream() time, see bellow.

> 
> > +	default:
> > +		vin->format.field = V4L2_FIELD_NONE;
> > +		break;
> > +	}
> > +
> >  	memcpy(mbus_fmt, &fmt.format, sizeof(*mbus_fmt));
> > 
> >  	return 0;
> > @@ -139,33 +161,6 @@ static int rvin_reset_format(struct rvin_dev *vin)
> > 
> >  	v4l2_fill_pix_format(&vin->format, &source_fmt);
> > 
> > -	/*
> > -	 * If the subdevice uses ALTERNATE field mode and G_STD is
> > -	 * implemented use the VIN HW to combine the two fields to
> > -	 * one INTERLACED frame. The ALTERNATE field mode can still
> > -	 * be requested in S_FMT and be respected, this is just the
> > -	 * default which is applied at probing or when S_STD is called.
> > -	 */
> > -	if (vin->format.field == V4L2_FIELD_ALTERNATE &&
> > -	    v4l2_subdev_has_op(vin_to_source(vin), video, g_std))
> > -		vin->format.field = V4L2_FIELD_INTERLACED;
> > -
> > -	switch (vin->format.field) {
> > -	case V4L2_FIELD_TOP:
> > -	case V4L2_FIELD_BOTTOM:
> > -	case V4L2_FIELD_ALTERNATE:
> > -		vin->format.height /= 2;
> > -		break;
> > -	case V4L2_FIELD_NONE:
> > -	case V4L2_FIELD_INTERLACED_TB:
> > -	case V4L2_FIELD_INTERLACED_BT:
> > -	case V4L2_FIELD_INTERLACED:
> > -		break;
> > -	default:
> > -		vin->format.field = V4L2_FIELD_NONE;
> > -		break;
> > -	}
> > -
> >  	ret = rvin_reset_crop_compose(vin);
> >  	if (ret)
> >  		return ret;
> > @@ -243,12 +238,10 @@ static int __rvin_try_format(struct rvin_dev *vin,
> >  	if (ret)
> >  		return ret;
> > 
> > +	/* Reject ALTERNATE  until support is added to the driver */
> >  	switch (pix->field) {
> >  	case V4L2_FIELD_TOP:
> >  	case V4L2_FIELD_BOTTOM:
> > -	case V4L2_FIELD_ALTERNATE:
> > -		pix->height /= 2;
> > -		break;
> >  	case V4L2_FIELD_NONE:
> >  	case V4L2_FIELD_INTERLACED_TB:
> >  	case V4L2_FIELD_INTERLACED_BT:
> 
> You will then set the field to V4L2_FIELD_NONE, but the source will still 
> provide V4L2_FIELD_ALTERNATE. What will happen in the VIN, what will it 
> produce ?

As stated above this is just the format produced from the VIN to 
user-space. The source field is validated at s_stream() time, if it is 
V4L2_FIELD_ALTERNATE the driver will handle it and possibly interlace it 
depending on how the user wants to consume it, which is what is 
specified here.

> 
> -- 
> Regards,
> 
> Laurent Pinchart
> 

-- 
Regards,
Niklas Söderlund

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v10 10/30] rcar-vin: fix handling of single field frames (top, bottom and alternate fields)
@ 2018-02-13 16:47       ` Niklas Söderlund
  0 siblings, 0 replies; 65+ messages in thread
From: Niklas Söderlund @ 2018-02-13 16:47 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Hans Verkuil, linux-media, linux-renesas-soc, tomoharu.fukawa.eb,
	Kieran Bingham

Hi Laurent,

On 2018-02-13 18:26:34 +0200, Laurent Pinchart wrote:
> Hi Niklas,
> 
> Thank you for the patch.

Thanks for your comments.

> 
> On Monday, 29 January 2018 18:34:15 EET Niklas S�derlund wrote:
> > There was never proper support in the VIN driver to deliver ALTERNATING
> > field format to user-space, remove this field option. The problem is
> > that ALTERNATING filed order requires the sequence numbers of buffers
> > returned to userspace to reflect if fields where dropped or not,
> > something which is not possible with the VIN drivers capture logic.
> > 
> > The VIN driver can still capture from a video source which delivers
> > frames in ALTERNATING field order, but needs to combine them using the
> > VIN hardware into INTERLACED field order. Before this change if a source
> > was delivering fields using ALTERNATE the driver would default to
> > combining them using this hardware feature. Only if the user explicitly
> > requested ALTERNATE filed order would incorrect frames be delivered.
> > 
> > The height should not be cut in half for the format for TOP or BOTTOM
> > fields settings. This was a mistake and it was made visible by the
> > scaling refactoring. Correct behavior is that the user should request a
> > frame size that fits the half height frame reflected in the field
> > setting. If not the VIN will do its best to scale the top or bottom to
> > the requested format and cropping and scaling do not work as expected.
> > 
> > Signed-off-by: Niklas S�derlund <niklas.soderlund+renesas@ragnatech.se>
> > Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
> > ---
> >  drivers/media/platform/rcar-vin/rcar-dma.c  | 15 +-------
> >  drivers/media/platform/rcar-vin/rcar-v4l2.c | 53 ++++++++++++--------------
> >  2 files changed, 24 insertions(+), 44 deletions(-)
> > 
> > diff --git a/drivers/media/platform/rcar-vin/rcar-dma.c
> > b/drivers/media/platform/rcar-vin/rcar-dma.c index
> > fd14be20a6604d7a..c8831e189d362c8b 100644
> > --- a/drivers/media/platform/rcar-vin/rcar-dma.c
> > +++ b/drivers/media/platform/rcar-vin/rcar-dma.c
> > @@ -617,7 +617,6 @@ static int rvin_setup(struct rvin_dev *vin)
> >  	case V4L2_FIELD_INTERLACED_BT:
> >  		vnmc = VNMC_IM_FULL | VNMC_FOC;
> >  		break;
> > -	case V4L2_FIELD_ALTERNATE:
> >  	case V4L2_FIELD_NONE:
> >  		if (vin->continuous) {
> >  			vnmc = VNMC_IM_ODD_EVEN;
> > @@ -757,18 +756,6 @@ static int rvin_get_active_slot(struct rvin_dev *vin,
> > u32 vnms) return 0;
> >  }
> > 
> > -static enum v4l2_field rvin_get_active_field(struct rvin_dev *vin, u32
> > vnms)
> > -{
> > -	if (vin->format.field == V4L2_FIELD_ALTERNATE) {
> > -		/* If FS is set it's a Even field */
> > -		if (vnms & VNMS_FS)
> > -			return V4L2_FIELD_BOTTOM;
> > -		return V4L2_FIELD_TOP;
> > -	}
> > -
> > -	return vin->format.field;
> > -}
> > -
> >  static void rvin_set_slot_addr(struct rvin_dev *vin, int slot, dma_addr_t
> > addr) {
> >  	const struct rvin_video_format *fmt;
> > @@ -941,7 +928,7 @@ static irqreturn_t rvin_irq(int irq, void *data)
> >  		goto done;
> > 
> >  	/* Capture frame */
> > -	vin->queue_buf[slot]->field = rvin_get_active_field(vin, vnms);
> > +	vin->queue_buf[slot]->field = vin->format.field;
> >  	vin->queue_buf[slot]->sequence = sequence;
> >  	vin->queue_buf[slot]->vb2_buf.timestamp = ktime_get_ns();
> >  	vb2_buffer_done(&vin->queue_buf[slot]->vb2_buf, VB2_BUF_STATE_DONE);
> > diff --git a/drivers/media/platform/rcar-vin/rcar-v4l2.c
> > b/drivers/media/platform/rcar-vin/rcar-v4l2.c index
> > 4d5be2d0c79c9c9a..9f7902d29c62e205 100644
> > --- a/drivers/media/platform/rcar-vin/rcar-v4l2.c
> > +++ b/drivers/media/platform/rcar-vin/rcar-v4l2.c
> > @@ -103,6 +103,28 @@ static int rvin_get_source_format(struct rvin_dev *vin,
> > if (ret)
> >  		return ret;
> > 
> > +	switch (fmt.format.field) {
> > +	case V4L2_FIELD_TOP:
> > +	case V4L2_FIELD_BOTTOM:
> > +	case V4L2_FIELD_NONE:
> > +	case V4L2_FIELD_INTERLACED_TB:
> > +	case V4L2_FIELD_INTERLACED_BT:
> > +	case V4L2_FIELD_INTERLACED:
> > +		break;
> > +	case V4L2_FIELD_ALTERNATE:
> > +		/*
> > +		 * Driver do not (yet) support outputting ALTERNATE to a
> > +		 * userspace. It dose support outputting INTERLACED so use
> 
> s/dose/does/
> 
> > +		 * the VIN hardware to combine the two fields.
> > +		 */
> > +		fmt.format.field = V4L2_FIELD_INTERLACED;
> > +		fmt.format.height *= 2;
> > +		break;
> 
> I don't like this much. The rvin_get_source_format() function is supposed to 
> return the media bus format for the bus between the source and the VIN. It's 
> the caller that should take the field limitations into account, otherwise you 
> end up with a mix of source and VIN data in the same structure.

When I read your comments I understand your argument better. And I 
understand this function is perhaps poorly named. Maybe it should be 
renamed to rvin_get_vin_format_from_source().

The source format is fetched at s_stream() time in order to do format 
validation. At this time the field is also taken into account once more 
to validate that the VIN format (calculated here) still is valid. It 
also handles the question you ask later at s_stream() time, see bellow.

> 
> > +	default:
> > +		vin->format.field = V4L2_FIELD_NONE;
> > +		break;
> > +	}
> > +
> >  	memcpy(mbus_fmt, &fmt.format, sizeof(*mbus_fmt));
> > 
> >  	return 0;
> > @@ -139,33 +161,6 @@ static int rvin_reset_format(struct rvin_dev *vin)
> > 
> >  	v4l2_fill_pix_format(&vin->format, &source_fmt);
> > 
> > -	/*
> > -	 * If the subdevice uses ALTERNATE field mode and G_STD is
> > -	 * implemented use the VIN HW to combine the two fields to
> > -	 * one INTERLACED frame. The ALTERNATE field mode can still
> > -	 * be requested in S_FMT and be respected, this is just the
> > -	 * default which is applied at probing or when S_STD is called.
> > -	 */
> > -	if (vin->format.field == V4L2_FIELD_ALTERNATE &&
> > -	    v4l2_subdev_has_op(vin_to_source(vin), video, g_std))
> > -		vin->format.field = V4L2_FIELD_INTERLACED;
> > -
> > -	switch (vin->format.field) {
> > -	case V4L2_FIELD_TOP:
> > -	case V4L2_FIELD_BOTTOM:
> > -	case V4L2_FIELD_ALTERNATE:
> > -		vin->format.height /= 2;
> > -		break;
> > -	case V4L2_FIELD_NONE:
> > -	case V4L2_FIELD_INTERLACED_TB:
> > -	case V4L2_FIELD_INTERLACED_BT:
> > -	case V4L2_FIELD_INTERLACED:
> > -		break;
> > -	default:
> > -		vin->format.field = V4L2_FIELD_NONE;
> > -		break;
> > -	}
> > -
> >  	ret = rvin_reset_crop_compose(vin);
> >  	if (ret)
> >  		return ret;
> > @@ -243,12 +238,10 @@ static int __rvin_try_format(struct rvin_dev *vin,
> >  	if (ret)
> >  		return ret;
> > 
> > +	/* Reject ALTERNATE  until support is added to the driver */
> >  	switch (pix->field) {
> >  	case V4L2_FIELD_TOP:
> >  	case V4L2_FIELD_BOTTOM:
> > -	case V4L2_FIELD_ALTERNATE:
> > -		pix->height /= 2;
> > -		break;
> >  	case V4L2_FIELD_NONE:
> >  	case V4L2_FIELD_INTERLACED_TB:
> >  	case V4L2_FIELD_INTERLACED_BT:
> 
> You will then set the field to V4L2_FIELD_NONE, but the source will still 
> provide V4L2_FIELD_ALTERNATE. What will happen in the VIN, what will it 
> produce ?

As stated above this is just the format produced from the VIN to 
user-space. The source field is validated at s_stream() time, if it is 
V4L2_FIELD_ALTERNATE the driver will handle it and possibly interlace it 
depending on how the user wants to consume it, which is what is 
specified here.

> 
> -- 
> Regards,
> 
> Laurent Pinchart
> 

-- 
Regards,
Niklas S�derlund

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v10 15/30] rcar-vin: break out format alignment and checking
  2018-01-29 16:34 ` [PATCH v10 15/30] rcar-vin: break out format alignment and checking Niklas Söderlund
@ 2018-02-13 16:56   ` Laurent Pinchart
  0 siblings, 0 replies; 65+ messages in thread
From: Laurent Pinchart @ 2018-02-13 16:56 UTC (permalink / raw)
  To: Niklas Söderlund
  Cc: Hans Verkuil, linux-media, linux-renesas-soc, tomoharu.fukawa.eb,
	Kieran Bingham

Hi Niklas,

Thank you for the patch.

On Monday, 29 January 2018 18:34:20 EET Niklas Söderlund wrote:
> Part of the format alignment and checking can be shared with the Gen3
> format handling. Break that part out to a separate function.
> 
> Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
> ---
>  drivers/media/platform/rcar-vin/rcar-v4l2.c | 93 +++++++++++++-----------
>  1 file changed, 50 insertions(+), 43 deletions(-)
> 
> diff --git a/drivers/media/platform/rcar-vin/rcar-v4l2.c
> b/drivers/media/platform/rcar-vin/rcar-v4l2.c index
> c606942e59b5d934..1169e6a279ecfb55 100644
> --- a/drivers/media/platform/rcar-vin/rcar-v4l2.c
> +++ b/drivers/media/platform/rcar-vin/rcar-v4l2.c
> @@ -86,6 +86,55 @@ static u32 rvin_format_sizeimage(struct v4l2_pix_format
> *pix) return pix->bytesperline * pix->height;
>  }
> 
> +static int rvin_format_align(struct rvin_dev *vin, struct v4l2_pix_format
> *pix)
> +{
> +	u32 walign;
> +
> +	/* If requested format is not supported fallback to the default */
> +	if (!rvin_format_from_pixel(pix->pixelformat)) {
> +		vin_dbg(vin, "Format 0x%x not found, using default 0x%x\n",
> +			pix->pixelformat, RVIN_DEFAULT_FORMAT);

I think you can drop the message.

> +		pix->pixelformat = RVIN_DEFAULT_FORMAT;
> +	}
> +
> +	/* Reject ALTERNATE  until support is added to the driver */
> +	switch (pix->field) {
> +	case V4L2_FIELD_TOP:
> +	case V4L2_FIELD_BOTTOM:
> +	case V4L2_FIELD_NONE:
> +	case V4L2_FIELD_INTERLACED_TB:
> +	case V4L2_FIELD_INTERLACED_BT:
> +	case V4L2_FIELD_INTERLACED:
> +		break;
> +	default:
> +		pix->field = V4L2_FIELD_NONE;
> +		break;
> +	}
> +
> +	/* HW limit width to a multiple of 32 (2^5) for NV16 else 2 (2^1) */
> +	walign = vin->format.pixelformat == V4L2_PIX_FMT_NV16 ? 5 : 1;
> +
> +	/* Limit to VIN capabilities */
> +	v4l_bound_align_image(&pix->width, 2, vin->info->max_width, walign,
> +			      &pix->height, 4, vin->info->max_height, 2, 0);
> +
> +	pix->bytesperline = max_t(u32, pix->bytesperline,
> +				  rvin_format_bytesperline(pix));
> +	pix->sizeimage = max_t(u32, pix->sizeimage,
> +			       rvin_format_sizeimage(pix));
> +
> +	if (vin->info->model == RCAR_M1 &&
> +	    pix->pixelformat == V4L2_PIX_FMT_XBGR32) {
> +		vin_err(vin, "pixel format XBGR32 not supported on M1\n");
> +		return -EINVAL;

This shouldn't print a message nor return an error, but default to a supported 
format. You can move the check to the beginning of the function to do so.

> +	}
> +
> +	vin_dbg(vin, "Format %ux%u bpl: %d size: %d\n",
> +		pix->width, pix->height, pix->bytesperline, pix->sizeimage);
> +
> +	return 0;
> +}
> +
>  /*
> ---------------------------------------------------------------------------
> -- * V4L2
>   */
> @@ -215,19 +264,12 @@ static int __rvin_try_format_source(struct rvin_dev
> *vin, static int __rvin_try_format(struct rvin_dev *vin,
>  			     u32 which, struct v4l2_pix_format *pix)
>  {
> -	u32 walign;
>  	int ret;
> 
>  	/* Keep current field if no specific one is asked for */
>  	if (pix->field == V4L2_FIELD_ANY)
>  		pix->field = vin->format.field;
> 
> -	/* If requested format is not supported fallback to the default */
> -	if (!rvin_format_from_pixel(pix->pixelformat)) {
> -		vin_dbg(vin, "Format 0x%x not found, using default 0x%x\n",
> -			pix->pixelformat, RVIN_DEFAULT_FORMAT);
> -		pix->pixelformat = RVIN_DEFAULT_FORMAT;
> -	}
> 
>  	/* Always recalculate */
>  	pix->bytesperline = 0;
> @@ -238,42 +280,7 @@ static int __rvin_try_format(struct rvin_dev *vin,
>  	if (ret)
>  		return ret;
> 
> -	/* Reject ALTERNATE  until support is added to the driver */
> -	switch (pix->field) {
> -	case V4L2_FIELD_TOP:
> -	case V4L2_FIELD_BOTTOM:
> -	case V4L2_FIELD_NONE:
> -	case V4L2_FIELD_INTERLACED_TB:
> -	case V4L2_FIELD_INTERLACED_BT:
> -	case V4L2_FIELD_INTERLACED:
> -		break;
> -	default:
> -		pix->field = V4L2_FIELD_NONE;
> -		break;
> -	}
> -
> -	/* HW limit width to a multiple of 32 (2^5) for NV16 else 2 (2^1) */
> -	walign = vin->format.pixelformat == V4L2_PIX_FMT_NV16 ? 5 : 1;
> -
> -	/* Limit to VIN capabilities */
> -	v4l_bound_align_image(&pix->width, 2, vin->info->max_width, walign,
> -			      &pix->height, 4, vin->info->max_height, 2, 0);
> -
> -	pix->bytesperline = max_t(u32, pix->bytesperline,
> -				  rvin_format_bytesperline(pix));
> -	pix->sizeimage = max_t(u32, pix->sizeimage,
> -			       rvin_format_sizeimage(pix));
> -
> -	if (vin->info->model == RCAR_M1 &&
> -	    pix->pixelformat == V4L2_PIX_FMT_XBGR32) {
> -		vin_err(vin, "pixel format XBGR32 not supported on M1\n");
> -		return -EINVAL;
> -	}
> -
> -	vin_dbg(vin, "Format %ux%u bpl: %d size: %d\n",
> -		pix->width, pix->height, pix->bytesperline, pix->sizeimage);
> -
> -	return 0;
> +	return rvin_format_align(vin, pix);
>  }
> 
>  static int rvin_querycap(struct file *file, void *priv,

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v10 13/30] rcar-vin: add function to manipulate Gen3 chsel value
  2018-02-13 16:41   ` Laurent Pinchart
@ 2018-02-13 16:58       ` Niklas Söderlund
  0 siblings, 0 replies; 65+ messages in thread
From: Niklas Söderlund @ 2018-02-13 16:58 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Hans Verkuil, linux-media, linux-renesas-soc, tomoharu.fukawa.eb,
	Kieran Bingham

Hi Laurent,

On 2018-02-13 18:41:33 +0200, Laurent Pinchart wrote:
> Hi Niklas,
> 
> Thank you for the patch.
> 
> On Monday, 29 January 2018 18:34:18 EET Niklas Söderlund wrote:
> > On Gen3 the CSI-2 routing is controlled by the VnCSI_IFMD register. One
> > feature of this register is that it's only present in the VIN0 and VIN4
> > instances. The register in VIN0 controls the routing for VIN0-3 and the
> > register in VIN4 controls routing for VIN4-7.
> > 
> > To be able to control routing from a media device this function is need
> > to control runtime PM for the subgroup master (VIN0 and VIN4). The
> > subgroup master must be switched on before the register is manipulated,
> > once the operation is complete it's safe to switch the master off and
> > the new routing will still be in effect.
> > 
> > Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
> > ---
> >  drivers/media/platform/rcar-vin/rcar-dma.c | 28 +++++++++++++++++++++++++++
> >  drivers/media/platform/rcar-vin/rcar-vin.h |  2 ++
> >  2 files changed, 30 insertions(+)
> > 
> > diff --git a/drivers/media/platform/rcar-vin/rcar-dma.c
> > b/drivers/media/platform/rcar-vin/rcar-dma.c index
> > 2f9ad1bec1c8a92f..ae286742f15a3ab5 100644
> > --- a/drivers/media/platform/rcar-vin/rcar-dma.c
> > +++ b/drivers/media/platform/rcar-vin/rcar-dma.c
> > @@ -16,6 +16,7 @@
> > 
> >  #include <linux/delay.h>
> >  #include <linux/interrupt.h>
> > +#include <linux/pm_runtime.h>
> > 
> >  #include <media/videobuf2-dma-contig.h>
> > 
> > @@ -1228,3 +1229,30 @@ int rvin_dma_register(struct rvin_dev *vin, int irq)
> > 
> >  	return ret;
> >  }
> > +
> > +/* ------------------------------------------------------------------------
> > + * Gen3 CHSEL manipulation
> > + */
> > +
> > +void rvin_set_channel_routing(struct rvin_dev *vin, u8 chsel)
> > +{
> > +	u32 ifmd, vnmc;
> > +
> > +	pm_runtime_get_sync(vin->dev);
> 
> No need to check for errors ?

You asked the samething for v9 so I will copy paste the same reply :-)

    Sakari asked the same thing in v4 :-)

    In short no its not needed please see Geert's response [1]. If I 
    recall correctly this was also discussed in more detail in another 
    thread for some other driver whit a bit longer answer saying that it
    pm_runtime_get_sync() fails you have big problems but I can't find 
    that thread now :-(

    1. https://www.spinics.net/lists/linux-media/msg115241.html

> 
> > +
> > +	/* Make register writes take effect immediately */
> > +	vnmc = rvin_read(vin, VNMC_REG);
> > +	rvin_write(vin, vnmc & ~VNMC_VUP, VNMC_REG);
> > +
> > +	ifmd = VNCSI_IFMD_DES2 | VNCSI_IFMD_DES1 | VNCSI_IFMD_DES0 |
> > +		VNCSI_IFMD_CSI_CHSEL(chsel);
> > +
> > +	rvin_write(vin, ifmd, VNCSI_IFMD_REG);
> > +
> > +	vin_dbg(vin, "Set IFMD 0x%x\n", ifmd);
> > +
> > +	/* Restore VNMC */
> > +	rvin_write(vin, vnmc, VNMC_REG);
> 
> No need for locking around all this ? What happens if this VIN instance 
> decides to write to another VIN register (for instance due to a userpace call) 
> when this function has disabled VNMC_VUP ?

You also asked a related question to this in v9 as a start I will copy 
in that reply.

    Media link changes are not allowed when any VIN in the group are
    streaming so this should not be an issue.

And to compliment that. This function is only valid for a VIN which has 
the CHSEL register which currently is VIN0 and VIN4. It can only be 
modified when a media link is enabled. Catching media links are only 
allowed when all VIN in the system are _not_ streaming. And VNMC_VUP is 
only enabled when a VIN is streaming so there is no need for locking 
here.

> 
> > +	pm_runtime_put(vin->dev);
> > +}
> > diff --git a/drivers/media/platform/rcar-vin/rcar-vin.h
> > b/drivers/media/platform/rcar-vin/rcar-vin.h index
> > 146683142e6533fa..a5dae5b5e9cb704b 100644
> > --- a/drivers/media/platform/rcar-vin/rcar-vin.h
> > +++ b/drivers/media/platform/rcar-vin/rcar-vin.h
> > @@ -165,4 +165,6 @@ const struct rvin_video_format
> > *rvin_format_from_pixel(u32 pixelformat); /* Cropping, composing and
> > scaling */
> >  void rvin_crop_scale_comp(struct rvin_dev *vin);
> > 
> > +void rvin_set_channel_routing(struct rvin_dev *vin, u8 chsel);
> > +
> >  #endif
> 
> -- 
> Regards,
> 
> Laurent Pinchart
> 

-- 
Regards,
Niklas Söderlund

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v10 13/30] rcar-vin: add function to manipulate Gen3 chsel value
@ 2018-02-13 16:58       ` Niklas Söderlund
  0 siblings, 0 replies; 65+ messages in thread
From: Niklas Söderlund @ 2018-02-13 16:58 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Hans Verkuil, linux-media, linux-renesas-soc, tomoharu.fukawa.eb,
	Kieran Bingham

Hi Laurent,

On 2018-02-13 18:41:33 +0200, Laurent Pinchart wrote:
> Hi Niklas,
> 
> Thank you for the patch.
> 
> On Monday, 29 January 2018 18:34:18 EET Niklas S�derlund wrote:
> > On Gen3 the CSI-2 routing is controlled by the VnCSI_IFMD register. One
> > feature of this register is that it's only present in the VIN0 and VIN4
> > instances. The register in VIN0 controls the routing for VIN0-3 and the
> > register in VIN4 controls routing for VIN4-7.
> > 
> > To be able to control routing from a media device this function is need
> > to control runtime PM for the subgroup master (VIN0 and VIN4). The
> > subgroup master must be switched on before the register is manipulated,
> > once the operation is complete it's safe to switch the master off and
> > the new routing will still be in effect.
> > 
> > Signed-off-by: Niklas S�derlund <niklas.soderlund+renesas@ragnatech.se>
> > ---
> >  drivers/media/platform/rcar-vin/rcar-dma.c | 28 +++++++++++++++++++++++++++
> >  drivers/media/platform/rcar-vin/rcar-vin.h |  2 ++
> >  2 files changed, 30 insertions(+)
> > 
> > diff --git a/drivers/media/platform/rcar-vin/rcar-dma.c
> > b/drivers/media/platform/rcar-vin/rcar-dma.c index
> > 2f9ad1bec1c8a92f..ae286742f15a3ab5 100644
> > --- a/drivers/media/platform/rcar-vin/rcar-dma.c
> > +++ b/drivers/media/platform/rcar-vin/rcar-dma.c
> > @@ -16,6 +16,7 @@
> > 
> >  #include <linux/delay.h>
> >  #include <linux/interrupt.h>
> > +#include <linux/pm_runtime.h>
> > 
> >  #include <media/videobuf2-dma-contig.h>
> > 
> > @@ -1228,3 +1229,30 @@ int rvin_dma_register(struct rvin_dev *vin, int irq)
> > 
> >  	return ret;
> >  }
> > +
> > +/* ------------------------------------------------------------------------
> > + * Gen3 CHSEL manipulation
> > + */
> > +
> > +void rvin_set_channel_routing(struct rvin_dev *vin, u8 chsel)
> > +{
> > +	u32 ifmd, vnmc;
> > +
> > +	pm_runtime_get_sync(vin->dev);
> 
> No need to check for errors ?

You asked the samething for v9 so I will copy paste the same reply :-)

    Sakari asked the same thing in v4 :-)

    In short no its not needed please see Geert's response [1]. If I 
    recall correctly this was also discussed in more detail in another 
    thread for some other driver whit a bit longer answer saying that it
    pm_runtime_get_sync() fails you have big problems but I can't find 
    that thread now :-(

    1. https://www.spinics.net/lists/linux-media/msg115241.html

> 
> > +
> > +	/* Make register writes take effect immediately */
> > +	vnmc = rvin_read(vin, VNMC_REG);
> > +	rvin_write(vin, vnmc & ~VNMC_VUP, VNMC_REG);
> > +
> > +	ifmd = VNCSI_IFMD_DES2 | VNCSI_IFMD_DES1 | VNCSI_IFMD_DES0 |
> > +		VNCSI_IFMD_CSI_CHSEL(chsel);
> > +
> > +	rvin_write(vin, ifmd, VNCSI_IFMD_REG);
> > +
> > +	vin_dbg(vin, "Set IFMD 0x%x\n", ifmd);
> > +
> > +	/* Restore VNMC */
> > +	rvin_write(vin, vnmc, VNMC_REG);
> 
> No need for locking around all this ? What happens if this VIN instance 
> decides to write to another VIN register (for instance due to a userpace call) 
> when this function has disabled VNMC_VUP ?

You also asked a related question to this in v9 as a start I will copy 
in that reply.

    Media link changes are not allowed when any VIN in the group are
    streaming so this should not be an issue.

And to compliment that. This function is only valid for a VIN which has 
the CHSEL register which currently is VIN0 and VIN4. It can only be 
modified when a media link is enabled. Catching media links are only 
allowed when all VIN in the system are _not_ streaming. And VNMC_VUP is 
only enabled when a VIN is streaming so there is no need for locking 
here.

> 
> > +	pm_runtime_put(vin->dev);
> > +}
> > diff --git a/drivers/media/platform/rcar-vin/rcar-vin.h
> > b/drivers/media/platform/rcar-vin/rcar-vin.h index
> > 146683142e6533fa..a5dae5b5e9cb704b 100644
> > --- a/drivers/media/platform/rcar-vin/rcar-vin.h
> > +++ b/drivers/media/platform/rcar-vin/rcar-vin.h
> > @@ -165,4 +165,6 @@ const struct rvin_video_format
> > *rvin_format_from_pixel(u32 pixelformat); /* Cropping, composing and
> > scaling */
> >  void rvin_crop_scale_comp(struct rvin_dev *vin);
> > 
> > +void rvin_set_channel_routing(struct rvin_dev *vin, u8 chsel);
> > +
> >  #endif
> 
> -- 
> Regards,
> 
> Laurent Pinchart
> 

-- 
Regards,
Niklas S�derlund

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v10 16/30] rcar-vin: update bytesperline and sizeimage calculation
  2018-01-29 16:34 ` [PATCH v10 16/30] rcar-vin: update bytesperline and sizeimage calculation Niklas Söderlund
@ 2018-02-13 16:58   ` Laurent Pinchart
  0 siblings, 0 replies; 65+ messages in thread
From: Laurent Pinchart @ 2018-02-13 16:58 UTC (permalink / raw)
  To: Niklas Söderlund
  Cc: Hans Verkuil, linux-media, linux-renesas-soc, tomoharu.fukawa.eb,
	Kieran Bingham

Hi Niklas,

Thank you for the patch.

On Monday, 29 January 2018 18:34:21 EET Niklas Söderlund wrote:
> Remove over complicated logic to calculate the value for bytesperline

s/over complicated/overcomplicated/

> and sizeimage that was carried over from the soc_camera port. Update the
> calculations to match how other drivers are doing it.
> 
> Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
> ---
>  drivers/media/platform/rcar-vin/rcar-v4l2.c | 11 ++---------
>  1 file changed, 2 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/media/platform/rcar-vin/rcar-v4l2.c
> b/drivers/media/platform/rcar-vin/rcar-v4l2.c index
> 1169e6a279ecfb55..bca6e204a574772f 100644
> --- a/drivers/media/platform/rcar-vin/rcar-v4l2.c
> +++ b/drivers/media/platform/rcar-vin/rcar-v4l2.c
> @@ -118,10 +118,8 @@ static int rvin_format_align(struct rvin_dev *vin,
> struct v4l2_pix_format *pix) v4l_bound_align_image(&pix->width, 2,
> vin->info->max_width, walign, &pix->height, 4, vin->info->max_height, 2,
> 0);
> 
> -	pix->bytesperline = max_t(u32, pix->bytesperline,
> -				  rvin_format_bytesperline(pix));
> -	pix->sizeimage = max_t(u32, pix->sizeimage,
> -			       rvin_format_sizeimage(pix));
> +	pix->bytesperline = rvin_format_bytesperline(pix);
> +	pix->sizeimage = rvin_format_sizeimage(pix);

Thus this mean that the driver will stop supporting configurable strides ? 
Isn't that a regression ?

>  	if (vin->info->model == RCAR_M1 &&
>  	    pix->pixelformat == V4L2_PIX_FMT_XBGR32) {
> @@ -270,11 +268,6 @@ static int __rvin_try_format(struct rvin_dev *vin,
>  	if (pix->field == V4L2_FIELD_ANY)
>  		pix->field = vin->format.field;
> 
> -
> -	/* Always recalculate */
> -	pix->bytesperline = 0;
> -	pix->sizeimage = 0;
> -
>  	/* Limit to source capabilities */
>  	ret = __rvin_try_format_source(vin, which, pix);
>  	if (ret)


-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v10 13/30] rcar-vin: add function to manipulate Gen3 chsel value
  2018-02-13 16:58       ` Niklas Söderlund
  (?)
@ 2018-02-13 17:02       ` Laurent Pinchart
  2018-02-13 17:11           ` Niklas Söderlund
  -1 siblings, 1 reply; 65+ messages in thread
From: Laurent Pinchart @ 2018-02-13 17:02 UTC (permalink / raw)
  To: Niklas Söderlund
  Cc: Hans Verkuil, linux-media, linux-renesas-soc, tomoharu.fukawa.eb,
	Kieran Bingham

Hi Niklas,

On Tuesday, 13 February 2018 18:58:09 EET Niklas Söderlund wrote:
> On 2018-02-13 18:41:33 +0200, Laurent Pinchart wrote:
> > On Monday, 29 January 2018 18:34:18 EET Niklas Söderlund wrote:
> > > On Gen3 the CSI-2 routing is controlled by the VnCSI_IFMD register. One
> > > feature of this register is that it's only present in the VIN0 and VIN4
> > > instances. The register in VIN0 controls the routing for VIN0-3 and the
> > > register in VIN4 controls routing for VIN4-7.
> > > 
> > > To be able to control routing from a media device this function is need
> > > to control runtime PM for the subgroup master (VIN0 and VIN4). The
> > > subgroup master must be switched on before the register is manipulated,
> > > once the operation is complete it's safe to switch the master off and
> > > the new routing will still be in effect.
> > > 
> > > Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
> > > ---
> >> 
> >>  drivers/media/platform/rcar-vin/rcar-dma.c | 28+++++++++++++++++++++++++
> >>  drivers/media/platform/rcar-vin/rcar-vin.h |  2 ++
> >>  2 files changed, 30 insertions(+)
> >> 
> >> diff --git a/drivers/media/platform/rcar-vin/rcar-dma.c
> >> b/drivers/media/platform/rcar-vin/rcar-dma.c index
> >> 2f9ad1bec1c8a92f..ae286742f15a3ab5 100644
> >> --- a/drivers/media/platform/rcar-vin/rcar-dma.c
> >> +++ b/drivers/media/platform/rcar-vin/rcar-dma.c
> >> @@ -16,6 +16,7 @@
> >> 
> >>  #include <linux/delay.h>
> >>  #include <linux/interrupt.h>
> >> +#include <linux/pm_runtime.h>
> >> 
> >>  #include <media/videobuf2-dma-contig.h>
> >> 
> >> @@ -1228,3 +1229,30 @@ int rvin_dma_register(struct rvin_dev *vin, int
> >> irq)
> >>  	return ret;
> >>  }
> >> 
> >> +
> >> +/* ---------------------------------------------------------------------
> >> + * Gen3 CHSEL manipulation
> >> + */
> >> +
> >> +void rvin_set_channel_routing(struct rvin_dev *vin, u8 chsel)
> >> +{
> >> +	u32 ifmd, vnmc;
> >> +
> >> +	pm_runtime_get_sync(vin->dev);
> > 
> > No need to check for errors ?
> 
> You asked the samething for v9 so I will copy paste the same reply :-)

Oh so you expect me to remember what happened with previous versions ? :-)

>     Sakari asked the same thing in v4 :-)
> 
>     In short no its not needed please see Geert's response [1]. If I
>     recall correctly this was also discussed in more detail in another
>     thread for some other driver whit a bit longer answer saying that it
>     pm_runtime_get_sync() fails you have big problems but I can't find
>     that thread now :-(
> 
>     1. https://www.spinics.net/lists/linux-media/msg115241.html

If kmalloc() fails we also have big problems, but we nonetheless check every 
memory allocation.

> >> +
> >> +	/* Make register writes take effect immediately */
> >> +	vnmc = rvin_read(vin, VNMC_REG);
> >> +	rvin_write(vin, vnmc & ~VNMC_VUP, VNMC_REG);
> >> +
> >> +	ifmd = VNCSI_IFMD_DES2 | VNCSI_IFMD_DES1 | VNCSI_IFMD_DES0 |
> >> +		VNCSI_IFMD_CSI_CHSEL(chsel);
> >> +
> >> +	rvin_write(vin, ifmd, VNCSI_IFMD_REG);
> >> +
> >> +	vin_dbg(vin, "Set IFMD 0x%x\n", ifmd);
> >> +
> >> +	/* Restore VNMC */
> >> +	rvin_write(vin, vnmc, VNMC_REG);
> > 
> > No need for locking around all this ? What happens if this VIN instance
> > decides to write to another VIN register (for instance due to a userpace
> > call) when this function has disabled VNMC_VUP ?
> 
> You also asked a related question to this in v9 as a start I will copy
> in that reply.
> 
>     Media link changes are not allowed when any VIN in the group are
>     streaming so this should not be an issue.
> 
> And to compliment that. This function is only valid for a VIN which has
> the CHSEL register which currently is VIN0 and VIN4. It can only be
> modified when a media link is enabled. Catching media links are only
> allowed when all VIN in the system are _not_ streaming. And VNMC_VUP is
> only enabled when a VIN is streaming so there is no need for locking
> here.

This seems a bit fragile to me, could you please capture the explanation in a 
comment ?

> >> +	pm_runtime_put(vin->dev);
> >> +}
> >> diff --git a/drivers/media/platform/rcar-vin/rcar-vin.h
> >> b/drivers/media/platform/rcar-vin/rcar-vin.h index
> >> 146683142e6533fa..a5dae5b5e9cb704b 100644
> >> --- a/drivers/media/platform/rcar-vin/rcar-vin.h
> >> +++ b/drivers/media/platform/rcar-vin/rcar-vin.h
> >> @@ -165,4 +165,6 @@ const struct rvin_video_format
> >> *rvin_format_from_pixel(u32 pixelformat); /* Cropping, composing and
> >> scaling */
> >> 
> >>  void rvin_crop_scale_comp(struct rvin_dev *vin);
> >> 
> >> +void rvin_set_channel_routing(struct rvin_dev *vin, u8 chsel);
> >> +
> >>  #endif

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v10 17/30] rcar-vin: update pixelformat check for M1
  2018-01-29 16:34 ` [PATCH v10 17/30] rcar-vin: update pixelformat check for M1 Niklas Söderlund
@ 2018-02-13 17:03   ` Laurent Pinchart
  0 siblings, 0 replies; 65+ messages in thread
From: Laurent Pinchart @ 2018-02-13 17:03 UTC (permalink / raw)
  To: Niklas Söderlund
  Cc: Hans Verkuil, linux-media, linux-renesas-soc, tomoharu.fukawa.eb,
	Kieran Bingham

Hi Niklas,

Thank you for the patch.

On Monday, 29 January 2018 18:34:22 EET Niklas Söderlund wrote:
> If the pixelformat is not supported it should not fail but be set to
> something that works. While we are at it move the check together with
> other pixelformat checks of this function.

Please ignore my related comment to patch 16/30 :-) However, could you move 
this patch before 16/30 ?

> Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>

Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

> ---
>  drivers/media/platform/rcar-vin/rcar-v4l2.c | 10 ++++------
>  1 file changed, 4 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/media/platform/rcar-vin/rcar-v4l2.c
> b/drivers/media/platform/rcar-vin/rcar-v4l2.c index
> bca6e204a574772f..841d62ca27e026d7 100644
> --- a/drivers/media/platform/rcar-vin/rcar-v4l2.c
> +++ b/drivers/media/platform/rcar-vin/rcar-v4l2.c
> @@ -97,6 +97,10 @@ static int rvin_format_align(struct rvin_dev *vin, struct
> v4l2_pix_format *pix) pix->pixelformat = RVIN_DEFAULT_FORMAT;
>  	}
> 
> +	if (vin->info->model == RCAR_M1 &&
> +	    pix->pixelformat == V4L2_PIX_FMT_XBGR32)
> +		pix->pixelformat = RVIN_DEFAULT_FORMAT;
> +
>  	/* Reject ALTERNATE  until support is added to the driver */
>  	switch (pix->field) {
>  	case V4L2_FIELD_TOP:
> @@ -121,12 +125,6 @@ static int rvin_format_align(struct rvin_dev *vin,
> struct v4l2_pix_format *pix) pix->bytesperline =
> rvin_format_bytesperline(pix);
>  	pix->sizeimage = rvin_format_sizeimage(pix);
> 
> -	if (vin->info->model == RCAR_M1 &&
> -	    pix->pixelformat == V4L2_PIX_FMT_XBGR32) {
> -		vin_err(vin, "pixel format XBGR32 not supported on M1\n");
> -		return -EINVAL;
> -	}
> -
>  	vin_dbg(vin, "Format %ux%u bpl: %d size: %d\n",
>  		pix->width, pix->height, pix->bytesperline, pix->sizeimage);

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v10 18/30] rcar-vin: add check for colorspace
  2018-01-29 16:34 ` [PATCH v10 18/30] rcar-vin: add check for colorspace Niklas Söderlund
@ 2018-02-13 17:08   ` Laurent Pinchart
  0 siblings, 0 replies; 65+ messages in thread
From: Laurent Pinchart @ 2018-02-13 17:08 UTC (permalink / raw)
  To: Niklas Söderlund
  Cc: Hans Verkuil, linux-media, linux-renesas-soc, tomoharu.fukawa.eb,
	Kieran Bingham

Hi Niklas,

Thank you for the patch.

On Monday, 29 January 2018 18:34:23 EET Niklas Söderlund wrote:
> Add a check to ensure the colorspace from user-space is good. On Gen2 it
> works without this change as the sensor sets the colorspace but on Gen3
> this can fail if the colorspace provided by the user is not good. The
> values to check for comes from v4l2-compliance sources which is the tool
> that found this error. If this check is not preformed v4l2-compliance

s/preformed/performed/

> fails when it tests colorspace.
> 
> Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
> ---
>  drivers/media/platform/rcar-vin/rcar-v4l2.c | 5 +++++
>  1 file changed, 5 insertions(+)
> 
> diff --git a/drivers/media/platform/rcar-vin/rcar-v4l2.c
> b/drivers/media/platform/rcar-vin/rcar-v4l2.c index
> 841d62ca27e026d7..6403650aff22a2ed 100644
> --- a/drivers/media/platform/rcar-vin/rcar-v4l2.c
> +++ b/drivers/media/platform/rcar-vin/rcar-v4l2.c
> @@ -23,6 +23,7 @@
>  #include "rcar-vin.h"
> 
>  #define RVIN_DEFAULT_FORMAT	V4L2_PIX_FMT_YUYV
> +#define RVIN_DEFAULT_COLORSPACE	V4L2_COLORSPACE_SRGB
> 
>  /* ------------------------------------------------------------------------
>   * Format Conversions
> @@ -115,6 +116,10 @@ static int rvin_format_align(struct rvin_dev *vin,
> struct v4l2_pix_format *pix) break;
>  	}
> 
> +	/* Check that colorspace is reasonable */
> +	if (!pix->colorspace || pix->colorspace >= 0xff)

I'd write the first check as

	pix->colorspace == V4L2_COLORSPACE_DEFAULT

For the second check I don't think 0xff is a meaningful value. We currently 
have 12 colorspaces defined. If we want to be future-proof I'd add a 
V4L2_COLORSPACE_MAX entry to enum v4l2_colorspace and use that for the check. 
Alternatively you could use V4L2_COLORSPACE_DCI_P3 but the driver would need 
to be updated when new colorspaces get added.

> +		pix->colorspace = RVIN_DEFAULT_COLORSPACE;
> +
>  	/* HW limit width to a multiple of 32 (2^5) for NV16 else 2 (2^1) */
>  	walign = vin->format.pixelformat == V4L2_PIX_FMT_NV16 ? 5 : 1;

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v10 13/30] rcar-vin: add function to manipulate Gen3 chsel value
  2018-02-13 17:02       ` Laurent Pinchart
@ 2018-02-13 17:11           ` Niklas Söderlund
  0 siblings, 0 replies; 65+ messages in thread
From: Niklas Söderlund @ 2018-02-13 17:11 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Hans Verkuil, linux-media, linux-renesas-soc, tomoharu.fukawa.eb,
	Kieran Bingham

Hi Laurent,

On 2018-02-13 19:02:38 +0200, Laurent Pinchart wrote:
> Hi Niklas,
> 
> On Tuesday, 13 February 2018 18:58:09 EET Niklas Söderlund wrote:
> > On 2018-02-13 18:41:33 +0200, Laurent Pinchart wrote:
> > > On Monday, 29 January 2018 18:34:18 EET Niklas Söderlund wrote:
> > > > On Gen3 the CSI-2 routing is controlled by the VnCSI_IFMD register. One
> > > > feature of this register is that it's only present in the VIN0 and VIN4
> > > > instances. The register in VIN0 controls the routing for VIN0-3 and the
> > > > register in VIN4 controls routing for VIN4-7.
> > > > 
> > > > To be able to control routing from a media device this function is need
> > > > to control runtime PM for the subgroup master (VIN0 and VIN4). The
> > > > subgroup master must be switched on before the register is manipulated,
> > > > once the operation is complete it's safe to switch the master off and
> > > > the new routing will still be in effect.
> > > > 
> > > > Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
> > > > ---
> > >> 
> > >>  drivers/media/platform/rcar-vin/rcar-dma.c | 28+++++++++++++++++++++++++
> > >>  drivers/media/platform/rcar-vin/rcar-vin.h |  2 ++
> > >>  2 files changed, 30 insertions(+)
> > >> 
> > >> diff --git a/drivers/media/platform/rcar-vin/rcar-dma.c
> > >> b/drivers/media/platform/rcar-vin/rcar-dma.c index
> > >> 2f9ad1bec1c8a92f..ae286742f15a3ab5 100644
> > >> --- a/drivers/media/platform/rcar-vin/rcar-dma.c
> > >> +++ b/drivers/media/platform/rcar-vin/rcar-dma.c
> > >> @@ -16,6 +16,7 @@
> > >> 
> > >>  #include <linux/delay.h>
> > >>  #include <linux/interrupt.h>
> > >> +#include <linux/pm_runtime.h>
> > >> 
> > >>  #include <media/videobuf2-dma-contig.h>
> > >> 
> > >> @@ -1228,3 +1229,30 @@ int rvin_dma_register(struct rvin_dev *vin, int
> > >> irq)
> > >>  	return ret;
> > >>  }
> > >> 
> > >> +
> > >> +/* ---------------------------------------------------------------------
> > >> + * Gen3 CHSEL manipulation
> > >> + */
> > >> +
> > >> +void rvin_set_channel_routing(struct rvin_dev *vin, u8 chsel)
> > >> +{
> > >> +	u32 ifmd, vnmc;
> > >> +
> > >> +	pm_runtime_get_sync(vin->dev);
> > > 
> > > No need to check for errors ?
> > 
> > You asked the samething for v9 so I will copy paste the same reply :-)
> 
> Oh so you expect me to remember what happened with previous versions ? :-)

:-)

> 
> >     Sakari asked the same thing in v4 :-)
> > 
> >     In short no its not needed please see Geert's response [1]. If I
> >     recall correctly this was also discussed in more detail in another
> >     thread for some other driver whit a bit longer answer saying that it
> >     pm_runtime_get_sync() fails you have big problems but I can't find
> >     that thread now :-(
> > 
> >     1. https://www.spinics.net/lists/linux-media/msg115241.html
> 
> If kmalloc() fails we also have big problems, but we nonetheless check every 
> memory allocation.

I did some quick and dirty statistics for current upstream behavior,

$ git grep pm_runtime_get_sync | wc -l
1044
$ git grep pm_runtime_get_sync | grep = | wc -l
367

It looks like a less then half checks the return value :-) But as it 
will take at least one more incarnation of this patch set I will add a 
check for it get to the good side of things.

> 
> > >> +
> > >> +	/* Make register writes take effect immediately */
> > >> +	vnmc = rvin_read(vin, VNMC_REG);
> > >> +	rvin_write(vin, vnmc & ~VNMC_VUP, VNMC_REG);
> > >> +
> > >> +	ifmd = VNCSI_IFMD_DES2 | VNCSI_IFMD_DES1 | VNCSI_IFMD_DES0 |
> > >> +		VNCSI_IFMD_CSI_CHSEL(chsel);
> > >> +
> > >> +	rvin_write(vin, ifmd, VNCSI_IFMD_REG);
> > >> +
> > >> +	vin_dbg(vin, "Set IFMD 0x%x\n", ifmd);
> > >> +
> > >> +	/* Restore VNMC */
> > >> +	rvin_write(vin, vnmc, VNMC_REG);
> > > 
> > > No need for locking around all this ? What happens if this VIN instance
> > > decides to write to another VIN register (for instance due to a userpace
> > > call) when this function has disabled VNMC_VUP ?
> > 
> > You also asked a related question to this in v9 as a start I will copy
> > in that reply.
> > 
> >     Media link changes are not allowed when any VIN in the group are
> >     streaming so this should not be an issue.
> > 
> > And to compliment that. This function is only valid for a VIN which has
> > the CHSEL register which currently is VIN0 and VIN4. It can only be
> > modified when a media link is enabled. Catching media links are only
> > allowed when all VIN in the system are _not_ streaming. And VNMC_VUP is
> > only enabled when a VIN is streaming so there is no need for locking
> > here.
> 
> This seems a bit fragile to me, could you please capture the explanation in a 
> comment ?
> 

Will do.

> > >> +	pm_runtime_put(vin->dev);
> > >> +}
> > >> diff --git a/drivers/media/platform/rcar-vin/rcar-vin.h
> > >> b/drivers/media/platform/rcar-vin/rcar-vin.h index
> > >> 146683142e6533fa..a5dae5b5e9cb704b 100644
> > >> --- a/drivers/media/platform/rcar-vin/rcar-vin.h
> > >> +++ b/drivers/media/platform/rcar-vin/rcar-vin.h
> > >> @@ -165,4 +165,6 @@ const struct rvin_video_format
> > >> *rvin_format_from_pixel(u32 pixelformat); /* Cropping, composing and
> > >> scaling */
> > >> 
> > >>  void rvin_crop_scale_comp(struct rvin_dev *vin);
> > >> 
> > >> +void rvin_set_channel_routing(struct rvin_dev *vin, u8 chsel);
> > >> +
> > >>  #endif
> 
> -- 
> Regards,
> 
> Laurent Pinchart
> 

-- 
Regards,
Niklas Söderlund

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v10 13/30] rcar-vin: add function to manipulate Gen3 chsel value
@ 2018-02-13 17:11           ` Niklas Söderlund
  0 siblings, 0 replies; 65+ messages in thread
From: Niklas Söderlund @ 2018-02-13 17:11 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Hans Verkuil, linux-media, linux-renesas-soc, tomoharu.fukawa.eb,
	Kieran Bingham

Hi Laurent,

On 2018-02-13 19:02:38 +0200, Laurent Pinchart wrote:
> Hi Niklas,
> 
> On Tuesday, 13 February 2018 18:58:09 EET Niklas S�derlund wrote:
> > On 2018-02-13 18:41:33 +0200, Laurent Pinchart wrote:
> > > On Monday, 29 January 2018 18:34:18 EET Niklas S�derlund wrote:
> > > > On Gen3 the CSI-2 routing is controlled by the VnCSI_IFMD register. One
> > > > feature of this register is that it's only present in the VIN0 and VIN4
> > > > instances. The register in VIN0 controls the routing for VIN0-3 and the
> > > > register in VIN4 controls routing for VIN4-7.
> > > > 
> > > > To be able to control routing from a media device this function is need
> > > > to control runtime PM for the subgroup master (VIN0 and VIN4). The
> > > > subgroup master must be switched on before the register is manipulated,
> > > > once the operation is complete it's safe to switch the master off and
> > > > the new routing will still be in effect.
> > > > 
> > > > Signed-off-by: Niklas S�derlund <niklas.soderlund+renesas@ragnatech.se>
> > > > ---
> > >> 
> > >>  drivers/media/platform/rcar-vin/rcar-dma.c | 28+++++++++++++++++++++++++
> > >>  drivers/media/platform/rcar-vin/rcar-vin.h |  2 ++
> > >>  2 files changed, 30 insertions(+)
> > >> 
> > >> diff --git a/drivers/media/platform/rcar-vin/rcar-dma.c
> > >> b/drivers/media/platform/rcar-vin/rcar-dma.c index
> > >> 2f9ad1bec1c8a92f..ae286742f15a3ab5 100644
> > >> --- a/drivers/media/platform/rcar-vin/rcar-dma.c
> > >> +++ b/drivers/media/platform/rcar-vin/rcar-dma.c
> > >> @@ -16,6 +16,7 @@
> > >> 
> > >>  #include <linux/delay.h>
> > >>  #include <linux/interrupt.h>
> > >> +#include <linux/pm_runtime.h>
> > >> 
> > >>  #include <media/videobuf2-dma-contig.h>
> > >> 
> > >> @@ -1228,3 +1229,30 @@ int rvin_dma_register(struct rvin_dev *vin, int
> > >> irq)
> > >>  	return ret;
> > >>  }
> > >> 
> > >> +
> > >> +/* ---------------------------------------------------------------------
> > >> + * Gen3 CHSEL manipulation
> > >> + */
> > >> +
> > >> +void rvin_set_channel_routing(struct rvin_dev *vin, u8 chsel)
> > >> +{
> > >> +	u32 ifmd, vnmc;
> > >> +
> > >> +	pm_runtime_get_sync(vin->dev);
> > > 
> > > No need to check for errors ?
> > 
> > You asked the samething for v9 so I will copy paste the same reply :-)
> 
> Oh so you expect me to remember what happened with previous versions ? :-)

:-)

> 
> >     Sakari asked the same thing in v4 :-)
> > 
> >     In short no its not needed please see Geert's response [1]. If I
> >     recall correctly this was also discussed in more detail in another
> >     thread for some other driver whit a bit longer answer saying that it
> >     pm_runtime_get_sync() fails you have big problems but I can't find
> >     that thread now :-(
> > 
> >     1. https://www.spinics.net/lists/linux-media/msg115241.html
> 
> If kmalloc() fails we also have big problems, but we nonetheless check every 
> memory allocation.

I did some quick and dirty statistics for current upstream behavior,

$ git grep pm_runtime_get_sync | wc -l
1044
$ git grep pm_runtime_get_sync | grep = | wc -l
367

It looks like a less then half checks the return value :-) But as it 
will take at least one more incarnation of this patch set I will add a 
check for it get to the good side of things.

> 
> > >> +
> > >> +	/* Make register writes take effect immediately */
> > >> +	vnmc = rvin_read(vin, VNMC_REG);
> > >> +	rvin_write(vin, vnmc & ~VNMC_VUP, VNMC_REG);
> > >> +
> > >> +	ifmd = VNCSI_IFMD_DES2 | VNCSI_IFMD_DES1 | VNCSI_IFMD_DES0 |
> > >> +		VNCSI_IFMD_CSI_CHSEL(chsel);
> > >> +
> > >> +	rvin_write(vin, ifmd, VNCSI_IFMD_REG);
> > >> +
> > >> +	vin_dbg(vin, "Set IFMD 0x%x\n", ifmd);
> > >> +
> > >> +	/* Restore VNMC */
> > >> +	rvin_write(vin, vnmc, VNMC_REG);
> > > 
> > > No need for locking around all this ? What happens if this VIN instance
> > > decides to write to another VIN register (for instance due to a userpace
> > > call) when this function has disabled VNMC_VUP ?
> > 
> > You also asked a related question to this in v9 as a start I will copy
> > in that reply.
> > 
> >     Media link changes are not allowed when any VIN in the group are
> >     streaming so this should not be an issue.
> > 
> > And to compliment that. This function is only valid for a VIN which has
> > the CHSEL register which currently is VIN0 and VIN4. It can only be
> > modified when a media link is enabled. Catching media links are only
> > allowed when all VIN in the system are _not_ streaming. And VNMC_VUP is
> > only enabled when a VIN is streaming so there is no need for locking
> > here.
> 
> This seems a bit fragile to me, could you please capture the explanation in a 
> comment ?
> 

Will do.

> > >> +	pm_runtime_put(vin->dev);
> > >> +}
> > >> diff --git a/drivers/media/platform/rcar-vin/rcar-vin.h
> > >> b/drivers/media/platform/rcar-vin/rcar-vin.h index
> > >> 146683142e6533fa..a5dae5b5e9cb704b 100644
> > >> --- a/drivers/media/platform/rcar-vin/rcar-vin.h
> > >> +++ b/drivers/media/platform/rcar-vin/rcar-vin.h
> > >> @@ -165,4 +165,6 @@ const struct rvin_video_format
> > >> *rvin_format_from_pixel(u32 pixelformat); /* Cropping, composing and
> > >> scaling */
> > >> 
> > >>  void rvin_crop_scale_comp(struct rvin_dev *vin);
> > >> 
> > >> +void rvin_set_channel_routing(struct rvin_dev *vin, u8 chsel);
> > >> +
> > >>  #endif
> 
> -- 
> Regards,
> 
> Laurent Pinchart
> 

-- 
Regards,
Niklas S�derlund

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v10 19/30] rcar-vin: set a default field to fallback on
  2018-01-29 16:34 ` [PATCH v10 19/30] rcar-vin: set a default field to fallback on Niklas Söderlund
@ 2018-02-13 17:51   ` Laurent Pinchart
  0 siblings, 0 replies; 65+ messages in thread
From: Laurent Pinchart @ 2018-02-13 17:51 UTC (permalink / raw)
  To: Niklas Söderlund
  Cc: Hans Verkuil, linux-media, linux-renesas-soc, tomoharu.fukawa.eb,
	Kieran Bingham

Hi Niklas,

Thank you for the patch.

On Monday, 29 January 2018 18:34:24 EET Niklas Söderlund wrote:
> If the field is not supported by the driver it should not try to keep
> the current field. Instead it should set it to a default fallback. Since
> trying a format should always result in the same state regardless of the
> current state of the device.
> 
> Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
> ---
>  drivers/media/platform/rcar-vin/rcar-v4l2.c | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/media/platform/rcar-vin/rcar-v4l2.c
> b/drivers/media/platform/rcar-vin/rcar-v4l2.c index
> 6403650aff22a2ed..f69ae76b3fda50c7 100644
> --- a/drivers/media/platform/rcar-vin/rcar-v4l2.c
> +++ b/drivers/media/platform/rcar-vin/rcar-v4l2.c
> @@ -23,6 +23,7 @@
>  #include "rcar-vin.h"
> 
>  #define RVIN_DEFAULT_FORMAT	V4L2_PIX_FMT_YUYV
> +#define RVIN_DEFAULT_FIELD	V4L2_FIELD_NONE
>  #define RVIN_DEFAULT_COLORSPACE	V4L2_COLORSPACE_SRGB
> 
>  /* ------------------------------------------------------------------------
> @@ -171,7 +172,7 @@ static int rvin_get_source_format(struct rvin_dev
> *vin, fmt.format.height *= 2;
>  		break;
>  	default:
> -		vin->format.field = V4L2_FIELD_NONE;
> +		vin->format.field = RVIN_DEFAULT_FIELD;
>  		break;
>  	}
> 
> @@ -267,9 +268,8 @@ static int __rvin_try_format(struct rvin_dev *vin,
>  {
>  	int ret;
> 
> -	/* Keep current field if no specific one is asked for */
>  	if (pix->field == V4L2_FIELD_ANY)
> -		pix->field = vin->format.field;
> +		pix->field = RVIN_DEFAULT_FIELD;

Won't this also be caught by the field check in the above function, called 
from __rvin_try_format_source() ? You could just remove this check completely.

However as mentioned in a comment for a previous patch I don't think the field 
handling belongs in rvin_get_source_format(), so you could merge both here. 
Or, if you repurpose and rename rvin_get_source_format(), then the check can 
probably be removed completely. I haven't checked the consolidated code after 
applying all patches from this series, but some refactoring might be useful. 
We'll see.

>  	/* Limit to source capabilities */
>  	ret = __rvin_try_format_source(vin, which, pix);

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v10 20/30] rcar-vin: use different v4l2 operations in media controller mode
  2018-01-29 16:34 ` [PATCH v10 20/30] rcar-vin: use different v4l2 operations in media controller mode Niklas Söderlund
@ 2018-02-13 19:42   ` Laurent Pinchart
  0 siblings, 0 replies; 65+ messages in thread
From: Laurent Pinchart @ 2018-02-13 19:42 UTC (permalink / raw)
  To: Niklas Söderlund
  Cc: Hans Verkuil, linux-media, linux-renesas-soc, tomoharu.fukawa.eb,
	Kieran Bingham

Hi Niklas,

Thank you for the patch.

On Monday, 29 January 2018 18:34:25 EET Niklas Söderlund wrote:
> When the driver runs in media controller mode it should not directly
> control the subdevice instead userspace will be responsible for
> configuring the pipeline. To be able to run in this mode a different set
> of v4l2 operations needs to be used.
> 
> Add a new set of v4l2 operations to support operation without directly
> interacting with the source subdevice.
> 
> Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
> Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
> ---
>  drivers/media/platform/rcar-vin/rcar-dma.c  |   3 +-
>  drivers/media/platform/rcar-vin/rcar-v4l2.c | 155 ++++++++++++++++++++++++-
>  2 files changed, 154 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/media/platform/rcar-vin/rcar-dma.c
> b/drivers/media/platform/rcar-vin/rcar-dma.c index
> ae286742f15a3ab5..811d8f8638d21200 100644
> --- a/drivers/media/platform/rcar-vin/rcar-dma.c
> +++ b/drivers/media/platform/rcar-vin/rcar-dma.c
> @@ -628,7 +628,8 @@ static int rvin_setup(struct rvin_dev *vin)
>  		/* Default to TB */
>  		vnmc = VNMC_IM_FULL;
>  		/* Use BT if video standard can be read and is 60 Hz format */
> -		if (!v4l2_subdev_call(vin_to_source(vin), video, g_std, &std)) {
> +		if (!vin->info->use_mc &&
> +		    !v4l2_subdev_call(vin_to_source(vin), video, g_std, &std)) {
>  			if (std & V4L2_STD_525_60)
>  				vnmc = VNMC_IM_FULL | VNMC_FOC;
>  		}
> diff --git a/drivers/media/platform/rcar-vin/rcar-v4l2.c
> b/drivers/media/platform/rcar-vin/rcar-v4l2.c index
> f69ae76b3fda50c7..292e1f22a4be36c7 100644
> --- a/drivers/media/platform/rcar-vin/rcar-v4l2.c
> +++ b/drivers/media/platform/rcar-vin/rcar-v4l2.c
> @@ -18,11 +18,14 @@
> 
>  #include <media/v4l2-event.h>
>  #include <media/v4l2-ioctl.h>
> +#include <media/v4l2-mc.h>
>  #include <media/v4l2-rect.h>
> 
>  #include "rcar-vin.h"
> 
>  #define RVIN_DEFAULT_FORMAT	V4L2_PIX_FMT_YUYV
> +#define RVIN_DEFAULT_WIDTH	800
> +#define RVIN_DEFAULT_HEIGHT	600
>  #define RVIN_DEFAULT_FIELD	V4L2_FIELD_NONE
>  #define RVIN_DEFAULT_COLORSPACE	V4L2_COLORSPACE_SRGB
> 
> @@ -698,6 +701,83 @@ static const struct v4l2_ioctl_ops rvin_ioctl_ops = {
>  	.vidioc_unsubscribe_event	= v4l2_event_unsubscribe,
>  };
> 
> +/* ------------------------------------------------------------------------
> + * V4L2 Media Controller
> + */
> +
> +static int __rvin_mc_try_format(struct rvin_dev *vin,
> +				struct v4l2_pix_format *pix)
> +{
> +	if (pix->field == V4L2_FIELD_ANY)
> +		pix->field = RVIN_DEFAULT_FIELD;
> +
> +	return rvin_format_align(vin, pix);
> +}
> +
> +static int rvin_mc_try_fmt_vid_cap(struct file *file, void *priv,
> +				   struct v4l2_format *f)
> +{
> +	struct rvin_dev *vin = video_drvdata(file);
> +
> +	return __rvin_mc_try_format(vin, &f->fmt.pix);
> +}
> +
> +static int rvin_mc_s_fmt_vid_cap(struct file *file, void *priv,
> +				 struct v4l2_format *f)
> +{
> +	struct rvin_dev *vin = video_drvdata(file);
> +	int ret;
> +
> +	if (vb2_is_busy(&vin->queue))
> +		return -EBUSY;
> +
> +	ret = __rvin_mc_try_format(vin, &f->fmt.pix);
> +	if (ret)
> +		return ret;
> +
> +	vin->format = f->fmt.pix;
> +
> +	return 0;
> +}
> +
> +static int rvin_mc_enum_input(struct file *file, void *priv,
> +			      struct v4l2_input *i)
> +{
> +	if (i->index != 0)
> +		return -EINVAL;
> +
> +	i->type = V4L2_INPUT_TYPE_CAMERA;
> +	strlcpy(i->name, "Camera", sizeof(i->name));
> +
> +	return 0;
> +}
> +
> +static const struct v4l2_ioctl_ops rvin_mc_ioctl_ops = {
> +	.vidioc_querycap		= rvin_querycap,
> +	.vidioc_try_fmt_vid_cap		= rvin_mc_try_fmt_vid_cap,
> +	.vidioc_g_fmt_vid_cap		= rvin_g_fmt_vid_cap,
> +	.vidioc_s_fmt_vid_cap		= rvin_mc_s_fmt_vid_cap,
> +	.vidioc_enum_fmt_vid_cap	= rvin_enum_fmt_vid_cap,
> +
> +	.vidioc_enum_input		= rvin_mc_enum_input,
> +	.vidioc_g_input			= rvin_g_input,
> +	.vidioc_s_input			= rvin_s_input,
> +
> +	.vidioc_reqbufs			= vb2_ioctl_reqbufs,
> +	.vidioc_create_bufs		= vb2_ioctl_create_bufs,
> +	.vidioc_querybuf		= vb2_ioctl_querybuf,
> +	.vidioc_qbuf			= vb2_ioctl_qbuf,
> +	.vidioc_dqbuf			= vb2_ioctl_dqbuf,
> +	.vidioc_expbuf			= vb2_ioctl_expbuf,
> +	.vidioc_prepare_buf		= vb2_ioctl_prepare_buf,
> +	.vidioc_streamon		= vb2_ioctl_streamon,
> +	.vidioc_streamoff		= vb2_ioctl_streamoff,
> +
> +	.vidioc_log_status		= v4l2_ctrl_log_status,
> +	.vidioc_subscribe_event		= rvin_subscribe_event,
> +	.vidioc_unsubscribe_event	= v4l2_event_unsubscribe,
> +};
> +
>  /* ------------------------------------------------------------------------
>   * File Operations
>   */
> @@ -841,6 +921,60 @@ static const struct v4l2_file_operations rvin_fops = {
>  	.read		= vb2_fop_read,
>  };
> 
> +/* ------------------------------------------------------------------------
> + * Media controller file operations
> + */
> +
> +static int rvin_mc_open(struct file *file)
> +{
> +	struct rvin_dev *vin = video_drvdata(file);
> +	int ret;
> +
> +	mutex_lock(&vin->lock);

Would it make sense to use mutex_lock_interruptible() ?

> +
> +	file->private_data = vin;
> +
> +	ret = v4l2_fh_open(file);
> +	if (ret)
> +		goto unlock;
> +
> +	pm_runtime_get_sync(vin->dev);

No need for error checking ?

> +	v4l2_pipeline_pm_use(&vin->vdev.entity, 1);

Same question.

> +unlock:
> +	mutex_unlock(&vin->lock);
> +
> +	return ret;
> +}
> +
> +static int rvin_mc_release(struct file *file)
> +{
> +	struct rvin_dev *vin = video_drvdata(file);
> +	int ret;
> +
> +	mutex_lock(&vin->lock);
> +
> +	/* the release helper will cleanup any on-going streaming */
> +	ret = _vb2_fop_release(file, NULL);
> +
> +	v4l2_pipeline_pm_use(&vin->vdev.entity, 0);
> +	pm_runtime_put(vin->dev);
> +
> +	mutex_unlock(&vin->lock);
> +
> +	return ret;
> +}
> +
> +static const struct v4l2_file_operations rvin_mc_fops = {
> +	.owner		= THIS_MODULE,
> +	.unlocked_ioctl	= video_ioctl2,
> +	.open		= rvin_mc_open,
> +	.release	= rvin_mc_release,
> +	.poll		= vb2_fop_poll,
> +	.mmap		= vb2_fop_mmap,
> +	.read		= vb2_fop_read,
> +};
> +
>  void rvin_v4l2_unregister(struct rvin_dev *vin)
>  {
>  	if (!video_is_registered(&vin->vdev))
> @@ -876,18 +1010,33 @@ int rvin_v4l2_register(struct rvin_dev *vin)
>  	vin->v4l2_dev.notify = rvin_notify;
> 
>  	/* video node */
> -	vdev->fops = &rvin_fops;
>  	vdev->v4l2_dev = &vin->v4l2_dev;
>  	vdev->queue = &vin->queue;
>  	strlcpy(vdev->name, KBUILD_MODNAME, sizeof(vdev->name));
>  	vdev->release = video_device_release_empty;
> -	vdev->ioctl_ops = &rvin_ioctl_ops;
>  	vdev->lock = &vin->lock;
>  	vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING |
>  		V4L2_CAP_READWRITE;
> 
> +	/* Set a default format */
>  	vin->format.pixelformat	= RVIN_DEFAULT_FORMAT;
> -	rvin_reset_format(vin);
> +	vin->format.width = RVIN_DEFAULT_WIDTH;
> +	vin->format.height = RVIN_DEFAULT_HEIGHT;
> +	vin->format.field = RVIN_DEFAULT_FIELD;
> +	vin->format.colorspace = RVIN_DEFAULT_COLORSPACE;
> +
> +	if (vin->info->use_mc) {
> +		vdev->fops = &rvin_mc_fops;
> +		vdev->ioctl_ops = &rvin_mc_ioctl_ops;
> +	} else {
> +		vdev->fops = &rvin_fops;
> +		vdev->ioctl_ops = &rvin_ioctl_ops;
> +		rvin_reset_format(vin);
> +	}
> +
> +	ret = rvin_format_align(vin, &vin->format);
> +	if (ret)
> +		return ret;
> 
>  	ret = video_register_device(&vin->vdev, VFL_TYPE_GRABBER, -1);
>  	if (ret) {

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v10 21/30] rcar-vin: prepare for media controller mode initialization
  2018-01-29 16:34 ` [PATCH v10 21/30] rcar-vin: prepare for media controller mode initialization Niklas Söderlund
@ 2018-02-13 19:47   ` Laurent Pinchart
  0 siblings, 0 replies; 65+ messages in thread
From: Laurent Pinchart @ 2018-02-13 19:47 UTC (permalink / raw)
  To: Niklas Söderlund
  Cc: Hans Verkuil, linux-media, linux-renesas-soc, tomoharu.fukawa.eb,
	Kieran Bingham

Hi Niklas,

Thank you for the patch.

On Monday, 29 January 2018 18:34:26 EET Niklas Söderlund wrote:
> Prepare for media controller by calling a different initialization then
> for when running in device centric mode. Add trivial configuration of

s/then for when/than when/

> the mbus and creation of the media pad for the video device entity.
> 
> While we are at it clearly mark the digital device centric notifier
> functions with a comment.
> 
> Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
> Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>

Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

> ---
>  drivers/media/platform/rcar-vin/rcar-core.c | 20 ++++++++++++++++++--
>  drivers/media/platform/rcar-vin/rcar-vin.h  |  4 ++++
>  2 files changed, 22 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/media/platform/rcar-vin/rcar-core.c
> b/drivers/media/platform/rcar-vin/rcar-core.c index
> 64034c96f384b3ed..0c6960756c33f86c 100644
> --- a/drivers/media/platform/rcar-vin/rcar-core.c
> +++ b/drivers/media/platform/rcar-vin/rcar-core.c
> @@ -46,6 +46,10 @@ static int rvin_find_pad(struct v4l2_subdev *sd, int
> direction) return -EINVAL;
>  }
> 
> +/* ------------------------------------------------------------------------
> + * Digital async notifier
> + */
> +
>  /* The vin lock shuld be held when calling the subdevice attach and detach
> */ static int rvin_digital_subdevice_attach(struct rvin_dev *vin,
>  					 struct v4l2_subdev *subdev)
> @@ -237,6 +241,16 @@ static int rvin_digital_graph_init(struct rvin_dev
> *vin) return 0;
>  }
> 
> +static int rvin_mc_init(struct rvin_dev *vin)
> +{
> +	/* All our sources are CSI-2 */
> +	vin->mbus_cfg.type = V4L2_MBUS_CSI2;
> +	vin->mbus_cfg.flags = 0;
> +
> +	vin->pad.flags = MEDIA_PAD_FL_SINK;
> +	return media_entity_pads_init(&vin->vdev.entity, 1, &vin->pad);
> +}
> +
>  /* ------------------------------------------------------------------------
>   * Platform Device Driver
>   */
> @@ -325,8 +339,10 @@ static int rcar_vin_probe(struct platform_device *pdev)
> return ret;
> 
>  	platform_set_drvdata(pdev, vin);
> -
> -	ret = rvin_digital_graph_init(vin);
> +	if (vin->info->use_mc)
> +		ret = rvin_mc_init(vin);
> +	else
> +		ret = rvin_digital_graph_init(vin);
>  	if (ret < 0)
>  		goto error;
> 
> diff --git a/drivers/media/platform/rcar-vin/rcar-vin.h
> b/drivers/media/platform/rcar-vin/rcar-vin.h index
> 64476bc5c8abc6d0..4caef7193db09c5b 100644
> --- a/drivers/media/platform/rcar-vin/rcar-vin.h
> +++ b/drivers/media/platform/rcar-vin/rcar-vin.h
> @@ -101,6 +101,8 @@ struct rvin_info {
>   * @notifier:		V4L2 asynchronous subdevs notifier
>   * @digital:		entity in the DT for local digital subdevice
>   *
> + * @pad:		media pad for the video device entity
> + *
>   * @lock:		protects @queue
>   * @queue:		vb2 buffers queue
>   *
> @@ -130,6 +132,8 @@ struct rvin_dev {
>  	struct v4l2_async_notifier notifier;
>  	struct rvin_graph_entity *digital;
> 
> +	struct media_pad pad;
> +
>  	struct mutex lock;
>  	struct vb2_queue queue;

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v10 22/30] rcar-vin: add group allocator functions
  2018-01-29 16:34 ` [PATCH v10 22/30] rcar-vin: add group allocator functions Niklas Söderlund
@ 2018-02-13 20:09   ` Laurent Pinchart
  0 siblings, 0 replies; 65+ messages in thread
From: Laurent Pinchart @ 2018-02-13 20:09 UTC (permalink / raw)
  To: Niklas Söderlund
  Cc: Hans Verkuil, linux-media, linux-renesas-soc, tomoharu.fukawa.eb,
	Kieran Bingham

Hi Niklas,

Thank you for the patch.

On Monday, 29 January 2018 18:34:27 EET Niklas Söderlund wrote:
> In media controller mode all VIN instances needs to be part of the same
> media graph. There is also a need for each VIN instance to know about
> and in some cases be able to communicate with other VIN instances.
> 
> Add an allocator framework where the first VIN instance to be probed
> creates a shared data structure and registers a media device.
> Consecutive VINs insert themself into the global group.
> 
> Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
> ---
>  drivers/media/platform/rcar-vin/rcar-core.c | 177 ++++++++++++++++++++++++-
>  drivers/media/platform/rcar-vin/rcar-vin.h  |  31 +++++
>  2 files changed, 206 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/media/platform/rcar-vin/rcar-core.c
> b/drivers/media/platform/rcar-vin/rcar-core.c index
> 0c6960756c33f86c..4a64df5019ce45f7 100644
> --- a/drivers/media/platform/rcar-vin/rcar-core.c
> +++ b/drivers/media/platform/rcar-vin/rcar-core.c
> @@ -20,12 +20,177 @@
>  #include <linux/of_graph.h>
>  #include <linux/platform_device.h>
>  #include <linux/pm_runtime.h>
> +#include <linux/slab.h>
> 
>  #include <media/v4l2-async.h>
>  #include <media/v4l2-fwnode.h>
> 
>  #include "rcar-vin.h"
> 
> +/* ------------------------------------------------------------------------
> + * Gen3 CSI2 Group Allocator
> + */
> +
> +/* FIXME:  This should if we find a system that supports more
> + * then one group for the whole system be replaced with a linked

s/then/than/

> + * list of groups. And eventually all of this should be replaced
> + * with a global device allocator API.
> + *
> + * But for now this works as on all supported systems there will
> + * be only one group for all instances.
> + */
> +
> +static DEFINE_MUTEX(rvin_group_lock);
> +static struct rvin_group *rvin_group_data;
> +
> +static void rvin_group_cleanup(struct rvin_group *group)
> +{
> +	media_device_unregister(&group->mdev);
> +	media_device_cleanup(&group->mdev);
> +	mutex_destroy(&group->lock);
> +}
> +
> +static int rvin_group_init(struct rvin_group *group, struct rvin_dev *vin)
> +{
> +	struct media_device *mdev = &group->mdev;
> +	const struct of_device_id *match;
> +	struct device_node *np;
> +	int ret;
> +
> +	mutex_init(&group->lock);
> +
> +	/* Count number of VINs in the system */
> +	group->count = 0;
> +	for_each_matching_node(np, vin->dev->driver->of_match_table)
> +		if (of_device_is_available(np))
> +			group->count++;
> +
> +	vin_dbg(vin, "found %u enabled VIN's in DT", group->count);
> +
> +	mdev->dev = vin->dev;
> +
> +	match = of_match_node(vin->dev->driver->of_match_table,
> +			      vin->dev->of_node);
> +
> +	strlcpy(mdev->driver_name, KBUILD_MODNAME, sizeof(mdev->driver_name));
> +	strlcpy(mdev->model, match->compatible, sizeof(mdev->model));
> +	snprintf(mdev->bus_info, sizeof(mdev->bus_info), "platform:%s",
> +		 dev_name(mdev->dev));
> +
> +	media_device_init(mdev);
> +
> +	ret = media_device_register(&group->mdev);
> +	if (ret)
> +		rvin_group_cleanup(group);
> +
> +	return ret;
> +}
> +
> +static void rvin_group_release(struct kref *kref)
> +{
> +	struct rvin_group *group =
> +		container_of(kref, struct rvin_group, refcount);
> +
> +	mutex_lock(&rvin_group_lock);
> +
> +	rvin_group_data = NULL;
> +
> +	rvin_group_cleanup(group);
> +
> +	kfree(group);
> +
> +	mutex_unlock(&rvin_group_lock);
> +}
> +
> +static int rvin_group_get(struct rvin_dev *vin)
> +{
> +	struct rvin_group *group;
> +	u32 id;
> +	int ret;
> +
> +	/* Make sure VIN id is present and sane */
> +	ret = of_property_read_u32(vin->dev->of_node, "renesas,id", &id);
> +	if (ret) {
> +		vin_err(vin, "%pOF: No renesas,id property found\n",
> +			vin->dev->of_node);
> +		return -EINVAL;
> +	}
> +
> +	if (id >= RCAR_VIN_NUM) {
> +		vin_err(vin, "%pOF: Invalid renesas,id '%u'\n",
> +			vin->dev->of_node, id);
> +		return -EINVAL;
> +	}

I'd move this out of this function to an OF parsing function, but we don't 
have one yet. Something to keep in mind for later.

> +	/* Join or create a VIN group */
> +	mutex_lock(&rvin_group_lock);
> +	if (rvin_group_data) {
> +		group = rvin_group_data;
> +		kref_get(&group->refcount);
> +	} else {
> +		group = kzalloc(sizeof(*group), GFP_KERNEL);
> +		if (!group) {
> +			ret = -ENOMEM;
> +			goto err_group;
> +		}
> +
> +		ret = rvin_group_init(group, vin);
> +		if (ret) {
> +			kfree(group);
> +			vin_err(vin, "Failed to initialize group\n");
> +			goto err_group;
> +		}
> +
> +		kref_init(&group->refcount);
> +
> +		rvin_group_data = group;
> +	}
> +	mutex_unlock(&rvin_group_lock);
> +
> +	/* Add VIN to group */
> +	mutex_lock(&group->lock);
> +
> +	if (group->vin[id]) {
> +		vin_err(vin, "Duplicate renesas,id property value %u\n", id);
> +		ret = -EINVAL;
> +		goto err_vin;
> +	}
> +
> +	group->vin[id] = vin;
> +
> +	vin->id = id;
> +	vin->group = group;
> +	vin->v4l2_dev.mdev = &group->mdev;
> +
> +	mutex_unlock(&group->lock);
> +
> +	return 0;
> +err_group:
> +	mutex_unlock(&rvin_group_lock);
> +	return ret;
> +err_vin:
> +	mutex_unlock(&group->lock);
> +	kref_put(&group->refcount, rvin_group_release);
> +	return ret;

This error handling path is used from a single location, you can inline it.

> +}
> +
> +static void rvin_group_put(struct rvin_dev *vin)
> +{
> +	mutex_lock(&vin->group->lock);
> +
> +	vin->group = NULL;
> +	vin->v4l2_dev.mdev = NULL;
> +
> +	if (WARN_ON(vin->group->vin[vin->id] != vin))
> +		goto out;
> +
> +	vin->group->vin[vin->id] = NULL;
> +out:
> +	mutex_unlock(&vin->group->lock);
> +
> +	kref_put(&vin->group->refcount, rvin_group_release);
> +}
> +
>  /* ------------------------------------------------------------------------
>   * Async notifier
>   */
> @@ -243,12 +408,18 @@ static int rvin_digital_graph_init(struct rvin_dev
> *vin)
> 
>  static int rvin_mc_init(struct rvin_dev *vin)
>  {
> +	int ret;
> +
>  	/* All our sources are CSI-2 */
>  	vin->mbus_cfg.type = V4L2_MBUS_CSI2;
>  	vin->mbus_cfg.flags = 0;
> 
>  	vin->pad.flags = MEDIA_PAD_FL_SINK;
> -	return media_entity_pads_init(&vin->vdev.entity, 1, &vin->pad);
> +	ret = media_entity_pads_init(&vin->vdev.entity, 1, &vin->pad);
> +	if (ret)
> +		return ret;
> +
> +	return rvin_group_get(vin);
>  }
> 
>  /* ------------------------------------------------------------------------
> @@ -368,7 +539,9 @@ static int rcar_vin_remove(struct platform_device
> *pdev) v4l2_async_notifier_unregister(&vin->notifier);
>  	v4l2_async_notifier_cleanup(&vin->notifier);
> 
> -	if (!vin->info->use_mc)
> +	if (vin->info->use_mc)
> +		rvin_group_put(vin);
> +	else
>  		v4l2_ctrl_handler_free(&vin->ctrl_handler);
> 
>  	rvin_dma_unregister(vin);
> diff --git a/drivers/media/platform/rcar-vin/rcar-vin.h
> b/drivers/media/platform/rcar-vin/rcar-vin.h index
> 4caef7193db09c5b..903d8fb8426a7860 100644
> --- a/drivers/media/platform/rcar-vin/rcar-vin.h
> +++ b/drivers/media/platform/rcar-vin/rcar-vin.h
> @@ -17,6 +17,8 @@
>  #ifndef __RCAR_VIN__
>  #define __RCAR_VIN__
> 
> +#include <linux/kref.h>
> +
>  #include <media/v4l2-async.h>
>  #include <media/v4l2-ctrls.h>
>  #include <media/v4l2-dev.h>
> @@ -29,6 +31,11 @@
>  /* Address alignment mask for HW buffers */
>  #define HW_BUFFER_MASK 0x7f
> 
> +/* Max number on VIN instances that can be in a system */
> +#define RCAR_VIN_NUM 8
> +
> +struct rvin_group;
> +
>  enum model_id {
>  	RCAR_H1,
>  	RCAR_M1,
> @@ -101,6 +108,8 @@ struct rvin_info {
>   * @notifier:		V4L2 asynchronous subdevs notifier
>   * @digital:		entity in the DT for local digital subdevice
>   *
> + * @group:		Gen3 CSI group
> + * @id:			Gen3 group id for this VIN
>   * @pad:		media pad for the video device entity
>   *
>   * @lock:		protects @queue
> @@ -132,6 +141,8 @@ struct rvin_dev {
>  	struct v4l2_async_notifier notifier;
>  	struct rvin_graph_entity *digital;
> 
> +	struct rvin_group *group;
> +	unsigned char id;

You can use an unsigned int, the compiler would pad the field anyway.

>  	struct media_pad pad;
> 
>  	struct mutex lock;
> @@ -160,6 +171,26 @@ struct rvin_dev {
>  #define vin_warn(d, fmt, arg...)	dev_warn(d->dev, fmt, ##arg)
>  #define vin_err(d, fmt, arg...)		dev_err(d->dev, fmt, ##arg)
> 
> +/**
> + * struct rvin_group - VIN CSI2 group information
> + * @refcount:		number of VIN instances using the group
> + *
> + * @mdev:		media device which represents the group
> + *
> + * @lock:		protects the count and vin members
> + * @count:		number of enabled VIN instances found in DT
> + * @vin:		VIN instances which are part of the group
> + */
> +struct rvin_group {
> +	struct kref refcount;
> +
> +	struct media_device mdev;
> +
> +	struct mutex lock;
> +	unsigned int count;
> +	struct rvin_dev *vin[RCAR_VIN_NUM];
> +};
> +
>  int rvin_dma_register(struct rvin_dev *vin, int irq);
>  void rvin_dma_unregister(struct rvin_dev *vin);

With these small issues fixed,

Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v10 23/30] rcar-vin: change name of video device
  2018-01-29 16:34 ` [PATCH v10 23/30] rcar-vin: change name of video device Niklas Söderlund
@ 2018-02-13 20:10   ` Laurent Pinchart
  0 siblings, 0 replies; 65+ messages in thread
From: Laurent Pinchart @ 2018-02-13 20:10 UTC (permalink / raw)
  To: Niklas Söderlund
  Cc: Hans Verkuil, linux-media, linux-renesas-soc, tomoharu.fukawa.eb,
	Kieran Bingham

Hi Niklas,

Thank you for the patch.

On Monday, 29 January 2018 18:34:28 EET Niklas Söderlund wrote:
> The rcar-vin driver needs to be part of a media controller to support
> Gen3. Give each VIN instance a unique name so it can be referenced from
> userspace.
> 
> Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>

Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

> ---
>  drivers/media/platform/rcar-vin/rcar-v4l2.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/media/platform/rcar-vin/rcar-v4l2.c
> b/drivers/media/platform/rcar-vin/rcar-v4l2.c index
> 292e1f22a4be36c7..3ac6cdcb18ce4a21 100644
> --- a/drivers/media/platform/rcar-vin/rcar-v4l2.c
> +++ b/drivers/media/platform/rcar-vin/rcar-v4l2.c
> @@ -1012,7 +1012,7 @@ int rvin_v4l2_register(struct rvin_dev *vin)
>  	/* video node */
>  	vdev->v4l2_dev = &vin->v4l2_dev;
>  	vdev->queue = &vin->queue;
> -	strlcpy(vdev->name, KBUILD_MODNAME, sizeof(vdev->name));
> +	snprintf(vdev->name, sizeof(vdev->name), "VIN%u output", vin->id);
>  	vdev->release = video_device_release_empty;
>  	vdev->lock = &vin->lock;
>  	vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING |


-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v10 24/30] rcar-vin: add chsel information to rvin_info
  2018-01-29 16:34 ` [PATCH v10 24/30] rcar-vin: add chsel information to rvin_info Niklas Söderlund
@ 2018-02-13 20:19   ` Laurent Pinchart
  0 siblings, 0 replies; 65+ messages in thread
From: Laurent Pinchart @ 2018-02-13 20:19 UTC (permalink / raw)
  To: Niklas Söderlund
  Cc: Hans Verkuil, linux-media, linux-renesas-soc, tomoharu.fukawa.eb,
	Kieran Bingham

Hi Niklas,

Thank you for the patch.

On Monday, 29 January 2018 18:34:29 EET Niklas Söderlund wrote:
> Each Gen3 SoC has a limited set of predefined routing possibilities for
> which CSI-2 device and virtual channel can be routed to which VIN
> instance. Prepare to store this information in the struct rvin_info.
> 
> Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
> ---
>  drivers/media/platform/rcar-vin/rcar-vin.h | 30 +++++++++++++++++++++++++++
>  1 file changed, 30 insertions(+)
> 
> diff --git a/drivers/media/platform/rcar-vin/rcar-vin.h
> b/drivers/media/platform/rcar-vin/rcar-vin.h index
> 903d8fb8426a7860..ca2c2a23cef8506c 100644
> --- a/drivers/media/platform/rcar-vin/rcar-vin.h
> +++ b/drivers/media/platform/rcar-vin/rcar-vin.h
> @@ -43,6 +43,14 @@ enum model_id {
>  	RCAR_GEN3,
>  };
> 
> +enum rvin_csi_id {
> +	RVIN_CSI20,
> +	RVIN_CSI21,
> +	RVIN_CSI40,
> +	RVIN_CSI41,
> +	RVIN_CSI_MAX,
> +};
> +
>  /**
>   * STOPPED  - No operation in progress
>   * RUNNING  - Operation in progress have buffers
> @@ -81,12 +89,33 @@ struct rvin_graph_entity {
>  	unsigned int sink_pad;
>  };
> 
> +/** struct rvin_group_route - Map a CSI-2 receiver and channel to a CHSEL

If my understanding is correct an entry describes a route from a channel of a 
CSI-2 receiver to a VIN, and how to configure the hardware to enable that 
route (in the mask field). Could you expand this single line of documentation 
to explain that more clearly ?

> + * @vin:		Which VIN the CSI-2 and VC describes

VC ? Is that virtual channel ? Isn't that internal to the CSI-2 receiver only 
?

> + * @csi:		VIN internal number for CSI-2 device

Or just "CSI-2 receiver ID" ?

> + * @chan:		Output channel of the CSI-2 receiver. Each R-Car CSI-2

Would "channel" be too long ?

> + *			receiver has four output channels facing the VIN
> + *			devices, each channel can carry one CSI-2 Virtual
> + *			Channel (VC) and there are no correlation between
> + *			output channel number and CSI-2 VC. It's up to the
> + *			CSI-2 receiver driver to configure which VC is
> + *			outputted on which channel, the VIN devices only

s/outputted/output/

> + *			cares about output channels.

s/cares/care/

> + * @mask:		Bitmask of chsel values which accommodates route

s/which/that/

Reading the documentation I'm not sure to understand how this works. In 
particular the mask field documentation isn't clear enough.

> + */
> +struct rvin_group_route {
> +	unsigned int vin;
> +	enum rvin_csi_id csi;
> +	unsigned char chan;

You can make this an unsigned int, the compiler will pad the field anyway.

I think it would be clearer to order the fields in "from -> to: configuration" 
order (csi, channel, vin, mask).

> +	unsigned int mask;
> +};
> +
>  /**
>   * struct rvin_info - Information about the particular VIN implementation
>   * @model:		VIN model
>   * @use_mc:		use media controller instead of controlling subdevice
>   * @max_width:		max input width the VIN supports
>   * @max_height:		max input height the VIN supports
> + * @routes:		routing table VIN <-> CSI-2 for the chsel values
>   */
>  struct rvin_info {
>  	enum model_id model;
> @@ -94,6 +123,7 @@ struct rvin_info {
> 
>  	unsigned int max_width;
>  	unsigned int max_height;
> +	const struct rvin_group_route *routes;
>  };
> 
>  /**

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v10 25/30] rcar-vin: parse Gen3 OF and setup media graph
  2018-01-29 16:34 ` [PATCH v10 25/30] rcar-vin: parse Gen3 OF and setup media graph Niklas Söderlund
@ 2018-02-13 21:01   ` Laurent Pinchart
  0 siblings, 0 replies; 65+ messages in thread
From: Laurent Pinchart @ 2018-02-13 21:01 UTC (permalink / raw)
  To: Niklas Söderlund
  Cc: Hans Verkuil, linux-media, linux-renesas-soc, tomoharu.fukawa.eb,
	Kieran Bingham

Hi Niklas,

Thank you for the patch.

On Monday, 29 January 2018 18:34:30 EET Niklas Söderlund wrote:
> The parsing and registering CSI-2 subdevices with the v4l2 async
> framework is a collaborative effort shared between the VIN instances
> which are part of the group. When the last VIN in the group is probed it
> asks all other VINs to parse its share of OF and record the async
> subdevices it finds in the notifier belonging to the last probed VIN.
> 
> Once all CSI-2 subdevices in this notifier are bound proceed to register
> all VIN video devices of the group and crate media device links between
> all CSI-2 and VIN entities according to the SoC specific routing
> configuration.
> 
> Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
> ---
>  drivers/media/platform/rcar-vin/rcar-core.c | 250 ++++++++++++++++++++++++-
>  drivers/media/platform/rcar-vin/rcar-vin.h  |  12 +-
>  2 files changed, 258 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/media/platform/rcar-vin/rcar-core.c
> b/drivers/media/platform/rcar-vin/rcar-core.c index
> 4a64df5019ce45f7..f08277a0dc11f477 100644
> --- a/drivers/media/platform/rcar-vin/rcar-core.c
> +++ b/drivers/media/platform/rcar-vin/rcar-core.c
> @@ -27,6 +27,23 @@
> 
>  #include "rcar-vin.h"
> 
> +/*
> + * The companion CSI-2 receiver driver (rcar-csi2) is known
> + * and we know it have one source pad (pad 0) and four sink

s/have/has/

> + * pads (pad 1-4). So to translate a pad on the remote
> + * CSI-2 receiver to/from the VIN internal channel number simply
> + * subtract/add or one from the pad/chan number.

s/or one/one/

and maybe s/chan/channel/ ?

> + */
> +#define rvin_group_csi_pad_to_chan(pad) ((pad) - 1)
> +#define rvin_group_csi_chan_to_pad(chan) ((chan) + 1)
> +
> +/*
> + * Not all VINs are created equal, master VINs control the
> + * routing for other VIN's. We can figure out which VIN is
> + * master by looking at a VINs id
> + */
> +#define rvin_group_id_to_master(vin) ((vin) < 4 ? 0 : 4)
> +
>  /* ------------------------------------------------------------------------
>   * Gen3 CSI2 Group Allocator
>   */
> @@ -77,6 +94,8 @@ static int rvin_group_init(struct rvin_group *group,
> struct rvin_dev *vin) snprintf(mdev->bus_info, sizeof(mdev->bus_info),
> "platform:%s",
>  		 dev_name(mdev->dev));
> 
> +	group->notifier = NULL;
> +

The group has been allocated with kzalloc() so this isn't necessary.

>  	media_device_init(mdev);
> 
>  	ret = media_device_register(&group->mdev);
> @@ -406,6 +425,218 @@ static int rvin_digital_graph_init(struct rvin_dev
> *vin) return 0;
>  }
> 
> +/* ------------------------------------------------------------------------
> + * Group async notifier
> + */
> +
> +static int rvin_group_notify_complete(struct v4l2_async_notifier *notifier)
> +{
> +	struct rvin_dev *vin = notifier_to_vin(notifier);
> +	const struct rvin_group_route *route;
> +	unsigned int i;
> +	int ret;
> +
> +	ret = v4l2_device_register_subdev_nodes(&vin->v4l2_dev);
> +	if (ret) {
> +		vin_err(vin, "Failed to register subdev nodes\n");
> +		return ret;
> +	}
> +
> +	/* Register all video nodes for the group */
> +	for (i = 0; i < RCAR_VIN_NUM; i++) {
> +		if (vin->group->vin[i]) {
> +			ret = rvin_v4l2_register(vin->group->vin[i]);
> +			if (ret)
> +				return ret;
> +		}
> +	}
> +
> +	/* Create all media device links between VINs and CSI-2's */
> +	mutex_lock(&vin->group->lock);
> +	for (route = vin->info->routes; route->mask; route++) {
> +		struct media_pad *source_pad, *sink_pad;
> +		struct media_entity *source, *sink;
> +		unsigned int source_idx;
> +
> +		/* Check that VIN is part of the group */
> +		if (!vin->group->vin[route->vin])
> +			continue;
> +
> +		/* Check that VIN' master is part of the group */
> +		if (!vin->group->vin[rvin_group_id_to_master(route->vin)])
> +			continue;
> +
> +		/* Check that CSI-2 is part of the group */
> +		if (!vin->group->csi[route->csi].subdev)
> +			continue;
> +
> +		source = &vin->group->csi[route->csi].subdev->entity;
> +		source_idx = rvin_group_csi_chan_to_pad(route->chan);
> +		source_pad = &source->pads[source_idx];
> +
> +		sink = &vin->group->vin[route->vin]->vdev.entity;
> +		sink_pad = &sink->pads[0];
> +
> +		/* Skip if link already exists */
> +		if (media_entity_find_link(source_pad, sink_pad))
> +			continue;
> +
> +		ret = media_create_pad_link(source, source_idx, sink, 0, 0);
> +		if (ret) {
> +			vin_err(vin, "Error adding link from %s to %s\n",
> +				source->name, sink->name);
> +			break;
> +		}
> +	}
> +	mutex_unlock(&vin->group->lock);
> +
> +	return ret;
> +}
> +
> +static void rvin_group_notify_unbind(struct v4l2_async_notifier *notifier,
> +				     struct v4l2_subdev *subdev,
> +				     struct v4l2_async_subdev *asd)
> +{
> +	struct rvin_dev *vin = notifier_to_vin(notifier);
> +	unsigned int i;
> +
> +	for (i = 0; i < RCAR_VIN_NUM; i++)
> +		if (vin->group->vin[i])
> +			rvin_v4l2_unregister(vin->group->vin[i]);
> +
> +	mutex_lock(&vin->group->lock);
> +
> +	for (i = 0; i < RVIN_CSI_MAX; i++) {
> +		if (vin->group->csi[i].fwnode != asd->match.fwnode)
> +			continue;
> +		vin->group->csi[i].subdev = NULL;
> +		vin_dbg(vin, "Unbind CSI-2 %s from slot %u\n", subdev->name, i);
> +		break;
> +	}
> +
> +	mutex_unlock(&vin->group->lock);
> +}
> +
> +static int rvin_group_notify_bound(struct v4l2_async_notifier *notifier,
> +				   struct v4l2_subdev *subdev,
> +				   struct v4l2_async_subdev *asd)
> +{
> +	struct rvin_dev *vin = notifier_to_vin(notifier);
> +	unsigned int i;
> +
> +	mutex_lock(&vin->group->lock);
> +
> +	for (i = 0; i < RVIN_CSI_MAX; i++) {
> +		if (vin->group->csi[i].fwnode != asd->match.fwnode)
> +			continue;
> +		vin->group->csi[i].subdev = subdev;
> +		vin_dbg(vin, "Bound CSI-2 %s to slot %u\n", subdev->name, i);
> +		break;
> +	}
> +
> +	mutex_unlock(&vin->group->lock);
> +
> +	return 0;
> +}
> +
> +static const struct v4l2_async_notifier_operations rvin_group_notify_ops =
> {
> +	.bound = rvin_group_notify_bound,
> +	.unbind = rvin_group_notify_unbind,
> +	.complete = rvin_group_notify_complete,
> +};
> +
> +static int rvin_mc_parse_v4l2(struct device *dev,
> +				   struct v4l2_fwnode_endpoint *vep,
> +				   struct v4l2_async_subdev *asd)

As this parses one endpoint, maybe rvin_mc_parse_of_endpoint() ?

> +{
> +	struct rvin_dev *vin = dev_get_drvdata(dev);
> +	struct v4l2_async_notifier *notifier = vin->group->notifier;
> +	unsigned int i;
> +
> +	if (vep->base.port != 1 || vep->base.id >= RVIN_CSI_MAX)
> +		return -EINVAL;
> +
> +	if (!of_device_is_available(to_of_node(asd->match.fwnode))) {
> +		vin_dbg(vin, "Subdevice %pOF disabled, ignoring\n",
> +			to_of_node(asd->match.fwnode));

It's not the subdevice that is disabled, it's the OF node, so I'd write this 
"OF device %pOF disabled, ignoring".

> +		return -ENOTCONN;
> +
> +	}
> +
> +	for (i = 0; i < notifier->num_subdevs; i++) {
> +		if (notifier->subdevs[i]->match.fwnode == asd->match.fwnode) {
> +			vin_dbg(vin, "Subdevice %pOF already handled\n",
> +				to_of_node(asd->match.fwnode));

Ditto.

> +			return -ENOTCONN;
> +		}
> +	}

Do you need a loop, or could you just test if vin->group->csi[vep-
>base.id].fwnode is non-NULL ?

> +	vin->group->csi[vep->base.id].fwnode = asd->match.fwnode;
> +
> +	vin_dbg(vin, "Add group subdevice %pOF to slot %u\n",
> +		to_of_node(asd->match.fwnode), vep->base.id);

And here too.

> +	return 0;
> +}
> +
> +static int rvin_mc_try_parse(struct rvin_dev *vin)

"try" parse ? Do you really expect this to be so difficult that we'll likely 
fail ? :-) How about rvin_mc_parse_of_graph() ?

> +{
> +	unsigned int i, count = 0;

I'd split that on two lines.

> +	int ret;
> +
> +	mutex_lock(&vin->group->lock);
> +
> +	/* If there already is a notifier something have gone wrong, bail */

s/have/has/

and I assume you mean "bail out", not "bail".

> +	if (WARN_ON(vin->group->notifier)) {
> +		mutex_unlock(&vin->group->lock);
> +		return -EINVAL;
> +	}
> +
> +	/* If not all VIN's are registered don't register the notifier */
> +	for (i = 0; i < RCAR_VIN_NUM; i++)
> +		if (vin->group->vin[i])
> +			count++;
> +
> +	if (vin->group->count != count) {
> +		mutex_unlock(&vin->group->lock);
> +		return 0;
> +	}
> +
> +	/*
> +	 * Have all VIN's look for subdevices. Some subdevices will overlap
> +	 * but the parser function can handle it, so each subdevice will
> +	 * only be registered once with the notifier

Do you have anything particular against periods at end of sentences (and this 
also applies to single-sentence comments) ? If not, this comment applies to 
the whole series.

> +	 */
> +
> +	vin->group->notifier = &vin->notifier;
> +
> +	for (i = 0; i < RCAR_VIN_NUM; i++) {
> +		if (!vin->group->vin[i])
> +			continue;
> +
> +		ret = v4l2_async_notifier_parse_fwnode_endpoints_by_port(
> +				vin->group->vin[i]->dev, vin->group->notifier,
> +				sizeof(struct v4l2_async_subdev), 1,
> +				rvin_mc_parse_v4l2);
> +		if (ret) {
> +			mutex_unlock(&vin->group->lock);
> +			return ret;
> +		}
> +	}

I'll refrain from telling how much this makes me want to cry. I know we have 
no other choice for now, but still :(

> +	mutex_unlock(&vin->group->lock);
> +
> +	vin->group->notifier->ops = &rvin_group_notify_ops;
> +
> +	ret = v4l2_async_notifier_register(&vin->v4l2_dev, &vin->notifier);
> +	if (ret < 0) {
> +		vin_err(vin, "Notifier registration failed\n");
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
>  static int rvin_mc_init(struct rvin_dev *vin)
>  {
>  	int ret;
> @@ -419,7 +650,15 @@ static int rvin_mc_init(struct rvin_dev *vin)
>  	if (ret)
>  		return ret;
> 
> -	return rvin_group_get(vin);
> +	ret = rvin_group_get(vin);
> +	if (ret)
> +		return ret;
> +
> +	ret = rvin_mc_try_parse(vin);
> +	if (ret)
> +		rvin_group_put(vin);
> +
> +	return ret;
>  }
> 
>  /* ------------------------------------------------------------------------
> @@ -539,10 +778,15 @@ static int rcar_vin_remove(struct platform_device
> *pdev) v4l2_async_notifier_unregister(&vin->notifier);
>  	v4l2_async_notifier_cleanup(&vin->notifier);
> 
> -	if (vin->info->use_mc)
> +	if (vin->info->use_mc) {
> +		mutex_lock(&vin->group->lock);
> +		if (vin->group->notifier == &vin->notifier)
> +			vin->group->notifier = NULL;
> +		mutex_unlock(&vin->group->lock);
>  		rvin_group_put(vin);
> -	else
> +	} else {
>  		v4l2_ctrl_handler_free(&vin->ctrl_handler);
> +	}
> 
>  	rvin_dma_unregister(vin);
> 
> diff --git a/drivers/media/platform/rcar-vin/rcar-vin.h
> b/drivers/media/platform/rcar-vin/rcar-vin.h index
> ca2c2a23cef8506c..6cef78df42047c8c 100644
> --- a/drivers/media/platform/rcar-vin/rcar-vin.h
> +++ b/drivers/media/platform/rcar-vin/rcar-vin.h
> @@ -207,9 +207,13 @@ struct rvin_dev {
>   *
>   * @mdev:		media device which represents the group
>   *
> - * @lock:		protects the count and vin members
> + * @lock:		protects the count, notifier, vin and csi members
>   * @count:		number of enabled VIN instances found in DT
> + * @notifier:		pointer to the notifier of a VIN which handles the
> + *			groups async sub-devices.
>   * @vin:		VIN instances which are part of the group
> + * @csi:		array of pairs of fwnode and subdev pointers
> + *			to all CSI-2 subdevices.
>   */
>  struct rvin_group {
>  	struct kref refcount;
> @@ -218,7 +222,13 @@ struct rvin_group {
> 
>  	struct mutex lock;
>  	unsigned int count;
> +	struct v4l2_async_notifier *notifier;
>  	struct rvin_dev *vin[RCAR_VIN_NUM];
> +
> +	struct {
> +		struct fwnode_handle *fwnode;
> +		struct v4l2_subdev *subdev;
> +	} csi[RVIN_CSI_MAX];
>  };
> 
>  int rvin_dma_register(struct rvin_dev *vin, int irq);

With these small issues fixed,

Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

We clearly need a new review tag to tell "this is horrible but I agree to let 
it in" :-/

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v10 26/30] rcar-vin: add link notify for Gen3
  2018-01-29 16:34 ` [PATCH v10 26/30] rcar-vin: add link notify for Gen3 Niklas Söderlund
@ 2018-02-13 21:17   ` Laurent Pinchart
  0 siblings, 0 replies; 65+ messages in thread
From: Laurent Pinchart @ 2018-02-13 21:17 UTC (permalink / raw)
  To: Niklas Söderlund
  Cc: Hans Verkuil, linux-media, linux-renesas-soc, tomoharu.fukawa.eb,
	Kieran Bingham

Hi Niklas,

Thank you for the patch.

On Monday, 29 January 2018 18:34:31 EET Niklas Söderlund wrote:
> Add the ability to process media device link change request. Link
> enabling is a bit complicated on Gen3, whether or not it's possible to
> enable a link depends on what other links already are enabled. On Gen3
> the 8 VINs are split into two subgroup's (VIN0-3 and VIN4-7) and from a
> routing perspective these two groups are independent of each other.
> Each subgroup's routing is controlled by the subgroup VIN master
> instance (VIN0 and VIN4).
> 
> There are a limited number of possible route setups available for each
> subgroup and the configuration of each setup is dictated by the
> hardware. On H3 for example there are 6 possible route setups for each
> subgroup to choose from.
> 
> This leads to the media device link notification code being rather large
> since it will find the best routing configuration to try and accommodate
> as many links as possible. When it's not possible to enable a new link
> due to hardware constrains the link_notifier callback will return
> -EMLINK.
> 
> Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
> ---
>  drivers/media/platform/rcar-vin/rcar-core.c | 129 +++++++++++++++++++++++++
>  1 file changed, 129 insertions(+)
> 
> diff --git a/drivers/media/platform/rcar-vin/rcar-core.c
> b/drivers/media/platform/rcar-vin/rcar-core.c index
> f08277a0dc11f477..7ceff0de40078580 100644
> --- a/drivers/media/platform/rcar-vin/rcar-core.c
> +++ b/drivers/media/platform/rcar-vin/rcar-core.c
> @@ -24,6 +24,7 @@
> 
>  #include <media/v4l2-async.h>
>  #include <media/v4l2-fwnode.h>
> +#include <media/v4l2-mc.h>
> 
>  #include "rcar-vin.h"
> 
> @@ -44,6 +45,133 @@
>   */
>  #define rvin_group_id_to_master(vin) ((vin) < 4 ? 0 : 4)
> 
> +/* ------------------------------------------------------------------------
> + * Media Controller link notification
> + */
> +
> +/* group lock should be held when calling this function */
> +static int rvin_group_entity_to_csi_id(struct rvin_group *group,
> +					struct media_entity *entity)
> +{
> +	struct v4l2_subdev *sd;
> +	int i;

unsigned int.

> +
> +	if (!is_media_entity_v4l2_subdev(entity))
> +		return -ENODEV;

Can this happen ?

> +	sd = media_entity_to_v4l2_subdev(entity);
> +
> +	for (i = 0; i < RVIN_CSI_MAX; i++)
> +		if (group->csi[i].subdev == sd)
> +			return i;
> +
> +	return -ENODEV;
> +}
> +
> +static unsigned int rvin_group_get_mask(struct rvin_dev *vin,
> +					enum rvin_csi_id csi_id,
> +					unsigned char chan)
> +{
> +	const struct rvin_group_route *route;
> +	unsigned int mask = 0;
> +
> +	for (route = vin->info->routes; route->mask; route++) {

Please document the fact that the array needs to be terminated by an empty 
element in the kerneldoc for vin->info->routes.

> +		if (route->vin == vin->id &&
> +		    route->csi == csi_id &&
> +		    route->chan == chan) {
> +			vin_dbg(vin, "Adding route: vin: %d csi: %d chan: %d\n",
> +				route->vin, route->csi, route->chan);
> +			mask |= route->mask;
> +		}
> +	}
> +
> +	return mask;
> +}
> +
> +static int rvin_group_link_notify(struct media_link *link, u32 flags,
> +				  unsigned int notification)
> +{
> +	struct rvin_group *group = container_of(link->graph_obj.mdev,
> +						struct rvin_group, mdev);
> +	unsigned int i, master_id, chan, mask_new, mask = ~0;

I'm sure you could spare a few more lines :-)

> +	struct media_entity *entity;
> +	struct video_device *vdev;
> +	struct media_pad *csi_pad;
> +	struct rvin_dev *vin = NULL;
> +	int csi_id, ret;
> +
> +	ret = v4l2_pipeline_link_notify(link, flags, notification);
> +	if (ret)
> +		return ret;
> +
> +	/* Only care about link enablement for VIN nodes */
> +	if (!(flags & MEDIA_LNK_FL_ENABLED) ||
> +	    !is_media_entity_v4l2_video_device(link->sink->entity))
> +		return 0;
> +
> +	/* If any entity are in use don't allow link changes */

s/are/is/

> +	media_device_for_each_entity(entity, &group->mdev)
> +		if (entity->use_count)
> +			return -EBUSY;
> +
> +	mutex_lock(&group->lock);
> +
> +	/* Find VIN and its master for which the link */

The words make sense individually. Maybe you could try a different order ? :-)

> +	entity = link->sink->entity;
> +	vdev = media_entity_to_video_device(entity);

You can combine those two lines and remove the entity variable.

> +	for (i = 0; i < RCAR_VIN_NUM; i++) {
> +		if (group->vin[i] && &group->vin[i]->vdev == vdev) {
> +			vin = group->vin[i];
> +			master_id = rvin_group_id_to_master(vin->id);
> +			break;
> +		}
> +	}
> +	if (WARN_ON(!vin || !group->vin[master_id])) {
> +		ret = -ENODEV;
> +		goto out;
> +	}
> +
> +	/* Build a mask for already enabled links */
> +	for (i = master_id; i < master_id + 4; i++) {
> +		if (!group->vin[i])
> +			continue;
> +
> +		/* Get remote CSI-2, if any */
> +		csi_pad = media_entity_remote_pad(
> +				&group->vin[i]->vdev.entity.pads[0]);
> +		if (!csi_pad)
> +			continue;
> +
> +		csi_id = rvin_group_entity_to_csi_id(group, csi_pad->entity);
> +		chan = rvin_group_csi_pad_to_chan(csi_pad->index);
> +
> +		mask &= rvin_group_get_mask(group->vin[i], csi_id, chan);
> +	}
> +
> +	/* Add the new link to the existing mask and check if it works */
> +	csi_id = rvin_group_entity_to_csi_id(group, link->source->entity);
> +	chan = rvin_group_csi_pad_to_chan(link->source->index);
> +	mask_new = mask & rvin_group_get_mask(vin, csi_id, chan);
> +
> +	vin_dbg(vin, "Try link change mask: 0x%x new: 0x%x\n", mask, mask_new);
> +
> +	if (!mask_new) {
> +		ret = -EMLINK;
> +		goto out;
> +	}
> +
> +	/* New valid CHSEL found, set the new value */
> +	rvin_set_channel_routing(group->vin[master_id], __ffs(mask_new));
> +out:
> +	mutex_unlock(&group->lock);
> +
> +	return ret;

I assume this work, but without knowing what the mask field is, it's hard to 
comment. As stated in the review of a previous patch please document the mask 
field correctly, and please explain the algorithm at the beginning of this 
function.

> +}
> +
> +static const struct media_device_ops rvin_media_ops = {
> +	.link_notify = rvin_group_link_notify,
> +};
> +
>  /* ------------------------------------------------------------------------
>   * Gen3 CSI2 Group Allocator
>   */
> @@ -85,6 +213,7 @@ static int rvin_group_init(struct rvin_group *group,
> struct rvin_dev *vin) vin_dbg(vin, "found %u enabled VIN's in DT",
> group->count);
> 
>  	mdev->dev = vin->dev;
> +	mdev->ops = &rvin_media_ops;
> 
>  	match = of_match_node(vin->dev->driver->of_match_table,
>  			      vin->dev->of_node);

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v10 27/30] rcar-vin: extend {start,stop}_streaming to work with media controller
  2018-01-29 16:34 ` [PATCH v10 27/30] rcar-vin: extend {start,stop}_streaming to work with media controller Niklas Söderlund
@ 2018-02-13 21:31   ` Laurent Pinchart
  0 siblings, 0 replies; 65+ messages in thread
From: Laurent Pinchart @ 2018-02-13 21:31 UTC (permalink / raw)
  To: Niklas Söderlund
  Cc: Hans Verkuil, linux-media, linux-renesas-soc, tomoharu.fukawa.eb,
	Kieran Bingham

Hi Niklas,

Thank you for the patch.

On Monday, 29 January 2018 18:34:32 EET Niklas Söderlund wrote:
> The procedure to start or stop streaming using the non-MC single
> subdevice and the MC graph and multiple subdevices are quite different.
> Create a new function to abstract which method is used based on which
> mode the driver is running in and add logic to start the MC graph.
> 
> Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
> ---
>  drivers/media/platform/rcar-vin/rcar-dma.c | 123 +++++++++++++++++++++++--
>  1 file changed, 116 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/media/platform/rcar-vin/rcar-dma.c
> b/drivers/media/platform/rcar-vin/rcar-dma.c index
> 811d8f8638d21200..6784e7eb3d96e1c0 100644
> --- a/drivers/media/platform/rcar-vin/rcar-dma.c
> +++ b/drivers/media/platform/rcar-vin/rcar-dma.c
> @@ -1087,15 +1087,126 @@ static void rvin_buffer_queue(struct vb2_buffer
> *vb) spin_unlock_irqrestore(&vin->qlock, flags);
>  }
> 
> +static int rvin_set_stream(struct rvin_dev *vin, int on)
> +{
> +	struct v4l2_subdev_format fmt = {
> +		.which = V4L2_SUBDEV_FORMAT_ACTIVE,
> +	};
> +	struct media_pipeline *pipe;
> +	struct media_device *mdev;
> +	struct  v4l2_subdev *sd;
> +	struct media_pad *pad;
> +	int ret;
> +
> +	/* No media controller used, simply pass operation to subdevice */
> +	if (!vin->info->use_mc) {
> +		ret = v4l2_subdev_call(vin->digital->subdev, video, s_stream,
> +				       on);
> +
> +		return ret == -ENOIOCTLCMD ? 0 : ret;
> +	}
> +
> +	pad = media_entity_remote_pad(&vin->pad);
> +	if (!pad)
> +		return -EPIPE;
> +
> +	sd = media_entity_to_v4l2_subdev(pad->entity);
> +
> +	if (!on) {
> +		media_pipeline_stop(&vin->vdev.entity);
> +		return v4l2_subdev_call(sd, video, s_stream, 0);
> +	}
> +
> +	fmt.pad = pad->index;
> +	if (v4l2_subdev_call(sd, pad, get_fmt, NULL, &fmt))
> +		return -EPIPE;
> +
> +	switch (fmt.format.code) {
> +	case MEDIA_BUS_FMT_YUYV8_1X16:
> +	case MEDIA_BUS_FMT_UYVY8_2X8:
> +	case MEDIA_BUS_FMT_UYVY10_2X10:
> +	case MEDIA_BUS_FMT_RGB888_1X24:
> +		vin->code = fmt.format.code;
> +		break;
> +	default:
> +		return -EPIPE;
> +	}
> +
> +	switch (fmt.format.field) {
> +	case V4L2_FIELD_TOP:
> +	case V4L2_FIELD_BOTTOM:
> +	case V4L2_FIELD_NONE:
> +	case V4L2_FIELD_INTERLACED_TB:
> +	case V4L2_FIELD_INTERLACED_BT:
> +	case V4L2_FIELD_INTERLACED:
> +	case V4L2_FIELD_SEQ_TB:
> +	case V4L2_FIELD_SEQ_BT:
> +		/* Supported natively */
> +		break;
> +	case V4L2_FIELD_ALTERNATE:
> +		switch (vin->format.field) {
> +		case V4L2_FIELD_TOP:
> +		case V4L2_FIELD_BOTTOM:
> +		case V4L2_FIELD_NONE:
> +			break;
> +		case V4L2_FIELD_INTERLACED_TB:
> +		case V4L2_FIELD_INTERLACED_BT:
> +		case V4L2_FIELD_INTERLACED:
> +		case V4L2_FIELD_SEQ_TB:
> +		case V4L2_FIELD_SEQ_BT:
> +			/* Use VIN hardware to combine the two fields */
> +			fmt.format.height *= 2;
> +			break;
> +		default:
> +			return -EPIPE;
> +		}
> +		break;
> +	default:
> +		return -EPIPE;
> +	}
> +
> +	if (fmt.format.width != vin->format.width ||
> +	    fmt.format.height != vin->format.height ||
> +	    fmt.format.code != vin->code)
> +		return -EPIPE;

I'd create a rvin_mc_validate_format() function and move this code there. This 
function is growing a bit too big.

> +	mdev = vin->vdev.entity.graph_obj.mdev;
> +
> +	/*
> +	 * The graph lock needs to be taken to protect concurrent
> +	 * starts of multiple VIN instances as they might share
> +	 * a common subdevice down the line and then should use
> +	 * the same pipe.
> +	 */
> +	mutex_lock(&mdev->graph_mutex);

I'd say mutex_lock_interruptible(), but videobuf2 won't support that :-S

> +	pipe = sd->entity.pipe ? sd->entity.pipe : &vin->vdev.pipe;
> +	ret = __media_pipeline_start(&vin->vdev.entity, pipe);
> +	mutex_unlock(&mdev->graph_mutex);
> +	if (ret)
> +		return ret;
> +
> +	ret = v4l2_subdev_call(sd, video, s_stream, 1);
> +	if (ret == -ENOIOCTLCMD)
> +		ret = 0;
> +	if (ret)
> +		media_pipeline_stop(&vin->vdev.entity);
> +
> +	return ret;
> +}
> +
>  static int rvin_start_streaming(struct vb2_queue *vq, unsigned int count)
>  {
>  	struct rvin_dev *vin = vb2_get_drv_priv(vq);
> -	struct v4l2_subdev *sd;
>  	unsigned long flags;
>  	int ret;
> 
> -	sd = vin_to_source(vin);
> -	v4l2_subdev_call(sd, video, s_stream, 1);
> +	ret = rvin_set_stream(vin, 1);
> +	if (ret) {
> +		spin_lock_irqsave(&vin->qlock, flags);
> +		return_all_buffers(vin, VB2_BUF_STATE_QUEUED);
> +		spin_unlock_irqrestore(&vin->qlock, flags);
> +		return ret;
> +	}
> 
>  	spin_lock_irqsave(&vin->qlock, flags);
> 
> @@ -1104,7 +1215,7 @@ static int rvin_start_streaming(struct vb2_queue *vq,
> unsigned int count) ret = rvin_capture_start(vin);
>  	if (ret) {
>  		return_all_buffers(vin, VB2_BUF_STATE_QUEUED);
> -		v4l2_subdev_call(sd, video, s_stream, 0);
> +		rvin_set_stream(vin, 0);
>  	}
> 
>  	spin_unlock_irqrestore(&vin->qlock, flags);
> @@ -1115,7 +1226,6 @@ static int rvin_start_streaming(struct vb2_queue *vq,
> unsigned int count) static void rvin_stop_streaming(struct vb2_queue *vq)
>  {
>  	struct rvin_dev *vin = vb2_get_drv_priv(vq);
> -	struct v4l2_subdev *sd;
>  	unsigned long flags;
>  	int retries = 0;
> 
> @@ -1154,8 +1264,7 @@ static void rvin_stop_streaming(struct vb2_queue *vq)
> 
>  	spin_unlock_irqrestore(&vin->qlock, flags);
> 
> -	sd = vin_to_source(vin);
> -	v4l2_subdev_call(sd, video, s_stream, 0);
> +	rvin_set_stream(vin, 0);
> 
>  	/* disable interrupts */
>  	rvin_disable_interrupts(vin);

With this small issue fixed,

Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v10 28/30] rcar-vin: enable support for r8a7795
  2018-01-29 16:34 ` [PATCH v10 28/30] rcar-vin: enable support for r8a7795 Niklas Söderlund
@ 2018-02-13 21:52   ` Laurent Pinchart
  0 siblings, 0 replies; 65+ messages in thread
From: Laurent Pinchart @ 2018-02-13 21:52 UTC (permalink / raw)
  To: Niklas Söderlund
  Cc: Hans Verkuil, linux-media, linux-renesas-soc, tomoharu.fukawa.eb,
	Kieran Bingham

Hi Niklas,

Thank you for the patch.

On Monday, 29 January 2018 18:34:33 EET Niklas Söderlund wrote:
> Add the SoC specific information for Renesas r8a7795 ES1.x and ES2.0.
> 
> Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>

Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

> ---
>  drivers/media/platform/rcar-vin/Kconfig     |   2 +-
>  drivers/media/platform/rcar-vin/rcar-core.c | 120 +++++++++++++++++++++++++
>  2 files changed, 121 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/media/platform/rcar-vin/Kconfig
> b/drivers/media/platform/rcar-vin/Kconfig index
> af4c98b44d2e22cb..8fa7ee468c63afb9 100644
> --- a/drivers/media/platform/rcar-vin/Kconfig
> +++ b/drivers/media/platform/rcar-vin/Kconfig
> @@ -6,7 +6,7 @@ config VIDEO_RCAR_VIN
>  	select V4L2_FWNODE
>  	---help---
>  	  Support for Renesas R-Car Video Input (VIN) driver.
> -	  Supports R-Car Gen2 SoCs.
> +	  Supports R-Car Gen2 and Gen3 SoCs.
> 
>  	  To compile this driver as a module, choose M here: the
>  	  module will be called rcar-vin.
> diff --git a/drivers/media/platform/rcar-vin/rcar-core.c
> b/drivers/media/platform/rcar-vin/rcar-core.c index
> 7ceff0de40078580..43d2fa83875817f0 100644
> --- a/drivers/media/platform/rcar-vin/rcar-core.c
> +++ b/drivers/media/platform/rcar-vin/rcar-core.c
> @@ -21,6 +21,7 @@
>  #include <linux/platform_device.h>
>  #include <linux/pm_runtime.h>
>  #include <linux/slab.h>
> +#include <linux/sys_soc.h>
> 
>  #include <media/v4l2-async.h>
>  #include <media/v4l2-fwnode.h>
> @@ -815,6 +816,104 @@ static const struct rvin_info rcar_info_gen2 = {
>  	.max_height = 2048,
>  };
> 
> +static const struct rvin_group_route rcar_info_r8a7795_routes[] = {
> +	{ .vin = 0, .csi = RVIN_CSI40, .chan = 0, .mask = BIT(0) | BIT(3) },
> +	{ .vin = 0, .csi = RVIN_CSI20, .chan = 0, .mask = BIT(1) | BIT(4) },
> +	{ .vin = 0, .csi = RVIN_CSI40, .chan = 1, .mask = BIT(2) },
> +	{ .vin = 1, .csi = RVIN_CSI20, .chan = 0, .mask = BIT(0) },
> +	{ .vin = 1, .csi = RVIN_CSI40, .chan = 1, .mask = BIT(1) | BIT(3) },
> +	{ .vin = 1, .csi = RVIN_CSI40, .chan = 0, .mask = BIT(2) },
> +	{ .vin = 1, .csi = RVIN_CSI20, .chan = 1, .mask = BIT(4) },
> +	{ .vin = 2, .csi = RVIN_CSI20, .chan = 1, .mask = BIT(0) },
> +	{ .vin = 2, .csi = RVIN_CSI40, .chan = 0, .mask = BIT(1) },
> +	{ .vin = 2, .csi = RVIN_CSI20, .chan = 0, .mask = BIT(2) },
> +	{ .vin = 2, .csi = RVIN_CSI40, .chan = 2, .mask = BIT(3) },
> +	{ .vin = 2, .csi = RVIN_CSI20, .chan = 2, .mask = BIT(4) },
> +	{ .vin = 3, .csi = RVIN_CSI40, .chan = 1, .mask = BIT(0) },
> +	{ .vin = 3, .csi = RVIN_CSI20, .chan = 1, .mask = BIT(1) | BIT(2) },
> +	{ .vin = 3, .csi = RVIN_CSI40, .chan = 3, .mask = BIT(3) },
> +	{ .vin = 3, .csi = RVIN_CSI20, .chan = 3, .mask = BIT(4) },
> +	{ .vin = 4, .csi = RVIN_CSI41, .chan = 0, .mask = BIT(0) | BIT(3) },
> +	{ .vin = 4, .csi = RVIN_CSI20, .chan = 0, .mask = BIT(1) | BIT(4) },
> +	{ .vin = 4, .csi = RVIN_CSI41, .chan = 1, .mask = BIT(2) },
> +	{ .vin = 5, .csi = RVIN_CSI20, .chan = 0, .mask = BIT(0) },
> +	{ .vin = 5, .csi = RVIN_CSI41, .chan = 1, .mask = BIT(1) | BIT(3) },
> +	{ .vin = 5, .csi = RVIN_CSI41, .chan = 0, .mask = BIT(2) },
> +	{ .vin = 5, .csi = RVIN_CSI20, .chan = 1, .mask = BIT(4) },
> +	{ .vin = 6, .csi = RVIN_CSI20, .chan = 1, .mask = BIT(0) },
> +	{ .vin = 6, .csi = RVIN_CSI41, .chan = 0, .mask = BIT(1) },
> +	{ .vin = 6, .csi = RVIN_CSI20, .chan = 0, .mask = BIT(2) },
> +	{ .vin = 6, .csi = RVIN_CSI41, .chan = 2, .mask = BIT(3) },
> +	{ .vin = 6, .csi = RVIN_CSI20, .chan = 2, .mask = BIT(4) },
> +	{ .vin = 7, .csi = RVIN_CSI41, .chan = 1, .mask = BIT(0) },
> +	{ .vin = 7, .csi = RVIN_CSI20, .chan = 1, .mask = BIT(1) | BIT(2) },
> +	{ .vin = 7, .csi = RVIN_CSI41, .chan = 3, .mask = BIT(3) },
> +	{ .vin = 7, .csi = RVIN_CSI20, .chan = 3, .mask = BIT(4) },
> +	{ /* Sentinel */ }
> +};
> +
> +static const struct rvin_info rcar_info_r8a7795 = {
> +	.model = RCAR_GEN3,
> +	.use_mc = true,
> +	.max_width = 4096,
> +	.max_height = 4096,
> +	.routes = rcar_info_r8a7795_routes,
> +};
> +
> +static const struct rvin_group_route rcar_info_r8a7795es1_routes[] = {
> +	{ .vin = 0, .csi = RVIN_CSI40, .chan = 0, .mask = BIT(0) | BIT(3) },
> +	{ .vin = 0, .csi = RVIN_CSI20, .chan = 0, .mask = BIT(1) | BIT(4) },
> +	{ .vin = 0, .csi = RVIN_CSI21, .chan = 0, .mask = BIT(2) | BIT(5) },
> +	{ .vin = 1, .csi = RVIN_CSI20, .chan = 0, .mask = BIT(0) },
> +	{ .vin = 1, .csi = RVIN_CSI21, .chan = 0, .mask = BIT(1) },
> +	{ .vin = 1, .csi = RVIN_CSI40, .chan = 0, .mask = BIT(2) },
> +	{ .vin = 1, .csi = RVIN_CSI40, .chan = 1, .mask = BIT(3) },
> +	{ .vin = 1, .csi = RVIN_CSI20, .chan = 1, .mask = BIT(4) },
> +	{ .vin = 1, .csi = RVIN_CSI21, .chan = 1, .mask = BIT(5) },
> +	{ .vin = 2, .csi = RVIN_CSI21, .chan = 0, .mask = BIT(0) },
> +	{ .vin = 2, .csi = RVIN_CSI40, .chan = 0, .mask = BIT(1) },
> +	{ .vin = 2, .csi = RVIN_CSI20, .chan = 0, .mask = BIT(2) },
> +	{ .vin = 2, .csi = RVIN_CSI40, .chan = 2, .mask = BIT(3) },
> +	{ .vin = 2, .csi = RVIN_CSI20, .chan = 2, .mask = BIT(4) },
> +	{ .vin = 2, .csi = RVIN_CSI21, .chan = 2, .mask = BIT(5) },
> +	{ .vin = 3, .csi = RVIN_CSI40, .chan = 1, .mask = BIT(0) },
> +	{ .vin = 3, .csi = RVIN_CSI20, .chan = 1, .mask = BIT(1) },
> +	{ .vin = 3, .csi = RVIN_CSI21, .chan = 1, .mask = BIT(2) },
> +	{ .vin = 3, .csi = RVIN_CSI40, .chan = 3, .mask = BIT(3) },
> +	{ .vin = 3, .csi = RVIN_CSI20, .chan = 3, .mask = BIT(4) },
> +	{ .vin = 3, .csi = RVIN_CSI21, .chan = 3, .mask = BIT(5) },
> +	{ .vin = 4, .csi = RVIN_CSI41, .chan = 0, .mask = BIT(0) | BIT(3) },
> +	{ .vin = 4, .csi = RVIN_CSI20, .chan = 0, .mask = BIT(1) | BIT(4) },
> +	{ .vin = 4, .csi = RVIN_CSI21, .chan = 0, .mask = BIT(2) | BIT(5) },
> +	{ .vin = 5, .csi = RVIN_CSI20, .chan = 0, .mask = BIT(0) },
> +	{ .vin = 5, .csi = RVIN_CSI21, .chan = 0, .mask = BIT(1) },
> +	{ .vin = 5, .csi = RVIN_CSI41, .chan = 0, .mask = BIT(2) },
> +	{ .vin = 5, .csi = RVIN_CSI41, .chan = 1, .mask = BIT(3) },
> +	{ .vin = 5, .csi = RVIN_CSI20, .chan = 1, .mask = BIT(4) },
> +	{ .vin = 5, .csi = RVIN_CSI21, .chan = 1, .mask = BIT(5) },
> +	{ .vin = 6, .csi = RVIN_CSI21, .chan = 0, .mask = BIT(0) },
> +	{ .vin = 6, .csi = RVIN_CSI41, .chan = 0, .mask = BIT(1) },
> +	{ .vin = 6, .csi = RVIN_CSI20, .chan = 0, .mask = BIT(2) },
> +	{ .vin = 6, .csi = RVIN_CSI41, .chan = 2, .mask = BIT(3) },
> +	{ .vin = 6, .csi = RVIN_CSI20, .chan = 2, .mask = BIT(4) },
> +	{ .vin = 6, .csi = RVIN_CSI21, .chan = 2, .mask = BIT(5) },
> +	{ .vin = 7, .csi = RVIN_CSI41, .chan = 1, .mask = BIT(0) },
> +	{ .vin = 7, .csi = RVIN_CSI20, .chan = 1, .mask = BIT(1) },
> +	{ .vin = 7, .csi = RVIN_CSI21, .chan = 1, .mask = BIT(2) },
> +	{ .vin = 7, .csi = RVIN_CSI41, .chan = 3, .mask = BIT(3) },
> +	{ .vin = 7, .csi = RVIN_CSI20, .chan = 3, .mask = BIT(4) },
> +	{ .vin = 7, .csi = RVIN_CSI21, .chan = 3, .mask = BIT(5) },
> +	{ /* Sentinel */ }
> +};
> +
> +static const struct rvin_info rcar_info_r8a7795es1 = {
> +	.model = RCAR_GEN3,
> +	.use_mc = true,
> +	.max_width = 4096,
> +	.max_height = 4096,
> +	.routes = rcar_info_r8a7795es1_routes,
> +};
> +
>  static const struct of_device_id rvin_of_id_table[] = {
>  	{
>  		.compatible = "renesas,vin-r8a7778",
> @@ -844,12 +943,25 @@ static const struct of_device_id rvin_of_id_table[] =
> { .compatible = "renesas,rcar-gen2-vin",
>  		.data = &rcar_info_gen2,
>  	},
> +	{
> +		.compatible = "renesas,vin-r8a7795",
> +		.data = &rcar_info_r8a7795,
> +	},
>  	{ /* Sentinel */ },
>  };
>  MODULE_DEVICE_TABLE(of, rvin_of_id_table);
> 
> +static const struct soc_device_attribute r8a7795es1[] = {
> +	{
> +		.soc_id = "r8a7795", .revision = "ES1.*",
> +		.data = &rcar_info_r8a7795es1,
> +	},
> +	{ /* Sentinel */ }
> +};
> +
>  static int rcar_vin_probe(struct platform_device *pdev)
>  {
> +	const struct soc_device_attribute *attr;
>  	struct rvin_dev *vin;
>  	struct resource *mem;
>  	int irq, ret;
> @@ -861,6 +973,14 @@ static int rcar_vin_probe(struct platform_device *pdev)
> vin->dev = &pdev->dev;
>  	vin->info = of_device_get_match_data(&pdev->dev);
> 
> +	/*
> +	 * Special care is needed on r8a7795 ES1.x since it
> +	 * uses different routing than r8a7795 ES2.0.
> +	 */
> +	attr = soc_device_match(r8a7795es1);
> +	if (attr)
> +		vin->info = attr->data;
> +
>  	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>  	if (mem == NULL)
>  		return -EINVAL;

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v10 29/30] rcar-vin: enable support for r8a7796
  2018-01-29 16:34 ` [PATCH v10 29/30] rcar-vin: enable support for r8a7796 Niklas Söderlund
@ 2018-02-13 21:54   ` Laurent Pinchart
  2018-02-13 21:55     ` Laurent Pinchart
  0 siblings, 1 reply; 65+ messages in thread
From: Laurent Pinchart @ 2018-02-13 21:54 UTC (permalink / raw)
  To: Niklas Söderlund
  Cc: Hans Verkuil, linux-media, linux-renesas-soc, tomoharu.fukawa.eb,
	Kieran Bingham

Hi Niklas,

Thank you for the patch.

On Monday, 29 January 2018 18:34:34 EET Niklas Söderlund wrote:
> Add the SoC specific information for Renesas r8a7796.
> 
> Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
> ---
>  drivers/media/platform/rcar-vin/rcar-core.c | 44 ++++++++++++++++++++++++++
>  1 file changed, 44 insertions(+)
> 
> diff --git a/drivers/media/platform/rcar-vin/rcar-core.c
> b/drivers/media/platform/rcar-vin/rcar-core.c index
> 43d2fa83875817f0..2305fedd293db241 100644
> --- a/drivers/media/platform/rcar-vin/rcar-core.c
> +++ b/drivers/media/platform/rcar-vin/rcar-core.c
> @@ -914,6 +914,46 @@ static const struct rvin_info rcar_info_r8a7795es1 = {
>  	.routes = rcar_info_r8a7795es1_routes,
>  };
> 
> +static const struct rvin_group_route rcar_info_r8a7796_routes[] = {
> +	{ .vin = 0, .csi = RVIN_CSI40, .chan = 0, .mask = BIT(0) | BIT(3) },
> +	{ .vin = 0, .csi = RVIN_CSI20, .chan = 0, .mask = BIT(1) | BIT(4) },
> +	{ .vin = 1, .csi = RVIN_CSI20, .chan = 0, .mask = BIT(0) },
> +	{ .vin = 1, .csi = RVIN_CSI40, .chan = 0, .mask = BIT(2) },
> +	{ .vin = 1, .csi = RVIN_CSI40, .chan = 1, .mask = BIT(3) },
> +	{ .vin = 1, .csi = RVIN_CSI20, .chan = 1, .mask = BIT(4) },
> +	{ .vin = 2, .csi = RVIN_CSI40, .chan = 0, .mask = BIT(1) },
> +	{ .vin = 2, .csi = RVIN_CSI20, .chan = 0, .mask = BIT(2) },
> +	{ .vin = 2, .csi = RVIN_CSI40, .chan = 2, .mask = BIT(3) },
> +	{ .vin = 2, .csi = RVIN_CSI20, .chan = 2, .mask = BIT(4) },
> +	{ .vin = 3, .csi = RVIN_CSI40, .chan = 1, .mask = BIT(0) },
> +	{ .vin = 3, .csi = RVIN_CSI20, .chan = 1, .mask = BIT(1) },
> +	{ .vin = 3, .csi = RVIN_CSI40, .chan = 3, .mask = BIT(3) },
> +	{ .vin = 3, .csi = RVIN_CSI20, .chan = 3, .mask = BIT(4) },
> +	{ .vin = 4, .csi = RVIN_CSI40, .chan = 0, .mask = BIT(0) | BIT(3) },
> +	{ .vin = 4, .csi = RVIN_CSI20, .chan = 0, .mask = BIT(1) | BIT(4) },
> +	{ .vin = 5, .csi = RVIN_CSI20, .chan = 0, .mask = BIT(0) },
> +	{ .vin = 5, .csi = RVIN_CSI40, .chan = 0, .mask = BIT(2) },
> +	{ .vin = 5, .csi = RVIN_CSI40, .chan = 1, .mask = BIT(3) },
> +	{ .vin = 5, .csi = RVIN_CSI20, .chan = 1, .mask = BIT(4) },
> +	{ .vin = 6, .csi = RVIN_CSI40, .chan = 0, .mask = BIT(1) },
> +	{ .vin = 6, .csi = RVIN_CSI20, .chan = 0, .mask = BIT(2) },
> +	{ .vin = 6, .csi = RVIN_CSI40, .chan = 2, .mask = BIT(3) },
> +	{ .vin = 6, .csi = RVIN_CSI20, .chan = 2, .mask = BIT(4) },
> +	{ .vin = 7, .csi = RVIN_CSI40, .chan = 1, .mask = BIT(0) },
> +	{ .vin = 7, .csi = RVIN_CSI20, .chan = 1, .mask = BIT(1) },
> +	{ .vin = 7, .csi = RVIN_CSI40, .chan = 3, .mask = BIT(3) },
> +	{ .vin = 7, .csi = RVIN_CSI20, .chan = 3, .mask = BIT(4) },
> +	{ /* Sentinel */ }
> +};
> +
> +static const struct rvin_info rcar_info_r8a7796 = {
> +	.model = RCAR_GEN3,
> +	.use_mc = true,
> +	.max_width = 4096,
> +	.max_height = 4096,
> +	.routes = rcar_info_r8a7796_routes,
> +};
> +
>  static const struct of_device_id rvin_of_id_table[] = {
>  	{
>  		.compatible = "renesas,vin-r8a7778",
> @@ -947,6 +987,10 @@ static const struct of_device_id rvin_of_id_table[] = {
> .compatible = "renesas,vin-r8a7795",
>  		.data = &rcar_info_r8a7795,
>  	},
> +	{
> +		.compatible = "renesas,vin-r8a7796",
> +		.data = &rcar_info_r8a7796,
> +	},
>  	{ /* Sentinel */ },
>  };
>  MODULE_DEVICE_TABLE(of, rvin_of_id_table);


-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v10 29/30] rcar-vin: enable support for r8a7796
  2018-02-13 21:54   ` Laurent Pinchart
@ 2018-02-13 21:55     ` Laurent Pinchart
  0 siblings, 0 replies; 65+ messages in thread
From: Laurent Pinchart @ 2018-02-13 21:55 UTC (permalink / raw)
  To: Niklas Söderlund
  Cc: Hans Verkuil, linux-media, linux-renesas-soc, tomoharu.fukawa.eb,
	Kieran Bingham

On Tuesday, 13 February 2018 23:54:55 EET Laurent Pinchart wrote:
> Hi Niklas,
> 
> Thank you for the patch.
> 
> On Monday, 29 January 2018 18:34:34 EET Niklas Söderlund wrote:
> > Add the SoC specific information for Renesas r8a7796.
> > 
> > Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>

And also

Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

> > ---
> > 
> >  drivers/media/platform/rcar-vin/rcar-core.c | 44
> >  ++++++++++++++++++++++++++
> >  1 file changed, 44 insertions(+)
> > 
> > diff --git a/drivers/media/platform/rcar-vin/rcar-core.c
> > b/drivers/media/platform/rcar-vin/rcar-core.c index
> > 43d2fa83875817f0..2305fedd293db241 100644
> > --- a/drivers/media/platform/rcar-vin/rcar-core.c
> > +++ b/drivers/media/platform/rcar-vin/rcar-core.c
> > @@ -914,6 +914,46 @@ static const struct rvin_info rcar_info_r8a7795es1 =
> > {
> > 
> >  	.routes = rcar_info_r8a7795es1_routes,
> >  
> >  };
> > 
> > +static const struct rvin_group_route rcar_info_r8a7796_routes[] = {
> > +	{ .vin = 0, .csi = RVIN_CSI40, .chan = 0, .mask = BIT(0) | BIT(3) },
> > +	{ .vin = 0, .csi = RVIN_CSI20, .chan = 0, .mask = BIT(1) | BIT(4) },
> > +	{ .vin = 1, .csi = RVIN_CSI20, .chan = 0, .mask = BIT(0) },
> > +	{ .vin = 1, .csi = RVIN_CSI40, .chan = 0, .mask = BIT(2) },
> > +	{ .vin = 1, .csi = RVIN_CSI40, .chan = 1, .mask = BIT(3) },
> > +	{ .vin = 1, .csi = RVIN_CSI20, .chan = 1, .mask = BIT(4) },
> > +	{ .vin = 2, .csi = RVIN_CSI40, .chan = 0, .mask = BIT(1) },
> > +	{ .vin = 2, .csi = RVIN_CSI20, .chan = 0, .mask = BIT(2) },
> > +	{ .vin = 2, .csi = RVIN_CSI40, .chan = 2, .mask = BIT(3) },
> > +	{ .vin = 2, .csi = RVIN_CSI20, .chan = 2, .mask = BIT(4) },
> > +	{ .vin = 3, .csi = RVIN_CSI40, .chan = 1, .mask = BIT(0) },
> > +	{ .vin = 3, .csi = RVIN_CSI20, .chan = 1, .mask = BIT(1) },
> > +	{ .vin = 3, .csi = RVIN_CSI40, .chan = 3, .mask = BIT(3) },
> > +	{ .vin = 3, .csi = RVIN_CSI20, .chan = 3, .mask = BIT(4) },
> > +	{ .vin = 4, .csi = RVIN_CSI40, .chan = 0, .mask = BIT(0) | BIT(3) },
> > +	{ .vin = 4, .csi = RVIN_CSI20, .chan = 0, .mask = BIT(1) | BIT(4) },
> > +	{ .vin = 5, .csi = RVIN_CSI20, .chan = 0, .mask = BIT(0) },
> > +	{ .vin = 5, .csi = RVIN_CSI40, .chan = 0, .mask = BIT(2) },
> > +	{ .vin = 5, .csi = RVIN_CSI40, .chan = 1, .mask = BIT(3) },
> > +	{ .vin = 5, .csi = RVIN_CSI20, .chan = 1, .mask = BIT(4) },
> > +	{ .vin = 6, .csi = RVIN_CSI40, .chan = 0, .mask = BIT(1) },
> > +	{ .vin = 6, .csi = RVIN_CSI20, .chan = 0, .mask = BIT(2) },
> > +	{ .vin = 6, .csi = RVIN_CSI40, .chan = 2, .mask = BIT(3) },
> > +	{ .vin = 6, .csi = RVIN_CSI20, .chan = 2, .mask = BIT(4) },
> > +	{ .vin = 7, .csi = RVIN_CSI40, .chan = 1, .mask = BIT(0) },
> > +	{ .vin = 7, .csi = RVIN_CSI20, .chan = 1, .mask = BIT(1) },
> > +	{ .vin = 7, .csi = RVIN_CSI40, .chan = 3, .mask = BIT(3) },
> > +	{ .vin = 7, .csi = RVIN_CSI20, .chan = 3, .mask = BIT(4) },
> > +	{ /* Sentinel */ }
> > +};
> > +
> > +static const struct rvin_info rcar_info_r8a7796 = {
> > +	.model = RCAR_GEN3,
> > +	.use_mc = true,
> > +	.max_width = 4096,
> > +	.max_height = 4096,
> > +	.routes = rcar_info_r8a7796_routes,
> > +};
> > +
> > 
> >  static const struct of_device_id rvin_of_id_table[] = {
> >  
> >  	{
> >  	
> >  		.compatible = "renesas,vin-r8a7778",
> > 
> > @@ -947,6 +987,10 @@ static const struct of_device_id rvin_of_id_table[] =
> > { .compatible = "renesas,vin-r8a7795",
> > 
> >  		.data = &rcar_info_r8a7795,
> >  	
> >  	},
> > 
> > +	{
> > +		.compatible = "renesas,vin-r8a7796",
> > +		.data = &rcar_info_r8a7796,
> > +	},
> > 
> >  	{ /* Sentinel */ },
> >  
> >  };
> >  MODULE_DEVICE_TABLE(of, rvin_of_id_table);


-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v10 30/30] rcar-vin: enable support for r8a77970
  2018-01-29 16:34 ` [PATCH v10 30/30] rcar-vin: enable support for r8a77970 Niklas Söderlund
@ 2018-02-13 21:56   ` Laurent Pinchart
  0 siblings, 0 replies; 65+ messages in thread
From: Laurent Pinchart @ 2018-02-13 21:56 UTC (permalink / raw)
  To: Niklas Söderlund
  Cc: Hans Verkuil, linux-media, linux-renesas-soc, tomoharu.fukawa.eb,
	Kieran Bingham

Hi Niklas,

Thank you for the patch.

On Monday, 29 January 2018 18:34:35 EET Niklas Söderlund wrote:
> Add the SoC specific information for Renesas r8a77970.
> 
> Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>

Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

> ---
>  drivers/media/platform/rcar-vin/rcar-core.c | 23 +++++++++++++++++++++++
>  1 file changed, 23 insertions(+)
> 
> diff --git a/drivers/media/platform/rcar-vin/rcar-core.c
> b/drivers/media/platform/rcar-vin/rcar-core.c index
> 2305fedd293db241..496b7d2189d73d37 100644
> --- a/drivers/media/platform/rcar-vin/rcar-core.c
> +++ b/drivers/media/platform/rcar-vin/rcar-core.c
> @@ -954,6 +954,25 @@ static const struct rvin_info rcar_info_r8a7796 = {
>  	.routes = rcar_info_r8a7796_routes,
>  };
> 
> +static const struct rvin_group_route _rcar_info_r8a77970_routes[] = {
> +	{ .vin = 0, .csi = RVIN_CSI40, .chan = 0, .mask = BIT(0) | BIT(3) },
> +	{ .vin = 1, .csi = RVIN_CSI40, .chan = 0, .mask = BIT(2) },
> +	{ .vin = 1, .csi = RVIN_CSI40, .chan = 1, .mask = BIT(3) },
> +	{ .vin = 2, .csi = RVIN_CSI40, .chan = 0, .mask = BIT(1) },
> +	{ .vin = 2, .csi = RVIN_CSI40, .chan = 2, .mask = BIT(3) },
> +	{ .vin = 3, .csi = RVIN_CSI40, .chan = 1, .mask = BIT(0) },
> +	{ .vin = 3, .csi = RVIN_CSI40, .chan = 3, .mask = BIT(3) },
> +	{ /* Sentinel */ }
> +};
> +
> +static const struct rvin_info rcar_info_r8a77970 = {
> +	.model = RCAR_GEN3,
> +	.use_mc = true,
> +	.max_width = 4096,
> +	.max_height = 4096,
> +	.routes = _rcar_info_r8a77970_routes,
> +};
> +
>  static const struct of_device_id rvin_of_id_table[] = {
>  	{
>  		.compatible = "renesas,vin-r8a7778",
> @@ -991,6 +1010,10 @@ static const struct of_device_id rvin_of_id_table[] =
> { .compatible = "renesas,vin-r8a7796",
>  		.data = &rcar_info_r8a7796,
>  	},
> +	{
> +		.compatible = "renesas,vin-r8a77970",
> +		.data = &rcar_info_r8a77970,
> +	},
>  	{ /* Sentinel */ },
>  };
>  MODULE_DEVICE_TABLE(of, rvin_of_id_table);


-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v10 10/30] rcar-vin: fix handling of single field frames (top, bottom and alternate fields)
  2018-02-13 16:47       ` Niklas Söderlund
  (?)
@ 2018-02-13 22:31       ` Laurent Pinchart
  2018-02-13 23:12           ` Niklas Söderlund
  -1 siblings, 1 reply; 65+ messages in thread
From: Laurent Pinchart @ 2018-02-13 22:31 UTC (permalink / raw)
  To: Niklas Söderlund
  Cc: Hans Verkuil, linux-media, linux-renesas-soc, tomoharu.fukawa.eb,
	Kieran Bingham

Hi Niklas,

On Tuesday, 13 February 2018 18:47:04 EET Niklas Söderlund wrote:
> On 2018-02-13 18:26:34 +0200, Laurent Pinchart wrote:
> > On Monday, 29 January 2018 18:34:15 EET Niklas Söderlund wrote:
> >> There was never proper support in the VIN driver to deliver ALTERNATING
> >> field format to user-space, remove this field option. The problem is
> >> that ALTERNATING filed order requires the sequence numbers of buffers
> >> returned to userspace to reflect if fields where dropped or not,
> >> something which is not possible with the VIN drivers capture logic.
> >> 
> >> The VIN driver can still capture from a video source which delivers
> >> frames in ALTERNATING field order, but needs to combine them using the
> >> VIN hardware into INTERLACED field order. Before this change if a source
> >> was delivering fields using ALTERNATE the driver would default to
> >> combining them using this hardware feature. Only if the user explicitly
> >> requested ALTERNATE filed order would incorrect frames be delivered.
> >> 
> >> The height should not be cut in half for the format for TOP or BOTTOM
> >> fields settings. This was a mistake and it was made visible by the
> >> scaling refactoring. Correct behavior is that the user should request a
> >> frame size that fits the half height frame reflected in the field
> >> setting. If not the VIN will do its best to scale the top or bottom to
> >> the requested format and cropping and scaling do not work as expected.
> >> 
> >> Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
> >> Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
> >> ---
> >> 
> >>  drivers/media/platform/rcar-vin/rcar-dma.c  | 15 +-------
> >>  drivers/media/platform/rcar-vin/rcar-v4l2.c | 53 +++++++++++------------
> >>  2 files changed, 24 insertions(+), 44 deletions(-)

[snip]

> >> diff --git a/drivers/media/platform/rcar-vin/rcar-v4l2.c
> >> b/drivers/media/platform/rcar-vin/rcar-v4l2.c index
> >> 4d5be2d0c79c9c9a..9f7902d29c62e205 100644
> >> --- a/drivers/media/platform/rcar-vin/rcar-v4l2.c
> >> +++ b/drivers/media/platform/rcar-vin/rcar-v4l2.c
> >> @@ -103,6 +103,28 @@ static int rvin_get_source_format(struct rvin_dev
> >> *vin,
> >>  	if (ret)
> >>  		return ret;
> >> 
> >> +	switch (fmt.format.field) {
> >> +	case V4L2_FIELD_TOP:
> >> +	case V4L2_FIELD_BOTTOM:
> >> +	case V4L2_FIELD_NONE:
> >> +	case V4L2_FIELD_INTERLACED_TB:
> >> +	case V4L2_FIELD_INTERLACED_BT:
> >> +	case V4L2_FIELD_INTERLACED:
> >> +		break;
> >> +	case V4L2_FIELD_ALTERNATE:
> >> +		/*
> >> +		 * Driver do not (yet) support outputting ALTERNATE to a
> >> +		 * userspace. It dose support outputting INTERLACED so use
> > 
> > s/dose/does/
> > 
> >> +		 * the VIN hardware to combine the two fields.
> >> +		 */
> >> +		fmt.format.field = V4L2_FIELD_INTERLACED;
> >> +		fmt.format.height *= 2;
> >> +		break;
> > 
> > I don't like this much. The rvin_get_source_format() function is supposed
> > to return the media bus format for the bus between the source and the
> > VIN. It's the caller that should take the field limitations into account,
> > otherwise you end up with a mix of source and VIN data in the same
> > structure.
> 
> When I read your comments I understand your argument better. And I
> understand this function is perhaps poorly named. Maybe it should be
> renamed to rvin_get_vin_format_from_source().

If you add a comment above the function I could live with that. Would it make 
sense to pass a v4l2_pix_format structure instead of a v4l2_mbus_framefmt ?

> The source format is fetched at s_stream() time in order to do format
> validation. At this time the field is also taken into account once more
> to validate that the VIN format (calculated here) still is valid. It
> also handles the question you ask later at s_stream() time, see bellow.
> 
> >> +	default:
> >> +		vin->format.field = V4L2_FIELD_NONE;
> >> +		break;
> >> +	}
> >> +
> >>  	memcpy(mbus_fmt, &fmt.format, sizeof(*mbus_fmt));
> >>  	
> >>  	return 0;
> >> @@ -139,33 +161,6 @@ static int rvin_reset_format(struct rvin_dev *vin)
> >> 
> >>  	v4l2_fill_pix_format(&vin->format, &source_fmt);
> >> 
> >> -	/*
> >> -	 * If the subdevice uses ALTERNATE field mode and G_STD is
> >> -	 * implemented use the VIN HW to combine the two fields to
> >> -	 * one INTERLACED frame. The ALTERNATE field mode can still
> >> -	 * be requested in S_FMT and be respected, this is just the
> >> -	 * default which is applied at probing or when S_STD is called.
> >> -	 */
> >> -	if (vin->format.field == V4L2_FIELD_ALTERNATE &&
> >> -	    v4l2_subdev_has_op(vin_to_source(vin), video, g_std))
> >> -		vin->format.field = V4L2_FIELD_INTERLACED;
> >> -
> >> -	switch (vin->format.field) {
> >> -	case V4L2_FIELD_TOP:
> >> -	case V4L2_FIELD_BOTTOM:
> >> -	case V4L2_FIELD_ALTERNATE:
> >> -		vin->format.height /= 2;
> >> -		break;
> >> -	case V4L2_FIELD_NONE:
> >> -	case V4L2_FIELD_INTERLACED_TB:
> >> -	case V4L2_FIELD_INTERLACED_BT:
> >> -	case V4L2_FIELD_INTERLACED:
> >> -		break;
> >> -	default:
> >> -		vin->format.field = V4L2_FIELD_NONE;
> >> -		break;
> >> -	}
> >> -
> >>  	ret = rvin_reset_crop_compose(vin);
> >>  	if (ret)
> >>  		return ret;
> >> @@ -243,12 +238,10 @@ static int __rvin_try_format(struct rvin_dev *vin,
> >>  	if (ret)
> >>  		return ret;
> >> 
> >> +	/* Reject ALTERNATE  until support is added to the driver */
> >>  	switch (pix->field) {
> >>  	case V4L2_FIELD_TOP:
> >>  	case V4L2_FIELD_BOTTOM:
> >> -	case V4L2_FIELD_ALTERNATE:
> >> -		pix->height /= 2;
> >> -		break;
> >>  	case V4L2_FIELD_NONE:
> >>  	case V4L2_FIELD_INTERLACED_TB:
> >>  	case V4L2_FIELD_INTERLACED_BT:
> > 
> > You will then set the field to V4L2_FIELD_NONE, but the source will still
> > provide V4L2_FIELD_ALTERNATE. What will happen in the VIN, what will it
> > produce ?
> 
> As stated above this is just the format produced from the VIN to
> user-space. The source field is validated at s_stream() time, if it is
> V4L2_FIELD_ALTERNATE the driver will handle it and possibly interlace it
> depending on how the user wants to consume it, which is what is
> specified here.

That was clearer when I read the patch that implemented .start_streaming() 
support for the MC mode. Defaulting to V4L2_FIELD_NONE seems fine to me.

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v10 10/30] rcar-vin: fix handling of single field frames (top, bottom and alternate fields)
  2018-02-13 22:31       ` Laurent Pinchart
@ 2018-02-13 23:12           ` Niklas Söderlund
  0 siblings, 0 replies; 65+ messages in thread
From: Niklas Söderlund @ 2018-02-13 23:12 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Hans Verkuil, linux-media, linux-renesas-soc, tomoharu.fukawa.eb,
	Kieran Bingham

Hi Laurent,

On 2018-02-14 00:31:21 +0200, Laurent Pinchart wrote:
> Hi Niklas,
> 
> On Tuesday, 13 February 2018 18:47:04 EET Niklas Söderlund wrote:
> > On 2018-02-13 18:26:34 +0200, Laurent Pinchart wrote:
> > > On Monday, 29 January 2018 18:34:15 EET Niklas Söderlund wrote:
> > >> There was never proper support in the VIN driver to deliver ALTERNATING
> > >> field format to user-space, remove this field option. The problem is
> > >> that ALTERNATING filed order requires the sequence numbers of buffers
> > >> returned to userspace to reflect if fields where dropped or not,
> > >> something which is not possible with the VIN drivers capture logic.
> > >> 
> > >> The VIN driver can still capture from a video source which delivers
> > >> frames in ALTERNATING field order, but needs to combine them using the
> > >> VIN hardware into INTERLACED field order. Before this change if a source
> > >> was delivering fields using ALTERNATE the driver would default to
> > >> combining them using this hardware feature. Only if the user explicitly
> > >> requested ALTERNATE filed order would incorrect frames be delivered.
> > >> 
> > >> The height should not be cut in half for the format for TOP or BOTTOM
> > >> fields settings. This was a mistake and it was made visible by the
> > >> scaling refactoring. Correct behavior is that the user should request a
> > >> frame size that fits the half height frame reflected in the field
> > >> setting. If not the VIN will do its best to scale the top or bottom to
> > >> the requested format and cropping and scaling do not work as expected.
> > >> 
> > >> Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
> > >> Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
> > >> ---
> > >> 
> > >>  drivers/media/platform/rcar-vin/rcar-dma.c  | 15 +-------
> > >>  drivers/media/platform/rcar-vin/rcar-v4l2.c | 53 +++++++++++------------
> > >>  2 files changed, 24 insertions(+), 44 deletions(-)
> 
> [snip]
> 
> > >> diff --git a/drivers/media/platform/rcar-vin/rcar-v4l2.c
> > >> b/drivers/media/platform/rcar-vin/rcar-v4l2.c index
> > >> 4d5be2d0c79c9c9a..9f7902d29c62e205 100644
> > >> --- a/drivers/media/platform/rcar-vin/rcar-v4l2.c
> > >> +++ b/drivers/media/platform/rcar-vin/rcar-v4l2.c
> > >> @@ -103,6 +103,28 @@ static int rvin_get_source_format(struct rvin_dev
> > >> *vin,
> > >>  	if (ret)
> > >>  		return ret;
> > >> 
> > >> +	switch (fmt.format.field) {
> > >> +	case V4L2_FIELD_TOP:
> > >> +	case V4L2_FIELD_BOTTOM:
> > >> +	case V4L2_FIELD_NONE:
> > >> +	case V4L2_FIELD_INTERLACED_TB:
> > >> +	case V4L2_FIELD_INTERLACED_BT:
> > >> +	case V4L2_FIELD_INTERLACED:
> > >> +		break;
> > >> +	case V4L2_FIELD_ALTERNATE:
> > >> +		/*
> > >> +		 * Driver do not (yet) support outputting ALTERNATE to a
> > >> +		 * userspace. It dose support outputting INTERLACED so use
> > > 
> > > s/dose/does/
> > > 
> > >> +		 * the VIN hardware to combine the two fields.
> > >> +		 */
> > >> +		fmt.format.field = V4L2_FIELD_INTERLACED;
> > >> +		fmt.format.height *= 2;
> > >> +		break;
> > > 
> > > I don't like this much. The rvin_get_source_format() function is supposed
> > > to return the media bus format for the bus between the source and the
> > > VIN. It's the caller that should take the field limitations into account,
> > > otherwise you end up with a mix of source and VIN data in the same
> > > structure.
> > 
> > When I read your comments I understand your argument better. And I
> > understand this function is perhaps poorly named. Maybe it should be
> > renamed to rvin_get_vin_format_from_source().
> 
> If you add a comment above the function I could live with that. Would it make 
> sense to pass a v4l2_pix_format structure instead of a v4l2_mbus_framefmt ?

I now see that the function name is misleading and I will change it as 
per above. I will also add a comment and swap to v4l2_pix_format (which 
was used before v10 but was changed due to your review comments, I'm 
happy you come around :-)

> 
> > The source format is fetched at s_stream() time in order to do format
> > validation. At this time the field is also taken into account once more
> > to validate that the VIN format (calculated here) still is valid. It
> > also handles the question you ask later at s_stream() time, see bellow.
> > 
> > >> +	default:
> > >> +		vin->format.field = V4L2_FIELD_NONE;
> > >> +		break;
> > >> +	}
> > >> +
> > >>  	memcpy(mbus_fmt, &fmt.format, sizeof(*mbus_fmt));
> > >>  	
> > >>  	return 0;
> > >> @@ -139,33 +161,6 @@ static int rvin_reset_format(struct rvin_dev *vin)
> > >> 
> > >>  	v4l2_fill_pix_format(&vin->format, &source_fmt);
> > >> 
> > >> -	/*
> > >> -	 * If the subdevice uses ALTERNATE field mode and G_STD is
> > >> -	 * implemented use the VIN HW to combine the two fields to
> > >> -	 * one INTERLACED frame. The ALTERNATE field mode can still
> > >> -	 * be requested in S_FMT and be respected, this is just the
> > >> -	 * default which is applied at probing or when S_STD is called.
> > >> -	 */
> > >> -	if (vin->format.field == V4L2_FIELD_ALTERNATE &&
> > >> -	    v4l2_subdev_has_op(vin_to_source(vin), video, g_std))
> > >> -		vin->format.field = V4L2_FIELD_INTERLACED;
> > >> -
> > >> -	switch (vin->format.field) {
> > >> -	case V4L2_FIELD_TOP:
> > >> -	case V4L2_FIELD_BOTTOM:
> > >> -	case V4L2_FIELD_ALTERNATE:
> > >> -		vin->format.height /= 2;
> > >> -		break;
> > >> -	case V4L2_FIELD_NONE:
> > >> -	case V4L2_FIELD_INTERLACED_TB:
> > >> -	case V4L2_FIELD_INTERLACED_BT:
> > >> -	case V4L2_FIELD_INTERLACED:
> > >> -		break;
> > >> -	default:
> > >> -		vin->format.field = V4L2_FIELD_NONE;
> > >> -		break;
> > >> -	}
> > >> -
> > >>  	ret = rvin_reset_crop_compose(vin);
> > >>  	if (ret)
> > >>  		return ret;
> > >> @@ -243,12 +238,10 @@ static int __rvin_try_format(struct rvin_dev *vin,
> > >>  	if (ret)
> > >>  		return ret;
> > >> 
> > >> +	/* Reject ALTERNATE  until support is added to the driver */
> > >>  	switch (pix->field) {
> > >>  	case V4L2_FIELD_TOP:
> > >>  	case V4L2_FIELD_BOTTOM:
> > >> -	case V4L2_FIELD_ALTERNATE:
> > >> -		pix->height /= 2;
> > >> -		break;
> > >>  	case V4L2_FIELD_NONE:
> > >>  	case V4L2_FIELD_INTERLACED_TB:
> > >>  	case V4L2_FIELD_INTERLACED_BT:
> > > 
> > > You will then set the field to V4L2_FIELD_NONE, but the source will still
> > > provide V4L2_FIELD_ALTERNATE. What will happen in the VIN, what will it
> > > produce ?
> > 
> > As stated above this is just the format produced from the VIN to
> > user-space. The source field is validated at s_stream() time, if it is
> > V4L2_FIELD_ALTERNATE the driver will handle it and possibly interlace it
> > depending on how the user wants to consume it, which is what is
> > specified here.
> 
> That was clearer when I read the patch that implemented .start_streaming() 
> support for the MC mode. Defaulting to V4L2_FIELD_NONE seems fine to me.
> 
> -- 
> Regards,
> 
> Laurent Pinchart
> 

-- 
Regards,
Niklas Söderlund

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v10 10/30] rcar-vin: fix handling of single field frames (top, bottom and alternate fields)
@ 2018-02-13 23:12           ` Niklas Söderlund
  0 siblings, 0 replies; 65+ messages in thread
From: Niklas Söderlund @ 2018-02-13 23:12 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Hans Verkuil, linux-media, linux-renesas-soc, tomoharu.fukawa.eb,
	Kieran Bingham

Hi Laurent,

On 2018-02-14 00:31:21 +0200, Laurent Pinchart wrote:
> Hi Niklas,
> 
> On Tuesday, 13 February 2018 18:47:04 EET Niklas S�derlund wrote:
> > On 2018-02-13 18:26:34 +0200, Laurent Pinchart wrote:
> > > On Monday, 29 January 2018 18:34:15 EET Niklas S�derlund wrote:
> > >> There was never proper support in the VIN driver to deliver ALTERNATING
> > >> field format to user-space, remove this field option. The problem is
> > >> that ALTERNATING filed order requires the sequence numbers of buffers
> > >> returned to userspace to reflect if fields where dropped or not,
> > >> something which is not possible with the VIN drivers capture logic.
> > >> 
> > >> The VIN driver can still capture from a video source which delivers
> > >> frames in ALTERNATING field order, but needs to combine them using the
> > >> VIN hardware into INTERLACED field order. Before this change if a source
> > >> was delivering fields using ALTERNATE the driver would default to
> > >> combining them using this hardware feature. Only if the user explicitly
> > >> requested ALTERNATE filed order would incorrect frames be delivered.
> > >> 
> > >> The height should not be cut in half for the format for TOP or BOTTOM
> > >> fields settings. This was a mistake and it was made visible by the
> > >> scaling refactoring. Correct behavior is that the user should request a
> > >> frame size that fits the half height frame reflected in the field
> > >> setting. If not the VIN will do its best to scale the top or bottom to
> > >> the requested format and cropping and scaling do not work as expected.
> > >> 
> > >> Signed-off-by: Niklas S�derlund <niklas.soderlund+renesas@ragnatech.se>
> > >> Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
> > >> ---
> > >> 
> > >>  drivers/media/platform/rcar-vin/rcar-dma.c  | 15 +-------
> > >>  drivers/media/platform/rcar-vin/rcar-v4l2.c | 53 +++++++++++------------
> > >>  2 files changed, 24 insertions(+), 44 deletions(-)
> 
> [snip]
> 
> > >> diff --git a/drivers/media/platform/rcar-vin/rcar-v4l2.c
> > >> b/drivers/media/platform/rcar-vin/rcar-v4l2.c index
> > >> 4d5be2d0c79c9c9a..9f7902d29c62e205 100644
> > >> --- a/drivers/media/platform/rcar-vin/rcar-v4l2.c
> > >> +++ b/drivers/media/platform/rcar-vin/rcar-v4l2.c
> > >> @@ -103,6 +103,28 @@ static int rvin_get_source_format(struct rvin_dev
> > >> *vin,
> > >>  	if (ret)
> > >>  		return ret;
> > >> 
> > >> +	switch (fmt.format.field) {
> > >> +	case V4L2_FIELD_TOP:
> > >> +	case V4L2_FIELD_BOTTOM:
> > >> +	case V4L2_FIELD_NONE:
> > >> +	case V4L2_FIELD_INTERLACED_TB:
> > >> +	case V4L2_FIELD_INTERLACED_BT:
> > >> +	case V4L2_FIELD_INTERLACED:
> > >> +		break;
> > >> +	case V4L2_FIELD_ALTERNATE:
> > >> +		/*
> > >> +		 * Driver do not (yet) support outputting ALTERNATE to a
> > >> +		 * userspace. It dose support outputting INTERLACED so use
> > > 
> > > s/dose/does/
> > > 
> > >> +		 * the VIN hardware to combine the two fields.
> > >> +		 */
> > >> +		fmt.format.field = V4L2_FIELD_INTERLACED;
> > >> +		fmt.format.height *= 2;
> > >> +		break;
> > > 
> > > I don't like this much. The rvin_get_source_format() function is supposed
> > > to return the media bus format for the bus between the source and the
> > > VIN. It's the caller that should take the field limitations into account,
> > > otherwise you end up with a mix of source and VIN data in the same
> > > structure.
> > 
> > When I read your comments I understand your argument better. And I
> > understand this function is perhaps poorly named. Maybe it should be
> > renamed to rvin_get_vin_format_from_source().
> 
> If you add a comment above the function I could live with that. Would it make 
> sense to pass a v4l2_pix_format structure instead of a v4l2_mbus_framefmt ?

I now see that the function name is misleading and I will change it as 
per above. I will also add a comment and swap to v4l2_pix_format (which 
was used before v10 but was changed due to your review comments, I'm 
happy you come around :-)

> 
> > The source format is fetched at s_stream() time in order to do format
> > validation. At this time the field is also taken into account once more
> > to validate that the VIN format (calculated here) still is valid. It
> > also handles the question you ask later at s_stream() time, see bellow.
> > 
> > >> +	default:
> > >> +		vin->format.field = V4L2_FIELD_NONE;
> > >> +		break;
> > >> +	}
> > >> +
> > >>  	memcpy(mbus_fmt, &fmt.format, sizeof(*mbus_fmt));
> > >>  	
> > >>  	return 0;
> > >> @@ -139,33 +161,6 @@ static int rvin_reset_format(struct rvin_dev *vin)
> > >> 
> > >>  	v4l2_fill_pix_format(&vin->format, &source_fmt);
> > >> 
> > >> -	/*
> > >> -	 * If the subdevice uses ALTERNATE field mode and G_STD is
> > >> -	 * implemented use the VIN HW to combine the two fields to
> > >> -	 * one INTERLACED frame. The ALTERNATE field mode can still
> > >> -	 * be requested in S_FMT and be respected, this is just the
> > >> -	 * default which is applied at probing or when S_STD is called.
> > >> -	 */
> > >> -	if (vin->format.field == V4L2_FIELD_ALTERNATE &&
> > >> -	    v4l2_subdev_has_op(vin_to_source(vin), video, g_std))
> > >> -		vin->format.field = V4L2_FIELD_INTERLACED;
> > >> -
> > >> -	switch (vin->format.field) {
> > >> -	case V4L2_FIELD_TOP:
> > >> -	case V4L2_FIELD_BOTTOM:
> > >> -	case V4L2_FIELD_ALTERNATE:
> > >> -		vin->format.height /= 2;
> > >> -		break;
> > >> -	case V4L2_FIELD_NONE:
> > >> -	case V4L2_FIELD_INTERLACED_TB:
> > >> -	case V4L2_FIELD_INTERLACED_BT:
> > >> -	case V4L2_FIELD_INTERLACED:
> > >> -		break;
> > >> -	default:
> > >> -		vin->format.field = V4L2_FIELD_NONE;
> > >> -		break;
> > >> -	}
> > >> -
> > >>  	ret = rvin_reset_crop_compose(vin);
> > >>  	if (ret)
> > >>  		return ret;
> > >> @@ -243,12 +238,10 @@ static int __rvin_try_format(struct rvin_dev *vin,
> > >>  	if (ret)
> > >>  		return ret;
> > >> 
> > >> +	/* Reject ALTERNATE  until support is added to the driver */
> > >>  	switch (pix->field) {
> > >>  	case V4L2_FIELD_TOP:
> > >>  	case V4L2_FIELD_BOTTOM:
> > >> -	case V4L2_FIELD_ALTERNATE:
> > >> -		pix->height /= 2;
> > >> -		break;
> > >>  	case V4L2_FIELD_NONE:
> > >>  	case V4L2_FIELD_INTERLACED_TB:
> > >>  	case V4L2_FIELD_INTERLACED_BT:
> > > 
> > > You will then set the field to V4L2_FIELD_NONE, but the source will still
> > > provide V4L2_FIELD_ALTERNATE. What will happen in the VIN, what will it
> > > produce ?
> > 
> > As stated above this is just the format produced from the VIN to
> > user-space. The source field is validated at s_stream() time, if it is
> > V4L2_FIELD_ALTERNATE the driver will handle it and possibly interlace it
> > depending on how the user wants to consume it, which is what is
> > specified here.
> 
> That was clearer when I read the patch that implemented .start_streaming() 
> support for the MC mode. Defaulting to V4L2_FIELD_NONE seems fine to me.
> 
> -- 
> Regards,
> 
> Laurent Pinchart
> 

-- 
Regards,
Niklas S�derlund

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v10 10/30] rcar-vin: fix handling of single field frames (top, bottom and alternate fields)
  2018-02-13 23:12           ` Niklas Söderlund
  (?)
@ 2018-02-13 23:28           ` Laurent Pinchart
  -1 siblings, 0 replies; 65+ messages in thread
From: Laurent Pinchart @ 2018-02-13 23:28 UTC (permalink / raw)
  To: Niklas Söderlund
  Cc: Hans Verkuil, linux-media, linux-renesas-soc, tomoharu.fukawa.eb,
	Kieran Bingham

Hi Niklas,

On Wednesday, 14 February 2018 01:12:50 EET Niklas Söderlund wrote:
> On 2018-02-14 00:31:21 +0200, Laurent Pinchart wrote:
> > On Tuesday, 13 February 2018 18:47:04 EET Niklas Söderlund wrote:
> >> On 2018-02-13 18:26:34 +0200, Laurent Pinchart wrote:
> >>> On Monday, 29 January 2018 18:34:15 EET Niklas Söderlund wrote:
> >>>> There was never proper support in the VIN driver to deliver
> >>>> ALTERNATING field format to user-space, remove this field option. The
> >>>> problem is that ALTERNATING filed order requires the sequence numbers
> >>>> of buffers returned to userspace to reflect if fields where dropped or
> >>>> not, something which is not possible with the VIN drivers capture
> >>>> logic.
> >>>> 
> >>>> The VIN driver can still capture from a video source which delivers
> >>>> frames in ALTERNATING field order, but needs to combine them using
> >>>> the VIN hardware into INTERLACED field order. Before this change if a
> >>>> source was delivering fields using ALTERNATE the driver would default
> >>>> to combining them using this hardware feature. Only if the user
> >>>> explicitly requested ALTERNATE filed order would incorrect frames be
> >>>> delivered.
> >>>> 
> >>>> The height should not be cut in half for the format for TOP or BOTTOM
> >>>> fields settings. This was a mistake and it was made visible by the
> >>>> scaling refactoring. Correct behavior is that the user should request
> >>>> a frame size that fits the half height frame reflected in the field
> >>>> setting. If not the VIN will do its best to scale the top or bottom
> >>>> to the requested format and cropping and scaling do not work as
> >>>> expected.
> >>>> 
> >>>> Signed-off-by: Niklas Söderlund
> >>>> <niklas.soderlund+renesas@ragnatech.se>
> >>>> Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
> >>>> ---
> >>>> 
> >>>>  drivers/media/platform/rcar-vin/rcar-dma.c  | 15 +-------
> >>>>  drivers/media/platform/rcar-vin/rcar-v4l2.c | 53
> >>>>  +++++++++++------------
> >>>>  2 files changed, 24 insertions(+), 44 deletions(-)
> > 
> > [snip]
> > 
> >>>> diff --git a/drivers/media/platform/rcar-vin/rcar-v4l2.c
> >>>> b/drivers/media/platform/rcar-vin/rcar-v4l2.c index
> >>>> 4d5be2d0c79c9c9a..9f7902d29c62e205 100644
> >>>> --- a/drivers/media/platform/rcar-vin/rcar-v4l2.c
> >>>> +++ b/drivers/media/platform/rcar-vin/rcar-v4l2.c
> >>>> @@ -103,6 +103,28 @@ static int rvin_get_source_format(struct
> >>>> rvin_dev *vin,
> >>>>  	if (ret)
> >>>>  		return ret;
> >>>> 
> >>>> +	switch (fmt.format.field) {
> >>>> +	case V4L2_FIELD_TOP:
> >>>> +	case V4L2_FIELD_BOTTOM:
> >>>> +	case V4L2_FIELD_NONE:
> >>>> +	case V4L2_FIELD_INTERLACED_TB:
> >>>> +	case V4L2_FIELD_INTERLACED_BT:
> >>>> +	case V4L2_FIELD_INTERLACED:
> >>>> +		break;
> >>>> +	case V4L2_FIELD_ALTERNATE:
> >>>> +		/*
> >>>> +		 * Driver do not (yet) support outputting ALTERNATE to a
> >>>> +		 * userspace. It dose support outputting INTERLACED so use
> >>> 
> >>> s/dose/does/
> >>> 
> >>>> +		 * the VIN hardware to combine the two fields.
> >>>> +		 */
> >>>> +		fmt.format.field = V4L2_FIELD_INTERLACED;
> >>>> +		fmt.format.height *= 2;
> >>>> +		break;
> >>> 
> >>> I don't like this much. The rvin_get_source_format() function is
> >>> supposed to return the media bus format for the bus between the source
> >>> and the VIN. It's the caller that should take the field limitations into
> >>> account, otherwise you end up with a mix of source and VIN data in the
> >>> same structure.
> >> 
> >> When I read your comments I understand your argument better. And I
> >> understand this function is perhaps poorly named. Maybe it should be
> >> renamed to rvin_get_vin_format_from_source().
> > 
> > If you add a comment above the function I could live with that. Would it
> > make sense to pass a v4l2_pix_format structure instead of a
> > v4l2_mbus_framefmt ?
> 
> I now see that the function name is misleading and I will change it as
> per above. I will also add a comment and swap to v4l2_pix_format (which
> was used before v10 but was changed due to your review comments, I'm
> happy you come around :-)

The argument type has to be consistent with the function's purpose and name. 
Now that you propose changing the function's purpose, my previous comments 
have to be updated. And I'm annoyed that you have such a good memory, it 
forces me to invent excuses :-)

> >> The source format is fetched at s_stream() time in order to do format
> >> validation. At this time the field is also taken into account once more
> >> to validate that the VIN format (calculated here) still is valid. It
> >> also handles the question you ask later at s_stream() time, see bellow.
> >> 
> >>>> +	default:
> >>>> +		vin->format.field = V4L2_FIELD_NONE;
> >>>> +		break;
> >>>> +	}
> >>>> +
> >>>>  	memcpy(mbus_fmt, &fmt.format, sizeof(*mbus_fmt));
> >>>>  	
> >>>>  	return 0;

[snip]

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 65+ messages in thread

end of thread, other threads:[~2018-02-13 23:28 UTC | newest]

Thread overview: 65+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-01-29 16:34 [PATCH v10 00/30] rcar-vin: Add Gen3 with media controller Niklas Söderlund
2018-01-29 16:34 ` [PATCH v10 01/30] rcar-vin: add Gen3 devicetree bindings documentation Niklas Söderlund
2018-02-13 15:24   ` Laurent Pinchart
2018-01-29 16:34 ` [PATCH v10 02/30] rcar-vin: rename poorly named initialize and cleanup functions Niklas Söderlund
2018-01-29 16:34 ` [PATCH v10 03/30] rcar-vin: unregister video device on driver removal Niklas Söderlund
2018-01-29 16:34 ` [PATCH v10 04/30] rcar-vin: move subdevice handling to async callbacks Niklas Söderlund
2018-02-13 15:47   ` Laurent Pinchart
2018-01-29 16:34 ` [PATCH v10 05/30] rcar-vin: move model information to own struct Niklas Söderlund
2018-01-29 16:34 ` [PATCH v10 06/30] rcar-vin: move max width and height information to chip information Niklas Söderlund
2018-01-29 16:34 ` [PATCH v10 07/30] rcar-vin: move functions regarding scaling Niklas Söderlund
2018-01-29 16:34 ` [PATCH v10 08/30] rcar-vin: all Gen2 boards can scale simplify logic Niklas Söderlund
2018-01-29 16:34 ` [PATCH v10 09/30] rcar-vin: read subdevice format for crop only when needed Niklas Söderlund
2018-02-13 16:14   ` Laurent Pinchart
2018-01-29 16:34 ` [PATCH v10 10/30] rcar-vin: fix handling of single field frames (top, bottom and alternate fields) Niklas Söderlund
2018-02-13 16:26   ` Laurent Pinchart
2018-02-13 16:47     ` Niklas Söderlund
2018-02-13 16:47       ` Niklas Söderlund
2018-02-13 22:31       ` Laurent Pinchart
2018-02-13 23:12         ` Niklas Söderlund
2018-02-13 23:12           ` Niklas Söderlund
2018-02-13 23:28           ` Laurent Pinchart
2018-01-29 16:34 ` [PATCH v10 11/30] rcar-vin: move media bus configuration to struct rvin_info Niklas Söderlund
2018-02-13 16:37   ` Laurent Pinchart
2018-01-29 16:34 ` [PATCH v10 12/30] rcar-vin: enable Gen3 hardware configuration Niklas Söderlund
2018-01-29 16:34 ` [PATCH v10 13/30] rcar-vin: add function to manipulate Gen3 chsel value Niklas Söderlund
2018-02-13 16:41   ` Laurent Pinchart
2018-02-13 16:58     ` Niklas Söderlund
2018-02-13 16:58       ` Niklas Söderlund
2018-02-13 17:02       ` Laurent Pinchart
2018-02-13 17:11         ` Niklas Söderlund
2018-02-13 17:11           ` Niklas Söderlund
2018-01-29 16:34 ` [PATCH v10 14/30] rcar-vin: add flag to switch to media controller mode Niklas Söderlund
2018-01-29 16:34 ` [PATCH v10 15/30] rcar-vin: break out format alignment and checking Niklas Söderlund
2018-02-13 16:56   ` Laurent Pinchart
2018-01-29 16:34 ` [PATCH v10 16/30] rcar-vin: update bytesperline and sizeimage calculation Niklas Söderlund
2018-02-13 16:58   ` Laurent Pinchart
2018-01-29 16:34 ` [PATCH v10 17/30] rcar-vin: update pixelformat check for M1 Niklas Söderlund
2018-02-13 17:03   ` Laurent Pinchart
2018-01-29 16:34 ` [PATCH v10 18/30] rcar-vin: add check for colorspace Niklas Söderlund
2018-02-13 17:08   ` Laurent Pinchart
2018-01-29 16:34 ` [PATCH v10 19/30] rcar-vin: set a default field to fallback on Niklas Söderlund
2018-02-13 17:51   ` Laurent Pinchart
2018-01-29 16:34 ` [PATCH v10 20/30] rcar-vin: use different v4l2 operations in media controller mode Niklas Söderlund
2018-02-13 19:42   ` Laurent Pinchart
2018-01-29 16:34 ` [PATCH v10 21/30] rcar-vin: prepare for media controller mode initialization Niklas Söderlund
2018-02-13 19:47   ` Laurent Pinchart
2018-01-29 16:34 ` [PATCH v10 22/30] rcar-vin: add group allocator functions Niklas Söderlund
2018-02-13 20:09   ` Laurent Pinchart
2018-01-29 16:34 ` [PATCH v10 23/30] rcar-vin: change name of video device Niklas Söderlund
2018-02-13 20:10   ` Laurent Pinchart
2018-01-29 16:34 ` [PATCH v10 24/30] rcar-vin: add chsel information to rvin_info Niklas Söderlund
2018-02-13 20:19   ` Laurent Pinchart
2018-01-29 16:34 ` [PATCH v10 25/30] rcar-vin: parse Gen3 OF and setup media graph Niklas Söderlund
2018-02-13 21:01   ` Laurent Pinchart
2018-01-29 16:34 ` [PATCH v10 26/30] rcar-vin: add link notify for Gen3 Niklas Söderlund
2018-02-13 21:17   ` Laurent Pinchart
2018-01-29 16:34 ` [PATCH v10 27/30] rcar-vin: extend {start,stop}_streaming to work with media controller Niklas Söderlund
2018-02-13 21:31   ` Laurent Pinchart
2018-01-29 16:34 ` [PATCH v10 28/30] rcar-vin: enable support for r8a7795 Niklas Söderlund
2018-02-13 21:52   ` Laurent Pinchart
2018-01-29 16:34 ` [PATCH v10 29/30] rcar-vin: enable support for r8a7796 Niklas Söderlund
2018-02-13 21:54   ` Laurent Pinchart
2018-02-13 21:55     ` Laurent Pinchart
2018-01-29 16:34 ` [PATCH v10 30/30] rcar-vin: enable support for r8a77970 Niklas Söderlund
2018-02-13 21:56   ` Laurent Pinchart

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.