1 /* SPDX-License-Identifier: GPL-2.0-or-later */
3 * Driver for STM32 Digital Camera Memory Interface Pixel Processor
5 * Copyright (C) STMicroelectronics SA 2023
8 * for STMicroelectronics.
11 #ifndef _DCMIPP_COMMON_H_
12 #define _DCMIPP_COMMON_H_
14 #include <linux/interrupt.h>
15 #include <linux/slab.h>
16 #include <media/media-device.h>
17 #include <media/v4l2-device.h>
18 #include <media/v4l2-fwnode.h>
20 #define DCMIPP_PDEV_NAME "dcmipp"
22 #define DCMIPP_FRAME_MAX_WIDTH 4096
23 #define DCMIPP_FRAME_MAX_HEIGHT 2160
24 #define DCMIPP_FRAME_MIN_WIDTH 16
25 #define DCMIPP_FRAME_MIN_HEIGHT 16
27 #define DCMIPP_FMT_WIDTH_DEFAULT 640
28 #define DCMIPP_FMT_HEIGHT_DEFAULT 480
30 #define DCMIPP_COLORSPACE_DEFAULT V4L2_COLORSPACE_REC709
31 #define DCMIPP_YCBCR_ENC_DEFAULT V4L2_YCBCR_ENC_DEFAULT
32 #define DCMIPP_QUANTIZATION_DEFAULT V4L2_QUANTIZATION_DEFAULT
33 #define DCMIPP_XFER_FUNC_DEFAULT V4L2_XFER_FUNC_DEFAULT
36 * dcmipp_colorimetry_clamp() - Adjust colorimetry parameters
38 * @fmt: the pointer to struct v4l2_pix_format or
39 * struct v4l2_mbus_framefmt
41 * Entities must check if colorimetry given by the userspace is valid, if not
42 * then set them as DEFAULT
44 #define dcmipp_colorimetry_clamp(fmt) \
46 if ((fmt)->colorspace == V4L2_COLORSPACE_DEFAULT || \
47 (fmt)->colorspace > V4L2_COLORSPACE_DCI_P3) { \
48 (fmt)->colorspace = DCMIPP_COLORSPACE_DEFAULT; \
49 (fmt)->ycbcr_enc = DCMIPP_YCBCR_ENC_DEFAULT; \
50 (fmt)->quantization = DCMIPP_QUANTIZATION_DEFAULT; \
51 (fmt)->xfer_func = DCMIPP_XFER_FUNC_DEFAULT; \
53 if ((fmt)->ycbcr_enc > V4L2_YCBCR_ENC_SMPTE240M) \
54 (fmt)->ycbcr_enc = DCMIPP_YCBCR_ENC_DEFAULT; \
55 if ((fmt)->quantization > V4L2_QUANTIZATION_LIM_RANGE) \
56 (fmt)->quantization = DCMIPP_QUANTIZATION_DEFAULT; \
57 if ((fmt)->xfer_func > V4L2_XFER_FUNC_SMPTE2084) \
58 (fmt)->xfer_func = DCMIPP_XFER_FUNC_DEFAULT; \
62 * struct dcmipp_ent_device - core struct that represents a node in the topology
64 * @ent: the pointer to struct media_entity for the node
65 * @pads: the list of pads of the node
66 * @bus: struct v4l2_mbus_config_parallel describing input bus
67 * @bus_type: type of input bus (parallel or BT656)
68 * @handler: irq handler dedicated to the subdev
69 * @handler_ret: value returned by the irq handler
70 * @thread_fn: threaded irq handler
72 * The DCMIPP provides a single IRQ line and a IRQ status registers for all
73 * subdevs, hence once the main irq handler (registered at probe time) is
74 * called, it will chain calls to the irq handler of each the subdevs of the
75 * pipelines, using the handler/handler_ret/thread_fn variables.
77 * Each node of the topology must create a dcmipp_ent_device struct.
78 * Depending on the node it will be of an instance of v4l2_subdev or
79 * video_device struct where both contains a struct media_entity.
80 * Those structures should embedded the dcmipp_ent_device struct through
81 * v4l2_set_subdevdata() and video_set_drvdata() respectivaly, allowing the
82 * dcmipp_ent_device struct to be retrieved from the corresponding struct
85 struct dcmipp_ent_device {
86 struct media_entity *ent;
87 struct media_pad *pads;
89 /* Parallel input device */
90 struct v4l2_mbus_config_parallel bus;
91 enum v4l2_mbus_type bus_type;
92 irq_handler_t handler;
93 irqreturn_t handler_ret;
94 irq_handler_t thread_fn;
98 * dcmipp_pads_init - initialize pads
100 * @num_pads: number of pads to initialize
101 * @pads_flags: flags to use in each pad
103 * Helper functions to allocate/initialize pads
105 struct media_pad *dcmipp_pads_init(u16 num_pads,
106 const unsigned long *pads_flags);
109 * dcmipp_pads_cleanup - free pads
111 * @pads: pointer to the pads
113 * Helper function to free the pads initialized with dcmipp_pads_init
115 static inline void dcmipp_pads_cleanup(struct media_pad *pads)
121 * dcmipp_ent_sd_register - initialize and register a subdev node
123 * @ved: the dcmipp_ent_device struct to be initialize
124 * @sd: the v4l2_subdev struct to be initialize and registered
125 * @v4l2_dev: the v4l2 device to register the v4l2_subdev
126 * @name: name of the sub-device. Please notice that the name must be
128 * @function: media entity function defined by MEDIA_ENT_F_* macros
129 * @num_pads: number of pads to initialize
130 * @pads_flag: flags to use in each pad
131 * @sd_int_ops: pointer to &struct v4l2_subdev_internal_ops
132 * @sd_ops: pointer to &struct v4l2_subdev_ops.
133 * @handler: func pointer of the irq handler
134 * @thread_fn: func pointer of the threaded irq handler
136 * Helper function initialize and register the struct dcmipp_ent_device and
137 * struct v4l2_subdev which represents a subdev node in the topology
139 int dcmipp_ent_sd_register(struct dcmipp_ent_device *ved,
140 struct v4l2_subdev *sd,
141 struct v4l2_device *v4l2_dev,
142 const char *const name,
145 const unsigned long *pads_flag,
146 const struct v4l2_subdev_internal_ops *sd_int_ops,
147 const struct v4l2_subdev_ops *sd_ops,
148 irq_handler_t handler,
149 irq_handler_t thread_fn);
152 * dcmipp_ent_sd_unregister - cleanup and unregister a subdev node
154 * @ved: the dcmipp_ent_device struct to be cleaned up
155 * @sd: the v4l2_subdev struct to be unregistered
157 * Helper function cleanup and unregister the struct dcmipp_ent_device and
158 * struct v4l2_subdev which represents a subdev node in the topology
160 void dcmipp_ent_sd_unregister(struct dcmipp_ent_device *ved,
161 struct v4l2_subdev *sd);
163 #define reg_write(device, reg, val) \
164 (__reg_write((device)->dev, (device)->regs, (reg), (val)))
165 #define reg_read(device, reg) \
166 (__reg_read((device)->dev, (device)->regs, (reg)))
167 #define reg_set(device, reg, mask) \
168 (__reg_set((device)->dev, (device)->regs, (reg), (mask)))
169 #define reg_clear(device, reg, mask) \
170 (__reg_clear((device)->dev, (device)->regs, (reg), (mask)))
172 static inline u32 __reg_read(struct device *dev, void __iomem *base, u32 reg)
174 u32 val = readl_relaxed(base + reg);
176 dev_dbg(dev, "RD 0x%x %#10.8x\n", reg, val);
180 static inline void __reg_write(struct device *dev, void __iomem *base, u32 reg,
183 dev_dbg(dev, "WR 0x%x %#10.8x\n", reg, val);
184 writel_relaxed(val, base + reg);
187 static inline void __reg_set(struct device *dev, void __iomem *base, u32 reg,
190 dev_dbg(dev, "SET 0x%x %#10.8x\n", reg, mask);
191 __reg_write(dev, base, reg, readl_relaxed(base + reg) | mask);
194 static inline void __reg_clear(struct device *dev, void __iomem *base, u32 reg,
197 dev_dbg(dev, "CLR 0x%x %#10.8x\n", reg, mask);
198 __reg_write(dev, base, reg, readl_relaxed(base + reg) & ~mask);
201 /* DCMIPP subdev init / release entry points */
202 struct dcmipp_ent_device *dcmipp_par_ent_init(struct device *dev,
203 const char *entity_name,
204 struct v4l2_device *v4l2_dev,
206 void dcmipp_par_ent_release(struct dcmipp_ent_device *ved);
207 struct dcmipp_ent_device *
208 dcmipp_byteproc_ent_init(struct device *dev, const char *entity_name,
209 struct v4l2_device *v4l2_dev, void __iomem *regs);
210 void dcmipp_byteproc_ent_release(struct dcmipp_ent_device *ved);
211 struct dcmipp_ent_device *dcmipp_bytecap_ent_init(struct device *dev,
212 const char *entity_name,
213 struct v4l2_device *v4l2_dev,
215 void dcmipp_bytecap_ent_release(struct dcmipp_ent_device *ved);