| /* |
| * V4L2 Media Controller Driver for Freescale i.MX5/6 SOC |
| * |
| * Copyright (c) 2016 Mentor Graphics Inc. |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License as published by |
| * the Free Software Foundation; either version 2 of the License, or |
| * (at your option) any later version. |
| */ |
| #ifndef _IMX_MEDIA_H |
| #define _IMX_MEDIA_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> |
| |
| /* |
| * This is somewhat arbitrary, but we need at least: |
| * - 4 video devices per IPU |
| * - 3 IC subdevs per IPU |
| * - 1 VDIC subdev per IPU |
| * - 2 CSI subdevs per IPU |
| * - 1 mipi-csi2 receiver subdev |
| * - 2 video-mux subdevs |
| * - 2 camera sensor subdevs per IPU (1 parallel, 1 mipi-csi2) |
| * |
| */ |
| /* max video devices */ |
| #define IMX_MEDIA_MAX_VDEVS 8 |
| /* max subdevices */ |
| #define IMX_MEDIA_MAX_SUBDEVS 32 |
| /* max pads per subdev */ |
| #define IMX_MEDIA_MAX_PADS 16 |
| /* max links per pad */ |
| #define IMX_MEDIA_MAX_LINKS 8 |
| |
| /* |
| * Pad definitions for the subdevs with multiple source or |
| * sink pads |
| */ |
| |
| /* ipu_csi */ |
| enum { |
| CSI_SINK_PAD = 0, |
| CSI_SRC_PAD_DIRECT, |
| CSI_SRC_PAD_IDMAC, |
| CSI_NUM_PADS, |
| }; |
| |
| #define CSI_NUM_SINK_PADS 1 |
| #define CSI_NUM_SRC_PADS 2 |
| |
| /* ipu_vdic */ |
| enum { |
| VDIC_SINK_PAD_DIRECT = 0, |
| VDIC_SINK_PAD_IDMAC, |
| VDIC_SRC_PAD_DIRECT, |
| VDIC_NUM_PADS, |
| }; |
| |
| #define VDIC_NUM_SINK_PADS 2 |
| #define VDIC_NUM_SRC_PADS 1 |
| |
| /* ipu_ic_prp */ |
| enum { |
| PRP_SINK_PAD = 0, |
| PRP_SRC_PAD_PRPENC, |
| PRP_SRC_PAD_PRPVF, |
| PRP_NUM_PADS, |
| }; |
| |
| #define PRP_NUM_SINK_PADS 1 |
| #define PRP_NUM_SRC_PADS 2 |
| |
| /* ipu_ic_prpencvf */ |
| enum { |
| PRPENCVF_SINK_PAD = 0, |
| PRPENCVF_SRC_PAD, |
| PRPENCVF_NUM_PADS, |
| }; |
| |
| #define PRPENCVF_NUM_SINK_PADS 1 |
| #define PRPENCVF_NUM_SRC_PADS 1 |
| |
| /* How long to wait for EOF interrupts in the buffer-capture subdevs */ |
| #define IMX_MEDIA_EOF_TIMEOUT 1000 |
| |
| struct imx_media_pixfmt { |
| u32 fourcc; |
| u32 codes[4]; |
| int bpp; /* total bpp */ |
| enum ipu_color_space cs; |
| bool planar; /* is a planar format */ |
| bool bayer; /* is a raw bayer format */ |
| bool ipufmt; /* is one of the IPU internal formats */ |
| }; |
| |
| struct imx_media_buffer { |
| struct vb2_v4l2_buffer vbuf; /* v4l buffer must be first */ |
| struct list_head list; |
| }; |
| |
| struct imx_media_video_dev { |
| struct video_device *vfd; |
| |
| /* the user format */ |
| struct v4l2_format fmt; |
| const struct imx_media_pixfmt *cc; |
| }; |
| |
| 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); |
| } |
| |
| struct imx_media_link { |
| struct device_node *remote_sd_node; |
| char remote_devname[32]; |
| int local_pad; |
| int remote_pad; |
| }; |
| |
| struct imx_media_pad { |
| struct media_pad pad; |
| struct imx_media_link link[IMX_MEDIA_MAX_LINKS]; |
| bool devnode; /* does this pad link to a device node */ |
| int num_links; |
| |
| /* |
| * list of video devices that can be reached from this pad, |
| * list is only valid for source pads. |
| */ |
| struct imx_media_video_dev *vdev[IMX_MEDIA_MAX_VDEVS]; |
| int num_vdevs; |
| }; |
| |
| struct imx_media_internal_sd_platformdata { |
| char sd_name[V4L2_SUBDEV_NAME_SIZE]; |
| u32 grp_id; |
| int ipu_id; |
| }; |
| |
| struct imx_media_subdev { |
| struct v4l2_async_subdev asd; |
| struct v4l2_subdev *sd; /* set when bound */ |
| |
| struct imx_media_pad pad[IMX_MEDIA_MAX_PADS]; |
| int num_sink_pads; |
| int num_src_pads; |
| |
| /* the platform device if this is an internal subdev */ |
| struct platform_device *pdev; |
| /* the devname is needed for async devname match */ |
| char devname[32]; |
| |
| /* if this is a sensor */ |
| struct v4l2_fwnode_endpoint sensor_ep; |
| }; |
| |
| struct imx_media_dev { |
| struct media_device md; |
| struct v4l2_device v4l2_dev; |
| |
| /* the pipeline object */ |
| struct media_pipeline pipe; |
| |
| struct mutex mutex; /* protect elements below */ |
| |
| /* master subdevice list */ |
| struct imx_media_subdev subdev[IMX_MEDIA_MAX_SUBDEVS]; |
| int num_subdevs; |
| |
| /* master video device list */ |
| struct imx_media_video_dev *vdev[IMX_MEDIA_MAX_VDEVS]; |
| int num_vdevs; |
| |
| /* IPUs this media driver control, valid after subdevs bound */ |
| struct ipu_soc *ipu[2]; |
| |
| /* for async subdev registration */ |
| struct v4l2_async_subdev *async_ptrs[IMX_MEDIA_MAX_SUBDEVS]; |
| struct v4l2_async_notifier subdev_notifier; |
| }; |
| |
| enum codespace_sel { |
| CS_SEL_YUV = 0, |
| CS_SEL_RGB, |
| CS_SEL_ANY, |
| }; |
| |
| const struct imx_media_pixfmt * |
| imx_media_find_format(u32 fourcc, enum codespace_sel cs_sel, bool allow_bayer); |
| int imx_media_enum_format(u32 *fourcc, u32 index, enum codespace_sel cs_sel); |
| const struct imx_media_pixfmt * |
| imx_media_find_mbus_format(u32 code, enum codespace_sel cs_sel, |
| bool allow_bayer); |
| int imx_media_enum_mbus_format(u32 *code, u32 index, enum codespace_sel cs_sel, |
| bool allow_bayer); |
| const struct imx_media_pixfmt * |
| imx_media_find_ipu_format(u32 code, enum codespace_sel cs_sel); |
| int imx_media_enum_ipu_format(u32 *code, u32 index, enum codespace_sel cs_sel); |
| |
| 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); |
| void imx_media_fill_default_mbus_fields(struct v4l2_mbus_framefmt *tryfmt, |
| struct v4l2_mbus_framefmt *fmt, |
| bool ic_route); |
| int imx_media_mbus_fmt_to_pix_fmt(struct v4l2_pix_format *pix, |
| struct v4l2_mbus_framefmt *mbus, |
| const struct imx_media_pixfmt *cc); |
| int imx_media_mbus_fmt_to_ipu_image(struct ipu_image *image, |
| struct v4l2_mbus_framefmt *mbus); |
| int imx_media_ipu_image_to_mbus_fmt(struct v4l2_mbus_framefmt *mbus, |
| struct ipu_image *image); |
| |
| struct imx_media_subdev * |
| imx_media_find_async_subdev(struct imx_media_dev *imxmd, |
| struct device_node *np, |
| const char *devname); |
| struct imx_media_subdev * |
| imx_media_add_async_subdev(struct imx_media_dev *imxmd, |
| struct device_node *np, |
| struct platform_device *pdev); |
| int imx_media_add_pad_link(struct imx_media_dev *imxmd, |
| struct imx_media_pad *pad, |
| struct device_node *remote_node, |
| const char *remote_devname, |
| int local_pad, int remote_pad); |
| |
| void imx_media_grp_id_to_sd_name(char *sd_name, int sz, |
| u32 grp_id, int ipu_id); |
| |
| int imx_media_add_internal_subdevs(struct imx_media_dev *imxmd, |
| struct imx_media_subdev *csi[4]); |
| void imx_media_remove_internal_subdevs(struct imx_media_dev *imxmd); |
| |
| struct imx_media_subdev * |
| imx_media_find_subdev_by_sd(struct imx_media_dev *imxmd, |
| struct v4l2_subdev *sd); |
| struct imx_media_subdev * |
| imx_media_find_subdev_by_id(struct imx_media_dev *imxmd, |
| u32 grp_id); |
| int imx_media_add_video_device(struct imx_media_dev *imxmd, |
| struct imx_media_video_dev *vdev); |
| int imx_media_find_mipi_csi2_channel(struct imx_media_dev *imxmd, |
| struct media_entity *start_entity); |
| struct imx_media_subdev * |
| imx_media_find_upstream_subdev(struct imx_media_dev *imxmd, |
| struct media_entity *start_entity, |
| u32 grp_id); |
| struct imx_media_subdev * |
| __imx_media_find_sensor(struct imx_media_dev *imxmd, |
| struct media_entity *start_entity); |
| struct imx_media_subdev * |
| imx_media_find_sensor(struct imx_media_dev *imxmd, |
| struct media_entity *start_entity); |
| |
| struct imx_media_dma_buf { |
| void *virt; |
| dma_addr_t phys; |
| unsigned long len; |
| }; |
| |
| void imx_media_free_dma_buf(struct imx_media_dev *imxmd, |
| struct imx_media_dma_buf *buf); |
| int imx_media_alloc_dma_buf(struct imx_media_dev *imxmd, |
| 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); |
| |
| /* imx-media-fim.c */ |
| struct imx_media_fim; |
| void imx_media_fim_eof_monitor(struct imx_media_fim *fim, struct timespec *ts); |
| int 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); |
| |
| /* imx-media-of.c */ |
| struct imx_media_subdev * |
| imx_media_of_find_subdev(struct imx_media_dev *imxmd, |
| struct device_node *np, |
| const char *name); |
| int imx_media_of_parse(struct imx_media_dev *dev, |
| struct imx_media_subdev *(*csi)[4], |
| struct device_node *np); |
| |
| /* imx-media-capture.c */ |
| struct imx_media_video_dev * |
| imx_media_capture_device_init(struct v4l2_subdev *src_sd, int pad); |
| void imx_media_capture_device_remove(struct imx_media_video_dev *vdev); |
| int imx_media_capture_device_register(struct imx_media_video_dev *vdev); |
| 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_set_format(struct imx_media_video_dev *vdev, |
| struct v4l2_pix_format *pix); |
| void imx_media_capture_device_error(struct imx_media_video_dev *vdev); |
| |
| /* subdev group ids */ |
| #define IMX_MEDIA_GRP_ID_SENSOR (1 << 8) |
| #define IMX_MEDIA_GRP_ID_VIDMUX (1 << 9) |
| #define IMX_MEDIA_GRP_ID_CSI2 (1 << 10) |
| #define IMX_MEDIA_GRP_ID_CSI_BIT 11 |
| #define IMX_MEDIA_GRP_ID_CSI (0x3 << IMX_MEDIA_GRP_ID_CSI_BIT) |
| #define IMX_MEDIA_GRP_ID_CSI0 (1 << IMX_MEDIA_GRP_ID_CSI_BIT) |
| #define IMX_MEDIA_GRP_ID_CSI1 (2 << IMX_MEDIA_GRP_ID_CSI_BIT) |
| #define IMX_MEDIA_GRP_ID_VDIC (1 << 13) |
| #define IMX_MEDIA_GRP_ID_IC_PRP (1 << 14) |
| #define IMX_MEDIA_GRP_ID_IC_PRPENC (1 << 15) |
| #define IMX_MEDIA_GRP_ID_IC_PRPVF (1 << 16) |
| |
| #endif |