This patch series address some issues at atomisp that are preventing camorama
to work with atomisp driver.
After this series, I can use camorama just like on any other device. The frame
rate is slow (~7fps), though. Not sure if this is due to some sensor limitation or
because of some other issue.
Anyway this is a start :-)
Some notes:
1. Patch 1 fixes an issue at ov2680 logic. It probably needs to be reflected at the
other supported sensors;
2. MMAP is not working. So, it requires a newer version of camorama that has
support for USERPTR.
3. There's nothing special on Camorama for atomisp, except that it has support
for USERPTR.
4. Camorama currently doesn't allow changing the resolution of the camera.
That's because of several things:
a. The driver has a scaler, supporting resolutions from 32x16 to 1600x1200
on Asus T101HA.
b. The atomisp driver doesn't implement ENUM_FRAMEINTERVALS;
c. camorama is not prepared for cameras with scalers on it. It just lets one to
select the resolutions enumerated by ENUM_FRAMEINTERVALS.
Mauro Carvalho Chehab (7):
media: atomisp-ov2680: use v4l2_find_nearest_size()
media: atomisp: move a debug printf to a better place
media: atomisp: fix VIDIOC_S_FMT logic
media: atomisp: fix enum_fmt logic
media: atomisp: move atomisp_g_fmt_cap()
media: atomisp: fix try_fmt logic
media: atomisp: fix g_fmt logic
.../media/atomisp/i2c/atomisp-ov2680.c | 127 +++-----------
drivers/staging/media/atomisp/i2c/ov2680.h | 3 +-
.../staging/media/atomisp/pci/atomisp_cmd.c | 59 +++++--
.../staging/media/atomisp/pci/atomisp_ioctl.c | 157 ++++++++++--------
4 files changed, 162 insertions(+), 184 deletions(-)
--
2.31.1
The g_fmt logic is currently broken, as it is not returning
the same imagesize as previoulsy calculated by s_fmt.
Fix it by just re-using whatever it was defined at s_fmt,
if this was called before.
Signed-off-by: Mauro Carvalho Chehab <[email protected]>
---
To mailbombing on a large number of people, only mailing lists were C/C on the cover.
See [PATCH 0/7] at: https://lore.kernel.org/all/[email protected]/
.../staging/media/atomisp/pci/atomisp_ioctl.c | 64 ++-----------------
1 file changed, 7 insertions(+), 57 deletions(-)
diff --git a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c
index 1e6da6116a06..2fb64d5cbead 100644
--- a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c
+++ b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c
@@ -934,75 +934,25 @@ static int atomisp_try_fmt_cap(struct file *file, void *fh,
static int atomisp_g_fmt_cap(struct file *file, void *fh,
struct v4l2_format *f)
{
- struct v4l2_subdev_format fmt = {
- .which = V4L2_SUBDEV_FORMAT_ACTIVE
- };
struct video_device *vdev = video_devdata(file);
struct atomisp_device *isp = video_get_drvdata(vdev);
- struct v4l2_fmtdesc fmtdesc = { 0 };
struct atomisp_video_pipe *pipe;
- struct atomisp_sub_device *asd;
- struct v4l2_subdev *camera;
- u32 depth;
- int ret;
rt_mutex_lock(&isp->mutex);
pipe = atomisp_to_video_pipe(vdev);
rt_mutex_unlock(&isp->mutex);
f->fmt.pix = pipe->pix;
- if (!f->fmt.pix.width) {
- asd = atomisp_to_video_pipe(vdev)->asd;
- if (!asd)
- return -EINVAL;
- camera = isp->inputs[asd->input_curr].camera;
- if(!camera)
- return -EINVAL;
+ /* If s_fmt was issued, just return whatever is was previouly set */
+ if (f->fmt.pix.sizeimage)
+ return 0;
- ret = atomisp_enum_fmt_cap(file, fh, &fmtdesc);
- if (ret)
- return ret;
+ f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
+ f->fmt.pix.width = 10000;
+ f->fmt.pix.height = 10000;
- rt_mutex_lock(&isp->mutex);
- ret = v4l2_subdev_call(isp->inputs[asd->input_curr].camera,
- pad, get_fmt, NULL, &fmt);
- rt_mutex_unlock(&isp->mutex);
- if (ret)
- return ret;
-
- v4l2_fill_pix_format(&f->fmt.pix, &fmt.format);
-
- f->fmt.pix.pixelformat = fmtdesc.pixelformat;
-
- /*
- * HACK: The atomisp does something different here, as it
- * seems to set the sensor to a slightly higher resolution than
- * the visible ones. That seems to be needed by atomisp's ISP
- * in order to properly handle the frames. So, s_fmt adds 16
- * extra columns/lines. See atomisp_subdev_set_selection().
- *
- * Yet, the V4L2 userspace API doesn't expect those, so it
- * needs to be decremented when reporting the visible
- * resolution to userspace.
- */
- f->fmt.pix.width -= pad_w;
- f->fmt.pix.height -= pad_h;
- }
-
- depth = atomisp_get_pixel_depth(f->fmt.pix.pixelformat);
- f->fmt.pix.bytesperline = DIV_ROUND_UP(f->fmt.pix.width * depth, 8);
- f->fmt.pix.sizeimage = PAGE_ALIGN(f->fmt.pix.height * f->fmt.pix.bytesperline);
-
- /*
- * FIXME: do we need to setup this differently, depending on the
- * sensor or the pipeline?
- */
- f->fmt.pix.colorspace = V4L2_COLORSPACE_REC709;
- f->fmt.pix.ycbcr_enc = V4L2_YCBCR_ENC_709;
- f->fmt.pix.xfer_func = V4L2_XFER_FUNC_709;
-
- return 0;
+ return atomisp_try_fmt_cap(file, fh, f);
}
static int atomisp_s_fmt_cap(struct file *file, void *fh,
--
2.31.1
Currently, the enum lists the sensor's native format as a
supported format. However, trying to setup a pipeline using
it doesn't work.
So, exclude such formats from the enum.
Signed-off-by: Mauro Carvalho Chehab <[email protected]>
---
To mailbombing on a large number of people, only mailing lists were C/C on the cover.
See [PATCH 0/7] at: https://lore.kernel.org/all/[email protected]/
drivers/staging/media/atomisp/pci/atomisp_ioctl.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c
index 8df052f6190d..30483a84ed80 100644
--- a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c
+++ b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c
@@ -775,6 +775,7 @@ static int atomisp_enum_fmt_cap(struct file *file, void *fh,
struct v4l2_subdev_mbus_code_enum code = {
.which = V4L2_SUBDEV_FORMAT_ACTIVE,
};
+ const struct atomisp_format_bridge *format;
struct v4l2_subdev *camera;
unsigned int i, fi = 0;
int rval;
@@ -806,15 +807,15 @@ static int atomisp_enum_fmt_cap(struct file *file, void *fh,
return rval;
for (i = 0; i < ARRAY_SIZE(atomisp_output_fmts); i++) {
- const struct atomisp_format_bridge *format =
- &atomisp_output_fmts[i];
+ format = &atomisp_output_fmts[i];
/*
* Is the atomisp-supported format is valid for the
* sensor (configuration)? If not, skip it.
+ *
+ * FIXME: fix the pipeline to allow sensor format too.
*/
- if (format->sh_fmt == IA_CSS_FRAME_FORMAT_RAW
- && format->mbus_code != code.code)
+ if (format->sh_fmt == IA_CSS_FRAME_FORMAT_RAW)
continue;
/* Found a match. Now let's pick f->index'th one. */
--
2.31.1
There are several issues on S_FMT implementation:
- it doesn't properly handle pad_h/pad_w;
- it reports a wrong visible size to userspace;
- it allows setting the format to a raw mode, which
currently causes the pipeline to break.
Address such issues, for it to start working with generic
apps.
Signed-off-by: Mauro Carvalho Chehab <[email protected]>
---
To mailbombing on a large number of people, only mailing lists were C/C on the cover.
See [PATCH 0/7] at: https://lore.kernel.org/all/[email protected]/
.../staging/media/atomisp/pci/atomisp_cmd.c | 46 ++++++++++++++++++-
1 file changed, 44 insertions(+), 2 deletions(-)
diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.c b/drivers/staging/media/atomisp/pci/atomisp_cmd.c
index 76c9e89afb48..851046ecbdbf 100644
--- a/drivers/staging/media/atomisp/pci/atomisp_cmd.c
+++ b/drivers/staging/media/atomisp/pci/atomisp_cmd.c
@@ -5635,13 +5635,17 @@ int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f)
const struct atomisp_format_bridge *format_bridge;
const struct atomisp_format_bridge *snr_format_bridge;
struct ia_css_frame_info output_info, raw_output_info;
- struct v4l2_pix_format snr_fmt = f->fmt.pix;
- struct v4l2_pix_format backup_fmt = snr_fmt, s_fmt;
+ struct v4l2_pix_format snr_fmt;
+ struct v4l2_pix_format backup_fmt, s_fmt;
unsigned int dvs_env_w = 0, dvs_env_h = 0;
unsigned int padding_w = pad_w, padding_h = pad_h;
bool res_overflow = false, crop_needs_override = false;
struct v4l2_mbus_framefmt *isp_sink_fmt;
struct v4l2_mbus_framefmt isp_source_fmt = {0};
+ struct v4l2_subdev_format vformat = {
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ };
+ struct v4l2_mbus_framefmt *ffmt = &vformat.format;
struct v4l2_rect isp_sink_crop;
u16 source_pad = atomisp_subdev_source_pad(vdev);
struct v4l2_subdev_fh fh;
@@ -5672,9 +5676,38 @@ int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f)
if (!format_bridge)
return -EINVAL;
+ /* Currently, raw formats are broken!!! */
+
+ if (format_bridge->sh_fmt == IA_CSS_FRAME_FORMAT_RAW) {
+ f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420;
+
+ format_bridge = atomisp_get_format_bridge(f->fmt.pix.pixelformat);
+ if (!format_bridge)
+ return -EINVAL;
+ }
pipe->sh_fmt = format_bridge->sh_fmt;
pipe->pix.pixelformat = f->fmt.pix.pixelformat;
+ /* Ensure that the resolution is equal or below the maximum supported */
+
+ vformat.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+ v4l2_fill_mbus_format(ffmt, &f->fmt.pix, format_bridge->mbus_code);
+ ffmt->height += padding_h;
+ ffmt->width += padding_w;
+
+ ret = v4l2_subdev_call(isp->inputs[asd->input_curr].camera, pad,
+ set_fmt, NULL, &vformat);
+ if (ret)
+ return ret;
+
+ f->fmt.pix.width = ffmt->width - padding_w;
+ f->fmt.pix.height = ffmt->height - padding_h;
+
+ snr_fmt = f->fmt.pix;
+ backup_fmt = snr_fmt;
+
+ /**********************************************************************/
+
if (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_VF ||
(source_pad == ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW
&& asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO)) {
@@ -6080,6 +6113,15 @@ int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f)
else
isp->need_gfx_throttle = true;
+ /* Report the needed sizes */
+ f->fmt.pix.sizeimage = pipe->pix.sizeimage;
+ f->fmt.pix.bytesperline = pipe->pix.bytesperline;
+
+ dev_dbg(isp->dev, "%s: %dx%d, image size: %d, %d bytes per line\n",
+ __func__,
+ f->fmt.pix.width, f->fmt.pix.height,
+ f->fmt.pix.sizeimage, f->fmt.pix.bytesperline);
+
return 0;
}
--
2.31.1
move atomisp_g_fmt_cap() for it to be after try_fmt, as we'll
re-use try_fmt there.
No functional changes.
Signed-off-by: Mauro Carvalho Chehab <[email protected]>
---
To mailbombing on a large number of people, only mailing lists were C/C on the cover.
See [PATCH 0/7] at: https://lore.kernel.org/all/[email protected]/
.../staging/media/atomisp/pci/atomisp_ioctl.c | 56 +++++++++----------
1 file changed, 28 insertions(+), 28 deletions(-)
diff --git a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c
index 30483a84ed80..84ff97dabbed 100644
--- a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c
+++ b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c
@@ -833,6 +833,34 @@ static int atomisp_enum_fmt_cap(struct file *file, void *fh,
return -EINVAL;
}
+static int atomisp_g_fmt_file(struct file *file, void *fh,
+ struct v4l2_format *f)
+{
+ struct video_device *vdev = video_devdata(file);
+ struct atomisp_device *isp = video_get_drvdata(vdev);
+ struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev);
+
+ rt_mutex_lock(&isp->mutex);
+ f->fmt.pix = pipe->pix;
+ rt_mutex_unlock(&isp->mutex);
+
+ return 0;
+}
+
+/* This function looks up the closest available resolution. */
+static int atomisp_try_fmt_cap(struct file *file, void *fh,
+ struct v4l2_format *f)
+{
+ struct video_device *vdev = video_devdata(file);
+ struct atomisp_device *isp = video_get_drvdata(vdev);
+ int ret;
+
+ rt_mutex_lock(&isp->mutex);
+ ret = atomisp_try_fmt(vdev, &f->fmt.pix, NULL);
+ rt_mutex_unlock(&isp->mutex);
+ return ret;
+}
+
static int atomisp_g_fmt_cap(struct file *file, void *fh,
struct v4l2_format *f)
{
@@ -907,34 +935,6 @@ static int atomisp_g_fmt_cap(struct file *file, void *fh,
return 0;
}
-static int atomisp_g_fmt_file(struct file *file, void *fh,
- struct v4l2_format *f)
-{
- struct video_device *vdev = video_devdata(file);
- struct atomisp_device *isp = video_get_drvdata(vdev);
- struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev);
-
- rt_mutex_lock(&isp->mutex);
- f->fmt.pix = pipe->pix;
- rt_mutex_unlock(&isp->mutex);
-
- return 0;
-}
-
-/* This function looks up the closest available resolution. */
-static int atomisp_try_fmt_cap(struct file *file, void *fh,
- struct v4l2_format *f)
-{
- struct video_device *vdev = video_devdata(file);
- struct atomisp_device *isp = video_get_drvdata(vdev);
- int ret;
-
- rt_mutex_lock(&isp->mutex);
- ret = atomisp_try_fmt(vdev, &f->fmt.pix, NULL);
- rt_mutex_unlock(&isp->mutex);
- return ret;
-}
-
static int atomisp_s_fmt_cap(struct file *file, void *fh,
struct v4l2_format *f)
{
--
2.31.1
The sensor width/height report is alread being printed after
its calculus. The only reason for an extra debug printk is
when dis is used. So, change its message to reflect and move
it to be inside the if checks.
Signed-off-by: Mauro Carvalho Chehab <[email protected]>
---
To mailbombing on a large number of people, only mailing lists were C/C on the cover.
See [PATCH 0/7] at: https://lore.kernel.org/all/[email protected]/
drivers/staging/media/atomisp/pci/atomisp_cmd.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.c b/drivers/staging/media/atomisp/pci/atomisp_cmd.c
index feb75491a273..76c9e89afb48 100644
--- a/drivers/staging/media/atomisp/pci/atomisp_cmd.c
+++ b/drivers/staging/media/atomisp/pci/atomisp_cmd.c
@@ -5583,6 +5583,10 @@ static int atomisp_set_fmt_to_snr(struct video_device *vdev,
pad, set_fmt, &pad_state, &vformat);
if (ret)
return ret;
+
+ dev_dbg(isp->dev, "video dis: sensor width: %d, height: %d\n",
+ ffmt->width, ffmt->height);
+
if (ffmt->width < req_ffmt->width ||
ffmt->height < req_ffmt->height) {
req_ffmt->height -= dvs_env_h;
@@ -5593,8 +5597,6 @@ static int atomisp_set_fmt_to_snr(struct video_device *vdev,
asd->params.video_dis_en = false;
}
}
- dev_dbg(isp->dev, "sensor width: %d, height: %d\n",
- ffmt->width, ffmt->height);
vformat.which = V4L2_SUBDEV_FORMAT_ACTIVE;
ret = v4l2_subdev_call(isp->inputs[asd->input_curr].camera, pad,
set_fmt, NULL, &vformat);
--
2.31.1
Instead of reinventing the wheel, use v4l2_find_nearest_size()
in order to get the closest resolution.
This should address a bug where the wrong resolution was
selected.
Signed-off-by: Mauro Carvalho Chehab <[email protected]>
---
To mailbombing on a large number of people, only mailing lists were C/C on the cover.
See [PATCH 0/7] at: https://lore.kernel.org/all/[email protected]/
.../media/atomisp/i2c/atomisp-ov2680.c | 127 ++++--------------
drivers/staging/media/atomisp/i2c/ov2680.h | 3 +-
2 files changed, 25 insertions(+), 105 deletions(-)
diff --git a/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c b/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c
index 2111e4a478c1..160efa432934 100644
--- a/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c
+++ b/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c
@@ -147,7 +147,7 @@ static int ov2680_g_bin_factor_x(struct v4l2_subdev *sd, s32 *val)
struct i2c_client *client = v4l2_get_subdevdata(sd);
dev_dbg(&client->dev, "++++ov2680_g_bin_factor_x\n");
- *val = ov2680_res[dev->fmt_idx].bin_factor_x;
+ *val = dev->res->bin_factor_x;
return 0;
}
@@ -157,7 +157,7 @@ static int ov2680_g_bin_factor_y(struct v4l2_subdev *sd, s32 *val)
struct ov2680_device *dev = to_ov2680_sensor(sd);
struct i2c_client *client = v4l2_get_subdevdata(sd);
- *val = ov2680_res[dev->fmt_idx].bin_factor_y;
+ *val = dev->res->bin_factor_y;
dev_dbg(&client->dev, "++++ov2680_g_bin_factor_y\n");
return 0;
}
@@ -254,7 +254,7 @@ static long __ov2680_set_exposure(struct v4l2_subdev *sd, int coarse_itg,
"+++++++__ov2680_set_exposure coarse_itg %d, gain %d, digitgain %d++\n",
coarse_itg, gain, digitgain);
- vts = ov2680_res[dev->fmt_idx].lines_per_frame;
+ vts = dev->res->lines_per_frame;
/* group hold */
ret = ov2680_write_reg(client, 1,
@@ -843,76 +843,6 @@ static int ov2680_s_power(struct v4l2_subdev *sd, int on)
return ret;
}
-/*
- * distance - calculate the distance
- * @res: resolution
- * @w: width
- * @h: height
- *
- * Get the gap between resolution and w/h.
- * res->width/height smaller than w/h wouldn't be considered.
- * Returns the value of gap or -1 if fail.
- */
-#define LARGEST_ALLOWED_RATIO_MISMATCH 600
-static int distance(struct ov2680_resolution *res, u32 w, u32 h)
-{
- unsigned int w_ratio = (res->width << 13) / w;
- unsigned int h_ratio;
- int match;
-
- if (h == 0)
- return -1;
- h_ratio = (res->height << 13) / h;
- if (h_ratio == 0)
- return -1;
- match = abs(((w_ratio << 13) / h_ratio) - 8192);
-
- if ((w_ratio < 8192) || (h_ratio < 8192) ||
- (match > LARGEST_ALLOWED_RATIO_MISMATCH))
- return -1;
-
- return w_ratio + h_ratio;
-}
-
-/* Return the nearest higher resolution index */
-static int nearest_resolution_index(int w, int h)
-{
- int i;
- int idx = -1;
- int dist;
- int min_dist = INT_MAX;
- struct ov2680_resolution *tmp_res = NULL;
-
- for (i = 0; i < N_RES; i++) {
- tmp_res = &ov2680_res[i];
- dist = distance(tmp_res, w, h);
- if (dist == -1)
- continue;
- if (dist < min_dist) {
- min_dist = dist;
- idx = i;
- }
- }
-
- return idx;
-}
-
-static int get_resolution_index(int w, int h)
-{
- int i;
-
- for (i = 0; i < N_RES; i++) {
- if (w != ov2680_res[i].width)
- continue;
- if (h != ov2680_res[i].height)
- continue;
-
- return i;
- }
-
- return -1;
-}
-
static int ov2680_set_fmt(struct v4l2_subdev *sd,
struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *format)
@@ -921,8 +851,8 @@ static int ov2680_set_fmt(struct v4l2_subdev *sd,
struct ov2680_device *dev = to_ov2680_sensor(sd);
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct camera_mipi_info *ov2680_info = NULL;
+ static struct ov2680_resolution *res;
int ret = 0;
- int idx = 0;
dev_dbg(&client->dev, "%s: %s: pad: %d, fmt: %p\n",
__func__,
@@ -940,41 +870,34 @@ static int ov2680_set_fmt(struct v4l2_subdev *sd,
return -EINVAL;
mutex_lock(&dev->input_lock);
- idx = nearest_resolution_index(fmt->width, fmt->height);
- if (idx == -1) {
- /* return the largest resolution */
- fmt->width = ov2680_res[N_RES - 1].width;
- fmt->height = ov2680_res[N_RES - 1].height;
- } else {
- fmt->width = ov2680_res[idx].width;
- fmt->height = ov2680_res[idx].height;
- }
+
+ res = v4l2_find_nearest_size(ov2680_res_preview,
+ ARRAY_SIZE(ov2680_res_preview), width,
+ height, fmt->width, fmt->height);
+ if (!res)
+ res = &ov2680_res[N_RES - 1];
+
+ fmt->width = res->width;
+ fmt->height = res->height;
+
fmt->code = MEDIA_BUS_FMT_SBGGR10_1X10;
if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
sd_state->pads->try_fmt = *fmt;
mutex_unlock(&dev->input_lock);
return 0;
}
- dev->fmt_idx = get_resolution_index(fmt->width, fmt->height);
- dev_dbg(&client->dev, "%s: Resolution index: %d\n",
- __func__, dev->fmt_idx);
- if (dev->fmt_idx == -1) {
- dev_err(&client->dev, "get resolution fail\n");
- mutex_unlock(&dev->input_lock);
- return -EINVAL;
- }
- dev_dbg(&client->dev, "%s: i=%d, w=%d, h=%d\n",
- __func__, dev->fmt_idx, fmt->width, fmt->height);
+
+ dev_dbg(&client->dev, "%s: %dx%d\n",
+ __func__, fmt->width, fmt->height);
// IS IT NEEDED?
power_up(sd);
- ret = ov2680_write_reg_array(client, ov2680_res[dev->fmt_idx].regs);
+ ret = ov2680_write_reg_array(client, dev->res->regs);
if (ret)
dev_err(&client->dev,
"ov2680 write resolution register err: %d\n", ret);
- ret = ov2680_get_intg_factor(client, ov2680_info,
- &ov2680_res[dev->fmt_idx]);
+ ret = ov2680_get_intg_factor(client, ov2680_info, res);
if (ret) {
dev_err(&client->dev, "failed to get integration factor\n");
goto err;
@@ -989,8 +912,6 @@ static int ov2680_set_fmt(struct v4l2_subdev *sd,
if (v_flag)
ov2680_v_flip(sd, v_flag);
- v4l2_info(client, "\n%s idx %d\n", __func__, dev->fmt_idx);
-
/*
* ret = startup(sd);
* if (ret)
@@ -1014,8 +935,8 @@ static int ov2680_get_fmt(struct v4l2_subdev *sd,
if (!fmt)
return -EINVAL;
- fmt->width = ov2680_res[dev->fmt_idx].width;
- fmt->height = ov2680_res[dev->fmt_idx].height;
+ fmt->width = dev->res->width;
+ fmt->height = dev->res->height;
fmt->code = MEDIA_BUS_FMT_SBGGR10_1X10;
return 0;
@@ -1155,7 +1076,7 @@ static int ov2680_g_frame_interval(struct v4l2_subdev *sd,
struct ov2680_device *dev = to_ov2680_sensor(sd);
interval->interval.numerator = 1;
- interval->interval.denominator = ov2680_res[dev->fmt_idx].fps;
+ interval->interval.denominator = dev->res->fps;
return 0;
}
@@ -1193,7 +1114,7 @@ static int ov2680_g_skip_frames(struct v4l2_subdev *sd, u32 *frames)
struct ov2680_device *dev = to_ov2680_sensor(sd);
mutex_lock(&dev->input_lock);
- *frames = ov2680_res[dev->fmt_idx].skip_frames;
+ *frames = dev->res->skip_frames;
mutex_unlock(&dev->input_lock);
return 0;
@@ -1257,7 +1178,7 @@ static int ov2680_probe(struct i2c_client *client)
mutex_init(&dev->input_lock);
- dev->fmt_idx = 0;
+ dev->res = &ov2680_res_preview[0];
v4l2_i2c_subdev_init(&dev->sd, client, &ov2680_ops);
pdata = gmin_camera_platform_data(&dev->sd,
diff --git a/drivers/staging/media/atomisp/i2c/ov2680.h b/drivers/staging/media/atomisp/i2c/ov2680.h
index 874115f35fca..535440ed14d7 100644
--- a/drivers/staging/media/atomisp/i2c/ov2680.h
+++ b/drivers/staging/media/atomisp/i2c/ov2680.h
@@ -172,11 +172,10 @@ struct ov2680_device {
struct v4l2_mbus_framefmt format;
struct mutex input_lock;
struct v4l2_ctrl_handler ctrl_handler;
+ struct ov2680_resolution *res;
struct camera_sensor_platform_data *platform_data;
int vt_pix_clk_freq_mhz;
- int fmt_idx;
int run_mode;
- u8 res;
u8 type;
};
--
2.31.1
The internal try_fmt logic is not meant to provide everything
that the V4L2 API should provide. Also, it doesn't decrement
the pads that are used only internally by the driver, but aren't
part of the device's output.
Fix it.
Signed-off-by: Mauro Carvalho Chehab <[email protected]>
---
To mailbombing on a large number of people, only mailing lists were C/C on the cover.
See [PATCH 0/7] at: https://lore.kernel.org/all/[email protected]/
.../staging/media/atomisp/pci/atomisp_cmd.c | 7 --
.../staging/media/atomisp/pci/atomisp_ioctl.c | 72 ++++++++++++++++++-
2 files changed, 71 insertions(+), 8 deletions(-)
diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.c b/drivers/staging/media/atomisp/pci/atomisp_cmd.c
index 851046ecbdbf..0ddee36cdcd7 100644
--- a/drivers/staging/media/atomisp/pci/atomisp_cmd.c
+++ b/drivers/staging/media/atomisp/pci/atomisp_cmd.c
@@ -4918,13 +4918,6 @@ int atomisp_try_fmt(struct video_device *vdev, struct v4l2_pix_format *f,
}
f->pixelformat = fmt->pixelformat;
- /*
- * FIXME: do we need to setup this differently, depending on the
- * sensor or the pipeline?
- */
- f->colorspace = V4L2_COLORSPACE_REC709;
- f->ycbcr_enc = V4L2_YCBCR_ENC_709;
- f->xfer_func = V4L2_XFER_FUNC_709;
/*
* If the format is jpeg or custom RAW, then the width and height will
diff --git a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c
index 84ff97dabbed..1e6da6116a06 100644
--- a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c
+++ b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c
@@ -847,6 +847,72 @@ static int atomisp_g_fmt_file(struct file *file, void *fh,
return 0;
}
+static int atomisp_adjust_fmt(struct v4l2_format *f)
+{
+ const struct atomisp_format_bridge *format_bridge;
+ u32 padded_width;
+
+ format_bridge = atomisp_get_format_bridge(f->fmt.pix.pixelformat);
+
+ padded_width = f->fmt.pix.width + pad_w;
+
+ if (format_bridge->planar) {
+ f->fmt.pix.bytesperline = padded_width;
+ f->fmt.pix.sizeimage = PAGE_ALIGN(f->fmt.pix.height *
+ DIV_ROUND_UP(format_bridge->depth *
+ padded_width, 8));
+ } else {
+ f->fmt.pix.bytesperline = DIV_ROUND_UP(format_bridge->depth *
+ padded_width, 8);
+ f->fmt.pix.sizeimage = PAGE_ALIGN(f->fmt.pix.height * f->fmt.pix.bytesperline);
+ }
+
+ if (f->fmt.pix.field == V4L2_FIELD_ANY)
+ f->fmt.pix.field = V4L2_FIELD_NONE;
+
+ format_bridge = atomisp_get_format_bridge(f->fmt.pix.pixelformat);
+ if (!format_bridge)
+ return -EINVAL;
+
+ /* Currently, raw formats are broken!!! */
+ if (format_bridge->sh_fmt == IA_CSS_FRAME_FORMAT_RAW) {
+ f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420;
+
+ format_bridge = atomisp_get_format_bridge(f->fmt.pix.pixelformat);
+ if (!format_bridge)
+ return -EINVAL;
+ }
+
+ padded_width = f->fmt.pix.width + pad_w;
+
+ if (format_bridge->planar) {
+ f->fmt.pix.bytesperline = padded_width;
+ f->fmt.pix.sizeimage = PAGE_ALIGN(f->fmt.pix.height *
+ DIV_ROUND_UP(format_bridge->depth *
+ padded_width, 8));
+ } else {
+ f->fmt.pix.bytesperline = DIV_ROUND_UP(format_bridge->depth *
+ padded_width, 8);
+ f->fmt.pix.sizeimage = PAGE_ALIGN(f->fmt.pix.height * f->fmt.pix.bytesperline);
+ }
+
+ if (f->fmt.pix.field == V4L2_FIELD_ANY)
+ f->fmt.pix.field = V4L2_FIELD_NONE;
+
+ /*
+ * FIXME: do we need to setup this differently, depending on the
+ * sensor or the pipeline?
+ */
+ f->fmt.pix.colorspace = V4L2_COLORSPACE_REC709;
+ f->fmt.pix.ycbcr_enc = V4L2_YCBCR_ENC_709;
+ f->fmt.pix.xfer_func = V4L2_XFER_FUNC_709;
+
+ f->fmt.pix.width -= pad_w;
+ f->fmt.pix.height -= pad_h;
+
+ return 0;
+}
+
/* This function looks up the closest available resolution. */
static int atomisp_try_fmt_cap(struct file *file, void *fh,
struct v4l2_format *f)
@@ -858,7 +924,11 @@ static int atomisp_try_fmt_cap(struct file *file, void *fh,
rt_mutex_lock(&isp->mutex);
ret = atomisp_try_fmt(vdev, &f->fmt.pix, NULL);
rt_mutex_unlock(&isp->mutex);
- return ret;
+
+ if (ret)
+ return ret;
+
+ return atomisp_adjust_fmt(f);
}
static int atomisp_g_fmt_cap(struct file *file, void *fh,
--
2.31.1