218 lines · c
1/* SPDX-License-Identifier: GPL-2.0-or-later */2/*3 * Driver for STM32 Digital Camera Memory Interface Pixel Processor4 *5 * Copyright (C) STMicroelectronics SA 20236 * 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 409623#define DCMIPP_FRAME_MAX_HEIGHT 216024#define DCMIPP_FRAME_MIN_WIDTH 1625#define DCMIPP_FRAME_MIN_HEIGHT 1626 27#define DCMIPP_FMT_WIDTH_DEFAULT 64028#define DCMIPP_FMT_HEIGHT_DEFAULT 48029 30#define DCMIPP_COLORSPACE_DEFAULT V4L2_COLORSPACE_REC70931#define DCMIPP_YCBCR_ENC_DEFAULT V4L2_YCBCR_ENC_DEFAULT32#define DCMIPP_QUANTIZATION_DEFAULT V4L2_QUANTIZATION_DEFAULT33#define DCMIPP_XFER_FUNC_DEFAULT V4L2_XFER_FUNC_DEFAULT34 35/**36 * dcmipp_colorimetry_clamp() - Adjust colorimetry parameters37 *38 * @fmt: the pointer to struct v4l2_pix_format or39 * struct v4l2_mbus_framefmt40 *41 * Entities must check if colorimetry given by the userspace is valid, if not42 * then set them as DEFAULT43 */44#define dcmipp_colorimetry_clamp(fmt) \45do { \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 topology63 *64 * @ent: the pointer to struct media_entity for the node65 * @pads: the list of pads of the node66 * @bus: struct v4l2_mbus_config_parallel describing input bus67 * @bus_type: type of input bus (parallel or BT656)68 * @handler: irq handler dedicated to the subdev69 * @handler_ret: value returned by the irq handler70 * @thread_fn: threaded irq handler71 *72 * The DCMIPP provides a single IRQ line and a IRQ status registers for all73 * subdevs, hence once the main irq handler (registered at probe time) is74 * called, it will chain calls to the irq handler of each the subdevs of the75 * 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 or79 * video_device struct where both contains a struct media_entity.80 * Those structures should embedded the dcmipp_ent_device struct through81 * v4l2_set_subdevdata() and video_set_drvdata() respectivaly, allowing the82 * dcmipp_ent_device struct to be retrieved from the corresponding struct83 * media_entity84 */85struct 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 pads99 *100 * @num_pads: number of pads to initialize101 * @pads_flags: flags to use in each pad102 *103 * Helper functions to allocate/initialize pads104 */105struct media_pad *dcmipp_pads_init(u16 num_pads,106 const unsigned long *pads_flags);107 108/**109 * dcmipp_pads_cleanup - free pads110 *111 * @pads: pointer to the pads112 *113 * Helper function to free the pads initialized with dcmipp_pads_init114 */115static 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 node122 *123 * @ved: the dcmipp_ent_device struct to be initialize124 * @sd: the v4l2_subdev struct to be initialize and registered125 * @v4l2_dev: the v4l2 device to register the v4l2_subdev126 * @name: name of the sub-device. Please notice that the name must be127 * unique.128 * @function: media entity function defined by MEDIA_ENT_F_* macros129 * @num_pads: number of pads to initialize130 * @pads_flag: flags to use in each pad131 * @sd_int_ops: pointer to &struct v4l2_subdev_internal_ops132 * @sd_ops: pointer to &struct v4l2_subdev_ops.133 * @handler: func pointer of the irq handler134 * @thread_fn: func pointer of the threaded irq handler135 *136 * Helper function initialize and register the struct dcmipp_ent_device and137 * struct v4l2_subdev which represents a subdev node in the topology138 */139int 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 node153 *154 * @ved: the dcmipp_ent_device struct to be cleaned up155 * @sd: the v4l2_subdev struct to be unregistered156 *157 * Helper function cleanup and unregister the struct dcmipp_ent_device and158 * struct v4l2_subdev which represents a subdev node in the topology159 */160void 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 172static 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 180static 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 187static 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 194static 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 */202struct 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);206void dcmipp_par_ent_release(struct dcmipp_ent_device *ved);207struct dcmipp_ent_device *208dcmipp_byteproc_ent_init(struct device *dev, const char *entity_name,209 struct v4l2_device *v4l2_dev, void __iomem *regs);210void dcmipp_byteproc_ent_release(struct dcmipp_ent_device *ved);211struct 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);215void dcmipp_bytecap_ent_release(struct dcmipp_ent_device *ved);216 217#endif218