#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
#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 {
struct media_entity *ent;
struct media_pad *pads;
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;
};
struct media_pad *dcmipp_pads_init(u16 num_pads,
const unsigned long *pads_flags);
static inline void dcmipp_pads_cleanup(struct media_pad *pads)
{
kfree(pads);
}
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);
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);
}
struct dcmipp_ent_device *dcmipp_inp_ent_init(struct device *dev,
const char *entity_name,
struct v4l2_device *v4l2_dev,
void __iomem *regs);
void dcmipp_inp_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