All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support
@ 2020-06-14 23:57 Laurent Pinchart
  2020-06-14 23:57 ` [PATCH v1 001/107] media: ti-vpe: cal: Sort headers alphabetically Laurent Pinchart
                   ` (108 more replies)
  0 siblings, 109 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:57 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

Hello,

This small patch series adds media controller support to the ti-cal
driver.

The end goal is to support pipelines where the image source is more
complex than a single subdev (for instance a SMIA++-compliant sensor, or
an FPD-Link source made of a camera, a serializer and a deserializer),
and to prepare for support of multiple hardware contexts, needed for
CSI-2 virtual channel and data type multiplexing support. These use
cases require configuration of the external pipeline from userspace, and
thus need support for the media controller and V4L2 subdev userspace
APIs.

The series starts with miscellaneous cleanups and refactoring, in
patches 001/107 to 083/107. Worth being noted is the split of the large
driver into multiple files, with patch 081/107 moving video node
handling to cal-video.c and patch 083/107 moving CAMERARX handling to
cal-camerarx.c.

Interleaved with more cleanup and refactoring, patch 084/107 creates
subdevs for the CAMERARX instances, patch 090/107 implements the subdev
operations, and patch 091/107 uses the subdev .set_fmt() and .s_stream()
operations to configure and control the CAMERARX. 

More refactoring and cleanup follow in patches 092/107 to 106/107, until
patch 107/107 that adds media controller support. As the existing video
node centric API needs to be preserved to avoid breaking userspace
applications, a module parameter is added to enable the media controller
API. Changes are otherwise fairly limited, and mostly involve the
implementation of MC-centric V4L2 ioctl handlers (which are far simpler
than their video node centric equivalents), additional pipeline
validation in the vb2 start streaming handler, and disabling control
handling in the video nodes.

The patches have been tested on an AM65x EVM with an OV5640 camera
module with the yavta test application, both in MC mode and in legacy
mode. As the ov5640 driver sets a default format identical to the
default of the ti-cal driver, capture in both modes can simply be tested
with

	yavta -f UYVY -s 640x480 -c10 --requeue-last /dev/video0

without requiring manual pipeline setup through the media controller
API. Usage of other formats or resolutions require pipeline
configuration before capture.

Laurent Pinchart (107):
  media: ti-vpe: cal: Sort headers alphabetically
  media: ti-vpe: cal: Avoid function forward declaration
  media: ti-vpe: cal: Decouple CSI2 port and CPORT
  media: ti-vpe: cal: Index CSI-2 port starting at 0
  media: ti-vpe: cal: Index IRQ registersstarting at 0
  media: ti-vpe: cal: Merge all status variables in IRQ handler
  media: ti-vpe: cal: Inline CAL_VERSION macro in its only user
  media: ti-vpe: cal: Turn reg_(read|write)_field() into inline
    functions
  media: ti-vpe: cal: Make cal_formats array const
  media: ti-vpe: cal: Remove needless variable initialization
  media: ti-vpe: cal: Remove needless casts
  media: ti-vpe: cal: Turn boolean variable into bool
  media: ti-vpe: cal: Make loop indices unsigned where applicable
  media: ti-vpe: cal: Embed base_fields array in struct cal_csi2_phy
  media: ti-vpe: cal: Don't modify cal_csi2_phy base_fields
  media: ti-vpe: cal: Store PHY regmap fields in struct cc_data
  media: ti-vpe: cal: Rename cal_csi2_phy base_fields to fields
  media: ti-vpe: cal: Make structure fields unsigned where applicable
  media: ti-vpe: cal: Constify platform data
  media: ti-vpe: cal: Remove static const cal_regmap_config template
  media: ti-vpe: cal: Remove unused structure fields
  media: ti-vpe: cal: Remove flags field from struct cal_dev
  media: ti-vpe: cal: Move function to avoid forward declaration
  media: ti-vpe: cal: Rename cc_data to cal_camerarx
  media: ti-vpe: cal: Rename cal_csi2_phy to cal_camerarx_data
  media: ti-vpe: cal: Name all cal_dev pointers consistently
  media: ti-vpe: cal: Name all cal_camerarx pointers consistently
  media: ti-vpe: cal: Remove internal phy structure from cal_camerarx
  media: ti-vpe: cal: Store instance ID and cal pointer in cal_camerarx
  media: ti-vpe: cal: Use dev_* print macros
  media: ti-vpe: cal: Add print macros for the cal_camerarx instances
  media: ti-vpe: cal: Store sensor-related data in cal_camerarx
  media: ti-vpe: cal: Create consistent naming for CAMERARX functions
  media: ti-vpe: cal: Group CAMERARX-related functions together
  media: ti-vpe: cal: Create consistent naming for context functions
  media: ti-vpe: cal: Reorganize remaining code in sections
  media: ti-vpe: cal: Rename cal_ctx.csi2_port to cal_ctx.index
  media: ti-vpe: cal: Use correct device name for bus_info
  media: ti-vpe: cal: Get struct device without going through
    v4l2_device
  media: ti-vpe: cal: Use ctx_info() instead of v4l2_info()
  media: ti-vpe: cal: Use a loop to create CAMERARX and context
    instances
  media: ti-vpe: cal: Drop struct cal_dev v4l2_dev field
  media: ti-vpe: cal: Split CAMERARX syscon regmap retrieval to a
    function
  media: ti-vpe: cal: Use syscon_regmap_lookup_by_phandle_args()
  media: ti-vpe: cal: Inline cal_get_camerarx_regmap() in caller
  media: ti-vpe: cal: Add comments to cal_probe() to delimitate sections
  media: ti-vpe: cal: Rename cal_create_instance() to cal_ctx_create()
  media: ti-vpe: cal: Hardcode virtual channel to 0
  media: ti-vpe: cal: Use of_graph_get_endpoint_by_regs() to parse OF
  media: ti-vpe: cal: Fix usage of v4l2_fwnode_endpoint_parse()
  media: ti-vpe: cal: Decouple control handler from v4l2_device
  media: ti-vpe: cal: Move v4l2_device from cal_ctx to cal_dev
  media: ti-vpe: cal: Split video device initialization and registration
  media: ti-vpe: cal: Add context V4L2 cleanup and unregister functions
  media: ti-vpe: cal: Unregister video device before cleanup
  media: ti-vpe: cal: Add cal_camerarx_destroy() to cleanup CAMERARX
  media: ti-vpe: cal: Move DT parsing to CAMERARX
  media: ti-vpe: cal: Use ARRAY_SIZE to replace numerical value
  media: ti-vpe: cal: Move all sensor-related init to .bound() notifier
  media: ti-vpe: cal: Allow multiple contexts per subdev notifier
  media: ti-vpe: cal: Move async notifiers from contexts to cal_dev
  media: ti-vpe: cal: Replace context with phy in async notifier entries
  media: ti-vpe: cal: Operate on phy instances in cal_quickdump_regs()
  media: ti-vpe: cal: Decouple context and phy cleanup at remove time
  media: ti-vpe: cal: Move CAL_NUM_CSI2_PORTS from cal_regs.h to cal.c
  media: ti-vpe: cal: Remove isvcirqset() and isportirqset() macros
  media: ti-vpe: cal: Replace number of ports numerical value by macro
  media: ti-vpe: cal: Split media initialization and cleanup to
    functions
  media: ti-vpe: cal: Read hardware revision earlier during probe
  media: ti-vpe: cal: Print revision and hwinfo in a more readable
    format
  media: ti-vpe: cal: Store struct device in cal_dev
  media: ti-vpe: cal: Register a media device
  media: ti-vpe: cal: Init formats in cal_ctx_v4l2_register()
  media: ti-vpe: cal: Allocate cal_ctx active_fmt array dynamically
  media: ti-vpe: cal: Inline cal_camerarx_max_lanes() in its only caller
  media: ti-vpe: cal: Reorder camerarx functions to prepare refactoring
  media: ti-vpe: cal: Refactor camerarx start and stop
  media: ti-vpe: cal: Don't store external rate in cal_camerarx
  media: ti-vpe: cal: Remove unneeded phy->sensor NULL check
  media: ti-vpe: cal: Use 'unsigned int' type instead of 'unsigned'
  media: ti-vpe: cal: Split video node handling to cal-video.c
  media: ti-vpe: cal: Move CAL I/O accessors to cal.h
  media: ti-vpe: cal: Split CAMERARX handling to cal-camerarx.c
  media: ti-vpe: cal: Create subdev for CAMERARX
  media: ti-vpe: cal: Drop cal_ctx m_fmt field
  media: ti-vpe: cal: Move format handling to cal.c and expose helpers
  media: ti-vpe: cal: Rename MAX_(WIDTH|HEIGHT)_* macros with CAL_
    prefix
  media: ti-vpe: cal: Replace hardcoded BIT() value with macro
  media: ti-vpe: cal: Iterate over correct number of CAMERARX instances
  media: ti-vpe: cal: Implement subdev ops for CAMERARX
  media: ti-vpe: cal: Use CAMERARX subdev s_stream op in video device
    code
  media: ti-vpe: cal: Don't pass format to cal_ctx_wr_dma_config()
  media: ti-vpe: cal: Rename struct cal_fmt to cal_format_info
  media: ti-vpe: cal: Refactor interrupt enable/disable
  media: ti-vpe: cal: Fold PPI enable in CAMERARX .s_stream()
  media: ti-vpe: cal: Stop write DMA without disabling PPI
  media: ti-vpe: cal: Use spin_lock_irq() when starting or stopping
    stream
  media: ti-vpe: cal: Share buffer release code between start and stop
  media: ti-vpe: cal: Drop V4L2_CAP_READWRITE
  media: ti-vpe: cal: Drop unneeded check in cal_calc_format_size()
  media: ti-vpe: cal: Remove DMA queue empty check at start streaming
    time
  media: ti-vpe: cal: Use list_first_entry()
  media: ti-vpe: cal: Group all DMA queue fields in struct cal_dmaqueue
  media: ti-vpe: cal: Set cal_dmaqueue.pending to NULL when no pending
    buffer
  media: ti-vpe: cal: Store buffer DMA address in dma_addr_t
  media: ti-vpe: cal: Simplify the context API
  media: ti-vpe: cal: Implement media controller centric API

 drivers/media/platform/ti-vpe/Makefile       |    2 +-
 drivers/media/platform/ti-vpe/cal-camerarx.c |  857 ++++++
 drivers/media/platform/ti-vpe/cal-video.c    |  957 ++++++
 drivers/media/platform/ti-vpe/cal.c          | 2732 +++++-------------
 drivers/media/platform/ti-vpe/cal.h          |  310 ++
 drivers/media/platform/ti-vpe/cal_regs.h     |   74 +-
 6 files changed, 2865 insertions(+), 2067 deletions(-)
 create mode 100644 drivers/media/platform/ti-vpe/cal-camerarx.c
 create mode 100644 drivers/media/platform/ti-vpe/cal-video.c
 create mode 100644 drivers/media/platform/ti-vpe/cal.h

-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 001/107] media: ti-vpe: cal: Sort headers alphabetically
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
@ 2020-06-14 23:57 ` Laurent Pinchart
  2020-06-14 23:57 ` [PATCH v1 002/107] media: ti-vpe: cal: Avoid function forward declaration Laurent Pinchart
                   ` (107 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:57 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

Sorting headers alphabetically helps locating duplicates.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 15 ++++++++-------
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index 9b18db7af6c3..19425248bd63 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -7,30 +7,31 @@
  */
 
 #include <linux/clk.h>
+#include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/ioctl.h>
+#include <linux/mfd/syscon.h>
 #include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/of_graph.h>
 #include <linux/platform_device.h>
-#include <linux/delay.h>
 #include <linux/pm_runtime.h>
-#include <linux/slab.h>
-#include <linux/mfd/syscon.h>
 #include <linux/regmap.h>
+#include <linux/slab.h>
 #include <linux/videodev2.h>
-#include <linux/of_device.h>
-#include <linux/of_graph.h>
 
-#include <media/v4l2-fwnode.h>
 #include <media/v4l2-async.h>
 #include <media/v4l2-common.h>
 #include <media/v4l2-ctrls.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-event.h>
-#include <media/v4l2-ioctl.h>
 #include <media/v4l2-fh.h>
+#include <media/v4l2-fwnode.h>
+#include <media/v4l2-ioctl.h>
 #include <media/videobuf2-core.h>
 #include <media/videobuf2-dma-contig.h>
+
 #include "cal_regs.h"
 
 #define CAL_MODULE_NAME "cal"
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 002/107] media: ti-vpe: cal: Avoid function forward declaration
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
  2020-06-14 23:57 ` [PATCH v1 001/107] media: ti-vpe: cal: Sort headers alphabetically Laurent Pinchart
@ 2020-06-14 23:57 ` Laurent Pinchart
  2020-06-14 23:58 ` [PATCH v1 003/107] media: ti-vpe: cal: Decouple CSI2 port and CPORT Laurent Pinchart
                   ` (106 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:57 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

Move the cal_complete_ctx() function earlier in the file to avoid a
foward declaration. There is no functional change.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 111 ++++++++++++++--------------
 1 file changed, 55 insertions(+), 56 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index 19425248bd63..88fed930ed50 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -1852,7 +1852,61 @@ static const struct video_device cal_videodev = {
  *	Initialization and module stuff
  * ------------------------------------------------------------------
  */
-static int cal_complete_ctx(struct cal_ctx *ctx);
+
+static int cal_complete_ctx(struct cal_ctx *ctx)
+{
+	struct video_device *vfd;
+	struct vb2_queue *q;
+	int ret;
+
+	ctx->timeperframe = tpf_default;
+	ctx->external_rate = 192000000;
+
+	/* initialize locks */
+	spin_lock_init(&ctx->slock);
+	mutex_init(&ctx->mutex);
+
+	/* initialize queue */
+	q = &ctx->vb_vidq;
+	q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	q->io_modes = VB2_MMAP | VB2_DMABUF | VB2_READ;
+	q->drv_priv = ctx;
+	q->buf_struct_size = sizeof(struct cal_buffer);
+	q->ops = &cal_video_qops;
+	q->mem_ops = &vb2_dma_contig_memops;
+	q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+	q->lock = &ctx->mutex;
+	q->min_buffers_needed = 3;
+	q->dev = ctx->v4l2_dev.dev;
+
+	ret = vb2_queue_init(q);
+	if (ret)
+		return ret;
+
+	/* init video dma queues */
+	INIT_LIST_HEAD(&ctx->vidq.active);
+
+	vfd = &ctx->vdev;
+	*vfd = cal_videodev;
+	vfd->v4l2_dev = &ctx->v4l2_dev;
+	vfd->queue = q;
+
+	/*
+	 * Provide a mutex to v4l2 core. It will be used to protect
+	 * all fops and v4l2 ioctls.
+	 */
+	vfd->lock = &ctx->mutex;
+	video_set_drvdata(vfd, ctx);
+
+	ret = video_register_device(vfd, VFL_TYPE_VIDEO, video_nr);
+	if (ret < 0)
+		return ret;
+
+	v4l2_info(&ctx->v4l2_dev, "V4L2 device registered as %s\n",
+		  video_device_node_name(vfd));
+
+	return 0;
+}
 
 static int cal_async_bound(struct v4l2_async_notifier *notifier,
 			   struct v4l2_subdev *subdev,
@@ -1948,61 +2002,6 @@ static const struct v4l2_async_notifier_operations cal_async_ops = {
 	.complete = cal_async_complete,
 };
 
-static int cal_complete_ctx(struct cal_ctx *ctx)
-{
-	struct video_device *vfd;
-	struct vb2_queue *q;
-	int ret;
-
-	ctx->timeperframe = tpf_default;
-	ctx->external_rate = 192000000;
-
-	/* initialize locks */
-	spin_lock_init(&ctx->slock);
-	mutex_init(&ctx->mutex);
-
-	/* initialize queue */
-	q = &ctx->vb_vidq;
-	q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-	q->io_modes = VB2_MMAP | VB2_DMABUF | VB2_READ;
-	q->drv_priv = ctx;
-	q->buf_struct_size = sizeof(struct cal_buffer);
-	q->ops = &cal_video_qops;
-	q->mem_ops = &vb2_dma_contig_memops;
-	q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
-	q->lock = &ctx->mutex;
-	q->min_buffers_needed = 3;
-	q->dev = ctx->v4l2_dev.dev;
-
-	ret = vb2_queue_init(q);
-	if (ret)
-		return ret;
-
-	/* init video dma queues */
-	INIT_LIST_HEAD(&ctx->vidq.active);
-
-	vfd = &ctx->vdev;
-	*vfd = cal_videodev;
-	vfd->v4l2_dev = &ctx->v4l2_dev;
-	vfd->queue = q;
-
-	/*
-	 * Provide a mutex to v4l2 core. It will be used to protect
-	 * all fops and v4l2 ioctls.
-	 */
-	vfd->lock = &ctx->mutex;
-	video_set_drvdata(vfd, ctx);
-
-	ret = video_register_device(vfd, VFL_TYPE_VIDEO, video_nr);
-	if (ret < 0)
-		return ret;
-
-	v4l2_info(&ctx->v4l2_dev, "V4L2 device registered as %s\n",
-		  video_device_node_name(vfd));
-
-	return 0;
-}
-
 static struct device_node *
 of_get_next_port(const struct device_node *parent,
 		 struct device_node *prev)
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 003/107] media: ti-vpe: cal: Decouple CSI2 port and CPORT
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
  2020-06-14 23:57 ` [PATCH v1 001/107] media: ti-vpe: cal: Sort headers alphabetically Laurent Pinchart
  2020-06-14 23:57 ` [PATCH v1 002/107] media: ti-vpe: cal: Avoid function forward declaration Laurent Pinchart
@ 2020-06-14 23:58 ` Laurent Pinchart
  2020-06-14 23:58 ` [PATCH v1 004/107] media: ti-vpe: cal: Index CSI-2 port starting at 0 Laurent Pinchart
                   ` (105 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:58 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

The CPORT mentioned in the CAL documentation has nothing to do with the
CSI-2 ports. It's a remnant of CSI-3 support (or an attempt to achieve
it), and now only serves as an arbitraty tag value used to associate
data samples with contexts. Add a cport field to the cal_ctx structure
and use it instead of the CSI-2 port number where a CPORT is required by
the hardware. The value of the cport field is currently the same as the
csi2_port field, so there's no functional change, but this will help
reworking CPORT and CSI-2 port handling separately.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index 88fed930ed50..201ef3585a48 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -409,6 +409,7 @@ struct cal_ctx {
 	struct vb2_queue	vb_vidq;
 	unsigned int		seq_count;
 	unsigned int		csi2_port;
+	unsigned int		cport;
 	unsigned int		virtual_channel;
 
 	/* Pointer pointing to current v4l2_buffer */
@@ -971,7 +972,7 @@ static void csi2_ctx_config(struct cal_ctx *ctx)
 	u32 val;
 
 	val = reg_read(ctx->dev, CAL_CSI2_CTX0(ctx->csi2_port));
-	set_field(&val, ctx->csi2_port, CAL_CSI2_CTX_CPORT_MASK);
+	set_field(&val, ctx->cport, CAL_CSI2_CTX_CPORT_MASK);
 	/*
 	 * DT type: MIPI CSI-2 Specs
 	 *   0x1: All - DT filter is disabled
@@ -1036,7 +1037,7 @@ static void pix_proc_config(struct cal_ctx *ctx)
 	set_field(&val, CAL_PIX_PROC_DPCMD_BYPASS, CAL_PIX_PROC_DPCMD_MASK);
 	set_field(&val, CAL_PIX_PROC_DPCME_BYPASS, CAL_PIX_PROC_DPCME_MASK);
 	set_field(&val, pack, CAL_PIX_PROC_PACK_MASK);
-	set_field(&val, ctx->csi2_port, CAL_PIX_PROC_CPORT_MASK);
+	set_field(&val, ctx->cport, CAL_PIX_PROC_CPORT_MASK);
 	set_field(&val, 1, CAL_PIX_PROC_EN_MASK);
 	reg_write(ctx->dev, CAL_PIX_PROC(ctx->csi2_port), val);
 	ctx_dbg(3, ctx, "CAL_PIX_PROC(%d) = 0x%08x\n", ctx->csi2_port,
@@ -1049,7 +1050,7 @@ static void cal_wr_dma_config(struct cal_ctx *ctx,
 	u32 val;
 
 	val = reg_read(ctx->dev, CAL_WR_DMA_CTRL(ctx->csi2_port));
-	set_field(&val, ctx->csi2_port, CAL_WR_DMA_CTRL_CPORT_MASK);
+	set_field(&val, ctx->cport, CAL_WR_DMA_CTRL_CPORT_MASK);
 	set_field(&val, height, CAL_WR_DMA_CTRL_YSIZE_MASK);
 	set_field(&val, CAL_WR_DMA_CTRL_DTAG_PIX_DAT,
 		  CAL_WR_DMA_CTRL_DTAG_MASK);
@@ -2221,6 +2222,7 @@ static struct cal_ctx *cal_create_instance(struct cal_dev *dev, int inst)
 
 	/* Store the instance id */
 	ctx->csi2_port = inst + 1;
+	ctx->cport = inst + 1;
 
 	ret = of_cal_create_instance(ctx, inst);
 	if (ret) {
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 004/107] media: ti-vpe: cal: Index CSI-2 port starting at 0
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (2 preceding siblings ...)
  2020-06-14 23:58 ` [PATCH v1 003/107] media: ti-vpe: cal: Decouple CSI2 port and CPORT Laurent Pinchart
@ 2020-06-14 23:58 ` Laurent Pinchart
  2020-06-14 23:58 ` [PATCH v1 005/107] media: ti-vpe: cal: Index IRQ registersstarting " Laurent Pinchart
                   ` (104 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:58 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

The datasheet numbers the CSI-2 PHYs (external to the CAL) starting from
1, but the PPI inputs to the CAL starting from 0. Update the numbering
scheme for csi2_port to match the datasheet, which also simplifies the
driver by removing the need to constantly subtract 1 from the value.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c      | 30 +++++------
 drivers/media/platform/ti-vpe/cal_regs.h | 64 ++++++++++++------------
 2 files changed, 47 insertions(+), 47 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index 201ef3585a48..799c25f5aafd 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -472,7 +472,7 @@ static inline void set_field(u32 *valp, u32 field, u32 mask)
 static u32 cal_data_get_phy_max_lanes(struct cal_ctx *ctx)
 {
 	struct cal_dev *dev = ctx->dev;
-	u32 phy_id = ctx->csi2_port - 1;
+	u32 phy_id = ctx->csi2_port;
 
 	return dev->data->csi2_phy_core[phy_id].num_lanes;
 }
@@ -557,7 +557,7 @@ static struct regmap *cal_get_camerarx_regmap(struct cal_dev *dev)
 static void camerarx_phy_enable(struct cal_ctx *ctx)
 {
 	struct cal_csi2_phy *phy;
-	u32 phy_id = ctx->csi2_port - 1;
+	u32 phy_id = ctx->csi2_port;
 	u32 max_lanes;
 
 	phy = &ctx->dev->data->csi2_phy_core[phy_id];
@@ -574,7 +574,7 @@ static void camerarx_phy_enable(struct cal_ctx *ctx)
 static void camerarx_phy_disable(struct cal_ctx *ctx)
 {
 	struct cal_csi2_phy *phy;
-	u32 phy_id = ctx->csi2_port - 1;
+	u32 phy_id = ctx->csi2_port;
 
 	phy = &ctx->dev->data->csi2_phy_core[phy_id];
 	regmap_field_write(phy->fields[F_CTRLCLKEN], 0);
@@ -712,7 +712,7 @@ static void enable_irqs(struct cal_ctx *ctx)
 	set_field(&val, 1, CAL_HL_IRQ_MASK(ctx->csi2_port));
 	reg_write(ctx->dev, CAL_HL_IRQENABLE_SET(3), val);
 	/* Todo: Add VC_IRQ and CSI2_COMPLEXIO_IRQ handling */
-	reg_write(ctx->dev, CAL_CSI2_VC_IRQENABLE(1), 0xFF000000);
+	reg_write(ctx->dev, CAL_CSI2_VC_IRQENABLE(0), 0xFF000000);
 }
 
 static void disable_irqs(struct cal_ctx *ctx)
@@ -734,7 +734,7 @@ static void disable_irqs(struct cal_ctx *ctx)
 	set_field(&val, 1, CAL_HL_IRQ_MASK(ctx->csi2_port));
 	reg_write(ctx->dev, CAL_HL_IRQENABLE_CLR(3), val);
 	/* Todo: Add VC_IRQ and CSI2_COMPLEXIO_IRQ handling */
-	reg_write(ctx->dev, CAL_CSI2_VC_IRQENABLE(1), 0);
+	reg_write(ctx->dev, CAL_CSI2_VC_IRQENABLE(0), 0);
 }
 
 static void csi2_cio_power(struct cal_ctx *ctx, bool enable)
@@ -894,7 +894,7 @@ static void csi2_wait_for_phy(struct cal_ctx *ctx)
 	csi2_wait_stop_state(ctx);
 
 	ctx_dbg(1, ctx, "CSI2_%d_REG1 = 0x%08x (Bit(31,28) should be set!)\n",
-		(ctx->csi2_port - 1), reg_read(ctx->cc, CAL_CSI2_PHY_REG1));
+		ctx->csi2_port, reg_read(ctx->cc, CAL_CSI2_PHY_REG1));
 }
 
 static void csi2_phy_deinit(struct cal_ctx *ctx)
@@ -1139,7 +1139,7 @@ static void csi2_phy_config(struct cal_ctx *ctx)
 	set_field(&reg0, ths_term, CAL_CSI2_PHY_REG0_THS_TERM_MASK);
 	set_field(&reg0, ths_settle, CAL_CSI2_PHY_REG0_THS_SETTLE_MASK);
 
-	ctx_dbg(1, ctx, "CSI2_%d_REG0 = 0x%08x\n", (ctx->csi2_port - 1), reg0);
+	ctx_dbg(1, ctx, "CSI2_%d_REG0 = 0x%08x\n", ctx->csi2_port, reg0);
 	reg_write(ctx->cc, CAL_CSI2_PHY_REG0, reg0);
 
 	reg1 = reg_read(ctx->cc, CAL_CSI2_PHY_REG1);
@@ -1148,7 +1148,7 @@ static void csi2_phy_config(struct cal_ctx *ctx)
 	set_field(&reg1, TCLK_MISS, CAL_CSI2_PHY_REG1_CTRLCLK_DIV_FACTOR_MASK);
 	set_field(&reg1, TCLK_SETTLE, CAL_CSI2_PHY_REG1_TCLK_SETTLE_MASK);
 
-	ctx_dbg(1, ctx, "CSI2_%d_REG1 = 0x%08x\n", (ctx->csi2_port - 1), reg1);
+	ctx_dbg(1, ctx, "CSI2_%d_REG1 = 0x%08x\n", ctx->csi2_port, reg1);
 	reg_write(ctx->cc, CAL_CSI2_PHY_REG1, reg1);
 }
 
@@ -1217,7 +1217,7 @@ static irqreturn_t cal_irq(int irq_cal, void *data)
 		if (irqst1 & CAL_HL_IRQ_OCPO_ERR_MASK)
 			dev_err_ratelimited(&dev->pdev->dev, "OCPO ERROR\n");
 
-		for (i = 1; i <= 2; ++i) {
+		for (i = 0; i < 2; ++i) {
 			if (irqst1 & CAL_HL_IRQ_CIO_MASK(i)) {
 				u32 cio_stat = reg_read(dev,
 							CAL_CSI2_COMPLEXIO_IRQSTATUS(i));
@@ -1239,9 +1239,9 @@ static irqreturn_t cal_irq(int irq_cal, void *data)
 		/* Clear Interrupt status */
 		reg_write(dev, CAL_HL_IRQSTATUS(2), irqst2);
 
-		for (i = 1; i <= 2; ++i) {
+		for (i = 0; i < 2; ++i) {
 			if (isportirqset(irqst2, i)) {
-				ctx = dev->ctx[i - 1];
+				ctx = dev->ctx[i];
 
 				spin_lock(&ctx->slock);
 				ctx->dma_act = false;
@@ -1262,9 +1262,9 @@ static irqreturn_t cal_irq(int irq_cal, void *data)
 		/* Clear Interrupt status */
 		reg_write(dev, CAL_HL_IRQSTATUS(3), irqst3);
 
-		for (i = 1; i <= 2; ++i) {
+		for (i = 0; i < 2; ++i) {
 			if (isportirqset(irqst3, i)) {
-				ctx = dev->ctx[i - 1];
+				ctx = dev->ctx[i];
 				dma_q = &ctx->vidq;
 
 				spin_lock(&ctx->slock);
@@ -2221,8 +2221,8 @@ static struct cal_ctx *cal_create_instance(struct cal_dev *dev, int inst)
 	ctx->cc = dev->cc[inst];
 
 	/* Store the instance id */
-	ctx->csi2_port = inst + 1;
-	ctx->cport = inst + 1;
+	ctx->csi2_port = inst;
+	ctx->cport = inst;
 
 	ret = of_cal_create_instance(ctx, inst);
 	if (ret) {
diff --git a/drivers/media/platform/ti-vpe/cal_regs.h b/drivers/media/platform/ti-vpe/cal_regs.h
index ac54a2fe7bb6..56c8ccd0e75f 100644
--- a/drivers/media/platform/ti-vpe/cal_regs.h
+++ b/drivers/media/platform/ti-vpe/cal_regs.h
@@ -46,7 +46,7 @@
 #define CAL_HL_IRQSTATUS(m)		(0x24U + ((m-1) * 0x10U))
 #define CAL_HL_IRQENABLE_SET(m)		(0x28U + ((m-1) * 0x10U))
 #define CAL_HL_IRQENABLE_CLR(m)		(0x2cU + ((m-1) * 0x10U))
-#define CAL_PIX_PROC(m)			(0xc0U + ((m-1) * 0x4U))
+#define CAL_PIX_PROC(m)			(0xc0U + (m) * 0x4U)
 #define CAL_CTRL			0x100
 #define CAL_CTRL1			0x104
 #define CAL_LINE_NUMBER_EVT		0x108
@@ -62,34 +62,34 @@
 #define CAL_RD_DMA_INIT_ADDR		0x154
 #define CAL_RD_DMA_INIT_OFST		0x168
 #define CAL_RD_DMA_CTRL2		0x16c
-#define CAL_WR_DMA_CTRL(m)		(0x200U + ((m-1) * 0x10U))
-#define CAL_WR_DMA_ADDR(m)		(0x204U + ((m-1) * 0x10U))
-#define CAL_WR_DMA_OFST(m)		(0x208U + ((m-1) * 0x10U))
-#define CAL_WR_DMA_XSIZE(m)		(0x20cU + ((m-1) * 0x10U))
-#define CAL_CSI2_PPI_CTRL(m)		(0x300U + ((m-1) * 0x80U))
-#define CAL_CSI2_COMPLEXIO_CFG(m)	(0x304U + ((m-1) * 0x80U))
-#define CAL_CSI2_COMPLEXIO_IRQSTATUS(m)	(0x308U + ((m-1) * 0x80U))
-#define CAL_CSI2_SHORT_PACKET(m)	(0x30cU + ((m-1) * 0x80U))
-#define CAL_CSI2_COMPLEXIO_IRQENABLE(m)	(0x310U + ((m-1) * 0x80U))
-#define CAL_CSI2_TIMING(m)		(0x314U + ((m-1) * 0x80U))
-#define CAL_CSI2_VC_IRQENABLE(m)	(0x318U + ((m-1) * 0x80U))
-#define CAL_CSI2_VC_IRQSTATUS(m)	(0x328U + ((m-1) * 0x80U))
-#define CAL_CSI2_CTX0(m)		(0x330U + ((m-1) * 0x80U))
-#define CAL_CSI2_CTX1(m)		(0x334U + ((m-1) * 0x80U))
-#define CAL_CSI2_CTX2(m)		(0x338U + ((m-1) * 0x80U))
-#define CAL_CSI2_CTX3(m)		(0x33cU + ((m-1) * 0x80U))
-#define CAL_CSI2_CTX4(m)		(0x340U + ((m-1) * 0x80U))
-#define CAL_CSI2_CTX5(m)		(0x344U + ((m-1) * 0x80U))
-#define CAL_CSI2_CTX6(m)		(0x348U + ((m-1) * 0x80U))
-#define CAL_CSI2_CTX7(m)		(0x34cU + ((m-1) * 0x80U))
-#define CAL_CSI2_STATUS0(m)		(0x350U + ((m-1) * 0x80U))
-#define CAL_CSI2_STATUS1(m)		(0x354U + ((m-1) * 0x80U))
-#define CAL_CSI2_STATUS2(m)		(0x358U + ((m-1) * 0x80U))
-#define CAL_CSI2_STATUS3(m)		(0x35cU + ((m-1) * 0x80U))
-#define CAL_CSI2_STATUS4(m)		(0x360U + ((m-1) * 0x80U))
-#define CAL_CSI2_STATUS5(m)		(0x364U + ((m-1) * 0x80U))
-#define CAL_CSI2_STATUS6(m)		(0x368U + ((m-1) * 0x80U))
-#define CAL_CSI2_STATUS7(m)		(0x36cU + ((m-1) * 0x80U))
+#define CAL_WR_DMA_CTRL(m)		(0x200U + (m) * 0x10U)
+#define CAL_WR_DMA_ADDR(m)		(0x204U + (m) * 0x10U)
+#define CAL_WR_DMA_OFST(m)		(0x208U + (m) * 0x10U)
+#define CAL_WR_DMA_XSIZE(m)		(0x20cU + (m) * 0x10U)
+#define CAL_CSI2_PPI_CTRL(m)		(0x300U + (m) * 0x80U)
+#define CAL_CSI2_COMPLEXIO_CFG(m)	(0x304U + (m) * 0x80U)
+#define CAL_CSI2_COMPLEXIO_IRQSTATUS(m)	(0x308U + (m) * 0x80U)
+#define CAL_CSI2_SHORT_PACKET(m)	(0x30cU + (m) * 0x80U)
+#define CAL_CSI2_COMPLEXIO_IRQENABLE(m)	(0x310U + (m) * 0x80U)
+#define CAL_CSI2_TIMING(m)		(0x314U + (m) * 0x80U)
+#define CAL_CSI2_VC_IRQENABLE(m)	(0x318U + (m) * 0x80U)
+#define CAL_CSI2_VC_IRQSTATUS(m)	(0x328U + (m) * 0x80U)
+#define CAL_CSI2_CTX0(m)		(0x330U + (m) * 0x80U)
+#define CAL_CSI2_CTX1(m)		(0x334U + (m) * 0x80U)
+#define CAL_CSI2_CTX2(m)		(0x338U + (m) * 0x80U)
+#define CAL_CSI2_CTX3(m)		(0x33cU + (m) * 0x80U)
+#define CAL_CSI2_CTX4(m)		(0x340U + (m) * 0x80U)
+#define CAL_CSI2_CTX5(m)		(0x344U + (m) * 0x80U)
+#define CAL_CSI2_CTX6(m)		(0x348U + (m) * 0x80U)
+#define CAL_CSI2_CTX7(m)		(0x34cU + (m) * 0x80U)
+#define CAL_CSI2_STATUS0(m)		(0x350U + (m) * 0x80U)
+#define CAL_CSI2_STATUS1(m)		(0x354U + (m) * 0x80U)
+#define CAL_CSI2_STATUS2(m)		(0x358U + (m) * 0x80U)
+#define CAL_CSI2_STATUS3(m)		(0x35cU + (m) * 0x80U)
+#define CAL_CSI2_STATUS4(m)		(0x360U + (m) * 0x80U)
+#define CAL_CSI2_STATUS5(m)		(0x364U + (m) * 0x80U)
+#define CAL_CSI2_STATUS6(m)		(0x368U + (m) * 0x80U)
+#define CAL_CSI2_STATUS7(m)		(0x36cU + (m) * 0x80U)
 
 /* CAL CSI2 PHY register offsets */
 #define CAL_CSI2_PHY_REG0		0x000
@@ -141,12 +141,12 @@
 #define CAL_HL_IRQ_EOI_LINE_NUMBER_READ0		0
 #define CAL_HL_IRQ_EOI_LINE_NUMBER_EOI0			0
 
-#define CAL_HL_IRQ_MASK(m)			BIT((m) - 1)
+#define CAL_HL_IRQ_MASK(m)			BIT(m)
 
 #define CAL_HL_IRQ_OCPO_ERR_MASK		BIT(6)
 
-#define CAL_HL_IRQ_CIO_MASK(i)			BIT(16 + ((i) - 1) * 8)
-#define CAL_HL_IRQ_VC_MASK(i)			BIT(17 + ((i) - 1) * 8)
+#define CAL_HL_IRQ_CIO_MASK(i)			BIT(16 + (i) * 8)
+#define CAL_HL_IRQ_VC_MASK(i)			BIT(17 + (i) * 8)
 
 #define CAL_PIX_PROC_EN_MASK			BIT(0)
 #define CAL_PIX_PROC_EXTRACT_MASK		GENMASK(4, 1)
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 005/107] media: ti-vpe: cal: Index IRQ registersstarting at 0
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (3 preceding siblings ...)
  2020-06-14 23:58 ` [PATCH v1 004/107] media: ti-vpe: cal: Index CSI-2 port starting at 0 Laurent Pinchart
@ 2020-06-14 23:58 ` Laurent Pinchart
  2020-06-14 23:58 ` [PATCH v1 006/107] media: ti-vpe: cal: Merge all status variables in IRQ handler Laurent Pinchart
                   ` (103 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:58 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

The datasheet numbers the IRQ registers starting from 0. Update the
numbering scheme to match the datasheet.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c      | 38 ++++++++++++------------
 drivers/media/platform/ti-vpe/cal_regs.h |  8 ++---
 2 files changed, 23 insertions(+), 23 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index 799c25f5aafd..b04d8cb86977 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -695,22 +695,22 @@ static void enable_irqs(struct cal_ctx *ctx)
 		CAL_CSI2_COMPLEXIO_IRQ_ECC_NO_CORRECTION_MASK;
 
 	/* Enable CIO error irqs */
-	reg_write(ctx->dev, CAL_HL_IRQENABLE_SET(1),
+	reg_write(ctx->dev, CAL_HL_IRQENABLE_SET(0),
 		  CAL_HL_IRQ_CIO_MASK(ctx->csi2_port));
 	reg_write(ctx->dev, CAL_CSI2_COMPLEXIO_IRQENABLE(ctx->csi2_port),
 		  cio_err_mask);
 
 	/* Always enable OCPO error */
-	reg_write(ctx->dev, CAL_HL_IRQENABLE_SET(1), CAL_HL_IRQ_OCPO_ERR_MASK);
+	reg_write(ctx->dev, CAL_HL_IRQENABLE_SET(0), CAL_HL_IRQ_OCPO_ERR_MASK);
 
 	/* Enable IRQ_WDMA_END 0/1 */
 	val = 0;
 	set_field(&val, 1, CAL_HL_IRQ_MASK(ctx->csi2_port));
-	reg_write(ctx->dev, CAL_HL_IRQENABLE_SET(2), val);
+	reg_write(ctx->dev, CAL_HL_IRQENABLE_SET(1), val);
 	/* Enable IRQ_WDMA_START 0/1 */
 	val = 0;
 	set_field(&val, 1, CAL_HL_IRQ_MASK(ctx->csi2_port));
-	reg_write(ctx->dev, CAL_HL_IRQENABLE_SET(3), val);
+	reg_write(ctx->dev, CAL_HL_IRQENABLE_SET(2), val);
 	/* Todo: Add VC_IRQ and CSI2_COMPLEXIO_IRQ handling */
 	reg_write(ctx->dev, CAL_CSI2_VC_IRQENABLE(0), 0xFF000000);
 }
@@ -720,7 +720,7 @@ static void disable_irqs(struct cal_ctx *ctx)
 	u32 val;
 
 	/* Disable CIO error irqs */
-	reg_write(ctx->dev, CAL_HL_IRQENABLE_CLR(1),
+	reg_write(ctx->dev, CAL_HL_IRQENABLE_CLR(0),
 		  CAL_HL_IRQ_CIO_MASK(ctx->csi2_port));
 	reg_write(ctx->dev, CAL_CSI2_COMPLEXIO_IRQENABLE(ctx->csi2_port),
 		  0);
@@ -728,11 +728,11 @@ static void disable_irqs(struct cal_ctx *ctx)
 	/* Disable IRQ_WDMA_END 0/1 */
 	val = 0;
 	set_field(&val, 1, CAL_HL_IRQ_MASK(ctx->csi2_port));
-	reg_write(ctx->dev, CAL_HL_IRQENABLE_CLR(2), val);
+	reg_write(ctx->dev, CAL_HL_IRQENABLE_CLR(1), val);
 	/* Disable IRQ_WDMA_START 0/1 */
 	val = 0;
 	set_field(&val, 1, CAL_HL_IRQ_MASK(ctx->csi2_port));
-	reg_write(ctx->dev, CAL_HL_IRQENABLE_CLR(3), val);
+	reg_write(ctx->dev, CAL_HL_IRQENABLE_CLR(2), val);
 	/* Todo: Add VC_IRQ and CSI2_COMPLEXIO_IRQ handling */
 	reg_write(ctx->dev, CAL_CSI2_VC_IRQENABLE(0), 0);
 }
@@ -1206,13 +1206,13 @@ static irqreturn_t cal_irq(int irq_cal, void *data)
 	struct cal_dev *dev = (struct cal_dev *)data;
 	struct cal_ctx *ctx;
 	struct cal_dmaqueue *dma_q;
-	u32 irqst1, irqst2, irqst3;
+	u32 irqst0, irqst1, irqst2;
 
-	irqst1 = reg_read(dev, CAL_HL_IRQSTATUS(1));
-	if (irqst1) {
+	irqst0 = reg_read(dev, CAL_HL_IRQSTATUS(0));
+	if (irqst0) {
 		int i;
 
-		reg_write(dev, CAL_HL_IRQSTATUS(1), irqst1);
+		reg_write(dev, CAL_HL_IRQSTATUS(0), irqst0);
 
 		if (irqst1 & CAL_HL_IRQ_OCPO_ERR_MASK)
 			dev_err_ratelimited(&dev->pdev->dev, "OCPO ERROR\n");
@@ -1232,15 +1232,15 @@ static irqreturn_t cal_irq(int irq_cal, void *data)
 	}
 
 	/* Check which DMA just finished */
-	irqst2 = reg_read(dev, CAL_HL_IRQSTATUS(2));
-	if (irqst2) {
+	irqst1 = reg_read(dev, CAL_HL_IRQSTATUS(1));
+	if (irqst1) {
 		int i;
 
 		/* Clear Interrupt status */
-		reg_write(dev, CAL_HL_IRQSTATUS(2), irqst2);
+		reg_write(dev, CAL_HL_IRQSTATUS(1), irqst1);
 
 		for (i = 0; i < 2; ++i) {
-			if (isportirqset(irqst2, i)) {
+			if (isportirqset(irqst1,  i)) {
 				ctx = dev->ctx[i];
 
 				spin_lock(&ctx->slock);
@@ -1255,15 +1255,15 @@ static irqreturn_t cal_irq(int irq_cal, void *data)
 	}
 
 	/* Check which DMA just started */
-	irqst3 = reg_read(dev, CAL_HL_IRQSTATUS(3));
-	if (irqst3) {
+	irqst2 = reg_read(dev, CAL_HL_IRQSTATUS(2));
+	if (irqst2) {
 		int i;
 
 		/* Clear Interrupt status */
-		reg_write(dev, CAL_HL_IRQSTATUS(3), irqst3);
+		reg_write(dev, CAL_HL_IRQSTATUS(2), irqst2);
 
 		for (i = 0; i < 2; ++i) {
-			if (isportirqset(irqst3, i)) {
+			if (isportirqset(irqst2, i)) {
 				ctx = dev->ctx[i];
 				dma_q = &ctx->vidq;
 
diff --git a/drivers/media/platform/ti-vpe/cal_regs.h b/drivers/media/platform/ti-vpe/cal_regs.h
index 56c8ccd0e75f..b551e67d5d41 100644
--- a/drivers/media/platform/ti-vpe/cal_regs.h
+++ b/drivers/media/platform/ti-vpe/cal_regs.h
@@ -42,10 +42,10 @@
 #define CAL_HL_HWINFO			0x0004
 #define CAL_HL_SYSCONFIG		0x0010
 #define CAL_HL_IRQ_EOI			0x001c
-#define CAL_HL_IRQSTATUS_RAW(m)		(0x20U + ((m-1) * 0x10U))
-#define CAL_HL_IRQSTATUS(m)		(0x24U + ((m-1) * 0x10U))
-#define CAL_HL_IRQENABLE_SET(m)		(0x28U + ((m-1) * 0x10U))
-#define CAL_HL_IRQENABLE_CLR(m)		(0x2cU + ((m-1) * 0x10U))
+#define CAL_HL_IRQSTATUS_RAW(m)		(0x20U + (m) * 0x10U)
+#define CAL_HL_IRQSTATUS(m)		(0x24U + (m) * 0x10U)
+#define CAL_HL_IRQENABLE_SET(m)		(0x28U + (m) * 0x10U)
+#define CAL_HL_IRQENABLE_CLR(m)		(0x2cU + (m) * 0x10U)
 #define CAL_PIX_PROC(m)			(0xc0U + (m) * 0x4U)
 #define CAL_CTRL			0x100
 #define CAL_CTRL1			0x104
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 006/107] media: ti-vpe: cal: Merge all status variables in IRQ handler
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (4 preceding siblings ...)
  2020-06-14 23:58 ` [PATCH v1 005/107] media: ti-vpe: cal: Index IRQ registersstarting " Laurent Pinchart
@ 2020-06-14 23:58 ` Laurent Pinchart
  2020-06-16 10:32   ` Tomi Valkeinen
  2020-06-14 23:58 ` [PATCH v1 007/107] media: ti-vpe: cal: Inline CAL_VERSION macro in its only user Laurent Pinchart
                   ` (102 subsequent siblings)
  108 siblings, 1 reply; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:58 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

The cal_irq() function reads three IRQ status registers and stores their
values in three different variables. As each value is processed right
after reading the corresponding register, a single variable is enough.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 35 +++++++++++++----------------
 1 file changed, 15 insertions(+), 20 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index b04d8cb86977..0a5fb81223da 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -1206,19 +1206,18 @@ static irqreturn_t cal_irq(int irq_cal, void *data)
 	struct cal_dev *dev = (struct cal_dev *)data;
 	struct cal_ctx *ctx;
 	struct cal_dmaqueue *dma_q;
-	u32 irqst0, irqst1, irqst2;
+	unsigned int i;
+	u32 status;
 
-	irqst0 = reg_read(dev, CAL_HL_IRQSTATUS(0));
-	if (irqst0) {
-		int i;
+	status = reg_read(dev, CAL_HL_IRQSTATUS(0));
+	if (status) {
+		reg_write(dev, CAL_HL_IRQSTATUS(0), status);
 
-		reg_write(dev, CAL_HL_IRQSTATUS(0), irqst0);
-
-		if (irqst1 & CAL_HL_IRQ_OCPO_ERR_MASK)
+		if (status & CAL_HL_IRQ_OCPO_ERR_MASK)
 			dev_err_ratelimited(&dev->pdev->dev, "OCPO ERROR\n");
 
 		for (i = 0; i < 2; ++i) {
-			if (irqst1 & CAL_HL_IRQ_CIO_MASK(i)) {
+			if (status & CAL_HL_IRQ_CIO_MASK(i)) {
 				u32 cio_stat = reg_read(dev,
 							CAL_CSI2_COMPLEXIO_IRQSTATUS(i));
 
@@ -1232,15 +1231,13 @@ static irqreturn_t cal_irq(int irq_cal, void *data)
 	}
 
 	/* Check which DMA just finished */
-	irqst1 = reg_read(dev, CAL_HL_IRQSTATUS(1));
-	if (irqst1) {
-		int i;
-
+	status = reg_read(dev, CAL_HL_IRQSTATUS(1));
+	if (status) {
 		/* Clear Interrupt status */
-		reg_write(dev, CAL_HL_IRQSTATUS(1), irqst1);
+		reg_write(dev, CAL_HL_IRQSTATUS(1), status);
 
 		for (i = 0; i < 2; ++i) {
-			if (isportirqset(irqst1,  i)) {
+			if (isportirqset(status, i)) {
 				ctx = dev->ctx[i];
 
 				spin_lock(&ctx->slock);
@@ -1255,15 +1252,13 @@ static irqreturn_t cal_irq(int irq_cal, void *data)
 	}
 
 	/* Check which DMA just started */
-	irqst2 = reg_read(dev, CAL_HL_IRQSTATUS(2));
-	if (irqst2) {
-		int i;
-
+	status = reg_read(dev, CAL_HL_IRQSTATUS(2));
+	if (status) {
 		/* Clear Interrupt status */
-		reg_write(dev, CAL_HL_IRQSTATUS(2), irqst2);
+		reg_write(dev, CAL_HL_IRQSTATUS(2), status);
 
 		for (i = 0; i < 2; ++i) {
-			if (isportirqset(irqst2, i)) {
+			if (isportirqset(status, i)) {
 				ctx = dev->ctx[i];
 				dma_q = &ctx->vidq;
 
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 007/107] media: ti-vpe: cal: Inline CAL_VERSION macro in its only user
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (5 preceding siblings ...)
  2020-06-14 23:58 ` [PATCH v1 006/107] media: ti-vpe: cal: Merge all status variables in IRQ handler Laurent Pinchart
@ 2020-06-14 23:58 ` Laurent Pinchart
  2020-06-14 23:58 ` [PATCH v1 008/107] media: ti-vpe: cal: Turn reg_(read|write)_field() into inline functions Laurent Pinchart
                   ` (101 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:58 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

The CAL_VERSION macro is used once only, in MODULE_VERSION(). This
doesn't improve readability, inline it.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index 0a5fb81223da..fa86a53882cc 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -39,12 +39,10 @@
 #define MAX_WIDTH_BYTES (8192 * 8)
 #define MAX_HEIGHT_LINES 16383
 
-#define CAL_VERSION "0.1.0"
-
 MODULE_DESCRIPTION("TI CAL driver");
 MODULE_AUTHOR("Benoit Parrot, <bparrot@ti.com>");
 MODULE_LICENSE("GPL v2");
-MODULE_VERSION(CAL_VERSION);
+MODULE_VERSION("0.1.0");
 
 static unsigned video_nr = -1;
 module_param(video_nr, uint, 0644);
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 008/107] media: ti-vpe: cal: Turn reg_(read|write)_field() into inline functions
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (6 preceding siblings ...)
  2020-06-14 23:58 ` [PATCH v1 007/107] media: ti-vpe: cal: Inline CAL_VERSION macro in its only user Laurent Pinchart
@ 2020-06-14 23:58 ` Laurent Pinchart
  2020-06-18 13:29   ` Benoit Parrot
  2020-06-14 23:58 ` [PATCH v1 009/107] media: ti-vpe: cal: Make cal_formats array const Laurent Pinchart
                   ` (100 subsequent siblings)
  108 siblings, 1 reply; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:58 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

Turn the reg_(read|write)_field() macros into inline functions for
additional type safety. Use the FIELD_GET() and FIELD_PREP() macros
internally instead of reinventing the wheel.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 28 ++++++++++++++++------------
 1 file changed, 16 insertions(+), 12 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index fa86a53882cc..8c068af936f0 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -6,6 +6,7 @@
  * Benoit Parrot, <bparrot@ti.com>
  */
 
+#include <linux/bitfield.h>
 #include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
@@ -76,13 +77,6 @@ static const struct v4l2_fract
 #define reg_read(dev, offset) ioread32(dev->base + offset)
 #define reg_write(dev, offset, val) iowrite32(val, dev->base + offset)
 
-#define reg_read_field(dev, offset, mask) get_field(reg_read(dev, offset), \
-						    mask)
-#define reg_write_field(dev, offset, field, mask) { \
-	u32 val = reg_read(dev, offset); \
-	set_field(&val, field, mask); \
-	reg_write(dev, offset, val); }
-
 /* ------------------------------------------------------------------
  *	Basic structures
  * ------------------------------------------------------------------
@@ -418,6 +412,21 @@ struct cal_ctx {
 	bool dma_act;
 };
 
+static inline u32 reg_read_field(struct cal_dev *dev, u32 offset, u32 mask)
+{
+	return FIELD_GET(mask, reg_read(dev, offset));
+}
+
+static inline void reg_write_field(struct cal_dev *dev, u32 offset, u32 value,
+				   u32 mask)
+{
+	u32 val = reg_read(dev, offset);
+
+	val &= ~mask;
+	val |= FIELD_PREP(mask, value);
+	reg_write(dev, offset, val);
+}
+
 static const struct cal_fmt *find_format_by_pix(struct cal_ctx *ctx,
 						u32 pixelformat)
 {
@@ -453,11 +462,6 @@ static inline struct cal_ctx *notifier_to_ctx(struct v4l2_async_notifier *n)
 	return container_of(n, struct cal_ctx, notifier);
 }
 
-static inline int get_field(u32 value, u32 mask)
-{
-	return (value & mask) >> __ffs(mask);
-}
-
 static inline void set_field(u32 *valp, u32 field, u32 mask)
 {
 	u32 val = *valp;
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 009/107] media: ti-vpe: cal: Make cal_formats array const
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (7 preceding siblings ...)
  2020-06-14 23:58 ` [PATCH v1 008/107] media: ti-vpe: cal: Turn reg_(read|write)_field() into inline functions Laurent Pinchart
@ 2020-06-14 23:58 ` Laurent Pinchart
  2020-06-14 23:58 ` [PATCH v1 010/107] media: ti-vpe: cal: Remove needless variable initialization Laurent Pinchart
                   ` (99 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:58 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

The static cal_formats array contains const data, make it const. This
requires turning a few cal_fmt pointers into const pointers.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index 8c068af936f0..35df94da7f2c 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -89,7 +89,7 @@ struct cal_fmt {
 	u8	bpp;
 };
 
-static struct cal_fmt cal_formats[] = {
+static const struct cal_fmt cal_formats[] = {
 	{
 		.fourcc		= V4L2_PIX_FMT_YUYV,
 		.code		= MEDIA_BUS_FMT_YUYV8_2X8,
@@ -392,7 +392,7 @@ struct cal_ctx {
 	struct v4l2_mbus_framefmt	m_fmt;
 
 	/* Current subdev enumerated format */
-	struct cal_fmt		*active_fmt[ARRAY_SIZE(cal_formats)];
+	const struct cal_fmt	*active_fmt[ARRAY_SIZE(cal_formats)];
 	int			num_active_fmt;
 
 	struct v4l2_fract	timeperframe;
@@ -1927,7 +1927,6 @@ static int cal_async_bound(struct v4l2_async_notifier *notifier,
 	/* Enumerate sub device formats and enable all matching local formats */
 	ctx->num_active_fmt = 0;
 	for (j = 0, i = 0; ret != -EINVAL; ++j) {
-		struct cal_fmt *fmt;
 
 		memset(&mbus_code, 0, sizeof(mbus_code));
 		mbus_code.index = j;
@@ -1942,7 +1941,7 @@ static int cal_async_bound(struct v4l2_async_notifier *notifier,
 			subdev->name, mbus_code.code, j);
 
 		for (k = 0; k < ARRAY_SIZE(cal_formats); k++) {
-			fmt = &cal_formats[k];
+			const struct cal_fmt *fmt = &cal_formats[k];
 
 			if (mbus_code.code == fmt->code) {
 				ctx->active_fmt[i] = fmt;
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 010/107] media: ti-vpe: cal: Remove needless variable initialization
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (8 preceding siblings ...)
  2020-06-14 23:58 ` [PATCH v1 009/107] media: ti-vpe: cal: Make cal_formats array const Laurent Pinchart
@ 2020-06-14 23:58 ` Laurent Pinchart
  2020-06-14 23:58 ` [PATCH v1 011/107] media: ti-vpe: cal: Remove needless casts Laurent Pinchart
                   ` (98 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:58 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

A few local variables are needlessly initialized. Fix them.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index 35df94da7f2c..6728bac36f3c 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -616,8 +616,8 @@ static struct cc_data *cc_create(struct cal_dev *dev, unsigned int core)
  */
 static void cal_get_hwinfo(struct cal_dev *dev)
 {
-	u32 revision = 0;
-	u32 hwinfo = 0;
+	u32 revision;
+	u32 hwinfo;
 
 	revision = reg_read(dev, CAL_HL_REVISION);
 	cal_dbg(3, dev, "CAL_HL_REVISION = 0x%08x (expecting 0x40000200)\n",
@@ -1297,7 +1297,7 @@ static int cal_enum_fmt_vid_cap(struct file *file, void  *priv,
 				struct v4l2_fmtdesc *f)
 {
 	struct cal_ctx *ctx = video_drvdata(file);
-	const struct cal_fmt *fmt = NULL;
+	const struct cal_fmt *fmt;
 
 	if (f->index >= ctx->num_active_fmt)
 		return -EINVAL;
@@ -1650,7 +1650,7 @@ static void cal_buffer_queue(struct vb2_buffer *vb)
 	struct cal_buffer *buf = container_of(vb, struct cal_buffer,
 					      vb.vb2_buf);
 	struct cal_dmaqueue *vidq = &ctx->vidq;
-	unsigned long flags = 0;
+	unsigned long flags;
 
 	/* recheck locking */
 	spin_lock_irqsave(&ctx->slock, flags);
@@ -1663,7 +1663,7 @@ static int cal_start_streaming(struct vb2_queue *vq, unsigned int count)
 	struct cal_ctx *ctx = vb2_get_drv_priv(vq);
 	struct cal_dmaqueue *dma_q = &ctx->vidq;
 	struct cal_buffer *buf, *tmp;
-	unsigned long addr = 0;
+	unsigned long addr;
 	unsigned long flags;
 	int ret;
 
@@ -2003,7 +2003,7 @@ static struct device_node *
 of_get_next_port(const struct device_node *parent,
 		 struct device_node *prev)
 {
-	struct device_node *port = NULL;
+	struct device_node *port;
 
 	if (!parent)
 		return NULL;
@@ -2047,7 +2047,7 @@ static struct device_node *
 of_get_next_endpoint(const struct device_node *parent,
 		     struct device_node *prev)
 {
-	struct device_node *ep = NULL;
+	struct device_node *ep;
 
 	if (!parent)
 		return NULL;
@@ -2261,8 +2261,8 @@ static int cal_probe(struct platform_device *pdev)
 	struct cal_dev *dev;
 	struct cal_ctx *ctx;
 	struct device_node *parent = pdev->dev.of_node;
-	struct regmap *syscon_camerrx = NULL;
-	u32 syscon_camerrx_offset = 0;
+	struct regmap *syscon_camerrx;
+	u32 syscon_camerrx_offset;
 	int ret;
 	int irq;
 	int i;
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 011/107] media: ti-vpe: cal: Remove needless casts
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (9 preceding siblings ...)
  2020-06-14 23:58 ` [PATCH v1 010/107] media: ti-vpe: cal: Remove needless variable initialization Laurent Pinchart
@ 2020-06-14 23:58 ` Laurent Pinchart
  2020-06-14 23:58 ` [PATCH v1 012/107] media: ti-vpe: cal: Turn boolean variable into bool Laurent Pinchart
                   ` (97 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:58 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

Casting from a void pointer to a struct pointer doesn't require a cast.
Remove them.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index 6728bac36f3c..34817f8d81b5 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -1205,7 +1205,7 @@ static inline void cal_process_buffer_complete(struct cal_ctx *ctx)
 
 static irqreturn_t cal_irq(int irq_cal, void *data)
 {
-	struct cal_dev *dev = (struct cal_dev *)data;
+	struct cal_dev *dev = data;
 	struct cal_ctx *ctx;
 	struct cal_dmaqueue *dma_q;
 	unsigned int i;
@@ -2399,8 +2399,7 @@ static int cal_probe(struct platform_device *pdev)
 
 static int cal_remove(struct platform_device *pdev)
 {
-	struct cal_dev *dev =
-		(struct cal_dev *)platform_get_drvdata(pdev);
+	struct cal_dev *dev = platform_get_drvdata(pdev);
 	struct cal_ctx *ctx;
 	int i;
 
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 012/107] media: ti-vpe: cal: Turn boolean variable into bool
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (10 preceding siblings ...)
  2020-06-14 23:58 ` [PATCH v1 011/107] media: ti-vpe: cal: Remove needless casts Laurent Pinchart
@ 2020-06-14 23:58 ` Laurent Pinchart
  2020-06-14 23:58 ` [PATCH v1 013/107] media: ti-vpe: cal: Make loop indices unsigned where applicable Laurent Pinchart
                   ` (96 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:58 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

The found_port variable contains a boolean value, make it a bool.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index 34817f8d81b5..0a4c2d1f72ef 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -2069,7 +2069,8 @@ static int of_cal_create_instance(struct cal_ctx *ctx, int inst)
 	struct v4l2_fwnode_endpoint *endpoint;
 	struct v4l2_async_subdev *asd;
 	u32 regval = 0;
-	int ret, index, found_port = 0, lane;
+	int ret, index, lane;
+	bool found_port = false;
 
 	parent = pdev->dev.of_node;
 
@@ -2094,7 +2095,7 @@ static int of_cal_create_instance(struct cal_ctx *ctx, int inst)
 		ctx_dbg(3, ctx, "port:%d inst:%d <reg>:%d\n",
 			index, inst, regval);
 		if ((regval == inst) && (index == inst)) {
-			found_port = 1;
+			found_port = true;
 			break;
 		}
 	}
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 013/107] media: ti-vpe: cal: Make loop indices unsigned where applicable
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (11 preceding siblings ...)
  2020-06-14 23:58 ` [PATCH v1 012/107] media: ti-vpe: cal: Turn boolean variable into bool Laurent Pinchart
@ 2020-06-14 23:58 ` Laurent Pinchart
  2020-06-14 23:58 ` [PATCH v1 014/107] media: ti-vpe: cal: Embed base_fields array in struct cal_csi2_phy Laurent Pinchart
                   ` (95 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:58 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

Many loop indices only take positive values. Make them unsigned.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index 0a4c2d1f72ef..a407dbeaa720 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -488,7 +488,7 @@ static int cal_camerarx_regmap_init(struct cal_dev *dev)
 {
 	struct reg_field *field;
 	struct cal_csi2_phy *phy;
-	int i, j;
+	unsigned int i, j;
 
 	if (!dev->data)
 		return -EINVAL;
@@ -901,7 +901,7 @@ static void csi2_wait_for_phy(struct cal_ctx *ctx)
 
 static void csi2_phy_deinit(struct cal_ctx *ctx)
 {
-	int i;
+	unsigned int i;
 
 	csi2_cio_power(ctx, false);
 
@@ -1224,7 +1224,7 @@ static irqreturn_t cal_irq(int irq_cal, void *data)
 							CAL_CSI2_COMPLEXIO_IRQSTATUS(i));
 
 				dev_err_ratelimited(&dev->pdev->dev,
-						    "CIO%d error: %#08x\n", i, cio_stat);
+						    "CIO%u error: %#08x\n", i, cio_stat);
 
 				reg_write(dev, CAL_CSI2_COMPLEXIO_IRQSTATUS(i),
 					  cio_stat);
@@ -1912,8 +1912,8 @@ static int cal_async_bound(struct v4l2_async_notifier *notifier,
 {
 	struct cal_ctx *ctx = notifier_to_ctx(notifier);
 	struct v4l2_subdev_mbus_code_enum mbus_code;
+	unsigned int i, j, k;
 	int ret = 0;
-	int i, j, k;
 
 	if (ctx->sensor) {
 		ctx_info(ctx, "Rejecting subdev %s (Already set!!)",
@@ -1937,7 +1937,7 @@ static int cal_async_bound(struct v4l2_async_notifier *notifier,
 			continue;
 
 		ctx_dbg(2, ctx,
-			"subdev %s: code: %04x idx: %d\n",
+			"subdev %s: code: %04x idx: %u\n",
 			subdev->name, mbus_code.code, j);
 
 		for (k = 0; k < ARRAY_SIZE(cal_formats); k++) {
@@ -1946,7 +1946,7 @@ static int cal_async_bound(struct v4l2_async_notifier *notifier,
 			if (mbus_code.code == fmt->code) {
 				ctx->active_fmt[i] = fmt;
 				ctx_dbg(2, ctx,
-					"matched fourcc: %s: code: %04x idx: %d\n",
+					"matched fourcc: %s: code: %04x idx: %u\n",
 					fourcc_to_str(fmt->fourcc),
 					fmt->code, i);
 				ctx->num_active_fmt = ++i;
@@ -2264,9 +2264,9 @@ static int cal_probe(struct platform_device *pdev)
 	struct device_node *parent = pdev->dev.of_node;
 	struct regmap *syscon_camerrx;
 	u32 syscon_camerrx_offset;
+	unsigned int i;
 	int ret;
 	int irq;
-	int i;
 
 	dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
 	if (!dev)
@@ -2402,7 +2402,7 @@ static int cal_remove(struct platform_device *pdev)
 {
 	struct cal_dev *dev = platform_get_drvdata(pdev);
 	struct cal_ctx *ctx;
-	int i;
+	unsigned int i;
 
 	cal_dbg(1, dev, "Removing %s\n", CAL_MODULE_NAME);
 
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 014/107] media: ti-vpe: cal: Embed base_fields array in struct cal_csi2_phy
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (12 preceding siblings ...)
  2020-06-14 23:58 ` [PATCH v1 013/107] media: ti-vpe: cal: Make loop indices unsigned where applicable Laurent Pinchart
@ 2020-06-14 23:58 ` Laurent Pinchart
  2020-06-14 23:58 ` [PATCH v1 015/107] media: ti-vpe: cal: Don't modify cal_csi2_phy base_fields Laurent Pinchart
                   ` (94 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:58 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

The base_fields field of cal_csi2_phy points to a fixed-size array of
struct reg_field. This level of indirection isn't needed, embed the
array directly in struct cal_csi2_phy.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 70 +++++++++++++----------------
 1 file changed, 30 insertions(+), 40 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index a407dbeaa720..116d7890cadd 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -234,7 +234,7 @@ enum cal_camerarx_field {
 
 struct cal_csi2_phy {
 	struct regmap_field *fields[F_MAX_FIELDS];
-	struct reg_field *base_fields;
+	struct reg_field base_fields[F_MAX_FIELDS];
 	const int num_lanes;
 };
 
@@ -245,27 +245,23 @@ struct cal_data {
 	const unsigned int flags;
 };
 
-static struct reg_field dra72x_ctrl_core_csi0_reg_fields[F_MAX_FIELDS] = {
-	[F_CTRLCLKEN] = REG_FIELD(0, 10, 10),
-	[F_CAMMODE] = REG_FIELD(0, 11, 12),
-	[F_LANEENABLE] = REG_FIELD(0, 13, 16),
-	[F_CSI_MODE] = REG_FIELD(0, 17, 17),
-};
-
-static struct reg_field dra72x_ctrl_core_csi1_reg_fields[F_MAX_FIELDS] = {
-	[F_CTRLCLKEN] = REG_FIELD(0, 0, 0),
-	[F_CAMMODE] = REG_FIELD(0, 1, 2),
-	[F_LANEENABLE] = REG_FIELD(0, 3, 4),
-	[F_CSI_MODE] = REG_FIELD(0, 5, 5),
-};
-
 static struct cal_csi2_phy dra72x_cal_csi_phy[] = {
 	{
-		.base_fields = dra72x_ctrl_core_csi0_reg_fields,
+		.base_fields = {
+			[F_CTRLCLKEN] = REG_FIELD(0, 10, 10),
+			[F_CAMMODE] = REG_FIELD(0, 11, 12),
+			[F_LANEENABLE] = REG_FIELD(0, 13, 16),
+			[F_CSI_MODE] = REG_FIELD(0, 17, 17),
+		},
 		.num_lanes = 4,
 	},
 	{
-		.base_fields = dra72x_ctrl_core_csi1_reg_fields,
+		.base_fields = {
+			[F_CTRLCLKEN] = REG_FIELD(0, 0, 0),
+			[F_CAMMODE] = REG_FIELD(0, 1, 2),
+			[F_LANEENABLE] = REG_FIELD(0, 3, 4),
+			[F_CSI_MODE] = REG_FIELD(0, 5, 5),
+		},
 		.num_lanes = 2,
 	},
 };
@@ -281,27 +277,23 @@ static const struct cal_data dra72x_es1_cal_data = {
 	.flags = DRA72_CAL_PRE_ES2_LDO_DISABLE,
 };
 
-static struct reg_field dra76x_ctrl_core_csi0_reg_fields[F_MAX_FIELDS] = {
-	[F_CTRLCLKEN] = REG_FIELD(0, 8, 8),
-	[F_CAMMODE] = REG_FIELD(0, 9, 10),
-	[F_CSI_MODE] = REG_FIELD(0, 11, 11),
-	[F_LANEENABLE] = REG_FIELD(0, 27, 31),
-};
-
-static struct reg_field dra76x_ctrl_core_csi1_reg_fields[F_MAX_FIELDS] = {
-	[F_CTRLCLKEN] = REG_FIELD(0, 0, 0),
-	[F_CAMMODE] = REG_FIELD(0, 1, 2),
-	[F_CSI_MODE] = REG_FIELD(0, 3, 3),
-	[F_LANEENABLE] = REG_FIELD(0, 24, 26),
-};
-
 static struct cal_csi2_phy dra76x_cal_csi_phy[] = {
 	{
-		.base_fields = dra76x_ctrl_core_csi0_reg_fields,
+		.base_fields = {
+			[F_CTRLCLKEN] = REG_FIELD(0, 8, 8),
+			[F_CAMMODE] = REG_FIELD(0, 9, 10),
+			[F_CSI_MODE] = REG_FIELD(0, 11, 11),
+			[F_LANEENABLE] = REG_FIELD(0, 27, 31),
+		},
 		.num_lanes = 5,
 	},
 	{
-		.base_fields = dra76x_ctrl_core_csi1_reg_fields,
+		.base_fields = {
+			[F_CTRLCLKEN] = REG_FIELD(0, 0, 0),
+			[F_CAMMODE] = REG_FIELD(0, 1, 2),
+			[F_CSI_MODE] = REG_FIELD(0, 3, 3),
+			[F_LANEENABLE] = REG_FIELD(0, 24, 26),
+		},
 		.num_lanes = 3,
 	},
 };
@@ -311,15 +303,13 @@ static const struct cal_data dra76x_cal_data = {
 	.num_csi2_phy = ARRAY_SIZE(dra76x_cal_csi_phy),
 };
 
-static struct reg_field am654_ctrl_core_csi0_reg_fields[F_MAX_FIELDS] = {
-	[F_CTRLCLKEN] = REG_FIELD(0, 15, 15),
-	[F_CAMMODE] = REG_FIELD(0, 24, 25),
-	[F_LANEENABLE] = REG_FIELD(0, 0, 4),
-};
-
 static struct cal_csi2_phy am654_cal_csi_phy[] = {
 	{
-		.base_fields = am654_ctrl_core_csi0_reg_fields,
+		.base_fields = {
+			[F_CTRLCLKEN] = REG_FIELD(0, 15, 15),
+			[F_CAMMODE] = REG_FIELD(0, 24, 25),
+			[F_LANEENABLE] = REG_FIELD(0, 0, 4),
+		},
 		.num_lanes = 5,
 	},
 };
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 015/107] media: ti-vpe: cal: Don't modify cal_csi2_phy base_fields
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (13 preceding siblings ...)
  2020-06-14 23:58 ` [PATCH v1 014/107] media: ti-vpe: cal: Embed base_fields array in struct cal_csi2_phy Laurent Pinchart
@ 2020-06-14 23:58 ` Laurent Pinchart
  2020-06-14 23:58 ` [PATCH v1 016/107] media: ti-vpe: cal: Store PHY regmap fields in struct cc_data Laurent Pinchart
                   ` (93 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:58 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

In preparation to constify cal_csi2_phy, avoid modifying the base_fields
array at runtime. As the array now only needs to stored two values
instead of a full struct reg_field instance, save memory by using a
custom structure for the base_fields elements.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 54 ++++++++++++++++-------------
 1 file changed, 30 insertions(+), 24 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index 116d7890cadd..dda0d7a6b02f 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -234,7 +234,10 @@ enum cal_camerarx_field {
 
 struct cal_csi2_phy {
 	struct regmap_field *fields[F_MAX_FIELDS];
-	struct reg_field base_fields[F_MAX_FIELDS];
+	struct {
+		unsigned int lsb;
+		unsigned int msb;
+	} base_fields[F_MAX_FIELDS];
 	const int num_lanes;
 };
 
@@ -248,19 +251,19 @@ struct cal_data {
 static struct cal_csi2_phy dra72x_cal_csi_phy[] = {
 	{
 		.base_fields = {
-			[F_CTRLCLKEN] = REG_FIELD(0, 10, 10),
-			[F_CAMMODE] = REG_FIELD(0, 11, 12),
-			[F_LANEENABLE] = REG_FIELD(0, 13, 16),
-			[F_CSI_MODE] = REG_FIELD(0, 17, 17),
+			[F_CTRLCLKEN] = { 10, 10 },
+			[F_CAMMODE] = { 11, 12 },
+			[F_LANEENABLE] = { 13, 16 },
+			[F_CSI_MODE] = { 17, 17 },
 		},
 		.num_lanes = 4,
 	},
 	{
 		.base_fields = {
-			[F_CTRLCLKEN] = REG_FIELD(0, 0, 0),
-			[F_CAMMODE] = REG_FIELD(0, 1, 2),
-			[F_LANEENABLE] = REG_FIELD(0, 3, 4),
-			[F_CSI_MODE] = REG_FIELD(0, 5, 5),
+			[F_CTRLCLKEN] = { 0, 0 },
+			[F_CAMMODE] = { 1, 2 },
+			[F_LANEENABLE] = { 3, 4 },
+			[F_CSI_MODE] = { 5, 5 },
 		},
 		.num_lanes = 2,
 	},
@@ -280,19 +283,19 @@ static const struct cal_data dra72x_es1_cal_data = {
 static struct cal_csi2_phy dra76x_cal_csi_phy[] = {
 	{
 		.base_fields = {
-			[F_CTRLCLKEN] = REG_FIELD(0, 8, 8),
-			[F_CAMMODE] = REG_FIELD(0, 9, 10),
-			[F_CSI_MODE] = REG_FIELD(0, 11, 11),
-			[F_LANEENABLE] = REG_FIELD(0, 27, 31),
+			[F_CTRLCLKEN] = { 8, 8 },
+			[F_CAMMODE] = { 9, 10 },
+			[F_CSI_MODE] = { 11, 11 },
+			[F_LANEENABLE] = { 27, 31 },
 		},
 		.num_lanes = 5,
 	},
 	{
 		.base_fields = {
-			[F_CTRLCLKEN] = REG_FIELD(0, 0, 0),
-			[F_CAMMODE] = REG_FIELD(0, 1, 2),
-			[F_CSI_MODE] = REG_FIELD(0, 3, 3),
-			[F_LANEENABLE] = REG_FIELD(0, 24, 26),
+			[F_CTRLCLKEN] = { 0, 0 },
+			[F_CAMMODE] = { 1, 2 },
+			[F_CSI_MODE] = { 3, 3 },
+			[F_LANEENABLE] = { 24, 26 },
 		},
 		.num_lanes = 3,
 	},
@@ -306,9 +309,9 @@ static const struct cal_data dra76x_cal_data = {
 static struct cal_csi2_phy am654_cal_csi_phy[] = {
 	{
 		.base_fields = {
-			[F_CTRLCLKEN] = REG_FIELD(0, 15, 15),
-			[F_CAMMODE] = REG_FIELD(0, 24, 25),
-			[F_LANEENABLE] = REG_FIELD(0, 0, 4),
+			[F_CTRLCLKEN] = { 15, 15 },
+			[F_CAMMODE] = { 24, 25 },
+			[F_LANEENABLE] = { 0, 4 },
 		},
 		.num_lanes = 5,
 	},
@@ -476,7 +479,6 @@ static u32 cal_data_get_num_csi2_phy(struct cal_dev *dev)
 
 static int cal_camerarx_regmap_init(struct cal_dev *dev)
 {
-	struct reg_field *field;
 	struct cal_csi2_phy *phy;
 	unsigned int i, j;
 
@@ -486,16 +488,20 @@ static int cal_camerarx_regmap_init(struct cal_dev *dev)
 	for (i = 0; i < cal_data_get_num_csi2_phy(dev); i++) {
 		phy = &dev->data->csi2_phy_core[i];
 		for (j = 0; j < F_MAX_FIELDS; j++) {
-			field = &phy->base_fields[j];
+			struct reg_field field = {
+				.reg = dev->syscon_camerrx_offset,
+				.lsb = phy->base_fields[j].lsb,
+				.msb = phy->base_fields[j].msb,
+			};
+
 			/*
 			 * Here we update the reg offset with the
 			 * value found in DT
 			 */
-			field->reg = dev->syscon_camerrx_offset;
 			phy->fields[j] =
 				devm_regmap_field_alloc(&dev->pdev->dev,
 							dev->syscon_camerrx,
-							*field);
+							field);
 			if (IS_ERR(phy->fields[j])) {
 				cal_err(dev, "Unable to allocate regmap fields\n");
 				return PTR_ERR(phy->fields[j]);
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 016/107] media: ti-vpe: cal: Store PHY regmap fields in struct cc_data
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (14 preceding siblings ...)
  2020-06-14 23:58 ` [PATCH v1 015/107] media: ti-vpe: cal: Don't modify cal_csi2_phy base_fields Laurent Pinchart
@ 2020-06-14 23:58 ` Laurent Pinchart
  2020-06-14 23:58 ` [PATCH v1 017/107] media: ti-vpe: cal: Rename cal_csi2_phy base_fields to fields Laurent Pinchart
                   ` (92 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:58 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

The PHY regmap fields are created dynamically at runtime. They don't
belong to the platform data that should be constant. Move them to the
cc_data structure.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 90 +++++++++++++++--------------
 1 file changed, 46 insertions(+), 44 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index dda0d7a6b02f..46e12e4c4f5d 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -215,13 +215,6 @@ struct cal_dmaqueue {
 	int			ini_jiffies;
 };
 
-struct cc_data {
-	void __iomem		*base;
-	struct resource		*res;
-
-	struct platform_device *pdev;
-};
-
 /* CTRL_CORE_CAMERRX_CONTROL register field id */
 enum cal_camerarx_field {
 	F_CTRLCLKEN,
@@ -232,8 +225,17 @@ enum cal_camerarx_field {
 	F_MAX_FIELDS,
 };
 
+struct cc_data {
+	void __iomem		*base;
+	struct resource		*res;
+	struct platform_device	*pdev;
+
+	struct {
+		struct regmap_field *fields[F_MAX_FIELDS];
+	} phy;
+};
+
 struct cal_csi2_phy {
-	struct regmap_field *fields[F_MAX_FIELDS];
 	struct {
 		unsigned int lsb;
 		unsigned int msb;
@@ -477,37 +479,37 @@ static u32 cal_data_get_num_csi2_phy(struct cal_dev *dev)
 	return dev->data->num_csi2_phy;
 }
 
-static int cal_camerarx_regmap_init(struct cal_dev *dev)
+static int cal_camerarx_regmap_init(struct cal_dev *dev, struct cc_data *cc,
+				    unsigned int idx)
 {
-	struct cal_csi2_phy *phy;
-	unsigned int i, j;
+	const struct cal_csi2_phy *phy;
+	unsigned int i;
 
 	if (!dev->data)
 		return -EINVAL;
 
-	for (i = 0; i < cal_data_get_num_csi2_phy(dev); i++) {
-		phy = &dev->data->csi2_phy_core[i];
-		for (j = 0; j < F_MAX_FIELDS; j++) {
-			struct reg_field field = {
-				.reg = dev->syscon_camerrx_offset,
-				.lsb = phy->base_fields[j].lsb,
-				.msb = phy->base_fields[j].msb,
-			};
+	phy = &dev->data->csi2_phy_core[idx];
 
-			/*
-			 * Here we update the reg offset with the
-			 * value found in DT
-			 */
-			phy->fields[j] =
-				devm_regmap_field_alloc(&dev->pdev->dev,
-							dev->syscon_camerrx,
-							field);
-			if (IS_ERR(phy->fields[j])) {
-				cal_err(dev, "Unable to allocate regmap fields\n");
-				return PTR_ERR(phy->fields[j]);
-			}
+	for (i = 0; i < F_MAX_FIELDS; i++) {
+		struct reg_field field = {
+			.reg = dev->syscon_camerrx_offset,
+			.lsb = phy->base_fields[i].lsb,
+			.msb = phy->base_fields[i].msb,
+		};
+
+		/*
+		 * Here we update the reg offset with the
+		 * value found in DT
+		 */
+		cc->phy.fields[i] = devm_regmap_field_alloc(&dev->pdev->dev,
+							    dev->syscon_camerrx,
+							    field);
+		if (IS_ERR(cc->phy.fields[i])) {
+			cal_err(dev, "Unable to allocate regmap fields\n");
+			return PTR_ERR(cc->phy.fields[i]);
 		}
 	}
+
 	return 0;
 }
 
@@ -554,28 +556,26 @@ static struct regmap *cal_get_camerarx_regmap(struct cal_dev *dev)
  */
 static void camerarx_phy_enable(struct cal_ctx *ctx)
 {
-	struct cal_csi2_phy *phy;
 	u32 phy_id = ctx->csi2_port;
+	struct cc_data *cc = ctx->dev->cc[phy_id];
 	u32 max_lanes;
 
-	phy = &ctx->dev->data->csi2_phy_core[phy_id];
-	regmap_field_write(phy->fields[F_CAMMODE], 0);
+	regmap_field_write(cc->phy.fields[F_CAMMODE], 0);
 	/* Always enable all lanes at the phy control level */
 	max_lanes = (1 << cal_data_get_phy_max_lanes(ctx)) - 1;
-	regmap_field_write(phy->fields[F_LANEENABLE], max_lanes);
+	regmap_field_write(cc->phy.fields[F_LANEENABLE], max_lanes);
 	/* F_CSI_MODE is not present on every architecture */
-	if (phy->fields[F_CSI_MODE])
-		regmap_field_write(phy->fields[F_CSI_MODE], 1);
-	regmap_field_write(phy->fields[F_CTRLCLKEN], 1);
+	if (cc->phy.fields[F_CSI_MODE])
+		regmap_field_write(cc->phy.fields[F_CSI_MODE], 1);
+	regmap_field_write(cc->phy.fields[F_CTRLCLKEN], 1);
 }
 
 static void camerarx_phy_disable(struct cal_ctx *ctx)
 {
-	struct cal_csi2_phy *phy;
 	u32 phy_id = ctx->csi2_port;
+	struct cc_data *cc = ctx->dev->cc[phy_id];
 
-	phy = &ctx->dev->data->csi2_phy_core[phy_id];
-	regmap_field_write(phy->fields[F_CTRLCLKEN], 0);
+	regmap_field_write(cc->phy.fields[F_CTRLCLKEN], 0);
 }
 
 /*
@@ -585,6 +585,7 @@ static struct cc_data *cc_create(struct cal_dev *dev, unsigned int core)
 {
 	struct platform_device *pdev = dev->pdev;
 	struct cc_data *cc;
+	int ret;
 
 	cc = devm_kzalloc(&pdev->dev, sizeof(*cc), GFP_KERNEL);
 	if (!cc)
@@ -604,6 +605,10 @@ static struct cc_data *cc_create(struct cal_dev *dev, unsigned int core)
 	cal_dbg(1, dev, "ioresource %s at %pa - %pa\n",
 		cc->res->name, &cc->res->start, &cc->res->end);
 
+	ret = cal_camerarx_regmap_init(dev, cc, core);
+	if (ret)
+		return ERR_PTR(ret);
+
 	return cc;
 }
 
@@ -2317,9 +2322,6 @@ static int cal_probe(struct platform_device *pdev)
 
 	dev->syscon_camerrx = syscon_camerrx;
 	dev->syscon_camerrx_offset = syscon_camerrx_offset;
-	ret = cal_camerarx_regmap_init(dev);
-	if (ret)
-		return ret;
 
 	dev->res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
 						"cal_top");
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 017/107] media: ti-vpe: cal: Rename cal_csi2_phy base_fields to fields
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (15 preceding siblings ...)
  2020-06-14 23:58 ` [PATCH v1 016/107] media: ti-vpe: cal: Store PHY regmap fields in struct cc_data Laurent Pinchart
@ 2020-06-14 23:58 ` Laurent Pinchart
  2020-06-14 23:58 ` [PATCH v1 018/107] media: ti-vpe: cal: Make structure fields unsigned where applicable Laurent Pinchart
                   ` (91 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:58 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

The cal_csi2_phy structure has lost its 'fields' field that used to
clash with the 'base_fields' field. Rename base_fields to fields.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index 46e12e4c4f5d..19cd795b71b9 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -239,7 +239,7 @@ struct cal_csi2_phy {
 	struct {
 		unsigned int lsb;
 		unsigned int msb;
-	} base_fields[F_MAX_FIELDS];
+	} fields[F_MAX_FIELDS];
 	const int num_lanes;
 };
 
@@ -252,7 +252,7 @@ struct cal_data {
 
 static struct cal_csi2_phy dra72x_cal_csi_phy[] = {
 	{
-		.base_fields = {
+		.fields = {
 			[F_CTRLCLKEN] = { 10, 10 },
 			[F_CAMMODE] = { 11, 12 },
 			[F_LANEENABLE] = { 13, 16 },
@@ -261,7 +261,7 @@ static struct cal_csi2_phy dra72x_cal_csi_phy[] = {
 		.num_lanes = 4,
 	},
 	{
-		.base_fields = {
+		.fields = {
 			[F_CTRLCLKEN] = { 0, 0 },
 			[F_CAMMODE] = { 1, 2 },
 			[F_LANEENABLE] = { 3, 4 },
@@ -284,7 +284,7 @@ static const struct cal_data dra72x_es1_cal_data = {
 
 static struct cal_csi2_phy dra76x_cal_csi_phy[] = {
 	{
-		.base_fields = {
+		.fields = {
 			[F_CTRLCLKEN] = { 8, 8 },
 			[F_CAMMODE] = { 9, 10 },
 			[F_CSI_MODE] = { 11, 11 },
@@ -293,7 +293,7 @@ static struct cal_csi2_phy dra76x_cal_csi_phy[] = {
 		.num_lanes = 5,
 	},
 	{
-		.base_fields = {
+		.fields = {
 			[F_CTRLCLKEN] = { 0, 0 },
 			[F_CAMMODE] = { 1, 2 },
 			[F_CSI_MODE] = { 3, 3 },
@@ -310,7 +310,7 @@ static const struct cal_data dra76x_cal_data = {
 
 static struct cal_csi2_phy am654_cal_csi_phy[] = {
 	{
-		.base_fields = {
+		.fields = {
 			[F_CTRLCLKEN] = { 15, 15 },
 			[F_CAMMODE] = { 24, 25 },
 			[F_LANEENABLE] = { 0, 4 },
@@ -493,8 +493,8 @@ static int cal_camerarx_regmap_init(struct cal_dev *dev, struct cc_data *cc,
 	for (i = 0; i < F_MAX_FIELDS; i++) {
 		struct reg_field field = {
 			.reg = dev->syscon_camerrx_offset,
-			.lsb = phy->base_fields[i].lsb,
-			.msb = phy->base_fields[i].msb,
+			.lsb = phy->fields[i].lsb,
+			.msb = phy->fields[i].msb,
 		};
 
 		/*
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 018/107] media: ti-vpe: cal: Make structure fields unsigned where applicable
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (16 preceding siblings ...)
  2020-06-14 23:58 ` [PATCH v1 017/107] media: ti-vpe: cal: Rename cal_csi2_phy base_fields to fields Laurent Pinchart
@ 2020-06-14 23:58 ` Laurent Pinchart
  2020-06-14 23:58 ` [PATCH v1 019/107] media: ti-vpe: cal: Constify platform data Laurent Pinchart
                   ` (90 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:58 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

Several structure fields declared as int store positive values only.
Make them unsigned.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index 19cd795b71b9..d8bf24029d54 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -240,11 +240,11 @@ struct cal_csi2_phy {
 		unsigned int lsb;
 		unsigned int msb;
 	} fields[F_MAX_FIELDS];
-	const int num_lanes;
+	const unsigned int num_lanes;
 };
 
 struct cal_data {
-	const int num_csi2_phy;
+	const unsigned int num_csi2_phy;
 	struct cal_csi2_phy *csi2_phy_core;
 
 	const unsigned int flags;
@@ -388,7 +388,7 @@ struct cal_ctx {
 
 	/* Current subdev enumerated format */
 	const struct cal_fmt	*active_fmt[ARRAY_SIZE(cal_formats)];
-	int			num_active_fmt;
+	unsigned int		num_active_fmt;
 
 	struct v4l2_fract	timeperframe;
 	unsigned int		sequence;
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 019/107] media: ti-vpe: cal: Constify platform data
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (17 preceding siblings ...)
  2020-06-14 23:58 ` [PATCH v1 018/107] media: ti-vpe: cal: Make structure fields unsigned where applicable Laurent Pinchart
@ 2020-06-14 23:58 ` Laurent Pinchart
  2020-06-14 23:58 ` [PATCH v1 020/107] media: ti-vpe: cal: Remove static const cal_regmap_config template Laurent Pinchart
                   ` (89 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:58 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

Now that no platform data fields are modified at runtime, make the
corresponding structures const. The const qualifier for integer fields
is removed as it's not required anymore.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index d8bf24029d54..d1ab7fc26d25 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -240,17 +240,17 @@ struct cal_csi2_phy {
 		unsigned int lsb;
 		unsigned int msb;
 	} fields[F_MAX_FIELDS];
-	const unsigned int num_lanes;
+	unsigned int num_lanes;
 };
 
 struct cal_data {
-	const unsigned int num_csi2_phy;
-	struct cal_csi2_phy *csi2_phy_core;
+	unsigned int num_csi2_phy;
+	const struct cal_csi2_phy *csi2_phy_core;
 
-	const unsigned int flags;
+	unsigned int flags;
 };
 
-static struct cal_csi2_phy dra72x_cal_csi_phy[] = {
+static const struct cal_csi2_phy dra72x_cal_csi_phy[] = {
 	{
 		.fields = {
 			[F_CTRLCLKEN] = { 10, 10 },
@@ -282,7 +282,7 @@ static const struct cal_data dra72x_es1_cal_data = {
 	.flags = DRA72_CAL_PRE_ES2_LDO_DISABLE,
 };
 
-static struct cal_csi2_phy dra76x_cal_csi_phy[] = {
+static const struct cal_csi2_phy dra76x_cal_csi_phy[] = {
 	{
 		.fields = {
 			[F_CTRLCLKEN] = { 8, 8 },
@@ -308,7 +308,7 @@ static const struct cal_data dra76x_cal_data = {
 	.num_csi2_phy = ARRAY_SIZE(dra76x_cal_csi_phy),
 };
 
-static struct cal_csi2_phy am654_cal_csi_phy[] = {
+static const struct cal_csi2_phy am654_cal_csi_phy[] = {
 	{
 		.fields = {
 			[F_CTRLCLKEN] = { 15, 15 },
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 020/107] media: ti-vpe: cal: Remove static const cal_regmap_config template
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (18 preceding siblings ...)
  2020-06-14 23:58 ` [PATCH v1 019/107] media: ti-vpe: cal: Constify platform data Laurent Pinchart
@ 2020-06-14 23:58 ` Laurent Pinchart
  2020-06-14 23:58 ` [PATCH v1 021/107] media: ti-vpe: cal: Remove unused structure fields Laurent Pinchart
                   ` (88 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:58 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

The global static const cal_regmap_config template is only used in a
single location, to initialize 3 fields of a local variable. Two of
those fields then get overwritten. Remove the template and set the last
remaining field manually. Simplify the code by hardcoding the field
values instead of calculating them for a variable that always has the
same value.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 19 ++++++-------------
 1 file changed, 6 insertions(+), 13 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index d1ab7fc26d25..852529abca7f 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -513,19 +513,12 @@ static int cal_camerarx_regmap_init(struct cal_dev *dev, struct cc_data *cc,
 	return 0;
 }
 
-static const struct regmap_config cal_regmap_config = {
-	.reg_bits = 32,
-	.val_bits = 32,
-	.reg_stride = 4,
-};
-
 static struct regmap *cal_get_camerarx_regmap(struct cal_dev *dev)
 {
 	struct platform_device *pdev = dev->pdev;
+	struct regmap_config config = { };
 	struct regmap *regmap;
 	void __iomem *base;
-	u32 reg_io_width;
-	struct regmap_config r_config = cal_regmap_config;
 	struct resource *res;
 
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
@@ -539,12 +532,12 @@ static struct regmap *cal_get_camerarx_regmap(struct cal_dev *dev)
 	cal_dbg(1, dev, "ioresource %s at %pa - %pa\n",
 		res->name, &res->start, &res->end);
 
-	reg_io_width = 4;
-	r_config.reg_stride = reg_io_width;
-	r_config.val_bits = reg_io_width * 8;
-	r_config.max_register = resource_size(res) - reg_io_width;
+	config.reg_bits = 32;
+	config.reg_stride = 4;
+	config.val_bits = 32;
+	config.max_register = resource_size(res) - 4;
 
-	regmap = regmap_init_mmio(NULL, base, &r_config);
+	regmap = regmap_init_mmio(NULL, base, &config);
 	if (IS_ERR(regmap))
 		pr_err("regmap init failed\n");
 
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 021/107] media: ti-vpe: cal: Remove unused structure fields
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (19 preceding siblings ...)
  2020-06-14 23:58 ` [PATCH v1 020/107] media: ti-vpe: cal: Remove static const cal_regmap_config template Laurent Pinchart
@ 2020-06-14 23:58 ` Laurent Pinchart
  2020-06-14 23:58 ` [PATCH v1 022/107] media: ti-vpe: cal: Remove flags field from struct cal_dev Laurent Pinchart
                   ` (87 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:58 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

Remove structure fields that are never set, set and never read, or set
to a fixed value. This allows removal of a global variable and a macro.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 34 +++--------------------------
 1 file changed, 3 insertions(+), 31 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index 852529abca7f..fcaf186e386b 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -53,10 +53,6 @@ static unsigned debug;
 module_param(debug, uint, 0644);
 MODULE_PARM_DESC(debug, "activates debug info");
 
-/* timeperframe: min/max and default */
-static const struct v4l2_fract
-	tpf_default = {.numerator = 1001,	.denominator = 30000};
-
 #define cal_dbg(level, caldev, fmt, arg...)	\
 		v4l2_dbg(level, debug, &caldev->v4l2_dev, fmt, ##arg)
 #define cal_info(caldev, fmt, arg...)	\
@@ -71,7 +67,6 @@ static const struct v4l2_fract
 #define ctx_err(ctx, fmt, arg...)	\
 		v4l2_err(&ctx->v4l2_dev, fmt, ##arg)
 
-#define CAL_NUM_INPUT 1
 #define CAL_NUM_CONTEXT 2
 
 #define reg_read(dev, offset) ioread32(dev->base + offset)
@@ -204,15 +199,10 @@ struct cal_buffer {
 	/* common v4l buffer stuff -- must be first */
 	struct vb2_v4l2_buffer	vb;
 	struct list_head	list;
-	const struct cal_fmt	*fmt;
 };
 
 struct cal_dmaqueue {
 	struct list_head	active;
-
-	/* Counters to control fps rate */
-	int			frame;
-	int			ini_jiffies;
 };
 
 /* CTRL_CORE_CAMERRX_CONTROL register field id */
@@ -362,7 +352,6 @@ struct cal_ctx {
 	struct v4l2_subdev	*sensor;
 	struct v4l2_fwnode_endpoint	endpoint;
 
-	struct v4l2_fh		fh;
 	struct cal_dev		*dev;
 	struct cc_data		*cc;
 
@@ -371,14 +360,8 @@ struct cal_ctx {
 	/* v4l2 buffers lock */
 	spinlock_t		slock;
 
-	/* Several counters */
-	unsigned long		jiffies;
-
 	struct cal_dmaqueue	vidq;
 
-	/* Input Number */
-	int			input;
-
 	/* video capture */
 	const struct cal_fmt	*fmt;
 	/* Used to store current pixel format */
@@ -390,11 +373,9 @@ struct cal_ctx {
 	const struct cal_fmt	*active_fmt[ARRAY_SIZE(cal_formats)];
 	unsigned int		num_active_fmt;
 
-	struct v4l2_fract	timeperframe;
 	unsigned int		sequence;
 	unsigned int		external_rate;
 	struct vb2_queue	vb_vidq;
-	unsigned int		seq_count;
 	unsigned int		csi2_port;
 	unsigned int		cport;
 	unsigned int		virtual_channel;
@@ -1533,7 +1514,7 @@ static int cal_enum_framesizes(struct file *file, void *fh,
 static int cal_enum_input(struct file *file, void *priv,
 			  struct v4l2_input *inp)
 {
-	if (inp->index >= CAL_NUM_INPUT)
+	if (inp->index > 0)
 		return -EINVAL;
 
 	inp->type = V4L2_INPUT_TYPE_CAMERA;
@@ -1543,21 +1524,13 @@ static int cal_enum_input(struct file *file, void *priv,
 
 static int cal_g_input(struct file *file, void *priv, unsigned int *i)
 {
-	struct cal_ctx *ctx = video_drvdata(file);
-
-	*i = ctx->input;
+	*i = 0;
 	return 0;
 }
 
 static int cal_s_input(struct file *file, void *priv, unsigned int i)
 {
-	struct cal_ctx *ctx = video_drvdata(file);
-
-	if (i >= CAL_NUM_INPUT)
-		return -EINVAL;
-
-	ctx->input = i;
-	return 0;
+	return i > 0 ? -EINVAL : 0;
 }
 
 /* timeperframe is arbitrary and continuous */
@@ -1851,7 +1824,6 @@ static int cal_complete_ctx(struct cal_ctx *ctx)
 	struct vb2_queue *q;
 	int ret;
 
-	ctx->timeperframe = tpf_default;
 	ctx->external_rate = 192000000;
 
 	/* initialize locks */
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 022/107] media: ti-vpe: cal: Remove flags field from struct cal_dev
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (20 preceding siblings ...)
  2020-06-14 23:58 ` [PATCH v1 021/107] media: ti-vpe: cal: Remove unused structure fields Laurent Pinchart
@ 2020-06-14 23:58 ` Laurent Pinchart
  2020-06-14 23:58 ` [PATCH v1 023/107] media: ti-vpe: cal: Move function to avoid forward declaration Laurent Pinchart
                   ` (86 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:58 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

The cal_dev flags field is a copy of data->flags. Use the latter and
remove the former.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 7 +------
 1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index fcaf186e386b..c5bd9cd4f105 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -326,9 +326,6 @@ struct cal_dev {
 	struct platform_device	*pdev;
 	struct v4l2_device	v4l2_dev;
 
-	/* Controller flags for special cases */
-	unsigned int		flags;
-
 	const struct cal_data	*data;
 
 	/* Control Module handle */
@@ -2244,8 +2241,6 @@ static int cal_probe(struct platform_device *pdev)
 		return -ENODEV;
 	}
 
-	dev->flags = dev->data->flags;
-
 	/* set pseudo v4l2 device name so we can use v4l2_printk */
 	strscpy(dev->v4l2_dev.name, CAL_MODULE_NAME,
 		sizeof(dev->v4l2_dev.name));
@@ -2397,7 +2392,7 @@ static int cal_runtime_resume(struct device *dev)
 {
 	struct cal_dev *caldev = dev_get_drvdata(dev);
 
-	if (caldev->flags & DRA72_CAL_PRE_ES2_LDO_DISABLE) {
+	if (caldev->data->flags & DRA72_CAL_PRE_ES2_LDO_DISABLE) {
 		/*
 		 * Apply errata on both port everytime we (re-)enable
 		 * the clock
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 023/107] media: ti-vpe: cal: Move function to avoid forward declaration
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (21 preceding siblings ...)
  2020-06-14 23:58 ` [PATCH v1 022/107] media: ti-vpe: cal: Remove flags field from struct cal_dev Laurent Pinchart
@ 2020-06-14 23:58 ` Laurent Pinchart
  2020-06-14 23:58 ` [PATCH v1 024/107] media: ti-vpe: cal: Rename cc_data to cal_camerarx Laurent Pinchart
                   ` (85 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:58 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

Move the csi2_phy_config() function to avoid its forward declaration. No
functional change is included.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 98 ++++++++++++++---------------
 1 file changed, 48 insertions(+), 50 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index c5bd9cd4f105..38a7c78e425e 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -740,7 +740,54 @@ static void csi2_cio_power(struct cal_ctx *ctx, bool enable)
 			enable ? "up" : "down");
 }
 
-static void csi2_phy_config(struct cal_ctx *ctx);
+/*
+ * TCLK values are OK at their reset values
+ */
+#define TCLK_TERM	0
+#define TCLK_MISS	1
+#define TCLK_SETTLE	14
+
+static void csi2_phy_config(struct cal_ctx *ctx)
+{
+	unsigned int reg0, reg1;
+	unsigned int ths_term, ths_settle;
+	unsigned int csi2_ddrclk_khz;
+	struct v4l2_fwnode_bus_mipi_csi2 *mipi_csi2 =
+			&ctx->endpoint.bus.mipi_csi2;
+	u32 num_lanes = mipi_csi2->num_data_lanes;
+
+	/* DPHY timing configuration */
+	/* CSI-2 is DDR and we only count used lanes. */
+	csi2_ddrclk_khz = ctx->external_rate / 1000
+		/ (2 * num_lanes) * ctx->fmt->bpp;
+	ctx_dbg(1, ctx, "csi2_ddrclk_khz: %d\n", csi2_ddrclk_khz);
+
+	/* THS_TERM: Programmed value = floor(20 ns/DDRClk period) */
+	ths_term = 20 * csi2_ddrclk_khz / 1000000;
+	ctx_dbg(1, ctx, "ths_term: %d (0x%02x)\n", ths_term, ths_term);
+
+	/* THS_SETTLE: Programmed value = floor(105 ns/DDRClk period) + 4 */
+	ths_settle = (105 * csi2_ddrclk_khz / 1000000) + 4;
+	ctx_dbg(1, ctx, "ths_settle: %d (0x%02x)\n", ths_settle, ths_settle);
+
+	reg0 = reg_read(ctx->cc, CAL_CSI2_PHY_REG0);
+	set_field(&reg0, CAL_CSI2_PHY_REG0_HSCLOCKCONFIG_DISABLE,
+		  CAL_CSI2_PHY_REG0_HSCLOCKCONFIG_MASK);
+	set_field(&reg0, ths_term, CAL_CSI2_PHY_REG0_THS_TERM_MASK);
+	set_field(&reg0, ths_settle, CAL_CSI2_PHY_REG0_THS_SETTLE_MASK);
+
+	ctx_dbg(1, ctx, "CSI2_%d_REG0 = 0x%08x\n", ctx->csi2_port, reg0);
+	reg_write(ctx->cc, CAL_CSI2_PHY_REG0, reg0);
+
+	reg1 = reg_read(ctx->cc, CAL_CSI2_PHY_REG1);
+	set_field(&reg1, TCLK_TERM, CAL_CSI2_PHY_REG1_TCLK_TERM_MASK);
+	set_field(&reg1, 0xb8, CAL_CSI2_PHY_REG1_DPHY_HS_SYNC_PATTERN_MASK);
+	set_field(&reg1, TCLK_MISS, CAL_CSI2_PHY_REG1_CTRLCLK_DIV_FACTOR_MASK);
+	set_field(&reg1, TCLK_SETTLE, CAL_CSI2_PHY_REG1_TCLK_SETTLE_MASK);
+
+	ctx_dbg(1, ctx, "CSI2_%d_REG1 = 0x%08x\n", ctx->csi2_port, reg1);
+	reg_write(ctx->cc, CAL_CSI2_PHY_REG1, reg1);
+}
 
 static void csi2_phy_init(struct cal_ctx *ctx)
 {
@@ -1077,55 +1124,6 @@ static void cal_wr_dma_addr(struct cal_ctx *ctx, unsigned int dmaaddr)
 	reg_write(ctx->dev, CAL_WR_DMA_ADDR(ctx->csi2_port), dmaaddr);
 }
 
-/*
- * TCLK values are OK at their reset values
- */
-#define TCLK_TERM	0
-#define TCLK_MISS	1
-#define TCLK_SETTLE	14
-
-static void csi2_phy_config(struct cal_ctx *ctx)
-{
-	unsigned int reg0, reg1;
-	unsigned int ths_term, ths_settle;
-	unsigned int csi2_ddrclk_khz;
-	struct v4l2_fwnode_bus_mipi_csi2 *mipi_csi2 =
-			&ctx->endpoint.bus.mipi_csi2;
-	u32 num_lanes = mipi_csi2->num_data_lanes;
-
-	/* DPHY timing configuration */
-	/* CSI-2 is DDR and we only count used lanes. */
-	csi2_ddrclk_khz = ctx->external_rate / 1000
-		/ (2 * num_lanes) * ctx->fmt->bpp;
-	ctx_dbg(1, ctx, "csi2_ddrclk_khz: %d\n", csi2_ddrclk_khz);
-
-	/* THS_TERM: Programmed value = floor(20 ns/DDRClk period) */
-	ths_term = 20 * csi2_ddrclk_khz / 1000000;
-	ctx_dbg(1, ctx, "ths_term: %d (0x%02x)\n", ths_term, ths_term);
-
-	/* THS_SETTLE: Programmed value = floor(105 ns/DDRClk period) + 4 */
-	ths_settle = (105 * csi2_ddrclk_khz / 1000000) + 4;
-	ctx_dbg(1, ctx, "ths_settle: %d (0x%02x)\n", ths_settle, ths_settle);
-
-	reg0 = reg_read(ctx->cc, CAL_CSI2_PHY_REG0);
-	set_field(&reg0, CAL_CSI2_PHY_REG0_HSCLOCKCONFIG_DISABLE,
-		  CAL_CSI2_PHY_REG0_HSCLOCKCONFIG_MASK);
-	set_field(&reg0, ths_term, CAL_CSI2_PHY_REG0_THS_TERM_MASK);
-	set_field(&reg0, ths_settle, CAL_CSI2_PHY_REG0_THS_SETTLE_MASK);
-
-	ctx_dbg(1, ctx, "CSI2_%d_REG0 = 0x%08x\n", ctx->csi2_port, reg0);
-	reg_write(ctx->cc, CAL_CSI2_PHY_REG0, reg0);
-
-	reg1 = reg_read(ctx->cc, CAL_CSI2_PHY_REG1);
-	set_field(&reg1, TCLK_TERM, CAL_CSI2_PHY_REG1_TCLK_TERM_MASK);
-	set_field(&reg1, 0xb8, CAL_CSI2_PHY_REG1_DPHY_HS_SYNC_PATTERN_MASK);
-	set_field(&reg1, TCLK_MISS, CAL_CSI2_PHY_REG1_CTRLCLK_DIV_FACTOR_MASK);
-	set_field(&reg1, TCLK_SETTLE, CAL_CSI2_PHY_REG1_TCLK_SETTLE_MASK);
-
-	ctx_dbg(1, ctx, "CSI2_%d_REG1 = 0x%08x\n", ctx->csi2_port, reg1);
-	reg_write(ctx->cc, CAL_CSI2_PHY_REG1, reg1);
-}
-
 static int cal_get_external_info(struct cal_ctx *ctx)
 {
 	struct v4l2_ctrl *ctrl;
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 024/107] media: ti-vpe: cal: Rename cc_data to cal_camerarx
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (22 preceding siblings ...)
  2020-06-14 23:58 ` [PATCH v1 023/107] media: ti-vpe: cal: Move function to avoid forward declaration Laurent Pinchart
@ 2020-06-14 23:58 ` Laurent Pinchart
  2020-06-14 23:58 ` [PATCH v1 025/107] media: ti-vpe: cal: Rename cal_csi2_phy to cal_camerarx_data Laurent Pinchart
                   ` (84 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:58 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

The various data structures that describe the components of the camera
access layer (CAL) are named without much consistency. Start cleaning
this up by renaming the structure that describes the CAMERARX block,
cc_data, to cal_camerarx.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 46 +++++++++++++++++------------
 1 file changed, 27 insertions(+), 19 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index 38a7c78e425e..df756c7b53b7 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -215,16 +215,6 @@ enum cal_camerarx_field {
 	F_MAX_FIELDS,
 };
 
-struct cc_data {
-	void __iomem		*base;
-	struct resource		*res;
-	struct platform_device	*pdev;
-
-	struct {
-		struct regmap_field *fields[F_MAX_FIELDS];
-	} phy;
-};
-
 struct cal_csi2_phy {
 	struct {
 		unsigned int lsb;
@@ -315,9 +305,26 @@ static const struct cal_data am654_cal_data = {
 };
 
 /*
- * there is one cal_dev structure in the driver, it is shared by
- * all instances.
+ * The Camera Adaptation Layer (CAL) module is paired with one or more complex
+ * I/O PHYs (CAMERARX). It contains multiple instances of CSI-2, processing and
+ * DMA contexts.
+ *
+ * The cal_dev structure represents the whole subsystem, including the CAL and
+ * the CAMERARX instances. The cal_camerarx structure represents one CAMERARX
+ * instance. The cal_ctx structure represents the combination of one CSI-2
+ * context, one processing context and one DMA context.
  */
+
+struct cal_camerarx {
+	void __iomem		*base;
+	struct resource		*res;
+	struct platform_device	*pdev;
+
+	struct {
+		struct regmap_field *fields[F_MAX_FIELDS];
+	} phy;
+};
+
 struct cal_dev {
 	struct clk		*fclk;
 	int			irq;
@@ -333,7 +340,7 @@ struct cal_dev {
 	u32			syscon_camerrx_offset;
 
 	/* Camera Core Module handle */
-	struct cc_data		*cc[CAL_NUM_CSI2_PORTS];
+	struct cal_camerarx	*cc[CAL_NUM_CSI2_PORTS];
 
 	struct cal_ctx		*ctx[CAL_NUM_CONTEXT];
 };
@@ -350,7 +357,7 @@ struct cal_ctx {
 	struct v4l2_fwnode_endpoint	endpoint;
 
 	struct cal_dev		*dev;
-	struct cc_data		*cc;
+	struct cal_camerarx	*cc;
 
 	/* v4l2_ioctl mutex */
 	struct mutex		mutex;
@@ -457,7 +464,8 @@ static u32 cal_data_get_num_csi2_phy(struct cal_dev *dev)
 	return dev->data->num_csi2_phy;
 }
 
-static int cal_camerarx_regmap_init(struct cal_dev *dev, struct cc_data *cc,
+static int cal_camerarx_regmap_init(struct cal_dev *dev,
+				    struct cal_camerarx *cc,
 				    unsigned int idx)
 {
 	const struct cal_csi2_phy *phy;
@@ -528,7 +536,7 @@ static struct regmap *cal_get_camerarx_regmap(struct cal_dev *dev)
 static void camerarx_phy_enable(struct cal_ctx *ctx)
 {
 	u32 phy_id = ctx->csi2_port;
-	struct cc_data *cc = ctx->dev->cc[phy_id];
+	struct cal_camerarx *cc = ctx->dev->cc[phy_id];
 	u32 max_lanes;
 
 	regmap_field_write(cc->phy.fields[F_CAMMODE], 0);
@@ -544,7 +552,7 @@ static void camerarx_phy_enable(struct cal_ctx *ctx)
 static void camerarx_phy_disable(struct cal_ctx *ctx)
 {
 	u32 phy_id = ctx->csi2_port;
-	struct cc_data *cc = ctx->dev->cc[phy_id];
+	struct cal_camerarx *cc = ctx->dev->cc[phy_id];
 
 	regmap_field_write(cc->phy.fields[F_CTRLCLKEN], 0);
 }
@@ -552,10 +560,10 @@ static void camerarx_phy_disable(struct cal_ctx *ctx)
 /*
  * Camera Instance access block
  */
-static struct cc_data *cc_create(struct cal_dev *dev, unsigned int core)
+static struct cal_camerarx *cc_create(struct cal_dev *dev, unsigned int core)
 {
 	struct platform_device *pdev = dev->pdev;
-	struct cc_data *cc;
+	struct cal_camerarx *cc;
 	int ret;
 
 	cc = devm_kzalloc(&pdev->dev, sizeof(*cc), GFP_KERNEL);
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 025/107] media: ti-vpe: cal: Rename cal_csi2_phy to cal_camerarx_data
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (23 preceding siblings ...)
  2020-06-14 23:58 ` [PATCH v1 024/107] media: ti-vpe: cal: Rename cc_data to cal_camerarx Laurent Pinchart
@ 2020-06-14 23:58 ` Laurent Pinchart
  2020-06-14 23:58 ` [PATCH v1 026/107] media: ti-vpe: cal: Name all cal_dev pointers consistently Laurent Pinchart
                   ` (83 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:58 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

The cal_csi2_phy contains platform data for the CAMERARX blocks. Rename
it to cal_camerarx_data.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 33 ++++++++++++++---------------
 1 file changed, 16 insertions(+), 17 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index df756c7b53b7..8b76e8709aad 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -215,7 +215,7 @@ enum cal_camerarx_field {
 	F_MAX_FIELDS,
 };
 
-struct cal_csi2_phy {
+struct cal_camerarx_data {
 	struct {
 		unsigned int lsb;
 		unsigned int msb;
@@ -224,13 +224,12 @@ struct cal_csi2_phy {
 };
 
 struct cal_data {
+	const struct cal_camerarx_data *camerarx;
 	unsigned int num_csi2_phy;
-	const struct cal_csi2_phy *csi2_phy_core;
-
 	unsigned int flags;
 };
 
-static const struct cal_csi2_phy dra72x_cal_csi_phy[] = {
+static const struct cal_camerarx_data dra72x_cal_camerarx[] = {
 	{
 		.fields = {
 			[F_CTRLCLKEN] = { 10, 10 },
@@ -252,17 +251,17 @@ static const struct cal_csi2_phy dra72x_cal_csi_phy[] = {
 };
 
 static const struct cal_data dra72x_cal_data = {
-	.csi2_phy_core = dra72x_cal_csi_phy,
-	.num_csi2_phy = ARRAY_SIZE(dra72x_cal_csi_phy),
+	.camerarx = dra72x_cal_camerarx,
+	.num_csi2_phy = ARRAY_SIZE(dra72x_cal_camerarx),
 };
 
 static const struct cal_data dra72x_es1_cal_data = {
-	.csi2_phy_core = dra72x_cal_csi_phy,
-	.num_csi2_phy = ARRAY_SIZE(dra72x_cal_csi_phy),
+	.camerarx = dra72x_cal_camerarx,
+	.num_csi2_phy = ARRAY_SIZE(dra72x_cal_camerarx),
 	.flags = DRA72_CAL_PRE_ES2_LDO_DISABLE,
 };
 
-static const struct cal_csi2_phy dra76x_cal_csi_phy[] = {
+static const struct cal_camerarx_data dra76x_cal_csi_phy[] = {
 	{
 		.fields = {
 			[F_CTRLCLKEN] = { 8, 8 },
@@ -284,11 +283,11 @@ static const struct cal_csi2_phy dra76x_cal_csi_phy[] = {
 };
 
 static const struct cal_data dra76x_cal_data = {
-	.csi2_phy_core = dra76x_cal_csi_phy,
+	.camerarx = dra76x_cal_csi_phy,
 	.num_csi2_phy = ARRAY_SIZE(dra76x_cal_csi_phy),
 };
 
-static const struct cal_csi2_phy am654_cal_csi_phy[] = {
+static const struct cal_camerarx_data am654_cal_csi_phy[] = {
 	{
 		.fields = {
 			[F_CTRLCLKEN] = { 15, 15 },
@@ -300,7 +299,7 @@ static const struct cal_csi2_phy am654_cal_csi_phy[] = {
 };
 
 static const struct cal_data am654_cal_data = {
-	.csi2_phy_core = am654_cal_csi_phy,
+	.camerarx = am654_cal_csi_phy,
 	.num_csi2_phy = ARRAY_SIZE(am654_cal_csi_phy),
 };
 
@@ -456,7 +455,7 @@ static u32 cal_data_get_phy_max_lanes(struct cal_ctx *ctx)
 	struct cal_dev *dev = ctx->dev;
 	u32 phy_id = ctx->csi2_port;
 
-	return dev->data->csi2_phy_core[phy_id].num_lanes;
+	return dev->data->camerarx[phy_id].num_lanes;
 }
 
 static u32 cal_data_get_num_csi2_phy(struct cal_dev *dev)
@@ -468,19 +467,19 @@ static int cal_camerarx_regmap_init(struct cal_dev *dev,
 				    struct cal_camerarx *cc,
 				    unsigned int idx)
 {
-	const struct cal_csi2_phy *phy;
+	const struct cal_camerarx_data *phy_data;
 	unsigned int i;
 
 	if (!dev->data)
 		return -EINVAL;
 
-	phy = &dev->data->csi2_phy_core[idx];
+	phy_data = &dev->data->camerarx[idx];
 
 	for (i = 0; i < F_MAX_FIELDS; i++) {
 		struct reg_field field = {
 			.reg = dev->syscon_camerrx_offset,
-			.lsb = phy->fields[i].lsb,
-			.msb = phy->fields[i].msb,
+			.lsb = phy_data->fields[i].lsb,
+			.msb = phy_data->fields[i].msb,
 		};
 
 		/*
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 026/107] media: ti-vpe: cal: Name all cal_dev pointers consistently
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (24 preceding siblings ...)
  2020-06-14 23:58 ` [PATCH v1 025/107] media: ti-vpe: cal: Rename cal_csi2_phy to cal_camerarx_data Laurent Pinchart
@ 2020-06-14 23:58 ` Laurent Pinchart
  2020-06-14 23:58 ` [PATCH v1 027/107] media: ti-vpe: cal: Name all cal_camerarx " Laurent Pinchart
                   ` (82 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:58 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

Name all variables pointing to a cal_dev instance 'cal', instead of a
combination of 'caldev' and 'dev'. 'caldev' is only used in a few places
and could have been renamed to 'dev', but 'dev' is confusing as it's
also used for struct device instances. This generates lots of changes,
but increases readability.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 368 ++++++++++++++--------------
 1 file changed, 186 insertions(+), 182 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index 8b76e8709aad..615e9d97e61f 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -53,12 +53,12 @@ static unsigned debug;
 module_param(debug, uint, 0644);
 MODULE_PARM_DESC(debug, "activates debug info");
 
-#define cal_dbg(level, caldev, fmt, arg...)	\
-		v4l2_dbg(level, debug, &caldev->v4l2_dev, fmt, ##arg)
-#define cal_info(caldev, fmt, arg...)	\
-		v4l2_info(&caldev->v4l2_dev, fmt, ##arg)
-#define cal_err(caldev, fmt, arg...)	\
-		v4l2_err(&caldev->v4l2_dev, fmt, ##arg)
+#define cal_dbg(level, cal, fmt, arg...)	\
+		v4l2_dbg(level, debug, &cal->v4l2_dev, fmt, ##arg)
+#define cal_info(cal, fmt, arg...)	\
+		v4l2_info(&cal->v4l2_dev, fmt, ##arg)
+#define cal_err(cal, fmt, arg...)	\
+		v4l2_err(&cal->v4l2_dev, fmt, ##arg)
 
 #define ctx_dbg(level, ctx, fmt, arg...)	\
 		v4l2_dbg(level, debug, &ctx->v4l2_dev, fmt, ##arg)
@@ -309,9 +309,14 @@ static const struct cal_data am654_cal_data = {
  * DMA contexts.
  *
  * The cal_dev structure represents the whole subsystem, including the CAL and
- * the CAMERARX instances. The cal_camerarx structure represents one CAMERARX
- * instance. The cal_ctx structure represents the combination of one CSI-2
- * context, one processing context and one DMA context.
+ * the CAMERARX instances. Instances of struct cal_dev are named cal through the
+ * driver.
+ *
+ * The cal_camerarx structure represents one CAMERARX instance.
+ *
+ * The cal_ctx structure represents the combination of one CSI-2 context, one
+ * processing context and one DMA context. Instance of struct cal_ctx are named
+ * ctx through the driver.
  */
 
 struct cal_camerarx {
@@ -355,7 +360,7 @@ struct cal_ctx {
 	struct v4l2_subdev	*sensor;
 	struct v4l2_fwnode_endpoint	endpoint;
 
-	struct cal_dev		*dev;
+	struct cal_dev		*cal;
 	struct cal_camerarx	*cc;
 
 	/* v4l2_ioctl mutex */
@@ -391,19 +396,19 @@ struct cal_ctx {
 	bool dma_act;
 };
 
-static inline u32 reg_read_field(struct cal_dev *dev, u32 offset, u32 mask)
+static inline u32 reg_read_field(struct cal_dev *cal, u32 offset, u32 mask)
 {
-	return FIELD_GET(mask, reg_read(dev, offset));
+	return FIELD_GET(mask, reg_read(cal, offset));
 }
 
-static inline void reg_write_field(struct cal_dev *dev, u32 offset, u32 value,
+static inline void reg_write_field(struct cal_dev *cal, u32 offset, u32 value,
 				   u32 mask)
 {
-	u32 val = reg_read(dev, offset);
+	u32 val = reg_read(cal, offset);
 
 	val &= ~mask;
 	val |= FIELD_PREP(mask, value);
-	reg_write(dev, offset, val);
+	reg_write(cal, offset, val);
 }
 
 static const struct cal_fmt *find_format_by_pix(struct cal_ctx *ctx,
@@ -452,32 +457,31 @@ static inline void set_field(u32 *valp, u32 field, u32 mask)
 
 static u32 cal_data_get_phy_max_lanes(struct cal_ctx *ctx)
 {
-	struct cal_dev *dev = ctx->dev;
 	u32 phy_id = ctx->csi2_port;
 
-	return dev->data->camerarx[phy_id].num_lanes;
+	return ctx->cal->data->camerarx[phy_id].num_lanes;
 }
 
-static u32 cal_data_get_num_csi2_phy(struct cal_dev *dev)
+static u32 cal_data_get_num_csi2_phy(struct cal_dev *cal)
 {
-	return dev->data->num_csi2_phy;
+	return cal->data->num_csi2_phy;
 }
 
-static int cal_camerarx_regmap_init(struct cal_dev *dev,
+static int cal_camerarx_regmap_init(struct cal_dev *cal,
 				    struct cal_camerarx *cc,
 				    unsigned int idx)
 {
 	const struct cal_camerarx_data *phy_data;
 	unsigned int i;
 
-	if (!dev->data)
+	if (!cal->data)
 		return -EINVAL;
 
-	phy_data = &dev->data->camerarx[idx];
+	phy_data = &cal->data->camerarx[idx];
 
 	for (i = 0; i < F_MAX_FIELDS; i++) {
 		struct reg_field field = {
-			.reg = dev->syscon_camerrx_offset,
+			.reg = cal->syscon_camerrx_offset,
 			.lsb = phy_data->fields[i].lsb,
 			.msb = phy_data->fields[i].msb,
 		};
@@ -486,11 +490,11 @@ static int cal_camerarx_regmap_init(struct cal_dev *dev,
 		 * Here we update the reg offset with the
 		 * value found in DT
 		 */
-		cc->phy.fields[i] = devm_regmap_field_alloc(&dev->pdev->dev,
-							    dev->syscon_camerrx,
+		cc->phy.fields[i] = devm_regmap_field_alloc(&cal->pdev->dev,
+							    cal->syscon_camerrx,
 							    field);
 		if (IS_ERR(cc->phy.fields[i])) {
-			cal_err(dev, "Unable to allocate regmap fields\n");
+			cal_err(cal, "Unable to allocate regmap fields\n");
 			return PTR_ERR(cc->phy.fields[i]);
 		}
 	}
@@ -498,9 +502,9 @@ static int cal_camerarx_regmap_init(struct cal_dev *dev,
 	return 0;
 }
 
-static struct regmap *cal_get_camerarx_regmap(struct cal_dev *dev)
+static struct regmap *cal_get_camerarx_regmap(struct cal_dev *cal)
 {
-	struct platform_device *pdev = dev->pdev;
+	struct platform_device *pdev = cal->pdev;
 	struct regmap_config config = { };
 	struct regmap *regmap;
 	void __iomem *base;
@@ -510,11 +514,11 @@ static struct regmap *cal_get_camerarx_regmap(struct cal_dev *dev)
 					   "camerrx_control");
 	base = devm_ioremap_resource(&pdev->dev, res);
 	if (IS_ERR(base)) {
-		cal_err(dev, "failed to ioremap\n");
+		cal_err(cal, "failed to ioremap\n");
 		return ERR_CAST(base);
 	}
 
-	cal_dbg(1, dev, "ioresource %s at %pa - %pa\n",
+	cal_dbg(1, cal, "ioresource %s at %pa - %pa\n",
 		res->name, &res->start, &res->end);
 
 	config.reg_bits = 32;
@@ -535,7 +539,7 @@ static struct regmap *cal_get_camerarx_regmap(struct cal_dev *dev)
 static void camerarx_phy_enable(struct cal_ctx *ctx)
 {
 	u32 phy_id = ctx->csi2_port;
-	struct cal_camerarx *cc = ctx->dev->cc[phy_id];
+	struct cal_camerarx *cc = ctx->cal->cc[phy_id];
 	u32 max_lanes;
 
 	regmap_field_write(cc->phy.fields[F_CAMMODE], 0);
@@ -551,7 +555,7 @@ static void camerarx_phy_enable(struct cal_ctx *ctx)
 static void camerarx_phy_disable(struct cal_ctx *ctx)
 {
 	u32 phy_id = ctx->csi2_port;
-	struct cal_camerarx *cc = ctx->dev->cc[phy_id];
+	struct cal_camerarx *cc = ctx->cal->cc[phy_id];
 
 	regmap_field_write(cc->phy.fields[F_CTRLCLKEN], 0);
 }
@@ -559,9 +563,9 @@ static void camerarx_phy_disable(struct cal_ctx *ctx)
 /*
  * Camera Instance access block
  */
-static struct cal_camerarx *cc_create(struct cal_dev *dev, unsigned int core)
+static struct cal_camerarx *cc_create(struct cal_dev *cal, unsigned int core)
 {
-	struct platform_device *pdev = dev->pdev;
+	struct platform_device *pdev = cal->pdev;
 	struct cal_camerarx *cc;
 	int ret;
 
@@ -576,14 +580,14 @@ static struct cal_camerarx *cc_create(struct cal_dev *dev, unsigned int core)
 						"cal_rx_core1");
 	cc->base = devm_ioremap_resource(&pdev->dev, cc->res);
 	if (IS_ERR(cc->base)) {
-		cal_err(dev, "failed to ioremap\n");
+		cal_err(cal, "failed to ioremap\n");
 		return ERR_CAST(cc->base);
 	}
 
-	cal_dbg(1, dev, "ioresource %s at %pa - %pa\n",
+	cal_dbg(1, cal, "ioresource %s at %pa - %pa\n",
 		cc->res->name, &cc->res->start, &cc->res->end);
 
-	ret = cal_camerarx_regmap_init(dev, cc, core);
+	ret = cal_camerarx_regmap_init(cal, cc, core);
 	if (ret)
 		return ERR_PTR(ret);
 
@@ -593,17 +597,17 @@ static struct cal_camerarx *cc_create(struct cal_dev *dev, unsigned int core)
 /*
  * Get Revision and HW info
  */
-static void cal_get_hwinfo(struct cal_dev *dev)
+static void cal_get_hwinfo(struct cal_dev *cal)
 {
 	u32 revision;
 	u32 hwinfo;
 
-	revision = reg_read(dev, CAL_HL_REVISION);
-	cal_dbg(3, dev, "CAL_HL_REVISION = 0x%08x (expecting 0x40000200)\n",
+	revision = reg_read(cal, CAL_HL_REVISION);
+	cal_dbg(3, cal, "CAL_HL_REVISION = 0x%08x (expecting 0x40000200)\n",
 		revision);
 
-	hwinfo = reg_read(dev, CAL_HL_HWINFO);
-	cal_dbg(3, dev, "CAL_HL_HWINFO = 0x%08x (expecting 0xA3C90469)\n",
+	hwinfo = reg_read(cal, CAL_HL_HWINFO);
+	cal_dbg(3, cal, "CAL_HL_HWINFO = 0x%08x (expecting 0xA3C90469)\n",
 		hwinfo);
 }
 
@@ -626,38 +630,38 @@ static void cal_get_hwinfo(struct cal_dev *dev)
  *		Core 0:  0x4845 B828 = 0x0000 0040
  *		Core 1:  0x4845 B928 = 0x0000 0040
  */
-static void i913_errata(struct cal_dev *dev, unsigned int port)
+static void i913_errata(struct cal_dev *cal, unsigned int port)
 {
-	u32 reg10 = reg_read(dev->cc[port], CAL_CSI2_PHY_REG10);
+	u32 reg10 = reg_read(cal->cc[port], CAL_CSI2_PHY_REG10);
 
 	set_field(&reg10, 1, CAL_CSI2_PHY_REG10_I933_LDO_DISABLE_MASK);
 
-	cal_dbg(1, dev, "CSI2_%d_REG10 = 0x%08x\n", port, reg10);
-	reg_write(dev->cc[port], CAL_CSI2_PHY_REG10, reg10);
+	cal_dbg(1, cal, "CSI2_%d_REG10 = 0x%08x\n", port, reg10);
+	reg_write(cal->cc[port], CAL_CSI2_PHY_REG10, reg10);
 }
 
-static void cal_quickdump_regs(struct cal_dev *dev)
+static void cal_quickdump_regs(struct cal_dev *cal)
 {
-	cal_info(dev, "CAL Registers @ 0x%pa:\n", &dev->res->start);
+	cal_info(cal, "CAL Registers @ 0x%pa:\n", &cal->res->start);
 	print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 4,
-		       (__force const void *)dev->base,
-		       resource_size(dev->res), false);
+		       (__force const void *)cal->base,
+		       resource_size(cal->res), false);
 
-	if (dev->ctx[0]) {
-		cal_info(dev, "CSI2 Core 0 Registers @ %pa:\n",
-			 &dev->ctx[0]->cc->res->start);
+	if (cal->ctx[0]) {
+		cal_info(cal, "CSI2 Core 0 Registers @ %pa:\n",
+			 &cal->ctx[0]->cc->res->start);
 		print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 4,
-			       (__force const void *)dev->ctx[0]->cc->base,
-			       resource_size(dev->ctx[0]->cc->res),
+			       (__force const void *)cal->ctx[0]->cc->base,
+			       resource_size(cal->ctx[0]->cc->res),
 			       false);
 	}
 
-	if (dev->ctx[1]) {
-		cal_info(dev, "CSI2 Core 1 Registers @ %pa:\n",
-			 &dev->ctx[1]->cc->res->start);
+	if (cal->ctx[1]) {
+		cal_info(cal, "CSI2 Core 1 Registers @ %pa:\n",
+			 &cal->ctx[1]->cc->res->start);
 		print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 4,
-			       (__force const void *)dev->ctx[1]->cc->base,
-			       resource_size(dev->ctx[1]->cc->res),
+			       (__force const void *)cal->ctx[1]->cc->base,
+			       resource_size(cal->ctx[1]->cc->res),
 			       false);
 	}
 }
@@ -676,24 +680,24 @@ static void enable_irqs(struct cal_ctx *ctx)
 		CAL_CSI2_COMPLEXIO_IRQ_ECC_NO_CORRECTION_MASK;
 
 	/* Enable CIO error irqs */
-	reg_write(ctx->dev, CAL_HL_IRQENABLE_SET(0),
+	reg_write(ctx->cal, CAL_HL_IRQENABLE_SET(0),
 		  CAL_HL_IRQ_CIO_MASK(ctx->csi2_port));
-	reg_write(ctx->dev, CAL_CSI2_COMPLEXIO_IRQENABLE(ctx->csi2_port),
+	reg_write(ctx->cal, CAL_CSI2_COMPLEXIO_IRQENABLE(ctx->csi2_port),
 		  cio_err_mask);
 
 	/* Always enable OCPO error */
-	reg_write(ctx->dev, CAL_HL_IRQENABLE_SET(0), CAL_HL_IRQ_OCPO_ERR_MASK);
+	reg_write(ctx->cal, CAL_HL_IRQENABLE_SET(0), CAL_HL_IRQ_OCPO_ERR_MASK);
 
 	/* Enable IRQ_WDMA_END 0/1 */
 	val = 0;
 	set_field(&val, 1, CAL_HL_IRQ_MASK(ctx->csi2_port));
-	reg_write(ctx->dev, CAL_HL_IRQENABLE_SET(1), val);
+	reg_write(ctx->cal, CAL_HL_IRQENABLE_SET(1), val);
 	/* Enable IRQ_WDMA_START 0/1 */
 	val = 0;
 	set_field(&val, 1, CAL_HL_IRQ_MASK(ctx->csi2_port));
-	reg_write(ctx->dev, CAL_HL_IRQENABLE_SET(2), val);
+	reg_write(ctx->cal, CAL_HL_IRQENABLE_SET(2), val);
 	/* Todo: Add VC_IRQ and CSI2_COMPLEXIO_IRQ handling */
-	reg_write(ctx->dev, CAL_CSI2_VC_IRQENABLE(0), 0xFF000000);
+	reg_write(ctx->cal, CAL_CSI2_VC_IRQENABLE(0), 0xFF000000);
 }
 
 static void disable_irqs(struct cal_ctx *ctx)
@@ -701,21 +705,21 @@ static void disable_irqs(struct cal_ctx *ctx)
 	u32 val;
 
 	/* Disable CIO error irqs */
-	reg_write(ctx->dev, CAL_HL_IRQENABLE_CLR(0),
+	reg_write(ctx->cal, CAL_HL_IRQENABLE_CLR(0),
 		  CAL_HL_IRQ_CIO_MASK(ctx->csi2_port));
-	reg_write(ctx->dev, CAL_CSI2_COMPLEXIO_IRQENABLE(ctx->csi2_port),
+	reg_write(ctx->cal, CAL_CSI2_COMPLEXIO_IRQENABLE(ctx->csi2_port),
 		  0);
 
 	/* Disable IRQ_WDMA_END 0/1 */
 	val = 0;
 	set_field(&val, 1, CAL_HL_IRQ_MASK(ctx->csi2_port));
-	reg_write(ctx->dev, CAL_HL_IRQENABLE_CLR(1), val);
+	reg_write(ctx->cal, CAL_HL_IRQENABLE_CLR(1), val);
 	/* Disable IRQ_WDMA_START 0/1 */
 	val = 0;
 	set_field(&val, 1, CAL_HL_IRQ_MASK(ctx->csi2_port));
-	reg_write(ctx->dev, CAL_HL_IRQENABLE_CLR(2), val);
+	reg_write(ctx->cal, CAL_HL_IRQENABLE_CLR(2), val);
 	/* Todo: Add VC_IRQ and CSI2_COMPLEXIO_IRQ handling */
-	reg_write(ctx->dev, CAL_CSI2_VC_IRQENABLE(0), 0);
+	reg_write(ctx->cal, CAL_CSI2_VC_IRQENABLE(0), 0);
 }
 
 static void csi2_cio_power(struct cal_ctx *ctx, bool enable)
@@ -726,13 +730,13 @@ static void csi2_cio_power(struct cal_ctx *ctx, bool enable)
 	target_state = enable ? CAL_CSI2_COMPLEXIO_CFG_PWR_CMD_STATE_ON :
 		       CAL_CSI2_COMPLEXIO_CFG_PWR_CMD_STATE_OFF;
 
-	reg_write_field(ctx->dev, CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port),
+	reg_write_field(ctx->cal, CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port),
 			target_state, CAL_CSI2_COMPLEXIO_CFG_PWR_CMD_MASK);
 
 	for (i = 0; i < 10; i++) {
 		u32 current_state;
 
-		current_state = reg_read_field(ctx->dev,
+		current_state = reg_read_field(ctx->cal,
 					       CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port),
 					       CAL_CSI2_COMPLEXIO_CFG_PWR_STATUS_MASK);
 
@@ -822,12 +826,12 @@ static void csi2_phy_init(struct cal_ctx *ctx)
 	camerarx_phy_enable(ctx);
 
 	/* 2. Reset complex IO - Do not wait for reset completion */
-	reg_write_field(ctx->dev, CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port),
+	reg_write_field(ctx->cal, CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port),
 			CAL_CSI2_COMPLEXIO_CFG_RESET_CTRL_OPERATIONAL,
 			CAL_CSI2_COMPLEXIO_CFG_RESET_CTRL_MASK);
 	ctx_dbg(3, ctx, "CAL_CSI2_COMPLEXIO_CFG(%d) = 0x%08x De-assert Complex IO Reset\n",
 		ctx->csi2_port,
-		reg_read(ctx->dev, CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port)));
+		reg_read(ctx->cal, CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port)));
 
 	/* Dummy read to allow SCP reset to complete */
 	reg_read(ctx->cc, CAL_CSI2_PHY_REG0);
@@ -844,23 +848,23 @@ static void csi2_phy_init(struct cal_ctx *ctx)
 	 * Stop-state-timeout must be more than 100us as per CSI2 spec, so we
 	 * calculate a timeout that's 100us (rounding up).
 	 */
-	sscounter = DIV_ROUND_UP(clk_get_rate(ctx->dev->fclk), 10000 *  16 * 4);
+	sscounter = DIV_ROUND_UP(clk_get_rate(ctx->cal->fclk), 10000 *  16 * 4);
 
-	val = reg_read(ctx->dev, CAL_CSI2_TIMING(ctx->csi2_port));
+	val = reg_read(ctx->cal, CAL_CSI2_TIMING(ctx->csi2_port));
 	set_field(&val, 1, CAL_CSI2_TIMING_STOP_STATE_X16_IO1_MASK);
 	set_field(&val, 1, CAL_CSI2_TIMING_STOP_STATE_X4_IO1_MASK);
 	set_field(&val, sscounter, CAL_CSI2_TIMING_STOP_STATE_COUNTER_IO1_MASK);
-	reg_write(ctx->dev, CAL_CSI2_TIMING(ctx->csi2_port), val);
+	reg_write(ctx->cal, CAL_CSI2_TIMING(ctx->csi2_port), val);
 	ctx_dbg(3, ctx, "CAL_CSI2_TIMING(%d) = 0x%08x Stop States\n",
 		ctx->csi2_port,
-		reg_read(ctx->dev, CAL_CSI2_TIMING(ctx->csi2_port)));
+		reg_read(ctx->cal, CAL_CSI2_TIMING(ctx->csi2_port)));
 
 	/* 4. Force FORCERXMODE */
-	reg_write_field(ctx->dev, CAL_CSI2_TIMING(ctx->csi2_port),
+	reg_write_field(ctx->cal, CAL_CSI2_TIMING(ctx->csi2_port),
 			1, CAL_CSI2_TIMING_FORCE_RX_MODE_IO1_MASK);
 	ctx_dbg(3, ctx, "CAL_CSI2_TIMING(%d) = 0x%08x Force RXMODE\n",
 		ctx->csi2_port,
-		reg_read(ctx->dev, CAL_CSI2_TIMING(ctx->csi2_port)));
+		reg_read(ctx->cal, CAL_CSI2_TIMING(ctx->csi2_port)));
 
 	/* E. Power up the PHY using the complex IO */
 	csi2_cio_power(ctx, true);
@@ -872,7 +876,7 @@ static void csi2_wait_complexio_reset(struct cal_ctx *ctx)
 
 	timeout = jiffies + msecs_to_jiffies(750);
 	while (time_before(jiffies, timeout)) {
-		if (reg_read_field(ctx->dev,
+		if (reg_read_field(ctx->cal,
 				   CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port),
 				   CAL_CSI2_COMPLEXIO_CFG_RESET_DONE_MASK) ==
 		    CAL_CSI2_COMPLEXIO_CFG_RESET_DONE_RESETCOMPLETED)
@@ -880,7 +884,7 @@ static void csi2_wait_complexio_reset(struct cal_ctx *ctx)
 		usleep_range(500, 5000);
 	}
 
-	if (reg_read_field(ctx->dev, CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port),
+	if (reg_read_field(ctx->cal, CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port),
 			   CAL_CSI2_COMPLEXIO_CFG_RESET_DONE_MASK) !=
 			   CAL_CSI2_COMPLEXIO_CFG_RESET_DONE_RESETCOMPLETED)
 		ctx_err(ctx, "Timeout waiting for Complex IO reset done\n");
@@ -892,14 +896,14 @@ static void csi2_wait_stop_state(struct cal_ctx *ctx)
 
 	timeout = jiffies + msecs_to_jiffies(750);
 	while (time_before(jiffies, timeout)) {
-		if (reg_read_field(ctx->dev,
+		if (reg_read_field(ctx->cal,
 				   CAL_CSI2_TIMING(ctx->csi2_port),
 				   CAL_CSI2_TIMING_FORCE_RX_MODE_IO1_MASK) == 0)
 			break;
 		usleep_range(500, 5000);
 	}
 
-	if (reg_read_field(ctx->dev, CAL_CSI2_TIMING(ctx->csi2_port),
+	if (reg_read_field(ctx->cal, CAL_CSI2_TIMING(ctx->csi2_port),
 			   CAL_CSI2_TIMING_FORCE_RX_MODE_IO1_MASK) != 0)
 		ctx_err(ctx, "Timeout waiting for stop state\n");
 }
@@ -932,13 +936,13 @@ static void csi2_phy_deinit(struct cal_ctx *ctx)
 	csi2_cio_power(ctx, false);
 
 	/* Assert Comple IO Reset */
-	reg_write_field(ctx->dev, CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port),
+	reg_write_field(ctx->cal, CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port),
 			CAL_CSI2_COMPLEXIO_CFG_RESET_CTRL,
 			CAL_CSI2_COMPLEXIO_CFG_RESET_CTRL_MASK);
 
 	/* Wait for power down completion */
 	for (i = 0; i < 10; i++) {
-		if (reg_read_field(ctx->dev,
+		if (reg_read_field(ctx->cal,
 				   CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port),
 				   CAL_CSI2_COMPLEXIO_CFG_RESET_DONE_MASK) ==
 		    CAL_CSI2_COMPLEXIO_CFG_RESET_DONE_RESETONGOING)
@@ -947,7 +951,7 @@ static void csi2_phy_deinit(struct cal_ctx *ctx)
 	}
 	ctx_dbg(3, ctx, "CAL_CSI2_COMPLEXIO_CFG(%d) = 0x%08x Complex IO in Reset (%d) %s\n",
 		ctx->csi2_port,
-		reg_read(ctx->dev, CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port)), i,
+		reg_read(ctx->cal, CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port)), i,
 		(i >= 10) ? "(timeout)" : "");
 
 	/* Disable the phy */
@@ -956,7 +960,7 @@ static void csi2_phy_deinit(struct cal_ctx *ctx)
 
 static void csi2_lane_config(struct cal_ctx *ctx)
 {
-	u32 val = reg_read(ctx->dev, CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port));
+	u32 val = reg_read(ctx->cal, CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port));
 	u32 lane_mask = CAL_CSI2_COMPLEXIO_CFG_CLOCK_POSITION_MASK;
 	u32 polarity_mask = CAL_CSI2_COMPLEXIO_CFG_CLOCK_POL_MASK;
 	struct v4l2_fwnode_bus_mipi_csi2 *mipi_csi2 =
@@ -977,21 +981,21 @@ static void csi2_lane_config(struct cal_ctx *ctx)
 			  polarity_mask);
 	}
 
-	reg_write(ctx->dev, CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port), val);
+	reg_write(ctx->cal, CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port), val);
 	ctx_dbg(3, ctx, "CAL_CSI2_COMPLEXIO_CFG(%d) = 0x%08x\n",
 		ctx->csi2_port, val);
 }
 
 static void csi2_ppi_enable(struct cal_ctx *ctx)
 {
-	reg_write(ctx->dev, CAL_CSI2_PPI_CTRL(ctx->csi2_port), BIT(3));
-	reg_write_field(ctx->dev, CAL_CSI2_PPI_CTRL(ctx->csi2_port),
+	reg_write(ctx->cal, CAL_CSI2_PPI_CTRL(ctx->csi2_port), BIT(3));
+	reg_write_field(ctx->cal, CAL_CSI2_PPI_CTRL(ctx->csi2_port),
 			1, CAL_CSI2_PPI_CTRL_IF_EN_MASK);
 }
 
 static void csi2_ppi_disable(struct cal_ctx *ctx)
 {
-	reg_write_field(ctx->dev, CAL_CSI2_PPI_CTRL(ctx->csi2_port),
+	reg_write_field(ctx->cal, CAL_CSI2_PPI_CTRL(ctx->csi2_port),
 			0, CAL_CSI2_PPI_CTRL_IF_EN_MASK);
 }
 
@@ -999,7 +1003,7 @@ static void csi2_ctx_config(struct cal_ctx *ctx)
 {
 	u32 val;
 
-	val = reg_read(ctx->dev, CAL_CSI2_CTX0(ctx->csi2_port));
+	val = reg_read(ctx->cal, CAL_CSI2_CTX0(ctx->csi2_port));
 	set_field(&val, ctx->cport, CAL_CSI2_CTX_CPORT_MASK);
 	/*
 	 * DT type: MIPI CSI-2 Specs
@@ -1016,9 +1020,9 @@ static void csi2_ctx_config(struct cal_ctx *ctx)
 	set_field(&val, CAL_CSI2_CTX_ATT_PIX, CAL_CSI2_CTX_ATT_MASK);
 	set_field(&val, CAL_CSI2_CTX_PACK_MODE_LINE,
 		  CAL_CSI2_CTX_PACK_MODE_MASK);
-	reg_write(ctx->dev, CAL_CSI2_CTX0(ctx->csi2_port), val);
+	reg_write(ctx->cal, CAL_CSI2_CTX0(ctx->csi2_port), val);
 	ctx_dbg(3, ctx, "CAL_CSI2_CTX0(%d) = 0x%08x\n", ctx->csi2_port,
-		reg_read(ctx->dev, CAL_CSI2_CTX0(ctx->csi2_port)));
+		reg_read(ctx->cal, CAL_CSI2_CTX0(ctx->csi2_port)));
 }
 
 static void pix_proc_config(struct cal_ctx *ctx)
@@ -1052,7 +1056,7 @@ static void pix_proc_config(struct cal_ctx *ctx)
 		 *
 		 * Instead of failing here just use 8 bpp as a default.
 		 */
-		dev_warn_once(&ctx->dev->pdev->dev,
+		dev_warn_once(&ctx->cal->pdev->dev,
 			      "%s:%d:%s: bpp:%d unsupported! Overwritten with 8.\n",
 			      __FILE__, __LINE__, __func__, ctx->fmt->bpp);
 		extract = CAL_PIX_PROC_EXTRACT_B8;
@@ -1060,16 +1064,16 @@ static void pix_proc_config(struct cal_ctx *ctx)
 		break;
 	}
 
-	val = reg_read(ctx->dev, CAL_PIX_PROC(ctx->csi2_port));
+	val = reg_read(ctx->cal, CAL_PIX_PROC(ctx->csi2_port));
 	set_field(&val, extract, CAL_PIX_PROC_EXTRACT_MASK);
 	set_field(&val, CAL_PIX_PROC_DPCMD_BYPASS, CAL_PIX_PROC_DPCMD_MASK);
 	set_field(&val, CAL_PIX_PROC_DPCME_BYPASS, CAL_PIX_PROC_DPCME_MASK);
 	set_field(&val, pack, CAL_PIX_PROC_PACK_MASK);
 	set_field(&val, ctx->cport, CAL_PIX_PROC_CPORT_MASK);
 	set_field(&val, 1, CAL_PIX_PROC_EN_MASK);
-	reg_write(ctx->dev, CAL_PIX_PROC(ctx->csi2_port), val);
+	reg_write(ctx->cal, CAL_PIX_PROC(ctx->csi2_port), val);
 	ctx_dbg(3, ctx, "CAL_PIX_PROC(%d) = 0x%08x\n", ctx->csi2_port,
-		reg_read(ctx->dev, CAL_PIX_PROC(ctx->csi2_port)));
+		reg_read(ctx->cal, CAL_PIX_PROC(ctx->csi2_port)));
 }
 
 static void cal_wr_dma_config(struct cal_ctx *ctx,
@@ -1077,7 +1081,7 @@ static void cal_wr_dma_config(struct cal_ctx *ctx,
 {
 	u32 val;
 
-	val = reg_read(ctx->dev, CAL_WR_DMA_CTRL(ctx->csi2_port));
+	val = reg_read(ctx->cal, CAL_WR_DMA_CTRL(ctx->csi2_port));
 	set_field(&val, ctx->cport, CAL_WR_DMA_CTRL_CPORT_MASK);
 	set_field(&val, height, CAL_WR_DMA_CTRL_YSIZE_MASK);
 	set_field(&val, CAL_WR_DMA_CTRL_DTAG_PIX_DAT,
@@ -1087,22 +1091,22 @@ static void cal_wr_dma_config(struct cal_ctx *ctx,
 	set_field(&val, CAL_WR_DMA_CTRL_PATTERN_LINEAR,
 		  CAL_WR_DMA_CTRL_PATTERN_MASK);
 	set_field(&val, 1, CAL_WR_DMA_CTRL_STALL_RD_MASK);
-	reg_write(ctx->dev, CAL_WR_DMA_CTRL(ctx->csi2_port), val);
+	reg_write(ctx->cal, CAL_WR_DMA_CTRL(ctx->csi2_port), val);
 	ctx_dbg(3, ctx, "CAL_WR_DMA_CTRL(%d) = 0x%08x\n", ctx->csi2_port,
-		reg_read(ctx->dev, CAL_WR_DMA_CTRL(ctx->csi2_port)));
+		reg_read(ctx->cal, CAL_WR_DMA_CTRL(ctx->csi2_port)));
 
 	/*
 	 * width/16 not sure but giving it a whirl.
 	 * zero does not work right
 	 */
-	reg_write_field(ctx->dev,
+	reg_write_field(ctx->cal,
 			CAL_WR_DMA_OFST(ctx->csi2_port),
 			(width / 16),
 			CAL_WR_DMA_OFST_MASK);
 	ctx_dbg(3, ctx, "CAL_WR_DMA_OFST(%d) = 0x%08x\n", ctx->csi2_port,
-		reg_read(ctx->dev, CAL_WR_DMA_OFST(ctx->csi2_port)));
+		reg_read(ctx->cal, CAL_WR_DMA_OFST(ctx->csi2_port)));
 
-	val = reg_read(ctx->dev, CAL_WR_DMA_XSIZE(ctx->csi2_port));
+	val = reg_read(ctx->cal, CAL_WR_DMA_XSIZE(ctx->csi2_port));
 	/* 64 bit word means no skipping */
 	set_field(&val, 0, CAL_WR_DMA_XSIZE_XSKIP_MASK);
 	/*
@@ -1111,24 +1115,24 @@ static void cal_wr_dma_config(struct cal_ctx *ctx,
 	 * is detected automagically
 	 */
 	set_field(&val, (width / 8), CAL_WR_DMA_XSIZE_MASK);
-	reg_write(ctx->dev, CAL_WR_DMA_XSIZE(ctx->csi2_port), val);
+	reg_write(ctx->cal, CAL_WR_DMA_XSIZE(ctx->csi2_port), val);
 	ctx_dbg(3, ctx, "CAL_WR_DMA_XSIZE(%d) = 0x%08x\n", ctx->csi2_port,
-		reg_read(ctx->dev, CAL_WR_DMA_XSIZE(ctx->csi2_port)));
+		reg_read(ctx->cal, CAL_WR_DMA_XSIZE(ctx->csi2_port)));
 
-	val = reg_read(ctx->dev, CAL_CTRL);
+	val = reg_read(ctx->cal, CAL_CTRL);
 	set_field(&val, CAL_CTRL_BURSTSIZE_BURST128, CAL_CTRL_BURSTSIZE_MASK);
 	set_field(&val, 0xF, CAL_CTRL_TAGCNT_MASK);
 	set_field(&val, CAL_CTRL_POSTED_WRITES_NONPOSTED,
 		  CAL_CTRL_POSTED_WRITES_MASK);
 	set_field(&val, 0xFF, CAL_CTRL_MFLAGL_MASK);
 	set_field(&val, 0xFF, CAL_CTRL_MFLAGH_MASK);
-	reg_write(ctx->dev, CAL_CTRL, val);
-	ctx_dbg(3, ctx, "CAL_CTRL = 0x%08x\n", reg_read(ctx->dev, CAL_CTRL));
+	reg_write(ctx->cal, CAL_CTRL, val);
+	ctx_dbg(3, ctx, "CAL_CTRL = 0x%08x\n", reg_read(ctx->cal, CAL_CTRL));
 }
 
 static void cal_wr_dma_addr(struct cal_ctx *ctx, unsigned int dmaaddr)
 {
-	reg_write(ctx->dev, CAL_WR_DMA_ADDR(ctx->csi2_port), dmaaddr);
+	reg_write(ctx->cal, CAL_WR_DMA_ADDR(ctx->csi2_port), dmaaddr);
 }
 
 static int cal_get_external_info(struct cal_ctx *ctx)
@@ -1182,42 +1186,42 @@ static inline void cal_process_buffer_complete(struct cal_ctx *ctx)
 
 static irqreturn_t cal_irq(int irq_cal, void *data)
 {
-	struct cal_dev *dev = data;
+	struct cal_dev *cal = data;
 	struct cal_ctx *ctx;
 	struct cal_dmaqueue *dma_q;
 	unsigned int i;
 	u32 status;
 
-	status = reg_read(dev, CAL_HL_IRQSTATUS(0));
+	status = reg_read(cal, CAL_HL_IRQSTATUS(0));
 	if (status) {
-		reg_write(dev, CAL_HL_IRQSTATUS(0), status);
+		reg_write(cal, CAL_HL_IRQSTATUS(0), status);
 
 		if (status & CAL_HL_IRQ_OCPO_ERR_MASK)
-			dev_err_ratelimited(&dev->pdev->dev, "OCPO ERROR\n");
+			dev_err_ratelimited(&cal->pdev->dev, "OCPO ERROR\n");
 
 		for (i = 0; i < 2; ++i) {
 			if (status & CAL_HL_IRQ_CIO_MASK(i)) {
-				u32 cio_stat = reg_read(dev,
+				u32 cio_stat = reg_read(cal,
 							CAL_CSI2_COMPLEXIO_IRQSTATUS(i));
 
-				dev_err_ratelimited(&dev->pdev->dev,
+				dev_err_ratelimited(&cal->pdev->dev,
 						    "CIO%u error: %#08x\n", i, cio_stat);
 
-				reg_write(dev, CAL_CSI2_COMPLEXIO_IRQSTATUS(i),
+				reg_write(cal, CAL_CSI2_COMPLEXIO_IRQSTATUS(i),
 					  cio_stat);
 			}
 		}
 	}
 
 	/* Check which DMA just finished */
-	status = reg_read(dev, CAL_HL_IRQSTATUS(1));
+	status = reg_read(cal, CAL_HL_IRQSTATUS(1));
 	if (status) {
 		/* Clear Interrupt status */
-		reg_write(dev, CAL_HL_IRQSTATUS(1), status);
+		reg_write(cal, CAL_HL_IRQSTATUS(1), status);
 
 		for (i = 0; i < 2; ++i) {
 			if (isportirqset(status, i)) {
-				ctx = dev->ctx[i];
+				ctx = cal->ctx[i];
 
 				spin_lock(&ctx->slock);
 				ctx->dma_act = false;
@@ -1231,14 +1235,14 @@ static irqreturn_t cal_irq(int irq_cal, void *data)
 	}
 
 	/* Check which DMA just started */
-	status = reg_read(dev, CAL_HL_IRQSTATUS(2));
+	status = reg_read(cal, CAL_HL_IRQSTATUS(2));
 	if (status) {
 		/* Clear Interrupt status */
-		reg_write(dev, CAL_HL_IRQSTATUS(2), status);
+		reg_write(cal, CAL_HL_IRQSTATUS(2), status);
 
 		for (i = 0; i < 2; ++i) {
 			if (isportirqset(status, i)) {
-				ctx = dev->ctx[i];
+				ctx = cal->ctx[i];
 				dma_q = &ctx->vidq;
 
 				spin_lock(&ctx->slock);
@@ -1662,7 +1666,7 @@ static int cal_start_streaming(struct vb2_queue *vq, unsigned int count)
 		goto err;
 	}
 
-	pm_runtime_get_sync(&ctx->dev->pdev->dev);
+	pm_runtime_get_sync(&ctx->cal->pdev->dev);
 
 	csi2_ctx_config(ctx);
 	pix_proc_config(ctx);
@@ -1677,7 +1681,7 @@ static int cal_start_streaming(struct vb2_queue *vq, unsigned int count)
 	if (ret) {
 		v4l2_subdev_call(ctx->sensor, core, s_power, 0);
 		ctx_err(ctx, "stream on failed in subdev\n");
-		pm_runtime_put_sync(&ctx->dev->pdev->dev);
+		pm_runtime_put_sync(&ctx->cal->pdev->dev);
 		goto err;
 	}
 
@@ -1686,7 +1690,7 @@ static int cal_start_streaming(struct vb2_queue *vq, unsigned int count)
 	csi2_ppi_enable(ctx);
 
 	if (debug >= 4)
-		cal_quickdump_regs(ctx->dev);
+		cal_quickdump_regs(ctx->cal);
 
 	return 0;
 
@@ -1757,7 +1761,7 @@ static void cal_stop_streaming(struct vb2_queue *vq)
 	ctx->next_frm = NULL;
 	spin_unlock_irqrestore(&ctx->slock, flags);
 
-	pm_runtime_put_sync(&ctx->dev->pdev->dev);
+	pm_runtime_put_sync(&ctx->cal->pdev->dev);
 }
 
 static const struct vb2_ops cal_video_qops = {
@@ -2032,7 +2036,7 @@ of_get_next_endpoint(const struct device_node *parent,
 
 static int of_cal_create_instance(struct cal_ctx *ctx, int inst)
 {
-	struct platform_device *pdev = ctx->dev->pdev;
+	struct platform_device *pdev = ctx->cal->pdev;
 	struct device_node *ep_node, *port, *sensor_node, *parent;
 	struct v4l2_fwnode_endpoint *endpoint;
 	struct v4l2_async_subdev *asd;
@@ -2155,22 +2159,22 @@ static int of_cal_create_instance(struct cal_ctx *ctx, int inst)
 	return ret;
 }
 
-static struct cal_ctx *cal_create_instance(struct cal_dev *dev, int inst)
+static struct cal_ctx *cal_create_instance(struct cal_dev *cal, int inst)
 {
 	struct cal_ctx *ctx;
 	struct v4l2_ctrl_handler *hdl;
 	int ret;
 
-	ctx = devm_kzalloc(&dev->pdev->dev, sizeof(*ctx), GFP_KERNEL);
+	ctx = devm_kzalloc(&cal->pdev->dev, sizeof(*ctx), GFP_KERNEL);
 	if (!ctx)
 		return NULL;
 
 	/* save the cal_dev * for future ref */
-	ctx->dev = dev;
+	ctx->cal = cal;
 
 	snprintf(ctx->v4l2_dev.name, sizeof(ctx->v4l2_dev.name),
 		 "%s-%03d", CAL_MODULE_NAME, inst);
-	ret = v4l2_device_register(&dev->pdev->dev, &ctx->v4l2_dev);
+	ret = v4l2_device_register(&cal->pdev->dev, &ctx->v4l2_dev);
 	if (ret)
 		goto err_exit;
 
@@ -2183,7 +2187,7 @@ static struct cal_ctx *cal_create_instance(struct cal_dev *dev, int inst)
 	ctx->v4l2_dev.ctrl_handler = hdl;
 
 	/* Make sure Camera Core H/W register area is available */
-	ctx->cc = dev->cc[inst];
+	ctx->cc = cal->cc[inst];
 
 	/* Store the instance id */
 	ctx->csi2_port = inst;
@@ -2227,7 +2231,7 @@ MODULE_DEVICE_TABLE(of, cal_of_match);
 
 static int cal_probe(struct platform_device *pdev)
 {
-	struct cal_dev *dev;
+	struct cal_dev *cal;
 	struct cal_ctx *ctx;
 	struct device_node *parent = pdev->dev.of_node;
 	struct regmap *syscon_camerrx;
@@ -2236,27 +2240,27 @@ static int cal_probe(struct platform_device *pdev)
 	int ret;
 	int irq;
 
-	dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
-	if (!dev)
+	cal = devm_kzalloc(&pdev->dev, sizeof(*cal), GFP_KERNEL);
+	if (!cal)
 		return -ENOMEM;
 
-	dev->data = of_device_get_match_data(&pdev->dev);
-	if (!dev->data) {
+	cal->data = of_device_get_match_data(&pdev->dev);
+	if (!cal->data) {
 		dev_err(&pdev->dev, "Could not get feature data based on compatible version\n");
 		return -ENODEV;
 	}
 
 	/* set pseudo v4l2 device name so we can use v4l2_printk */
-	strscpy(dev->v4l2_dev.name, CAL_MODULE_NAME,
-		sizeof(dev->v4l2_dev.name));
+	strscpy(cal->v4l2_dev.name, CAL_MODULE_NAME,
+		sizeof(cal->v4l2_dev.name));
 
 	/* save pdev pointer */
-	dev->pdev = pdev;
+	cal->pdev = pdev;
 
-	dev->fclk = devm_clk_get(&pdev->dev, "fck");
-	if (IS_ERR(dev->fclk)) {
+	cal->fclk = devm_clk_get(&pdev->dev, "fck");
+	if (IS_ERR(cal->fclk)) {
 		dev_err(&pdev->dev, "cannot get CAL fclk\n");
-		return PTR_ERR(dev->fclk);
+		return PTR_ERR(cal->fclk);
 	}
 
 	syscon_camerrx = syscon_regmap_lookup_by_phandle(parent,
@@ -2274,7 +2278,7 @@ static int cal_probe(struct platform_device *pdev)
 		 * If syscon entry is not present then check if the
 		 * camerrx_control resource is present.
 		 */
-		syscon_camerrx = cal_get_camerarx_regmap(dev);
+		syscon_camerrx = cal_get_camerarx_regmap(cal);
 		if (IS_ERR(syscon_camerrx)) {
 			dev_err(&pdev->dev, "failed to get camerrx_control regmap\n");
 			return PTR_ERR(syscon_camerrx);
@@ -2285,47 +2289,47 @@ static int cal_probe(struct platform_device *pdev)
 		syscon_camerrx_offset = 0;
 	}
 
-	dev->syscon_camerrx = syscon_camerrx;
-	dev->syscon_camerrx_offset = syscon_camerrx_offset;
+	cal->syscon_camerrx = syscon_camerrx;
+	cal->syscon_camerrx_offset = syscon_camerrx_offset;
 
-	dev->res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+	cal->res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
 						"cal_top");
-	dev->base = devm_ioremap_resource(&pdev->dev, dev->res);
-	if (IS_ERR(dev->base))
-		return PTR_ERR(dev->base);
+	cal->base = devm_ioremap_resource(&pdev->dev, cal->res);
+	if (IS_ERR(cal->base))
+		return PTR_ERR(cal->base);
 
-	cal_dbg(1, dev, "ioresource %s at %pa - %pa\n",
-		dev->res->name, &dev->res->start, &dev->res->end);
+	cal_dbg(1, cal, "ioresource %s at %pa - %pa\n",
+		cal->res->name, &cal->res->start, &cal->res->end);
 
 	irq = platform_get_irq(pdev, 0);
-	cal_dbg(1, dev, "got irq# %d\n", irq);
+	cal_dbg(1, cal, "got irq# %d\n", irq);
 	ret = devm_request_irq(&pdev->dev, irq, cal_irq, 0, CAL_MODULE_NAME,
-			       dev);
+			       cal);
 	if (ret)
 		return ret;
 
-	platform_set_drvdata(pdev, dev);
+	platform_set_drvdata(pdev, cal);
 
-	dev->cc[0] = cc_create(dev, 0);
-	if (IS_ERR(dev->cc[0]))
-		return PTR_ERR(dev->cc[0]);
+	cal->cc[0] = cc_create(cal, 0);
+	if (IS_ERR(cal->cc[0]))
+		return PTR_ERR(cal->cc[0]);
 
-	if (cal_data_get_num_csi2_phy(dev) > 1) {
-		dev->cc[1] = cc_create(dev, 1);
-		if (IS_ERR(dev->cc[1]))
-			return PTR_ERR(dev->cc[1]);
+	if (cal_data_get_num_csi2_phy(cal) > 1) {
+		cal->cc[1] = cc_create(cal, 1);
+		if (IS_ERR(cal->cc[1]))
+			return PTR_ERR(cal->cc[1]);
 	} else {
-		dev->cc[1] = NULL;
+		cal->cc[1] = NULL;
 	}
 
-	dev->ctx[0] = NULL;
-	dev->ctx[1] = NULL;
+	cal->ctx[0] = NULL;
+	cal->ctx[1] = NULL;
 
-	dev->ctx[0] = cal_create_instance(dev, 0);
-	if (cal_data_get_num_csi2_phy(dev) > 1)
-		dev->ctx[1] = cal_create_instance(dev, 1);
-	if (!dev->ctx[0] && !dev->ctx[1]) {
-		cal_err(dev, "Neither port is configured, no point in staying up\n");
+	cal->ctx[0] = cal_create_instance(cal, 0);
+	if (cal_data_get_num_csi2_phy(cal) > 1)
+		cal->ctx[1] = cal_create_instance(cal, 1);
+	if (!cal->ctx[0] && !cal->ctx[1]) {
+		cal_err(cal, "Neither port is configured, no point in staying up\n");
 		return -ENODEV;
 	}
 
@@ -2338,7 +2342,7 @@ static int cal_probe(struct platform_device *pdev)
 		goto runtime_disable;
 
 	/* Just check we can actually access the module */
-	cal_get_hwinfo(dev);
+	cal_get_hwinfo(cal);
 
 	pm_runtime_put_sync(&pdev->dev);
 
@@ -2349,7 +2353,7 @@ static int cal_probe(struct platform_device *pdev)
 
 	pm_runtime_disable(&pdev->dev);
 	for (i = 0; i < CAL_NUM_CONTEXT; i++) {
-		ctx = dev->ctx[i];
+		ctx = cal->ctx[i];
 		if (ctx) {
 			v4l2_async_notifier_unregister(&ctx->notifier);
 			v4l2_async_notifier_cleanup(&ctx->notifier);
@@ -2363,16 +2367,16 @@ static int cal_probe(struct platform_device *pdev)
 
 static int cal_remove(struct platform_device *pdev)
 {
-	struct cal_dev *dev = platform_get_drvdata(pdev);
+	struct cal_dev *cal = platform_get_drvdata(pdev);
 	struct cal_ctx *ctx;
 	unsigned int i;
 
-	cal_dbg(1, dev, "Removing %s\n", CAL_MODULE_NAME);
+	cal_dbg(1, cal, "Removing %s\n", CAL_MODULE_NAME);
 
 	pm_runtime_get_sync(&pdev->dev);
 
 	for (i = 0; i < CAL_NUM_CONTEXT; i++) {
-		ctx = dev->ctx[i];
+		ctx = cal->ctx[i];
 		if (ctx) {
 			ctx_dbg(1, ctx, "unregistering %s\n",
 				video_device_node_name(&ctx->vdev));
@@ -2395,15 +2399,15 @@ static int cal_remove(struct platform_device *pdev)
 
 static int cal_runtime_resume(struct device *dev)
 {
-	struct cal_dev *caldev = dev_get_drvdata(dev);
+	struct cal_dev *cal = dev_get_drvdata(dev);
 
-	if (caldev->data->flags & DRA72_CAL_PRE_ES2_LDO_DISABLE) {
+	if (cal->data->flags & DRA72_CAL_PRE_ES2_LDO_DISABLE) {
 		/*
 		 * Apply errata on both port everytime we (re-)enable
 		 * the clock
 		 */
-		i913_errata(caldev, 0);
-		i913_errata(caldev, 1);
+		i913_errata(cal, 0);
+		i913_errata(cal, 1);
 	}
 
 	return 0;
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 027/107] media: ti-vpe: cal: Name all cal_camerarx pointers consistently
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (25 preceding siblings ...)
  2020-06-14 23:58 ` [PATCH v1 026/107] media: ti-vpe: cal: Name all cal_dev pointers consistently Laurent Pinchart
@ 2020-06-14 23:58 ` Laurent Pinchart
  2020-06-16 10:58   ` Tomi Valkeinen
  2020-06-18 14:06   ` Benoit Parrot
  2020-06-14 23:58 ` [PATCH v1 028/107] media: ti-vpe: cal: Remove internal phy structure from cal_camerarx Laurent Pinchart
                   ` (81 subsequent siblings)
  108 siblings, 2 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:58 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

Name all variables htat point to a cal_camerax instance 'phy' instead of
'cc'. The name 'cc' refers to Camera Core, but is not commonly used in
the driver or in datasheets.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 102 ++++++++++++++--------------
 1 file changed, 51 insertions(+), 51 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index 615e9d97e61f..8864a00a22b0 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -312,7 +312,8 @@ static const struct cal_data am654_cal_data = {
  * the CAMERARX instances. Instances of struct cal_dev are named cal through the
  * driver.
  *
- * The cal_camerarx structure represents one CAMERARX instance.
+ * The cal_camerarx structure represents one CAMERARX instance. Instances of
+ * cal_camerarx are named phy through the driver.
  *
  * The cal_ctx structure represents the combination of one CSI-2 context, one
  * processing context and one DMA context. Instance of struct cal_ctx are named
@@ -344,7 +345,7 @@ struct cal_dev {
 	u32			syscon_camerrx_offset;
 
 	/* Camera Core Module handle */
-	struct cal_camerarx	*cc[CAL_NUM_CSI2_PORTS];
+	struct cal_camerarx	*phy[CAL_NUM_CSI2_PORTS];
 
 	struct cal_ctx		*ctx[CAL_NUM_CONTEXT];
 };
@@ -361,7 +362,7 @@ struct cal_ctx {
 	struct v4l2_fwnode_endpoint	endpoint;
 
 	struct cal_dev		*cal;
-	struct cal_camerarx	*cc;
+	struct cal_camerarx	*phy;
 
 	/* v4l2_ioctl mutex */
 	struct mutex		mutex;
@@ -468,7 +469,7 @@ static u32 cal_data_get_num_csi2_phy(struct cal_dev *cal)
 }
 
 static int cal_camerarx_regmap_init(struct cal_dev *cal,
-				    struct cal_camerarx *cc,
+				    struct cal_camerarx *phy,
 				    unsigned int idx)
 {
 	const struct cal_camerarx_data *phy_data;
@@ -490,12 +491,12 @@ static int cal_camerarx_regmap_init(struct cal_dev *cal,
 		 * Here we update the reg offset with the
 		 * value found in DT
 		 */
-		cc->phy.fields[i] = devm_regmap_field_alloc(&cal->pdev->dev,
-							    cal->syscon_camerrx,
-							    field);
-		if (IS_ERR(cc->phy.fields[i])) {
+		phy->phy.fields[i] = devm_regmap_field_alloc(&cal->pdev->dev,
+							     cal->syscon_camerrx,
+							     field);
+		if (IS_ERR(phy->phy.fields[i])) {
 			cal_err(cal, "Unable to allocate regmap fields\n");
-			return PTR_ERR(cc->phy.fields[i]);
+			return PTR_ERR(phy->phy.fields[i]);
 		}
 	}
 
@@ -539,25 +540,25 @@ static struct regmap *cal_get_camerarx_regmap(struct cal_dev *cal)
 static void camerarx_phy_enable(struct cal_ctx *ctx)
 {
 	u32 phy_id = ctx->csi2_port;
-	struct cal_camerarx *cc = ctx->cal->cc[phy_id];
+	struct cal_camerarx *phy = ctx->cal->phy[phy_id];
 	u32 max_lanes;
 
-	regmap_field_write(cc->phy.fields[F_CAMMODE], 0);
+	regmap_field_write(phy->phy.fields[F_CAMMODE], 0);
 	/* Always enable all lanes at the phy control level */
 	max_lanes = (1 << cal_data_get_phy_max_lanes(ctx)) - 1;
-	regmap_field_write(cc->phy.fields[F_LANEENABLE], max_lanes);
+	regmap_field_write(phy->phy.fields[F_LANEENABLE], max_lanes);
 	/* F_CSI_MODE is not present on every architecture */
-	if (cc->phy.fields[F_CSI_MODE])
-		regmap_field_write(cc->phy.fields[F_CSI_MODE], 1);
-	regmap_field_write(cc->phy.fields[F_CTRLCLKEN], 1);
+	if (phy->phy.fields[F_CSI_MODE])
+		regmap_field_write(phy->phy.fields[F_CSI_MODE], 1);
+	regmap_field_write(phy->phy.fields[F_CTRLCLKEN], 1);
 }
 
 static void camerarx_phy_disable(struct cal_ctx *ctx)
 {
 	u32 phy_id = ctx->csi2_port;
-	struct cal_camerarx *cc = ctx->cal->cc[phy_id];
+	struct cal_camerarx *phy = ctx->cal->phy[phy_id];
 
-	regmap_field_write(cc->phy.fields[F_CTRLCLKEN], 0);
+	regmap_field_write(phy->phy.fields[F_CTRLCLKEN], 0);
 }
 
 /*
@@ -566,32 +567,31 @@ static void camerarx_phy_disable(struct cal_ctx *ctx)
 static struct cal_camerarx *cc_create(struct cal_dev *cal, unsigned int core)
 {
 	struct platform_device *pdev = cal->pdev;
-	struct cal_camerarx *cc;
+	struct cal_camerarx *phy;
 	int ret;
 
-	cc = devm_kzalloc(&pdev->dev, sizeof(*cc), GFP_KERNEL);
-	if (!cc)
+	phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL);
+	if (!phy)
 		return ERR_PTR(-ENOMEM);
 
-	cc->res = platform_get_resource_byname(pdev,
-					       IORESOURCE_MEM,
-					       (core == 0) ?
+	phy->res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+						(core == 0) ?
 						"cal_rx_core0" :
 						"cal_rx_core1");
-	cc->base = devm_ioremap_resource(&pdev->dev, cc->res);
-	if (IS_ERR(cc->base)) {
+	phy->base = devm_ioremap_resource(&pdev->dev, phy->res);
+	if (IS_ERR(phy->base)) {
 		cal_err(cal, "failed to ioremap\n");
-		return ERR_CAST(cc->base);
+		return ERR_CAST(phy->base);
 	}
 
 	cal_dbg(1, cal, "ioresource %s at %pa - %pa\n",
-		cc->res->name, &cc->res->start, &cc->res->end);
+		phy->res->name, &phy->res->start, &phy->res->end);
 
-	ret = cal_camerarx_regmap_init(cal, cc, core);
+	ret = cal_camerarx_regmap_init(cal, phy, core);
 	if (ret)
 		return ERR_PTR(ret);
 
-	return cc;
+	return phy;
 }
 
 /*
@@ -632,12 +632,12 @@ static void cal_get_hwinfo(struct cal_dev *cal)
  */
 static void i913_errata(struct cal_dev *cal, unsigned int port)
 {
-	u32 reg10 = reg_read(cal->cc[port], CAL_CSI2_PHY_REG10);
+	u32 reg10 = reg_read(cal->phy[port], CAL_CSI2_PHY_REG10);
 
 	set_field(&reg10, 1, CAL_CSI2_PHY_REG10_I933_LDO_DISABLE_MASK);
 
 	cal_dbg(1, cal, "CSI2_%d_REG10 = 0x%08x\n", port, reg10);
-	reg_write(cal->cc[port], CAL_CSI2_PHY_REG10, reg10);
+	reg_write(cal->phy[port], CAL_CSI2_PHY_REG10, reg10);
 }
 
 static void cal_quickdump_regs(struct cal_dev *cal)
@@ -649,19 +649,19 @@ static void cal_quickdump_regs(struct cal_dev *cal)
 
 	if (cal->ctx[0]) {
 		cal_info(cal, "CSI2 Core 0 Registers @ %pa:\n",
-			 &cal->ctx[0]->cc->res->start);
+			 &cal->ctx[0]->phy->res->start);
 		print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 4,
-			       (__force const void *)cal->ctx[0]->cc->base,
-			       resource_size(cal->ctx[0]->cc->res),
+			       (__force const void *)cal->ctx[0]->phy->base,
+			       resource_size(cal->ctx[0]->phy->res),
 			       false);
 	}
 
 	if (cal->ctx[1]) {
 		cal_info(cal, "CSI2 Core 1 Registers @ %pa:\n",
-			 &cal->ctx[1]->cc->res->start);
+			 &cal->ctx[1]->phy->res->start);
 		print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 4,
-			       (__force const void *)cal->ctx[1]->cc->base,
-			       resource_size(cal->ctx[1]->cc->res),
+			       (__force const void *)cal->ctx[1]->phy->base,
+			       resource_size(cal->ctx[1]->phy->res),
 			       false);
 	}
 }
@@ -781,23 +781,23 @@ static void csi2_phy_config(struct cal_ctx *ctx)
 	ths_settle = (105 * csi2_ddrclk_khz / 1000000) + 4;
 	ctx_dbg(1, ctx, "ths_settle: %d (0x%02x)\n", ths_settle, ths_settle);
 
-	reg0 = reg_read(ctx->cc, CAL_CSI2_PHY_REG0);
+	reg0 = reg_read(ctx->phy, CAL_CSI2_PHY_REG0);
 	set_field(&reg0, CAL_CSI2_PHY_REG0_HSCLOCKCONFIG_DISABLE,
 		  CAL_CSI2_PHY_REG0_HSCLOCKCONFIG_MASK);
 	set_field(&reg0, ths_term, CAL_CSI2_PHY_REG0_THS_TERM_MASK);
 	set_field(&reg0, ths_settle, CAL_CSI2_PHY_REG0_THS_SETTLE_MASK);
 
 	ctx_dbg(1, ctx, "CSI2_%d_REG0 = 0x%08x\n", ctx->csi2_port, reg0);
-	reg_write(ctx->cc, CAL_CSI2_PHY_REG0, reg0);
+	reg_write(ctx->phy, CAL_CSI2_PHY_REG0, reg0);
 
-	reg1 = reg_read(ctx->cc, CAL_CSI2_PHY_REG1);
+	reg1 = reg_read(ctx->phy, CAL_CSI2_PHY_REG1);
 	set_field(&reg1, TCLK_TERM, CAL_CSI2_PHY_REG1_TCLK_TERM_MASK);
 	set_field(&reg1, 0xb8, CAL_CSI2_PHY_REG1_DPHY_HS_SYNC_PATTERN_MASK);
 	set_field(&reg1, TCLK_MISS, CAL_CSI2_PHY_REG1_CTRLCLK_DIV_FACTOR_MASK);
 	set_field(&reg1, TCLK_SETTLE, CAL_CSI2_PHY_REG1_TCLK_SETTLE_MASK);
 
 	ctx_dbg(1, ctx, "CSI2_%d_REG1 = 0x%08x\n", ctx->csi2_port, reg1);
-	reg_write(ctx->cc, CAL_CSI2_PHY_REG1, reg1);
+	reg_write(ctx->phy, CAL_CSI2_PHY_REG1, reg1);
 }
 
 static void csi2_phy_init(struct cal_ctx *ctx)
@@ -834,7 +834,7 @@ static void csi2_phy_init(struct cal_ctx *ctx)
 		reg_read(ctx->cal, CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port)));
 
 	/* Dummy read to allow SCP reset to complete */
-	reg_read(ctx->cc, CAL_CSI2_PHY_REG0);
+	reg_read(ctx->phy, CAL_CSI2_PHY_REG0);
 
 	/* 3.A. Program Phy Timing Parameters */
 	csi2_phy_config(ctx);
@@ -926,7 +926,7 @@ static void csi2_wait_for_phy(struct cal_ctx *ctx)
 	csi2_wait_stop_state(ctx);
 
 	ctx_dbg(1, ctx, "CSI2_%d_REG1 = 0x%08x (Bit(31,28) should be set!)\n",
-		ctx->csi2_port, reg_read(ctx->cc, CAL_CSI2_PHY_REG1));
+		ctx->csi2_port, reg_read(ctx->phy, CAL_CSI2_PHY_REG1));
 }
 
 static void csi2_phy_deinit(struct cal_ctx *ctx)
@@ -2187,7 +2187,7 @@ static struct cal_ctx *cal_create_instance(struct cal_dev *cal, int inst)
 	ctx->v4l2_dev.ctrl_handler = hdl;
 
 	/* Make sure Camera Core H/W register area is available */
-	ctx->cc = cal->cc[inst];
+	ctx->phy = cal->phy[inst];
 
 	/* Store the instance id */
 	ctx->csi2_port = inst;
@@ -2310,16 +2310,16 @@ static int cal_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, cal);
 
-	cal->cc[0] = cc_create(cal, 0);
-	if (IS_ERR(cal->cc[0]))
-		return PTR_ERR(cal->cc[0]);
+	cal->phy[0] = cc_create(cal, 0);
+	if (IS_ERR(cal->phy[0]))
+		return PTR_ERR(cal->phy[0]);
 
 	if (cal_data_get_num_csi2_phy(cal) > 1) {
-		cal->cc[1] = cc_create(cal, 1);
-		if (IS_ERR(cal->cc[1]))
-			return PTR_ERR(cal->cc[1]);
+		cal->phy[1] = cc_create(cal, 1);
+		if (IS_ERR(cal->phy[1]))
+			return PTR_ERR(cal->phy[1]);
 	} else {
-		cal->cc[1] = NULL;
+		cal->phy[1] = NULL;
 	}
 
 	cal->ctx[0] = NULL;
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 028/107] media: ti-vpe: cal: Remove internal phy structure from cal_camerarx
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (26 preceding siblings ...)
  2020-06-14 23:58 ` [PATCH v1 027/107] media: ti-vpe: cal: Name all cal_camerarx " Laurent Pinchart
@ 2020-06-14 23:58 ` Laurent Pinchart
  2020-06-18 14:08   ` Benoit Parrot
  2020-06-14 23:58 ` [PATCH v1 029/107] media: ti-vpe: cal: Store instance ID and cal pointer in cal_camerarx Laurent Pinchart
                   ` (80 subsequent siblings)
  108 siblings, 1 reply; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:58 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

The cal_camerarx structure describes the PHY, there's no need for an
internal structure named phy. Removed that level of indirection.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 27 ++++++++++++---------------
 1 file changed, 12 insertions(+), 15 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index 8864a00a22b0..9b905b61148f 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -324,10 +324,7 @@ struct cal_camerarx {
 	void __iomem		*base;
 	struct resource		*res;
 	struct platform_device	*pdev;
-
-	struct {
-		struct regmap_field *fields[F_MAX_FIELDS];
-	} phy;
+	struct regmap_field	*fields[F_MAX_FIELDS];
 };
 
 struct cal_dev {
@@ -491,12 +488,12 @@ static int cal_camerarx_regmap_init(struct cal_dev *cal,
 		 * Here we update the reg offset with the
 		 * value found in DT
 		 */
-		phy->phy.fields[i] = devm_regmap_field_alloc(&cal->pdev->dev,
-							     cal->syscon_camerrx,
-							     field);
-		if (IS_ERR(phy->phy.fields[i])) {
+		phy->fields[i] = devm_regmap_field_alloc(&cal->pdev->dev,
+							 cal->syscon_camerrx,
+							 field);
+		if (IS_ERR(phy->fields[i])) {
 			cal_err(cal, "Unable to allocate regmap fields\n");
-			return PTR_ERR(phy->phy.fields[i]);
+			return PTR_ERR(phy->fields[i]);
 		}
 	}
 
@@ -543,14 +540,14 @@ static void camerarx_phy_enable(struct cal_ctx *ctx)
 	struct cal_camerarx *phy = ctx->cal->phy[phy_id];
 	u32 max_lanes;
 
-	regmap_field_write(phy->phy.fields[F_CAMMODE], 0);
+	regmap_field_write(phy->fields[F_CAMMODE], 0);
 	/* Always enable all lanes at the phy control level */
 	max_lanes = (1 << cal_data_get_phy_max_lanes(ctx)) - 1;
-	regmap_field_write(phy->phy.fields[F_LANEENABLE], max_lanes);
+	regmap_field_write(phy->fields[F_LANEENABLE], max_lanes);
 	/* F_CSI_MODE is not present on every architecture */
-	if (phy->phy.fields[F_CSI_MODE])
-		regmap_field_write(phy->phy.fields[F_CSI_MODE], 1);
-	regmap_field_write(phy->phy.fields[F_CTRLCLKEN], 1);
+	if (phy->fields[F_CSI_MODE])
+		regmap_field_write(phy->fields[F_CSI_MODE], 1);
+	regmap_field_write(phy->fields[F_CTRLCLKEN], 1);
 }
 
 static void camerarx_phy_disable(struct cal_ctx *ctx)
@@ -558,7 +555,7 @@ static void camerarx_phy_disable(struct cal_ctx *ctx)
 	u32 phy_id = ctx->csi2_port;
 	struct cal_camerarx *phy = ctx->cal->phy[phy_id];
 
-	regmap_field_write(phy->phy.fields[F_CTRLCLKEN], 0);
+	regmap_field_write(phy->fields[F_CTRLCLKEN], 0);
 }
 
 /*
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 029/107] media: ti-vpe: cal: Store instance ID and cal pointer in cal_camerarx
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (27 preceding siblings ...)
  2020-06-14 23:58 ` [PATCH v1 028/107] media: ti-vpe: cal: Remove internal phy structure from cal_camerarx Laurent Pinchart
@ 2020-06-14 23:58 ` Laurent Pinchart
  2020-06-14 23:58 ` [PATCH v1 030/107] media: ti-vpe: cal: Use dev_* print macros Laurent Pinchart
                   ` (79 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:58 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

Store a pointer to the cal_dev and the cal_camerarx instance number in
the cal_camerarx structure. This prepares for passing a cal_camerarx
pointer instead of a cal_ctx pointer to multiple functions that deal
with the CAMERARX.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 18 ++++++++++++------
 1 file changed, 12 insertions(+), 6 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index 9b905b61148f..e40967751aa4 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -325,6 +325,9 @@ struct cal_camerarx {
 	struct resource		*res;
 	struct platform_device	*pdev;
 	struct regmap_field	*fields[F_MAX_FIELDS];
+
+	struct cal_dev		*cal;
+	unsigned int		instance;
 };
 
 struct cal_dev {
@@ -466,8 +469,7 @@ static u32 cal_data_get_num_csi2_phy(struct cal_dev *cal)
 }
 
 static int cal_camerarx_regmap_init(struct cal_dev *cal,
-				    struct cal_camerarx *phy,
-				    unsigned int idx)
+				    struct cal_camerarx *phy)
 {
 	const struct cal_camerarx_data *phy_data;
 	unsigned int i;
@@ -475,7 +477,7 @@ static int cal_camerarx_regmap_init(struct cal_dev *cal,
 	if (!cal->data)
 		return -EINVAL;
 
-	phy_data = &cal->data->camerarx[idx];
+	phy_data = &cal->data->camerarx[phy->instance];
 
 	for (i = 0; i < F_MAX_FIELDS; i++) {
 		struct reg_field field = {
@@ -561,7 +563,8 @@ static void camerarx_phy_disable(struct cal_ctx *ctx)
 /*
  * Camera Instance access block
  */
-static struct cal_camerarx *cc_create(struct cal_dev *cal, unsigned int core)
+static struct cal_camerarx *cc_create(struct cal_dev *cal,
+				      unsigned int instance)
 {
 	struct platform_device *pdev = cal->pdev;
 	struct cal_camerarx *phy;
@@ -571,8 +574,11 @@ static struct cal_camerarx *cc_create(struct cal_dev *cal, unsigned int core)
 	if (!phy)
 		return ERR_PTR(-ENOMEM);
 
+	phy->cal = cal;
+	phy->instance = instance;
+
 	phy->res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
-						(core == 0) ?
+						(instance == 0) ?
 						"cal_rx_core0" :
 						"cal_rx_core1");
 	phy->base = devm_ioremap_resource(&pdev->dev, phy->res);
@@ -584,7 +590,7 @@ static struct cal_camerarx *cc_create(struct cal_dev *cal, unsigned int core)
 	cal_dbg(1, cal, "ioresource %s at %pa - %pa\n",
 		phy->res->name, &phy->res->start, &phy->res->end);
 
-	ret = cal_camerarx_regmap_init(cal, phy, core);
+	ret = cal_camerarx_regmap_init(cal, phy);
 	if (ret)
 		return ERR_PTR(ret);
 
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 030/107] media: ti-vpe: cal: Use dev_* print macros
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (28 preceding siblings ...)
  2020-06-14 23:58 ` [PATCH v1 029/107] media: ti-vpe: cal: Store instance ID and cal pointer in cal_camerarx Laurent Pinchart
@ 2020-06-14 23:58 ` Laurent Pinchart
  2020-06-18 18:28   ` Benoit Parrot
  2020-06-14 23:58 ` [PATCH v1 031/107] media: ti-vpe: cal: Add print macros for the cal_camerarx instances Laurent Pinchart
                   ` (78 subsequent siblings)
  108 siblings, 1 reply; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:58 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

Use the dev_* print macros instead of the v4l2_* print macros. This
prepares for a common print infrastructure that will also support the
cal_camerarx instances.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 17 ++++++++++-------
 1 file changed, 10 insertions(+), 7 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index e40967751aa4..e62089832713 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -53,19 +53,22 @@ static unsigned debug;
 module_param(debug, uint, 0644);
 MODULE_PARM_DESC(debug, "activates debug info");
 
-#define cal_dbg(level, cal, fmt, arg...)	\
-		v4l2_dbg(level, debug, &cal->v4l2_dev, fmt, ##arg)
+#define cal_dbg(level, cal, fmt, arg...)				\
+	do {								\
+		if (debug >= (level))					\
+			dev_dbg(&(cal)->pdev->dev, fmt, ##arg);		\
+	} while (0)
 #define cal_info(cal, fmt, arg...)	\
-		v4l2_info(&cal->v4l2_dev, fmt, ##arg)
+	dev_info(&(cal)->pdev->dev, fmt, ##arg)
 #define cal_err(cal, fmt, arg...)	\
-		v4l2_err(&cal->v4l2_dev, fmt, ##arg)
+	dev_err(&(cal)->pdev->dev, fmt, ##arg)
 
 #define ctx_dbg(level, ctx, fmt, arg...)	\
-		v4l2_dbg(level, debug, &ctx->v4l2_dev, fmt, ##arg)
+	cal_dbg(level, (ctx)->cal, "ctx%u: " fmt, (ctx)->csi2_port, ##arg)
 #define ctx_info(ctx, fmt, arg...)	\
-		v4l2_info(&ctx->v4l2_dev, fmt, ##arg)
+	cal_info((ctx)->cal, "ctx%u: " fmt, (ctx)->csi2_port, ##arg)
 #define ctx_err(ctx, fmt, arg...)	\
-		v4l2_err(&ctx->v4l2_dev, fmt, ##arg)
+	cal_err((ctx)->cal, "ctx%u: " fmt, (ctx)->csi2_port, ##arg)
 
 #define CAL_NUM_CONTEXT 2
 
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 031/107] media: ti-vpe: cal: Add print macros for the cal_camerarx instances
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (29 preceding siblings ...)
  2020-06-14 23:58 ` [PATCH v1 030/107] media: ti-vpe: cal: Use dev_* print macros Laurent Pinchart
@ 2020-06-14 23:58 ` Laurent Pinchart
  2020-06-14 23:58 ` [PATCH v1 032/107] media: ti-vpe: cal: Store sensor-related data in cal_camerarx Laurent Pinchart
                   ` (77 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:58 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

Prepare for passing the cal_camerarx pointer instead of the cal_ctx
pointer to CAMERARX-related functions by adding print macros for
cal_camerarx.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index e62089832713..dd85efa89bcb 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -70,6 +70,13 @@ MODULE_PARM_DESC(debug, "activates debug info");
 #define ctx_err(ctx, fmt, arg...)	\
 	cal_err((ctx)->cal, "ctx%u: " fmt, (ctx)->csi2_port, ##arg)
 
+#define phy_dbg(level, phy, fmt, arg...)	\
+	cal_dbg(level, (phy)->cal, "phy%u: " fmt, (phy)->instance, ##arg)
+#define phy_info(phy, fmt, arg...)	\
+	cal_info((phy)->cal, "phy%u: " fmt, (phy)->instance, ##arg)
+#define phy_err(phy, fmt, arg...)	\
+	cal_err((phy)->cal, "phy%u: " fmt, (phy)->instance, ##arg)
+
 #define CAL_NUM_CONTEXT 2
 
 #define reg_read(dev, offset) ioread32(dev->base + offset)
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 032/107] media: ti-vpe: cal: Store sensor-related data in cal_camerarx
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (30 preceding siblings ...)
  2020-06-14 23:58 ` [PATCH v1 031/107] media: ti-vpe: cal: Add print macros for the cal_camerarx instances Laurent Pinchart
@ 2020-06-14 23:58 ` Laurent Pinchart
  2020-06-14 23:58 ` [PATCH v1 033/107] media: ti-vpe: cal: Create consistent naming for CAMERARX functions Laurent Pinchart
                   ` (76 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:58 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

The sensor is connected to the CAMERARX. Store its pointer, as well as
the sensor pixel rate and the endpoint, in the cal_camerarx. This
prepares for decoupling the cal_camerarx and cal_ctx.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 59 +++++++++++++++--------------
 1 file changed, 30 insertions(+), 29 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index dd85efa89bcb..30323d61d8e9 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -338,6 +338,10 @@ struct cal_camerarx {
 
 	struct cal_dev		*cal;
 	unsigned int		instance;
+
+	struct v4l2_fwnode_endpoint	endpoint;
+	struct v4l2_subdev	*sensor;
+	unsigned int		external_rate;
 };
 
 struct cal_dev {
@@ -368,8 +372,6 @@ struct cal_ctx {
 	struct v4l2_ctrl_handler ctrl_handler;
 	struct video_device	vdev;
 	struct v4l2_async_notifier notifier;
-	struct v4l2_subdev	*sensor;
-	struct v4l2_fwnode_endpoint	endpoint;
 
 	struct cal_dev		*cal;
 	struct cal_camerarx	*phy;
@@ -393,7 +395,6 @@ struct cal_ctx {
 	unsigned int		num_active_fmt;
 
 	unsigned int		sequence;
-	unsigned int		external_rate;
 	struct vb2_queue	vb_vidq;
 	unsigned int		csi2_port;
 	unsigned int		cport;
@@ -586,6 +587,7 @@ static struct cal_camerarx *cc_create(struct cal_dev *cal,
 
 	phy->cal = cal;
 	phy->instance = instance;
+	phy->external_rate = 192000000;
 
 	phy->res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
 						(instance == 0) ?
@@ -777,12 +779,12 @@ static void csi2_phy_config(struct cal_ctx *ctx)
 	unsigned int ths_term, ths_settle;
 	unsigned int csi2_ddrclk_khz;
 	struct v4l2_fwnode_bus_mipi_csi2 *mipi_csi2 =
-			&ctx->endpoint.bus.mipi_csi2;
+			&ctx->phy->endpoint.bus.mipi_csi2;
 	u32 num_lanes = mipi_csi2->num_data_lanes;
 
 	/* DPHY timing configuration */
 	/* CSI-2 is DDR and we only count used lanes. */
-	csi2_ddrclk_khz = ctx->external_rate / 1000
+	csi2_ddrclk_khz = ctx->phy->external_rate / 1000
 		/ (2 * num_lanes) * ctx->fmt->bpp;
 	ctx_dbg(1, ctx, "csi2_ddrclk_khz: %d\n", csi2_ddrclk_khz);
 
@@ -977,7 +979,7 @@ static void csi2_lane_config(struct cal_ctx *ctx)
 	u32 lane_mask = CAL_CSI2_COMPLEXIO_CFG_CLOCK_POSITION_MASK;
 	u32 polarity_mask = CAL_CSI2_COMPLEXIO_CFG_CLOCK_POL_MASK;
 	struct v4l2_fwnode_bus_mipi_csi2 *mipi_csi2 =
-		&ctx->endpoint.bus.mipi_csi2;
+		&ctx->phy->endpoint.bus.mipi_csi2;
 	int lane;
 
 	set_field(&val, mipi_csi2->clock_lane + 1, lane_mask);
@@ -1148,22 +1150,22 @@ static void cal_wr_dma_addr(struct cal_ctx *ctx, unsigned int dmaaddr)
 	reg_write(ctx->cal, CAL_WR_DMA_ADDR(ctx->csi2_port), dmaaddr);
 }
 
-static int cal_get_external_info(struct cal_ctx *ctx)
+static int cal_get_external_info(struct cal_camerarx *phy)
 {
 	struct v4l2_ctrl *ctrl;
 
-	if (!ctx->sensor)
+	if (!phy->sensor)
 		return -ENODEV;
 
-	ctrl = v4l2_ctrl_find(ctx->sensor->ctrl_handler, V4L2_CID_PIXEL_RATE);
+	ctrl = v4l2_ctrl_find(phy->sensor->ctrl_handler, V4L2_CID_PIXEL_RATE);
 	if (!ctrl) {
-		ctx_err(ctx, "no pixel rate control in subdev: %s\n",
-			ctx->sensor->name);
+		phy_err(phy, "no pixel rate control in subdev: %s\n",
+			phy->sensor->name);
 		return -EPIPE;
 	}
 
-	ctx->external_rate = v4l2_ctrl_g_ctrl_int64(ctrl);
-	ctx_dbg(3, ctx, "sensor Pixel Rate: %d\n", ctx->external_rate);
+	phy->external_rate = v4l2_ctrl_g_ctrl_int64(ctrl);
+	phy_dbg(3, phy, "sensor Pixel Rate: %u\n", phy->external_rate);
 
 	return 0;
 }
@@ -1313,7 +1315,7 @@ static int __subdev_get_format(struct cal_ctx *ctx,
 	sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
 	sd_fmt.pad = 0;
 
-	ret = v4l2_subdev_call(ctx->sensor, pad, get_fmt, NULL, &sd_fmt);
+	ret = v4l2_subdev_call(ctx->phy->sensor, pad, get_fmt, NULL, &sd_fmt);
 	if (ret)
 		return ret;
 
@@ -1336,7 +1338,7 @@ static int __subdev_set_format(struct cal_ctx *ctx,
 	sd_fmt.pad = 0;
 	*mbus_fmt = *fmt;
 
-	ret = v4l2_subdev_call(ctx->sensor, pad, set_fmt, NULL, &sd_fmt);
+	ret = v4l2_subdev_call(ctx->phy->sensor, pad, set_fmt, NULL, &sd_fmt);
 	if (ret)
 		return ret;
 
@@ -1417,7 +1419,7 @@ static int cal_try_fmt_vid_cap(struct file *file, void *priv,
 	fse.code = fmt->code;
 	fse.which = V4L2_SUBDEV_FORMAT_ACTIVE;
 	for (fse.index = 0; ; fse.index++) {
-		ret = v4l2_subdev_call(ctx->sensor, pad, enum_frame_size,
+		ret = v4l2_subdev_call(ctx->phy->sensor, pad, enum_frame_size,
 				       NULL, &fse);
 		if (ret)
 			break;
@@ -1515,7 +1517,8 @@ static int cal_enum_framesizes(struct file *file, void *fh,
 	fse.code = fmt->code;
 	fse.which = V4L2_SUBDEV_FORMAT_ACTIVE;
 
-	ret = v4l2_subdev_call(ctx->sensor, pad, enum_frame_size, NULL, &fse);
+	ret = v4l2_subdev_call(ctx->phy->sensor, pad, enum_frame_size, NULL,
+			       &fse);
 	if (ret)
 		return ret;
 
@@ -1571,7 +1574,7 @@ static int cal_enum_frameintervals(struct file *file, void *priv,
 		return -EINVAL;
 
 	fie.code = fmt->code;
-	ret = v4l2_subdev_call(ctx->sensor, pad, enum_frame_interval,
+	ret = v4l2_subdev_call(ctx->phy->sensor, pad, enum_frame_interval,
 			       NULL, &fie);
 	if (ret)
 		return ret;
@@ -1669,11 +1672,11 @@ static int cal_start_streaming(struct vb2_queue *vq, unsigned int count)
 	addr = vb2_dma_contig_plane_dma_addr(&ctx->cur_frm->vb.vb2_buf, 0);
 	ctx->sequence = 0;
 
-	ret = cal_get_external_info(ctx);
+	ret = cal_get_external_info(ctx->phy);
 	if (ret < 0)
 		goto err;
 
-	ret = v4l2_subdev_call(ctx->sensor, core, s_power, 1);
+	ret = v4l2_subdev_call(ctx->phy->sensor, core, s_power, 1);
 	if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV) {
 		ctx_err(ctx, "power on failed in subdev\n");
 		goto err;
@@ -1690,9 +1693,9 @@ static int cal_start_streaming(struct vb2_queue *vq, unsigned int count)
 	enable_irqs(ctx);
 	csi2_phy_init(ctx);
 
-	ret = v4l2_subdev_call(ctx->sensor, video, s_stream, 1);
+	ret = v4l2_subdev_call(ctx->phy->sensor, video, s_stream, 1);
 	if (ret) {
-		v4l2_subdev_call(ctx->sensor, core, s_power, 0);
+		v4l2_subdev_call(ctx->phy->sensor, core, s_power, 0);
 		ctx_err(ctx, "stream on failed in subdev\n");
 		pm_runtime_put_sync(&ctx->cal->pdev->dev);
 		goto err;
@@ -1749,10 +1752,10 @@ static void cal_stop_streaming(struct vb2_queue *vq)
 	disable_irqs(ctx);
 	csi2_phy_deinit(ctx);
 
-	if (v4l2_subdev_call(ctx->sensor, video, s_stream, 0))
+	if (v4l2_subdev_call(ctx->phy->sensor, video, s_stream, 0))
 		ctx_err(ctx, "stream off failed in subdev\n");
 
-	ret = v4l2_subdev_call(ctx->sensor, core, s_power, 0);
+	ret = v4l2_subdev_call(ctx->phy->sensor, core, s_power, 0);
 	if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV)
 		ctx_err(ctx, "power off failed in subdev\n");
 
@@ -1843,8 +1846,6 @@ static int cal_complete_ctx(struct cal_ctx *ctx)
 	struct vb2_queue *q;
 	int ret;
 
-	ctx->external_rate = 192000000;
-
 	/* initialize locks */
 	spin_lock_init(&ctx->slock);
 	mutex_init(&ctx->mutex);
@@ -1900,13 +1901,13 @@ static int cal_async_bound(struct v4l2_async_notifier *notifier,
 	unsigned int i, j, k;
 	int ret = 0;
 
-	if (ctx->sensor) {
+	if (ctx->phy->sensor) {
 		ctx_info(ctx, "Rejecting subdev %s (Already set!!)",
 			 subdev->name);
 		return 0;
 	}
 
-	ctx->sensor = subdev;
+	ctx->phy->sensor = subdev;
 	ctx_dbg(1, ctx, "Using sensor %s for capture\n", subdev->name);
 
 	/* Enumerate sub device formats and enable all matching local formats */
@@ -2059,7 +2060,7 @@ static int of_cal_create_instance(struct cal_ctx *ctx, int inst)
 
 	parent = pdev->dev.of_node;
 
-	endpoint = &ctx->endpoint;
+	endpoint = &ctx->phy->endpoint;
 
 	ep_node = NULL;
 	port = NULL;
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 033/107] media: ti-vpe: cal: Create consistent naming for CAMERARX functions
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (31 preceding siblings ...)
  2020-06-14 23:58 ` [PATCH v1 032/107] media: ti-vpe: cal: Store sensor-related data in cal_camerarx Laurent Pinchart
@ 2020-06-14 23:58 ` Laurent Pinchart
  2020-06-14 23:58 ` [PATCH v1 034/107] media: ti-vpe: cal: Group CAMERARX-related functions together Laurent Pinchart
                   ` (75 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:58 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

Rename all functions related to CAMERARX with a cal_camerarx_ prefix,
and pass them a cal_camerarx pointer. This performs most of the
decoupling of the CAMERARX from the context.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 243 ++++++++++++++--------------
 1 file changed, 119 insertions(+), 124 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index 30323d61d8e9..73254ebf8f9b 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -467,11 +467,9 @@ static inline void set_field(u32 *valp, u32 field, u32 mask)
 	*valp = val;
 }
 
-static u32 cal_data_get_phy_max_lanes(struct cal_ctx *ctx)
+static u32 cal_camerarx_max_lanes(struct cal_camerarx *phy)
 {
-	u32 phy_id = ctx->csi2_port;
-
-	return ctx->cal->data->camerarx[phy_id].num_lanes;
+	return phy->cal->data->camerarx[phy->instance].num_lanes;
 }
 
 static u32 cal_data_get_num_csi2_phy(struct cal_dev *cal)
@@ -547,15 +545,13 @@ static struct regmap *cal_get_camerarx_regmap(struct cal_dev *cal)
 /*
  * Control Module CAMERARX block access
  */
-static void camerarx_phy_enable(struct cal_ctx *ctx)
+static void cal_camerarx_enable(struct cal_camerarx *phy)
 {
-	u32 phy_id = ctx->csi2_port;
-	struct cal_camerarx *phy = ctx->cal->phy[phy_id];
 	u32 max_lanes;
 
 	regmap_field_write(phy->fields[F_CAMMODE], 0);
 	/* Always enable all lanes at the phy control level */
-	max_lanes = (1 << cal_data_get_phy_max_lanes(ctx)) - 1;
+	max_lanes = (1 << cal_camerarx_max_lanes(phy)) - 1;
 	regmap_field_write(phy->fields[F_LANEENABLE], max_lanes);
 	/* F_CSI_MODE is not present on every architecture */
 	if (phy->fields[F_CSI_MODE])
@@ -563,19 +559,16 @@ static void camerarx_phy_enable(struct cal_ctx *ctx)
 	regmap_field_write(phy->fields[F_CTRLCLKEN], 1);
 }
 
-static void camerarx_phy_disable(struct cal_ctx *ctx)
+static void cal_camerarx_disable(struct cal_camerarx *phy)
 {
-	u32 phy_id = ctx->csi2_port;
-	struct cal_camerarx *phy = ctx->cal->phy[phy_id];
-
 	regmap_field_write(phy->fields[F_CTRLCLKEN], 0);
 }
 
 /*
  * Camera Instance access block
  */
-static struct cal_camerarx *cc_create(struct cal_dev *cal,
-				      unsigned int instance)
+static struct cal_camerarx *cal_camerarx_create(struct cal_dev *cal,
+						unsigned int instance)
 {
 	struct platform_device *pdev = cal->pdev;
 	struct cal_camerarx *phy;
@@ -645,14 +638,14 @@ static void cal_get_hwinfo(struct cal_dev *cal)
  *		Core 0:  0x4845 B828 = 0x0000 0040
  *		Core 1:  0x4845 B928 = 0x0000 0040
  */
-static void i913_errata(struct cal_dev *cal, unsigned int port)
+static void cal_camerarx_i913_errata(struct cal_camerarx *phy)
 {
-	u32 reg10 = reg_read(cal->phy[port], CAL_CSI2_PHY_REG10);
+	u32 reg10 = reg_read(phy, CAL_CSI2_PHY_REG10);
 
 	set_field(&reg10, 1, CAL_CSI2_PHY_REG10_I933_LDO_DISABLE_MASK);
 
-	cal_dbg(1, cal, "CSI2_%d_REG10 = 0x%08x\n", port, reg10);
-	reg_write(cal->phy[port], CAL_CSI2_PHY_REG10, reg10);
+	phy_dbg(1, phy, "CSI2_%d_REG10 = 0x%08x\n", phy->instance, reg10);
+	reg_write(phy, CAL_CSI2_PHY_REG10, reg10);
 }
 
 static void cal_quickdump_regs(struct cal_dev *cal)
@@ -684,7 +677,7 @@ static void cal_quickdump_regs(struct cal_dev *cal)
 /*
  * Enable the expected IRQ sources
  */
-static void enable_irqs(struct cal_ctx *ctx)
+static void cal_camerarx_enable_irqs(struct cal_camerarx *phy)
 {
 	u32 val;
 
@@ -695,49 +688,49 @@ static void enable_irqs(struct cal_ctx *ctx)
 		CAL_CSI2_COMPLEXIO_IRQ_ECC_NO_CORRECTION_MASK;
 
 	/* Enable CIO error irqs */
-	reg_write(ctx->cal, CAL_HL_IRQENABLE_SET(0),
-		  CAL_HL_IRQ_CIO_MASK(ctx->csi2_port));
-	reg_write(ctx->cal, CAL_CSI2_COMPLEXIO_IRQENABLE(ctx->csi2_port),
+	reg_write(phy->cal, CAL_HL_IRQENABLE_SET(0),
+		  CAL_HL_IRQ_CIO_MASK(phy->instance));
+	reg_write(phy->cal, CAL_CSI2_COMPLEXIO_IRQENABLE(phy->instance),
 		  cio_err_mask);
 
 	/* Always enable OCPO error */
-	reg_write(ctx->cal, CAL_HL_IRQENABLE_SET(0), CAL_HL_IRQ_OCPO_ERR_MASK);
+	reg_write(phy->cal, CAL_HL_IRQENABLE_SET(0), CAL_HL_IRQ_OCPO_ERR_MASK);
 
 	/* Enable IRQ_WDMA_END 0/1 */
 	val = 0;
-	set_field(&val, 1, CAL_HL_IRQ_MASK(ctx->csi2_port));
-	reg_write(ctx->cal, CAL_HL_IRQENABLE_SET(1), val);
+	set_field(&val, 1, CAL_HL_IRQ_MASK(phy->instance));
+	reg_write(phy->cal, CAL_HL_IRQENABLE_SET(1), val);
 	/* Enable IRQ_WDMA_START 0/1 */
 	val = 0;
-	set_field(&val, 1, CAL_HL_IRQ_MASK(ctx->csi2_port));
-	reg_write(ctx->cal, CAL_HL_IRQENABLE_SET(2), val);
+	set_field(&val, 1, CAL_HL_IRQ_MASK(phy->instance));
+	reg_write(phy->cal, CAL_HL_IRQENABLE_SET(2), val);
 	/* Todo: Add VC_IRQ and CSI2_COMPLEXIO_IRQ handling */
-	reg_write(ctx->cal, CAL_CSI2_VC_IRQENABLE(0), 0xFF000000);
+	reg_write(phy->cal, CAL_CSI2_VC_IRQENABLE(0), 0xFF000000);
 }
 
-static void disable_irqs(struct cal_ctx *ctx)
+static void cal_camerarx_disable_irqs(struct cal_camerarx *phy)
 {
 	u32 val;
 
 	/* Disable CIO error irqs */
-	reg_write(ctx->cal, CAL_HL_IRQENABLE_CLR(0),
-		  CAL_HL_IRQ_CIO_MASK(ctx->csi2_port));
-	reg_write(ctx->cal, CAL_CSI2_COMPLEXIO_IRQENABLE(ctx->csi2_port),
+	reg_write(phy->cal, CAL_HL_IRQENABLE_CLR(0),
+		  CAL_HL_IRQ_CIO_MASK(phy->instance));
+	reg_write(phy->cal, CAL_CSI2_COMPLEXIO_IRQENABLE(phy->instance),
 		  0);
 
 	/* Disable IRQ_WDMA_END 0/1 */
 	val = 0;
-	set_field(&val, 1, CAL_HL_IRQ_MASK(ctx->csi2_port));
-	reg_write(ctx->cal, CAL_HL_IRQENABLE_CLR(1), val);
+	set_field(&val, 1, CAL_HL_IRQ_MASK(phy->instance));
+	reg_write(phy->cal, CAL_HL_IRQENABLE_CLR(1), val);
 	/* Disable IRQ_WDMA_START 0/1 */
 	val = 0;
-	set_field(&val, 1, CAL_HL_IRQ_MASK(ctx->csi2_port));
-	reg_write(ctx->cal, CAL_HL_IRQENABLE_CLR(2), val);
+	set_field(&val, 1, CAL_HL_IRQ_MASK(phy->instance));
+	reg_write(phy->cal, CAL_HL_IRQENABLE_CLR(2), val);
 	/* Todo: Add VC_IRQ and CSI2_COMPLEXIO_IRQ handling */
-	reg_write(ctx->cal, CAL_CSI2_VC_IRQENABLE(0), 0);
+	reg_write(phy->cal, CAL_CSI2_VC_IRQENABLE(0), 0);
 }
 
-static void csi2_cio_power(struct cal_ctx *ctx, bool enable)
+static void cal_camerarx_power(struct cal_camerarx *phy, bool enable)
 {
 	u32 target_state;
 	unsigned int i;
@@ -745,14 +738,14 @@ static void csi2_cio_power(struct cal_ctx *ctx, bool enable)
 	target_state = enable ? CAL_CSI2_COMPLEXIO_CFG_PWR_CMD_STATE_ON :
 		       CAL_CSI2_COMPLEXIO_CFG_PWR_CMD_STATE_OFF;
 
-	reg_write_field(ctx->cal, CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port),
+	reg_write_field(phy->cal, CAL_CSI2_COMPLEXIO_CFG(phy->instance),
 			target_state, CAL_CSI2_COMPLEXIO_CFG_PWR_CMD_MASK);
 
 	for (i = 0; i < 10; i++) {
 		u32 current_state;
 
-		current_state = reg_read_field(ctx->cal,
-					       CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port),
+		current_state = reg_read_field(phy->cal,
+					       CAL_CSI2_COMPLEXIO_CFG(phy->instance),
 					       CAL_CSI2_COMPLEXIO_CFG_PWR_STATUS_MASK);
 
 		if (current_state == target_state)
@@ -762,7 +755,7 @@ static void csi2_cio_power(struct cal_ctx *ctx, bool enable)
 	}
 
 	if (i == 10)
-		ctx_err(ctx, "Failed to power %s complexio\n",
+		phy_err(phy, "Failed to power %s complexio\n",
 			enable ? "up" : "down");
 }
 
@@ -773,49 +766,51 @@ static void csi2_cio_power(struct cal_ctx *ctx, bool enable)
 #define TCLK_MISS	1
 #define TCLK_SETTLE	14
 
-static void csi2_phy_config(struct cal_ctx *ctx)
+static void cal_camerarx_config(struct cal_camerarx *phy,
+				const struct cal_fmt *fmt)
 {
 	unsigned int reg0, reg1;
 	unsigned int ths_term, ths_settle;
 	unsigned int csi2_ddrclk_khz;
 	struct v4l2_fwnode_bus_mipi_csi2 *mipi_csi2 =
-			&ctx->phy->endpoint.bus.mipi_csi2;
+			&phy->endpoint.bus.mipi_csi2;
 	u32 num_lanes = mipi_csi2->num_data_lanes;
 
 	/* DPHY timing configuration */
 	/* CSI-2 is DDR and we only count used lanes. */
-	csi2_ddrclk_khz = ctx->phy->external_rate / 1000
-		/ (2 * num_lanes) * ctx->fmt->bpp;
-	ctx_dbg(1, ctx, "csi2_ddrclk_khz: %d\n", csi2_ddrclk_khz);
+	csi2_ddrclk_khz = phy->external_rate / 1000
+		/ (2 * num_lanes) * fmt->bpp;
+	phy_dbg(1, phy, "csi2_ddrclk_khz: %d\n", csi2_ddrclk_khz);
 
 	/* THS_TERM: Programmed value = floor(20 ns/DDRClk period) */
 	ths_term = 20 * csi2_ddrclk_khz / 1000000;
-	ctx_dbg(1, ctx, "ths_term: %d (0x%02x)\n", ths_term, ths_term);
+	phy_dbg(1, phy, "ths_term: %d (0x%02x)\n", ths_term, ths_term);
 
 	/* THS_SETTLE: Programmed value = floor(105 ns/DDRClk period) + 4 */
 	ths_settle = (105 * csi2_ddrclk_khz / 1000000) + 4;
-	ctx_dbg(1, ctx, "ths_settle: %d (0x%02x)\n", ths_settle, ths_settle);
+	phy_dbg(1, phy, "ths_settle: %d (0x%02x)\n", ths_settle, ths_settle);
 
-	reg0 = reg_read(ctx->phy, CAL_CSI2_PHY_REG0);
+	reg0 = reg_read(phy, CAL_CSI2_PHY_REG0);
 	set_field(&reg0, CAL_CSI2_PHY_REG0_HSCLOCKCONFIG_DISABLE,
 		  CAL_CSI2_PHY_REG0_HSCLOCKCONFIG_MASK);
 	set_field(&reg0, ths_term, CAL_CSI2_PHY_REG0_THS_TERM_MASK);
 	set_field(&reg0, ths_settle, CAL_CSI2_PHY_REG0_THS_SETTLE_MASK);
 
-	ctx_dbg(1, ctx, "CSI2_%d_REG0 = 0x%08x\n", ctx->csi2_port, reg0);
-	reg_write(ctx->phy, CAL_CSI2_PHY_REG0, reg0);
+	phy_dbg(1, phy, "CSI2_%d_REG0 = 0x%08x\n", phy->instance, reg0);
+	reg_write(phy, CAL_CSI2_PHY_REG0, reg0);
 
-	reg1 = reg_read(ctx->phy, CAL_CSI2_PHY_REG1);
+	reg1 = reg_read(phy, CAL_CSI2_PHY_REG1);
 	set_field(&reg1, TCLK_TERM, CAL_CSI2_PHY_REG1_TCLK_TERM_MASK);
 	set_field(&reg1, 0xb8, CAL_CSI2_PHY_REG1_DPHY_HS_SYNC_PATTERN_MASK);
 	set_field(&reg1, TCLK_MISS, CAL_CSI2_PHY_REG1_CTRLCLK_DIV_FACTOR_MASK);
 	set_field(&reg1, TCLK_SETTLE, CAL_CSI2_PHY_REG1_TCLK_SETTLE_MASK);
 
-	ctx_dbg(1, ctx, "CSI2_%d_REG1 = 0x%08x\n", ctx->csi2_port, reg1);
-	reg_write(ctx->phy, CAL_CSI2_PHY_REG1, reg1);
+	phy_dbg(1, phy, "CSI2_%d_REG1 = 0x%08x\n", phy->instance, reg1);
+	reg_write(phy, CAL_CSI2_PHY_REG1, reg1);
 }
 
-static void csi2_phy_init(struct cal_ctx *ctx)
+static void cal_camerarx_init(struct cal_camerarx *phy,
+			      const struct cal_fmt *fmt)
 {
 	u32 val;
 	u32 sscounter;
@@ -838,21 +833,21 @@ static void csi2_phy_init(struct cal_ctx *ctx)
 	 */
 
 	/* 1. Configure D-PHY mode and enable required lanes */
-	camerarx_phy_enable(ctx);
+	cal_camerarx_enable(phy);
 
 	/* 2. Reset complex IO - Do not wait for reset completion */
-	reg_write_field(ctx->cal, CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port),
+	reg_write_field(phy->cal, CAL_CSI2_COMPLEXIO_CFG(phy->instance),
 			CAL_CSI2_COMPLEXIO_CFG_RESET_CTRL_OPERATIONAL,
 			CAL_CSI2_COMPLEXIO_CFG_RESET_CTRL_MASK);
-	ctx_dbg(3, ctx, "CAL_CSI2_COMPLEXIO_CFG(%d) = 0x%08x De-assert Complex IO Reset\n",
-		ctx->csi2_port,
-		reg_read(ctx->cal, CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port)));
+	phy_dbg(3, phy, "CAL_CSI2_COMPLEXIO_CFG(%d) = 0x%08x De-assert Complex IO Reset\n",
+		phy->instance,
+		reg_read(phy->cal, CAL_CSI2_COMPLEXIO_CFG(phy->instance)));
 
 	/* Dummy read to allow SCP reset to complete */
-	reg_read(ctx->phy, CAL_CSI2_PHY_REG0);
+	reg_read(phy, CAL_CSI2_PHY_REG0);
 
 	/* 3.A. Program Phy Timing Parameters */
-	csi2_phy_config(ctx);
+	cal_camerarx_config(phy, fmt);
 
 	/* 3.B. Program Stop States */
 	/*
@@ -863,67 +858,67 @@ static void csi2_phy_init(struct cal_ctx *ctx)
 	 * Stop-state-timeout must be more than 100us as per CSI2 spec, so we
 	 * calculate a timeout that's 100us (rounding up).
 	 */
-	sscounter = DIV_ROUND_UP(clk_get_rate(ctx->cal->fclk), 10000 *  16 * 4);
+	sscounter = DIV_ROUND_UP(clk_get_rate(phy->cal->fclk), 10000 *  16 * 4);
 
-	val = reg_read(ctx->cal, CAL_CSI2_TIMING(ctx->csi2_port));
+	val = reg_read(phy->cal, CAL_CSI2_TIMING(phy->instance));
 	set_field(&val, 1, CAL_CSI2_TIMING_STOP_STATE_X16_IO1_MASK);
 	set_field(&val, 1, CAL_CSI2_TIMING_STOP_STATE_X4_IO1_MASK);
 	set_field(&val, sscounter, CAL_CSI2_TIMING_STOP_STATE_COUNTER_IO1_MASK);
-	reg_write(ctx->cal, CAL_CSI2_TIMING(ctx->csi2_port), val);
-	ctx_dbg(3, ctx, "CAL_CSI2_TIMING(%d) = 0x%08x Stop States\n",
-		ctx->csi2_port,
-		reg_read(ctx->cal, CAL_CSI2_TIMING(ctx->csi2_port)));
+	reg_write(phy->cal, CAL_CSI2_TIMING(phy->instance), val);
+	phy_dbg(3, phy, "CAL_CSI2_TIMING(%d) = 0x%08x Stop States\n",
+		phy->instance,
+		reg_read(phy->cal, CAL_CSI2_TIMING(phy->instance)));
 
 	/* 4. Force FORCERXMODE */
-	reg_write_field(ctx->cal, CAL_CSI2_TIMING(ctx->csi2_port),
+	reg_write_field(phy->cal, CAL_CSI2_TIMING(phy->instance),
 			1, CAL_CSI2_TIMING_FORCE_RX_MODE_IO1_MASK);
-	ctx_dbg(3, ctx, "CAL_CSI2_TIMING(%d) = 0x%08x Force RXMODE\n",
-		ctx->csi2_port,
-		reg_read(ctx->cal, CAL_CSI2_TIMING(ctx->csi2_port)));
+	phy_dbg(3, phy, "CAL_CSI2_TIMING(%d) = 0x%08x Force RXMODE\n",
+		phy->instance,
+		reg_read(phy->cal, CAL_CSI2_TIMING(phy->instance)));
 
 	/* E. Power up the PHY using the complex IO */
-	csi2_cio_power(ctx, true);
+	cal_camerarx_power(phy, true);
 }
 
-static void csi2_wait_complexio_reset(struct cal_ctx *ctx)
+static void cal_camerarx_wait_reset(struct cal_camerarx *phy)
 {
 	unsigned long timeout;
 
 	timeout = jiffies + msecs_to_jiffies(750);
 	while (time_before(jiffies, timeout)) {
-		if (reg_read_field(ctx->cal,
-				   CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port),
+		if (reg_read_field(phy->cal,
+				   CAL_CSI2_COMPLEXIO_CFG(phy->instance),
 				   CAL_CSI2_COMPLEXIO_CFG_RESET_DONE_MASK) ==
 		    CAL_CSI2_COMPLEXIO_CFG_RESET_DONE_RESETCOMPLETED)
 			break;
 		usleep_range(500, 5000);
 	}
 
-	if (reg_read_field(ctx->cal, CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port),
+	if (reg_read_field(phy->cal, CAL_CSI2_COMPLEXIO_CFG(phy->instance),
 			   CAL_CSI2_COMPLEXIO_CFG_RESET_DONE_MASK) !=
 			   CAL_CSI2_COMPLEXIO_CFG_RESET_DONE_RESETCOMPLETED)
-		ctx_err(ctx, "Timeout waiting for Complex IO reset done\n");
+		phy_err(phy, "Timeout waiting for Complex IO reset done\n");
 }
 
-static void csi2_wait_stop_state(struct cal_ctx *ctx)
+static void cal_camerarx_wait_stop_state(struct cal_camerarx *phy)
 {
 	unsigned long timeout;
 
 	timeout = jiffies + msecs_to_jiffies(750);
 	while (time_before(jiffies, timeout)) {
-		if (reg_read_field(ctx->cal,
-				   CAL_CSI2_TIMING(ctx->csi2_port),
+		if (reg_read_field(phy->cal,
+				   CAL_CSI2_TIMING(phy->instance),
 				   CAL_CSI2_TIMING_FORCE_RX_MODE_IO1_MASK) == 0)
 			break;
 		usleep_range(500, 5000);
 	}
 
-	if (reg_read_field(ctx->cal, CAL_CSI2_TIMING(ctx->csi2_port),
+	if (reg_read_field(phy->cal, CAL_CSI2_TIMING(phy->instance),
 			   CAL_CSI2_TIMING_FORCE_RX_MODE_IO1_MASK) != 0)
-		ctx_err(ctx, "Timeout waiting for stop state\n");
+		phy_err(phy, "Timeout waiting for stop state\n");
 }
 
-static void csi2_wait_for_phy(struct cal_ctx *ctx)
+static void cal_camerarx_wait_ready(struct cal_camerarx *phy)
 {
 	/* Steps
 	 *  2. Wait for completion of reset
@@ -935,51 +930,51 @@ static void csi2_wait_for_phy(struct cal_ctx *ctx)
 	 */
 
 	/* 2. Wait for reset completion */
-	csi2_wait_complexio_reset(ctx);
+	cal_camerarx_wait_reset(phy);
 
 	/* 4. G. Wait for all enabled lane to reach stop state */
-	csi2_wait_stop_state(ctx);
+	cal_camerarx_wait_stop_state(phy);
 
-	ctx_dbg(1, ctx, "CSI2_%d_REG1 = 0x%08x (Bit(31,28) should be set!)\n",
-		ctx->csi2_port, reg_read(ctx->phy, CAL_CSI2_PHY_REG1));
+	phy_dbg(1, phy, "CSI2_%d_REG1 = 0x%08x (Bit(31,28) should be set!)\n",
+		phy->instance, reg_read(phy, CAL_CSI2_PHY_REG1));
 }
 
-static void csi2_phy_deinit(struct cal_ctx *ctx)
+static void cal_camerarx_deinit(struct cal_camerarx *phy)
 {
 	unsigned int i;
 
-	csi2_cio_power(ctx, false);
+	cal_camerarx_power(phy, false);
 
 	/* Assert Comple IO Reset */
-	reg_write_field(ctx->cal, CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port),
+	reg_write_field(phy->cal, CAL_CSI2_COMPLEXIO_CFG(phy->instance),
 			CAL_CSI2_COMPLEXIO_CFG_RESET_CTRL,
 			CAL_CSI2_COMPLEXIO_CFG_RESET_CTRL_MASK);
 
 	/* Wait for power down completion */
 	for (i = 0; i < 10; i++) {
-		if (reg_read_field(ctx->cal,
-				   CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port),
+		if (reg_read_field(phy->cal,
+				   CAL_CSI2_COMPLEXIO_CFG(phy->instance),
 				   CAL_CSI2_COMPLEXIO_CFG_RESET_DONE_MASK) ==
 		    CAL_CSI2_COMPLEXIO_CFG_RESET_DONE_RESETONGOING)
 			break;
 		usleep_range(1000, 1100);
 	}
-	ctx_dbg(3, ctx, "CAL_CSI2_COMPLEXIO_CFG(%d) = 0x%08x Complex IO in Reset (%d) %s\n",
-		ctx->csi2_port,
-		reg_read(ctx->cal, CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port)), i,
+	phy_dbg(3, phy, "CAL_CSI2_COMPLEXIO_CFG(%d) = 0x%08x Complex IO in Reset (%d) %s\n",
+		phy->instance,
+		reg_read(phy->cal, CAL_CSI2_COMPLEXIO_CFG(phy->instance)), i,
 		(i >= 10) ? "(timeout)" : "");
 
 	/* Disable the phy */
-	camerarx_phy_disable(ctx);
+	cal_camerarx_disable(phy);
 }
 
-static void csi2_lane_config(struct cal_ctx *ctx)
+static void cal_camerarx_lane_config(struct cal_camerarx *phy)
 {
-	u32 val = reg_read(ctx->cal, CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port));
+	u32 val = reg_read(phy->cal, CAL_CSI2_COMPLEXIO_CFG(phy->instance));
 	u32 lane_mask = CAL_CSI2_COMPLEXIO_CFG_CLOCK_POSITION_MASK;
 	u32 polarity_mask = CAL_CSI2_COMPLEXIO_CFG_CLOCK_POL_MASK;
 	struct v4l2_fwnode_bus_mipi_csi2 *mipi_csi2 =
-		&ctx->phy->endpoint.bus.mipi_csi2;
+		&phy->endpoint.bus.mipi_csi2;
 	int lane;
 
 	set_field(&val, mipi_csi2->clock_lane + 1, lane_mask);
@@ -996,21 +991,21 @@ static void csi2_lane_config(struct cal_ctx *ctx)
 			  polarity_mask);
 	}
 
-	reg_write(ctx->cal, CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port), val);
-	ctx_dbg(3, ctx, "CAL_CSI2_COMPLEXIO_CFG(%d) = 0x%08x\n",
-		ctx->csi2_port, val);
+	reg_write(phy->cal, CAL_CSI2_COMPLEXIO_CFG(phy->instance), val);
+	phy_dbg(3, phy, "CAL_CSI2_COMPLEXIO_CFG(%d) = 0x%08x\n",
+		phy->instance, val);
 }
 
-static void csi2_ppi_enable(struct cal_ctx *ctx)
+static void cal_camerarx_ppi_enable(struct cal_camerarx *phy)
 {
-	reg_write(ctx->cal, CAL_CSI2_PPI_CTRL(ctx->csi2_port), BIT(3));
-	reg_write_field(ctx->cal, CAL_CSI2_PPI_CTRL(ctx->csi2_port),
+	reg_write(phy->cal, CAL_CSI2_PPI_CTRL(phy->instance), BIT(3));
+	reg_write_field(phy->cal, CAL_CSI2_PPI_CTRL(phy->instance),
 			1, CAL_CSI2_PPI_CTRL_IF_EN_MASK);
 }
 
-static void csi2_ppi_disable(struct cal_ctx *ctx)
+static void cal_camerarx_ppi_disable(struct cal_camerarx *phy)
 {
-	reg_write_field(ctx->cal, CAL_CSI2_PPI_CTRL(ctx->csi2_port),
+	reg_write_field(phy->cal, CAL_CSI2_PPI_CTRL(phy->instance),
 			0, CAL_CSI2_PPI_CTRL_IF_EN_MASK);
 }
 
@@ -1150,7 +1145,7 @@ static void cal_wr_dma_addr(struct cal_ctx *ctx, unsigned int dmaaddr)
 	reg_write(ctx->cal, CAL_WR_DMA_ADDR(ctx->csi2_port), dmaaddr);
 }
 
-static int cal_get_external_info(struct cal_camerarx *phy)
+static int cal_camerarx_get_external_info(struct cal_camerarx *phy)
 {
 	struct v4l2_ctrl *ctrl;
 
@@ -1672,7 +1667,7 @@ static int cal_start_streaming(struct vb2_queue *vq, unsigned int count)
 	addr = vb2_dma_contig_plane_dma_addr(&ctx->cur_frm->vb.vb2_buf, 0);
 	ctx->sequence = 0;
 
-	ret = cal_get_external_info(ctx->phy);
+	ret = cal_camerarx_get_external_info(ctx->phy);
 	if (ret < 0)
 		goto err;
 
@@ -1688,10 +1683,10 @@ static int cal_start_streaming(struct vb2_queue *vq, unsigned int count)
 	pix_proc_config(ctx);
 	cal_wr_dma_config(ctx, ctx->v_fmt.fmt.pix.bytesperline,
 			  ctx->v_fmt.fmt.pix.height);
-	csi2_lane_config(ctx);
+	cal_camerarx_lane_config(ctx->phy);
 
-	enable_irqs(ctx);
-	csi2_phy_init(ctx);
+	cal_camerarx_enable_irqs(ctx->phy);
+	cal_camerarx_init(ctx->phy, ctx->fmt);
 
 	ret = v4l2_subdev_call(ctx->phy->sensor, video, s_stream, 1);
 	if (ret) {
@@ -1701,9 +1696,9 @@ static int cal_start_streaming(struct vb2_queue *vq, unsigned int count)
 		goto err;
 	}
 
-	csi2_wait_for_phy(ctx);
+	cal_camerarx_wait_ready(ctx->phy);
 	cal_wr_dma_addr(ctx, addr);
-	csi2_ppi_enable(ctx);
+	cal_camerarx_ppi_enable(ctx->phy);
 
 	if (debug >= 4)
 		cal_quickdump_regs(ctx->cal);
@@ -1733,7 +1728,7 @@ static void cal_stop_streaming(struct vb2_queue *vq)
 	int ret;
 	bool dma_act;
 
-	csi2_ppi_disable(ctx);
+	cal_camerarx_ppi_disable(ctx->phy);
 
 	/* wait for stream and dma to finish */
 	dma_act = true;
@@ -1749,8 +1744,8 @@ static void cal_stop_streaming(struct vb2_queue *vq)
 	if (dma_act)
 		ctx_err(ctx, "failed to disable dma cleanly\n");
 
-	disable_irqs(ctx);
-	csi2_phy_deinit(ctx);
+	cal_camerarx_disable_irqs(ctx->phy);
+	cal_camerarx_deinit(ctx->phy);
 
 	if (v4l2_subdev_call(ctx->phy->sensor, video, s_stream, 0))
 		ctx_err(ctx, "stream off failed in subdev\n");
@@ -2324,12 +2319,12 @@ static int cal_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, cal);
 
-	cal->phy[0] = cc_create(cal, 0);
+	cal->phy[0] = cal_camerarx_create(cal, 0);
 	if (IS_ERR(cal->phy[0]))
 		return PTR_ERR(cal->phy[0]);
 
 	if (cal_data_get_num_csi2_phy(cal) > 1) {
-		cal->phy[1] = cc_create(cal, 1);
+		cal->phy[1] = cal_camerarx_create(cal, 1);
 		if (IS_ERR(cal->phy[1]))
 			return PTR_ERR(cal->phy[1]);
 	} else {
@@ -2394,7 +2389,7 @@ static int cal_remove(struct platform_device *pdev)
 		if (ctx) {
 			ctx_dbg(1, ctx, "unregistering %s\n",
 				video_device_node_name(&ctx->vdev));
-			camerarx_phy_disable(ctx);
+			cal_camerarx_disable(ctx->phy);
 			v4l2_async_notifier_unregister(&ctx->notifier);
 			v4l2_async_notifier_cleanup(&ctx->notifier);
 			v4l2_ctrl_handler_free(&ctx->ctrl_handler);
@@ -2420,8 +2415,8 @@ static int cal_runtime_resume(struct device *dev)
 		 * Apply errata on both port everytime we (re-)enable
 		 * the clock
 		 */
-		i913_errata(cal, 0);
-		i913_errata(cal, 1);
+		cal_camerarx_i913_errata(cal->phy[0]);
+		cal_camerarx_i913_errata(cal->phy[1]);
 	}
 
 	return 0;
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 034/107] media: ti-vpe: cal: Group CAMERARX-related functions together
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (32 preceding siblings ...)
  2020-06-14 23:58 ` [PATCH v1 033/107] media: ti-vpe: cal: Create consistent naming for CAMERARX functions Laurent Pinchart
@ 2020-06-14 23:58 ` Laurent Pinchart
  2020-06-14 23:58 ` [PATCH v1 035/107] media: ti-vpe: cal: Create consistent naming for context functions Laurent Pinchart
                   ` (74 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:58 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

Group the CAMERARX functions together to make the overall driver
structure easier to navigate. This only moves functions around, no
functional change is included.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 339 ++++++++++++++--------------
 1 file changed, 169 insertions(+), 170 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index 73254ebf8f9b..f995dabbed19 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -467,9 +467,30 @@ static inline void set_field(u32 *valp, u32 field, u32 mask)
 	*valp = val;
 }
 
-static u32 cal_camerarx_max_lanes(struct cal_camerarx *phy)
+static void cal_quickdump_regs(struct cal_dev *cal)
 {
-	return phy->cal->data->camerarx[phy->instance].num_lanes;
+	cal_info(cal, "CAL Registers @ 0x%pa:\n", &cal->res->start);
+	print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 4,
+		       (__force const void *)cal->base,
+		       resource_size(cal->res), false);
+
+	if (cal->ctx[0]) {
+		cal_info(cal, "CSI2 Core 0 Registers @ %pa:\n",
+			 &cal->ctx[0]->phy->res->start);
+		print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 4,
+			       (__force const void *)cal->ctx[0]->phy->base,
+			       resource_size(cal->ctx[0]->phy->res),
+			       false);
+	}
+
+	if (cal->ctx[1]) {
+		cal_info(cal, "CSI2 Core 1 Registers @ %pa:\n",
+			 &cal->ctx[1]->phy->res->start);
+		print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 4,
+			       (__force const void *)cal->ctx[1]->phy->base,
+			       resource_size(cal->ctx[1]->phy->res),
+			       false);
+	}
 }
 
 static u32 cal_data_get_num_csi2_phy(struct cal_dev *cal)
@@ -477,74 +498,16 @@ static u32 cal_data_get_num_csi2_phy(struct cal_dev *cal)
 	return cal->data->num_csi2_phy;
 }
 
-static int cal_camerarx_regmap_init(struct cal_dev *cal,
-				    struct cal_camerarx *phy)
-{
-	const struct cal_camerarx_data *phy_data;
-	unsigned int i;
-
-	if (!cal->data)
-		return -EINVAL;
-
-	phy_data = &cal->data->camerarx[phy->instance];
-
-	for (i = 0; i < F_MAX_FIELDS; i++) {
-		struct reg_field field = {
-			.reg = cal->syscon_camerrx_offset,
-			.lsb = phy_data->fields[i].lsb,
-			.msb = phy_data->fields[i].msb,
-		};
-
-		/*
-		 * Here we update the reg offset with the
-		 * value found in DT
-		 */
-		phy->fields[i] = devm_regmap_field_alloc(&cal->pdev->dev,
-							 cal->syscon_camerrx,
-							 field);
-		if (IS_ERR(phy->fields[i])) {
-			cal_err(cal, "Unable to allocate regmap fields\n");
-			return PTR_ERR(phy->fields[i]);
-		}
-	}
-
-	return 0;
-}
-
-static struct regmap *cal_get_camerarx_regmap(struct cal_dev *cal)
-{
-	struct platform_device *pdev = cal->pdev;
-	struct regmap_config config = { };
-	struct regmap *regmap;
-	void __iomem *base;
-	struct resource *res;
-
-	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
-					   "camerrx_control");
-	base = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(base)) {
-		cal_err(cal, "failed to ioremap\n");
-		return ERR_CAST(base);
-	}
-
-	cal_dbg(1, cal, "ioresource %s at %pa - %pa\n",
-		res->name, &res->start, &res->end);
-
-	config.reg_bits = 32;
-	config.reg_stride = 4;
-	config.val_bits = 32;
-	config.max_register = resource_size(res) - 4;
-
-	regmap = regmap_init_mmio(NULL, base, &config);
-	if (IS_ERR(regmap))
-		pr_err("regmap init failed\n");
-
-	return regmap;
-}
-
-/*
- * Control Module CAMERARX block access
+/* ------------------------------------------------------------------
+ *	CAMERARX Management
+ * ------------------------------------------------------------------
  */
+
+static u32 cal_camerarx_max_lanes(struct cal_camerarx *phy)
+{
+	return phy->cal->data->camerarx[phy->instance].num_lanes;
+}
+
 static void cal_camerarx_enable(struct cal_camerarx *phy)
 {
 	u32 max_lanes;
@@ -564,61 +527,6 @@ static void cal_camerarx_disable(struct cal_camerarx *phy)
 	regmap_field_write(phy->fields[F_CTRLCLKEN], 0);
 }
 
-/*
- * Camera Instance access block
- */
-static struct cal_camerarx *cal_camerarx_create(struct cal_dev *cal,
-						unsigned int instance)
-{
-	struct platform_device *pdev = cal->pdev;
-	struct cal_camerarx *phy;
-	int ret;
-
-	phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL);
-	if (!phy)
-		return ERR_PTR(-ENOMEM);
-
-	phy->cal = cal;
-	phy->instance = instance;
-	phy->external_rate = 192000000;
-
-	phy->res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
-						(instance == 0) ?
-						"cal_rx_core0" :
-						"cal_rx_core1");
-	phy->base = devm_ioremap_resource(&pdev->dev, phy->res);
-	if (IS_ERR(phy->base)) {
-		cal_err(cal, "failed to ioremap\n");
-		return ERR_CAST(phy->base);
-	}
-
-	cal_dbg(1, cal, "ioresource %s at %pa - %pa\n",
-		phy->res->name, &phy->res->start, &phy->res->end);
-
-	ret = cal_camerarx_regmap_init(cal, phy);
-	if (ret)
-		return ERR_PTR(ret);
-
-	return phy;
-}
-
-/*
- * Get Revision and HW info
- */
-static void cal_get_hwinfo(struct cal_dev *cal)
-{
-	u32 revision;
-	u32 hwinfo;
-
-	revision = reg_read(cal, CAL_HL_REVISION);
-	cal_dbg(3, cal, "CAL_HL_REVISION = 0x%08x (expecting 0x40000200)\n",
-		revision);
-
-	hwinfo = reg_read(cal, CAL_HL_HWINFO);
-	cal_dbg(3, cal, "CAL_HL_HWINFO = 0x%08x (expecting 0xA3C90469)\n",
-		hwinfo);
-}
-
 /*
  *   Errata i913: CSI2 LDO Needs to be disabled when module is powered on
  *
@@ -648,32 +556,6 @@ static void cal_camerarx_i913_errata(struct cal_camerarx *phy)
 	reg_write(phy, CAL_CSI2_PHY_REG10, reg10);
 }
 
-static void cal_quickdump_regs(struct cal_dev *cal)
-{
-	cal_info(cal, "CAL Registers @ 0x%pa:\n", &cal->res->start);
-	print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 4,
-		       (__force const void *)cal->base,
-		       resource_size(cal->res), false);
-
-	if (cal->ctx[0]) {
-		cal_info(cal, "CSI2 Core 0 Registers @ %pa:\n",
-			 &cal->ctx[0]->phy->res->start);
-		print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 4,
-			       (__force const void *)cal->ctx[0]->phy->base,
-			       resource_size(cal->ctx[0]->phy->res),
-			       false);
-	}
-
-	if (cal->ctx[1]) {
-		cal_info(cal, "CSI2 Core 1 Registers @ %pa:\n",
-			 &cal->ctx[1]->phy->res->start);
-		print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 4,
-			       (__force const void *)cal->ctx[1]->phy->base,
-			       resource_size(cal->ctx[1]->phy->res),
-			       false);
-	}
-}
-
 /*
  * Enable the expected IRQ sources
  */
@@ -1009,6 +891,126 @@ static void cal_camerarx_ppi_disable(struct cal_camerarx *phy)
 			0, CAL_CSI2_PPI_CTRL_IF_EN_MASK);
 }
 
+static int cal_camerarx_get_external_info(struct cal_camerarx *phy)
+{
+	struct v4l2_ctrl *ctrl;
+
+	if (!phy->sensor)
+		return -ENODEV;
+
+	ctrl = v4l2_ctrl_find(phy->sensor->ctrl_handler, V4L2_CID_PIXEL_RATE);
+	if (!ctrl) {
+		phy_err(phy, "no pixel rate control in subdev: %s\n",
+			phy->sensor->name);
+		return -EPIPE;
+	}
+
+	phy->external_rate = v4l2_ctrl_g_ctrl_int64(ctrl);
+	phy_dbg(3, phy, "sensor Pixel Rate: %u\n", phy->external_rate);
+
+	return 0;
+}
+
+static int cal_camerarx_regmap_init(struct cal_dev *cal,
+				    struct cal_camerarx *phy)
+{
+	const struct cal_camerarx_data *phy_data;
+	unsigned int i;
+
+	if (!cal->data)
+		return -EINVAL;
+
+	phy_data = &cal->data->camerarx[phy->instance];
+
+	for (i = 0; i < F_MAX_FIELDS; i++) {
+		struct reg_field field = {
+			.reg = cal->syscon_camerrx_offset,
+			.lsb = phy_data->fields[i].lsb,
+			.msb = phy_data->fields[i].msb,
+		};
+
+		/*
+		 * Here we update the reg offset with the
+		 * value found in DT
+		 */
+		phy->fields[i] = devm_regmap_field_alloc(&cal->pdev->dev,
+							 cal->syscon_camerrx,
+							 field);
+		if (IS_ERR(phy->fields[i])) {
+			cal_err(cal, "Unable to allocate regmap fields\n");
+			return PTR_ERR(phy->fields[i]);
+		}
+	}
+
+	return 0;
+}
+
+static struct cal_camerarx *cal_camerarx_create(struct cal_dev *cal,
+						unsigned int instance)
+{
+	struct platform_device *pdev = cal->pdev;
+	struct cal_camerarx *phy;
+	int ret;
+
+	phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL);
+	if (!phy)
+		return ERR_PTR(-ENOMEM);
+
+	phy->cal = cal;
+	phy->instance = instance;
+	phy->external_rate = 192000000;
+
+	phy->res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+						(instance == 0) ?
+						"cal_rx_core0" :
+						"cal_rx_core1");
+	phy->base = devm_ioremap_resource(&pdev->dev, phy->res);
+	if (IS_ERR(phy->base)) {
+		cal_err(cal, "failed to ioremap\n");
+		return ERR_CAST(phy->base);
+	}
+
+	cal_dbg(1, cal, "ioresource %s at %pa - %pa\n",
+		phy->res->name, &phy->res->start, &phy->res->end);
+
+	ret = cal_camerarx_regmap_init(cal, phy);
+	if (ret)
+		return ERR_PTR(ret);
+
+	return phy;
+}
+
+static struct regmap *cal_get_camerarx_regmap(struct cal_dev *cal)
+{
+	struct platform_device *pdev = cal->pdev;
+	struct regmap_config config = { };
+	struct regmap *regmap;
+	void __iomem *base;
+	struct resource *res;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+					   "camerrx_control");
+	base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(base)) {
+		cal_err(cal, "failed to ioremap\n");
+		return ERR_CAST(base);
+	}
+
+	cal_dbg(1, cal, "ioresource %s at %pa - %pa\n",
+		res->name, &res->start, &res->end);
+
+	config.reg_bits = 32;
+	config.reg_stride = 4;
+	config.val_bits = 32;
+	config.max_register = resource_size(res) - 4;
+
+	regmap = regmap_init_mmio(NULL, base, &config);
+	if (IS_ERR(regmap))
+		pr_err("regmap init failed\n");
+
+	return regmap;
+}
+
 static void csi2_ctx_config(struct cal_ctx *ctx)
 {
 	u32 val;
@@ -1145,26 +1147,6 @@ static void cal_wr_dma_addr(struct cal_ctx *ctx, unsigned int dmaaddr)
 	reg_write(ctx->cal, CAL_WR_DMA_ADDR(ctx->csi2_port), dmaaddr);
 }
 
-static int cal_camerarx_get_external_info(struct cal_camerarx *phy)
-{
-	struct v4l2_ctrl *ctrl;
-
-	if (!phy->sensor)
-		return -ENODEV;
-
-	ctrl = v4l2_ctrl_find(phy->sensor->ctrl_handler, V4L2_CID_PIXEL_RATE);
-	if (!ctrl) {
-		phy_err(phy, "no pixel rate control in subdev: %s\n",
-			phy->sensor->name);
-		return -EPIPE;
-	}
-
-	phy->external_rate = v4l2_ctrl_g_ctrl_int64(ctrl);
-	phy_dbg(3, phy, "sensor Pixel Rate: %u\n", phy->external_rate);
-
-	return 0;
-}
-
 static inline void cal_schedule_next_buffer(struct cal_ctx *ctx)
 {
 	struct cal_dmaqueue *dma_q = &ctx->vidq;
@@ -2238,6 +2220,23 @@ static const struct of_device_id cal_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, cal_of_match);
 
+/*
+ * Get Revision and HW info
+ */
+static void cal_get_hwinfo(struct cal_dev *cal)
+{
+	u32 revision;
+	u32 hwinfo;
+
+	revision = reg_read(cal, CAL_HL_REVISION);
+	cal_dbg(3, cal, "CAL_HL_REVISION = 0x%08x (expecting 0x40000200)\n",
+		revision);
+
+	hwinfo = reg_read(cal, CAL_HL_HWINFO);
+	cal_dbg(3, cal, "CAL_HL_HWINFO = 0x%08x (expecting 0xA3C90469)\n",
+		hwinfo);
+}
+
 static int cal_probe(struct platform_device *pdev)
 {
 	struct cal_dev *cal;
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 035/107] media: ti-vpe: cal: Create consistent naming for context functions
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (33 preceding siblings ...)
  2020-06-14 23:58 ` [PATCH v1 034/107] media: ti-vpe: cal: Group CAMERARX-related functions together Laurent Pinchart
@ 2020-06-14 23:58 ` Laurent Pinchart
  2020-06-14 23:58 ` [PATCH v1 036/107] media: ti-vpe: cal: Reorganize remaining code in sections Laurent Pinchart
                   ` (73 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:58 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

Rename all functions related to contexts with a cal_ctx_ prefix to
increase readability.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 27 ++++++++++++++++-----------
 1 file changed, 16 insertions(+), 11 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index f995dabbed19..176f616033a1 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -1011,7 +1011,12 @@ static struct regmap *cal_get_camerarx_regmap(struct cal_dev *cal)
 	return regmap;
 }
 
-static void csi2_ctx_config(struct cal_ctx *ctx)
+/* ------------------------------------------------------------------
+ *	Context Management
+ * ------------------------------------------------------------------
+ */
+
+static void cal_ctx_csi2_config(struct cal_ctx *ctx)
 {
 	u32 val;
 
@@ -1037,7 +1042,7 @@ static void csi2_ctx_config(struct cal_ctx *ctx)
 		reg_read(ctx->cal, CAL_CSI2_CTX0(ctx->csi2_port)));
 }
 
-static void pix_proc_config(struct cal_ctx *ctx)
+static void cal_ctx_pix_proc_config(struct cal_ctx *ctx)
 {
 	u32 val, extract, pack;
 
@@ -1088,8 +1093,8 @@ static void pix_proc_config(struct cal_ctx *ctx)
 		reg_read(ctx->cal, CAL_PIX_PROC(ctx->csi2_port)));
 }
 
-static void cal_wr_dma_config(struct cal_ctx *ctx,
-			      unsigned int width, unsigned int height)
+static void cal_ctx_wr_dma_config(struct cal_ctx *ctx,
+				  unsigned int width, unsigned int height)
 {
 	u32 val;
 
@@ -1142,7 +1147,7 @@ static void cal_wr_dma_config(struct cal_ctx *ctx,
 	ctx_dbg(3, ctx, "CAL_CTRL = 0x%08x\n", reg_read(ctx->cal, CAL_CTRL));
 }
 
-static void cal_wr_dma_addr(struct cal_ctx *ctx, unsigned int dmaaddr)
+static void cal_ctx_wr_dma_addr(struct cal_ctx *ctx, unsigned int dmaaddr)
 {
 	reg_write(ctx->cal, CAL_WR_DMA_ADDR(ctx->csi2_port), dmaaddr);
 }
@@ -1158,7 +1163,7 @@ static inline void cal_schedule_next_buffer(struct cal_ctx *ctx)
 	list_del(&buf->list);
 
 	addr = vb2_dma_contig_plane_dma_addr(&buf->vb.vb2_buf, 0);
-	cal_wr_dma_addr(ctx, addr);
+	cal_ctx_wr_dma_addr(ctx, addr);
 }
 
 static inline void cal_process_buffer_complete(struct cal_ctx *ctx)
@@ -1661,10 +1666,10 @@ static int cal_start_streaming(struct vb2_queue *vq, unsigned int count)
 
 	pm_runtime_get_sync(&ctx->cal->pdev->dev);
 
-	csi2_ctx_config(ctx);
-	pix_proc_config(ctx);
-	cal_wr_dma_config(ctx, ctx->v_fmt.fmt.pix.bytesperline,
-			  ctx->v_fmt.fmt.pix.height);
+	cal_ctx_csi2_config(ctx);
+	cal_ctx_pix_proc_config(ctx);
+	cal_ctx_wr_dma_config(ctx, ctx->v_fmt.fmt.pix.bytesperline,
+			      ctx->v_fmt.fmt.pix.height);
 	cal_camerarx_lane_config(ctx->phy);
 
 	cal_camerarx_enable_irqs(ctx->phy);
@@ -1679,7 +1684,7 @@ static int cal_start_streaming(struct vb2_queue *vq, unsigned int count)
 	}
 
 	cal_camerarx_wait_ready(ctx->phy);
-	cal_wr_dma_addr(ctx, addr);
+	cal_ctx_wr_dma_addr(ctx, addr);
 	cal_camerarx_ppi_enable(ctx->phy);
 
 	if (debug >= 4)
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 036/107] media: ti-vpe: cal: Reorganize remaining code in sections
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (34 preceding siblings ...)
  2020-06-14 23:58 ` [PATCH v1 035/107] media: ti-vpe: cal: Create consistent naming for context functions Laurent Pinchart
@ 2020-06-14 23:58 ` Laurent Pinchart
  2020-06-17 10:00   ` Kieran Bingham
  2020-06-14 23:58 ` [PATCH v1 037/107] media: ti-vpe: cal: Rename cal_ctx.csi2_port to cal_ctx.index Laurent Pinchart
                   ` (72 subsequent siblings)
  108 siblings, 1 reply; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:58 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

Increase readability by reorganizing the remaining code in sections. No
functional change is included.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 350 +++++++++++++++-------------
 1 file changed, 187 insertions(+), 163 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index 176f616033a1..6f33853ecdb2 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -37,9 +37,6 @@
 
 #define CAL_MODULE_NAME "cal"
 
-#define MAX_WIDTH_BYTES (8192 * 8)
-#define MAX_HEIGHT_LINES 16383
-
 MODULE_DESCRIPTION("TI CAL driver");
 MODULE_AUTHOR("Benoit Parrot, <bparrot@ti.com>");
 MODULE_LICENSE("GPL v2");
@@ -79,11 +76,11 @@ MODULE_PARM_DESC(debug, "activates debug info");
 
 #define CAL_NUM_CONTEXT 2
 
-#define reg_read(dev, offset) ioread32(dev->base + offset)
-#define reg_write(dev, offset, val) iowrite32(val, dev->base + offset)
+#define MAX_WIDTH_BYTES (8192 * 8)
+#define MAX_HEIGHT_LINES 16383
 
 /* ------------------------------------------------------------------
- *	Basic structures
+ *	Format Handling
  * ------------------------------------------------------------------
  */
 
@@ -204,6 +201,11 @@ static char *fourcc_to_str(u32 fmt)
 	return code;
 }
 
+/* ------------------------------------------------------------------
+ *	Driver Structures
+ * ------------------------------------------------------------------
+ */
+
 /* buffer for one video frame */
 struct cal_buffer {
 	/* common v4l buffer stuff -- must be first */
@@ -239,80 +241,6 @@ struct cal_data {
 	unsigned int flags;
 };
 
-static const struct cal_camerarx_data dra72x_cal_camerarx[] = {
-	{
-		.fields = {
-			[F_CTRLCLKEN] = { 10, 10 },
-			[F_CAMMODE] = { 11, 12 },
-			[F_LANEENABLE] = { 13, 16 },
-			[F_CSI_MODE] = { 17, 17 },
-		},
-		.num_lanes = 4,
-	},
-	{
-		.fields = {
-			[F_CTRLCLKEN] = { 0, 0 },
-			[F_CAMMODE] = { 1, 2 },
-			[F_LANEENABLE] = { 3, 4 },
-			[F_CSI_MODE] = { 5, 5 },
-		},
-		.num_lanes = 2,
-	},
-};
-
-static const struct cal_data dra72x_cal_data = {
-	.camerarx = dra72x_cal_camerarx,
-	.num_csi2_phy = ARRAY_SIZE(dra72x_cal_camerarx),
-};
-
-static const struct cal_data dra72x_es1_cal_data = {
-	.camerarx = dra72x_cal_camerarx,
-	.num_csi2_phy = ARRAY_SIZE(dra72x_cal_camerarx),
-	.flags = DRA72_CAL_PRE_ES2_LDO_DISABLE,
-};
-
-static const struct cal_camerarx_data dra76x_cal_csi_phy[] = {
-	{
-		.fields = {
-			[F_CTRLCLKEN] = { 8, 8 },
-			[F_CAMMODE] = { 9, 10 },
-			[F_CSI_MODE] = { 11, 11 },
-			[F_LANEENABLE] = { 27, 31 },
-		},
-		.num_lanes = 5,
-	},
-	{
-		.fields = {
-			[F_CTRLCLKEN] = { 0, 0 },
-			[F_CAMMODE] = { 1, 2 },
-			[F_CSI_MODE] = { 3, 3 },
-			[F_LANEENABLE] = { 24, 26 },
-		},
-		.num_lanes = 3,
-	},
-};
-
-static const struct cal_data dra76x_cal_data = {
-	.camerarx = dra76x_cal_csi_phy,
-	.num_csi2_phy = ARRAY_SIZE(dra76x_cal_csi_phy),
-};
-
-static const struct cal_camerarx_data am654_cal_csi_phy[] = {
-	{
-		.fields = {
-			[F_CTRLCLKEN] = { 15, 15 },
-			[F_CAMMODE] = { 24, 25 },
-			[F_LANEENABLE] = { 0, 4 },
-		},
-		.num_lanes = 5,
-	},
-};
-
-static const struct cal_data am654_cal_data = {
-	.camerarx = am654_cal_csi_phy,
-	.num_csi2_phy = ARRAY_SIZE(am654_cal_csi_phy),
-};
-
 /*
  * The Camera Adaptation Layer (CAL) module is paired with one or more complex
  * I/O PHYs (CAMERARX). It contains multiple instances of CSI-2, processing and
@@ -408,6 +336,98 @@ struct cal_ctx {
 	bool dma_act;
 };
 
+static inline struct cal_ctx *notifier_to_ctx(struct v4l2_async_notifier *n)
+{
+	return container_of(n, struct cal_ctx, notifier);
+}
+
+/* ------------------------------------------------------------------
+ *	Platform Data
+ * ------------------------------------------------------------------
+ */
+
+static const struct cal_camerarx_data dra72x_cal_camerarx[] = {
+	{
+		.fields = {
+			[F_CTRLCLKEN] = { 10, 10 },
+			[F_CAMMODE] = { 11, 12 },
+			[F_LANEENABLE] = { 13, 16 },
+			[F_CSI_MODE] = { 17, 17 },
+		},
+		.num_lanes = 4,
+	},
+	{
+		.fields = {
+			[F_CTRLCLKEN] = { 0, 0 },
+			[F_CAMMODE] = { 1, 2 },
+			[F_LANEENABLE] = { 3, 4 },
+			[F_CSI_MODE] = { 5, 5 },
+		},
+		.num_lanes = 2,
+	},
+};
+
+static const struct cal_data dra72x_cal_data = {
+	.camerarx = dra72x_cal_camerarx,
+	.num_csi2_phy = ARRAY_SIZE(dra72x_cal_camerarx),
+};
+
+static const struct cal_data dra72x_es1_cal_data = {
+	.camerarx = dra72x_cal_camerarx,
+	.num_csi2_phy = ARRAY_SIZE(dra72x_cal_camerarx),
+	.flags = DRA72_CAL_PRE_ES2_LDO_DISABLE,
+};
+
+static const struct cal_camerarx_data dra76x_cal_csi_phy[] = {
+	{
+		.fields = {
+			[F_CTRLCLKEN] = { 8, 8 },
+			[F_CAMMODE] = { 9, 10 },
+			[F_CSI_MODE] = { 11, 11 },
+			[F_LANEENABLE] = { 27, 31 },
+		},
+		.num_lanes = 5,
+	},
+	{
+		.fields = {
+			[F_CTRLCLKEN] = { 0, 0 },
+			[F_CAMMODE] = { 1, 2 },
+			[F_CSI_MODE] = { 3, 3 },
+			[F_LANEENABLE] = { 24, 26 },
+		},
+		.num_lanes = 3,
+	},
+};
+
+static const struct cal_data dra76x_cal_data = {
+	.camerarx = dra76x_cal_csi_phy,
+	.num_csi2_phy = ARRAY_SIZE(dra76x_cal_csi_phy),
+};
+
+static const struct cal_camerarx_data am654_cal_csi_phy[] = {
+	{
+		.fields = {
+			[F_CTRLCLKEN] = { 15, 15 },
+			[F_CAMMODE] = { 24, 25 },
+			[F_LANEENABLE] = { 0, 4 },
+		},
+		.num_lanes = 5,
+	},
+};
+
+static const struct cal_data am654_cal_data = {
+	.camerarx = am654_cal_csi_phy,
+	.num_csi2_phy = ARRAY_SIZE(am654_cal_csi_phy),
+};
+
+/* ------------------------------------------------------------------
+ *	I/O Register Accessors
+ * ------------------------------------------------------------------
+ */
+
+#define reg_read(dev, offset) ioread32(dev->base + offset)
+#define reg_write(dev, offset, val) iowrite32(val, dev->base + offset)
+
 static inline u32 reg_read_field(struct cal_dev *cal, u32 offset, u32 mask)
 {
 	return FIELD_GET(mask, reg_read(cal, offset));
@@ -423,41 +443,6 @@ static inline void reg_write_field(struct cal_dev *cal, u32 offset, u32 value,
 	reg_write(cal, offset, val);
 }
 
-static const struct cal_fmt *find_format_by_pix(struct cal_ctx *ctx,
-						u32 pixelformat)
-{
-	const struct cal_fmt *fmt;
-	unsigned int k;
-
-	for (k = 0; k < ctx->num_active_fmt; k++) {
-		fmt = ctx->active_fmt[k];
-		if (fmt->fourcc == pixelformat)
-			return fmt;
-	}
-
-	return NULL;
-}
-
-static const struct cal_fmt *find_format_by_code(struct cal_ctx *ctx,
-						 u32 code)
-{
-	const struct cal_fmt *fmt;
-	unsigned int k;
-
-	for (k = 0; k < ctx->num_active_fmt; k++) {
-		fmt = ctx->active_fmt[k];
-		if (fmt->code == code)
-			return fmt;
-	}
-
-	return NULL;
-}
-
-static inline struct cal_ctx *notifier_to_ctx(struct v4l2_async_notifier *n)
-{
-	return container_of(n, struct cal_ctx, notifier);
-}
-
 static inline void set_field(u32 *valp, u32 field, u32 mask)
 {
 	u32 val = *valp;
@@ -493,11 +478,6 @@ static void cal_quickdump_regs(struct cal_dev *cal)
 	}
 }
 
-static u32 cal_data_get_num_csi2_phy(struct cal_dev *cal)
-{
-	return cal->data->num_csi2_phy;
-}
-
 /* ------------------------------------------------------------------
  *	CAMERARX Management
  * ------------------------------------------------------------------
@@ -1152,6 +1132,11 @@ static void cal_ctx_wr_dma_addr(struct cal_ctx *ctx, unsigned int dmaaddr)
 	reg_write(ctx->cal, CAL_WR_DMA_ADDR(ctx->csi2_port), dmaaddr);
 }
 
+/* ------------------------------------------------------------------
+ *	IRQ Handling
+ * ------------------------------------------------------------------
+ */
+
 static inline void cal_schedule_next_buffer(struct cal_ctx *ctx)
 {
 	struct cal_dmaqueue *dma_q = &ctx->vidq;
@@ -1255,9 +1240,41 @@ static irqreturn_t cal_irq(int irq_cal, void *data)
 	return IRQ_HANDLED;
 }
 
-/*
- * video ioctls
+/* ------------------------------------------------------------------
+ *	V4L2 Video IOCTLs
+ * ------------------------------------------------------------------
  */
+
+static const struct cal_fmt *find_format_by_pix(struct cal_ctx *ctx,
+						u32 pixelformat)
+{
+	const struct cal_fmt *fmt;
+	unsigned int k;
+
+	for (k = 0; k < ctx->num_active_fmt; k++) {
+		fmt = ctx->active_fmt[k];
+		if (fmt->fourcc == pixelformat)
+			return fmt;
+	}
+
+	return NULL;
+}
+
+static const struct cal_fmt *find_format_by_code(struct cal_ctx *ctx,
+						 u32 code)
+{
+	const struct cal_fmt *fmt;
+	unsigned int k;
+
+	for (k = 0; k < ctx->num_active_fmt; k++) {
+		fmt = ctx->active_fmt[k];
+		if (fmt->code == code)
+			return fmt;
+	}
+
+	return NULL;
+}
+
 static int cal_querycap(struct file *file, void *priv,
 			struct v4l2_capability *cap)
 {
@@ -1566,9 +1583,46 @@ static int cal_enum_frameintervals(struct file *file, void *priv,
 	return 0;
 }
 
-/*
- * Videobuf operations
+static const struct v4l2_file_operations cal_fops = {
+	.owner		= THIS_MODULE,
+	.open           = v4l2_fh_open,
+	.release        = vb2_fop_release,
+	.read           = vb2_fop_read,
+	.poll		= vb2_fop_poll,
+	.unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */
+	.mmap           = vb2_fop_mmap,
+};
+
+static const struct v4l2_ioctl_ops cal_ioctl_ops = {
+	.vidioc_querycap      = cal_querycap,
+	.vidioc_enum_fmt_vid_cap  = cal_enum_fmt_vid_cap,
+	.vidioc_g_fmt_vid_cap     = cal_g_fmt_vid_cap,
+	.vidioc_try_fmt_vid_cap   = cal_try_fmt_vid_cap,
+	.vidioc_s_fmt_vid_cap     = cal_s_fmt_vid_cap,
+	.vidioc_enum_framesizes   = cal_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_enum_input    = cal_enum_input,
+	.vidioc_g_input       = cal_g_input,
+	.vidioc_s_input       = cal_s_input,
+	.vidioc_enum_frameintervals = cal_enum_frameintervals,
+	.vidioc_streamon      = vb2_ioctl_streamon,
+	.vidioc_streamoff     = vb2_ioctl_streamoff,
+	.vidioc_log_status    = v4l2_ctrl_log_status,
+	.vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
+	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
+};
+
+/* ------------------------------------------------------------------
+ *	videobuf2 Operations
+ * ------------------------------------------------------------------
  */
+
 static int cal_queue_setup(struct vb2_queue *vq,
 			   unsigned int *nbuffers, unsigned int *nplanes,
 			   unsigned int sizes[], struct device *alloc_devs[])
@@ -1772,40 +1826,10 @@ static const struct vb2_ops cal_video_qops = {
 	.wait_finish		= vb2_ops_wait_finish,
 };
 
-static const struct v4l2_file_operations cal_fops = {
-	.owner		= THIS_MODULE,
-	.open           = v4l2_fh_open,
-	.release        = vb2_fop_release,
-	.read           = vb2_fop_read,
-	.poll		= vb2_fop_poll,
-	.unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */
-	.mmap           = vb2_fop_mmap,
-};
-
-static const struct v4l2_ioctl_ops cal_ioctl_ops = {
-	.vidioc_querycap      = cal_querycap,
-	.vidioc_enum_fmt_vid_cap  = cal_enum_fmt_vid_cap,
-	.vidioc_g_fmt_vid_cap     = cal_g_fmt_vid_cap,
-	.vidioc_try_fmt_vid_cap   = cal_try_fmt_vid_cap,
-	.vidioc_s_fmt_vid_cap     = cal_s_fmt_vid_cap,
-	.vidioc_enum_framesizes   = cal_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_enum_input    = cal_enum_input,
-	.vidioc_g_input       = cal_g_input,
-	.vidioc_s_input       = cal_s_input,
-	.vidioc_enum_frameintervals = cal_enum_frameintervals,
-	.vidioc_streamon      = vb2_ioctl_streamon,
-	.vidioc_streamoff     = vb2_ioctl_streamoff,
-	.vidioc_log_status    = v4l2_ctrl_log_status,
-	.vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
-	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
-};
+/* ------------------------------------------------------------------
+ *	Initialization and module stuff
+ * ------------------------------------------------------------------
+ */
 
 static const struct video_device cal_videodev = {
 	.name		= CAL_MODULE_NAME,
@@ -1817,11 +1841,6 @@ static const struct video_device cal_videodev = {
 			  V4L2_CAP_READWRITE,
 };
 
-/* -----------------------------------------------------------------
- *	Initialization and module stuff
- * ------------------------------------------------------------------
- */
-
 static int cal_complete_ctx(struct cal_ctx *ctx)
 {
 	struct video_device *vfd;
@@ -2242,6 +2261,11 @@ static void cal_get_hwinfo(struct cal_dev *cal)
 		hwinfo);
 }
 
+static u32 cal_data_get_num_csi2_phy(struct cal_dev *cal)
+{
+	return cal->data->num_csi2_phy;
+}
+
 static int cal_probe(struct platform_device *pdev)
 {
 	struct cal_dev *cal;
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 037/107] media: ti-vpe: cal: Rename cal_ctx.csi2_port to cal_ctx.index
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (35 preceding siblings ...)
  2020-06-14 23:58 ` [PATCH v1 036/107] media: ti-vpe: cal: Reorganize remaining code in sections Laurent Pinchart
@ 2020-06-14 23:58 ` Laurent Pinchart
  2020-06-14 23:58 ` [PATCH v1 038/107] media: ti-vpe: cal: Use correct device name for bus_info Laurent Pinchart
                   ` (71 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:58 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

The csi2_port field of the cal_ctx structure holds the context index,
and is independent from the CSI-2 port (even if it currently has the
same numerical value). Rename it to index to avoid the ambiguity.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 50 ++++++++++++++---------------
 1 file changed, 25 insertions(+), 25 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index 6f33853ecdb2..8576a4321e25 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -61,11 +61,11 @@ MODULE_PARM_DESC(debug, "activates debug info");
 	dev_err(&(cal)->pdev->dev, fmt, ##arg)
 
 #define ctx_dbg(level, ctx, fmt, arg...)	\
-	cal_dbg(level, (ctx)->cal, "ctx%u: " fmt, (ctx)->csi2_port, ##arg)
+	cal_dbg(level, (ctx)->cal, "ctx%u: " fmt, (ctx)->index, ##arg)
 #define ctx_info(ctx, fmt, arg...)	\
-	cal_info((ctx)->cal, "ctx%u: " fmt, (ctx)->csi2_port, ##arg)
+	cal_info((ctx)->cal, "ctx%u: " fmt, (ctx)->index, ##arg)
 #define ctx_err(ctx, fmt, arg...)	\
-	cal_err((ctx)->cal, "ctx%u: " fmt, (ctx)->csi2_port, ##arg)
+	cal_err((ctx)->cal, "ctx%u: " fmt, (ctx)->index, ##arg)
 
 #define phy_dbg(level, phy, fmt, arg...)	\
 	cal_dbg(level, (phy)->cal, "phy%u: " fmt, (phy)->instance, ##arg)
@@ -324,7 +324,7 @@ struct cal_ctx {
 
 	unsigned int		sequence;
 	struct vb2_queue	vb_vidq;
-	unsigned int		csi2_port;
+	unsigned int		index;
 	unsigned int		cport;
 	unsigned int		virtual_channel;
 
@@ -1000,7 +1000,7 @@ static void cal_ctx_csi2_config(struct cal_ctx *ctx)
 {
 	u32 val;
 
-	val = reg_read(ctx->cal, CAL_CSI2_CTX0(ctx->csi2_port));
+	val = reg_read(ctx->cal, CAL_CSI2_CTX0(ctx->index));
 	set_field(&val, ctx->cport, CAL_CSI2_CTX_CPORT_MASK);
 	/*
 	 * DT type: MIPI CSI-2 Specs
@@ -1017,9 +1017,9 @@ static void cal_ctx_csi2_config(struct cal_ctx *ctx)
 	set_field(&val, CAL_CSI2_CTX_ATT_PIX, CAL_CSI2_CTX_ATT_MASK);
 	set_field(&val, CAL_CSI2_CTX_PACK_MODE_LINE,
 		  CAL_CSI2_CTX_PACK_MODE_MASK);
-	reg_write(ctx->cal, CAL_CSI2_CTX0(ctx->csi2_port), val);
-	ctx_dbg(3, ctx, "CAL_CSI2_CTX0(%d) = 0x%08x\n", ctx->csi2_port,
-		reg_read(ctx->cal, CAL_CSI2_CTX0(ctx->csi2_port)));
+	reg_write(ctx->cal, CAL_CSI2_CTX0(ctx->index), val);
+	ctx_dbg(3, ctx, "CAL_CSI2_CTX0(%d) = 0x%08x\n", ctx->index,
+		reg_read(ctx->cal, CAL_CSI2_CTX0(ctx->index)));
 }
 
 static void cal_ctx_pix_proc_config(struct cal_ctx *ctx)
@@ -1061,16 +1061,16 @@ static void cal_ctx_pix_proc_config(struct cal_ctx *ctx)
 		break;
 	}
 
-	val = reg_read(ctx->cal, CAL_PIX_PROC(ctx->csi2_port));
+	val = reg_read(ctx->cal, CAL_PIX_PROC(ctx->index));
 	set_field(&val, extract, CAL_PIX_PROC_EXTRACT_MASK);
 	set_field(&val, CAL_PIX_PROC_DPCMD_BYPASS, CAL_PIX_PROC_DPCMD_MASK);
 	set_field(&val, CAL_PIX_PROC_DPCME_BYPASS, CAL_PIX_PROC_DPCME_MASK);
 	set_field(&val, pack, CAL_PIX_PROC_PACK_MASK);
 	set_field(&val, ctx->cport, CAL_PIX_PROC_CPORT_MASK);
 	set_field(&val, 1, CAL_PIX_PROC_EN_MASK);
-	reg_write(ctx->cal, CAL_PIX_PROC(ctx->csi2_port), val);
-	ctx_dbg(3, ctx, "CAL_PIX_PROC(%d) = 0x%08x\n", ctx->csi2_port,
-		reg_read(ctx->cal, CAL_PIX_PROC(ctx->csi2_port)));
+	reg_write(ctx->cal, CAL_PIX_PROC(ctx->index), val);
+	ctx_dbg(3, ctx, "CAL_PIX_PROC(%d) = 0x%08x\n", ctx->index,
+		reg_read(ctx->cal, CAL_PIX_PROC(ctx->index)));
 }
 
 static void cal_ctx_wr_dma_config(struct cal_ctx *ctx,
@@ -1078,7 +1078,7 @@ static void cal_ctx_wr_dma_config(struct cal_ctx *ctx,
 {
 	u32 val;
 
-	val = reg_read(ctx->cal, CAL_WR_DMA_CTRL(ctx->csi2_port));
+	val = reg_read(ctx->cal, CAL_WR_DMA_CTRL(ctx->index));
 	set_field(&val, ctx->cport, CAL_WR_DMA_CTRL_CPORT_MASK);
 	set_field(&val, height, CAL_WR_DMA_CTRL_YSIZE_MASK);
 	set_field(&val, CAL_WR_DMA_CTRL_DTAG_PIX_DAT,
@@ -1088,22 +1088,22 @@ static void cal_ctx_wr_dma_config(struct cal_ctx *ctx,
 	set_field(&val, CAL_WR_DMA_CTRL_PATTERN_LINEAR,
 		  CAL_WR_DMA_CTRL_PATTERN_MASK);
 	set_field(&val, 1, CAL_WR_DMA_CTRL_STALL_RD_MASK);
-	reg_write(ctx->cal, CAL_WR_DMA_CTRL(ctx->csi2_port), val);
-	ctx_dbg(3, ctx, "CAL_WR_DMA_CTRL(%d) = 0x%08x\n", ctx->csi2_port,
-		reg_read(ctx->cal, CAL_WR_DMA_CTRL(ctx->csi2_port)));
+	reg_write(ctx->cal, CAL_WR_DMA_CTRL(ctx->index), val);
+	ctx_dbg(3, ctx, "CAL_WR_DMA_CTRL(%d) = 0x%08x\n", ctx->index,
+		reg_read(ctx->cal, CAL_WR_DMA_CTRL(ctx->index)));
 
 	/*
 	 * width/16 not sure but giving it a whirl.
 	 * zero does not work right
 	 */
 	reg_write_field(ctx->cal,
-			CAL_WR_DMA_OFST(ctx->csi2_port),
+			CAL_WR_DMA_OFST(ctx->index),
 			(width / 16),
 			CAL_WR_DMA_OFST_MASK);
-	ctx_dbg(3, ctx, "CAL_WR_DMA_OFST(%d) = 0x%08x\n", ctx->csi2_port,
-		reg_read(ctx->cal, CAL_WR_DMA_OFST(ctx->csi2_port)));
+	ctx_dbg(3, ctx, "CAL_WR_DMA_OFST(%d) = 0x%08x\n", ctx->index,
+		reg_read(ctx->cal, CAL_WR_DMA_OFST(ctx->index)));
 
-	val = reg_read(ctx->cal, CAL_WR_DMA_XSIZE(ctx->csi2_port));
+	val = reg_read(ctx->cal, CAL_WR_DMA_XSIZE(ctx->index));
 	/* 64 bit word means no skipping */
 	set_field(&val, 0, CAL_WR_DMA_XSIZE_XSKIP_MASK);
 	/*
@@ -1112,9 +1112,9 @@ static void cal_ctx_wr_dma_config(struct cal_ctx *ctx,
 	 * is detected automagically
 	 */
 	set_field(&val, (width / 8), CAL_WR_DMA_XSIZE_MASK);
-	reg_write(ctx->cal, CAL_WR_DMA_XSIZE(ctx->csi2_port), val);
-	ctx_dbg(3, ctx, "CAL_WR_DMA_XSIZE(%d) = 0x%08x\n", ctx->csi2_port,
-		reg_read(ctx->cal, CAL_WR_DMA_XSIZE(ctx->csi2_port)));
+	reg_write(ctx->cal, CAL_WR_DMA_XSIZE(ctx->index), val);
+	ctx_dbg(3, ctx, "CAL_WR_DMA_XSIZE(%d) = 0x%08x\n", ctx->index,
+		reg_read(ctx->cal, CAL_WR_DMA_XSIZE(ctx->index)));
 
 	val = reg_read(ctx->cal, CAL_CTRL);
 	set_field(&val, CAL_CTRL_BURSTSIZE_BURST128, CAL_CTRL_BURSTSIZE_MASK);
@@ -1129,7 +1129,7 @@ static void cal_ctx_wr_dma_config(struct cal_ctx *ctx,
 
 static void cal_ctx_wr_dma_addr(struct cal_ctx *ctx, unsigned int dmaaddr)
 {
-	reg_write(ctx->cal, CAL_WR_DMA_ADDR(ctx->csi2_port), dmaaddr);
+	reg_write(ctx->cal, CAL_WR_DMA_ADDR(ctx->index), dmaaddr);
 }
 
 /* ------------------------------------------------------------------
@@ -2205,7 +2205,7 @@ static struct cal_ctx *cal_create_instance(struct cal_dev *cal, int inst)
 	ctx->phy = cal->phy[inst];
 
 	/* Store the instance id */
-	ctx->csi2_port = inst;
+	ctx->index = inst;
 	ctx->cport = inst;
 
 	ret = of_cal_create_instance(ctx, inst);
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 038/107] media: ti-vpe: cal: Use correct device name for bus_info
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (36 preceding siblings ...)
  2020-06-14 23:58 ` [PATCH v1 037/107] media: ti-vpe: cal: Rename cal_ctx.csi2_port to cal_ctx.index Laurent Pinchart
@ 2020-06-14 23:58 ` Laurent Pinchart
  2020-06-14 23:58 ` [PATCH v1 039/107] media: ti-vpe: cal: Get struct device without going through v4l2_device Laurent Pinchart
                   ` (70 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:58 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

The v4l2_capability bus_info field, filled by the VIDIOC_QUERYCAP ioctl
handler, specifies the location of the device in the system. For
platform devices, V4L2 specifies that the value must be "platform:"
followed by the device name. Fix the cal_querycap() function to set the
right value.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index 8576a4321e25..fdc8248ef44a 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -1284,7 +1284,7 @@ static int cal_querycap(struct file *file, void *priv,
 	strscpy(cap->card, CAL_MODULE_NAME, sizeof(cap->card));
 
 	snprintf(cap->bus_info, sizeof(cap->bus_info),
-		 "platform:%s", ctx->v4l2_dev.name);
+		 "platform:%s", dev_name(&ctx->cal->pdev->dev));
 	return 0;
 }
 
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 039/107] media: ti-vpe: cal: Get struct device without going through v4l2_device
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (37 preceding siblings ...)
  2020-06-14 23:58 ` [PATCH v1 038/107] media: ti-vpe: cal: Use correct device name for bus_info Laurent Pinchart
@ 2020-06-14 23:58 ` Laurent Pinchart
  2020-06-14 23:58 ` [PATCH v1 040/107] media: ti-vpe: cal: Use ctx_info() instead of v4l2_info() Laurent Pinchart
                   ` (69 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:58 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

Instead of retrieving the struct device for the platform device from the
v4l2_device, get it from the platform device directly. This prepares for
cleanups related to v4l2_device handling.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index fdc8248ef44a..10baca7cfcee 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -1862,7 +1862,7 @@ static int cal_complete_ctx(struct cal_ctx *ctx)
 	q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
 	q->lock = &ctx->mutex;
 	q->min_buffers_needed = 3;
-	q->dev = ctx->v4l2_dev.dev;
+	q->dev = &ctx->cal->pdev->dev;
 
 	ret = vb2_queue_init(q);
 	if (ret)
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 040/107] media: ti-vpe: cal: Use ctx_info() instead of v4l2_info()
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (38 preceding siblings ...)
  2020-06-14 23:58 ` [PATCH v1 039/107] media: ti-vpe: cal: Get struct device without going through v4l2_device Laurent Pinchart
@ 2020-06-14 23:58 ` Laurent Pinchart
  2020-06-14 23:58 ` [PATCH v1 041/107] media: ti-vpe: cal: Use a loop to create CAMERARX and context instances Laurent Pinchart
                   ` (68 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:58 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

Use the context-specific print macro to replace the last usage of the
v4l2_* print macros.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index 10baca7cfcee..e353b1b0f6f9 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -1887,8 +1887,8 @@ static int cal_complete_ctx(struct cal_ctx *ctx)
 	if (ret < 0)
 		return ret;
 
-	v4l2_info(&ctx->v4l2_dev, "V4L2 device registered as %s\n",
-		  video_device_node_name(vfd));
+	ctx_info(ctx, "V4L2 device registered as %s\n",
+		 video_device_node_name(vfd));
 
 	return 0;
 }
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 041/107] media: ti-vpe: cal: Use a loop to create CAMERARX and context instances
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (39 preceding siblings ...)
  2020-06-14 23:58 ` [PATCH v1 040/107] media: ti-vpe: cal: Use ctx_info() instead of v4l2_info() Laurent Pinchart
@ 2020-06-14 23:58 ` Laurent Pinchart
  2020-06-14 23:58 ` [PATCH v1 042/107] media: ti-vpe: cal: Drop struct cal_dev v4l2_dev field Laurent Pinchart
                   ` (67 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:58 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

Replace a manually unrolled loop with an explicit for loop to increase
readability when creating the CAMERARX and context instances. The
explicit NULL initialization of cal->phy[] and cal->ctx[] is removed, as
the cal structure is zeroed when allocated.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 21 ++++++---------------
 1 file changed, 6 insertions(+), 15 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index e353b1b0f6f9..681e846eb236 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -2347,24 +2347,15 @@ static int cal_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, cal);
 
-	cal->phy[0] = cal_camerarx_create(cal, 0);
-	if (IS_ERR(cal->phy[0]))
-		return PTR_ERR(cal->phy[0]);
-
-	if (cal_data_get_num_csi2_phy(cal) > 1) {
-		cal->phy[1] = cal_camerarx_create(cal, 1);
-		if (IS_ERR(cal->phy[1]))
-			return PTR_ERR(cal->phy[1]);
-	} else {
-		cal->phy[1] = NULL;
+	for (i = 0; i < cal_data_get_num_csi2_phy(cal); ++i) {
+		cal->phy[i] = cal_camerarx_create(cal, i);
+		if (IS_ERR(cal->phy[i]))
+			return PTR_ERR(cal->phy[i]);
 	}
 
-	cal->ctx[0] = NULL;
-	cal->ctx[1] = NULL;
+	for (i = 0; i < cal_data_get_num_csi2_phy(cal); ++i)
+		cal->ctx[i] = cal_create_instance(cal, i);
 
-	cal->ctx[0] = cal_create_instance(cal, 0);
-	if (cal_data_get_num_csi2_phy(cal) > 1)
-		cal->ctx[1] = cal_create_instance(cal, 1);
 	if (!cal->ctx[0] && !cal->ctx[1]) {
 		cal_err(cal, "Neither port is configured, no point in staying up\n");
 		return -ENODEV;
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 042/107] media: ti-vpe: cal: Drop struct cal_dev v4l2_dev field
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (40 preceding siblings ...)
  2020-06-14 23:58 ` [PATCH v1 041/107] media: ti-vpe: cal: Use a loop to create CAMERARX and context instances Laurent Pinchart
@ 2020-06-14 23:58 ` Laurent Pinchart
  2020-06-14 23:58 ` [PATCH v1 043/107] media: ti-vpe: cal: Split CAMERARX syscon regmap retrieval to a function Laurent Pinchart
                   ` (66 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:58 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

The v4l2_dev field of the cal_dev structure is initialized but never
used. Drop it.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 5 -----
 1 file changed, 5 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index 681e846eb236..479ea9337f30 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -278,7 +278,6 @@ struct cal_dev {
 	void __iomem		*base;
 	struct resource		*res;
 	struct platform_device	*pdev;
-	struct v4l2_device	v4l2_dev;
 
 	const struct cal_data	*data;
 
@@ -2287,10 +2286,6 @@ static int cal_probe(struct platform_device *pdev)
 		return -ENODEV;
 	}
 
-	/* set pseudo v4l2 device name so we can use v4l2_printk */
-	strscpy(cal->v4l2_dev.name, CAL_MODULE_NAME,
-		sizeof(cal->v4l2_dev.name));
-
 	/* save pdev pointer */
 	cal->pdev = pdev;
 
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 043/107] media: ti-vpe: cal: Split CAMERARX syscon regmap retrieval to a function
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (41 preceding siblings ...)
  2020-06-14 23:58 ` [PATCH v1 042/107] media: ti-vpe: cal: Drop struct cal_dev v4l2_dev field Laurent Pinchart
@ 2020-06-14 23:58 ` Laurent Pinchart
  2020-06-14 23:58 ` [PATCH v1 044/107] media: ti-vpe: cal: Use syscon_regmap_lookup_by_phandle_args() Laurent Pinchart
                   ` (65 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:58 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

Simplify the cal_probe() function by splitting the CAMERARX syscon
regmap retrieval to a separate function. A few local variables are
renamed in the process to shorten them (syscon_camerrx_*) or to make
them more accurate (parent isn't the parent OF node but the CAL device's
own OF node).

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 73 +++++++++++++++++------------
 1 file changed, 42 insertions(+), 31 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index 479ea9337f30..d7f251b8a8a3 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -990,6 +990,45 @@ static struct regmap *cal_get_camerarx_regmap(struct cal_dev *cal)
 	return regmap;
 }
 
+static int cal_camerarx_init_regmap(struct cal_dev *cal)
+{
+	struct device_node *np = cal->pdev->dev.of_node;
+	struct regmap *syscon;
+	u32 syscon_offset;
+	int ret;
+
+	syscon = syscon_regmap_lookup_by_phandle(np, "ti,camerrx-control");
+	ret = of_property_read_u32_index(np, "ti,camerrx-control", 1,
+					 &syscon_offset);
+	if (IS_ERR(syscon))
+		ret = PTR_ERR(syscon);
+	if (ret) {
+		dev_warn(&cal->pdev->dev,
+			 "failed to get ti,camerrx-control: %d\n", ret);
+
+		/*
+		 * Backward DTS compatibility.
+		 * If syscon entry is not present then check if the
+		 * camerrx_control resource is present.
+		 */
+		syscon = cal_get_camerarx_regmap(cal);
+		if (IS_ERR(syscon)) {
+			dev_err(&cal->pdev->dev,
+				"failed to get camerrx_control regmap\n");
+			return PTR_ERR(syscon);
+		}
+		/* In this case the base already point to the direct
+		 * CM register so no need for an offset
+		 */
+		syscon_offset = 0;
+	}
+
+	cal->syscon_camerrx = syscon;
+	cal->syscon_camerrx_offset = syscon_offset;
+
+	return 0;
+}
+
 /* ------------------------------------------------------------------
  *	Context Management
  * ------------------------------------------------------------------
@@ -2269,9 +2308,6 @@ static int cal_probe(struct platform_device *pdev)
 {
 	struct cal_dev *cal;
 	struct cal_ctx *ctx;
-	struct device_node *parent = pdev->dev.of_node;
-	struct regmap *syscon_camerrx;
-	u32 syscon_camerrx_offset;
 	unsigned int i;
 	int ret;
 	int irq;
@@ -2295,34 +2331,9 @@ static int cal_probe(struct platform_device *pdev)
 		return PTR_ERR(cal->fclk);
 	}
 
-	syscon_camerrx = syscon_regmap_lookup_by_phandle(parent,
-							 "ti,camerrx-control");
-	ret = of_property_read_u32_index(parent, "ti,camerrx-control", 1,
-					 &syscon_camerrx_offset);
-	if (IS_ERR(syscon_camerrx))
-		ret = PTR_ERR(syscon_camerrx);
-	if (ret) {
-		dev_warn(&pdev->dev, "failed to get ti,camerrx-control: %d\n",
-			 ret);
-
-		/*
-		 * Backward DTS compatibility.
-		 * If syscon entry is not present then check if the
-		 * camerrx_control resource is present.
-		 */
-		syscon_camerrx = cal_get_camerarx_regmap(cal);
-		if (IS_ERR(syscon_camerrx)) {
-			dev_err(&pdev->dev, "failed to get camerrx_control regmap\n");
-			return PTR_ERR(syscon_camerrx);
-		}
-		/* In this case the base already point to the direct
-		 * CM register so no need for an offset
-		 */
-		syscon_camerrx_offset = 0;
-	}
-
-	cal->syscon_camerrx = syscon_camerrx;
-	cal->syscon_camerrx_offset = syscon_camerrx_offset;
+	ret = cal_camerarx_init_regmap(cal);
+	if (ret < 0)
+		return ret;
 
 	cal->res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
 						"cal_top");
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 044/107] media: ti-vpe: cal: Use syscon_regmap_lookup_by_phandle_args()
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (42 preceding siblings ...)
  2020-06-14 23:58 ` [PATCH v1 043/107] media: ti-vpe: cal: Split CAMERARX syscon regmap retrieval to a function Laurent Pinchart
@ 2020-06-14 23:58 ` Laurent Pinchart
  2020-06-14 23:58 ` [PATCH v1 045/107] media: ti-vpe: cal: Inline cal_get_camerarx_regmap() in caller Laurent Pinchart
                   ` (64 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:58 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

Use the syscon_regmap_lookup_by_phandle_args() function to replace
manual lookup of the syscon regmap offset. This simplifies the
cal_camerarx_init_regmap() implementation.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 19 ++++++++-----------
 1 file changed, 8 insertions(+), 11 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index d7f251b8a8a3..522b2b4b76e0 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -994,17 +994,14 @@ static int cal_camerarx_init_regmap(struct cal_dev *cal)
 {
 	struct device_node *np = cal->pdev->dev.of_node;
 	struct regmap *syscon;
-	u32 syscon_offset;
-	int ret;
+	unsigned int offset;
 
-	syscon = syscon_regmap_lookup_by_phandle(np, "ti,camerrx-control");
-	ret = of_property_read_u32_index(np, "ti,camerrx-control", 1,
-					 &syscon_offset);
-	if (IS_ERR(syscon))
-		ret = PTR_ERR(syscon);
-	if (ret) {
+	syscon = syscon_regmap_lookup_by_phandle_args(np, "ti,camerrx-control",
+						      1, &offset);
+	if (IS_ERR(syscon)) {
 		dev_warn(&cal->pdev->dev,
-			 "failed to get ti,camerrx-control: %d\n", ret);
+			 "failed to get ti,camerrx-control: %ld\n",
+			 PTR_ERR(syscon));
 
 		/*
 		 * Backward DTS compatibility.
@@ -1020,11 +1017,11 @@ static int cal_camerarx_init_regmap(struct cal_dev *cal)
 		/* In this case the base already point to the direct
 		 * CM register so no need for an offset
 		 */
-		syscon_offset = 0;
+		offset = 0;
 	}
 
 	cal->syscon_camerrx = syscon;
-	cal->syscon_camerrx_offset = syscon_offset;
+	cal->syscon_camerrx_offset = offset;
 
 	return 0;
 }
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 045/107] media: ti-vpe: cal: Inline cal_get_camerarx_regmap() in caller
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (43 preceding siblings ...)
  2020-06-14 23:58 ` [PATCH v1 044/107] media: ti-vpe: cal: Use syscon_regmap_lookup_by_phandle_args() Laurent Pinchart
@ 2020-06-14 23:58 ` Laurent Pinchart
  2020-06-14 23:58 ` [PATCH v1 046/107] media: ti-vpe: cal: Add comments to cal_probe() to delimitate sections Laurent Pinchart
                   ` (63 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:58 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

The cal_get_camerarx_regmap() function is called in a single place.
Inline it in its caller, as it results in a clear code flow.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 75 ++++++++++++-----------------
 1 file changed, 32 insertions(+), 43 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index 522b2b4b76e0..c83bf261da91 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -959,20 +959,36 @@ static struct cal_camerarx *cal_camerarx_create(struct cal_dev *cal,
 	return phy;
 }
 
-static struct regmap *cal_get_camerarx_regmap(struct cal_dev *cal)
+static int cal_camerarx_init_regmap(struct cal_dev *cal)
 {
-	struct platform_device *pdev = cal->pdev;
+	struct device_node *np = cal->pdev->dev.of_node;
 	struct regmap_config config = { };
-	struct regmap *regmap;
-	void __iomem *base;
+	struct regmap *syscon;
 	struct resource *res;
+	unsigned int offset;
+	void __iomem *base;
 
-	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+	syscon = syscon_regmap_lookup_by_phandle_args(np, "ti,camerrx-control",
+						      1, &offset);
+	if (!IS_ERR(syscon)) {
+		cal->syscon_camerrx = syscon;
+		cal->syscon_camerrx_offset = offset;
+		return 0;
+	}
+
+	dev_warn(&cal->pdev->dev, "failed to get ti,camerrx-control: %ld\n",
+		 PTR_ERR(syscon));
+
+	/*
+	 * Backward DTS compatibility. If syscon entry is not present then
+	 * check if the camerrx_control resource is present.
+	 */
+	res = platform_get_resource_byname(cal->pdev, IORESOURCE_MEM,
 					   "camerrx_control");
-	base = devm_ioremap_resource(&pdev->dev, res);
+	base = devm_ioremap_resource(&cal->pdev->dev, res);
 	if (IS_ERR(base)) {
-		cal_err(cal, "failed to ioremap\n");
-		return ERR_CAST(base);
+		cal_err(cal, "failed to ioremap camerrx_control\n");
+		return PTR_ERR(base);
 	}
 
 	cal_dbg(1, cal, "ioresource %s at %pa - %pa\n",
@@ -983,45 +999,18 @@ static struct regmap *cal_get_camerarx_regmap(struct cal_dev *cal)
 	config.val_bits = 32;
 	config.max_register = resource_size(res) - 4;
 
-	regmap = regmap_init_mmio(NULL, base, &config);
-	if (IS_ERR(regmap))
-		pr_err("regmap init failed\n");
-
-	return regmap;
-}
-
-static int cal_camerarx_init_regmap(struct cal_dev *cal)
-{
-	struct device_node *np = cal->pdev->dev.of_node;
-	struct regmap *syscon;
-	unsigned int offset;
-
-	syscon = syscon_regmap_lookup_by_phandle_args(np, "ti,camerrx-control",
-						      1, &offset);
+	syscon = regmap_init_mmio(NULL, base, &config);
 	if (IS_ERR(syscon)) {
-		dev_warn(&cal->pdev->dev,
-			 "failed to get ti,camerrx-control: %ld\n",
-			 PTR_ERR(syscon));
-
-		/*
-		 * Backward DTS compatibility.
-		 * If syscon entry is not present then check if the
-		 * camerrx_control resource is present.
-		 */
-		syscon = cal_get_camerarx_regmap(cal);
-		if (IS_ERR(syscon)) {
-			dev_err(&cal->pdev->dev,
-				"failed to get camerrx_control regmap\n");
-			return PTR_ERR(syscon);
-		}
-		/* In this case the base already point to the direct
-		 * CM register so no need for an offset
-		 */
-		offset = 0;
+		pr_err("regmap init failed\n");
+		return PTR_ERR(syscon);
 	}
 
+	/*
+	 * In this case the base already point to the direct CM register so no
+	 * need for an offset.
+	 */
 	cal->syscon_camerrx = syscon;
-	cal->syscon_camerrx_offset = offset;
+	cal->syscon_camerrx_offset = 0;
 
 	return 0;
 }
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 046/107] media: ti-vpe: cal: Add comments to cal_probe() to delimitate sections
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (44 preceding siblings ...)
  2020-06-14 23:58 ` [PATCH v1 045/107] media: ti-vpe: cal: Inline cal_get_camerarx_regmap() in caller Laurent Pinchart
@ 2020-06-14 23:58 ` Laurent Pinchart
  2020-06-14 23:58 ` [PATCH v1 047/107] media: ti-vpe: cal: Rename cal_create_instance() to cal_ctx_create() Laurent Pinchart
                   ` (62 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:58 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

The cal_probe() function is a bit long, add comments to delimitate
sections in order to improve readability. The platform_set_drvdata()
call is moved to a more logical place as a result.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index c83bf261da91..9b116ffd6e41 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -2308,9 +2308,10 @@ static int cal_probe(struct platform_device *pdev)
 		return -ENODEV;
 	}
 
-	/* save pdev pointer */
 	cal->pdev = pdev;
+	platform_set_drvdata(pdev, cal);
 
+	/* Acquire resources: clocks, CAMERARX regmap, I/O memory and IRQ. */
 	cal->fclk = devm_clk_get(&pdev->dev, "fck");
 	if (IS_ERR(cal->fclk)) {
 		dev_err(&pdev->dev, "cannot get CAL fclk\n");
@@ -2337,14 +2338,14 @@ static int cal_probe(struct platform_device *pdev)
 	if (ret)
 		return ret;
 
-	platform_set_drvdata(pdev, cal);
-
+	/* Create CAMERARX PHYs. */
 	for (i = 0; i < cal_data_get_num_csi2_phy(cal); ++i) {
 		cal->phy[i] = cal_camerarx_create(cal, i);
 		if (IS_ERR(cal->phy[i]))
 			return PTR_ERR(cal->phy[i]);
 	}
 
+	/* Create contexts. */
 	for (i = 0; i < cal_data_get_num_csi2_phy(cal); ++i)
 		cal->ctx[i] = cal_create_instance(cal, i);
 
@@ -2355,15 +2356,13 @@ static int cal_probe(struct platform_device *pdev)
 
 	vb2_dma_contig_set_max_seg_size(&pdev->dev, DMA_BIT_MASK(32));
 
+	/* Read the revision and hardware info to verify hardware access. */
 	pm_runtime_enable(&pdev->dev);
-
 	ret = pm_runtime_get_sync(&pdev->dev);
 	if (ret)
 		goto runtime_disable;
 
-	/* Just check we can actually access the module */
 	cal_get_hwinfo(cal);
-
 	pm_runtime_put_sync(&pdev->dev);
 
 	return 0;
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 047/107] media: ti-vpe: cal: Rename cal_create_instance() to cal_ctx_create()
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (45 preceding siblings ...)
  2020-06-14 23:58 ` [PATCH v1 046/107] media: ti-vpe: cal: Add comments to cal_probe() to delimitate sections Laurent Pinchart
@ 2020-06-14 23:58 ` Laurent Pinchart
  2020-06-14 23:58 ` [PATCH v1 048/107] media: ti-vpe: cal: Hardcode virtual channel to 0 Laurent Pinchart
                   ` (61 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:58 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

The cal_create_instance() function creates a CAL context. Rename it to
cal_ctx_create() to make its purpose more explicit.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index 9b116ffd6e41..52b4fa1ff7a5 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -2198,7 +2198,7 @@ static int of_cal_create_instance(struct cal_ctx *ctx, int inst)
 	return ret;
 }
 
-static struct cal_ctx *cal_create_instance(struct cal_dev *cal, int inst)
+static struct cal_ctx *cal_ctx_create(struct cal_dev *cal, int inst)
 {
 	struct cal_ctx *ctx;
 	struct v4l2_ctrl_handler *hdl;
@@ -2347,7 +2347,7 @@ static int cal_probe(struct platform_device *pdev)
 
 	/* Create contexts. */
 	for (i = 0; i < cal_data_get_num_csi2_phy(cal); ++i)
-		cal->ctx[i] = cal_create_instance(cal, i);
+		cal->ctx[i] = cal_ctx_create(cal, i);
 
 	if (!cal->ctx[0] && !cal->ctx[1]) {
 		cal_err(cal, "Neither port is configured, no point in staying up\n");
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 048/107] media: ti-vpe: cal: Hardcode virtual channel to 0
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (46 preceding siblings ...)
  2020-06-14 23:58 ` [PATCH v1 047/107] media: ti-vpe: cal: Rename cal_create_instance() to cal_ctx_create() Laurent Pinchart
@ 2020-06-14 23:58 ` Laurent Pinchart
  2020-06-14 23:58 ` [PATCH v1 049/107] media: ti-vpe: cal: Use of_graph_get_endpoint_by_regs() to parse OF Laurent Pinchart
                   ` (60 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:58 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

Using the endpoint reg value to pass the CSI-2 source virtual channel ID
in DT is a hack, isn't documented in the DT bindings, and isn't used in
neither upstream DT nor TI official overlays. Hardcode the virtual
channel to 0 to simplify reworking the code, proper virtual channel
support will be implemented later.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 8 +-------
 1 file changed, 1 insertion(+), 7 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index 52b4fa1ff7a5..c1866e58e9ec 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -325,7 +325,6 @@ struct cal_ctx {
 	struct vb2_queue	vb_vidq;
 	unsigned int		index;
 	unsigned int		cport;
-	unsigned int		virtual_channel;
 
 	/* Pointer pointing to current v4l2_buffer */
 	struct cal_buffer	*cur_frm;
@@ -1035,8 +1034,7 @@ static void cal_ctx_csi2_config(struct cal_ctx *ctx)
 	 *  0x1E: YUV422 2 pixels = 4 bytes
 	 */
 	set_field(&val, 0x1, CAL_CSI2_CTX_DT_MASK);
-	/* Virtual Channel from the CSI2 sensor usually 0! */
-	set_field(&val, ctx->virtual_channel, CAL_CSI2_CTX_VC_MASK);
+	set_field(&val, 0, CAL_CSI2_CTX_VC_MASK);
 	set_field(&val, ctx->v_fmt.fmt.pix.height, CAL_CSI2_CTX_LINES_MASK);
 	set_field(&val, CAL_CSI2_CTX_ATT_PIX, CAL_CSI2_CTX_ATT_MASK);
 	set_field(&val, CAL_CSI2_CTX_PACK_MODE_LINE,
@@ -2140,11 +2138,7 @@ static int of_cal_create_instance(struct cal_ctx *ctx, int inst)
 		goto cleanup_exit;
 	}
 
-	/* Store Virtual Channel number */
-	ctx->virtual_channel = endpoint->base.id;
-
 	ctx_dbg(3, ctx, "Port:%d v4l2-endpoint: CSI2\n", inst);
-	ctx_dbg(3, ctx, "Virtual Channel=%d\n", ctx->virtual_channel);
 	ctx_dbg(3, ctx, "flags=0x%08x\n", endpoint->bus.mipi_csi2.flags);
 	ctx_dbg(3, ctx, "clock_lane=%d\n", endpoint->bus.mipi_csi2.clock_lane);
 	ctx_dbg(3, ctx, "num_data_lanes=%d\n",
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 049/107] media: ti-vpe: cal: Use of_graph_get_endpoint_by_regs() to parse OF
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (47 preceding siblings ...)
  2020-06-14 23:58 ` [PATCH v1 048/107] media: ti-vpe: cal: Hardcode virtual channel to 0 Laurent Pinchart
@ 2020-06-14 23:58 ` Laurent Pinchart
  2020-06-14 23:58 ` [PATCH v1 050/107] media: ti-vpe: cal: Fix usage of v4l2_fwnode_endpoint_parse() Laurent Pinchart
                   ` (59 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:58 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

Replace the manual of_get_next_port() and of_get_next_endpoint()
implementations and the corresponding logic in the caller with a call to
of_graph_get_endpoint_by_regs(). This greatly simplifies OF parsing.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 114 ++--------------------------
 1 file changed, 7 insertions(+), 107 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index c1866e58e9ec..7f2f206f578b 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -2008,125 +2008,26 @@ static const struct v4l2_async_notifier_operations cal_async_ops = {
 	.complete = cal_async_complete,
 };
 
-static struct device_node *
-of_get_next_port(const struct device_node *parent,
-		 struct device_node *prev)
-{
-	struct device_node *port;
-
-	if (!parent)
-		return NULL;
-
-	if (!prev) {
-		struct device_node *ports;
-		/*
-		 * It's the first call, we have to find a port subnode
-		 * within this node or within an optional 'ports' node.
-		 */
-		ports = of_get_child_by_name(parent, "ports");
-		if (ports)
-			parent = ports;
-
-		port = of_get_child_by_name(parent, "port");
-
-		/* release the 'ports' node */
-		of_node_put(ports);
-	} else {
-		struct device_node *ports;
-
-		ports = of_get_parent(prev);
-		if (!ports)
-			return NULL;
-
-		do {
-			port = of_get_next_child(ports, prev);
-			if (!port) {
-				of_node_put(ports);
-				return NULL;
-			}
-			prev = port;
-		} while (!of_node_name_eq(port, "port"));
-		of_node_put(ports);
-	}
-
-	return port;
-}
-
-static struct device_node *
-of_get_next_endpoint(const struct device_node *parent,
-		     struct device_node *prev)
-{
-	struct device_node *ep;
-
-	if (!parent)
-		return NULL;
-
-	do {
-		ep = of_get_next_child(parent, prev);
-		if (!ep)
-			return NULL;
-		prev = ep;
-	} while (!of_node_name_eq(ep, "endpoint"));
-
-	return ep;
-}
-
 static int of_cal_create_instance(struct cal_ctx *ctx, int inst)
 {
 	struct platform_device *pdev = ctx->cal->pdev;
-	struct device_node *ep_node, *port, *sensor_node, *parent;
+	struct device_node *ep_node, *sensor_node;
 	struct v4l2_fwnode_endpoint *endpoint;
 	struct v4l2_async_subdev *asd;
-	u32 regval = 0;
-	int ret, index, lane;
-	bool found_port = false;
-
-	parent = pdev->dev.of_node;
+	int ret = -EINVAL, lane;
 
 	endpoint = &ctx->phy->endpoint;
 
-	ep_node = NULL;
-	port = NULL;
-	sensor_node = NULL;
-	ret = -EINVAL;
-
-	ctx_dbg(3, ctx, "Scanning Port node for csi2 port: %d\n", inst);
-	for (index = 0; index < CAL_NUM_CSI2_PORTS; index++) {
-		port = of_get_next_port(parent, port);
-		if (!port) {
-			ctx_dbg(1, ctx, "No port node found for csi2 port:%d\n",
-				index);
-			goto cleanup_exit;
-		}
-
-		/* Match the slice number with <REG> */
-		of_property_read_u32(port, "reg", &regval);
-		ctx_dbg(3, ctx, "port:%d inst:%d <reg>:%d\n",
-			index, inst, regval);
-		if ((regval == inst) && (index == inst)) {
-			found_port = true;
-			break;
-		}
-	}
-
-	if (!found_port) {
-		ctx_dbg(1, ctx, "No port node matches csi2 port:%d\n",
-			inst);
-		goto cleanup_exit;
-	}
-
-	ctx_dbg(3, ctx, "Scanning sub-device for csi2 port: %d\n",
-		inst);
-
-	ep_node = of_get_next_endpoint(port, ep_node);
+	ctx_dbg(3, ctx, "Getting endpoint for port@%d\n", inst);
+	ep_node = of_graph_get_endpoint_by_regs(pdev->dev.of_node, inst, 0);
 	if (!ep_node) {
-		ctx_dbg(3, ctx, "can't get next endpoint\n");
-		goto cleanup_exit;
+		ctx_dbg(3, ctx, "Can't get endpoint\n");
+		return -EINVAL;
 	}
 
 	sensor_node = of_graph_get_remote_port_parent(ep_node);
 	if (!sensor_node) {
-		ctx_dbg(3, ctx, "can't get remote parent\n");
+		ctx_dbg(3, ctx, "Can't get remote parent\n");
 		goto cleanup_exit;
 	}
 
@@ -2187,7 +2088,6 @@ static int of_cal_create_instance(struct cal_ctx *ctx, int inst)
 cleanup_exit:
 	of_node_put(sensor_node);
 	of_node_put(ep_node);
-	of_node_put(port);
 
 	return ret;
 }
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 050/107] media: ti-vpe: cal: Fix usage of v4l2_fwnode_endpoint_parse()
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (48 preceding siblings ...)
  2020-06-14 23:58 ` [PATCH v1 049/107] media: ti-vpe: cal: Use of_graph_get_endpoint_by_regs() to parse OF Laurent Pinchart
@ 2020-06-14 23:58 ` Laurent Pinchart
  2020-06-16 11:28   ` Tomi Valkeinen
  2020-06-14 23:58 ` [PATCH v1 051/107] media: ti-vpe: cal: Decouple control handler from v4l2_device Laurent Pinchart
                   ` (58 subsequent siblings)
  108 siblings, 1 reply; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:58 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

Letting the v4l2_fwnode_endpoint_parse() function determine the bus type
automatically is deprecated. Set the bus type to DPHY manually as the TI
CAL only supports DPHY.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index 7f2f206f578b..af7b4fede021 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -2031,11 +2031,10 @@ static int of_cal_create_instance(struct cal_ctx *ctx, int inst)
 		goto cleanup_exit;
 	}
 
-	v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep_node), endpoint);
-
-	if (endpoint->bus_type != V4L2_MBUS_CSI2_DPHY) {
-		ctx_err(ctx, "Port:%d sub-device %pOFn is not a CSI2 device\n",
-			inst, sensor_node);
+	endpoint->bus_type = V4L2_MBUS_CSI2_DPHY;
+	ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep_node), endpoint);
+	if (ret < 0) {
+		ctx_err(ctx, "Failed to parse endpoint\n");
 		goto cleanup_exit;
 	}
 
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 051/107] media: ti-vpe: cal: Decouple control handler from v4l2_device
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (49 preceding siblings ...)
  2020-06-14 23:58 ` [PATCH v1 050/107] media: ti-vpe: cal: Fix usage of v4l2_fwnode_endpoint_parse() Laurent Pinchart
@ 2020-06-14 23:58 ` Laurent Pinchart
  2020-06-14 23:58 ` [PATCH v1 052/107] media: ti-vpe: cal: Move v4l2_device from cal_ctx to cal_dev Laurent Pinchart
                   ` (57 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:58 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

To prepare for decoupling the v4l2_device from the cal_ctx, don't set
the control handler in the v4l2_device and expect the video node to use
it automatically, but set the video node control handler directly. This
requires adding the sensor subdev controls to the control handler
manually, as that operation was performed on the v4l2_device by
v4l2_device_register_subdev().

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 34 ++++++++++++++++-------------
 1 file changed, 19 insertions(+), 15 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index af7b4fede021..60eb5e6de2b6 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -1865,6 +1865,7 @@ static const struct video_device cal_videodev = {
 
 static int cal_complete_ctx(struct cal_ctx *ctx)
 {
+	struct v4l2_ctrl_handler *hdl = &ctx->ctrl_handler;
 	struct video_device *vfd;
 	struct vb2_queue *q;
 	int ret;
@@ -1898,6 +1899,17 @@ static int cal_complete_ctx(struct cal_ctx *ctx)
 	vfd->v4l2_dev = &ctx->v4l2_dev;
 	vfd->queue = q;
 
+	/* Initialize the control handler. */
+	v4l2_ctrl_handler_init(hdl, 11);
+	v4l2_ctrl_add_handler(hdl, ctx->phy->sensor->ctrl_handler, NULL, true);
+	if (hdl->error) {
+		ctx_err(ctx, "Failed to init ctrl handler\n");
+		ret = hdl->error;
+		goto error;
+	}
+
+	vfd->ctrl_handler = hdl;
+
 	/*
 	 * Provide a mutex to v4l2 core. It will be used to protect
 	 * all fops and v4l2 ioctls.
@@ -1907,12 +1919,16 @@ static int cal_complete_ctx(struct cal_ctx *ctx)
 
 	ret = video_register_device(vfd, VFL_TYPE_VIDEO, video_nr);
 	if (ret < 0)
-		return ret;
+		goto error;
 
 	ctx_info(ctx, "V4L2 device registered as %s\n",
 		 video_device_node_name(vfd));
 
 	return 0;
+
+error:
+	v4l2_ctrl_handler_free(hdl);
+	return ret;
 }
 
 static int cal_async_bound(struct v4l2_async_notifier *notifier,
@@ -2094,7 +2110,6 @@ static int of_cal_create_instance(struct cal_ctx *ctx, int inst)
 static struct cal_ctx *cal_ctx_create(struct cal_dev *cal, int inst)
 {
 	struct cal_ctx *ctx;
-	struct v4l2_ctrl_handler *hdl;
 	int ret;
 
 	ctx = devm_kzalloc(&cal->pdev->dev, sizeof(*ctx), GFP_KERNEL);
@@ -2108,15 +2123,7 @@ static struct cal_ctx *cal_ctx_create(struct cal_dev *cal, int inst)
 		 "%s-%03d", CAL_MODULE_NAME, inst);
 	ret = v4l2_device_register(&cal->pdev->dev, &ctx->v4l2_dev);
 	if (ret)
-		goto err_exit;
-
-	hdl = &ctx->ctrl_handler;
-	ret = v4l2_ctrl_handler_init(hdl, 11);
-	if (ret) {
-		ctx_err(ctx, "Failed to init ctrl handler\n");
-		goto unreg_dev;
-	}
-	ctx->v4l2_dev.ctrl_handler = hdl;
+		return NULL;
 
 	/* Make sure Camera Core H/W register area is available */
 	ctx->phy = cal->phy[inst];
@@ -2128,15 +2135,12 @@ static struct cal_ctx *cal_ctx_create(struct cal_dev *cal, int inst)
 	ret = of_cal_create_instance(ctx, inst);
 	if (ret) {
 		ret = -EINVAL;
-		goto free_hdl;
+		goto unreg_dev;
 	}
 	return ctx;
 
-free_hdl:
-	v4l2_ctrl_handler_free(hdl);
 unreg_dev:
 	v4l2_device_unregister(&ctx->v4l2_dev);
-err_exit:
 	return NULL;
 }
 
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 052/107] media: ti-vpe: cal: Move v4l2_device from cal_ctx to cal_dev
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (50 preceding siblings ...)
  2020-06-14 23:58 ` [PATCH v1 051/107] media: ti-vpe: cal: Decouple control handler from v4l2_device Laurent Pinchart
@ 2020-06-14 23:58 ` Laurent Pinchart
  2020-06-14 23:58 ` [PATCH v1 053/107] media: ti-vpe: cal: Split video device initialization and registration Laurent Pinchart
                   ` (56 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:58 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

The v4l2_device structure is meant to represent the whole device. In the
CAL case, this corresponds to the CAL, the CAMERARX instances and the
connected sensors. There should thus be a single v4l2_device instance.
Replace the per-context instance with a global instance in the cal_dev
structure.

Don't set the v4l2_device name manually as v4l2_device_register() sets
it to a value that is suitable for the driver.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 44 ++++++++++++++---------------
 1 file changed, 22 insertions(+), 22 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index 60eb5e6de2b6..754f5af82ef6 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -289,13 +289,14 @@ struct cal_dev {
 	struct cal_camerarx	*phy[CAL_NUM_CSI2_PORTS];
 
 	struct cal_ctx		*ctx[CAL_NUM_CONTEXT];
+
+	struct v4l2_device	v4l2_dev;
 };
 
 /*
  * There is one cal_ctx structure for each camera core context.
  */
 struct cal_ctx {
-	struct v4l2_device	v4l2_dev;
 	struct v4l2_ctrl_handler ctrl_handler;
 	struct video_device	vdev;
 	struct v4l2_async_notifier notifier;
@@ -1896,7 +1897,7 @@ static int cal_complete_ctx(struct cal_ctx *ctx)
 
 	vfd = &ctx->vdev;
 	*vfd = cal_videodev;
-	vfd->v4l2_dev = &ctx->v4l2_dev;
+	vfd->v4l2_dev = &ctx->cal->v4l2_dev;
 	vfd->queue = q;
 
 	/* Initialize the control handler. */
@@ -2085,7 +2086,7 @@ static int of_cal_create_instance(struct cal_ctx *ctx, int inst)
 	}
 
 	ctx->notifier.ops = &cal_async_ops;
-	ret = v4l2_async_notifier_register(&ctx->v4l2_dev,
+	ret = v4l2_async_notifier_register(&ctx->cal->v4l2_dev,
 					   &ctx->notifier);
 	if (ret) {
 		ctx_err(ctx, "Error registering async notifier\n");
@@ -2119,12 +2120,6 @@ static struct cal_ctx *cal_ctx_create(struct cal_dev *cal, int inst)
 	/* save the cal_dev * for future ref */
 	ctx->cal = cal;
 
-	snprintf(ctx->v4l2_dev.name, sizeof(ctx->v4l2_dev.name),
-		 "%s-%03d", CAL_MODULE_NAME, inst);
-	ret = v4l2_device_register(&cal->pdev->dev, &ctx->v4l2_dev);
-	if (ret)
-		return NULL;
-
 	/* Make sure Camera Core H/W register area is available */
 	ctx->phy = cal->phy[inst];
 
@@ -2133,15 +2128,10 @@ static struct cal_ctx *cal_ctx_create(struct cal_dev *cal, int inst)
 	ctx->cport = inst;
 
 	ret = of_cal_create_instance(ctx, inst);
-	if (ret) {
-		ret = -EINVAL;
-		goto unreg_dev;
-	}
+	if (ret)
+		return NULL;
+
 	return ctx;
-
-unreg_dev:
-	v4l2_device_unregister(&ctx->v4l2_dev);
-	return NULL;
 }
 
 static const struct of_device_id cal_of_match[] = {
@@ -2242,13 +2232,21 @@ static int cal_probe(struct platform_device *pdev)
 			return PTR_ERR(cal->phy[i]);
 	}
 
+	/* Register the V4L2 device. */
+	ret = v4l2_device_register(&pdev->dev, &cal->v4l2_dev);
+	if (ret) {
+		cal_err(cal, "Failed to register V4L2 device\n");
+		return ret;
+	}
+
 	/* Create contexts. */
 	for (i = 0; i < cal_data_get_num_csi2_phy(cal); ++i)
 		cal->ctx[i] = cal_ctx_create(cal, i);
 
 	if (!cal->ctx[0] && !cal->ctx[1]) {
 		cal_err(cal, "Neither port is configured, no point in staying up\n");
-		return -ENODEV;
+		ret = -ENODEV;
+		goto error_v4l2;
 	}
 
 	vb2_dma_contig_set_max_seg_size(&pdev->dev, DMA_BIT_MASK(32));
@@ -2257,14 +2255,14 @@ static int cal_probe(struct platform_device *pdev)
 	pm_runtime_enable(&pdev->dev);
 	ret = pm_runtime_get_sync(&pdev->dev);
 	if (ret)
-		goto runtime_disable;
+		goto error_pm_runtime;
 
 	cal_get_hwinfo(cal);
 	pm_runtime_put_sync(&pdev->dev);
 
 	return 0;
 
-runtime_disable:
+error_pm_runtime:
 	vb2_dma_contig_clear_max_seg_size(&pdev->dev);
 
 	pm_runtime_disable(&pdev->dev);
@@ -2274,10 +2272,11 @@ static int cal_probe(struct platform_device *pdev)
 			v4l2_async_notifier_unregister(&ctx->notifier);
 			v4l2_async_notifier_cleanup(&ctx->notifier);
 			v4l2_ctrl_handler_free(&ctx->ctrl_handler);
-			v4l2_device_unregister(&ctx->v4l2_dev);
 		}
 	}
 
+error_v4l2:
+	v4l2_device_unregister(&cal->v4l2_dev);
 	return ret;
 }
 
@@ -2300,11 +2299,12 @@ static int cal_remove(struct platform_device *pdev)
 			v4l2_async_notifier_unregister(&ctx->notifier);
 			v4l2_async_notifier_cleanup(&ctx->notifier);
 			v4l2_ctrl_handler_free(&ctx->ctrl_handler);
-			v4l2_device_unregister(&ctx->v4l2_dev);
 			video_unregister_device(&ctx->vdev);
 		}
 	}
 
+	v4l2_device_unregister(&cal->v4l2_dev);
+
 	pm_runtime_put_sync(&pdev->dev);
 	pm_runtime_disable(&pdev->dev);
 
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 053/107] media: ti-vpe: cal: Split video device initialization and registration
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (51 preceding siblings ...)
  2020-06-14 23:58 ` [PATCH v1 052/107] media: ti-vpe: cal: Move v4l2_device from cal_ctx to cal_dev Laurent Pinchart
@ 2020-06-14 23:58 ` Laurent Pinchart
  2020-06-14 23:58 ` [PATCH v1 054/107] media: ti-vpe: cal: Add context V4L2 cleanup and unregister functions Laurent Pinchart
                   ` (55 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:58 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

There's no need to delay most of the video device initialization until
the sensor subdevs are bound. Split the initialization and registration,
and perform the initialization when creating the context.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 70 +++++++++++++++++------------
 1 file changed, 42 insertions(+), 28 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index 754f5af82ef6..52f4798024ad 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -1850,7 +1850,7 @@ static const struct vb2_ops cal_video_qops = {
 };
 
 /* ------------------------------------------------------------------
- *	Initialization and module stuff
+ *	V4L2 Initialization and Registration
  * ------------------------------------------------------------------
  */
 
@@ -1864,11 +1864,36 @@ static const struct video_device cal_videodev = {
 			  V4L2_CAP_READWRITE,
 };
 
-static int cal_complete_ctx(struct cal_ctx *ctx)
+static int cal_ctx_v4l2_register(struct cal_ctx *ctx)
 {
 	struct v4l2_ctrl_handler *hdl = &ctx->ctrl_handler;
-	struct video_device *vfd;
-	struct vb2_queue *q;
+	struct video_device *vfd = &ctx->vdev;
+	int ret;
+
+	ret = v4l2_ctrl_add_handler(hdl, ctx->phy->sensor->ctrl_handler, NULL,
+				    true);
+	if (ret < 0) {
+		ctx_err(ctx, "Failed to add sensor ctrl handler\n");
+		return ret;
+	}
+
+	ret = video_register_device(vfd, VFL_TYPE_VIDEO, video_nr);
+	if (ret < 0) {
+		ctx_err(ctx, "Failed to register video device\n");
+		return ret;
+	}
+
+	ctx_info(ctx, "V4L2 device registered as %s\n",
+		 video_device_node_name(vfd));
+
+	return 0;
+}
+
+static int cal_ctx_v4l2_init(struct cal_ctx *ctx)
+{
+	struct v4l2_ctrl_handler *hdl = &ctx->ctrl_handler;
+	struct video_device *vfd = &ctx->vdev;
+	struct vb2_queue *q = &ctx->vb_vidq;
 	int ret;
 
 	/* initialize locks */
@@ -1876,7 +1901,6 @@ static int cal_complete_ctx(struct cal_ctx *ctx)
 	mutex_init(&ctx->mutex);
 
 	/* initialize queue */
-	q = &ctx->vb_vidq;
 	q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 	q->io_modes = VB2_MMAP | VB2_DMABUF | VB2_READ;
 	q->drv_priv = ctx;
@@ -1895,18 +1919,15 @@ static int cal_complete_ctx(struct cal_ctx *ctx)
 	/* init video dma queues */
 	INIT_LIST_HEAD(&ctx->vidq.active);
 
-	vfd = &ctx->vdev;
 	*vfd = cal_videodev;
 	vfd->v4l2_dev = &ctx->cal->v4l2_dev;
 	vfd->queue = q;
 
 	/* Initialize the control handler. */
-	v4l2_ctrl_handler_init(hdl, 11);
-	v4l2_ctrl_add_handler(hdl, ctx->phy->sensor->ctrl_handler, NULL, true);
-	if (hdl->error) {
+	ret = v4l2_ctrl_handler_init(hdl, 11);
+	if (ret < 0) {
 		ctx_err(ctx, "Failed to init ctrl handler\n");
-		ret = hdl->error;
-		goto error;
+		return ret;
 	}
 
 	vfd->ctrl_handler = hdl;
@@ -1918,20 +1939,14 @@ static int cal_complete_ctx(struct cal_ctx *ctx)
 	vfd->lock = &ctx->mutex;
 	video_set_drvdata(vfd, ctx);
 
-	ret = video_register_device(vfd, VFL_TYPE_VIDEO, video_nr);
-	if (ret < 0)
-		goto error;
-
-	ctx_info(ctx, "V4L2 device registered as %s\n",
-		 video_device_node_name(vfd));
-
 	return 0;
-
-error:
-	v4l2_ctrl_handler_free(hdl);
-	return ret;
 }
 
+/* ------------------------------------------------------------------
+ *	Initialization and module stuff
+ * ------------------------------------------------------------------
+ */
+
 static int cal_async_bound(struct v4l2_async_notifier *notifier,
 			   struct v4l2_subdev *subdev,
 			   struct v4l2_async_subdev *asd)
@@ -1986,7 +2001,7 @@ static int cal_async_bound(struct v4l2_async_notifier *notifier,
 		return -EINVAL;
 	}
 
-	cal_complete_ctx(ctx);
+	cal_ctx_v4l2_register(ctx);
 
 	return 0;
 }
@@ -2117,16 +2132,15 @@ static struct cal_ctx *cal_ctx_create(struct cal_dev *cal, int inst)
 	if (!ctx)
 		return NULL;
 
-	/* save the cal_dev * for future ref */
 	ctx->cal = cal;
-
-	/* Make sure Camera Core H/W register area is available */
 	ctx->phy = cal->phy[inst];
-
-	/* Store the instance id */
 	ctx->index = inst;
 	ctx->cport = inst;
 
+	ret = cal_ctx_v4l2_init(ctx);
+	if (ret)
+		return NULL;
+
 	ret = of_cal_create_instance(ctx, inst);
 	if (ret)
 		return NULL;
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 054/107] media: ti-vpe: cal: Add context V4L2 cleanup and unregister functions
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (52 preceding siblings ...)
  2020-06-14 23:58 ` [PATCH v1 053/107] media: ti-vpe: cal: Split video device initialization and registration Laurent Pinchart
@ 2020-06-14 23:58 ` Laurent Pinchart
  2020-06-14 23:58 ` [PATCH v1 055/107] media: ti-vpe: cal: Unregister video device before cleanup Laurent Pinchart
                   ` (54 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:58 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

Create cal_ctx_v4l2_unregister() and cal_ctx_v4l2_cleanup() functions to
unregister and cleanup the V4L2-related objects from the context, and
call them in cal_remove() and in the error path of cal_probe().

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 16 +++++++++++++---
 1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index 52f4798024ad..1af64c144653 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -1889,6 +1889,11 @@ static int cal_ctx_v4l2_register(struct cal_ctx *ctx)
 	return 0;
 }
 
+static void cal_ctx_v4l2_unregister(struct cal_ctx *ctx)
+{
+	video_unregister_device(&ctx->vdev);
+}
+
 static int cal_ctx_v4l2_init(struct cal_ctx *ctx)
 {
 	struct v4l2_ctrl_handler *hdl = &ctx->ctrl_handler;
@@ -1942,6 +1947,11 @@ static int cal_ctx_v4l2_init(struct cal_ctx *ctx)
 	return 0;
 }
 
+static void cal_ctx_v4l2_cleanup(struct cal_ctx *ctx)
+{
+	v4l2_ctrl_handler_free(&ctx->ctrl_handler);
+}
+
 /* ------------------------------------------------------------------
  *	Initialization and module stuff
  * ------------------------------------------------------------------
@@ -2285,7 +2295,7 @@ static int cal_probe(struct platform_device *pdev)
 		if (ctx) {
 			v4l2_async_notifier_unregister(&ctx->notifier);
 			v4l2_async_notifier_cleanup(&ctx->notifier);
-			v4l2_ctrl_handler_free(&ctx->ctrl_handler);
+			cal_ctx_v4l2_cleanup(ctx);
 		}
 	}
 
@@ -2312,8 +2322,8 @@ static int cal_remove(struct platform_device *pdev)
 			cal_camerarx_disable(ctx->phy);
 			v4l2_async_notifier_unregister(&ctx->notifier);
 			v4l2_async_notifier_cleanup(&ctx->notifier);
-			v4l2_ctrl_handler_free(&ctx->ctrl_handler);
-			video_unregister_device(&ctx->vdev);
+			cal_ctx_v4l2_cleanup(ctx);
+			cal_ctx_v4l2_unregister(ctx);
 		}
 	}
 
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 055/107] media: ti-vpe: cal: Unregister video device before cleanup
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (53 preceding siblings ...)
  2020-06-14 23:58 ` [PATCH v1 054/107] media: ti-vpe: cal: Add context V4L2 cleanup and unregister functions Laurent Pinchart
@ 2020-06-14 23:58 ` Laurent Pinchart
  2020-06-23 11:01   ` Tomi Valkeinen
  2020-06-14 23:58 ` [PATCH v1 056/107] media: ti-vpe: cal: Add cal_camerarx_destroy() to cleanup CAMERARX Laurent Pinchart
                   ` (53 subsequent siblings)
  108 siblings, 1 reply; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:58 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

In cal_remove(), unregister the video devices as the first operation,
before cleaning up the V4L2 objects, to avoid user-after-free. This
isn't a complete solution yet, as video nodes can be kept open across
unregistration.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index 1af64c144653..b8c7ad8e39cd 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -2319,11 +2319,11 @@ static int cal_remove(struct platform_device *pdev)
 		if (ctx) {
 			ctx_dbg(1, ctx, "unregistering %s\n",
 				video_device_node_name(&ctx->vdev));
-			cal_camerarx_disable(ctx->phy);
-			v4l2_async_notifier_unregister(&ctx->notifier);
-			v4l2_async_notifier_cleanup(&ctx->notifier);
-			cal_ctx_v4l2_cleanup(ctx);
 			cal_ctx_v4l2_unregister(ctx);
+			cal_camerarx_disable(ctx->phy);
+			v4l2_async_notifier_unregister(&ctx->notifier);
+			v4l2_async_notifier_cleanup(&ctx->notifier);
+			cal_ctx_v4l2_cleanup(ctx);
 		}
 	}
 
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 056/107] media: ti-vpe: cal: Add cal_camerarx_destroy() to cleanup CAMERARX
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (54 preceding siblings ...)
  2020-06-14 23:58 ` [PATCH v1 055/107] media: ti-vpe: cal: Unregister video device before cleanup Laurent Pinchart
@ 2020-06-14 23:58 ` Laurent Pinchart
  2020-06-17 10:43   ` Kieran Bingham
  2020-06-14 23:58 ` [PATCH v1 057/107] media: ti-vpe: cal: Move DT parsing to CAMERARX Laurent Pinchart
                   ` (52 subsequent siblings)
  108 siblings, 1 reply; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:58 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

The cal_camerarx_create() function allocates resources with devm_*, and
thus doesn't need any manual cleanup. Those won't hold true for long, as
we will need to store resources that have no devm_* allocation variant
in cal_camerarx. Furthermore, devm_kzalloc() is the wrong memory
allocation API for structures that can be accessed from userspace, as
device nodes can be kept open across device removal.

Add a cal_camerarx_destroy() function to destroy a CAMERARX instance
explicitly, and switch to kzalloc() for memory allocation.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 35 ++++++++++++++++++++++++-----
 1 file changed, 29 insertions(+), 6 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index b8c7ad8e39cd..c9fef333c532 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -931,7 +931,7 @@ static struct cal_camerarx *cal_camerarx_create(struct cal_dev *cal,
 	struct cal_camerarx *phy;
 	int ret;
 
-	phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL);
+	phy = kzalloc(sizeof(*phy), GFP_KERNEL);
 	if (!phy)
 		return ERR_PTR(-ENOMEM);
 
@@ -946,7 +946,8 @@ static struct cal_camerarx *cal_camerarx_create(struct cal_dev *cal,
 	phy->base = devm_ioremap_resource(&pdev->dev, phy->res);
 	if (IS_ERR(phy->base)) {
 		cal_err(cal, "failed to ioremap\n");
-		return ERR_CAST(phy->base);
+		ret = PTR_ERR(phy->base);
+		goto error;
 	}
 
 	cal_dbg(1, cal, "ioresource %s at %pa - %pa\n",
@@ -954,9 +955,21 @@ static struct cal_camerarx *cal_camerarx_create(struct cal_dev *cal,
 
 	ret = cal_camerarx_regmap_init(cal, phy);
 	if (ret)
-		return ERR_PTR(ret);
+		goto error;
 
 	return phy;
+
+error:
+	kfree(phy);
+	return ERR_PTR(ret);
+}
+
+static void cal_camerarx_destroy(struct cal_camerarx *phy)
+{
+	if (!phy)
+		return;
+
+	kfree(phy);
 }
 
 static int cal_camerarx_init_regmap(struct cal_dev *cal)
@@ -2252,15 +2265,17 @@ static int cal_probe(struct platform_device *pdev)
 	/* Create CAMERARX PHYs. */
 	for (i = 0; i < cal_data_get_num_csi2_phy(cal); ++i) {
 		cal->phy[i] = cal_camerarx_create(cal, i);
-		if (IS_ERR(cal->phy[i]))
-			return PTR_ERR(cal->phy[i]);
+		if (IS_ERR(cal->phy[i])) {
+			ret = PTR_ERR(cal->phy[i]);
+			goto error_camerarx;
+		}
 	}
 
 	/* Register the V4L2 device. */
 	ret = v4l2_device_register(&pdev->dev, &cal->v4l2_dev);
 	if (ret) {
 		cal_err(cal, "Failed to register V4L2 device\n");
-		return ret;
+		goto error_camerarx;
 	}
 
 	/* Create contexts. */
@@ -2301,6 +2316,11 @@ static int cal_probe(struct platform_device *pdev)
 
 error_v4l2:
 	v4l2_device_unregister(&cal->v4l2_dev);
+
+error_camerarx:
+	for (i = 0; i < ARRAY_SIZE(cal->phy); i++)
+		cal_camerarx_destroy(cal->phy[i]);
+
 	return ret;
 }
 
@@ -2329,6 +2349,9 @@ static int cal_remove(struct platform_device *pdev)
 
 	v4l2_device_unregister(&cal->v4l2_dev);
 
+	for (i = 0; i < ARRAY_SIZE(cal->phy); i++)
+		cal_camerarx_destroy(cal->phy[i]);
+
 	pm_runtime_put_sync(&pdev->dev);
 	pm_runtime_disable(&pdev->dev);
 
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 057/107] media: ti-vpe: cal: Move DT parsing to CAMERARX
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (55 preceding siblings ...)
  2020-06-14 23:58 ` [PATCH v1 056/107] media: ti-vpe: cal: Add cal_camerarx_destroy() to cleanup CAMERARX Laurent Pinchart
@ 2020-06-14 23:58 ` Laurent Pinchart
  2020-06-14 23:58 ` [PATCH v1 058/107] media: ti-vpe: cal: Use ARRAY_SIZE to replace numerical value Laurent Pinchart
                   ` (51 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:58 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

The DT port nodes corresponding to the CSI-2 inputs belong to the
CAMERARX instances. Move parsing of the DT properties to a new
cal_camerarx_parse_dt() function, called by cal_camerarx_create().

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 156 ++++++++++++++++------------
 1 file changed, 87 insertions(+), 69 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index c9fef333c532..af142b00ee0b 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -268,6 +268,7 @@ struct cal_camerarx {
 	unsigned int		instance;
 
 	struct v4l2_fwnode_endpoint	endpoint;
+	struct device_node	*sensor_node;
 	struct v4l2_subdev	*sensor;
 	unsigned int		external_rate;
 };
@@ -924,6 +925,68 @@ static int cal_camerarx_regmap_init(struct cal_dev *cal,
 	return 0;
 }
 
+static int cal_camerarx_parse_dt(struct cal_camerarx *phy)
+{
+	struct v4l2_fwnode_endpoint *endpoint = &phy->endpoint;
+	struct platform_device *pdev = phy->cal->pdev;
+	struct device_node *ep_node;
+	char data_lanes[V4L2_FWNODE_CSI2_MAX_DATA_LANES * 2];
+	unsigned int i;
+	int ret;
+
+	/*
+	 * Find the endpoint node for the port corresponding to the PHY
+	 * instance, and parse its CSI-2-related properties.
+	 */
+	ep_node = of_graph_get_endpoint_by_regs(pdev->dev.of_node,
+						phy->instance, 0);
+	if (!ep_node) {
+		phy_dbg(3, phy, "Can't get endpoint\n");
+		return -EINVAL;
+	}
+
+	endpoint->bus_type = V4L2_MBUS_CSI2_DPHY;
+	ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep_node), endpoint);
+	if (ret < 0) {
+		phy_err(phy, "Failed to parse endpoint\n");
+		goto done;
+	}
+
+	for (i = 0; i < endpoint->bus.mipi_csi2.num_data_lanes; i++) {
+		unsigned int lane = endpoint->bus.mipi_csi2.data_lanes[i];
+
+		if (lane > 4) {
+			phy_err(phy, "Invalid position %u for data lane %u\n",
+				lane, i);
+			ret = -EINVAL;
+			goto done;
+		}
+
+		data_lanes[i*2] = '0' + lane;
+		data_lanes[i*2+1] = ' ';
+	}
+
+	data_lanes[i*2-1] = '\0';
+
+	phy_dbg(3, phy,
+		"CSI-2 bus: clock lane <%u>, data lanes <%s>, flags 0x%08x\n",
+		endpoint->bus.mipi_csi2.clock_lane, data_lanes,
+		endpoint->bus.mipi_csi2.flags);
+
+	/* Retrieve the connected device and store it for later use. */
+	phy->sensor_node = of_graph_get_remote_port_parent(ep_node);
+	if (!phy->sensor_node) {
+		phy_dbg(3, phy, "Can't get remote parent\n");
+		goto done;
+	}
+
+	phy_dbg(1, phy, "Found connected device %pOFn\n", phy->sensor_node);
+
+done:
+	of_node_put(ep_node);
+	return ret;
+}
+
 static struct cal_camerarx *cal_camerarx_create(struct cal_dev *cal,
 						unsigned int instance)
 {
@@ -957,6 +1020,10 @@ static struct cal_camerarx *cal_camerarx_create(struct cal_dev *cal,
 	if (ret)
 		goto error;
 
+	ret = cal_camerarx_parse_dt(phy);
+	if (ret)
+		goto error;
+
 	return phy;
 
 error:
@@ -969,6 +1036,7 @@ static void cal_camerarx_destroy(struct cal_camerarx *phy)
 	if (!phy)
 		return;
 
+	of_node_put(phy->sensor_node);
 	kfree(phy);
 }
 
@@ -1966,7 +2034,7 @@ static void cal_ctx_v4l2_cleanup(struct cal_ctx *ctx)
 }
 
 /* ------------------------------------------------------------------
- *	Initialization and module stuff
+ *	Asynchronous V4L2 subdev binding
  * ------------------------------------------------------------------
  */
 
@@ -2065,87 +2133,37 @@ static const struct v4l2_async_notifier_operations cal_async_ops = {
 
 static int of_cal_create_instance(struct cal_ctx *ctx, int inst)
 {
-	struct platform_device *pdev = ctx->cal->pdev;
-	struct device_node *ep_node, *sensor_node;
-	struct v4l2_fwnode_endpoint *endpoint;
 	struct v4l2_async_subdev *asd;
-	int ret = -EINVAL, lane;
-
-	endpoint = &ctx->phy->endpoint;
-
-	ctx_dbg(3, ctx, "Getting endpoint for port@%d\n", inst);
-	ep_node = of_graph_get_endpoint_by_regs(pdev->dev.of_node, inst, 0);
-	if (!ep_node) {
-		ctx_dbg(3, ctx, "Can't get endpoint\n");
-		return -EINVAL;
-	}
-
-	sensor_node = of_graph_get_remote_port_parent(ep_node);
-	if (!sensor_node) {
-		ctx_dbg(3, ctx, "Can't get remote parent\n");
-		goto cleanup_exit;
-	}
-
-	endpoint->bus_type = V4L2_MBUS_CSI2_DPHY;
-	ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep_node), endpoint);
-	if (ret < 0) {
-		ctx_err(ctx, "Failed to parse endpoint\n");
-		goto cleanup_exit;
-	}
-
-	ctx_dbg(3, ctx, "Port:%d v4l2-endpoint: CSI2\n", inst);
-	ctx_dbg(3, ctx, "flags=0x%08x\n", endpoint->bus.mipi_csi2.flags);
-	ctx_dbg(3, ctx, "clock_lane=%d\n", endpoint->bus.mipi_csi2.clock_lane);
-	ctx_dbg(3, ctx, "num_data_lanes=%d\n",
-		endpoint->bus.mipi_csi2.num_data_lanes);
-	ctx_dbg(3, ctx, "data_lanes= <\n");
-	for (lane = 0; lane < endpoint->bus.mipi_csi2.num_data_lanes; lane++)
-		ctx_dbg(3, ctx, "\t%d\n",
-			endpoint->bus.mipi_csi2.data_lanes[lane]);
-	ctx_dbg(3, ctx, "\t>\n");
-
-	ctx_dbg(1, ctx, "Port: %d found sub-device %pOFn\n",
-		inst, sensor_node);
+	struct fwnode_handle *fwnode;
+	int ret;
 
 	v4l2_async_notifier_init(&ctx->notifier);
-
-	asd = kzalloc(sizeof(*asd), GFP_KERNEL);
-	if (!asd)
-		goto cleanup_exit;
-
-	asd->match_type = V4L2_ASYNC_MATCH_FWNODE;
-	asd->match.fwnode = of_fwnode_handle(sensor_node);
-
-	ret = v4l2_async_notifier_add_subdev(&ctx->notifier, asd);
-	if (ret) {
-		ctx_err(ctx, "Error adding asd\n");
-		kfree(asd);
-		goto cleanup_exit;
-	}
-
 	ctx->notifier.ops = &cal_async_ops;
+
+	fwnode = of_fwnode_handle(ctx->phy->sensor_node);
+	asd = v4l2_async_notifier_add_fwnode_subdev(&ctx->notifier, fwnode,
+						    sizeof(*asd));
+	if (IS_ERR(asd)) {
+		ctx_err(ctx, "Failed to add subdev to notifier\n");
+		return PTR_ERR(asd);
+	}
+
 	ret = v4l2_async_notifier_register(&ctx->cal->v4l2_dev,
 					   &ctx->notifier);
 	if (ret) {
 		ctx_err(ctx, "Error registering async notifier\n");
 		v4l2_async_notifier_cleanup(&ctx->notifier);
-		ret = -EINVAL;
+		return ret;
 	}
 
-	/*
-	 * On success we need to keep reference on sensor_node, or
-	 * if notifier_cleanup was called above, sensor_node was
-	 * already put.
-	 */
-	sensor_node = NULL;
-
-cleanup_exit:
-	of_node_put(sensor_node);
-	of_node_put(ep_node);
-
-	return ret;
+	return 0;
 }
 
+/* ------------------------------------------------------------------
+ *	Initialization and module stuff
+ * ------------------------------------------------------------------
+ */
+
 static struct cal_ctx *cal_ctx_create(struct cal_dev *cal, int inst)
 {
 	struct cal_ctx *ctx;
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 058/107] media: ti-vpe: cal: Use ARRAY_SIZE to replace numerical value
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (56 preceding siblings ...)
  2020-06-14 23:58 ` [PATCH v1 057/107] media: ti-vpe: cal: Move DT parsing to CAMERARX Laurent Pinchart
@ 2020-06-14 23:58 ` Laurent Pinchart
  2020-06-14 23:58 ` [PATCH v1 059/107] media: ti-vpe: cal: Move all sensor-related init to .bound() notifier Laurent Pinchart
                   ` (50 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:58 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

Use ARRAY_SIZE(cal->ctx) to iterate over the cal->ctx array instead of
using the numerical value from the CAL_NUM_CONTEXT macro (or, worse,
hardcoding the value 2). This will allow reworking contexts with less
changes in the code.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index af142b00ee0b..ca8aa630b9b3 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -1305,7 +1305,7 @@ static irqreturn_t cal_irq(int irq_cal, void *data)
 		/* Clear Interrupt status */
 		reg_write(cal, CAL_HL_IRQSTATUS(1), status);
 
-		for (i = 0; i < 2; ++i) {
+		for (i = 0; i < ARRAY_SIZE(cal->ctx); ++i) {
 			if (isportirqset(status, i)) {
 				ctx = cal->ctx[i];
 
@@ -1326,7 +1326,7 @@ static irqreturn_t cal_irq(int irq_cal, void *data)
 		/* Clear Interrupt status */
 		reg_write(cal, CAL_HL_IRQSTATUS(2), status);
 
-		for (i = 0; i < 2; ++i) {
+		for (i = 0; i < ARRAY_SIZE(cal->ctx); ++i) {
 			if (isportirqset(status, i)) {
 				ctx = cal->ctx[i];
 				dma_q = &ctx->vidq;
@@ -2323,7 +2323,7 @@ static int cal_probe(struct platform_device *pdev)
 	vb2_dma_contig_clear_max_seg_size(&pdev->dev);
 
 	pm_runtime_disable(&pdev->dev);
-	for (i = 0; i < CAL_NUM_CONTEXT; i++) {
+	for (i = 0; i < ARRAY_SIZE(cal->ctx); i++) {
 		ctx = cal->ctx[i];
 		if (ctx) {
 			v4l2_async_notifier_unregister(&ctx->notifier);
@@ -2352,7 +2352,7 @@ static int cal_remove(struct platform_device *pdev)
 
 	pm_runtime_get_sync(&pdev->dev);
 
-	for (i = 0; i < CAL_NUM_CONTEXT; i++) {
+	for (i = 0; i < ARRAY_SIZE(cal->ctx); i++) {
 		ctx = cal->ctx[i];
 		if (ctx) {
 			ctx_dbg(1, ctx, "unregistering %s\n",
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 059/107] media: ti-vpe: cal: Move all sensor-related init to .bound() notifier
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (57 preceding siblings ...)
  2020-06-14 23:58 ` [PATCH v1 058/107] media: ti-vpe: cal: Use ARRAY_SIZE to replace numerical value Laurent Pinchart
@ 2020-06-14 23:58 ` Laurent Pinchart
  2020-06-14 23:58 ` [PATCH v1 060/107] media: ti-vpe: cal: Allow multiple contexts per subdev notifier Laurent Pinchart
                   ` (49 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:58 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

The initialization of the context based on the connected sensor is split
between the async notifier .bound() and .complete() operations. Move it
all to a separate function and call it from .bound() operation to
prepare for the move of the notifiers from the contexts to the cal_dev.
Only V4L2 registration is kept in the .complete() operation.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 132 ++++++++++++++--------------
 1 file changed, 68 insertions(+), 64 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index ca8aa630b9b3..52f6d4b68169 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -1975,6 +1975,72 @@ static void cal_ctx_v4l2_unregister(struct cal_ctx *ctx)
 	video_unregister_device(&ctx->vdev);
 }
 
+static int cal_ctx_v4l2_init_formats(struct cal_ctx *ctx)
+{
+	struct v4l2_subdev_mbus_code_enum mbus_code;
+	struct v4l2_mbus_framefmt mbus_fmt;
+	const struct cal_fmt *fmt;
+	unsigned int i, j, k;
+	int ret = 0;
+
+	/* Enumerate sub device formats and enable all matching local formats */
+	ctx->num_active_fmt = 0;
+	for (j = 0, i = 0; ret != -EINVAL; ++j) {
+
+		memset(&mbus_code, 0, sizeof(mbus_code));
+		mbus_code.index = j;
+		mbus_code.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+		ret = v4l2_subdev_call(ctx->phy->sensor, pad, enum_mbus_code,
+				       NULL, &mbus_code);
+		if (ret)
+			continue;
+
+		ctx_dbg(2, ctx,
+			"subdev %s: code: %04x idx: %u\n",
+			ctx->phy->sensor->name, mbus_code.code, j);
+
+		for (k = 0; k < ARRAY_SIZE(cal_formats); k++) {
+			const struct cal_fmt *fmt = &cal_formats[k];
+
+			if (mbus_code.code == fmt->code) {
+				ctx->active_fmt[i] = fmt;
+				ctx_dbg(2, ctx,
+					"matched fourcc: %s: code: %04x idx: %u\n",
+					fourcc_to_str(fmt->fourcc),
+					fmt->code, i);
+				ctx->num_active_fmt = ++i;
+			}
+		}
+	}
+
+	if (i == 0) {
+		ctx_err(ctx, "No suitable format reported by subdev %s\n",
+			ctx->phy->sensor->name);
+		return -EINVAL;
+	}
+
+	ret = __subdev_get_format(ctx, &mbus_fmt);
+	if (ret)
+		return ret;
+
+	fmt = find_format_by_code(ctx, mbus_fmt.code);
+	if (!fmt) {
+		ctx_dbg(3, ctx, "mbus code format (0x%08x) not found.\n",
+			mbus_fmt.code);
+		return -EINVAL;
+	}
+
+	/* Save current subdev format */
+	v4l2_fill_pix_format(&ctx->v_fmt.fmt.pix, &mbus_fmt);
+	ctx->v_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	ctx->v_fmt.fmt.pix.pixelformat  = fmt->fourcc;
+	cal_calc_format_size(ctx, fmt, &ctx->v_fmt);
+	ctx->fmt = fmt;
+	ctx->m_fmt = mbus_fmt;
+
+	return 0;
+}
+
 static int cal_ctx_v4l2_init(struct cal_ctx *ctx)
 {
 	struct v4l2_ctrl_handler *hdl = &ctx->ctrl_handler;
@@ -2043,9 +2109,6 @@ static int cal_async_bound(struct v4l2_async_notifier *notifier,
 			   struct v4l2_async_subdev *asd)
 {
 	struct cal_ctx *ctx = notifier_to_ctx(notifier);
-	struct v4l2_subdev_mbus_code_enum mbus_code;
-	unsigned int i, j, k;
-	int ret = 0;
 
 	if (ctx->phy->sensor) {
 		ctx_info(ctx, "Rejecting subdev %s (Already set!!)",
@@ -2056,73 +2119,14 @@ static int cal_async_bound(struct v4l2_async_notifier *notifier,
 	ctx->phy->sensor = subdev;
 	ctx_dbg(1, ctx, "Using sensor %s for capture\n", subdev->name);
 
-	/* Enumerate sub device formats and enable all matching local formats */
-	ctx->num_active_fmt = 0;
-	for (j = 0, i = 0; ret != -EINVAL; ++j) {
-
-		memset(&mbus_code, 0, sizeof(mbus_code));
-		mbus_code.index = j;
-		mbus_code.which = V4L2_SUBDEV_FORMAT_ACTIVE;
-		ret = v4l2_subdev_call(subdev, pad, enum_mbus_code,
-				       NULL, &mbus_code);
-		if (ret)
-			continue;
-
-		ctx_dbg(2, ctx,
-			"subdev %s: code: %04x idx: %u\n",
-			subdev->name, mbus_code.code, j);
-
-		for (k = 0; k < ARRAY_SIZE(cal_formats); k++) {
-			const struct cal_fmt *fmt = &cal_formats[k];
-
-			if (mbus_code.code == fmt->code) {
-				ctx->active_fmt[i] = fmt;
-				ctx_dbg(2, ctx,
-					"matched fourcc: %s: code: %04x idx: %u\n",
-					fourcc_to_str(fmt->fourcc),
-					fmt->code, i);
-				ctx->num_active_fmt = ++i;
-			}
-		}
-	}
-
-	if (i == 0) {
-		ctx_err(ctx, "No suitable format reported by subdev %s\n",
-			subdev->name);
-		return -EINVAL;
-	}
-
-	cal_ctx_v4l2_register(ctx);
-
-	return 0;
+	return cal_ctx_v4l2_init_formats(ctx);
 }
 
 static int cal_async_complete(struct v4l2_async_notifier *notifier)
 {
 	struct cal_ctx *ctx = notifier_to_ctx(notifier);
-	const struct cal_fmt *fmt;
-	struct v4l2_mbus_framefmt mbus_fmt;
-	int ret;
-
-	ret = __subdev_get_format(ctx, &mbus_fmt);
-	if (ret)
-		return ret;
-
-	fmt = find_format_by_code(ctx, mbus_fmt.code);
-	if (!fmt) {
-		ctx_dbg(3, ctx, "mbus code format (0x%08x) not found.\n",
-			mbus_fmt.code);
-		return -EINVAL;
-	}
-
-	/* Save current subdev format */
-	v4l2_fill_pix_format(&ctx->v_fmt.fmt.pix, &mbus_fmt);
-	ctx->v_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-	ctx->v_fmt.fmt.pix.pixelformat  = fmt->fourcc;
-	cal_calc_format_size(ctx, fmt, &ctx->v_fmt);
-	ctx->fmt = fmt;
-	ctx->m_fmt = mbus_fmt;
 
+	cal_ctx_v4l2_register(ctx);
 	return 0;
 }
 
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 060/107] media: ti-vpe: cal: Allow multiple contexts per subdev notifier
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (58 preceding siblings ...)
  2020-06-14 23:58 ` [PATCH v1 059/107] media: ti-vpe: cal: Move all sensor-related init to .bound() notifier Laurent Pinchart
@ 2020-06-14 23:58 ` Laurent Pinchart
  2020-06-14 23:58 ` [PATCH v1 061/107] media: ti-vpe: cal: Move async notifiers from contexts to cal_dev Laurent Pinchart
                   ` (48 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:58 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

The subdev notifier handling assumes a 1:1 mapping between CAL contexts
and notifiers. To prepare for merging the multiple notifiers into a
single one, retrieve the CAL context from the async subdev structure
instead of from the notifier.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index 52f6d4b68169..0ae88f3593c6 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -2104,11 +2104,22 @@ static void cal_ctx_v4l2_cleanup(struct cal_ctx *ctx)
  * ------------------------------------------------------------------
  */
 
+struct cal_v4l2_async_subdev {
+	struct v4l2_async_subdev asd;
+	struct cal_ctx *ctx;
+};
+
+static inline struct cal_v4l2_async_subdev *
+to_cal_asd(struct v4l2_async_subdev *asd)
+{
+	return container_of(asd, struct cal_v4l2_async_subdev, asd);
+}
+
 static int cal_async_bound(struct v4l2_async_notifier *notifier,
 			   struct v4l2_subdev *subdev,
 			   struct v4l2_async_subdev *asd)
 {
-	struct cal_ctx *ctx = notifier_to_ctx(notifier);
+	struct cal_ctx *ctx = to_cal_asd(asd)->ctx;
 
 	if (ctx->phy->sensor) {
 		ctx_info(ctx, "Rejecting subdev %s (Already set!!)",
@@ -2137,6 +2148,7 @@ static const struct v4l2_async_notifier_operations cal_async_ops = {
 
 static int of_cal_create_instance(struct cal_ctx *ctx, int inst)
 {
+	struct cal_v4l2_async_subdev *casd;
 	struct v4l2_async_subdev *asd;
 	struct fwnode_handle *fwnode;
 	int ret;
@@ -2152,6 +2164,9 @@ static int of_cal_create_instance(struct cal_ctx *ctx, int inst)
 		return PTR_ERR(asd);
 	}
 
+	casd = to_cal_asd(asd);
+	casd->ctx = ctx;
+
 	ret = v4l2_async_notifier_register(&ctx->cal->v4l2_dev,
 					   &ctx->notifier);
 	if (ret) {
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 061/107] media: ti-vpe: cal: Move async notifiers from contexts to cal_dev
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (59 preceding siblings ...)
  2020-06-14 23:58 ` [PATCH v1 060/107] media: ti-vpe: cal: Allow multiple contexts per subdev notifier Laurent Pinchart
@ 2020-06-14 23:58 ` Laurent Pinchart
  2020-06-14 23:58 ` [PATCH v1 062/107] media: ti-vpe: cal: Replace context with phy in async notifier entries Laurent Pinchart
                   ` (47 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:58 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

There's no need to create one async notifier per CAL context. Merge them
all in a single notifier, stored in cal_dev.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 119 +++++++++++++++++-----------
 1 file changed, 72 insertions(+), 47 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index 0ae88f3593c6..1c9a0369d025 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -292,6 +292,7 @@ struct cal_dev {
 	struct cal_ctx		*ctx[CAL_NUM_CONTEXT];
 
 	struct v4l2_device	v4l2_dev;
+	struct v4l2_async_notifier notifier;
 };
 
 /*
@@ -300,7 +301,6 @@ struct cal_dev {
 struct cal_ctx {
 	struct v4l2_ctrl_handler ctrl_handler;
 	struct video_device	vdev;
-	struct v4l2_async_notifier notifier;
 
 	struct cal_dev		*cal;
 	struct cal_camerarx	*phy;
@@ -336,11 +336,6 @@ struct cal_ctx {
 	bool dma_act;
 };
 
-static inline struct cal_ctx *notifier_to_ctx(struct v4l2_async_notifier *n)
-{
-	return container_of(n, struct cal_ctx, notifier);
-}
-
 /* ------------------------------------------------------------------
  *	Platform Data
  * ------------------------------------------------------------------
@@ -2115,9 +2110,9 @@ to_cal_asd(struct v4l2_async_subdev *asd)
 	return container_of(asd, struct cal_v4l2_async_subdev, asd);
 }
 
-static int cal_async_bound(struct v4l2_async_notifier *notifier,
-			   struct v4l2_subdev *subdev,
-			   struct v4l2_async_subdev *asd)
+static int cal_async_notifier_bound(struct v4l2_async_notifier *notifier,
+				    struct v4l2_subdev *subdev,
+				    struct v4l2_async_subdev *asd)
 {
 	struct cal_ctx *ctx = to_cal_asd(asd)->ctx;
 
@@ -2130,52 +2125,84 @@ static int cal_async_bound(struct v4l2_async_notifier *notifier,
 	ctx->phy->sensor = subdev;
 	ctx_dbg(1, ctx, "Using sensor %s for capture\n", subdev->name);
 
-	return cal_ctx_v4l2_init_formats(ctx);
+	return 0;
 }
 
-static int cal_async_complete(struct v4l2_async_notifier *notifier)
+static int cal_async_notifier_complete(struct v4l2_async_notifier *notifier)
 {
-	struct cal_ctx *ctx = notifier_to_ctx(notifier);
+	struct cal_dev *cal = container_of(notifier, struct cal_dev, notifier);
+	unsigned int i;
+	int ret;
+
+	for (i = 0; i < ARRAY_SIZE(cal->ctx); ++i) {
+		struct cal_ctx *ctx = cal->ctx[i];
+
+		if (!ctx)
+			continue;
+
+		ret = cal_ctx_v4l2_init_formats(ctx);
+		if (ret)
+			continue;
+
+		cal_ctx_v4l2_register(ctx);
+	}
 
-	cal_ctx_v4l2_register(ctx);
 	return 0;
 }
 
-static const struct v4l2_async_notifier_operations cal_async_ops = {
-	.bound = cal_async_bound,
-	.complete = cal_async_complete,
+static const struct v4l2_async_notifier_operations cal_async_notifier_ops = {
+	.bound = cal_async_notifier_bound,
+	.complete = cal_async_notifier_complete,
 };
 
-static int of_cal_create_instance(struct cal_ctx *ctx, int inst)
+static int cal_async_notifier_register(struct cal_dev *cal)
 {
-	struct cal_v4l2_async_subdev *casd;
-	struct v4l2_async_subdev *asd;
-	struct fwnode_handle *fwnode;
+	unsigned int i;
 	int ret;
 
-	v4l2_async_notifier_init(&ctx->notifier);
-	ctx->notifier.ops = &cal_async_ops;
-
-	fwnode = of_fwnode_handle(ctx->phy->sensor_node);
-	asd = v4l2_async_notifier_add_fwnode_subdev(&ctx->notifier, fwnode,
-						    sizeof(*asd));
-	if (IS_ERR(asd)) {
-		ctx_err(ctx, "Failed to add subdev to notifier\n");
-		return PTR_ERR(asd);
+	v4l2_async_notifier_init(&cal->notifier);
+	cal->notifier.ops = &cal_async_notifier_ops;
+
+	for (i = 0; i < ARRAY_SIZE(cal->ctx); ++i) {
+		struct cal_ctx *ctx = cal->ctx[i];
+		struct cal_v4l2_async_subdev *casd;
+		struct v4l2_async_subdev *asd;
+		struct fwnode_handle *fwnode;
+
+		if (!ctx)
+			continue;
+
+		fwnode = of_fwnode_handle(ctx->phy->sensor_node);
+		asd = v4l2_async_notifier_add_fwnode_subdev(&cal->notifier,
+							    fwnode,
+							    sizeof(*asd));
+		if (IS_ERR(asd)) {
+			ctx_err(ctx, "Failed to add subdev to notifier\n");
+			ret = PTR_ERR(asd);
+			goto error;
+		}
+
+		casd = to_cal_asd(asd);
+		casd->ctx = ctx;
 	}
 
-	casd = to_cal_asd(asd);
-	casd->ctx = ctx;
-
-	ret = v4l2_async_notifier_register(&ctx->cal->v4l2_dev,
-					   &ctx->notifier);
+	ret = v4l2_async_notifier_register(&cal->v4l2_dev, &cal->notifier);
 	if (ret) {
-		ctx_err(ctx, "Error registering async notifier\n");
-		v4l2_async_notifier_cleanup(&ctx->notifier);
-		return ret;
+		cal_err(cal, "Error registering async notifier\n");
+		goto error;
 	}
 
 	return 0;
+
+error:
+	v4l2_async_notifier_cleanup(&cal->notifier);
+	return ret;
+}
+
+static void cal_async_notifier_unregister(struct cal_dev *cal)
+{
+	v4l2_async_notifier_unregister(&cal->notifier);
+	v4l2_async_notifier_cleanup(&cal->notifier);
 }
 
 /* ------------------------------------------------------------------
@@ -2201,10 +2228,6 @@ static struct cal_ctx *cal_ctx_create(struct cal_dev *cal, int inst)
 	if (ret)
 		return NULL;
 
-	ret = of_cal_create_instance(ctx, inst);
-	if (ret)
-		return NULL;
-
 	return ctx;
 }
 
@@ -2336,6 +2359,11 @@ static int cal_probe(struct platform_device *pdev)
 	cal_get_hwinfo(cal);
 	pm_runtime_put_sync(&pdev->dev);
 
+	/* Register the async notifier. */
+	ret = cal_async_notifier_register(cal);
+	if (ret)
+		goto error_pm_runtime;
+
 	return 0;
 
 error_pm_runtime:
@@ -2344,11 +2372,8 @@ static int cal_probe(struct platform_device *pdev)
 	pm_runtime_disable(&pdev->dev);
 	for (i = 0; i < ARRAY_SIZE(cal->ctx); i++) {
 		ctx = cal->ctx[i];
-		if (ctx) {
-			v4l2_async_notifier_unregister(&ctx->notifier);
-			v4l2_async_notifier_cleanup(&ctx->notifier);
+		if (ctx)
 			cal_ctx_v4l2_cleanup(ctx);
-		}
 	}
 
 error_v4l2:
@@ -2371,6 +2396,8 @@ static int cal_remove(struct platform_device *pdev)
 
 	pm_runtime_get_sync(&pdev->dev);
 
+	cal_async_notifier_unregister(cal);
+
 	for (i = 0; i < ARRAY_SIZE(cal->ctx); i++) {
 		ctx = cal->ctx[i];
 		if (ctx) {
@@ -2378,8 +2405,6 @@ static int cal_remove(struct platform_device *pdev)
 				video_device_node_name(&ctx->vdev));
 			cal_ctx_v4l2_unregister(ctx);
 			cal_camerarx_disable(ctx->phy);
-			v4l2_async_notifier_unregister(&ctx->notifier);
-			v4l2_async_notifier_cleanup(&ctx->notifier);
 			cal_ctx_v4l2_cleanup(ctx);
 		}
 	}
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 062/107] media: ti-vpe: cal: Replace context with phy in async notifier entries
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (60 preceding siblings ...)
  2020-06-14 23:58 ` [PATCH v1 061/107] media: ti-vpe: cal: Move async notifiers from contexts to cal_dev Laurent Pinchart
@ 2020-06-14 23:58 ` Laurent Pinchart
  2020-06-14 23:59 ` [PATCH v1 063/107] media: ti-vpe: cal: Operate on phy instances in cal_quickdump_regs() Laurent Pinchart
                   ` (46 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:58 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

The async notifier is meant to bind to subdevs connected to the CSI-2
ports. Those ports are modelled by the CAMERARX phy instances. To
prepare for additional decoupling of contexts and phys, make the
notifier operate on phys. We still initialize and register the context
V4L2 support in the async notifier complete operation as that's our
signal that the userspace API is ready to be exposed.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 24 ++++++++++++------------
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index 1c9a0369d025..d551f1d9895b 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -2101,7 +2101,7 @@ static void cal_ctx_v4l2_cleanup(struct cal_ctx *ctx)
 
 struct cal_v4l2_async_subdev {
 	struct v4l2_async_subdev asd;
-	struct cal_ctx *ctx;
+	struct cal_camerarx *phy;
 };
 
 static inline struct cal_v4l2_async_subdev *
@@ -2114,16 +2114,16 @@ static int cal_async_notifier_bound(struct v4l2_async_notifier *notifier,
 				    struct v4l2_subdev *subdev,
 				    struct v4l2_async_subdev *asd)
 {
-	struct cal_ctx *ctx = to_cal_asd(asd)->ctx;
+	struct cal_camerarx *phy = to_cal_asd(asd)->phy;
 
-	if (ctx->phy->sensor) {
-		ctx_info(ctx, "Rejecting subdev %s (Already set!!)",
+	if (phy->sensor) {
+		phy_info(phy, "Rejecting subdev %s (Already set!!)",
 			 subdev->name);
 		return 0;
 	}
 
-	ctx->phy->sensor = subdev;
-	ctx_dbg(1, ctx, "Using sensor %s for capture\n", subdev->name);
+	phy->sensor = subdev;
+	phy_dbg(1, phy, "Using sensor %s for capture\n", subdev->name);
 
 	return 0;
 }
@@ -2163,27 +2163,27 @@ static int cal_async_notifier_register(struct cal_dev *cal)
 	v4l2_async_notifier_init(&cal->notifier);
 	cal->notifier.ops = &cal_async_notifier_ops;
 
-	for (i = 0; i < ARRAY_SIZE(cal->ctx); ++i) {
-		struct cal_ctx *ctx = cal->ctx[i];
+	for (i = 0; i < ARRAY_SIZE(cal->phy); ++i) {
+		struct cal_camerarx *phy = cal->phy[i];
 		struct cal_v4l2_async_subdev *casd;
 		struct v4l2_async_subdev *asd;
 		struct fwnode_handle *fwnode;
 
-		if (!ctx)
+		if (!phy)
 			continue;
 
-		fwnode = of_fwnode_handle(ctx->phy->sensor_node);
+		fwnode = of_fwnode_handle(phy->sensor_node);
 		asd = v4l2_async_notifier_add_fwnode_subdev(&cal->notifier,
 							    fwnode,
 							    sizeof(*asd));
 		if (IS_ERR(asd)) {
-			ctx_err(ctx, "Failed to add subdev to notifier\n");
+			phy_err(phy, "Failed to add subdev to notifier\n");
 			ret = PTR_ERR(asd);
 			goto error;
 		}
 
 		casd = to_cal_asd(asd);
-		casd->ctx = ctx;
+		casd->phy = phy;
 	}
 
 	ret = v4l2_async_notifier_register(&cal->v4l2_dev, &cal->notifier);
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 063/107] media: ti-vpe: cal: Operate on phy instances in cal_quickdump_regs()
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (61 preceding siblings ...)
  2020-06-14 23:58 ` [PATCH v1 062/107] media: ti-vpe: cal: Replace context with phy in async notifier entries Laurent Pinchart
@ 2020-06-14 23:59 ` Laurent Pinchart
  2020-06-14 23:59 ` [PATCH v1 064/107] media: ti-vpe: cal: Decouple context and phy cleanup at remove time Laurent Pinchart
                   ` (45 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:59 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

The cal_quickdump_regs() dumps registers for the two CAMERARX instances.
Retrieve those instances from the cal_dev directly instead of going
through the contexts, and simplify the code by using a loop.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 24 +++++++++++-------------
 1 file changed, 11 insertions(+), 13 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index d551f1d9895b..d9cb7a53cb8d 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -449,26 +449,24 @@ static inline void set_field(u32 *valp, u32 field, u32 mask)
 
 static void cal_quickdump_regs(struct cal_dev *cal)
 {
+	unsigned int i;
+
 	cal_info(cal, "CAL Registers @ 0x%pa:\n", &cal->res->start);
 	print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 4,
 		       (__force const void *)cal->base,
 		       resource_size(cal->res), false);
 
-	if (cal->ctx[0]) {
-		cal_info(cal, "CSI2 Core 0 Registers @ %pa:\n",
-			 &cal->ctx[0]->phy->res->start);
-		print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 4,
-			       (__force const void *)cal->ctx[0]->phy->base,
-			       resource_size(cal->ctx[0]->phy->res),
-			       false);
-	}
+	for (i = 0; i < ARRAY_SIZE(cal->phy); ++i) {
+		struct cal_camerarx *phy = cal->phy[i];
+
+		if (!phy)
+			continue;
 
-	if (cal->ctx[1]) {
-		cal_info(cal, "CSI2 Core 1 Registers @ %pa:\n",
-			 &cal->ctx[1]->phy->res->start);
+		cal_info(cal, "CSI2 Core %u Registers @ %pa:\n", i,
+			 &phy->res->start);
 		print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 4,
-			       (__force const void *)cal->ctx[1]->phy->base,
-			       resource_size(cal->ctx[1]->phy->res),
+			       (__force const void *)phy->base,
+			       resource_size(phy->res),
 			       false);
 	}
 }
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 064/107] media: ti-vpe: cal: Decouple context and phy cleanup at remove time
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (62 preceding siblings ...)
  2020-06-14 23:59 ` [PATCH v1 063/107] media: ti-vpe: cal: Operate on phy instances in cal_quickdump_regs() Laurent Pinchart
@ 2020-06-14 23:59 ` Laurent Pinchart
  2020-06-14 23:59 ` [PATCH v1 065/107] media: ti-vpe: cal: Move CAL_NUM_CSI2_PORTS from cal_regs.h to cal.c Laurent Pinchart
                   ` (44 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:59 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

The driver happens the use the same number of CAMERARX and context, but
coupling their cleanup at remove time is wrong. To prepare for the
introduction of additional contexts, decouple the two.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 24 +++++++++++++++---------
 1 file changed, 15 insertions(+), 9 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index d9cb7a53cb8d..0ce627b668ab 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -1965,6 +1965,9 @@ static int cal_ctx_v4l2_register(struct cal_ctx *ctx)
 
 static void cal_ctx_v4l2_unregister(struct cal_ctx *ctx)
 {
+	ctx_dbg(1, ctx, "unregistering %s\n",
+		video_device_node_name(&ctx->vdev));
+
 	video_unregister_device(&ctx->vdev);
 }
 
@@ -2387,7 +2390,6 @@ static int cal_probe(struct platform_device *pdev)
 static int cal_remove(struct platform_device *pdev)
 {
 	struct cal_dev *cal = platform_get_drvdata(pdev);
-	struct cal_ctx *ctx;
 	unsigned int i;
 
 	cal_dbg(1, cal, "Removing %s\n", CAL_MODULE_NAME);
@@ -2397,14 +2399,18 @@ static int cal_remove(struct platform_device *pdev)
 	cal_async_notifier_unregister(cal);
 
 	for (i = 0; i < ARRAY_SIZE(cal->ctx); i++) {
-		ctx = cal->ctx[i];
-		if (ctx) {
-			ctx_dbg(1, ctx, "unregistering %s\n",
-				video_device_node_name(&ctx->vdev));
-			cal_ctx_v4l2_unregister(ctx);
-			cal_camerarx_disable(ctx->phy);
-			cal_ctx_v4l2_cleanup(ctx);
-		}
+		if (cal->ctx[i])
+			cal_ctx_v4l2_unregister(cal->ctx[i]);
+	}
+
+	for (i = 0; i < ARRAY_SIZE(cal->phy); i++) {
+		if (cal->phy[i])
+			cal_camerarx_disable(cal->phy[i]);
+	}
+
+	for (i = 0; i < ARRAY_SIZE(cal->ctx); i++) {
+		if (cal->ctx[i])
+			cal_ctx_v4l2_cleanup(cal->ctx[i]);
 	}
 
 	v4l2_device_unregister(&cal->v4l2_dev);
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 065/107] media: ti-vpe: cal: Move CAL_NUM_CSI2_PORTS from cal_regs.h to cal.c
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (63 preceding siblings ...)
  2020-06-14 23:59 ` [PATCH v1 064/107] media: ti-vpe: cal: Decouple context and phy cleanup at remove time Laurent Pinchart
@ 2020-06-14 23:59 ` Laurent Pinchart
  2020-06-14 23:59 ` [PATCH v1 066/107] media: ti-vpe: cal: Remove isvcirqset() and isportirqset() macros Laurent Pinchart
                   ` (43 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:59 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

The CAL_NUM_CSI2_PORTS macro isn't a register definition. Move it to
cal.c, and fix indentation of the other macros while at it.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c      | 7 ++++---
 drivers/media/platform/ti-vpe/cal_regs.h | 2 --
 2 files changed, 4 insertions(+), 5 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index 0ce627b668ab..518f8af616b6 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -74,10 +74,11 @@ MODULE_PARM_DESC(debug, "activates debug info");
 #define phy_err(phy, fmt, arg...)	\
 	cal_err((phy)->cal, "phy%u: " fmt, (phy)->instance, ##arg)
 
-#define CAL_NUM_CONTEXT 2
+#define CAL_NUM_CONTEXT			2
+#define CAL_NUM_CSI2_PORTS		2
 
-#define MAX_WIDTH_BYTES (8192 * 8)
-#define MAX_HEIGHT_LINES 16383
+#define MAX_WIDTH_BYTES			(8192 * 8)
+#define MAX_HEIGHT_LINES		16383
 
 /* ------------------------------------------------------------------
  *	Format Handling
diff --git a/drivers/media/platform/ti-vpe/cal_regs.h b/drivers/media/platform/ti-vpe/cal_regs.h
index b551e67d5d41..f752096dcf7f 100644
--- a/drivers/media/platform/ti-vpe/cal_regs.h
+++ b/drivers/media/platform/ti-vpe/cal_regs.h
@@ -34,8 +34,6 @@
  */
 #define DRA72_CAL_PRE_ES2_LDO_DISABLE BIT(0)
 
-#define CAL_NUM_CSI2_PORTS		2
-
 /* CAL register offsets */
 
 #define CAL_HL_REVISION			0x0000
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 066/107] media: ti-vpe: cal: Remove isvcirqset() and isportirqset() macros
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (64 preceding siblings ...)
  2020-06-14 23:59 ` [PATCH v1 065/107] media: ti-vpe: cal: Move CAL_NUM_CSI2_PORTS from cal_regs.h to cal.c Laurent Pinchart
@ 2020-06-14 23:59 ` Laurent Pinchart
  2020-06-14 23:59 ` [PATCH v1 067/107] media: ti-vpe: cal: Replace number of ports numerical value by macro Laurent Pinchart
                   ` (42 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:59 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

The isvcirqset() isn't used. The isportirqset() doesn't increase
readability. Inline the latter and simply drop the former.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 9 ++-------
 1 file changed, 2 insertions(+), 7 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index 518f8af616b6..26b9f4638084 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -1259,11 +1259,6 @@ static inline void cal_process_buffer_complete(struct cal_ctx *ctx)
 	ctx->cur_frm = ctx->next_frm;
 }
 
-#define isvcirqset(irq, vc, ff) (irq & \
-	(CAL_CSI2_VC_IRQENABLE_ ##ff ##_IRQ_##vc ##_MASK))
-
-#define isportirqset(irq, port) (irq & CAL_HL_IRQ_MASK(port))
-
 static irqreturn_t cal_irq(int irq_cal, void *data)
 {
 	struct cal_dev *cal = data;
@@ -1300,7 +1295,7 @@ static irqreturn_t cal_irq(int irq_cal, void *data)
 		reg_write(cal, CAL_HL_IRQSTATUS(1), status);
 
 		for (i = 0; i < ARRAY_SIZE(cal->ctx); ++i) {
-			if (isportirqset(status, i)) {
+			if (status & CAL_HL_IRQ_MASK(i)) {
 				ctx = cal->ctx[i];
 
 				spin_lock(&ctx->slock);
@@ -1321,7 +1316,7 @@ static irqreturn_t cal_irq(int irq_cal, void *data)
 		reg_write(cal, CAL_HL_IRQSTATUS(2), status);
 
 		for (i = 0; i < ARRAY_SIZE(cal->ctx); ++i) {
-			if (isportirqset(status, i)) {
+			if (status & CAL_HL_IRQ_MASK(i)) {
 				ctx = cal->ctx[i];
 				dma_q = &ctx->vidq;
 
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 067/107] media: ti-vpe: cal: Replace number of ports numerical value by macro
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (65 preceding siblings ...)
  2020-06-14 23:59 ` [PATCH v1 066/107] media: ti-vpe: cal: Remove isvcirqset() and isportirqset() macros Laurent Pinchart
@ 2020-06-14 23:59 ` Laurent Pinchart
  2020-06-14 23:59 ` [PATCH v1 068/107] media: ti-vpe: cal: Split media initialization and cleanup to functions Laurent Pinchart
                   ` (41 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:59 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

Use the CAL_NUM_CSI2_PORTS macro instead of the hardcoded numerical
value 2 to iterate over the CSI-2 ports.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index 26b9f4638084..9fe8abfa1df9 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -1274,7 +1274,7 @@ static irqreturn_t cal_irq(int irq_cal, void *data)
 		if (status & CAL_HL_IRQ_OCPO_ERR_MASK)
 			dev_err_ratelimited(&cal->pdev->dev, "OCPO ERROR\n");
 
-		for (i = 0; i < 2; ++i) {
+		for (i = 0; i < CAL_NUM_CSI2_PORTS; ++i) {
 			if (status & CAL_HL_IRQ_CIO_MASK(i)) {
 				u32 cio_stat = reg_read(cal,
 							CAL_CSI2_COMPLEXIO_IRQSTATUS(i));
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 068/107] media: ti-vpe: cal: Split media initialization and cleanup to functions
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (66 preceding siblings ...)
  2020-06-14 23:59 ` [PATCH v1 067/107] media: ti-vpe: cal: Replace number of ports numerical value by macro Laurent Pinchart
@ 2020-06-14 23:59 ` Laurent Pinchart
  2020-06-18 19:17   ` Benoit Parrot
  2020-06-14 23:59 ` [PATCH v1 069/107] media: ti-vpe: cal: Read hardware revision earlier during probe Laurent Pinchart
                   ` (40 subsequent siblings)
  108 siblings, 1 reply; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:59 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

Create four functions to handle initialization, cleanup, registration
and unregistration of the V4L2 (and sonn media controller) objects:

- init() is meant to be called early at probe time to initialize the
  objects, before they get used from within the kernel

- cleanup() is the counterpart of init, and is meant to be called at the
  end of the remove sequence to free all objects

- register() is meant to be called at the end of the probe sequence, to
  register the userspace-facing devices

- unregister() is the counterpart of register, and is meant to be called
  at the beginning for the remove sequence, to disallow access from
  userspace

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 120 +++++++++++++++++++++-------
 1 file changed, 92 insertions(+), 28 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index 9fe8abfa1df9..6655c0051ccc 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -2202,6 +2202,88 @@ static void cal_async_notifier_unregister(struct cal_dev *cal)
 	v4l2_async_notifier_cleanup(&cal->notifier);
 }
 
+/* ------------------------------------------------------------------
+ *	Media and V4L2 device handling
+ * ------------------------------------------------------------------
+ */
+
+/*
+ * Register user-facing devices. To be called at the end of the probe function
+ * when all resources are initialized and ready.
+ */
+static int cal_media_register(struct cal_dev *cal)
+{
+	int ret;
+
+	/*
+	 * Register the async notifier. This may trigger registration of the
+	 * V4L2 video devices if all subdevs are ready.
+	 */
+	ret = cal_async_notifier_register(cal);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+/*
+ * Unregister the user-facing devices, but don't free memory yet. To be called
+ * at the beginning of the remove function, to disallow access from userspace.
+ */
+static void cal_media_unregister(struct cal_dev *cal)
+{
+	unsigned int i;
+
+	/* Unregister all the V4L2 video devices. */
+	for (i = 0; i < ARRAY_SIZE(cal->ctx); i++) {
+		if (cal->ctx[i])
+			cal_ctx_v4l2_unregister(cal->ctx[i]);
+	}
+
+	cal_async_notifier_unregister(cal);
+}
+
+/*
+ * Initialize the in-kernel objects. To be called at the beginning of the probe
+ * function, before the V4L2 device is used by the driver.
+ */
+static int cal_media_init(struct cal_dev *cal)
+{
+	int ret;
+
+	/*
+	 * Initialize the V4L2 device (despite the function name, this performs
+	 * initialization, not registration).
+	 */
+	ret = v4l2_device_register(&cal->pdev->dev, &cal->v4l2_dev);
+	if (ret) {
+		cal_err(cal, "Failed to register V4L2 device\n");
+		return ret;
+	}
+
+	vb2_dma_contig_set_max_seg_size(&cal->pdev->dev, DMA_BIT_MASK(32));
+
+	return 0;
+}
+
+/*
+ * Cleanup the in-kernel objects, freeing memory. To be called at the very end
+ * of the remove sequence, when nothing (including userspace) can access the
+ * objects anymore.
+ */
+static void cal_media_cleanup(struct cal_dev *cal)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(cal->ctx); i++) {
+		if (cal->ctx[i])
+			cal_ctx_v4l2_cleanup(cal->ctx[i]);
+	}
+
+	v4l2_device_unregister(&cal->v4l2_dev);
+	vb2_dma_contig_clear_max_seg_size(&cal->pdev->dev);
+}
+
 /* ------------------------------------------------------------------
  *	Initialization and module stuff
  * ------------------------------------------------------------------
@@ -2328,12 +2410,10 @@ static int cal_probe(struct platform_device *pdev)
 		}
 	}
 
-	/* Register the V4L2 device. */
-	ret = v4l2_device_register(&pdev->dev, &cal->v4l2_dev);
-	if (ret) {
-		cal_err(cal, "Failed to register V4L2 device\n");
+	/* Initialize the media device. */
+	ret = cal_media_init(cal);
+	if (ret < 0)
 		goto error_camerarx;
-	}
 
 	/* Create contexts. */
 	for (i = 0; i < cal_data_get_num_csi2_phy(cal); ++i)
@@ -2342,11 +2422,9 @@ static int cal_probe(struct platform_device *pdev)
 	if (!cal->ctx[0] && !cal->ctx[1]) {
 		cal_err(cal, "Neither port is configured, no point in staying up\n");
 		ret = -ENODEV;
-		goto error_v4l2;
+		goto error_media;
 	}
 
-	vb2_dma_contig_set_max_seg_size(&pdev->dev, DMA_BIT_MASK(32));
-
 	/* Read the revision and hardware info to verify hardware access. */
 	pm_runtime_enable(&pdev->dev);
 	ret = pm_runtime_get_sync(&pdev->dev);
@@ -2356,16 +2434,14 @@ static int cal_probe(struct platform_device *pdev)
 	cal_get_hwinfo(cal);
 	pm_runtime_put_sync(&pdev->dev);
 
-	/* Register the async notifier. */
-	ret = cal_async_notifier_register(cal);
+	/* Register the media device. */
+	ret = cal_media_register(cal);
 	if (ret)
 		goto error_pm_runtime;
 
 	return 0;
 
 error_pm_runtime:
-	vb2_dma_contig_clear_max_seg_size(&pdev->dev);
-
 	pm_runtime_disable(&pdev->dev);
 	for (i = 0; i < ARRAY_SIZE(cal->ctx); i++) {
 		ctx = cal->ctx[i];
@@ -2373,8 +2449,8 @@ static int cal_probe(struct platform_device *pdev)
 			cal_ctx_v4l2_cleanup(ctx);
 	}
 
-error_v4l2:
-	v4l2_device_unregister(&cal->v4l2_dev);
+error_media:
+	cal_media_cleanup(cal);
 
 error_camerarx:
 	for (i = 0; i < ARRAY_SIZE(cal->phy); i++)
@@ -2392,24 +2468,14 @@ static int cal_remove(struct platform_device *pdev)
 
 	pm_runtime_get_sync(&pdev->dev);
 
-	cal_async_notifier_unregister(cal);
-
-	for (i = 0; i < ARRAY_SIZE(cal->ctx); i++) {
-		if (cal->ctx[i])
-			cal_ctx_v4l2_unregister(cal->ctx[i]);
-	}
+	cal_media_unregister(cal);
 
 	for (i = 0; i < ARRAY_SIZE(cal->phy); i++) {
 		if (cal->phy[i])
 			cal_camerarx_disable(cal->phy[i]);
 	}
 
-	for (i = 0; i < ARRAY_SIZE(cal->ctx); i++) {
-		if (cal->ctx[i])
-			cal_ctx_v4l2_cleanup(cal->ctx[i]);
-	}
-
-	v4l2_device_unregister(&cal->v4l2_dev);
+	cal_media_cleanup(cal);
 
 	for (i = 0; i < ARRAY_SIZE(cal->phy); i++)
 		cal_camerarx_destroy(cal->phy[i]);
@@ -2417,8 +2483,6 @@ static int cal_remove(struct platform_device *pdev)
 	pm_runtime_put_sync(&pdev->dev);
 	pm_runtime_disable(&pdev->dev);
 
-	vb2_dma_contig_clear_max_seg_size(&pdev->dev);
-
 	return 0;
 }
 
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 069/107] media: ti-vpe: cal: Read hardware revision earlier during probe
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (67 preceding siblings ...)
  2020-06-14 23:59 ` [PATCH v1 068/107] media: ti-vpe: cal: Split media initialization and cleanup to functions Laurent Pinchart
@ 2020-06-14 23:59 ` Laurent Pinchart
  2020-06-14 23:59 ` [PATCH v1 070/107] media: ti-vpe: cal: Print revision and hwinfo in a more readable format Laurent Pinchart
                   ` (39 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:59 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

Read the hardware revision and info right after allocating resources, as
there's no need to delay doing so until all initialization is complete.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 26 ++++++++++++++------------
 1 file changed, 14 insertions(+), 12 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index 6655c0051ccc..33a985300045 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -2401,6 +2401,15 @@ static int cal_probe(struct platform_device *pdev)
 	if (ret)
 		return ret;
 
+	/* Read the revision and hardware info to verify hardware access. */
+	pm_runtime_enable(&pdev->dev);
+	ret = pm_runtime_get_sync(&pdev->dev);
+	if (ret)
+		goto error_pm_runtime;
+
+	cal_get_hwinfo(cal);
+	pm_runtime_put_sync(&pdev->dev);
+
 	/* Create CAMERARX PHYs. */
 	for (i = 0; i < cal_data_get_num_csi2_phy(cal); ++i) {
 		cal->phy[i] = cal_camerarx_create(cal, i);
@@ -2425,24 +2434,14 @@ static int cal_probe(struct platform_device *pdev)
 		goto error_media;
 	}
 
-	/* Read the revision and hardware info to verify hardware access. */
-	pm_runtime_enable(&pdev->dev);
-	ret = pm_runtime_get_sync(&pdev->dev);
-	if (ret)
-		goto error_pm_runtime;
-
-	cal_get_hwinfo(cal);
-	pm_runtime_put_sync(&pdev->dev);
-
 	/* Register the media device. */
 	ret = cal_media_register(cal);
 	if (ret)
-		goto error_pm_runtime;
+		goto error_context;
 
 	return 0;
 
-error_pm_runtime:
-	pm_runtime_disable(&pdev->dev);
+error_context:
 	for (i = 0; i < ARRAY_SIZE(cal->ctx); i++) {
 		ctx = cal->ctx[i];
 		if (ctx)
@@ -2456,6 +2455,9 @@ static int cal_probe(struct platform_device *pdev)
 	for (i = 0; i < ARRAY_SIZE(cal->phy); i++)
 		cal_camerarx_destroy(cal->phy[i]);
 
+error_pm_runtime:
+	pm_runtime_disable(&pdev->dev);
+
 	return ret;
 }
 
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 070/107] media: ti-vpe: cal: Print revision and hwinfo in a more readable format
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (68 preceding siblings ...)
  2020-06-14 23:59 ` [PATCH v1 069/107] media: ti-vpe: cal: Read hardware revision earlier during probe Laurent Pinchart
@ 2020-06-14 23:59 ` Laurent Pinchart
  2020-06-14 23:59 ` [PATCH v1 071/107] media: ti-vpe: cal: Store struct device in cal_dev Laurent Pinchart
                   ` (38 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:59 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

Print the hardware revision in the X.Y.R format, which is more readable
that the 32-bit hex value. For the hardware info register, only print
its value if it doesn't contain what we expect.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 29 ++++++++++++++++++++++-------
 1 file changed, 22 insertions(+), 7 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index 33a985300045..4a1f76b12130 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -2331,21 +2331,36 @@ static const struct of_device_id cal_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, cal_of_match);
 
-/*
- * Get Revision and HW info
- */
+/* Get hardware revision and info. */
+
+#define CAL_HL_HWINFO_VALUE		0xa3c90469
+
 static void cal_get_hwinfo(struct cal_dev *cal)
 {
 	u32 revision;
 	u32 hwinfo;
 
 	revision = reg_read(cal, CAL_HL_REVISION);
-	cal_dbg(3, cal, "CAL_HL_REVISION = 0x%08x (expecting 0x40000200)\n",
-		revision);
+	switch (FIELD_GET(CAL_HL_REVISION_SCHEME_MASK, revision)) {
+	case CAL_HL_REVISION_SCHEME_H08:
+		cal_dbg(3, cal, "CAL HW revision %lu.%lu.%lu (0x%08x)\n",
+			FIELD_GET(CAL_HL_REVISION_MAJOR_MASK, revision),
+			FIELD_GET(CAL_HL_REVISION_MINOR_MASK, revision),
+			FIELD_GET(CAL_HL_REVISION_RTL_MASK, revision),
+			revision);
+		break;
+
+	case CAL_HL_REVISION_SCHEME_LEGACY:
+	default:
+		cal_info(cal, "Unexpected CAL HW revision 0x%08x\n",
+			 revision);
+		break;
+	}
 
 	hwinfo = reg_read(cal, CAL_HL_HWINFO);
-	cal_dbg(3, cal, "CAL_HL_HWINFO = 0x%08x (expecting 0xA3C90469)\n",
-		hwinfo);
+	if (hwinfo != CAL_HL_HWINFO_VALUE)
+		cal_info(cal, "CAL_HL_HWINFO = 0x%08x, expected 0x%08x\n",
+			 hwinfo, CAL_HL_HWINFO_VALUE);
 }
 
 static u32 cal_data_get_num_csi2_phy(struct cal_dev *cal)
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 071/107] media: ti-vpe: cal: Store struct device in cal_dev
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (69 preceding siblings ...)
  2020-06-14 23:59 ` [PATCH v1 070/107] media: ti-vpe: cal: Print revision and hwinfo in a more readable format Laurent Pinchart
@ 2020-06-14 23:59 ` Laurent Pinchart
  2020-06-14 23:59 ` [PATCH v1 072/107] media: ti-vpe: cal: Register a media device Laurent Pinchart
                   ` (37 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:59 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

The cal_dev structure stores the platform_device pointer, but most
accesses to that field need the device pointer. Store the struct device
pointer directly to simplify the code, and use to_platform_device() in
the two locations that need the platform device.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 54 ++++++++++++++---------------
 1 file changed, 27 insertions(+), 27 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index 4a1f76b12130..205fb736e27a 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -53,12 +53,12 @@ MODULE_PARM_DESC(debug, "activates debug info");
 #define cal_dbg(level, cal, fmt, arg...)				\
 	do {								\
 		if (debug >= (level))					\
-			dev_dbg(&(cal)->pdev->dev, fmt, ##arg);		\
+			dev_dbg((cal)->dev, fmt, ##arg);		\
 	} while (0)
 #define cal_info(cal, fmt, arg...)	\
-	dev_info(&(cal)->pdev->dev, fmt, ##arg)
+	dev_info((cal)->dev, fmt, ##arg)
 #define cal_err(cal, fmt, arg...)	\
-	dev_err(&(cal)->pdev->dev, fmt, ##arg)
+	dev_err((cal)->dev, fmt, ##arg)
 
 #define ctx_dbg(level, ctx, fmt, arg...)	\
 	cal_dbg(level, (ctx)->cal, "ctx%u: " fmt, (ctx)->index, ##arg)
@@ -262,7 +262,7 @@ struct cal_data {
 struct cal_camerarx {
 	void __iomem		*base;
 	struct resource		*res;
-	struct platform_device	*pdev;
+	struct device		*dev;
 	struct regmap_field	*fields[F_MAX_FIELDS];
 
 	struct cal_dev		*cal;
@@ -279,7 +279,7 @@ struct cal_dev {
 	int			irq;
 	void __iomem		*base;
 	struct resource		*res;
-	struct platform_device	*pdev;
+	struct device		*dev;
 
 	const struct cal_data	*data;
 
@@ -907,7 +907,7 @@ static int cal_camerarx_regmap_init(struct cal_dev *cal,
 		 * Here we update the reg offset with the
 		 * value found in DT
 		 */
-		phy->fields[i] = devm_regmap_field_alloc(&cal->pdev->dev,
+		phy->fields[i] = devm_regmap_field_alloc(cal->dev,
 							 cal->syscon_camerrx,
 							 field);
 		if (IS_ERR(phy->fields[i])) {
@@ -922,7 +922,6 @@ static int cal_camerarx_regmap_init(struct cal_dev *cal,
 static int cal_camerarx_parse_dt(struct cal_camerarx *phy)
 {
 	struct v4l2_fwnode_endpoint *endpoint = &phy->endpoint;
-	struct platform_device *pdev = phy->cal->pdev;
 	struct device_node *ep_node;
 	char data_lanes[V4L2_FWNODE_CSI2_MAX_DATA_LANES * 2];
 	unsigned int i;
@@ -932,7 +931,7 @@ static int cal_camerarx_parse_dt(struct cal_camerarx *phy)
 	 * Find the endpoint node for the port corresponding to the PHY
 	 * instance, and parse its CSI-2-related properties.
 	 */
-	ep_node = of_graph_get_endpoint_by_regs(pdev->dev.of_node,
+	ep_node = of_graph_get_endpoint_by_regs(phy->cal->dev->of_node,
 						phy->instance, 0);
 	if (!ep_node) {
 		phy_dbg(3, phy, "Can't get endpoint\n");
@@ -984,7 +983,7 @@ static int cal_camerarx_parse_dt(struct cal_camerarx *phy)
 static struct cal_camerarx *cal_camerarx_create(struct cal_dev *cal,
 						unsigned int instance)
 {
-	struct platform_device *pdev = cal->pdev;
+	struct platform_device *pdev = to_platform_device(cal->dev);
 	struct cal_camerarx *phy;
 	int ret;
 
@@ -1000,7 +999,7 @@ static struct cal_camerarx *cal_camerarx_create(struct cal_dev *cal,
 						(instance == 0) ?
 						"cal_rx_core0" :
 						"cal_rx_core1");
-	phy->base = devm_ioremap_resource(&pdev->dev, phy->res);
+	phy->base = devm_ioremap_resource(cal->dev, phy->res);
 	if (IS_ERR(phy->base)) {
 		cal_err(cal, "failed to ioremap\n");
 		ret = PTR_ERR(phy->base);
@@ -1036,7 +1035,8 @@ static void cal_camerarx_destroy(struct cal_camerarx *phy)
 
 static int cal_camerarx_init_regmap(struct cal_dev *cal)
 {
-	struct device_node *np = cal->pdev->dev.of_node;
+	struct platform_device *pdev = to_platform_device(cal->dev);
+	struct device_node *np = cal->dev->of_node;
 	struct regmap_config config = { };
 	struct regmap *syscon;
 	struct resource *res;
@@ -1051,16 +1051,16 @@ static int cal_camerarx_init_regmap(struct cal_dev *cal)
 		return 0;
 	}
 
-	dev_warn(&cal->pdev->dev, "failed to get ti,camerrx-control: %ld\n",
+	dev_warn(cal->dev, "failed to get ti,camerrx-control: %ld\n",
 		 PTR_ERR(syscon));
 
 	/*
 	 * Backward DTS compatibility. If syscon entry is not present then
 	 * check if the camerrx_control resource is present.
 	 */
-	res = platform_get_resource_byname(cal->pdev, IORESOURCE_MEM,
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
 					   "camerrx_control");
-	base = devm_ioremap_resource(&cal->pdev->dev, res);
+	base = devm_ioremap_resource(cal->dev, res);
 	if (IS_ERR(base)) {
 		cal_err(cal, "failed to ioremap camerrx_control\n");
 		return PTR_ERR(base);
@@ -1151,7 +1151,7 @@ static void cal_ctx_pix_proc_config(struct cal_ctx *ctx)
 		 *
 		 * Instead of failing here just use 8 bpp as a default.
 		 */
-		dev_warn_once(&ctx->cal->pdev->dev,
+		dev_warn_once(ctx->cal->dev,
 			      "%s:%d:%s: bpp:%d unsupported! Overwritten with 8.\n",
 			      __FILE__, __LINE__, __func__, ctx->fmt->bpp);
 		extract = CAL_PIX_PROC_EXTRACT_B8;
@@ -1272,14 +1272,14 @@ static irqreturn_t cal_irq(int irq_cal, void *data)
 		reg_write(cal, CAL_HL_IRQSTATUS(0), status);
 
 		if (status & CAL_HL_IRQ_OCPO_ERR_MASK)
-			dev_err_ratelimited(&cal->pdev->dev, "OCPO ERROR\n");
+			dev_err_ratelimited(cal->dev, "OCPO ERROR\n");
 
 		for (i = 0; i < CAL_NUM_CSI2_PORTS; ++i) {
 			if (status & CAL_HL_IRQ_CIO_MASK(i)) {
 				u32 cio_stat = reg_read(cal,
 							CAL_CSI2_COMPLEXIO_IRQSTATUS(i));
 
-				dev_err_ratelimited(&cal->pdev->dev,
+				dev_err_ratelimited(cal->dev,
 						    "CIO%u error: %#08x\n", i, cio_stat);
 
 				reg_write(cal, CAL_CSI2_COMPLEXIO_IRQSTATUS(i),
@@ -1377,7 +1377,7 @@ static int cal_querycap(struct file *file, void *priv,
 	strscpy(cap->card, CAL_MODULE_NAME, sizeof(cap->card));
 
 	snprintf(cap->bus_info, sizeof(cap->bus_info),
-		 "platform:%s", dev_name(&ctx->cal->pdev->dev));
+		 "platform:%s", dev_name(ctx->cal->dev));
 	return 0;
 }
 
@@ -1811,7 +1811,7 @@ static int cal_start_streaming(struct vb2_queue *vq, unsigned int count)
 		goto err;
 	}
 
-	pm_runtime_get_sync(&ctx->cal->pdev->dev);
+	pm_runtime_get_sync(ctx->cal->dev);
 
 	cal_ctx_csi2_config(ctx);
 	cal_ctx_pix_proc_config(ctx);
@@ -1826,7 +1826,7 @@ static int cal_start_streaming(struct vb2_queue *vq, unsigned int count)
 	if (ret) {
 		v4l2_subdev_call(ctx->phy->sensor, core, s_power, 0);
 		ctx_err(ctx, "stream on failed in subdev\n");
-		pm_runtime_put_sync(&ctx->cal->pdev->dev);
+		pm_runtime_put_sync(ctx->cal->dev);
 		goto err;
 	}
 
@@ -1906,7 +1906,7 @@ static void cal_stop_streaming(struct vb2_queue *vq)
 	ctx->next_frm = NULL;
 	spin_unlock_irqrestore(&ctx->slock, flags);
 
-	pm_runtime_put_sync(&ctx->cal->pdev->dev);
+	pm_runtime_put_sync(ctx->cal->dev);
 }
 
 static const struct vb2_ops cal_video_qops = {
@@ -2054,7 +2054,7 @@ static int cal_ctx_v4l2_init(struct cal_ctx *ctx)
 	q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
 	q->lock = &ctx->mutex;
 	q->min_buffers_needed = 3;
-	q->dev = &ctx->cal->pdev->dev;
+	q->dev = ctx->cal->dev;
 
 	ret = vb2_queue_init(q);
 	if (ret)
@@ -2255,13 +2255,13 @@ static int cal_media_init(struct cal_dev *cal)
 	 * Initialize the V4L2 device (despite the function name, this performs
 	 * initialization, not registration).
 	 */
-	ret = v4l2_device_register(&cal->pdev->dev, &cal->v4l2_dev);
+	ret = v4l2_device_register(cal->dev, &cal->v4l2_dev);
 	if (ret) {
 		cal_err(cal, "Failed to register V4L2 device\n");
 		return ret;
 	}
 
-	vb2_dma_contig_set_max_seg_size(&cal->pdev->dev, DMA_BIT_MASK(32));
+	vb2_dma_contig_set_max_seg_size(cal->dev, DMA_BIT_MASK(32));
 
 	return 0;
 }
@@ -2281,7 +2281,7 @@ static void cal_media_cleanup(struct cal_dev *cal)
 	}
 
 	v4l2_device_unregister(&cal->v4l2_dev);
-	vb2_dma_contig_clear_max_seg_size(&cal->pdev->dev);
+	vb2_dma_contig_clear_max_seg_size(cal->dev);
 }
 
 /* ------------------------------------------------------------------
@@ -2294,7 +2294,7 @@ static struct cal_ctx *cal_ctx_create(struct cal_dev *cal, int inst)
 	struct cal_ctx *ctx;
 	int ret;
 
-	ctx = devm_kzalloc(&cal->pdev->dev, sizeof(*ctx), GFP_KERNEL);
+	ctx = devm_kzalloc(cal->dev, sizeof(*ctx), GFP_KERNEL);
 	if (!ctx)
 		return NULL;
 
@@ -2386,7 +2386,7 @@ static int cal_probe(struct platform_device *pdev)
 		return -ENODEV;
 	}
 
-	cal->pdev = pdev;
+	cal->dev = &pdev->dev;
 	platform_set_drvdata(pdev, cal);
 
 	/* Acquire resources: clocks, CAMERARX regmap, I/O memory and IRQ. */
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 072/107] media: ti-vpe: cal: Register a media device
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (70 preceding siblings ...)
  2020-06-14 23:59 ` [PATCH v1 071/107] media: ti-vpe: cal: Store struct device in cal_dev Laurent Pinchart
@ 2020-06-14 23:59 ` Laurent Pinchart
  2020-06-14 23:59 ` [PATCH v1 073/107] media: ti-vpe: cal: Init formats in cal_ctx_v4l2_register() Laurent Pinchart
                   ` (36 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:59 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

Enable the media controller API by registering a media device and
initializing the media entities corresponding to the video devices. The
context initialization is slightly refactored as a result. The media
graph will be built in a subsequent change.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 71 ++++++++++++++++++++---------
 1 file changed, 49 insertions(+), 22 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index 205fb736e27a..9d338f3ee452 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -22,6 +22,7 @@
 #include <linux/slab.h>
 #include <linux/videodev2.h>
 
+#include <media/media-device.h>
 #include <media/v4l2-async.h>
 #include <media/v4l2-common.h>
 #include <media/v4l2-ctrls.h>
@@ -282,6 +283,7 @@ struct cal_dev {
 	struct device		*dev;
 
 	const struct cal_data	*data;
+	u32			revision;
 
 	/* Control Module handle */
 	struct regmap		*syscon_camerrx;
@@ -292,6 +294,7 @@ struct cal_dev {
 
 	struct cal_ctx		*ctx[CAL_NUM_CONTEXT];
 
+	struct media_device	mdev;
 	struct v4l2_device	v4l2_dev;
 	struct v4l2_async_notifier notifier;
 };
@@ -302,6 +305,7 @@ struct cal_dev {
 struct cal_ctx {
 	struct v4l2_ctrl_handler ctrl_handler;
 	struct video_device	vdev;
+	struct media_pad	pad;
 
 	struct cal_dev		*cal;
 	struct cal_camerarx	*phy;
@@ -2040,11 +2044,11 @@ static int cal_ctx_v4l2_init(struct cal_ctx *ctx)
 	struct vb2_queue *q = &ctx->vb_vidq;
 	int ret;
 
-	/* initialize locks */
+	INIT_LIST_HEAD(&ctx->vidq.active);
 	spin_lock_init(&ctx->slock);
 	mutex_init(&ctx->mutex);
 
-	/* initialize queue */
+	/* Initialize the vb2 queue. */
 	q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 	q->io_modes = VB2_MMAP | VB2_DMABUF | VB2_READ;
 	q->drv_priv = ctx;
@@ -2060,35 +2064,39 @@ static int cal_ctx_v4l2_init(struct cal_ctx *ctx)
 	if (ret)
 		return ret;
 
-	/* init video dma queues */
-	INIT_LIST_HEAD(&ctx->vidq.active);
-
+	/* Initialize the video device and media entity. */
 	*vfd = cal_videodev;
 	vfd->v4l2_dev = &ctx->cal->v4l2_dev;
 	vfd->queue = q;
+	snprintf(vfd->name, sizeof(vfd->name), "CAL output %u", ctx->index);
+	vfd->lock = &ctx->mutex;
+	video_set_drvdata(vfd, ctx);
+
+	ctx->pad.flags = MEDIA_PAD_FL_SINK;
+	ret = media_entity_pads_init(&vfd->entity, 1, &ctx->pad);
+	if (ret < 0)
+		return ret;
 
 	/* Initialize the control handler. */
 	ret = v4l2_ctrl_handler_init(hdl, 11);
 	if (ret < 0) {
 		ctx_err(ctx, "Failed to init ctrl handler\n");
-		return ret;
+		goto error;
 	}
 
 	vfd->ctrl_handler = hdl;
 
-	/*
-	 * Provide a mutex to v4l2 core. It will be used to protect
-	 * all fops and v4l2 ioctls.
-	 */
-	vfd->lock = &ctx->mutex;
-	video_set_drvdata(vfd, ctx);
-
 	return 0;
+
+error:
+	media_entity_cleanup(&vfd->entity);
+	return ret;
 }
 
 static void cal_ctx_v4l2_cleanup(struct cal_ctx *ctx)
 {
 	v4l2_ctrl_handler_free(&ctx->ctrl_handler);
+	media_entity_cleanup(&ctx->vdev.entity);
 }
 
 /* ------------------------------------------------------------------
@@ -2215,13 +2223,21 @@ static int cal_media_register(struct cal_dev *cal)
 {
 	int ret;
 
+	ret = media_device_register(&cal->mdev);
+	if (ret) {
+		cal_err(cal, "Failed to register media device\n");
+		return ret;
+	}
+
 	/*
 	 * Register the async notifier. This may trigger registration of the
 	 * V4L2 video devices if all subdevs are ready.
 	 */
 	ret = cal_async_notifier_register(cal);
-	if (ret)
+	if (ret) {
+		media_device_unregister(&cal->mdev);
 		return ret;
+	}
 
 	return 0;
 }
@@ -2241,6 +2257,7 @@ static void cal_media_unregister(struct cal_dev *cal)
 	}
 
 	cal_async_notifier_unregister(cal);
+	media_device_unregister(&cal->mdev);
 }
 
 /*
@@ -2249,12 +2266,21 @@ static void cal_media_unregister(struct cal_dev *cal)
  */
 static int cal_media_init(struct cal_dev *cal)
 {
+	struct media_device *mdev = &cal->mdev;
 	int ret;
 
+	mdev->dev = cal->dev;
+	mdev->hw_revision = cal->revision;
+	strscpy(mdev->model, "CAL", sizeof(mdev->model));
+	snprintf(mdev->bus_info, sizeof(mdev->bus_info), "platform:%s",
+		 dev_name(mdev->dev));
+	media_device_init(mdev);
+
 	/*
 	 * Initialize the V4L2 device (despite the function name, this performs
 	 * initialization, not registration).
 	 */
+	cal->v4l2_dev.mdev = mdev;
 	ret = v4l2_device_register(cal->dev, &cal->v4l2_dev);
 	if (ret) {
 		cal_err(cal, "Failed to register V4L2 device\n");
@@ -2281,6 +2307,8 @@ static void cal_media_cleanup(struct cal_dev *cal)
 	}
 
 	v4l2_device_unregister(&cal->v4l2_dev);
+	media_device_cleanup(&cal->mdev);
+
 	vb2_dma_contig_clear_max_seg_size(cal->dev);
 }
 
@@ -2337,23 +2365,22 @@ MODULE_DEVICE_TABLE(of, cal_of_match);
 
 static void cal_get_hwinfo(struct cal_dev *cal)
 {
-	u32 revision;
 	u32 hwinfo;
 
-	revision = reg_read(cal, CAL_HL_REVISION);
-	switch (FIELD_GET(CAL_HL_REVISION_SCHEME_MASK, revision)) {
+	cal->revision = reg_read(cal, CAL_HL_REVISION);
+	switch (FIELD_GET(CAL_HL_REVISION_SCHEME_MASK, cal->revision)) {
 	case CAL_HL_REVISION_SCHEME_H08:
 		cal_dbg(3, cal, "CAL HW revision %lu.%lu.%lu (0x%08x)\n",
-			FIELD_GET(CAL_HL_REVISION_MAJOR_MASK, revision),
-			FIELD_GET(CAL_HL_REVISION_MINOR_MASK, revision),
-			FIELD_GET(CAL_HL_REVISION_RTL_MASK, revision),
-			revision);
+			FIELD_GET(CAL_HL_REVISION_MAJOR_MASK, cal->revision),
+			FIELD_GET(CAL_HL_REVISION_MINOR_MASK, cal->revision),
+			FIELD_GET(CAL_HL_REVISION_RTL_MASK, cal->revision),
+			cal->revision);
 		break;
 
 	case CAL_HL_REVISION_SCHEME_LEGACY:
 	default:
 		cal_info(cal, "Unexpected CAL HW revision 0x%08x\n",
-			 revision);
+			 cal->revision);
 		break;
 	}
 
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 073/107] media: ti-vpe: cal: Init formats in cal_ctx_v4l2_register()
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (71 preceding siblings ...)
  2020-06-14 23:59 ` [PATCH v1 072/107] media: ti-vpe: cal: Register a media device Laurent Pinchart
@ 2020-06-14 23:59 ` Laurent Pinchart
  2020-06-14 23:59 ` [PATCH v1 074/107] media: ti-vpe: cal: Allocate cal_ctx active_fmt array dynamically Laurent Pinchart
                   ` (35 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:59 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

To prepare for splitting the V4L2 API support to a separate file, call
cal_ctx_v4l2_init_formats() from cal_ctx_v4l2_register().

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 83 ++++++++++++++---------------
 1 file changed, 39 insertions(+), 44 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index 9d338f3ee452..d81195006026 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -1938,39 +1938,6 @@ static const struct video_device cal_videodev = {
 			  V4L2_CAP_READWRITE,
 };
 
-static int cal_ctx_v4l2_register(struct cal_ctx *ctx)
-{
-	struct v4l2_ctrl_handler *hdl = &ctx->ctrl_handler;
-	struct video_device *vfd = &ctx->vdev;
-	int ret;
-
-	ret = v4l2_ctrl_add_handler(hdl, ctx->phy->sensor->ctrl_handler, NULL,
-				    true);
-	if (ret < 0) {
-		ctx_err(ctx, "Failed to add sensor ctrl handler\n");
-		return ret;
-	}
-
-	ret = video_register_device(vfd, VFL_TYPE_VIDEO, video_nr);
-	if (ret < 0) {
-		ctx_err(ctx, "Failed to register video device\n");
-		return ret;
-	}
-
-	ctx_info(ctx, "V4L2 device registered as %s\n",
-		 video_device_node_name(vfd));
-
-	return 0;
-}
-
-static void cal_ctx_v4l2_unregister(struct cal_ctx *ctx)
-{
-	ctx_dbg(1, ctx, "unregistering %s\n",
-		video_device_node_name(&ctx->vdev));
-
-	video_unregister_device(&ctx->vdev);
-}
-
 static int cal_ctx_v4l2_init_formats(struct cal_ctx *ctx)
 {
 	struct v4l2_subdev_mbus_code_enum mbus_code;
@@ -2037,6 +2004,43 @@ static int cal_ctx_v4l2_init_formats(struct cal_ctx *ctx)
 	return 0;
 }
 
+static int cal_ctx_v4l2_register(struct cal_ctx *ctx)
+{
+	struct v4l2_ctrl_handler *hdl = &ctx->ctrl_handler;
+	struct video_device *vfd = &ctx->vdev;
+	int ret;
+
+	ret = cal_ctx_v4l2_init_formats(ctx);
+	if (ret)
+		return ret;
+
+	ret = v4l2_ctrl_add_handler(hdl, ctx->phy->sensor->ctrl_handler, NULL,
+				    true);
+	if (ret < 0) {
+		ctx_err(ctx, "Failed to add sensor ctrl handler\n");
+		return ret;
+	}
+
+	ret = video_register_device(vfd, VFL_TYPE_VIDEO, video_nr);
+	if (ret < 0) {
+		ctx_err(ctx, "Failed to register video device\n");
+		return ret;
+	}
+
+	ctx_info(ctx, "V4L2 device registered as %s\n",
+		 video_device_node_name(vfd));
+
+	return 0;
+}
+
+static void cal_ctx_v4l2_unregister(struct cal_ctx *ctx)
+{
+	ctx_dbg(1, ctx, "unregistering %s\n",
+		video_device_node_name(&ctx->vdev));
+
+	video_unregister_device(&ctx->vdev);
+}
+
 static int cal_ctx_v4l2_init(struct cal_ctx *ctx)
 {
 	struct v4l2_ctrl_handler *hdl = &ctx->ctrl_handler;
@@ -2137,19 +2141,10 @@ static int cal_async_notifier_complete(struct v4l2_async_notifier *notifier)
 {
 	struct cal_dev *cal = container_of(notifier, struct cal_dev, notifier);
 	unsigned int i;
-	int ret;
 
 	for (i = 0; i < ARRAY_SIZE(cal->ctx); ++i) {
-		struct cal_ctx *ctx = cal->ctx[i];
-
-		if (!ctx)
-			continue;
-
-		ret = cal_ctx_v4l2_init_formats(ctx);
-		if (ret)
-			continue;
-
-		cal_ctx_v4l2_register(ctx);
+		if (cal->ctx[i])
+			cal_ctx_v4l2_register(cal->ctx[i]);
 	}
 
 	return 0;
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 074/107] media: ti-vpe: cal: Allocate cal_ctx active_fmt array dynamically
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (72 preceding siblings ...)
  2020-06-14 23:59 ` [PATCH v1 073/107] media: ti-vpe: cal: Init formats in cal_ctx_v4l2_register() Laurent Pinchart
@ 2020-06-14 23:59 ` Laurent Pinchart
  2020-06-14 23:59 ` [PATCH v1 075/107] media: ti-vpe: cal: Inline cal_camerarx_max_lanes() in its only caller Laurent Pinchart
                   ` (34 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:59 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

To avoid making the cal_ctx structure layoug depend on the size of the
cal_formats array, allocate the active_fmt array dynamically. This
prepares for splitting the driver in multiple files.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index d81195006026..3c24a7f7f1d9 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -325,7 +325,7 @@ struct cal_ctx {
 	struct v4l2_mbus_framefmt	m_fmt;
 
 	/* Current subdev enumerated format */
-	const struct cal_fmt	*active_fmt[ARRAY_SIZE(cal_formats)];
+	const struct cal_fmt	**active_fmt;
 	unsigned int		num_active_fmt;
 
 	unsigned int		sequence;
@@ -1947,7 +1947,13 @@ static int cal_ctx_v4l2_init_formats(struct cal_ctx *ctx)
 	int ret = 0;
 
 	/* Enumerate sub device formats and enable all matching local formats */
+	ctx->active_fmt = devm_kcalloc(ctx->cal->dev, ARRAY_SIZE(cal_formats),
+				       sizeof(*ctx->active_fmt), GFP_KERNEL);
+	if (!ctx->active_fmt)
+		return -ENOMEM;
+
 	ctx->num_active_fmt = 0;
+
 	for (j = 0, i = 0; ret != -EINVAL; ++j) {
 
 		memset(&mbus_code, 0, sizeof(mbus_code));
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 075/107] media: ti-vpe: cal: Inline cal_camerarx_max_lanes() in its only caller
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (73 preceding siblings ...)
  2020-06-14 23:59 ` [PATCH v1 074/107] media: ti-vpe: cal: Allocate cal_ctx active_fmt array dynamically Laurent Pinchart
@ 2020-06-14 23:59 ` Laurent Pinchart
  2020-06-14 23:59 ` [PATCH v1 076/107] media: ti-vpe: cal: Reorder camerarx functions to prepare refactoring Laurent Pinchart
                   ` (33 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:59 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

The cal_camerarx_max_lanes() function is a one-liner that has a single
caller. It doesn't improve readability. Inline it in its caller.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 10 ++--------
 1 file changed, 2 insertions(+), 8 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index 3c24a7f7f1d9..be5b0b70420c 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -481,19 +481,13 @@ static void cal_quickdump_regs(struct cal_dev *cal)
  * ------------------------------------------------------------------
  */
 
-static u32 cal_camerarx_max_lanes(struct cal_camerarx *phy)
-{
-	return phy->cal->data->camerarx[phy->instance].num_lanes;
-}
-
 static void cal_camerarx_enable(struct cal_camerarx *phy)
 {
-	u32 max_lanes;
+	u32 num_lanes = phy->cal->data->camerarx[phy->instance].num_lanes;
 
 	regmap_field_write(phy->fields[F_CAMMODE], 0);
 	/* Always enable all lanes at the phy control level */
-	max_lanes = (1 << cal_camerarx_max_lanes(phy)) - 1;
-	regmap_field_write(phy->fields[F_LANEENABLE], max_lanes);
+	regmap_field_write(phy->fields[F_LANEENABLE], (1 << num_lanes) - 1);
 	/* F_CSI_MODE is not present on every architecture */
 	if (phy->fields[F_CSI_MODE])
 		regmap_field_write(phy->fields[F_CSI_MODE], 1);
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 076/107] media: ti-vpe: cal: Reorder camerarx functions to prepare refactoring
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (74 preceding siblings ...)
  2020-06-14 23:59 ` [PATCH v1 075/107] media: ti-vpe: cal: Inline cal_camerarx_max_lanes() in its only caller Laurent Pinchart
@ 2020-06-14 23:59 ` Laurent Pinchart
  2020-06-14 23:59 ` [PATCH v1 077/107] media: ti-vpe: cal: Refactor camerarx start and stop Laurent Pinchart
                   ` (32 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:59 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

To prepare for the camerarx refactoring, reorder functions without any
functional change to ease review of the refactoring itself.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 436 ++++++++++++++--------------
 1 file changed, 218 insertions(+), 218 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index be5b0b70420c..3d6b5aeacc1b 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -481,6 +481,54 @@ static void cal_quickdump_regs(struct cal_dev *cal)
  * ------------------------------------------------------------------
  */
 
+static int cal_camerarx_get_external_info(struct cal_camerarx *phy)
+{
+	struct v4l2_ctrl *ctrl;
+
+	if (!phy->sensor)
+		return -ENODEV;
+
+	ctrl = v4l2_ctrl_find(phy->sensor->ctrl_handler, V4L2_CID_PIXEL_RATE);
+	if (!ctrl) {
+		phy_err(phy, "no pixel rate control in subdev: %s\n",
+			phy->sensor->name);
+		return -EPIPE;
+	}
+
+	phy->external_rate = v4l2_ctrl_g_ctrl_int64(ctrl);
+	phy_dbg(3, phy, "sensor Pixel Rate: %u\n", phy->external_rate);
+
+	return 0;
+}
+
+static void cal_camerarx_lane_config(struct cal_camerarx *phy)
+{
+	u32 val = reg_read(phy->cal, CAL_CSI2_COMPLEXIO_CFG(phy->instance));
+	u32 lane_mask = CAL_CSI2_COMPLEXIO_CFG_CLOCK_POSITION_MASK;
+	u32 polarity_mask = CAL_CSI2_COMPLEXIO_CFG_CLOCK_POL_MASK;
+	struct v4l2_fwnode_bus_mipi_csi2 *mipi_csi2 =
+		&phy->endpoint.bus.mipi_csi2;
+	int lane;
+
+	set_field(&val, mipi_csi2->clock_lane + 1, lane_mask);
+	set_field(&val, mipi_csi2->lane_polarities[0], polarity_mask);
+	for (lane = 0; lane < mipi_csi2->num_data_lanes; lane++) {
+		/*
+		 * Every lane are one nibble apart starting with the
+		 * clock followed by the data lanes so shift masks by 4.
+		 */
+		lane_mask <<= 4;
+		polarity_mask <<= 4;
+		set_field(&val, mipi_csi2->data_lanes[lane] + 1, lane_mask);
+		set_field(&val, mipi_csi2->lane_polarities[lane + 1],
+			  polarity_mask);
+	}
+
+	reg_write(phy->cal, CAL_CSI2_COMPLEXIO_CFG(phy->instance), val);
+	phy_dbg(3, phy, "CAL_CSI2_COMPLEXIO_CFG(%d) = 0x%08x\n",
+		phy->instance, val);
+}
+
 static void cal_camerarx_enable(struct cal_camerarx *phy)
 {
 	u32 num_lanes = phy->cal->data->camerarx[phy->instance].num_lanes;
@@ -499,120 +547,6 @@ static void cal_camerarx_disable(struct cal_camerarx *phy)
 	regmap_field_write(phy->fields[F_CTRLCLKEN], 0);
 }
 
-/*
- *   Errata i913: CSI2 LDO Needs to be disabled when module is powered on
- *
- *   Enabling CSI2 LDO shorts it to core supply. It is crucial the 2 CSI2
- *   LDOs on the device are disabled if CSI-2 module is powered on
- *   (0x4845 B304 | 0x4845 B384 [28:27] = 0x1) or in ULPS (0x4845 B304
- *   | 0x4845 B384 [28:27] = 0x2) mode. Common concerns include: high
- *   current draw on the module supply in active mode.
- *
- *   Errata does not apply when CSI-2 module is powered off
- *   (0x4845 B304 | 0x4845 B384 [28:27] = 0x0).
- *
- * SW Workaround:
- *	Set the following register bits to disable the LDO,
- *	which is essentially CSI2 REG10 bit 6:
- *
- *		Core 0:  0x4845 B828 = 0x0000 0040
- *		Core 1:  0x4845 B928 = 0x0000 0040
- */
-static void cal_camerarx_i913_errata(struct cal_camerarx *phy)
-{
-	u32 reg10 = reg_read(phy, CAL_CSI2_PHY_REG10);
-
-	set_field(&reg10, 1, CAL_CSI2_PHY_REG10_I933_LDO_DISABLE_MASK);
-
-	phy_dbg(1, phy, "CSI2_%d_REG10 = 0x%08x\n", phy->instance, reg10);
-	reg_write(phy, CAL_CSI2_PHY_REG10, reg10);
-}
-
-/*
- * Enable the expected IRQ sources
- */
-static void cal_camerarx_enable_irqs(struct cal_camerarx *phy)
-{
-	u32 val;
-
-	const u32 cio_err_mask =
-		CAL_CSI2_COMPLEXIO_IRQ_LANE_ERRORS_MASK |
-		CAL_CSI2_COMPLEXIO_IRQ_FIFO_OVR_MASK |
-		CAL_CSI2_COMPLEXIO_IRQ_SHORT_PACKET_MASK |
-		CAL_CSI2_COMPLEXIO_IRQ_ECC_NO_CORRECTION_MASK;
-
-	/* Enable CIO error irqs */
-	reg_write(phy->cal, CAL_HL_IRQENABLE_SET(0),
-		  CAL_HL_IRQ_CIO_MASK(phy->instance));
-	reg_write(phy->cal, CAL_CSI2_COMPLEXIO_IRQENABLE(phy->instance),
-		  cio_err_mask);
-
-	/* Always enable OCPO error */
-	reg_write(phy->cal, CAL_HL_IRQENABLE_SET(0), CAL_HL_IRQ_OCPO_ERR_MASK);
-
-	/* Enable IRQ_WDMA_END 0/1 */
-	val = 0;
-	set_field(&val, 1, CAL_HL_IRQ_MASK(phy->instance));
-	reg_write(phy->cal, CAL_HL_IRQENABLE_SET(1), val);
-	/* Enable IRQ_WDMA_START 0/1 */
-	val = 0;
-	set_field(&val, 1, CAL_HL_IRQ_MASK(phy->instance));
-	reg_write(phy->cal, CAL_HL_IRQENABLE_SET(2), val);
-	/* Todo: Add VC_IRQ and CSI2_COMPLEXIO_IRQ handling */
-	reg_write(phy->cal, CAL_CSI2_VC_IRQENABLE(0), 0xFF000000);
-}
-
-static void cal_camerarx_disable_irqs(struct cal_camerarx *phy)
-{
-	u32 val;
-
-	/* Disable CIO error irqs */
-	reg_write(phy->cal, CAL_HL_IRQENABLE_CLR(0),
-		  CAL_HL_IRQ_CIO_MASK(phy->instance));
-	reg_write(phy->cal, CAL_CSI2_COMPLEXIO_IRQENABLE(phy->instance),
-		  0);
-
-	/* Disable IRQ_WDMA_END 0/1 */
-	val = 0;
-	set_field(&val, 1, CAL_HL_IRQ_MASK(phy->instance));
-	reg_write(phy->cal, CAL_HL_IRQENABLE_CLR(1), val);
-	/* Disable IRQ_WDMA_START 0/1 */
-	val = 0;
-	set_field(&val, 1, CAL_HL_IRQ_MASK(phy->instance));
-	reg_write(phy->cal, CAL_HL_IRQENABLE_CLR(2), val);
-	/* Todo: Add VC_IRQ and CSI2_COMPLEXIO_IRQ handling */
-	reg_write(phy->cal, CAL_CSI2_VC_IRQENABLE(0), 0);
-}
-
-static void cal_camerarx_power(struct cal_camerarx *phy, bool enable)
-{
-	u32 target_state;
-	unsigned int i;
-
-	target_state = enable ? CAL_CSI2_COMPLEXIO_CFG_PWR_CMD_STATE_ON :
-		       CAL_CSI2_COMPLEXIO_CFG_PWR_CMD_STATE_OFF;
-
-	reg_write_field(phy->cal, CAL_CSI2_COMPLEXIO_CFG(phy->instance),
-			target_state, CAL_CSI2_COMPLEXIO_CFG_PWR_CMD_MASK);
-
-	for (i = 0; i < 10; i++) {
-		u32 current_state;
-
-		current_state = reg_read_field(phy->cal,
-					       CAL_CSI2_COMPLEXIO_CFG(phy->instance),
-					       CAL_CSI2_COMPLEXIO_CFG_PWR_STATUS_MASK);
-
-		if (current_state == target_state)
-			break;
-
-		usleep_range(1000, 1100);
-	}
-
-	if (i == 10)
-		phy_err(phy, "Failed to power %s complexio\n",
-			enable ? "up" : "down");
-}
-
 /*
  * TCLK values are OK at their reset values
  */
@@ -663,6 +597,94 @@ static void cal_camerarx_config(struct cal_camerarx *phy,
 	reg_write(phy, CAL_CSI2_PHY_REG1, reg1);
 }
 
+static void cal_camerarx_power(struct cal_camerarx *phy, bool enable)
+{
+	u32 target_state;
+	unsigned int i;
+
+	target_state = enable ? CAL_CSI2_COMPLEXIO_CFG_PWR_CMD_STATE_ON :
+		       CAL_CSI2_COMPLEXIO_CFG_PWR_CMD_STATE_OFF;
+
+	reg_write_field(phy->cal, CAL_CSI2_COMPLEXIO_CFG(phy->instance),
+			target_state, CAL_CSI2_COMPLEXIO_CFG_PWR_CMD_MASK);
+
+	for (i = 0; i < 10; i++) {
+		u32 current_state;
+
+		current_state = reg_read_field(phy->cal,
+					       CAL_CSI2_COMPLEXIO_CFG(phy->instance),
+					       CAL_CSI2_COMPLEXIO_CFG_PWR_STATUS_MASK);
+
+		if (current_state == target_state)
+			break;
+
+		usleep_range(1000, 1100);
+	}
+
+	if (i == 10)
+		phy_err(phy, "Failed to power %s complexio\n",
+			enable ? "up" : "down");
+}
+
+static void cal_camerarx_wait_reset(struct cal_camerarx *phy)
+{
+	unsigned long timeout;
+
+	timeout = jiffies + msecs_to_jiffies(750);
+	while (time_before(jiffies, timeout)) {
+		if (reg_read_field(phy->cal,
+				   CAL_CSI2_COMPLEXIO_CFG(phy->instance),
+				   CAL_CSI2_COMPLEXIO_CFG_RESET_DONE_MASK) ==
+		    CAL_CSI2_COMPLEXIO_CFG_RESET_DONE_RESETCOMPLETED)
+			break;
+		usleep_range(500, 5000);
+	}
+
+	if (reg_read_field(phy->cal, CAL_CSI2_COMPLEXIO_CFG(phy->instance),
+			   CAL_CSI2_COMPLEXIO_CFG_RESET_DONE_MASK) !=
+			   CAL_CSI2_COMPLEXIO_CFG_RESET_DONE_RESETCOMPLETED)
+		phy_err(phy, "Timeout waiting for Complex IO reset done\n");
+}
+
+static void cal_camerarx_wait_stop_state(struct cal_camerarx *phy)
+{
+	unsigned long timeout;
+
+	timeout = jiffies + msecs_to_jiffies(750);
+	while (time_before(jiffies, timeout)) {
+		if (reg_read_field(phy->cal,
+				   CAL_CSI2_TIMING(phy->instance),
+				   CAL_CSI2_TIMING_FORCE_RX_MODE_IO1_MASK) == 0)
+			break;
+		usleep_range(500, 5000);
+	}
+
+	if (reg_read_field(phy->cal, CAL_CSI2_TIMING(phy->instance),
+			   CAL_CSI2_TIMING_FORCE_RX_MODE_IO1_MASK) != 0)
+		phy_err(phy, "Timeout waiting for stop state\n");
+}
+
+static void cal_camerarx_wait_ready(struct cal_camerarx *phy)
+{
+	/* Steps
+	 *  2. Wait for completion of reset
+	 *          Note if the external sensor is not sending byte clock,
+	 *          the reset will timeout
+	 *  4.Force FORCERXMODE
+	 *      G. Wait for all enabled lane to reach stop state
+	 *      H. Disable pull down using pad control
+	 */
+
+	/* 2. Wait for reset completion */
+	cal_camerarx_wait_reset(phy);
+
+	/* 4. G. Wait for all enabled lane to reach stop state */
+	cal_camerarx_wait_stop_state(phy);
+
+	phy_dbg(1, phy, "CSI2_%d_REG1 = 0x%08x (Bit(31,28) should be set!)\n",
+		phy->instance, reg_read(phy, CAL_CSI2_PHY_REG1));
+}
+
 static void cal_camerarx_init(struct cal_camerarx *phy,
 			      const struct cal_fmt *fmt)
 {
@@ -734,65 +756,6 @@ static void cal_camerarx_init(struct cal_camerarx *phy,
 	cal_camerarx_power(phy, true);
 }
 
-static void cal_camerarx_wait_reset(struct cal_camerarx *phy)
-{
-	unsigned long timeout;
-
-	timeout = jiffies + msecs_to_jiffies(750);
-	while (time_before(jiffies, timeout)) {
-		if (reg_read_field(phy->cal,
-				   CAL_CSI2_COMPLEXIO_CFG(phy->instance),
-				   CAL_CSI2_COMPLEXIO_CFG_RESET_DONE_MASK) ==
-		    CAL_CSI2_COMPLEXIO_CFG_RESET_DONE_RESETCOMPLETED)
-			break;
-		usleep_range(500, 5000);
-	}
-
-	if (reg_read_field(phy->cal, CAL_CSI2_COMPLEXIO_CFG(phy->instance),
-			   CAL_CSI2_COMPLEXIO_CFG_RESET_DONE_MASK) !=
-			   CAL_CSI2_COMPLEXIO_CFG_RESET_DONE_RESETCOMPLETED)
-		phy_err(phy, "Timeout waiting for Complex IO reset done\n");
-}
-
-static void cal_camerarx_wait_stop_state(struct cal_camerarx *phy)
-{
-	unsigned long timeout;
-
-	timeout = jiffies + msecs_to_jiffies(750);
-	while (time_before(jiffies, timeout)) {
-		if (reg_read_field(phy->cal,
-				   CAL_CSI2_TIMING(phy->instance),
-				   CAL_CSI2_TIMING_FORCE_RX_MODE_IO1_MASK) == 0)
-			break;
-		usleep_range(500, 5000);
-	}
-
-	if (reg_read_field(phy->cal, CAL_CSI2_TIMING(phy->instance),
-			   CAL_CSI2_TIMING_FORCE_RX_MODE_IO1_MASK) != 0)
-		phy_err(phy, "Timeout waiting for stop state\n");
-}
-
-static void cal_camerarx_wait_ready(struct cal_camerarx *phy)
-{
-	/* Steps
-	 *  2. Wait for completion of reset
-	 *          Note if the external sensor is not sending byte clock,
-	 *          the reset will timeout
-	 *  4.Force FORCERXMODE
-	 *      G. Wait for all enabled lane to reach stop state
-	 *      H. Disable pull down using pad control
-	 */
-
-	/* 2. Wait for reset completion */
-	cal_camerarx_wait_reset(phy);
-
-	/* 4. G. Wait for all enabled lane to reach stop state */
-	cal_camerarx_wait_stop_state(phy);
-
-	phy_dbg(1, phy, "CSI2_%d_REG1 = 0x%08x (Bit(31,28) should be set!)\n",
-		phy->instance, reg_read(phy, CAL_CSI2_PHY_REG1));
-}
-
 static void cal_camerarx_deinit(struct cal_camerarx *phy)
 {
 	unsigned int i;
@@ -822,32 +785,89 @@ static void cal_camerarx_deinit(struct cal_camerarx *phy)
 	cal_camerarx_disable(phy);
 }
 
-static void cal_camerarx_lane_config(struct cal_camerarx *phy)
+/*
+ *   Errata i913: CSI2 LDO Needs to be disabled when module is powered on
+ *
+ *   Enabling CSI2 LDO shorts it to core supply. It is crucial the 2 CSI2
+ *   LDOs on the device are disabled if CSI-2 module is powered on
+ *   (0x4845 B304 | 0x4845 B384 [28:27] = 0x1) or in ULPS (0x4845 B304
+ *   | 0x4845 B384 [28:27] = 0x2) mode. Common concerns include: high
+ *   current draw on the module supply in active mode.
+ *
+ *   Errata does not apply when CSI-2 module is powered off
+ *   (0x4845 B304 | 0x4845 B384 [28:27] = 0x0).
+ *
+ * SW Workaround:
+ *	Set the following register bits to disable the LDO,
+ *	which is essentially CSI2 REG10 bit 6:
+ *
+ *		Core 0:  0x4845 B828 = 0x0000 0040
+ *		Core 1:  0x4845 B928 = 0x0000 0040
+ */
+static void cal_camerarx_i913_errata(struct cal_camerarx *phy)
 {
-	u32 val = reg_read(phy->cal, CAL_CSI2_COMPLEXIO_CFG(phy->instance));
-	u32 lane_mask = CAL_CSI2_COMPLEXIO_CFG_CLOCK_POSITION_MASK;
-	u32 polarity_mask = CAL_CSI2_COMPLEXIO_CFG_CLOCK_POL_MASK;
-	struct v4l2_fwnode_bus_mipi_csi2 *mipi_csi2 =
-		&phy->endpoint.bus.mipi_csi2;
-	int lane;
-
-	set_field(&val, mipi_csi2->clock_lane + 1, lane_mask);
-	set_field(&val, mipi_csi2->lane_polarities[0], polarity_mask);
-	for (lane = 0; lane < mipi_csi2->num_data_lanes; lane++) {
-		/*
-		 * Every lane are one nibble apart starting with the
-		 * clock followed by the data lanes so shift masks by 4.
-		 */
-		lane_mask <<= 4;
-		polarity_mask <<= 4;
-		set_field(&val, mipi_csi2->data_lanes[lane] + 1, lane_mask);
-		set_field(&val, mipi_csi2->lane_polarities[lane + 1],
-			  polarity_mask);
-	}
-
-	reg_write(phy->cal, CAL_CSI2_COMPLEXIO_CFG(phy->instance), val);
-	phy_dbg(3, phy, "CAL_CSI2_COMPLEXIO_CFG(%d) = 0x%08x\n",
-		phy->instance, val);
+	u32 reg10 = reg_read(phy, CAL_CSI2_PHY_REG10);
+
+	set_field(&reg10, 1, CAL_CSI2_PHY_REG10_I933_LDO_DISABLE_MASK);
+
+	phy_dbg(1, phy, "CSI2_%d_REG10 = 0x%08x\n", phy->instance, reg10);
+	reg_write(phy, CAL_CSI2_PHY_REG10, reg10);
+}
+
+/*
+ * Enable the expected IRQ sources
+ */
+static void cal_camerarx_enable_irqs(struct cal_camerarx *phy)
+{
+	u32 val;
+
+	const u32 cio_err_mask =
+		CAL_CSI2_COMPLEXIO_IRQ_LANE_ERRORS_MASK |
+		CAL_CSI2_COMPLEXIO_IRQ_FIFO_OVR_MASK |
+		CAL_CSI2_COMPLEXIO_IRQ_SHORT_PACKET_MASK |
+		CAL_CSI2_COMPLEXIO_IRQ_ECC_NO_CORRECTION_MASK;
+
+	/* Enable CIO error irqs */
+	reg_write(phy->cal, CAL_HL_IRQENABLE_SET(0),
+		  CAL_HL_IRQ_CIO_MASK(phy->instance));
+	reg_write(phy->cal, CAL_CSI2_COMPLEXIO_IRQENABLE(phy->instance),
+		  cio_err_mask);
+
+	/* Always enable OCPO error */
+	reg_write(phy->cal, CAL_HL_IRQENABLE_SET(0), CAL_HL_IRQ_OCPO_ERR_MASK);
+
+	/* Enable IRQ_WDMA_END 0/1 */
+	val = 0;
+	set_field(&val, 1, CAL_HL_IRQ_MASK(phy->instance));
+	reg_write(phy->cal, CAL_HL_IRQENABLE_SET(1), val);
+	/* Enable IRQ_WDMA_START 0/1 */
+	val = 0;
+	set_field(&val, 1, CAL_HL_IRQ_MASK(phy->instance));
+	reg_write(phy->cal, CAL_HL_IRQENABLE_SET(2), val);
+	/* Todo: Add VC_IRQ and CSI2_COMPLEXIO_IRQ handling */
+	reg_write(phy->cal, CAL_CSI2_VC_IRQENABLE(0), 0xFF000000);
+}
+
+static void cal_camerarx_disable_irqs(struct cal_camerarx *phy)
+{
+	u32 val;
+
+	/* Disable CIO error irqs */
+	reg_write(phy->cal, CAL_HL_IRQENABLE_CLR(0),
+		  CAL_HL_IRQ_CIO_MASK(phy->instance));
+	reg_write(phy->cal, CAL_CSI2_COMPLEXIO_IRQENABLE(phy->instance),
+		  0);
+
+	/* Disable IRQ_WDMA_END 0/1 */
+	val = 0;
+	set_field(&val, 1, CAL_HL_IRQ_MASK(phy->instance));
+	reg_write(phy->cal, CAL_HL_IRQENABLE_CLR(1), val);
+	/* Disable IRQ_WDMA_START 0/1 */
+	val = 0;
+	set_field(&val, 1, CAL_HL_IRQ_MASK(phy->instance));
+	reg_write(phy->cal, CAL_HL_IRQENABLE_CLR(2), val);
+	/* Todo: Add VC_IRQ and CSI2_COMPLEXIO_IRQ handling */
+	reg_write(phy->cal, CAL_CSI2_VC_IRQENABLE(0), 0);
 }
 
 static void cal_camerarx_ppi_enable(struct cal_camerarx *phy)
@@ -863,26 +883,6 @@ static void cal_camerarx_ppi_disable(struct cal_camerarx *phy)
 			0, CAL_CSI2_PPI_CTRL_IF_EN_MASK);
 }
 
-static int cal_camerarx_get_external_info(struct cal_camerarx *phy)
-{
-	struct v4l2_ctrl *ctrl;
-
-	if (!phy->sensor)
-		return -ENODEV;
-
-	ctrl = v4l2_ctrl_find(phy->sensor->ctrl_handler, V4L2_CID_PIXEL_RATE);
-	if (!ctrl) {
-		phy_err(phy, "no pixel rate control in subdev: %s\n",
-			phy->sensor->name);
-		return -EPIPE;
-	}
-
-	phy->external_rate = v4l2_ctrl_g_ctrl_int64(ctrl);
-	phy_dbg(3, phy, "sensor Pixel Rate: %u\n", phy->external_rate);
-
-	return 0;
-}
-
 static int cal_camerarx_regmap_init(struct cal_dev *cal,
 				    struct cal_camerarx *phy)
 {
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 077/107] media: ti-vpe: cal: Refactor camerarx start and stop
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (75 preceding siblings ...)
  2020-06-14 23:59 ` [PATCH v1 076/107] media: ti-vpe: cal: Reorder camerarx functions to prepare refactoring Laurent Pinchart
@ 2020-06-14 23:59 ` Laurent Pinchart
  2020-06-14 23:59 ` [PATCH v1 078/107] media: ti-vpe: cal: Don't store external rate in cal_camerarx Laurent Pinchart
                   ` (31 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:59 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

Refactor the camerarx start and stop procedure to group all the
corresponding operations in two functions, cal_camerarx_start() and
cal_camerarx_stop() instead of splitting them in multiple steps called
from the vb2 stream start and stop functions. This reduces the coupling
between the camerarx and the contexts, and better models the camerarx
hardware.

The cal_camerarx_start() is a reworked version of cal_camerarx_init()
with the description of the start procedure updated to match the AM65x,
DRA7[124567]x and DRA80xM TRMs. The cal_camerarx_wait_ready() function
is inlined in cal_camerarx_start() to better describe the start
procedure.

No functional change is included in the camerarx start and stop
procedures themselves, but the interleaving of the start steps with the
context configuration has been changed in cal_start_streaming().

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 170 +++++++++++++++-------------
 1 file changed, 94 insertions(+), 76 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index 3d6b5aeacc1b..8326db0e4197 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -664,54 +664,50 @@ static void cal_camerarx_wait_stop_state(struct cal_camerarx *phy)
 		phy_err(phy, "Timeout waiting for stop state\n");
 }
 
-static void cal_camerarx_wait_ready(struct cal_camerarx *phy)
-{
-	/* Steps
-	 *  2. Wait for completion of reset
-	 *          Note if the external sensor is not sending byte clock,
-	 *          the reset will timeout
-	 *  4.Force FORCERXMODE
-	 *      G. Wait for all enabled lane to reach stop state
-	 *      H. Disable pull down using pad control
-	 */
-
-	/* 2. Wait for reset completion */
-	cal_camerarx_wait_reset(phy);
-
-	/* 4. G. Wait for all enabled lane to reach stop state */
-	cal_camerarx_wait_stop_state(phy);
-
-	phy_dbg(1, phy, "CSI2_%d_REG1 = 0x%08x (Bit(31,28) should be set!)\n",
-		phy->instance, reg_read(phy, CAL_CSI2_PHY_REG1));
-}
-
-static void cal_camerarx_init(struct cal_camerarx *phy,
+static int cal_camerarx_start(struct cal_camerarx *phy,
 			      const struct cal_fmt *fmt)
 {
-	u32 val;
 	u32 sscounter;
+	u32 val;
+	int ret;
 
-	/* Steps
-	 *  1. Configure D-PHY mode and enable required lanes
-	 *  2. Reset complex IO - Wait for completion of reset
-	 *          Note if the external sensor is not sending byte clock,
-	 *          the reset will timeout
-	 *  3 Program Stop States
-	 *      A. Program THS_TERM, THS_SETTLE, etc... Timings parameters
-	 *              in terms of DDR clock periods
-	 *      B. Enable stop state transition timeouts
-	 *  4.Force FORCERXMODE
-	 *      D. Enable pull down using pad control
-	 *      E. Power up PHY
-	 *      F. Wait for power up completion
-	 *      G. Wait for all enabled lane to reach stop state
-	 *      H. Disable pull down using pad control
+	ret = cal_camerarx_get_external_info(phy);
+	if (ret < 0)
+		return ret;
+
+	ret = v4l2_subdev_call(phy->sensor, core, s_power, 1);
+	if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV) {
+		phy_err(phy, "power on failed in subdev\n");
+		return ret;
+	}
+
+	/*
+	 * CSI-2 PHY Link Initialization Sequence, according to the DRA74xP /
+	 * DRA75xP / DRA76xP / DRA77xP TRM. The DRA71x / DRA72x and the AM65x /
+	 * DRA80xM TRMs have a a slightly simplified sequence.
 	 */
 
-	/* 1. Configure D-PHY mode and enable required lanes */
+	/*
+	 * 1. Configure all CSI-2 low level protocol registers to be ready to
+	 *    receive signals/data from the CSI-2 PHY.
+	 *
+	 *    i.-v. Configure the lanes position and polarity.
+	 */
+	cal_camerarx_lane_config(phy);
+
+	/*
+	 *    vi.-vii. Configure D-PHY mode, enable the required lanes and
+	 *             enable the CAMERARX clock.
+	 */
 	cal_camerarx_enable(phy);
 
-	/* 2. Reset complex IO - Do not wait for reset completion */
+	/*
+	 * 2. CSI PHY and link initialization sequence.
+	 *
+	 *    a. Deassert the CSI-2 PHY reset. Do not wait for reset completion
+	 *       at this point, as it requires the external sensor to send the
+	 *       CSI-2 HS clock.
+	 */
 	reg_write_field(phy->cal, CAL_CSI2_COMPLEXIO_CFG(phy->instance),
 			CAL_CSI2_COMPLEXIO_CFG_RESET_CTRL_OPERATIONAL,
 			CAL_CSI2_COMPLEXIO_CFG_RESET_CTRL_MASK);
@@ -719,19 +715,20 @@ static void cal_camerarx_init(struct cal_camerarx *phy,
 		phy->instance,
 		reg_read(phy->cal, CAL_CSI2_COMPLEXIO_CFG(phy->instance)));
 
-	/* Dummy read to allow SCP reset to complete */
+	/* Dummy read to allow SCP reset to complete. */
 	reg_read(phy, CAL_CSI2_PHY_REG0);
 
-	/* 3.A. Program Phy Timing Parameters */
+	/* Program the PHY timing parameters. */
 	cal_camerarx_config(phy, fmt);
 
-	/* 3.B. Program Stop States */
 	/*
+	 *    b. Assert the FORCERXMODE signal.
+	 *
 	 * The stop-state-counter is based on fclk cycles, and we always use
 	 * the x16 and x4 settings, so stop-state-timeout =
 	 * fclk-cycle * 16 * 4 * counter.
 	 *
-	 * Stop-state-timeout must be more than 100us as per CSI2 spec, so we
+	 * Stop-state-timeout must be more than 100us as per CSI-2 spec, so we
 	 * calculate a timeout that's 100us (rounding up).
 	 */
 	sscounter = DIV_ROUND_UP(clk_get_rate(phy->cal->fclk), 10000 *  16 * 4);
@@ -745,24 +742,63 @@ static void cal_camerarx_init(struct cal_camerarx *phy,
 		phy->instance,
 		reg_read(phy->cal, CAL_CSI2_TIMING(phy->instance)));
 
-	/* 4. Force FORCERXMODE */
+	/* Assert the FORCERXMODE signal. */
 	reg_write_field(phy->cal, CAL_CSI2_TIMING(phy->instance),
 			1, CAL_CSI2_TIMING_FORCE_RX_MODE_IO1_MASK);
 	phy_dbg(3, phy, "CAL_CSI2_TIMING(%d) = 0x%08x Force RXMODE\n",
 		phy->instance,
 		reg_read(phy->cal, CAL_CSI2_TIMING(phy->instance)));
 
-	/* E. Power up the PHY using the complex IO */
+	/*
+	 * c. Connect pull-down on CSI-2 PHY link (using pad control).
+	 *
+	 * This is not required on DRA71x, DRA72x, AM65x and DRA80xM. Not
+	 * implemented.
+	 */
+
+	/*
+	 * d. Power up the CSI-2 PHY.
+	 * e. Check whether the state status reaches the ON state.
+	 */
 	cal_camerarx_power(phy, true);
+
+	/*
+	 * Start the sensor to enable the CSI-2 HS clock. We can now wait for
+	 * CSI-2 PHY reset to complete.
+	 */
+	ret = v4l2_subdev_call(phy->sensor, video, s_stream, 1);
+	if (ret) {
+		v4l2_subdev_call(phy->sensor, core, s_power, 0);
+		phy_err(phy, "stream on failed in subdev\n");
+		return ret;
+	}
+
+	cal_camerarx_wait_reset(phy);
+
+	/* f. Wait for STOPSTATE=1 for all enabled lane modules. */
+	cal_camerarx_wait_stop_state(phy);
+
+	phy_dbg(1, phy, "CSI2_%u_REG1 = 0x%08x (bits 31-28 should be set)\n",
+		phy->instance, reg_read(phy, CAL_CSI2_PHY_REG1));
+
+	/*
+	 * g. Disable pull-down on CSI-2 PHY link (using pad control).
+	 *
+	 * This is not required on DRA71x, DRA72x, AM65x and DRA80xM. Not
+	 * implemented.
+	 */
+
+	return 0;
 }
 
-static void cal_camerarx_deinit(struct cal_camerarx *phy)
+static void cal_camerarx_stop(struct cal_camerarx *phy)
 {
 	unsigned int i;
+	int ret;
 
 	cal_camerarx_power(phy, false);
 
-	/* Assert Comple IO Reset */
+	/* Assert Complex IO Reset */
 	reg_write_field(phy->cal, CAL_CSI2_COMPLEXIO_CFG(phy->instance),
 			CAL_CSI2_COMPLEXIO_CFG_RESET_CTRL,
 			CAL_CSI2_COMPLEXIO_CFG_RESET_CTRL_MASK);
@@ -783,6 +819,13 @@ static void cal_camerarx_deinit(struct cal_camerarx *phy)
 
 	/* Disable the phy */
 	cal_camerarx_disable(phy);
+
+	if (v4l2_subdev_call(phy->sensor, video, s_stream, 0))
+		phy_err(phy, "stream off failed in subdev\n");
+
+	ret = v4l2_subdev_call(phy->sensor, core, s_power, 0);
+	if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV)
+		phy_err(phy, "power off failed in subdev\n");
 }
 
 /*
@@ -1799,36 +1842,19 @@ static int cal_start_streaming(struct vb2_queue *vq, unsigned int count)
 	addr = vb2_dma_contig_plane_dma_addr(&ctx->cur_frm->vb.vb2_buf, 0);
 	ctx->sequence = 0;
 
-	ret = cal_camerarx_get_external_info(ctx->phy);
-	if (ret < 0)
-		goto err;
-
-	ret = v4l2_subdev_call(ctx->phy->sensor, core, s_power, 1);
-	if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV) {
-		ctx_err(ctx, "power on failed in subdev\n");
-		goto err;
-	}
-
 	pm_runtime_get_sync(ctx->cal->dev);
 
 	cal_ctx_csi2_config(ctx);
 	cal_ctx_pix_proc_config(ctx);
 	cal_ctx_wr_dma_config(ctx, ctx->v_fmt.fmt.pix.bytesperline,
 			      ctx->v_fmt.fmt.pix.height);
-	cal_camerarx_lane_config(ctx->phy);
 
 	cal_camerarx_enable_irqs(ctx->phy);
-	cal_camerarx_init(ctx->phy, ctx->fmt);
 
-	ret = v4l2_subdev_call(ctx->phy->sensor, video, s_stream, 1);
-	if (ret) {
-		v4l2_subdev_call(ctx->phy->sensor, core, s_power, 0);
-		ctx_err(ctx, "stream on failed in subdev\n");
-		pm_runtime_put_sync(ctx->cal->dev);
+	ret = cal_camerarx_start(ctx->phy, ctx->fmt);
+	if (ret)
 		goto err;
-	}
 
-	cal_camerarx_wait_ready(ctx->phy);
 	cal_ctx_wr_dma_addr(ctx, addr);
 	cal_camerarx_ppi_enable(ctx->phy);
 
@@ -1857,7 +1883,6 @@ static void cal_stop_streaming(struct vb2_queue *vq)
 	struct cal_buffer *buf, *tmp;
 	unsigned long timeout;
 	unsigned long flags;
-	int ret;
 	bool dma_act;
 
 	cal_camerarx_ppi_disable(ctx->phy);
@@ -1877,14 +1902,7 @@ static void cal_stop_streaming(struct vb2_queue *vq)
 		ctx_err(ctx, "failed to disable dma cleanly\n");
 
 	cal_camerarx_disable_irqs(ctx->phy);
-	cal_camerarx_deinit(ctx->phy);
-
-	if (v4l2_subdev_call(ctx->phy->sensor, video, s_stream, 0))
-		ctx_err(ctx, "stream off failed in subdev\n");
-
-	ret = v4l2_subdev_call(ctx->phy->sensor, core, s_power, 0);
-	if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV)
-		ctx_err(ctx, "power off failed in subdev\n");
+	cal_camerarx_stop(ctx->phy);
 
 	/* Release all active buffers */
 	spin_lock_irqsave(&ctx->slock, flags);
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 078/107] media: ti-vpe: cal: Don't store external rate in cal_camerarx
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (76 preceding siblings ...)
  2020-06-14 23:59 ` [PATCH v1 077/107] media: ti-vpe: cal: Refactor camerarx start and stop Laurent Pinchart
@ 2020-06-14 23:59 ` Laurent Pinchart
  2020-06-17  9:56   ` Kieran Bingham
  2020-06-14 23:59 ` [PATCH v1 079/107] media: ti-vpe: cal: Remove unneeded phy->sensor NULL check Laurent Pinchart
                   ` (30 subsequent siblings)
  108 siblings, 1 reply; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:59 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

The external pixel rate is retrieved when starting the camerarx and only
used then. There's no need to store it in the cal_camerarx structure, it
can be returned by cal_camerarx_get_external_info() and explicitly
passed to cal_camerarx_config().

While at it, rename cal_camerarx_get_external_info() to
cal_camerarx_get_external_rate() to better reflect the function's
purpose.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 24 ++++++++++++------------
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index 8326db0e4197..a11457909134 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -272,7 +272,6 @@ struct cal_camerarx {
 	struct v4l2_fwnode_endpoint	endpoint;
 	struct device_node	*sensor_node;
 	struct v4l2_subdev	*sensor;
-	unsigned int		external_rate;
 };
 
 struct cal_dev {
@@ -481,9 +480,10 @@ static void cal_quickdump_regs(struct cal_dev *cal)
  * ------------------------------------------------------------------
  */
 
-static int cal_camerarx_get_external_info(struct cal_camerarx *phy)
+static s64 cal_camerarx_get_external_rate(struct cal_camerarx *phy)
 {
 	struct v4l2_ctrl *ctrl;
+	s64 rate;
 
 	if (!phy->sensor)
 		return -ENODEV;
@@ -495,10 +495,10 @@ static int cal_camerarx_get_external_info(struct cal_camerarx *phy)
 		return -EPIPE;
 	}
 
-	phy->external_rate = v4l2_ctrl_g_ctrl_int64(ctrl);
-	phy_dbg(3, phy, "sensor Pixel Rate: %u\n", phy->external_rate);
+	rate = v4l2_ctrl_g_ctrl_int64(ctrl);
+	phy_dbg(3, phy, "sensor Pixel Rate: %llu\n", rate);
 
-	return 0;
+	return rate;
 }
 
 static void cal_camerarx_lane_config(struct cal_camerarx *phy)
@@ -554,7 +554,7 @@ static void cal_camerarx_disable(struct cal_camerarx *phy)
 #define TCLK_MISS	1
 #define TCLK_SETTLE	14
 
-static void cal_camerarx_config(struct cal_camerarx *phy,
+static void cal_camerarx_config(struct cal_camerarx *phy, s64 external_rate,
 				const struct cal_fmt *fmt)
 {
 	unsigned int reg0, reg1;
@@ -566,7 +566,7 @@ static void cal_camerarx_config(struct cal_camerarx *phy,
 
 	/* DPHY timing configuration */
 	/* CSI-2 is DDR and we only count used lanes. */
-	csi2_ddrclk_khz = phy->external_rate / 1000
+	csi2_ddrclk_khz = external_rate / 1000
 		/ (2 * num_lanes) * fmt->bpp;
 	phy_dbg(1, phy, "csi2_ddrclk_khz: %d\n", csi2_ddrclk_khz);
 
@@ -667,13 +667,14 @@ static void cal_camerarx_wait_stop_state(struct cal_camerarx *phy)
 static int cal_camerarx_start(struct cal_camerarx *phy,
 			      const struct cal_fmt *fmt)
 {
+	s64 external_rate;
 	u32 sscounter;
 	u32 val;
 	int ret;
 
-	ret = cal_camerarx_get_external_info(phy);
-	if (ret < 0)
-		return ret;
+	external_rate = cal_camerarx_get_external_rate(phy);
+	if (external_rate < 0)
+		return external_rate;
 
 	ret = v4l2_subdev_call(phy->sensor, core, s_power, 1);
 	if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV) {
@@ -719,7 +720,7 @@ static int cal_camerarx_start(struct cal_camerarx *phy,
 	reg_read(phy, CAL_CSI2_PHY_REG0);
 
 	/* Program the PHY timing parameters. */
-	cal_camerarx_config(phy, fmt);
+	cal_camerarx_config(phy, external_rate, fmt);
 
 	/*
 	 *    b. Assert the FORCERXMODE signal.
@@ -1034,7 +1035,6 @@ static struct cal_camerarx *cal_camerarx_create(struct cal_dev *cal,
 
 	phy->cal = cal;
 	phy->instance = instance;
-	phy->external_rate = 192000000;
 
 	phy->res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
 						(instance == 0) ?
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 079/107] media: ti-vpe: cal: Remove unneeded phy->sensor NULL check
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (77 preceding siblings ...)
  2020-06-14 23:59 ` [PATCH v1 078/107] media: ti-vpe: cal: Don't store external rate in cal_camerarx Laurent Pinchart
@ 2020-06-14 23:59 ` Laurent Pinchart
  2020-06-14 23:59 ` [PATCH v1 080/107] media: ti-vpe: cal: Use 'unsigned int' type instead of 'unsigned' Laurent Pinchart
                   ` (29 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:59 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

The phy->sensor NULL check in cal_camerarx_get_external_rate() is not
needed, as the V4L2 video devices are only registered when the sensor is
bound. Remove it.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index a11457909134..38d2fc186ba7 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -485,9 +485,6 @@ static s64 cal_camerarx_get_external_rate(struct cal_camerarx *phy)
 	struct v4l2_ctrl *ctrl;
 	s64 rate;
 
-	if (!phy->sensor)
-		return -ENODEV;
-
 	ctrl = v4l2_ctrl_find(phy->sensor->ctrl_handler, V4L2_CID_PIXEL_RATE);
 	if (!ctrl) {
 		phy_err(phy, "no pixel rate control in subdev: %s\n",
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 080/107] media: ti-vpe: cal: Use 'unsigned int' type instead of 'unsigned'
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (78 preceding siblings ...)
  2020-06-14 23:59 ` [PATCH v1 079/107] media: ti-vpe: cal: Remove unneeded phy->sensor NULL check Laurent Pinchart
@ 2020-06-14 23:59 ` Laurent Pinchart
  2020-06-14 23:59 ` [PATCH v1 081/107] media: ti-vpe: cal: Split video node handling to cal-video.c Laurent Pinchart
                   ` (28 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:59 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

Specifying 'int' explicitly is generally preferred in the kernel for
unsigned int types. Fix the only wrong occurrence.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index 38d2fc186ba7..b67e59a4eedd 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -1759,7 +1759,7 @@ static int cal_queue_setup(struct vb2_queue *vq,
 			   unsigned int sizes[], struct device *alloc_devs[])
 {
 	struct cal_ctx *ctx = vb2_get_drv_priv(vq);
-	unsigned size = ctx->v_fmt.fmt.pix.sizeimage;
+	unsigned int size = ctx->v_fmt.fmt.pix.sizeimage;
 
 	if (vq->num_buffers + *nbuffers < 3)
 		*nbuffers = 3 - vq->num_buffers;
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 081/107] media: ti-vpe: cal: Split video node handling to cal-video.c
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (79 preceding siblings ...)
  2020-06-14 23:59 ` [PATCH v1 080/107] media: ti-vpe: cal: Use 'unsigned int' type instead of 'unsigned' Laurent Pinchart
@ 2020-06-14 23:59 ` Laurent Pinchart
  2020-06-14 23:59 ` [PATCH v1 082/107] media: ti-vpe: cal: Move CAL I/O accessors to cal.h Laurent Pinchart
                   ` (27 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:59 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

To prepare for implementation of media controller centric device
configuration, move all the video node handling support to a separate
file.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/Makefile    |    2 +-
 drivers/media/platform/ti-vpe/cal-video.c |  887 +++++++++++++++++
 drivers/media/platform/ti-vpe/cal.c       | 1085 +--------------------
 drivers/media/platform/ti-vpe/cal.h       |  226 +++++
 4 files changed, 1137 insertions(+), 1063 deletions(-)
 create mode 100644 drivers/media/platform/ti-vpe/cal-video.c
 create mode 100644 drivers/media/platform/ti-vpe/cal.h

diff --git a/drivers/media/platform/ti-vpe/Makefile b/drivers/media/platform/ti-vpe/Makefile
index 886ac5ec073f..a7bf8f2a1386 100644
--- a/drivers/media/platform/ti-vpe/Makefile
+++ b/drivers/media/platform/ti-vpe/Makefile
@@ -13,4 +13,4 @@ ccflags-$(CONFIG_VIDEO_TI_VPE_DEBUG) += -DDEBUG
 
 obj-$(CONFIG_VIDEO_TI_CAL) += ti-cal.o
 
-ti-cal-y := cal.o
+ti-cal-y := cal.o cal-video.o
diff --git a/drivers/media/platform/ti-vpe/cal-video.c b/drivers/media/platform/ti-vpe/cal-video.c
new file mode 100644
index 000000000000..82b32a2f9db5
--- /dev/null
+++ b/drivers/media/platform/ti-vpe/cal-video.c
@@ -0,0 +1,887 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * TI Camera Access Layer (CAL) - Video Device
+ *
+ * Copyright (c) 2015-2020 Texas Instruments Inc.
+ *
+ * Authors:
+ *	Benoit Parrot <bparrot@ti.com>
+ *	Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ */
+
+#include <linux/bitfield.h>
+#include <linux/delay.h>
+#include <linux/ioctl.h>
+#include <linux/pm_runtime.h>
+#include <linux/videodev2.h>
+
+#include <media/media-device.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-fh.h>
+#include <media/v4l2-ioctl.h>
+#include <media/videobuf2-core.h>
+#include <media/videobuf2-dma-contig.h>
+
+#include "cal.h"
+
+/* ------------------------------------------------------------------
+ *	Format Handling
+ * ------------------------------------------------------------------
+ */
+
+static const struct cal_fmt cal_formats[] = {
+	{
+		.fourcc		= V4L2_PIX_FMT_YUYV,
+		.code		= MEDIA_BUS_FMT_YUYV8_2X8,
+		.bpp		= 16,
+	}, {
+		.fourcc		= V4L2_PIX_FMT_UYVY,
+		.code		= MEDIA_BUS_FMT_UYVY8_2X8,
+		.bpp		= 16,
+	}, {
+		.fourcc		= V4L2_PIX_FMT_YVYU,
+		.code		= MEDIA_BUS_FMT_YVYU8_2X8,
+		.bpp		= 16,
+	}, {
+		.fourcc		= V4L2_PIX_FMT_VYUY,
+		.code		= MEDIA_BUS_FMT_VYUY8_2X8,
+		.bpp		= 16,
+	}, {
+		.fourcc		= V4L2_PIX_FMT_RGB565, /* gggbbbbb rrrrrggg */
+		.code		= MEDIA_BUS_FMT_RGB565_2X8_LE,
+		.bpp		= 16,
+	}, {
+		.fourcc		= V4L2_PIX_FMT_RGB565X, /* rrrrrggg gggbbbbb */
+		.code		= MEDIA_BUS_FMT_RGB565_2X8_BE,
+		.bpp		= 16,
+	}, {
+		.fourcc		= V4L2_PIX_FMT_RGB555, /* gggbbbbb arrrrrgg */
+		.code		= MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE,
+		.bpp		= 16,
+	}, {
+		.fourcc		= V4L2_PIX_FMT_RGB555X, /* arrrrrgg gggbbbbb */
+		.code		= MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE,
+		.bpp		= 16,
+	}, {
+		.fourcc		= V4L2_PIX_FMT_RGB24, /* rgb */
+		.code		= MEDIA_BUS_FMT_RGB888_2X12_LE,
+		.bpp		= 24,
+	}, {
+		.fourcc		= V4L2_PIX_FMT_BGR24, /* bgr */
+		.code		= MEDIA_BUS_FMT_RGB888_2X12_BE,
+		.bpp		= 24,
+	}, {
+		.fourcc		= V4L2_PIX_FMT_RGB32, /* argb */
+		.code		= MEDIA_BUS_FMT_ARGB8888_1X32,
+		.bpp		= 32,
+	}, {
+		.fourcc		= V4L2_PIX_FMT_SBGGR8,
+		.code		= MEDIA_BUS_FMT_SBGGR8_1X8,
+		.bpp		= 8,
+	}, {
+		.fourcc		= V4L2_PIX_FMT_SGBRG8,
+		.code		= MEDIA_BUS_FMT_SGBRG8_1X8,
+		.bpp		= 8,
+	}, {
+		.fourcc		= V4L2_PIX_FMT_SGRBG8,
+		.code		= MEDIA_BUS_FMT_SGRBG8_1X8,
+		.bpp		= 8,
+	}, {
+		.fourcc		= V4L2_PIX_FMT_SRGGB8,
+		.code		= MEDIA_BUS_FMT_SRGGB8_1X8,
+		.bpp		= 8,
+	}, {
+		.fourcc		= V4L2_PIX_FMT_SBGGR10,
+		.code		= MEDIA_BUS_FMT_SBGGR10_1X10,
+		.bpp		= 10,
+	}, {
+		.fourcc		= V4L2_PIX_FMT_SGBRG10,
+		.code		= MEDIA_BUS_FMT_SGBRG10_1X10,
+		.bpp		= 10,
+	}, {
+		.fourcc		= V4L2_PIX_FMT_SGRBG10,
+		.code		= MEDIA_BUS_FMT_SGRBG10_1X10,
+		.bpp		= 10,
+	}, {
+		.fourcc		= V4L2_PIX_FMT_SRGGB10,
+		.code		= MEDIA_BUS_FMT_SRGGB10_1X10,
+		.bpp		= 10,
+	}, {
+		.fourcc		= V4L2_PIX_FMT_SBGGR12,
+		.code		= MEDIA_BUS_FMT_SBGGR12_1X12,
+		.bpp		= 12,
+	}, {
+		.fourcc		= V4L2_PIX_FMT_SGBRG12,
+		.code		= MEDIA_BUS_FMT_SGBRG12_1X12,
+		.bpp		= 12,
+	}, {
+		.fourcc		= V4L2_PIX_FMT_SGRBG12,
+		.code		= MEDIA_BUS_FMT_SGRBG12_1X12,
+		.bpp		= 12,
+	}, {
+		.fourcc		= V4L2_PIX_FMT_SRGGB12,
+		.code		= MEDIA_BUS_FMT_SRGGB12_1X12,
+		.bpp		= 12,
+	},
+};
+
+/*  Print Four-character-code (FOURCC) */
+static char *fourcc_to_str(u32 fmt)
+{
+	static char code[5];
+
+	code[0] = (unsigned char)(fmt & 0xff);
+	code[1] = (unsigned char)((fmt >> 8) & 0xff);
+	code[2] = (unsigned char)((fmt >> 16) & 0xff);
+	code[3] = (unsigned char)((fmt >> 24) & 0xff);
+	code[4] = '\0';
+
+	return code;
+}
+
+/* ------------------------------------------------------------------
+ *	V4L2 Video IOCTLs
+ * ------------------------------------------------------------------
+ */
+
+static const struct cal_fmt *find_format_by_pix(struct cal_ctx *ctx,
+						u32 pixelformat)
+{
+	const struct cal_fmt *fmt;
+	unsigned int k;
+
+	for (k = 0; k < ctx->num_active_fmt; k++) {
+		fmt = ctx->active_fmt[k];
+		if (fmt->fourcc == pixelformat)
+			return fmt;
+	}
+
+	return NULL;
+}
+
+static const struct cal_fmt *find_format_by_code(struct cal_ctx *ctx,
+						 u32 code)
+{
+	const struct cal_fmt *fmt;
+	unsigned int k;
+
+	for (k = 0; k < ctx->num_active_fmt; k++) {
+		fmt = ctx->active_fmt[k];
+		if (fmt->code == code)
+			return fmt;
+	}
+
+	return NULL;
+}
+
+static int cal_querycap(struct file *file, void *priv,
+			struct v4l2_capability *cap)
+{
+	struct cal_ctx *ctx = video_drvdata(file);
+
+	strscpy(cap->driver, CAL_MODULE_NAME, sizeof(cap->driver));
+	strscpy(cap->card, CAL_MODULE_NAME, sizeof(cap->card));
+
+	snprintf(cap->bus_info, sizeof(cap->bus_info),
+		 "platform:%s", dev_name(ctx->cal->dev));
+	return 0;
+}
+
+static int cal_enum_fmt_vid_cap(struct file *file, void  *priv,
+				struct v4l2_fmtdesc *f)
+{
+	struct cal_ctx *ctx = video_drvdata(file);
+	const struct cal_fmt *fmt;
+
+	if (f->index >= ctx->num_active_fmt)
+		return -EINVAL;
+
+	fmt = ctx->active_fmt[f->index];
+
+	f->pixelformat = fmt->fourcc;
+	f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	return 0;
+}
+
+static int __subdev_get_format(struct cal_ctx *ctx,
+			       struct v4l2_mbus_framefmt *fmt)
+{
+	struct v4l2_subdev_format sd_fmt;
+	struct v4l2_mbus_framefmt *mbus_fmt = &sd_fmt.format;
+	int ret;
+
+	sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+	sd_fmt.pad = 0;
+
+	ret = v4l2_subdev_call(ctx->phy->sensor, pad, get_fmt, NULL, &sd_fmt);
+	if (ret)
+		return ret;
+
+	*fmt = *mbus_fmt;
+
+	ctx_dbg(1, ctx, "%s %dx%d code:%04X\n", __func__,
+		fmt->width, fmt->height, fmt->code);
+
+	return 0;
+}
+
+static int __subdev_set_format(struct cal_ctx *ctx,
+			       struct v4l2_mbus_framefmt *fmt)
+{
+	struct v4l2_subdev_format sd_fmt;
+	struct v4l2_mbus_framefmt *mbus_fmt = &sd_fmt.format;
+	int ret;
+
+	sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+	sd_fmt.pad = 0;
+	*mbus_fmt = *fmt;
+
+	ret = v4l2_subdev_call(ctx->phy->sensor, pad, set_fmt, NULL, &sd_fmt);
+	if (ret)
+		return ret;
+
+	ctx_dbg(1, ctx, "%s %dx%d code:%04X\n", __func__,
+		fmt->width, fmt->height, fmt->code);
+
+	return 0;
+}
+
+static int cal_calc_format_size(struct cal_ctx *ctx,
+				const struct cal_fmt *fmt,
+				struct v4l2_format *f)
+{
+	u32 bpl, max_width;
+
+	if (!fmt) {
+		ctx_dbg(3, ctx, "No cal_fmt provided!\n");
+		return -EINVAL;
+	}
+
+	/*
+	 * Maximum width is bound by the DMA max width in bytes.
+	 * We need to recalculate the actual maxi width depending on the
+	 * number of bytes per pixels required.
+	 */
+	max_width = MAX_WIDTH_BYTES / (ALIGN(fmt->bpp, 8) >> 3);
+	v4l_bound_align_image(&f->fmt.pix.width, 48, max_width, 2,
+			      &f->fmt.pix.height, 32, MAX_HEIGHT_LINES, 0, 0);
+
+	bpl = (f->fmt.pix.width * ALIGN(fmt->bpp, 8)) >> 3;
+	f->fmt.pix.bytesperline = ALIGN(bpl, 16);
+
+	f->fmt.pix.sizeimage = f->fmt.pix.height *
+			       f->fmt.pix.bytesperline;
+
+	ctx_dbg(3, ctx, "%s: fourcc: %s size: %dx%d bpl:%d img_size:%d\n",
+		__func__, fourcc_to_str(f->fmt.pix.pixelformat),
+		f->fmt.pix.width, f->fmt.pix.height,
+		f->fmt.pix.bytesperline, f->fmt.pix.sizeimage);
+
+	return 0;
+}
+
+static int cal_g_fmt_vid_cap(struct file *file, void *priv,
+			     struct v4l2_format *f)
+{
+	struct cal_ctx *ctx = video_drvdata(file);
+
+	*f = ctx->v_fmt;
+
+	return 0;
+}
+
+static int cal_try_fmt_vid_cap(struct file *file, void *priv,
+			       struct v4l2_format *f)
+{
+	struct cal_ctx *ctx = video_drvdata(file);
+	const struct cal_fmt *fmt;
+	struct v4l2_subdev_frame_size_enum fse;
+	int ret, found;
+
+	fmt = find_format_by_pix(ctx, f->fmt.pix.pixelformat);
+	if (!fmt) {
+		ctx_dbg(3, ctx, "Fourcc format (0x%08x) not found.\n",
+			f->fmt.pix.pixelformat);
+
+		/* Just get the first one enumerated */
+		fmt = ctx->active_fmt[0];
+		f->fmt.pix.pixelformat = fmt->fourcc;
+	}
+
+	f->fmt.pix.field = ctx->v_fmt.fmt.pix.field;
+
+	/* check for/find a valid width/height */
+	ret = 0;
+	found = false;
+	fse.pad = 0;
+	fse.code = fmt->code;
+	fse.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+	for (fse.index = 0; ; fse.index++) {
+		ret = v4l2_subdev_call(ctx->phy->sensor, pad, enum_frame_size,
+				       NULL, &fse);
+		if (ret)
+			break;
+
+		if ((f->fmt.pix.width == fse.max_width) &&
+		    (f->fmt.pix.height == fse.max_height)) {
+			found = true;
+			break;
+		} else if ((f->fmt.pix.width >= fse.min_width) &&
+			 (f->fmt.pix.width <= fse.max_width) &&
+			 (f->fmt.pix.height >= fse.min_height) &&
+			 (f->fmt.pix.height <= fse.max_height)) {
+			found = true;
+			break;
+		}
+	}
+
+	if (!found) {
+		/* use existing values as default */
+		f->fmt.pix.width = ctx->v_fmt.fmt.pix.width;
+		f->fmt.pix.height =  ctx->v_fmt.fmt.pix.height;
+	}
+
+	/*
+	 * Use current colorspace for now, it will get
+	 * updated properly during s_fmt
+	 */
+	f->fmt.pix.colorspace = ctx->v_fmt.fmt.pix.colorspace;
+	return cal_calc_format_size(ctx, fmt, f);
+}
+
+static int cal_s_fmt_vid_cap(struct file *file, void *priv,
+			     struct v4l2_format *f)
+{
+	struct cal_ctx *ctx = video_drvdata(file);
+	struct vb2_queue *q = &ctx->vb_vidq;
+	const struct cal_fmt *fmt;
+	struct v4l2_mbus_framefmt mbus_fmt;
+	int ret;
+
+	if (vb2_is_busy(q)) {
+		ctx_dbg(3, ctx, "%s device busy\n", __func__);
+		return -EBUSY;
+	}
+
+	ret = cal_try_fmt_vid_cap(file, priv, f);
+	if (ret < 0)
+		return ret;
+
+	fmt = find_format_by_pix(ctx, f->fmt.pix.pixelformat);
+
+	v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, fmt->code);
+
+	ret = __subdev_set_format(ctx, &mbus_fmt);
+	if (ret)
+		return ret;
+
+	/* Just double check nothing has gone wrong */
+	if (mbus_fmt.code != fmt->code) {
+		ctx_dbg(3, ctx,
+			"%s subdev changed format on us, this should not happen\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	v4l2_fill_pix_format(&ctx->v_fmt.fmt.pix, &mbus_fmt);
+	ctx->v_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	ctx->v_fmt.fmt.pix.pixelformat  = fmt->fourcc;
+	cal_calc_format_size(ctx, fmt, &ctx->v_fmt);
+	ctx->fmt = fmt;
+	ctx->m_fmt = mbus_fmt;
+	*f = ctx->v_fmt;
+
+	return 0;
+}
+
+static int cal_enum_framesizes(struct file *file, void *fh,
+			       struct v4l2_frmsizeenum *fsize)
+{
+	struct cal_ctx *ctx = video_drvdata(file);
+	const struct cal_fmt *fmt;
+	struct v4l2_subdev_frame_size_enum fse;
+	int ret;
+
+	/* check for valid format */
+	fmt = find_format_by_pix(ctx, fsize->pixel_format);
+	if (!fmt) {
+		ctx_dbg(3, ctx, "Invalid pixel code: %x\n",
+			fsize->pixel_format);
+		return -EINVAL;
+	}
+
+	fse.index = fsize->index;
+	fse.pad = 0;
+	fse.code = fmt->code;
+	fse.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+
+	ret = v4l2_subdev_call(ctx->phy->sensor, pad, enum_frame_size, NULL,
+			       &fse);
+	if (ret)
+		return ret;
+
+	ctx_dbg(1, ctx, "%s: index: %d code: %x W:[%d,%d] H:[%d,%d]\n",
+		__func__, fse.index, fse.code, fse.min_width, fse.max_width,
+		fse.min_height, fse.max_height);
+
+	fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
+	fsize->discrete.width = fse.max_width;
+	fsize->discrete.height = fse.max_height;
+
+	return 0;
+}
+
+static int cal_enum_input(struct file *file, void *priv,
+			  struct v4l2_input *inp)
+{
+	if (inp->index > 0)
+		return -EINVAL;
+
+	inp->type = V4L2_INPUT_TYPE_CAMERA;
+	sprintf(inp->name, "Camera %u", inp->index);
+	return 0;
+}
+
+static int cal_g_input(struct file *file, void *priv, unsigned int *i)
+{
+	*i = 0;
+	return 0;
+}
+
+static int cal_s_input(struct file *file, void *priv, unsigned int i)
+{
+	return i > 0 ? -EINVAL : 0;
+}
+
+/* timeperframe is arbitrary and continuous */
+static int cal_enum_frameintervals(struct file *file, void *priv,
+				   struct v4l2_frmivalenum *fival)
+{
+	struct cal_ctx *ctx = video_drvdata(file);
+	const struct cal_fmt *fmt;
+	struct v4l2_subdev_frame_interval_enum fie = {
+		.index = fival->index,
+		.width = fival->width,
+		.height = fival->height,
+		.which = V4L2_SUBDEV_FORMAT_ACTIVE,
+	};
+	int ret;
+
+	fmt = find_format_by_pix(ctx, fival->pixel_format);
+	if (!fmt)
+		return -EINVAL;
+
+	fie.code = fmt->code;
+	ret = v4l2_subdev_call(ctx->phy->sensor, pad, enum_frame_interval,
+			       NULL, &fie);
+	if (ret)
+		return ret;
+	fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
+	fival->discrete = fie.interval;
+
+	return 0;
+}
+
+static const struct v4l2_file_operations cal_fops = {
+	.owner		= THIS_MODULE,
+	.open           = v4l2_fh_open,
+	.release        = vb2_fop_release,
+	.read           = vb2_fop_read,
+	.poll		= vb2_fop_poll,
+	.unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */
+	.mmap           = vb2_fop_mmap,
+};
+
+static const struct v4l2_ioctl_ops cal_ioctl_ops = {
+	.vidioc_querycap      = cal_querycap,
+	.vidioc_enum_fmt_vid_cap  = cal_enum_fmt_vid_cap,
+	.vidioc_g_fmt_vid_cap     = cal_g_fmt_vid_cap,
+	.vidioc_try_fmt_vid_cap   = cal_try_fmt_vid_cap,
+	.vidioc_s_fmt_vid_cap     = cal_s_fmt_vid_cap,
+	.vidioc_enum_framesizes   = cal_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_enum_input    = cal_enum_input,
+	.vidioc_g_input       = cal_g_input,
+	.vidioc_s_input       = cal_s_input,
+	.vidioc_enum_frameintervals = cal_enum_frameintervals,
+	.vidioc_streamon      = vb2_ioctl_streamon,
+	.vidioc_streamoff     = vb2_ioctl_streamoff,
+	.vidioc_log_status    = v4l2_ctrl_log_status,
+	.vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
+	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
+};
+
+/* ------------------------------------------------------------------
+ *	videobuf2 Operations
+ * ------------------------------------------------------------------
+ */
+
+static int cal_queue_setup(struct vb2_queue *vq,
+			   unsigned int *nbuffers, unsigned int *nplanes,
+			   unsigned int sizes[], struct device *alloc_devs[])
+{
+	struct cal_ctx *ctx = vb2_get_drv_priv(vq);
+	unsigned int size = ctx->v_fmt.fmt.pix.sizeimage;
+
+	if (vq->num_buffers + *nbuffers < 3)
+		*nbuffers = 3 - vq->num_buffers;
+
+	if (*nplanes) {
+		if (sizes[0] < size)
+			return -EINVAL;
+		size = sizes[0];
+	}
+
+	*nplanes = 1;
+	sizes[0] = size;
+
+	ctx_dbg(3, ctx, "nbuffers=%d, size=%d\n", *nbuffers, sizes[0]);
+
+	return 0;
+}
+
+static int cal_buffer_prepare(struct vb2_buffer *vb)
+{
+	struct cal_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+	struct cal_buffer *buf = container_of(vb, struct cal_buffer,
+					      vb.vb2_buf);
+	unsigned long size;
+
+	if (WARN_ON(!ctx->fmt))
+		return -EINVAL;
+
+	size = ctx->v_fmt.fmt.pix.sizeimage;
+	if (vb2_plane_size(vb, 0) < size) {
+		ctx_err(ctx,
+			"data will not fit into plane (%lu < %lu)\n",
+			vb2_plane_size(vb, 0), size);
+		return -EINVAL;
+	}
+
+	vb2_set_plane_payload(&buf->vb.vb2_buf, 0, size);
+	return 0;
+}
+
+static void cal_buffer_queue(struct vb2_buffer *vb)
+{
+	struct cal_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+	struct cal_buffer *buf = container_of(vb, struct cal_buffer,
+					      vb.vb2_buf);
+	struct cal_dmaqueue *vidq = &ctx->vidq;
+	unsigned long flags;
+
+	/* recheck locking */
+	spin_lock_irqsave(&ctx->slock, flags);
+	list_add_tail(&buf->list, &vidq->active);
+	spin_unlock_irqrestore(&ctx->slock, flags);
+}
+
+static int cal_start_streaming(struct vb2_queue *vq, unsigned int count)
+{
+	struct cal_ctx *ctx = vb2_get_drv_priv(vq);
+	struct cal_dmaqueue *dma_q = &ctx->vidq;
+	struct cal_buffer *buf, *tmp;
+	unsigned long addr;
+	unsigned long flags;
+	int ret;
+
+	spin_lock_irqsave(&ctx->slock, flags);
+	if (list_empty(&dma_q->active)) {
+		spin_unlock_irqrestore(&ctx->slock, flags);
+		ctx_dbg(3, ctx, "buffer queue is empty\n");
+		return -EIO;
+	}
+
+	buf = list_entry(dma_q->active.next, struct cal_buffer, list);
+	ctx->cur_frm = buf;
+	ctx->next_frm = buf;
+	list_del(&buf->list);
+	spin_unlock_irqrestore(&ctx->slock, flags);
+
+	addr = vb2_dma_contig_plane_dma_addr(&ctx->cur_frm->vb.vb2_buf, 0);
+	ctx->sequence = 0;
+
+	pm_runtime_get_sync(ctx->cal->dev);
+
+	cal_ctx_csi2_config(ctx);
+	cal_ctx_pix_proc_config(ctx);
+	cal_ctx_wr_dma_config(ctx, ctx->v_fmt.fmt.pix.bytesperline,
+			      ctx->v_fmt.fmt.pix.height);
+
+	cal_camerarx_enable_irqs(ctx->phy);
+
+	ret = cal_camerarx_start(ctx->phy, ctx->fmt);
+	if (ret)
+		goto err;
+
+	cal_ctx_wr_dma_addr(ctx, addr);
+	cal_camerarx_ppi_enable(ctx->phy);
+
+	if (cal_debug >= 4)
+		cal_quickdump_regs(ctx->cal);
+
+	return 0;
+
+err:
+	spin_lock_irqsave(&ctx->slock, flags);
+	vb2_buffer_done(&ctx->cur_frm->vb.vb2_buf, VB2_BUF_STATE_QUEUED);
+	ctx->cur_frm = NULL;
+	ctx->next_frm = NULL;
+	list_for_each_entry_safe(buf, tmp, &dma_q->active, list) {
+		list_del(&buf->list);
+		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_QUEUED);
+	}
+	spin_unlock_irqrestore(&ctx->slock, flags);
+	return ret;
+}
+
+static void cal_stop_streaming(struct vb2_queue *vq)
+{
+	struct cal_ctx *ctx = vb2_get_drv_priv(vq);
+	struct cal_dmaqueue *dma_q = &ctx->vidq;
+	struct cal_buffer *buf, *tmp;
+	unsigned long timeout;
+	unsigned long flags;
+	bool dma_act;
+
+	cal_camerarx_ppi_disable(ctx->phy);
+
+	/* wait for stream and dma to finish */
+	dma_act = true;
+	timeout = jiffies + msecs_to_jiffies(500);
+	while (dma_act && time_before(jiffies, timeout)) {
+		msleep(50);
+
+		spin_lock_irqsave(&ctx->slock, flags);
+		dma_act = ctx->dma_act;
+		spin_unlock_irqrestore(&ctx->slock, flags);
+	}
+
+	if (dma_act)
+		ctx_err(ctx, "failed to disable dma cleanly\n");
+
+	cal_camerarx_disable_irqs(ctx->phy);
+	cal_camerarx_stop(ctx->phy);
+
+	/* Release all active buffers */
+	spin_lock_irqsave(&ctx->slock, flags);
+	list_for_each_entry_safe(buf, tmp, &dma_q->active, list) {
+		list_del(&buf->list);
+		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
+	}
+
+	if (ctx->cur_frm == ctx->next_frm) {
+		vb2_buffer_done(&ctx->cur_frm->vb.vb2_buf, VB2_BUF_STATE_ERROR);
+	} else {
+		vb2_buffer_done(&ctx->cur_frm->vb.vb2_buf, VB2_BUF_STATE_ERROR);
+		vb2_buffer_done(&ctx->next_frm->vb.vb2_buf,
+				VB2_BUF_STATE_ERROR);
+	}
+	ctx->cur_frm = NULL;
+	ctx->next_frm = NULL;
+	spin_unlock_irqrestore(&ctx->slock, flags);
+
+	pm_runtime_put_sync(ctx->cal->dev);
+}
+
+static const struct vb2_ops cal_video_qops = {
+	.queue_setup		= cal_queue_setup,
+	.buf_prepare		= cal_buffer_prepare,
+	.buf_queue		= cal_buffer_queue,
+	.start_streaming	= cal_start_streaming,
+	.stop_streaming		= cal_stop_streaming,
+	.wait_prepare		= vb2_ops_wait_prepare,
+	.wait_finish		= vb2_ops_wait_finish,
+};
+
+/* ------------------------------------------------------------------
+ *	V4L2 Initialization and Registration
+ * ------------------------------------------------------------------
+ */
+
+static const struct video_device cal_videodev = {
+	.name		= CAL_MODULE_NAME,
+	.fops		= &cal_fops,
+	.ioctl_ops	= &cal_ioctl_ops,
+	.minor		= -1,
+	.release	= video_device_release_empty,
+	.device_caps	= V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING |
+			  V4L2_CAP_READWRITE,
+};
+
+static int cal_ctx_v4l2_init_formats(struct cal_ctx *ctx)
+{
+	struct v4l2_subdev_mbus_code_enum mbus_code;
+	struct v4l2_mbus_framefmt mbus_fmt;
+	const struct cal_fmt *fmt;
+	unsigned int i, j, k;
+	int ret = 0;
+
+	/* Enumerate sub device formats and enable all matching local formats */
+	ctx->active_fmt = devm_kcalloc(ctx->cal->dev, ARRAY_SIZE(cal_formats),
+				       sizeof(*ctx->active_fmt), GFP_KERNEL);
+	ctx->num_active_fmt = 0;
+
+	for (j = 0, i = 0; ret != -EINVAL; ++j) {
+
+		memset(&mbus_code, 0, sizeof(mbus_code));
+		mbus_code.index = j;
+		mbus_code.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+		ret = v4l2_subdev_call(ctx->phy->sensor, pad, enum_mbus_code,
+				       NULL, &mbus_code);
+		if (ret)
+			continue;
+
+		ctx_dbg(2, ctx,
+			"subdev %s: code: %04x idx: %u\n",
+			ctx->phy->sensor->name, mbus_code.code, j);
+
+		for (k = 0; k < ARRAY_SIZE(cal_formats); k++) {
+			const struct cal_fmt *fmt = &cal_formats[k];
+
+			if (mbus_code.code == fmt->code) {
+				ctx->active_fmt[i] = fmt;
+				ctx_dbg(2, ctx,
+					"matched fourcc: %s: code: %04x idx: %u\n",
+					fourcc_to_str(fmt->fourcc),
+					fmt->code, i);
+				ctx->num_active_fmt = ++i;
+			}
+		}
+	}
+
+	if (i == 0) {
+		ctx_err(ctx, "No suitable format reported by subdev %s\n",
+			ctx->phy->sensor->name);
+		return -EINVAL;
+	}
+
+	ret = __subdev_get_format(ctx, &mbus_fmt);
+	if (ret)
+		return ret;
+
+	fmt = find_format_by_code(ctx, mbus_fmt.code);
+	if (!fmt) {
+		ctx_dbg(3, ctx, "mbus code format (0x%08x) not found.\n",
+			mbus_fmt.code);
+		return -EINVAL;
+	}
+
+	/* Save current subdev format */
+	v4l2_fill_pix_format(&ctx->v_fmt.fmt.pix, &mbus_fmt);
+	ctx->v_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	ctx->v_fmt.fmt.pix.pixelformat  = fmt->fourcc;
+	cal_calc_format_size(ctx, fmt, &ctx->v_fmt);
+	ctx->fmt = fmt;
+	ctx->m_fmt = mbus_fmt;
+
+	return 0;
+}
+
+int cal_ctx_v4l2_register(struct cal_ctx *ctx)
+{
+	struct v4l2_ctrl_handler *hdl = &ctx->ctrl_handler;
+	struct video_device *vfd = &ctx->vdev;
+	int ret;
+
+	ret = cal_ctx_v4l2_init_formats(ctx);
+	if (ret)
+		return ret;
+
+	ret = v4l2_ctrl_add_handler(hdl, ctx->phy->sensor->ctrl_handler, NULL,
+				    true);
+	if (ret < 0) {
+		ctx_err(ctx, "Failed to add sensor ctrl handler\n");
+		return ret;
+	}
+
+	ret = video_register_device(vfd, VFL_TYPE_VIDEO, cal_video_nr);
+	if (ret < 0) {
+		ctx_err(ctx, "Failed to register video device\n");
+		return ret;
+	}
+
+	ctx_info(ctx, "V4L2 device registered as %s\n",
+		 video_device_node_name(vfd));
+
+	return 0;
+}
+
+void cal_ctx_v4l2_unregister(struct cal_ctx *ctx)
+{
+	ctx_dbg(1, ctx, "unregistering %s\n",
+		video_device_node_name(&ctx->vdev));
+
+	video_unregister_device(&ctx->vdev);
+}
+
+int cal_ctx_v4l2_init(struct cal_ctx *ctx)
+{
+	struct v4l2_ctrl_handler *hdl = &ctx->ctrl_handler;
+	struct video_device *vfd = &ctx->vdev;
+	struct vb2_queue *q = &ctx->vb_vidq;
+	int ret;
+
+	INIT_LIST_HEAD(&ctx->vidq.active);
+	spin_lock_init(&ctx->slock);
+	mutex_init(&ctx->mutex);
+
+	/* Initialize the vb2 queue. */
+	q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	q->io_modes = VB2_MMAP | VB2_DMABUF | VB2_READ;
+	q->drv_priv = ctx;
+	q->buf_struct_size = sizeof(struct cal_buffer);
+	q->ops = &cal_video_qops;
+	q->mem_ops = &vb2_dma_contig_memops;
+	q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+	q->lock = &ctx->mutex;
+	q->min_buffers_needed = 3;
+	q->dev = ctx->cal->dev;
+
+	ret = vb2_queue_init(q);
+	if (ret)
+		return ret;
+
+	/* Initialize the video device and media entity. */
+	*vfd = cal_videodev;
+	vfd->v4l2_dev = &ctx->cal->v4l2_dev;
+	vfd->queue = q;
+	snprintf(vfd->name, sizeof(vfd->name), "CAL output %u", ctx->index);
+	vfd->lock = &ctx->mutex;
+	video_set_drvdata(vfd, ctx);
+
+	ctx->pad.flags = MEDIA_PAD_FL_SINK;
+	ret = media_entity_pads_init(&vfd->entity, 1, &ctx->pad);
+	if (ret < 0)
+		return ret;
+
+	/* Initialize the control handler. */
+	ret = v4l2_ctrl_handler_init(hdl, 11);
+	if (ret < 0) {
+		ctx_err(ctx, "Failed to init ctrl handler\n");
+		goto error;
+	}
+
+	vfd->ctrl_handler = hdl;
+
+	return 0;
+
+error:
+	media_entity_cleanup(&vfd->entity);
+	return ret;
+}
+
+void cal_ctx_v4l2_cleanup(struct cal_ctx *ctx)
+{
+	v4l2_ctrl_handler_free(&ctx->ctrl_handler);
+	media_entity_cleanup(&ctx->vdev.entity);
+}
diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index b67e59a4eedd..0bc02ba52b59 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -1,9 +1,12 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * TI CAL camera interface driver
+ * TI Camera Access Layer (CAL) - Driver
  *
- * Copyright (c) 2015 Texas Instruments Inc.
- * Benoit Parrot, <bparrot@ti.com>
+ * Copyright (c) 2015-2020 Texas Instruments Inc.
+ *
+ * Authors:
+ *	Benoit Parrot <bparrot@ti.com>
+ *	Laurent Pinchart <laurent.pinchart@ideasonboard.com>
  */
 
 #include <linux/bitfield.h>
@@ -11,7 +14,6 @@
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
-#include <linux/ioctl.h>
 #include <linux/mfd/syscon.h>
 #include <linux/module.h>
 #include <linux/of_device.h>
@@ -27,319 +29,26 @@
 #include <media/v4l2-common.h>
 #include <media/v4l2-ctrls.h>
 #include <media/v4l2-device.h>
-#include <media/v4l2-event.h>
-#include <media/v4l2-fh.h>
 #include <media/v4l2-fwnode.h>
-#include <media/v4l2-ioctl.h>
 #include <media/videobuf2-core.h>
 #include <media/videobuf2-dma-contig.h>
 
+#include "cal.h"
 #include "cal_regs.h"
 
-#define CAL_MODULE_NAME "cal"
-
 MODULE_DESCRIPTION("TI CAL driver");
 MODULE_AUTHOR("Benoit Parrot, <bparrot@ti.com>");
 MODULE_LICENSE("GPL v2");
 MODULE_VERSION("0.1.0");
 
-static unsigned video_nr = -1;
-module_param(video_nr, uint, 0644);
+int cal_video_nr = -1;
+module_param_named(video_nr, cal_video_nr, uint, 0644);
 MODULE_PARM_DESC(video_nr, "videoX start number, -1 is autodetect");
 
-static unsigned debug;
-module_param(debug, uint, 0644);
+unsigned int cal_debug;
+module_param_named(debug, cal_debug, uint, 0644);
 MODULE_PARM_DESC(debug, "activates debug info");
 
-#define cal_dbg(level, cal, fmt, arg...)				\
-	do {								\
-		if (debug >= (level))					\
-			dev_dbg((cal)->dev, fmt, ##arg);		\
-	} while (0)
-#define cal_info(cal, fmt, arg...)	\
-	dev_info((cal)->dev, fmt, ##arg)
-#define cal_err(cal, fmt, arg...)	\
-	dev_err((cal)->dev, fmt, ##arg)
-
-#define ctx_dbg(level, ctx, fmt, arg...)	\
-	cal_dbg(level, (ctx)->cal, "ctx%u: " fmt, (ctx)->index, ##arg)
-#define ctx_info(ctx, fmt, arg...)	\
-	cal_info((ctx)->cal, "ctx%u: " fmt, (ctx)->index, ##arg)
-#define ctx_err(ctx, fmt, arg...)	\
-	cal_err((ctx)->cal, "ctx%u: " fmt, (ctx)->index, ##arg)
-
-#define phy_dbg(level, phy, fmt, arg...)	\
-	cal_dbg(level, (phy)->cal, "phy%u: " fmt, (phy)->instance, ##arg)
-#define phy_info(phy, fmt, arg...)	\
-	cal_info((phy)->cal, "phy%u: " fmt, (phy)->instance, ##arg)
-#define phy_err(phy, fmt, arg...)	\
-	cal_err((phy)->cal, "phy%u: " fmt, (phy)->instance, ##arg)
-
-#define CAL_NUM_CONTEXT			2
-#define CAL_NUM_CSI2_PORTS		2
-
-#define MAX_WIDTH_BYTES			(8192 * 8)
-#define MAX_HEIGHT_LINES		16383
-
-/* ------------------------------------------------------------------
- *	Format Handling
- * ------------------------------------------------------------------
- */
-
-struct cal_fmt {
-	u32	fourcc;
-	u32	code;
-	/* Bits per pixel */
-	u8	bpp;
-};
-
-static const struct cal_fmt cal_formats[] = {
-	{
-		.fourcc		= V4L2_PIX_FMT_YUYV,
-		.code		= MEDIA_BUS_FMT_YUYV8_2X8,
-		.bpp		= 16,
-	}, {
-		.fourcc		= V4L2_PIX_FMT_UYVY,
-		.code		= MEDIA_BUS_FMT_UYVY8_2X8,
-		.bpp		= 16,
-	}, {
-		.fourcc		= V4L2_PIX_FMT_YVYU,
-		.code		= MEDIA_BUS_FMT_YVYU8_2X8,
-		.bpp		= 16,
-	}, {
-		.fourcc		= V4L2_PIX_FMT_VYUY,
-		.code		= MEDIA_BUS_FMT_VYUY8_2X8,
-		.bpp		= 16,
-	}, {
-		.fourcc		= V4L2_PIX_FMT_RGB565, /* gggbbbbb rrrrrggg */
-		.code		= MEDIA_BUS_FMT_RGB565_2X8_LE,
-		.bpp		= 16,
-	}, {
-		.fourcc		= V4L2_PIX_FMT_RGB565X, /* rrrrrggg gggbbbbb */
-		.code		= MEDIA_BUS_FMT_RGB565_2X8_BE,
-		.bpp		= 16,
-	}, {
-		.fourcc		= V4L2_PIX_FMT_RGB555, /* gggbbbbb arrrrrgg */
-		.code		= MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE,
-		.bpp		= 16,
-	}, {
-		.fourcc		= V4L2_PIX_FMT_RGB555X, /* arrrrrgg gggbbbbb */
-		.code		= MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE,
-		.bpp		= 16,
-	}, {
-		.fourcc		= V4L2_PIX_FMT_RGB24, /* rgb */
-		.code		= MEDIA_BUS_FMT_RGB888_2X12_LE,
-		.bpp		= 24,
-	}, {
-		.fourcc		= V4L2_PIX_FMT_BGR24, /* bgr */
-		.code		= MEDIA_BUS_FMT_RGB888_2X12_BE,
-		.bpp		= 24,
-	}, {
-		.fourcc		= V4L2_PIX_FMT_RGB32, /* argb */
-		.code		= MEDIA_BUS_FMT_ARGB8888_1X32,
-		.bpp		= 32,
-	}, {
-		.fourcc		= V4L2_PIX_FMT_SBGGR8,
-		.code		= MEDIA_BUS_FMT_SBGGR8_1X8,
-		.bpp		= 8,
-	}, {
-		.fourcc		= V4L2_PIX_FMT_SGBRG8,
-		.code		= MEDIA_BUS_FMT_SGBRG8_1X8,
-		.bpp		= 8,
-	}, {
-		.fourcc		= V4L2_PIX_FMT_SGRBG8,
-		.code		= MEDIA_BUS_FMT_SGRBG8_1X8,
-		.bpp		= 8,
-	}, {
-		.fourcc		= V4L2_PIX_FMT_SRGGB8,
-		.code		= MEDIA_BUS_FMT_SRGGB8_1X8,
-		.bpp		= 8,
-	}, {
-		.fourcc		= V4L2_PIX_FMT_SBGGR10,
-		.code		= MEDIA_BUS_FMT_SBGGR10_1X10,
-		.bpp		= 10,
-	}, {
-		.fourcc		= V4L2_PIX_FMT_SGBRG10,
-		.code		= MEDIA_BUS_FMT_SGBRG10_1X10,
-		.bpp		= 10,
-	}, {
-		.fourcc		= V4L2_PIX_FMT_SGRBG10,
-		.code		= MEDIA_BUS_FMT_SGRBG10_1X10,
-		.bpp		= 10,
-	}, {
-		.fourcc		= V4L2_PIX_FMT_SRGGB10,
-		.code		= MEDIA_BUS_FMT_SRGGB10_1X10,
-		.bpp		= 10,
-	}, {
-		.fourcc		= V4L2_PIX_FMT_SBGGR12,
-		.code		= MEDIA_BUS_FMT_SBGGR12_1X12,
-		.bpp		= 12,
-	}, {
-		.fourcc		= V4L2_PIX_FMT_SGBRG12,
-		.code		= MEDIA_BUS_FMT_SGBRG12_1X12,
-		.bpp		= 12,
-	}, {
-		.fourcc		= V4L2_PIX_FMT_SGRBG12,
-		.code		= MEDIA_BUS_FMT_SGRBG12_1X12,
-		.bpp		= 12,
-	}, {
-		.fourcc		= V4L2_PIX_FMT_SRGGB12,
-		.code		= MEDIA_BUS_FMT_SRGGB12_1X12,
-		.bpp		= 12,
-	},
-};
-
-/*  Print Four-character-code (FOURCC) */
-static char *fourcc_to_str(u32 fmt)
-{
-	static char code[5];
-
-	code[0] = (unsigned char)(fmt & 0xff);
-	code[1] = (unsigned char)((fmt >> 8) & 0xff);
-	code[2] = (unsigned char)((fmt >> 16) & 0xff);
-	code[3] = (unsigned char)((fmt >> 24) & 0xff);
-	code[4] = '\0';
-
-	return code;
-}
-
-/* ------------------------------------------------------------------
- *	Driver Structures
- * ------------------------------------------------------------------
- */
-
-/* buffer for one video frame */
-struct cal_buffer {
-	/* common v4l buffer stuff -- must be first */
-	struct vb2_v4l2_buffer	vb;
-	struct list_head	list;
-};
-
-struct cal_dmaqueue {
-	struct list_head	active;
-};
-
-/* CTRL_CORE_CAMERRX_CONTROL register field id */
-enum cal_camerarx_field {
-	F_CTRLCLKEN,
-	F_CAMMODE,
-	F_LANEENABLE,
-	F_CSI_MODE,
-
-	F_MAX_FIELDS,
-};
-
-struct cal_camerarx_data {
-	struct {
-		unsigned int lsb;
-		unsigned int msb;
-	} fields[F_MAX_FIELDS];
-	unsigned int num_lanes;
-};
-
-struct cal_data {
-	const struct cal_camerarx_data *camerarx;
-	unsigned int num_csi2_phy;
-	unsigned int flags;
-};
-
-/*
- * The Camera Adaptation Layer (CAL) module is paired with one or more complex
- * I/O PHYs (CAMERARX). It contains multiple instances of CSI-2, processing and
- * DMA contexts.
- *
- * The cal_dev structure represents the whole subsystem, including the CAL and
- * the CAMERARX instances. Instances of struct cal_dev are named cal through the
- * driver.
- *
- * The cal_camerarx structure represents one CAMERARX instance. Instances of
- * cal_camerarx are named phy through the driver.
- *
- * The cal_ctx structure represents the combination of one CSI-2 context, one
- * processing context and one DMA context. Instance of struct cal_ctx are named
- * ctx through the driver.
- */
-
-struct cal_camerarx {
-	void __iomem		*base;
-	struct resource		*res;
-	struct device		*dev;
-	struct regmap_field	*fields[F_MAX_FIELDS];
-
-	struct cal_dev		*cal;
-	unsigned int		instance;
-
-	struct v4l2_fwnode_endpoint	endpoint;
-	struct device_node	*sensor_node;
-	struct v4l2_subdev	*sensor;
-};
-
-struct cal_dev {
-	struct clk		*fclk;
-	int			irq;
-	void __iomem		*base;
-	struct resource		*res;
-	struct device		*dev;
-
-	const struct cal_data	*data;
-	u32			revision;
-
-	/* Control Module handle */
-	struct regmap		*syscon_camerrx;
-	u32			syscon_camerrx_offset;
-
-	/* Camera Core Module handle */
-	struct cal_camerarx	*phy[CAL_NUM_CSI2_PORTS];
-
-	struct cal_ctx		*ctx[CAL_NUM_CONTEXT];
-
-	struct media_device	mdev;
-	struct v4l2_device	v4l2_dev;
-	struct v4l2_async_notifier notifier;
-};
-
-/*
- * There is one cal_ctx structure for each camera core context.
- */
-struct cal_ctx {
-	struct v4l2_ctrl_handler ctrl_handler;
-	struct video_device	vdev;
-	struct media_pad	pad;
-
-	struct cal_dev		*cal;
-	struct cal_camerarx	*phy;
-
-	/* v4l2_ioctl mutex */
-	struct mutex		mutex;
-	/* v4l2 buffers lock */
-	spinlock_t		slock;
-
-	struct cal_dmaqueue	vidq;
-
-	/* video capture */
-	const struct cal_fmt	*fmt;
-	/* Used to store current pixel format */
-	struct v4l2_format		v_fmt;
-	/* Used to store current mbus frame format */
-	struct v4l2_mbus_framefmt	m_fmt;
-
-	/* Current subdev enumerated format */
-	const struct cal_fmt	**active_fmt;
-	unsigned int		num_active_fmt;
-
-	unsigned int		sequence;
-	struct vb2_queue	vb_vidq;
-	unsigned int		index;
-	unsigned int		cport;
-
-	/* Pointer pointing to current v4l2_buffer */
-	struct cal_buffer	*cur_frm;
-	/* Pointer pointing to next v4l2_buffer */
-	struct cal_buffer	*next_frm;
-
-	bool dma_act;
-};
-
 /* ------------------------------------------------------------------
  *	Platform Data
  * ------------------------------------------------------------------
@@ -451,7 +160,7 @@ static inline void set_field(u32 *valp, u32 field, u32 mask)
 	*valp = val;
 }
 
-static void cal_quickdump_regs(struct cal_dev *cal)
+void cal_quickdump_regs(struct cal_dev *cal)
 {
 	unsigned int i;
 
@@ -661,8 +370,7 @@ static void cal_camerarx_wait_stop_state(struct cal_camerarx *phy)
 		phy_err(phy, "Timeout waiting for stop state\n");
 }
 
-static int cal_camerarx_start(struct cal_camerarx *phy,
-			      const struct cal_fmt *fmt)
+int cal_camerarx_start(struct cal_camerarx *phy, const struct cal_fmt *fmt)
 {
 	s64 external_rate;
 	u32 sscounter;
@@ -789,7 +497,7 @@ static int cal_camerarx_start(struct cal_camerarx *phy,
 	return 0;
 }
 
-static void cal_camerarx_stop(struct cal_camerarx *phy)
+void cal_camerarx_stop(struct cal_camerarx *phy)
 {
 	unsigned int i;
 	int ret;
@@ -858,7 +566,7 @@ static void cal_camerarx_i913_errata(struct cal_camerarx *phy)
 /*
  * Enable the expected IRQ sources
  */
-static void cal_camerarx_enable_irqs(struct cal_camerarx *phy)
+void cal_camerarx_enable_irqs(struct cal_camerarx *phy)
 {
 	u32 val;
 
@@ -889,7 +597,7 @@ static void cal_camerarx_enable_irqs(struct cal_camerarx *phy)
 	reg_write(phy->cal, CAL_CSI2_VC_IRQENABLE(0), 0xFF000000);
 }
 
-static void cal_camerarx_disable_irqs(struct cal_camerarx *phy)
+void cal_camerarx_disable_irqs(struct cal_camerarx *phy)
 {
 	u32 val;
 
@@ -911,14 +619,14 @@ static void cal_camerarx_disable_irqs(struct cal_camerarx *phy)
 	reg_write(phy->cal, CAL_CSI2_VC_IRQENABLE(0), 0);
 }
 
-static void cal_camerarx_ppi_enable(struct cal_camerarx *phy)
+void cal_camerarx_ppi_enable(struct cal_camerarx *phy)
 {
 	reg_write(phy->cal, CAL_CSI2_PPI_CTRL(phy->instance), BIT(3));
 	reg_write_field(phy->cal, CAL_CSI2_PPI_CTRL(phy->instance),
 			1, CAL_CSI2_PPI_CTRL_IF_EN_MASK);
 }
 
-static void cal_camerarx_ppi_disable(struct cal_camerarx *phy)
+void cal_camerarx_ppi_disable(struct cal_camerarx *phy)
 {
 	reg_write_field(phy->cal, CAL_CSI2_PPI_CTRL(phy->instance),
 			0, CAL_CSI2_PPI_CTRL_IF_EN_MASK);
@@ -1133,7 +841,7 @@ static int cal_camerarx_init_regmap(struct cal_dev *cal)
  * ------------------------------------------------------------------
  */
 
-static void cal_ctx_csi2_config(struct cal_ctx *ctx)
+void cal_ctx_csi2_config(struct cal_ctx *ctx)
 {
 	u32 val;
 
@@ -1158,7 +866,7 @@ static void cal_ctx_csi2_config(struct cal_ctx *ctx)
 		reg_read(ctx->cal, CAL_CSI2_CTX0(ctx->index)));
 }
 
-static void cal_ctx_pix_proc_config(struct cal_ctx *ctx)
+void cal_ctx_pix_proc_config(struct cal_ctx *ctx)
 {
 	u32 val, extract, pack;
 
@@ -1209,8 +917,8 @@ static void cal_ctx_pix_proc_config(struct cal_ctx *ctx)
 		reg_read(ctx->cal, CAL_PIX_PROC(ctx->index)));
 }
 
-static void cal_ctx_wr_dma_config(struct cal_ctx *ctx,
-				  unsigned int width, unsigned int height)
+void cal_ctx_wr_dma_config(struct cal_ctx *ctx, unsigned int width,
+			    unsigned int height)
 {
 	u32 val;
 
@@ -1263,7 +971,7 @@ static void cal_ctx_wr_dma_config(struct cal_ctx *ctx,
 	ctx_dbg(3, ctx, "CAL_CTRL = 0x%08x\n", reg_read(ctx->cal, CAL_CTRL));
 }
 
-static void cal_ctx_wr_dma_addr(struct cal_ctx *ctx, unsigned int dmaaddr)
+void cal_ctx_wr_dma_addr(struct cal_ctx *ctx, unsigned int dmaaddr)
 {
 	reg_write(ctx->cal, CAL_WR_DMA_ADDR(ctx->index), dmaaddr);
 }
@@ -1371,753 +1079,6 @@ static irqreturn_t cal_irq(int irq_cal, void *data)
 	return IRQ_HANDLED;
 }
 
-/* ------------------------------------------------------------------
- *	V4L2 Video IOCTLs
- * ------------------------------------------------------------------
- */
-
-static const struct cal_fmt *find_format_by_pix(struct cal_ctx *ctx,
-						u32 pixelformat)
-{
-	const struct cal_fmt *fmt;
-	unsigned int k;
-
-	for (k = 0; k < ctx->num_active_fmt; k++) {
-		fmt = ctx->active_fmt[k];
-		if (fmt->fourcc == pixelformat)
-			return fmt;
-	}
-
-	return NULL;
-}
-
-static const struct cal_fmt *find_format_by_code(struct cal_ctx *ctx,
-						 u32 code)
-{
-	const struct cal_fmt *fmt;
-	unsigned int k;
-
-	for (k = 0; k < ctx->num_active_fmt; k++) {
-		fmt = ctx->active_fmt[k];
-		if (fmt->code == code)
-			return fmt;
-	}
-
-	return NULL;
-}
-
-static int cal_querycap(struct file *file, void *priv,
-			struct v4l2_capability *cap)
-{
-	struct cal_ctx *ctx = video_drvdata(file);
-
-	strscpy(cap->driver, CAL_MODULE_NAME, sizeof(cap->driver));
-	strscpy(cap->card, CAL_MODULE_NAME, sizeof(cap->card));
-
-	snprintf(cap->bus_info, sizeof(cap->bus_info),
-		 "platform:%s", dev_name(ctx->cal->dev));
-	return 0;
-}
-
-static int cal_enum_fmt_vid_cap(struct file *file, void  *priv,
-				struct v4l2_fmtdesc *f)
-{
-	struct cal_ctx *ctx = video_drvdata(file);
-	const struct cal_fmt *fmt;
-
-	if (f->index >= ctx->num_active_fmt)
-		return -EINVAL;
-
-	fmt = ctx->active_fmt[f->index];
-
-	f->pixelformat = fmt->fourcc;
-	f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-	return 0;
-}
-
-static int __subdev_get_format(struct cal_ctx *ctx,
-			       struct v4l2_mbus_framefmt *fmt)
-{
-	struct v4l2_subdev_format sd_fmt;
-	struct v4l2_mbus_framefmt *mbus_fmt = &sd_fmt.format;
-	int ret;
-
-	sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
-	sd_fmt.pad = 0;
-
-	ret = v4l2_subdev_call(ctx->phy->sensor, pad, get_fmt, NULL, &sd_fmt);
-	if (ret)
-		return ret;
-
-	*fmt = *mbus_fmt;
-
-	ctx_dbg(1, ctx, "%s %dx%d code:%04X\n", __func__,
-		fmt->width, fmt->height, fmt->code);
-
-	return 0;
-}
-
-static int __subdev_set_format(struct cal_ctx *ctx,
-			       struct v4l2_mbus_framefmt *fmt)
-{
-	struct v4l2_subdev_format sd_fmt;
-	struct v4l2_mbus_framefmt *mbus_fmt = &sd_fmt.format;
-	int ret;
-
-	sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
-	sd_fmt.pad = 0;
-	*mbus_fmt = *fmt;
-
-	ret = v4l2_subdev_call(ctx->phy->sensor, pad, set_fmt, NULL, &sd_fmt);
-	if (ret)
-		return ret;
-
-	ctx_dbg(1, ctx, "%s %dx%d code:%04X\n", __func__,
-		fmt->width, fmt->height, fmt->code);
-
-	return 0;
-}
-
-static int cal_calc_format_size(struct cal_ctx *ctx,
-				const struct cal_fmt *fmt,
-				struct v4l2_format *f)
-{
-	u32 bpl, max_width;
-
-	if (!fmt) {
-		ctx_dbg(3, ctx, "No cal_fmt provided!\n");
-		return -EINVAL;
-	}
-
-	/*
-	 * Maximum width is bound by the DMA max width in bytes.
-	 * We need to recalculate the actual maxi width depending on the
-	 * number of bytes per pixels required.
-	 */
-	max_width = MAX_WIDTH_BYTES / (ALIGN(fmt->bpp, 8) >> 3);
-	v4l_bound_align_image(&f->fmt.pix.width, 48, max_width, 2,
-			      &f->fmt.pix.height, 32, MAX_HEIGHT_LINES, 0, 0);
-
-	bpl = (f->fmt.pix.width * ALIGN(fmt->bpp, 8)) >> 3;
-	f->fmt.pix.bytesperline = ALIGN(bpl, 16);
-
-	f->fmt.pix.sizeimage = f->fmt.pix.height *
-			       f->fmt.pix.bytesperline;
-
-	ctx_dbg(3, ctx, "%s: fourcc: %s size: %dx%d bpl:%d img_size:%d\n",
-		__func__, fourcc_to_str(f->fmt.pix.pixelformat),
-		f->fmt.pix.width, f->fmt.pix.height,
-		f->fmt.pix.bytesperline, f->fmt.pix.sizeimage);
-
-	return 0;
-}
-
-static int cal_g_fmt_vid_cap(struct file *file, void *priv,
-			     struct v4l2_format *f)
-{
-	struct cal_ctx *ctx = video_drvdata(file);
-
-	*f = ctx->v_fmt;
-
-	return 0;
-}
-
-static int cal_try_fmt_vid_cap(struct file *file, void *priv,
-			       struct v4l2_format *f)
-{
-	struct cal_ctx *ctx = video_drvdata(file);
-	const struct cal_fmt *fmt;
-	struct v4l2_subdev_frame_size_enum fse;
-	int ret, found;
-
-	fmt = find_format_by_pix(ctx, f->fmt.pix.pixelformat);
-	if (!fmt) {
-		ctx_dbg(3, ctx, "Fourcc format (0x%08x) not found.\n",
-			f->fmt.pix.pixelformat);
-
-		/* Just get the first one enumerated */
-		fmt = ctx->active_fmt[0];
-		f->fmt.pix.pixelformat = fmt->fourcc;
-	}
-
-	f->fmt.pix.field = ctx->v_fmt.fmt.pix.field;
-
-	/* check for/find a valid width/height */
-	ret = 0;
-	found = false;
-	fse.pad = 0;
-	fse.code = fmt->code;
-	fse.which = V4L2_SUBDEV_FORMAT_ACTIVE;
-	for (fse.index = 0; ; fse.index++) {
-		ret = v4l2_subdev_call(ctx->phy->sensor, pad, enum_frame_size,
-				       NULL, &fse);
-		if (ret)
-			break;
-
-		if ((f->fmt.pix.width == fse.max_width) &&
-		    (f->fmt.pix.height == fse.max_height)) {
-			found = true;
-			break;
-		} else if ((f->fmt.pix.width >= fse.min_width) &&
-			 (f->fmt.pix.width <= fse.max_width) &&
-			 (f->fmt.pix.height >= fse.min_height) &&
-			 (f->fmt.pix.height <= fse.max_height)) {
-			found = true;
-			break;
-		}
-	}
-
-	if (!found) {
-		/* use existing values as default */
-		f->fmt.pix.width = ctx->v_fmt.fmt.pix.width;
-		f->fmt.pix.height =  ctx->v_fmt.fmt.pix.height;
-	}
-
-	/*
-	 * Use current colorspace for now, it will get
-	 * updated properly during s_fmt
-	 */
-	f->fmt.pix.colorspace = ctx->v_fmt.fmt.pix.colorspace;
-	return cal_calc_format_size(ctx, fmt, f);
-}
-
-static int cal_s_fmt_vid_cap(struct file *file, void *priv,
-			     struct v4l2_format *f)
-{
-	struct cal_ctx *ctx = video_drvdata(file);
-	struct vb2_queue *q = &ctx->vb_vidq;
-	const struct cal_fmt *fmt;
-	struct v4l2_mbus_framefmt mbus_fmt;
-	int ret;
-
-	if (vb2_is_busy(q)) {
-		ctx_dbg(3, ctx, "%s device busy\n", __func__);
-		return -EBUSY;
-	}
-
-	ret = cal_try_fmt_vid_cap(file, priv, f);
-	if (ret < 0)
-		return ret;
-
-	fmt = find_format_by_pix(ctx, f->fmt.pix.pixelformat);
-
-	v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, fmt->code);
-
-	ret = __subdev_set_format(ctx, &mbus_fmt);
-	if (ret)
-		return ret;
-
-	/* Just double check nothing has gone wrong */
-	if (mbus_fmt.code != fmt->code) {
-		ctx_dbg(3, ctx,
-			"%s subdev changed format on us, this should not happen\n",
-			__func__);
-		return -EINVAL;
-	}
-
-	v4l2_fill_pix_format(&ctx->v_fmt.fmt.pix, &mbus_fmt);
-	ctx->v_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-	ctx->v_fmt.fmt.pix.pixelformat  = fmt->fourcc;
-	cal_calc_format_size(ctx, fmt, &ctx->v_fmt);
-	ctx->fmt = fmt;
-	ctx->m_fmt = mbus_fmt;
-	*f = ctx->v_fmt;
-
-	return 0;
-}
-
-static int cal_enum_framesizes(struct file *file, void *fh,
-			       struct v4l2_frmsizeenum *fsize)
-{
-	struct cal_ctx *ctx = video_drvdata(file);
-	const struct cal_fmt *fmt;
-	struct v4l2_subdev_frame_size_enum fse;
-	int ret;
-
-	/* check for valid format */
-	fmt = find_format_by_pix(ctx, fsize->pixel_format);
-	if (!fmt) {
-		ctx_dbg(3, ctx, "Invalid pixel code: %x\n",
-			fsize->pixel_format);
-		return -EINVAL;
-	}
-
-	fse.index = fsize->index;
-	fse.pad = 0;
-	fse.code = fmt->code;
-	fse.which = V4L2_SUBDEV_FORMAT_ACTIVE;
-
-	ret = v4l2_subdev_call(ctx->phy->sensor, pad, enum_frame_size, NULL,
-			       &fse);
-	if (ret)
-		return ret;
-
-	ctx_dbg(1, ctx, "%s: index: %d code: %x W:[%d,%d] H:[%d,%d]\n",
-		__func__, fse.index, fse.code, fse.min_width, fse.max_width,
-		fse.min_height, fse.max_height);
-
-	fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
-	fsize->discrete.width = fse.max_width;
-	fsize->discrete.height = fse.max_height;
-
-	return 0;
-}
-
-static int cal_enum_input(struct file *file, void *priv,
-			  struct v4l2_input *inp)
-{
-	if (inp->index > 0)
-		return -EINVAL;
-
-	inp->type = V4L2_INPUT_TYPE_CAMERA;
-	sprintf(inp->name, "Camera %u", inp->index);
-	return 0;
-}
-
-static int cal_g_input(struct file *file, void *priv, unsigned int *i)
-{
-	*i = 0;
-	return 0;
-}
-
-static int cal_s_input(struct file *file, void *priv, unsigned int i)
-{
-	return i > 0 ? -EINVAL : 0;
-}
-
-/* timeperframe is arbitrary and continuous */
-static int cal_enum_frameintervals(struct file *file, void *priv,
-				   struct v4l2_frmivalenum *fival)
-{
-	struct cal_ctx *ctx = video_drvdata(file);
-	const struct cal_fmt *fmt;
-	struct v4l2_subdev_frame_interval_enum fie = {
-		.index = fival->index,
-		.width = fival->width,
-		.height = fival->height,
-		.which = V4L2_SUBDEV_FORMAT_ACTIVE,
-	};
-	int ret;
-
-	fmt = find_format_by_pix(ctx, fival->pixel_format);
-	if (!fmt)
-		return -EINVAL;
-
-	fie.code = fmt->code;
-	ret = v4l2_subdev_call(ctx->phy->sensor, pad, enum_frame_interval,
-			       NULL, &fie);
-	if (ret)
-		return ret;
-	fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
-	fival->discrete = fie.interval;
-
-	return 0;
-}
-
-static const struct v4l2_file_operations cal_fops = {
-	.owner		= THIS_MODULE,
-	.open           = v4l2_fh_open,
-	.release        = vb2_fop_release,
-	.read           = vb2_fop_read,
-	.poll		= vb2_fop_poll,
-	.unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */
-	.mmap           = vb2_fop_mmap,
-};
-
-static const struct v4l2_ioctl_ops cal_ioctl_ops = {
-	.vidioc_querycap      = cal_querycap,
-	.vidioc_enum_fmt_vid_cap  = cal_enum_fmt_vid_cap,
-	.vidioc_g_fmt_vid_cap     = cal_g_fmt_vid_cap,
-	.vidioc_try_fmt_vid_cap   = cal_try_fmt_vid_cap,
-	.vidioc_s_fmt_vid_cap     = cal_s_fmt_vid_cap,
-	.vidioc_enum_framesizes   = cal_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_enum_input    = cal_enum_input,
-	.vidioc_g_input       = cal_g_input,
-	.vidioc_s_input       = cal_s_input,
-	.vidioc_enum_frameintervals = cal_enum_frameintervals,
-	.vidioc_streamon      = vb2_ioctl_streamon,
-	.vidioc_streamoff     = vb2_ioctl_streamoff,
-	.vidioc_log_status    = v4l2_ctrl_log_status,
-	.vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
-	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
-};
-
-/* ------------------------------------------------------------------
- *	videobuf2 Operations
- * ------------------------------------------------------------------
- */
-
-static int cal_queue_setup(struct vb2_queue *vq,
-			   unsigned int *nbuffers, unsigned int *nplanes,
-			   unsigned int sizes[], struct device *alloc_devs[])
-{
-	struct cal_ctx *ctx = vb2_get_drv_priv(vq);
-	unsigned int size = ctx->v_fmt.fmt.pix.sizeimage;
-
-	if (vq->num_buffers + *nbuffers < 3)
-		*nbuffers = 3 - vq->num_buffers;
-
-	if (*nplanes) {
-		if (sizes[0] < size)
-			return -EINVAL;
-		size = sizes[0];
-	}
-
-	*nplanes = 1;
-	sizes[0] = size;
-
-	ctx_dbg(3, ctx, "nbuffers=%d, size=%d\n", *nbuffers, sizes[0]);
-
-	return 0;
-}
-
-static int cal_buffer_prepare(struct vb2_buffer *vb)
-{
-	struct cal_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
-	struct cal_buffer *buf = container_of(vb, struct cal_buffer,
-					      vb.vb2_buf);
-	unsigned long size;
-
-	if (WARN_ON(!ctx->fmt))
-		return -EINVAL;
-
-	size = ctx->v_fmt.fmt.pix.sizeimage;
-	if (vb2_plane_size(vb, 0) < size) {
-		ctx_err(ctx,
-			"data will not fit into plane (%lu < %lu)\n",
-			vb2_plane_size(vb, 0), size);
-		return -EINVAL;
-	}
-
-	vb2_set_plane_payload(&buf->vb.vb2_buf, 0, size);
-	return 0;
-}
-
-static void cal_buffer_queue(struct vb2_buffer *vb)
-{
-	struct cal_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
-	struct cal_buffer *buf = container_of(vb, struct cal_buffer,
-					      vb.vb2_buf);
-	struct cal_dmaqueue *vidq = &ctx->vidq;
-	unsigned long flags;
-
-	/* recheck locking */
-	spin_lock_irqsave(&ctx->slock, flags);
-	list_add_tail(&buf->list, &vidq->active);
-	spin_unlock_irqrestore(&ctx->slock, flags);
-}
-
-static int cal_start_streaming(struct vb2_queue *vq, unsigned int count)
-{
-	struct cal_ctx *ctx = vb2_get_drv_priv(vq);
-	struct cal_dmaqueue *dma_q = &ctx->vidq;
-	struct cal_buffer *buf, *tmp;
-	unsigned long addr;
-	unsigned long flags;
-	int ret;
-
-	spin_lock_irqsave(&ctx->slock, flags);
-	if (list_empty(&dma_q->active)) {
-		spin_unlock_irqrestore(&ctx->slock, flags);
-		ctx_dbg(3, ctx, "buffer queue is empty\n");
-		return -EIO;
-	}
-
-	buf = list_entry(dma_q->active.next, struct cal_buffer, list);
-	ctx->cur_frm = buf;
-	ctx->next_frm = buf;
-	list_del(&buf->list);
-	spin_unlock_irqrestore(&ctx->slock, flags);
-
-	addr = vb2_dma_contig_plane_dma_addr(&ctx->cur_frm->vb.vb2_buf, 0);
-	ctx->sequence = 0;
-
-	pm_runtime_get_sync(ctx->cal->dev);
-
-	cal_ctx_csi2_config(ctx);
-	cal_ctx_pix_proc_config(ctx);
-	cal_ctx_wr_dma_config(ctx, ctx->v_fmt.fmt.pix.bytesperline,
-			      ctx->v_fmt.fmt.pix.height);
-
-	cal_camerarx_enable_irqs(ctx->phy);
-
-	ret = cal_camerarx_start(ctx->phy, ctx->fmt);
-	if (ret)
-		goto err;
-
-	cal_ctx_wr_dma_addr(ctx, addr);
-	cal_camerarx_ppi_enable(ctx->phy);
-
-	if (debug >= 4)
-		cal_quickdump_regs(ctx->cal);
-
-	return 0;
-
-err:
-	spin_lock_irqsave(&ctx->slock, flags);
-	vb2_buffer_done(&ctx->cur_frm->vb.vb2_buf, VB2_BUF_STATE_QUEUED);
-	ctx->cur_frm = NULL;
-	ctx->next_frm = NULL;
-	list_for_each_entry_safe(buf, tmp, &dma_q->active, list) {
-		list_del(&buf->list);
-		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_QUEUED);
-	}
-	spin_unlock_irqrestore(&ctx->slock, flags);
-	return ret;
-}
-
-static void cal_stop_streaming(struct vb2_queue *vq)
-{
-	struct cal_ctx *ctx = vb2_get_drv_priv(vq);
-	struct cal_dmaqueue *dma_q = &ctx->vidq;
-	struct cal_buffer *buf, *tmp;
-	unsigned long timeout;
-	unsigned long flags;
-	bool dma_act;
-
-	cal_camerarx_ppi_disable(ctx->phy);
-
-	/* wait for stream and dma to finish */
-	dma_act = true;
-	timeout = jiffies + msecs_to_jiffies(500);
-	while (dma_act && time_before(jiffies, timeout)) {
-		msleep(50);
-
-		spin_lock_irqsave(&ctx->slock, flags);
-		dma_act = ctx->dma_act;
-		spin_unlock_irqrestore(&ctx->slock, flags);
-	}
-
-	if (dma_act)
-		ctx_err(ctx, "failed to disable dma cleanly\n");
-
-	cal_camerarx_disable_irqs(ctx->phy);
-	cal_camerarx_stop(ctx->phy);
-
-	/* Release all active buffers */
-	spin_lock_irqsave(&ctx->slock, flags);
-	list_for_each_entry_safe(buf, tmp, &dma_q->active, list) {
-		list_del(&buf->list);
-		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
-	}
-
-	if (ctx->cur_frm == ctx->next_frm) {
-		vb2_buffer_done(&ctx->cur_frm->vb.vb2_buf, VB2_BUF_STATE_ERROR);
-	} else {
-		vb2_buffer_done(&ctx->cur_frm->vb.vb2_buf, VB2_BUF_STATE_ERROR);
-		vb2_buffer_done(&ctx->next_frm->vb.vb2_buf,
-				VB2_BUF_STATE_ERROR);
-	}
-	ctx->cur_frm = NULL;
-	ctx->next_frm = NULL;
-	spin_unlock_irqrestore(&ctx->slock, flags);
-
-	pm_runtime_put_sync(ctx->cal->dev);
-}
-
-static const struct vb2_ops cal_video_qops = {
-	.queue_setup		= cal_queue_setup,
-	.buf_prepare		= cal_buffer_prepare,
-	.buf_queue		= cal_buffer_queue,
-	.start_streaming	= cal_start_streaming,
-	.stop_streaming		= cal_stop_streaming,
-	.wait_prepare		= vb2_ops_wait_prepare,
-	.wait_finish		= vb2_ops_wait_finish,
-};
-
-/* ------------------------------------------------------------------
- *	V4L2 Initialization and Registration
- * ------------------------------------------------------------------
- */
-
-static const struct video_device cal_videodev = {
-	.name		= CAL_MODULE_NAME,
-	.fops		= &cal_fops,
-	.ioctl_ops	= &cal_ioctl_ops,
-	.minor		= -1,
-	.release	= video_device_release_empty,
-	.device_caps	= V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING |
-			  V4L2_CAP_READWRITE,
-};
-
-static int cal_ctx_v4l2_init_formats(struct cal_ctx *ctx)
-{
-	struct v4l2_subdev_mbus_code_enum mbus_code;
-	struct v4l2_mbus_framefmt mbus_fmt;
-	const struct cal_fmt *fmt;
-	unsigned int i, j, k;
-	int ret = 0;
-
-	/* Enumerate sub device formats and enable all matching local formats */
-	ctx->active_fmt = devm_kcalloc(ctx->cal->dev, ARRAY_SIZE(cal_formats),
-				       sizeof(*ctx->active_fmt), GFP_KERNEL);
-	if (!ctx->active_fmt)
-		return -ENOMEM;
-
-	ctx->num_active_fmt = 0;
-
-	for (j = 0, i = 0; ret != -EINVAL; ++j) {
-
-		memset(&mbus_code, 0, sizeof(mbus_code));
-		mbus_code.index = j;
-		mbus_code.which = V4L2_SUBDEV_FORMAT_ACTIVE;
-		ret = v4l2_subdev_call(ctx->phy->sensor, pad, enum_mbus_code,
-				       NULL, &mbus_code);
-		if (ret)
-			continue;
-
-		ctx_dbg(2, ctx,
-			"subdev %s: code: %04x idx: %u\n",
-			ctx->phy->sensor->name, mbus_code.code, j);
-
-		for (k = 0; k < ARRAY_SIZE(cal_formats); k++) {
-			const struct cal_fmt *fmt = &cal_formats[k];
-
-			if (mbus_code.code == fmt->code) {
-				ctx->active_fmt[i] = fmt;
-				ctx_dbg(2, ctx,
-					"matched fourcc: %s: code: %04x idx: %u\n",
-					fourcc_to_str(fmt->fourcc),
-					fmt->code, i);
-				ctx->num_active_fmt = ++i;
-			}
-		}
-	}
-
-	if (i == 0) {
-		ctx_err(ctx, "No suitable format reported by subdev %s\n",
-			ctx->phy->sensor->name);
-		return -EINVAL;
-	}
-
-	ret = __subdev_get_format(ctx, &mbus_fmt);
-	if (ret)
-		return ret;
-
-	fmt = find_format_by_code(ctx, mbus_fmt.code);
-	if (!fmt) {
-		ctx_dbg(3, ctx, "mbus code format (0x%08x) not found.\n",
-			mbus_fmt.code);
-		return -EINVAL;
-	}
-
-	/* Save current subdev format */
-	v4l2_fill_pix_format(&ctx->v_fmt.fmt.pix, &mbus_fmt);
-	ctx->v_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-	ctx->v_fmt.fmt.pix.pixelformat  = fmt->fourcc;
-	cal_calc_format_size(ctx, fmt, &ctx->v_fmt);
-	ctx->fmt = fmt;
-	ctx->m_fmt = mbus_fmt;
-
-	return 0;
-}
-
-static int cal_ctx_v4l2_register(struct cal_ctx *ctx)
-{
-	struct v4l2_ctrl_handler *hdl = &ctx->ctrl_handler;
-	struct video_device *vfd = &ctx->vdev;
-	int ret;
-
-	ret = cal_ctx_v4l2_init_formats(ctx);
-	if (ret)
-		return ret;
-
-	ret = v4l2_ctrl_add_handler(hdl, ctx->phy->sensor->ctrl_handler, NULL,
-				    true);
-	if (ret < 0) {
-		ctx_err(ctx, "Failed to add sensor ctrl handler\n");
-		return ret;
-	}
-
-	ret = video_register_device(vfd, VFL_TYPE_VIDEO, video_nr);
-	if (ret < 0) {
-		ctx_err(ctx, "Failed to register video device\n");
-		return ret;
-	}
-
-	ctx_info(ctx, "V4L2 device registered as %s\n",
-		 video_device_node_name(vfd));
-
-	return 0;
-}
-
-static void cal_ctx_v4l2_unregister(struct cal_ctx *ctx)
-{
-	ctx_dbg(1, ctx, "unregistering %s\n",
-		video_device_node_name(&ctx->vdev));
-
-	video_unregister_device(&ctx->vdev);
-}
-
-static int cal_ctx_v4l2_init(struct cal_ctx *ctx)
-{
-	struct v4l2_ctrl_handler *hdl = &ctx->ctrl_handler;
-	struct video_device *vfd = &ctx->vdev;
-	struct vb2_queue *q = &ctx->vb_vidq;
-	int ret;
-
-	INIT_LIST_HEAD(&ctx->vidq.active);
-	spin_lock_init(&ctx->slock);
-	mutex_init(&ctx->mutex);
-
-	/* Initialize the vb2 queue. */
-	q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-	q->io_modes = VB2_MMAP | VB2_DMABUF | VB2_READ;
-	q->drv_priv = ctx;
-	q->buf_struct_size = sizeof(struct cal_buffer);
-	q->ops = &cal_video_qops;
-	q->mem_ops = &vb2_dma_contig_memops;
-	q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
-	q->lock = &ctx->mutex;
-	q->min_buffers_needed = 3;
-	q->dev = ctx->cal->dev;
-
-	ret = vb2_queue_init(q);
-	if (ret)
-		return ret;
-
-	/* Initialize the video device and media entity. */
-	*vfd = cal_videodev;
-	vfd->v4l2_dev = &ctx->cal->v4l2_dev;
-	vfd->queue = q;
-	snprintf(vfd->name, sizeof(vfd->name), "CAL output %u", ctx->index);
-	vfd->lock = &ctx->mutex;
-	video_set_drvdata(vfd, ctx);
-
-	ctx->pad.flags = MEDIA_PAD_FL_SINK;
-	ret = media_entity_pads_init(&vfd->entity, 1, &ctx->pad);
-	if (ret < 0)
-		return ret;
-
-	/* Initialize the control handler. */
-	ret = v4l2_ctrl_handler_init(hdl, 11);
-	if (ret < 0) {
-		ctx_err(ctx, "Failed to init ctrl handler\n");
-		goto error;
-	}
-
-	vfd->ctrl_handler = hdl;
-
-	return 0;
-
-error:
-	media_entity_cleanup(&vfd->entity);
-	return ret;
-}
-
-static void cal_ctx_v4l2_cleanup(struct cal_ctx *ctx)
-{
-	v4l2_ctrl_handler_free(&ctx->ctrl_handler);
-	media_entity_cleanup(&ctx->vdev.entity);
-}
-
 /* ------------------------------------------------------------------
  *	Asynchronous V4L2 subdev binding
  * ------------------------------------------------------------------
diff --git a/drivers/media/platform/ti-vpe/cal.h b/drivers/media/platform/ti-vpe/cal.h
new file mode 100644
index 000000000000..88a6473b1dbe
--- /dev/null
+++ b/drivers/media/platform/ti-vpe/cal.h
@@ -0,0 +1,226 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * TI Camera Access Layer (CAL)
+ *
+ * Copyright (c) 2015-2020 Texas Instruments Inc.
+ *
+ * Authors:
+ *	Benoit Parrot <bparrot@ti.com>
+ *	Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ */
+#ifndef __TI_CAL_H__
+#define __TI_CAL_H__
+
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
+#include <linux/videodev2.h>
+
+#include <media/media-device.h>
+#include <media/v4l2-async.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-dev.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-fwnode.h>
+#include <media/videobuf2-v4l2.h>
+
+#define CAL_MODULE_NAME			"cal"
+#define CAL_NUM_CONTEXT			2
+#define CAL_NUM_CSI2_PORTS		2
+
+#define MAX_WIDTH_BYTES			(8192 * 8)
+#define MAX_HEIGHT_LINES		16383
+
+struct device;
+struct device_node;
+struct resource;
+struct regmap;
+struct regmap_fied;
+struct v4l2_subdev;
+
+/* CTRL_CORE_CAMERRX_CONTROL register field id */
+enum cal_camerarx_field {
+	F_CTRLCLKEN,
+	F_CAMMODE,
+	F_LANEENABLE,
+	F_CSI_MODE,
+	F_MAX_FIELDS,
+};
+
+struct cal_fmt {
+	u32	fourcc;
+	u32	code;
+	/* Bits per pixel */
+	u8	bpp;
+};
+
+/* buffer for one video frame */
+struct cal_buffer {
+	/* common v4l buffer stuff -- must be first */
+	struct vb2_v4l2_buffer	vb;
+	struct list_head	list;
+};
+
+struct cal_dmaqueue {
+	struct list_head	active;
+};
+
+struct cal_camerarx_data {
+	struct {
+		unsigned int lsb;
+		unsigned int msb;
+	} fields[F_MAX_FIELDS];
+	unsigned int num_lanes;
+};
+
+struct cal_data {
+	const struct cal_camerarx_data *camerarx;
+	unsigned int num_csi2_phy;
+	unsigned int flags;
+};
+
+/*
+ * The Camera Adaptation Layer (CAL) module is paired with one or more complex
+ * I/O PHYs (CAMERARX). It contains multiple instances of CSI-2, processing and
+ * DMA contexts.
+ *
+ * The cal_dev structure represents the whole subsystem, including the CAL and
+ * the CAMERARX instances. Instances of struct cal_dev are named cal through the
+ * driver.
+ *
+ * The cal_camerarx structure represents one CAMERARX instance. Instances of
+ * cal_camerarx are named phy through the driver.
+ *
+ * The cal_ctx structure represents the combination of one CSI-2 context, one
+ * processing context and one DMA context. Instance of struct cal_ctx are named
+ * ctx through the driver.
+ */
+
+struct cal_camerarx {
+	void __iomem		*base;
+	struct resource		*res;
+	struct device		*dev;
+	struct regmap_field	*fields[F_MAX_FIELDS];
+
+	struct cal_dev		*cal;
+	unsigned int		instance;
+
+	struct v4l2_fwnode_endpoint	endpoint;
+	struct device_node	*sensor_node;
+	struct v4l2_subdev	*sensor;
+};
+
+struct cal_dev {
+	struct clk		*fclk;
+	int			irq;
+	void __iomem		*base;
+	struct resource		*res;
+	struct device		*dev;
+
+	const struct cal_data	*data;
+	u32			revision;
+
+	/* Control Module handle */
+	struct regmap		*syscon_camerrx;
+	u32			syscon_camerrx_offset;
+
+	/* Camera Core Module handle */
+	struct cal_camerarx	*phy[CAL_NUM_CSI2_PORTS];
+
+	struct cal_ctx		*ctx[CAL_NUM_CONTEXT];
+
+	struct media_device	mdev;
+	struct v4l2_device	v4l2_dev;
+	struct v4l2_async_notifier notifier;
+};
+
+/*
+ * There is one cal_ctx structure for each camera core context.
+ */
+struct cal_ctx {
+	struct v4l2_ctrl_handler ctrl_handler;
+	struct video_device	vdev;
+	struct media_pad	pad;
+
+	struct cal_dev		*cal;
+	struct cal_camerarx	*phy;
+
+	/* v4l2_ioctl mutex */
+	struct mutex		mutex;
+	/* v4l2 buffers lock */
+	spinlock_t		slock;
+
+	struct cal_dmaqueue	vidq;
+
+	/* video capture */
+	const struct cal_fmt	*fmt;
+	/* Used to store current pixel format */
+	struct v4l2_format		v_fmt;
+	/* Used to store current mbus frame format */
+	struct v4l2_mbus_framefmt	m_fmt;
+
+	/* Current subdev enumerated format */
+	const struct cal_fmt	**active_fmt;
+	unsigned int		num_active_fmt;
+
+	unsigned int		sequence;
+	struct vb2_queue	vb_vidq;
+	unsigned int		index;
+	unsigned int		cport;
+
+	/* Pointer pointing to current v4l2_buffer */
+	struct cal_buffer	*cur_frm;
+	/* Pointer pointing to next v4l2_buffer */
+	struct cal_buffer	*next_frm;
+
+	bool dma_act;
+};
+
+extern unsigned int cal_debug;
+extern int cal_video_nr;
+
+#define cal_dbg(level, cal, fmt, arg...)				\
+	do {								\
+		if (cal_debug >= (level))				\
+			dev_dbg((cal)->dev, fmt, ##arg);		\
+	} while (0)
+#define cal_info(cal, fmt, arg...)					\
+	dev_info((cal)->dev, fmt, ##arg)
+#define cal_err(cal, fmt, arg...)					\
+	dev_err((cal)->dev, fmt, ##arg)
+
+#define ctx_dbg(level, ctx, fmt, arg...)				\
+	cal_dbg(level, (ctx)->cal, "ctx%u: " fmt, (ctx)->index, ##arg)
+#define ctx_info(ctx, fmt, arg...)					\
+	cal_info((ctx)->cal, "ctx%u: " fmt, (ctx)->index, ##arg)
+#define ctx_err(ctx, fmt, arg...)					\
+	cal_err((ctx)->cal, "ctx%u: " fmt, (ctx)->index, ##arg)
+
+#define phy_dbg(level, phy, fmt, arg...)				\
+	cal_dbg(level, (phy)->cal, "phy%u: " fmt, (phy)->instance, ##arg)
+#define phy_info(phy, fmt, arg...)					\
+	cal_info((phy)->cal, "phy%u: " fmt, (phy)->instance, ##arg)
+#define phy_err(phy, fmt, arg...)					\
+	cal_err((phy)->cal, "phy%u: " fmt, (phy)->instance, ##arg)
+
+void cal_quickdump_regs(struct cal_dev *cal);
+
+int cal_camerarx_start(struct cal_camerarx *phy, const struct cal_fmt *fmt);
+void cal_camerarx_stop(struct cal_camerarx *phy);
+void cal_camerarx_enable_irqs(struct cal_camerarx *phy);
+void cal_camerarx_disable_irqs(struct cal_camerarx *phy);
+void cal_camerarx_ppi_enable(struct cal_camerarx *phy);
+void cal_camerarx_ppi_disable(struct cal_camerarx *phy);
+
+void cal_ctx_csi2_config(struct cal_ctx *ctx);
+void cal_ctx_pix_proc_config(struct cal_ctx *ctx);
+void cal_ctx_wr_dma_config(struct cal_ctx *ctx, unsigned int width,
+			   unsigned int height);
+void cal_ctx_wr_dma_addr(struct cal_ctx *ctx, unsigned int dmaaddr);
+
+int cal_ctx_v4l2_register(struct cal_ctx *ctx);
+void cal_ctx_v4l2_unregister(struct cal_ctx *ctx);
+int cal_ctx_v4l2_init(struct cal_ctx *ctx);
+void cal_ctx_v4l2_cleanup(struct cal_ctx *ctx);
+
+#endif /* __TI_CAL_H__ */
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 082/107] media: ti-vpe: cal: Move CAL I/O accessors to cal.h
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (80 preceding siblings ...)
  2020-06-14 23:59 ` [PATCH v1 081/107] media: ti-vpe: cal: Split video node handling to cal-video.c Laurent Pinchart
@ 2020-06-14 23:59 ` Laurent Pinchart
  2020-06-15  2:50     ` kernel test robot
  2020-06-19  4:18   ` Ezequiel Garcia
  2020-06-14 23:59 ` [PATCH v1 083/107] media: ti-vpe: cal: Split CAMERARX handling to cal-camerarx.c Laurent Pinchart
                   ` (26 subsequent siblings)
  108 siblings, 2 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:59 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

To prepare for the split of the camerarx code to a separate file, move
the CAL I/O accessors to cal.h. This requires renaming the accessors
with a cal_prefix, as the current names are too generic and prone to
namespace clashes.

The reg_read() and read_write() macros, that cover both CAL and CAMERARX
register access, are split in two groups of inline functions, one for
CAL access and one for CAMERARX access.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal-video.c |   1 -
 drivers/media/platform/ti-vpe/cal.c       | 280 ++++++++++------------
 drivers/media/platform/ti-vpe/cal.h       |  36 +++
 3 files changed, 168 insertions(+), 149 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal-video.c b/drivers/media/platform/ti-vpe/cal-video.c
index 82b32a2f9db5..df472a175e83 100644
--- a/drivers/media/platform/ti-vpe/cal-video.c
+++ b/drivers/media/platform/ti-vpe/cal-video.c
@@ -9,7 +9,6 @@
  *	Laurent Pinchart <laurent.pinchart@ideasonboard.com>
  */
 
-#include <linux/bitfield.h>
 #include <linux/delay.h>
 #include <linux/ioctl.h>
 #include <linux/pm_runtime.h>
diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index 0bc02ba52b59..abeded3b5e6c 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -9,11 +9,9 @@
  *	Laurent Pinchart <laurent.pinchart@ideasonboard.com>
  */
 
-#include <linux/bitfield.h>
 #include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
-#include <linux/io.h>
 #include <linux/mfd/syscon.h>
 #include <linux/module.h>
 #include <linux/of_device.h>
@@ -133,33 +131,6 @@ static const struct cal_data am654_cal_data = {
  * ------------------------------------------------------------------
  */
 
-#define reg_read(dev, offset) ioread32(dev->base + offset)
-#define reg_write(dev, offset, val) iowrite32(val, dev->base + offset)
-
-static inline u32 reg_read_field(struct cal_dev *cal, u32 offset, u32 mask)
-{
-	return FIELD_GET(mask, reg_read(cal, offset));
-}
-
-static inline void reg_write_field(struct cal_dev *cal, u32 offset, u32 value,
-				   u32 mask)
-{
-	u32 val = reg_read(cal, offset);
-
-	val &= ~mask;
-	val |= FIELD_PREP(mask, value);
-	reg_write(cal, offset, val);
-}
-
-static inline void set_field(u32 *valp, u32 field, u32 mask)
-{
-	u32 val = *valp;
-
-	val &= ~mask;
-	val |= (field << __ffs(mask)) & mask;
-	*valp = val;
-}
-
 void cal_quickdump_regs(struct cal_dev *cal)
 {
 	unsigned int i;
@@ -189,6 +160,16 @@ void cal_quickdump_regs(struct cal_dev *cal)
  * ------------------------------------------------------------------
  */
 
+static inline u32 camerarx_read(struct cal_camerarx *phy, u32 offset)
+{
+	return ioread32(phy->base + offset);
+}
+
+static inline void camerarx_write(struct cal_camerarx *phy, u32 offset, u32 val)
+{
+	iowrite32(val, phy->base + offset);
+}
+
 static s64 cal_camerarx_get_external_rate(struct cal_camerarx *phy)
 {
 	struct v4l2_ctrl *ctrl;
@@ -209,15 +190,15 @@ static s64 cal_camerarx_get_external_rate(struct cal_camerarx *phy)
 
 static void cal_camerarx_lane_config(struct cal_camerarx *phy)
 {
-	u32 val = reg_read(phy->cal, CAL_CSI2_COMPLEXIO_CFG(phy->instance));
+	u32 val = cal_read(phy->cal, CAL_CSI2_COMPLEXIO_CFG(phy->instance));
 	u32 lane_mask = CAL_CSI2_COMPLEXIO_CFG_CLOCK_POSITION_MASK;
 	u32 polarity_mask = CAL_CSI2_COMPLEXIO_CFG_CLOCK_POL_MASK;
 	struct v4l2_fwnode_bus_mipi_csi2 *mipi_csi2 =
 		&phy->endpoint.bus.mipi_csi2;
 	int lane;
 
-	set_field(&val, mipi_csi2->clock_lane + 1, lane_mask);
-	set_field(&val, mipi_csi2->lane_polarities[0], polarity_mask);
+	cal_set_field(&val, mipi_csi2->clock_lane + 1, lane_mask);
+	cal_set_field(&val, mipi_csi2->lane_polarities[0], polarity_mask);
 	for (lane = 0; lane < mipi_csi2->num_data_lanes; lane++) {
 		/*
 		 * Every lane are one nibble apart starting with the
@@ -225,12 +206,12 @@ static void cal_camerarx_lane_config(struct cal_camerarx *phy)
 		 */
 		lane_mask <<= 4;
 		polarity_mask <<= 4;
-		set_field(&val, mipi_csi2->data_lanes[lane] + 1, lane_mask);
-		set_field(&val, mipi_csi2->lane_polarities[lane + 1],
-			  polarity_mask);
+		cal_set_field(&val, mipi_csi2->data_lanes[lane] + 1, lane_mask);
+		cal_set_field(&val, mipi_csi2->lane_polarities[lane + 1],
+			      polarity_mask);
 	}
 
-	reg_write(phy->cal, CAL_CSI2_COMPLEXIO_CFG(phy->instance), val);
+	cal_write(phy->cal, CAL_CSI2_COMPLEXIO_CFG(phy->instance), val);
 	phy_dbg(3, phy, "CAL_CSI2_COMPLEXIO_CFG(%d) = 0x%08x\n",
 		phy->instance, val);
 }
@@ -284,23 +265,24 @@ static void cal_camerarx_config(struct cal_camerarx *phy, s64 external_rate,
 	ths_settle = (105 * csi2_ddrclk_khz / 1000000) + 4;
 	phy_dbg(1, phy, "ths_settle: %d (0x%02x)\n", ths_settle, ths_settle);
 
-	reg0 = reg_read(phy, CAL_CSI2_PHY_REG0);
-	set_field(&reg0, CAL_CSI2_PHY_REG0_HSCLOCKCONFIG_DISABLE,
-		  CAL_CSI2_PHY_REG0_HSCLOCKCONFIG_MASK);
-	set_field(&reg0, ths_term, CAL_CSI2_PHY_REG0_THS_TERM_MASK);
-	set_field(&reg0, ths_settle, CAL_CSI2_PHY_REG0_THS_SETTLE_MASK);
+	reg0 = camerarx_read(phy, CAL_CSI2_PHY_REG0);
+	cal_set_field(&reg0, CAL_CSI2_PHY_REG0_HSCLOCKCONFIG_DISABLE,
+		      CAL_CSI2_PHY_REG0_HSCLOCKCONFIG_MASK);
+	cal_set_field(&reg0, ths_term, CAL_CSI2_PHY_REG0_THS_TERM_MASK);
+	cal_set_field(&reg0, ths_settle, CAL_CSI2_PHY_REG0_THS_SETTLE_MASK);
 
 	phy_dbg(1, phy, "CSI2_%d_REG0 = 0x%08x\n", phy->instance, reg0);
-	reg_write(phy, CAL_CSI2_PHY_REG0, reg0);
+	camerarx_write(phy, CAL_CSI2_PHY_REG0, reg0);
 
-	reg1 = reg_read(phy, CAL_CSI2_PHY_REG1);
-	set_field(&reg1, TCLK_TERM, CAL_CSI2_PHY_REG1_TCLK_TERM_MASK);
-	set_field(&reg1, 0xb8, CAL_CSI2_PHY_REG1_DPHY_HS_SYNC_PATTERN_MASK);
-	set_field(&reg1, TCLK_MISS, CAL_CSI2_PHY_REG1_CTRLCLK_DIV_FACTOR_MASK);
-	set_field(&reg1, TCLK_SETTLE, CAL_CSI2_PHY_REG1_TCLK_SETTLE_MASK);
+	reg1 = camerarx_read(phy, CAL_CSI2_PHY_REG1);
+	cal_set_field(&reg1, TCLK_TERM, CAL_CSI2_PHY_REG1_TCLK_TERM_MASK);
+	cal_set_field(&reg1, 0xb8, CAL_CSI2_PHY_REG1_DPHY_HS_SYNC_PATTERN_MASK);
+	cal_set_field(&reg1, TCLK_MISS,
+		      CAL_CSI2_PHY_REG1_CTRLCLK_DIV_FACTOR_MASK);
+	cal_set_field(&reg1, TCLK_SETTLE, CAL_CSI2_PHY_REG1_TCLK_SETTLE_MASK);
 
 	phy_dbg(1, phy, "CSI2_%d_REG1 = 0x%08x\n", phy->instance, reg1);
-	reg_write(phy, CAL_CSI2_PHY_REG1, reg1);
+	camerarx_write(phy, CAL_CSI2_PHY_REG1, reg1);
 }
 
 static void cal_camerarx_power(struct cal_camerarx *phy, bool enable)
@@ -311,13 +293,13 @@ static void cal_camerarx_power(struct cal_camerarx *phy, bool enable)
 	target_state = enable ? CAL_CSI2_COMPLEXIO_CFG_PWR_CMD_STATE_ON :
 		       CAL_CSI2_COMPLEXIO_CFG_PWR_CMD_STATE_OFF;
 
-	reg_write_field(phy->cal, CAL_CSI2_COMPLEXIO_CFG(phy->instance),
+	cal_write_field(phy->cal, CAL_CSI2_COMPLEXIO_CFG(phy->instance),
 			target_state, CAL_CSI2_COMPLEXIO_CFG_PWR_CMD_MASK);
 
 	for (i = 0; i < 10; i++) {
 		u32 current_state;
 
-		current_state = reg_read_field(phy->cal,
+		current_state = cal_read_field(phy->cal,
 					       CAL_CSI2_COMPLEXIO_CFG(phy->instance),
 					       CAL_CSI2_COMPLEXIO_CFG_PWR_STATUS_MASK);
 
@@ -338,7 +320,7 @@ static void cal_camerarx_wait_reset(struct cal_camerarx *phy)
 
 	timeout = jiffies + msecs_to_jiffies(750);
 	while (time_before(jiffies, timeout)) {
-		if (reg_read_field(phy->cal,
+		if (cal_read_field(phy->cal,
 				   CAL_CSI2_COMPLEXIO_CFG(phy->instance),
 				   CAL_CSI2_COMPLEXIO_CFG_RESET_DONE_MASK) ==
 		    CAL_CSI2_COMPLEXIO_CFG_RESET_DONE_RESETCOMPLETED)
@@ -346,7 +328,7 @@ static void cal_camerarx_wait_reset(struct cal_camerarx *phy)
 		usleep_range(500, 5000);
 	}
 
-	if (reg_read_field(phy->cal, CAL_CSI2_COMPLEXIO_CFG(phy->instance),
+	if (cal_read_field(phy->cal, CAL_CSI2_COMPLEXIO_CFG(phy->instance),
 			   CAL_CSI2_COMPLEXIO_CFG_RESET_DONE_MASK) !=
 			   CAL_CSI2_COMPLEXIO_CFG_RESET_DONE_RESETCOMPLETED)
 		phy_err(phy, "Timeout waiting for Complex IO reset done\n");
@@ -358,14 +340,14 @@ static void cal_camerarx_wait_stop_state(struct cal_camerarx *phy)
 
 	timeout = jiffies + msecs_to_jiffies(750);
 	while (time_before(jiffies, timeout)) {
-		if (reg_read_field(phy->cal,
+		if (cal_read_field(phy->cal,
 				   CAL_CSI2_TIMING(phy->instance),
 				   CAL_CSI2_TIMING_FORCE_RX_MODE_IO1_MASK) == 0)
 			break;
 		usleep_range(500, 5000);
 	}
 
-	if (reg_read_field(phy->cal, CAL_CSI2_TIMING(phy->instance),
+	if (cal_read_field(phy->cal, CAL_CSI2_TIMING(phy->instance),
 			   CAL_CSI2_TIMING_FORCE_RX_MODE_IO1_MASK) != 0)
 		phy_err(phy, "Timeout waiting for stop state\n");
 }
@@ -414,15 +396,15 @@ int cal_camerarx_start(struct cal_camerarx *phy, const struct cal_fmt *fmt)
 	 *       at this point, as it requires the external sensor to send the
 	 *       CSI-2 HS clock.
 	 */
-	reg_write_field(phy->cal, CAL_CSI2_COMPLEXIO_CFG(phy->instance),
+	cal_write_field(phy->cal, CAL_CSI2_COMPLEXIO_CFG(phy->instance),
 			CAL_CSI2_COMPLEXIO_CFG_RESET_CTRL_OPERATIONAL,
 			CAL_CSI2_COMPLEXIO_CFG_RESET_CTRL_MASK);
 	phy_dbg(3, phy, "CAL_CSI2_COMPLEXIO_CFG(%d) = 0x%08x De-assert Complex IO Reset\n",
 		phy->instance,
-		reg_read(phy->cal, CAL_CSI2_COMPLEXIO_CFG(phy->instance)));
+		cal_read(phy->cal, CAL_CSI2_COMPLEXIO_CFG(phy->instance)));
 
 	/* Dummy read to allow SCP reset to complete. */
-	reg_read(phy, CAL_CSI2_PHY_REG0);
+	camerarx_read(phy, CAL_CSI2_PHY_REG0);
 
 	/* Program the PHY timing parameters. */
 	cal_camerarx_config(phy, external_rate, fmt);
@@ -439,21 +421,22 @@ int cal_camerarx_start(struct cal_camerarx *phy, const struct cal_fmt *fmt)
 	 */
 	sscounter = DIV_ROUND_UP(clk_get_rate(phy->cal->fclk), 10000 *  16 * 4);
 
-	val = reg_read(phy->cal, CAL_CSI2_TIMING(phy->instance));
-	set_field(&val, 1, CAL_CSI2_TIMING_STOP_STATE_X16_IO1_MASK);
-	set_field(&val, 1, CAL_CSI2_TIMING_STOP_STATE_X4_IO1_MASK);
-	set_field(&val, sscounter, CAL_CSI2_TIMING_STOP_STATE_COUNTER_IO1_MASK);
-	reg_write(phy->cal, CAL_CSI2_TIMING(phy->instance), val);
+	val = cal_read(phy->cal, CAL_CSI2_TIMING(phy->instance));
+	cal_set_field(&val, 1, CAL_CSI2_TIMING_STOP_STATE_X16_IO1_MASK);
+	cal_set_field(&val, 1, CAL_CSI2_TIMING_STOP_STATE_X4_IO1_MASK);
+	cal_set_field(&val, sscounter,
+		      CAL_CSI2_TIMING_STOP_STATE_COUNTER_IO1_MASK);
+	cal_write(phy->cal, CAL_CSI2_TIMING(phy->instance), val);
 	phy_dbg(3, phy, "CAL_CSI2_TIMING(%d) = 0x%08x Stop States\n",
 		phy->instance,
-		reg_read(phy->cal, CAL_CSI2_TIMING(phy->instance)));
+		cal_read(phy->cal, CAL_CSI2_TIMING(phy->instance)));
 
 	/* Assert the FORCERXMODE signal. */
-	reg_write_field(phy->cal, CAL_CSI2_TIMING(phy->instance),
+	cal_write_field(phy->cal, CAL_CSI2_TIMING(phy->instance),
 			1, CAL_CSI2_TIMING_FORCE_RX_MODE_IO1_MASK);
 	phy_dbg(3, phy, "CAL_CSI2_TIMING(%d) = 0x%08x Force RXMODE\n",
 		phy->instance,
-		reg_read(phy->cal, CAL_CSI2_TIMING(phy->instance)));
+		cal_read(phy->cal, CAL_CSI2_TIMING(phy->instance)));
 
 	/*
 	 * c. Connect pull-down on CSI-2 PHY link (using pad control).
@@ -485,7 +468,7 @@ int cal_camerarx_start(struct cal_camerarx *phy, const struct cal_fmt *fmt)
 	cal_camerarx_wait_stop_state(phy);
 
 	phy_dbg(1, phy, "CSI2_%u_REG1 = 0x%08x (bits 31-28 should be set)\n",
-		phy->instance, reg_read(phy, CAL_CSI2_PHY_REG1));
+		phy->instance, camerarx_read(phy, CAL_CSI2_PHY_REG1));
 
 	/*
 	 * g. Disable pull-down on CSI-2 PHY link (using pad control).
@@ -505,13 +488,13 @@ void cal_camerarx_stop(struct cal_camerarx *phy)
 	cal_camerarx_power(phy, false);
 
 	/* Assert Complex IO Reset */
-	reg_write_field(phy->cal, CAL_CSI2_COMPLEXIO_CFG(phy->instance),
+	cal_write_field(phy->cal, CAL_CSI2_COMPLEXIO_CFG(phy->instance),
 			CAL_CSI2_COMPLEXIO_CFG_RESET_CTRL,
 			CAL_CSI2_COMPLEXIO_CFG_RESET_CTRL_MASK);
 
 	/* Wait for power down completion */
 	for (i = 0; i < 10; i++) {
-		if (reg_read_field(phy->cal,
+		if (cal_read_field(phy->cal,
 				   CAL_CSI2_COMPLEXIO_CFG(phy->instance),
 				   CAL_CSI2_COMPLEXIO_CFG_RESET_DONE_MASK) ==
 		    CAL_CSI2_COMPLEXIO_CFG_RESET_DONE_RESETONGOING)
@@ -520,7 +503,7 @@ void cal_camerarx_stop(struct cal_camerarx *phy)
 	}
 	phy_dbg(3, phy, "CAL_CSI2_COMPLEXIO_CFG(%d) = 0x%08x Complex IO in Reset (%d) %s\n",
 		phy->instance,
-		reg_read(phy->cal, CAL_CSI2_COMPLEXIO_CFG(phy->instance)), i,
+		cal_read(phy->cal, CAL_CSI2_COMPLEXIO_CFG(phy->instance)), i,
 		(i >= 10) ? "(timeout)" : "");
 
 	/* Disable the phy */
@@ -555,12 +538,12 @@ void cal_camerarx_stop(struct cal_camerarx *phy)
  */
 static void cal_camerarx_i913_errata(struct cal_camerarx *phy)
 {
-	u32 reg10 = reg_read(phy, CAL_CSI2_PHY_REG10);
+	u32 reg10 = camerarx_read(phy, CAL_CSI2_PHY_REG10);
 
-	set_field(&reg10, 1, CAL_CSI2_PHY_REG10_I933_LDO_DISABLE_MASK);
+	cal_set_field(&reg10, 1, CAL_CSI2_PHY_REG10_I933_LDO_DISABLE_MASK);
 
 	phy_dbg(1, phy, "CSI2_%d_REG10 = 0x%08x\n", phy->instance, reg10);
-	reg_write(phy, CAL_CSI2_PHY_REG10, reg10);
+	camerarx_write(phy, CAL_CSI2_PHY_REG10, reg10);
 }
 
 /*
@@ -577,24 +560,24 @@ void cal_camerarx_enable_irqs(struct cal_camerarx *phy)
 		CAL_CSI2_COMPLEXIO_IRQ_ECC_NO_CORRECTION_MASK;
 
 	/* Enable CIO error irqs */
-	reg_write(phy->cal, CAL_HL_IRQENABLE_SET(0),
+	cal_write(phy->cal, CAL_HL_IRQENABLE_SET(0),
 		  CAL_HL_IRQ_CIO_MASK(phy->instance));
-	reg_write(phy->cal, CAL_CSI2_COMPLEXIO_IRQENABLE(phy->instance),
+	cal_write(phy->cal, CAL_CSI2_COMPLEXIO_IRQENABLE(phy->instance),
 		  cio_err_mask);
 
 	/* Always enable OCPO error */
-	reg_write(phy->cal, CAL_HL_IRQENABLE_SET(0), CAL_HL_IRQ_OCPO_ERR_MASK);
+	cal_write(phy->cal, CAL_HL_IRQENABLE_SET(0), CAL_HL_IRQ_OCPO_ERR_MASK);
 
 	/* Enable IRQ_WDMA_END 0/1 */
 	val = 0;
-	set_field(&val, 1, CAL_HL_IRQ_MASK(phy->instance));
-	reg_write(phy->cal, CAL_HL_IRQENABLE_SET(1), val);
+	cal_set_field(&val, 1, CAL_HL_IRQ_MASK(phy->instance));
+	cal_write(phy->cal, CAL_HL_IRQENABLE_SET(1), val);
 	/* Enable IRQ_WDMA_START 0/1 */
 	val = 0;
-	set_field(&val, 1, CAL_HL_IRQ_MASK(phy->instance));
-	reg_write(phy->cal, CAL_HL_IRQENABLE_SET(2), val);
+	cal_set_field(&val, 1, CAL_HL_IRQ_MASK(phy->instance));
+	cal_write(phy->cal, CAL_HL_IRQENABLE_SET(2), val);
 	/* Todo: Add VC_IRQ and CSI2_COMPLEXIO_IRQ handling */
-	reg_write(phy->cal, CAL_CSI2_VC_IRQENABLE(0), 0xFF000000);
+	cal_write(phy->cal, CAL_CSI2_VC_IRQENABLE(0), 0xFF000000);
 }
 
 void cal_camerarx_disable_irqs(struct cal_camerarx *phy)
@@ -602,33 +585,33 @@ void cal_camerarx_disable_irqs(struct cal_camerarx *phy)
 	u32 val;
 
 	/* Disable CIO error irqs */
-	reg_write(phy->cal, CAL_HL_IRQENABLE_CLR(0),
+	cal_write(phy->cal, CAL_HL_IRQENABLE_CLR(0),
 		  CAL_HL_IRQ_CIO_MASK(phy->instance));
-	reg_write(phy->cal, CAL_CSI2_COMPLEXIO_IRQENABLE(phy->instance),
+	cal_write(phy->cal, CAL_CSI2_COMPLEXIO_IRQENABLE(phy->instance),
 		  0);
 
 	/* Disable IRQ_WDMA_END 0/1 */
 	val = 0;
-	set_field(&val, 1, CAL_HL_IRQ_MASK(phy->instance));
-	reg_write(phy->cal, CAL_HL_IRQENABLE_CLR(1), val);
+	cal_set_field(&val, 1, CAL_HL_IRQ_MASK(phy->instance));
+	cal_write(phy->cal, CAL_HL_IRQENABLE_CLR(1), val);
 	/* Disable IRQ_WDMA_START 0/1 */
 	val = 0;
-	set_field(&val, 1, CAL_HL_IRQ_MASK(phy->instance));
-	reg_write(phy->cal, CAL_HL_IRQENABLE_CLR(2), val);
+	cal_set_field(&val, 1, CAL_HL_IRQ_MASK(phy->instance));
+	cal_write(phy->cal, CAL_HL_IRQENABLE_CLR(2), val);
 	/* Todo: Add VC_IRQ and CSI2_COMPLEXIO_IRQ handling */
-	reg_write(phy->cal, CAL_CSI2_VC_IRQENABLE(0), 0);
+	cal_write(phy->cal, CAL_CSI2_VC_IRQENABLE(0), 0);
 }
 
 void cal_camerarx_ppi_enable(struct cal_camerarx *phy)
 {
-	reg_write(phy->cal, CAL_CSI2_PPI_CTRL(phy->instance), BIT(3));
-	reg_write_field(phy->cal, CAL_CSI2_PPI_CTRL(phy->instance),
+	cal_write(phy->cal, CAL_CSI2_PPI_CTRL(phy->instance), BIT(3));
+	cal_write_field(phy->cal, CAL_CSI2_PPI_CTRL(phy->instance),
 			1, CAL_CSI2_PPI_CTRL_IF_EN_MASK);
 }
 
 void cal_camerarx_ppi_disable(struct cal_camerarx *phy)
 {
-	reg_write_field(phy->cal, CAL_CSI2_PPI_CTRL(phy->instance),
+	cal_write_field(phy->cal, CAL_CSI2_PPI_CTRL(phy->instance),
 			0, CAL_CSI2_PPI_CTRL_IF_EN_MASK);
 }
 
@@ -845,8 +828,8 @@ void cal_ctx_csi2_config(struct cal_ctx *ctx)
 {
 	u32 val;
 
-	val = reg_read(ctx->cal, CAL_CSI2_CTX0(ctx->index));
-	set_field(&val, ctx->cport, CAL_CSI2_CTX_CPORT_MASK);
+	val = cal_read(ctx->cal, CAL_CSI2_CTX0(ctx->index));
+	cal_set_field(&val, ctx->cport, CAL_CSI2_CTX_CPORT_MASK);
 	/*
 	 * DT type: MIPI CSI-2 Specs
 	 *   0x1: All - DT filter is disabled
@@ -855,15 +838,15 @@ void cal_ctx_csi2_config(struct cal_ctx *ctx)
 	 *  0x2A: RAW8   1 pixel  = 1 byte
 	 *  0x1E: YUV422 2 pixels = 4 bytes
 	 */
-	set_field(&val, 0x1, CAL_CSI2_CTX_DT_MASK);
-	set_field(&val, 0, CAL_CSI2_CTX_VC_MASK);
-	set_field(&val, ctx->v_fmt.fmt.pix.height, CAL_CSI2_CTX_LINES_MASK);
-	set_field(&val, CAL_CSI2_CTX_ATT_PIX, CAL_CSI2_CTX_ATT_MASK);
-	set_field(&val, CAL_CSI2_CTX_PACK_MODE_LINE,
-		  CAL_CSI2_CTX_PACK_MODE_MASK);
-	reg_write(ctx->cal, CAL_CSI2_CTX0(ctx->index), val);
+	cal_set_field(&val, 0x1, CAL_CSI2_CTX_DT_MASK);
+	cal_set_field(&val, 0, CAL_CSI2_CTX_VC_MASK);
+	cal_set_field(&val, ctx->v_fmt.fmt.pix.height, CAL_CSI2_CTX_LINES_MASK);
+	cal_set_field(&val, CAL_CSI2_CTX_ATT_PIX, CAL_CSI2_CTX_ATT_MASK);
+	cal_set_field(&val, CAL_CSI2_CTX_PACK_MODE_LINE,
+		      CAL_CSI2_CTX_PACK_MODE_MASK);
+	cal_write(ctx->cal, CAL_CSI2_CTX0(ctx->index), val);
 	ctx_dbg(3, ctx, "CAL_CSI2_CTX0(%d) = 0x%08x\n", ctx->index,
-		reg_read(ctx->cal, CAL_CSI2_CTX0(ctx->index)));
+		cal_read(ctx->cal, CAL_CSI2_CTX0(ctx->index)));
 }
 
 void cal_ctx_pix_proc_config(struct cal_ctx *ctx)
@@ -905,16 +888,16 @@ void cal_ctx_pix_proc_config(struct cal_ctx *ctx)
 		break;
 	}
 
-	val = reg_read(ctx->cal, CAL_PIX_PROC(ctx->index));
-	set_field(&val, extract, CAL_PIX_PROC_EXTRACT_MASK);
-	set_field(&val, CAL_PIX_PROC_DPCMD_BYPASS, CAL_PIX_PROC_DPCMD_MASK);
-	set_field(&val, CAL_PIX_PROC_DPCME_BYPASS, CAL_PIX_PROC_DPCME_MASK);
-	set_field(&val, pack, CAL_PIX_PROC_PACK_MASK);
-	set_field(&val, ctx->cport, CAL_PIX_PROC_CPORT_MASK);
-	set_field(&val, 1, CAL_PIX_PROC_EN_MASK);
-	reg_write(ctx->cal, CAL_PIX_PROC(ctx->index), val);
+	val = cal_read(ctx->cal, CAL_PIX_PROC(ctx->index));
+	cal_set_field(&val, extract, CAL_PIX_PROC_EXTRACT_MASK);
+	cal_set_field(&val, CAL_PIX_PROC_DPCMD_BYPASS, CAL_PIX_PROC_DPCMD_MASK);
+	cal_set_field(&val, CAL_PIX_PROC_DPCME_BYPASS, CAL_PIX_PROC_DPCME_MASK);
+	cal_set_field(&val, pack, CAL_PIX_PROC_PACK_MASK);
+	cal_set_field(&val, ctx->cport, CAL_PIX_PROC_CPORT_MASK);
+	cal_set_field(&val, 1, CAL_PIX_PROC_EN_MASK);
+	cal_write(ctx->cal, CAL_PIX_PROC(ctx->index), val);
 	ctx_dbg(3, ctx, "CAL_PIX_PROC(%d) = 0x%08x\n", ctx->index,
-		reg_read(ctx->cal, CAL_PIX_PROC(ctx->index)));
+		cal_read(ctx->cal, CAL_PIX_PROC(ctx->index)));
 }
 
 void cal_ctx_wr_dma_config(struct cal_ctx *ctx, unsigned int width,
@@ -922,58 +905,59 @@ void cal_ctx_wr_dma_config(struct cal_ctx *ctx, unsigned int width,
 {
 	u32 val;
 
-	val = reg_read(ctx->cal, CAL_WR_DMA_CTRL(ctx->index));
-	set_field(&val, ctx->cport, CAL_WR_DMA_CTRL_CPORT_MASK);
-	set_field(&val, height, CAL_WR_DMA_CTRL_YSIZE_MASK);
-	set_field(&val, CAL_WR_DMA_CTRL_DTAG_PIX_DAT,
-		  CAL_WR_DMA_CTRL_DTAG_MASK);
-	set_field(&val, CAL_WR_DMA_CTRL_MODE_CONST,
-		  CAL_WR_DMA_CTRL_MODE_MASK);
-	set_field(&val, CAL_WR_DMA_CTRL_PATTERN_LINEAR,
-		  CAL_WR_DMA_CTRL_PATTERN_MASK);
-	set_field(&val, 1, CAL_WR_DMA_CTRL_STALL_RD_MASK);
-	reg_write(ctx->cal, CAL_WR_DMA_CTRL(ctx->index), val);
+	val = cal_read(ctx->cal, CAL_WR_DMA_CTRL(ctx->index));
+	cal_set_field(&val, ctx->cport, CAL_WR_DMA_CTRL_CPORT_MASK);
+	cal_set_field(&val, height, CAL_WR_DMA_CTRL_YSIZE_MASK);
+	cal_set_field(&val, CAL_WR_DMA_CTRL_DTAG_PIX_DAT,
+		      CAL_WR_DMA_CTRL_DTAG_MASK);
+	cal_set_field(&val, CAL_WR_DMA_CTRL_MODE_CONST,
+		      CAL_WR_DMA_CTRL_MODE_MASK);
+	cal_set_field(&val, CAL_WR_DMA_CTRL_PATTERN_LINEAR,
+		      CAL_WR_DMA_CTRL_PATTERN_MASK);
+	cal_set_field(&val, 1, CAL_WR_DMA_CTRL_STALL_RD_MASK);
+	cal_write(ctx->cal, CAL_WR_DMA_CTRL(ctx->index), val);
 	ctx_dbg(3, ctx, "CAL_WR_DMA_CTRL(%d) = 0x%08x\n", ctx->index,
-		reg_read(ctx->cal, CAL_WR_DMA_CTRL(ctx->index)));
+		cal_read(ctx->cal, CAL_WR_DMA_CTRL(ctx->index)));
 
 	/*
 	 * width/16 not sure but giving it a whirl.
 	 * zero does not work right
 	 */
-	reg_write_field(ctx->cal,
+	cal_write_field(ctx->cal,
 			CAL_WR_DMA_OFST(ctx->index),
 			(width / 16),
 			CAL_WR_DMA_OFST_MASK);
 	ctx_dbg(3, ctx, "CAL_WR_DMA_OFST(%d) = 0x%08x\n", ctx->index,
-		reg_read(ctx->cal, CAL_WR_DMA_OFST(ctx->index)));
+		cal_read(ctx->cal, CAL_WR_DMA_OFST(ctx->index)));
 
-	val = reg_read(ctx->cal, CAL_WR_DMA_XSIZE(ctx->index));
+	val = cal_read(ctx->cal, CAL_WR_DMA_XSIZE(ctx->index));
 	/* 64 bit word means no skipping */
-	set_field(&val, 0, CAL_WR_DMA_XSIZE_XSKIP_MASK);
+	cal_set_field(&val, 0, CAL_WR_DMA_XSIZE_XSKIP_MASK);
 	/*
 	 * (width*8)/64 this should be size of an entire line
 	 * in 64bit word but 0 means all data until the end
 	 * is detected automagically
 	 */
-	set_field(&val, (width / 8), CAL_WR_DMA_XSIZE_MASK);
-	reg_write(ctx->cal, CAL_WR_DMA_XSIZE(ctx->index), val);
+	cal_set_field(&val, (width / 8), CAL_WR_DMA_XSIZE_MASK);
+	cal_write(ctx->cal, CAL_WR_DMA_XSIZE(ctx->index), val);
 	ctx_dbg(3, ctx, "CAL_WR_DMA_XSIZE(%d) = 0x%08x\n", ctx->index,
-		reg_read(ctx->cal, CAL_WR_DMA_XSIZE(ctx->index)));
+		cal_read(ctx->cal, CAL_WR_DMA_XSIZE(ctx->index)));
 
-	val = reg_read(ctx->cal, CAL_CTRL);
-	set_field(&val, CAL_CTRL_BURSTSIZE_BURST128, CAL_CTRL_BURSTSIZE_MASK);
-	set_field(&val, 0xF, CAL_CTRL_TAGCNT_MASK);
-	set_field(&val, CAL_CTRL_POSTED_WRITES_NONPOSTED,
-		  CAL_CTRL_POSTED_WRITES_MASK);
-	set_field(&val, 0xFF, CAL_CTRL_MFLAGL_MASK);
-	set_field(&val, 0xFF, CAL_CTRL_MFLAGH_MASK);
-	reg_write(ctx->cal, CAL_CTRL, val);
-	ctx_dbg(3, ctx, "CAL_CTRL = 0x%08x\n", reg_read(ctx->cal, CAL_CTRL));
+	val = cal_read(ctx->cal, CAL_CTRL);
+	cal_set_field(&val, CAL_CTRL_BURSTSIZE_BURST128,
+		      CAL_CTRL_BURSTSIZE_MASK);
+	cal_set_field(&val, 0xF, CAL_CTRL_TAGCNT_MASK);
+	cal_set_field(&val, CAL_CTRL_POSTED_WRITES_NONPOSTED,
+		      CAL_CTRL_POSTED_WRITES_MASK);
+	cal_set_field(&val, 0xFF, CAL_CTRL_MFLAGL_MASK);
+	cal_set_field(&val, 0xFF, CAL_CTRL_MFLAGH_MASK);
+	cal_write(ctx->cal, CAL_CTRL, val);
+	ctx_dbg(3, ctx, "CAL_CTRL = 0x%08x\n", cal_read(ctx->cal, CAL_CTRL));
 }
 
 void cal_ctx_wr_dma_addr(struct cal_ctx *ctx, unsigned int dmaaddr)
 {
-	reg_write(ctx->cal, CAL_WR_DMA_ADDR(ctx->index), dmaaddr);
+	cal_write(ctx->cal, CAL_WR_DMA_ADDR(ctx->index), dmaaddr);
 }
 
 /* ------------------------------------------------------------------
@@ -1013,32 +997,32 @@ static irqreturn_t cal_irq(int irq_cal, void *data)
 	unsigned int i;
 	u32 status;
 
-	status = reg_read(cal, CAL_HL_IRQSTATUS(0));
+	status = cal_read(cal, CAL_HL_IRQSTATUS(0));
 	if (status) {
-		reg_write(cal, CAL_HL_IRQSTATUS(0), status);
+		cal_write(cal, CAL_HL_IRQSTATUS(0), status);
 
 		if (status & CAL_HL_IRQ_OCPO_ERR_MASK)
 			dev_err_ratelimited(cal->dev, "OCPO ERROR\n");
 
 		for (i = 0; i < CAL_NUM_CSI2_PORTS; ++i) {
 			if (status & CAL_HL_IRQ_CIO_MASK(i)) {
-				u32 cio_stat = reg_read(cal,
+				u32 cio_stat = cal_read(cal,
 							CAL_CSI2_COMPLEXIO_IRQSTATUS(i));
 
 				dev_err_ratelimited(cal->dev,
 						    "CIO%u error: %#08x\n", i, cio_stat);
 
-				reg_write(cal, CAL_CSI2_COMPLEXIO_IRQSTATUS(i),
+				cal_write(cal, CAL_CSI2_COMPLEXIO_IRQSTATUS(i),
 					  cio_stat);
 			}
 		}
 	}
 
 	/* Check which DMA just finished */
-	status = reg_read(cal, CAL_HL_IRQSTATUS(1));
+	status = cal_read(cal, CAL_HL_IRQSTATUS(1));
 	if (status) {
 		/* Clear Interrupt status */
-		reg_write(cal, CAL_HL_IRQSTATUS(1), status);
+		cal_write(cal, CAL_HL_IRQSTATUS(1), status);
 
 		for (i = 0; i < ARRAY_SIZE(cal->ctx); ++i) {
 			if (status & CAL_HL_IRQ_MASK(i)) {
@@ -1056,10 +1040,10 @@ static irqreturn_t cal_irq(int irq_cal, void *data)
 	}
 
 	/* Check which DMA just started */
-	status = reg_read(cal, CAL_HL_IRQSTATUS(2));
+	status = cal_read(cal, CAL_HL_IRQSTATUS(2));
 	if (status) {
 		/* Clear Interrupt status */
-		reg_write(cal, CAL_HL_IRQSTATUS(2), status);
+		cal_write(cal, CAL_HL_IRQSTATUS(2), status);
 
 		for (i = 0; i < ARRAY_SIZE(cal->ctx); ++i) {
 			if (status & CAL_HL_IRQ_MASK(i)) {
@@ -1338,7 +1322,7 @@ static void cal_get_hwinfo(struct cal_dev *cal)
 {
 	u32 hwinfo;
 
-	cal->revision = reg_read(cal, CAL_HL_REVISION);
+	cal->revision = cal_read(cal, CAL_HL_REVISION);
 	switch (FIELD_GET(CAL_HL_REVISION_SCHEME_MASK, cal->revision)) {
 	case CAL_HL_REVISION_SCHEME_H08:
 		cal_dbg(3, cal, "CAL HW revision %lu.%lu.%lu (0x%08x)\n",
@@ -1355,7 +1339,7 @@ static void cal_get_hwinfo(struct cal_dev *cal)
 		break;
 	}
 
-	hwinfo = reg_read(cal, CAL_HL_HWINFO);
+	hwinfo = cal_read(cal, CAL_HL_HWINFO);
 	if (hwinfo != CAL_HL_HWINFO_VALUE)
 		cal_info(cal, "CAL_HL_HWINFO = 0x%08x, expected 0x%08x\n",
 			 hwinfo, CAL_HL_HWINFO_VALUE);
diff --git a/drivers/media/platform/ti-vpe/cal.h b/drivers/media/platform/ti-vpe/cal.h
index 88a6473b1dbe..523049f3f9dc 100644
--- a/drivers/media/platform/ti-vpe/cal.h
+++ b/drivers/media/platform/ti-vpe/cal.h
@@ -11,6 +11,8 @@
 #ifndef __TI_CAL_H__
 #define __TI_CAL_H__
 
+#include <linux/bitfield.h>
+#include <linux/io.h>
 #include <linux/list.h>
 #include <linux/mutex.h>
 #include <linux/spinlock.h>
@@ -203,6 +205,40 @@ extern int cal_video_nr;
 #define phy_err(phy, fmt, arg...)					\
 	cal_err((phy)->cal, "phy%u: " fmt, (phy)->instance, ##arg)
 
+static inline u32 cal_read(struct cal_dev *cal, u32 offset)
+{
+	return ioread32(cal->base + offset);
+}
+
+static inline void cal_write(struct cal_dev *cal, u32 offset, u32 val)
+{
+	iowrite32(val, cal->base + offset);
+}
+
+static inline u32 cal_read_field(struct cal_dev *cal, u32 offset, u32 mask)
+{
+	return FIELD_GET(mask, cal_read(cal, offset));
+}
+
+static inline void cal_write_field(struct cal_dev *cal, u32 offset, u32 value,
+				   u32 mask)
+{
+	u32 val = cal_read(cal, offset);
+
+	val &= ~mask;
+	val |= FIELD_PREP(mask, value);
+	cal_write(cal, offset, val);
+}
+
+static inline void cal_set_field(u32 *valp, u32 field, u32 mask)
+{
+	u32 val = *valp;
+
+	val &= ~mask;
+	val |= (field << __ffs(mask)) & mask;
+	*valp = val;
+}
+
 void cal_quickdump_regs(struct cal_dev *cal);
 
 int cal_camerarx_start(struct cal_camerarx *phy, const struct cal_fmt *fmt);
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 083/107] media: ti-vpe: cal: Split CAMERARX handling to cal-camerarx.c
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (81 preceding siblings ...)
  2020-06-14 23:59 ` [PATCH v1 082/107] media: ti-vpe: cal: Move CAL I/O accessors to cal.h Laurent Pinchart
@ 2020-06-14 23:59 ` Laurent Pinchart
  2020-06-14 23:59 ` [PATCH v1 084/107] media: ti-vpe: cal: Create subdev for CAMERARX Laurent Pinchart
                   ` (25 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:59 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

Implementation of media controller centric device configuration will add
code to the CAMERARX support section, which is already quite big. Move
it to a separate file to make the code more manageable. No functional
change is included.

The cal_camerarx_init_regmap() function is kept in cal.c and renamed to
cal_init_camerarx_regmap() as it's not specific to one CAMERARX
instance, but related to the whole CAL device.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/Makefile       |   2 +-
 drivers/media/platform/ti-vpe/cal-camerarx.c | 637 ++++++++++++++++
 drivers/media/platform/ti-vpe/cal.c          | 727 ++-----------------
 drivers/media/platform/ti-vpe/cal.h          |   5 +
 4 files changed, 701 insertions(+), 670 deletions(-)
 create mode 100644 drivers/media/platform/ti-vpe/cal-camerarx.c

diff --git a/drivers/media/platform/ti-vpe/Makefile b/drivers/media/platform/ti-vpe/Makefile
index a7bf8f2a1386..ad624056e039 100644
--- a/drivers/media/platform/ti-vpe/Makefile
+++ b/drivers/media/platform/ti-vpe/Makefile
@@ -13,4 +13,4 @@ ccflags-$(CONFIG_VIDEO_TI_VPE_DEBUG) += -DDEBUG
 
 obj-$(CONFIG_VIDEO_TI_CAL) += ti-cal.o
 
-ti-cal-y := cal.o cal-video.o
+ti-cal-y := cal.o cal-camerarx.o cal-video.o
diff --git a/drivers/media/platform/ti-vpe/cal-camerarx.c b/drivers/media/platform/ti-vpe/cal-camerarx.c
new file mode 100644
index 000000000000..a7e4b81c9734
--- /dev/null
+++ b/drivers/media/platform/ti-vpe/cal-camerarx.c
@@ -0,0 +1,637 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * TI Camera Access Layer (CAL) - CAMERARX
+ *
+ * Copyright (c) 2015-2020 Texas Instruments Inc.
+ *
+ * Authors:
+ *	Benoit Parrot <bparrot@ti.com>
+ *	Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of_graph.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-fwnode.h>
+#include <media/v4l2-subdev.h>
+
+#include "cal.h"
+#include "cal_regs.h"
+
+/* ------------------------------------------------------------------
+ *	I/O Register Accessors
+ * ------------------------------------------------------------------
+ */
+
+static inline u32 camerarx_read(struct cal_camerarx *phy, u32 offset)
+{
+	return ioread32(phy->base + offset);
+}
+
+static inline void camerarx_write(struct cal_camerarx *phy, u32 offset, u32 val)
+{
+	iowrite32(val, phy->base + offset);
+}
+
+/* ------------------------------------------------------------------
+ *	CAMERARX Management
+ * ------------------------------------------------------------------
+ */
+
+static s64 cal_camerarx_get_external_rate(struct cal_camerarx *phy)
+{
+	struct v4l2_ctrl *ctrl;
+	s64 rate;
+
+	ctrl = v4l2_ctrl_find(phy->sensor->ctrl_handler, V4L2_CID_PIXEL_RATE);
+	if (!ctrl) {
+		phy_err(phy, "no pixel rate control in subdev: %s\n",
+			phy->sensor->name);
+		return -EPIPE;
+	}
+
+	rate = v4l2_ctrl_g_ctrl_int64(ctrl);
+	phy_dbg(3, phy, "sensor Pixel Rate: %llu\n", rate);
+
+	return rate;
+}
+
+static void cal_camerarx_lane_config(struct cal_camerarx *phy)
+{
+	u32 val = cal_read(phy->cal, CAL_CSI2_COMPLEXIO_CFG(phy->instance));
+	u32 lane_mask = CAL_CSI2_COMPLEXIO_CFG_CLOCK_POSITION_MASK;
+	u32 polarity_mask = CAL_CSI2_COMPLEXIO_CFG_CLOCK_POL_MASK;
+	struct v4l2_fwnode_bus_mipi_csi2 *mipi_csi2 =
+		&phy->endpoint.bus.mipi_csi2;
+	int lane;
+
+	cal_set_field(&val, mipi_csi2->clock_lane + 1, lane_mask);
+	cal_set_field(&val, mipi_csi2->lane_polarities[0], polarity_mask);
+	for (lane = 0; lane < mipi_csi2->num_data_lanes; lane++) {
+		/*
+		 * Every lane are one nibble apart starting with the
+		 * clock followed by the data lanes so shift masks by 4.
+		 */
+		lane_mask <<= 4;
+		polarity_mask <<= 4;
+		cal_set_field(&val, mipi_csi2->data_lanes[lane] + 1, lane_mask);
+		cal_set_field(&val, mipi_csi2->lane_polarities[lane + 1],
+			      polarity_mask);
+	}
+
+	cal_write(phy->cal, CAL_CSI2_COMPLEXIO_CFG(phy->instance), val);
+	phy_dbg(3, phy, "CAL_CSI2_COMPLEXIO_CFG(%d) = 0x%08x\n",
+		phy->instance, val);
+}
+
+static void cal_camerarx_enable(struct cal_camerarx *phy)
+{
+	u32 num_lanes = phy->cal->data->camerarx[phy->instance].num_lanes;
+
+	regmap_field_write(phy->fields[F_CAMMODE], 0);
+	/* Always enable all lanes at the phy control level */
+	regmap_field_write(phy->fields[F_LANEENABLE], (1 << num_lanes) - 1);
+	/* F_CSI_MODE is not present on every architecture */
+	if (phy->fields[F_CSI_MODE])
+		regmap_field_write(phy->fields[F_CSI_MODE], 1);
+	regmap_field_write(phy->fields[F_CTRLCLKEN], 1);
+}
+
+void cal_camerarx_disable(struct cal_camerarx *phy)
+{
+	regmap_field_write(phy->fields[F_CTRLCLKEN], 0);
+}
+
+/*
+ * TCLK values are OK at their reset values
+ */
+#define TCLK_TERM	0
+#define TCLK_MISS	1
+#define TCLK_SETTLE	14
+
+static void cal_camerarx_config(struct cal_camerarx *phy, s64 external_rate,
+				const struct cal_fmt *fmt)
+{
+	unsigned int reg0, reg1;
+	unsigned int ths_term, ths_settle;
+	unsigned int csi2_ddrclk_khz;
+	struct v4l2_fwnode_bus_mipi_csi2 *mipi_csi2 =
+			&phy->endpoint.bus.mipi_csi2;
+	u32 num_lanes = mipi_csi2->num_data_lanes;
+
+	/* DPHY timing configuration */
+	/* CSI-2 is DDR and we only count used lanes. */
+	csi2_ddrclk_khz = external_rate / 1000
+		/ (2 * num_lanes) * fmt->bpp;
+	phy_dbg(1, phy, "csi2_ddrclk_khz: %d\n", csi2_ddrclk_khz);
+
+	/* THS_TERM: Programmed value = floor(20 ns/DDRClk period) */
+	ths_term = 20 * csi2_ddrclk_khz / 1000000;
+	phy_dbg(1, phy, "ths_term: %d (0x%02x)\n", ths_term, ths_term);
+
+	/* THS_SETTLE: Programmed value = floor(105 ns/DDRClk period) + 4 */
+	ths_settle = (105 * csi2_ddrclk_khz / 1000000) + 4;
+	phy_dbg(1, phy, "ths_settle: %d (0x%02x)\n", ths_settle, ths_settle);
+
+	reg0 = camerarx_read(phy, CAL_CSI2_PHY_REG0);
+	cal_set_field(&reg0, CAL_CSI2_PHY_REG0_HSCLOCKCONFIG_DISABLE,
+		      CAL_CSI2_PHY_REG0_HSCLOCKCONFIG_MASK);
+	cal_set_field(&reg0, ths_term, CAL_CSI2_PHY_REG0_THS_TERM_MASK);
+	cal_set_field(&reg0, ths_settle, CAL_CSI2_PHY_REG0_THS_SETTLE_MASK);
+
+	phy_dbg(1, phy, "CSI2_%d_REG0 = 0x%08x\n", phy->instance, reg0);
+	camerarx_write(phy, CAL_CSI2_PHY_REG0, reg0);
+
+	reg1 = camerarx_read(phy, CAL_CSI2_PHY_REG1);
+	cal_set_field(&reg1, TCLK_TERM, CAL_CSI2_PHY_REG1_TCLK_TERM_MASK);
+	cal_set_field(&reg1, 0xb8, CAL_CSI2_PHY_REG1_DPHY_HS_SYNC_PATTERN_MASK);
+	cal_set_field(&reg1, TCLK_MISS,
+		      CAL_CSI2_PHY_REG1_CTRLCLK_DIV_FACTOR_MASK);
+	cal_set_field(&reg1, TCLK_SETTLE, CAL_CSI2_PHY_REG1_TCLK_SETTLE_MASK);
+
+	phy_dbg(1, phy, "CSI2_%d_REG1 = 0x%08x\n", phy->instance, reg1);
+	camerarx_write(phy, CAL_CSI2_PHY_REG1, reg1);
+}
+
+static void cal_camerarx_power(struct cal_camerarx *phy, bool enable)
+{
+	u32 target_state;
+	unsigned int i;
+
+	target_state = enable ? CAL_CSI2_COMPLEXIO_CFG_PWR_CMD_STATE_ON :
+		       CAL_CSI2_COMPLEXIO_CFG_PWR_CMD_STATE_OFF;
+
+	cal_write_field(phy->cal, CAL_CSI2_COMPLEXIO_CFG(phy->instance),
+			target_state, CAL_CSI2_COMPLEXIO_CFG_PWR_CMD_MASK);
+
+	for (i = 0; i < 10; i++) {
+		u32 current_state;
+
+		current_state = cal_read_field(phy->cal,
+					       CAL_CSI2_COMPLEXIO_CFG(phy->instance),
+					       CAL_CSI2_COMPLEXIO_CFG_PWR_STATUS_MASK);
+
+		if (current_state == target_state)
+			break;
+
+		usleep_range(1000, 1100);
+	}
+
+	if (i == 10)
+		phy_err(phy, "Failed to power %s complexio\n",
+			enable ? "up" : "down");
+}
+
+static void cal_camerarx_wait_reset(struct cal_camerarx *phy)
+{
+	unsigned long timeout;
+
+	timeout = jiffies + msecs_to_jiffies(750);
+	while (time_before(jiffies, timeout)) {
+		if (cal_read_field(phy->cal,
+				   CAL_CSI2_COMPLEXIO_CFG(phy->instance),
+				   CAL_CSI2_COMPLEXIO_CFG_RESET_DONE_MASK) ==
+		    CAL_CSI2_COMPLEXIO_CFG_RESET_DONE_RESETCOMPLETED)
+			break;
+		usleep_range(500, 5000);
+	}
+
+	if (cal_read_field(phy->cal, CAL_CSI2_COMPLEXIO_CFG(phy->instance),
+			   CAL_CSI2_COMPLEXIO_CFG_RESET_DONE_MASK) !=
+			   CAL_CSI2_COMPLEXIO_CFG_RESET_DONE_RESETCOMPLETED)
+		phy_err(phy, "Timeout waiting for Complex IO reset done\n");
+}
+
+static void cal_camerarx_wait_stop_state(struct cal_camerarx *phy)
+{
+	unsigned long timeout;
+
+	timeout = jiffies + msecs_to_jiffies(750);
+	while (time_before(jiffies, timeout)) {
+		if (cal_read_field(phy->cal,
+				   CAL_CSI2_TIMING(phy->instance),
+				   CAL_CSI2_TIMING_FORCE_RX_MODE_IO1_MASK) == 0)
+			break;
+		usleep_range(500, 5000);
+	}
+
+	if (cal_read_field(phy->cal, CAL_CSI2_TIMING(phy->instance),
+			   CAL_CSI2_TIMING_FORCE_RX_MODE_IO1_MASK) != 0)
+		phy_err(phy, "Timeout waiting for stop state\n");
+}
+
+int cal_camerarx_start(struct cal_camerarx *phy, const struct cal_fmt *fmt)
+{
+	s64 external_rate;
+	u32 sscounter;
+	u32 val;
+	int ret;
+
+	external_rate = cal_camerarx_get_external_rate(phy);
+	if (external_rate < 0)
+		return external_rate;
+
+	ret = v4l2_subdev_call(phy->sensor, core, s_power, 1);
+	if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV) {
+		phy_err(phy, "power on failed in subdev\n");
+		return ret;
+	}
+
+	/*
+	 * CSI-2 PHY Link Initialization Sequence, according to the DRA74xP /
+	 * DRA75xP / DRA76xP / DRA77xP TRM. The DRA71x / DRA72x and the AM65x /
+	 * DRA80xM TRMs have a a slightly simplified sequence.
+	 */
+
+	/*
+	 * 1. Configure all CSI-2 low level protocol registers to be ready to
+	 *    receive signals/data from the CSI-2 PHY.
+	 *
+	 *    i.-v. Configure the lanes position and polarity.
+	 */
+	cal_camerarx_lane_config(phy);
+
+	/*
+	 *    vi.-vii. Configure D-PHY mode, enable the required lanes and
+	 *             enable the CAMERARX clock.
+	 */
+	cal_camerarx_enable(phy);
+
+	/*
+	 * 2. CSI PHY and link initialization sequence.
+	 *
+	 *    a. Deassert the CSI-2 PHY reset. Do not wait for reset completion
+	 *       at this point, as it requires the external sensor to send the
+	 *       CSI-2 HS clock.
+	 */
+	cal_write_field(phy->cal, CAL_CSI2_COMPLEXIO_CFG(phy->instance),
+			CAL_CSI2_COMPLEXIO_CFG_RESET_CTRL_OPERATIONAL,
+			CAL_CSI2_COMPLEXIO_CFG_RESET_CTRL_MASK);
+	phy_dbg(3, phy, "CAL_CSI2_COMPLEXIO_CFG(%d) = 0x%08x De-assert Complex IO Reset\n",
+		phy->instance,
+		cal_read(phy->cal, CAL_CSI2_COMPLEXIO_CFG(phy->instance)));
+
+	/* Dummy read to allow SCP reset to complete. */
+	camerarx_read(phy, CAL_CSI2_PHY_REG0);
+
+	/* Program the PHY timing parameters. */
+	cal_camerarx_config(phy, external_rate, fmt);
+
+	/*
+	 *    b. Assert the FORCERXMODE signal.
+	 *
+	 * The stop-state-counter is based on fclk cycles, and we always use
+	 * the x16 and x4 settings, so stop-state-timeout =
+	 * fclk-cycle * 16 * 4 * counter.
+	 *
+	 * Stop-state-timeout must be more than 100us as per CSI-2 spec, so we
+	 * calculate a timeout that's 100us (rounding up).
+	 */
+	sscounter = DIV_ROUND_UP(clk_get_rate(phy->cal->fclk), 10000 *  16 * 4);
+
+	val = cal_read(phy->cal, CAL_CSI2_TIMING(phy->instance));
+	cal_set_field(&val, 1, CAL_CSI2_TIMING_STOP_STATE_X16_IO1_MASK);
+	cal_set_field(&val, 1, CAL_CSI2_TIMING_STOP_STATE_X4_IO1_MASK);
+	cal_set_field(&val, sscounter,
+		      CAL_CSI2_TIMING_STOP_STATE_COUNTER_IO1_MASK);
+	cal_write(phy->cal, CAL_CSI2_TIMING(phy->instance), val);
+	phy_dbg(3, phy, "CAL_CSI2_TIMING(%d) = 0x%08x Stop States\n",
+		phy->instance,
+		cal_read(phy->cal, CAL_CSI2_TIMING(phy->instance)));
+
+	/* Assert the FORCERXMODE signal. */
+	cal_write_field(phy->cal, CAL_CSI2_TIMING(phy->instance),
+			1, CAL_CSI2_TIMING_FORCE_RX_MODE_IO1_MASK);
+	phy_dbg(3, phy, "CAL_CSI2_TIMING(%d) = 0x%08x Force RXMODE\n",
+		phy->instance,
+		cal_read(phy->cal, CAL_CSI2_TIMING(phy->instance)));
+
+	/*
+	 * c. Connect pull-down on CSI-2 PHY link (using pad control).
+	 *
+	 * This is not required on DRA71x, DRA72x, AM65x and DRA80xM. Not
+	 * implemented.
+	 */
+
+	/*
+	 * d. Power up the CSI-2 PHY.
+	 * e. Check whether the state status reaches the ON state.
+	 */
+	cal_camerarx_power(phy, true);
+
+	/*
+	 * Start the sensor to enable the CSI-2 HS clock. We can now wait for
+	 * CSI-2 PHY reset to complete.
+	 */
+	ret = v4l2_subdev_call(phy->sensor, video, s_stream, 1);
+	if (ret) {
+		v4l2_subdev_call(phy->sensor, core, s_power, 0);
+		phy_err(phy, "stream on failed in subdev\n");
+		return ret;
+	}
+
+	cal_camerarx_wait_reset(phy);
+
+	/* f. Wait for STOPSTATE=1 for all enabled lane modules. */
+	cal_camerarx_wait_stop_state(phy);
+
+	phy_dbg(1, phy, "CSI2_%u_REG1 = 0x%08x (bits 31-28 should be set)\n",
+		phy->instance, camerarx_read(phy, CAL_CSI2_PHY_REG1));
+
+	/*
+	 * g. Disable pull-down on CSI-2 PHY link (using pad control).
+	 *
+	 * This is not required on DRA71x, DRA72x, AM65x and DRA80xM. Not
+	 * implemented.
+	 */
+
+	return 0;
+}
+
+void cal_camerarx_stop(struct cal_camerarx *phy)
+{
+	unsigned int i;
+	int ret;
+
+	cal_camerarx_power(phy, false);
+
+	/* Assert Complex IO Reset */
+	cal_write_field(phy->cal, CAL_CSI2_COMPLEXIO_CFG(phy->instance),
+			CAL_CSI2_COMPLEXIO_CFG_RESET_CTRL,
+			CAL_CSI2_COMPLEXIO_CFG_RESET_CTRL_MASK);
+
+	/* Wait for power down completion */
+	for (i = 0; i < 10; i++) {
+		if (cal_read_field(phy->cal,
+				   CAL_CSI2_COMPLEXIO_CFG(phy->instance),
+				   CAL_CSI2_COMPLEXIO_CFG_RESET_DONE_MASK) ==
+		    CAL_CSI2_COMPLEXIO_CFG_RESET_DONE_RESETONGOING)
+			break;
+		usleep_range(1000, 1100);
+	}
+	phy_dbg(3, phy, "CAL_CSI2_COMPLEXIO_CFG(%d) = 0x%08x Complex IO in Reset (%d) %s\n",
+		phy->instance,
+		cal_read(phy->cal, CAL_CSI2_COMPLEXIO_CFG(phy->instance)), i,
+		(i >= 10) ? "(timeout)" : "");
+
+	/* Disable the phy */
+	cal_camerarx_disable(phy);
+
+	if (v4l2_subdev_call(phy->sensor, video, s_stream, 0))
+		phy_err(phy, "stream off failed in subdev\n");
+
+	ret = v4l2_subdev_call(phy->sensor, core, s_power, 0);
+	if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV)
+		phy_err(phy, "power off failed in subdev\n");
+}
+
+/*
+ *   Errata i913: CSI2 LDO Needs to be disabled when module is powered on
+ *
+ *   Enabling CSI2 LDO shorts it to core supply. It is crucial the 2 CSI2
+ *   LDOs on the device are disabled if CSI-2 module is powered on
+ *   (0x4845 B304 | 0x4845 B384 [28:27] = 0x1) or in ULPS (0x4845 B304
+ *   | 0x4845 B384 [28:27] = 0x2) mode. Common concerns include: high
+ *   current draw on the module supply in active mode.
+ *
+ *   Errata does not apply when CSI-2 module is powered off
+ *   (0x4845 B304 | 0x4845 B384 [28:27] = 0x0).
+ *
+ * SW Workaround:
+ *	Set the following register bits to disable the LDO,
+ *	which is essentially CSI2 REG10 bit 6:
+ *
+ *		Core 0:  0x4845 B828 = 0x0000 0040
+ *		Core 1:  0x4845 B928 = 0x0000 0040
+ */
+void cal_camerarx_i913_errata(struct cal_camerarx *phy)
+{
+	u32 reg10 = camerarx_read(phy, CAL_CSI2_PHY_REG10);
+
+	cal_set_field(&reg10, 1, CAL_CSI2_PHY_REG10_I933_LDO_DISABLE_MASK);
+
+	phy_dbg(1, phy, "CSI2_%d_REG10 = 0x%08x\n", phy->instance, reg10);
+	camerarx_write(phy, CAL_CSI2_PHY_REG10, reg10);
+}
+
+/*
+ * Enable the expected IRQ sources
+ */
+void cal_camerarx_enable_irqs(struct cal_camerarx *phy)
+{
+	u32 val;
+
+	const u32 cio_err_mask =
+		CAL_CSI2_COMPLEXIO_IRQ_LANE_ERRORS_MASK |
+		CAL_CSI2_COMPLEXIO_IRQ_FIFO_OVR_MASK |
+		CAL_CSI2_COMPLEXIO_IRQ_SHORT_PACKET_MASK |
+		CAL_CSI2_COMPLEXIO_IRQ_ECC_NO_CORRECTION_MASK;
+
+	/* Enable CIO error irqs */
+	cal_write(phy->cal, CAL_HL_IRQENABLE_SET(0),
+		  CAL_HL_IRQ_CIO_MASK(phy->instance));
+	cal_write(phy->cal, CAL_CSI2_COMPLEXIO_IRQENABLE(phy->instance),
+		  cio_err_mask);
+
+	/* Always enable OCPO error */
+	cal_write(phy->cal, CAL_HL_IRQENABLE_SET(0), CAL_HL_IRQ_OCPO_ERR_MASK);
+
+	/* Enable IRQ_WDMA_END 0/1 */
+	val = 0;
+	cal_set_field(&val, 1, CAL_HL_IRQ_MASK(phy->instance));
+	cal_write(phy->cal, CAL_HL_IRQENABLE_SET(1), val);
+	/* Enable IRQ_WDMA_START 0/1 */
+	val = 0;
+	cal_set_field(&val, 1, CAL_HL_IRQ_MASK(phy->instance));
+	cal_write(phy->cal, CAL_HL_IRQENABLE_SET(2), val);
+	/* Todo: Add VC_IRQ and CSI2_COMPLEXIO_IRQ handling */
+	cal_write(phy->cal, CAL_CSI2_VC_IRQENABLE(0), 0xFF000000);
+}
+
+void cal_camerarx_disable_irqs(struct cal_camerarx *phy)
+{
+	u32 val;
+
+	/* Disable CIO error irqs */
+	cal_write(phy->cal, CAL_HL_IRQENABLE_CLR(0),
+		  CAL_HL_IRQ_CIO_MASK(phy->instance));
+	cal_write(phy->cal, CAL_CSI2_COMPLEXIO_IRQENABLE(phy->instance), 0);
+
+	/* Disable IRQ_WDMA_END 0/1 */
+	val = 0;
+	cal_set_field(&val, 1, CAL_HL_IRQ_MASK(phy->instance));
+	cal_write(phy->cal, CAL_HL_IRQENABLE_CLR(1), val);
+	/* Disable IRQ_WDMA_START 0/1 */
+	val = 0;
+	cal_set_field(&val, 1, CAL_HL_IRQ_MASK(phy->instance));
+	cal_write(phy->cal, CAL_HL_IRQENABLE_CLR(2), val);
+	/* Todo: Add VC_IRQ and CSI2_COMPLEXIO_IRQ handling */
+	cal_write(phy->cal, CAL_CSI2_VC_IRQENABLE(0), 0);
+}
+
+void cal_camerarx_ppi_enable(struct cal_camerarx *phy)
+{
+	cal_write(phy->cal, CAL_CSI2_PPI_CTRL(phy->instance), BIT(3));
+	cal_write_field(phy->cal, CAL_CSI2_PPI_CTRL(phy->instance),
+			1, CAL_CSI2_PPI_CTRL_IF_EN_MASK);
+}
+
+void cal_camerarx_ppi_disable(struct cal_camerarx *phy)
+{
+	cal_write_field(phy->cal, CAL_CSI2_PPI_CTRL(phy->instance),
+			0, CAL_CSI2_PPI_CTRL_IF_EN_MASK);
+}
+
+static int cal_camerarx_regmap_init(struct cal_dev *cal,
+				    struct cal_camerarx *phy)
+{
+	const struct cal_camerarx_data *phy_data;
+	unsigned int i;
+
+	if (!cal->data)
+		return -EINVAL;
+
+	phy_data = &cal->data->camerarx[phy->instance];
+
+	for (i = 0; i < F_MAX_FIELDS; i++) {
+		struct reg_field field = {
+			.reg = cal->syscon_camerrx_offset,
+			.lsb = phy_data->fields[i].lsb,
+			.msb = phy_data->fields[i].msb,
+		};
+
+		/*
+		 * Here we update the reg offset with the
+		 * value found in DT
+		 */
+		phy->fields[i] = devm_regmap_field_alloc(cal->dev,
+							 cal->syscon_camerrx,
+							 field);
+		if (IS_ERR(phy->fields[i])) {
+			cal_err(cal, "Unable to allocate regmap fields\n");
+			return PTR_ERR(phy->fields[i]);
+		}
+	}
+
+	return 0;
+}
+
+static int cal_camerarx_parse_dt(struct cal_camerarx *phy)
+{
+	struct v4l2_fwnode_endpoint *endpoint = &phy->endpoint;
+	struct device_node *ep_node;
+	char data_lanes[V4L2_FWNODE_CSI2_MAX_DATA_LANES * 2];
+	unsigned int i;
+	int ret;
+
+	/*
+	 * Find the endpoint node for the port corresponding to the PHY
+	 * instance, and parse its CSI-2-related properties.
+	 */
+	ep_node = of_graph_get_endpoint_by_regs(phy->cal->dev->of_node,
+						phy->instance, 0);
+	if (!ep_node) {
+		phy_dbg(3, phy, "Can't get endpoint\n");
+		return -EINVAL;
+	}
+
+	endpoint->bus_type = V4L2_MBUS_CSI2_DPHY;
+	ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep_node), endpoint);
+	if (ret < 0) {
+		phy_err(phy, "Failed to parse endpoint\n");
+		goto done;
+	}
+
+	for (i = 0; i < endpoint->bus.mipi_csi2.num_data_lanes; i++) {
+		unsigned int lane = endpoint->bus.mipi_csi2.data_lanes[i];
+
+		if (lane > 4) {
+			phy_err(phy, "Invalid position %u for data lane %u\n",
+				lane, i);
+			ret = -EINVAL;
+			goto done;
+		}
+
+		data_lanes[i*2] = '0' + lane;
+		data_lanes[i*2+1] = ' ';
+	}
+
+	data_lanes[i*2-1] = '\0';
+
+	phy_dbg(3, phy,
+		"CSI-2 bus: clock lane <%u>, data lanes <%s>, flags 0x%08x\n",
+		endpoint->bus.mipi_csi2.clock_lane, data_lanes,
+		endpoint->bus.mipi_csi2.flags);
+
+	/* Retrieve the connected device and store it for later use. */
+	phy->sensor_node = of_graph_get_remote_port_parent(ep_node);
+	if (!phy->sensor_node) {
+		phy_dbg(3, phy, "Can't get remote parent\n");
+		goto done;
+	}
+
+	phy_dbg(1, phy, "Found connected device %pOFn\n", phy->sensor_node);
+
+done:
+	of_node_put(ep_node);
+	return ret;
+}
+
+struct cal_camerarx *cal_camerarx_create(struct cal_dev *cal,
+					 unsigned int instance)
+{
+	struct platform_device *pdev = to_platform_device(cal->dev);
+	struct cal_camerarx *phy;
+	int ret;
+
+	phy = kzalloc(sizeof(*phy), GFP_KERNEL);
+	if (!phy)
+		return ERR_PTR(-ENOMEM);
+
+	phy->cal = cal;
+	phy->instance = instance;
+
+	phy->res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+						(instance == 0) ?
+						"cal_rx_core0" :
+						"cal_rx_core1");
+	phy->base = devm_ioremap_resource(cal->dev, phy->res);
+	if (IS_ERR(phy->base)) {
+		cal_err(cal, "failed to ioremap\n");
+		ret = PTR_ERR(phy->base);
+		goto error;
+	}
+
+	cal_dbg(1, cal, "ioresource %s at %pa - %pa\n",
+		phy->res->name, &phy->res->start, &phy->res->end);
+
+	ret = cal_camerarx_regmap_init(cal, phy);
+	if (ret)
+		goto error;
+
+	ret = cal_camerarx_parse_dt(phy);
+	if (ret)
+		goto error;
+
+	return phy;
+
+error:
+	kfree(phy);
+	return ERR_PTR(ret);
+}
+
+void cal_camerarx_destroy(struct cal_camerarx *phy)
+{
+	if (!phy)
+		return;
+
+	of_node_put(phy->sensor_node);
+	kfree(phy);
+}
diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index abeded3b5e6c..ca8576aa2646 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -10,12 +10,10 @@
  */
 
 #include <linux/clk.h>
-#include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/mfd/syscon.h>
 #include <linux/module.h>
 #include <linux/of_device.h>
-#include <linux/of_graph.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/regmap.h>
@@ -25,9 +23,7 @@
 #include <media/media-device.h>
 #include <media/v4l2-async.h>
 #include <media/v4l2-common.h>
-#include <media/v4l2-ctrls.h>
 #include <media/v4l2-device.h>
-#include <media/v4l2-fwnode.h>
 #include <media/videobuf2-core.h>
 #include <media/videobuf2-dma-contig.h>
 
@@ -155,670 +151,6 @@ void cal_quickdump_regs(struct cal_dev *cal)
 	}
 }
 
-/* ------------------------------------------------------------------
- *	CAMERARX Management
- * ------------------------------------------------------------------
- */
-
-static inline u32 camerarx_read(struct cal_camerarx *phy, u32 offset)
-{
-	return ioread32(phy->base + offset);
-}
-
-static inline void camerarx_write(struct cal_camerarx *phy, u32 offset, u32 val)
-{
-	iowrite32(val, phy->base + offset);
-}
-
-static s64 cal_camerarx_get_external_rate(struct cal_camerarx *phy)
-{
-	struct v4l2_ctrl *ctrl;
-	s64 rate;
-
-	ctrl = v4l2_ctrl_find(phy->sensor->ctrl_handler, V4L2_CID_PIXEL_RATE);
-	if (!ctrl) {
-		phy_err(phy, "no pixel rate control in subdev: %s\n",
-			phy->sensor->name);
-		return -EPIPE;
-	}
-
-	rate = v4l2_ctrl_g_ctrl_int64(ctrl);
-	phy_dbg(3, phy, "sensor Pixel Rate: %llu\n", rate);
-
-	return rate;
-}
-
-static void cal_camerarx_lane_config(struct cal_camerarx *phy)
-{
-	u32 val = cal_read(phy->cal, CAL_CSI2_COMPLEXIO_CFG(phy->instance));
-	u32 lane_mask = CAL_CSI2_COMPLEXIO_CFG_CLOCK_POSITION_MASK;
-	u32 polarity_mask = CAL_CSI2_COMPLEXIO_CFG_CLOCK_POL_MASK;
-	struct v4l2_fwnode_bus_mipi_csi2 *mipi_csi2 =
-		&phy->endpoint.bus.mipi_csi2;
-	int lane;
-
-	cal_set_field(&val, mipi_csi2->clock_lane + 1, lane_mask);
-	cal_set_field(&val, mipi_csi2->lane_polarities[0], polarity_mask);
-	for (lane = 0; lane < mipi_csi2->num_data_lanes; lane++) {
-		/*
-		 * Every lane are one nibble apart starting with the
-		 * clock followed by the data lanes so shift masks by 4.
-		 */
-		lane_mask <<= 4;
-		polarity_mask <<= 4;
-		cal_set_field(&val, mipi_csi2->data_lanes[lane] + 1, lane_mask);
-		cal_set_field(&val, mipi_csi2->lane_polarities[lane + 1],
-			      polarity_mask);
-	}
-
-	cal_write(phy->cal, CAL_CSI2_COMPLEXIO_CFG(phy->instance), val);
-	phy_dbg(3, phy, "CAL_CSI2_COMPLEXIO_CFG(%d) = 0x%08x\n",
-		phy->instance, val);
-}
-
-static void cal_camerarx_enable(struct cal_camerarx *phy)
-{
-	u32 num_lanes = phy->cal->data->camerarx[phy->instance].num_lanes;
-
-	regmap_field_write(phy->fields[F_CAMMODE], 0);
-	/* Always enable all lanes at the phy control level */
-	regmap_field_write(phy->fields[F_LANEENABLE], (1 << num_lanes) - 1);
-	/* F_CSI_MODE is not present on every architecture */
-	if (phy->fields[F_CSI_MODE])
-		regmap_field_write(phy->fields[F_CSI_MODE], 1);
-	regmap_field_write(phy->fields[F_CTRLCLKEN], 1);
-}
-
-static void cal_camerarx_disable(struct cal_camerarx *phy)
-{
-	regmap_field_write(phy->fields[F_CTRLCLKEN], 0);
-}
-
-/*
- * TCLK values are OK at their reset values
- */
-#define TCLK_TERM	0
-#define TCLK_MISS	1
-#define TCLK_SETTLE	14
-
-static void cal_camerarx_config(struct cal_camerarx *phy, s64 external_rate,
-				const struct cal_fmt *fmt)
-{
-	unsigned int reg0, reg1;
-	unsigned int ths_term, ths_settle;
-	unsigned int csi2_ddrclk_khz;
-	struct v4l2_fwnode_bus_mipi_csi2 *mipi_csi2 =
-			&phy->endpoint.bus.mipi_csi2;
-	u32 num_lanes = mipi_csi2->num_data_lanes;
-
-	/* DPHY timing configuration */
-	/* CSI-2 is DDR and we only count used lanes. */
-	csi2_ddrclk_khz = external_rate / 1000
-		/ (2 * num_lanes) * fmt->bpp;
-	phy_dbg(1, phy, "csi2_ddrclk_khz: %d\n", csi2_ddrclk_khz);
-
-	/* THS_TERM: Programmed value = floor(20 ns/DDRClk period) */
-	ths_term = 20 * csi2_ddrclk_khz / 1000000;
-	phy_dbg(1, phy, "ths_term: %d (0x%02x)\n", ths_term, ths_term);
-
-	/* THS_SETTLE: Programmed value = floor(105 ns/DDRClk period) + 4 */
-	ths_settle = (105 * csi2_ddrclk_khz / 1000000) + 4;
-	phy_dbg(1, phy, "ths_settle: %d (0x%02x)\n", ths_settle, ths_settle);
-
-	reg0 = camerarx_read(phy, CAL_CSI2_PHY_REG0);
-	cal_set_field(&reg0, CAL_CSI2_PHY_REG0_HSCLOCKCONFIG_DISABLE,
-		      CAL_CSI2_PHY_REG0_HSCLOCKCONFIG_MASK);
-	cal_set_field(&reg0, ths_term, CAL_CSI2_PHY_REG0_THS_TERM_MASK);
-	cal_set_field(&reg0, ths_settle, CAL_CSI2_PHY_REG0_THS_SETTLE_MASK);
-
-	phy_dbg(1, phy, "CSI2_%d_REG0 = 0x%08x\n", phy->instance, reg0);
-	camerarx_write(phy, CAL_CSI2_PHY_REG0, reg0);
-
-	reg1 = camerarx_read(phy, CAL_CSI2_PHY_REG1);
-	cal_set_field(&reg1, TCLK_TERM, CAL_CSI2_PHY_REG1_TCLK_TERM_MASK);
-	cal_set_field(&reg1, 0xb8, CAL_CSI2_PHY_REG1_DPHY_HS_SYNC_PATTERN_MASK);
-	cal_set_field(&reg1, TCLK_MISS,
-		      CAL_CSI2_PHY_REG1_CTRLCLK_DIV_FACTOR_MASK);
-	cal_set_field(&reg1, TCLK_SETTLE, CAL_CSI2_PHY_REG1_TCLK_SETTLE_MASK);
-
-	phy_dbg(1, phy, "CSI2_%d_REG1 = 0x%08x\n", phy->instance, reg1);
-	camerarx_write(phy, CAL_CSI2_PHY_REG1, reg1);
-}
-
-static void cal_camerarx_power(struct cal_camerarx *phy, bool enable)
-{
-	u32 target_state;
-	unsigned int i;
-
-	target_state = enable ? CAL_CSI2_COMPLEXIO_CFG_PWR_CMD_STATE_ON :
-		       CAL_CSI2_COMPLEXIO_CFG_PWR_CMD_STATE_OFF;
-
-	cal_write_field(phy->cal, CAL_CSI2_COMPLEXIO_CFG(phy->instance),
-			target_state, CAL_CSI2_COMPLEXIO_CFG_PWR_CMD_MASK);
-
-	for (i = 0; i < 10; i++) {
-		u32 current_state;
-
-		current_state = cal_read_field(phy->cal,
-					       CAL_CSI2_COMPLEXIO_CFG(phy->instance),
-					       CAL_CSI2_COMPLEXIO_CFG_PWR_STATUS_MASK);
-
-		if (current_state == target_state)
-			break;
-
-		usleep_range(1000, 1100);
-	}
-
-	if (i == 10)
-		phy_err(phy, "Failed to power %s complexio\n",
-			enable ? "up" : "down");
-}
-
-static void cal_camerarx_wait_reset(struct cal_camerarx *phy)
-{
-	unsigned long timeout;
-
-	timeout = jiffies + msecs_to_jiffies(750);
-	while (time_before(jiffies, timeout)) {
-		if (cal_read_field(phy->cal,
-				   CAL_CSI2_COMPLEXIO_CFG(phy->instance),
-				   CAL_CSI2_COMPLEXIO_CFG_RESET_DONE_MASK) ==
-		    CAL_CSI2_COMPLEXIO_CFG_RESET_DONE_RESETCOMPLETED)
-			break;
-		usleep_range(500, 5000);
-	}
-
-	if (cal_read_field(phy->cal, CAL_CSI2_COMPLEXIO_CFG(phy->instance),
-			   CAL_CSI2_COMPLEXIO_CFG_RESET_DONE_MASK) !=
-			   CAL_CSI2_COMPLEXIO_CFG_RESET_DONE_RESETCOMPLETED)
-		phy_err(phy, "Timeout waiting for Complex IO reset done\n");
-}
-
-static void cal_camerarx_wait_stop_state(struct cal_camerarx *phy)
-{
-	unsigned long timeout;
-
-	timeout = jiffies + msecs_to_jiffies(750);
-	while (time_before(jiffies, timeout)) {
-		if (cal_read_field(phy->cal,
-				   CAL_CSI2_TIMING(phy->instance),
-				   CAL_CSI2_TIMING_FORCE_RX_MODE_IO1_MASK) == 0)
-			break;
-		usleep_range(500, 5000);
-	}
-
-	if (cal_read_field(phy->cal, CAL_CSI2_TIMING(phy->instance),
-			   CAL_CSI2_TIMING_FORCE_RX_MODE_IO1_MASK) != 0)
-		phy_err(phy, "Timeout waiting for stop state\n");
-}
-
-int cal_camerarx_start(struct cal_camerarx *phy, const struct cal_fmt *fmt)
-{
-	s64 external_rate;
-	u32 sscounter;
-	u32 val;
-	int ret;
-
-	external_rate = cal_camerarx_get_external_rate(phy);
-	if (external_rate < 0)
-		return external_rate;
-
-	ret = v4l2_subdev_call(phy->sensor, core, s_power, 1);
-	if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV) {
-		phy_err(phy, "power on failed in subdev\n");
-		return ret;
-	}
-
-	/*
-	 * CSI-2 PHY Link Initialization Sequence, according to the DRA74xP /
-	 * DRA75xP / DRA76xP / DRA77xP TRM. The DRA71x / DRA72x and the AM65x /
-	 * DRA80xM TRMs have a a slightly simplified sequence.
-	 */
-
-	/*
-	 * 1. Configure all CSI-2 low level protocol registers to be ready to
-	 *    receive signals/data from the CSI-2 PHY.
-	 *
-	 *    i.-v. Configure the lanes position and polarity.
-	 */
-	cal_camerarx_lane_config(phy);
-
-	/*
-	 *    vi.-vii. Configure D-PHY mode, enable the required lanes and
-	 *             enable the CAMERARX clock.
-	 */
-	cal_camerarx_enable(phy);
-
-	/*
-	 * 2. CSI PHY and link initialization sequence.
-	 *
-	 *    a. Deassert the CSI-2 PHY reset. Do not wait for reset completion
-	 *       at this point, as it requires the external sensor to send the
-	 *       CSI-2 HS clock.
-	 */
-	cal_write_field(phy->cal, CAL_CSI2_COMPLEXIO_CFG(phy->instance),
-			CAL_CSI2_COMPLEXIO_CFG_RESET_CTRL_OPERATIONAL,
-			CAL_CSI2_COMPLEXIO_CFG_RESET_CTRL_MASK);
-	phy_dbg(3, phy, "CAL_CSI2_COMPLEXIO_CFG(%d) = 0x%08x De-assert Complex IO Reset\n",
-		phy->instance,
-		cal_read(phy->cal, CAL_CSI2_COMPLEXIO_CFG(phy->instance)));
-
-	/* Dummy read to allow SCP reset to complete. */
-	camerarx_read(phy, CAL_CSI2_PHY_REG0);
-
-	/* Program the PHY timing parameters. */
-	cal_camerarx_config(phy, external_rate, fmt);
-
-	/*
-	 *    b. Assert the FORCERXMODE signal.
-	 *
-	 * The stop-state-counter is based on fclk cycles, and we always use
-	 * the x16 and x4 settings, so stop-state-timeout =
-	 * fclk-cycle * 16 * 4 * counter.
-	 *
-	 * Stop-state-timeout must be more than 100us as per CSI-2 spec, so we
-	 * calculate a timeout that's 100us (rounding up).
-	 */
-	sscounter = DIV_ROUND_UP(clk_get_rate(phy->cal->fclk), 10000 *  16 * 4);
-
-	val = cal_read(phy->cal, CAL_CSI2_TIMING(phy->instance));
-	cal_set_field(&val, 1, CAL_CSI2_TIMING_STOP_STATE_X16_IO1_MASK);
-	cal_set_field(&val, 1, CAL_CSI2_TIMING_STOP_STATE_X4_IO1_MASK);
-	cal_set_field(&val, sscounter,
-		      CAL_CSI2_TIMING_STOP_STATE_COUNTER_IO1_MASK);
-	cal_write(phy->cal, CAL_CSI2_TIMING(phy->instance), val);
-	phy_dbg(3, phy, "CAL_CSI2_TIMING(%d) = 0x%08x Stop States\n",
-		phy->instance,
-		cal_read(phy->cal, CAL_CSI2_TIMING(phy->instance)));
-
-	/* Assert the FORCERXMODE signal. */
-	cal_write_field(phy->cal, CAL_CSI2_TIMING(phy->instance),
-			1, CAL_CSI2_TIMING_FORCE_RX_MODE_IO1_MASK);
-	phy_dbg(3, phy, "CAL_CSI2_TIMING(%d) = 0x%08x Force RXMODE\n",
-		phy->instance,
-		cal_read(phy->cal, CAL_CSI2_TIMING(phy->instance)));
-
-	/*
-	 * c. Connect pull-down on CSI-2 PHY link (using pad control).
-	 *
-	 * This is not required on DRA71x, DRA72x, AM65x and DRA80xM. Not
-	 * implemented.
-	 */
-
-	/*
-	 * d. Power up the CSI-2 PHY.
-	 * e. Check whether the state status reaches the ON state.
-	 */
-	cal_camerarx_power(phy, true);
-
-	/*
-	 * Start the sensor to enable the CSI-2 HS clock. We can now wait for
-	 * CSI-2 PHY reset to complete.
-	 */
-	ret = v4l2_subdev_call(phy->sensor, video, s_stream, 1);
-	if (ret) {
-		v4l2_subdev_call(phy->sensor, core, s_power, 0);
-		phy_err(phy, "stream on failed in subdev\n");
-		return ret;
-	}
-
-	cal_camerarx_wait_reset(phy);
-
-	/* f. Wait for STOPSTATE=1 for all enabled lane modules. */
-	cal_camerarx_wait_stop_state(phy);
-
-	phy_dbg(1, phy, "CSI2_%u_REG1 = 0x%08x (bits 31-28 should be set)\n",
-		phy->instance, camerarx_read(phy, CAL_CSI2_PHY_REG1));
-
-	/*
-	 * g. Disable pull-down on CSI-2 PHY link (using pad control).
-	 *
-	 * This is not required on DRA71x, DRA72x, AM65x and DRA80xM. Not
-	 * implemented.
-	 */
-
-	return 0;
-}
-
-void cal_camerarx_stop(struct cal_camerarx *phy)
-{
-	unsigned int i;
-	int ret;
-
-	cal_camerarx_power(phy, false);
-
-	/* Assert Complex IO Reset */
-	cal_write_field(phy->cal, CAL_CSI2_COMPLEXIO_CFG(phy->instance),
-			CAL_CSI2_COMPLEXIO_CFG_RESET_CTRL,
-			CAL_CSI2_COMPLEXIO_CFG_RESET_CTRL_MASK);
-
-	/* Wait for power down completion */
-	for (i = 0; i < 10; i++) {
-		if (cal_read_field(phy->cal,
-				   CAL_CSI2_COMPLEXIO_CFG(phy->instance),
-				   CAL_CSI2_COMPLEXIO_CFG_RESET_DONE_MASK) ==
-		    CAL_CSI2_COMPLEXIO_CFG_RESET_DONE_RESETONGOING)
-			break;
-		usleep_range(1000, 1100);
-	}
-	phy_dbg(3, phy, "CAL_CSI2_COMPLEXIO_CFG(%d) = 0x%08x Complex IO in Reset (%d) %s\n",
-		phy->instance,
-		cal_read(phy->cal, CAL_CSI2_COMPLEXIO_CFG(phy->instance)), i,
-		(i >= 10) ? "(timeout)" : "");
-
-	/* Disable the phy */
-	cal_camerarx_disable(phy);
-
-	if (v4l2_subdev_call(phy->sensor, video, s_stream, 0))
-		phy_err(phy, "stream off failed in subdev\n");
-
-	ret = v4l2_subdev_call(phy->sensor, core, s_power, 0);
-	if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV)
-		phy_err(phy, "power off failed in subdev\n");
-}
-
-/*
- *   Errata i913: CSI2 LDO Needs to be disabled when module is powered on
- *
- *   Enabling CSI2 LDO shorts it to core supply. It is crucial the 2 CSI2
- *   LDOs on the device are disabled if CSI-2 module is powered on
- *   (0x4845 B304 | 0x4845 B384 [28:27] = 0x1) or in ULPS (0x4845 B304
- *   | 0x4845 B384 [28:27] = 0x2) mode. Common concerns include: high
- *   current draw on the module supply in active mode.
- *
- *   Errata does not apply when CSI-2 module is powered off
- *   (0x4845 B304 | 0x4845 B384 [28:27] = 0x0).
- *
- * SW Workaround:
- *	Set the following register bits to disable the LDO,
- *	which is essentially CSI2 REG10 bit 6:
- *
- *		Core 0:  0x4845 B828 = 0x0000 0040
- *		Core 1:  0x4845 B928 = 0x0000 0040
- */
-static void cal_camerarx_i913_errata(struct cal_camerarx *phy)
-{
-	u32 reg10 = camerarx_read(phy, CAL_CSI2_PHY_REG10);
-
-	cal_set_field(&reg10, 1, CAL_CSI2_PHY_REG10_I933_LDO_DISABLE_MASK);
-
-	phy_dbg(1, phy, "CSI2_%d_REG10 = 0x%08x\n", phy->instance, reg10);
-	camerarx_write(phy, CAL_CSI2_PHY_REG10, reg10);
-}
-
-/*
- * Enable the expected IRQ sources
- */
-void cal_camerarx_enable_irqs(struct cal_camerarx *phy)
-{
-	u32 val;
-
-	const u32 cio_err_mask =
-		CAL_CSI2_COMPLEXIO_IRQ_LANE_ERRORS_MASK |
-		CAL_CSI2_COMPLEXIO_IRQ_FIFO_OVR_MASK |
-		CAL_CSI2_COMPLEXIO_IRQ_SHORT_PACKET_MASK |
-		CAL_CSI2_COMPLEXIO_IRQ_ECC_NO_CORRECTION_MASK;
-
-	/* Enable CIO error irqs */
-	cal_write(phy->cal, CAL_HL_IRQENABLE_SET(0),
-		  CAL_HL_IRQ_CIO_MASK(phy->instance));
-	cal_write(phy->cal, CAL_CSI2_COMPLEXIO_IRQENABLE(phy->instance),
-		  cio_err_mask);
-
-	/* Always enable OCPO error */
-	cal_write(phy->cal, CAL_HL_IRQENABLE_SET(0), CAL_HL_IRQ_OCPO_ERR_MASK);
-
-	/* Enable IRQ_WDMA_END 0/1 */
-	val = 0;
-	cal_set_field(&val, 1, CAL_HL_IRQ_MASK(phy->instance));
-	cal_write(phy->cal, CAL_HL_IRQENABLE_SET(1), val);
-	/* Enable IRQ_WDMA_START 0/1 */
-	val = 0;
-	cal_set_field(&val, 1, CAL_HL_IRQ_MASK(phy->instance));
-	cal_write(phy->cal, CAL_HL_IRQENABLE_SET(2), val);
-	/* Todo: Add VC_IRQ and CSI2_COMPLEXIO_IRQ handling */
-	cal_write(phy->cal, CAL_CSI2_VC_IRQENABLE(0), 0xFF000000);
-}
-
-void cal_camerarx_disable_irqs(struct cal_camerarx *phy)
-{
-	u32 val;
-
-	/* Disable CIO error irqs */
-	cal_write(phy->cal, CAL_HL_IRQENABLE_CLR(0),
-		  CAL_HL_IRQ_CIO_MASK(phy->instance));
-	cal_write(phy->cal, CAL_CSI2_COMPLEXIO_IRQENABLE(phy->instance),
-		  0);
-
-	/* Disable IRQ_WDMA_END 0/1 */
-	val = 0;
-	cal_set_field(&val, 1, CAL_HL_IRQ_MASK(phy->instance));
-	cal_write(phy->cal, CAL_HL_IRQENABLE_CLR(1), val);
-	/* Disable IRQ_WDMA_START 0/1 */
-	val = 0;
-	cal_set_field(&val, 1, CAL_HL_IRQ_MASK(phy->instance));
-	cal_write(phy->cal, CAL_HL_IRQENABLE_CLR(2), val);
-	/* Todo: Add VC_IRQ and CSI2_COMPLEXIO_IRQ handling */
-	cal_write(phy->cal, CAL_CSI2_VC_IRQENABLE(0), 0);
-}
-
-void cal_camerarx_ppi_enable(struct cal_camerarx *phy)
-{
-	cal_write(phy->cal, CAL_CSI2_PPI_CTRL(phy->instance), BIT(3));
-	cal_write_field(phy->cal, CAL_CSI2_PPI_CTRL(phy->instance),
-			1, CAL_CSI2_PPI_CTRL_IF_EN_MASK);
-}
-
-void cal_camerarx_ppi_disable(struct cal_camerarx *phy)
-{
-	cal_write_field(phy->cal, CAL_CSI2_PPI_CTRL(phy->instance),
-			0, CAL_CSI2_PPI_CTRL_IF_EN_MASK);
-}
-
-static int cal_camerarx_regmap_init(struct cal_dev *cal,
-				    struct cal_camerarx *phy)
-{
-	const struct cal_camerarx_data *phy_data;
-	unsigned int i;
-
-	if (!cal->data)
-		return -EINVAL;
-
-	phy_data = &cal->data->camerarx[phy->instance];
-
-	for (i = 0; i < F_MAX_FIELDS; i++) {
-		struct reg_field field = {
-			.reg = cal->syscon_camerrx_offset,
-			.lsb = phy_data->fields[i].lsb,
-			.msb = phy_data->fields[i].msb,
-		};
-
-		/*
-		 * Here we update the reg offset with the
-		 * value found in DT
-		 */
-		phy->fields[i] = devm_regmap_field_alloc(cal->dev,
-							 cal->syscon_camerrx,
-							 field);
-		if (IS_ERR(phy->fields[i])) {
-			cal_err(cal, "Unable to allocate regmap fields\n");
-			return PTR_ERR(phy->fields[i]);
-		}
-	}
-
-	return 0;
-}
-
-static int cal_camerarx_parse_dt(struct cal_camerarx *phy)
-{
-	struct v4l2_fwnode_endpoint *endpoint = &phy->endpoint;
-	struct device_node *ep_node;
-	char data_lanes[V4L2_FWNODE_CSI2_MAX_DATA_LANES * 2];
-	unsigned int i;
-	int ret;
-
-	/*
-	 * Find the endpoint node for the port corresponding to the PHY
-	 * instance, and parse its CSI-2-related properties.
-	 */
-	ep_node = of_graph_get_endpoint_by_regs(phy->cal->dev->of_node,
-						phy->instance, 0);
-	if (!ep_node) {
-		phy_dbg(3, phy, "Can't get endpoint\n");
-		return -EINVAL;
-	}
-
-	endpoint->bus_type = V4L2_MBUS_CSI2_DPHY;
-	ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep_node), endpoint);
-	if (ret < 0) {
-		phy_err(phy, "Failed to parse endpoint\n");
-		goto done;
-	}
-
-	for (i = 0; i < endpoint->bus.mipi_csi2.num_data_lanes; i++) {
-		unsigned int lane = endpoint->bus.mipi_csi2.data_lanes[i];
-
-		if (lane > 4) {
-			phy_err(phy, "Invalid position %u for data lane %u\n",
-				lane, i);
-			ret = -EINVAL;
-			goto done;
-		}
-
-		data_lanes[i*2] = '0' + lane;
-		data_lanes[i*2+1] = ' ';
-	}
-
-	data_lanes[i*2-1] = '\0';
-
-	phy_dbg(3, phy,
-		"CSI-2 bus: clock lane <%u>, data lanes <%s>, flags 0x%08x\n",
-		endpoint->bus.mipi_csi2.clock_lane, data_lanes,
-		endpoint->bus.mipi_csi2.flags);
-
-	/* Retrieve the connected device and store it for later use. */
-	phy->sensor_node = of_graph_get_remote_port_parent(ep_node);
-	if (!phy->sensor_node) {
-		phy_dbg(3, phy, "Can't get remote parent\n");
-		goto done;
-	}
-
-	phy_dbg(1, phy, "Found connected device %pOFn\n", phy->sensor_node);
-
-done:
-	of_node_put(ep_node);
-	return ret;
-}
-
-static struct cal_camerarx *cal_camerarx_create(struct cal_dev *cal,
-						unsigned int instance)
-{
-	struct platform_device *pdev = to_platform_device(cal->dev);
-	struct cal_camerarx *phy;
-	int ret;
-
-	phy = kzalloc(sizeof(*phy), GFP_KERNEL);
-	if (!phy)
-		return ERR_PTR(-ENOMEM);
-
-	phy->cal = cal;
-	phy->instance = instance;
-
-	phy->res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
-						(instance == 0) ?
-						"cal_rx_core0" :
-						"cal_rx_core1");
-	phy->base = devm_ioremap_resource(cal->dev, phy->res);
-	if (IS_ERR(phy->base)) {
-		cal_err(cal, "failed to ioremap\n");
-		ret = PTR_ERR(phy->base);
-		goto error;
-	}
-
-	cal_dbg(1, cal, "ioresource %s at %pa - %pa\n",
-		phy->res->name, &phy->res->start, &phy->res->end);
-
-	ret = cal_camerarx_regmap_init(cal, phy);
-	if (ret)
-		goto error;
-
-	ret = cal_camerarx_parse_dt(phy);
-	if (ret)
-		goto error;
-
-	return phy;
-
-error:
-	kfree(phy);
-	return ERR_PTR(ret);
-}
-
-static void cal_camerarx_destroy(struct cal_camerarx *phy)
-{
-	if (!phy)
-		return;
-
-	of_node_put(phy->sensor_node);
-	kfree(phy);
-}
-
-static int cal_camerarx_init_regmap(struct cal_dev *cal)
-{
-	struct platform_device *pdev = to_platform_device(cal->dev);
-	struct device_node *np = cal->dev->of_node;
-	struct regmap_config config = { };
-	struct regmap *syscon;
-	struct resource *res;
-	unsigned int offset;
-	void __iomem *base;
-
-	syscon = syscon_regmap_lookup_by_phandle_args(np, "ti,camerrx-control",
-						      1, &offset);
-	if (!IS_ERR(syscon)) {
-		cal->syscon_camerrx = syscon;
-		cal->syscon_camerrx_offset = offset;
-		return 0;
-	}
-
-	dev_warn(cal->dev, "failed to get ti,camerrx-control: %ld\n",
-		 PTR_ERR(syscon));
-
-	/*
-	 * Backward DTS compatibility. If syscon entry is not present then
-	 * check if the camerrx_control resource is present.
-	 */
-	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
-					   "camerrx_control");
-	base = devm_ioremap_resource(cal->dev, res);
-	if (IS_ERR(base)) {
-		cal_err(cal, "failed to ioremap camerrx_control\n");
-		return PTR_ERR(base);
-	}
-
-	cal_dbg(1, cal, "ioresource %s at %pa - %pa\n",
-		res->name, &res->start, &res->end);
-
-	config.reg_bits = 32;
-	config.reg_stride = 4;
-	config.val_bits = 32;
-	config.max_register = resource_size(res) - 4;
-
-	syscon = regmap_init_mmio(NULL, base, &config);
-	if (IS_ERR(syscon)) {
-		pr_err("regmap init failed\n");
-		return PTR_ERR(syscon);
-	}
-
-	/*
-	 * In this case the base already point to the direct CM register so no
-	 * need for an offset.
-	 */
-	cal->syscon_camerrx = syscon;
-	cal->syscon_camerrx_offset = 0;
-
-	return 0;
-}
-
 /* ------------------------------------------------------------------
  *	Context Management
  * ------------------------------------------------------------------
@@ -1350,6 +682,63 @@ static u32 cal_data_get_num_csi2_phy(struct cal_dev *cal)
 	return cal->data->num_csi2_phy;
 }
 
+static int cal_init_camerarx_regmap(struct cal_dev *cal)
+{
+	struct platform_device *pdev = to_platform_device(cal->dev);
+	struct device_node *np = cal->dev->of_node;
+	struct regmap_config config = { };
+	struct regmap *syscon;
+	struct resource *res;
+	unsigned int offset;
+	void __iomem *base;
+
+	syscon = syscon_regmap_lookup_by_phandle_args(np, "ti,camerrx-control",
+						      1, &offset);
+	if (!IS_ERR(syscon)) {
+		cal->syscon_camerrx = syscon;
+		cal->syscon_camerrx_offset = offset;
+		return 0;
+	}
+
+	dev_warn(cal->dev, "failed to get ti,camerrx-control: %ld\n",
+		 PTR_ERR(syscon));
+
+	/*
+	 * Backward DTS compatibility. If syscon entry is not present then
+	 * check if the camerrx_control resource is present.
+	 */
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+					   "camerrx_control");
+	base = devm_ioremap_resource(cal->dev, res);
+	if (IS_ERR(base)) {
+		cal_err(cal, "failed to ioremap camerrx_control\n");
+		return PTR_ERR(base);
+	}
+
+	cal_dbg(1, cal, "ioresource %s at %pa - %pa\n",
+		res->name, &res->start, &res->end);
+
+	config.reg_bits = 32;
+	config.reg_stride = 4;
+	config.val_bits = 32;
+	config.max_register = resource_size(res) - 4;
+
+	syscon = regmap_init_mmio(NULL, base, &config);
+	if (IS_ERR(syscon)) {
+		pr_err("regmap init failed\n");
+		return PTR_ERR(syscon);
+	}
+
+	/*
+	 * In this case the base already point to the direct CM register so no
+	 * need for an offset.
+	 */
+	cal->syscon_camerrx = syscon;
+	cal->syscon_camerrx_offset = 0;
+
+	return 0;
+}
+
 static int cal_probe(struct platform_device *pdev)
 {
 	struct cal_dev *cal;
@@ -1378,7 +767,7 @@ static int cal_probe(struct platform_device *pdev)
 		return PTR_ERR(cal->fclk);
 	}
 
-	ret = cal_camerarx_init_regmap(cal);
+	ret = cal_init_camerarx_regmap(cal);
 	if (ret < 0)
 		return ret;
 
diff --git a/drivers/media/platform/ti-vpe/cal.h b/drivers/media/platform/ti-vpe/cal.h
index 523049f3f9dc..cb167bfc2773 100644
--- a/drivers/media/platform/ti-vpe/cal.h
+++ b/drivers/media/platform/ti-vpe/cal.h
@@ -241,12 +241,17 @@ static inline void cal_set_field(u32 *valp, u32 field, u32 mask)
 
 void cal_quickdump_regs(struct cal_dev *cal);
 
+void cal_camerarx_disable(struct cal_camerarx *phy);
 int cal_camerarx_start(struct cal_camerarx *phy, const struct cal_fmt *fmt);
 void cal_camerarx_stop(struct cal_camerarx *phy);
 void cal_camerarx_enable_irqs(struct cal_camerarx *phy);
 void cal_camerarx_disable_irqs(struct cal_camerarx *phy);
 void cal_camerarx_ppi_enable(struct cal_camerarx *phy);
 void cal_camerarx_ppi_disable(struct cal_camerarx *phy);
+void cal_camerarx_i913_errata(struct cal_camerarx *phy);
+struct cal_camerarx *cal_camerarx_create(struct cal_dev *cal,
+					 unsigned int instance);
+void cal_camerarx_destroy(struct cal_camerarx *phy);
 
 void cal_ctx_csi2_config(struct cal_ctx *ctx);
 void cal_ctx_pix_proc_config(struct cal_ctx *ctx);
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 084/107] media: ti-vpe: cal: Create subdev for CAMERARX
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (82 preceding siblings ...)
  2020-06-14 23:59 ` [PATCH v1 083/107] media: ti-vpe: cal: Split CAMERARX handling to cal-camerarx.c Laurent Pinchart
@ 2020-06-14 23:59 ` Laurent Pinchart
  2020-06-17 10:10   ` Kieran Bingham
  2020-06-14 23:59 ` [PATCH v1 085/107] media: ti-vpe: cal: Drop cal_ctx m_fmt field Laurent Pinchart
                   ` (24 subsequent siblings)
  108 siblings, 1 reply; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:59 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

Create and register V4L2 sudbevs for the CAMERARX instances, and link
them in the media graph to the sensors and video nodes. The subdev API
is not exposed to userspace at this point, and no subdev operation is
implemented, but the media controller graph is visible to applications.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal-camerarx.c | 42 +++++++++++++++++++-
 drivers/media/platform/ti-vpe/cal-video.c    | 12 ++++++
 drivers/media/platform/ti-vpe/cal.c          | 31 ++++++++++++---
 drivers/media/platform/ti-vpe/cal.h          |  9 ++++-
 4 files changed, 86 insertions(+), 8 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal-camerarx.c b/drivers/media/platform/ti-vpe/cal-camerarx.c
index a7e4b81c9734..9be432ff87b2 100644
--- a/drivers/media/platform/ti-vpe/cal-camerarx.c
+++ b/drivers/media/platform/ti-vpe/cal-camerarx.c
@@ -526,8 +526,8 @@ static int cal_camerarx_regmap_init(struct cal_dev *cal,
 static int cal_camerarx_parse_dt(struct cal_camerarx *phy)
 {
 	struct v4l2_fwnode_endpoint *endpoint = &phy->endpoint;
-	struct device_node *ep_node;
 	char data_lanes[V4L2_FWNODE_CSI2_MAX_DATA_LANES * 2];
+	struct device_node *ep_node;
 	unsigned int i;
 	int ret;
 
@@ -571,7 +571,8 @@ static int cal_camerarx_parse_dt(struct cal_camerarx *phy)
 		endpoint->bus.mipi_csi2.flags);
 
 	/* Retrieve the connected device and store it for later use. */
-	phy->sensor_node = of_graph_get_remote_port_parent(ep_node);
+	phy->sensor_ep_node = of_graph_get_remote_endpoint(ep_node);
+	phy->sensor_node = of_graph_get_port_parent(phy->sensor_ep_node);
 	if (!phy->sensor_node) {
 		phy_dbg(3, phy, "Can't get remote parent\n");
 		goto done;
@@ -580,15 +581,30 @@ static int cal_camerarx_parse_dt(struct cal_camerarx *phy)
 	phy_dbg(1, phy, "Found connected device %pOFn\n", phy->sensor_node);
 
 done:
+	of_node_put(phy->sensor_ep_node);
 	of_node_put(ep_node);
 	return ret;
 }
 
+/* ------------------------------------------------------------------
+ *	V4L2 Subdev Operations
+ * ------------------------------------------------------------------
+ */
+
+static const struct v4l2_subdev_ops cal_camerarx_subdev_ops = {
+};
+
+/* ------------------------------------------------------------------
+ *	Create and Destroy
+ * ------------------------------------------------------------------
+ */
+
 struct cal_camerarx *cal_camerarx_create(struct cal_dev *cal,
 					 unsigned int instance)
 {
 	struct platform_device *pdev = to_platform_device(cal->dev);
 	struct cal_camerarx *phy;
+	struct v4l2_subdev *sd;
 	int ret;
 
 	phy = kzalloc(sizeof(*phy), GFP_KERNEL);
@@ -620,9 +636,28 @@ struct cal_camerarx *cal_camerarx_create(struct cal_dev *cal,
 	if (ret)
 		goto error;
 
+	/* Initialize the V4L2 subdev and media entity. */
+	sd = &phy->subdev;
+	v4l2_subdev_init(sd, &cal_camerarx_subdev_ops);
+	sd->entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
+	snprintf(sd->name, sizeof(sd->name), "CAMERARX%u", instance);
+	sd->dev = cal->dev;
+
+	phy->pads[CAL_CAMERARX_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
+	phy->pads[CAL_CAMERARX_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
+	ret = media_entity_pads_init(&sd->entity, ARRAY_SIZE(phy->pads),
+				     phy->pads);
+	if (ret)
+		goto error;
+
+	ret = v4l2_device_register_subdev(&cal->v4l2_dev, sd);
+	if (ret)
+		goto error;
+
 	return phy;
 
 error:
+	media_entity_cleanup(&phy->subdev.entity);
 	kfree(phy);
 	return ERR_PTR(ret);
 }
@@ -632,6 +667,9 @@ void cal_camerarx_destroy(struct cal_camerarx *phy)
 	if (!phy)
 		return;
 
+	v4l2_device_unregister_subdev(&phy->subdev);
+	media_entity_cleanup(&phy->subdev.entity);
+	of_node_put(phy->sensor_ep_node);
 	of_node_put(phy->sensor_node);
 	kfree(phy);
 }
diff --git a/drivers/media/platform/ti-vpe/cal-video.c b/drivers/media/platform/ti-vpe/cal-video.c
index df472a175e83..0a1a11692208 100644
--- a/drivers/media/platform/ti-vpe/cal-video.c
+++ b/drivers/media/platform/ti-vpe/cal-video.c
@@ -809,6 +809,18 @@ int cal_ctx_v4l2_register(struct cal_ctx *ctx)
 		return ret;
 	}
 
+	ret = media_create_pad_link(&ctx->phy->subdev.entity,
+				    CAL_CAMERARX_PAD_SOURCE,
+				    &vfd->entity, 0,
+				    MEDIA_LNK_FL_IMMUTABLE |
+				    MEDIA_LNK_FL_ENABLED);
+	if (ret) {
+		ctx_err(ctx, "Failed to create media link for context %u\n",
+			ctx->index);
+		video_unregister_device(vfd);
+		return ret;
+	}
+
 	ctx_info(ctx, "V4L2 device registered as %s\n",
 		 video_device_node_name(vfd));
 
diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index ca8576aa2646..bf1734d4d800 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -416,6 +416,8 @@ static int cal_async_notifier_bound(struct v4l2_async_notifier *notifier,
 				    struct v4l2_async_subdev *asd)
 {
 	struct cal_camerarx *phy = to_cal_asd(asd)->phy;
+	int pad;
+	int ret;
 
 	if (phy->sensor) {
 		phy_info(phy, "Rejecting subdev %s (Already set!!)",
@@ -426,6 +428,25 @@ static int cal_async_notifier_bound(struct v4l2_async_notifier *notifier,
 	phy->sensor = subdev;
 	phy_dbg(1, phy, "Using sensor %s for capture\n", subdev->name);
 
+	pad = media_entity_get_fwnode_pad(&subdev->entity,
+					  of_fwnode_handle(phy->sensor_ep_node),
+					  MEDIA_PAD_FL_SOURCE);
+	if (pad < 0) {
+		phy_err(phy, "Sensor %s has no connected source pad\n",
+			subdev->name);
+		return pad;
+	}
+
+	ret = media_create_pad_link(&subdev->entity, pad,
+				    &phy->subdev.entity, CAL_CAMERARX_PAD_SINK,
+				    MEDIA_LNK_FL_IMMUTABLE |
+				    MEDIA_LNK_FL_ENABLED);
+	if (ret) {
+		phy_err(phy, "Failed to create media link for sensor %s\n",
+			subdev->name);
+		return ret;
+	}
+
 	return 0;
 }
 
@@ -796,6 +817,11 @@ static int cal_probe(struct platform_device *pdev)
 	cal_get_hwinfo(cal);
 	pm_runtime_put_sync(&pdev->dev);
 
+	/* Initialize the media device. */
+	ret = cal_media_init(cal);
+	if (ret < 0)
+		goto error_camerarx;
+
 	/* Create CAMERARX PHYs. */
 	for (i = 0; i < cal_data_get_num_csi2_phy(cal); ++i) {
 		cal->phy[i] = cal_camerarx_create(cal, i);
@@ -805,11 +831,6 @@ static int cal_probe(struct platform_device *pdev)
 		}
 	}
 
-	/* Initialize the media device. */
-	ret = cal_media_init(cal);
-	if (ret < 0)
-		goto error_camerarx;
-
 	/* Create contexts. */
 	for (i = 0; i < cal_data_get_num_csi2_phy(cal); ++i)
 		cal->ctx[i] = cal_ctx_create(cal, i);
diff --git a/drivers/media/platform/ti-vpe/cal.h b/drivers/media/platform/ti-vpe/cal.h
index cb167bfc2773..bf31dbf24523 100644
--- a/drivers/media/platform/ti-vpe/cal.h
+++ b/drivers/media/platform/ti-vpe/cal.h
@@ -24,6 +24,7 @@
 #include <media/v4l2-dev.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-fwnode.h>
+#include <media/v4l2-subdev.h>
 #include <media/videobuf2-v4l2.h>
 
 #define CAL_MODULE_NAME			"cal"
@@ -33,12 +34,14 @@
 #define MAX_WIDTH_BYTES			(8192 * 8)
 #define MAX_HEIGHT_LINES		16383
 
+#define CAL_CAMERARX_PAD_SINK		0
+#define CAL_CAMERARX_PAD_SOURCE		1
+
 struct device;
 struct device_node;
 struct resource;
 struct regmap;
 struct regmap_fied;
-struct v4l2_subdev;
 
 /* CTRL_CORE_CAMERRX_CONTROL register field id */
 enum cal_camerarx_field {
@@ -108,8 +111,12 @@ struct cal_camerarx {
 	unsigned int		instance;
 
 	struct v4l2_fwnode_endpoint	endpoint;
+	struct device_node	*sensor_ep_node;
 	struct device_node	*sensor_node;
 	struct v4l2_subdev	*sensor;
+
+	struct v4l2_subdev	subdev;
+	struct media_pad	pads[2];
 };
 
 struct cal_dev {
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 085/107] media: ti-vpe: cal: Drop cal_ctx m_fmt field
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (83 preceding siblings ...)
  2020-06-14 23:59 ` [PATCH v1 084/107] media: ti-vpe: cal: Create subdev for CAMERARX Laurent Pinchart
@ 2020-06-14 23:59 ` Laurent Pinchart
  2020-06-14 23:59 ` [PATCH v1 086/107] media: ti-vpe: cal: Move format handling to cal.c and expose helpers Laurent Pinchart
                   ` (23 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:59 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

The struct cal_ctx m_fmt field stores the media bus format for the
context input. Only the format 'field' field is used, store it in the
video format instead, and drop m_fmt.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal-video.c | 10 +++++-----
 drivers/media/platform/ti-vpe/cal.c       |  2 +-
 drivers/media/platform/ti-vpe/cal.h       |  4 +---
 3 files changed, 7 insertions(+), 9 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal-video.c b/drivers/media/platform/ti-vpe/cal-video.c
index 0a1a11692208..f57767e79ca5 100644
--- a/drivers/media/platform/ti-vpe/cal-video.c
+++ b/drivers/media/platform/ti-vpe/cal-video.c
@@ -387,10 +387,10 @@ static int cal_s_fmt_vid_cap(struct file *file, void *priv,
 
 	v4l2_fill_pix_format(&ctx->v_fmt.fmt.pix, &mbus_fmt);
 	ctx->v_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-	ctx->v_fmt.fmt.pix.pixelformat  = fmt->fourcc;
+	ctx->v_fmt.fmt.pix.pixelformat = fmt->fourcc;
+	ctx->v_fmt.fmt.pix.field = mbus_fmt.field;
 	cal_calc_format_size(ctx, fmt, &ctx->v_fmt);
 	ctx->fmt = fmt;
-	ctx->m_fmt = mbus_fmt;
 	*f = ctx->v_fmt;
 
 	return 0;
@@ -775,13 +775,13 @@ static int cal_ctx_v4l2_init_formats(struct cal_ctx *ctx)
 		return -EINVAL;
 	}
 
-	/* Save current subdev format */
+	/* Save current format */
 	v4l2_fill_pix_format(&ctx->v_fmt.fmt.pix, &mbus_fmt);
 	ctx->v_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-	ctx->v_fmt.fmt.pix.pixelformat  = fmt->fourcc;
+	ctx->v_fmt.fmt.pix.pixelformat = fmt->fourcc;
+	ctx->v_fmt.fmt.pix.field = mbus_fmt.field;
 	cal_calc_format_size(ctx, fmt, &ctx->v_fmt);
 	ctx->fmt = fmt;
-	ctx->m_fmt = mbus_fmt;
 
 	return 0;
 }
diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index bf1734d4d800..101d0a2c4404 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -314,7 +314,7 @@ static inline void cal_schedule_next_buffer(struct cal_ctx *ctx)
 static inline void cal_process_buffer_complete(struct cal_ctx *ctx)
 {
 	ctx->cur_frm->vb.vb2_buf.timestamp = ktime_get_ns();
-	ctx->cur_frm->vb.field = ctx->m_fmt.field;
+	ctx->cur_frm->vb.field = ctx->v_fmt.fmt.pix.field;
 	ctx->cur_frm->vb.sequence = ctx->sequence++;
 
 	vb2_buffer_done(&ctx->cur_frm->vb.vb2_buf, VB2_BUF_STATE_DONE);
diff --git a/drivers/media/platform/ti-vpe/cal.h b/drivers/media/platform/ti-vpe/cal.h
index bf31dbf24523..cdee28bb88c4 100644
--- a/drivers/media/platform/ti-vpe/cal.h
+++ b/drivers/media/platform/ti-vpe/cal.h
@@ -164,9 +164,7 @@ struct cal_ctx {
 	/* video capture */
 	const struct cal_fmt	*fmt;
 	/* Used to store current pixel format */
-	struct v4l2_format		v_fmt;
-	/* Used to store current mbus frame format */
-	struct v4l2_mbus_framefmt	m_fmt;
+	struct v4l2_format	v_fmt;
 
 	/* Current subdev enumerated format */
 	const struct cal_fmt	**active_fmt;
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 086/107] media: ti-vpe: cal: Move format handling to cal.c and expose helpers
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (84 preceding siblings ...)
  2020-06-14 23:59 ` [PATCH v1 085/107] media: ti-vpe: cal: Drop cal_ctx m_fmt field Laurent Pinchart
@ 2020-06-14 23:59 ` Laurent Pinchart
  2020-06-14 23:59 ` [PATCH v1 087/107] media: ti-vpe: cal: Rename MAX_(WIDTH|HEIGHT)_* macros with CAL_ prefix Laurent Pinchart
                   ` (22 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:59 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

The cal_formats array contain the description of all formats supported
by the hardware. It's currently used by the V4L2 video device operations
only, but will be needed by the CAMERARX subdev code too. Move it from
cal-video.c to cal.c and add helper functions to access it.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal-video.c | 105 +-----------------
 drivers/media/platform/ti-vpe/cal.c       | 127 ++++++++++++++++++++++
 drivers/media/platform/ti-vpe/cal.h       |   5 +
 3 files changed, 134 insertions(+), 103 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal-video.c b/drivers/media/platform/ti-vpe/cal-video.c
index f57767e79ca5..355bb365daf0 100644
--- a/drivers/media/platform/ti-vpe/cal-video.c
+++ b/drivers/media/platform/ti-vpe/cal-video.c
@@ -26,107 +26,6 @@
 
 #include "cal.h"
 
-/* ------------------------------------------------------------------
- *	Format Handling
- * ------------------------------------------------------------------
- */
-
-static const struct cal_fmt cal_formats[] = {
-	{
-		.fourcc		= V4L2_PIX_FMT_YUYV,
-		.code		= MEDIA_BUS_FMT_YUYV8_2X8,
-		.bpp		= 16,
-	}, {
-		.fourcc		= V4L2_PIX_FMT_UYVY,
-		.code		= MEDIA_BUS_FMT_UYVY8_2X8,
-		.bpp		= 16,
-	}, {
-		.fourcc		= V4L2_PIX_FMT_YVYU,
-		.code		= MEDIA_BUS_FMT_YVYU8_2X8,
-		.bpp		= 16,
-	}, {
-		.fourcc		= V4L2_PIX_FMT_VYUY,
-		.code		= MEDIA_BUS_FMT_VYUY8_2X8,
-		.bpp		= 16,
-	}, {
-		.fourcc		= V4L2_PIX_FMT_RGB565, /* gggbbbbb rrrrrggg */
-		.code		= MEDIA_BUS_FMT_RGB565_2X8_LE,
-		.bpp		= 16,
-	}, {
-		.fourcc		= V4L2_PIX_FMT_RGB565X, /* rrrrrggg gggbbbbb */
-		.code		= MEDIA_BUS_FMT_RGB565_2X8_BE,
-		.bpp		= 16,
-	}, {
-		.fourcc		= V4L2_PIX_FMT_RGB555, /* gggbbbbb arrrrrgg */
-		.code		= MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE,
-		.bpp		= 16,
-	}, {
-		.fourcc		= V4L2_PIX_FMT_RGB555X, /* arrrrrgg gggbbbbb */
-		.code		= MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE,
-		.bpp		= 16,
-	}, {
-		.fourcc		= V4L2_PIX_FMT_RGB24, /* rgb */
-		.code		= MEDIA_BUS_FMT_RGB888_2X12_LE,
-		.bpp		= 24,
-	}, {
-		.fourcc		= V4L2_PIX_FMT_BGR24, /* bgr */
-		.code		= MEDIA_BUS_FMT_RGB888_2X12_BE,
-		.bpp		= 24,
-	}, {
-		.fourcc		= V4L2_PIX_FMT_RGB32, /* argb */
-		.code		= MEDIA_BUS_FMT_ARGB8888_1X32,
-		.bpp		= 32,
-	}, {
-		.fourcc		= V4L2_PIX_FMT_SBGGR8,
-		.code		= MEDIA_BUS_FMT_SBGGR8_1X8,
-		.bpp		= 8,
-	}, {
-		.fourcc		= V4L2_PIX_FMT_SGBRG8,
-		.code		= MEDIA_BUS_FMT_SGBRG8_1X8,
-		.bpp		= 8,
-	}, {
-		.fourcc		= V4L2_PIX_FMT_SGRBG8,
-		.code		= MEDIA_BUS_FMT_SGRBG8_1X8,
-		.bpp		= 8,
-	}, {
-		.fourcc		= V4L2_PIX_FMT_SRGGB8,
-		.code		= MEDIA_BUS_FMT_SRGGB8_1X8,
-		.bpp		= 8,
-	}, {
-		.fourcc		= V4L2_PIX_FMT_SBGGR10,
-		.code		= MEDIA_BUS_FMT_SBGGR10_1X10,
-		.bpp		= 10,
-	}, {
-		.fourcc		= V4L2_PIX_FMT_SGBRG10,
-		.code		= MEDIA_BUS_FMT_SGBRG10_1X10,
-		.bpp		= 10,
-	}, {
-		.fourcc		= V4L2_PIX_FMT_SGRBG10,
-		.code		= MEDIA_BUS_FMT_SGRBG10_1X10,
-		.bpp		= 10,
-	}, {
-		.fourcc		= V4L2_PIX_FMT_SRGGB10,
-		.code		= MEDIA_BUS_FMT_SRGGB10_1X10,
-		.bpp		= 10,
-	}, {
-		.fourcc		= V4L2_PIX_FMT_SBGGR12,
-		.code		= MEDIA_BUS_FMT_SBGGR12_1X12,
-		.bpp		= 12,
-	}, {
-		.fourcc		= V4L2_PIX_FMT_SGBRG12,
-		.code		= MEDIA_BUS_FMT_SGBRG12_1X12,
-		.bpp		= 12,
-	}, {
-		.fourcc		= V4L2_PIX_FMT_SGRBG12,
-		.code		= MEDIA_BUS_FMT_SGRBG12_1X12,
-		.bpp		= 12,
-	}, {
-		.fourcc		= V4L2_PIX_FMT_SRGGB12,
-		.code		= MEDIA_BUS_FMT_SRGGB12_1X12,
-		.bpp		= 12,
-	},
-};
-
 /*  Print Four-character-code (FOURCC) */
 static char *fourcc_to_str(u32 fmt)
 {
@@ -726,7 +625,7 @@ static int cal_ctx_v4l2_init_formats(struct cal_ctx *ctx)
 	int ret = 0;
 
 	/* Enumerate sub device formats and enable all matching local formats */
-	ctx->active_fmt = devm_kcalloc(ctx->cal->dev, ARRAY_SIZE(cal_formats),
+	ctx->active_fmt = devm_kcalloc(ctx->cal->dev, cal_num_formats,
 				       sizeof(*ctx->active_fmt), GFP_KERNEL);
 	ctx->num_active_fmt = 0;
 
@@ -744,7 +643,7 @@ static int cal_ctx_v4l2_init_formats(struct cal_ctx *ctx)
 			"subdev %s: code: %04x idx: %u\n",
 			ctx->phy->sensor->name, mbus_code.code, j);
 
-		for (k = 0; k < ARRAY_SIZE(cal_formats); k++) {
+		for (k = 0; k < cal_num_formats; k++) {
 			const struct cal_fmt *fmt = &cal_formats[k];
 
 			if (mbus_code.code == fmt->code) {
diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index 101d0a2c4404..3e82a5edf376 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -43,6 +43,133 @@ unsigned int cal_debug;
 module_param_named(debug, cal_debug, uint, 0644);
 MODULE_PARM_DESC(debug, "activates debug info");
 
+/* ------------------------------------------------------------------
+ *	Format Handling
+ * ------------------------------------------------------------------
+ */
+
+const struct cal_fmt cal_formats[] = {
+	{
+		.fourcc		= V4L2_PIX_FMT_YUYV,
+		.code		= MEDIA_BUS_FMT_YUYV8_2X8,
+		.bpp		= 16,
+	}, {
+		.fourcc		= V4L2_PIX_FMT_UYVY,
+		.code		= MEDIA_BUS_FMT_UYVY8_2X8,
+		.bpp		= 16,
+	}, {
+		.fourcc		= V4L2_PIX_FMT_YVYU,
+		.code		= MEDIA_BUS_FMT_YVYU8_2X8,
+		.bpp		= 16,
+	}, {
+		.fourcc		= V4L2_PIX_FMT_VYUY,
+		.code		= MEDIA_BUS_FMT_VYUY8_2X8,
+		.bpp		= 16,
+	}, {
+		.fourcc		= V4L2_PIX_FMT_RGB565, /* gggbbbbb rrrrrggg */
+		.code		= MEDIA_BUS_FMT_RGB565_2X8_LE,
+		.bpp		= 16,
+	}, {
+		.fourcc		= V4L2_PIX_FMT_RGB565X, /* rrrrrggg gggbbbbb */
+		.code		= MEDIA_BUS_FMT_RGB565_2X8_BE,
+		.bpp		= 16,
+	}, {
+		.fourcc		= V4L2_PIX_FMT_RGB555, /* gggbbbbb arrrrrgg */
+		.code		= MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE,
+		.bpp		= 16,
+	}, {
+		.fourcc		= V4L2_PIX_FMT_RGB555X, /* arrrrrgg gggbbbbb */
+		.code		= MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE,
+		.bpp		= 16,
+	}, {
+		.fourcc		= V4L2_PIX_FMT_RGB24, /* rgb */
+		.code		= MEDIA_BUS_FMT_RGB888_2X12_LE,
+		.bpp		= 24,
+	}, {
+		.fourcc		= V4L2_PIX_FMT_BGR24, /* bgr */
+		.code		= MEDIA_BUS_FMT_RGB888_2X12_BE,
+		.bpp		= 24,
+	}, {
+		.fourcc		= V4L2_PIX_FMT_RGB32, /* argb */
+		.code		= MEDIA_BUS_FMT_ARGB8888_1X32,
+		.bpp		= 32,
+	}, {
+		.fourcc		= V4L2_PIX_FMT_SBGGR8,
+		.code		= MEDIA_BUS_FMT_SBGGR8_1X8,
+		.bpp		= 8,
+	}, {
+		.fourcc		= V4L2_PIX_FMT_SGBRG8,
+		.code		= MEDIA_BUS_FMT_SGBRG8_1X8,
+		.bpp		= 8,
+	}, {
+		.fourcc		= V4L2_PIX_FMT_SGRBG8,
+		.code		= MEDIA_BUS_FMT_SGRBG8_1X8,
+		.bpp		= 8,
+	}, {
+		.fourcc		= V4L2_PIX_FMT_SRGGB8,
+		.code		= MEDIA_BUS_FMT_SRGGB8_1X8,
+		.bpp		= 8,
+	}, {
+		.fourcc		= V4L2_PIX_FMT_SBGGR10,
+		.code		= MEDIA_BUS_FMT_SBGGR10_1X10,
+		.bpp		= 10,
+	}, {
+		.fourcc		= V4L2_PIX_FMT_SGBRG10,
+		.code		= MEDIA_BUS_FMT_SGBRG10_1X10,
+		.bpp		= 10,
+	}, {
+		.fourcc		= V4L2_PIX_FMT_SGRBG10,
+		.code		= MEDIA_BUS_FMT_SGRBG10_1X10,
+		.bpp		= 10,
+	}, {
+		.fourcc		= V4L2_PIX_FMT_SRGGB10,
+		.code		= MEDIA_BUS_FMT_SRGGB10_1X10,
+		.bpp		= 10,
+	}, {
+		.fourcc		= V4L2_PIX_FMT_SBGGR12,
+		.code		= MEDIA_BUS_FMT_SBGGR12_1X12,
+		.bpp		= 12,
+	}, {
+		.fourcc		= V4L2_PIX_FMT_SGBRG12,
+		.code		= MEDIA_BUS_FMT_SGBRG12_1X12,
+		.bpp		= 12,
+	}, {
+		.fourcc		= V4L2_PIX_FMT_SGRBG12,
+		.code		= MEDIA_BUS_FMT_SGRBG12_1X12,
+		.bpp		= 12,
+	}, {
+		.fourcc		= V4L2_PIX_FMT_SRGGB12,
+		.code		= MEDIA_BUS_FMT_SRGGB12_1X12,
+		.bpp		= 12,
+	},
+};
+
+const unsigned int cal_num_formats = ARRAY_SIZE(cal_formats);
+
+const struct cal_fmt *cal_format_by_fourcc(u32 fourcc)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(cal_formats); ++i) {
+		if (cal_formats[i].fourcc == fourcc)
+			return &cal_formats[i];
+	}
+
+	return NULL;
+}
+
+const struct cal_fmt *cal_format_by_code(u32 code)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(cal_formats); ++i) {
+		if (cal_formats[i].code == code)
+			return &cal_formats[i];
+	}
+
+	return NULL;
+}
+
 /* ------------------------------------------------------------------
  *	Platform Data
  * ------------------------------------------------------------------
diff --git a/drivers/media/platform/ti-vpe/cal.h b/drivers/media/platform/ti-vpe/cal.h
index cdee28bb88c4..8d1753ebb7c4 100644
--- a/drivers/media/platform/ti-vpe/cal.h
+++ b/drivers/media/platform/ti-vpe/cal.h
@@ -244,6 +244,11 @@ static inline void cal_set_field(u32 *valp, u32 field, u32 mask)
 	*valp = val;
 }
 
+extern const struct cal_fmt cal_formats[];
+extern const unsigned int cal_num_formats;
+const struct cal_fmt *cal_format_by_fourcc(u32 fourcc);
+const struct cal_fmt *cal_format_by_code(u32 code);
+
 void cal_quickdump_regs(struct cal_dev *cal);
 
 void cal_camerarx_disable(struct cal_camerarx *phy);
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 087/107] media: ti-vpe: cal: Rename MAX_(WIDTH|HEIGHT)_* macros with CAL_ prefix
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (85 preceding siblings ...)
  2020-06-14 23:59 ` [PATCH v1 086/107] media: ti-vpe: cal: Move format handling to cal.c and expose helpers Laurent Pinchart
@ 2020-06-14 23:59 ` Laurent Pinchart
  2020-06-14 23:59 ` [PATCH v1 088/107] media: ti-vpe: cal: Replace hardcoded BIT() value with macro Laurent Pinchart
                   ` (21 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:59 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

The MAX_WIDTH_BYTES and MAX_HEIGHT_LINES macros have a generic name that
is prone to namespace clashes. Rename them with a CAL_ prefix. While at
it, expand their documentation and add CAL_MIN_(WIDTH|HEIGHT)_* macros
that will be used to implement CAMERARX subdev operations.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal-video.c |  5 +++--
 drivers/media/platform/ti-vpe/cal.h       | 12 ++++++++++--
 2 files changed, 13 insertions(+), 4 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal-video.c b/drivers/media/platform/ti-vpe/cal-video.c
index 355bb365daf0..42e750925e8b 100644
--- a/drivers/media/platform/ti-vpe/cal-video.c
+++ b/drivers/media/platform/ti-vpe/cal-video.c
@@ -163,9 +163,10 @@ static int cal_calc_format_size(struct cal_ctx *ctx,
 	 * We need to recalculate the actual maxi width depending on the
 	 * number of bytes per pixels required.
 	 */
-	max_width = MAX_WIDTH_BYTES / (ALIGN(fmt->bpp, 8) >> 3);
+	max_width = CAL_MAX_WIDTH_BYTES / (ALIGN(fmt->bpp, 8) >> 3);
 	v4l_bound_align_image(&f->fmt.pix.width, 48, max_width, 2,
-			      &f->fmt.pix.height, 32, MAX_HEIGHT_LINES, 0, 0);
+			      &f->fmt.pix.height, 32, CAL_MAX_HEIGHT_LINES,
+			      0, 0);
 
 	bpl = (f->fmt.pix.width * ALIGN(fmt->bpp, 8)) >> 3;
 	f->fmt.pix.bytesperline = ALIGN(bpl, 16);
diff --git a/drivers/media/platform/ti-vpe/cal.h b/drivers/media/platform/ti-vpe/cal.h
index 8d1753ebb7c4..7356d01e8d73 100644
--- a/drivers/media/platform/ti-vpe/cal.h
+++ b/drivers/media/platform/ti-vpe/cal.h
@@ -31,8 +31,16 @@
 #define CAL_NUM_CONTEXT			2
 #define CAL_NUM_CSI2_PORTS		2
 
-#define MAX_WIDTH_BYTES			(8192 * 8)
-#define MAX_HEIGHT_LINES		16383
+/*
+ * The width is limited by the size of the CAL_WR_DMA_XSIZE_j.XSIZE field,
+ * expressed in multiples of 64 bits. The height is limited by the size of the
+ * CAL_CSI2_CTXi_j.CTXi_LINES and CAL_WR_DMA_CTRL_j.YSIZE fields, expressed in
+ * lines.
+ */
+#define CAL_MIN_WIDTH_BYTES		16
+#define CAL_MAX_WIDTH_BYTES		(8192 * 8)
+#define CAL_MIN_HEIGHT_LINES		1
+#define CAL_MAX_HEIGHT_LINES		16383
 
 #define CAL_CAMERARX_PAD_SINK		0
 #define CAL_CAMERARX_PAD_SOURCE		1
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 088/107] media: ti-vpe: cal: Replace hardcoded BIT() value with macro
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (86 preceding siblings ...)
  2020-06-14 23:59 ` [PATCH v1 087/107] media: ti-vpe: cal: Rename MAX_(WIDTH|HEIGHT)_* macros with CAL_ prefix Laurent Pinchart
@ 2020-06-14 23:59 ` Laurent Pinchart
  2020-06-14 23:59 ` [PATCH v1 089/107] media: ti-vpe: cal: Iterate over correct number of CAMERARX instances Laurent Pinchart
                   ` (20 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:59 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

Replace the hardcoded BIT(3) value with CAL_CSI2_PPI_CTRL_FRAME_MASK to
increase readability.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal-camerarx.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/media/platform/ti-vpe/cal-camerarx.c b/drivers/media/platform/ti-vpe/cal-camerarx.c
index 9be432ff87b2..c69c26e88a1d 100644
--- a/drivers/media/platform/ti-vpe/cal-camerarx.c
+++ b/drivers/media/platform/ti-vpe/cal-camerarx.c
@@ -478,7 +478,8 @@ void cal_camerarx_disable_irqs(struct cal_camerarx *phy)
 
 void cal_camerarx_ppi_enable(struct cal_camerarx *phy)
 {
-	cal_write(phy->cal, CAL_CSI2_PPI_CTRL(phy->instance), BIT(3));
+	cal_write(phy->cal, CAL_CSI2_PPI_CTRL(phy->instance),
+		  CAL_CSI2_PPI_CTRL_FRAME_MASK);
 	cal_write_field(phy->cal, CAL_CSI2_PPI_CTRL(phy->instance),
 			1, CAL_CSI2_PPI_CTRL_IF_EN_MASK);
 }
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 089/107] media: ti-vpe: cal: Iterate over correct number of CAMERARX instances
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (87 preceding siblings ...)
  2020-06-14 23:59 ` [PATCH v1 088/107] media: ti-vpe: cal: Replace hardcoded BIT() value with macro Laurent Pinchart
@ 2020-06-14 23:59 ` Laurent Pinchart
  2020-06-14 23:59 ` [PATCH v1 090/107] media: ti-vpe: cal: Implement subdev ops for CAMERARX Laurent Pinchart
                   ` (19 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:59 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

When performing operations on all CAMERARX instances, code usually
iterates over all cal->phy[] entries and skips the NULL pointers. The
number of available CAMERARX instances is however available through
cal->data->num_csi2_phy. Use it instead.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 21 ++++++++-------------
 1 file changed, 8 insertions(+), 13 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index 3e82a5edf376..ad6e8a1e352b 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -263,12 +263,9 @@ void cal_quickdump_regs(struct cal_dev *cal)
 		       (__force const void *)cal->base,
 		       resource_size(cal->res), false);
 
-	for (i = 0; i < ARRAY_SIZE(cal->phy); ++i) {
+	for (i = 0; i < cal->data->num_csi2_phy; ++i) {
 		struct cal_camerarx *phy = cal->phy[i];
 
-		if (!phy)
-			continue;
-
 		cal_info(cal, "CSI2 Core %u Registers @ %pa:\n", i,
 			 &phy->res->start);
 		print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 4,
@@ -463,7 +460,7 @@ static irqreturn_t cal_irq(int irq_cal, void *data)
 		if (status & CAL_HL_IRQ_OCPO_ERR_MASK)
 			dev_err_ratelimited(cal->dev, "OCPO ERROR\n");
 
-		for (i = 0; i < CAL_NUM_CSI2_PORTS; ++i) {
+		for (i = 0; i < cal->data->num_csi2_phy; ++i) {
 			if (status & CAL_HL_IRQ_CIO_MASK(i)) {
 				u32 cio_stat = cal_read(cal,
 							CAL_CSI2_COMPLEXIO_IRQSTATUS(i));
@@ -603,15 +600,12 @@ static int cal_async_notifier_register(struct cal_dev *cal)
 	v4l2_async_notifier_init(&cal->notifier);
 	cal->notifier.ops = &cal_async_notifier_ops;
 
-	for (i = 0; i < ARRAY_SIZE(cal->phy); ++i) {
+	for (i = 0; i < cal->data->num_csi2_phy; ++i) {
 		struct cal_camerarx *phy = cal->phy[i];
 		struct cal_v4l2_async_subdev *casd;
 		struct v4l2_async_subdev *asd;
 		struct fwnode_handle *fwnode;
 
-		if (!phy)
-			continue;
-
 		fwnode = of_fwnode_handle(phy->sensor_node);
 		asd = v4l2_async_notifier_add_fwnode_subdev(&cal->notifier,
 							    fwnode,
@@ -986,7 +980,7 @@ static int cal_probe(struct platform_device *pdev)
 	cal_media_cleanup(cal);
 
 error_camerarx:
-	for (i = 0; i < ARRAY_SIZE(cal->phy); i++)
+	for (i = 0; i < cal->data->num_csi2_phy; i++)
 		cal_camerarx_destroy(cal->phy[i]);
 
 error_pm_runtime:
@@ -1013,7 +1007,7 @@ static int cal_remove(struct platform_device *pdev)
 
 	cal_media_cleanup(cal);
 
-	for (i = 0; i < ARRAY_SIZE(cal->phy); i++)
+	for (i = 0; i < cal->data->num_csi2_phy; i++)
 		cal_camerarx_destroy(cal->phy[i]);
 
 	pm_runtime_put_sync(&pdev->dev);
@@ -1025,14 +1019,15 @@ static int cal_remove(struct platform_device *pdev)
 static int cal_runtime_resume(struct device *dev)
 {
 	struct cal_dev *cal = dev_get_drvdata(dev);
+	unsigned int i;
 
 	if (cal->data->flags & DRA72_CAL_PRE_ES2_LDO_DISABLE) {
 		/*
 		 * Apply errata on both port everytime we (re-)enable
 		 * the clock
 		 */
-		cal_camerarx_i913_errata(cal->phy[0]);
-		cal_camerarx_i913_errata(cal->phy[1]);
+		for (i = 0; i < cal->data->num_csi2_phy; i++)
+			cal_camerarx_i913_errata(cal->phy[i]);
 	}
 
 	return 0;
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 090/107] media: ti-vpe: cal: Implement subdev ops for CAMERARX
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (88 preceding siblings ...)
  2020-06-14 23:59 ` [PATCH v1 089/107] media: ti-vpe: cal: Iterate over correct number of CAMERARX instances Laurent Pinchart
@ 2020-06-14 23:59 ` Laurent Pinchart
  2020-06-14 23:59 ` [PATCH v1 091/107] media: ti-vpe: cal: Use CAMERARX subdev s_stream op in video device code Laurent Pinchart
                   ` (18 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:59 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

Implement subdev operations for the CAMERARX. They will be used to
replace calls to custom CAMERARX functions in the V4L2 video device
code, and will be exposed to userspace.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal-camerarx.c | 205 +++++++++++++++++++
 drivers/media/platform/ti-vpe/cal.h          |   2 +
 2 files changed, 207 insertions(+)

diff --git a/drivers/media/platform/ti-vpe/cal-camerarx.c b/drivers/media/platform/ti-vpe/cal-camerarx.c
index c69c26e88a1d..a7f17ecfbd90 100644
--- a/drivers/media/platform/ti-vpe/cal-camerarx.c
+++ b/drivers/media/platform/ti-vpe/cal-camerarx.c
@@ -592,7 +592,209 @@ static int cal_camerarx_parse_dt(struct cal_camerarx *phy)
  * ------------------------------------------------------------------
  */
 
+static inline struct cal_camerarx *to_cal_camerarx(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct cal_camerarx, subdev);
+}
+
+static struct v4l2_mbus_framefmt *
+cal_camerarx_get_pad_format(struct cal_camerarx *phy,
+			    struct v4l2_subdev_pad_config *cfg,
+			    unsigned int pad, u32 which)
+{
+	switch (which) {
+	case V4L2_SUBDEV_FORMAT_TRY:
+		return v4l2_subdev_get_try_format(&phy->subdev, cfg, pad);
+	case V4L2_SUBDEV_FORMAT_ACTIVE:
+		return &phy->formats[pad];
+	default:
+		return NULL;
+	}
+}
+
+static int cal_camerarx_sd_s_stream(struct v4l2_subdev *sd, int enable)
+{
+	struct cal_camerarx *phy = to_cal_camerarx(sd);
+
+	if (enable)
+		return cal_camerarx_start(phy, NULL);
+
+	cal_camerarx_stop(phy);
+	return 0;
+}
+
+static int cal_camerarx_sd_enum_mbus_code(struct v4l2_subdev *sd,
+					  struct v4l2_subdev_pad_config *cfg,
+					  struct v4l2_subdev_mbus_code_enum *code)
+{
+	struct cal_camerarx *phy = to_cal_camerarx(sd);
+
+	/* No transcoding, source and sink codes must match. */
+	if (code->pad == CAL_CAMERARX_PAD_SOURCE) {
+		struct v4l2_mbus_framefmt *fmt;
+
+		if (code->index > 0)
+			return -EINVAL;
+
+		fmt = cal_camerarx_get_pad_format(phy, cfg,
+						  CAL_CAMERARX_PAD_SINK,
+						  code->which);
+		code->code = fmt->code;
+		return 0;
+	}
+
+	if (code->index >= cal_num_formats)
+		return -EINVAL;
+
+	code->code = cal_formats[code->index].code;
+
+	return 0;
+}
+
+static int cal_camerarx_sd_enum_frame_size(struct v4l2_subdev *sd,
+					   struct v4l2_subdev_pad_config *cfg,
+					   struct v4l2_subdev_frame_size_enum *fse)
+{
+	struct cal_camerarx *phy = to_cal_camerarx(sd);
+	const struct cal_fmt *fmtinfo;
+
+	if (fse->index > 0)
+		return -EINVAL;
+
+	/* No transcoding, source and sink formats must match. */
+	if (fse->pad == CAL_CAMERARX_PAD_SOURCE) {
+		struct v4l2_mbus_framefmt *fmt;
+
+		fmt = cal_camerarx_get_pad_format(phy, cfg,
+						  CAL_CAMERARX_PAD_SINK,
+						  fse->which);
+		if (fse->code != fmt->code)
+			return -EINVAL;
+
+		fse->min_width = fmt->width;
+		fse->max_width = fmt->width;
+		fse->min_height = fmt->height;
+		fse->max_height = fmt->height;
+
+		return 0;
+	}
+
+	fmtinfo = cal_format_by_code(fse->code);
+	if (!fmtinfo)
+		return -EINVAL;
+
+	fse->min_width = CAL_MIN_WIDTH_BYTES * 8 / ALIGN(fmtinfo->bpp, 8);
+	fse->max_width = CAL_MAX_WIDTH_BYTES * 8 / ALIGN(fmtinfo->bpp, 8);
+	fse->min_height = CAL_MIN_HEIGHT_LINES;
+	fse->max_height = CAL_MAX_HEIGHT_LINES;
+
+	return 0;
+}
+
+static int cal_camerarx_sd_get_fmt(struct v4l2_subdev *sd,
+				   struct v4l2_subdev_pad_config *cfg,
+				   struct v4l2_subdev_format *format)
+{
+	struct cal_camerarx *phy = to_cal_camerarx(sd);
+	struct v4l2_mbus_framefmt *fmt;
+
+	fmt = cal_camerarx_get_pad_format(phy, cfg, format->pad, format->which);
+	format->format = *fmt;
+
+	return 0;
+}
+
+static int cal_camerarx_sd_set_fmt(struct v4l2_subdev *sd,
+				   struct v4l2_subdev_pad_config *cfg,
+				   struct v4l2_subdev_format *format)
+{
+	struct cal_camerarx *phy = to_cal_camerarx(sd);
+	const struct cal_fmt *fmtinfo;
+	struct v4l2_mbus_framefmt *fmt;
+	unsigned int bpp;
+
+	/* No transcoding, source and sink formats must match. */
+	if (format->pad == CAL_CAMERARX_PAD_SOURCE)
+		return cal_camerarx_sd_get_fmt(sd, cfg, format);
+
+	/*
+	 * Default to the first format is the requested media bus code isn't
+	 * supported.
+	 */
+	fmtinfo = cal_format_by_code(format->format.code);
+	if (!fmtinfo)
+		fmtinfo = &cal_formats[0];
+
+	/*
+	 * Clamp the size, update the code. The field and colorspace are
+	 * accepted as-is.
+	 */
+	bpp = ALIGN(fmtinfo->bpp, 8);
+
+	format->format.width = clamp_t(unsigned int, format->format.width,
+				       CAL_MIN_WIDTH_BYTES * 8 / bpp,
+				       CAL_MAX_WIDTH_BYTES * 8 / bpp);
+	format->format.height = clamp_t(unsigned int, format->format.height,
+					CAL_MIN_HEIGHT_LINES,
+					CAL_MAX_HEIGHT_LINES);
+	format->format.code = fmtinfo->code;
+
+	/* Store the format and propagate it to the source pad. */
+	fmt = cal_camerarx_get_pad_format(phy, cfg, CAL_CAMERARX_PAD_SINK,
+					  format->which);
+	*fmt = format->format;
+
+	fmt = cal_camerarx_get_pad_format(phy, cfg, CAL_CAMERARX_PAD_SOURCE,
+					  format->which);
+	*fmt = format->format;
+
+	if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE)
+		phy->fmtinfo = fmtinfo;
+
+	return 0;
+}
+
+static int cal_camerarx_sd_init_cfg(struct v4l2_subdev *sd,
+				    struct v4l2_subdev_pad_config *cfg)
+{
+	struct v4l2_subdev_format format = {
+		.which = cfg ? V4L2_SUBDEV_FORMAT_TRY
+		       : V4L2_SUBDEV_FORMAT_ACTIVE,
+		.pad = CAL_CAMERARX_PAD_SINK,
+		.format = {
+			.width = 640,
+			.height = 480,
+			.code = MEDIA_BUS_FMT_UYVY8_2X8,
+			.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 cal_camerarx_sd_set_fmt(sd, cfg, &format);
+}
+
+static const struct v4l2_subdev_video_ops cal_camerarx_video_ops = {
+	.s_stream = cal_camerarx_sd_s_stream,
+};
+
+static const struct v4l2_subdev_pad_ops cal_camerarx_pad_ops = {
+	.init_cfg = cal_camerarx_sd_init_cfg,
+	.enum_mbus_code = cal_camerarx_sd_enum_mbus_code,
+	.enum_frame_size = cal_camerarx_sd_enum_frame_size,
+	.get_fmt = cal_camerarx_sd_get_fmt,
+	.set_fmt = cal_camerarx_sd_set_fmt,
+};
+
 static const struct v4l2_subdev_ops cal_camerarx_subdev_ops = {
+	.video = &cal_camerarx_video_ops,
+	.pad = &cal_camerarx_pad_ops,
+};
+
+struct media_entity_operations cal_camerarx_media_ops = {
+	.link_validate = v4l2_subdev_link_validate,
 };
 
 /* ------------------------------------------------------------------
@@ -646,11 +848,14 @@ struct cal_camerarx *cal_camerarx_create(struct cal_dev *cal,
 
 	phy->pads[CAL_CAMERARX_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
 	phy->pads[CAL_CAMERARX_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
+	sd->entity.ops = &cal_camerarx_media_ops;
 	ret = media_entity_pads_init(&sd->entity, ARRAY_SIZE(phy->pads),
 				     phy->pads);
 	if (ret)
 		goto error;
 
+	cal_camerarx_sd_init_cfg(sd, NULL);
+
 	ret = v4l2_device_register_subdev(&cal->v4l2_dev, sd);
 	if (ret)
 		goto error;
diff --git a/drivers/media/platform/ti-vpe/cal.h b/drivers/media/platform/ti-vpe/cal.h
index 7356d01e8d73..c7b3941ffd1b 100644
--- a/drivers/media/platform/ti-vpe/cal.h
+++ b/drivers/media/platform/ti-vpe/cal.h
@@ -125,6 +125,8 @@ struct cal_camerarx {
 
 	struct v4l2_subdev	subdev;
 	struct media_pad	pads[2];
+	struct v4l2_mbus_framefmt	formats[2];
+	const struct cal_fmt	*fmtinfo;
 };
 
 struct cal_dev {
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 091/107] media: ti-vpe: cal: Use CAMERARX subdev s_stream op in video device code
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (89 preceding siblings ...)
  2020-06-14 23:59 ` [PATCH v1 090/107] media: ti-vpe: cal: Implement subdev ops for CAMERARX Laurent Pinchart
@ 2020-06-14 23:59 ` Laurent Pinchart
  2020-06-14 23:59 ` [PATCH v1 092/107] media: ti-vpe: cal: Don't pass format to cal_ctx_wr_dma_config() Laurent Pinchart
                   ` (17 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:59 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

Replace calls to cal_camerarx_start() and cal_camerarx_stop() with usage
of the .s_stream() subdev operation. This requires calling the
.set_fmt() operation as the CAMERARX now relies on the format
information set through the subdev API instead of receiving it in the
cal_camerarx_start() function.

This change prepare for exposing the CAMERARX subdev operations to
userspace by using the same API within the kernel.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal-camerarx.c | 13 +++++-----
 drivers/media/platform/ti-vpe/cal-video.c    | 25 +++++++++++---------
 drivers/media/platform/ti-vpe/cal.h          |  2 --
 3 files changed, 20 insertions(+), 20 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal-camerarx.c b/drivers/media/platform/ti-vpe/cal-camerarx.c
index a7f17ecfbd90..70940bfa31dc 100644
--- a/drivers/media/platform/ti-vpe/cal-camerarx.c
+++ b/drivers/media/platform/ti-vpe/cal-camerarx.c
@@ -116,8 +116,7 @@ void cal_camerarx_disable(struct cal_camerarx *phy)
 #define TCLK_MISS	1
 #define TCLK_SETTLE	14
 
-static void cal_camerarx_config(struct cal_camerarx *phy, s64 external_rate,
-				const struct cal_fmt *fmt)
+static void cal_camerarx_config(struct cal_camerarx *phy, s64 external_rate)
 {
 	unsigned int reg0, reg1;
 	unsigned int ths_term, ths_settle;
@@ -129,7 +128,7 @@ static void cal_camerarx_config(struct cal_camerarx *phy, s64 external_rate,
 	/* DPHY timing configuration */
 	/* CSI-2 is DDR and we only count used lanes. */
 	csi2_ddrclk_khz = external_rate / 1000
-		/ (2 * num_lanes) * fmt->bpp;
+		/ (2 * num_lanes) * phy->fmtinfo->bpp;
 	phy_dbg(1, phy, "csi2_ddrclk_khz: %d\n", csi2_ddrclk_khz);
 
 	/* THS_TERM: Programmed value = floor(20 ns/DDRClk period) */
@@ -227,7 +226,7 @@ static void cal_camerarx_wait_stop_state(struct cal_camerarx *phy)
 		phy_err(phy, "Timeout waiting for stop state\n");
 }
 
-int cal_camerarx_start(struct cal_camerarx *phy, const struct cal_fmt *fmt)
+static int cal_camerarx_start(struct cal_camerarx *phy)
 {
 	s64 external_rate;
 	u32 sscounter;
@@ -282,7 +281,7 @@ int cal_camerarx_start(struct cal_camerarx *phy, const struct cal_fmt *fmt)
 	camerarx_read(phy, CAL_CSI2_PHY_REG0);
 
 	/* Program the PHY timing parameters. */
-	cal_camerarx_config(phy, external_rate, fmt);
+	cal_camerarx_config(phy, external_rate);
 
 	/*
 	 *    b. Assert the FORCERXMODE signal.
@@ -355,7 +354,7 @@ int cal_camerarx_start(struct cal_camerarx *phy, const struct cal_fmt *fmt)
 	return 0;
 }
 
-void cal_camerarx_stop(struct cal_camerarx *phy)
+static void cal_camerarx_stop(struct cal_camerarx *phy)
 {
 	unsigned int i;
 	int ret;
@@ -617,7 +616,7 @@ static int cal_camerarx_sd_s_stream(struct v4l2_subdev *sd, int enable)
 	struct cal_camerarx *phy = to_cal_camerarx(sd);
 
 	if (enable)
-		return cal_camerarx_start(phy, NULL);
+		return cal_camerarx_start(phy);
 
 	cal_camerarx_stop(phy);
 	return 0;
diff --git a/drivers/media/platform/ti-vpe/cal-video.c b/drivers/media/platform/ti-vpe/cal-video.c
index 42e750925e8b..1ada27d42da1 100644
--- a/drivers/media/platform/ti-vpe/cal-video.c
+++ b/drivers/media/platform/ti-vpe/cal-video.c
@@ -256,8 +256,11 @@ static int cal_s_fmt_vid_cap(struct file *file, void *priv,
 {
 	struct cal_ctx *ctx = video_drvdata(file);
 	struct vb2_queue *q = &ctx->vb_vidq;
+	struct v4l2_subdev_format sd_fmt = {
+		.which = V4L2_SUBDEV_FORMAT_ACTIVE,
+		.pad = CAL_CAMERARX_PAD_SINK,
+	};
 	const struct cal_fmt *fmt;
-	struct v4l2_mbus_framefmt mbus_fmt;
 	int ret;
 
 	if (vb2_is_busy(q)) {
@@ -271,25 +274,28 @@ static int cal_s_fmt_vid_cap(struct file *file, void *priv,
 
 	fmt = find_format_by_pix(ctx, f->fmt.pix.pixelformat);
 
-	v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, fmt->code);
+	v4l2_fill_mbus_format(&sd_fmt.format, &f->fmt.pix, fmt->code);
 
-	ret = __subdev_set_format(ctx, &mbus_fmt);
+	ret = __subdev_set_format(ctx, &sd_fmt.format);
 	if (ret)
 		return ret;
 
 	/* Just double check nothing has gone wrong */
-	if (mbus_fmt.code != fmt->code) {
+	if (sd_fmt.format.code != fmt->code) {
 		ctx_dbg(3, ctx,
 			"%s subdev changed format on us, this should not happen\n",
 			__func__);
 		return -EINVAL;
 	}
 
-	v4l2_fill_pix_format(&ctx->v_fmt.fmt.pix, &mbus_fmt);
+	v4l2_fill_pix_format(&ctx->v_fmt.fmt.pix, &sd_fmt.format);
 	ctx->v_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 	ctx->v_fmt.fmt.pix.pixelformat = fmt->fourcc;
-	ctx->v_fmt.fmt.pix.field = mbus_fmt.field;
+	ctx->v_fmt.fmt.pix.field = sd_fmt.format.field;
 	cal_calc_format_size(ctx, fmt, &ctx->v_fmt);
+
+	v4l2_subdev_call(&ctx->phy->subdev, pad, set_fmt, NULL, &sd_fmt);
+
 	ctx->fmt = fmt;
 	*f = ctx->v_fmt;
 
@@ -455,9 +461,6 @@ static int cal_buffer_prepare(struct vb2_buffer *vb)
 					      vb.vb2_buf);
 	unsigned long size;
 
-	if (WARN_ON(!ctx->fmt))
-		return -EINVAL;
-
 	size = ctx->v_fmt.fmt.pix.sizeimage;
 	if (vb2_plane_size(vb, 0) < size) {
 		ctx_err(ctx,
@@ -518,7 +521,7 @@ static int cal_start_streaming(struct vb2_queue *vq, unsigned int count)
 
 	cal_camerarx_enable_irqs(ctx->phy);
 
-	ret = cal_camerarx_start(ctx->phy, ctx->fmt);
+	ret = v4l2_subdev_call(&ctx->phy->subdev, video, s_stream, 1);
 	if (ret)
 		goto err;
 
@@ -569,7 +572,7 @@ static void cal_stop_streaming(struct vb2_queue *vq)
 		ctx_err(ctx, "failed to disable dma cleanly\n");
 
 	cal_camerarx_disable_irqs(ctx->phy);
-	cal_camerarx_stop(ctx->phy);
+	v4l2_subdev_call(&ctx->phy->subdev, video, s_stream, 0);
 
 	/* Release all active buffers */
 	spin_lock_irqsave(&ctx->slock, flags);
diff --git a/drivers/media/platform/ti-vpe/cal.h b/drivers/media/platform/ti-vpe/cal.h
index c7b3941ffd1b..66168f8fe724 100644
--- a/drivers/media/platform/ti-vpe/cal.h
+++ b/drivers/media/platform/ti-vpe/cal.h
@@ -262,8 +262,6 @@ const struct cal_fmt *cal_format_by_code(u32 code);
 void cal_quickdump_regs(struct cal_dev *cal);
 
 void cal_camerarx_disable(struct cal_camerarx *phy);
-int cal_camerarx_start(struct cal_camerarx *phy, const struct cal_fmt *fmt);
-void cal_camerarx_stop(struct cal_camerarx *phy);
 void cal_camerarx_enable_irqs(struct cal_camerarx *phy);
 void cal_camerarx_disable_irqs(struct cal_camerarx *phy);
 void cal_camerarx_ppi_enable(struct cal_camerarx *phy);
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 092/107] media: ti-vpe: cal: Don't pass format to cal_ctx_wr_dma_config()
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (90 preceding siblings ...)
  2020-06-14 23:59 ` [PATCH v1 091/107] media: ti-vpe: cal: Use CAMERARX subdev s_stream op in video device code Laurent Pinchart
@ 2020-06-14 23:59 ` Laurent Pinchart
  2020-06-14 23:59 ` [PATCH v1 093/107] media: ti-vpe: cal: Rename struct cal_fmt to cal_format_info Laurent Pinchart
                   ` (16 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:59 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

The cal_ctx_wr_dma_config() function has access to the context, there's
no need to give it format-related values retrieved from the context.
Access the values internally, and reword internal comments. The comment
regarding the CAL_WR_DMA_OFST register not being well understood is
dropped, as the datasheet explicitly documents it as "Offset between two
consecutive line starts".

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal-video.c |  3 +--
 drivers/media/platform/ti-vpe/cal.c       | 25 +++++++++--------------
 drivers/media/platform/ti-vpe/cal.h       |  3 +--
 3 files changed, 12 insertions(+), 19 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal-video.c b/drivers/media/platform/ti-vpe/cal-video.c
index 1ada27d42da1..083389635269 100644
--- a/drivers/media/platform/ti-vpe/cal-video.c
+++ b/drivers/media/platform/ti-vpe/cal-video.c
@@ -516,8 +516,7 @@ static int cal_start_streaming(struct vb2_queue *vq, unsigned int count)
 
 	cal_ctx_csi2_config(ctx);
 	cal_ctx_pix_proc_config(ctx);
-	cal_ctx_wr_dma_config(ctx, ctx->v_fmt.fmt.pix.bytesperline,
-			      ctx->v_fmt.fmt.pix.height);
+	cal_ctx_wr_dma_config(ctx);
 
 	cal_camerarx_enable_irqs(ctx->phy);
 
diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index ad6e8a1e352b..860e393f3d21 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -356,14 +356,15 @@ void cal_ctx_pix_proc_config(struct cal_ctx *ctx)
 		cal_read(ctx->cal, CAL_PIX_PROC(ctx->index)));
 }
 
-void cal_ctx_wr_dma_config(struct cal_ctx *ctx, unsigned int width,
-			    unsigned int height)
+void cal_ctx_wr_dma_config(struct cal_ctx *ctx)
 {
+	unsigned int stride = ctx->v_fmt.fmt.pix.bytesperline;
 	u32 val;
 
 	val = cal_read(ctx->cal, CAL_WR_DMA_CTRL(ctx->index));
 	cal_set_field(&val, ctx->cport, CAL_WR_DMA_CTRL_CPORT_MASK);
-	cal_set_field(&val, height, CAL_WR_DMA_CTRL_YSIZE_MASK);
+	cal_set_field(&val, ctx->v_fmt.fmt.pix.height,
+		      CAL_WR_DMA_CTRL_YSIZE_MASK);
 	cal_set_field(&val, CAL_WR_DMA_CTRL_DTAG_PIX_DAT,
 		      CAL_WR_DMA_CTRL_DTAG_MASK);
 	cal_set_field(&val, CAL_WR_DMA_CTRL_MODE_CONST,
@@ -375,14 +376,8 @@ void cal_ctx_wr_dma_config(struct cal_ctx *ctx, unsigned int width,
 	ctx_dbg(3, ctx, "CAL_WR_DMA_CTRL(%d) = 0x%08x\n", ctx->index,
 		cal_read(ctx->cal, CAL_WR_DMA_CTRL(ctx->index)));
 
-	/*
-	 * width/16 not sure but giving it a whirl.
-	 * zero does not work right
-	 */
-	cal_write_field(ctx->cal,
-			CAL_WR_DMA_OFST(ctx->index),
-			(width / 16),
-			CAL_WR_DMA_OFST_MASK);
+	cal_write_field(ctx->cal, CAL_WR_DMA_OFST(ctx->index),
+			stride / 16, CAL_WR_DMA_OFST_MASK);
 	ctx_dbg(3, ctx, "CAL_WR_DMA_OFST(%d) = 0x%08x\n", ctx->index,
 		cal_read(ctx->cal, CAL_WR_DMA_OFST(ctx->index)));
 
@@ -390,11 +385,11 @@ void cal_ctx_wr_dma_config(struct cal_ctx *ctx, unsigned int width,
 	/* 64 bit word means no skipping */
 	cal_set_field(&val, 0, CAL_WR_DMA_XSIZE_XSKIP_MASK);
 	/*
-	 * (width*8)/64 this should be size of an entire line
-	 * in 64bit word but 0 means all data until the end
-	 * is detected automagically
+	 * The XSIZE field is expressed in 64-bit units and prevents overflows
+	 * in case of synchronization issues by limiting the number of bytes
+	 * written per line.
 	 */
-	cal_set_field(&val, (width / 8), CAL_WR_DMA_XSIZE_MASK);
+	cal_set_field(&val, stride / 8, CAL_WR_DMA_XSIZE_MASK);
 	cal_write(ctx->cal, CAL_WR_DMA_XSIZE(ctx->index), val);
 	ctx_dbg(3, ctx, "CAL_WR_DMA_XSIZE(%d) = 0x%08x\n", ctx->index,
 		cal_read(ctx->cal, CAL_WR_DMA_XSIZE(ctx->index)));
diff --git a/drivers/media/platform/ti-vpe/cal.h b/drivers/media/platform/ti-vpe/cal.h
index 66168f8fe724..2fcd5ba2da28 100644
--- a/drivers/media/platform/ti-vpe/cal.h
+++ b/drivers/media/platform/ti-vpe/cal.h
@@ -273,8 +273,7 @@ void cal_camerarx_destroy(struct cal_camerarx *phy);
 
 void cal_ctx_csi2_config(struct cal_ctx *ctx);
 void cal_ctx_pix_proc_config(struct cal_ctx *ctx);
-void cal_ctx_wr_dma_config(struct cal_ctx *ctx, unsigned int width,
-			   unsigned int height);
+void cal_ctx_wr_dma_config(struct cal_ctx *ctx);
 void cal_ctx_wr_dma_addr(struct cal_ctx *ctx, unsigned int dmaaddr);
 
 int cal_ctx_v4l2_register(struct cal_ctx *ctx);
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 093/107] media: ti-vpe: cal: Rename struct cal_fmt to cal_format_info
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (91 preceding siblings ...)
  2020-06-14 23:59 ` [PATCH v1 092/107] media: ti-vpe: cal: Don't pass format to cal_ctx_wr_dma_config() Laurent Pinchart
@ 2020-06-14 23:59 ` Laurent Pinchart
  2020-06-14 23:59 ` [PATCH v1 094/107] media: ti-vpe: cal: Refactor interrupt enable/disable Laurent Pinchart
                   ` (15 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:59 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

The cal_fmt structure stores information about a format. Its name is
ambiguous, as it could be understood as storing a format. Furthermore,
instances of the structure are called 'fmt' through the code, which
leads to confusion with the 'format' variables. Rename the structure to
cal_format_info, and the corresponding 'fmt' variables to 'fmtinfo'.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal-camerarx.c |   4 +-
 drivers/media/platform/ti-vpe/cal-video.c    | 104 +++++++++----------
 drivers/media/platform/ti-vpe/cal.c          |  10 +-
 drivers/media/platform/ti-vpe/cal.h          |  14 +--
 4 files changed, 66 insertions(+), 66 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal-camerarx.c b/drivers/media/platform/ti-vpe/cal-camerarx.c
index 70940bfa31dc..3f33079fcfd1 100644
--- a/drivers/media/platform/ti-vpe/cal-camerarx.c
+++ b/drivers/media/platform/ti-vpe/cal-camerarx.c
@@ -655,7 +655,7 @@ static int cal_camerarx_sd_enum_frame_size(struct v4l2_subdev *sd,
 					   struct v4l2_subdev_frame_size_enum *fse)
 {
 	struct cal_camerarx *phy = to_cal_camerarx(sd);
-	const struct cal_fmt *fmtinfo;
+	const struct cal_format_info *fmtinfo;
 
 	if (fse->index > 0)
 		return -EINVAL;
@@ -708,7 +708,7 @@ static int cal_camerarx_sd_set_fmt(struct v4l2_subdev *sd,
 				   struct v4l2_subdev_format *format)
 {
 	struct cal_camerarx *phy = to_cal_camerarx(sd);
-	const struct cal_fmt *fmtinfo;
+	const struct cal_format_info *fmtinfo;
 	struct v4l2_mbus_framefmt *fmt;
 	unsigned int bpp;
 
diff --git a/drivers/media/platform/ti-vpe/cal-video.c b/drivers/media/platform/ti-vpe/cal-video.c
index 083389635269..e7ad0b93fc59 100644
--- a/drivers/media/platform/ti-vpe/cal-video.c
+++ b/drivers/media/platform/ti-vpe/cal-video.c
@@ -45,31 +45,31 @@ static char *fourcc_to_str(u32 fmt)
  * ------------------------------------------------------------------
  */
 
-static const struct cal_fmt *find_format_by_pix(struct cal_ctx *ctx,
-						u32 pixelformat)
+static const struct cal_format_info *find_format_by_pix(struct cal_ctx *ctx,
+							u32 pixelformat)
 {
-	const struct cal_fmt *fmt;
+	const struct cal_format_info *fmtinfo;
 	unsigned int k;
 
 	for (k = 0; k < ctx->num_active_fmt; k++) {
-		fmt = ctx->active_fmt[k];
-		if (fmt->fourcc == pixelformat)
-			return fmt;
+		fmtinfo = ctx->active_fmt[k];
+		if (fmtinfo->fourcc == pixelformat)
+			return fmtinfo;
 	}
 
 	return NULL;
 }
 
-static const struct cal_fmt *find_format_by_code(struct cal_ctx *ctx,
-						 u32 code)
+static const struct cal_format_info *find_format_by_code(struct cal_ctx *ctx,
+							 u32 code)
 {
-	const struct cal_fmt *fmt;
+	const struct cal_format_info *fmtinfo;
 	unsigned int k;
 
 	for (k = 0; k < ctx->num_active_fmt; k++) {
-		fmt = ctx->active_fmt[k];
-		if (fmt->code == code)
-			return fmt;
+		fmtinfo = ctx->active_fmt[k];
+		if (fmtinfo->code == code)
+			return fmtinfo;
 	}
 
 	return NULL;
@@ -92,14 +92,14 @@ static int cal_enum_fmt_vid_cap(struct file *file, void  *priv,
 				struct v4l2_fmtdesc *f)
 {
 	struct cal_ctx *ctx = video_drvdata(file);
-	const struct cal_fmt *fmt;
+	const struct cal_format_info *fmtinfo;
 
 	if (f->index >= ctx->num_active_fmt)
 		return -EINVAL;
 
-	fmt = ctx->active_fmt[f->index];
+	fmtinfo = ctx->active_fmt[f->index];
 
-	f->pixelformat = fmt->fourcc;
+	f->pixelformat = fmtinfo->fourcc;
 	f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 	return 0;
 }
@@ -148,12 +148,12 @@ static int __subdev_set_format(struct cal_ctx *ctx,
 }
 
 static int cal_calc_format_size(struct cal_ctx *ctx,
-				const struct cal_fmt *fmt,
+				const struct cal_format_info *fmtinfo,
 				struct v4l2_format *f)
 {
 	u32 bpl, max_width;
 
-	if (!fmt) {
+	if (!fmtinfo) {
 		ctx_dbg(3, ctx, "No cal_fmt provided!\n");
 		return -EINVAL;
 	}
@@ -163,12 +163,12 @@ static int cal_calc_format_size(struct cal_ctx *ctx,
 	 * We need to recalculate the actual maxi width depending on the
 	 * number of bytes per pixels required.
 	 */
-	max_width = CAL_MAX_WIDTH_BYTES / (ALIGN(fmt->bpp, 8) >> 3);
+	max_width = CAL_MAX_WIDTH_BYTES / (ALIGN(fmtinfo->bpp, 8) >> 3);
 	v4l_bound_align_image(&f->fmt.pix.width, 48, max_width, 2,
 			      &f->fmt.pix.height, 32, CAL_MAX_HEIGHT_LINES,
 			      0, 0);
 
-	bpl = (f->fmt.pix.width * ALIGN(fmt->bpp, 8)) >> 3;
+	bpl = (f->fmt.pix.width * ALIGN(fmtinfo->bpp, 8)) >> 3;
 	f->fmt.pix.bytesperline = ALIGN(bpl, 16);
 
 	f->fmt.pix.sizeimage = f->fmt.pix.height *
@@ -196,18 +196,18 @@ static int cal_try_fmt_vid_cap(struct file *file, void *priv,
 			       struct v4l2_format *f)
 {
 	struct cal_ctx *ctx = video_drvdata(file);
-	const struct cal_fmt *fmt;
+	const struct cal_format_info *fmtinfo;
 	struct v4l2_subdev_frame_size_enum fse;
 	int ret, found;
 
-	fmt = find_format_by_pix(ctx, f->fmt.pix.pixelformat);
-	if (!fmt) {
+	fmtinfo = find_format_by_pix(ctx, f->fmt.pix.pixelformat);
+	if (!fmtinfo) {
 		ctx_dbg(3, ctx, "Fourcc format (0x%08x) not found.\n",
 			f->fmt.pix.pixelformat);
 
 		/* Just get the first one enumerated */
-		fmt = ctx->active_fmt[0];
-		f->fmt.pix.pixelformat = fmt->fourcc;
+		fmtinfo = ctx->active_fmt[0];
+		f->fmt.pix.pixelformat = fmtinfo->fourcc;
 	}
 
 	f->fmt.pix.field = ctx->v_fmt.fmt.pix.field;
@@ -216,7 +216,7 @@ static int cal_try_fmt_vid_cap(struct file *file, void *priv,
 	ret = 0;
 	found = false;
 	fse.pad = 0;
-	fse.code = fmt->code;
+	fse.code = fmtinfo->code;
 	fse.which = V4L2_SUBDEV_FORMAT_ACTIVE;
 	for (fse.index = 0; ; fse.index++) {
 		ret = v4l2_subdev_call(ctx->phy->sensor, pad, enum_frame_size,
@@ -248,7 +248,7 @@ static int cal_try_fmt_vid_cap(struct file *file, void *priv,
 	 * updated properly during s_fmt
 	 */
 	f->fmt.pix.colorspace = ctx->v_fmt.fmt.pix.colorspace;
-	return cal_calc_format_size(ctx, fmt, f);
+	return cal_calc_format_size(ctx, fmtinfo, f);
 }
 
 static int cal_s_fmt_vid_cap(struct file *file, void *priv,
@@ -260,7 +260,7 @@ static int cal_s_fmt_vid_cap(struct file *file, void *priv,
 		.which = V4L2_SUBDEV_FORMAT_ACTIVE,
 		.pad = CAL_CAMERARX_PAD_SINK,
 	};
-	const struct cal_fmt *fmt;
+	const struct cal_format_info *fmtinfo;
 	int ret;
 
 	if (vb2_is_busy(q)) {
@@ -272,16 +272,16 @@ static int cal_s_fmt_vid_cap(struct file *file, void *priv,
 	if (ret < 0)
 		return ret;
 
-	fmt = find_format_by_pix(ctx, f->fmt.pix.pixelformat);
+	fmtinfo = find_format_by_pix(ctx, f->fmt.pix.pixelformat);
 
-	v4l2_fill_mbus_format(&sd_fmt.format, &f->fmt.pix, fmt->code);
+	v4l2_fill_mbus_format(&sd_fmt.format, &f->fmt.pix, fmtinfo->code);
 
 	ret = __subdev_set_format(ctx, &sd_fmt.format);
 	if (ret)
 		return ret;
 
 	/* Just double check nothing has gone wrong */
-	if (sd_fmt.format.code != fmt->code) {
+	if (sd_fmt.format.code != fmtinfo->code) {
 		ctx_dbg(3, ctx,
 			"%s subdev changed format on us, this should not happen\n",
 			__func__);
@@ -290,13 +290,13 @@ static int cal_s_fmt_vid_cap(struct file *file, void *priv,
 
 	v4l2_fill_pix_format(&ctx->v_fmt.fmt.pix, &sd_fmt.format);
 	ctx->v_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-	ctx->v_fmt.fmt.pix.pixelformat = fmt->fourcc;
+	ctx->v_fmt.fmt.pix.pixelformat = fmtinfo->fourcc;
 	ctx->v_fmt.fmt.pix.field = sd_fmt.format.field;
-	cal_calc_format_size(ctx, fmt, &ctx->v_fmt);
+	cal_calc_format_size(ctx, fmtinfo, &ctx->v_fmt);
 
 	v4l2_subdev_call(&ctx->phy->subdev, pad, set_fmt, NULL, &sd_fmt);
 
-	ctx->fmt = fmt;
+	ctx->fmtinfo = fmtinfo;
 	*f = ctx->v_fmt;
 
 	return 0;
@@ -306,13 +306,13 @@ static int cal_enum_framesizes(struct file *file, void *fh,
 			       struct v4l2_frmsizeenum *fsize)
 {
 	struct cal_ctx *ctx = video_drvdata(file);
-	const struct cal_fmt *fmt;
+	const struct cal_format_info *fmtinfo;
 	struct v4l2_subdev_frame_size_enum fse;
 	int ret;
 
 	/* check for valid format */
-	fmt = find_format_by_pix(ctx, fsize->pixel_format);
-	if (!fmt) {
+	fmtinfo = find_format_by_pix(ctx, fsize->pixel_format);
+	if (!fmtinfo) {
 		ctx_dbg(3, ctx, "Invalid pixel code: %x\n",
 			fsize->pixel_format);
 		return -EINVAL;
@@ -320,7 +320,7 @@ static int cal_enum_framesizes(struct file *file, void *fh,
 
 	fse.index = fsize->index;
 	fse.pad = 0;
-	fse.code = fmt->code;
+	fse.code = fmtinfo->code;
 	fse.which = V4L2_SUBDEV_FORMAT_ACTIVE;
 
 	ret = v4l2_subdev_call(ctx->phy->sensor, pad, enum_frame_size, NULL,
@@ -366,7 +366,7 @@ static int cal_enum_frameintervals(struct file *file, void *priv,
 				   struct v4l2_frmivalenum *fival)
 {
 	struct cal_ctx *ctx = video_drvdata(file);
-	const struct cal_fmt *fmt;
+	const struct cal_format_info *fmtinfo;
 	struct v4l2_subdev_frame_interval_enum fie = {
 		.index = fival->index,
 		.width = fival->width,
@@ -375,11 +375,11 @@ static int cal_enum_frameintervals(struct file *file, void *priv,
 	};
 	int ret;
 
-	fmt = find_format_by_pix(ctx, fival->pixel_format);
-	if (!fmt)
+	fmtinfo = find_format_by_pix(ctx, fival->pixel_format);
+	if (!fmtinfo)
 		return -EINVAL;
 
-	fie.code = fmt->code;
+	fie.code = fmtinfo->code;
 	ret = v4l2_subdev_call(ctx->phy->sensor, pad, enum_frame_interval,
 			       NULL, &fie);
 	if (ret)
@@ -623,7 +623,7 @@ static int cal_ctx_v4l2_init_formats(struct cal_ctx *ctx)
 {
 	struct v4l2_subdev_mbus_code_enum mbus_code;
 	struct v4l2_mbus_framefmt mbus_fmt;
-	const struct cal_fmt *fmt;
+	const struct cal_format_info *fmtinfo;
 	unsigned int i, j, k;
 	int ret = 0;
 
@@ -647,14 +647,14 @@ static int cal_ctx_v4l2_init_formats(struct cal_ctx *ctx)
 			ctx->phy->sensor->name, mbus_code.code, j);
 
 		for (k = 0; k < cal_num_formats; k++) {
-			const struct cal_fmt *fmt = &cal_formats[k];
+			fmtinfo = &cal_formats[k];
 
-			if (mbus_code.code == fmt->code) {
-				ctx->active_fmt[i] = fmt;
+			if (mbus_code.code == fmtinfo->code) {
+				ctx->active_fmt[i] = fmtinfo;
 				ctx_dbg(2, ctx,
 					"matched fourcc: %s: code: %04x idx: %u\n",
-					fourcc_to_str(fmt->fourcc),
-					fmt->code, i);
+					fourcc_to_str(fmtinfo->fourcc),
+					fmtinfo->code, i);
 				ctx->num_active_fmt = ++i;
 			}
 		}
@@ -670,8 +670,8 @@ static int cal_ctx_v4l2_init_formats(struct cal_ctx *ctx)
 	if (ret)
 		return ret;
 
-	fmt = find_format_by_code(ctx, mbus_fmt.code);
-	if (!fmt) {
+	fmtinfo = find_format_by_code(ctx, mbus_fmt.code);
+	if (!fmtinfo) {
 		ctx_dbg(3, ctx, "mbus code format (0x%08x) not found.\n",
 			mbus_fmt.code);
 		return -EINVAL;
@@ -680,10 +680,10 @@ static int cal_ctx_v4l2_init_formats(struct cal_ctx *ctx)
 	/* Save current format */
 	v4l2_fill_pix_format(&ctx->v_fmt.fmt.pix, &mbus_fmt);
 	ctx->v_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-	ctx->v_fmt.fmt.pix.pixelformat = fmt->fourcc;
+	ctx->v_fmt.fmt.pix.pixelformat = fmtinfo->fourcc;
 	ctx->v_fmt.fmt.pix.field = mbus_fmt.field;
-	cal_calc_format_size(ctx, fmt, &ctx->v_fmt);
-	ctx->fmt = fmt;
+	cal_calc_format_size(ctx, fmtinfo, &ctx->v_fmt);
+	ctx->fmtinfo = fmtinfo;
 
 	return 0;
 }
diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index 860e393f3d21..15f578b18d72 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -48,7 +48,7 @@ MODULE_PARM_DESC(debug, "activates debug info");
  * ------------------------------------------------------------------
  */
 
-const struct cal_fmt cal_formats[] = {
+const struct cal_format_info cal_formats[] = {
 	{
 		.fourcc		= V4L2_PIX_FMT_YUYV,
 		.code		= MEDIA_BUS_FMT_YUYV8_2X8,
@@ -146,7 +146,7 @@ const struct cal_fmt cal_formats[] = {
 
 const unsigned int cal_num_formats = ARRAY_SIZE(cal_formats);
 
-const struct cal_fmt *cal_format_by_fourcc(u32 fourcc)
+const struct cal_format_info *cal_format_by_fourcc(u32 fourcc)
 {
 	unsigned int i;
 
@@ -158,7 +158,7 @@ const struct cal_fmt *cal_format_by_fourcc(u32 fourcc)
 	return NULL;
 }
 
-const struct cal_fmt *cal_format_by_code(u32 code)
+const struct cal_format_info *cal_format_by_code(u32 code)
 {
 	unsigned int i;
 
@@ -309,7 +309,7 @@ void cal_ctx_pix_proc_config(struct cal_ctx *ctx)
 {
 	u32 val, extract, pack;
 
-	switch (ctx->fmt->bpp) {
+	switch (ctx->fmtinfo->bpp) {
 	case 8:
 		extract = CAL_PIX_PROC_EXTRACT_B8;
 		pack = CAL_PIX_PROC_PACK_B8;
@@ -338,7 +338,7 @@ void cal_ctx_pix_proc_config(struct cal_ctx *ctx)
 		 */
 		dev_warn_once(ctx->cal->dev,
 			      "%s:%d:%s: bpp:%d unsupported! Overwritten with 8.\n",
-			      __FILE__, __LINE__, __func__, ctx->fmt->bpp);
+			      __FILE__, __LINE__, __func__, ctx->fmtinfo->bpp);
 		extract = CAL_PIX_PROC_EXTRACT_B8;
 		pack = CAL_PIX_PROC_PACK_B8;
 		break;
diff --git a/drivers/media/platform/ti-vpe/cal.h b/drivers/media/platform/ti-vpe/cal.h
index 2fcd5ba2da28..719314e01b59 100644
--- a/drivers/media/platform/ti-vpe/cal.h
+++ b/drivers/media/platform/ti-vpe/cal.h
@@ -60,7 +60,7 @@ enum cal_camerarx_field {
 	F_MAX_FIELDS,
 };
 
-struct cal_fmt {
+struct cal_format_info {
 	u32	fourcc;
 	u32	code;
 	/* Bits per pixel */
@@ -126,7 +126,7 @@ struct cal_camerarx {
 	struct v4l2_subdev	subdev;
 	struct media_pad	pads[2];
 	struct v4l2_mbus_framefmt	formats[2];
-	const struct cal_fmt	*fmtinfo;
+	const struct cal_format_info	*fmtinfo;
 };
 
 struct cal_dev {
@@ -172,12 +172,12 @@ struct cal_ctx {
 	struct cal_dmaqueue	vidq;
 
 	/* video capture */
-	const struct cal_fmt	*fmt;
+	const struct cal_format_info	*fmtinfo;
 	/* Used to store current pixel format */
 	struct v4l2_format	v_fmt;
 
 	/* Current subdev enumerated format */
-	const struct cal_fmt	**active_fmt;
+	const struct cal_format_info	**active_fmt;
 	unsigned int		num_active_fmt;
 
 	unsigned int		sequence;
@@ -254,10 +254,10 @@ static inline void cal_set_field(u32 *valp, u32 field, u32 mask)
 	*valp = val;
 }
 
-extern const struct cal_fmt cal_formats[];
+extern const struct cal_format_info cal_formats[];
 extern const unsigned int cal_num_formats;
-const struct cal_fmt *cal_format_by_fourcc(u32 fourcc);
-const struct cal_fmt *cal_format_by_code(u32 code);
+const struct cal_format_info *cal_format_by_fourcc(u32 fourcc);
+const struct cal_format_info *cal_format_by_code(u32 code);
 
 void cal_quickdump_regs(struct cal_dev *cal);
 
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 094/107] media: ti-vpe: cal: Refactor interrupt enable/disable
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (92 preceding siblings ...)
  2020-06-14 23:59 ` [PATCH v1 093/107] media: ti-vpe: cal: Rename struct cal_fmt to cal_format_info Laurent Pinchart
@ 2020-06-14 23:59 ` Laurent Pinchart
  2020-06-14 23:59 ` [PATCH v1 095/107] media: ti-vpe: cal: Fold PPI enable in CAMERARX .s_stream() Laurent Pinchart
                   ` (14 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:59 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

Interrupts are enabled and disabled by the cal_camerarx_enable_irqs()
and cal_camerarx_disable_irqs(). Despite their name, they deal with all
interrupts, not just the CAMERARX interrupts, and they hardcode the
assumption that the context index is identical to the CAMERARX index.

Split the context-related interrupt management to two new functions,
cal_ctx_enable_irqs() and cal_ctx_disable_irqs(), called from the
cal_start_streaming() and cal_stop_streaming() functions. The explicit
calls to cal_camerarx_enable_irqs() and cal_camerarx_disable_irqs() are
folded with the CAMERARX .s_stream() operation to simplify the CAMERARX
API.

Enabling the OCPO error interrupt is moved to the PM runtime resume
operation, as it's global to the device, not related to a CAMERARX or
context. The VC IRQ enable and disable are removed as they're not used,
the parent interrupt bit (CAL_HL_IRQ_VC_MASK) never being set.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal-camerarx.c | 83 +++++++-------------
 drivers/media/platform/ti-vpe/cal-video.c    |  6 +-
 drivers/media/platform/ti-vpe/cal.c          | 24 ++++++
 drivers/media/platform/ti-vpe/cal.h          |  4 +-
 4 files changed, 57 insertions(+), 60 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal-camerarx.c b/drivers/media/platform/ti-vpe/cal-camerarx.c
index 3f33079fcfd1..a1d0f72a4b0a 100644
--- a/drivers/media/platform/ti-vpe/cal-camerarx.c
+++ b/drivers/media/platform/ti-vpe/cal-camerarx.c
@@ -226,6 +226,29 @@ static void cal_camerarx_wait_stop_state(struct cal_camerarx *phy)
 		phy_err(phy, "Timeout waiting for stop state\n");
 }
 
+static void cal_camerarx_enable_irqs(struct cal_camerarx *phy)
+{
+	const u32 cio_err_mask =
+		CAL_CSI2_COMPLEXIO_IRQ_LANE_ERRORS_MASK |
+		CAL_CSI2_COMPLEXIO_IRQ_FIFO_OVR_MASK |
+		CAL_CSI2_COMPLEXIO_IRQ_SHORT_PACKET_MASK |
+		CAL_CSI2_COMPLEXIO_IRQ_ECC_NO_CORRECTION_MASK;
+
+	/* Enable CIO error IRQs. */
+	cal_write(phy->cal, CAL_HL_IRQENABLE_SET(0),
+		  CAL_HL_IRQ_CIO_MASK(phy->instance));
+	cal_write(phy->cal, CAL_CSI2_COMPLEXIO_IRQENABLE(phy->instance),
+		  cio_err_mask);
+}
+
+static void cal_camerarx_disable_irqs(struct cal_camerarx *phy)
+{
+	/* Disable CIO error irqs */
+	cal_write(phy->cal, CAL_HL_IRQENABLE_CLR(0),
+		  CAL_HL_IRQ_CIO_MASK(phy->instance));
+	cal_write(phy->cal, CAL_CSI2_COMPLEXIO_IRQENABLE(phy->instance), 0);
+}
+
 static int cal_camerarx_start(struct cal_camerarx *phy)
 {
 	s64 external_rate;
@@ -243,6 +266,8 @@ static int cal_camerarx_start(struct cal_camerarx *phy)
 		return ret;
 	}
 
+	cal_camerarx_enable_irqs(phy);
+
 	/*
 	 * CSI-2 PHY Link Initialization Sequence, according to the DRA74xP /
 	 * DRA75xP / DRA76xP / DRA77xP TRM. The DRA71x / DRA72x and the AM65x /
@@ -332,6 +357,7 @@ static int cal_camerarx_start(struct cal_camerarx *phy)
 	ret = v4l2_subdev_call(phy->sensor, video, s_stream, 1);
 	if (ret) {
 		v4l2_subdev_call(phy->sensor, core, s_power, 0);
+		cal_camerarx_disable_irqs(phy);
 		phy_err(phy, "stream on failed in subdev\n");
 		return ret;
 	}
@@ -359,6 +385,8 @@ static void cal_camerarx_stop(struct cal_camerarx *phy)
 	unsigned int i;
 	int ret;
 
+	cal_camerarx_disable_irqs(phy);
+
 	cal_camerarx_power(phy, false);
 
 	/* Assert Complex IO Reset */
@@ -420,61 +448,6 @@ void cal_camerarx_i913_errata(struct cal_camerarx *phy)
 	camerarx_write(phy, CAL_CSI2_PHY_REG10, reg10);
 }
 
-/*
- * Enable the expected IRQ sources
- */
-void cal_camerarx_enable_irqs(struct cal_camerarx *phy)
-{
-	u32 val;
-
-	const u32 cio_err_mask =
-		CAL_CSI2_COMPLEXIO_IRQ_LANE_ERRORS_MASK |
-		CAL_CSI2_COMPLEXIO_IRQ_FIFO_OVR_MASK |
-		CAL_CSI2_COMPLEXIO_IRQ_SHORT_PACKET_MASK |
-		CAL_CSI2_COMPLEXIO_IRQ_ECC_NO_CORRECTION_MASK;
-
-	/* Enable CIO error irqs */
-	cal_write(phy->cal, CAL_HL_IRQENABLE_SET(0),
-		  CAL_HL_IRQ_CIO_MASK(phy->instance));
-	cal_write(phy->cal, CAL_CSI2_COMPLEXIO_IRQENABLE(phy->instance),
-		  cio_err_mask);
-
-	/* Always enable OCPO error */
-	cal_write(phy->cal, CAL_HL_IRQENABLE_SET(0), CAL_HL_IRQ_OCPO_ERR_MASK);
-
-	/* Enable IRQ_WDMA_END 0/1 */
-	val = 0;
-	cal_set_field(&val, 1, CAL_HL_IRQ_MASK(phy->instance));
-	cal_write(phy->cal, CAL_HL_IRQENABLE_SET(1), val);
-	/* Enable IRQ_WDMA_START 0/1 */
-	val = 0;
-	cal_set_field(&val, 1, CAL_HL_IRQ_MASK(phy->instance));
-	cal_write(phy->cal, CAL_HL_IRQENABLE_SET(2), val);
-	/* Todo: Add VC_IRQ and CSI2_COMPLEXIO_IRQ handling */
-	cal_write(phy->cal, CAL_CSI2_VC_IRQENABLE(0), 0xFF000000);
-}
-
-void cal_camerarx_disable_irqs(struct cal_camerarx *phy)
-{
-	u32 val;
-
-	/* Disable CIO error irqs */
-	cal_write(phy->cal, CAL_HL_IRQENABLE_CLR(0),
-		  CAL_HL_IRQ_CIO_MASK(phy->instance));
-	cal_write(phy->cal, CAL_CSI2_COMPLEXIO_IRQENABLE(phy->instance), 0);
-
-	/* Disable IRQ_WDMA_END 0/1 */
-	val = 0;
-	cal_set_field(&val, 1, CAL_HL_IRQ_MASK(phy->instance));
-	cal_write(phy->cal, CAL_HL_IRQENABLE_CLR(1), val);
-	/* Disable IRQ_WDMA_START 0/1 */
-	val = 0;
-	cal_set_field(&val, 1, CAL_HL_IRQ_MASK(phy->instance));
-	cal_write(phy->cal, CAL_HL_IRQENABLE_CLR(2), val);
-	/* Todo: Add VC_IRQ and CSI2_COMPLEXIO_IRQ handling */
-	cal_write(phy->cal, CAL_CSI2_VC_IRQENABLE(0), 0);
-}
-
 void cal_camerarx_ppi_enable(struct cal_camerarx *phy)
 {
 	cal_write(phy->cal, CAL_CSI2_PPI_CTRL(phy->instance),
diff --git a/drivers/media/platform/ti-vpe/cal-video.c b/drivers/media/platform/ti-vpe/cal-video.c
index e7ad0b93fc59..3807d91f0392 100644
--- a/drivers/media/platform/ti-vpe/cal-video.c
+++ b/drivers/media/platform/ti-vpe/cal-video.c
@@ -517,8 +517,7 @@ static int cal_start_streaming(struct vb2_queue *vq, unsigned int count)
 	cal_ctx_csi2_config(ctx);
 	cal_ctx_pix_proc_config(ctx);
 	cal_ctx_wr_dma_config(ctx);
-
-	cal_camerarx_enable_irqs(ctx->phy);
+	cal_ctx_enable_irqs(ctx);
 
 	ret = v4l2_subdev_call(&ctx->phy->subdev, video, s_stream, 1);
 	if (ret)
@@ -570,7 +569,8 @@ static void cal_stop_streaming(struct vb2_queue *vq)
 	if (dma_act)
 		ctx_err(ctx, "failed to disable dma cleanly\n");
 
-	cal_camerarx_disable_irqs(ctx->phy);
+	cal_ctx_disable_irqs(ctx);
+
 	v4l2_subdev_call(&ctx->phy->subdev, video, s_stream, 0);
 
 	/* Release all active buffers */
diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index 15f578b18d72..4b986d818cb9 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -411,6 +411,24 @@ void cal_ctx_wr_dma_addr(struct cal_ctx *ctx, unsigned int dmaaddr)
 	cal_write(ctx->cal, CAL_WR_DMA_ADDR(ctx->index), dmaaddr);
 }
 
+void cal_ctx_enable_irqs(struct cal_ctx *ctx)
+{
+	/* Enable IRQ_WDMA_END and IRQ_WDMA_START. */
+	cal_write(ctx->cal, CAL_HL_IRQENABLE_SET(1),
+		  CAL_HL_IRQ_MASK(ctx->index));
+	cal_write(ctx->cal, CAL_HL_IRQENABLE_SET(2),
+		  CAL_HL_IRQ_MASK(ctx->index));
+}
+
+void cal_ctx_disable_irqs(struct cal_ctx *ctx)
+{
+	/* Disable IRQ_WDMA_END and IRQ_WDMA_START. */
+	cal_write(ctx->cal, CAL_HL_IRQENABLE_CLR(1),
+		  CAL_HL_IRQ_MASK(ctx->index));
+	cal_write(ctx->cal, CAL_HL_IRQENABLE_CLR(2),
+		  CAL_HL_IRQ_MASK(ctx->index));
+}
+
 /* ------------------------------------------------------------------
  *	IRQ Handling
  * ------------------------------------------------------------------
@@ -1025,6 +1043,12 @@ static int cal_runtime_resume(struct device *dev)
 			cal_camerarx_i913_errata(cal->phy[i]);
 	}
 
+	/*
+	 * Enable global interrupts that are not related to a particular
+	 * CAMERARAX or context.
+	 */
+	cal_write(cal, CAL_HL_IRQENABLE_SET(0), CAL_HL_IRQ_OCPO_ERR_MASK);
+
 	return 0;
 }
 
diff --git a/drivers/media/platform/ti-vpe/cal.h b/drivers/media/platform/ti-vpe/cal.h
index 719314e01b59..b39f6468d142 100644
--- a/drivers/media/platform/ti-vpe/cal.h
+++ b/drivers/media/platform/ti-vpe/cal.h
@@ -262,8 +262,6 @@ const struct cal_format_info *cal_format_by_code(u32 code);
 void cal_quickdump_regs(struct cal_dev *cal);
 
 void cal_camerarx_disable(struct cal_camerarx *phy);
-void cal_camerarx_enable_irqs(struct cal_camerarx *phy);
-void cal_camerarx_disable_irqs(struct cal_camerarx *phy);
 void cal_camerarx_ppi_enable(struct cal_camerarx *phy);
 void cal_camerarx_ppi_disable(struct cal_camerarx *phy);
 void cal_camerarx_i913_errata(struct cal_camerarx *phy);
@@ -275,6 +273,8 @@ void cal_ctx_csi2_config(struct cal_ctx *ctx);
 void cal_ctx_pix_proc_config(struct cal_ctx *ctx);
 void cal_ctx_wr_dma_config(struct cal_ctx *ctx);
 void cal_ctx_wr_dma_addr(struct cal_ctx *ctx, unsigned int dmaaddr);
+void cal_ctx_enable_irqs(struct cal_ctx *ctx);
+void cal_ctx_disable_irqs(struct cal_ctx *ctx);
 
 int cal_ctx_v4l2_register(struct cal_ctx *ctx);
 void cal_ctx_v4l2_unregister(struct cal_ctx *ctx);
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 095/107] media: ti-vpe: cal: Fold PPI enable in CAMERARX .s_stream()
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (93 preceding siblings ...)
  2020-06-14 23:59 ` [PATCH v1 094/107] media: ti-vpe: cal: Refactor interrupt enable/disable Laurent Pinchart
@ 2020-06-14 23:59 ` Laurent Pinchart
  2020-06-14 23:59 ` [PATCH v1 096/107] media: ti-vpe: cal: Stop write DMA without disabling PPI Laurent Pinchart
                   ` (13 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:59 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

To further decouple the context and CAMERARX components, move the call
to cal_camerarx_ppi_enable() from cal_start_streaming() to the CAMERARX
.s_stream() operation. The DMA destination address has to be set before
starting the CAMERARX, which is desirable anyway.

cal_camerarx_ppi_disable() will be addressed separately.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal-camerarx.c | 31 +++++++++++---------
 drivers/media/platform/ti-vpe/cal-video.c    |  4 +--
 drivers/media/platform/ti-vpe/cal.h          |  1 -
 3 files changed, 18 insertions(+), 18 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal-camerarx.c b/drivers/media/platform/ti-vpe/cal-camerarx.c
index a1d0f72a4b0a..2d0e9d8414e7 100644
--- a/drivers/media/platform/ti-vpe/cal-camerarx.c
+++ b/drivers/media/platform/ti-vpe/cal-camerarx.c
@@ -249,6 +249,20 @@ static void cal_camerarx_disable_irqs(struct cal_camerarx *phy)
 	cal_write(phy->cal, CAL_CSI2_COMPLEXIO_IRQENABLE(phy->instance), 0);
 }
 
+static void cal_camerarx_ppi_enable(struct cal_camerarx *phy)
+{
+	cal_write(phy->cal, CAL_CSI2_PPI_CTRL(phy->instance),
+		  CAL_CSI2_PPI_CTRL_FRAME_MASK);
+	cal_write_field(phy->cal, CAL_CSI2_PPI_CTRL(phy->instance),
+			1, CAL_CSI2_PPI_CTRL_IF_EN_MASK);
+}
+
+void cal_camerarx_ppi_disable(struct cal_camerarx *phy)
+{
+	cal_write_field(phy->cal, CAL_CSI2_PPI_CTRL(phy->instance),
+			0, CAL_CSI2_PPI_CTRL_IF_EN_MASK);
+}
+
 static int cal_camerarx_start(struct cal_camerarx *phy)
 {
 	s64 external_rate;
@@ -377,6 +391,9 @@ static int cal_camerarx_start(struct cal_camerarx *phy)
 	 * implemented.
 	 */
 
+	/* Finally, enable the PHY Protocol Interface (PPI). */
+	cal_camerarx_ppi_enable(phy);
+
 	return 0;
 }
 
@@ -448,20 +465,6 @@ void cal_camerarx_i913_errata(struct cal_camerarx *phy)
 	camerarx_write(phy, CAL_CSI2_PHY_REG10, reg10);
 }
 
-void cal_camerarx_ppi_enable(struct cal_camerarx *phy)
-{
-	cal_write(phy->cal, CAL_CSI2_PPI_CTRL(phy->instance),
-		  CAL_CSI2_PPI_CTRL_FRAME_MASK);
-	cal_write_field(phy->cal, CAL_CSI2_PPI_CTRL(phy->instance),
-			1, CAL_CSI2_PPI_CTRL_IF_EN_MASK);
-}
-
-void cal_camerarx_ppi_disable(struct cal_camerarx *phy)
-{
-	cal_write_field(phy->cal, CAL_CSI2_PPI_CTRL(phy->instance),
-			0, CAL_CSI2_PPI_CTRL_IF_EN_MASK);
-}
-
 static int cal_camerarx_regmap_init(struct cal_dev *cal,
 				    struct cal_camerarx *phy)
 {
diff --git a/drivers/media/platform/ti-vpe/cal-video.c b/drivers/media/platform/ti-vpe/cal-video.c
index 3807d91f0392..627d816548b8 100644
--- a/drivers/media/platform/ti-vpe/cal-video.c
+++ b/drivers/media/platform/ti-vpe/cal-video.c
@@ -517,15 +517,13 @@ static int cal_start_streaming(struct vb2_queue *vq, unsigned int count)
 	cal_ctx_csi2_config(ctx);
 	cal_ctx_pix_proc_config(ctx);
 	cal_ctx_wr_dma_config(ctx);
+	cal_ctx_wr_dma_addr(ctx, addr);
 	cal_ctx_enable_irqs(ctx);
 
 	ret = v4l2_subdev_call(&ctx->phy->subdev, video, s_stream, 1);
 	if (ret)
 		goto err;
 
-	cal_ctx_wr_dma_addr(ctx, addr);
-	cal_camerarx_ppi_enable(ctx->phy);
-
 	if (cal_debug >= 4)
 		cal_quickdump_regs(ctx->cal);
 
diff --git a/drivers/media/platform/ti-vpe/cal.h b/drivers/media/platform/ti-vpe/cal.h
index b39f6468d142..5cfdcaae4b16 100644
--- a/drivers/media/platform/ti-vpe/cal.h
+++ b/drivers/media/platform/ti-vpe/cal.h
@@ -262,7 +262,6 @@ const struct cal_format_info *cal_format_by_code(u32 code);
 void cal_quickdump_regs(struct cal_dev *cal);
 
 void cal_camerarx_disable(struct cal_camerarx *phy);
-void cal_camerarx_ppi_enable(struct cal_camerarx *phy);
 void cal_camerarx_ppi_disable(struct cal_camerarx *phy);
 void cal_camerarx_i913_errata(struct cal_camerarx *phy);
 struct cal_camerarx *cal_camerarx_create(struct cal_dev *cal,
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 096/107] media: ti-vpe: cal: Stop write DMA without disabling PPI
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (94 preceding siblings ...)
  2020-06-14 23:59 ` [PATCH v1 095/107] media: ti-vpe: cal: Fold PPI enable in CAMERARX .s_stream() Laurent Pinchart
@ 2020-06-14 23:59 ` Laurent Pinchart
  2020-06-14 23:59 ` [PATCH v1 097/107] media: ti-vpe: cal: Use spin_lock_irq() when starting or stopping stream Laurent Pinchart
                   ` (12 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:59 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

When stopping the stream, the driver needs to ensure that ongoing DMA
completes and that no new DMA is started. It does so using a feature of
the PPI that can be stopped on a frame boundary. The downside of this
mechanism is that the DMA can't be stopped independently of the source,
which prevents usage of multiple contexts for the same source (to handle
CSI-2 virtual channels or data types).

Rework the stream stop mechanism to stop the write DMA without disabling
the PPI first. The new mechanism relies on the combination of a state
machine in the driver and shadowing of the CAL_WR_DMA_CTRL_j.MODE field
in the hardware. When a stop is requested, the DMA start interrupt
handler will request the hardware to stop at the end of the current
frame by disabling the write DMA context in the shadowed register, and
flag that a stop is in progress. The next DMA end interrupt will then
report that the stop is complete.

This makes it possible to stop the PPI after stopping the DMA, and fold
the cal_camerarx_ppi_disable() call into cal_camerarx_stop().

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal-camerarx.c |   6 +-
 drivers/media/platform/ti-vpe/cal-video.c    |  26 +---
 drivers/media/platform/ti-vpe/cal.c          | 133 +++++++++++++------
 drivers/media/platform/ti-vpe/cal.h          |  14 +-
 4 files changed, 117 insertions(+), 62 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal-camerarx.c b/drivers/media/platform/ti-vpe/cal-camerarx.c
index 2d0e9d8414e7..2e7a3bc716cf 100644
--- a/drivers/media/platform/ti-vpe/cal-camerarx.c
+++ b/drivers/media/platform/ti-vpe/cal-camerarx.c
@@ -251,13 +251,11 @@ static void cal_camerarx_disable_irqs(struct cal_camerarx *phy)
 
 static void cal_camerarx_ppi_enable(struct cal_camerarx *phy)
 {
-	cal_write(phy->cal, CAL_CSI2_PPI_CTRL(phy->instance),
-		  CAL_CSI2_PPI_CTRL_FRAME_MASK);
 	cal_write_field(phy->cal, CAL_CSI2_PPI_CTRL(phy->instance),
 			1, CAL_CSI2_PPI_CTRL_IF_EN_MASK);
 }
 
-void cal_camerarx_ppi_disable(struct cal_camerarx *phy)
+static void cal_camerarx_ppi_disable(struct cal_camerarx *phy)
 {
 	cal_write_field(phy->cal, CAL_CSI2_PPI_CTRL(phy->instance),
 			0, CAL_CSI2_PPI_CTRL_IF_EN_MASK);
@@ -402,6 +400,8 @@ static void cal_camerarx_stop(struct cal_camerarx *phy)
 	unsigned int i;
 	int ret;
 
+	cal_camerarx_ppi_disable(phy);
+
 	cal_camerarx_disable_irqs(phy);
 
 	cal_camerarx_power(phy, false);
diff --git a/drivers/media/platform/ti-vpe/cal-video.c b/drivers/media/platform/ti-vpe/cal-video.c
index 627d816548b8..d3f805a512c0 100644
--- a/drivers/media/platform/ti-vpe/cal-video.c
+++ b/drivers/media/platform/ti-vpe/cal-video.c
@@ -9,7 +9,6 @@
  *	Laurent Pinchart <laurent.pinchart@ideasonboard.com>
  */
 
-#include <linux/delay.h>
 #include <linux/ioctl.h>
 #include <linux/pm_runtime.h>
 #include <linux/videodev2.h>
@@ -511,6 +510,7 @@ static int cal_start_streaming(struct vb2_queue *vq, unsigned int count)
 
 	addr = vb2_dma_contig_plane_dma_addr(&ctx->cur_frm->vb.vb2_buf, 0);
 	ctx->sequence = 0;
+	ctx->dma_state = CAL_DMA_RUNNING;
 
 	pm_runtime_get_sync(ctx->cal->dev);
 
@@ -530,6 +530,10 @@ static int cal_start_streaming(struct vb2_queue *vq, unsigned int count)
 	return 0;
 
 err:
+	cal_ctx_wr_dma_disable(ctx);
+	cal_ctx_disable_irqs(ctx);
+	ctx->dma_state = CAL_DMA_STOPPED;
+
 	spin_lock_irqsave(&ctx->slock, flags);
 	vb2_buffer_done(&ctx->cur_frm->vb.vb2_buf, VB2_BUF_STATE_QUEUED);
 	ctx->cur_frm = NULL;
@@ -547,26 +551,9 @@ static void cal_stop_streaming(struct vb2_queue *vq)
 	struct cal_ctx *ctx = vb2_get_drv_priv(vq);
 	struct cal_dmaqueue *dma_q = &ctx->vidq;
 	struct cal_buffer *buf, *tmp;
-	unsigned long timeout;
 	unsigned long flags;
-	bool dma_act;
-
-	cal_camerarx_ppi_disable(ctx->phy);
-
-	/* wait for stream and dma to finish */
-	dma_act = true;
-	timeout = jiffies + msecs_to_jiffies(500);
-	while (dma_act && time_before(jiffies, timeout)) {
-		msleep(50);
-
-		spin_lock_irqsave(&ctx->slock, flags);
-		dma_act = ctx->dma_act;
-		spin_unlock_irqrestore(&ctx->slock, flags);
-	}
-
-	if (dma_act)
-		ctx_err(ctx, "failed to disable dma cleanly\n");
 
+	cal_ctx_wr_dma_stop(ctx);
 	cal_ctx_disable_irqs(ctx);
 
 	v4l2_subdev_call(&ctx->phy->subdev, video, s_stream, 0);
@@ -745,6 +732,7 @@ int cal_ctx_v4l2_init(struct cal_ctx *ctx)
 	INIT_LIST_HEAD(&ctx->vidq.active);
 	spin_lock_init(&ctx->slock);
 	mutex_init(&ctx->mutex);
+	init_waitqueue_head(&ctx->dma_wait);
 
 	/* Initialize the vb2 queue. */
 	q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index 4b986d818cb9..09cad8046910 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -411,6 +411,45 @@ void cal_ctx_wr_dma_addr(struct cal_ctx *ctx, unsigned int dmaaddr)
 	cal_write(ctx->cal, CAL_WR_DMA_ADDR(ctx->index), dmaaddr);
 }
 
+void cal_ctx_wr_dma_disable(struct cal_ctx *ctx)
+{
+	u32 val = cal_read(ctx->cal, CAL_WR_DMA_CTRL(ctx->index));
+
+	cal_set_field(&val, CAL_WR_DMA_CTRL_MODE_DIS,
+		      CAL_WR_DMA_CTRL_MODE_MASK);
+	cal_write(ctx->cal, CAL_WR_DMA_CTRL(ctx->index), val);
+}
+
+static bool cal_ctx_wr_dma_stopped(struct cal_ctx *ctx)
+{
+	bool stopped;
+
+	spin_lock_irq(&ctx->slock);
+	stopped = ctx->dma_state == CAL_DMA_STOPPED;
+	spin_unlock_irq(&ctx->slock);
+
+	return stopped;
+}
+
+int cal_ctx_wr_dma_stop(struct cal_ctx *ctx)
+{
+	long timeout;
+
+	/* Request DMA stop and wait until it completes. */
+	spin_lock_irq(&ctx->slock);
+	ctx->dma_state = CAL_DMA_STOP_REQUESTED;
+	spin_unlock_irq(&ctx->slock);
+
+	timeout = wait_event_timeout(ctx->dma_wait, cal_ctx_wr_dma_stopped(ctx),
+				     msecs_to_jiffies(500));
+	if (!timeout) {
+		ctx_err(ctx, "failed to disable dma cleanly\n");
+		return -ETIMEDOUT;
+	}
+
+	return 0;
+}
+
 void cal_ctx_enable_irqs(struct cal_ctx *ctx)
 {
 	/* Enable IRQ_WDMA_END and IRQ_WDMA_START. */
@@ -434,35 +473,71 @@ void cal_ctx_disable_irqs(struct cal_ctx *ctx)
  * ------------------------------------------------------------------
  */
 
-static inline void cal_schedule_next_buffer(struct cal_ctx *ctx)
+static inline void cal_irq_wdma_start(struct cal_ctx *ctx)
 {
 	struct cal_dmaqueue *dma_q = &ctx->vidq;
-	struct cal_buffer *buf;
-	unsigned long addr;
 
-	buf = list_entry(dma_q->active.next, struct cal_buffer, list);
-	ctx->next_frm = buf;
-	list_del(&buf->list);
+	spin_lock(&ctx->slock);
 
-	addr = vb2_dma_contig_plane_dma_addr(&buf->vb.vb2_buf, 0);
-	cal_ctx_wr_dma_addr(ctx, addr);
+	if (ctx->dma_state == CAL_DMA_STOP_REQUESTED) {
+		/*
+		 * If a stop is requested, disable the write DMA context
+		 * immediately. The CAL_WR_DMA_CTRL_j.MODE field is shadowed,
+		 * the current frame will complete and the DMA will then stop.
+		 */
+		cal_ctx_wr_dma_disable(ctx);
+		ctx->dma_state = CAL_DMA_STOP_PENDING;
+	} else if (!list_empty(&dma_q->active) &&
+		   ctx->cur_frm == ctx->next_frm) {
+		/*
+		 * Otherwise, if a new buffer is available, queue it to the
+		 * hardware.
+		 */
+		struct cal_buffer *buf;
+		unsigned long addr;
+
+		buf = list_entry(dma_q->active.next, struct cal_buffer, list);
+		addr = vb2_dma_contig_plane_dma_addr(&buf->vb.vb2_buf, 0);
+		cal_ctx_wr_dma_addr(ctx, addr);
+
+		ctx->next_frm = buf;
+		list_del(&buf->list);
+	}
+
+	spin_unlock(&ctx->slock);
 }
 
-static inline void cal_process_buffer_complete(struct cal_ctx *ctx)
+static inline void cal_irq_wdma_end(struct cal_ctx *ctx)
 {
-	ctx->cur_frm->vb.vb2_buf.timestamp = ktime_get_ns();
-	ctx->cur_frm->vb.field = ctx->v_fmt.fmt.pix.field;
-	ctx->cur_frm->vb.sequence = ctx->sequence++;
+	struct cal_buffer *buf = NULL;
 
-	vb2_buffer_done(&ctx->cur_frm->vb.vb2_buf, VB2_BUF_STATE_DONE);
-	ctx->cur_frm = ctx->next_frm;
+	spin_lock(&ctx->slock);
+
+	/* If the DMA context was stopping, it is now stopped. */
+	if (ctx->dma_state == CAL_DMA_STOP_PENDING) {
+		ctx->dma_state = CAL_DMA_STOPPED;
+		wake_up(&ctx->dma_wait);
+	}
+
+	/* If a new buffer was queued, complete the current buffer. */
+	if (ctx->cur_frm != ctx->next_frm) {
+		buf = ctx->cur_frm;
+		ctx->cur_frm = ctx->next_frm;
+	}
+
+	spin_unlock(&ctx->slock);
+
+	if (buf) {
+		buf->vb.vb2_buf.timestamp = ktime_get_ns();
+		buf->vb.field = ctx->v_fmt.fmt.pix.field;
+		buf->vb.sequence = ctx->sequence++;
+		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
+	}
 }
 
 static irqreturn_t cal_irq(int irq_cal, void *data)
 {
 	struct cal_dev *cal = data;
-	struct cal_ctx *ctx;
-	struct cal_dmaqueue *dma_q;
 	unsigned int i;
 	u32 status;
 
@@ -494,17 +569,8 @@ static irqreturn_t cal_irq(int irq_cal, void *data)
 		cal_write(cal, CAL_HL_IRQSTATUS(1), status);
 
 		for (i = 0; i < ARRAY_SIZE(cal->ctx); ++i) {
-			if (status & CAL_HL_IRQ_MASK(i)) {
-				ctx = cal->ctx[i];
-
-				spin_lock(&ctx->slock);
-				ctx->dma_act = false;
-
-				if (ctx->cur_frm != ctx->next_frm)
-					cal_process_buffer_complete(ctx);
-
-				spin_unlock(&ctx->slock);
-			}
+			if (status & CAL_HL_IRQ_MASK(i))
+				cal_irq_wdma_end(cal->ctx[i]);
 		}
 	}
 
@@ -515,17 +581,8 @@ static irqreturn_t cal_irq(int irq_cal, void *data)
 		cal_write(cal, CAL_HL_IRQSTATUS(2), status);
 
 		for (i = 0; i < ARRAY_SIZE(cal->ctx); ++i) {
-			if (status & CAL_HL_IRQ_MASK(i)) {
-				ctx = cal->ctx[i];
-				dma_q = &ctx->vidq;
-
-				spin_lock(&ctx->slock);
-				ctx->dma_act = true;
-				if (!list_empty(&dma_q->active) &&
-				    ctx->cur_frm == ctx->next_frm)
-					cal_schedule_next_buffer(ctx);
-				spin_unlock(&ctx->slock);
-			}
+			if (status & CAL_HL_IRQ_MASK(i))
+				cal_irq_wdma_start(cal->ctx[i]);
 		}
 	}
 
diff --git a/drivers/media/platform/ti-vpe/cal.h b/drivers/media/platform/ti-vpe/cal.h
index 5cfdcaae4b16..7e4589c6dee2 100644
--- a/drivers/media/platform/ti-vpe/cal.h
+++ b/drivers/media/platform/ti-vpe/cal.h
@@ -17,6 +17,7 @@
 #include <linux/mutex.h>
 #include <linux/spinlock.h>
 #include <linux/videodev2.h>
+#include <linux/wait.h>
 
 #include <media/media-device.h>
 #include <media/v4l2-async.h>
@@ -60,6 +61,13 @@ enum cal_camerarx_field {
 	F_MAX_FIELDS,
 };
 
+enum cal_dma_state {
+	CAL_DMA_RUNNING,
+	CAL_DMA_STOP_REQUESTED,
+	CAL_DMA_STOP_PENDING,
+	CAL_DMA_STOPPED,
+};
+
 struct cal_format_info {
 	u32	fourcc;
 	u32	code;
@@ -190,7 +198,8 @@ struct cal_ctx {
 	/* Pointer pointing to next v4l2_buffer */
 	struct cal_buffer	*next_frm;
 
-	bool dma_act;
+	enum cal_dma_state	dma_state;
+	struct wait_queue_head	dma_wait;
 };
 
 extern unsigned int cal_debug;
@@ -262,7 +271,6 @@ const struct cal_format_info *cal_format_by_code(u32 code);
 void cal_quickdump_regs(struct cal_dev *cal);
 
 void cal_camerarx_disable(struct cal_camerarx *phy);
-void cal_camerarx_ppi_disable(struct cal_camerarx *phy);
 void cal_camerarx_i913_errata(struct cal_camerarx *phy);
 struct cal_camerarx *cal_camerarx_create(struct cal_dev *cal,
 					 unsigned int instance);
@@ -272,6 +280,8 @@ void cal_ctx_csi2_config(struct cal_ctx *ctx);
 void cal_ctx_pix_proc_config(struct cal_ctx *ctx);
 void cal_ctx_wr_dma_config(struct cal_ctx *ctx);
 void cal_ctx_wr_dma_addr(struct cal_ctx *ctx, unsigned int dmaaddr);
+void cal_ctx_wr_dma_disable(struct cal_ctx *ctx);
+int cal_ctx_wr_dma_stop(struct cal_ctx *ctx);
 void cal_ctx_enable_irqs(struct cal_ctx *ctx);
 void cal_ctx_disable_irqs(struct cal_ctx *ctx);
 
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 097/107] media: ti-vpe: cal: Use spin_lock_irq() when starting or stopping stream
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (95 preceding siblings ...)
  2020-06-14 23:59 ` [PATCH v1 096/107] media: ti-vpe: cal: Stop write DMA without disabling PPI Laurent Pinchart
@ 2020-06-14 23:59 ` Laurent Pinchart
  2020-06-14 23:59 ` [PATCH v1 098/107] media: ti-vpe: cal: Share buffer release code between start and stop Laurent Pinchart
                   ` (11 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:59 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

The cal_start_streaming() and cal_stop_streaming() functions are called
with interrupts enabled. spin_lock_irq() can thus be used instead of
spin_lock_irqsave().

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal-video.c | 16 +++++++---------
 1 file changed, 7 insertions(+), 9 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal-video.c b/drivers/media/platform/ti-vpe/cal-video.c
index d3f805a512c0..de0ba6128715 100644
--- a/drivers/media/platform/ti-vpe/cal-video.c
+++ b/drivers/media/platform/ti-vpe/cal-video.c
@@ -492,12 +492,11 @@ static int cal_start_streaming(struct vb2_queue *vq, unsigned int count)
 	struct cal_dmaqueue *dma_q = &ctx->vidq;
 	struct cal_buffer *buf, *tmp;
 	unsigned long addr;
-	unsigned long flags;
 	int ret;
 
-	spin_lock_irqsave(&ctx->slock, flags);
+	spin_lock_irq(&ctx->slock);
 	if (list_empty(&dma_q->active)) {
-		spin_unlock_irqrestore(&ctx->slock, flags);
+		spin_unlock_irq(&ctx->slock);
 		ctx_dbg(3, ctx, "buffer queue is empty\n");
 		return -EIO;
 	}
@@ -506,7 +505,7 @@ static int cal_start_streaming(struct vb2_queue *vq, unsigned int count)
 	ctx->cur_frm = buf;
 	ctx->next_frm = buf;
 	list_del(&buf->list);
-	spin_unlock_irqrestore(&ctx->slock, flags);
+	spin_unlock_irq(&ctx->slock);
 
 	addr = vb2_dma_contig_plane_dma_addr(&ctx->cur_frm->vb.vb2_buf, 0);
 	ctx->sequence = 0;
@@ -534,7 +533,7 @@ static int cal_start_streaming(struct vb2_queue *vq, unsigned int count)
 	cal_ctx_disable_irqs(ctx);
 	ctx->dma_state = CAL_DMA_STOPPED;
 
-	spin_lock_irqsave(&ctx->slock, flags);
+	spin_lock_irq(&ctx->slock);
 	vb2_buffer_done(&ctx->cur_frm->vb.vb2_buf, VB2_BUF_STATE_QUEUED);
 	ctx->cur_frm = NULL;
 	ctx->next_frm = NULL;
@@ -542,7 +541,7 @@ static int cal_start_streaming(struct vb2_queue *vq, unsigned int count)
 		list_del(&buf->list);
 		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_QUEUED);
 	}
-	spin_unlock_irqrestore(&ctx->slock, flags);
+	spin_unlock_irq(&ctx->slock);
 	return ret;
 }
 
@@ -551,7 +550,6 @@ static void cal_stop_streaming(struct vb2_queue *vq)
 	struct cal_ctx *ctx = vb2_get_drv_priv(vq);
 	struct cal_dmaqueue *dma_q = &ctx->vidq;
 	struct cal_buffer *buf, *tmp;
-	unsigned long flags;
 
 	cal_ctx_wr_dma_stop(ctx);
 	cal_ctx_disable_irqs(ctx);
@@ -559,7 +557,7 @@ static void cal_stop_streaming(struct vb2_queue *vq)
 	v4l2_subdev_call(&ctx->phy->subdev, video, s_stream, 0);
 
 	/* Release all active buffers */
-	spin_lock_irqsave(&ctx->slock, flags);
+	spin_lock_irq(&ctx->slock);
 	list_for_each_entry_safe(buf, tmp, &dma_q->active, list) {
 		list_del(&buf->list);
 		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
@@ -574,7 +572,7 @@ static void cal_stop_streaming(struct vb2_queue *vq)
 	}
 	ctx->cur_frm = NULL;
 	ctx->next_frm = NULL;
-	spin_unlock_irqrestore(&ctx->slock, flags);
+	spin_unlock_irq(&ctx->slock);
 
 	pm_runtime_put_sync(ctx->cal->dev);
 }
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 098/107] media: ti-vpe: cal: Share buffer release code between start and stop
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (96 preceding siblings ...)
  2020-06-14 23:59 ` [PATCH v1 097/107] media: ti-vpe: cal: Use spin_lock_irq() when starting or stopping stream Laurent Pinchart
@ 2020-06-14 23:59 ` Laurent Pinchart
  2020-06-14 23:59 ` [PATCH v1 099/107] media: ti-vpe: cal: Drop V4L2_CAP_READWRITE Laurent Pinchart
                   ` (10 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:59 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

The cal_start_streaming() and cal_stop_streaming() functions duplicate
the same buffer release logic. split it to a separate function to share
the code.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal-video.c | 55 +++++++++++------------
 1 file changed, 26 insertions(+), 29 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal-video.c b/drivers/media/platform/ti-vpe/cal-video.c
index de0ba6128715..7eec0a57b141 100644
--- a/drivers/media/platform/ti-vpe/cal-video.c
+++ b/drivers/media/platform/ti-vpe/cal-video.c
@@ -486,11 +486,34 @@ static void cal_buffer_queue(struct vb2_buffer *vb)
 	spin_unlock_irqrestore(&ctx->slock, flags);
 }
 
+static void cal_release_buffers(struct cal_ctx *ctx,
+				enum vb2_buffer_state state)
+{
+	struct cal_buffer *buf, *tmp;
+
+	/* Release all active buffers. */
+	spin_lock_irq(&ctx->slock);
+
+	list_for_each_entry_safe(buf, tmp, &ctx->vidq.active, list) {
+		list_del(&buf->list);
+		vb2_buffer_done(&buf->vb.vb2_buf, state);
+	}
+
+	if (ctx->next_frm != ctx->cur_frm)
+		vb2_buffer_done(&ctx->next_frm->vb.vb2_buf, state);
+	vb2_buffer_done(&ctx->cur_frm->vb.vb2_buf, state);
+
+	ctx->cur_frm = NULL;
+	ctx->next_frm = NULL;
+
+	spin_unlock_irq(&ctx->slock);
+}
+
 static int cal_start_streaming(struct vb2_queue *vq, unsigned int count)
 {
 	struct cal_ctx *ctx = vb2_get_drv_priv(vq);
 	struct cal_dmaqueue *dma_q = &ctx->vidq;
-	struct cal_buffer *buf, *tmp;
+	struct cal_buffer *buf;
 	unsigned long addr;
 	int ret;
 
@@ -533,46 +556,20 @@ static int cal_start_streaming(struct vb2_queue *vq, unsigned int count)
 	cal_ctx_disable_irqs(ctx);
 	ctx->dma_state = CAL_DMA_STOPPED;
 
-	spin_lock_irq(&ctx->slock);
-	vb2_buffer_done(&ctx->cur_frm->vb.vb2_buf, VB2_BUF_STATE_QUEUED);
-	ctx->cur_frm = NULL;
-	ctx->next_frm = NULL;
-	list_for_each_entry_safe(buf, tmp, &dma_q->active, list) {
-		list_del(&buf->list);
-		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_QUEUED);
-	}
-	spin_unlock_irq(&ctx->slock);
+	cal_release_buffers(ctx, VB2_BUF_STATE_QUEUED);
 	return ret;
 }
 
 static void cal_stop_streaming(struct vb2_queue *vq)
 {
 	struct cal_ctx *ctx = vb2_get_drv_priv(vq);
-	struct cal_dmaqueue *dma_q = &ctx->vidq;
-	struct cal_buffer *buf, *tmp;
 
 	cal_ctx_wr_dma_stop(ctx);
 	cal_ctx_disable_irqs(ctx);
 
 	v4l2_subdev_call(&ctx->phy->subdev, video, s_stream, 0);
 
-	/* Release all active buffers */
-	spin_lock_irq(&ctx->slock);
-	list_for_each_entry_safe(buf, tmp, &dma_q->active, list) {
-		list_del(&buf->list);
-		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
-	}
-
-	if (ctx->cur_frm == ctx->next_frm) {
-		vb2_buffer_done(&ctx->cur_frm->vb.vb2_buf, VB2_BUF_STATE_ERROR);
-	} else {
-		vb2_buffer_done(&ctx->cur_frm->vb.vb2_buf, VB2_BUF_STATE_ERROR);
-		vb2_buffer_done(&ctx->next_frm->vb.vb2_buf,
-				VB2_BUF_STATE_ERROR);
-	}
-	ctx->cur_frm = NULL;
-	ctx->next_frm = NULL;
-	spin_unlock_irq(&ctx->slock);
+	cal_release_buffers(ctx, VB2_BUF_STATE_ERROR);
 
 	pm_runtime_put_sync(ctx->cal->dev);
 }
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 099/107] media: ti-vpe: cal: Drop V4L2_CAP_READWRITE
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (97 preceding siblings ...)
  2020-06-14 23:59 ` [PATCH v1 098/107] media: ti-vpe: cal: Share buffer release code between start and stop Laurent Pinchart
@ 2020-06-14 23:59 ` Laurent Pinchart
  2020-06-14 23:59 ` [PATCH v1 100/107] media: ti-vpe: cal: Drop unneeded check in cal_calc_format_size() Laurent Pinchart
                   ` (9 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:59 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

The V4L2 read/write API is inefficient and makes little sense for
devices that handle frame-based formats. Applications shouldn't use it,
drop its support from the driver.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal-video.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal-video.c b/drivers/media/platform/ti-vpe/cal-video.c
index 7eec0a57b141..775ed2fd9f1e 100644
--- a/drivers/media/platform/ti-vpe/cal-video.c
+++ b/drivers/media/platform/ti-vpe/cal-video.c
@@ -595,8 +595,7 @@ static const struct video_device cal_videodev = {
 	.ioctl_ops	= &cal_ioctl_ops,
 	.minor		= -1,
 	.release	= video_device_release_empty,
-	.device_caps	= V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING |
-			  V4L2_CAP_READWRITE,
+	.device_caps	= V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING,
 };
 
 static int cal_ctx_v4l2_init_formats(struct cal_ctx *ctx)
@@ -731,7 +730,7 @@ int cal_ctx_v4l2_init(struct cal_ctx *ctx)
 
 	/* Initialize the vb2 queue. */
 	q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-	q->io_modes = VB2_MMAP | VB2_DMABUF | VB2_READ;
+	q->io_modes = VB2_MMAP | VB2_DMABUF;
 	q->drv_priv = ctx;
 	q->buf_struct_size = sizeof(struct cal_buffer);
 	q->ops = &cal_video_qops;
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 100/107] media: ti-vpe: cal: Drop unneeded check in cal_calc_format_size()
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (98 preceding siblings ...)
  2020-06-14 23:59 ` [PATCH v1 099/107] media: ti-vpe: cal: Drop V4L2_CAP_READWRITE Laurent Pinchart
@ 2020-06-14 23:59 ` Laurent Pinchart
  2020-06-14 23:59 ` [PATCH v1 101/107] media: ti-vpe: cal: Remove DMA queue empty check at start streaming time Laurent Pinchart
                   ` (8 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:59 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

The cal_calc_format_size() function checks that the passed fmtinfo
argument is not NULL. All callers ensure that the pointer is valid. Drop
the check.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal-video.c | 16 +++++-----------
 1 file changed, 5 insertions(+), 11 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal-video.c b/drivers/media/platform/ti-vpe/cal-video.c
index 775ed2fd9f1e..6d6ea02bf0b2 100644
--- a/drivers/media/platform/ti-vpe/cal-video.c
+++ b/drivers/media/platform/ti-vpe/cal-video.c
@@ -146,17 +146,12 @@ static int __subdev_set_format(struct cal_ctx *ctx,
 	return 0;
 }
 
-static int cal_calc_format_size(struct cal_ctx *ctx,
-				const struct cal_format_info *fmtinfo,
-				struct v4l2_format *f)
+static void cal_calc_format_size(struct cal_ctx *ctx,
+				 const struct cal_format_info *fmtinfo,
+				 struct v4l2_format *f)
 {
 	u32 bpl, max_width;
 
-	if (!fmtinfo) {
-		ctx_dbg(3, ctx, "No cal_fmt provided!\n");
-		return -EINVAL;
-	}
-
 	/*
 	 * Maximum width is bound by the DMA max width in bytes.
 	 * We need to recalculate the actual maxi width depending on the
@@ -177,8 +172,6 @@ static int cal_calc_format_size(struct cal_ctx *ctx,
 		__func__, fourcc_to_str(f->fmt.pix.pixelformat),
 		f->fmt.pix.width, f->fmt.pix.height,
 		f->fmt.pix.bytesperline, f->fmt.pix.sizeimage);
-
-	return 0;
 }
 
 static int cal_g_fmt_vid_cap(struct file *file, void *priv,
@@ -247,7 +240,8 @@ static int cal_try_fmt_vid_cap(struct file *file, void *priv,
 	 * updated properly during s_fmt
 	 */
 	f->fmt.pix.colorspace = ctx->v_fmt.fmt.pix.colorspace;
-	return cal_calc_format_size(ctx, fmtinfo, f);
+	cal_calc_format_size(ctx, fmtinfo, f);
+	return 0;
 }
 
 static int cal_s_fmt_vid_cap(struct file *file, void *priv,
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 101/107] media: ti-vpe: cal: Remove DMA queue empty check at start streaming time
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (99 preceding siblings ...)
  2020-06-14 23:59 ` [PATCH v1 100/107] media: ti-vpe: cal: Drop unneeded check in cal_calc_format_size() Laurent Pinchart
@ 2020-06-14 23:59 ` Laurent Pinchart
  2020-06-14 23:59 ` [PATCH v1 102/107] media: ti-vpe: cal: Use list_first_entry() Laurent Pinchart
                   ` (7 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:59 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

The vb2 queue ensures that the start streaming operation will only be
called with a minimal number of buffers queued to the driver. There's
thus no need to manually check if the DMA queue is empty. Remove the
check.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal-video.c | 6 ------
 1 file changed, 6 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal-video.c b/drivers/media/platform/ti-vpe/cal-video.c
index 6d6ea02bf0b2..d10c8c16abd3 100644
--- a/drivers/media/platform/ti-vpe/cal-video.c
+++ b/drivers/media/platform/ti-vpe/cal-video.c
@@ -512,12 +512,6 @@ static int cal_start_streaming(struct vb2_queue *vq, unsigned int count)
 	int ret;
 
 	spin_lock_irq(&ctx->slock);
-	if (list_empty(&dma_q->active)) {
-		spin_unlock_irq(&ctx->slock);
-		ctx_dbg(3, ctx, "buffer queue is empty\n");
-		return -EIO;
-	}
-
 	buf = list_entry(dma_q->active.next, struct cal_buffer, list);
 	ctx->cur_frm = buf;
 	ctx->next_frm = buf;
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 102/107] media: ti-vpe: cal: Use list_first_entry()
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (100 preceding siblings ...)
  2020-06-14 23:59 ` [PATCH v1 101/107] media: ti-vpe: cal: Remove DMA queue empty check at start streaming time Laurent Pinchart
@ 2020-06-14 23:59 ` Laurent Pinchart
  2020-06-14 23:59 ` [PATCH v1 103/107] media: ti-vpe: cal: Group all DMA queue fields in struct cal_dmaqueue Laurent Pinchart
                   ` (6 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:59 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

Use the list_first_entry() macro where appropriate to replace manual
usage of list_entry(head.next).

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal-video.c | 2 +-
 drivers/media/platform/ti-vpe/cal.c       | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal-video.c b/drivers/media/platform/ti-vpe/cal-video.c
index d10c8c16abd3..1b9b0e0719d4 100644
--- a/drivers/media/platform/ti-vpe/cal-video.c
+++ b/drivers/media/platform/ti-vpe/cal-video.c
@@ -512,7 +512,7 @@ static int cal_start_streaming(struct vb2_queue *vq, unsigned int count)
 	int ret;
 
 	spin_lock_irq(&ctx->slock);
-	buf = list_entry(dma_q->active.next, struct cal_buffer, list);
+	buf = list_first_entry(&dma_q->active, struct cal_buffer, list);
 	ctx->cur_frm = buf;
 	ctx->next_frm = buf;
 	list_del(&buf->list);
diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index 09cad8046910..ca9168fd7a13 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -496,7 +496,7 @@ static inline void cal_irq_wdma_start(struct cal_ctx *ctx)
 		struct cal_buffer *buf;
 		unsigned long addr;
 
-		buf = list_entry(dma_q->active.next, struct cal_buffer, list);
+		buf = list_first_entry(&dma_q->active, struct cal_buffer, list);
 		addr = vb2_dma_contig_plane_dma_addr(&buf->vb.vb2_buf, 0);
 		cal_ctx_wr_dma_addr(ctx, addr);
 
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 103/107] media: ti-vpe: cal: Group all DMA queue fields in struct cal_dmaqueue
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (101 preceding siblings ...)
  2020-06-14 23:59 ` [PATCH v1 102/107] media: ti-vpe: cal: Use list_first_entry() Laurent Pinchart
@ 2020-06-14 23:59 ` Laurent Pinchart
  2020-06-14 23:59 ` [PATCH v1 104/107] media: ti-vpe: cal: Set cal_dmaqueue.pending to NULL when no pending buffer Laurent Pinchart
                   ` (5 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:59 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

The cal_dmaqueue structure only contains the list of queued buffers.
Move the other fields that are logically related to the DMA queue
(current and next buffer points, state, wait queue and lock) from
cal_ctx to cal_dmaqueue.

Take this as an opportunity to document the fields usage and to give
them more appropriate names. The 'active' field stored the list of all
queued buffers, not the active buffers, so rename it to 'queue'. The
'cur_frm' and 'next_frm' are respectively renamed to 'active' and
'pending' to better explain their purpose. The 'dma_state' and
'dma_wait' fields are stripped of their 'dma_' prefix as they're now
part of cal_dmaqueue. Finally, 'slock' is renamed to 'lock'.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal-video.c | 48 +++++++++++-----------
 drivers/media/platform/ti-vpe/cal.c       | 49 +++++++++++------------
 drivers/media/platform/ti-vpe/cal.h       | 44 ++++++++++++++------
 3 files changed, 79 insertions(+), 62 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal-video.c b/drivers/media/platform/ti-vpe/cal-video.c
index 1b9b0e0719d4..996b0b94648e 100644
--- a/drivers/media/platform/ti-vpe/cal-video.c
+++ b/drivers/media/platform/ti-vpe/cal-video.c
@@ -471,13 +471,12 @@ static void cal_buffer_queue(struct vb2_buffer *vb)
 	struct cal_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
 	struct cal_buffer *buf = container_of(vb, struct cal_buffer,
 					      vb.vb2_buf);
-	struct cal_dmaqueue *vidq = &ctx->vidq;
 	unsigned long flags;
 
 	/* recheck locking */
-	spin_lock_irqsave(&ctx->slock, flags);
-	list_add_tail(&buf->list, &vidq->active);
-	spin_unlock_irqrestore(&ctx->slock, flags);
+	spin_lock_irqsave(&ctx->dma.lock, flags);
+	list_add_tail(&buf->list, &ctx->dma.queue);
+	spin_unlock_irqrestore(&ctx->dma.lock, flags);
 }
 
 static void cal_release_buffers(struct cal_ctx *ctx,
@@ -485,42 +484,41 @@ static void cal_release_buffers(struct cal_ctx *ctx,
 {
 	struct cal_buffer *buf, *tmp;
 
-	/* Release all active buffers. */
-	spin_lock_irq(&ctx->slock);
+	/* Release all queued buffers. */
+	spin_lock_irq(&ctx->dma.lock);
 
-	list_for_each_entry_safe(buf, tmp, &ctx->vidq.active, list) {
+	list_for_each_entry_safe(buf, tmp, &ctx->dma.queue, list) {
 		list_del(&buf->list);
 		vb2_buffer_done(&buf->vb.vb2_buf, state);
 	}
 
-	if (ctx->next_frm != ctx->cur_frm)
-		vb2_buffer_done(&ctx->next_frm->vb.vb2_buf, state);
-	vb2_buffer_done(&ctx->cur_frm->vb.vb2_buf, state);
+	if (ctx->dma.pending != ctx->dma.active)
+		vb2_buffer_done(&ctx->dma.pending->vb.vb2_buf, state);
+	vb2_buffer_done(&ctx->dma.active->vb.vb2_buf, state);
 
-	ctx->cur_frm = NULL;
-	ctx->next_frm = NULL;
+	ctx->dma.active = NULL;
+	ctx->dma.pending = NULL;
 
-	spin_unlock_irq(&ctx->slock);
+	spin_unlock_irq(&ctx->dma.lock);
 }
 
 static int cal_start_streaming(struct vb2_queue *vq, unsigned int count)
 {
 	struct cal_ctx *ctx = vb2_get_drv_priv(vq);
-	struct cal_dmaqueue *dma_q = &ctx->vidq;
 	struct cal_buffer *buf;
 	unsigned long addr;
 	int ret;
 
-	spin_lock_irq(&ctx->slock);
-	buf = list_first_entry(&dma_q->active, struct cal_buffer, list);
-	ctx->cur_frm = buf;
-	ctx->next_frm = buf;
+	spin_lock_irq(&ctx->dma.lock);
+	buf = list_first_entry(&ctx->dma.queue, struct cal_buffer, list);
+	ctx->dma.active = buf;
+	ctx->dma.pending = buf;
 	list_del(&buf->list);
-	spin_unlock_irq(&ctx->slock);
+	spin_unlock_irq(&ctx->dma.lock);
 
-	addr = vb2_dma_contig_plane_dma_addr(&ctx->cur_frm->vb.vb2_buf, 0);
+	addr = vb2_dma_contig_plane_dma_addr(&ctx->dma.active->vb.vb2_buf, 0);
 	ctx->sequence = 0;
-	ctx->dma_state = CAL_DMA_RUNNING;
+	ctx->dma.state = CAL_DMA_RUNNING;
 
 	pm_runtime_get_sync(ctx->cal->dev);
 
@@ -542,7 +540,7 @@ static int cal_start_streaming(struct vb2_queue *vq, unsigned int count)
 err:
 	cal_ctx_wr_dma_disable(ctx);
 	cal_ctx_disable_irqs(ctx);
-	ctx->dma_state = CAL_DMA_STOPPED;
+	ctx->dma.state = CAL_DMA_STOPPED;
 
 	cal_release_buffers(ctx, VB2_BUF_STATE_QUEUED);
 	return ret;
@@ -711,10 +709,10 @@ int cal_ctx_v4l2_init(struct cal_ctx *ctx)
 	struct vb2_queue *q = &ctx->vb_vidq;
 	int ret;
 
-	INIT_LIST_HEAD(&ctx->vidq.active);
-	spin_lock_init(&ctx->slock);
+	INIT_LIST_HEAD(&ctx->dma.queue);
+	spin_lock_init(&ctx->dma.lock);
 	mutex_init(&ctx->mutex);
-	init_waitqueue_head(&ctx->dma_wait);
+	init_waitqueue_head(&ctx->dma.wait);
 
 	/* Initialize the vb2 queue. */
 	q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index ca9168fd7a13..edecd3b4c24f 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -424,9 +424,9 @@ static bool cal_ctx_wr_dma_stopped(struct cal_ctx *ctx)
 {
 	bool stopped;
 
-	spin_lock_irq(&ctx->slock);
-	stopped = ctx->dma_state == CAL_DMA_STOPPED;
-	spin_unlock_irq(&ctx->slock);
+	spin_lock_irq(&ctx->dma.lock);
+	stopped = ctx->dma.state == CAL_DMA_STOPPED;
+	spin_unlock_irq(&ctx->dma.lock);
 
 	return stopped;
 }
@@ -436,11 +436,11 @@ int cal_ctx_wr_dma_stop(struct cal_ctx *ctx)
 	long timeout;
 
 	/* Request DMA stop and wait until it completes. */
-	spin_lock_irq(&ctx->slock);
-	ctx->dma_state = CAL_DMA_STOP_REQUESTED;
-	spin_unlock_irq(&ctx->slock);
+	spin_lock_irq(&ctx->dma.lock);
+	ctx->dma.state = CAL_DMA_STOP_REQUESTED;
+	spin_unlock_irq(&ctx->dma.lock);
 
-	timeout = wait_event_timeout(ctx->dma_wait, cal_ctx_wr_dma_stopped(ctx),
+	timeout = wait_event_timeout(ctx->dma.wait, cal_ctx_wr_dma_stopped(ctx),
 				     msecs_to_jiffies(500));
 	if (!timeout) {
 		ctx_err(ctx, "failed to disable dma cleanly\n");
@@ -475,20 +475,18 @@ void cal_ctx_disable_irqs(struct cal_ctx *ctx)
 
 static inline void cal_irq_wdma_start(struct cal_ctx *ctx)
 {
-	struct cal_dmaqueue *dma_q = &ctx->vidq;
+	spin_lock(&ctx->dma.lock);
 
-	spin_lock(&ctx->slock);
-
-	if (ctx->dma_state == CAL_DMA_STOP_REQUESTED) {
+	if (ctx->dma.state == CAL_DMA_STOP_REQUESTED) {
 		/*
 		 * If a stop is requested, disable the write DMA context
 		 * immediately. The CAL_WR_DMA_CTRL_j.MODE field is shadowed,
 		 * the current frame will complete and the DMA will then stop.
 		 */
 		cal_ctx_wr_dma_disable(ctx);
-		ctx->dma_state = CAL_DMA_STOP_PENDING;
-	} else if (!list_empty(&dma_q->active) &&
-		   ctx->cur_frm == ctx->next_frm) {
+		ctx->dma.state = CAL_DMA_STOP_PENDING;
+	} else if (!list_empty(&ctx->dma.queue) &&
+		   ctx->dma.active == ctx->dma.pending) {
 		/*
 		 * Otherwise, if a new buffer is available, queue it to the
 		 * hardware.
@@ -496,36 +494,37 @@ static inline void cal_irq_wdma_start(struct cal_ctx *ctx)
 		struct cal_buffer *buf;
 		unsigned long addr;
 
-		buf = list_first_entry(&dma_q->active, struct cal_buffer, list);
+		buf = list_first_entry(&ctx->dma.queue, struct cal_buffer,
+				       list);
 		addr = vb2_dma_contig_plane_dma_addr(&buf->vb.vb2_buf, 0);
 		cal_ctx_wr_dma_addr(ctx, addr);
 
-		ctx->next_frm = buf;
+		ctx->dma.pending = buf;
 		list_del(&buf->list);
 	}
 
-	spin_unlock(&ctx->slock);
+	spin_unlock(&ctx->dma.lock);
 }
 
 static inline void cal_irq_wdma_end(struct cal_ctx *ctx)
 {
 	struct cal_buffer *buf = NULL;
 
-	spin_lock(&ctx->slock);
+	spin_lock(&ctx->dma.lock);
 
 	/* If the DMA context was stopping, it is now stopped. */
-	if (ctx->dma_state == CAL_DMA_STOP_PENDING) {
-		ctx->dma_state = CAL_DMA_STOPPED;
-		wake_up(&ctx->dma_wait);
+	if (ctx->dma.state == CAL_DMA_STOP_PENDING) {
+		ctx->dma.state = CAL_DMA_STOPPED;
+		wake_up(&ctx->dma.wait);
 	}
 
 	/* If a new buffer was queued, complete the current buffer. */
-	if (ctx->cur_frm != ctx->next_frm) {
-		buf = ctx->cur_frm;
-		ctx->cur_frm = ctx->next_frm;
+	if (ctx->dma.active != ctx->dma.pending) {
+		buf = ctx->dma.active;
+		ctx->dma.active = ctx->dma.pending;
 	}
 
-	spin_unlock(&ctx->slock);
+	spin_unlock(&ctx->dma.lock);
 
 	if (buf) {
 		buf->vb.vb2_buf.timestamp = ktime_get_ns();
diff --git a/drivers/media/platform/ti-vpe/cal.h b/drivers/media/platform/ti-vpe/cal.h
index 7e4589c6dee2..2eeb01996c4e 100644
--- a/drivers/media/platform/ti-vpe/cal.h
+++ b/drivers/media/platform/ti-vpe/cal.h
@@ -82,8 +82,38 @@ struct cal_buffer {
 	struct list_head	list;
 };
 
+/**
+ * struct cal_dmaqueue - Queue of DMA buffers
+ * @active: Buffer being DMA'ed to for the current frame
+ */
 struct cal_dmaqueue {
-	struct list_head	active;
+	/**
+	 * Protects all fields in the cal_dmaqueue.
+	 */
+	spinlock_t		lock;
+
+	/**
+	 * Buffers queued to the driver and waiting for DMA processing.
+	 * Buffers are added to the list by the vb2 .buffer_queue() operation,
+	 * and move to @pending when they are scheduled for the next frame.
+	 */
+	struct list_head	queue;
+	/**
+	 * Buffer provided to the hardware to DMA the next frame. Will move to
+	 * @active at the end of the current frame.
+	 */
+	struct cal_buffer	*pending;
+	/**
+	 * Buffer being DMA'ed to for the current frame. Will be retired and
+	 * given back to vb2 at the end of the current frame if a @pending
+	 * buffer has been scheduled to replace it.
+	 */
+	struct cal_buffer	*active;
+
+	/** State of the DMA engine. */
+	enum cal_dma_state	state;
+	/** Wait queue to signal a @state transition to CAL_DMA_STOPPED. */
+	struct wait_queue_head	wait;
 };
 
 struct cal_camerarx_data {
@@ -174,10 +204,8 @@ struct cal_ctx {
 
 	/* v4l2_ioctl mutex */
 	struct mutex		mutex;
-	/* v4l2 buffers lock */
-	spinlock_t		slock;
 
-	struct cal_dmaqueue	vidq;
+	struct cal_dmaqueue	dma;
 
 	/* video capture */
 	const struct cal_format_info	*fmtinfo;
@@ -192,14 +220,6 @@ struct cal_ctx {
 	struct vb2_queue	vb_vidq;
 	unsigned int		index;
 	unsigned int		cport;
-
-	/* Pointer pointing to current v4l2_buffer */
-	struct cal_buffer	*cur_frm;
-	/* Pointer pointing to next v4l2_buffer */
-	struct cal_buffer	*next_frm;
-
-	enum cal_dma_state	dma_state;
-	struct wait_queue_head	dma_wait;
 };
 
 extern unsigned int cal_debug;
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 104/107] media: ti-vpe: cal: Set cal_dmaqueue.pending to NULL when no pending buffer
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (102 preceding siblings ...)
  2020-06-14 23:59 ` [PATCH v1 103/107] media: ti-vpe: cal: Group all DMA queue fields in struct cal_dmaqueue Laurent Pinchart
@ 2020-06-14 23:59 ` Laurent Pinchart
  2020-06-14 23:59 ` [PATCH v1 105/107] media: ti-vpe: cal: Store buffer DMA address in dma_addr_t Laurent Pinchart
                   ` (4 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:59 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

When a pending buffer becomes active, the cal_dmaqueue.active field is
updated, but the pending field keeps the same value until a new buffer
becomes pending. This requires handling the special case of
pending == active in different places. Simplify the code by setting the
pending field to NULL when the pending buffer becomes active. Buffers
are now simply moved from queue to pending and from pending to active.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal-video.c | 14 ++++++++------
 drivers/media/platform/ti-vpe/cal.c       |  6 +++---
 2 files changed, 11 insertions(+), 9 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal-video.c b/drivers/media/platform/ti-vpe/cal-video.c
index 996b0b94648e..1f34e9b1aa55 100644
--- a/drivers/media/platform/ti-vpe/cal-video.c
+++ b/drivers/media/platform/ti-vpe/cal-video.c
@@ -492,12 +492,15 @@ static void cal_release_buffers(struct cal_ctx *ctx,
 		vb2_buffer_done(&buf->vb.vb2_buf, state);
 	}
 
-	if (ctx->dma.pending != ctx->dma.active)
+	if (ctx->dma.pending) {
 		vb2_buffer_done(&ctx->dma.pending->vb.vb2_buf, state);
-	vb2_buffer_done(&ctx->dma.active->vb.vb2_buf, state);
+		ctx->dma.pending = NULL;
+	}
 
-	ctx->dma.active = NULL;
-	ctx->dma.pending = NULL;
+	if (ctx->dma.active) {
+		vb2_buffer_done(&ctx->dma.active->vb.vb2_buf, state);
+		ctx->dma.active = NULL;
+	}
 
 	spin_unlock_irq(&ctx->dma.lock);
 }
@@ -511,12 +514,11 @@ static int cal_start_streaming(struct vb2_queue *vq, unsigned int count)
 
 	spin_lock_irq(&ctx->dma.lock);
 	buf = list_first_entry(&ctx->dma.queue, struct cal_buffer, list);
-	ctx->dma.active = buf;
 	ctx->dma.pending = buf;
 	list_del(&buf->list);
 	spin_unlock_irq(&ctx->dma.lock);
 
-	addr = vb2_dma_contig_plane_dma_addr(&ctx->dma.active->vb.vb2_buf, 0);
+	addr = vb2_dma_contig_plane_dma_addr(&buf->vb.vb2_buf, 0);
 	ctx->sequence = 0;
 	ctx->dma.state = CAL_DMA_RUNNING;
 
diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index edecd3b4c24f..c4ba52d2c196 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -485,8 +485,7 @@ static inline void cal_irq_wdma_start(struct cal_ctx *ctx)
 		 */
 		cal_ctx_wr_dma_disable(ctx);
 		ctx->dma.state = CAL_DMA_STOP_PENDING;
-	} else if (!list_empty(&ctx->dma.queue) &&
-		   ctx->dma.active == ctx->dma.pending) {
+	} else if (!list_empty(&ctx->dma.queue) && !ctx->dma.pending) {
 		/*
 		 * Otherwise, if a new buffer is available, queue it to the
 		 * hardware.
@@ -519,9 +518,10 @@ static inline void cal_irq_wdma_end(struct cal_ctx *ctx)
 	}
 
 	/* If a new buffer was queued, complete the current buffer. */
-	if (ctx->dma.active != ctx->dma.pending) {
+	if (ctx->dma.pending) {
 		buf = ctx->dma.active;
 		ctx->dma.active = ctx->dma.pending;
+		ctx->dma.pending = NULL;
 	}
 
 	spin_unlock(&ctx->dma.lock);
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 105/107] media: ti-vpe: cal: Store buffer DMA address in dma_addr_t
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (103 preceding siblings ...)
  2020-06-14 23:59 ` [PATCH v1 104/107] media: ti-vpe: cal: Set cal_dmaqueue.pending to NULL when no pending buffer Laurent Pinchart
@ 2020-06-14 23:59 ` Laurent Pinchart
  2020-06-14 23:59 ` [PATCH v1 106/107] media: ti-vpe: cal: Simplify the context API Laurent Pinchart
                   ` (3 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:59 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

dma_addr_t is the correct type to store DMA addresses. Replace incorrect
usage of unsigned long and unsigned int.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal-video.c | 2 +-
 drivers/media/platform/ti-vpe/cal.c       | 6 +++---
 drivers/media/platform/ti-vpe/cal.h       | 2 +-
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal-video.c b/drivers/media/platform/ti-vpe/cal-video.c
index 1f34e9b1aa55..0b4e5b11474d 100644
--- a/drivers/media/platform/ti-vpe/cal-video.c
+++ b/drivers/media/platform/ti-vpe/cal-video.c
@@ -509,7 +509,7 @@ static int cal_start_streaming(struct vb2_queue *vq, unsigned int count)
 {
 	struct cal_ctx *ctx = vb2_get_drv_priv(vq);
 	struct cal_buffer *buf;
-	unsigned long addr;
+	dma_addr_t addr;
 	int ret;
 
 	spin_lock_irq(&ctx->dma.lock);
diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index c4ba52d2c196..520f9e8ec917 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -406,9 +406,9 @@ void cal_ctx_wr_dma_config(struct cal_ctx *ctx)
 	ctx_dbg(3, ctx, "CAL_CTRL = 0x%08x\n", cal_read(ctx->cal, CAL_CTRL));
 }
 
-void cal_ctx_wr_dma_addr(struct cal_ctx *ctx, unsigned int dmaaddr)
+void cal_ctx_wr_dma_addr(struct cal_ctx *ctx, dma_addr_t addr)
 {
-	cal_write(ctx->cal, CAL_WR_DMA_ADDR(ctx->index), dmaaddr);
+	cal_write(ctx->cal, CAL_WR_DMA_ADDR(ctx->index), addr);
 }
 
 void cal_ctx_wr_dma_disable(struct cal_ctx *ctx)
@@ -491,7 +491,7 @@ static inline void cal_irq_wdma_start(struct cal_ctx *ctx)
 		 * hardware.
 		 */
 		struct cal_buffer *buf;
-		unsigned long addr;
+		dma_addr_t addr;
 
 		buf = list_first_entry(&ctx->dma.queue, struct cal_buffer,
 				       list);
diff --git a/drivers/media/platform/ti-vpe/cal.h b/drivers/media/platform/ti-vpe/cal.h
index 2eeb01996c4e..26b5eb20fd57 100644
--- a/drivers/media/platform/ti-vpe/cal.h
+++ b/drivers/media/platform/ti-vpe/cal.h
@@ -299,7 +299,7 @@ void cal_camerarx_destroy(struct cal_camerarx *phy);
 void cal_ctx_csi2_config(struct cal_ctx *ctx);
 void cal_ctx_pix_proc_config(struct cal_ctx *ctx);
 void cal_ctx_wr_dma_config(struct cal_ctx *ctx);
-void cal_ctx_wr_dma_addr(struct cal_ctx *ctx, unsigned int dmaaddr);
+void cal_ctx_wr_dma_addr(struct cal_ctx *ctx, dma_addr_t addr);
 void cal_ctx_wr_dma_disable(struct cal_ctx *ctx);
 int cal_ctx_wr_dma_stop(struct cal_ctx *ctx);
 void cal_ctx_enable_irqs(struct cal_ctx *ctx);
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 106/107] media: ti-vpe: cal: Simplify the context API
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (104 preceding siblings ...)
  2020-06-14 23:59 ` [PATCH v1 105/107] media: ti-vpe: cal: Store buffer DMA address in dma_addr_t Laurent Pinchart
@ 2020-06-14 23:59 ` Laurent Pinchart
  2020-06-14 23:59 ` [PATCH v1 107/107] media: ti-vpe: cal: Implement media controller centric API Laurent Pinchart
                   ` (2 subsequent siblings)
  108 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:59 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

Rework the context API exposed to cal-video.c to simplify it. The
configuration and enable steps are all grouped in a single
cal_ctx_start() function, and the DMA stop and IRQ disable are similarly
groupd in cal_ctx_stop(). The cal_ctx_wr_dma_addr() function is renamed
to cal_ctx_set_dma_addr() for consistency with the cal_ctx_ prefix of
the start and stop functions.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal-video.c | 21 +++------
 drivers/media/platform/ti-vpe/cal.c       | 54 +++++++++++++----------
 drivers/media/platform/ti-vpe/cal.h       | 11 ++---
 3 files changed, 41 insertions(+), 45 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal-video.c b/drivers/media/platform/ti-vpe/cal-video.c
index 0b4e5b11474d..0f8702bd77db 100644
--- a/drivers/media/platform/ti-vpe/cal-video.c
+++ b/drivers/media/platform/ti-vpe/cal-video.c
@@ -519,16 +519,11 @@ static int cal_start_streaming(struct vb2_queue *vq, unsigned int count)
 	spin_unlock_irq(&ctx->dma.lock);
 
 	addr = vb2_dma_contig_plane_dma_addr(&buf->vb.vb2_buf, 0);
-	ctx->sequence = 0;
-	ctx->dma.state = CAL_DMA_RUNNING;
 
 	pm_runtime_get_sync(ctx->cal->dev);
 
-	cal_ctx_csi2_config(ctx);
-	cal_ctx_pix_proc_config(ctx);
-	cal_ctx_wr_dma_config(ctx);
-	cal_ctx_wr_dma_addr(ctx, addr);
-	cal_ctx_enable_irqs(ctx);
+	cal_ctx_set_dma_addr(ctx, addr);
+	cal_ctx_start(ctx);
 
 	ret = v4l2_subdev_call(&ctx->phy->subdev, video, s_stream, 1);
 	if (ret)
@@ -540,9 +535,8 @@ static int cal_start_streaming(struct vb2_queue *vq, unsigned int count)
 	return 0;
 
 err:
-	cal_ctx_wr_dma_disable(ctx);
-	cal_ctx_disable_irqs(ctx);
-	ctx->dma.state = CAL_DMA_STOPPED;
+	cal_ctx_stop(ctx);
+	pm_runtime_put_sync(ctx->cal->dev);
 
 	cal_release_buffers(ctx, VB2_BUF_STATE_QUEUED);
 	return ret;
@@ -552,14 +546,13 @@ static void cal_stop_streaming(struct vb2_queue *vq)
 {
 	struct cal_ctx *ctx = vb2_get_drv_priv(vq);
 
-	cal_ctx_wr_dma_stop(ctx);
-	cal_ctx_disable_irqs(ctx);
+	cal_ctx_stop(ctx);
 
 	v4l2_subdev_call(&ctx->phy->subdev, video, s_stream, 0);
 
+	pm_runtime_put_sync(ctx->cal->dev);
+
 	cal_release_buffers(ctx, VB2_BUF_STATE_ERROR);
-
-	pm_runtime_put_sync(ctx->cal->dev);
 }
 
 static const struct vb2_ops cal_video_qops = {
diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index 520f9e8ec917..f97c213f716f 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -280,7 +280,7 @@ void cal_quickdump_regs(struct cal_dev *cal)
  * ------------------------------------------------------------------
  */
 
-void cal_ctx_csi2_config(struct cal_ctx *ctx)
+static void cal_ctx_csi2_config(struct cal_ctx *ctx)
 {
 	u32 val;
 
@@ -305,7 +305,7 @@ void cal_ctx_csi2_config(struct cal_ctx *ctx)
 		cal_read(ctx->cal, CAL_CSI2_CTX0(ctx->index)));
 }
 
-void cal_ctx_pix_proc_config(struct cal_ctx *ctx)
+static void cal_ctx_pix_proc_config(struct cal_ctx *ctx)
 {
 	u32 val, extract, pack;
 
@@ -356,7 +356,7 @@ void cal_ctx_pix_proc_config(struct cal_ctx *ctx)
 		cal_read(ctx->cal, CAL_PIX_PROC(ctx->index)));
 }
 
-void cal_ctx_wr_dma_config(struct cal_ctx *ctx)
+static void cal_ctx_wr_dma_config(struct cal_ctx *ctx)
 {
 	unsigned int stride = ctx->v_fmt.fmt.pix.bytesperline;
 	u32 val;
@@ -406,12 +406,12 @@ void cal_ctx_wr_dma_config(struct cal_ctx *ctx)
 	ctx_dbg(3, ctx, "CAL_CTRL = 0x%08x\n", cal_read(ctx->cal, CAL_CTRL));
 }
 
-void cal_ctx_wr_dma_addr(struct cal_ctx *ctx, dma_addr_t addr)
+void cal_ctx_set_dma_addr(struct cal_ctx *ctx, dma_addr_t addr)
 {
 	cal_write(ctx->cal, CAL_WR_DMA_ADDR(ctx->index), addr);
 }
 
-void cal_ctx_wr_dma_disable(struct cal_ctx *ctx)
+static void cal_ctx_wr_dma_disable(struct cal_ctx *ctx)
 {
 	u32 val = cal_read(ctx->cal, CAL_WR_DMA_CTRL(ctx->index));
 
@@ -431,11 +431,31 @@ static bool cal_ctx_wr_dma_stopped(struct cal_ctx *ctx)
 	return stopped;
 }
 
-int cal_ctx_wr_dma_stop(struct cal_ctx *ctx)
+void cal_ctx_start(struct cal_ctx *ctx)
+{
+	ctx->sequence = 0;
+	ctx->dma.state = CAL_DMA_RUNNING;
+
+	/* Configure the CSI-2, pixel processing and write DMA contexts. */
+	cal_ctx_csi2_config(ctx);
+	cal_ctx_pix_proc_config(ctx);
+	cal_ctx_wr_dma_config(ctx);
+
+	/* Enable IRQ_WDMA_END and IRQ_WDMA_START. */
+	cal_write(ctx->cal, CAL_HL_IRQENABLE_SET(1),
+		  CAL_HL_IRQ_MASK(ctx->index));
+	cal_write(ctx->cal, CAL_HL_IRQENABLE_SET(2),
+		  CAL_HL_IRQ_MASK(ctx->index));
+}
+
+void cal_ctx_stop(struct cal_ctx *ctx)
 {
 	long timeout;
 
-	/* Request DMA stop and wait until it completes. */
+	/*
+	 * Request DMA stop and wait until it completes. If completion times
+	 * out, forcefully disable the DMA.
+	 */
 	spin_lock_irq(&ctx->dma.lock);
 	ctx->dma.state = CAL_DMA_STOP_REQUESTED;
 	spin_unlock_irq(&ctx->dma.lock);
@@ -444,28 +464,16 @@ int cal_ctx_wr_dma_stop(struct cal_ctx *ctx)
 				     msecs_to_jiffies(500));
 	if (!timeout) {
 		ctx_err(ctx, "failed to disable dma cleanly\n");
-		return -ETIMEDOUT;
+		cal_ctx_wr_dma_disable(ctx);
 	}
 
-	return 0;
-}
-
-void cal_ctx_enable_irqs(struct cal_ctx *ctx)
-{
-	/* Enable IRQ_WDMA_END and IRQ_WDMA_START. */
-	cal_write(ctx->cal, CAL_HL_IRQENABLE_SET(1),
-		  CAL_HL_IRQ_MASK(ctx->index));
-	cal_write(ctx->cal, CAL_HL_IRQENABLE_SET(2),
-		  CAL_HL_IRQ_MASK(ctx->index));
-}
-
-void cal_ctx_disable_irqs(struct cal_ctx *ctx)
-{
 	/* Disable IRQ_WDMA_END and IRQ_WDMA_START. */
 	cal_write(ctx->cal, CAL_HL_IRQENABLE_CLR(1),
 		  CAL_HL_IRQ_MASK(ctx->index));
 	cal_write(ctx->cal, CAL_HL_IRQENABLE_CLR(2),
 		  CAL_HL_IRQ_MASK(ctx->index));
+
+	ctx->dma.state = CAL_DMA_STOPPED;
 }
 
 /* ------------------------------------------------------------------
@@ -496,7 +504,7 @@ static inline void cal_irq_wdma_start(struct cal_ctx *ctx)
 		buf = list_first_entry(&ctx->dma.queue, struct cal_buffer,
 				       list);
 		addr = vb2_dma_contig_plane_dma_addr(&buf->vb.vb2_buf, 0);
-		cal_ctx_wr_dma_addr(ctx, addr);
+		cal_ctx_set_dma_addr(ctx, addr);
 
 		ctx->dma.pending = buf;
 		list_del(&buf->list);
diff --git a/drivers/media/platform/ti-vpe/cal.h b/drivers/media/platform/ti-vpe/cal.h
index 26b5eb20fd57..036b944c3862 100644
--- a/drivers/media/platform/ti-vpe/cal.h
+++ b/drivers/media/platform/ti-vpe/cal.h
@@ -296,14 +296,9 @@ struct cal_camerarx *cal_camerarx_create(struct cal_dev *cal,
 					 unsigned int instance);
 void cal_camerarx_destroy(struct cal_camerarx *phy);
 
-void cal_ctx_csi2_config(struct cal_ctx *ctx);
-void cal_ctx_pix_proc_config(struct cal_ctx *ctx);
-void cal_ctx_wr_dma_config(struct cal_ctx *ctx);
-void cal_ctx_wr_dma_addr(struct cal_ctx *ctx, dma_addr_t addr);
-void cal_ctx_wr_dma_disable(struct cal_ctx *ctx);
-int cal_ctx_wr_dma_stop(struct cal_ctx *ctx);
-void cal_ctx_enable_irqs(struct cal_ctx *ctx);
-void cal_ctx_disable_irqs(struct cal_ctx *ctx);
+void cal_ctx_set_dma_addr(struct cal_ctx *ctx, dma_addr_t addr);
+void cal_ctx_start(struct cal_ctx *ctx);
+void cal_ctx_stop(struct cal_ctx *ctx);
 
 int cal_ctx_v4l2_register(struct cal_ctx *ctx);
 void cal_ctx_v4l2_unregister(struct cal_ctx *ctx);
-- 
Regards,

Laurent Pinchart


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

* [PATCH v1 107/107] media: ti-vpe: cal: Implement media controller centric API
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (105 preceding siblings ...)
  2020-06-14 23:59 ` [PATCH v1 106/107] media: ti-vpe: cal: Simplify the context API Laurent Pinchart
@ 2020-06-14 23:59 ` Laurent Pinchart
  2020-06-19 14:46   ` Benoit Parrot
  2020-06-16 11:43 ` [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Tomi Valkeinen
  2020-06-19 14:53 ` Benoit Parrot
  108 siblings, 1 reply; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-14 23:59 UTC (permalink / raw)
  To: linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

The CAL driver is video node centric, it controls the whole device
through the video device nodes. This limits the possible use cases as it
can't support sources that are more complex than a single subdev. To
support more complex hardware pipelines, implement support for the media
controller centric API. The exposed API can be selected through a module
parameter.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal-camerarx.c |   1 +
 drivers/media/platform/ti-vpe/cal-video.c    | 358 ++++++++++++++-----
 drivers/media/platform/ti-vpe/cal.c          |  10 +-
 drivers/media/platform/ti-vpe/cal.h          |   2 +
 4 files changed, 289 insertions(+), 82 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal-camerarx.c b/drivers/media/platform/ti-vpe/cal-camerarx.c
index 2e7a3bc716cf..014ca46509db 100644
--- a/drivers/media/platform/ti-vpe/cal-camerarx.c
+++ b/drivers/media/platform/ti-vpe/cal-camerarx.c
@@ -818,6 +818,7 @@ struct cal_camerarx *cal_camerarx_create(struct cal_dev *cal,
 	sd = &phy->subdev;
 	v4l2_subdev_init(sd, &cal_camerarx_subdev_ops);
 	sd->entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
+	sd->flags = V4L2_SUBDEV_FL_HAS_DEVNODE;
 	snprintf(sd->name, sizeof(sd->name), "CAMERARX%u", instance);
 	sd->dev = cal->dev;
 
diff --git a/drivers/media/platform/ti-vpe/cal-video.c b/drivers/media/platform/ti-vpe/cal-video.c
index 0f8702bd77db..5f9cd449f027 100644
--- a/drivers/media/platform/ti-vpe/cal-video.c
+++ b/drivers/media/platform/ti-vpe/cal-video.c
@@ -40,40 +40,10 @@ static char *fourcc_to_str(u32 fmt)
 }
 
 /* ------------------------------------------------------------------
- *	V4L2 Video IOCTLs
+ *	V4L2 Common IOCTLs
  * ------------------------------------------------------------------
  */
 
-static const struct cal_format_info *find_format_by_pix(struct cal_ctx *ctx,
-							u32 pixelformat)
-{
-	const struct cal_format_info *fmtinfo;
-	unsigned int k;
-
-	for (k = 0; k < ctx->num_active_fmt; k++) {
-		fmtinfo = ctx->active_fmt[k];
-		if (fmtinfo->fourcc == pixelformat)
-			return fmtinfo;
-	}
-
-	return NULL;
-}
-
-static const struct cal_format_info *find_format_by_code(struct cal_ctx *ctx,
-							 u32 code)
-{
-	const struct cal_format_info *fmtinfo;
-	unsigned int k;
-
-	for (k = 0; k < ctx->num_active_fmt; k++) {
-		fmtinfo = ctx->active_fmt[k];
-		if (fmtinfo->code == code)
-			return fmtinfo;
-	}
-
-	return NULL;
-}
-
 static int cal_querycap(struct file *file, void *priv,
 			struct v4l2_capability *cap)
 {
@@ -87,6 +57,51 @@ static int cal_querycap(struct file *file, void *priv,
 	return 0;
 }
 
+static int cal_g_fmt_vid_cap(struct file *file, void *priv,
+			     struct v4l2_format *f)
+{
+	struct cal_ctx *ctx = video_drvdata(file);
+
+	*f = ctx->v_fmt;
+
+	return 0;
+}
+
+/* ------------------------------------------------------------------
+ *	V4L2 Video Node Centric IOCTLs
+ * ------------------------------------------------------------------
+ */
+
+static const struct cal_format_info *find_format_by_pix(struct cal_ctx *ctx,
+							u32 pixelformat)
+{
+	const struct cal_format_info *fmtinfo;
+	unsigned int k;
+
+	for (k = 0; k < ctx->num_active_fmt; k++) {
+		fmtinfo = ctx->active_fmt[k];
+		if (fmtinfo->fourcc == pixelformat)
+			return fmtinfo;
+	}
+
+	return NULL;
+}
+
+static const struct cal_format_info *find_format_by_code(struct cal_ctx *ctx,
+							 u32 code)
+{
+	const struct cal_format_info *fmtinfo;
+	unsigned int k;
+
+	for (k = 0; k < ctx->num_active_fmt; k++) {
+		fmtinfo = ctx->active_fmt[k];
+		if (fmtinfo->code == code)
+			return fmtinfo;
+	}
+
+	return NULL;
+}
+
 static int cal_enum_fmt_vid_cap(struct file *file, void  *priv,
 				struct v4l2_fmtdesc *f)
 {
@@ -174,16 +189,6 @@ static void cal_calc_format_size(struct cal_ctx *ctx,
 		f->fmt.pix.bytesperline, f->fmt.pix.sizeimage);
 }
 
-static int cal_g_fmt_vid_cap(struct file *file, void *priv,
-			     struct v4l2_format *f)
-{
-	struct cal_ctx *ctx = video_drvdata(file);
-
-	*f = ctx->v_fmt;
-
-	return 0;
-}
-
 static int cal_try_fmt_vid_cap(struct file *file, void *priv,
 			       struct v4l2_format *f)
 {
@@ -383,17 +388,7 @@ static int cal_enum_frameintervals(struct file *file, void *priv,
 	return 0;
 }
 
-static const struct v4l2_file_operations cal_fops = {
-	.owner		= THIS_MODULE,
-	.open           = v4l2_fh_open,
-	.release        = vb2_fop_release,
-	.read           = vb2_fop_read,
-	.poll		= vb2_fop_poll,
-	.unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */
-	.mmap           = vb2_fop_mmap,
-};
-
-static const struct v4l2_ioctl_ops cal_ioctl_ops = {
+static const struct v4l2_ioctl_ops cal_ioctl_video_ops = {
 	.vidioc_querycap      = cal_querycap,
 	.vidioc_enum_fmt_vid_cap  = cal_enum_fmt_vid_cap,
 	.vidioc_g_fmt_vid_cap     = cal_g_fmt_vid_cap,
@@ -419,7 +414,153 @@ static const struct v4l2_ioctl_ops cal_ioctl_ops = {
 };
 
 /* ------------------------------------------------------------------
- *	videobuf2 Operations
+ *	V4L2 Media Controller Centric IOCTLs
+ * ------------------------------------------------------------------
+ */
+
+static int cal_mc_enum_fmt_vid_cap(struct file *file, void  *priv,
+				   struct v4l2_fmtdesc *f)
+{
+	if (f->index >= cal_num_formats)
+		return -EINVAL;
+
+	f->pixelformat = cal_formats[f->index].fourcc;
+	f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+	return 0;
+}
+
+static void cal_mc_try_fmt(struct cal_ctx *ctx, struct v4l2_format *f,
+			   const struct cal_format_info **info)
+{
+	struct v4l2_pix_format *format = &f->fmt.pix;
+	const struct cal_format_info *fmtinfo;
+	unsigned int bpp;
+
+	/*
+	 * Default to the first format is the requested pixel format code isn't
+	 * supported.
+	 */
+	fmtinfo = cal_format_by_fourcc(f->fmt.pix.pixelformat);
+	if (!fmtinfo)
+		fmtinfo = &cal_formats[0];
+
+	/*
+	 * Clamp the size, update the pixel format. The field and colorspace are
+	 * accepted as-is, except for V4L2_FIELD_ANY that is turned into
+	 * V4L2_FIELD_NONE.
+	 */
+	bpp = ALIGN(fmtinfo->bpp, 8);
+
+	format->width = clamp_t(unsigned int, format->width,
+				CAL_MIN_WIDTH_BYTES * 8 / bpp,
+				CAL_MAX_WIDTH_BYTES * 8 / bpp);
+	format->height = clamp_t(unsigned int, format->height,
+				 CAL_MIN_HEIGHT_LINES, CAL_MAX_HEIGHT_LINES);
+	format->pixelformat = fmtinfo->fourcc;
+
+	if (format->field == V4L2_FIELD_ANY)
+		format->field = V4L2_FIELD_NONE;
+
+	/*
+	 * Calculate the number of bytes per line and the image size. The
+	 * hardware stores the stride as a number of 16 bytes words, in a
+	 * signed 15-bit value. Only 14 bits are thus usable.
+	 */
+	format->bytesperline = ALIGN(clamp(format->bytesperline,
+					   format->width * bpp / 8,
+					   ((1U << 14) - 1) * 16), 16);
+
+	format->sizeimage = format->height * format->bytesperline;
+
+	if (info)
+		*info = fmtinfo;
+
+	ctx_dbg(3, ctx, "%s: %s %ux%u (bytesperline %u sizeimage %u)\n",
+		__func__, fourcc_to_str(format->pixelformat),
+		format->width, format->height,
+		format->bytesperline, format->sizeimage);
+}
+
+static int cal_mc_try_fmt_vid_cap(struct file *file, void *priv,
+				  struct v4l2_format *f)
+{
+	struct cal_ctx *ctx = video_drvdata(file);
+
+	cal_mc_try_fmt(ctx, f, NULL);
+	return 0;
+}
+
+static int cal_mc_s_fmt_vid_cap(struct file *file, void *priv,
+				struct v4l2_format *f)
+{
+	struct cal_ctx *ctx = video_drvdata(file);
+	const struct cal_format_info *fmtinfo;
+
+	if (vb2_is_busy(&ctx->vb_vidq)) {
+		ctx_dbg(3, ctx, "%s device busy\n", __func__);
+		return -EBUSY;
+	}
+
+	cal_mc_try_fmt(ctx, f, &fmtinfo);
+
+	ctx->v_fmt = *f;
+	ctx->fmtinfo = fmtinfo;
+
+	return 0;
+}
+
+static int cal_mc_enum_framesizes(struct file *file, void *fh,
+				  struct v4l2_frmsizeenum *fsize)
+{
+	struct cal_ctx *ctx = video_drvdata(file);
+	const struct cal_format_info *fmtinfo;
+	unsigned int bpp;
+
+	if (fsize->index > 0)
+		return -EINVAL;
+
+	fmtinfo = cal_format_by_fourcc(fsize->pixel_format);
+	if (!fmtinfo) {
+		ctx_dbg(3, ctx, "Invalid pixel format 0x%08x\n",
+			fsize->pixel_format);
+		return -EINVAL;
+	}
+
+	bpp = ALIGN(fmtinfo->bpp, 8);
+
+	fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
+	fsize->stepwise.min_width = CAL_MIN_WIDTH_BYTES * 8 / bpp;
+	fsize->stepwise.max_width = CAL_MAX_WIDTH_BYTES * 8 / bpp;
+	fsize->stepwise.step_width = 64 / bpp;
+	fsize->stepwise.min_height = CAL_MIN_HEIGHT_LINES;
+	fsize->stepwise.max_height = CAL_MAX_HEIGHT_LINES;
+	fsize->stepwise.step_height = 1;
+
+	return 0;
+}
+
+static const struct v4l2_ioctl_ops cal_ioctl_mc_ops = {
+	.vidioc_querycap      = cal_querycap,
+	.vidioc_enum_fmt_vid_cap  = cal_mc_enum_fmt_vid_cap,
+	.vidioc_g_fmt_vid_cap     = cal_g_fmt_vid_cap,
+	.vidioc_try_fmt_vid_cap   = cal_mc_try_fmt_vid_cap,
+	.vidioc_s_fmt_vid_cap     = cal_mc_s_fmt_vid_cap,
+	.vidioc_enum_framesizes   = cal_mc_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,
+	.vidioc_log_status    = v4l2_ctrl_log_status,
+};
+
+/* ------------------------------------------------------------------
+ *	videobuf2 Common Operations
  * ------------------------------------------------------------------
  */
 
@@ -505,6 +646,26 @@ static void cal_release_buffers(struct cal_ctx *ctx,
 	spin_unlock_irq(&ctx->dma.lock);
 }
 
+/* ------------------------------------------------------------------
+ *	videobuf2 Operations
+ * ------------------------------------------------------------------
+ */
+
+static int cal_video_check_format(struct cal_ctx *ctx)
+{
+	const struct v4l2_mbus_framefmt *format;
+
+	format = &ctx->phy->formats[CAL_CAMERARX_PAD_SOURCE];
+
+	if (ctx->fmtinfo->code != format->code ||
+	    ctx->v_fmt.fmt.pix.height != format->height ||
+	    ctx->v_fmt.fmt.pix.width != format->width ||
+	    ctx->v_fmt.fmt.pix.field != format->field)
+		return -EPIPE;
+
+	return 0;
+}
+
 static int cal_start_streaming(struct vb2_queue *vq, unsigned int count)
 {
 	struct cal_ctx *ctx = vb2_get_drv_priv(vq);
@@ -512,6 +673,23 @@ static int cal_start_streaming(struct vb2_queue *vq, unsigned int count)
 	dma_addr_t addr;
 	int ret;
 
+	ret = media_pipeline_start(&ctx->vdev.entity, &ctx->phy->pipe);
+	if (ret < 0) {
+		ctx_err(ctx, "Failed to start media pipeline: %d\n", ret);
+		return ret;
+	}
+
+	/*
+	 * Verify that the currently configured format matches the output of
+	 * the connected CAMERARX.
+	 */
+	ret = cal_video_check_format(ctx);
+	if (ret < 0) {
+		ctx_dbg(3, ctx,
+			"Format mismatch between CAMERARX and video node\n");
+		goto error_pipeline;
+	}
+
 	spin_lock_irq(&ctx->dma.lock);
 	buf = list_first_entry(&ctx->dma.queue, struct cal_buffer, list);
 	ctx->dma.pending = buf;
@@ -527,18 +705,21 @@ static int cal_start_streaming(struct vb2_queue *vq, unsigned int count)
 
 	ret = v4l2_subdev_call(&ctx->phy->subdev, video, s_stream, 1);
 	if (ret)
-		goto err;
+		goto error_stop;
 
 	if (cal_debug >= 4)
 		cal_quickdump_regs(ctx->cal);
 
 	return 0;
 
-err:
+error_stop:
 	cal_ctx_stop(ctx);
 	pm_runtime_put_sync(ctx->cal->dev);
 
+error_pipeline:
+	media_pipeline_stop(&ctx->vdev.entity);
 	cal_release_buffers(ctx, VB2_BUF_STATE_QUEUED);
+
 	return ret;
 }
 
@@ -553,6 +734,8 @@ static void cal_stop_streaming(struct vb2_queue *vq)
 	pm_runtime_put_sync(ctx->cal->dev);
 
 	cal_release_buffers(ctx, VB2_BUF_STATE_ERROR);
+
+	media_pipeline_stop(&ctx->vdev.entity);
 }
 
 static const struct vb2_ops cal_video_qops = {
@@ -570,13 +753,14 @@ static const struct vb2_ops cal_video_qops = {
  * ------------------------------------------------------------------
  */
 
-static const struct video_device cal_videodev = {
-	.name		= CAL_MODULE_NAME,
-	.fops		= &cal_fops,
-	.ioctl_ops	= &cal_ioctl_ops,
-	.minor		= -1,
-	.release	= video_device_release_empty,
-	.device_caps	= V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING,
+static const struct v4l2_file_operations cal_fops = {
+	.owner		= THIS_MODULE,
+	.open           = v4l2_fh_open,
+	.release        = vb2_fop_release,
+	.read           = vb2_fop_read,
+	.poll		= vb2_fop_poll,
+	.unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */
+	.mmap           = vb2_fop_mmap,
 };
 
 static int cal_ctx_v4l2_init_formats(struct cal_ctx *ctx)
@@ -650,19 +834,22 @@ static int cal_ctx_v4l2_init_formats(struct cal_ctx *ctx)
 
 int cal_ctx_v4l2_register(struct cal_ctx *ctx)
 {
-	struct v4l2_ctrl_handler *hdl = &ctx->ctrl_handler;
 	struct video_device *vfd = &ctx->vdev;
 	int ret;
 
-	ret = cal_ctx_v4l2_init_formats(ctx);
-	if (ret)
-		return ret;
+	if (!cal_mc_api) {
+		struct v4l2_ctrl_handler *hdl = &ctx->ctrl_handler;
 
-	ret = v4l2_ctrl_add_handler(hdl, ctx->phy->sensor->ctrl_handler, NULL,
-				    true);
-	if (ret < 0) {
-		ctx_err(ctx, "Failed to add sensor ctrl handler\n");
-		return ret;
+		ret = cal_ctx_v4l2_init_formats(ctx);
+		if (ret)
+			return ret;
+
+		ret = v4l2_ctrl_add_handler(hdl, ctx->phy->sensor->ctrl_handler,
+					    NULL, true);
+		if (ret < 0) {
+			ctx_err(ctx, "Failed to add sensor ctrl handler\n");
+			return ret;
+		}
 	}
 
 	ret = video_register_device(vfd, VFL_TYPE_VIDEO, cal_video_nr);
@@ -699,7 +886,6 @@ void cal_ctx_v4l2_unregister(struct cal_ctx *ctx)
 
 int cal_ctx_v4l2_init(struct cal_ctx *ctx)
 {
-	struct v4l2_ctrl_handler *hdl = &ctx->ctrl_handler;
 	struct video_device *vfd = &ctx->vdev;
 	struct vb2_queue *q = &ctx->vb_vidq;
 	int ret;
@@ -726,10 +912,14 @@ int cal_ctx_v4l2_init(struct cal_ctx *ctx)
 		return ret;
 
 	/* Initialize the video device and media entity. */
-	*vfd = cal_videodev;
+	vfd->fops = &cal_fops;
+	vfd->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING
+			 | (cal_mc_api ? V4L2_CAP_IO_MC : 0);
 	vfd->v4l2_dev = &ctx->cal->v4l2_dev;
 	vfd->queue = q;
 	snprintf(vfd->name, sizeof(vfd->name), "CAL output %u", ctx->index);
+	vfd->release = video_device_release_empty;
+	vfd->ioctl_ops = cal_mc_api ? &cal_ioctl_mc_ops : &cal_ioctl_video_ops;
 	vfd->lock = &ctx->mutex;
 	video_set_drvdata(vfd, ctx);
 
@@ -738,15 +928,19 @@ int cal_ctx_v4l2_init(struct cal_ctx *ctx)
 	if (ret < 0)
 		return ret;
 
-	/* Initialize the control handler. */
-	ret = v4l2_ctrl_handler_init(hdl, 11);
-	if (ret < 0) {
-		ctx_err(ctx, "Failed to init ctrl handler\n");
-		goto error;
+	if (!cal_mc_api) {
+		/* Initialize the control handler. */
+		struct v4l2_ctrl_handler *hdl = &ctx->ctrl_handler;
+
+		ret = v4l2_ctrl_handler_init(hdl, 11);
+		if (ret < 0) {
+			ctx_err(ctx, "Failed to init ctrl handler\n");
+			goto error;
+		}
+
+		vfd->ctrl_handler = hdl;
 	}
 
-	vfd->ctrl_handler = hdl;
-
 	return 0;
 
 error:
@@ -756,6 +950,8 @@ int cal_ctx_v4l2_init(struct cal_ctx *ctx)
 
 void cal_ctx_v4l2_cleanup(struct cal_ctx *ctx)
 {
-	v4l2_ctrl_handler_free(&ctx->ctrl_handler);
+	if (!cal_mc_api)
+		v4l2_ctrl_handler_free(&ctx->ctrl_handler);
+
 	media_entity_cleanup(&ctx->vdev.entity);
 }
diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index f97c213f716f..caea3e129c87 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -43,6 +43,10 @@ unsigned int cal_debug;
 module_param_named(debug, cal_debug, uint, 0644);
 MODULE_PARM_DESC(debug, "activates debug info");
 
+bool cal_mc_api;
+module_param_named(mc_api, cal_mc_api, bool, 0444);
+MODULE_PARM_DESC(debug, "activates MC API");
+
 /* ------------------------------------------------------------------
  *	Format Handling
  * ------------------------------------------------------------------
@@ -655,13 +659,17 @@ static int cal_async_notifier_complete(struct v4l2_async_notifier *notifier)
 {
 	struct cal_dev *cal = container_of(notifier, struct cal_dev, notifier);
 	unsigned int i;
+	int ret = 0;
 
 	for (i = 0; i < ARRAY_SIZE(cal->ctx); ++i) {
 		if (cal->ctx[i])
 			cal_ctx_v4l2_register(cal->ctx[i]);
 	}
 
-	return 0;
+	if (cal_mc_api)
+		ret = v4l2_device_register_subdev_nodes(&cal->v4l2_dev);
+
+	return ret;
 }
 
 static const struct v4l2_async_notifier_operations cal_async_notifier_ops = {
diff --git a/drivers/media/platform/ti-vpe/cal.h b/drivers/media/platform/ti-vpe/cal.h
index 036b944c3862..f6b4c9a73aab 100644
--- a/drivers/media/platform/ti-vpe/cal.h
+++ b/drivers/media/platform/ti-vpe/cal.h
@@ -160,6 +160,7 @@ struct cal_camerarx {
 	struct device_node	*sensor_ep_node;
 	struct device_node	*sensor_node;
 	struct v4l2_subdev	*sensor;
+	struct media_pipeline	pipe;
 
 	struct v4l2_subdev	subdev;
 	struct media_pad	pads[2];
@@ -224,6 +225,7 @@ struct cal_ctx {
 
 extern unsigned int cal_debug;
 extern int cal_video_nr;
+extern bool cal_mc_api;
 
 #define cal_dbg(level, cal, fmt, arg...)				\
 	do {								\
-- 
Regards,

Laurent Pinchart


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

* Re: [PATCH v1 082/107] media: ti-vpe: cal: Move CAL I/O accessors to cal.h
  2020-06-14 23:59 ` [PATCH v1 082/107] media: ti-vpe: cal: Move CAL I/O accessors to cal.h Laurent Pinchart
@ 2020-06-15  2:50     ` kernel test robot
  2020-06-19  4:18   ` Ezequiel Garcia
  1 sibling, 0 replies; 150+ messages in thread
From: kernel test robot @ 2020-06-15  2:50 UTC (permalink / raw)
  To: Laurent Pinchart, linux-media; +Cc: kbuild-all, Tomi Valkeinen, Benoit Parrot

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

Hi Laurent,

I love your patch! Perhaps something to improve:

[auto build test WARNING on linuxtv-media/master]
[also build test WARNING on v5.8-rc1 next-20200614]
[if your patch is applied to the wrong git tree, please drop us a note to help
improve the system. BTW, we also suggest to use '--base' option to specify the
base tree in git format-patch, please see https://stackoverflow.com/a/37406982]

url:    https://github.com/0day-ci/linux/commits/Laurent-Pinchart/media-ti-vpe-cal-Add-media-controller-support/20200615-080443
base:   git://linuxtv.org/media_tree.git master
config: sh-allmodconfig (attached as .config)
compiler: sh4-linux-gcc (GCC) 9.3.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross ARCH=sh 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>, old ones prefixed by <<):

In file included from include/linux/err.h:5,
from include/linux/clk.h:12,
from drivers/media/platform/ti-vpe/cal.c:12:
drivers/media/platform/ti-vpe/cal.h: In function 'cal_write_field':
include/linux/bitfield.h:52:28: warning: comparison is always false due to limited range of data type [-Wtype-limits]
52 |   BUILD_BUG_ON_MSG((_mask) > (typeof(_reg))~0ull,           |                            ^
include/linux/compiler.h:330:9: note: in definition of macro '__compiletime_assert'
330 |   if (!(condition))              |         ^~~~~~~~~
include/linux/compiler.h:350:2: note: in expansion of macro '_compiletime_assert'
350 |  _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__)
|  ^~~~~~~~~~~~~~~~~~~
include/linux/build_bug.h:39:37: note: in expansion of macro 'compiletime_assert'
39 | #define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg)
|                                     ^~~~~~~~~~~~~~~~~~
include/linux/bitfield.h:52:3: note: in expansion of macro 'BUILD_BUG_ON_MSG'
52 |   BUILD_BUG_ON_MSG((_mask) > (typeof(_reg))~0ull,           |   ^~~~~~~~~~~~~~~~
include/linux/bitfield.h:94:3: note: in expansion of macro '__BF_FIELD_CHECK'
94 |   __BF_FIELD_CHECK(_mask, 0ULL, _val, "FIELD_PREP: ");          |   ^~~~~~~~~~~~~~~~
>> drivers/media/platform/ti-vpe/cal.h:229:9: note: in expansion of macro 'FIELD_PREP'
229 |  val |= FIELD_PREP(mask, value);
|         ^~~~~~~~~~

vim +/FIELD_PREP +229 drivers/media/platform/ti-vpe/cal.h

   222	
   223	static inline void cal_write_field(struct cal_dev *cal, u32 offset, u32 value,
   224					   u32 mask)
   225	{
   226		u32 val = cal_read(cal, offset);
   227	
   228		val &= ~mask;
 > 229		val |= FIELD_PREP(mask, value);
   230		cal_write(cal, offset, val);
   231	}
   232	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 54847 bytes --]

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

* Re: [PATCH v1 082/107] media: ti-vpe: cal: Move CAL I/O accessors to cal.h
@ 2020-06-15  2:50     ` kernel test robot
  0 siblings, 0 replies; 150+ messages in thread
From: kernel test robot @ 2020-06-15  2:50 UTC (permalink / raw)
  To: kbuild-all

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

Hi Laurent,

I love your patch! Perhaps something to improve:

[auto build test WARNING on linuxtv-media/master]
[also build test WARNING on v5.8-rc1 next-20200614]
[if your patch is applied to the wrong git tree, please drop us a note to help
improve the system. BTW, we also suggest to use '--base' option to specify the
base tree in git format-patch, please see https://stackoverflow.com/a/37406982]

url:    https://github.com/0day-ci/linux/commits/Laurent-Pinchart/media-ti-vpe-cal-Add-media-controller-support/20200615-080443
base:   git://linuxtv.org/media_tree.git master
config: sh-allmodconfig (attached as .config)
compiler: sh4-linux-gcc (GCC) 9.3.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross ARCH=sh 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>, old ones prefixed by <<):

In file included from include/linux/err.h:5,
from include/linux/clk.h:12,
from drivers/media/platform/ti-vpe/cal.c:12:
drivers/media/platform/ti-vpe/cal.h: In function 'cal_write_field':
include/linux/bitfield.h:52:28: warning: comparison is always false due to limited range of data type [-Wtype-limits]
52 |   BUILD_BUG_ON_MSG((_mask) > (typeof(_reg))~0ull,           |                            ^
include/linux/compiler.h:330:9: note: in definition of macro '__compiletime_assert'
330 |   if (!(condition))              |         ^~~~~~~~~
include/linux/compiler.h:350:2: note: in expansion of macro '_compiletime_assert'
350 |  _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__)
|  ^~~~~~~~~~~~~~~~~~~
include/linux/build_bug.h:39:37: note: in expansion of macro 'compiletime_assert'
39 | #define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg)
|                                     ^~~~~~~~~~~~~~~~~~
include/linux/bitfield.h:52:3: note: in expansion of macro 'BUILD_BUG_ON_MSG'
52 |   BUILD_BUG_ON_MSG((_mask) > (typeof(_reg))~0ull,           |   ^~~~~~~~~~~~~~~~
include/linux/bitfield.h:94:3: note: in expansion of macro '__BF_FIELD_CHECK'
94 |   __BF_FIELD_CHECK(_mask, 0ULL, _val, "FIELD_PREP: ");          |   ^~~~~~~~~~~~~~~~
>> drivers/media/platform/ti-vpe/cal.h:229:9: note: in expansion of macro 'FIELD_PREP'
229 |  val |= FIELD_PREP(mask, value);
|         ^~~~~~~~~~

vim +/FIELD_PREP +229 drivers/media/platform/ti-vpe/cal.h

   222	
   223	static inline void cal_write_field(struct cal_dev *cal, u32 offset, u32 value,
   224					   u32 mask)
   225	{
   226		u32 val = cal_read(cal, offset);
   227	
   228		val &= ~mask;
 > 229		val |= FIELD_PREP(mask, value);
   230		cal_write(cal, offset, val);
   231	}
   232	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org

[-- Attachment #2: config.gz --]
[-- Type: application/gzip, Size: 54847 bytes --]

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

* Re: [PATCH v1 006/107] media: ti-vpe: cal: Merge all status variables in IRQ handler
  2020-06-14 23:58 ` [PATCH v1 006/107] media: ti-vpe: cal: Merge all status variables in IRQ handler Laurent Pinchart
@ 2020-06-16 10:32   ` Tomi Valkeinen
  2020-06-16 10:44     ` Laurent Pinchart
  0 siblings, 1 reply; 150+ messages in thread
From: Tomi Valkeinen @ 2020-06-16 10:32 UTC (permalink / raw)
  To: Laurent Pinchart, linux-media; +Cc: Benoit Parrot

Hi,

On 15/06/2020 02:58, Laurent Pinchart wrote:
> The cal_irq() function reads three IRQ status registers and stores their
> values in three different variables. As each value is processed right
> after reading the corresponding register, a single variable is enough.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>   drivers/media/platform/ti-vpe/cal.c | 35 +++++++++++++----------------
>   1 file changed, 15 insertions(+), 20 deletions(-)
> 
> diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
> index b04d8cb86977..0a5fb81223da 100644
> --- a/drivers/media/platform/ti-vpe/cal.c
> +++ b/drivers/media/platform/ti-vpe/cal.c
> @@ -1206,19 +1206,18 @@ static irqreturn_t cal_irq(int irq_cal, void *data)
>   	struct cal_dev *dev = (struct cal_dev *)data;
>   	struct cal_ctx *ctx;
>   	struct cal_dmaqueue *dma_q;
> -	u32 irqst0, irqst1, irqst2;
> +	unsigned int i;
> +	u32 status;
>   
> -	irqst0 = reg_read(dev, CAL_HL_IRQSTATUS(0));
> -	if (irqst0) {
> -		int i;

I do like to keep local variables inside smaller scopes when possible, as it reduces chances for 
bugs. Any reason you moved i to the whole function scope?

  Tomi

-- 
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki

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

* Re: [PATCH v1 006/107] media: ti-vpe: cal: Merge all status variables in IRQ handler
  2020-06-16 10:32   ` Tomi Valkeinen
@ 2020-06-16 10:44     ` Laurent Pinchart
  2020-06-16 10:49       ` Tomi Valkeinen
  0 siblings, 1 reply; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-16 10:44 UTC (permalink / raw)
  To: Tomi Valkeinen; +Cc: linux-media, Benoit Parrot

Hi Tomi,

On Tue, Jun 16, 2020 at 01:32:17PM +0300, Tomi Valkeinen wrote:
> On 15/06/2020 02:58, Laurent Pinchart wrote:
> > The cal_irq() function reads three IRQ status registers and stores their
> > values in three different variables. As each value is processed right
> > after reading the corresponding register, a single variable is enough.
> > 
> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > ---
> >   drivers/media/platform/ti-vpe/cal.c | 35 +++++++++++++----------------
> >   1 file changed, 15 insertions(+), 20 deletions(-)
> > 
> > diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
> > index b04d8cb86977..0a5fb81223da 100644
> > --- a/drivers/media/platform/ti-vpe/cal.c
> > +++ b/drivers/media/platform/ti-vpe/cal.c
> > @@ -1206,19 +1206,18 @@ static irqreturn_t cal_irq(int irq_cal, void *data)
> >   	struct cal_dev *dev = (struct cal_dev *)data;
> >   	struct cal_ctx *ctx;
> >   	struct cal_dmaqueue *dma_q;
> > -	u32 irqst0, irqst1, irqst2;
> > +	unsigned int i;
> > +	u32 status;
> >   
> > -	irqst0 = reg_read(dev, CAL_HL_IRQSTATUS(0));
> > -	if (irqst0) {
> > -		int i;
> 
> I do like to keep local variables inside smaller scopes when possible,
> as it reduces chances for bugs. Any reason you moved i to the whole
> function scope?

I do the same as well, but tend to keep variables used in multiple
smaller scopes as top-level variables. I'm fine multiple instances of
'i' if you prefer.

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH v1 006/107] media: ti-vpe: cal: Merge all status variables in IRQ handler
  2020-06-16 10:44     ` Laurent Pinchart
@ 2020-06-16 10:49       ` Tomi Valkeinen
  0 siblings, 0 replies; 150+ messages in thread
From: Tomi Valkeinen @ 2020-06-16 10:49 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Benoit Parrot

On 16/06/2020 13:44, Laurent Pinchart wrote:

>> I do like to keep local variables inside smaller scopes when possible,
>> as it reduces chances for bugs. Any reason you moved i to the whole
>> function scope?
> 
> I do the same as well, but tend to keep variables used in multiple
> smaller scopes as top-level variables. I'm fine multiple instances of
> 'i' if you prefer.

Then you risk having the first use initialize the variable, and the second use missing 
initialization but using it as initialized from the first use. And the compiler doesn't warn about 
the bug.

If changing it here would create lots of conflicts (as this is in the beginning of the series), it's 
fine.

  Tomi

-- 
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki

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

* Re: [PATCH v1 027/107] media: ti-vpe: cal: Name all cal_camerarx pointers consistently
  2020-06-14 23:58 ` [PATCH v1 027/107] media: ti-vpe: cal: Name all cal_camerarx " Laurent Pinchart
@ 2020-06-16 10:58   ` Tomi Valkeinen
  2020-06-18 14:06   ` Benoit Parrot
  1 sibling, 0 replies; 150+ messages in thread
From: Tomi Valkeinen @ 2020-06-16 10:58 UTC (permalink / raw)
  To: Laurent Pinchart, linux-media; +Cc: Benoit Parrot

On 15/06/2020 02:58, Laurent Pinchart wrote:
> Name all variables htat point to a cal_camerax instance 'phy' instead of
> 'cc'. The name 'cc' refers to Camera Core, but is not commonly used in
> the driver or in datasheets.

s/htat/that/

  Tomi

-- 
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki

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

* Re: [PATCH v1 050/107] media: ti-vpe: cal: Fix usage of v4l2_fwnode_endpoint_parse()
  2020-06-14 23:58 ` [PATCH v1 050/107] media: ti-vpe: cal: Fix usage of v4l2_fwnode_endpoint_parse() Laurent Pinchart
@ 2020-06-16 11:28   ` Tomi Valkeinen
  0 siblings, 0 replies; 150+ messages in thread
From: Tomi Valkeinen @ 2020-06-16 11:28 UTC (permalink / raw)
  To: Laurent Pinchart, linux-media; +Cc: Benoit Parrot

Hi Laurent,

On 15/06/2020 02:58, Laurent Pinchart wrote:
> Letting the v4l2_fwnode_endpoint_parse() function determine the bus type
> automatically is deprecated. Set the bus type to DPHY manually as the TI
> CAL only supports DPHY.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>   drivers/media/platform/ti-vpe/cal.c | 9 ++++-----
>   1 file changed, 4 insertions(+), 5 deletions(-)

Up to and including this patch:

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

Very nice cleanups. I'll continue with the rest later, I need a break =).

  Tomi

-- 
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki

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

* Re: [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (106 preceding siblings ...)
  2020-06-14 23:59 ` [PATCH v1 107/107] media: ti-vpe: cal: Implement media controller centric API Laurent Pinchart
@ 2020-06-16 11:43 ` Tomi Valkeinen
  2020-06-19 17:04   ` Laurent Pinchart
  2020-06-19 14:53 ` Benoit Parrot
  108 siblings, 1 reply; 150+ messages in thread
From: Tomi Valkeinen @ 2020-06-16 11:43 UTC (permalink / raw)
  To: Laurent Pinchart, linux-media; +Cc: Benoit Parrot

Hi Laurent,

On 15/06/2020 02:57, Laurent Pinchart wrote:
> Hello,
> 
> This small patch series adds media controller support to the ti-cal
> driver.

I did some small testing on AM6, and after third module unload I got:

[   75.292797] OF: ERROR: Bad of_node_put() on /interconnect@100000/i2c@2010000/ov5640@3c/port/endpoint
[   75.292839] ------------[ cut here ]------------
[   75.292849] refcount_t: addition on 0; use-after-free.
[   75.292856] WARNING: CPU: 0 PID: 421 at lib/refcount.c:25 refcount_warn_saturate+0xa0/0x148
[   75.292861] Modules linked in: ov5640 ti_cal(-) tidss ti_tfp410 tc358767 display_connector phy_j721e_wiz phy_cadence_torrent panel_simple drm_kms_helper drm drm_panel_orienta
tion_quirks cfbfillrect cfbimgblt cfbcopyarea [last unloaded: ov5640]
[   75.292935] CPU: 0 PID: 421 Comm: rmmod Not tainted 5.8.0-rc1-00107-g5de7cabe3995 #6
[   75.292941] Hardware name: Texas Instruments AM654 Base Board (DT)
[   75.292946] pstate: 00000085 (nzcv daIf -PAN -UAO BTYPE=--)
[   75.292951] pc : refcount_warn_saturate+0xa0/0x148
[   75.292956] lr : refcount_warn_saturate+0xa0/0x148
[   75.292961] sp : ffff80001324f760
[   75.292965] x29: ffff80001324f760 x28: ffff0a00ffffff05 
[   75.292978] x27: ffff800011f2731a x26: ffff800010e21c28 
[   75.292991] x25: ffff800010b6d468 x24: ffff00087ff30338 
[   75.293003] x23: ffff800011f276d8 x22: 0000000000000005 
[   75.293016] x21: 0000000000000005 x20: ffff800011f276d8 
[   75.293028] x19: ffff00087ff30378 x18: 0000000000000000 
[   75.293041] x17: 0000000000000000 x16: 0000000000000000 
[   75.293054] x15: 0000000000000004 x14: 0000000000048963 
[   75.293066] x13: 0000000000000000 x12: 0000000000000000 
[   75.293079] x11: ffff8000116e1540 x10: 0000000000000000 
[   75.293091] x9 : 000000006d17ab9f x8 : 612d657375203b30 
[   75.293104] x7 : 206e6f206e6f6974 x6 : ffff00087f823c12 
[   75.293116] x5 : 0000000000000000 x4 : ffff00087f823bb0 
[   75.293128] x3 : 0000000000000000 x2 : 0000000000000023 
[   75.293141] x1 : 2e76dc4eebb2b000 x0 : 0000000000000000 
[   75.293153] Call trace:
[   75.293158]  refcount_warn_saturate+0xa0/0x148
[   75.293163]  kobject_get+0x40/0xb0
[   75.293168]  of_node_get+0x20/0x38
[   75.293172]  of_fwnode_get+0x34/0x58
[   75.293177]  fwnode_get_nth_parent+0x34/0x78
[   75.293182]  fwnode_full_name_string+0x4c/0xc8
[   75.293187]  device_node_string+0x318/0x3f0
[   75.293192]  pointer+0x204/0x2e0
[   75.293196]  vsnprintf+0x204/0x728
[   75.293201]  vscnprintf+0x30/0x68
[   75.293206]  vprintk_store+0x64/0x210
[   75.293210]  vprintk_emit+0xd4/0x340
[   75.293215]  vprintk_default+0x3c/0x48
[   75.293219]  vprintk_func+0xec/0x258
[   75.293224]  printk+0x60/0x84
[   75.293229]  of_node_release+0xcc/0xd8
[   75.293233]  kobject_put+0x8c/0x200
[   75.293238]  of_node_put+0x18/0x28
[   75.293243]  cal_camerarx_destroy+0x28/0x50 [ti_cal]
[   75.293247]  cal_remove+0xa4/0x110 [ti_cal]
[   75.293252]  platform_drv_remove+0x2c/0x50
[   75.293257]  device_release_driver_internal+0xfc/0x1d0
[   75.293262]  driver_detach+0x50/0xe0
[   75.293267]  bus_remove_driver+0x5c/0xd8
[   75.293272]  driver_unregister+0x30/0x60
[   75.293276]  platform_driver_unregister+0x14/0x20
[   75.293281]  cal_pdrv_exit+0x1c/0xb060 [ti_cal]
[   75.293286]  __arm64_sys_delete_module+0x1a8/0x250
[   75.293291]  el0_svc_common.constprop.0+0x74/0x198
[   75.293296]  do_el0_svc+0x24/0x90
[   75.293300]  el0_sync_handler+0x9c/0x1b8
[   75.293305]  el0_sync+0x158/0x180
[   75.293309] irq event stamp: 4884
[   75.293315] hardirqs last  enabled at (4883): [<ffff800010235b14>] slab_free_freelist_hook+0xf4/0x190
[   75.293322] hardirqs last disabled at (4884): [<ffff8000100cf090>] vprintk_emit+0x88/0x340
[   75.293328] softirqs last  enabled at (4150): [<ffff800010000db8>] _stext+0x5b8/0x5fc
[   75.293333] softirqs last disabled at (4135): [<ffff800010047f7c>] irq_exit+0x114/0x128
[   75.293339] ---[ end trace 3ee89555752a3b07 ]---
[   75.293344] ------------[ cut here ]------------
[   75.293349] refcount_t: underflow; use-after-free.
[   75.293356] WARNING: CPU: 0 PID: 421 at lib/refcount.c:28 refcount_warn_saturate+0xf4/0x148
[   75.293360] Modules linked in: ov5640 ti_cal(-) tidss ti_tfp410 tc358767 display_connector phy_j721e_wiz phy_cadence_torrent panel_simple drm_kms_helper drm drm_panel_orienta
tion_quirks cfbfillrect cfbimgblt cfbcopyarea [last unloaded: ov5640]
[   75.293433] CPU: 0 PID: 421 Comm: rmmod Tainted: G        W         5.8.0-rc1-00107-g5de7cabe3995 #6
[   75.293438] Hardware name: Texas Instruments AM654 Base Board (DT)
[   75.293443] pstate: 00000085 (nzcv daIf -PAN -UAO BTYPE=--)
[   75.293448] pc : refcount_warn_saturate+0xf4/0x148
[   75.293453] lr : refcount_warn_saturate+0xf4/0x148
[   75.293458] sp : ffff80001324f740
[   75.293462] x29: ffff80001324f740 x28: ffff0a00ffffff05 
[   75.293475] x27: ffff800011f2731a x26: ffff800010e21c28 
[   75.293487] x25: ffff800010b6d468 x24: ffff00087ff30338 
[   75.293500] x23: ffff800011f276d8 x22: 0000000000000005 
[   75.293512] x21: 0000000000000005 x20: ffff00087ff30208 
[   75.293525] x19: ffff00087ff30378 x18: 0000000000000000 
[   75.293537] x17: 0000000000000000 x16: 0000000000000000 
[   75.293550] x15: 0000000000000004 x14: 0000000000048963 
[   75.293562] x13: 0000000000000000 x12: 0000000000000000 
[   75.293574] x11: ffff8000116e1540 x10: 0000000000000000 
[   75.293587] x9 : 000000006d17ab9f x8 : 72657466612d6573 
[   75.293600] x7 : 75203b776f6c6672 x6 : ffff00087f8246d1 
[   75.293612] x5 : 0000000000000000 x4 : ffff00087f823bb0 
[   75.293625] x3 : 0000000000000000 x2 : 0000000000000023 
[   75.293637] x1 : 2e76dc4eebb2b000 x0 : 0000000000000000 
[   75.293650] Call trace:
[   75.293655]  refcount_warn_saturate+0xf4/0x148
[   75.293659]  kobject_put+0x140/0x200
[   75.293664]  of_node_put+0x18/0x28
[   75.293668]  of_fwnode_put+0x34/0x48
[   75.293673]  fwnode_get_next_parent+0x48/0x80
[   75.293678]  fwnode_get_nth_parent+0x4c/0x78
[   75.293683]  fwnode_full_name_string+0x4c/0xc8
[   75.293688]  device_node_string+0x318/0x3f0
[   75.293693]  pointer+0x204/0x2e0
[   75.293697]  vsnprintf+0x204/0x728
[   75.293702]  vscnprintf+0x30/0x68
[   75.293706]  vprintk_store+0x64/0x210
[   75.293711]  vprintk_emit+0xd4/0x340
[   75.293715]  vprintk_default+0x3c/0x48
[   75.293720]  vprintk_func+0xec/0x258
[   75.293724]  printk+0x60/0x84
[   75.293729]  of_node_release+0xcc/0xd8
[   75.293734]  kobject_put+0x8c/0x200
[   75.293738]  of_node_put+0x18/0x28
[   75.293743]  cal_camerarx_destroy+0x28/0x50 [ti_cal]
[   75.293748]  cal_remove+0xa4/0x110 [ti_cal]
[   75.293753]  platform_drv_remove+0x2c/0x50
[   75.293758]  device_release_driver_internal+0xfc/0x1d0
[   75.293763]  driver_detach+0x50/0xe0
[   75.293768]  bus_remove_driver+0x5c/0xd8
[   75.293772]  driver_unregister+0x30/0x60
[   75.293777]  platform_driver_unregister+0x14/0x20
[   75.293782]  cal_pdrv_exit+0x1c/0xb060 [ti_cal]
[   75.293787]  __arm64_sys_delete_module+0x1a8/0x250
[   75.293792]  el0_svc_common.constprop.0+0x74/0x198
[   75.293796]  do_el0_svc+0x24/0x90
[   75.293801]  el0_sync_handler+0x9c/0x1b8
[   75.293806]  el0_sync+0x158/0x180
[   75.293810] irq event stamp: 4884
[   75.293816] hardirqs last  enabled at (4883): [<ffff800010235b14>] slab_free_freelist_hook+0xf4/0x190
[   75.293822] hardirqs last disabled at (4884): [<ffff8000100cf090>] vprintk_emit+0x88/0x340
[   75.293828] softirqs last  enabled at (4150): [<ffff800010000db8>] _stext+0x5b8/0x5fc
[   75.293834] softirqs last disabled at (4135): [<ffff800010047f7c>] irq_exit+0x114/0x128
[   75.293839] ---[ end trace 3ee89555752a3b08 ]---
[   75.293844] ------------[ cut here ]------------
[   75.293849] refcount_t: saturated; leaking memory.
[   75.293855] WARNING: CPU: 0 PID: 421 at lib/refcount.c:22 refcount_warn_saturate+0x74/0x148
[   75.293859] Modules linked in: ov5640 ti_cal(-) tidss ti_tfp410 tc358767 display_connector phy_j721e_wiz phy_cadence_torrent panel_simple drm_kms_helper drm drm_panel_orienta
tion_quirks cfbfillrect cfbimgblt cfbcopyarea [last unloaded: ov5640]
[   75.293932] CPU: 0 PID: 421 Comm: rmmod Tainted: G        W         5.8.0-rc1-00107-g5de7cabe3995 #6
[   75.293938] Hardware name: Texas Instruments AM654 Base Board (DT)
[   75.293943] pstate: 00000085 (nzcv daIf -PAN -UAO BTYPE=--)
[   75.293948] pc : refcount_warn_saturate+0x74/0x148
[   75.293952] lr : refcount_warn_saturate+0x74/0x148
[   75.293957] sp : ffff80001324f760
[   75.293961] x29: ffff80001324f760 x28: ffff0a00ffffff05 
[   75.293974] x27: ffff800011f2731a x26: ffff800010e21c28 
[   75.293986] x25: ffff800010b6d468 x24: ffff00087ff30338 
[   75.293999] x23: ffff800011f276d8 x22: 0000000000000004 
[   75.294011] x21: 0000000000000004 x20: ffff0000ffffff00 
[   75.294024] x19: ffff00087ff30378 x18: 0000000000000000 
[   75.294036] x17: 0000000000000000 x16: 0000000000000000 
[   75.294049] x15: 0000000000000004 x14: 0000000000048963 
[   75.294061] x13: 0000000000000000 x12: 0000000000000000 
[   75.294073] x11: ffff8000116e1540 x10: 0000000000000000 
[   75.294086] x9 : 00000000fffffffe x8 : 6c203b6465746172 
[   75.294098] x7 : 75746173203a745f x6 : ffff00087f8251c4 
[   75.294111] x5 : 0000000000000000 x4 : ffff00087f823bb0 
[   75.294123] x3 : 0000000000000000 x2 : 0000000000000023 
[   75.294136] x1 : 2e76dc4eebb2b000 x0 : 0000000000000000 
[   75.294148] Call trace:
[   75.294153]  refcount_warn_saturate+0x74/0x148
[   75.294157]  kobject_get+0x78/0xb0
[   75.294162]  of_node_get+0x20/0x38
[   75.294166]  of_fwnode_get+0x34/0x58
[   75.294171]  fwnode_get_nth_parent+0x34/0x78
[   75.294176]  fwnode_full_name_string+0x4c/0xc8
[   75.294181]  device_node_string+0x318/0x3f0
[   75.294186]  pointer+0x204/0x2e0
[   75.294190]  vsnprintf+0x204/0x728
[   75.294195]  vscnprintf+0x30/0x68
[   75.294199]  vprintk_store+0x64/0x210
[   75.294204]  vprintk_emit+0xd4/0x340
[   75.294208]  vprintk_default+0x3c/0x48
[   75.294213]  vprintk_func+0xec/0x258
[   75.294218]  printk+0x60/0x84
[   75.294222]  of_node_release+0xcc/0xd8
[   75.294227]  kobject_put+0x8c/0x200
[   75.294231]  of_node_put+0x18/0x28
[   75.294236]  cal_camerarx_destroy+0x28/0x50 [ti_cal]
[   75.294241]  cal_remove+0xa4/0x110 [ti_cal]
[   75.294246]  platform_drv_remove+0x2c/0x50
[   75.294251]  device_release_driver_internal+0xfc/0x1d0
[   75.294255]  driver_detach+0x50/0xe0
[   75.294260]  bus_remove_driver+0x5c/0xd8
[   75.294265]  driver_unregister+0x30/0x60
[   75.294270]  platform_driver_unregister+0x14/0x20
[   75.294275]  cal_pdrv_exit+0x1c/0xb060 [ti_cal]
[   75.294280]  __arm64_sys_delete_module+0x1a8/0x250
[   75.294285]  el0_svc_common.constprop.0+0x74/0x198
[   75.294289]  do_el0_svc+0x24/0x90
[   75.294294]  el0_sync_handler+0x9c/0x1b8
[   75.294299]  el0_sync+0x158/0x180
[   75.294303] irq event stamp: 4884
[   75.294309] hardirqs last  enabled at (4883): [<ffff800010235b14>] slab_free_freelist_hook+0xf4/0x190
[   75.294315] hardirqs last disabled at (4884): [<ffff8000100cf090>] vprintk_emit+0x88/0x340
[   75.294320] softirqs last  enabled 
[   75.294329] Lost 2 message(s)!
[   76.258340] CPU: 1 PID: 421 Comm: rmmod Tainted: G        W         5.8.0-rc1-00107-g5de7cabe3995 #6
[   76.267490] Hardware name: Texas Instruments AM654 Base Board (DT)
[   76.273689] Call trace:
[   76.276160]  dump_backtrace+0x0/0x1d8
[   76.279843]  show_stack+0x18/0x28
[   76.283177]  dump_stack+0xe4/0x150
[   76.286596]  of_node_release+0xd0/0xd8
[   76.290360]  kobject_put+0x8c/0x200
[   76.293864]  of_node_put+0x18/0x28
[   76.297296]  cal_camerarx_destroy+0x28/0x50 [ti_cal]
[   76.302283]  cal_remove+0xa4/0x110 [ti_cal]
[   76.306484]  platform_drv_remove+0x2c/0x50
[   76.310597]  device_release_driver_internal+0xfc/0x1d0
[   76.315748]  driver_detach+0x50/0xe0
[   76.319338]  bus_remove_driver+0x5c/0xd8
[   76.323274]  driver_unregister+0x30/0x60
[   76.327211]  platform_driver_unregister+0x14/0x20
[   76.331936]  cal_pdrv_exit+0x1c/0xb060 [ti_cal]
[   76.336483]  __arm64_sys_delete_module+0x1a8/0x250
[   76.341289]  el0_svc_common.constprop.0+0x74/0x198
[   76.346094]  do_el0_svc+0x24/0x90
[   76.349426]  el0_sync_handler+0x9c/0x1b8
[   76.353361]  el0_sync+0x158/0x180

 Tomi

-- 
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki

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

* Re: [PATCH v1 078/107] media: ti-vpe: cal: Don't store external rate in cal_camerarx
  2020-06-14 23:59 ` [PATCH v1 078/107] media: ti-vpe: cal: Don't store external rate in cal_camerarx Laurent Pinchart
@ 2020-06-17  9:56   ` Kieran Bingham
  2020-06-17 10:05     ` Laurent Pinchart
  0 siblings, 1 reply; 150+ messages in thread
From: Kieran Bingham @ 2020-06-17  9:56 UTC (permalink / raw)
  To: Laurent Pinchart, linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

Hi Laurent,

On 15/06/2020 00:59, Laurent Pinchart wrote:
> The external pixel rate is retrieved when starting the camerarx and only
> used then. There's no need to store it in the cal_camerarx structure, it
> can be returned by cal_camerarx_get_external_info() and explicitly
> passed to cal_camerarx_config().
> 
> While at it, rename cal_camerarx_get_external_info() to
> cal_camerarx_get_external_rate() to better reflect the function's
> purpose.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>  drivers/media/platform/ti-vpe/cal.c | 24 ++++++++++++------------
>  1 file changed, 12 insertions(+), 12 deletions(-)
> 
> diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
> index 8326db0e4197..a11457909134 100644
> --- a/drivers/media/platform/ti-vpe/cal.c
> +++ b/drivers/media/platform/ti-vpe/cal.c
> @@ -272,7 +272,6 @@ struct cal_camerarx {
>  	struct v4l2_fwnode_endpoint	endpoint;
>  	struct device_node	*sensor_node;
>  	struct v4l2_subdev	*sensor;
> -	unsigned int		external_rate;

Here, external_rate is 32 bit,

>  };
>  
>  struct cal_dev {
> @@ -481,9 +480,10 @@ static void cal_quickdump_regs(struct cal_dev *cal)
>   * ------------------------------------------------------------------
>   */
>  
> -static int cal_camerarx_get_external_info(struct cal_camerarx *phy)
> +static s64 cal_camerarx_get_external_rate(struct cal_camerarx *phy)
>  {
>  	struct v4l2_ctrl *ctrl;
> +	s64 rate;

and now it becomes a 64 bit value.

>  
>  	if (!phy->sensor)
>  		return -ENODEV;
> @@ -495,10 +495,10 @@ static int cal_camerarx_get_external_info(struct cal_camerarx *phy)
>  		return -EPIPE;
>  	}
>  
> -	phy->external_rate = v4l2_ctrl_g_ctrl_int64(ctrl);
> -	phy_dbg(3, phy, "sensor Pixel Rate: %u\n", phy->external_rate);
> +	rate = v4l2_ctrl_g_ctrl_int64(ctrl);
> +	phy_dbg(3, phy, "sensor Pixel Rate: %llu\n", rate);
>  
> -	return 0;
> +	return rate;
>  }
>  
>  static void cal_camerarx_lane_config(struct cal_camerarx *phy)
> @@ -554,7 +554,7 @@ static void cal_camerarx_disable(struct cal_camerarx *phy)
>  #define TCLK_MISS	1
>  #define TCLK_SETTLE	14
>  
> -static void cal_camerarx_config(struct cal_camerarx *phy,
> +static void cal_camerarx_config(struct cal_camerarx *phy, s64 external_rate,
>  				const struct cal_fmt *fmt)
>  {
>  	unsigned int reg0, reg1;
> @@ -566,7 +566,7 @@ static void cal_camerarx_config(struct cal_camerarx *phy,
>  
>  	/* DPHY timing configuration */
>  	/* CSI-2 is DDR and we only count used lanes. */
> -	csi2_ddrclk_khz = phy->external_rate / 1000
> +	csi2_ddrclk_khz = external_rate / 1000
>  		/ (2 * num_lanes) * fmt->bpp;


Which causes this calculation to fail on 32 bit ARM builds.
(I'm building for the DRA76-EVM).


I've got the following fix up on the top of your tree to solve this, but
I'm not particularly happy about having to break the calculation up (and
re-use external_rate) though the use of do_div.


From ca6ce335a852e34364bc45cb4240f703e4ea4248 Mon Sep 17 00:00:00 2001
From: Kieran Bingham <kieran.bingham@ideasonboard.com>
Date: Tue, 16 Jun 2020 16:19:04 +0100
Subject: [PATCH] media: ti-vpe: cal: Use do_div() for 64 bit operations

Support building the CAL driver on arm32 bit targets by updating the
CSI2 clock calculation (which uses a signed 64 bit input value from
the sensors pixel clock rate) to use the do_div() helpers.

The calculation is split into distinct parts to maintain
order of operations while making use of the do_div macro and further
re-ordered to convert to kHz at the end to maintain precision.

Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal-camerarx.c | 22 +++++++++++++++++---
 1 file changed, 19 insertions(+), 3 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal-camerarx.c
b/drivers/media/platform/ti-vpe/cal-camerarx.c
index 014ca46509db..0ef19a516902 100644
--- a/drivers/media/platform/ti-vpe/cal-camerarx.c
+++ b/drivers/media/platform/ti-vpe/cal-camerarx.c
@@ -126,9 +126,25 @@ static void cal_camerarx_config(struct cal_camerarx
*phy, s64 external_rate)
        u32 num_lanes = mipi_csi2->num_data_lanes;

        /* DPHY timing configuration */
-       /* CSI-2 is DDR and we only count used lanes. */
-       csi2_ddrclk_khz = external_rate / 1000
-               / (2 * num_lanes) * phy->fmtinfo->bpp;
+
+       /*
+        * CSI-2 is DDR and we only count used lanes.
+        *
+        * csi2_ddrclk_khz = external_rate / 1000
+        *                   / (2 * num_lanes) * phy->fmtinfo->bpp;
+        *
+        * The equation is broken into separate statements to maintain
+        * order of operations, and conversion to kHz is done last to
+        * keep precision.
+        *
+        * The 64 bit external_rate is modified during this equation and
+        * contains the result, not the original after calculation.
+        */
+       do_div(external_rate, 2 * num_lanes);
+       external_rate *= phy->fmtinfo->bpp;
+       do_div(external_rate, 1000);
+       csi2_ddrclk_khz = external_rate;
+
        phy_dbg(1, phy, "csi2_ddrclk_khz: %d\n", csi2_ddrclk_khz);

        /* THS_TERM: Programmed value = floor(20 ns/DDRClk period) */
-- 
2.25.1


If you have a better way to correctly calculate the rate (also noting
that I moved the /1000 to the end, I'm not sure if that's more correct,
or makes it stop following what the hardware would do) - please update
accordingly, or feel free to squash this patch in as you wish.


With the calculation corrected:

Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>

--
Kieran


>  	phy_dbg(1, phy, "csi2_ddrclk_khz: %d\n", csi2_ddrclk_khz);
>  
> @@ -667,13 +667,14 @@ static void cal_camerarx_wait_stop_state(struct cal_camerarx *phy)
>  static int cal_camerarx_start(struct cal_camerarx *phy,
>  			      const struct cal_fmt *fmt)
>  {
> +	s64 external_rate;
>  	u32 sscounter;
>  	u32 val;
>  	int ret;
>  
> -	ret = cal_camerarx_get_external_info(phy);
> -	if (ret < 0)
> -		return ret;
> +	external_rate = cal_camerarx_get_external_rate(phy);
> +	if (external_rate < 0)
> +		return external_rate;
>  
>  	ret = v4l2_subdev_call(phy->sensor, core, s_power, 1);
>  	if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV) {
> @@ -719,7 +720,7 @@ static int cal_camerarx_start(struct cal_camerarx *phy,
>  	reg_read(phy, CAL_CSI2_PHY_REG0);
>  
>  	/* Program the PHY timing parameters. */
> -	cal_camerarx_config(phy, fmt);
> +	cal_camerarx_config(phy, external_rate, fmt);
>  
>  	/*
>  	 *    b. Assert the FORCERXMODE signal.
> @@ -1034,7 +1035,6 @@ static struct cal_camerarx *cal_camerarx_create(struct cal_dev *cal,
>  
>  	phy->cal = cal;
>  	phy->instance = instance;
> -	phy->external_rate = 192000000;
>  
>  	phy->res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
>  						(instance == 0) ?
> 


-- 
Regards
--
Kieran

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

* Re: [PATCH v1 036/107] media: ti-vpe: cal: Reorganize remaining code in sections
  2020-06-14 23:58 ` [PATCH v1 036/107] media: ti-vpe: cal: Reorganize remaining code in sections Laurent Pinchart
@ 2020-06-17 10:00   ` Kieran Bingham
  2020-06-17 10:02     ` [PATCH] media: ti-vpe: cal: Use cal_data_get_num_csi2_phy() consistently Kieran Bingham
  2020-06-17 10:51     ` [PATCH v1 036/107] media: ti-vpe: cal: Reorganize remaining code in sections Laurent Pinchart
  0 siblings, 2 replies; 150+ messages in thread
From: Kieran Bingham @ 2020-06-17 10:00 UTC (permalink / raw)
  To: Laurent Pinchart, linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

Hi Laurent,

On 15/06/2020 00:58, Laurent Pinchart wrote:
> Increase readability by reorganizing the remaining code in sections. No
> functional change is included.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>  drivers/media/platform/ti-vpe/cal.c | 350 +++++++++++++++-------------
>  1 file changed, 187 insertions(+), 163 deletions(-)
> 
> diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
> index 176f616033a1..6f33853ecdb2 100644
> --- a/drivers/media/platform/ti-vpe/cal.c
> +++ b/drivers/media/platform/ti-vpe/cal.c
> @@ -37,9 +37,6 @@
>  
>  #define CAL_MODULE_NAME "cal"
>  
> -#define MAX_WIDTH_BYTES (8192 * 8)
> -#define MAX_HEIGHT_LINES 16383
> -
>  MODULE_DESCRIPTION("TI CAL driver");
>  MODULE_AUTHOR("Benoit Parrot, <bparrot@ti.com>");
>  MODULE_LICENSE("GPL v2");
> @@ -79,11 +76,11 @@ MODULE_PARM_DESC(debug, "activates debug info");
>  
>  #define CAL_NUM_CONTEXT 2
>  
> -#define reg_read(dev, offset) ioread32(dev->base + offset)
> -#define reg_write(dev, offset, val) iowrite32(val, dev->base + offset)
> +#define MAX_WIDTH_BYTES (8192 * 8)
> +#define MAX_HEIGHT_LINES 16383
>  
>  /* ------------------------------------------------------------------
> - *	Basic structures
> + *	Format Handling
>   * ------------------------------------------------------------------
>   */
>  
> @@ -204,6 +201,11 @@ static char *fourcc_to_str(u32 fmt)
>  	return code;
>  }
>  
> +/* ------------------------------------------------------------------
> + *	Driver Structures
> + * ------------------------------------------------------------------
> + */
> +
>  /* buffer for one video frame */
>  struct cal_buffer {
>  	/* common v4l buffer stuff -- must be first */
> @@ -239,80 +241,6 @@ struct cal_data {
>  	unsigned int flags;
>  };
>  
> -static const struct cal_camerarx_data dra72x_cal_camerarx[] = {
> -	{
> -		.fields = {
> -			[F_CTRLCLKEN] = { 10, 10 },
> -			[F_CAMMODE] = { 11, 12 },
> -			[F_LANEENABLE] = { 13, 16 },
> -			[F_CSI_MODE] = { 17, 17 },
> -		},
> -		.num_lanes = 4,
> -	},
> -	{
> -		.fields = {
> -			[F_CTRLCLKEN] = { 0, 0 },
> -			[F_CAMMODE] = { 1, 2 },
> -			[F_LANEENABLE] = { 3, 4 },
> -			[F_CSI_MODE] = { 5, 5 },
> -		},
> -		.num_lanes = 2,
> -	},
> -};
> -
> -static const struct cal_data dra72x_cal_data = {
> -	.camerarx = dra72x_cal_camerarx,
> -	.num_csi2_phy = ARRAY_SIZE(dra72x_cal_camerarx),
> -};
> -
> -static const struct cal_data dra72x_es1_cal_data = {
> -	.camerarx = dra72x_cal_camerarx,
> -	.num_csi2_phy = ARRAY_SIZE(dra72x_cal_camerarx),
> -	.flags = DRA72_CAL_PRE_ES2_LDO_DISABLE,
> -};
> -
> -static const struct cal_camerarx_data dra76x_cal_csi_phy[] = {
> -	{
> -		.fields = {
> -			[F_CTRLCLKEN] = { 8, 8 },
> -			[F_CAMMODE] = { 9, 10 },
> -			[F_CSI_MODE] = { 11, 11 },
> -			[F_LANEENABLE] = { 27, 31 },
> -		},
> -		.num_lanes = 5,
> -	},
> -	{
> -		.fields = {
> -			[F_CTRLCLKEN] = { 0, 0 },
> -			[F_CAMMODE] = { 1, 2 },
> -			[F_CSI_MODE] = { 3, 3 },
> -			[F_LANEENABLE] = { 24, 26 },
> -		},
> -		.num_lanes = 3,
> -	},
> -};
> -
> -static const struct cal_data dra76x_cal_data = {
> -	.camerarx = dra76x_cal_csi_phy,
> -	.num_csi2_phy = ARRAY_SIZE(dra76x_cal_csi_phy),
> -};
> -
> -static const struct cal_camerarx_data am654_cal_csi_phy[] = {
> -	{
> -		.fields = {
> -			[F_CTRLCLKEN] = { 15, 15 },
> -			[F_CAMMODE] = { 24, 25 },
> -			[F_LANEENABLE] = { 0, 4 },
> -		},
> -		.num_lanes = 5,
> -	},
> -};
> -
> -static const struct cal_data am654_cal_data = {
> -	.camerarx = am654_cal_csi_phy,
> -	.num_csi2_phy = ARRAY_SIZE(am654_cal_csi_phy),
> -};
> -
>  /*
>   * The Camera Adaptation Layer (CAL) module is paired with one or more complex
>   * I/O PHYs (CAMERARX). It contains multiple instances of CSI-2, processing and
> @@ -408,6 +336,98 @@ struct cal_ctx {
>  	bool dma_act;
>  };
>  
> +static inline struct cal_ctx *notifier_to_ctx(struct v4l2_async_notifier *n)
> +{
> +	return container_of(n, struct cal_ctx, notifier);
> +}
> +
> +/* ------------------------------------------------------------------
> + *	Platform Data
> + * ------------------------------------------------------------------
> + */
> +
> +static const struct cal_camerarx_data dra72x_cal_camerarx[] = {
> +	{
> +		.fields = {
> +			[F_CTRLCLKEN] = { 10, 10 },
> +			[F_CAMMODE] = { 11, 12 },
> +			[F_LANEENABLE] = { 13, 16 },
> +			[F_CSI_MODE] = { 17, 17 },
> +		},
> +		.num_lanes = 4,
> +	},
> +	{
> +		.fields = {
> +			[F_CTRLCLKEN] = { 0, 0 },
> +			[F_CAMMODE] = { 1, 2 },
> +			[F_LANEENABLE] = { 3, 4 },
> +			[F_CSI_MODE] = { 5, 5 },
> +		},
> +		.num_lanes = 2,
> +	},
> +};
> +
> +static const struct cal_data dra72x_cal_data = {
> +	.camerarx = dra72x_cal_camerarx,
> +	.num_csi2_phy = ARRAY_SIZE(dra72x_cal_camerarx),
> +};
> +
> +static const struct cal_data dra72x_es1_cal_data = {
> +	.camerarx = dra72x_cal_camerarx,
> +	.num_csi2_phy = ARRAY_SIZE(dra72x_cal_camerarx),
> +	.flags = DRA72_CAL_PRE_ES2_LDO_DISABLE,
> +};
> +
> +static const struct cal_camerarx_data dra76x_cal_csi_phy[] = {
> +	{
> +		.fields = {
> +			[F_CTRLCLKEN] = { 8, 8 },
> +			[F_CAMMODE] = { 9, 10 },
> +			[F_CSI_MODE] = { 11, 11 },
> +			[F_LANEENABLE] = { 27, 31 },
> +		},
> +		.num_lanes = 5,
> +	},
> +	{
> +		.fields = {
> +			[F_CTRLCLKEN] = { 0, 0 },
> +			[F_CAMMODE] = { 1, 2 },
> +			[F_CSI_MODE] = { 3, 3 },
> +			[F_LANEENABLE] = { 24, 26 },
> +		},
> +		.num_lanes = 3,
> +	},
> +};
> +
> +static const struct cal_data dra76x_cal_data = {
> +	.camerarx = dra76x_cal_csi_phy,
> +	.num_csi2_phy = ARRAY_SIZE(dra76x_cal_csi_phy),
> +};
> +
> +static const struct cal_camerarx_data am654_cal_csi_phy[] = {
> +	{
> +		.fields = {
> +			[F_CTRLCLKEN] = { 15, 15 },
> +			[F_CAMMODE] = { 24, 25 },
> +			[F_LANEENABLE] = { 0, 4 },
> +		},
> +		.num_lanes = 5,
> +	},
> +};
> +
> +static const struct cal_data am654_cal_data = {
> +	.camerarx = am654_cal_csi_phy,
> +	.num_csi2_phy = ARRAY_SIZE(am654_cal_csi_phy),
> +};
> +
> +/* ------------------------------------------------------------------
> + *	I/O Register Accessors
> + * ------------------------------------------------------------------
> + */
> +
> +#define reg_read(dev, offset) ioread32(dev->base + offset)
> +#define reg_write(dev, offset, val) iowrite32(val, dev->base + offset)
> +
>  static inline u32 reg_read_field(struct cal_dev *cal, u32 offset, u32 mask)
>  {
>  	return FIELD_GET(mask, reg_read(cal, offset));
> @@ -423,41 +443,6 @@ static inline void reg_write_field(struct cal_dev *cal, u32 offset, u32 value,
>  	reg_write(cal, offset, val);
>  }
>  
> -static const struct cal_fmt *find_format_by_pix(struct cal_ctx *ctx,
> -						u32 pixelformat)
> -{
> -	const struct cal_fmt *fmt;
> -	unsigned int k;
> -
> -	for (k = 0; k < ctx->num_active_fmt; k++) {
> -		fmt = ctx->active_fmt[k];
> -		if (fmt->fourcc == pixelformat)
> -			return fmt;
> -	}
> -
> -	return NULL;
> -}
> -
> -static const struct cal_fmt *find_format_by_code(struct cal_ctx *ctx,
> -						 u32 code)
> -{
> -	const struct cal_fmt *fmt;
> -	unsigned int k;
> -
> -	for (k = 0; k < ctx->num_active_fmt; k++) {
> -		fmt = ctx->active_fmt[k];
> -		if (fmt->code == code)
> -			return fmt;
> -	}
> -
> -	return NULL;
> -}
> -
> -static inline struct cal_ctx *notifier_to_ctx(struct v4l2_async_notifier *n)
> -{
> -	return container_of(n, struct cal_ctx, notifier);
> -}
> -
>  static inline void set_field(u32 *valp, u32 field, u32 mask)
>  {
>  	u32 val = *valp;
> @@ -493,11 +478,6 @@ static void cal_quickdump_regs(struct cal_dev *cal)
>  	}
>  }
>  
> -static u32 cal_data_get_num_csi2_phy(struct cal_dev *cal)
> -{
> -	return cal->data->num_csi2_phy;
> -}
> -
>  /* ------------------------------------------------------------------
>   *	CAMERARX Management
>   * ------------------------------------------------------------------
> @@ -1152,6 +1132,11 @@ static void cal_ctx_wr_dma_addr(struct cal_ctx *ctx, unsigned int dmaaddr)
>  	reg_write(ctx->cal, CAL_WR_DMA_ADDR(ctx->csi2_port), dmaaddr);
>  }
>  
> +/* ------------------------------------------------------------------
> + *	IRQ Handling
> + * ------------------------------------------------------------------
> + */
> +
>  static inline void cal_schedule_next_buffer(struct cal_ctx *ctx)
>  {
>  	struct cal_dmaqueue *dma_q = &ctx->vidq;
> @@ -1255,9 +1240,41 @@ static irqreturn_t cal_irq(int irq_cal, void *data)
>  	return IRQ_HANDLED;
>  }
>  
> -/*
> - * video ioctls
> +/* ------------------------------------------------------------------
> + *	V4L2 Video IOCTLs
> + * ------------------------------------------------------------------
>   */
> +
> +static const struct cal_fmt *find_format_by_pix(struct cal_ctx *ctx,
> +						u32 pixelformat)
> +{
> +	const struct cal_fmt *fmt;
> +	unsigned int k;
> +
> +	for (k = 0; k < ctx->num_active_fmt; k++) {
> +		fmt = ctx->active_fmt[k];
> +		if (fmt->fourcc == pixelformat)
> +			return fmt;
> +	}
> +
> +	return NULL;
> +}
> +
> +static const struct cal_fmt *find_format_by_code(struct cal_ctx *ctx,
> +						 u32 code)
> +{
> +	const struct cal_fmt *fmt;
> +	unsigned int k;
> +
> +	for (k = 0; k < ctx->num_active_fmt; k++) {
> +		fmt = ctx->active_fmt[k];
> +		if (fmt->code == code)
> +			return fmt;
> +	}
> +
> +	return NULL;
> +}
> +
>  static int cal_querycap(struct file *file, void *priv,
>  			struct v4l2_capability *cap)
>  {
> @@ -1566,9 +1583,46 @@ static int cal_enum_frameintervals(struct file *file, void *priv,
>  	return 0;
>  }
>  
> -/*
> - * Videobuf operations
> +static const struct v4l2_file_operations cal_fops = {
> +	.owner		= THIS_MODULE,
> +	.open           = v4l2_fh_open,
> +	.release        = vb2_fop_release,
> +	.read           = vb2_fop_read,
> +	.poll		= vb2_fop_poll,
> +	.unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */
> +	.mmap           = vb2_fop_mmap,
> +};
> +
> +static const struct v4l2_ioctl_ops cal_ioctl_ops = {
> +	.vidioc_querycap      = cal_querycap,
> +	.vidioc_enum_fmt_vid_cap  = cal_enum_fmt_vid_cap,
> +	.vidioc_g_fmt_vid_cap     = cal_g_fmt_vid_cap,
> +	.vidioc_try_fmt_vid_cap   = cal_try_fmt_vid_cap,
> +	.vidioc_s_fmt_vid_cap     = cal_s_fmt_vid_cap,
> +	.vidioc_enum_framesizes   = cal_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_enum_input    = cal_enum_input,
> +	.vidioc_g_input       = cal_g_input,
> +	.vidioc_s_input       = cal_s_input,
> +	.vidioc_enum_frameintervals = cal_enum_frameintervals,
> +	.vidioc_streamon      = vb2_ioctl_streamon,
> +	.vidioc_streamoff     = vb2_ioctl_streamoff,
> +	.vidioc_log_status    = v4l2_ctrl_log_status,
> +	.vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
> +	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
> +};
> +
> +/* ------------------------------------------------------------------
> + *	videobuf2 Operations
> + * ------------------------------------------------------------------
>   */
> +
>  static int cal_queue_setup(struct vb2_queue *vq,
>  			   unsigned int *nbuffers, unsigned int *nplanes,
>  			   unsigned int sizes[], struct device *alloc_devs[])
> @@ -1772,40 +1826,10 @@ static const struct vb2_ops cal_video_qops = {
>  	.wait_finish		= vb2_ops_wait_finish,
>  };
>  
> -static const struct v4l2_file_operations cal_fops = {
> -	.owner		= THIS_MODULE,
> -	.open           = v4l2_fh_open,
> -	.release        = vb2_fop_release,
> -	.read           = vb2_fop_read,
> -	.poll		= vb2_fop_poll,
> -	.unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */
> -	.mmap           = vb2_fop_mmap,
> -};
> -
> -static const struct v4l2_ioctl_ops cal_ioctl_ops = {
> -	.vidioc_querycap      = cal_querycap,
> -	.vidioc_enum_fmt_vid_cap  = cal_enum_fmt_vid_cap,
> -	.vidioc_g_fmt_vid_cap     = cal_g_fmt_vid_cap,
> -	.vidioc_try_fmt_vid_cap   = cal_try_fmt_vid_cap,
> -	.vidioc_s_fmt_vid_cap     = cal_s_fmt_vid_cap,
> -	.vidioc_enum_framesizes   = cal_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_enum_input    = cal_enum_input,
> -	.vidioc_g_input       = cal_g_input,
> -	.vidioc_s_input       = cal_s_input,
> -	.vidioc_enum_frameintervals = cal_enum_frameintervals,
> -	.vidioc_streamon      = vb2_ioctl_streamon,
> -	.vidioc_streamoff     = vb2_ioctl_streamoff,
> -	.vidioc_log_status    = v4l2_ctrl_log_status,
> -	.vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
> -	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
> -};
> +/* ------------------------------------------------------------------
> + *	Initialization and module stuff
> + * ------------------------------------------------------------------
> + */
>  
>  static const struct video_device cal_videodev = {
>  	.name		= CAL_MODULE_NAME,
> @@ -1817,11 +1841,6 @@ static const struct video_device cal_videodev = {
>  			  V4L2_CAP_READWRITE,
>  };
>  
> -/* -----------------------------------------------------------------
> - *	Initialization and module stuff
> - * ------------------------------------------------------------------
> - */
> -
>  static int cal_complete_ctx(struct cal_ctx *ctx)
>  {
>  	struct video_device *vfd;
> @@ -2242,6 +2261,11 @@ static void cal_get_hwinfo(struct cal_dev *cal)
>  		hwinfo);
>  }
>  


Overall, the reorganisation is certainly helpful.

> +static u32 cal_data_get_num_csi2_phy(struct cal_dev *cal)
> +{
> +	return cal->data->num_csi2_phy;
> +}

However, this function (which is possibly a bit overkill on it's own
anyway) could be moved much higher in the module, so that /all/
references to the num_csi2_phy variable are accessed through it.

Otherwise, the code is inconsistent with other parts of the driver
directly accessing this value even with an accessor.

We could remove the accessor... or - apply the patch "media: ti-vpe:
cal: Use cal_data_get_num_csi2_phy() consistently" (which will follow
next) on top.

Otherwise,

Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>

> +
>  static int cal_probe(struct platform_device *pdev)
>  {
>  	struct cal_dev *cal;
> 


-- 
Regards
--
Kieran

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

* [PATCH] media: ti-vpe: cal: Use cal_data_get_num_csi2_phy() consistently
  2020-06-17 10:00   ` Kieran Bingham
@ 2020-06-17 10:02     ` Kieran Bingham
  2020-06-17 11:44       ` [PATCH] media: ti-vpe: cal: Handle multiple PHYs Kieran Bingham
  2020-06-17 10:51     ` [PATCH v1 036/107] media: ti-vpe: cal: Reorganize remaining code in sections Laurent Pinchart
  1 sibling, 1 reply; 150+ messages in thread
From: Kieran Bingham @ 2020-06-17 10:02 UTC (permalink / raw)
  To: Laurent Pinchart, linux-media
  Cc: Tomi Valkeinen, Benoit Parrot, Kieran Bingham

The helper cal_data_get_num_csi2_phy() is defined late in the module,
leaving 3 instances of open-coded access to the num_csi2_phy value.

Move the helper function directly after the 'struct cal_data' definitions
and utilise the helper consistently throughout.

Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 22 +++++++++++-----------
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index d00dc241804b..8e99e7e58188 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -253,6 +253,11 @@ static const struct cal_data am654_cal_data = {
 	.num_csi2_phy = ARRAY_SIZE(am654_cal_csi_phy),
 };
 
+static u32 cal_data_get_num_csi2_phy(struct cal_dev *cal)
+{
+	return cal->data->num_csi2_phy;
+}
+
 /* ------------------------------------------------------------------
  *	I/O Register Accessors
  * ------------------------------------------------------------------
@@ -267,7 +272,7 @@ void cal_quickdump_regs(struct cal_dev *cal)
 		       (__force const void *)cal->base,
 		       resource_size(cal->res), false);
 
-	for (i = 0; i < cal->data->num_csi2_phy; ++i) {
+	for (i = 0; i < cal_data_get_num_csi2_phy(cal); ++i) {
 		struct cal_camerarx *phy = cal->phy[i];
 
 		cal_info(cal, "CSI2 Core %u Registers @ %pa:\n", i,
@@ -559,7 +564,7 @@ static irqreturn_t cal_irq(int irq_cal, void *data)
 		if (status & CAL_HL_IRQ_OCPO_ERR_MASK)
 			dev_err_ratelimited(cal->dev, "OCPO ERROR\n");
 
-		for (i = 0; i < cal->data->num_csi2_phy; ++i) {
+		for (i = 0; i < cal_data_get_num_csi2_phy(cal); ++i) {
 			if (status & CAL_HL_IRQ_CIO_MASK(i)) {
 				u32 cio_stat = cal_read(cal,
 							CAL_CSI2_COMPLEXIO_IRQSTATUS(i));
@@ -685,7 +690,7 @@ static int cal_async_notifier_register(struct cal_dev *cal)
 	v4l2_async_notifier_init(&cal->notifier);
 	cal->notifier.ops = &cal_async_notifier_ops;
 
-	for (i = 0; i < cal->data->num_csi2_phy; ++i) {
+	for (i = 0; i < cal_data_get_num_csi2_phy(cal); ++i) {
 		struct cal_camerarx *phy = cal->phy[i];
 		struct cal_v4l2_async_subdev *casd;
 		struct v4l2_async_subdev *asd;
@@ -904,11 +909,6 @@ static void cal_get_hwinfo(struct cal_dev *cal)
 			 hwinfo, CAL_HL_HWINFO_VALUE);
 }
 
-static u32 cal_data_get_num_csi2_phy(struct cal_dev *cal)
-{
-	return cal->data->num_csi2_phy;
-}
-
 static int cal_init_camerarx_regmap(struct cal_dev *cal)
 {
 	struct platform_device *pdev = to_platform_device(cal->dev);
@@ -1063,7 +1063,7 @@ static int cal_probe(struct platform_device *pdev)
 
 error_media:
 	cal_media_cleanup(cal);
-	for (i = 0; i < cal->data->num_csi2_phy; i++)
+	for (i = 0; i < cal_data_get_num_csi2_phy(cal); i++)
 		cal_camerarx_destroy(cal->phy[i]);
 
 error_pm_runtime:
@@ -1090,7 +1090,7 @@ static int cal_remove(struct platform_device *pdev)
 
 	cal_media_cleanup(cal);
 
-	for (i = 0; i < cal->data->num_csi2_phy; i++)
+	for (i = 0; i < cal_data_get_num_csi2_phy(cal); i++)
 		cal_camerarx_destroy(cal->phy[i]);
 
 	pm_runtime_put_sync(&pdev->dev);
@@ -1109,7 +1109,7 @@ static int cal_runtime_resume(struct device *dev)
 		 * Apply errata on both port everytime we (re-)enable
 		 * the clock
 		 */
-		for (i = 0; i < cal->data->num_csi2_phy; i++)
+		for (i = 0; i < cal_data_get_num_csi2_phy(cal); i++)
 			cal_camerarx_i913_errata(cal->phy[i]);
 	}
 
-- 
2.25.1


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

* Re: [PATCH v1 078/107] media: ti-vpe: cal: Don't store external rate in cal_camerarx
  2020-06-17  9:56   ` Kieran Bingham
@ 2020-06-17 10:05     ` Laurent Pinchart
  2020-06-17 10:16       ` Kieran Bingham
  0 siblings, 1 reply; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-17 10:05 UTC (permalink / raw)
  To: Kieran Bingham; +Cc: linux-media, Tomi Valkeinen, Benoit Parrot

Hi Kieran,

On Wed, Jun 17, 2020 at 10:56:29AM +0100, Kieran Bingham wrote:
> On 15/06/2020 00:59, Laurent Pinchart wrote:
> > The external pixel rate is retrieved when starting the camerarx and only
> > used then. There's no need to store it in the cal_camerarx structure, it
> > can be returned by cal_camerarx_get_external_info() and explicitly
> > passed to cal_camerarx_config().
> > 
> > While at it, rename cal_camerarx_get_external_info() to
> > cal_camerarx_get_external_rate() to better reflect the function's
> > purpose.
> > 
> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > ---
> >  drivers/media/platform/ti-vpe/cal.c | 24 ++++++++++++------------
> >  1 file changed, 12 insertions(+), 12 deletions(-)
> > 
> > diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
> > index 8326db0e4197..a11457909134 100644
> > --- a/drivers/media/platform/ti-vpe/cal.c
> > +++ b/drivers/media/platform/ti-vpe/cal.c
> > @@ -272,7 +272,6 @@ struct cal_camerarx {
> >  	struct v4l2_fwnode_endpoint	endpoint;
> >  	struct device_node	*sensor_node;
> >  	struct v4l2_subdev	*sensor;
> > -	unsigned int		external_rate;
> 
> Here, external_rate is 32 bit,
> 
> >  };
> >  
> >  struct cal_dev {
> > @@ -481,9 +480,10 @@ static void cal_quickdump_regs(struct cal_dev *cal)
> >   * ------------------------------------------------------------------
> >   */
> >  
> > -static int cal_camerarx_get_external_info(struct cal_camerarx *phy)
> > +static s64 cal_camerarx_get_external_rate(struct cal_camerarx *phy)
> >  {
> >  	struct v4l2_ctrl *ctrl;
> > +	s64 rate;
> 
> and now it becomes a 64 bit value.
> 
> >  
> >  	if (!phy->sensor)
> >  		return -ENODEV;
> > @@ -495,10 +495,10 @@ static int cal_camerarx_get_external_info(struct cal_camerarx *phy)
> >  		return -EPIPE;
> >  	}
> >  
> > -	phy->external_rate = v4l2_ctrl_g_ctrl_int64(ctrl);
> > -	phy_dbg(3, phy, "sensor Pixel Rate: %u\n", phy->external_rate);
> > +	rate = v4l2_ctrl_g_ctrl_int64(ctrl);
> > +	phy_dbg(3, phy, "sensor Pixel Rate: %llu\n", rate);
> >  
> > -	return 0;
> > +	return rate;
> >  }
> >  
> >  static void cal_camerarx_lane_config(struct cal_camerarx *phy)
> > @@ -554,7 +554,7 @@ static void cal_camerarx_disable(struct cal_camerarx *phy)
> >  #define TCLK_MISS	1
> >  #define TCLK_SETTLE	14
> >  
> > -static void cal_camerarx_config(struct cal_camerarx *phy,
> > +static void cal_camerarx_config(struct cal_camerarx *phy, s64 external_rate,
> >  				const struct cal_fmt *fmt)
> >  {
> >  	unsigned int reg0, reg1;
> > @@ -566,7 +566,7 @@ static void cal_camerarx_config(struct cal_camerarx *phy,
> >  
> >  	/* DPHY timing configuration */
> >  	/* CSI-2 is DDR and we only count used lanes. */
> > -	csi2_ddrclk_khz = phy->external_rate / 1000
> > +	csi2_ddrclk_khz = external_rate / 1000
> >  		/ (2 * num_lanes) * fmt->bpp;
> 
> Which causes this calculation to fail on 32 bit ARM builds.
> (I'm building for the DRA76-EVM).

Oops :-/

> I've got the following fix up on the top of your tree to solve this, but
> I'm not particularly happy about having to break the calculation up (and
> re-use external_rate) though the use of do_div.
> 
> From ca6ce335a852e34364bc45cb4240f703e4ea4248 Mon Sep 17 00:00:00 2001
> From: Kieran Bingham <kieran.bingham@ideasonboard.com>
> Date: Tue, 16 Jun 2020 16:19:04 +0100
> Subject: [PATCH] media: ti-vpe: cal: Use do_div() for 64 bit operations
> 
> Support building the CAL driver on arm32 bit targets by updating the
> CSI2 clock calculation (which uses a signed 64 bit input value from
> the sensors pixel clock rate) to use the do_div() helpers.
> 
> The calculation is split into distinct parts to maintain
> order of operations while making use of the do_div macro and further
> re-ordered to convert to kHz at the end to maintain precision.
> 
> Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
> ---
>  drivers/media/platform/ti-vpe/cal-camerarx.c | 22 +++++++++++++++++---
>  1 file changed, 19 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/media/platform/ti-vpe/cal-camerarx.c
> b/drivers/media/platform/ti-vpe/cal-camerarx.c
> index 014ca46509db..0ef19a516902 100644
> --- a/drivers/media/platform/ti-vpe/cal-camerarx.c
> +++ b/drivers/media/platform/ti-vpe/cal-camerarx.c
> @@ -126,9 +126,25 @@ static void cal_camerarx_config(struct cal_camerarx
> *phy, s64 external_rate)
>         u32 num_lanes = mipi_csi2->num_data_lanes;
> 
>         /* DPHY timing configuration */
> -       /* CSI-2 is DDR and we only count used lanes. */
> -       csi2_ddrclk_khz = external_rate / 1000
> -               / (2 * num_lanes) * phy->fmtinfo->bpp;
> +
> +       /*
> +        * CSI-2 is DDR and we only count used lanes.
> +        *
> +        * csi2_ddrclk_khz = external_rate / 1000
> +        *                   / (2 * num_lanes) * phy->fmtinfo->bpp;
> +        *
> +        * The equation is broken into separate statements to maintain
> +        * order of operations, and conversion to kHz is done last to
> +        * keep precision.
> +        *
> +        * The 64 bit external_rate is modified during this equation and
> +        * contains the result, not the original after calculation.
> +        */
> +       do_div(external_rate, 2 * num_lanes);
> +       external_rate *= phy->fmtinfo->bpp;
> +       do_div(external_rate, 1000);
> +       csi2_ddrclk_khz = external_rate;

How about

	external_rate *= phy->fmtinfo->bpp;
 	do_div(external_rate, 2 * num_lanes * 1000);

> +
>         phy_dbg(1, phy, "csi2_ddrclk_khz: %d\n", csi2_ddrclk_khz);
> 
>         /* THS_TERM: Programmed value = floor(20 ns/DDRClk period) */
> -- 
> 2.25.1
> 
> 
> If you have a better way to correctly calculate the rate (also noting
> that I moved the /1000 to the end, I'm not sure if that's more correct,
> or makes it stop following what the hardware would do) - please update
> accordingly, or feel free to squash this patch in as you wish.
> 
> 
> With the calculation corrected:
> 
> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
> 
> --
> Kieran
> 
> 
> >  	phy_dbg(1, phy, "csi2_ddrclk_khz: %d\n", csi2_ddrclk_khz);
> >  
> > @@ -667,13 +667,14 @@ static void cal_camerarx_wait_stop_state(struct cal_camerarx *phy)
> >  static int cal_camerarx_start(struct cal_camerarx *phy,
> >  			      const struct cal_fmt *fmt)
> >  {
> > +	s64 external_rate;
> >  	u32 sscounter;
> >  	u32 val;
> >  	int ret;
> >  
> > -	ret = cal_camerarx_get_external_info(phy);
> > -	if (ret < 0)
> > -		return ret;
> > +	external_rate = cal_camerarx_get_external_rate(phy);
> > +	if (external_rate < 0)
> > +		return external_rate;
> >  
> >  	ret = v4l2_subdev_call(phy->sensor, core, s_power, 1);
> >  	if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV) {
> > @@ -719,7 +720,7 @@ static int cal_camerarx_start(struct cal_camerarx *phy,
> >  	reg_read(phy, CAL_CSI2_PHY_REG0);
> >  
> >  	/* Program the PHY timing parameters. */
> > -	cal_camerarx_config(phy, fmt);
> > +	cal_camerarx_config(phy, external_rate, fmt);
> >  
> >  	/*
> >  	 *    b. Assert the FORCERXMODE signal.
> > @@ -1034,7 +1035,6 @@ static struct cal_camerarx *cal_camerarx_create(struct cal_dev *cal,
> >  
> >  	phy->cal = cal;
> >  	phy->instance = instance;
> > -	phy->external_rate = 192000000;
> >  
> >  	phy->res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
> >  						(instance == 0) ?

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH v1 084/107] media: ti-vpe: cal: Create subdev for CAMERARX
  2020-06-14 23:59 ` [PATCH v1 084/107] media: ti-vpe: cal: Create subdev for CAMERARX Laurent Pinchart
@ 2020-06-17 10:10   ` Kieran Bingham
  2020-06-19 15:52     ` Laurent Pinchart
  0 siblings, 1 reply; 150+ messages in thread
From: Kieran Bingham @ 2020-06-17 10:10 UTC (permalink / raw)
  To: Laurent Pinchart, linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

Hi Laurent,

On 15/06/2020 00:59, Laurent Pinchart wrote:
> Create and register V4L2 sudbevs for the CAMERARX instances, and link

s/sudbevs/subdevs/

> them in the media graph to the sensors and video nodes. The subdev API
> is not exposed to userspace at this point, and no subdev operation is
> implemented, but the media controller graph is visible to applications.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>  drivers/media/platform/ti-vpe/cal-camerarx.c | 42 +++++++++++++++++++-
>  drivers/media/platform/ti-vpe/cal-video.c    | 12 ++++++
>  drivers/media/platform/ti-vpe/cal.c          | 31 ++++++++++++---
>  drivers/media/platform/ti-vpe/cal.h          |  9 ++++-
>  4 files changed, 86 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/media/platform/ti-vpe/cal-camerarx.c b/drivers/media/platform/ti-vpe/cal-camerarx.c
> index a7e4b81c9734..9be432ff87b2 100644
> --- a/drivers/media/platform/ti-vpe/cal-camerarx.c
> +++ b/drivers/media/platform/ti-vpe/cal-camerarx.c
> @@ -526,8 +526,8 @@ static int cal_camerarx_regmap_init(struct cal_dev *cal,
>  static int cal_camerarx_parse_dt(struct cal_camerarx *phy)
>  {
>  	struct v4l2_fwnode_endpoint *endpoint = &phy->endpoint;
> -	struct device_node *ep_node;
>  	char data_lanes[V4L2_FWNODE_CSI2_MAX_DATA_LANES * 2];
> +	struct device_node *ep_node;
>  	unsigned int i;
>  	int ret;
>  
> @@ -571,7 +571,8 @@ static int cal_camerarx_parse_dt(struct cal_camerarx *phy)
>  		endpoint->bus.mipi_csi2.flags);
>  
>  	/* Retrieve the connected device and store it for later use. */
> -	phy->sensor_node = of_graph_get_remote_port_parent(ep_node);
> +	phy->sensor_ep_node = of_graph_get_remote_endpoint(ep_node);
> +	phy->sensor_node = of_graph_get_port_parent(phy->sensor_ep_node);
>  	if (!phy->sensor_node) {
>  		phy_dbg(3, phy, "Can't get remote parent\n");
>  		goto done;
> @@ -580,15 +581,30 @@ static int cal_camerarx_parse_dt(struct cal_camerarx *phy)
>  	phy_dbg(1, phy, "Found connected device %pOFn\n", phy->sensor_node);
>  
>  done:
> +	of_node_put(phy->sensor_ep_node);
>  	of_node_put(ep_node);
>  	return ret;
>  }
>  
> +/* ------------------------------------------------------------------
> + *	V4L2 Subdev Operations
> + * ------------------------------------------------------------------
> + */
> +
> +static const struct v4l2_subdev_ops cal_camerarx_subdev_ops = {
> +};
> +
> +/* ------------------------------------------------------------------
> + *	Create and Destroy
> + * ------------------------------------------------------------------
> + */
> +
>  struct cal_camerarx *cal_camerarx_create(struct cal_dev *cal,
>  					 unsigned int instance)
>  {
>  	struct platform_device *pdev = to_platform_device(cal->dev);
>  	struct cal_camerarx *phy;
> +	struct v4l2_subdev *sd;
>  	int ret;
>  
>  	phy = kzalloc(sizeof(*phy), GFP_KERNEL);
> @@ -620,9 +636,28 @@ struct cal_camerarx *cal_camerarx_create(struct cal_dev *cal,
>  	if (ret)
>  		goto error;
>  
> +	/* Initialize the V4L2 subdev and media entity. */
> +	sd = &phy->subdev;
> +	v4l2_subdev_init(sd, &cal_camerarx_subdev_ops);
> +	sd->entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
> +	snprintf(sd->name, sizeof(sd->name), "CAMERARX%u", instance);
> +	sd->dev = cal->dev;
> +
> +	phy->pads[CAL_CAMERARX_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
> +	phy->pads[CAL_CAMERARX_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
> +	ret = media_entity_pads_init(&sd->entity, ARRAY_SIZE(phy->pads),
> +				     phy->pads);
> +	if (ret)
> +		goto error;
> +
> +	ret = v4l2_device_register_subdev(&cal->v4l2_dev, sd);
> +	if (ret)
> +		goto error;
> +
>  	return phy;
>  
>  error:
> +	media_entity_cleanup(&phy->subdev.entity);
>  	kfree(phy);
>  	return ERR_PTR(ret);
>  }
> @@ -632,6 +667,9 @@ void cal_camerarx_destroy(struct cal_camerarx *phy)
>  	if (!phy)
>  		return;
>  
> +	v4l2_device_unregister_subdev(&phy->subdev);
> +	media_entity_cleanup(&phy->subdev.entity);
> +	of_node_put(phy->sensor_ep_node);
>  	of_node_put(phy->sensor_node);
>  	kfree(phy);
>  }
> diff --git a/drivers/media/platform/ti-vpe/cal-video.c b/drivers/media/platform/ti-vpe/cal-video.c
> index df472a175e83..0a1a11692208 100644
> --- a/drivers/media/platform/ti-vpe/cal-video.c
> +++ b/drivers/media/platform/ti-vpe/cal-video.c
> @@ -809,6 +809,18 @@ int cal_ctx_v4l2_register(struct cal_ctx *ctx)
>  		return ret;
>  	}
>  
> +	ret = media_create_pad_link(&ctx->phy->subdev.entity,
> +				    CAL_CAMERARX_PAD_SOURCE,
> +				    &vfd->entity, 0,
> +				    MEDIA_LNK_FL_IMMUTABLE |
> +				    MEDIA_LNK_FL_ENABLED);
> +	if (ret) {
> +		ctx_err(ctx, "Failed to create media link for context %u\n",
> +			ctx->index);
> +		video_unregister_device(vfd);
> +		return ret;
> +	}
> +
>  	ctx_info(ctx, "V4L2 device registered as %s\n",
>  		 video_device_node_name(vfd));
>  
> diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
> index ca8576aa2646..bf1734d4d800 100644
> --- a/drivers/media/platform/ti-vpe/cal.c
> +++ b/drivers/media/platform/ti-vpe/cal.c
> @@ -416,6 +416,8 @@ static int cal_async_notifier_bound(struct v4l2_async_notifier *notifier,
>  				    struct v4l2_async_subdev *asd)
>  {
>  	struct cal_camerarx *phy = to_cal_asd(asd)->phy;
> +	int pad;
> +	int ret;
>  
>  	if (phy->sensor) {
>  		phy_info(phy, "Rejecting subdev %s (Already set!!)",
> @@ -426,6 +428,25 @@ static int cal_async_notifier_bound(struct v4l2_async_notifier *notifier,
>  	phy->sensor = subdev;
>  	phy_dbg(1, phy, "Using sensor %s for capture\n", subdev->name);
>  
> +	pad = media_entity_get_fwnode_pad(&subdev->entity,
> +					  of_fwnode_handle(phy->sensor_ep_node),
> +					  MEDIA_PAD_FL_SOURCE);
> +	if (pad < 0) {
> +		phy_err(phy, "Sensor %s has no connected source pad\n",
> +			subdev->name);
> +		return pad;
> +	}
> +
> +	ret = media_create_pad_link(&subdev->entity, pad,
> +				    &phy->subdev.entity, CAL_CAMERARX_PAD_SINK,
> +				    MEDIA_LNK_FL_IMMUTABLE |
> +				    MEDIA_LNK_FL_ENABLED);
> +	if (ret) {
> +		phy_err(phy, "Failed to create media link for sensor %s\n",
> +			subdev->name);
> +		return ret;
> +	}
> +
>  	return 0;
>  }
>  
> @@ -796,6 +817,11 @@ static int cal_probe(struct platform_device *pdev)
>  	cal_get_hwinfo(cal);
>  	pm_runtime_put_sync(&pdev->dev);
>  
> +	/* Initialize the media device. */
> +	ret = cal_media_init(cal);
> +	if (ret < 0)
> +		goto error_camerarx;

This code moves now uses the wrong error label.

Moreover, moving it - now means that the loop creating the CAMERARX PHYs
should now also cleanup the media device upon failure.

I have the following fixup patch which you could squash in here if you wish.


From e6fc5364d92d0ded26f3d8bb6c06a650fcb1ba84 Mon Sep 17 00:00:00 2001
From: Kieran Bingham <kieran.bingham@ideasonboard.com>
Date: Tue, 16 Jun 2020 15:00:19 +0100
Subject: [PATCH] media: ti-vpe: cal: Fix error path jumps

The error paths in cal_probe() incorrectly called through the
error_camerarx before the camerarx instances were created, and neglected
to call the error_media/cal_media_cleanup() paths if a camera failed to
be created.

Tidy up the error paths, removing the now redundant error_media label.

Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal.c
b/drivers/media/platform/ti-vpe/cal.c
index caea3e129c87..d00dc241804b 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -1026,14 +1026,14 @@ static int cal_probe(struct platform_device *pdev)
        /* Initialize the media device. */
        ret = cal_media_init(cal);
        if (ret < 0)
-               goto error_camerarx;
+               goto error_pm_runtime;

        /* Create CAMERARX PHYs. */
        for (i = 0; i < cal_data_get_num_csi2_phy(cal); ++i) {
                cal->phy[i] = cal_camerarx_create(cal, i);
                if (IS_ERR(cal->phy[i])) {
                        ret = PTR_ERR(cal->phy[i]);
-                       goto error_camerarx;
+                       goto error_media;
                }
        }

@@ -1063,8 +1063,6 @@ static int cal_probe(struct platform_device *pdev)

 error_media:
        cal_media_cleanup(cal);
-
-error_camerarx:
        for (i = 0; i < cal->data->num_csi2_phy; i++)
                cal_camerarx_destroy(cal->phy[i]);

-- 
2.25.1



With that fixed,

Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>


> +
>  	/* Create CAMERARX PHYs. */
>  	for (i = 0; i < cal_data_get_num_csi2_phy(cal); ++i) {
>  		cal->phy[i] = cal_camerarx_create(cal, i);
> @@ -805,11 +831,6 @@ static int cal_probe(struct platform_device *pdev)
>  		}
>  	}
>  
> -	/* Initialize the media device. */
> -	ret = cal_media_init(cal);
> -	if (ret < 0)
> -		goto error_camerarx;
> -
>  	/* Create contexts. */
>  	for (i = 0; i < cal_data_get_num_csi2_phy(cal); ++i)
>  		cal->ctx[i] = cal_ctx_create(cal, i);
> diff --git a/drivers/media/platform/ti-vpe/cal.h b/drivers/media/platform/ti-vpe/cal.h
> index cb167bfc2773..bf31dbf24523 100644
> --- a/drivers/media/platform/ti-vpe/cal.h
> +++ b/drivers/media/platform/ti-vpe/cal.h
> @@ -24,6 +24,7 @@
>  #include <media/v4l2-dev.h>
>  #include <media/v4l2-device.h>
>  #include <media/v4l2-fwnode.h>
> +#include <media/v4l2-subdev.h>
>  #include <media/videobuf2-v4l2.h>
>  
>  #define CAL_MODULE_NAME			"cal"
> @@ -33,12 +34,14 @@
>  #define MAX_WIDTH_BYTES			(8192 * 8)
>  #define MAX_HEIGHT_LINES		16383
>  
> +#define CAL_CAMERARX_PAD_SINK		0
> +#define CAL_CAMERARX_PAD_SOURCE		1
> +
>  struct device;
>  struct device_node;
>  struct resource;
>  struct regmap;
>  struct regmap_fied;
> -struct v4l2_subdev;
>  
>  /* CTRL_CORE_CAMERRX_CONTROL register field id */
>  enum cal_camerarx_field {
> @@ -108,8 +111,12 @@ struct cal_camerarx {
>  	unsigned int		instance;
>  
>  	struct v4l2_fwnode_endpoint	endpoint;
> +	struct device_node	*sensor_ep_node;
>  	struct device_node	*sensor_node;
>  	struct v4l2_subdev	*sensor;
> +
> +	struct v4l2_subdev	subdev;
> +	struct media_pad	pads[2];
>  };
>  
>  struct cal_dev {
> 


-- 
Regards
--
Kieran

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

* Re: [PATCH v1 078/107] media: ti-vpe: cal: Don't store external rate in cal_camerarx
  2020-06-17 10:05     ` Laurent Pinchart
@ 2020-06-17 10:16       ` Kieran Bingham
  2020-06-18  2:36         ` Laurent Pinchart
  0 siblings, 1 reply; 150+ messages in thread
From: Kieran Bingham @ 2020-06-17 10:16 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Tomi Valkeinen, Benoit Parrot

Hi Laurent,

On 17/06/2020 11:05, Laurent Pinchart wrote:
> Hi Kieran,
> 
> On Wed, Jun 17, 2020 at 10:56:29AM +0100, Kieran Bingham wrote:
>> On 15/06/2020 00:59, Laurent Pinchart wrote:
>>> The external pixel rate is retrieved when starting the camerarx and only
>>> used then. There's no need to store it in the cal_camerarx structure, it
>>> can be returned by cal_camerarx_get_external_info() and explicitly
>>> passed to cal_camerarx_config().
>>>
>>> While at it, rename cal_camerarx_get_external_info() to
>>> cal_camerarx_get_external_rate() to better reflect the function's
>>> purpose.
>>>
>>> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
>>> ---
>>>  drivers/media/platform/ti-vpe/cal.c | 24 ++++++++++++------------
>>>  1 file changed, 12 insertions(+), 12 deletions(-)
>>>
>>> diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
>>> index 8326db0e4197..a11457909134 100644
>>> --- a/drivers/media/platform/ti-vpe/cal.c
>>> +++ b/drivers/media/platform/ti-vpe/cal.c
>>> @@ -272,7 +272,6 @@ struct cal_camerarx {
>>>  	struct v4l2_fwnode_endpoint	endpoint;
>>>  	struct device_node	*sensor_node;
>>>  	struct v4l2_subdev	*sensor;
>>> -	unsigned int		external_rate;
>>
>> Here, external_rate is 32 bit,
>>
>>>  };
>>>  
>>>  struct cal_dev {
>>> @@ -481,9 +480,10 @@ static void cal_quickdump_regs(struct cal_dev *cal)
>>>   * ------------------------------------------------------------------
>>>   */
>>>  
>>> -static int cal_camerarx_get_external_info(struct cal_camerarx *phy)
>>> +static s64 cal_camerarx_get_external_rate(struct cal_camerarx *phy)
>>>  {
>>>  	struct v4l2_ctrl *ctrl;
>>> +	s64 rate;
>>
>> and now it becomes a 64 bit value.
>>
>>>  
>>>  	if (!phy->sensor)
>>>  		return -ENODEV;
>>> @@ -495,10 +495,10 @@ static int cal_camerarx_get_external_info(struct cal_camerarx *phy)
>>>  		return -EPIPE;
>>>  	}
>>>  
>>> -	phy->external_rate = v4l2_ctrl_g_ctrl_int64(ctrl);
>>> -	phy_dbg(3, phy, "sensor Pixel Rate: %u\n", phy->external_rate);
>>> +	rate = v4l2_ctrl_g_ctrl_int64(ctrl);
>>> +	phy_dbg(3, phy, "sensor Pixel Rate: %llu\n", rate);
>>>  
>>> -	return 0;
>>> +	return rate;
>>>  }
>>>  
>>>  static void cal_camerarx_lane_config(struct cal_camerarx *phy)
>>> @@ -554,7 +554,7 @@ static void cal_camerarx_disable(struct cal_camerarx *phy)
>>>  #define TCLK_MISS	1
>>>  #define TCLK_SETTLE	14
>>>  
>>> -static void cal_camerarx_config(struct cal_camerarx *phy,
>>> +static void cal_camerarx_config(struct cal_camerarx *phy, s64 external_rate,
>>>  				const struct cal_fmt *fmt)
>>>  {
>>>  	unsigned int reg0, reg1;
>>> @@ -566,7 +566,7 @@ static void cal_camerarx_config(struct cal_camerarx *phy,
>>>  
>>>  	/* DPHY timing configuration */
>>>  	/* CSI-2 is DDR and we only count used lanes. */
>>> -	csi2_ddrclk_khz = phy->external_rate / 1000
>>> +	csi2_ddrclk_khz = external_rate / 1000
>>>  		/ (2 * num_lanes) * fmt->bpp;
>>
>> Which causes this calculation to fail on 32 bit ARM builds.
>> (I'm building for the DRA76-EVM).
> 
> Oops :-/
> 
>> I've got the following fix up on the top of your tree to solve this, but
>> I'm not particularly happy about having to break the calculation up (and
>> re-use external_rate) though the use of do_div.
>>
>> From ca6ce335a852e34364bc45cb4240f703e4ea4248 Mon Sep 17 00:00:00 2001
>> From: Kieran Bingham <kieran.bingham@ideasonboard.com>
>> Date: Tue, 16 Jun 2020 16:19:04 +0100
>> Subject: [PATCH] media: ti-vpe: cal: Use do_div() for 64 bit operations
>>
>> Support building the CAL driver on arm32 bit targets by updating the
>> CSI2 clock calculation (which uses a signed 64 bit input value from
>> the sensors pixel clock rate) to use the do_div() helpers.
>>
>> The calculation is split into distinct parts to maintain
>> order of operations while making use of the do_div macro and further
>> re-ordered to convert to kHz at the end to maintain precision.
>>
>> Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
>> ---
>>  drivers/media/platform/ti-vpe/cal-camerarx.c | 22 +++++++++++++++++---
>>  1 file changed, 19 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/media/platform/ti-vpe/cal-camerarx.c
>> b/drivers/media/platform/ti-vpe/cal-camerarx.c
>> index 014ca46509db..0ef19a516902 100644
>> --- a/drivers/media/platform/ti-vpe/cal-camerarx.c
>> +++ b/drivers/media/platform/ti-vpe/cal-camerarx.c
>> @@ -126,9 +126,25 @@ static void cal_camerarx_config(struct cal_camerarx
>> *phy, s64 external_rate)
>>         u32 num_lanes = mipi_csi2->num_data_lanes;
>>
>>         /* DPHY timing configuration */
>> -       /* CSI-2 is DDR and we only count used lanes. */
>> -       csi2_ddrclk_khz = external_rate / 1000
>> -               / (2 * num_lanes) * phy->fmtinfo->bpp;
>> +
>> +       /*
>> +        * CSI-2 is DDR and we only count used lanes.
>> +        *
>> +        * csi2_ddrclk_khz = external_rate / 1000
>> +        *                   / (2 * num_lanes) * phy->fmtinfo->bpp;
>> +        *
>> +        * The equation is broken into separate statements to maintain
>> +        * order of operations, and conversion to kHz is done last to
>> +        * keep precision.
>> +        *
>> +        * The 64 bit external_rate is modified during this equation and
>> +        * contains the result, not the original after calculation.
>> +        */
>> +       do_div(external_rate, 2 * num_lanes);
>> +       external_rate *= phy->fmtinfo->bpp;
>> +       do_div(external_rate, 1000);
>> +       csi2_ddrclk_khz = external_rate;
> 
> How about
> 
> 	external_rate *= phy->fmtinfo->bpp;
>  	do_div(external_rate, 2 * num_lanes * 1000);

Ah yes, that looks better indeed, and keeps the improved integer precision.

I believe the s64 external_rate should cope with the * bpp operation
easily too, so I don't think there's any risk of an overflow there.

Squash it ;-)

--
Kieran


> 
>> +
>>         phy_dbg(1, phy, "csi2_ddrclk_khz: %d\n", csi2_ddrclk_khz);
>>
>>         /* THS_TERM: Programmed value = floor(20 ns/DDRClk period) */
>> -- 
>> 2.25.1
>>
>>
>> If you have a better way to correctly calculate the rate (also noting
>> that I moved the /1000 to the end, I'm not sure if that's more correct,
>> or makes it stop following what the hardware would do) - please update
>> accordingly, or feel free to squash this patch in as you wish.
>>
>>
>> With the calculation corrected:
>>
>> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
>>
>> --
>> Kieran
>>
>>
>>>  	phy_dbg(1, phy, "csi2_ddrclk_khz: %d\n", csi2_ddrclk_khz);
>>>  
>>> @@ -667,13 +667,14 @@ static void cal_camerarx_wait_stop_state(struct cal_camerarx *phy)
>>>  static int cal_camerarx_start(struct cal_camerarx *phy,
>>>  			      const struct cal_fmt *fmt)
>>>  {
>>> +	s64 external_rate;
>>>  	u32 sscounter;
>>>  	u32 val;
>>>  	int ret;
>>>  
>>> -	ret = cal_camerarx_get_external_info(phy);
>>> -	if (ret < 0)
>>> -		return ret;
>>> +	external_rate = cal_camerarx_get_external_rate(phy);
>>> +	if (external_rate < 0)
>>> +		return external_rate;
>>>  
>>>  	ret = v4l2_subdev_call(phy->sensor, core, s_power, 1);
>>>  	if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV) {
>>> @@ -719,7 +720,7 @@ static int cal_camerarx_start(struct cal_camerarx *phy,
>>>  	reg_read(phy, CAL_CSI2_PHY_REG0);
>>>  
>>>  	/* Program the PHY timing parameters. */
>>> -	cal_camerarx_config(phy, fmt);
>>> +	cal_camerarx_config(phy, external_rate, fmt);
>>>  
>>>  	/*
>>>  	 *    b. Assert the FORCERXMODE signal.
>>> @@ -1034,7 +1035,6 @@ static struct cal_camerarx *cal_camerarx_create(struct cal_dev *cal,
>>>  
>>>  	phy->cal = cal;
>>>  	phy->instance = instance;
>>> -	phy->external_rate = 192000000;
>>>  
>>>  	phy->res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
>>>  						(instance == 0) ?
> 

-- 
Regards
--
Kieran

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

* Re: [PATCH v1 056/107] media: ti-vpe: cal: Add cal_camerarx_destroy() to cleanup CAMERARX
  2020-06-14 23:58 ` [PATCH v1 056/107] media: ti-vpe: cal: Add cal_camerarx_destroy() to cleanup CAMERARX Laurent Pinchart
@ 2020-06-17 10:43   ` Kieran Bingham
  2020-06-19 15:36     ` Laurent Pinchart
  0 siblings, 1 reply; 150+ messages in thread
From: Kieran Bingham @ 2020-06-17 10:43 UTC (permalink / raw)
  To: Laurent Pinchart, linux-media; +Cc: Tomi Valkeinen, Benoit Parrot

Hi Laurent,

On 15/06/2020 00:58, Laurent Pinchart wrote:
> The cal_camerarx_create() function allocates resources with devm_*, and
> thus doesn't need any manual cleanup. Those won't hold true for long, as
> we will need to store resources that have no devm_* allocation variant
> in cal_camerarx. Furthermore, devm_kzalloc() is the wrong memory
> allocation API for structures that can be accessed from userspace, as
> device nodes can be kept open across device removal.

I still think that should be fixed by making devm_ allocations able to
be reference counted so that it doesn't remove until until references
(from open file handles) are released ;-) but that's completely out of
scope here...


> 
> Add a cal_camerarx_destroy() function to destroy a CAMERARX instance
> explicitly, and switch to kzalloc() for memory allocation.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>  drivers/media/platform/ti-vpe/cal.c | 35 ++++++++++++++++++++++++-----
>  1 file changed, 29 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
> index b8c7ad8e39cd..c9fef333c532 100644
> --- a/drivers/media/platform/ti-vpe/cal.c
> +++ b/drivers/media/platform/ti-vpe/cal.c
> @@ -931,7 +931,7 @@ static struct cal_camerarx *cal_camerarx_create(struct cal_dev *cal,
>  	struct cal_camerarx *phy;
>  	int ret;
>  
> -	phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL);
> +	phy = kzalloc(sizeof(*phy), GFP_KERNEL);
>  	if (!phy)
>  		return ERR_PTR(-ENOMEM);
>  
> @@ -946,7 +946,8 @@ static struct cal_camerarx *cal_camerarx_create(struct cal_dev *cal,
>  	phy->base = devm_ioremap_resource(&pdev->dev, phy->res);
>  	if (IS_ERR(phy->base)) {
>  		cal_err(cal, "failed to ioremap\n");
> -		return ERR_CAST(phy->base);
> +		ret = PTR_ERR(phy->base);
> +		goto error;
>  	}
>  
>  	cal_dbg(1, cal, "ioresource %s at %pa - %pa\n",
> @@ -954,9 +955,21 @@ static struct cal_camerarx *cal_camerarx_create(struct cal_dev *cal,
>  
>  	ret = cal_camerarx_regmap_init(cal, phy);
>  	if (ret)
> -		return ERR_PTR(ret);
> +		goto error;
>  
>  	return phy;
> +
> +error:
> +	kfree(phy);
> +	return ERR_PTR(ret);
> +}
> +
> +static void cal_camerarx_destroy(struct cal_camerarx *phy)
> +{
> +	if (!phy)
> +		return;
> +
> +	kfree(phy);
>  }
>  
>  static int cal_camerarx_init_regmap(struct cal_dev *cal)
> @@ -2252,15 +2265,17 @@ static int cal_probe(struct platform_device *pdev)
>  	/* Create CAMERARX PHYs. */
>  	for (i = 0; i < cal_data_get_num_csi2_phy(cal); ++i) {
>  		cal->phy[i] = cal_camerarx_create(cal, i);
> -		if (IS_ERR(cal->phy[i]))
> -			return PTR_ERR(cal->phy[i]);
> +		if (IS_ERR(cal->phy[i])) {
> +			ret = PTR_ERR(cal->phy[i]);

here, cal->phy[i] is an error value, but you then iterate them and call
cal_camerarx_destroy() on this value.

Perhaps you should set the following here, before jumping:

			cal->phy[i] = NULL;


> +			goto error_camerarx;
> +		}
>  	}
>  
>  	/* Register the V4L2 device. */
>  	ret = v4l2_device_register(&pdev->dev, &cal->v4l2_dev);
>  	if (ret) {
>  		cal_err(cal, "Failed to register V4L2 device\n");
> -		return ret;
> +		goto error_camerarx;
>  	}
>  
>  	/* Create contexts. */
> @@ -2301,6 +2316,11 @@ static int cal_probe(struct platform_device *pdev)
>  
>  error_v4l2:
>  	v4l2_device_unregister(&cal->v4l2_dev);
> +
> +error_camerarx:
> +	for (i = 0; i < ARRAY_SIZE(cal->phy); i++)
> +		cal_camerarx_destroy(cal->phy[i]);
> +
>  	return ret;
>  }
>  
> @@ -2329,6 +2349,9 @@ static int cal_remove(struct platform_device *pdev)
>  
>  	v4l2_device_unregister(&cal->v4l2_dev);
>  
> +	for (i = 0; i < ARRAY_SIZE(cal->phy); i++)
> +		cal_camerarx_destroy(cal->phy[i]);
> +
>  	pm_runtime_put_sync(&pdev->dev);
>  	pm_runtime_disable(&pdev->dev);
>  
> 

-- 
Regards
--
Kieran

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

* Re: [PATCH v1 036/107] media: ti-vpe: cal: Reorganize remaining code in sections
  2020-06-17 10:00   ` Kieran Bingham
  2020-06-17 10:02     ` [PATCH] media: ti-vpe: cal: Use cal_data_get_num_csi2_phy() consistently Kieran Bingham
@ 2020-06-17 10:51     ` Laurent Pinchart
  2020-06-17 10:54       ` Kieran Bingham
  1 sibling, 1 reply; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-17 10:51 UTC (permalink / raw)
  To: Kieran Bingham; +Cc: linux-media, Tomi Valkeinen, Benoit Parrot

On Wed, Jun 17, 2020 at 11:00:31AM +0100, Kieran Bingham wrote:
> On 15/06/2020 00:58, Laurent Pinchart wrote:
> > Increase readability by reorganizing the remaining code in sections. No
> > functional change is included.
> > 
> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > ---
> >  drivers/media/platform/ti-vpe/cal.c | 350 +++++++++++++++-------------
> >  1 file changed, 187 insertions(+), 163 deletions(-)
> > 
> > diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
> > index 176f616033a1..6f33853ecdb2 100644
> > --- a/drivers/media/platform/ti-vpe/cal.c
> > +++ b/drivers/media/platform/ti-vpe/cal.c
> > @@ -37,9 +37,6 @@
> >  
> >  #define CAL_MODULE_NAME "cal"
> >  
> > -#define MAX_WIDTH_BYTES (8192 * 8)
> > -#define MAX_HEIGHT_LINES 16383
> > -
> >  MODULE_DESCRIPTION("TI CAL driver");
> >  MODULE_AUTHOR("Benoit Parrot, <bparrot@ti.com>");
> >  MODULE_LICENSE("GPL v2");
> > @@ -79,11 +76,11 @@ MODULE_PARM_DESC(debug, "activates debug info");
> >  
> >  #define CAL_NUM_CONTEXT 2
> >  
> > -#define reg_read(dev, offset) ioread32(dev->base + offset)
> > -#define reg_write(dev, offset, val) iowrite32(val, dev->base + offset)
> > +#define MAX_WIDTH_BYTES (8192 * 8)
> > +#define MAX_HEIGHT_LINES 16383
> >  
> >  /* ------------------------------------------------------------------
> > - *	Basic structures
> > + *	Format Handling
> >   * ------------------------------------------------------------------
> >   */
> >  
> > @@ -204,6 +201,11 @@ static char *fourcc_to_str(u32 fmt)
> >  	return code;
> >  }
> >  
> > +/* ------------------------------------------------------------------
> > + *	Driver Structures
> > + * ------------------------------------------------------------------
> > + */
> > +
> >  /* buffer for one video frame */
> >  struct cal_buffer {
> >  	/* common v4l buffer stuff -- must be first */
> > @@ -239,80 +241,6 @@ struct cal_data {
> >  	unsigned int flags;
> >  };
> >  
> > -static const struct cal_camerarx_data dra72x_cal_camerarx[] = {
> > -	{
> > -		.fields = {
> > -			[F_CTRLCLKEN] = { 10, 10 },
> > -			[F_CAMMODE] = { 11, 12 },
> > -			[F_LANEENABLE] = { 13, 16 },
> > -			[F_CSI_MODE] = { 17, 17 },
> > -		},
> > -		.num_lanes = 4,
> > -	},
> > -	{
> > -		.fields = {
> > -			[F_CTRLCLKEN] = { 0, 0 },
> > -			[F_CAMMODE] = { 1, 2 },
> > -			[F_LANEENABLE] = { 3, 4 },
> > -			[F_CSI_MODE] = { 5, 5 },
> > -		},
> > -		.num_lanes = 2,
> > -	},
> > -};
> > -
> > -static const struct cal_data dra72x_cal_data = {
> > -	.camerarx = dra72x_cal_camerarx,
> > -	.num_csi2_phy = ARRAY_SIZE(dra72x_cal_camerarx),
> > -};
> > -
> > -static const struct cal_data dra72x_es1_cal_data = {
> > -	.camerarx = dra72x_cal_camerarx,
> > -	.num_csi2_phy = ARRAY_SIZE(dra72x_cal_camerarx),
> > -	.flags = DRA72_CAL_PRE_ES2_LDO_DISABLE,
> > -};
> > -
> > -static const struct cal_camerarx_data dra76x_cal_csi_phy[] = {
> > -	{
> > -		.fields = {
> > -			[F_CTRLCLKEN] = { 8, 8 },
> > -			[F_CAMMODE] = { 9, 10 },
> > -			[F_CSI_MODE] = { 11, 11 },
> > -			[F_LANEENABLE] = { 27, 31 },
> > -		},
> > -		.num_lanes = 5,
> > -	},
> > -	{
> > -		.fields = {
> > -			[F_CTRLCLKEN] = { 0, 0 },
> > -			[F_CAMMODE] = { 1, 2 },
> > -			[F_CSI_MODE] = { 3, 3 },
> > -			[F_LANEENABLE] = { 24, 26 },
> > -		},
> > -		.num_lanes = 3,
> > -	},
> > -};
> > -
> > -static const struct cal_data dra76x_cal_data = {
> > -	.camerarx = dra76x_cal_csi_phy,
> > -	.num_csi2_phy = ARRAY_SIZE(dra76x_cal_csi_phy),
> > -};
> > -
> > -static const struct cal_camerarx_data am654_cal_csi_phy[] = {
> > -	{
> > -		.fields = {
> > -			[F_CTRLCLKEN] = { 15, 15 },
> > -			[F_CAMMODE] = { 24, 25 },
> > -			[F_LANEENABLE] = { 0, 4 },
> > -		},
> > -		.num_lanes = 5,
> > -	},
> > -};
> > -
> > -static const struct cal_data am654_cal_data = {
> > -	.camerarx = am654_cal_csi_phy,
> > -	.num_csi2_phy = ARRAY_SIZE(am654_cal_csi_phy),
> > -};
> > -
> >  /*
> >   * The Camera Adaptation Layer (CAL) module is paired with one or more complex
> >   * I/O PHYs (CAMERARX). It contains multiple instances of CSI-2, processing and
> > @@ -408,6 +336,98 @@ struct cal_ctx {
> >  	bool dma_act;
> >  };
> >  
> > +static inline struct cal_ctx *notifier_to_ctx(struct v4l2_async_notifier *n)
> > +{
> > +	return container_of(n, struct cal_ctx, notifier);
> > +}
> > +
> > +/* ------------------------------------------------------------------
> > + *	Platform Data
> > + * ------------------------------------------------------------------
> > + */
> > +
> > +static const struct cal_camerarx_data dra72x_cal_camerarx[] = {
> > +	{
> > +		.fields = {
> > +			[F_CTRLCLKEN] = { 10, 10 },
> > +			[F_CAMMODE] = { 11, 12 },
> > +			[F_LANEENABLE] = { 13, 16 },
> > +			[F_CSI_MODE] = { 17, 17 },
> > +		},
> > +		.num_lanes = 4,
> > +	},
> > +	{
> > +		.fields = {
> > +			[F_CTRLCLKEN] = { 0, 0 },
> > +			[F_CAMMODE] = { 1, 2 },
> > +			[F_LANEENABLE] = { 3, 4 },
> > +			[F_CSI_MODE] = { 5, 5 },
> > +		},
> > +		.num_lanes = 2,
> > +	},
> > +};
> > +
> > +static const struct cal_data dra72x_cal_data = {
> > +	.camerarx = dra72x_cal_camerarx,
> > +	.num_csi2_phy = ARRAY_SIZE(dra72x_cal_camerarx),
> > +};
> > +
> > +static const struct cal_data dra72x_es1_cal_data = {
> > +	.camerarx = dra72x_cal_camerarx,
> > +	.num_csi2_phy = ARRAY_SIZE(dra72x_cal_camerarx),
> > +	.flags = DRA72_CAL_PRE_ES2_LDO_DISABLE,
> > +};
> > +
> > +static const struct cal_camerarx_data dra76x_cal_csi_phy[] = {
> > +	{
> > +		.fields = {
> > +			[F_CTRLCLKEN] = { 8, 8 },
> > +			[F_CAMMODE] = { 9, 10 },
> > +			[F_CSI_MODE] = { 11, 11 },
> > +			[F_LANEENABLE] = { 27, 31 },
> > +		},
> > +		.num_lanes = 5,
> > +	},
> > +	{
> > +		.fields = {
> > +			[F_CTRLCLKEN] = { 0, 0 },
> > +			[F_CAMMODE] = { 1, 2 },
> > +			[F_CSI_MODE] = { 3, 3 },
> > +			[F_LANEENABLE] = { 24, 26 },
> > +		},
> > +		.num_lanes = 3,
> > +	},
> > +};
> > +
> > +static const struct cal_data dra76x_cal_data = {
> > +	.camerarx = dra76x_cal_csi_phy,
> > +	.num_csi2_phy = ARRAY_SIZE(dra76x_cal_csi_phy),
> > +};
> > +
> > +static const struct cal_camerarx_data am654_cal_csi_phy[] = {
> > +	{
> > +		.fields = {
> > +			[F_CTRLCLKEN] = { 15, 15 },
> > +			[F_CAMMODE] = { 24, 25 },
> > +			[F_LANEENABLE] = { 0, 4 },
> > +		},
> > +		.num_lanes = 5,
> > +	},
> > +};
> > +
> > +static const struct cal_data am654_cal_data = {
> > +	.camerarx = am654_cal_csi_phy,
> > +	.num_csi2_phy = ARRAY_SIZE(am654_cal_csi_phy),
> > +};
> > +
> > +/* ------------------------------------------------------------------
> > + *	I/O Register Accessors
> > + * ------------------------------------------------------------------
> > + */
> > +
> > +#define reg_read(dev, offset) ioread32(dev->base + offset)
> > +#define reg_write(dev, offset, val) iowrite32(val, dev->base + offset)
> > +
> >  static inline u32 reg_read_field(struct cal_dev *cal, u32 offset, u32 mask)
> >  {
> >  	return FIELD_GET(mask, reg_read(cal, offset));
> > @@ -423,41 +443,6 @@ static inline void reg_write_field(struct cal_dev *cal, u32 offset, u32 value,
> >  	reg_write(cal, offset, val);
> >  }
> >  
> > -static const struct cal_fmt *find_format_by_pix(struct cal_ctx *ctx,
> > -						u32 pixelformat)
> > -{
> > -	const struct cal_fmt *fmt;
> > -	unsigned int k;
> > -
> > -	for (k = 0; k < ctx->num_active_fmt; k++) {
> > -		fmt = ctx->active_fmt[k];
> > -		if (fmt->fourcc == pixelformat)
> > -			return fmt;
> > -	}
> > -
> > -	return NULL;
> > -}
> > -
> > -static const struct cal_fmt *find_format_by_code(struct cal_ctx *ctx,
> > -						 u32 code)
> > -{
> > -	const struct cal_fmt *fmt;
> > -	unsigned int k;
> > -
> > -	for (k = 0; k < ctx->num_active_fmt; k++) {
> > -		fmt = ctx->active_fmt[k];
> > -		if (fmt->code == code)
> > -			return fmt;
> > -	}
> > -
> > -	return NULL;
> > -}
> > -
> > -static inline struct cal_ctx *notifier_to_ctx(struct v4l2_async_notifier *n)
> > -{
> > -	return container_of(n, struct cal_ctx, notifier);
> > -}
> > -
> >  static inline void set_field(u32 *valp, u32 field, u32 mask)
> >  {
> >  	u32 val = *valp;
> > @@ -493,11 +478,6 @@ static void cal_quickdump_regs(struct cal_dev *cal)
> >  	}
> >  }
> >  
> > -static u32 cal_data_get_num_csi2_phy(struct cal_dev *cal)
> > -{
> > -	return cal->data->num_csi2_phy;
> > -}
> > -
> >  /* ------------------------------------------------------------------
> >   *	CAMERARX Management
> >   * ------------------------------------------------------------------
> > @@ -1152,6 +1132,11 @@ static void cal_ctx_wr_dma_addr(struct cal_ctx *ctx, unsigned int dmaaddr)
> >  	reg_write(ctx->cal, CAL_WR_DMA_ADDR(ctx->csi2_port), dmaaddr);
> >  }
> >  
> > +/* ------------------------------------------------------------------
> > + *	IRQ Handling
> > + * ------------------------------------------------------------------
> > + */
> > +
> >  static inline void cal_schedule_next_buffer(struct cal_ctx *ctx)
> >  {
> >  	struct cal_dmaqueue *dma_q = &ctx->vidq;
> > @@ -1255,9 +1240,41 @@ static irqreturn_t cal_irq(int irq_cal, void *data)
> >  	return IRQ_HANDLED;
> >  }
> >  
> > -/*
> > - * video ioctls
> > +/* ------------------------------------------------------------------
> > + *	V4L2 Video IOCTLs
> > + * ------------------------------------------------------------------
> >   */
> > +
> > +static const struct cal_fmt *find_format_by_pix(struct cal_ctx *ctx,
> > +						u32 pixelformat)
> > +{
> > +	const struct cal_fmt *fmt;
> > +	unsigned int k;
> > +
> > +	for (k = 0; k < ctx->num_active_fmt; k++) {
> > +		fmt = ctx->active_fmt[k];
> > +		if (fmt->fourcc == pixelformat)
> > +			return fmt;
> > +	}
> > +
> > +	return NULL;
> > +}
> > +
> > +static const struct cal_fmt *find_format_by_code(struct cal_ctx *ctx,
> > +						 u32 code)
> > +{
> > +	const struct cal_fmt *fmt;
> > +	unsigned int k;
> > +
> > +	for (k = 0; k < ctx->num_active_fmt; k++) {
> > +		fmt = ctx->active_fmt[k];
> > +		if (fmt->code == code)
> > +			return fmt;
> > +	}
> > +
> > +	return NULL;
> > +}
> > +
> >  static int cal_querycap(struct file *file, void *priv,
> >  			struct v4l2_capability *cap)
> >  {
> > @@ -1566,9 +1583,46 @@ static int cal_enum_frameintervals(struct file *file, void *priv,
> >  	return 0;
> >  }
> >  
> > -/*
> > - * Videobuf operations
> > +static const struct v4l2_file_operations cal_fops = {
> > +	.owner		= THIS_MODULE,
> > +	.open           = v4l2_fh_open,
> > +	.release        = vb2_fop_release,
> > +	.read           = vb2_fop_read,
> > +	.poll		= vb2_fop_poll,
> > +	.unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */
> > +	.mmap           = vb2_fop_mmap,
> > +};
> > +
> > +static const struct v4l2_ioctl_ops cal_ioctl_ops = {
> > +	.vidioc_querycap      = cal_querycap,
> > +	.vidioc_enum_fmt_vid_cap  = cal_enum_fmt_vid_cap,
> > +	.vidioc_g_fmt_vid_cap     = cal_g_fmt_vid_cap,
> > +	.vidioc_try_fmt_vid_cap   = cal_try_fmt_vid_cap,
> > +	.vidioc_s_fmt_vid_cap     = cal_s_fmt_vid_cap,
> > +	.vidioc_enum_framesizes   = cal_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_enum_input    = cal_enum_input,
> > +	.vidioc_g_input       = cal_g_input,
> > +	.vidioc_s_input       = cal_s_input,
> > +	.vidioc_enum_frameintervals = cal_enum_frameintervals,
> > +	.vidioc_streamon      = vb2_ioctl_streamon,
> > +	.vidioc_streamoff     = vb2_ioctl_streamoff,
> > +	.vidioc_log_status    = v4l2_ctrl_log_status,
> > +	.vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
> > +	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
> > +};
> > +
> > +/* ------------------------------------------------------------------
> > + *	videobuf2 Operations
> > + * ------------------------------------------------------------------
> >   */
> > +
> >  static int cal_queue_setup(struct vb2_queue *vq,
> >  			   unsigned int *nbuffers, unsigned int *nplanes,
> >  			   unsigned int sizes[], struct device *alloc_devs[])
> > @@ -1772,40 +1826,10 @@ static const struct vb2_ops cal_video_qops = {
> >  	.wait_finish		= vb2_ops_wait_finish,
> >  };
> >  
> > -static const struct v4l2_file_operations cal_fops = {
> > -	.owner		= THIS_MODULE,
> > -	.open           = v4l2_fh_open,
> > -	.release        = vb2_fop_release,
> > -	.read           = vb2_fop_read,
> > -	.poll		= vb2_fop_poll,
> > -	.unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */
> > -	.mmap           = vb2_fop_mmap,
> > -};
> > -
> > -static const struct v4l2_ioctl_ops cal_ioctl_ops = {
> > -	.vidioc_querycap      = cal_querycap,
> > -	.vidioc_enum_fmt_vid_cap  = cal_enum_fmt_vid_cap,
> > -	.vidioc_g_fmt_vid_cap     = cal_g_fmt_vid_cap,
> > -	.vidioc_try_fmt_vid_cap   = cal_try_fmt_vid_cap,
> > -	.vidioc_s_fmt_vid_cap     = cal_s_fmt_vid_cap,
> > -	.vidioc_enum_framesizes   = cal_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_enum_input    = cal_enum_input,
> > -	.vidioc_g_input       = cal_g_input,
> > -	.vidioc_s_input       = cal_s_input,
> > -	.vidioc_enum_frameintervals = cal_enum_frameintervals,
> > -	.vidioc_streamon      = vb2_ioctl_streamon,
> > -	.vidioc_streamoff     = vb2_ioctl_streamoff,
> > -	.vidioc_log_status    = v4l2_ctrl_log_status,
> > -	.vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
> > -	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
> > -};
> > +/* ------------------------------------------------------------------
> > + *	Initialization and module stuff
> > + * ------------------------------------------------------------------
> > + */
> >  
> >  static const struct video_device cal_videodev = {
> >  	.name		= CAL_MODULE_NAME,
> > @@ -1817,11 +1841,6 @@ static const struct video_device cal_videodev = {
> >  			  V4L2_CAP_READWRITE,
> >  };
> >  
> > -/* -----------------------------------------------------------------
> > - *	Initialization and module stuff
> > - * ------------------------------------------------------------------
> > - */
> > -
> >  static int cal_complete_ctx(struct cal_ctx *ctx)
> >  {
> >  	struct video_device *vfd;
> > @@ -2242,6 +2261,11 @@ static void cal_get_hwinfo(struct cal_dev *cal)
> >  		hwinfo);
> >  }
> >  
> 
> 
> Overall, the reorganisation is certainly helpful.
> 
> > +static u32 cal_data_get_num_csi2_phy(struct cal_dev *cal)
> > +{
> > +	return cal->data->num_csi2_phy;
> > +}
> 
> However, this function (which is possibly a bit overkill on it's own
> anyway) could be moved much higher in the module, so that /all/
> references to the num_csi2_phy variable are accessed through it.
> 
> Otherwise, the code is inconsistent with other parts of the driver
> directly accessing this value even with an accessor.
> 
> We could remove the accessor... or - apply the patch "media: ti-vpe:
> cal: Use cal_data_get_num_csi2_phy() consistently" (which will follow
> next) on top.

I think I'd rather remove the accessors, this function provides little
value.

> Otherwise,
> 
> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
> 
> > +
> >  static int cal_probe(struct platform_device *pdev)
> >  {
> >  	struct cal_dev *cal;

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH v1 036/107] media: ti-vpe: cal: Reorganize remaining code in sections
  2020-06-17 10:51     ` [PATCH v1 036/107] media: ti-vpe: cal: Reorganize remaining code in sections Laurent Pinchart
@ 2020-06-17 10:54       ` Kieran Bingham
  2020-06-17 11:01         ` Kieran Bingham
  0 siblings, 1 reply; 150+ messages in thread
From: Kieran Bingham @ 2020-06-17 10:54 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Tomi Valkeinen, Benoit Parrot

Hi Laurent,

On 17/06/2020 11:51, Laurent Pinchart wrote:
> On Wed, Jun 17, 2020 at 11:00:31AM +0100, Kieran Bingham wrote:
>> On 15/06/2020 00:58, Laurent Pinchart wrote:
>>> Increase readability by reorganizing the remaining code in sections. No
>>> functional change is included.
>>>
>>> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
>>> ---
>>>  drivers/media/platform/ti-vpe/cal.c | 350 +++++++++++++++-------------
>>>  1 file changed, 187 insertions(+), 163 deletions(-)
>>>
>>> diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
>>> index 176f616033a1..6f33853ecdb2 100644
>>> --- a/drivers/media/platform/ti-vpe/cal.c
>>> +++ b/drivers/media/platform/ti-vpe/cal.c
>>> @@ -37,9 +37,6 @@
>>>  
>>>  #define CAL_MODULE_NAME "cal"
>>>  
>>> -#define MAX_WIDTH_BYTES (8192 * 8)
>>> -#define MAX_HEIGHT_LINES 16383
>>> -
>>>  MODULE_DESCRIPTION("TI CAL driver");
>>>  MODULE_AUTHOR("Benoit Parrot, <bparrot@ti.com>");
>>>  MODULE_LICENSE("GPL v2");
>>> @@ -79,11 +76,11 @@ MODULE_PARM_DESC(debug, "activates debug info");
>>>  
>>>  #define CAL_NUM_CONTEXT 2
>>>  
>>> -#define reg_read(dev, offset) ioread32(dev->base + offset)
>>> -#define reg_write(dev, offset, val) iowrite32(val, dev->base + offset)
>>> +#define MAX_WIDTH_BYTES (8192 * 8)
>>> +#define MAX_HEIGHT_LINES 16383
>>>  
>>>  /* ------------------------------------------------------------------
>>> - *	Basic structures
>>> + *	Format Handling
>>>   * ------------------------------------------------------------------
>>>   */
>>>  
>>> @@ -204,6 +201,11 @@ static char *fourcc_to_str(u32 fmt)
>>>  	return code;
>>>  }
>>>  
>>> +/* ------------------------------------------------------------------
>>> + *	Driver Structures
>>> + * ------------------------------------------------------------------
>>> + */
>>> +
>>>  /* buffer for one video frame */
>>>  struct cal_buffer {
>>>  	/* common v4l buffer stuff -- must be first */
>>> @@ -239,80 +241,6 @@ struct cal_data {
>>>  	unsigned int flags;
>>>  };
>>>  
>>> -static const struct cal_camerarx_data dra72x_cal_camerarx[] = {
>>> -	{
>>> -		.fields = {
>>> -			[F_CTRLCLKEN] = { 10, 10 },
>>> -			[F_CAMMODE] = { 11, 12 },
>>> -			[F_LANEENABLE] = { 13, 16 },
>>> -			[F_CSI_MODE] = { 17, 17 },
>>> -		},
>>> -		.num_lanes = 4,
>>> -	},
>>> -	{
>>> -		.fields = {
>>> -			[F_CTRLCLKEN] = { 0, 0 },
>>> -			[F_CAMMODE] = { 1, 2 },
>>> -			[F_LANEENABLE] = { 3, 4 },
>>> -			[F_CSI_MODE] = { 5, 5 },
>>> -		},
>>> -		.num_lanes = 2,
>>> -	},
>>> -};
>>> -
>>> -static const struct cal_data dra72x_cal_data = {
>>> -	.camerarx = dra72x_cal_camerarx,
>>> -	.num_csi2_phy = ARRAY_SIZE(dra72x_cal_camerarx),
>>> -};
>>> -
>>> -static const struct cal_data dra72x_es1_cal_data = {
>>> -	.camerarx = dra72x_cal_camerarx,
>>> -	.num_csi2_phy = ARRAY_SIZE(dra72x_cal_camerarx),
>>> -	.flags = DRA72_CAL_PRE_ES2_LDO_DISABLE,
>>> -};
>>> -
>>> -static const struct cal_camerarx_data dra76x_cal_csi_phy[] = {
>>> -	{
>>> -		.fields = {
>>> -			[F_CTRLCLKEN] = { 8, 8 },
>>> -			[F_CAMMODE] = { 9, 10 },
>>> -			[F_CSI_MODE] = { 11, 11 },
>>> -			[F_LANEENABLE] = { 27, 31 },
>>> -		},
>>> -		.num_lanes = 5,
>>> -	},
>>> -	{
>>> -		.fields = {
>>> -			[F_CTRLCLKEN] = { 0, 0 },
>>> -			[F_CAMMODE] = { 1, 2 },
>>> -			[F_CSI_MODE] = { 3, 3 },
>>> -			[F_LANEENABLE] = { 24, 26 },
>>> -		},
>>> -		.num_lanes = 3,
>>> -	},
>>> -};
>>> -
>>> -static const struct cal_data dra76x_cal_data = {
>>> -	.camerarx = dra76x_cal_csi_phy,
>>> -	.num_csi2_phy = ARRAY_SIZE(dra76x_cal_csi_phy),
>>> -};
>>> -
>>> -static const struct cal_camerarx_data am654_cal_csi_phy[] = {
>>> -	{
>>> -		.fields = {
>>> -			[F_CTRLCLKEN] = { 15, 15 },
>>> -			[F_CAMMODE] = { 24, 25 },
>>> -			[F_LANEENABLE] = { 0, 4 },
>>> -		},
>>> -		.num_lanes = 5,
>>> -	},
>>> -};
>>> -
>>> -static const struct cal_data am654_cal_data = {
>>> -	.camerarx = am654_cal_csi_phy,
>>> -	.num_csi2_phy = ARRAY_SIZE(am654_cal_csi_phy),
>>> -};
>>> -
>>>  /*
>>>   * The Camera Adaptation Layer (CAL) module is paired with one or more complex
>>>   * I/O PHYs (CAMERARX). It contains multiple instances of CSI-2, processing and
>>> @@ -408,6 +336,98 @@ struct cal_ctx {
>>>  	bool dma_act;
>>>  };
>>>  
>>> +static inline struct cal_ctx *notifier_to_ctx(struct v4l2_async_notifier *n)
>>> +{
>>> +	return container_of(n, struct cal_ctx, notifier);
>>> +}
>>> +
>>> +/* ------------------------------------------------------------------
>>> + *	Platform Data
>>> + * ------------------------------------------------------------------
>>> + */
>>> +
>>> +static const struct cal_camerarx_data dra72x_cal_camerarx[] = {
>>> +	{
>>> +		.fields = {
>>> +			[F_CTRLCLKEN] = { 10, 10 },
>>> +			[F_CAMMODE] = { 11, 12 },
>>> +			[F_LANEENABLE] = { 13, 16 },
>>> +			[F_CSI_MODE] = { 17, 17 },
>>> +		},
>>> +		.num_lanes = 4,
>>> +	},
>>> +	{
>>> +		.fields = {
>>> +			[F_CTRLCLKEN] = { 0, 0 },
>>> +			[F_CAMMODE] = { 1, 2 },
>>> +			[F_LANEENABLE] = { 3, 4 },
>>> +			[F_CSI_MODE] = { 5, 5 },
>>> +		},
>>> +		.num_lanes = 2,
>>> +	},
>>> +};
>>> +
>>> +static const struct cal_data dra72x_cal_data = {
>>> +	.camerarx = dra72x_cal_camerarx,
>>> +	.num_csi2_phy = ARRAY_SIZE(dra72x_cal_camerarx),
>>> +};
>>> +
>>> +static const struct cal_data dra72x_es1_cal_data = {
>>> +	.camerarx = dra72x_cal_camerarx,
>>> +	.num_csi2_phy = ARRAY_SIZE(dra72x_cal_camerarx),
>>> +	.flags = DRA72_CAL_PRE_ES2_LDO_DISABLE,
>>> +};
>>> +
>>> +static const struct cal_camerarx_data dra76x_cal_csi_phy[] = {
>>> +	{
>>> +		.fields = {
>>> +			[F_CTRLCLKEN] = { 8, 8 },
>>> +			[F_CAMMODE] = { 9, 10 },
>>> +			[F_CSI_MODE] = { 11, 11 },
>>> +			[F_LANEENABLE] = { 27, 31 },
>>> +		},
>>> +		.num_lanes = 5,
>>> +	},
>>> +	{
>>> +		.fields = {
>>> +			[F_CTRLCLKEN] = { 0, 0 },
>>> +			[F_CAMMODE] = { 1, 2 },
>>> +			[F_CSI_MODE] = { 3, 3 },
>>> +			[F_LANEENABLE] = { 24, 26 },
>>> +		},
>>> +		.num_lanes = 3,
>>> +	},
>>> +};
>>> +
>>> +static const struct cal_data dra76x_cal_data = {
>>> +	.camerarx = dra76x_cal_csi_phy,
>>> +	.num_csi2_phy = ARRAY_SIZE(dra76x_cal_csi_phy),
>>> +};
>>> +
>>> +static const struct cal_camerarx_data am654_cal_csi_phy[] = {
>>> +	{
>>> +		.fields = {
>>> +			[F_CTRLCLKEN] = { 15, 15 },
>>> +			[F_CAMMODE] = { 24, 25 },
>>> +			[F_LANEENABLE] = { 0, 4 },
>>> +		},
>>> +		.num_lanes = 5,
>>> +	},
>>> +};
>>> +
>>> +static const struct cal_data am654_cal_data = {
>>> +	.camerarx = am654_cal_csi_phy,
>>> +	.num_csi2_phy = ARRAY_SIZE(am654_cal_csi_phy),
>>> +};
>>> +
>>> +/* ------------------------------------------------------------------
>>> + *	I/O Register Accessors
>>> + * ------------------------------------------------------------------
>>> + */
>>> +
>>> +#define reg_read(dev, offset) ioread32(dev->base + offset)
>>> +#define reg_write(dev, offset, val) iowrite32(val, dev->base + offset)
>>> +
>>>  static inline u32 reg_read_field(struct cal_dev *cal, u32 offset, u32 mask)
>>>  {
>>>  	return FIELD_GET(mask, reg_read(cal, offset));
>>> @@ -423,41 +443,6 @@ static inline void reg_write_field(struct cal_dev *cal, u32 offset, u32 value,
>>>  	reg_write(cal, offset, val);
>>>  }
>>>  
>>> -static const struct cal_fmt *find_format_by_pix(struct cal_ctx *ctx,
>>> -						u32 pixelformat)
>>> -{
>>> -	const struct cal_fmt *fmt;
>>> -	unsigned int k;
>>> -
>>> -	for (k = 0; k < ctx->num_active_fmt; k++) {
>>> -		fmt = ctx->active_fmt[k];
>>> -		if (fmt->fourcc == pixelformat)
>>> -			return fmt;
>>> -	}
>>> -
>>> -	return NULL;
>>> -}
>>> -
>>> -static const struct cal_fmt *find_format_by_code(struct cal_ctx *ctx,
>>> -						 u32 code)
>>> -{
>>> -	const struct cal_fmt *fmt;
>>> -	unsigned int k;
>>> -
>>> -	for (k = 0; k < ctx->num_active_fmt; k++) {
>>> -		fmt = ctx->active_fmt[k];
>>> -		if (fmt->code == code)
>>> -			return fmt;
>>> -	}
>>> -
>>> -	return NULL;
>>> -}
>>> -
>>> -static inline struct cal_ctx *notifier_to_ctx(struct v4l2_async_notifier *n)
>>> -{
>>> -	return container_of(n, struct cal_ctx, notifier);
>>> -}
>>> -
>>>  static inline void set_field(u32 *valp, u32 field, u32 mask)
>>>  {
>>>  	u32 val = *valp;
>>> @@ -493,11 +478,6 @@ static void cal_quickdump_regs(struct cal_dev *cal)
>>>  	}
>>>  }
>>>  
>>> -static u32 cal_data_get_num_csi2_phy(struct cal_dev *cal)
>>> -{
>>> -	return cal->data->num_csi2_phy;
>>> -}
>>> -
>>>  /* ------------------------------------------------------------------
>>>   *	CAMERARX Management
>>>   * ------------------------------------------------------------------
>>> @@ -1152,6 +1132,11 @@ static void cal_ctx_wr_dma_addr(struct cal_ctx *ctx, unsigned int dmaaddr)
>>>  	reg_write(ctx->cal, CAL_WR_DMA_ADDR(ctx->csi2_port), dmaaddr);
>>>  }
>>>  
>>> +/* ------------------------------------------------------------------
>>> + *	IRQ Handling
>>> + * ------------------------------------------------------------------
>>> + */
>>> +
>>>  static inline void cal_schedule_next_buffer(struct cal_ctx *ctx)
>>>  {
>>>  	struct cal_dmaqueue *dma_q = &ctx->vidq;
>>> @@ -1255,9 +1240,41 @@ static irqreturn_t cal_irq(int irq_cal, void *data)
>>>  	return IRQ_HANDLED;
>>>  }
>>>  
>>> -/*
>>> - * video ioctls
>>> +/* ------------------------------------------------------------------
>>> + *	V4L2 Video IOCTLs
>>> + * ------------------------------------------------------------------
>>>   */
>>> +
>>> +static const struct cal_fmt *find_format_by_pix(struct cal_ctx *ctx,
>>> +						u32 pixelformat)
>>> +{
>>> +	const struct cal_fmt *fmt;
>>> +	unsigned int k;
>>> +
>>> +	for (k = 0; k < ctx->num_active_fmt; k++) {
>>> +		fmt = ctx->active_fmt[k];
>>> +		if (fmt->fourcc == pixelformat)
>>> +			return fmt;
>>> +	}
>>> +
>>> +	return NULL;
>>> +}
>>> +
>>> +static const struct cal_fmt *find_format_by_code(struct cal_ctx *ctx,
>>> +						 u32 code)
>>> +{
>>> +	const struct cal_fmt *fmt;
>>> +	unsigned int k;
>>> +
>>> +	for (k = 0; k < ctx->num_active_fmt; k++) {
>>> +		fmt = ctx->active_fmt[k];
>>> +		if (fmt->code == code)
>>> +			return fmt;
>>> +	}
>>> +
>>> +	return NULL;
>>> +}
>>> +
>>>  static int cal_querycap(struct file *file, void *priv,
>>>  			struct v4l2_capability *cap)
>>>  {
>>> @@ -1566,9 +1583,46 @@ static int cal_enum_frameintervals(struct file *file, void *priv,
>>>  	return 0;
>>>  }
>>>  
>>> -/*
>>> - * Videobuf operations
>>> +static const struct v4l2_file_operations cal_fops = {
>>> +	.owner		= THIS_MODULE,
>>> +	.open           = v4l2_fh_open,
>>> +	.release        = vb2_fop_release,
>>> +	.read           = vb2_fop_read,
>>> +	.poll		= vb2_fop_poll,
>>> +	.unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */
>>> +	.mmap           = vb2_fop_mmap,
>>> +};
>>> +
>>> +static const struct v4l2_ioctl_ops cal_ioctl_ops = {
>>> +	.vidioc_querycap      = cal_querycap,
>>> +	.vidioc_enum_fmt_vid_cap  = cal_enum_fmt_vid_cap,
>>> +	.vidioc_g_fmt_vid_cap     = cal_g_fmt_vid_cap,
>>> +	.vidioc_try_fmt_vid_cap   = cal_try_fmt_vid_cap,
>>> +	.vidioc_s_fmt_vid_cap     = cal_s_fmt_vid_cap,
>>> +	.vidioc_enum_framesizes   = cal_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_enum_input    = cal_enum_input,
>>> +	.vidioc_g_input       = cal_g_input,
>>> +	.vidioc_s_input       = cal_s_input,
>>> +	.vidioc_enum_frameintervals = cal_enum_frameintervals,
>>> +	.vidioc_streamon      = vb2_ioctl_streamon,
>>> +	.vidioc_streamoff     = vb2_ioctl_streamoff,
>>> +	.vidioc_log_status    = v4l2_ctrl_log_status,
>>> +	.vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
>>> +	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
>>> +};
>>> +
>>> +/* ------------------------------------------------------------------
>>> + *	videobuf2 Operations
>>> + * ------------------------------------------------------------------
>>>   */
>>> +
>>>  static int cal_queue_setup(struct vb2_queue *vq,
>>>  			   unsigned int *nbuffers, unsigned int *nplanes,
>>>  			   unsigned int sizes[], struct device *alloc_devs[])
>>> @@ -1772,40 +1826,10 @@ static const struct vb2_ops cal_video_qops = {
>>>  	.wait_finish		= vb2_ops_wait_finish,
>>>  };
>>>  
>>> -static const struct v4l2_file_operations cal_fops = {
>>> -	.owner		= THIS_MODULE,
>>> -	.open           = v4l2_fh_open,
>>> -	.release        = vb2_fop_release,
>>> -	.read           = vb2_fop_read,
>>> -	.poll		= vb2_fop_poll,
>>> -	.unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */
>>> -	.mmap           = vb2_fop_mmap,
>>> -};
>>> -
>>> -static const struct v4l2_ioctl_ops cal_ioctl_ops = {
>>> -	.vidioc_querycap      = cal_querycap,
>>> -	.vidioc_enum_fmt_vid_cap  = cal_enum_fmt_vid_cap,
>>> -	.vidioc_g_fmt_vid_cap     = cal_g_fmt_vid_cap,
>>> -	.vidioc_try_fmt_vid_cap   = cal_try_fmt_vid_cap,
>>> -	.vidioc_s_fmt_vid_cap     = cal_s_fmt_vid_cap,
>>> -	.vidioc_enum_framesizes   = cal_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_enum_input    = cal_enum_input,
>>> -	.vidioc_g_input       = cal_g_input,
>>> -	.vidioc_s_input       = cal_s_input,
>>> -	.vidioc_enum_frameintervals = cal_enum_frameintervals,
>>> -	.vidioc_streamon      = vb2_ioctl_streamon,
>>> -	.vidioc_streamoff     = vb2_ioctl_streamoff,
>>> -	.vidioc_log_status    = v4l2_ctrl_log_status,
>>> -	.vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
>>> -	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
>>> -};
>>> +/* ------------------------------------------------------------------
>>> + *	Initialization and module stuff
>>> + * ------------------------------------------------------------------
>>> + */
>>>  
>>>  static const struct video_device cal_videodev = {
>>>  	.name		= CAL_MODULE_NAME,
>>> @@ -1817,11 +1841,6 @@ static const struct video_device cal_videodev = {
>>>  			  V4L2_CAP_READWRITE,
>>>  };
>>>  
>>> -/* -----------------------------------------------------------------
>>> - *	Initialization and module stuff
>>> - * ------------------------------------------------------------------
>>> - */
>>> -
>>>  static int cal_complete_ctx(struct cal_ctx *ctx)
>>>  {
>>>  	struct video_device *vfd;
>>> @@ -2242,6 +2261,11 @@ static void cal_get_hwinfo(struct cal_dev *cal)
>>>  		hwinfo);
>>>  }
>>>  
>>
>>
>> Overall, the reorganisation is certainly helpful.
>>
>>> +static u32 cal_data_get_num_csi2_phy(struct cal_dev *cal)
>>> +{
>>> +	return cal->data->num_csi2_phy;
>>> +}
>>
>> However, this function (which is possibly a bit overkill on it's own
>> anyway) could be moved much higher in the module, so that /all/
>> references to the num_csi2_phy variable are accessed through it.
>>
>> Otherwise, the code is inconsistent with other parts of the driver
>> directly accessing this value even with an accessor.
>>
>> We could remove the accessor... or - apply the patch "media: ti-vpe:
>> cal: Use cal_data_get_num_csi2_phy() consistently" (which will follow
>> next) on top.
> 
> I think I'd rather remove the accessors, this function provides little
> value.

It had some value in giving me a clean place to override having only a
single phy, but that's not a reason to keep it (just helpful while
debugging).

I'm fine dropping the accessor, and open-coding the usage too.



> 
>> Otherwise,
>>
>> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
>>
>>> +
>>>  static int cal_probe(struct platform_device *pdev)
>>>  {
>>>  	struct cal_dev *cal;
> 

-- 
Regards
--
Kieran

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

* Re: [PATCH v1 036/107] media: ti-vpe: cal: Reorganize remaining code in sections
  2020-06-17 10:54       ` Kieran Bingham
@ 2020-06-17 11:01         ` Kieran Bingham
  2020-06-17 11:04           ` Laurent Pinchart
  0 siblings, 1 reply; 150+ messages in thread
From: Kieran Bingham @ 2020-06-17 11:01 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Tomi Valkeinen, Benoit Parrot

Hi Laurent,

On 17/06/2020 11:54, Kieran Bingham wrote:
> Hi Laurent,
> 
> On 17/06/2020 11:51, Laurent Pinchart wrote:
>> On Wed, Jun 17, 2020 at 11:00:31AM +0100, Kieran Bingham wrote:
>>> On 15/06/2020 00:58, Laurent Pinchart wrote:
>>>> Increase readability by reorganizing the remaining code in sections. No
>>>> functional change is included.
>>>>
>>>> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
>>>> ---
>>>>  drivers/media/platform/ti-vpe/cal.c | 350 +++++++++++++++-------------
>>>>  1 file changed, 187 insertions(+), 163 deletions(-)
>>>>
>>>> diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
>>>> index 176f616033a1..6f33853ecdb2 100644
>>>> --- a/drivers/media/platform/ti-vpe/cal.c
>>>> +++ b/drivers/media/platform/ti-vpe/cal.c
>>>> @@ -37,9 +37,6 @@
>>>>  
>>>>  #define CAL_MODULE_NAME "cal"
>>>>  
>>>> -#define MAX_WIDTH_BYTES (8192 * 8)
>>>> -#define MAX_HEIGHT_LINES 16383
>>>> -
>>>>  MODULE_DESCRIPTION("TI CAL driver");
>>>>  MODULE_AUTHOR("Benoit Parrot, <bparrot@ti.com>");
>>>>  MODULE_LICENSE("GPL v2");
>>>> @@ -79,11 +76,11 @@ MODULE_PARM_DESC(debug, "activates debug info");
>>>>  
>>>>  #define CAL_NUM_CONTEXT 2
>>>>  
>>>> -#define reg_read(dev, offset) ioread32(dev->base + offset)
>>>> -#define reg_write(dev, offset, val) iowrite32(val, dev->base + offset)
>>>> +#define MAX_WIDTH_BYTES (8192 * 8)
>>>> +#define MAX_HEIGHT_LINES 16383
>>>>  
>>>>  /* ------------------------------------------------------------------
>>>> - *	Basic structures
>>>> + *	Format Handling
>>>>   * ------------------------------------------------------------------
>>>>   */
>>>>  
>>>> @@ -204,6 +201,11 @@ static char *fourcc_to_str(u32 fmt)
>>>>  	return code;
>>>>  }
>>>>  
>>>> +/* ------------------------------------------------------------------
>>>> + *	Driver Structures
>>>> + * ------------------------------------------------------------------
>>>> + */
>>>> +
>>>>  /* buffer for one video frame */
>>>>  struct cal_buffer {
>>>>  	/* common v4l buffer stuff -- must be first */
>>>> @@ -239,80 +241,6 @@ struct cal_data {
>>>>  	unsigned int flags;
>>>>  };
>>>>  
>>>> -static const struct cal_camerarx_data dra72x_cal_camerarx[] = {
>>>> -	{
>>>> -		.fields = {
>>>> -			[F_CTRLCLKEN] = { 10, 10 },
>>>> -			[F_CAMMODE] = { 11, 12 },
>>>> -			[F_LANEENABLE] = { 13, 16 },
>>>> -			[F_CSI_MODE] = { 17, 17 },
>>>> -		},
>>>> -		.num_lanes = 4,
>>>> -	},
>>>> -	{
>>>> -		.fields = {
>>>> -			[F_CTRLCLKEN] = { 0, 0 },
>>>> -			[F_CAMMODE] = { 1, 2 },
>>>> -			[F_LANEENABLE] = { 3, 4 },
>>>> -			[F_CSI_MODE] = { 5, 5 },
>>>> -		},
>>>> -		.num_lanes = 2,
>>>> -	},
>>>> -};
>>>> -
>>>> -static const struct cal_data dra72x_cal_data = {
>>>> -	.camerarx = dra72x_cal_camerarx,
>>>> -	.num_csi2_phy = ARRAY_SIZE(dra72x_cal_camerarx),
>>>> -};
>>>> -
>>>> -static const struct cal_data dra72x_es1_cal_data = {
>>>> -	.camerarx = dra72x_cal_camerarx,
>>>> -	.num_csi2_phy = ARRAY_SIZE(dra72x_cal_camerarx),
>>>> -	.flags = DRA72_CAL_PRE_ES2_LDO_DISABLE,
>>>> -};
>>>> -
>>>> -static const struct cal_camerarx_data dra76x_cal_csi_phy[] = {
>>>> -	{
>>>> -		.fields = {
>>>> -			[F_CTRLCLKEN] = { 8, 8 },
>>>> -			[F_CAMMODE] = { 9, 10 },
>>>> -			[F_CSI_MODE] = { 11, 11 },
>>>> -			[F_LANEENABLE] = { 27, 31 },
>>>> -		},
>>>> -		.num_lanes = 5,
>>>> -	},
>>>> -	{
>>>> -		.fields = {
>>>> -			[F_CTRLCLKEN] = { 0, 0 },
>>>> -			[F_CAMMODE] = { 1, 2 },
>>>> -			[F_CSI_MODE] = { 3, 3 },
>>>> -			[F_LANEENABLE] = { 24, 26 },
>>>> -		},
>>>> -		.num_lanes = 3,
>>>> -	},
>>>> -};
>>>> -
>>>> -static const struct cal_data dra76x_cal_data = {
>>>> -	.camerarx = dra76x_cal_csi_phy,
>>>> -	.num_csi2_phy = ARRAY_SIZE(dra76x_cal_csi_phy),
>>>> -};
>>>> -
>>>> -static const struct cal_camerarx_data am654_cal_csi_phy[] = {
>>>> -	{
>>>> -		.fields = {
>>>> -			[F_CTRLCLKEN] = { 15, 15 },
>>>> -			[F_CAMMODE] = { 24, 25 },
>>>> -			[F_LANEENABLE] = { 0, 4 },
>>>> -		},
>>>> -		.num_lanes = 5,
>>>> -	},
>>>> -};
>>>> -
>>>> -static const struct cal_data am654_cal_data = {
>>>> -	.camerarx = am654_cal_csi_phy,
>>>> -	.num_csi2_phy = ARRAY_SIZE(am654_cal_csi_phy),
>>>> -};
>>>> -
>>>>  /*
>>>>   * The Camera Adaptation Layer (CAL) module is paired with one or more complex
>>>>   * I/O PHYs (CAMERARX). It contains multiple instances of CSI-2, processing and
>>>> @@ -408,6 +336,98 @@ struct cal_ctx {
>>>>  	bool dma_act;
>>>>  };
>>>>  
>>>> +static inline struct cal_ctx *notifier_to_ctx(struct v4l2_async_notifier *n)
>>>> +{
>>>> +	return container_of(n, struct cal_ctx, notifier);
>>>> +}
>>>> +
>>>> +/* ------------------------------------------------------------------
>>>> + *	Platform Data
>>>> + * ------------------------------------------------------------------
>>>> + */
>>>> +
>>>> +static const struct cal_camerarx_data dra72x_cal_camerarx[] = {
>>>> +	{
>>>> +		.fields = {
>>>> +			[F_CTRLCLKEN] = { 10, 10 },
>>>> +			[F_CAMMODE] = { 11, 12 },
>>>> +			[F_LANEENABLE] = { 13, 16 },
>>>> +			[F_CSI_MODE] = { 17, 17 },
>>>> +		},
>>>> +		.num_lanes = 4,
>>>> +	},
>>>> +	{
>>>> +		.fields = {
>>>> +			[F_CTRLCLKEN] = { 0, 0 },
>>>> +			[F_CAMMODE] = { 1, 2 },
>>>> +			[F_LANEENABLE] = { 3, 4 },
>>>> +			[F_CSI_MODE] = { 5, 5 },
>>>> +		},
>>>> +		.num_lanes = 2,
>>>> +	},
>>>> +};
>>>> +
>>>> +static const struct cal_data dra72x_cal_data = {
>>>> +	.camerarx = dra72x_cal_camerarx,
>>>> +	.num_csi2_phy = ARRAY_SIZE(dra72x_cal_camerarx),
>>>> +};
>>>> +
>>>> +static const struct cal_data dra72x_es1_cal_data = {
>>>> +	.camerarx = dra72x_cal_camerarx,
>>>> +	.num_csi2_phy = ARRAY_SIZE(dra72x_cal_camerarx),
>>>> +	.flags = DRA72_CAL_PRE_ES2_LDO_DISABLE,
>>>> +};
>>>> +
>>>> +static const struct cal_camerarx_data dra76x_cal_csi_phy[] = {
>>>> +	{
>>>> +		.fields = {
>>>> +			[F_CTRLCLKEN] = { 8, 8 },
>>>> +			[F_CAMMODE] = { 9, 10 },
>>>> +			[F_CSI_MODE] = { 11, 11 },
>>>> +			[F_LANEENABLE] = { 27, 31 },
>>>> +		},
>>>> +		.num_lanes = 5,
>>>> +	},
>>>> +	{
>>>> +		.fields = {
>>>> +			[F_CTRLCLKEN] = { 0, 0 },
>>>> +			[F_CAMMODE] = { 1, 2 },
>>>> +			[F_CSI_MODE] = { 3, 3 },
>>>> +			[F_LANEENABLE] = { 24, 26 },
>>>> +		},
>>>> +		.num_lanes = 3,
>>>> +	},
>>>> +};
>>>> +
>>>> +static const struct cal_data dra76x_cal_data = {
>>>> +	.camerarx = dra76x_cal_csi_phy,
>>>> +	.num_csi2_phy = ARRAY_SIZE(dra76x_cal_csi_phy),
>>>> +};
>>>> +
>>>> +static const struct cal_camerarx_data am654_cal_csi_phy[] = {
>>>> +	{
>>>> +		.fields = {
>>>> +			[F_CTRLCLKEN] = { 15, 15 },
>>>> +			[F_CAMMODE] = { 24, 25 },
>>>> +			[F_LANEENABLE] = { 0, 4 },
>>>> +		},
>>>> +		.num_lanes = 5,
>>>> +	},
>>>> +};
>>>> +
>>>> +static const struct cal_data am654_cal_data = {
>>>> +	.camerarx = am654_cal_csi_phy,
>>>> +	.num_csi2_phy = ARRAY_SIZE(am654_cal_csi_phy),
>>>> +};
>>>> +
>>>> +/* ------------------------------------------------------------------
>>>> + *	I/O Register Accessors
>>>> + * ------------------------------------------------------------------
>>>> + */
>>>> +
>>>> +#define reg_read(dev, offset) ioread32(dev->base + offset)
>>>> +#define reg_write(dev, offset, val) iowrite32(val, dev->base + offset)
>>>> +
>>>>  static inline u32 reg_read_field(struct cal_dev *cal, u32 offset, u32 mask)
>>>>  {
>>>>  	return FIELD_GET(mask, reg_read(cal, offset));
>>>> @@ -423,41 +443,6 @@ static inline void reg_write_field(struct cal_dev *cal, u32 offset, u32 value,
>>>>  	reg_write(cal, offset, val);
>>>>  }
>>>>  
>>>> -static const struct cal_fmt *find_format_by_pix(struct cal_ctx *ctx,
>>>> -						u32 pixelformat)
>>>> -{
>>>> -	const struct cal_fmt *fmt;
>>>> -	unsigned int k;
>>>> -
>>>> -	for (k = 0; k < ctx->num_active_fmt; k++) {
>>>> -		fmt = ctx->active_fmt[k];
>>>> -		if (fmt->fourcc == pixelformat)
>>>> -			return fmt;
>>>> -	}
>>>> -
>>>> -	return NULL;
>>>> -}
>>>> -
>>>> -static const struct cal_fmt *find_format_by_code(struct cal_ctx *ctx,
>>>> -						 u32 code)
>>>> -{
>>>> -	const struct cal_fmt *fmt;
>>>> -	unsigned int k;
>>>> -
>>>> -	for (k = 0; k < ctx->num_active_fmt; k++) {
>>>> -		fmt = ctx->active_fmt[k];
>>>> -		if (fmt->code == code)
>>>> -			return fmt;
>>>> -	}
>>>> -
>>>> -	return NULL;
>>>> -}
>>>> -
>>>> -static inline struct cal_ctx *notifier_to_ctx(struct v4l2_async_notifier *n)
>>>> -{
>>>> -	return container_of(n, struct cal_ctx, notifier);
>>>> -}
>>>> -
>>>>  static inline void set_field(u32 *valp, u32 field, u32 mask)
>>>>  {
>>>>  	u32 val = *valp;
>>>> @@ -493,11 +478,6 @@ static void cal_quickdump_regs(struct cal_dev *cal)
>>>>  	}
>>>>  }
>>>>  
>>>> -static u32 cal_data_get_num_csi2_phy(struct cal_dev *cal)
>>>> -{
>>>> -	return cal->data->num_csi2_phy;
>>>> -}
>>>> -
>>>>  /* ------------------------------------------------------------------
>>>>   *	CAMERARX Management
>>>>   * ------------------------------------------------------------------
>>>> @@ -1152,6 +1132,11 @@ static void cal_ctx_wr_dma_addr(struct cal_ctx *ctx, unsigned int dmaaddr)
>>>>  	reg_write(ctx->cal, CAL_WR_DMA_ADDR(ctx->csi2_port), dmaaddr);
>>>>  }
>>>>  
>>>> +/* ------------------------------------------------------------------
>>>> + *	IRQ Handling
>>>> + * ------------------------------------------------------------------
>>>> + */
>>>> +
>>>>  static inline void cal_schedule_next_buffer(struct cal_ctx *ctx)
>>>>  {
>>>>  	struct cal_dmaqueue *dma_q = &ctx->vidq;
>>>> @@ -1255,9 +1240,41 @@ static irqreturn_t cal_irq(int irq_cal, void *data)
>>>>  	return IRQ_HANDLED;
>>>>  }
>>>>  
>>>> -/*
>>>> - * video ioctls
>>>> +/* ------------------------------------------------------------------
>>>> + *	V4L2 Video IOCTLs
>>>> + * ------------------------------------------------------------------
>>>>   */
>>>> +
>>>> +static const struct cal_fmt *find_format_by_pix(struct cal_ctx *ctx,
>>>> +						u32 pixelformat)
>>>> +{
>>>> +	const struct cal_fmt *fmt;
>>>> +	unsigned int k;
>>>> +
>>>> +	for (k = 0; k < ctx->num_active_fmt; k++) {
>>>> +		fmt = ctx->active_fmt[k];
>>>> +		if (fmt->fourcc == pixelformat)
>>>> +			return fmt;
>>>> +	}
>>>> +
>>>> +	return NULL;
>>>> +}
>>>> +
>>>> +static const struct cal_fmt *find_format_by_code(struct cal_ctx *ctx,
>>>> +						 u32 code)
>>>> +{
>>>> +	const struct cal_fmt *fmt;
>>>> +	unsigned int k;
>>>> +
>>>> +	for (k = 0; k < ctx->num_active_fmt; k++) {
>>>> +		fmt = ctx->active_fmt[k];
>>>> +		if (fmt->code == code)
>>>> +			return fmt;
>>>> +	}
>>>> +
>>>> +	return NULL;
>>>> +}
>>>> +
>>>>  static int cal_querycap(struct file *file, void *priv,
>>>>  			struct v4l2_capability *cap)
>>>>  {
>>>> @@ -1566,9 +1583,46 @@ static int cal_enum_frameintervals(struct file *file, void *priv,
>>>>  	return 0;
>>>>  }
>>>>  
>>>> -/*
>>>> - * Videobuf operations
>>>> +static const struct v4l2_file_operations cal_fops = {
>>>> +	.owner		= THIS_MODULE,
>>>> +	.open           = v4l2_fh_open,
>>>> +	.release        = vb2_fop_release,
>>>> +	.read           = vb2_fop_read,
>>>> +	.poll		= vb2_fop_poll,
>>>> +	.unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */
>>>> +	.mmap           = vb2_fop_mmap,
>>>> +};
>>>> +
>>>> +static const struct v4l2_ioctl_ops cal_ioctl_ops = {
>>>> +	.vidioc_querycap      = cal_querycap,
>>>> +	.vidioc_enum_fmt_vid_cap  = cal_enum_fmt_vid_cap,
>>>> +	.vidioc_g_fmt_vid_cap     = cal_g_fmt_vid_cap,
>>>> +	.vidioc_try_fmt_vid_cap   = cal_try_fmt_vid_cap,
>>>> +	.vidioc_s_fmt_vid_cap     = cal_s_fmt_vid_cap,
>>>> +	.vidioc_enum_framesizes   = cal_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_enum_input    = cal_enum_input,
>>>> +	.vidioc_g_input       = cal_g_input,
>>>> +	.vidioc_s_input       = cal_s_input,
>>>> +	.vidioc_enum_frameintervals = cal_enum_frameintervals,
>>>> +	.vidioc_streamon      = vb2_ioctl_streamon,
>>>> +	.vidioc_streamoff     = vb2_ioctl_streamoff,
>>>> +	.vidioc_log_status    = v4l2_ctrl_log_status,
>>>> +	.vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
>>>> +	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
>>>> +};
>>>> +
>>>> +/* ------------------------------------------------------------------
>>>> + *	videobuf2 Operations
>>>> + * ------------------------------------------------------------------
>>>>   */
>>>> +
>>>>  static int cal_queue_setup(struct vb2_queue *vq,
>>>>  			   unsigned int *nbuffers, unsigned int *nplanes,
>>>>  			   unsigned int sizes[], struct device *alloc_devs[])
>>>> @@ -1772,40 +1826,10 @@ static const struct vb2_ops cal_video_qops = {
>>>>  	.wait_finish		= vb2_ops_wait_finish,
>>>>  };
>>>>  
>>>> -static const struct v4l2_file_operations cal_fops = {
>>>> -	.owner		= THIS_MODULE,
>>>> -	.open           = v4l2_fh_open,
>>>> -	.release        = vb2_fop_release,
>>>> -	.read           = vb2_fop_read,
>>>> -	.poll		= vb2_fop_poll,
>>>> -	.unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */
>>>> -	.mmap           = vb2_fop_mmap,
>>>> -};
>>>> -
>>>> -static const struct v4l2_ioctl_ops cal_ioctl_ops = {
>>>> -	.vidioc_querycap      = cal_querycap,
>>>> -	.vidioc_enum_fmt_vid_cap  = cal_enum_fmt_vid_cap,
>>>> -	.vidioc_g_fmt_vid_cap     = cal_g_fmt_vid_cap,
>>>> -	.vidioc_try_fmt_vid_cap   = cal_try_fmt_vid_cap,
>>>> -	.vidioc_s_fmt_vid_cap     = cal_s_fmt_vid_cap,
>>>> -	.vidioc_enum_framesizes   = cal_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_enum_input    = cal_enum_input,
>>>> -	.vidioc_g_input       = cal_g_input,
>>>> -	.vidioc_s_input       = cal_s_input,
>>>> -	.vidioc_enum_frameintervals = cal_enum_frameintervals,
>>>> -	.vidioc_streamon      = vb2_ioctl_streamon,
>>>> -	.vidioc_streamoff     = vb2_ioctl_streamoff,
>>>> -	.vidioc_log_status    = v4l2_ctrl_log_status,
>>>> -	.vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
>>>> -	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
>>>> -};
>>>> +/* ------------------------------------------------------------------
>>>> + *	Initialization and module stuff
>>>> + * ------------------------------------------------------------------
>>>> + */
>>>>  
>>>>  static const struct video_device cal_videodev = {
>>>>  	.name		= CAL_MODULE_NAME,
>>>> @@ -1817,11 +1841,6 @@ static const struct video_device cal_videodev = {
>>>>  			  V4L2_CAP_READWRITE,
>>>>  };
>>>>  
>>>> -/* -----------------------------------------------------------------
>>>> - *	Initialization and module stuff
>>>> - * ------------------------------------------------------------------
>>>> - */
>>>> -
>>>>  static int cal_complete_ctx(struct cal_ctx *ctx)
>>>>  {
>>>>  	struct video_device *vfd;
>>>> @@ -2242,6 +2261,11 @@ static void cal_get_hwinfo(struct cal_dev *cal)
>>>>  		hwinfo);
>>>>  }
>>>>  
>>>
>>>
>>> Overall, the reorganisation is certainly helpful.
>>>
>>>> +static u32 cal_data_get_num_csi2_phy(struct cal_dev *cal)
>>>> +{
>>>> +	return cal->data->num_csi2_phy;
>>>> +}
>>>
>>> However, this function (which is possibly a bit overkill on it's own
>>> anyway) could be moved much higher in the module, so that /all/
>>> references to the num_csi2_phy variable are accessed through it.
>>>
>>> Otherwise, the code is inconsistent with other parts of the driver
>>> directly accessing this value even with an accessor.
>>>
>>> We could remove the accessor... or - apply the patch "media: ti-vpe:
>>> cal: Use cal_data_get_num_csi2_phy() consistently" (which will follow
>>> next) on top.
>>
>> I think I'd rather remove the accessors, this function provides little
>> value.
> 
> It had some value in giving me a clean place to override having only a
> single phy, but that's not a reason to keep it (just helpful while
> debugging).
> 
> I'm fine dropping the accessor, and open-coding the usage too.

Actually, further to that - we might want some loop helper here on this
topic anyway, as when a PHY is unused (/unconnected) we need a good way
to make sure we don't process anything on that phy.

I think all of the places where that accessor is used would be key
locations that should also check if the phy is defined too.

But that accessor alone is not enough, there needs to be a check that
the phy was created too. (currently working through that now for better
support on the DRA76-evm which has two phys, and only one is connected
to the OV5640).


--
Kieran

> 
> 
> 
>>
>>> Otherwise,
>>>
>>> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
>>>
>>>> +
>>>>  static int cal_probe(struct platform_device *pdev)
>>>>  {
>>>>  	struct cal_dev *cal;
>>
> 

-- 
Regards
--
Kieran

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

* Re: [PATCH v1 036/107] media: ti-vpe: cal: Reorganize remaining code in sections
  2020-06-17 11:01         ` Kieran Bingham
@ 2020-06-17 11:04           ` Laurent Pinchart
  2020-06-17 11:49             ` Kieran Bingham
  0 siblings, 1 reply; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-17 11:04 UTC (permalink / raw)
  To: Kieran Bingham; +Cc: linux-media, Tomi Valkeinen, Benoit Parrot

Hi Kieran,

On Wed, Jun 17, 2020 at 12:01:39PM +0100, Kieran Bingham wrote:
> On 17/06/2020 11:54, Kieran Bingham wrote:
> > On 17/06/2020 11:51, Laurent Pinchart wrote:
> >> On Wed, Jun 17, 2020 at 11:00:31AM +0100, Kieran Bingham wrote:
> >>> On 15/06/2020 00:58, Laurent Pinchart wrote:
> >>>> Increase readability by reorganizing the remaining code in sections. No
> >>>> functional change is included.
> >>>>
> >>>> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> >>>> ---
> >>>>  drivers/media/platform/ti-vpe/cal.c | 350 +++++++++++++++-------------
> >>>>  1 file changed, 187 insertions(+), 163 deletions(-)
> >>>>
> >>>> diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
> >>>> index 176f616033a1..6f33853ecdb2 100644
> >>>> --- a/drivers/media/platform/ti-vpe/cal.c
> >>>> +++ b/drivers/media/platform/ti-vpe/cal.c
> >>>> @@ -37,9 +37,6 @@
> >>>>  
> >>>>  #define CAL_MODULE_NAME "cal"
> >>>>  
> >>>> -#define MAX_WIDTH_BYTES (8192 * 8)
> >>>> -#define MAX_HEIGHT_LINES 16383
> >>>> -
> >>>>  MODULE_DESCRIPTION("TI CAL driver");
> >>>>  MODULE_AUTHOR("Benoit Parrot, <bparrot@ti.com>");
> >>>>  MODULE_LICENSE("GPL v2");
> >>>> @@ -79,11 +76,11 @@ MODULE_PARM_DESC(debug, "activates debug info");
> >>>>  
> >>>>  #define CAL_NUM_CONTEXT 2
> >>>>  
> >>>> -#define reg_read(dev, offset) ioread32(dev->base + offset)
> >>>> -#define reg_write(dev, offset, val) iowrite32(val, dev->base + offset)
> >>>> +#define MAX_WIDTH_BYTES (8192 * 8)
> >>>> +#define MAX_HEIGHT_LINES 16383
> >>>>  
> >>>>  /* ------------------------------------------------------------------
> >>>> - *	Basic structures
> >>>> + *	Format Handling
> >>>>   * ------------------------------------------------------------------
> >>>>   */
> >>>>  
> >>>> @@ -204,6 +201,11 @@ static char *fourcc_to_str(u32 fmt)
> >>>>  	return code;
> >>>>  }
> >>>>  
> >>>> +/* ------------------------------------------------------------------
> >>>> + *	Driver Structures
> >>>> + * ------------------------------------------------------------------
> >>>> + */
> >>>> +
> >>>>  /* buffer for one video frame */
> >>>>  struct cal_buffer {
> >>>>  	/* common v4l buffer stuff -- must be first */
> >>>> @@ -239,80 +241,6 @@ struct cal_data {
> >>>>  	unsigned int flags;
> >>>>  };
> >>>>  
> >>>> -static const struct cal_camerarx_data dra72x_cal_camerarx[] = {
> >>>> -	{
> >>>> -		.fields = {
> >>>> -			[F_CTRLCLKEN] = { 10, 10 },
> >>>> -			[F_CAMMODE] = { 11, 12 },
> >>>> -			[F_LANEENABLE] = { 13, 16 },
> >>>> -			[F_CSI_MODE] = { 17, 17 },
> >>>> -		},
> >>>> -		.num_lanes = 4,
> >>>> -	},
> >>>> -	{
> >>>> -		.fields = {
> >>>> -			[F_CTRLCLKEN] = { 0, 0 },
> >>>> -			[F_CAMMODE] = { 1, 2 },
> >>>> -			[F_LANEENABLE] = { 3, 4 },
> >>>> -			[F_CSI_MODE] = { 5, 5 },
> >>>> -		},
> >>>> -		.num_lanes = 2,
> >>>> -	},
> >>>> -};
> >>>> -
> >>>> -static const struct cal_data dra72x_cal_data = {
> >>>> -	.camerarx = dra72x_cal_camerarx,
> >>>> -	.num_csi2_phy = ARRAY_SIZE(dra72x_cal_camerarx),
> >>>> -};
> >>>> -
> >>>> -static const struct cal_data dra72x_es1_cal_data = {
> >>>> -	.camerarx = dra72x_cal_camerarx,
> >>>> -	.num_csi2_phy = ARRAY_SIZE(dra72x_cal_camerarx),
> >>>> -	.flags = DRA72_CAL_PRE_ES2_LDO_DISABLE,
> >>>> -};
> >>>> -
> >>>> -static const struct cal_camerarx_data dra76x_cal_csi_phy[] = {
> >>>> -	{
> >>>> -		.fields = {
> >>>> -			[F_CTRLCLKEN] = { 8, 8 },
> >>>> -			[F_CAMMODE] = { 9, 10 },
> >>>> -			[F_CSI_MODE] = { 11, 11 },
> >>>> -			[F_LANEENABLE] = { 27, 31 },
> >>>> -		},
> >>>> -		.num_lanes = 5,
> >>>> -	},
> >>>> -	{
> >>>> -		.fields = {
> >>>> -			[F_CTRLCLKEN] = { 0, 0 },
> >>>> -			[F_CAMMODE] = { 1, 2 },
> >>>> -			[F_CSI_MODE] = { 3, 3 },
> >>>> -			[F_LANEENABLE] = { 24, 26 },
> >>>> -		},
> >>>> -		.num_lanes = 3,
> >>>> -	},
> >>>> -};
> >>>> -
> >>>> -static const struct cal_data dra76x_cal_data = {
> >>>> -	.camerarx = dra76x_cal_csi_phy,
> >>>> -	.num_csi2_phy = ARRAY_SIZE(dra76x_cal_csi_phy),
> >>>> -};
> >>>> -
> >>>> -static const struct cal_camerarx_data am654_cal_csi_phy[] = {
> >>>> -	{
> >>>> -		.fields = {
> >>>> -			[F_CTRLCLKEN] = { 15, 15 },
> >>>> -			[F_CAMMODE] = { 24, 25 },
> >>>> -			[F_LANEENABLE] = { 0, 4 },
> >>>> -		},
> >>>> -		.num_lanes = 5,
> >>>> -	},
> >>>> -};
> >>>> -
> >>>> -static const struct cal_data am654_cal_data = {
> >>>> -	.camerarx = am654_cal_csi_phy,
> >>>> -	.num_csi2_phy = ARRAY_SIZE(am654_cal_csi_phy),
> >>>> -};
> >>>> -
> >>>>  /*
> >>>>   * The Camera Adaptation Layer (CAL) module is paired with one or more complex
> >>>>   * I/O PHYs (CAMERARX). It contains multiple instances of CSI-2, processing and
> >>>> @@ -408,6 +336,98 @@ struct cal_ctx {
> >>>>  	bool dma_act;
> >>>>  };
> >>>>  
> >>>> +static inline struct cal_ctx *notifier_to_ctx(struct v4l2_async_notifier *n)
> >>>> +{
> >>>> +	return container_of(n, struct cal_ctx, notifier);
> >>>> +}
> >>>> +
> >>>> +/* ------------------------------------------------------------------
> >>>> + *	Platform Data
> >>>> + * ------------------------------------------------------------------
> >>>> + */
> >>>> +
> >>>> +static const struct cal_camerarx_data dra72x_cal_camerarx[] = {
> >>>> +	{
> >>>> +		.fields = {
> >>>> +			[F_CTRLCLKEN] = { 10, 10 },
> >>>> +			[F_CAMMODE] = { 11, 12 },
> >>>> +			[F_LANEENABLE] = { 13, 16 },
> >>>> +			[F_CSI_MODE] = { 17, 17 },
> >>>> +		},
> >>>> +		.num_lanes = 4,
> >>>> +	},
> >>>> +	{
> >>>> +		.fields = {
> >>>> +			[F_CTRLCLKEN] = { 0, 0 },
> >>>> +			[F_CAMMODE] = { 1, 2 },
> >>>> +			[F_LANEENABLE] = { 3, 4 },
> >>>> +			[F_CSI_MODE] = { 5, 5 },
> >>>> +		},
> >>>> +		.num_lanes = 2,
> >>>> +	},
> >>>> +};
> >>>> +
> >>>> +static const struct cal_data dra72x_cal_data = {
> >>>> +	.camerarx = dra72x_cal_camerarx,
> >>>> +	.num_csi2_phy = ARRAY_SIZE(dra72x_cal_camerarx),
> >>>> +};
> >>>> +
> >>>> +static const struct cal_data dra72x_es1_cal_data = {
> >>>> +	.camerarx = dra72x_cal_camerarx,
> >>>> +	.num_csi2_phy = ARRAY_SIZE(dra72x_cal_camerarx),
> >>>> +	.flags = DRA72_CAL_PRE_ES2_LDO_DISABLE,
> >>>> +};
> >>>> +
> >>>> +static const struct cal_camerarx_data dra76x_cal_csi_phy[] = {
> >>>> +	{
> >>>> +		.fields = {
> >>>> +			[F_CTRLCLKEN] = { 8, 8 },
> >>>> +			[F_CAMMODE] = { 9, 10 },
> >>>> +			[F_CSI_MODE] = { 11, 11 },
> >>>> +			[F_LANEENABLE] = { 27, 31 },
> >>>> +		},
> >>>> +		.num_lanes = 5,
> >>>> +	},
> >>>> +	{
> >>>> +		.fields = {
> >>>> +			[F_CTRLCLKEN] = { 0, 0 },
> >>>> +			[F_CAMMODE] = { 1, 2 },
> >>>> +			[F_CSI_MODE] = { 3, 3 },
> >>>> +			[F_LANEENABLE] = { 24, 26 },
> >>>> +		},
> >>>> +		.num_lanes = 3,
> >>>> +	},
> >>>> +};
> >>>> +
> >>>> +static const struct cal_data dra76x_cal_data = {
> >>>> +	.camerarx = dra76x_cal_csi_phy,
> >>>> +	.num_csi2_phy = ARRAY_SIZE(dra76x_cal_csi_phy),
> >>>> +};
> >>>> +
> >>>> +static const struct cal_camerarx_data am654_cal_csi_phy[] = {
> >>>> +	{
> >>>> +		.fields = {
> >>>> +			[F_CTRLCLKEN] = { 15, 15 },
> >>>> +			[F_CAMMODE] = { 24, 25 },
> >>>> +			[F_LANEENABLE] = { 0, 4 },
> >>>> +		},
> >>>> +		.num_lanes = 5,
> >>>> +	},
> >>>> +};
> >>>> +
> >>>> +static const struct cal_data am654_cal_data = {
> >>>> +	.camerarx = am654_cal_csi_phy,
> >>>> +	.num_csi2_phy = ARRAY_SIZE(am654_cal_csi_phy),
> >>>> +};
> >>>> +
> >>>> +/* ------------------------------------------------------------------
> >>>> + *	I/O Register Accessors
> >>>> + * ------------------------------------------------------------------
> >>>> + */
> >>>> +
> >>>> +#define reg_read(dev, offset) ioread32(dev->base + offset)
> >>>> +#define reg_write(dev, offset, val) iowrite32(val, dev->base + offset)
> >>>> +
> >>>>  static inline u32 reg_read_field(struct cal_dev *cal, u32 offset, u32 mask)
> >>>>  {
> >>>>  	return FIELD_GET(mask, reg_read(cal, offset));
> >>>> @@ -423,41 +443,6 @@ static inline void reg_write_field(struct cal_dev *cal, u32 offset, u32 value,
> >>>>  	reg_write(cal, offset, val);
> >>>>  }
> >>>>  
> >>>> -static const struct cal_fmt *find_format_by_pix(struct cal_ctx *ctx,
> >>>> -						u32 pixelformat)
> >>>> -{
> >>>> -	const struct cal_fmt *fmt;
> >>>> -	unsigned int k;
> >>>> -
> >>>> -	for (k = 0; k < ctx->num_active_fmt; k++) {
> >>>> -		fmt = ctx->active_fmt[k];
> >>>> -		if (fmt->fourcc == pixelformat)
> >>>> -			return fmt;
> >>>> -	}
> >>>> -
> >>>> -	return NULL;
> >>>> -}
> >>>> -
> >>>> -static const struct cal_fmt *find_format_by_code(struct cal_ctx *ctx,
> >>>> -						 u32 code)
> >>>> -{
> >>>> -	const struct cal_fmt *fmt;
> >>>> -	unsigned int k;
> >>>> -
> >>>> -	for (k = 0; k < ctx->num_active_fmt; k++) {
> >>>> -		fmt = ctx->active_fmt[k];
> >>>> -		if (fmt->code == code)
> >>>> -			return fmt;
> >>>> -	}
> >>>> -
> >>>> -	return NULL;
> >>>> -}
> >>>> -
> >>>> -static inline struct cal_ctx *notifier_to_ctx(struct v4l2_async_notifier *n)
> >>>> -{
> >>>> -	return container_of(n, struct cal_ctx, notifier);
> >>>> -}
> >>>> -
> >>>>  static inline void set_field(u32 *valp, u32 field, u32 mask)
> >>>>  {
> >>>>  	u32 val = *valp;
> >>>> @@ -493,11 +478,6 @@ static void cal_quickdump_regs(struct cal_dev *cal)
> >>>>  	}
> >>>>  }
> >>>>  
> >>>> -static u32 cal_data_get_num_csi2_phy(struct cal_dev *cal)
> >>>> -{
> >>>> -	return cal->data->num_csi2_phy;
> >>>> -}
> >>>> -
> >>>>  /* ------------------------------------------------------------------
> >>>>   *	CAMERARX Management
> >>>>   * ------------------------------------------------------------------
> >>>> @@ -1152,6 +1132,11 @@ static void cal_ctx_wr_dma_addr(struct cal_ctx *ctx, unsigned int dmaaddr)
> >>>>  	reg_write(ctx->cal, CAL_WR_DMA_ADDR(ctx->csi2_port), dmaaddr);
> >>>>  }
> >>>>  
> >>>> +/* ------------------------------------------------------------------
> >>>> + *	IRQ Handling
> >>>> + * ------------------------------------------------------------------
> >>>> + */
> >>>> +
> >>>>  static inline void cal_schedule_next_buffer(struct cal_ctx *ctx)
> >>>>  {
> >>>>  	struct cal_dmaqueue *dma_q = &ctx->vidq;
> >>>> @@ -1255,9 +1240,41 @@ static irqreturn_t cal_irq(int irq_cal, void *data)
> >>>>  	return IRQ_HANDLED;
> >>>>  }
> >>>>  
> >>>> -/*
> >>>> - * video ioctls
> >>>> +/* ------------------------------------------------------------------
> >>>> + *	V4L2 Video IOCTLs
> >>>> + * ------------------------------------------------------------------
> >>>>   */
> >>>> +
> >>>> +static const struct cal_fmt *find_format_by_pix(struct cal_ctx *ctx,
> >>>> +						u32 pixelformat)
> >>>> +{
> >>>> +	const struct cal_fmt *fmt;
> >>>> +	unsigned int k;
> >>>> +
> >>>> +	for (k = 0; k < ctx->num_active_fmt; k++) {
> >>>> +		fmt = ctx->active_fmt[k];
> >>>> +		if (fmt->fourcc == pixelformat)
> >>>> +			return fmt;
> >>>> +	}
> >>>> +
> >>>> +	return NULL;
> >>>> +}
> >>>> +
> >>>> +static const struct cal_fmt *find_format_by_code(struct cal_ctx *ctx,
> >>>> +						 u32 code)
> >>>> +{
> >>>> +	const struct cal_fmt *fmt;
> >>>> +	unsigned int k;
> >>>> +
> >>>> +	for (k = 0; k < ctx->num_active_fmt; k++) {
> >>>> +		fmt = ctx->active_fmt[k];
> >>>> +		if (fmt->code == code)
> >>>> +			return fmt;
> >>>> +	}
> >>>> +
> >>>> +	return NULL;
> >>>> +}
> >>>> +
> >>>>  static int cal_querycap(struct file *file, void *priv,
> >>>>  			struct v4l2_capability *cap)
> >>>>  {
> >>>> @@ -1566,9 +1583,46 @@ static int cal_enum_frameintervals(struct file *file, void *priv,
> >>>>  	return 0;
> >>>>  }
> >>>>  
> >>>> -/*
> >>>> - * Videobuf operations
> >>>> +static const struct v4l2_file_operations cal_fops = {
> >>>> +	.owner		= THIS_MODULE,
> >>>> +	.open           = v4l2_fh_open,
> >>>> +	.release        = vb2_fop_release,
> >>>> +	.read           = vb2_fop_read,
> >>>> +	.poll		= vb2_fop_poll,
> >>>> +	.unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */
> >>>> +	.mmap           = vb2_fop_mmap,
> >>>> +};
> >>>> +
> >>>> +static const struct v4l2_ioctl_ops cal_ioctl_ops = {
> >>>> +	.vidioc_querycap      = cal_querycap,
> >>>> +	.vidioc_enum_fmt_vid_cap  = cal_enum_fmt_vid_cap,
> >>>> +	.vidioc_g_fmt_vid_cap     = cal_g_fmt_vid_cap,
> >>>> +	.vidioc_try_fmt_vid_cap   = cal_try_fmt_vid_cap,
> >>>> +	.vidioc_s_fmt_vid_cap     = cal_s_fmt_vid_cap,
> >>>> +	.vidioc_enum_framesizes   = cal_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_enum_input    = cal_enum_input,
> >>>> +	.vidioc_g_input       = cal_g_input,
> >>>> +	.vidioc_s_input       = cal_s_input,
> >>>> +	.vidioc_enum_frameintervals = cal_enum_frameintervals,
> >>>> +	.vidioc_streamon      = vb2_ioctl_streamon,
> >>>> +	.vidioc_streamoff     = vb2_ioctl_streamoff,
> >>>> +	.vidioc_log_status    = v4l2_ctrl_log_status,
> >>>> +	.vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
> >>>> +	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
> >>>> +};
> >>>> +
> >>>> +/* ------------------------------------------------------------------
> >>>> + *	videobuf2 Operations
> >>>> + * ------------------------------------------------------------------
> >>>>   */
> >>>> +
> >>>>  static int cal_queue_setup(struct vb2_queue *vq,
> >>>>  			   unsigned int *nbuffers, unsigned int *nplanes,
> >>>>  			   unsigned int sizes[], struct device *alloc_devs[])
> >>>> @@ -1772,40 +1826,10 @@ static const struct vb2_ops cal_video_qops = {
> >>>>  	.wait_finish		= vb2_ops_wait_finish,
> >>>>  };
> >>>>  
> >>>> -static const struct v4l2_file_operations cal_fops = {
> >>>> -	.owner		= THIS_MODULE,
> >>>> -	.open           = v4l2_fh_open,
> >>>> -	.release        = vb2_fop_release,
> >>>> -	.read           = vb2_fop_read,
> >>>> -	.poll		= vb2_fop_poll,
> >>>> -	.unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */
> >>>> -	.mmap           = vb2_fop_mmap,
> >>>> -};
> >>>> -
> >>>> -static const struct v4l2_ioctl_ops cal_ioctl_ops = {
> >>>> -	.vidioc_querycap      = cal_querycap,
> >>>> -	.vidioc_enum_fmt_vid_cap  = cal_enum_fmt_vid_cap,
> >>>> -	.vidioc_g_fmt_vid_cap     = cal_g_fmt_vid_cap,
> >>>> -	.vidioc_try_fmt_vid_cap   = cal_try_fmt_vid_cap,
> >>>> -	.vidioc_s_fmt_vid_cap     = cal_s_fmt_vid_cap,
> >>>> -	.vidioc_enum_framesizes   = cal_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_enum_input    = cal_enum_input,
> >>>> -	.vidioc_g_input       = cal_g_input,
> >>>> -	.vidioc_s_input       = cal_s_input,
> >>>> -	.vidioc_enum_frameintervals = cal_enum_frameintervals,
> >>>> -	.vidioc_streamon      = vb2_ioctl_streamon,
> >>>> -	.vidioc_streamoff     = vb2_ioctl_streamoff,
> >>>> -	.vidioc_log_status    = v4l2_ctrl_log_status,
> >>>> -	.vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
> >>>> -	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
> >>>> -};
> >>>> +/* ------------------------------------------------------------------
> >>>> + *	Initialization and module stuff
> >>>> + * ------------------------------------------------------------------
> >>>> + */
> >>>>  
> >>>>  static const struct video_device cal_videodev = {
> >>>>  	.name		= CAL_MODULE_NAME,
> >>>> @@ -1817,11 +1841,6 @@ static const struct video_device cal_videodev = {
> >>>>  			  V4L2_CAP_READWRITE,
> >>>>  };
> >>>>  
> >>>> -/* -----------------------------------------------------------------
> >>>> - *	Initialization and module stuff
> >>>> - * ------------------------------------------------------------------
> >>>> - */
> >>>> -
> >>>>  static int cal_complete_ctx(struct cal_ctx *ctx)
> >>>>  {
> >>>>  	struct video_device *vfd;
> >>>> @@ -2242,6 +2261,11 @@ static void cal_get_hwinfo(struct cal_dev *cal)
> >>>>  		hwinfo);
> >>>>  }
> >>>>  
> >>>
> >>>
> >>> Overall, the reorganisation is certainly helpful.
> >>>
> >>>> +static u32 cal_data_get_num_csi2_phy(struct cal_dev *cal)
> >>>> +{
> >>>> +	return cal->data->num_csi2_phy;
> >>>> +}
> >>>
> >>> However, this function (which is possibly a bit overkill on it's own
> >>> anyway) could be moved much higher in the module, so that /all/
> >>> references to the num_csi2_phy variable are accessed through it.
> >>>
> >>> Otherwise, the code is inconsistent with other parts of the driver
> >>> directly accessing this value even with an accessor.
> >>>
> >>> We could remove the accessor... or - apply the patch "media: ti-vpe:
> >>> cal: Use cal_data_get_num_csi2_phy() consistently" (which will follow
> >>> next) on top.
> >>
> >> I think I'd rather remove the accessors, this function provides little
> >> value.
> > 
> > It had some value in giving me a clean place to override having only a
> > single phy, but that's not a reason to keep it (just helpful while
> > debugging).
> > 
> > I'm fine dropping the accessor, and open-coding the usage too.
> 
> Actually, further to that - we might want some loop helper here on this
> topic anyway, as when a PHY is unused (/unconnected) we need a good way
> to make sure we don't process anything on that phy.
> 
> I think all of the places where that accessor is used would be key
> locations that should also check if the phy is defined too.
> 
> But that accessor alone is not enough, there needs to be a check that
> the phy was created too. (currently working through that now for better
> support on the DRA76-evm which has two phys, and only one is connected
> to the OV5640).

Shouldn't we still create two cal_camerarx instances, even if only one
of them is used ? Think about it from a media controller point of view,
there should be two phy entities, even if one has its input left
unconnected.

> >>> Otherwise,
> >>>
> >>> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
> >>>
> >>>> +
> >>>>  static int cal_probe(struct platform_device *pdev)
> >>>>  {
> >>>>  	struct cal_dev *cal;

-- 
Regards,

Laurent Pinchart

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

* [PATCH] media: ti-vpe: cal: Handle multiple PHYs
  2020-06-17 10:02     ` [PATCH] media: ti-vpe: cal: Use cal_data_get_num_csi2_phy() consistently Kieran Bingham
@ 2020-06-17 11:44       ` Kieran Bingham
  0 siblings, 0 replies; 150+ messages in thread
From: Kieran Bingham @ 2020-06-17 11:44 UTC (permalink / raw)
  To: Laurent Pinchart, linux-media
  Cc: Tomi Valkeinen, Benoit Parrot, Kieran Bingham

There can be multiple PHY devices supported by the CAL, however if either
has no device connected, the current code will fail to complete probe.

Update the code paths to support a PHY with no device connected, and fix
up code loops which iterate the PHY devices to ensure they are NULL
safe.

Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
---
 drivers/media/platform/ti-vpe/cal-camerarx.c | 14 +++++++++-----
 drivers/media/platform/ti-vpe/cal.c          | 13 +++++++++++--
 2 files changed, 20 insertions(+), 7 deletions(-)

diff --git a/drivers/media/platform/ti-vpe/cal-camerarx.c b/drivers/media/platform/ti-vpe/cal-camerarx.c
index 97b95973004f..14674634d882 100644
--- a/drivers/media/platform/ti-vpe/cal-camerarx.c
+++ b/drivers/media/platform/ti-vpe/cal-camerarx.c
@@ -526,7 +526,7 @@ static int cal_camerarx_parse_dt(struct cal_camerarx *phy)
 						phy->instance, 0);
 	if (!ep_node) {
 		phy_dbg(3, phy, "Can't get endpoint\n");
-		return -EINVAL;
+		return -ENODEV;
 	}
 
 	endpoint->bus_type = V4L2_MBUS_CSI2_DPHY;
@@ -803,6 +803,14 @@ struct cal_camerarx *cal_camerarx_create(struct cal_dev *cal,
 	phy->cal = cal;
 	phy->instance = instance;
 
+	ret = cal_camerarx_parse_dt(phy);
+	if (ret) {
+		if (ret == -ENODEV)
+			ret = NULL;
+
+		goto error;
+	}
+
 	phy->res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
 						(instance == 0) ?
 						"cal_rx_core0" :
@@ -821,10 +829,6 @@ struct cal_camerarx *cal_camerarx_create(struct cal_dev *cal,
 	if (ret)
 		goto error;
 
-	ret = cal_camerarx_parse_dt(phy);
-	if (ret)
-		goto error;
-
 	/* Initialize the V4L2 subdev and media entity. */
 	sd = &phy->subdev;
 	v4l2_subdev_init(sd, &cal_camerarx_subdev_ops);
diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
index 21206c3ed68e..842197f97b3b 100644
--- a/drivers/media/platform/ti-vpe/cal.c
+++ b/drivers/media/platform/ti-vpe/cal.c
@@ -275,6 +275,9 @@ void cal_quickdump_regs(struct cal_dev *cal)
 	for (i = 0; i < cal_data_get_num_csi2_phy(cal); ++i) {
 		struct cal_camerarx *phy = cal->phy[i];
 
+		if (!phy)
+			continue;
+
 		cal_info(cal, "CSI2 Core %u Registers @ %pa:\n", i,
 			 &phy->res->start);
 		print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 4,
@@ -696,6 +699,9 @@ static int cal_async_notifier_register(struct cal_dev *cal)
 		struct v4l2_async_subdev *asd;
 		struct fwnode_handle *fwnode;
 
+		if (!phy)
+			continue;
+
 		fwnode = of_fwnode_handle(phy->sensor_node);
 		asd = v4l2_async_notifier_add_fwnode_subdev(&cal->notifier,
 							    fwnode,
@@ -1033,13 +1039,15 @@ static int cal_probe(struct platform_device *pdev)
 		cal->phy[i] = cal_camerarx_create(cal, i);
 		if (IS_ERR(cal->phy[i])) {
 			ret = PTR_ERR(cal->phy[i]);
+			cal->phy[i] = NULL;
 			goto error_media;
 		}
 	}
 
 	/* Create contexts. */
 	for (i = 0; i < cal_data_get_num_csi2_phy(cal); ++i)
-		cal->ctx[i] = cal_ctx_create(cal, i);
+		if (cal->phy[i])
+			cal->ctx[i] = cal_ctx_create(cal, i);
 
 	if (!cal->ctx[0] && !cal->ctx[1]) {
 		cal_err(cal, "Neither port is configured, no point in staying up\n");
@@ -1110,7 +1118,8 @@ static int cal_runtime_resume(struct device *dev)
 		 * the clock
 		 */
 		for (i = 0; i < cal_data_get_num_csi2_phy(cal); i++)
-			cal_camerarx_i913_errata(cal->phy[i]);
+			if (cal->phy[i])
+				cal_camerarx_i913_errata(cal->phy[i]);
 	}
 
 	/*
-- 
2.25.1


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

* Re: [PATCH v1 036/107] media: ti-vpe: cal: Reorganize remaining code in sections
  2020-06-17 11:04           ` Laurent Pinchart
@ 2020-06-17 11:49             ` Kieran Bingham
  0 siblings, 0 replies; 150+ messages in thread
From: Kieran Bingham @ 2020-06-17 11:49 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Tomi Valkeinen, Benoit Parrot

Hi Laurent,

On 17/06/2020 12:04, Laurent Pinchart wrote:
> Hi Kieran,
> 
> On Wed, Jun 17, 2020 at 12:01:39PM +0100, Kieran Bingham wrote:
>> On 17/06/2020 11:54, Kieran Bingham wrote:
>>> On 17/06/2020 11:51, Laurent Pinchart wrote:
>>>> On Wed, Jun 17, 2020 at 11:00:31AM +0100, Kieran Bingham wrote:
>>>>> On 15/06/2020 00:58, Laurent Pinchart wrote:
>>>>>> Increase readability by reorganizing the remaining code in sections. No
>>>>>> functional change is included.
>>>>>>
>>>>>> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
>>>>>> ---
>>>>>>  drivers/media/platform/ti-vpe/cal.c | 350 +++++++++++++++-------------
>>>>>>  1 file changed, 187 insertions(+), 163 deletions(-)
>>>>>>
>>>>>> diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
>>>>>> index 176f616033a1..6f33853ecdb2 100644
>>>>>> --- a/drivers/media/platform/ti-vpe/cal.c
>>>>>> +++ b/drivers/media/platform/ti-vpe/cal.c
>>>>>> @@ -37,9 +37,6 @@
>>>>>>  
>>>>>>  #define CAL_MODULE_NAME "cal"
>>>>>>  
>>>>>> -#define MAX_WIDTH_BYTES (8192 * 8)
>>>>>> -#define MAX_HEIGHT_LINES 16383
>>>>>> -
>>>>>>  MODULE_DESCRIPTION("TI CAL driver");
>>>>>>  MODULE_AUTHOR("Benoit Parrot, <bparrot@ti.com>");
>>>>>>  MODULE_LICENSE("GPL v2");
>>>>>> @@ -79,11 +76,11 @@ MODULE_PARM_DESC(debug, "activates debug info");
>>>>>>  
>>>>>>  #define CAL_NUM_CONTEXT 2
>>>>>>  
>>>>>> -#define reg_read(dev, offset) ioread32(dev->base + offset)
>>>>>> -#define reg_write(dev, offset, val) iowrite32(val, dev->base + offset)
>>>>>> +#define MAX_WIDTH_BYTES (8192 * 8)
>>>>>> +#define MAX_HEIGHT_LINES 16383
>>>>>>  
>>>>>>  /* ------------------------------------------------------------------
>>>>>> - *	Basic structures
>>>>>> + *	Format Handling
>>>>>>   * ------------------------------------------------------------------
>>>>>>   */
>>>>>>  
>>>>>> @@ -204,6 +201,11 @@ static char *fourcc_to_str(u32 fmt)
>>>>>>  	return code;
>>>>>>  }
>>>>>>  
>>>>>> +/* ------------------------------------------------------------------
>>>>>> + *	Driver Structures
>>>>>> + * ------------------------------------------------------------------
>>>>>> + */
>>>>>> +
>>>>>>  /* buffer for one video frame */
>>>>>>  struct cal_buffer {
>>>>>>  	/* common v4l buffer stuff -- must be first */
>>>>>> @@ -239,80 +241,6 @@ struct cal_data {
>>>>>>  	unsigned int flags;
>>>>>>  };
>>>>>>  
>>>>>> -static const struct cal_camerarx_data dra72x_cal_camerarx[] = {
>>>>>> -	{
>>>>>> -		.fields = {
>>>>>> -			[F_CTRLCLKEN] = { 10, 10 },
>>>>>> -			[F_CAMMODE] = { 11, 12 },
>>>>>> -			[F_LANEENABLE] = { 13, 16 },
>>>>>> -			[F_CSI_MODE] = { 17, 17 },
>>>>>> -		},
>>>>>> -		.num_lanes = 4,
>>>>>> -	},
>>>>>> -	{
>>>>>> -		.fields = {
>>>>>> -			[F_CTRLCLKEN] = { 0, 0 },
>>>>>> -			[F_CAMMODE] = { 1, 2 },
>>>>>> -			[F_LANEENABLE] = { 3, 4 },
>>>>>> -			[F_CSI_MODE] = { 5, 5 },
>>>>>> -		},
>>>>>> -		.num_lanes = 2,
>>>>>> -	},
>>>>>> -};
>>>>>> -
>>>>>> -static const struct cal_data dra72x_cal_data = {
>>>>>> -	.camerarx = dra72x_cal_camerarx,
>>>>>> -	.num_csi2_phy = ARRAY_SIZE(dra72x_cal_camerarx),
>>>>>> -};
>>>>>> -
>>>>>> -static const struct cal_data dra72x_es1_cal_data = {
>>>>>> -	.camerarx = dra72x_cal_camerarx,
>>>>>> -	.num_csi2_phy = ARRAY_SIZE(dra72x_cal_camerarx),
>>>>>> -	.flags = DRA72_CAL_PRE_ES2_LDO_DISABLE,
>>>>>> -};
>>>>>> -
>>>>>> -static const struct cal_camerarx_data dra76x_cal_csi_phy[] = {
>>>>>> -	{
>>>>>> -		.fields = {
>>>>>> -			[F_CTRLCLKEN] = { 8, 8 },
>>>>>> -			[F_CAMMODE] = { 9, 10 },
>>>>>> -			[F_CSI_MODE] = { 11, 11 },
>>>>>> -			[F_LANEENABLE] = { 27, 31 },
>>>>>> -		},
>>>>>> -		.num_lanes = 5,
>>>>>> -	},
>>>>>> -	{
>>>>>> -		.fields = {
>>>>>> -			[F_CTRLCLKEN] = { 0, 0 },
>>>>>> -			[F_CAMMODE] = { 1, 2 },
>>>>>> -			[F_CSI_MODE] = { 3, 3 },
>>>>>> -			[F_LANEENABLE] = { 24, 26 },
>>>>>> -		},
>>>>>> -		.num_lanes = 3,
>>>>>> -	},
>>>>>> -};
>>>>>> -
>>>>>> -static const struct cal_data dra76x_cal_data = {
>>>>>> -	.camerarx = dra76x_cal_csi_phy,
>>>>>> -	.num_csi2_phy = ARRAY_SIZE(dra76x_cal_csi_phy),
>>>>>> -};
>>>>>> -
>>>>>> -static const struct cal_camerarx_data am654_cal_csi_phy[] = {
>>>>>> -	{
>>>>>> -		.fields = {
>>>>>> -			[F_CTRLCLKEN] = { 15, 15 },
>>>>>> -			[F_CAMMODE] = { 24, 25 },
>>>>>> -			[F_LANEENABLE] = { 0, 4 },
>>>>>> -		},
>>>>>> -		.num_lanes = 5,
>>>>>> -	},
>>>>>> -};
>>>>>> -
>>>>>> -static const struct cal_data am654_cal_data = {
>>>>>> -	.camerarx = am654_cal_csi_phy,
>>>>>> -	.num_csi2_phy = ARRAY_SIZE(am654_cal_csi_phy),
>>>>>> -};
>>>>>> -
>>>>>>  /*
>>>>>>   * The Camera Adaptation Layer (CAL) module is paired with one or more complex
>>>>>>   * I/O PHYs (CAMERARX). It contains multiple instances of CSI-2, processing and
>>>>>> @@ -408,6 +336,98 @@ struct cal_ctx {
>>>>>>  	bool dma_act;
>>>>>>  };
>>>>>>  
>>>>>> +static inline struct cal_ctx *notifier_to_ctx(struct v4l2_async_notifier *n)
>>>>>> +{
>>>>>> +	return container_of(n, struct cal_ctx, notifier);
>>>>>> +}
>>>>>> +
>>>>>> +/* ------------------------------------------------------------------
>>>>>> + *	Platform Data
>>>>>> + * ------------------------------------------------------------------
>>>>>> + */
>>>>>> +
>>>>>> +static const struct cal_camerarx_data dra72x_cal_camerarx[] = {
>>>>>> +	{
>>>>>> +		.fields = {
>>>>>> +			[F_CTRLCLKEN] = { 10, 10 },
>>>>>> +			[F_CAMMODE] = { 11, 12 },
>>>>>> +			[F_LANEENABLE] = { 13, 16 },
>>>>>> +			[F_CSI_MODE] = { 17, 17 },
>>>>>> +		},
>>>>>> +		.num_lanes = 4,
>>>>>> +	},
>>>>>> +	{
>>>>>> +		.fields = {
>>>>>> +			[F_CTRLCLKEN] = { 0, 0 },
>>>>>> +			[F_CAMMODE] = { 1, 2 },
>>>>>> +			[F_LANEENABLE] = { 3, 4 },
>>>>>> +			[F_CSI_MODE] = { 5, 5 },
>>>>>> +		},
>>>>>> +		.num_lanes = 2,
>>>>>> +	},
>>>>>> +};
>>>>>> +
>>>>>> +static const struct cal_data dra72x_cal_data = {
>>>>>> +	.camerarx = dra72x_cal_camerarx,
>>>>>> +	.num_csi2_phy = ARRAY_SIZE(dra72x_cal_camerarx),
>>>>>> +};
>>>>>> +
>>>>>> +static const struct cal_data dra72x_es1_cal_data = {
>>>>>> +	.camerarx = dra72x_cal_camerarx,
>>>>>> +	.num_csi2_phy = ARRAY_SIZE(dra72x_cal_camerarx),
>>>>>> +	.flags = DRA72_CAL_PRE_ES2_LDO_DISABLE,
>>>>>> +};
>>>>>> +
>>>>>> +static const struct cal_camerarx_data dra76x_cal_csi_phy[] = {
>>>>>> +	{
>>>>>> +		.fields = {
>>>>>> +			[F_CTRLCLKEN] = { 8, 8 },
>>>>>> +			[F_CAMMODE] = { 9, 10 },
>>>>>> +			[F_CSI_MODE] = { 11, 11 },
>>>>>> +			[F_LANEENABLE] = { 27, 31 },
>>>>>> +		},
>>>>>> +		.num_lanes = 5,
>>>>>> +	},
>>>>>> +	{
>>>>>> +		.fields = {
>>>>>> +			[F_CTRLCLKEN] = { 0, 0 },
>>>>>> +			[F_CAMMODE] = { 1, 2 },
>>>>>> +			[F_CSI_MODE] = { 3, 3 },
>>>>>> +			[F_LANEENABLE] = { 24, 26 },
>>>>>> +		},
>>>>>> +		.num_lanes = 3,
>>>>>> +	},
>>>>>> +};
>>>>>> +
>>>>>> +static const struct cal_data dra76x_cal_data = {
>>>>>> +	.camerarx = dra76x_cal_csi_phy,
>>>>>> +	.num_csi2_phy = ARRAY_SIZE(dra76x_cal_csi_phy),
>>>>>> +};
>>>>>> +
>>>>>> +static const struct cal_camerarx_data am654_cal_csi_phy[] = {
>>>>>> +	{
>>>>>> +		.fields = {
>>>>>> +			[F_CTRLCLKEN] = { 15, 15 },
>>>>>> +			[F_CAMMODE] = { 24, 25 },
>>>>>> +			[F_LANEENABLE] = { 0, 4 },
>>>>>> +		},
>>>>>> +		.num_lanes = 5,
>>>>>> +	},
>>>>>> +};
>>>>>> +
>>>>>> +static const struct cal_data am654_cal_data = {
>>>>>> +	.camerarx = am654_cal_csi_phy,
>>>>>> +	.num_csi2_phy = ARRAY_SIZE(am654_cal_csi_phy),
>>>>>> +};
>>>>>> +
>>>>>> +/* ------------------------------------------------------------------
>>>>>> + *	I/O Register Accessors
>>>>>> + * ------------------------------------------------------------------
>>>>>> + */
>>>>>> +
>>>>>> +#define reg_read(dev, offset) ioread32(dev->base + offset)
>>>>>> +#define reg_write(dev, offset, val) iowrite32(val, dev->base + offset)
>>>>>> +
>>>>>>  static inline u32 reg_read_field(struct cal_dev *cal, u32 offset, u32 mask)
>>>>>>  {
>>>>>>  	return FIELD_GET(mask, reg_read(cal, offset));
>>>>>> @@ -423,41 +443,6 @@ static inline void reg_write_field(struct cal_dev *cal, u32 offset, u32 value,
>>>>>>  	reg_write(cal, offset, val);
>>>>>>  }
>>>>>>  
>>>>>> -static const struct cal_fmt *find_format_by_pix(struct cal_ctx *ctx,
>>>>>> -						u32 pixelformat)
>>>>>> -{
>>>>>> -	const struct cal_fmt *fmt;
>>>>>> -	unsigned int k;
>>>>>> -
>>>>>> -	for (k = 0; k < ctx->num_active_fmt; k++) {
>>>>>> -		fmt = ctx->active_fmt[k];
>>>>>> -		if (fmt->fourcc == pixelformat)
>>>>>> -			return fmt;
>>>>>> -	}
>>>>>> -
>>>>>> -	return NULL;
>>>>>> -}
>>>>>> -
>>>>>> -static const struct cal_fmt *find_format_by_code(struct cal_ctx *ctx,
>>>>>> -						 u32 code)
>>>>>> -{
>>>>>> -	const struct cal_fmt *fmt;
>>>>>> -	unsigned int k;
>>>>>> -
>>>>>> -	for (k = 0; k < ctx->num_active_fmt; k++) {
>>>>>> -		fmt = ctx->active_fmt[k];
>>>>>> -		if (fmt->code == code)
>>>>>> -			return fmt;
>>>>>> -	}
>>>>>> -
>>>>>> -	return NULL;
>>>>>> -}
>>>>>> -
>>>>>> -static inline struct cal_ctx *notifier_to_ctx(struct v4l2_async_notifier *n)
>>>>>> -{
>>>>>> -	return container_of(n, struct cal_ctx, notifier);
>>>>>> -}
>>>>>> -
>>>>>>  static inline void set_field(u32 *valp, u32 field, u32 mask)
>>>>>>  {
>>>>>>  	u32 val = *valp;
>>>>>> @@ -493,11 +478,6 @@ static void cal_quickdump_regs(struct cal_dev *cal)
>>>>>>  	}
>>>>>>  }
>>>>>>  
>>>>>> -static u32 cal_data_get_num_csi2_phy(struct cal_dev *cal)
>>>>>> -{
>>>>>> -	return cal->data->num_csi2_phy;
>>>>>> -}
>>>>>> -
>>>>>>  /* ------------------------------------------------------------------
>>>>>>   *	CAMERARX Management
>>>>>>   * ------------------------------------------------------------------
>>>>>> @@ -1152,6 +1132,11 @@ static void cal_ctx_wr_dma_addr(struct cal_ctx *ctx, unsigned int dmaaddr)
>>>>>>  	reg_write(ctx->cal, CAL_WR_DMA_ADDR(ctx->csi2_port), dmaaddr);
>>>>>>  }
>>>>>>  
>>>>>> +/* ------------------------------------------------------------------
>>>>>> + *	IRQ Handling
>>>>>> + * ------------------------------------------------------------------
>>>>>> + */
>>>>>> +
>>>>>>  static inline void cal_schedule_next_buffer(struct cal_ctx *ctx)
>>>>>>  {
>>>>>>  	struct cal_dmaqueue *dma_q = &ctx->vidq;
>>>>>> @@ -1255,9 +1240,41 @@ static irqreturn_t cal_irq(int irq_cal, void *data)
>>>>>>  	return IRQ_HANDLED;
>>>>>>  }
>>>>>>  
>>>>>> -/*
>>>>>> - * video ioctls
>>>>>> +/* ------------------------------------------------------------------
>>>>>> + *	V4L2 Video IOCTLs
>>>>>> + * ------------------------------------------------------------------
>>>>>>   */
>>>>>> +
>>>>>> +static const struct cal_fmt *find_format_by_pix(struct cal_ctx *ctx,
>>>>>> +						u32 pixelformat)
>>>>>> +{
>>>>>> +	const struct cal_fmt *fmt;
>>>>>> +	unsigned int k;
>>>>>> +
>>>>>> +	for (k = 0; k < ctx->num_active_fmt; k++) {
>>>>>> +		fmt = ctx->active_fmt[k];
>>>>>> +		if (fmt->fourcc == pixelformat)
>>>>>> +			return fmt;
>>>>>> +	}
>>>>>> +
>>>>>> +	return NULL;
>>>>>> +}
>>>>>> +
>>>>>> +static const struct cal_fmt *find_format_by_code(struct cal_ctx *ctx,
>>>>>> +						 u32 code)
>>>>>> +{
>>>>>> +	const struct cal_fmt *fmt;
>>>>>> +	unsigned int k;
>>>>>> +
>>>>>> +	for (k = 0; k < ctx->num_active_fmt; k++) {
>>>>>> +		fmt = ctx->active_fmt[k];
>>>>>> +		if (fmt->code == code)
>>>>>> +			return fmt;
>>>>>> +	}
>>>>>> +
>>>>>> +	return NULL;
>>>>>> +}
>>>>>> +
>>>>>>  static int cal_querycap(struct file *file, void *priv,
>>>>>>  			struct v4l2_capability *cap)
>>>>>>  {
>>>>>> @@ -1566,9 +1583,46 @@ static int cal_enum_frameintervals(struct file *file, void *priv,
>>>>>>  	return 0;
>>>>>>  }
>>>>>>  
>>>>>> -/*
>>>>>> - * Videobuf operations
>>>>>> +static const struct v4l2_file_operations cal_fops = {
>>>>>> +	.owner		= THIS_MODULE,
>>>>>> +	.open           = v4l2_fh_open,
>>>>>> +	.release        = vb2_fop_release,
>>>>>> +	.read           = vb2_fop_read,
>>>>>> +	.poll		= vb2_fop_poll,
>>>>>> +	.unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */
>>>>>> +	.mmap           = vb2_fop_mmap,
>>>>>> +};
>>>>>> +
>>>>>> +static const struct v4l2_ioctl_ops cal_ioctl_ops = {
>>>>>> +	.vidioc_querycap      = cal_querycap,
>>>>>> +	.vidioc_enum_fmt_vid_cap  = cal_enum_fmt_vid_cap,
>>>>>> +	.vidioc_g_fmt_vid_cap     = cal_g_fmt_vid_cap,
>>>>>> +	.vidioc_try_fmt_vid_cap   = cal_try_fmt_vid_cap,
>>>>>> +	.vidioc_s_fmt_vid_cap     = cal_s_fmt_vid_cap,
>>>>>> +	.vidioc_enum_framesizes   = cal_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_enum_input    = cal_enum_input,
>>>>>> +	.vidioc_g_input       = cal_g_input,
>>>>>> +	.vidioc_s_input       = cal_s_input,
>>>>>> +	.vidioc_enum_frameintervals = cal_enum_frameintervals,
>>>>>> +	.vidioc_streamon      = vb2_ioctl_streamon,
>>>>>> +	.vidioc_streamoff     = vb2_ioctl_streamoff,
>>>>>> +	.vidioc_log_status    = v4l2_ctrl_log_status,
>>>>>> +	.vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
>>>>>> +	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
>>>>>> +};
>>>>>> +
>>>>>> +/* ------------------------------------------------------------------
>>>>>> + *	videobuf2 Operations
>>>>>> + * ------------------------------------------------------------------
>>>>>>   */
>>>>>> +
>>>>>>  static int cal_queue_setup(struct vb2_queue *vq,
>>>>>>  			   unsigned int *nbuffers, unsigned int *nplanes,
>>>>>>  			   unsigned int sizes[], struct device *alloc_devs[])
>>>>>> @@ -1772,40 +1826,10 @@ static const struct vb2_ops cal_video_qops = {
>>>>>>  	.wait_finish		= vb2_ops_wait_finish,
>>>>>>  };
>>>>>>  
>>>>>> -static const struct v4l2_file_operations cal_fops = {
>>>>>> -	.owner		= THIS_MODULE,
>>>>>> -	.open           = v4l2_fh_open,
>>>>>> -	.release        = vb2_fop_release,
>>>>>> -	.read           = vb2_fop_read,
>>>>>> -	.poll		= vb2_fop_poll,
>>>>>> -	.unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */
>>>>>> -	.mmap           = vb2_fop_mmap,
>>>>>> -};
>>>>>> -
>>>>>> -static const struct v4l2_ioctl_ops cal_ioctl_ops = {
>>>>>> -	.vidioc_querycap      = cal_querycap,
>>>>>> -	.vidioc_enum_fmt_vid_cap  = cal_enum_fmt_vid_cap,
>>>>>> -	.vidioc_g_fmt_vid_cap     = cal_g_fmt_vid_cap,
>>>>>> -	.vidioc_try_fmt_vid_cap   = cal_try_fmt_vid_cap,
>>>>>> -	.vidioc_s_fmt_vid_cap     = cal_s_fmt_vid_cap,
>>>>>> -	.vidioc_enum_framesizes   = cal_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_enum_input    = cal_enum_input,
>>>>>> -	.vidioc_g_input       = cal_g_input,
>>>>>> -	.vidioc_s_input       = cal_s_input,
>>>>>> -	.vidioc_enum_frameintervals = cal_enum_frameintervals,
>>>>>> -	.vidioc_streamon      = vb2_ioctl_streamon,
>>>>>> -	.vidioc_streamoff     = vb2_ioctl_streamoff,
>>>>>> -	.vidioc_log_status    = v4l2_ctrl_log_status,
>>>>>> -	.vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
>>>>>> -	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
>>>>>> -};
>>>>>> +/* ------------------------------------------------------------------
>>>>>> + *	Initialization and module stuff
>>>>>> + * ------------------------------------------------------------------
>>>>>> + */
>>>>>>  
>>>>>>  static const struct video_device cal_videodev = {
>>>>>>  	.name		= CAL_MODULE_NAME,
>>>>>> @@ -1817,11 +1841,6 @@ static const struct video_device cal_videodev = {
>>>>>>  			  V4L2_CAP_READWRITE,
>>>>>>  };
>>>>>>  
>>>>>> -/* -----------------------------------------------------------------
>>>>>> - *	Initialization and module stuff
>>>>>> - * ------------------------------------------------------------------
>>>>>> - */
>>>>>> -
>>>>>>  static int cal_complete_ctx(struct cal_ctx *ctx)
>>>>>>  {
>>>>>>  	struct video_device *vfd;
>>>>>> @@ -2242,6 +2261,11 @@ static void cal_get_hwinfo(struct cal_dev *cal)
>>>>>>  		hwinfo);
>>>>>>  }
>>>>>>  
>>>>>
>>>>>
>>>>> Overall, the reorganisation is certainly helpful.
>>>>>
>>>>>> +static u32 cal_data_get_num_csi2_phy(struct cal_dev *cal)
>>>>>> +{
>>>>>> +	return cal->data->num_csi2_phy;
>>>>>> +}
>>>>>
>>>>> However, this function (which is possibly a bit overkill on it's own
>>>>> anyway) could be moved much higher in the module, so that /all/
>>>>> references to the num_csi2_phy variable are accessed through it.
>>>>>
>>>>> Otherwise, the code is inconsistent with other parts of the driver
>>>>> directly accessing this value even with an accessor.
>>>>>
>>>>> We could remove the accessor... or - apply the patch "media: ti-vpe:
>>>>> cal: Use cal_data_get_num_csi2_phy() consistently" (which will follow
>>>>> next) on top.
>>>>
>>>> I think I'd rather remove the accessors, this function provides little
>>>> value.
>>>
>>> It had some value in giving me a clean place to override having only a
>>> single phy, but that's not a reason to keep it (just helpful while
>>> debugging).
>>>
>>> I'm fine dropping the accessor, and open-coding the usage too.
>>
>> Actually, further to that - we might want some loop helper here on this
>> topic anyway, as when a PHY is unused (/unconnected) we need a good way
>> to make sure we don't process anything on that phy.
>>
>> I think all of the places where that accessor is used would be key
>> locations that should also check if the phy is defined too.
>>
>> But that accessor alone is not enough, there needs to be a check that
>> the phy was created too. (currently working through that now for better
>> support on the DRA76-evm which has two phys, and only one is connected
>> to the OV5640).
> 
> Shouldn't we still create two cal_camerarx instances, even if only one
> of them is used ? Think about it from a media controller point of view,
> there should be two phy entities, even if one has its input left
> unconnected.

Ok - well I'll leave you to fix up in your series as you see fit, and I
can re-test when the series is revised.

I've just posted "[PATCH] media: ti-vpe: cal: Handle multiple PHYs"
which fixes up the fail paths for me on the 2-phy target, and allows
successful capture again, but given the above isn't a suitable approach.

--
Kieran



> 
>>>>> Otherwise,
>>>>>
>>>>> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
>>>>>
>>>>>> +
>>>>>>  static int cal_probe(struct platform_device *pdev)
>>>>>>  {
>>>>>>  	struct cal_dev *cal;
> 

-- 
Regards
--
Kieran

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

* Re: [PATCH v1 078/107] media: ti-vpe: cal: Don't store external rate in cal_camerarx
  2020-06-17 10:16       ` Kieran Bingham
@ 2020-06-18  2:36         ` Laurent Pinchart
  2020-06-18  8:07           ` Kieran Bingham
  0 siblings, 1 reply; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-18  2:36 UTC (permalink / raw)
  To: Kieran Bingham; +Cc: linux-media, Tomi Valkeinen, Benoit Parrot

Hi Kieran,

On Wed, Jun 17, 2020 at 11:16:45AM +0100, Kieran Bingham wrote:
> On 17/06/2020 11:05, Laurent Pinchart wrote:
> > On Wed, Jun 17, 2020 at 10:56:29AM +0100, Kieran Bingham wrote:
> >> On 15/06/2020 00:59, Laurent Pinchart wrote:
> >>> The external pixel rate is retrieved when starting the camerarx and only
> >>> used then. There's no need to store it in the cal_camerarx structure, it
> >>> can be returned by cal_camerarx_get_external_info() and explicitly
> >>> passed to cal_camerarx_config().
> >>>
> >>> While at it, rename cal_camerarx_get_external_info() to
> >>> cal_camerarx_get_external_rate() to better reflect the function's
> >>> purpose.
> >>>
> >>> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> >>> ---
> >>>  drivers/media/platform/ti-vpe/cal.c | 24 ++++++++++++------------
> >>>  1 file changed, 12 insertions(+), 12 deletions(-)
> >>>
> >>> diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
> >>> index 8326db0e4197..a11457909134 100644
> >>> --- a/drivers/media/platform/ti-vpe/cal.c
> >>> +++ b/drivers/media/platform/ti-vpe/cal.c
> >>> @@ -272,7 +272,6 @@ struct cal_camerarx {
> >>>  	struct v4l2_fwnode_endpoint	endpoint;
> >>>  	struct device_node	*sensor_node;
> >>>  	struct v4l2_subdev	*sensor;
> >>> -	unsigned int		external_rate;
> >>
> >> Here, external_rate is 32 bit,
> >>
> >>>  };
> >>>  
> >>>  struct cal_dev {
> >>> @@ -481,9 +480,10 @@ static void cal_quickdump_regs(struct cal_dev *cal)
> >>>   * ------------------------------------------------------------------
> >>>   */
> >>>  
> >>> -static int cal_camerarx_get_external_info(struct cal_camerarx *phy)
> >>> +static s64 cal_camerarx_get_external_rate(struct cal_camerarx *phy)
> >>>  {
> >>>  	struct v4l2_ctrl *ctrl;
> >>> +	s64 rate;
> >>
> >> and now it becomes a 64 bit value.
> >>
> >>>  
> >>>  	if (!phy->sensor)
> >>>  		return -ENODEV;
> >>> @@ -495,10 +495,10 @@ static int cal_camerarx_get_external_info(struct cal_camerarx *phy)
> >>>  		return -EPIPE;
> >>>  	}
> >>>  
> >>> -	phy->external_rate = v4l2_ctrl_g_ctrl_int64(ctrl);
> >>> -	phy_dbg(3, phy, "sensor Pixel Rate: %u\n", phy->external_rate);
> >>> +	rate = v4l2_ctrl_g_ctrl_int64(ctrl);
> >>> +	phy_dbg(3, phy, "sensor Pixel Rate: %llu\n", rate);
> >>>  
> >>> -	return 0;
> >>> +	return rate;
> >>>  }
> >>>  
> >>>  static void cal_camerarx_lane_config(struct cal_camerarx *phy)
> >>> @@ -554,7 +554,7 @@ static void cal_camerarx_disable(struct cal_camerarx *phy)
> >>>  #define TCLK_MISS	1
> >>>  #define TCLK_SETTLE	14
> >>>  
> >>> -static void cal_camerarx_config(struct cal_camerarx *phy,
> >>> +static void cal_camerarx_config(struct cal_camerarx *phy, s64 external_rate,
> >>>  				const struct cal_fmt *fmt)
> >>>  {
> >>>  	unsigned int reg0, reg1;
> >>> @@ -566,7 +566,7 @@ static void cal_camerarx_config(struct cal_camerarx *phy,
> >>>  
> >>>  	/* DPHY timing configuration */
> >>>  	/* CSI-2 is DDR and we only count used lanes. */
> >>> -	csi2_ddrclk_khz = phy->external_rate / 1000
> >>> +	csi2_ddrclk_khz = external_rate / 1000
> >>>  		/ (2 * num_lanes) * fmt->bpp;
> >>
> >> Which causes this calculation to fail on 32 bit ARM builds.
> >> (I'm building for the DRA76-EVM).
> > 
> > Oops :-/
> > 
> >> I've got the following fix up on the top of your tree to solve this, but
> >> I'm not particularly happy about having to break the calculation up (and
> >> re-use external_rate) though the use of do_div.
> >>
> >> From ca6ce335a852e34364bc45cb4240f703e4ea4248 Mon Sep 17 00:00:00 2001
> >> From: Kieran Bingham <kieran.bingham@ideasonboard.com>
> >> Date: Tue, 16 Jun 2020 16:19:04 +0100
> >> Subject: [PATCH] media: ti-vpe: cal: Use do_div() for 64 bit operations
> >>
> >> Support building the CAL driver on arm32 bit targets by updating the
> >> CSI2 clock calculation (which uses a signed 64 bit input value from
> >> the sensors pixel clock rate) to use the do_div() helpers.
> >>
> >> The calculation is split into distinct parts to maintain
> >> order of operations while making use of the do_div macro and further
> >> re-ordered to convert to kHz at the end to maintain precision.
> >>
> >> Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
> >> ---
> >>  drivers/media/platform/ti-vpe/cal-camerarx.c | 22 +++++++++++++++++---
> >>  1 file changed, 19 insertions(+), 3 deletions(-)
> >>
> >> diff --git a/drivers/media/platform/ti-vpe/cal-camerarx.c
> >> b/drivers/media/platform/ti-vpe/cal-camerarx.c
> >> index 014ca46509db..0ef19a516902 100644
> >> --- a/drivers/media/platform/ti-vpe/cal-camerarx.c
> >> +++ b/drivers/media/platform/ti-vpe/cal-camerarx.c
> >> @@ -126,9 +126,25 @@ static void cal_camerarx_config(struct cal_camerarx
> >> *phy, s64 external_rate)
> >>         u32 num_lanes = mipi_csi2->num_data_lanes;
> >>
> >>         /* DPHY timing configuration */
> >> -       /* CSI-2 is DDR and we only count used lanes. */
> >> -       csi2_ddrclk_khz = external_rate / 1000
> >> -               / (2 * num_lanes) * phy->fmtinfo->bpp;
> >> +
> >> +       /*
> >> +        * CSI-2 is DDR and we only count used lanes.
> >> +        *
> >> +        * csi2_ddrclk_khz = external_rate / 1000
> >> +        *                   / (2 * num_lanes) * phy->fmtinfo->bpp;
> >> +        *
> >> +        * The equation is broken into separate statements to maintain
> >> +        * order of operations, and conversion to kHz is done last to
> >> +        * keep precision.
> >> +        *
> >> +        * The 64 bit external_rate is modified during this equation and
> >> +        * contains the result, not the original after calculation.
> >> +        */
> >> +       do_div(external_rate, 2 * num_lanes);
> >> +       external_rate *= phy->fmtinfo->bpp;
> >> +       do_div(external_rate, 1000);
> >> +       csi2_ddrclk_khz = external_rate;
> > 
> > How about
> > 
> > 	external_rate *= phy->fmtinfo->bpp;
> >  	do_div(external_rate, 2 * num_lanes * 1000);
> 
> Ah yes, that looks better indeed, and keeps the improved integer precision.
> 
> I believe the s64 external_rate should cope with the * bpp operation
> easily too, so I don't think there's any risk of an overflow there.
> 
> Squash it ;-)

Even better,

	csi2_ddrclk_khz = div_s64(external_rate * phy->fmtinfo->bpp,
				  2 * num_lanes * 1000);

> >> +
> >>         phy_dbg(1, phy, "csi2_ddrclk_khz: %d\n", csi2_ddrclk_khz);
> >>
> >>         /* THS_TERM: Programmed value = floor(20 ns/DDRClk period) */
> >> -- 
> >> 2.25.1
> >>
> >>
> >> If you have a better way to correctly calculate the rate (also noting
> >> that I moved the /1000 to the end, I'm not sure if that's more correct,
> >> or makes it stop following what the hardware would do) - please update
> >> accordingly, or feel free to squash this patch in as you wish.
> >>
> >>
> >> With the calculation corrected:
> >>
> >> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
> >>
> >> --
> >> Kieran
> >>
> >>
> >>>  	phy_dbg(1, phy, "csi2_ddrclk_khz: %d\n", csi2_ddrclk_khz);
> >>>  
> >>> @@ -667,13 +667,14 @@ static void cal_camerarx_wait_stop_state(struct cal_camerarx *phy)
> >>>  static int cal_camerarx_start(struct cal_camerarx *phy,
> >>>  			      const struct cal_fmt *fmt)
> >>>  {
> >>> +	s64 external_rate;
> >>>  	u32 sscounter;
> >>>  	u32 val;
> >>>  	int ret;
> >>>  
> >>> -	ret = cal_camerarx_get_external_info(phy);
> >>> -	if (ret < 0)
> >>> -		return ret;
> >>> +	external_rate = cal_camerarx_get_external_rate(phy);
> >>> +	if (external_rate < 0)
> >>> +		return external_rate;
> >>>  
> >>>  	ret = v4l2_subdev_call(phy->sensor, core, s_power, 1);
> >>>  	if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV) {
> >>> @@ -719,7 +720,7 @@ static int cal_camerarx_start(struct cal_camerarx *phy,
> >>>  	reg_read(phy, CAL_CSI2_PHY_REG0);
> >>>  
> >>>  	/* Program the PHY timing parameters. */
> >>> -	cal_camerarx_config(phy, fmt);
> >>> +	cal_camerarx_config(phy, external_rate, fmt);
> >>>  
> >>>  	/*
> >>>  	 *    b. Assert the FORCERXMODE signal.
> >>> @@ -1034,7 +1035,6 @@ static struct cal_camerarx *cal_camerarx_create(struct cal_dev *cal,
> >>>  
> >>>  	phy->cal = cal;
> >>>  	phy->instance = instance;
> >>> -	phy->external_rate = 192000000;
> >>>  
> >>>  	phy->res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
> >>>  						(instance == 0) ?

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH v1 078/107] media: ti-vpe: cal: Don't store external rate in cal_camerarx
  2020-06-18  2:36         ` Laurent Pinchart
@ 2020-06-18  8:07           ` Kieran Bingham
  0 siblings, 0 replies; 150+ messages in thread
From: Kieran Bingham @ 2020-06-18  8:07 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Tomi Valkeinen, Benoit Parrot

Hi Laurent,

On 18/06/2020 03:36, Laurent Pinchart wrote:
> Hi Kieran,
> 
> On Wed, Jun 17, 2020 at 11:16:45AM +0100, Kieran Bingham wrote:
>> On 17/06/2020 11:05, Laurent Pinchart wrote:
>>> On Wed, Jun 17, 2020 at 10:56:29AM +0100, Kieran Bingham wrote:
>>>> On 15/06/2020 00:59, Laurent Pinchart wrote:
>>>>> The external pixel rate is retrieved when starting the camerarx and only
>>>>> used then. There's no need to store it in the cal_camerarx structure, it
>>>>> can be returned by cal_camerarx_get_external_info() and explicitly
>>>>> passed to cal_camerarx_config().
>>>>>
>>>>> While at it, rename cal_camerarx_get_external_info() to
>>>>> cal_camerarx_get_external_rate() to better reflect the function's
>>>>> purpose.
>>>>>
>>>>> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
>>>>> ---
>>>>>  drivers/media/platform/ti-vpe/cal.c | 24 ++++++++++++------------
>>>>>  1 file changed, 12 insertions(+), 12 deletions(-)
>>>>>
>>>>> diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
>>>>> index 8326db0e4197..a11457909134 100644
>>>>> --- a/drivers/media/platform/ti-vpe/cal.c
>>>>> +++ b/drivers/media/platform/ti-vpe/cal.c
>>>>> @@ -272,7 +272,6 @@ struct cal_camerarx {
>>>>>  	struct v4l2_fwnode_endpoint	endpoint;
>>>>>  	struct device_node	*sensor_node;
>>>>>  	struct v4l2_subdev	*sensor;
>>>>> -	unsigned int		external_rate;
>>>>
>>>> Here, external_rate is 32 bit,
>>>>
>>>>>  };
>>>>>  
>>>>>  struct cal_dev {
>>>>> @@ -481,9 +480,10 @@ static void cal_quickdump_regs(struct cal_dev *cal)
>>>>>   * ------------------------------------------------------------------
>>>>>   */
>>>>>  
>>>>> -static int cal_camerarx_get_external_info(struct cal_camerarx *phy)
>>>>> +static s64 cal_camerarx_get_external_rate(struct cal_camerarx *phy)
>>>>>  {
>>>>>  	struct v4l2_ctrl *ctrl;
>>>>> +	s64 rate;
>>>>
>>>> and now it becomes a 64 bit value.
>>>>
>>>>>  
>>>>>  	if (!phy->sensor)
>>>>>  		return -ENODEV;
>>>>> @@ -495,10 +495,10 @@ static int cal_camerarx_get_external_info(struct cal_camerarx *phy)
>>>>>  		return -EPIPE;
>>>>>  	}
>>>>>  
>>>>> -	phy->external_rate = v4l2_ctrl_g_ctrl_int64(ctrl);
>>>>> -	phy_dbg(3, phy, "sensor Pixel Rate: %u\n", phy->external_rate);
>>>>> +	rate = v4l2_ctrl_g_ctrl_int64(ctrl);
>>>>> +	phy_dbg(3, phy, "sensor Pixel Rate: %llu\n", rate);
>>>>>  
>>>>> -	return 0;
>>>>> +	return rate;
>>>>>  }
>>>>>  
>>>>>  static void cal_camerarx_lane_config(struct cal_camerarx *phy)
>>>>> @@ -554,7 +554,7 @@ static void cal_camerarx_disable(struct cal_camerarx *phy)
>>>>>  #define TCLK_MISS	1
>>>>>  #define TCLK_SETTLE	14
>>>>>  
>>>>> -static void cal_camerarx_config(struct cal_camerarx *phy,
>>>>> +static void cal_camerarx_config(struct cal_camerarx *phy, s64 external_rate,
>>>>>  				const struct cal_fmt *fmt)
>>>>>  {
>>>>>  	unsigned int reg0, reg1;
>>>>> @@ -566,7 +566,7 @@ static void cal_camerarx_config(struct cal_camerarx *phy,
>>>>>  
>>>>>  	/* DPHY timing configuration */
>>>>>  	/* CSI-2 is DDR and we only count used lanes. */
>>>>> -	csi2_ddrclk_khz = phy->external_rate / 1000
>>>>> +	csi2_ddrclk_khz = external_rate / 1000
>>>>>  		/ (2 * num_lanes) * fmt->bpp;
>>>>
>>>> Which causes this calculation to fail on 32 bit ARM builds.
>>>> (I'm building for the DRA76-EVM).
>>>
>>> Oops :-/
>>>
>>>> I've got the following fix up on the top of your tree to solve this, but
>>>> I'm not particularly happy about having to break the calculation up (and
>>>> re-use external_rate) though the use of do_div.
>>>>
>>>> From ca6ce335a852e34364bc45cb4240f703e4ea4248 Mon Sep 17 00:00:00 2001
>>>> From: Kieran Bingham <kieran.bingham@ideasonboard.com>
>>>> Date: Tue, 16 Jun 2020 16:19:04 +0100
>>>> Subject: [PATCH] media: ti-vpe: cal: Use do_div() for 64 bit operations
>>>>
>>>> Support building the CAL driver on arm32 bit targets by updating the
>>>> CSI2 clock calculation (which uses a signed 64 bit input value from
>>>> the sensors pixel clock rate) to use the do_div() helpers.
>>>>
>>>> The calculation is split into distinct parts to maintain
>>>> order of operations while making use of the do_div macro and further
>>>> re-ordered to convert to kHz at the end to maintain precision.
>>>>
>>>> Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
>>>> ---
>>>>  drivers/media/platform/ti-vpe/cal-camerarx.c | 22 +++++++++++++++++---
>>>>  1 file changed, 19 insertions(+), 3 deletions(-)
>>>>
>>>> diff --git a/drivers/media/platform/ti-vpe/cal-camerarx.c
>>>> b/drivers/media/platform/ti-vpe/cal-camerarx.c
>>>> index 014ca46509db..0ef19a516902 100644
>>>> --- a/drivers/media/platform/ti-vpe/cal-camerarx.c
>>>> +++ b/drivers/media/platform/ti-vpe/cal-camerarx.c
>>>> @@ -126,9 +126,25 @@ static void cal_camerarx_config(struct cal_camerarx
>>>> *phy, s64 external_rate)
>>>>         u32 num_lanes = mipi_csi2->num_data_lanes;
>>>>
>>>>         /* DPHY timing configuration */
>>>> -       /* CSI-2 is DDR and we only count used lanes. */
>>>> -       csi2_ddrclk_khz = external_rate / 1000
>>>> -               / (2 * num_lanes) * phy->fmtinfo->bpp;
>>>> +
>>>> +       /*
>>>> +        * CSI-2 is DDR and we only count used lanes.
>>>> +        *
>>>> +        * csi2_ddrclk_khz = external_rate / 1000
>>>> +        *                   / (2 * num_lanes) * phy->fmtinfo->bpp;
>>>> +        *
>>>> +        * The equation is broken into separate statements to maintain
>>>> +        * order of operations, and conversion to kHz is done last to
>>>> +        * keep precision.
>>>> +        *
>>>> +        * The 64 bit external_rate is modified during this equation and
>>>> +        * contains the result, not the original after calculation.
>>>> +        */
>>>> +       do_div(external_rate, 2 * num_lanes);
>>>> +       external_rate *= phy->fmtinfo->bpp;
>>>> +       do_div(external_rate, 1000);
>>>> +       csi2_ddrclk_khz = external_rate;
>>>
>>> How about
>>>
>>> 	external_rate *= phy->fmtinfo->bpp;
>>>  	do_div(external_rate, 2 * num_lanes * 1000);
>>
>> Ah yes, that looks better indeed, and keeps the improved integer precision.
>>
>> I believe the s64 external_rate should cope with the * bpp operation
>> easily too, so I don't think there's any risk of an overflow there.
>>
>> Squash it ;-)
> 
> Even better,
> 
> 	csi2_ddrclk_khz = div_s64(external_rate * phy->fmtinfo->bpp,
> 				  2 * num_lanes * 1000);


Ah, here I was about to say "you can't put the rate*bpp together because
the do_div reuses the argument ... and now I see div_s64 ...

/me discovers yet another way to do divides :-S

Well that's better all round ;-)


--
Kieran



>>>> +
>>>>         phy_dbg(1, phy, "csi2_ddrclk_khz: %d\n", csi2_ddrclk_khz);
>>>>
>>>>         /* THS_TERM: Programmed value = floor(20 ns/DDRClk period) */
>>>> -- 
>>>> 2.25.1
>>>>
>>>>
>>>> If you have a better way to correctly calculate the rate (also noting
>>>> that I moved the /1000 to the end, I'm not sure if that's more correct,
>>>> or makes it stop following what the hardware would do) - please update
>>>> accordingly, or feel free to squash this patch in as you wish.
>>>>
>>>>
>>>> With the calculation corrected:
>>>>
>>>> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
>>>>
>>>> --
>>>> Kieran
>>>>
>>>>
>>>>>  	phy_dbg(1, phy, "csi2_ddrclk_khz: %d\n", csi2_ddrclk_khz);
>>>>>  
>>>>> @@ -667,13 +667,14 @@ static void cal_camerarx_wait_stop_state(struct cal_camerarx *phy)
>>>>>  static int cal_camerarx_start(struct cal_camerarx *phy,
>>>>>  			      const struct cal_fmt *fmt)
>>>>>  {
>>>>> +	s64 external_rate;
>>>>>  	u32 sscounter;
>>>>>  	u32 val;
>>>>>  	int ret;
>>>>>  
>>>>> -	ret = cal_camerarx_get_external_info(phy);
>>>>> -	if (ret < 0)
>>>>> -		return ret;
>>>>> +	external_rate = cal_camerarx_get_external_rate(phy);
>>>>> +	if (external_rate < 0)
>>>>> +		return external_rate;
>>>>>  
>>>>>  	ret = v4l2_subdev_call(phy->sensor, core, s_power, 1);
>>>>>  	if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV) {
>>>>> @@ -719,7 +720,7 @@ static int cal_camerarx_start(struct cal_camerarx *phy,
>>>>>  	reg_read(phy, CAL_CSI2_PHY_REG0);
>>>>>  
>>>>>  	/* Program the PHY timing parameters. */
>>>>> -	cal_camerarx_config(phy, fmt);
>>>>> +	cal_camerarx_config(phy, external_rate, fmt);
>>>>>  
>>>>>  	/*
>>>>>  	 *    b. Assert the FORCERXMODE signal.
>>>>> @@ -1034,7 +1035,6 @@ static struct cal_camerarx *cal_camerarx_create(struct cal_dev *cal,
>>>>>  
>>>>>  	phy->cal = cal;
>>>>>  	phy->instance = instance;
>>>>> -	phy->external_rate = 192000000;
>>>>>  
>>>>>  	phy->res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
>>>>>  						(instance == 0) ?
> 

-- 
Regards
--
Kieran

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

* Re: [PATCH v1 008/107] media: ti-vpe: cal: Turn reg_(read|write)_field() into inline functions
  2020-06-14 23:58 ` [PATCH v1 008/107] media: ti-vpe: cal: Turn reg_(read|write)_field() into inline functions Laurent Pinchart
@ 2020-06-18 13:29   ` Benoit Parrot
  2020-06-19 15:15     ` Laurent Pinchart
  0 siblings, 1 reply; 150+ messages in thread
From: Benoit Parrot @ 2020-06-18 13:29 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Tomi Valkeinen

Hi Laurent,

Thank you for the patch.

Laurent Pinchart <laurent.pinchart@ideasonboard.com> wrote on Mon [2020-Jun-15 02:58:05 +0300]:
> Turn the reg_(read|write)_field() macros into inline functions for
> additional type safety. Use the FIELD_GET() and FIELD_PREP() macros
> internally instead of reinventing the wheel.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>  drivers/media/platform/ti-vpe/cal.c | 28 ++++++++++++++++------------
>  1 file changed, 16 insertions(+), 12 deletions(-)
> 
> diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
> index fa86a53882cc..8c068af936f0 100644
> --- a/drivers/media/platform/ti-vpe/cal.c
> +++ b/drivers/media/platform/ti-vpe/cal.c
> @@ -6,6 +6,7 @@
>   * Benoit Parrot, <bparrot@ti.com>
>   */
>  
> +#include <linux/bitfield.h>
>  #include <linux/clk.h>
>  #include <linux/delay.h>
>  #include <linux/interrupt.h>
> @@ -76,13 +77,6 @@ static const struct v4l2_fract
>  #define reg_read(dev, offset) ioread32(dev->base + offset)
>  #define reg_write(dev, offset, val) iowrite32(val, dev->base + offset)
>  
> -#define reg_read_field(dev, offset, mask) get_field(reg_read(dev, offset), \
> -						    mask)
> -#define reg_write_field(dev, offset, field, mask) { \
> -	u32 val = reg_read(dev, offset); \
> -	set_field(&val, field, mask); \
> -	reg_write(dev, offset, val); }
> -
>  /* ------------------------------------------------------------------
>   *	Basic structures
>   * ------------------------------------------------------------------
> @@ -418,6 +412,21 @@ struct cal_ctx {
>  	bool dma_act;
>  };
>  
> +static inline u32 reg_read_field(struct cal_dev *dev, u32 offset, u32 mask)
> +{
> +	return FIELD_GET(mask, reg_read(dev, offset));
> +}
> +
> +static inline void reg_write_field(struct cal_dev *dev, u32 offset, u32 value,
> +				   u32 mask)
> +{
> +	u32 val = reg_read(dev, offset);
> +
> +	val &= ~mask;
> +	val |= FIELD_PREP(mask, value);
> +	reg_write(dev, offset, val);
> +}
> +
>  static const struct cal_fmt *find_format_by_pix(struct cal_ctx *ctx,
>  						u32 pixelformat)
>  {
> @@ -453,11 +462,6 @@ static inline struct cal_ctx *notifier_to_ctx(struct v4l2_async_notifier *n)
>  	return container_of(n, struct cal_ctx, notifier);
>  }
>  
> -static inline int get_field(u32 value, u32 mask)
> -{
> -	return (value & mask) >> __ffs(mask);
> -}
> -
>  static inline void set_field(u32 *valp, u32 field, u32 mask)
>  {
>  	u32 val = *valp;

Is set_field still in use then after this patch?
Any reason to keep it around?

Benoit

> -- 
> Regards,
> 
> Laurent Pinchart
> 

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

* Re: [PATCH v1 027/107] media: ti-vpe: cal: Name all cal_camerarx pointers consistently
  2020-06-14 23:58 ` [PATCH v1 027/107] media: ti-vpe: cal: Name all cal_camerarx " Laurent Pinchart
  2020-06-16 10:58   ` Tomi Valkeinen
@ 2020-06-18 14:06   ` Benoit Parrot
  2020-06-18 14:15     ` Laurent Pinchart
  1 sibling, 1 reply; 150+ messages in thread
From: Benoit Parrot @ 2020-06-18 14:06 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Tomi Valkeinen

Hi Laurent,

Thank you for the patch.

Laurent Pinchart <laurent.pinchart@ideasonboard.com> wrote on Mon [2020-Jun-15 02:58:24 +0300]:
> Name all variables htat point to a cal_camerax instance 'phy' instead of
> 'cc'. The name 'cc' refers to Camera Core, but is not commonly used in
> the driver or in datasheets.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>  drivers/media/platform/ti-vpe/cal.c | 102 ++++++++++++++--------------
>  1 file changed, 51 insertions(+), 51 deletions(-)
> 
> diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
> index 615e9d97e61f..8864a00a22b0 100644
> --- a/drivers/media/platform/ti-vpe/cal.c
> +++ b/drivers/media/platform/ti-vpe/cal.c
> @@ -312,7 +312,8 @@ static const struct cal_data am654_cal_data = {
>   * the CAMERARX instances. Instances of struct cal_dev are named cal through the
>   * driver.
>   *
> - * The cal_camerarx structure represents one CAMERARX instance.
> + * The cal_camerarx structure represents one CAMERARX instance. Instances of
> + * cal_camerarx are named phy through the driver.
>   *
>   * The cal_ctx structure represents the combination of one CSI-2 context, one
>   * processing context and one DMA context. Instance of struct cal_ctx are named
> @@ -344,7 +345,7 @@ struct cal_dev {
>  	u32			syscon_camerrx_offset;
>  
>  	/* Camera Core Module handle */
> -	struct cal_camerarx	*cc[CAL_NUM_CSI2_PORTS];
> +	struct cal_camerarx	*phy[CAL_NUM_CSI2_PORTS];
>  
>  	struct cal_ctx		*ctx[CAL_NUM_CONTEXT];
>  };
> @@ -361,7 +362,7 @@ struct cal_ctx {
>  	struct v4l2_fwnode_endpoint	endpoint;
>  
>  	struct cal_dev		*cal;
> -	struct cal_camerarx	*cc;
> +	struct cal_camerarx	*phy;
>  
>  	/* v4l2_ioctl mutex */
>  	struct mutex		mutex;
> @@ -468,7 +469,7 @@ static u32 cal_data_get_num_csi2_phy(struct cal_dev *cal)
>  }
>  
>  static int cal_camerarx_regmap_init(struct cal_dev *cal,
> -				    struct cal_camerarx *cc,
> +				    struct cal_camerarx *phy,
>  				    unsigned int idx)
>  {
>  	const struct cal_camerarx_data *phy_data;
> @@ -490,12 +491,12 @@ static int cal_camerarx_regmap_init(struct cal_dev *cal,
>  		 * Here we update the reg offset with the
>  		 * value found in DT
>  		 */
> -		cc->phy.fields[i] = devm_regmap_field_alloc(&cal->pdev->dev,
> -							    cal->syscon_camerrx,
> -							    field);
> -		if (IS_ERR(cc->phy.fields[i])) {
> +		phy->phy.fields[i] = devm_regmap_field_alloc(&cal->pdev->dev,
> +							     cal->syscon_camerrx,
> +							     field);

So we end up with these construct phy->phy.
Is that really more readable?

Benoit

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

* Re: [PATCH v1 028/107] media: ti-vpe: cal: Remove internal phy structure from cal_camerarx
  2020-06-14 23:58 ` [PATCH v1 028/107] media: ti-vpe: cal: Remove internal phy structure from cal_camerarx Laurent Pinchart
@ 2020-06-18 14:08   ` Benoit Parrot
  0 siblings, 0 replies; 150+ messages in thread
From: Benoit Parrot @ 2020-06-18 14:08 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Tomi Valkeinen

Hi Laurent,

Never mind my last comment then.... sigh

Benoit

Laurent Pinchart <laurent.pinchart@ideasonboard.com> wrote on Mon [2020-Jun-15 02:58:25 +0300]:
> The cal_camerarx structure describes the PHY, there's no need for an
> internal structure named phy. Removed that level of indirection.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>  drivers/media/platform/ti-vpe/cal.c | 27 ++++++++++++---------------
>  1 file changed, 12 insertions(+), 15 deletions(-)
> 
> diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
> index 8864a00a22b0..9b905b61148f 100644
> --- a/drivers/media/platform/ti-vpe/cal.c
> +++ b/drivers/media/platform/ti-vpe/cal.c
> @@ -324,10 +324,7 @@ struct cal_camerarx {
>  	void __iomem		*base;
>  	struct resource		*res;
>  	struct platform_device	*pdev;
> -
> -	struct {
> -		struct regmap_field *fields[F_MAX_FIELDS];
> -	} phy;
> +	struct regmap_field	*fields[F_MAX_FIELDS];
>  };
>  
>  struct cal_dev {
> @@ -491,12 +488,12 @@ static int cal_camerarx_regmap_init(struct cal_dev *cal,
>  		 * Here we update the reg offset with the
>  		 * value found in DT
>  		 */
> -		phy->phy.fields[i] = devm_regmap_field_alloc(&cal->pdev->dev,
> -							     cal->syscon_camerrx,
> -							     field);
> -		if (IS_ERR(phy->phy.fields[i])) {
> +		phy->fields[i] = devm_regmap_field_alloc(&cal->pdev->dev,
> +							 cal->syscon_camerrx,
> +							 field);
> +		if (IS_ERR(phy->fields[i])) {
>  			cal_err(cal, "Unable to allocate regmap fields\n");
> -			return PTR_ERR(phy->phy.fields[i]);
> +			return PTR_ERR(phy->fields[i]);
>  		}
>  	}
>  
> @@ -543,14 +540,14 @@ static void camerarx_phy_enable(struct cal_ctx *ctx)
>  	struct cal_camerarx *phy = ctx->cal->phy[phy_id];
>  	u32 max_lanes;
>  
> -	regmap_field_write(phy->phy.fields[F_CAMMODE], 0);
> +	regmap_field_write(phy->fields[F_CAMMODE], 0);
>  	/* Always enable all lanes at the phy control level */
>  	max_lanes = (1 << cal_data_get_phy_max_lanes(ctx)) - 1;
> -	regmap_field_write(phy->phy.fields[F_LANEENABLE], max_lanes);
> +	regmap_field_write(phy->fields[F_LANEENABLE], max_lanes);
>  	/* F_CSI_MODE is not present on every architecture */
> -	if (phy->phy.fields[F_CSI_MODE])
> -		regmap_field_write(phy->phy.fields[F_CSI_MODE], 1);
> -	regmap_field_write(phy->phy.fields[F_CTRLCLKEN], 1);
> +	if (phy->fields[F_CSI_MODE])
> +		regmap_field_write(phy->fields[F_CSI_MODE], 1);
> +	regmap_field_write(phy->fields[F_CTRLCLKEN], 1);
>  }
>  
>  static void camerarx_phy_disable(struct cal_ctx *ctx)
> @@ -558,7 +555,7 @@ static void camerarx_phy_disable(struct cal_ctx *ctx)
>  	u32 phy_id = ctx->csi2_port;
>  	struct cal_camerarx *phy = ctx->cal->phy[phy_id];
>  
> -	regmap_field_write(phy->phy.fields[F_CTRLCLKEN], 0);
> +	regmap_field_write(phy->fields[F_CTRLCLKEN], 0);
>  }
>  
>  /*
> -- 
> Regards,
> 
> Laurent Pinchart
> 

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

* Re: [PATCH v1 027/107] media: ti-vpe: cal: Name all cal_camerarx pointers consistently
  2020-06-18 14:06   ` Benoit Parrot
@ 2020-06-18 14:15     ` Laurent Pinchart
  0 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-18 14:15 UTC (permalink / raw)
  To: Benoit Parrot; +Cc: linux-media, Tomi Valkeinen

Hi Benoit,

On Thu, Jun 18, 2020 at 09:06:09AM -0500, Benoit Parrot wrote:
> Laurent Pinchart <laurent.pinchart@ideasonboard.com> wrote on Mon [2020-Jun-15 02:58:24 +0300]:
> > Name all variables htat point to a cal_camerax instance 'phy' instead of
> > 'cc'. The name 'cc' refers to Camera Core, but is not commonly used in
> > the driver or in datasheets.
> > 
> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > ---
> >  drivers/media/platform/ti-vpe/cal.c | 102 ++++++++++++++--------------
> >  1 file changed, 51 insertions(+), 51 deletions(-)
> > 
> > diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
> > index 615e9d97e61f..8864a00a22b0 100644
> > --- a/drivers/media/platform/ti-vpe/cal.c
> > +++ b/drivers/media/platform/ti-vpe/cal.c
> > @@ -312,7 +312,8 @@ static const struct cal_data am654_cal_data = {
> >   * the CAMERARX instances. Instances of struct cal_dev are named cal through the
> >   * driver.
> >   *
> > - * The cal_camerarx structure represents one CAMERARX instance.
> > + * The cal_camerarx structure represents one CAMERARX instance. Instances of
> > + * cal_camerarx are named phy through the driver.
> >   *
> >   * The cal_ctx structure represents the combination of one CSI-2 context, one
> >   * processing context and one DMA context. Instance of struct cal_ctx are named
> > @@ -344,7 +345,7 @@ struct cal_dev {
> >  	u32			syscon_camerrx_offset;
> >  
> >  	/* Camera Core Module handle */
> > -	struct cal_camerarx	*cc[CAL_NUM_CSI2_PORTS];
> > +	struct cal_camerarx	*phy[CAL_NUM_CSI2_PORTS];
> >  
> >  	struct cal_ctx		*ctx[CAL_NUM_CONTEXT];
> >  };
> > @@ -361,7 +362,7 @@ struct cal_ctx {
> >  	struct v4l2_fwnode_endpoint	endpoint;
> >  
> >  	struct cal_dev		*cal;
> > -	struct cal_camerarx	*cc;
> > +	struct cal_camerarx	*phy;
> >  
> >  	/* v4l2_ioctl mutex */
> >  	struct mutex		mutex;
> > @@ -468,7 +469,7 @@ static u32 cal_data_get_num_csi2_phy(struct cal_dev *cal)
> >  }
> >  
> >  static int cal_camerarx_regmap_init(struct cal_dev *cal,
> > -				    struct cal_camerarx *cc,
> > +				    struct cal_camerarx *phy,
> >  				    unsigned int idx)
> >  {
> >  	const struct cal_camerarx_data *phy_data;
> > @@ -490,12 +491,12 @@ static int cal_camerarx_regmap_init(struct cal_dev *cal,
> >  		 * Here we update the reg offset with the
> >  		 * value found in DT
> >  		 */
> > -		cc->phy.fields[i] = devm_regmap_field_alloc(&cal->pdev->dev,
> > -							    cal->syscon_camerrx,
> > -							    field);
> > -		if (IS_ERR(cc->phy.fields[i])) {
> > +		phy->phy.fields[i] = devm_regmap_field_alloc(&cal->pdev->dev,
> > +							     cal->syscon_camerrx,
> > +							     field);
> 
> So we end up with these construct phy->phy.
> Is that really more readable?

I agree with you that it's not very nice. That's why it gets fixed
later, with the 'fields' field being moved from struct cal_camerarx_data
to struct cal_camerarx :-) I could try to rearrange the patches to avoid
this, but as it's an intermediary step only, it would be quite a bit of
rebase and conflict resolution to achieve the exact same result. Would
it be OK with you to keep this intermediate step as-is (assuming you
like the end result of course) ?

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH v1 030/107] media: ti-vpe: cal: Use dev_* print macros
  2020-06-14 23:58 ` [PATCH v1 030/107] media: ti-vpe: cal: Use dev_* print macros Laurent Pinchart
@ 2020-06-18 18:28   ` Benoit Parrot
  2020-06-19 15:22     ` Laurent Pinchart
  0 siblings, 1 reply; 150+ messages in thread
From: Benoit Parrot @ 2020-06-18 18:28 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Tomi Valkeinen

Hi Laurent,

Thanks you for the patch.

Laurent Pinchart <laurent.pinchart@ideasonboard.com> wrote on Mon [2020-Jun-15 02:58:27 +0300]:
> Use the dev_* print macros instead of the v4l2_* print macros. This
> prepares for a common print infrastructure that will also support the
> cal_camerarx instances.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>  drivers/media/platform/ti-vpe/cal.c | 17 ++++++++++-------
>  1 file changed, 10 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
> index e40967751aa4..e62089832713 100644
> --- a/drivers/media/platform/ti-vpe/cal.c
> +++ b/drivers/media/platform/ti-vpe/cal.c
> @@ -53,19 +53,22 @@ static unsigned debug;
>  module_param(debug, uint, 0644);
>  MODULE_PARM_DESC(debug, "activates debug info");
>  
> -#define cal_dbg(level, cal, fmt, arg...)	\
> -		v4l2_dbg(level, debug, &cal->v4l2_dev, fmt, ##arg)
> +#define cal_dbg(level, cal, fmt, arg...)				\
> +	do {								\
> +		if (debug >= (level))					\
> +			dev_dbg(&(cal)->pdev->dev, fmt, ##arg);		\
> +	} while (0)

The problem here with using dev_dbg is that you loose the ability to enable
or disable debug log at runtime. Which I find highly convenient.

With dev_dbg you have to compile with DEBUG defined or at the very least
DYNAMIC_DEBUG.

Benoit

>  #define cal_info(cal, fmt, arg...)	\
> -		v4l2_info(&cal->v4l2_dev, fmt, ##arg)
> +	dev_info(&(cal)->pdev->dev, fmt, ##arg)
>  #define cal_err(cal, fmt, arg...)	\
> -		v4l2_err(&cal->v4l2_dev, fmt, ##arg)
> +	dev_err(&(cal)->pdev->dev, fmt, ##arg)
>  
>  #define ctx_dbg(level, ctx, fmt, arg...)	\
> -		v4l2_dbg(level, debug, &ctx->v4l2_dev, fmt, ##arg)
> +	cal_dbg(level, (ctx)->cal, "ctx%u: " fmt, (ctx)->csi2_port, ##arg)
>  #define ctx_info(ctx, fmt, arg...)	\
> -		v4l2_info(&ctx->v4l2_dev, fmt, ##arg)
> +	cal_info((ctx)->cal, "ctx%u: " fmt, (ctx)->csi2_port, ##arg)
>  #define ctx_err(ctx, fmt, arg...)	\
> -		v4l2_err(&ctx->v4l2_dev, fmt, ##arg)
> +	cal_err((ctx)->cal, "ctx%u: " fmt, (ctx)->csi2_port, ##arg)
>  
>  #define CAL_NUM_CONTEXT 2
>  
> -- 
> Regards,
> 
> Laurent Pinchart
> 

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

* Re: [PATCH v1 068/107] media: ti-vpe: cal: Split media initialization and cleanup to functions
  2020-06-14 23:59 ` [PATCH v1 068/107] media: ti-vpe: cal: Split media initialization and cleanup to functions Laurent Pinchart
@ 2020-06-18 19:17   ` Benoit Parrot
  0 siblings, 0 replies; 150+ messages in thread
From: Benoit Parrot @ 2020-06-18 19:17 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Tomi Valkeinen

Hi Laurent,

Thank you for the patch.

Laurent Pinchart <laurent.pinchart@ideasonboard.com> wrote on Mon [2020-Jun-15 02:59:05 +0300]:
> Create four functions to handle initialization, cleanup, registration
> and unregistration of the V4L2 (and sonn media controller) objects:

s/sonn/soon/

Benoit
> 
> - init() is meant to be called early at probe time to initialize the
>   objects, before they get used from within the kernel
> 
> - cleanup() is the counterpart of init, and is meant to be called at the
>   end of the remove sequence to free all objects
> 
> - register() is meant to be called at the end of the probe sequence, to
>   register the userspace-facing devices
> 
> - unregister() is the counterpart of register, and is meant to be called
>   at the beginning for the remove sequence, to disallow access from
>   userspace
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>  drivers/media/platform/ti-vpe/cal.c | 120 +++++++++++++++++++++-------
>  1 file changed, 92 insertions(+), 28 deletions(-)
> 
> diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
> index 9fe8abfa1df9..6655c0051ccc 100644
> --- a/drivers/media/platform/ti-vpe/cal.c
> +++ b/drivers/media/platform/ti-vpe/cal.c
> @@ -2202,6 +2202,88 @@ static void cal_async_notifier_unregister(struct cal_dev *cal)
>  	v4l2_async_notifier_cleanup(&cal->notifier);
>  }
>  
> +/* ------------------------------------------------------------------
> + *	Media and V4L2 device handling
> + * ------------------------------------------------------------------
> + */
> +
> +/*
> + * Register user-facing devices. To be called at the end of the probe function
> + * when all resources are initialized and ready.
> + */
> +static int cal_media_register(struct cal_dev *cal)
> +{
> +	int ret;
> +
> +	/*
> +	 * Register the async notifier. This may trigger registration of the
> +	 * V4L2 video devices if all subdevs are ready.
> +	 */
> +	ret = cal_async_notifier_register(cal);
> +	if (ret)
> +		return ret;
> +
> +	return 0;
> +}
> +
> +/*
> + * Unregister the user-facing devices, but don't free memory yet. To be called
> + * at the beginning of the remove function, to disallow access from userspace.
> + */
> +static void cal_media_unregister(struct cal_dev *cal)
> +{
> +	unsigned int i;
> +
> +	/* Unregister all the V4L2 video devices. */
> +	for (i = 0; i < ARRAY_SIZE(cal->ctx); i++) {
> +		if (cal->ctx[i])
> +			cal_ctx_v4l2_unregister(cal->ctx[i]);
> +	}
> +
> +	cal_async_notifier_unregister(cal);
> +}
> +
> +/*
> + * Initialize the in-kernel objects. To be called at the beginning of the probe
> + * function, before the V4L2 device is used by the driver.
> + */
> +static int cal_media_init(struct cal_dev *cal)
> +{
> +	int ret;
> +
> +	/*
> +	 * Initialize the V4L2 device (despite the function name, this performs
> +	 * initialization, not registration).
> +	 */
> +	ret = v4l2_device_register(&cal->pdev->dev, &cal->v4l2_dev);
> +	if (ret) {
> +		cal_err(cal, "Failed to register V4L2 device\n");
> +		return ret;
> +	}
> +
> +	vb2_dma_contig_set_max_seg_size(&cal->pdev->dev, DMA_BIT_MASK(32));
> +
> +	return 0;
> +}
> +
> +/*
> + * Cleanup the in-kernel objects, freeing memory. To be called at the very end
> + * of the remove sequence, when nothing (including userspace) can access the
> + * objects anymore.
> + */
> +static void cal_media_cleanup(struct cal_dev *cal)
> +{
> +	unsigned int i;
> +
> +	for (i = 0; i < ARRAY_SIZE(cal->ctx); i++) {
> +		if (cal->ctx[i])
> +			cal_ctx_v4l2_cleanup(cal->ctx[i]);
> +	}
> +
> +	v4l2_device_unregister(&cal->v4l2_dev);
> +	vb2_dma_contig_clear_max_seg_size(&cal->pdev->dev);
> +}
> +
>  /* ------------------------------------------------------------------
>   *	Initialization and module stuff
>   * ------------------------------------------------------------------
> @@ -2328,12 +2410,10 @@ static int cal_probe(struct platform_device *pdev)
>  		}
>  	}
>  
> -	/* Register the V4L2 device. */
> -	ret = v4l2_device_register(&pdev->dev, &cal->v4l2_dev);
> -	if (ret) {
> -		cal_err(cal, "Failed to register V4L2 device\n");
> +	/* Initialize the media device. */
> +	ret = cal_media_init(cal);
> +	if (ret < 0)
>  		goto error_camerarx;
> -	}
>  
>  	/* Create contexts. */
>  	for (i = 0; i < cal_data_get_num_csi2_phy(cal); ++i)
> @@ -2342,11 +2422,9 @@ static int cal_probe(struct platform_device *pdev)
>  	if (!cal->ctx[0] && !cal->ctx[1]) {
>  		cal_err(cal, "Neither port is configured, no point in staying up\n");
>  		ret = -ENODEV;
> -		goto error_v4l2;
> +		goto error_media;
>  	}
>  
> -	vb2_dma_contig_set_max_seg_size(&pdev->dev, DMA_BIT_MASK(32));
> -
>  	/* Read the revision and hardware info to verify hardware access. */
>  	pm_runtime_enable(&pdev->dev);
>  	ret = pm_runtime_get_sync(&pdev->dev);
> @@ -2356,16 +2434,14 @@ static int cal_probe(struct platform_device *pdev)
>  	cal_get_hwinfo(cal);
>  	pm_runtime_put_sync(&pdev->dev);
>  
> -	/* Register the async notifier. */
> -	ret = cal_async_notifier_register(cal);
> +	/* Register the media device. */
> +	ret = cal_media_register(cal);
>  	if (ret)
>  		goto error_pm_runtime;
>  
>  	return 0;
>  
>  error_pm_runtime:
> -	vb2_dma_contig_clear_max_seg_size(&pdev->dev);
> -
>  	pm_runtime_disable(&pdev->dev);
>  	for (i = 0; i < ARRAY_SIZE(cal->ctx); i++) {
>  		ctx = cal->ctx[i];
> @@ -2373,8 +2449,8 @@ static int cal_probe(struct platform_device *pdev)
>  			cal_ctx_v4l2_cleanup(ctx);
>  	}
>  
> -error_v4l2:
> -	v4l2_device_unregister(&cal->v4l2_dev);
> +error_media:
> +	cal_media_cleanup(cal);
>  
>  error_camerarx:
>  	for (i = 0; i < ARRAY_SIZE(cal->phy); i++)
> @@ -2392,24 +2468,14 @@ static int cal_remove(struct platform_device *pdev)
>  
>  	pm_runtime_get_sync(&pdev->dev);
>  
> -	cal_async_notifier_unregister(cal);
> -
> -	for (i = 0; i < ARRAY_SIZE(cal->ctx); i++) {
> -		if (cal->ctx[i])
> -			cal_ctx_v4l2_unregister(cal->ctx[i]);
> -	}
> +	cal_media_unregister(cal);
>  
>  	for (i = 0; i < ARRAY_SIZE(cal->phy); i++) {
>  		if (cal->phy[i])
>  			cal_camerarx_disable(cal->phy[i]);
>  	}
>  
> -	for (i = 0; i < ARRAY_SIZE(cal->ctx); i++) {
> -		if (cal->ctx[i])
> -			cal_ctx_v4l2_cleanup(cal->ctx[i]);
> -	}
> -
> -	v4l2_device_unregister(&cal->v4l2_dev);
> +	cal_media_cleanup(cal);
>  
>  	for (i = 0; i < ARRAY_SIZE(cal->phy); i++)
>  		cal_camerarx_destroy(cal->phy[i]);
> @@ -2417,8 +2483,6 @@ static int cal_remove(struct platform_device *pdev)
>  	pm_runtime_put_sync(&pdev->dev);
>  	pm_runtime_disable(&pdev->dev);
>  
> -	vb2_dma_contig_clear_max_seg_size(&pdev->dev);
> -
>  	return 0;
>  }
>  
> -- 
> Regards,
> 
> Laurent Pinchart
> 

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

* Re: [PATCH v1 082/107] media: ti-vpe: cal: Move CAL I/O accessors to cal.h
  2020-06-14 23:59 ` [PATCH v1 082/107] media: ti-vpe: cal: Move CAL I/O accessors to cal.h Laurent Pinchart
  2020-06-15  2:50     ` kernel test robot
@ 2020-06-19  4:18   ` Ezequiel Garcia
  2020-06-19 15:40     ` Laurent Pinchart
  1 sibling, 1 reply; 150+ messages in thread
From: Ezequiel Garcia @ 2020-06-19  4:18 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Tomi Valkeinen, Benoit Parrot

Hello Laurent,

On Sun, 14 Jun 2020 at 21:01, Laurent Pinchart
<laurent.pinchart@ideasonboard.com> wrote:
>
> To prepare for the split of the camerarx code to a separate file, move
> the CAL I/O accessors to cal.h. This requires renaming the accessors
> with a cal_prefix, as the current names are too generic and prone to
> namespace clashes.
>
> The reg_read() and read_write() macros, that cover both CAL and CAMERARX
> register access, are split in two groups of inline functions, one for
> CAL access and one for CAMERARX access.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>  drivers/media/platform/ti-vpe/cal-video.c |   1 -
>  drivers/media/platform/ti-vpe/cal.c       | 280 ++++++++++------------
>  drivers/media/platform/ti-vpe/cal.h       |  36 +++
>  3 files changed, 168 insertions(+), 149 deletions(-)
>
> diff --git a/drivers/media/platform/ti-vpe/cal-video.c b/drivers/media/platform/ti-vpe/cal-video.c
> index 82b32a2f9db5..df472a175e83 100644
> --- a/drivers/media/platform/ti-vpe/cal-video.c
> +++ b/drivers/media/platform/ti-vpe/cal-video.c
> @@ -9,7 +9,6 @@
>   *     Laurent Pinchart <laurent.pinchart@ideasonboard.com>
>   */
>
> -#include <linux/bitfield.h>
>  #include <linux/delay.h>
>  #include <linux/ioctl.h>
>  #include <linux/pm_runtime.h>
> diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
> index 0bc02ba52b59..abeded3b5e6c 100644
> --- a/drivers/media/platform/ti-vpe/cal.c
> +++ b/drivers/media/platform/ti-vpe/cal.c
> @@ -9,11 +9,9 @@
>   *     Laurent Pinchart <laurent.pinchart@ideasonboard.com>
>   */
>
> -#include <linux/bitfield.h>
>  #include <linux/clk.h>
>  #include <linux/delay.h>
>  #include <linux/interrupt.h>
> -#include <linux/io.h>
>  #include <linux/mfd/syscon.h>
>  #include <linux/module.h>
>  #include <linux/of_device.h>
> @@ -133,33 +131,6 @@ static const struct cal_data am654_cal_data = {
>   * ------------------------------------------------------------------
>   */
>
> -#define reg_read(dev, offset) ioread32(dev->base + offset)
> -#define reg_write(dev, offset, val) iowrite32(val, dev->base + offset)
> -
> -static inline u32 reg_read_field(struct cal_dev *cal, u32 offset, u32 mask)
> -{
> -       return FIELD_GET(mask, reg_read(cal, offset));
> -}
> -
> -static inline void reg_write_field(struct cal_dev *cal, u32 offset, u32 value,
> -                                  u32 mask)
> -{
> -       u32 val = reg_read(cal, offset);
> -
> -       val &= ~mask;
> -       val |= FIELD_PREP(mask, value);
> -       reg_write(cal, offset, val);
> -}
> -
> -static inline void set_field(u32 *valp, u32 field, u32 mask)
> -{
> -       u32 val = *valp;
> -
> -       val &= ~mask;
> -       val |= (field << __ffs(mask)) & mask;
> -       *valp = val;
> -}
> -

Slightly unrelated, have you considered moving all of these to regmap?

Perhaps it will make the code more maintainable.

Regards,
Ezequiel

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

* Re: [PATCH v1 107/107] media: ti-vpe: cal: Implement media controller centric API
  2020-06-14 23:59 ` [PATCH v1 107/107] media: ti-vpe: cal: Implement media controller centric API Laurent Pinchart
@ 2020-06-19 14:46   ` Benoit Parrot
  2020-06-19 15:58     ` Laurent Pinchart
  0 siblings, 1 reply; 150+ messages in thread
From: Benoit Parrot @ 2020-06-19 14:46 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Tomi Valkeinen

Hi Laurent,

Thank you for the patch.

Laurent Pinchart <laurent.pinchart@ideasonboard.com> wrote on Mon [2020-Jun-15 02:59:44 +0300]:
> The CAL driver is video node centric, it controls the whole device
> through the video device nodes. This limits the possible use cases as it
> can't support sources that are more complex than a single subdev. To
> support more complex hardware pipelines, implement support for the media
> controller centric API. The exposed API can be selected through a module
> parameter.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>  drivers/media/platform/ti-vpe/cal-camerarx.c |   1 +
>  drivers/media/platform/ti-vpe/cal-video.c    | 358 ++++++++++++++-----
>  drivers/media/platform/ti-vpe/cal.c          |  10 +-
>  drivers/media/platform/ti-vpe/cal.h          |   2 +
>  4 files changed, 289 insertions(+), 82 deletions(-)
> 
> diff --git a/drivers/media/platform/ti-vpe/cal-camerarx.c b/drivers/media/platform/ti-vpe/cal-camerarx.c
> index 2e7a3bc716cf..014ca46509db 100644
> --- a/drivers/media/platform/ti-vpe/cal-camerarx.c
> +++ b/drivers/media/platform/ti-vpe/cal-camerarx.c
> @@ -818,6 +818,7 @@ struct cal_camerarx *cal_camerarx_create(struct cal_dev *cal,
>  	sd = &phy->subdev;
>  	v4l2_subdev_init(sd, &cal_camerarx_subdev_ops);
>  	sd->entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
> +	sd->flags = V4L2_SUBDEV_FL_HAS_DEVNODE;
>  	snprintf(sd->name, sizeof(sd->name), "CAMERARX%u", instance);
>  	sd->dev = cal->dev;
>  
> diff --git a/drivers/media/platform/ti-vpe/cal-video.c b/drivers/media/platform/ti-vpe/cal-video.c
> index 0f8702bd77db..5f9cd449f027 100644
> --- a/drivers/media/platform/ti-vpe/cal-video.c
> +++ b/drivers/media/platform/ti-vpe/cal-video.c
> @@ -40,40 +40,10 @@ static char *fourcc_to_str(u32 fmt)
>  }
>  
>  /* ------------------------------------------------------------------
> - *	V4L2 Video IOCTLs
> + *	V4L2 Common IOCTLs
>   * ------------------------------------------------------------------
>   */
>  
> -static const struct cal_format_info *find_format_by_pix(struct cal_ctx *ctx,
> -							u32 pixelformat)
> -{
> -	const struct cal_format_info *fmtinfo;
> -	unsigned int k;
> -
> -	for (k = 0; k < ctx->num_active_fmt; k++) {
> -		fmtinfo = ctx->active_fmt[k];
> -		if (fmtinfo->fourcc == pixelformat)
> -			return fmtinfo;
> -	}
> -
> -	return NULL;
> -}
> -
> -static const struct cal_format_info *find_format_by_code(struct cal_ctx *ctx,
> -							 u32 code)
> -{
> -	const struct cal_format_info *fmtinfo;
> -	unsigned int k;
> -
> -	for (k = 0; k < ctx->num_active_fmt; k++) {
> -		fmtinfo = ctx->active_fmt[k];
> -		if (fmtinfo->code == code)
> -			return fmtinfo;
> -	}
> -
> -	return NULL;
> -}
> -
>  static int cal_querycap(struct file *file, void *priv,
>  			struct v4l2_capability *cap)
>  {
> @@ -87,6 +57,51 @@ static int cal_querycap(struct file *file, void *priv,
>  	return 0;
>  }
>  
> +static int cal_g_fmt_vid_cap(struct file *file, void *priv,
> +			     struct v4l2_format *f)
> +{
> +	struct cal_ctx *ctx = video_drvdata(file);
> +
> +	*f = ctx->v_fmt;
> +
> +	return 0;
> +}
> +
> +/* ------------------------------------------------------------------
> + *	V4L2 Video Node Centric IOCTLs
> + * ------------------------------------------------------------------
> + */
> +
> +static const struct cal_format_info *find_format_by_pix(struct cal_ctx *ctx,
> +							u32 pixelformat)
> +{
> +	const struct cal_format_info *fmtinfo;
> +	unsigned int k;
> +
> +	for (k = 0; k < ctx->num_active_fmt; k++) {
> +		fmtinfo = ctx->active_fmt[k];
> +		if (fmtinfo->fourcc == pixelformat)
> +			return fmtinfo;
> +	}
> +
> +	return NULL;
> +}
> +
> +static const struct cal_format_info *find_format_by_code(struct cal_ctx *ctx,
> +							 u32 code)
> +{
> +	const struct cal_format_info *fmtinfo;
> +	unsigned int k;
> +
> +	for (k = 0; k < ctx->num_active_fmt; k++) {
> +		fmtinfo = ctx->active_fmt[k];
> +		if (fmtinfo->code == code)
> +			return fmtinfo;
> +	}
> +
> +	return NULL;
> +}
> +
>  static int cal_enum_fmt_vid_cap(struct file *file, void  *priv,
>  				struct v4l2_fmtdesc *f)
>  {
> @@ -174,16 +189,6 @@ static void cal_calc_format_size(struct cal_ctx *ctx,
>  		f->fmt.pix.bytesperline, f->fmt.pix.sizeimage);
>  }
>  
> -static int cal_g_fmt_vid_cap(struct file *file, void *priv,
> -			     struct v4l2_format *f)
> -{
> -	struct cal_ctx *ctx = video_drvdata(file);
> -
> -	*f = ctx->v_fmt;
> -
> -	return 0;
> -}
> -
>  static int cal_try_fmt_vid_cap(struct file *file, void *priv,
>  			       struct v4l2_format *f)
>  {
> @@ -383,17 +388,7 @@ static int cal_enum_frameintervals(struct file *file, void *priv,
>  	return 0;
>  }
>  
> -static const struct v4l2_file_operations cal_fops = {
> -	.owner		= THIS_MODULE,
> -	.open           = v4l2_fh_open,
> -	.release        = vb2_fop_release,
> -	.read           = vb2_fop_read,
> -	.poll		= vb2_fop_poll,
> -	.unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */
> -	.mmap           = vb2_fop_mmap,
> -};
> -
> -static const struct v4l2_ioctl_ops cal_ioctl_ops = {
> +static const struct v4l2_ioctl_ops cal_ioctl_video_ops = {
>  	.vidioc_querycap      = cal_querycap,
>  	.vidioc_enum_fmt_vid_cap  = cal_enum_fmt_vid_cap,
>  	.vidioc_g_fmt_vid_cap     = cal_g_fmt_vid_cap,
> @@ -419,7 +414,153 @@ static const struct v4l2_ioctl_ops cal_ioctl_ops = {
>  };
>  
>  /* ------------------------------------------------------------------
> - *	videobuf2 Operations
> + *	V4L2 Media Controller Centric IOCTLs
> + * ------------------------------------------------------------------
> + */
> +
> +static int cal_mc_enum_fmt_vid_cap(struct file *file, void  *priv,
> +				   struct v4l2_fmtdesc *f)
> +{
> +	if (f->index >= cal_num_formats)
> +		return -EINVAL;
> +
> +	f->pixelformat = cal_formats[f->index].fourcc;
> +	f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
> +
> +	return 0;
> +}
> +
> +static void cal_mc_try_fmt(struct cal_ctx *ctx, struct v4l2_format *f,
> +			   const struct cal_format_info **info)
> +{
> +	struct v4l2_pix_format *format = &f->fmt.pix;
> +	const struct cal_format_info *fmtinfo;
> +	unsigned int bpp;
> +
> +	/*
> +	 * Default to the first format is the requested pixel format code isn't
> +	 * supported.
> +	 */
> +	fmtinfo = cal_format_by_fourcc(f->fmt.pix.pixelformat);
> +	if (!fmtinfo)
> +		fmtinfo = &cal_formats[0];
> +
> +	/*
> +	 * Clamp the size, update the pixel format. The field and colorspace are
> +	 * accepted as-is, except for V4L2_FIELD_ANY that is turned into
> +	 * V4L2_FIELD_NONE.
> +	 */
> +	bpp = ALIGN(fmtinfo->bpp, 8);
> +
> +	format->width = clamp_t(unsigned int, format->width,
> +				CAL_MIN_WIDTH_BYTES * 8 / bpp,
> +				CAL_MAX_WIDTH_BYTES * 8 / bpp);
> +	format->height = clamp_t(unsigned int, format->height,
> +				 CAL_MIN_HEIGHT_LINES, CAL_MAX_HEIGHT_LINES);
> +	format->pixelformat = fmtinfo->fourcc;
> +
> +	if (format->field == V4L2_FIELD_ANY)
> +		format->field = V4L2_FIELD_NONE;
> +
> +	/*
> +	 * Calculate the number of bytes per line and the image size. The
> +	 * hardware stores the stride as a number of 16 bytes words, in a
> +	 * signed 15-bit value. Only 14 bits are thus usable.
> +	 */
> +	format->bytesperline = ALIGN(clamp(format->bytesperline,
> +					   format->width * bpp / 8,
> +					   ((1U << 14) - 1) * 16), 16);
> +
> +	format->sizeimage = format->height * format->bytesperline;
> +
> +	if (info)
> +		*info = fmtinfo;
> +
> +	ctx_dbg(3, ctx, "%s: %s %ux%u (bytesperline %u sizeimage %u)\n",
> +		__func__, fourcc_to_str(format->pixelformat),
> +		format->width, format->height,
> +		format->bytesperline, format->sizeimage);
> +}
> +
> +static int cal_mc_try_fmt_vid_cap(struct file *file, void *priv,
> +				  struct v4l2_format *f)
> +{
> +	struct cal_ctx *ctx = video_drvdata(file);
> +
> +	cal_mc_try_fmt(ctx, f, NULL);
> +	return 0;
> +}
> +
> +static int cal_mc_s_fmt_vid_cap(struct file *file, void *priv,
> +				struct v4l2_format *f)
> +{
> +	struct cal_ctx *ctx = video_drvdata(file);
> +	const struct cal_format_info *fmtinfo;
> +
> +	if (vb2_is_busy(&ctx->vb_vidq)) {
> +		ctx_dbg(3, ctx, "%s device busy\n", __func__);
> +		return -EBUSY;
> +	}
> +
> +	cal_mc_try_fmt(ctx, f, &fmtinfo);
> +
> +	ctx->v_fmt = *f;
> +	ctx->fmtinfo = fmtinfo;
> +
> +	return 0;
> +}
> +
> +static int cal_mc_enum_framesizes(struct file *file, void *fh,
> +				  struct v4l2_frmsizeenum *fsize)
> +{
> +	struct cal_ctx *ctx = video_drvdata(file);
> +	const struct cal_format_info *fmtinfo;
> +	unsigned int bpp;
> +
> +	if (fsize->index > 0)
> +		return -EINVAL;
> +
> +	fmtinfo = cal_format_by_fourcc(fsize->pixel_format);
> +	if (!fmtinfo) {
> +		ctx_dbg(3, ctx, "Invalid pixel format 0x%08x\n",
> +			fsize->pixel_format);
> +		return -EINVAL;
> +	}
> +
> +	bpp = ALIGN(fmtinfo->bpp, 8);
> +
> +	fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
> +	fsize->stepwise.min_width = CAL_MIN_WIDTH_BYTES * 8 / bpp;
> +	fsize->stepwise.max_width = CAL_MAX_WIDTH_BYTES * 8 / bpp;
> +	fsize->stepwise.step_width = 64 / bpp;
> +	fsize->stepwise.min_height = CAL_MIN_HEIGHT_LINES;
> +	fsize->stepwise.max_height = CAL_MAX_HEIGHT_LINES;
> +	fsize->stepwise.step_height = 1;
> +
> +	return 0;
> +}
> +
> +static const struct v4l2_ioctl_ops cal_ioctl_mc_ops = {
> +	.vidioc_querycap      = cal_querycap,
> +	.vidioc_enum_fmt_vid_cap  = cal_mc_enum_fmt_vid_cap,
> +	.vidioc_g_fmt_vid_cap     = cal_g_fmt_vid_cap,
> +	.vidioc_try_fmt_vid_cap   = cal_mc_try_fmt_vid_cap,
> +	.vidioc_s_fmt_vid_cap     = cal_mc_s_fmt_vid_cap,
> +	.vidioc_enum_framesizes   = cal_mc_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,
> +	.vidioc_log_status    = v4l2_ctrl_log_status,
> +};
> +
> +/* ------------------------------------------------------------------
> + *	videobuf2 Common Operations
>   * ------------------------------------------------------------------
>   */
>  
> @@ -505,6 +646,26 @@ static void cal_release_buffers(struct cal_ctx *ctx,
>  	spin_unlock_irq(&ctx->dma.lock);
>  }
>  
> +/* ------------------------------------------------------------------
> + *	videobuf2 Operations
> + * ------------------------------------------------------------------
> + */
> +
> +static int cal_video_check_format(struct cal_ctx *ctx)
> +{
> +	const struct v4l2_mbus_framefmt *format;
> +
> +	format = &ctx->phy->formats[CAL_CAMERARX_PAD_SOURCE];
> +
> +	if (ctx->fmtinfo->code != format->code ||
> +	    ctx->v_fmt.fmt.pix.height != format->height ||
> +	    ctx->v_fmt.fmt.pix.width != format->width ||
> +	    ctx->v_fmt.fmt.pix.field != format->field)
> +		return -EPIPE;
> +
> +	return 0;
> +}
> +
>  static int cal_start_streaming(struct vb2_queue *vq, unsigned int count)
>  {
>  	struct cal_ctx *ctx = vb2_get_drv_priv(vq);
> @@ -512,6 +673,23 @@ static int cal_start_streaming(struct vb2_queue *vq, unsigned int count)
>  	dma_addr_t addr;
>  	int ret;
>  
> +	ret = media_pipeline_start(&ctx->vdev.entity, &ctx->phy->pipe);
> +	if (ret < 0) {
> +		ctx_err(ctx, "Failed to start media pipeline: %d\n", ret);
> +		return ret;
> +	}
> +
> +	/*
> +	 * Verify that the currently configured format matches the output of
> +	 * the connected CAMERARX.
> +	 */
> +	ret = cal_video_check_format(ctx);
> +	if (ret < 0) {
> +		ctx_dbg(3, ctx,
> +			"Format mismatch between CAMERARX and video node\n");
> +		goto error_pipeline;
> +	}
> +
>  	spin_lock_irq(&ctx->dma.lock);
>  	buf = list_first_entry(&ctx->dma.queue, struct cal_buffer, list);
>  	ctx->dma.pending = buf;
> @@ -527,18 +705,21 @@ static int cal_start_streaming(struct vb2_queue *vq, unsigned int count)
>  
>  	ret = v4l2_subdev_call(&ctx->phy->subdev, video, s_stream, 1);
>  	if (ret)
> -		goto err;
> +		goto error_stop;
>  
>  	if (cal_debug >= 4)
>  		cal_quickdump_regs(ctx->cal);
>  
>  	return 0;
>  
> -err:
> +error_stop:
>  	cal_ctx_stop(ctx);
>  	pm_runtime_put_sync(ctx->cal->dev);
>  
> +error_pipeline:
> +	media_pipeline_stop(&ctx->vdev.entity);
>  	cal_release_buffers(ctx, VB2_BUF_STATE_QUEUED);
> +
>  	return ret;
>  }
>  
> @@ -553,6 +734,8 @@ static void cal_stop_streaming(struct vb2_queue *vq)
>  	pm_runtime_put_sync(ctx->cal->dev);
>  
>  	cal_release_buffers(ctx, VB2_BUF_STATE_ERROR);
> +
> +	media_pipeline_stop(&ctx->vdev.entity);
>  }
>  
>  static const struct vb2_ops cal_video_qops = {
> @@ -570,13 +753,14 @@ static const struct vb2_ops cal_video_qops = {
>   * ------------------------------------------------------------------
>   */
>  
> -static const struct video_device cal_videodev = {
> -	.name		= CAL_MODULE_NAME,
> -	.fops		= &cal_fops,
> -	.ioctl_ops	= &cal_ioctl_ops,
> -	.minor		= -1,
> -	.release	= video_device_release_empty,
> -	.device_caps	= V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING,
> +static const struct v4l2_file_operations cal_fops = {
> +	.owner		= THIS_MODULE,
> +	.open           = v4l2_fh_open,
> +	.release        = vb2_fop_release,
> +	.read           = vb2_fop_read,
> +	.poll		= vb2_fop_poll,
> +	.unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */
> +	.mmap           = vb2_fop_mmap,
>  };
>  
>  static int cal_ctx_v4l2_init_formats(struct cal_ctx *ctx)
> @@ -650,19 +834,22 @@ static int cal_ctx_v4l2_init_formats(struct cal_ctx *ctx)
>  
>  int cal_ctx_v4l2_register(struct cal_ctx *ctx)
>  {
> -	struct v4l2_ctrl_handler *hdl = &ctx->ctrl_handler;
>  	struct video_device *vfd = &ctx->vdev;
>  	int ret;
>  
> -	ret = cal_ctx_v4l2_init_formats(ctx);
> -	if (ret)
> -		return ret;
> +	if (!cal_mc_api) {
> +		struct v4l2_ctrl_handler *hdl = &ctx->ctrl_handler;
>  
> -	ret = v4l2_ctrl_add_handler(hdl, ctx->phy->sensor->ctrl_handler, NULL,
> -				    true);
> -	if (ret < 0) {
> -		ctx_err(ctx, "Failed to add sensor ctrl handler\n");
> -		return ret;
> +		ret = cal_ctx_v4l2_init_formats(ctx);
> +		if (ret)
> +			return ret;
> +
> +		ret = v4l2_ctrl_add_handler(hdl, ctx->phy->sensor->ctrl_handler,
> +					    NULL, true);
> +		if (ret < 0) {
> +			ctx_err(ctx, "Failed to add sensor ctrl handler\n");
> +			return ret;
> +		}
>  	}
>  
>  	ret = video_register_device(vfd, VFL_TYPE_VIDEO, cal_video_nr);
> @@ -699,7 +886,6 @@ void cal_ctx_v4l2_unregister(struct cal_ctx *ctx)
>  
>  int cal_ctx_v4l2_init(struct cal_ctx *ctx)
>  {
> -	struct v4l2_ctrl_handler *hdl = &ctx->ctrl_handler;
>  	struct video_device *vfd = &ctx->vdev;
>  	struct vb2_queue *q = &ctx->vb_vidq;
>  	int ret;
> @@ -726,10 +912,14 @@ int cal_ctx_v4l2_init(struct cal_ctx *ctx)
>  		return ret;
>  
>  	/* Initialize the video device and media entity. */
> -	*vfd = cal_videodev;
> +	vfd->fops = &cal_fops;
> +	vfd->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING
> +			 | (cal_mc_api ? V4L2_CAP_IO_MC : 0);
>  	vfd->v4l2_dev = &ctx->cal->v4l2_dev;
>  	vfd->queue = q;
>  	snprintf(vfd->name, sizeof(vfd->name), "CAL output %u", ctx->index);
> +	vfd->release = video_device_release_empty;
> +	vfd->ioctl_ops = cal_mc_api ? &cal_ioctl_mc_ops : &cal_ioctl_video_ops;
>  	vfd->lock = &ctx->mutex;
>  	video_set_drvdata(vfd, ctx);
>  
> @@ -738,15 +928,19 @@ int cal_ctx_v4l2_init(struct cal_ctx *ctx)
>  	if (ret < 0)
>  		return ret;
>  
> -	/* Initialize the control handler. */
> -	ret = v4l2_ctrl_handler_init(hdl, 11);
> -	if (ret < 0) {
> -		ctx_err(ctx, "Failed to init ctrl handler\n");
> -		goto error;
> +	if (!cal_mc_api) {
> +		/* Initialize the control handler. */
> +		struct v4l2_ctrl_handler *hdl = &ctx->ctrl_handler;
> +
> +		ret = v4l2_ctrl_handler_init(hdl, 11);
> +		if (ret < 0) {
> +			ctx_err(ctx, "Failed to init ctrl handler\n");
> +			goto error;
> +		}
> +
> +		vfd->ctrl_handler = hdl;
>  	}
>  
> -	vfd->ctrl_handler = hdl;
> -
>  	return 0;
>  
>  error:
> @@ -756,6 +950,8 @@ int cal_ctx_v4l2_init(struct cal_ctx *ctx)
>  
>  void cal_ctx_v4l2_cleanup(struct cal_ctx *ctx)
>  {
> -	v4l2_ctrl_handler_free(&ctx->ctrl_handler);
> +	if (!cal_mc_api)
> +		v4l2_ctrl_handler_free(&ctx->ctrl_handler);
> +
>  	media_entity_cleanup(&ctx->vdev.entity);
>  }
> diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
> index f97c213f716f..caea3e129c87 100644
> --- a/drivers/media/platform/ti-vpe/cal.c
> +++ b/drivers/media/platform/ti-vpe/cal.c
> @@ -43,6 +43,10 @@ unsigned int cal_debug;
>  module_param_named(debug, cal_debug, uint, 0644);
>  MODULE_PARM_DESC(debug, "activates debug info");
>  
> +bool cal_mc_api;
> +module_param_named(mc_api, cal_mc_api, bool, 0444);
> +MODULE_PARM_DESC(debug, "activates MC API");

Shouldn't this be 
	MODULE_PARM_DESC(mc_api, "activates MC API");
instead?

Benoit

> +
>  /* ------------------------------------------------------------------
>   *	Format Handling
>   * ------------------------------------------------------------------
> @@ -655,13 +659,17 @@ static int cal_async_notifier_complete(struct v4l2_async_notifier *notifier)
>  {
>  	struct cal_dev *cal = container_of(notifier, struct cal_dev, notifier);
>  	unsigned int i;
> +	int ret = 0;
>  
>  	for (i = 0; i < ARRAY_SIZE(cal->ctx); ++i) {
>  		if (cal->ctx[i])
>  			cal_ctx_v4l2_register(cal->ctx[i]);
>  	}
>  
> -	return 0;
> +	if (cal_mc_api)
> +		ret = v4l2_device_register_subdev_nodes(&cal->v4l2_dev);
> +
> +	return ret;
>  }
>  
>  static const struct v4l2_async_notifier_operations cal_async_notifier_ops = {
> diff --git a/drivers/media/platform/ti-vpe/cal.h b/drivers/media/platform/ti-vpe/cal.h
> index 036b944c3862..f6b4c9a73aab 100644
> --- a/drivers/media/platform/ti-vpe/cal.h
> +++ b/drivers/media/platform/ti-vpe/cal.h
> @@ -160,6 +160,7 @@ struct cal_camerarx {
>  	struct device_node	*sensor_ep_node;
>  	struct device_node	*sensor_node;
>  	struct v4l2_subdev	*sensor;
> +	struct media_pipeline	pipe;
>  
>  	struct v4l2_subdev	subdev;
>  	struct media_pad	pads[2];
> @@ -224,6 +225,7 @@ struct cal_ctx {
>  
>  extern unsigned int cal_debug;
>  extern int cal_video_nr;
> +extern bool cal_mc_api;
>  
>  #define cal_dbg(level, cal, fmt, arg...)				\
>  	do {								\
> -- 
> Regards,
> 
> Laurent Pinchart
> 

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

* Re: [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support
  2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
                   ` (107 preceding siblings ...)
  2020-06-16 11:43 ` [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Tomi Valkeinen
@ 2020-06-19 14:53 ` Benoit Parrot
  2020-06-19 14:57   ` Benoit Parrot
  108 siblings, 1 reply; 150+ messages in thread
From: Benoit Parrot @ 2020-06-19 14:53 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Tomi Valkeinen

Hi Laurent,

Except for patch 56, 78, 84 and 107.

Reviewed-by: Benoit Parrot <bparrot@ti.com>

Benoit

Laurent Pinchart <laurent.pinchart@ideasonboard.com> wrote on Mon [2020-Jun-15 02:57:57 +0300]:
> Hello,
> 
> This small patch series adds media controller support to the ti-cal
> driver.
> 
> The end goal is to support pipelines where the image source is more
> complex than a single subdev (for instance a SMIA++-compliant sensor, or
> an FPD-Link source made of a camera, a serializer and a deserializer),
> and to prepare for support of multiple hardware contexts, needed for
> CSI-2 virtual channel and data type multiplexing support. These use
> cases require configuration of the external pipeline from userspace, and
> thus need support for the media controller and V4L2 subdev userspace
> APIs.
> 
> The series starts with miscellaneous cleanups and refactoring, in
> patches 001/107 to 083/107. Worth being noted is the split of the large
> driver into multiple files, with patch 081/107 moving video node
> handling to cal-video.c and patch 083/107 moving CAMERARX handling to
> cal-camerarx.c.
> 
> Interleaved with more cleanup and refactoring, patch 084/107 creates
> subdevs for the CAMERARX instances, patch 090/107 implements the subdev
> operations, and patch 091/107 uses the subdev .set_fmt() and .s_stream()
> operations to configure and control the CAMERARX. 
> 
> More refactoring and cleanup follow in patches 092/107 to 106/107, until
> patch 107/107 that adds media controller support. As the existing video
> node centric API needs to be preserved to avoid breaking userspace
> applications, a module parameter is added to enable the media controller
> API. Changes are otherwise fairly limited, and mostly involve the
> implementation of MC-centric V4L2 ioctl handlers (which are far simpler
> than their video node centric equivalents), additional pipeline
> validation in the vb2 start streaming handler, and disabling control
> handling in the video nodes.
> 
> The patches have been tested on an AM65x EVM with an OV5640 camera
> module with the yavta test application, both in MC mode and in legacy
> mode. As the ov5640 driver sets a default format identical to the
> default of the ti-cal driver, capture in both modes can simply be tested
> with
> 
> 	yavta -f UYVY -s 640x480 -c10 --requeue-last /dev/video0
> 
> without requiring manual pipeline setup through the media controller
> API. Usage of other formats or resolutions require pipeline
> configuration before capture.
> 
> Laurent Pinchart (107):
>   media: ti-vpe: cal: Sort headers alphabetically
>   media: ti-vpe: cal: Avoid function forward declaration
>   media: ti-vpe: cal: Decouple CSI2 port and CPORT
>   media: ti-vpe: cal: Index CSI-2 port starting at 0
>   media: ti-vpe: cal: Index IRQ registersstarting at 0
>   media: ti-vpe: cal: Merge all status variables in IRQ handler
>   media: ti-vpe: cal: Inline CAL_VERSION macro in its only user
>   media: ti-vpe: cal: Turn reg_(read|write)_field() into inline
>     functions
>   media: ti-vpe: cal: Make cal_formats array const
>   media: ti-vpe: cal: Remove needless variable initialization
>   media: ti-vpe: cal: Remove needless casts
>   media: ti-vpe: cal: Turn boolean variable into bool
>   media: ti-vpe: cal: Make loop indices unsigned where applicable
>   media: ti-vpe: cal: Embed base_fields array in struct cal_csi2_phy
>   media: ti-vpe: cal: Don't modify cal_csi2_phy base_fields
>   media: ti-vpe: cal: Store PHY regmap fields in struct cc_data
>   media: ti-vpe: cal: Rename cal_csi2_phy base_fields to fields
>   media: ti-vpe: cal: Make structure fields unsigned where applicable
>   media: ti-vpe: cal: Constify platform data
>   media: ti-vpe: cal: Remove static const cal_regmap_config template
>   media: ti-vpe: cal: Remove unused structure fields
>   media: ti-vpe: cal: Remove flags field from struct cal_dev
>   media: ti-vpe: cal: Move function to avoid forward declaration
>   media: ti-vpe: cal: Rename cc_data to cal_camerarx
>   media: ti-vpe: cal: Rename cal_csi2_phy to cal_camerarx_data
>   media: ti-vpe: cal: Name all cal_dev pointers consistently
>   media: ti-vpe: cal: Name all cal_camerarx pointers consistently
>   media: ti-vpe: cal: Remove internal phy structure from cal_camerarx
>   media: ti-vpe: cal: Store instance ID and cal pointer in cal_camerarx
>   media: ti-vpe: cal: Use dev_* print macros
>   media: ti-vpe: cal: Add print macros for the cal_camerarx instances
>   media: ti-vpe: cal: Store sensor-related data in cal_camerarx
>   media: ti-vpe: cal: Create consistent naming for CAMERARX functions
>   media: ti-vpe: cal: Group CAMERARX-related functions together
>   media: ti-vpe: cal: Create consistent naming for context functions
>   media: ti-vpe: cal: Reorganize remaining code in sections
>   media: ti-vpe: cal: Rename cal_ctx.csi2_port to cal_ctx.index
>   media: ti-vpe: cal: Use correct device name for bus_info
>   media: ti-vpe: cal: Get struct device without going through
>     v4l2_device
>   media: ti-vpe: cal: Use ctx_info() instead of v4l2_info()
>   media: ti-vpe: cal: Use a loop to create CAMERARX and context
>     instances
>   media: ti-vpe: cal: Drop struct cal_dev v4l2_dev field
>   media: ti-vpe: cal: Split CAMERARX syscon regmap retrieval to a
>     function
>   media: ti-vpe: cal: Use syscon_regmap_lookup_by_phandle_args()
>   media: ti-vpe: cal: Inline cal_get_camerarx_regmap() in caller
>   media: ti-vpe: cal: Add comments to cal_probe() to delimitate sections
>   media: ti-vpe: cal: Rename cal_create_instance() to cal_ctx_create()
>   media: ti-vpe: cal: Hardcode virtual channel to 0
>   media: ti-vpe: cal: Use of_graph_get_endpoint_by_regs() to parse OF
>   media: ti-vpe: cal: Fix usage of v4l2_fwnode_endpoint_parse()
>   media: ti-vpe: cal: Decouple control handler from v4l2_device
>   media: ti-vpe: cal: Move v4l2_device from cal_ctx to cal_dev
>   media: ti-vpe: cal: Split video device initialization and registration
>   media: ti-vpe: cal: Add context V4L2 cleanup and unregister functions
>   media: ti-vpe: cal: Unregister video device before cleanup
>   media: ti-vpe: cal: Add cal_camerarx_destroy() to cleanup CAMERARX
>   media: ti-vpe: cal: Move DT parsing to CAMERARX
>   media: ti-vpe: cal: Use ARRAY_SIZE to replace numerical value
>   media: ti-vpe: cal: Move all sensor-related init to .bound() notifier
>   media: ti-vpe: cal: Allow multiple contexts per subdev notifier
>   media: ti-vpe: cal: Move async notifiers from contexts to cal_dev
>   media: ti-vpe: cal: Replace context with phy in async notifier entries
>   media: ti-vpe: cal: Operate on phy instances in cal_quickdump_regs()
>   media: ti-vpe: cal: Decouple context and phy cleanup at remove time
>   media: ti-vpe: cal: Move CAL_NUM_CSI2_PORTS from cal_regs.h to cal.c
>   media: ti-vpe: cal: Remove isvcirqset() and isportirqset() macros
>   media: ti-vpe: cal: Replace number of ports numerical value by macro
>   media: ti-vpe: cal: Split media initialization and cleanup to
>     functions
>   media: ti-vpe: cal: Read hardware revision earlier during probe
>   media: ti-vpe: cal: Print revision and hwinfo in a more readable
>     format
>   media: ti-vpe: cal: Store struct device in cal_dev
>   media: ti-vpe: cal: Register a media device
>   media: ti-vpe: cal: Init formats in cal_ctx_v4l2_register()
>   media: ti-vpe: cal: Allocate cal_ctx active_fmt array dynamically
>   media: ti-vpe: cal: Inline cal_camerarx_max_lanes() in its only caller
>   media: ti-vpe: cal: Reorder camerarx functions to prepare refactoring
>   media: ti-vpe: cal: Refactor camerarx start and stop
>   media: ti-vpe: cal: Don't store external rate in cal_camerarx
>   media: ti-vpe: cal: Remove unneeded phy->sensor NULL check
>   media: ti-vpe: cal: Use 'unsigned int' type instead of 'unsigned'
>   media: ti-vpe: cal: Split video node handling to cal-video.c
>   media: ti-vpe: cal: Move CAL I/O accessors to cal.h
>   media: ti-vpe: cal: Split CAMERARX handling to cal-camerarx.c
>   media: ti-vpe: cal: Create subdev for CAMERARX
>   media: ti-vpe: cal: Drop cal_ctx m_fmt field
>   media: ti-vpe: cal: Move format handling to cal.c and expose helpers
>   media: ti-vpe: cal: Rename MAX_(WIDTH|HEIGHT)_* macros with CAL_
>     prefix
>   media: ti-vpe: cal: Replace hardcoded BIT() value with macro
>   media: ti-vpe: cal: Iterate over correct number of CAMERARX instances
>   media: ti-vpe: cal: Implement subdev ops for CAMERARX
>   media: ti-vpe: cal: Use CAMERARX subdev s_stream op in video device
>     code
>   media: ti-vpe: cal: Don't pass format to cal_ctx_wr_dma_config()
>   media: ti-vpe: cal: Rename struct cal_fmt to cal_format_info
>   media: ti-vpe: cal: Refactor interrupt enable/disable
>   media: ti-vpe: cal: Fold PPI enable in CAMERARX .s_stream()
>   media: ti-vpe: cal: Stop write DMA without disabling PPI
>   media: ti-vpe: cal: Use spin_lock_irq() when starting or stopping
>     stream
>   media: ti-vpe: cal: Share buffer release code between start and stop
>   media: ti-vpe: cal: Drop V4L2_CAP_READWRITE
>   media: ti-vpe: cal: Drop unneeded check in cal_calc_format_size()
>   media: ti-vpe: cal: Remove DMA queue empty check at start streaming
>     time
>   media: ti-vpe: cal: Use list_first_entry()
>   media: ti-vpe: cal: Group all DMA queue fields in struct cal_dmaqueue
>   media: ti-vpe: cal: Set cal_dmaqueue.pending to NULL when no pending
>     buffer
>   media: ti-vpe: cal: Store buffer DMA address in dma_addr_t
>   media: ti-vpe: cal: Simplify the context API
>   media: ti-vpe: cal: Implement media controller centric API
> 
>  drivers/media/platform/ti-vpe/Makefile       |    2 +-
>  drivers/media/platform/ti-vpe/cal-camerarx.c |  857 ++++++
>  drivers/media/platform/ti-vpe/cal-video.c    |  957 ++++++
>  drivers/media/platform/ti-vpe/cal.c          | 2732 +++++-------------
>  drivers/media/platform/ti-vpe/cal.h          |  310 ++
>  drivers/media/platform/ti-vpe/cal_regs.h     |   74 +-
>  6 files changed, 2865 insertions(+), 2067 deletions(-)
>  create mode 100644 drivers/media/platform/ti-vpe/cal-camerarx.c
>  create mode 100644 drivers/media/platform/ti-vpe/cal-video.c
>  create mode 100644 drivers/media/platform/ti-vpe/cal.h
> 
> -- 
> Regards,
> 
> Laurent Pinchart
> 

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

* Re: [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support
  2020-06-19 14:53 ` Benoit Parrot
@ 2020-06-19 14:57   ` Benoit Parrot
  0 siblings, 0 replies; 150+ messages in thread
From: Benoit Parrot @ 2020-06-19 14:57 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Tomi Valkeinen

Benoit Parrot <bparrot@ti.com> wrote on Fri [2020-Jun-19 09:53:03 -0500]:
> Hi Laurent,
> 
> Except for patch 56, 78, 84 and 107.

Sorry, hit send too quickly here.

Except for patch 8, 30, 56, 68, 78, 84 and 107.

> 
> Reviewed-by: Benoit Parrot <bparrot@ti.com>
> 
> Benoit
> 
> Laurent Pinchart <laurent.pinchart@ideasonboard.com> wrote on Mon [2020-Jun-15 02:57:57 +0300]:
> > Hello,
> > 
> > This small patch series adds media controller support to the ti-cal
> > driver.
> > 
> > The end goal is to support pipelines where the image source is more
> > complex than a single subdev (for instance a SMIA++-compliant sensor, or
> > an FPD-Link source made of a camera, a serializer and a deserializer),
> > and to prepare for support of multiple hardware contexts, needed for
> > CSI-2 virtual channel and data type multiplexing support. These use
> > cases require configuration of the external pipeline from userspace, and
> > thus need support for the media controller and V4L2 subdev userspace
> > APIs.
> > 
> > The series starts with miscellaneous cleanups and refactoring, in
> > patches 001/107 to 083/107. Worth being noted is the split of the large
> > driver into multiple files, with patch 081/107 moving video node
> > handling to cal-video.c and patch 083/107 moving CAMERARX handling to
> > cal-camerarx.c.
> > 
> > Interleaved with more cleanup and refactoring, patch 084/107 creates
> > subdevs for the CAMERARX instances, patch 090/107 implements the subdev
> > operations, and patch 091/107 uses the subdev .set_fmt() and .s_stream()
> > operations to configure and control the CAMERARX. 
> > 
> > More refactoring and cleanup follow in patches 092/107 to 106/107, until
> > patch 107/107 that adds media controller support. As the existing video
> > node centric API needs to be preserved to avoid breaking userspace
> > applications, a module parameter is added to enable the media controller
> > API. Changes are otherwise fairly limited, and mostly involve the
> > implementation of MC-centric V4L2 ioctl handlers (which are far simpler
> > than their video node centric equivalents), additional pipeline
> > validation in the vb2 start streaming handler, and disabling control
> > handling in the video nodes.
> > 
> > The patches have been tested on an AM65x EVM with an OV5640 camera
> > module with the yavta test application, both in MC mode and in legacy
> > mode. As the ov5640 driver sets a default format identical to the
> > default of the ti-cal driver, capture in both modes can simply be tested
> > with
> > 
> > 	yavta -f UYVY -s 640x480 -c10 --requeue-last /dev/video0
> > 
> > without requiring manual pipeline setup through the media controller
> > API. Usage of other formats or resolutions require pipeline
> > configuration before capture.
> > 
> > Laurent Pinchart (107):
> >   media: ti-vpe: cal: Sort headers alphabetically
> >   media: ti-vpe: cal: Avoid function forward declaration
> >   media: ti-vpe: cal: Decouple CSI2 port and CPORT
> >   media: ti-vpe: cal: Index CSI-2 port starting at 0
> >   media: ti-vpe: cal: Index IRQ registersstarting at 0
> >   media: ti-vpe: cal: Merge all status variables in IRQ handler
> >   media: ti-vpe: cal: Inline CAL_VERSION macro in its only user
> >   media: ti-vpe: cal: Turn reg_(read|write)_field() into inline
> >     functions
> >   media: ti-vpe: cal: Make cal_formats array const
> >   media: ti-vpe: cal: Remove needless variable initialization
> >   media: ti-vpe: cal: Remove needless casts
> >   media: ti-vpe: cal: Turn boolean variable into bool
> >   media: ti-vpe: cal: Make loop indices unsigned where applicable
> >   media: ti-vpe: cal: Embed base_fields array in struct cal_csi2_phy
> >   media: ti-vpe: cal: Don't modify cal_csi2_phy base_fields
> >   media: ti-vpe: cal: Store PHY regmap fields in struct cc_data
> >   media: ti-vpe: cal: Rename cal_csi2_phy base_fields to fields
> >   media: ti-vpe: cal: Make structure fields unsigned where applicable
> >   media: ti-vpe: cal: Constify platform data
> >   media: ti-vpe: cal: Remove static const cal_regmap_config template
> >   media: ti-vpe: cal: Remove unused structure fields
> >   media: ti-vpe: cal: Remove flags field from struct cal_dev
> >   media: ti-vpe: cal: Move function to avoid forward declaration
> >   media: ti-vpe: cal: Rename cc_data to cal_camerarx
> >   media: ti-vpe: cal: Rename cal_csi2_phy to cal_camerarx_data
> >   media: ti-vpe: cal: Name all cal_dev pointers consistently
> >   media: ti-vpe: cal: Name all cal_camerarx pointers consistently
> >   media: ti-vpe: cal: Remove internal phy structure from cal_camerarx
> >   media: ti-vpe: cal: Store instance ID and cal pointer in cal_camerarx
> >   media: ti-vpe: cal: Use dev_* print macros
> >   media: ti-vpe: cal: Add print macros for the cal_camerarx instances
> >   media: ti-vpe: cal: Store sensor-related data in cal_camerarx
> >   media: ti-vpe: cal: Create consistent naming for CAMERARX functions
> >   media: ti-vpe: cal: Group CAMERARX-related functions together
> >   media: ti-vpe: cal: Create consistent naming for context functions
> >   media: ti-vpe: cal: Reorganize remaining code in sections
> >   media: ti-vpe: cal: Rename cal_ctx.csi2_port to cal_ctx.index
> >   media: ti-vpe: cal: Use correct device name for bus_info
> >   media: ti-vpe: cal: Get struct device without going through
> >     v4l2_device
> >   media: ti-vpe: cal: Use ctx_info() instead of v4l2_info()
> >   media: ti-vpe: cal: Use a loop to create CAMERARX and context
> >     instances
> >   media: ti-vpe: cal: Drop struct cal_dev v4l2_dev field
> >   media: ti-vpe: cal: Split CAMERARX syscon regmap retrieval to a
> >     function
> >   media: ti-vpe: cal: Use syscon_regmap_lookup_by_phandle_args()
> >   media: ti-vpe: cal: Inline cal_get_camerarx_regmap() in caller
> >   media: ti-vpe: cal: Add comments to cal_probe() to delimitate sections
> >   media: ti-vpe: cal: Rename cal_create_instance() to cal_ctx_create()
> >   media: ti-vpe: cal: Hardcode virtual channel to 0
> >   media: ti-vpe: cal: Use of_graph_get_endpoint_by_regs() to parse OF
> >   media: ti-vpe: cal: Fix usage of v4l2_fwnode_endpoint_parse()
> >   media: ti-vpe: cal: Decouple control handler from v4l2_device
> >   media: ti-vpe: cal: Move v4l2_device from cal_ctx to cal_dev
> >   media: ti-vpe: cal: Split video device initialization and registration
> >   media: ti-vpe: cal: Add context V4L2 cleanup and unregister functions
> >   media: ti-vpe: cal: Unregister video device before cleanup
> >   media: ti-vpe: cal: Add cal_camerarx_destroy() to cleanup CAMERARX
> >   media: ti-vpe: cal: Move DT parsing to CAMERARX
> >   media: ti-vpe: cal: Use ARRAY_SIZE to replace numerical value
> >   media: ti-vpe: cal: Move all sensor-related init to .bound() notifier
> >   media: ti-vpe: cal: Allow multiple contexts per subdev notifier
> >   media: ti-vpe: cal: Move async notifiers from contexts to cal_dev
> >   media: ti-vpe: cal: Replace context with phy in async notifier entries
> >   media: ti-vpe: cal: Operate on phy instances in cal_quickdump_regs()
> >   media: ti-vpe: cal: Decouple context and phy cleanup at remove time
> >   media: ti-vpe: cal: Move CAL_NUM_CSI2_PORTS from cal_regs.h to cal.c
> >   media: ti-vpe: cal: Remove isvcirqset() and isportirqset() macros
> >   media: ti-vpe: cal: Replace number of ports numerical value by macro
> >   media: ti-vpe: cal: Split media initialization and cleanup to
> >     functions
> >   media: ti-vpe: cal: Read hardware revision earlier during probe
> >   media: ti-vpe: cal: Print revision and hwinfo in a more readable
> >     format
> >   media: ti-vpe: cal: Store struct device in cal_dev
> >   media: ti-vpe: cal: Register a media device
> >   media: ti-vpe: cal: Init formats in cal_ctx_v4l2_register()
> >   media: ti-vpe: cal: Allocate cal_ctx active_fmt array dynamically
> >   media: ti-vpe: cal: Inline cal_camerarx_max_lanes() in its only caller
> >   media: ti-vpe: cal: Reorder camerarx functions to prepare refactoring
> >   media: ti-vpe: cal: Refactor camerarx start and stop
> >   media: ti-vpe: cal: Don't store external rate in cal_camerarx
> >   media: ti-vpe: cal: Remove unneeded phy->sensor NULL check
> >   media: ti-vpe: cal: Use 'unsigned int' type instead of 'unsigned'
> >   media: ti-vpe: cal: Split video node handling to cal-video.c
> >   media: ti-vpe: cal: Move CAL I/O accessors to cal.h
> >   media: ti-vpe: cal: Split CAMERARX handling to cal-camerarx.c
> >   media: ti-vpe: cal: Create subdev for CAMERARX
> >   media: ti-vpe: cal: Drop cal_ctx m_fmt field
> >   media: ti-vpe: cal: Move format handling to cal.c and expose helpers
> >   media: ti-vpe: cal: Rename MAX_(WIDTH|HEIGHT)_* macros with CAL_
> >     prefix
> >   media: ti-vpe: cal: Replace hardcoded BIT() value with macro
> >   media: ti-vpe: cal: Iterate over correct number of CAMERARX instances
> >   media: ti-vpe: cal: Implement subdev ops for CAMERARX
> >   media: ti-vpe: cal: Use CAMERARX subdev s_stream op in video device
> >     code
> >   media: ti-vpe: cal: Don't pass format to cal_ctx_wr_dma_config()
> >   media: ti-vpe: cal: Rename struct cal_fmt to cal_format_info
> >   media: ti-vpe: cal: Refactor interrupt enable/disable
> >   media: ti-vpe: cal: Fold PPI enable in CAMERARX .s_stream()
> >   media: ti-vpe: cal: Stop write DMA without disabling PPI
> >   media: ti-vpe: cal: Use spin_lock_irq() when starting or stopping
> >     stream
> >   media: ti-vpe: cal: Share buffer release code between start and stop
> >   media: ti-vpe: cal: Drop V4L2_CAP_READWRITE
> >   media: ti-vpe: cal: Drop unneeded check in cal_calc_format_size()
> >   media: ti-vpe: cal: Remove DMA queue empty check at start streaming
> >     time
> >   media: ti-vpe: cal: Use list_first_entry()
> >   media: ti-vpe: cal: Group all DMA queue fields in struct cal_dmaqueue
> >   media: ti-vpe: cal: Set cal_dmaqueue.pending to NULL when no pending
> >     buffer
> >   media: ti-vpe: cal: Store buffer DMA address in dma_addr_t
> >   media: ti-vpe: cal: Simplify the context API
> >   media: ti-vpe: cal: Implement media controller centric API
> > 
> >  drivers/media/platform/ti-vpe/Makefile       |    2 +-
> >  drivers/media/platform/ti-vpe/cal-camerarx.c |  857 ++++++
> >  drivers/media/platform/ti-vpe/cal-video.c    |  957 ++++++
> >  drivers/media/platform/ti-vpe/cal.c          | 2732 +++++-------------
> >  drivers/media/platform/ti-vpe/cal.h          |  310 ++
> >  drivers/media/platform/ti-vpe/cal_regs.h     |   74 +-
> >  6 files changed, 2865 insertions(+), 2067 deletions(-)
> >  create mode 100644 drivers/media/platform/ti-vpe/cal-camerarx.c
> >  create mode 100644 drivers/media/platform/ti-vpe/cal-video.c
> >  create mode 100644 drivers/media/platform/ti-vpe/cal.h
> > 
> > -- 
> > Regards,
> > 
> > Laurent Pinchart
> > 

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

* Re: [PATCH v1 008/107] media: ti-vpe: cal: Turn reg_(read|write)_field() into inline functions
  2020-06-18 13:29   ` Benoit Parrot
@ 2020-06-19 15:15     ` Laurent Pinchart
  0 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-19 15:15 UTC (permalink / raw)
  To: Benoit Parrot; +Cc: linux-media, Tomi Valkeinen

Hi Benoit,

On Thu, Jun 18, 2020 at 08:29:55AM -0500, Benoit Parrot wrote:
> Laurent Pinchart <laurent.pinchart@ideasonboard.com> wrote on Mon [2020-Jun-15 02:58:05 +0300]:
> > Turn the reg_(read|write)_field() macros into inline functions for
> > additional type safety. Use the FIELD_GET() and FIELD_PREP() macros
> > internally instead of reinventing the wheel.
> > 
> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > ---
> >  drivers/media/platform/ti-vpe/cal.c | 28 ++++++++++++++++------------
> >  1 file changed, 16 insertions(+), 12 deletions(-)
> > 
> > diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
> > index fa86a53882cc..8c068af936f0 100644
> > --- a/drivers/media/platform/ti-vpe/cal.c
> > +++ b/drivers/media/platform/ti-vpe/cal.c
> > @@ -6,6 +6,7 @@
> >   * Benoit Parrot, <bparrot@ti.com>
> >   */
> >  
> > +#include <linux/bitfield.h>
> >  #include <linux/clk.h>
> >  #include <linux/delay.h>
> >  #include <linux/interrupt.h>
> > @@ -76,13 +77,6 @@ static const struct v4l2_fract
> >  #define reg_read(dev, offset) ioread32(dev->base + offset)
> >  #define reg_write(dev, offset, val) iowrite32(val, dev->base + offset)
> >  
> > -#define reg_read_field(dev, offset, mask) get_field(reg_read(dev, offset), \
> > -						    mask)
> > -#define reg_write_field(dev, offset, field, mask) { \
> > -	u32 val = reg_read(dev, offset); \
> > -	set_field(&val, field, mask); \
> > -	reg_write(dev, offset, val); }
> > -
> >  /* ------------------------------------------------------------------
> >   *	Basic structures
> >   * ------------------------------------------------------------------
> > @@ -418,6 +412,21 @@ struct cal_ctx {
> >  	bool dma_act;
> >  };
> >  
> > +static inline u32 reg_read_field(struct cal_dev *dev, u32 offset, u32 mask)
> > +{
> > +	return FIELD_GET(mask, reg_read(dev, offset));
> > +}
> > +
> > +static inline void reg_write_field(struct cal_dev *dev, u32 offset, u32 value,
> > +				   u32 mask)
> > +{
> > +	u32 val = reg_read(dev, offset);
> > +
> > +	val &= ~mask;
> > +	val |= FIELD_PREP(mask, value);
> > +	reg_write(dev, offset, val);
> > +}
> > +
> >  static const struct cal_fmt *find_format_by_pix(struct cal_ctx *ctx,
> >  						u32 pixelformat)
> >  {
> > @@ -453,11 +462,6 @@ static inline struct cal_ctx *notifier_to_ctx(struct v4l2_async_notifier *n)
> >  	return container_of(n, struct cal_ctx, notifier);
> >  }
> >  
> > -static inline int get_field(u32 value, u32 mask)
> > -{
> > -	return (value & mask) >> __ffs(mask);
> > -}
> > -
> >  static inline void set_field(u32 *valp, u32 field, u32 mask)
> >  {
> >  	u32 val = *valp;
> 
> Is set_field still in use then after this patch?
> Any reason to keep it around?

Yes, it's still used in a quite few functions. I'm considering
addressing that on top, several (but not all) use caes are in functions
that perform read-modify-write updates when they could just write the
whole register.

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH v1 030/107] media: ti-vpe: cal: Use dev_* print macros
  2020-06-18 18:28   ` Benoit Parrot
@ 2020-06-19 15:22     ` Laurent Pinchart
  0 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-19 15:22 UTC (permalink / raw)
  To: Benoit Parrot; +Cc: linux-media, Tomi Valkeinen

Hi Benoit,

On Thu, Jun 18, 2020 at 01:28:55PM -0500, Benoit Parrot wrote:
> Laurent Pinchart <laurent.pinchart@ideasonboard.com> wrote on Mon [2020-Jun-15 02:58:27 +0300]:
> > Use the dev_* print macros instead of the v4l2_* print macros. This
> > prepares for a common print infrastructure that will also support the
> > cal_camerarx instances.
> > 
> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > ---
> >  drivers/media/platform/ti-vpe/cal.c | 17 ++++++++++-------
> >  1 file changed, 10 insertions(+), 7 deletions(-)
> > 
> > diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
> > index e40967751aa4..e62089832713 100644
> > --- a/drivers/media/platform/ti-vpe/cal.c
> > +++ b/drivers/media/platform/ti-vpe/cal.c
> > @@ -53,19 +53,22 @@ static unsigned debug;
> >  module_param(debug, uint, 0644);
> >  MODULE_PARM_DESC(debug, "activates debug info");
> >  
> > -#define cal_dbg(level, cal, fmt, arg...)	\
> > -		v4l2_dbg(level, debug, &cal->v4l2_dev, fmt, ##arg)
> > +#define cal_dbg(level, cal, fmt, arg...)				\
> > +	do {								\
> > +		if (debug >= (level))					\
> > +			dev_dbg(&(cal)->pdev->dev, fmt, ##arg);		\
> > +	} while (0)
> 
> The problem here with using dev_dbg is that you loose the ability to enable
> or disable debug log at runtime. Which I find highly convenient.
> 
> With dev_dbg you have to compile with DEBUG defined or at the very least
> DYNAMIC_DEBUG.

That's actually one of the things I like about dev_dbg(), it shrinks the
kernel when DEBUG (or DYNAMIC_DEBUG) isn't defined. In which case we
could possibly even remove the debug module parameter, as DYNAMIC_DEBUG
already gives us control over which messages are printed.

I however hear your concern, and I don't dispute that a module parameter
can also make debugging easier, at in some cases. It's partly a matter
of getting use to DYNAMIC_DEBUG, but not just that. I'll thus replace
dev_dbg() with dev_printk(KERN_DEBUG, ...) here.

> >  #define cal_info(cal, fmt, arg...)	\
> > -		v4l2_info(&cal->v4l2_dev, fmt, ##arg)
> > +	dev_info(&(cal)->pdev->dev, fmt, ##arg)
> >  #define cal_err(cal, fmt, arg...)	\
> > -		v4l2_err(&cal->v4l2_dev, fmt, ##arg)
> > +	dev_err(&(cal)->pdev->dev, fmt, ##arg)
> >  
> >  #define ctx_dbg(level, ctx, fmt, arg...)	\
> > -		v4l2_dbg(level, debug, &ctx->v4l2_dev, fmt, ##arg)
> > +	cal_dbg(level, (ctx)->cal, "ctx%u: " fmt, (ctx)->csi2_port, ##arg)
> >  #define ctx_info(ctx, fmt, arg...)	\
> > -		v4l2_info(&ctx->v4l2_dev, fmt, ##arg)
> > +	cal_info((ctx)->cal, "ctx%u: " fmt, (ctx)->csi2_port, ##arg)
> >  #define ctx_err(ctx, fmt, arg...)	\
> > -		v4l2_err(&ctx->v4l2_dev, fmt, ##arg)
> > +	cal_err((ctx)->cal, "ctx%u: " fmt, (ctx)->csi2_port, ##arg)
> >  
> >  #define CAL_NUM_CONTEXT 2
> >  

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH v1 056/107] media: ti-vpe: cal: Add cal_camerarx_destroy() to cleanup CAMERARX
  2020-06-17 10:43   ` Kieran Bingham
@ 2020-06-19 15:36     ` Laurent Pinchart
  0 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-19 15:36 UTC (permalink / raw)
  To: Kieran Bingham; +Cc: linux-media, Tomi Valkeinen, Benoit Parrot

Hi Kieran,

On Wed, Jun 17, 2020 at 11:43:25AM +0100, Kieran Bingham wrote:
> On 15/06/2020 00:58, Laurent Pinchart wrote:
> > The cal_camerarx_create() function allocates resources with devm_*, and
> > thus doesn't need any manual cleanup. Those won't hold true for long, as
> > we will need to store resources that have no devm_* allocation variant
> > in cal_camerarx. Furthermore, devm_kzalloc() is the wrong memory
> > allocation API for structures that can be accessed from userspace, as
> > device nodes can be kept open across device removal.
> 
> I still think that should be fixed by making devm_ allocations able to
> be reference counted so that it doesn't remove until until references
> (from open file handles) are released ;-) but that's completely out of
> scope here...

I don't think we can use devm_* for this purpose, as the resources are
tied to the lifetime of the device to driver binding, and that's the
completely wrong option in most cases. Fixing devm_* is likely not
possible. Ideally, I'd like devres to be moved to a different container
than struct device (kref comes to mind, there's probably other options),
and devm_* should be updated accordingly. We could then create a
separate devres-based API for resources visible to userspace.

Daniel Vetter has proposed a different approach, specific to DRM, see
include/drm/drm_managed.h. I don't like it much as it's a bit of a "I
don't care about the rest of the world I'll do my own thing and leave
others behind" approach, but I also agree that sometimes the rest of the
world has a too large inertia. The Linux kernel is like any human
construct, it has progressive and conservative sides.

> > Add a cal_camerarx_destroy() function to destroy a CAMERARX instance
> > explicitly, and switch to kzalloc() for memory allocation.
> > 
> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > ---
> >  drivers/media/platform/ti-vpe/cal.c | 35 ++++++++++++++++++++++++-----
> >  1 file changed, 29 insertions(+), 6 deletions(-)
> > 
> > diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
> > index b8c7ad8e39cd..c9fef333c532 100644
> > --- a/drivers/media/platform/ti-vpe/cal.c
> > +++ b/drivers/media/platform/ti-vpe/cal.c
> > @@ -931,7 +931,7 @@ static struct cal_camerarx *cal_camerarx_create(struct cal_dev *cal,
> >  	struct cal_camerarx *phy;
> >  	int ret;
> >  
> > -	phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL);
> > +	phy = kzalloc(sizeof(*phy), GFP_KERNEL);
> >  	if (!phy)
> >  		return ERR_PTR(-ENOMEM);
> >  
> > @@ -946,7 +946,8 @@ static struct cal_camerarx *cal_camerarx_create(struct cal_dev *cal,
> >  	phy->base = devm_ioremap_resource(&pdev->dev, phy->res);
> >  	if (IS_ERR(phy->base)) {
> >  		cal_err(cal, "failed to ioremap\n");
> > -		return ERR_CAST(phy->base);
> > +		ret = PTR_ERR(phy->base);
> > +		goto error;
> >  	}
> >  
> >  	cal_dbg(1, cal, "ioresource %s at %pa - %pa\n",
> > @@ -954,9 +955,21 @@ static struct cal_camerarx *cal_camerarx_create(struct cal_dev *cal,
> >  
> >  	ret = cal_camerarx_regmap_init(cal, phy);
> >  	if (ret)
> > -		return ERR_PTR(ret);
> > +		goto error;
> >  
> >  	return phy;
> > +
> > +error:
> > +	kfree(phy);
> > +	return ERR_PTR(ret);
> > +}
> > +
> > +static void cal_camerarx_destroy(struct cal_camerarx *phy)
> > +{
> > +	if (!phy)
> > +		return;
> > +
> > +	kfree(phy);
> >  }
> >  
> >  static int cal_camerarx_init_regmap(struct cal_dev *cal)
> > @@ -2252,15 +2265,17 @@ static int cal_probe(struct platform_device *pdev)
> >  	/* Create CAMERARX PHYs. */
> >  	for (i = 0; i < cal_data_get_num_csi2_phy(cal); ++i) {
> >  		cal->phy[i] = cal_camerarx_create(cal, i);
> > -		if (IS_ERR(cal->phy[i]))
> > -			return PTR_ERR(cal->phy[i]);
> > +		if (IS_ERR(cal->phy[i])) {
> > +			ret = PTR_ERR(cal->phy[i]);
> 
> here, cal->phy[i] is an error value, but you then iterate them and call
> cal_camerarx_destroy() on this value.
> 
> Perhaps you should set the following here, before jumping:
> 
> 			cal->phy[i] = NULL;

Good catch, I'll fix that.

> > +			goto error_camerarx;
> > +		}
> >  	}
> >  
> >  	/* Register the V4L2 device. */
> >  	ret = v4l2_device_register(&pdev->dev, &cal->v4l2_dev);
> >  	if (ret) {
> >  		cal_err(cal, "Failed to register V4L2 device\n");
> > -		return ret;
> > +		goto error_camerarx;
> >  	}
> >  
> >  	/* Create contexts. */
> > @@ -2301,6 +2316,11 @@ static int cal_probe(struct platform_device *pdev)
> >  
> >  error_v4l2:
> >  	v4l2_device_unregister(&cal->v4l2_dev);
> > +
> > +error_camerarx:
> > +	for (i = 0; i < ARRAY_SIZE(cal->phy); i++)
> > +		cal_camerarx_destroy(cal->phy[i]);
> > +
> >  	return ret;
> >  }
> >  
> > @@ -2329,6 +2349,9 @@ static int cal_remove(struct platform_device *pdev)
> >  
> >  	v4l2_device_unregister(&cal->v4l2_dev);
> >  
> > +	for (i = 0; i < ARRAY_SIZE(cal->phy); i++)
> > +		cal_camerarx_destroy(cal->phy[i]);
> > +
> >  	pm_runtime_put_sync(&pdev->dev);
> >  	pm_runtime_disable(&pdev->dev);
> >  

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH v1 082/107] media: ti-vpe: cal: Move CAL I/O accessors to cal.h
  2020-06-19  4:18   ` Ezequiel Garcia
@ 2020-06-19 15:40     ` Laurent Pinchart
  2020-06-19 17:18       ` Benoit Parrot
  0 siblings, 1 reply; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-19 15:40 UTC (permalink / raw)
  To: Ezequiel Garcia; +Cc: linux-media, Tomi Valkeinen, Benoit Parrot

Hi Ezequiel,

On Fri, Jun 19, 2020 at 01:18:28AM -0300, Ezequiel Garcia wrote:
> On Sun, 14 Jun 2020 at 21:01, Laurent Pinchart wrote:
> >
> > To prepare for the split of the camerarx code to a separate file, move
> > the CAL I/O accessors to cal.h. This requires renaming the accessors
> > with a cal_prefix, as the current names are too generic and prone to
> > namespace clashes.
> >
> > The reg_read() and read_write() macros, that cover both CAL and CAMERARX
> > register access, are split in two groups of inline functions, one for
> > CAL access and one for CAMERARX access.
> >
> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > ---
> >  drivers/media/platform/ti-vpe/cal-video.c |   1 -
> >  drivers/media/platform/ti-vpe/cal.c       | 280 ++++++++++------------
> >  drivers/media/platform/ti-vpe/cal.h       |  36 +++
> >  3 files changed, 168 insertions(+), 149 deletions(-)
> >
> > diff --git a/drivers/media/platform/ti-vpe/cal-video.c b/drivers/media/platform/ti-vpe/cal-video.c
> > index 82b32a2f9db5..df472a175e83 100644
> > --- a/drivers/media/platform/ti-vpe/cal-video.c
> > +++ b/drivers/media/platform/ti-vpe/cal-video.c
> > @@ -9,7 +9,6 @@
> >   *     Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> >   */
> >
> > -#include <linux/bitfield.h>
> >  #include <linux/delay.h>
> >  #include <linux/ioctl.h>
> >  #include <linux/pm_runtime.h>
> > diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
> > index 0bc02ba52b59..abeded3b5e6c 100644
> > --- a/drivers/media/platform/ti-vpe/cal.c
> > +++ b/drivers/media/platform/ti-vpe/cal.c
> > @@ -9,11 +9,9 @@
> >   *     Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> >   */
> >
> > -#include <linux/bitfield.h>
> >  #include <linux/clk.h>
> >  #include <linux/delay.h>
> >  #include <linux/interrupt.h>
> > -#include <linux/io.h>
> >  #include <linux/mfd/syscon.h>
> >  #include <linux/module.h>
> >  #include <linux/of_device.h>
> > @@ -133,33 +131,6 @@ static const struct cal_data am654_cal_data = {
> >   * ------------------------------------------------------------------
> >   */
> >
> > -#define reg_read(dev, offset) ioread32(dev->base + offset)
> > -#define reg_write(dev, offset, val) iowrite32(val, dev->base + offset)
> > -
> > -static inline u32 reg_read_field(struct cal_dev *cal, u32 offset, u32 mask)
> > -{
> > -       return FIELD_GET(mask, reg_read(cal, offset));
> > -}
> > -
> > -static inline void reg_write_field(struct cal_dev *cal, u32 offset, u32 value,
> > -                                  u32 mask)
> > -{
> > -       u32 val = reg_read(cal, offset);
> > -
> > -       val &= ~mask;
> > -       val |= FIELD_PREP(mask, value);
> > -       reg_write(cal, offset, val);
> > -}
> > -
> > -static inline void set_field(u32 *valp, u32 field, u32 mask)
> > -{
> > -       u32 val = *valp;
> > -
> > -       val &= ~mask;
> > -       val |= (field << __ffs(mask)) & mask;
> > -       *valp = val;
> > -}
> > -
> 
> Slightly unrelated, have you considered moving all of these to regmap?
> 
> Perhaps it will make the code more maintainable.

I'm considering it now :-) Benoit, Tomi, any objection ? Otherwise I'll
try to switch to regmap on top of this series.

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH v1 084/107] media: ti-vpe: cal: Create subdev for CAMERARX
  2020-06-17 10:10   ` Kieran Bingham
@ 2020-06-19 15:52     ` Laurent Pinchart
  0 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-19 15:52 UTC (permalink / raw)
  To: Kieran Bingham; +Cc: linux-media, Tomi Valkeinen, Benoit Parrot

Hi Kieran,

On Wed, Jun 17, 2020 at 11:10:32AM +0100, Kieran Bingham wrote:
> On 15/06/2020 00:59, Laurent Pinchart wrote:
> > Create and register V4L2 sudbevs for the CAMERARX instances, and link
> 
> s/sudbevs/subdevs/
> 
> > them in the media graph to the sensors and video nodes. The subdev API
> > is not exposed to userspace at this point, and no subdev operation is
> > implemented, but the media controller graph is visible to applications.
> > 
> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > ---
> >  drivers/media/platform/ti-vpe/cal-camerarx.c | 42 +++++++++++++++++++-
> >  drivers/media/platform/ti-vpe/cal-video.c    | 12 ++++++
> >  drivers/media/platform/ti-vpe/cal.c          | 31 ++++++++++++---
> >  drivers/media/platform/ti-vpe/cal.h          |  9 ++++-
> >  4 files changed, 86 insertions(+), 8 deletions(-)
> > 
> > diff --git a/drivers/media/platform/ti-vpe/cal-camerarx.c b/drivers/media/platform/ti-vpe/cal-camerarx.c
> > index a7e4b81c9734..9be432ff87b2 100644
> > --- a/drivers/media/platform/ti-vpe/cal-camerarx.c
> > +++ b/drivers/media/platform/ti-vpe/cal-camerarx.c
> > @@ -526,8 +526,8 @@ static int cal_camerarx_regmap_init(struct cal_dev *cal,
> >  static int cal_camerarx_parse_dt(struct cal_camerarx *phy)
> >  {
> >  	struct v4l2_fwnode_endpoint *endpoint = &phy->endpoint;
> > -	struct device_node *ep_node;
> >  	char data_lanes[V4L2_FWNODE_CSI2_MAX_DATA_LANES * 2];
> > +	struct device_node *ep_node;
> >  	unsigned int i;
> >  	int ret;
> >  
> > @@ -571,7 +571,8 @@ static int cal_camerarx_parse_dt(struct cal_camerarx *phy)
> >  		endpoint->bus.mipi_csi2.flags);
> >  
> >  	/* Retrieve the connected device and store it for later use. */
> > -	phy->sensor_node = of_graph_get_remote_port_parent(ep_node);
> > +	phy->sensor_ep_node = of_graph_get_remote_endpoint(ep_node);
> > +	phy->sensor_node = of_graph_get_port_parent(phy->sensor_ep_node);
> >  	if (!phy->sensor_node) {
> >  		phy_dbg(3, phy, "Can't get remote parent\n");
> >  		goto done;
> > @@ -580,15 +581,30 @@ static int cal_camerarx_parse_dt(struct cal_camerarx *phy)
> >  	phy_dbg(1, phy, "Found connected device %pOFn\n", phy->sensor_node);
> >  
> >  done:
> > +	of_node_put(phy->sensor_ep_node);
> >  	of_node_put(ep_node);
> >  	return ret;
> >  }
> >  
> > +/* ------------------------------------------------------------------
> > + *	V4L2 Subdev Operations
> > + * ------------------------------------------------------------------
> > + */
> > +
> > +static const struct v4l2_subdev_ops cal_camerarx_subdev_ops = {
> > +};
> > +
> > +/* ------------------------------------------------------------------
> > + *	Create and Destroy
> > + * ------------------------------------------------------------------
> > + */
> > +
> >  struct cal_camerarx *cal_camerarx_create(struct cal_dev *cal,
> >  					 unsigned int instance)
> >  {
> >  	struct platform_device *pdev = to_platform_device(cal->dev);
> >  	struct cal_camerarx *phy;
> > +	struct v4l2_subdev *sd;
> >  	int ret;
> >  
> >  	phy = kzalloc(sizeof(*phy), GFP_KERNEL);
> > @@ -620,9 +636,28 @@ struct cal_camerarx *cal_camerarx_create(struct cal_dev *cal,
> >  	if (ret)
> >  		goto error;
> >  
> > +	/* Initialize the V4L2 subdev and media entity. */
> > +	sd = &phy->subdev;
> > +	v4l2_subdev_init(sd, &cal_camerarx_subdev_ops);
> > +	sd->entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
> > +	snprintf(sd->name, sizeof(sd->name), "CAMERARX%u", instance);
> > +	sd->dev = cal->dev;
> > +
> > +	phy->pads[CAL_CAMERARX_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
> > +	phy->pads[CAL_CAMERARX_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
> > +	ret = media_entity_pads_init(&sd->entity, ARRAY_SIZE(phy->pads),
> > +				     phy->pads);
> > +	if (ret)
> > +		goto error;
> > +
> > +	ret = v4l2_device_register_subdev(&cal->v4l2_dev, sd);
> > +	if (ret)
> > +		goto error;
> > +
> >  	return phy;
> >  
> >  error:
> > +	media_entity_cleanup(&phy->subdev.entity);
> >  	kfree(phy);
> >  	return ERR_PTR(ret);
> >  }
> > @@ -632,6 +667,9 @@ void cal_camerarx_destroy(struct cal_camerarx *phy)
> >  	if (!phy)
> >  		return;
> >  
> > +	v4l2_device_unregister_subdev(&phy->subdev);
> > +	media_entity_cleanup(&phy->subdev.entity);
> > +	of_node_put(phy->sensor_ep_node);
> >  	of_node_put(phy->sensor_node);
> >  	kfree(phy);
> >  }
> > diff --git a/drivers/media/platform/ti-vpe/cal-video.c b/drivers/media/platform/ti-vpe/cal-video.c
> > index df472a175e83..0a1a11692208 100644
> > --- a/drivers/media/platform/ti-vpe/cal-video.c
> > +++ b/drivers/media/platform/ti-vpe/cal-video.c
> > @@ -809,6 +809,18 @@ int cal_ctx_v4l2_register(struct cal_ctx *ctx)
> >  		return ret;
> >  	}
> >  
> > +	ret = media_create_pad_link(&ctx->phy->subdev.entity,
> > +				    CAL_CAMERARX_PAD_SOURCE,
> > +				    &vfd->entity, 0,
> > +				    MEDIA_LNK_FL_IMMUTABLE |
> > +				    MEDIA_LNK_FL_ENABLED);
> > +	if (ret) {
> > +		ctx_err(ctx, "Failed to create media link for context %u\n",
> > +			ctx->index);
> > +		video_unregister_device(vfd);
> > +		return ret;
> > +	}
> > +
> >  	ctx_info(ctx, "V4L2 device registered as %s\n",
> >  		 video_device_node_name(vfd));
> >  
> > diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
> > index ca8576aa2646..bf1734d4d800 100644
> > --- a/drivers/media/platform/ti-vpe/cal.c
> > +++ b/drivers/media/platform/ti-vpe/cal.c
> > @@ -416,6 +416,8 @@ static int cal_async_notifier_bound(struct v4l2_async_notifier *notifier,
> >  				    struct v4l2_async_subdev *asd)
> >  {
> >  	struct cal_camerarx *phy = to_cal_asd(asd)->phy;
> > +	int pad;
> > +	int ret;
> >  
> >  	if (phy->sensor) {
> >  		phy_info(phy, "Rejecting subdev %s (Already set!!)",
> > @@ -426,6 +428,25 @@ static int cal_async_notifier_bound(struct v4l2_async_notifier *notifier,
> >  	phy->sensor = subdev;
> >  	phy_dbg(1, phy, "Using sensor %s for capture\n", subdev->name);
> >  
> > +	pad = media_entity_get_fwnode_pad(&subdev->entity,
> > +					  of_fwnode_handle(phy->sensor_ep_node),
> > +					  MEDIA_PAD_FL_SOURCE);
> > +	if (pad < 0) {
> > +		phy_err(phy, "Sensor %s has no connected source pad\n",
> > +			subdev->name);
> > +		return pad;
> > +	}
> > +
> > +	ret = media_create_pad_link(&subdev->entity, pad,
> > +				    &phy->subdev.entity, CAL_CAMERARX_PAD_SINK,
> > +				    MEDIA_LNK_FL_IMMUTABLE |
> > +				    MEDIA_LNK_FL_ENABLED);
> > +	if (ret) {
> > +		phy_err(phy, "Failed to create media link for sensor %s\n",
> > +			subdev->name);
> > +		return ret;
> > +	}
> > +
> >  	return 0;
> >  }
> >  
> > @@ -796,6 +817,11 @@ static int cal_probe(struct platform_device *pdev)
> >  	cal_get_hwinfo(cal);
> >  	pm_runtime_put_sync(&pdev->dev);
> >  
> > +	/* Initialize the media device. */
> > +	ret = cal_media_init(cal);
> > +	if (ret < 0)
> > +		goto error_camerarx;
> 
> This code moves now uses the wrong error label.
> 
> Moreover, moving it - now means that the loop creating the CAMERARX PHYs
> should now also cleanup the media device upon failure.
> 
> I have the following fixup patch which you could squash in here if you wish.
> 
> 
> From e6fc5364d92d0ded26f3d8bb6c06a650fcb1ba84 Mon Sep 17 00:00:00 2001
> From: Kieran Bingham <kieran.bingham@ideasonboard.com>
> Date: Tue, 16 Jun 2020 15:00:19 +0100
> Subject: [PATCH] media: ti-vpe: cal: Fix error path jumps
> 
> The error paths in cal_probe() incorrectly called through the
> error_camerarx before the camerarx instances were created, and neglected
> to call the error_media/cal_media_cleanup() paths if a camera failed to
> be created.
> 
> Tidy up the error paths, removing the now redundant error_media label.
> 
> Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
> ---
>  drivers/media/platform/ti-vpe/cal.c | 6 ++----
>  1 file changed, 2 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/media/platform/ti-vpe/cal.c
> b/drivers/media/platform/ti-vpe/cal.c
> index caea3e129c87..d00dc241804b 100644
> --- a/drivers/media/platform/ti-vpe/cal.c
> +++ b/drivers/media/platform/ti-vpe/cal.c
> @@ -1026,14 +1026,14 @@ static int cal_probe(struct platform_device *pdev)
>         /* Initialize the media device. */
>         ret = cal_media_init(cal);
>         if (ret < 0)
> -               goto error_camerarx;
> +               goto error_pm_runtime;
> 
>         /* Create CAMERARX PHYs. */
>         for (i = 0; i < cal_data_get_num_csi2_phy(cal); ++i) {
>                 cal->phy[i] = cal_camerarx_create(cal, i);
>                 if (IS_ERR(cal->phy[i])) {
>                         ret = PTR_ERR(cal->phy[i]);
> -                       goto error_camerarx;
> +                       goto error_media;
>                 }
>         }
> 
> @@ -1063,8 +1063,6 @@ static int cal_probe(struct platform_device *pdev)
> 
>  error_media:
>         cal_media_cleanup(cal);
> -
> -error_camerarx:
>         for (i = 0; i < cal->data->num_csi2_phy; i++)
>                 cal_camerarx_destroy(cal->phy[i]);

Good catch. I'll fix the second issues slightly differently, by moving
cal_media_cleanup() below the cal_camerarx_destroy() loop, and keeping
the error_camerarx label, as it's best to perform cleanups in the
reverse order of the inits (unless there's a specific reason not to do
so).

> With that fixed,
> 
> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>

Please let me know if you see problems in the proposed change, otherwise
I'll add your tag.

> > +
> >  	/* Create CAMERARX PHYs. */
> >  	for (i = 0; i < cal_data_get_num_csi2_phy(cal); ++i) {
> >  		cal->phy[i] = cal_camerarx_create(cal, i);
> > @@ -805,11 +831,6 @@ static int cal_probe(struct platform_device *pdev)
> >  		}
> >  	}
> >  
> > -	/* Initialize the media device. */
> > -	ret = cal_media_init(cal);
> > -	if (ret < 0)
> > -		goto error_camerarx;
> > -
> >  	/* Create contexts. */
> >  	for (i = 0; i < cal_data_get_num_csi2_phy(cal); ++i)
> >  		cal->ctx[i] = cal_ctx_create(cal, i);
> > diff --git a/drivers/media/platform/ti-vpe/cal.h b/drivers/media/platform/ti-vpe/cal.h
> > index cb167bfc2773..bf31dbf24523 100644
> > --- a/drivers/media/platform/ti-vpe/cal.h
> > +++ b/drivers/media/platform/ti-vpe/cal.h
> > @@ -24,6 +24,7 @@
> >  #include <media/v4l2-dev.h>
> >  #include <media/v4l2-device.h>
> >  #include <media/v4l2-fwnode.h>
> > +#include <media/v4l2-subdev.h>
> >  #include <media/videobuf2-v4l2.h>
> >  
> >  #define CAL_MODULE_NAME			"cal"
> > @@ -33,12 +34,14 @@
> >  #define MAX_WIDTH_BYTES			(8192 * 8)
> >  #define MAX_HEIGHT_LINES		16383
> >  
> > +#define CAL_CAMERARX_PAD_SINK		0
> > +#define CAL_CAMERARX_PAD_SOURCE		1
> > +
> >  struct device;
> >  struct device_node;
> >  struct resource;
> >  struct regmap;
> >  struct regmap_fied;
> > -struct v4l2_subdev;
> >  
> >  /* CTRL_CORE_CAMERRX_CONTROL register field id */
> >  enum cal_camerarx_field {
> > @@ -108,8 +111,12 @@ struct cal_camerarx {
> >  	unsigned int		instance;
> >  
> >  	struct v4l2_fwnode_endpoint	endpoint;
> > +	struct device_node	*sensor_ep_node;
> >  	struct device_node	*sensor_node;
> >  	struct v4l2_subdev	*sensor;
> > +
> > +	struct v4l2_subdev	subdev;
> > +	struct media_pad	pads[2];
> >  };
> >  
> >  struct cal_dev {

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH v1 107/107] media: ti-vpe: cal: Implement media controller centric API
  2020-06-19 14:46   ` Benoit Parrot
@ 2020-06-19 15:58     ` Laurent Pinchart
  0 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-19 15:58 UTC (permalink / raw)
  To: Benoit Parrot; +Cc: linux-media, Tomi Valkeinen

Hi Benoit,

On Fri, Jun 19, 2020 at 09:46:50AM -0500, Benoit Parrot wrote:
> Laurent Pinchart <laurent.pinchart@ideasonboard.com> wrote on Mon [2020-Jun-15 02:59:44 +0300]:
> > The CAL driver is video node centric, it controls the whole device
> > through the video device nodes. This limits the possible use cases as it
> > can't support sources that are more complex than a single subdev. To
> > support more complex hardware pipelines, implement support for the media
> > controller centric API. The exposed API can be selected through a module
> > parameter.
> > 
> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > ---
> >  drivers/media/platform/ti-vpe/cal-camerarx.c |   1 +
> >  drivers/media/platform/ti-vpe/cal-video.c    | 358 ++++++++++++++-----
> >  drivers/media/platform/ti-vpe/cal.c          |  10 +-
> >  drivers/media/platform/ti-vpe/cal.h          |   2 +
> >  4 files changed, 289 insertions(+), 82 deletions(-)
> > 
> > diff --git a/drivers/media/platform/ti-vpe/cal-camerarx.c b/drivers/media/platform/ti-vpe/cal-camerarx.c
> > index 2e7a3bc716cf..014ca46509db 100644
> > --- a/drivers/media/platform/ti-vpe/cal-camerarx.c
> > +++ b/drivers/media/platform/ti-vpe/cal-camerarx.c
> > @@ -818,6 +818,7 @@ struct cal_camerarx *cal_camerarx_create(struct cal_dev *cal,
> >  	sd = &phy->subdev;
> >  	v4l2_subdev_init(sd, &cal_camerarx_subdev_ops);
> >  	sd->entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
> > +	sd->flags = V4L2_SUBDEV_FL_HAS_DEVNODE;
> >  	snprintf(sd->name, sizeof(sd->name), "CAMERARX%u", instance);
> >  	sd->dev = cal->dev;
> >  
> > diff --git a/drivers/media/platform/ti-vpe/cal-video.c b/drivers/media/platform/ti-vpe/cal-video.c
> > index 0f8702bd77db..5f9cd449f027 100644
> > --- a/drivers/media/platform/ti-vpe/cal-video.c
> > +++ b/drivers/media/platform/ti-vpe/cal-video.c
> > @@ -40,40 +40,10 @@ static char *fourcc_to_str(u32 fmt)
> >  }
> >  
> >  /* ------------------------------------------------------------------
> > - *	V4L2 Video IOCTLs
> > + *	V4L2 Common IOCTLs
> >   * ------------------------------------------------------------------
> >   */
> >  
> > -static const struct cal_format_info *find_format_by_pix(struct cal_ctx *ctx,
> > -							u32 pixelformat)
> > -{
> > -	const struct cal_format_info *fmtinfo;
> > -	unsigned int k;
> > -
> > -	for (k = 0; k < ctx->num_active_fmt; k++) {
> > -		fmtinfo = ctx->active_fmt[k];
> > -		if (fmtinfo->fourcc == pixelformat)
> > -			return fmtinfo;
> > -	}
> > -
> > -	return NULL;
> > -}
> > -
> > -static const struct cal_format_info *find_format_by_code(struct cal_ctx *ctx,
> > -							 u32 code)
> > -{
> > -	const struct cal_format_info *fmtinfo;
> > -	unsigned int k;
> > -
> > -	for (k = 0; k < ctx->num_active_fmt; k++) {
> > -		fmtinfo = ctx->active_fmt[k];
> > -		if (fmtinfo->code == code)
> > -			return fmtinfo;
> > -	}
> > -
> > -	return NULL;
> > -}
> > -
> >  static int cal_querycap(struct file *file, void *priv,
> >  			struct v4l2_capability *cap)
> >  {
> > @@ -87,6 +57,51 @@ static int cal_querycap(struct file *file, void *priv,
> >  	return 0;
> >  }
> >  
> > +static int cal_g_fmt_vid_cap(struct file *file, void *priv,
> > +			     struct v4l2_format *f)
> > +{
> > +	struct cal_ctx *ctx = video_drvdata(file);
> > +
> > +	*f = ctx->v_fmt;
> > +
> > +	return 0;
> > +}
> > +
> > +/* ------------------------------------------------------------------
> > + *	V4L2 Video Node Centric IOCTLs
> > + * ------------------------------------------------------------------
> > + */
> > +
> > +static const struct cal_format_info *find_format_by_pix(struct cal_ctx *ctx,
> > +							u32 pixelformat)
> > +{
> > +	const struct cal_format_info *fmtinfo;
> > +	unsigned int k;
> > +
> > +	for (k = 0; k < ctx->num_active_fmt; k++) {
> > +		fmtinfo = ctx->active_fmt[k];
> > +		if (fmtinfo->fourcc == pixelformat)
> > +			return fmtinfo;
> > +	}
> > +
> > +	return NULL;
> > +}
> > +
> > +static const struct cal_format_info *find_format_by_code(struct cal_ctx *ctx,
> > +							 u32 code)
> > +{
> > +	const struct cal_format_info *fmtinfo;
> > +	unsigned int k;
> > +
> > +	for (k = 0; k < ctx->num_active_fmt; k++) {
> > +		fmtinfo = ctx->active_fmt[k];
> > +		if (fmtinfo->code == code)
> > +			return fmtinfo;
> > +	}
> > +
> > +	return NULL;
> > +}
> > +
> >  static int cal_enum_fmt_vid_cap(struct file *file, void  *priv,
> >  				struct v4l2_fmtdesc *f)
> >  {
> > @@ -174,16 +189,6 @@ static void cal_calc_format_size(struct cal_ctx *ctx,
> >  		f->fmt.pix.bytesperline, f->fmt.pix.sizeimage);
> >  }
> >  
> > -static int cal_g_fmt_vid_cap(struct file *file, void *priv,
> > -			     struct v4l2_format *f)
> > -{
> > -	struct cal_ctx *ctx = video_drvdata(file);
> > -
> > -	*f = ctx->v_fmt;
> > -
> > -	return 0;
> > -}
> > -
> >  static int cal_try_fmt_vid_cap(struct file *file, void *priv,
> >  			       struct v4l2_format *f)
> >  {
> > @@ -383,17 +388,7 @@ static int cal_enum_frameintervals(struct file *file, void *priv,
> >  	return 0;
> >  }
> >  
> > -static const struct v4l2_file_operations cal_fops = {
> > -	.owner		= THIS_MODULE,
> > -	.open           = v4l2_fh_open,
> > -	.release        = vb2_fop_release,
> > -	.read           = vb2_fop_read,
> > -	.poll		= vb2_fop_poll,
> > -	.unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */
> > -	.mmap           = vb2_fop_mmap,
> > -};
> > -
> > -static const struct v4l2_ioctl_ops cal_ioctl_ops = {
> > +static const struct v4l2_ioctl_ops cal_ioctl_video_ops = {
> >  	.vidioc_querycap      = cal_querycap,
> >  	.vidioc_enum_fmt_vid_cap  = cal_enum_fmt_vid_cap,
> >  	.vidioc_g_fmt_vid_cap     = cal_g_fmt_vid_cap,
> > @@ -419,7 +414,153 @@ static const struct v4l2_ioctl_ops cal_ioctl_ops = {
> >  };
> >  
> >  /* ------------------------------------------------------------------
> > - *	videobuf2 Operations
> > + *	V4L2 Media Controller Centric IOCTLs
> > + * ------------------------------------------------------------------
> > + */
> > +
> > +static int cal_mc_enum_fmt_vid_cap(struct file *file, void  *priv,
> > +				   struct v4l2_fmtdesc *f)
> > +{
> > +	if (f->index >= cal_num_formats)
> > +		return -EINVAL;
> > +
> > +	f->pixelformat = cal_formats[f->index].fourcc;
> > +	f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
> > +
> > +	return 0;
> > +}
> > +
> > +static void cal_mc_try_fmt(struct cal_ctx *ctx, struct v4l2_format *f,
> > +			   const struct cal_format_info **info)
> > +{
> > +	struct v4l2_pix_format *format = &f->fmt.pix;
> > +	const struct cal_format_info *fmtinfo;
> > +	unsigned int bpp;
> > +
> > +	/*
> > +	 * Default to the first format is the requested pixel format code isn't
> > +	 * supported.
> > +	 */
> > +	fmtinfo = cal_format_by_fourcc(f->fmt.pix.pixelformat);
> > +	if (!fmtinfo)
> > +		fmtinfo = &cal_formats[0];
> > +
> > +	/*
> > +	 * Clamp the size, update the pixel format. The field and colorspace are
> > +	 * accepted as-is, except for V4L2_FIELD_ANY that is turned into
> > +	 * V4L2_FIELD_NONE.
> > +	 */
> > +	bpp = ALIGN(fmtinfo->bpp, 8);
> > +
> > +	format->width = clamp_t(unsigned int, format->width,
> > +				CAL_MIN_WIDTH_BYTES * 8 / bpp,
> > +				CAL_MAX_WIDTH_BYTES * 8 / bpp);
> > +	format->height = clamp_t(unsigned int, format->height,
> > +				 CAL_MIN_HEIGHT_LINES, CAL_MAX_HEIGHT_LINES);
> > +	format->pixelformat = fmtinfo->fourcc;
> > +
> > +	if (format->field == V4L2_FIELD_ANY)
> > +		format->field = V4L2_FIELD_NONE;
> > +
> > +	/*
> > +	 * Calculate the number of bytes per line and the image size. The
> > +	 * hardware stores the stride as a number of 16 bytes words, in a
> > +	 * signed 15-bit value. Only 14 bits are thus usable.
> > +	 */
> > +	format->bytesperline = ALIGN(clamp(format->bytesperline,
> > +					   format->width * bpp / 8,
> > +					   ((1U << 14) - 1) * 16), 16);
> > +
> > +	format->sizeimage = format->height * format->bytesperline;
> > +
> > +	if (info)
> > +		*info = fmtinfo;
> > +
> > +	ctx_dbg(3, ctx, "%s: %s %ux%u (bytesperline %u sizeimage %u)\n",
> > +		__func__, fourcc_to_str(format->pixelformat),
> > +		format->width, format->height,
> > +		format->bytesperline, format->sizeimage);
> > +}
> > +
> > +static int cal_mc_try_fmt_vid_cap(struct file *file, void *priv,
> > +				  struct v4l2_format *f)
> > +{
> > +	struct cal_ctx *ctx = video_drvdata(file);
> > +
> > +	cal_mc_try_fmt(ctx, f, NULL);
> > +	return 0;
> > +}
> > +
> > +static int cal_mc_s_fmt_vid_cap(struct file *file, void *priv,
> > +				struct v4l2_format *f)
> > +{
> > +	struct cal_ctx *ctx = video_drvdata(file);
> > +	const struct cal_format_info *fmtinfo;
> > +
> > +	if (vb2_is_busy(&ctx->vb_vidq)) {
> > +		ctx_dbg(3, ctx, "%s device busy\n", __func__);
> > +		return -EBUSY;
> > +	}
> > +
> > +	cal_mc_try_fmt(ctx, f, &fmtinfo);
> > +
> > +	ctx->v_fmt = *f;
> > +	ctx->fmtinfo = fmtinfo;
> > +
> > +	return 0;
> > +}
> > +
> > +static int cal_mc_enum_framesizes(struct file *file, void *fh,
> > +				  struct v4l2_frmsizeenum *fsize)
> > +{
> > +	struct cal_ctx *ctx = video_drvdata(file);
> > +	const struct cal_format_info *fmtinfo;
> > +	unsigned int bpp;
> > +
> > +	if (fsize->index > 0)
> > +		return -EINVAL;
> > +
> > +	fmtinfo = cal_format_by_fourcc(fsize->pixel_format);
> > +	if (!fmtinfo) {
> > +		ctx_dbg(3, ctx, "Invalid pixel format 0x%08x\n",
> > +			fsize->pixel_format);
> > +		return -EINVAL;
> > +	}
> > +
> > +	bpp = ALIGN(fmtinfo->bpp, 8);
> > +
> > +	fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
> > +	fsize->stepwise.min_width = CAL_MIN_WIDTH_BYTES * 8 / bpp;
> > +	fsize->stepwise.max_width = CAL_MAX_WIDTH_BYTES * 8 / bpp;
> > +	fsize->stepwise.step_width = 64 / bpp;
> > +	fsize->stepwise.min_height = CAL_MIN_HEIGHT_LINES;
> > +	fsize->stepwise.max_height = CAL_MAX_HEIGHT_LINES;
> > +	fsize->stepwise.step_height = 1;
> > +
> > +	return 0;
> > +}
> > +
> > +static const struct v4l2_ioctl_ops cal_ioctl_mc_ops = {
> > +	.vidioc_querycap      = cal_querycap,
> > +	.vidioc_enum_fmt_vid_cap  = cal_mc_enum_fmt_vid_cap,
> > +	.vidioc_g_fmt_vid_cap     = cal_g_fmt_vid_cap,
> > +	.vidioc_try_fmt_vid_cap   = cal_mc_try_fmt_vid_cap,
> > +	.vidioc_s_fmt_vid_cap     = cal_mc_s_fmt_vid_cap,
> > +	.vidioc_enum_framesizes   = cal_mc_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,
> > +	.vidioc_log_status    = v4l2_ctrl_log_status,
> > +};
> > +
> > +/* ------------------------------------------------------------------
> > + *	videobuf2 Common Operations
> >   * ------------------------------------------------------------------
> >   */
> >  
> > @@ -505,6 +646,26 @@ static void cal_release_buffers(struct cal_ctx *ctx,
> >  	spin_unlock_irq(&ctx->dma.lock);
> >  }
> >  
> > +/* ------------------------------------------------------------------
> > + *	videobuf2 Operations
> > + * ------------------------------------------------------------------
> > + */
> > +
> > +static int cal_video_check_format(struct cal_ctx *ctx)
> > +{
> > +	const struct v4l2_mbus_framefmt *format;
> > +
> > +	format = &ctx->phy->formats[CAL_CAMERARX_PAD_SOURCE];
> > +
> > +	if (ctx->fmtinfo->code != format->code ||
> > +	    ctx->v_fmt.fmt.pix.height != format->height ||
> > +	    ctx->v_fmt.fmt.pix.width != format->width ||
> > +	    ctx->v_fmt.fmt.pix.field != format->field)
> > +		return -EPIPE;
> > +
> > +	return 0;
> > +}
> > +
> >  static int cal_start_streaming(struct vb2_queue *vq, unsigned int count)
> >  {
> >  	struct cal_ctx *ctx = vb2_get_drv_priv(vq);
> > @@ -512,6 +673,23 @@ static int cal_start_streaming(struct vb2_queue *vq, unsigned int count)
> >  	dma_addr_t addr;
> >  	int ret;
> >  
> > +	ret = media_pipeline_start(&ctx->vdev.entity, &ctx->phy->pipe);
> > +	if (ret < 0) {
> > +		ctx_err(ctx, "Failed to start media pipeline: %d\n", ret);
> > +		return ret;
> > +	}
> > +
> > +	/*
> > +	 * Verify that the currently configured format matches the output of
> > +	 * the connected CAMERARX.
> > +	 */
> > +	ret = cal_video_check_format(ctx);
> > +	if (ret < 0) {
> > +		ctx_dbg(3, ctx,
> > +			"Format mismatch between CAMERARX and video node\n");
> > +		goto error_pipeline;
> > +	}
> > +
> >  	spin_lock_irq(&ctx->dma.lock);
> >  	buf = list_first_entry(&ctx->dma.queue, struct cal_buffer, list);
> >  	ctx->dma.pending = buf;
> > @@ -527,18 +705,21 @@ static int cal_start_streaming(struct vb2_queue *vq, unsigned int count)
> >  
> >  	ret = v4l2_subdev_call(&ctx->phy->subdev, video, s_stream, 1);
> >  	if (ret)
> > -		goto err;
> > +		goto error_stop;
> >  
> >  	if (cal_debug >= 4)
> >  		cal_quickdump_regs(ctx->cal);
> >  
> >  	return 0;
> >  
> > -err:
> > +error_stop:
> >  	cal_ctx_stop(ctx);
> >  	pm_runtime_put_sync(ctx->cal->dev);
> >  
> > +error_pipeline:
> > +	media_pipeline_stop(&ctx->vdev.entity);
> >  	cal_release_buffers(ctx, VB2_BUF_STATE_QUEUED);
> > +
> >  	return ret;
> >  }
> >  
> > @@ -553,6 +734,8 @@ static void cal_stop_streaming(struct vb2_queue *vq)
> >  	pm_runtime_put_sync(ctx->cal->dev);
> >  
> >  	cal_release_buffers(ctx, VB2_BUF_STATE_ERROR);
> > +
> > +	media_pipeline_stop(&ctx->vdev.entity);
> >  }
> >  
> >  static const struct vb2_ops cal_video_qops = {
> > @@ -570,13 +753,14 @@ static const struct vb2_ops cal_video_qops = {
> >   * ------------------------------------------------------------------
> >   */
> >  
> > -static const struct video_device cal_videodev = {
> > -	.name		= CAL_MODULE_NAME,
> > -	.fops		= &cal_fops,
> > -	.ioctl_ops	= &cal_ioctl_ops,
> > -	.minor		= -1,
> > -	.release	= video_device_release_empty,
> > -	.device_caps	= V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING,
> > +static const struct v4l2_file_operations cal_fops = {
> > +	.owner		= THIS_MODULE,
> > +	.open           = v4l2_fh_open,
> > +	.release        = vb2_fop_release,
> > +	.read           = vb2_fop_read,
> > +	.poll		= vb2_fop_poll,
> > +	.unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */
> > +	.mmap           = vb2_fop_mmap,
> >  };
> >  
> >  static int cal_ctx_v4l2_init_formats(struct cal_ctx *ctx)
> > @@ -650,19 +834,22 @@ static int cal_ctx_v4l2_init_formats(struct cal_ctx *ctx)
> >  
> >  int cal_ctx_v4l2_register(struct cal_ctx *ctx)
> >  {
> > -	struct v4l2_ctrl_handler *hdl = &ctx->ctrl_handler;
> >  	struct video_device *vfd = &ctx->vdev;
> >  	int ret;
> >  
> > -	ret = cal_ctx_v4l2_init_formats(ctx);
> > -	if (ret)
> > -		return ret;
> > +	if (!cal_mc_api) {
> > +		struct v4l2_ctrl_handler *hdl = &ctx->ctrl_handler;
> >  
> > -	ret = v4l2_ctrl_add_handler(hdl, ctx->phy->sensor->ctrl_handler, NULL,
> > -				    true);
> > -	if (ret < 0) {
> > -		ctx_err(ctx, "Failed to add sensor ctrl handler\n");
> > -		return ret;
> > +		ret = cal_ctx_v4l2_init_formats(ctx);
> > +		if (ret)
> > +			return ret;
> > +
> > +		ret = v4l2_ctrl_add_handler(hdl, ctx->phy->sensor->ctrl_handler,
> > +					    NULL, true);
> > +		if (ret < 0) {
> > +			ctx_err(ctx, "Failed to add sensor ctrl handler\n");
> > +			return ret;
> > +		}
> >  	}
> >  
> >  	ret = video_register_device(vfd, VFL_TYPE_VIDEO, cal_video_nr);
> > @@ -699,7 +886,6 @@ void cal_ctx_v4l2_unregister(struct cal_ctx *ctx)
> >  
> >  int cal_ctx_v4l2_init(struct cal_ctx *ctx)
> >  {
> > -	struct v4l2_ctrl_handler *hdl = &ctx->ctrl_handler;
> >  	struct video_device *vfd = &ctx->vdev;
> >  	struct vb2_queue *q = &ctx->vb_vidq;
> >  	int ret;
> > @@ -726,10 +912,14 @@ int cal_ctx_v4l2_init(struct cal_ctx *ctx)
> >  		return ret;
> >  
> >  	/* Initialize the video device and media entity. */
> > -	*vfd = cal_videodev;
> > +	vfd->fops = &cal_fops;
> > +	vfd->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING
> > +			 | (cal_mc_api ? V4L2_CAP_IO_MC : 0);
> >  	vfd->v4l2_dev = &ctx->cal->v4l2_dev;
> >  	vfd->queue = q;
> >  	snprintf(vfd->name, sizeof(vfd->name), "CAL output %u", ctx->index);
> > +	vfd->release = video_device_release_empty;
> > +	vfd->ioctl_ops = cal_mc_api ? &cal_ioctl_mc_ops : &cal_ioctl_video_ops;
> >  	vfd->lock = &ctx->mutex;
> >  	video_set_drvdata(vfd, ctx);
> >  
> > @@ -738,15 +928,19 @@ int cal_ctx_v4l2_init(struct cal_ctx *ctx)
> >  	if (ret < 0)
> >  		return ret;
> >  
> > -	/* Initialize the control handler. */
> > -	ret = v4l2_ctrl_handler_init(hdl, 11);
> > -	if (ret < 0) {
> > -		ctx_err(ctx, "Failed to init ctrl handler\n");
> > -		goto error;
> > +	if (!cal_mc_api) {
> > +		/* Initialize the control handler. */
> > +		struct v4l2_ctrl_handler *hdl = &ctx->ctrl_handler;
> > +
> > +		ret = v4l2_ctrl_handler_init(hdl, 11);
> > +		if (ret < 0) {
> > +			ctx_err(ctx, "Failed to init ctrl handler\n");
> > +			goto error;
> > +		}
> > +
> > +		vfd->ctrl_handler = hdl;
> >  	}
> >  
> > -	vfd->ctrl_handler = hdl;
> > -
> >  	return 0;
> >  
> >  error:
> > @@ -756,6 +950,8 @@ int cal_ctx_v4l2_init(struct cal_ctx *ctx)
> >  
> >  void cal_ctx_v4l2_cleanup(struct cal_ctx *ctx)
> >  {
> > -	v4l2_ctrl_handler_free(&ctx->ctrl_handler);
> > +	if (!cal_mc_api)
> > +		v4l2_ctrl_handler_free(&ctx->ctrl_handler);
> > +
> >  	media_entity_cleanup(&ctx->vdev.entity);
> >  }
> > diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
> > index f97c213f716f..caea3e129c87 100644
> > --- a/drivers/media/platform/ti-vpe/cal.c
> > +++ b/drivers/media/platform/ti-vpe/cal.c
> > @@ -43,6 +43,10 @@ unsigned int cal_debug;
> >  module_param_named(debug, cal_debug, uint, 0644);
> >  MODULE_PARM_DESC(debug, "activates debug info");
> >  
> > +bool cal_mc_api;
> > +module_param_named(mc_api, cal_mc_api, bool, 0444);
> > +MODULE_PARM_DESC(debug, "activates MC API");
> 
> Shouldn't this be 
> 	MODULE_PARM_DESC(mc_api, "activates MC API");
> instead?

Of course :-) Thanks for catching this wrong copy&paste, I'll fix it.

> > +
> >  /* ------------------------------------------------------------------
> >   *	Format Handling
> >   * ------------------------------------------------------------------
> > @@ -655,13 +659,17 @@ static int cal_async_notifier_complete(struct v4l2_async_notifier *notifier)
> >  {
> >  	struct cal_dev *cal = container_of(notifier, struct cal_dev, notifier);
> >  	unsigned int i;
> > +	int ret = 0;
> >  
> >  	for (i = 0; i < ARRAY_SIZE(cal->ctx); ++i) {
> >  		if (cal->ctx[i])
> >  			cal_ctx_v4l2_register(cal->ctx[i]);
> >  	}
> >  
> > -	return 0;
> > +	if (cal_mc_api)
> > +		ret = v4l2_device_register_subdev_nodes(&cal->v4l2_dev);
> > +
> > +	return ret;
> >  }
> >  
> >  static const struct v4l2_async_notifier_operations cal_async_notifier_ops = {
> > diff --git a/drivers/media/platform/ti-vpe/cal.h b/drivers/media/platform/ti-vpe/cal.h
> > index 036b944c3862..f6b4c9a73aab 100644
> > --- a/drivers/media/platform/ti-vpe/cal.h
> > +++ b/drivers/media/platform/ti-vpe/cal.h
> > @@ -160,6 +160,7 @@ struct cal_camerarx {
> >  	struct device_node	*sensor_ep_node;
> >  	struct device_node	*sensor_node;
> >  	struct v4l2_subdev	*sensor;
> > +	struct media_pipeline	pipe;
> >  
> >  	struct v4l2_subdev	subdev;
> >  	struct media_pad	pads[2];
> > @@ -224,6 +225,7 @@ struct cal_ctx {
> >  
> >  extern unsigned int cal_debug;
> >  extern int cal_video_nr;
> > +extern bool cal_mc_api;
> >  
> >  #define cal_dbg(level, cal, fmt, arg...)				\
> >  	do {								\

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support
  2020-06-16 11:43 ` [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Tomi Valkeinen
@ 2020-06-19 17:04   ` Laurent Pinchart
  0 siblings, 0 replies; 150+ messages in thread
From: Laurent Pinchart @ 2020-06-19 17:04 UTC (permalink / raw)
  To: Tomi Valkeinen; +Cc: linux-media, Benoit Parrot

Hi Tomi,

On Tue, Jun 16, 2020 at 02:43:09PM +0300, Tomi Valkeinen wrote:
> Hi Laurent,
> 
> On 15/06/2020 02:57, Laurent Pinchart wrote:
> > Hello,
> > 
> > This small patch series adds media controller support to the ti-cal
> > driver.
> 
> I did some small testing on AM6, and after third module unload I got:

My bad, it's a bug in "media: ti-vpe: cal: Create subdev for CAMERARX"
that erronously calls of_node_put(phy->sensor_ep_node) on success. I'll
fix it in v2.

> [   75.292797] OF: ERROR: Bad of_node_put() on /interconnect@100000/i2c@2010000/ov5640@3c/port/endpoint
> [   75.292839] ------------[ cut here ]------------
> [   75.292849] refcount_t: addition on 0; use-after-free.
> [   75.292856] WARNING: CPU: 0 PID: 421 at lib/refcount.c:25 refcount_warn_saturate+0xa0/0x148
> [   75.292861] Modules linked in: ov5640 ti_cal(-) tidss ti_tfp410 tc358767 display_connector phy_j721e_wiz phy_cadence_torrent panel_simple drm_kms_helper drm drm_panel_orientation_quirks cfbfillrect cfbimgblt cfbcopyarea [last unloaded: ov5640]
> [   75.292935] CPU: 0 PID: 421 Comm: rmmod Not tainted 5.8.0-rc1-00107-g5de7cabe3995 #6
> [   75.292941] Hardware name: Texas Instruments AM654 Base Board (DT)
> [   75.292946] pstate: 00000085 (nzcv daIf -PAN -UAO BTYPE=--)
> [   75.292951] pc : refcount_warn_saturate+0xa0/0x148
> [   75.292956] lr : refcount_warn_saturate+0xa0/0x148
> [   75.292961] sp : ffff80001324f760
> [   75.292965] x29: ffff80001324f760 x28: ffff0a00ffffff05 
> [   75.292978] x27: ffff800011f2731a x26: ffff800010e21c28 
> [   75.292991] x25: ffff800010b6d468 x24: ffff00087ff30338 
> [   75.293003] x23: ffff800011f276d8 x22: 0000000000000005 
> [   75.293016] x21: 0000000000000005 x20: ffff800011f276d8 
> [   75.293028] x19: ffff00087ff30378 x18: 0000000000000000 
> [   75.293041] x17: 0000000000000000 x16: 0000000000000000 
> [   75.293054] x15: 0000000000000004 x14: 0000000000048963 
> [   75.293066] x13: 0000000000000000 x12: 0000000000000000 
> [   75.293079] x11: ffff8000116e1540 x10: 0000000000000000 
> [   75.293091] x9 : 000000006d17ab9f x8 : 612d657375203b30 
> [   75.293104] x7 : 206e6f206e6f6974 x6 : ffff00087f823c12 
> [   75.293116] x5 : 0000000000000000 x4 : ffff00087f823bb0 
> [   75.293128] x3 : 0000000000000000 x2 : 0000000000000023 
> [   75.293141] x1 : 2e76dc4eebb2b000 x0 : 0000000000000000 
> [   75.293153] Call trace:
> [   75.293158]  refcount_warn_saturate+0xa0/0x148
> [   75.293163]  kobject_get+0x40/0xb0
> [   75.293168]  of_node_get+0x20/0x38
> [   75.293172]  of_fwnode_get+0x34/0x58
> [   75.293177]  fwnode_get_nth_parent+0x34/0x78
> [   75.293182]  fwnode_full_name_string+0x4c/0xc8
> [   75.293187]  device_node_string+0x318/0x3f0
> [   75.293192]  pointer+0x204/0x2e0
> [   75.293196]  vsnprintf+0x204/0x728
> [   75.293201]  vscnprintf+0x30/0x68
> [   75.293206]  vprintk_store+0x64/0x210
> [   75.293210]  vprintk_emit+0xd4/0x340
> [   75.293215]  vprintk_default+0x3c/0x48
> [   75.293219]  vprintk_func+0xec/0x258
> [   75.293224]  printk+0x60/0x84
> [   75.293229]  of_node_release+0xcc/0xd8
> [   75.293233]  kobject_put+0x8c/0x200
> [   75.293238]  of_node_put+0x18/0x28
> [   75.293243]  cal_camerarx_destroy+0x28/0x50 [ti_cal]
> [   75.293247]  cal_remove+0xa4/0x110 [ti_cal]
> [   75.293252]  platform_drv_remove+0x2c/0x50
> [   75.293257]  device_release_driver_internal+0xfc/0x1d0
> [   75.293262]  driver_detach+0x50/0xe0
> [   75.293267]  bus_remove_driver+0x5c/0xd8
> [   75.293272]  driver_unregister+0x30/0x60
> [   75.293276]  platform_driver_unregister+0x14/0x20
> [   75.293281]  cal_pdrv_exit+0x1c/0xb060 [ti_cal]
> [   75.293286]  __arm64_sys_delete_module+0x1a8/0x250
> [   75.293291]  el0_svc_common.constprop.0+0x74/0x198
> [   75.293296]  do_el0_svc+0x24/0x90
> [   75.293300]  el0_sync_handler+0x9c/0x1b8
> [   75.293305]  el0_sync+0x158/0x180
> [   75.293309] irq event stamp: 4884
> [   75.293315] hardirqs last  enabled at (4883): [<ffff800010235b14>] slab_free_freelist_hook+0xf4/0x190
> [   75.293322] hardirqs last disabled at (4884): [<ffff8000100cf090>] vprintk_emit+0x88/0x340
> [   75.293328] softirqs last  enabled at (4150): [<ffff800010000db8>] _stext+0x5b8/0x5fc
> [   75.293333] softirqs last disabled at (4135): [<ffff800010047f7c>] irq_exit+0x114/0x128
> [   75.293339] ---[ end trace 3ee89555752a3b07 ]---
> [   75.293344] ------------[ cut here ]------------
> [   75.293349] refcount_t: underflow; use-after-free.
> [   75.293356] WARNING: CPU: 0 PID: 421 at lib/refcount.c:28 refcount_warn_saturate+0xf4/0x148
> [   75.293360] Modules linked in: ov5640 ti_cal(-) tidss ti_tfp410 tc358767 display_connector phy_j721e_wiz phy_cadence_torrent panel_simple drm_kms_helper drm drm_panel_orientation_quirks cfbfillrect cfbimgblt cfbcopyarea [last unloaded: ov5640]
> [   75.293433] CPU: 0 PID: 421 Comm: rmmod Tainted: G        W         5.8.0-rc1-00107-g5de7cabe3995 #6
> [   75.293438] Hardware name: Texas Instruments AM654 Base Board (DT)
> [   75.293443] pstate: 00000085 (nzcv daIf -PAN -UAO BTYPE=--)
> [   75.293448] pc : refcount_warn_saturate+0xf4/0x148
> [   75.293453] lr : refcount_warn_saturate+0xf4/0x148
> [   75.293458] sp : ffff80001324f740
> [   75.293462] x29: ffff80001324f740 x28: ffff0a00ffffff05 
> [   75.293475] x27: ffff800011f2731a x26: ffff800010e21c28 
> [   75.293487] x25: ffff800010b6d468 x24: ffff00087ff30338 
> [   75.293500] x23: ffff800011f276d8 x22: 0000000000000005 
> [   75.293512] x21: 0000000000000005 x20: ffff00087ff30208 
> [   75.293525] x19: ffff00087ff30378 x18: 0000000000000000 
> [   75.293537] x17: 0000000000000000 x16: 0000000000000000 
> [   75.293550] x15: 0000000000000004 x14: 0000000000048963 
> [   75.293562] x13: 0000000000000000 x12: 0000000000000000 
> [   75.293574] x11: ffff8000116e1540 x10: 0000000000000000 
> [   75.293587] x9 : 000000006d17ab9f x8 : 72657466612d6573 
> [   75.293600] x7 : 75203b776f6c6672 x6 : ffff00087f8246d1 
> [   75.293612] x5 : 0000000000000000 x4 : ffff00087f823bb0 
> [   75.293625] x3 : 0000000000000000 x2 : 0000000000000023 
> [   75.293637] x1 : 2e76dc4eebb2b000 x0 : 0000000000000000 
> [   75.293650] Call trace:
> [   75.293655]  refcount_warn_saturate+0xf4/0x148
> [   75.293659]  kobject_put+0x140/0x200
> [   75.293664]  of_node_put+0x18/0x28
> [   75.293668]  of_fwnode_put+0x34/0x48
> [   75.293673]  fwnode_get_next_parent+0x48/0x80
> [   75.293678]  fwnode_get_nth_parent+0x4c/0x78
> [   75.293683]  fwnode_full_name_string+0x4c/0xc8
> [   75.293688]  device_node_string+0x318/0x3f0
> [   75.293693]  pointer+0x204/0x2e0
> [   75.293697]  vsnprintf+0x204/0x728
> [   75.293702]  vscnprintf+0x30/0x68
> [   75.293706]  vprintk_store+0x64/0x210
> [   75.293711]  vprintk_emit+0xd4/0x340
> [   75.293715]  vprintk_default+0x3c/0x48
> [   75.293720]  vprintk_func+0xec/0x258
> [   75.293724]  printk+0x60/0x84
> [   75.293729]  of_node_release+0xcc/0xd8
> [   75.293734]  kobject_put+0x8c/0x200
> [   75.293738]  of_node_put+0x18/0x28
> [   75.293743]  cal_camerarx_destroy+0x28/0x50 [ti_cal]
> [   75.293748]  cal_remove+0xa4/0x110 [ti_cal]
> [   75.293753]  platform_drv_remove+0x2c/0x50
> [   75.293758]  device_release_driver_internal+0xfc/0x1d0
> [   75.293763]  driver_detach+0x50/0xe0
> [   75.293768]  bus_remove_driver+0x5c/0xd8
> [   75.293772]  driver_unregister+0x30/0x60
> [   75.293777]  platform_driver_unregister+0x14/0x20
> [   75.293782]  cal_pdrv_exit+0x1c/0xb060 [ti_cal]
> [   75.293787]  __arm64_sys_delete_module+0x1a8/0x250
> [   75.293792]  el0_svc_common.constprop.0+0x74/0x198
> [   75.293796]  do_el0_svc+0x24/0x90
> [   75.293801]  el0_sync_handler+0x9c/0x1b8
> [   75.293806]  el0_sync+0x158/0x180
> [   75.293810] irq event stamp: 4884
> [   75.293816] hardirqs last  enabled at (4883): [<ffff800010235b14>] slab_free_freelist_hook+0xf4/0x190
> [   75.293822] hardirqs last disabled at (4884): [<ffff8000100cf090>] vprintk_emit+0x88/0x340
> [   75.293828] softirqs last  enabled at (4150): [<ffff800010000db8>] _stext+0x5b8/0x5fc
> [   75.293834] softirqs last disabled at (4135): [<ffff800010047f7c>] irq_exit+0x114/0x128
> [   75.293839] ---[ end trace 3ee89555752a3b08 ]---
> [   75.293844] ------------[ cut here ]------------
> [   75.293849] refcount_t: saturated; leaking memory.
> [   75.293855] WARNING: CPU: 0 PID: 421 at lib/refcount.c:22 refcount_warn_saturate+0x74/0x148
> [   75.293859] Modules linked in: ov5640 ti_cal(-) tidss ti_tfp410 tc358767 display_connector phy_j721e_wiz phy_cadence_torrent panel_simple drm_kms_helper drm drm_panel_orientation_quirks cfbfillrect cfbimgblt cfbcopyarea [last unloaded: ov5640]
> [   75.293932] CPU: 0 PID: 421 Comm: rmmod Tainted: G        W         5.8.0-rc1-00107-g5de7cabe3995 #6
> [   75.293938] Hardware name: Texas Instruments AM654 Base Board (DT)
> [   75.293943] pstate: 00000085 (nzcv daIf -PAN -UAO BTYPE=--)
> [   75.293948] pc : refcount_warn_saturate+0x74/0x148
> [   75.293952] lr : refcount_warn_saturate+0x74/0x148
> [   75.293957] sp : ffff80001324f760
> [   75.293961] x29: ffff80001324f760 x28: ffff0a00ffffff05 
> [   75.293974] x27: ffff800011f2731a x26: ffff800010e21c28 
> [   75.293986] x25: ffff800010b6d468 x24: ffff00087ff30338 
> [   75.293999] x23: ffff800011f276d8 x22: 0000000000000004 
> [   75.294011] x21: 0000000000000004 x20: ffff0000ffffff00 
> [   75.294024] x19: ffff00087ff30378 x18: 0000000000000000 
> [   75.294036] x17: 0000000000000000 x16: 0000000000000000 
> [   75.294049] x15: 0000000000000004 x14: 0000000000048963 
> [   75.294061] x13: 0000000000000000 x12: 0000000000000000 
> [   75.294073] x11: ffff8000116e1540 x10: 0000000000000000 
> [   75.294086] x9 : 00000000fffffffe x8 : 6c203b6465746172 
> [   75.294098] x7 : 75746173203a745f x6 : ffff00087f8251c4 
> [   75.294111] x5 : 0000000000000000 x4 : ffff00087f823bb0 
> [   75.294123] x3 : 0000000000000000 x2 : 0000000000000023 
> [   75.294136] x1 : 2e76dc4eebb2b000 x0 : 0000000000000000 
> [   75.294148] Call trace:
> [   75.294153]  refcount_warn_saturate+0x74/0x148
> [   75.294157]  kobject_get+0x78/0xb0
> [   75.294162]  of_node_get+0x20/0x38
> [   75.294166]  of_fwnode_get+0x34/0x58
> [   75.294171]  fwnode_get_nth_parent+0x34/0x78
> [   75.294176]  fwnode_full_name_string+0x4c/0xc8
> [   75.294181]  device_node_string+0x318/0x3f0
> [   75.294186]  pointer+0x204/0x2e0
> [   75.294190]  vsnprintf+0x204/0x728
> [   75.294195]  vscnprintf+0x30/0x68
> [   75.294199]  vprintk_store+0x64/0x210
> [   75.294204]  vprintk_emit+0xd4/0x340
> [   75.294208]  vprintk_default+0x3c/0x48
> [   75.294213]  vprintk_func+0xec/0x258
> [   75.294218]  printk+0x60/0x84
> [   75.294222]  of_node_release+0xcc/0xd8
> [   75.294227]  kobject_put+0x8c/0x200
> [   75.294231]  of_node_put+0x18/0x28
> [   75.294236]  cal_camerarx_destroy+0x28/0x50 [ti_cal]
> [   75.294241]  cal_remove+0xa4/0x110 [ti_cal]
> [   75.294246]  platform_drv_remove+0x2c/0x50
> [   75.294251]  device_release_driver_internal+0xfc/0x1d0
> [   75.294255]  driver_detach+0x50/0xe0
> [   75.294260]  bus_remove_driver+0x5c/0xd8
> [   75.294265]  driver_unregister+0x30/0x60
> [   75.294270]  platform_driver_unregister+0x14/0x20
> [   75.294275]  cal_pdrv_exit+0x1c/0xb060 [ti_cal]
> [   75.294280]  __arm64_sys_delete_module+0x1a8/0x250
> [   75.294285]  el0_svc_common.constprop.0+0x74/0x198
> [   75.294289]  do_el0_svc+0x24/0x90
> [   75.294294]  el0_sync_handler+0x9c/0x1b8
> [   75.294299]  el0_sync+0x158/0x180
> [   75.294303] irq event stamp: 4884
> [   75.294309] hardirqs last  enabled at (4883): [<ffff800010235b14>] slab_free_freelist_hook+0xf4/0x190
> [   75.294315] hardirqs last disabled at (4884): [<ffff8000100cf090>] vprintk_emit+0x88/0x340
> [   75.294320] softirqs last  enabled 
> [   75.294329] Lost 2 message(s)!
> [   76.258340] CPU: 1 PID: 421 Comm: rmmod Tainted: G        W         5.8.0-rc1-00107-g5de7cabe3995 #6
> [   76.267490] Hardware name: Texas Instruments AM654 Base Board (DT)
> [   76.273689] Call trace:
> [   76.276160]  dump_backtrace+0x0/0x1d8
> [   76.279843]  show_stack+0x18/0x28
> [   76.283177]  dump_stack+0xe4/0x150
> [   76.286596]  of_node_release+0xd0/0xd8
> [   76.290360]  kobject_put+0x8c/0x200
> [   76.293864]  of_node_put+0x18/0x28
> [   76.297296]  cal_camerarx_destroy+0x28/0x50 [ti_cal]
> [   76.302283]  cal_remove+0xa4/0x110 [ti_cal]
> [   76.306484]  platform_drv_remove+0x2c/0x50
> [   76.310597]  device_release_driver_internal+0xfc/0x1d0
> [   76.315748]  driver_detach+0x50/0xe0
> [   76.319338]  bus_remove_driver+0x5c/0xd8
> [   76.323274]  driver_unregister+0x30/0x60
> [   76.327211]  platform_driver_unregister+0x14/0x20
> [   76.331936]  cal_pdrv_exit+0x1c/0xb060 [ti_cal]
> [   76.336483]  __arm64_sys_delete_module+0x1a8/0x250
> [   76.341289]  el0_svc_common.constprop.0+0x74/0x198
> [   76.346094]  do_el0_svc+0x24/0x90
> [   76.349426]  el0_sync_handler+0x9c/0x1b8
> [   76.353361]  el0_sync+0x158/0x180

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH v1 082/107] media: ti-vpe: cal: Move CAL I/O accessors to cal.h
  2020-06-19 15:40     ` Laurent Pinchart
@ 2020-06-19 17:18       ` Benoit Parrot
  0 siblings, 0 replies; 150+ messages in thread
From: Benoit Parrot @ 2020-06-19 17:18 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: Ezequiel Garcia, linux-media, Tomi Valkeinen

> > 
> > Slightly unrelated, have you considered moving all of these to regmap?
> > 
> > Perhaps it will make the code more maintainable.
> 
> I'm considering it now :-) Benoit, Tomi, any objection ? Otherwise I'll
> try to switch to regmap on top of this series.

No objection from me.

Benoit

> 
> -- 
> Regards,
> 
> Laurent Pinchart

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

* Re: [PATCH v1 055/107] media: ti-vpe: cal: Unregister video device before cleanup
  2020-06-14 23:58 ` [PATCH v1 055/107] media: ti-vpe: cal: Unregister video device before cleanup Laurent Pinchart
@ 2020-06-23 11:01   ` Tomi Valkeinen
  0 siblings, 0 replies; 150+ messages in thread
From: Tomi Valkeinen @ 2020-06-23 11:01 UTC (permalink / raw)
  To: Laurent Pinchart, linux-media; +Cc: Benoit Parrot

On 15/06/2020 02:58, Laurent Pinchart wrote:
> In cal_remove(), unregister the video devices as the first operation,
> before cleaning up the V4L2 objects, to avoid user-after-free. This

"use"

  Tomi

-- 
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki

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

end of thread, other threads:[~2020-06-23 11:01 UTC | newest]

Thread overview: 150+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-06-14 23:57 [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Laurent Pinchart
2020-06-14 23:57 ` [PATCH v1 001/107] media: ti-vpe: cal: Sort headers alphabetically Laurent Pinchart
2020-06-14 23:57 ` [PATCH v1 002/107] media: ti-vpe: cal: Avoid function forward declaration Laurent Pinchart
2020-06-14 23:58 ` [PATCH v1 003/107] media: ti-vpe: cal: Decouple CSI2 port and CPORT Laurent Pinchart
2020-06-14 23:58 ` [PATCH v1 004/107] media: ti-vpe: cal: Index CSI-2 port starting at 0 Laurent Pinchart
2020-06-14 23:58 ` [PATCH v1 005/107] media: ti-vpe: cal: Index IRQ registersstarting " Laurent Pinchart
2020-06-14 23:58 ` [PATCH v1 006/107] media: ti-vpe: cal: Merge all status variables in IRQ handler Laurent Pinchart
2020-06-16 10:32   ` Tomi Valkeinen
2020-06-16 10:44     ` Laurent Pinchart
2020-06-16 10:49       ` Tomi Valkeinen
2020-06-14 23:58 ` [PATCH v1 007/107] media: ti-vpe: cal: Inline CAL_VERSION macro in its only user Laurent Pinchart
2020-06-14 23:58 ` [PATCH v1 008/107] media: ti-vpe: cal: Turn reg_(read|write)_field() into inline functions Laurent Pinchart
2020-06-18 13:29   ` Benoit Parrot
2020-06-19 15:15     ` Laurent Pinchart
2020-06-14 23:58 ` [PATCH v1 009/107] media: ti-vpe: cal: Make cal_formats array const Laurent Pinchart
2020-06-14 23:58 ` [PATCH v1 010/107] media: ti-vpe: cal: Remove needless variable initialization Laurent Pinchart
2020-06-14 23:58 ` [PATCH v1 011/107] media: ti-vpe: cal: Remove needless casts Laurent Pinchart
2020-06-14 23:58 ` [PATCH v1 012/107] media: ti-vpe: cal: Turn boolean variable into bool Laurent Pinchart
2020-06-14 23:58 ` [PATCH v1 013/107] media: ti-vpe: cal: Make loop indices unsigned where applicable Laurent Pinchart
2020-06-14 23:58 ` [PATCH v1 014/107] media: ti-vpe: cal: Embed base_fields array in struct cal_csi2_phy Laurent Pinchart
2020-06-14 23:58 ` [PATCH v1 015/107] media: ti-vpe: cal: Don't modify cal_csi2_phy base_fields Laurent Pinchart
2020-06-14 23:58 ` [PATCH v1 016/107] media: ti-vpe: cal: Store PHY regmap fields in struct cc_data Laurent Pinchart
2020-06-14 23:58 ` [PATCH v1 017/107] media: ti-vpe: cal: Rename cal_csi2_phy base_fields to fields Laurent Pinchart
2020-06-14 23:58 ` [PATCH v1 018/107] media: ti-vpe: cal: Make structure fields unsigned where applicable Laurent Pinchart
2020-06-14 23:58 ` [PATCH v1 019/107] media: ti-vpe: cal: Constify platform data Laurent Pinchart
2020-06-14 23:58 ` [PATCH v1 020/107] media: ti-vpe: cal: Remove static const cal_regmap_config template Laurent Pinchart
2020-06-14 23:58 ` [PATCH v1 021/107] media: ti-vpe: cal: Remove unused structure fields Laurent Pinchart
2020-06-14 23:58 ` [PATCH v1 022/107] media: ti-vpe: cal: Remove flags field from struct cal_dev Laurent Pinchart
2020-06-14 23:58 ` [PATCH v1 023/107] media: ti-vpe: cal: Move function to avoid forward declaration Laurent Pinchart
2020-06-14 23:58 ` [PATCH v1 024/107] media: ti-vpe: cal: Rename cc_data to cal_camerarx Laurent Pinchart
2020-06-14 23:58 ` [PATCH v1 025/107] media: ti-vpe: cal: Rename cal_csi2_phy to cal_camerarx_data Laurent Pinchart
2020-06-14 23:58 ` [PATCH v1 026/107] media: ti-vpe: cal: Name all cal_dev pointers consistently Laurent Pinchart
2020-06-14 23:58 ` [PATCH v1 027/107] media: ti-vpe: cal: Name all cal_camerarx " Laurent Pinchart
2020-06-16 10:58   ` Tomi Valkeinen
2020-06-18 14:06   ` Benoit Parrot
2020-06-18 14:15     ` Laurent Pinchart
2020-06-14 23:58 ` [PATCH v1 028/107] media: ti-vpe: cal: Remove internal phy structure from cal_camerarx Laurent Pinchart
2020-06-18 14:08   ` Benoit Parrot
2020-06-14 23:58 ` [PATCH v1 029/107] media: ti-vpe: cal: Store instance ID and cal pointer in cal_camerarx Laurent Pinchart
2020-06-14 23:58 ` [PATCH v1 030/107] media: ti-vpe: cal: Use dev_* print macros Laurent Pinchart
2020-06-18 18:28   ` Benoit Parrot
2020-06-19 15:22     ` Laurent Pinchart
2020-06-14 23:58 ` [PATCH v1 031/107] media: ti-vpe: cal: Add print macros for the cal_camerarx instances Laurent Pinchart
2020-06-14 23:58 ` [PATCH v1 032/107] media: ti-vpe: cal: Store sensor-related data in cal_camerarx Laurent Pinchart
2020-06-14 23:58 ` [PATCH v1 033/107] media: ti-vpe: cal: Create consistent naming for CAMERARX functions Laurent Pinchart
2020-06-14 23:58 ` [PATCH v1 034/107] media: ti-vpe: cal: Group CAMERARX-related functions together Laurent Pinchart
2020-06-14 23:58 ` [PATCH v1 035/107] media: ti-vpe: cal: Create consistent naming for context functions Laurent Pinchart
2020-06-14 23:58 ` [PATCH v1 036/107] media: ti-vpe: cal: Reorganize remaining code in sections Laurent Pinchart
2020-06-17 10:00   ` Kieran Bingham
2020-06-17 10:02     ` [PATCH] media: ti-vpe: cal: Use cal_data_get_num_csi2_phy() consistently Kieran Bingham
2020-06-17 11:44       ` [PATCH] media: ti-vpe: cal: Handle multiple PHYs Kieran Bingham
2020-06-17 10:51     ` [PATCH v1 036/107] media: ti-vpe: cal: Reorganize remaining code in sections Laurent Pinchart
2020-06-17 10:54       ` Kieran Bingham
2020-06-17 11:01         ` Kieran Bingham
2020-06-17 11:04           ` Laurent Pinchart
2020-06-17 11:49             ` Kieran Bingham
2020-06-14 23:58 ` [PATCH v1 037/107] media: ti-vpe: cal: Rename cal_ctx.csi2_port to cal_ctx.index Laurent Pinchart
2020-06-14 23:58 ` [PATCH v1 038/107] media: ti-vpe: cal: Use correct device name for bus_info Laurent Pinchart
2020-06-14 23:58 ` [PATCH v1 039/107] media: ti-vpe: cal: Get struct device without going through v4l2_device Laurent Pinchart
2020-06-14 23:58 ` [PATCH v1 040/107] media: ti-vpe: cal: Use ctx_info() instead of v4l2_info() Laurent Pinchart
2020-06-14 23:58 ` [PATCH v1 041/107] media: ti-vpe: cal: Use a loop to create CAMERARX and context instances Laurent Pinchart
2020-06-14 23:58 ` [PATCH v1 042/107] media: ti-vpe: cal: Drop struct cal_dev v4l2_dev field Laurent Pinchart
2020-06-14 23:58 ` [PATCH v1 043/107] media: ti-vpe: cal: Split CAMERARX syscon regmap retrieval to a function Laurent Pinchart
2020-06-14 23:58 ` [PATCH v1 044/107] media: ti-vpe: cal: Use syscon_regmap_lookup_by_phandle_args() Laurent Pinchart
2020-06-14 23:58 ` [PATCH v1 045/107] media: ti-vpe: cal: Inline cal_get_camerarx_regmap() in caller Laurent Pinchart
2020-06-14 23:58 ` [PATCH v1 046/107] media: ti-vpe: cal: Add comments to cal_probe() to delimitate sections Laurent Pinchart
2020-06-14 23:58 ` [PATCH v1 047/107] media: ti-vpe: cal: Rename cal_create_instance() to cal_ctx_create() Laurent Pinchart
2020-06-14 23:58 ` [PATCH v1 048/107] media: ti-vpe: cal: Hardcode virtual channel to 0 Laurent Pinchart
2020-06-14 23:58 ` [PATCH v1 049/107] media: ti-vpe: cal: Use of_graph_get_endpoint_by_regs() to parse OF Laurent Pinchart
2020-06-14 23:58 ` [PATCH v1 050/107] media: ti-vpe: cal: Fix usage of v4l2_fwnode_endpoint_parse() Laurent Pinchart
2020-06-16 11:28   ` Tomi Valkeinen
2020-06-14 23:58 ` [PATCH v1 051/107] media: ti-vpe: cal: Decouple control handler from v4l2_device Laurent Pinchart
2020-06-14 23:58 ` [PATCH v1 052/107] media: ti-vpe: cal: Move v4l2_device from cal_ctx to cal_dev Laurent Pinchart
2020-06-14 23:58 ` [PATCH v1 053/107] media: ti-vpe: cal: Split video device initialization and registration Laurent Pinchart
2020-06-14 23:58 ` [PATCH v1 054/107] media: ti-vpe: cal: Add context V4L2 cleanup and unregister functions Laurent Pinchart
2020-06-14 23:58 ` [PATCH v1 055/107] media: ti-vpe: cal: Unregister video device before cleanup Laurent Pinchart
2020-06-23 11:01   ` Tomi Valkeinen
2020-06-14 23:58 ` [PATCH v1 056/107] media: ti-vpe: cal: Add cal_camerarx_destroy() to cleanup CAMERARX Laurent Pinchart
2020-06-17 10:43   ` Kieran Bingham
2020-06-19 15:36     ` Laurent Pinchart
2020-06-14 23:58 ` [PATCH v1 057/107] media: ti-vpe: cal: Move DT parsing to CAMERARX Laurent Pinchart
2020-06-14 23:58 ` [PATCH v1 058/107] media: ti-vpe: cal: Use ARRAY_SIZE to replace numerical value Laurent Pinchart
2020-06-14 23:58 ` [PATCH v1 059/107] media: ti-vpe: cal: Move all sensor-related init to .bound() notifier Laurent Pinchart
2020-06-14 23:58 ` [PATCH v1 060/107] media: ti-vpe: cal: Allow multiple contexts per subdev notifier Laurent Pinchart
2020-06-14 23:58 ` [PATCH v1 061/107] media: ti-vpe: cal: Move async notifiers from contexts to cal_dev Laurent Pinchart
2020-06-14 23:58 ` [PATCH v1 062/107] media: ti-vpe: cal: Replace context with phy in async notifier entries Laurent Pinchart
2020-06-14 23:59 ` [PATCH v1 063/107] media: ti-vpe: cal: Operate on phy instances in cal_quickdump_regs() Laurent Pinchart
2020-06-14 23:59 ` [PATCH v1 064/107] media: ti-vpe: cal: Decouple context and phy cleanup at remove time Laurent Pinchart
2020-06-14 23:59 ` [PATCH v1 065/107] media: ti-vpe: cal: Move CAL_NUM_CSI2_PORTS from cal_regs.h to cal.c Laurent Pinchart
2020-06-14 23:59 ` [PATCH v1 066/107] media: ti-vpe: cal: Remove isvcirqset() and isportirqset() macros Laurent Pinchart
2020-06-14 23:59 ` [PATCH v1 067/107] media: ti-vpe: cal: Replace number of ports numerical value by macro Laurent Pinchart
2020-06-14 23:59 ` [PATCH v1 068/107] media: ti-vpe: cal: Split media initialization and cleanup to functions Laurent Pinchart
2020-06-18 19:17   ` Benoit Parrot
2020-06-14 23:59 ` [PATCH v1 069/107] media: ti-vpe: cal: Read hardware revision earlier during probe Laurent Pinchart
2020-06-14 23:59 ` [PATCH v1 070/107] media: ti-vpe: cal: Print revision and hwinfo in a more readable format Laurent Pinchart
2020-06-14 23:59 ` [PATCH v1 071/107] media: ti-vpe: cal: Store struct device in cal_dev Laurent Pinchart
2020-06-14 23:59 ` [PATCH v1 072/107] media: ti-vpe: cal: Register a media device Laurent Pinchart
2020-06-14 23:59 ` [PATCH v1 073/107] media: ti-vpe: cal: Init formats in cal_ctx_v4l2_register() Laurent Pinchart
2020-06-14 23:59 ` [PATCH v1 074/107] media: ti-vpe: cal: Allocate cal_ctx active_fmt array dynamically Laurent Pinchart
2020-06-14 23:59 ` [PATCH v1 075/107] media: ti-vpe: cal: Inline cal_camerarx_max_lanes() in its only caller Laurent Pinchart
2020-06-14 23:59 ` [PATCH v1 076/107] media: ti-vpe: cal: Reorder camerarx functions to prepare refactoring Laurent Pinchart
2020-06-14 23:59 ` [PATCH v1 077/107] media: ti-vpe: cal: Refactor camerarx start and stop Laurent Pinchart
2020-06-14 23:59 ` [PATCH v1 078/107] media: ti-vpe: cal: Don't store external rate in cal_camerarx Laurent Pinchart
2020-06-17  9:56   ` Kieran Bingham
2020-06-17 10:05     ` Laurent Pinchart
2020-06-17 10:16       ` Kieran Bingham
2020-06-18  2:36         ` Laurent Pinchart
2020-06-18  8:07           ` Kieran Bingham
2020-06-14 23:59 ` [PATCH v1 079/107] media: ti-vpe: cal: Remove unneeded phy->sensor NULL check Laurent Pinchart
2020-06-14 23:59 ` [PATCH v1 080/107] media: ti-vpe: cal: Use 'unsigned int' type instead of 'unsigned' Laurent Pinchart
2020-06-14 23:59 ` [PATCH v1 081/107] media: ti-vpe: cal: Split video node handling to cal-video.c Laurent Pinchart
2020-06-14 23:59 ` [PATCH v1 082/107] media: ti-vpe: cal: Move CAL I/O accessors to cal.h Laurent Pinchart
2020-06-15  2:50   ` kernel test robot
2020-06-15  2:50     ` kernel test robot
2020-06-19  4:18   ` Ezequiel Garcia
2020-06-19 15:40     ` Laurent Pinchart
2020-06-19 17:18       ` Benoit Parrot
2020-06-14 23:59 ` [PATCH v1 083/107] media: ti-vpe: cal: Split CAMERARX handling to cal-camerarx.c Laurent Pinchart
2020-06-14 23:59 ` [PATCH v1 084/107] media: ti-vpe: cal: Create subdev for CAMERARX Laurent Pinchart
2020-06-17 10:10   ` Kieran Bingham
2020-06-19 15:52     ` Laurent Pinchart
2020-06-14 23:59 ` [PATCH v1 085/107] media: ti-vpe: cal: Drop cal_ctx m_fmt field Laurent Pinchart
2020-06-14 23:59 ` [PATCH v1 086/107] media: ti-vpe: cal: Move format handling to cal.c and expose helpers Laurent Pinchart
2020-06-14 23:59 ` [PATCH v1 087/107] media: ti-vpe: cal: Rename MAX_(WIDTH|HEIGHT)_* macros with CAL_ prefix Laurent Pinchart
2020-06-14 23:59 ` [PATCH v1 088/107] media: ti-vpe: cal: Replace hardcoded BIT() value with macro Laurent Pinchart
2020-06-14 23:59 ` [PATCH v1 089/107] media: ti-vpe: cal: Iterate over correct number of CAMERARX instances Laurent Pinchart
2020-06-14 23:59 ` [PATCH v1 090/107] media: ti-vpe: cal: Implement subdev ops for CAMERARX Laurent Pinchart
2020-06-14 23:59 ` [PATCH v1 091/107] media: ti-vpe: cal: Use CAMERARX subdev s_stream op in video device code Laurent Pinchart
2020-06-14 23:59 ` [PATCH v1 092/107] media: ti-vpe: cal: Don't pass format to cal_ctx_wr_dma_config() Laurent Pinchart
2020-06-14 23:59 ` [PATCH v1 093/107] media: ti-vpe: cal: Rename struct cal_fmt to cal_format_info Laurent Pinchart
2020-06-14 23:59 ` [PATCH v1 094/107] media: ti-vpe: cal: Refactor interrupt enable/disable Laurent Pinchart
2020-06-14 23:59 ` [PATCH v1 095/107] media: ti-vpe: cal: Fold PPI enable in CAMERARX .s_stream() Laurent Pinchart
2020-06-14 23:59 ` [PATCH v1 096/107] media: ti-vpe: cal: Stop write DMA without disabling PPI Laurent Pinchart
2020-06-14 23:59 ` [PATCH v1 097/107] media: ti-vpe: cal: Use spin_lock_irq() when starting or stopping stream Laurent Pinchart
2020-06-14 23:59 ` [PATCH v1 098/107] media: ti-vpe: cal: Share buffer release code between start and stop Laurent Pinchart
2020-06-14 23:59 ` [PATCH v1 099/107] media: ti-vpe: cal: Drop V4L2_CAP_READWRITE Laurent Pinchart
2020-06-14 23:59 ` [PATCH v1 100/107] media: ti-vpe: cal: Drop unneeded check in cal_calc_format_size() Laurent Pinchart
2020-06-14 23:59 ` [PATCH v1 101/107] media: ti-vpe: cal: Remove DMA queue empty check at start streaming time Laurent Pinchart
2020-06-14 23:59 ` [PATCH v1 102/107] media: ti-vpe: cal: Use list_first_entry() Laurent Pinchart
2020-06-14 23:59 ` [PATCH v1 103/107] media: ti-vpe: cal: Group all DMA queue fields in struct cal_dmaqueue Laurent Pinchart
2020-06-14 23:59 ` [PATCH v1 104/107] media: ti-vpe: cal: Set cal_dmaqueue.pending to NULL when no pending buffer Laurent Pinchart
2020-06-14 23:59 ` [PATCH v1 105/107] media: ti-vpe: cal: Store buffer DMA address in dma_addr_t Laurent Pinchart
2020-06-14 23:59 ` [PATCH v1 106/107] media: ti-vpe: cal: Simplify the context API Laurent Pinchart
2020-06-14 23:59 ` [PATCH v1 107/107] media: ti-vpe: cal: Implement media controller centric API Laurent Pinchart
2020-06-19 14:46   ` Benoit Parrot
2020-06-19 15:58     ` Laurent Pinchart
2020-06-16 11:43 ` [PATCH v1 000/107] media: ti-vpe: cal: Add media controller support Tomi Valkeinen
2020-06-19 17:04   ` Laurent Pinchart
2020-06-19 14:53 ` Benoit Parrot
2020-06-19 14:57   ` Benoit Parrot

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.