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