1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3 * V4L2 Capture ISI subdev for i.MX8QXP/QM platform
4 *
5 * ISI is a Image Sensor Interface of i.MX8QXP/QM platform, which
6 * used to process image from camera sensor to memory or DC
7 * Copyright 2019-2020 NXP
8 */
9
10 #ifndef __MXC_ISI_CORE_H__
11 #define __MXC_ISI_CORE_H__
12
13 #include <linux/list.h>
14 #include <linux/mutex.h>
15 #include <linux/spinlock.h>
16 #include <linux/types.h>
17 #include <linux/videodev2.h>
18
19 #include <media/media-device.h>
20 #include <media/media-entity.h>
21 #include <media/v4l2-async.h>
22 #include <media/v4l2-ctrls.h>
23 #include <media/v4l2-dev.h>
24 #include <media/v4l2-device.h>
25 #include <media/v4l2-subdev.h>
26 #include <media/videobuf2-core.h>
27 #include <media/videobuf2-v4l2.h>
28
29 struct clk_bulk_data;
30 struct dentry;
31 struct device;
32 struct media_intf_devnode;
33 struct regmap;
34 struct v4l2_m2m_dev;
35
36 /* Pipeline pads */
37 #define MXC_ISI_PIPE_PAD_SINK 0
38 #define MXC_ISI_PIPE_PAD_SOURCE 1
39 #define MXC_ISI_PIPE_PADS_NUM 2
40
41 #define MXC_ISI_MIN_WIDTH 1U
42 #define MXC_ISI_MIN_HEIGHT 1U
43 #define MXC_ISI_MAX_WIDTH_UNCHAINED 2048U
44 #define MXC_ISI_MAX_WIDTH_CHAINED 4096U
45 #define MXC_ISI_MAX_HEIGHT 8191U
46
47 #define MXC_ISI_DEF_WIDTH 1920U
48 #define MXC_ISI_DEF_HEIGHT 1080U
49 #define MXC_ISI_DEF_MBUS_CODE_SINK MEDIA_BUS_FMT_UYVY8_1X16
50 #define MXC_ISI_DEF_MBUS_CODE_SOURCE MEDIA_BUS_FMT_YUV8_1X24
51 #define MXC_ISI_DEF_PIXEL_FORMAT V4L2_PIX_FMT_YUYV
52 #define MXC_ISI_DEF_COLOR_SPACE V4L2_COLORSPACE_SRGB
53 #define MXC_ISI_DEF_YCBCR_ENC V4L2_YCBCR_ENC_601
54 #define MXC_ISI_DEF_QUANTIZATION V4L2_QUANTIZATION_LIM_RANGE
55 #define MXC_ISI_DEF_XFER_FUNC V4L2_XFER_FUNC_SRGB
56
57 #define MXC_ISI_DRIVER_NAME "mxc-isi"
58 #define MXC_ISI_CAPTURE "mxc-isi-cap"
59 #define MXC_ISI_M2M "mxc-isi-m2m"
60 #define MXC_MAX_PLANES 3
61
62 struct mxc_isi_dev;
63 struct mxc_isi_m2m_ctx;
64
65 enum mxc_isi_buf_id {
66 MXC_ISI_BUF1 = 0x0,
67 MXC_ISI_BUF2,
68 };
69
70 enum mxc_isi_encoding {
71 MXC_ISI_ENC_RAW,
72 MXC_ISI_ENC_RGB,
73 MXC_ISI_ENC_YUV,
74 };
75
76 enum mxc_isi_input_id {
77 /* Inputs from the crossbar switch range from 0 to 15 */
78 MXC_ISI_INPUT_MEM = 16,
79 };
80
81 enum mxc_isi_video_type {
82 MXC_ISI_VIDEO_CAP = BIT(0),
83 MXC_ISI_VIDEO_M2M_OUT = BIT(1),
84 MXC_ISI_VIDEO_M2M_CAP = BIT(2),
85 };
86
87 struct mxc_isi_format_info {
88 u32 mbus_code;
89 u32 fourcc;
90 enum mxc_isi_video_type type;
91 u32 isi_in_format;
92 u32 isi_out_format;
93 u8 mem_planes;
94 u8 color_planes;
95 u8 depth[MXC_MAX_PLANES];
96 u8 hsub;
97 u8 vsub;
98 enum mxc_isi_encoding encoding;
99 };
100
101 struct mxc_isi_bus_format_info {
102 u32 mbus_code;
103 u32 output;
104 u32 pads;
105 enum mxc_isi_encoding encoding;
106 };
107
108 struct mxc_isi_buffer {
109 struct vb2_v4l2_buffer v4l2_buf;
110 struct list_head list;
111 dma_addr_t dma_addrs[3];
112 enum mxc_isi_buf_id id;
113 bool discard;
114 };
115
116 struct mxc_isi_reg {
117 u32 offset;
118 u32 mask;
119 };
120
121 struct mxc_isi_ier_reg {
122 /* Overflow Y/U/V trigger enable*/
123 struct mxc_isi_reg oflw_y_buf_en;
124 struct mxc_isi_reg oflw_u_buf_en;
125 struct mxc_isi_reg oflw_v_buf_en;
126
127 /* Excess overflow Y/U/V trigger enable*/
128 struct mxc_isi_reg excs_oflw_y_buf_en;
129 struct mxc_isi_reg excs_oflw_u_buf_en;
130 struct mxc_isi_reg excs_oflw_v_buf_en;
131
132 /* Panic Y/U/V trigger enable*/
133 struct mxc_isi_reg panic_y_buf_en;
134 struct mxc_isi_reg panic_v_buf_en;
135 struct mxc_isi_reg panic_u_buf_en;
136 };
137
138 struct mxc_isi_panic_thd {
139 u32 mask;
140 u32 offset;
141 u32 threshold;
142 };
143
144 struct mxc_isi_set_thd {
145 struct mxc_isi_panic_thd panic_set_thd_y;
146 struct mxc_isi_panic_thd panic_set_thd_u;
147 struct mxc_isi_panic_thd panic_set_thd_v;
148 };
149
150 struct mxc_gasket_ops {
151 void (*enable)(struct mxc_isi_dev *isi,
152 const struct v4l2_mbus_frame_desc *fd,
153 const struct v4l2_mbus_framefmt *fmt,
154 const unsigned int port);
155 void (*disable)(struct mxc_isi_dev *isi, const unsigned int port);
156 };
157
158 enum model {
159 MXC_ISI_IMX8MN,
160 MXC_ISI_IMX8MP,
161 MXC_ISI_IMX8ULP,
162 MXC_ISI_IMX93,
163 };
164
165 struct mxc_isi_plat_data {
166 enum model model;
167 unsigned int num_ports;
168 unsigned int num_channels;
169 unsigned int reg_offset;
170 const struct mxc_isi_ier_reg *ier_reg;
171 const struct mxc_isi_set_thd *set_thd;
172 const struct mxc_gasket_ops *gasket_ops;
173 const struct clk_bulk_data *clks;
174 unsigned int num_clks;
175 bool buf_active_reverse;
176 bool has_36bit_dma;
177 };
178
179 struct mxc_isi_dma_buffer {
180 size_t size;
181 void *addr;
182 dma_addr_t dma;
183 };
184
185 struct mxc_isi_input {
186 unsigned int enable_count;
187 };
188
189 struct mxc_isi_crossbar {
190 struct mxc_isi_dev *isi;
191
192 unsigned int num_sinks;
193 unsigned int num_sources;
194 struct mxc_isi_input *inputs;
195
196 struct v4l2_subdev sd;
197 struct media_pad *pads;
198 };
199
200 struct mxc_isi_video {
201 struct mxc_isi_pipe *pipe;
202
203 struct video_device vdev;
204 struct media_pad pad;
205
206 /* Protects is_streaming, and the vdev and vb2_q operations */
207 struct mutex lock;
208 bool is_streaming;
209
210 struct v4l2_pix_format_mplane pix;
211 const struct mxc_isi_format_info *fmtinfo;
212
213 struct {
214 struct v4l2_ctrl_handler handler;
215 unsigned int alpha;
216 bool hflip;
217 bool vflip;
218 } ctrls;
219
220 struct vb2_queue vb2_q;
221 struct mxc_isi_buffer buf_discard[3];
222 struct list_head out_pending;
223 struct list_head out_active;
224 struct list_head out_discard;
225 u32 frame_count;
226 /* Protects out_pending, out_active, out_discard and frame_count */
227 spinlock_t buf_lock;
228
229 struct mxc_isi_dma_buffer discard_buffer[MXC_MAX_PLANES];
230 };
231
232 typedef void(*mxc_isi_pipe_irq_t)(struct mxc_isi_pipe *, u32);
233
234 struct mxc_isi_pipe {
235 struct mxc_isi_dev *isi;
236 u32 id;
237 void __iomem *regs;
238
239 struct media_pipeline pipe;
240
241 struct v4l2_subdev sd;
242 struct media_pad pads[MXC_ISI_PIPE_PADS_NUM];
243
244 struct mxc_isi_video video;
245
246 /*
247 * Protects use_count, irq_handler, res_available, res_acquired,
248 * chained_res, and the CHNL_CTRL register.
249 */
250 struct mutex lock;
251 unsigned int use_count;
252 mxc_isi_pipe_irq_t irq_handler;
253
254 #define MXC_ISI_CHANNEL_RES_LINE_BUF BIT(0)
255 #define MXC_ISI_CHANNEL_RES_OUTPUT_BUF BIT(1)
256 u8 available_res;
257 u8 acquired_res;
258 u8 chained_res;
259 bool chained;
260 };
261
262 struct mxc_isi_m2m {
263 struct mxc_isi_dev *isi;
264 struct mxc_isi_pipe *pipe;
265
266 struct media_pad pad;
267 struct video_device vdev;
268 struct media_intf_devnode *intf;
269 struct v4l2_m2m_dev *m2m_dev;
270
271 /* Protects last_ctx, usage_count and chained_count */
272 struct mutex lock;
273
274 struct mxc_isi_m2m_ctx *last_ctx;
275 int usage_count;
276 int chained_count;
277 };
278
279 struct mxc_isi_dev {
280 struct device *dev;
281
282 const struct mxc_isi_plat_data *pdata;
283
284 void __iomem *regs;
285 struct clk_bulk_data *clks;
286 struct regmap *gasket;
287
288 struct mxc_isi_crossbar crossbar;
289 struct mxc_isi_pipe *pipes;
290 struct mxc_isi_m2m m2m;
291
292 struct media_device media_dev;
293 struct v4l2_device v4l2_dev;
294 struct v4l2_async_notifier notifier;
295
296 struct dentry *debugfs_root;
297 };
298
299 extern const struct mxc_gasket_ops mxc_imx8_gasket_ops;
300 extern const struct mxc_gasket_ops mxc_imx93_gasket_ops;
301
302 int mxc_isi_crossbar_init(struct mxc_isi_dev *isi);
303 void mxc_isi_crossbar_cleanup(struct mxc_isi_crossbar *xbar);
304 int mxc_isi_crossbar_register(struct mxc_isi_crossbar *xbar);
305 void mxc_isi_crossbar_unregister(struct mxc_isi_crossbar *xbar);
306
307 const struct mxc_isi_bus_format_info *
308 mxc_isi_bus_format_by_code(u32 code, unsigned int pad);
309 const struct mxc_isi_bus_format_info *
310 mxc_isi_bus_format_by_index(unsigned int index, unsigned int pad);
311 const struct mxc_isi_format_info *
312 mxc_isi_format_by_fourcc(u32 fourcc, enum mxc_isi_video_type type);
313 const struct mxc_isi_format_info *
314 mxc_isi_format_enum(unsigned int index, enum mxc_isi_video_type type);
315 const struct mxc_isi_format_info *
316 mxc_isi_format_try(struct mxc_isi_pipe *pipe, struct v4l2_pix_format_mplane *pix,
317 enum mxc_isi_video_type type);
318
319 int mxc_isi_pipe_init(struct mxc_isi_dev *isi, unsigned int id);
320 void mxc_isi_pipe_cleanup(struct mxc_isi_pipe *pipe);
321 int mxc_isi_pipe_acquire(struct mxc_isi_pipe *pipe,
322 mxc_isi_pipe_irq_t irq_handler);
323 void mxc_isi_pipe_release(struct mxc_isi_pipe *pipe);
324 int mxc_isi_pipe_enable(struct mxc_isi_pipe *pipe);
325 void mxc_isi_pipe_disable(struct mxc_isi_pipe *pipe);
326
327 int mxc_isi_video_register(struct mxc_isi_pipe *pipe,
328 struct v4l2_device *v4l2_dev);
329 void mxc_isi_video_unregister(struct mxc_isi_pipe *pipe);
330 void mxc_isi_video_suspend(struct mxc_isi_pipe *pipe);
331 int mxc_isi_video_resume(struct mxc_isi_pipe *pipe);
332 int mxc_isi_video_queue_setup(const struct v4l2_pix_format_mplane *format,
333 const struct mxc_isi_format_info *info,
334 unsigned int *num_buffers,
335 unsigned int *num_planes, unsigned int sizes[]);
336 void mxc_isi_video_buffer_init(struct vb2_buffer *vb2, dma_addr_t dma_addrs[3],
337 const struct mxc_isi_format_info *info,
338 const struct v4l2_pix_format_mplane *pix);
339 int mxc_isi_video_buffer_prepare(struct mxc_isi_dev *isi, struct vb2_buffer *vb2,
340 const struct mxc_isi_format_info *info,
341 const struct v4l2_pix_format_mplane *pix);
342
343 #ifdef CONFIG_VIDEO_IMX8_ISI_M2M
344 int mxc_isi_m2m_register(struct mxc_isi_dev *isi, struct v4l2_device *v4l2_dev);
345 int mxc_isi_m2m_unregister(struct mxc_isi_dev *isi);
346 #else
mxc_isi_m2m_register(struct mxc_isi_dev * isi,struct v4l2_device * v4l2_dev)347 static inline int mxc_isi_m2m_register(struct mxc_isi_dev *isi,
348 struct v4l2_device *v4l2_dev)
349 {
350 return 0;
351 }
mxc_isi_m2m_unregister(struct mxc_isi_dev * isi)352 static inline int mxc_isi_m2m_unregister(struct mxc_isi_dev *isi)
353 {
354 return 0;
355 }
356 #endif
357
358 int mxc_isi_channel_acquire(struct mxc_isi_pipe *pipe,
359 mxc_isi_pipe_irq_t irq_handler, bool bypass);
360 void mxc_isi_channel_release(struct mxc_isi_pipe *pipe);
361 void mxc_isi_channel_get(struct mxc_isi_pipe *pipe);
362 void mxc_isi_channel_put(struct mxc_isi_pipe *pipe);
363 void mxc_isi_channel_enable(struct mxc_isi_pipe *pipe);
364 void mxc_isi_channel_disable(struct mxc_isi_pipe *pipe);
365 int mxc_isi_channel_chain(struct mxc_isi_pipe *pipe, bool bypass);
366 void mxc_isi_channel_unchain(struct mxc_isi_pipe *pipe);
367
368 void mxc_isi_channel_config(struct mxc_isi_pipe *pipe,
369 enum mxc_isi_input_id input,
370 const struct v4l2_area *in_size,
371 const struct v4l2_area *scale,
372 const struct v4l2_rect *crop,
373 enum mxc_isi_encoding in_encoding,
374 enum mxc_isi_encoding out_encoding);
375
376 void mxc_isi_channel_set_input_format(struct mxc_isi_pipe *pipe,
377 const struct mxc_isi_format_info *info,
378 const struct v4l2_pix_format_mplane *format);
379 void mxc_isi_channel_set_output_format(struct mxc_isi_pipe *pipe,
380 const struct mxc_isi_format_info *info,
381 struct v4l2_pix_format_mplane *format);
382 void mxc_isi_channel_m2m_start(struct mxc_isi_pipe *pipe);
383
384 void mxc_isi_channel_set_alpha(struct mxc_isi_pipe *pipe, u8 alpha);
385 void mxc_isi_channel_set_flip(struct mxc_isi_pipe *pipe, bool hflip, bool vflip);
386
387 void mxc_isi_channel_set_inbuf(struct mxc_isi_pipe *pipe, dma_addr_t dma_addr);
388 void mxc_isi_channel_set_outbuf(struct mxc_isi_pipe *pipe,
389 const dma_addr_t dma_addrs[3],
390 enum mxc_isi_buf_id buf_id);
391
392 u32 mxc_isi_channel_irq_status(struct mxc_isi_pipe *pipe, bool clear);
393 void mxc_isi_channel_irq_clear(struct mxc_isi_pipe *pipe);
394
395 #if IS_ENABLED(CONFIG_DEBUG_FS)
396 void mxc_isi_debug_init(struct mxc_isi_dev *isi);
397 void mxc_isi_debug_cleanup(struct mxc_isi_dev *isi);
398 #else
mxc_isi_debug_init(struct mxc_isi_dev * isi)399 static inline void mxc_isi_debug_init(struct mxc_isi_dev *isi)
400 {
401 }
mxc_isi_debug_cleanup(struct mxc_isi_dev * isi)402 static inline void mxc_isi_debug_cleanup(struct mxc_isi_dev *isi)
403 {
404 }
405 #endif
406
407 #endif /* __MXC_ISI_CORE_H__ */
408