1/* SPDX-License-Identifier: GPL-2.0+ */
2/*
3 * V4L2 Media Controller Driver for Freescale i.MX5/6 SOC
4 *
5 * Copyright (c) 2016 Mentor Graphics Inc.
6 */
7#ifndef _IMX_MEDIA_H
8#define _IMX_MEDIA_H
9
10#include <linux/platform_device.h>
11#include <media/v4l2-ctrls.h>
12#include <media/v4l2-device.h>
13#include <media/v4l2-fwnode.h>
14#include <media/v4l2-subdev.h>
15#include <media/videobuf2-dma-contig.h>
16#include <video/imx-ipu-v3.h>
17
18#define IMX_MEDIA_DEF_PIX_WIDTH		640
19#define IMX_MEDIA_DEF_PIX_HEIGHT	480
20
21/*
22 * Enumeration of the IPU internal sub-devices
23 */
24enum {
25	IPU_CSI0 = 0,
26	IPU_CSI1,
27	IPU_VDIC,
28	IPU_IC_PRP,
29	IPU_IC_PRPENC,
30	IPU_IC_PRPVF,
31	NUM_IPU_SUBDEVS,
32};
33
34/*
35 * Pad definitions for the subdevs with multiple source or
36 * sink pads
37 */
38
39/* ipu_csi */
40enum {
41	CSI_SINK_PAD = 0,
42	CSI_SRC_PAD_DIRECT,
43	CSI_SRC_PAD_IDMAC,
44	CSI_NUM_PADS,
45};
46
47/* ipu_vdic */
48enum {
49	VDIC_SINK_PAD_DIRECT = 0,
50	VDIC_SINK_PAD_IDMAC,
51	VDIC_SRC_PAD_DIRECT,
52	VDIC_NUM_PADS,
53};
54
55/* ipu_ic_prp */
56enum {
57	PRP_SINK_PAD = 0,
58	PRP_SRC_PAD_PRPENC,
59	PRP_SRC_PAD_PRPVF,
60	PRP_NUM_PADS,
61};
62
63/* ipu_ic_prpencvf */
64enum {
65	PRPENCVF_SINK_PAD = 0,
66	PRPENCVF_SRC_PAD,
67	PRPENCVF_NUM_PADS,
68};
69
70/* How long to wait for EOF interrupts in the buffer-capture subdevs */
71#define IMX_MEDIA_EOF_TIMEOUT       2000
72
73struct imx_media_pixfmt {
74	/* the in-memory FourCC pixel format */
75	u32     fourcc;
76	/*
77	 * the set of equivalent media bus codes for the fourcc.
78	 * NOTE! codes pointer is NULL for in-memory-only formats.
79	 */
80	const u32 *codes;
81	int     bpp;     /* total bpp */
82	/* cycles per pixel for generic (bayer) formats for the parallel bus */
83	int	cycles;
84	enum ipu_color_space cs;
85	bool    planar;  /* is a planar format */
86	bool    bayer;   /* is a raw bayer format */
87	bool    ipufmt;  /* is one of the IPU internal formats */
88};
89
90enum imx_pixfmt_sel {
91	PIXFMT_SEL_YUV   = BIT(0), /* select YUV formats */
92	PIXFMT_SEL_RGB   = BIT(1), /* select RGB formats */
93	PIXFMT_SEL_BAYER = BIT(2), /* select BAYER formats */
94	PIXFMT_SEL_IPU   = BIT(3), /* select IPU-internal formats */
95	PIXFMT_SEL_YUV_RGB = PIXFMT_SEL_YUV | PIXFMT_SEL_RGB,
96	PIXFMT_SEL_ANY = PIXFMT_SEL_YUV | PIXFMT_SEL_RGB | PIXFMT_SEL_BAYER,
97};
98
99struct imx_media_buffer {
100	struct vb2_v4l2_buffer vbuf; /* v4l buffer must be first */
101	struct list_head  list;
102};
103
104struct imx_media_video_dev {
105	struct video_device *vfd;
106
107	/* the user format */
108	struct v4l2_pix_format fmt;
109	/* the compose rectangle */
110	struct v4l2_rect compose;
111	const struct imx_media_pixfmt *cc;
112
113	/* links this vdev to master list */
114	struct list_head list;
115};
116
117static inline struct imx_media_buffer *to_imx_media_vb(struct vb2_buffer *vb)
118{
119	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
120
121	return container_of(vbuf, struct imx_media_buffer, vbuf);
122}
123
124/*
125 * to support control inheritance to video devices, this
126 * retrieves a pad's list_head of video devices that can
127 * be reached from the pad. Note that only the lists in
128 * source pads get populated, sink pads have empty lists.
129 */
130static inline struct list_head *
131to_pad_vdev_list(struct v4l2_subdev *sd, int pad_index)
132{
133	struct list_head *vdev_list = sd->host_priv;
134
135	return vdev_list ? &vdev_list[pad_index] : NULL;
136}
137
138/* an entry in a pad's video device list */
139struct imx_media_pad_vdev {
140	struct imx_media_video_dev *vdev;
141	struct list_head list;
142};
143
144struct imx_media_dev {
145	struct media_device md;
146	struct v4l2_device  v4l2_dev;
147
148	/* the pipeline object */
149	struct media_pipeline pipe;
150
151	struct mutex mutex; /* protect elements below */
152
153	/* master video device list */
154	struct list_head vdev_list;
155
156	/* IPUs this media driver control, valid after subdevs bound */
157	struct ipu_soc *ipu[2];
158
159	/* for async subdev registration */
160	struct v4l2_async_notifier notifier;
161
162	/* IC scaler/CSC mem2mem video device */
163	struct imx_media_video_dev *m2m_vdev;
164
165	/* the IPU internal subdev's registered synchronously */
166	struct v4l2_subdev *sync_sd[2][NUM_IPU_SUBDEVS];
167};
168
169/* imx-media-utils.c */
170const struct imx_media_pixfmt *
171imx_media_find_pixel_format(u32 fourcc, enum imx_pixfmt_sel sel);
172int imx_media_enum_pixel_formats(u32 *fourcc, u32 index,
173				 enum imx_pixfmt_sel sel, u32 code);
174const struct imx_media_pixfmt *
175imx_media_find_mbus_format(u32 code, enum imx_pixfmt_sel sel);
176int imx_media_enum_mbus_formats(u32 *code, u32 index,
177				enum imx_pixfmt_sel sel);
178
179static inline const struct imx_media_pixfmt *
180imx_media_find_ipu_format(u32 code, enum imx_pixfmt_sel fmt_sel)
181{
182	return imx_media_find_mbus_format(code, fmt_sel | PIXFMT_SEL_IPU);
183}
184
185static inline int imx_media_enum_ipu_formats(u32 *code, u32 index,
186					     enum imx_pixfmt_sel fmt_sel)
187{
188	return imx_media_enum_mbus_formats(code, index,
189					  fmt_sel | PIXFMT_SEL_IPU);
190}
191
192int imx_media_init_mbus_fmt(struct v4l2_mbus_framefmt *mbus,
193			    u32 width, u32 height, u32 code, u32 field,
194			    const struct imx_media_pixfmt **cc);
195int imx_media_init_state(struct v4l2_subdev *sd,
196			 struct v4l2_subdev_state *sd_state);
197void imx_media_try_colorimetry(struct v4l2_mbus_framefmt *tryfmt,
198			       bool ic_route);
199int imx_media_mbus_fmt_to_pix_fmt(struct v4l2_pix_format *pix,
200				  const struct v4l2_mbus_framefmt *mbus,
201				  const struct imx_media_pixfmt *cc);
202void imx_media_grp_id_to_sd_name(char *sd_name, int sz,
203				 u32 grp_id, int ipu_id);
204void imx_media_add_video_device(struct imx_media_dev *imxmd,
205				struct imx_media_video_dev *vdev);
206struct media_pad *
207imx_media_pipeline_pad(struct media_entity *start_entity, u32 grp_id,
208		       enum v4l2_buf_type buftype, bool upstream);
209struct v4l2_subdev *
210imx_media_pipeline_subdev(struct media_entity *start_entity, u32 grp_id,
211			  bool upstream);
212
213struct imx_media_dma_buf {
214	void          *virt;
215	dma_addr_t     phys;
216	unsigned long  len;
217};
218
219void imx_media_free_dma_buf(struct device *dev,
220			    struct imx_media_dma_buf *buf);
221int imx_media_alloc_dma_buf(struct device *dev,
222			    struct imx_media_dma_buf *buf,
223			    int size);
224
225int imx_media_pipeline_set_stream(struct imx_media_dev *imxmd,
226				  struct media_entity *entity,
227				  bool on);
228
229/* imx-media-dev-common.c */
230int imx_media_probe_complete(struct v4l2_async_notifier *notifier);
231struct imx_media_dev *imx_media_dev_init(struct device *dev,
232					 const struct media_device_ops *ops);
233int imx_media_dev_notifier_register(struct imx_media_dev *imxmd,
234			    const struct v4l2_async_notifier_operations *ops);
235
236/* imx-media-fim.c */
237struct imx_media_fim;
238void imx_media_fim_eof_monitor(struct imx_media_fim *fim, ktime_t timestamp);
239void imx_media_fim_set_stream(struct imx_media_fim *fim,
240			      const struct v4l2_fract *frame_interval,
241			      bool on);
242int imx_media_fim_add_controls(struct imx_media_fim *fim);
243struct imx_media_fim *imx_media_fim_init(struct v4l2_subdev *sd);
244void imx_media_fim_free(struct imx_media_fim *fim);
245
246/* imx-media-internal-sd.c */
247int imx_media_register_ipu_internal_subdevs(struct imx_media_dev *imxmd,
248					    struct v4l2_subdev *csi);
249void imx_media_unregister_ipu_internal_subdevs(struct imx_media_dev *imxmd);
250
251/* imx-media-of.c */
252int imx_media_add_of_subdevs(struct imx_media_dev *dev,
253			     struct device_node *np);
254
255/* imx-media-vdic.c */
256struct v4l2_subdev *imx_media_vdic_register(struct v4l2_device *v4l2_dev,
257					    struct device *ipu_dev,
258					    struct ipu_soc *ipu,
259					    u32 grp_id);
260int imx_media_vdic_unregister(struct v4l2_subdev *sd);
261
262/* imx-ic-common.c */
263struct v4l2_subdev *imx_media_ic_register(struct v4l2_device *v4l2_dev,
264					  struct device *ipu_dev,
265					  struct ipu_soc *ipu,
266					  u32 grp_id);
267int imx_media_ic_unregister(struct v4l2_subdev *sd);
268
269/* imx-media-capture.c */
270struct imx_media_video_dev *
271imx_media_capture_device_init(struct device *dev, struct v4l2_subdev *src_sd,
272			      int pad, bool legacy_api);
273void imx_media_capture_device_remove(struct imx_media_video_dev *vdev);
274int imx_media_capture_device_register(struct imx_media_video_dev *vdev,
275				      u32 link_flags);
276void imx_media_capture_device_unregister(struct imx_media_video_dev *vdev);
277struct imx_media_buffer *
278imx_media_capture_device_next_buf(struct imx_media_video_dev *vdev);
279void imx_media_capture_device_error(struct imx_media_video_dev *vdev);
280
281/* imx-media-csc-scaler.c */
282struct imx_media_video_dev *
283imx_media_csc_scaler_device_init(struct imx_media_dev *dev);
284int imx_media_csc_scaler_device_register(struct imx_media_video_dev *vdev);
285void imx_media_csc_scaler_device_unregister(struct imx_media_video_dev *vdev);
286
287/* subdev group ids */
288#define IMX_MEDIA_GRP_ID_CSI2          BIT(8)
289#define IMX_MEDIA_GRP_ID_IPU_CSI_BIT   10
290#define IMX_MEDIA_GRP_ID_IPU_CSI       (0x3 << IMX_MEDIA_GRP_ID_IPU_CSI_BIT)
291#define IMX_MEDIA_GRP_ID_IPU_CSI0      BIT(IMX_MEDIA_GRP_ID_IPU_CSI_BIT)
292#define IMX_MEDIA_GRP_ID_IPU_CSI1      (2 << IMX_MEDIA_GRP_ID_IPU_CSI_BIT)
293#define IMX_MEDIA_GRP_ID_IPU_VDIC      BIT(12)
294#define IMX_MEDIA_GRP_ID_IPU_IC_PRP    BIT(13)
295#define IMX_MEDIA_GRP_ID_IPU_IC_PRPENC BIT(14)
296#define IMX_MEDIA_GRP_ID_IPU_IC_PRPVF  BIT(15)
297#define IMX_MEDIA_GRP_ID_CSI_MUX       BIT(16)
298
299#endif
300