Hi,
This series is the v8 series that attempts to support the Camera Subsystem
found on StarFive JH7110 SoC.
The following are the media graph for the device and the v4l2-compliance
output.
===========================================================================
[the media graph]:
digraph board {
rankdir=TB
n00000001 [label="{{<port0> 0} | stf_isp\n/dev/v4l-subdev0 | {<port1> 1}}", shape=Mrecord, style=filled, fillcolor=green]
n00000001:port1 -> n00000008 [style=dashed]
n00000004 [label="capture_raw\n/dev/video0", shape=box, style=filled, fillcolor=yellow]
n00000008 [label="capture_yuv\n/dev/video1", shape=box, style=filled, fillcolor=yellow]
n0000000e [label="{{<port0> 0} | cdns_csi2rx.19800000.csi-bridge\n | {<port1> 1 | <port2> 2 | <port3> 3 | <port4> 4}}", shape=Mrecord, style=filled, fillcolor=green]
n0000000e:port1 -> n00000001:port0 [style=dashed]
n0000000e:port1 -> n00000004 [style=dashed]
n00000018 [label="{{} | imx219 6-0010\n/dev/v4l-subdev1 | {<port0> 0}}", shape=Mrecord, style=filled, fillcolor=green]
n00000018:port0 -> n0000000e:port0 [style=bold]
}
[the device topology]:
Media controller API version 6.5.0
Media device information
------------------------
driver starfive-camss
model Starfive Camera Subsystem
serial
bus info platform:19840000.camss
hw revision 0x0
driver version 6.5.0
Device topology
- entity 1: stf_isp (2 pads, 2 links)
type V4L2 subdev subtype Unknown flags 0
device node name /dev/v4l-subdev0
pad0: Sink
[fmt:SRGGB10_1X10/1920x1080 field:none colorspace:srgb
crop.bounds:(0,0)/1920x1080
crop:(0,0)/1920x1080]
<- "cdns_csi2rx.19800000.csi-bridge":1 []
pad1: Source
[fmt:YUYV8_1_5X8/1920x1080 field:none colorspace:srgb
crop.bounds:(0,0)/1920x1080
crop:(0,0)/1920x1080]
-> "capture_yuv":0 []
- entity 4: capture_raw (1 pad, 1 link)
type Node subtype V4L flags 0
device node name /dev/video0
pad0: Sink
<- "cdns_csi2rx.19800000.csi-bridge":1 []
- entity 8: capture_yuv (1 pad, 1 link)
type Node subtype V4L flags 0
device node name /dev/video1
pad0: Sink
<- "stf_isp":1 []
- entity 14: cdns_csi2rx.19800000.csi-bridge (5 pads, 3 links)
type V4L2 subdev subtype Unknown flags 0
pad0: Sink
<- "imx219 6-0010":0 [ENABLED,IMMUTABLE]
pad1: Source
-> "stf_isp":0 []
-> "capture_raw":0 []
pad2: Source
pad3: Source
pad4: Source
- entity 24: imx219 6-0010 (1 pad, 1 link)
type V4L2 subdev subtype Sensor flags 0
device node name /dev/v4l-subdev1
pad0: Source
[fmt:SRGGB10_1X10/3280x2464 field:none colorspace:srgb xfer:srgb ycbcr:601 quantization:full-range
crop.bounds:(8,8)/3280x2464
crop:(8,8)/3280x2464]
-> "cdns_csi2rx.19800000.csi-bridge":0 [ENABLED,IMMUTABLE]
===========================================================================
[the v4l2-compliance output]:
v4l2-compliance 1.24.1, 64 bits, 64-bit time_t
Compliance test for stf camss device /dev/video1:
Driver Info:
Driver name : stf camss
Card type : Starfive Camera Subsystem
Bus info : platform:19840000.camss
Driver version : 6.5.0
Capabilities : 0x84200001
Video Capture
Streaming
Extended Pix Format
Device Capabilities
Device Caps : 0x04200001
Video Capture
Streaming
Extended Pix Format
Media Driver Info:
Driver name : starfive-camss
Model : Starfive Camera Subsystem
Serial :
Bus info : platform:19840000.camss
Media version : 6.5.0
Hardware revision: 0x00000000 (0)
Driver version : 6.5.0
Interface Info:
ID : 0x0300000a
Type : V4L Video
Entity Info:
ID : 0x00000008 (8)
Name : capture_yuv
Function : V4L2 I/O
Pad 0x01000009 : 0: Sink
Link 0x0200000c: from remote pad 0x1000003 of entity 'stf_isp' (Unknown Function (00004009)): Data, Enabled
Required ioctls:
test MC information (see 'Media Driver Info' above): OK
test VIDIOC_QUERYCAP: OK
test invalid ioctls: OK
Allow for multiple opens:
test second /dev/video1 open: OK
test VIDIOC_QUERYCAP: OK
test VIDIOC_G/S_PRIORITY: OK
test for unlimited opens: OK
Debug ioctls:
test VIDIOC_DBG_G/S_REGISTER: OK (Not Supported)
test VIDIOC_LOG_STATUS: OK (Not Supported)
Input ioctls:
test VIDIOC_G/S_TUNER/ENUM_FREQ_BANDS: OK (Not Supported)
test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
test VIDIOC_S_HW_FREQ_SEEK: OK (Not Supported)
test VIDIOC_ENUMAUDIO: OK (Not Supported)
test VIDIOC_G/S/ENUMINPUT: OK (Not Supported)
test VIDIOC_G/S_AUDIO: OK (Not Supported)
Inputs: 0 Audio Inputs: 0 Tuners: 0
Output ioctls:
test VIDIOC_G/S_MODULATOR: OK (Not Supported)
test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
test VIDIOC_ENUMAUDOUT: OK (Not Supported)
test VIDIOC_G/S/ENUMOUTPUT: OK (Not Supported)
test VIDIOC_G/S_AUDOUT: OK (Not Supported)
Outputs: 0 Audio Outputs: 0 Modulators: 0
Input/Output configuration ioctls:
test VIDIOC_ENUM/G/S/QUERY_STD: OK (Not Supported)
test VIDIOC_ENUM/G/S/QUERY_DV_TIMINGS: OK (Not Supported)
test VIDIOC_DV_TIMINGS_CAP: OK (Not Supported)
test VIDIOC_G/S_EDID: OK (Not Supported)
Control ioctls:
test VIDIOC_QUERY_EXT_CTRL/QUERYMENU: OK (Not Supported)
test VIDIOC_QUERYCTRL: OK (Not Supported)
test VIDIOC_G/S_CTRL: OK (Not Supported)
test VIDIOC_G/S/TRY_EXT_CTRLS: OK (Not Supported)
test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: OK (Not Supported)
test VIDIOC_G/S_JPEGCOMP: OK (Not Supported)
Standard Controls: 0 Private Controls: 0
Format ioctls:
test VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: OK
test VIDIOC_G/S_PARM: OK (Not Supported)
test VIDIOC_G_FBUF: OK (Not Supported)
test VIDIOC_G_FMT: OK
test VIDIOC_TRY_FMT: OK
test VIDIOC_S_FMT: OK
test VIDIOC_G_SLICED_VBI_CAP: OK (Not Supported)
test Cropping: OK (Not Supported)
test Composing: OK (Not Supported)
test Scaling: OK
Codec ioctls:
test VIDIOC_(TRY_)ENCODER_CMD: OK (Not Supported)
test VIDIOC_G_ENC_INDEX: OK (Not Supported)
test VIDIOC_(TRY_)DECODER_CMD: OK (Not Supported)
Buffer ioctls:
test VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: OK
test VIDIOC_EXPBUF: OK
test Requests: OK (Not Supported)
Test input 0:
Streaming ioctls:
test read/write: OK (Not Supported)
test blocking wait: OK
test MMAP (no poll): OK
test MMAP (select): OK
test MMAP (epoll): OK
test USERPTR (no poll): OK (Not Supported)
test USERPTR (select): OK (Not Supported)
test DMABUF: Cannot test, specify --expbuf-device
Total for stf camss device /dev/video1: 53, Succeeded: 53, Failed: 0, Warnings: 0
===========================================================================
Changes in v8:
- Rebased on v6.5-rc7.
- Dropped VIN subdev.
- Created two new video devices: capture_raw and capture_yuv, to replace
the previous video devices.
- Dropped VB2_READ io methods.
- Recursively called .s_stream() on subdevs.
v7 link: https://lore.kernel.org/all/[email protected]/
Changes in v7:
- HAS_DMA is used instead of DMA_CMA in Kconfig.
- Dropped some non-essential member variables.
- Used v4l2_async_nf_add_fwnode_remote() to simplify the relevant code.
- Modified some Local variable types in the function.
- Used v4l2_create_fwnode_links_to_pad() to simplify the relevant code.
- Added error handling for clk_prepare_enable().
- Simplified stfcamss_format_info struct and modified the relevant code.
- Dropped enum_input, g_input and s_input.
- Unified v4l2_ioctl_ops struct.
- Used v4l2_fh_open()/vb2_fop_release to replace deprecated APIs.
- Added a camss directory under the starfive directory and modified the
patch title.
v6 link: https://lore.kernel.org/all/[email protected]/
Changes in v6:
- Added 'bus-type' in bindings example.
- Corrected spelling errors.
- As reviewed by Bryan, used 'nclks' and 'nrsts' variables.
- Added lccf config for ISP.
v5 link: https://lore.kernel.org/all/[email protected]/
Changes in v5:
- Rebased on v6.4-rc1.
- Added new patch.
- Modified ISP driver.
v4 link: https://lore.kernel.org/all/[email protected]/
Previous cover letter from v4:
This patch series adds support for the StarFive Camera Subsystem
found on StarFive JH7110 SoC.
The driver implements V4L2, Media controller and V4L2 subdev interfaces.
Camera sensor using V4L2 subdev interface in the kernel is supported.
The driver is tested on VisionFive V2 board with IMX219 camera sensor.
GStreamer 1.18.5 with v4l2src plugin is supported.
Previous version link, missing v1 version:
v3: https://lore.kernel.org/all/[email protected]/
v2: https://lore.kernel.org/all/[email protected]/
Jack Zhu (8):
media: dt-bindings: Add JH7110 Camera Subsystem
media: admin-guide: Add starfive_camss.rst for Starfive Camera
Subsystem
media: staging: media: starfive: camss: Add core driver
media: staging: media: starfive: camss: Add video driver
media: staging: media: starfive: camss: Add ISP driver
media: staging: media: starfive: camss: Add capture driver
media: staging: media: starfive: camss: Add interrupt handling
media: staging: media: starfive: camss: Register devices
.../admin-guide/media/starfive_camss.rst | 72 +++
.../media/starfive_camss_graph.dot | 12 +
.../admin-guide/media/v4l-drivers.rst | 1 +
.../bindings/media/starfive,jh7110-camss.yaml | 180 ++++++
MAINTAINERS | 9 +
drivers/staging/media/Kconfig | 2 +
drivers/staging/media/Makefile | 1 +
drivers/staging/media/starfive/Kconfig | 5 +
drivers/staging/media/starfive/Makefile | 2 +
drivers/staging/media/starfive/camss/Kconfig | 17 +
drivers/staging/media/starfive/camss/Makefile | 13 +
.../staging/media/starfive/camss/stf_camss.c | 432 +++++++++++++
.../staging/media/starfive/camss/stf_camss.h | 134 ++++
.../media/starfive/camss/stf_capture.c | 603 ++++++++++++++++++
.../media/starfive/camss/stf_capture.h | 87 +++
.../staging/media/starfive/camss/stf_isp.c | 407 ++++++++++++
.../staging/media/starfive/camss/stf_isp.h | 428 +++++++++++++
.../media/starfive/camss/stf_isp_hw_ops.c | 445 +++++++++++++
.../staging/media/starfive/camss/stf_video.c | 557 ++++++++++++++++
.../staging/media/starfive/camss/stf_video.h | 100 +++
20 files changed, 3507 insertions(+)
create mode 100644 Documentation/admin-guide/media/starfive_camss.rst
create mode 100644 Documentation/admin-guide/media/starfive_camss_graph.dot
create mode 100644 Documentation/devicetree/bindings/media/starfive,jh7110-camss.yaml
create mode 100644 drivers/staging/media/starfive/Kconfig
create mode 100644 drivers/staging/media/starfive/Makefile
create mode 100644 drivers/staging/media/starfive/camss/Kconfig
create mode 100644 drivers/staging/media/starfive/camss/Makefile
create mode 100644 drivers/staging/media/starfive/camss/stf_camss.c
create mode 100644 drivers/staging/media/starfive/camss/stf_camss.h
create mode 100644 drivers/staging/media/starfive/camss/stf_capture.c
create mode 100644 drivers/staging/media/starfive/camss/stf_capture.h
create mode 100644 drivers/staging/media/starfive/camss/stf_isp.c
create mode 100644 drivers/staging/media/starfive/camss/stf_isp.h
create mode 100644 drivers/staging/media/starfive/camss/stf_isp_hw_ops.c
create mode 100644 drivers/staging/media/starfive/camss/stf_video.c
create mode 100644 drivers/staging/media/starfive/camss/stf_video.h
--
2.34.1
Add capture driver for StarFive Camera Subsystem. It contains two video
devices: capture_yuv and capture_raw.
Signed-off-by: Jack Zhu <[email protected]>
---
drivers/staging/media/starfive/camss/Makefile | 1 +
.../staging/media/starfive/camss/stf_camss.h | 2 +
.../media/starfive/camss/stf_capture.c | 603 ++++++++++++++++++
.../media/starfive/camss/stf_capture.h | 87 +++
4 files changed, 693 insertions(+)
create mode 100644 drivers/staging/media/starfive/camss/stf_capture.c
create mode 100644 drivers/staging/media/starfive/camss/stf_capture.h
diff --git a/drivers/staging/media/starfive/camss/Makefile b/drivers/staging/media/starfive/camss/Makefile
index cdf57e8c9546..685f9f16acba 100644
--- a/drivers/staging/media/starfive/camss/Makefile
+++ b/drivers/staging/media/starfive/camss/Makefile
@@ -5,6 +5,7 @@
starfive-camss-objs += \
stf_camss.o \
+ stf_capture.o \
stf_isp.o \
stf_isp_hw_ops.o \
stf_video.o
diff --git a/drivers/staging/media/starfive/camss/stf_camss.h b/drivers/staging/media/starfive/camss/stf_camss.h
index e0f7ee9f2583..5e026a4c0528 100644
--- a/drivers/staging/media/starfive/camss/stf_camss.h
+++ b/drivers/staging/media/starfive/camss/stf_camss.h
@@ -19,6 +19,7 @@
#include <media/v4l2-device.h>
#include "stf_isp.h"
+#include "stf_capture.h"
enum stf_port_num {
STF_PORT_DVP = 0,
@@ -52,6 +53,7 @@ struct stfcamss {
struct media_pipeline pipe;
struct device *dev;
struct stf_isp_dev isp_dev;
+ struct stf_capture captures[STF_CAPTURE_NUM];
struct v4l2_async_notifier notifier;
void __iomem *syscon_base;
void __iomem *isp_base;
diff --git a/drivers/staging/media/starfive/camss/stf_capture.c b/drivers/staging/media/starfive/camss/stf_capture.c
new file mode 100644
index 000000000000..ebdb2550174e
--- /dev/null
+++ b/drivers/staging/media/starfive/camss/stf_capture.c
@@ -0,0 +1,603 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * stf_capture.c
+ *
+ * StarFive Camera Subsystem - capture device
+ *
+ * Copyright (C) 2021-2023 StarFive Technology Co., Ltd.
+ */
+
+#include "stf_camss.h"
+
+static const char * const stf_cap_names[] = {
+ "capture_raw",
+ "capture_yuv",
+};
+
+static const struct stfcamss_format_info stf_wr_fmts[] = {
+ {
+ .code = MEDIA_BUS_FMT_SRGGB10_1X10,
+ .pixelformat = V4L2_PIX_FMT_SRGGB10,
+ .planes = 1,
+ .vsub = { 1 },
+ .bpp = 10,
+ },
+ {
+ .code = MEDIA_BUS_FMT_SGRBG10_1X10,
+ .pixelformat = V4L2_PIX_FMT_SGRBG10,
+ .planes = 1,
+ .vsub = { 1 },
+ .bpp = 10,
+ },
+ {
+ .code = MEDIA_BUS_FMT_SGBRG10_1X10,
+ .pixelformat = V4L2_PIX_FMT_SGBRG10,
+ .planes = 1,
+ .vsub = { 1 },
+ .bpp = 10,
+ },
+ {
+ .code = MEDIA_BUS_FMT_SBGGR10_1X10,
+ .pixelformat = V4L2_PIX_FMT_SBGGR10,
+ .planes = 1,
+ .vsub = { 1 },
+ .bpp = 10,
+ },
+};
+
+static const struct stfcamss_format_info stf_isp_fmts[] = {
+ {
+ .code = MEDIA_BUS_FMT_YUYV8_1_5X8,
+ .pixelformat = V4L2_PIX_FMT_NV12,
+ .planes = 2,
+ .vsub = { 1, 2 },
+ .bpp = 8,
+ },
+};
+
+static inline struct stf_capture *to_stf_capture(struct stfcamss_video *video)
+{
+ return container_of(video, struct stf_capture, video);
+}
+
+static void stf_set_raw_addr(struct stfcamss *stfcamss, dma_addr_t addr)
+{
+ stf_syscon_reg_write(stfcamss, VIN_START_ADDR_O, (long)addr);
+ stf_syscon_reg_write(stfcamss, VIN_START_ADDR_N, (long)addr);
+}
+
+static void stf_set_yuv_addr(struct stfcamss *stfcamss,
+ dma_addr_t y_addr, dma_addr_t uv_addr)
+{
+ stf_isp_reg_write(stfcamss, ISP_REG_Y_PLANE_START_ADDR, y_addr);
+ stf_isp_reg_write(stfcamss, ISP_REG_UV_PLANE_START_ADDR, uv_addr);
+}
+
+static void stf_init_addrs(struct stfcamss_video *video)
+{
+ struct stf_capture *cap = to_stf_capture(video);
+ struct stf_v_buf *output = &cap->buffers;
+ dma_addr_t addr0, addr1;
+
+ output->active_buf = 0;
+
+ if (!output->buf[0])
+ return;
+
+ addr0 = output->buf[0]->addr[0];
+ addr1 = output->buf[0]->addr[1];
+
+ if (cap->type == STF_CAPTURE_RAW)
+ stf_set_raw_addr(video->stfcamss, addr0);
+ else if (cap->type == STF_CAPTURE_YUV)
+ stf_set_yuv_addr(video->stfcamss, addr0, addr1);
+}
+
+static struct stfcamss_buffer *stf_buf_get_pending(struct stf_v_buf *output)
+{
+ struct stfcamss_buffer *buffer = NULL;
+
+ if (!list_empty(&output->pending_bufs)) {
+ buffer = list_first_entry(&output->pending_bufs,
+ struct stfcamss_buffer,
+ queue);
+ list_del(&buffer->queue);
+ }
+
+ return buffer;
+}
+
+static void stf_cap_s_cfg(struct stfcamss_video *video)
+{
+ struct stf_capture *cap = to_stf_capture(video);
+ struct stf_v_buf *output = &cap->buffers;
+ unsigned long flags;
+
+ spin_lock_irqsave(&output->lock, flags);
+
+ output->state = STF_OUTPUT_IDLE;
+ output->buf[0] = stf_buf_get_pending(output);
+
+ if (!output->buf[0] && output->buf[1]) {
+ output->buf[0] = output->buf[1];
+ output->buf[1] = NULL;
+ }
+
+ if (output->buf[0])
+ output->state = STF_OUTPUT_SINGLE;
+
+ output->sequence = 0;
+ stf_init_addrs(video);
+
+ spin_unlock_irqrestore(&output->lock, flags);
+}
+
+static int stf_cap_s_cleanup(struct stfcamss_video *video)
+{
+ struct stf_capture *cap = to_stf_capture(video);
+ struct stf_v_buf *output = &cap->buffers;
+ unsigned long flags;
+
+ spin_lock_irqsave(&output->lock, flags);
+
+ output->state = STF_OUTPUT_OFF;
+
+ spin_unlock_irqrestore(&output->lock, flags);
+
+ return 0;
+}
+
+static void stf_wr_data_en(struct stfcamss_video *video)
+{
+ struct stf_capture *cap = to_stf_capture(video);
+ struct stfcamss *stfcamss = cap->video.stfcamss;
+
+ stf_syscon_reg_set_bit(stfcamss, VIN_CHANNEL_SEL_EN, U0_VIN_AXIWR0_EN);
+}
+
+static void stf_wr_irq_enable(struct stfcamss_video *video)
+{
+ struct stf_capture *cap = to_stf_capture(video);
+ struct stfcamss *stfcamss = cap->video.stfcamss;
+
+ stf_syscon_reg_clear_bit(stfcamss, VIN_INRT_PIX_CFG, U0_VIN_INTR_M);
+}
+
+static void stf_wr_irq_disable(struct stfcamss_video *video)
+{
+ struct stf_capture *cap = to_stf_capture(video);
+ struct stfcamss *stfcamss = cap->video.stfcamss;
+
+ stf_syscon_reg_set_bit(stfcamss, VIN_INRT_PIX_CFG, U0_VIN_INTR_CLEAN);
+ stf_syscon_reg_clear_bit(stfcamss, VIN_INRT_PIX_CFG, U0_VIN_INTR_CLEAN);
+ stf_syscon_reg_set_bit(stfcamss, VIN_INRT_PIX_CFG, U0_VIN_INTR_M);
+}
+
+static void stf_channel_set(struct stfcamss_video *video)
+{
+ struct stf_capture *cap = to_stf_capture(video);
+ struct stfcamss *stfcamss = cap->video.stfcamss;
+ u32 val;
+
+ if (cap->type == STF_CAPTURE_RAW) {
+ val = stf_syscon_reg_read(stfcamss, VIN_CHANNEL_SEL_EN);
+ val &= ~U0_VIN_CHANNEL_SEL_MASK;
+ val |= CHANNEL(0);
+ stf_syscon_reg_write(stfcamss, VIN_CHANNEL_SEL_EN, val);
+
+ val = stf_syscon_reg_read(stfcamss, VIN_INRT_PIX_CFG);
+ val &= ~U0_VIN_PIX_CT_MASK;
+ val |= PIX_CT(1);
+
+ val &= ~U0_VIN_PIXEL_HEIGH_BIT_SEL_MAKS;
+ val |= PIXEL_HEIGH_BIT_SEL(0);
+
+ val &= ~U0_VIN_PIX_CNT_END_MASK;
+ val |= PIX_CNT_END(IMAGE_MAX_WIDTH / 4 - 1);
+
+ stf_syscon_reg_write(stfcamss, VIN_INRT_PIX_CFG, val);
+ } else if (cap->type == STF_CAPTURE_YUV) {
+ val = stf_syscon_reg_read(stfcamss, VIN_CFG_REG);
+ val &= ~U0_VIN_MIPI_BYTE_EN_ISP0_MASK;
+ val |= U0_VIN_MIPI_BYTE_EN_ISP0(0);
+
+ val &= ~U0_VIN_MIPI_CHANNEL_SEL0_MASK;
+ val |= U0_VIN_MIPI_CHANNEL_SEL0(0);
+
+ val &= ~U0_VIN_PIX_NUM_MASK;
+ val |= U0_VIN_PIX_NUM(0);
+
+ val &= ~U0_VIN_P_I_MIPI_HAEDER_EN0_MASK;
+ val |= U0_VIN_P_I_MIPI_HAEDER_EN0(1);
+
+ stf_syscon_reg_write(stfcamss, VIN_CFG_REG, val);
+ }
+}
+
+static void stf_capture_start(struct stfcamss_video *video)
+{
+ struct stf_capture *cap = to_stf_capture(video);
+
+ stf_channel_set(video);
+ if (cap->type == STF_CAPTURE_RAW) {
+ stf_wr_irq_enable(video);
+ stf_wr_data_en(video);
+ }
+
+ stf_cap_s_cfg(video);
+}
+
+static void stf_capture_stop(struct stfcamss_video *video)
+{
+ struct stf_capture *cap = to_stf_capture(video);
+
+ if (cap->type == STF_CAPTURE_RAW)
+ stf_wr_irq_disable(video);
+
+ stf_cap_s_cleanup(video);
+}
+
+static void stf_capture_init(struct stfcamss *stfcamss, struct stf_capture *cap)
+{
+ cap->buffers.state = STF_OUTPUT_OFF;
+ cap->buffers.buf[0] = NULL;
+ cap->buffers.buf[1] = NULL;
+ cap->buffers.active_buf = 0;
+ atomic_set(&cap->buffers.frame_skip, 4);
+ INIT_LIST_HEAD(&cap->buffers.pending_bufs);
+ INIT_LIST_HEAD(&cap->buffers.ready_bufs);
+ spin_lock_init(&cap->buffers.lock);
+
+ cap->video.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ cap->video.stfcamss = stfcamss;
+ cap->video.bpl_alignment = 16 * 8;
+
+ if (cap->type == STF_CAPTURE_RAW) {
+ cap->video.formats = stf_wr_fmts;
+ cap->video.nformats = ARRAY_SIZE(stf_wr_fmts);
+ cap->video.bpl_alignment = 8;
+ } else if (cap->type == STF_CAPTURE_YUV) {
+ cap->video.formats = stf_isp_fmts;
+ cap->video.nformats = ARRAY_SIZE(stf_isp_fmts);
+ cap->video.bpl_alignment = 1;
+ }
+}
+
+static void stf_buf_add_ready(struct stf_v_buf *output,
+ struct stfcamss_buffer *buffer)
+{
+ INIT_LIST_HEAD(&buffer->queue);
+ list_add_tail(&buffer->queue, &output->ready_bufs);
+}
+
+static struct stfcamss_buffer *stf_buf_get_ready(struct stf_v_buf *output)
+{
+ struct stfcamss_buffer *buffer = NULL;
+
+ if (!list_empty(&output->ready_bufs)) {
+ buffer = list_first_entry(&output->ready_bufs,
+ struct stfcamss_buffer,
+ queue);
+ list_del(&buffer->queue);
+ }
+
+ return buffer;
+}
+
+static void stf_buf_add_pending(struct stf_v_buf *output,
+ struct stfcamss_buffer *buffer)
+{
+ INIT_LIST_HEAD(&buffer->queue);
+ list_add_tail(&buffer->queue, &output->pending_bufs);
+}
+
+static void stf_buf_update_on_last(struct stf_v_buf *output)
+{
+ switch (output->state) {
+ case STF_OUTPUT_CONTINUOUS:
+ output->state = STF_OUTPUT_SINGLE;
+ output->active_buf = !output->active_buf;
+ break;
+ case STF_OUTPUT_SINGLE:
+ output->state = STF_OUTPUT_STOPPING;
+ break;
+ default:
+ break;
+ }
+}
+
+static void stf_buf_update_on_next(struct stf_v_buf *output)
+{
+ switch (output->state) {
+ case STF_OUTPUT_CONTINUOUS:
+ output->active_buf = !output->active_buf;
+ break;
+ case STF_OUTPUT_SINGLE:
+ default:
+ break;
+ }
+}
+
+static void stf_buf_update_on_new(struct stfcamss_video *video,
+ struct stfcamss_buffer *new_buf)
+{
+ struct stf_capture *cap = to_stf_capture(video);
+ struct stf_v_buf *output = &cap->buffers;
+
+ switch (output->state) {
+ case STF_OUTPUT_SINGLE:
+ stf_buf_add_pending(output, new_buf);
+ break;
+ case STF_OUTPUT_IDLE:
+ if (!output->buf[0]) {
+ output->buf[0] = new_buf;
+ stf_init_addrs(video);
+ output->state = STF_OUTPUT_SINGLE;
+ } else {
+ stf_buf_add_pending(output, new_buf);
+ }
+ break;
+ case STF_OUTPUT_STOPPING:
+ if (output->last_buffer) {
+ output->buf[output->active_buf] = output->last_buffer;
+ output->last_buffer = NULL;
+ }
+
+ output->state = STF_OUTPUT_SINGLE;
+ stf_buf_add_pending(output, new_buf);
+ break;
+ case STF_OUTPUT_CONTINUOUS:
+ default:
+ stf_buf_add_pending(output, new_buf);
+ break;
+ }
+}
+
+static void stf_buf_flush(struct stf_v_buf *output, enum vb2_buffer_state state)
+{
+ struct stfcamss_buffer *buf;
+ struct stfcamss_buffer *t;
+
+ list_for_each_entry_safe(buf, t, &output->pending_bufs, queue) {
+ vb2_buffer_done(&buf->vb.vb2_buf, state);
+ list_del(&buf->queue);
+ }
+ list_for_each_entry_safe(buf, t, &output->ready_bufs, queue) {
+ vb2_buffer_done(&buf->vb.vb2_buf, state);
+ list_del(&buf->queue);
+ }
+}
+
+static void stf_buf_done(struct stf_v_buf *output)
+{
+ struct stfcamss_buffer *ready_buf;
+ u64 ts = ktime_get_ns();
+ unsigned long flags;
+
+ if (output->state == STF_OUTPUT_OFF ||
+ output->state == STF_OUTPUT_RESERVED)
+ return;
+
+ spin_lock_irqsave(&output->lock, flags);
+
+ while ((ready_buf = stf_buf_get_ready(output))) {
+ ready_buf->vb.vb2_buf.timestamp = ts;
+ ready_buf->vb.sequence = output->sequence++;
+
+ vb2_buffer_done(&ready_buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
+ }
+
+ spin_unlock_irqrestore(&output->lock, flags);
+}
+
+static void stf_change_buffer(struct stf_v_buf *output)
+{
+ struct stf_capture *cap = container_of(output, struct stf_capture,
+ buffers);
+ struct stfcamss *stfcamss = cap->video.stfcamss;
+ struct stfcamss_buffer *ready_buf;
+ dma_addr_t *new_addr;
+ unsigned long flags;
+ u32 active_index;
+
+ if (output->state == STF_OUTPUT_OFF ||
+ output->state == STF_OUTPUT_STOPPING ||
+ output->state == STF_OUTPUT_RESERVED ||
+ output->state == STF_OUTPUT_IDLE)
+ return;
+
+ spin_lock_irqsave(&output->lock, flags);
+
+ active_index = output->active_buf;
+
+ ready_buf = output->buf[active_index];
+ if (!ready_buf) {
+ dev_dbg(stfcamss->dev, "missing ready buf %d %d.\n",
+ active_index, output->state);
+ active_index = !active_index;
+ ready_buf = output->buf[active_index];
+ if (!ready_buf) {
+ dev_dbg(stfcamss->dev,
+ "missing ready buf2 %d %d.\n",
+ active_index, output->state);
+ goto out_unlock;
+ }
+ }
+
+ /* Get next buffer */
+ output->buf[active_index] = stf_buf_get_pending(output);
+ if (!output->buf[active_index]) {
+ new_addr = ready_buf->addr;
+ stf_buf_update_on_last(output);
+ } else {
+ new_addr = output->buf[active_index]->addr;
+ stf_buf_update_on_next(output);
+ }
+
+ if (output->state == STF_OUTPUT_STOPPING) {
+ output->last_buffer = ready_buf;
+ } else {
+ if (cap->type == STF_CAPTURE_RAW)
+ stf_set_raw_addr(stfcamss, new_addr[0]);
+ else if (cap->type == STF_CAPTURE_YUV)
+ stf_set_yuv_addr(stfcamss, new_addr[0], new_addr[1]);
+
+ stf_buf_add_ready(output, ready_buf);
+ }
+
+out_unlock:
+ spin_unlock_irqrestore(&output->lock, flags);
+}
+
+irqreturn_t stf_wr_irq_handler(int irq, void *priv)
+{
+ struct stfcamss *stfcamss = priv;
+ struct stf_capture *cap = &stfcamss->captures[STF_CAPTURE_RAW];
+
+ if (atomic_dec_if_positive(&cap->buffers.frame_skip) < 0) {
+ stf_change_buffer(&cap->buffers);
+ stf_buf_done(&cap->buffers);
+ }
+
+ stf_syscon_reg_set_bit(stfcamss, VIN_INRT_PIX_CFG, U0_VIN_INTR_CLEAN);
+ stf_syscon_reg_clear_bit(stfcamss, VIN_INRT_PIX_CFG, U0_VIN_INTR_CLEAN);
+
+ return IRQ_HANDLED;
+}
+
+irqreturn_t stf_isp_irq_handler(int irq, void *priv)
+{
+ struct stfcamss *stfcamss = priv;
+ struct stf_capture *cap = &stfcamss->captures[STF_CAPTURE_YUV];
+ u32 status;
+
+ status = stf_isp_reg_read(stfcamss, ISP_REG_ISP_CTRL_0);
+ if (status & ISPC_ISP) {
+ if (status & ISPC_ENUO)
+ stf_buf_done(&cap->buffers);
+
+ stf_isp_reg_write(stfcamss, ISP_REG_ISP_CTRL_0,
+ (status & ~ISPC_INT_ALL_MASK) |
+ ISPC_ISP | ISPC_CSI | ISPC_SC);
+ }
+
+ return IRQ_HANDLED;
+}
+
+irqreturn_t stf_line_irq_handler(int irq, void *priv)
+{
+ struct stfcamss *stfcamss = priv;
+ struct stf_capture *cap = &stfcamss->captures[STF_CAPTURE_YUV];
+ u32 status;
+
+ 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);
+ }
+
+ stf_isp_reg_set_bit(stfcamss, ISP_REG_CSIINTS,
+ CSI_INTS_MASK, CSI_INTS(0x3));
+ stf_isp_reg_set_bit(stfcamss, ISP_REG_IESHD,
+ SHAD_UP_M | SHAD_UP_EN, 0x3);
+
+ stf_isp_reg_write(stfcamss, ISP_REG_ISP_CTRL_0,
+ (status & ~ISPC_INT_ALL_MASK) | ISPC_LINE);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static int stf_queue_buffer(struct stfcamss_video *video,
+ struct stfcamss_buffer *buf)
+{
+ struct stf_capture *cap = to_stf_capture(video);
+ struct stf_v_buf *v_bufs = &cap->buffers;
+ unsigned long flags;
+
+ spin_lock_irqsave(&v_bufs->lock, flags);
+ stf_buf_update_on_new(video, buf);
+ spin_unlock_irqrestore(&v_bufs->lock, flags);
+
+ return 0;
+}
+
+static int stf_flush_buffers(struct stfcamss_video *video,
+ enum vb2_buffer_state state)
+{
+ struct stf_capture *cap = to_stf_capture(video);
+ struct stf_v_buf *v_bufs = &cap->buffers;
+ unsigned long flags;
+ unsigned int i;
+
+ spin_lock_irqsave(&v_bufs->lock, flags);
+
+ stf_buf_flush(v_bufs, state);
+
+ for (i = 0; i < ARRAY_SIZE(v_bufs->buf); i++) {
+ if (v_bufs->buf[i])
+ vb2_buffer_done(&v_bufs->buf[i]->vb.vb2_buf, state);
+
+ v_bufs->buf[i] = NULL;
+ }
+
+ if (v_bufs->last_buffer) {
+ vb2_buffer_done(&v_bufs->last_buffer->vb.vb2_buf, state);
+ v_bufs->last_buffer = NULL;
+ }
+
+ spin_unlock_irqrestore(&v_bufs->lock, flags);
+ return 0;
+}
+
+static const struct stfcamss_video_ops stf_capture_ops = {
+ .queue_buffer = stf_queue_buffer,
+ .flush_buffers = stf_flush_buffers,
+ .start_streaming = stf_capture_start,
+ .stop_streaming = stf_capture_stop,
+};
+
+static void stf_capture_unregister_one(struct stf_capture *cap)
+{
+ if (!video_is_registered(&cap->video.vdev))
+ return;
+
+ media_entity_cleanup(&cap->video.vdev.entity);
+ vb2_video_unregister_device(&cap->video.vdev);
+}
+
+void stf_capture_unregister(struct stfcamss *stfcamss)
+{
+ struct stf_capture *cap_raw = &stfcamss->captures[STF_CAPTURE_RAW];
+ struct stf_capture *cap_yuv = &stfcamss->captures[STF_CAPTURE_YUV];
+
+ stf_capture_unregister_one(cap_raw);
+ stf_capture_unregister_one(cap_yuv);
+}
+
+int stf_capture_register(struct stfcamss *stfcamss,
+ struct v4l2_device *v4l2_dev)
+{
+ unsigned int i;
+ int ret;
+
+ for (i = 0; i < ARRAY_SIZE(stfcamss->captures); i++) {
+ struct stf_capture *capture = &stfcamss->captures[i];
+
+ capture->type = i;
+ capture->video.ops = &stf_capture_ops;
+ stf_capture_init(stfcamss, capture);
+
+ ret = stf_video_register(&capture->video, v4l2_dev,
+ stf_cap_names[i]);
+ if (ret < 0) {
+ dev_err(stfcamss->dev,
+ "Failed to register video node: %d\n", ret);
+ stf_capture_unregister(stfcamss);
+ return ret;
+ }
+ }
+
+ return 0;
+}
diff --git a/drivers/staging/media/starfive/camss/stf_capture.h b/drivers/staging/media/starfive/camss/stf_capture.h
new file mode 100644
index 000000000000..a01782eb5019
--- /dev/null
+++ b/drivers/staging/media/starfive/camss/stf_capture.h
@@ -0,0 +1,87 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * stf_capture.h
+ *
+ * Starfive Camera Subsystem driver
+ *
+ * Copyright (C) 2021-2023 StarFive Technology Co., Ltd.
+ */
+
+#ifndef STF_CAPTURE_H
+#define STF_CAPTURE_H
+
+#include "stf_video.h"
+
+#define VIN_CHANNEL_SEL_EN 0x14
+#define VIN_START_ADDR_N 0x18
+#define VIN_INRT_PIX_CFG 0x1c
+#define VIN_START_ADDR_O 0x20
+#define VIN_CFG_REG 0x24
+
+#define U0_VIN_CNFG_AXI_DVP_EN BIT(2)
+
+#define U0_VIN_CHANNEL_SEL_MASK GENMASK(3, 0)
+#define U0_VIN_AXIWR0_EN BIT(4)
+#define CHANNEL(x) ((x) << 0)
+
+#define U0_VIN_INTR_CLEAN BIT(0)
+#define U0_VIN_INTR_M BIT(1)
+#define U0_VIN_PIX_CNT_END_MASK GENMASK(12, 2)
+#define U0_VIN_PIX_CT_MASK GENMASK(14, 13)
+#define U0_VIN_PIXEL_HEIGH_BIT_SEL_MAKS GENMASK(16, 15)
+
+#define PIX_CNT_END(x) ((x) << 2)
+#define PIX_CT(x) ((x) << 13)
+#define PIXEL_HEIGH_BIT_SEL(x) ((x) << 15)
+
+#define U0_VIN_CNFG_DVP_HS_POS BIT(1)
+#define U0_VIN_CNFG_DVP_SWAP_EN BIT(2)
+#define U0_VIN_CNFG_DVP_VS_POS BIT(3)
+#define U0_VIN_CNFG_GEN_EN_AXIRD BIT(4)
+#define U0_VIN_CNFG_ISP_DVP_EN0 BIT(5)
+#define U0_VIN_MIPI_BYTE_EN_ISP0(n) ((n) << 6)
+#define U0_VIN_MIPI_CHANNEL_SEL0(n) ((n) << 8)
+#define U0_VIN_P_I_MIPI_HAEDER_EN0(n) ((n) << 12)
+#define U0_VIN_PIX_NUM(n) ((n) << 13)
+#define U0_VIN_MIPI_BYTE_EN_ISP0_MASK GENMASK(7, 6)
+#define U0_VIN_MIPI_CHANNEL_SEL0_MASK GENMASK(11, 8)
+#define U0_VIN_P_I_MIPI_HAEDER_EN0_MASK BIT(12)
+#define U0_VIN_PIX_NUM_MASK GENMASK(16, 13)
+
+enum stf_v_state {
+ STF_OUTPUT_OFF,
+ STF_OUTPUT_RESERVED,
+ STF_OUTPUT_SINGLE,
+ STF_OUTPUT_CONTINUOUS,
+ STF_OUTPUT_IDLE,
+ STF_OUTPUT_STOPPING
+};
+
+struct stf_v_buf {
+ int active_buf;
+ struct stfcamss_buffer *buf[2];
+ struct stfcamss_buffer *last_buffer;
+ struct list_head pending_bufs;
+ struct list_head ready_bufs;
+ enum stf_v_state state;
+ unsigned int sequence;
+ /* protects the above member variables */
+ spinlock_t lock;
+ atomic_t frame_skip;
+};
+
+struct stf_capture {
+ struct stfcamss_video video;
+ struct stf_v_buf buffers;
+ enum stf_capture_type type;
+};
+
+irqreturn_t stf_wr_irq_handler(int irq, void *priv);
+irqreturn_t stf_isp_irq_handler(int irq, void *priv);
+irqreturn_t stf_line_irq_handler(int irq, void *priv);
+int stf_capture_register(struct stfcamss *stfcamss,
+ struct v4l2_device *v4l2_dev);
+void stf_capture_unregister(struct stfcamss *stfcamss);
+
+#endif
+
--
2.34.1
Add core driver for StarFive Camera Subsystem. The code parses
the device platform resources and registers related devices.
Reviewed-by: Bryan O'Donoghue <[email protected]>
Signed-off-by: Jack Zhu <[email protected]>
---
MAINTAINERS | 1 +
drivers/staging/media/Kconfig | 2 +
drivers/staging/media/Makefile | 1 +
drivers/staging/media/starfive/Kconfig | 5 +
drivers/staging/media/starfive/Makefile | 2 +
drivers/staging/media/starfive/camss/Kconfig | 17 +
drivers/staging/media/starfive/camss/Makefile | 9 +
.../staging/media/starfive/camss/stf_camss.c | 316 ++++++++++++++++++
.../staging/media/starfive/camss/stf_camss.h | 129 +++++++
9 files changed, 482 insertions(+)
create mode 100644 drivers/staging/media/starfive/Kconfig
create mode 100644 drivers/staging/media/starfive/Makefile
create mode 100644 drivers/staging/media/starfive/camss/Kconfig
create mode 100644 drivers/staging/media/starfive/camss/Makefile
create mode 100644 drivers/staging/media/starfive/camss/stf_camss.c
create mode 100644 drivers/staging/media/starfive/camss/stf_camss.h
diff --git a/MAINTAINERS b/MAINTAINERS
index 4c63c0a85301..97d3054416ed 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -20258,6 +20258,7 @@ L: [email protected]
S: Maintained
F: Documentation/admin-guide/media/starfive_camss.rst
F: Documentation/devicetree/bindings/media/starfive,jh7110-camss.yaml
+F: drivers/staging/media/starfive/camss
STARFIVE CRYPTO DRIVER
M: Jia Jie Ho <[email protected]>
diff --git a/drivers/staging/media/Kconfig b/drivers/staging/media/Kconfig
index bc6c7b248f86..554c2e475ce3 100644
--- a/drivers/staging/media/Kconfig
+++ b/drivers/staging/media/Kconfig
@@ -36,6 +36,8 @@ source "drivers/staging/media/omap4iss/Kconfig"
source "drivers/staging/media/rkvdec/Kconfig"
+source "drivers/staging/media/starfive/Kconfig"
+
source "drivers/staging/media/sunxi/Kconfig"
source "drivers/staging/media/tegra-video/Kconfig"
diff --git a/drivers/staging/media/Makefile b/drivers/staging/media/Makefile
index 1a4c3a062e3d..dcaeeca0ee6d 100644
--- a/drivers/staging/media/Makefile
+++ b/drivers/staging/media/Makefile
@@ -6,6 +6,7 @@ obj-$(CONFIG_VIDEO_MAX96712) += max96712/
obj-$(CONFIG_VIDEO_MESON_VDEC) += meson/vdec/
obj-$(CONFIG_VIDEO_OMAP4) += omap4iss/
obj-$(CONFIG_VIDEO_ROCKCHIP_VDEC) += rkvdec/
+obj-$(CONFIG_VIDEO_STARFIVE_CAMSS) += starfive/
obj-$(CONFIG_VIDEO_SUNXI) += sunxi/
obj-$(CONFIG_VIDEO_TEGRA) += tegra-video/
obj-$(CONFIG_VIDEO_IPU3_IMGU) += ipu3/
diff --git a/drivers/staging/media/starfive/Kconfig b/drivers/staging/media/starfive/Kconfig
new file mode 100644
index 000000000000..34727cf56072
--- /dev/null
+++ b/drivers/staging/media/starfive/Kconfig
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+comment "StarFive media platform drivers"
+
+source "drivers/staging/media/starfive/camss/Kconfig"
diff --git a/drivers/staging/media/starfive/Makefile b/drivers/staging/media/starfive/Makefile
new file mode 100644
index 000000000000..4639fa1bca32
--- /dev/null
+++ b/drivers/staging/media/starfive/Makefile
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0-only
+obj-y += camss/
diff --git a/drivers/staging/media/starfive/camss/Kconfig b/drivers/staging/media/starfive/camss/Kconfig
new file mode 100644
index 000000000000..8d20e2bd2559
--- /dev/null
+++ b/drivers/staging/media/starfive/camss/Kconfig
@@ -0,0 +1,17 @@
+# SPDX-License-Identifier: GPL-2.0-only
+config VIDEO_STARFIVE_CAMSS
+ tristate "Starfive Camera Subsystem driver"
+ depends on V4L_PLATFORM_DRIVERS
+ depends on VIDEO_DEV && OF
+ depends on HAS_DMA
+ depends on PM
+ select MEDIA_CONTROLLER
+ select VIDEO_V4L2_SUBDEV_API
+ select VIDEOBUF2_DMA_CONTIG
+ select V4L2_FWNODE
+ help
+ Enable this to support for the Starfive Camera subsystem
+ found on Starfive JH7110 SoC.
+
+ To compile this driver as a module, choose M here: the
+ module will be called stf-camss.
diff --git a/drivers/staging/media/starfive/camss/Makefile b/drivers/staging/media/starfive/camss/Makefile
new file mode 100644
index 000000000000..f53c5cbe958f
--- /dev/null
+++ b/drivers/staging/media/starfive/camss/Makefile
@@ -0,0 +1,9 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Makefile for StarFive Camera Subsystem driver
+#
+
+starfive-camss-objs += \
+ stf_camss.o
+
+obj-$(CONFIG_VIDEO_STARFIVE_CAMSS) += starfive-camss.o
diff --git a/drivers/staging/media/starfive/camss/stf_camss.c b/drivers/staging/media/starfive/camss/stf_camss.c
new file mode 100644
index 000000000000..75ebc3a35218
--- /dev/null
+++ b/drivers/staging/media/starfive/camss/stf_camss.c
@@ -0,0 +1,316 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * stf_camss.c
+ *
+ * Starfive Camera Subsystem driver
+ *
+ * Copyright (C) 2021-2023 StarFive Technology Co., Ltd.
+ *
+ * Author: Jack Zhu <[email protected]>
+ * Author: Changhuang Liang <[email protected]>
+ *
+ */
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_graph.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-fwnode.h>
+#include <media/v4l2-mc.h>
+
+#include "stf_camss.h"
+
+static const char * const stfcamss_clocks[] = {
+ "clk_wrapper_clk_c",
+ "clk_ispcore_2x",
+ "clk_isp_axi",
+};
+
+static const char * const stfcamss_resets[] = {
+ "rst_wrapper_p",
+ "rst_wrapper_c",
+ "rst_axiwr",
+ "rst_isp_top_n",
+ "rst_isp_top_axi",
+};
+
+static int stfcamss_get_mem_res(struct stfcamss *stfcamss)
+{
+ struct platform_device *pdev = to_platform_device(stfcamss->dev);
+
+ stfcamss->syscon_base =
+ devm_platform_ioremap_resource_byname(pdev, "syscon");
+ if (IS_ERR(stfcamss->syscon_base))
+ return PTR_ERR(stfcamss->syscon_base);
+
+ stfcamss->isp_base = devm_platform_ioremap_resource_byname(pdev, "isp");
+ if (IS_ERR(stfcamss->isp_base))
+ return PTR_ERR(stfcamss->isp_base);
+
+ return 0;
+}
+
+/*
+ * stfcamss_of_parse_endpoint_node - Parse port endpoint node
+ * @dev: Device
+ * @node: Device node to be parsed
+ * @csd: Parsed data from port endpoint node
+ *
+ * Return 0 on success or a negative error code on failure
+ */
+static int stfcamss_of_parse_endpoint_node(struct stfcamss *stfcamss,
+ struct device_node *node,
+ struct stfcamss_async_subdev *csd)
+{
+ struct v4l2_fwnode_endpoint vep = { { 0 } };
+ int ret;
+
+ ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(node), &vep);
+ if (ret) {
+ dev_err(stfcamss->dev, "endpoint not defined at %pOF\n", node);
+ return ret;
+ }
+
+ csd->port = vep.base.port;
+
+ return 0;
+}
+
+/*
+ * stfcamss_of_parse_ports - Parse ports node
+ * @stfcamss: STFCAMSS device
+ *
+ * Return number of "port" nodes found in "ports" node
+ */
+static int stfcamss_of_parse_ports(struct stfcamss *stfcamss)
+{
+ struct device_node *node = NULL;
+ int ret, num_subdevs = 0;
+
+ for_each_endpoint_of_node(stfcamss->dev->of_node, node) {
+ struct stfcamss_async_subdev *csd;
+
+ if (!of_device_is_available(node))
+ continue;
+
+ csd = v4l2_async_nf_add_fwnode_remote(&stfcamss->notifier,
+ of_fwnode_handle(node),
+ struct stfcamss_async_subdev);
+ if (IS_ERR(csd)) {
+ ret = PTR_ERR(csd);
+ dev_err(stfcamss->dev, "failed to add async notifier\n");
+ v4l2_async_nf_cleanup(&stfcamss->notifier);
+ return ret;
+ }
+
+ ret = stfcamss_of_parse_endpoint_node(stfcamss, node, csd);
+ if (ret)
+ return ret;
+
+ num_subdevs++;
+ }
+
+ return num_subdevs;
+}
+
+static int stfcamss_subdev_notifier_complete(struct v4l2_async_notifier *ntf)
+{
+ struct stfcamss *stfcamss =
+ container_of(ntf, struct stfcamss, notifier);
+
+ return v4l2_device_register_subdev_nodes(&stfcamss->v4l2_dev);
+}
+
+static const struct v4l2_async_notifier_operations
+stfcamss_subdev_notifier_ops = {
+ .complete = stfcamss_subdev_notifier_complete,
+};
+
+static void stfcamss_mc_init(struct platform_device *pdev,
+ struct stfcamss *stfcamss)
+{
+ stfcamss->media_dev.dev = stfcamss->dev;
+ strscpy(stfcamss->media_dev.model, "Starfive Camera Subsystem",
+ sizeof(stfcamss->media_dev.model));
+ media_device_init(&stfcamss->media_dev);
+
+ stfcamss->v4l2_dev.mdev = &stfcamss->media_dev;
+}
+
+/*
+ * stfcamss_probe - Probe STFCAMSS platform device
+ * @pdev: Pointer to STFCAMSS platform device
+ *
+ * Return 0 on success or a negative error code on failure
+ */
+static int stfcamss_probe(struct platform_device *pdev)
+{
+ struct stfcamss *stfcamss;
+ struct device *dev = &pdev->dev;
+ int ret, num_subdevs;
+ unsigned int i;
+
+ stfcamss = devm_kzalloc(dev, sizeof(*stfcamss), GFP_KERNEL);
+ if (!stfcamss)
+ return -ENOMEM;
+
+ stfcamss->dev = dev;
+
+ stfcamss->nclks = ARRAY_SIZE(stfcamss->sys_clk);
+ for (i = 0; i < stfcamss->nclks; ++i)
+ stfcamss->sys_clk[i].id = stfcamss_clocks[i];
+ ret = devm_clk_bulk_get(dev, stfcamss->nclks, stfcamss->sys_clk);
+ if (ret) {
+ dev_err(dev, "Failed to get clk controls\n");
+ return ret;
+ }
+
+ stfcamss->nrsts = ARRAY_SIZE(stfcamss->sys_rst);
+ for (i = 0; i < stfcamss->nrsts; ++i)
+ stfcamss->sys_rst[i].id = stfcamss_resets[i];
+ ret = devm_reset_control_bulk_get_shared(dev, stfcamss->nrsts,
+ stfcamss->sys_rst);
+ if (ret) {
+ dev_err(dev, "Failed to get reset controls\n");
+ return ret;
+ }
+
+ ret = stfcamss_get_mem_res(stfcamss);
+ if (ret) {
+ dev_err(dev, "Could not map registers\n");
+ return ret;
+ }
+
+ platform_set_drvdata(pdev, stfcamss);
+
+ v4l2_async_nf_init(&stfcamss->notifier);
+
+ num_subdevs = stfcamss_of_parse_ports(stfcamss);
+ if (num_subdevs < 0) {
+ ret = -ENODEV;
+ dev_err(dev, "Failed to get sub devices: %d\n", ret);
+ goto err_cleanup_notifier;
+ }
+
+ stfcamss_mc_init(pdev, stfcamss);
+
+ ret = v4l2_device_register(stfcamss->dev, &stfcamss->v4l2_dev);
+ if (ret < 0) {
+ dev_err(dev, "Failed to register V4L2 device: %d\n", ret);
+ goto err_cleanup_media_device;
+ }
+
+ ret = media_device_register(&stfcamss->media_dev);
+ if (ret) {
+ dev_err(dev, "Failed to register media device: %d\n", ret);
+ goto err_unregister_device;
+ }
+
+ pm_runtime_enable(dev);
+
+ stfcamss->notifier.ops = &stfcamss_subdev_notifier_ops;
+ ret = v4l2_async_nf_register(&stfcamss->v4l2_dev, &stfcamss->notifier);
+ if (ret) {
+ dev_err(dev, "Failed to register async subdev nodes: %d\n",
+ ret);
+ pm_runtime_disable(dev);
+ goto err_unregister_media_dev;
+ }
+
+ return 0;
+
+err_unregister_media_dev:
+ media_device_unregister(&stfcamss->media_dev);
+err_unregister_device:
+ v4l2_device_unregister(&stfcamss->v4l2_dev);
+err_cleanup_media_device:
+ media_device_cleanup(&stfcamss->media_dev);
+err_cleanup_notifier:
+ v4l2_async_nf_cleanup(&stfcamss->notifier);
+ return ret;
+}
+
+/*
+ * stfcamss_remove - Remove STFCAMSS platform device
+ * @pdev: Pointer to STFCAMSS platform device
+ *
+ * Always returns 0.
+ */
+static int stfcamss_remove(struct platform_device *pdev)
+{
+ struct stfcamss *stfcamss = platform_get_drvdata(pdev);
+
+ v4l2_device_unregister(&stfcamss->v4l2_dev);
+ media_device_cleanup(&stfcamss->media_dev);
+ pm_runtime_disable(&pdev->dev);
+
+ return 0;
+}
+
+static const struct of_device_id stfcamss_of_match[] = {
+ { .compatible = "starfive,jh7110-camss" },
+ { /* sentinel */ },
+};
+
+MODULE_DEVICE_TABLE(of, stfcamss_of_match);
+
+static int __maybe_unused stfcamss_runtime_suspend(struct device *dev)
+{
+ struct stfcamss *stfcamss = dev_get_drvdata(dev);
+ int ret;
+
+ ret = reset_control_bulk_assert(stfcamss->nrsts, stfcamss->sys_rst);
+ if (ret) {
+ dev_err(dev, "reset assert failed\n");
+ return ret;
+ }
+
+ clk_bulk_disable_unprepare(stfcamss->nclks, stfcamss->sys_clk);
+
+ return 0;
+}
+
+static int __maybe_unused stfcamss_runtime_resume(struct device *dev)
+{
+ struct stfcamss *stfcamss = dev_get_drvdata(dev);
+ int ret;
+
+ ret = clk_bulk_prepare_enable(stfcamss->nclks, stfcamss->sys_clk);
+ if (ret) {
+ dev_err(dev, "clock prepare enable failed\n");
+ return ret;
+ }
+
+ ret = reset_control_bulk_deassert(stfcamss->nrsts, stfcamss->sys_rst);
+ if (ret < 0) {
+ dev_err(dev, "cannot deassert resets\n");
+ clk_bulk_disable_unprepare(stfcamss->nclks, stfcamss->sys_clk);
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct dev_pm_ops stfcamss_pm_ops = {
+ SET_RUNTIME_PM_OPS(stfcamss_runtime_suspend,
+ stfcamss_runtime_resume,
+ NULL)
+};
+
+static struct platform_driver stfcamss_driver = {
+ .probe = stfcamss_probe,
+ .remove = stfcamss_remove,
+ .driver = {
+ .name = "starfive-camss",
+ .pm = &stfcamss_pm_ops,
+ .of_match_table = stfcamss_of_match,
+ },
+};
+
+module_platform_driver(stfcamss_driver);
+
+MODULE_AUTHOR("Jack Zhu <[email protected]>");
+MODULE_AUTHOR("Changhuang Liang <[email protected]>");
+MODULE_DESCRIPTION("StarFive Camera Subsystem driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/media/starfive/camss/stf_camss.h b/drivers/staging/media/starfive/camss/stf_camss.h
new file mode 100644
index 000000000000..6110433e59f7
--- /dev/null
+++ b/drivers/staging/media/starfive/camss/stf_camss.h
@@ -0,0 +1,129 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * stf_camss.h
+ *
+ * Starfive Camera Subsystem driver
+ *
+ * Copyright (C) 2021-2023 StarFive Technology Co., Ltd.
+ */
+
+#ifndef STF_CAMSS_H
+#define STF_CAMSS_H
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/reset.h>
+#include <media/media-device.h>
+#include <media/media-entity.h>
+#include <media/v4l2-async.h>
+#include <media/v4l2-device.h>
+
+enum stf_port_num {
+ STF_PORT_DVP = 0,
+ STF_PORT_CSI2RX
+};
+
+enum stf_clk {
+ STF_CLK_WRAPPER_CLK_C = 0,
+ STF_CLK_ISPCORE_2X,
+ STF_CLK_ISP_AXI,
+ STF_CLK_NUM
+};
+
+enum stf_rst {
+ STF_RST_WRAPPER_P = 0,
+ STF_RST_WRAPPER_C,
+ STF_RST_AXIWR,
+ STF_RST_ISP_TOP_N,
+ STF_RST_ISP_TOP_AXI,
+ STF_RST_NUM
+};
+
+struct stf_isr_data {
+ const char *name;
+ irqreturn_t (*isr)(int irq, void *priv);
+};
+
+struct stfcamss {
+ struct v4l2_device v4l2_dev;
+ struct media_device media_dev;
+ struct media_pipeline pipe;
+ struct device *dev;
+ struct v4l2_async_notifier notifier;
+ void __iomem *syscon_base;
+ void __iomem *isp_base;
+ struct clk_bulk_data sys_clk[STF_CLK_NUM];
+ int nclks;
+ struct reset_control_bulk_data sys_rst[STF_RST_NUM];
+ int nrsts;
+};
+
+struct stfcamss_async_subdev {
+ struct v4l2_async_subdev asd; /* must be first */
+ enum stf_port_num port;
+};
+
+static inline u32 stf_isp_reg_read(struct stfcamss *stfcamss, u32 reg)
+{
+ return ioread32(stfcamss->isp_base + reg);
+}
+
+static inline void stf_isp_reg_write(struct stfcamss *stfcamss,
+ u32 reg, u32 val)
+{
+ iowrite32(val, stfcamss->isp_base + reg);
+}
+
+static inline void stf_isp_reg_write_delay(struct stfcamss *stfcamss,
+ u32 reg, u32 val, u32 delay)
+{
+ iowrite32(val, stfcamss->isp_base + reg);
+ usleep_range(1000 * delay, 1000 * delay + 100);
+}
+
+static inline void stf_isp_reg_set_bit(struct stfcamss *stfcamss,
+ u32 reg, u32 mask, u32 val)
+{
+ u32 value;
+
+ value = ioread32(stfcamss->isp_base + reg) & ~mask;
+ val &= mask;
+ val |= value;
+ iowrite32(val, stfcamss->isp_base + reg);
+}
+
+static inline void stf_isp_reg_set(struct stfcamss *stfcamss, u32 reg, u32 mask)
+{
+ iowrite32(ioread32(stfcamss->isp_base + reg) | mask,
+ stfcamss->isp_base + reg);
+}
+
+static inline u32 stf_syscon_reg_read(struct stfcamss *stfcamss, u32 reg)
+{
+ return ioread32(stfcamss->syscon_base + reg);
+}
+
+static inline void stf_syscon_reg_write(struct stfcamss *stfcamss,
+ u32 reg, u32 val)
+{
+ iowrite32(val, stfcamss->syscon_base + reg);
+}
+
+static inline void stf_syscon_reg_set_bit(struct stfcamss *stfcamss,
+ u32 reg, u32 bit_mask)
+{
+ u32 value;
+
+ value = ioread32(stfcamss->syscon_base + reg);
+ iowrite32(value | bit_mask, stfcamss->syscon_base + reg);
+}
+
+static inline void stf_syscon_reg_clear_bit(struct stfcamss *stfcamss,
+ u32 reg, u32 bit_mask)
+{
+ u32 value;
+
+ value = ioread32(stfcamss->syscon_base + reg);
+ iowrite32(value & ~bit_mask, stfcamss->syscon_base + reg);
+}
+#endif /* STF_CAMSS_H */
--
2.34.1
Hi Greg,
On 2023/8/24 19:37, Greg Kroah-Hartman wrote:
> On Thu, Aug 24, 2023 at 04:01:01PM +0800, Jack Zhu wrote:
>> Hi,
>>
>> This series is the v8 series that attempts to support the Camera Subsystem
>> found on StarFive JH7110 SoC.
>
> I don't see anything here about why this is in drivers/staging/media/
> now and not just in drivers/media/. What is preventing this to be put
> into the correct place to start with? What needs to be done to the code
> to get it out of drivers/staging/media/ and who is going to do that
> work?
>
The series does not contain 3A interface. According to Laurent's suggestion,
we put the driver in the staging directory first. In the next stage, we will
continue to submit the 3A interface in the way of incremental development,
and finally expect the code to be placed in the drivers/media/.
> thanks,
>
> greg k-h
--
Regards,
Jack Zhu
On 2023/8/24 21:08, Greg Kroah-Hartman wrote:
> On Thu, Aug 24, 2023 at 08:23:33PM +0800, Jack Zhu wrote:
>> Hi Greg,
>>
>> On 2023/8/24 19:37, Greg Kroah-Hartman wrote:
>> > On Thu, Aug 24, 2023 at 04:01:01PM +0800, Jack Zhu wrote:
>> >> Hi,
>> >>
>> >> This series is the v8 series that attempts to support the Camera Subsystem
>> >> found on StarFive JH7110 SoC.
>> >
>> > I don't see anything here about why this is in drivers/staging/media/
>> > now and not just in drivers/media/. What is preventing this to be put
>> > into the correct place to start with? What needs to be done to the code
>> > to get it out of drivers/staging/media/ and who is going to do that
>> > work?
>> >
>>
>> The series does not contain 3A interface. According to Laurent's suggestion,
>> we put the driver in the staging directory first. In the next stage, we will
>> continue to submit the 3A interface in the way of incremental development,
>> and finally expect the code to be placed in the drivers/media/.
>
> Can you please say that in the changelog text for when you are adding
> the driver so that we know this?
>
Yes, will do it. Thank you for your suggestion!
> thanks,
>
> greg k-h
On 2023/8/24 21:34, Laurent Pinchart wrote:
> On Thu, Aug 24, 2023 at 03:08:33PM +0200, Greg Kroah-Hartman wrote:
>> On Thu, Aug 24, 2023 at 08:23:33PM +0800, Jack Zhu wrote:
>> > On 2023/8/24 19:37, Greg Kroah-Hartman wrote:
>> > > On Thu, Aug 24, 2023 at 04:01:01PM +0800, Jack Zhu wrote:
>> > >> Hi,
>> > >>
>> > >> This series is the v8 series that attempts to support the Camera Subsystem
>> > >> found on StarFive JH7110 SoC.
>> > >
>> > > I don't see anything here about why this is in drivers/staging/media/
>> > > now and not just in drivers/media/. What is preventing this to be put
>> > > into the correct place to start with? What needs to be done to the code
>> > > to get it out of drivers/staging/media/ and who is going to do that
>> > > work?
>> >
>> > The series does not contain 3A interface. According to Laurent's suggestion,
>> > we put the driver in the staging directory first. In the next stage, we will
>> > continue to submit the 3A interface in the way of incremental development,
>> > and finally expect the code to be placed in the drivers/media/.
>>
>> Can you please say that in the changelog text for when you are adding
>> the driver so that we know this?
>
> It's also customary to add a TODO file in the driver directory to list
> the work needed before moving the code to drivers/media/. Jack, could
> you please do so ?
>
Yes, thank you for your reminder.
>
--
Regards,
Jack Zhu
On 24/08/2023 10:01, Jack Zhu wrote:
> Add core driver for StarFive Camera Subsystem. The code parses
> the device platform resources and registers related devices.
>
> Reviewed-by: Bryan O'Donoghue <[email protected]>
> Signed-off-by: Jack Zhu <[email protected]>
> ---
> MAINTAINERS | 1 +
> drivers/staging/media/Kconfig | 2 +
> drivers/staging/media/Makefile | 1 +
> drivers/staging/media/starfive/Kconfig | 5 +
> drivers/staging/media/starfive/Makefile | 2 +
> drivers/staging/media/starfive/camss/Kconfig | 17 +
> drivers/staging/media/starfive/camss/Makefile | 9 +
> .../staging/media/starfive/camss/stf_camss.c | 316 ++++++++++++++++++
> .../staging/media/starfive/camss/stf_camss.h | 129 +++++++
> 9 files changed, 482 insertions(+)
> create mode 100644 drivers/staging/media/starfive/Kconfig
> create mode 100644 drivers/staging/media/starfive/Makefile
> create mode 100644 drivers/staging/media/starfive/camss/Kconfig
> create mode 100644 drivers/staging/media/starfive/camss/Makefile
> create mode 100644 drivers/staging/media/starfive/camss/stf_camss.c
> create mode 100644 drivers/staging/media/starfive/camss/stf_camss.h
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 4c63c0a85301..97d3054416ed 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -20258,6 +20258,7 @@ L: [email protected]
> S: Maintained
> F: Documentation/admin-guide/media/starfive_camss.rst
> F: Documentation/devicetree/bindings/media/starfive,jh7110-camss.yaml
> +F: drivers/staging/media/starfive/camss
>
> STARFIVE CRYPTO DRIVER
> M: Jia Jie Ho <[email protected]>
> diff --git a/drivers/staging/media/Kconfig b/drivers/staging/media/Kconfig
> index bc6c7b248f86..554c2e475ce3 100644
> --- a/drivers/staging/media/Kconfig
> +++ b/drivers/staging/media/Kconfig
> @@ -36,6 +36,8 @@ source "drivers/staging/media/omap4iss/Kconfig"
>
> source "drivers/staging/media/rkvdec/Kconfig"
>
> +source "drivers/staging/media/starfive/Kconfig"
> +
> source "drivers/staging/media/sunxi/Kconfig"
>
> source "drivers/staging/media/tegra-video/Kconfig"
> diff --git a/drivers/staging/media/Makefile b/drivers/staging/media/Makefile
> index 1a4c3a062e3d..dcaeeca0ee6d 100644
> --- a/drivers/staging/media/Makefile
> +++ b/drivers/staging/media/Makefile
> @@ -6,6 +6,7 @@ obj-$(CONFIG_VIDEO_MAX96712) += max96712/
> obj-$(CONFIG_VIDEO_MESON_VDEC) += meson/vdec/
> obj-$(CONFIG_VIDEO_OMAP4) += omap4iss/
> obj-$(CONFIG_VIDEO_ROCKCHIP_VDEC) += rkvdec/
> +obj-$(CONFIG_VIDEO_STARFIVE_CAMSS) += starfive/
> obj-$(CONFIG_VIDEO_SUNXI) += sunxi/
> obj-$(CONFIG_VIDEO_TEGRA) += tegra-video/
> obj-$(CONFIG_VIDEO_IPU3_IMGU) += ipu3/
> diff --git a/drivers/staging/media/starfive/Kconfig b/drivers/staging/media/starfive/Kconfig
> new file mode 100644
> index 000000000000..34727cf56072
> --- /dev/null
> +++ b/drivers/staging/media/starfive/Kconfig
> @@ -0,0 +1,5 @@
> +# SPDX-License-Identifier: GPL-2.0-only
> +
> +comment "StarFive media platform drivers"
> +
> +source "drivers/staging/media/starfive/camss/Kconfig"
> diff --git a/drivers/staging/media/starfive/Makefile b/drivers/staging/media/starfive/Makefile
> new file mode 100644
> index 000000000000..4639fa1bca32
> --- /dev/null
> +++ b/drivers/staging/media/starfive/Makefile
> @@ -0,0 +1,2 @@
> +# SPDX-License-Identifier: GPL-2.0-only
> +obj-y += camss/
> diff --git a/drivers/staging/media/starfive/camss/Kconfig b/drivers/staging/media/starfive/camss/Kconfig
> new file mode 100644
> index 000000000000..8d20e2bd2559
> --- /dev/null
> +++ b/drivers/staging/media/starfive/camss/Kconfig
> @@ -0,0 +1,17 @@
> +# SPDX-License-Identifier: GPL-2.0-only
> +config VIDEO_STARFIVE_CAMSS
> + tristate "Starfive Camera Subsystem driver"
> + depends on V4L_PLATFORM_DRIVERS
> + depends on VIDEO_DEV && OF
> + depends on HAS_DMA
> + depends on PM
> + select MEDIA_CONTROLLER
> + select VIDEO_V4L2_SUBDEV_API
> + select VIDEOBUF2_DMA_CONTIG
> + select V4L2_FWNODE
> + help
> + Enable this to support for the Starfive Camera subsystem
> + found on Starfive JH7110 SoC.
> +
> + To compile this driver as a module, choose M here: the
> + module will be called stf-camss.
Erm, isn't it called starfive-camss.ko?
Regards,
Hans
On 24/08/2023 10:01, Jack Zhu wrote:
> Add core driver for StarFive Camera Subsystem. The code parses
> the device platform resources and registers related devices.
>
> Reviewed-by: Bryan O'Donoghue <[email protected]>
> Signed-off-by: Jack Zhu <[email protected]>
> ---
> MAINTAINERS | 1 +
> drivers/staging/media/Kconfig | 2 +
> drivers/staging/media/Makefile | 1 +
> drivers/staging/media/starfive/Kconfig | 5 +
> drivers/staging/media/starfive/Makefile | 2 +
> drivers/staging/media/starfive/camss/Kconfig | 17 +
> drivers/staging/media/starfive/camss/Makefile | 9 +
> .../staging/media/starfive/camss/stf_camss.c | 316 ++++++++++++++++++
> .../staging/media/starfive/camss/stf_camss.h | 129 +++++++
> 9 files changed, 482 insertions(+)
> create mode 100644 drivers/staging/media/starfive/Kconfig
> create mode 100644 drivers/staging/media/starfive/Makefile
> create mode 100644 drivers/staging/media/starfive/camss/Kconfig
> create mode 100644 drivers/staging/media/starfive/camss/Makefile
> create mode 100644 drivers/staging/media/starfive/camss/stf_camss.c
> create mode 100644 drivers/staging/media/starfive/camss/stf_camss.h
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 4c63c0a85301..97d3054416ed 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -20258,6 +20258,7 @@ L: [email protected]
> S: Maintained
> F: Documentation/admin-guide/media/starfive_camss.rst
> F: Documentation/devicetree/bindings/media/starfive,jh7110-camss.yaml
> +F: drivers/staging/media/starfive/camss
>
> STARFIVE CRYPTO DRIVER
> M: Jia Jie Ho <[email protected]>
> diff --git a/drivers/staging/media/Kconfig b/drivers/staging/media/Kconfig
> index bc6c7b248f86..554c2e475ce3 100644
> --- a/drivers/staging/media/Kconfig
> +++ b/drivers/staging/media/Kconfig
> @@ -36,6 +36,8 @@ source "drivers/staging/media/omap4iss/Kconfig"
>
> source "drivers/staging/media/rkvdec/Kconfig"
>
> +source "drivers/staging/media/starfive/Kconfig"
> +
> source "drivers/staging/media/sunxi/Kconfig"
>
> source "drivers/staging/media/tegra-video/Kconfig"
> diff --git a/drivers/staging/media/Makefile b/drivers/staging/media/Makefile
> index 1a4c3a062e3d..dcaeeca0ee6d 100644
> --- a/drivers/staging/media/Makefile
> +++ b/drivers/staging/media/Makefile
> @@ -6,6 +6,7 @@ obj-$(CONFIG_VIDEO_MAX96712) += max96712/
> obj-$(CONFIG_VIDEO_MESON_VDEC) += meson/vdec/
> obj-$(CONFIG_VIDEO_OMAP4) += omap4iss/
> obj-$(CONFIG_VIDEO_ROCKCHIP_VDEC) += rkvdec/
> +obj-$(CONFIG_VIDEO_STARFIVE_CAMSS) += starfive/
> obj-$(CONFIG_VIDEO_SUNXI) += sunxi/
> obj-$(CONFIG_VIDEO_TEGRA) += tegra-video/
> obj-$(CONFIG_VIDEO_IPU3_IMGU) += ipu3/
> diff --git a/drivers/staging/media/starfive/Kconfig b/drivers/staging/media/starfive/Kconfig
> new file mode 100644
> index 000000000000..34727cf56072
> --- /dev/null
> +++ b/drivers/staging/media/starfive/Kconfig
> @@ -0,0 +1,5 @@
> +# SPDX-License-Identifier: GPL-2.0-only
> +
> +comment "StarFive media platform drivers"
> +
> +source "drivers/staging/media/starfive/camss/Kconfig"
> diff --git a/drivers/staging/media/starfive/Makefile b/drivers/staging/media/starfive/Makefile
> new file mode 100644
> index 000000000000..4639fa1bca32
> --- /dev/null
> +++ b/drivers/staging/media/starfive/Makefile
> @@ -0,0 +1,2 @@
> +# SPDX-License-Identifier: GPL-2.0-only
> +obj-y += camss/
> diff --git a/drivers/staging/media/starfive/camss/Kconfig b/drivers/staging/media/starfive/camss/Kconfig
> new file mode 100644
> index 000000000000..8d20e2bd2559
> --- /dev/null
> +++ b/drivers/staging/media/starfive/camss/Kconfig
> @@ -0,0 +1,17 @@
> +# SPDX-License-Identifier: GPL-2.0-only
> +config VIDEO_STARFIVE_CAMSS
> + tristate "Starfive Camera Subsystem driver"
> + depends on V4L_PLATFORM_DRIVERS
> + depends on VIDEO_DEV && OF
> + depends on HAS_DMA
> + depends on PM
> + select MEDIA_CONTROLLER
> + select VIDEO_V4L2_SUBDEV_API
> + select VIDEOBUF2_DMA_CONTIG
> + select V4L2_FWNODE
> + help
> + Enable this to support for the Starfive Camera subsystem
> + found on Starfive JH7110 SoC.
> +
> + To compile this driver as a module, choose M here: the
> + module will be called stf-camss.
This is actually called starfive-camss.ko!
Regards,
Hans
Hi Jack,
On 24/08/2023 10:01, Jack Zhu wrote:
> Hi,
>
> This series is the v8 series that attempts to support the Camera Subsystem
> found on StarFive JH7110 SoC.
>
> The following are the media graph for the device and the v4l2-compliance
> output.
Please note that this driver no longer compiles after v4l2-async changes were
merged to our media_stage tree.
Make sure you base your v9 on top of the master branch of
https://git.linuxtv.org/media_stage.git/
Regards,
Hans
>
> ===========================================================================
> [the media graph]:
>
> digraph board {
> rankdir=TB
> n00000001 [label="{{<port0> 0} | stf_isp\n/dev/v4l-subdev0 | {<port1> 1}}", shape=Mrecord, style=filled, fillcolor=green]
> n00000001:port1 -> n00000008 [style=dashed]
> n00000004 [label="capture_raw\n/dev/video0", shape=box, style=filled, fillcolor=yellow]
> n00000008 [label="capture_yuv\n/dev/video1", shape=box, style=filled, fillcolor=yellow]
> n0000000e [label="{{<port0> 0} | cdns_csi2rx.19800000.csi-bridge\n | {<port1> 1 | <port2> 2 | <port3> 3 | <port4> 4}}", shape=Mrecord, style=filled, fillcolor=green]
> n0000000e:port1 -> n00000001:port0 [style=dashed]
> n0000000e:port1 -> n00000004 [style=dashed]
> n00000018 [label="{{} | imx219 6-0010\n/dev/v4l-subdev1 | {<port0> 0}}", shape=Mrecord, style=filled, fillcolor=green]
> n00000018:port0 -> n0000000e:port0 [style=bold]
> }
>
> [the device topology]:
>
> Media controller API version 6.5.0
>
> Media device information
> ------------------------
> driver starfive-camss
> model Starfive Camera Subsystem
> serial
> bus info platform:19840000.camss
> hw revision 0x0
> driver version 6.5.0
>
> Device topology
> - entity 1: stf_isp (2 pads, 2 links)
> type V4L2 subdev subtype Unknown flags 0
> device node name /dev/v4l-subdev0
> pad0: Sink
> [fmt:SRGGB10_1X10/1920x1080 field:none colorspace:srgb
> crop.bounds:(0,0)/1920x1080
> crop:(0,0)/1920x1080]
> <- "cdns_csi2rx.19800000.csi-bridge":1 []
> pad1: Source
> [fmt:YUYV8_1_5X8/1920x1080 field:none colorspace:srgb
> crop.bounds:(0,0)/1920x1080
> crop:(0,0)/1920x1080]
> -> "capture_yuv":0 []
>
> - entity 4: capture_raw (1 pad, 1 link)
> type Node subtype V4L flags 0
> device node name /dev/video0
> pad0: Sink
> <- "cdns_csi2rx.19800000.csi-bridge":1 []
>
> - entity 8: capture_yuv (1 pad, 1 link)
> type Node subtype V4L flags 0
> device node name /dev/video1
> pad0: Sink
> <- "stf_isp":1 []
>
> - entity 14: cdns_csi2rx.19800000.csi-bridge (5 pads, 3 links)
> type V4L2 subdev subtype Unknown flags 0
> pad0: Sink
> <- "imx219 6-0010":0 [ENABLED,IMMUTABLE]
> pad1: Source
> -> "stf_isp":0 []
> -> "capture_raw":0 []
> pad2: Source
> pad3: Source
> pad4: Source
>
> - entity 24: imx219 6-0010 (1 pad, 1 link)
> type V4L2 subdev subtype Sensor flags 0
> device node name /dev/v4l-subdev1
> pad0: Source
> [fmt:SRGGB10_1X10/3280x2464 field:none colorspace:srgb xfer:srgb ycbcr:601 quantization:full-range
> crop.bounds:(8,8)/3280x2464
> crop:(8,8)/3280x2464]
> -> "cdns_csi2rx.19800000.csi-bridge":0 [ENABLED,IMMUTABLE]
>
> ===========================================================================
> [the v4l2-compliance output]:
>
> v4l2-compliance 1.24.1, 64 bits, 64-bit time_t
>
> Compliance test for stf camss device /dev/video1:
>
> Driver Info:
> Driver name : stf camss
> Card type : Starfive Camera Subsystem
> Bus info : platform:19840000.camss
> Driver version : 6.5.0
> Capabilities : 0x84200001
> Video Capture
> Streaming
> Extended Pix Format
> Device Capabilities
> Device Caps : 0x04200001
> Video Capture
> Streaming
> Extended Pix Format
> Media Driver Info:
> Driver name : starfive-camss
> Model : Starfive Camera Subsystem
> Serial :
> Bus info : platform:19840000.camss
> Media version : 6.5.0
> Hardware revision: 0x00000000 (0)
> Driver version : 6.5.0
> Interface Info:
> ID : 0x0300000a
> Type : V4L Video
> Entity Info:
> ID : 0x00000008 (8)
> Name : capture_yuv
> Function : V4L2 I/O
> Pad 0x01000009 : 0: Sink
> Link 0x0200000c: from remote pad 0x1000003 of entity 'stf_isp' (Unknown Function (00004009)): Data, Enabled
>
> Required ioctls:
> test MC information (see 'Media Driver Info' above): OK
> test VIDIOC_QUERYCAP: OK
> test invalid ioctls: OK
>
> Allow for multiple opens:
> test second /dev/video1 open: OK
> test VIDIOC_QUERYCAP: OK
> test VIDIOC_G/S_PRIORITY: OK
> test for unlimited opens: OK
>
> Debug ioctls:
> test VIDIOC_DBG_G/S_REGISTER: OK (Not Supported)
> test VIDIOC_LOG_STATUS: OK (Not Supported)
>
> Input ioctls:
> test VIDIOC_G/S_TUNER/ENUM_FREQ_BANDS: OK (Not Supported)
> test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
> test VIDIOC_S_HW_FREQ_SEEK: OK (Not Supported)
> test VIDIOC_ENUMAUDIO: OK (Not Supported)
> test VIDIOC_G/S/ENUMINPUT: OK (Not Supported)
> test VIDIOC_G/S_AUDIO: OK (Not Supported)
> Inputs: 0 Audio Inputs: 0 Tuners: 0
>
> Output ioctls:
> test VIDIOC_G/S_MODULATOR: OK (Not Supported)
> test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
> test VIDIOC_ENUMAUDOUT: OK (Not Supported)
> test VIDIOC_G/S/ENUMOUTPUT: OK (Not Supported)
> test VIDIOC_G/S_AUDOUT: OK (Not Supported)
> Outputs: 0 Audio Outputs: 0 Modulators: 0
>
> Input/Output configuration ioctls:
> test VIDIOC_ENUM/G/S/QUERY_STD: OK (Not Supported)
> test VIDIOC_ENUM/G/S/QUERY_DV_TIMINGS: OK (Not Supported)
> test VIDIOC_DV_TIMINGS_CAP: OK (Not Supported)
> test VIDIOC_G/S_EDID: OK (Not Supported)
>
> Control ioctls:
> test VIDIOC_QUERY_EXT_CTRL/QUERYMENU: OK (Not Supported)
> test VIDIOC_QUERYCTRL: OK (Not Supported)
> test VIDIOC_G/S_CTRL: OK (Not Supported)
> test VIDIOC_G/S/TRY_EXT_CTRLS: OK (Not Supported)
> test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: OK (Not Supported)
> test VIDIOC_G/S_JPEGCOMP: OK (Not Supported)
> Standard Controls: 0 Private Controls: 0
>
> Format ioctls:
> test VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: OK
> test VIDIOC_G/S_PARM: OK (Not Supported)
> test VIDIOC_G_FBUF: OK (Not Supported)
> test VIDIOC_G_FMT: OK
> test VIDIOC_TRY_FMT: OK
> test VIDIOC_S_FMT: OK
> test VIDIOC_G_SLICED_VBI_CAP: OK (Not Supported)
> test Cropping: OK (Not Supported)
> test Composing: OK (Not Supported)
> test Scaling: OK
>
> Codec ioctls:
> test VIDIOC_(TRY_)ENCODER_CMD: OK (Not Supported)
> test VIDIOC_G_ENC_INDEX: OK (Not Supported)
> test VIDIOC_(TRY_)DECODER_CMD: OK (Not Supported)
>
> Buffer ioctls:
> test VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: OK
> test VIDIOC_EXPBUF: OK
> test Requests: OK (Not Supported)
>
> Test input 0:
>
> Streaming ioctls:
> test read/write: OK (Not Supported)
> test blocking wait: OK
> test MMAP (no poll): OK
> test MMAP (select): OK
> test MMAP (epoll): OK
> test USERPTR (no poll): OK (Not Supported)
> test USERPTR (select): OK (Not Supported)
> test DMABUF: Cannot test, specify --expbuf-device
>
> Total for stf camss device /dev/video1: 53, Succeeded: 53, Failed: 0, Warnings: 0
>
> ===========================================================================
>
> Changes in v8:
> - Rebased on v6.5-rc7.
> - Dropped VIN subdev.
> - Created two new video devices: capture_raw and capture_yuv, to replace
> the previous video devices.
> - Dropped VB2_READ io methods.
> - Recursively called .s_stream() on subdevs.
>
> v7 link: https://lore.kernel.org/all/[email protected]/
>
> Changes in v7:
> - HAS_DMA is used instead of DMA_CMA in Kconfig.
> - Dropped some non-essential member variables.
> - Used v4l2_async_nf_add_fwnode_remote() to simplify the relevant code.
> - Modified some Local variable types in the function.
> - Used v4l2_create_fwnode_links_to_pad() to simplify the relevant code.
> - Added error handling for clk_prepare_enable().
> - Simplified stfcamss_format_info struct and modified the relevant code.
> - Dropped enum_input, g_input and s_input.
> - Unified v4l2_ioctl_ops struct.
> - Used v4l2_fh_open()/vb2_fop_release to replace deprecated APIs.
> - Added a camss directory under the starfive directory and modified the
> patch title.
>
> v6 link: https://lore.kernel.org/all/[email protected]/
>
> Changes in v6:
> - Added 'bus-type' in bindings example.
> - Corrected spelling errors.
> - As reviewed by Bryan, used 'nclks' and 'nrsts' variables.
> - Added lccf config for ISP.
>
> v5 link: https://lore.kernel.org/all/[email protected]/
>
> Changes in v5:
> - Rebased on v6.4-rc1.
> - Added new patch.
> - Modified ISP driver.
>
> v4 link: https://lore.kernel.org/all/[email protected]/
>
> Previous cover letter from v4:
>
> This patch series adds support for the StarFive Camera Subsystem
> found on StarFive JH7110 SoC.
>
> The driver implements V4L2, Media controller and V4L2 subdev interfaces.
> Camera sensor using V4L2 subdev interface in the kernel is supported.
>
> The driver is tested on VisionFive V2 board with IMX219 camera sensor.
> GStreamer 1.18.5 with v4l2src plugin is supported.
>
> Previous version link, missing v1 version:
>
> v3: https://lore.kernel.org/all/[email protected]/
> v2: https://lore.kernel.org/all/[email protected]/
>
> Jack Zhu (8):
> media: dt-bindings: Add JH7110 Camera Subsystem
> media: admin-guide: Add starfive_camss.rst for Starfive Camera
> Subsystem
> media: staging: media: starfive: camss: Add core driver
> media: staging: media: starfive: camss: Add video driver
> media: staging: media: starfive: camss: Add ISP driver
> media: staging: media: starfive: camss: Add capture driver
> media: staging: media: starfive: camss: Add interrupt handling
> media: staging: media: starfive: camss: Register devices
>
> .../admin-guide/media/starfive_camss.rst | 72 +++
> .../media/starfive_camss_graph.dot | 12 +
> .../admin-guide/media/v4l-drivers.rst | 1 +
> .../bindings/media/starfive,jh7110-camss.yaml | 180 ++++++
> MAINTAINERS | 9 +
> drivers/staging/media/Kconfig | 2 +
> drivers/staging/media/Makefile | 1 +
> drivers/staging/media/starfive/Kconfig | 5 +
> drivers/staging/media/starfive/Makefile | 2 +
> drivers/staging/media/starfive/camss/Kconfig | 17 +
> drivers/staging/media/starfive/camss/Makefile | 13 +
> .../staging/media/starfive/camss/stf_camss.c | 432 +++++++++++++
> .../staging/media/starfive/camss/stf_camss.h | 134 ++++
> .../media/starfive/camss/stf_capture.c | 603 ++++++++++++++++++
> .../media/starfive/camss/stf_capture.h | 87 +++
> .../staging/media/starfive/camss/stf_isp.c | 407 ++++++++++++
> .../staging/media/starfive/camss/stf_isp.h | 428 +++++++++++++
> .../media/starfive/camss/stf_isp_hw_ops.c | 445 +++++++++++++
> .../staging/media/starfive/camss/stf_video.c | 557 ++++++++++++++++
> .../staging/media/starfive/camss/stf_video.h | 100 +++
> 20 files changed, 3507 insertions(+)
> create mode 100644 Documentation/admin-guide/media/starfive_camss.rst
> create mode 100644 Documentation/admin-guide/media/starfive_camss_graph.dot
> create mode 100644 Documentation/devicetree/bindings/media/starfive,jh7110-camss.yaml
> create mode 100644 drivers/staging/media/starfive/Kconfig
> create mode 100644 drivers/staging/media/starfive/Makefile
> create mode 100644 drivers/staging/media/starfive/camss/Kconfig
> create mode 100644 drivers/staging/media/starfive/camss/Makefile
> create mode 100644 drivers/staging/media/starfive/camss/stf_camss.c
> create mode 100644 drivers/staging/media/starfive/camss/stf_camss.h
> create mode 100644 drivers/staging/media/starfive/camss/stf_capture.c
> create mode 100644 drivers/staging/media/starfive/camss/stf_capture.h
> create mode 100644 drivers/staging/media/starfive/camss/stf_isp.c
> create mode 100644 drivers/staging/media/starfive/camss/stf_isp.h
> create mode 100644 drivers/staging/media/starfive/camss/stf_isp_hw_ops.c
> create mode 100644 drivers/staging/media/starfive/camss/stf_video.c
> create mode 100644 drivers/staging/media/starfive/camss/stf_video.h
>