All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v8 00/16] CSI2RX support on J721E and AM62
@ 2023-07-31  8:29 ` Jai Luthra
  0 siblings, 0 replies; 84+ messages in thread
From: Jai Luthra @ 2023-07-31  8:29 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Sakari Ailus, Laurent Pinchart, Tomi Valkeinen
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht, j-luthra

Hi,

This series adds support for CSI2 capture on J721E. It includes some
fixes to the Cadence CSI2RX driver, and adds the TI CSI2RX wrapper driver.

This is a V8 of the below V7 series,
https://lore.kernel.org/all/20230314115516.667-1-vaishnav.a@ti.com/

Since Pratyush moved out of TI, Vaishnav & I have been working on
this driver, and I will be maintaining it upstream.

J721E CSI2RX driver can also be extended to support multi-stream
capture, filtering different CSI Virtual Channels (VC) or Data Types
(DT) to different DMA channels. A WIP series based on v7 is available
for reference at https://github.com/jailuthra/linux/commits/csi_multi_wip

I will rebase the multi-stream patches on the current series (v8) and
post them as RFC in the coming weeks.

Testing logs: https://gist.github.com/jailuthra/eaeb3af3c65b67e1bc0d5db28180131d

Signed-off-by: Jai Luthra <j-luthra@ti.com>
---

Range-diff from v7 -> v8: http://0x0.st/H21u.diff

New Patches:
[01/16]	   Export v4l2_subdev_link_validate_get_format() helper
[03-04/16] Add new compatible for TI-specific SoC intergration of the
           Cadence CSI2RX bridge IP
[14/16]    Add support for RAW8 and RAW10 formats in Cadence CSI2RX

For [07/16] media: cadence: csi2rx: Add get_fmt and set_fmt pad ops:
- Use active subdev state to use v4l2_subdev_get_fmt
- Propagate formats from sink to source pads
- Drop Laurent's R-by because of the above changes

For [08/16] media: cadence: csi2rx: Configure DPHY using link freq:
- Drop original patch in-lieu of already merged
  https://lore.kernel.org/linux-media/20230523085626.3295-5-jack.zhu@starfivetech.com/
- Add a new patch to configure DPHY using link_freq control from the
  source

For [10/16] media: cadence: csi2rx: Set the STOP bit when stopping a stream:
- Fix bug where intention was to wait till stream status is idle, i.e.
  STREAM_STATUS[31] -> 0 - but we were instead checking the opposite

For [15/16] media: dt-bindings: Add DT bindings for TI J721E CSI2RX driver:
- Drop "Device Tree Bindings" from title
- Rename "Wrapper" to "Shim" in title as that is the name referred in
  the TRM and other places
- Update maintainer to myself
- Drop items from compatible as only a single element is present
- Rename compatible to "ti,j721e-csi2rx-shim" to distinguish from the
  SoC-specific CSI2RX bridge compatible

For [16/16] media: ti: Add CSI2RX support for J721E:
- Move after dt-bindings to keep the series bisectable
- Rename compatible to "ti,j721e-csi2rx-shim" to distinguish from the
  SoC-specific CSI2RX bridge compatible
- Make myself the Maintainer
- Support RAW8 and RAW10 formats, and setting the pixel-unwrap size on
  SHIM (RAW10 is stored in 16-bit containers, while RAW8 in 8-bit containers)
- Fix enum_fmt_vid_cap() to respect CAP_IO_MC and only list pixelformats
  matching the mbus formats set on the subdev.
- Fix enum_framesizes() to stop enumerating more than a single framesize
  (reject non-zero fsize->index)
- Simplify notifier bound fucntion to use v4l2_create_fwnode_links_to_pad()
  and inline the video_register() method
- Add support for draining the DMA with an extra buffer, to get rid of
  stale data in the pipeline on stream stop (or when frames start
  getting dropped due to load)
- Queue all available buffers to DMAEngine in the callback, also use a
  separate "submitted" queue to track all buffers submitted to DMA
- Use video_device_pipeline_start() instead of media_pipeline_start()
- Drop support for VB_READ
- Print issues in link validation as DEBUG instead of ERROR
- s/async_subdev/async_connection

For [v7 13/13] media: dt-bindings: Convert Cadence CSI2RX binding to YAML:
 - Drop patch in-lieu of
   https://lore.kernel.org/linux-media/20230523085626.3295-2-jack.zhu@starfivetech.com/

---
Jai Luthra (4):
      media: subdev: Export get_format helper for link validation
      media: dt-bindings: cadence-csi2rx: Add TI compatible string
      media: cadence: Add support for TI SoCs
      media: cadence: csi2rx: Support RAW8 and RAW10 formats

Pratyush Yadav (12):
      media: dt-bindings: Make sure items in data-lanes are unique
      media: cadence: csi2rx: Unregister v4l2 async notifier
      media: cadence: csi2rx: Cleanup media entity properly
      media: cadence: csi2rx: Add get_fmt and set_fmt pad ops
      media: cadence: csi2rx: Configure DPHY using link freq
      media: cadence: csi2rx: Soft reset the streams before starting capture
      media: cadence: csi2rx: Set the STOP bit when stopping a stream
      media: cadence: csi2rx: Fix stream data configuration
      media: cadence: csi2rx: Populate subdev devnode
      media: cadence: csi2rx: Add link validation
      media: dt-bindings: Add TI J721E CSI2RX
      media: ti: Add CSI2RX support for J721E

 .../devicetree/bindings/media/cdns,csi2rx.yaml     |    1 +
 .../bindings/media/ti,j721e-csi2rx-shim.yaml       |  100 ++
 .../bindings/media/video-interfaces.yaml           |    1 +
 MAINTAINERS                                        |    7 +
 drivers/media/platform/cadence/cdns-csi2rx.c       |  217 +++-
 drivers/media/platform/ti/Kconfig                  |   12 +
 drivers/media/platform/ti/Makefile                 |    1 +
 drivers/media/platform/ti/j721e-csi2rx/Makefile    |    2 +
 .../media/platform/ti/j721e-csi2rx/j721e-csi2rx.c  | 1127 ++++++++++++++++++++
 drivers/media/v4l2-core/v4l2-subdev.c              |    8 +-
 include/media/v4l2-subdev.h                        |   12 +
 11 files changed, 1478 insertions(+), 10 deletions(-)
---
base-commit: ec89391563792edd11d138a853901bce76d11f44
change-id: 20230727-upstream_csi-acbeabe038d8

Best regards,
-- 
Jai Luthra <j-luthra@ti.com>

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

* [PATCH v8 00/16] CSI2RX support on J721E and AM62
@ 2023-07-31  8:29 ` Jai Luthra
  0 siblings, 0 replies; 84+ messages in thread
From: Jai Luthra @ 2023-07-31  8:29 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Sakari Ailus, Laurent Pinchart, Tomi Valkeinen
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht, j-luthra

Hi,

This series adds support for CSI2 capture on J721E. It includes some
fixes to the Cadence CSI2RX driver, and adds the TI CSI2RX wrapper driver.

This is a V8 of the below V7 series,
https://lore.kernel.org/all/20230314115516.667-1-vaishnav.a@ti.com/

Since Pratyush moved out of TI, Vaishnav & I have been working on
this driver, and I will be maintaining it upstream.

J721E CSI2RX driver can also be extended to support multi-stream
capture, filtering different CSI Virtual Channels (VC) or Data Types
(DT) to different DMA channels. A WIP series based on v7 is available
for reference at https://github.com/jailuthra/linux/commits/csi_multi_wip

I will rebase the multi-stream patches on the current series (v8) and
post them as RFC in the coming weeks.

Testing logs: https://gist.github.com/jailuthra/eaeb3af3c65b67e1bc0d5db28180131d

Signed-off-by: Jai Luthra <j-luthra@ti.com>
---

Range-diff from v7 -> v8: http://0x0.st/H21u.diff

New Patches:
[01/16]	   Export v4l2_subdev_link_validate_get_format() helper
[03-04/16] Add new compatible for TI-specific SoC intergration of the
           Cadence CSI2RX bridge IP
[14/16]    Add support for RAW8 and RAW10 formats in Cadence CSI2RX

For [07/16] media: cadence: csi2rx: Add get_fmt and set_fmt pad ops:
- Use active subdev state to use v4l2_subdev_get_fmt
- Propagate formats from sink to source pads
- Drop Laurent's R-by because of the above changes

For [08/16] media: cadence: csi2rx: Configure DPHY using link freq:
- Drop original patch in-lieu of already merged
  https://lore.kernel.org/linux-media/20230523085626.3295-5-jack.zhu@starfivetech.com/
- Add a new patch to configure DPHY using link_freq control from the
  source

For [10/16] media: cadence: csi2rx: Set the STOP bit when stopping a stream:
- Fix bug where intention was to wait till stream status is idle, i.e.
  STREAM_STATUS[31] -> 0 - but we were instead checking the opposite

For [15/16] media: dt-bindings: Add DT bindings for TI J721E CSI2RX driver:
- Drop "Device Tree Bindings" from title
- Rename "Wrapper" to "Shim" in title as that is the name referred in
  the TRM and other places
- Update maintainer to myself
- Drop items from compatible as only a single element is present
- Rename compatible to "ti,j721e-csi2rx-shim" to distinguish from the
  SoC-specific CSI2RX bridge compatible

For [16/16] media: ti: Add CSI2RX support for J721E:
- Move after dt-bindings to keep the series bisectable
- Rename compatible to "ti,j721e-csi2rx-shim" to distinguish from the
  SoC-specific CSI2RX bridge compatible
- Make myself the Maintainer
- Support RAW8 and RAW10 formats, and setting the pixel-unwrap size on
  SHIM (RAW10 is stored in 16-bit containers, while RAW8 in 8-bit containers)
- Fix enum_fmt_vid_cap() to respect CAP_IO_MC and only list pixelformats
  matching the mbus formats set on the subdev.
- Fix enum_framesizes() to stop enumerating more than a single framesize
  (reject non-zero fsize->index)
- Simplify notifier bound fucntion to use v4l2_create_fwnode_links_to_pad()
  and inline the video_register() method
- Add support for draining the DMA with an extra buffer, to get rid of
  stale data in the pipeline on stream stop (or when frames start
  getting dropped due to load)
- Queue all available buffers to DMAEngine in the callback, also use a
  separate "submitted" queue to track all buffers submitted to DMA
- Use video_device_pipeline_start() instead of media_pipeline_start()
- Drop support for VB_READ
- Print issues in link validation as DEBUG instead of ERROR
- s/async_subdev/async_connection

For [v7 13/13] media: dt-bindings: Convert Cadence CSI2RX binding to YAML:
 - Drop patch in-lieu of
   https://lore.kernel.org/linux-media/20230523085626.3295-2-jack.zhu@starfivetech.com/

---
Jai Luthra (4):
      media: subdev: Export get_format helper for link validation
      media: dt-bindings: cadence-csi2rx: Add TI compatible string
      media: cadence: Add support for TI SoCs
      media: cadence: csi2rx: Support RAW8 and RAW10 formats

Pratyush Yadav (12):
      media: dt-bindings: Make sure items in data-lanes are unique
      media: cadence: csi2rx: Unregister v4l2 async notifier
      media: cadence: csi2rx: Cleanup media entity properly
      media: cadence: csi2rx: Add get_fmt and set_fmt pad ops
      media: cadence: csi2rx: Configure DPHY using link freq
      media: cadence: csi2rx: Soft reset the streams before starting capture
      media: cadence: csi2rx: Set the STOP bit when stopping a stream
      media: cadence: csi2rx: Fix stream data configuration
      media: cadence: csi2rx: Populate subdev devnode
      media: cadence: csi2rx: Add link validation
      media: dt-bindings: Add TI J721E CSI2RX
      media: ti: Add CSI2RX support for J721E

 .../devicetree/bindings/media/cdns,csi2rx.yaml     |    1 +
 .../bindings/media/ti,j721e-csi2rx-shim.yaml       |  100 ++
 .../bindings/media/video-interfaces.yaml           |    1 +
 MAINTAINERS                                        |    7 +
 drivers/media/platform/cadence/cdns-csi2rx.c       |  217 +++-
 drivers/media/platform/ti/Kconfig                  |   12 +
 drivers/media/platform/ti/Makefile                 |    1 +
 drivers/media/platform/ti/j721e-csi2rx/Makefile    |    2 +
 .../media/platform/ti/j721e-csi2rx/j721e-csi2rx.c  | 1127 ++++++++++++++++++++
 drivers/media/v4l2-core/v4l2-subdev.c              |    8 +-
 include/media/v4l2-subdev.h                        |   12 +
 11 files changed, 1478 insertions(+), 10 deletions(-)
---
base-commit: ec89391563792edd11d138a853901bce76d11f44
change-id: 20230727-upstream_csi-acbeabe038d8

Best regards,
-- 
Jai Luthra <j-luthra@ti.com>

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v8 01/16] media: subdev: Export get_format helper for link validation
  2023-07-31  8:29 ` Jai Luthra
@ 2023-07-31  8:29   ` Jai Luthra
  -1 siblings, 0 replies; 84+ messages in thread
From: Jai Luthra @ 2023-07-31  8:29 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Sakari Ailus, Laurent Pinchart, Tomi Valkeinen
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht, j-luthra

For link validation on video device drivers, it may be required to
match the formats set on the source subdev with the formats set on the
video device.

Export the existing v4l2_subdev_link_validate_get_format() helper so it
can be reused by such drivers.

Suggested-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Jai Luthra <j-luthra@ti.com>
---
New in v8

 drivers/media/v4l2-core/v4l2-subdev.c |  8 ++++----
 include/media/v4l2-subdev.h           | 12 ++++++++++++
 2 files changed, 16 insertions(+), 4 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c
index 217b8019fb9b..0d3b5ff5cacc 100644
--- a/drivers/media/v4l2-core/v4l2-subdev.c
+++ b/drivers/media/v4l2-core/v4l2-subdev.c
@@ -1130,10 +1130,9 @@ int v4l2_subdev_link_validate_default(struct v4l2_subdev *sd,
 }
 EXPORT_SYMBOL_GPL(v4l2_subdev_link_validate_default);
 
-static int
-v4l2_subdev_link_validate_get_format(struct media_pad *pad, u32 stream,
-				     struct v4l2_subdev_format *fmt,
-				     bool states_locked)
+int v4l2_subdev_link_validate_get_format(struct media_pad *pad, u32 stream,
+					 struct v4l2_subdev_format *fmt,
+					 bool states_locked)
 {
 	struct v4l2_subdev_state *state;
 	struct v4l2_subdev *sd;
@@ -1165,6 +1164,7 @@ v4l2_subdev_link_validate_get_format(struct media_pad *pad, u32 stream,
 
 	return ret;
 }
+EXPORT_SYMBOL_GPL(v4l2_subdev_link_validate_get_format);
 
 #if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
 
diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
index a012741cc876..ef7007f46889 100644
--- a/include/media/v4l2-subdev.h
+++ b/include/media/v4l2-subdev.h
@@ -1301,6 +1301,18 @@ int v4l2_subdev_link_validate_default(struct v4l2_subdev *sd,
 				      struct v4l2_subdev_format *source_fmt,
 				      struct v4l2_subdev_format *sink_fmt);
 
+/**
+ * v4l2_subdev_link_validate_get_format - get format for media link validation
+ *
+ * @pad: pad id
+ * @stream: stream id
+ * @fmt: pointer to &struct v4l2_subdev_format
+ * @states_locked: is the subdev state already locked
+ */
+int v4l2_subdev_link_validate_get_format(struct media_pad *pad, u32 stream,
+					 struct v4l2_subdev_format *fmt,
+					 bool states_locked);
+
 /**
  * v4l2_subdev_link_validate - validates a media link
  *

-- 
2.41.0

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

* [PATCH v8 01/16] media: subdev: Export get_format helper for link validation
@ 2023-07-31  8:29   ` Jai Luthra
  0 siblings, 0 replies; 84+ messages in thread
From: Jai Luthra @ 2023-07-31  8:29 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Sakari Ailus, Laurent Pinchart, Tomi Valkeinen
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht, j-luthra

For link validation on video device drivers, it may be required to
match the formats set on the source subdev with the formats set on the
video device.

Export the existing v4l2_subdev_link_validate_get_format() helper so it
can be reused by such drivers.

Suggested-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Jai Luthra <j-luthra@ti.com>
---
New in v8

 drivers/media/v4l2-core/v4l2-subdev.c |  8 ++++----
 include/media/v4l2-subdev.h           | 12 ++++++++++++
 2 files changed, 16 insertions(+), 4 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c
index 217b8019fb9b..0d3b5ff5cacc 100644
--- a/drivers/media/v4l2-core/v4l2-subdev.c
+++ b/drivers/media/v4l2-core/v4l2-subdev.c
@@ -1130,10 +1130,9 @@ int v4l2_subdev_link_validate_default(struct v4l2_subdev *sd,
 }
 EXPORT_SYMBOL_GPL(v4l2_subdev_link_validate_default);
 
-static int
-v4l2_subdev_link_validate_get_format(struct media_pad *pad, u32 stream,
-				     struct v4l2_subdev_format *fmt,
-				     bool states_locked)
+int v4l2_subdev_link_validate_get_format(struct media_pad *pad, u32 stream,
+					 struct v4l2_subdev_format *fmt,
+					 bool states_locked)
 {
 	struct v4l2_subdev_state *state;
 	struct v4l2_subdev *sd;
@@ -1165,6 +1164,7 @@ v4l2_subdev_link_validate_get_format(struct media_pad *pad, u32 stream,
 
 	return ret;
 }
+EXPORT_SYMBOL_GPL(v4l2_subdev_link_validate_get_format);
 
 #if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
 
diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
index a012741cc876..ef7007f46889 100644
--- a/include/media/v4l2-subdev.h
+++ b/include/media/v4l2-subdev.h
@@ -1301,6 +1301,18 @@ int v4l2_subdev_link_validate_default(struct v4l2_subdev *sd,
 				      struct v4l2_subdev_format *source_fmt,
 				      struct v4l2_subdev_format *sink_fmt);
 
+/**
+ * v4l2_subdev_link_validate_get_format - get format for media link validation
+ *
+ * @pad: pad id
+ * @stream: stream id
+ * @fmt: pointer to &struct v4l2_subdev_format
+ * @states_locked: is the subdev state already locked
+ */
+int v4l2_subdev_link_validate_get_format(struct media_pad *pad, u32 stream,
+					 struct v4l2_subdev_format *fmt,
+					 bool states_locked);
+
 /**
  * v4l2_subdev_link_validate - validates a media link
  *

-- 
2.41.0

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v8 02/16] media: dt-bindings: Make sure items in data-lanes are unique
  2023-07-31  8:29 ` Jai Luthra
@ 2023-07-31  8:29   ` Jai Luthra
  -1 siblings, 0 replies; 84+ messages in thread
From: Jai Luthra @ 2023-07-31  8:29 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Sakari Ailus, Laurent Pinchart, Tomi Valkeinen
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht, j-luthra

From: Pratyush Yadav <p.yadav@ti.com>

The data-lanes property maps the logical lane numbers to the physical
lane numbers. The position of an entry is the logical lane number and
its value is the physical lane number. Since one physical lane can only
map to one logical lane, no number in the list should repeat. Add the
uniqueItems constraint on the property to enforce this.

Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
Signed-off-by: Jai Luthra <j-luthra@ti.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: Rob Herring <robh@kernel.org>
---
v7->v8: No change

 Documentation/devicetree/bindings/media/video-interfaces.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/media/video-interfaces.yaml b/Documentation/devicetree/bindings/media/video-interfaces.yaml
index a211d49dc2ac..26e3e7d7c67b 100644
--- a/Documentation/devicetree/bindings/media/video-interfaces.yaml
+++ b/Documentation/devicetree/bindings/media/video-interfaces.yaml
@@ -160,6 +160,7 @@ properties:
     $ref: /schemas/types.yaml#/definitions/uint32-array
     minItems: 1
     maxItems: 8
+    uniqueItems: true
     items:
       # Assume up to 9 physical lane indices
       maximum: 8

-- 
2.41.0

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

* [PATCH v8 02/16] media: dt-bindings: Make sure items in data-lanes are unique
@ 2023-07-31  8:29   ` Jai Luthra
  0 siblings, 0 replies; 84+ messages in thread
From: Jai Luthra @ 2023-07-31  8:29 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Sakari Ailus, Laurent Pinchart, Tomi Valkeinen
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht, j-luthra

From: Pratyush Yadav <p.yadav@ti.com>

The data-lanes property maps the logical lane numbers to the physical
lane numbers. The position of an entry is the logical lane number and
its value is the physical lane number. Since one physical lane can only
map to one logical lane, no number in the list should repeat. Add the
uniqueItems constraint on the property to enforce this.

Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
Signed-off-by: Jai Luthra <j-luthra@ti.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: Rob Herring <robh@kernel.org>
---
v7->v8: No change

 Documentation/devicetree/bindings/media/video-interfaces.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/media/video-interfaces.yaml b/Documentation/devicetree/bindings/media/video-interfaces.yaml
index a211d49dc2ac..26e3e7d7c67b 100644
--- a/Documentation/devicetree/bindings/media/video-interfaces.yaml
+++ b/Documentation/devicetree/bindings/media/video-interfaces.yaml
@@ -160,6 +160,7 @@ properties:
     $ref: /schemas/types.yaml#/definitions/uint32-array
     minItems: 1
     maxItems: 8
+    uniqueItems: true
     items:
       # Assume up to 9 physical lane indices
       maximum: 8

-- 
2.41.0

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v8 03/16] media: dt-bindings: cadence-csi2rx: Add TI compatible string
  2023-07-31  8:29 ` Jai Luthra
@ 2023-07-31  8:29   ` Jai Luthra
  -1 siblings, 0 replies; 84+ messages in thread
From: Jai Luthra @ 2023-07-31  8:29 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Sakari Ailus, Laurent Pinchart, Tomi Valkeinen
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht, j-luthra

Add a SoC-specific compatible string for TI's integration of this IP in
J7 and AM62 line of SoCs.

Signed-off-by: Jai Luthra <j-luthra@ti.com>
---
New in v8

 Documentation/devicetree/bindings/media/cdns,csi2rx.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/media/cdns,csi2rx.yaml b/Documentation/devicetree/bindings/media/cdns,csi2rx.yaml
index 30a335b10762..2008a47c0580 100644
--- a/Documentation/devicetree/bindings/media/cdns,csi2rx.yaml
+++ b/Documentation/devicetree/bindings/media/cdns,csi2rx.yaml
@@ -18,6 +18,7 @@ properties:
     items:
       - enum:
           - starfive,jh7110-csi2rx
+          - ti,j721e-csi2rx
       - const: cdns,csi2rx
 
   reg:

-- 
2.41.0

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

* [PATCH v8 03/16] media: dt-bindings: cadence-csi2rx: Add TI compatible string
@ 2023-07-31  8:29   ` Jai Luthra
  0 siblings, 0 replies; 84+ messages in thread
From: Jai Luthra @ 2023-07-31  8:29 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Sakari Ailus, Laurent Pinchart, Tomi Valkeinen
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht, j-luthra

Add a SoC-specific compatible string for TI's integration of this IP in
J7 and AM62 line of SoCs.

Signed-off-by: Jai Luthra <j-luthra@ti.com>
---
New in v8

 Documentation/devicetree/bindings/media/cdns,csi2rx.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/media/cdns,csi2rx.yaml b/Documentation/devicetree/bindings/media/cdns,csi2rx.yaml
index 30a335b10762..2008a47c0580 100644
--- a/Documentation/devicetree/bindings/media/cdns,csi2rx.yaml
+++ b/Documentation/devicetree/bindings/media/cdns,csi2rx.yaml
@@ -18,6 +18,7 @@ properties:
     items:
       - enum:
           - starfive,jh7110-csi2rx
+          - ti,j721e-csi2rx
       - const: cdns,csi2rx
 
   reg:

-- 
2.41.0

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v8 04/16] media: cadence: Add support for TI SoCs
  2023-07-31  8:29 ` Jai Luthra
@ 2023-07-31  8:29   ` Jai Luthra
  -1 siblings, 0 replies; 84+ messages in thread
From: Jai Luthra @ 2023-07-31  8:29 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Sakari Ailus, Laurent Pinchart, Tomi Valkeinen
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht, j-luthra

Multiple TI SoCs (J721E, AM62) use this CSI2RX receiver, integrated with
an external DPHY and a pixel-grabber IP that unwraps the pixel data and
send it to memory via DMA.

Add a separate compatible for the TI-specific version of this IP.

Signed-off-by: Jai Luthra <j-luthra@ti.com>
---
New in v8

 drivers/media/platform/cadence/cdns-csi2rx.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/media/platform/cadence/cdns-csi2rx.c b/drivers/media/platform/cadence/cdns-csi2rx.c
index 0d879d71d818..b087583d636f 100644
--- a/drivers/media/platform/cadence/cdns-csi2rx.c
+++ b/drivers/media/platform/cadence/cdns-csi2rx.c
@@ -559,6 +559,7 @@ static void csi2rx_remove(struct platform_device *pdev)
 
 static const struct of_device_id csi2rx_of_table[] = {
 	{ .compatible = "starfive,jh7110-csi2rx" },
+	{ .compatible = "ti,j721e-csi2rx" },
 	{ .compatible = "cdns,csi2rx" },
 	{ },
 };

-- 
2.41.0

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

* [PATCH v8 04/16] media: cadence: Add support for TI SoCs
@ 2023-07-31  8:29   ` Jai Luthra
  0 siblings, 0 replies; 84+ messages in thread
From: Jai Luthra @ 2023-07-31  8:29 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Sakari Ailus, Laurent Pinchart, Tomi Valkeinen
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht, j-luthra

Multiple TI SoCs (J721E, AM62) use this CSI2RX receiver, integrated with
an external DPHY and a pixel-grabber IP that unwraps the pixel data and
send it to memory via DMA.

Add a separate compatible for the TI-specific version of this IP.

Signed-off-by: Jai Luthra <j-luthra@ti.com>
---
New in v8

 drivers/media/platform/cadence/cdns-csi2rx.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/media/platform/cadence/cdns-csi2rx.c b/drivers/media/platform/cadence/cdns-csi2rx.c
index 0d879d71d818..b087583d636f 100644
--- a/drivers/media/platform/cadence/cdns-csi2rx.c
+++ b/drivers/media/platform/cadence/cdns-csi2rx.c
@@ -559,6 +559,7 @@ static void csi2rx_remove(struct platform_device *pdev)
 
 static const struct of_device_id csi2rx_of_table[] = {
 	{ .compatible = "starfive,jh7110-csi2rx" },
+	{ .compatible = "ti,j721e-csi2rx" },
 	{ .compatible = "cdns,csi2rx" },
 	{ },
 };

-- 
2.41.0

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v8 05/16] media: cadence: csi2rx: Unregister v4l2 async notifier
  2023-07-31  8:29 ` Jai Luthra
@ 2023-07-31  8:29   ` Jai Luthra
  -1 siblings, 0 replies; 84+ messages in thread
From: Jai Luthra @ 2023-07-31  8:29 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Sakari Ailus, Laurent Pinchart, Tomi Valkeinen
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht, j-luthra

From: Pratyush Yadav <p.yadav@ti.com>

The notifier is added to the global notifier list when registered. When
the module is removed, the struct csi2rx_priv in which the notifier is
embedded, is destroyed. As a result the notifier list has a reference to
a notifier that no longer exists. This causes invalid memory accesses
when the list is iterated over. Similar for when the probe fails.
Unregister and clean up the notifier to avoid this.

Fixes: 1fc3b37f34f6 ("media: v4l: cadence: Add Cadence MIPI-CSI2 RX driver")

Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
Signed-off-by: Jai Luthra <j-luthra@ti.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
v7->v8: No change

 drivers/media/platform/cadence/cdns-csi2rx.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/media/platform/cadence/cdns-csi2rx.c b/drivers/media/platform/cadence/cdns-csi2rx.c
index b087583d636f..fd6f2e04e77f 100644
--- a/drivers/media/platform/cadence/cdns-csi2rx.c
+++ b/drivers/media/platform/cadence/cdns-csi2rx.c
@@ -479,8 +479,10 @@ static int csi2rx_parse_dt(struct csi2rx_priv *csi2rx)
 	asd = v4l2_async_nf_add_fwnode_remote(&csi2rx->notifier, fwh,
 					      struct v4l2_async_connection);
 	of_node_put(ep);
-	if (IS_ERR(asd))
+	if (IS_ERR(asd)) {
+		v4l2_async_nf_cleanup(&csi2rx->notifier);
 		return PTR_ERR(asd);
+	}
 
 	csi2rx->notifier.ops = &csi2rx_notifier_ops;
 
@@ -543,6 +545,7 @@ static int csi2rx_probe(struct platform_device *pdev)
 	return 0;
 
 err_cleanup:
+	v4l2_async_nf_unregister(&csi2rx->notifier);
 	v4l2_async_nf_cleanup(&csi2rx->notifier);
 err_free_priv:
 	kfree(csi2rx);
@@ -553,6 +556,8 @@ static void csi2rx_remove(struct platform_device *pdev)
 {
 	struct csi2rx_priv *csi2rx = platform_get_drvdata(pdev);
 
+	v4l2_async_nf_unregister(&csi2rx->notifier);
+	v4l2_async_nf_cleanup(&csi2rx->notifier);
 	v4l2_async_unregister_subdev(&csi2rx->subdev);
 	kfree(csi2rx);
 }

-- 
2.41.0

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

* [PATCH v8 05/16] media: cadence: csi2rx: Unregister v4l2 async notifier
@ 2023-07-31  8:29   ` Jai Luthra
  0 siblings, 0 replies; 84+ messages in thread
From: Jai Luthra @ 2023-07-31  8:29 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Sakari Ailus, Laurent Pinchart, Tomi Valkeinen
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht, j-luthra

From: Pratyush Yadav <p.yadav@ti.com>

The notifier is added to the global notifier list when registered. When
the module is removed, the struct csi2rx_priv in which the notifier is
embedded, is destroyed. As a result the notifier list has a reference to
a notifier that no longer exists. This causes invalid memory accesses
when the list is iterated over. Similar for when the probe fails.
Unregister and clean up the notifier to avoid this.

Fixes: 1fc3b37f34f6 ("media: v4l: cadence: Add Cadence MIPI-CSI2 RX driver")

Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
Signed-off-by: Jai Luthra <j-luthra@ti.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
v7->v8: No change

 drivers/media/platform/cadence/cdns-csi2rx.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/media/platform/cadence/cdns-csi2rx.c b/drivers/media/platform/cadence/cdns-csi2rx.c
index b087583d636f..fd6f2e04e77f 100644
--- a/drivers/media/platform/cadence/cdns-csi2rx.c
+++ b/drivers/media/platform/cadence/cdns-csi2rx.c
@@ -479,8 +479,10 @@ static int csi2rx_parse_dt(struct csi2rx_priv *csi2rx)
 	asd = v4l2_async_nf_add_fwnode_remote(&csi2rx->notifier, fwh,
 					      struct v4l2_async_connection);
 	of_node_put(ep);
-	if (IS_ERR(asd))
+	if (IS_ERR(asd)) {
+		v4l2_async_nf_cleanup(&csi2rx->notifier);
 		return PTR_ERR(asd);
+	}
 
 	csi2rx->notifier.ops = &csi2rx_notifier_ops;
 
@@ -543,6 +545,7 @@ static int csi2rx_probe(struct platform_device *pdev)
 	return 0;
 
 err_cleanup:
+	v4l2_async_nf_unregister(&csi2rx->notifier);
 	v4l2_async_nf_cleanup(&csi2rx->notifier);
 err_free_priv:
 	kfree(csi2rx);
@@ -553,6 +556,8 @@ static void csi2rx_remove(struct platform_device *pdev)
 {
 	struct csi2rx_priv *csi2rx = platform_get_drvdata(pdev);
 
+	v4l2_async_nf_unregister(&csi2rx->notifier);
+	v4l2_async_nf_cleanup(&csi2rx->notifier);
 	v4l2_async_unregister_subdev(&csi2rx->subdev);
 	kfree(csi2rx);
 }

-- 
2.41.0

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v8 06/16] media: cadence: csi2rx: Cleanup media entity properly
  2023-07-31  8:29 ` Jai Luthra
@ 2023-07-31  8:29   ` Jai Luthra
  -1 siblings, 0 replies; 84+ messages in thread
From: Jai Luthra @ 2023-07-31  8:29 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Sakari Ailus, Laurent Pinchart, Tomi Valkeinen
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht, j-luthra

From: Pratyush Yadav <p.yadav@ti.com>

Call media_entity_cleanup() in probe error path and remove to make sure
the media entity is cleaned up properly.

Suggested-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
Signed-off-by: Jai Luthra <j-luthra@ti.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
v7->v8: No change

 drivers/media/platform/cadence/cdns-csi2rx.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/media/platform/cadence/cdns-csi2rx.c b/drivers/media/platform/cadence/cdns-csi2rx.c
index fd6f2e04e77f..83d1fadd592b 100644
--- a/drivers/media/platform/cadence/cdns-csi2rx.c
+++ b/drivers/media/platform/cadence/cdns-csi2rx.c
@@ -547,6 +547,7 @@ static int csi2rx_probe(struct platform_device *pdev)
 err_cleanup:
 	v4l2_async_nf_unregister(&csi2rx->notifier);
 	v4l2_async_nf_cleanup(&csi2rx->notifier);
+	media_entity_cleanup(&csi2rx->subdev.entity);
 err_free_priv:
 	kfree(csi2rx);
 	return ret;
@@ -559,6 +560,7 @@ static void csi2rx_remove(struct platform_device *pdev)
 	v4l2_async_nf_unregister(&csi2rx->notifier);
 	v4l2_async_nf_cleanup(&csi2rx->notifier);
 	v4l2_async_unregister_subdev(&csi2rx->subdev);
+	media_entity_cleanup(&csi2rx->subdev.entity);
 	kfree(csi2rx);
 }
 

-- 
2.41.0

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

* [PATCH v8 06/16] media: cadence: csi2rx: Cleanup media entity properly
@ 2023-07-31  8:29   ` Jai Luthra
  0 siblings, 0 replies; 84+ messages in thread
From: Jai Luthra @ 2023-07-31  8:29 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Sakari Ailus, Laurent Pinchart, Tomi Valkeinen
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht, j-luthra

From: Pratyush Yadav <p.yadav@ti.com>

Call media_entity_cleanup() in probe error path and remove to make sure
the media entity is cleaned up properly.

Suggested-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
Signed-off-by: Jai Luthra <j-luthra@ti.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
v7->v8: No change

 drivers/media/platform/cadence/cdns-csi2rx.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/media/platform/cadence/cdns-csi2rx.c b/drivers/media/platform/cadence/cdns-csi2rx.c
index fd6f2e04e77f..83d1fadd592b 100644
--- a/drivers/media/platform/cadence/cdns-csi2rx.c
+++ b/drivers/media/platform/cadence/cdns-csi2rx.c
@@ -547,6 +547,7 @@ static int csi2rx_probe(struct platform_device *pdev)
 err_cleanup:
 	v4l2_async_nf_unregister(&csi2rx->notifier);
 	v4l2_async_nf_cleanup(&csi2rx->notifier);
+	media_entity_cleanup(&csi2rx->subdev.entity);
 err_free_priv:
 	kfree(csi2rx);
 	return ret;
@@ -559,6 +560,7 @@ static void csi2rx_remove(struct platform_device *pdev)
 	v4l2_async_nf_unregister(&csi2rx->notifier);
 	v4l2_async_nf_cleanup(&csi2rx->notifier);
 	v4l2_async_unregister_subdev(&csi2rx->subdev);
+	media_entity_cleanup(&csi2rx->subdev.entity);
 	kfree(csi2rx);
 }
 

-- 
2.41.0

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v8 07/16] media: cadence: csi2rx: Add get_fmt and set_fmt pad ops
  2023-07-31  8:29 ` Jai Luthra
@ 2023-07-31  8:29   ` Jai Luthra
  -1 siblings, 0 replies; 84+ messages in thread
From: Jai Luthra @ 2023-07-31  8:29 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Sakari Ailus, Laurent Pinchart, Tomi Valkeinen
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht, j-luthra

From: Pratyush Yadav <p.yadav@ti.com>

The format is needed to calculate the link speed for the external DPHY
configuration. It is not right to query the format from the source
subdev. Add get_fmt and set_fmt pad operations so that the format can be
configured and correct bpp be selected.

Initialize and use the v4l2 subdev active state to keep track of the
active formats. Also propagate the new format from the sink pad to all
the source pads.

Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
Co-authored-by: Jai Luthra <j-luthra@ti.com>
Signed-off-by: Jai Luthra <j-luthra@ti.com>
---
v7->v8:
- Use active subdev state to use v4l2_subdev_get_fmt
- Propagate formats from sink to source pads
- Drop Laurent's R-by because of the above changes

 drivers/media/platform/cadence/cdns-csi2rx.c | 107 ++++++++++++++++++++++++++-
 1 file changed, 106 insertions(+), 1 deletion(-)

diff --git a/drivers/media/platform/cadence/cdns-csi2rx.c b/drivers/media/platform/cadence/cdns-csi2rx.c
index 83d1fadd592b..4f9654366485 100644
--- a/drivers/media/platform/cadence/cdns-csi2rx.c
+++ b/drivers/media/platform/cadence/cdns-csi2rx.c
@@ -61,6 +61,11 @@ enum csi2rx_pads {
 	CSI2RX_PAD_MAX,
 };
 
+struct csi2rx_fmt {
+	u32				code;
+	u8				bpp;
+};
+
 struct csi2rx_priv {
 	struct device			*dev;
 	unsigned int			count;
@@ -95,6 +100,36 @@ struct csi2rx_priv {
 	int				source_pad;
 };
 
+static const struct csi2rx_fmt formats[] = {
+	{
+		.code	= MEDIA_BUS_FMT_YUYV8_1X16,
+		.bpp	= 16,
+	},
+	{
+		.code	= MEDIA_BUS_FMT_UYVY8_1X16,
+		.bpp	= 16,
+	},
+	{
+		.code	= MEDIA_BUS_FMT_YVYU8_1X16,
+		.bpp	= 16,
+	},
+	{
+		.code	= MEDIA_BUS_FMT_VYUY8_1X16,
+		.bpp	= 16,
+	},
+};
+
+static const struct csi2rx_fmt *csi2rx_get_fmt_by_code(u32 code)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(formats); i++)
+		if (formats[i].code == code)
+			return &formats[i];
+
+	return NULL;
+}
+
 static inline
 struct csi2rx_priv *v4l2_subdev_to_csi2rx(struct v4l2_subdev *subdev)
 {
@@ -303,12 +338,75 @@ static int csi2rx_s_stream(struct v4l2_subdev *subdev, int enable)
 	return ret;
 }
 
+static int csi2rx_set_fmt(struct v4l2_subdev *subdev,
+			  struct v4l2_subdev_state *state,
+			  struct v4l2_subdev_format *format)
+{
+	struct v4l2_mbus_framefmt *fmt;
+	unsigned int i;
+
+	/* No transcoding, source and sink formats must match. */
+	if (format->pad != CSI2RX_PAD_SINK)
+		return v4l2_subdev_get_fmt(subdev, state, format);
+
+	if (!csi2rx_get_fmt_by_code(format->format.code))
+		format->format.code = formats[0].code;
+
+	format->format.field = V4L2_FIELD_NONE;
+
+	/* Set sink format */
+	fmt = v4l2_subdev_get_pad_format(subdev, state, format->pad);
+	if (!fmt)
+		return -EINVAL;
+
+	*fmt = format->format;
+
+	/* Propagate to source formats */
+	for (i = CSI2RX_PAD_SOURCE_STREAM0; i < CSI2RX_PAD_MAX; i++) {
+		fmt = v4l2_subdev_get_pad_format(subdev, state, i);
+		if (!fmt)
+			return -EINVAL;
+		*fmt = format->format;
+	}
+
+	return 0;
+}
+
+static int csi2rx_init_cfg(struct v4l2_subdev *subdev,
+			   struct v4l2_subdev_state *state)
+{
+	struct v4l2_subdev_format format = {
+		.which = state ? V4L2_SUBDEV_FORMAT_TRY
+			: V4L2_SUBDEV_FORMAT_ACTIVE,
+		.pad = CSI2RX_PAD_SINK,
+		.format = {
+			.width = 640,
+			.height = 480,
+			.code = MEDIA_BUS_FMT_UYVY8_1X16,
+			.field = V4L2_FIELD_NONE,
+			.colorspace = V4L2_COLORSPACE_SRGB,
+			.ycbcr_enc = V4L2_YCBCR_ENC_601,
+			.quantization = V4L2_QUANTIZATION_LIM_RANGE,
+			.xfer_func = V4L2_XFER_FUNC_SRGB,
+		},
+	};
+
+	return csi2rx_set_fmt(subdev, state, &format);
+}
+
+static const struct v4l2_subdev_pad_ops csi2rx_pad_ops = {
+	.get_fmt	= v4l2_subdev_get_fmt,
+	.set_fmt	= csi2rx_set_fmt,
+	.init_cfg	= csi2rx_init_cfg,
+};
+
 static const struct v4l2_subdev_video_ops csi2rx_video_ops = {
 	.s_stream	= csi2rx_s_stream,
 };
 
 static const struct v4l2_subdev_ops csi2rx_subdev_ops = {
 	.video		= &csi2rx_video_ops,
+	.pad		= &csi2rx_pad_ops,
 };
 
 static int csi2rx_async_bound(struct v4l2_async_notifier *notifier,
@@ -532,9 +630,13 @@ static int csi2rx_probe(struct platform_device *pdev)
 	if (ret)
 		goto err_cleanup;
 
+	ret = v4l2_subdev_init_finalize(&csi2rx->subdev);
+	if (ret)
+		goto err_cleanup;
+
 	ret = v4l2_async_register_subdev(&csi2rx->subdev);
 	if (ret < 0)
-		goto err_cleanup;
+		goto err_free_state;
 
 	dev_info(&pdev->dev,
 		 "Probed CSI2RX with %u/%u lanes, %u streams, %s D-PHY\n",
@@ -544,6 +646,8 @@ static int csi2rx_probe(struct platform_device *pdev)
 
 	return 0;
 
+err_free_state:
+	v4l2_subdev_cleanup(&csi2rx->subdev);
 err_cleanup:
 	v4l2_async_nf_unregister(&csi2rx->notifier);
 	v4l2_async_nf_cleanup(&csi2rx->notifier);
@@ -560,6 +664,7 @@ static void csi2rx_remove(struct platform_device *pdev)
 	v4l2_async_nf_unregister(&csi2rx->notifier);
 	v4l2_async_nf_cleanup(&csi2rx->notifier);
 	v4l2_async_unregister_subdev(&csi2rx->subdev);
+	v4l2_subdev_cleanup(&csi2rx->subdev);
 	media_entity_cleanup(&csi2rx->subdev.entity);
 	kfree(csi2rx);
 }

-- 
2.41.0

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

* [PATCH v8 07/16] media: cadence: csi2rx: Add get_fmt and set_fmt pad ops
@ 2023-07-31  8:29   ` Jai Luthra
  0 siblings, 0 replies; 84+ messages in thread
From: Jai Luthra @ 2023-07-31  8:29 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Sakari Ailus, Laurent Pinchart, Tomi Valkeinen
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht, j-luthra

From: Pratyush Yadav <p.yadav@ti.com>

The format is needed to calculate the link speed for the external DPHY
configuration. It is not right to query the format from the source
subdev. Add get_fmt and set_fmt pad operations so that the format can be
configured and correct bpp be selected.

Initialize and use the v4l2 subdev active state to keep track of the
active formats. Also propagate the new format from the sink pad to all
the source pads.

Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
Co-authored-by: Jai Luthra <j-luthra@ti.com>
Signed-off-by: Jai Luthra <j-luthra@ti.com>
---
v7->v8:
- Use active subdev state to use v4l2_subdev_get_fmt
- Propagate formats from sink to source pads
- Drop Laurent's R-by because of the above changes

 drivers/media/platform/cadence/cdns-csi2rx.c | 107 ++++++++++++++++++++++++++-
 1 file changed, 106 insertions(+), 1 deletion(-)

diff --git a/drivers/media/platform/cadence/cdns-csi2rx.c b/drivers/media/platform/cadence/cdns-csi2rx.c
index 83d1fadd592b..4f9654366485 100644
--- a/drivers/media/platform/cadence/cdns-csi2rx.c
+++ b/drivers/media/platform/cadence/cdns-csi2rx.c
@@ -61,6 +61,11 @@ enum csi2rx_pads {
 	CSI2RX_PAD_MAX,
 };
 
+struct csi2rx_fmt {
+	u32				code;
+	u8				bpp;
+};
+
 struct csi2rx_priv {
 	struct device			*dev;
 	unsigned int			count;
@@ -95,6 +100,36 @@ struct csi2rx_priv {
 	int				source_pad;
 };
 
+static const struct csi2rx_fmt formats[] = {
+	{
+		.code	= MEDIA_BUS_FMT_YUYV8_1X16,
+		.bpp	= 16,
+	},
+	{
+		.code	= MEDIA_BUS_FMT_UYVY8_1X16,
+		.bpp	= 16,
+	},
+	{
+		.code	= MEDIA_BUS_FMT_YVYU8_1X16,
+		.bpp	= 16,
+	},
+	{
+		.code	= MEDIA_BUS_FMT_VYUY8_1X16,
+		.bpp	= 16,
+	},
+};
+
+static const struct csi2rx_fmt *csi2rx_get_fmt_by_code(u32 code)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(formats); i++)
+		if (formats[i].code == code)
+			return &formats[i];
+
+	return NULL;
+}
+
 static inline
 struct csi2rx_priv *v4l2_subdev_to_csi2rx(struct v4l2_subdev *subdev)
 {
@@ -303,12 +338,75 @@ static int csi2rx_s_stream(struct v4l2_subdev *subdev, int enable)
 	return ret;
 }
 
+static int csi2rx_set_fmt(struct v4l2_subdev *subdev,
+			  struct v4l2_subdev_state *state,
+			  struct v4l2_subdev_format *format)
+{
+	struct v4l2_mbus_framefmt *fmt;
+	unsigned int i;
+
+	/* No transcoding, source and sink formats must match. */
+	if (format->pad != CSI2RX_PAD_SINK)
+		return v4l2_subdev_get_fmt(subdev, state, format);
+
+	if (!csi2rx_get_fmt_by_code(format->format.code))
+		format->format.code = formats[0].code;
+
+	format->format.field = V4L2_FIELD_NONE;
+
+	/* Set sink format */
+	fmt = v4l2_subdev_get_pad_format(subdev, state, format->pad);
+	if (!fmt)
+		return -EINVAL;
+
+	*fmt = format->format;
+
+	/* Propagate to source formats */
+	for (i = CSI2RX_PAD_SOURCE_STREAM0; i < CSI2RX_PAD_MAX; i++) {
+		fmt = v4l2_subdev_get_pad_format(subdev, state, i);
+		if (!fmt)
+			return -EINVAL;
+		*fmt = format->format;
+	}
+
+	return 0;
+}
+
+static int csi2rx_init_cfg(struct v4l2_subdev *subdev,
+			   struct v4l2_subdev_state *state)
+{
+	struct v4l2_subdev_format format = {
+		.which = state ? V4L2_SUBDEV_FORMAT_TRY
+			: V4L2_SUBDEV_FORMAT_ACTIVE,
+		.pad = CSI2RX_PAD_SINK,
+		.format = {
+			.width = 640,
+			.height = 480,
+			.code = MEDIA_BUS_FMT_UYVY8_1X16,
+			.field = V4L2_FIELD_NONE,
+			.colorspace = V4L2_COLORSPACE_SRGB,
+			.ycbcr_enc = V4L2_YCBCR_ENC_601,
+			.quantization = V4L2_QUANTIZATION_LIM_RANGE,
+			.xfer_func = V4L2_XFER_FUNC_SRGB,
+		},
+	};
+
+	return csi2rx_set_fmt(subdev, state, &format);
+}
+
+static const struct v4l2_subdev_pad_ops csi2rx_pad_ops = {
+	.get_fmt	= v4l2_subdev_get_fmt,
+	.set_fmt	= csi2rx_set_fmt,
+	.init_cfg	= csi2rx_init_cfg,
+};
+
 static const struct v4l2_subdev_video_ops csi2rx_video_ops = {
 	.s_stream	= csi2rx_s_stream,
 };
 
 static const struct v4l2_subdev_ops csi2rx_subdev_ops = {
 	.video		= &csi2rx_video_ops,
+	.pad		= &csi2rx_pad_ops,
 };
 
 static int csi2rx_async_bound(struct v4l2_async_notifier *notifier,
@@ -532,9 +630,13 @@ static int csi2rx_probe(struct platform_device *pdev)
 	if (ret)
 		goto err_cleanup;
 
+	ret = v4l2_subdev_init_finalize(&csi2rx->subdev);
+	if (ret)
+		goto err_cleanup;
+
 	ret = v4l2_async_register_subdev(&csi2rx->subdev);
 	if (ret < 0)
-		goto err_cleanup;
+		goto err_free_state;
 
 	dev_info(&pdev->dev,
 		 "Probed CSI2RX with %u/%u lanes, %u streams, %s D-PHY\n",
@@ -544,6 +646,8 @@ static int csi2rx_probe(struct platform_device *pdev)
 
 	return 0;
 
+err_free_state:
+	v4l2_subdev_cleanup(&csi2rx->subdev);
 err_cleanup:
 	v4l2_async_nf_unregister(&csi2rx->notifier);
 	v4l2_async_nf_cleanup(&csi2rx->notifier);
@@ -560,6 +664,7 @@ static void csi2rx_remove(struct platform_device *pdev)
 	v4l2_async_nf_unregister(&csi2rx->notifier);
 	v4l2_async_nf_cleanup(&csi2rx->notifier);
 	v4l2_async_unregister_subdev(&csi2rx->subdev);
+	v4l2_subdev_cleanup(&csi2rx->subdev);
 	media_entity_cleanup(&csi2rx->subdev.entity);
 	kfree(csi2rx);
 }

-- 
2.41.0

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v8 08/16] media: cadence: csi2rx: Configure DPHY using link freq
  2023-07-31  8:29 ` Jai Luthra
@ 2023-07-31  8:29   ` Jai Luthra
  -1 siblings, 0 replies; 84+ messages in thread
From: Jai Luthra @ 2023-07-31  8:29 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Sakari Ailus, Laurent Pinchart, Tomi Valkeinen
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht, j-luthra

From: Pratyush Yadav <p.yadav@ti.com>

Some platforms like TI's J721E can have the CSI2RX paired with an
external DPHY. Use the generic PHY framework to configure the DPHY with
the correct link frequency.

Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
Co-authored-by: Jai Luthra <j-luthra@ti.com>
Signed-off-by: Jai Luthra <j-luthra@ti.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
v7->v8
- Drop original patch in-lieu of already merged
  https://lore.kernel.org/linux-media/20230523085626.3295-5-jack.zhu@starfivetech.com/
- Add a new patch to configure DPHY using link_freq control from the
  source

 drivers/media/platform/cadence/cdns-csi2rx.c | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/drivers/media/platform/cadence/cdns-csi2rx.c b/drivers/media/platform/cadence/cdns-csi2rx.c
index 4f9654366485..2a80c66fb547 100644
--- a/drivers/media/platform/cadence/cdns-csi2rx.c
+++ b/drivers/media/platform/cadence/cdns-csi2rx.c
@@ -149,8 +149,33 @@ static void csi2rx_reset(struct csi2rx_priv *csi2rx)
 static int csi2rx_configure_ext_dphy(struct csi2rx_priv *csi2rx)
 {
 	union phy_configure_opts opts = { };
+	struct phy_configure_opts_mipi_dphy *cfg = &opts.mipi_dphy;
+	struct v4l2_subdev_format sd_fmt = {
+		.which	= V4L2_SUBDEV_FORMAT_ACTIVE,
+		.pad	= CSI2RX_PAD_SINK,
+		.stream	= 0,
+	};
+	const struct csi2rx_fmt *fmt;
+	s64 link_freq;
 	int ret;
 
+	ret = v4l2_subdev_call_state_active(&csi2rx->subdev, pad, get_fmt,
+					    &sd_fmt);
+	if (ret < 0)
+		return ret;
+
+	fmt = csi2rx_get_fmt_by_code(sd_fmt.format.code);
+
+	link_freq = v4l2_get_link_freq(csi2rx->source_subdev->ctrl_handler,
+				       fmt->bpp, 2 * csi2rx->num_lanes);
+	if (link_freq < 0)
+		return link_freq;
+
+	ret = phy_mipi_dphy_get_default_config_for_hsclk(link_freq,
+							 csi2rx->num_lanes, cfg);
+	if (ret)
+		return ret;
+
 	ret = phy_power_on(csi2rx->dphy);
 	if (ret)
 		return ret;

-- 
2.41.0

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

* [PATCH v8 08/16] media: cadence: csi2rx: Configure DPHY using link freq
@ 2023-07-31  8:29   ` Jai Luthra
  0 siblings, 0 replies; 84+ messages in thread
From: Jai Luthra @ 2023-07-31  8:29 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Sakari Ailus, Laurent Pinchart, Tomi Valkeinen
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht, j-luthra

From: Pratyush Yadav <p.yadav@ti.com>

Some platforms like TI's J721E can have the CSI2RX paired with an
external DPHY. Use the generic PHY framework to configure the DPHY with
the correct link frequency.

Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
Co-authored-by: Jai Luthra <j-luthra@ti.com>
Signed-off-by: Jai Luthra <j-luthra@ti.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
v7->v8
- Drop original patch in-lieu of already merged
  https://lore.kernel.org/linux-media/20230523085626.3295-5-jack.zhu@starfivetech.com/
- Add a new patch to configure DPHY using link_freq control from the
  source

 drivers/media/platform/cadence/cdns-csi2rx.c | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/drivers/media/platform/cadence/cdns-csi2rx.c b/drivers/media/platform/cadence/cdns-csi2rx.c
index 4f9654366485..2a80c66fb547 100644
--- a/drivers/media/platform/cadence/cdns-csi2rx.c
+++ b/drivers/media/platform/cadence/cdns-csi2rx.c
@@ -149,8 +149,33 @@ static void csi2rx_reset(struct csi2rx_priv *csi2rx)
 static int csi2rx_configure_ext_dphy(struct csi2rx_priv *csi2rx)
 {
 	union phy_configure_opts opts = { };
+	struct phy_configure_opts_mipi_dphy *cfg = &opts.mipi_dphy;
+	struct v4l2_subdev_format sd_fmt = {
+		.which	= V4L2_SUBDEV_FORMAT_ACTIVE,
+		.pad	= CSI2RX_PAD_SINK,
+		.stream	= 0,
+	};
+	const struct csi2rx_fmt *fmt;
+	s64 link_freq;
 	int ret;
 
+	ret = v4l2_subdev_call_state_active(&csi2rx->subdev, pad, get_fmt,
+					    &sd_fmt);
+	if (ret < 0)
+		return ret;
+
+	fmt = csi2rx_get_fmt_by_code(sd_fmt.format.code);
+
+	link_freq = v4l2_get_link_freq(csi2rx->source_subdev->ctrl_handler,
+				       fmt->bpp, 2 * csi2rx->num_lanes);
+	if (link_freq < 0)
+		return link_freq;
+
+	ret = phy_mipi_dphy_get_default_config_for_hsclk(link_freq,
+							 csi2rx->num_lanes, cfg);
+	if (ret)
+		return ret;
+
 	ret = phy_power_on(csi2rx->dphy);
 	if (ret)
 		return ret;

-- 
2.41.0

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v8 09/16] media: cadence: csi2rx: Soft reset the streams before starting capture
  2023-07-31  8:29 ` Jai Luthra
@ 2023-07-31  8:29   ` Jai Luthra
  -1 siblings, 0 replies; 84+ messages in thread
From: Jai Luthra @ 2023-07-31  8:29 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Sakari Ailus, Laurent Pinchart, Tomi Valkeinen
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht, j-luthra

From: Pratyush Yadav <p.yadav@ti.com>

This resets the stream state machines and FIFOs, giving them a clean
slate. On J721E if the streams are not reset before starting the
capture, the captured frame gets wrapped around vertically on every run
after the first.

Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
Signed-off-by: Jai Luthra <j-luthra@ti.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
v7->v8: No change

 drivers/media/platform/cadence/cdns-csi2rx.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/drivers/media/platform/cadence/cdns-csi2rx.c b/drivers/media/platform/cadence/cdns-csi2rx.c
index 2a80c66fb547..30cdc260b46a 100644
--- a/drivers/media/platform/cadence/cdns-csi2rx.c
+++ b/drivers/media/platform/cadence/cdns-csi2rx.c
@@ -40,6 +40,7 @@
 #define CSI2RX_STREAM_BASE(n)		(((n) + 1) * 0x100)
 
 #define CSI2RX_STREAM_CTRL_REG(n)		(CSI2RX_STREAM_BASE(n) + 0x000)
+#define CSI2RX_STREAM_CTRL_SOFT_RST			BIT(4)
 #define CSI2RX_STREAM_CTRL_START			BIT(0)
 
 #define CSI2RX_STREAM_DATA_CFG_REG(n)		(CSI2RX_STREAM_BASE(n) + 0x008)
@@ -138,12 +139,22 @@ struct csi2rx_priv *v4l2_subdev_to_csi2rx(struct v4l2_subdev *subdev)
 
 static void csi2rx_reset(struct csi2rx_priv *csi2rx)
 {
+	unsigned int i;
+
 	writel(CSI2RX_SOFT_RESET_PROTOCOL | CSI2RX_SOFT_RESET_FRONT,
 	       csi2rx->base + CSI2RX_SOFT_RESET_REG);
 
 	udelay(10);
 
 	writel(0, csi2rx->base + CSI2RX_SOFT_RESET_REG);
+
+	/* Reset individual streams. */
+	for (i = 0; i < csi2rx->max_streams; i++) {
+		writel(CSI2RX_STREAM_CTRL_SOFT_RST,
+		       csi2rx->base + CSI2RX_STREAM_CTRL_REG(i));
+		usleep_range(10, 20);
+		writel(0, csi2rx->base + CSI2RX_STREAM_CTRL_REG(i));
+	}
 }
 
 static int csi2rx_configure_ext_dphy(struct csi2rx_priv *csi2rx)

-- 
2.41.0

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

* [PATCH v8 09/16] media: cadence: csi2rx: Soft reset the streams before starting capture
@ 2023-07-31  8:29   ` Jai Luthra
  0 siblings, 0 replies; 84+ messages in thread
From: Jai Luthra @ 2023-07-31  8:29 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Sakari Ailus, Laurent Pinchart, Tomi Valkeinen
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht, j-luthra

From: Pratyush Yadav <p.yadav@ti.com>

This resets the stream state machines and FIFOs, giving them a clean
slate. On J721E if the streams are not reset before starting the
capture, the captured frame gets wrapped around vertically on every run
after the first.

Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
Signed-off-by: Jai Luthra <j-luthra@ti.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
v7->v8: No change

 drivers/media/platform/cadence/cdns-csi2rx.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/drivers/media/platform/cadence/cdns-csi2rx.c b/drivers/media/platform/cadence/cdns-csi2rx.c
index 2a80c66fb547..30cdc260b46a 100644
--- a/drivers/media/platform/cadence/cdns-csi2rx.c
+++ b/drivers/media/platform/cadence/cdns-csi2rx.c
@@ -40,6 +40,7 @@
 #define CSI2RX_STREAM_BASE(n)		(((n) + 1) * 0x100)
 
 #define CSI2RX_STREAM_CTRL_REG(n)		(CSI2RX_STREAM_BASE(n) + 0x000)
+#define CSI2RX_STREAM_CTRL_SOFT_RST			BIT(4)
 #define CSI2RX_STREAM_CTRL_START			BIT(0)
 
 #define CSI2RX_STREAM_DATA_CFG_REG(n)		(CSI2RX_STREAM_BASE(n) + 0x008)
@@ -138,12 +139,22 @@ struct csi2rx_priv *v4l2_subdev_to_csi2rx(struct v4l2_subdev *subdev)
 
 static void csi2rx_reset(struct csi2rx_priv *csi2rx)
 {
+	unsigned int i;
+
 	writel(CSI2RX_SOFT_RESET_PROTOCOL | CSI2RX_SOFT_RESET_FRONT,
 	       csi2rx->base + CSI2RX_SOFT_RESET_REG);
 
 	udelay(10);
 
 	writel(0, csi2rx->base + CSI2RX_SOFT_RESET_REG);
+
+	/* Reset individual streams. */
+	for (i = 0; i < csi2rx->max_streams; i++) {
+		writel(CSI2RX_STREAM_CTRL_SOFT_RST,
+		       csi2rx->base + CSI2RX_STREAM_CTRL_REG(i));
+		usleep_range(10, 20);
+		writel(0, csi2rx->base + CSI2RX_STREAM_CTRL_REG(i));
+	}
 }
 
 static int csi2rx_configure_ext_dphy(struct csi2rx_priv *csi2rx)

-- 
2.41.0

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v8 10/16] media: cadence: csi2rx: Set the STOP bit when stopping a stream
  2023-07-31  8:29 ` Jai Luthra
@ 2023-07-31  8:29   ` Jai Luthra
  -1 siblings, 0 replies; 84+ messages in thread
From: Jai Luthra @ 2023-07-31  8:29 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Sakari Ailus, Laurent Pinchart, Tomi Valkeinen
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht, j-luthra

From: Pratyush Yadav <p.yadav@ti.com>

The stream stop procedure says that the STOP bit should be set when the
stream is to be stopped, and then the ready bit in stream status
register polled to make sure the STOP operation is finished.

Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
Signed-off-by: Jai Luthra <j-luthra@ti.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
v7->v8:
- Fix bug where intention was to wait till stream status is idle, i.e.
  STREAM_STATUS[31] -> 0 - but we were instead checking the opposite

 drivers/media/platform/cadence/cdns-csi2rx.c | 18 +++++++++++++++++-
 1 file changed, 17 insertions(+), 1 deletion(-)

diff --git a/drivers/media/platform/cadence/cdns-csi2rx.c b/drivers/media/platform/cadence/cdns-csi2rx.c
index 30cdc260b46a..a17ef88dff82 100644
--- a/drivers/media/platform/cadence/cdns-csi2rx.c
+++ b/drivers/media/platform/cadence/cdns-csi2rx.c
@@ -8,6 +8,7 @@
 #include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/io.h>
+#include <linux/iopoll.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_graph.h>
@@ -41,8 +42,12 @@
 
 #define CSI2RX_STREAM_CTRL_REG(n)		(CSI2RX_STREAM_BASE(n) + 0x000)
 #define CSI2RX_STREAM_CTRL_SOFT_RST			BIT(4)
+#define CSI2RX_STREAM_CTRL_STOP				BIT(1)
 #define CSI2RX_STREAM_CTRL_START			BIT(0)
 
+#define CSI2RX_STREAM_STATUS_REG(n)		(CSI2RX_STREAM_BASE(n) + 0x004)
+#define CSI2RX_STREAM_STATUS_RDY			BIT(31)
+
 #define CSI2RX_STREAM_DATA_CFG_REG(n)		(CSI2RX_STREAM_BASE(n) + 0x008)
 #define CSI2RX_STREAM_DATA_CFG_EN_VC_SELECT		BIT(31)
 #define CSI2RX_STREAM_DATA_CFG_VC_SELECT(n)		BIT((n) + 16)
@@ -314,13 +319,24 @@ static int csi2rx_start(struct csi2rx_priv *csi2rx)
 static void csi2rx_stop(struct csi2rx_priv *csi2rx)
 {
 	unsigned int i;
+	u32 val;
+	int ret;
 
 	clk_prepare_enable(csi2rx->p_clk);
 	reset_control_assert(csi2rx->sys_rst);
 	clk_disable_unprepare(csi2rx->sys_clk);
 
 	for (i = 0; i < csi2rx->max_streams; i++) {
-		writel(0, csi2rx->base + CSI2RX_STREAM_CTRL_REG(i));
+		writel(CSI2RX_STREAM_CTRL_STOP,
+		       csi2rx->base + CSI2RX_STREAM_CTRL_REG(i));
+
+		ret = readl_relaxed_poll_timeout(csi2rx->base +
+						 CSI2RX_STREAM_STATUS_REG(i),
+						 val,
+						 !(val & CSI2RX_STREAM_STATUS_RDY),
+						 10, 10000);
+		if (ret)
+			dev_warn(csi2rx->dev, "Failed to stop stream%u\n", i);
 
 		reset_control_assert(csi2rx->pixel_rst[i]);
 		clk_disable_unprepare(csi2rx->pixel_clk[i]);

-- 
2.41.0

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

* [PATCH v8 10/16] media: cadence: csi2rx: Set the STOP bit when stopping a stream
@ 2023-07-31  8:29   ` Jai Luthra
  0 siblings, 0 replies; 84+ messages in thread
From: Jai Luthra @ 2023-07-31  8:29 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Sakari Ailus, Laurent Pinchart, Tomi Valkeinen
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht, j-luthra

From: Pratyush Yadav <p.yadav@ti.com>

The stream stop procedure says that the STOP bit should be set when the
stream is to be stopped, and then the ready bit in stream status
register polled to make sure the STOP operation is finished.

Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
Signed-off-by: Jai Luthra <j-luthra@ti.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
v7->v8:
- Fix bug where intention was to wait till stream status is idle, i.e.
  STREAM_STATUS[31] -> 0 - but we were instead checking the opposite

 drivers/media/platform/cadence/cdns-csi2rx.c | 18 +++++++++++++++++-
 1 file changed, 17 insertions(+), 1 deletion(-)

diff --git a/drivers/media/platform/cadence/cdns-csi2rx.c b/drivers/media/platform/cadence/cdns-csi2rx.c
index 30cdc260b46a..a17ef88dff82 100644
--- a/drivers/media/platform/cadence/cdns-csi2rx.c
+++ b/drivers/media/platform/cadence/cdns-csi2rx.c
@@ -8,6 +8,7 @@
 #include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/io.h>
+#include <linux/iopoll.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_graph.h>
@@ -41,8 +42,12 @@
 
 #define CSI2RX_STREAM_CTRL_REG(n)		(CSI2RX_STREAM_BASE(n) + 0x000)
 #define CSI2RX_STREAM_CTRL_SOFT_RST			BIT(4)
+#define CSI2RX_STREAM_CTRL_STOP				BIT(1)
 #define CSI2RX_STREAM_CTRL_START			BIT(0)
 
+#define CSI2RX_STREAM_STATUS_REG(n)		(CSI2RX_STREAM_BASE(n) + 0x004)
+#define CSI2RX_STREAM_STATUS_RDY			BIT(31)
+
 #define CSI2RX_STREAM_DATA_CFG_REG(n)		(CSI2RX_STREAM_BASE(n) + 0x008)
 #define CSI2RX_STREAM_DATA_CFG_EN_VC_SELECT		BIT(31)
 #define CSI2RX_STREAM_DATA_CFG_VC_SELECT(n)		BIT((n) + 16)
@@ -314,13 +319,24 @@ static int csi2rx_start(struct csi2rx_priv *csi2rx)
 static void csi2rx_stop(struct csi2rx_priv *csi2rx)
 {
 	unsigned int i;
+	u32 val;
+	int ret;
 
 	clk_prepare_enable(csi2rx->p_clk);
 	reset_control_assert(csi2rx->sys_rst);
 	clk_disable_unprepare(csi2rx->sys_clk);
 
 	for (i = 0; i < csi2rx->max_streams; i++) {
-		writel(0, csi2rx->base + CSI2RX_STREAM_CTRL_REG(i));
+		writel(CSI2RX_STREAM_CTRL_STOP,
+		       csi2rx->base + CSI2RX_STREAM_CTRL_REG(i));
+
+		ret = readl_relaxed_poll_timeout(csi2rx->base +
+						 CSI2RX_STREAM_STATUS_REG(i),
+						 val,
+						 !(val & CSI2RX_STREAM_STATUS_RDY),
+						 10, 10000);
+		if (ret)
+			dev_warn(csi2rx->dev, "Failed to stop stream%u\n", i);
 
 		reset_control_assert(csi2rx->pixel_rst[i]);
 		clk_disable_unprepare(csi2rx->pixel_clk[i]);

-- 
2.41.0

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v8 11/16] media: cadence: csi2rx: Fix stream data configuration
  2023-07-31  8:29 ` Jai Luthra
@ 2023-07-31  8:29   ` Jai Luthra
  -1 siblings, 0 replies; 84+ messages in thread
From: Jai Luthra @ 2023-07-31  8:29 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Sakari Ailus, Laurent Pinchart, Tomi Valkeinen
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht, j-luthra

From: Pratyush Yadav <p.yadav@ti.com>

Firstly, there is no VC_EN bit present in the STREAM_DATA_CFG register.
Bit 31 is part of the VL_SELECT field. Remove it completely.

Secondly, it makes little sense to enable ith virtual channel for ith
stream. Sure, there might be a use-case that demands it. But there might
also be a use case that demands all streams to use the 0th virtual
channel. Prefer this case over the former because it is less arbitrary
and also makes it very clear what the limitations of the current driver
is instead of giving a false impression that multiple virtual channels
are supported.

Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
Signed-off-by: Jai Luthra <j-luthra@ti.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
v7->v8: No change

 drivers/media/platform/cadence/cdns-csi2rx.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/media/platform/cadence/cdns-csi2rx.c b/drivers/media/platform/cadence/cdns-csi2rx.c
index a17ef88dff82..cde7fd6463e1 100644
--- a/drivers/media/platform/cadence/cdns-csi2rx.c
+++ b/drivers/media/platform/cadence/cdns-csi2rx.c
@@ -49,7 +49,6 @@
 #define CSI2RX_STREAM_STATUS_RDY			BIT(31)
 
 #define CSI2RX_STREAM_DATA_CFG_REG(n)		(CSI2RX_STREAM_BASE(n) + 0x008)
-#define CSI2RX_STREAM_DATA_CFG_EN_VC_SELECT		BIT(31)
 #define CSI2RX_STREAM_DATA_CFG_VC_SELECT(n)		BIT((n) + 16)
 
 #define CSI2RX_STREAM_CFG_REG(n)		(CSI2RX_STREAM_BASE(n) + 0x00c)
@@ -275,8 +274,11 @@ static int csi2rx_start(struct csi2rx_priv *csi2rx)
 		writel(CSI2RX_STREAM_CFG_FIFO_MODE_LARGE_BUF,
 		       csi2rx->base + CSI2RX_STREAM_CFG_REG(i));
 
-		writel(CSI2RX_STREAM_DATA_CFG_EN_VC_SELECT |
-		       CSI2RX_STREAM_DATA_CFG_VC_SELECT(i),
+		/*
+		 * Enable one virtual channel. When multiple virtual channels
+		 * are supported this will have to be changed.
+		 */
+		writel(CSI2RX_STREAM_DATA_CFG_VC_SELECT(0),
 		       csi2rx->base + CSI2RX_STREAM_DATA_CFG_REG(i));
 
 		writel(CSI2RX_STREAM_CTRL_START,

-- 
2.41.0

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

* [PATCH v8 11/16] media: cadence: csi2rx: Fix stream data configuration
@ 2023-07-31  8:29   ` Jai Luthra
  0 siblings, 0 replies; 84+ messages in thread
From: Jai Luthra @ 2023-07-31  8:29 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Sakari Ailus, Laurent Pinchart, Tomi Valkeinen
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht, j-luthra

From: Pratyush Yadav <p.yadav@ti.com>

Firstly, there is no VC_EN bit present in the STREAM_DATA_CFG register.
Bit 31 is part of the VL_SELECT field. Remove it completely.

Secondly, it makes little sense to enable ith virtual channel for ith
stream. Sure, there might be a use-case that demands it. But there might
also be a use case that demands all streams to use the 0th virtual
channel. Prefer this case over the former because it is less arbitrary
and also makes it very clear what the limitations of the current driver
is instead of giving a false impression that multiple virtual channels
are supported.

Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
Signed-off-by: Jai Luthra <j-luthra@ti.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
v7->v8: No change

 drivers/media/platform/cadence/cdns-csi2rx.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/media/platform/cadence/cdns-csi2rx.c b/drivers/media/platform/cadence/cdns-csi2rx.c
index a17ef88dff82..cde7fd6463e1 100644
--- a/drivers/media/platform/cadence/cdns-csi2rx.c
+++ b/drivers/media/platform/cadence/cdns-csi2rx.c
@@ -49,7 +49,6 @@
 #define CSI2RX_STREAM_STATUS_RDY			BIT(31)
 
 #define CSI2RX_STREAM_DATA_CFG_REG(n)		(CSI2RX_STREAM_BASE(n) + 0x008)
-#define CSI2RX_STREAM_DATA_CFG_EN_VC_SELECT		BIT(31)
 #define CSI2RX_STREAM_DATA_CFG_VC_SELECT(n)		BIT((n) + 16)
 
 #define CSI2RX_STREAM_CFG_REG(n)		(CSI2RX_STREAM_BASE(n) + 0x00c)
@@ -275,8 +274,11 @@ static int csi2rx_start(struct csi2rx_priv *csi2rx)
 		writel(CSI2RX_STREAM_CFG_FIFO_MODE_LARGE_BUF,
 		       csi2rx->base + CSI2RX_STREAM_CFG_REG(i));
 
-		writel(CSI2RX_STREAM_DATA_CFG_EN_VC_SELECT |
-		       CSI2RX_STREAM_DATA_CFG_VC_SELECT(i),
+		/*
+		 * Enable one virtual channel. When multiple virtual channels
+		 * are supported this will have to be changed.
+		 */
+		writel(CSI2RX_STREAM_DATA_CFG_VC_SELECT(0),
 		       csi2rx->base + CSI2RX_STREAM_DATA_CFG_REG(i));
 
 		writel(CSI2RX_STREAM_CTRL_START,

-- 
2.41.0

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v8 12/16] media: cadence: csi2rx: Populate subdev devnode
  2023-07-31  8:29 ` Jai Luthra
@ 2023-07-31  8:29   ` Jai Luthra
  -1 siblings, 0 replies; 84+ messages in thread
From: Jai Luthra @ 2023-07-31  8:29 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Sakari Ailus, Laurent Pinchart, Tomi Valkeinen
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht, j-luthra

From: Pratyush Yadav <p.yadav@ti.com>

The devnode can be used by media-ctl and other userspace tools to
perform configurations on the subdev. Without it, media-ctl returns
ENOENT when setting format on the sensor subdev.

Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
Signed-off-by: Jai Luthra <j-luthra@ti.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
v7->v8: No change

 drivers/media/platform/cadence/cdns-csi2rx.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/media/platform/cadence/cdns-csi2rx.c b/drivers/media/platform/cadence/cdns-csi2rx.c
index cde7fd6463e1..d82a8938932f 100644
--- a/drivers/media/platform/cadence/cdns-csi2rx.c
+++ b/drivers/media/platform/cadence/cdns-csi2rx.c
@@ -678,6 +678,7 @@ static int csi2rx_probe(struct platform_device *pdev)
 	csi2rx->pads[CSI2RX_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
 	for (i = CSI2RX_PAD_SOURCE_STREAM0; i < CSI2RX_PAD_MAX; i++)
 		csi2rx->pads[i].flags = MEDIA_PAD_FL_SOURCE;
+	csi2rx->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
 
 	ret = media_entity_pads_init(&csi2rx->subdev.entity, CSI2RX_PAD_MAX,
 				     csi2rx->pads);

-- 
2.41.0

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

* [PATCH v8 12/16] media: cadence: csi2rx: Populate subdev devnode
@ 2023-07-31  8:29   ` Jai Luthra
  0 siblings, 0 replies; 84+ messages in thread
From: Jai Luthra @ 2023-07-31  8:29 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Sakari Ailus, Laurent Pinchart, Tomi Valkeinen
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht, j-luthra

From: Pratyush Yadav <p.yadav@ti.com>

The devnode can be used by media-ctl and other userspace tools to
perform configurations on the subdev. Without it, media-ctl returns
ENOENT when setting format on the sensor subdev.

Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
Signed-off-by: Jai Luthra <j-luthra@ti.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
v7->v8: No change

 drivers/media/platform/cadence/cdns-csi2rx.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/media/platform/cadence/cdns-csi2rx.c b/drivers/media/platform/cadence/cdns-csi2rx.c
index cde7fd6463e1..d82a8938932f 100644
--- a/drivers/media/platform/cadence/cdns-csi2rx.c
+++ b/drivers/media/platform/cadence/cdns-csi2rx.c
@@ -678,6 +678,7 @@ static int csi2rx_probe(struct platform_device *pdev)
 	csi2rx->pads[CSI2RX_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
 	for (i = CSI2RX_PAD_SOURCE_STREAM0; i < CSI2RX_PAD_MAX; i++)
 		csi2rx->pads[i].flags = MEDIA_PAD_FL_SOURCE;
+	csi2rx->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
 
 	ret = media_entity_pads_init(&csi2rx->subdev.entity, CSI2RX_PAD_MAX,
 				     csi2rx->pads);

-- 
2.41.0

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v8 13/16] media: cadence: csi2rx: Add link validation
  2023-07-31  8:29 ` Jai Luthra
@ 2023-07-31  8:29   ` Jai Luthra
  -1 siblings, 0 replies; 84+ messages in thread
From: Jai Luthra @ 2023-07-31  8:29 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Sakari Ailus, Laurent Pinchart, Tomi Valkeinen
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht, j-luthra

From: Pratyush Yadav <p.yadav@ti.com>

Add media link validation to make sure incorrectly configured pipelines
are caught.

Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
Signed-off-by: Jai Luthra <j-luthra@ti.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
v7->v8: No change

 drivers/media/platform/cadence/cdns-csi2rx.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/media/platform/cadence/cdns-csi2rx.c b/drivers/media/platform/cadence/cdns-csi2rx.c
index d82a8938932f..aec33d28a66f 100644
--- a/drivers/media/platform/cadence/cdns-csi2rx.c
+++ b/drivers/media/platform/cadence/cdns-csi2rx.c
@@ -463,6 +463,10 @@ static const struct v4l2_subdev_ops csi2rx_subdev_ops = {
 	.pad		= &csi2rx_pad_ops,
 };
 
+static const struct media_entity_operations csi2rx_media_ops = {
+	.link_validate = v4l2_subdev_link_validate,
+};
+
 static int csi2rx_async_bound(struct v4l2_async_notifier *notifier,
 			      struct v4l2_subdev *s_subdev,
 			      struct v4l2_async_connection *asd)
@@ -679,6 +683,7 @@ static int csi2rx_probe(struct platform_device *pdev)
 	for (i = CSI2RX_PAD_SOURCE_STREAM0; i < CSI2RX_PAD_MAX; i++)
 		csi2rx->pads[i].flags = MEDIA_PAD_FL_SOURCE;
 	csi2rx->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+	csi2rx->subdev.entity.ops = &csi2rx_media_ops;
 
 	ret = media_entity_pads_init(&csi2rx->subdev.entity, CSI2RX_PAD_MAX,
 				     csi2rx->pads);

-- 
2.41.0

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

* [PATCH v8 13/16] media: cadence: csi2rx: Add link validation
@ 2023-07-31  8:29   ` Jai Luthra
  0 siblings, 0 replies; 84+ messages in thread
From: Jai Luthra @ 2023-07-31  8:29 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Sakari Ailus, Laurent Pinchart, Tomi Valkeinen
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht, j-luthra

From: Pratyush Yadav <p.yadav@ti.com>

Add media link validation to make sure incorrectly configured pipelines
are caught.

Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
Signed-off-by: Jai Luthra <j-luthra@ti.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
v7->v8: No change

 drivers/media/platform/cadence/cdns-csi2rx.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/media/platform/cadence/cdns-csi2rx.c b/drivers/media/platform/cadence/cdns-csi2rx.c
index d82a8938932f..aec33d28a66f 100644
--- a/drivers/media/platform/cadence/cdns-csi2rx.c
+++ b/drivers/media/platform/cadence/cdns-csi2rx.c
@@ -463,6 +463,10 @@ static const struct v4l2_subdev_ops csi2rx_subdev_ops = {
 	.pad		= &csi2rx_pad_ops,
 };
 
+static const struct media_entity_operations csi2rx_media_ops = {
+	.link_validate = v4l2_subdev_link_validate,
+};
+
 static int csi2rx_async_bound(struct v4l2_async_notifier *notifier,
 			      struct v4l2_subdev *s_subdev,
 			      struct v4l2_async_connection *asd)
@@ -679,6 +683,7 @@ static int csi2rx_probe(struct platform_device *pdev)
 	for (i = CSI2RX_PAD_SOURCE_STREAM0; i < CSI2RX_PAD_MAX; i++)
 		csi2rx->pads[i].flags = MEDIA_PAD_FL_SOURCE;
 	csi2rx->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+	csi2rx->subdev.entity.ops = &csi2rx_media_ops;
 
 	ret = media_entity_pads_init(&csi2rx->subdev.entity, CSI2RX_PAD_MAX,
 				     csi2rx->pads);

-- 
2.41.0

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v8 14/16] media: cadence: csi2rx: Support RAW8 and RAW10 formats
  2023-07-31  8:29 ` Jai Luthra
@ 2023-07-31  8:29   ` Jai Luthra
  -1 siblings, 0 replies; 84+ messages in thread
From: Jai Luthra @ 2023-07-31  8:29 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Sakari Ailus, Laurent Pinchart, Tomi Valkeinen
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht, j-luthra

Many CSI-2 sensors (specifically IMX219) send RAW bayer data instead of
processed YUV or RGB, so add support for 8-bit and 10-bit bayer formats.

Signed-off-by: Jai Luthra <j-luthra@ti.com>
---
New in v8

 drivers/media/platform/cadence/cdns-csi2rx.c | 32 ++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/drivers/media/platform/cadence/cdns-csi2rx.c b/drivers/media/platform/cadence/cdns-csi2rx.c
index aec33d28a66f..bac74474841a 100644
--- a/drivers/media/platform/cadence/cdns-csi2rx.c
+++ b/drivers/media/platform/cadence/cdns-csi2rx.c
@@ -122,6 +122,38 @@ static const struct csi2rx_fmt formats[] = {
 		.code	= MEDIA_BUS_FMT_VYUY8_1X16,
 		.bpp	= 16,
 	},
+	{
+		.code	= MEDIA_BUS_FMT_SBGGR8_1X8,
+		.bpp	= 8,
+	},
+	{
+		.code	= MEDIA_BUS_FMT_SGBRG8_1X8,
+		.bpp	= 8,
+	},
+	{
+		.code	= MEDIA_BUS_FMT_SGRBG8_1X8,
+		.bpp	= 8,
+	},
+	{
+		.code	= MEDIA_BUS_FMT_SRGGB8_1X8,
+		.bpp	= 8,
+	},
+	{
+		.code	= MEDIA_BUS_FMT_SBGGR10_1X10,
+		.bpp	= 10,
+	},
+	{
+		.code	= MEDIA_BUS_FMT_SGBRG10_1X10,
+		.bpp	= 10,
+	},
+	{
+		.code	= MEDIA_BUS_FMT_SGRBG10_1X10,
+		.bpp	= 10,
+	},
+	{
+		.code	= MEDIA_BUS_FMT_SRGGB10_1X10,
+		.bpp	= 10,
+	},
 };
 
 static const struct csi2rx_fmt *csi2rx_get_fmt_by_code(u32 code)

-- 
2.41.0

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

* [PATCH v8 14/16] media: cadence: csi2rx: Support RAW8 and RAW10 formats
@ 2023-07-31  8:29   ` Jai Luthra
  0 siblings, 0 replies; 84+ messages in thread
From: Jai Luthra @ 2023-07-31  8:29 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Sakari Ailus, Laurent Pinchart, Tomi Valkeinen
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht, j-luthra

Many CSI-2 sensors (specifically IMX219) send RAW bayer data instead of
processed YUV or RGB, so add support for 8-bit and 10-bit bayer formats.

Signed-off-by: Jai Luthra <j-luthra@ti.com>
---
New in v8

 drivers/media/platform/cadence/cdns-csi2rx.c | 32 ++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/drivers/media/platform/cadence/cdns-csi2rx.c b/drivers/media/platform/cadence/cdns-csi2rx.c
index aec33d28a66f..bac74474841a 100644
--- a/drivers/media/platform/cadence/cdns-csi2rx.c
+++ b/drivers/media/platform/cadence/cdns-csi2rx.c
@@ -122,6 +122,38 @@ static const struct csi2rx_fmt formats[] = {
 		.code	= MEDIA_BUS_FMT_VYUY8_1X16,
 		.bpp	= 16,
 	},
+	{
+		.code	= MEDIA_BUS_FMT_SBGGR8_1X8,
+		.bpp	= 8,
+	},
+	{
+		.code	= MEDIA_BUS_FMT_SGBRG8_1X8,
+		.bpp	= 8,
+	},
+	{
+		.code	= MEDIA_BUS_FMT_SGRBG8_1X8,
+		.bpp	= 8,
+	},
+	{
+		.code	= MEDIA_BUS_FMT_SRGGB8_1X8,
+		.bpp	= 8,
+	},
+	{
+		.code	= MEDIA_BUS_FMT_SBGGR10_1X10,
+		.bpp	= 10,
+	},
+	{
+		.code	= MEDIA_BUS_FMT_SGBRG10_1X10,
+		.bpp	= 10,
+	},
+	{
+		.code	= MEDIA_BUS_FMT_SGRBG10_1X10,
+		.bpp	= 10,
+	},
+	{
+		.code	= MEDIA_BUS_FMT_SRGGB10_1X10,
+		.bpp	= 10,
+	},
 };
 
 static const struct csi2rx_fmt *csi2rx_get_fmt_by_code(u32 code)

-- 
2.41.0

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v8 15/16] media: dt-bindings: Add TI J721E CSI2RX
  2023-07-31  8:29 ` Jai Luthra
@ 2023-07-31  8:29   ` Jai Luthra
  -1 siblings, 0 replies; 84+ messages in thread
From: Jai Luthra @ 2023-07-31  8:29 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Sakari Ailus, Laurent Pinchart, Tomi Valkeinen
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht, j-luthra

From: Pratyush Yadav <p.yadav@ti.com>

TI's J721E uses the Cadence CSI2RX and DPHY peripherals to facilitate
capture over a CSI-2 bus. The TI CSI2RX platform driver glues all the
parts together.

Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
Signed-off-by: Jai Luthra <j-luthra@ti.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Rob Herring <robh@kernel.org>
---
v7->v8:
- Drop "Device Tree Bindings" from title
- Rename "Wrapper" to "Shim" in title as that is the name referred in
  the TRM and other places
- Update maintainer to myself
- Drop items from compatible as only a single element is present
- Rename compatible to "ti,j721e-csi2rx-shim" to distinguish from the
  SoC-specific CSI2RX bridge compatible

 .../bindings/media/ti,j721e-csi2rx-shim.yaml       | 100 +++++++++++++++++++++
 1 file changed, 100 insertions(+)

diff --git a/Documentation/devicetree/bindings/media/ti,j721e-csi2rx-shim.yaml b/Documentation/devicetree/bindings/media/ti,j721e-csi2rx-shim.yaml
new file mode 100644
index 000000000000..f762fdc05e4d
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/ti,j721e-csi2rx-shim.yaml
@@ -0,0 +1,100 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/ti,j721e-csi2rx-shim.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: TI J721E CSI2RX Shim
+
+description: |
+  The TI J721E CSI2RX Shim is a wrapper around Cadence CSI2RX bridge that
+  enables sending captured frames to memory over PSI-L DMA. In the J721E
+  Technical Reference Manual (SPRUIL1B) it is referred to as "SHIM" under the
+  CSI_RX_IF section.
+
+maintainers:
+  - Jai Luthra <j-luthra@ti.com>
+
+properties:
+  compatible:
+    const: ti,j721e-csi2rx-shim
+
+  dmas:
+    maxItems: 1
+
+  dma-names:
+    items:
+      - const: rx0
+
+  reg:
+    maxItems: 1
+
+  power-domains:
+    maxItems: 1
+
+  ranges: true
+
+  "#address-cells": true
+
+  "#size-cells": true
+
+patternProperties:
+  "^csi-bridge@":
+    type: object
+    description: CSI2 bridge node.
+    $ref: cdns,csi2rx.yaml#
+
+required:
+  - compatible
+  - reg
+  - dmas
+  - dma-names
+  - power-domains
+  - ranges
+  - "#address-cells"
+  - "#size-cells"
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/soc/ti,sci_pm_domain.h>
+
+    ti_csi2rx0: ticsi2rx@4500000 {
+        compatible = "ti,j721e-csi2rx-shim";
+        dmas = <&main_udmap 0x4940>;
+        dma-names = "rx0";
+        reg = <0x4500000 0x1000>;
+        power-domains = <&k3_pds 26 TI_SCI_PD_EXCLUSIVE>;
+        #address-cells = <1>;
+        #size-cells = <1>;
+        ranges;
+
+        cdns_csi2rx: csi-bridge@4504000 {
+            compatible = "ti,j721e-csi2rx", "cdns,csi2rx";
+            reg = <0x4504000 0x1000>;
+            clocks = <&k3_clks 26 2>, <&k3_clks 26 0>, <&k3_clks 26 2>,
+              <&k3_clks 26 2>, <&k3_clks 26 3>, <&k3_clks 26 3>;
+            clock-names = "sys_clk", "p_clk", "pixel_if0_clk",
+              "pixel_if1_clk", "pixel_if2_clk", "pixel_if3_clk";
+            phys = <&dphy0>;
+            phy-names = "dphy";
+
+            ports {
+                #address-cells = <1>;
+                #size-cells = <0>;
+
+                csi2_0: port@0 {
+
+                    reg = <0>;
+
+                    csi2rx0_in_sensor: endpoint {
+                        remote-endpoint = <&csi2_cam0>;
+                        bus-type = <4>; /* CSI2 DPHY. */
+                        clock-lanes = <0>;
+                        data-lanes = <1 2>;
+                    };
+                };
+            };
+        };
+    };

-- 
2.41.0

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

* [PATCH v8 15/16] media: dt-bindings: Add TI J721E CSI2RX
@ 2023-07-31  8:29   ` Jai Luthra
  0 siblings, 0 replies; 84+ messages in thread
From: Jai Luthra @ 2023-07-31  8:29 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Sakari Ailus, Laurent Pinchart, Tomi Valkeinen
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht, j-luthra

From: Pratyush Yadav <p.yadav@ti.com>

TI's J721E uses the Cadence CSI2RX and DPHY peripherals to facilitate
capture over a CSI-2 bus. The TI CSI2RX platform driver glues all the
parts together.

Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
Signed-off-by: Jai Luthra <j-luthra@ti.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Rob Herring <robh@kernel.org>
---
v7->v8:
- Drop "Device Tree Bindings" from title
- Rename "Wrapper" to "Shim" in title as that is the name referred in
  the TRM and other places
- Update maintainer to myself
- Drop items from compatible as only a single element is present
- Rename compatible to "ti,j721e-csi2rx-shim" to distinguish from the
  SoC-specific CSI2RX bridge compatible

 .../bindings/media/ti,j721e-csi2rx-shim.yaml       | 100 +++++++++++++++++++++
 1 file changed, 100 insertions(+)

diff --git a/Documentation/devicetree/bindings/media/ti,j721e-csi2rx-shim.yaml b/Documentation/devicetree/bindings/media/ti,j721e-csi2rx-shim.yaml
new file mode 100644
index 000000000000..f762fdc05e4d
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/ti,j721e-csi2rx-shim.yaml
@@ -0,0 +1,100 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/ti,j721e-csi2rx-shim.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: TI J721E CSI2RX Shim
+
+description: |
+  The TI J721E CSI2RX Shim is a wrapper around Cadence CSI2RX bridge that
+  enables sending captured frames to memory over PSI-L DMA. In the J721E
+  Technical Reference Manual (SPRUIL1B) it is referred to as "SHIM" under the
+  CSI_RX_IF section.
+
+maintainers:
+  - Jai Luthra <j-luthra@ti.com>
+
+properties:
+  compatible:
+    const: ti,j721e-csi2rx-shim
+
+  dmas:
+    maxItems: 1
+
+  dma-names:
+    items:
+      - const: rx0
+
+  reg:
+    maxItems: 1
+
+  power-domains:
+    maxItems: 1
+
+  ranges: true
+
+  "#address-cells": true
+
+  "#size-cells": true
+
+patternProperties:
+  "^csi-bridge@":
+    type: object
+    description: CSI2 bridge node.
+    $ref: cdns,csi2rx.yaml#
+
+required:
+  - compatible
+  - reg
+  - dmas
+  - dma-names
+  - power-domains
+  - ranges
+  - "#address-cells"
+  - "#size-cells"
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/soc/ti,sci_pm_domain.h>
+
+    ti_csi2rx0: ticsi2rx@4500000 {
+        compatible = "ti,j721e-csi2rx-shim";
+        dmas = <&main_udmap 0x4940>;
+        dma-names = "rx0";
+        reg = <0x4500000 0x1000>;
+        power-domains = <&k3_pds 26 TI_SCI_PD_EXCLUSIVE>;
+        #address-cells = <1>;
+        #size-cells = <1>;
+        ranges;
+
+        cdns_csi2rx: csi-bridge@4504000 {
+            compatible = "ti,j721e-csi2rx", "cdns,csi2rx";
+            reg = <0x4504000 0x1000>;
+            clocks = <&k3_clks 26 2>, <&k3_clks 26 0>, <&k3_clks 26 2>,
+              <&k3_clks 26 2>, <&k3_clks 26 3>, <&k3_clks 26 3>;
+            clock-names = "sys_clk", "p_clk", "pixel_if0_clk",
+              "pixel_if1_clk", "pixel_if2_clk", "pixel_if3_clk";
+            phys = <&dphy0>;
+            phy-names = "dphy";
+
+            ports {
+                #address-cells = <1>;
+                #size-cells = <0>;
+
+                csi2_0: port@0 {
+
+                    reg = <0>;
+
+                    csi2rx0_in_sensor: endpoint {
+                        remote-endpoint = <&csi2_cam0>;
+                        bus-type = <4>; /* CSI2 DPHY. */
+                        clock-lanes = <0>;
+                        data-lanes = <1 2>;
+                    };
+                };
+            };
+        };
+    };

-- 
2.41.0

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v8 16/16] media: ti: Add CSI2RX support for J721E
  2023-07-31  8:29 ` Jai Luthra
@ 2023-07-31  8:29   ` Jai Luthra
  -1 siblings, 0 replies; 84+ messages in thread
From: Jai Luthra @ 2023-07-31  8:29 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Sakari Ailus, Laurent Pinchart, Tomi Valkeinen
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht, j-luthra

From: Pratyush Yadav <p.yadav@ti.com>

TI's J721E uses the Cadence CSI2RX and DPHY peripherals to facilitate
capture over a CSI-2 bus.

The Cadence CSI2RX IP acts as a bridge between the TI specific parts and
the CSI-2 protocol parts. TI then has a wrapper on top of this bridge
called the SHIM layer. It takes in data from stream 0, repacks it, and
sends it to memory over PSI-L DMA.

This driver acts as the "front end" to V4L2 client applications. It
implements the required ioctls and buffer operations, passes the
necessary calls on to the bridge, programs the SHIM layer, and performs
DMA via the dmaengine API to finally return the data to a buffer
supplied by the application.

Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
Co-authored-by: Vaishnav Achath <vaishnav.a@ti.com>
Signed-off-by: Vaishnav Achath <vaishnav.a@ti.com>
Co-authored-by: Jai Luthra <j-luthra@ti.com>
Signed-off-by: Jai Luthra <j-luthra@ti.com>
---
v7->v8:
- Move after dt-bindings to keep the series bisectable
- Rename compatible to "ti,j721e-csi2rx-shim" to distinguish from the
  SoC-specific CSI2RX bridge compatible
- Make myself the Maintainer
- Support RAW8 and RAW10 formats, and setting the pixel-unwrap size on
  SHIM (RAW10 is stored in 16-bit containers, while RAW8 in 8-bit containers)
- Fix enum_fmt_vid_cap() to respect CAP_IO_MC and only list pixelformats
  matching the mbus formats set on the subdev.
- Fix enum_framesizes() to stop enumerating more than a single framesize
  (reject non-zero fsize->index)
- Simplify notifier bound fucntion to use v4l2_create_fwnode_links_to_pad()
  and inline the video_register() method
- Add support for draining the DMA with an extra buffer, to get rid of
  stale data in the pipeline on stream stop (or when frames start
  getting dropped due to load)
- Queue all available buffers to DMAEngine in the callback, also use a
  separate "submitted" queue to track all buffers submitted to DMA
- Use video_device_pipeline_start() instead of media_pipeline_start()
- Drop support for VB_READ
- Print issues in link validation as DEBUG instead of ERROR
- s/async_subdev/async_connection

 MAINTAINERS                                        |    7 +
 drivers/media/platform/ti/Kconfig                  |   12 +
 drivers/media/platform/ti/Makefile                 |    1 +
 drivers/media/platform/ti/j721e-csi2rx/Makefile    |    2 +
 .../media/platform/ti/j721e-csi2rx/j721e-csi2rx.c  | 1127 ++++++++++++++++++++
 5 files changed, 1149 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index d7b867c57920..1c2d75c30ce7 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -21445,6 +21445,13 @@ F:	Documentation/devicetree/bindings/media/i2c/ti,ds90*
 F:	drivers/media/i2c/ds90*
 F:	include/media/i2c/ds90*
 
+TI J721E CSI2RX DRIVER
+M:	Jai Luthra <j-luthra@ti.com>
+L:	linux-media@vger.kernel.org
+S:	Maintained
+F:	Documentation/devicetree/bindings/media/ti,j721e-csi2rx.yaml
+F:	drivers/media/platform/ti/j721e-csi2rx/
+
 TI KEYSTONE MULTICORE NAVIGATOR DRIVERS
 M:	Nishanth Menon <nm@ti.com>
 M:	Santosh Shilimkar <ssantosh@kernel.org>
diff --git a/drivers/media/platform/ti/Kconfig b/drivers/media/platform/ti/Kconfig
index e1ab56c3be1f..42c908f6e1ae 100644
--- a/drivers/media/platform/ti/Kconfig
+++ b/drivers/media/platform/ti/Kconfig
@@ -63,6 +63,18 @@ config VIDEO_TI_VPE_DEBUG
 	help
 	  Enable debug messages on VPE driver.
 
+config VIDEO_TI_J721E_CSI2RX
+	tristate "TI J721E CSI2RX wrapper layer driver"
+	depends on VIDEO_DEV && VIDEO_V4L2_SUBDEV_API
+	depends on MEDIA_SUPPORT && MEDIA_CONTROLLER
+	depends on PHY_CADENCE_DPHY_RX && VIDEO_CADENCE_CSI2RX
+	depends on ARCH_K3 || COMPILE_TEST
+	select VIDEOBUF2_DMA_CONTIG
+	select V4L2_FWNODE
+	help
+	  Support for TI CSI2RX wrapper layer. This just enables the wrapper driver.
+	  The Cadence CSI2RX bridge driver needs to be enabled separately.
+
 source "drivers/media/platform/ti/am437x/Kconfig"
 source "drivers/media/platform/ti/davinci/Kconfig"
 source "drivers/media/platform/ti/omap/Kconfig"
diff --git a/drivers/media/platform/ti/Makefile b/drivers/media/platform/ti/Makefile
index 98c5fe5c40d6..8a2f74c9380e 100644
--- a/drivers/media/platform/ti/Makefile
+++ b/drivers/media/platform/ti/Makefile
@@ -3,5 +3,6 @@ obj-y += am437x/
 obj-y += cal/
 obj-y += vpe/
 obj-y += davinci/
+obj-y += j721e-csi2rx/
 obj-y += omap/
 obj-y += omap3isp/
diff --git a/drivers/media/platform/ti/j721e-csi2rx/Makefile b/drivers/media/platform/ti/j721e-csi2rx/Makefile
new file mode 100644
index 000000000000..377afc1d6280
--- /dev/null
+++ b/drivers/media/platform/ti/j721e-csi2rx/Makefile
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0
+obj-$(CONFIG_VIDEO_TI_J721E_CSI2RX) += j721e-csi2rx.o
diff --git a/drivers/media/platform/ti/j721e-csi2rx/j721e-csi2rx.c b/drivers/media/platform/ti/j721e-csi2rx/j721e-csi2rx.c
new file mode 100644
index 000000000000..29f1879cfc25
--- /dev/null
+++ b/drivers/media/platform/ti/j721e-csi2rx/j721e-csi2rx.c
@@ -0,0 +1,1127 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * TI CSI2RX Shim Wrapper Driver
+ *
+ * Copyright (C) 2021 Texas Instruments Incorporated - https://www.ti.com/
+ *
+ * Author: Pratyush Yadav <p.yadav@ti.com>
+ */
+
+#include <linux/bitfield.h>
+#include <linux/dmaengine.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+
+#include <media/mipi-csi2.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-mc.h>
+#include <media/videobuf2-dma-contig.h>
+
+#define TI_CSI2RX_MODULE_NAME		"j721e-csi2rx"
+
+#define SHIM_CNTL			0x10
+#define SHIM_CNTL_PIX_RST		BIT(0)
+
+#define SHIM_DMACNTX			0x20
+#define SHIM_DMACNTX_EN			BIT(31)
+#define SHIM_DMACNTX_YUV422		GENMASK(27, 26)
+#define SHIM_DMACNTX_SIZE		GENMASK(21, 20)
+#define SHIM_DMACNTX_FMT		GENMASK(5, 0)
+#define SHIM_DMACNTX_UYVY		0
+#define SHIM_DMACNTX_VYUY		1
+#define SHIM_DMACNTX_YUYV		2
+#define SHIM_DMACNTX_YVYU		3
+#define SHIM_DMACNTX_SIZE_8		0
+#define SHIM_DMACNTX_SIZE_16		1
+#define SHIM_DMACNTX_SIZE_32		2
+
+#define SHIM_PSI_CFG0			0x24
+#define SHIM_PSI_CFG0_SRC_TAG		GENMASK(15, 0)
+#define SHIM_PSI_CFG0_DST_TAG		GENMASK(31, 16)
+
+#define PSIL_WORD_SIZE_BYTES		16
+/*
+ * There are no hard limits on the width or height. The DMA engine can handle
+ * all sizes. The max width and height are arbitrary numbers for this driver.
+ * Use 16K * 16K as the arbitrary limit. It is large enough that it is unlikely
+ * the limit will be hit in practice.
+ */
+#define MAX_WIDTH_BYTES			SZ_16K
+#define MAX_HEIGHT_LINES		SZ_16K
+
+#define DRAIN_TIMEOUT_MS		50
+
+struct ti_csi2rx_fmt {
+	u32				fourcc;	/* Four character code. */
+	u32				code;	/* Mbus code. */
+	u32				csi_dt;	/* CSI Data type. */
+	u8				bpp;	/* Bits per pixel. */
+	u8				size;	/* Data size shift when unpacking. */
+};
+
+struct ti_csi2rx_buffer {
+	/* Common v4l2 buffer. Must be first. */
+	struct vb2_v4l2_buffer		vb;
+	struct list_head		list;
+	struct ti_csi2rx_dev		*csi;
+};
+
+enum ti_csi2rx_dma_state {
+	TI_CSI2RX_DMA_STOPPED,	/* Streaming not started yet. */
+	TI_CSI2RX_DMA_IDLE,	/* Streaming but no pending DMA operation. */
+	TI_CSI2RX_DMA_ACTIVE,	/* Streaming and pending DMA operation. */
+};
+
+struct ti_csi2rx_dma {
+	/* Protects all fields in this struct. */
+	spinlock_t			lock;
+	struct dma_chan			*chan;
+	/* Buffers queued to the driver, waiting to be processed by DMA. */
+	struct list_head		queue;
+	enum ti_csi2rx_dma_state	state;
+	/*
+	 * Queue of buffers submitted to DMA engine.
+	 */
+	struct list_head		submitted;
+};
+
+struct ti_csi2rx_dev {
+	struct device			*dev;
+	void __iomem			*shim;
+	struct v4l2_device		v4l2_dev;
+	struct video_device		vdev;
+	struct media_device		mdev;
+	struct media_pipeline		pipe;
+	struct media_pad		pad;
+	struct v4l2_async_notifier	notifier;
+	struct v4l2_subdev		*subdev;
+	struct vb2_queue		vidq;
+	struct mutex			mutex; /* To serialize ioctls. */
+	struct v4l2_format		v_fmt;
+	struct ti_csi2rx_dma		dma;
+	u32				sequence;
+};
+
+static const struct ti_csi2rx_fmt formats[] = {
+	{
+		.fourcc			= V4L2_PIX_FMT_YUYV,
+		.code			= MEDIA_BUS_FMT_YUYV8_1X16,
+		.csi_dt			= MIPI_CSI2_DT_YUV422_8B,
+		.bpp			= 16,
+		.size			= SHIM_DMACNTX_SIZE_8,
+	}, {
+		.fourcc			= V4L2_PIX_FMT_UYVY,
+		.code			= MEDIA_BUS_FMT_UYVY8_1X16,
+		.csi_dt			= MIPI_CSI2_DT_YUV422_8B,
+		.bpp			= 16,
+		.size			= SHIM_DMACNTX_SIZE_8,
+	}, {
+		.fourcc			= V4L2_PIX_FMT_YVYU,
+		.code			= MEDIA_BUS_FMT_YVYU8_1X16,
+		.csi_dt			= MIPI_CSI2_DT_YUV422_8B,
+		.bpp			= 16,
+		.size			= SHIM_DMACNTX_SIZE_8,
+	}, {
+		.fourcc			= V4L2_PIX_FMT_VYUY,
+		.code			= MEDIA_BUS_FMT_VYUY8_1X16,
+		.csi_dt			= MIPI_CSI2_DT_YUV422_8B,
+		.bpp			= 16,
+		.size			= SHIM_DMACNTX_SIZE_8,
+	}, {
+		.fourcc			= V4L2_PIX_FMT_SBGGR8,
+		.code			= MEDIA_BUS_FMT_SBGGR8_1X8,
+		.csi_dt			= MIPI_CSI2_DT_RAW8,
+		.bpp			= 8,
+		.size			= SHIM_DMACNTX_SIZE_8,
+	}, {
+		.fourcc			= V4L2_PIX_FMT_SGBRG8,
+		.code			= MEDIA_BUS_FMT_SGBRG8_1X8,
+		.csi_dt			= MIPI_CSI2_DT_RAW8,
+		.bpp			= 8,
+		.size			= SHIM_DMACNTX_SIZE_8,
+	}, {
+		.fourcc			= V4L2_PIX_FMT_SGRBG8,
+		.code			= MEDIA_BUS_FMT_SGRBG8_1X8,
+		.csi_dt			= MIPI_CSI2_DT_RAW8,
+		.bpp			= 8,
+		.size			= SHIM_DMACNTX_SIZE_8,
+	}, {
+		.fourcc			= V4L2_PIX_FMT_SRGGB8,
+		.code			= MEDIA_BUS_FMT_SRGGB8_1X8,
+		.csi_dt			= MIPI_CSI2_DT_RAW8,
+		.bpp			= 8,
+		.size			= SHIM_DMACNTX_SIZE_8,
+	}, {
+		.fourcc			= V4L2_PIX_FMT_SBGGR10,
+		.code			= MEDIA_BUS_FMT_SBGGR10_1X10,
+		.csi_dt			= MIPI_CSI2_DT_RAW10,
+		.bpp			= 16,
+		.size			= SHIM_DMACNTX_SIZE_16,
+	}, {
+		.fourcc			= V4L2_PIX_FMT_SGBRG10,
+		.code			= MEDIA_BUS_FMT_SGBRG10_1X10,
+		.csi_dt			= MIPI_CSI2_DT_RAW10,
+		.bpp			= 16,
+		.size			= SHIM_DMACNTX_SIZE_16,
+	}, {
+		.fourcc			= V4L2_PIX_FMT_SGRBG10,
+		.code			= MEDIA_BUS_FMT_SGRBG10_1X10,
+		.csi_dt			= MIPI_CSI2_DT_RAW10,
+		.bpp			= 16,
+		.size			= SHIM_DMACNTX_SIZE_16,
+	}, {
+		.fourcc			= V4L2_PIX_FMT_SRGGB10,
+		.code			= MEDIA_BUS_FMT_SRGGB10_1X10,
+		.csi_dt			= MIPI_CSI2_DT_RAW10,
+		.bpp			= 16,
+		.size			= SHIM_DMACNTX_SIZE_16,
+	},
+
+	/* More formats can be supported but they are not listed for now. */
+};
+
+static const unsigned int num_formats = ARRAY_SIZE(formats);
+
+/* Forward declaration needed by ti_csi2rx_dma_callback. */
+static int ti_csi2rx_start_dma(struct ti_csi2rx_dev *csi,
+			       struct ti_csi2rx_buffer *buf);
+
+static const struct ti_csi2rx_fmt *find_format_by_pix(u32 pixelformat)
+{
+	unsigned int i;
+
+	for (i = 0; i < num_formats; i++) {
+		if (formats[i].fourcc == pixelformat)
+			return &formats[i];
+	}
+
+	return NULL;
+}
+
+static const struct ti_csi2rx_fmt *find_format_by_code(u32 code)
+{
+	unsigned int i;
+
+	for (i = 0; i < num_formats; i++) {
+		if (formats[i].code == code)
+			return &formats[i];
+	}
+
+	return NULL;
+}
+
+static void ti_csi2rx_fill_fmt(const struct ti_csi2rx_fmt *csi_fmt,
+			       struct v4l2_format *v4l2_fmt)
+{
+	struct v4l2_pix_format *pix = &v4l2_fmt->fmt.pix;
+	unsigned int pixels_in_word;
+	u8 bpp = csi_fmt->bpp;
+	u32 bpl;
+
+	pixels_in_word = PSIL_WORD_SIZE_BYTES * 8 / bpp;
+
+	pix->width = clamp_t(unsigned int, pix->width,
+			     pixels_in_word,
+			     MAX_WIDTH_BYTES * 8 / bpp);
+	pix->width = rounddown(pix->width, pixels_in_word);
+
+	pix->height = clamp_t(unsigned int, pix->height, 1, MAX_HEIGHT_LINES);
+
+	v4l2_fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	pix->pixelformat = csi_fmt->fourcc;
+	pix->colorspace = V4L2_COLORSPACE_SRGB;
+	pix->sizeimage = pix->height * pix->width * (bpp / 8);
+
+	bpl = (pix->width * ALIGN(bpp, 8)) >> 3;
+	pix->bytesperline = ALIGN(bpl, 16);
+}
+
+static int ti_csi2rx_querycap(struct file *file, void *priv,
+			      struct v4l2_capability *cap)
+{
+	strscpy(cap->driver, TI_CSI2RX_MODULE_NAME, sizeof(cap->driver));
+	strscpy(cap->card, TI_CSI2RX_MODULE_NAME, sizeof(cap->card));
+
+	return 0;
+}
+
+static int ti_csi2rx_enum_fmt_vid_cap(struct file *file, void *priv,
+				      struct v4l2_fmtdesc *f)
+{
+	const struct ti_csi2rx_fmt *fmt = NULL;
+
+	if (f->mbus_code) {
+		if (f->index > 0)
+			return -EINVAL;
+
+		fmt = find_format_by_code(f->mbus_code);
+	} else {
+		if (f->index >= num_formats)
+			return -EINVAL;
+
+		fmt = &formats[f->index];
+	}
+
+	if (!fmt)
+		return -EINVAL;
+
+	f->pixelformat = fmt->fourcc;
+	memset(f->reserved, 0, sizeof(f->reserved));
+	f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+	return 0;
+}
+
+static int ti_csi2rx_g_fmt_vid_cap(struct file *file, void *prov,
+				   struct v4l2_format *f)
+{
+	struct ti_csi2rx_dev *csi = video_drvdata(file);
+
+	*f = csi->v_fmt;
+
+	return 0;
+}
+
+static int ti_csi2rx_try_fmt_vid_cap(struct file *file, void *priv,
+				     struct v4l2_format *f)
+{
+	const struct ti_csi2rx_fmt *fmt;
+
+	/*
+	 * Default to the first format if the requested pixel format code isn't
+	 * supported.
+	 */
+	fmt = find_format_by_pix(f->fmt.pix.pixelformat);
+	if (!fmt)
+		fmt = &formats[0];
+
+	if (f->fmt.pix.field == V4L2_FIELD_ANY)
+		f->fmt.pix.field = V4L2_FIELD_NONE;
+
+	if (f->fmt.pix.field != V4L2_FIELD_NONE)
+		/* Interlaced formats are not supported. */
+		f->fmt.pix.field = V4L2_FIELD_NONE;
+
+	ti_csi2rx_fill_fmt(fmt, f);
+
+	return 0;
+}
+
+static int ti_csi2rx_s_fmt_vid_cap(struct file *file, void *priv,
+				   struct v4l2_format *f)
+{
+	struct ti_csi2rx_dev *csi = video_drvdata(file);
+	struct vb2_queue *q = &csi->vidq;
+	int ret;
+
+	if (vb2_is_busy(q))
+		return -EBUSY;
+
+	ret = ti_csi2rx_try_fmt_vid_cap(file, priv, f);
+	if (ret < 0)
+		return ret;
+
+	csi->v_fmt = *f;
+
+	return 0;
+}
+
+static int ti_csi2rx_enum_framesizes(struct file *file, void *fh,
+				     struct v4l2_frmsizeenum *fsize)
+{
+	const struct ti_csi2rx_fmt *fmt;
+	unsigned int pixels_in_word;
+	u8 bpp;
+
+	fmt = find_format_by_pix(fsize->pixel_format);
+	if (!fmt || fsize->index != 0)
+		return -EINVAL;
+
+	bpp = ALIGN(fmt->bpp, 8);
+
+	/*
+	 * Number of pixels in one PSI-L word. The transfer happens in multiples
+	 * of PSI-L word sizes.
+	 */
+	pixels_in_word = PSIL_WORD_SIZE_BYTES * 8 / bpp;
+
+	fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
+	fsize->stepwise.min_width = pixels_in_word;
+	fsize->stepwise.max_width = rounddown(MAX_WIDTH_BYTES * 8 / bpp,
+					      pixels_in_word);
+	fsize->stepwise.step_width = pixels_in_word;
+	fsize->stepwise.min_height = 1;
+	fsize->stepwise.max_height = MAX_HEIGHT_LINES;
+	fsize->stepwise.step_height = 1;
+
+	return 0;
+}
+
+static const struct v4l2_ioctl_ops csi_ioctl_ops = {
+	.vidioc_querycap      = ti_csi2rx_querycap,
+	.vidioc_enum_fmt_vid_cap = ti_csi2rx_enum_fmt_vid_cap,
+	.vidioc_try_fmt_vid_cap = ti_csi2rx_try_fmt_vid_cap,
+	.vidioc_g_fmt_vid_cap = ti_csi2rx_g_fmt_vid_cap,
+	.vidioc_s_fmt_vid_cap = ti_csi2rx_s_fmt_vid_cap,
+	.vidioc_enum_framesizes = ti_csi2rx_enum_framesizes,
+	.vidioc_reqbufs       = vb2_ioctl_reqbufs,
+	.vidioc_create_bufs   = vb2_ioctl_create_bufs,
+	.vidioc_prepare_buf   = vb2_ioctl_prepare_buf,
+	.vidioc_querybuf      = vb2_ioctl_querybuf,
+	.vidioc_qbuf          = vb2_ioctl_qbuf,
+	.vidioc_dqbuf         = vb2_ioctl_dqbuf,
+	.vidioc_expbuf        = vb2_ioctl_expbuf,
+	.vidioc_streamon      = vb2_ioctl_streamon,
+	.vidioc_streamoff     = vb2_ioctl_streamoff,
+};
+
+static const struct v4l2_file_operations csi_fops = {
+	.owner = THIS_MODULE,
+	.open = v4l2_fh_open,
+	.release = vb2_fop_release,
+	.read = vb2_fop_read,
+	.poll = vb2_fop_poll,
+	.unlocked_ioctl = video_ioctl2,
+	.mmap = vb2_fop_mmap,
+};
+
+static int csi_async_notifier_bound(struct v4l2_async_notifier *notifier,
+				    struct v4l2_subdev *subdev,
+				    struct v4l2_async_connection *asc)
+{
+	struct ti_csi2rx_dev *csi = dev_get_drvdata(notifier->v4l2_dev->dev);
+
+	csi->subdev = subdev;
+
+	return 0;
+}
+
+static int csi_async_notifier_complete(struct v4l2_async_notifier *notifier)
+{
+	struct ti_csi2rx_dev *csi = dev_get_drvdata(notifier->v4l2_dev->dev);
+	struct video_device *vdev = &csi->vdev;
+	int ret;
+
+	ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1);
+	if (ret)
+		return ret;
+
+	ret = v4l2_create_fwnode_links_to_pad(csi->subdev, &csi->pad,
+					      MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED);
+
+	if (ret) {
+		video_unregister_device(vdev);
+		return ret;
+	}
+
+	return v4l2_device_register_subdev_nodes(&csi->v4l2_dev);
+}
+
+static const struct v4l2_async_notifier_operations csi_async_notifier_ops = {
+	.bound = csi_async_notifier_bound,
+	.complete = csi_async_notifier_complete,
+};
+
+static int ti_csi2rx_init_subdev(struct ti_csi2rx_dev *csi)
+{
+	struct fwnode_handle *fwnode;
+	struct v4l2_async_connection *asc;
+	struct device_node *node;
+	int ret;
+
+	node = of_get_child_by_name(csi->dev->of_node, "csi-bridge");
+	if (!node)
+		return -EINVAL;
+
+	fwnode = of_fwnode_handle(node);
+	if (!fwnode) {
+		of_node_put(node);
+		return -EINVAL;
+	}
+
+	v4l2_async_nf_init(&csi->notifier, &csi->v4l2_dev);
+	csi->notifier.ops = &csi_async_notifier_ops;
+
+	asc = v4l2_async_nf_add_fwnode(&csi->notifier, fwnode,
+				       struct v4l2_async_connection);
+	of_node_put(node);
+	if (IS_ERR(asc)) {
+		v4l2_async_nf_cleanup(&csi->notifier);
+		return PTR_ERR(asc);
+	}
+
+	ret = v4l2_async_nf_register(&csi->notifier);
+	if (ret) {
+		v4l2_async_nf_cleanup(&csi->notifier);
+		return ret;
+	}
+
+	return 0;
+}
+
+static void ti_csi2rx_setup_shim(struct ti_csi2rx_dev *csi)
+{
+	const struct ti_csi2rx_fmt *fmt;
+	unsigned int reg;
+
+	fmt = find_format_by_pix(csi->v_fmt.fmt.pix.pixelformat);
+	if (!fmt) {
+		dev_err(csi->dev, "Unknown format\n");
+		return;
+	}
+
+	/* De-assert the pixel interface reset. */
+	reg = SHIM_CNTL_PIX_RST;
+	writel(reg, csi->shim + SHIM_CNTL);
+
+	reg = SHIM_DMACNTX_EN;
+	reg |= FIELD_PREP(SHIM_DMACNTX_FMT, fmt->csi_dt);
+
+	/*
+	 * Using the values from the documentation gives incorrect ordering for
+	 * the luma and chroma components. In practice, the "reverse" format
+	 * gives the correct image. So for example, if the image is in UYVY, the
+	 * reverse would be YVYU.
+	 */
+	switch (fmt->fourcc) {
+	case V4L2_PIX_FMT_UYVY:
+		reg |= FIELD_PREP(SHIM_DMACNTX_YUV422,
+					SHIM_DMACNTX_YVYU);
+		break;
+	case V4L2_PIX_FMT_VYUY:
+		reg |= FIELD_PREP(SHIM_DMACNTX_YUV422,
+					SHIM_DMACNTX_YUYV);
+		break;
+	case V4L2_PIX_FMT_YUYV:
+		reg |= FIELD_PREP(SHIM_DMACNTX_YUV422,
+					SHIM_DMACNTX_VYUY);
+		break;
+	case V4L2_PIX_FMT_YVYU:
+		reg |= FIELD_PREP(SHIM_DMACNTX_YUV422,
+					SHIM_DMACNTX_UYVY);
+		break;
+	default:
+		/* Ignore if not YUV 4:2:2 */
+		break;
+	}
+
+	reg |= FIELD_PREP(SHIM_DMACNTX_SIZE, fmt->size);
+
+	writel(reg, csi->shim + SHIM_DMACNTX);
+
+	reg = FIELD_PREP(SHIM_PSI_CFG0_SRC_TAG, 0) |
+	      FIELD_PREP(SHIM_PSI_CFG0_DST_TAG, 0);
+	writel(reg, csi->shim + SHIM_PSI_CFG0);
+}
+
+static void ti_csi2rx_drain_callback(void *param)
+{
+	struct completion *drain_complete = param;
+
+	complete(drain_complete);
+}
+
+static int ti_csi2rx_drain_dma(struct ti_csi2rx_dev *csi)
+{
+	struct dma_async_tx_descriptor *desc;
+	struct device *dev = csi->dma.chan->device->dev;
+	struct completion drain_complete;
+	void *buf;
+	size_t len = csi->v_fmt.fmt.pix.sizeimage;
+	dma_addr_t addr;
+	dma_cookie_t cookie;
+	int ret;
+
+	init_completion(&drain_complete);
+
+	buf = dma_alloc_coherent(dev, len, &addr, GFP_KERNEL | GFP_ATOMIC);
+	if (!buf)
+		return -ENOMEM;
+
+	desc = dmaengine_prep_slave_single(csi->dma.chan, addr, len,
+					   DMA_DEV_TO_MEM,
+					   DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+	if (!desc) {
+		ret = -EIO;
+		goto out;
+	}
+
+	desc->callback = ti_csi2rx_drain_callback;
+	desc->callback_param = &drain_complete;
+
+	cookie = dmaengine_submit(desc);
+	ret = dma_submit_error(cookie);
+	if (ret)
+		goto out;
+
+	dma_async_issue_pending(csi->dma.chan);
+
+	if (!wait_for_completion_timeout(&drain_complete,
+					 msecs_to_jiffies(DRAIN_TIMEOUT_MS))) {
+		dmaengine_terminate_sync(csi->dma.chan);
+		ret = -ETIMEDOUT;
+		goto out;
+	}
+out:
+	dma_free_coherent(dev, len, buf, addr);
+	return ret;
+}
+
+static void ti_csi2rx_dma_callback(void *param)
+{
+	struct ti_csi2rx_buffer *buf = param;
+	struct ti_csi2rx_dev *csi = buf->csi;
+	struct ti_csi2rx_dma *dma = &csi->dma;
+	unsigned long flags;
+
+	/*
+	 * TODO: Derive the sequence number from the CSI2RX frame number
+	 * hardware monitor registers.
+	 */
+	buf->vb.vb2_buf.timestamp = ktime_get_ns();
+	buf->vb.sequence = csi->sequence++;
+
+	spin_lock_irqsave(&dma->lock, flags);
+
+	WARN_ON(!list_is_first(&buf->list, &dma->submitted));
+	vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
+	list_del(&buf->list);
+
+	/* If there are more buffers to process then start their transfer. */
+	while (!list_empty(&dma->queue)) {
+		buf = list_entry(dma->queue.next, struct ti_csi2rx_buffer, list);
+
+		if (ti_csi2rx_start_dma(csi, buf)) {
+			dev_err(csi->dev, "Failed to queue the next buffer for DMA\n");
+			vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
+		} else {
+			list_move_tail(&buf->list, &dma->submitted);
+		}
+	}
+
+	if (list_empty(&dma->submitted))
+		dma->state = TI_CSI2RX_DMA_IDLE;
+
+	spin_unlock_irqrestore(&dma->lock, flags);
+}
+
+static int ti_csi2rx_start_dma(struct ti_csi2rx_dev *csi,
+			       struct ti_csi2rx_buffer *buf)
+{
+	unsigned long addr;
+	struct dma_async_tx_descriptor *desc;
+	size_t len = csi->v_fmt.fmt.pix.sizeimage;
+	dma_cookie_t cookie;
+	int ret = 0;
+
+	addr = vb2_dma_contig_plane_dma_addr(&buf->vb.vb2_buf, 0);
+	desc = dmaengine_prep_slave_single(csi->dma.chan, addr, len,
+					   DMA_DEV_TO_MEM,
+					   DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+	if (!desc)
+		return -EIO;
+
+	desc->callback = ti_csi2rx_dma_callback;
+	desc->callback_param = buf;
+
+	cookie = dmaengine_submit(desc);
+	ret = dma_submit_error(cookie);
+	if (ret)
+		return ret;
+
+	dma_async_issue_pending(csi->dma.chan);
+
+	return 0;
+}
+
+static void ti_csi2rx_cleanup_buffers(struct ti_csi2rx_dev *csi,
+				      enum vb2_buffer_state buf_state)
+{
+	struct ti_csi2rx_dma *dma = &csi->dma;
+	struct ti_csi2rx_buffer *buf, *tmp;
+	enum ti_csi2rx_dma_state state;
+	unsigned long flags;
+	int ret;
+
+	spin_lock_irqsave(&dma->lock, flags);
+	state = csi->dma.state;
+	dma->state = TI_CSI2RX_DMA_STOPPED;
+	spin_unlock_irqrestore(&dma->lock, flags);
+
+	if (state != TI_CSI2RX_DMA_STOPPED) {
+		ret = ti_csi2rx_drain_dma(csi);
+		if (ret)
+			dev_dbg(csi->dev,
+				"Failed to drain DMA. Next frame might be bogus\n");
+	}
+	ret = dmaengine_terminate_sync(csi->dma.chan);
+	if (ret)
+		dev_err(csi->dev, "Failed to stop DMA: %d\n", ret);
+
+	spin_lock_irqsave(&dma->lock, flags);
+	list_for_each_entry_safe(buf, tmp, &csi->dma.queue, list) {
+		list_del(&buf->list);
+		vb2_buffer_done(&buf->vb.vb2_buf, buf_state);
+	}
+	list_for_each_entry_safe(buf, tmp, &csi->dma.submitted, list) {
+		list_del(&buf->list);
+		vb2_buffer_done(&buf->vb.vb2_buf, buf_state);
+	}
+	spin_unlock_irqrestore(&dma->lock, flags);
+}
+
+static int ti_csi2rx_queue_setup(struct vb2_queue *q, unsigned int *nbuffers,
+				 unsigned int *nplanes, unsigned int sizes[],
+				 struct device *alloc_devs[])
+{
+	struct ti_csi2rx_dev *csi = vb2_get_drv_priv(q);
+	unsigned int size = csi->v_fmt.fmt.pix.sizeimage;
+
+	if (*nplanes) {
+		if (sizes[0] < size)
+			return -EINVAL;
+		size = sizes[0];
+	}
+
+	*nplanes = 1;
+	sizes[0] = size;
+
+	return 0;
+}
+
+static int ti_csi2rx_buffer_prepare(struct vb2_buffer *vb)
+{
+	struct ti_csi2rx_dev *csi = vb2_get_drv_priv(vb->vb2_queue);
+	unsigned long size = csi->v_fmt.fmt.pix.sizeimage;
+
+	if (vb2_plane_size(vb, 0) < size) {
+		dev_err(csi->dev, "Data will not fit into plane\n");
+		return -EINVAL;
+	}
+
+	vb2_set_plane_payload(vb, 0, size);
+	return 0;
+}
+
+static void ti_csi2rx_buffer_queue(struct vb2_buffer *vb)
+{
+	struct ti_csi2rx_dev *csi = vb2_get_drv_priv(vb->vb2_queue);
+	struct ti_csi2rx_buffer *buf;
+	struct ti_csi2rx_dma *dma = &csi->dma;
+	bool restart_dma = false;
+	unsigned long flags = 0;
+	int ret;
+
+	buf = container_of(vb, struct ti_csi2rx_buffer, vb.vb2_buf);
+	buf->csi = csi;
+
+	spin_lock_irqsave(&dma->lock, flags);
+	/*
+	 * Usually the DMA callback takes care of queueing the pending buffers.
+	 * But if DMA has stalled due to lack of buffers, restart it now.
+	 */
+	if (dma->state == TI_CSI2RX_DMA_IDLE) {
+		/*
+		 * Do not restart DMA with the lock held because
+		 * ti_csi2rx_drain_dma() might block when allocating a buffer.
+		 * There won't be a race on queueing DMA anyway since the
+		 * callback is not being fired.
+		 */
+		restart_dma = true;
+		dma->state = TI_CSI2RX_DMA_ACTIVE;
+	} else {
+		list_add_tail(&buf->list, &dma->queue);
+	}
+	spin_unlock_irqrestore(&dma->lock, flags);
+
+	if (restart_dma) {
+		/*
+		 * Once frames start dropping, some data gets stuck in the DMA
+		 * pipeline somewhere. So the first DMA transfer after frame
+		 * drops gives a partial frame. This is obviously not useful to
+		 * the application and will only confuse it. Issue a DMA
+		 * transaction to drain that up.
+		 */
+		ret = ti_csi2rx_drain_dma(csi);
+		if (ret)
+			dev_warn(csi->dev,
+				 "Failed to drain DMA. Next frame might be bogus\n");
+
+		ret = ti_csi2rx_start_dma(csi, buf);
+		if (ret) {
+			dev_err(csi->dev, "Failed to start DMA: %d\n", ret);
+			spin_lock_irqsave(&dma->lock, flags);
+			vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
+			dma->state = TI_CSI2RX_DMA_IDLE;
+			spin_unlock_irqrestore(&dma->lock, flags);
+		} else {
+			spin_lock_irqsave(&dma->lock, flags);
+			list_add_tail(&buf->list, &dma->submitted);
+			spin_unlock_irqrestore(&dma->lock, flags);
+		}
+	}
+}
+
+static int ti_csi2rx_start_streaming(struct vb2_queue *vq, unsigned int count)
+{
+	struct ti_csi2rx_dev *csi = vb2_get_drv_priv(vq);
+	struct ti_csi2rx_dma *dma = &csi->dma;
+	struct ti_csi2rx_buffer *buf;
+	unsigned long flags;
+	int ret = 0;
+
+	spin_lock_irqsave(&dma->lock, flags);
+	if (list_empty(&dma->queue))
+		ret = -EIO;
+	spin_unlock_irqrestore(&dma->lock, flags);
+	if (ret)
+		return ret;
+
+	ret = video_device_pipeline_start(&csi->vdev, &csi->pipe);
+	if (ret)
+		goto err;
+
+	ti_csi2rx_setup_shim(csi);
+
+	csi->sequence = 0;
+
+	spin_lock_irqsave(&dma->lock, flags);
+	buf = list_entry(dma->queue.next, struct ti_csi2rx_buffer, list);
+
+	ret = ti_csi2rx_start_dma(csi, buf);
+	if (ret) {
+		dev_err(csi->dev, "Failed to start DMA: %d\n", ret);
+		spin_unlock_irqrestore(&dma->lock, flags);
+		goto err_pipeline;
+	}
+
+	list_move_tail(&buf->list, &dma->submitted);
+	dma->state = TI_CSI2RX_DMA_ACTIVE;
+	spin_unlock_irqrestore(&dma->lock, flags);
+
+	ret = v4l2_subdev_call(csi->subdev, video, s_stream, 1);
+	if (ret)
+		goto err_dma;
+
+	return 0;
+
+err_dma:
+	dmaengine_terminate_sync(csi->dma.chan);
+	writel(0, csi->shim + SHIM_DMACNTX);
+err_pipeline:
+	video_device_pipeline_stop(&csi->vdev);
+err:
+	ti_csi2rx_cleanup_buffers(csi, VB2_BUF_STATE_QUEUED);
+	return ret;
+}
+
+static void ti_csi2rx_stop_streaming(struct vb2_queue *vq)
+{
+	struct ti_csi2rx_dev *csi = vb2_get_drv_priv(vq);
+	int ret;
+
+	video_device_pipeline_stop(&csi->vdev);
+
+	writel(0, csi->shim + SHIM_CNTL);
+	writel(0, csi->shim + SHIM_DMACNTX);
+
+	ret = v4l2_subdev_call(csi->subdev, video, s_stream, 0);
+	if (ret)
+		dev_err(csi->dev, "Failed to stop subdev stream\n");
+
+	ti_csi2rx_cleanup_buffers(csi, VB2_BUF_STATE_ERROR);
+}
+
+static const struct vb2_ops csi_vb2_qops = {
+	.queue_setup = ti_csi2rx_queue_setup,
+	.buf_prepare = ti_csi2rx_buffer_prepare,
+	.buf_queue = ti_csi2rx_buffer_queue,
+	.start_streaming = ti_csi2rx_start_streaming,
+	.stop_streaming = ti_csi2rx_stop_streaming,
+	.wait_prepare = vb2_ops_wait_prepare,
+	.wait_finish = vb2_ops_wait_finish,
+};
+
+static int ti_csi2rx_init_vb2q(struct ti_csi2rx_dev *csi)
+{
+	struct vb2_queue *q = &csi->vidq;
+	int ret;
+
+	q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	q->io_modes = VB2_MMAP | VB2_DMABUF;
+	q->drv_priv = csi;
+	q->buf_struct_size = sizeof(struct ti_csi2rx_buffer);
+	q->ops = &csi_vb2_qops;
+	q->mem_ops = &vb2_dma_contig_memops;
+	q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+	q->dev = dmaengine_get_dma_device(csi->dma.chan);
+	q->lock = &csi->mutex;
+	q->min_buffers_needed = 1;
+
+	ret = vb2_queue_init(q);
+	if (ret)
+		return ret;
+
+	csi->vdev.queue = q;
+
+	return 0;
+}
+
+static int ti_csi2rx_link_validate(struct media_link *link)
+{
+	struct media_entity *entity = link->sink->entity;
+	struct video_device *vdev = media_entity_to_video_device(entity);
+	struct ti_csi2rx_dev *csi = container_of(vdev, struct ti_csi2rx_dev, vdev);
+	struct v4l2_pix_format *csi_fmt = &csi->v_fmt.fmt.pix;
+	struct v4l2_subdev_format source_fmt = {};
+	const struct ti_csi2rx_fmt *ti_fmt;
+	int ret;
+
+	ret = v4l2_subdev_link_validate_get_format(link->source, 0,
+						   &source_fmt, false);
+	if (ret)
+		return ret;
+
+	if (source_fmt.format.width != csi_fmt->width) {
+		dev_dbg(csi->dev, "Width does not match (source %u, sink %u)\n",
+			source_fmt.format.width, csi_fmt->width);
+		return -EPIPE;
+	}
+
+	if (source_fmt.format.height != csi_fmt->height) {
+		dev_dbg(csi->dev, "Height does not match (source %u, sink %u)\n",
+			source_fmt.format.height, csi_fmt->height);
+		return -EPIPE;
+	}
+
+	if (source_fmt.format.field != csi_fmt->field &&
+	    csi_fmt->field != V4L2_FIELD_NONE) {
+		dev_dbg(csi->dev, "Field does not match (source %u, sink %u)\n",
+			source_fmt.format.field, csi_fmt->field);
+		return -EPIPE;
+	}
+
+	ti_fmt = find_format_by_code(source_fmt.format.code);
+	if (!ti_fmt) {
+		dev_dbg(csi->dev, "Media bus format 0x%x not supported\n",
+			source_fmt.format.code);
+		return -EPIPE;
+	}
+
+	if (ti_fmt->fourcc != csi_fmt->pixelformat) {
+		dev_dbg(csi->dev,
+			"Cannot transform source fmt 0x%x to sink fmt 0x%x\n",
+			ti_fmt->fourcc, csi_fmt->pixelformat);
+		return -EPIPE;
+	}
+
+	return 0;
+}
+
+static const struct media_entity_operations ti_csi2rx_video_entity_ops = {
+	.link_validate = ti_csi2rx_link_validate,
+};
+
+static int ti_csi2rx_init_dma(struct ti_csi2rx_dev *csi)
+{
+	struct dma_slave_config cfg = {
+		.src_addr_width = DMA_SLAVE_BUSWIDTH_16_BYTES,
+	};
+	int ret;
+
+	INIT_LIST_HEAD(&csi->dma.queue);
+	INIT_LIST_HEAD(&csi->dma.submitted);
+	spin_lock_init(&csi->dma.lock);
+
+	csi->dma.state = TI_CSI2RX_DMA_STOPPED;
+
+	csi->dma.chan = dma_request_chan(csi->dev, "rx0");
+	if (IS_ERR(csi->dma.chan))
+		return PTR_ERR(csi->dma.chan);
+
+	ret = dmaengine_slave_config(csi->dma.chan, &cfg);
+	if (ret) {
+		dma_release_channel(csi->dma.chan);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int ti_csi2rx_v4l2_init(struct ti_csi2rx_dev *csi)
+{
+	struct media_device *mdev = &csi->mdev;
+	struct video_device *vdev = &csi->vdev;
+	const struct ti_csi2rx_fmt *fmt;
+	struct v4l2_pix_format *pix_fmt = &csi->v_fmt.fmt.pix;
+	int ret;
+
+	fmt = find_format_by_pix(V4L2_PIX_FMT_UYVY);
+	if (!fmt)
+		return -EINVAL;
+
+	pix_fmt->width = 640;
+	pix_fmt->height = 480;
+	pix_fmt->field = V4L2_FIELD_NONE;
+
+	ti_csi2rx_fill_fmt(fmt, &csi->v_fmt);
+
+	mdev->dev = csi->dev;
+	mdev->hw_revision = 1;
+	strscpy(mdev->model, "TI-CSI2RX", sizeof(mdev->model));
+
+	media_device_init(mdev);
+
+	strscpy(vdev->name, TI_CSI2RX_MODULE_NAME, sizeof(vdev->name));
+	vdev->v4l2_dev = &csi->v4l2_dev;
+	vdev->vfl_dir = VFL_DIR_RX;
+	vdev->fops = &csi_fops;
+	vdev->ioctl_ops = &csi_ioctl_ops;
+	vdev->release = video_device_release_empty;
+	vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING |
+			    V4L2_CAP_IO_MC;
+	vdev->lock = &csi->mutex;
+	video_set_drvdata(vdev, csi);
+
+	csi->pad.flags = MEDIA_PAD_FL_SINK;
+	vdev->entity.ops = &ti_csi2rx_video_entity_ops;
+	ret = media_entity_pads_init(&csi->vdev.entity, 1, &csi->pad);
+	if (ret)
+		return ret;
+
+	csi->v4l2_dev.mdev = mdev;
+
+	ret = v4l2_device_register(csi->dev, &csi->v4l2_dev);
+	if (ret)
+		return ret;
+
+	ret = media_device_register(mdev);
+	if (ret) {
+		v4l2_device_unregister(&csi->v4l2_dev);
+		media_device_cleanup(mdev);
+		return ret;
+	}
+
+	return 0;
+}
+
+static void ti_csi2rx_cleanup_dma(struct ti_csi2rx_dev *csi)
+{
+	dma_release_channel(csi->dma.chan);
+}
+
+static void ti_csi2rx_cleanup_v4l2(struct ti_csi2rx_dev *csi)
+{
+	media_device_unregister(&csi->mdev);
+	v4l2_device_unregister(&csi->v4l2_dev);
+	media_device_cleanup(&csi->mdev);
+}
+
+static void ti_csi2rx_cleanup_subdev(struct ti_csi2rx_dev *csi)
+{
+	v4l2_async_nf_unregister(&csi->notifier);
+	v4l2_async_nf_cleanup(&csi->notifier);
+}
+
+static void ti_csi2rx_cleanup_vb2q(struct ti_csi2rx_dev *csi)
+{
+	vb2_queue_release(&csi->vidq);
+}
+
+static int ti_csi2rx_probe(struct platform_device *pdev)
+{
+	struct ti_csi2rx_dev *csi;
+	struct resource *res;
+	int ret;
+
+	csi = devm_kzalloc(&pdev->dev, sizeof(*csi), GFP_KERNEL);
+	if (!csi)
+		return -ENOMEM;
+
+	csi->dev = &pdev->dev;
+	platform_set_drvdata(pdev, csi);
+
+	mutex_init(&csi->mutex);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	csi->shim = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(csi->shim)) {
+		ret = PTR_ERR(csi->shim);
+		goto err_mutex;
+	}
+
+	ret = ti_csi2rx_init_dma(csi);
+	if (ret)
+		goto err_mutex;
+
+	ret = ti_csi2rx_v4l2_init(csi);
+	if (ret)
+		goto err_dma;
+
+	ret = ti_csi2rx_init_vb2q(csi);
+	if (ret)
+		goto err_v4l2;
+
+	ret = ti_csi2rx_init_subdev(csi);
+	if (ret)
+		goto err_vb2q;
+
+	ret = of_platform_populate(csi->dev->of_node, NULL, NULL, csi->dev);
+	if (ret) {
+		dev_err(csi->dev, "Failed to create children: %d\n", ret);
+		goto err_subdev;
+	}
+
+	return 0;
+
+err_subdev:
+	ti_csi2rx_cleanup_subdev(csi);
+err_vb2q:
+	ti_csi2rx_cleanup_vb2q(csi);
+err_v4l2:
+	ti_csi2rx_cleanup_v4l2(csi);
+err_dma:
+	ti_csi2rx_cleanup_dma(csi);
+err_mutex:
+	mutex_destroy(&csi->mutex);
+	return ret;
+}
+
+static int ti_csi2rx_remove(struct platform_device *pdev)
+{
+	struct ti_csi2rx_dev *csi = platform_get_drvdata(pdev);
+
+	video_unregister_device(&csi->vdev);
+
+	ti_csi2rx_cleanup_vb2q(csi);
+	ti_csi2rx_cleanup_subdev(csi);
+	ti_csi2rx_cleanup_v4l2(csi);
+	ti_csi2rx_cleanup_dma(csi);
+
+	mutex_destroy(&csi->mutex);
+
+	return 0;
+}
+
+static const struct of_device_id ti_csi2rx_of_match[] = {
+	{ .compatible = "ti,j721e-csi2rx-shim", },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, ti_csi2rx_of_match);
+
+static struct platform_driver ti_csi2rx_pdrv = {
+	.probe = ti_csi2rx_probe,
+	.remove = ti_csi2rx_remove,
+	.driver = {
+		.name = TI_CSI2RX_MODULE_NAME,
+		.of_match_table = ti_csi2rx_of_match,
+	},
+};
+
+module_platform_driver(ti_csi2rx_pdrv);
+
+MODULE_DESCRIPTION("TI J721E CSI2 RX Driver");
+MODULE_AUTHOR("Pratyush Yadav <p.yadav@ti.com>");
+MODULE_LICENSE("GPL");

-- 
2.41.0

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v8 16/16] media: ti: Add CSI2RX support for J721E
@ 2023-07-31  8:29   ` Jai Luthra
  0 siblings, 0 replies; 84+ messages in thread
From: Jai Luthra @ 2023-07-31  8:29 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Sakari Ailus, Laurent Pinchart, Tomi Valkeinen
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht, j-luthra

From: Pratyush Yadav <p.yadav@ti.com>

TI's J721E uses the Cadence CSI2RX and DPHY peripherals to facilitate
capture over a CSI-2 bus.

The Cadence CSI2RX IP acts as a bridge between the TI specific parts and
the CSI-2 protocol parts. TI then has a wrapper on top of this bridge
called the SHIM layer. It takes in data from stream 0, repacks it, and
sends it to memory over PSI-L DMA.

This driver acts as the "front end" to V4L2 client applications. It
implements the required ioctls and buffer operations, passes the
necessary calls on to the bridge, programs the SHIM layer, and performs
DMA via the dmaengine API to finally return the data to a buffer
supplied by the application.

Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
Co-authored-by: Vaishnav Achath <vaishnav.a@ti.com>
Signed-off-by: Vaishnav Achath <vaishnav.a@ti.com>
Co-authored-by: Jai Luthra <j-luthra@ti.com>
Signed-off-by: Jai Luthra <j-luthra@ti.com>
---
v7->v8:
- Move after dt-bindings to keep the series bisectable
- Rename compatible to "ti,j721e-csi2rx-shim" to distinguish from the
  SoC-specific CSI2RX bridge compatible
- Make myself the Maintainer
- Support RAW8 and RAW10 formats, and setting the pixel-unwrap size on
  SHIM (RAW10 is stored in 16-bit containers, while RAW8 in 8-bit containers)
- Fix enum_fmt_vid_cap() to respect CAP_IO_MC and only list pixelformats
  matching the mbus formats set on the subdev.
- Fix enum_framesizes() to stop enumerating more than a single framesize
  (reject non-zero fsize->index)
- Simplify notifier bound fucntion to use v4l2_create_fwnode_links_to_pad()
  and inline the video_register() method
- Add support for draining the DMA with an extra buffer, to get rid of
  stale data in the pipeline on stream stop (or when frames start
  getting dropped due to load)
- Queue all available buffers to DMAEngine in the callback, also use a
  separate "submitted" queue to track all buffers submitted to DMA
- Use video_device_pipeline_start() instead of media_pipeline_start()
- Drop support for VB_READ
- Print issues in link validation as DEBUG instead of ERROR
- s/async_subdev/async_connection

 MAINTAINERS                                        |    7 +
 drivers/media/platform/ti/Kconfig                  |   12 +
 drivers/media/platform/ti/Makefile                 |    1 +
 drivers/media/platform/ti/j721e-csi2rx/Makefile    |    2 +
 .../media/platform/ti/j721e-csi2rx/j721e-csi2rx.c  | 1127 ++++++++++++++++++++
 5 files changed, 1149 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index d7b867c57920..1c2d75c30ce7 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -21445,6 +21445,13 @@ F:	Documentation/devicetree/bindings/media/i2c/ti,ds90*
 F:	drivers/media/i2c/ds90*
 F:	include/media/i2c/ds90*
 
+TI J721E CSI2RX DRIVER
+M:	Jai Luthra <j-luthra@ti.com>
+L:	linux-media@vger.kernel.org
+S:	Maintained
+F:	Documentation/devicetree/bindings/media/ti,j721e-csi2rx.yaml
+F:	drivers/media/platform/ti/j721e-csi2rx/
+
 TI KEYSTONE MULTICORE NAVIGATOR DRIVERS
 M:	Nishanth Menon <nm@ti.com>
 M:	Santosh Shilimkar <ssantosh@kernel.org>
diff --git a/drivers/media/platform/ti/Kconfig b/drivers/media/platform/ti/Kconfig
index e1ab56c3be1f..42c908f6e1ae 100644
--- a/drivers/media/platform/ti/Kconfig
+++ b/drivers/media/platform/ti/Kconfig
@@ -63,6 +63,18 @@ config VIDEO_TI_VPE_DEBUG
 	help
 	  Enable debug messages on VPE driver.
 
+config VIDEO_TI_J721E_CSI2RX
+	tristate "TI J721E CSI2RX wrapper layer driver"
+	depends on VIDEO_DEV && VIDEO_V4L2_SUBDEV_API
+	depends on MEDIA_SUPPORT && MEDIA_CONTROLLER
+	depends on PHY_CADENCE_DPHY_RX && VIDEO_CADENCE_CSI2RX
+	depends on ARCH_K3 || COMPILE_TEST
+	select VIDEOBUF2_DMA_CONTIG
+	select V4L2_FWNODE
+	help
+	  Support for TI CSI2RX wrapper layer. This just enables the wrapper driver.
+	  The Cadence CSI2RX bridge driver needs to be enabled separately.
+
 source "drivers/media/platform/ti/am437x/Kconfig"
 source "drivers/media/platform/ti/davinci/Kconfig"
 source "drivers/media/platform/ti/omap/Kconfig"
diff --git a/drivers/media/platform/ti/Makefile b/drivers/media/platform/ti/Makefile
index 98c5fe5c40d6..8a2f74c9380e 100644
--- a/drivers/media/platform/ti/Makefile
+++ b/drivers/media/platform/ti/Makefile
@@ -3,5 +3,6 @@ obj-y += am437x/
 obj-y += cal/
 obj-y += vpe/
 obj-y += davinci/
+obj-y += j721e-csi2rx/
 obj-y += omap/
 obj-y += omap3isp/
diff --git a/drivers/media/platform/ti/j721e-csi2rx/Makefile b/drivers/media/platform/ti/j721e-csi2rx/Makefile
new file mode 100644
index 000000000000..377afc1d6280
--- /dev/null
+++ b/drivers/media/platform/ti/j721e-csi2rx/Makefile
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0
+obj-$(CONFIG_VIDEO_TI_J721E_CSI2RX) += j721e-csi2rx.o
diff --git a/drivers/media/platform/ti/j721e-csi2rx/j721e-csi2rx.c b/drivers/media/platform/ti/j721e-csi2rx/j721e-csi2rx.c
new file mode 100644
index 000000000000..29f1879cfc25
--- /dev/null
+++ b/drivers/media/platform/ti/j721e-csi2rx/j721e-csi2rx.c
@@ -0,0 +1,1127 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * TI CSI2RX Shim Wrapper Driver
+ *
+ * Copyright (C) 2021 Texas Instruments Incorporated - https://www.ti.com/
+ *
+ * Author: Pratyush Yadav <p.yadav@ti.com>
+ */
+
+#include <linux/bitfield.h>
+#include <linux/dmaengine.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+
+#include <media/mipi-csi2.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-mc.h>
+#include <media/videobuf2-dma-contig.h>
+
+#define TI_CSI2RX_MODULE_NAME		"j721e-csi2rx"
+
+#define SHIM_CNTL			0x10
+#define SHIM_CNTL_PIX_RST		BIT(0)
+
+#define SHIM_DMACNTX			0x20
+#define SHIM_DMACNTX_EN			BIT(31)
+#define SHIM_DMACNTX_YUV422		GENMASK(27, 26)
+#define SHIM_DMACNTX_SIZE		GENMASK(21, 20)
+#define SHIM_DMACNTX_FMT		GENMASK(5, 0)
+#define SHIM_DMACNTX_UYVY		0
+#define SHIM_DMACNTX_VYUY		1
+#define SHIM_DMACNTX_YUYV		2
+#define SHIM_DMACNTX_YVYU		3
+#define SHIM_DMACNTX_SIZE_8		0
+#define SHIM_DMACNTX_SIZE_16		1
+#define SHIM_DMACNTX_SIZE_32		2
+
+#define SHIM_PSI_CFG0			0x24
+#define SHIM_PSI_CFG0_SRC_TAG		GENMASK(15, 0)
+#define SHIM_PSI_CFG0_DST_TAG		GENMASK(31, 16)
+
+#define PSIL_WORD_SIZE_BYTES		16
+/*
+ * There are no hard limits on the width or height. The DMA engine can handle
+ * all sizes. The max width and height are arbitrary numbers for this driver.
+ * Use 16K * 16K as the arbitrary limit. It is large enough that it is unlikely
+ * the limit will be hit in practice.
+ */
+#define MAX_WIDTH_BYTES			SZ_16K
+#define MAX_HEIGHT_LINES		SZ_16K
+
+#define DRAIN_TIMEOUT_MS		50
+
+struct ti_csi2rx_fmt {
+	u32				fourcc;	/* Four character code. */
+	u32				code;	/* Mbus code. */
+	u32				csi_dt;	/* CSI Data type. */
+	u8				bpp;	/* Bits per pixel. */
+	u8				size;	/* Data size shift when unpacking. */
+};
+
+struct ti_csi2rx_buffer {
+	/* Common v4l2 buffer. Must be first. */
+	struct vb2_v4l2_buffer		vb;
+	struct list_head		list;
+	struct ti_csi2rx_dev		*csi;
+};
+
+enum ti_csi2rx_dma_state {
+	TI_CSI2RX_DMA_STOPPED,	/* Streaming not started yet. */
+	TI_CSI2RX_DMA_IDLE,	/* Streaming but no pending DMA operation. */
+	TI_CSI2RX_DMA_ACTIVE,	/* Streaming and pending DMA operation. */
+};
+
+struct ti_csi2rx_dma {
+	/* Protects all fields in this struct. */
+	spinlock_t			lock;
+	struct dma_chan			*chan;
+	/* Buffers queued to the driver, waiting to be processed by DMA. */
+	struct list_head		queue;
+	enum ti_csi2rx_dma_state	state;
+	/*
+	 * Queue of buffers submitted to DMA engine.
+	 */
+	struct list_head		submitted;
+};
+
+struct ti_csi2rx_dev {
+	struct device			*dev;
+	void __iomem			*shim;
+	struct v4l2_device		v4l2_dev;
+	struct video_device		vdev;
+	struct media_device		mdev;
+	struct media_pipeline		pipe;
+	struct media_pad		pad;
+	struct v4l2_async_notifier	notifier;
+	struct v4l2_subdev		*subdev;
+	struct vb2_queue		vidq;
+	struct mutex			mutex; /* To serialize ioctls. */
+	struct v4l2_format		v_fmt;
+	struct ti_csi2rx_dma		dma;
+	u32				sequence;
+};
+
+static const struct ti_csi2rx_fmt formats[] = {
+	{
+		.fourcc			= V4L2_PIX_FMT_YUYV,
+		.code			= MEDIA_BUS_FMT_YUYV8_1X16,
+		.csi_dt			= MIPI_CSI2_DT_YUV422_8B,
+		.bpp			= 16,
+		.size			= SHIM_DMACNTX_SIZE_8,
+	}, {
+		.fourcc			= V4L2_PIX_FMT_UYVY,
+		.code			= MEDIA_BUS_FMT_UYVY8_1X16,
+		.csi_dt			= MIPI_CSI2_DT_YUV422_8B,
+		.bpp			= 16,
+		.size			= SHIM_DMACNTX_SIZE_8,
+	}, {
+		.fourcc			= V4L2_PIX_FMT_YVYU,
+		.code			= MEDIA_BUS_FMT_YVYU8_1X16,
+		.csi_dt			= MIPI_CSI2_DT_YUV422_8B,
+		.bpp			= 16,
+		.size			= SHIM_DMACNTX_SIZE_8,
+	}, {
+		.fourcc			= V4L2_PIX_FMT_VYUY,
+		.code			= MEDIA_BUS_FMT_VYUY8_1X16,
+		.csi_dt			= MIPI_CSI2_DT_YUV422_8B,
+		.bpp			= 16,
+		.size			= SHIM_DMACNTX_SIZE_8,
+	}, {
+		.fourcc			= V4L2_PIX_FMT_SBGGR8,
+		.code			= MEDIA_BUS_FMT_SBGGR8_1X8,
+		.csi_dt			= MIPI_CSI2_DT_RAW8,
+		.bpp			= 8,
+		.size			= SHIM_DMACNTX_SIZE_8,
+	}, {
+		.fourcc			= V4L2_PIX_FMT_SGBRG8,
+		.code			= MEDIA_BUS_FMT_SGBRG8_1X8,
+		.csi_dt			= MIPI_CSI2_DT_RAW8,
+		.bpp			= 8,
+		.size			= SHIM_DMACNTX_SIZE_8,
+	}, {
+		.fourcc			= V4L2_PIX_FMT_SGRBG8,
+		.code			= MEDIA_BUS_FMT_SGRBG8_1X8,
+		.csi_dt			= MIPI_CSI2_DT_RAW8,
+		.bpp			= 8,
+		.size			= SHIM_DMACNTX_SIZE_8,
+	}, {
+		.fourcc			= V4L2_PIX_FMT_SRGGB8,
+		.code			= MEDIA_BUS_FMT_SRGGB8_1X8,
+		.csi_dt			= MIPI_CSI2_DT_RAW8,
+		.bpp			= 8,
+		.size			= SHIM_DMACNTX_SIZE_8,
+	}, {
+		.fourcc			= V4L2_PIX_FMT_SBGGR10,
+		.code			= MEDIA_BUS_FMT_SBGGR10_1X10,
+		.csi_dt			= MIPI_CSI2_DT_RAW10,
+		.bpp			= 16,
+		.size			= SHIM_DMACNTX_SIZE_16,
+	}, {
+		.fourcc			= V4L2_PIX_FMT_SGBRG10,
+		.code			= MEDIA_BUS_FMT_SGBRG10_1X10,
+		.csi_dt			= MIPI_CSI2_DT_RAW10,
+		.bpp			= 16,
+		.size			= SHIM_DMACNTX_SIZE_16,
+	}, {
+		.fourcc			= V4L2_PIX_FMT_SGRBG10,
+		.code			= MEDIA_BUS_FMT_SGRBG10_1X10,
+		.csi_dt			= MIPI_CSI2_DT_RAW10,
+		.bpp			= 16,
+		.size			= SHIM_DMACNTX_SIZE_16,
+	}, {
+		.fourcc			= V4L2_PIX_FMT_SRGGB10,
+		.code			= MEDIA_BUS_FMT_SRGGB10_1X10,
+		.csi_dt			= MIPI_CSI2_DT_RAW10,
+		.bpp			= 16,
+		.size			= SHIM_DMACNTX_SIZE_16,
+	},
+
+	/* More formats can be supported but they are not listed for now. */
+};
+
+static const unsigned int num_formats = ARRAY_SIZE(formats);
+
+/* Forward declaration needed by ti_csi2rx_dma_callback. */
+static int ti_csi2rx_start_dma(struct ti_csi2rx_dev *csi,
+			       struct ti_csi2rx_buffer *buf);
+
+static const struct ti_csi2rx_fmt *find_format_by_pix(u32 pixelformat)
+{
+	unsigned int i;
+
+	for (i = 0; i < num_formats; i++) {
+		if (formats[i].fourcc == pixelformat)
+			return &formats[i];
+	}
+
+	return NULL;
+}
+
+static const struct ti_csi2rx_fmt *find_format_by_code(u32 code)
+{
+	unsigned int i;
+
+	for (i = 0; i < num_formats; i++) {
+		if (formats[i].code == code)
+			return &formats[i];
+	}
+
+	return NULL;
+}
+
+static void ti_csi2rx_fill_fmt(const struct ti_csi2rx_fmt *csi_fmt,
+			       struct v4l2_format *v4l2_fmt)
+{
+	struct v4l2_pix_format *pix = &v4l2_fmt->fmt.pix;
+	unsigned int pixels_in_word;
+	u8 bpp = csi_fmt->bpp;
+	u32 bpl;
+
+	pixels_in_word = PSIL_WORD_SIZE_BYTES * 8 / bpp;
+
+	pix->width = clamp_t(unsigned int, pix->width,
+			     pixels_in_word,
+			     MAX_WIDTH_BYTES * 8 / bpp);
+	pix->width = rounddown(pix->width, pixels_in_word);
+
+	pix->height = clamp_t(unsigned int, pix->height, 1, MAX_HEIGHT_LINES);
+
+	v4l2_fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	pix->pixelformat = csi_fmt->fourcc;
+	pix->colorspace = V4L2_COLORSPACE_SRGB;
+	pix->sizeimage = pix->height * pix->width * (bpp / 8);
+
+	bpl = (pix->width * ALIGN(bpp, 8)) >> 3;
+	pix->bytesperline = ALIGN(bpl, 16);
+}
+
+static int ti_csi2rx_querycap(struct file *file, void *priv,
+			      struct v4l2_capability *cap)
+{
+	strscpy(cap->driver, TI_CSI2RX_MODULE_NAME, sizeof(cap->driver));
+	strscpy(cap->card, TI_CSI2RX_MODULE_NAME, sizeof(cap->card));
+
+	return 0;
+}
+
+static int ti_csi2rx_enum_fmt_vid_cap(struct file *file, void *priv,
+				      struct v4l2_fmtdesc *f)
+{
+	const struct ti_csi2rx_fmt *fmt = NULL;
+
+	if (f->mbus_code) {
+		if (f->index > 0)
+			return -EINVAL;
+
+		fmt = find_format_by_code(f->mbus_code);
+	} else {
+		if (f->index >= num_formats)
+			return -EINVAL;
+
+		fmt = &formats[f->index];
+	}
+
+	if (!fmt)
+		return -EINVAL;
+
+	f->pixelformat = fmt->fourcc;
+	memset(f->reserved, 0, sizeof(f->reserved));
+	f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+	return 0;
+}
+
+static int ti_csi2rx_g_fmt_vid_cap(struct file *file, void *prov,
+				   struct v4l2_format *f)
+{
+	struct ti_csi2rx_dev *csi = video_drvdata(file);
+
+	*f = csi->v_fmt;
+
+	return 0;
+}
+
+static int ti_csi2rx_try_fmt_vid_cap(struct file *file, void *priv,
+				     struct v4l2_format *f)
+{
+	const struct ti_csi2rx_fmt *fmt;
+
+	/*
+	 * Default to the first format if the requested pixel format code isn't
+	 * supported.
+	 */
+	fmt = find_format_by_pix(f->fmt.pix.pixelformat);
+	if (!fmt)
+		fmt = &formats[0];
+
+	if (f->fmt.pix.field == V4L2_FIELD_ANY)
+		f->fmt.pix.field = V4L2_FIELD_NONE;
+
+	if (f->fmt.pix.field != V4L2_FIELD_NONE)
+		/* Interlaced formats are not supported. */
+		f->fmt.pix.field = V4L2_FIELD_NONE;
+
+	ti_csi2rx_fill_fmt(fmt, f);
+
+	return 0;
+}
+
+static int ti_csi2rx_s_fmt_vid_cap(struct file *file, void *priv,
+				   struct v4l2_format *f)
+{
+	struct ti_csi2rx_dev *csi = video_drvdata(file);
+	struct vb2_queue *q = &csi->vidq;
+	int ret;
+
+	if (vb2_is_busy(q))
+		return -EBUSY;
+
+	ret = ti_csi2rx_try_fmt_vid_cap(file, priv, f);
+	if (ret < 0)
+		return ret;
+
+	csi->v_fmt = *f;
+
+	return 0;
+}
+
+static int ti_csi2rx_enum_framesizes(struct file *file, void *fh,
+				     struct v4l2_frmsizeenum *fsize)
+{
+	const struct ti_csi2rx_fmt *fmt;
+	unsigned int pixels_in_word;
+	u8 bpp;
+
+	fmt = find_format_by_pix(fsize->pixel_format);
+	if (!fmt || fsize->index != 0)
+		return -EINVAL;
+
+	bpp = ALIGN(fmt->bpp, 8);
+
+	/*
+	 * Number of pixels in one PSI-L word. The transfer happens in multiples
+	 * of PSI-L word sizes.
+	 */
+	pixels_in_word = PSIL_WORD_SIZE_BYTES * 8 / bpp;
+
+	fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
+	fsize->stepwise.min_width = pixels_in_word;
+	fsize->stepwise.max_width = rounddown(MAX_WIDTH_BYTES * 8 / bpp,
+					      pixels_in_word);
+	fsize->stepwise.step_width = pixels_in_word;
+	fsize->stepwise.min_height = 1;
+	fsize->stepwise.max_height = MAX_HEIGHT_LINES;
+	fsize->stepwise.step_height = 1;
+
+	return 0;
+}
+
+static const struct v4l2_ioctl_ops csi_ioctl_ops = {
+	.vidioc_querycap      = ti_csi2rx_querycap,
+	.vidioc_enum_fmt_vid_cap = ti_csi2rx_enum_fmt_vid_cap,
+	.vidioc_try_fmt_vid_cap = ti_csi2rx_try_fmt_vid_cap,
+	.vidioc_g_fmt_vid_cap = ti_csi2rx_g_fmt_vid_cap,
+	.vidioc_s_fmt_vid_cap = ti_csi2rx_s_fmt_vid_cap,
+	.vidioc_enum_framesizes = ti_csi2rx_enum_framesizes,
+	.vidioc_reqbufs       = vb2_ioctl_reqbufs,
+	.vidioc_create_bufs   = vb2_ioctl_create_bufs,
+	.vidioc_prepare_buf   = vb2_ioctl_prepare_buf,
+	.vidioc_querybuf      = vb2_ioctl_querybuf,
+	.vidioc_qbuf          = vb2_ioctl_qbuf,
+	.vidioc_dqbuf         = vb2_ioctl_dqbuf,
+	.vidioc_expbuf        = vb2_ioctl_expbuf,
+	.vidioc_streamon      = vb2_ioctl_streamon,
+	.vidioc_streamoff     = vb2_ioctl_streamoff,
+};
+
+static const struct v4l2_file_operations csi_fops = {
+	.owner = THIS_MODULE,
+	.open = v4l2_fh_open,
+	.release = vb2_fop_release,
+	.read = vb2_fop_read,
+	.poll = vb2_fop_poll,
+	.unlocked_ioctl = video_ioctl2,
+	.mmap = vb2_fop_mmap,
+};
+
+static int csi_async_notifier_bound(struct v4l2_async_notifier *notifier,
+				    struct v4l2_subdev *subdev,
+				    struct v4l2_async_connection *asc)
+{
+	struct ti_csi2rx_dev *csi = dev_get_drvdata(notifier->v4l2_dev->dev);
+
+	csi->subdev = subdev;
+
+	return 0;
+}
+
+static int csi_async_notifier_complete(struct v4l2_async_notifier *notifier)
+{
+	struct ti_csi2rx_dev *csi = dev_get_drvdata(notifier->v4l2_dev->dev);
+	struct video_device *vdev = &csi->vdev;
+	int ret;
+
+	ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1);
+	if (ret)
+		return ret;
+
+	ret = v4l2_create_fwnode_links_to_pad(csi->subdev, &csi->pad,
+					      MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED);
+
+	if (ret) {
+		video_unregister_device(vdev);
+		return ret;
+	}
+
+	return v4l2_device_register_subdev_nodes(&csi->v4l2_dev);
+}
+
+static const struct v4l2_async_notifier_operations csi_async_notifier_ops = {
+	.bound = csi_async_notifier_bound,
+	.complete = csi_async_notifier_complete,
+};
+
+static int ti_csi2rx_init_subdev(struct ti_csi2rx_dev *csi)
+{
+	struct fwnode_handle *fwnode;
+	struct v4l2_async_connection *asc;
+	struct device_node *node;
+	int ret;
+
+	node = of_get_child_by_name(csi->dev->of_node, "csi-bridge");
+	if (!node)
+		return -EINVAL;
+
+	fwnode = of_fwnode_handle(node);
+	if (!fwnode) {
+		of_node_put(node);
+		return -EINVAL;
+	}
+
+	v4l2_async_nf_init(&csi->notifier, &csi->v4l2_dev);
+	csi->notifier.ops = &csi_async_notifier_ops;
+
+	asc = v4l2_async_nf_add_fwnode(&csi->notifier, fwnode,
+				       struct v4l2_async_connection);
+	of_node_put(node);
+	if (IS_ERR(asc)) {
+		v4l2_async_nf_cleanup(&csi->notifier);
+		return PTR_ERR(asc);
+	}
+
+	ret = v4l2_async_nf_register(&csi->notifier);
+	if (ret) {
+		v4l2_async_nf_cleanup(&csi->notifier);
+		return ret;
+	}
+
+	return 0;
+}
+
+static void ti_csi2rx_setup_shim(struct ti_csi2rx_dev *csi)
+{
+	const struct ti_csi2rx_fmt *fmt;
+	unsigned int reg;
+
+	fmt = find_format_by_pix(csi->v_fmt.fmt.pix.pixelformat);
+	if (!fmt) {
+		dev_err(csi->dev, "Unknown format\n");
+		return;
+	}
+
+	/* De-assert the pixel interface reset. */
+	reg = SHIM_CNTL_PIX_RST;
+	writel(reg, csi->shim + SHIM_CNTL);
+
+	reg = SHIM_DMACNTX_EN;
+	reg |= FIELD_PREP(SHIM_DMACNTX_FMT, fmt->csi_dt);
+
+	/*
+	 * Using the values from the documentation gives incorrect ordering for
+	 * the luma and chroma components. In practice, the "reverse" format
+	 * gives the correct image. So for example, if the image is in UYVY, the
+	 * reverse would be YVYU.
+	 */
+	switch (fmt->fourcc) {
+	case V4L2_PIX_FMT_UYVY:
+		reg |= FIELD_PREP(SHIM_DMACNTX_YUV422,
+					SHIM_DMACNTX_YVYU);
+		break;
+	case V4L2_PIX_FMT_VYUY:
+		reg |= FIELD_PREP(SHIM_DMACNTX_YUV422,
+					SHIM_DMACNTX_YUYV);
+		break;
+	case V4L2_PIX_FMT_YUYV:
+		reg |= FIELD_PREP(SHIM_DMACNTX_YUV422,
+					SHIM_DMACNTX_VYUY);
+		break;
+	case V4L2_PIX_FMT_YVYU:
+		reg |= FIELD_PREP(SHIM_DMACNTX_YUV422,
+					SHIM_DMACNTX_UYVY);
+		break;
+	default:
+		/* Ignore if not YUV 4:2:2 */
+		break;
+	}
+
+	reg |= FIELD_PREP(SHIM_DMACNTX_SIZE, fmt->size);
+
+	writel(reg, csi->shim + SHIM_DMACNTX);
+
+	reg = FIELD_PREP(SHIM_PSI_CFG0_SRC_TAG, 0) |
+	      FIELD_PREP(SHIM_PSI_CFG0_DST_TAG, 0);
+	writel(reg, csi->shim + SHIM_PSI_CFG0);
+}
+
+static void ti_csi2rx_drain_callback(void *param)
+{
+	struct completion *drain_complete = param;
+
+	complete(drain_complete);
+}
+
+static int ti_csi2rx_drain_dma(struct ti_csi2rx_dev *csi)
+{
+	struct dma_async_tx_descriptor *desc;
+	struct device *dev = csi->dma.chan->device->dev;
+	struct completion drain_complete;
+	void *buf;
+	size_t len = csi->v_fmt.fmt.pix.sizeimage;
+	dma_addr_t addr;
+	dma_cookie_t cookie;
+	int ret;
+
+	init_completion(&drain_complete);
+
+	buf = dma_alloc_coherent(dev, len, &addr, GFP_KERNEL | GFP_ATOMIC);
+	if (!buf)
+		return -ENOMEM;
+
+	desc = dmaengine_prep_slave_single(csi->dma.chan, addr, len,
+					   DMA_DEV_TO_MEM,
+					   DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+	if (!desc) {
+		ret = -EIO;
+		goto out;
+	}
+
+	desc->callback = ti_csi2rx_drain_callback;
+	desc->callback_param = &drain_complete;
+
+	cookie = dmaengine_submit(desc);
+	ret = dma_submit_error(cookie);
+	if (ret)
+		goto out;
+
+	dma_async_issue_pending(csi->dma.chan);
+
+	if (!wait_for_completion_timeout(&drain_complete,
+					 msecs_to_jiffies(DRAIN_TIMEOUT_MS))) {
+		dmaengine_terminate_sync(csi->dma.chan);
+		ret = -ETIMEDOUT;
+		goto out;
+	}
+out:
+	dma_free_coherent(dev, len, buf, addr);
+	return ret;
+}
+
+static void ti_csi2rx_dma_callback(void *param)
+{
+	struct ti_csi2rx_buffer *buf = param;
+	struct ti_csi2rx_dev *csi = buf->csi;
+	struct ti_csi2rx_dma *dma = &csi->dma;
+	unsigned long flags;
+
+	/*
+	 * TODO: Derive the sequence number from the CSI2RX frame number
+	 * hardware monitor registers.
+	 */
+	buf->vb.vb2_buf.timestamp = ktime_get_ns();
+	buf->vb.sequence = csi->sequence++;
+
+	spin_lock_irqsave(&dma->lock, flags);
+
+	WARN_ON(!list_is_first(&buf->list, &dma->submitted));
+	vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
+	list_del(&buf->list);
+
+	/* If there are more buffers to process then start their transfer. */
+	while (!list_empty(&dma->queue)) {
+		buf = list_entry(dma->queue.next, struct ti_csi2rx_buffer, list);
+
+		if (ti_csi2rx_start_dma(csi, buf)) {
+			dev_err(csi->dev, "Failed to queue the next buffer for DMA\n");
+			vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
+		} else {
+			list_move_tail(&buf->list, &dma->submitted);
+		}
+	}
+
+	if (list_empty(&dma->submitted))
+		dma->state = TI_CSI2RX_DMA_IDLE;
+
+	spin_unlock_irqrestore(&dma->lock, flags);
+}
+
+static int ti_csi2rx_start_dma(struct ti_csi2rx_dev *csi,
+			       struct ti_csi2rx_buffer *buf)
+{
+	unsigned long addr;
+	struct dma_async_tx_descriptor *desc;
+	size_t len = csi->v_fmt.fmt.pix.sizeimage;
+	dma_cookie_t cookie;
+	int ret = 0;
+
+	addr = vb2_dma_contig_plane_dma_addr(&buf->vb.vb2_buf, 0);
+	desc = dmaengine_prep_slave_single(csi->dma.chan, addr, len,
+					   DMA_DEV_TO_MEM,
+					   DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+	if (!desc)
+		return -EIO;
+
+	desc->callback = ti_csi2rx_dma_callback;
+	desc->callback_param = buf;
+
+	cookie = dmaengine_submit(desc);
+	ret = dma_submit_error(cookie);
+	if (ret)
+		return ret;
+
+	dma_async_issue_pending(csi->dma.chan);
+
+	return 0;
+}
+
+static void ti_csi2rx_cleanup_buffers(struct ti_csi2rx_dev *csi,
+				      enum vb2_buffer_state buf_state)
+{
+	struct ti_csi2rx_dma *dma = &csi->dma;
+	struct ti_csi2rx_buffer *buf, *tmp;
+	enum ti_csi2rx_dma_state state;
+	unsigned long flags;
+	int ret;
+
+	spin_lock_irqsave(&dma->lock, flags);
+	state = csi->dma.state;
+	dma->state = TI_CSI2RX_DMA_STOPPED;
+	spin_unlock_irqrestore(&dma->lock, flags);
+
+	if (state != TI_CSI2RX_DMA_STOPPED) {
+		ret = ti_csi2rx_drain_dma(csi);
+		if (ret)
+			dev_dbg(csi->dev,
+				"Failed to drain DMA. Next frame might be bogus\n");
+	}
+	ret = dmaengine_terminate_sync(csi->dma.chan);
+	if (ret)
+		dev_err(csi->dev, "Failed to stop DMA: %d\n", ret);
+
+	spin_lock_irqsave(&dma->lock, flags);
+	list_for_each_entry_safe(buf, tmp, &csi->dma.queue, list) {
+		list_del(&buf->list);
+		vb2_buffer_done(&buf->vb.vb2_buf, buf_state);
+	}
+	list_for_each_entry_safe(buf, tmp, &csi->dma.submitted, list) {
+		list_del(&buf->list);
+		vb2_buffer_done(&buf->vb.vb2_buf, buf_state);
+	}
+	spin_unlock_irqrestore(&dma->lock, flags);
+}
+
+static int ti_csi2rx_queue_setup(struct vb2_queue *q, unsigned int *nbuffers,
+				 unsigned int *nplanes, unsigned int sizes[],
+				 struct device *alloc_devs[])
+{
+	struct ti_csi2rx_dev *csi = vb2_get_drv_priv(q);
+	unsigned int size = csi->v_fmt.fmt.pix.sizeimage;
+
+	if (*nplanes) {
+		if (sizes[0] < size)
+			return -EINVAL;
+		size = sizes[0];
+	}
+
+	*nplanes = 1;
+	sizes[0] = size;
+
+	return 0;
+}
+
+static int ti_csi2rx_buffer_prepare(struct vb2_buffer *vb)
+{
+	struct ti_csi2rx_dev *csi = vb2_get_drv_priv(vb->vb2_queue);
+	unsigned long size = csi->v_fmt.fmt.pix.sizeimage;
+
+	if (vb2_plane_size(vb, 0) < size) {
+		dev_err(csi->dev, "Data will not fit into plane\n");
+		return -EINVAL;
+	}
+
+	vb2_set_plane_payload(vb, 0, size);
+	return 0;
+}
+
+static void ti_csi2rx_buffer_queue(struct vb2_buffer *vb)
+{
+	struct ti_csi2rx_dev *csi = vb2_get_drv_priv(vb->vb2_queue);
+	struct ti_csi2rx_buffer *buf;
+	struct ti_csi2rx_dma *dma = &csi->dma;
+	bool restart_dma = false;
+	unsigned long flags = 0;
+	int ret;
+
+	buf = container_of(vb, struct ti_csi2rx_buffer, vb.vb2_buf);
+	buf->csi = csi;
+
+	spin_lock_irqsave(&dma->lock, flags);
+	/*
+	 * Usually the DMA callback takes care of queueing the pending buffers.
+	 * But if DMA has stalled due to lack of buffers, restart it now.
+	 */
+	if (dma->state == TI_CSI2RX_DMA_IDLE) {
+		/*
+		 * Do not restart DMA with the lock held because
+		 * ti_csi2rx_drain_dma() might block when allocating a buffer.
+		 * There won't be a race on queueing DMA anyway since the
+		 * callback is not being fired.
+		 */
+		restart_dma = true;
+		dma->state = TI_CSI2RX_DMA_ACTIVE;
+	} else {
+		list_add_tail(&buf->list, &dma->queue);
+	}
+	spin_unlock_irqrestore(&dma->lock, flags);
+
+	if (restart_dma) {
+		/*
+		 * Once frames start dropping, some data gets stuck in the DMA
+		 * pipeline somewhere. So the first DMA transfer after frame
+		 * drops gives a partial frame. This is obviously not useful to
+		 * the application and will only confuse it. Issue a DMA
+		 * transaction to drain that up.
+		 */
+		ret = ti_csi2rx_drain_dma(csi);
+		if (ret)
+			dev_warn(csi->dev,
+				 "Failed to drain DMA. Next frame might be bogus\n");
+
+		ret = ti_csi2rx_start_dma(csi, buf);
+		if (ret) {
+			dev_err(csi->dev, "Failed to start DMA: %d\n", ret);
+			spin_lock_irqsave(&dma->lock, flags);
+			vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
+			dma->state = TI_CSI2RX_DMA_IDLE;
+			spin_unlock_irqrestore(&dma->lock, flags);
+		} else {
+			spin_lock_irqsave(&dma->lock, flags);
+			list_add_tail(&buf->list, &dma->submitted);
+			spin_unlock_irqrestore(&dma->lock, flags);
+		}
+	}
+}
+
+static int ti_csi2rx_start_streaming(struct vb2_queue *vq, unsigned int count)
+{
+	struct ti_csi2rx_dev *csi = vb2_get_drv_priv(vq);
+	struct ti_csi2rx_dma *dma = &csi->dma;
+	struct ti_csi2rx_buffer *buf;
+	unsigned long flags;
+	int ret = 0;
+
+	spin_lock_irqsave(&dma->lock, flags);
+	if (list_empty(&dma->queue))
+		ret = -EIO;
+	spin_unlock_irqrestore(&dma->lock, flags);
+	if (ret)
+		return ret;
+
+	ret = video_device_pipeline_start(&csi->vdev, &csi->pipe);
+	if (ret)
+		goto err;
+
+	ti_csi2rx_setup_shim(csi);
+
+	csi->sequence = 0;
+
+	spin_lock_irqsave(&dma->lock, flags);
+	buf = list_entry(dma->queue.next, struct ti_csi2rx_buffer, list);
+
+	ret = ti_csi2rx_start_dma(csi, buf);
+	if (ret) {
+		dev_err(csi->dev, "Failed to start DMA: %d\n", ret);
+		spin_unlock_irqrestore(&dma->lock, flags);
+		goto err_pipeline;
+	}
+
+	list_move_tail(&buf->list, &dma->submitted);
+	dma->state = TI_CSI2RX_DMA_ACTIVE;
+	spin_unlock_irqrestore(&dma->lock, flags);
+
+	ret = v4l2_subdev_call(csi->subdev, video, s_stream, 1);
+	if (ret)
+		goto err_dma;
+
+	return 0;
+
+err_dma:
+	dmaengine_terminate_sync(csi->dma.chan);
+	writel(0, csi->shim + SHIM_DMACNTX);
+err_pipeline:
+	video_device_pipeline_stop(&csi->vdev);
+err:
+	ti_csi2rx_cleanup_buffers(csi, VB2_BUF_STATE_QUEUED);
+	return ret;
+}
+
+static void ti_csi2rx_stop_streaming(struct vb2_queue *vq)
+{
+	struct ti_csi2rx_dev *csi = vb2_get_drv_priv(vq);
+	int ret;
+
+	video_device_pipeline_stop(&csi->vdev);
+
+	writel(0, csi->shim + SHIM_CNTL);
+	writel(0, csi->shim + SHIM_DMACNTX);
+
+	ret = v4l2_subdev_call(csi->subdev, video, s_stream, 0);
+	if (ret)
+		dev_err(csi->dev, "Failed to stop subdev stream\n");
+
+	ti_csi2rx_cleanup_buffers(csi, VB2_BUF_STATE_ERROR);
+}
+
+static const struct vb2_ops csi_vb2_qops = {
+	.queue_setup = ti_csi2rx_queue_setup,
+	.buf_prepare = ti_csi2rx_buffer_prepare,
+	.buf_queue = ti_csi2rx_buffer_queue,
+	.start_streaming = ti_csi2rx_start_streaming,
+	.stop_streaming = ti_csi2rx_stop_streaming,
+	.wait_prepare = vb2_ops_wait_prepare,
+	.wait_finish = vb2_ops_wait_finish,
+};
+
+static int ti_csi2rx_init_vb2q(struct ti_csi2rx_dev *csi)
+{
+	struct vb2_queue *q = &csi->vidq;
+	int ret;
+
+	q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	q->io_modes = VB2_MMAP | VB2_DMABUF;
+	q->drv_priv = csi;
+	q->buf_struct_size = sizeof(struct ti_csi2rx_buffer);
+	q->ops = &csi_vb2_qops;
+	q->mem_ops = &vb2_dma_contig_memops;
+	q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+	q->dev = dmaengine_get_dma_device(csi->dma.chan);
+	q->lock = &csi->mutex;
+	q->min_buffers_needed = 1;
+
+	ret = vb2_queue_init(q);
+	if (ret)
+		return ret;
+
+	csi->vdev.queue = q;
+
+	return 0;
+}
+
+static int ti_csi2rx_link_validate(struct media_link *link)
+{
+	struct media_entity *entity = link->sink->entity;
+	struct video_device *vdev = media_entity_to_video_device(entity);
+	struct ti_csi2rx_dev *csi = container_of(vdev, struct ti_csi2rx_dev, vdev);
+	struct v4l2_pix_format *csi_fmt = &csi->v_fmt.fmt.pix;
+	struct v4l2_subdev_format source_fmt = {};
+	const struct ti_csi2rx_fmt *ti_fmt;
+	int ret;
+
+	ret = v4l2_subdev_link_validate_get_format(link->source, 0,
+						   &source_fmt, false);
+	if (ret)
+		return ret;
+
+	if (source_fmt.format.width != csi_fmt->width) {
+		dev_dbg(csi->dev, "Width does not match (source %u, sink %u)\n",
+			source_fmt.format.width, csi_fmt->width);
+		return -EPIPE;
+	}
+
+	if (source_fmt.format.height != csi_fmt->height) {
+		dev_dbg(csi->dev, "Height does not match (source %u, sink %u)\n",
+			source_fmt.format.height, csi_fmt->height);
+		return -EPIPE;
+	}
+
+	if (source_fmt.format.field != csi_fmt->field &&
+	    csi_fmt->field != V4L2_FIELD_NONE) {
+		dev_dbg(csi->dev, "Field does not match (source %u, sink %u)\n",
+			source_fmt.format.field, csi_fmt->field);
+		return -EPIPE;
+	}
+
+	ti_fmt = find_format_by_code(source_fmt.format.code);
+	if (!ti_fmt) {
+		dev_dbg(csi->dev, "Media bus format 0x%x not supported\n",
+			source_fmt.format.code);
+		return -EPIPE;
+	}
+
+	if (ti_fmt->fourcc != csi_fmt->pixelformat) {
+		dev_dbg(csi->dev,
+			"Cannot transform source fmt 0x%x to sink fmt 0x%x\n",
+			ti_fmt->fourcc, csi_fmt->pixelformat);
+		return -EPIPE;
+	}
+
+	return 0;
+}
+
+static const struct media_entity_operations ti_csi2rx_video_entity_ops = {
+	.link_validate = ti_csi2rx_link_validate,
+};
+
+static int ti_csi2rx_init_dma(struct ti_csi2rx_dev *csi)
+{
+	struct dma_slave_config cfg = {
+		.src_addr_width = DMA_SLAVE_BUSWIDTH_16_BYTES,
+	};
+	int ret;
+
+	INIT_LIST_HEAD(&csi->dma.queue);
+	INIT_LIST_HEAD(&csi->dma.submitted);
+	spin_lock_init(&csi->dma.lock);
+
+	csi->dma.state = TI_CSI2RX_DMA_STOPPED;
+
+	csi->dma.chan = dma_request_chan(csi->dev, "rx0");
+	if (IS_ERR(csi->dma.chan))
+		return PTR_ERR(csi->dma.chan);
+
+	ret = dmaengine_slave_config(csi->dma.chan, &cfg);
+	if (ret) {
+		dma_release_channel(csi->dma.chan);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int ti_csi2rx_v4l2_init(struct ti_csi2rx_dev *csi)
+{
+	struct media_device *mdev = &csi->mdev;
+	struct video_device *vdev = &csi->vdev;
+	const struct ti_csi2rx_fmt *fmt;
+	struct v4l2_pix_format *pix_fmt = &csi->v_fmt.fmt.pix;
+	int ret;
+
+	fmt = find_format_by_pix(V4L2_PIX_FMT_UYVY);
+	if (!fmt)
+		return -EINVAL;
+
+	pix_fmt->width = 640;
+	pix_fmt->height = 480;
+	pix_fmt->field = V4L2_FIELD_NONE;
+
+	ti_csi2rx_fill_fmt(fmt, &csi->v_fmt);
+
+	mdev->dev = csi->dev;
+	mdev->hw_revision = 1;
+	strscpy(mdev->model, "TI-CSI2RX", sizeof(mdev->model));
+
+	media_device_init(mdev);
+
+	strscpy(vdev->name, TI_CSI2RX_MODULE_NAME, sizeof(vdev->name));
+	vdev->v4l2_dev = &csi->v4l2_dev;
+	vdev->vfl_dir = VFL_DIR_RX;
+	vdev->fops = &csi_fops;
+	vdev->ioctl_ops = &csi_ioctl_ops;
+	vdev->release = video_device_release_empty;
+	vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING |
+			    V4L2_CAP_IO_MC;
+	vdev->lock = &csi->mutex;
+	video_set_drvdata(vdev, csi);
+
+	csi->pad.flags = MEDIA_PAD_FL_SINK;
+	vdev->entity.ops = &ti_csi2rx_video_entity_ops;
+	ret = media_entity_pads_init(&csi->vdev.entity, 1, &csi->pad);
+	if (ret)
+		return ret;
+
+	csi->v4l2_dev.mdev = mdev;
+
+	ret = v4l2_device_register(csi->dev, &csi->v4l2_dev);
+	if (ret)
+		return ret;
+
+	ret = media_device_register(mdev);
+	if (ret) {
+		v4l2_device_unregister(&csi->v4l2_dev);
+		media_device_cleanup(mdev);
+		return ret;
+	}
+
+	return 0;
+}
+
+static void ti_csi2rx_cleanup_dma(struct ti_csi2rx_dev *csi)
+{
+	dma_release_channel(csi->dma.chan);
+}
+
+static void ti_csi2rx_cleanup_v4l2(struct ti_csi2rx_dev *csi)
+{
+	media_device_unregister(&csi->mdev);
+	v4l2_device_unregister(&csi->v4l2_dev);
+	media_device_cleanup(&csi->mdev);
+}
+
+static void ti_csi2rx_cleanup_subdev(struct ti_csi2rx_dev *csi)
+{
+	v4l2_async_nf_unregister(&csi->notifier);
+	v4l2_async_nf_cleanup(&csi->notifier);
+}
+
+static void ti_csi2rx_cleanup_vb2q(struct ti_csi2rx_dev *csi)
+{
+	vb2_queue_release(&csi->vidq);
+}
+
+static int ti_csi2rx_probe(struct platform_device *pdev)
+{
+	struct ti_csi2rx_dev *csi;
+	struct resource *res;
+	int ret;
+
+	csi = devm_kzalloc(&pdev->dev, sizeof(*csi), GFP_KERNEL);
+	if (!csi)
+		return -ENOMEM;
+
+	csi->dev = &pdev->dev;
+	platform_set_drvdata(pdev, csi);
+
+	mutex_init(&csi->mutex);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	csi->shim = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(csi->shim)) {
+		ret = PTR_ERR(csi->shim);
+		goto err_mutex;
+	}
+
+	ret = ti_csi2rx_init_dma(csi);
+	if (ret)
+		goto err_mutex;
+
+	ret = ti_csi2rx_v4l2_init(csi);
+	if (ret)
+		goto err_dma;
+
+	ret = ti_csi2rx_init_vb2q(csi);
+	if (ret)
+		goto err_v4l2;
+
+	ret = ti_csi2rx_init_subdev(csi);
+	if (ret)
+		goto err_vb2q;
+
+	ret = of_platform_populate(csi->dev->of_node, NULL, NULL, csi->dev);
+	if (ret) {
+		dev_err(csi->dev, "Failed to create children: %d\n", ret);
+		goto err_subdev;
+	}
+
+	return 0;
+
+err_subdev:
+	ti_csi2rx_cleanup_subdev(csi);
+err_vb2q:
+	ti_csi2rx_cleanup_vb2q(csi);
+err_v4l2:
+	ti_csi2rx_cleanup_v4l2(csi);
+err_dma:
+	ti_csi2rx_cleanup_dma(csi);
+err_mutex:
+	mutex_destroy(&csi->mutex);
+	return ret;
+}
+
+static int ti_csi2rx_remove(struct platform_device *pdev)
+{
+	struct ti_csi2rx_dev *csi = platform_get_drvdata(pdev);
+
+	video_unregister_device(&csi->vdev);
+
+	ti_csi2rx_cleanup_vb2q(csi);
+	ti_csi2rx_cleanup_subdev(csi);
+	ti_csi2rx_cleanup_v4l2(csi);
+	ti_csi2rx_cleanup_dma(csi);
+
+	mutex_destroy(&csi->mutex);
+
+	return 0;
+}
+
+static const struct of_device_id ti_csi2rx_of_match[] = {
+	{ .compatible = "ti,j721e-csi2rx-shim", },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, ti_csi2rx_of_match);
+
+static struct platform_driver ti_csi2rx_pdrv = {
+	.probe = ti_csi2rx_probe,
+	.remove = ti_csi2rx_remove,
+	.driver = {
+		.name = TI_CSI2RX_MODULE_NAME,
+		.of_match_table = ti_csi2rx_of_match,
+	},
+};
+
+module_platform_driver(ti_csi2rx_pdrv);
+
+MODULE_DESCRIPTION("TI J721E CSI2 RX Driver");
+MODULE_AUTHOR("Pratyush Yadav <p.yadav@ti.com>");
+MODULE_LICENSE("GPL");

-- 
2.41.0

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

* Re: [PATCH v8 15/16] media: dt-bindings: Add TI J721E CSI2RX
  2023-07-31  8:29   ` Jai Luthra
@ 2023-07-31  9:31     ` Rob Herring
  -1 siblings, 0 replies; 84+ messages in thread
From: Rob Herring @ 2023-07-31  9:31 UTC (permalink / raw)
  To: Jai Luthra
  Cc: linux-arm-kernel, Mauro Carvalho Chehab, Conor Dooley, nm,
	devarsht, Vaishnav Achath, Mauro Carvalho Chehab,
	niklas.soderlund+renesas, Tomi Valkeinen, Rob Herring,
	Benoit Parrot, Vignesh Raghavendra, Laurent Pinchart,
	Sakari Ailus, Maxime Ripard, devicetree, Krzysztof Kozlowski,
	linux-media, linux-kernel


On Mon, 31 Jul 2023 13:59:33 +0530, Jai Luthra wrote:
> From: Pratyush Yadav <p.yadav@ti.com>
> 
> TI's J721E uses the Cadence CSI2RX and DPHY peripherals to facilitate
> capture over a CSI-2 bus. The TI CSI2RX platform driver glues all the
> parts together.
> 
> Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
> Signed-off-by: Jai Luthra <j-luthra@ti.com>
> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Reviewed-by: Rob Herring <robh@kernel.org>
> ---
> v7->v8:
> - Drop "Device Tree Bindings" from title
> - Rename "Wrapper" to "Shim" in title as that is the name referred in
>   the TRM and other places
> - Update maintainer to myself
> - Drop items from compatible as only a single element is present
> - Rename compatible to "ti,j721e-csi2rx-shim" to distinguish from the
>   SoC-specific CSI2RX bridge compatible
> 
>  .../bindings/media/ti,j721e-csi2rx-shim.yaml       | 100 +++++++++++++++++++++
>  1 file changed, 100 insertions(+)
> 

My bot found errors running 'make DT_CHECKER_FLAGS=-m dt_binding_check'
on your patch (DT_CHECKER_FLAGS is new in v5.13):

yamllint warnings/errors:

dtschema/dtc warnings/errors:
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/media/ti,j721e-csi2rx-shim.yaml:
Error in referenced schema matching $id: http://devicetree.org/schemas/media/cdns,csi2rx.yaml
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/media/ti,j721e-csi2rx-shim.example.dtb: ticsi2rx@4500000: csi-bridge@4504000: False schema does not allow {'compatible': ['ti,j721e-csi2rx', 'cdns,csi2rx'], 'reg': [[72368128, 4096]], 'clocks': [[4294967295, 26, 2], [4294967295, 26, 0], [4294967295, 26, 2], [4294967295, 26, 2], [4294967295, 26, 3], [4294967295, 26, 3]], 'clock-names': ['sys_clk', 'p_clk', 'pixel_if0_clk', 'pixel_if1_clk', 'pixel_if2_clk', 'pixel_if3_clk'], 'phys': [[4294967295]], 'phy-names': ['dphy'], 'ports': {'#address-cells': [[1]], '#size-cells': [[0]], 'port@0': {'reg': [[0]], 'endpoint': {'remote-endpoint': [[4294967295]], 'bus-type': [[4]], 'clock-lanes': [[0]], 'data-lanes': [[1, 2]]}}}}
	from schema $id: http://devicetree.org/schemas/media/ti,j721e-csi2rx-shim.yaml#
Documentation/devicetree/bindings/media/ti,j721e-csi2rx-shim.example.dtb: /example-0/ticsi2rx@4500000/csi-bridge@4504000: failed to match any schema with compatible: ['ti,j721e-csi2rx', 'cdns,csi2rx']
Documentation/devicetree/bindings/media/ti,j721e-csi2rx-shim.example.dtb: /example-0/ticsi2rx@4500000/csi-bridge@4504000: failed to match any schema with compatible: ['ti,j721e-csi2rx', 'cdns,csi2rx']

doc reference errors (make refcheckdocs):

See https://patchwork.ozlabs.org/project/devicetree-bindings/patch/20230731-upstream_csi-v8-15-fb7d3661c2c9@ti.com

The base for the series is generally the latest rc1. A different dependency
should be noted in *this* patch.

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:

pip3 install dtschema --upgrade

Please check and re-submit after running the above command yourself. Note
that DT_SCHEMA_FILES can be set to your schema file to speed up checking
your schema. However, it must be unset to test all examples with your schema.


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

* Re: [PATCH v8 15/16] media: dt-bindings: Add TI J721E CSI2RX
@ 2023-07-31  9:31     ` Rob Herring
  0 siblings, 0 replies; 84+ messages in thread
From: Rob Herring @ 2023-07-31  9:31 UTC (permalink / raw)
  To: Jai Luthra
  Cc: linux-arm-kernel, Mauro Carvalho Chehab, Conor Dooley, nm,
	devarsht, Vaishnav Achath, Mauro Carvalho Chehab,
	niklas.soderlund+renesas, Tomi Valkeinen, Rob Herring,
	Benoit Parrot, Vignesh Raghavendra, Laurent Pinchart,
	Sakari Ailus, Maxime Ripard, devicetree, Krzysztof Kozlowski,
	linux-media, linux-kernel


On Mon, 31 Jul 2023 13:59:33 +0530, Jai Luthra wrote:
> From: Pratyush Yadav <p.yadav@ti.com>
> 
> TI's J721E uses the Cadence CSI2RX and DPHY peripherals to facilitate
> capture over a CSI-2 bus. The TI CSI2RX platform driver glues all the
> parts together.
> 
> Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
> Signed-off-by: Jai Luthra <j-luthra@ti.com>
> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Reviewed-by: Rob Herring <robh@kernel.org>
> ---
> v7->v8:
> - Drop "Device Tree Bindings" from title
> - Rename "Wrapper" to "Shim" in title as that is the name referred in
>   the TRM and other places
> - Update maintainer to myself
> - Drop items from compatible as only a single element is present
> - Rename compatible to "ti,j721e-csi2rx-shim" to distinguish from the
>   SoC-specific CSI2RX bridge compatible
> 
>  .../bindings/media/ti,j721e-csi2rx-shim.yaml       | 100 +++++++++++++++++++++
>  1 file changed, 100 insertions(+)
> 

My bot found errors running 'make DT_CHECKER_FLAGS=-m dt_binding_check'
on your patch (DT_CHECKER_FLAGS is new in v5.13):

yamllint warnings/errors:

dtschema/dtc warnings/errors:
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/media/ti,j721e-csi2rx-shim.yaml:
Error in referenced schema matching $id: http://devicetree.org/schemas/media/cdns,csi2rx.yaml
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/media/ti,j721e-csi2rx-shim.example.dtb: ticsi2rx@4500000: csi-bridge@4504000: False schema does not allow {'compatible': ['ti,j721e-csi2rx', 'cdns,csi2rx'], 'reg': [[72368128, 4096]], 'clocks': [[4294967295, 26, 2], [4294967295, 26, 0], [4294967295, 26, 2], [4294967295, 26, 2], [4294967295, 26, 3], [4294967295, 26, 3]], 'clock-names': ['sys_clk', 'p_clk', 'pixel_if0_clk', 'pixel_if1_clk', 'pixel_if2_clk', 'pixel_if3_clk'], 'phys': [[4294967295]], 'phy-names': ['dphy'], 'ports': {'#address-cells': [[1]], '#size-cells': [[0]], 'port@0': {'reg': [[0]], 'endpoint': {'remote-endpoint': [[4294967295]], 'bus-type': [[4]], 'clock-lanes': [[0]], 'data-lanes': [[1, 2]]}}}}
	from schema $id: http://devicetree.org/schemas/media/ti,j721e-csi2rx-shim.yaml#
Documentation/devicetree/bindings/media/ti,j721e-csi2rx-shim.example.dtb: /example-0/ticsi2rx@4500000/csi-bridge@4504000: failed to match any schema with compatible: ['ti,j721e-csi2rx', 'cdns,csi2rx']
Documentation/devicetree/bindings/media/ti,j721e-csi2rx-shim.example.dtb: /example-0/ticsi2rx@4500000/csi-bridge@4504000: failed to match any schema with compatible: ['ti,j721e-csi2rx', 'cdns,csi2rx']

doc reference errors (make refcheckdocs):

See https://patchwork.ozlabs.org/project/devicetree-bindings/patch/20230731-upstream_csi-v8-15-fb7d3661c2c9@ti.com

The base for the series is generally the latest rc1. A different dependency
should be noted in *this* patch.

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:

pip3 install dtschema --upgrade

Please check and re-submit after running the above command yourself. Note
that DT_SCHEMA_FILES can be set to your schema file to speed up checking
your schema. However, it must be unset to test all examples with your schema.


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v8 15/16] media: dt-bindings: Add TI J721E CSI2RX
  2023-07-31  9:31     ` Rob Herring
@ 2023-07-31  9:54       ` Jai Luthra
  -1 siblings, 0 replies; 84+ messages in thread
From: Jai Luthra @ 2023-07-31  9:54 UTC (permalink / raw)
  To: Rob Herring
  Cc: linux-arm-kernel, Mauro Carvalho Chehab, Conor Dooley, nm,
	devarsht, Vaishnav Achath, Mauro Carvalho Chehab,
	niklas.soderlund+renesas, Tomi Valkeinen, Rob Herring,
	Benoit Parrot, Vignesh Raghavendra, Laurent Pinchart,
	Sakari Ailus, Maxime Ripard, devicetree, Krzysztof Kozlowski,
	linux-media, linux-kernel

Hi Rob,

On 31/07/23 15:01, Rob Herring wrote:
> 
> On Mon, 31 Jul 2023 13:59:33 +0530, Jai Luthra wrote:
>> From: Pratyush Yadav <p.yadav@ti.com>
>>
>> TI's J721E uses the Cadence CSI2RX and DPHY peripherals to facilitate
>> capture over a CSI-2 bus. The TI CSI2RX platform driver glues all the
>> parts together.
>>
>> Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
>> Signed-off-by: Jai Luthra <j-luthra@ti.com>
>> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
>> Reviewed-by: Rob Herring <robh@kernel.org>
>> ---
>> v7->v8:
>> - Drop "Device Tree Bindings" from title
>> - Rename "Wrapper" to "Shim" in title as that is the name referred in
>>    the TRM and other places
>> - Update maintainer to myself
>> - Drop items from compatible as only a single element is present
>> - Rename compatible to "ti,j721e-csi2rx-shim" to distinguish from the
>>    SoC-specific CSI2RX bridge compatible
>>
>>   .../bindings/media/ti,j721e-csi2rx-shim.yaml       | 100 +++++++++++++++++++++
>>   1 file changed, 100 insertions(+)
>>
> 
> My bot found errors running 'make DT_CHECKER_FLAGS=-m dt_binding_check'
> on your patch (DT_CHECKER_FLAGS is new in v5.13):
> 
> yamllint warnings/errors:
> 
> dtschema/dtc warnings/errors:
> /builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/media/ti,j721e-csi2rx-shim.yaml:
> Error in referenced schema matching $id: http://devicetree.org/schemas/media/cdns,csi2rx.yaml
> /builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/media/ti,j721e-csi2rx-shim.example.dtb: ticsi2rx@4500000: csi-bridge@4504000: False schema does not allow {'compatible': ['ti,j721e-csi2rx', 'cdns,csi2rx'], 'reg': [[72368128, 4096]], 'clocks': [[4294967295, 26, 2], [4294967295, 26, 0], [4294967295, 26, 2], [4294967295, 26, 2], [4294967295, 26, 3], [4294967295, 26, 3]], 'clock-names': ['sys_clk', 'p_clk', 'pixel_if0_clk', 'pixel_if1_clk', 'pixel_if2_clk', 'pixel_if3_clk'], 'phys': [[4294967295]], 'phy-names': ['dphy'], 'ports': {'#address-cells': [[1]], '#size-cells': [[0]], 'port@0': {'reg': [[0]], 'endpoint': {'remote-endpoint': [[4294967295]], 'bus-type': [[4]], 'clock-lanes': [[0]], 'data-lanes': [[1, 2]]}}}}
> 	from schema $id: http://devicetree.org/schemas/media/ti,j721e-csi2rx-shim.yaml#
> Documentation/devicetree/bindings/media/ti,j721e-csi2rx-shim.example.dtb: /example-0/ticsi2rx@4500000/csi-bridge@4504000: failed to match any schema with compatible: ['ti,j721e-csi2rx', 'cdns,csi2rx']
> Documentation/devicetree/bindings/media/ti,j721e-csi2rx-shim.example.dtb: /example-0/ticsi2rx@4500000/csi-bridge@4504000: failed to match any schema with compatible: ['ti,j721e-csi2rx', 'cdns,csi2rx']
> 
> doc reference errors (make refcheckdocs):
> 
> See https://patchwork.ozlabs.org/project/devicetree-bindings/patch/20230731-upstream_csi-v8-15-fb7d3661c2c9@ti.com
> 
> The base for the series is generally the latest rc1. A different dependency
> should be noted in *this* patch.

Sorry I missed this warning from v7.

This patch depends on 9536cc949235 ("media: dt-bindings: cadence-csi2rx: 
Convert to DT schema") which is part of linux-next.

The base for this series should be linux-next/master 
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git 
instead of 6.5-rc1.

> 
> If you already ran 'make dt_binding_check' and didn't see the above
> error(s), then make sure 'yamllint' is installed and dt-schema is up to
> date:
> 
> pip3 install dtschema --upgrade
> 
> Please check and re-submit after running the above command yourself. Note
> that DT_SCHEMA_FILES can be set to your schema file to speed up checking
> your schema. However, it must be unset to test all examples with your schema.
> 

-- 
Thanks,
Jai

GPG Fingerprint: 4DE0 D818 E5D5 75E8 D45A AFC5 43DE 91F9 249A 7145

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

* Re: [PATCH v8 15/16] media: dt-bindings: Add TI J721E CSI2RX
@ 2023-07-31  9:54       ` Jai Luthra
  0 siblings, 0 replies; 84+ messages in thread
From: Jai Luthra @ 2023-07-31  9:54 UTC (permalink / raw)
  To: Rob Herring
  Cc: linux-arm-kernel, Mauro Carvalho Chehab, Conor Dooley, nm,
	devarsht, Vaishnav Achath, Mauro Carvalho Chehab,
	niklas.soderlund+renesas, Tomi Valkeinen, Rob Herring,
	Benoit Parrot, Vignesh Raghavendra, Laurent Pinchart,
	Sakari Ailus, Maxime Ripard, devicetree, Krzysztof Kozlowski,
	linux-media, linux-kernel

Hi Rob,

On 31/07/23 15:01, Rob Herring wrote:
> 
> On Mon, 31 Jul 2023 13:59:33 +0530, Jai Luthra wrote:
>> From: Pratyush Yadav <p.yadav@ti.com>
>>
>> TI's J721E uses the Cadence CSI2RX and DPHY peripherals to facilitate
>> capture over a CSI-2 bus. The TI CSI2RX platform driver glues all the
>> parts together.
>>
>> Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
>> Signed-off-by: Jai Luthra <j-luthra@ti.com>
>> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
>> Reviewed-by: Rob Herring <robh@kernel.org>
>> ---
>> v7->v8:
>> - Drop "Device Tree Bindings" from title
>> - Rename "Wrapper" to "Shim" in title as that is the name referred in
>>    the TRM and other places
>> - Update maintainer to myself
>> - Drop items from compatible as only a single element is present
>> - Rename compatible to "ti,j721e-csi2rx-shim" to distinguish from the
>>    SoC-specific CSI2RX bridge compatible
>>
>>   .../bindings/media/ti,j721e-csi2rx-shim.yaml       | 100 +++++++++++++++++++++
>>   1 file changed, 100 insertions(+)
>>
> 
> My bot found errors running 'make DT_CHECKER_FLAGS=-m dt_binding_check'
> on your patch (DT_CHECKER_FLAGS is new in v5.13):
> 
> yamllint warnings/errors:
> 
> dtschema/dtc warnings/errors:
> /builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/media/ti,j721e-csi2rx-shim.yaml:
> Error in referenced schema matching $id: http://devicetree.org/schemas/media/cdns,csi2rx.yaml
> /builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/media/ti,j721e-csi2rx-shim.example.dtb: ticsi2rx@4500000: csi-bridge@4504000: False schema does not allow {'compatible': ['ti,j721e-csi2rx', 'cdns,csi2rx'], 'reg': [[72368128, 4096]], 'clocks': [[4294967295, 26, 2], [4294967295, 26, 0], [4294967295, 26, 2], [4294967295, 26, 2], [4294967295, 26, 3], [4294967295, 26, 3]], 'clock-names': ['sys_clk', 'p_clk', 'pixel_if0_clk', 'pixel_if1_clk', 'pixel_if2_clk', 'pixel_if3_clk'], 'phys': [[4294967295]], 'phy-names': ['dphy'], 'ports': {'#address-cells': [[1]], '#size-cells': [[0]], 'port@0': {'reg': [[0]], 'endpoint': {'remote-endpoint': [[4294967295]], 'bus-type': [[4]], 'clock-lanes': [[0]], 'data-lanes': [[1, 2]]}}}}
> 	from schema $id: http://devicetree.org/schemas/media/ti,j721e-csi2rx-shim.yaml#
> Documentation/devicetree/bindings/media/ti,j721e-csi2rx-shim.example.dtb: /example-0/ticsi2rx@4500000/csi-bridge@4504000: failed to match any schema with compatible: ['ti,j721e-csi2rx', 'cdns,csi2rx']
> Documentation/devicetree/bindings/media/ti,j721e-csi2rx-shim.example.dtb: /example-0/ticsi2rx@4500000/csi-bridge@4504000: failed to match any schema with compatible: ['ti,j721e-csi2rx', 'cdns,csi2rx']
> 
> doc reference errors (make refcheckdocs):
> 
> See https://patchwork.ozlabs.org/project/devicetree-bindings/patch/20230731-upstream_csi-v8-15-fb7d3661c2c9@ti.com
> 
> The base for the series is generally the latest rc1. A different dependency
> should be noted in *this* patch.

Sorry I missed this warning from v7.

This patch depends on 9536cc949235 ("media: dt-bindings: cadence-csi2rx: 
Convert to DT schema") which is part of linux-next.

The base for this series should be linux-next/master 
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git 
instead of 6.5-rc1.

> 
> If you already ran 'make dt_binding_check' and didn't see the above
> error(s), then make sure 'yamllint' is installed and dt-schema is up to
> date:
> 
> pip3 install dtschema --upgrade
> 
> Please check and re-submit after running the above command yourself. Note
> that DT_SCHEMA_FILES can be set to your schema file to speed up checking
> your schema. However, it must be unset to test all examples with your schema.
> 

-- 
Thanks,
Jai

GPG Fingerprint: 4DE0 D818 E5D5 75E8 D45A AFC5 43DE 91F9 249A 7145

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v8 00/16] CSI2RX support on J721E and AM62
  2023-07-31  8:29 ` Jai Luthra
@ 2023-07-31 12:11   ` Maxime Ripard
  -1 siblings, 0 replies; 84+ messages in thread
From: Maxime Ripard @ 2023-07-31 12:11 UTC (permalink / raw)
  To: Jai Luthra
  Cc: Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Sakari Ailus, Laurent Pinchart, Tomi Valkeinen,
	linux-media, linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, niklas.soderlund+renesas, Benoit Parrot,
	Vaishnav Achath, Vignesh Raghavendra, nm, devarsht

[-- Attachment #1: Type: text/plain, Size: 1103 bytes --]

Hi,

On Mon, Jul 31, 2023 at 01:59:18PM +0530, Jai Luthra wrote:

> This series adds support for CSI2 capture on J721E. It includes some
> fixes to the Cadence CSI2RX driver, and adds the TI CSI2RX wrapper driver.
> 
> This is a V8 of the below V7 series,
> https://lore.kernel.org/all/20230314115516.667-1-vaishnav.a@ti.com/
> 
> Since Pratyush moved out of TI, Vaishnav & I have been working on
> this driver, and I will be maintaining it upstream.
> 
> J721E CSI2RX driver can also be extended to support multi-stream
> capture, filtering different CSI Virtual Channels (VC) or Data Types
> (DT) to different DMA channels. A WIP series based on v7 is available
> for reference at https://github.com/jailuthra/linux/commits/csi_multi_wip
> 
> I will rebase the multi-stream patches on the current series (v8) and
> post them as RFC in the coming weeks.
> 
> Testing logs: https://gist.github.com/jailuthra/eaeb3af3c65b67e1bc0d5db28180131d
> 
> Signed-off-by: Jai Luthra <j-luthra@ti.com>

For patches 1-14:
Reviewed-by: Maxime Ripard <mripard@kernel.org>

Thanks!
Maxime

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

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

* Re: [PATCH v8 00/16] CSI2RX support on J721E and AM62
@ 2023-07-31 12:11   ` Maxime Ripard
  0 siblings, 0 replies; 84+ messages in thread
From: Maxime Ripard @ 2023-07-31 12:11 UTC (permalink / raw)
  To: Jai Luthra
  Cc: Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Sakari Ailus, Laurent Pinchart, Tomi Valkeinen,
	linux-media, linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, niklas.soderlund+renesas, Benoit Parrot,
	Vaishnav Achath, Vignesh Raghavendra, nm, devarsht


[-- Attachment #1.1: Type: text/plain, Size: 1103 bytes --]

Hi,

On Mon, Jul 31, 2023 at 01:59:18PM +0530, Jai Luthra wrote:

> This series adds support for CSI2 capture on J721E. It includes some
> fixes to the Cadence CSI2RX driver, and adds the TI CSI2RX wrapper driver.
> 
> This is a V8 of the below V7 series,
> https://lore.kernel.org/all/20230314115516.667-1-vaishnav.a@ti.com/
> 
> Since Pratyush moved out of TI, Vaishnav & I have been working on
> this driver, and I will be maintaining it upstream.
> 
> J721E CSI2RX driver can also be extended to support multi-stream
> capture, filtering different CSI Virtual Channels (VC) or Data Types
> (DT) to different DMA channels. A WIP series based on v7 is available
> for reference at https://github.com/jailuthra/linux/commits/csi_multi_wip
> 
> I will rebase the multi-stream patches on the current series (v8) and
> post them as RFC in the coming weeks.
> 
> Testing logs: https://gist.github.com/jailuthra/eaeb3af3c65b67e1bc0d5db28180131d
> 
> Signed-off-by: Jai Luthra <j-luthra@ti.com>

For patches 1-14:
Reviewed-by: Maxime Ripard <mripard@kernel.org>

Thanks!
Maxime

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

[-- Attachment #2: Type: text/plain, Size: 176 bytes --]

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v8 01/16] media: subdev: Export get_format helper for link validation
  2023-07-31  8:29   ` Jai Luthra
@ 2023-08-01 14:09     ` Tomi Valkeinen
  -1 siblings, 0 replies; 84+ messages in thread
From: Tomi Valkeinen @ 2023-08-01 14:09 UTC (permalink / raw)
  To: Jai Luthra, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Sakari Ailus,
	Laurent Pinchart
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht

On 31/07/2023 11:29, Jai Luthra wrote:
> For link validation on video device drivers, it may be required to
> match the formats set on the source subdev with the formats set on the
> video device.
> 
> Export the existing v4l2_subdev_link_validate_get_format() helper so it
> can be reused by such drivers.
> 
> Suggested-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Signed-off-by: Jai Luthra <j-luthra@ti.com>
> ---
> New in v8
> 
>   drivers/media/v4l2-core/v4l2-subdev.c |  8 ++++----
>   include/media/v4l2-subdev.h           | 12 ++++++++++++
>   2 files changed, 16 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c
> index 217b8019fb9b..0d3b5ff5cacc 100644
> --- a/drivers/media/v4l2-core/v4l2-subdev.c
> +++ b/drivers/media/v4l2-core/v4l2-subdev.c
> @@ -1130,10 +1130,9 @@ int v4l2_subdev_link_validate_default(struct v4l2_subdev *sd,
>   }
>   EXPORT_SYMBOL_GPL(v4l2_subdev_link_validate_default);
>   
> -static int
> -v4l2_subdev_link_validate_get_format(struct media_pad *pad, u32 stream,
> -				     struct v4l2_subdev_format *fmt,
> -				     bool states_locked)
> +int v4l2_subdev_link_validate_get_format(struct media_pad *pad, u32 stream,
> +					 struct v4l2_subdev_format *fmt,
> +					 bool states_locked)
>   {
>   	struct v4l2_subdev_state *state;
>   	struct v4l2_subdev *sd;
> @@ -1165,6 +1164,7 @@ v4l2_subdev_link_validate_get_format(struct media_pad *pad, u32 stream,
>   
>   	return ret;
>   }
> +EXPORT_SYMBOL_GPL(v4l2_subdev_link_validate_get_format);
>   
>   #if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
>   
> diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
> index a012741cc876..ef7007f46889 100644
> --- a/include/media/v4l2-subdev.h
> +++ b/include/media/v4l2-subdev.h
> @@ -1301,6 +1301,18 @@ int v4l2_subdev_link_validate_default(struct v4l2_subdev *sd,
>   				      struct v4l2_subdev_format *source_fmt,
>   				      struct v4l2_subdev_format *sink_fmt);
>   
> +/**
> + * v4l2_subdev_link_validate_get_format - get format for media link validation
> + *
> + * @pad: pad id
> + * @stream: stream id
> + * @fmt: pointer to &struct v4l2_subdev_format
> + * @states_locked: is the subdev state already locked
> + */
> +int v4l2_subdev_link_validate_get_format(struct media_pad *pad, u32 stream,
> +					 struct v4l2_subdev_format *fmt,
> +					 bool states_locked);
> +
>   /**
>    * v4l2_subdev_link_validate - validates a media link
>    *
> 

I don't know about this one... The 
v4l2_subdev_link_validate_get_format() is a bit of an internal function, 
especially with the relatively-new "states_locked" parameter. If it's 
made public, at least the "states_locked" should be renamed to 
"state_locked" (well, it could perhaps be renamed anyway).

But just looking at the function doc above, I think the developer's 
question would be "what does this do?". What does "get format for media 
link validation" mean? Is it similar to 
v4l2_subdev_state_get_stream_format() or v4l2_subdev_get_pad_format()? 
What does states_locked do?

How do you use this with multi-stream support? Do you lock the source, 
then validate all streams (with the help of this function), and then 
unlock? If yes, then all the states_locked stuff is extra, and all the 
function really does is v4l2_subdev_call(sd, pad, get_fmt, state, fmt). 
And if so, would it be clearer to just do that, instead of hiding it 
behind v4l2_subdev_link_validate_get_format()?

  Tomi


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

* Re: [PATCH v8 01/16] media: subdev: Export get_format helper for link validation
@ 2023-08-01 14:09     ` Tomi Valkeinen
  0 siblings, 0 replies; 84+ messages in thread
From: Tomi Valkeinen @ 2023-08-01 14:09 UTC (permalink / raw)
  To: Jai Luthra, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Sakari Ailus,
	Laurent Pinchart
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht

On 31/07/2023 11:29, Jai Luthra wrote:
> For link validation on video device drivers, it may be required to
> match the formats set on the source subdev with the formats set on the
> video device.
> 
> Export the existing v4l2_subdev_link_validate_get_format() helper so it
> can be reused by such drivers.
> 
> Suggested-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Signed-off-by: Jai Luthra <j-luthra@ti.com>
> ---
> New in v8
> 
>   drivers/media/v4l2-core/v4l2-subdev.c |  8 ++++----
>   include/media/v4l2-subdev.h           | 12 ++++++++++++
>   2 files changed, 16 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c
> index 217b8019fb9b..0d3b5ff5cacc 100644
> --- a/drivers/media/v4l2-core/v4l2-subdev.c
> +++ b/drivers/media/v4l2-core/v4l2-subdev.c
> @@ -1130,10 +1130,9 @@ int v4l2_subdev_link_validate_default(struct v4l2_subdev *sd,
>   }
>   EXPORT_SYMBOL_GPL(v4l2_subdev_link_validate_default);
>   
> -static int
> -v4l2_subdev_link_validate_get_format(struct media_pad *pad, u32 stream,
> -				     struct v4l2_subdev_format *fmt,
> -				     bool states_locked)
> +int v4l2_subdev_link_validate_get_format(struct media_pad *pad, u32 stream,
> +					 struct v4l2_subdev_format *fmt,
> +					 bool states_locked)
>   {
>   	struct v4l2_subdev_state *state;
>   	struct v4l2_subdev *sd;
> @@ -1165,6 +1164,7 @@ v4l2_subdev_link_validate_get_format(struct media_pad *pad, u32 stream,
>   
>   	return ret;
>   }
> +EXPORT_SYMBOL_GPL(v4l2_subdev_link_validate_get_format);
>   
>   #if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
>   
> diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
> index a012741cc876..ef7007f46889 100644
> --- a/include/media/v4l2-subdev.h
> +++ b/include/media/v4l2-subdev.h
> @@ -1301,6 +1301,18 @@ int v4l2_subdev_link_validate_default(struct v4l2_subdev *sd,
>   				      struct v4l2_subdev_format *source_fmt,
>   				      struct v4l2_subdev_format *sink_fmt);
>   
> +/**
> + * v4l2_subdev_link_validate_get_format - get format for media link validation
> + *
> + * @pad: pad id
> + * @stream: stream id
> + * @fmt: pointer to &struct v4l2_subdev_format
> + * @states_locked: is the subdev state already locked
> + */
> +int v4l2_subdev_link_validate_get_format(struct media_pad *pad, u32 stream,
> +					 struct v4l2_subdev_format *fmt,
> +					 bool states_locked);
> +
>   /**
>    * v4l2_subdev_link_validate - validates a media link
>    *
> 

I don't know about this one... The 
v4l2_subdev_link_validate_get_format() is a bit of an internal function, 
especially with the relatively-new "states_locked" parameter. If it's 
made public, at least the "states_locked" should be renamed to 
"state_locked" (well, it could perhaps be renamed anyway).

But just looking at the function doc above, I think the developer's 
question would be "what does this do?". What does "get format for media 
link validation" mean? Is it similar to 
v4l2_subdev_state_get_stream_format() or v4l2_subdev_get_pad_format()? 
What does states_locked do?

How do you use this with multi-stream support? Do you lock the source, 
then validate all streams (with the help of this function), and then 
unlock? If yes, then all the states_locked stuff is extra, and all the 
function really does is v4l2_subdev_call(sd, pad, get_fmt, state, fmt). 
And if so, would it be clearer to just do that, instead of hiding it 
behind v4l2_subdev_link_validate_get_format()?

  Tomi


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v8 02/16] media: dt-bindings: Make sure items in data-lanes are unique
  2023-07-31  8:29   ` Jai Luthra
@ 2023-08-01 14:09     ` Tomi Valkeinen
  -1 siblings, 0 replies; 84+ messages in thread
From: Tomi Valkeinen @ 2023-08-01 14:09 UTC (permalink / raw)
  To: Jai Luthra, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Sakari Ailus,
	Laurent Pinchart
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht

On 31/07/2023 11:29, Jai Luthra wrote:
> From: Pratyush Yadav <p.yadav@ti.com>
> 
> The data-lanes property maps the logical lane numbers to the physical
> lane numbers. The position of an entry is the logical lane number and
> its value is the physical lane number. Since one physical lane can only
> map to one logical lane, no number in the list should repeat. Add the
> uniqueItems constraint on the property to enforce this.
> 
> Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
> Signed-off-by: Jai Luthra <j-luthra@ti.com>
> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Acked-by: Rob Herring <robh@kernel.org>
> ---
> v7->v8: No change
> 
>   Documentation/devicetree/bindings/media/video-interfaces.yaml | 1 +
>   1 file changed, 1 insertion(+)
> 
> diff --git a/Documentation/devicetree/bindings/media/video-interfaces.yaml b/Documentation/devicetree/bindings/media/video-interfaces.yaml
> index a211d49dc2ac..26e3e7d7c67b 100644
> --- a/Documentation/devicetree/bindings/media/video-interfaces.yaml
> +++ b/Documentation/devicetree/bindings/media/video-interfaces.yaml
> @@ -160,6 +160,7 @@ properties:
>       $ref: /schemas/types.yaml#/definitions/uint32-array
>       minItems: 1
>       maxItems: 8
> +    uniqueItems: true
>       items:
>         # Assume up to 9 physical lane indices
>         maximum: 8
> 

Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>

  Tomi


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

* Re: [PATCH v8 02/16] media: dt-bindings: Make sure items in data-lanes are unique
@ 2023-08-01 14:09     ` Tomi Valkeinen
  0 siblings, 0 replies; 84+ messages in thread
From: Tomi Valkeinen @ 2023-08-01 14:09 UTC (permalink / raw)
  To: Jai Luthra, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Sakari Ailus,
	Laurent Pinchart
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht

On 31/07/2023 11:29, Jai Luthra wrote:
> From: Pratyush Yadav <p.yadav@ti.com>
> 
> The data-lanes property maps the logical lane numbers to the physical
> lane numbers. The position of an entry is the logical lane number and
> its value is the physical lane number. Since one physical lane can only
> map to one logical lane, no number in the list should repeat. Add the
> uniqueItems constraint on the property to enforce this.
> 
> Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
> Signed-off-by: Jai Luthra <j-luthra@ti.com>
> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Acked-by: Rob Herring <robh@kernel.org>
> ---
> v7->v8: No change
> 
>   Documentation/devicetree/bindings/media/video-interfaces.yaml | 1 +
>   1 file changed, 1 insertion(+)
> 
> diff --git a/Documentation/devicetree/bindings/media/video-interfaces.yaml b/Documentation/devicetree/bindings/media/video-interfaces.yaml
> index a211d49dc2ac..26e3e7d7c67b 100644
> --- a/Documentation/devicetree/bindings/media/video-interfaces.yaml
> +++ b/Documentation/devicetree/bindings/media/video-interfaces.yaml
> @@ -160,6 +160,7 @@ properties:
>       $ref: /schemas/types.yaml#/definitions/uint32-array
>       minItems: 1
>       maxItems: 8
> +    uniqueItems: true
>       items:
>         # Assume up to 9 physical lane indices
>         maximum: 8
> 

Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>

  Tomi


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v8 05/16] media: cadence: csi2rx: Unregister v4l2 async notifier
  2023-07-31  8:29   ` Jai Luthra
@ 2023-08-01 14:11     ` Tomi Valkeinen
  -1 siblings, 0 replies; 84+ messages in thread
From: Tomi Valkeinen @ 2023-08-01 14:11 UTC (permalink / raw)
  To: Jai Luthra, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Sakari Ailus,
	Laurent Pinchart
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht

On 31/07/2023 11:29, Jai Luthra wrote:
> From: Pratyush Yadav <p.yadav@ti.com>
> 
> The notifier is added to the global notifier list when registered. When
> the module is removed, the struct csi2rx_priv in which the notifier is
> embedded, is destroyed. As a result the notifier list has a reference to
> a notifier that no longer exists. This causes invalid memory accesses
> when the list is iterated over. Similar for when the probe fails.
> Unregister and clean up the notifier to avoid this.
> 
> Fixes: 1fc3b37f34f6 ("media: v4l: cadence: Add Cadence MIPI-CSI2 RX driver")
> 
> Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
> Signed-off-by: Jai Luthra <j-luthra@ti.com>
> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
> v7->v8: No change
> 
>   drivers/media/platform/cadence/cdns-csi2rx.c | 7 ++++++-
>   1 file changed, 6 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/media/platform/cadence/cdns-csi2rx.c b/drivers/media/platform/cadence/cdns-csi2rx.c
> index b087583d636f..fd6f2e04e77f 100644
> --- a/drivers/media/platform/cadence/cdns-csi2rx.c
> +++ b/drivers/media/platform/cadence/cdns-csi2rx.c
> @@ -479,8 +479,10 @@ static int csi2rx_parse_dt(struct csi2rx_priv *csi2rx)
>   	asd = v4l2_async_nf_add_fwnode_remote(&csi2rx->notifier, fwh,
>   					      struct v4l2_async_connection);
>   	of_node_put(ep);
> -	if (IS_ERR(asd))
> +	if (IS_ERR(asd)) {
> +		v4l2_async_nf_cleanup(&csi2rx->notifier);
>   		return PTR_ERR(asd);
> +	}
>   
>   	csi2rx->notifier.ops = &csi2rx_notifier_ops;
>   
> @@ -543,6 +545,7 @@ static int csi2rx_probe(struct platform_device *pdev)
>   	return 0;
>   
>   err_cleanup:
> +	v4l2_async_nf_unregister(&csi2rx->notifier);
>   	v4l2_async_nf_cleanup(&csi2rx->notifier);
>   err_free_priv:
>   	kfree(csi2rx);
> @@ -553,6 +556,8 @@ static void csi2rx_remove(struct platform_device *pdev)
>   {
>   	struct csi2rx_priv *csi2rx = platform_get_drvdata(pdev);
>   
> +	v4l2_async_nf_unregister(&csi2rx->notifier);
> +	v4l2_async_nf_cleanup(&csi2rx->notifier);
>   	v4l2_async_unregister_subdev(&csi2rx->subdev);
>   	kfree(csi2rx);
>   }
> 

Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>

  Tomi


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

* Re: [PATCH v8 05/16] media: cadence: csi2rx: Unregister v4l2 async notifier
@ 2023-08-01 14:11     ` Tomi Valkeinen
  0 siblings, 0 replies; 84+ messages in thread
From: Tomi Valkeinen @ 2023-08-01 14:11 UTC (permalink / raw)
  To: Jai Luthra, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Sakari Ailus,
	Laurent Pinchart
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht

On 31/07/2023 11:29, Jai Luthra wrote:
> From: Pratyush Yadav <p.yadav@ti.com>
> 
> The notifier is added to the global notifier list when registered. When
> the module is removed, the struct csi2rx_priv in which the notifier is
> embedded, is destroyed. As a result the notifier list has a reference to
> a notifier that no longer exists. This causes invalid memory accesses
> when the list is iterated over. Similar for when the probe fails.
> Unregister and clean up the notifier to avoid this.
> 
> Fixes: 1fc3b37f34f6 ("media: v4l: cadence: Add Cadence MIPI-CSI2 RX driver")
> 
> Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
> Signed-off-by: Jai Luthra <j-luthra@ti.com>
> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
> v7->v8: No change
> 
>   drivers/media/platform/cadence/cdns-csi2rx.c | 7 ++++++-
>   1 file changed, 6 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/media/platform/cadence/cdns-csi2rx.c b/drivers/media/platform/cadence/cdns-csi2rx.c
> index b087583d636f..fd6f2e04e77f 100644
> --- a/drivers/media/platform/cadence/cdns-csi2rx.c
> +++ b/drivers/media/platform/cadence/cdns-csi2rx.c
> @@ -479,8 +479,10 @@ static int csi2rx_parse_dt(struct csi2rx_priv *csi2rx)
>   	asd = v4l2_async_nf_add_fwnode_remote(&csi2rx->notifier, fwh,
>   					      struct v4l2_async_connection);
>   	of_node_put(ep);
> -	if (IS_ERR(asd))
> +	if (IS_ERR(asd)) {
> +		v4l2_async_nf_cleanup(&csi2rx->notifier);
>   		return PTR_ERR(asd);
> +	}
>   
>   	csi2rx->notifier.ops = &csi2rx_notifier_ops;
>   
> @@ -543,6 +545,7 @@ static int csi2rx_probe(struct platform_device *pdev)
>   	return 0;
>   
>   err_cleanup:
> +	v4l2_async_nf_unregister(&csi2rx->notifier);
>   	v4l2_async_nf_cleanup(&csi2rx->notifier);
>   err_free_priv:
>   	kfree(csi2rx);
> @@ -553,6 +556,8 @@ static void csi2rx_remove(struct platform_device *pdev)
>   {
>   	struct csi2rx_priv *csi2rx = platform_get_drvdata(pdev);
>   
> +	v4l2_async_nf_unregister(&csi2rx->notifier);
> +	v4l2_async_nf_cleanup(&csi2rx->notifier);
>   	v4l2_async_unregister_subdev(&csi2rx->subdev);
>   	kfree(csi2rx);
>   }
> 

Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>

  Tomi


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v8 06/16] media: cadence: csi2rx: Cleanup media entity properly
  2023-07-31  8:29   ` Jai Luthra
@ 2023-08-01 14:11     ` Tomi Valkeinen
  -1 siblings, 0 replies; 84+ messages in thread
From: Tomi Valkeinen @ 2023-08-01 14:11 UTC (permalink / raw)
  To: Jai Luthra, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Sakari Ailus,
	Laurent Pinchart
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht

On 31/07/2023 11:29, Jai Luthra wrote:
> From: Pratyush Yadav <p.yadav@ti.com>
> 
> Call media_entity_cleanup() in probe error path and remove to make sure
> the media entity is cleaned up properly.
> 
> Suggested-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
> Signed-off-by: Jai Luthra <j-luthra@ti.com>
> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
> v7->v8: No change
> 
>   drivers/media/platform/cadence/cdns-csi2rx.c | 2 ++
>   1 file changed, 2 insertions(+)
> 
> diff --git a/drivers/media/platform/cadence/cdns-csi2rx.c b/drivers/media/platform/cadence/cdns-csi2rx.c
> index fd6f2e04e77f..83d1fadd592b 100644
> --- a/drivers/media/platform/cadence/cdns-csi2rx.c
> +++ b/drivers/media/platform/cadence/cdns-csi2rx.c
> @@ -547,6 +547,7 @@ static int csi2rx_probe(struct platform_device *pdev)
>   err_cleanup:
>   	v4l2_async_nf_unregister(&csi2rx->notifier);
>   	v4l2_async_nf_cleanup(&csi2rx->notifier);
> +	media_entity_cleanup(&csi2rx->subdev.entity);
>   err_free_priv:
>   	kfree(csi2rx);
>   	return ret;
> @@ -559,6 +560,7 @@ static void csi2rx_remove(struct platform_device *pdev)
>   	v4l2_async_nf_unregister(&csi2rx->notifier);
>   	v4l2_async_nf_cleanup(&csi2rx->notifier);
>   	v4l2_async_unregister_subdev(&csi2rx->subdev);
> +	media_entity_cleanup(&csi2rx->subdev.entity);
>   	kfree(csi2rx);
>   }
>   
> 

Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>

  Tomi


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

* Re: [PATCH v8 06/16] media: cadence: csi2rx: Cleanup media entity properly
@ 2023-08-01 14:11     ` Tomi Valkeinen
  0 siblings, 0 replies; 84+ messages in thread
From: Tomi Valkeinen @ 2023-08-01 14:11 UTC (permalink / raw)
  To: Jai Luthra, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Sakari Ailus,
	Laurent Pinchart
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht

On 31/07/2023 11:29, Jai Luthra wrote:
> From: Pratyush Yadav <p.yadav@ti.com>
> 
> Call media_entity_cleanup() in probe error path and remove to make sure
> the media entity is cleaned up properly.
> 
> Suggested-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
> Signed-off-by: Jai Luthra <j-luthra@ti.com>
> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
> v7->v8: No change
> 
>   drivers/media/platform/cadence/cdns-csi2rx.c | 2 ++
>   1 file changed, 2 insertions(+)
> 
> diff --git a/drivers/media/platform/cadence/cdns-csi2rx.c b/drivers/media/platform/cadence/cdns-csi2rx.c
> index fd6f2e04e77f..83d1fadd592b 100644
> --- a/drivers/media/platform/cadence/cdns-csi2rx.c
> +++ b/drivers/media/platform/cadence/cdns-csi2rx.c
> @@ -547,6 +547,7 @@ static int csi2rx_probe(struct platform_device *pdev)
>   err_cleanup:
>   	v4l2_async_nf_unregister(&csi2rx->notifier);
>   	v4l2_async_nf_cleanup(&csi2rx->notifier);
> +	media_entity_cleanup(&csi2rx->subdev.entity);
>   err_free_priv:
>   	kfree(csi2rx);
>   	return ret;
> @@ -559,6 +560,7 @@ static void csi2rx_remove(struct platform_device *pdev)
>   	v4l2_async_nf_unregister(&csi2rx->notifier);
>   	v4l2_async_nf_cleanup(&csi2rx->notifier);
>   	v4l2_async_unregister_subdev(&csi2rx->subdev);
> +	media_entity_cleanup(&csi2rx->subdev.entity);
>   	kfree(csi2rx);
>   }
>   
> 

Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>

  Tomi


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v8 09/16] media: cadence: csi2rx: Soft reset the streams before starting capture
  2023-07-31  8:29   ` Jai Luthra
@ 2023-08-01 14:16     ` Tomi Valkeinen
  -1 siblings, 0 replies; 84+ messages in thread
From: Tomi Valkeinen @ 2023-08-01 14:16 UTC (permalink / raw)
  To: Jai Luthra, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Sakari Ailus,
	Laurent Pinchart
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht

On 31/07/2023 11:29, Jai Luthra wrote:
> From: Pratyush Yadav <p.yadav@ti.com>
> 
> This resets the stream state machines and FIFOs, giving them a clean
> slate. On J721E if the streams are not reset before starting the
> capture, the captured frame gets wrapped around vertically on every run
> after the first.
> 
> Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
> Signed-off-by: Jai Luthra <j-luthra@ti.com>
> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
> v7->v8: No change
> 
>   drivers/media/platform/cadence/cdns-csi2rx.c | 11 +++++++++++
>   1 file changed, 11 insertions(+)
> 
> diff --git a/drivers/media/platform/cadence/cdns-csi2rx.c b/drivers/media/platform/cadence/cdns-csi2rx.c
> index 2a80c66fb547..30cdc260b46a 100644
> --- a/drivers/media/platform/cadence/cdns-csi2rx.c
> +++ b/drivers/media/platform/cadence/cdns-csi2rx.c
> @@ -40,6 +40,7 @@
>   #define CSI2RX_STREAM_BASE(n)		(((n) + 1) * 0x100)
>   
>   #define CSI2RX_STREAM_CTRL_REG(n)		(CSI2RX_STREAM_BASE(n) + 0x000)
> +#define CSI2RX_STREAM_CTRL_SOFT_RST			BIT(4)
>   #define CSI2RX_STREAM_CTRL_START			BIT(0)
>   
>   #define CSI2RX_STREAM_DATA_CFG_REG(n)		(CSI2RX_STREAM_BASE(n) + 0x008)
> @@ -138,12 +139,22 @@ struct csi2rx_priv *v4l2_subdev_to_csi2rx(struct v4l2_subdev *subdev)
>   
>   static void csi2rx_reset(struct csi2rx_priv *csi2rx)
>   {
> +	unsigned int i;
> +
>   	writel(CSI2RX_SOFT_RESET_PROTOCOL | CSI2RX_SOFT_RESET_FRONT,
>   	       csi2rx->base + CSI2RX_SOFT_RESET_REG);
>   
>   	udelay(10);
>   
>   	writel(0, csi2rx->base + CSI2RX_SOFT_RESET_REG);
> +
> +	/* Reset individual streams. */
> +	for (i = 0; i < csi2rx->max_streams; i++) {
> +		writel(CSI2RX_STREAM_CTRL_SOFT_RST,
> +		       csi2rx->base + CSI2RX_STREAM_CTRL_REG(i));
> +		usleep_range(10, 20);
> +		writel(0, csi2rx->base + CSI2RX_STREAM_CTRL_REG(i));
> +	}

Do you have to do it like this? Or would it be fine to set the reset bit 
for all stream regs, then sleep, then clear the reset bit from all 
stream regs? Or going even further, can you set the 
CSI2RX_SOFT_RESET_REG and all CSI2RX_STREAM_CTRL_REG regs, then sleep, 
and then clear them all?

  Tomi


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

* Re: [PATCH v8 09/16] media: cadence: csi2rx: Soft reset the streams before starting capture
@ 2023-08-01 14:16     ` Tomi Valkeinen
  0 siblings, 0 replies; 84+ messages in thread
From: Tomi Valkeinen @ 2023-08-01 14:16 UTC (permalink / raw)
  To: Jai Luthra, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Sakari Ailus,
	Laurent Pinchart
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht

On 31/07/2023 11:29, Jai Luthra wrote:
> From: Pratyush Yadav <p.yadav@ti.com>
> 
> This resets the stream state machines and FIFOs, giving them a clean
> slate. On J721E if the streams are not reset before starting the
> capture, the captured frame gets wrapped around vertically on every run
> after the first.
> 
> Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
> Signed-off-by: Jai Luthra <j-luthra@ti.com>
> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
> v7->v8: No change
> 
>   drivers/media/platform/cadence/cdns-csi2rx.c | 11 +++++++++++
>   1 file changed, 11 insertions(+)
> 
> diff --git a/drivers/media/platform/cadence/cdns-csi2rx.c b/drivers/media/platform/cadence/cdns-csi2rx.c
> index 2a80c66fb547..30cdc260b46a 100644
> --- a/drivers/media/platform/cadence/cdns-csi2rx.c
> +++ b/drivers/media/platform/cadence/cdns-csi2rx.c
> @@ -40,6 +40,7 @@
>   #define CSI2RX_STREAM_BASE(n)		(((n) + 1) * 0x100)
>   
>   #define CSI2RX_STREAM_CTRL_REG(n)		(CSI2RX_STREAM_BASE(n) + 0x000)
> +#define CSI2RX_STREAM_CTRL_SOFT_RST			BIT(4)
>   #define CSI2RX_STREAM_CTRL_START			BIT(0)
>   
>   #define CSI2RX_STREAM_DATA_CFG_REG(n)		(CSI2RX_STREAM_BASE(n) + 0x008)
> @@ -138,12 +139,22 @@ struct csi2rx_priv *v4l2_subdev_to_csi2rx(struct v4l2_subdev *subdev)
>   
>   static void csi2rx_reset(struct csi2rx_priv *csi2rx)
>   {
> +	unsigned int i;
> +
>   	writel(CSI2RX_SOFT_RESET_PROTOCOL | CSI2RX_SOFT_RESET_FRONT,
>   	       csi2rx->base + CSI2RX_SOFT_RESET_REG);
>   
>   	udelay(10);
>   
>   	writel(0, csi2rx->base + CSI2RX_SOFT_RESET_REG);
> +
> +	/* Reset individual streams. */
> +	for (i = 0; i < csi2rx->max_streams; i++) {
> +		writel(CSI2RX_STREAM_CTRL_SOFT_RST,
> +		       csi2rx->base + CSI2RX_STREAM_CTRL_REG(i));
> +		usleep_range(10, 20);
> +		writel(0, csi2rx->base + CSI2RX_STREAM_CTRL_REG(i));
> +	}

Do you have to do it like this? Or would it be fine to set the reset bit 
for all stream regs, then sleep, then clear the reset bit from all 
stream regs? Or going even further, can you set the 
CSI2RX_SOFT_RESET_REG and all CSI2RX_STREAM_CTRL_REG regs, then sleep, 
and then clear them all?

  Tomi


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v8 11/16] media: cadence: csi2rx: Fix stream data configuration
  2023-07-31  8:29   ` Jai Luthra
@ 2023-08-01 14:17     ` Tomi Valkeinen
  -1 siblings, 0 replies; 84+ messages in thread
From: Tomi Valkeinen @ 2023-08-01 14:17 UTC (permalink / raw)
  To: Jai Luthra, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Sakari Ailus,
	Laurent Pinchart
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht

On 31/07/2023 11:29, Jai Luthra wrote:
> From: Pratyush Yadav <p.yadav@ti.com>
> 
> Firstly, there is no VC_EN bit present in the STREAM_DATA_CFG register.
> Bit 31 is part of the VL_SELECT field. Remove it completely.
> 
> Secondly, it makes little sense to enable ith virtual channel for ith
> stream. Sure, there might be a use-case that demands it. But there might
> also be a use case that demands all streams to use the 0th virtual
> channel. Prefer this case over the former because it is less arbitrary
> and also makes it very clear what the limitations of the current driver
> is instead of giving a false impression that multiple virtual channels
> are supported.
> 
> Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
> Signed-off-by: Jai Luthra <j-luthra@ti.com>
> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
> v7->v8: No change
> 
>   drivers/media/platform/cadence/cdns-csi2rx.c | 8 +++++---
>   1 file changed, 5 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/media/platform/cadence/cdns-csi2rx.c b/drivers/media/platform/cadence/cdns-csi2rx.c
> index a17ef88dff82..cde7fd6463e1 100644
> --- a/drivers/media/platform/cadence/cdns-csi2rx.c
> +++ b/drivers/media/platform/cadence/cdns-csi2rx.c
> @@ -49,7 +49,6 @@
>   #define CSI2RX_STREAM_STATUS_RDY			BIT(31)
>   
>   #define CSI2RX_STREAM_DATA_CFG_REG(n)		(CSI2RX_STREAM_BASE(n) + 0x008)
> -#define CSI2RX_STREAM_DATA_CFG_EN_VC_SELECT		BIT(31)
>   #define CSI2RX_STREAM_DATA_CFG_VC_SELECT(n)		BIT((n) + 16)
>   
>   #define CSI2RX_STREAM_CFG_REG(n)		(CSI2RX_STREAM_BASE(n) + 0x00c)
> @@ -275,8 +274,11 @@ static int csi2rx_start(struct csi2rx_priv *csi2rx)
>   		writel(CSI2RX_STREAM_CFG_FIFO_MODE_LARGE_BUF,
>   		       csi2rx->base + CSI2RX_STREAM_CFG_REG(i));
>   
> -		writel(CSI2RX_STREAM_DATA_CFG_EN_VC_SELECT |
> -		       CSI2RX_STREAM_DATA_CFG_VC_SELECT(i),
> +		/*
> +		 * Enable one virtual channel. When multiple virtual channels
> +		 * are supported this will have to be changed.
> +		 */
> +		writel(CSI2RX_STREAM_DATA_CFG_VC_SELECT(0),
>   		       csi2rx->base + CSI2RX_STREAM_DATA_CFG_REG(i));
>   
>   		writel(CSI2RX_STREAM_CTRL_START,
> 

Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>

  Tomi


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

* Re: [PATCH v8 11/16] media: cadence: csi2rx: Fix stream data configuration
@ 2023-08-01 14:17     ` Tomi Valkeinen
  0 siblings, 0 replies; 84+ messages in thread
From: Tomi Valkeinen @ 2023-08-01 14:17 UTC (permalink / raw)
  To: Jai Luthra, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Sakari Ailus,
	Laurent Pinchart
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht

On 31/07/2023 11:29, Jai Luthra wrote:
> From: Pratyush Yadav <p.yadav@ti.com>
> 
> Firstly, there is no VC_EN bit present in the STREAM_DATA_CFG register.
> Bit 31 is part of the VL_SELECT field. Remove it completely.
> 
> Secondly, it makes little sense to enable ith virtual channel for ith
> stream. Sure, there might be a use-case that demands it. But there might
> also be a use case that demands all streams to use the 0th virtual
> channel. Prefer this case over the former because it is less arbitrary
> and also makes it very clear what the limitations of the current driver
> is instead of giving a false impression that multiple virtual channels
> are supported.
> 
> Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
> Signed-off-by: Jai Luthra <j-luthra@ti.com>
> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
> v7->v8: No change
> 
>   drivers/media/platform/cadence/cdns-csi2rx.c | 8 +++++---
>   1 file changed, 5 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/media/platform/cadence/cdns-csi2rx.c b/drivers/media/platform/cadence/cdns-csi2rx.c
> index a17ef88dff82..cde7fd6463e1 100644
> --- a/drivers/media/platform/cadence/cdns-csi2rx.c
> +++ b/drivers/media/platform/cadence/cdns-csi2rx.c
> @@ -49,7 +49,6 @@
>   #define CSI2RX_STREAM_STATUS_RDY			BIT(31)
>   
>   #define CSI2RX_STREAM_DATA_CFG_REG(n)		(CSI2RX_STREAM_BASE(n) + 0x008)
> -#define CSI2RX_STREAM_DATA_CFG_EN_VC_SELECT		BIT(31)
>   #define CSI2RX_STREAM_DATA_CFG_VC_SELECT(n)		BIT((n) + 16)
>   
>   #define CSI2RX_STREAM_CFG_REG(n)		(CSI2RX_STREAM_BASE(n) + 0x00c)
> @@ -275,8 +274,11 @@ static int csi2rx_start(struct csi2rx_priv *csi2rx)
>   		writel(CSI2RX_STREAM_CFG_FIFO_MODE_LARGE_BUF,
>   		       csi2rx->base + CSI2RX_STREAM_CFG_REG(i));
>   
> -		writel(CSI2RX_STREAM_DATA_CFG_EN_VC_SELECT |
> -		       CSI2RX_STREAM_DATA_CFG_VC_SELECT(i),
> +		/*
> +		 * Enable one virtual channel. When multiple virtual channels
> +		 * are supported this will have to be changed.
> +		 */
> +		writel(CSI2RX_STREAM_DATA_CFG_VC_SELECT(0),
>   		       csi2rx->base + CSI2RX_STREAM_DATA_CFG_REG(i));
>   
>   		writel(CSI2RX_STREAM_CTRL_START,
> 

Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>

  Tomi


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v8 12/16] media: cadence: csi2rx: Populate subdev devnode
  2023-07-31  8:29   ` Jai Luthra
@ 2023-08-01 14:18     ` Tomi Valkeinen
  -1 siblings, 0 replies; 84+ messages in thread
From: Tomi Valkeinen @ 2023-08-01 14:18 UTC (permalink / raw)
  To: Jai Luthra, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Sakari Ailus,
	Laurent Pinchart
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht

On 31/07/2023 11:29, Jai Luthra wrote:
> From: Pratyush Yadav <p.yadav@ti.com>
> 
> The devnode can be used by media-ctl and other userspace tools to
> perform configurations on the subdev. Without it, media-ctl returns
> ENOENT when setting format on the sensor subdev.
> 
> Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
> Signed-off-by: Jai Luthra <j-luthra@ti.com>
> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
> v7->v8: No change
> 
>   drivers/media/platform/cadence/cdns-csi2rx.c | 1 +
>   1 file changed, 1 insertion(+)
> 
> diff --git a/drivers/media/platform/cadence/cdns-csi2rx.c b/drivers/media/platform/cadence/cdns-csi2rx.c
> index cde7fd6463e1..d82a8938932f 100644
> --- a/drivers/media/platform/cadence/cdns-csi2rx.c
> +++ b/drivers/media/platform/cadence/cdns-csi2rx.c
> @@ -678,6 +678,7 @@ static int csi2rx_probe(struct platform_device *pdev)
>   	csi2rx->pads[CSI2RX_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
>   	for (i = CSI2RX_PAD_SOURCE_STREAM0; i < CSI2RX_PAD_MAX; i++)
>   		csi2rx->pads[i].flags = MEDIA_PAD_FL_SOURCE;
> +	csi2rx->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
>   
>   	ret = media_entity_pads_init(&csi2rx->subdev.entity, CSI2RX_PAD_MAX,
>   				     csi2rx->pads);
> 

Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>

  Tomi


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

* Re: [PATCH v8 12/16] media: cadence: csi2rx: Populate subdev devnode
@ 2023-08-01 14:18     ` Tomi Valkeinen
  0 siblings, 0 replies; 84+ messages in thread
From: Tomi Valkeinen @ 2023-08-01 14:18 UTC (permalink / raw)
  To: Jai Luthra, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Sakari Ailus,
	Laurent Pinchart
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht

On 31/07/2023 11:29, Jai Luthra wrote:
> From: Pratyush Yadav <p.yadav@ti.com>
> 
> The devnode can be used by media-ctl and other userspace tools to
> perform configurations on the subdev. Without it, media-ctl returns
> ENOENT when setting format on the sensor subdev.
> 
> Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
> Signed-off-by: Jai Luthra <j-luthra@ti.com>
> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
> v7->v8: No change
> 
>   drivers/media/platform/cadence/cdns-csi2rx.c | 1 +
>   1 file changed, 1 insertion(+)
> 
> diff --git a/drivers/media/platform/cadence/cdns-csi2rx.c b/drivers/media/platform/cadence/cdns-csi2rx.c
> index cde7fd6463e1..d82a8938932f 100644
> --- a/drivers/media/platform/cadence/cdns-csi2rx.c
> +++ b/drivers/media/platform/cadence/cdns-csi2rx.c
> @@ -678,6 +678,7 @@ static int csi2rx_probe(struct platform_device *pdev)
>   	csi2rx->pads[CSI2RX_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
>   	for (i = CSI2RX_PAD_SOURCE_STREAM0; i < CSI2RX_PAD_MAX; i++)
>   		csi2rx->pads[i].flags = MEDIA_PAD_FL_SOURCE;
> +	csi2rx->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
>   
>   	ret = media_entity_pads_init(&csi2rx->subdev.entity, CSI2RX_PAD_MAX,
>   				     csi2rx->pads);
> 

Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>

  Tomi


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v8 13/16] media: cadence: csi2rx: Add link validation
  2023-07-31  8:29   ` Jai Luthra
@ 2023-08-01 14:19     ` Tomi Valkeinen
  -1 siblings, 0 replies; 84+ messages in thread
From: Tomi Valkeinen @ 2023-08-01 14:19 UTC (permalink / raw)
  To: Jai Luthra, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Sakari Ailus,
	Laurent Pinchart
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht

On 31/07/2023 11:29, Jai Luthra wrote:
> From: Pratyush Yadav <p.yadav@ti.com>
> 
> Add media link validation to make sure incorrectly configured pipelines
> are caught.
> 
> Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
> Signed-off-by: Jai Luthra <j-luthra@ti.com>
> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
> v7->v8: No change
> 
>   drivers/media/platform/cadence/cdns-csi2rx.c | 5 +++++
>   1 file changed, 5 insertions(+)
> 
> diff --git a/drivers/media/platform/cadence/cdns-csi2rx.c b/drivers/media/platform/cadence/cdns-csi2rx.c
> index d82a8938932f..aec33d28a66f 100644
> --- a/drivers/media/platform/cadence/cdns-csi2rx.c
> +++ b/drivers/media/platform/cadence/cdns-csi2rx.c
> @@ -463,6 +463,10 @@ static const struct v4l2_subdev_ops csi2rx_subdev_ops = {
>   	.pad		= &csi2rx_pad_ops,
>   };
>   
> +static const struct media_entity_operations csi2rx_media_ops = {
> +	.link_validate = v4l2_subdev_link_validate,
> +};
> +
>   static int csi2rx_async_bound(struct v4l2_async_notifier *notifier,
>   			      struct v4l2_subdev *s_subdev,
>   			      struct v4l2_async_connection *asd)
> @@ -679,6 +683,7 @@ static int csi2rx_probe(struct platform_device *pdev)
>   	for (i = CSI2RX_PAD_SOURCE_STREAM0; i < CSI2RX_PAD_MAX; i++)
>   		csi2rx->pads[i].flags = MEDIA_PAD_FL_SOURCE;
>   	csi2rx->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
> +	csi2rx->subdev.entity.ops = &csi2rx_media_ops;
>   
>   	ret = media_entity_pads_init(&csi2rx->subdev.entity, CSI2RX_PAD_MAX,
>   				     csi2rx->pads);
> 

Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>

  Tomi


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

* Re: [PATCH v8 13/16] media: cadence: csi2rx: Add link validation
@ 2023-08-01 14:19     ` Tomi Valkeinen
  0 siblings, 0 replies; 84+ messages in thread
From: Tomi Valkeinen @ 2023-08-01 14:19 UTC (permalink / raw)
  To: Jai Luthra, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Sakari Ailus,
	Laurent Pinchart
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht

On 31/07/2023 11:29, Jai Luthra wrote:
> From: Pratyush Yadav <p.yadav@ti.com>
> 
> Add media link validation to make sure incorrectly configured pipelines
> are caught.
> 
> Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
> Signed-off-by: Jai Luthra <j-luthra@ti.com>
> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
> v7->v8: No change
> 
>   drivers/media/platform/cadence/cdns-csi2rx.c | 5 +++++
>   1 file changed, 5 insertions(+)
> 
> diff --git a/drivers/media/platform/cadence/cdns-csi2rx.c b/drivers/media/platform/cadence/cdns-csi2rx.c
> index d82a8938932f..aec33d28a66f 100644
> --- a/drivers/media/platform/cadence/cdns-csi2rx.c
> +++ b/drivers/media/platform/cadence/cdns-csi2rx.c
> @@ -463,6 +463,10 @@ static const struct v4l2_subdev_ops csi2rx_subdev_ops = {
>   	.pad		= &csi2rx_pad_ops,
>   };
>   
> +static const struct media_entity_operations csi2rx_media_ops = {
> +	.link_validate = v4l2_subdev_link_validate,
> +};
> +
>   static int csi2rx_async_bound(struct v4l2_async_notifier *notifier,
>   			      struct v4l2_subdev *s_subdev,
>   			      struct v4l2_async_connection *asd)
> @@ -679,6 +683,7 @@ static int csi2rx_probe(struct platform_device *pdev)
>   	for (i = CSI2RX_PAD_SOURCE_STREAM0; i < CSI2RX_PAD_MAX; i++)
>   		csi2rx->pads[i].flags = MEDIA_PAD_FL_SOURCE;
>   	csi2rx->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
> +	csi2rx->subdev.entity.ops = &csi2rx_media_ops;
>   
>   	ret = media_entity_pads_init(&csi2rx->subdev.entity, CSI2RX_PAD_MAX,
>   				     csi2rx->pads);
> 

Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>

  Tomi


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v8 07/16] media: cadence: csi2rx: Add get_fmt and set_fmt pad ops
  2023-07-31  8:29   ` Jai Luthra
@ 2023-08-02  8:48     ` Tomi Valkeinen
  -1 siblings, 0 replies; 84+ messages in thread
From: Tomi Valkeinen @ 2023-08-02  8:48 UTC (permalink / raw)
  To: Jai Luthra, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Sakari Ailus,
	Laurent Pinchart
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht

On 31/07/2023 11:29, Jai Luthra wrote:
> From: Pratyush Yadav <p.yadav@ti.com>
> 
> The format is needed to calculate the link speed for the external DPHY
> configuration. It is not right to query the format from the source
> subdev. Add get_fmt and set_fmt pad operations so that the format can be
> configured and correct bpp be selected.
> 
> Initialize and use the v4l2 subdev active state to keep track of the
> active formats. Also propagate the new format from the sink pad to all
> the source pads.
> 
> Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
> Co-authored-by: Jai Luthra <j-luthra@ti.com>
> Signed-off-by: Jai Luthra <j-luthra@ti.com>
> ---
> v7->v8:
> - Use active subdev state to use v4l2_subdev_get_fmt
> - Propagate formats from sink to source pads
> - Drop Laurent's R-by because of the above changes
> 
>   drivers/media/platform/cadence/cdns-csi2rx.c | 107 ++++++++++++++++++++++++++-
>   1 file changed, 106 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/media/platform/cadence/cdns-csi2rx.c b/drivers/media/platform/cadence/cdns-csi2rx.c
> index 83d1fadd592b..4f9654366485 100644
> --- a/drivers/media/platform/cadence/cdns-csi2rx.c
> +++ b/drivers/media/platform/cadence/cdns-csi2rx.c
> @@ -61,6 +61,11 @@ enum csi2rx_pads {
>   	CSI2RX_PAD_MAX,
>   };
>   
> +struct csi2rx_fmt {
> +	u32				code;
> +	u8				bpp;
> +};
> +
>   struct csi2rx_priv {
>   	struct device			*dev;
>   	unsigned int			count;
> @@ -95,6 +100,36 @@ struct csi2rx_priv {
>   	int				source_pad;
>   };
>   
> +static const struct csi2rx_fmt formats[] = {
> +	{
> +		.code	= MEDIA_BUS_FMT_YUYV8_1X16,
> +		.bpp	= 16,
> +	},
> +	{
> +		.code	= MEDIA_BUS_FMT_UYVY8_1X16,
> +		.bpp	= 16,
> +	},
> +	{
> +		.code	= MEDIA_BUS_FMT_YVYU8_1X16,
> +		.bpp	= 16,
> +	},
> +	{
> +		.code	= MEDIA_BUS_FMT_VYUY8_1X16,
> +		.bpp	= 16,
> +	},
> +};

I think you could just squash the "media: cadence: csi2rx: Support RAW8 
and RAW10 formats" into this one. Also, the lines could well be one-liners:

	{ .code	= MEDIA_BUS_FMT_YUYV8_1X16, .bpp = 16, },


> +static const struct csi2rx_fmt *csi2rx_get_fmt_by_code(u32 code)
> +{
> +	unsigned int i;
> +
> +	for (i = 0; i < ARRAY_SIZE(formats); i++)
> +		if (formats[i].code == code)
> +			return &formats[i];
> +
> +	return NULL;
> +}
> +
>   static inline
>   struct csi2rx_priv *v4l2_subdev_to_csi2rx(struct v4l2_subdev *subdev)
>   {
> @@ -303,12 +338,75 @@ static int csi2rx_s_stream(struct v4l2_subdev *subdev, int enable)
>   	return ret;
>   }
>   
> +static int csi2rx_set_fmt(struct v4l2_subdev *subdev,
> +			  struct v4l2_subdev_state *state,
> +			  struct v4l2_subdev_format *format)
> +{
> +	struct v4l2_mbus_framefmt *fmt;
> +	unsigned int i;
> +
> +	/* No transcoding, source and sink formats must match. */
> +	if (format->pad != CSI2RX_PAD_SINK)
> +		return v4l2_subdev_get_fmt(subdev, state, format);
> +
> +	if (!csi2rx_get_fmt_by_code(format->format.code))
> +		format->format.code = formats[0].code;
> +
> +	format->format.field = V4L2_FIELD_NONE;
> +
> +	/* Set sink format */
> +	fmt = v4l2_subdev_get_pad_format(subdev, state, format->pad);
> +	if (!fmt)
> +		return -EINVAL;
> +
> +	*fmt = format->format;
> +
> +	/* Propagate to source formats */
> +	for (i = CSI2RX_PAD_SOURCE_STREAM0; i < CSI2RX_PAD_MAX; i++) {
> +		fmt = v4l2_subdev_get_pad_format(subdev, state, i);
> +		if (!fmt)
> +			return -EINVAL;
> +		*fmt = format->format;
> +	}

Not really part of this patch, but why does csi2rx create more than one 
source pad? It doesn't support streams, so how are those pads used?

> +	return 0;
> +}
> +
> +static int csi2rx_init_cfg(struct v4l2_subdev *subdev,
> +			   struct v4l2_subdev_state *state)
> +{
> +	struct v4l2_subdev_format format = {
> +		.which = state ? V4L2_SUBDEV_FORMAT_TRY
> +			: V4L2_SUBDEV_FORMAT_ACTIVE,

I don't think this is correct. If you enable the active state, you'll 
always get a state here, and thus this function doesn't really know if 
it is TRY or ACTIVE state (nor should it care).

> +		.pad = CSI2RX_PAD_SINK,
> +		.format = {
> +			.width = 640,
> +			.height = 480,
> +			.code = MEDIA_BUS_FMT_UYVY8_1X16,
> +			.field = V4L2_FIELD_NONE,
> +			.colorspace = V4L2_COLORSPACE_SRGB,
> +			.ycbcr_enc = V4L2_YCBCR_ENC_601,
> +			.quantization = V4L2_QUANTIZATION_LIM_RANGE,
> +			.xfer_func = V4L2_XFER_FUNC_SRGB,
> +		},
> +	};
> +
> +	return csi2rx_set_fmt(subdev, state, &format);
> +}
> +
> +static const struct v4l2_subdev_pad_ops csi2rx_pad_ops = {
> +	.get_fmt	= v4l2_subdev_get_fmt,
> +	.set_fmt	= csi2rx_set_fmt,
> +	.init_cfg	= csi2rx_init_cfg,
> +};
> +
>   static const struct v4l2_subdev_video_ops csi2rx_video_ops = {
>   	.s_stream	= csi2rx_s_stream,
>   };
>   
>   static const struct v4l2_subdev_ops csi2rx_subdev_ops = {
>   	.video		= &csi2rx_video_ops,
> +	.pad		= &csi2rx_pad_ops,
>   };
>   
>   static int csi2rx_async_bound(struct v4l2_async_notifier *notifier,
> @@ -532,9 +630,13 @@ static int csi2rx_probe(struct platform_device *pdev)
>   	if (ret)
>   		goto err_cleanup;
>   
> +	ret = v4l2_subdev_init_finalize(&csi2rx->subdev);
> +	if (ret)
> +		goto err_cleanup;
> +
>   	ret = v4l2_async_register_subdev(&csi2rx->subdev);
>   	if (ret < 0)
> -		goto err_cleanup;
> +		goto err_free_state;
>   
>   	dev_info(&pdev->dev,
>   		 "Probed CSI2RX with %u/%u lanes, %u streams, %s D-PHY\n",
> @@ -544,6 +646,8 @@ static int csi2rx_probe(struct platform_device *pdev)
>   
>   	return 0;
>   
> +err_free_state:
> +	v4l2_subdev_cleanup(&csi2rx->subdev);
>   err_cleanup:
>   	v4l2_async_nf_unregister(&csi2rx->notifier);
>   	v4l2_async_nf_cleanup(&csi2rx->notifier);
> @@ -560,6 +664,7 @@ static void csi2rx_remove(struct platform_device *pdev)
>   	v4l2_async_nf_unregister(&csi2rx->notifier);
>   	v4l2_async_nf_cleanup(&csi2rx->notifier);
>   	v4l2_async_unregister_subdev(&csi2rx->subdev);
> +	v4l2_subdev_cleanup(&csi2rx->subdev);
>   	media_entity_cleanup(&csi2rx->subdev.entity);
>   	kfree(csi2rx);
>   }
> 


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

* Re: [PATCH v8 07/16] media: cadence: csi2rx: Add get_fmt and set_fmt pad ops
@ 2023-08-02  8:48     ` Tomi Valkeinen
  0 siblings, 0 replies; 84+ messages in thread
From: Tomi Valkeinen @ 2023-08-02  8:48 UTC (permalink / raw)
  To: Jai Luthra, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Sakari Ailus,
	Laurent Pinchart
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht

On 31/07/2023 11:29, Jai Luthra wrote:
> From: Pratyush Yadav <p.yadav@ti.com>
> 
> The format is needed to calculate the link speed for the external DPHY
> configuration. It is not right to query the format from the source
> subdev. Add get_fmt and set_fmt pad operations so that the format can be
> configured and correct bpp be selected.
> 
> Initialize and use the v4l2 subdev active state to keep track of the
> active formats. Also propagate the new format from the sink pad to all
> the source pads.
> 
> Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
> Co-authored-by: Jai Luthra <j-luthra@ti.com>
> Signed-off-by: Jai Luthra <j-luthra@ti.com>
> ---
> v7->v8:
> - Use active subdev state to use v4l2_subdev_get_fmt
> - Propagate formats from sink to source pads
> - Drop Laurent's R-by because of the above changes
> 
>   drivers/media/platform/cadence/cdns-csi2rx.c | 107 ++++++++++++++++++++++++++-
>   1 file changed, 106 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/media/platform/cadence/cdns-csi2rx.c b/drivers/media/platform/cadence/cdns-csi2rx.c
> index 83d1fadd592b..4f9654366485 100644
> --- a/drivers/media/platform/cadence/cdns-csi2rx.c
> +++ b/drivers/media/platform/cadence/cdns-csi2rx.c
> @@ -61,6 +61,11 @@ enum csi2rx_pads {
>   	CSI2RX_PAD_MAX,
>   };
>   
> +struct csi2rx_fmt {
> +	u32				code;
> +	u8				bpp;
> +};
> +
>   struct csi2rx_priv {
>   	struct device			*dev;
>   	unsigned int			count;
> @@ -95,6 +100,36 @@ struct csi2rx_priv {
>   	int				source_pad;
>   };
>   
> +static const struct csi2rx_fmt formats[] = {
> +	{
> +		.code	= MEDIA_BUS_FMT_YUYV8_1X16,
> +		.bpp	= 16,
> +	},
> +	{
> +		.code	= MEDIA_BUS_FMT_UYVY8_1X16,
> +		.bpp	= 16,
> +	},
> +	{
> +		.code	= MEDIA_BUS_FMT_YVYU8_1X16,
> +		.bpp	= 16,
> +	},
> +	{
> +		.code	= MEDIA_BUS_FMT_VYUY8_1X16,
> +		.bpp	= 16,
> +	},
> +};

I think you could just squash the "media: cadence: csi2rx: Support RAW8 
and RAW10 formats" into this one. Also, the lines could well be one-liners:

	{ .code	= MEDIA_BUS_FMT_YUYV8_1X16, .bpp = 16, },


> +static const struct csi2rx_fmt *csi2rx_get_fmt_by_code(u32 code)
> +{
> +	unsigned int i;
> +
> +	for (i = 0; i < ARRAY_SIZE(formats); i++)
> +		if (formats[i].code == code)
> +			return &formats[i];
> +
> +	return NULL;
> +}
> +
>   static inline
>   struct csi2rx_priv *v4l2_subdev_to_csi2rx(struct v4l2_subdev *subdev)
>   {
> @@ -303,12 +338,75 @@ static int csi2rx_s_stream(struct v4l2_subdev *subdev, int enable)
>   	return ret;
>   }
>   
> +static int csi2rx_set_fmt(struct v4l2_subdev *subdev,
> +			  struct v4l2_subdev_state *state,
> +			  struct v4l2_subdev_format *format)
> +{
> +	struct v4l2_mbus_framefmt *fmt;
> +	unsigned int i;
> +
> +	/* No transcoding, source and sink formats must match. */
> +	if (format->pad != CSI2RX_PAD_SINK)
> +		return v4l2_subdev_get_fmt(subdev, state, format);
> +
> +	if (!csi2rx_get_fmt_by_code(format->format.code))
> +		format->format.code = formats[0].code;
> +
> +	format->format.field = V4L2_FIELD_NONE;
> +
> +	/* Set sink format */
> +	fmt = v4l2_subdev_get_pad_format(subdev, state, format->pad);
> +	if (!fmt)
> +		return -EINVAL;
> +
> +	*fmt = format->format;
> +
> +	/* Propagate to source formats */
> +	for (i = CSI2RX_PAD_SOURCE_STREAM0; i < CSI2RX_PAD_MAX; i++) {
> +		fmt = v4l2_subdev_get_pad_format(subdev, state, i);
> +		if (!fmt)
> +			return -EINVAL;
> +		*fmt = format->format;
> +	}

Not really part of this patch, but why does csi2rx create more than one 
source pad? It doesn't support streams, so how are those pads used?

> +	return 0;
> +}
> +
> +static int csi2rx_init_cfg(struct v4l2_subdev *subdev,
> +			   struct v4l2_subdev_state *state)
> +{
> +	struct v4l2_subdev_format format = {
> +		.which = state ? V4L2_SUBDEV_FORMAT_TRY
> +			: V4L2_SUBDEV_FORMAT_ACTIVE,

I don't think this is correct. If you enable the active state, you'll 
always get a state here, and thus this function doesn't really know if 
it is TRY or ACTIVE state (nor should it care).

> +		.pad = CSI2RX_PAD_SINK,
> +		.format = {
> +			.width = 640,
> +			.height = 480,
> +			.code = MEDIA_BUS_FMT_UYVY8_1X16,
> +			.field = V4L2_FIELD_NONE,
> +			.colorspace = V4L2_COLORSPACE_SRGB,
> +			.ycbcr_enc = V4L2_YCBCR_ENC_601,
> +			.quantization = V4L2_QUANTIZATION_LIM_RANGE,
> +			.xfer_func = V4L2_XFER_FUNC_SRGB,
> +		},
> +	};
> +
> +	return csi2rx_set_fmt(subdev, state, &format);
> +}
> +
> +static const struct v4l2_subdev_pad_ops csi2rx_pad_ops = {
> +	.get_fmt	= v4l2_subdev_get_fmt,
> +	.set_fmt	= csi2rx_set_fmt,
> +	.init_cfg	= csi2rx_init_cfg,
> +};
> +
>   static const struct v4l2_subdev_video_ops csi2rx_video_ops = {
>   	.s_stream	= csi2rx_s_stream,
>   };
>   
>   static const struct v4l2_subdev_ops csi2rx_subdev_ops = {
>   	.video		= &csi2rx_video_ops,
> +	.pad		= &csi2rx_pad_ops,
>   };
>   
>   static int csi2rx_async_bound(struct v4l2_async_notifier *notifier,
> @@ -532,9 +630,13 @@ static int csi2rx_probe(struct platform_device *pdev)
>   	if (ret)
>   		goto err_cleanup;
>   
> +	ret = v4l2_subdev_init_finalize(&csi2rx->subdev);
> +	if (ret)
> +		goto err_cleanup;
> +
>   	ret = v4l2_async_register_subdev(&csi2rx->subdev);
>   	if (ret < 0)
> -		goto err_cleanup;
> +		goto err_free_state;
>   
>   	dev_info(&pdev->dev,
>   		 "Probed CSI2RX with %u/%u lanes, %u streams, %s D-PHY\n",
> @@ -544,6 +646,8 @@ static int csi2rx_probe(struct platform_device *pdev)
>   
>   	return 0;
>   
> +err_free_state:
> +	v4l2_subdev_cleanup(&csi2rx->subdev);
>   err_cleanup:
>   	v4l2_async_nf_unregister(&csi2rx->notifier);
>   	v4l2_async_nf_cleanup(&csi2rx->notifier);
> @@ -560,6 +664,7 @@ static void csi2rx_remove(struct platform_device *pdev)
>   	v4l2_async_nf_unregister(&csi2rx->notifier);
>   	v4l2_async_nf_cleanup(&csi2rx->notifier);
>   	v4l2_async_unregister_subdev(&csi2rx->subdev);
> +	v4l2_subdev_cleanup(&csi2rx->subdev);
>   	media_entity_cleanup(&csi2rx->subdev.entity);
>   	kfree(csi2rx);
>   }
> 


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v8 08/16] media: cadence: csi2rx: Configure DPHY using link freq
  2023-07-31  8:29   ` Jai Luthra
@ 2023-08-02  9:41     ` Tomi Valkeinen
  -1 siblings, 0 replies; 84+ messages in thread
From: Tomi Valkeinen @ 2023-08-02  9:41 UTC (permalink / raw)
  To: Jai Luthra, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Sakari Ailus,
	Laurent Pinchart
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht

On 31/07/2023 11:29, Jai Luthra wrote:
> From: Pratyush Yadav <p.yadav@ti.com>
> 
> Some platforms like TI's J721E can have the CSI2RX paired with an
> external DPHY. Use the generic PHY framework to configure the DPHY with
> the correct link frequency.
> 
> Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
> Co-authored-by: Jai Luthra <j-luthra@ti.com>
> Signed-off-by: Jai Luthra <j-luthra@ti.com>
> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
> v7->v8
> - Drop original patch in-lieu of already merged
>    https://lore.kernel.org/linux-media/20230523085626.3295-5-jack.zhu@starfivetech.com/
> - Add a new patch to configure DPHY using link_freq control from the
>    source
> 
>   drivers/media/platform/cadence/cdns-csi2rx.c | 25 +++++++++++++++++++++++++
>   1 file changed, 25 insertions(+)
> 
> diff --git a/drivers/media/platform/cadence/cdns-csi2rx.c b/drivers/media/platform/cadence/cdns-csi2rx.c
> index 4f9654366485..2a80c66fb547 100644
> --- a/drivers/media/platform/cadence/cdns-csi2rx.c
> +++ b/drivers/media/platform/cadence/cdns-csi2rx.c
> @@ -149,8 +149,33 @@ static void csi2rx_reset(struct csi2rx_priv *csi2rx)
>   static int csi2rx_configure_ext_dphy(struct csi2rx_priv *csi2rx)
>   {
>   	union phy_configure_opts opts = { };
> +	struct phy_configure_opts_mipi_dphy *cfg = &opts.mipi_dphy;
> +	struct v4l2_subdev_format sd_fmt = {
> +		.which	= V4L2_SUBDEV_FORMAT_ACTIVE,
> +		.pad	= CSI2RX_PAD_SINK,
> +		.stream	= 0,

I would drop the above line, as this doesn't support streams yet.

> +	};
> +	const struct csi2rx_fmt *fmt;
> +	s64 link_freq;
>   	int ret;
>   
> +	ret = v4l2_subdev_call_state_active(&csi2rx->subdev, pad, get_fmt,
> +					    &sd_fmt);
> +	if (ret < 0)
> +		return ret;
> +
> +	fmt = csi2rx_get_fmt_by_code(sd_fmt.format.code);
> +
> +	link_freq = v4l2_get_link_freq(csi2rx->source_subdev->ctrl_handler,
> +				       fmt->bpp, 2 * csi2rx->num_lanes);
> +	if (link_freq < 0)
> +		return link_freq;
> +
> +	ret = phy_mipi_dphy_get_default_config_for_hsclk(link_freq,
> +							 csi2rx->num_lanes, cfg);
> +	if (ret)
> +		return ret;
> +
>   	ret = phy_power_on(csi2rx->dphy);
>   	if (ret)
>   		return ret;
> 

I think this is fine, but a few things to think about:

Here you lock and unlock the active state for the duration of the 
get_fmt call (and you call it for this same subdev). If the driver 
supports active state, and you need to get the fmt of the driver's 
subdev, I think it usually makes more sense to just use the state and 
get the format from there.

And you might want to keep the active state locked for the duration of 
the s_stream operation, in which case the state would already be locked 
when csi2rx_configure_ext_dphy() gets called.

And if you implement enable_streams/disable_streams, then the state has 
already been locked by the framework. However, I think 
enable_streams/disable_streams only works if the driver actually 
supports streams.

But maybe you have already done all these with the out-of-tree streams 
support?

Anyway, I think this is fine for now:

Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>

  Tomi


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

* Re: [PATCH v8 08/16] media: cadence: csi2rx: Configure DPHY using link freq
@ 2023-08-02  9:41     ` Tomi Valkeinen
  0 siblings, 0 replies; 84+ messages in thread
From: Tomi Valkeinen @ 2023-08-02  9:41 UTC (permalink / raw)
  To: Jai Luthra, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Sakari Ailus,
	Laurent Pinchart
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht

On 31/07/2023 11:29, Jai Luthra wrote:
> From: Pratyush Yadav <p.yadav@ti.com>
> 
> Some platforms like TI's J721E can have the CSI2RX paired with an
> external DPHY. Use the generic PHY framework to configure the DPHY with
> the correct link frequency.
> 
> Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
> Co-authored-by: Jai Luthra <j-luthra@ti.com>
> Signed-off-by: Jai Luthra <j-luthra@ti.com>
> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
> v7->v8
> - Drop original patch in-lieu of already merged
>    https://lore.kernel.org/linux-media/20230523085626.3295-5-jack.zhu@starfivetech.com/
> - Add a new patch to configure DPHY using link_freq control from the
>    source
> 
>   drivers/media/platform/cadence/cdns-csi2rx.c | 25 +++++++++++++++++++++++++
>   1 file changed, 25 insertions(+)
> 
> diff --git a/drivers/media/platform/cadence/cdns-csi2rx.c b/drivers/media/platform/cadence/cdns-csi2rx.c
> index 4f9654366485..2a80c66fb547 100644
> --- a/drivers/media/platform/cadence/cdns-csi2rx.c
> +++ b/drivers/media/platform/cadence/cdns-csi2rx.c
> @@ -149,8 +149,33 @@ static void csi2rx_reset(struct csi2rx_priv *csi2rx)
>   static int csi2rx_configure_ext_dphy(struct csi2rx_priv *csi2rx)
>   {
>   	union phy_configure_opts opts = { };
> +	struct phy_configure_opts_mipi_dphy *cfg = &opts.mipi_dphy;
> +	struct v4l2_subdev_format sd_fmt = {
> +		.which	= V4L2_SUBDEV_FORMAT_ACTIVE,
> +		.pad	= CSI2RX_PAD_SINK,
> +		.stream	= 0,

I would drop the above line, as this doesn't support streams yet.

> +	};
> +	const struct csi2rx_fmt *fmt;
> +	s64 link_freq;
>   	int ret;
>   
> +	ret = v4l2_subdev_call_state_active(&csi2rx->subdev, pad, get_fmt,
> +					    &sd_fmt);
> +	if (ret < 0)
> +		return ret;
> +
> +	fmt = csi2rx_get_fmt_by_code(sd_fmt.format.code);
> +
> +	link_freq = v4l2_get_link_freq(csi2rx->source_subdev->ctrl_handler,
> +				       fmt->bpp, 2 * csi2rx->num_lanes);
> +	if (link_freq < 0)
> +		return link_freq;
> +
> +	ret = phy_mipi_dphy_get_default_config_for_hsclk(link_freq,
> +							 csi2rx->num_lanes, cfg);
> +	if (ret)
> +		return ret;
> +
>   	ret = phy_power_on(csi2rx->dphy);
>   	if (ret)
>   		return ret;
> 

I think this is fine, but a few things to think about:

Here you lock and unlock the active state for the duration of the 
get_fmt call (and you call it for this same subdev). If the driver 
supports active state, and you need to get the fmt of the driver's 
subdev, I think it usually makes more sense to just use the state and 
get the format from there.

And you might want to keep the active state locked for the duration of 
the s_stream operation, in which case the state would already be locked 
when csi2rx_configure_ext_dphy() gets called.

And if you implement enable_streams/disable_streams, then the state has 
already been locked by the framework. However, I think 
enable_streams/disable_streams only works if the driver actually 
supports streams.

But maybe you have already done all these with the out-of-tree streams 
support?

Anyway, I think this is fine for now:

Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>

  Tomi


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v8 10/16] media: cadence: csi2rx: Set the STOP bit when stopping a stream
  2023-07-31  8:29   ` Jai Luthra
@ 2023-08-02  9:45     ` Tomi Valkeinen
  -1 siblings, 0 replies; 84+ messages in thread
From: Tomi Valkeinen @ 2023-08-02  9:45 UTC (permalink / raw)
  To: Jai Luthra, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Sakari Ailus,
	Laurent Pinchart
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht

On 31/07/2023 11:29, Jai Luthra wrote:
> From: Pratyush Yadav <p.yadav@ti.com>
> 
> The stream stop procedure says that the STOP bit should be set when the
> stream is to be stopped, and then the ready bit in stream status
> register polled to make sure the STOP operation is finished.
> 
> Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
> Signed-off-by: Jai Luthra <j-luthra@ti.com>
> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
> v7->v8:
> - Fix bug where intention was to wait till stream status is idle, i.e.
>    STREAM_STATUS[31] -> 0 - but we were instead checking the opposite
> 
>   drivers/media/platform/cadence/cdns-csi2rx.c | 18 +++++++++++++++++-
>   1 file changed, 17 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/media/platform/cadence/cdns-csi2rx.c b/drivers/media/platform/cadence/cdns-csi2rx.c
> index 30cdc260b46a..a17ef88dff82 100644
> --- a/drivers/media/platform/cadence/cdns-csi2rx.c
> +++ b/drivers/media/platform/cadence/cdns-csi2rx.c
> @@ -8,6 +8,7 @@
>   #include <linux/clk.h>
>   #include <linux/delay.h>
>   #include <linux/io.h>
> +#include <linux/iopoll.h>
>   #include <linux/module.h>
>   #include <linux/of.h>
>   #include <linux/of_graph.h>
> @@ -41,8 +42,12 @@
>   
>   #define CSI2RX_STREAM_CTRL_REG(n)		(CSI2RX_STREAM_BASE(n) + 0x000)
>   #define CSI2RX_STREAM_CTRL_SOFT_RST			BIT(4)
> +#define CSI2RX_STREAM_CTRL_STOP				BIT(1)
>   #define CSI2RX_STREAM_CTRL_START			BIT(0)
>   
> +#define CSI2RX_STREAM_STATUS_REG(n)		(CSI2RX_STREAM_BASE(n) + 0x004)
> +#define CSI2RX_STREAM_STATUS_RDY			BIT(31)
> +
>   #define CSI2RX_STREAM_DATA_CFG_REG(n)		(CSI2RX_STREAM_BASE(n) + 0x008)
>   #define CSI2RX_STREAM_DATA_CFG_EN_VC_SELECT		BIT(31)
>   #define CSI2RX_STREAM_DATA_CFG_VC_SELECT(n)		BIT((n) + 16)
> @@ -314,13 +319,24 @@ static int csi2rx_start(struct csi2rx_priv *csi2rx)
>   static void csi2rx_stop(struct csi2rx_priv *csi2rx)
>   {
>   	unsigned int i;
> +	u32 val;
> +	int ret;
>   
>   	clk_prepare_enable(csi2rx->p_clk);
>   	reset_control_assert(csi2rx->sys_rst);
>   	clk_disable_unprepare(csi2rx->sys_clk);
>   
>   	for (i = 0; i < csi2rx->max_streams; i++) {
> -		writel(0, csi2rx->base + CSI2RX_STREAM_CTRL_REG(i));
> +		writel(CSI2RX_STREAM_CTRL_STOP,
> +		       csi2rx->base + CSI2RX_STREAM_CTRL_REG(i));
> +
> +		ret = readl_relaxed_poll_timeout(csi2rx->base +
> +						 CSI2RX_STREAM_STATUS_REG(i),
> +						 val,
> +						 !(val & CSI2RX_STREAM_STATUS_RDY),
> +						 10, 10000);
> +		if (ret)
> +			dev_warn(csi2rx->dev, "Failed to stop stream%u\n", i);

When adding streams support, I think the driver might need some 
adjustments. E.g. above says that e.g. stopping stream2 failed, which 
will be quite confusing as the reader probably thinks it refers to the 
"logical" streams. It would be helpful if it was always clear which of 
the streams the driver refers to (in prints, but also in code).

Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>

  Tomi


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

* Re: [PATCH v8 10/16] media: cadence: csi2rx: Set the STOP bit when stopping a stream
@ 2023-08-02  9:45     ` Tomi Valkeinen
  0 siblings, 0 replies; 84+ messages in thread
From: Tomi Valkeinen @ 2023-08-02  9:45 UTC (permalink / raw)
  To: Jai Luthra, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Sakari Ailus,
	Laurent Pinchart
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht

On 31/07/2023 11:29, Jai Luthra wrote:
> From: Pratyush Yadav <p.yadav@ti.com>
> 
> The stream stop procedure says that the STOP bit should be set when the
> stream is to be stopped, and then the ready bit in stream status
> register polled to make sure the STOP operation is finished.
> 
> Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
> Signed-off-by: Jai Luthra <j-luthra@ti.com>
> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
> v7->v8:
> - Fix bug where intention was to wait till stream status is idle, i.e.
>    STREAM_STATUS[31] -> 0 - but we were instead checking the opposite
> 
>   drivers/media/platform/cadence/cdns-csi2rx.c | 18 +++++++++++++++++-
>   1 file changed, 17 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/media/platform/cadence/cdns-csi2rx.c b/drivers/media/platform/cadence/cdns-csi2rx.c
> index 30cdc260b46a..a17ef88dff82 100644
> --- a/drivers/media/platform/cadence/cdns-csi2rx.c
> +++ b/drivers/media/platform/cadence/cdns-csi2rx.c
> @@ -8,6 +8,7 @@
>   #include <linux/clk.h>
>   #include <linux/delay.h>
>   #include <linux/io.h>
> +#include <linux/iopoll.h>
>   #include <linux/module.h>
>   #include <linux/of.h>
>   #include <linux/of_graph.h>
> @@ -41,8 +42,12 @@
>   
>   #define CSI2RX_STREAM_CTRL_REG(n)		(CSI2RX_STREAM_BASE(n) + 0x000)
>   #define CSI2RX_STREAM_CTRL_SOFT_RST			BIT(4)
> +#define CSI2RX_STREAM_CTRL_STOP				BIT(1)
>   #define CSI2RX_STREAM_CTRL_START			BIT(0)
>   
> +#define CSI2RX_STREAM_STATUS_REG(n)		(CSI2RX_STREAM_BASE(n) + 0x004)
> +#define CSI2RX_STREAM_STATUS_RDY			BIT(31)
> +
>   #define CSI2RX_STREAM_DATA_CFG_REG(n)		(CSI2RX_STREAM_BASE(n) + 0x008)
>   #define CSI2RX_STREAM_DATA_CFG_EN_VC_SELECT		BIT(31)
>   #define CSI2RX_STREAM_DATA_CFG_VC_SELECT(n)		BIT((n) + 16)
> @@ -314,13 +319,24 @@ static int csi2rx_start(struct csi2rx_priv *csi2rx)
>   static void csi2rx_stop(struct csi2rx_priv *csi2rx)
>   {
>   	unsigned int i;
> +	u32 val;
> +	int ret;
>   
>   	clk_prepare_enable(csi2rx->p_clk);
>   	reset_control_assert(csi2rx->sys_rst);
>   	clk_disable_unprepare(csi2rx->sys_clk);
>   
>   	for (i = 0; i < csi2rx->max_streams; i++) {
> -		writel(0, csi2rx->base + CSI2RX_STREAM_CTRL_REG(i));
> +		writel(CSI2RX_STREAM_CTRL_STOP,
> +		       csi2rx->base + CSI2RX_STREAM_CTRL_REG(i));
> +
> +		ret = readl_relaxed_poll_timeout(csi2rx->base +
> +						 CSI2RX_STREAM_STATUS_REG(i),
> +						 val,
> +						 !(val & CSI2RX_STREAM_STATUS_RDY),
> +						 10, 10000);
> +		if (ret)
> +			dev_warn(csi2rx->dev, "Failed to stop stream%u\n", i);

When adding streams support, I think the driver might need some 
adjustments. E.g. above says that e.g. stopping stream2 failed, which 
will be quite confusing as the reader probably thinks it refers to the 
"logical" streams. It would be helpful if it was always clear which of 
the streams the driver refers to (in prints, but also in code).

Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>

  Tomi


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v8 14/16] media: cadence: csi2rx: Support RAW8 and RAW10 formats
  2023-07-31  8:29   ` Jai Luthra
@ 2023-08-02  9:46     ` Tomi Valkeinen
  -1 siblings, 0 replies; 84+ messages in thread
From: Tomi Valkeinen @ 2023-08-02  9:46 UTC (permalink / raw)
  To: Jai Luthra, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Sakari Ailus,
	Laurent Pinchart
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht

On 31/07/2023 11:29, Jai Luthra wrote:
> Many CSI-2 sensors (specifically IMX219) send RAW bayer data instead of
> processed YUV or RGB, so add support for 8-bit and 10-bit bayer formats.
> 
> Signed-off-by: Jai Luthra <j-luthra@ti.com>
> ---
> New in v8
> 
>   drivers/media/platform/cadence/cdns-csi2rx.c | 32 ++++++++++++++++++++++++++++
>   1 file changed, 32 insertions(+)
> 
> diff --git a/drivers/media/platform/cadence/cdns-csi2rx.c b/drivers/media/platform/cadence/cdns-csi2rx.c
> index aec33d28a66f..bac74474841a 100644
> --- a/drivers/media/platform/cadence/cdns-csi2rx.c
> +++ b/drivers/media/platform/cadence/cdns-csi2rx.c
> @@ -122,6 +122,38 @@ static const struct csi2rx_fmt formats[] = {
>   		.code	= MEDIA_BUS_FMT_VYUY8_1X16,
>   		.bpp	= 16,
>   	},
> +	{
> +		.code	= MEDIA_BUS_FMT_SBGGR8_1X8,
> +		.bpp	= 8,
> +	},
> +	{
> +		.code	= MEDIA_BUS_FMT_SGBRG8_1X8,
> +		.bpp	= 8,
> +	},
> +	{
> +		.code	= MEDIA_BUS_FMT_SGRBG8_1X8,
> +		.bpp	= 8,
> +	},
> +	{
> +		.code	= MEDIA_BUS_FMT_SRGGB8_1X8,
> +		.bpp	= 8,
> +	},
> +	{
> +		.code	= MEDIA_BUS_FMT_SBGGR10_1X10,
> +		.bpp	= 10,
> +	},
> +	{
> +		.code	= MEDIA_BUS_FMT_SGBRG10_1X10,
> +		.bpp	= 10,
> +	},
> +	{
> +		.code	= MEDIA_BUS_FMT_SGRBG10_1X10,
> +		.bpp	= 10,
> +	},
> +	{
> +		.code	= MEDIA_BUS_FMT_SRGGB10_1X10,
> +		.bpp	= 10,
> +	},
>   };
>   
>   static const struct csi2rx_fmt *csi2rx_get_fmt_by_code(u32 code)
> 

Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>

  Tomi


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

* Re: [PATCH v8 14/16] media: cadence: csi2rx: Support RAW8 and RAW10 formats
@ 2023-08-02  9:46     ` Tomi Valkeinen
  0 siblings, 0 replies; 84+ messages in thread
From: Tomi Valkeinen @ 2023-08-02  9:46 UTC (permalink / raw)
  To: Jai Luthra, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Sakari Ailus,
	Laurent Pinchart
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht

On 31/07/2023 11:29, Jai Luthra wrote:
> Many CSI-2 sensors (specifically IMX219) send RAW bayer data instead of
> processed YUV or RGB, so add support for 8-bit and 10-bit bayer formats.
> 
> Signed-off-by: Jai Luthra <j-luthra@ti.com>
> ---
> New in v8
> 
>   drivers/media/platform/cadence/cdns-csi2rx.c | 32 ++++++++++++++++++++++++++++
>   1 file changed, 32 insertions(+)
> 
> diff --git a/drivers/media/platform/cadence/cdns-csi2rx.c b/drivers/media/platform/cadence/cdns-csi2rx.c
> index aec33d28a66f..bac74474841a 100644
> --- a/drivers/media/platform/cadence/cdns-csi2rx.c
> +++ b/drivers/media/platform/cadence/cdns-csi2rx.c
> @@ -122,6 +122,38 @@ static const struct csi2rx_fmt formats[] = {
>   		.code	= MEDIA_BUS_FMT_VYUY8_1X16,
>   		.bpp	= 16,
>   	},
> +	{
> +		.code	= MEDIA_BUS_FMT_SBGGR8_1X8,
> +		.bpp	= 8,
> +	},
> +	{
> +		.code	= MEDIA_BUS_FMT_SGBRG8_1X8,
> +		.bpp	= 8,
> +	},
> +	{
> +		.code	= MEDIA_BUS_FMT_SGRBG8_1X8,
> +		.bpp	= 8,
> +	},
> +	{
> +		.code	= MEDIA_BUS_FMT_SRGGB8_1X8,
> +		.bpp	= 8,
> +	},
> +	{
> +		.code	= MEDIA_BUS_FMT_SBGGR10_1X10,
> +		.bpp	= 10,
> +	},
> +	{
> +		.code	= MEDIA_BUS_FMT_SGBRG10_1X10,
> +		.bpp	= 10,
> +	},
> +	{
> +		.code	= MEDIA_BUS_FMT_SGRBG10_1X10,
> +		.bpp	= 10,
> +	},
> +	{
> +		.code	= MEDIA_BUS_FMT_SRGGB10_1X10,
> +		.bpp	= 10,
> +	},
>   };
>   
>   static const struct csi2rx_fmt *csi2rx_get_fmt_by_code(u32 code)
> 

Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>

  Tomi


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v8 16/16] media: ti: Add CSI2RX support for J721E
  2023-07-31  8:29   ` Jai Luthra
@ 2023-08-02 11:04     ` Tomi Valkeinen
  -1 siblings, 0 replies; 84+ messages in thread
From: Tomi Valkeinen @ 2023-08-02 11:04 UTC (permalink / raw)
  To: Jai Luthra, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Sakari Ailus,
	Laurent Pinchart
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht

On 31/07/2023 11:29, Jai Luthra wrote:
> From: Pratyush Yadav <p.yadav@ti.com>
> 
> TI's J721E uses the Cadence CSI2RX and DPHY peripherals to facilitate
> capture over a CSI-2 bus.
> 
> The Cadence CSI2RX IP acts as a bridge between the TI specific parts and
> the CSI-2 protocol parts. TI then has a wrapper on top of this bridge
> called the SHIM layer. It takes in data from stream 0, repacks it, and
> sends it to memory over PSI-L DMA.
> 
> This driver acts as the "front end" to V4L2 client applications. It
> implements the required ioctls and buffer operations, passes the
> necessary calls on to the bridge, programs the SHIM layer, and performs
> DMA via the dmaengine API to finally return the data to a buffer
> supplied by the application.
> 
> Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
> Co-authored-by: Vaishnav Achath <vaishnav.a@ti.com>
> Signed-off-by: Vaishnav Achath <vaishnav.a@ti.com>
> Co-authored-by: Jai Luthra <j-luthra@ti.com>
> Signed-off-by: Jai Luthra <j-luthra@ti.com>
> ---
> v7->v8:
> - Move after dt-bindings to keep the series bisectable
> - Rename compatible to "ti,j721e-csi2rx-shim" to distinguish from the
>    SoC-specific CSI2RX bridge compatible
> - Make myself the Maintainer
> - Support RAW8 and RAW10 formats, and setting the pixel-unwrap size on
>    SHIM (RAW10 is stored in 16-bit containers, while RAW8 in 8-bit containers)
> - Fix enum_fmt_vid_cap() to respect CAP_IO_MC and only list pixelformats
>    matching the mbus formats set on the subdev.
> - Fix enum_framesizes() to stop enumerating more than a single framesize
>    (reject non-zero fsize->index)
> - Simplify notifier bound fucntion to use v4l2_create_fwnode_links_to_pad()
>    and inline the video_register() method
> - Add support for draining the DMA with an extra buffer, to get rid of
>    stale data in the pipeline on stream stop (or when frames start
>    getting dropped due to load)
> - Queue all available buffers to DMAEngine in the callback, also use a
>    separate "submitted" queue to track all buffers submitted to DMA
> - Use video_device_pipeline_start() instead of media_pipeline_start()
> - Drop support for VB_READ
> - Print issues in link validation as DEBUG instead of ERROR
> - s/async_subdev/async_connection
> 
>   MAINTAINERS                                        |    7 +
>   drivers/media/platform/ti/Kconfig                  |   12 +
>   drivers/media/platform/ti/Makefile                 |    1 +
>   drivers/media/platform/ti/j721e-csi2rx/Makefile    |    2 +
>   .../media/platform/ti/j721e-csi2rx/j721e-csi2rx.c  | 1127 ++++++++++++++++++++
>   5 files changed, 1149 insertions(+)
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index d7b867c57920..1c2d75c30ce7 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -21445,6 +21445,13 @@ F:	Documentation/devicetree/bindings/media/i2c/ti,ds90*
>   F:	drivers/media/i2c/ds90*
>   F:	include/media/i2c/ds90*
>   
> +TI J721E CSI2RX DRIVER
> +M:	Jai Luthra <j-luthra@ti.com>
> +L:	linux-media@vger.kernel.org
> +S:	Maintained
> +F:	Documentation/devicetree/bindings/media/ti,j721e-csi2rx.yaml
> +F:	drivers/media/platform/ti/j721e-csi2rx/
> +
>   TI KEYSTONE MULTICORE NAVIGATOR DRIVERS
>   M:	Nishanth Menon <nm@ti.com>
>   M:	Santosh Shilimkar <ssantosh@kernel.org>
> diff --git a/drivers/media/platform/ti/Kconfig b/drivers/media/platform/ti/Kconfig
> index e1ab56c3be1f..42c908f6e1ae 100644
> --- a/drivers/media/platform/ti/Kconfig
> +++ b/drivers/media/platform/ti/Kconfig
> @@ -63,6 +63,18 @@ config VIDEO_TI_VPE_DEBUG
>   	help
>   	  Enable debug messages on VPE driver.
>   
> +config VIDEO_TI_J721E_CSI2RX
> +	tristate "TI J721E CSI2RX wrapper layer driver"
> +	depends on VIDEO_DEV && VIDEO_V4L2_SUBDEV_API
> +	depends on MEDIA_SUPPORT && MEDIA_CONTROLLER
> +	depends on PHY_CADENCE_DPHY_RX && VIDEO_CADENCE_CSI2RX
> +	depends on ARCH_K3 || COMPILE_TEST
> +	select VIDEOBUF2_DMA_CONTIG
> +	select V4L2_FWNODE
> +	help
> +	  Support for TI CSI2RX wrapper layer. This just enables the wrapper driver.
> +	  The Cadence CSI2RX bridge driver needs to be enabled separately.
> +
>   source "drivers/media/platform/ti/am437x/Kconfig"
>   source "drivers/media/platform/ti/davinci/Kconfig"
>   source "drivers/media/platform/ti/omap/Kconfig"
> diff --git a/drivers/media/platform/ti/Makefile b/drivers/media/platform/ti/Makefile
> index 98c5fe5c40d6..8a2f74c9380e 100644
> --- a/drivers/media/platform/ti/Makefile
> +++ b/drivers/media/platform/ti/Makefile
> @@ -3,5 +3,6 @@ obj-y += am437x/
>   obj-y += cal/
>   obj-y += vpe/
>   obj-y += davinci/
> +obj-y += j721e-csi2rx/
>   obj-y += omap/
>   obj-y += omap3isp/
> diff --git a/drivers/media/platform/ti/j721e-csi2rx/Makefile b/drivers/media/platform/ti/j721e-csi2rx/Makefile
> new file mode 100644
> index 000000000000..377afc1d6280
> --- /dev/null
> +++ b/drivers/media/platform/ti/j721e-csi2rx/Makefile
> @@ -0,0 +1,2 @@
> +# SPDX-License-Identifier: GPL-2.0
> +obj-$(CONFIG_VIDEO_TI_J721E_CSI2RX) += j721e-csi2rx.o
> diff --git a/drivers/media/platform/ti/j721e-csi2rx/j721e-csi2rx.c b/drivers/media/platform/ti/j721e-csi2rx/j721e-csi2rx.c
> new file mode 100644
> index 000000000000..29f1879cfc25
> --- /dev/null
> +++ b/drivers/media/platform/ti/j721e-csi2rx/j721e-csi2rx.c
> @@ -0,0 +1,1127 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * TI CSI2RX Shim Wrapper Driver
> + *
> + * Copyright (C) 2021 Texas Instruments Incorporated - https://www.ti.com/

You can update the year above.

> + * Author: Pratyush Yadav <p.yadav@ti.com>
> + */
> +
> +#include <linux/bitfield.h>
> +#include <linux/dmaengine.h>
> +#include <linux/module.h>
> +#include <linux/of_platform.h>
> +#include <linux/platform_device.h>
> +
> +#include <media/mipi-csi2.h>
> +#include <media/v4l2-device.h>
> +#include <media/v4l2-ioctl.h>
> +#include <media/v4l2-mc.h>
> +#include <media/videobuf2-dma-contig.h>
> +
> +#define TI_CSI2RX_MODULE_NAME		"j721e-csi2rx"
> +
> +#define SHIM_CNTL			0x10
> +#define SHIM_CNTL_PIX_RST		BIT(0)
> +
> +#define SHIM_DMACNTX			0x20
> +#define SHIM_DMACNTX_EN			BIT(31)
> +#define SHIM_DMACNTX_YUV422		GENMASK(27, 26)
> +#define SHIM_DMACNTX_SIZE		GENMASK(21, 20)
> +#define SHIM_DMACNTX_FMT		GENMASK(5, 0)
> +#define SHIM_DMACNTX_UYVY		0
> +#define SHIM_DMACNTX_VYUY		1
> +#define SHIM_DMACNTX_YUYV		2
> +#define SHIM_DMACNTX_YVYU		3
> +#define SHIM_DMACNTX_SIZE_8		0
> +#define SHIM_DMACNTX_SIZE_16		1
> +#define SHIM_DMACNTX_SIZE_32		2
> +
> +#define SHIM_PSI_CFG0			0x24
> +#define SHIM_PSI_CFG0_SRC_TAG		GENMASK(15, 0)
> +#define SHIM_PSI_CFG0_DST_TAG		GENMASK(31, 16)
> +
> +#define PSIL_WORD_SIZE_BYTES		16
> +/*
> + * There are no hard limits on the width or height. The DMA engine can handle
> + * all sizes. The max width and height are arbitrary numbers for this driver.
> + * Use 16K * 16K as the arbitrary limit. It is large enough that it is unlikely
> + * the limit will be hit in practice.
> + */
> +#define MAX_WIDTH_BYTES			SZ_16K
> +#define MAX_HEIGHT_LINES		SZ_16K
> +
> +#define DRAIN_TIMEOUT_MS		50
> +
> +struct ti_csi2rx_fmt {
> +	u32				fourcc;	/* Four character code. */
> +	u32				code;	/* Mbus code. */
> +	u32				csi_dt;	/* CSI Data type. */
> +	u8				bpp;	/* Bits per pixel. */
> +	u8				size;	/* Data size shift when unpacking. */
> +};
> +
> +struct ti_csi2rx_buffer {
> +	/* Common v4l2 buffer. Must be first. */
> +	struct vb2_v4l2_buffer		vb;
> +	struct list_head		list;
> +	struct ti_csi2rx_dev		*csi;
> +};
> +
> +enum ti_csi2rx_dma_state {
> +	TI_CSI2RX_DMA_STOPPED,	/* Streaming not started yet. */
> +	TI_CSI2RX_DMA_IDLE,	/* Streaming but no pending DMA operation. */
> +	TI_CSI2RX_DMA_ACTIVE,	/* Streaming and pending DMA operation. */
> +};
> +
> +struct ti_csi2rx_dma {
> +	/* Protects all fields in this struct. */
> +	spinlock_t			lock;
> +	struct dma_chan			*chan;
> +	/* Buffers queued to the driver, waiting to be processed by DMA. */
> +	struct list_head		queue;
> +	enum ti_csi2rx_dma_state	state;
> +	/*
> +	 * Queue of buffers submitted to DMA engine.
> +	 */
> +	struct list_head		submitted;
> +};
> +
> +struct ti_csi2rx_dev {
> +	struct device			*dev;
> +	void __iomem			*shim;
> +	struct v4l2_device		v4l2_dev;
> +	struct video_device		vdev;
> +	struct media_device		mdev;
> +	struct media_pipeline		pipe;
> +	struct media_pad		pad;
> +	struct v4l2_async_notifier	notifier;
> +	struct v4l2_subdev		*subdev;

I think "source_subdev" is a better name, to make it clear it's not 
referring to a subdev owned by this driver.

> +	struct vb2_queue		vidq;
> +	struct mutex			mutex; /* To serialize ioctls. */
> +	struct v4l2_format		v_fmt;
> +	struct ti_csi2rx_dma		dma;
> +	u32				sequence;
> +};
> +
> +static const struct ti_csi2rx_fmt formats[] = {
> +	{
> +		.fourcc			= V4L2_PIX_FMT_YUYV,
> +		.code			= MEDIA_BUS_FMT_YUYV8_1X16,
> +		.csi_dt			= MIPI_CSI2_DT_YUV422_8B,
> +		.bpp			= 16,
> +		.size			= SHIM_DMACNTX_SIZE_8,
> +	}, {
> +		.fourcc			= V4L2_PIX_FMT_UYVY,
> +		.code			= MEDIA_BUS_FMT_UYVY8_1X16,
> +		.csi_dt			= MIPI_CSI2_DT_YUV422_8B,
> +		.bpp			= 16,
> +		.size			= SHIM_DMACNTX_SIZE_8,
> +	}, {
> +		.fourcc			= V4L2_PIX_FMT_YVYU,
> +		.code			= MEDIA_BUS_FMT_YVYU8_1X16,
> +		.csi_dt			= MIPI_CSI2_DT_YUV422_8B,
> +		.bpp			= 16,
> +		.size			= SHIM_DMACNTX_SIZE_8,
> +	}, {
> +		.fourcc			= V4L2_PIX_FMT_VYUY,
> +		.code			= MEDIA_BUS_FMT_VYUY8_1X16,
> +		.csi_dt			= MIPI_CSI2_DT_YUV422_8B,
> +		.bpp			= 16,
> +		.size			= SHIM_DMACNTX_SIZE_8,
> +	}, {
> +		.fourcc			= V4L2_PIX_FMT_SBGGR8,
> +		.code			= MEDIA_BUS_FMT_SBGGR8_1X8,
> +		.csi_dt			= MIPI_CSI2_DT_RAW8,
> +		.bpp			= 8,
> +		.size			= SHIM_DMACNTX_SIZE_8,
> +	}, {
> +		.fourcc			= V4L2_PIX_FMT_SGBRG8,
> +		.code			= MEDIA_BUS_FMT_SGBRG8_1X8,
> +		.csi_dt			= MIPI_CSI2_DT_RAW8,
> +		.bpp			= 8,
> +		.size			= SHIM_DMACNTX_SIZE_8,
> +	}, {
> +		.fourcc			= V4L2_PIX_FMT_SGRBG8,
> +		.code			= MEDIA_BUS_FMT_SGRBG8_1X8,
> +		.csi_dt			= MIPI_CSI2_DT_RAW8,
> +		.bpp			= 8,
> +		.size			= SHIM_DMACNTX_SIZE_8,
> +	}, {
> +		.fourcc			= V4L2_PIX_FMT_SRGGB8,
> +		.code			= MEDIA_BUS_FMT_SRGGB8_1X8,
> +		.csi_dt			= MIPI_CSI2_DT_RAW8,
> +		.bpp			= 8,
> +		.size			= SHIM_DMACNTX_SIZE_8,
> +	}, {
> +		.fourcc			= V4L2_PIX_FMT_SBGGR10,
> +		.code			= MEDIA_BUS_FMT_SBGGR10_1X10,
> +		.csi_dt			= MIPI_CSI2_DT_RAW10,
> +		.bpp			= 16,
> +		.size			= SHIM_DMACNTX_SIZE_16,
> +	}, {
> +		.fourcc			= V4L2_PIX_FMT_SGBRG10,
> +		.code			= MEDIA_BUS_FMT_SGBRG10_1X10,
> +		.csi_dt			= MIPI_CSI2_DT_RAW10,
> +		.bpp			= 16,
> +		.size			= SHIM_DMACNTX_SIZE_16,
> +	}, {
> +		.fourcc			= V4L2_PIX_FMT_SGRBG10,
> +		.code			= MEDIA_BUS_FMT_SGRBG10_1X10,
> +		.csi_dt			= MIPI_CSI2_DT_RAW10,
> +		.bpp			= 16,
> +		.size			= SHIM_DMACNTX_SIZE_16,
> +	}, {
> +		.fourcc			= V4L2_PIX_FMT_SRGGB10,
> +		.code			= MEDIA_BUS_FMT_SRGGB10_1X10,
> +		.csi_dt			= MIPI_CSI2_DT_RAW10,
> +		.bpp			= 16,
> +		.size			= SHIM_DMACNTX_SIZE_16,
> +	},
> +
> +	/* More formats can be supported but they are not listed for now. */
> +};
> +
> +static const unsigned int num_formats = ARRAY_SIZE(formats);
> +
> +/* Forward declaration needed by ti_csi2rx_dma_callback. */
> +static int ti_csi2rx_start_dma(struct ti_csi2rx_dev *csi,
> +			       struct ti_csi2rx_buffer *buf);
> +
> +static const struct ti_csi2rx_fmt *find_format_by_pix(u32 pixelformat)
> +{
> +	unsigned int i;
> +
> +	for (i = 0; i < num_formats; i++) {
> +		if (formats[i].fourcc == pixelformat)
> +			return &formats[i];
> +	}
> +
> +	return NULL;
> +}
> +
> +static const struct ti_csi2rx_fmt *find_format_by_code(u32 code)
> +{
> +	unsigned int i;
> +
> +	for (i = 0; i < num_formats; i++) {
> +		if (formats[i].code == code)
> +			return &formats[i];
> +	}
> +
> +	return NULL;
> +}
> +
> +static void ti_csi2rx_fill_fmt(const struct ti_csi2rx_fmt *csi_fmt,
> +			       struct v4l2_format *v4l2_fmt)
> +{
> +	struct v4l2_pix_format *pix = &v4l2_fmt->fmt.pix;
> +	unsigned int pixels_in_word;
> +	u8 bpp = csi_fmt->bpp;
> +	u32 bpl;
> +
> +	pixels_in_word = PSIL_WORD_SIZE_BYTES * 8 / bpp;
> +
> +	pix->width = clamp_t(unsigned int, pix->width,
> +			     pixels_in_word,
> +			     MAX_WIDTH_BYTES * 8 / bpp);
> +	pix->width = rounddown(pix->width, pixels_in_word);
> +
> +	pix->height = clamp_t(unsigned int, pix->height, 1, MAX_HEIGHT_LINES);
> +
> +	v4l2_fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
> +	pix->pixelformat = csi_fmt->fourcc;
> +	pix->colorspace = V4L2_COLORSPACE_SRGB;
> +	pix->sizeimage = pix->height * pix->width * (bpp / 8);
> +
> +	bpl = (pix->width * ALIGN(bpp, 8)) >> 3;

You do "/ 8" and "* 8" elsewhere in the function, so I think it makes 
sense to "/ 8" here too, instead of ">> 3".

Is this correct? Why is aligned bpp used here, but when calculating 
sizeimage, bpp is not aligned?

> +	pix->bytesperline = ALIGN(bpl, 16);

Why align to 16?

Shouldn't sizeimage usually be bytesperline * height?

You could add a few comments here to clarify all the aligns, roundings 
and clampings.

> +}
> +
> +static int ti_csi2rx_querycap(struct file *file, void *priv,
> +			      struct v4l2_capability *cap)
> +{
> +	strscpy(cap->driver, TI_CSI2RX_MODULE_NAME, sizeof(cap->driver));
> +	strscpy(cap->card, TI_CSI2RX_MODULE_NAME, sizeof(cap->card));
> +
> +	return 0;
> +}
> +
> +static int ti_csi2rx_enum_fmt_vid_cap(struct file *file, void *priv,
> +				      struct v4l2_fmtdesc *f)
> +{
> +	const struct ti_csi2rx_fmt *fmt = NULL;
> +
> +	if (f->mbus_code) {
> +		if (f->index > 0)
> +			return -EINVAL;

This fails to enumerate the formats if mbus_code is set, doesn't it?

> +
> +		fmt = find_format_by_code(f->mbus_code);
> +	} else {
> +		if (f->index >= num_formats)
> +			return -EINVAL;
> +
> +		fmt = &formats[f->index];
> +	}
> +
> +	if (!fmt)
> +		return -EINVAL;
> +
> +	f->pixelformat = fmt->fourcc;
> +	memset(f->reserved, 0, sizeof(f->reserved));
> +	f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
> +
> +	return 0;
> +}
> +
> +static int ti_csi2rx_g_fmt_vid_cap(struct file *file, void *prov,
> +				   struct v4l2_format *f)
> +{
> +	struct ti_csi2rx_dev *csi = video_drvdata(file);
> +
> +	*f = csi->v_fmt;
> +
> +	return 0;
> +}
> +
> +static int ti_csi2rx_try_fmt_vid_cap(struct file *file, void *priv,
> +				     struct v4l2_format *f)
> +{
> +	const struct ti_csi2rx_fmt *fmt;
> +
> +	/*
> +	 * Default to the first format if the requested pixel format code isn't
> +	 * supported.
> +	 */
> +	fmt = find_format_by_pix(f->fmt.pix.pixelformat);
> +	if (!fmt)
> +		fmt = &formats[0];
> +
> +	if (f->fmt.pix.field == V4L2_FIELD_ANY)
> +		f->fmt.pix.field = V4L2_FIELD_NONE;
> +
> +	if (f->fmt.pix.field != V4L2_FIELD_NONE)
> +		/* Interlaced formats are not supported. */
> +		f->fmt.pix.field = V4L2_FIELD_NONE;

Can't you just always set the field to V4L2_FIELD_NONE?

> +	ti_csi2rx_fill_fmt(fmt, f);
> +
> +	return 0;
> +}
> +
> +static int ti_csi2rx_s_fmt_vid_cap(struct file *file, void *priv,
> +				   struct v4l2_format *f)
> +{
> +	struct ti_csi2rx_dev *csi = video_drvdata(file);
> +	struct vb2_queue *q = &csi->vidq;
> +	int ret;
> +
> +	if (vb2_is_busy(q))
> +		return -EBUSY;
> +
> +	ret = ti_csi2rx_try_fmt_vid_cap(file, priv, f);
> +	if (ret < 0)
> +		return ret;
> +
> +	csi->v_fmt = *f;
> +
> +	return 0;
> +}
> +
> +static int ti_csi2rx_enum_framesizes(struct file *file, void *fh,
> +				     struct v4l2_frmsizeenum *fsize)
> +{
> +	const struct ti_csi2rx_fmt *fmt;
> +	unsigned int pixels_in_word;
> +	u8 bpp;
> +
> +	fmt = find_format_by_pix(fsize->pixel_format);
> +	if (!fmt || fsize->index != 0)
> +		return -EINVAL;
> +
> +	bpp = ALIGN(fmt->bpp, 8);
> +
> +	/*
> +	 * Number of pixels in one PSI-L word. The transfer happens in multiples
> +	 * of PSI-L word sizes.
> +	 */
> +	pixels_in_word = PSIL_WORD_SIZE_BYTES * 8 / bpp;
> +
> +	fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
> +	fsize->stepwise.min_width = pixels_in_word;
> +	fsize->stepwise.max_width = rounddown(MAX_WIDTH_BYTES * 8 / bpp,
> +					      pixels_in_word);
> +	fsize->stepwise.step_width = pixels_in_word;
> +	fsize->stepwise.min_height = 1;
> +	fsize->stepwise.max_height = MAX_HEIGHT_LINES;
> +	fsize->stepwise.step_height = 1;
> +
> +	return 0;
> +}
> +
> +static const struct v4l2_ioctl_ops csi_ioctl_ops = {
> +	.vidioc_querycap      = ti_csi2rx_querycap,
> +	.vidioc_enum_fmt_vid_cap = ti_csi2rx_enum_fmt_vid_cap,
> +	.vidioc_try_fmt_vid_cap = ti_csi2rx_try_fmt_vid_cap,
> +	.vidioc_g_fmt_vid_cap = ti_csi2rx_g_fmt_vid_cap,
> +	.vidioc_s_fmt_vid_cap = ti_csi2rx_s_fmt_vid_cap,
> +	.vidioc_enum_framesizes = ti_csi2rx_enum_framesizes,
> +	.vidioc_reqbufs       = vb2_ioctl_reqbufs,
> +	.vidioc_create_bufs   = vb2_ioctl_create_bufs,
> +	.vidioc_prepare_buf   = vb2_ioctl_prepare_buf,
> +	.vidioc_querybuf      = vb2_ioctl_querybuf,
> +	.vidioc_qbuf          = vb2_ioctl_qbuf,
> +	.vidioc_dqbuf         = vb2_ioctl_dqbuf,
> +	.vidioc_expbuf        = vb2_ioctl_expbuf,
> +	.vidioc_streamon      = vb2_ioctl_streamon,
> +	.vidioc_streamoff     = vb2_ioctl_streamoff,
> +};
> +
> +static const struct v4l2_file_operations csi_fops = {
> +	.owner = THIS_MODULE,
> +	.open = v4l2_fh_open,
> +	.release = vb2_fop_release,
> +	.read = vb2_fop_read,
> +	.poll = vb2_fop_poll,
> +	.unlocked_ioctl = video_ioctl2,
> +	.mmap = vb2_fop_mmap,
> +};
> +
> +static int csi_async_notifier_bound(struct v4l2_async_notifier *notifier,
> +				    struct v4l2_subdev *subdev,
> +				    struct v4l2_async_connection *asc)
> +{
> +	struct ti_csi2rx_dev *csi = dev_get_drvdata(notifier->v4l2_dev->dev);
> +
> +	csi->subdev = subdev;
> +
> +	return 0;
> +}
> +
> +static int csi_async_notifier_complete(struct v4l2_async_notifier *notifier)
> +{
> +	struct ti_csi2rx_dev *csi = dev_get_drvdata(notifier->v4l2_dev->dev);
> +	struct video_device *vdev = &csi->vdev;
> +	int ret;
> +
> +	ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1);
> +	if (ret)
> +		return ret;
> +
> +	ret = v4l2_create_fwnode_links_to_pad(csi->subdev, &csi->pad,
> +					      MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED);
> +
> +	if (ret) {
> +		video_unregister_device(vdev);
> +		return ret;
> +	}
> +
> +	return v4l2_device_register_subdev_nodes(&csi->v4l2_dev);
> +}
> +
> +static const struct v4l2_async_notifier_operations csi_async_notifier_ops = {
> +	.bound = csi_async_notifier_bound,
> +	.complete = csi_async_notifier_complete,
> +};
> +
> +static int ti_csi2rx_init_subdev(struct ti_csi2rx_dev *csi)

This is misnamed. ti_csi2rx_async_notifier_register()?

> +{
> +	struct fwnode_handle *fwnode;
> +	struct v4l2_async_connection *asc;
> +	struct device_node *node;
> +	int ret;
> +
> +	node = of_get_child_by_name(csi->dev->of_node, "csi-bridge");
> +	if (!node)
> +		return -EINVAL;
> +
> +	fwnode = of_fwnode_handle(node);
> +	if (!fwnode) {
> +		of_node_put(node);
> +		return -EINVAL;
> +	}
> +
> +	v4l2_async_nf_init(&csi->notifier, &csi->v4l2_dev);
> +	csi->notifier.ops = &csi_async_notifier_ops;
> +
> +	asc = v4l2_async_nf_add_fwnode(&csi->notifier, fwnode,
> +				       struct v4l2_async_connection);
> +	of_node_put(node);
> +	if (IS_ERR(asc)) {
> +		v4l2_async_nf_cleanup(&csi->notifier);
> +		return PTR_ERR(asc);
> +	}
> +
> +	ret = v4l2_async_nf_register(&csi->notifier);
> +	if (ret) {
> +		v4l2_async_nf_cleanup(&csi->notifier);
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +static void ti_csi2rx_setup_shim(struct ti_csi2rx_dev *csi)
> +{
> +	const struct ti_csi2rx_fmt *fmt;
> +	unsigned int reg;
> +
> +	fmt = find_format_by_pix(csi->v_fmt.fmt.pix.pixelformat);
> +	if (!fmt) {
> +		dev_err(csi->dev, "Unknown format\n");
> +		return;
> +	}

The error print here is rather vague, and as there's no error code 
returned, the caller doesn't handle the error.

> +
> +	/* De-assert the pixel interface reset. */
> +	reg = SHIM_CNTL_PIX_RST;
> +	writel(reg, csi->shim + SHIM_CNTL);
> +
> +	reg = SHIM_DMACNTX_EN;
> +	reg |= FIELD_PREP(SHIM_DMACNTX_FMT, fmt->csi_dt);
> +
> +	/*
> +	 * Using the values from the documentation gives incorrect ordering for
> +	 * the luma and chroma components. In practice, the "reverse" format
> +	 * gives the correct image. So for example, if the image is in UYVY, the
> +	 * reverse would be YVYU.
> +	 */
> +	switch (fmt->fourcc) {
> +	case V4L2_PIX_FMT_UYVY:
> +		reg |= FIELD_PREP(SHIM_DMACNTX_YUV422,
> +					SHIM_DMACNTX_YVYU);
> +		break;
> +	case V4L2_PIX_FMT_VYUY:
> +		reg |= FIELD_PREP(SHIM_DMACNTX_YUV422,
> +					SHIM_DMACNTX_YUYV);
> +		break;
> +	case V4L2_PIX_FMT_YUYV:
> +		reg |= FIELD_PREP(SHIM_DMACNTX_YUV422,
> +					SHIM_DMACNTX_VYUY);
> +		break;
> +	case V4L2_PIX_FMT_YVYU:
> +		reg |= FIELD_PREP(SHIM_DMACNTX_YUV422,
> +					SHIM_DMACNTX_UYVY);
> +		break;
> +	default:
> +		/* Ignore if not YUV 4:2:2 */
> +		break;
> +	}
> +
> +	reg |= FIELD_PREP(SHIM_DMACNTX_SIZE, fmt->size);
> +
> +	writel(reg, csi->shim + SHIM_DMACNTX);
> +
> +	reg = FIELD_PREP(SHIM_PSI_CFG0_SRC_TAG, 0) |
> +	      FIELD_PREP(SHIM_PSI_CFG0_DST_TAG, 0);
> +	writel(reg, csi->shim + SHIM_PSI_CFG0);
> +}
> +
> +static void ti_csi2rx_drain_callback(void *param)
> +{
> +	struct completion *drain_complete = param;
> +
> +	complete(drain_complete);
> +}
> +
> +static int ti_csi2rx_drain_dma(struct ti_csi2rx_dev *csi)
> +{

I think it would be good to explain in a comment somewhere what why this 
dma draining is needed and how it works.

> +	struct dma_async_tx_descriptor *desc;
> +	struct device *dev = csi->dma.chan->device->dev;
> +	struct completion drain_complete;
> +	void *buf;
> +	size_t len = csi->v_fmt.fmt.pix.sizeimage;
> +	dma_addr_t addr;
> +	dma_cookie_t cookie;
> +	int ret;
> +
> +	init_completion(&drain_complete);
> +
> +	buf = dma_alloc_coherent(dev, len, &addr, GFP_KERNEL | GFP_ATOMIC);
> +	if (!buf)
> +		return -ENOMEM;

If I understand right, this is called when the streaming is stopped, but 
could also be called on frame drops? You're allocating a DMA buffer for 
a full frame. Large runtime DMA buffer allocations are a bit scary. What 
happens if it fails?

Is it possible to preallocate, or use smaller buffers (perhaps with 
multiple dma operations) to do the flush?

The dma doesn't support writing to a constant address, does it (in which 
case a very small buffer would suffice)?

  Tomi


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

* Re: [PATCH v8 16/16] media: ti: Add CSI2RX support for J721E
@ 2023-08-02 11:04     ` Tomi Valkeinen
  0 siblings, 0 replies; 84+ messages in thread
From: Tomi Valkeinen @ 2023-08-02 11:04 UTC (permalink / raw)
  To: Jai Luthra, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Sakari Ailus,
	Laurent Pinchart
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht

On 31/07/2023 11:29, Jai Luthra wrote:
> From: Pratyush Yadav <p.yadav@ti.com>
> 
> TI's J721E uses the Cadence CSI2RX and DPHY peripherals to facilitate
> capture over a CSI-2 bus.
> 
> The Cadence CSI2RX IP acts as a bridge between the TI specific parts and
> the CSI-2 protocol parts. TI then has a wrapper on top of this bridge
> called the SHIM layer. It takes in data from stream 0, repacks it, and
> sends it to memory over PSI-L DMA.
> 
> This driver acts as the "front end" to V4L2 client applications. It
> implements the required ioctls and buffer operations, passes the
> necessary calls on to the bridge, programs the SHIM layer, and performs
> DMA via the dmaengine API to finally return the data to a buffer
> supplied by the application.
> 
> Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
> Co-authored-by: Vaishnav Achath <vaishnav.a@ti.com>
> Signed-off-by: Vaishnav Achath <vaishnav.a@ti.com>
> Co-authored-by: Jai Luthra <j-luthra@ti.com>
> Signed-off-by: Jai Luthra <j-luthra@ti.com>
> ---
> v7->v8:
> - Move after dt-bindings to keep the series bisectable
> - Rename compatible to "ti,j721e-csi2rx-shim" to distinguish from the
>    SoC-specific CSI2RX bridge compatible
> - Make myself the Maintainer
> - Support RAW8 and RAW10 formats, and setting the pixel-unwrap size on
>    SHIM (RAW10 is stored in 16-bit containers, while RAW8 in 8-bit containers)
> - Fix enum_fmt_vid_cap() to respect CAP_IO_MC and only list pixelformats
>    matching the mbus formats set on the subdev.
> - Fix enum_framesizes() to stop enumerating more than a single framesize
>    (reject non-zero fsize->index)
> - Simplify notifier bound fucntion to use v4l2_create_fwnode_links_to_pad()
>    and inline the video_register() method
> - Add support for draining the DMA with an extra buffer, to get rid of
>    stale data in the pipeline on stream stop (or when frames start
>    getting dropped due to load)
> - Queue all available buffers to DMAEngine in the callback, also use a
>    separate "submitted" queue to track all buffers submitted to DMA
> - Use video_device_pipeline_start() instead of media_pipeline_start()
> - Drop support for VB_READ
> - Print issues in link validation as DEBUG instead of ERROR
> - s/async_subdev/async_connection
> 
>   MAINTAINERS                                        |    7 +
>   drivers/media/platform/ti/Kconfig                  |   12 +
>   drivers/media/platform/ti/Makefile                 |    1 +
>   drivers/media/platform/ti/j721e-csi2rx/Makefile    |    2 +
>   .../media/platform/ti/j721e-csi2rx/j721e-csi2rx.c  | 1127 ++++++++++++++++++++
>   5 files changed, 1149 insertions(+)
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index d7b867c57920..1c2d75c30ce7 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -21445,6 +21445,13 @@ F:	Documentation/devicetree/bindings/media/i2c/ti,ds90*
>   F:	drivers/media/i2c/ds90*
>   F:	include/media/i2c/ds90*
>   
> +TI J721E CSI2RX DRIVER
> +M:	Jai Luthra <j-luthra@ti.com>
> +L:	linux-media@vger.kernel.org
> +S:	Maintained
> +F:	Documentation/devicetree/bindings/media/ti,j721e-csi2rx.yaml
> +F:	drivers/media/platform/ti/j721e-csi2rx/
> +
>   TI KEYSTONE MULTICORE NAVIGATOR DRIVERS
>   M:	Nishanth Menon <nm@ti.com>
>   M:	Santosh Shilimkar <ssantosh@kernel.org>
> diff --git a/drivers/media/platform/ti/Kconfig b/drivers/media/platform/ti/Kconfig
> index e1ab56c3be1f..42c908f6e1ae 100644
> --- a/drivers/media/platform/ti/Kconfig
> +++ b/drivers/media/platform/ti/Kconfig
> @@ -63,6 +63,18 @@ config VIDEO_TI_VPE_DEBUG
>   	help
>   	  Enable debug messages on VPE driver.
>   
> +config VIDEO_TI_J721E_CSI2RX
> +	tristate "TI J721E CSI2RX wrapper layer driver"
> +	depends on VIDEO_DEV && VIDEO_V4L2_SUBDEV_API
> +	depends on MEDIA_SUPPORT && MEDIA_CONTROLLER
> +	depends on PHY_CADENCE_DPHY_RX && VIDEO_CADENCE_CSI2RX
> +	depends on ARCH_K3 || COMPILE_TEST
> +	select VIDEOBUF2_DMA_CONTIG
> +	select V4L2_FWNODE
> +	help
> +	  Support for TI CSI2RX wrapper layer. This just enables the wrapper driver.
> +	  The Cadence CSI2RX bridge driver needs to be enabled separately.
> +
>   source "drivers/media/platform/ti/am437x/Kconfig"
>   source "drivers/media/platform/ti/davinci/Kconfig"
>   source "drivers/media/platform/ti/omap/Kconfig"
> diff --git a/drivers/media/platform/ti/Makefile b/drivers/media/platform/ti/Makefile
> index 98c5fe5c40d6..8a2f74c9380e 100644
> --- a/drivers/media/platform/ti/Makefile
> +++ b/drivers/media/platform/ti/Makefile
> @@ -3,5 +3,6 @@ obj-y += am437x/
>   obj-y += cal/
>   obj-y += vpe/
>   obj-y += davinci/
> +obj-y += j721e-csi2rx/
>   obj-y += omap/
>   obj-y += omap3isp/
> diff --git a/drivers/media/platform/ti/j721e-csi2rx/Makefile b/drivers/media/platform/ti/j721e-csi2rx/Makefile
> new file mode 100644
> index 000000000000..377afc1d6280
> --- /dev/null
> +++ b/drivers/media/platform/ti/j721e-csi2rx/Makefile
> @@ -0,0 +1,2 @@
> +# SPDX-License-Identifier: GPL-2.0
> +obj-$(CONFIG_VIDEO_TI_J721E_CSI2RX) += j721e-csi2rx.o
> diff --git a/drivers/media/platform/ti/j721e-csi2rx/j721e-csi2rx.c b/drivers/media/platform/ti/j721e-csi2rx/j721e-csi2rx.c
> new file mode 100644
> index 000000000000..29f1879cfc25
> --- /dev/null
> +++ b/drivers/media/platform/ti/j721e-csi2rx/j721e-csi2rx.c
> @@ -0,0 +1,1127 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * TI CSI2RX Shim Wrapper Driver
> + *
> + * Copyright (C) 2021 Texas Instruments Incorporated - https://www.ti.com/

You can update the year above.

> + * Author: Pratyush Yadav <p.yadav@ti.com>
> + */
> +
> +#include <linux/bitfield.h>
> +#include <linux/dmaengine.h>
> +#include <linux/module.h>
> +#include <linux/of_platform.h>
> +#include <linux/platform_device.h>
> +
> +#include <media/mipi-csi2.h>
> +#include <media/v4l2-device.h>
> +#include <media/v4l2-ioctl.h>
> +#include <media/v4l2-mc.h>
> +#include <media/videobuf2-dma-contig.h>
> +
> +#define TI_CSI2RX_MODULE_NAME		"j721e-csi2rx"
> +
> +#define SHIM_CNTL			0x10
> +#define SHIM_CNTL_PIX_RST		BIT(0)
> +
> +#define SHIM_DMACNTX			0x20
> +#define SHIM_DMACNTX_EN			BIT(31)
> +#define SHIM_DMACNTX_YUV422		GENMASK(27, 26)
> +#define SHIM_DMACNTX_SIZE		GENMASK(21, 20)
> +#define SHIM_DMACNTX_FMT		GENMASK(5, 0)
> +#define SHIM_DMACNTX_UYVY		0
> +#define SHIM_DMACNTX_VYUY		1
> +#define SHIM_DMACNTX_YUYV		2
> +#define SHIM_DMACNTX_YVYU		3
> +#define SHIM_DMACNTX_SIZE_8		0
> +#define SHIM_DMACNTX_SIZE_16		1
> +#define SHIM_DMACNTX_SIZE_32		2
> +
> +#define SHIM_PSI_CFG0			0x24
> +#define SHIM_PSI_CFG0_SRC_TAG		GENMASK(15, 0)
> +#define SHIM_PSI_CFG0_DST_TAG		GENMASK(31, 16)
> +
> +#define PSIL_WORD_SIZE_BYTES		16
> +/*
> + * There are no hard limits on the width or height. The DMA engine can handle
> + * all sizes. The max width and height are arbitrary numbers for this driver.
> + * Use 16K * 16K as the arbitrary limit. It is large enough that it is unlikely
> + * the limit will be hit in practice.
> + */
> +#define MAX_WIDTH_BYTES			SZ_16K
> +#define MAX_HEIGHT_LINES		SZ_16K
> +
> +#define DRAIN_TIMEOUT_MS		50
> +
> +struct ti_csi2rx_fmt {
> +	u32				fourcc;	/* Four character code. */
> +	u32				code;	/* Mbus code. */
> +	u32				csi_dt;	/* CSI Data type. */
> +	u8				bpp;	/* Bits per pixel. */
> +	u8				size;	/* Data size shift when unpacking. */
> +};
> +
> +struct ti_csi2rx_buffer {
> +	/* Common v4l2 buffer. Must be first. */
> +	struct vb2_v4l2_buffer		vb;
> +	struct list_head		list;
> +	struct ti_csi2rx_dev		*csi;
> +};
> +
> +enum ti_csi2rx_dma_state {
> +	TI_CSI2RX_DMA_STOPPED,	/* Streaming not started yet. */
> +	TI_CSI2RX_DMA_IDLE,	/* Streaming but no pending DMA operation. */
> +	TI_CSI2RX_DMA_ACTIVE,	/* Streaming and pending DMA operation. */
> +};
> +
> +struct ti_csi2rx_dma {
> +	/* Protects all fields in this struct. */
> +	spinlock_t			lock;
> +	struct dma_chan			*chan;
> +	/* Buffers queued to the driver, waiting to be processed by DMA. */
> +	struct list_head		queue;
> +	enum ti_csi2rx_dma_state	state;
> +	/*
> +	 * Queue of buffers submitted to DMA engine.
> +	 */
> +	struct list_head		submitted;
> +};
> +
> +struct ti_csi2rx_dev {
> +	struct device			*dev;
> +	void __iomem			*shim;
> +	struct v4l2_device		v4l2_dev;
> +	struct video_device		vdev;
> +	struct media_device		mdev;
> +	struct media_pipeline		pipe;
> +	struct media_pad		pad;
> +	struct v4l2_async_notifier	notifier;
> +	struct v4l2_subdev		*subdev;

I think "source_subdev" is a better name, to make it clear it's not 
referring to a subdev owned by this driver.

> +	struct vb2_queue		vidq;
> +	struct mutex			mutex; /* To serialize ioctls. */
> +	struct v4l2_format		v_fmt;
> +	struct ti_csi2rx_dma		dma;
> +	u32				sequence;
> +};
> +
> +static const struct ti_csi2rx_fmt formats[] = {
> +	{
> +		.fourcc			= V4L2_PIX_FMT_YUYV,
> +		.code			= MEDIA_BUS_FMT_YUYV8_1X16,
> +		.csi_dt			= MIPI_CSI2_DT_YUV422_8B,
> +		.bpp			= 16,
> +		.size			= SHIM_DMACNTX_SIZE_8,
> +	}, {
> +		.fourcc			= V4L2_PIX_FMT_UYVY,
> +		.code			= MEDIA_BUS_FMT_UYVY8_1X16,
> +		.csi_dt			= MIPI_CSI2_DT_YUV422_8B,
> +		.bpp			= 16,
> +		.size			= SHIM_DMACNTX_SIZE_8,
> +	}, {
> +		.fourcc			= V4L2_PIX_FMT_YVYU,
> +		.code			= MEDIA_BUS_FMT_YVYU8_1X16,
> +		.csi_dt			= MIPI_CSI2_DT_YUV422_8B,
> +		.bpp			= 16,
> +		.size			= SHIM_DMACNTX_SIZE_8,
> +	}, {
> +		.fourcc			= V4L2_PIX_FMT_VYUY,
> +		.code			= MEDIA_BUS_FMT_VYUY8_1X16,
> +		.csi_dt			= MIPI_CSI2_DT_YUV422_8B,
> +		.bpp			= 16,
> +		.size			= SHIM_DMACNTX_SIZE_8,
> +	}, {
> +		.fourcc			= V4L2_PIX_FMT_SBGGR8,
> +		.code			= MEDIA_BUS_FMT_SBGGR8_1X8,
> +		.csi_dt			= MIPI_CSI2_DT_RAW8,
> +		.bpp			= 8,
> +		.size			= SHIM_DMACNTX_SIZE_8,
> +	}, {
> +		.fourcc			= V4L2_PIX_FMT_SGBRG8,
> +		.code			= MEDIA_BUS_FMT_SGBRG8_1X8,
> +		.csi_dt			= MIPI_CSI2_DT_RAW8,
> +		.bpp			= 8,
> +		.size			= SHIM_DMACNTX_SIZE_8,
> +	}, {
> +		.fourcc			= V4L2_PIX_FMT_SGRBG8,
> +		.code			= MEDIA_BUS_FMT_SGRBG8_1X8,
> +		.csi_dt			= MIPI_CSI2_DT_RAW8,
> +		.bpp			= 8,
> +		.size			= SHIM_DMACNTX_SIZE_8,
> +	}, {
> +		.fourcc			= V4L2_PIX_FMT_SRGGB8,
> +		.code			= MEDIA_BUS_FMT_SRGGB8_1X8,
> +		.csi_dt			= MIPI_CSI2_DT_RAW8,
> +		.bpp			= 8,
> +		.size			= SHIM_DMACNTX_SIZE_8,
> +	}, {
> +		.fourcc			= V4L2_PIX_FMT_SBGGR10,
> +		.code			= MEDIA_BUS_FMT_SBGGR10_1X10,
> +		.csi_dt			= MIPI_CSI2_DT_RAW10,
> +		.bpp			= 16,
> +		.size			= SHIM_DMACNTX_SIZE_16,
> +	}, {
> +		.fourcc			= V4L2_PIX_FMT_SGBRG10,
> +		.code			= MEDIA_BUS_FMT_SGBRG10_1X10,
> +		.csi_dt			= MIPI_CSI2_DT_RAW10,
> +		.bpp			= 16,
> +		.size			= SHIM_DMACNTX_SIZE_16,
> +	}, {
> +		.fourcc			= V4L2_PIX_FMT_SGRBG10,
> +		.code			= MEDIA_BUS_FMT_SGRBG10_1X10,
> +		.csi_dt			= MIPI_CSI2_DT_RAW10,
> +		.bpp			= 16,
> +		.size			= SHIM_DMACNTX_SIZE_16,
> +	}, {
> +		.fourcc			= V4L2_PIX_FMT_SRGGB10,
> +		.code			= MEDIA_BUS_FMT_SRGGB10_1X10,
> +		.csi_dt			= MIPI_CSI2_DT_RAW10,
> +		.bpp			= 16,
> +		.size			= SHIM_DMACNTX_SIZE_16,
> +	},
> +
> +	/* More formats can be supported but they are not listed for now. */
> +};
> +
> +static const unsigned int num_formats = ARRAY_SIZE(formats);
> +
> +/* Forward declaration needed by ti_csi2rx_dma_callback. */
> +static int ti_csi2rx_start_dma(struct ti_csi2rx_dev *csi,
> +			       struct ti_csi2rx_buffer *buf);
> +
> +static const struct ti_csi2rx_fmt *find_format_by_pix(u32 pixelformat)
> +{
> +	unsigned int i;
> +
> +	for (i = 0; i < num_formats; i++) {
> +		if (formats[i].fourcc == pixelformat)
> +			return &formats[i];
> +	}
> +
> +	return NULL;
> +}
> +
> +static const struct ti_csi2rx_fmt *find_format_by_code(u32 code)
> +{
> +	unsigned int i;
> +
> +	for (i = 0; i < num_formats; i++) {
> +		if (formats[i].code == code)
> +			return &formats[i];
> +	}
> +
> +	return NULL;
> +}
> +
> +static void ti_csi2rx_fill_fmt(const struct ti_csi2rx_fmt *csi_fmt,
> +			       struct v4l2_format *v4l2_fmt)
> +{
> +	struct v4l2_pix_format *pix = &v4l2_fmt->fmt.pix;
> +	unsigned int pixels_in_word;
> +	u8 bpp = csi_fmt->bpp;
> +	u32 bpl;
> +
> +	pixels_in_word = PSIL_WORD_SIZE_BYTES * 8 / bpp;
> +
> +	pix->width = clamp_t(unsigned int, pix->width,
> +			     pixels_in_word,
> +			     MAX_WIDTH_BYTES * 8 / bpp);
> +	pix->width = rounddown(pix->width, pixels_in_word);
> +
> +	pix->height = clamp_t(unsigned int, pix->height, 1, MAX_HEIGHT_LINES);
> +
> +	v4l2_fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
> +	pix->pixelformat = csi_fmt->fourcc;
> +	pix->colorspace = V4L2_COLORSPACE_SRGB;
> +	pix->sizeimage = pix->height * pix->width * (bpp / 8);
> +
> +	bpl = (pix->width * ALIGN(bpp, 8)) >> 3;

You do "/ 8" and "* 8" elsewhere in the function, so I think it makes 
sense to "/ 8" here too, instead of ">> 3".

Is this correct? Why is aligned bpp used here, but when calculating 
sizeimage, bpp is not aligned?

> +	pix->bytesperline = ALIGN(bpl, 16);

Why align to 16?

Shouldn't sizeimage usually be bytesperline * height?

You could add a few comments here to clarify all the aligns, roundings 
and clampings.

> +}
> +
> +static int ti_csi2rx_querycap(struct file *file, void *priv,
> +			      struct v4l2_capability *cap)
> +{
> +	strscpy(cap->driver, TI_CSI2RX_MODULE_NAME, sizeof(cap->driver));
> +	strscpy(cap->card, TI_CSI2RX_MODULE_NAME, sizeof(cap->card));
> +
> +	return 0;
> +}
> +
> +static int ti_csi2rx_enum_fmt_vid_cap(struct file *file, void *priv,
> +				      struct v4l2_fmtdesc *f)
> +{
> +	const struct ti_csi2rx_fmt *fmt = NULL;
> +
> +	if (f->mbus_code) {
> +		if (f->index > 0)
> +			return -EINVAL;

This fails to enumerate the formats if mbus_code is set, doesn't it?

> +
> +		fmt = find_format_by_code(f->mbus_code);
> +	} else {
> +		if (f->index >= num_formats)
> +			return -EINVAL;
> +
> +		fmt = &formats[f->index];
> +	}
> +
> +	if (!fmt)
> +		return -EINVAL;
> +
> +	f->pixelformat = fmt->fourcc;
> +	memset(f->reserved, 0, sizeof(f->reserved));
> +	f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
> +
> +	return 0;
> +}
> +
> +static int ti_csi2rx_g_fmt_vid_cap(struct file *file, void *prov,
> +				   struct v4l2_format *f)
> +{
> +	struct ti_csi2rx_dev *csi = video_drvdata(file);
> +
> +	*f = csi->v_fmt;
> +
> +	return 0;
> +}
> +
> +static int ti_csi2rx_try_fmt_vid_cap(struct file *file, void *priv,
> +				     struct v4l2_format *f)
> +{
> +	const struct ti_csi2rx_fmt *fmt;
> +
> +	/*
> +	 * Default to the first format if the requested pixel format code isn't
> +	 * supported.
> +	 */
> +	fmt = find_format_by_pix(f->fmt.pix.pixelformat);
> +	if (!fmt)
> +		fmt = &formats[0];
> +
> +	if (f->fmt.pix.field == V4L2_FIELD_ANY)
> +		f->fmt.pix.field = V4L2_FIELD_NONE;
> +
> +	if (f->fmt.pix.field != V4L2_FIELD_NONE)
> +		/* Interlaced formats are not supported. */
> +		f->fmt.pix.field = V4L2_FIELD_NONE;

Can't you just always set the field to V4L2_FIELD_NONE?

> +	ti_csi2rx_fill_fmt(fmt, f);
> +
> +	return 0;
> +}
> +
> +static int ti_csi2rx_s_fmt_vid_cap(struct file *file, void *priv,
> +				   struct v4l2_format *f)
> +{
> +	struct ti_csi2rx_dev *csi = video_drvdata(file);
> +	struct vb2_queue *q = &csi->vidq;
> +	int ret;
> +
> +	if (vb2_is_busy(q))
> +		return -EBUSY;
> +
> +	ret = ti_csi2rx_try_fmt_vid_cap(file, priv, f);
> +	if (ret < 0)
> +		return ret;
> +
> +	csi->v_fmt = *f;
> +
> +	return 0;
> +}
> +
> +static int ti_csi2rx_enum_framesizes(struct file *file, void *fh,
> +				     struct v4l2_frmsizeenum *fsize)
> +{
> +	const struct ti_csi2rx_fmt *fmt;
> +	unsigned int pixels_in_word;
> +	u8 bpp;
> +
> +	fmt = find_format_by_pix(fsize->pixel_format);
> +	if (!fmt || fsize->index != 0)
> +		return -EINVAL;
> +
> +	bpp = ALIGN(fmt->bpp, 8);
> +
> +	/*
> +	 * Number of pixels in one PSI-L word. The transfer happens in multiples
> +	 * of PSI-L word sizes.
> +	 */
> +	pixels_in_word = PSIL_WORD_SIZE_BYTES * 8 / bpp;
> +
> +	fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
> +	fsize->stepwise.min_width = pixels_in_word;
> +	fsize->stepwise.max_width = rounddown(MAX_WIDTH_BYTES * 8 / bpp,
> +					      pixels_in_word);
> +	fsize->stepwise.step_width = pixels_in_word;
> +	fsize->stepwise.min_height = 1;
> +	fsize->stepwise.max_height = MAX_HEIGHT_LINES;
> +	fsize->stepwise.step_height = 1;
> +
> +	return 0;
> +}
> +
> +static const struct v4l2_ioctl_ops csi_ioctl_ops = {
> +	.vidioc_querycap      = ti_csi2rx_querycap,
> +	.vidioc_enum_fmt_vid_cap = ti_csi2rx_enum_fmt_vid_cap,
> +	.vidioc_try_fmt_vid_cap = ti_csi2rx_try_fmt_vid_cap,
> +	.vidioc_g_fmt_vid_cap = ti_csi2rx_g_fmt_vid_cap,
> +	.vidioc_s_fmt_vid_cap = ti_csi2rx_s_fmt_vid_cap,
> +	.vidioc_enum_framesizes = ti_csi2rx_enum_framesizes,
> +	.vidioc_reqbufs       = vb2_ioctl_reqbufs,
> +	.vidioc_create_bufs   = vb2_ioctl_create_bufs,
> +	.vidioc_prepare_buf   = vb2_ioctl_prepare_buf,
> +	.vidioc_querybuf      = vb2_ioctl_querybuf,
> +	.vidioc_qbuf          = vb2_ioctl_qbuf,
> +	.vidioc_dqbuf         = vb2_ioctl_dqbuf,
> +	.vidioc_expbuf        = vb2_ioctl_expbuf,
> +	.vidioc_streamon      = vb2_ioctl_streamon,
> +	.vidioc_streamoff     = vb2_ioctl_streamoff,
> +};
> +
> +static const struct v4l2_file_operations csi_fops = {
> +	.owner = THIS_MODULE,
> +	.open = v4l2_fh_open,
> +	.release = vb2_fop_release,
> +	.read = vb2_fop_read,
> +	.poll = vb2_fop_poll,
> +	.unlocked_ioctl = video_ioctl2,
> +	.mmap = vb2_fop_mmap,
> +};
> +
> +static int csi_async_notifier_bound(struct v4l2_async_notifier *notifier,
> +				    struct v4l2_subdev *subdev,
> +				    struct v4l2_async_connection *asc)
> +{
> +	struct ti_csi2rx_dev *csi = dev_get_drvdata(notifier->v4l2_dev->dev);
> +
> +	csi->subdev = subdev;
> +
> +	return 0;
> +}
> +
> +static int csi_async_notifier_complete(struct v4l2_async_notifier *notifier)
> +{
> +	struct ti_csi2rx_dev *csi = dev_get_drvdata(notifier->v4l2_dev->dev);
> +	struct video_device *vdev = &csi->vdev;
> +	int ret;
> +
> +	ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1);
> +	if (ret)
> +		return ret;
> +
> +	ret = v4l2_create_fwnode_links_to_pad(csi->subdev, &csi->pad,
> +					      MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED);
> +
> +	if (ret) {
> +		video_unregister_device(vdev);
> +		return ret;
> +	}
> +
> +	return v4l2_device_register_subdev_nodes(&csi->v4l2_dev);
> +}
> +
> +static const struct v4l2_async_notifier_operations csi_async_notifier_ops = {
> +	.bound = csi_async_notifier_bound,
> +	.complete = csi_async_notifier_complete,
> +};
> +
> +static int ti_csi2rx_init_subdev(struct ti_csi2rx_dev *csi)

This is misnamed. ti_csi2rx_async_notifier_register()?

> +{
> +	struct fwnode_handle *fwnode;
> +	struct v4l2_async_connection *asc;
> +	struct device_node *node;
> +	int ret;
> +
> +	node = of_get_child_by_name(csi->dev->of_node, "csi-bridge");
> +	if (!node)
> +		return -EINVAL;
> +
> +	fwnode = of_fwnode_handle(node);
> +	if (!fwnode) {
> +		of_node_put(node);
> +		return -EINVAL;
> +	}
> +
> +	v4l2_async_nf_init(&csi->notifier, &csi->v4l2_dev);
> +	csi->notifier.ops = &csi_async_notifier_ops;
> +
> +	asc = v4l2_async_nf_add_fwnode(&csi->notifier, fwnode,
> +				       struct v4l2_async_connection);
> +	of_node_put(node);
> +	if (IS_ERR(asc)) {
> +		v4l2_async_nf_cleanup(&csi->notifier);
> +		return PTR_ERR(asc);
> +	}
> +
> +	ret = v4l2_async_nf_register(&csi->notifier);
> +	if (ret) {
> +		v4l2_async_nf_cleanup(&csi->notifier);
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +static void ti_csi2rx_setup_shim(struct ti_csi2rx_dev *csi)
> +{
> +	const struct ti_csi2rx_fmt *fmt;
> +	unsigned int reg;
> +
> +	fmt = find_format_by_pix(csi->v_fmt.fmt.pix.pixelformat);
> +	if (!fmt) {
> +		dev_err(csi->dev, "Unknown format\n");
> +		return;
> +	}

The error print here is rather vague, and as there's no error code 
returned, the caller doesn't handle the error.

> +
> +	/* De-assert the pixel interface reset. */
> +	reg = SHIM_CNTL_PIX_RST;
> +	writel(reg, csi->shim + SHIM_CNTL);
> +
> +	reg = SHIM_DMACNTX_EN;
> +	reg |= FIELD_PREP(SHIM_DMACNTX_FMT, fmt->csi_dt);
> +
> +	/*
> +	 * Using the values from the documentation gives incorrect ordering for
> +	 * the luma and chroma components. In practice, the "reverse" format
> +	 * gives the correct image. So for example, if the image is in UYVY, the
> +	 * reverse would be YVYU.
> +	 */
> +	switch (fmt->fourcc) {
> +	case V4L2_PIX_FMT_UYVY:
> +		reg |= FIELD_PREP(SHIM_DMACNTX_YUV422,
> +					SHIM_DMACNTX_YVYU);
> +		break;
> +	case V4L2_PIX_FMT_VYUY:
> +		reg |= FIELD_PREP(SHIM_DMACNTX_YUV422,
> +					SHIM_DMACNTX_YUYV);
> +		break;
> +	case V4L2_PIX_FMT_YUYV:
> +		reg |= FIELD_PREP(SHIM_DMACNTX_YUV422,
> +					SHIM_DMACNTX_VYUY);
> +		break;
> +	case V4L2_PIX_FMT_YVYU:
> +		reg |= FIELD_PREP(SHIM_DMACNTX_YUV422,
> +					SHIM_DMACNTX_UYVY);
> +		break;
> +	default:
> +		/* Ignore if not YUV 4:2:2 */
> +		break;
> +	}
> +
> +	reg |= FIELD_PREP(SHIM_DMACNTX_SIZE, fmt->size);
> +
> +	writel(reg, csi->shim + SHIM_DMACNTX);
> +
> +	reg = FIELD_PREP(SHIM_PSI_CFG0_SRC_TAG, 0) |
> +	      FIELD_PREP(SHIM_PSI_CFG0_DST_TAG, 0);
> +	writel(reg, csi->shim + SHIM_PSI_CFG0);
> +}
> +
> +static void ti_csi2rx_drain_callback(void *param)
> +{
> +	struct completion *drain_complete = param;
> +
> +	complete(drain_complete);
> +}
> +
> +static int ti_csi2rx_drain_dma(struct ti_csi2rx_dev *csi)
> +{

I think it would be good to explain in a comment somewhere what why this 
dma draining is needed and how it works.

> +	struct dma_async_tx_descriptor *desc;
> +	struct device *dev = csi->dma.chan->device->dev;
> +	struct completion drain_complete;
> +	void *buf;
> +	size_t len = csi->v_fmt.fmt.pix.sizeimage;
> +	dma_addr_t addr;
> +	dma_cookie_t cookie;
> +	int ret;
> +
> +	init_completion(&drain_complete);
> +
> +	buf = dma_alloc_coherent(dev, len, &addr, GFP_KERNEL | GFP_ATOMIC);
> +	if (!buf)
> +		return -ENOMEM;

If I understand right, this is called when the streaming is stopped, but 
could also be called on frame drops? You're allocating a DMA buffer for 
a full frame. Large runtime DMA buffer allocations are a bit scary. What 
happens if it fails?

Is it possible to preallocate, or use smaller buffers (perhaps with 
multiple dma operations) to do the flush?

The dma doesn't support writing to a constant address, does it (in which 
case a very small buffer would suffice)?

  Tomi


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v8 16/16] media: ti: Add CSI2RX support for J721E
  2023-08-02 11:04     ` Tomi Valkeinen
@ 2023-08-02 11:14       ` Sakari Ailus
  -1 siblings, 0 replies; 84+ messages in thread
From: Sakari Ailus @ 2023-08-02 11:14 UTC (permalink / raw)
  To: Tomi Valkeinen
  Cc: Jai Luthra, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Laurent Pinchart, linux-media,
	linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht

Moi,

On Wed, Aug 02, 2023 at 02:04:57PM +0300, Tomi Valkeinen wrote:
> > +static int ti_csi2rx_enum_fmt_vid_cap(struct file *file, void *priv,
> > +				      struct v4l2_fmtdesc *f)
> > +{
> > +	const struct ti_csi2rx_fmt *fmt = NULL;
> > +
> > +	if (f->mbus_code) {
> > +		if (f->index > 0)
> > +			return -EINVAL;
> 
> This fails to enumerate the formats if mbus_code is set, doesn't it?

This is intentional: if the mbus_code field is set, you're supposed to get
only format(s) corresponding to that mbus code.

> 
> > +
> > +		fmt = find_format_by_code(f->mbus_code);
> > +	} else {
> > +		if (f->index >= num_formats)
> > +			return -EINVAL;
> > +
> > +		fmt = &formats[f->index];
> > +	}
> > +
> > +	if (!fmt)
> > +		return -EINVAL;
> > +
> > +	f->pixelformat = fmt->fourcc;
> > +	memset(f->reserved, 0, sizeof(f->reserved));
> > +	f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
> > +
> > +	return 0;
> > +}

-- 
Sakari Ailus

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

* Re: [PATCH v8 16/16] media: ti: Add CSI2RX support for J721E
@ 2023-08-02 11:14       ` Sakari Ailus
  0 siblings, 0 replies; 84+ messages in thread
From: Sakari Ailus @ 2023-08-02 11:14 UTC (permalink / raw)
  To: Tomi Valkeinen
  Cc: Jai Luthra, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Laurent Pinchart, linux-media,
	linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht

Moi,

On Wed, Aug 02, 2023 at 02:04:57PM +0300, Tomi Valkeinen wrote:
> > +static int ti_csi2rx_enum_fmt_vid_cap(struct file *file, void *priv,
> > +				      struct v4l2_fmtdesc *f)
> > +{
> > +	const struct ti_csi2rx_fmt *fmt = NULL;
> > +
> > +	if (f->mbus_code) {
> > +		if (f->index > 0)
> > +			return -EINVAL;
> 
> This fails to enumerate the formats if mbus_code is set, doesn't it?

This is intentional: if the mbus_code field is set, you're supposed to get
only format(s) corresponding to that mbus code.

> 
> > +
> > +		fmt = find_format_by_code(f->mbus_code);
> > +	} else {
> > +		if (f->index >= num_formats)
> > +			return -EINVAL;
> > +
> > +		fmt = &formats[f->index];
> > +	}
> > +
> > +	if (!fmt)
> > +		return -EINVAL;
> > +
> > +	f->pixelformat = fmt->fourcc;
> > +	memset(f->reserved, 0, sizeof(f->reserved));
> > +	f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
> > +
> > +	return 0;
> > +}

-- 
Sakari Ailus

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v8 16/16] media: ti: Add CSI2RX support for J721E
  2023-08-02 11:14       ` Sakari Ailus
@ 2023-08-02 12:09         ` Tomi Valkeinen
  -1 siblings, 0 replies; 84+ messages in thread
From: Tomi Valkeinen @ 2023-08-02 12:09 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: Jai Luthra, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Laurent Pinchart, linux-media,
	linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht

On 02/08/2023 14:14, Sakari Ailus wrote:
> Moi,
> 
> On Wed, Aug 02, 2023 at 02:04:57PM +0300, Tomi Valkeinen wrote:
>>> +static int ti_csi2rx_enum_fmt_vid_cap(struct file *file, void *priv,
>>> +				      struct v4l2_fmtdesc *f)
>>> +{
>>> +	const struct ti_csi2rx_fmt *fmt = NULL;
>>> +
>>> +	if (f->mbus_code) {
>>> +		if (f->index > 0)
>>> +			return -EINVAL;
>>
>> This fails to enumerate the formats if mbus_code is set, doesn't it?
> 
> This is intentional: if the mbus_code field is set, you're supposed to get
> only format(s) corresponding to that mbus code.

Right. But the above code doesn't do that, does it? It will only return 
the first format, and error for anything else. Ah, the driver only 
supports a single mbus code per fourcc. In that case it's ok.

  Tomi

>>
>>> +
>>> +		fmt = find_format_by_code(f->mbus_code);
>>> +	} else {
>>> +		if (f->index >= num_formats)
>>> +			return -EINVAL;
>>> +
>>> +		fmt = &formats[f->index];
>>> +	}
>>> +
>>> +	if (!fmt)
>>> +		return -EINVAL;
>>> +
>>> +	f->pixelformat = fmt->fourcc;
>>> +	memset(f->reserved, 0, sizeof(f->reserved));
>>> +	f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
>>> +
>>> +	return 0;
>>> +}
> 


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

* Re: [PATCH v8 16/16] media: ti: Add CSI2RX support for J721E
@ 2023-08-02 12:09         ` Tomi Valkeinen
  0 siblings, 0 replies; 84+ messages in thread
From: Tomi Valkeinen @ 2023-08-02 12:09 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: Jai Luthra, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Laurent Pinchart, linux-media,
	linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht

On 02/08/2023 14:14, Sakari Ailus wrote:
> Moi,
> 
> On Wed, Aug 02, 2023 at 02:04:57PM +0300, Tomi Valkeinen wrote:
>>> +static int ti_csi2rx_enum_fmt_vid_cap(struct file *file, void *priv,
>>> +				      struct v4l2_fmtdesc *f)
>>> +{
>>> +	const struct ti_csi2rx_fmt *fmt = NULL;
>>> +
>>> +	if (f->mbus_code) {
>>> +		if (f->index > 0)
>>> +			return -EINVAL;
>>
>> This fails to enumerate the formats if mbus_code is set, doesn't it?
> 
> This is intentional: if the mbus_code field is set, you're supposed to get
> only format(s) corresponding to that mbus code.

Right. But the above code doesn't do that, does it? It will only return 
the first format, and error for anything else. Ah, the driver only 
supports a single mbus code per fourcc. In that case it's ok.

  Tomi

>>
>>> +
>>> +		fmt = find_format_by_code(f->mbus_code);
>>> +	} else {
>>> +		if (f->index >= num_formats)
>>> +			return -EINVAL;
>>> +
>>> +		fmt = &formats[f->index];
>>> +	}
>>> +
>>> +	if (!fmt)
>>> +		return -EINVAL;
>>> +
>>> +	f->pixelformat = fmt->fourcc;
>>> +	memset(f->reserved, 0, sizeof(f->reserved));
>>> +	f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
>>> +
>>> +	return 0;
>>> +}
> 


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v8 07/16] media: cadence: csi2rx: Add get_fmt and set_fmt pad ops
  2023-08-02  8:48     ` Tomi Valkeinen
@ 2023-08-03 11:18       ` Jai Luthra
  -1 siblings, 0 replies; 84+ messages in thread
From: Jai Luthra @ 2023-08-03 11:18 UTC (permalink / raw)
  To: Tomi Valkeinen
  Cc: Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Sakari Ailus, Laurent Pinchart, linux-media,
	linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht

[-- Attachment #1: Type: text/plain, Size: 7585 bytes --]

Hi Tomi,

Thanks for the review.

On Aug 02, 2023 at 11:48:52 +0300, Tomi Valkeinen wrote:
> On 31/07/2023 11:29, Jai Luthra wrote:
> > From: Pratyush Yadav <p.yadav@ti.com>
> > 
> > The format is needed to calculate the link speed for the external DPHY
> > configuration. It is not right to query the format from the source
> > subdev. Add get_fmt and set_fmt pad operations so that the format can be
> > configured and correct bpp be selected.
> > 
> > Initialize and use the v4l2 subdev active state to keep track of the
> > active formats. Also propagate the new format from the sink pad to all
> > the source pads.
> > 
> > Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
> > Co-authored-by: Jai Luthra <j-luthra@ti.com>
> > Signed-off-by: Jai Luthra <j-luthra@ti.com>
> > ---
> > v7->v8:
> > - Use active subdev state to use v4l2_subdev_get_fmt
> > - Propagate formats from sink to source pads
> > - Drop Laurent's R-by because of the above changes
> > 
> >   drivers/media/platform/cadence/cdns-csi2rx.c | 107 ++++++++++++++++++++++++++-
> >   1 file changed, 106 insertions(+), 1 deletion(-)
> > 
> > diff --git a/drivers/media/platform/cadence/cdns-csi2rx.c b/drivers/media/platform/cadence/cdns-csi2rx.c
> > index 83d1fadd592b..4f9654366485 100644
> > --- a/drivers/media/platform/cadence/cdns-csi2rx.c
> > +++ b/drivers/media/platform/cadence/cdns-csi2rx.c
> > @@ -61,6 +61,11 @@ enum csi2rx_pads {
> >   	CSI2RX_PAD_MAX,
> >   };
> > +struct csi2rx_fmt {
> > +	u32				code;
> > +	u8				bpp;
> > +};
> > +
> >   struct csi2rx_priv {
> >   	struct device			*dev;
> >   	unsigned int			count;
> > @@ -95,6 +100,36 @@ struct csi2rx_priv {
> >   	int				source_pad;
> >   };
> > +static const struct csi2rx_fmt formats[] = {
> > +	{
> > +		.code	= MEDIA_BUS_FMT_YUYV8_1X16,
> > +		.bpp	= 16,
> > +	},
> > +	{
> > +		.code	= MEDIA_BUS_FMT_UYVY8_1X16,
> > +		.bpp	= 16,
> > +	},
> > +	{
> > +		.code	= MEDIA_BUS_FMT_YVYU8_1X16,
> > +		.bpp	= 16,
> > +	},
> > +	{
> > +		.code	= MEDIA_BUS_FMT_VYUY8_1X16,
> > +		.bpp	= 16,
> > +	},
> > +};
> 
> I think you could just squash the "media: cadence: csi2rx: Support RAW8 and
> RAW10 formats" into this one. Also, the lines could well be one-liners:
> 
> 	{ .code	= MEDIA_BUS_FMT_YUYV8_1X16, .bpp = 16, },
> 

Will fix.

> 
> > +static const struct csi2rx_fmt *csi2rx_get_fmt_by_code(u32 code)
> > +{
> > +	unsigned int i;
> > +
> > +	for (i = 0; i < ARRAY_SIZE(formats); i++)
> > +		if (formats[i].code == code)
> > +			return &formats[i];
> > +
> > +	return NULL;
> > +}
> > +
> >   static inline
> >   struct csi2rx_priv *v4l2_subdev_to_csi2rx(struct v4l2_subdev *subdev)
> >   {
> > @@ -303,12 +338,75 @@ static int csi2rx_s_stream(struct v4l2_subdev *subdev, int enable)
> >   	return ret;
> >   }
> > +static int csi2rx_set_fmt(struct v4l2_subdev *subdev,
> > +			  struct v4l2_subdev_state *state,
> > +			  struct v4l2_subdev_format *format)
> > +{
> > +	struct v4l2_mbus_framefmt *fmt;
> > +	unsigned int i;
> > +
> > +	/* No transcoding, source and sink formats must match. */
> > +	if (format->pad != CSI2RX_PAD_SINK)
> > +		return v4l2_subdev_get_fmt(subdev, state, format);
> > +
> > +	if (!csi2rx_get_fmt_by_code(format->format.code))
> > +		format->format.code = formats[0].code;
> > +
> > +	format->format.field = V4L2_FIELD_NONE;
> > +
> > +	/* Set sink format */
> > +	fmt = v4l2_subdev_get_pad_format(subdev, state, format->pad);
> > +	if (!fmt)
> > +		return -EINVAL;
> > +
> > +	*fmt = format->format;
> > +
> > +	/* Propagate to source formats */
> > +	for (i = CSI2RX_PAD_SOURCE_STREAM0; i < CSI2RX_PAD_MAX; i++) {
> > +		fmt = v4l2_subdev_get_pad_format(subdev, state, i);
> > +		if (!fmt)
> > +			return -EINVAL;
> > +		*fmt = format->format;
> > +	}
> 
> Not really part of this patch, but why does csi2rx create more than one
> source pad? It doesn't support streams, so how are those pads used?
> 

These pads correspond to the 4 output pixel data "streams" the Cadence 
IP provides. We can route the incoming pixel data over MIPI CSI to 
different peripherals in the SoC, while doing some optional filtering on 
VC and DT using the STREAM_DATA_CFG register.

Different vendors may integrate these streams in their own way. For 
example on AM62A this is how they are mapped in the hardware [1]:

pad1 -> shim   -> upto 32x dma chans
pad2 ->
pad3 -> vp0    -> ISP
pad4 -> vp1

For shim the idea is to pass-through all VCs and DTs, as shim can filter 
and send different v4l2-streams to different dma chans.

For the ISP (when supported) we will have to filter for a specific VC or 
DT here, in case multiple streams are coming over CSI.

[1] TRM, Section 12.6.4 https://www.ti.com/lit/ug/spruj16/spruj16.pdf 

> > +	return 0;
> > +}
> > +
> > +static int csi2rx_init_cfg(struct v4l2_subdev *subdev,
> > +			   struct v4l2_subdev_state *state)
> > +{
> > +	struct v4l2_subdev_format format = {
> > +		.which = state ? V4L2_SUBDEV_FORMAT_TRY
> > +			: V4L2_SUBDEV_FORMAT_ACTIVE,
> 
> I don't think this is correct. If you enable the active state, you'll always
> get a state here, and thus this function doesn't really know if it is TRY or
> ACTIVE state (nor should it care).

My bad I forgot to clean this up. Will fix in next revision.

> 
> > +		.pad = CSI2RX_PAD_SINK,
> > +		.format = {
> > +			.width = 640,
> > +			.height = 480,
> > +			.code = MEDIA_BUS_FMT_UYVY8_1X16,
> > +			.field = V4L2_FIELD_NONE,
> > +			.colorspace = V4L2_COLORSPACE_SRGB,
> > +			.ycbcr_enc = V4L2_YCBCR_ENC_601,
> > +			.quantization = V4L2_QUANTIZATION_LIM_RANGE,
> > +			.xfer_func = V4L2_XFER_FUNC_SRGB,
> > +		},
> > +	};
> > +
> > +	return csi2rx_set_fmt(subdev, state, &format);
> > +}
> > +
> > +static const struct v4l2_subdev_pad_ops csi2rx_pad_ops = {
> > +	.get_fmt	= v4l2_subdev_get_fmt,
> > +	.set_fmt	= csi2rx_set_fmt,
> > +	.init_cfg	= csi2rx_init_cfg,
> > +};
> > +
> >   static const struct v4l2_subdev_video_ops csi2rx_video_ops = {
> >   	.s_stream	= csi2rx_s_stream,
> >   };
> >   static const struct v4l2_subdev_ops csi2rx_subdev_ops = {
> >   	.video		= &csi2rx_video_ops,
> > +	.pad		= &csi2rx_pad_ops,
> >   };
> >   static int csi2rx_async_bound(struct v4l2_async_notifier *notifier,
> > @@ -532,9 +630,13 @@ static int csi2rx_probe(struct platform_device *pdev)
> >   	if (ret)
> >   		goto err_cleanup;
> > +	ret = v4l2_subdev_init_finalize(&csi2rx->subdev);
> > +	if (ret)
> > +		goto err_cleanup;
> > +
> >   	ret = v4l2_async_register_subdev(&csi2rx->subdev);
> >   	if (ret < 0)
> > -		goto err_cleanup;
> > +		goto err_free_state;
> >   	dev_info(&pdev->dev,
> >   		 "Probed CSI2RX with %u/%u lanes, %u streams, %s D-PHY\n",
> > @@ -544,6 +646,8 @@ static int csi2rx_probe(struct platform_device *pdev)
> >   	return 0;
> > +err_free_state:
> > +	v4l2_subdev_cleanup(&csi2rx->subdev);
> >   err_cleanup:
> >   	v4l2_async_nf_unregister(&csi2rx->notifier);
> >   	v4l2_async_nf_cleanup(&csi2rx->notifier);
> > @@ -560,6 +664,7 @@ static void csi2rx_remove(struct platform_device *pdev)
> >   	v4l2_async_nf_unregister(&csi2rx->notifier);
> >   	v4l2_async_nf_cleanup(&csi2rx->notifier);
> >   	v4l2_async_unregister_subdev(&csi2rx->subdev);
> > +	v4l2_subdev_cleanup(&csi2rx->subdev);
> >   	media_entity_cleanup(&csi2rx->subdev.entity);
> >   	kfree(csi2rx);
> >   }
> > 
> 

-- 
Thanks,
Jai

GPG Fingerprint: 4DE0 D818 E5D5 75E8 D45A AFC5 43DE 91F9 249A 7145

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v8 07/16] media: cadence: csi2rx: Add get_fmt and set_fmt pad ops
@ 2023-08-03 11:18       ` Jai Luthra
  0 siblings, 0 replies; 84+ messages in thread
From: Jai Luthra @ 2023-08-03 11:18 UTC (permalink / raw)
  To: Tomi Valkeinen
  Cc: Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Sakari Ailus, Laurent Pinchart, linux-media,
	linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht


[-- Attachment #1.1: Type: text/plain, Size: 7585 bytes --]

Hi Tomi,

Thanks for the review.

On Aug 02, 2023 at 11:48:52 +0300, Tomi Valkeinen wrote:
> On 31/07/2023 11:29, Jai Luthra wrote:
> > From: Pratyush Yadav <p.yadav@ti.com>
> > 
> > The format is needed to calculate the link speed for the external DPHY
> > configuration. It is not right to query the format from the source
> > subdev. Add get_fmt and set_fmt pad operations so that the format can be
> > configured and correct bpp be selected.
> > 
> > Initialize and use the v4l2 subdev active state to keep track of the
> > active formats. Also propagate the new format from the sink pad to all
> > the source pads.
> > 
> > Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
> > Co-authored-by: Jai Luthra <j-luthra@ti.com>
> > Signed-off-by: Jai Luthra <j-luthra@ti.com>
> > ---
> > v7->v8:
> > - Use active subdev state to use v4l2_subdev_get_fmt
> > - Propagate formats from sink to source pads
> > - Drop Laurent's R-by because of the above changes
> > 
> >   drivers/media/platform/cadence/cdns-csi2rx.c | 107 ++++++++++++++++++++++++++-
> >   1 file changed, 106 insertions(+), 1 deletion(-)
> > 
> > diff --git a/drivers/media/platform/cadence/cdns-csi2rx.c b/drivers/media/platform/cadence/cdns-csi2rx.c
> > index 83d1fadd592b..4f9654366485 100644
> > --- a/drivers/media/platform/cadence/cdns-csi2rx.c
> > +++ b/drivers/media/platform/cadence/cdns-csi2rx.c
> > @@ -61,6 +61,11 @@ enum csi2rx_pads {
> >   	CSI2RX_PAD_MAX,
> >   };
> > +struct csi2rx_fmt {
> > +	u32				code;
> > +	u8				bpp;
> > +};
> > +
> >   struct csi2rx_priv {
> >   	struct device			*dev;
> >   	unsigned int			count;
> > @@ -95,6 +100,36 @@ struct csi2rx_priv {
> >   	int				source_pad;
> >   };
> > +static const struct csi2rx_fmt formats[] = {
> > +	{
> > +		.code	= MEDIA_BUS_FMT_YUYV8_1X16,
> > +		.bpp	= 16,
> > +	},
> > +	{
> > +		.code	= MEDIA_BUS_FMT_UYVY8_1X16,
> > +		.bpp	= 16,
> > +	},
> > +	{
> > +		.code	= MEDIA_BUS_FMT_YVYU8_1X16,
> > +		.bpp	= 16,
> > +	},
> > +	{
> > +		.code	= MEDIA_BUS_FMT_VYUY8_1X16,
> > +		.bpp	= 16,
> > +	},
> > +};
> 
> I think you could just squash the "media: cadence: csi2rx: Support RAW8 and
> RAW10 formats" into this one. Also, the lines could well be one-liners:
> 
> 	{ .code	= MEDIA_BUS_FMT_YUYV8_1X16, .bpp = 16, },
> 

Will fix.

> 
> > +static const struct csi2rx_fmt *csi2rx_get_fmt_by_code(u32 code)
> > +{
> > +	unsigned int i;
> > +
> > +	for (i = 0; i < ARRAY_SIZE(formats); i++)
> > +		if (formats[i].code == code)
> > +			return &formats[i];
> > +
> > +	return NULL;
> > +}
> > +
> >   static inline
> >   struct csi2rx_priv *v4l2_subdev_to_csi2rx(struct v4l2_subdev *subdev)
> >   {
> > @@ -303,12 +338,75 @@ static int csi2rx_s_stream(struct v4l2_subdev *subdev, int enable)
> >   	return ret;
> >   }
> > +static int csi2rx_set_fmt(struct v4l2_subdev *subdev,
> > +			  struct v4l2_subdev_state *state,
> > +			  struct v4l2_subdev_format *format)
> > +{
> > +	struct v4l2_mbus_framefmt *fmt;
> > +	unsigned int i;
> > +
> > +	/* No transcoding, source and sink formats must match. */
> > +	if (format->pad != CSI2RX_PAD_SINK)
> > +		return v4l2_subdev_get_fmt(subdev, state, format);
> > +
> > +	if (!csi2rx_get_fmt_by_code(format->format.code))
> > +		format->format.code = formats[0].code;
> > +
> > +	format->format.field = V4L2_FIELD_NONE;
> > +
> > +	/* Set sink format */
> > +	fmt = v4l2_subdev_get_pad_format(subdev, state, format->pad);
> > +	if (!fmt)
> > +		return -EINVAL;
> > +
> > +	*fmt = format->format;
> > +
> > +	/* Propagate to source formats */
> > +	for (i = CSI2RX_PAD_SOURCE_STREAM0; i < CSI2RX_PAD_MAX; i++) {
> > +		fmt = v4l2_subdev_get_pad_format(subdev, state, i);
> > +		if (!fmt)
> > +			return -EINVAL;
> > +		*fmt = format->format;
> > +	}
> 
> Not really part of this patch, but why does csi2rx create more than one
> source pad? It doesn't support streams, so how are those pads used?
> 

These pads correspond to the 4 output pixel data "streams" the Cadence 
IP provides. We can route the incoming pixel data over MIPI CSI to 
different peripherals in the SoC, while doing some optional filtering on 
VC and DT using the STREAM_DATA_CFG register.

Different vendors may integrate these streams in their own way. For 
example on AM62A this is how they are mapped in the hardware [1]:

pad1 -> shim   -> upto 32x dma chans
pad2 ->
pad3 -> vp0    -> ISP
pad4 -> vp1

For shim the idea is to pass-through all VCs and DTs, as shim can filter 
and send different v4l2-streams to different dma chans.

For the ISP (when supported) we will have to filter for a specific VC or 
DT here, in case multiple streams are coming over CSI.

[1] TRM, Section 12.6.4 https://www.ti.com/lit/ug/spruj16/spruj16.pdf 

> > +	return 0;
> > +}
> > +
> > +static int csi2rx_init_cfg(struct v4l2_subdev *subdev,
> > +			   struct v4l2_subdev_state *state)
> > +{
> > +	struct v4l2_subdev_format format = {
> > +		.which = state ? V4L2_SUBDEV_FORMAT_TRY
> > +			: V4L2_SUBDEV_FORMAT_ACTIVE,
> 
> I don't think this is correct. If you enable the active state, you'll always
> get a state here, and thus this function doesn't really know if it is TRY or
> ACTIVE state (nor should it care).

My bad I forgot to clean this up. Will fix in next revision.

> 
> > +		.pad = CSI2RX_PAD_SINK,
> > +		.format = {
> > +			.width = 640,
> > +			.height = 480,
> > +			.code = MEDIA_BUS_FMT_UYVY8_1X16,
> > +			.field = V4L2_FIELD_NONE,
> > +			.colorspace = V4L2_COLORSPACE_SRGB,
> > +			.ycbcr_enc = V4L2_YCBCR_ENC_601,
> > +			.quantization = V4L2_QUANTIZATION_LIM_RANGE,
> > +			.xfer_func = V4L2_XFER_FUNC_SRGB,
> > +		},
> > +	};
> > +
> > +	return csi2rx_set_fmt(subdev, state, &format);
> > +}
> > +
> > +static const struct v4l2_subdev_pad_ops csi2rx_pad_ops = {
> > +	.get_fmt	= v4l2_subdev_get_fmt,
> > +	.set_fmt	= csi2rx_set_fmt,
> > +	.init_cfg	= csi2rx_init_cfg,
> > +};
> > +
> >   static const struct v4l2_subdev_video_ops csi2rx_video_ops = {
> >   	.s_stream	= csi2rx_s_stream,
> >   };
> >   static const struct v4l2_subdev_ops csi2rx_subdev_ops = {
> >   	.video		= &csi2rx_video_ops,
> > +	.pad		= &csi2rx_pad_ops,
> >   };
> >   static int csi2rx_async_bound(struct v4l2_async_notifier *notifier,
> > @@ -532,9 +630,13 @@ static int csi2rx_probe(struct platform_device *pdev)
> >   	if (ret)
> >   		goto err_cleanup;
> > +	ret = v4l2_subdev_init_finalize(&csi2rx->subdev);
> > +	if (ret)
> > +		goto err_cleanup;
> > +
> >   	ret = v4l2_async_register_subdev(&csi2rx->subdev);
> >   	if (ret < 0)
> > -		goto err_cleanup;
> > +		goto err_free_state;
> >   	dev_info(&pdev->dev,
> >   		 "Probed CSI2RX with %u/%u lanes, %u streams, %s D-PHY\n",
> > @@ -544,6 +646,8 @@ static int csi2rx_probe(struct platform_device *pdev)
> >   	return 0;
> > +err_free_state:
> > +	v4l2_subdev_cleanup(&csi2rx->subdev);
> >   err_cleanup:
> >   	v4l2_async_nf_unregister(&csi2rx->notifier);
> >   	v4l2_async_nf_cleanup(&csi2rx->notifier);
> > @@ -560,6 +664,7 @@ static void csi2rx_remove(struct platform_device *pdev)
> >   	v4l2_async_nf_unregister(&csi2rx->notifier);
> >   	v4l2_async_nf_cleanup(&csi2rx->notifier);
> >   	v4l2_async_unregister_subdev(&csi2rx->subdev);
> > +	v4l2_subdev_cleanup(&csi2rx->subdev);
> >   	media_entity_cleanup(&csi2rx->subdev.entity);
> >   	kfree(csi2rx);
> >   }
> > 
> 

-- 
Thanks,
Jai

GPG Fingerprint: 4DE0 D818 E5D5 75E8 D45A AFC5 43DE 91F9 249A 7145

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

[-- Attachment #2: Type: text/plain, Size: 176 bytes --]

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v8 09/16] media: cadence: csi2rx: Soft reset the streams before starting capture
  2023-08-01 14:16     ` Tomi Valkeinen
@ 2023-08-03 11:19       ` Jai Luthra
  -1 siblings, 0 replies; 84+ messages in thread
From: Jai Luthra @ 2023-08-03 11:19 UTC (permalink / raw)
  To: Tomi Valkeinen
  Cc: Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Sakari Ailus, Laurent Pinchart, linux-media,
	linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht

[-- Attachment #1: Type: text/plain, Size: 2513 bytes --]

On Aug 01, 2023 at 17:16:41 +0300, Tomi Valkeinen wrote:
> On 31/07/2023 11:29, Jai Luthra wrote:
> > From: Pratyush Yadav <p.yadav@ti.com>
> > 
> > This resets the stream state machines and FIFOs, giving them a clean
> > slate. On J721E if the streams are not reset before starting the
> > capture, the captured frame gets wrapped around vertically on every run
> > after the first.
> > 
> > Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
> > Signed-off-by: Jai Luthra <j-luthra@ti.com>
> > Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > ---
> > v7->v8: No change
> > 
> >   drivers/media/platform/cadence/cdns-csi2rx.c | 11 +++++++++++
> >   1 file changed, 11 insertions(+)
> > 
> > diff --git a/drivers/media/platform/cadence/cdns-csi2rx.c b/drivers/media/platform/cadence/cdns-csi2rx.c
> > index 2a80c66fb547..30cdc260b46a 100644
> > --- a/drivers/media/platform/cadence/cdns-csi2rx.c
> > +++ b/drivers/media/platform/cadence/cdns-csi2rx.c
> > @@ -40,6 +40,7 @@
> >   #define CSI2RX_STREAM_BASE(n)		(((n) + 1) * 0x100)
> >   #define CSI2RX_STREAM_CTRL_REG(n)		(CSI2RX_STREAM_BASE(n) + 0x000)
> > +#define CSI2RX_STREAM_CTRL_SOFT_RST			BIT(4)
> >   #define CSI2RX_STREAM_CTRL_START			BIT(0)
> >   #define CSI2RX_STREAM_DATA_CFG_REG(n)		(CSI2RX_STREAM_BASE(n) + 0x008)
> > @@ -138,12 +139,22 @@ struct csi2rx_priv *v4l2_subdev_to_csi2rx(struct v4l2_subdev *subdev)
> >   static void csi2rx_reset(struct csi2rx_priv *csi2rx)
> >   {
> > +	unsigned int i;
> > +
> >   	writel(CSI2RX_SOFT_RESET_PROTOCOL | CSI2RX_SOFT_RESET_FRONT,
> >   	       csi2rx->base + CSI2RX_SOFT_RESET_REG);
> >   	udelay(10);
> >   	writel(0, csi2rx->base + CSI2RX_SOFT_RESET_REG);
> > +
> > +	/* Reset individual streams. */
> > +	for (i = 0; i < csi2rx->max_streams; i++) {
> > +		writel(CSI2RX_STREAM_CTRL_SOFT_RST,
> > +		       csi2rx->base + CSI2RX_STREAM_CTRL_REG(i));
> > +		usleep_range(10, 20);
> > +		writel(0, csi2rx->base + CSI2RX_STREAM_CTRL_REG(i));
> > +	}
> 
> Do you have to do it like this? Or would it be fine to set the reset bit for
> all stream regs, then sleep, then clear the reset bit from all stream regs?
> Or going even further, can you set the CSI2RX_SOFT_RESET_REG and all
> CSI2RX_STREAM_CTRL_REG regs, then sleep, and then clear them all?

You're right I think that should work, and would be much cleaner. Will 
fix.

> 
>  Tomi
> 

-- 
Thanks,
Jai

GPG Fingerprint: 4DE0 D818 E5D5 75E8 D45A AFC5 43DE 91F9 249A 7145

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v8 09/16] media: cadence: csi2rx: Soft reset the streams before starting capture
@ 2023-08-03 11:19       ` Jai Luthra
  0 siblings, 0 replies; 84+ messages in thread
From: Jai Luthra @ 2023-08-03 11:19 UTC (permalink / raw)
  To: Tomi Valkeinen
  Cc: Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Sakari Ailus, Laurent Pinchart, linux-media,
	linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht


[-- Attachment #1.1: Type: text/plain, Size: 2513 bytes --]

On Aug 01, 2023 at 17:16:41 +0300, Tomi Valkeinen wrote:
> On 31/07/2023 11:29, Jai Luthra wrote:
> > From: Pratyush Yadav <p.yadav@ti.com>
> > 
> > This resets the stream state machines and FIFOs, giving them a clean
> > slate. On J721E if the streams are not reset before starting the
> > capture, the captured frame gets wrapped around vertically on every run
> > after the first.
> > 
> > Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
> > Signed-off-by: Jai Luthra <j-luthra@ti.com>
> > Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > ---
> > v7->v8: No change
> > 
> >   drivers/media/platform/cadence/cdns-csi2rx.c | 11 +++++++++++
> >   1 file changed, 11 insertions(+)
> > 
> > diff --git a/drivers/media/platform/cadence/cdns-csi2rx.c b/drivers/media/platform/cadence/cdns-csi2rx.c
> > index 2a80c66fb547..30cdc260b46a 100644
> > --- a/drivers/media/platform/cadence/cdns-csi2rx.c
> > +++ b/drivers/media/platform/cadence/cdns-csi2rx.c
> > @@ -40,6 +40,7 @@
> >   #define CSI2RX_STREAM_BASE(n)		(((n) + 1) * 0x100)
> >   #define CSI2RX_STREAM_CTRL_REG(n)		(CSI2RX_STREAM_BASE(n) + 0x000)
> > +#define CSI2RX_STREAM_CTRL_SOFT_RST			BIT(4)
> >   #define CSI2RX_STREAM_CTRL_START			BIT(0)
> >   #define CSI2RX_STREAM_DATA_CFG_REG(n)		(CSI2RX_STREAM_BASE(n) + 0x008)
> > @@ -138,12 +139,22 @@ struct csi2rx_priv *v4l2_subdev_to_csi2rx(struct v4l2_subdev *subdev)
> >   static void csi2rx_reset(struct csi2rx_priv *csi2rx)
> >   {
> > +	unsigned int i;
> > +
> >   	writel(CSI2RX_SOFT_RESET_PROTOCOL | CSI2RX_SOFT_RESET_FRONT,
> >   	       csi2rx->base + CSI2RX_SOFT_RESET_REG);
> >   	udelay(10);
> >   	writel(0, csi2rx->base + CSI2RX_SOFT_RESET_REG);
> > +
> > +	/* Reset individual streams. */
> > +	for (i = 0; i < csi2rx->max_streams; i++) {
> > +		writel(CSI2RX_STREAM_CTRL_SOFT_RST,
> > +		       csi2rx->base + CSI2RX_STREAM_CTRL_REG(i));
> > +		usleep_range(10, 20);
> > +		writel(0, csi2rx->base + CSI2RX_STREAM_CTRL_REG(i));
> > +	}
> 
> Do you have to do it like this? Or would it be fine to set the reset bit for
> all stream regs, then sleep, then clear the reset bit from all stream regs?
> Or going even further, can you set the CSI2RX_SOFT_RESET_REG and all
> CSI2RX_STREAM_CTRL_REG regs, then sleep, and then clear them all?

You're right I think that should work, and would be much cleaner. Will 
fix.

> 
>  Tomi
> 

-- 
Thanks,
Jai

GPG Fingerprint: 4DE0 D818 E5D5 75E8 D45A AFC5 43DE 91F9 249A 7145

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

[-- Attachment #2: Type: text/plain, Size: 176 bytes --]

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v8 16/16] media: ti: Add CSI2RX support for J721E
  2023-08-02 11:04     ` Tomi Valkeinen
@ 2023-08-03 11:51       ` Jai Luthra
  -1 siblings, 0 replies; 84+ messages in thread
From: Jai Luthra @ 2023-08-03 11:51 UTC (permalink / raw)
  To: Tomi Valkeinen
  Cc: Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Sakari Ailus, Laurent Pinchart, linux-media,
	linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht

[-- Attachment #1: Type: text/plain, Size: 25482 bytes --]

Hi Tomi,

Thanks for the review.

On Aug 02, 2023 at 14:04:57 +0300, Tomi Valkeinen wrote:
> On 31/07/2023 11:29, Jai Luthra wrote:
> > From: Pratyush Yadav <p.yadav@ti.com>
> > 
> > TI's J721E uses the Cadence CSI2RX and DPHY peripherals to facilitate
> > capture over a CSI-2 bus.
> > 
> > The Cadence CSI2RX IP acts as a bridge between the TI specific parts and
> > the CSI-2 protocol parts. TI then has a wrapper on top of this bridge
> > called the SHIM layer. It takes in data from stream 0, repacks it, and
> > sends it to memory over PSI-L DMA.
> > 
> > This driver acts as the "front end" to V4L2 client applications. It
> > implements the required ioctls and buffer operations, passes the
> > necessary calls on to the bridge, programs the SHIM layer, and performs
> > DMA via the dmaengine API to finally return the data to a buffer
> > supplied by the application.
> > 
> > Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
> > Co-authored-by: Vaishnav Achath <vaishnav.a@ti.com>
> > Signed-off-by: Vaishnav Achath <vaishnav.a@ti.com>
> > Co-authored-by: Jai Luthra <j-luthra@ti.com>
> > Signed-off-by: Jai Luthra <j-luthra@ti.com>
> > ---
> > v7->v8:
> > - Move after dt-bindings to keep the series bisectable
> > - Rename compatible to "ti,j721e-csi2rx-shim" to distinguish from the
> >    SoC-specific CSI2RX bridge compatible
> > - Make myself the Maintainer
> > - Support RAW8 and RAW10 formats, and setting the pixel-unwrap size on
> >    SHIM (RAW10 is stored in 16-bit containers, while RAW8 in 8-bit containers)
> > - Fix enum_fmt_vid_cap() to respect CAP_IO_MC and only list pixelformats
> >    matching the mbus formats set on the subdev.
> > - Fix enum_framesizes() to stop enumerating more than a single framesize
> >    (reject non-zero fsize->index)
> > - Simplify notifier bound fucntion to use v4l2_create_fwnode_links_to_pad()
> >    and inline the video_register() method
> > - Add support for draining the DMA with an extra buffer, to get rid of
> >    stale data in the pipeline on stream stop (or when frames start
> >    getting dropped due to load)
> > - Queue all available buffers to DMAEngine in the callback, also use a
> >    separate "submitted" queue to track all buffers submitted to DMA
> > - Use video_device_pipeline_start() instead of media_pipeline_start()
> > - Drop support for VB_READ
> > - Print issues in link validation as DEBUG instead of ERROR
> > - s/async_subdev/async_connection
> > 
> >   MAINTAINERS                                        |    7 +
> >   drivers/media/platform/ti/Kconfig                  |   12 +
> >   drivers/media/platform/ti/Makefile                 |    1 +
> >   drivers/media/platform/ti/j721e-csi2rx/Makefile    |    2 +
> >   .../media/platform/ti/j721e-csi2rx/j721e-csi2rx.c  | 1127 ++++++++++++++++++++
> >   5 files changed, 1149 insertions(+)
> > 
> > diff --git a/MAINTAINERS b/MAINTAINERS
> > index d7b867c57920..1c2d75c30ce7 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -21445,6 +21445,13 @@ F:	Documentation/devicetree/bindings/media/i2c/ti,ds90*
> >   F:	drivers/media/i2c/ds90*
> >   F:	include/media/i2c/ds90*
> > +TI J721E CSI2RX DRIVER
> > +M:	Jai Luthra <j-luthra@ti.com>
> > +L:	linux-media@vger.kernel.org
> > +S:	Maintained
> > +F:	Documentation/devicetree/bindings/media/ti,j721e-csi2rx.yaml
> > +F:	drivers/media/platform/ti/j721e-csi2rx/
> > +
> >   TI KEYSTONE MULTICORE NAVIGATOR DRIVERS
> >   M:	Nishanth Menon <nm@ti.com>
> >   M:	Santosh Shilimkar <ssantosh@kernel.org>
> > diff --git a/drivers/media/platform/ti/Kconfig b/drivers/media/platform/ti/Kconfig
> > index e1ab56c3be1f..42c908f6e1ae 100644
> > --- a/drivers/media/platform/ti/Kconfig
> > +++ b/drivers/media/platform/ti/Kconfig
> > @@ -63,6 +63,18 @@ config VIDEO_TI_VPE_DEBUG
> >   	help
> >   	  Enable debug messages on VPE driver.
> > +config VIDEO_TI_J721E_CSI2RX
> > +	tristate "TI J721E CSI2RX wrapper layer driver"
> > +	depends on VIDEO_DEV && VIDEO_V4L2_SUBDEV_API
> > +	depends on MEDIA_SUPPORT && MEDIA_CONTROLLER
> > +	depends on PHY_CADENCE_DPHY_RX && VIDEO_CADENCE_CSI2RX
> > +	depends on ARCH_K3 || COMPILE_TEST
> > +	select VIDEOBUF2_DMA_CONTIG
> > +	select V4L2_FWNODE
> > +	help
> > +	  Support for TI CSI2RX wrapper layer. This just enables the wrapper driver.
> > +	  The Cadence CSI2RX bridge driver needs to be enabled separately.
> > +
> >   source "drivers/media/platform/ti/am437x/Kconfig"
> >   source "drivers/media/platform/ti/davinci/Kconfig"
> >   source "drivers/media/platform/ti/omap/Kconfig"
> > diff --git a/drivers/media/platform/ti/Makefile b/drivers/media/platform/ti/Makefile
> > index 98c5fe5c40d6..8a2f74c9380e 100644
> > --- a/drivers/media/platform/ti/Makefile
> > +++ b/drivers/media/platform/ti/Makefile
> > @@ -3,5 +3,6 @@ obj-y += am437x/
> >   obj-y += cal/
> >   obj-y += vpe/
> >   obj-y += davinci/
> > +obj-y += j721e-csi2rx/
> >   obj-y += omap/
> >   obj-y += omap3isp/
> > diff --git a/drivers/media/platform/ti/j721e-csi2rx/Makefile b/drivers/media/platform/ti/j721e-csi2rx/Makefile
> > new file mode 100644
> > index 000000000000..377afc1d6280
> > --- /dev/null
> > +++ b/drivers/media/platform/ti/j721e-csi2rx/Makefile
> > @@ -0,0 +1,2 @@
> > +# SPDX-License-Identifier: GPL-2.0
> > +obj-$(CONFIG_VIDEO_TI_J721E_CSI2RX) += j721e-csi2rx.o
> > diff --git a/drivers/media/platform/ti/j721e-csi2rx/j721e-csi2rx.c b/drivers/media/platform/ti/j721e-csi2rx/j721e-csi2rx.c
> > new file mode 100644
> > index 000000000000..29f1879cfc25
> > --- /dev/null
> > +++ b/drivers/media/platform/ti/j721e-csi2rx/j721e-csi2rx.c
> > @@ -0,0 +1,1127 @@
> > +// SPDX-License-Identifier: GPL-2.0-only
> > +/*
> > + * TI CSI2RX Shim Wrapper Driver
> > + *
> > + * Copyright (C) 2021 Texas Instruments Incorporated - https://www.ti.com/
> 
> You can update the year above.
> 

Will do.

> > + * Author: Pratyush Yadav <p.yadav@ti.com>
> > + */
> > +
> > +#include <linux/bitfield.h>
> > +#include <linux/dmaengine.h>
> > +#include <linux/module.h>
> > +#include <linux/of_platform.h>
> > +#include <linux/platform_device.h>
> > +
> > +#include <media/mipi-csi2.h>
> > +#include <media/v4l2-device.h>
> > +#include <media/v4l2-ioctl.h>
> > +#include <media/v4l2-mc.h>
> > +#include <media/videobuf2-dma-contig.h>
> > +
> > +#define TI_CSI2RX_MODULE_NAME		"j721e-csi2rx"
> > +
> > +#define SHIM_CNTL			0x10
> > +#define SHIM_CNTL_PIX_RST		BIT(0)
> > +
> > +#define SHIM_DMACNTX			0x20
> > +#define SHIM_DMACNTX_EN			BIT(31)
> > +#define SHIM_DMACNTX_YUV422		GENMASK(27, 26)
> > +#define SHIM_DMACNTX_SIZE		GENMASK(21, 20)
> > +#define SHIM_DMACNTX_FMT		GENMASK(5, 0)
> > +#define SHIM_DMACNTX_UYVY		0
> > +#define SHIM_DMACNTX_VYUY		1
> > +#define SHIM_DMACNTX_YUYV		2
> > +#define SHIM_DMACNTX_YVYU		3
> > +#define SHIM_DMACNTX_SIZE_8		0
> > +#define SHIM_DMACNTX_SIZE_16		1
> > +#define SHIM_DMACNTX_SIZE_32		2
> > +
> > +#define SHIM_PSI_CFG0			0x24
> > +#define SHIM_PSI_CFG0_SRC_TAG		GENMASK(15, 0)
> > +#define SHIM_PSI_CFG0_DST_TAG		GENMASK(31, 16)
> > +
> > +#define PSIL_WORD_SIZE_BYTES		16
> > +/*
> > + * There are no hard limits on the width or height. The DMA engine can handle
> > + * all sizes. The max width and height are arbitrary numbers for this driver.
> > + * Use 16K * 16K as the arbitrary limit. It is large enough that it is unlikely
> > + * the limit will be hit in practice.
> > + */
> > +#define MAX_WIDTH_BYTES			SZ_16K
> > +#define MAX_HEIGHT_LINES		SZ_16K
> > +
> > +#define DRAIN_TIMEOUT_MS		50
> > +
> > +struct ti_csi2rx_fmt {
> > +	u32				fourcc;	/* Four character code. */
> > +	u32				code;	/* Mbus code. */
> > +	u32				csi_dt;	/* CSI Data type. */
> > +	u8				bpp;	/* Bits per pixel. */
> > +	u8				size;	/* Data size shift when unpacking. */
> > +};
> > +
> > +struct ti_csi2rx_buffer {
> > +	/* Common v4l2 buffer. Must be first. */
> > +	struct vb2_v4l2_buffer		vb;
> > +	struct list_head		list;
> > +	struct ti_csi2rx_dev		*csi;
> > +};
> > +
> > +enum ti_csi2rx_dma_state {
> > +	TI_CSI2RX_DMA_STOPPED,	/* Streaming not started yet. */
> > +	TI_CSI2RX_DMA_IDLE,	/* Streaming but no pending DMA operation. */
> > +	TI_CSI2RX_DMA_ACTIVE,	/* Streaming and pending DMA operation. */
> > +};
> > +
> > +struct ti_csi2rx_dma {
> > +	/* Protects all fields in this struct. */
> > +	spinlock_t			lock;
> > +	struct dma_chan			*chan;
> > +	/* Buffers queued to the driver, waiting to be processed by DMA. */
> > +	struct list_head		queue;
> > +	enum ti_csi2rx_dma_state	state;
> > +	/*
> > +	 * Queue of buffers submitted to DMA engine.
> > +	 */
> > +	struct list_head		submitted;
> > +};
> > +
> > +struct ti_csi2rx_dev {
> > +	struct device			*dev;
> > +	void __iomem			*shim;
> > +	struct v4l2_device		v4l2_dev;
> > +	struct video_device		vdev;
> > +	struct media_device		mdev;
> > +	struct media_pipeline		pipe;
> > +	struct media_pad		pad;
> > +	struct v4l2_async_notifier	notifier;
> > +	struct v4l2_subdev		*subdev;
> 
> I think "source_subdev" is a better name, to make it clear it's not
> referring to a subdev owned by this driver.
> 

Good catch, for multi-stream support we did end up renaming this to 
"source" as this driver gets a subdev of its own. Will update the name 
here itself in next revision.

> > +	struct vb2_queue		vidq;
> > +	struct mutex			mutex; /* To serialize ioctls. */
> > +	struct v4l2_format		v_fmt;
> > +	struct ti_csi2rx_dma		dma;
> > +	u32				sequence;
> > +};
> > +
> > +static const struct ti_csi2rx_fmt formats[] = {
> > +	{
> > +		.fourcc			= V4L2_PIX_FMT_YUYV,
> > +		.code			= MEDIA_BUS_FMT_YUYV8_1X16,
> > +		.csi_dt			= MIPI_CSI2_DT_YUV422_8B,
> > +		.bpp			= 16,
> > +		.size			= SHIM_DMACNTX_SIZE_8,
> > +	}, {
> > +		.fourcc			= V4L2_PIX_FMT_UYVY,
> > +		.code			= MEDIA_BUS_FMT_UYVY8_1X16,
> > +		.csi_dt			= MIPI_CSI2_DT_YUV422_8B,
> > +		.bpp			= 16,
> > +		.size			= SHIM_DMACNTX_SIZE_8,
> > +	}, {
> > +		.fourcc			= V4L2_PIX_FMT_YVYU,
> > +		.code			= MEDIA_BUS_FMT_YVYU8_1X16,
> > +		.csi_dt			= MIPI_CSI2_DT_YUV422_8B,
> > +		.bpp			= 16,
> > +		.size			= SHIM_DMACNTX_SIZE_8,
> > +	}, {
> > +		.fourcc			= V4L2_PIX_FMT_VYUY,
> > +		.code			= MEDIA_BUS_FMT_VYUY8_1X16,
> > +		.csi_dt			= MIPI_CSI2_DT_YUV422_8B,
> > +		.bpp			= 16,
> > +		.size			= SHIM_DMACNTX_SIZE_8,
> > +	}, {
> > +		.fourcc			= V4L2_PIX_FMT_SBGGR8,
> > +		.code			= MEDIA_BUS_FMT_SBGGR8_1X8,
> > +		.csi_dt			= MIPI_CSI2_DT_RAW8,
> > +		.bpp			= 8,
> > +		.size			= SHIM_DMACNTX_SIZE_8,
> > +	}, {
> > +		.fourcc			= V4L2_PIX_FMT_SGBRG8,
> > +		.code			= MEDIA_BUS_FMT_SGBRG8_1X8,
> > +		.csi_dt			= MIPI_CSI2_DT_RAW8,
> > +		.bpp			= 8,
> > +		.size			= SHIM_DMACNTX_SIZE_8,
> > +	}, {
> > +		.fourcc			= V4L2_PIX_FMT_SGRBG8,
> > +		.code			= MEDIA_BUS_FMT_SGRBG8_1X8,
> > +		.csi_dt			= MIPI_CSI2_DT_RAW8,
> > +		.bpp			= 8,
> > +		.size			= SHIM_DMACNTX_SIZE_8,
> > +	}, {
> > +		.fourcc			= V4L2_PIX_FMT_SRGGB8,
> > +		.code			= MEDIA_BUS_FMT_SRGGB8_1X8,
> > +		.csi_dt			= MIPI_CSI2_DT_RAW8,
> > +		.bpp			= 8,
> > +		.size			= SHIM_DMACNTX_SIZE_8,
> > +	}, {
> > +		.fourcc			= V4L2_PIX_FMT_SBGGR10,
> > +		.code			= MEDIA_BUS_FMT_SBGGR10_1X10,
> > +		.csi_dt			= MIPI_CSI2_DT_RAW10,
> > +		.bpp			= 16,
> > +		.size			= SHIM_DMACNTX_SIZE_16,
> > +	}, {
> > +		.fourcc			= V4L2_PIX_FMT_SGBRG10,
> > +		.code			= MEDIA_BUS_FMT_SGBRG10_1X10,
> > +		.csi_dt			= MIPI_CSI2_DT_RAW10,
> > +		.bpp			= 16,
> > +		.size			= SHIM_DMACNTX_SIZE_16,
> > +	}, {
> > +		.fourcc			= V4L2_PIX_FMT_SGRBG10,
> > +		.code			= MEDIA_BUS_FMT_SGRBG10_1X10,
> > +		.csi_dt			= MIPI_CSI2_DT_RAW10,
> > +		.bpp			= 16,
> > +		.size			= SHIM_DMACNTX_SIZE_16,
> > +	}, {
> > +		.fourcc			= V4L2_PIX_FMT_SRGGB10,
> > +		.code			= MEDIA_BUS_FMT_SRGGB10_1X10,
> > +		.csi_dt			= MIPI_CSI2_DT_RAW10,
> > +		.bpp			= 16,
> > +		.size			= SHIM_DMACNTX_SIZE_16,
> > +	},
> > +
> > +	/* More formats can be supported but they are not listed for now. */
> > +};
> > +
> > +static const unsigned int num_formats = ARRAY_SIZE(formats);
> > +
> > +/* Forward declaration needed by ti_csi2rx_dma_callback. */
> > +static int ti_csi2rx_start_dma(struct ti_csi2rx_dev *csi,
> > +			       struct ti_csi2rx_buffer *buf);
> > +
> > +static const struct ti_csi2rx_fmt *find_format_by_pix(u32 pixelformat)
> > +{
> > +	unsigned int i;
> > +
> > +	for (i = 0; i < num_formats; i++) {
> > +		if (formats[i].fourcc == pixelformat)
> > +			return &formats[i];
> > +	}
> > +
> > +	return NULL;
> > +}
> > +
> > +static const struct ti_csi2rx_fmt *find_format_by_code(u32 code)
> > +{
> > +	unsigned int i;
> > +
> > +	for (i = 0; i < num_formats; i++) {
> > +		if (formats[i].code == code)
> > +			return &formats[i];
> > +	}
> > +
> > +	return NULL;
> > +}
> > +
> > +static void ti_csi2rx_fill_fmt(const struct ti_csi2rx_fmt *csi_fmt,
> > +			       struct v4l2_format *v4l2_fmt)
> > +{
> > +	struct v4l2_pix_format *pix = &v4l2_fmt->fmt.pix;
> > +	unsigned int pixels_in_word;
> > +	u8 bpp = csi_fmt->bpp;
> > +	u32 bpl;
> > +
> > +	pixels_in_word = PSIL_WORD_SIZE_BYTES * 8 / bpp;
> > +
> > +	pix->width = clamp_t(unsigned int, pix->width,
> > +			     pixels_in_word,
> > +			     MAX_WIDTH_BYTES * 8 / bpp);
> > +	pix->width = rounddown(pix->width, pixels_in_word);
> > +
> > +	pix->height = clamp_t(unsigned int, pix->height, 1, MAX_HEIGHT_LINES);
> > +
> > +	v4l2_fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
> > +	pix->pixelformat = csi_fmt->fourcc;
> > +	pix->colorspace = V4L2_COLORSPACE_SRGB;
> > +	pix->sizeimage = pix->height * pix->width * (bpp / 8);
> > +
> > +	bpl = (pix->width * ALIGN(bpp, 8)) >> 3;
> 
> You do "/ 8" and "* 8" elsewhere in the function, so I think it makes sense
> to "/ 8" here too, instead of ">> 3".

Will fix.

> 
> Is this correct? Why is aligned bpp used here, but when calculating
> sizeimage, bpp is not aligned?

Hmm I agree this whole function is quite confusing, It should either be 
ALIGN(bpp, 8) everywhere or we can just remove that given the hardware 
is unwrapping currently supported formats to multiples of 8 bits (even 
RAW10/RAW12) and the bpp in the table above matches that.

> 
> > +	pix->bytesperline = ALIGN(bpl, 16);
> 
> Why align to 16?

This might be redundant given we are rounding down the width to make 
sure it's a multiple of PSIL_WORD_SIZE_BYTES.

> 
> Shouldn't sizeimage usually be bytesperline * height?
> 
> You could add a few comments here to clarify all the aligns, roundings and
> clampings.

Will do.

> 
> > +}
> > +
> > +static int ti_csi2rx_querycap(struct file *file, void *priv,
> > +			      struct v4l2_capability *cap)
> > +{
> > +	strscpy(cap->driver, TI_CSI2RX_MODULE_NAME, sizeof(cap->driver));
> > +	strscpy(cap->card, TI_CSI2RX_MODULE_NAME, sizeof(cap->card));
> > +
> > +	return 0;
> > +}
> > +
> > +static int ti_csi2rx_enum_fmt_vid_cap(struct file *file, void *priv,
> > +				      struct v4l2_fmtdesc *f)
> > +{
> > +	const struct ti_csi2rx_fmt *fmt = NULL;
> > +
> > +	if (f->mbus_code) {
> > +		if (f->index > 0)
> > +			return -EINVAL;
> 
> This fails to enumerate the formats if mbus_code is set, doesn't it?
> 

Sakari is correct, this is required according to the spec for devices 
that set the V4L2_CAP_IO_MC capability. Caught this while enabling 
libcamera simple pipeline:)

> > +
> > +		fmt = find_format_by_code(f->mbus_code);
> > +	} else {
> > +		if (f->index >= num_formats)
> > +			return -EINVAL;
> > +
> > +		fmt = &formats[f->index];
> > +	}
> > +
> > +	if (!fmt)
> > +		return -EINVAL;
> > +
> > +	f->pixelformat = fmt->fourcc;
> > +	memset(f->reserved, 0, sizeof(f->reserved));
> > +	f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
> > +
> > +	return 0;
> > +}
> > +
> > +static int ti_csi2rx_g_fmt_vid_cap(struct file *file, void *prov,
> > +				   struct v4l2_format *f)
> > +{
> > +	struct ti_csi2rx_dev *csi = video_drvdata(file);
> > +
> > +	*f = csi->v_fmt;
> > +
> > +	return 0;
> > +}
> > +
> > +static int ti_csi2rx_try_fmt_vid_cap(struct file *file, void *priv,
> > +				     struct v4l2_format *f)
> > +{
> > +	const struct ti_csi2rx_fmt *fmt;
> > +
> > +	/*
> > +	 * Default to the first format if the requested pixel format code isn't
> > +	 * supported.
> > +	 */
> > +	fmt = find_format_by_pix(f->fmt.pix.pixelformat);
> > +	if (!fmt)
> > +		fmt = &formats[0];
> > +
> > +	if (f->fmt.pix.field == V4L2_FIELD_ANY)
> > +		f->fmt.pix.field = V4L2_FIELD_NONE;
> > +
> > +	if (f->fmt.pix.field != V4L2_FIELD_NONE)
> > +		/* Interlaced formats are not supported. */
> > +		f->fmt.pix.field = V4L2_FIELD_NONE;
> 
> Can't you just always set the field to V4L2_FIELD_NONE?
> 

Will fix.

> > +	ti_csi2rx_fill_fmt(fmt, f);
> > +
> > +	return 0;
> > +}
> > +
> > +static int ti_csi2rx_s_fmt_vid_cap(struct file *file, void *priv,
> > +				   struct v4l2_format *f)
> > +{
> > +	struct ti_csi2rx_dev *csi = video_drvdata(file);
> > +	struct vb2_queue *q = &csi->vidq;
> > +	int ret;
> > +
> > +	if (vb2_is_busy(q))
> > +		return -EBUSY;
> > +
> > +	ret = ti_csi2rx_try_fmt_vid_cap(file, priv, f);
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	csi->v_fmt = *f;
> > +
> > +	return 0;
> > +}
> > +
> > +static int ti_csi2rx_enum_framesizes(struct file *file, void *fh,
> > +				     struct v4l2_frmsizeenum *fsize)
> > +{
> > +	const struct ti_csi2rx_fmt *fmt;
> > +	unsigned int pixels_in_word;
> > +	u8 bpp;
> > +
> > +	fmt = find_format_by_pix(fsize->pixel_format);
> > +	if (!fmt || fsize->index != 0)
> > +		return -EINVAL;
> > +
> > +	bpp = ALIGN(fmt->bpp, 8);
> > +
> > +	/*
> > +	 * Number of pixels in one PSI-L word. The transfer happens in multiples
> > +	 * of PSI-L word sizes.
> > +	 */
> > +	pixels_in_word = PSIL_WORD_SIZE_BYTES * 8 / bpp;
> > +
> > +	fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
> > +	fsize->stepwise.min_width = pixels_in_word;
> > +	fsize->stepwise.max_width = rounddown(MAX_WIDTH_BYTES * 8 / bpp,
> > +					      pixels_in_word);
> > +	fsize->stepwise.step_width = pixels_in_word;
> > +	fsize->stepwise.min_height = 1;
> > +	fsize->stepwise.max_height = MAX_HEIGHT_LINES;
> > +	fsize->stepwise.step_height = 1;
> > +
> > +	return 0;
> > +}
> > +
> > +static const struct v4l2_ioctl_ops csi_ioctl_ops = {
> > +	.vidioc_querycap      = ti_csi2rx_querycap,
> > +	.vidioc_enum_fmt_vid_cap = ti_csi2rx_enum_fmt_vid_cap,
> > +	.vidioc_try_fmt_vid_cap = ti_csi2rx_try_fmt_vid_cap,
> > +	.vidioc_g_fmt_vid_cap = ti_csi2rx_g_fmt_vid_cap,
> > +	.vidioc_s_fmt_vid_cap = ti_csi2rx_s_fmt_vid_cap,
> > +	.vidioc_enum_framesizes = ti_csi2rx_enum_framesizes,
> > +	.vidioc_reqbufs       = vb2_ioctl_reqbufs,
> > +	.vidioc_create_bufs   = vb2_ioctl_create_bufs,
> > +	.vidioc_prepare_buf   = vb2_ioctl_prepare_buf,
> > +	.vidioc_querybuf      = vb2_ioctl_querybuf,
> > +	.vidioc_qbuf          = vb2_ioctl_qbuf,
> > +	.vidioc_dqbuf         = vb2_ioctl_dqbuf,
> > +	.vidioc_expbuf        = vb2_ioctl_expbuf,
> > +	.vidioc_streamon      = vb2_ioctl_streamon,
> > +	.vidioc_streamoff     = vb2_ioctl_streamoff,
> > +};
> > +
> > +static const struct v4l2_file_operations csi_fops = {
> > +	.owner = THIS_MODULE,
> > +	.open = v4l2_fh_open,
> > +	.release = vb2_fop_release,
> > +	.read = vb2_fop_read,
> > +	.poll = vb2_fop_poll,
> > +	.unlocked_ioctl = video_ioctl2,
> > +	.mmap = vb2_fop_mmap,
> > +};
> > +
> > +static int csi_async_notifier_bound(struct v4l2_async_notifier *notifier,
> > +				    struct v4l2_subdev *subdev,
> > +				    struct v4l2_async_connection *asc)
> > +{
> > +	struct ti_csi2rx_dev *csi = dev_get_drvdata(notifier->v4l2_dev->dev);
> > +
> > +	csi->subdev = subdev;
> > +
> > +	return 0;
> > +}
> > +
> > +static int csi_async_notifier_complete(struct v4l2_async_notifier *notifier)
> > +{
> > +	struct ti_csi2rx_dev *csi = dev_get_drvdata(notifier->v4l2_dev->dev);
> > +	struct video_device *vdev = &csi->vdev;
> > +	int ret;
> > +
> > +	ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1);
> > +	if (ret)
> > +		return ret;
> > +
> > +	ret = v4l2_create_fwnode_links_to_pad(csi->subdev, &csi->pad,
> > +					      MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED);
> > +
> > +	if (ret) {
> > +		video_unregister_device(vdev);
> > +		return ret;
> > +	}
> > +
> > +	return v4l2_device_register_subdev_nodes(&csi->v4l2_dev);
> > +}
> > +
> > +static const struct v4l2_async_notifier_operations csi_async_notifier_ops = {
> > +	.bound = csi_async_notifier_bound,
> > +	.complete = csi_async_notifier_complete,
> > +};
> > +
> > +static int ti_csi2rx_init_subdev(struct ti_csi2rx_dev *csi)
> 
> This is misnamed. ti_csi2rx_async_notifier_register()?
> 

Will fix.

> > +{
> > +	struct fwnode_handle *fwnode;
> > +	struct v4l2_async_connection *asc;
> > +	struct device_node *node;
> > +	int ret;
> > +
> > +	node = of_get_child_by_name(csi->dev->of_node, "csi-bridge");
> > +	if (!node)
> > +		return -EINVAL;
> > +
> > +	fwnode = of_fwnode_handle(node);
> > +	if (!fwnode) {
> > +		of_node_put(node);
> > +		return -EINVAL;
> > +	}
> > +
> > +	v4l2_async_nf_init(&csi->notifier, &csi->v4l2_dev);
> > +	csi->notifier.ops = &csi_async_notifier_ops;
> > +
> > +	asc = v4l2_async_nf_add_fwnode(&csi->notifier, fwnode,
> > +				       struct v4l2_async_connection);
> > +	of_node_put(node);
> > +	if (IS_ERR(asc)) {
> > +		v4l2_async_nf_cleanup(&csi->notifier);
> > +		return PTR_ERR(asc);
> > +	}
> > +
> > +	ret = v4l2_async_nf_register(&csi->notifier);
> > +	if (ret) {
> > +		v4l2_async_nf_cleanup(&csi->notifier);
> > +		return ret;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +static void ti_csi2rx_setup_shim(struct ti_csi2rx_dev *csi)
> > +{
> > +	const struct ti_csi2rx_fmt *fmt;
> > +	unsigned int reg;
> > +
> > +	fmt = find_format_by_pix(csi->v_fmt.fmt.pix.pixelformat);
> > +	if (!fmt) {
> > +		dev_err(csi->dev, "Unknown format\n");
> > +		return;
> > +	}
> 
> The error print here is rather vague, and as there's no error code returned,
> the caller doesn't handle the error.
> 

Will fix.

> > +
> > +	/* De-assert the pixel interface reset. */
> > +	reg = SHIM_CNTL_PIX_RST;
> > +	writel(reg, csi->shim + SHIM_CNTL);
> > +
> > +	reg = SHIM_DMACNTX_EN;
> > +	reg |= FIELD_PREP(SHIM_DMACNTX_FMT, fmt->csi_dt);
> > +
> > +	/*
> > +	 * Using the values from the documentation gives incorrect ordering for
> > +	 * the luma and chroma components. In practice, the "reverse" format
> > +	 * gives the correct image. So for example, if the image is in UYVY, the
> > +	 * reverse would be YVYU.
> > +	 */
> > +	switch (fmt->fourcc) {
> > +	case V4L2_PIX_FMT_UYVY:
> > +		reg |= FIELD_PREP(SHIM_DMACNTX_YUV422,
> > +					SHIM_DMACNTX_YVYU);
> > +		break;
> > +	case V4L2_PIX_FMT_VYUY:
> > +		reg |= FIELD_PREP(SHIM_DMACNTX_YUV422,
> > +					SHIM_DMACNTX_YUYV);
> > +		break;
> > +	case V4L2_PIX_FMT_YUYV:
> > +		reg |= FIELD_PREP(SHIM_DMACNTX_YUV422,
> > +					SHIM_DMACNTX_VYUY);
> > +		break;
> > +	case V4L2_PIX_FMT_YVYU:
> > +		reg |= FIELD_PREP(SHIM_DMACNTX_YUV422,
> > +					SHIM_DMACNTX_UYVY);
> > +		break;
> > +	default:
> > +		/* Ignore if not YUV 4:2:2 */
> > +		break;
> > +	}
> > +
> > +	reg |= FIELD_PREP(SHIM_DMACNTX_SIZE, fmt->size);
> > +
> > +	writel(reg, csi->shim + SHIM_DMACNTX);
> > +
> > +	reg = FIELD_PREP(SHIM_PSI_CFG0_SRC_TAG, 0) |
> > +	      FIELD_PREP(SHIM_PSI_CFG0_DST_TAG, 0);
> > +	writel(reg, csi->shim + SHIM_PSI_CFG0);
> > +}
> > +
> > +static void ti_csi2rx_drain_callback(void *param)
> > +{
> > +	struct completion *drain_complete = param;
> > +
> > +	complete(drain_complete);
> > +}
> > +
> > +static int ti_csi2rx_drain_dma(struct ti_csi2rx_dev *csi)
> > +{
> 
> I think it would be good to explain in a comment somewhere what why this dma
> draining is needed and how it works.
> 

Makes sense, will do.

> > +	struct dma_async_tx_descriptor *desc;
> > +	struct device *dev = csi->dma.chan->device->dev;
> > +	struct completion drain_complete;
> > +	void *buf;
> > +	size_t len = csi->v_fmt.fmt.pix.sizeimage;
> > +	dma_addr_t addr;
> > +	dma_cookie_t cookie;
> > +	int ret;
> > +
> > +	init_completion(&drain_complete);
> > +
> > +	buf = dma_alloc_coherent(dev, len, &addr, GFP_KERNEL | GFP_ATOMIC);
> > +	if (!buf)
> > +		return -ENOMEM;
> 
> If I understand right, this is called when the streaming is stopped, but
> could also be called on frame drops? You're allocating a DMA buffer for a
> full frame. Large runtime DMA buffer allocations are a bit scary. What
> happens if it fails?
> 
> Is it possible to preallocate, or use smaller buffers (perhaps with multiple
> dma operations) to do the flush?
> 
> The dma doesn't support writing to a constant address, does it (in which
> case a very small buffer would suffice)?

Hmm you're absolutely right. Will have to experiment if doing multiple 
dma ops on a small buffer would be feasible for multi-camera/stream 
scenarios. But at the minimum will switch to allocating the drain buffer 
only one time in the next revision.

> 
>  Tomi
> 

-- 
Thanks,
Jai

GPG Fingerprint: 4DE0 D818 E5D5 75E8 D45A AFC5 43DE 91F9 249A 7145

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v8 16/16] media: ti: Add CSI2RX support for J721E
@ 2023-08-03 11:51       ` Jai Luthra
  0 siblings, 0 replies; 84+ messages in thread
From: Jai Luthra @ 2023-08-03 11:51 UTC (permalink / raw)
  To: Tomi Valkeinen
  Cc: Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Sakari Ailus, Laurent Pinchart, linux-media,
	linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht


[-- Attachment #1.1: Type: text/plain, Size: 25482 bytes --]

Hi Tomi,

Thanks for the review.

On Aug 02, 2023 at 14:04:57 +0300, Tomi Valkeinen wrote:
> On 31/07/2023 11:29, Jai Luthra wrote:
> > From: Pratyush Yadav <p.yadav@ti.com>
> > 
> > TI's J721E uses the Cadence CSI2RX and DPHY peripherals to facilitate
> > capture over a CSI-2 bus.
> > 
> > The Cadence CSI2RX IP acts as a bridge between the TI specific parts and
> > the CSI-2 protocol parts. TI then has a wrapper on top of this bridge
> > called the SHIM layer. It takes in data from stream 0, repacks it, and
> > sends it to memory over PSI-L DMA.
> > 
> > This driver acts as the "front end" to V4L2 client applications. It
> > implements the required ioctls and buffer operations, passes the
> > necessary calls on to the bridge, programs the SHIM layer, and performs
> > DMA via the dmaengine API to finally return the data to a buffer
> > supplied by the application.
> > 
> > Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
> > Co-authored-by: Vaishnav Achath <vaishnav.a@ti.com>
> > Signed-off-by: Vaishnav Achath <vaishnav.a@ti.com>
> > Co-authored-by: Jai Luthra <j-luthra@ti.com>
> > Signed-off-by: Jai Luthra <j-luthra@ti.com>
> > ---
> > v7->v8:
> > - Move after dt-bindings to keep the series bisectable
> > - Rename compatible to "ti,j721e-csi2rx-shim" to distinguish from the
> >    SoC-specific CSI2RX bridge compatible
> > - Make myself the Maintainer
> > - Support RAW8 and RAW10 formats, and setting the pixel-unwrap size on
> >    SHIM (RAW10 is stored in 16-bit containers, while RAW8 in 8-bit containers)
> > - Fix enum_fmt_vid_cap() to respect CAP_IO_MC and only list pixelformats
> >    matching the mbus formats set on the subdev.
> > - Fix enum_framesizes() to stop enumerating more than a single framesize
> >    (reject non-zero fsize->index)
> > - Simplify notifier bound fucntion to use v4l2_create_fwnode_links_to_pad()
> >    and inline the video_register() method
> > - Add support for draining the DMA with an extra buffer, to get rid of
> >    stale data in the pipeline on stream stop (or when frames start
> >    getting dropped due to load)
> > - Queue all available buffers to DMAEngine in the callback, also use a
> >    separate "submitted" queue to track all buffers submitted to DMA
> > - Use video_device_pipeline_start() instead of media_pipeline_start()
> > - Drop support for VB_READ
> > - Print issues in link validation as DEBUG instead of ERROR
> > - s/async_subdev/async_connection
> > 
> >   MAINTAINERS                                        |    7 +
> >   drivers/media/platform/ti/Kconfig                  |   12 +
> >   drivers/media/platform/ti/Makefile                 |    1 +
> >   drivers/media/platform/ti/j721e-csi2rx/Makefile    |    2 +
> >   .../media/platform/ti/j721e-csi2rx/j721e-csi2rx.c  | 1127 ++++++++++++++++++++
> >   5 files changed, 1149 insertions(+)
> > 
> > diff --git a/MAINTAINERS b/MAINTAINERS
> > index d7b867c57920..1c2d75c30ce7 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -21445,6 +21445,13 @@ F:	Documentation/devicetree/bindings/media/i2c/ti,ds90*
> >   F:	drivers/media/i2c/ds90*
> >   F:	include/media/i2c/ds90*
> > +TI J721E CSI2RX DRIVER
> > +M:	Jai Luthra <j-luthra@ti.com>
> > +L:	linux-media@vger.kernel.org
> > +S:	Maintained
> > +F:	Documentation/devicetree/bindings/media/ti,j721e-csi2rx.yaml
> > +F:	drivers/media/platform/ti/j721e-csi2rx/
> > +
> >   TI KEYSTONE MULTICORE NAVIGATOR DRIVERS
> >   M:	Nishanth Menon <nm@ti.com>
> >   M:	Santosh Shilimkar <ssantosh@kernel.org>
> > diff --git a/drivers/media/platform/ti/Kconfig b/drivers/media/platform/ti/Kconfig
> > index e1ab56c3be1f..42c908f6e1ae 100644
> > --- a/drivers/media/platform/ti/Kconfig
> > +++ b/drivers/media/platform/ti/Kconfig
> > @@ -63,6 +63,18 @@ config VIDEO_TI_VPE_DEBUG
> >   	help
> >   	  Enable debug messages on VPE driver.
> > +config VIDEO_TI_J721E_CSI2RX
> > +	tristate "TI J721E CSI2RX wrapper layer driver"
> > +	depends on VIDEO_DEV && VIDEO_V4L2_SUBDEV_API
> > +	depends on MEDIA_SUPPORT && MEDIA_CONTROLLER
> > +	depends on PHY_CADENCE_DPHY_RX && VIDEO_CADENCE_CSI2RX
> > +	depends on ARCH_K3 || COMPILE_TEST
> > +	select VIDEOBUF2_DMA_CONTIG
> > +	select V4L2_FWNODE
> > +	help
> > +	  Support for TI CSI2RX wrapper layer. This just enables the wrapper driver.
> > +	  The Cadence CSI2RX bridge driver needs to be enabled separately.
> > +
> >   source "drivers/media/platform/ti/am437x/Kconfig"
> >   source "drivers/media/platform/ti/davinci/Kconfig"
> >   source "drivers/media/platform/ti/omap/Kconfig"
> > diff --git a/drivers/media/platform/ti/Makefile b/drivers/media/platform/ti/Makefile
> > index 98c5fe5c40d6..8a2f74c9380e 100644
> > --- a/drivers/media/platform/ti/Makefile
> > +++ b/drivers/media/platform/ti/Makefile
> > @@ -3,5 +3,6 @@ obj-y += am437x/
> >   obj-y += cal/
> >   obj-y += vpe/
> >   obj-y += davinci/
> > +obj-y += j721e-csi2rx/
> >   obj-y += omap/
> >   obj-y += omap3isp/
> > diff --git a/drivers/media/platform/ti/j721e-csi2rx/Makefile b/drivers/media/platform/ti/j721e-csi2rx/Makefile
> > new file mode 100644
> > index 000000000000..377afc1d6280
> > --- /dev/null
> > +++ b/drivers/media/platform/ti/j721e-csi2rx/Makefile
> > @@ -0,0 +1,2 @@
> > +# SPDX-License-Identifier: GPL-2.0
> > +obj-$(CONFIG_VIDEO_TI_J721E_CSI2RX) += j721e-csi2rx.o
> > diff --git a/drivers/media/platform/ti/j721e-csi2rx/j721e-csi2rx.c b/drivers/media/platform/ti/j721e-csi2rx/j721e-csi2rx.c
> > new file mode 100644
> > index 000000000000..29f1879cfc25
> > --- /dev/null
> > +++ b/drivers/media/platform/ti/j721e-csi2rx/j721e-csi2rx.c
> > @@ -0,0 +1,1127 @@
> > +// SPDX-License-Identifier: GPL-2.0-only
> > +/*
> > + * TI CSI2RX Shim Wrapper Driver
> > + *
> > + * Copyright (C) 2021 Texas Instruments Incorporated - https://www.ti.com/
> 
> You can update the year above.
> 

Will do.

> > + * Author: Pratyush Yadav <p.yadav@ti.com>
> > + */
> > +
> > +#include <linux/bitfield.h>
> > +#include <linux/dmaengine.h>
> > +#include <linux/module.h>
> > +#include <linux/of_platform.h>
> > +#include <linux/platform_device.h>
> > +
> > +#include <media/mipi-csi2.h>
> > +#include <media/v4l2-device.h>
> > +#include <media/v4l2-ioctl.h>
> > +#include <media/v4l2-mc.h>
> > +#include <media/videobuf2-dma-contig.h>
> > +
> > +#define TI_CSI2RX_MODULE_NAME		"j721e-csi2rx"
> > +
> > +#define SHIM_CNTL			0x10
> > +#define SHIM_CNTL_PIX_RST		BIT(0)
> > +
> > +#define SHIM_DMACNTX			0x20
> > +#define SHIM_DMACNTX_EN			BIT(31)
> > +#define SHIM_DMACNTX_YUV422		GENMASK(27, 26)
> > +#define SHIM_DMACNTX_SIZE		GENMASK(21, 20)
> > +#define SHIM_DMACNTX_FMT		GENMASK(5, 0)
> > +#define SHIM_DMACNTX_UYVY		0
> > +#define SHIM_DMACNTX_VYUY		1
> > +#define SHIM_DMACNTX_YUYV		2
> > +#define SHIM_DMACNTX_YVYU		3
> > +#define SHIM_DMACNTX_SIZE_8		0
> > +#define SHIM_DMACNTX_SIZE_16		1
> > +#define SHIM_DMACNTX_SIZE_32		2
> > +
> > +#define SHIM_PSI_CFG0			0x24
> > +#define SHIM_PSI_CFG0_SRC_TAG		GENMASK(15, 0)
> > +#define SHIM_PSI_CFG0_DST_TAG		GENMASK(31, 16)
> > +
> > +#define PSIL_WORD_SIZE_BYTES		16
> > +/*
> > + * There are no hard limits on the width or height. The DMA engine can handle
> > + * all sizes. The max width and height are arbitrary numbers for this driver.
> > + * Use 16K * 16K as the arbitrary limit. It is large enough that it is unlikely
> > + * the limit will be hit in practice.
> > + */
> > +#define MAX_WIDTH_BYTES			SZ_16K
> > +#define MAX_HEIGHT_LINES		SZ_16K
> > +
> > +#define DRAIN_TIMEOUT_MS		50
> > +
> > +struct ti_csi2rx_fmt {
> > +	u32				fourcc;	/* Four character code. */
> > +	u32				code;	/* Mbus code. */
> > +	u32				csi_dt;	/* CSI Data type. */
> > +	u8				bpp;	/* Bits per pixel. */
> > +	u8				size;	/* Data size shift when unpacking. */
> > +};
> > +
> > +struct ti_csi2rx_buffer {
> > +	/* Common v4l2 buffer. Must be first. */
> > +	struct vb2_v4l2_buffer		vb;
> > +	struct list_head		list;
> > +	struct ti_csi2rx_dev		*csi;
> > +};
> > +
> > +enum ti_csi2rx_dma_state {
> > +	TI_CSI2RX_DMA_STOPPED,	/* Streaming not started yet. */
> > +	TI_CSI2RX_DMA_IDLE,	/* Streaming but no pending DMA operation. */
> > +	TI_CSI2RX_DMA_ACTIVE,	/* Streaming and pending DMA operation. */
> > +};
> > +
> > +struct ti_csi2rx_dma {
> > +	/* Protects all fields in this struct. */
> > +	spinlock_t			lock;
> > +	struct dma_chan			*chan;
> > +	/* Buffers queued to the driver, waiting to be processed by DMA. */
> > +	struct list_head		queue;
> > +	enum ti_csi2rx_dma_state	state;
> > +	/*
> > +	 * Queue of buffers submitted to DMA engine.
> > +	 */
> > +	struct list_head		submitted;
> > +};
> > +
> > +struct ti_csi2rx_dev {
> > +	struct device			*dev;
> > +	void __iomem			*shim;
> > +	struct v4l2_device		v4l2_dev;
> > +	struct video_device		vdev;
> > +	struct media_device		mdev;
> > +	struct media_pipeline		pipe;
> > +	struct media_pad		pad;
> > +	struct v4l2_async_notifier	notifier;
> > +	struct v4l2_subdev		*subdev;
> 
> I think "source_subdev" is a better name, to make it clear it's not
> referring to a subdev owned by this driver.
> 

Good catch, for multi-stream support we did end up renaming this to 
"source" as this driver gets a subdev of its own. Will update the name 
here itself in next revision.

> > +	struct vb2_queue		vidq;
> > +	struct mutex			mutex; /* To serialize ioctls. */
> > +	struct v4l2_format		v_fmt;
> > +	struct ti_csi2rx_dma		dma;
> > +	u32				sequence;
> > +};
> > +
> > +static const struct ti_csi2rx_fmt formats[] = {
> > +	{
> > +		.fourcc			= V4L2_PIX_FMT_YUYV,
> > +		.code			= MEDIA_BUS_FMT_YUYV8_1X16,
> > +		.csi_dt			= MIPI_CSI2_DT_YUV422_8B,
> > +		.bpp			= 16,
> > +		.size			= SHIM_DMACNTX_SIZE_8,
> > +	}, {
> > +		.fourcc			= V4L2_PIX_FMT_UYVY,
> > +		.code			= MEDIA_BUS_FMT_UYVY8_1X16,
> > +		.csi_dt			= MIPI_CSI2_DT_YUV422_8B,
> > +		.bpp			= 16,
> > +		.size			= SHIM_DMACNTX_SIZE_8,
> > +	}, {
> > +		.fourcc			= V4L2_PIX_FMT_YVYU,
> > +		.code			= MEDIA_BUS_FMT_YVYU8_1X16,
> > +		.csi_dt			= MIPI_CSI2_DT_YUV422_8B,
> > +		.bpp			= 16,
> > +		.size			= SHIM_DMACNTX_SIZE_8,
> > +	}, {
> > +		.fourcc			= V4L2_PIX_FMT_VYUY,
> > +		.code			= MEDIA_BUS_FMT_VYUY8_1X16,
> > +		.csi_dt			= MIPI_CSI2_DT_YUV422_8B,
> > +		.bpp			= 16,
> > +		.size			= SHIM_DMACNTX_SIZE_8,
> > +	}, {
> > +		.fourcc			= V4L2_PIX_FMT_SBGGR8,
> > +		.code			= MEDIA_BUS_FMT_SBGGR8_1X8,
> > +		.csi_dt			= MIPI_CSI2_DT_RAW8,
> > +		.bpp			= 8,
> > +		.size			= SHIM_DMACNTX_SIZE_8,
> > +	}, {
> > +		.fourcc			= V4L2_PIX_FMT_SGBRG8,
> > +		.code			= MEDIA_BUS_FMT_SGBRG8_1X8,
> > +		.csi_dt			= MIPI_CSI2_DT_RAW8,
> > +		.bpp			= 8,
> > +		.size			= SHIM_DMACNTX_SIZE_8,
> > +	}, {
> > +		.fourcc			= V4L2_PIX_FMT_SGRBG8,
> > +		.code			= MEDIA_BUS_FMT_SGRBG8_1X8,
> > +		.csi_dt			= MIPI_CSI2_DT_RAW8,
> > +		.bpp			= 8,
> > +		.size			= SHIM_DMACNTX_SIZE_8,
> > +	}, {
> > +		.fourcc			= V4L2_PIX_FMT_SRGGB8,
> > +		.code			= MEDIA_BUS_FMT_SRGGB8_1X8,
> > +		.csi_dt			= MIPI_CSI2_DT_RAW8,
> > +		.bpp			= 8,
> > +		.size			= SHIM_DMACNTX_SIZE_8,
> > +	}, {
> > +		.fourcc			= V4L2_PIX_FMT_SBGGR10,
> > +		.code			= MEDIA_BUS_FMT_SBGGR10_1X10,
> > +		.csi_dt			= MIPI_CSI2_DT_RAW10,
> > +		.bpp			= 16,
> > +		.size			= SHIM_DMACNTX_SIZE_16,
> > +	}, {
> > +		.fourcc			= V4L2_PIX_FMT_SGBRG10,
> > +		.code			= MEDIA_BUS_FMT_SGBRG10_1X10,
> > +		.csi_dt			= MIPI_CSI2_DT_RAW10,
> > +		.bpp			= 16,
> > +		.size			= SHIM_DMACNTX_SIZE_16,
> > +	}, {
> > +		.fourcc			= V4L2_PIX_FMT_SGRBG10,
> > +		.code			= MEDIA_BUS_FMT_SGRBG10_1X10,
> > +		.csi_dt			= MIPI_CSI2_DT_RAW10,
> > +		.bpp			= 16,
> > +		.size			= SHIM_DMACNTX_SIZE_16,
> > +	}, {
> > +		.fourcc			= V4L2_PIX_FMT_SRGGB10,
> > +		.code			= MEDIA_BUS_FMT_SRGGB10_1X10,
> > +		.csi_dt			= MIPI_CSI2_DT_RAW10,
> > +		.bpp			= 16,
> > +		.size			= SHIM_DMACNTX_SIZE_16,
> > +	},
> > +
> > +	/* More formats can be supported but they are not listed for now. */
> > +};
> > +
> > +static const unsigned int num_formats = ARRAY_SIZE(formats);
> > +
> > +/* Forward declaration needed by ti_csi2rx_dma_callback. */
> > +static int ti_csi2rx_start_dma(struct ti_csi2rx_dev *csi,
> > +			       struct ti_csi2rx_buffer *buf);
> > +
> > +static const struct ti_csi2rx_fmt *find_format_by_pix(u32 pixelformat)
> > +{
> > +	unsigned int i;
> > +
> > +	for (i = 0; i < num_formats; i++) {
> > +		if (formats[i].fourcc == pixelformat)
> > +			return &formats[i];
> > +	}
> > +
> > +	return NULL;
> > +}
> > +
> > +static const struct ti_csi2rx_fmt *find_format_by_code(u32 code)
> > +{
> > +	unsigned int i;
> > +
> > +	for (i = 0; i < num_formats; i++) {
> > +		if (formats[i].code == code)
> > +			return &formats[i];
> > +	}
> > +
> > +	return NULL;
> > +}
> > +
> > +static void ti_csi2rx_fill_fmt(const struct ti_csi2rx_fmt *csi_fmt,
> > +			       struct v4l2_format *v4l2_fmt)
> > +{
> > +	struct v4l2_pix_format *pix = &v4l2_fmt->fmt.pix;
> > +	unsigned int pixels_in_word;
> > +	u8 bpp = csi_fmt->bpp;
> > +	u32 bpl;
> > +
> > +	pixels_in_word = PSIL_WORD_SIZE_BYTES * 8 / bpp;
> > +
> > +	pix->width = clamp_t(unsigned int, pix->width,
> > +			     pixels_in_word,
> > +			     MAX_WIDTH_BYTES * 8 / bpp);
> > +	pix->width = rounddown(pix->width, pixels_in_word);
> > +
> > +	pix->height = clamp_t(unsigned int, pix->height, 1, MAX_HEIGHT_LINES);
> > +
> > +	v4l2_fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
> > +	pix->pixelformat = csi_fmt->fourcc;
> > +	pix->colorspace = V4L2_COLORSPACE_SRGB;
> > +	pix->sizeimage = pix->height * pix->width * (bpp / 8);
> > +
> > +	bpl = (pix->width * ALIGN(bpp, 8)) >> 3;
> 
> You do "/ 8" and "* 8" elsewhere in the function, so I think it makes sense
> to "/ 8" here too, instead of ">> 3".

Will fix.

> 
> Is this correct? Why is aligned bpp used here, but when calculating
> sizeimage, bpp is not aligned?

Hmm I agree this whole function is quite confusing, It should either be 
ALIGN(bpp, 8) everywhere or we can just remove that given the hardware 
is unwrapping currently supported formats to multiples of 8 bits (even 
RAW10/RAW12) and the bpp in the table above matches that.

> 
> > +	pix->bytesperline = ALIGN(bpl, 16);
> 
> Why align to 16?

This might be redundant given we are rounding down the width to make 
sure it's a multiple of PSIL_WORD_SIZE_BYTES.

> 
> Shouldn't sizeimage usually be bytesperline * height?
> 
> You could add a few comments here to clarify all the aligns, roundings and
> clampings.

Will do.

> 
> > +}
> > +
> > +static int ti_csi2rx_querycap(struct file *file, void *priv,
> > +			      struct v4l2_capability *cap)
> > +{
> > +	strscpy(cap->driver, TI_CSI2RX_MODULE_NAME, sizeof(cap->driver));
> > +	strscpy(cap->card, TI_CSI2RX_MODULE_NAME, sizeof(cap->card));
> > +
> > +	return 0;
> > +}
> > +
> > +static int ti_csi2rx_enum_fmt_vid_cap(struct file *file, void *priv,
> > +				      struct v4l2_fmtdesc *f)
> > +{
> > +	const struct ti_csi2rx_fmt *fmt = NULL;
> > +
> > +	if (f->mbus_code) {
> > +		if (f->index > 0)
> > +			return -EINVAL;
> 
> This fails to enumerate the formats if mbus_code is set, doesn't it?
> 

Sakari is correct, this is required according to the spec for devices 
that set the V4L2_CAP_IO_MC capability. Caught this while enabling 
libcamera simple pipeline:)

> > +
> > +		fmt = find_format_by_code(f->mbus_code);
> > +	} else {
> > +		if (f->index >= num_formats)
> > +			return -EINVAL;
> > +
> > +		fmt = &formats[f->index];
> > +	}
> > +
> > +	if (!fmt)
> > +		return -EINVAL;
> > +
> > +	f->pixelformat = fmt->fourcc;
> > +	memset(f->reserved, 0, sizeof(f->reserved));
> > +	f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
> > +
> > +	return 0;
> > +}
> > +
> > +static int ti_csi2rx_g_fmt_vid_cap(struct file *file, void *prov,
> > +				   struct v4l2_format *f)
> > +{
> > +	struct ti_csi2rx_dev *csi = video_drvdata(file);
> > +
> > +	*f = csi->v_fmt;
> > +
> > +	return 0;
> > +}
> > +
> > +static int ti_csi2rx_try_fmt_vid_cap(struct file *file, void *priv,
> > +				     struct v4l2_format *f)
> > +{
> > +	const struct ti_csi2rx_fmt *fmt;
> > +
> > +	/*
> > +	 * Default to the first format if the requested pixel format code isn't
> > +	 * supported.
> > +	 */
> > +	fmt = find_format_by_pix(f->fmt.pix.pixelformat);
> > +	if (!fmt)
> > +		fmt = &formats[0];
> > +
> > +	if (f->fmt.pix.field == V4L2_FIELD_ANY)
> > +		f->fmt.pix.field = V4L2_FIELD_NONE;
> > +
> > +	if (f->fmt.pix.field != V4L2_FIELD_NONE)
> > +		/* Interlaced formats are not supported. */
> > +		f->fmt.pix.field = V4L2_FIELD_NONE;
> 
> Can't you just always set the field to V4L2_FIELD_NONE?
> 

Will fix.

> > +	ti_csi2rx_fill_fmt(fmt, f);
> > +
> > +	return 0;
> > +}
> > +
> > +static int ti_csi2rx_s_fmt_vid_cap(struct file *file, void *priv,
> > +				   struct v4l2_format *f)
> > +{
> > +	struct ti_csi2rx_dev *csi = video_drvdata(file);
> > +	struct vb2_queue *q = &csi->vidq;
> > +	int ret;
> > +
> > +	if (vb2_is_busy(q))
> > +		return -EBUSY;
> > +
> > +	ret = ti_csi2rx_try_fmt_vid_cap(file, priv, f);
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	csi->v_fmt = *f;
> > +
> > +	return 0;
> > +}
> > +
> > +static int ti_csi2rx_enum_framesizes(struct file *file, void *fh,
> > +				     struct v4l2_frmsizeenum *fsize)
> > +{
> > +	const struct ti_csi2rx_fmt *fmt;
> > +	unsigned int pixels_in_word;
> > +	u8 bpp;
> > +
> > +	fmt = find_format_by_pix(fsize->pixel_format);
> > +	if (!fmt || fsize->index != 0)
> > +		return -EINVAL;
> > +
> > +	bpp = ALIGN(fmt->bpp, 8);
> > +
> > +	/*
> > +	 * Number of pixels in one PSI-L word. The transfer happens in multiples
> > +	 * of PSI-L word sizes.
> > +	 */
> > +	pixels_in_word = PSIL_WORD_SIZE_BYTES * 8 / bpp;
> > +
> > +	fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
> > +	fsize->stepwise.min_width = pixels_in_word;
> > +	fsize->stepwise.max_width = rounddown(MAX_WIDTH_BYTES * 8 / bpp,
> > +					      pixels_in_word);
> > +	fsize->stepwise.step_width = pixels_in_word;
> > +	fsize->stepwise.min_height = 1;
> > +	fsize->stepwise.max_height = MAX_HEIGHT_LINES;
> > +	fsize->stepwise.step_height = 1;
> > +
> > +	return 0;
> > +}
> > +
> > +static const struct v4l2_ioctl_ops csi_ioctl_ops = {
> > +	.vidioc_querycap      = ti_csi2rx_querycap,
> > +	.vidioc_enum_fmt_vid_cap = ti_csi2rx_enum_fmt_vid_cap,
> > +	.vidioc_try_fmt_vid_cap = ti_csi2rx_try_fmt_vid_cap,
> > +	.vidioc_g_fmt_vid_cap = ti_csi2rx_g_fmt_vid_cap,
> > +	.vidioc_s_fmt_vid_cap = ti_csi2rx_s_fmt_vid_cap,
> > +	.vidioc_enum_framesizes = ti_csi2rx_enum_framesizes,
> > +	.vidioc_reqbufs       = vb2_ioctl_reqbufs,
> > +	.vidioc_create_bufs   = vb2_ioctl_create_bufs,
> > +	.vidioc_prepare_buf   = vb2_ioctl_prepare_buf,
> > +	.vidioc_querybuf      = vb2_ioctl_querybuf,
> > +	.vidioc_qbuf          = vb2_ioctl_qbuf,
> > +	.vidioc_dqbuf         = vb2_ioctl_dqbuf,
> > +	.vidioc_expbuf        = vb2_ioctl_expbuf,
> > +	.vidioc_streamon      = vb2_ioctl_streamon,
> > +	.vidioc_streamoff     = vb2_ioctl_streamoff,
> > +};
> > +
> > +static const struct v4l2_file_operations csi_fops = {
> > +	.owner = THIS_MODULE,
> > +	.open = v4l2_fh_open,
> > +	.release = vb2_fop_release,
> > +	.read = vb2_fop_read,
> > +	.poll = vb2_fop_poll,
> > +	.unlocked_ioctl = video_ioctl2,
> > +	.mmap = vb2_fop_mmap,
> > +};
> > +
> > +static int csi_async_notifier_bound(struct v4l2_async_notifier *notifier,
> > +				    struct v4l2_subdev *subdev,
> > +				    struct v4l2_async_connection *asc)
> > +{
> > +	struct ti_csi2rx_dev *csi = dev_get_drvdata(notifier->v4l2_dev->dev);
> > +
> > +	csi->subdev = subdev;
> > +
> > +	return 0;
> > +}
> > +
> > +static int csi_async_notifier_complete(struct v4l2_async_notifier *notifier)
> > +{
> > +	struct ti_csi2rx_dev *csi = dev_get_drvdata(notifier->v4l2_dev->dev);
> > +	struct video_device *vdev = &csi->vdev;
> > +	int ret;
> > +
> > +	ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1);
> > +	if (ret)
> > +		return ret;
> > +
> > +	ret = v4l2_create_fwnode_links_to_pad(csi->subdev, &csi->pad,
> > +					      MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED);
> > +
> > +	if (ret) {
> > +		video_unregister_device(vdev);
> > +		return ret;
> > +	}
> > +
> > +	return v4l2_device_register_subdev_nodes(&csi->v4l2_dev);
> > +}
> > +
> > +static const struct v4l2_async_notifier_operations csi_async_notifier_ops = {
> > +	.bound = csi_async_notifier_bound,
> > +	.complete = csi_async_notifier_complete,
> > +};
> > +
> > +static int ti_csi2rx_init_subdev(struct ti_csi2rx_dev *csi)
> 
> This is misnamed. ti_csi2rx_async_notifier_register()?
> 

Will fix.

> > +{
> > +	struct fwnode_handle *fwnode;
> > +	struct v4l2_async_connection *asc;
> > +	struct device_node *node;
> > +	int ret;
> > +
> > +	node = of_get_child_by_name(csi->dev->of_node, "csi-bridge");
> > +	if (!node)
> > +		return -EINVAL;
> > +
> > +	fwnode = of_fwnode_handle(node);
> > +	if (!fwnode) {
> > +		of_node_put(node);
> > +		return -EINVAL;
> > +	}
> > +
> > +	v4l2_async_nf_init(&csi->notifier, &csi->v4l2_dev);
> > +	csi->notifier.ops = &csi_async_notifier_ops;
> > +
> > +	asc = v4l2_async_nf_add_fwnode(&csi->notifier, fwnode,
> > +				       struct v4l2_async_connection);
> > +	of_node_put(node);
> > +	if (IS_ERR(asc)) {
> > +		v4l2_async_nf_cleanup(&csi->notifier);
> > +		return PTR_ERR(asc);
> > +	}
> > +
> > +	ret = v4l2_async_nf_register(&csi->notifier);
> > +	if (ret) {
> > +		v4l2_async_nf_cleanup(&csi->notifier);
> > +		return ret;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +static void ti_csi2rx_setup_shim(struct ti_csi2rx_dev *csi)
> > +{
> > +	const struct ti_csi2rx_fmt *fmt;
> > +	unsigned int reg;
> > +
> > +	fmt = find_format_by_pix(csi->v_fmt.fmt.pix.pixelformat);
> > +	if (!fmt) {
> > +		dev_err(csi->dev, "Unknown format\n");
> > +		return;
> > +	}
> 
> The error print here is rather vague, and as there's no error code returned,
> the caller doesn't handle the error.
> 

Will fix.

> > +
> > +	/* De-assert the pixel interface reset. */
> > +	reg = SHIM_CNTL_PIX_RST;
> > +	writel(reg, csi->shim + SHIM_CNTL);
> > +
> > +	reg = SHIM_DMACNTX_EN;
> > +	reg |= FIELD_PREP(SHIM_DMACNTX_FMT, fmt->csi_dt);
> > +
> > +	/*
> > +	 * Using the values from the documentation gives incorrect ordering for
> > +	 * the luma and chroma components. In practice, the "reverse" format
> > +	 * gives the correct image. So for example, if the image is in UYVY, the
> > +	 * reverse would be YVYU.
> > +	 */
> > +	switch (fmt->fourcc) {
> > +	case V4L2_PIX_FMT_UYVY:
> > +		reg |= FIELD_PREP(SHIM_DMACNTX_YUV422,
> > +					SHIM_DMACNTX_YVYU);
> > +		break;
> > +	case V4L2_PIX_FMT_VYUY:
> > +		reg |= FIELD_PREP(SHIM_DMACNTX_YUV422,
> > +					SHIM_DMACNTX_YUYV);
> > +		break;
> > +	case V4L2_PIX_FMT_YUYV:
> > +		reg |= FIELD_PREP(SHIM_DMACNTX_YUV422,
> > +					SHIM_DMACNTX_VYUY);
> > +		break;
> > +	case V4L2_PIX_FMT_YVYU:
> > +		reg |= FIELD_PREP(SHIM_DMACNTX_YUV422,
> > +					SHIM_DMACNTX_UYVY);
> > +		break;
> > +	default:
> > +		/* Ignore if not YUV 4:2:2 */
> > +		break;
> > +	}
> > +
> > +	reg |= FIELD_PREP(SHIM_DMACNTX_SIZE, fmt->size);
> > +
> > +	writel(reg, csi->shim + SHIM_DMACNTX);
> > +
> > +	reg = FIELD_PREP(SHIM_PSI_CFG0_SRC_TAG, 0) |
> > +	      FIELD_PREP(SHIM_PSI_CFG0_DST_TAG, 0);
> > +	writel(reg, csi->shim + SHIM_PSI_CFG0);
> > +}
> > +
> > +static void ti_csi2rx_drain_callback(void *param)
> > +{
> > +	struct completion *drain_complete = param;
> > +
> > +	complete(drain_complete);
> > +}
> > +
> > +static int ti_csi2rx_drain_dma(struct ti_csi2rx_dev *csi)
> > +{
> 
> I think it would be good to explain in a comment somewhere what why this dma
> draining is needed and how it works.
> 

Makes sense, will do.

> > +	struct dma_async_tx_descriptor *desc;
> > +	struct device *dev = csi->dma.chan->device->dev;
> > +	struct completion drain_complete;
> > +	void *buf;
> > +	size_t len = csi->v_fmt.fmt.pix.sizeimage;
> > +	dma_addr_t addr;
> > +	dma_cookie_t cookie;
> > +	int ret;
> > +
> > +	init_completion(&drain_complete);
> > +
> > +	buf = dma_alloc_coherent(dev, len, &addr, GFP_KERNEL | GFP_ATOMIC);
> > +	if (!buf)
> > +		return -ENOMEM;
> 
> If I understand right, this is called when the streaming is stopped, but
> could also be called on frame drops? You're allocating a DMA buffer for a
> full frame. Large runtime DMA buffer allocations are a bit scary. What
> happens if it fails?
> 
> Is it possible to preallocate, or use smaller buffers (perhaps with multiple
> dma operations) to do the flush?
> 
> The dma doesn't support writing to a constant address, does it (in which
> case a very small buffer would suffice)?

Hmm you're absolutely right. Will have to experiment if doing multiple 
dma ops on a small buffer would be feasible for multi-camera/stream 
scenarios. But at the minimum will switch to allocating the drain buffer 
only one time in the next revision.

> 
>  Tomi
> 

-- 
Thanks,
Jai

GPG Fingerprint: 4DE0 D818 E5D5 75E8 D45A AFC5 43DE 91F9 249A 7145

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

[-- Attachment #2: Type: text/plain, Size: 176 bytes --]

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v8 03/16] media: dt-bindings: cadence-csi2rx: Add TI compatible string
  2023-07-31  8:29   ` Jai Luthra
@ 2023-08-05 21:06     ` Krzysztof Kozlowski
  -1 siblings, 0 replies; 84+ messages in thread
From: Krzysztof Kozlowski @ 2023-08-05 21:06 UTC (permalink / raw)
  To: Jai Luthra, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Sakari Ailus,
	Laurent Pinchart, Tomi Valkeinen
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht

On 31/07/2023 10:29, Jai Luthra wrote:
> Add a SoC-specific compatible string for TI's integration of this IP in
> J7 and AM62 line of SoCs.
> 
> Signed-off-by: Jai Luthra <j-luthra@ti.com>
> ---


Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>

Best regards,
Krzysztof


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

* Re: [PATCH v8 03/16] media: dt-bindings: cadence-csi2rx: Add TI compatible string
@ 2023-08-05 21:06     ` Krzysztof Kozlowski
  0 siblings, 0 replies; 84+ messages in thread
From: Krzysztof Kozlowski @ 2023-08-05 21:06 UTC (permalink / raw)
  To: Jai Luthra, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Sakari Ailus,
	Laurent Pinchart, Tomi Valkeinen
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht

On 31/07/2023 10:29, Jai Luthra wrote:
> Add a SoC-specific compatible string for TI's integration of this IP in
> J7 and AM62 line of SoCs.
> 
> Signed-off-by: Jai Luthra <j-luthra@ti.com>
> ---


Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>

Best regards,
Krzysztof


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v8 04/16] media: cadence: Add support for TI SoCs
  2023-07-31  8:29   ` Jai Luthra
@ 2023-08-05 21:06     ` Krzysztof Kozlowski
  -1 siblings, 0 replies; 84+ messages in thread
From: Krzysztof Kozlowski @ 2023-08-05 21:06 UTC (permalink / raw)
  To: Jai Luthra, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Sakari Ailus,
	Laurent Pinchart, Tomi Valkeinen
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht

On 31/07/2023 10:29, Jai Luthra wrote:
> Multiple TI SoCs (J721E, AM62) use this CSI2RX receiver, integrated with
> an external DPHY and a pixel-grabber IP that unwraps the pixel data and
> send it to memory via DMA.
> 
> Add a separate compatible for the TI-specific version of this IP.
> 
> Signed-off-by: Jai Luthra <j-luthra@ti.com>
> ---
> New in v8
> 
>  drivers/media/platform/cadence/cdns-csi2rx.c | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/drivers/media/platform/cadence/cdns-csi2rx.c b/drivers/media/platform/cadence/cdns-csi2rx.c
> index 0d879d71d818..b087583d636f 100644
> --- a/drivers/media/platform/cadence/cdns-csi2rx.c
> +++ b/drivers/media/platform/cadence/cdns-csi2rx.c
> @@ -559,6 +559,7 @@ static void csi2rx_remove(struct platform_device *pdev)
>  
>  static const struct of_device_id csi2rx_of_table[] = {
>  	{ .compatible = "starfive,jh7110-csi2rx" },
> +	{ .compatible = "ti,j721e-csi2rx" },

Why do you need it? It's redundant - already compatible with cdns. No
need to add empty match entries.

>  	{ .compatible = "cdns,csi2rx" },
>  	{ },


Best regards,
Krzysztof


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

* Re: [PATCH v8 04/16] media: cadence: Add support for TI SoCs
@ 2023-08-05 21:06     ` Krzysztof Kozlowski
  0 siblings, 0 replies; 84+ messages in thread
From: Krzysztof Kozlowski @ 2023-08-05 21:06 UTC (permalink / raw)
  To: Jai Luthra, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Sakari Ailus,
	Laurent Pinchart, Tomi Valkeinen
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht

On 31/07/2023 10:29, Jai Luthra wrote:
> Multiple TI SoCs (J721E, AM62) use this CSI2RX receiver, integrated with
> an external DPHY and a pixel-grabber IP that unwraps the pixel data and
> send it to memory via DMA.
> 
> Add a separate compatible for the TI-specific version of this IP.
> 
> Signed-off-by: Jai Luthra <j-luthra@ti.com>
> ---
> New in v8
> 
>  drivers/media/platform/cadence/cdns-csi2rx.c | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/drivers/media/platform/cadence/cdns-csi2rx.c b/drivers/media/platform/cadence/cdns-csi2rx.c
> index 0d879d71d818..b087583d636f 100644
> --- a/drivers/media/platform/cadence/cdns-csi2rx.c
> +++ b/drivers/media/platform/cadence/cdns-csi2rx.c
> @@ -559,6 +559,7 @@ static void csi2rx_remove(struct platform_device *pdev)
>  
>  static const struct of_device_id csi2rx_of_table[] = {
>  	{ .compatible = "starfive,jh7110-csi2rx" },
> +	{ .compatible = "ti,j721e-csi2rx" },

Why do you need it? It's redundant - already compatible with cdns. No
need to add empty match entries.

>  	{ .compatible = "cdns,csi2rx" },
>  	{ },


Best regards,
Krzysztof


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v8 04/16] media: cadence: Add support for TI SoCs
  2023-08-05 21:06     ` Krzysztof Kozlowski
@ 2023-08-07  7:58       ` Jai Luthra
  -1 siblings, 0 replies; 84+ messages in thread
From: Jai Luthra @ 2023-08-07  7:58 UTC (permalink / raw)
  To: Krzysztof Kozlowski
  Cc: Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Sakari Ailus, Laurent Pinchart, Tomi Valkeinen,
	linux-media, linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht

[-- Attachment #1: Type: text/plain, Size: 1548 bytes --]

Hi Krzysztof,

Thanks for the review.

On Aug 05, 2023 at 23:06:43 +0200, Krzysztof Kozlowski wrote:
> On 31/07/2023 10:29, Jai Luthra wrote:
> > Multiple TI SoCs (J721E, AM62) use this CSI2RX receiver, integrated with
> > an external DPHY and a pixel-grabber IP that unwraps the pixel data and
> > send it to memory via DMA.
> > 
> > Add a separate compatible for the TI-specific version of this IP.
> > 
> > Signed-off-by: Jai Luthra <j-luthra@ti.com>
> > ---
> > New in v8
> > 
> >  drivers/media/platform/cadence/cdns-csi2rx.c | 1 +
> >  1 file changed, 1 insertion(+)
> > 
> > diff --git a/drivers/media/platform/cadence/cdns-csi2rx.c b/drivers/media/platform/cadence/cdns-csi2rx.c
> > index 0d879d71d818..b087583d636f 100644
> > --- a/drivers/media/platform/cadence/cdns-csi2rx.c
> > +++ b/drivers/media/platform/cadence/cdns-csi2rx.c
> > @@ -559,6 +559,7 @@ static void csi2rx_remove(struct platform_device *pdev)
> >  
> >  static const struct of_device_id csi2rx_of_table[] = {
> >  	{ .compatible = "starfive,jh7110-csi2rx" },
> > +	{ .compatible = "ti,j721e-csi2rx" },
> 
> Why do you need it? It's redundant - already compatible with cdns. No
> need to add empty match entries.
> 

Understood, will drop this patch in the next revision and re-introduce 
later whenever we add something SoC specific in the driver.

> >  	{ .compatible = "cdns,csi2rx" },
> >  	{ },
> 
> 
> Best regards,
> Krzysztof
> 

-- 
Thanks,
Jai

GPG Fingerprint: 4DE0 D818 E5D5 75E8 D45A AFC5 43DE 91F9 249A 7145

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v8 04/16] media: cadence: Add support for TI SoCs
@ 2023-08-07  7:58       ` Jai Luthra
  0 siblings, 0 replies; 84+ messages in thread
From: Jai Luthra @ 2023-08-07  7:58 UTC (permalink / raw)
  To: Krzysztof Kozlowski
  Cc: Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Sakari Ailus, Laurent Pinchart, Tomi Valkeinen,
	linux-media, linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vaishnav Achath, Vignesh Raghavendra, nm,
	devarsht


[-- Attachment #1.1: Type: text/plain, Size: 1548 bytes --]

Hi Krzysztof,

Thanks for the review.

On Aug 05, 2023 at 23:06:43 +0200, Krzysztof Kozlowski wrote:
> On 31/07/2023 10:29, Jai Luthra wrote:
> > Multiple TI SoCs (J721E, AM62) use this CSI2RX receiver, integrated with
> > an external DPHY and a pixel-grabber IP that unwraps the pixel data and
> > send it to memory via DMA.
> > 
> > Add a separate compatible for the TI-specific version of this IP.
> > 
> > Signed-off-by: Jai Luthra <j-luthra@ti.com>
> > ---
> > New in v8
> > 
> >  drivers/media/platform/cadence/cdns-csi2rx.c | 1 +
> >  1 file changed, 1 insertion(+)
> > 
> > diff --git a/drivers/media/platform/cadence/cdns-csi2rx.c b/drivers/media/platform/cadence/cdns-csi2rx.c
> > index 0d879d71d818..b087583d636f 100644
> > --- a/drivers/media/platform/cadence/cdns-csi2rx.c
> > +++ b/drivers/media/platform/cadence/cdns-csi2rx.c
> > @@ -559,6 +559,7 @@ static void csi2rx_remove(struct platform_device *pdev)
> >  
> >  static const struct of_device_id csi2rx_of_table[] = {
> >  	{ .compatible = "starfive,jh7110-csi2rx" },
> > +	{ .compatible = "ti,j721e-csi2rx" },
> 
> Why do you need it? It's redundant - already compatible with cdns. No
> need to add empty match entries.
> 

Understood, will drop this patch in the next revision and re-introduce 
later whenever we add something SoC specific in the driver.

> >  	{ .compatible = "cdns,csi2rx" },
> >  	{ },
> 
> 
> Best regards,
> Krzysztof
> 

-- 
Thanks,
Jai

GPG Fingerprint: 4DE0 D818 E5D5 75E8 D45A AFC5 43DE 91F9 249A 7145

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

[-- Attachment #2: Type: text/plain, Size: 176 bytes --]

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v8 00/16] CSI2RX support on J721E and AM62
  2023-07-31  8:29 ` Jai Luthra
@ 2023-08-08 22:55   ` Vaishnav Achath
  -1 siblings, 0 replies; 84+ messages in thread
From: Vaishnav Achath @ 2023-08-08 22:55 UTC (permalink / raw)
  To: Jai Luthra, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Sakari Ailus,
	Laurent Pinchart, Tomi Valkeinen
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vignesh Raghavendra, nm, devarsht


On 31/07/23 13:59, Jai Luthra wrote:
> Hi,
> 
> This series adds support for CSI2 capture on J721E. It includes some
> fixes to the Cadence CSI2RX driver, and adds the TI CSI2RX wrapper driver.
> 
> This is a V8 of the below V7 series,
> https://lore.kernel.org/all/20230314115516.667-1-vaishnav.a@ti.com/
> 
> Since Pratyush moved out of TI, Vaishnav & I have been working on
> this driver, and I will be maintaining it upstream.
> 
> J721E CSI2RX driver can also be extended to support multi-stream
> capture, filtering different CSI Virtual Channels (VC) or Data Types
> (DT) to different DMA channels. A WIP series based on v7 is available
> for reference at https://github.com/jailuthra/linux/commits/csi_multi_wip
> 
> I will rebase the multi-stream patches on the current series (v8) and
> post them as RFC in the coming weeks.
> 
> Testing logs: https://gist.github.com/jailuthra/eaeb3af3c65b67e1bc0d5db28180131d
> 

Hi Jai,

Thank you for the series,

Tested the series for capture with OV5640 (LI-OV5640 module) on J721E EVM,
Logs and captured images available here:
https://gist.github.com/vaishnavachath/0b70bc5aaef6a3a88be4900979c788d6

Tested-by: Vaishnav Achath <vaishnav.a@ti.com>

Thanks and Regards,
Vaishnav

> Signed-off-by: Jai Luthra <j-luthra@ti.com>
> ---
> 
> Range-diff from v7 -> v8: http://0x0.st/H21u.diff
> 
> New Patches:
> [01/16]	   Export v4l2_subdev_link_validate_get_format() helper
> [03-04/16] Add new compatible for TI-specific SoC intergration of the
>            Cadence CSI2RX bridge IP
> [14/16]    Add support for RAW8 and RAW10 formats in Cadence CSI2RX
> 
> For [07/16] media: cadence: csi2rx: Add get_fmt and set_fmt pad ops:
> - Use active subdev state to use v4l2_subdev_get_fmt
> - Propagate formats from sink to source pads
> - Drop Laurent's R-by because of the above changes
> 
> For [08/16] media: cadence: csi2rx: Configure DPHY using link freq:
> - Drop original patch in-lieu of already merged
>   https://lore.kernel.org/linux-media/20230523085626.3295-5-jack.zhu@starfivetech.com/
> - Add a new patch to configure DPHY using link_freq control from the
>   source
> 
> For [10/16] media: cadence: csi2rx: Set the STOP bit when stopping a stream:
> - Fix bug where intention was to wait till stream status is idle, i.e.
>   STREAM_STATUS[31] -> 0 - but we were instead checking the opposite
> 
> For [15/16] media: dt-bindings: Add DT bindings for TI J721E CSI2RX driver:
> - Drop "Device Tree Bindings" from title
> - Rename "Wrapper" to "Shim" in title as that is the name referred in
>   the TRM and other places
> - Update maintainer to myself
> - Drop items from compatible as only a single element is present
> - Rename compatible to "ti,j721e-csi2rx-shim" to distinguish from the
>   SoC-specific CSI2RX bridge compatible
> 
> For [16/16] media: ti: Add CSI2RX support for J721E:
> - Move after dt-bindings to keep the series bisectable
> - Rename compatible to "ti,j721e-csi2rx-shim" to distinguish from the
>   SoC-specific CSI2RX bridge compatible
> - Make myself the Maintainer
> - Support RAW8 and RAW10 formats, and setting the pixel-unwrap size on
>   SHIM (RAW10 is stored in 16-bit containers, while RAW8 in 8-bit containers)
> - Fix enum_fmt_vid_cap() to respect CAP_IO_MC and only list pixelformats
>   matching the mbus formats set on the subdev.
> - Fix enum_framesizes() to stop enumerating more than a single framesize
>   (reject non-zero fsize->index)
> - Simplify notifier bound fucntion to use v4l2_create_fwnode_links_to_pad()
>   and inline the video_register() method
> - Add support for draining the DMA with an extra buffer, to get rid of
>   stale data in the pipeline on stream stop (or when frames start
>   getting dropped due to load)
> - Queue all available buffers to DMAEngine in the callback, also use a
>   separate "submitted" queue to track all buffers submitted to DMA
> - Use video_device_pipeline_start() instead of media_pipeline_start()
> - Drop support for VB_READ
> - Print issues in link validation as DEBUG instead of ERROR
> - s/async_subdev/async_connection
> 
> For [v7 13/13] media: dt-bindings: Convert Cadence CSI2RX binding to YAML:
>  - Drop patch in-lieu of
>    https://lore.kernel.org/linux-media/20230523085626.3295-2-jack.zhu@starfivetech.com/
> 
> ---
> Jai Luthra (4):
>       media: subdev: Export get_format helper for link validation
>       media: dt-bindings: cadence-csi2rx: Add TI compatible string
>       media: cadence: Add support for TI SoCs
>       media: cadence: csi2rx: Support RAW8 and RAW10 formats
> 
> Pratyush Yadav (12):
>       media: dt-bindings: Make sure items in data-lanes are unique
>       media: cadence: csi2rx: Unregister v4l2 async notifier
>       media: cadence: csi2rx: Cleanup media entity properly
>       media: cadence: csi2rx: Add get_fmt and set_fmt pad ops
>       media: cadence: csi2rx: Configure DPHY using link freq
>       media: cadence: csi2rx: Soft reset the streams before starting capture
>       media: cadence: csi2rx: Set the STOP bit when stopping a stream
>       media: cadence: csi2rx: Fix stream data configuration
>       media: cadence: csi2rx: Populate subdev devnode
>       media: cadence: csi2rx: Add link validation
>       media: dt-bindings: Add TI J721E CSI2RX
>       media: ti: Add CSI2RX support for J721E
> 
>  .../devicetree/bindings/media/cdns,csi2rx.yaml     |    1 +
>  .../bindings/media/ti,j721e-csi2rx-shim.yaml       |  100 ++
>  .../bindings/media/video-interfaces.yaml           |    1 +
>  MAINTAINERS                                        |    7 +
>  drivers/media/platform/cadence/cdns-csi2rx.c       |  217 +++-
>  drivers/media/platform/ti/Kconfig                  |   12 +
>  drivers/media/platform/ti/Makefile                 |    1 +
>  drivers/media/platform/ti/j721e-csi2rx/Makefile    |    2 +
>  .../media/platform/ti/j721e-csi2rx/j721e-csi2rx.c  | 1127 ++++++++++++++++++++
>  drivers/media/v4l2-core/v4l2-subdev.c              |    8 +-
>  include/media/v4l2-subdev.h                        |   12 +
>  11 files changed, 1478 insertions(+), 10 deletions(-)
> ---
> base-commit: ec89391563792edd11d138a853901bce76d11f44
> change-id: 20230727-upstream_csi-acbeabe038d8
> 
> Best regards,

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

* Re: [PATCH v8 00/16] CSI2RX support on J721E and AM62
@ 2023-08-08 22:55   ` Vaishnav Achath
  0 siblings, 0 replies; 84+ messages in thread
From: Vaishnav Achath @ 2023-08-08 22:55 UTC (permalink / raw)
  To: Jai Luthra, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Sakari Ailus,
	Laurent Pinchart, Tomi Valkeinen
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	Mauro Carvalho Chehab, Maxime Ripard, niklas.soderlund+renesas,
	Benoit Parrot, Vignesh Raghavendra, nm, devarsht


On 31/07/23 13:59, Jai Luthra wrote:
> Hi,
> 
> This series adds support for CSI2 capture on J721E. It includes some
> fixes to the Cadence CSI2RX driver, and adds the TI CSI2RX wrapper driver.
> 
> This is a V8 of the below V7 series,
> https://lore.kernel.org/all/20230314115516.667-1-vaishnav.a@ti.com/
> 
> Since Pratyush moved out of TI, Vaishnav & I have been working on
> this driver, and I will be maintaining it upstream.
> 
> J721E CSI2RX driver can also be extended to support multi-stream
> capture, filtering different CSI Virtual Channels (VC) or Data Types
> (DT) to different DMA channels. A WIP series based on v7 is available
> for reference at https://github.com/jailuthra/linux/commits/csi_multi_wip
> 
> I will rebase the multi-stream patches on the current series (v8) and
> post them as RFC in the coming weeks.
> 
> Testing logs: https://gist.github.com/jailuthra/eaeb3af3c65b67e1bc0d5db28180131d
> 

Hi Jai,

Thank you for the series,

Tested the series for capture with OV5640 (LI-OV5640 module) on J721E EVM,
Logs and captured images available here:
https://gist.github.com/vaishnavachath/0b70bc5aaef6a3a88be4900979c788d6

Tested-by: Vaishnav Achath <vaishnav.a@ti.com>

Thanks and Regards,
Vaishnav

> Signed-off-by: Jai Luthra <j-luthra@ti.com>
> ---
> 
> Range-diff from v7 -> v8: http://0x0.st/H21u.diff
> 
> New Patches:
> [01/16]	   Export v4l2_subdev_link_validate_get_format() helper
> [03-04/16] Add new compatible for TI-specific SoC intergration of the
>            Cadence CSI2RX bridge IP
> [14/16]    Add support for RAW8 and RAW10 formats in Cadence CSI2RX
> 
> For [07/16] media: cadence: csi2rx: Add get_fmt and set_fmt pad ops:
> - Use active subdev state to use v4l2_subdev_get_fmt
> - Propagate formats from sink to source pads
> - Drop Laurent's R-by because of the above changes
> 
> For [08/16] media: cadence: csi2rx: Configure DPHY using link freq:
> - Drop original patch in-lieu of already merged
>   https://lore.kernel.org/linux-media/20230523085626.3295-5-jack.zhu@starfivetech.com/
> - Add a new patch to configure DPHY using link_freq control from the
>   source
> 
> For [10/16] media: cadence: csi2rx: Set the STOP bit when stopping a stream:
> - Fix bug where intention was to wait till stream status is idle, i.e.
>   STREAM_STATUS[31] -> 0 - but we were instead checking the opposite
> 
> For [15/16] media: dt-bindings: Add DT bindings for TI J721E CSI2RX driver:
> - Drop "Device Tree Bindings" from title
> - Rename "Wrapper" to "Shim" in title as that is the name referred in
>   the TRM and other places
> - Update maintainer to myself
> - Drop items from compatible as only a single element is present
> - Rename compatible to "ti,j721e-csi2rx-shim" to distinguish from the
>   SoC-specific CSI2RX bridge compatible
> 
> For [16/16] media: ti: Add CSI2RX support for J721E:
> - Move after dt-bindings to keep the series bisectable
> - Rename compatible to "ti,j721e-csi2rx-shim" to distinguish from the
>   SoC-specific CSI2RX bridge compatible
> - Make myself the Maintainer
> - Support RAW8 and RAW10 formats, and setting the pixel-unwrap size on
>   SHIM (RAW10 is stored in 16-bit containers, while RAW8 in 8-bit containers)
> - Fix enum_fmt_vid_cap() to respect CAP_IO_MC and only list pixelformats
>   matching the mbus formats set on the subdev.
> - Fix enum_framesizes() to stop enumerating more than a single framesize
>   (reject non-zero fsize->index)
> - Simplify notifier bound fucntion to use v4l2_create_fwnode_links_to_pad()
>   and inline the video_register() method
> - Add support for draining the DMA with an extra buffer, to get rid of
>   stale data in the pipeline on stream stop (or when frames start
>   getting dropped due to load)
> - Queue all available buffers to DMAEngine in the callback, also use a
>   separate "submitted" queue to track all buffers submitted to DMA
> - Use video_device_pipeline_start() instead of media_pipeline_start()
> - Drop support for VB_READ
> - Print issues in link validation as DEBUG instead of ERROR
> - s/async_subdev/async_connection
> 
> For [v7 13/13] media: dt-bindings: Convert Cadence CSI2RX binding to YAML:
>  - Drop patch in-lieu of
>    https://lore.kernel.org/linux-media/20230523085626.3295-2-jack.zhu@starfivetech.com/
> 
> ---
> Jai Luthra (4):
>       media: subdev: Export get_format helper for link validation
>       media: dt-bindings: cadence-csi2rx: Add TI compatible string
>       media: cadence: Add support for TI SoCs
>       media: cadence: csi2rx: Support RAW8 and RAW10 formats
> 
> Pratyush Yadav (12):
>       media: dt-bindings: Make sure items in data-lanes are unique
>       media: cadence: csi2rx: Unregister v4l2 async notifier
>       media: cadence: csi2rx: Cleanup media entity properly
>       media: cadence: csi2rx: Add get_fmt and set_fmt pad ops
>       media: cadence: csi2rx: Configure DPHY using link freq
>       media: cadence: csi2rx: Soft reset the streams before starting capture
>       media: cadence: csi2rx: Set the STOP bit when stopping a stream
>       media: cadence: csi2rx: Fix stream data configuration
>       media: cadence: csi2rx: Populate subdev devnode
>       media: cadence: csi2rx: Add link validation
>       media: dt-bindings: Add TI J721E CSI2RX
>       media: ti: Add CSI2RX support for J721E
> 
>  .../devicetree/bindings/media/cdns,csi2rx.yaml     |    1 +
>  .../bindings/media/ti,j721e-csi2rx-shim.yaml       |  100 ++
>  .../bindings/media/video-interfaces.yaml           |    1 +
>  MAINTAINERS                                        |    7 +
>  drivers/media/platform/cadence/cdns-csi2rx.c       |  217 +++-
>  drivers/media/platform/ti/Kconfig                  |   12 +
>  drivers/media/platform/ti/Makefile                 |    1 +
>  drivers/media/platform/ti/j721e-csi2rx/Makefile    |    2 +
>  .../media/platform/ti/j721e-csi2rx/j721e-csi2rx.c  | 1127 ++++++++++++++++++++
>  drivers/media/v4l2-core/v4l2-subdev.c              |    8 +-
>  include/media/v4l2-subdev.h                        |   12 +
>  11 files changed, 1478 insertions(+), 10 deletions(-)
> ---
> base-commit: ec89391563792edd11d138a853901bce76d11f44
> change-id: 20230727-upstream_csi-acbeabe038d8
> 
> Best regards,

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

end of thread, other threads:[~2023-08-08 22:56 UTC | newest]

Thread overview: 84+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-07-31  8:29 [PATCH v8 00/16] CSI2RX support on J721E and AM62 Jai Luthra
2023-07-31  8:29 ` Jai Luthra
2023-07-31  8:29 ` [PATCH v8 01/16] media: subdev: Export get_format helper for link validation Jai Luthra
2023-07-31  8:29   ` Jai Luthra
2023-08-01 14:09   ` Tomi Valkeinen
2023-08-01 14:09     ` Tomi Valkeinen
2023-07-31  8:29 ` [PATCH v8 02/16] media: dt-bindings: Make sure items in data-lanes are unique Jai Luthra
2023-07-31  8:29   ` Jai Luthra
2023-08-01 14:09   ` Tomi Valkeinen
2023-08-01 14:09     ` Tomi Valkeinen
2023-07-31  8:29 ` [PATCH v8 03/16] media: dt-bindings: cadence-csi2rx: Add TI compatible string Jai Luthra
2023-07-31  8:29   ` Jai Luthra
2023-08-05 21:06   ` Krzysztof Kozlowski
2023-08-05 21:06     ` Krzysztof Kozlowski
2023-07-31  8:29 ` [PATCH v8 04/16] media: cadence: Add support for TI SoCs Jai Luthra
2023-07-31  8:29   ` Jai Luthra
2023-08-05 21:06   ` Krzysztof Kozlowski
2023-08-05 21:06     ` Krzysztof Kozlowski
2023-08-07  7:58     ` Jai Luthra
2023-08-07  7:58       ` Jai Luthra
2023-07-31  8:29 ` [PATCH v8 05/16] media: cadence: csi2rx: Unregister v4l2 async notifier Jai Luthra
2023-07-31  8:29   ` Jai Luthra
2023-08-01 14:11   ` Tomi Valkeinen
2023-08-01 14:11     ` Tomi Valkeinen
2023-07-31  8:29 ` [PATCH v8 06/16] media: cadence: csi2rx: Cleanup media entity properly Jai Luthra
2023-07-31  8:29   ` Jai Luthra
2023-08-01 14:11   ` Tomi Valkeinen
2023-08-01 14:11     ` Tomi Valkeinen
2023-07-31  8:29 ` [PATCH v8 07/16] media: cadence: csi2rx: Add get_fmt and set_fmt pad ops Jai Luthra
2023-07-31  8:29   ` Jai Luthra
2023-08-02  8:48   ` Tomi Valkeinen
2023-08-02  8:48     ` Tomi Valkeinen
2023-08-03 11:18     ` Jai Luthra
2023-08-03 11:18       ` Jai Luthra
2023-07-31  8:29 ` [PATCH v8 08/16] media: cadence: csi2rx: Configure DPHY using link freq Jai Luthra
2023-07-31  8:29   ` Jai Luthra
2023-08-02  9:41   ` Tomi Valkeinen
2023-08-02  9:41     ` Tomi Valkeinen
2023-07-31  8:29 ` [PATCH v8 09/16] media: cadence: csi2rx: Soft reset the streams before starting capture Jai Luthra
2023-07-31  8:29   ` Jai Luthra
2023-08-01 14:16   ` Tomi Valkeinen
2023-08-01 14:16     ` Tomi Valkeinen
2023-08-03 11:19     ` Jai Luthra
2023-08-03 11:19       ` Jai Luthra
2023-07-31  8:29 ` [PATCH v8 10/16] media: cadence: csi2rx: Set the STOP bit when stopping a stream Jai Luthra
2023-07-31  8:29   ` Jai Luthra
2023-08-02  9:45   ` Tomi Valkeinen
2023-08-02  9:45     ` Tomi Valkeinen
2023-07-31  8:29 ` [PATCH v8 11/16] media: cadence: csi2rx: Fix stream data configuration Jai Luthra
2023-07-31  8:29   ` Jai Luthra
2023-08-01 14:17   ` Tomi Valkeinen
2023-08-01 14:17     ` Tomi Valkeinen
2023-07-31  8:29 ` [PATCH v8 12/16] media: cadence: csi2rx: Populate subdev devnode Jai Luthra
2023-07-31  8:29   ` Jai Luthra
2023-08-01 14:18   ` Tomi Valkeinen
2023-08-01 14:18     ` Tomi Valkeinen
2023-07-31  8:29 ` [PATCH v8 13/16] media: cadence: csi2rx: Add link validation Jai Luthra
2023-07-31  8:29   ` Jai Luthra
2023-08-01 14:19   ` Tomi Valkeinen
2023-08-01 14:19     ` Tomi Valkeinen
2023-07-31  8:29 ` [PATCH v8 14/16] media: cadence: csi2rx: Support RAW8 and RAW10 formats Jai Luthra
2023-07-31  8:29   ` Jai Luthra
2023-08-02  9:46   ` Tomi Valkeinen
2023-08-02  9:46     ` Tomi Valkeinen
2023-07-31  8:29 ` [PATCH v8 15/16] media: dt-bindings: Add TI J721E CSI2RX Jai Luthra
2023-07-31  8:29   ` Jai Luthra
2023-07-31  9:31   ` Rob Herring
2023-07-31  9:31     ` Rob Herring
2023-07-31  9:54     ` Jai Luthra
2023-07-31  9:54       ` Jai Luthra
2023-07-31  8:29 ` [PATCH v8 16/16] media: ti: Add CSI2RX support for J721E Jai Luthra
2023-07-31  8:29   ` Jai Luthra
2023-08-02 11:04   ` Tomi Valkeinen
2023-08-02 11:04     ` Tomi Valkeinen
2023-08-02 11:14     ` Sakari Ailus
2023-08-02 11:14       ` Sakari Ailus
2023-08-02 12:09       ` Tomi Valkeinen
2023-08-02 12:09         ` Tomi Valkeinen
2023-08-03 11:51     ` Jai Luthra
2023-08-03 11:51       ` Jai Luthra
2023-07-31 12:11 ` [PATCH v8 00/16] CSI2RX support on J721E and AM62 Maxime Ripard
2023-07-31 12:11   ` Maxime Ripard
2023-08-08 22:55 ` Vaishnav Achath
2023-08-08 22:55   ` Vaishnav Achath

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.