#ifndef _IMX_MEDIA_H
#define _IMX_MEDIA_H
#include <linux/platform_device.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
#include <media/v4l2-fwnode.h>
#include <media/v4l2-subdev.h>
#include <media/videobuf2-dma-contig.h>
#include <video/imx-ipu-v3.h>
#define IMX_MEDIA_DEF_PIX_WIDTH 640
#define IMX_MEDIA_DEF_PIX_HEIGHT 480
enum {
IPU_CSI0 = 0,
IPU_CSI1,
IPU_VDIC,
IPU_IC_PRP,
IPU_IC_PRPENC,
IPU_IC_PRPVF,
NUM_IPU_SUBDEVS,
};
enum {
CSI_SINK_PAD = 0,
CSI_SRC_PAD_DIRECT,
CSI_SRC_PAD_IDMAC,
CSI_NUM_PADS,
};
enum {
VDIC_SINK_PAD_DIRECT = 0,
VDIC_SINK_PAD_IDMAC,
VDIC_SRC_PAD_DIRECT,
VDIC_NUM_PADS,
};
enum {
PRP_SINK_PAD = 0,
PRP_SRC_PAD_PRPENC,
PRP_SRC_PAD_PRPVF,
PRP_NUM_PADS,
};
enum {
PRPENCVF_SINK_PAD = 0,
PRPENCVF_SRC_PAD,
PRPENCVF_NUM_PADS,
};
#define IMX_MEDIA_EOF_TIMEOUT 2000
struct imx_media_pixfmt {
u32 fourcc;
const u32 *codes;
int bpp;
int cycles;
enum ipu_color_space cs;
bool planar;
bool bayer;
bool ipufmt;
};
enum imx_pixfmt_sel {
PIXFMT_SEL_YUV = BIT(0),
PIXFMT_SEL_RGB = BIT(1),
PIXFMT_SEL_BAYER = BIT(2),
PIXFMT_SEL_IPU = BIT(3),
PIXFMT_SEL_YUV_RGB = PIXFMT_SEL_YUV | PIXFMT_SEL_RGB,
PIXFMT_SEL_ANY = PIXFMT_SEL_YUV | PIXFMT_SEL_RGB | PIXFMT_SEL_BAYER,
};
struct imx_media_buffer {
struct vb2_v4l2_buffer vbuf;
struct list_head list;
};
struct imx_media_video_dev {
struct video_device *vfd;
struct v4l2_pix_format fmt;
struct v4l2_rect compose;
const struct imx_media_pixfmt *cc;
struct list_head list;
};
static inline struct imx_media_buffer *to_imx_media_vb(struct vb2_buffer *vb)
{
struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
return container_of(vbuf, struct imx_media_buffer, vbuf);
}
static inline struct list_head *
to_pad_vdev_list(struct v4l2_subdev *sd, int pad_index)
{
struct list_head *vdev_list = sd->host_priv;
return vdev_list ? &vdev_list[pad_index] : NULL;
}
struct imx_media_pad_vdev {
struct imx_media_video_dev *vdev;
struct list_head list;
};
struct imx_media_dev {
struct media_device md;
struct v4l2_device v4l2_dev;
struct media_pipeline pipe;
struct mutex mutex;
struct list_head vdev_list;
struct ipu_soc *ipu[2];
struct v4l2_async_notifier notifier;
struct imx_media_video_dev *m2m_vdev;
struct v4l2_subdev *sync_sd[2][NUM_IPU_SUBDEVS];
};
const struct imx_media_pixfmt *
imx_media_find_pixel_format(u32 fourcc, enum imx_pixfmt_sel sel);
int imx_media_enum_pixel_formats(u32 *fourcc, u32 index,
enum imx_pixfmt_sel sel, u32 code);
const struct imx_media_pixfmt *
imx_media_find_mbus_format(u32 code, enum imx_pixfmt_sel sel);
int imx_media_enum_mbus_formats(u32 *code, u32 index,
enum imx_pixfmt_sel sel);
static inline const struct imx_media_pixfmt *
imx_media_find_ipu_format(u32 code, enum imx_pixfmt_sel fmt_sel)
{
return imx_media_find_mbus_format(code, fmt_sel | PIXFMT_SEL_IPU);
}
static inline int imx_media_enum_ipu_formats(u32 *code, u32 index,
enum imx_pixfmt_sel fmt_sel)
{
return imx_media_enum_mbus_formats(code, index,
fmt_sel | PIXFMT_SEL_IPU);
}
int imx_media_init_mbus_fmt(struct v4l2_mbus_framefmt *mbus,
u32 width, u32 height, u32 code, u32 field,
const struct imx_media_pixfmt **cc);
int imx_media_init_cfg(struct v4l2_subdev *sd,
struct v4l2_subdev_state *sd_state);
void imx_media_try_colorimetry(struct v4l2_mbus_framefmt *tryfmt,
bool ic_route);
int imx_media_mbus_fmt_to_pix_fmt(struct v4l2_pix_format *pix,
const struct v4l2_mbus_framefmt *mbus,
const struct imx_media_pixfmt *cc);
void imx_media_grp_id_to_sd_name(char *sd_name, int sz,
u32 grp_id, int ipu_id);
void imx_media_add_video_device(struct imx_media_dev *imxmd,
struct imx_media_video_dev *vdev);
struct media_pad *
imx_media_pipeline_pad(struct media_entity *start_entity, u32 grp_id,
enum v4l2_buf_type buftype, bool upstream);
struct v4l2_subdev *
imx_media_pipeline_subdev(struct media_entity *start_entity, u32 grp_id,
bool upstream);
struct imx_media_dma_buf {
void *virt;
dma_addr_t phys;
unsigned long len;
};
void imx_media_free_dma_buf(struct device *dev,
struct imx_media_dma_buf *buf);
int imx_media_alloc_dma_buf(struct device *dev,
struct imx_media_dma_buf *buf,
int size);
int imx_media_pipeline_set_stream(struct imx_media_dev *imxmd,
struct media_entity *entity,
bool on);
int imx_media_probe_complete(struct v4l2_async_notifier *notifier);
struct imx_media_dev *imx_media_dev_init(struct device *dev,
const struct media_device_ops *ops);
int imx_media_dev_notifier_register(struct imx_media_dev *imxmd,
const struct v4l2_async_notifier_operations *ops);
struct imx_media_fim;
void imx_media_fim_eof_monitor(struct imx_media_fim *fim, ktime_t timestamp);
void imx_media_fim_set_stream(struct imx_media_fim *fim,
const struct v4l2_fract *frame_interval,
bool on);
int imx_media_fim_add_controls(struct imx_media_fim *fim);
struct imx_media_fim *imx_media_fim_init(struct v4l2_subdev *sd);
void imx_media_fim_free(struct imx_media_fim *fim);
int imx_media_register_ipu_internal_subdevs(struct imx_media_dev *imxmd,
struct v4l2_subdev *csi);
void imx_media_unregister_ipu_internal_subdevs(struct imx_media_dev *imxmd);
int imx_media_add_of_subdevs(struct imx_media_dev *dev,
struct device_node *np);
struct v4l2_subdev *imx_media_vdic_register(struct v4l2_device *v4l2_dev,
struct device *ipu_dev,
struct ipu_soc *ipu,
u32 grp_id);
int imx_media_vdic_unregister(struct v4l2_subdev *sd);
struct v4l2_subdev *imx_media_ic_register(struct v4l2_device *v4l2_dev,
struct device *ipu_dev,
struct ipu_soc *ipu,
u32 grp_id);
int imx_media_ic_unregister(struct v4l2_subdev *sd);
struct imx_media_video_dev *
imx_media_capture_device_init(struct device *dev, struct v4l2_subdev *src_sd,
int pad, bool legacy_api);
void imx_media_capture_device_remove(struct imx_media_video_dev *vdev);
int imx_media_capture_device_register(struct imx_media_video_dev *vdev,
u32 link_flags);
void imx_media_capture_device_unregister(struct imx_media_video_dev *vdev);
struct imx_media_buffer *
imx_media_capture_device_next_buf(struct imx_media_video_dev *vdev);
void imx_media_capture_device_error(struct imx_media_video_dev *vdev);
struct imx_media_video_dev *
imx_media_csc_scaler_device_init(struct imx_media_dev *dev);
int imx_media_csc_scaler_device_register(struct imx_media_video_dev *vdev);
void imx_media_csc_scaler_device_unregister(struct imx_media_video_dev *vdev);
#define IMX_MEDIA_GRP_ID_CSI2 BIT(8)
#define IMX_MEDIA_GRP_ID_IPU_CSI_BIT 10
#define IMX_MEDIA_GRP_ID_IPU_CSI (0x3 << IMX_MEDIA_GRP_ID_IPU_CSI_BIT)
#define IMX_MEDIA_GRP_ID_IPU_CSI0 BIT(IMX_MEDIA_GRP_ID_IPU_CSI_BIT)
#define IMX_MEDIA_GRP_ID_IPU_CSI1 (2 << IMX_MEDIA_GRP_ID_IPU_CSI_BIT)
#define IMX_MEDIA_GRP_ID_IPU_VDIC BIT(12)
#define IMX_MEDIA_GRP_ID_IPU_IC_PRP BIT(13)
#define IMX_MEDIA_GRP_ID_IPU_IC_PRPENC BIT(14)
#define IMX_MEDIA_GRP_ID_IPU_IC_PRPVF BIT(15)
#define IMX_MEDIA_GRP_ID_CSI_MUX BIT(16)
#endif