diff --git a/drivers/staging/media/starfive/camss/stf-camss.c b/drivers/staging/media/starfive/camss/stf-camss.c
index 81fc39f20615..90ac8b67c76e 100644
--- a/drivers/staging/media/starfive/camss/stf-camss.c
+++ b/drivers/staging/media/starfive/camss/stf-camss.c
@@ -126,6 +126,7 @@ static int stfcamss_of_parse_ports(struct stfcamss *stfcamss)
 static int stfcamss_register_devs(struct stfcamss *stfcamss)
 {
 	struct stf_capture *cap_yuv = &stfcamss->captures[STF_CAPTURE_YUV];
+	struct stf_capture *cap_raw = &stfcamss->captures[STF_CAPTURE_RAW];
 	struct stf_isp_dev *isp_dev = &stfcamss->isp_dev;
 	int ret;
 
@@ -150,8 +151,18 @@ static int stfcamss_register_devs(struct stfcamss *stfcamss)
 
 	cap_yuv->video.source_subdev = &isp_dev->subdev;
 
+	ret = media_create_pad_link(&isp_dev->subdev.entity, STF_ISP_PAD_SRC_RAW,
+				    &cap_raw->video.vdev.entity, 0, 0);
+	if (ret)
+		goto err_rm_links0;
+
+	cap_raw->video.source_subdev = &isp_dev->subdev;
+
 	return ret;
 
+err_rm_links0:
+	media_entity_remove_links(&isp_dev->subdev.entity);
+	media_entity_remove_links(&cap_yuv->video.vdev.entity);
 err_cap_unregister:
 	stf_capture_unregister(stfcamss);
 err_isp_unregister:
@@ -162,6 +173,14 @@ static int stfcamss_register_devs(struct stfcamss *stfcamss)
 
 static void stfcamss_unregister_devs(struct stfcamss *stfcamss)
 {
+	struct stf_capture *cap_yuv = &stfcamss->captures[STF_CAPTURE_YUV];
+	struct stf_capture *cap_raw = &stfcamss->captures[STF_CAPTURE_RAW];
+	struct stf_isp_dev *isp_dev = &stfcamss->isp_dev;
+
+	media_entity_remove_links(&isp_dev->subdev.entity);
+	media_entity_remove_links(&cap_raw->video.vdev.entity);
+	media_entity_remove_links(&cap_yuv->video.vdev.entity);
+
 	stf_isp_unregister(&stfcamss->isp_dev);
 	stf_capture_unregister(stfcamss);
 }
diff --git a/drivers/staging/media/starfive/camss/stf-capture.c b/drivers/staging/media/starfive/camss/stf-capture.c
index 5c91126d5132..a5f10ec57782 100644
--- a/drivers/staging/media/starfive/camss/stf-capture.c
+++ b/drivers/staging/media/starfive/camss/stf-capture.c
@@ -12,6 +12,7 @@
 static const char * const stf_cap_names[] = {
 	"capture_dump",
 	"capture_yuv",
+	"capture_raw",
 };
 
 static const struct stfcamss_format_info stf_wr_fmts[] = {
@@ -55,6 +56,37 @@ static const struct stfcamss_format_info stf_isp_fmts[] = {
 	},
 };
 
+static const struct stfcamss_format_info stf_isp_raw_fmts[] = {
+	{
+		.code = MEDIA_BUS_FMT_SRGGB12_1X12,
+		.pixelformat = V4L2_PIX_FMT_SRGGB12,
+		.planes = 1,
+		.vsub = { 1 },
+		.bpp = 12,
+	},
+	{
+		.code = MEDIA_BUS_FMT_SGRBG12_1X12,
+		.pixelformat = V4L2_PIX_FMT_SGRBG12,
+		.planes = 1,
+		.vsub = { 1 },
+		.bpp = 12,
+	},
+	{
+		.code = MEDIA_BUS_FMT_SGBRG12_1X12,
+		.pixelformat = V4L2_PIX_FMT_SGBRG12,
+		.planes = 1,
+		.vsub = { 1 },
+		.bpp = 12,
+	},
+	{
+		.code = MEDIA_BUS_FMT_SBGGR12_1X12,
+		.pixelformat = V4L2_PIX_FMT_SBGGR12,
+		.planes = 1,
+		.vsub = { 1 },
+		.bpp = 12,
+	},
+};
+
 static inline struct stf_capture *to_stf_capture(struct stfcamss_video *video)
 {
 	return container_of(video, struct stf_capture, video);
@@ -73,6 +105,11 @@ static void stf_set_yuv_addr(struct stfcamss *stfcamss,
 	stf_isp_reg_write(stfcamss, ISP_REG_UV_PLANE_START_ADDR, uv_addr);
 }
 
+static void stf_set_raw_addr(struct stfcamss *stfcamss, dma_addr_t raw_addr)
+{
+	stf_isp_reg_write(stfcamss, ISP_REG_DUMP_CFG_0, raw_addr);
+}
+
 static void stf_init_addrs(struct stfcamss_video *video)
 {
 	struct stf_capture *cap = to_stf_capture(video);
@@ -91,6 +128,8 @@ static void stf_init_addrs(struct stfcamss_video *video)
 		stf_set_dump_addr(video->stfcamss, addr0);
 	else if (cap->type == STF_CAPTURE_YUV)
 		stf_set_yuv_addr(video->stfcamss, addr0, addr1);
+	else
+		stf_set_raw_addr(video->stfcamss, addr0);
 }
 
 static struct stfcamss_buffer *stf_buf_get_pending(struct stf_v_buf *output)
@@ -250,7 +289,6 @@ static void stf_capture_init(struct stfcamss *stfcamss, struct stf_capture *cap)
 
 	cap->video.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 	cap->video.stfcamss = stfcamss;
-	cap->video.bpl_alignment = 16 * 8;
 
 	if (cap->type == STF_CAPTURE_DUMP) {
 		cap->video.formats = stf_wr_fmts;
@@ -260,6 +298,10 @@ static void stf_capture_init(struct stfcamss *stfcamss, struct stf_capture *cap)
 		cap->video.formats = stf_isp_fmts;
 		cap->video.nformats = ARRAY_SIZE(stf_isp_fmts);
 		cap->video.bpl_alignment = 1;
+	} else {
+		cap->video.formats = stf_isp_raw_fmts;
+		cap->video.nformats = ARRAY_SIZE(stf_isp_raw_fmts);
+		cap->video.bpl_alignment = STFCAMSS_FRAME_WIDTH_ALIGN_128;
 	}
 }
 
@@ -441,6 +483,8 @@ static void stf_change_buffer(struct stf_v_buf *output)
 			stf_set_dump_addr(stfcamss, new_addr[0]);
 		else if (cap->type == STF_CAPTURE_YUV)
 			stf_set_yuv_addr(stfcamss, new_addr[0], new_addr[1]);
+		else
+			stf_set_raw_addr(stfcamss, new_addr[0]);
 
 		stf_buf_add_ready(output, ready_buf);
 	}
@@ -468,6 +512,7 @@ irqreturn_t stf_wr_irq_handler(int irq, void *priv)
 irqreturn_t stf_isp_irq_handler(int irq, void *priv)
 {
 	struct stfcamss *stfcamss = priv;
+	struct stf_capture *cap_raw = &stfcamss->captures[STF_CAPTURE_RAW];
 	struct stf_capture *cap = &stfcamss->captures[STF_CAPTURE_YUV];
 	u32 status;
 
@@ -476,6 +521,9 @@ irqreturn_t stf_isp_irq_handler(int irq, void *priv)
 		if (status & ISPC_ENUO)
 			stf_buf_done(&cap->buffers);
 
+		if (status & ISPC_CSI)
+			stf_buf_done(&cap_raw->buffers);
+
 		stf_isp_reg_write(stfcamss, ISP_REG_ISP_CTRL_0,
 				  (status & ~ISPC_INT_ALL_MASK) |
 				  ISPC_ISP | ISPC_CSI | ISPC_SC);
@@ -487,14 +535,20 @@ irqreturn_t stf_isp_irq_handler(int irq, void *priv)
 irqreturn_t stf_line_irq_handler(int irq, void *priv)
 {
 	struct stfcamss *stfcamss = priv;
+	struct stf_capture *cap_raw = &stfcamss->captures[STF_CAPTURE_RAW];
 	struct stf_capture *cap = &stfcamss->captures[STF_CAPTURE_YUV];
 	u32 status;
+	u32 value;
 
 	status = stf_isp_reg_read(stfcamss, ISP_REG_ISP_CTRL_0);
 	if (status & ISPC_LINE) {
 		if (atomic_dec_if_positive(&cap->buffers.frame_skip) < 0) {
 			if ((status & ISPC_ENUO))
 				stf_change_buffer(&cap->buffers);
+
+			value = stf_isp_reg_read(stfcamss, ISP_REG_CSI_MODULE_CFG);
+			if (value & CSI_DUMP_EN)
+				stf_change_buffer(&cap_raw->buffers);
 		}
 
 		stf_isp_reg_set_bit(stfcamss, ISP_REG_CSIINTS,
@@ -571,9 +625,11 @@ void stf_capture_unregister(struct stfcamss *stfcamss)
 {
 	struct stf_capture *cap_dump = &stfcamss->captures[STF_CAPTURE_DUMP];
 	struct stf_capture *cap_yuv = &stfcamss->captures[STF_CAPTURE_YUV];
+	struct stf_capture *cap_raw = &stfcamss->captures[STF_CAPTURE_RAW];
 
 	stf_capture_unregister_one(cap_dump);
 	stf_capture_unregister_one(cap_yuv);
+	stf_capture_unregister_one(cap_raw);
 }
 
 int stf_capture_register(struct stfcamss *stfcamss,
diff --git a/drivers/staging/media/starfive/camss/stf-video.h b/drivers/staging/media/starfive/camss/stf-video.h
index 90c73c0dee89..cad861aae31c 100644
--- a/drivers/staging/media/starfive/camss/stf-video.h
+++ b/drivers/staging/media/starfive/camss/stf-video.h
@@ -37,6 +37,7 @@ enum stf_v_line_id {
 enum stf_capture_type {
 	STF_CAPTURE_DUMP = 0,
 	STF_CAPTURE_YUV,
+	STF_CAPTURE_RAW,
 	STF_CAPTURE_NUM,
 };
 
