* [PATCH 00/16] media: sun6i-csi/isp MC-centric support and cleanups
@ 2026-05-18 10:24 Paul Kocialkowski
2026-05-18 10:24 ` [PATCH 01/16] media: sun6i-csi: bridge: Use V4L2 subdev active state Paul Kocialkowski
` (16 more replies)
0 siblings, 17 replies; 24+ messages in thread
From: Paul Kocialkowski @ 2026-05-18 10:24 UTC (permalink / raw)
To: linux-media, linux-arm-kernel, linux-sunxi, linux-kernel,
linux-staging
Cc: Paul Kocialkowski, Mauro Carvalho Chehab, Chen-Yu Tsai,
Jernej Skrabec, Samuel Holland, Greg Kroah-Hartman, Arash Golgol,
Laurent Pinchart, Nicolas Dufresne
This series first introduces some fixes and new formats to v4l2 format
info, one of which we need for the sun6i-csi driver. Support for
MC-centric format enumeration is then added, along with cleanups and
improvements for both the sun6i-csi and sun6i-isp drivers.
The first 4 patches are already reviewed and ready to go and are
included here as a reminder that this series depends on them.
Arash Golgol (4):
media: sun6i-csi: bridge: Use V4L2 subdev active state
media: sun6i-csi: capture: Implement vidioc_enum_framesizes
media: sun6i-mipi-csi2: Use V4L2 subdev active state
media: sun8i-a83t-mipi-csi2: Use V4L2 subdev active state
Paul Kocialkowski (12):
media: v4l2-common: Fix NV15_4L4 format info block height
media: v4l2-common: Add missing tiled format info block sizes
media: v4l2-common: Add NV12_16L16 pixel format to v4l2 format info
media: v4l2-common: Add NV12_32L32 pixel format to v4l2 format info
media: sun6i-csi: Split format validation to a dedicated helper
media: sun6i-csi: Add support for MC-centric format enumeration
media: sun6i-csi: Tidy up and unify coding style
media: sun6i-mipi-csi2: Fix parenthesis alignment
media: sun6i-isp: Add dummy params link_validate implementation
media: sun6i-isp: Use V4L2 subdev active state
media: sun6i-isp: Add support for MC-centric format enumeration
media: sun6i-isp: Add support for frame size enumeration
.../sunxi/sun6i-csi/sun6i_csi_bridge.c | 153 +++++++---------
.../sunxi/sun6i-csi/sun6i_csi_bridge.h | 9 -
.../sunxi/sun6i-csi/sun6i_csi_capture.c | 168 +++++++++++++-----
.../sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.c | 107 ++++++-----
.../sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.h | 2 -
.../sun8i_a83t_mipi_csi2.c | 113 ++++++------
.../sun8i_a83t_mipi_csi2.h | 2 -
drivers/media/v4l2-core/v4l2-common.c | 12 +-
.../media/sunxi/sun6i-isp/sun6i_isp_capture.c | 47 ++++-
.../media/sunxi/sun6i-isp/sun6i_isp_params.c | 37 +++-
.../media/sunxi/sun6i-isp/sun6i_isp_params.h | 4 +-
.../media/sunxi/sun6i-isp/sun6i_isp_proc.c | 117 ++++++------
.../media/sunxi/sun6i-isp/sun6i_isp_proc.h | 7 -
13 files changed, 437 insertions(+), 341 deletions(-)
--
2.54.0
^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH 01/16] media: sun6i-csi: bridge: Use V4L2 subdev active state
2026-05-18 10:24 [PATCH 00/16] media: sun6i-csi/isp MC-centric support and cleanups Paul Kocialkowski
@ 2026-05-18 10:24 ` Paul Kocialkowski
2026-05-18 10:24 ` [PATCH 02/16] media: sun6i-csi: capture: Implement vidioc_enum_framesizes Paul Kocialkowski
` (15 subsequent siblings)
16 siblings, 0 replies; 24+ messages in thread
From: Paul Kocialkowski @ 2026-05-18 10:24 UTC (permalink / raw)
To: linux-media, linux-arm-kernel, linux-sunxi, linux-kernel,
linux-staging
Cc: Paul Kocialkowski, Mauro Carvalho Chehab, Chen-Yu Tsai,
Jernej Skrabec, Samuel Holland, Greg Kroah-Hartman, Arash Golgol,
Laurent Pinchart, Nicolas Dufresne
From: Arash Golgol <arash.golgol@gmail.com>
Use the V4L2 subdev active state API to store the active format.
This simplifies the driver not only by dropping the bridge mbus_format
field, but it also allows dropping the bridge lock, replaced with
the state lock.
Previously, capture accessed bridge private state directly. After
moving to framework-managed state, resolve the format through the
subdev pad API.
The sun6i-csi-bridge hardware does not perform any format conversion.
Enforce identical formats on the sink and source pads in the set_fmt()
and init_state() callbacks.
Signed-off-by: Arash Golgol <arash.golgol@gmail.com>
Reviewed-by: Paul Kocialkowski <paulk@sys-base.io>
Tested-by: Paul Kocialkowski <paulk@sys-base.io>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
.../sunxi/sun6i-csi/sun6i_csi_bridge.c | 155 ++++++++----------
.../sunxi/sun6i-csi/sun6i_csi_bridge.h | 9 -
.../sunxi/sun6i-csi/sun6i_csi_capture.c | 27 ++-
3 files changed, 86 insertions(+), 105 deletions(-)
diff --git a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_bridge.c b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_bridge.c
index d006d9dd0170..43a85bcc2ba2 100644
--- a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_bridge.c
+++ b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_bridge.c
@@ -13,26 +13,6 @@
#include "sun6i_csi_bridge.h"
#include "sun6i_csi_reg.h"
-/* Helpers */
-
-void sun6i_csi_bridge_dimensions(struct sun6i_csi_device *csi_dev,
- unsigned int *width, unsigned int *height)
-{
- if (width)
- *width = csi_dev->bridge.mbus_format.width;
- if (height)
- *height = csi_dev->bridge.mbus_format.height;
-}
-
-void sun6i_csi_bridge_format(struct sun6i_csi_device *csi_dev,
- u32 *mbus_code, u32 *field)
-{
- if (mbus_code)
- *mbus_code = csi_dev->bridge.mbus_format.code;
- if (field)
- *field = csi_dev->bridge.mbus_format.field;
-}
-
/* Format */
static const struct sun6i_csi_bridge_format sun6i_csi_bridge_formats[] = {
@@ -226,7 +206,8 @@ static void sun6i_csi_bridge_disable(struct sun6i_csi_device *csi_dev)
}
static void
-sun6i_csi_bridge_configure_parallel(struct sun6i_csi_device *csi_dev)
+sun6i_csi_bridge_configure_parallel(struct sun6i_csi_device *csi_dev,
+ const struct v4l2_mbus_framefmt *mbus_format)
{
struct device *dev = csi_dev->dev;
struct regmap *regmap = csi_dev->regmap;
@@ -234,11 +215,9 @@ sun6i_csi_bridge_configure_parallel(struct sun6i_csi_device *csi_dev)
&csi_dev->bridge.source_parallel.endpoint;
unsigned char bus_width = endpoint->bus.parallel.bus_width;
unsigned int flags = endpoint->bus.parallel.flags;
- u32 field;
+ u32 field = mbus_format->field;
u32 value = SUN6I_CSI_IF_CFG_IF_CSI;
- sun6i_csi_bridge_format(csi_dev, NULL, &field);
-
if (field == V4L2_FIELD_INTERLACED ||
field == V4L2_FIELD_INTERLACED_TB ||
field == V4L2_FIELD_INTERLACED_BT)
@@ -317,13 +296,12 @@ sun6i_csi_bridge_configure_parallel(struct sun6i_csi_device *csi_dev)
}
static void
-sun6i_csi_bridge_configure_mipi_csi2(struct sun6i_csi_device *csi_dev)
+sun6i_csi_bridge_configure_mipi_csi2(struct sun6i_csi_device *csi_dev,
+ const struct v4l2_mbus_framefmt *mbus_format)
{
struct regmap *regmap = csi_dev->regmap;
u32 value = SUN6I_CSI_IF_CFG_IF_MIPI;
- u32 field;
-
- sun6i_csi_bridge_format(csi_dev, NULL, &field);
+ u32 field = mbus_format->field;
if (field == V4L2_FIELD_INTERLACED ||
field == V4L2_FIELD_INTERLACED_TB ||
@@ -335,19 +313,20 @@ sun6i_csi_bridge_configure_mipi_csi2(struct sun6i_csi_device *csi_dev)
regmap_write(regmap, SUN6I_CSI_IF_CFG_REG, value);
}
-static void sun6i_csi_bridge_configure_format(struct sun6i_csi_device *csi_dev)
+static void
+sun6i_csi_bridge_configure_format(struct sun6i_csi_device *csi_dev,
+ const struct v4l2_mbus_framefmt *mbus_format)
{
struct regmap *regmap = csi_dev->regmap;
bool capture_streaming = csi_dev->capture.state.streaming;
const struct sun6i_csi_bridge_format *bridge_format;
const struct sun6i_csi_capture_format *capture_format;
- u32 mbus_code, field, pixelformat;
+ u32 pixelformat;
+ u32 field = mbus_format->field;
u8 input_format, input_yuv_seq, output_format;
u32 value = 0;
- sun6i_csi_bridge_format(csi_dev, &mbus_code, &field);
-
- bridge_format = sun6i_csi_bridge_format_find(mbus_code);
+ bridge_format = sun6i_csi_bridge_format_find(mbus_format->code);
if (WARN_ON(!bridge_format))
return;
@@ -391,16 +370,17 @@ static void sun6i_csi_bridge_configure_format(struct sun6i_csi_device *csi_dev)
}
static void sun6i_csi_bridge_configure(struct sun6i_csi_device *csi_dev,
- struct sun6i_csi_bridge_source *source)
+ struct sun6i_csi_bridge_source *source,
+ const struct v4l2_mbus_framefmt *mbus_format)
{
struct sun6i_csi_bridge *bridge = &csi_dev->bridge;
if (source == &bridge->source_parallel)
- sun6i_csi_bridge_configure_parallel(csi_dev);
+ sun6i_csi_bridge_configure_parallel(csi_dev, mbus_format);
else
- sun6i_csi_bridge_configure_mipi_csi2(csi_dev);
+ sun6i_csi_bridge_configure_mipi_csi2(csi_dev, mbus_format);
- sun6i_csi_bridge_configure_format(csi_dev);
+ sun6i_csi_bridge_configure_format(csi_dev, mbus_format);
}
/* V4L2 Subdev */
@@ -415,6 +395,8 @@ static int sun6i_csi_bridge_s_stream(struct v4l2_subdev *subdev, int on)
struct sun6i_csi_bridge_source *source;
struct v4l2_subdev *source_subdev;
struct media_pad *remote_pad;
+ struct v4l2_subdev_state *state;
+ const struct v4l2_mbus_framefmt *mbus_format;
int ret;
/* Source */
@@ -433,6 +415,10 @@ static int sun6i_csi_bridge_s_stream(struct v4l2_subdev *subdev, int on)
else
source = &bridge->source_mipi_csi2;
+ /* Active State */
+
+ state = v4l2_subdev_lock_and_get_active_state(subdev);
+
if (!on) {
v4l2_subdev_call(source_subdev, video, s_stream, 0);
ret = 0;
@@ -443,7 +429,7 @@ static int sun6i_csi_bridge_s_stream(struct v4l2_subdev *subdev, int on)
ret = pm_runtime_resume_and_get(dev);
if (ret < 0)
- return ret;
+ goto unlock;
/* Clear */
@@ -451,7 +437,9 @@ static int sun6i_csi_bridge_s_stream(struct v4l2_subdev *subdev, int on)
/* Configure */
- sun6i_csi_bridge_configure(csi_dev, source);
+ mbus_format = v4l2_subdev_state_get_format(state,
+ SUN6I_CSI_BRIDGE_PAD_SINK);
+ sun6i_csi_bridge_configure(csi_dev, source, mbus_format);
if (capture_streaming)
sun6i_csi_capture_configure(csi_dev);
@@ -472,7 +460,8 @@ static int sun6i_csi_bridge_s_stream(struct v4l2_subdev *subdev, int on)
if (ret && ret != -ENOIOCTLCMD)
goto disable;
- return 0;
+ ret = 0;
+ goto unlock;
disable:
if (capture_streaming)
@@ -482,6 +471,8 @@ static int sun6i_csi_bridge_s_stream(struct v4l2_subdev *subdev, int on)
pm_runtime_put(dev);
+unlock:
+ v4l2_subdev_unlock_state(state);
return ret;
}
@@ -504,21 +495,23 @@ sun6i_csi_bridge_mbus_format_prepare(struct v4l2_mbus_framefmt *mbus_format)
static int sun6i_csi_bridge_init_state(struct v4l2_subdev *subdev,
struct v4l2_subdev_state *state)
{
- struct sun6i_csi_device *csi_dev = v4l2_get_subdevdata(subdev);
- unsigned int pad = SUN6I_CSI_BRIDGE_PAD_SINK;
- struct v4l2_mbus_framefmt *mbus_format =
- v4l2_subdev_state_get_format(state, pad);
- struct mutex *lock = &csi_dev->bridge.lock;
+ unsigned int pad;
- mutex_lock(lock);
+ /*
+ * This subdev does not perform format conversion,
+ * initialize both pads identically.
+ */
+ for (pad = 0; pad < subdev->entity.num_pads; pad++) {
+ struct v4l2_mbus_framefmt *mbus_format;
- mbus_format->code = sun6i_csi_bridge_formats[0].mbus_code;
- mbus_format->width = 1280;
- mbus_format->height = 720;
+ mbus_format = v4l2_subdev_state_get_format(state, pad);
- sun6i_csi_bridge_mbus_format_prepare(mbus_format);
+ mbus_format->code = sun6i_csi_bridge_formats[0].mbus_code;
+ mbus_format->width = 1280;
+ mbus_format->height = 720;
- mutex_unlock(lock);
+ sun6i_csi_bridge_mbus_format_prepare(mbus_format);
+ }
return 0;
}
@@ -536,53 +529,32 @@ sun6i_csi_bridge_enum_mbus_code(struct v4l2_subdev *subdev,
return 0;
}
-static int sun6i_csi_bridge_get_fmt(struct v4l2_subdev *subdev,
- struct v4l2_subdev_state *state,
- struct v4l2_subdev_format *format)
-{
- struct sun6i_csi_device *csi_dev = v4l2_get_subdevdata(subdev);
- struct v4l2_mbus_framefmt *mbus_format = &format->format;
- struct mutex *lock = &csi_dev->bridge.lock;
-
- mutex_lock(lock);
-
- if (format->which == V4L2_SUBDEV_FORMAT_TRY)
- *mbus_format = *v4l2_subdev_state_get_format(state,
- format->pad);
- else
- *mbus_format = csi_dev->bridge.mbus_format;
-
- mutex_unlock(lock);
-
- return 0;
-}
-
static int sun6i_csi_bridge_set_fmt(struct v4l2_subdev *subdev,
struct v4l2_subdev_state *state,
struct v4l2_subdev_format *format)
{
- struct sun6i_csi_device *csi_dev = v4l2_get_subdevdata(subdev);
- struct v4l2_mbus_framefmt *mbus_format = &format->format;
- struct mutex *lock = &csi_dev->bridge.lock;
+ struct v4l2_mbus_framefmt *fmt;
- mutex_lock(lock);
+ /* The format on the source pad always matches the sink pad. */
+ if (format->pad != SUN6I_CSI_BRIDGE_PAD_SINK)
+ return v4l2_subdev_get_fmt(subdev, state, format);
- sun6i_csi_bridge_mbus_format_prepare(mbus_format);
+ sun6i_csi_bridge_mbus_format_prepare(&format->format);
- if (format->which == V4L2_SUBDEV_FORMAT_TRY)
- *v4l2_subdev_state_get_format(state, format->pad) =
- *mbus_format;
- else
- csi_dev->bridge.mbus_format = *mbus_format;
+ /* Set the format on the sink pad. */
+ fmt = v4l2_subdev_state_get_format(state, format->pad);
+ *fmt = format->format;
- mutex_unlock(lock);
+ /* Propagate the format to the source pad. */
+ fmt = v4l2_subdev_state_get_format(state, SUN6I_CSI_BRIDGE_PAD_SOURCE);
+ *fmt = format->format;
return 0;
}
static const struct v4l2_subdev_pad_ops sun6i_csi_bridge_pad_ops = {
.enum_mbus_code = sun6i_csi_bridge_enum_mbus_code,
- .get_fmt = sun6i_csi_bridge_get_fmt,
+ .get_fmt = v4l2_subdev_get_fmt,
.set_fmt = sun6i_csi_bridge_set_fmt,
};
@@ -780,8 +752,6 @@ int sun6i_csi_bridge_setup(struct sun6i_csi_device *csi_dev)
};
int ret;
- mutex_init(&bridge->lock);
-
/* V4L2 Subdev */
v4l2_subdev_init(subdev, &sun6i_csi_bridge_subdev_ops);
@@ -809,6 +779,12 @@ int sun6i_csi_bridge_setup(struct sun6i_csi_device *csi_dev)
if (ret < 0)
return ret;
+ /* V4L2 Subdev finalize */
+
+ ret = v4l2_subdev_init_finalize(subdev);
+ if (ret < 0)
+ goto error_media_entity;
+
/* V4L2 Subdev */
if (csi_dev->isp_available)
@@ -818,7 +794,7 @@ int sun6i_csi_bridge_setup(struct sun6i_csi_device *csi_dev)
if (ret) {
dev_err(dev, "failed to register v4l2 subdev: %d\n", ret);
- goto error_media_entity;
+ goto error_subdev_finalize;
}
/* V4L2 Async */
@@ -852,6 +828,9 @@ int sun6i_csi_bridge_setup(struct sun6i_csi_device *csi_dev)
else
v4l2_device_unregister_subdev(subdev);
+error_subdev_finalize:
+ v4l2_subdev_cleanup(subdev);
+
error_media_entity:
media_entity_cleanup(&subdev->entity);
@@ -868,5 +847,7 @@ void sun6i_csi_bridge_cleanup(struct sun6i_csi_device *csi_dev)
v4l2_device_unregister_subdev(subdev);
+ v4l2_subdev_cleanup(subdev);
+
media_entity_cleanup(&subdev->entity);
}
diff --git a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_bridge.h b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_bridge.h
index 44653b38f722..a5b0a6f064dd 100644
--- a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_bridge.h
+++ b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_bridge.h
@@ -42,20 +42,11 @@ struct sun6i_csi_bridge {
struct v4l2_subdev subdev;
struct v4l2_async_notifier notifier;
struct media_pad pads[2];
- struct v4l2_mbus_framefmt mbus_format;
- struct mutex lock; /* Mbus format lock. */
struct sun6i_csi_bridge_source source_parallel;
struct sun6i_csi_bridge_source source_mipi_csi2;
};
-/* Helpers */
-
-void sun6i_csi_bridge_dimensions(struct sun6i_csi_device *csi_dev,
- unsigned int *width, unsigned int *height);
-void sun6i_csi_bridge_format(struct sun6i_csi_device *csi_dev,
- u32 *mbus_code, u32 *field);
-
/* Format */
const struct sun6i_csi_bridge_format *
diff --git a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_capture.c b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_capture.c
index 65879f4802c0..d90abba21309 100644
--- a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_capture.c
+++ b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_capture.c
@@ -888,14 +888,19 @@ static int sun6i_csi_capture_link_validate(struct media_link *link)
media_entity_to_video_device(link->sink->entity);
struct sun6i_csi_device *csi_dev = video_get_drvdata(video_dev);
struct v4l2_device *v4l2_dev = csi_dev->v4l2_dev;
+ struct v4l2_subdev *src_subdev =
+ media_entity_to_v4l2_subdev(link->source->entity);
const struct sun6i_csi_capture_format *capture_format;
const struct sun6i_csi_bridge_format *bridge_format;
unsigned int capture_width, capture_height;
- unsigned int bridge_width, bridge_height;
const struct v4l2_format_info *format_info;
+ struct v4l2_subdev_format src_fmt = {
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ .pad = link->source->index
+ };
u32 pixelformat, capture_field;
- u32 mbus_code, bridge_field;
bool match;
+ int ret;
sun6i_csi_capture_dimensions(csi_dev, &capture_width, &capture_height);
@@ -904,19 +909,22 @@ static int sun6i_csi_capture_link_validate(struct media_link *link)
if (WARN_ON(!capture_format))
return -EINVAL;
- sun6i_csi_bridge_dimensions(csi_dev, &bridge_width, &bridge_height);
+ /* Resolve csi bridge format. */
+ ret = v4l2_subdev_call(src_subdev, pad, get_fmt, NULL, &src_fmt);
+ if (ret)
+ return ret;
- sun6i_csi_bridge_format(csi_dev, &mbus_code, &bridge_field);
- bridge_format = sun6i_csi_bridge_format_find(mbus_code);
+ bridge_format = sun6i_csi_bridge_format_find(src_fmt.format.code);
if (WARN_ON(!bridge_format))
return -EINVAL;
/* No cropping/scaling is supported. */
- if (capture_width != bridge_width || capture_height != bridge_height) {
+ if (capture_width != src_fmt.format.width ||
+ capture_height != src_fmt.format.height) {
v4l2_err(v4l2_dev,
"invalid input/output dimensions: %ux%u/%ux%u\n",
- bridge_width, bridge_height, capture_width,
- capture_height);
+ src_fmt.format.width, src_fmt.format.height,
+ capture_width, capture_height);
return -EINVAL;
}
@@ -947,7 +955,8 @@ static int sun6i_csi_capture_link_validate(struct media_link *link)
/* With raw input mode, we need a 1:1 match between input and output. */
if (bridge_format->input_format == SUN6I_CSI_INPUT_FMT_RAW ||
capture_format->input_format_raw) {
- match = sun6i_csi_capture_format_match(pixelformat, mbus_code);
+ match = sun6i_csi_capture_format_match(pixelformat,
+ src_fmt.format.code);
if (!match)
goto invalid;
}
--
2.54.0
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 02/16] media: sun6i-csi: capture: Implement vidioc_enum_framesizes
2026-05-18 10:24 [PATCH 00/16] media: sun6i-csi/isp MC-centric support and cleanups Paul Kocialkowski
2026-05-18 10:24 ` [PATCH 01/16] media: sun6i-csi: bridge: Use V4L2 subdev active state Paul Kocialkowski
@ 2026-05-18 10:24 ` Paul Kocialkowski
2026-05-18 10:24 ` [PATCH 03/16] media: sun6i-mipi-csi2: Use V4L2 subdev active state Paul Kocialkowski
` (14 subsequent siblings)
16 siblings, 0 replies; 24+ messages in thread
From: Paul Kocialkowski @ 2026-05-18 10:24 UTC (permalink / raw)
To: linux-media, linux-arm-kernel, linux-sunxi, linux-kernel,
linux-staging
Cc: Paul Kocialkowski, Mauro Carvalho Chehab, Chen-Yu Tsai,
Jernej Skrabec, Samuel Holland, Greg Kroah-Hartman, Arash Golgol,
Laurent Pinchart, Nicolas Dufresne
From: Arash Golgol <arash.golgol@gmail.com>
Report the stepwise frame size range supported by the CSI capture
hardware for the pixel formats exposed by the driver.
The hardware does not perform scaling and accepts any even width and
height within the reported limits.
Signed-off-by: Arash Golgol <arash.golgol@gmail.com>
Reviewed-by: Paul Kocialkowski <paulk@sys-base.io>
Tested-by: Paul Kocialkowski <paulk@sys-base.io>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
.../sunxi/sun6i-csi/sun6i_csi_capture.c | 22 +++++++++++++++++++
1 file changed, 22 insertions(+)
diff --git a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_capture.c b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_capture.c
index d90abba21309..f788b4234673 100644
--- a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_capture.c
+++ b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_capture.c
@@ -738,6 +738,27 @@ static int sun6i_csi_capture_enum_fmt(struct file *file, void *priv,
return 0;
}
+static int sun6i_csi_capture_enum_framesize(struct file *file, void *fh,
+ struct v4l2_frmsizeenum *fsize)
+{
+ if (fsize->index)
+ return -EINVAL;
+
+ /* Only accept format in map table. */
+ if (!sun6i_csi_capture_format_find(fsize->pixel_format))
+ return -EINVAL;
+
+ fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
+ fsize->stepwise.min_width = SUN6I_CSI_CAPTURE_WIDTH_MIN;
+ fsize->stepwise.max_width = SUN6I_CSI_CAPTURE_WIDTH_MAX;
+ fsize->stepwise.min_height = SUN6I_CSI_CAPTURE_HEIGHT_MIN;
+ fsize->stepwise.max_height = SUN6I_CSI_CAPTURE_HEIGHT_MAX;
+ fsize->stepwise.step_width = 2;
+ fsize->stepwise.step_height = 2;
+
+ return 0;
+}
+
static int sun6i_csi_capture_g_fmt(struct file *file, void *priv,
struct v4l2_format *format)
{
@@ -805,6 +826,7 @@ static const struct v4l2_ioctl_ops sun6i_csi_capture_ioctl_ops = {
.vidioc_querycap = sun6i_csi_capture_querycap,
.vidioc_enum_fmt_vid_cap = sun6i_csi_capture_enum_fmt,
+ .vidioc_enum_framesizes = sun6i_csi_capture_enum_framesize,
.vidioc_g_fmt_vid_cap = sun6i_csi_capture_g_fmt,
.vidioc_s_fmt_vid_cap = sun6i_csi_capture_s_fmt,
.vidioc_try_fmt_vid_cap = sun6i_csi_capture_try_fmt,
--
2.54.0
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 03/16] media: sun6i-mipi-csi2: Use V4L2 subdev active state
2026-05-18 10:24 [PATCH 00/16] media: sun6i-csi/isp MC-centric support and cleanups Paul Kocialkowski
2026-05-18 10:24 ` [PATCH 01/16] media: sun6i-csi: bridge: Use V4L2 subdev active state Paul Kocialkowski
2026-05-18 10:24 ` [PATCH 02/16] media: sun6i-csi: capture: Implement vidioc_enum_framesizes Paul Kocialkowski
@ 2026-05-18 10:24 ` Paul Kocialkowski
2026-05-18 10:24 ` [PATCH 04/16] media: sun8i-a83t-mipi-csi2: " Paul Kocialkowski
` (13 subsequent siblings)
16 siblings, 0 replies; 24+ messages in thread
From: Paul Kocialkowski @ 2026-05-18 10:24 UTC (permalink / raw)
To: linux-media, linux-arm-kernel, linux-sunxi, linux-kernel,
linux-staging
Cc: Paul Kocialkowski, Mauro Carvalho Chehab, Chen-Yu Tsai,
Jernej Skrabec, Samuel Holland, Greg Kroah-Hartman, Arash Golgol,
Laurent Pinchart, Nicolas Dufresne
From: Arash Golgol <arash.golgol@gmail.com>
Use the V4L2 subdev active state API to store the active format.
This simplifies the driver not only by dropping the bridge mbus_format
field, but it also allows dropping the bridge lock, replaced with
the state lock.
The sun6i-mipi-csi2 hardware does not perform any format conversion.
Enforce identical formats on the sink and source pads in the set_fmt()
and init_state() callbacks.
Signed-off-by: Arash Golgol <arash.golgol@gmail.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
.../sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.c | 107 +++++++++---------
.../sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.h | 2 -
2 files changed, 53 insertions(+), 56 deletions(-)
diff --git a/drivers/media/platform/sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.c b/drivers/media/platform/sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.c
index b06cb73015cd..682bdd82098c 100644
--- a/drivers/media/platform/sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.c
+++ b/drivers/media/platform/sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.c
@@ -95,12 +95,12 @@ static void sun6i_mipi_csi2_disable(struct sun6i_mipi_csi2_device *csi2_dev)
SUN6I_MIPI_CSI2_CTL_EN, 0);
}
-static void sun6i_mipi_csi2_configure(struct sun6i_mipi_csi2_device *csi2_dev)
+static void sun6i_mipi_csi2_configure(struct sun6i_mipi_csi2_device *csi2_dev,
+ const struct v4l2_mbus_framefmt *mbus_format)
{
struct regmap *regmap = csi2_dev->regmap;
unsigned int lanes_count =
csi2_dev->bridge.endpoint.bus.mipi_csi2.num_data_lanes;
- struct v4l2_mbus_framefmt *mbus_format = &csi2_dev->bridge.mbus_format;
const struct sun6i_mipi_csi2_format *format;
struct device *dev = csi2_dev->dev;
u32 version = 0;
@@ -173,7 +173,8 @@ static int sun6i_mipi_csi2_s_stream(struct v4l2_subdev *subdev, int on)
struct v4l2_subdev *source_subdev = csi2_dev->bridge.source_subdev;
union phy_configure_opts dphy_opts = { 0 };
struct phy_configure_opts_mipi_dphy *dphy_cfg = &dphy_opts.mipi_dphy;
- struct v4l2_mbus_framefmt *mbus_format = &csi2_dev->bridge.mbus_format;
+ struct v4l2_subdev_state *state;
+ const struct v4l2_mbus_framefmt *mbus_format;
const struct sun6i_mipi_csi2_format *format;
struct phy *dphy = csi2_dev->dphy;
struct device *dev = csi2_dev->dev;
@@ -183,8 +184,12 @@ static int sun6i_mipi_csi2_s_stream(struct v4l2_subdev *subdev, int on)
unsigned long pixel_rate;
int ret;
- if (!source_subdev)
- return -ENODEV;
+ state = v4l2_subdev_lock_and_get_active_state(subdev);
+
+ if (!source_subdev) {
+ ret = -ENODEV;
+ goto unlock;
+ }
if (!on) {
v4l2_subdev_call(source_subdev, video, s_stream, 0);
@@ -196,7 +201,7 @@ static int sun6i_mipi_csi2_s_stream(struct v4l2_subdev *subdev, int on)
ret = pm_runtime_resume_and_get(dev);
if (ret < 0)
- return ret;
+ goto unlock;
/* Sensor Pixel Rate */
@@ -222,6 +227,8 @@ static int sun6i_mipi_csi2_s_stream(struct v4l2_subdev *subdev, int on)
goto error_pm;
}
+ mbus_format = v4l2_subdev_state_get_format(state,
+ SUN6I_MIPI_CSI2_PAD_SINK);
format = sun6i_mipi_csi2_format_find(mbus_format->code);
if (WARN_ON(!format)) {
ret = -ENODEV;
@@ -260,7 +267,7 @@ static int sun6i_mipi_csi2_s_stream(struct v4l2_subdev *subdev, int on)
/* Controller */
- sun6i_mipi_csi2_configure(csi2_dev);
+ sun6i_mipi_csi2_configure(csi2_dev, mbus_format);
sun6i_mipi_csi2_enable(csi2_dev);
/* D-PHY */
@@ -277,7 +284,8 @@ static int sun6i_mipi_csi2_s_stream(struct v4l2_subdev *subdev, int on)
if (ret && ret != -ENOIOCTLCMD)
goto disable;
- return 0;
+ ret = 0;
+ goto unlock;
disable:
phy_power_off(dphy);
@@ -286,6 +294,8 @@ static int sun6i_mipi_csi2_s_stream(struct v4l2_subdev *subdev, int on)
error_pm:
pm_runtime_put(dev);
+unlock:
+ v4l2_subdev_unlock_state(state);
return ret;
}
@@ -308,21 +318,23 @@ sun6i_mipi_csi2_mbus_format_prepare(struct v4l2_mbus_framefmt *mbus_format)
static int sun6i_mipi_csi2_init_state(struct v4l2_subdev *subdev,
struct v4l2_subdev_state *state)
{
- struct sun6i_mipi_csi2_device *csi2_dev = v4l2_get_subdevdata(subdev);
- unsigned int pad = SUN6I_MIPI_CSI2_PAD_SINK;
- struct v4l2_mbus_framefmt *mbus_format =
- v4l2_subdev_state_get_format(state, pad);
- struct mutex *lock = &csi2_dev->bridge.lock;
+ unsigned int pad;
- mutex_lock(lock);
+ /*
+ * This subdev does not perform format conversion,
+ * initialize both pads identically.
+ */
+ for (pad = 0; pad < subdev->entity.num_pads; pad++) {
+ struct v4l2_mbus_framefmt *mbus_format;
- mbus_format->code = sun6i_mipi_csi2_formats[0].mbus_code;
- mbus_format->width = 640;
- mbus_format->height = 480;
+ mbus_format = v4l2_subdev_state_get_format(state, pad);
- sun6i_mipi_csi2_mbus_format_prepare(mbus_format);
+ mbus_format->code = sun6i_mipi_csi2_formats[0].mbus_code;
+ mbus_format->width = 640;
+ mbus_format->height = 480;
- mutex_unlock(lock);
+ sun6i_mipi_csi2_mbus_format_prepare(mbus_format);
+ }
return 0;
}
@@ -340,53 +352,32 @@ sun6i_mipi_csi2_enum_mbus_code(struct v4l2_subdev *subdev,
return 0;
}
-static int sun6i_mipi_csi2_get_fmt(struct v4l2_subdev *subdev,
- struct v4l2_subdev_state *state,
- struct v4l2_subdev_format *format)
-{
- struct sun6i_mipi_csi2_device *csi2_dev = v4l2_get_subdevdata(subdev);
- struct v4l2_mbus_framefmt *mbus_format = &format->format;
- struct mutex *lock = &csi2_dev->bridge.lock;
-
- mutex_lock(lock);
-
- if (format->which == V4L2_SUBDEV_FORMAT_TRY)
- *mbus_format = *v4l2_subdev_state_get_format(state,
- format->pad);
- else
- *mbus_format = csi2_dev->bridge.mbus_format;
-
- mutex_unlock(lock);
-
- return 0;
-}
-
static int sun6i_mipi_csi2_set_fmt(struct v4l2_subdev *subdev,
struct v4l2_subdev_state *state,
struct v4l2_subdev_format *format)
{
- struct sun6i_mipi_csi2_device *csi2_dev = v4l2_get_subdevdata(subdev);
- struct v4l2_mbus_framefmt *mbus_format = &format->format;
- struct mutex *lock = &csi2_dev->bridge.lock;
+ struct v4l2_mbus_framefmt *fmt;
- mutex_lock(lock);
+ /* The format on the source pad always matches the sink pad. */
+ if (format->pad != SUN6I_MIPI_CSI2_PAD_SINK)
+ return v4l2_subdev_get_fmt(subdev, state, format);
- sun6i_mipi_csi2_mbus_format_prepare(mbus_format);
+ sun6i_mipi_csi2_mbus_format_prepare(&format->format);
- if (format->which == V4L2_SUBDEV_FORMAT_TRY)
- *v4l2_subdev_state_get_format(state, format->pad) =
- *mbus_format;
- else
- csi2_dev->bridge.mbus_format = *mbus_format;
+ /* Set the format on the sink pad. */
+ fmt = v4l2_subdev_state_get_format(state, format->pad);
+ *fmt = format->format;
- mutex_unlock(lock);
+ /* Propagate the format to the source pad. */
+ fmt = v4l2_subdev_state_get_format(state, SUN6I_MIPI_CSI2_PAD_SOURCE);
+ *fmt = format->format;
return 0;
}
static const struct v4l2_subdev_pad_ops sun6i_mipi_csi2_pad_ops = {
.enum_mbus_code = sun6i_mipi_csi2_enum_mbus_code,
- .get_fmt = sun6i_mipi_csi2_get_fmt,
+ .get_fmt = v4l2_subdev_get_fmt,
.set_fmt = sun6i_mipi_csi2_set_fmt,
};
@@ -502,8 +493,6 @@ static int sun6i_mipi_csi2_bridge_setup(struct sun6i_mipi_csi2_device *csi2_dev)
bool notifier_registered = false;
int ret;
- mutex_init(&bridge->lock);
-
/* V4L2 Subdev */
v4l2_subdev_init(subdev, &sun6i_mipi_csi2_subdev_ops);
@@ -532,6 +521,12 @@ static int sun6i_mipi_csi2_bridge_setup(struct sun6i_mipi_csi2_device *csi2_dev)
if (ret)
return ret;
+ /* V4L2 Subdev finalize */
+
+ ret = v4l2_subdev_init_finalize(subdev);
+ if (ret < 0)
+ goto error_media_entity_cleanup;
+
/* V4L2 Async */
v4l2_async_subdev_nf_init(notifier, subdev);
@@ -565,6 +560,9 @@ static int sun6i_mipi_csi2_bridge_setup(struct sun6i_mipi_csi2_device *csi2_dev)
error_v4l2_notifier_cleanup:
v4l2_async_nf_cleanup(notifier);
+ v4l2_subdev_cleanup(subdev);
+
+error_media_entity_cleanup:
media_entity_cleanup(&subdev->entity);
return ret;
@@ -579,6 +577,7 @@ sun6i_mipi_csi2_bridge_cleanup(struct sun6i_mipi_csi2_device *csi2_dev)
v4l2_async_unregister_subdev(subdev);
v4l2_async_nf_unregister(notifier);
v4l2_async_nf_cleanup(notifier);
+ v4l2_subdev_cleanup(subdev);
media_entity_cleanup(&subdev->entity);
}
diff --git a/drivers/media/platform/sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.h b/drivers/media/platform/sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.h
index 24b15e34b5e8..d72dfbd6a993 100644
--- a/drivers/media/platform/sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.h
+++ b/drivers/media/platform/sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.h
@@ -32,8 +32,6 @@ struct sun6i_mipi_csi2_bridge {
struct media_pad pads[SUN6I_MIPI_CSI2_PAD_COUNT];
struct v4l2_fwnode_endpoint endpoint;
struct v4l2_async_notifier notifier;
- struct v4l2_mbus_framefmt mbus_format;
- struct mutex lock; /* Mbus format lock. */
struct v4l2_subdev *source_subdev;
};
--
2.54.0
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 04/16] media: sun8i-a83t-mipi-csi2: Use V4L2 subdev active state
2026-05-18 10:24 [PATCH 00/16] media: sun6i-csi/isp MC-centric support and cleanups Paul Kocialkowski
` (2 preceding siblings ...)
2026-05-18 10:24 ` [PATCH 03/16] media: sun6i-mipi-csi2: Use V4L2 subdev active state Paul Kocialkowski
@ 2026-05-18 10:24 ` Paul Kocialkowski
2026-05-18 14:09 ` Paul Kocialkowski
2026-05-18 10:24 ` [PATCH 05/16] media: v4l2-common: Fix NV15_4L4 format info block height Paul Kocialkowski
` (12 subsequent siblings)
16 siblings, 1 reply; 24+ messages in thread
From: Paul Kocialkowski @ 2026-05-18 10:24 UTC (permalink / raw)
To: linux-media, linux-arm-kernel, linux-sunxi, linux-kernel,
linux-staging
Cc: Paul Kocialkowski, Mauro Carvalho Chehab, Chen-Yu Tsai,
Jernej Skrabec, Samuel Holland, Greg Kroah-Hartman, Arash Golgol,
Laurent Pinchart, Nicolas Dufresne
From: Arash Golgol <arash.golgol@gmail.com>
Use the V4L2 subdev active state API to store the active format.
This simplifies the driver not only by dropping the bridge mbus_format
field, but it also allows dropping the bridge lock, replaced with
the state lock.
The sun8i-a83t-mipi-csi2 hardware does not perform any format
conversion. Enforce identical formats on the sink and source pads in
the set_fmt() and init_state() callbacks.
Signed-off-by: Arash Golgol <arash.golgol@gmail.com>
---
.../sun8i_a83t_mipi_csi2.c | 113 +++++++++---------
.../sun8i_a83t_mipi_csi2.h | 2 -
2 files changed, 56 insertions(+), 59 deletions(-)
diff --git a/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_mipi_csi2.c b/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_mipi_csi2.c
index dbc51daa4fe3..2b7635f3952d 100644
--- a/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_mipi_csi2.c
+++ b/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_mipi_csi2.c
@@ -144,12 +144,12 @@ sun8i_a83t_mipi_csi2_disable(struct sun8i_a83t_mipi_csi2_device *csi2_dev)
}
static void
-sun8i_a83t_mipi_csi2_configure(struct sun8i_a83t_mipi_csi2_device *csi2_dev)
+sun8i_a83t_mipi_csi2_configure(struct sun8i_a83t_mipi_csi2_device *csi2_dev,
+ const struct v4l2_mbus_framefmt *mbus_format)
{
struct regmap *regmap = csi2_dev->regmap;
unsigned int lanes_count =
csi2_dev->bridge.endpoint.bus.mipi_csi2.num_data_lanes;
- struct v4l2_mbus_framefmt *mbus_format = &csi2_dev->bridge.mbus_format;
const struct sun8i_a83t_mipi_csi2_format *format;
struct device *dev = csi2_dev->dev;
u32 version = 0;
@@ -205,7 +205,8 @@ static int sun8i_a83t_mipi_csi2_s_stream(struct v4l2_subdev *subdev, int on)
struct v4l2_subdev *source_subdev = csi2_dev->bridge.source_subdev;
union phy_configure_opts dphy_opts = { 0 };
struct phy_configure_opts_mipi_dphy *dphy_cfg = &dphy_opts.mipi_dphy;
- struct v4l2_mbus_framefmt *mbus_format = &csi2_dev->bridge.mbus_format;
+ struct v4l2_subdev_state *state;
+ const struct v4l2_mbus_framefmt *mbus_format;
const struct sun8i_a83t_mipi_csi2_format *format;
struct phy *dphy = csi2_dev->dphy;
struct device *dev = csi2_dev->dev;
@@ -215,8 +216,12 @@ static int sun8i_a83t_mipi_csi2_s_stream(struct v4l2_subdev *subdev, int on)
unsigned long pixel_rate;
int ret;
- if (!source_subdev)
- return -ENODEV;
+ state = v4l2_subdev_lock_and_get_active_state(subdev);
+
+ if (!source_subdev) {
+ ret = -ENODEV;
+ goto unlock;
+ }
if (!on) {
v4l2_subdev_call(source_subdev, video, s_stream, 0);
@@ -228,7 +233,7 @@ static int sun8i_a83t_mipi_csi2_s_stream(struct v4l2_subdev *subdev, int on)
ret = pm_runtime_resume_and_get(dev);
if (ret < 0)
- return ret;
+ goto unlock;
/* Sensor pixel rate */
@@ -254,6 +259,9 @@ static int sun8i_a83t_mipi_csi2_s_stream(struct v4l2_subdev *subdev, int on)
goto error_pm;
}
+ mbus_format =
+ v4l2_subdev_state_get_format(state,
+ SUN8I_A83T_MIPI_CSI2_PAD_SINK);
format = sun8i_a83t_mipi_csi2_format_find(mbus_format->code);
if (WARN_ON(!format)) {
ret = -ENODEV;
@@ -292,7 +300,7 @@ static int sun8i_a83t_mipi_csi2_s_stream(struct v4l2_subdev *subdev, int on)
/* Controller */
- sun8i_a83t_mipi_csi2_configure(csi2_dev);
+ sun8i_a83t_mipi_csi2_configure(csi2_dev, mbus_format);
sun8i_a83t_mipi_csi2_enable(csi2_dev);
/* D-PHY */
@@ -309,7 +317,8 @@ static int sun8i_a83t_mipi_csi2_s_stream(struct v4l2_subdev *subdev, int on)
if (ret && ret != -ENOIOCTLCMD)
goto disable;
- return 0;
+ ret = 0;
+ goto unlock;
disable:
phy_power_off(dphy);
@@ -318,6 +327,8 @@ static int sun8i_a83t_mipi_csi2_s_stream(struct v4l2_subdev *subdev, int on)
error_pm:
pm_runtime_put(dev);
+unlock:
+ v4l2_subdev_unlock_state(state);
return ret;
}
@@ -341,22 +352,24 @@ sun8i_a83t_mipi_csi2_mbus_format_prepare(struct v4l2_mbus_framefmt *mbus_format)
static int sun8i_a83t_mipi_csi2_init_state(struct v4l2_subdev *subdev,
struct v4l2_subdev_state *state)
{
- struct sun8i_a83t_mipi_csi2_device *csi2_dev =
- v4l2_get_subdevdata(subdev);
- unsigned int pad = SUN8I_A83T_MIPI_CSI2_PAD_SINK;
- struct v4l2_mbus_framefmt *mbus_format =
- v4l2_subdev_state_get_format(state, pad);
- struct mutex *lock = &csi2_dev->bridge.lock;
+ unsigned int pad;
- mutex_lock(lock);
+ /*
+ * This subdev does not perform format conversion,
+ * initialize both pads identically.
+ */
+ for (pad = 0; pad < subdev->entity.num_pads; pad++) {
+ struct v4l2_mbus_framefmt *mbus_format;
- mbus_format->code = sun8i_a83t_mipi_csi2_formats[0].mbus_code;
- mbus_format->width = 640;
- mbus_format->height = 480;
+ mbus_format = v4l2_subdev_state_get_format(state, pad);
+
+ mbus_format->code = sun8i_a83t_mipi_csi2_formats[0].mbus_code;
+ mbus_format->width = 640;
+ mbus_format->height = 480;
- sun8i_a83t_mipi_csi2_mbus_format_prepare(mbus_format);
+ sun8i_a83t_mipi_csi2_mbus_format_prepare(mbus_format);
+ }
- mutex_unlock(lock);
return 0;
}
@@ -375,55 +388,33 @@ sun8i_a83t_mipi_csi2_enum_mbus_code(struct v4l2_subdev *subdev,
return 0;
}
-static int sun8i_a83t_mipi_csi2_get_fmt(struct v4l2_subdev *subdev,
- struct v4l2_subdev_state *state,
- struct v4l2_subdev_format *format)
-{
- struct sun8i_a83t_mipi_csi2_device *csi2_dev =
- v4l2_get_subdevdata(subdev);
- struct v4l2_mbus_framefmt *mbus_format = &format->format;
- struct mutex *lock = &csi2_dev->bridge.lock;
-
- mutex_lock(lock);
-
- if (format->which == V4L2_SUBDEV_FORMAT_TRY)
- *mbus_format = *v4l2_subdev_state_get_format(state,
- format->pad);
- else
- *mbus_format = csi2_dev->bridge.mbus_format;
-
- mutex_unlock(lock);
-
- return 0;
-}
-
static int sun8i_a83t_mipi_csi2_set_fmt(struct v4l2_subdev *subdev,
struct v4l2_subdev_state *state,
struct v4l2_subdev_format *format)
{
- struct sun8i_a83t_mipi_csi2_device *csi2_dev =
- v4l2_get_subdevdata(subdev);
- struct v4l2_mbus_framefmt *mbus_format = &format->format;
- struct mutex *lock = &csi2_dev->bridge.lock;
+ struct v4l2_mbus_framefmt *fmt;
- mutex_lock(lock);
+ /* The format on the source pad always matches the sink pad. */
+ if (format->pad != SUN8I_A83T_MIPI_CSI2_PAD_SINK)
+ return v4l2_subdev_get_fmt(subdev, state, format);
- sun8i_a83t_mipi_csi2_mbus_format_prepare(mbus_format);
+ sun8i_a83t_mipi_csi2_mbus_format_prepare(&format->format);
- if (format->which == V4L2_SUBDEV_FORMAT_TRY)
- *v4l2_subdev_state_get_format(state, format->pad) =
- *mbus_format;
- else
- csi2_dev->bridge.mbus_format = *mbus_format;
+ /* Set the format on the sink pad. */
+ fmt = v4l2_subdev_state_get_format(state, format->pad);
+ *fmt = format->format;
- mutex_unlock(lock);
+ /* Propagate the format to the source pad. */
+ fmt = v4l2_subdev_state_get_format(state,
+ SUN8I_A83T_MIPI_CSI2_PAD_SOURCE);
+ *fmt = format->format;
return 0;
}
static const struct v4l2_subdev_pad_ops sun8i_a83t_mipi_csi2_pad_ops = {
.enum_mbus_code = sun8i_a83t_mipi_csi2_enum_mbus_code,
- .get_fmt = sun8i_a83t_mipi_csi2_get_fmt,
+ .get_fmt = v4l2_subdev_get_fmt,
.set_fmt = sun8i_a83t_mipi_csi2_set_fmt,
};
@@ -540,8 +531,6 @@ sun8i_a83t_mipi_csi2_bridge_setup(struct sun8i_a83t_mipi_csi2_device *csi2_dev)
bool notifier_registered = false;
int ret;
- mutex_init(&bridge->lock);
-
/* V4L2 Subdev */
v4l2_subdev_init(subdev, &sun8i_a83t_mipi_csi2_subdev_ops);
@@ -570,6 +559,12 @@ sun8i_a83t_mipi_csi2_bridge_setup(struct sun8i_a83t_mipi_csi2_device *csi2_dev)
if (ret)
return ret;
+ /* V4L2 Subdev finalize */
+
+ ret = v4l2_subdev_init_finalize(subdev);
+ if (ret < 0)
+ goto error_media_entity_cleanup;
+
/* V4L2 Async */
v4l2_async_subdev_nf_init(notifier, subdev);
@@ -603,6 +598,9 @@ sun8i_a83t_mipi_csi2_bridge_setup(struct sun8i_a83t_mipi_csi2_device *csi2_dev)
error_v4l2_notifier_cleanup:
v4l2_async_nf_cleanup(notifier);
+ v4l2_subdev_cleanup(subdev);
+
+error_media_entity_cleanup:
media_entity_cleanup(&subdev->entity);
return ret;
@@ -617,6 +615,7 @@ sun8i_a83t_mipi_csi2_bridge_cleanup(struct sun8i_a83t_mipi_csi2_device *csi2_dev
v4l2_async_unregister_subdev(subdev);
v4l2_async_nf_unregister(notifier);
v4l2_async_nf_cleanup(notifier);
+ v4l2_subdev_cleanup(subdev);
media_entity_cleanup(&subdev->entity);
}
diff --git a/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_mipi_csi2.h b/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_mipi_csi2.h
index f1e64c53434c..819527bcd64d 100644
--- a/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_mipi_csi2.h
+++ b/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_mipi_csi2.h
@@ -33,8 +33,6 @@ struct sun8i_a83t_mipi_csi2_bridge {
struct media_pad pads[SUN8I_A83T_MIPI_CSI2_PAD_COUNT];
struct v4l2_fwnode_endpoint endpoint;
struct v4l2_async_notifier notifier;
- struct v4l2_mbus_framefmt mbus_format;
- struct mutex lock; /* Mbus format lock. */
struct v4l2_subdev *source_subdev;
};
--
2.54.0
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 05/16] media: v4l2-common: Fix NV15_4L4 format info block height
2026-05-18 10:24 [PATCH 00/16] media: sun6i-csi/isp MC-centric support and cleanups Paul Kocialkowski
` (3 preceding siblings ...)
2026-05-18 10:24 ` [PATCH 04/16] media: sun8i-a83t-mipi-csi2: " Paul Kocialkowski
@ 2026-05-18 10:24 ` Paul Kocialkowski
2026-05-19 15:16 ` Nicolas Dufresne
2026-05-18 10:24 ` [PATCH 06/16] media: v4l2-common: Add missing tiled format info block sizes Paul Kocialkowski
` (11 subsequent siblings)
16 siblings, 1 reply; 24+ messages in thread
From: Paul Kocialkowski @ 2026-05-18 10:24 UTC (permalink / raw)
To: linux-media, linux-arm-kernel, linux-sunxi, linux-kernel,
linux-staging
Cc: Paul Kocialkowski, Mauro Carvalho Chehab, Chen-Yu Tsai,
Jernej Skrabec, Samuel Holland, Greg Kroah-Hartman, Arash Golgol,
Laurent Pinchart, Nicolas Dufresne
The NV15_4L4 format is specified as a 4x4 format, not 4x1.
In addition the block size should not take subsampling in account,
so specify it as 4x4 for both luma and chroma.
Signed-off-by: Paul Kocialkowski <paulk@sys-base.io>
---
drivers/media/v4l2-core/v4l2-common.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/media/v4l2-core/v4l2-common.c b/drivers/media/v4l2-core/v4l2-common.c
index 554c591e1113..77a0daa92c2b 100644
--- a/drivers/media/v4l2-core/v4l2-common.c
+++ b/drivers/media/v4l2-core/v4l2-common.c
@@ -309,7 +309,7 @@ const struct v4l2_format_info *v4l2_format_info(u32 format)
/* Tiled YUV formats */
{ .format = V4L2_PIX_FMT_NV12_4L4, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2 },
{ .format = V4L2_PIX_FMT_NV15_4L4, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 5, 10, 0, 0 }, .bpp_div = { 4, 4, 1, 1 }, .hdiv = 2, .vdiv = 2,
- .block_w = { 4, 2, 0, 0 }, .block_h = { 1, 1, 0, 0 }},
+ .block_w = { 4, 4, 0, 0 }, .block_h = { 4, 4, 0, 0 }},
{ .format = V4L2_PIX_FMT_P010_4L4, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 2, 4, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2 },
/* YUV planar formats, non contiguous variant */
--
2.54.0
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 06/16] media: v4l2-common: Add missing tiled format info block sizes
2026-05-18 10:24 [PATCH 00/16] media: sun6i-csi/isp MC-centric support and cleanups Paul Kocialkowski
` (4 preceding siblings ...)
2026-05-18 10:24 ` [PATCH 05/16] media: v4l2-common: Fix NV15_4L4 format info block height Paul Kocialkowski
@ 2026-05-18 10:24 ` Paul Kocialkowski
2026-05-19 15:18 ` Nicolas Dufresne
2026-05-18 10:24 ` [PATCH 07/16] media: v4l2-common: Add NV12_16L16 pixel format to v4l2 format info Paul Kocialkowski
` (10 subsequent siblings)
16 siblings, 1 reply; 24+ messages in thread
From: Paul Kocialkowski @ 2026-05-18 10:24 UTC (permalink / raw)
To: linux-media, linux-arm-kernel, linux-sunxi, linux-kernel,
linux-staging
Cc: Paul Kocialkowski, Mauro Carvalho Chehab, Chen-Yu Tsai,
Jernej Skrabec, Samuel Holland, Greg Kroah-Hartman, Arash Golgol,
Laurent Pinchart, Nicolas Dufresne
Some YUV420 tiled format info definitions are missing block sizes.
Add the missing block sizes (they are all 4x4).
Signed-off-by: Paul Kocialkowski <paulk@sys-base.io>
---
drivers/media/v4l2-core/v4l2-common.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/media/v4l2-core/v4l2-common.c b/drivers/media/v4l2-core/v4l2-common.c
index 77a0daa92c2b..e142d40c71b9 100644
--- a/drivers/media/v4l2-core/v4l2-common.c
+++ b/drivers/media/v4l2-core/v4l2-common.c
@@ -307,10 +307,12 @@ const struct v4l2_format_info *v4l2_format_info(u32 format)
{ .format = V4L2_PIX_FMT_GREY, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
/* Tiled YUV formats */
- { .format = V4L2_PIX_FMT_NV12_4L4, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2 },
+ { .format = V4L2_PIX_FMT_NV12_4L4, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2,
+ .block_w = { 4, 4, 0, 0 }, .block_h = { 4, 4, 0, 0 }},
{ .format = V4L2_PIX_FMT_NV15_4L4, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 5, 10, 0, 0 }, .bpp_div = { 4, 4, 1, 1 }, .hdiv = 2, .vdiv = 2,
.block_w = { 4, 4, 0, 0 }, .block_h = { 4, 4, 0, 0 }},
- { .format = V4L2_PIX_FMT_P010_4L4, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 2, 4, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2 },
+ { .format = V4L2_PIX_FMT_P010_4L4, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 2, 4, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2,
+ .block_w = { 4, 4, 0, 0 }, .block_h = { 4, 4, 0, 0 }},
/* YUV planar formats, non contiguous variant */
{ .format = V4L2_PIX_FMT_YUV420M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2 },
--
2.54.0
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 07/16] media: v4l2-common: Add NV12_16L16 pixel format to v4l2 format info
2026-05-18 10:24 [PATCH 00/16] media: sun6i-csi/isp MC-centric support and cleanups Paul Kocialkowski
` (5 preceding siblings ...)
2026-05-18 10:24 ` [PATCH 06/16] media: v4l2-common: Add missing tiled format info block sizes Paul Kocialkowski
@ 2026-05-18 10:24 ` Paul Kocialkowski
2026-05-19 15:22 ` Nicolas Dufresne
2026-05-18 10:24 ` [PATCH 08/16] media: v4l2-common: Add NV12_32L32 " Paul Kocialkowski
` (9 subsequent siblings)
16 siblings, 1 reply; 24+ messages in thread
From: Paul Kocialkowski @ 2026-05-18 10:24 UTC (permalink / raw)
To: linux-media, linux-arm-kernel, linux-sunxi, linux-kernel,
linux-staging
Cc: Paul Kocialkowski, Mauro Carvalho Chehab, Chen-Yu Tsai,
Jernej Skrabec, Samuel Holland, Greg Kroah-Hartman, Arash Golgol,
Laurent Pinchart, Nicolas Dufresne
Represent the NV12_16L16 pixel format in the v4l2 format info table.
This is a 16x16 tiled version of NV12.
Signed-off-by: Paul Kocialkowski <paulk@sys-base.io>
---
drivers/media/v4l2-core/v4l2-common.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/media/v4l2-core/v4l2-common.c b/drivers/media/v4l2-core/v4l2-common.c
index e142d40c71b9..6194d6eb9c56 100644
--- a/drivers/media/v4l2-core/v4l2-common.c
+++ b/drivers/media/v4l2-core/v4l2-common.c
@@ -313,6 +313,8 @@ const struct v4l2_format_info *v4l2_format_info(u32 format)
.block_w = { 4, 4, 0, 0 }, .block_h = { 4, 4, 0, 0 }},
{ .format = V4L2_PIX_FMT_P010_4L4, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 2, 4, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2,
.block_w = { 4, 4, 0, 0 }, .block_h = { 4, 4, 0, 0 }},
+ { .format = V4L2_PIX_FMT_NV12_16L16, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2,
+ .block_w = { 16, 16, 0, 0 }, .block_h = { 16, 16, 0, 0 }},
/* YUV planar formats, non contiguous variant */
{ .format = V4L2_PIX_FMT_YUV420M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2 },
--
2.54.0
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 08/16] media: v4l2-common: Add NV12_32L32 pixel format to v4l2 format info
2026-05-18 10:24 [PATCH 00/16] media: sun6i-csi/isp MC-centric support and cleanups Paul Kocialkowski
` (6 preceding siblings ...)
2026-05-18 10:24 ` [PATCH 07/16] media: v4l2-common: Add NV12_16L16 pixel format to v4l2 format info Paul Kocialkowski
@ 2026-05-18 10:24 ` Paul Kocialkowski
2026-05-19 15:23 ` Nicolas Dufresne
2026-05-18 10:24 ` [PATCH 09/16] media: sun6i-csi: Split format validation to a dedicated helper Paul Kocialkowski
` (8 subsequent siblings)
16 siblings, 1 reply; 24+ messages in thread
From: Paul Kocialkowski @ 2026-05-18 10:24 UTC (permalink / raw)
To: linux-media, linux-arm-kernel, linux-sunxi, linux-kernel,
linux-staging
Cc: Paul Kocialkowski, Mauro Carvalho Chehab, Chen-Yu Tsai,
Jernej Skrabec, Samuel Holland, Greg Kroah-Hartman, Arash Golgol,
Laurent Pinchart, Nicolas Dufresne
Represent the NV12_32L32 pixel format in the v4l2 format info table.
This is a 32x32 tiled version of NV12.
Signed-off-by: Paul Kocialkowski <paulk@sys-base.io>
---
drivers/media/v4l2-core/v4l2-common.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/media/v4l2-core/v4l2-common.c b/drivers/media/v4l2-core/v4l2-common.c
index 6194d6eb9c56..fe7141883ec5 100644
--- a/drivers/media/v4l2-core/v4l2-common.c
+++ b/drivers/media/v4l2-core/v4l2-common.c
@@ -315,6 +315,8 @@ const struct v4l2_format_info *v4l2_format_info(u32 format)
.block_w = { 4, 4, 0, 0 }, .block_h = { 4, 4, 0, 0 }},
{ .format = V4L2_PIX_FMT_NV12_16L16, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2,
.block_w = { 16, 16, 0, 0 }, .block_h = { 16, 16, 0, 0 }},
+ { .format = V4L2_PIX_FMT_NV12_32L32, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2,
+ .block_w = { 32, 32, 0, 0 }, .block_h = { 32, 32, 0, 0 }},
/* YUV planar formats, non contiguous variant */
{ .format = V4L2_PIX_FMT_YUV420M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2 },
--
2.54.0
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 09/16] media: sun6i-csi: Split format validation to a dedicated helper
2026-05-18 10:24 [PATCH 00/16] media: sun6i-csi/isp MC-centric support and cleanups Paul Kocialkowski
` (7 preceding siblings ...)
2026-05-18 10:24 ` [PATCH 08/16] media: v4l2-common: Add NV12_32L32 " Paul Kocialkowski
@ 2026-05-18 10:24 ` Paul Kocialkowski
2026-05-18 10:24 ` [PATCH 10/16] media: sun6i-csi: Add support for MC-centric format enumeration Paul Kocialkowski
` (7 subsequent siblings)
16 siblings, 0 replies; 24+ messages in thread
From: Paul Kocialkowski @ 2026-05-18 10:24 UTC (permalink / raw)
To: linux-media, linux-arm-kernel, linux-sunxi, linux-kernel,
linux-staging
Cc: Paul Kocialkowski, Mauro Carvalho Chehab, Chen-Yu Tsai,
Jernej Skrabec, Samuel Holland, Greg Kroah-Hartman, Arash Golgol,
Laurent Pinchart, Nicolas Dufresne
Introduce a new sun6i_csi_capture_format_check helper based on the
link_validate code, which will be reused to implement MC-style
pixelformat enumeration.
Formats not listed in v4l2_format_info are now checked via
sun6i_csi_capture_format_check (which only concerns raw formats)
instead of blindly allowing them.
Also fix a comment in the raw format table.
Signed-off-by: Paul Kocialkowski <paulk@sys-base.io>
---
.../sunxi/sun6i-csi/sun6i_csi_capture.c | 87 +++++++++++--------
1 file changed, 49 insertions(+), 38 deletions(-)
diff --git a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_capture.c b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_capture.c
index f788b4234673..a836fa7f081a 100644
--- a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_capture.c
+++ b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_capture.c
@@ -213,7 +213,7 @@ struct sun6i_csi_capture_format *sun6i_csi_capture_format_find(u32 pixelformat)
/* RAW formats need an exact match between pixel and mbus formats. */
static const
struct sun6i_csi_capture_format_match sun6i_csi_capture_format_matches[] = {
- /* YUV420 */
+ /* YUV422 */
{
.pixelformat = V4L2_PIX_FMT_YUYV,
.mbus_code = MEDIA_BUS_FMT_YUYV8_2X8,
@@ -327,6 +327,51 @@ static bool sun6i_csi_capture_format_match(u32 pixelformat, u32 mbus_code)
return false;
}
+static bool
+sun6i_csi_capture_format_check(const struct sun6i_csi_capture_format *capture_format,
+ const struct sun6i_csi_bridge_format *bridge_format)
+{
+ const struct v4l2_format_info *format_info;
+ u32 pixelformat = capture_format->pixelformat;
+ u32 mbus_code = bridge_format->mbus_code;
+ bool match;
+
+ format_info = v4l2_format_info(pixelformat);
+
+ /* Some raw formats like JPEG are not listed: try a direct match. */
+ if (!format_info)
+ return sun6i_csi_capture_format_match(pixelformat, mbus_code);
+
+ if (format_info->pixel_enc == V4L2_PIXEL_ENC_BAYER &&
+ bridge_format->input_format != SUN6I_CSI_INPUT_FMT_RAW)
+ return false;
+
+ if (format_info->pixel_enc == V4L2_PIXEL_ENC_RGB &&
+ bridge_format->input_format != SUN6I_CSI_INPUT_FMT_RAW)
+ return false;
+
+ if (format_info->pixel_enc == V4L2_PIXEL_ENC_YUV) {
+ if (bridge_format->input_format != SUN6I_CSI_INPUT_FMT_YUV420 &&
+ bridge_format->input_format != SUN6I_CSI_INPUT_FMT_YUV422)
+ return false;
+
+ /* YUV420 input can't produce YUV422 output. */
+ if (bridge_format->input_format == SUN6I_CSI_INPUT_FMT_YUV420 &&
+ format_info->vdiv == 1)
+ return false;
+ }
+
+ /* With raw input mode, we need a 1:1 match between input and output. */
+ if (bridge_format->input_format == SUN6I_CSI_INPUT_FMT_RAW ||
+ capture_format->input_format_raw) {
+ match = sun6i_csi_capture_format_match(pixelformat, mbus_code);
+ if (!match)
+ return false;
+ }
+
+ return true;
+}
+
/* Capture */
static void
@@ -915,13 +960,11 @@ static int sun6i_csi_capture_link_validate(struct media_link *link)
const struct sun6i_csi_capture_format *capture_format;
const struct sun6i_csi_bridge_format *bridge_format;
unsigned int capture_width, capture_height;
- const struct v4l2_format_info *format_info;
struct v4l2_subdev_format src_fmt = {
.which = V4L2_SUBDEV_FORMAT_ACTIVE,
.pad = link->source->index
};
u32 pixelformat, capture_field;
- bool match;
int ret;
sun6i_csi_capture_dimensions(csi_dev, &capture_width, &capture_height);
@@ -950,44 +993,12 @@ static int sun6i_csi_capture_link_validate(struct media_link *link)
return -EINVAL;
}
- format_info = v4l2_format_info(pixelformat);
- /* Some formats are not listed. */
- if (!format_info)
- return 0;
-
- if (format_info->pixel_enc == V4L2_PIXEL_ENC_BAYER &&
- bridge_format->input_format != SUN6I_CSI_INPUT_FMT_RAW)
- goto invalid;
-
- if (format_info->pixel_enc == V4L2_PIXEL_ENC_RGB &&
- bridge_format->input_format != SUN6I_CSI_INPUT_FMT_RAW)
- goto invalid;
-
- if (format_info->pixel_enc == V4L2_PIXEL_ENC_YUV) {
- if (bridge_format->input_format != SUN6I_CSI_INPUT_FMT_YUV420 &&
- bridge_format->input_format != SUN6I_CSI_INPUT_FMT_YUV422)
- goto invalid;
-
- /* YUV420 input can't produce YUV422 output. */
- if (bridge_format->input_format == SUN6I_CSI_INPUT_FMT_YUV420 &&
- format_info->vdiv == 1)
- goto invalid;
- }
-
- /* With raw input mode, we need a 1:1 match between input and output. */
- if (bridge_format->input_format == SUN6I_CSI_INPUT_FMT_RAW ||
- capture_format->input_format_raw) {
- match = sun6i_csi_capture_format_match(pixelformat,
- src_fmt.format.code);
- if (!match)
- goto invalid;
+ if (!sun6i_csi_capture_format_check(capture_format, bridge_format)) {
+ v4l2_err(v4l2_dev, "invalid input/output format combination\n");
+ return -EINVAL;
}
return 0;
-
-invalid:
- v4l2_err(v4l2_dev, "invalid input/output format combination\n");
- return -EINVAL;
}
static const struct media_entity_operations sun6i_csi_capture_media_ops = {
--
2.54.0
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 10/16] media: sun6i-csi: Add support for MC-centric format enumeration
2026-05-18 10:24 [PATCH 00/16] media: sun6i-csi/isp MC-centric support and cleanups Paul Kocialkowski
` (8 preceding siblings ...)
2026-05-18 10:24 ` [PATCH 09/16] media: sun6i-csi: Split format validation to a dedicated helper Paul Kocialkowski
@ 2026-05-18 10:24 ` Paul Kocialkowski
2026-05-18 10:24 ` [PATCH 11/16] media: sun6i-csi: Tidy up and unify coding style Paul Kocialkowski
` (6 subsequent siblings)
16 siblings, 0 replies; 24+ messages in thread
From: Paul Kocialkowski @ 2026-05-18 10:24 UTC (permalink / raw)
To: linux-media, linux-arm-kernel, linux-sunxi, linux-kernel,
linux-staging
Cc: Paul Kocialkowski, Mauro Carvalho Chehab, Chen-Yu Tsai,
Jernej Skrabec, Samuel Holland, Greg Kroah-Hartman, Arash Golgol,
Laurent Pinchart, Nicolas Dufresne
Use the dedicated helper to check possible pixelformats against the
provided mbus code in order to support MC-centric format enumeration.
Note that multiple pixelformats may be returned for a given mbus code.
Signed-off-by: Paul Kocialkowski <paulk@sys-base.io>
---
.../sunxi/sun6i-csi/sun6i_csi_capture.c | 38 +++++++++++++++++--
1 file changed, 34 insertions(+), 4 deletions(-)
diff --git a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_capture.c b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_capture.c
index a836fa7f081a..409c28621093 100644
--- a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_capture.c
+++ b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_capture.c
@@ -773,14 +773,43 @@ static int sun6i_csi_capture_querycap(struct file *file, void *priv,
static int sun6i_csi_capture_enum_fmt(struct file *file, void *priv,
struct v4l2_fmtdesc *fmtdesc)
{
+ const struct sun6i_csi_capture_format *capture_format;
+ const struct sun6i_csi_bridge_format *bridge_format;
+ u32 mbus_code = fmtdesc->mbus_code;
u32 index = fmtdesc->index;
+ unsigned int index_valid = 0;
+ unsigned int i;
+
+ /* Video-node-centric enumeration. */
+ if (!mbus_code) {
+ if (index >= ARRAY_SIZE(sun6i_csi_capture_formats))
+ return -EINVAL;
+
+ fmtdesc->pixelformat =
+ sun6i_csi_capture_formats[index].pixelformat;
+ return 0;
+ }
- if (index >= ARRAY_SIZE(sun6i_csi_capture_formats))
+ bridge_format = sun6i_csi_bridge_format_find(mbus_code);
+ if (!bridge_format)
return -EINVAL;
- fmtdesc->pixelformat = sun6i_csi_capture_formats[index].pixelformat;
+ for (i = 0; i < ARRAY_SIZE(sun6i_csi_capture_formats); i++) {
+ capture_format = &sun6i_csi_capture_formats[i];
- return 0;
+ if (!sun6i_csi_capture_format_check(capture_format,
+ bridge_format))
+ continue;
+
+ if (index_valid == index) {
+ fmtdesc->pixelformat = capture_format->pixelformat;
+ return 0;
+ }
+
+ index_valid++;
+ }
+
+ return -EINVAL;
}
static int sun6i_csi_capture_enum_framesize(struct file *file, void *fh,
@@ -1076,7 +1105,8 @@ int sun6i_csi_capture_setup(struct sun6i_csi_device *csi_dev)
strscpy(video_dev->name, SUN6I_CSI_CAPTURE_NAME,
sizeof(video_dev->name));
- video_dev->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
+ video_dev->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING |
+ V4L2_CAP_IO_MC;
video_dev->vfl_dir = VFL_DIR_RX;
video_dev->release = video_device_release_empty;
video_dev->fops = &sun6i_csi_capture_fops;
--
2.54.0
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 11/16] media: sun6i-csi: Tidy up and unify coding style
2026-05-18 10:24 [PATCH 00/16] media: sun6i-csi/isp MC-centric support and cleanups Paul Kocialkowski
` (9 preceding siblings ...)
2026-05-18 10:24 ` [PATCH 10/16] media: sun6i-csi: Add support for MC-centric format enumeration Paul Kocialkowski
@ 2026-05-18 10:24 ` Paul Kocialkowski
2026-05-18 10:24 ` [PATCH 12/16] media: sun6i-mipi-csi2: Fix parenthesis alignment Paul Kocialkowski
` (5 subsequent siblings)
16 siblings, 0 replies; 24+ messages in thread
From: Paul Kocialkowski @ 2026-05-18 10:24 UTC (permalink / raw)
To: linux-media, linux-arm-kernel, linux-sunxi, linux-kernel,
linux-staging
Cc: Paul Kocialkowski, Mauro Carvalho Chehab, Chen-Yu Tsai,
Jernej Skrabec, Samuel Holland, Greg Kroah-Hartman, Arash Golgol,
Laurent Pinchart, Nicolas Dufresne
Bring recent changes to the same coding style as the rest of the driver.
This is purely cosmetic and no functional change is intended.
Signed-off-by: Paul Kocialkowski <paulk@sys-base.io>
---
.../sunxi/sun6i-csi/sun6i_csi_bridge.c | 16 ++---
.../sunxi/sun6i-csi/sun6i_csi_capture.c | 72 ++++++++++---------
2 files changed, 46 insertions(+), 42 deletions(-)
diff --git a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_bridge.c b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_bridge.c
index 43a85bcc2ba2..18f79075d3ad 100644
--- a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_bridge.c
+++ b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_bridge.c
@@ -473,6 +473,7 @@ static int sun6i_csi_bridge_s_stream(struct v4l2_subdev *subdev, int on)
unlock:
v4l2_subdev_unlock_state(state);
+
return ret;
}
@@ -533,7 +534,7 @@ static int sun6i_csi_bridge_set_fmt(struct v4l2_subdev *subdev,
struct v4l2_subdev_state *state,
struct v4l2_subdev_format *format)
{
- struct v4l2_mbus_framefmt *fmt;
+ struct v4l2_mbus_framefmt *mbus_format;
/* The format on the source pad always matches the sink pad. */
if (format->pad != SUN6I_CSI_BRIDGE_PAD_SINK)
@@ -542,12 +543,12 @@ static int sun6i_csi_bridge_set_fmt(struct v4l2_subdev *subdev,
sun6i_csi_bridge_mbus_format_prepare(&format->format);
/* Set the format on the sink pad. */
- fmt = v4l2_subdev_state_get_format(state, format->pad);
- *fmt = format->format;
+ mbus_format = v4l2_subdev_state_get_format(state, format->pad);
+ *mbus_format = format->format;
/* Propagate the format to the source pad. */
- fmt = v4l2_subdev_state_get_format(state, SUN6I_CSI_BRIDGE_PAD_SOURCE);
- *fmt = format->format;
+ mbus_format = v4l2_subdev_state_get_format(state, SUN6I_CSI_BRIDGE_PAD_SOURCE);
+ *mbus_format = format->format;
return 0;
}
@@ -779,14 +780,12 @@ int sun6i_csi_bridge_setup(struct sun6i_csi_device *csi_dev)
if (ret < 0)
return ret;
- /* V4L2 Subdev finalize */
+ /* V4L2 Subdev */
ret = v4l2_subdev_init_finalize(subdev);
if (ret < 0)
goto error_media_entity;
- /* V4L2 Subdev */
-
if (csi_dev->isp_available)
ret = v4l2_async_register_subdev(subdev);
else
@@ -846,7 +845,6 @@ void sun6i_csi_bridge_cleanup(struct sun6i_csi_device *csi_dev)
v4l2_async_nf_cleanup(notifier);
v4l2_device_unregister_subdev(subdev);
-
v4l2_subdev_cleanup(subdev);
media_entity_cleanup(&subdev->entity);
diff --git a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_capture.c b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_capture.c
index 409c28621093..eea682f47eea 100644
--- a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_capture.c
+++ b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_capture.c
@@ -812,27 +812,6 @@ static int sun6i_csi_capture_enum_fmt(struct file *file, void *priv,
return -EINVAL;
}
-static int sun6i_csi_capture_enum_framesize(struct file *file, void *fh,
- struct v4l2_frmsizeenum *fsize)
-{
- if (fsize->index)
- return -EINVAL;
-
- /* Only accept format in map table. */
- if (!sun6i_csi_capture_format_find(fsize->pixel_format))
- return -EINVAL;
-
- fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
- fsize->stepwise.min_width = SUN6I_CSI_CAPTURE_WIDTH_MIN;
- fsize->stepwise.max_width = SUN6I_CSI_CAPTURE_WIDTH_MAX;
- fsize->stepwise.min_height = SUN6I_CSI_CAPTURE_HEIGHT_MIN;
- fsize->stepwise.max_height = SUN6I_CSI_CAPTURE_HEIGHT_MAX;
- fsize->stepwise.step_width = 2;
- fsize->stepwise.step_height = 2;
-
- return 0;
-}
-
static int sun6i_csi_capture_g_fmt(struct file *file, void *priv,
struct v4l2_format *format)
{
@@ -867,6 +846,27 @@ static int sun6i_csi_capture_try_fmt(struct file *file, void *priv,
return 0;
}
+static int sun6i_csi_capture_enum_framesizes(struct file *file, void *fh,
+ struct v4l2_frmsizeenum *frmsize)
+{
+ if (frmsize->index)
+ return -EINVAL;
+
+ /* Only accept format in map table. */
+ if (!sun6i_csi_capture_format_find(frmsize->pixel_format))
+ return -EINVAL;
+
+ frmsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
+ frmsize->stepwise.min_width = SUN6I_CSI_CAPTURE_WIDTH_MIN;
+ frmsize->stepwise.max_width = SUN6I_CSI_CAPTURE_WIDTH_MAX;
+ frmsize->stepwise.min_height = SUN6I_CSI_CAPTURE_HEIGHT_MIN;
+ frmsize->stepwise.max_height = SUN6I_CSI_CAPTURE_HEIGHT_MAX;
+ frmsize->stepwise.step_width = 2;
+ frmsize->stepwise.step_height = 2;
+
+ return 0;
+}
+
static int sun6i_csi_capture_enum_input(struct file *file, void *priv,
struct v4l2_input *input)
{
@@ -900,11 +900,12 @@ static const struct v4l2_ioctl_ops sun6i_csi_capture_ioctl_ops = {
.vidioc_querycap = sun6i_csi_capture_querycap,
.vidioc_enum_fmt_vid_cap = sun6i_csi_capture_enum_fmt,
- .vidioc_enum_framesizes = sun6i_csi_capture_enum_framesize,
.vidioc_g_fmt_vid_cap = sun6i_csi_capture_g_fmt,
.vidioc_s_fmt_vid_cap = sun6i_csi_capture_s_fmt,
.vidioc_try_fmt_vid_cap = sun6i_csi_capture_try_fmt,
+ .vidioc_enum_framesizes = sun6i_csi_capture_enum_framesizes,
+
.vidioc_enum_input = sun6i_csi_capture_enum_input,
.vidioc_g_input = sun6i_csi_capture_g_input,
.vidioc_s_input = sun6i_csi_capture_s_input,
@@ -984,16 +985,17 @@ static int sun6i_csi_capture_link_validate(struct media_link *link)
media_entity_to_video_device(link->sink->entity);
struct sun6i_csi_device *csi_dev = video_get_drvdata(video_dev);
struct v4l2_device *v4l2_dev = csi_dev->v4l2_dev;
- struct v4l2_subdev *src_subdev =
+ struct v4l2_subdev *bridge_subdev =
media_entity_to_v4l2_subdev(link->source->entity);
const struct sun6i_csi_capture_format *capture_format;
const struct sun6i_csi_bridge_format *bridge_format;
unsigned int capture_width, capture_height;
- struct v4l2_subdev_format src_fmt = {
- .which = V4L2_SUBDEV_FORMAT_ACTIVE,
- .pad = link->source->index
+ unsigned int bridge_width, bridge_height;
+ struct v4l2_subdev_format bridge_subdev_format = {
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ .pad = link->source->index,
};
- u32 pixelformat, capture_field;
+ u32 pixelformat, capture_field, mbus_code;
int ret;
sun6i_csi_capture_dimensions(csi_dev, &capture_width, &capture_height);
@@ -1004,21 +1006,25 @@ static int sun6i_csi_capture_link_validate(struct media_link *link)
return -EINVAL;
/* Resolve csi bridge format. */
- ret = v4l2_subdev_call(src_subdev, pad, get_fmt, NULL, &src_fmt);
+ ret = v4l2_subdev_call(bridge_subdev, pad, get_fmt, NULL,
+ &bridge_subdev_format);
if (ret)
return ret;
- bridge_format = sun6i_csi_bridge_format_find(src_fmt.format.code);
+ bridge_width = bridge_subdev_format.format.width;
+ bridge_height = bridge_subdev_format.format.height;
+ mbus_code = bridge_subdev_format.format.code;
+
+ bridge_format = sun6i_csi_bridge_format_find(mbus_code);
if (WARN_ON(!bridge_format))
return -EINVAL;
/* No cropping/scaling is supported. */
- if (capture_width != src_fmt.format.width ||
- capture_height != src_fmt.format.height) {
+ if (capture_width != bridge_width || capture_height != bridge_height) {
v4l2_err(v4l2_dev,
"invalid input/output dimensions: %ux%u/%ux%u\n",
- src_fmt.format.width, src_fmt.format.height,
- capture_width, capture_height);
+ bridge_width, bridge_height, capture_width,
+ capture_height);
return -EINVAL;
}
--
2.54.0
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 12/16] media: sun6i-mipi-csi2: Fix parenthesis alignment
2026-05-18 10:24 [PATCH 00/16] media: sun6i-csi/isp MC-centric support and cleanups Paul Kocialkowski
` (10 preceding siblings ...)
2026-05-18 10:24 ` [PATCH 11/16] media: sun6i-csi: Tidy up and unify coding style Paul Kocialkowski
@ 2026-05-18 10:24 ` Paul Kocialkowski
2026-05-18 10:24 ` [PATCH 13/16] media: sun6i-isp: Add dummy params link_validate implementation Paul Kocialkowski
` (4 subsequent siblings)
16 siblings, 0 replies; 24+ messages in thread
From: Paul Kocialkowski @ 2026-05-18 10:24 UTC (permalink / raw)
To: linux-media, linux-arm-kernel, linux-sunxi, linux-kernel,
linux-staging
Cc: Paul Kocialkowski, Mauro Carvalho Chehab, Chen-Yu Tsai,
Jernej Skrabec, Samuel Holland, Greg Kroah-Hartman, Arash Golgol,
Laurent Pinchart, Nicolas Dufresne
This is purely cosmetic, no functional change intended.
Signed-off-by: Paul Kocialkowski <paulk@sys-base.io>
---
drivers/media/platform/sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/media/platform/sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.c b/drivers/media/platform/sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.c
index 682bdd82098c..17a9a215a98a 100644
--- a/drivers/media/platform/sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.c
+++ b/drivers/media/platform/sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.c
@@ -96,7 +96,7 @@ static void sun6i_mipi_csi2_disable(struct sun6i_mipi_csi2_device *csi2_dev)
}
static void sun6i_mipi_csi2_configure(struct sun6i_mipi_csi2_device *csi2_dev,
- const struct v4l2_mbus_framefmt *mbus_format)
+ const struct v4l2_mbus_framefmt *mbus_format)
{
struct regmap *regmap = csi2_dev->regmap;
unsigned int lanes_count =
--
2.54.0
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 13/16] media: sun6i-isp: Add dummy params link_validate implementation
2026-05-18 10:24 [PATCH 00/16] media: sun6i-csi/isp MC-centric support and cleanups Paul Kocialkowski
` (11 preceding siblings ...)
2026-05-18 10:24 ` [PATCH 12/16] media: sun6i-mipi-csi2: Fix parenthesis alignment Paul Kocialkowski
@ 2026-05-18 10:24 ` Paul Kocialkowski
2026-05-18 10:24 ` [PATCH 14/16] media: sun6i-isp: Use V4L2 subdev active state Paul Kocialkowski
` (3 subsequent siblings)
16 siblings, 0 replies; 24+ messages in thread
From: Paul Kocialkowski @ 2026-05-18 10:24 UTC (permalink / raw)
To: linux-media, linux-arm-kernel, linux-sunxi, linux-kernel,
linux-staging
Cc: Paul Kocialkowski, Mauro Carvalho Chehab, Chen-Yu Tsai,
Jernej Skrabec, Samuel Holland, Greg Kroah-Hartman, Arash Golgol,
Laurent Pinchart, Nicolas Dufresne
There isn't anything configurable about the params video device link,
but the v4l2 core complains that no op is provided so implement a dummy
one to make it happy.
Signed-off-by: Paul Kocialkowski <paulk@sys-base.io>
---
.../media/sunxi/sun6i-isp/sun6i_isp_params.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_params.c b/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_params.c
index 77c2d06c0436..b7ef33fa2b13 100644
--- a/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_params.c
+++ b/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_params.c
@@ -450,6 +450,18 @@ static const struct v4l2_file_operations sun6i_isp_params_fops = {
.poll = vb2_fop_poll,
};
+/* Media Entity */
+
+static int sun6i_isp_params_link_validate(struct media_link *link)
+{
+ /* Nothing to validate here. */
+ return 0;
+}
+
+static const struct media_entity_operations sun6i_isp_params_entity_ops = {
+ .link_validate = sun6i_isp_params_link_validate,
+};
+
/* Params */
int sun6i_isp_params_setup(struct sun6i_isp_device *isp_dev)
@@ -470,6 +482,10 @@ int sun6i_isp_params_setup(struct sun6i_isp_device *isp_dev)
INIT_LIST_HEAD(&state->queue);
spin_lock_init(&state->lock);
+ /* Media Entity */
+
+ video_dev->entity.ops = &sun6i_isp_params_entity_ops;
+
/* Media Pads */
pad->flags = MEDIA_PAD_FL_SOURCE | MEDIA_PAD_FL_MUST_CONNECT;
--
2.54.0
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 14/16] media: sun6i-isp: Use V4L2 subdev active state
2026-05-18 10:24 [PATCH 00/16] media: sun6i-csi/isp MC-centric support and cleanups Paul Kocialkowski
` (12 preceding siblings ...)
2026-05-18 10:24 ` [PATCH 13/16] media: sun6i-isp: Add dummy params link_validate implementation Paul Kocialkowski
@ 2026-05-18 10:24 ` Paul Kocialkowski
2026-05-18 10:24 ` [PATCH 15/16] media: sun6i-isp: Add support for MC-centric format enumeration Paul Kocialkowski
` (2 subsequent siblings)
16 siblings, 0 replies; 24+ messages in thread
From: Paul Kocialkowski @ 2026-05-18 10:24 UTC (permalink / raw)
To: linux-media, linux-arm-kernel, linux-sunxi, linux-kernel,
linux-staging
Cc: Paul Kocialkowski, Mauro Carvalho Chehab, Chen-Yu Tsai,
Jernej Skrabec, Samuel Holland, Greg Kroah-Hartman, Arash Golgol,
Laurent Pinchart, Nicolas Dufresne
Store the active format using the common V4L2 subdev active state
instead of our local copy of it.
Signed-off-by: Paul Kocialkowski <paulk@sys-base.io>
---
.../media/sunxi/sun6i-isp/sun6i_isp_capture.c | 16 ++-
.../media/sunxi/sun6i-isp/sun6i_isp_params.c | 18 ++-
.../media/sunxi/sun6i-isp/sun6i_isp_params.h | 4 +-
.../media/sunxi/sun6i-isp/sun6i_isp_proc.c | 117 ++++++++----------
.../media/sunxi/sun6i-isp/sun6i_isp_proc.h | 7 --
5 files changed, 82 insertions(+), 80 deletions(-)
diff --git a/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_capture.c b/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_capture.c
index e7b99cee63d6..24e731bcabe9 100644
--- a/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_capture.c
+++ b/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_capture.c
@@ -595,11 +595,25 @@ static int sun6i_isp_capture_link_validate(struct media_link *link)
media_entity_to_video_device(link->sink->entity);
struct sun6i_isp_device *isp_dev = video_get_drvdata(video_dev);
struct v4l2_device *v4l2_dev = &isp_dev->v4l2.v4l2_dev;
+ struct v4l2_subdev *proc_subdev =
+ media_entity_to_v4l2_subdev(link->source->entity);
unsigned int capture_width, capture_height;
unsigned int proc_width, proc_height;
+ struct v4l2_subdev_format proc_subdev_format = {
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ .pad = link->source->index,
+ };
+ int ret;
sun6i_isp_capture_dimensions(isp_dev, &capture_width, &capture_height);
- sun6i_isp_proc_dimensions(isp_dev, &proc_width, &proc_height);
+
+ ret = v4l2_subdev_call(proc_subdev, pad, get_fmt, NULL,
+ &proc_subdev_format);
+ if (ret)
+ return ret;
+
+ proc_width = proc_subdev_format.format.width;
+ proc_height = proc_subdev_format.format.height;
/* No cropping/scaling is supported (yet). */
if (capture_width != proc_width || capture_height != proc_height) {
diff --git a/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_params.c b/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_params.c
index b7ef33fa2b13..0cc48e2bc8c6 100644
--- a/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_params.c
+++ b/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_params.c
@@ -43,11 +43,14 @@ static const struct sun6i_isp_params_config sun6i_isp_params_config_default = {
},
};
-static void sun6i_isp_params_configure_ob(struct sun6i_isp_device *isp_dev)
+static void
+sun6i_isp_params_configure_ob(struct sun6i_isp_device *isp_dev,
+ const struct v4l2_mbus_framefmt *mbus_format)
{
unsigned int width, height;
- sun6i_isp_proc_dimensions(isp_dev, &width, &height);
+ width = mbus_format->width;
+ height = mbus_format->height;
sun6i_isp_load_write(isp_dev, SUN6I_ISP_OB_SIZE_REG,
SUN6I_ISP_OB_SIZE_WIDTH(width) |
@@ -112,10 +115,12 @@ static void sun6i_isp_params_configure_wb(struct sun6i_isp_device *isp_dev)
SUN6I_ISP_WB_CFG_CLIP(0xfff));
}
-static void sun6i_isp_params_configure_base(struct sun6i_isp_device *isp_dev)
+static void
+sun6i_isp_params_configure_base(struct sun6i_isp_device *isp_dev,
+ const struct v4l2_mbus_framefmt *mbus_format)
{
sun6i_isp_params_configure_ae(isp_dev);
- sun6i_isp_params_configure_ob(isp_dev);
+ sun6i_isp_params_configure_ob(isp_dev, mbus_format);
sun6i_isp_params_configure_wb(isp_dev);
}
@@ -170,14 +175,15 @@ sun6i_isp_params_configure_modules(struct sun6i_isp_device *isp_dev,
sun6i_isp_load_write(isp_dev, SUN6I_ISP_MODULE_EN_REG, value);
}
-void sun6i_isp_params_configure(struct sun6i_isp_device *isp_dev)
+void sun6i_isp_params_configure(struct sun6i_isp_device *isp_dev,
+ const struct v4l2_mbus_framefmt *mbus_format)
{
struct sun6i_isp_params_state *state = &isp_dev->params.state;
unsigned long flags;
spin_lock_irqsave(&state->lock, flags);
- sun6i_isp_params_configure_base(isp_dev);
+ sun6i_isp_params_configure_base(isp_dev, mbus_format);
/* Default config is only applied at the very first stream start. */
if (state->configured)
diff --git a/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_params.h b/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_params.h
index 50f10f879c42..c0d6cff95d54 100644
--- a/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_params.h
+++ b/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_params.h
@@ -36,8 +36,8 @@ struct sun6i_isp_params {
/* Params */
-void sun6i_isp_params_configure(struct sun6i_isp_device *isp_dev);
-
+void sun6i_isp_params_configure(struct sun6i_isp_device *isp_dev,
+ const struct v4l2_mbus_framefmt *mbus_format);
/* State */
void sun6i_isp_params_state_update(struct sun6i_isp_device *isp_dev,
diff --git a/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_proc.c b/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_proc.c
index 46a334b602f1..9073a7f3f8c8 100644
--- a/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_proc.c
+++ b/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_proc.c
@@ -15,17 +15,6 @@
#include "sun6i_isp_proc.h"
#include "sun6i_isp_reg.h"
-/* Helpers */
-
-void sun6i_isp_proc_dimensions(struct sun6i_isp_device *isp_dev,
- unsigned int *width, unsigned int *height)
-{
- if (width)
- *width = isp_dev->proc.mbus_format.width;
- if (height)
- *height = isp_dev->proc.mbus_format.height;
-}
-
/* Format */
static const struct sun6i_isp_proc_format sun6i_isp_proc_formats[] = {
@@ -137,9 +126,10 @@ static void sun6i_isp_proc_disable(struct sun6i_isp_device *isp_dev)
regmap_write(regmap, SUN6I_ISP_FE_CFG_REG, 0);
}
-static void sun6i_isp_proc_configure(struct sun6i_isp_device *isp_dev)
+static void
+sun6i_isp_proc_configure(struct sun6i_isp_device *isp_dev,
+ const struct v4l2_mbus_framefmt *mbus_format)
{
- struct v4l2_mbus_framefmt *mbus_format = &isp_dev->proc.mbus_format;
const struct sun6i_isp_proc_format *format;
u32 value;
@@ -173,6 +163,8 @@ static int sun6i_isp_proc_s_stream(struct v4l2_subdev *subdev, int on)
struct sun6i_isp_proc_source *source;
struct v4l2_subdev *source_subdev;
struct media_pad *remote_pad;
+ struct v4l2_subdev_state *state;
+ const struct v4l2_mbus_framefmt *mbus_format;
int ret;
/* Source */
@@ -191,6 +183,10 @@ static int sun6i_isp_proc_s_stream(struct v4l2_subdev *subdev, int on)
else
source = &proc->source_csi1;
+ /* Active State */
+
+ state = v4l2_subdev_lock_and_get_active_state(subdev);
+
if (!on) {
sun6i_isp_proc_irq_disable(isp_dev);
v4l2_subdev_call(source_subdev, video, s_stream, 0);
@@ -202,7 +198,7 @@ static int sun6i_isp_proc_s_stream(struct v4l2_subdev *subdev, int on)
ret = pm_runtime_resume_and_get(dev);
if (ret < 0)
- return ret;
+ goto unlock;
/* Clear */
@@ -210,9 +206,12 @@ static int sun6i_isp_proc_s_stream(struct v4l2_subdev *subdev, int on)
/* Configure */
+ mbus_format = v4l2_subdev_state_get_format(state,
+ SUN6I_ISP_PROC_PAD_SINK_CSI);
+
sun6i_isp_tables_configure(isp_dev);
- sun6i_isp_params_configure(isp_dev);
- sun6i_isp_proc_configure(isp_dev);
+ sun6i_isp_params_configure(isp_dev, mbus_format);
+ sun6i_isp_proc_configure(isp_dev, mbus_format);
sun6i_isp_capture_configure(isp_dev);
/* State Update */
@@ -230,13 +229,17 @@ static int sun6i_isp_proc_s_stream(struct v4l2_subdev *subdev, int on)
goto disable;
}
- return 0;
+ ret = 0;
+ goto unlock;
disable:
sun6i_isp_proc_disable(isp_dev);
pm_runtime_put(dev);
+unlock:
+ v4l2_subdev_unlock_state(state);
+
return ret;
}
@@ -259,21 +262,22 @@ sun6i_isp_proc_mbus_format_prepare(struct v4l2_mbus_framefmt *mbus_format)
static int sun6i_isp_proc_init_state(struct v4l2_subdev *subdev,
struct v4l2_subdev_state *state)
{
- struct sun6i_isp_device *isp_dev = v4l2_get_subdevdata(subdev);
- unsigned int pad = SUN6I_ISP_PROC_PAD_SINK_CSI;
- struct v4l2_mbus_framefmt *mbus_format =
- v4l2_subdev_state_get_format(state, pad);
- struct mutex *lock = &isp_dev->proc.lock;
+ unsigned int pad;
- mutex_lock(lock);
+ for (pad = 0; pad < subdev->entity.num_pads; pad++) {
+ struct v4l2_mbus_framefmt *mbus_format;
- mbus_format->code = sun6i_isp_proc_formats[0].mbus_code;
- mbus_format->width = 1280;
- mbus_format->height = 720;
+ if (pad == SUN6I_ISP_PROC_PAD_SINK_PARAMS)
+ continue;
- sun6i_isp_proc_mbus_format_prepare(mbus_format);
+ mbus_format = v4l2_subdev_state_get_format(state, pad);
- mutex_unlock(lock);
+ mbus_format->code = sun6i_isp_proc_formats[0].mbus_code;
+ mbus_format->width = 1280;
+ mbus_format->height = 720;
+
+ sun6i_isp_proc_mbus_format_prepare(mbus_format);
+ }
return 0;
}
@@ -291,53 +295,31 @@ sun6i_isp_proc_enum_mbus_code(struct v4l2_subdev *subdev,
return 0;
}
-static int sun6i_isp_proc_get_fmt(struct v4l2_subdev *subdev,
- struct v4l2_subdev_state *state,
- struct v4l2_subdev_format *format)
-{
- struct sun6i_isp_device *isp_dev = v4l2_get_subdevdata(subdev);
- struct v4l2_mbus_framefmt *mbus_format = &format->format;
- struct mutex *lock = &isp_dev->proc.lock;
-
- mutex_lock(lock);
-
- if (format->which == V4L2_SUBDEV_FORMAT_TRY)
- *mbus_format = *v4l2_subdev_state_get_format(state,
- format->pad);
- else
- *mbus_format = isp_dev->proc.mbus_format;
-
- mutex_unlock(lock);
-
- return 0;
-}
-
static int sun6i_isp_proc_set_fmt(struct v4l2_subdev *subdev,
struct v4l2_subdev_state *state,
struct v4l2_subdev_format *format)
{
- struct sun6i_isp_device *isp_dev = v4l2_get_subdevdata(subdev);
- struct v4l2_mbus_framefmt *mbus_format = &format->format;
- struct mutex *lock = &isp_dev->proc.lock;
+ struct v4l2_mbus_framefmt *mbus_format;
- mutex_lock(lock);
+ if (format->pad != SUN6I_ISP_PROC_PAD_SINK_CSI)
+ return v4l2_subdev_get_fmt(subdev, state, format);
- sun6i_isp_proc_mbus_format_prepare(mbus_format);
+ sun6i_isp_proc_mbus_format_prepare(&format->format);
- if (format->which == V4L2_SUBDEV_FORMAT_TRY)
- *v4l2_subdev_state_get_format(state, format->pad) =
- *mbus_format;
- else
- isp_dev->proc.mbus_format = *mbus_format;
+ mbus_format = v4l2_subdev_state_get_format(state, format->pad);
+ *mbus_format = format->format;
- mutex_unlock(lock);
+ /* Propagate the format to the source pad. */
+ mbus_format = v4l2_subdev_state_get_format(state,
+ SUN6I_ISP_PROC_PAD_SOURCE);
+ *mbus_format = format->format;
return 0;
}
static const struct v4l2_subdev_pad_ops sun6i_isp_proc_pad_ops = {
.enum_mbus_code = sun6i_isp_proc_enum_mbus_code,
- .get_fmt = sun6i_isp_proc_get_fmt,
+ .get_fmt = v4l2_subdev_get_fmt,
.set_fmt = sun6i_isp_proc_set_fmt,
};
@@ -499,8 +481,6 @@ int sun6i_isp_proc_setup(struct sun6i_isp_device *isp_dev)
struct media_pad *pads = proc->pads;
int ret;
- mutex_init(&proc->lock);
-
/* V4L2 Subdev */
v4l2_subdev_init(subdev, &sun6i_isp_proc_subdev_ops);
@@ -532,10 +512,14 @@ int sun6i_isp_proc_setup(struct sun6i_isp_device *isp_dev)
/* V4L2 Subdev */
+ ret = v4l2_subdev_init_finalize(subdev);
+ if (ret < 0)
+ goto error_media_entity;
+
ret = v4l2_device_register_subdev(v4l2_dev, subdev);
if (ret < 0) {
v4l2_err(v4l2_dev, "failed to register v4l2 subdev: %d\n", ret);
- goto error_media_entity;
+ goto error_subdev_finalize;
}
/* V4L2 Async */
@@ -562,6 +546,9 @@ int sun6i_isp_proc_setup(struct sun6i_isp_device *isp_dev)
v4l2_device_unregister_subdev(subdev);
+error_subdev_finalize:
+ v4l2_subdev_cleanup(subdev);
+
error_media_entity:
media_entity_cleanup(&subdev->entity);
@@ -577,5 +564,7 @@ void sun6i_isp_proc_cleanup(struct sun6i_isp_device *isp_dev)
v4l2_async_nf_cleanup(notifier);
v4l2_device_unregister_subdev(subdev);
+ v4l2_subdev_cleanup(subdev);
+
media_entity_cleanup(&subdev->entity);
}
diff --git a/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_proc.h b/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_proc.h
index db6738a39147..26c4327c5ed7 100644
--- a/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_proc.h
+++ b/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_proc.h
@@ -42,18 +42,11 @@ struct sun6i_isp_proc {
struct v4l2_subdev subdev;
struct media_pad pads[3];
struct v4l2_async_notifier notifier;
- struct v4l2_mbus_framefmt mbus_format;
- struct mutex lock; /* Mbus format lock. */
struct sun6i_isp_proc_source source_csi0;
struct sun6i_isp_proc_source source_csi1;
};
-/* Helpers */
-
-void sun6i_isp_proc_dimensions(struct sun6i_isp_device *isp_dev,
- unsigned int *width, unsigned int *height);
-
/* Format */
const struct sun6i_isp_proc_format *sun6i_isp_proc_format_find(u32 mbus_code);
--
2.54.0
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 15/16] media: sun6i-isp: Add support for MC-centric format enumeration
2026-05-18 10:24 [PATCH 00/16] media: sun6i-csi/isp MC-centric support and cleanups Paul Kocialkowski
` (13 preceding siblings ...)
2026-05-18 10:24 ` [PATCH 14/16] media: sun6i-isp: Use V4L2 subdev active state Paul Kocialkowski
@ 2026-05-18 10:24 ` Paul Kocialkowski
2026-05-18 10:24 ` [PATCH 16/16] media: sun6i-isp: Add support for frame size enumeration Paul Kocialkowski
2026-05-18 12:15 ` [PATCH 00/16] media: sun6i-csi/isp MC-centric support and cleanups Laurent Pinchart
16 siblings, 0 replies; 24+ messages in thread
From: Paul Kocialkowski @ 2026-05-18 10:24 UTC (permalink / raw)
To: linux-media, linux-arm-kernel, linux-sunxi, linux-kernel,
linux-staging
Cc: Paul Kocialkowski, Mauro Carvalho Chehab, Chen-Yu Tsai,
Jernej Skrabec, Samuel Holland, Greg Kroah-Hartman, Arash Golgol,
Laurent Pinchart, Nicolas Dufresne
Just make sure the provided mbus code is supported and carry on with the
existing implementation since the pixelformat is independent from the
mbus code.
The params video node only supports a single format and does not care
about the mbus format, but we can still report MC-centric support.
Signed-off-by: Paul Kocialkowski <paulk@sys-base.io>
---
.../staging/media/sunxi/sun6i-isp/sun6i_isp_capture.c | 9 ++++++++-
drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_params.c | 3 ++-
2 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_capture.c b/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_capture.c
index 24e731bcabe9..372b9331bd6d 100644
--- a/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_capture.c
+++ b/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_capture.c
@@ -436,8 +436,14 @@ static int sun6i_isp_capture_querycap(struct file *file, void *priv,
static int sun6i_isp_capture_enum_fmt(struct file *file, void *priv,
struct v4l2_fmtdesc *fmtdesc)
{
+ u32 mbus_code = fmtdesc->mbus_code;
u32 index = fmtdesc->index;
+ if (mbus_code && !sun6i_isp_proc_format_find(mbus_code))
+ return -EINVAL;
+
+ /* Capture format is independent from proc format. */
+
if (index >= ARRAY_SIZE(sun6i_isp_capture_formats))
return -EINVAL;
@@ -697,7 +703,8 @@ int sun6i_isp_capture_setup(struct sun6i_isp_device *isp_dev)
strscpy(video_dev->name, SUN6I_ISP_CAPTURE_NAME,
sizeof(video_dev->name));
- video_dev->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
+ video_dev->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING |
+ V4L2_CAP_IO_MC;
video_dev->vfl_dir = VFL_DIR_RX;
video_dev->release = video_device_release_empty;
video_dev->fops = &sun6i_isp_capture_fops;
diff --git a/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_params.c b/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_params.c
index 0cc48e2bc8c6..2622e5a07817 100644
--- a/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_params.c
+++ b/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_params.c
@@ -531,7 +531,8 @@ int sun6i_isp_params_setup(struct sun6i_isp_device *isp_dev)
strscpy(video_dev->name, SUN6I_ISP_PARAMS_NAME,
sizeof(video_dev->name));
- video_dev->device_caps = V4L2_CAP_META_OUTPUT | V4L2_CAP_STREAMING;
+ video_dev->device_caps = V4L2_CAP_META_OUTPUT | V4L2_CAP_STREAMING |
+ V4L2_CAP_IO_MC;
video_dev->vfl_dir = VFL_DIR_TX;
video_dev->release = video_device_release_empty;
video_dev->fops = &sun6i_isp_params_fops;
--
2.54.0
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 16/16] media: sun6i-isp: Add support for frame size enumeration
2026-05-18 10:24 [PATCH 00/16] media: sun6i-csi/isp MC-centric support and cleanups Paul Kocialkowski
` (14 preceding siblings ...)
2026-05-18 10:24 ` [PATCH 15/16] media: sun6i-isp: Add support for MC-centric format enumeration Paul Kocialkowski
@ 2026-05-18 10:24 ` Paul Kocialkowski
2026-05-18 12:15 ` [PATCH 00/16] media: sun6i-csi/isp MC-centric support and cleanups Laurent Pinchart
16 siblings, 0 replies; 24+ messages in thread
From: Paul Kocialkowski @ 2026-05-18 10:24 UTC (permalink / raw)
To: linux-media, linux-arm-kernel, linux-sunxi, linux-kernel,
linux-staging
Cc: Paul Kocialkowski, Mauro Carvalho Chehab, Chen-Yu Tsai,
Jernej Skrabec, Samuel Holland, Greg Kroah-Hartman, Arash Golgol,
Laurent Pinchart, Nicolas Dufresne
This implements the enum_framesizes operation, which reports support for
even sizes.
Signed-off-by: Paul Kocialkowski <paulk@sys-base.io>
---
.../media/sunxi/sun6i-isp/sun6i_isp_capture.c | 22 +++++++++++++++++++
1 file changed, 22 insertions(+)
diff --git a/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_capture.c b/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_capture.c
index 372b9331bd6d..e638ec32c7cd 100644
--- a/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_capture.c
+++ b/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_capture.c
@@ -452,6 +452,26 @@ static int sun6i_isp_capture_enum_fmt(struct file *file, void *priv,
return 0;
}
+static int sun6i_isp_capture_enum_framesizes(struct file *file, void *fh,
+ struct v4l2_frmsizeenum *frmsize)
+{
+ if (frmsize->index)
+ return -EINVAL;
+
+ if (!sun6i_isp_capture_format_find(frmsize->pixel_format))
+ return -EINVAL;
+
+ frmsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
+ frmsize->stepwise.min_width = SUN6I_ISP_CAPTURE_WIDTH_MIN;
+ frmsize->stepwise.max_width = SUN6I_ISP_CAPTURE_WIDTH_MAX;
+ frmsize->stepwise.min_height = SUN6I_ISP_CAPTURE_HEIGHT_MIN;
+ frmsize->stepwise.max_height = SUN6I_ISP_CAPTURE_HEIGHT_MAX;
+ frmsize->stepwise.step_width = 2;
+ frmsize->stepwise.step_height = 2;
+
+ return 0;
+}
+
static int sun6i_isp_capture_g_fmt(struct file *file, void *priv,
struct v4l2_format *format)
{
@@ -522,6 +542,8 @@ static const struct v4l2_ioctl_ops sun6i_isp_capture_ioctl_ops = {
.vidioc_s_fmt_vid_cap = sun6i_isp_capture_s_fmt,
.vidioc_try_fmt_vid_cap = sun6i_isp_capture_try_fmt,
+ .vidioc_enum_framesizes = sun6i_isp_capture_enum_framesizes,
+
.vidioc_enum_input = sun6i_isp_capture_enum_input,
.vidioc_g_input = sun6i_isp_capture_g_input,
.vidioc_s_input = sun6i_isp_capture_s_input,
--
2.54.0
^ permalink raw reply related [flat|nested] 24+ messages in thread
* Re: [PATCH 00/16] media: sun6i-csi/isp MC-centric support and cleanups
2026-05-18 10:24 [PATCH 00/16] media: sun6i-csi/isp MC-centric support and cleanups Paul Kocialkowski
` (15 preceding siblings ...)
2026-05-18 10:24 ` [PATCH 16/16] media: sun6i-isp: Add support for frame size enumeration Paul Kocialkowski
@ 2026-05-18 12:15 ` Laurent Pinchart
2026-05-18 14:08 ` Paul Kocialkowski
16 siblings, 1 reply; 24+ messages in thread
From: Laurent Pinchart @ 2026-05-18 12:15 UTC (permalink / raw)
To: Paul Kocialkowski
Cc: linux-media, linux-arm-kernel, linux-sunxi, linux-kernel,
linux-staging, Mauro Carvalho Chehab, Chen-Yu Tsai,
Jernej Skrabec, Samuel Holland, Greg Kroah-Hartman, Arash Golgol,
Nicolas Dufresne
On Mon, May 18, 2026 at 12:24:35PM +0200, Paul Kocialkowski wrote:
> This series first introduces some fixes and new formats to v4l2 format
> info, one of which we need for the sun6i-csi driver. Support for
> MC-centric format enumeration is then added, along with cleanups and
> improvements for both the sun6i-csi and sun6i-isp drivers.
>
> The first 4 patches are already reviewed and ready to go and are
> included here as a reminder that this series depends on them.
Patch 04/16 has no R-b tag.
> Arash Golgol (4):
> media: sun6i-csi: bridge: Use V4L2 subdev active state
> media: sun6i-csi: capture: Implement vidioc_enum_framesizes
> media: sun6i-mipi-csi2: Use V4L2 subdev active state
> media: sun8i-a83t-mipi-csi2: Use V4L2 subdev active state
>
> Paul Kocialkowski (12):
> media: v4l2-common: Fix NV15_4L4 format info block height
> media: v4l2-common: Add missing tiled format info block sizes
> media: v4l2-common: Add NV12_16L16 pixel format to v4l2 format info
> media: v4l2-common: Add NV12_32L32 pixel format to v4l2 format info
> media: sun6i-csi: Split format validation to a dedicated helper
> media: sun6i-csi: Add support for MC-centric format enumeration
> media: sun6i-csi: Tidy up and unify coding style
> media: sun6i-mipi-csi2: Fix parenthesis alignment
> media: sun6i-isp: Add dummy params link_validate implementation
> media: sun6i-isp: Use V4L2 subdev active state
> media: sun6i-isp: Add support for MC-centric format enumeration
> media: sun6i-isp: Add support for frame size enumeration
>
> .../sunxi/sun6i-csi/sun6i_csi_bridge.c | 153 +++++++---------
> .../sunxi/sun6i-csi/sun6i_csi_bridge.h | 9 -
> .../sunxi/sun6i-csi/sun6i_csi_capture.c | 168 +++++++++++++-----
> .../sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.c | 107 ++++++-----
> .../sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.h | 2 -
> .../sun8i_a83t_mipi_csi2.c | 113 ++++++------
> .../sun8i_a83t_mipi_csi2.h | 2 -
> drivers/media/v4l2-core/v4l2-common.c | 12 +-
> .../media/sunxi/sun6i-isp/sun6i_isp_capture.c | 47 ++++-
> .../media/sunxi/sun6i-isp/sun6i_isp_params.c | 37 +++-
> .../media/sunxi/sun6i-isp/sun6i_isp_params.h | 4 +-
> .../media/sunxi/sun6i-isp/sun6i_isp_proc.c | 117 ++++++------
> .../media/sunxi/sun6i-isp/sun6i_isp_proc.h | 7 -
> 13 files changed, 437 insertions(+), 341 deletions(-)
--
Regards,
Laurent Pinchart
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 00/16] media: sun6i-csi/isp MC-centric support and cleanups
2026-05-18 12:15 ` [PATCH 00/16] media: sun6i-csi/isp MC-centric support and cleanups Laurent Pinchart
@ 2026-05-18 14:08 ` Paul Kocialkowski
0 siblings, 0 replies; 24+ messages in thread
From: Paul Kocialkowski @ 2026-05-18 14:08 UTC (permalink / raw)
To: Laurent Pinchart
Cc: linux-media, linux-arm-kernel, linux-sunxi, linux-kernel,
linux-staging, Mauro Carvalho Chehab, Chen-Yu Tsai,
Jernej Skrabec, Samuel Holland, Greg Kroah-Hartman, Arash Golgol,
Nicolas Dufresne
[-- Attachment #1: Type: text/plain, Size: 3050 bytes --]
Hi Laurent,
Le Mon 18 May 26, 14:15, Laurent Pinchart a écrit :
> On Mon, May 18, 2026 at 12:24:35PM +0200, Paul Kocialkowski wrote:
> > This series first introduces some fixes and new formats to v4l2 format
> > info, one of which we need for the sun6i-csi driver. Support for
> > MC-centric format enumeration is then added, along with cleanups and
> > improvements for both the sun6i-csi and sun6i-isp drivers.
> >
> > The first 4 patches are already reviewed and ready to go and are
> > included here as a reminder that this series depends on them.
>
> Patch 04/16 has no R-b tag.
Oops you're right, I added the tag in my reply to the patch yesterday
but did not add it when resending it with this series.
All the best,
Paul
> > Arash Golgol (4):
> > media: sun6i-csi: bridge: Use V4L2 subdev active state
> > media: sun6i-csi: capture: Implement vidioc_enum_framesizes
> > media: sun6i-mipi-csi2: Use V4L2 subdev active state
> > media: sun8i-a83t-mipi-csi2: Use V4L2 subdev active state
> >
> > Paul Kocialkowski (12):
> > media: v4l2-common: Fix NV15_4L4 format info block height
> > media: v4l2-common: Add missing tiled format info block sizes
> > media: v4l2-common: Add NV12_16L16 pixel format to v4l2 format info
> > media: v4l2-common: Add NV12_32L32 pixel format to v4l2 format info
> > media: sun6i-csi: Split format validation to a dedicated helper
> > media: sun6i-csi: Add support for MC-centric format enumeration
> > media: sun6i-csi: Tidy up and unify coding style
> > media: sun6i-mipi-csi2: Fix parenthesis alignment
> > media: sun6i-isp: Add dummy params link_validate implementation
> > media: sun6i-isp: Use V4L2 subdev active state
> > media: sun6i-isp: Add support for MC-centric format enumeration
> > media: sun6i-isp: Add support for frame size enumeration
> >
> > .../sunxi/sun6i-csi/sun6i_csi_bridge.c | 153 +++++++---------
> > .../sunxi/sun6i-csi/sun6i_csi_bridge.h | 9 -
> > .../sunxi/sun6i-csi/sun6i_csi_capture.c | 168 +++++++++++++-----
> > .../sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.c | 107 ++++++-----
> > .../sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.h | 2 -
> > .../sun8i_a83t_mipi_csi2.c | 113 ++++++------
> > .../sun8i_a83t_mipi_csi2.h | 2 -
> > drivers/media/v4l2-core/v4l2-common.c | 12 +-
> > .../media/sunxi/sun6i-isp/sun6i_isp_capture.c | 47 ++++-
> > .../media/sunxi/sun6i-isp/sun6i_isp_params.c | 37 +++-
> > .../media/sunxi/sun6i-isp/sun6i_isp_params.h | 4 +-
> > .../media/sunxi/sun6i-isp/sun6i_isp_proc.c | 117 ++++++------
> > .../media/sunxi/sun6i-isp/sun6i_isp_proc.h | 7 -
> > 13 files changed, 437 insertions(+), 341 deletions(-)
>
> --
> Regards,
>
> Laurent Pinchart
--
Paul Kocialkowski,
Independent contractor - sys-base - https://www.sys-base.io/
Free software developer - https://www.paulk.fr/
Expert in multimedia, graphics and embedded hardware support with Linux.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 04/16] media: sun8i-a83t-mipi-csi2: Use V4L2 subdev active state
2026-05-18 10:24 ` [PATCH 04/16] media: sun8i-a83t-mipi-csi2: " Paul Kocialkowski
@ 2026-05-18 14:09 ` Paul Kocialkowski
0 siblings, 0 replies; 24+ messages in thread
From: Paul Kocialkowski @ 2026-05-18 14:09 UTC (permalink / raw)
To: linux-media, linux-arm-kernel, linux-sunxi, linux-kernel,
linux-staging
Cc: Mauro Carvalho Chehab, Chen-Yu Tsai, Jernej Skrabec,
Samuel Holland, Greg Kroah-Hartman, Arash Golgol,
Laurent Pinchart, Nicolas Dufresne
[-- Attachment #1: Type: text/plain, Size: 10308 bytes --]
Le Mon 18 May 26, 12:24, Paul Kocialkowski a écrit :
> From: Arash Golgol <arash.golgol@gmail.com>
>
> Use the V4L2 subdev active state API to store the active format.
> This simplifies the driver not only by dropping the bridge mbus_format
> field, but it also allows dropping the bridge lock, replaced with
> the state lock.
>
> The sun8i-a83t-mipi-csi2 hardware does not perform any format
> conversion. Enforce identical formats on the sink and source pads in
> the set_fmt() and init_state() callbacks.
>
> Signed-off-by: Arash Golgol <arash.golgol@gmail.com>
I forgot to pick it up but this is already:
Reviewed-by: Paul Kocialkowski <paulk@sys-base.io>
Tested-by: Paul Kocialkowski <paulk@sys-base.io>
Paul
> ---
> .../sun8i_a83t_mipi_csi2.c | 113 +++++++++---------
> .../sun8i_a83t_mipi_csi2.h | 2 -
> 2 files changed, 56 insertions(+), 59 deletions(-)
>
> diff --git a/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_mipi_csi2.c b/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_mipi_csi2.c
> index dbc51daa4fe3..2b7635f3952d 100644
> --- a/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_mipi_csi2.c
> +++ b/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_mipi_csi2.c
> @@ -144,12 +144,12 @@ sun8i_a83t_mipi_csi2_disable(struct sun8i_a83t_mipi_csi2_device *csi2_dev)
> }
>
> static void
> -sun8i_a83t_mipi_csi2_configure(struct sun8i_a83t_mipi_csi2_device *csi2_dev)
> +sun8i_a83t_mipi_csi2_configure(struct sun8i_a83t_mipi_csi2_device *csi2_dev,
> + const struct v4l2_mbus_framefmt *mbus_format)
> {
> struct regmap *regmap = csi2_dev->regmap;
> unsigned int lanes_count =
> csi2_dev->bridge.endpoint.bus.mipi_csi2.num_data_lanes;
> - struct v4l2_mbus_framefmt *mbus_format = &csi2_dev->bridge.mbus_format;
> const struct sun8i_a83t_mipi_csi2_format *format;
> struct device *dev = csi2_dev->dev;
> u32 version = 0;
> @@ -205,7 +205,8 @@ static int sun8i_a83t_mipi_csi2_s_stream(struct v4l2_subdev *subdev, int on)
> struct v4l2_subdev *source_subdev = csi2_dev->bridge.source_subdev;
> union phy_configure_opts dphy_opts = { 0 };
> struct phy_configure_opts_mipi_dphy *dphy_cfg = &dphy_opts.mipi_dphy;
> - struct v4l2_mbus_framefmt *mbus_format = &csi2_dev->bridge.mbus_format;
> + struct v4l2_subdev_state *state;
> + const struct v4l2_mbus_framefmt *mbus_format;
> const struct sun8i_a83t_mipi_csi2_format *format;
> struct phy *dphy = csi2_dev->dphy;
> struct device *dev = csi2_dev->dev;
> @@ -215,8 +216,12 @@ static int sun8i_a83t_mipi_csi2_s_stream(struct v4l2_subdev *subdev, int on)
> unsigned long pixel_rate;
> int ret;
>
> - if (!source_subdev)
> - return -ENODEV;
> + state = v4l2_subdev_lock_and_get_active_state(subdev);
> +
> + if (!source_subdev) {
> + ret = -ENODEV;
> + goto unlock;
> + }
>
> if (!on) {
> v4l2_subdev_call(source_subdev, video, s_stream, 0);
> @@ -228,7 +233,7 @@ static int sun8i_a83t_mipi_csi2_s_stream(struct v4l2_subdev *subdev, int on)
>
> ret = pm_runtime_resume_and_get(dev);
> if (ret < 0)
> - return ret;
> + goto unlock;
>
> /* Sensor pixel rate */
>
> @@ -254,6 +259,9 @@ static int sun8i_a83t_mipi_csi2_s_stream(struct v4l2_subdev *subdev, int on)
> goto error_pm;
> }
>
> + mbus_format =
> + v4l2_subdev_state_get_format(state,
> + SUN8I_A83T_MIPI_CSI2_PAD_SINK);
> format = sun8i_a83t_mipi_csi2_format_find(mbus_format->code);
> if (WARN_ON(!format)) {
> ret = -ENODEV;
> @@ -292,7 +300,7 @@ static int sun8i_a83t_mipi_csi2_s_stream(struct v4l2_subdev *subdev, int on)
>
> /* Controller */
>
> - sun8i_a83t_mipi_csi2_configure(csi2_dev);
> + sun8i_a83t_mipi_csi2_configure(csi2_dev, mbus_format);
> sun8i_a83t_mipi_csi2_enable(csi2_dev);
>
> /* D-PHY */
> @@ -309,7 +317,8 @@ static int sun8i_a83t_mipi_csi2_s_stream(struct v4l2_subdev *subdev, int on)
> if (ret && ret != -ENOIOCTLCMD)
> goto disable;
>
> - return 0;
> + ret = 0;
> + goto unlock;
>
> disable:
> phy_power_off(dphy);
> @@ -318,6 +327,8 @@ static int sun8i_a83t_mipi_csi2_s_stream(struct v4l2_subdev *subdev, int on)
> error_pm:
> pm_runtime_put(dev);
>
> +unlock:
> + v4l2_subdev_unlock_state(state);
> return ret;
> }
>
> @@ -341,22 +352,24 @@ sun8i_a83t_mipi_csi2_mbus_format_prepare(struct v4l2_mbus_framefmt *mbus_format)
> static int sun8i_a83t_mipi_csi2_init_state(struct v4l2_subdev *subdev,
> struct v4l2_subdev_state *state)
> {
> - struct sun8i_a83t_mipi_csi2_device *csi2_dev =
> - v4l2_get_subdevdata(subdev);
> - unsigned int pad = SUN8I_A83T_MIPI_CSI2_PAD_SINK;
> - struct v4l2_mbus_framefmt *mbus_format =
> - v4l2_subdev_state_get_format(state, pad);
> - struct mutex *lock = &csi2_dev->bridge.lock;
> + unsigned int pad;
>
> - mutex_lock(lock);
> + /*
> + * This subdev does not perform format conversion,
> + * initialize both pads identically.
> + */
> + for (pad = 0; pad < subdev->entity.num_pads; pad++) {
> + struct v4l2_mbus_framefmt *mbus_format;
>
> - mbus_format->code = sun8i_a83t_mipi_csi2_formats[0].mbus_code;
> - mbus_format->width = 640;
> - mbus_format->height = 480;
> + mbus_format = v4l2_subdev_state_get_format(state, pad);
> +
> + mbus_format->code = sun8i_a83t_mipi_csi2_formats[0].mbus_code;
> + mbus_format->width = 640;
> + mbus_format->height = 480;
>
> - sun8i_a83t_mipi_csi2_mbus_format_prepare(mbus_format);
> + sun8i_a83t_mipi_csi2_mbus_format_prepare(mbus_format);
> + }
>
> - mutex_unlock(lock);
>
> return 0;
> }
> @@ -375,55 +388,33 @@ sun8i_a83t_mipi_csi2_enum_mbus_code(struct v4l2_subdev *subdev,
> return 0;
> }
>
> -static int sun8i_a83t_mipi_csi2_get_fmt(struct v4l2_subdev *subdev,
> - struct v4l2_subdev_state *state,
> - struct v4l2_subdev_format *format)
> -{
> - struct sun8i_a83t_mipi_csi2_device *csi2_dev =
> - v4l2_get_subdevdata(subdev);
> - struct v4l2_mbus_framefmt *mbus_format = &format->format;
> - struct mutex *lock = &csi2_dev->bridge.lock;
> -
> - mutex_lock(lock);
> -
> - if (format->which == V4L2_SUBDEV_FORMAT_TRY)
> - *mbus_format = *v4l2_subdev_state_get_format(state,
> - format->pad);
> - else
> - *mbus_format = csi2_dev->bridge.mbus_format;
> -
> - mutex_unlock(lock);
> -
> - return 0;
> -}
> -
> static int sun8i_a83t_mipi_csi2_set_fmt(struct v4l2_subdev *subdev,
> struct v4l2_subdev_state *state,
> struct v4l2_subdev_format *format)
> {
> - struct sun8i_a83t_mipi_csi2_device *csi2_dev =
> - v4l2_get_subdevdata(subdev);
> - struct v4l2_mbus_framefmt *mbus_format = &format->format;
> - struct mutex *lock = &csi2_dev->bridge.lock;
> + struct v4l2_mbus_framefmt *fmt;
>
> - mutex_lock(lock);
> + /* The format on the source pad always matches the sink pad. */
> + if (format->pad != SUN8I_A83T_MIPI_CSI2_PAD_SINK)
> + return v4l2_subdev_get_fmt(subdev, state, format);
>
> - sun8i_a83t_mipi_csi2_mbus_format_prepare(mbus_format);
> + sun8i_a83t_mipi_csi2_mbus_format_prepare(&format->format);
>
> - if (format->which == V4L2_SUBDEV_FORMAT_TRY)
> - *v4l2_subdev_state_get_format(state, format->pad) =
> - *mbus_format;
> - else
> - csi2_dev->bridge.mbus_format = *mbus_format;
> + /* Set the format on the sink pad. */
> + fmt = v4l2_subdev_state_get_format(state, format->pad);
> + *fmt = format->format;
>
> - mutex_unlock(lock);
> + /* Propagate the format to the source pad. */
> + fmt = v4l2_subdev_state_get_format(state,
> + SUN8I_A83T_MIPI_CSI2_PAD_SOURCE);
> + *fmt = format->format;
>
> return 0;
> }
>
> static const struct v4l2_subdev_pad_ops sun8i_a83t_mipi_csi2_pad_ops = {
> .enum_mbus_code = sun8i_a83t_mipi_csi2_enum_mbus_code,
> - .get_fmt = sun8i_a83t_mipi_csi2_get_fmt,
> + .get_fmt = v4l2_subdev_get_fmt,
> .set_fmt = sun8i_a83t_mipi_csi2_set_fmt,
> };
>
> @@ -540,8 +531,6 @@ sun8i_a83t_mipi_csi2_bridge_setup(struct sun8i_a83t_mipi_csi2_device *csi2_dev)
> bool notifier_registered = false;
> int ret;
>
> - mutex_init(&bridge->lock);
> -
> /* V4L2 Subdev */
>
> v4l2_subdev_init(subdev, &sun8i_a83t_mipi_csi2_subdev_ops);
> @@ -570,6 +559,12 @@ sun8i_a83t_mipi_csi2_bridge_setup(struct sun8i_a83t_mipi_csi2_device *csi2_dev)
> if (ret)
> return ret;
>
> + /* V4L2 Subdev finalize */
> +
> + ret = v4l2_subdev_init_finalize(subdev);
> + if (ret < 0)
> + goto error_media_entity_cleanup;
> +
> /* V4L2 Async */
>
> v4l2_async_subdev_nf_init(notifier, subdev);
> @@ -603,6 +598,9 @@ sun8i_a83t_mipi_csi2_bridge_setup(struct sun8i_a83t_mipi_csi2_device *csi2_dev)
> error_v4l2_notifier_cleanup:
> v4l2_async_nf_cleanup(notifier);
>
> + v4l2_subdev_cleanup(subdev);
> +
> +error_media_entity_cleanup:
> media_entity_cleanup(&subdev->entity);
>
> return ret;
> @@ -617,6 +615,7 @@ sun8i_a83t_mipi_csi2_bridge_cleanup(struct sun8i_a83t_mipi_csi2_device *csi2_dev
> v4l2_async_unregister_subdev(subdev);
> v4l2_async_nf_unregister(notifier);
> v4l2_async_nf_cleanup(notifier);
> + v4l2_subdev_cleanup(subdev);
> media_entity_cleanup(&subdev->entity);
> }
>
> diff --git a/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_mipi_csi2.h b/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_mipi_csi2.h
> index f1e64c53434c..819527bcd64d 100644
> --- a/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_mipi_csi2.h
> +++ b/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_mipi_csi2.h
> @@ -33,8 +33,6 @@ struct sun8i_a83t_mipi_csi2_bridge {
> struct media_pad pads[SUN8I_A83T_MIPI_CSI2_PAD_COUNT];
> struct v4l2_fwnode_endpoint endpoint;
> struct v4l2_async_notifier notifier;
> - struct v4l2_mbus_framefmt mbus_format;
> - struct mutex lock; /* Mbus format lock. */
>
> struct v4l2_subdev *source_subdev;
> };
> --
> 2.54.0
>
--
Paul Kocialkowski,
Independent contractor - sys-base - https://www.sys-base.io/
Free software developer - https://www.paulk.fr/
Expert in multimedia, graphics and embedded hardware support with Linux.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 05/16] media: v4l2-common: Fix NV15_4L4 format info block height
2026-05-18 10:24 ` [PATCH 05/16] media: v4l2-common: Fix NV15_4L4 format info block height Paul Kocialkowski
@ 2026-05-19 15:16 ` Nicolas Dufresne
0 siblings, 0 replies; 24+ messages in thread
From: Nicolas Dufresne @ 2026-05-19 15:16 UTC (permalink / raw)
To: Paul Kocialkowski, linux-media, linux-arm-kernel, linux-sunxi,
linux-kernel, linux-staging
Cc: Mauro Carvalho Chehab, Chen-Yu Tsai, Jernej Skrabec,
Samuel Holland, Greg Kroah-Hartman, Arash Golgol,
Laurent Pinchart
[-- Attachment #1: Type: text/plain, Size: 2021 bytes --]
Le lundi 18 mai 2026 à 12:24 +0200, Paul Kocialkowski a écrit :
> The NV15_4L4 format is specified as a 4x4 format, not 4x1.
> In addition the block size should not take subsampling in account,
> so specify it as 4x4 for both luma and chroma.
>
> Signed-off-by: Paul Kocialkowski <paulk@sys-base.io>
> ---
> drivers/media/v4l2-core/v4l2-common.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/media/v4l2-core/v4l2-common.c b/drivers/media/v4l2-core/v4l2-common.c
> index 554c591e1113..77a0daa92c2b 100644
> --- a/drivers/media/v4l2-core/v4l2-common.c
> +++ b/drivers/media/v4l2-core/v4l2-common.c
> @@ -309,7 +309,7 @@ const struct v4l2_format_info *v4l2_format_info(u32 format)
> /* Tiled YUV formats */
> { .format = V4L2_PIX_FMT_NV12_4L4, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2 },
> { .format = V4L2_PIX_FMT_NV15_4L4, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 5, 10, 0, 0 }, .bpp_div = { 4, 4, 1, 1 }, .hdiv = 2, .vdiv = 2,
> - .block_w = { 4, 2, 0, 0 }, .block_h = { 1, 1, 0, 0 }},
> + .block_w = { 4, 4, 0, 0 }, .block_h = { 4, 4, 0, 0 }},
Only the block_h is broken. The block_w is in "pixels" which for the UV plane is
component pairs. So both set of tiles have 5bytes stride. But since the second
set, the UV tiles, are interleaved, they only have 2 pairs of UV per row. So to
me the correct fix is:
+ .block_w = { 4, 2, 0, 0 }, .block_h = { 4, 4, 0, 0 }},
If its not the case for the camera pipeline, then a new format is needed, since
this format should perfectly match NV15 + VIVANTE_TILED in the DRM world.
regards,
Nicolas
> { .format = V4L2_PIX_FMT_P010_4L4, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 2, 4, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2 },
>
> /* YUV planar formats, non contiguous variant */
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 06/16] media: v4l2-common: Add missing tiled format info block sizes
2026-05-18 10:24 ` [PATCH 06/16] media: v4l2-common: Add missing tiled format info block sizes Paul Kocialkowski
@ 2026-05-19 15:18 ` Nicolas Dufresne
0 siblings, 0 replies; 24+ messages in thread
From: Nicolas Dufresne @ 2026-05-19 15:18 UTC (permalink / raw)
To: Paul Kocialkowski, linux-media, linux-arm-kernel, linux-sunxi,
linux-kernel, linux-staging
Cc: Mauro Carvalho Chehab, Chen-Yu Tsai, Jernej Skrabec,
Samuel Holland, Greg Kroah-Hartman, Arash Golgol,
Laurent Pinchart
[-- Attachment #1: Type: text/plain, Size: 2655 bytes --]
Le lundi 18 mai 2026 à 12:24 +0200, Paul Kocialkowski a écrit :
> Some YUV420 tiled format info definitions are missing block sizes.
> Add the missing block sizes (they are all 4x4).
>
> Signed-off-by: Paul Kocialkowski <paulk@sys-base.io>
> ---
> drivers/media/v4l2-core/v4l2-common.c | 6 ++++--
> 1 file changed, 4 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/media/v4l2-core/v4l2-common.c b/drivers/media/v4l2-core/v4l2-common.c
> index 77a0daa92c2b..e142d40c71b9 100644
> --- a/drivers/media/v4l2-core/v4l2-common.c
> +++ b/drivers/media/v4l2-core/v4l2-common.c
> @@ -307,10 +307,12 @@ const struct v4l2_format_info *v4l2_format_info(u32 format)
> { .format = V4L2_PIX_FMT_GREY, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
>
> /* Tiled YUV formats */
> - { .format = V4L2_PIX_FMT_NV12_4L4, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2 },
> + { .format = V4L2_PIX_FMT_NV12_4L4, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2,
> + .block_w = { 4, 4, 0, 0 }, .block_h = { 4, 4, 0, 0 }},
.block_w = { 4, 2, 0, 0 }, .block_h = { 4, 4, 0, 0 }},
> { .format = V4L2_PIX_FMT_NV15_4L4, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 5, 10, 0, 0 }, .bpp_div = { 4, 4, 1, 1 }, .hdiv = 2, .vdiv = 2,
> .block_w = { 4, 4, 0, 0 }, .block_h = { 4, 4, 0, 0 }},
> - { .format = V4L2_PIX_FMT_P010_4L4, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 2, 4, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2 },
> + { .format = V4L2_PIX_FMT_P010_4L4, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 2, 4, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2,
> + .block_w = { 4, 4, 0, 0 }, .block_h = { 4, 4, 0, 0 }},
.block_w = { 4, 2, 0, 0 }, .block_h = { 4, 4, 0, 0 }},
This one is speecial, this format does not exists. I believe Jernej made that
one based on assumptions, the actual HW should produce NV15 4L4, but I don't own
that hardware, and so I never managed remove that last "user" of it, which is I
believe H6 VP9 decoder.
Nicolas
>
> /* YUV planar formats, non contiguous variant */
> { .format = V4L2_PIX_FMT_YUV420M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2 },
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 07/16] media: v4l2-common: Add NV12_16L16 pixel format to v4l2 format info
2026-05-18 10:24 ` [PATCH 07/16] media: v4l2-common: Add NV12_16L16 pixel format to v4l2 format info Paul Kocialkowski
@ 2026-05-19 15:22 ` Nicolas Dufresne
0 siblings, 0 replies; 24+ messages in thread
From: Nicolas Dufresne @ 2026-05-19 15:22 UTC (permalink / raw)
To: Paul Kocialkowski, linux-media, linux-arm-kernel, linux-sunxi,
linux-kernel, linux-staging
Cc: Mauro Carvalho Chehab, Chen-Yu Tsai, Jernej Skrabec,
Samuel Holland, Greg Kroah-Hartman, Arash Golgol,
Laurent Pinchart
[-- Attachment #1: Type: text/plain, Size: 2032 bytes --]
Le lundi 18 mai 2026 à 12:24 +0200, Paul Kocialkowski a écrit :
> Represent the NV12_16L16 pixel format in the v4l2 format info table.
> This is a 16x16 tiled version of NV12.
>
> Signed-off-by: Paul Kocialkowski <paulk@sys-base.io>
> ---
> drivers/media/v4l2-core/v4l2-common.c | 2 ++
> 1 file changed, 2 insertions(+)
>
> diff --git a/drivers/media/v4l2-core/v4l2-common.c b/drivers/media/v4l2-core/v4l2-common.c
> index e142d40c71b9..6194d6eb9c56 100644
> --- a/drivers/media/v4l2-core/v4l2-common.c
> +++ b/drivers/media/v4l2-core/v4l2-common.c
> @@ -313,6 +313,8 @@ const struct v4l2_format_info *v4l2_format_info(u32 format)
> .block_w = { 4, 4, 0, 0 }, .block_h = { 4, 4, 0, 0 }},
> { .format = V4L2_PIX_FMT_P010_4L4, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 2, 4, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2,
> .block_w = { 4, 4, 0, 0 }, .block_h = { 4, 4, 0, 0 }},
> + { .format = V4L2_PIX_FMT_NV12_16L16, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2,
> + .block_w = { 16, 16, 0, 0 }, .block_h = { 16, 16, 0, 0 }},
I suspect this is:
+ { .format = V4L2_PIX_FMT_NV12_16L16, .pixel_enc =
V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 },
.bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2,
+ .block_w = { 16, 8, 0, 0 }, .block_h = { 16, 16, 0, 0 }},
This was introduced for the Samsung MFC decoders on Exynos 5, has been matched
to V4L2_PIX_FMT_HM12, but I don't how it was tested though. But in this erra,
all the tiling was fixes dimensions in bytes, where your definition would make
the UV tiles twice the size of Y tiles.
Nicolas
>
> /* YUV planar formats, non contiguous variant */
> { .format = V4L2_PIX_FMT_YUV420M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2 },
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 08/16] media: v4l2-common: Add NV12_32L32 pixel format to v4l2 format info
2026-05-18 10:24 ` [PATCH 08/16] media: v4l2-common: Add NV12_32L32 " Paul Kocialkowski
@ 2026-05-19 15:23 ` Nicolas Dufresne
0 siblings, 0 replies; 24+ messages in thread
From: Nicolas Dufresne @ 2026-05-19 15:23 UTC (permalink / raw)
To: Paul Kocialkowski, linux-media, linux-arm-kernel, linux-sunxi,
linux-kernel, linux-staging
Cc: Mauro Carvalho Chehab, Chen-Yu Tsai, Jernej Skrabec,
Samuel Holland, Greg Kroah-Hartman, Arash Golgol,
Laurent Pinchart
[-- Attachment #1: Type: text/plain, Size: 1729 bytes --]
Le lundi 18 mai 2026 à 12:24 +0200, Paul Kocialkowski a écrit :
> Represent the NV12_32L32 pixel format in the v4l2 format info table.
> This is a 32x32 tiled version of NV12.
>
> Signed-off-by: Paul Kocialkowski <paulk@sys-base.io>
> ---
> drivers/media/v4l2-core/v4l2-common.c | 2 ++
> 1 file changed, 2 insertions(+)
>
> diff --git a/drivers/media/v4l2-core/v4l2-common.c b/drivers/media/v4l2-core/v4l2-common.c
> index 6194d6eb9c56..fe7141883ec5 100644
> --- a/drivers/media/v4l2-core/v4l2-common.c
> +++ b/drivers/media/v4l2-core/v4l2-common.c
> @@ -315,6 +315,8 @@ const struct v4l2_format_info *v4l2_format_info(u32 format)
> .block_w = { 4, 4, 0, 0 }, .block_h = { 4, 4, 0, 0 }},
> { .format = V4L2_PIX_FMT_NV12_16L16, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2,
> .block_w = { 16, 16, 0, 0 }, .block_h = { 16, 16, 0, 0 }},
> + { .format = V4L2_PIX_FMT_NV12_32L32, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2,
> + .block_w = { 32, 32, 0, 0 }, .block_h = { 32, 32, 0, 0 }},
Same.
+ { .format = V4L2_PIX_FMT_NV12_32L32, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2,
+ .block_w = { 32, 16, 0, 0 }, .block_h = { 32, 32, 0, 0 }},
>
> /* YUV planar formats, non contiguous variant */
> { .format = V4L2_PIX_FMT_YUV420M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2 },
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 24+ messages in thread
end of thread, other threads:[~2026-05-19 15:23 UTC | newest]
Thread overview: 24+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-18 10:24 [PATCH 00/16] media: sun6i-csi/isp MC-centric support and cleanups Paul Kocialkowski
2026-05-18 10:24 ` [PATCH 01/16] media: sun6i-csi: bridge: Use V4L2 subdev active state Paul Kocialkowski
2026-05-18 10:24 ` [PATCH 02/16] media: sun6i-csi: capture: Implement vidioc_enum_framesizes Paul Kocialkowski
2026-05-18 10:24 ` [PATCH 03/16] media: sun6i-mipi-csi2: Use V4L2 subdev active state Paul Kocialkowski
2026-05-18 10:24 ` [PATCH 04/16] media: sun8i-a83t-mipi-csi2: " Paul Kocialkowski
2026-05-18 14:09 ` Paul Kocialkowski
2026-05-18 10:24 ` [PATCH 05/16] media: v4l2-common: Fix NV15_4L4 format info block height Paul Kocialkowski
2026-05-19 15:16 ` Nicolas Dufresne
2026-05-18 10:24 ` [PATCH 06/16] media: v4l2-common: Add missing tiled format info block sizes Paul Kocialkowski
2026-05-19 15:18 ` Nicolas Dufresne
2026-05-18 10:24 ` [PATCH 07/16] media: v4l2-common: Add NV12_16L16 pixel format to v4l2 format info Paul Kocialkowski
2026-05-19 15:22 ` Nicolas Dufresne
2026-05-18 10:24 ` [PATCH 08/16] media: v4l2-common: Add NV12_32L32 " Paul Kocialkowski
2026-05-19 15:23 ` Nicolas Dufresne
2026-05-18 10:24 ` [PATCH 09/16] media: sun6i-csi: Split format validation to a dedicated helper Paul Kocialkowski
2026-05-18 10:24 ` [PATCH 10/16] media: sun6i-csi: Add support for MC-centric format enumeration Paul Kocialkowski
2026-05-18 10:24 ` [PATCH 11/16] media: sun6i-csi: Tidy up and unify coding style Paul Kocialkowski
2026-05-18 10:24 ` [PATCH 12/16] media: sun6i-mipi-csi2: Fix parenthesis alignment Paul Kocialkowski
2026-05-18 10:24 ` [PATCH 13/16] media: sun6i-isp: Add dummy params link_validate implementation Paul Kocialkowski
2026-05-18 10:24 ` [PATCH 14/16] media: sun6i-isp: Use V4L2 subdev active state Paul Kocialkowski
2026-05-18 10:24 ` [PATCH 15/16] media: sun6i-isp: Add support for MC-centric format enumeration Paul Kocialkowski
2026-05-18 10:24 ` [PATCH 16/16] media: sun6i-isp: Add support for frame size enumeration Paul Kocialkowski
2026-05-18 12:15 ` [PATCH 00/16] media: sun6i-csi/isp MC-centric support and cleanups Laurent Pinchart
2026-05-18 14:08 ` Paul Kocialkowski
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox