xref: /linux/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-common.h (revision be239684b18e1cdcafcf8c7face4a2f562c745ad)
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 /*
3  * Driver for STM32 Digital Camera Memory Interface Pixel Processor
4  *
5  * Copyright (C) STMicroelectronics SA 2023
6  * Authors: Hugues Fruchet <hugues.fruchet@foss.st.com>
7  *          Alain Volmat <alain.volmat@foss.st.com>
8  *          for STMicroelectronics.
9  */
10 
11 #ifndef _DCMIPP_COMMON_H_
12 #define _DCMIPP_COMMON_H_
13 
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>
19 
20 #define DCMIPP_PDEV_NAME "dcmipp"
21 
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
26 
27 #define DCMIPP_FMT_WIDTH_DEFAULT  640
28 #define DCMIPP_FMT_HEIGHT_DEFAULT 480
29 
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
34 
35 /**
36  * dcmipp_colorimetry_clamp() - Adjust colorimetry parameters
37  *
38  * @fmt:		the pointer to struct v4l2_pix_format or
39  *			struct v4l2_mbus_framefmt
40  *
41  * Entities must check if colorimetry given by the userspace is valid, if not
42  * then set them as DEFAULT
43  */
44 #define dcmipp_colorimetry_clamp(fmt)					\
45 do {									\
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;		\
52 	}								\
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;		\
59 } while (0)
60 
61 /**
62  * struct dcmipp_ent_device - core struct that represents a node in the topology
63  *
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
71  *
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.
76  *
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
83  * media_entity
84  */
85 struct dcmipp_ent_device {
86 	struct media_entity *ent;
87 	struct media_pad *pads;
88 
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;
95 };
96 
97 /**
98  * dcmipp_pads_init - initialize pads
99  *
100  * @num_pads:	number of pads to initialize
101  * @pads_flags:	flags to use in each pad
102  *
103  * Helper functions to allocate/initialize pads
104  */
105 struct media_pad *dcmipp_pads_init(u16 num_pads,
106 				   const unsigned long *pads_flags);
107 
108 /**
109  * dcmipp_pads_cleanup - free pads
110  *
111  * @pads: pointer to the pads
112  *
113  * Helper function to free the pads initialized with dcmipp_pads_init
114  */
115 static inline void dcmipp_pads_cleanup(struct media_pad *pads)
116 {
117 	kfree(pads);
118 }
119 
120 /**
121  * dcmipp_ent_sd_register - initialize and register a subdev node
122  *
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
127  *		unique.
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
135  *
136  * Helper function initialize and register the struct dcmipp_ent_device and
137  * struct v4l2_subdev which represents a subdev node in the topology
138  */
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,
143 			   u32 function,
144 			   u16 num_pads,
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);
150 
151 /**
152  * dcmipp_ent_sd_unregister - cleanup and unregister a subdev node
153  *
154  * @ved:	the dcmipp_ent_device struct to be cleaned up
155  * @sd:		the v4l2_subdev struct to be unregistered
156  *
157  * Helper function cleanup and unregister the struct dcmipp_ent_device and
158  * struct v4l2_subdev which represents a subdev node in the topology
159  */
160 void dcmipp_ent_sd_unregister(struct dcmipp_ent_device *ved,
161 			      struct v4l2_subdev *sd);
162 
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)))
171 
172 static inline u32 __reg_read(struct device *dev, void __iomem *base, u32 reg)
173 {
174 	u32 val = readl_relaxed(base + reg);
175 
176 	dev_dbg(dev, "RD 0x%x %#10.8x\n", reg, val);
177 	return val;
178 }
179 
180 static inline void __reg_write(struct device *dev, void __iomem *base, u32 reg,
181 			       u32 val)
182 {
183 	dev_dbg(dev, "WR 0x%x %#10.8x\n", reg, val);
184 	writel_relaxed(val, base + reg);
185 }
186 
187 static inline void __reg_set(struct device *dev, void __iomem *base, u32 reg,
188 			     u32 mask)
189 {
190 	dev_dbg(dev, "SET 0x%x %#10.8x\n", reg, mask);
191 	__reg_write(dev, base, reg, readl_relaxed(base + reg) | mask);
192 }
193 
194 static inline void __reg_clear(struct device *dev, void __iomem *base, u32 reg,
195 			       u32 mask)
196 {
197 	dev_dbg(dev, "CLR 0x%x %#10.8x\n", reg, mask);
198 	__reg_write(dev, base, reg, readl_relaxed(base + reg) & ~mask);
199 }
200 
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,
205 					      void __iomem *regs);
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,
214 						  void __iomem *regs);
215 void dcmipp_bytecap_ent_release(struct dcmipp_ent_device *ved);
216 
217 #endif
218