aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/media/rkisp1
diff options
context:
space:
mode:
authorPeter Zijlstra <peterz@infradead.org>2020-11-26 13:16:55 +0100
committerPeter Zijlstra <peterz@infradead.org>2020-11-26 13:16:55 +0100
commit20c7775aecea04d8ca322039969d49dcf568e0e9 (patch)
tree138c057839197c9021043353e994815c0250e669 /drivers/staging/media/rkisp1
parentperf/x86/intel: Add event constraint for CYCLE_ACTIVITY.STALLS_MEM_ANY (diff)
parentMerge tag 'media/v5.10-2' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media (diff)
downloadlinux-dev-20c7775aecea04d8ca322039969d49dcf568e0e9.tar.xz
linux-dev-20c7775aecea04d8ca322039969d49dcf568e0e9.zip
Merge remote-tracking branch 'origin/master' into perf/core
Further perf/core patches will depend on: d3f7b1bb2040 ("mm/gup: fix gup_fast with dynamic page table folding") which is already in Linus' tree.
Diffstat (limited to 'drivers/staging/media/rkisp1')
-rw-r--r--drivers/staging/media/rkisp1/Documentation/media/uapi/v4l/pixfmt-meta-rkisp1-params.rst23
-rw-r--r--drivers/staging/media/rkisp1/Documentation/media/uapi/v4l/pixfmt-meta-rkisp1-stat.rst22
-rw-r--r--drivers/staging/media/rkisp1/TODO4
-rw-r--r--drivers/staging/media/rkisp1/rkisp1-capture.c230
-rw-r--r--drivers/staging/media/rkisp1/rkisp1-common.h281
-rw-r--r--drivers/staging/media/rkisp1/rkisp1-dev.c17
-rw-r--r--drivers/staging/media/rkisp1/rkisp1-isp.c59
-rw-r--r--drivers/staging/media/rkisp1/rkisp1-params.c211
-rw-r--r--drivers/staging/media/rkisp1/rkisp1-regs.h1
-rw-r--r--drivers/staging/media/rkisp1/rkisp1-resizer.c94
-rw-r--r--drivers/staging/media/rkisp1/rkisp1-stats.c29
-rw-r--r--drivers/staging/media/rkisp1/uapi/rkisp1-config.h289
12 files changed, 743 insertions, 517 deletions
diff --git a/drivers/staging/media/rkisp1/Documentation/media/uapi/v4l/pixfmt-meta-rkisp1-params.rst b/drivers/staging/media/rkisp1/Documentation/media/uapi/v4l/pixfmt-meta-rkisp1-params.rst
deleted file mode 100644
index 32034e481357..000000000000
--- a/drivers/staging/media/rkisp1/Documentation/media/uapi/v4l/pixfmt-meta-rkisp1-params.rst
+++ /dev/null
@@ -1,23 +0,0 @@
-.. SPDX-License-Identifier: (GPL-2.0+ OR MIT)
-
-.. _v4l2-meta-fmt-rkisp1-params:
-
-============================
-V4L2_META_FMT_RK_ISP1_PARAMS
-============================
-
-Rockchip ISP1 Parameters Data
-
-Description
-===========
-
-This format describes input parameters for the Rockchip ISP1.
-
-It uses c-struct :c:type:`rkisp1_params_cfg`, which is defined in
-the ``linux/rkisp1-config.h`` header file.
-
-The parameters consist of multiple modules.
-The module won't be updated if the corresponding bit was not set in module_*_update.
-
-.. kernel-doc:: include/uapi/linux/rkisp1-config.h
- :functions: rkisp1_params_cfg
diff --git a/drivers/staging/media/rkisp1/Documentation/media/uapi/v4l/pixfmt-meta-rkisp1-stat.rst b/drivers/staging/media/rkisp1/Documentation/media/uapi/v4l/pixfmt-meta-rkisp1-stat.rst
deleted file mode 100644
index 4ad303f96421..000000000000
--- a/drivers/staging/media/rkisp1/Documentation/media/uapi/v4l/pixfmt-meta-rkisp1-stat.rst
+++ /dev/null
@@ -1,22 +0,0 @@
-.. SPDX-License-Identifier: (GPL-2.0+ OR MIT)
-
-.. _v4l2-meta-fmt-rkisp1-stat:
-
-=============================
-V4L2_META_FMT_RK_ISP1_STAT_3A
-=============================
-
-
-Rockchip ISP1 Statistics Data
-
-Description
-===========
-
-This format describes image color statistics information generated by the Rockchip
-ISP1.
-
-It uses c-struct :c:type:`rkisp1_stat_buffer`, which is defined in
-the ``linux/rkisp1-config.h`` header file.
-
-.. kernel-doc:: include/uapi/linux/rkisp1-config.h
- :functions: rkisp1_stat_buffer
diff --git a/drivers/staging/media/rkisp1/TODO b/drivers/staging/media/rkisp1/TODO
index bdb1b8f73556..e7c8398fc2ce 100644
--- a/drivers/staging/media/rkisp1/TODO
+++ b/drivers/staging/media/rkisp1/TODO
@@ -1,8 +1,6 @@
* Fix pad format size for statistics and parameters entities.
* Fix checkpatch errors.
-* Review and comment every lock
-* Handle quantization
-* Document rkisp1-common.h
+* Add uapi docs. Remember to add documentation of how quantization is handled.
* streaming paths (mainpath and selfpath) check if the other path is streaming
in several places of the code, review this, specially that it doesn't seem it
supports streaming from both paths at the same time.
diff --git a/drivers/staging/media/rkisp1/rkisp1-capture.c b/drivers/staging/media/rkisp1/rkisp1-capture.c
index c05280950ea0..b6f497ce3e95 100644
--- a/drivers/staging/media/rkisp1/rkisp1-capture.c
+++ b/drivers/staging/media/rkisp1/rkisp1-capture.c
@@ -49,12 +49,14 @@ enum rkisp1_plane {
* @uv_swap: if cb cr swaped, for yuv
* @write_format: defines how YCbCr self picture data is written to memory
* @output_format: defines sp output format
+ * @mbus: the mbus code on the src resizer pad that matches the pixel format
*/
struct rkisp1_capture_fmt_cfg {
u32 fourcc;
u8 uv_swap;
u32 write_format;
u32 output_format;
+ u32 mbus;
};
struct rkisp1_capture_ops {
@@ -82,114 +84,133 @@ struct rkisp1_capture_config {
} mi;
};
+/*
+ * The supported pixel formats for mainpath. NOTE, pixel formats with identical 'mbus'
+ * are grouped together. This is assumed and used by the function rkisp1_cap_enum_mbus_codes
+ */
static const struct rkisp1_capture_fmt_cfg rkisp1_mp_fmts[] = {
/* yuv422 */
{
.fourcc = V4L2_PIX_FMT_YUYV,
.uv_swap = 0,
.write_format = RKISP1_MI_CTRL_MP_WRITE_YUVINT,
- }, {
- .fourcc = V4L2_PIX_FMT_YVYU,
- .uv_swap = 1,
- .write_format = RKISP1_MI_CTRL_MP_WRITE_YUVINT,
- }, {
- .fourcc = V4L2_PIX_FMT_VYUY,
- .write_format = RKISP1_MI_CTRL_MP_WRITE_YUVINT,
+ .mbus = MEDIA_BUS_FMT_YUYV8_2X8,
}, {
.fourcc = V4L2_PIX_FMT_YUV422P,
.uv_swap = 0,
.write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8,
+ .mbus = MEDIA_BUS_FMT_YUYV8_2X8,
}, {
.fourcc = V4L2_PIX_FMT_NV16,
.uv_swap = 0,
.write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_SPLA,
+ .mbus = MEDIA_BUS_FMT_YUYV8_2X8,
}, {
.fourcc = V4L2_PIX_FMT_NV61,
.uv_swap = 1,
.write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_SPLA,
+ .mbus = MEDIA_BUS_FMT_YUYV8_2X8,
}, {
.fourcc = V4L2_PIX_FMT_YVU422M,
.uv_swap = 1,
.write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8,
+ .mbus = MEDIA_BUS_FMT_YUYV8_2X8,
+ },
+ /* yuv400 */
+ {
+ .fourcc = V4L2_PIX_FMT_GREY,
+ .uv_swap = 0,
+ .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8,
+ .mbus = MEDIA_BUS_FMT_YUYV8_2X8,
},
/* yuv420 */
{
.fourcc = V4L2_PIX_FMT_NV21,
.uv_swap = 1,
.write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_SPLA,
+ .mbus = MEDIA_BUS_FMT_YUYV8_1_5X8,
}, {
.fourcc = V4L2_PIX_FMT_NV12,
.uv_swap = 0,
.write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_SPLA,
+ .mbus = MEDIA_BUS_FMT_YUYV8_1_5X8,
}, {
.fourcc = V4L2_PIX_FMT_NV21M,
.uv_swap = 1,
.write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_SPLA,
+ .mbus = MEDIA_BUS_FMT_YUYV8_1_5X8,
}, {
.fourcc = V4L2_PIX_FMT_NV12M,
.uv_swap = 0,
.write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_SPLA,
+ .mbus = MEDIA_BUS_FMT_YUYV8_1_5X8,
}, {
.fourcc = V4L2_PIX_FMT_YUV420,
.uv_swap = 0,
.write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8,
+ .mbus = MEDIA_BUS_FMT_YUYV8_1_5X8,
}, {
.fourcc = V4L2_PIX_FMT_YVU420,
.uv_swap = 1,
.write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8,
- },
- /* yuv444 */
- {
- .fourcc = V4L2_PIX_FMT_YUV444M,
- .uv_swap = 0,
- .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8,
- },
- /* yuv400 */
- {
- .fourcc = V4L2_PIX_FMT_GREY,
- .uv_swap = 0,
- .write_format = RKISP1_MI_CTRL_MP_WRITE_YUVINT,
+ .mbus = MEDIA_BUS_FMT_YUYV8_1_5X8,
},
/* raw */
{
.fourcc = V4L2_PIX_FMT_SRGGB8,
.write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8,
+ .mbus = MEDIA_BUS_FMT_SRGGB8_1X8,
}, {
.fourcc = V4L2_PIX_FMT_SGRBG8,
.write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8,
+ .mbus = MEDIA_BUS_FMT_SGRBG8_1X8,
}, {
.fourcc = V4L2_PIX_FMT_SGBRG8,
.write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8,
+ .mbus = MEDIA_BUS_FMT_SGBRG8_1X8,
}, {
.fourcc = V4L2_PIX_FMT_SBGGR8,
.write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8,
+ .mbus = MEDIA_BUS_FMT_SBGGR8_1X8,
}, {
.fourcc = V4L2_PIX_FMT_SRGGB10,
.write_format = RKISP1_MI_CTRL_MP_WRITE_RAW12,
+ .mbus = MEDIA_BUS_FMT_SRGGB10_1X10,
}, {
.fourcc = V4L2_PIX_FMT_SGRBG10,
.write_format = RKISP1_MI_CTRL_MP_WRITE_RAW12,
+ .mbus = MEDIA_BUS_FMT_SGRBG10_1X10,
}, {
.fourcc = V4L2_PIX_FMT_SGBRG10,
.write_format = RKISP1_MI_CTRL_MP_WRITE_RAW12,
+ .mbus = MEDIA_BUS_FMT_SGBRG10_1X10,
}, {
.fourcc = V4L2_PIX_FMT_SBGGR10,
.write_format = RKISP1_MI_CTRL_MP_WRITE_RAW12,
+ .mbus = MEDIA_BUS_FMT_SBGGR10_1X10,
}, {
.fourcc = V4L2_PIX_FMT_SRGGB12,
.write_format = RKISP1_MI_CTRL_MP_WRITE_RAW12,
+ .mbus = MEDIA_BUS_FMT_SRGGB12_1X12,
}, {
.fourcc = V4L2_PIX_FMT_SGRBG12,
.write_format = RKISP1_MI_CTRL_MP_WRITE_RAW12,
+ .mbus = MEDIA_BUS_FMT_SGRBG12_1X12,
}, {
.fourcc = V4L2_PIX_FMT_SGBRG12,
.write_format = RKISP1_MI_CTRL_MP_WRITE_RAW12,
+ .mbus = MEDIA_BUS_FMT_SGBRG12_1X12,
}, {
.fourcc = V4L2_PIX_FMT_SBGGR12,
.write_format = RKISP1_MI_CTRL_MP_WRITE_RAW12,
+ .mbus = MEDIA_BUS_FMT_SBGGR12_1X12,
},
};
+/*
+ * The supported pixel formats for selfpath. NOTE, pixel formats with identical 'mbus'
+ * are grouped together. This is assumed and used by the function rkisp1_cap_enum_mbus_codes
+ */
static const struct rkisp1_capture_fmt_cfg rkisp1_sp_fmts[] = {
/* yuv422 */
{
@@ -197,36 +218,51 @@ static const struct rkisp1_capture_fmt_cfg rkisp1_sp_fmts[] = {
.uv_swap = 0,
.write_format = RKISP1_MI_CTRL_SP_WRITE_INT,
.output_format = RKISP1_MI_CTRL_SP_OUTPUT_YUV422,
- }, {
- .fourcc = V4L2_PIX_FMT_YVYU,
- .uv_swap = 1,
- .write_format = RKISP1_MI_CTRL_SP_WRITE_INT,
- .output_format = RKISP1_MI_CTRL_SP_OUTPUT_YUV422,
- }, {
- .fourcc = V4L2_PIX_FMT_VYUY,
- .uv_swap = 1,
- .write_format = RKISP1_MI_CTRL_SP_WRITE_INT,
- .output_format = RKISP1_MI_CTRL_SP_OUTPUT_YUV422,
+ .mbus = MEDIA_BUS_FMT_YUYV8_2X8,
}, {
.fourcc = V4L2_PIX_FMT_YUV422P,
.uv_swap = 0,
.write_format = RKISP1_MI_CTRL_SP_WRITE_PLA,
.output_format = RKISP1_MI_CTRL_SP_OUTPUT_YUV422,
+ .mbus = MEDIA_BUS_FMT_YUYV8_2X8,
}, {
.fourcc = V4L2_PIX_FMT_NV16,
.uv_swap = 0,
.write_format = RKISP1_MI_CTRL_SP_WRITE_SPLA,
.output_format = RKISP1_MI_CTRL_SP_OUTPUT_YUV422,
+ .mbus = MEDIA_BUS_FMT_YUYV8_2X8,
}, {
.fourcc = V4L2_PIX_FMT_NV61,
.uv_swap = 1,
.write_format = RKISP1_MI_CTRL_SP_WRITE_SPLA,
.output_format = RKISP1_MI_CTRL_SP_OUTPUT_YUV422,
+ .mbus = MEDIA_BUS_FMT_YUYV8_2X8,
}, {
.fourcc = V4L2_PIX_FMT_YVU422M,
.uv_swap = 1,
.write_format = RKISP1_MI_CTRL_SP_WRITE_PLA,
.output_format = RKISP1_MI_CTRL_SP_OUTPUT_YUV422,
+ .mbus = MEDIA_BUS_FMT_YUYV8_2X8,
+ },
+ /* yuv400 */
+ {
+ .fourcc = V4L2_PIX_FMT_GREY,
+ .uv_swap = 0,
+ .write_format = RKISP1_MI_CTRL_SP_WRITE_PLA,
+ .output_format = RKISP1_MI_CTRL_SP_OUTPUT_YUV400,
+ .mbus = MEDIA_BUS_FMT_YUYV8_2X8,
+ },
+ /* rgb */
+ {
+ .fourcc = V4L2_PIX_FMT_XBGR32,
+ .write_format = RKISP1_MI_CTRL_SP_WRITE_PLA,
+ .output_format = RKISP1_MI_CTRL_SP_OUTPUT_RGB888,
+ .mbus = MEDIA_BUS_FMT_YUYV8_2X8,
+ }, {
+ .fourcc = V4L2_PIX_FMT_RGB565,
+ .write_format = RKISP1_MI_CTRL_SP_WRITE_PLA,
+ .output_format = RKISP1_MI_CTRL_SP_OUTPUT_RGB565,
+ .mbus = MEDIA_BUS_FMT_YUYV8_2X8,
},
/* yuv420 */
{
@@ -234,55 +270,37 @@ static const struct rkisp1_capture_fmt_cfg rkisp1_sp_fmts[] = {
.uv_swap = 1,
.write_format = RKISP1_MI_CTRL_SP_WRITE_SPLA,
.output_format = RKISP1_MI_CTRL_SP_OUTPUT_YUV420,
+ .mbus = MEDIA_BUS_FMT_YUYV8_1_5X8,
}, {
.fourcc = V4L2_PIX_FMT_NV12,
.uv_swap = 0,
.write_format = RKISP1_MI_CTRL_SP_WRITE_SPLA,
.output_format = RKISP1_MI_CTRL_SP_OUTPUT_YUV420,
+ .mbus = MEDIA_BUS_FMT_YUYV8_1_5X8,
}, {
.fourcc = V4L2_PIX_FMT_NV21M,
.uv_swap = 1,
.write_format = RKISP1_MI_CTRL_SP_WRITE_SPLA,
.output_format = RKISP1_MI_CTRL_SP_OUTPUT_YUV420,
+ .mbus = MEDIA_BUS_FMT_YUYV8_1_5X8,
}, {
.fourcc = V4L2_PIX_FMT_NV12M,
.uv_swap = 0,
.write_format = RKISP1_MI_CTRL_SP_WRITE_SPLA,
.output_format = RKISP1_MI_CTRL_SP_OUTPUT_YUV420,
+ .mbus = MEDIA_BUS_FMT_YUYV8_1_5X8,
}, {
.fourcc = V4L2_PIX_FMT_YUV420,
.uv_swap = 0,
.write_format = RKISP1_MI_CTRL_SP_WRITE_PLA,
.output_format = RKISP1_MI_CTRL_SP_OUTPUT_YUV420,
+ .mbus = MEDIA_BUS_FMT_YUYV8_1_5X8,
}, {
.fourcc = V4L2_PIX_FMT_YVU420,
.uv_swap = 1,
.write_format = RKISP1_MI_CTRL_SP_WRITE_PLA,
.output_format = RKISP1_MI_CTRL_SP_OUTPUT_YUV420,
- },
- /* yuv444 */
- {
- .fourcc = V4L2_PIX_FMT_YUV444M,
- .uv_swap = 0,
- .write_format = RKISP1_MI_CTRL_SP_WRITE_PLA,
- .output_format = RKISP1_MI_CTRL_SP_OUTPUT_YUV444,
- },
- /* yuv400 */
- {
- .fourcc = V4L2_PIX_FMT_GREY,
- .uv_swap = 0,
- .write_format = RKISP1_MI_CTRL_SP_WRITE_INT,
- .output_format = RKISP1_MI_CTRL_SP_OUTPUT_YUV400,
- },
- /* rgb */
- {
- .fourcc = V4L2_PIX_FMT_RGB24,
- .write_format = RKISP1_MI_CTRL_SP_WRITE_PLA,
- .output_format = RKISP1_MI_CTRL_SP_OUTPUT_RGB888,
- }, {
- .fourcc = V4L2_PIX_FMT_RGB565,
- .write_format = RKISP1_MI_CTRL_SP_WRITE_PLA,
- .output_format = RKISP1_MI_CTRL_SP_OUTPUT_RGB565,
+ .mbus = MEDIA_BUS_FMT_YUYV8_1_5X8,
},
};
@@ -324,6 +342,30 @@ rkisp1_vdev_to_node(struct video_device *vdev)
return container_of(vdev, struct rkisp1_vdev_node, vdev);
}
+int rkisp1_cap_enum_mbus_codes(struct rkisp1_capture *cap,
+ struct v4l2_subdev_mbus_code_enum *code)
+{
+ const struct rkisp1_capture_fmt_cfg *fmts = cap->config->fmts;
+ /*
+ * initialize curr_mbus to non existing mbus code 0 to ensure it is
+ * different from fmts[0].mbus
+ */
+ u32 curr_mbus = 0;
+ int i, n = 0;
+
+ for (i = 0; i < cap->config->fmt_size; i++) {
+ if (fmts[i].mbus == curr_mbus)
+ continue;
+
+ curr_mbus = fmts[i].mbus;
+ if (n++ == code->index) {
+ code->code = curr_mbus;
+ return 0;
+ }
+ }
+ return -EINVAL;
+}
+
/* ----------------------------------------------------------------------------
* Stream operations for self-picture path (sp) and main-picture path (mp)
*/
@@ -626,13 +668,12 @@ static void rkisp1_handle_buffer(struct rkisp1_capture *cap)
{
struct rkisp1_isp *isp = &cap->rkisp1->isp;
struct rkisp1_buffer *curr_buf;
- unsigned long flags;
- spin_lock_irqsave(&cap->buf.lock, flags);
+ spin_lock(&cap->buf.lock);
curr_buf = cap->buf.curr;
if (curr_buf) {
- curr_buf->vb.sequence = atomic_read(&isp->frame_sequence);
+ curr_buf->vb.sequence = isp->frame_sequence;
curr_buf->vb.vb2_buf.timestamp = ktime_get_boottime_ns();
curr_buf->vb.field = V4L2_FIELD_NONE;
vb2_buffer_done(&curr_buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
@@ -641,7 +682,7 @@ static void rkisp1_handle_buffer(struct rkisp1_capture *cap)
}
rkisp1_set_next_buf(cap);
- spin_unlock_irqrestore(&cap->buf.lock, flags);
+ spin_unlock(&cap->buf.lock);
}
void rkisp1_capture_isr(struct rkisp1_device *rkisp1)
@@ -716,7 +757,6 @@ static void rkisp1_vb2_buf_queue(struct vb2_buffer *vb)
container_of(vbuf, struct rkisp1_buffer, vb);
struct rkisp1_capture *cap = vb->vb2_queue->drv_priv;
const struct v4l2_pix_format_mplane *pixm = &cap->pix.fmt;
- unsigned long flags;
unsigned int i;
memset(ispbuf->buff_addr, 0, sizeof(ispbuf->buff_addr));
@@ -741,9 +781,9 @@ static void rkisp1_vb2_buf_queue(struct vb2_buffer *vb)
swap(ispbuf->buff_addr[RKISP1_PLANE_CR],
ispbuf->buff_addr[RKISP1_PLANE_CB]);
- spin_lock_irqsave(&cap->buf.lock, flags);
+ spin_lock_irq(&cap->buf.lock);
list_add_tail(&ispbuf->queue, &cap->buf.queue);
- spin_unlock_irqrestore(&cap->buf.lock, flags);
+ spin_unlock_irq(&cap->buf.lock);
}
static int rkisp1_vb2_buf_prepare(struct vb2_buffer *vb)
@@ -769,10 +809,9 @@ static int rkisp1_vb2_buf_prepare(struct vb2_buffer *vb)
static void rkisp1_return_all_buffers(struct rkisp1_capture *cap,
enum vb2_buffer_state state)
{
- unsigned long flags;
struct rkisp1_buffer *buf;
- spin_lock_irqsave(&cap->buf.lock, flags);
+ spin_lock_irq(&cap->buf.lock);
if (cap->buf.curr) {
vb2_buffer_done(&cap->buf.curr->vb.vb2_buf, state);
cap->buf.curr = NULL;
@@ -787,7 +826,7 @@ static void rkisp1_return_all_buffers(struct rkisp1_capture *cap,
list_del(&buf->queue);
vb2_buffer_done(&buf->vb.vb2_buf, state);
}
- spin_unlock_irqrestore(&cap->buf.lock, flags);
+ spin_unlock_irq(&cap->buf.lock);
}
/*
@@ -916,6 +955,7 @@ static void rkisp1_stream_start(struct rkisp1_capture *cap)
cap->ops->config(cap);
/* Setup a buffer for the next frame */
+ spin_lock_irq(&cap->buf.lock);
rkisp1_set_next_buf(cap);
cap->ops->enable(cap);
/* It's safe to config ACTIVE and SHADOW regs for the
@@ -933,6 +973,7 @@ static void rkisp1_stream_start(struct rkisp1_capture *cap)
RKISP1_CIF_MI_INIT_SOFT_UPD, RKISP1_CIF_MI_INIT);
rkisp1_set_next_buf(cap);
}
+ spin_unlock_irq(&cap->buf.lock);
cap->is_streaming = true;
}
@@ -1017,6 +1058,7 @@ rkisp1_fill_pixfmt(struct v4l2_pix_format_mplane *pixm,
unsigned int i;
u32 stride;
+ memset(pixm->plane_fmt, 0, sizeof(pixm->plane_fmt));
info = v4l2_format_info(pixm->pixelformat);
pixm->num_planes = info->mem_planes;
stride = info->bpp[0] * pixm->width;
@@ -1069,8 +1111,6 @@ static void rkisp1_try_fmt(const struct rkisp1_capture *cap,
const struct v4l2_format_info **fmt_info)
{
const struct rkisp1_capture_config *config = cap->config;
- struct rkisp1_capture *other_cap =
- &cap->rkisp1->capture_devs[cap->id ^ 1];
const struct rkisp1_capture_fmt_cfg *fmt;
const struct v4l2_format_info *info;
const unsigned int max_widths[] = { RKISP1_RSZ_MP_SRC_MAX_WIDTH,
@@ -1095,14 +1135,6 @@ static void rkisp1_try_fmt(const struct rkisp1_capture *cap,
info = rkisp1_fill_pixfmt(pixm, cap->id);
- /* can not change quantization when stream-on */
- if (other_cap->is_streaming)
- pixm->quantization = other_cap->pix.fmt.quantization;
- /* output full range by default, take effect in params */
- else if (!pixm->quantization ||
- pixm->quantization > V4L2_QUANTIZATION_LIM_RANGE)
- pixm->quantization = V4L2_QUANTIZATION_FULL_RANGE;
-
if (fmt_cfg)
*fmt_cfg = fmt;
if (fmt_info)
@@ -1136,14 +1168,27 @@ static int rkisp1_enum_fmt_vid_cap_mplane(struct file *file, void *priv,
{
struct rkisp1_capture *cap = video_drvdata(file);
const struct rkisp1_capture_fmt_cfg *fmt = NULL;
+ unsigned int i, n = 0;
- if (f->index >= cap->config->fmt_size)
- return -EINVAL;
+ if (!f->mbus_code) {
+ if (f->index >= cap->config->fmt_size)
+ return -EINVAL;
- fmt = &cap->config->fmts[f->index];
- f->pixelformat = fmt->fourcc;
+ fmt = &cap->config->fmts[f->index];
+ f->pixelformat = fmt->fourcc;
+ return 0;
+ }
- return 0;
+ for (i = 0; i < cap->config->fmt_size; i++) {
+ if (cap->config->fmts[i].mbus != f->mbus_code)
+ continue;
+
+ if (n++ == f->index) {
+ f->pixelformat = cap->config->fmts[i].fourcc;
+ return 0;
+ }
+ }
+ return -EINVAL;
}
static int rkisp1_s_fmt_vid_cap_mplane(struct file *file,
@@ -1210,29 +1255,11 @@ static int rkisp1_capture_link_validate(struct media_link *link)
struct v4l2_subdev *sd =
media_entity_to_v4l2_subdev(link->source->entity);
struct rkisp1_capture *cap = video_get_drvdata(vdev);
- struct rkisp1_isp *isp = &cap->rkisp1->isp;
- u8 isp_pix_enc = isp->src_fmt->pixel_enc;
- u8 cap_pix_enc = cap->pix.info->pixel_enc;
+ const struct rkisp1_capture_fmt_cfg *fmt =
+ rkisp1_find_fmt_cfg(cap, cap->pix.fmt.pixelformat);
struct v4l2_subdev_format sd_fmt;
int ret;
- if (cap->id == RKISP1_SELFPATH &&
- isp->src_fmt->mbus_code != MEDIA_BUS_FMT_YUYV8_2X8) {
- dev_err(cap->rkisp1->dev,
- "selfpath only supports MEDIA_BUS_FMT_YUYV8_2X8\n");
- return -EPIPE;
- }
-
- if (cap_pix_enc != isp_pix_enc &&
- !(isp_pix_enc == V4L2_PIXEL_ENC_YUV &&
- cap_pix_enc == V4L2_PIXEL_ENC_RGB)) {
- dev_err(cap->rkisp1->dev,
- "format type mismatch in link '%s:%d->%s:%d'\n",
- link->source->entity->name, link->source->index,
- link->sink->entity->name, link->sink->index);
- return -EPIPE;
- }
-
sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
sd_fmt.pad = link->source->index;
ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &sd_fmt);
@@ -1240,7 +1267,8 @@ static int rkisp1_capture_link_validate(struct media_link *link)
return ret;
if (sd_fmt.format.height != cap->pix.fmt.height ||
- sd_fmt.format.width != cap->pix.fmt.width)
+ sd_fmt.format.width != cap->pix.fmt.width ||
+ sd_fmt.format.code != fmt->mbus)
return -EPIPE;
return 0;
@@ -1265,7 +1293,7 @@ static const struct v4l2_file_operations rkisp1_fops = {
static void rkisp1_unregister_capture(struct rkisp1_capture *cap)
{
media_entity_cleanup(&cap->vnode.vdev.entity);
- video_unregister_device(&cap->vnode.vdev);
+ vb2_video_unregister_device(&cap->vnode.vdev);
}
void rkisp1_capture_devs_unregister(struct rkisp1_device *rkisp1)
@@ -1298,7 +1326,7 @@ static int rkisp1_register_capture(struct rkisp1_capture *cap)
vdev->v4l2_dev = v4l2_dev;
vdev->lock = &node->vlock;
vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE_MPLANE |
- V4L2_CAP_STREAMING;
+ V4L2_CAP_STREAMING | V4L2_CAP_IO_MC;
vdev->entity.ops = &rkisp1_media_ops;
video_set_drvdata(vdev, cap);
vdev->vfl_dir = VFL_DIR_RX;
diff --git a/drivers/staging/media/rkisp1/rkisp1-common.h b/drivers/staging/media/rkisp1/rkisp1-common.h
index 3dc51d703f73..45abacdbb664 100644
--- a/drivers/staging/media/rkisp1/rkisp1-common.h
+++ b/drivers/staging/media/rkisp1/rkisp1-common.h
@@ -22,9 +22,14 @@
#include "rkisp1-regs.h"
#include "uapi/rkisp1-config.h"
+/*
+ * flags on the 'direction' field in struct 'rkisp1_isp_mbus_info' that indicate
+ * on which pad the media bus format is supported
+ */
#define RKISP1_ISP_SD_SRC BIT(0)
#define RKISP1_ISP_SD_SINK BIT(1)
+/* min and max values for the widths and heights of the entities */
#define RKISP1_ISP_MAX_WIDTH 4032
#define RKISP1_ISP_MAX_HEIGHT 3024
#define RKISP1_ISP_MIN_WIDTH 32
@@ -37,29 +42,36 @@
#define RKISP1_RSZ_SRC_MIN_WIDTH 32
#define RKISP1_RSZ_SRC_MIN_HEIGHT 16
+/* the default width and height of all the entities */
#define RKISP1_DEFAULT_WIDTH 800
#define RKISP1_DEFAULT_HEIGHT 600
#define RKISP1_DRIVER_NAME "rkisp1"
#define RKISP1_BUS_INFO "platform:" RKISP1_DRIVER_NAME
+/* maximum number of clocks */
#define RKISP1_MAX_BUS_CLK 8
+/* a bitmask of the ready stats */
#define RKISP1_STATS_MEAS_MASK (RKISP1_CIF_ISP_AWB_DONE | \
RKISP1_CIF_ISP_AFM_FIN | \
RKISP1_CIF_ISP_EXP_END | \
RKISP1_CIF_ISP_HIST_MEASURE_RDY)
+
+/* enum for the resizer pads */
enum rkisp1_rsz_pad {
RKISP1_RSZ_PAD_SINK,
RKISP1_RSZ_PAD_SRC,
RKISP1_RSZ_PAD_MAX
};
+/* enum for the capture id */
enum rkisp1_stream_id {
RKISP1_MAINPATH,
RKISP1_SELFPATH,
};
+/* bayer patterns */
enum rkisp1_fmt_raw_pat_type {
RKISP1_RAW_RGGB = 0,
RKISP1_RAW_GRBG,
@@ -67,6 +79,7 @@ enum rkisp1_fmt_raw_pat_type {
RKISP1_RAW_BGGR,
};
+/* enum for the isp pads */
enum rkisp1_isp_pad {
RKISP1_ISP_PAD_SINK_VIDEO,
RKISP1_ISP_PAD_SINK_PARAMS,
@@ -76,8 +89,16 @@ enum rkisp1_isp_pad {
};
/*
- * struct rkisp1_sensor_async - Sensor information
- * @mbus: media bus configuration
+ * struct rkisp1_sensor_async - A container for the v4l2_async_subdev to add to the notifier
+ * of the v4l2-async API
+ *
+ * @asd: async_subdev variable for the sensor
+ * @lanes: number of lanes
+ * @mbus_type: type of bus (currently only CSI2 is supported)
+ * @mbus_flags: media bus (V4L2_MBUS_*) flags
+ * @sd: a pointer to v4l2_subdev struct of the sensor
+ * @pixel_rate_ctrl: pixel rate of the sensor, used to initialize the phy
+ * @dphy: a pointer to the phy
*/
struct rkisp1_sensor_async {
struct v4l2_async_subdev asd;
@@ -90,19 +111,17 @@ struct rkisp1_sensor_async {
};
/*
- * struct rkisp1_isp - ISP sub-device
+ * struct rkisp1_isp - ISP subdev entity
*
- * See Cropping regions of ISP in rkisp1.c for details
- * @sink_frm: input size, don't have to be equal to sensor size
- * @sink_fmt: input format
- * @sink_crop: crop for sink pad
- * @src_fmt: output format
- * @src_crop: output size
- * @ops_lock: ops serialization
- *
- * @is_dphy_errctrl_disabled : if dphy errctrl is disabled (avoid endless interrupt)
- * @frame_sequence: used to synchronize frame_id between video devices.
- * @quantization: output quantization
+ * @sd: v4l2_subdev variable
+ * @rkisp1: pointer to rkisp1_device
+ * @pads: media pads
+ * @pad_cfg: pads configurations
+ * @sink_fmt: input format
+ * @src_fmt: output format
+ * @ops_lock: ops serialization
+ * @is_dphy_errctrl_disabled: if dphy errctrl is disabled (avoid endless interrupt)
+ * @frame_sequence: used to synchronize frame_id between video devices.
*/
struct rkisp1_isp {
struct v4l2_subdev sd;
@@ -110,11 +129,19 @@ struct rkisp1_isp {
struct v4l2_subdev_pad_config pad_cfg[RKISP1_ISP_PAD_MAX];
const struct rkisp1_isp_mbus_info *sink_fmt;
const struct rkisp1_isp_mbus_info *src_fmt;
- struct mutex ops_lock;
+ struct mutex ops_lock; /* serialize the subdevice ops */
bool is_dphy_errctrl_disabled;
- atomic_t frame_sequence;
+ __u32 frame_sequence;
};
+/*
+ * struct rkisp1_vdev_node - Container for the video nodes: params, stats, mainpath, selfpath
+ *
+ * @buf_queue: queue of buffers
+ * @vlock: lock of the video node
+ * @vdev: video node
+ * @pad: media pad
+ */
struct rkisp1_vdev_node {
struct vb2_queue buf_queue;
struct mutex vlock; /* ioctl serialization mutex */
@@ -122,15 +149,32 @@ struct rkisp1_vdev_node {
struct media_pad pad;
};
+/*
+ * struct rkisp1_buffer - A container for the vb2 buffers used by the video devices:
+ * params, stats, mainpath, selfpath
+ *
+ * @vb: vb2 buffer
+ * @queue: entry of the buffer in the queue
+ * @buff_addr: dma addresses of each plane, used only by the capture devices: selfpath, mainpath
+ * @vaddr: virtual address for buffers used by params and stats devices
+ */
struct rkisp1_buffer {
struct vb2_v4l2_buffer vb;
struct list_head queue;
union {
u32 buff_addr[VIDEO_MAX_PLANES];
- void *vaddr[VIDEO_MAX_PLANES];
+ void *vaddr;
};
};
+/*
+ * struct rkisp1_dummy_buffer - A buffer to write the next frame to in case
+ * there are no vb2 buffers available.
+ *
+ * @vaddr: return value of call to dma_alloc_attrs.
+ * @dma_addr: dma address of the buffer.
+ * @size: size of the buffer.
+ */
struct rkisp1_dummy_buffer {
void *vaddr;
dma_addr_t dma_addr;
@@ -142,17 +186,29 @@ struct rkisp1_device;
/*
* struct rkisp1_capture - ISP capture video device
*
- * @pix.fmt: buffer format
- * @pix.info: pixel information
- * @pix.cfg: pixel configuration
+ * @vnode: video node
+ * @rkisp1: pointer to rkisp1_device
+ * @id: id of the capture, one of RKISP1_SELFPATH, RKISP1_MAINPATH
+ * @ops: list of callbacks to configure the capture device.
+ * @config: a pointer to the list of registers to configure the capture format.
+ * @is_streaming: device is streaming
+ * @is_stopping: stop_streaming callback was called and the device is in the process of
+ * stopping the streaming.
+ * @done: when stop_streaming callback is called, the device waits for the next irq
+ * handler to stop the streaming by waiting on the 'done' wait queue.
+ * If the irq handler is not called, the stream is stopped by the callback
+ * after timeout.
+ * @sp_y_stride: the selfpath allows to configure a y stride that is longer than the image width.
+ * @buf.lock: lock to protect buf.queue
+ * @buf.queue: queued buffer list
+ * @buf.dummy: dummy space to store dropped data
*
- * @buf.lock: lock to protect buf_queue
- * @buf.queue: queued buffer list
- * @buf.dummy: dummy space to store dropped data
- *
- * rkisp1 use shadowsock registers, so it need two buffer at a time
- * @buf.curr: the buffer used for current frame
- * @buf.next: the buffer used for next frame
+ * rkisp1 uses shadow registers, so it needs two buffers at a time
+ * @buf.curr: the buffer used for current frame
+ * @buf.next: the buffer used for next frame
+ * @pix.cfg: pixel configuration
+ * @pix.info: a pointer to the v4l2_format_info of the pixel format
+ * @pix.fmt: buffer format
*/
struct rkisp1_capture {
struct rkisp1_vdev_node vnode;
@@ -182,14 +238,18 @@ struct rkisp1_capture {
/*
* struct rkisp1_stats - ISP Statistics device
*
- * @lock: locks the buffer list 'stat' and 'is_streaming'
- * @stat: stats buffer list
+ * @vnode: video node
+ * @rkisp1: pointer to the rkisp1 device
+ * @lock: locks the buffer list 'stat' and 'is_streaming'
+ * @stat: queue of rkisp1_buffer
+ * @vdev_fmt: v4l2_format of the metadata format
+ * @is_streaming: device is streaming
*/
struct rkisp1_stats {
struct rkisp1_vdev_node vnode;
struct rkisp1_device *rkisp1;
- spinlock_t lock; /* locks 'is_streaming', and 'stats' */
+ spinlock_t lock; /* locks the buffers list 'stats' and 'is_streaming' */
struct list_head stat;
struct v4l2_format vdev_fmt;
bool is_streaming;
@@ -198,24 +258,40 @@ struct rkisp1_stats {
/*
* struct rkisp1_params - ISP input parameters device
*
- * @cur_params: Current ISP parameters
- * @is_first_params: the first params should take effect immediately
+ * @vnode: video node
+ * @rkisp1: pointer to the rkisp1 device
+ * @config_lock: locks the buffer list 'params' and 'is_streaming'
+ * @params: queue of rkisp1_buffer
+ * @vdev_fmt: v4l2_format of the metadata format
+ * @is_streaming: device is streaming
+ * @quantization: the quantization configured on the isp's src pad
+ * @raw_type: the bayer pattern on the isp video sink pad
*/
struct rkisp1_params {
struct rkisp1_vdev_node vnode;
struct rkisp1_device *rkisp1;
- spinlock_t config_lock;
+ spinlock_t config_lock; /* locks the buffers list 'params' and 'is_streaming' */
struct list_head params;
- struct rkisp1_params_cfg cur_params;
struct v4l2_format vdev_fmt;
bool is_streaming;
- bool is_first_params;
enum v4l2_quantization quantization;
enum rkisp1_fmt_raw_pat_type raw_type;
};
+/*
+ * struct rkisp1_resizer - Resizer subdev
+ *
+ * @sd: v4l2_subdev variable
+ * @id: id of the resizer, one of RKISP1_SELFPATH, RKISP1_MAINPATH
+ * @rkisp1: pointer to the rkisp1 device
+ * @pads: media pads
+ * @pad_cfg: configurations for the pads
+ * @config: the set of registers to configure the resizer
+ * @pixel_enc: pixel encoding of the resizer
+ * @ops_lock: a lock for the subdev ops
+ */
struct rkisp1_resizer {
struct v4l2_subdev sd;
enum rkisp1_stream_id id;
@@ -224,15 +300,33 @@ struct rkisp1_resizer {
struct v4l2_subdev_pad_config pad_cfg[RKISP1_RSZ_PAD_MAX];
const struct rkisp1_rsz_config *config;
enum v4l2_pixel_encoding pixel_enc;
- struct mutex ops_lock;
+ struct mutex ops_lock; /* serialize the subdevice ops */
};
+/*
+ * struct rkisp1_debug - Values to be exposed on debugfs.
+ * The parameters are counters of the number of times the
+ * event occurred since the driver was loaded.
+ *
+ * @data_loss: loss of data occurred within a line, processing failure
+ * @outform_size_error: size error is generated in outmux submodule
+ * @img_stabilization_size_error: size error is generated in image stabilization submodule
+ * @inform_size_err: size error is generated in inform submodule
+ * @mipi_error: mipi error occurred
+ * @stats_error: writing to the 'Interrupt clear register' did not clear
+ * it in the register 'Masked interrupt status'
+ * @stop_timeout: upon stream stop, the capture waits 1 second for the isr to stop
+ * the stream. This param is incremented in case of timeout.
+ * @frame_drop: a frame was ready but the buffer queue was empty so the frame
+ * was not sent to userspace
+ */
struct rkisp1_debug {
struct dentry *debugfs_dir;
unsigned long data_loss;
unsigned long outform_size_error;
unsigned long img_stabilization_size_error;
unsigned long inform_size_error;
+ unsigned long irq_delay;
unsigned long mipi_error;
unsigned long stats_error;
unsigned long stop_timeout[2];
@@ -241,13 +335,24 @@ struct rkisp1_debug {
/*
* struct rkisp1_device - ISP platform device
- * @base_addr: base register address
+ *
+ * @base_addr: base register address
+ * @irq: the irq number
+ * @dev: a pointer to the struct device
+ * @clk_size: number of clocks
+ * @clks: array of clocks
+ * @v4l2_dev: v4l2_device variable
+ * @media_dev: media_device variable
+ * @notifier: a notifier to register on the v4l2-async API to be notified on the sensor
* @active_sensor: sensor in-use, set when streaming on
- * @isp: ISP sub-device
- * @rkisp1_capture: capture video device
- * @stats: ISP statistics output device
- * @params: ISP input parameters device
- * @stream_lock: lock to serialize start/stop streaming in capture devices.
+ * @isp: ISP sub-device
+ * @resizer_devs: resizer sub-devices
+ * @capture_devs: capture devices
+ * @stats: ISP statistics metadata capture device
+ * @params: ISP parameters metadata output device
+ * @pipe: media pipeline
+ * @stream_lock: serializes {start/stop}_streaming callbacks between the capture devices.
+ * @debug: debug params to be exposed on debugfs
*/
struct rkisp1_device {
void __iomem *base_addr;
@@ -265,16 +370,21 @@ struct rkisp1_device {
struct rkisp1_stats stats;
struct rkisp1_params params;
struct media_pipeline pipe;
- struct mutex stream_lock;
+ struct mutex stream_lock; /* serialize {start/stop}_streaming cb between capture devices */
struct rkisp1_debug debug;
};
/*
- * struct rkisp1_isp_mbus_info - ISP pad format info
- *
- * Translate mbus_code to hardware format values
+ * struct rkisp1_isp_mbus_info - ISP media bus info, Translates media bus code to hardware
+ * format values
*
- * @bus_width: used for parallel
+ * @mbus_code: media bus code
+ * @pixel_enc: pixel encoding
+ * @mipi_dt: mipi data type
+ * @yuv_seq: the order of the Y, Cb, Cr values
+ * @bus_width: bus width
+ * @bayer_pat: bayer pattern
+ * @direction: a bitmask of the flags indicating on which pad the format is supported on
*/
struct rkisp1_isp_mbus_info {
u32 mbus_code;
@@ -297,44 +407,83 @@ static inline u32 rkisp1_read(struct rkisp1_device *rkisp1, unsigned int addr)
return readl(rkisp1->base_addr + addr);
}
+/*
+ * rkisp1_cap_enum_mbus_codes - A helper function that return the i'th supported mbus code
+ * of the capture entity. This is used to enumerate the supported
+ * mbus codes on the source pad of the resizer.
+ *
+ * @cap: the capture entity
+ * @code: the mbus code, the function reads the code->index and fills the code->code
+ */
+int rkisp1_cap_enum_mbus_codes(struct rkisp1_capture *cap,
+ struct v4l2_subdev_mbus_code_enum *code);
+
+/*
+ * rkisp1_sd_adjust_crop_rect - adjust a rectangle to fit into another rectangle.
+ *
+ * @crop: rectangle to adjust.
+ * @bounds: rectangle used as bounds.
+ */
void rkisp1_sd_adjust_crop_rect(struct v4l2_rect *crop,
const struct v4l2_rect *bounds);
+/*
+ * rkisp1_sd_adjust_crop - adjust a rectangle to fit into media bus format
+ *
+ * @crop: rectangle to adjust.
+ * @bounds: media bus format used as bounds.
+ */
void rkisp1_sd_adjust_crop(struct v4l2_rect *crop,
const struct v4l2_mbus_framefmt *bounds);
-int rkisp1_isp_register(struct rkisp1_device *rkisp1,
- struct v4l2_device *v4l2_dev);
-void rkisp1_isp_unregister(struct rkisp1_device *rkisp1);
-
+/*
+ * rkisp1_isp_mbus_info - get the isp info of the media bus code
+ *
+ * @mbus_code: the media bus code
+ */
const struct rkisp1_isp_mbus_info *rkisp1_isp_mbus_info_get(u32 mbus_code);
+/* rkisp1_params_configure - configure the params when stream starts.
+ * This function is called by the isp entity upon stream starts.
+ * The function applies the initial configuration of the parameters.
+ *
+ * @params: pointer to rkisp1_params.
+ * @bayer_pat: the bayer pattern on the isp video sink pad
+ * @quantization: the quantization configured on the isp's src pad
+ */
+void rkisp1_params_configure(struct rkisp1_params *params,
+ enum rkisp1_fmt_raw_pat_type bayer_pat,
+ enum v4l2_quantization quantization);
+
+/* rkisp1_params_disable - disable all parameters.
+ * This function is called by the isp entity upon stream start
+ * when capturing bayer format.
+ *
+ * @params: pointer to rkisp1_params.
+ */
+void rkisp1_params_disable(struct rkisp1_params *params);
+
+/* irq handlers */
void rkisp1_isp_isr(struct rkisp1_device *rkisp1);
void rkisp1_mipi_isr(struct rkisp1_device *rkisp1);
void rkisp1_capture_isr(struct rkisp1_device *rkisp1);
void rkisp1_stats_isr(struct rkisp1_stats *stats, u32 isp_ris);
-void rkisp1_params_isr(struct rkisp1_device *rkisp1, u32 isp_mis);
+void rkisp1_params_isr(struct rkisp1_device *rkisp1);
+/* register/unregisters functions of the entities */
int rkisp1_capture_devs_register(struct rkisp1_device *rkisp1);
void rkisp1_capture_devs_unregister(struct rkisp1_device *rkisp1);
+int rkisp1_isp_register(struct rkisp1_device *rkisp1);
+void rkisp1_isp_unregister(struct rkisp1_device *rkisp1);
+
int rkisp1_resizer_devs_register(struct rkisp1_device *rkisp1);
void rkisp1_resizer_devs_unregister(struct rkisp1_device *rkisp1);
-int rkisp1_stats_register(struct rkisp1_stats *stats,
- struct v4l2_device *v4l2_dev,
- struct rkisp1_device *rkisp1);
-void rkisp1_stats_unregister(struct rkisp1_stats *stats);
-
-void rkisp1_params_configure(struct rkisp1_params *params,
- enum rkisp1_fmt_raw_pat_type bayer_pat,
- enum v4l2_quantization quantization);
-void rkisp1_params_disable(struct rkisp1_params *params);
-int rkisp1_params_register(struct rkisp1_params *params,
- struct v4l2_device *v4l2_dev,
- struct rkisp1_device *rkisp1);
-void rkisp1_params_unregister(struct rkisp1_params *params);
+int rkisp1_stats_register(struct rkisp1_device *rkisp1);
+void rkisp1_stats_unregister(struct rkisp1_device *rkisp1);
-void rkisp1_params_isr_handler(struct rkisp1_device *rkisp1, u32 isp_mis);
+int rkisp1_params_register(struct rkisp1_device *rkisp1);
+void rkisp1_params_unregister(struct rkisp1_device *rkisp1);
#endif /* _RKISP1_COMMON_H */
diff --git a/drivers/staging/media/rkisp1/rkisp1-dev.c b/drivers/staging/media/rkisp1/rkisp1-dev.c
index a0eb8f08708b..91584695804b 100644
--- a/drivers/staging/media/rkisp1/rkisp1-dev.c
+++ b/drivers/staging/media/rkisp1/rkisp1-dev.c
@@ -345,7 +345,7 @@ static int rkisp1_entities_register(struct rkisp1_device *rkisp1)
{
int ret;
- ret = rkisp1_isp_register(rkisp1, &rkisp1->v4l2_dev);
+ ret = rkisp1_isp_register(rkisp1);
if (ret)
return ret;
@@ -357,12 +357,11 @@ static int rkisp1_entities_register(struct rkisp1_device *rkisp1)
if (ret)
goto err_unreg_resizer_devs;
- ret = rkisp1_stats_register(&rkisp1->stats, &rkisp1->v4l2_dev, rkisp1);
+ ret = rkisp1_stats_register(rkisp1);
if (ret)
goto err_unreg_capture_devs;
- ret = rkisp1_params_register(&rkisp1->params,
- &rkisp1->v4l2_dev, rkisp1);
+ ret = rkisp1_params_register(rkisp1);
if (ret)
goto err_unreg_stats;
@@ -375,9 +374,9 @@ static int rkisp1_entities_register(struct rkisp1_device *rkisp1)
return 0;
err_unreg_params:
- rkisp1_params_unregister(&rkisp1->params);
+ rkisp1_params_unregister(rkisp1);
err_unreg_stats:
- rkisp1_stats_unregister(&rkisp1->stats);
+ rkisp1_stats_unregister(rkisp1);
err_unreg_capture_devs:
rkisp1_capture_devs_unregister(rkisp1);
err_unreg_resizer_devs:
@@ -445,6 +444,8 @@ static void rkisp1_debug_init(struct rkisp1_device *rkisp1)
&debug->img_stabilization_size_error);
debugfs_create_ulong("inform_size_error", 0444, debug->debugfs_dir,
&debug->inform_size_error);
+ debugfs_create_ulong("irq_delay", 0444, debug->debugfs_dir,
+ &debug->irq_delay);
debugfs_create_ulong("mipi_error", 0444, debug->debugfs_dir,
&debug->mipi_error);
debugfs_create_ulong("stats_error", 0444, debug->debugfs_dir,
@@ -551,8 +552,8 @@ static int rkisp1_remove(struct platform_device *pdev)
v4l2_async_notifier_unregister(&rkisp1->notifier);
v4l2_async_notifier_cleanup(&rkisp1->notifier);
- rkisp1_params_unregister(&rkisp1->params);
- rkisp1_stats_unregister(&rkisp1->stats);
+ rkisp1_params_unregister(rkisp1);
+ rkisp1_stats_unregister(rkisp1);
rkisp1_capture_devs_unregister(rkisp1);
rkisp1_resizer_devs_unregister(rkisp1);
rkisp1_isp_unregister(rkisp1);
diff --git a/drivers/staging/media/rkisp1/rkisp1-isp.c b/drivers/staging/media/rkisp1/rkisp1-isp.c
index 6ec1e9816e9f..a9715b0b7264 100644
--- a/drivers/staging/media/rkisp1/rkisp1-isp.c
+++ b/drivers/staging/media/rkisp1/rkisp1-isp.c
@@ -348,7 +348,7 @@ static int rkisp1_config_isp(struct rkisp1_device *rkisp1)
rkisp1_write(rkisp1, sink_crop->height, RKISP1_CIF_ISP_OUT_V_SIZE);
irq_mask |= RKISP1_CIF_ISP_FRAME | RKISP1_CIF_ISP_V_START |
- RKISP1_CIF_ISP_PIC_SIZE_ERROR | RKISP1_CIF_ISP_FRAME_IN;
+ RKISP1_CIF_ISP_PIC_SIZE_ERROR;
rkisp1_write(rkisp1, irq_mask, RKISP1_CIF_ISP_IMSC);
if (src_fmt->pixel_enc == V4L2_PIXEL_ENC_BAYER) {
@@ -589,6 +589,10 @@ static int rkisp1_isp_enum_mbus_code(struct v4l2_subdev *sd,
if (code->index == pos - 1) {
code->code = fmt->mbus_code;
+ if (fmt->pixel_enc == V4L2_PIXEL_ENC_YUV &&
+ dir == RKISP1_ISP_SD_SRC)
+ code->flags =
+ V4L2_SUBDEV_MBUS_CODE_CSC_QUANTIZATION;
return 0;
}
}
@@ -620,7 +624,6 @@ static int rkisp1_isp_init_config(struct v4l2_subdev *sd,
RKISP1_ISP_PAD_SOURCE_VIDEO);
*src_fmt = *sink_fmt;
src_fmt->code = RKISP1_DEF_SRC_PAD_FMT;
- src_fmt->quantization = V4L2_QUANTIZATION_FULL_RANGE;
src_crop = v4l2_subdev_get_try_crop(sd, cfg,
RKISP1_ISP_PAD_SOURCE_VIDEO);
@@ -663,9 +666,18 @@ static void rkisp1_isp_set_src_fmt(struct rkisp1_isp *isp,
isp->src_fmt = mbus_info;
src_fmt->width = src_crop->width;
src_fmt->height = src_crop->height;
- src_fmt->quantization = format->quantization;
- /* full range by default */
- if (!src_fmt->quantization)
+
+ /*
+ * The CSC API is used to allow userspace to force full
+ * quantization on YUV formats.
+ */
+ if (format->flags & V4L2_MBUS_FRAMEFMT_SET_CSC &&
+ format->quantization == V4L2_QUANTIZATION_FULL_RANGE &&
+ mbus_info->pixel_enc == V4L2_PIXEL_ENC_YUV)
+ src_fmt->quantization = V4L2_QUANTIZATION_FULL_RANGE;
+ else if (mbus_info->pixel_enc == V4L2_PIXEL_ENC_YUV)
+ src_fmt->quantization = V4L2_QUANTIZATION_LIM_RANGE;
+ else
src_fmt->quantization = V4L2_QUANTIZATION_FULL_RANGE;
*format = *src_fmt;
@@ -940,7 +952,7 @@ static int rkisp1_isp_s_stream(struct v4l2_subdev *sd, int enable)
if (rkisp1->active_sensor->mbus_type != V4L2_MBUS_CSI2_DPHY)
return -EINVAL;
- atomic_set(&rkisp1->isp.frame_sequence, -1);
+ rkisp1->isp.frame_sequence = -1;
mutex_lock(&isp->ops_lock);
ret = rkisp1_config_cif(rkisp1);
if (ret)
@@ -989,8 +1001,7 @@ static const struct v4l2_subdev_ops rkisp1_isp_ops = {
.pad = &rkisp1_isp_pad_ops,
};
-int rkisp1_isp_register(struct rkisp1_device *rkisp1,
- struct v4l2_device *v4l2_dev)
+int rkisp1_isp_register(struct rkisp1_device *rkisp1)
{
struct rkisp1_isp *isp = &rkisp1->isp;
struct media_pad *pads = isp->pads;
@@ -1018,7 +1029,7 @@ int rkisp1_isp_register(struct rkisp1_device *rkisp1,
if (ret)
return ret;
- ret = v4l2_device_register_subdev(v4l2_dev, sd);
+ ret = v4l2_device_register_subdev(&rkisp1->v4l2_dev, sd);
if (ret) {
dev_err(rkisp1->dev, "Failed to register isp subdev\n");
goto err_cleanup_media_entity;
@@ -1093,15 +1104,8 @@ static void rkisp1_isp_queue_event_sof(struct rkisp1_isp *isp)
struct v4l2_event event = {
.type = V4L2_EVENT_FRAME_SYNC,
};
+ event.u.frame_sync.frame_sequence = isp->frame_sequence;
- /*
- * Increment the frame sequence on the vsync signal.
- * This will allow applications to detect dropped.
- * Note that there is a debugfs counter for dropped
- * frames, but using this event is more accurate.
- */
- event.u.frame_sync.frame_sequence =
- atomic_inc_return(&isp->frame_sequence);
v4l2_event_queue(isp->sd.devnode, &event);
}
@@ -1116,9 +1120,14 @@ void rkisp1_isp_isr(struct rkisp1_device *rkisp1)
rkisp1_write(rkisp1, status, RKISP1_CIF_ISP_ICR);
/* Vertical sync signal, starting generating new frame */
- if (status & RKISP1_CIF_ISP_V_START)
+ if (status & RKISP1_CIF_ISP_V_START) {
+ rkisp1->isp.frame_sequence++;
rkisp1_isp_queue_event_sof(&rkisp1->isp);
-
+ if (status & RKISP1_CIF_ISP_FRAME) {
+ WARN_ONCE(1, "irq delay is too long, buffers might not be in sync\n");
+ rkisp1->debug.irq_delay++;
+ }
+ }
if (status & RKISP1_CIF_ISP_PIC_SIZE_ERROR) {
/* Clear pic_size_error */
isp_err = rkisp1_read(rkisp1, RKISP1_CIF_ISP_ERR);
@@ -1141,12 +1150,12 @@ void rkisp1_isp_isr(struct rkisp1_device *rkisp1)
isp_ris = rkisp1_read(rkisp1, RKISP1_CIF_ISP_RIS);
if (isp_ris & RKISP1_STATS_MEAS_MASK)
rkisp1_stats_isr(&rkisp1->stats, isp_ris);
+ /*
+ * Then update changed configs. Some of them involve
+ * lot of register writes. Do those only one per frame.
+ * Do the updates in the order of the processing flow.
+ */
+ rkisp1_params_isr(rkisp1);
}
- /*
- * Then update changed configs. Some of them involve
- * lot of register writes. Do those only one per frame.
- * Do the updates in the order of the processing flow.
- */
- rkisp1_params_isr(rkisp1, status);
}
diff --git a/drivers/staging/media/rkisp1/rkisp1-params.c b/drivers/staging/media/rkisp1/rkisp1-params.c
index 797e79de659c..986d293201e6 100644
--- a/drivers/staging/media/rkisp1/rkisp1-params.c
+++ b/drivers/staging/media/rkisp1/rkisp1-params.c
@@ -206,47 +206,45 @@ rkisp1_lsc_correct_matrix_config(struct rkisp1_params *params,
RKISP1_CIF_ISP_LSC_B_TABLE_ADDR);
/* program data tables (table size is 9 * 17 = 153) */
- for (i = 0;
- i < RKISP1_CIF_ISP_LSC_SECTORS_MAX * RKISP1_CIF_ISP_LSC_SECTORS_MAX;
- i += RKISP1_CIF_ISP_LSC_SECTORS_MAX) {
+ for (i = 0; i < RKISP1_CIF_ISP_LSC_SAMPLES_MAX; i++) {
/*
* 17 sectors with 2 values in one DWORD = 9
* DWORDs (2nd value of last DWORD unused)
*/
- for (j = 0; j < RKISP1_CIF_ISP_LSC_SECTORS_MAX - 1; j += 2) {
- data = RKISP1_CIF_ISP_LSC_TABLE_DATA(pconfig->r_data_tbl[i + j],
- pconfig->r_data_tbl[i + j + 1]);
+ for (j = 0; j < RKISP1_CIF_ISP_LSC_SAMPLES_MAX - 1; j += 2) {
+ data = RKISP1_CIF_ISP_LSC_TABLE_DATA(pconfig->r_data_tbl[i][j],
+ pconfig->r_data_tbl[i][j + 1]);
rkisp1_write(params->rkisp1, data,
RKISP1_CIF_ISP_LSC_R_TABLE_DATA);
- data = RKISP1_CIF_ISP_LSC_TABLE_DATA(pconfig->gr_data_tbl[i + j],
- pconfig->gr_data_tbl[i + j + 1]);
+ data = RKISP1_CIF_ISP_LSC_TABLE_DATA(pconfig->gr_data_tbl[i][j],
+ pconfig->gr_data_tbl[i][j + 1]);
rkisp1_write(params->rkisp1, data,
RKISP1_CIF_ISP_LSC_GR_TABLE_DATA);
- data = RKISP1_CIF_ISP_LSC_TABLE_DATA(pconfig->gb_data_tbl[i + j],
- pconfig->gb_data_tbl[i + j + 1]);
+ data = RKISP1_CIF_ISP_LSC_TABLE_DATA(pconfig->gb_data_tbl[i][j],
+ pconfig->gb_data_tbl[i][j + 1]);
rkisp1_write(params->rkisp1, data,
RKISP1_CIF_ISP_LSC_GB_TABLE_DATA);
- data = RKISP1_CIF_ISP_LSC_TABLE_DATA(pconfig->b_data_tbl[i + j],
- pconfig->b_data_tbl[i + j + 1]);
+ data = RKISP1_CIF_ISP_LSC_TABLE_DATA(pconfig->b_data_tbl[i][j],
+ pconfig->b_data_tbl[i][j + 1]);
rkisp1_write(params->rkisp1, data,
RKISP1_CIF_ISP_LSC_B_TABLE_DATA);
}
- data = RKISP1_CIF_ISP_LSC_TABLE_DATA(pconfig->r_data_tbl[i + j], 0);
+ data = RKISP1_CIF_ISP_LSC_TABLE_DATA(pconfig->r_data_tbl[i][j], 0);
rkisp1_write(params->rkisp1, data,
RKISP1_CIF_ISP_LSC_R_TABLE_DATA);
- data = RKISP1_CIF_ISP_LSC_TABLE_DATA(pconfig->gr_data_tbl[i + j], 0);
+ data = RKISP1_CIF_ISP_LSC_TABLE_DATA(pconfig->gr_data_tbl[i][j], 0);
rkisp1_write(params->rkisp1, data,
RKISP1_CIF_ISP_LSC_GR_TABLE_DATA);
- data = RKISP1_CIF_ISP_LSC_TABLE_DATA(pconfig->gb_data_tbl[i + j], 0);
+ data = RKISP1_CIF_ISP_LSC_TABLE_DATA(pconfig->gb_data_tbl[i][j], 0);
rkisp1_write(params->rkisp1, data,
RKISP1_CIF_ISP_LSC_GB_TABLE_DATA);
- data = RKISP1_CIF_ISP_LSC_TABLE_DATA(pconfig->b_data_tbl[i + j], 0);
+ data = RKISP1_CIF_ISP_LSC_TABLE_DATA(pconfig->b_data_tbl[i][j], 0);
rkisp1_write(params->rkisp1, data,
RKISP1_CIF_ISP_LSC_B_TABLE_DATA);
}
@@ -269,7 +267,7 @@ static void rkisp1_lsc_config(struct rkisp1_params *params,
RKISP1_CIF_ISP_LSC_CTRL_ENA);
rkisp1_lsc_correct_matrix_config(params, arg);
- for (i = 0; i < 4; i++) {
+ for (i = 0; i < RKISP1_CIF_ISP_LSC_SECTORS_TBL_SIZE / 2; i++) {
/* program x size tables */
data = RKISP1_CIF_ISP_LSC_SECT_SIZE(arg->x_size_tbl[i * 2],
arg->x_size_tbl[i * 2 + 1]);
@@ -402,21 +400,15 @@ static void rkisp1_goc_config(struct rkisp1_params *params,
static void rkisp1_ctk_config(struct rkisp1_params *params,
const struct rkisp1_cif_isp_ctk_config *arg)
{
- rkisp1_write(params->rkisp1, arg->coeff0, RKISP1_CIF_ISP_CT_COEFF_0);
- rkisp1_write(params->rkisp1, arg->coeff1, RKISP1_CIF_ISP_CT_COEFF_1);
- rkisp1_write(params->rkisp1, arg->coeff2, RKISP1_CIF_ISP_CT_COEFF_2);
- rkisp1_write(params->rkisp1, arg->coeff3, RKISP1_CIF_ISP_CT_COEFF_3);
- rkisp1_write(params->rkisp1, arg->coeff4, RKISP1_CIF_ISP_CT_COEFF_4);
- rkisp1_write(params->rkisp1, arg->coeff5, RKISP1_CIF_ISP_CT_COEFF_5);
- rkisp1_write(params->rkisp1, arg->coeff6, RKISP1_CIF_ISP_CT_COEFF_6);
- rkisp1_write(params->rkisp1, arg->coeff7, RKISP1_CIF_ISP_CT_COEFF_7);
- rkisp1_write(params->rkisp1, arg->coeff8, RKISP1_CIF_ISP_CT_COEFF_8);
- rkisp1_write(params->rkisp1, arg->ct_offset_r,
- RKISP1_CIF_ISP_CT_OFFSET_R);
- rkisp1_write(params->rkisp1, arg->ct_offset_g,
- RKISP1_CIF_ISP_CT_OFFSET_G);
- rkisp1_write(params->rkisp1, arg->ct_offset_b,
- RKISP1_CIF_ISP_CT_OFFSET_B);
+ unsigned int i, j, k = 0;
+
+ for (i = 0; i < 3; i++)
+ for (j = 0; j < 3; j++)
+ rkisp1_write(params->rkisp1, arg->coeff[i][j],
+ RKISP1_CIF_ISP_CT_COEFF_0 + 4 * k++);
+ for (i = 0; i < 3; i++)
+ rkisp1_write(params->rkisp1, arg->ct_offset[i],
+ RKISP1_CIF_ISP_CT_OFFSET_R + i * 4);
}
static void rkisp1_ctk_enable(struct rkisp1_params *params, bool en)
@@ -560,7 +552,7 @@ static void rkisp1_cproc_config(struct rkisp1_params *params,
const struct rkisp1_cif_isp_cproc_config *arg)
{
struct rkisp1_cif_isp_isp_other_cfg *cur_other_cfg =
- &params->cur_params.others;
+ container_of(arg, struct rkisp1_cif_isp_isp_other_cfg, cproc_config);
struct rkisp1_cif_isp_ie_config *cur_ie_config =
&cur_other_cfg->ie_config;
u32 effect = cur_ie_config->effect;
@@ -1193,48 +1185,52 @@ static void rkisp1_isp_isr_meas_config(struct rkisp1_params *params,
}
}
-void rkisp1_params_isr(struct rkisp1_device *rkisp1, u32 isp_mis)
+static void rkisp1_params_apply_params_cfg(struct rkisp1_params *params,
+ unsigned int frame_sequence)
{
- unsigned int frame_sequence = atomic_read(&rkisp1->isp.frame_sequence);
- struct rkisp1_params *params = &rkisp1->params;
struct rkisp1_params_cfg *new_params;
struct rkisp1_buffer *cur_buf = NULL;
- spin_lock(&params->config_lock);
- if (!params->is_streaming) {
- spin_unlock(&params->config_lock);
+ if (list_empty(&params->params))
return;
- }
- /* get one empty buffer */
- if (!list_empty(&params->params))
- cur_buf = list_first_entry(&params->params,
- struct rkisp1_buffer, queue);
- spin_unlock(&params->config_lock);
+ cur_buf = list_first_entry(&params->params,
+ struct rkisp1_buffer, queue);
- if (!cur_buf)
- return;
+ new_params = (struct rkisp1_params_cfg *)(cur_buf->vaddr);
- new_params = (struct rkisp1_params_cfg *)(cur_buf->vaddr[0]);
+ rkisp1_isp_isr_other_config(params, new_params);
+ rkisp1_isp_isr_meas_config(params, new_params);
- if (isp_mis & RKISP1_CIF_ISP_FRAME) {
- u32 isp_ctrl;
+ /* update shadow register immediately */
+ rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL, RKISP1_CIF_ISP_CTRL_ISP_CFG_UPD);
- rkisp1_isp_isr_other_config(params, new_params);
- rkisp1_isp_isr_meas_config(params, new_params);
+ list_del(&cur_buf->queue);
- /* update shadow register immediately */
- isp_ctrl = rkisp1_read(params->rkisp1, RKISP1_CIF_ISP_CTRL);
- isp_ctrl |= RKISP1_CIF_ISP_CTRL_ISP_CFG_UPD;
- rkisp1_write(params->rkisp1, isp_ctrl, RKISP1_CIF_ISP_CTRL);
+ cur_buf->vb.sequence = frame_sequence;
+ vb2_buffer_done(&cur_buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
+}
- spin_lock(&params->config_lock);
- list_del(&cur_buf->queue);
- spin_unlock(&params->config_lock);
+void rkisp1_params_isr(struct rkisp1_device *rkisp1)
+{
+ /*
+ * This isr is called when the ISR finishes processing a frame (RKISP1_CIF_ISP_FRAME).
+ * Configurations performed here will be applied on the next frame.
+ * Since frame_sequence is updated on the vertical sync signal, we should use
+ * frame_sequence + 1 here to indicate to userspace on which frame these parameters
+ * are being applied.
+ */
+ unsigned int frame_sequence = rkisp1->isp.frame_sequence + 1;
+ struct rkisp1_params *params = &rkisp1->params;
- cur_buf->vb.sequence = frame_sequence;
- vb2_buffer_done(&cur_buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
+ spin_lock(&params->config_lock);
+ if (!params->is_streaming) {
+ spin_unlock(&params->config_lock);
+ return;
}
+ rkisp1_params_apply_params_cfg(params, frame_sequence);
+
+ spin_unlock(&params->config_lock);
}
static const struct rkisp1_cif_isp_awb_meas_config rkisp1_awb_params_default_config = {
@@ -1280,8 +1276,6 @@ static void rkisp1_params_config_parameter(struct rkisp1_params *params)
{
struct rkisp1_cif_isp_hst_config hst = rkisp1_hst_params_default_config;
- spin_lock(&params->config_lock);
-
rkisp1_awb_meas_config(params, &rkisp1_awb_params_default_config);
rkisp1_awb_meas_enable(params, &rkisp1_awb_params_default_config,
true);
@@ -1306,14 +1300,15 @@ static void rkisp1_params_config_parameter(struct rkisp1_params *params)
else
rkisp1_csm_config(params, false);
- /* override the default things */
- rkisp1_isp_isr_other_config(params, &params->cur_params);
- rkisp1_isp_isr_meas_config(params, &params->cur_params);
+ spin_lock_irq(&params->config_lock);
- spin_unlock(&params->config_lock);
+ /* apply the first buffer if there is one already */
+ if (params->is_streaming)
+ rkisp1_params_apply_params_cfg(params, 0);
+
+ spin_unlock_irq(&params->config_lock);
}
-/* Not called when the camera active, thus not isr protection. */
void rkisp1_params_configure(struct rkisp1_params *params,
enum rkisp1_fmt_raw_pat_type bayer_pat,
enum v4l2_quantization quantization)
@@ -1436,8 +1431,6 @@ static int rkisp1_params_vb2_queue_setup(struct vb2_queue *vq,
sizes[0] = sizeof(struct rkisp1_params_cfg);
INIT_LIST_HEAD(&params->params);
- params->is_first_params = true;
-
return 0;
}
@@ -1448,25 +1441,11 @@ static void rkisp1_params_vb2_buf_queue(struct vb2_buffer *vb)
container_of(vbuf, struct rkisp1_buffer, vb);
struct vb2_queue *vq = vb->vb2_queue;
struct rkisp1_params *params = vq->drv_priv;
- struct rkisp1_params_cfg *new_params;
- unsigned long flags;
- unsigned int frame_sequence =
- atomic_read(&params->rkisp1->isp.frame_sequence);
-
- if (params->is_first_params) {
- new_params = (struct rkisp1_params_cfg *)
- (vb2_plane_vaddr(vb, 0));
- vbuf->sequence = frame_sequence;
- vb2_buffer_done(&params_buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
- params->is_first_params = false;
- params->cur_params = *new_params;
- return;
- }
- params_buf->vaddr[0] = vb2_plane_vaddr(vb, 0);
- spin_lock_irqsave(&params->config_lock, flags);
+ params_buf->vaddr = vb2_plane_vaddr(vb, 0);
+ spin_lock_irq(&params->config_lock);
list_add_tail(&params_buf->queue, &params->params);
- spin_unlock_irqrestore(&params->config_lock, flags);
+ spin_unlock_irq(&params->config_lock);
}
static int rkisp1_params_vb2_buf_prepare(struct vb2_buffer *vb)
@@ -1483,43 +1462,32 @@ static void rkisp1_params_vb2_stop_streaming(struct vb2_queue *vq)
{
struct rkisp1_params *params = vq->drv_priv;
struct rkisp1_buffer *buf;
- unsigned long flags;
- unsigned int i;
+ struct list_head tmp_list;
+
+ INIT_LIST_HEAD(&tmp_list);
- /* stop params input firstly */
- spin_lock_irqsave(&params->config_lock, flags);
+ /*
+ * we first move the buffers into a local list 'tmp_list'
+ * and then we can iterate it and call vb2_buffer_done
+ * without holding the lock
+ */
+ spin_lock_irq(&params->config_lock);
params->is_streaming = false;
- spin_unlock_irqrestore(&params->config_lock, flags);
-
- for (i = 0; i < RKISP1_ISP_PARAMS_REQ_BUFS_MAX; i++) {
- spin_lock_irqsave(&params->config_lock, flags);
- if (!list_empty(&params->params)) {
- buf = list_first_entry(&params->params,
- struct rkisp1_buffer, queue);
- list_del(&buf->queue);
- spin_unlock_irqrestore(&params->config_lock,
- flags);
- } else {
- spin_unlock_irqrestore(&params->config_lock,
- flags);
- break;
- }
+ list_cut_position(&tmp_list, &params->params, params->params.prev);
+ spin_unlock_irq(&params->config_lock);
- if (buf)
- vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
- buf = NULL;
- }
+ list_for_each_entry(buf, &tmp_list, queue)
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
}
static int
rkisp1_params_vb2_start_streaming(struct vb2_queue *queue, unsigned int count)
{
struct rkisp1_params *params = queue->drv_priv;
- unsigned long flags;
- spin_lock_irqsave(&params->config_lock, flags);
+ spin_lock_irq(&params->config_lock);
params->is_streaming = true;
- spin_unlock_irqrestore(&params->config_lock, flags);
+ spin_unlock_irq(&params->config_lock);
return 0;
}
@@ -1570,10 +1538,9 @@ static void rkisp1_init_params(struct rkisp1_params *params)
sizeof(struct rkisp1_params_cfg);
}
-int rkisp1_params_register(struct rkisp1_params *params,
- struct v4l2_device *v4l2_dev,
- struct rkisp1_device *rkisp1)
+int rkisp1_params_register(struct rkisp1_device *rkisp1)
{
+ struct rkisp1_params *params = &rkisp1->params;
struct rkisp1_vdev_node *node = &params->vnode;
struct video_device *vdev = &node->vdev;
int ret;
@@ -1593,7 +1560,7 @@ int rkisp1_params_register(struct rkisp1_params *params,
* to protect all fops and v4l2 ioctls.
*/
vdev->lock = &node->vlock;
- vdev->v4l2_dev = v4l2_dev;
+ vdev->v4l2_dev = &rkisp1->v4l2_dev;
vdev->queue = &node->buf_queue;
vdev->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_META_OUTPUT;
vdev->vfl_dir = VFL_DIR_TX;
@@ -1604,7 +1571,7 @@ int rkisp1_params_register(struct rkisp1_params *params,
node->pad.flags = MEDIA_PAD_FL_SOURCE;
ret = media_entity_pads_init(&vdev->entity, 1, &node->pad);
if (ret)
- goto err_release_queue;
+ return ret;
ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1);
if (ret) {
dev_err(rkisp1->dev,
@@ -1614,17 +1581,15 @@ int rkisp1_params_register(struct rkisp1_params *params,
return 0;
err_cleanup_media_entity:
media_entity_cleanup(&vdev->entity);
-err_release_queue:
- vb2_queue_release(vdev->queue);
return ret;
}
-void rkisp1_params_unregister(struct rkisp1_params *params)
+void rkisp1_params_unregister(struct rkisp1_device *rkisp1)
{
+ struct rkisp1_params *params = &rkisp1->params;
struct rkisp1_vdev_node *node = &params->vnode;
struct video_device *vdev = &node->vdev;
- video_unregister_device(vdev);
+ vb2_video_unregister_device(vdev);
media_entity_cleanup(&vdev->entity);
- vb2_queue_release(vdev->queue);
}
diff --git a/drivers/staging/media/rkisp1/rkisp1-regs.h b/drivers/staging/media/rkisp1/rkisp1-regs.h
index 9b8e616ea24c..049f6c3a11df 100644
--- a/drivers/staging/media/rkisp1/rkisp1-regs.h
+++ b/drivers/staging/media/rkisp1/rkisp1-regs.h
@@ -475,7 +475,6 @@
#define RKISP1_CIF_ISP_LSC_SECT_SIZE_RESERVED 0xFC00FC00
#define RKISP1_CIF_ISP_LSC_GRAD_RESERVED 0xF000F000
#define RKISP1_CIF_ISP_LSC_SAMPLE_RESERVED 0xF000F000
-#define RKISP1_CIF_ISP_LSC_SECTORS_MAX 17
#define RKISP1_CIF_ISP_LSC_TABLE_DATA(v0, v1) \
(((v0) & 0xFFF) | (((v1) & 0xFFF) << 12))
#define RKISP1_CIF_ISP_LSC_SECT_SIZE(v0, v1) \
diff --git a/drivers/staging/media/rkisp1/rkisp1-resizer.c b/drivers/staging/media/rkisp1/rkisp1-resizer.c
index c66d2a52fd71..1687d82e6c68 100644
--- a/drivers/staging/media/rkisp1/rkisp1-resizer.c
+++ b/drivers/staging/media/rkisp1/rkisp1-resizer.c
@@ -16,8 +16,36 @@
#define RKISP1_DEF_FMT MEDIA_BUS_FMT_YUYV8_2X8
#define RKISP1_DEF_PIXEL_ENC V4L2_PIXEL_ENC_YUV
-#define RKISP1_MBUS_FMT_HDIV 2
-#define RKISP1_MBUS_FMT_VDIV 1
+struct rkisp1_rsz_yuv_mbus_info {
+ u32 mbus_code;
+ u32 hdiv;
+ u32 vdiv;
+};
+
+static const struct rkisp1_rsz_yuv_mbus_info rkisp1_rsz_yuv_src_formats[] = {
+ {
+ .mbus_code = MEDIA_BUS_FMT_YUYV8_2X8, /* YUV422 */
+ .hdiv = 2,
+ .vdiv = 1,
+ },
+ {
+ .mbus_code = MEDIA_BUS_FMT_YUYV8_1_5X8, /* YUV420 */
+ .hdiv = 2,
+ .vdiv = 2,
+ },
+};
+
+static const struct rkisp1_rsz_yuv_mbus_info *rkisp1_rsz_get_yuv_mbus_info(u32 mbus_code)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(rkisp1_rsz_yuv_src_formats); i++) {
+ if (rkisp1_rsz_yuv_src_formats[i].mbus_code == mbus_code)
+ return &rkisp1_rsz_yuv_src_formats[i];
+ }
+
+ return NULL;
+}
enum rkisp1_shadow_regs_when {
RKISP1_SHADOW_REGS_SYNC,
@@ -361,16 +389,19 @@ static void rkisp1_rsz_config_regs(struct rkisp1_resizer *rsz,
static void rkisp1_rsz_config(struct rkisp1_resizer *rsz,
enum rkisp1_shadow_regs_when when)
{
- u8 hdiv = RKISP1_MBUS_FMT_HDIV, vdiv = RKISP1_MBUS_FMT_VDIV;
+ const struct rkisp1_rsz_yuv_mbus_info *sink_yuv_info, *src_yuv_info;
struct v4l2_rect sink_y, sink_c, src_y, src_c;
- struct v4l2_mbus_framefmt *src_fmt;
+ struct v4l2_mbus_framefmt *src_fmt, *sink_fmt;
struct v4l2_rect *sink_crop;
- struct rkisp1_capture *cap = &rsz->rkisp1->capture_devs[rsz->id];
sink_crop = rkisp1_rsz_get_pad_crop(rsz, NULL, RKISP1_RSZ_PAD_SINK,
V4L2_SUBDEV_FORMAT_ACTIVE);
src_fmt = rkisp1_rsz_get_pad_fmt(rsz, NULL, RKISP1_RSZ_PAD_SRC,
V4L2_SUBDEV_FORMAT_ACTIVE);
+ src_yuv_info = rkisp1_rsz_get_yuv_mbus_info(src_fmt->code);
+ sink_fmt = rkisp1_rsz_get_pad_fmt(rsz, NULL, RKISP1_RSZ_PAD_SINK,
+ V4L2_SUBDEV_FORMAT_ACTIVE);
+ sink_yuv_info = rkisp1_rsz_get_yuv_mbus_info(sink_fmt->code);
/*
* The resizer only works on yuv formats,
@@ -386,25 +417,17 @@ static void rkisp1_rsz_config(struct rkisp1_resizer *rsz,
src_y.width = src_fmt->width;
src_y.height = src_fmt->height;
- sink_c.width = sink_y.width / RKISP1_MBUS_FMT_HDIV;
- sink_c.height = sink_y.height / RKISP1_MBUS_FMT_VDIV;
+ sink_c.width = sink_y.width / sink_yuv_info->hdiv;
+ sink_c.height = sink_y.height / sink_yuv_info->vdiv;
/*
* The resizer is used not only to change the dimensions of the frame
* but also to change the scale for YUV formats,
* (4:2:2 -> 4:2:0 for example). So the width/height of the CbCr
- * streams should be set according to the pixel format in the capture.
- * The resizer always gets the input as YUV422. If the capture format
- * is RGB then the memory input should be YUV422 so we don't change the
- * default hdiv, vdiv in that case.
+ * streams should be set according to the media bus format in the src pad.
*/
- if (v4l2_is_format_yuv(cap->pix.info)) {
- hdiv = cap->pix.info->hdiv;
- vdiv = cap->pix.info->vdiv;
- }
-
- src_c.width = src_y.width / hdiv;
- src_c.height = src_y.height / vdiv;
+ src_c.width = src_y.width / src_yuv_info->hdiv;
+ src_c.height = src_y.height / src_yuv_info->vdiv;
if (sink_c.width == src_c.width && sink_c.height == src_c.height) {
rkisp1_rsz_disable(rsz, when);
@@ -437,13 +460,32 @@ static int rkisp1_rsz_enum_mbus_code(struct v4l2_subdev *sd,
u32 pad = code->pad;
int ret;
- /* supported mbus codes are the same in isp video src pad */
+ if (code->pad == RKISP1_RSZ_PAD_SRC) {
+ /* supported mbus codes on the src are the same as in the capture */
+ struct rkisp1_capture *cap = &rsz->rkisp1->capture_devs[rsz->id];
+
+ return rkisp1_cap_enum_mbus_codes(cap, code);
+ }
+
+ /*
+ * The selfpath capture doesn't support bayer formats. Therefore the selfpath resizer
+ * should support only YUV422 on the sink pad
+ */
+ if (rsz->id == RKISP1_SELFPATH) {
+ if (code->index > 0)
+ return -EINVAL;
+ code->code = MEDIA_BUS_FMT_YUYV8_2X8;
+ return 0;
+ }
+
+ /* supported mbus codes on the sink pad are the same as isp src pad */
code->pad = RKISP1_ISP_PAD_SOURCE_VIDEO;
ret = v4l2_subdev_call(&rsz->rkisp1->isp.sd, pad, enum_mbus_code,
&dummy_cfg, code);
/* restore pad */
code->pad = pad;
+ code->flags = 0;
return ret;
}
@@ -478,9 +520,17 @@ static void rkisp1_rsz_set_src_fmt(struct rkisp1_resizer *rsz,
struct v4l2_mbus_framefmt *format,
unsigned int which)
{
+ const struct rkisp1_isp_mbus_info *mbus_info;
struct v4l2_mbus_framefmt *src_fmt;
src_fmt = rkisp1_rsz_get_pad_fmt(rsz, cfg, RKISP1_RSZ_PAD_SRC, which);
+ mbus_info = rkisp1_isp_mbus_info_get(src_fmt->code);
+
+ /* for YUV formats, userspace can change the mbus code on the src pad if it is supported */
+ if (mbus_info->pixel_enc == V4L2_PIXEL_ENC_YUV &&
+ rkisp1_rsz_get_yuv_mbus_info(format->code))
+ src_fmt->code = format->code;
+
src_fmt->width = clamp_t(u32, format->width,
rsz->config->min_rsz_width,
rsz->config->max_rsz_width);
@@ -540,7 +590,11 @@ static void rkisp1_rsz_set_sink_fmt(struct rkisp1_resizer *rsz,
src_fmt = rkisp1_rsz_get_pad_fmt(rsz, cfg, RKISP1_RSZ_PAD_SRC, which);
sink_crop = rkisp1_rsz_get_pad_crop(rsz, cfg, RKISP1_RSZ_PAD_SINK,
which);
- sink_fmt->code = format->code;
+ if (rsz->id == RKISP1_SELFPATH)
+ sink_fmt->code = MEDIA_BUS_FMT_YUYV8_2X8;
+ else
+ sink_fmt->code = format->code;
+
mbus_info = rkisp1_isp_mbus_info_get(sink_fmt->code);
if (!mbus_info || !(mbus_info->direction & RKISP1_ISP_SD_SRC)) {
sink_fmt->code = RKISP1_DEF_FMT;
diff --git a/drivers/staging/media/rkisp1/rkisp1-stats.c b/drivers/staging/media/rkisp1/rkisp1-stats.c
index 87e4104d20dd..51c64f75fe29 100644
--- a/drivers/staging/media/rkisp1/rkisp1-stats.c
+++ b/drivers/staging/media/rkisp1/rkisp1-stats.c
@@ -116,7 +116,7 @@ static void rkisp1_stats_vb2_buf_queue(struct vb2_buffer *vb)
struct vb2_queue *vq = vb->vb2_queue;
struct rkisp1_stats *stats_dev = vq->drv_priv;
- stats_buf->vaddr[0] = vb2_plane_vaddr(vb, 0);
+ stats_buf->vaddr = vb2_plane_vaddr(vb, 0);
spin_lock_irq(&stats_dev->lock);
list_add_tail(&stats_buf->queue, &stats_dev->stat);
@@ -157,7 +157,9 @@ rkisp1_stats_vb2_start_streaming(struct vb2_queue *queue, unsigned int count)
{
struct rkisp1_stats *stats = queue->drv_priv;
+ spin_lock_irq(&stats->lock);
stats->is_streaming = true;
+ spin_unlock_irq(&stats->lock);
return 0;
}
@@ -231,7 +233,7 @@ static void rkisp1_stats_get_afc_meas(struct rkisp1_stats *stats,
struct rkisp1_device *rkisp1 = stats->rkisp1;
struct rkisp1_cif_isp_af_stat *af;
- pbuf->meas_type |= RKISP1_CIF_ISP_STAT_AFM_FIN;
+ pbuf->meas_type |= RKISP1_CIF_ISP_STAT_AFM;
af = &pbuf->params.af;
af->window[0].sum = rkisp1_read(rkisp1, RKISP1_CIF_ISP_AFM_SUM_A);
@@ -307,8 +309,7 @@ rkisp1_stats_send_measurement(struct rkisp1_stats *stats, u32 isp_ris)
{
struct rkisp1_stat_buffer *cur_stat_buf;
struct rkisp1_buffer *cur_buf = NULL;
- unsigned int frame_sequence =
- atomic_read(&stats->rkisp1->isp.frame_sequence);
+ unsigned int frame_sequence = stats->rkisp1->isp.frame_sequence;
u64 timestamp = ktime_get_ns();
/* get one empty buffer */
@@ -322,7 +323,7 @@ rkisp1_stats_send_measurement(struct rkisp1_stats *stats, u32 isp_ris)
return;
cur_stat_buf =
- (struct rkisp1_stat_buffer *)(cur_buf->vaddr[0]);
+ (struct rkisp1_stat_buffer *)(cur_buf->vaddr);
if (isp_ris & RKISP1_CIF_ISP_AWB_DONE)
rkisp1_stats_get_awb_meas(stats, cur_stat_buf);
@@ -375,10 +376,9 @@ static void rkisp1_init_stats(struct rkisp1_stats *stats)
sizeof(struct rkisp1_stat_buffer);
}
-int rkisp1_stats_register(struct rkisp1_stats *stats,
- struct v4l2_device *v4l2_dev,
- struct rkisp1_device *rkisp1)
+int rkisp1_stats_register(struct rkisp1_device *rkisp1)
{
+ struct rkisp1_stats *stats = &rkisp1->stats;
struct rkisp1_vdev_node *node = &stats->vnode;
struct video_device *vdev = &node->vdev;
int ret;
@@ -395,7 +395,7 @@ int rkisp1_stats_register(struct rkisp1_stats *stats,
vdev->fops = &rkisp1_stats_fops;
vdev->release = video_device_release_empty;
vdev->lock = &node->vlock;
- vdev->v4l2_dev = v4l2_dev;
+ vdev->v4l2_dev = &rkisp1->v4l2_dev;
vdev->queue = &node->buf_queue;
vdev->device_caps = V4L2_CAP_META_CAPTURE | V4L2_CAP_STREAMING;
vdev->vfl_dir = VFL_DIR_RX;
@@ -406,7 +406,7 @@ int rkisp1_stats_register(struct rkisp1_stats *stats,
node->pad.flags = MEDIA_PAD_FL_SINK;
ret = media_entity_pads_init(&vdev->entity, 1, &node->pad);
if (ret)
- goto err_release_queue;
+ goto err_mutex_destroy;
ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1);
if (ret) {
@@ -419,19 +419,18 @@ int rkisp1_stats_register(struct rkisp1_stats *stats,
err_cleanup_media_entity:
media_entity_cleanup(&vdev->entity);
-err_release_queue:
- vb2_queue_release(vdev->queue);
+err_mutex_destroy:
mutex_destroy(&node->vlock);
return ret;
}
-void rkisp1_stats_unregister(struct rkisp1_stats *stats)
+void rkisp1_stats_unregister(struct rkisp1_device *rkisp1)
{
+ struct rkisp1_stats *stats = &rkisp1->stats;
struct rkisp1_vdev_node *node = &stats->vnode;
struct video_device *vdev = &node->vdev;
- video_unregister_device(vdev);
+ vb2_video_unregister_device(vdev);
media_entity_cleanup(&vdev->entity);
- vb2_queue_release(vdev->queue);
mutex_destroy(&node->vlock);
}
diff --git a/drivers/staging/media/rkisp1/uapi/rkisp1-config.h b/drivers/staging/media/rkisp1/uapi/rkisp1-config.h
index 8f9b061e5b6b..432cb6be55b4 100644
--- a/drivers/staging/media/rkisp1/uapi/rkisp1-config.h
+++ b/drivers/staging/media/rkisp1/uapi/rkisp1-config.h
@@ -4,11 +4,6 @@
* Copyright (C) 2017 Rockchip Electronics Co., Ltd.
*/
-/*
- * TODO: Improve documentation, mostly regarding abbreviation and hardware
- * specificities. Reference: "REF_01 - ISP_user_manual, Rev 2.57" (not public)
- */
-
#ifndef _UAPI_RKISP1_CONFIG_H
#define _UAPI_RKISP1_CONFIG_H
@@ -18,24 +13,42 @@
#define V4L2_META_FMT_RK_ISP1_PARAMS v4l2_fourcc('R', 'K', '1', 'P') /* Rockchip ISP1 params */
#define V4L2_META_FMT_RK_ISP1_STAT_3A v4l2_fourcc('R', 'K', '1', 'S') /* Rockchip ISP1 3A statistics */
-#define RKISP1_CIF_ISP_MODULE_DPCC BIT(0)
-#define RKISP1_CIF_ISP_MODULE_BLS BIT(1)
-#define RKISP1_CIF_ISP_MODULE_SDG BIT(2)
-#define RKISP1_CIF_ISP_MODULE_HST BIT(3)
-#define RKISP1_CIF_ISP_MODULE_LSC BIT(4)
-#define RKISP1_CIF_ISP_MODULE_AWB_GAIN BIT(5)
-#define RKISP1_CIF_ISP_MODULE_FLT BIT(6)
-#define RKISP1_CIF_ISP_MODULE_BDM BIT(7)
-#define RKISP1_CIF_ISP_MODULE_CTK BIT(8)
-#define RKISP1_CIF_ISP_MODULE_GOC BIT(9)
-#define RKISP1_CIF_ISP_MODULE_CPROC BIT(10)
-#define RKISP1_CIF_ISP_MODULE_AFC BIT(11)
-#define RKISP1_CIF_ISP_MODULE_AWB BIT(12)
-#define RKISP1_CIF_ISP_MODULE_IE BIT(13)
-#define RKISP1_CIF_ISP_MODULE_AEC BIT(14)
-#define RKISP1_CIF_ISP_MODULE_WDR BIT(15)
-#define RKISP1_CIF_ISP_MODULE_DPF BIT(16)
-#define RKISP1_CIF_ISP_MODULE_DPF_STRENGTH BIT(17)
+/* Defect Pixel Cluster Detection */
+#define RKISP1_CIF_ISP_MODULE_DPCC (1U << 0)
+/* Black Level Subtraction */
+#define RKISP1_CIF_ISP_MODULE_BLS (1U << 1)
+/* Sensor De-gamma */
+#define RKISP1_CIF_ISP_MODULE_SDG (1U << 2)
+/* Histogram */
+#define RKISP1_CIF_ISP_MODULE_HST (1U << 3)
+/* Lens Shade Control */
+#define RKISP1_CIF_ISP_MODULE_LSC (1U << 4)
+/* Auto White Balance Gain */
+#define RKISP1_CIF_ISP_MODULE_AWB_GAIN (1U << 5)
+/* Filter */
+#define RKISP1_CIF_ISP_MODULE_FLT (1U << 6)
+/* Bayer Demosaic */
+#define RKISP1_CIF_ISP_MODULE_BDM (1U << 7)
+/* Cross Talk */
+#define RKISP1_CIF_ISP_MODULE_CTK (1U << 8)
+/* Gamma Out Curve */
+#define RKISP1_CIF_ISP_MODULE_GOC (1U << 9)
+/* Color Processing */
+#define RKISP1_CIF_ISP_MODULE_CPROC (1U << 10)
+/* Auto Focus Control */
+#define RKISP1_CIF_ISP_MODULE_AFC (1U << 11)
+/* Auto White Balancing */
+#define RKISP1_CIF_ISP_MODULE_AWB (1U << 12)
+/* Image Effect */
+#define RKISP1_CIF_ISP_MODULE_IE (1U << 13)
+/* Auto Exposure Control */
+#define RKISP1_CIF_ISP_MODULE_AEC (1U << 14)
+/* Wide Dynamic Range */
+#define RKISP1_CIF_ISP_MODULE_WDR (1U << 15)
+/* Denoise Pre-Filter */
+#define RKISP1_CIF_ISP_MODULE_DPF (1U << 16)
+/* Denoise Pre-Filter Strength */
+#define RKISP1_CIF_ISP_MODULE_DPF_STRENGTH (1U << 17)
#define RKISP1_CIF_ISP_CTK_COEFF_MAX 0x100
#define RKISP1_CIF_ISP_CTK_OFFSET_MAX 0x800
@@ -82,14 +95,13 @@
/*
* Lens shade correction
*/
-#define RKISP1_CIF_ISP_LSC_GRAD_TBL_SIZE 8
-#define RKISP1_CIF_ISP_LSC_SIZE_TBL_SIZE 8
+#define RKISP1_CIF_ISP_LSC_SECTORS_TBL_SIZE 8
+
/*
* The following matches the tuning process,
* not the max capabilities of the chip.
- * Last value unused.
*/
-#define RKISP1_CIF_ISP_LSC_DATA_TBL_SIZE 290
+#define RKISP1_CIF_ISP_LSC_SAMPLES_MAX 17
/*
* Histogram calculation
@@ -111,10 +123,10 @@
/*
* Measurement types
*/
-#define RKISP1_CIF_ISP_STAT_AWB BIT(0)
-#define RKISP1_CIF_ISP_STAT_AUTOEXP BIT(1)
-#define RKISP1_CIF_ISP_STAT_AFM_FIN BIT(2)
-#define RKISP1_CIF_ISP_STAT_HIST BIT(3)
+#define RKISP1_CIF_ISP_STAT_AWB (1U << 0)
+#define RKISP1_CIF_ISP_STAT_AUTOEXP (1U << 1)
+#define RKISP1_CIF_ISP_STAT_AFM (1U << 2)
+#define RKISP1_CIF_ISP_STAT_HIST (1U << 3)
enum rkisp1_cif_isp_histogram_mode {
RKISP1_CIF_ISP_HISTOGRAM_MODE_DISABLE,
@@ -158,12 +170,23 @@ enum rkisp1_cif_isp_exp_meas_mode {
/*---------- PART1: Input Parameters ------------*/
+/**
+ * struct rkisp1_cif_isp_window - measurement window.
+ *
+ * Measurements are calculated per window inside the frame.
+ * This struct represents a window for a measurement.
+ *
+ * @h_offs: the horizontal offset of the window from the left of the frame in pixels.
+ * @v_offs: the vertical offset of the window from the top of the frame in pixels.
+ * @h_size: the horizontal size of the window in pixels
+ * @v_size: the vertical size of the window in pixels.
+ */
struct rkisp1_cif_isp_window {
__u16 h_offs;
__u16 v_offs;
__u16 h_size;
__u16 v_size;
-} __packed;
+};
/**
* struct rkisp1_cif_isp_bls_fixed_val - BLS fixed subtraction values
@@ -181,7 +204,7 @@ struct rkisp1_cif_isp_bls_fixed_val {
__s16 gr;
__s16 gb;
__s16 b;
-} __packed;
+};
/**
* struct rkisp1_cif_isp_bls_config - Configuration used by black level subtraction
@@ -203,7 +226,7 @@ struct rkisp1_cif_isp_bls_config {
struct rkisp1_cif_isp_window bls_window2;
__u8 bls_samples;
struct rkisp1_cif_isp_bls_fixed_val fixed_val;
-} __packed;
+};
/**
* struct rkisp1_cif_isp_dpcc_methods_config - Methods Configuration used by DPCC
@@ -224,7 +247,7 @@ struct rkisp1_cif_isp_dpcc_methods_config {
__u32 pg_fac;
__u32 rnd_thresh;
__u32 rg_fac;
-} __packed;
+};
/**
* struct rkisp1_cif_isp_dpcc_config - Configuration used by DPCC
@@ -245,53 +268,88 @@ struct rkisp1_cif_isp_dpcc_config {
struct rkisp1_cif_isp_dpcc_methods_config methods[RKISP1_CIF_ISP_DPCC_METHODS_MAX];
__u32 ro_limits;
__u32 rnd_offs;
-} __packed;
+};
+/**
+ * struct rkisp1_cif_isp_gamma_corr_curve - gamma curve point definition y-axis (output).
+ *
+ * The reset values define a linear curve which has the same effect as bypass. Reset values are:
+ * gamma_y[0] = 0x0000, gamma_y[1] = 0x0100, ... gamma_y[15] = 0x0f00, gamma_y[16] = 0xfff
+ *
+ * @gamma_y: the values for the y-axis of gamma curve points. Each value is 12 bit.
+ */
struct rkisp1_cif_isp_gamma_corr_curve {
__u16 gamma_y[RKISP1_CIF_ISP_DEGAMMA_CURVE_SIZE];
-} __packed;
+};
+/**
+ * struct rkisp1_cif_isp_gamma_curve_x_axis_pnts - De-Gamma Curve definition x increments
+ * (sampling points). gamma_dx0 is for the lower samples (1-8), gamma_dx1 is for the
+ * higher samples (9-16). The reset values for both fields is 0x44444444. This means
+ * that each sample is 4 units away from the previous one on the x-axis.
+ *
+ * @gamma_dx0: gamma curve sample points definitions. Bits 0:2 for sample 1. Bit 3 unused.
+ * Bits 4:6 for sample 2. bit 7 unused ... Bits 28:30 for sample 8. Bit 31 unused
+ * @gamma_dx1: gamma curve sample points definitions. Bits 0:2 for sample 9. Bit 3 unused.
+ * Bits 4:6 for sample 10. bit 7 unused ... Bits 28:30 for sample 16. Bit 31 unused
+ */
struct rkisp1_cif_isp_gamma_curve_x_axis_pnts {
__u32 gamma_dx0;
__u32 gamma_dx1;
-} __packed;
+};
/**
* struct rkisp1_cif_isp_sdg_config - Configuration used by sensor degamma
*
- * @curve_x: gamma curve point definition axis for x
- * @xa_pnts: x increments
+ * @curve_r: gamma curve point definition axis for red
+ * @curve_g: gamma curve point definition axis for green
+ * @curve_b: gamma curve point definition axis for blue
+ * @xa_pnts: x axis increments
*/
struct rkisp1_cif_isp_sdg_config {
struct rkisp1_cif_isp_gamma_corr_curve curve_r;
struct rkisp1_cif_isp_gamma_corr_curve curve_g;
struct rkisp1_cif_isp_gamma_corr_curve curve_b;
struct rkisp1_cif_isp_gamma_curve_x_axis_pnts xa_pnts;
-} __packed;
+};
/**
* struct rkisp1_cif_isp_lsc_config - Configuration used by Lens shading correction
*
- * refer to REF_01 for details
+ * @r_data_tbl: sample table red
+ * @gr_data_tbl: sample table green (red)
+ * @gb_data_tbl: sample table green (blue)
+ * @b_data_tbl: sample table blue
+ * @x_grad_tbl: gradient table x
+ * @y_grad_tbl: gradient table y
+ * @x_size_tbl: size table x
+ * @y_size_tbl: size table y
+ * @config_width: not used at the moment
+ * @config_height: not used at the moment
*/
struct rkisp1_cif_isp_lsc_config {
- __u32 r_data_tbl[RKISP1_CIF_ISP_LSC_DATA_TBL_SIZE];
- __u32 gr_data_tbl[RKISP1_CIF_ISP_LSC_DATA_TBL_SIZE];
- __u32 gb_data_tbl[RKISP1_CIF_ISP_LSC_DATA_TBL_SIZE];
- __u32 b_data_tbl[RKISP1_CIF_ISP_LSC_DATA_TBL_SIZE];
+ __u16 r_data_tbl[RKISP1_CIF_ISP_LSC_SAMPLES_MAX][RKISP1_CIF_ISP_LSC_SAMPLES_MAX];
+ __u16 gr_data_tbl[RKISP1_CIF_ISP_LSC_SAMPLES_MAX][RKISP1_CIF_ISP_LSC_SAMPLES_MAX];
+ __u16 gb_data_tbl[RKISP1_CIF_ISP_LSC_SAMPLES_MAX][RKISP1_CIF_ISP_LSC_SAMPLES_MAX];
+ __u16 b_data_tbl[RKISP1_CIF_ISP_LSC_SAMPLES_MAX][RKISP1_CIF_ISP_LSC_SAMPLES_MAX];
- __u32 x_grad_tbl[RKISP1_CIF_ISP_LSC_GRAD_TBL_SIZE];
- __u32 y_grad_tbl[RKISP1_CIF_ISP_LSC_GRAD_TBL_SIZE];
+ __u16 x_grad_tbl[RKISP1_CIF_ISP_LSC_SECTORS_TBL_SIZE];
+ __u16 y_grad_tbl[RKISP1_CIF_ISP_LSC_SECTORS_TBL_SIZE];
- __u32 x_size_tbl[RKISP1_CIF_ISP_LSC_SIZE_TBL_SIZE];
- __u32 y_size_tbl[RKISP1_CIF_ISP_LSC_SIZE_TBL_SIZE];
+ __u16 x_size_tbl[RKISP1_CIF_ISP_LSC_SECTORS_TBL_SIZE];
+ __u16 y_size_tbl[RKISP1_CIF_ISP_LSC_SECTORS_TBL_SIZE];
__u16 config_width;
__u16 config_height;
-} __packed;
+};
/**
* struct rkisp1_cif_isp_ie_config - Configuration used by image effects
*
+ * @effect: values from 'enum v4l2_colorfx'. Possible values are: V4L2_COLORFX_SEPIA,
+ * V4L2_COLORFX_SET_CBCR, V4L2_COLORFX_AQUA, V4L2_COLORFX_EMBOSS,
+ * V4L2_COLORFX_SKETCH, V4L2_COLORFX_BW, V4L2_COLORFX_NEGATIVE
+ * @color_sel: bits 0:2 - colors bitmask (001 - blue, 010 - green, 100 - red).
+ * bits 8:15 - Threshold value of the RGB colors for the color selection effect.
* @eff_mat_1: 3x3 Matrix Coefficients for Emboss Effect 1
* @eff_mat_2: 3x3 Matrix Coefficients for Emboss Effect 2
* @eff_mat_3: 3x3 Matrix Coefficients for Emboss 3/Sketch 1
@@ -308,7 +366,7 @@ struct rkisp1_cif_isp_ie_config {
__u16 eff_mat_4;
__u16 eff_mat_5;
__u16 eff_tint;
-} __packed;
+};
/**
* struct rkisp1_cif_isp_cproc_config - Configuration used by Color Processing
@@ -330,13 +388,13 @@ struct rkisp1_cif_isp_cproc_config {
__u8 brightness;
__u8 sat;
__u8 hue;
-} __packed;
+};
/**
* struct rkisp1_cif_isp_awb_meas_config - Configuration used by auto white balance
*
+ * @awb_mode: the awb meas mode. From enum rkisp1_cif_isp_awb_mode_type.
* @awb_wnd: white balance measurement window (in pixels)
- * (from enum rkisp1_cif_isp_awb_mode_type)
* @max_y: only pixels values < max_y contribute to awb measurement, set to 0
* to disable this feature
* @min_y: only pixels values > min_y contribute to awb measurement
@@ -348,6 +406,7 @@ struct rkisp1_cif_isp_cproc_config {
* (ucFrames=0 means 1 Frame)
* @awb_ref_cr: reference Cr value for AWB regulation, target for AWB
* @awb_ref_cb: reference Cb value for AWB regulation, target for AWB
+ * @enable_ymax_cmp: enable Y_MAX compare (Not valid in RGB measurement mode.)
*/
struct rkisp1_cif_isp_awb_meas_config {
/*
@@ -363,31 +422,49 @@ struct rkisp1_cif_isp_awb_meas_config {
__u8 awb_ref_cr;
__u8 awb_ref_cb;
__u8 enable_ymax_cmp;
-} __packed;
+};
/**
* struct rkisp1_cif_isp_awb_gain_config - Configuration used by auto white balance gain
*
- * out_data_x = ( AWB_GEAIN_X * in_data + 128) >> 8
+ * All fields in this struct are 10 bit, where:
+ * 0x100h = 1, unsigned integer value, range 0 to 4 with 8 bit fractional part.
+ *
+ * out_data_x = ( AWB_GAIN_X * in_data + 128) >> 8
+ *
+ * @gain_red: gain value for red component.
+ * @gain_green_r: gain value for green component in red line.
+ * @gain_blue: gain value for blue component.
+ * @gain_green_b: gain value for green component in blue line.
*/
struct rkisp1_cif_isp_awb_gain_config {
__u16 gain_red;
__u16 gain_green_r;
__u16 gain_blue;
__u16 gain_green_b;
-} __packed;
+};
/**
* struct rkisp1_cif_isp_flt_config - Configuration used by ISP filtering
*
- * @mode: ISP_FILT_MODE register fields (from enum rkisp1_cif_isp_flt_mode)
- * @grn_stage1: ISP_FILT_MODE register fields
- * @chr_h_mode: ISP_FILT_MODE register fields
- * @chr_v_mode: ISP_FILT_MODE register fields
+ * All 4 threshold fields (thresh_*) are 10 bits.
+ * All 6 factor fields (fac_*) are 6 bits.
*
- * refer to REF_01 for details.
+ * @mode: ISP_FILT_MODE register fields (from enum rkisp1_cif_isp_flt_mode)
+ * @grn_stage1: Green filter stage 1 select (range 0x0...0x8)
+ * @chr_h_mode: Chroma filter horizontal mode
+ * @chr_v_mode: Chroma filter vertical mode
+ * @thresh_bl0: If thresh_bl1 < sum_grad < thresh_bl0 then fac_bl0 is selected (blurring th)
+ * @thresh_bl1: If sum_grad < thresh_bl1 then fac_bl1 is selected (blurring th)
+ * @thresh_sh0: If thresh_sh0 < sum_grad < thresh_sh1 then thresh_sh0 is selected (sharpening th)
+ * @thresh_sh1: If thresh_sh1 < sum_grad then thresh_sh1 is selected (sharpening th)
+ * @lum_weight: Parameters for luminance weight function.
+ * @fac_sh1: filter factor for sharp1 level
+ * @fac_sh0: filter factor for sharp0 level
+ * @fac_mid: filter factor for mid level and for static filter mode
+ * @fac_bl0: filter factor for blur 0 level
+ * @fac_bl1: filter factor for blur 1 level (max blur)
*/
-
struct rkisp1_cif_isp_flt_config {
__u32 mode;
__u8 grn_stage1;
@@ -403,7 +480,7 @@ struct rkisp1_cif_isp_flt_config {
__u32 fac_mid;
__u32 fac_bl0;
__u32 fac_bl1;
-} __packed;
+};
/**
* struct rkisp1_cif_isp_bdm_config - Configuration used by Bayer DeMosaic
@@ -412,28 +489,20 @@ struct rkisp1_cif_isp_flt_config {
*/
struct rkisp1_cif_isp_bdm_config {
__u8 demosaic_th;
-} __packed;
+};
/**
* struct rkisp1_cif_isp_ctk_config - Configuration used by Cross Talk correction
*
- * @coeff: color correction matrix
- * @ct_offset_b: offset for the crosstalk correction matrix
+ * @coeff: color correction matrix. Values are 11-bit signed fixed-point numbers with 4 bit integer
+ * and 7 bit fractional part, ranging from -8 (0x400) to +7.992 (0x3FF). 0 is
+ * represented by 0x000 and a coefficient value of 1 as 0x080.
+ * @ct_offset: Red, Green, Blue offsets for the crosstalk correction matrix
*/
struct rkisp1_cif_isp_ctk_config {
- __u16 coeff0;
- __u16 coeff1;
- __u16 coeff2;
- __u16 coeff3;
- __u16 coeff4;
- __u16 coeff5;
- __u16 coeff6;
- __u16 coeff7;
- __u16 coeff8;
- __u16 ct_offset_r;
- __u16 ct_offset_g;
- __u16 ct_offset_b;
-} __packed;
+ __u16 coeff[3][3];
+ __u16 ct_offset[3];
+};
enum rkisp1_cif_isp_goc_mode {
RKISP1_CIF_ISP_GOC_MODE_LOGARITHMIC,
@@ -449,7 +518,7 @@ enum rkisp1_cif_isp_goc_mode {
struct rkisp1_cif_isp_goc_config {
__u32 mode;
__u16 gamma_y[RKISP1_CIF_ISP_GAMMA_OUT_MAX_SAMPLES];
-} __packed;
+};
/**
* struct rkisp1_cif_isp_hst_config - Configuration used by Histogram
@@ -465,7 +534,7 @@ struct rkisp1_cif_isp_hst_config {
__u8 histogram_predivider;
struct rkisp1_cif_isp_window meas_window;
__u8 hist_weight[RKISP1_CIF_ISP_HISTOGRAM_WEIGHT_GRIDS_SIZE];
-} __packed;
+};
/**
* struct rkisp1_cif_isp_aec_config - Configuration used by Auto Exposure Control
@@ -478,7 +547,7 @@ struct rkisp1_cif_isp_aec_config {
__u32 mode;
__u32 autostop;
struct rkisp1_cif_isp_window meas_window;
-} __packed;
+};
/**
* struct rkisp1_cif_isp_afc_config - Configuration used by Auto Focus Control
@@ -494,7 +563,7 @@ struct rkisp1_cif_isp_afc_config {
struct rkisp1_cif_isp_window afm_win[RKISP1_CIF_ISP_AFM_MAX_WINDOWS];
__u32 thres;
__u32 var_shift;
-} __packed;
+};
/**
* enum rkisp1_cif_isp_dpf_gain_usage - dpf gain usage
@@ -549,7 +618,7 @@ enum rkisp1_cif_isp_dpf_nll_scale_mode {
struct rkisp1_cif_isp_dpf_nll {
__u16 coeff[RKISP1_CIF_ISP_DPF_MAX_NLF_COEFFS];
__u32 scale_mode;
-} __packed;
+};
/**
* struct rkisp1_cif_isp_dpf_rb_flt - Red blue filter config
@@ -565,7 +634,7 @@ struct rkisp1_cif_isp_dpf_rb_flt {
__u8 spatial_coeff[RKISP1_CIF_ISP_DPF_MAX_SPATIAL_COEFFS];
__u8 r_enable;
__u8 b_enable;
-} __packed;
+};
/**
* struct rkisp1_cif_isp_dpf_g_flt - Green filter Configuration
@@ -578,7 +647,7 @@ struct rkisp1_cif_isp_dpf_g_flt {
__u8 spatial_coeff[RKISP1_CIF_ISP_DPF_MAX_SPATIAL_COEFFS];
__u8 gr_enable;
__u8 gb_enable;
-} __packed;
+};
/**
* struct rkisp1_cif_isp_dpf_gain - Noise function Configuration
@@ -597,7 +666,7 @@ struct rkisp1_cif_isp_dpf_gain {
__u16 nf_b_gain;
__u16 nf_gr_gain;
__u16 nf_gb_gain;
-} __packed;
+};
/**
* struct rkisp1_cif_isp_dpf_config - Configuration used by De-noising pre-filter
@@ -612,7 +681,7 @@ struct rkisp1_cif_isp_dpf_config {
struct rkisp1_cif_isp_dpf_g_flt g_flt;
struct rkisp1_cif_isp_dpf_rb_flt rb_flt;
struct rkisp1_cif_isp_dpf_nll nll;
-} __packed;
+};
/**
* struct rkisp1_cif_isp_dpf_strength_config - strength of the filter
@@ -625,7 +694,7 @@ struct rkisp1_cif_isp_dpf_strength_config {
__u8 r;
__u8 g;
__u8 b;
-} __packed;
+};
/**
* struct rkisp1_cif_isp_isp_other_cfg - Parameters for some blocks in rockchip isp1
@@ -659,7 +728,7 @@ struct rkisp1_cif_isp_isp_other_cfg {
struct rkisp1_cif_isp_dpf_strength_config dpf_strength_config;
struct rkisp1_cif_isp_cproc_config cproc_config;
struct rkisp1_cif_isp_ie_config ie_config;
-} __packed;
+};
/**
* struct rkisp1_cif_isp_isp_meas_cfg - Rockchip ISP1 Measure Parameters
@@ -674,7 +743,7 @@ struct rkisp1_cif_isp_isp_meas_cfg {
struct rkisp1_cif_isp_hst_config hst_config;
struct rkisp1_cif_isp_aec_config aec_config;
struct rkisp1_cif_isp_afc_config afc_config;
-} __packed;
+};
/**
* struct rkisp1_params_cfg - Rockchip ISP1 Input Parameters Meta Data
@@ -693,7 +762,7 @@ struct rkisp1_params_cfg {
struct rkisp1_cif_isp_isp_meas_cfg meas;
struct rkisp1_cif_isp_isp_other_cfg others;
-} __packed;
+};
/*---------- PART2: Measurement Statistics ------------*/
@@ -714,7 +783,7 @@ struct rkisp1_cif_isp_awb_meas {
__u8 mean_y_or_g;
__u8 mean_cb_or_b;
__u8 mean_cr_or_r;
-} __packed;
+};
/**
* struct rkisp1_cif_isp_awb_stat - statistics automatic white balance data
@@ -723,7 +792,7 @@ struct rkisp1_cif_isp_awb_meas {
*/
struct rkisp1_cif_isp_awb_stat {
struct rkisp1_cif_isp_awb_meas awb_mean[RKISP1_CIF_ISP_AWB_MAX_GRID];
-} __packed;
+};
/**
* struct rkisp1_cif_isp_bls_meas_val - BLS measured values
@@ -738,7 +807,7 @@ struct rkisp1_cif_isp_bls_meas_val {
__u16 meas_gr;
__u16 meas_gb;
__u16 meas_b;
-} __packed;
+};
/**
* struct rkisp1_cif_isp_ae_stat - statistics auto exposure data
@@ -751,18 +820,18 @@ struct rkisp1_cif_isp_bls_meas_val {
struct rkisp1_cif_isp_ae_stat {
__u8 exp_mean[RKISP1_CIF_ISP_AE_MEAN_MAX];
struct rkisp1_cif_isp_bls_meas_val bls_val;
-} __packed;
+};
/**
* struct rkisp1_cif_isp_af_meas_val - AF measured values
*
- * @sum: sharpness, refer to REF_01 for definition
- * @lum: luminance, refer to REF_01 for definition
+ * @sum: sharpness value
+ * @lum: luminance value
*/
struct rkisp1_cif_isp_af_meas_val {
__u32 sum;
__u32 lum;
-} __packed;
+};
/**
* struct rkisp1_cif_isp_af_stat - statistics auto focus data
@@ -774,7 +843,7 @@ struct rkisp1_cif_isp_af_meas_val {
*/
struct rkisp1_cif_isp_af_stat {
struct rkisp1_cif_isp_af_meas_val window[RKISP1_CIF_ISP_AFM_MAX_WINDOWS];
-} __packed;
+};
/**
* struct rkisp1_cif_isp_hist_stat - statistics histogram data
@@ -786,27 +855,27 @@ struct rkisp1_cif_isp_af_stat {
*/
struct rkisp1_cif_isp_hist_stat {
__u16 hist_bins[RKISP1_CIF_ISP_HIST_BIN_N_MAX];
-} __packed;
+};
/**
- * struct rkisp1_stat_buffer - Rockchip ISP1 Statistics Data
+ * struct rkisp1_cif_isp_stat - Rockchip ISP1 Statistics Data
*
- * @rkisp1_cif_isp_awb_stat: statistics data for automatic white balance
- * @rkisp1_cif_isp_ae_stat: statistics data for auto exposure
- * @rkisp1_cif_isp_af_stat: statistics data for auto focus
- * @rkisp1_cif_isp_hist_stat: statistics histogram data
+ * @awb: statistics data for automatic white balance
+ * @ae: statistics data for auto exposure
+ * @af: statistics data for auto focus
+ * @hist: statistics histogram data
*/
struct rkisp1_cif_isp_stat {
struct rkisp1_cif_isp_awb_stat awb;
struct rkisp1_cif_isp_ae_stat ae;
struct rkisp1_cif_isp_af_stat af;
struct rkisp1_cif_isp_hist_stat hist;
-} __packed;
+};
/**
* struct rkisp1_stat_buffer - Rockchip ISP1 Statistics Meta Data
*
- * @meas_type: measurement types (RKISP1_CIF_ISP_STAT_ definitions)
+ * @meas_type: measurement types (RKISP1_CIF_ISP_STAT_* definitions)
* @frame_id: frame ID for sync
* @params: statistics data
*/
@@ -814,6 +883,6 @@ struct rkisp1_stat_buffer {
__u32 meas_type;
__u32 frame_id;
struct rkisp1_cif_isp_stat params;
-} __packed;
+};
#endif /* _UAPI_RKISP1_CONFIG_H */