summaryrefslogtreecommitdiffstats
path: root/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-common.h
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2024-01-12 14:29:48 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2024-01-12 14:29:48 -0800
commit61da593f4458f25c59f65cfd9ba1bda570db5db7 (patch)
tree42196179375dfda07901577e080f979b2897d308 /drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-common.h
parentMerge tag 'libnvdimm-for-6.8' of git://git.kernel.org/pub/scm/linux/kernel/gi... (diff)
parentmedia: i2c: thp7312: select CONFIG_FW_LOADER (diff)
downloadlinux-61da593f4458f25c59f65cfd9ba1bda570db5db7.tar.gz
linux-61da593f4458f25c59f65cfd9ba1bda570db5db7.zip
Merge tag 'media/v6.8-2' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
Pull media updates from Mauro Carvalho Chehab: - v4l core: subdev frame interval now supports which field - v4l kapi: moves and renames the init_cfg pad op to init_state as an internal op. - new sensor drivers: gc0308, gc2145, Avnet Alvium, ov64a40, tw9900 - new camera driver: STM32 DCMIPP - s5p-mfc has gained MFC v12 support - new ISP driver added to staging: Starfive - new stateful encoder/decoded: Wave5 codec It is found on the J721S2 SoC, JH7100 SoC, ssd202d SoC. Etc. - fwnode gained support for MIPI "DisCo for Imaging" (https://www.mipi.org/specifications/mipi-disco-imaging) - as usual, lots of cleanups, fixups and driver improvements. * tag 'media/v6.8-2' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (309 commits) media: i2c: thp7312: select CONFIG_FW_LOADER media: i2c: mt9m114: use fsleep() in place of udelay() media: videobuf2: core: Rename min_buffers_needed field in vb2_queue media: i2c: thp7312: Store frame interval in subdev state media: docs: uAPI: Fix documentation of 'which' field for routing ioctls media: docs: uAPI: Expand error documentation for invalid 'which' value media: docs: uAPI: Clarify error documentation for invalid 'which' value media: v4l2-subdev: Store frame interval in subdev state media: v4l2-subdev: Add which field to struct v4l2_subdev_frame_interval media: v4l2-subdev: Turn .[gs]_frame_interval into pad operations media: v4l: subdev: Move out subdev state lock macros outside CONFIG_MEDIA_CONTROLLER media: s5p-mfc: DPB Count Independent of VIDIOC_REQBUF media: s5p-mfc: Load firmware for each run in MFCv12. media: s5p-mfc: Set context for valid case before calling try_run media: s5p-mfc: Add support for DMABUF for encoder media: s5p-mfc: Add support for UHD encoding. media: s5p-mfc: Add support for rate controls in MFCv12 media: s5p-mfc: Add YV12 and I420 multiplanar format support media: s5p-mfc: Add initial support for MFCv12 media: s5p-mfc: Rename IS_MFCV10 macro ...
Diffstat (limited to 'drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-common.h')
-rw-r--r--drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-common.h217
1 files changed, 217 insertions, 0 deletions
diff --git a/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-common.h b/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-common.h
new file mode 100644
index 000000000000..7a7cf43baf24
--- /dev/null
+++ b/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-common.h
@@ -0,0 +1,217 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Driver for STM32 Digital Camera Memory Interface Pixel Processor
+ *
+ * Copyright (C) STMicroelectronics SA 2023
+ * Authors: Hugues Fruchet <hugues.fruchet@foss.st.com>
+ * Alain Volmat <alain.volmat@foss.st.com>
+ * for STMicroelectronics.
+ */
+
+#ifndef _DCMIPP_COMMON_H_
+#define _DCMIPP_COMMON_H_
+
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <media/media-device.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-fwnode.h>
+
+#define DCMIPP_PDEV_NAME "dcmipp"
+
+#define DCMIPP_FRAME_MAX_WIDTH 4096
+#define DCMIPP_FRAME_MAX_HEIGHT 2160
+#define DCMIPP_FRAME_MIN_WIDTH 16
+#define DCMIPP_FRAME_MIN_HEIGHT 16
+
+#define DCMIPP_FMT_WIDTH_DEFAULT 640
+#define DCMIPP_FMT_HEIGHT_DEFAULT 480
+
+#define DCMIPP_COLORSPACE_DEFAULT V4L2_COLORSPACE_REC709
+#define DCMIPP_YCBCR_ENC_DEFAULT V4L2_YCBCR_ENC_DEFAULT
+#define DCMIPP_QUANTIZATION_DEFAULT V4L2_QUANTIZATION_DEFAULT
+#define DCMIPP_XFER_FUNC_DEFAULT V4L2_XFER_FUNC_DEFAULT
+
+/**
+ * dcmipp_colorimetry_clamp() - Adjust colorimetry parameters
+ *
+ * @fmt: the pointer to struct v4l2_pix_format or
+ * struct v4l2_mbus_framefmt
+ *
+ * Entities must check if colorimetry given by the userspace is valid, if not
+ * then set them as DEFAULT
+ */
+#define dcmipp_colorimetry_clamp(fmt) \
+do { \
+ if ((fmt)->colorspace == V4L2_COLORSPACE_DEFAULT || \
+ (fmt)->colorspace > V4L2_COLORSPACE_DCI_P3) { \
+ (fmt)->colorspace = DCMIPP_COLORSPACE_DEFAULT; \
+ (fmt)->ycbcr_enc = DCMIPP_YCBCR_ENC_DEFAULT; \
+ (fmt)->quantization = DCMIPP_QUANTIZATION_DEFAULT; \
+ (fmt)->xfer_func = DCMIPP_XFER_FUNC_DEFAULT; \
+ } \
+ if ((fmt)->ycbcr_enc > V4L2_YCBCR_ENC_SMPTE240M) \
+ (fmt)->ycbcr_enc = DCMIPP_YCBCR_ENC_DEFAULT; \
+ if ((fmt)->quantization > V4L2_QUANTIZATION_LIM_RANGE) \
+ (fmt)->quantization = DCMIPP_QUANTIZATION_DEFAULT; \
+ if ((fmt)->xfer_func > V4L2_XFER_FUNC_SMPTE2084) \
+ (fmt)->xfer_func = DCMIPP_XFER_FUNC_DEFAULT; \
+} while (0)
+
+/**
+ * struct dcmipp_ent_device - core struct that represents a node in the topology
+ *
+ * @ent: the pointer to struct media_entity for the node
+ * @pads: the list of pads of the node
+ * @bus: struct v4l2_mbus_config_parallel describing input bus
+ * @bus_type: type of input bus (parallel or BT656)
+ * @handler: irq handler dedicated to the subdev
+ * @handler_ret: value returned by the irq handler
+ * @thread_fn: threaded irq handler
+ *
+ * The DCMIPP provides a single IRQ line and a IRQ status registers for all
+ * subdevs, hence once the main irq handler (registered at probe time) is
+ * called, it will chain calls to the irq handler of each the subdevs of the
+ * pipelines, using the handler/handler_ret/thread_fn variables.
+ *
+ * Each node of the topology must create a dcmipp_ent_device struct.
+ * Depending on the node it will be of an instance of v4l2_subdev or
+ * video_device struct where both contains a struct media_entity.
+ * Those structures should embedded the dcmipp_ent_device struct through
+ * v4l2_set_subdevdata() and video_set_drvdata() respectivaly, allowing the
+ * dcmipp_ent_device struct to be retrieved from the corresponding struct
+ * media_entity
+ */
+struct dcmipp_ent_device {
+ struct media_entity *ent;
+ struct media_pad *pads;
+
+ /* Parallel input device */
+ struct v4l2_mbus_config_parallel bus;
+ enum v4l2_mbus_type bus_type;
+ irq_handler_t handler;
+ irqreturn_t handler_ret;
+ irq_handler_t thread_fn;
+};
+
+/**
+ * dcmipp_pads_init - initialize pads
+ *
+ * @num_pads: number of pads to initialize
+ * @pads_flags: flags to use in each pad
+ *
+ * Helper functions to allocate/initialize pads
+ */
+struct media_pad *dcmipp_pads_init(u16 num_pads,
+ const unsigned long *pads_flags);
+
+/**
+ * dcmipp_pads_cleanup - free pads
+ *
+ * @pads: pointer to the pads
+ *
+ * Helper function to free the pads initialized with dcmipp_pads_init
+ */
+static inline void dcmipp_pads_cleanup(struct media_pad *pads)
+{
+ kfree(pads);
+}
+
+/**
+ * dcmipp_ent_sd_register - initialize and register a subdev node
+ *
+ * @ved: the dcmipp_ent_device struct to be initialize
+ * @sd: the v4l2_subdev struct to be initialize and registered
+ * @v4l2_dev: the v4l2 device to register the v4l2_subdev
+ * @name: name of the sub-device. Please notice that the name must be
+ * unique.
+ * @function: media entity function defined by MEDIA_ENT_F_* macros
+ * @num_pads: number of pads to initialize
+ * @pads_flag: flags to use in each pad
+ * @sd_int_ops: pointer to &struct v4l2_subdev_internal_ops
+ * @sd_ops: pointer to &struct v4l2_subdev_ops.
+ * @handler: func pointer of the irq handler
+ * @thread_fn: func pointer of the threaded irq handler
+ *
+ * Helper function initialize and register the struct dcmipp_ent_device and
+ * struct v4l2_subdev which represents a subdev node in the topology
+ */
+int dcmipp_ent_sd_register(struct dcmipp_ent_device *ved,
+ struct v4l2_subdev *sd,
+ struct v4l2_device *v4l2_dev,
+ const char *const name,
+ u32 function,
+ u16 num_pads,
+ const unsigned long *pads_flag,
+ const struct v4l2_subdev_internal_ops *sd_int_ops,
+ const struct v4l2_subdev_ops *sd_ops,
+ irq_handler_t handler,
+ irq_handler_t thread_fn);
+
+/**
+ * dcmipp_ent_sd_unregister - cleanup and unregister a subdev node
+ *
+ * @ved: the dcmipp_ent_device struct to be cleaned up
+ * @sd: the v4l2_subdev struct to be unregistered
+ *
+ * Helper function cleanup and unregister the struct dcmipp_ent_device and
+ * struct v4l2_subdev which represents a subdev node in the topology
+ */
+void dcmipp_ent_sd_unregister(struct dcmipp_ent_device *ved,
+ struct v4l2_subdev *sd);
+
+#define reg_write(device, reg, val) \
+ (__reg_write((device)->dev, (device)->regs, (reg), (val)))
+#define reg_read(device, reg) \
+ (__reg_read((device)->dev, (device)->regs, (reg)))
+#define reg_set(device, reg, mask) \
+ (__reg_set((device)->dev, (device)->regs, (reg), (mask)))
+#define reg_clear(device, reg, mask) \
+ (__reg_clear((device)->dev, (device)->regs, (reg), (mask)))
+
+static inline u32 __reg_read(struct device *dev, void __iomem *base, u32 reg)
+{
+ u32 val = readl_relaxed(base + reg);
+
+ dev_dbg(dev, "RD 0x%x %#10.8x\n", reg, val);
+ return val;
+}
+
+static inline void __reg_write(struct device *dev, void __iomem *base, u32 reg,
+ u32 val)
+{
+ dev_dbg(dev, "WR 0x%x %#10.8x\n", reg, val);
+ writel_relaxed(val, base + reg);
+}
+
+static inline void __reg_set(struct device *dev, void __iomem *base, u32 reg,
+ u32 mask)
+{
+ dev_dbg(dev, "SET 0x%x %#10.8x\n", reg, mask);
+ __reg_write(dev, base, reg, readl_relaxed(base + reg) | mask);
+}
+
+static inline void __reg_clear(struct device *dev, void __iomem *base, u32 reg,
+ u32 mask)
+{
+ dev_dbg(dev, "CLR 0x%x %#10.8x\n", reg, mask);
+ __reg_write(dev, base, reg, readl_relaxed(base + reg) & ~mask);
+}
+
+/* DCMIPP subdev init / release entry points */
+struct dcmipp_ent_device *dcmipp_par_ent_init(struct device *dev,
+ const char *entity_name,
+ struct v4l2_device *v4l2_dev,
+ void __iomem *regs);
+void dcmipp_par_ent_release(struct dcmipp_ent_device *ved);
+struct dcmipp_ent_device *
+dcmipp_byteproc_ent_init(struct device *dev, const char *entity_name,
+ struct v4l2_device *v4l2_dev, void __iomem *regs);
+void dcmipp_byteproc_ent_release(struct dcmipp_ent_device *ved);
+struct dcmipp_ent_device *dcmipp_bytecap_ent_init(struct device *dev,
+ const char *entity_name,
+ struct v4l2_device *v4l2_dev,
+ void __iomem *regs);
+void dcmipp_bytecap_ent_release(struct dcmipp_ent_device *ved);
+
+#endif