[PATCH v4 14/15] media: atomisp: allow raw Bayer capture

From: Maurizio Casciano

Date: Fri Aug 28 2026 - 12:24:40 EST


AtomISP currently rejects all raw formats and silently substitutes
YUV420. This prevents userspace camera processing stacks from obtaining
unprocessed sensor frames.

Enumerate only the raw format matching the sensor media-bus code and
reconcile raw requests with the code selected by the sensor. Userspace
opts in by selecting that raw V4L2 pixel format with VIDIOC_S_FMT.

Raw formats expose the full sensor transport frame so ISP2401 can use
its copy pipeline. Processed formats retain the existing global padding
behavior; selecting a smaller receiver crop remains a userspace pipeline
decision.

Link: https://lore.kernel.org/linux-media/apCc_pt5dDxGJrei@ashevche-desk.local/
Link: https://lore.kernel.org/linux-media/apF0Cds9fnqQ7XRg@kekkonen.localdomain/
Signed-off-by: Maurizio Casciano <mauriziocasciano7@xxxxxxxxx>
Assisted-by: Codex:gpt-5.6-sol sparse
---
.../staging/media/atomisp/pci/atomisp_cmd.c | 19 +++++++++++++------
.../staging/media/atomisp/pci/atomisp_ioctl.c | 19 ++++++++++++++++---
2 files changed, 29 insertions(+), 9 deletions(-)

diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.c b/drivers/staging/media/atomisp/pci/atomisp_cmd.c
index 51dd59d98b3b..3d62cb948e31 100644
--- a/drivers/staging/media/atomisp/pci/atomisp_cmd.c
+++ b/drivers/staging/media/atomisp/pci/atomisp_cmd.c
@@ -3572,7 +3572,6 @@ void atomisp_get_padding(struct atomisp_device *isp, struct v4l2_area size,
u32 min_pad_w = ISP2400_MIN_PAD_W;
u32 min_pad_h = ISP2400_MIN_PAD_H;
struct v4l2_mbus_framefmt *sink;
-
if (!input->crop_support) {
pad->width = pad_w;
pad->height = pad_h;
@@ -3806,8 +3805,7 @@ int atomisp_try_fmt(struct atomisp_device *isp, struct v4l2_pix_format *f,
int ret;

fmt = atomisp_get_format_bridge(f->pixelformat);
- /* Currently, raw formats are broken!!! */
- if (!fmt || fmt->sh_fmt == IA_CSS_FRAME_FORMAT_RAW) {
+ if (!fmt) {
f->pixelformat = V4L2_PIX_FMT_YUV420;

fmt = atomisp_get_format_bridge(f->pixelformat);
@@ -3829,9 +3827,13 @@ int atomisp_try_fmt(struct atomisp_device *isp, struct v4l2_pix_format *f,
* resolution + padding. Add padding here and remove it again after
* the set_fmt call, like atomisp_set_fmt_to_snr() does.
*/
- size.width = f->width;
- size.height = f->height;
- atomisp_get_padding(isp, size, &padding);
+ if (fmt->sh_fmt == IA_CSS_FRAME_FORMAT_RAW) {
+ padding = (struct v4l2_area) { };
+ } else {
+ size.width = f->width;
+ size.height = f->height;
+ atomisp_get_padding(isp, size, &padding);
+ }
v4l2_fill_mbus_format(&ffmt, f, fmt->mbus_code);
ffmt.width += padding.width;
ffmt.height += padding.height;
@@ -3850,6 +3852,11 @@ int atomisp_try_fmt(struct atomisp_device *isp, struct v4l2_pix_format *f,
ffmt.code);
return -EINVAL;
}
+ if (fmt->sh_fmt == IA_CSS_FRAME_FORMAT_RAW &&
+ fmt->mbus_code != snr_fmt->mbus_code) {
+ fmt = snr_fmt;
+ f->pixelformat = fmt->pixelformat;
+ }

f->width = ffmt.width - padding.width;
f->height = ffmt.height - padding.height;
diff --git a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c
index 43bca68d1e6d..edad38809fc9 100644
--- a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c
+++ b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c
@@ -540,12 +540,21 @@ static int atomisp_enum_framesizes(struct file *file, void *priv,
.which = V4L2_SUBDEV_FORMAT_ACTIVE,
.code = input->code,
};
+ const struct atomisp_format_bridge *format;
struct v4l2_subdev_state *act_sd_state;
+ struct v4l2_area padding = {
+ .width = pad_w,
+ .height = pad_h,
+ };
int ret;

if (!input->sensor)
return -EINVAL;

+ format = atomisp_get_format_bridge(fsize->pixel_format);
+ if (!format)
+ return -EINVAL;
+
if (input->crop_support)
return atomisp_enum_framesizes_crop(isp, fsize);

@@ -557,9 +566,12 @@ static int atomisp_enum_framesizes(struct file *file, void *priv,
if (ret)
return ret;

+ if (format->sh_fmt == IA_CSS_FRAME_FORMAT_RAW)
+ padding = (struct v4l2_area) { };
+
fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
- fsize->discrete.width = fse.max_width - pad_w;
- fsize->discrete.height = fse.max_height - pad_h;
+ fsize->discrete.width = fse.max_width - padding.width;
+ fsize->discrete.height = fse.max_height - padding.height;

return 0;
}
@@ -633,7 +645,8 @@ static int atomisp_enum_fmt_cap(struct file *file, void *fh,
*
* FIXME: fix the pipeline to allow sensor format too.
*/
- if (format->sh_fmt == IA_CSS_FRAME_FORMAT_RAW)
+ if (format->sh_fmt == IA_CSS_FRAME_FORMAT_RAW &&
+ format->mbus_code != code.code)
continue;

/* Found a match. Now let's pick f->index'th one. */
--
2.53.0