From 2f7c68cb55ecb7331f2381deb497c27155f32faf Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Wed, 03 Jan 2024 09:43:39 +0000
Subject: [PATCH] update kernel to 5.10.198
---
kernel/drivers/media/platform/rockchip/isp/capture.c | 1132 +++++++++++++++++++++++++++++++++++++----------------------
1 files changed, 712 insertions(+), 420 deletions(-)
diff --git a/kernel/drivers/media/platform/rockchip/isp/capture.c b/kernel/drivers/media/platform/rockchip/isp/capture.c
index 416d369..a43e6e4 100644
--- a/kernel/drivers/media/platform/rockchip/isp/capture.c
+++ b/kernel/drivers/media/platform/rockchip/isp/capture.c
@@ -11,17 +11,18 @@
#include <media/videobuf2-dma-contig.h>
#include "dev.h"
#include "regs.h"
+#include "rkisp_tb_helper.h"
#define STREAM_MAX_MP_RSZ_OUTPUT_WIDTH 4416
#define STREAM_MAX_MP_RSZ_OUTPUT_HEIGHT 3312
#define STREAM_MAX_SP_RSZ_OUTPUT_WIDTH 1920
#define STREAM_MAX_SP_RSZ_OUTPUT_HEIGHT 1080
#define STREAM_MIN_RSZ_OUTPUT_WIDTH 32
-#define STREAM_MIN_RSZ_OUTPUT_HEIGHT 16
+#define STREAM_MIN_RSZ_OUTPUT_HEIGHT 32
#define STREAM_OUTPUT_STEP_WISE 8
-#define STREAM_MIN_MP_SP_INPUT_WIDTH 32
-#define STREAM_MIN_MP_SP_INPUT_HEIGHT 32
+#define STREAM_MIN_MP_SP_INPUT_WIDTH STREAM_MIN_RSZ_OUTPUT_WIDTH
+#define STREAM_MIN_MP_SP_INPUT_HEIGHT STREAM_MIN_RSZ_OUTPUT_HEIGHT
static int hdr_dma_frame(struct rkisp_device *dev)
{
@@ -124,7 +125,7 @@
if (atomic_read(&dev->cap_dev.refcnt) > 1 ||
!dev->active_sensor ||
(dev->active_sensor &&
- dev->active_sensor->mbus.type != V4L2_MBUS_CSI2) ||
+ dev->active_sensor->mbus.type != V4L2_MBUS_CSI2_DPHY) ||
(dev->isp_inp & INP_CIF) ||
(dev->isp_ver != ISP_V20 && dev->isp_ver != ISP_V21))
return;
@@ -157,7 +158,7 @@
if (!dev->active_sensor ||
(dev->active_sensor &&
- dev->active_sensor->mbus.type != V4L2_MBUS_CSI2) ||
+ dev->active_sensor->mbus.type != V4L2_MBUS_CSI2_DPHY) ||
(dev->isp_inp & INP_CIF) ||
(dev->isp_ver != ISP_V20 && dev->isp_ver != ISP_V21))
return 0;
@@ -165,7 +166,7 @@
for (i = RKISP_STREAM_DMATX0; i <= RKISP_STREAM_DMATX2; i++) {
dmatx = &dev->cap_dev.stream[i];
if (dmatx->ops && dmatx->ops->frame_end)
- dmatx->ops->frame_end(dmatx);
+ dmatx->ops->frame_end(dmatx, FRAME_INIT);
}
if (dev->dmarx_dev.trigger)
@@ -225,7 +226,7 @@
if (atomic_inc_return(&dev->hdr.refcnt) > 1 ||
!dev->active_sensor ||
(dev->active_sensor &&
- dev->active_sensor->mbus.type != V4L2_MBUS_CSI2) ||
+ dev->active_sensor->mbus.type != V4L2_MBUS_CSI2_DPHY) ||
(dev->isp_inp & INP_CIF) ||
(dev->isp_ver != ISP_V20 && dev->isp_ver != ISP_V21))
return 0;
@@ -294,7 +295,7 @@
if (atomic_dec_return(&dev->hdr.refcnt) ||
!dev->active_sensor ||
(dev->active_sensor &&
- dev->active_sensor->mbus.type != V4L2_MBUS_CSI2) ||
+ dev->active_sensor->mbus.type != V4L2_MBUS_CSI2_DPHY) ||
(dev->isp_inp & INP_CIF) ||
(dev->isp_ver != ISP_V20 && dev->isp_ver != ISP_V21))
return;
@@ -351,7 +352,7 @@
if (!hw->dummy_buf.mem_priv ||
!dev->active_sensor ||
(dev->active_sensor &&
- dev->active_sensor->mbus.type != V4L2_MBUS_CSI2) ||
+ dev->active_sensor->mbus.type != V4L2_MBUS_CSI2_DPHY) ||
(dev->isp_inp & INP_CIF) ||
(dev->isp_ver != ISP_V20 && dev->isp_ver != ISP_V21))
return;
@@ -360,11 +361,12 @@
*/
for (i = 0; i < hw->dev_num; i++) {
isp = hw->isp[i];
- if (!(isp->isp_inp & INP_CSI))
+ if (!isp ||
+ (isp && !(isp->isp_inp & INP_CSI)))
continue;
for (j = RKISP_STREAM_DMATX0; j < RKISP_MAX_STREAM; j++) {
stream = &isp->cap_dev.stream[j];
- if (!stream->linked || stream->u.dmatx.is_config)
+ if (!stream->linked || stream->curr_buf || stream->next_buf)
continue;
mi_set_y_addr(stream, hw->dummy_buf.dma_addr);
}
@@ -392,6 +394,7 @@
case V4L2_PIX_FMT_NV16:
case V4L2_PIX_FMT_NV61:
case V4L2_PIX_FMT_YVU422M:
+ case V4L2_PIX_FMT_FBC2:
*xsubs = 2;
*ysubs = 1;
break;
@@ -402,6 +405,7 @@
case V4L2_PIX_FMT_YUV420:
case V4L2_PIX_FMT_YVU420:
case V4L2_PIX_FMT_FBCG:
+ case V4L2_PIX_FMT_FBC0:
*xsubs = 2;
*ysubs = 2;
break;
@@ -430,326 +434,48 @@
return 0;
}
-static const struct capture_fmt mp_fmts[] = {
- /* yuv422 */
- {
- .fourcc = V4L2_PIX_FMT_UYVY,
- .fmt_type = FMT_YUV,
- .bpp = { 16 },
- .cplanes = 1,
- .mplanes = 1,
- .uv_swap = 0,
- .write_format = MI_CTRL_MP_WRITE_YUVINT,
- }, {
- .fourcc = V4L2_PIX_FMT_YUV422P,
- .fmt_type = FMT_YUV,
- .bpp = { 8, 4, 4 },
- .cplanes = 3,
- .mplanes = 1,
- .uv_swap = 0,
- .write_format = MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8,
- }, {
- .fourcc = V4L2_PIX_FMT_NV16,
- .fmt_type = FMT_YUV,
- .bpp = { 8, 16 },
- .cplanes = 2,
- .mplanes = 1,
- .uv_swap = 0,
- .write_format = MI_CTRL_MP_WRITE_YUV_SPLA,
- }, {
- .fourcc = V4L2_PIX_FMT_NV61,
- .fmt_type = FMT_YUV,
- .bpp = { 8, 16 },
- .cplanes = 2,
- .mplanes = 1,
- .uv_swap = 1,
- .write_format = MI_CTRL_MP_WRITE_YUV_SPLA,
- }, {
- .fourcc = V4L2_PIX_FMT_YUV422M,
- .fmt_type = FMT_YUV,
- .bpp = { 8, 8, 8 },
- .cplanes = 3,
- .mplanes = 3,
- .uv_swap = 0,
- .write_format = MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8,
- },
- /* yuv420 */
- {
- .fourcc = V4L2_PIX_FMT_NV21,
- .fmt_type = FMT_YUV,
- .bpp = { 8, 16 },
- .cplanes = 2,
- .mplanes = 1,
- .uv_swap = 1,
- .write_format = MI_CTRL_MP_WRITE_YUV_SPLA,
- }, {
- .fourcc = V4L2_PIX_FMT_NV12,
- .fmt_type = FMT_YUV,
- .bpp = { 8, 16 },
- .cplanes = 2,
- .mplanes = 1,
- .uv_swap = 0,
- .write_format = MI_CTRL_MP_WRITE_YUV_SPLA,
- }, {
- .fourcc = V4L2_PIX_FMT_NV21M,
- .fmt_type = FMT_YUV,
- .bpp = { 8, 16 },
- .cplanes = 2,
- .mplanes = 2,
- .uv_swap = 1,
- .write_format = MI_CTRL_MP_WRITE_YUV_SPLA,
- }, {
- .fourcc = V4L2_PIX_FMT_NV12M,
- .fmt_type = FMT_YUV,
- .bpp = { 8, 16 },
- .cplanes = 2,
- .mplanes = 2,
- .uv_swap = 0,
- .write_format = MI_CTRL_MP_WRITE_YUV_SPLA,
- }, {
- .fourcc = V4L2_PIX_FMT_YUV420,
- .fmt_type = FMT_YUV,
- .bpp = { 8, 8, 8 },
- .cplanes = 3,
- .mplanes = 1,
- .uv_swap = 0,
- .write_format = MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8,
- },
- /* yuv444 */
- {
- .fourcc = V4L2_PIX_FMT_YUV444M,
- .fmt_type = FMT_YUV,
- .bpp = { 8, 8, 8 },
- .cplanes = 3,
- .mplanes = 3,
- .uv_swap = 0,
- .write_format = MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8,
- },
- /* raw */
- {
- .fourcc = V4L2_PIX_FMT_SRGGB8,
- .fmt_type = FMT_BAYER,
- .bpp = { 8 },
- .mplanes = 1,
- .write_format = MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8,
- }, {
- .fourcc = V4L2_PIX_FMT_SGRBG8,
- .fmt_type = FMT_BAYER,
- .bpp = { 8 },
- .mplanes = 1,
- .write_format = MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8,
- }, {
- .fourcc = V4L2_PIX_FMT_SGBRG8,
- .fmt_type = FMT_BAYER,
- .bpp = { 8 },
- .mplanes = 1,
- .write_format = MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8,
- }, {
- .fourcc = V4L2_PIX_FMT_SBGGR8,
- .fmt_type = FMT_BAYER,
- .bpp = { 8 },
- .mplanes = 1,
- .write_format = MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8,
- }, {
- .fourcc = V4L2_PIX_FMT_SRGGB10,
- .fmt_type = FMT_BAYER,
- .bpp = { 10 },
- .mplanes = 1,
- .write_format = MI_CTRL_MP_WRITE_RAW12,
- }, {
- .fourcc = V4L2_PIX_FMT_SGRBG10,
- .fmt_type = FMT_BAYER,
- .bpp = { 10 },
- .mplanes = 1,
- .write_format = MI_CTRL_MP_WRITE_RAW12,
- }, {
- .fourcc = V4L2_PIX_FMT_SGBRG10,
- .fmt_type = FMT_BAYER,
- .bpp = { 10 },
- .mplanes = 1,
- .write_format = MI_CTRL_MP_WRITE_RAW12,
- }, {
- .fourcc = V4L2_PIX_FMT_SBGGR10,
- .fmt_type = FMT_BAYER,
- .bpp = { 10 },
- .mplanes = 1,
- .write_format = MI_CTRL_MP_WRITE_RAW12,
- }, {
- .fourcc = V4L2_PIX_FMT_SRGGB12,
- .fmt_type = FMT_BAYER,
- .bpp = { 12 },
- .mplanes = 1,
- .write_format = MI_CTRL_MP_WRITE_RAW12,
- }, {
- .fourcc = V4L2_PIX_FMT_SGRBG12,
- .fmt_type = FMT_BAYER,
- .bpp = { 12 },
- .mplanes = 1,
- .write_format = MI_CTRL_MP_WRITE_RAW12,
- }, {
- .fourcc = V4L2_PIX_FMT_SGBRG12,
- .fmt_type = FMT_BAYER,
- .bpp = { 12 },
- .mplanes = 1,
- .write_format = MI_CTRL_MP_WRITE_RAW12,
- }, {
- .fourcc = V4L2_PIX_FMT_SBGGR12,
- .fmt_type = FMT_BAYER,
- .bpp = { 12 },
- .mplanes = 1,
- .write_format = MI_CTRL_MP_WRITE_RAW12,
- },
-};
+int rkisp_stream_frame_start(struct rkisp_device *dev, u32 isp_mis)
+{
+ struct rkisp_stream *stream;
+ int i;
-static const struct capture_fmt sp_fmts[] = {
- /* yuv422 */
- {
- .fourcc = V4L2_PIX_FMT_UYVY,
- .fmt_type = FMT_YUV,
- .bpp = { 16 },
- .cplanes = 1,
- .mplanes = 1,
- .uv_swap = 0,
- .write_format = MI_CTRL_SP_WRITE_INT,
- .output_format = MI_CTRL_SP_OUTPUT_YUV422,
- }, {
- .fourcc = V4L2_PIX_FMT_YUV422P,
- .fmt_type = FMT_YUV,
- .bpp = { 8, 8, 8 },
- .cplanes = 3,
- .mplanes = 1,
- .uv_swap = 0,
- .write_format = MI_CTRL_SP_WRITE_PLA,
- .output_format = MI_CTRL_SP_OUTPUT_YUV422,
- }, {
- .fourcc = V4L2_PIX_FMT_NV16,
- .fmt_type = FMT_YUV,
- .bpp = { 8, 16 },
- .cplanes = 2,
- .mplanes = 1,
- .uv_swap = 0,
- .write_format = MI_CTRL_SP_WRITE_SPLA,
- .output_format = MI_CTRL_SP_OUTPUT_YUV422,
- }, {
- .fourcc = V4L2_PIX_FMT_NV61,
- .fmt_type = FMT_YUV,
- .bpp = { 8, 16 },
- .cplanes = 2,
- .mplanes = 1,
- .uv_swap = 1,
- .write_format = MI_CTRL_SP_WRITE_SPLA,
- .output_format = MI_CTRL_SP_OUTPUT_YUV422,
- }, {
- .fourcc = V4L2_PIX_FMT_YUV422M,
- .fmt_type = FMT_YUV,
- .bpp = { 8, 8, 8 },
- .cplanes = 3,
- .mplanes = 3,
- .uv_swap = 0,
- .write_format = MI_CTRL_SP_WRITE_PLA,
- .output_format = MI_CTRL_SP_OUTPUT_YUV422,
- },
- /* yuv420 */
- {
- .fourcc = V4L2_PIX_FMT_NV21,
- .fmt_type = FMT_YUV,
- .bpp = { 8, 16 },
- .cplanes = 2,
- .mplanes = 1,
- .uv_swap = 1,
- .write_format = MI_CTRL_SP_WRITE_SPLA,
- .output_format = MI_CTRL_SP_OUTPUT_YUV420,
- }, {
- .fourcc = V4L2_PIX_FMT_NV12,
- .fmt_type = FMT_YUV,
- .bpp = { 8, 16 },
- .cplanes = 2,
- .mplanes = 1,
- .uv_swap = 0,
- .write_format = MI_CTRL_SP_WRITE_SPLA,
- .output_format = MI_CTRL_SP_OUTPUT_YUV420,
- }, {
- .fourcc = V4L2_PIX_FMT_NV21M,
- .fmt_type = FMT_YUV,
- .bpp = { 8, 16 },
- .cplanes = 2,
- .mplanes = 2,
- .uv_swap = 1,
- .write_format = MI_CTRL_SP_WRITE_SPLA,
- .output_format = MI_CTRL_SP_OUTPUT_YUV420,
- }, {
- .fourcc = V4L2_PIX_FMT_NV12M,
- .fmt_type = FMT_YUV,
- .bpp = { 8, 16 },
- .cplanes = 2,
- .mplanes = 2,
- .uv_swap = 0,
- .write_format = MI_CTRL_SP_WRITE_SPLA,
- .output_format = MI_CTRL_SP_OUTPUT_YUV420,
- }, {
- .fourcc = V4L2_PIX_FMT_YUV420,
- .fmt_type = FMT_YUV,
- .bpp = { 8, 8, 8 },
- .cplanes = 3,
- .mplanes = 1,
- .uv_swap = 0,
- .write_format = MI_CTRL_SP_WRITE_PLA,
- .output_format = MI_CTRL_SP_OUTPUT_YUV420,
- },
- /* yuv444 */
- {
- .fourcc = V4L2_PIX_FMT_YUV444M,
- .fmt_type = FMT_YUV,
- .bpp = { 8, 8, 8 },
- .cplanes = 3,
- .mplanes = 3,
- .uv_swap = 0,
- .write_format = MI_CTRL_SP_WRITE_PLA,
- .output_format = MI_CTRL_SP_OUTPUT_YUV444,
- },
- /* yuv400 */
- {
- .fourcc = V4L2_PIX_FMT_GREY,
- .fmt_type = FMT_YUV,
- .bpp = { 8 },
- .cplanes = 1,
- .mplanes = 1,
- .uv_swap = 0,
- .write_format = MI_CTRL_SP_WRITE_PLA,
- .output_format = MI_CTRL_SP_OUTPUT_YUV400,
- },
- /* rgb */
- {
- .fourcc = V4L2_PIX_FMT_XBGR32,
- .fmt_type = FMT_RGB,
- .bpp = { 32 },
- .mplanes = 1,
- .write_format = MI_CTRL_SP_WRITE_PLA,
- .output_format = MI_CTRL_SP_OUTPUT_RGB888,
- }, {
- .fourcc = V4L2_PIX_FMT_RGB565,
- .fmt_type = FMT_RGB,
- .bpp = { 16 },
- .mplanes = 1,
- .write_format = MI_CTRL_SP_WRITE_PLA,
- .output_format = MI_CTRL_SP_OUTPUT_RGB565,
- },
- /* fbcg */
- {
- .fourcc = V4L2_PIX_FMT_FBCG,
- .fmt_type = FMT_FBCGAIN,
- .bpp = { 8, 16 },
- .cplanes = 2,
- .mplanes = 2,
- .uv_swap = 0,
- .write_format = MI_CTRL_SP_WRITE_SPLA,
- .output_format = MI_CTRL_SP_OUTPUT_YUV420,
+ if (isp_mis)
+ rkisp_dvbm_event(dev, CIF_ISP_V_START);
+ rkisp_bridge_update_mi(dev, isp_mis);
+
+ for (i = 0; i < RKISP_MAX_STREAM; i++) {
+ if (i == RKISP_STREAM_VIR || i == RKISP_STREAM_LUMA)
+ continue;
+ stream = &dev->cap_dev.stream[i];
+ if (stream->streaming &&
+ stream->ops && stream->ops->frame_start)
+ stream->ops->frame_start(stream, isp_mis);
}
-};
+
+ return 0;
+}
+
+void rkisp_stream_buf_done_early(struct rkisp_device *dev)
+{
+ struct rkisp_stream *stream;
+ int i;
+
+ if (!dev->cap_dev.is_done_early)
+ return;
+
+ for (i = 0; i < RKISP_MAX_STREAM; i++) {
+ if (i == RKISP_STREAM_VIR || i == RKISP_STREAM_LUMA ||
+ i == RKISP_STREAM_DMATX0 || i == RKISP_STREAM_DMATX1 ||
+ i == RKISP_STREAM_DMATX2 || i == RKISP_STREAM_DMATX3)
+ continue;
+ stream = &dev->cap_dev.stream[i];
+ if (stream->streaming && !stream->stopping &&
+ stream->ops && stream->ops->frame_end)
+ stream->ops->frame_end(stream, FRAME_WORK);
+ }
+}
struct stream_config rkisp_mp_stream_config = {
- .fmts = mp_fmts,
- .fmt_size = ARRAY_SIZE(mp_fmts),
/* constraints */
.max_rsz_width = STREAM_MAX_MP_RSZ_OUTPUT_WIDTH,
.max_rsz_height = STREAM_MAX_MP_RSZ_OUTPUT_HEIGHT,
@@ -801,12 +527,11 @@
.cb_offs_cnt_init = CIF_MI_MP_CB_OFFS_CNT_INIT,
.cr_offs_cnt_init = CIF_MI_MP_CR_OFFS_CNT_INIT,
.y_base_ad_shd = CIF_MI_MP_Y_BASE_AD_SHD,
+ .y_pic_size = ISP3X_MI_MP_WR_Y_PIC_SIZE,
},
};
struct stream_config rkisp_sp_stream_config = {
- .fmts = sp_fmts,
- .fmt_size = ARRAY_SIZE(sp_fmts),
/* constraints */
.max_rsz_width = STREAM_MAX_SP_RSZ_OUTPUT_WIDTH,
.max_rsz_height = STREAM_MAX_SP_RSZ_OUTPUT_HEIGHT,
@@ -858,6 +583,7 @@
.cb_offs_cnt_init = CIF_MI_SP_CB_OFFS_CNT_INIT,
.cr_offs_cnt_init = CIF_MI_SP_CR_OFFS_CNT_INIT,
.y_base_ad_shd = CIF_MI_SP_Y_BASE_AD_SHD,
+ .y_pic_size = ISP3X_MI_SP_WR_Y_PIC_SIZE,
},
};
@@ -875,21 +601,40 @@
return NULL;
}
-/*
- * Make sure max resize/output resolution is smaller than
- * isp sub device output size. This assumes it's not
- * recommended to use ISP scale-up function to get output size
- * that exceeds sensor max resolution.
- */
-static void restrict_rsz_resolution(struct rkisp_device *dev,
- const struct stream_config *config,
+static void restrict_rsz_resolution(struct rkisp_stream *stream,
+ const struct stream_config *cfg,
struct v4l2_rect *max_rsz)
{
- struct v4l2_rect *input_win;
+ struct rkisp_device *dev = stream->ispdev;
+ struct v4l2_rect *input_win = rkisp_get_isp_sd_win(&dev->isp_sdev);
- input_win = rkisp_get_isp_sd_win(&dev->isp_sdev);
- max_rsz->width = min_t(int, input_win->width, config->max_rsz_width);
- max_rsz->height = min_t(int, input_win->height, config->max_rsz_height);
+ if (stream->id == RKISP_STREAM_VIR ||
+ (dev->isp_ver == ISP_V30 && stream->id == RKISP_STREAM_BP)) {
+ max_rsz->width = input_win->width;
+ max_rsz->height = input_win->height;
+ } else if (stream->id == RKISP_STREAM_FBC) {
+ max_rsz->width = stream->dcrop.width;
+ max_rsz->height = stream->dcrop.height;
+ } else if (stream->id == RKISP_STREAM_MPDS ||
+ stream->id == RKISP_STREAM_BPDS) {
+ struct rkisp_stream *t = &dev->cap_dev.stream[stream->conn_id];
+
+ max_rsz->width = t->out_fmt.width / 4;
+ max_rsz->height = t->out_fmt.height / 4;
+ } else if (stream->id == RKISP_STREAM_LUMA) {
+ u32 div = dev->is_bigmode ? 32 : 16;
+
+ max_rsz->width = ALIGN(DIV_ROUND_UP(input_win->width, div), 4);
+ max_rsz->height = DIV_ROUND_UP(input_win->height, div);
+ } else if (dev->hw_dev->unite) {
+ /* scale down only for unite mode */
+ max_rsz->width = min_t(int, input_win->width, cfg->max_rsz_width);
+ max_rsz->height = min_t(int, input_win->height, cfg->max_rsz_height);
+ } else {
+ /* scale up/down */
+ max_rsz->width = cfg->max_rsz_width;
+ max_rsz->height = cfg->max_rsz_height;
+ }
}
static int rkisp_set_fmt(struct rkisp_stream *stream,
@@ -897,18 +642,17 @@
bool try)
{
const struct capture_fmt *fmt;
+ struct rkisp_vdev_node *node = &stream->vnode;
const struct stream_config *config = stream->config;
struct rkisp_device *dev = stream->ispdev;
- struct rkisp_stream *other_stream;
- unsigned int imagsize = 0;
- unsigned int planes;
- u32 xsubs = 1, ysubs = 1;
- unsigned int i;
+ struct v4l2_rect max_rsz;
+ u32 i, planes, imagsize = 0, xsubs = 1, ysubs = 1;
fmt = find_fmt(stream, pixm->pixelformat);
if (!fmt) {
- v4l2_err(&stream->ispdev->v4l2_dev,
- "nonsupport pixelformat:%c%c%c%c\n",
+ v4l2_err(&dev->v4l2_dev,
+ "%s nonsupport pixelformat:%c%c%c%c\n",
+ node->vdev.name,
pixm->pixelformat,
pixm->pixelformat >> 8,
pixm->pixelformat >> 16,
@@ -916,51 +660,89 @@
return -EINVAL;
}
+ /* do checks on resolution */
+ restrict_rsz_resolution(stream, config, &max_rsz);
if (stream->id == RKISP_STREAM_MP ||
- stream->id == RKISP_STREAM_SP) {
- struct v4l2_rect max_rsz;
+ stream->id == RKISP_STREAM_SP ||
+ (stream->id == RKISP_STREAM_BP && dev->isp_ver != ISP_V30)) {
+ pixm->width = clamp_t(u32, pixm->width, config->min_rsz_width, max_rsz.width);
+ } else if (pixm->width != max_rsz.width &&
+ pixm->height != max_rsz.height &&
+ (stream->id == RKISP_STREAM_LUMA ||
+ (dev->isp_ver == ISP_V30 &&
+ (stream->id == RKISP_STREAM_BP || stream->id == RKISP_STREAM_FBC)))) {
+ v4l2_warn(&dev->v4l2_dev,
+ "%s no scale %dx%d should equal to %dx%d\n",
+ node->vdev.name,
+ pixm->width, pixm->height,
+ max_rsz.width, max_rsz.height);
+ pixm->width = max_rsz.width;
+ pixm->height = max_rsz.height;
+ } else if (stream->id == RKISP_STREAM_MPDS || stream->id == RKISP_STREAM_BPDS) {
+ struct rkisp_stream *t = &dev->cap_dev.stream[stream->conn_id];
- other_stream = (stream->id == RKISP_STREAM_MP) ?
- &dev->cap_dev.stream[RKISP_STREAM_SP] :
- &dev->cap_dev.stream[RKISP_STREAM_MP];
- /* do checks on resolution */
- restrict_rsz_resolution(stream->ispdev, config, &max_rsz);
- pixm->width = clamp_t(u32, pixm->width,
- config->min_rsz_width, max_rsz.width);
- pixm->height = clamp_t(u32, pixm->height,
- config->min_rsz_height, max_rsz.height);
- } else {
- other_stream =
- &stream->ispdev->cap_dev.stream[RKISP_STREAM_MP];
+ if (pixm->pixelformat != t->out_fmt.pixelformat ||
+ pixm->width != max_rsz.width || pixm->height != max_rsz.height) {
+ v4l2_warn(&dev->v4l2_dev,
+ "%s from %s, force to %dx%d %c%c%c%c\n",
+ node->vdev.name, t->vnode.vdev.name,
+ max_rsz.width, max_rsz.height,
+ t->out_fmt.pixelformat,
+ t->out_fmt.pixelformat >> 8,
+ t->out_fmt.pixelformat >> 16,
+ t->out_fmt.pixelformat >> 24);
+ pixm->pixelformat = t->out_fmt.pixelformat;
+ pixm->width = max_rsz.width;
+ pixm->height = max_rsz.height;
+ }
+ } else if (stream->id == RKISP_STREAM_VIR) {
+ struct rkisp_stream *t;
+
+ if (stream->conn_id != -1) {
+ t = &dev->cap_dev.stream[stream->conn_id];
+ *pixm = t->out_fmt;
+ } else {
+ for (i = RKISP_STREAM_MP; i < RKISP_STREAM_VIR; i++) {
+ t = &dev->cap_dev.stream[i];
+ if (t->out_isp_fmt.fmt_type != FMT_YUV || !t->streaming)
+ continue;
+ if (t->out_fmt.plane_fmt[0].sizeimage > imagsize) {
+ imagsize = t->out_fmt.plane_fmt[0].sizeimage;
+ *pixm = t->out_fmt;
+ stream->conn_id = t->id;
+ }
+ }
+ }
+ if (stream->conn_id == -1) {
+ v4l2_err(&dev->v4l2_dev, "no output stream for iqtool\n");
+ return -EINVAL;
+ }
+ imagsize = 0;
}
+
pixm->num_planes = fmt->mplanes;
pixm->field = V4L2_FIELD_NONE;
/* get quantization from ispsd */
pixm->quantization = stream->ispdev->isp_sdev.quantization;
-
- /* output full range by default, take effect in isp_params */
- if (!pixm->quantization)
- pixm->quantization = V4L2_QUANTIZATION_FULL_RANGE;
- /* can not change quantization when stream-on */
- if (other_stream->streaming)
- pixm->quantization = other_stream->out_fmt.quantization;
/* calculate size */
rkisp_fcc_xysubs(fmt->fourcc, &xsubs, &ysubs);
planes = fmt->cplanes ? fmt->cplanes : fmt->mplanes;
for (i = 0; i < planes; i++) {
struct v4l2_plane_pix_format *plane_fmt;
- unsigned int width, height, bytesperline;
+ unsigned int width, height, bytesperline, w, h;
plane_fmt = pixm->plane_fmt + i;
- if (i == 0) {
- width = pixm->width;
- height = pixm->height;
- } else {
- width = pixm->width / xsubs;
- height = pixm->height / ysubs;
- }
+ w = (fmt->fmt_type == FMT_FBC) ?
+ ALIGN(pixm->width, 16) : pixm->width;
+ h = (fmt->fmt_type == FMT_FBC) ?
+ ALIGN(pixm->height, 16) : pixm->height;
+ /* mainpath for warp default */
+ if (dev->cap_dev.wrap_line && stream->id == RKISP_STREAM_MP)
+ h = dev->cap_dev.wrap_line;
+ width = i ? w / xsubs : w;
+ height = i ? h / ysubs : h;
if (dev->isp_ver == ISP_V20 &&
fmt->fmt_type == FMT_BAYER &&
@@ -977,20 +759,28 @@
bytesperline = ALIGN(width * fmt->bpp[i] / 8, 256);
else
bytesperline = width * DIV_ROUND_UP(fmt->bpp[i], 8);
- /* 128bit AXI, 16byte align for bytesperline */
- if (dev->isp_ver >= ISP_V20 && stream->id == RKISP_STREAM_SP)
- bytesperline = ALIGN(bytesperline, 16);
- /* stride is only available for sp stream and y plane */
- if (stream->id != RKISP_STREAM_SP || i != 0 ||
- plane_fmt->bytesperline < bytesperline)
+
+ if (i != 0 || plane_fmt->bytesperline < bytesperline)
plane_fmt->bytesperline = bytesperline;
+
+ /* 128bit AXI, 16byte align for bytesperline */
+ if ((dev->isp_ver == ISP_V20 && stream->id == RKISP_STREAM_SP) ||
+ dev->isp_ver >= ISP_V30)
+ plane_fmt->bytesperline = ALIGN(plane_fmt->bytesperline, 16);
plane_fmt->sizeimage = plane_fmt->bytesperline * height;
- /* uv address is y size offset need 64 align */
+ /* FMT_FBCGAIN: uv address is y size offset need 64 align
+ * FMT_FBC: width and height need 16 align
+ * header: width * height / 16, and 4096 align for mpp
+ * payload: yuv420 or yuv422 size
+ */
if (fmt->fmt_type == FMT_FBCGAIN && i == 0)
plane_fmt->sizeimage = ALIGN(plane_fmt->sizeimage, 64);
-
+ else if (fmt->fmt_type == FMT_FBC && i == 0)
+ plane_fmt->sizeimage = ALIGN(plane_fmt->sizeimage >> 4, RK_MPP_ALIGN);
+ else if (fmt->fmt_type == FMT_FBC)
+ plane_fmt->sizeimage += w * h;
imagsize += plane_fmt->sizeimage;
}
@@ -1014,22 +804,29 @@
}
v4l2_dbg(1, rkisp_debug, &stream->ispdev->v4l2_dev,
- "%s: stream: %d req(%d, %d) out(%d, %d)\n", __func__,
- stream->id, pixm->width, pixm->height,
+ "%s: %s req(%d, %d) out(%d, %d)\n", __func__,
+ node->vdev.name, pixm->width, pixm->height,
stream->out_fmt.width, stream->out_fmt.height);
}
return 0;
}
+struct rockit_isp_ops rockit_isp_ops = {
+ .rkisp_set_fmt = rkisp_set_fmt,
+};
+
int rkisp_fh_open(struct file *filp)
{
struct rkisp_stream *stream = video_drvdata(filp);
int ret;
+ if (!stream->ispdev->is_probe_end)
+ return -EINVAL;
+
ret = v4l2_fh_open(filp);
if (!ret) {
- ret = v4l2_pipeline_pm_use(&stream->vnode.vdev.entity, 1);
+ ret = v4l2_pipeline_pm_get(&stream->vnode.vdev.entity);
if (ret < 0)
vb2_fop_release(filp);
}
@@ -1043,12 +840,8 @@
int ret;
ret = vb2_fop_release(file);
- if (!ret) {
- ret = v4l2_pipeline_pm_use(&stream->vnode.vdev.entity, 0);
- if (ret < 0)
- v4l2_err(&stream->ispdev->v4l2_dev,
- "set pipeline power failed %d\n", ret);
- }
+ if (!ret)
+ v4l2_pipeline_pm_put(&stream->vnode.vdev.entity);
return ret;
}
@@ -1065,14 +858,15 @@
pixm.pixelformat = stream->out_isp_fmt.fourcc;
if (!pixm.pixelformat)
return;
- pixm.width = width;
- pixm.height = height;
- rkisp_set_fmt(stream, &pixm, false);
stream->dcrop.left = 0;
stream->dcrop.top = 0;
stream->dcrop.width = width;
stream->dcrop.height = height;
+
+ pixm.width = width;
+ pixm.height = height;
+ rkisp_set_fmt(stream, &pixm, false);
}
/************************* v4l2_file_operations***************************/
@@ -1082,6 +876,9 @@
.unlocked_ioctl = video_ioctl2,
.poll = vb2_fop_poll,
.mmap = vb2_fop_mmap,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl32 = video_ioctl2,
+#endif
};
/*
@@ -1115,8 +912,9 @@
const struct stream_config *config = stream->config;
struct v4l2_frmsize_stepwise *s = &fsize->stepwise;
struct v4l2_frmsize_discrete *d = &fsize->discrete;
- const struct ispsd_out_fmt *input_isp_fmt;
+ struct rkisp_device *dev = stream->ispdev;
struct v4l2_rect max_rsz;
+ struct v4l2_rect *input_win = rkisp_get_isp_sd_win(&dev->isp_sdev);
if (fsize->index != 0)
return -EINVAL;
@@ -1124,10 +922,15 @@
if (!find_fmt(stream, fsize->pixel_format))
return -EINVAL;
- restrict_rsz_resolution(stream->ispdev, config, &max_rsz);
+ restrict_rsz_resolution(stream, config, &max_rsz);
- input_isp_fmt = rkisp_get_ispsd_out_fmt(&stream->ispdev->isp_sdev);
- if (input_isp_fmt->fmt_type == FMT_BAYER) {
+ if (stream->out_isp_fmt.fmt_type == FMT_BAYER ||
+ stream->id == RKISP_STREAM_FBC ||
+ stream->id == RKISP_STREAM_BPDS ||
+ stream->id == RKISP_STREAM_MPDS ||
+ stream->id == RKISP_STREAM_LUMA ||
+ stream->id == RKISP_STREAM_VIR ||
+ (stream->id == RKISP_STREAM_BP && dev->hw_dev->isp_ver == ISP_V30)) {
fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
d->width = max_rsz.width;
d->height = max_rsz.height;
@@ -1135,13 +938,286 @@
fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
s->min_width = STREAM_MIN_RSZ_OUTPUT_WIDTH;
s->min_height = STREAM_MIN_RSZ_OUTPUT_HEIGHT;
- s->max_width = max_rsz.width;
- s->max_height = max_rsz.height;
+ s->max_width = min_t(u32, max_rsz.width, input_win->width);
+ s->max_height = input_win->height;
s->step_width = STREAM_OUTPUT_STEP_WISE;
s->step_height = STREAM_OUTPUT_STEP_WISE;
}
return 0;
+}
+
+static int rkisp_get_cmsk(struct rkisp_stream *stream, struct rkisp_cmsk_cfg *cfg)
+{
+ struct rkisp_device *dev = stream->ispdev;
+ unsigned long lock_flags = 0;
+ u32 i, win_en, mode;
+
+ if ((dev->isp_ver != ISP_V30 && dev->isp_ver != ISP_V32) ||
+ stream->id == RKISP_STREAM_FBC ||
+ stream->id == RKISP_STREAM_MPDS ||
+ stream->id == RKISP_STREAM_BPDS) {
+ v4l2_err(&dev->v4l2_dev, "%s not support\n", __func__);
+ return -EINVAL;
+ }
+
+ spin_lock_irqsave(&dev->cmsk_lock, lock_flags);
+ *cfg = dev->cmsk_cfg;
+ spin_unlock_irqrestore(&dev->cmsk_lock, lock_flags);
+
+ switch (stream->id) {
+ case RKISP_STREAM_MP:
+ win_en = cfg->win[0].win_en;
+ mode = cfg->win[0].mode;
+ break;
+ case RKISP_STREAM_SP:
+ win_en = cfg->win[1].win_en;
+ mode = cfg->win[1].mode;
+ break;
+ case RKISP_STREAM_BP:
+ default:
+ win_en = cfg->win[2].win_en;
+ mode = cfg->win[2].mode;
+ break;
+ }
+
+ cfg->width_ro = dev->isp_sdev.out_crop.width;
+ cfg->height_ro = dev->isp_sdev.out_crop.height;
+ for (i = 0; i < RKISP_CMSK_WIN_MAX; i++) {
+ cfg->win[i].win_en = !!(win_en & BIT(i));
+ cfg->win[i].mode = !!(mode & BIT(i));
+ }
+
+ return 0;
+}
+
+static int rkisp_set_cmsk(struct rkisp_stream *stream, struct rkisp_cmsk_cfg *cfg)
+{
+ struct rkisp_device *dev = stream->ispdev;
+ unsigned long lock_flags = 0;
+ u16 i, win_en = 0, mode = 0;
+ u16 h_offs, v_offs, h_size, v_size;
+ u32 width = dev->isp_sdev.out_crop.width;
+ u32 height = dev->isp_sdev.out_crop.height;
+ u32 align = (dev->isp_ver == ISP_V30) ? 8 : 2;
+ bool warn = false;
+
+ if ((dev->isp_ver != ISP_V30 && dev->isp_ver != ISP_V32) ||
+ stream->id == RKISP_STREAM_FBC ||
+ stream->id == RKISP_STREAM_MPDS ||
+ stream->id == RKISP_STREAM_BPDS) {
+ v4l2_err(&dev->v4l2_dev, "%s not support\n", __func__);
+ return -EINVAL;
+ }
+
+ spin_lock_irqsave(&dev->cmsk_lock, lock_flags);
+ dev->is_cmsk_upd = true;
+ for (i = 0; i < RKISP_CMSK_WIN_MAX; i++) {
+ win_en |= cfg->win[i].win_en ? BIT(i) : 0;
+ mode |= cfg->win[i].mode ? BIT(i) : 0;
+
+ if (cfg->win[i].win_en) {
+ if (cfg->win[i].mode) {
+ dev->cmsk_cfg.win[i].cover_color_y = cfg->win[i].cover_color_y;
+ dev->cmsk_cfg.win[i].cover_color_u = cfg->win[i].cover_color_u;
+ dev->cmsk_cfg.win[i].cover_color_v = cfg->win[i].cover_color_v;
+ }
+ h_offs = cfg->win[i].h_offs & ~0x1;
+ v_offs = cfg->win[i].v_offs & ~0x1;
+ h_size = ALIGN_DOWN(cfg->win[i].h_size, align);
+ v_size = ALIGN_DOWN(cfg->win[i].v_size, align);
+ if (h_offs != cfg->win[i].h_offs ||
+ v_offs != cfg->win[i].v_offs ||
+ h_size != cfg->win[i].h_size ||
+ v_size != cfg->win[i].v_size)
+ warn = true;
+ if (h_offs + h_size > width) {
+ h_size = ALIGN_DOWN(width - h_offs, align);
+ warn = true;
+ }
+ if (v_offs + v_size > height) {
+ v_size = ALIGN_DOWN(height - v_offs, align);
+ warn = true;
+ }
+ if (warn) {
+ warn = false;
+ v4l2_warn(&dev->v4l2_dev,
+ "%s cmsk offs 2 align, size %d align and offs + size < resolution\n"
+ "\t cmsk win%d result to offs:%d %d, size:%d %d\n",
+ stream->vnode.vdev.name, i, align, h_offs, v_offs, h_size, v_size);
+ }
+ dev->cmsk_cfg.win[i].h_offs = h_offs;
+ dev->cmsk_cfg.win[i].v_offs = v_offs;
+ dev->cmsk_cfg.win[i].h_size = h_size;
+ dev->cmsk_cfg.win[i].v_size = v_size;
+ }
+ }
+
+ switch (stream->id) {
+ case RKISP_STREAM_MP:
+ dev->cmsk_cfg.win[0].win_en = win_en;
+ dev->cmsk_cfg.win[0].mode = mode;
+ break;
+ case RKISP_STREAM_SP:
+ dev->cmsk_cfg.win[1].win_en = win_en;
+ dev->cmsk_cfg.win[1].mode = mode;
+ break;
+ case RKISP_STREAM_BP:
+ default:
+ dev->cmsk_cfg.win[2].win_en = win_en;
+ dev->cmsk_cfg.win[2].mode = mode;
+ break;
+ }
+ dev->cmsk_cfg.mosaic_block = cfg->mosaic_block;
+ spin_unlock_irqrestore(&dev->cmsk_lock, lock_flags);
+ return 0;
+
+}
+
+static int rkisp_get_stream_info(struct rkisp_stream *stream,
+ struct rkisp_stream_info *info)
+{
+ struct rkisp_device *dev = stream->ispdev;
+ u32 id = 0;
+
+ rkisp_dmarx_get_frame(stream->ispdev, &id, NULL, NULL, true);
+ info->cur_frame_id = stream->dbg.id;
+ info->input_frame_loss = dev->isp_sdev.dbg.frameloss;
+ info->output_frame_loss = stream->dbg.frameloss;
+ info->stream_on = stream->streaming;
+ info->stream_id = stream->id;
+ return 0;
+}
+
+static int rkisp_get_mirror_flip(struct rkisp_stream *stream,
+ struct rkisp_mirror_flip *cfg)
+{
+ struct rkisp_device *dev = stream->ispdev;
+
+ if (dev->isp_ver != ISP_V32)
+ return -EINVAL;
+
+ cfg->mirror = dev->cap_dev.is_mirror;
+ cfg->flip = stream->is_flip;
+ return 0;
+}
+
+static int rkisp_set_mirror_flip(struct rkisp_stream *stream,
+ struct rkisp_mirror_flip *cfg)
+{
+ struct rkisp_device *dev = stream->ispdev;
+
+ if (dev->isp_ver != ISP_V32)
+ return -EINVAL;
+
+ if (dev->cap_dev.wrap_line) {
+ v4l2_warn(&dev->v4l2_dev, "wrap_line mode can not set the mirror");
+ dev->cap_dev.is_mirror = 0;
+ } else {
+ dev->cap_dev.is_mirror = cfg->mirror;
+ }
+
+ stream->is_flip = cfg->flip;
+ stream->is_mf_upd = true;
+ return 0;
+}
+
+static int rkisp_get_wrap_line(struct rkisp_stream *stream, struct rkisp_wrap_info *arg)
+{
+ struct rkisp_device *dev = stream->ispdev;
+
+ if (dev->isp_ver != ISP_V32 && stream->id != RKISP_STREAM_MP)
+ return -EINVAL;
+
+ arg->width = dev->cap_dev.wrap_width;
+ arg->height = dev->cap_dev.wrap_line;
+ return 0;
+}
+
+static int rkisp_set_wrap_line(struct rkisp_stream *stream, struct rkisp_wrap_info *arg)
+{
+ struct rkisp_device *dev = stream->ispdev;
+
+ if (dev->isp_ver != ISP_V32 ||
+ dev->hw_dev->dev_link_num > 1 ||
+ !stream->ops->set_wrap ||
+ dev->hw_dev->unite) {
+ v4l2_err(&dev->v4l2_dev,
+ "wrap only support for single sensor and mainpath\n");
+ return -EINVAL;
+ }
+ dev->cap_dev.wrap_width = arg->width;
+ return stream->ops->set_wrap(stream, arg->height);
+}
+
+static int rkisp_set_fps(struct rkisp_stream *stream, int *fps)
+{
+ struct rkisp_device *dev = stream->ispdev;
+
+ if (dev->isp_ver != ISP_V32)
+ return -EINVAL;
+
+ return rkisp_rockit_fps_set(fps, stream);
+}
+
+static int rkisp_get_fps(struct rkisp_stream *stream, int *fps)
+{
+ struct rkisp_device *dev = stream->ispdev;
+
+ if (dev->isp_ver != ISP_V32)
+ return -EINVAL;
+
+ return rkisp_rockit_fps_get(fps, stream);
+}
+
+int rkisp_get_tb_stream_info(struct rkisp_stream *stream,
+ struct rkisp_tb_stream_info *info)
+{
+ struct rkisp_device *dev = stream->ispdev;
+
+ if (stream->id != RKISP_STREAM_MP) {
+ v4l2_err(&dev->v4l2_dev, "fast only support for MP\n");
+ return -EINVAL;
+ }
+
+ if (!dev->tb_stream_info.buf_max) {
+ v4l2_err(&dev->v4l2_dev, "thunderboot no enough memory for image\n");
+ return -EINVAL;
+ }
+
+ memcpy(info, &dev->tb_stream_info, sizeof(*info));
+ return 0;
+}
+
+int rkisp_free_tb_stream_buf(struct rkisp_stream *stream)
+{
+ struct rkisp_device *dev = stream->ispdev;
+ struct rkisp_isp_subdev *sdev = &dev->isp_sdev;
+ struct v4l2_subdev *sd = &sdev->sd;
+
+ return sd->ops->core->ioctl(sd, RKISP_CMD_FREE_SHARED_BUF, NULL);
+}
+
+static int rkisp_set_iqtool_connect_id(struct rkisp_stream *stream, int stream_id)
+{
+ struct rkisp_device *dev = stream->ispdev;
+
+ if (stream->id != RKISP_STREAM_VIR) {
+ v4l2_err(&dev->v4l2_dev, "only support for iqtool video\n");
+ goto err;
+ }
+
+ if (stream_id != RKISP_STREAM_MP &&
+ stream_id != RKISP_STREAM_SP &&
+ stream_id != RKISP_STREAM_BP) {
+ v4l2_err(&dev->v4l2_dev, "invalid connect stream id\n");
+ goto err;
+ }
+
+ stream->conn_id = stream_id;
+ return 0;
+err:
+ return -EINVAL;
}
static long rkisp_ioctl_default(struct file *file, void *fh,
@@ -1150,7 +1226,7 @@
struct rkisp_stream *stream = video_drvdata(file);
long ret = 0;
- if (!arg)
+ if (!arg && cmd != RKISP_CMD_FREE_TB_STREAM_BUF)
return -EINVAL;
switch (cmd) {
@@ -1180,6 +1256,42 @@
else
stream->memory =
SW_CSI_RWA_WR_SIMG_SWP | SW_CSI_RAW_WR_SIMG_MODE;
+ break;
+ case RKISP_CMD_GET_CMSK:
+ ret = rkisp_get_cmsk(stream, arg);
+ break;
+ case RKISP_CMD_SET_CMSK:
+ ret = rkisp_set_cmsk(stream, arg);
+ break;
+ case RKISP_CMD_GET_STREAM_INFO:
+ ret = rkisp_get_stream_info(stream, arg);
+ break;
+ case RKISP_CMD_GET_MIRROR_FLIP:
+ ret = rkisp_get_mirror_flip(stream, arg);
+ break;
+ case RKISP_CMD_SET_MIRROR_FLIP:
+ ret = rkisp_set_mirror_flip(stream, arg);
+ break;
+ case RKISP_CMD_GET_WRAP_LINE:
+ ret = rkisp_get_wrap_line(stream, arg);
+ break;
+ case RKISP_CMD_SET_WRAP_LINE:
+ ret = rkisp_set_wrap_line(stream, arg);
+ break;
+ case RKISP_CMD_SET_FPS:
+ ret = rkisp_set_fps(stream, arg);
+ break;
+ case RKISP_CMD_GET_FPS:
+ ret = rkisp_get_fps(stream, arg);
+ break;
+ case RKISP_CMD_GET_TB_STREAM_INFO:
+ ret = rkisp_get_tb_stream_info(stream, arg);
+ break;
+ case RKISP_CMD_FREE_TB_STREAM_BUF:
+ ret = rkisp_free_tb_stream_buf(stream);
+ break;
+ case RKISP_CMD_SET_IQTOOL_CONN_ID:
+ ret = rkisp_set_iqtool_connect_id(stream, *(int *)arg);
break;
default:
ret = -EINVAL;
@@ -1231,12 +1343,67 @@
{
struct rkisp_stream *stream = video_drvdata(file);
const struct capture_fmt *fmt = NULL;
+ struct rkisp_device *dev = stream->ispdev;
+ struct ispsd_in_fmt *isp_in_fmt = &dev->isp_sdev.in_fmt;
+ struct ispsd_out_fmt *isp_out_fmt = &dev->isp_sdev.out_fmt;
+ int ret = -EINVAL;
+
+ /* only one output format for raw */
+ if (isp_out_fmt->fmt_type == FMT_BAYER ||
+ stream->id == RKISP_STREAM_DMATX0 ||
+ stream->id == RKISP_STREAM_DMATX1 ||
+ stream->id == RKISP_STREAM_DMATX2 ||
+ stream->id == RKISP_STREAM_DMATX3) {
+ u32 pixelformat = rkisp_mbus_pixelcode_to_v4l2(isp_in_fmt->mbus_code);
+
+ if (f->index == 0) {
+ fmt = find_fmt(stream, pixelformat);
+ if (fmt) {
+ f->pixelformat = pixelformat;
+ ret = 0;
+ }
+ }
+ return ret;
+ }
if (f->index >= stream->config->fmt_size)
return -EINVAL;
fmt = &stream->config->fmts[f->index];
+ /* only output yuv format */
+ if (isp_out_fmt->fmt_type == FMT_YUV && fmt->fmt_type == FMT_BAYER)
+ return -EINVAL;
+
f->pixelformat = fmt->fourcc;
+ switch (f->pixelformat) {
+ case V4L2_PIX_FMT_FBC2:
+ strscpy(f->description,
+ "Rockchip yuv422sp fbc encoder",
+ sizeof(f->description));
+ break;
+ case V4L2_PIX_FMT_FBC0:
+ strscpy(f->description,
+ "Rockchip yuv420sp fbc encoder",
+ sizeof(f->description));
+ break;
+ case V4L2_PIX_FMT_FBCG:
+ strscpy(f->description,
+ "Rockchip fbc gain",
+ sizeof(f->description));
+ break;
+ case V4l2_PIX_FMT_EBD8:
+ strscpy(f->description,
+ "Embedded data 8-bit",
+ sizeof(f->description));
+ break;
+ case V4l2_PIX_FMT_SPD16:
+ strscpy(f->description,
+ "Shield pix data 16-bit",
+ sizeof(f->description));
+ break;
+ default:
+ break;
+ }
return 0;
}
@@ -1298,13 +1465,19 @@
struct v4l2_rect *sel,
const struct v4l2_rect *in)
{
+ struct rkisp_device *dev = stream->ispdev;
+ bool is_unite = !!dev->hw_dev->unite;
+ u32 align = is_unite ? 4 : 2;
+
/* Not crop for MP bayer raw data and dmatx path */
if ((stream->id == RKISP_STREAM_MP &&
stream->out_isp_fmt.fmt_type == FMT_BAYER) ||
stream->id == RKISP_STREAM_DMATX0 ||
stream->id == RKISP_STREAM_DMATX1 ||
stream->id == RKISP_STREAM_DMATX2 ||
- stream->id == RKISP_STREAM_DMATX3) {
+ stream->id == RKISP_STREAM_DMATX3 ||
+ stream->id == RKISP_STREAM_MPDS ||
+ stream->id == RKISP_STREAM_BPDS) {
sel->left = 0;
sel->top = 0;
sel->width = in->width;
@@ -1313,7 +1486,7 @@
}
sel->left = ALIGN(sel->left, 2);
- sel->width = ALIGN(sel->width, 2);
+ sel->width = ALIGN(sel->width, align);
sel->left = clamp_t(u32, sel->left, 0,
in->width - STREAM_MIN_MP_SP_INPUT_WIDTH);
sel->top = clamp_t(u32, sel->top, 0,
@@ -1322,6 +1495,13 @@
in->width - sel->left);
sel->height = clamp_t(u32, sel->height, STREAM_MIN_MP_SP_INPUT_HEIGHT,
in->height - sel->top);
+ if (is_unite && (sel->width + 2 * sel->left) != in->width) {
+ sel->left = ALIGN_DOWN((in->width - sel->width) / 2, 2);
+ v4l2_warn(&dev->v4l2_dev,
+ "try horizontal center crop(%d,%d)/%dx%d for dual isp\n",
+ sel->left, sel->top, sel->width, sel->height);
+ }
+ stream->is_crop_upd = true;
return sel;
}
@@ -1329,18 +1509,9 @@
struct v4l2_selection *sel)
{
struct rkisp_stream *stream = video_drvdata(file);
- struct video_device *vdev = &stream->vnode.vdev;
- struct rkisp_vdev_node *node = vdev_to_node(vdev);
struct rkisp_device *dev = stream->ispdev;
struct v4l2_rect *dcrop = &stream->dcrop;
const struct v4l2_rect *input_win;
-
- if (vb2_is_busy(&node->buf_queue)) {
- v4l2_err(&dev->v4l2_dev, "%s queue busy\n", __func__);
- return -EBUSY;
- }
-
- input_win = rkisp_get_isp_sd_win(&dev->isp_sdev);
if (sel->target != V4L2_SEL_TGT_CROP)
return -EINVAL;
@@ -1348,6 +1519,7 @@
if (sel->flags != 0)
return -EINVAL;
+ input_win = rkisp_get_isp_sd_win(&dev->isp_sdev);
*dcrop = *rkisp_update_crop(stream, &sel->r, input_win);
v4l2_dbg(1, rkisp_debug, &dev->v4l2_dev,
"stream %d crop(%d,%d)/%dx%d\n", stream->id,
@@ -1385,7 +1557,7 @@
.vidioc_streamoff = vb2_ioctl_streamoff,
.vidioc_enum_input = rkisp_enum_input,
.vidioc_try_fmt_vid_cap_mplane = rkisp_try_fmt_vid_cap_mplane,
- .vidioc_enum_fmt_vid_cap_mplane = rkisp_enum_fmt_vid_cap_mplane,
+ .vidioc_enum_fmt_vid_cap = rkisp_enum_fmt_vid_cap_mplane,
.vidioc_s_fmt_vid_cap_mplane = rkisp_s_fmt_vid_cap_mplane,
.vidioc_g_fmt_vid_cap_mplane = rkisp_g_fmt_vid_cap_mplane,
.vidioc_s_selection = rkisp_s_selection,
@@ -1396,8 +1568,78 @@
.vidioc_default = rkisp_ioctl_default,
};
+static void rkisp_buf_done_task(unsigned long arg)
+{
+ struct rkisp_stream *stream = (struct rkisp_stream *)arg;
+ struct rkisp_buffer *buf = NULL;
+ unsigned long lock_flags = 0;
+ LIST_HEAD(local_list);
+
+ spin_lock_irqsave(&stream->vbq_lock, lock_flags);
+ list_replace_init(&stream->buf_done_list, &local_list);
+ spin_unlock_irqrestore(&stream->vbq_lock, lock_flags);
+
+ while (!list_empty(&local_list)) {
+ buf = list_first_entry(&local_list,
+ struct rkisp_buffer, queue);
+ list_del(&buf->queue);
+
+ v4l2_dbg(2, rkisp_debug, &stream->ispdev->v4l2_dev,
+ "stream:%d seq:%d buf:0x%x done\n",
+ stream->id, buf->vb.sequence, buf->buff_addr[0]);
+ vb2_buffer_done(&buf->vb.vb2_buf,
+ stream->streaming ? VB2_BUF_STATE_DONE : VB2_BUF_STATE_ERROR);
+ }
+}
+
+void rkisp_stream_buf_done(struct rkisp_stream *stream,
+ struct rkisp_buffer *buf)
+{
+ unsigned long lock_flags = 0;
+
+ if (!stream || !buf)
+ return;
+ spin_lock_irqsave(&stream->vbq_lock, lock_flags);
+ list_add_tail(&buf->queue, &stream->buf_done_list);
+ spin_unlock_irqrestore(&stream->vbq_lock, lock_flags);
+ tasklet_schedule(&stream->buf_done_tasklet);
+}
+
+static void rkisp_stream_fast(struct work_struct *work)
+{
+ struct rkisp_capture_device *cap_dev =
+ container_of(work, struct rkisp_capture_device, fast_work);
+ struct rkisp_stream *stream = &cap_dev->stream[0];
+ struct rkisp_device *ispdev = cap_dev->ispdev;
+ struct v4l2_subdev *sd = ispdev->active_sensor->sd;
+ int ret;
+
+ if (ispdev->isp_ver != ISP_V32)
+ return;
+
+ mutex_lock(&ispdev->hw_dev->dev_lock);
+ rkisp_chk_tb_over(ispdev);
+ mutex_unlock(&ispdev->hw_dev->dev_lock);
+ if (ispdev->tb_head.complete != RKISP_TB_OK)
+ return;
+ ret = v4l2_pipeline_pm_get(&stream->vnode.vdev.entity);
+ if (ret < 0) {
+ dev_err(ispdev->dev, "%s PM get fail:%d\n", __func__, ret);
+ ispdev->is_thunderboot = false;
+ return;
+ }
+
+ if (ispdev->hw_dev->dev_num > 1)
+ ispdev->hw_dev->is_single = false;
+ ispdev->is_pre_on = true;
+ ispdev->is_rdbk_auto = true;
+ ispdev->pipe.open(&ispdev->pipe, &stream->vnode.vdev.entity, true);
+ v4l2_subdev_call(sd, video, s_stream, true);
+}
+
void rkisp_unregister_stream_vdev(struct rkisp_stream *stream)
{
+ tasklet_kill(&stream->buf_done_tasklet);
media_entity_cleanup(&stream->vnode.vdev.entity);
video_unregister_device(&stream->vnode.vdev);
}
@@ -1427,7 +1669,7 @@
node->pad.flags = MEDIA_PAD_FL_SINK;
vdev->queue = &node->buf_queue;
- ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
+ ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1);
if (ret < 0) {
v4l2_err(v4l2_dev,
"video_register_device failed with error %d\n", ret);
@@ -1457,6 +1699,11 @@
sink, 0, stream->linked);
if (ret < 0)
goto unreg;
+ INIT_LIST_HEAD(&stream->buf_done_list);
+ tasklet_init(&stream->buf_done_tasklet,
+ rkisp_buf_done_task,
+ (unsigned long)stream);
+ tasklet_disable(&stream->buf_done_tasklet);
return 0;
unreg:
video_unregister_device(vdev);
@@ -1466,18 +1713,55 @@
int rkisp_register_stream_vdevs(struct rkisp_device *dev)
{
struct rkisp_capture_device *cap_dev = &dev->cap_dev;
+ struct stream_config *st_cfg = &rkisp_mp_stream_config;
int ret = 0;
memset(cap_dev, 0, sizeof(*cap_dev));
cap_dev->ispdev = dev;
atomic_set(&cap_dev->refcnt, 0);
- if (dev->isp_ver <= ISP_V13)
+ if (dev->isp_ver <= ISP_V13) {
+ if (dev->isp_ver == ISP_V12) {
+ st_cfg->max_rsz_width = CIF_ISP_INPUT_W_MAX_V12;
+ st_cfg->max_rsz_height = CIF_ISP_INPUT_H_MAX_V12;
+ } else if (dev->isp_ver == ISP_V13) {
+ st_cfg->max_rsz_width = CIF_ISP_INPUT_W_MAX_V13;
+ st_cfg->max_rsz_height = CIF_ISP_INPUT_H_MAX_V13;
+ }
ret = rkisp_register_stream_v1x(dev);
- else if (dev->isp_ver == ISP_V20)
+ } else if (dev->isp_ver == ISP_V20) {
ret = rkisp_register_stream_v20(dev);
- else if (dev->isp_ver == ISP_V21)
+ } else if (dev->isp_ver == ISP_V21) {
+ st_cfg->max_rsz_width = CIF_ISP_INPUT_W_MAX_V21;
+ st_cfg->max_rsz_height = CIF_ISP_INPUT_H_MAX_V21;
ret = rkisp_register_stream_v21(dev);
+ } else if (dev->isp_ver == ISP_V30) {
+ st_cfg->max_rsz_width = dev->hw_dev->unite ?
+ CIF_ISP_INPUT_W_MAX_V30_UNITE : CIF_ISP_INPUT_W_MAX_V30;
+ st_cfg->max_rsz_height = dev->hw_dev->unite ?
+ CIF_ISP_INPUT_H_MAX_V30_UNITE : CIF_ISP_INPUT_H_MAX_V30;
+ ret = rkisp_register_stream_v30(dev);
+ } else if (dev->isp_ver == ISP_V32) {
+ st_cfg->max_rsz_width = dev->hw_dev->unite ?
+ CIF_ISP_INPUT_W_MAX_V32_UNITE : CIF_ISP_INPUT_W_MAX_V32;
+ st_cfg->max_rsz_height = dev->hw_dev->unite ?
+ CIF_ISP_INPUT_H_MAX_V32_UNITE : CIF_ISP_INPUT_H_MAX_V32;
+ st_cfg = &rkisp_sp_stream_config;
+ st_cfg->max_rsz_width = dev->hw_dev->unite ?
+ CIF_ISP_INPUT_W_MAX_V32_UNITE : CIF_ISP_INPUT_W_MAX_V32;
+ st_cfg->max_rsz_height = dev->hw_dev->unite ?
+ CIF_ISP_INPUT_H_MAX_V32_UNITE : CIF_ISP_INPUT_H_MAX_V32;
+ ret = rkisp_register_stream_v32(dev);
+ } else if (dev->isp_ver == ISP_V32_L) {
+ st_cfg->max_rsz_width = CIF_ISP_INPUT_W_MAX_V32_L;
+ st_cfg->max_rsz_height = CIF_ISP_INPUT_H_MAX_V32_L;
+ st_cfg = &rkisp_sp_stream_config;
+ st_cfg->max_rsz_width = CIF_ISP_INPUT_W_MAX_V32_L;
+ st_cfg->max_rsz_height = CIF_ISP_INPUT_H_MAX_V32_L;
+ ret = rkisp_register_stream_v32(dev);
+ }
+
+ INIT_WORK(&cap_dev->fast_work, rkisp_stream_fast);
return ret;
}
@@ -1489,6 +1773,10 @@
rkisp_unregister_stream_v20(dev);
else if (dev->isp_ver == ISP_V21)
rkisp_unregister_stream_v21(dev);
+ else if (dev->isp_ver == ISP_V30)
+ rkisp_unregister_stream_v30(dev);
+ else if (dev->isp_ver == ISP_V32 || dev->isp_ver == ISP_V32_L)
+ rkisp_unregister_stream_v32(dev);
}
void rkisp_mi_isr(u32 mis_val, struct rkisp_device *dev)
@@ -1499,4 +1787,8 @@
rkisp_mi_v20_isr(mis_val, dev);
else if (dev->isp_ver == ISP_V21)
rkisp_mi_v21_isr(mis_val, dev);
+ else if (dev->isp_ver == ISP_V30)
+ rkisp_mi_v30_isr(mis_val, dev);
+ else if (dev->isp_ver == ISP_V32 || dev->isp_ver == ISP_V32_L)
+ rkisp_mi_v32_isr(mis_val, dev);
}
--
Gitblit v1.6.2