summaryrefslogtreecommitdiff
path: root/drivers/staging
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2026-04-15 08:32:10 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2026-04-15 08:32:10 -0700
commit00c6649bafef628955569dd39a59e3170e48f7b5 (patch)
tree597ea4250d8e340daca614e1cc9b982391d91c2f /drivers/staging
parent1f5ffc672165ff851063a5fd044b727ab2517ae3 (diff)
parent4fbeef21f5387234111b5d52924e77757626faa5 (diff)
Merge tag 'media/v7.1-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
Pull media updates from Mauro Carvalho Chehab: - new CSI tegra support, covering Tegra20 and Tegra30 - new camera sensor drivers: T4ka3 and ov2732 - m88ds3103: add 3103c chip support - uvcvideo: add support for Intel RealSense D436/D555 and P010 pixel format - synopsys csi2rx: add i.MX93 support - imx8-isi: add i.MX95 support - imx8mq-mipi-csi2: add i.MX8ULP support - dw100: add V4L2 requests support - support for DTV devices from Hauppauge got some improvements - media staging: dropped starfive-camss driver - media docs: document multi-committers model and improve maint profile - media core: - add v4l2_subdev_get_frame_desc_passthrough() helper - improve error handling in fwnode parsing - lots of driver fixes, cleanups and improvements * tag 'media/v7.1-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (251 commits) Revert "media: cx231xx: add USB ID 2040:8360 for Hauppauge WinTV-HVR-935" media: synopsys: csi2rx: add i.MX93 support media: dt-bindings: add NXP i.MX93 compatible string media: synopsys: csi2rx: Use enum and u32 array for register offsets media: synopsys: csi2rx: implement .get_frame_desc() callback media: synopsys: csi2rx: only check errors from devm_clk_bulk_get_all() media: synopsys: csi2rx: use devm_reset_control_get_optional_exclusive() media: i2c: imx283: add support for non-continuous MIPI clock mode media: i2c: ov08d10: add support for 24 MHz input clock media: i2c: ov08d10: add support for reset and power management media: i2c: ov08d10: add support for binding via device tree dt-bindings: media: i2c: document Omnivision OV08D10 CMOS image sensor media: i2c: ov08d10: add missing newline to prints media: i2c: ov08d10: fix some typos in comments media: i2c: ov08d10: remove duplicate register write media: i2c: ov08d10: fix image vertical start setting media: i2c: ov08d10: fix runtime PM handling in probe staging: media: ipu7: Update TODO media: Add t4ka3 camera sensor driver media: i2c: Add ov2732 image sensor driver ...
Diffstat (limited to 'drivers/staging')
-rw-r--r--drivers/staging/media/Kconfig2
-rw-r--r--drivers/staging/media/Makefile1
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_ioctl.c4
-rw-r--r--drivers/staging/media/av7110/av7110.c2
-rw-r--r--drivers/staging/media/av7110/av7110_ir.c1
-rw-r--r--drivers/staging/media/imx/imx-media-csi.c86
-rw-r--r--drivers/staging/media/imx/imx-media-of.c3
-rw-r--r--drivers/staging/media/imx/imx-media-vdic.c2
-rw-r--r--drivers/staging/media/imx/imx-media.h2
-rw-r--r--drivers/staging/media/ipu3/ipu3.c2
-rw-r--r--drivers/staging/media/ipu7/TODO12
-rw-r--r--drivers/staging/media/starfive/Kconfig5
-rw-r--r--drivers/staging/media/starfive/Makefile2
-rw-r--r--drivers/staging/media/starfive/camss/Kconfig18
-rw-r--r--drivers/staging/media/starfive/camss/Makefile13
-rw-r--r--drivers/staging/media/starfive/camss/TODO.txt4
-rw-r--r--drivers/staging/media/starfive/camss/stf-camss.c438
-rw-r--r--drivers/staging/media/starfive/camss/stf-camss.h134
-rw-r--r--drivers/staging/media/starfive/camss/stf-capture.c605
-rw-r--r--drivers/staging/media/starfive/camss/stf-capture.h86
-rw-r--r--drivers/staging/media/starfive/camss/stf-isp-hw-ops.c445
-rw-r--r--drivers/staging/media/starfive/camss/stf-isp.c379
-rw-r--r--drivers/staging/media/starfive/camss/stf-isp.h428
-rw-r--r--drivers/staging/media/starfive/camss/stf-video.c570
-rw-r--r--drivers/staging/media/starfive/camss/stf-video.h100
-rw-r--r--drivers/staging/media/tegra-video/Makefile1
-rw-r--r--drivers/staging/media/tegra-video/csi.c64
-rw-r--r--drivers/staging/media/tegra-video/csi.h22
-rw-r--r--drivers/staging/media/tegra-video/tegra20.c820
-rw-r--r--drivers/staging/media/tegra-video/vi.c58
-rw-r--r--drivers/staging/media/tegra-video/vi.h6
-rw-r--r--drivers/staging/media/tegra-video/video.c8
-rw-r--r--drivers/staging/media/tegra-video/vip.c2
-rw-r--r--drivers/staging/media/tegra-video/vip.h2
34 files changed, 881 insertions, 3446 deletions
diff --git a/drivers/staging/media/Kconfig b/drivers/staging/media/Kconfig
index ab250c89cd4d..1aa31bddf970 100644
--- a/drivers/staging/media/Kconfig
+++ b/drivers/staging/media/Kconfig
@@ -34,8 +34,6 @@ source "drivers/staging/media/max96712/Kconfig"
source "drivers/staging/media/meson/vdec/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 4a073938b2b2..6f78b0edde1e 100644
--- a/drivers/staging/media/Makefile
+++ b/drivers/staging/media/Makefile
@@ -4,7 +4,6 @@ obj-$(CONFIG_INTEL_ATOMISP) += atomisp/
obj-$(CONFIG_VIDEO_IMX_MEDIA) += imx/
obj-$(CONFIG_VIDEO_MAX96712) += max96712/
obj-$(CONFIG_VIDEO_MESON_VDEC) += meson/vdec/
-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/atomisp/pci/atomisp_ioctl.c b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c
index a7f22de1c889..50366bf10f32 100644
--- a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c
+++ b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c
@@ -1356,6 +1356,10 @@ static int atomisp_s_parm(struct file *file, void *fh,
static long atomisp_vidioc_default(struct file *file, void *fh,
bool valid_prio, unsigned int cmd, void *arg)
{
+ /* Disable all private IOCTLs for now! */
+ if (cmd)
+ return -EINVAL;
+
struct video_device *vdev = video_devdata(file);
struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd;
int err;
diff --git a/drivers/staging/media/av7110/av7110.c b/drivers/staging/media/av7110/av7110.c
index 607992100baf..014d0c6f0a8b 100644
--- a/drivers/staging/media/av7110/av7110.c
+++ b/drivers/staging/media/av7110/av7110.c
@@ -460,7 +460,7 @@ static void gpioirq(struct tasklet_struct *t)
if (saa7146_wait_for_debi_done(av7110->dev, 0)) {
pr_err("%s(): saa7146_wait_for_debi_done timed out\n", __func__);
- BUG(); /* maybe we should try resetting the debi? */
+ return;
}
spin_lock(&av7110->debilock);
diff --git a/drivers/staging/media/av7110/av7110_ir.c b/drivers/staging/media/av7110/av7110_ir.c
index 68b3979ba5f2..fdae467fd7ab 100644
--- a/drivers/staging/media/av7110/av7110_ir.c
+++ b/drivers/staging/media/av7110/av7110_ir.c
@@ -151,6 +151,7 @@ int av7110_ir_init(struct av7110 *av7110)
void av7110_ir_exit(struct av7110 *av7110)
{
rc_unregister_device(av7110->ir.rcdev);
+ rc_free_device(av7110->ir.rcdev);
}
//MODULE_AUTHOR("Holger Waechtler <holger@convergence.de>, Oliver Endriss <o.endriss@gmx.de>");
diff --git a/drivers/staging/media/imx/imx-media-csi.c b/drivers/staging/media/imx/imx-media-csi.c
index fd7e37d803e7..ef22a083f8eb 100644
--- a/drivers/staging/media/imx/imx-media-csi.c
+++ b/drivers/staging/media/imx/imx-media-csi.c
@@ -97,9 +97,6 @@ struct csi_priv {
/* the mipi virtual channel number at link validate */
int vc_num;
- /* media bus config of the upstream subdevice CSI is receiving from */
- struct v4l2_mbus_config mbus_cfg;
-
spinlock_t irqlock; /* protect eof_irq handler */
struct timer_list eof_timeout_timer;
int eof_irq;
@@ -403,7 +400,8 @@ static void csi_idmac_unsetup_vb2_buf(struct csi_priv *priv,
}
/* init the SMFC IDMAC channel */
-static int csi_idmac_setup_channel(struct csi_priv *priv)
+static int csi_idmac_setup_channel(struct csi_priv *priv,
+ struct v4l2_mbus_config *mbus_cfg)
{
struct imx_media_video_dev *vdev = priv->vdev;
const struct imx_media_pixfmt *incc;
@@ -432,7 +430,7 @@ static int csi_idmac_setup_channel(struct csi_priv *priv)
image.phys0 = phys[0];
image.phys1 = phys[1];
- passthrough = requires_passthrough(&priv->mbus_cfg, infmt, incc);
+ passthrough = requires_passthrough(mbus_cfg, infmt, incc);
passthrough_cycles = 1;
/*
@@ -572,11 +570,12 @@ static void csi_idmac_unsetup(struct csi_priv *priv,
csi_idmac_unsetup_vb2_buf(priv, state);
}
-static int csi_idmac_setup(struct csi_priv *priv)
+static int csi_idmac_setup(struct csi_priv *priv,
+ struct v4l2_mbus_config *mbus_cfg)
{
int ret;
- ret = csi_idmac_setup_channel(priv);
+ ret = csi_idmac_setup_channel(priv, mbus_cfg);
if (ret)
return ret;
@@ -595,7 +594,8 @@ static int csi_idmac_setup(struct csi_priv *priv)
return 0;
}
-static int csi_idmac_start(struct csi_priv *priv)
+static int csi_idmac_start(struct csi_priv *priv,
+ struct v4l2_mbus_config *mbus_cfg)
{
struct imx_media_video_dev *vdev = priv->vdev;
int ret;
@@ -619,7 +619,7 @@ static int csi_idmac_start(struct csi_priv *priv)
priv->last_eof = false;
priv->nfb4eof = false;
- ret = csi_idmac_setup(priv);
+ ret = csi_idmac_setup(priv, mbus_cfg);
if (ret) {
v4l2_err(&priv->sd, "csi_idmac_setup failed: %d\n", ret);
goto out_free_dma_buf;
@@ -701,7 +701,8 @@ static void csi_idmac_stop(struct csi_priv *priv)
}
/* Update the CSI whole sensor and active windows */
-static int csi_setup(struct csi_priv *priv)
+static int csi_setup(struct csi_priv *priv,
+ struct v4l2_mbus_config *mbus_cfg)
{
struct v4l2_mbus_framefmt *infmt, *outfmt;
const struct imx_media_pixfmt *incc;
@@ -719,7 +720,7 @@ static int csi_setup(struct csi_priv *priv)
* if cycles is set, we need to handle this over multiple cycles as
* generic/bayer data
*/
- if (is_parallel_bus(&priv->mbus_cfg) && incc->cycles) {
+ if (is_parallel_bus(mbus_cfg) && incc->cycles) {
if_fmt.width *= incc->cycles;
crop.width *= incc->cycles;
}
@@ -730,7 +731,7 @@ static int csi_setup(struct csi_priv *priv)
priv->crop.width == 2 * priv->compose.width,
priv->crop.height == 2 * priv->compose.height);
- ipu_csi_init_interface(priv->csi, &priv->mbus_cfg, &if_fmt, outfmt);
+ ipu_csi_init_interface(priv->csi, mbus_cfg, &if_fmt, outfmt);
ipu_csi_set_dest(priv->csi, priv->dest);
@@ -743,14 +744,46 @@ static int csi_setup(struct csi_priv *priv)
return 0;
}
+static void csi_set_src(struct csi_priv *priv,
+ struct v4l2_mbus_config *mbus_cfg)
+{
+ bool is_csi2;
+
+ is_csi2 = !is_parallel_bus(mbus_cfg);
+ if (is_csi2) {
+ /*
+ * NOTE! It seems the virtual channels from the mipi csi-2
+ * receiver are used only for routing by the video mux's,
+ * or for hard-wired routing to the CSI's. Once the stream
+ * enters the CSI's however, they are treated internally
+ * in the IPU as virtual channel 0.
+ */
+ ipu_csi_set_mipi_datatype(priv->csi, 0,
+ &priv->format_mbus[CSI_SINK_PAD]);
+ }
+
+ /* select either parallel or MIPI-CSI2 as input to CSI */
+ ipu_set_csi_src_mux(priv->ipu, priv->csi_id, is_csi2);
+}
+
static int csi_start(struct csi_priv *priv)
{
+ struct v4l2_mbus_config mbus_cfg = { .type = 0 };
struct v4l2_fract *input_fi, *output_fi;
int ret;
+ ret = csi_get_upstream_mbus_config(priv, &mbus_cfg);
+ if (ret) {
+ v4l2_err(&priv->sd,
+ "failed to get upstream media bus configuration\n");
+ return ret;
+ }
+
input_fi = &priv->frame_interval[CSI_SINK_PAD];
output_fi = &priv->frame_interval[priv->active_output_pad];
+ csi_set_src(priv, &mbus_cfg);
+
/* start upstream */
ret = v4l2_subdev_call(priv->src_sd, video, s_stream, 1);
ret = (ret && ret != -ENOIOCTLCMD) ? ret : 0;
@@ -758,7 +791,7 @@ static int csi_start(struct csi_priv *priv)
return ret;
/* Skip first few frames from a BT.656 source */
- if (priv->mbus_cfg.type == V4L2_MBUS_BT656) {
+ if (mbus_cfg.type == V4L2_MBUS_BT656) {
u32 delay_usec, bad_frames = 20;
delay_usec = DIV_ROUND_UP_ULL((u64)USEC_PER_SEC *
@@ -769,12 +802,12 @@ static int csi_start(struct csi_priv *priv)
}
if (priv->dest == IPU_CSI_DEST_IDMAC) {
- ret = csi_idmac_start(priv);
+ ret = csi_idmac_start(priv, &mbus_cfg);
if (ret)
goto stop_upstream;
}
- ret = csi_setup(priv);
+ ret = csi_setup(priv, &mbus_cfg);
if (ret)
goto idmac_stop;
@@ -1121,7 +1154,6 @@ static int csi_link_validate(struct v4l2_subdev *sd,
{
struct csi_priv *priv = v4l2_get_subdevdata(sd);
struct v4l2_mbus_config mbus_cfg = { .type = 0 };
- bool is_csi2;
int ret;
ret = v4l2_subdev_link_validate_default(sd, link,
@@ -1136,26 +1168,6 @@ static int csi_link_validate(struct v4l2_subdev *sd,
return ret;
}
- mutex_lock(&priv->lock);
-
- priv->mbus_cfg = mbus_cfg;
- is_csi2 = !is_parallel_bus(&mbus_cfg);
- if (is_csi2) {
- /*
- * NOTE! It seems the virtual channels from the mipi csi-2
- * receiver are used only for routing by the video mux's,
- * or for hard-wired routing to the CSI's. Once the stream
- * enters the CSI's however, they are treated internally
- * in the IPU as virtual channel 0.
- */
- ipu_csi_set_mipi_datatype(priv->csi, 0,
- &priv->format_mbus[CSI_SINK_PAD]);
- }
-
- /* select either parallel or MIPI-CSI2 as input to CSI */
- ipu_set_csi_src_mux(priv->ipu, priv->csi_id, is_csi2);
-
- mutex_unlock(&priv->lock);
return ret;
}
@@ -1509,7 +1521,7 @@ static void csi_try_fmt(struct csi_priv *priv,
}
imx_media_try_colorimetry(&sdformat->format,
- priv->active_output_pad == CSI_SRC_PAD_DIRECT);
+ priv->active_output_pad == CSI_SRC_PAD_DIRECT);
}
static int csi_set_fmt(struct v4l2_subdev *sd,
diff --git a/drivers/staging/media/imx/imx-media-of.c b/drivers/staging/media/imx/imx-media-of.c
index bb28daa4d713..7413551052ae 100644
--- a/drivers/staging/media/imx/imx-media-of.c
+++ b/drivers/staging/media/imx/imx-media-of.c
@@ -57,9 +57,8 @@ int imx_media_add_of_subdevs(struct imx_media_dev *imxmd,
of_node_put(csi_np);
if (ret) {
/* unavailable or already added is not an error */
- if (ret == -ENODEV || ret == -EEXIST) {
+ if (ret == -ENODEV || ret == -EEXIST)
continue;
- }
/* other error, can't continue */
return ret;
diff --git a/drivers/staging/media/imx/imx-media-vdic.c b/drivers/staging/media/imx/imx-media-vdic.c
index 86f2b30cb06c..58f1112e28e5 100644
--- a/drivers/staging/media/imx/imx-media-vdic.c
+++ b/drivers/staging/media/imx/imx-media-vdic.c
@@ -616,7 +616,7 @@ out:
}
static int vdic_link_setup(struct media_entity *entity,
- const struct media_pad *local,
+ const struct media_pad *local,
const struct media_pad *remote, u32 flags)
{
struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
diff --git a/drivers/staging/media/imx/imx-media.h b/drivers/staging/media/imx/imx-media.h
index f095d9134fee..135daca7d55b 100644
--- a/drivers/staging/media/imx/imx-media.h
+++ b/drivers/staging/media/imx/imx-media.h
@@ -231,7 +231,7 @@ int imx_media_probe_complete(struct v4l2_async_notifier *notifier);
struct imx_media_dev *imx_media_dev_init(struct device *dev,
const struct media_device_ops *ops);
int imx_media_dev_notifier_register(struct imx_media_dev *imxmd,
- const struct v4l2_async_notifier_operations *ops);
+ const struct v4l2_async_notifier_operations *ops);
/* imx-media-fim.c */
struct imx_media_fim;
diff --git a/drivers/staging/media/ipu3/ipu3.c b/drivers/staging/media/ipu3/ipu3.c
index bdf5a457752b..84c4d0bf027d 100644
--- a/drivers/staging/media/ipu3/ipu3.c
+++ b/drivers/staging/media/ipu3/ipu3.c
@@ -151,7 +151,7 @@ static int imgu_dummybufs_init(struct imgu_device *imgu, unsigned int pipe)
/* May be called from atomic context */
static struct imgu_css_buffer *imgu_dummybufs_get(struct imgu_device *imgu,
- int queue, unsigned int pipe)
+ int queue, unsigned int pipe)
{
unsigned int i;
struct imgu_media_pipe *imgu_pipe = &imgu->imgu_pipe[pipe];
diff --git a/drivers/staging/media/ipu7/TODO b/drivers/staging/media/ipu7/TODO
index 7fbc37059adf..dc27bb6463da 100644
--- a/drivers/staging/media/ipu7/TODO
+++ b/drivers/staging/media/ipu7/TODO
@@ -19,10 +19,8 @@ staging directory.
IPU7 driver is expected to work with the common IPU module in future.
- Register definition cleanup
- Cleanup the register definitions - remove some unnecessary definitions
- remove 'U' suffix for hexadecimal and decimal values and add IPU7 prefix
- for IPU7 specific registers.
- Some ISYS IO sub-blocks register definitions are offset values from
- specific sub-block base, but it is not clear and well suited for driver
- to use, need to update the register definitions to make it more clear
- and readable.
+ Add IPU7 prefix for IPU7 specific registers and related macros. Some
+ ISYS IO sub-blocks register definitions are offset values from specific
+ sub-block base, but it is not clear and well suited for driver to use,
+ need to update the register definitions to make it more clear and
+ readable.
diff --git a/drivers/staging/media/starfive/Kconfig b/drivers/staging/media/starfive/Kconfig
deleted file mode 100644
index 34727cf56072..000000000000
--- a/drivers/staging/media/starfive/Kconfig
+++ /dev/null
@@ -1,5 +0,0 @@
-# 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
deleted file mode 100644
index 4639fa1bca32..000000000000
--- a/drivers/staging/media/starfive/Makefile
+++ /dev/null
@@ -1,2 +0,0 @@
-# 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
deleted file mode 100644
index 9ea5708fe409..000000000000
--- a/drivers/staging/media/starfive/camss/Kconfig
+++ /dev/null
@@ -1,18 +0,0 @@
-# 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
- depends on ARCH_STARFIVE || COMPILE_TEST
- 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 starfive-camss.
diff --git a/drivers/staging/media/starfive/camss/Makefile b/drivers/staging/media/starfive/camss/Makefile
deleted file mode 100644
index 005790202e7b..000000000000
--- a/drivers/staging/media/starfive/camss/Makefile
+++ /dev/null
@@ -1,13 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-#
-# Makefile for StarFive Camera Subsystem driver
-#
-
-starfive-camss-objs += \
- stf-camss.o \
- stf-capture.o \
- stf-isp.o \
- stf-isp-hw-ops.o \
- stf-video.o
-
-obj-$(CONFIG_VIDEO_STARFIVE_CAMSS) += starfive-camss.o
diff --git a/drivers/staging/media/starfive/camss/TODO.txt b/drivers/staging/media/starfive/camss/TODO.txt
deleted file mode 100644
index 7d459f4f09d0..000000000000
--- a/drivers/staging/media/starfive/camss/TODO.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-Unstaging requirements:
-- Add userspace support which demonstrates the ability to receive statistics and
- adapt hardware modules configuration accordingly;
-- Add documentation for description of the statistics data structures;
diff --git a/drivers/staging/media/starfive/camss/stf-camss.c b/drivers/staging/media/starfive/camss/stf-camss.c
deleted file mode 100644
index 259aaad010d2..000000000000
--- a/drivers/staging/media/starfive/camss/stf-camss.c
+++ /dev/null
@@ -1,438 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * stf_camss.c
- *
- * Starfive Camera Subsystem driver
- *
- * Copyright (C) 2021-2023 StarFive Technology Co., Ltd.
- *
- * Author: Jack Zhu <jack.zhu@starfivetech.com>
- * Author: Changhuang Liang <changhuang.liang@starfivetech.com>
- *
- */
-#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[] = {
- "wrapper_clk_c",
- "ispcore_2x",
- "isp_axi",
-};
-
-static const char * const stfcamss_resets[] = {
- "wrapper_p",
- "wrapper_c",
- "axiwr",
- "isp_top_n",
- "isp_top_axi",
-};
-
-static const struct stf_isr_data stf_isrs[] = {
- {"wr_irq", stf_wr_irq_handler},
- {"isp_irq", stf_isp_irq_handler},
- {"line_irq", stf_line_irq_handler},
-};
-
-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");
- goto err_cleanup;
- }
-
- ret = stfcamss_of_parse_endpoint_node(stfcamss, node, csd);
- if (ret)
- goto err_cleanup;
-
- num_subdevs++;
- }
-
- return num_subdevs;
-
-err_cleanup:
- of_node_put(node);
- return ret;
-}
-
-static int stfcamss_register_devs(struct stfcamss *stfcamss)
-{
- struct stf_capture *cap_yuv = &stfcamss->captures[STF_CAPTURE_YUV];
- struct stf_isp_dev *isp_dev = &stfcamss->isp_dev;
- int ret;
-
- ret = stf_isp_register(isp_dev, &stfcamss->v4l2_dev);
- if (ret < 0) {
- dev_err(stfcamss->dev,
- "failed to register stf isp%d entity: %d\n", 0, ret);
- return ret;
- }
-
- ret = stf_capture_register(stfcamss, &stfcamss->v4l2_dev);
- if (ret < 0) {
- dev_err(stfcamss->dev,
- "failed to register capture: %d\n", ret);
- goto err_isp_unregister;
- }
-
- ret = media_create_pad_link(&isp_dev->subdev.entity, STF_ISP_PAD_SRC,
- &cap_yuv->video.vdev.entity, 0, 0);
- if (ret)
- goto err_cap_unregister;
-
- cap_yuv->video.source_subdev = &isp_dev->subdev;
-
- return ret;
-
-err_cap_unregister:
- stf_capture_unregister(stfcamss);
-err_isp_unregister:
- stf_isp_unregister(&stfcamss->isp_dev);
-
- return ret;
-}
-
-static void stfcamss_unregister_devs(struct stfcamss *stfcamss)
-{
- struct stf_capture *cap_yuv = &stfcamss->captures[STF_CAPTURE_YUV];
- struct stf_isp_dev *isp_dev = &stfcamss->isp_dev;
-
- media_entity_remove_links(&isp_dev->subdev.entity);
- media_entity_remove_links(&cap_yuv->video.vdev.entity);
-
- stf_isp_unregister(&stfcamss->isp_dev);
- stf_capture_unregister(stfcamss);
-}
-
-static int stfcamss_subdev_notifier_bound(struct v4l2_async_notifier *async,
- struct v4l2_subdev *subdev,
- struct v4l2_async_connection *asc)
-{
- struct stfcamss *stfcamss =
- container_of(async, struct stfcamss, notifier);
- struct stfcamss_async_subdev *csd =
- container_of(asc, struct stfcamss_async_subdev, asd);
- enum stf_port_num port = csd->port;
- struct stf_isp_dev *isp_dev = &stfcamss->isp_dev;
- struct stf_capture *cap_raw = &stfcamss->captures[STF_CAPTURE_RAW];
- struct media_pad *pad;
- int ret;
-
- if (port == STF_PORT_CSI2RX) {
- pad = &isp_dev->pads[STF_ISP_PAD_SINK];
- } else {
- dev_err(stfcamss->dev, "not support port %d\n", port);
- return -EPERM;
- }
-
- ret = v4l2_create_fwnode_links_to_pad(subdev, pad, 0);
- if (ret)
- return ret;
-
- ret = media_create_pad_link(&subdev->entity, 1,
- &cap_raw->video.vdev.entity, 0, 0);
- if (ret)
- return ret;
-
- isp_dev->source_subdev = subdev;
- cap_raw->video.source_subdev = subdev;
-
- return 0;
-}
-
-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 = {
- .bound = stfcamss_subdev_notifier_bound,
- .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;
-
- for (i = 0; i < ARRAY_SIZE(stf_isrs); ++i) {
- int irq;
-
- irq = platform_get_irq(pdev, i);
- if (irq < 0)
- return irq;
-
- ret = devm_request_irq(stfcamss->dev, irq, stf_isrs[i].isr, 0,
- stf_isrs[i].name, stfcamss);
- if (ret) {
- dev_err(dev, "request irq failed: %d\n", ret);
- return ret;
- }
- }
-
- 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, &stfcamss->v4l2_dev);
-
- 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;
- }
-
- ret = stf_isp_init(stfcamss);
- if (ret < 0) {
- dev_err(dev, "Failed to init isp: %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;
- }
-
- ret = stfcamss_register_devs(stfcamss);
- if (ret < 0) {
- dev_err(dev, "Failed to register subdevice: %d\n", ret);
- goto err_unregister_media_dev;
- }
-
- pm_runtime_enable(dev);
-
- stfcamss->notifier.ops = &stfcamss_subdev_notifier_ops;
- ret = v4l2_async_nf_register(&stfcamss->notifier);
- if (ret) {
- dev_err(dev, "Failed to register async subdev nodes: %d\n",
- ret);
- pm_runtime_disable(dev);
- goto err_unregister_subdevs;
- }
-
- return 0;
-
-err_unregister_subdevs:
- stfcamss_unregister_devs(stfcamss);
-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
- */
-static void stfcamss_remove(struct platform_device *pdev)
-{
- struct stfcamss *stfcamss = platform_get_drvdata(pdev);
-
- stfcamss_unregister_devs(stfcamss);
- v4l2_device_unregister(&stfcamss->v4l2_dev);
- media_device_cleanup(&stfcamss->media_dev);
- v4l2_async_nf_cleanup(&stfcamss->notifier);
- pm_runtime_disable(&pdev->dev);
-}
-
-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 <jack.zhu@starfivetech.com>");
-MODULE_AUTHOR("Changhuang Liang <changhuang.liang@starfivetech.com>");
-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
deleted file mode 100644
index e2b0cfb437bd..000000000000
--- a/drivers/staging/media/starfive/camss/stf-camss.h
+++ /dev/null
@@ -1,134 +0,0 @@
-/* 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>
-
-#include "stf-isp.h"
-#include "stf-capture.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 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;
- 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_connection 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 */
diff --git a/drivers/staging/media/starfive/camss/stf-capture.c b/drivers/staging/media/starfive/camss/stf-capture.c
deleted file mode 100644
index e15d2e97eb0b..000000000000
--- a/drivers/staging/media/starfive/camss/stf-capture.c
+++ /dev/null
@@ -1,605 +0,0 @@
-// 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 = 16,
- },
- {
- .code = MEDIA_BUS_FMT_SGRBG10_1X10,
- .pixelformat = V4L2_PIX_FMT_SGRBG10,
- .planes = 1,
- .vsub = { 1 },
- .bpp = 16,
- },
- {
- .code = MEDIA_BUS_FMT_SGBRG10_1X10,
- .pixelformat = V4L2_PIX_FMT_SGBRG10,
- .planes = 1,
- .vsub = { 1 },
- .bpp = 16,
- },
- {
- .code = MEDIA_BUS_FMT_SBGGR10_1X10,
- .pixelformat = V4L2_PIX_FMT_SBGGR10,
- .planes = 1,
- .vsub = { 1 },
- .bpp = 16,
- },
-};
-
-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) {
- const struct v4l2_pix_format *pix = &video->active_fmt.fmt.pix;
-
- 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(pix->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
deleted file mode 100644
index 2f9740b7e500..000000000000
--- a/drivers/staging/media/starfive/camss/stf-capture.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/* 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
diff --git a/drivers/staging/media/starfive/camss/stf-isp-hw-ops.c b/drivers/staging/media/starfive/camss/stf-isp-hw-ops.c
deleted file mode 100644
index c34631ff9422..000000000000
--- a/drivers/staging/media/starfive/camss/stf-isp-hw-ops.c
+++ /dev/null
@@ -1,445 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * stf_isp_hw_ops.c
- *
- * Register interface file for StarFive ISP driver
- *
- * Copyright (C) 2021-2023 StarFive Technology Co., Ltd.
- *
- */
-
-#include "stf-camss.h"
-
-static void stf_isp_config_obc(struct stfcamss *stfcamss)
-{
- u32 reg_val, reg_add;
-
- stf_isp_reg_write(stfcamss, ISP_REG_OBC_CFG, OBC_W_H(11) | OBC_W_W(11));
-
- reg_val = GAIN_D_POINT(0x40) | GAIN_C_POINT(0x40) |
- GAIN_B_POINT(0x40) | GAIN_A_POINT(0x40);
- for (reg_add = ISP_REG_OBCG_CFG_0; reg_add <= ISP_REG_OBCG_CFG_3;) {
- stf_isp_reg_write(stfcamss, reg_add, reg_val);
- reg_add += 4;
- }
-
- reg_val = OFFSET_D_POINT(0) | OFFSET_C_POINT(0) |
- OFFSET_B_POINT(0) | OFFSET_A_POINT(0);
- for (reg_add = ISP_REG_OBCO_CFG_0; reg_add <= ISP_REG_OBCO_CFG_3;) {
- stf_isp_reg_write(stfcamss, reg_add, reg_val);
- reg_add += 4;
- }
-}
-
-static void stf_isp_config_oecf(struct stfcamss *stfcamss)
-{
- u32 reg_add, par_val;
- u16 par_h, par_l;
-
- par_h = 0x10; par_l = 0;
- par_val = OCEF_PAR_H(par_h) | OCEF_PAR_L(par_l);
- for (reg_add = ISP_REG_OECF_X0_CFG0; reg_add <= ISP_REG_OECF_Y3_CFG0;) {
- stf_isp_reg_write(stfcamss, reg_add, par_val);
- reg_add += 0x20;
- }
-
- par_h = 0x40; par_l = 0x20;
- par_val = OCEF_PAR_H(par_h) | OCEF_PAR_L(par_l);
- for (reg_add = ISP_REG_OECF_X0_CFG1; reg_add <= ISP_REG_OECF_Y3_CFG1;) {
- stf_isp_reg_write(stfcamss, reg_add, par_val);
- reg_add += 0x20;
- }
-
- par_h = 0x80; par_l = 0x60;
- par_val = OCEF_PAR_H(par_h) | OCEF_PAR_L(par_l);
- for (reg_add = ISP_REG_OECF_X0_CFG2; reg_add <= ISP_REG_OECF_Y3_CFG2;) {
- stf_isp_reg_write(stfcamss, reg_add, par_val);
- reg_add += 0x20;
- }
-
- par_h = 0xc0; par_l = 0xa0;
- par_val = OCEF_PAR_H(par_h) | OCEF_PAR_L(par_l);
- for (reg_add = ISP_REG_OECF_X0_CFG3; reg_add <= ISP_REG_OECF_Y3_CFG3;) {
- stf_isp_reg_write(stfcamss, reg_add, par_val);
- reg_add += 0x20;
- }
-
- par_h = 0x100; par_l = 0xe0;
- par_val = OCEF_PAR_H(par_h) | OCEF_PAR_L(par_l);
- for (reg_add = ISP_REG_OECF_X0_CFG4; reg_add <= ISP_REG_OECF_Y3_CFG4;) {
- stf_isp_reg_write(stfcamss, reg_add, par_val);
- reg_add += 0x20;
- }
-
- par_h = 0x200; par_l = 0x180;
- par_val = OCEF_PAR_H(par_h) | OCEF_PAR_L(par_l);
- for (reg_add = ISP_REG_OECF_X0_CFG5; reg_add <= ISP_REG_OECF_Y3_CFG5;) {
- stf_isp_reg_write(stfcamss, reg_add, par_val);
- reg_add += 0x20;
- }
-
- par_h = 0x300; par_l = 0x280;
- par_val = OCEF_PAR_H(par_h) | OCEF_PAR_L(par_l);
- for (reg_add = ISP_REG_OECF_X0_CFG6; reg_add <= ISP_REG_OECF_Y3_CFG6;) {
- stf_isp_reg_write(stfcamss, reg_add, par_val);
- reg_add += 0x20;
- }
-
- par_h = 0x3fe; par_l = 0x380;
- par_val = OCEF_PAR_H(par_h) | OCEF_PAR_L(par_l);
- for (reg_add = ISP_REG_OECF_X0_CFG7; reg_add <= ISP_REG_OECF_Y3_CFG7;) {
- stf_isp_reg_write(stfcamss, reg_add, par_val);
- reg_add += 0x20;
- }
-
- par_h = 0x80; par_l = 0x80;
- par_val = OCEF_PAR_H(par_h) | OCEF_PAR_L(par_l);
- for (reg_add = ISP_REG_OECF_S0_CFG0; reg_add <= ISP_REG_OECF_S3_CFG7;) {
- stf_isp_reg_write(stfcamss, reg_add, par_val);
- reg_add += 4;
- }
-}
-
-static void stf_isp_config_lccf(struct stfcamss *stfcamss)
-{
- u32 reg_add;
-
- stf_isp_reg_write(stfcamss, ISP_REG_LCCF_CFG_0,
- Y_DISTANCE(0x21C) | X_DISTANCE(0x3C0));
- stf_isp_reg_write(stfcamss, ISP_REG_LCCF_CFG_1, LCCF_MAX_DIS(0xb));
-
- for (reg_add = ISP_REG_LCCF_CFG_2; reg_add <= ISP_REG_LCCF_CFG_5;) {
- stf_isp_reg_write(stfcamss, reg_add,
- LCCF_F2_PAR(0x0) | LCCF_F1_PAR(0x0));
- reg_add += 4;
- }
-}
-
-static void stf_isp_config_awb(struct stfcamss *stfcamss)
-{
- u32 reg_val, reg_add;
- u16 symbol_h, symbol_l;
-
- symbol_h = 0x0; symbol_l = 0x0;
- reg_val = AWB_X_SYMBOL_H(symbol_h) | AWB_X_SYMBOL_L(symbol_l);
-
- for (reg_add = ISP_REG_AWB_X0_CFG_0; reg_add <= ISP_REG_AWB_X3_CFG_1;) {
- stf_isp_reg_write(stfcamss, reg_add, reg_val);
- reg_add += 4;
- }
-
- symbol_h = 0x0, symbol_l = 0x0;
- reg_val = AWB_Y_SYMBOL_H(symbol_h) | AWB_Y_SYMBOL_L(symbol_l);
-
- for (reg_add = ISP_REG_AWB_Y0_CFG_0; reg_add <= ISP_REG_AWB_Y3_CFG_1;) {
- stf_isp_reg_write(stfcamss, reg_add, reg_val);
- reg_add += 4;
- }
-
- symbol_h = 0x80, symbol_l = 0x80;
- reg_val = AWB_S_SYMBOL_H(symbol_h) | AWB_S_SYMBOL_L(symbol_l);
-
- for (reg_add = ISP_REG_AWB_S0_CFG_0; reg_add <= ISP_REG_AWB_S3_CFG_1;) {
- stf_isp_reg_write(stfcamss, reg_add, reg_val);
- reg_add += 4;
- }
-}
-
-static void stf_isp_config_grgb(struct stfcamss *stfcamss)
-{
- stf_isp_reg_write(stfcamss, ISP_REG_ICTC,
- GF_MODE(1) | MAXGT(0x140) | MINGT(0x40));
- stf_isp_reg_write(stfcamss, ISP_REG_IDBC, BADGT(0x200) | BADXT(0x200));
-}
-
-static void stf_isp_config_cfa(struct stfcamss *stfcamss)
-{
- stf_isp_reg_write(stfcamss, ISP_REG_RAW_FORMAT_CFG,
- SMY13(0) | SMY12(1) | SMY11(0) | SMY10(1) | SMY3(2) |
- SMY2(3) | SMY1(2) | SMY0(3));
- stf_isp_reg_write(stfcamss, ISP_REG_ICFAM, CROSS_COV(3) | HV_W(2));
-}
-
-static void stf_isp_config_ccm(struct stfcamss *stfcamss)
-{
- u32 reg_add;
-
- stf_isp_reg_write(stfcamss, ISP_REG_ICAMD_0, DNRM_F(6) | CCM_M_DAT(0));
-
- for (reg_add = ISP_REG_ICAMD_12; reg_add <= ISP_REG_ICAMD_20;) {
- stf_isp_reg_write(stfcamss, reg_add, CCM_M_DAT(0x80));
- reg_add += 0x10;
- }
-
- stf_isp_reg_write(stfcamss, ISP_REG_ICAMD_24, CCM_M_DAT(0x700));
- stf_isp_reg_write(stfcamss, ISP_REG_ICAMD_25, CCM_M_DAT(0x200));
-}
-
-static void stf_isp_config_gamma(struct stfcamss *stfcamss)
-{
- u32 reg_val, reg_add;
- u16 gamma_slope_v, gamma_v;
-
- gamma_slope_v = 0x2400; gamma_v = 0x0;
- reg_val = GAMMA_S_VAL(gamma_slope_v) | GAMMA_VAL(gamma_v);
- stf_isp_reg_write(stfcamss, ISP_REG_GAMMA_VAL0, reg_val);
-
- gamma_slope_v = 0x800; gamma_v = 0x20;
- for (reg_add = ISP_REG_GAMMA_VAL1; reg_add <= ISP_REG_GAMMA_VAL7;) {
- reg_val = GAMMA_S_VAL(gamma_slope_v) | GAMMA_VAL(gamma_v);
- stf_isp_reg_write(stfcamss, reg_add, reg_val);
- reg_add += 4;
- gamma_v += 0x20;
- }
-
- gamma_v = 0x100;
- for (reg_add = ISP_REG_GAMMA_VAL8; reg_add <= ISP_REG_GAMMA_VAL13;) {
- reg_val = GAMMA_S_VAL(gamma_slope_v) | GAMMA_VAL(gamma_v);
- stf_isp_reg_write(stfcamss, reg_add, reg_val);
- reg_add += 4;
- gamma_v += 0x80;
- }
-
- gamma_v = 0x3fe;
- reg_val = GAMMA_S_VAL(gamma_slope_v) | GAMMA_VAL(gamma_v);
- stf_isp_reg_write(stfcamss, ISP_REG_GAMMA_VAL14, reg_val);
-}
-
-static void stf_isp_config_r2y(struct stfcamss *stfcamss)
-{
- stf_isp_reg_write(stfcamss, ISP_REG_R2Y_0, 0x4C);
- stf_isp_reg_write(stfcamss, ISP_REG_R2Y_1, 0x97);
- stf_isp_reg_write(stfcamss, ISP_REG_R2Y_2, 0x1d);
- stf_isp_reg_write(stfcamss, ISP_REG_R2Y_3, 0x1d5);
- stf_isp_reg_write(stfcamss, ISP_REG_R2Y_4, 0x1ac);
- stf_isp_reg_write(stfcamss, ISP_REG_R2Y_5, 0x80);
- stf_isp_reg_write(stfcamss, ISP_REG_R2Y_6, 0x80);
- stf_isp_reg_write(stfcamss, ISP_REG_R2Y_7, 0x194);
- stf_isp_reg_write(stfcamss, ISP_REG_R2Y_8, 0x1ec);
-}
-
-static void stf_isp_config_y_curve(struct stfcamss *stfcamss)
-{
- u32 reg_add;
- u16 y_curve;
-
- y_curve = 0x0;
- for (reg_add = ISP_REG_YCURVE_0; reg_add <= ISP_REG_YCURVE_63;) {
- stf_isp_reg_write(stfcamss, reg_add, y_curve);
- reg_add += 4;
- y_curve += 0x10;
- }
-}
-
-static void stf_isp_config_sharpen(struct stfcamss *sc)
-{
- u32 reg_add;
-
- stf_isp_reg_write(sc, ISP_REG_SHARPEN0, S_DELTA(0x7) | S_WEIGHT(0xf));
- stf_isp_reg_write(sc, ISP_REG_SHARPEN1, S_DELTA(0x18) | S_WEIGHT(0xf));
- stf_isp_reg_write(sc, ISP_REG_SHARPEN2, S_DELTA(0x80) | S_WEIGHT(0xf));
- stf_isp_reg_write(sc, ISP_REG_SHARPEN3, S_DELTA(0x100) | S_WEIGHT(0xf));
- stf_isp_reg_write(sc, ISP_REG_SHARPEN4, S_DELTA(0x10) | S_WEIGHT(0xf));
- stf_isp_reg_write(sc, ISP_REG_SHARPEN5, S_DELTA(0x60) | S_WEIGHT(0xf));
- stf_isp_reg_write(sc, ISP_REG_SHARPEN6, S_DELTA(0x100) | S_WEIGHT(0xf));
- stf_isp_reg_write(sc, ISP_REG_SHARPEN7, S_DELTA(0x190) | S_WEIGHT(0xf));
- stf_isp_reg_write(sc, ISP_REG_SHARPEN8, S_DELTA(0x0) | S_WEIGHT(0xf));
-
- for (reg_add = ISP_REG_SHARPEN9; reg_add <= ISP_REG_SHARPEN14;) {
- stf_isp_reg_write(sc, reg_add, S_WEIGHT(0xf));
- reg_add += 4;
- }
-
- for (reg_add = ISP_REG_SHARPEN_FS0; reg_add <= ISP_REG_SHARPEN_FS5;) {
- stf_isp_reg_write(sc, reg_add, S_FACTOR(0x10) | S_SLOPE(0x0));
- reg_add += 4;
- }
-
- stf_isp_reg_write(sc, ISP_REG_SHARPEN_WN,
- PDIRF(0x8) | NDIRF(0x8) | WSUM(0xd7c));
- stf_isp_reg_write(sc, ISP_REG_IUVS1, UVDIFF2(0xC0) | UVDIFF1(0x40));
- stf_isp_reg_write(sc, ISP_REG_IUVS2, UVF(0xff) | UVSLOPE(0x0));
- stf_isp_reg_write(sc, ISP_REG_IUVCKS1,
- UVCKDIFF2(0xa0) | UVCKDIFF1(0x40));
-}
-
-static void stf_isp_config_dnyuv(struct stfcamss *stfcamss)
-{
- u32 reg_val;
-
- reg_val = YUVSW5(7) | YUVSW4(7) | YUVSW3(7) | YUVSW2(7) |
- YUVSW1(7) | YUVSW0(7);
- stf_isp_reg_write(stfcamss, ISP_REG_DNYUV_YSWR0, reg_val);
- stf_isp_reg_write(stfcamss, ISP_REG_DNYUV_CSWR0, reg_val);
-
- reg_val = YUVSW3(7) | YUVSW2(7) | YUVSW1(7) | YUVSW0(7);
- stf_isp_reg_write(stfcamss, ISP_REG_DNYUV_YSWR1, reg_val);
- stf_isp_reg_write(stfcamss, ISP_REG_DNYUV_CSWR1, reg_val);
-
- reg_val = CURVE_D_H(0x60) | CURVE_D_L(0x40);
- stf_isp_reg_write(stfcamss, ISP_REG_DNYUV_YDR0, reg_val);
- stf_isp_reg_write(stfcamss, ISP_REG_DNYUV_CDR0, reg_val);
-
- reg_val = CURVE_D_H(0xd8) | CURVE_D_L(0x90);
- stf_isp_reg_write(stfcamss, ISP_REG_DNYUV_YDR1, reg_val);
- stf_isp_reg_write(stfcamss, ISP_REG_DNYUV_CDR1, reg_val);
-
- reg_val = CURVE_D_H(0x1e6) | CURVE_D_L(0x144);
- stf_isp_reg_write(stfcamss, ISP_REG_DNYUV_YDR2, reg_val);
- stf_isp_reg_write(stfcamss, ISP_REG_DNYUV_CDR2, reg_val);
-}
-
-static void stf_isp_config_sat(struct stfcamss *stfcamss)
-{
- stf_isp_reg_write(stfcamss, ISP_REG_CS_GAIN, CMAD(0x0) | CMAB(0x100));
- stf_isp_reg_write(stfcamss, ISP_REG_CS_THRESHOLD, CMD(0x1f) | CMB(0x1));
- stf_isp_reg_write(stfcamss, ISP_REG_CS_OFFSET, VOFF(0x0) | UOFF(0x0));
- stf_isp_reg_write(stfcamss, ISP_REG_CS_HUE_F, SIN(0x0) | COS(0x100));
- stf_isp_reg_write(stfcamss, ISP_REG_CS_SCALE, 0x8);
- stf_isp_reg_write(stfcamss, ISP_REG_YADJ0, YOIR(0x401) | YIMIN(0x1));
- stf_isp_reg_write(stfcamss, ISP_REG_YADJ1, YOMAX(0x3ff) | YOMIN(0x1));
-}
-
-int stf_isp_reset(struct stf_isp_dev *isp_dev)
-{
- stf_isp_reg_set_bit(isp_dev->stfcamss, ISP_REG_ISP_CTRL_0,
- ISPC_RST_MASK, ISPC_RST);
- stf_isp_reg_set_bit(isp_dev->stfcamss, ISP_REG_ISP_CTRL_0,
- ISPC_RST_MASK, 0);
-
- return 0;
-}
-
-void stf_isp_init_cfg(struct stf_isp_dev *isp_dev)
-{
- stf_isp_reg_write(isp_dev->stfcamss, ISP_REG_DC_CFG_1, DC_AXI_ID(0x0));
- stf_isp_reg_write(isp_dev->stfcamss, ISP_REG_DEC_CFG,
- DEC_V_KEEP(0x0) |
- DEC_V_PERIOD(0x0) |
- DEC_H_KEEP(0x0) |
- DEC_H_PERIOD(0x0));
-
- stf_isp_config_obc(isp_dev->stfcamss);
- stf_isp_config_oecf(isp_dev->stfcamss);
- stf_isp_config_lccf(isp_dev->stfcamss);
- stf_isp_config_awb(isp_dev->stfcamss);
- stf_isp_config_grgb(isp_dev->stfcamss);
- stf_isp_config_cfa(isp_dev->stfcamss);
- stf_isp_config_ccm(isp_dev->stfcamss);
- stf_isp_config_gamma(isp_dev->stfcamss);
- stf_isp_config_r2y(isp_dev->stfcamss);
- stf_isp_config_y_curve(isp_dev->stfcamss);
- stf_isp_config_sharpen(isp_dev->stfcamss);
- stf_isp_config_dnyuv(isp_dev->stfcamss);
- stf_isp_config_sat(isp_dev->stfcamss);
-
- stf_isp_reg_write(isp_dev->stfcamss, ISP_REG_CSI_MODULE_CFG,
- CSI_DUMP_EN | CSI_SC_EN | CSI_AWB_EN |
- CSI_LCCF_EN | CSI_OECF_EN | CSI_OBC_EN | CSI_DEC_EN);
- stf_isp_reg_write(isp_dev->stfcamss, ISP_REG_ISP_CTRL_1,
- CTRL_SAT(1) | CTRL_DBC | CTRL_CTC | CTRL_YHIST |
- CTRL_YCURVE | CTRL_BIYUV | CTRL_SCE | CTRL_EE |
- CTRL_CCE | CTRL_RGE | CTRL_CME | CTRL_AE | CTRL_CE);
-}
-
-static void stf_isp_config_crop(struct stfcamss *stfcamss,
- struct v4l2_rect *crop)
-{
- u32 bpp = stfcamss->isp_dev.current_fmt->bpp;
- u32 val;
-
- val = VSTART_CAP(crop->top) | HSTART_CAP(crop->left);
- stf_isp_reg_write(stfcamss, ISP_REG_PIC_CAPTURE_START_CFG, val);
-
- val = VEND_CAP(crop->height + crop->top - 1) |
- HEND_CAP(crop->width + crop->left - 1);
- stf_isp_reg_write(stfcamss, ISP_REG_PIC_CAPTURE_END_CFG, val);
-
- val = H_ACT_CAP(crop->height) | W_ACT_CAP(crop->width);
- stf_isp_reg_write(stfcamss, ISP_REG_PIPELINE_XY_SIZE, val);
-
- val = ALIGN(crop->width * bpp / 8, STFCAMSS_FRAME_WIDTH_ALIGN_8);
- stf_isp_reg_write(stfcamss, ISP_REG_STRIDE, val);
-}
-
-static void stf_isp_config_raw_fmt(struct stfcamss *stfcamss, u32 mcode)
-{
- u32 val, val1;
-
- switch (mcode) {
- case MEDIA_BUS_FMT_SRGGB10_1X10:
- case MEDIA_BUS_FMT_SRGGB8_1X8:
- /* 3 2 3 2 1 0 1 0 B Gb B Gb Gr R Gr R */
- val = SMY13(3) | SMY12(2) | SMY11(3) | SMY10(2) |
- SMY3(1) | SMY2(0) | SMY1(1) | SMY0(0);
- val1 = CTRL_SAT(0x0);
- break;
- case MEDIA_BUS_FMT_SGRBG10_1X10:
- case MEDIA_BUS_FMT_SGRBG8_1X8:
- /* 2 3 2 3 0 1 0 1, Gb B Gb B R Gr R Gr */
- val = SMY13(2) | SMY12(3) | SMY11(2) | SMY10(3) |
- SMY3(0) | SMY2(1) | SMY1(0) | SMY0(1);
- val1 = CTRL_SAT(0x2);
- break;
- case MEDIA_BUS_FMT_SGBRG10_1X10:
- case MEDIA_BUS_FMT_SGBRG8_1X8:
- /* 1 0 1 0 3 2 3 2, Gr R Gr R B Gb B Gb */
- val = SMY13(1) | SMY12(0) | SMY11(1) | SMY10(0) |
- SMY3(3) | SMY2(2) | SMY1(3) | SMY0(2);
- val1 = CTRL_SAT(0x3);
- break;
- case MEDIA_BUS_FMT_SBGGR10_1X10:
- case MEDIA_BUS_FMT_SBGGR8_1X8:
- /* 0 1 0 1 2 3 2 3 R Gr R Gr Gb B Gb B */
- val = SMY13(0) | SMY12(1) | SMY11(0) | SMY10(1) |
- SMY3(2) | SMY2(3) | SMY1(2) | SMY0(3);
- val1 = CTRL_SAT(0x1);
- break;
- default:
- val = SMY13(0) | SMY12(1) | SMY11(0) | SMY10(1) |
- SMY3(2) | SMY2(3) | SMY1(2) | SMY0(3);
- val1 = CTRL_SAT(0x1);
- break;
- }
- stf_isp_reg_write(stfcamss, ISP_REG_RAW_FORMAT_CFG, val);
- stf_isp_reg_set_bit(stfcamss, ISP_REG_ISP_CTRL_1, CTRL_SAT_MASK, val1);
-}
-
-void stf_isp_settings(struct stf_isp_dev *isp_dev,
- struct v4l2_rect *crop, u32 mcode)
-{
- struct stfcamss *stfcamss = isp_dev->stfcamss;
-
- stf_isp_config_crop(stfcamss, crop);
- stf_isp_config_raw_fmt(stfcamss, mcode);
-
- stf_isp_reg_set_bit(stfcamss, ISP_REG_DUMP_CFG_1,
- DUMP_BURST_LEN_MASK | DUMP_SD_MASK,
- DUMP_BURST_LEN(3));
-
- stf_isp_reg_write(stfcamss, ISP_REG_ITIIWSR,
- ITI_HSIZE(IMAGE_MAX_HEIGH) |
- ITI_WSIZE(IMAGE_MAX_WIDTH));
- stf_isp_reg_write(stfcamss, ISP_REG_ITIDWLSR, 0x960);
- stf_isp_reg_write(stfcamss, ISP_REG_ITIDRLSR, 0x960);
- stf_isp_reg_write(stfcamss, ISP_REG_SENSOR, IMAGER_SEL(1));
-}
-
-void stf_isp_stream_set(struct stf_isp_dev *isp_dev)
-{
- struct stfcamss *stfcamss = isp_dev->stfcamss;
-
- stf_isp_reg_write_delay(stfcamss, ISP_REG_ISP_CTRL_0,
- ISPC_ENUO | ISPC_ENLS | ISPC_RST, 10);
- stf_isp_reg_write_delay(stfcamss, ISP_REG_ISP_CTRL_0,
- ISPC_ENUO | ISPC_ENLS, 10);
- stf_isp_reg_write(stfcamss, ISP_REG_IESHD, SHAD_UP_M);
- stf_isp_reg_write_delay(stfcamss, ISP_REG_ISP_CTRL_0,
- ISPC_ENUO | ISPC_ENLS | ISPC_EN, 10);
- stf_isp_reg_write_delay(stfcamss, ISP_REG_CSIINTS,
- CSI_INTS(1) | CSI_SHA_M(4), 10);
- stf_isp_reg_write_delay(stfcamss, ISP_REG_CSIINTS,
- CSI_INTS(2) | CSI_SHA_M(4), 10);
- stf_isp_reg_write_delay(stfcamss, ISP_REG_CSI_INPUT_EN_AND_STATUS,
- CSI_EN_S, 10);
-}
diff --git a/drivers/staging/media/starfive/camss/stf-isp.c b/drivers/staging/media/starfive/camss/stf-isp.c
deleted file mode 100644
index df7a903fbb1b..000000000000
--- a/drivers/staging/media/starfive/camss/stf-isp.c
+++ /dev/null
@@ -1,379 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * stf_isp.c
- *
- * StarFive Camera Subsystem - ISP Module
- *
- * Copyright (C) 2021-2023 StarFive Technology Co., Ltd.
- */
-#include <media/v4l2-rect.h>
-
-#include "stf-camss.h"
-
-static int isp_set_selection(struct v4l2_subdev *sd,
- struct v4l2_subdev_state *state,
- struct v4l2_subdev_selection *sel);
-
-static const struct stf_isp_format isp_formats_sink[] = {
- { MEDIA_BUS_FMT_SRGGB10_1X10, 10 },
- { MEDIA_BUS_FMT_SGRBG10_1X10, 10 },
- { MEDIA_BUS_FMT_SGBRG10_1X10, 10 },
- { MEDIA_BUS_FMT_SBGGR10_1X10, 10 },
-};
-
-static const struct stf_isp_format isp_formats_source[] = {
- { MEDIA_BUS_FMT_YUYV8_1_5X8, 8 },
-};
-
-static const struct stf_isp_format_table isp_formats_st7110[] = {
- { isp_formats_sink, ARRAY_SIZE(isp_formats_sink) },
- { isp_formats_source, ARRAY_SIZE(isp_formats_source) },
-};
-
-static const struct stf_isp_format *
-stf_g_fmt_by_mcode(const struct stf_isp_format_table *fmt_table, u32 mcode)
-{
- unsigned int i;
-
- for (i = 0; i < fmt_table->nfmts; i++) {
- if (fmt_table->fmts[i].code == mcode)
- return &fmt_table->fmts[i];
- }
-
- return NULL;
-}
-
-int stf_isp_init(struct stfcamss *stfcamss)
-{
- struct stf_isp_dev *isp_dev = &stfcamss->isp_dev;
-
- isp_dev->stfcamss = stfcamss;
- isp_dev->formats = isp_formats_st7110;
- isp_dev->nformats = ARRAY_SIZE(isp_formats_st7110);
- isp_dev->current_fmt = &isp_formats_source[0];
-
- return 0;
-}
-
-static int isp_set_stream(struct v4l2_subdev *sd, int enable)
-{
- struct stf_isp_dev *isp_dev = v4l2_get_subdevdata(sd);
- struct v4l2_subdev_state *sd_state;
- struct v4l2_mbus_framefmt *fmt;
- struct v4l2_rect *crop;
-
- sd_state = v4l2_subdev_lock_and_get_active_state(sd);
- fmt = v4l2_subdev_state_get_format(sd_state, STF_ISP_PAD_SINK);
- crop = v4l2_subdev_state_get_crop(sd_state, STF_ISP_PAD_SRC);
-
- if (enable) {
- stf_isp_reset(isp_dev);
- stf_isp_init_cfg(isp_dev);
- stf_isp_settings(isp_dev, crop, fmt->code);
- stf_isp_stream_set(isp_dev);
- }
-
- v4l2_subdev_call(isp_dev->source_subdev, video, s_stream, enable);
-
- v4l2_subdev_unlock_state(sd_state);
- return 0;
-}
-
-static void isp_try_format(struct stf_isp_dev *isp_dev,
- struct v4l2_subdev_state *state,
- unsigned int pad,
- struct v4l2_mbus_framefmt *fmt)
-{
- const struct stf_isp_format_table *formats;
-
- if (pad >= STF_ISP_PAD_MAX) {
- fmt->colorspace = V4L2_COLORSPACE_SRGB;
- return;
- }
-
- formats = &isp_dev->formats[pad];
-
- fmt->width = clamp_t(u32, fmt->width, STFCAMSS_FRAME_MIN_WIDTH,
- STFCAMSS_FRAME_MAX_WIDTH);
- fmt->height = clamp_t(u32, fmt->height, STFCAMSS_FRAME_MIN_HEIGHT,
- STFCAMSS_FRAME_MAX_HEIGHT);
- fmt->height &= ~0x1;
- fmt->field = V4L2_FIELD_NONE;
- fmt->colorspace = V4L2_COLORSPACE_SRGB;
- fmt->flags = 0;
-
- if (!stf_g_fmt_by_mcode(formats, fmt->code))
- fmt->code = formats->fmts[0].code;
-}
-
-static int isp_enum_mbus_code(struct v4l2_subdev *sd,
- struct v4l2_subdev_state *state,
- struct v4l2_subdev_mbus_code_enum *code)
-{
- struct stf_isp_dev *isp_dev = v4l2_get_subdevdata(sd);
- const struct stf_isp_format_table *formats;
-
- if (code->pad == STF_ISP_PAD_SINK) {
- if (code->index >= ARRAY_SIZE(isp_formats_sink))
- return -EINVAL;
-
- formats = &isp_dev->formats[code->pad];
- code->code = formats->fmts[code->index].code;
- } else {
- struct v4l2_mbus_framefmt *sink_fmt;
-
- if (code->index >= ARRAY_SIZE(isp_formats_source))
- return -EINVAL;
-
- sink_fmt = v4l2_subdev_state_get_format(state,
- STF_ISP_PAD_SRC);
-
- code->code = sink_fmt->code;
- if (!code->code)
- return -EINVAL;
- }
- code->flags = 0;
-
- return 0;
-}
-
-static int isp_set_format(struct v4l2_subdev *sd,
- struct v4l2_subdev_state *state,
- struct v4l2_subdev_format *fmt)
-{
- struct stf_isp_dev *isp_dev = v4l2_get_subdevdata(sd);
- struct v4l2_mbus_framefmt *format;
-
- format = v4l2_subdev_state_get_format(state, fmt->pad);
- if (!format)
- return -EINVAL;
-
- isp_try_format(isp_dev, state, fmt->pad, &fmt->format);
- *format = fmt->format;
-
- isp_dev->current_fmt = stf_g_fmt_by_mcode(&isp_dev->formats[fmt->pad],
- fmt->format.code);
-
- /* Propagate to in crop */
- if (fmt->pad == STF_ISP_PAD_SINK) {
- struct v4l2_subdev_selection sel = { 0 };
-
- /* Reset sink pad compose selection */
- sel.which = fmt->which;
- sel.pad = STF_ISP_PAD_SINK;
- sel.target = V4L2_SEL_TGT_CROP;
- sel.r.width = fmt->format.width;
- sel.r.height = fmt->format.height;
- isp_set_selection(sd, state, &sel);
- }
-
- return 0;
-}
-
-static const struct v4l2_rect stf_frame_min_crop = {
- .width = STFCAMSS_FRAME_MIN_WIDTH,
- .height = STFCAMSS_FRAME_MIN_HEIGHT,
- .top = 0,
- .left = 0,
-};
-
-static void isp_try_crop(struct stf_isp_dev *isp_dev,
- struct v4l2_subdev_state *state,
- struct v4l2_rect *crop)
-{
- struct v4l2_mbus_framefmt *fmt =
- v4l2_subdev_state_get_format(state, STF_ISP_PAD_SINK);
-
- const struct v4l2_rect bounds = {
- .width = fmt->width,
- .height = fmt->height,
- .left = 0,
- .top = 0,
- };
-
- v4l2_rect_set_min_size(crop, &stf_frame_min_crop);
- v4l2_rect_map_inside(crop, &bounds);
-}
-
-static int isp_get_selection(struct v4l2_subdev *sd,
- struct v4l2_subdev_state *state,
- struct v4l2_subdev_selection *sel)
-{
- struct v4l2_subdev_format fmt = { 0 };
- struct v4l2_rect *rect;
-
- switch (sel->target) {
- case V4L2_SEL_TGT_CROP_BOUNDS:
- if (sel->pad == STF_ISP_PAD_SINK) {
- fmt.format = *v4l2_subdev_state_get_format(state,
- sel->pad);
- sel->r.left = 0;
- sel->r.top = 0;
- sel->r.width = fmt.format.width;
- sel->r.height = fmt.format.height;
- } else if (sel->pad == STF_ISP_PAD_SRC) {
- rect = v4l2_subdev_state_get_crop(state, sel->pad);
- sel->r = *rect;
- }
- break;
-
- case V4L2_SEL_TGT_CROP:
- rect = v4l2_subdev_state_get_crop(state, sel->pad);
- if (!rect)
- return -EINVAL;
-
- sel->r = *rect;
- break;
-
- default:
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int isp_set_selection(struct v4l2_subdev *sd,
- struct v4l2_subdev_state *state,
- struct v4l2_subdev_selection *sel)
-{
- struct stf_isp_dev *isp_dev = v4l2_get_subdevdata(sd);
- struct v4l2_rect *rect;
-
- if (sel->target != V4L2_SEL_TGT_CROP)
- return -EINVAL;
-
- if (sel->target == V4L2_SEL_TGT_CROP &&
- sel->pad == STF_ISP_PAD_SINK) {
- struct v4l2_subdev_selection crop = { 0 };
-
- rect = v4l2_subdev_state_get_crop(state, sel->pad);
- if (!rect)
- return -EINVAL;
-
- isp_try_crop(isp_dev, state, &sel->r);
- *rect = sel->r;
-
- /* Reset source crop selection */
- crop.which = sel->which;
- crop.pad = STF_ISP_PAD_SRC;
- crop.target = V4L2_SEL_TGT_CROP;
- crop.r = *rect;
- isp_set_selection(sd, state, &crop);
- } else if (sel->target == V4L2_SEL_TGT_CROP &&
- sel->pad == STF_ISP_PAD_SRC) {
- struct v4l2_subdev_format fmt = { 0 };
-
- rect = v4l2_subdev_state_get_crop(state, sel->pad);
- if (!rect)
- return -EINVAL;
-
- isp_try_crop(isp_dev, state, &sel->r);
- *rect = sel->r;
-
- /* Reset source pad format width and height */
- fmt.which = sel->which;
- fmt.pad = STF_ISP_PAD_SRC;
- fmt.format.width = rect->width;
- fmt.format.height = rect->height;
- isp_set_format(sd, state, &fmt);
- }
-
- dev_dbg(isp_dev->stfcamss->dev, "pad: %d sel(%d,%d)/%ux%u\n",
- sel->pad, sel->r.left, sel->r.top, sel->r.width, sel->r.height);
-
- return 0;
-}
-
-static int isp_init_formats(struct v4l2_subdev *sd,
- struct v4l2_subdev_state *sd_state)
-{
- struct v4l2_subdev_format format = {
- .pad = STF_ISP_PAD_SINK,
- .which = V4L2_SUBDEV_FORMAT_ACTIVE,
- .format = {
- .code = MEDIA_BUS_FMT_SRGGB10_1X10,
- .width = 1920,
- .height = 1080
- }
- };
-
- return isp_set_format(sd, sd_state, &format);
-}
-
-static const struct v4l2_subdev_video_ops isp_video_ops = {
- .s_stream = isp_set_stream,
-};
-
-static const struct v4l2_subdev_pad_ops isp_pad_ops = {
- .enum_mbus_code = isp_enum_mbus_code,
- .get_fmt = v4l2_subdev_get_fmt,
- .set_fmt = isp_set_format,
- .get_selection = isp_get_selection,
- .set_selection = isp_set_selection,
-};
-
-static const struct v4l2_subdev_ops isp_v4l2_ops = {
- .video = &isp_video_ops,
- .pad = &isp_pad_ops,
-};
-
-static const struct v4l2_subdev_internal_ops isp_internal_ops = {
- .init_state = isp_init_formats,
-};
-
-static const struct media_entity_operations isp_media_ops = {
- .link_validate = v4l2_subdev_link_validate,
-};
-
-int stf_isp_register(struct stf_isp_dev *isp_dev, struct v4l2_device *v4l2_dev)
-{
- struct v4l2_subdev *sd = &isp_dev->subdev;
- struct media_pad *pads = isp_dev->pads;
- int ret;
-
- v4l2_subdev_init(sd, &isp_v4l2_ops);
- sd->internal_ops = &isp_internal_ops;
- sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
- snprintf(sd->name, ARRAY_SIZE(sd->name), "stf_isp");
- v4l2_set_subdevdata(sd, isp_dev);
-
- pads[STF_ISP_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
- pads[STF_ISP_PAD_SRC].flags = MEDIA_PAD_FL_SOURCE;
-
- sd->entity.function = MEDIA_ENT_F_PROC_VIDEO_ISP;
- sd->entity.ops = &isp_media_ops;
- ret = media_entity_pads_init(&sd->entity, STF_ISP_PAD_MAX, pads);
- if (ret) {
- dev_err(isp_dev->stfcamss->dev,
- "Failed to init media entity: %d\n", ret);
- return ret;
- }
-
- ret = v4l2_subdev_init_finalize(sd);
- if (ret)
- goto err_entity_cleanup;
-
- ret = v4l2_device_register_subdev(v4l2_dev, sd);
- if (ret) {
- dev_err(isp_dev->stfcamss->dev,
- "Failed to register subdev: %d\n", ret);
- goto err_subdev_cleanup;
- }
-
- return 0;
-
-err_subdev_cleanup:
- v4l2_subdev_cleanup(sd);
-err_entity_cleanup:
- media_entity_cleanup(&sd->entity);
- return ret;
-}
-
-int stf_isp_unregister(struct stf_isp_dev *isp_dev)
-{
- v4l2_device_unregister_subdev(&isp_dev->subdev);
- v4l2_subdev_cleanup(&isp_dev->subdev);
- media_entity_cleanup(&isp_dev->subdev.entity);
-
- return 0;
-}
diff --git a/drivers/staging/media/starfive/camss/stf-isp.h b/drivers/staging/media/starfive/camss/stf-isp.h
deleted file mode 100644
index 955cbb048363..000000000000
--- a/drivers/staging/media/starfive/camss/stf-isp.h
+++ /dev/null
@@ -1,428 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * stf_isp.h
- *
- * StarFive Camera Subsystem - ISP Module
- *
- * Copyright (C) 2021-2023 StarFive Technology Co., Ltd.
- */
-
-#ifndef STF_ISP_H
-#define STF_ISP_H
-
-#include <media/v4l2-subdev.h>
-
-#include "stf-video.h"
-
-#define ISP_RAW_DATA_BITS 12
-#define SCALER_RATIO_MAX 1
-#define STF_ISP_REG_OFFSET_MAX 0x0fff
-#define STF_ISP_REG_DELAY_MAX 100
-
-/* isp registers */
-#define ISP_REG_CSI_INPUT_EN_AND_STATUS 0x000
-#define CSI_SCD_ERR BIT(6)
-#define CSI_ITU656_ERR BIT(4)
-#define CSI_ITU656_F BIT(3)
-#define CSI_SCD_DONE BIT(2)
-#define CSI_BUSY_S BIT(1)
-#define CSI_EN_S BIT(0)
-
-#define ISP_REG_CSIINTS 0x008
-#define CSI_INTS(n) ((n) << 16)
-#define CSI_SHA_M(n) ((n) << 0)
-#define CSI_INTS_MASK GENMASK(17, 16)
-
-#define ISP_REG_CSI_MODULE_CFG 0x010
-#define CSI_DUMP_EN BIT(19)
-#define CSI_VS_EN BIT(18)
-#define CSI_SC_EN BIT(17)
-#define CSI_OBA_EN BIT(16)
-#define CSI_AWB_EN BIT(7)
-#define CSI_LCCF_EN BIT(6)
-#define CSI_OECFHM_EN BIT(5)
-#define CSI_OECF_EN BIT(4)
-#define CSI_LCBQ_EN BIT(3)
-#define CSI_OBC_EN BIT(2)
-#define CSI_DEC_EN BIT(1)
-#define CSI_DC_EN BIT(0)
-
-#define ISP_REG_SENSOR 0x014
-#define DVP_SYNC_POL(n) ((n) << 2)
-#define ITU656_EN(n) ((n) << 1)
-#define IMAGER_SEL(n) ((n) << 0)
-
-#define ISP_REG_RAW_FORMAT_CFG 0x018
-#define SMY13(n) ((n) << 14)
-#define SMY12(n) ((n) << 12)
-#define SMY11(n) ((n) << 10)
-#define SMY10(n) ((n) << 8)
-#define SMY3(n) ((n) << 6)
-#define SMY2(n) ((n) << 4)
-#define SMY1(n) ((n) << 2)
-#define SMY0(n) ((n) << 0)
-
-#define ISP_REG_PIC_CAPTURE_START_CFG 0x01c
-#define VSTART_CAP(n) ((n) << 16)
-#define HSTART_CAP(n) ((n) << 0)
-
-#define ISP_REG_PIC_CAPTURE_END_CFG 0x020
-#define VEND_CAP(n) ((n) << 16)
-#define HEND_CAP(n) ((n) << 0)
-
-#define ISP_REG_DUMP_CFG_0 0x024
-#define ISP_REG_DUMP_CFG_1 0x028
-#define DUMP_ID(n) ((n) << 24)
-#define DUMP_SHT(n) ((n) << 20)
-#define DUMP_BURST_LEN(n) ((n) << 16)
-#define DUMP_SD(n) ((n) << 0)
-#define DUMP_BURST_LEN_MASK GENMASK(17, 16)
-#define DUMP_SD_MASK GENMASK(15, 0)
-
-#define ISP_REG_DEC_CFG 0x030
-#define DEC_V_KEEP(n) ((n) << 24)
-#define DEC_V_PERIOD(n) ((n) << 16)
-#define DEC_H_KEEP(n) ((n) << 8)
-#define DEC_H_PERIOD(n) ((n) << 0)
-
-#define ISP_REG_OBC_CFG 0x034
-#define OBC_W_H(y) ((y) << 4)
-#define OBC_W_W(x) ((x) << 0)
-
-#define ISP_REG_DC_CFG_1 0x044
-#define DC_AXI_ID(n) ((n) << 0)
-
-#define ISP_REG_LCCF_CFG_0 0x050
-#define Y_DISTANCE(y) ((y) << 16)
-#define X_DISTANCE(x) ((x) << 0)
-
-#define ISP_REG_LCCF_CFG_1 0x058
-#define LCCF_MAX_DIS(n) ((n) << 0)
-
-#define ISP_REG_LCBQ_CFG_0 0x074
-#define H_LCBQ(y) ((y) << 12)
-#define W_LCBQ(x) ((x) << 8)
-
-#define ISP_REG_LCBQ_CFG_1 0x07c
-#define Y_COOR(y) ((y) << 16)
-#define X_COOR(x) ((x) << 0)
-
-#define ISP_REG_LCCF_CFG_2 0x0e0
-#define ISP_REG_LCCF_CFG_3 0x0e4
-#define ISP_REG_LCCF_CFG_4 0x0e8
-#define ISP_REG_LCCF_CFG_5 0x0ec
-#define LCCF_F2_PAR(n) ((n) << 16)
-#define LCCF_F1_PAR(n) ((n) << 0)
-
-#define ISP_REG_OECF_X0_CFG0 0x100
-#define ISP_REG_OECF_X0_CFG1 0x104
-#define ISP_REG_OECF_X0_CFG2 0x108
-#define ISP_REG_OECF_X0_CFG3 0x10c
-#define ISP_REG_OECF_X0_CFG4 0x110
-#define ISP_REG_OECF_X0_CFG5 0x114
-#define ISP_REG_OECF_X0_CFG6 0x118
-#define ISP_REG_OECF_X0_CFG7 0x11c
-
-#define ISP_REG_OECF_Y3_CFG0 0x1e0
-#define ISP_REG_OECF_Y3_CFG1 0x1e4
-#define ISP_REG_OECF_Y3_CFG2 0x1e8
-#define ISP_REG_OECF_Y3_CFG3 0x1ec
-#define ISP_REG_OECF_Y3_CFG4 0x1f0
-#define ISP_REG_OECF_Y3_CFG5 0x1f4
-#define ISP_REG_OECF_Y3_CFG6 0x1f8
-#define ISP_REG_OECF_Y3_CFG7 0x1fc
-
-#define ISP_REG_OECF_S0_CFG0 0x200
-#define ISP_REG_OECF_S3_CFG7 0x27c
-#define OCEF_PAR_H(n) ((n) << 16)
-#define OCEF_PAR_L(n) ((n) << 0)
-
-#define ISP_REG_AWB_X0_CFG_0 0x280
-#define ISP_REG_AWB_X0_CFG_1 0x284
-#define ISP_REG_AWB_X1_CFG_0 0x288
-#define ISP_REG_AWB_X1_CFG_1 0x28c
-#define ISP_REG_AWB_X2_CFG_0 0x290
-#define ISP_REG_AWB_X2_CFG_1 0x294
-#define ISP_REG_AWB_X3_CFG_0 0x298
-#define ISP_REG_AWB_X3_CFG_1 0x29c
-#define AWB_X_SYMBOL_H(n) ((n) << 16)
-#define AWB_X_SYMBOL_L(n) ((n) << 0)
-
-#define ISP_REG_AWB_Y0_CFG_0 0x2a0
-#define ISP_REG_AWB_Y0_CFG_1 0x2a4
-#define ISP_REG_AWB_Y1_CFG_0 0x2a8
-#define ISP_REG_AWB_Y1_CFG_1 0x2ac
-#define ISP_REG_AWB_Y2_CFG_0 0x2b0
-#define ISP_REG_AWB_Y2_CFG_1 0x2b4
-#define ISP_REG_AWB_Y3_CFG_0 0x2b8
-#define ISP_REG_AWB_Y3_CFG_1 0x2bc
-#define AWB_Y_SYMBOL_H(n) ((n) << 16)
-#define AWB_Y_SYMBOL_L(n) ((n) << 0)
-
-#define ISP_REG_AWB_S0_CFG_0 0x2c0
-#define ISP_REG_AWB_S0_CFG_1 0x2c4
-#define ISP_REG_AWB_S1_CFG_0 0x2c8
-#define ISP_REG_AWB_S1_CFG_1 0x2cc
-#define ISP_REG_AWB_S2_CFG_0 0x2d0
-#define ISP_REG_AWB_S2_CFG_1 0x2d4
-#define ISP_REG_AWB_S3_CFG_0 0x2d8
-#define ISP_REG_AWB_S3_CFG_1 0x2dc
-#define AWB_S_SYMBOL_H(n) ((n) << 16)
-#define AWB_S_SYMBOL_L(n) ((n) << 0)
-
-#define ISP_REG_OBCG_CFG_0 0x2e0
-#define ISP_REG_OBCG_CFG_1 0x2e4
-#define ISP_REG_OBCG_CFG_2 0x2e8
-#define ISP_REG_OBCG_CFG_3 0x2ec
-#define ISP_REG_OBCO_CFG_0 0x2f0
-#define ISP_REG_OBCO_CFG_1 0x2f4
-#define ISP_REG_OBCO_CFG_2 0x2f8
-#define ISP_REG_OBCO_CFG_3 0x2fc
-#define GAIN_D_POINT(x) ((x) << 24)
-#define GAIN_C_POINT(x) ((x) << 16)
-#define GAIN_B_POINT(x) ((x) << 8)
-#define GAIN_A_POINT(x) ((x) << 0)
-#define OFFSET_D_POINT(x) ((x) << 24)
-#define OFFSET_C_POINT(x) ((x) << 16)
-#define OFFSET_B_POINT(x) ((x) << 8)
-#define OFFSET_A_POINT(x) ((x) << 0)
-
-#define ISP_REG_ISP_CTRL_0 0xa00
-#define ISPC_LINE BIT(27)
-#define ISPC_SC BIT(26)
-#define ISPC_CSI BIT(25)
-#define ISPC_ISP BIT(24)
-#define ISPC_ENUO BIT(20)
-#define ISPC_ENLS BIT(17)
-#define ISPC_ENSS1 BIT(12)
-#define ISPC_ENSS0 BIT(11)
-#define ISPC_RST BIT(1)
-#define ISPC_EN BIT(0)
-#define ISPC_RST_MASK BIT(1)
-#define ISPC_INT_ALL_MASK GENMASK(27, 24)
-
-#define ISP_REG_ISP_CTRL_1 0xa08
-#define CTRL_SAT(n) ((n) << 28)
-#define CTRL_DBC BIT(22)
-#define CTRL_CTC BIT(21)
-#define CTRL_YHIST BIT(20)
-#define CTRL_YCURVE BIT(19)
-#define CTRL_CTM BIT(18)
-#define CTRL_BIYUV BIT(17)
-#define CTRL_SCE BIT(8)
-#define CTRL_EE BIT(7)
-#define CTRL_CCE BIT(5)
-#define CTRL_RGE BIT(4)
-#define CTRL_CME BIT(3)
-#define CTRL_AE BIT(2)
-#define CTRL_CE BIT(1)
-#define CTRL_SAT_MASK GENMASK(31, 28)
-
-#define ISP_REG_PIPELINE_XY_SIZE 0xa0c
-#define H_ACT_CAP(n) ((n) << 16)
-#define W_ACT_CAP(n) ((n) << 0)
-
-#define ISP_REG_ICTC 0xa10
-#define GF_MODE(n) ((n) << 30)
-#define MAXGT(n) ((n) << 16)
-#define MINGT(n) ((n) << 0)
-
-#define ISP_REG_IDBC 0xa14
-#define BADGT(n) ((n) << 16)
-#define BADXT(n) ((n) << 0)
-
-#define ISP_REG_ICFAM 0xa1c
-#define CROSS_COV(n) ((n) << 4)
-#define HV_W(n) ((n) << 0)
-
-#define ISP_REG_CS_GAIN 0xa30
-#define CMAD(n) ((n) << 16)
-#define CMAB(n) ((n) << 0)
-
-#define ISP_REG_CS_THRESHOLD 0xa34
-#define CMD(n) ((n) << 16)
-#define CMB(n) ((n) << 0)
-
-#define ISP_REG_CS_OFFSET 0xa38
-#define VOFF(n) ((n) << 16)
-#define UOFF(n) ((n) << 0)
-
-#define ISP_REG_CS_HUE_F 0xa3c
-#define SIN(n) ((n) << 16)
-#define COS(n) ((n) << 0)
-
-#define ISP_REG_CS_SCALE 0xa40
-
-#define ISP_REG_IESHD 0xa50
-#define SHAD_UP_M BIT(1)
-#define SHAD_UP_EN BIT(0)
-
-#define ISP_REG_YADJ0 0xa54
-#define YOIR(n) ((n) << 16)
-#define YIMIN(n) ((n) << 0)
-
-#define ISP_REG_YADJ1 0xa58
-#define YOMAX(n) ((n) << 16)
-#define YOMIN(n) ((n) << 0)
-
-#define ISP_REG_Y_PLANE_START_ADDR 0xa80
-#define ISP_REG_UV_PLANE_START_ADDR 0xa84
-#define ISP_REG_STRIDE 0xa88
-
-#define ISP_REG_ITIIWSR 0xb20
-#define ITI_HSIZE(n) ((n) << 16)
-#define ITI_WSIZE(n) ((n) << 0)
-
-#define ISP_REG_ITIDWLSR 0xb24
-#define ISP_REG_ITIPDFR 0xb38
-#define ISP_REG_ITIDRLSR 0xb3C
-
-#define ISP_REG_DNYUV_YSWR0 0xc00
-#define ISP_REG_DNYUV_YSWR1 0xc04
-#define ISP_REG_DNYUV_CSWR0 0xc08
-#define ISP_REG_DNYUV_CSWR1 0xc0c
-#define YUVSW5(n) ((n) << 20)
-#define YUVSW4(n) ((n) << 16)
-#define YUVSW3(n) ((n) << 12)
-#define YUVSW2(n) ((n) << 8)
-#define YUVSW1(n) ((n) << 4)
-#define YUVSW0(n) ((n) << 0)
-
-#define ISP_REG_DNYUV_YDR0 0xc10
-#define ISP_REG_DNYUV_YDR1 0xc14
-#define ISP_REG_DNYUV_YDR2 0xc18
-#define ISP_REG_DNYUV_CDR0 0xc1c
-#define ISP_REG_DNYUV_CDR1 0xc20
-#define ISP_REG_DNYUV_CDR2 0xc24
-#define CURVE_D_H(n) ((n) << 16)
-#define CURVE_D_L(n) ((n) << 0)
-
-#define ISP_REG_ICAMD_0 0xc40
-#define ISP_REG_ICAMD_12 0xc70
-#define ISP_REG_ICAMD_20 0xc90
-#define ISP_REG_ICAMD_24 0xca0
-#define ISP_REG_ICAMD_25 0xca4
-#define DNRM_F(n) ((n) << 16)
-#define CCM_M_DAT(n) ((n) << 0)
-
-#define ISP_REG_GAMMA_VAL0 0xe00
-#define ISP_REG_GAMMA_VAL1 0xe04
-#define ISP_REG_GAMMA_VAL2 0xe08
-#define ISP_REG_GAMMA_VAL3 0xe0c
-#define ISP_REG_GAMMA_VAL4 0xe10
-#define ISP_REG_GAMMA_VAL5 0xe14
-#define ISP_REG_GAMMA_VAL6 0xe18
-#define ISP_REG_GAMMA_VAL7 0xe1c
-#define ISP_REG_GAMMA_VAL8 0xe20
-#define ISP_REG_GAMMA_VAL9 0xe24
-#define ISP_REG_GAMMA_VAL10 0xe28
-#define ISP_REG_GAMMA_VAL11 0xe2c
-#define ISP_REG_GAMMA_VAL12 0xe30
-#define ISP_REG_GAMMA_VAL13 0xe34
-#define ISP_REG_GAMMA_VAL14 0xe38
-#define GAMMA_S_VAL(n) ((n) << 16)
-#define GAMMA_VAL(n) ((n) << 0)
-
-#define ISP_REG_R2Y_0 0xe40
-#define ISP_REG_R2Y_1 0xe44
-#define ISP_REG_R2Y_2 0xe48
-#define ISP_REG_R2Y_3 0xe4c
-#define ISP_REG_R2Y_4 0xe50
-#define ISP_REG_R2Y_5 0xe54
-#define ISP_REG_R2Y_6 0xe58
-#define ISP_REG_R2Y_7 0xe5c
-#define ISP_REG_R2Y_8 0xe60
-
-#define ISP_REG_SHARPEN0 0xe80
-#define ISP_REG_SHARPEN1 0xe84
-#define ISP_REG_SHARPEN2 0xe88
-#define ISP_REG_SHARPEN3 0xe8c
-#define ISP_REG_SHARPEN4 0xe90
-#define ISP_REG_SHARPEN5 0xe94
-#define ISP_REG_SHARPEN6 0xe98
-#define ISP_REG_SHARPEN7 0xe9c
-#define ISP_REG_SHARPEN8 0xea0
-#define ISP_REG_SHARPEN9 0xea4
-#define ISP_REG_SHARPEN10 0xea8
-#define ISP_REG_SHARPEN11 0xeac
-#define ISP_REG_SHARPEN12 0xeb0
-#define ISP_REG_SHARPEN13 0xeb4
-#define ISP_REG_SHARPEN14 0xeb8
-#define S_DELTA(n) ((n) << 16)
-#define S_WEIGHT(n) ((n) << 8)
-
-#define ISP_REG_SHARPEN_FS0 0xebc
-#define ISP_REG_SHARPEN_FS1 0xec0
-#define ISP_REG_SHARPEN_FS2 0xec4
-#define ISP_REG_SHARPEN_FS3 0xec8
-#define ISP_REG_SHARPEN_FS4 0xecc
-#define ISP_REG_SHARPEN_FS5 0xed0
-#define S_FACTOR(n) ((n) << 24)
-#define S_SLOPE(n) ((n) << 0)
-
-#define ISP_REG_SHARPEN_WN 0xed4
-#define PDIRF(n) ((n) << 28)
-#define NDIRF(n) ((n) << 24)
-#define WSUM(n) ((n) << 0)
-
-#define ISP_REG_IUVS1 0xed8
-#define UVDIFF2(n) ((n) << 16)
-#define UVDIFF1(n) ((n) << 0)
-
-#define ISP_REG_IUVS2 0xedc
-#define UVF(n) ((n) << 24)
-#define UVSLOPE(n) ((n) << 0)
-
-#define ISP_REG_IUVCKS1 0xee0
-#define UVCKDIFF2(n) ((n) << 16)
-#define UVCKDIFF1(n) ((n) << 0)
-
-#define ISP_REG_IUVCKS2 0xee4
-
-#define ISP_REG_ISHRPET 0xee8
-#define TH(n) ((n) << 8)
-#define EN(n) ((n) << 0)
-
-#define ISP_REG_YCURVE_0 0xf00
-#define ISP_REG_YCURVE_63 0xffc
-
-#define IMAGE_MAX_WIDTH 1920
-#define IMAGE_MAX_HEIGH 1080
-
-/* pad id for media framework */
-enum stf_isp_pad_id {
- STF_ISP_PAD_SINK = 0,
- STF_ISP_PAD_SRC,
- STF_ISP_PAD_MAX
-};
-
-struct stf_isp_format {
- u32 code;
- u8 bpp;
-};
-
-struct stf_isp_format_table {
- const struct stf_isp_format *fmts;
- int nfmts;
-};
-
-struct stf_isp_dev {
- struct stfcamss *stfcamss;
- struct v4l2_subdev subdev;
- struct media_pad pads[STF_ISP_PAD_MAX];
- const struct stf_isp_format_table *formats;
- unsigned int nformats;
- struct v4l2_subdev *source_subdev;
- const struct stf_isp_format *current_fmt;
-};
-
-int stf_isp_reset(struct stf_isp_dev *isp_dev);
-void stf_isp_init_cfg(struct stf_isp_dev *isp_dev);
-void stf_isp_settings(struct stf_isp_dev *isp_dev,
- struct v4l2_rect *crop, u32 mcode);
-void stf_isp_stream_set(struct stf_isp_dev *isp_dev);
-int stf_isp_init(struct stfcamss *stfcamss);
-int stf_isp_register(struct stf_isp_dev *isp_dev, struct v4l2_device *v4l2_dev);
-int stf_isp_unregister(struct stf_isp_dev *isp_dev);
-
-#endif /* STF_ISP_H */
diff --git a/drivers/staging/media/starfive/camss/stf-video.c b/drivers/staging/media/starfive/camss/stf-video.c
deleted file mode 100644
index a0420eb6a0aa..000000000000
--- a/drivers/staging/media/starfive/camss/stf-video.c
+++ /dev/null
@@ -1,570 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * stf_video.c
- *
- * StarFive Camera Subsystem - V4L2 device node
- *
- * Copyright (C) 2021-2023 StarFive Technology Co., Ltd.
- */
-
-#include <linux/pm_runtime.h>
-#include <media/v4l2-ctrls.h>
-#include <media/v4l2-event.h>
-#include <media/v4l2-mc.h>
-#include <media/videobuf2-dma-contig.h>
-
-#include "stf-camss.h"
-#include "stf-video.h"
-
-/* -----------------------------------------------------------------------------
- * Helper functions
- */
-
-static inline struct stfcamss_buffer *
-to_stfcamss_buffer(struct vb2_v4l2_buffer *vbuf)
-{
- return container_of(vbuf, struct stfcamss_buffer, vb);
-}
-
-static const struct stfcamss_format_info *
-video_g_fi_by_index(struct stfcamss_video *video, int index)
-{
- if (index >= video->nformats)
- return NULL;
-
- return &video->formats[index];
-}
-
-static const struct stfcamss_format_info *
-video_g_fi_by_mcode(struct stfcamss_video *video, u32 mcode)
-{
- unsigned int i;
-
- for (i = 0; i < video->nformats; i++) {
- if (video->formats[i].code == mcode)
- return &video->formats[i];
- }
-
- return NULL;
-}
-
-static const struct stfcamss_format_info *
-video_g_fi_by_pfmt(struct stfcamss_video *video, u32 pixelformat)
-{
- unsigned int i;
-
- for (i = 0; i < video->nformats; i++) {
- if (video->formats[i].pixelformat == pixelformat)
- return &video->formats[i];
- }
-
- return NULL;
-}
-
-static int __video_try_fmt(struct stfcamss_video *video, struct v4l2_format *f)
-{
- struct v4l2_pix_format *pix = &f->fmt.pix;
- const struct stfcamss_format_info *fi;
- u32 width, height;
- u32 bpl;
- unsigned int i;
-
- fi = video_g_fi_by_pfmt(video, pix->pixelformat);
- if (!fi)
- fi = &video->formats[0]; /* default format */
-
- width = pix->width;
- height = pix->height;
-
- memset(pix, 0, sizeof(*pix));
-
- pix->pixelformat = fi->pixelformat;
- pix->width = clamp_t(u32, width, STFCAMSS_FRAME_MIN_WIDTH,
- STFCAMSS_FRAME_MAX_WIDTH);
- pix->height = clamp_t(u32, height, STFCAMSS_FRAME_MIN_HEIGHT,
- STFCAMSS_FRAME_MAX_HEIGHT);
- bpl = pix->width * fi->bpp / 8;
- bpl = ALIGN(bpl, video->bpl_alignment);
- pix->bytesperline = bpl;
-
- for (i = 0; i < fi->planes; ++i)
- pix->sizeimage += bpl * pix->height / fi->vsub[i];
-
- pix->field = V4L2_FIELD_NONE;
- pix->colorspace = V4L2_COLORSPACE_SRGB;
- pix->flags = 0;
- pix->ycbcr_enc =
- V4L2_MAP_YCBCR_ENC_DEFAULT(pix->colorspace);
- pix->quantization = V4L2_MAP_QUANTIZATION_DEFAULT(true,
- pix->colorspace,
- pix->ycbcr_enc);
- pix->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(pix->colorspace);
-
- return 0;
-}
-
-static int stf_video_init_format(struct stfcamss_video *video)
-{
- int ret;
- struct v4l2_format format = {
- .type = video->type,
- .fmt.pix = {
- .width = 1920,
- .height = 1080,
- .pixelformat = V4L2_PIX_FMT_NV12,
- },
- };
-
- ret = __video_try_fmt(video, &format);
-
- if (ret < 0)
- return ret;
-
- video->active_fmt = format;
-
- return 0;
-}
-
-/* -----------------------------------------------------------------------------
- * Video queue operations
- */
-
-static int video_queue_setup(struct vb2_queue *q,
- unsigned int *num_buffers,
- unsigned int *num_planes,
- unsigned int sizes[],
- struct device *alloc_devs[])
-{
- struct stfcamss_video *video = vb2_get_drv_priv(q);
- const struct v4l2_pix_format *format = &video->active_fmt.fmt.pix;
-
- if (*num_planes) {
- if (*num_planes != 1)
- return -EINVAL;
-
- if (sizes[0] < format->sizeimage)
- return -EINVAL;
- } else {
- *num_planes = 1;
- sizes[0] = format->sizeimage;
- }
-
- if (!sizes[0]) {
- dev_dbg(video->stfcamss->dev,
- "%s: error size is zero.\n", __func__);
- return -EINVAL;
- }
-
- dev_dbg(video->stfcamss->dev, "planes = %d, size = %d\n",
- *num_planes, sizes[0]);
-
- return 0;
-}
-
-static int video_buf_init(struct vb2_buffer *vb)
-{
- struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
- struct stfcamss_video *video = vb2_get_drv_priv(vb->vb2_queue);
- struct stfcamss_buffer *buffer = to_stfcamss_buffer(vbuf);
- const struct v4l2_pix_format *fmt = &video->active_fmt.fmt.pix;
- dma_addr_t *paddr;
-
- paddr = vb2_plane_cookie(vb, 0);
- buffer->addr[0] = *paddr;
-
- if (fmt->pixelformat == V4L2_PIX_FMT_NV12)
- buffer->addr[1] =
- buffer->addr[0] + fmt->bytesperline * fmt->height;
-
- return 0;
-}
-
-static int video_buf_prepare(struct vb2_buffer *vb)
-{
- struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
- struct stfcamss_video *video = vb2_get_drv_priv(vb->vb2_queue);
- const struct v4l2_pix_format *fmt = &video->active_fmt.fmt.pix;
-
- if (fmt->sizeimage > vb2_plane_size(vb, 0)) {
- dev_dbg(video->stfcamss->dev,
- "sizeimage = %u, plane size = %u\n",
- fmt->sizeimage, (unsigned int)vb2_plane_size(vb, 0));
- return -EINVAL;
- }
- vb2_set_plane_payload(vb, 0, fmt->sizeimage);
-
- vbuf->field = V4L2_FIELD_NONE;
-
- return 0;
-}
-
-static void video_buf_queue(struct vb2_buffer *vb)
-{
- struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
- struct stfcamss_video *video = vb2_get_drv_priv(vb->vb2_queue);
- struct stfcamss_buffer *buffer = to_stfcamss_buffer(vbuf);
-
- video->ops->queue_buffer(video, buffer);
-}
-
-static int video_get_subdev_format(struct stfcamss_video *video,
- struct v4l2_subdev_format *fmt)
-{
- struct v4l2_subdev *subdev;
- struct media_pad *pad;
- struct media_entity *entity;
- int ret;
-
- entity = &video->vdev.entity;
- while (1) {
- pad = &entity->pads[0];
- if (!(pad->flags & MEDIA_PAD_FL_SINK))
- break;
-
- pad = media_pad_remote_pad_first(pad);
- if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
- break;
-
- entity = pad->entity;
- subdev = media_entity_to_v4l2_subdev(entity);
-
- fmt->pad = pad->index;
-
- ret = v4l2_subdev_call_state_active(subdev, pad, get_fmt, fmt);
- if (ret < 0 && ret != -ENOIOCTLCMD)
- return ret;
- else if (!ret)
- break;
- }
-
- return 0;
-}
-
-static int stf_video_check_format(struct stfcamss_video *video)
-{
- struct v4l2_pix_format *pix = &video->active_fmt.fmt.pix;
- const struct stfcamss_format_info *fi;
- int ret;
- struct v4l2_subdev_format sd_fmt = {
- .which = V4L2_SUBDEV_FORMAT_ACTIVE,
- };
-
- ret = video_get_subdev_format(video, &sd_fmt);
- if (ret < 0)
- return ret;
-
- fi = video_g_fi_by_mcode(video, sd_fmt.format.code);
- if (!fi)
- return -EINVAL;
-
- if (pix->pixelformat != fi->pixelformat ||
- pix->height != sd_fmt.format.height ||
- pix->width != sd_fmt.format.width ||
- pix->field != sd_fmt.format.field)
- return -EPIPE;
-
- return 0;
-}
-
-static int video_start_streaming(struct vb2_queue *q, unsigned int count)
-{
- struct stfcamss_video *video = vb2_get_drv_priv(q);
- struct video_device *vdev = &video->vdev;
- int ret;
-
- ret = video_device_pipeline_start(vdev, &video->stfcamss->pipe);
- if (ret < 0) {
- dev_err(video->stfcamss->dev,
- "Failed to media_pipeline_start: %d\n", ret);
- goto err_ret_buffers;
- }
-
- ret = pm_runtime_resume_and_get(video->stfcamss->dev);
- if (ret < 0) {
- dev_err(video->stfcamss->dev, "power up failed %d\n", ret);
- goto err_pipeline_stop;
- }
-
- video->ops->start_streaming(video);
-
- ret = v4l2_subdev_call(video->source_subdev, video, s_stream, true);
- if (ret) {
- dev_err(video->stfcamss->dev, "stream on failed\n");
- goto err_pm_put;
- }
-
- return 0;
-
-err_pm_put:
- pm_runtime_put(video->stfcamss->dev);
-err_pipeline_stop:
- video_device_pipeline_stop(vdev);
-err_ret_buffers:
- video->ops->flush_buffers(video, VB2_BUF_STATE_QUEUED);
- return ret;
-}
-
-static void video_stop_streaming(struct vb2_queue *q)
-{
- struct stfcamss_video *video = vb2_get_drv_priv(q);
- struct video_device *vdev = &video->vdev;
-
- video->ops->stop_streaming(video);
-
- v4l2_subdev_call(video->source_subdev, video, s_stream, false);
-
- pm_runtime_put(video->stfcamss->dev);
-
- video_device_pipeline_stop(vdev);
- video->ops->flush_buffers(video, VB2_BUF_STATE_ERROR);
-}
-
-static const struct vb2_ops stf_video_vb2_q_ops = {
- .queue_setup = video_queue_setup,
- .buf_init = video_buf_init,
- .buf_prepare = video_buf_prepare,
- .buf_queue = video_buf_queue,
- .start_streaming = video_start_streaming,
- .stop_streaming = video_stop_streaming,
-};
-
-/* -----------------------------------------------------------------------------
- * V4L2 ioctls
- */
-
-static int video_querycap(struct file *file, void *fh,
- struct v4l2_capability *cap)
-{
- strscpy(cap->driver, "starfive-camss", sizeof(cap->driver));
- strscpy(cap->card, "Starfive Camera Subsystem", sizeof(cap->card));
-
- return 0;
-}
-
-static int video_enum_fmt(struct file *file, void *fh, struct v4l2_fmtdesc *f)
-{
- struct stfcamss_video *video = video_drvdata(file);
- const struct stfcamss_format_info *fi;
-
- if (f->index >= video->nformats)
- return -EINVAL;
-
- if (f->mbus_code) {
- /* Each entry in formats[] table has unique mbus_code */
- if (f->index > 0)
- return -EINVAL;
-
- fi = video_g_fi_by_mcode(video, f->mbus_code);
- } else {
- fi = video_g_fi_by_index(video, f->index);
- }
-
- if (!fi)
- return -EINVAL;
-
- f->pixelformat = fi->pixelformat;
-
- return 0;
-}
-
-static int video_enum_framesizes(struct file *file, void *fh,
- struct v4l2_frmsizeenum *fsize)
-{
- struct stfcamss_video *video = video_drvdata(file);
- unsigned int i;
-
- if (fsize->index)
- return -EINVAL;
-
- for (i = 0; i < video->nformats; i++) {
- if (video->formats[i].pixelformat == fsize->pixel_format)
- break;
- }
-
- if (i == video->nformats)
- return -EINVAL;
-
- fsize->type = V4L2_FRMSIZE_TYPE_CONTINUOUS;
- fsize->stepwise.min_width = STFCAMSS_FRAME_MIN_WIDTH;
- fsize->stepwise.max_width = STFCAMSS_FRAME_MAX_WIDTH;
- fsize->stepwise.min_height = STFCAMSS_FRAME_MIN_HEIGHT;
- fsize->stepwise.max_height = STFCAMSS_FRAME_MAX_HEIGHT;
- fsize->stepwise.step_width = 1;
- fsize->stepwise.step_height = 1;
-
- return 0;
-}
-
-static int video_g_fmt(struct file *file, void *fh, struct v4l2_format *f)
-{
- struct stfcamss_video *video = video_drvdata(file);
-
- *f = video->active_fmt;
-
- return 0;
-}
-
-static int video_s_fmt(struct file *file, void *fh, struct v4l2_format *f)
-{
- struct stfcamss_video *video = video_drvdata(file);
- int ret;
-
- if (vb2_is_busy(&video->vb2_q))
- return -EBUSY;
-
- ret = __video_try_fmt(video, f);
- if (ret < 0)
- return ret;
-
- video->active_fmt = *f;
-
- return 0;
-}
-
-static int video_try_fmt(struct file *file, void *fh, struct v4l2_format *f)
-{
- struct stfcamss_video *video = video_drvdata(file);
-
- return __video_try_fmt(video, f);
-}
-
-static const struct v4l2_ioctl_ops stf_vid_ioctl_ops = {
- .vidioc_querycap = video_querycap,
- .vidioc_enum_fmt_vid_cap = video_enum_fmt,
- .vidioc_enum_framesizes = video_enum_framesizes,
- .vidioc_g_fmt_vid_cap = video_g_fmt,
- .vidioc_s_fmt_vid_cap = video_s_fmt,
- .vidioc_try_fmt_vid_cap = 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,
-};
-
-/* -----------------------------------------------------------------------------
- * V4L2 file operations
- */
-
-static const struct v4l2_file_operations stf_vid_fops = {
- .owner = THIS_MODULE,
- .unlocked_ioctl = video_ioctl2,
- .open = v4l2_fh_open,
- .release = vb2_fop_release,
- .poll = vb2_fop_poll,
- .mmap = vb2_fop_mmap,
- .read = vb2_fop_read,
-};
-
-/* -----------------------------------------------------------------------------
- * STFCAMSS video core
- */
-
-static int stf_link_validate(struct media_link *link)
-{
- struct video_device *vdev =
- media_entity_to_video_device(link->sink->entity);
- struct stfcamss_video *video = video_get_drvdata(vdev);
- int ret;
-
- ret = stf_video_check_format(video);
-
- return ret;
-}
-
-static const struct media_entity_operations stf_media_ops = {
- .link_validate = stf_link_validate,
-};
-
-static void stf_video_release(struct video_device *vdev)
-{
- struct stfcamss_video *video = video_get_drvdata(vdev);
-
- media_entity_cleanup(&vdev->entity);
-
- mutex_destroy(&video->q_lock);
- mutex_destroy(&video->lock);
-}
-
-int stf_video_register(struct stfcamss_video *video,
- struct v4l2_device *v4l2_dev, const char *name)
-{
- struct video_device *vdev = &video->vdev;
- struct vb2_queue *q;
- struct media_pad *pad = &video->pad;
- int ret;
-
- mutex_init(&video->q_lock);
- mutex_init(&video->lock);
-
- q = &video->vb2_q;
- q->drv_priv = video;
- q->mem_ops = &vb2_dma_contig_memops;
- q->ops = &stf_video_vb2_q_ops;
- q->type = video->type;
- q->io_modes = VB2_DMABUF | VB2_MMAP;
- 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_queued_buffers = STFCAMSS_MIN_BUFFERS;
- ret = vb2_queue_init(q);
- if (ret < 0) {
- dev_err(video->stfcamss->dev,
- "Failed to init vb2 queue: %d\n", ret);
- goto err_mutex_destroy;
- }
-
- pad->flags = MEDIA_PAD_FL_SINK;
- ret = media_entity_pads_init(&vdev->entity, 1, pad);
- if (ret < 0) {
- dev_err(video->stfcamss->dev,
- "Failed to init video entity: %d\n", ret);
- goto err_mutex_destroy;
- }
-
- ret = stf_video_init_format(video);
- if (ret < 0) {
- dev_err(video->stfcamss->dev,
- "Failed to init format: %d\n", ret);
- goto err_media_cleanup;
- }
-
- vdev->fops = &stf_vid_fops;
- vdev->ioctl_ops = &stf_vid_ioctl_ops;
- vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
- vdev->entity.ops = &stf_media_ops;
- vdev->vfl_dir = VFL_DIR_RX;
- vdev->release = stf_video_release;
- vdev->v4l2_dev = v4l2_dev;
- vdev->queue = &video->vb2_q;
- vdev->lock = &video->lock;
- strscpy(vdev->name, name, sizeof(vdev->name));
-
- video_set_drvdata(vdev, video);
-
- ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1);
- if (ret < 0) {
- dev_err(video->stfcamss->dev,
- "Failed to register video device: %d\n", ret);
- goto err_media_cleanup;
- }
-
- return 0;
-
-err_media_cleanup:
- media_entity_cleanup(&vdev->entity);
-err_mutex_destroy:
- mutex_destroy(&video->lock);
- mutex_destroy(&video->q_lock);
- return ret;
-}
-
-void stf_video_unregister(struct stfcamss_video *video)
-{
- vb2_video_unregister_device(&video->vdev);
-}
diff --git a/drivers/staging/media/starfive/camss/stf-video.h b/drivers/staging/media/starfive/camss/stf-video.h
deleted file mode 100644
index 8052b77e3ad8..000000000000
--- a/drivers/staging/media/starfive/camss/stf-video.h
+++ /dev/null
@@ -1,100 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * stf_video.h
- *
- * StarFive Camera Subsystem - V4L2 device node
- *
- * Copyright (C) 2021-2023 StarFive Technology Co., Ltd.
- */
-
-#ifndef STF_VIDEO_H
-#define STF_VIDEO_H
-
-#include <linux/list.h>
-#include <linux/mutex.h>
-#include <linux/videodev2.h>
-#include <media/v4l2-dev.h>
-#include <media/v4l2-fh.h>
-#include <media/v4l2-ioctl.h>
-#include <media/videobuf2-v4l2.h>
-
-#define STFCAMSS_FRAME_MIN_WIDTH 64
-#define STFCAMSS_FRAME_MAX_WIDTH 1920
-#define STFCAMSS_FRAME_MIN_HEIGHT 64
-#define STFCAMSS_FRAME_MAX_HEIGHT 1080
-#define STFCAMSS_FRAME_WIDTH_ALIGN_8 8
-#define STFCAMSS_FRAME_WIDTH_ALIGN_128 128
-#define STFCAMSS_MIN_BUFFERS 2
-
-#define STFCAMSS_MAX_ENTITY_NAME_LEN 27
-
-enum stf_v_line_id {
- STF_V_LINE_WR = 0,
- STF_V_LINE_ISP,
- STF_V_LINE_MAX,
-};
-
-enum stf_capture_type {
- STF_CAPTURE_RAW = 0,
- STF_CAPTURE_YUV,
- STF_CAPTURE_NUM,
-};
-
-struct stfcamss_buffer {
- struct vb2_v4l2_buffer vb;
- dma_addr_t addr[2];
- struct list_head queue;
-};
-
-struct fract {
- u8 numerator;
- u8 denominator;
-};
-
-/*
- * struct stfcamss_format_info - ISP media bus format information
- * @code: V4L2 media bus format code
- * @pixelformat: V4L2 pixel format FCC identifier
- * @planes: Number of planes
- * @vsub: Vertical subsampling (for each plane)
- * @bpp: Bits per pixel when stored in memory (for each plane)
- */
-struct stfcamss_format_info {
- u32 code;
- u32 pixelformat;
- u8 planes;
- u8 vsub[3];
- u8 bpp;
-};
-
-struct stfcamss_video {
- struct stfcamss *stfcamss;
- struct vb2_queue vb2_q;
- struct video_device vdev;
- struct media_pad pad;
- struct v4l2_format active_fmt;
- enum v4l2_buf_type type;
- const struct stfcamss_video_ops *ops;
- struct mutex lock; /* serialize device access */
- struct mutex q_lock; /* protects the queue */
- unsigned int bpl_alignment;
- const struct stfcamss_format_info *formats;
- unsigned int nformats;
- struct v4l2_subdev *source_subdev;
-};
-
-struct stfcamss_video_ops {
- int (*queue_buffer)(struct stfcamss_video *video,
- struct stfcamss_buffer *buf);
- int (*flush_buffers)(struct stfcamss_video *video,
- enum vb2_buffer_state state);
- void (*start_streaming)(struct stfcamss_video *video);
- void (*stop_streaming)(struct stfcamss_video *video);
-};
-
-int stf_video_register(struct stfcamss_video *video,
- struct v4l2_device *v4l2_dev, const char *name);
-
-void stf_video_unregister(struct stfcamss_video *video);
-
-#endif /* STF_VIDEO_H */
diff --git a/drivers/staging/media/tegra-video/Makefile b/drivers/staging/media/tegra-video/Makefile
index 6c7552e05109..96380b5dbd8b 100644
--- a/drivers/staging/media/tegra-video/Makefile
+++ b/drivers/staging/media/tegra-video/Makefile
@@ -6,5 +6,6 @@ tegra-video-objs := \
csi.o
tegra-video-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra20.o
+tegra-video-$(CONFIG_ARCH_TEGRA_3x_SOC) += tegra20.o
tegra-video-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210.o
obj-$(CONFIG_VIDEO_TEGRA) += tegra-video.o
diff --git a/drivers/staging/media/tegra-video/csi.c b/drivers/staging/media/tegra-video/csi.c
index 7842104ca933..41d57dac61a7 100644
--- a/drivers/staging/media/tegra-video/csi.c
+++ b/drivers/staging/media/tegra-video/csi.c
@@ -12,6 +12,7 @@
#include <linux/of_graph.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
+#include <linux/tegra-mipi-cal.h>
#include <media/v4l2-fwnode.h>
@@ -20,17 +21,6 @@
#define MHZ 1000000
-static inline struct tegra_csi *
-host1x_client_to_csi(struct host1x_client *client)
-{
- return container_of(client, struct tegra_csi, client);
-}
-
-static inline struct tegra_csi_channel *to_csi_chan(struct v4l2_subdev *subdev)
-{
- return container_of(subdev, struct tegra_csi_channel, subdev);
-}
-
/*
* CSI is a separate subdevice which has 6 source pads to generate
* test pattern. CSI subdevice pad ops are used only for TPG and
@@ -455,6 +445,22 @@ static const struct v4l2_subdev_ops tegra_csi_ops = {
.pad = &tegra_csi_pad_ops,
};
+struct v4l2_subdev *tegra_channel_get_remote_csi_subdev(struct tegra_vi_channel *chan)
+{
+ struct media_pad *pad;
+ struct v4l2_subdev *subdev;
+
+ pad = media_pad_remote_pad_first(&chan->pad);
+ if (!pad)
+ return NULL;
+
+ subdev = media_entity_to_v4l2_subdev(pad->entity);
+ if (!subdev)
+ return NULL;
+
+ return subdev->ops == &tegra_csi_ops ? subdev : NULL;
+}
+
static int tegra_csi_channel_alloc(struct tegra_csi *csi,
struct device_node *node,
unsigned int port_num, unsigned int lanes,
@@ -704,6 +710,8 @@ static int __maybe_unused csi_runtime_suspend(struct device *dev)
clk_bulk_disable_unprepare(csi->soc->num_clks, csi->clks);
+ regulator_disable(csi->vdd);
+
return 0;
}
@@ -712,13 +720,23 @@ static int __maybe_unused csi_runtime_resume(struct device *dev)
struct tegra_csi *csi = dev_get_drvdata(dev);
int ret;
+ ret = regulator_enable(csi->vdd);
+ if (ret) {
+ dev_err(dev, "failed to enable VDD supply: %d\n", ret);
+ return ret;
+ }
+
ret = clk_bulk_prepare_enable(csi->soc->num_clks, csi->clks);
if (ret < 0) {
dev_err(csi->dev, "failed to enable clocks: %d\n", ret);
- return ret;
+ goto disable_vdd;
}
return 0;
+
+disable_vdd:
+ regulator_disable(csi->vdd);
+ return ret;
}
static int tegra_csi_init(struct host1x_client *client)
@@ -796,6 +814,11 @@ static int tegra_csi_probe(struct platform_device *pdev)
return ret;
}
+ csi->vdd = devm_regulator_get(&pdev->dev, "avdd-dsi-csi");
+ if (IS_ERR(csi->vdd))
+ return dev_err_probe(&pdev->dev, PTR_ERR(csi->vdd),
+ "failed to get VDD supply");
+
if (!pdev->dev.pm_domain) {
ret = -ENOENT;
dev_warn(&pdev->dev, "PM domain is not attached: %d\n", ret);
@@ -804,6 +827,17 @@ static int tegra_csi_probe(struct platform_device *pdev)
csi->dev = &pdev->dev;
csi->ops = csi->soc->ops;
+
+ if (csi->soc->mipi_ops) {
+ ret = devm_tegra_mipi_add_provider(&pdev->dev, pdev->dev.of_node,
+ csi->soc->mipi_ops);
+ if (ret)
+ return dev_err_probe(&pdev->dev, ret,
+ "failed to add MIPI calibration operations\n");
+ }
+
+ mutex_init(&csi->mipi_lock);
+
platform_set_drvdata(pdev, csi);
pm_runtime_enable(&pdev->dev);
@@ -836,6 +870,12 @@ static void tegra_csi_remove(struct platform_device *pdev)
}
static const struct of_device_id tegra_csi_of_id_table[] = {
+#if defined(CONFIG_ARCH_TEGRA_2x_SOC)
+ { .compatible = "nvidia,tegra20-csi", .data = &tegra20_csi_soc },
+#endif
+#if defined(CONFIG_ARCH_TEGRA_3x_SOC)
+ { .compatible = "nvidia,tegra30-csi", .data = &tegra30_csi_soc },
+#endif
#if defined(CONFIG_ARCH_TEGRA_210_SOC)
{ .compatible = "nvidia,tegra210-csi", .data = &tegra210_csi_soc },
#endif
diff --git a/drivers/staging/media/tegra-video/csi.h b/drivers/staging/media/tegra-video/csi.h
index 609c5952e050..f0277cb42446 100644
--- a/drivers/staging/media/tegra-video/csi.h
+++ b/drivers/staging/media/tegra-video/csi.h
@@ -115,6 +115,7 @@ struct tegra_csi_ops {
* struct tegra_csi_soc - NVIDIA Tegra CSI SoC structure
*
* @ops: csi hardware operations
+ * @mipi_ops: MIPI calibration operations
* @csi_max_channels: supported max streaming channels
* @clk_names: csi and cil clock names
* @num_clks: total clocks count
@@ -123,6 +124,7 @@ struct tegra_csi_ops {
*/
struct tegra_csi_soc {
const struct tegra_csi_ops *ops;
+ const struct tegra_mipi_ops *mipi_ops;
unsigned int csi_max_channels;
const char * const *clk_names;
unsigned int num_clks;
@@ -130,6 +132,12 @@ struct tegra_csi_soc {
unsigned int tpg_frmrate_table_size;
};
+#if defined(CONFIG_ARCH_TEGRA_2x_SOC)
+extern const struct tegra_csi_soc tegra20_csi_soc;
+#endif
+#if defined(CONFIG_ARCH_TEGRA_3x_SOC)
+extern const struct tegra_csi_soc tegra30_csi_soc;
+#endif
#if defined(CONFIG_ARCH_TEGRA_210_SOC)
extern const struct tegra_csi_soc tegra210_csi_soc;
#endif
@@ -141,8 +149,10 @@ extern const struct tegra_csi_soc tegra210_csi_soc;
* @client: host1x_client struct
* @iomem: register base
* @clks: clock for CSI and CIL
+ * @vdd: vdd regulator for CSI hardware, usually avdd_dsi_csi
* @soc: pointer to SoC data structure
* @ops: csi operations
+ * @mipi_lock: for MIPI calibration operations
* @csi_chans: list head for CSI channels
*/
struct tegra_csi {
@@ -150,11 +160,23 @@ struct tegra_csi {
struct host1x_client client;
void __iomem *iomem;
struct clk_bulk_data *clks;
+ struct regulator *vdd;
const struct tegra_csi_soc *soc;
const struct tegra_csi_ops *ops;
+ struct mutex mipi_lock; /* for register access */
struct list_head csi_chans;
};
+static inline struct tegra_csi *host1x_client_to_csi(struct host1x_client *client)
+{
+ return container_of(client, struct tegra_csi, client);
+}
+
+static inline struct tegra_csi_channel *to_csi_chan(struct v4l2_subdev *subdev)
+{
+ return container_of(subdev, struct tegra_csi_channel, subdev);
+}
+
void tegra_csi_error_recover(struct v4l2_subdev *subdev);
void tegra_csi_calc_settle_time(struct tegra_csi_channel *csi_chan,
u8 csi_port_num,
diff --git a/drivers/staging/media/tegra-video/tegra20.c b/drivers/staging/media/tegra-video/tegra20.c
index aa9ff7fec4f9..e513e6ccb776 100644
--- a/drivers/staging/media/tegra-video/tegra20.c
+++ b/drivers/staging/media/tegra-video/tegra20.c
@@ -4,6 +4,9 @@
*
* Copyright (C) 2023 SKIDATA GmbH
* Author: Luca Ceresoli <luca.ceresoli@bootlin.com>
+ *
+ * Copyright (c) 2025 Svyatoslav Ryhel <clamor95@gmail.com>
+ * Copyright (c) 2025 Jonas Schwöbel <jonasschwoebel@yahoo.de>
*/
/*
@@ -12,10 +15,15 @@
*/
#include <linux/bitfield.h>
+#include <linux/clk.h>
+#include <linux/clk/tegra.h>
#include <linux/delay.h>
#include <linux/host1x.h>
+#include <linux/iopoll.h>
#include <linux/kernel.h>
#include <linux/kthread.h>
+#include <linux/pm_runtime.h>
+#include <linux/tegra-mipi-cal.h>
#include <linux/v4l2-mediabus.h>
#include "vip.h"
@@ -23,19 +31,27 @@
#define TEGRA_VI_SYNCPT_WAIT_TIMEOUT msecs_to_jiffies(200)
-/* This are just good-sense numbers. The actual min/max is not documented. */
#define TEGRA20_MIN_WIDTH 32U
+#define TEGRA20_MAX_WIDTH 8190U
#define TEGRA20_MIN_HEIGHT 32U
-#define TEGRA20_MAX_WIDTH 2048U
-#define TEGRA20_MAX_HEIGHT 2048U
+#define TEGRA20_MAX_HEIGHT 8190U
+
+/* Tegra20/Tegra30 has 2 outputs in VI */
+enum tegra_vi_out {
+ TEGRA_VI_OUT_1 = 0,
+ TEGRA_VI_OUT_2 = 1,
+};
/* --------------------------------------------------------------------------
* Registers
*/
-#define TEGRA_VI_CONT_SYNCPT_OUT_1 0x0060
-#define VI_CONT_SYNCPT_OUT_1_CONTINUOUS_SYNCPT BIT(8)
-#define VI_CONT_SYNCPT_OUT_1_SYNCPT_IDX_SFT 0
+#define TEGRA_VI_CONT_SYNCPT_OUT(n) (0x0060 + (n) * 4)
+#define VI_CONT_SYNCPT_OUT_CONTINUOUS_SYNCPT BIT(8)
+#define VI_CONT_SYNCPT_OUT_SYNCPT_IDX_SFT 0
+
+#define TEGRA_VI_CONT_SYNCPT_CSI_PP_FRAME_START(n) (0x0070 + (n) * 8)
+#define TEGRA_VI_CONT_SYNCPT_CSI_PP_FRAME_END(n) (0x0074 + (n) * 8)
#define TEGRA_VI_VI_INPUT_CONTROL 0x0088
#define VI_INPUT_FIELD_DETECT BIT(27)
@@ -47,6 +63,7 @@
#define VI_INPUT_YUV_INPUT_FORMAT_YVYU (3 << VI_INPUT_YUV_INPUT_FORMAT_SFT)
#define VI_INPUT_INPUT_FORMAT_SFT 2 /* bits [5:2] */
#define VI_INPUT_INPUT_FORMAT_YUV422 (0 << VI_INPUT_INPUT_FORMAT_SFT)
+#define VI_INPUT_INPUT_FORMAT_BAYER (2 << VI_INPUT_INPUT_FORMAT_SFT)
#define VI_INPUT_VIP_INPUT_ENABLE BIT(1)
#define TEGRA_VI_VI_CORE_CONTROL 0x008c
@@ -67,7 +84,7 @@
#define VI_VI_CORE_CONTROL_OUTPUT_TO_EPP_SFT 2
#define VI_VI_CORE_CONTROL_OUTPUT_TO_ISP_SFT 0
-#define TEGRA_VI_VI_FIRST_OUTPUT_CONTROL 0x0090
+#define TEGRA_VI_VI_OUTPUT_CONTROL(n) (0x0090 + (n) * 4)
#define VI_OUTPUT_FORMAT_EXT BIT(22)
#define VI_OUTPUT_V_DIRECTION BIT(20)
#define VI_OUTPUT_H_DIRECTION BIT(19)
@@ -81,6 +98,10 @@
#define VI_OUTPUT_OUTPUT_FORMAT_SFT 0
#define VI_OUTPUT_OUTPUT_FORMAT_YUV422POST (3 << VI_OUTPUT_OUTPUT_FORMAT_SFT)
#define VI_OUTPUT_OUTPUT_FORMAT_YUV420PLANAR (6 << VI_OUTPUT_OUTPUT_FORMAT_SFT)
+/* TEGRA_VI_OUT_2 supported formats */
+#define VI_OUTPUT_OUTPUT_FORMAT_CSI_PPA_BAYER (7 << VI_OUTPUT_OUTPUT_FORMAT_SFT)
+#define VI_OUTPUT_OUTPUT_FORMAT_CSI_PPB_BAYER (8 << VI_OUTPUT_OUTPUT_FORMAT_SFT)
+#define VI_OUTPUT_OUTPUT_FORMAT_VIP_BAYER_DIRECT (9 << VI_OUTPUT_OUTPUT_FORMAT_SFT)
#define TEGRA_VI_VIP_H_ACTIVE 0x00a4
#define VI_VIP_H_ACTIVE_PERIOD_SFT 16 /* active pixels/line, must be even */
@@ -90,26 +111,26 @@
#define VI_VIP_V_ACTIVE_PERIOD_SFT 16 /* active lines */
#define VI_VIP_V_ACTIVE_START_SFT 0
-#define TEGRA_VI_VB0_START_ADDRESS_FIRST 0x00c4
-#define TEGRA_VI_VB0_BASE_ADDRESS_FIRST 0x00c8
+#define TEGRA_VI_VB0_START_ADDRESS(n) (0x00c4 + (n) * 44)
+#define TEGRA_VI_VB0_BASE_ADDRESS(n) (0x00c8 + (n) * 44)
#define TEGRA_VI_VB0_START_ADDRESS_U 0x00cc
#define TEGRA_VI_VB0_BASE_ADDRESS_U 0x00d0
#define TEGRA_VI_VB0_START_ADDRESS_V 0x00d4
#define TEGRA_VI_VB0_BASE_ADDRESS_V 0x00d8
-#define TEGRA_VI_FIRST_OUTPUT_FRAME_SIZE 0x00e0
-#define VI_FIRST_OUTPUT_FRAME_HEIGHT_SFT 16
-#define VI_FIRST_OUTPUT_FRAME_WIDTH_SFT 0
+#define TEGRA_VI_OUTPUT_FRAME_SIZE(n) (0x00e0 + (n) * 24)
+#define VI_OUTPUT_FRAME_HEIGHT_SFT 16
+#define VI_OUTPUT_FRAME_WIDTH_SFT 0
-#define TEGRA_VI_VB0_COUNT_FIRST 0x00e4
+#define TEGRA_VI_VB0_COUNT(n) (0x00e4 + (n) * 24)
-#define TEGRA_VI_VB0_SIZE_FIRST 0x00e8
-#define VI_VB0_SIZE_FIRST_V_SFT 16
-#define VI_VB0_SIZE_FIRST_H_SFT 0
+#define TEGRA_VI_VB0_SIZE(n) (0x00e8 + (n) * 24)
+#define VI_VB0_SIZE_V_SFT 16
+#define VI_VB0_SIZE_H_SFT 0
-#define TEGRA_VI_VB0_BUFFER_STRIDE_FIRST 0x00ec
-#define VI_VB0_BUFFER_STRIDE_FIRST_CHROMA_SFT 30
-#define VI_VB0_BUFFER_STRIDE_FIRST_LUMA_SFT 0
+#define TEGRA_VI_VB0_BUFFER_STRIDE(n) (0x00ec + (n) * 24)
+#define VI_VB0_BUFFER_STRIDE_CHROMA_SFT 30
+#define VI_VB0_BUFFER_STRIDE_LUMA_SFT 0
#define TEGRA_VI_H_LPF_CONTROL 0x0108
#define VI_H_LPF_CONTROL_CHROMA_SFT 16
@@ -137,15 +158,113 @@
#define VI_CAMERA_CONTROL_TEST_MODE BIT(1)
#define VI_CAMERA_CONTROL_VIP_ENABLE BIT(0)
-#define TEGRA_VI_VI_ENABLE 0x01a4
+#define TEGRA_VI_VI_ENABLE(n) (0x01a4 + (n) * 4)
#define VI_VI_ENABLE_SW_FLOW_CONTROL_OUT1 BIT(1)
#define VI_VI_ENABLE_FIRST_OUTPUT_TO_MEM_DISABLE BIT(0)
#define TEGRA_VI_VI_RAISE 0x01ac
#define VI_VI_RAISE_ON_EDGE BIT(0)
+#define TEGRA_VI_CSI_PP_RAISE_FRAME_START(n) (0x01d8 + (n) * 8)
+#define TEGRA_VI_CSI_PP_RAISE_FRAME_END(n) (0x01dc + (n) * 8)
+#define TEGRA_VI_CSI_PP_H_ACTIVE(n) (0x01e8 + (n) * 8)
+#define TEGRA_VI_CSI_PP_V_ACTIVE(n) (0x01ec + (n) * 8)
+
+/* Tegra20 CSI registers: Starts from 0x800, offset 0x0 */
+#define TEGRA_CSI_VI_INPUT_STREAM_CONTROL 0x0000
+#define TEGRA_CSI_HOST_INPUT_STREAM_CONTROL 0x0008
+#define TEGRA_CSI_INPUT_STREAM_CONTROL(n) (0x0010 + (n) * 0x2c)
+#define CSI_SKIP_PACKET_THRESHOLD(n) (((n) & 0xff) << 16)
+#define TEGRA_CSI_PIXEL_STREAM_CONTROL0(n) (0x0018 + (n) * 0x2c)
+#define CSI_PP_PAD_FRAME_PAD0S (0 << 28)
+#define CSI_PP_PAD_FRAME_PAD1S (1 << 28)
+#define CSI_PP_PAD_FRAME_NOPAD (2 << 28)
+#define CSI_PP_HEADER_EC_ENABLE BIT(27)
+#define CSI_PP_PAD_SHORT_LINE_PAD0S (0 << 24)
+#define CSI_PP_PAD_SHORT_LINE_PAD1S (1 << 24)
+#define CSI_PP_PAD_SHORT_LINE_NOPAD (2 << 24)
+#define CSI_PP_EMBEDDED_DATA_EMBEDDED BIT(20)
+#define CSI_PP_OUTPUT_FORMAT_ARBITRARY (0 << 16)
+#define CSI_PP_OUTPUT_FORMAT_PIXEL (1 << 16)
+#define CSI_PP_OUTPUT_FORMAT_PIXEL_REP (2 << 16)
+#define CSI_PP_OUTPUT_FORMAT_STORE (3 << 16)
+#define CSI_PP_VIRTUAL_CHANNEL_ID(n) (((n) - 1) << 14)
+#define CSI_PP_DATA_TYPE(n) ((n) << 8)
+#define CSI_PP_CRC_CHECK_ENABLE BIT(7)
+#define CSI_PP_WORD_COUNT_HEADER BIT(6)
+#define CSI_PP_DATA_IDENTIFIER_ENABLE BIT(5)
+#define CSI_PP_PACKET_HEADER_SENT BIT(4)
+#define TEGRA_CSI_PIXEL_STREAM_CONTROL1(n) (0x001c + (n) * 0x2c)
+#define TEGRA_CSI_PIXEL_STREAM_WORD_COUNT(n) (0x0020 + (n) * 0x2c)
+#define TEGRA_CSI_PIXEL_STREAM_GAP(n) (0x0024 + (n) * 0x2c)
+#define CSI_PP_FRAME_MIN_GAP(n) (((n) & 0xffff) << 16)
+#define CSI_PP_LINE_MIN_GAP(n) (((n) & 0xffff))
+#define TEGRA_CSI_PIXEL_STREAM_PP_COMMAND(n) (0x0028 + (n) * 0x2c)
+#define CSI_PP_START_MARKER_FRAME_MAX(n) (((n) & 0xf) << 12)
+#define CSI_PP_START_MARKER_FRAME_MIN(n) (((n) & 0xf) << 8)
+#define CSI_PP_VSYNC_START_MARKER BIT(4)
+#define CSI_PP_SINGLE_SHOT BIT(2)
+#define CSI_PP_NOP 0
+#define CSI_PP_ENABLE 1
+#define CSI_PP_DISABLE 2
+#define CSI_PP_RESET 3
+#define TEGRA_CSI_PHY_CIL_COMMAND 0x0068
+#define CSI_A_PHY_CIL_NOP 0x0
+#define CSI_A_PHY_CIL_ENABLE 0x1
+#define CSI_A_PHY_CIL_DISABLE 0x2
+#define CSI_A_PHY_CIL_ENABLE_MASK 0x3
+#define CSI_B_PHY_CIL_NOP (0x0 << 16)
+#define CSI_B_PHY_CIL_ENABLE (0x1 << 16)
+#define CSI_B_PHY_CIL_DISABLE (0x2 << 16)
+#define CSI_B_PHY_CIL_ENABLE_MASK (0x3 << 16)
+#define TEGRA_CSI_PHY_CIL_CONTROL0(n) (0x006c + (n) * 4)
+#define CSI_CONTINUOUS_CLOCK_MODE_ENABLE BIT(5)
+#define TEGRA_CSI_CSI_PIXEL_PARSER_STATUS 0x0078
+#define TEGRA_CSI_CSI_CIL_STATUS 0x007c
+#define CSI_MIPI_AUTO_CAL_DONE BIT(15)
+#define TEGRA_CSI_CSI_PIXEL_PARSER_INTERRUPT_MASK 0x0080
+#define TEGRA_CSI_CSI_CIL_INTERRUPT_MASK 0x0084
+#define TEGRA_CSI_CSI_READONLY_STATUS 0x0088
+#define TEGRA_CSI_ESCAPE_MODE_COMMAND 0x008c
+#define TEGRA_CSI_ESCAPE_MODE_DATA 0x0090
+#define TEGRA_CSI_CIL_PAD_CONFIG0(n) (0x0094 + (n) * 8)
+#define TEGRA_CSI_CIL_PAD_CONFIG1(n) (0x0098 + (n) * 8)
+#define TEGRA_CSI_CIL_PAD_CONFIG 0x00a4
+#define TEGRA_CSI_CILA_MIPI_CAL_CONFIG 0x00a8
+#define TEGRA_CSI_CILB_MIPI_CAL_CONFIG 0x00ac
+#define CSI_CIL_MIPI_CAL_STARTCAL BIT(31)
+#define CSI_CIL_MIPI_CAL_OVERIDE_A BIT(30)
+#define CSI_CIL_MIPI_CAL_OVERIDE_B BIT(30)
+#define CSI_CIL_MIPI_CAL_NOISE_FLT(n) (((n) & 0xf) << 26)
+#define CSI_CIL_MIPI_CAL_PRESCALE(n) (((n) & 0x3) << 24)
+#define CSI_CIL_MIPI_CAL_SEL_A BIT(21)
+#define CSI_CIL_MIPI_CAL_SEL_B BIT(21)
+#define CSI_CIL_MIPI_CAL_HSPDOS(n) (((n) & 0x1f) << 16)
+#define CSI_CIL_MIPI_CAL_HSPUOS(n) (((n) & 0x1f) << 8)
+#define CSI_CIL_MIPI_CAL_TERMOS(n) (((n) & 0x1f))
+#define TEGRA_CSI_CIL_MIPI_CAL_STATUS 0x00b0
+#define TEGRA_CSI_CLKEN_OVERRIDE 0x00b4
+#define TEGRA_CSI_DEBUG_CONTROL 0x00b8
+#define CSI_DEBUG_CONTROL_DEBUG_EN_ENABLED BIT(0)
+#define CSI_DEBUG_CONTROL_CLR_DBG_CNT_0 BIT(4)
+#define CSI_DEBUG_CONTROL_CLR_DBG_CNT_1 BIT(5)
+#define CSI_DEBUG_CONTROL_CLR_DBG_CNT_2 BIT(6)
+#define CSI_DEBUG_CONTROL_DBG_CNT_SEL(n, v) ((v) << (8 + 8 * (n)))
+#define TEGRA_CSI_DEBUG_COUNTER(n) (0x00bc + (n) * 4)
+#define TEGRA_CSI_PIXEL_STREAM_EXPECTED_FRAME(n) (0x00c8 + (n) * 4)
+#define CSI_PP_EXP_FRAME_HEIGHT(n) (((n) & 0x1fff) << 16)
+#define CSI_PP_MAX_CLOCKS(n) (((n) & 0xfff) << 4)
+#define CSI_PP_LINE_TIMEOUT_ENABLE BIT(0)
+#define TEGRA_CSI_DSI_MIPI_CAL_CONFIG 0x00d0
+#define TEGRA_CSI_MIPIBIAS_PAD_CONFIG 0x00d4
+#define CSI_PAD_DRIV_DN_REF(n) (((n) & 0x7) << 16)
+#define CSI_PAD_DRIV_UP_REF(n) (((n) & 0x7) << 8)
+#define CSI_PAD_TERM_REF(n) (((n) & 0x7) << 0)
+#define TEGRA_CSI_CSI_CILA_STATUS 0x00d8
+#define TEGRA_CSI_CSI_CILB_STATUS 0x00dc
+
/* --------------------------------------------------------------------------
- * VI
+ * Read and Write helpers
*/
static void tegra20_vi_write(struct tegra_vi_channel *chan, unsigned int addr, u32 val)
@@ -153,6 +272,35 @@ static void tegra20_vi_write(struct tegra_vi_channel *chan, unsigned int addr, u
writel(val, chan->vi->iomem + addr);
}
+static int __maybe_unused tegra20_vi_read(struct tegra_vi_channel *chan, unsigned int addr)
+{
+ return readl(chan->vi->iomem + addr);
+}
+
+static void tegra20_csi_write(struct tegra_csi_channel *csi_chan, unsigned int addr, u32 val)
+{
+ writel(val, csi_chan->csi->iomem + addr);
+}
+
+static int __maybe_unused tegra20_csi_read(struct tegra_csi_channel *csi_chan, unsigned int addr)
+{
+ return readl(csi_chan->csi->iomem + addr);
+}
+
+static void tegra20_mipi_write(struct tegra_csi *csi, unsigned int addr, u32 val)
+{
+ writel(val, csi->iomem + addr);
+}
+
+static int __maybe_unused tegra20_mipi_read(struct tegra_csi *csi, unsigned int addr)
+{
+ return readl(csi->iomem + addr);
+}
+
+/* --------------------------------------------------------------------------
+ * VI
+ */
+
/*
* Get the main input format (YUV/RGB...) and the YUV variant as values to
* be written into registers for the current VI input mbus code.
@@ -179,6 +327,18 @@ static void tegra20_vi_get_input_formats(struct tegra_vi_channel *chan,
case MEDIA_BUS_FMT_YVYU8_2X8:
(*yuv_input_format) = VI_INPUT_YUV_INPUT_FORMAT_YVYU;
break;
+ /* RAW8 */
+ case MEDIA_BUS_FMT_SBGGR8_1X8:
+ case MEDIA_BUS_FMT_SGBRG8_1X8:
+ case MEDIA_BUS_FMT_SGRBG8_1X8:
+ case MEDIA_BUS_FMT_SRGGB8_1X8:
+ /* RAW10 */
+ case MEDIA_BUS_FMT_SBGGR10_1X10:
+ case MEDIA_BUS_FMT_SGBRG10_1X10:
+ case MEDIA_BUS_FMT_SGRBG10_1X10:
+ case MEDIA_BUS_FMT_SRGGB10_1X10:
+ (*main_input_format) = VI_INPUT_INPUT_FORMAT_BAYER;
+ break;
}
}
@@ -213,6 +373,18 @@ static void tegra20_vi_get_output_formats(struct tegra_vi_channel *chan,
case V4L2_PIX_FMT_YVU420:
(*main_output_format) = VI_OUTPUT_OUTPUT_FORMAT_YUV420PLANAR;
break;
+ /* RAW8 */
+ case V4L2_PIX_FMT_SBGGR8:
+ case V4L2_PIX_FMT_SGBRG8:
+ case V4L2_PIX_FMT_SGRBG8:
+ case V4L2_PIX_FMT_SRGGB8:
+ /* RAW10 */
+ case V4L2_PIX_FMT_SBGGR10:
+ case V4L2_PIX_FMT_SGBRG10:
+ case V4L2_PIX_FMT_SGRBG10:
+ case V4L2_PIX_FMT_SRGGB10:
+ (*main_output_format) = VI_OUTPUT_OUTPUT_FORMAT_VIP_BAYER_DIRECT;
+ break;
}
}
@@ -251,20 +423,27 @@ static int tegra20_vi_enable(struct tegra_vi *vi, bool on)
static int tegra20_channel_host1x_syncpt_init(struct tegra_vi_channel *chan)
{
struct tegra_vi *vi = chan->vi;
- struct host1x_syncpt *out_sp;
+ struct host1x_syncpt *out_sp, *fs_sp;
out_sp = host1x_syncpt_request(&vi->client, HOST1X_SYNCPT_CLIENT_MANAGED);
if (!out_sp)
- return -ENOMEM;
+ return dev_err_probe(vi->dev, -EBUSY, "failed to request mw ack syncpoint\n");
chan->mw_ack_sp[0] = out_sp;
+ fs_sp = host1x_syncpt_request(&vi->client, HOST1X_SYNCPT_CLIENT_MANAGED);
+ if (!fs_sp)
+ return dev_err_probe(vi->dev, -EBUSY, "failed to request frame start syncpoint\n");
+
+ chan->frame_start_sp[0] = fs_sp;
+
return 0;
}
static void tegra20_channel_host1x_syncpt_free(struct tegra_vi_channel *chan)
{
host1x_syncpt_put(chan->mw_ack_sp[0]);
+ host1x_syncpt_put(chan->frame_start_sp[0]);
}
static void tegra20_fmt_align(struct v4l2_pix_format *pix, unsigned int bpp)
@@ -272,18 +451,13 @@ static void tegra20_fmt_align(struct v4l2_pix_format *pix, unsigned int bpp)
pix->width = clamp(pix->width, TEGRA20_MIN_WIDTH, TEGRA20_MAX_WIDTH);
pix->height = clamp(pix->height, TEGRA20_MIN_HEIGHT, TEGRA20_MAX_HEIGHT);
+ pix->bytesperline = roundup(pix->width, 8) * bpp;
+ pix->sizeimage = pix->bytesperline * pix->height;
+
switch (pix->pixelformat) {
- case V4L2_PIX_FMT_UYVY:
- case V4L2_PIX_FMT_VYUY:
- case V4L2_PIX_FMT_YUYV:
- case V4L2_PIX_FMT_YVYU:
- pix->bytesperline = roundup(pix->width, 2) * 2;
- pix->sizeimage = roundup(pix->width, 2) * 2 * pix->height;
- break;
case V4L2_PIX_FMT_YUV420:
case V4L2_PIX_FMT_YVU420:
- pix->bytesperline = roundup(pix->width, 8);
- pix->sizeimage = roundup(pix->width, 8) * pix->height * 3 / 2;
+ pix->sizeimage = pix->sizeimage * 3 / 2;
break;
}
}
@@ -305,6 +479,16 @@ static void tegra20_channel_queue_setup(struct tegra_vi_channel *chan)
case V4L2_PIX_FMT_VYUY:
case V4L2_PIX_FMT_YUYV:
case V4L2_PIX_FMT_YVYU:
+ /* RAW8 */
+ case V4L2_PIX_FMT_SRGGB8:
+ case V4L2_PIX_FMT_SGRBG8:
+ case V4L2_PIX_FMT_SGBRG8:
+ case V4L2_PIX_FMT_SBGGR8:
+ /* RAW10 */
+ case V4L2_PIX_FMT_SRGGB10:
+ case V4L2_PIX_FMT_SGRBG10:
+ case V4L2_PIX_FMT_SGBRG10:
+ case V4L2_PIX_FMT_SBGGR10:
if (chan->vflip)
chan->start_offset += stride * (height - 1);
if (chan->hflip)
@@ -367,48 +551,111 @@ static void tegra20_channel_vi_buffer_setup(struct tegra_vi_channel *chan,
case V4L2_PIX_FMT_VYUY:
case V4L2_PIX_FMT_YUYV:
case V4L2_PIX_FMT_YVYU:
- tegra20_vi_write(chan, TEGRA_VI_VB0_BASE_ADDRESS_FIRST, base);
- tegra20_vi_write(chan, TEGRA_VI_VB0_START_ADDRESS_FIRST, base + chan->start_offset);
+ tegra20_vi_write(chan, TEGRA_VI_VB0_BASE_ADDRESS(TEGRA_VI_OUT_1), base);
+ tegra20_vi_write(chan, TEGRA_VI_VB0_START_ADDRESS(TEGRA_VI_OUT_1), base + chan->start_offset);
+ break;
+ /* RAW8 */
+ case V4L2_PIX_FMT_SRGGB8:
+ case V4L2_PIX_FMT_SGRBG8:
+ case V4L2_PIX_FMT_SGBRG8:
+ case V4L2_PIX_FMT_SBGGR8:
+ /* RAW10 */
+ case V4L2_PIX_FMT_SRGGB10:
+ case V4L2_PIX_FMT_SGRBG10:
+ case V4L2_PIX_FMT_SGBRG10:
+ case V4L2_PIX_FMT_SBGGR10:
+ tegra20_vi_write(chan, TEGRA_VI_VB0_BASE_ADDRESS(TEGRA_VI_OUT_2), base);
+ tegra20_vi_write(chan, TEGRA_VI_VB0_START_ADDRESS(TEGRA_VI_OUT_2), base + chan->start_offset);
break;
}
}
static int tegra20_channel_capture_frame(struct tegra_vi_channel *chan,
- struct tegra_channel_buffer *buf)
+ struct tegra_channel_buffer *buf,
+ struct tegra_csi_channel *csi_chan)
{
+ u32 val;
int err;
- chan->next_out_sp_idx++;
-
tegra20_channel_vi_buffer_setup(chan, buf);
- tegra20_vi_write(chan, TEGRA_VI_CAMERA_CONTROL, VI_CAMERA_CONTROL_VIP_ENABLE);
+ if (csi_chan) {
+ u32 port = csi_chan->csi_port_nums[0] & 1;
+
+ tegra20_csi_write(csi_chan, TEGRA_CSI_PIXEL_STREAM_PP_COMMAND(port),
+ CSI_PP_START_MARKER_FRAME_MAX(0xf) |
+ CSI_PP_SINGLE_SHOT | CSI_PP_ENABLE);
+
+ /*
+ * ERESTARTSYS workaround for syncpoints is used because host1x_syncpt_wait
+ * is unconditionally interruptible. This is not an issue with single shots
+ * or low resolution capture, but -ERESTARTSYS occurs quite often with high
+ * resolution or high framerate captures and if not addressed here will
+ * cause capture to fail entirely.
+ *
+ * TODO: once uninterruptible version of host1x_syncpt_wait is available,
+ * host1x_syncpt_wait should be swapped and ERESTARTSYS workaround can be
+ * removed.
+ */
+
+ val = host1x_syncpt_read(chan->frame_start_sp[0]);
+ do {
+ err = host1x_syncpt_wait(chan->frame_start_sp[0],
+ val + 1, TEGRA_VI_SYNCPT_WAIT_TIMEOUT, NULL);
+ } while (err == -ERESTARTSYS);
+
+ if (err) {
+ if (err != -ERESTARTSYS)
+ dev_err_ratelimited(&chan->video.dev,
+ "frame start syncpt timeout: %d\n", err);
+
+ tegra20_csi_write(csi_chan, TEGRA_CSI_PIXEL_STREAM_PP_COMMAND(port),
+ CSI_PP_START_MARKER_FRAME_MAX(0xf) | CSI_PP_RESET);
+ goto exit;
+ }
+
+ tegra20_csi_write(csi_chan, TEGRA_CSI_PIXEL_STREAM_PP_COMMAND(port),
+ CSI_PP_START_MARKER_FRAME_MAX(0xf) |
+ CSI_PP_DISABLE);
+ } else {
+ tegra20_vi_write(chan, TEGRA_VI_CAMERA_CONTROL, VI_CAMERA_CONTROL_VIP_ENABLE);
+ }
+
+ val = host1x_syncpt_read(chan->mw_ack_sp[0]);
+ do {
+ err = host1x_syncpt_wait(chan->mw_ack_sp[0], val + 1,
+ TEGRA_VI_SYNCPT_WAIT_TIMEOUT, NULL);
+ } while (err == -ERESTARTSYS);
- /* Wait for syncpt counter to reach frame start event threshold */
- err = host1x_syncpt_wait(chan->mw_ack_sp[0], chan->next_out_sp_idx,
- TEGRA_VI_SYNCPT_WAIT_TIMEOUT, NULL);
if (err) {
- host1x_syncpt_incr(chan->mw_ack_sp[0]);
- dev_err_ratelimited(&chan->video.dev, "frame start syncpt timeout: %d\n", err);
- release_buffer(chan, buf, VB2_BUF_STATE_ERROR);
- return err;
+ if (err != -ERESTARTSYS)
+ dev_err_ratelimited(&chan->video.dev, "mw ack syncpt timeout: %d\n", err);
+ goto exit;
}
- tegra20_vi_write(chan, TEGRA_VI_CAMERA_CONTROL,
- VI_CAMERA_CONTROL_STOP_CAPTURE | VI_CAMERA_CONTROL_VIP_ENABLE);
+ if (!csi_chan)
+ tegra20_vi_write(chan, TEGRA_VI_CAMERA_CONTROL,
+ VI_CAMERA_CONTROL_STOP_CAPTURE | VI_CAMERA_CONTROL_VIP_ENABLE);
+exit:
release_buffer(chan, buf, VB2_BUF_STATE_DONE);
- return 0;
+ return err;
}
static int tegra20_chan_capture_kthread_start(void *data)
{
struct tegra_vi_channel *chan = data;
struct tegra_channel_buffer *buf;
+ struct v4l2_subdev *csi_subdev = NULL;
+ struct tegra_csi_channel *csi_chan = NULL;
unsigned int retries = 0;
int err = 0;
+ csi_subdev = tegra_channel_get_remote_csi_subdev(chan);
+ if (csi_subdev)
+ csi_chan = to_csi_chan(csi_subdev);
+
while (1) {
/*
* Source is not streaming if error is non-zero.
@@ -433,7 +680,7 @@ static int tegra20_chan_capture_kthread_start(void *data)
list_del_init(&buf->queue);
spin_unlock(&chan->start_lock);
- err = tegra20_channel_capture_frame(chan, buf);
+ err = tegra20_channel_capture_frame(chan, buf, csi_chan);
if (!err) {
retries = 0;
continue;
@@ -451,55 +698,37 @@ static int tegra20_chan_capture_kthread_start(void *data)
static void tegra20_camera_capture_setup(struct tegra_vi_channel *chan)
{
u32 output_fourcc = chan->format.pixelformat;
+ u32 data_type = chan->fmtinfo->img_dt;
int width = chan->format.width;
int height = chan->format.height;
- int stride_l = chan->format.bytesperline;
+ int stride_l = chan->format.bytesperline * height;
int stride_c = (output_fourcc == V4L2_PIX_FMT_YUV420 ||
output_fourcc == V4L2_PIX_FMT_YVU420) ? 1 : 0;
- int main_output_format;
- int yuv_output_format;
-
- tegra20_vi_get_output_formats(chan, &main_output_format, &yuv_output_format);
-
- /*
- * Set up low pass filter. Use 0x240 for chromaticity and 0x240
- * for luminance, which is the default and means not to touch
- * anything.
- */
- tegra20_vi_write(chan, TEGRA_VI_H_LPF_CONTROL,
- 0x0240 << VI_H_LPF_CONTROL_LUMA_SFT |
- 0x0240 << VI_H_LPF_CONTROL_CHROMA_SFT);
-
- /* Set up raise-on-edge, so we get an interrupt on end of frame. */
- tegra20_vi_write(chan, TEGRA_VI_VI_RAISE, VI_VI_RAISE_ON_EDGE);
-
- tegra20_vi_write(chan, TEGRA_VI_VI_FIRST_OUTPUT_CONTROL,
- (chan->vflip ? VI_OUTPUT_V_DIRECTION : 0) |
- (chan->hflip ? VI_OUTPUT_H_DIRECTION : 0) |
- yuv_output_format << VI_OUTPUT_YUV_OUTPUT_FORMAT_SFT |
- main_output_format << VI_OUTPUT_OUTPUT_FORMAT_SFT);
+ enum tegra_vi_out output_channel = (data_type == TEGRA_IMAGE_DT_RAW8 ||
+ data_type == TEGRA_IMAGE_DT_RAW10) ?
+ TEGRA_VI_OUT_2 : TEGRA_VI_OUT_1;
/* Set up frame size */
- tegra20_vi_write(chan, TEGRA_VI_FIRST_OUTPUT_FRAME_SIZE,
- height << VI_FIRST_OUTPUT_FRAME_HEIGHT_SFT |
- width << VI_FIRST_OUTPUT_FRAME_WIDTH_SFT);
+ tegra20_vi_write(chan, TEGRA_VI_OUTPUT_FRAME_SIZE(output_channel),
+ height << VI_OUTPUT_FRAME_HEIGHT_SFT |
+ width << VI_OUTPUT_FRAME_WIDTH_SFT);
/* First output memory enabled */
- tegra20_vi_write(chan, TEGRA_VI_VI_ENABLE, 0);
+ tegra20_vi_write(chan, TEGRA_VI_VI_ENABLE(output_channel), 0);
/* Set the number of frames in the buffer */
- tegra20_vi_write(chan, TEGRA_VI_VB0_COUNT_FIRST, 1);
+ tegra20_vi_write(chan, TEGRA_VI_VB0_COUNT(output_channel), 1);
/* Set up buffer frame size */
- tegra20_vi_write(chan, TEGRA_VI_VB0_SIZE_FIRST,
- height << VI_VB0_SIZE_FIRST_V_SFT |
- width << VI_VB0_SIZE_FIRST_H_SFT);
+ tegra20_vi_write(chan, TEGRA_VI_VB0_SIZE(output_channel),
+ height << VI_VB0_SIZE_V_SFT |
+ width << VI_VB0_SIZE_H_SFT);
- tegra20_vi_write(chan, TEGRA_VI_VB0_BUFFER_STRIDE_FIRST,
- stride_l << VI_VB0_BUFFER_STRIDE_FIRST_LUMA_SFT |
- stride_c << VI_VB0_BUFFER_STRIDE_FIRST_CHROMA_SFT);
+ tegra20_vi_write(chan, TEGRA_VI_VB0_BUFFER_STRIDE(output_channel),
+ stride_l << VI_VB0_BUFFER_STRIDE_LUMA_SFT |
+ stride_c << VI_VB0_BUFFER_STRIDE_CHROMA_SFT);
- tegra20_vi_write(chan, TEGRA_VI_VI_ENABLE, 0);
+ tegra20_vi_write(chan, TEGRA_VI_VI_ENABLE(output_channel), 0);
}
static int tegra20_vi_start_streaming(struct vb2_queue *vq, u32 count)
@@ -508,18 +737,28 @@ static int tegra20_vi_start_streaming(struct vb2_queue *vq, u32 count)
struct media_pipeline *pipe = &chan->video.pipe;
int err;
- chan->next_out_sp_idx = host1x_syncpt_read(chan->mw_ack_sp[0]);
-
err = video_device_pipeline_start(&chan->video, pipe);
if (err)
goto error_pipeline_start;
- tegra20_camera_capture_setup(chan);
+ /*
+ * Set up low pass filter. Use 0x240 for chromaticity and 0x240
+ * for luminance, which is the default and means not to touch
+ * anything.
+ */
+ tegra20_vi_write(chan, TEGRA_VI_H_LPF_CONTROL,
+ 0x0240 << VI_H_LPF_CONTROL_LUMA_SFT |
+ 0x0240 << VI_H_LPF_CONTROL_CHROMA_SFT);
+
+ /* Set up raise-on-edge, so we get an interrupt on end of frame. */
+ tegra20_vi_write(chan, TEGRA_VI_VI_RAISE, VI_VI_RAISE_ON_EDGE);
err = tegra_channel_set_stream(chan, true);
if (err)
goto error_set_stream;
+ tegra20_camera_capture_setup(chan);
+
chan->sequence = 0;
chan->kthread_start_capture = kthread_run(tegra20_chan_capture_kthread_start,
@@ -567,20 +806,40 @@ static const struct tegra_vi_ops tegra20_vi_ops = {
.vi_stop_streaming = tegra20_vi_stop_streaming,
};
-#define TEGRA20_VIDEO_FMT(MBUS_CODE, BPP, FOURCC) \
-{ \
- .code = MEDIA_BUS_FMT_##MBUS_CODE, \
- .bpp = BPP, \
- .fourcc = V4L2_PIX_FMT_##FOURCC, \
+#define TEGRA20_VIDEO_FMT(DATA_TYPE, BIT_WIDTH, MBUS_CODE, BPP, FOURCC) \
+{ \
+ .img_dt = TEGRA_IMAGE_DT_##DATA_TYPE, \
+ .bit_width = BIT_WIDTH, \
+ .code = MEDIA_BUS_FMT_##MBUS_CODE, \
+ .bpp = BPP, \
+ .fourcc = V4L2_PIX_FMT_##FOURCC, \
}
static const struct tegra_video_format tegra20_video_formats[] = {
- TEGRA20_VIDEO_FMT(UYVY8_2X8, 2, UYVY),
- TEGRA20_VIDEO_FMT(VYUY8_2X8, 2, VYUY),
- TEGRA20_VIDEO_FMT(YUYV8_2X8, 2, YUYV),
- TEGRA20_VIDEO_FMT(YVYU8_2X8, 2, YVYU),
- TEGRA20_VIDEO_FMT(UYVY8_2X8, 1, YUV420),
- TEGRA20_VIDEO_FMT(UYVY8_2X8, 1, YVU420),
+ /* YUV422 */
+ TEGRA20_VIDEO_FMT(YUV422_8, 16, UYVY8_2X8, 2, UYVY),
+ TEGRA20_VIDEO_FMT(YUV422_8, 16, VYUY8_2X8, 2, VYUY),
+ TEGRA20_VIDEO_FMT(YUV422_8, 16, YUYV8_2X8, 2, YUYV),
+ TEGRA20_VIDEO_FMT(YUV422_8, 16, YVYU8_2X8, 2, YVYU),
+ TEGRA20_VIDEO_FMT(YUV422_8, 16, UYVY8_1X16, 2, UYVY),
+ TEGRA20_VIDEO_FMT(YUV422_8, 16, VYUY8_1X16, 2, VYUY),
+ TEGRA20_VIDEO_FMT(YUV422_8, 16, YUYV8_1X16, 2, YUYV),
+ TEGRA20_VIDEO_FMT(YUV422_8, 16, YVYU8_1X16, 2, YVYU),
+ /* YUV420P */
+ TEGRA20_VIDEO_FMT(YUV422_8, 16, UYVY8_2X8, 1, YUV420),
+ TEGRA20_VIDEO_FMT(YUV422_8, 16, UYVY8_2X8, 1, YVU420),
+ TEGRA20_VIDEO_FMT(YUV422_8, 16, UYVY8_1X16, 1, YUV420),
+ TEGRA20_VIDEO_FMT(YUV422_8, 16, UYVY8_1X16, 1, YVU420),
+ /* RAW 8 */
+ TEGRA20_VIDEO_FMT(RAW8, 8, SRGGB8_1X8, 2, SRGGB8),
+ TEGRA20_VIDEO_FMT(RAW8, 8, SGRBG8_1X8, 2, SGRBG8),
+ TEGRA20_VIDEO_FMT(RAW8, 8, SGBRG8_1X8, 2, SGBRG8),
+ TEGRA20_VIDEO_FMT(RAW8, 8, SBGGR8_1X8, 2, SBGGR8),
+ /* RAW 10 */
+ TEGRA20_VIDEO_FMT(RAW10, 10, SRGGB10_1X10, 2, SRGGB10),
+ TEGRA20_VIDEO_FMT(RAW10, 10, SGRBG10_1X10, 2, SGRBG10),
+ TEGRA20_VIDEO_FMT(RAW10, 10, SGBRG10_1X10, 2, SGBRG10),
+ TEGRA20_VIDEO_FMT(RAW10, 10, SBGGR10_1X10, 2, SBGGR10),
};
const struct tegra_vi_soc tegra20_vi_soc = {
@@ -588,12 +847,352 @@ const struct tegra_vi_soc tegra20_vi_soc = {
.nformats = ARRAY_SIZE(tegra20_video_formats),
.default_video_format = &tegra20_video_formats[0],
.ops = &tegra20_vi_ops,
- .vi_max_channels = 1, /* parallel input (VIP) */
- .vi_max_clk_hz = 150000000,
+ .hw_revision = 1,
+ .vi_max_channels = 2, /* TEGRA_VI_OUT_1 and TEGRA_VI_OUT_2 */
+ .vi_max_clk_hz = 450000000,
.has_h_v_flip = true,
};
/* --------------------------------------------------------------------------
+ * MIPI Calibration
+ */
+static int tegra20_start_pad_calibration(struct tegra_mipi_device *mipi)
+{
+ struct tegra_csi *csi = platform_get_drvdata(mipi->pdev);
+ unsigned int port = mipi->pads;
+ u32 value;
+ int ret;
+
+ guard(mutex)(&csi->mipi_lock);
+
+ ret = pm_runtime_resume_and_get(csi->dev);
+ if (ret < 0) {
+ dev_err(csi->dev, "failed to get runtime PM: %d\n", ret);
+ return ret;
+ }
+
+ tegra20_mipi_write(csi, TEGRA_CSI_DSI_MIPI_CAL_CONFIG,
+ CSI_CIL_MIPI_CAL_HSPDOS(4) |
+ CSI_CIL_MIPI_CAL_HSPUOS(3) |
+ CSI_CIL_MIPI_CAL_TERMOS(0));
+ tegra20_mipi_write(csi, TEGRA_CSI_MIPIBIAS_PAD_CONFIG,
+ CSI_PAD_DRIV_DN_REF(5) |
+ CSI_PAD_DRIV_UP_REF(7) |
+ CSI_PAD_TERM_REF(0));
+
+ /* CSI B */
+ value = CSI_CIL_MIPI_CAL_HSPDOS(0) |
+ CSI_CIL_MIPI_CAL_HSPUOS(0) |
+ CSI_CIL_MIPI_CAL_TERMOS(4);
+
+ if (port == PORT_B)
+ value |= CSI_CIL_MIPI_CAL_SEL_B;
+
+ tegra20_mipi_write(csi, TEGRA_CSI_CILB_MIPI_CAL_CONFIG, value);
+
+ /* CSI A */
+ value = CSI_CIL_MIPI_CAL_STARTCAL |
+ CSI_CIL_MIPI_CAL_NOISE_FLT(0xa) |
+ CSI_CIL_MIPI_CAL_PRESCALE(0x2) |
+ CSI_CIL_MIPI_CAL_HSPDOS(0) |
+ CSI_CIL_MIPI_CAL_HSPUOS(0) |
+ CSI_CIL_MIPI_CAL_TERMOS(4);
+
+ if (port == PORT_A)
+ value |= CSI_CIL_MIPI_CAL_SEL_A;
+
+ tegra20_mipi_write(csi, TEGRA_CSI_CILA_MIPI_CAL_CONFIG, value);
+
+ tegra20_mipi_write(csi, TEGRA_CSI_CIL_PAD_CONFIG, 0);
+
+ return 0;
+}
+
+static int tegra20_finish_pad_calibration(struct tegra_mipi_device *mipi)
+{
+ struct tegra_csi *csi = platform_get_drvdata(mipi->pdev);
+ void __iomem *cil_status_reg = csi->iomem + TEGRA_CSI_CSI_CIL_STATUS;
+ unsigned int port = mipi->pads;
+ u32 value, pp = 0, cil = 0;
+ int ret;
+
+ /* This part is only for CSI */
+ if (port > PORT_B) {
+ pm_runtime_put(csi->dev);
+
+ return 0;
+ }
+
+ guard(mutex)(&csi->mipi_lock);
+
+ ret = readl_relaxed_poll_timeout(cil_status_reg, value,
+ value & CSI_MIPI_AUTO_CAL_DONE, 50, 250000);
+ if (ret < 0) {
+ dev_warn(csi->dev, "MIPI calibration timeout!\n");
+ goto exit;
+ }
+
+ /* clear status */
+ tegra20_mipi_write(csi, TEGRA_CSI_CSI_CIL_STATUS, value);
+ ret = readl_relaxed_poll_timeout(cil_status_reg, value,
+ !(value & CSI_MIPI_AUTO_CAL_DONE), 50, 250000);
+ if (ret < 0) {
+ dev_warn(csi->dev, "MIPI calibration status timeout!\n");
+ goto exit;
+ }
+
+ pp = tegra20_mipi_read(csi, TEGRA_CSI_CSI_PIXEL_PARSER_STATUS);
+ cil = tegra20_mipi_read(csi, TEGRA_CSI_CSI_CIL_STATUS);
+ if (pp | cil) {
+ dev_warn(csi->dev, "Calibration status not been cleared!\n");
+ ret = -EINVAL;
+ goto exit;
+ }
+
+exit:
+ tegra20_mipi_write(csi, TEGRA_CSI_CSI_CIL_STATUS, pp);
+
+ /* un-select to avoid interference with DSI */
+ tegra20_mipi_write(csi, TEGRA_CSI_CILB_MIPI_CAL_CONFIG,
+ CSI_CIL_MIPI_CAL_HSPDOS(0) |
+ CSI_CIL_MIPI_CAL_HSPUOS(0) |
+ CSI_CIL_MIPI_CAL_TERMOS(4));
+
+ tegra20_mipi_write(csi, TEGRA_CSI_CILA_MIPI_CAL_CONFIG,
+ CSI_CIL_MIPI_CAL_NOISE_FLT(0xa) |
+ CSI_CIL_MIPI_CAL_PRESCALE(0x2) |
+ CSI_CIL_MIPI_CAL_HSPDOS(0) |
+ CSI_CIL_MIPI_CAL_HSPUOS(0) |
+ CSI_CIL_MIPI_CAL_TERMOS(4));
+
+ pm_runtime_put(csi->dev);
+
+ return ret;
+}
+
+static const struct tegra_mipi_ops tegra20_mipi_ops = {
+ .start_calibration = tegra20_start_pad_calibration,
+ .finish_calibration = tegra20_finish_pad_calibration,
+};
+
+/* --------------------------------------------------------------------------
+ * CSI
+ */
+static void tegra20_csi_capture_clean(struct tegra_csi_channel *csi_chan)
+{
+ tegra20_csi_write(csi_chan, TEGRA_CSI_VI_INPUT_STREAM_CONTROL, 0);
+ tegra20_csi_write(csi_chan, TEGRA_CSI_HOST_INPUT_STREAM_CONTROL, 0);
+
+ tegra20_csi_write(csi_chan, TEGRA_CSI_CSI_PIXEL_PARSER_STATUS, 0);
+ tegra20_csi_write(csi_chan, TEGRA_CSI_CSI_CIL_STATUS, 0);
+ tegra20_csi_write(csi_chan, TEGRA_CSI_CSI_PIXEL_PARSER_INTERRUPT_MASK, 0);
+ tegra20_csi_write(csi_chan, TEGRA_CSI_CSI_CIL_INTERRUPT_MASK, 0);
+ tegra20_csi_write(csi_chan, TEGRA_CSI_CSI_READONLY_STATUS, 0);
+ tegra20_csi_write(csi_chan, TEGRA_CSI_ESCAPE_MODE_COMMAND, 0);
+ tegra20_csi_write(csi_chan, TEGRA_CSI_ESCAPE_MODE_DATA, 0);
+
+ tegra20_csi_write(csi_chan, TEGRA_CSI_CIL_PAD_CONFIG, 0);
+ tegra20_csi_write(csi_chan, TEGRA_CSI_CIL_MIPI_CAL_STATUS, 0);
+ tegra20_csi_write(csi_chan, TEGRA_CSI_CLKEN_OVERRIDE, 0);
+
+ tegra20_csi_write(csi_chan, TEGRA_CSI_DEBUG_CONTROL,
+ CSI_DEBUG_CONTROL_CLR_DBG_CNT_0 |
+ CSI_DEBUG_CONTROL_CLR_DBG_CNT_1 |
+ CSI_DEBUG_CONTROL_CLR_DBG_CNT_2);
+}
+
+static int tegra20_csi_port_start_streaming(struct tegra_csi_channel *csi_chan,
+ u8 portno)
+{
+ struct tegra_vi_channel *vi_chan = v4l2_get_subdev_hostdata(&csi_chan->subdev);
+ int width = vi_chan->format.width;
+ int height = vi_chan->format.height;
+ u32 data_type = vi_chan->fmtinfo->img_dt;
+ u32 word_count = (width * vi_chan->fmtinfo->bit_width) / 8;
+ enum tegra_vi_out output_channel = TEGRA_VI_OUT_1;
+
+ unsigned int main_output_format, yuv_output_format;
+ unsigned int port = portno & 1;
+ u32 value;
+
+ tegra20_vi_get_output_formats(vi_chan, &main_output_format, &yuv_output_format);
+
+ switch (data_type) {
+ case TEGRA_IMAGE_DT_RAW8:
+ case TEGRA_IMAGE_DT_RAW10:
+ output_channel = TEGRA_VI_OUT_2;
+ if (port == PORT_A)
+ main_output_format = VI_OUTPUT_OUTPUT_FORMAT_CSI_PPA_BAYER;
+ else
+ main_output_format = VI_OUTPUT_OUTPUT_FORMAT_CSI_PPB_BAYER;
+ break;
+ }
+
+ tegra20_csi_capture_clean(csi_chan);
+
+ /* CSI port cleanup */
+ tegra20_csi_write(csi_chan, TEGRA_CSI_INPUT_STREAM_CONTROL(port), 0);
+ tegra20_csi_write(csi_chan, TEGRA_CSI_PIXEL_STREAM_CONTROL0(port), 0);
+ tegra20_csi_write(csi_chan, TEGRA_CSI_PIXEL_STREAM_CONTROL1(port), 0);
+ tegra20_csi_write(csi_chan, TEGRA_CSI_PIXEL_STREAM_WORD_COUNT(port), 0);
+ tegra20_csi_write(csi_chan, TEGRA_CSI_PIXEL_STREAM_GAP(port), 0);
+ tegra20_csi_write(csi_chan, TEGRA_CSI_PIXEL_STREAM_PP_COMMAND(port), 0);
+ tegra20_csi_write(csi_chan, TEGRA_CSI_PIXEL_STREAM_EXPECTED_FRAME(port), 0);
+ tegra20_csi_write(csi_chan, TEGRA_CSI_PHY_CIL_CONTROL0(port), 0);
+ tegra20_csi_write(csi_chan, TEGRA_CSI_CIL_PAD_CONFIG0(port), 0);
+ tegra20_csi_write(csi_chan, TEGRA_CSI_CIL_PAD_CONFIG1(port), 0);
+
+ tegra20_vi_write(vi_chan, TEGRA_VI_VI_CORE_CONTROL, BIT(25 + port)); /* CSI_PP_YUV422 */
+
+ tegra20_vi_write(vi_chan, TEGRA_VI_H_DOWNSCALE_CONTROL, BIT(2 + port)); /* CSI_PP */
+ tegra20_vi_write(vi_chan, TEGRA_VI_V_DOWNSCALE_CONTROL, BIT(2 + port)); /* CSI_PP */
+
+ tegra20_vi_write(vi_chan, TEGRA_VI_CSI_PP_H_ACTIVE(port), width << 16);
+ tegra20_vi_write(vi_chan, TEGRA_VI_CSI_PP_V_ACTIVE(port), height << 16);
+
+ tegra20_csi_write(csi_chan, TEGRA_CSI_PIXEL_STREAM_CONTROL1(port), 0x1);
+
+ tegra20_csi_write(csi_chan, TEGRA_CSI_PIXEL_STREAM_WORD_COUNT(port), word_count);
+ tegra20_csi_write(csi_chan, TEGRA_CSI_PIXEL_STREAM_GAP(port),
+ CSI_PP_FRAME_MIN_GAP(0x14)); /* 14 vi clks between frames */
+
+ tegra20_csi_write(csi_chan, TEGRA_CSI_PIXEL_STREAM_EXPECTED_FRAME(port),
+ CSI_PP_EXP_FRAME_HEIGHT(height) |
+ CSI_PP_MAX_CLOCKS(0x300) | /* wait 0x300 vi clks for timeout */
+ CSI_PP_LINE_TIMEOUT_ENABLE);
+
+ tegra20_csi_write(csi_chan, TEGRA_CSI_PIXEL_STREAM_CONTROL0(port),
+ CSI_PP_OUTPUT_FORMAT_PIXEL |
+ CSI_PP_DATA_TYPE(data_type) |
+ CSI_PP_CRC_CHECK_ENABLE |
+ CSI_PP_WORD_COUNT_HEADER |
+ CSI_PP_DATA_IDENTIFIER_ENABLE |
+ CSI_PP_PACKET_HEADER_SENT |
+ port);
+
+ tegra20_csi_write(csi_chan, TEGRA_CSI_INPUT_STREAM_CONTROL(port),
+ CSI_SKIP_PACKET_THRESHOLD(0x3f) |
+ (csi_chan->numlanes - 1));
+
+ tegra20_csi_write(csi_chan, TEGRA_CSI_PHY_CIL_CONTROL0(port),
+ CSI_CONTINUOUS_CLOCK_MODE_ENABLE |
+ 0x5); /* Clock settle time */
+
+ tegra20_vi_write(vi_chan, TEGRA_VI_CONT_SYNCPT_CSI_PP_FRAME_START(port),
+ VI_CONT_SYNCPT_OUT_CONTINUOUS_SYNCPT |
+ host1x_syncpt_id(vi_chan->frame_start_sp[0])
+ << VI_CONT_SYNCPT_OUT_SYNCPT_IDX_SFT);
+
+ tegra20_vi_write(vi_chan, TEGRA_VI_CONT_SYNCPT_OUT(output_channel),
+ VI_CONT_SYNCPT_OUT_CONTINUOUS_SYNCPT |
+ host1x_syncpt_id(vi_chan->mw_ack_sp[0])
+ << VI_CONT_SYNCPT_OUT_SYNCPT_IDX_SFT);
+
+ value = (port == PORT_A) ? CSI_A_PHY_CIL_ENABLE | CSI_B_PHY_CIL_DISABLE :
+ CSI_B_PHY_CIL_ENABLE | CSI_A_PHY_CIL_DISABLE;
+ tegra20_csi_write(csi_chan, TEGRA_CSI_PHY_CIL_COMMAND, value);
+
+ tegra20_csi_write(csi_chan, TEGRA_CSI_PIXEL_STREAM_PP_COMMAND(port),
+ CSI_PP_START_MARKER_FRAME_MAX(0xf) |
+ CSI_PP_DISABLE);
+
+ tegra20_vi_write(vi_chan, TEGRA_VI_VI_OUTPUT_CONTROL(output_channel),
+ (vi_chan->vflip ? VI_OUTPUT_V_DIRECTION : 0) |
+ (vi_chan->hflip ? VI_OUTPUT_H_DIRECTION : 0) |
+ yuv_output_format | main_output_format);
+
+ return 0;
+};
+
+static void tegra20_csi_port_stop_streaming(struct tegra_csi_channel *csi_chan, u8 portno)
+{
+ struct tegra_csi *csi = csi_chan->csi;
+ unsigned int port = portno & 1;
+ u32 value;
+
+ value = tegra20_csi_read(csi_chan, TEGRA_CSI_CSI_PIXEL_PARSER_STATUS);
+ dev_dbg(csi->dev, "TEGRA_CSI_CSI_PIXEL_PARSER_STATUS 0x%08x\n", value);
+ tegra20_csi_write(csi_chan, TEGRA_CSI_CSI_PIXEL_PARSER_STATUS, value);
+
+ value = tegra20_csi_read(csi_chan, TEGRA_CSI_CSI_CIL_STATUS);
+ dev_dbg(csi->dev, "TEGRA_CSI_CSI_CIL_STATUS 0x%08x\n", value);
+ tegra20_csi_write(csi_chan, TEGRA_CSI_CSI_CIL_STATUS, value);
+
+ tegra20_csi_write(csi_chan, TEGRA_CSI_PIXEL_STREAM_PP_COMMAND(port),
+ CSI_PP_START_MARKER_FRAME_MAX(0xf) |
+ CSI_PP_DISABLE);
+
+ if (csi_chan->numlanes == 4) {
+ tegra20_csi_write(csi_chan, TEGRA_CSI_PHY_CIL_COMMAND,
+ CSI_A_PHY_CIL_DISABLE | CSI_B_PHY_CIL_DISABLE);
+ } else {
+ value = (port == PORT_A) ? CSI_A_PHY_CIL_DISABLE | CSI_B_PHY_CIL_NOP :
+ CSI_B_PHY_CIL_DISABLE | CSI_A_PHY_CIL_NOP;
+ tegra20_csi_write(csi_chan, TEGRA_CSI_PHY_CIL_COMMAND, value);
+ }
+}
+
+static int tegra20_csi_start_streaming(struct tegra_csi_channel *csi_chan)
+{
+ u8 *portnos = csi_chan->csi_port_nums;
+ int ret, i;
+
+ for (i = 0; i < csi_chan->numgangports; i++) {
+ ret = tegra20_csi_port_start_streaming(csi_chan, portnos[i]);
+ if (ret)
+ goto stream_start_fail;
+ }
+
+ return 0;
+
+stream_start_fail:
+ for (i = i - 1; i >= 0; i--)
+ tegra20_csi_port_stop_streaming(csi_chan, portnos[i]);
+
+ return ret;
+}
+
+static void tegra20_csi_stop_streaming(struct tegra_csi_channel *csi_chan)
+{
+ u8 *portnos = csi_chan->csi_port_nums;
+ int i;
+
+ for (i = 0; i < csi_chan->numgangports; i++)
+ tegra20_csi_port_stop_streaming(csi_chan, portnos[i]);
+}
+
+static const struct tegra_csi_ops tegra20_csi_ops = {
+ .csi_start_streaming = tegra20_csi_start_streaming,
+ .csi_stop_streaming = tegra20_csi_stop_streaming,
+};
+
+static const char * const tegra20_csi_clks[] = {
+ NULL,
+};
+
+const struct tegra_csi_soc tegra20_csi_soc = {
+ .ops = &tegra20_csi_ops,
+ .mipi_ops = &tegra20_mipi_ops,
+ .csi_max_channels = 2, /* CSI-A and CSI-B */
+ .clk_names = tegra20_csi_clks,
+ .num_clks = ARRAY_SIZE(tegra20_csi_clks),
+};
+
+static const char * const tegra30_csi_clks[] = {
+ "csi",
+ "csia-pad",
+ "csib-pad",
+};
+
+const struct tegra_csi_soc tegra30_csi_soc = {
+ .ops = &tegra20_csi_ops,
+ .mipi_ops = &tegra20_mipi_ops,
+ .csi_max_channels = 2, /* CSI-A and CSI-B */
+ .clk_names = tegra30_csi_clks,
+ .num_clks = ARRAY_SIZE(tegra30_csi_clks),
+};
+
+/* --------------------------------------------------------------------------
* VIP
*/
@@ -606,13 +1205,17 @@ const struct tegra_vi_soc tegra20_vi_soc = {
static int tegra20_vip_start_streaming(struct tegra_vip_channel *vip_chan)
{
struct tegra_vi_channel *vi_chan = v4l2_get_subdev_hostdata(&vip_chan->subdev);
+ u32 data_type = vi_chan->fmtinfo->img_dt;
int width = vi_chan->format.width;
int height = vi_chan->format.height;
-
- unsigned int main_input_format;
- unsigned int yuv_input_format;
+ enum tegra_vi_out output_channel = (data_type == TEGRA_IMAGE_DT_RAW8 ||
+ data_type == TEGRA_IMAGE_DT_RAW10) ?
+ TEGRA_VI_OUT_2 : TEGRA_VI_OUT_1;
+ unsigned int main_input_format, yuv_input_format;
+ unsigned int main_output_format, yuv_output_format;
tegra20_vi_get_input_formats(vi_chan, &main_input_format, &yuv_input_format);
+ tegra20_vi_get_output_formats(vi_chan, &main_output_format, &yuv_output_format);
tegra20_vi_write(vi_chan, TEGRA_VI_VI_CORE_CONTROL, 0);
@@ -638,13 +1241,18 @@ static int tegra20_vip_start_streaming(struct tegra_vip_channel *vip_chan)
GENMASK(9, 2) << VI_DATA_INPUT_SFT);
tegra20_vi_write(vi_chan, TEGRA_VI_PIN_INVERSION, 0);
- tegra20_vi_write(vi_chan, TEGRA_VI_CONT_SYNCPT_OUT_1,
- VI_CONT_SYNCPT_OUT_1_CONTINUOUS_SYNCPT |
+ tegra20_vi_write(vi_chan, TEGRA_VI_CONT_SYNCPT_OUT(output_channel),
+ VI_CONT_SYNCPT_OUT_CONTINUOUS_SYNCPT |
host1x_syncpt_id(vi_chan->mw_ack_sp[0])
- << VI_CONT_SYNCPT_OUT_1_SYNCPT_IDX_SFT);
+ << VI_CONT_SYNCPT_OUT_SYNCPT_IDX_SFT);
tegra20_vi_write(vi_chan, TEGRA_VI_CAMERA_CONTROL, VI_CAMERA_CONTROL_STOP_CAPTURE);
+ tegra20_vi_write(vi_chan, TEGRA_VI_VI_OUTPUT_CONTROL(output_channel),
+ (vi_chan->vflip ? VI_OUTPUT_V_DIRECTION : 0) |
+ (vi_chan->hflip ? VI_OUTPUT_H_DIRECTION : 0) |
+ yuv_output_format | main_output_format);
+
return 0;
}
diff --git a/drivers/staging/media/tegra-video/vi.c b/drivers/staging/media/tegra-video/vi.c
index 9c0b38585d63..f14cdc7b5211 100644
--- a/drivers/staging/media/tegra-video/vi.c
+++ b/drivers/staging/media/tegra-video/vi.c
@@ -160,8 +160,8 @@ static void tegra_channel_buffer_queue(struct vb2_buffer *vb)
wake_up_interruptible(&chan->start_wait);
}
-struct v4l2_subdev *
-tegra_channel_get_remote_csi_subdev(struct tegra_vi_channel *chan)
+static struct v4l2_subdev *
+tegra_channel_get_remote_bridge_subdev(struct tegra_vi_channel *chan)
{
struct media_pad *pad;
@@ -182,7 +182,7 @@ tegra_channel_get_remote_source_subdev(struct tegra_vi_channel *chan)
struct v4l2_subdev *subdev;
struct media_entity *entity;
- subdev = tegra_channel_get_remote_csi_subdev(chan);
+ subdev = tegra_channel_get_remote_bridge_subdev(chan);
if (!subdev)
return NULL;
@@ -204,7 +204,7 @@ static int tegra_channel_enable_stream(struct tegra_vi_channel *chan)
struct v4l2_subdev *subdev;
int ret;
- subdev = tegra_channel_get_remote_csi_subdev(chan);
+ subdev = tegra_channel_get_remote_bridge_subdev(chan);
ret = v4l2_subdev_call(subdev, video, s_stream, true);
if (ret < 0 && ret != -ENOIOCTLCMD)
return ret;
@@ -217,7 +217,7 @@ static int tegra_channel_disable_stream(struct tegra_vi_channel *chan)
struct v4l2_subdev *subdev;
int ret;
- subdev = tegra_channel_get_remote_csi_subdev(chan);
+ subdev = tegra_channel_get_remote_bridge_subdev(chan);
ret = v4l2_subdev_call(subdev, video, s_stream, false);
if (ret < 0 && ret != -ENOIOCTLCMD)
return ret;
@@ -476,17 +476,11 @@ static int __tegra_channel_try_format(struct tegra_vi_channel *chan,
fse.code = fmtinfo->code;
ret = v4l2_subdev_call(subdev, pad, enum_frame_size, sd_state, &fse);
if (ret) {
- if (!v4l2_subdev_has_op(subdev, pad, get_selection)) {
+ if (!v4l2_subdev_has_op(subdev, pad, get_selection) ||
+ v4l2_subdev_call(subdev, pad, get_selection, NULL, &sdsel)) {
try_crop->width = 0;
try_crop->height = 0;
} else {
- ret = v4l2_subdev_call(subdev, pad, get_selection,
- NULL, &sdsel);
- if (ret) {
- ret = -EINVAL;
- goto out_free;
- }
-
try_crop->width = sdsel.r.width;
try_crop->height = sdsel.r.height;
}
@@ -968,6 +962,7 @@ static int tegra_channel_setup_ctrl_handler(struct tegra_vi_channel *chan)
}
#else
struct v4l2_subdev *subdev;
+ struct v4l2_ctrl *hflip, *vflip;
/* custom control */
v4l2_ctrl_new_custom(&chan->ctrl_handler, &syncpt_timeout_ctrl, NULL);
@@ -993,11 +988,13 @@ static int tegra_channel_setup_ctrl_handler(struct tegra_vi_channel *chan)
return ret;
}
- if (chan->vi->soc->has_h_v_flip) {
+ hflip = v4l2_ctrl_find(subdev->ctrl_handler, V4L2_CID_HFLIP);
+ if (chan->vi->soc->has_h_v_flip && !hflip)
v4l2_ctrl_new_std(&chan->ctrl_handler, &vi_ctrl_ops, V4L2_CID_HFLIP, 0, 1, 1, 0);
- v4l2_ctrl_new_std(&chan->ctrl_handler, &vi_ctrl_ops, V4L2_CID_VFLIP, 0, 1, 1, 0);
- }
+ vflip = v4l2_ctrl_find(subdev->ctrl_handler, V4L2_CID_VFLIP);
+ if (chan->vi->soc->has_h_v_flip && !vflip)
+ v4l2_ctrl_new_std(&chan->ctrl_handler, &vi_ctrl_ops, V4L2_CID_VFLIP, 0, 1, 1, 0);
#endif
/* setup the controls */
@@ -1421,29 +1418,19 @@ static int __maybe_unused vi_runtime_resume(struct device *dev)
struct tegra_vi *vi = dev_get_drvdata(dev);
int ret;
- ret = regulator_enable(vi->vdd);
- if (ret) {
- dev_err(dev, "failed to enable VDD supply: %d\n", ret);
- return ret;
- }
-
ret = clk_set_rate(vi->clk, vi->soc->vi_max_clk_hz);
if (ret) {
dev_err(dev, "failed to set vi clock rate: %d\n", ret);
- goto disable_vdd;
+ return ret;
}
ret = clk_prepare_enable(vi->clk);
if (ret) {
dev_err(dev, "failed to enable vi clock: %d\n", ret);
- goto disable_vdd;
+ return ret;
}
return 0;
-
-disable_vdd:
- regulator_disable(vi->vdd);
- return ret;
}
static int __maybe_unused vi_runtime_suspend(struct device *dev)
@@ -1452,8 +1439,6 @@ static int __maybe_unused vi_runtime_suspend(struct device *dev)
clk_disable_unprepare(vi->clk);
- regulator_disable(vi->vdd);
-
return 0;
}
@@ -1634,11 +1619,11 @@ static int tegra_vi_graph_notify_complete(struct v4l2_async_notifier *notifier)
goto unregister_video;
}
- subdev = tegra_channel_get_remote_csi_subdev(chan);
+ subdev = tegra_channel_get_remote_bridge_subdev(chan);
if (!subdev) {
ret = -ENODEV;
dev_err(vi->dev,
- "failed to get remote csi subdev: %d\n", ret);
+ "failed to get remote bridge subdev: %d\n", ret);
goto unregister_video;
}
@@ -1898,13 +1883,6 @@ static int tegra_vi_probe(struct platform_device *pdev)
return ret;
}
- vi->vdd = devm_regulator_get(&pdev->dev, "avdd-dsi-csi");
- if (IS_ERR(vi->vdd)) {
- ret = PTR_ERR(vi->vdd);
- dev_err(&pdev->dev, "failed to get VDD supply: %d\n", ret);
- return ret;
- }
-
if (!pdev->dev.pm_domain) {
ret = -ENOENT;
dev_warn(&pdev->dev, "PM domain is not attached: %d\n", ret);
@@ -1959,7 +1937,7 @@ static void tegra_vi_remove(struct platform_device *pdev)
}
static const struct of_device_id tegra_vi_of_id_table[] = {
-#if defined(CONFIG_ARCH_TEGRA_2x_SOC)
+#if defined(CONFIG_ARCH_TEGRA_2x_SOC) || defined(CONFIG_ARCH_TEGRA_3x_SOC)
{ .compatible = "nvidia,tegra20-vi", .data = &tegra20_vi_soc },
#endif
#if defined(CONFIG_ARCH_TEGRA_210_SOC)
diff --git a/drivers/staging/media/tegra-video/vi.h b/drivers/staging/media/tegra-video/vi.h
index 1e6a5caa7082..46328e488aa3 100644
--- a/drivers/staging/media/tegra-video/vi.h
+++ b/drivers/staging/media/tegra-video/vi.h
@@ -94,7 +94,6 @@ struct tegra_vi_soc {
* @client: host1x_client struct
* @iomem: register base
* @clk: main clock for VI block
- * @vdd: vdd regulator for VI hardware, normally it is avdd_dsi_csi
* @soc: pointer to SoC data structure
* @ops: vi operations
* @vi_chans: list head for VI channels
@@ -104,7 +103,6 @@ struct tegra_vi {
struct host1x_client client;
void __iomem *iomem;
struct clk *clk;
- struct regulator *vdd;
const struct tegra_vi_soc *soc;
const struct tegra_vi_ops *ops;
struct list_head vi_chans;
@@ -127,7 +125,6 @@ struct tegra_vi {
* frame through host1x syncpoint counters (On Tegra20 used for the
* OUT_1 syncpt)
* @sp_incr_lock: protects cpu syncpoint increment.
- * @next_out_sp_idx: next expected value for mw_ack_sp[0], i.e. OUT_1 (Tegra20)
*
* @kthread_start_capture: kthread to start capture of single frame when
* vb buffer is available. This thread programs VI CSI hardware
@@ -190,7 +187,6 @@ struct tegra_vi_channel {
struct host1x_syncpt *mw_ack_sp[GANG_PORTS_MAX];
/* protects the cpu syncpoint increment */
spinlock_t sp_incr_lock[GANG_PORTS_MAX];
- u32 next_out_sp_idx;
struct task_struct *kthread_start_capture;
wait_queue_head_t start_wait;
@@ -296,7 +292,7 @@ struct tegra_video_format {
u32 fourcc;
};
-#if defined(CONFIG_ARCH_TEGRA_2x_SOC)
+#if defined(CONFIG_ARCH_TEGRA_2x_SOC) || defined(CONFIG_ARCH_TEGRA_3x_SOC)
extern const struct tegra_vi_soc tegra20_vi_soc;
#endif
#if defined(CONFIG_ARCH_TEGRA_210_SOC)
diff --git a/drivers/staging/media/tegra-video/video.c b/drivers/staging/media/tegra-video/video.c
index ae1ae03fa9de..2e84385708ba 100644
--- a/drivers/staging/media/tegra-video/video.c
+++ b/drivers/staging/media/tegra-video/video.c
@@ -121,10 +121,16 @@ static void host1x_video_remove(struct host1x_device *dev)
}
static const struct of_device_id host1x_video_subdevs[] = {
-#if defined(CONFIG_ARCH_TEGRA_2x_SOC)
+#if defined(CONFIG_ARCH_TEGRA_2x_SOC) || defined(CONFIG_ARCH_TEGRA_3x_SOC)
{ .compatible = "nvidia,tegra20-vip", },
{ .compatible = "nvidia,tegra20-vi", },
#endif
+#if defined(CONFIG_ARCH_TEGRA_2x_SOC)
+ { .compatible = "nvidia,tegra20-csi", },
+#endif
+#if defined(CONFIG_ARCH_TEGRA_3x_SOC)
+ { .compatible = "nvidia,tegra30-csi", },
+#endif
#if defined(CONFIG_ARCH_TEGRA_210_SOC)
{ .compatible = "nvidia,tegra210-csi", },
{ .compatible = "nvidia,tegra210-vi", },
diff --git a/drivers/staging/media/tegra-video/vip.c b/drivers/staging/media/tegra-video/vip.c
index 80cd3b113125..9ff1f1750a15 100644
--- a/drivers/staging/media/tegra-video/vip.c
+++ b/drivers/staging/media/tegra-video/vip.c
@@ -264,7 +264,7 @@ static void tegra_vip_remove(struct platform_device *pdev)
}
static const struct of_device_id tegra_vip_of_id_table[] = {
-#if defined(CONFIG_ARCH_TEGRA_2x_SOC)
+#if defined(CONFIG_ARCH_TEGRA_2x_SOC) || defined(CONFIG_ARCH_TEGRA_3x_SOC)
{ .compatible = "nvidia,tegra20-vip", .data = &tegra20_vip_soc },
#endif
{ }
diff --git a/drivers/staging/media/tegra-video/vip.h b/drivers/staging/media/tegra-video/vip.h
index fdded00447e4..563059cbf5b5 100644
--- a/drivers/staging/media/tegra-video/vip.h
+++ b/drivers/staging/media/tegra-video/vip.h
@@ -50,7 +50,7 @@ struct tegra_vip_soc {
const struct tegra_vip_ops *ops;
};
-#if defined(CONFIG_ARCH_TEGRA_2x_SOC)
+#if defined(CONFIG_ARCH_TEGRA_2x_SOC) || defined(CONFIG_ARCH_TEGRA_3x_SOC)
extern const struct tegra_vip_soc tegra20_vip_soc;
#endif