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 | */ |
24 | enum { |
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 */ |
40 | enum { |
41 | CSI_SINK_PAD = 0, |
42 | CSI_SRC_PAD_DIRECT, |
43 | CSI_SRC_PAD_IDMAC, |
44 | CSI_NUM_PADS, |
45 | }; |
46 | |
47 | /* ipu_vdic */ |
48 | enum { |
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 */ |
56 | enum { |
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 */ |
64 | enum { |
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 | |
73 | struct 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 | |
90 | enum 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 | |
99 | struct imx_media_buffer { |
100 | struct vb2_v4l2_buffer vbuf; /* v4l buffer must be first */ |
101 | struct list_head list; |
102 | }; |
103 | |
104 | struct 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 | |
117 | static 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 | */ |
130 | static inline struct list_head * |
131 | to_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 */ |
139 | struct imx_media_pad_vdev { |
140 | struct imx_media_video_dev *vdev; |
141 | struct list_head list; |
142 | }; |
143 | |
144 | struct 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 */ |
170 | const struct imx_media_pixfmt * |
171 | imx_media_find_pixel_format(u32 fourcc, enum imx_pixfmt_sel sel); |
172 | int imx_media_enum_pixel_formats(u32 *fourcc, u32 index, |
173 | enum imx_pixfmt_sel sel, u32 code); |
174 | const struct imx_media_pixfmt * |
175 | imx_media_find_mbus_format(u32 code, enum imx_pixfmt_sel sel); |
176 | int imx_media_enum_mbus_formats(u32 *code, u32 index, |
177 | enum imx_pixfmt_sel sel); |
178 | |
179 | static inline const struct imx_media_pixfmt * |
180 | imx_media_find_ipu_format(u32 code, enum imx_pixfmt_sel fmt_sel) |
181 | { |
182 | return imx_media_find_mbus_format(code, sel: fmt_sel | PIXFMT_SEL_IPU); |
183 | } |
184 | |
185 | static 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 | sel: fmt_sel | PIXFMT_SEL_IPU); |
190 | } |
191 | |
192 | int 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); |
195 | int imx_media_init_state(struct v4l2_subdev *sd, |
196 | struct v4l2_subdev_state *sd_state); |
197 | void imx_media_try_colorimetry(struct v4l2_mbus_framefmt *tryfmt, |
198 | bool ic_route); |
199 | int 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); |
202 | void imx_media_grp_id_to_sd_name(char *sd_name, int sz, |
203 | u32 grp_id, int ipu_id); |
204 | void imx_media_add_video_device(struct imx_media_dev *imxmd, |
205 | struct imx_media_video_dev *vdev); |
206 | struct media_pad * |
207 | imx_media_pipeline_pad(struct media_entity *start_entity, u32 grp_id, |
208 | enum v4l2_buf_type buftype, bool upstream); |
209 | struct v4l2_subdev * |
210 | imx_media_pipeline_subdev(struct media_entity *start_entity, u32 grp_id, |
211 | bool upstream); |
212 | |
213 | struct imx_media_dma_buf { |
214 | void *virt; |
215 | dma_addr_t phys; |
216 | unsigned long len; |
217 | }; |
218 | |
219 | void imx_media_free_dma_buf(struct device *dev, |
220 | struct imx_media_dma_buf *buf); |
221 | int imx_media_alloc_dma_buf(struct device *dev, |
222 | struct imx_media_dma_buf *buf, |
223 | int size); |
224 | |
225 | int 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 */ |
230 | int imx_media_probe_complete(struct v4l2_async_notifier *notifier); |
231 | struct imx_media_dev *imx_media_dev_init(struct device *dev, |
232 | const struct media_device_ops *ops); |
233 | int imx_media_dev_notifier_register(struct imx_media_dev *imxmd, |
234 | const struct v4l2_async_notifier_operations *ops); |
235 | |
236 | /* imx-media-fim.c */ |
237 | struct imx_media_fim; |
238 | void imx_media_fim_eof_monitor(struct imx_media_fim *fim, ktime_t timestamp); |
239 | void imx_media_fim_set_stream(struct imx_media_fim *fim, |
240 | const struct v4l2_fract *frame_interval, |
241 | bool on); |
242 | int imx_media_fim_add_controls(struct imx_media_fim *fim); |
243 | struct imx_media_fim *imx_media_fim_init(struct v4l2_subdev *sd); |
244 | void imx_media_fim_free(struct imx_media_fim *fim); |
245 | |
246 | /* imx-media-internal-sd.c */ |
247 | int imx_media_register_ipu_internal_subdevs(struct imx_media_dev *imxmd, |
248 | struct v4l2_subdev *csi); |
249 | void imx_media_unregister_ipu_internal_subdevs(struct imx_media_dev *imxmd); |
250 | |
251 | /* imx-media-of.c */ |
252 | int imx_media_add_of_subdevs(struct imx_media_dev *dev, |
253 | struct device_node *np); |
254 | |
255 | /* imx-media-vdic.c */ |
256 | struct 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); |
260 | int imx_media_vdic_unregister(struct v4l2_subdev *sd); |
261 | |
262 | /* imx-ic-common.c */ |
263 | struct 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); |
267 | int imx_media_ic_unregister(struct v4l2_subdev *sd); |
268 | |
269 | /* imx-media-capture.c */ |
270 | struct imx_media_video_dev * |
271 | imx_media_capture_device_init(struct device *dev, struct v4l2_subdev *src_sd, |
272 | int pad, bool legacy_api); |
273 | void imx_media_capture_device_remove(struct imx_media_video_dev *vdev); |
274 | int imx_media_capture_device_register(struct imx_media_video_dev *vdev, |
275 | u32 link_flags); |
276 | void imx_media_capture_device_unregister(struct imx_media_video_dev *vdev); |
277 | struct imx_media_buffer * |
278 | imx_media_capture_device_next_buf(struct imx_media_video_dev *vdev); |
279 | void imx_media_capture_device_error(struct imx_media_video_dev *vdev); |
280 | |
281 | /* imx-media-csc-scaler.c */ |
282 | struct imx_media_video_dev * |
283 | imx_media_csc_scaler_device_init(struct imx_media_dev *dev); |
284 | int imx_media_csc_scaler_device_register(struct imx_media_video_dev *vdev); |
285 | void 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 | |