{
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;
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;
* 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:
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;
}
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;
}
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;
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;
}
#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,
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;
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;
{ { 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)
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]);
|| 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);
|| 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;
}
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);
}
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);
struct v4l2_subdev *subdev;
int ret;
- subdev = get_senname(file, __func__);
+ subdev = get_senname(file, (char *)__func__);
if (!subdev)
return -EINVAL;
struct v4l2_fh *vfh;
int ret;
- subdev = get_senname(file, __func__);
+ subdev = get_senname(file, (char *)__func__);
if (!subdev)
return -EINVAL;
struct v4l2_subdev *subdev;
int ret;
- subdev = get_senname(file, __func__);
+ subdev = get_senname(file, (char *)__func__);
if (!subdev)
return -EINVAL;
struct v4l2_subdev *subdev;
int ret;
- subdev = get_senname(file, __func__);
+ subdev = get_senname(file, (char *)__func__);
if (!subdev)
return -EINVAL;
struct v4l2_fh *vfh;
int ret;
- subdev = get_senname(file, __func__);
+ subdev = get_senname(file, (char *)__func__);
if (!subdev)
return -EINVAL;
struct v4l2_fh *vfh;
int ret;
- subdev = get_senname(file, __func__);
+ subdev = get_senname(file, (char *)__func__);
if (!subdev)
return -EINVAL;
return ret;
}
+
#ifdef UNUSED_CODE
static int video_querymenu(struct file *file, void *fh,
struct v4l2_querymenu *qm)
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;
.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 = {
.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)
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,
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;
}
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));
#include <media/v4l2-fh.h>
#include <media/v4l2-ioctl.h>
-#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;
#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
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;
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;
{
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;
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 */
fmt->which);
}
+out:
return 0;
}
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];
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;
}
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
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
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);
}
#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
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;
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);
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)
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);
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;
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);
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;
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
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);
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)
.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,
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",
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);
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,
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 = {
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