From: liuxl0327 Date: Mon, 21 Mar 2022 09:37:32 +0000 (+0800) Subject: v4l2: ISP/VIN support multi stream X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=1b5841bdd30425c9c12c70e50ce0ba5a0b0bc3cf;p=platform%2Fkernel%2Flinux-starfive.git v4l2: ISP/VIN support multi stream Signed-off-by: mason.huo --- diff --git a/drivers/media/platform/starfive/v4l2_driver/stf_isp.c b/drivers/media/platform/starfive/v4l2_driver/stf_isp.c index 70a0dde..93bacaffe 100644 --- a/drivers/media/platform/starfive/v4l2_driver/stf_isp.c +++ b/drivers/media/platform/starfive/v4l2_driver/stf_isp.c @@ -28,7 +28,6 @@ int stf_isp_subdev_init(struct stfcamss *stfcamss, int id) { struct stf_isp_dev *isp_dev = &stfcamss->isp_dev[id]; - atomic_set(&isp_dev->ref_count, 0); isp_dev->sdev_type = id == 0 ? ISP0_DEV_TYPE : ISP1_DEV_TYPE; isp_dev->id = id; isp_dev->hw_ops = &isp_ops; @@ -36,6 +35,7 @@ int stf_isp_subdev_init(struct stfcamss *stfcamss, int id) isp_dev->formats = isp_formats_st7110; isp_dev->nformats = ARRAY_SIZE(isp_formats_st7110); mutex_init(&isp_dev->stream_lock); + mutex_init(&isp_dev->power_lock); mutex_init(&isp_dev->setfile_lock); atomic_set(&isp_dev->shadow_count, 0); return 0; @@ -198,8 +198,12 @@ static int isp_s_ctrl(struct v4l2_ctrl *ctrl) * not apply any controls to H/W at this time. Instead * the controls will be restored right after power-up. */ - if (!atomic_read(&isp_dev->ref_count)) + mutex_lock(&isp_dev->power_lock); + if (isp_dev->power_count == 0) { + mutex_unlock(&isp_dev->power_lock); return 0; + } + mutex_unlock(&isp_dev->power_lock); switch (ctrl->id) { case V4L2_CID_AUTOGAIN: @@ -325,11 +329,27 @@ free_ctrls: static int isp_set_power(struct v4l2_subdev *sd, int on) { struct stf_isp_dev *isp_dev = v4l2_get_subdevdata(sd); + struct stf_vin2_dev *vin_dev = isp_dev->stfcamss->vin_dev; - if (on) - atomic_inc(&isp_dev->ref_count); - else - atomic_dec(&isp_dev->ref_count); + st_debug(ST_ISP, "%s, %d\n", __func__, __LINE__); + mutex_lock(&isp_dev->power_lock); + if (on) { + if (isp_dev->power_count == 0) { + vin_dev->hw_ops->vin_clk_enable(vin_dev); + isp_dev->hw_ops->isp_clk_enable(isp_dev); + if (!user_config_isp) + isp_dev->hw_ops->isp_config_set(isp_dev); + } + isp_dev->power_count++; + } else { + if (isp_dev->power_count == 0) + goto exit; + if (isp_dev->power_count == 1) + isp_dev->hw_ops->isp_clk_disable(isp_dev); + isp_dev->power_count--; + } +exit: + mutex_unlock(&isp_dev->power_lock); return 0; } @@ -357,31 +377,31 @@ static int isp_set_stream(struct v4l2_subdev *sd, int enable) mutex_lock(&isp_dev->stream_lock); if (enable) { if (isp_dev->stream_count == 0) { - isp_dev->hw_ops->isp_clk_enable(isp_dev); - isp_dev->hw_ops->isp_reset(isp_dev); isp_dev->hw_ops->isp_set_format(isp_dev, &isp_dev->crop, fmt->code); // format->width, format->height); - isp_dev->hw_ops->isp_config_set(isp_dev); + isp_dev->hw_ops->isp_reset(isp_dev); isp_dev->hw_ops->isp_stream_set(isp_dev, enable); + user_config_isp = 0; } isp_dev->stream_count++; } else { if (isp_dev->stream_count == 0) goto exit; - if (isp_dev->stream_count == 1) { + if (isp_dev->stream_count == 1) isp_dev->hw_ops->isp_stream_set(isp_dev, enable); - isp_dev->hw_ops->isp_clk_disable(isp_dev); - } isp_dev->stream_count--; } exit: mutex_unlock(&isp_dev->stream_lock); - if (enable && atomic_read(&isp_dev->ref_count) == 1) { - /* restore controls */ + mutex_lock(&isp_dev->power_lock); + /* restore controls */ + if (enable && isp_dev->power_count == 1) { + mutex_unlock(&isp_dev->power_lock); ret = v4l2_ctrl_handler_setup(&isp_dev->ctrls.handler); - } + } else + mutex_unlock(&isp_dev->power_lock); return ret; } @@ -943,6 +963,12 @@ int stf_isp_register(struct stf_isp_dev *isp_dev, pads[STF_ISP_PAD_SINK].flags = MEDIA_PAD_FL_SINK; pads[STF_ISP_PAD_SRC].flags = MEDIA_PAD_FL_SOURCE; + pads[STF_ISP_PAD_SRC_SS0].flags = MEDIA_PAD_FL_SOURCE; + pads[STF_ISP_PAD_SRC_SS1].flags = MEDIA_PAD_FL_SOURCE; + pads[STF_ISP_PAD_SRC_ITIW].flags = MEDIA_PAD_FL_SOURCE; + pads[STF_ISP_PAD_SRC_ITIR].flags = MEDIA_PAD_FL_SOURCE; + pads[STF_ISP_PAD_SRC_RAW].flags = MEDIA_PAD_FL_SOURCE; + pads[STF_ISP_PAD_SRC_SCD_Y].flags = MEDIA_PAD_FL_SOURCE; sd->entity.function = MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER; sd->entity.ops = &isp_media_ops; @@ -982,6 +1008,7 @@ int stf_isp_unregister(struct stf_isp_dev *isp_dev) media_entity_cleanup(&isp_dev->subdev.entity); v4l2_ctrl_handler_free(&isp_dev->ctrls.handler); mutex_destroy(&isp_dev->stream_lock); + mutex_destroy(&isp_dev->power_lock); mutex_destroy(&isp_dev->setfile_lock); return 0; } diff --git a/drivers/media/platform/starfive/v4l2_driver/stf_isp.h b/drivers/media/platform/starfive/v4l2_driver/stf_isp.h index 926e79d..97c3b2c 100644 --- a/drivers/media/platform/starfive/v4l2_driver/stf_isp.h +++ b/drivers/media/platform/starfive/v4l2_driver/stf_isp.h @@ -14,21 +14,56 @@ #define STF_ISP_NAME "stf_isp" //#define ISP_USE_CSI_AND_SC_DONE_INTERRUPT 1 -#define STF_ISP_PAD_SINK 0 -#define STF_ISP_PAD_SRC 1 -#define STF_ISP_PADS_NUM 2 + +#define STF_ISP_PAD_SINK 0 +#define STF_ISP_PAD_SRC 1 +#define STF_ISP_PAD_SRC_SS0 2 +#define STF_ISP_PAD_SRC_SS1 3 +#define STF_ISP_PAD_SRC_ITIW 4 +#define STF_ISP_PAD_SRC_ITIR 5 +#define STF_ISP_PAD_SRC_RAW 6 +#define STF_ISP_PAD_SRC_SCD_Y 7 +#define STF_ISP_PADS_NUM 8 #define STF_ISP0_SETFILE "stf_isp0_fw.bin" #define STF_ISP1_SETFILE "stf_isp1_fw.bin" -#define SCALER_RATIO_MAX 1 // no compose function +#define ISP_SCD_BUFFER_SIZE (19 * 256 * 4) // align 128 +#define ISP_YHIST_BUFFER_SIZE (64 * 4) +#define ISP_SCD_Y_BUFFER_SIZE (ISP_SCD_BUFFER_SIZE + ISP_YHIST_BUFFER_SIZE) +#define ISP_RAW_DATA_BITS 12 +#define SCALER_RATIO_MAX 1 // no compose function #define STF_ISP_REG_OFFSET_MAX 0x0FFF #define STF_ISP_REG_DELAY_MAX 100 #define ISP_REG_CSIINTS_ADDR 0x00000008 +#define ISP_REG_SENSOR 0x00000014 #define ISP_REG_DUMP_CFG_0 0x00000024 #define ISP_REG_DUMP_CFG_1 0x00000028 +#define ISP_REG_SCD_CFG_0 0x00000098 +#define ISP_REG_SCD_CFG_1 0x0000009C +#define ISP_REG_SC_CFG_1 0x000000BC #define ISP_REG_IESHD_ADDR 0x00000A50 +#define ISP_REG_SS0AY 0x00000A94 +#define ISP_REG_SS0AUV 0x00000A98 +#define ISP_REG_SS0S 0x00000A9C +#define ISP_REG_SS0IW 0x00000AA8 +#define ISP_REG_SS1AY 0x00000AAC +#define ISP_REG_SS1AUV 0x00000AB0 +#define ISP_REG_SS1S 0x00000AB4 +#define ISP_REG_SS1IW 0x00000AC0 +#define ISP_REG_YHIST_CFG_4 0x00000CD8 +#define ISP_REG_ITIIWSR 0x00000B20 +#define ISP_REG_ITIDWLSR 0x00000B24 +#define ISP_REG_ITIDWYSAR 0x00000B28 +#define ISP_REG_ITIDWUSAR 0x00000B2C +#define ISP_REG_ITIDRYSAR 0x00000B30 +#define ISP_REG_ITIDRUSAR 0x00000B34 +#define ISP_REG_ITIPDFR 0x00000B38 +#define ISP_REG_ITIDRLSR 0x00000B3C +#define ISP_REG_ITIBSR 0x00000B40 +#define ISP_REG_ITIAIR 0x00000B44 +#define ISP_REG_ITIDPSR 0x00000B48 enum { EN_INT_NONE = 0, @@ -39,6 +74,21 @@ enum { EN_INT_ALL = (0xF << 24), }; +enum { + DVP_SENSOR = 0, + CSI_SENSOR, +}; + +#define ISP_AWB_OECF_SKIP_FRAME 1 +// 0x0BC [31:30] SEL - sc0 input mux for sc awb +// 00 : after DEC, 01 : after OBC, 10 : after OECF, 11 : after AWB +enum scd_type { + DEC_TYPE = 0, + OBC_TYPE, + OECF_TYPE, + AWB_TYPE +}; + struct isp_format { u32 code; u8 bpp; @@ -119,6 +169,8 @@ struct stf_isp_dev { const struct isp_format *formats; unsigned int nformats; struct isp_hw_ops *hw_ops; + struct mutex power_lock; + int power_count; struct mutex stream_lock; int stream_count; atomic_t shadow_count; diff --git a/drivers/media/platform/starfive/v4l2_driver/stf_video.c b/drivers/media/platform/starfive/v4l2_driver/stf_video.c old mode 100755 new mode 100644 index 62cf9e6..a165033 --- a/drivers/media/platform/starfive/v4l2_driver/stf_video.c +++ b/drivers/media/platform/starfive/v4l2_driver/stf_video.c @@ -51,6 +51,38 @@ static const struct stfcamss_format_info formats_pix_st7110_isp[] = { { { 1, 1 } }, { { 2, 3 } }, { 8 } }, }; +static const struct stfcamss_format_info formats_st7110_isp_iti[] = { + // raw format + { MEDIA_BUS_FMT_SRGGB10_1X10, V4L2_PIX_FMT_SRGGB10, 1, + { { 1, 1 } }, { { 1, 1 } }, { 10 } }, + { MEDIA_BUS_FMT_SGRBG10_1X10, V4L2_PIX_FMT_SGRBG10, 1, + { { 1, 1 } }, { { 1, 1 } }, { 10 } }, + { MEDIA_BUS_FMT_SGBRG10_1X10, V4L2_PIX_FMT_SGBRG10, 1, + { { 1, 1 } }, { { 1, 1 } }, { 10 } }, + { MEDIA_BUS_FMT_SBGGR10_1X10, V4L2_PIX_FMT_SBGGR10, 1, + { { 1, 1 } }, { { 1, 1 } }, { 10 } }, + { MEDIA_BUS_FMT_SRGGB12_1X12, V4L2_PIX_FMT_SRGGB12, 1, + { { 1, 1 } }, { { 1, 1 } }, { 12 } }, + { MEDIA_BUS_FMT_SGRBG12_1X12, V4L2_PIX_FMT_SGRBG12, 1, + { { 1, 1 } }, { { 1, 1 } }, { 12 } }, + { MEDIA_BUS_FMT_SGBRG12_1X12, V4L2_PIX_FMT_SGBRG12, 1, + { { 1, 1 } }, { { 1, 1 } }, { 12 } }, + { MEDIA_BUS_FMT_SBGGR12_1X12, V4L2_PIX_FMT_SBGGR12, 1, + { { 1, 1 } }, { { 1, 1 } }, { 12 } }, + + // YUV420 + { MEDIA_BUS_FMT_Y12_1X12, V4L2_PIX_FMT_NV12, 1, + { { 1, 1 } }, { { 2, 3 } }, { 8 } }, + { MEDIA_BUS_FMT_Y12_1X12, V4L2_PIX_FMT_NV21, 1, + { { 1, 1 } }, { { 2, 3 } }, { 8 } }, + + // YUV444 + { MEDIA_BUS_FMT_YUV8_1X24, V4L2_PIX_FMT_NV24, 1, + { { 1, 1 } }, { { 1, 3 } }, { 8 } }, + { MEDIA_BUS_FMT_VUY8_1X24, V4L2_PIX_FMT_NV42, 1, + { { 1, 1 } }, { { 1, 3 } }, { 8 } }, +}; + static int video_find_format(u32 code, u32 pixelformat, const struct stfcamss_format_info *formats, unsigned int nformats) @@ -258,6 +290,11 @@ static int video_queue_setup(struct vb2_queue *q, if (!sizes[0]) st_err(ST_VIDEO, "%s: error size is zero!!!\n", __func__); } + if ((video->id == VIN_LINE_ISP0_SCD_Y + || video->id == VIN_LINE_ISP1_SCD_Y) + && sizes[0] < ISP_SCD_Y_BUFFER_SIZE) { + sizes[0] = ISP_SCD_Y_BUFFER_SIZE; + } st_info(ST_VIDEO, "%s, planes = %d, size = %d\n", __func__, *num_planes, sizes[0]); @@ -289,7 +326,7 @@ static int video_buf_init(struct vb2_buffer *vb) || fmt_mp->pixelformat == V4L2_PIX_FMT_NV16 || fmt_mp->pixelformat == V4L2_PIX_FMT_NV61)) buffer->addr[1] = buffer->addr[0] + - fmt_mp->width * + fmt_mp->plane_fmt[0].bytesperline * fmt_mp->height; } else { paddr = vb2_plane_cookie(vb, 0); @@ -299,10 +336,14 @@ static int video_buf_init(struct vb2_buffer *vb) || fmt->pixelformat == V4L2_PIX_FMT_NV16 || fmt->pixelformat == V4L2_PIX_FMT_NV61) buffer->addr[1] = buffer->addr[0] + - fmt->width * + fmt->bytesperline * fmt->height; } + if (video->id == VIN_LINE_ISP0_SCD_Y + || video->id == VIN_LINE_ISP1_SCD_Y) + buffer->addr[1] = buffer->addr[0] + ISP_YHIST_BUFFER_SIZE; + return 0; } @@ -325,8 +366,11 @@ static int video_buf_prepare(struct vb2_buffer *vb) fmt_mp->plane_fmt[i].sizeimage); } } else { - if (fmt->sizeimage > vb2_plane_size(vb, 0)) + if (fmt->sizeimage > vb2_plane_size(vb, 0)) { + st_err(ST_VIDEO, "sizeimage = %d, plane size = %d\n", + fmt->sizeimage, (unsigned int)vb2_plane_size(vb, 0)); return -EINVAL; + } vb2_set_plane_payload(vb, 0, fmt->sizeimage); } @@ -507,7 +551,8 @@ static int video_start_streaming(struct vb2_queue *q, unsigned int count) int ret; #ifdef USE_MEDIA_PIPELINE - ret = media_pipeline_start(&vdev->entity, &video->pipe); + // ret = media_pipeline_start(&vdev->entity, &video->pipe); + ret = media_pipeline_start(&vdev->entity, &video->stfcamss->pipe); if (ret < 0) { st_err(ST_VIDEO, "Failed to media_pipeline_start: %d\n", ret); @@ -1188,7 +1233,7 @@ int video_g_ctrl(struct file *file, void *fh, struct v4l2_subdev *subdev; int ret; - subdev = get_senname(file, __func__); + subdev = get_senname(file, (char *)__func__); if (!subdev) return -EINVAL; @@ -1204,7 +1249,7 @@ static int video_s_ctrl(struct file *file, void *fh, struct v4l2_fh *vfh; int ret; - subdev = get_senname(file, __func__); + subdev = get_senname(file, (char *)__func__); if (!subdev) return -EINVAL; @@ -1224,7 +1269,7 @@ static int video_query_ext_ctrl(struct file *file, void *fh, struct v4l2_subdev *subdev; int ret; - subdev = get_senname(file, __func__); + subdev = get_senname(file, (char *)__func__); if (!subdev) return -EINVAL; @@ -1242,7 +1287,7 @@ static int video_g_ext_ctrls(struct file *file, void *fh, struct v4l2_subdev *subdev; int ret; - subdev = get_senname(file, __func__); + subdev = get_senname(file, (char *)__func__); if (!subdev) return -EINVAL; @@ -1283,7 +1328,7 @@ static int video_s_ext_ctrls(struct file *file, void *fh, struct v4l2_fh *vfh; int ret; - subdev = get_senname(file, __func__); + subdev = get_senname(file, (char *)__func__); if (!subdev) return -EINVAL; @@ -1305,7 +1350,7 @@ static int video_try_ext_ctrls(struct file *file, void *fh, struct v4l2_fh *vfh; int ret; - subdev = get_senname(file, __func__); + subdev = get_senname(file, (char *)__func__); if (!subdev) return -EINVAL; @@ -1318,6 +1363,7 @@ static int video_try_ext_ctrls(struct file *file, void *fh, return ret; } + #ifdef UNUSED_CODE static int video_querymenu(struct file *file, void *fh, struct v4l2_querymenu *qm) @@ -1325,9 +1371,10 @@ static int video_querymenu(struct file *file, void *fh, struct v4l2_subdev *subdev; int ret; - subdev = get_senname(file, __func__); + subdev = get_senname(file, (char *)__func__); if (!subdev) return -EINVAL; + ret = v4l2_querymenu(subdev->ctrl_handler, qm); return ret; @@ -1364,9 +1411,6 @@ static const struct v4l2_ioctl_ops stf_vid_ioctl_ops = { .vidioc_queryctrl = video_queryctrl, .vidioc_s_ext_ctrls = video_s_ext_ctrls, .vidioc_try_ext_ctrls = video_try_ext_ctrls, - //.vidioc_query_ext_ctrl = video_query_ext_ctrl, - //.vidioc_querymenu = video_querymenu, - }; static const struct v4l2_ioctl_ops stf_vid_ioctl_ops_mp = { @@ -1399,8 +1443,25 @@ static const struct v4l2_ioctl_ops stf_vid_ioctl_ops_mp = { .vidioc_queryctrl = video_queryctrl, .vidioc_s_ext_ctrls = video_s_ext_ctrls, .vidioc_try_ext_ctrls = video_try_ext_ctrls, -// .vidioc_querymenu = video_querymenu, -// .vidioc_query_ext_ctrl = video_query_ext_ctrl, +}; + +static const struct v4l2_ioctl_ops stf_vid_ioctl_ops_out = { + .vidioc_querycap = video_querycap, + .vidioc_enum_fmt_vid_out = video_enum_fmt, + .vidioc_enum_framesizes = video_enum_framesizes, + .vidioc_enum_frameintervals = video_enum_frameintervals, + .vidioc_g_fmt_vid_out = video_g_fmt, + .vidioc_s_fmt_vid_out = video_s_fmt, + .vidioc_try_fmt_vid_out = video_try_fmt, + .vidioc_reqbufs = vb2_ioctl_reqbufs, + .vidioc_querybuf = vb2_ioctl_querybuf, + .vidioc_qbuf = vb2_ioctl_qbuf, + .vidioc_expbuf = vb2_ioctl_expbuf, + .vidioc_dqbuf = vb2_ioctl_dqbuf, + .vidioc_create_bufs = vb2_ioctl_create_bufs, + .vidioc_prepare_buf = vb2_ioctl_prepare_buf, + .vidioc_streamon = vb2_ioctl_streamon, + .vidioc_streamoff = vb2_ioctl_streamoff, }; static int video_open(struct file *file) @@ -1553,13 +1614,15 @@ int stf_video_register(struct stfcamss_video *video, q->drv_priv = video; q->mem_ops = &vb2_dma_contig_memops; q->ops = &stf_video_vb2_q_ops; - q->type = is_mp ? V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE : - V4L2_BUF_TYPE_VIDEO_CAPTURE; + //q->type = is_mp ? V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE : + // V4L2_BUF_TYPE_VIDEO_CAPTURE; + q->type = video->type; q->io_modes = VB2_DMABUF | VB2_MMAP | VB2_READ; q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; q->buf_struct_size = sizeof(struct stfcamss_buffer); q->dev = video->stfcamss->dev; q->lock = &video->q_lock; + q->min_buffers_needed = STFCAMSS_MIN_BUFFERS; ret = vb2_queue_init(q); if (ret < 0) { st_err(ST_VIDEO, @@ -1581,16 +1644,27 @@ int stf_video_register(struct stfcamss_video *video, if (video->id == VIN_LINE_WR) { video->formats = formats_pix_st7110_wr; video->nformats = ARRAY_SIZE(formats_pix_st7110_wr); - video->bpl_alignment = 8; + video->bpl_alignment = STFCAMSS_FRAME_WIDTH_ALIGN_8; } else if (video->id == VIN_LINE_ISP0 - || video->id == VIN_LINE_ISP1) { // ISP0/ISP1 + || video->id == VIN_LINE_ISP1 + || video->id == VIN_LINE_ISP0_SS0 + || video->id == VIN_LINE_ISP1_SS0 + || video->id == VIN_LINE_ISP0_SS1 + || video->id == VIN_LINE_ISP1_SS1) { // ISP0/ISP1 video->formats = formats_pix_st7110_isp; video->nformats = ARRAY_SIZE(formats_pix_st7110_isp); - video->bpl_alignment = 8; - } else { + video->bpl_alignment = STFCAMSS_FRAME_WIDTH_ALIGN_8; + } else if (video->id == VIN_LINE_ISP0_ITIW + || video->id == VIN_LINE_ISP0_ITIR + || video->id == VIN_LINE_ISP1_ITIW + || video->id == VIN_LINE_ISP1_ITIR) { // ISP0/ISP1 + video->formats = formats_st7110_isp_iti; + video->nformats = ARRAY_SIZE(formats_st7110_isp_iti); + video->bpl_alignment = STFCAMSS_FRAME_WIDTH_ALIGN_8; + } else { // raw/scdump/yhist video->formats = formats_raw_st7110_isp; video->nformats = ARRAY_SIZE(formats_raw_st7110_isp); - video->bpl_alignment = 16 * 8; + video->bpl_alignment = STFCAMSS_FRAME_WIDTH_ALIGN_128; } video->is_mp = is_mp; @@ -1601,13 +1675,22 @@ int stf_video_register(struct stfcamss_video *video, } vdev->fops = &stf_vid_fops; - vdev->device_caps = is_mp ? V4L2_CAP_VIDEO_CAPTURE_MPLANE : + if (video->id == VIN_LINE_ISP0_ITIR + || video->id == VIN_LINE_ISP1_ITIR) { + vdev->device_caps = V4L2_CAP_VIDEO_OUTPUT; + vdev->vfl_dir = VFL_DIR_TX; + } else { + vdev->device_caps = is_mp ? V4L2_CAP_VIDEO_CAPTURE_MPLANE : V4L2_CAP_VIDEO_CAPTURE; + vdev->vfl_dir = VFL_DIR_RX; + } vdev->device_caps |= V4L2_CAP_STREAMING | V4L2_CAP_READWRITE; - vdev->ioctl_ops = is_mp ? &stf_vid_ioctl_ops_mp : &stf_vid_ioctl_ops; + if (video->type == V4L2_CAP_VIDEO_OUTPUT) + vdev->ioctl_ops = &stf_vid_ioctl_ops_out; + else + vdev->ioctl_ops = is_mp ? &stf_vid_ioctl_ops_mp : &stf_vid_ioctl_ops; vdev->release = stf_video_release; vdev->v4l2_dev = v4l2_dev; - vdev->vfl_dir = VFL_DIR_RX; vdev->queue = &video->vb2_q; vdev->lock = &video->lock; //strlcpy(vdev->name, name, sizeof(vdev->name)); diff --git a/drivers/media/platform/starfive/v4l2_driver/stf_video.h b/drivers/media/platform/starfive/v4l2_driver/stf_video.h index f8a21ba..896124a 100755 --- a/drivers/media/platform/starfive/v4l2_driver/stf_video.h +++ b/drivers/media/platform/starfive/v4l2_driver/stf_video.h @@ -13,12 +13,14 @@ #include #include -#define STFCAMSS_FRAME_MIN_WIDTH 1 +#define STFCAMSS_FRAME_MIN_WIDTH 64 #define STFCAMSS_FRAME_MAX_WIDTH 8191 -#define STFCAMSS_FRAME_MIN_HEIGHT 1 +#define STFCAMSS_FRAME_MIN_HEIGHT 64 #define STFCAMSS_FRAME_MAX_HEIGHT_RDI 8191 #define STFCAMSS_FRAME_MAX_HEIGHT_PIX 4096 -#define STFCAMSS_FRAME_WIDTH_ALIGN 8 +#define STFCAMSS_FRAME_WIDTH_ALIGN_8 8 +#define STFCAMSS_FRAME_WIDTH_ALIGN_128 128 +#define STFCAMSS_MIN_BUFFERS 2 struct stfcamss_buffer { struct vb2_v4l2_buffer vb; diff --git a/drivers/media/platform/starfive/v4l2_driver/stf_vin.c b/drivers/media/platform/starfive/v4l2_driver/stf_vin.c index 9a46913..79d4a34 100644 --- a/drivers/media/platform/starfive/v4l2_driver/stf_vin.c +++ b/drivers/media/platform/starfive/v4l2_driver/stf_vin.c @@ -9,12 +9,10 @@ #include "stfcamss.h" -#define STF_VIN_NAME "stf_vin" - -#define vin_line_array(ptr_line) \ +#define vin_line_array(ptr_line) \ ((const struct vin_line (*)[]) &(ptr_line[-(ptr_line->id)])) -#define line_to_vin2_dev(ptr_line) \ +#define line_to_vin2_dev(ptr_line) \ container_of(vin_line_array(ptr_line), struct stf_vin2_dev, line) #define VIN_FRAME_DROP_MAX_VAL 30 @@ -51,12 +49,42 @@ static char *get_line_subdevname(int line_id) case VIN_LINE_ISP1: name = "isp1"; break; + case VIN_LINE_ISP0_SS0: + name = "isp0_ss0"; + break; + case VIN_LINE_ISP1_SS0: + name = "isp1_ss0"; + break; + case VIN_LINE_ISP0_SS1: + name = "isp0_ss1"; + break; + case VIN_LINE_ISP1_SS1: + name = "isp1_ss1"; + break; + case VIN_LINE_ISP0_ITIW: + name = "isp0_itiw"; + break; + case VIN_LINE_ISP1_ITIW: + name = "isp1_itiw"; + break; + case VIN_LINE_ISP0_ITIR: + name = "isp0_itir"; + break; + case VIN_LINE_ISP1_ITIR: + name = "isp1_itir"; + break; case VIN_LINE_ISP0_RAW: name = "isp0_raw"; break; case VIN_LINE_ISP1_RAW: name = "isp1_raw"; break; + case VIN_LINE_ISP0_SCD_Y: + name = "isp0_scd_y"; + break; + case VIN_LINE_ISP1_SCD_Y: + name = "isp1_scd_y"; + break; default: name = "unknow"; break; @@ -186,7 +214,10 @@ int stf_vin_subdev_init(struct stfcamss *stfcamss) is_mp = i == VIN_LINE_WR ? false : true; is_mp = false; - l->video_out.type = is_mp ? V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE : + if (i == VIN_LINE_ISP0_ITIR || i == VIN_LINE_ISP1_ITIR) + l->video_out.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; + else + l->video_out.type = is_mp ? V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE : V4L2_BUF_TYPE_VIDEO_CAPTURE; l->video_out.stfcamss = stfcamss; l->id = i; @@ -258,23 +289,8 @@ static int vin_enable_output(struct vin_line *line) { struct vin_output *output = &line->output; unsigned long flags; - unsigned int frame_skip = 0; - struct media_entity *sensor; - - sensor = stfcamss_find_sensor(&line->subdev.entity); - if (sensor) { - struct v4l2_subdev *subdev = - media_entity_to_v4l2_subdev(sensor); - - v4l2_subdev_call(subdev, sensor, g_skip_frames, &frame_skip); - frame_skip += VIN_FRAME_DROP_MIN_VAL; - if (frame_skip > VIN_FRAME_DROP_MAX_VAL) - frame_skip = VIN_FRAME_DROP_MAX_VAL; - st_debug(ST_VIN, "%s, frame_skip %d\n", __func__, frame_skip); - } spin_lock_irqsave(&line->output_lock, flags); - output->frame_skip = frame_skip; output->state = VIN_OUTPUT_IDLE; @@ -479,8 +495,16 @@ static int vin_set_format(struct v4l2_subdev *sd, if (format == NULL) return -EINVAL; - vin_try_format(line, state, fmt->pad, &fmt->format, fmt->which); - *format = fmt->format; + mutex_lock(&line->stream_lock); + if (line->stream_count) { + fmt->format = *format; + mutex_unlock(&line->stream_lock); + goto out; + } else { + vin_try_format(line, state, fmt->pad, &fmt->format, fmt->which); + *format = fmt->format; + } + mutex_unlock(&line->stream_lock); if (fmt->pad == STF_VIN_PAD_SINK) { /* Propagate the format from sink to source */ @@ -492,6 +516,7 @@ static int vin_set_format(struct v4l2_subdev *sd, fmt->which); } +out: return 0; } @@ -526,9 +551,8 @@ static void vin_output_init_addrs(struct vin_line *line) ping_addr = output->buf[0]->addr[0]; y_addr = output->buf[0]->addr[0]; uv_addr = output->buf[0]->addr[1]; - } else - ping_addr = 0; + return; if (output->buf[1]) pong_addr = output->buf[1]->addr[0]; @@ -552,11 +576,42 @@ static void vin_output_init_addrs(struct vin_line *line) y_addr, uv_addr); break; + case VIN_LINE_ISP0_SS0: // isp0_ss0 + case VIN_LINE_ISP1_SS0: // isp1_ss0 + vin_dev->hw_ops->vin_isp_set_ss0_addr(vin_dev, + line->id - VIN_LINE_ISP0_SS0, + y_addr, uv_addr); + break; + case VIN_LINE_ISP0_SS1: // isp0_ss1 + case VIN_LINE_ISP1_SS1: // isp1_ss1 + vin_dev->hw_ops->vin_isp_set_ss1_addr(vin_dev, + line->id - VIN_LINE_ISP0_SS1, + y_addr, uv_addr); + break; + case VIN_LINE_ISP0_ITIW: // isp0_itiw + case VIN_LINE_ISP1_ITIW: // isp1_itiw + vin_dev->hw_ops->vin_isp_set_itiw_addr(vin_dev, + line->id - VIN_LINE_ISP0_ITIW, + y_addr, uv_addr); + break; + case VIN_LINE_ISP0_ITIR: // isp0_itir + case VIN_LINE_ISP1_ITIR: // isp1_itir + vin_dev->hw_ops->vin_isp_set_itir_addr(vin_dev, + line->id - VIN_LINE_ISP0_ITIR, + y_addr, uv_addr); + break; case VIN_LINE_ISP0_RAW: // isp0_raw case VIN_LINE_ISP1_RAW: // isp1_raw vin_dev->hw_ops->vin_isp_set_raw_addr(vin_dev, line->id - VIN_LINE_ISP0_RAW, y_addr); break; + case VIN_LINE_ISP0_SCD_Y: // isp0_scd_y + case VIN_LINE_ISP1_SCD_Y: // isp1_scd_y + output->frame_skip = ISP_AWB_OECF_SKIP_FRAME; + vin_dev->hw_ops->vin_isp_set_scd_addr(vin_dev, + line->id - VIN_LINE_ISP0_SCD_Y, y_addr, uv_addr, + AWB_TYPE); + break; default: break; } @@ -700,6 +755,11 @@ static void vin_buf_update_on_new(struct vin_line *line, struct vin_output *output, struct stfcamss_buffer *new_buf) { +#ifdef VIN_TWO_BUFFER + struct stf_vin2_dev *vin_dev = line_to_vin2_dev(line); + int inactive_idx; +#endif + switch (output->state) { case VIN_OUTPUT_SINGLE: #ifdef VIN_TWO_BUFFER @@ -798,6 +858,7 @@ static void vin_change_buffer(struct vin_line *line) dma_addr_t *new_addr; unsigned long flags; u32 active_index; + int scd_type; if (output->state == VIN_OUTPUT_OFF || output->state == VIN_OUTPUT_STOPPING @@ -857,22 +918,65 @@ static void vin_change_buffer(struct vin_line *line) vin_dev->hw_ops->vin_wr_set_pong_addr(vin_dev, new_addr[0]); #endif - break; - case VIN_LINE_ISP0: // isp0 - case VIN_LINE_ISP1: // isp1 - vin_dev->hw_ops->vin_isp_set_yuv_addr(vin_dev, - line->id - VIN_LINE_ISP0, - new_addr[0], new_addr[1]); - break; - case VIN_LINE_ISP0_RAW: // isp0_raw - case VIN_LINE_ISP1_RAW: // isp1_raw - vin_dev->hw_ops->vin_isp_set_raw_addr(vin_dev, - line->id - VIN_LINE_ISP0_RAW, new_addr[0]); - break; - - default: - break; - } + break; + case VIN_LINE_ISP0: // isp0 + case VIN_LINE_ISP1: // isp1 + vin_dev->hw_ops->vin_isp_set_yuv_addr(vin_dev, + line->id - VIN_LINE_ISP0, + new_addr[0], new_addr[1]); + break; + case VIN_LINE_ISP0_SS0: // isp0_ss0 + case VIN_LINE_ISP1_SS0: // isp1_ss0 + vin_dev->hw_ops->vin_isp_set_ss0_addr(vin_dev, + line->id - VIN_LINE_ISP0_SS0, + new_addr[0], new_addr[1]); + break; + case VIN_LINE_ISP0_SS1: // isp0_ss1 + case VIN_LINE_ISP1_SS1: // isp1_ss1 + vin_dev->hw_ops->vin_isp_set_ss1_addr(vin_dev, + line->id - VIN_LINE_ISP0_SS1, + new_addr[0], new_addr[1]); + break; + case VIN_LINE_ISP0_ITIW: // isp0_itiw + case VIN_LINE_ISP1_ITIW: // isp1_itiw + vin_dev->hw_ops->vin_isp_set_itiw_addr(vin_dev, + line->id - VIN_LINE_ISP0_ITIW, + new_addr[0], new_addr[1]); + break; + case VIN_LINE_ISP0_ITIR: // isp0_itir + case VIN_LINE_ISP1_ITIR: // isp1_itir + vin_dev->hw_ops->vin_isp_set_itir_addr(vin_dev, + line->id - VIN_LINE_ISP0_ITIR, + new_addr[0], new_addr[1]); + break; + case VIN_LINE_ISP0_RAW: // isp0_raw + case VIN_LINE_ISP1_RAW: // isp1_raw + vin_dev->hw_ops->vin_isp_set_raw_addr(vin_dev, + line->id - VIN_LINE_ISP0_RAW, new_addr[0]); + break; + case VIN_LINE_ISP0_SCD_Y: // isp0_scd_y + case VIN_LINE_ISP1_SCD_Y: // isp1_scd_y + scd_type = vin_dev->hw_ops->vin_isp_get_scd_type(vin_dev, + line->id - VIN_LINE_ISP0_SCD_Y); + ready_buf->vb.flags &= ~(V4L2_BUF_FLAG_PFRAME | V4L2_BUF_FLAG_BFRAME); + if (scd_type == AWB_TYPE) + ready_buf->vb.flags |= V4L2_BUF_FLAG_PFRAME; + else + ready_buf->vb.flags |= V4L2_BUF_FLAG_BFRAME; + if (!output->frame_skip) { + output->frame_skip = ISP_AWB_OECF_SKIP_FRAME; + scd_type = scd_type == AWB_TYPE ? OECF_TYPE : AWB_TYPE; + } else { + output->frame_skip--; + scd_type = scd_type == AWB_TYPE ? AWB_TYPE : OECF_TYPE; + } + vin_dev->hw_ops->vin_isp_set_scd_addr(vin_dev, + line->id - VIN_LINE_ISP0_SCD_Y, new_addr[0], new_addr[1], + scd_type); + break; + default: + break; + } vin_buf_add_ready(output, ready_buf); } diff --git a/drivers/media/platform/starfive/v4l2_driver/stf_vin.h b/drivers/media/platform/starfive/v4l2_driver/stf_vin.h index 584d1e6..92a57b6 100755 --- a/drivers/media/platform/starfive/v4l2_driver/stf_vin.h +++ b/drivers/media/platform/starfive/v4l2_driver/stf_vin.h @@ -13,6 +13,8 @@ #include "stf_video.h" +#define STF_VIN_NAME "stf_vin" + #define STF_VIN_PAD_SINK 0 #define STF_VIN_PAD_SRC 1 #define STF_VIN_PADS_NUM 2 @@ -47,9 +49,19 @@ enum vin_line_id { VIN_LINE_WR = 0, VIN_LINE_ISP0 = 1, VIN_LINE_ISP1 = 2, - VIN_LINE_ISP0_RAW = 3, - VIN_LINE_ISP1_RAW = 4, - VIN_LINE_MAX = 5 + VIN_LINE_ISP0_SS0 = 3, + VIN_LINE_ISP1_SS0 = 4, + VIN_LINE_ISP0_SS1 = 5, + VIN_LINE_ISP1_SS1 = 6, + VIN_LINE_ISP0_ITIW = 7, + VIN_LINE_ISP1_ITIW = 8, + VIN_LINE_ISP0_ITIR = 9, + VIN_LINE_ISP1_ITIR = 10, + VIN_LINE_ISP0_RAW = 11, + VIN_LINE_ISP1_RAW = 12, + VIN_LINE_ISP0_SCD_Y = 13, + VIN_LINE_ISP1_SCD_Y = 14, + VIN_LINE_MAX = 15 }; enum subdev_type; @@ -94,6 +106,22 @@ struct vin_hw_ops { dma_addr_t y_addr, dma_addr_t uv_addr); void (*vin_isp_set_raw_addr)(struct stf_vin2_dev *vin_dev, int isp_id, dma_addr_t raw_addr); + void (*vin_isp_set_ss0_addr)(struct stf_vin2_dev *vin_dev, + int isp_id, + dma_addr_t y_addr, dma_addr_t uv_addr); + void (*vin_isp_set_ss1_addr)(struct stf_vin2_dev *vin_dev, + int isp_id, + dma_addr_t y_addr, dma_addr_t uv_addr); + void (*vin_isp_set_itiw_addr)(struct stf_vin2_dev *vin_dev, + int isp_id, + dma_addr_t y_addr, dma_addr_t uv_addr); + void (*vin_isp_set_itir_addr)(struct stf_vin2_dev *vin_dev, + int isp_id, + dma_addr_t y_addr, dma_addr_t uv_addr); + void (*vin_isp_set_scd_addr)(struct stf_vin2_dev *vin_dev, + int isp_id, dma_addr_t yhist_addr, + dma_addr_t scd_addr, int scd_type); + int (*vin_isp_get_scd_type)(struct stf_vin2_dev *vin_dev, int isp_id); irqreturn_t (*vin_wr_irq_handler)(int irq, void *priv); irqreturn_t (*vin_isp_irq_handler)(int irq, void *priv); irqreturn_t (*vin_isp_csi_irq_handler)(int irq, void *priv); diff --git a/drivers/media/platform/starfive/v4l2_driver/stf_vin_hw_ops.c b/drivers/media/platform/starfive/v4l2_driver/stf_vin_hw_ops.c index 3766589..c32486f 100644 --- a/drivers/media/platform/starfive/v4l2_driver/stf_vin_hw_ops.c +++ b/drivers/media/platform/starfive/v4l2_driver/stf_vin_hw_ops.c @@ -39,7 +39,7 @@ static irqreturn_t stf_vin_isp_irq_handler(int irq, void *priv) struct stf_vin2_dev *vin_dev = priv; struct stf_vin_dev *vin = vin_dev->stfcamss->vin; void __iomem *ispbase; - u32 int_status; + u32 int_status, value; int isp_id = irq == vin->isp0_irq ? 0 : 1; if (isp_id == 0) @@ -50,15 +50,35 @@ static irqreturn_t stf_vin_isp_irq_handler(int irq, void *priv) int_status = reg_read(ispbase, ISP_REG_ISP_CTRL_0); if (int_status & BIT(24)) { + if ((int_status & BIT(11))) + vin_dev->hw_ops->isr_buffer_done( + &vin_dev->line[VIN_LINE_ISP0_SS0 + isp_id], ¶ms); + + if ((int_status & BIT(12))) + vin_dev->hw_ops->isr_buffer_done( + &vin_dev->line[VIN_LINE_ISP0_SS1 + isp_id], ¶ms); + if ((int_status & BIT(20))) vin_dev->hw_ops->isr_buffer_done( &vin_dev->line[VIN_LINE_ISP0 + isp_id], ¶ms); + value = reg_read(ispbase, ISP_REG_ITIDPSR); + if ((value & BIT(17))) + vin_dev->hw_ops->isr_buffer_done( + &vin_dev->line[VIN_LINE_ISP0_ITIW + isp_id], ¶ms); + if ((value & BIT(16))) + vin_dev->hw_ops->isr_buffer_done( + &vin_dev->line[VIN_LINE_ISP0_ITIR + isp_id], ¶ms); + #ifndef ISP_USE_CSI_AND_SC_DONE_INTERRUPT if (int_status & BIT(25)) vin_dev->hw_ops->isr_buffer_done( &vin_dev->line[VIN_LINE_ISP0_RAW + isp_id], ¶ms); + if (int_status & BIT(26)) + vin_dev->hw_ops->isr_buffer_done( + &vin_dev->line[VIN_LINE_ISP0_SCD_Y + isp_id], ¶ms); + /* clear interrupt */ reg_write(ispbase, ISP_REG_ISP_CTRL_0, (int_status & ~EN_INT_ALL) | EN_INT_ISP_DONE | EN_INT_CSI_DONE | EN_INT_SC_DONE); @@ -75,6 +95,7 @@ static irqreturn_t stf_vin_isp_irq_handler(int irq, void *priv) static irqreturn_t stf_vin_isp_csi_irq_handler(int irq, void *priv) { + static struct vin_params params; struct stf_vin2_dev *vin_dev = priv; struct stf_vin_dev *vin = vin_dev->stfcamss->vin; void __iomem *ispbase; @@ -89,6 +110,9 @@ static irqreturn_t stf_vin_isp_csi_irq_handler(int irq, void *priv) int_status = reg_read(ispbase, ISP_REG_ISP_CTRL_0); if (int_status & BIT(25)) { + vin_dev->hw_ops->isr_buffer_done( + &vin_dev->line[VIN_LINE_ISP0_RAW + isp_id], ¶ms); + /* clear interrupt */ reg_write(ispbase, ISP_REG_ISP_CTRL_0, (int_status & ~EN_INT_ALL) | EN_INT_CSI_DONE); @@ -100,6 +124,7 @@ static irqreturn_t stf_vin_isp_csi_irq_handler(int irq, void *priv) static irqreturn_t stf_vin_isp_scd_irq_handler(int irq, void *priv) { + static struct vin_params params; struct stf_vin2_dev *vin_dev = priv; struct stf_vin_dev *vin = vin_dev->stfcamss->vin; void __iomem *ispbase; @@ -114,6 +139,9 @@ static irqreturn_t stf_vin_isp_scd_irq_handler(int irq, void *priv) int_status = reg_read(ispbase, ISP_REG_ISP_CTRL_0); if (int_status & BIT(26)) { + vin_dev->hw_ops->isr_buffer_done( + &vin_dev->line[VIN_LINE_ISP0_SCD_Y + isp_id], ¶ms); + /* clear interrupt */ reg_write(ispbase, ISP_REG_ISP_CTRL_0, (int_status & ~EN_INT_ALL) | EN_INT_SC_DONE); } else @@ -140,14 +168,31 @@ static irqreturn_t stf_vin_isp_irq_csiline_handler(int irq, void *priv) int_status = reg_read(ispbase, ISP_REG_ISP_CTRL_0); if (int_status & BIT(27)) { if (!atomic_read(&isp_dev->shadow_count)) { + if ((int_status & BIT(11))) + vin_dev->hw_ops->isr_change_buffer( + &vin_dev->line[VIN_LINE_ISP0_SS0 + isp_id]); + if ((int_status & BIT(12))) + vin_dev->hw_ops->isr_change_buffer( + &vin_dev->line[VIN_LINE_ISP0_SS1 + isp_id]); if ((int_status & BIT(20))) vin_dev->hw_ops->isr_change_buffer( &vin_dev->line[VIN_LINE_ISP0 + isp_id]); + value = reg_read(ispbase, ISP_REG_ITIDPSR); + if ((value & BIT(17))) + vin_dev->hw_ops->isr_change_buffer( + &vin_dev->line[VIN_LINE_ISP0_ITIW + isp_id]); + if ((value & BIT(16))) + vin_dev->hw_ops->isr_change_buffer( + &vin_dev->line[VIN_LINE_ISP0_ITIR + isp_id]); + value = reg_read(ispbase, ISP_REG_CSI_MODULE_CFG); if ((value & BIT(19))) vin_dev->hw_ops->isr_change_buffer( &vin_dev->line[VIN_LINE_ISP0_RAW + isp_id]); + if ((value & BIT(17))) + vin_dev->hw_ops->isr_change_buffer( + &vin_dev->line[VIN_LINE_ISP0_SCD_Y + isp_id]); /* shadow update */ reg_set_bit(ispbase, ISP_REG_CSIINTS_ADDR, 0x30000, 0x30000); @@ -323,14 +368,76 @@ void stf_vin_isp_set_yuv_addr(struct stf_vin2_dev *vin_dev, int isp_id, void stf_vin_isp_set_raw_addr(struct stf_vin2_dev *vin_dev, int isp_id, dma_addr_t raw_addr) { -#ifdef UNUSED_CODE struct stf_vin_dev *vin = vin_dev->stfcamss->vin; void __iomem *ispbase = isp_id ? vin->isp_isp1_base : vin->isp_isp0_base; reg_write(ispbase, ISP_REG_DUMP_CFG_0, raw_addr); - reg_set_bit(ispbase, ISP_REG_CSIINTS_ADDR, 0x3FFFF, 0x3000a); -#endif +} + +void stf_vin_isp_set_ss0_addr(struct stf_vin2_dev *vin_dev, int isp_id, + dma_addr_t y_addr, dma_addr_t uv_addr) +{ + struct stf_vin_dev *vin = vin_dev->stfcamss->vin; + void __iomem *ispbase = + isp_id ? vin->isp_isp1_base : vin->isp_isp0_base; + + reg_write(ispbase, ISP_REG_SS0AY, y_addr); + reg_write(ispbase, ISP_REG_SS0AUV, uv_addr); +} + +void stf_vin_isp_set_ss1_addr(struct stf_vin2_dev *vin_dev, int isp_id, + dma_addr_t y_addr, dma_addr_t uv_addr) +{ + struct stf_vin_dev *vin = vin_dev->stfcamss->vin; + void __iomem *ispbase = + isp_id ? vin->isp_isp1_base : vin->isp_isp0_base; + + reg_write(ispbase, ISP_REG_SS1AY, y_addr); + reg_write(ispbase, ISP_REG_SS1AUV, uv_addr); +} + +void stf_vin_isp_set_itiw_addr(struct stf_vin2_dev *vin_dev, int isp_id, + dma_addr_t y_addr, dma_addr_t uv_addr) +{ + struct stf_vin_dev *vin = vin_dev->stfcamss->vin; + void __iomem *ispbase = + isp_id ? vin->isp_isp1_base : vin->isp_isp0_base; + + reg_write(ispbase, ISP_REG_ITIDWYSAR, y_addr); + reg_write(ispbase, ISP_REG_ITIDWUSAR, uv_addr); +} + +void stf_vin_isp_set_itir_addr(struct stf_vin2_dev *vin_dev, int isp_id, + dma_addr_t y_addr, dma_addr_t uv_addr) +{ + struct stf_vin_dev *vin = vin_dev->stfcamss->vin; + void __iomem *ispbase = + isp_id ? vin->isp_isp1_base : vin->isp_isp0_base; + + reg_write(ispbase, ISP_REG_ITIDRYSAR, y_addr); + reg_write(ispbase, ISP_REG_ITIDRUSAR, uv_addr); +} + +int stf_vin_isp_get_scd_type(struct stf_vin2_dev *vin_dev, int isp_id) +{ + struct stf_vin_dev *vin = vin_dev->stfcamss->vin; + void __iomem *ispbase = + isp_id ? vin->isp_isp1_base : vin->isp_isp0_base; + + return (reg_read(ispbase, ISP_REG_SC_CFG_1) & (0x3 << 30)) >> 30; +} + +void stf_vin_isp_set_scd_addr(struct stf_vin2_dev *vin_dev, int isp_id, + dma_addr_t yhist_addr, dma_addr_t scd_addr, int scd_type) +{ + struct stf_vin_dev *vin = vin_dev->stfcamss->vin; + void __iomem *ispbase = + isp_id ? vin->isp_isp1_base : vin->isp_isp0_base; + + reg_set_bit(ispbase, ISP_REG_SC_CFG_1, 0x3 << 30, scd_type << 30); + reg_write(ispbase, ISP_REG_SCD_CFG_0, scd_addr); + reg_write(ispbase, ISP_REG_YHIST_CFG_4, yhist_addr); } void dump_vin_reg(void *__iomem regbase) @@ -362,6 +469,12 @@ struct vin_hw_ops vin_ops = { .vin_wr_set_pong_addr = stf_vin_wr_set_pong_addr, .vin_isp_set_yuv_addr = stf_vin_isp_set_yuv_addr, .vin_isp_set_raw_addr = stf_vin_isp_set_raw_addr, + .vin_isp_set_ss0_addr = stf_vin_isp_set_ss0_addr, + .vin_isp_set_ss1_addr = stf_vin_isp_set_ss1_addr, + .vin_isp_set_itiw_addr = stf_vin_isp_set_itiw_addr, + .vin_isp_set_itir_addr = stf_vin_isp_set_itir_addr, + .vin_isp_set_scd_addr = stf_vin_isp_set_scd_addr, + .vin_isp_get_scd_type = stf_vin_isp_get_scd_type, .vin_wr_irq_handler = stf_vin_wr_irq_handler, .vin_isp_irq_handler = stf_vin_isp_irq_handler, .vin_isp_csi_irq_handler = stf_vin_isp_csi_irq_handler, diff --git a/drivers/media/platform/starfive/v4l2_driver/stfcamss.c b/drivers/media/platform/starfive/v4l2_driver/stfcamss.c index c12ce0a..40f8cd9 100644 --- a/drivers/media/platform/starfive/v4l2_driver/stfcamss.c +++ b/drivers/media/platform/starfive/v4l2_driver/stfcamss.c @@ -425,7 +425,7 @@ static int stfcamss_register_subdevices(struct stfcamss *stfcamss) STF_CSIPHY_PAD_SRC, &csi_dev[j].subdev.entity, STF_CSI_PAD_SINK, - 0); + MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED); if (ret < 0) { st_err(ST_CAMSS, "Failed to link %s->%s entities: %d\n", @@ -455,7 +455,67 @@ static int stfcamss_register_subdevices(struct stfcamss *stfcamss) ret = media_create_pad_link( &isp_dev[i].subdev.entity, - STF_ISP_PAD_SRC, + STF_ISP_PAD_SRC_SS0, + &vin_dev->line[i + VIN_LINE_ISP0_SS0].subdev.entity, + STF_VIN_PAD_SINK, + 0); + if (ret < 0) { + st_err(ST_CAMSS, + "Failed to link %s->%s entities: %d\n", + isp_dev[i].subdev.entity.name, + vin_dev->line[i + VIN_LINE_ISP0_SS0] + .subdev.entity.name, + ret); + goto err_link; + } + ret = media_create_pad_link( + &isp_dev[i].subdev.entity, + STF_ISP_PAD_SRC_SS1, + &vin_dev->line[i + VIN_LINE_ISP0_SS1].subdev.entity, + STF_VIN_PAD_SINK, + 0); + if (ret < 0) { + st_err(ST_CAMSS, + "Failed to link %s->%s entities: %d\n", + isp_dev[i].subdev.entity.name, + vin_dev->line[i + VIN_LINE_ISP0_SS1] + .subdev.entity.name, + ret); + goto err_link; + } + ret = media_create_pad_link( + &isp_dev[i].subdev.entity, + STF_ISP_PAD_SRC_ITIW, + &vin_dev->line[i + VIN_LINE_ISP0_ITIW].subdev.entity, + STF_VIN_PAD_SINK, + 0); + if (ret < 0) { + st_err(ST_CAMSS, + "Failed to link %s->%s entities: %d\n", + isp_dev[i].subdev.entity.name, + vin_dev->line[i + VIN_LINE_ISP0_ITIW] + .subdev.entity.name, + ret); + goto err_link; + } + ret = media_create_pad_link( + &isp_dev[i].subdev.entity, + STF_ISP_PAD_SRC_ITIR, + &vin_dev->line[i + VIN_LINE_ISP0_ITIR].subdev.entity, + STF_VIN_PAD_SINK, + 0); + if (ret < 0) { + st_err(ST_CAMSS, + "Failed to link %s->%s entities: %d\n", + isp_dev[i].subdev.entity.name, + vin_dev->line[i + VIN_LINE_ISP0_ITIR] + .subdev.entity.name, + ret); + goto err_link; + } + ret = media_create_pad_link( + &isp_dev[i].subdev.entity, + STF_ISP_PAD_SRC_RAW, &vin_dev->line[i + VIN_LINE_ISP0_RAW].subdev.entity, STF_VIN_PAD_SINK, 0); @@ -468,7 +528,21 @@ static int stfcamss_register_subdevices(struct stfcamss *stfcamss) ret); goto err_link; } - + ret = media_create_pad_link( + &isp_dev[i].subdev.entity, + STF_ISP_PAD_SRC_SCD_Y, + &vin_dev->line[i + VIN_LINE_ISP0_SCD_Y].subdev.entity, + STF_VIN_PAD_SINK, + 0); + if (ret < 0) { + st_err(ST_CAMSS, + "Failed to link %s->%s entities: %d\n", + isp_dev[i].subdev.entity.name, + vin_dev->line[i + VIN_LINE_ISP0_SCD_Y] + .subdev.entity.name, + ret); + goto err_link; + } ret = media_create_pad_link( &dvp_dev->subdev.entity, STF_DVP_PAD_SRC, @@ -688,7 +762,6 @@ static int stfcamss_subdev_notifier_complete( static const struct v4l2_async_notifier_operations stfcamss_subdev_notifier_ops = { .bound = stfcamss_subdev_notifier_bound, - // .complete = stfcamss_subdev_notifier_complete, }; static const struct media_device_ops stfcamss_media_ops = { diff --git a/drivers/media/platform/starfive/v4l2_driver/stfcamss.h b/drivers/media/platform/starfive/v4l2_driver/stfcamss.h index 095d210..fe6ebc3 100755 --- a/drivers/media/platform/starfive/v4l2_driver/stfcamss.h +++ b/drivers/media/platform/starfive/v4l2_driver/stfcamss.h @@ -84,6 +84,7 @@ struct stfcamss { struct stf_vin_dev *vin; // stfcamss phy res struct v4l2_device v4l2_dev; struct media_device media_dev; + struct media_pipeline pipe; struct device *dev; struct stf_vin2_dev *vin_dev; // subdev struct stf_dvp_dev *dvp_dev; // subdev