From 9999e48639b3cecb08ffb37358bcba3b48161b29 Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Fri, 10 May 2024 08:50:17 +0000 Subject: [PATCH] add ax88772_rst --- kernel/drivers/media/platform/rockchip/isp/capture.c | 1130 +++++++++++++++++++++++++++++++++++++---------------------- 1 files changed, 709 insertions(+), 421 deletions(-) diff --git a/kernel/drivers/media/platform/rockchip/isp/capture.c b/kernel/drivers/media/platform/rockchip/isp/capture.c index 670acc1..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,14 +361,14 @@ */ 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->curr_buf || stream->next_buf) continue; - if (!rkisp_read(dev, stream->config->mi.y_base_ad_init, true)) - mi_set_y_addr(stream, hw->dummy_buf.dma_addr); + mi_set_y_addr(stream, hw->dummy_buf.dma_addr); } } } @@ -393,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; @@ -403,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; @@ -431,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, @@ -802,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, @@ -859,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, }, }; @@ -876,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, @@ -898,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, @@ -917,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 && @@ -978,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; } @@ -1015,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); } @@ -1044,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; } @@ -1066,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***************************/ @@ -1119,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; @@ -1128,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; @@ -1139,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, @@ -1154,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) { @@ -1184,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; @@ -1235,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; } @@ -1302,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; @@ -1317,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, @@ -1326,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; } @@ -1333,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; @@ -1352,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, @@ -1389,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, @@ -1400,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); } @@ -1431,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); @@ -1461,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); @@ -1470,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; } @@ -1493,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) @@ -1503,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