1 /**
2  * @file
3  *
4  * @brief Public APIs for Video.
5  */
6 
7 /*
8  * Copyright (c) 2019 Linaro Limited.
9  *
10  * SPDX-License-Identifier: Apache-2.0
11  */
12 #ifndef ZEPHYR_INCLUDE_VIDEO_H_
13 #define ZEPHYR_INCLUDE_VIDEO_H_
14 
15 /**
16  * @brief Video Interface
17  * @defgroup video_interface Video Interface
18  * @since 2.1
19  * @version 1.1.0
20  * @ingroup io_interfaces
21  * @{
22  */
23 
24 #include <zephyr/device.h>
25 #include <stddef.h>
26 #include <zephyr/kernel.h>
27 
28 #include <zephyr/types.h>
29 
30 #ifdef __cplusplus
31 extern "C" {
32 #endif
33 
34 /*
35  * Flag used by @ref video_caps structure to indicate endpoint operates on
36  * buffers the size of the video frame
37  */
38 #define LINE_COUNT_HEIGHT (-1)
39 
40 /**
41  * @struct video_format
42  * @brief Video format structure
43  *
44  * Used to configure frame format.
45  */
46 struct video_format {
47 	/** FourCC pixel format value (\ref video_pixel_formats) */
48 	uint32_t pixelformat;
49 	/** frame width in pixels. */
50 	uint32_t width;
51 	/** frame height in pixels. */
52 	uint32_t height;
53 	/**
54 	 * @brief line stride.
55 	 *
56 	 * This is the number of bytes that needs to be added to the address in the
57 	 * first pixel of a row in order to go to the address of the first pixel of
58 	 * the next row (>=width).
59 	 */
60 	uint32_t pitch;
61 };
62 
63 /**
64  * @struct video_format_cap
65  * @brief Video format capability
66  *
67  * Used to describe a video endpoint format capability.
68  */
69 struct video_format_cap {
70 	/** FourCC pixel format value (\ref video_pixel_formats). */
71 	uint32_t pixelformat;
72 	/** minimum supported frame width in pixels. */
73 	uint32_t width_min;
74 	/** maximum supported frame width in pixels. */
75 	uint32_t width_max;
76 	/** minimum supported frame height in pixels. */
77 	uint32_t height_min;
78 	/** maximum supported frame height in pixels. */
79 	uint32_t height_max;
80 	/** width step size in pixels. */
81 	uint16_t width_step;
82 	/** height step size in pixels. */
83 	uint16_t height_step;
84 };
85 
86 /**
87  * @struct video_caps
88  * @brief Video format capabilities
89  *
90  * Used to describe video endpoint capabilities.
91  */
92 struct video_caps {
93 	/** list of video format capabilities (zero terminated). */
94 	const struct video_format_cap *format_caps;
95 	/** minimal count of video buffers to enqueue before being able to start
96 	 * the stream.
97 	 */
98 	uint8_t min_vbuf_count;
99 	/** Denotes minimum line count of a video buffer that this endpoint
100 	 * can fill or process. Each line is expected to consume the number
101 	 * of bytes the selected video format's pitch uses, so the video
102 	 * buffer must be at least `pitch` * `min_line_count` bytes.
103 	 * `LINE_COUNT_HEIGHT` is a special value, indicating the endpoint
104 	 * only supports video buffers with at least enough bytes to store
105 	 * a full video frame
106 	 */
107 	int16_t min_line_count;
108 	/**
109 	 * Denotes maximum line count of a video buffer that this endpoint
110 	 * can fill or process. Similar constraints to `min_line_count`,
111 	 * but `LINE_COUNT_HEIGHT` indicates that the endpoint will never
112 	 * fill or process more than a full video frame in one video buffer.
113 	 */
114 	int16_t max_line_count;
115 };
116 
117 /**
118  * @struct video_buffer
119  * @brief Video buffer structure
120  *
121  * Represent a video frame.
122  */
123 struct video_buffer {
124 	/** pointer to driver specific data. */
125 	void *driver_data;
126 	/** pointer to the start of the buffer. */
127 	uint8_t *buffer;
128 	/** size of the buffer in bytes. */
129 	uint32_t size;
130 	/** number of bytes occupied by the valid data in the buffer. */
131 	uint32_t bytesused;
132 	/** time reference in milliseconds at which the last data byte was
133 	 * actually received for input endpoints or to be consumed for output
134 	 * endpoints.
135 	 */
136 	uint32_t timestamp;
137 	/** Line offset within frame this buffer represents, from the
138 	 * beginning of the frame. This offset is given in pixels,
139 	 * so `line_offset` * `pitch` provides offset from the start of
140 	 * the frame in bytes.
141 	 */
142 	uint16_t line_offset;
143 };
144 
145 /**
146  * @brief video_frmival_type enum
147  *
148  * Supported frame interval type of a video device.
149  */
150 enum video_frmival_type {
151 	/** discrete frame interval type */
152 	VIDEO_FRMIVAL_TYPE_DISCRETE = 1,
153 	/** stepwise frame interval type */
154 	VIDEO_FRMIVAL_TYPE_STEPWISE = 2,
155 };
156 
157 /**
158  * @struct video_frmival
159  * @brief Video frame interval structure
160  *
161  * Used to describe a video frame interval.
162  */
163 struct video_frmival {
164 	/** numerator of the frame interval */
165 	uint32_t numerator;
166 	/** denominator of the frame interval */
167 	uint32_t denominator;
168 };
169 
170 /**
171  * @struct video_frmival_stepwise
172  * @brief Video frame interval stepwise structure
173  *
174  * Used to describe the video frame interval stepwise type.
175  */
176 struct video_frmival_stepwise {
177 	/** minimum frame interval in seconds */
178 	struct video_frmival min;
179 	/** maximum frame interval in seconds */
180 	struct video_frmival max;
181 	/** frame interval step size in seconds */
182 	struct video_frmival step;
183 };
184 
185 /**
186  * @struct video_frmival_enum
187  * @brief Video frame interval enumeration structure
188  *
189  * Used to describe the supported video frame intervals of a given video format.
190  */
191 struct video_frmival_enum {
192 	/** frame interval index during enumeration */
193 	uint32_t index;
194 	/** video format for which the query is made */
195 	const struct video_format *format;
196 	/** frame interval type the device supports */
197 	enum video_frmival_type type;
198 	/** the actual frame interval */
199 	union {
200 		struct video_frmival discrete;
201 		struct video_frmival_stepwise stepwise;
202 	};
203 };
204 
205 /**
206  * @brief video_endpoint_id enum
207  *
208  * Identify the video device endpoint.
209  */
210 enum video_endpoint_id {
211 	/** Targets some part of the video device not bound to an endpoint */
212 	VIDEO_EP_NONE = -1,
213 	/** Targets all input or output endpoints of the device */
214 	VIDEO_EP_ALL = -2,
215 	/** Targets all input endpoints of the device: those consuming data */
216 	VIDEO_EP_IN = -3,
217 	/** Targets all output endpoints of the device: those producing data */
218 	VIDEO_EP_OUT = -4,
219 };
220 
221 /**
222  * @brief video_event enum
223  *
224  * Identify video event.
225  */
226 enum video_signal_result {
227 	VIDEO_BUF_DONE,
228 	VIDEO_BUF_ABORTED,
229 	VIDEO_BUF_ERROR,
230 };
231 
232 /**
233  * @typedef video_api_set_format_t
234  * @brief Set video format
235  *
236  * See video_set_format() for argument descriptions.
237  */
238 typedef int (*video_api_set_format_t)(const struct device *dev, enum video_endpoint_id ep,
239 				      struct video_format *fmt);
240 
241 /**
242  * @typedef video_api_get_format_t
243  * @brief Get current video format
244  *
245  * See video_get_format() for argument descriptions.
246  */
247 typedef int (*video_api_get_format_t)(const struct device *dev, enum video_endpoint_id ep,
248 				      struct video_format *fmt);
249 
250 /**
251  * @typedef video_api_set_frmival_t
252  * @brief Set video frame interval
253  *
254  * See video_set_frmival() for argument descriptions.
255  */
256 typedef int (*video_api_set_frmival_t)(const struct device *dev, enum video_endpoint_id ep,
257 				       struct video_frmival *frmival);
258 
259 /**
260  * @typedef video_api_get_frmival_t
261  * @brief Get current video frame interval
262  *
263  * See video_get_frmival() for argument descriptions.
264  */
265 typedef int (*video_api_get_frmival_t)(const struct device *dev, enum video_endpoint_id ep,
266 				       struct video_frmival *frmival);
267 
268 /**
269  * @typedef video_api_enum_frmival_t
270  * @brief List all supported frame intervals of a given format
271  *
272  * See video_enum_frmival() for argument descriptions.
273  */
274 typedef int (*video_api_enum_frmival_t)(const struct device *dev, enum video_endpoint_id ep,
275 					struct video_frmival_enum *fie);
276 
277 /**
278  * @typedef video_api_enqueue_t
279  * @brief Enqueue a buffer in the driver’s incoming queue.
280  *
281  * See video_enqueue() for argument descriptions.
282  */
283 typedef int (*video_api_enqueue_t)(const struct device *dev, enum video_endpoint_id ep,
284 				   struct video_buffer *buf);
285 
286 /**
287  * @typedef video_api_dequeue_t
288  * @brief Dequeue a buffer from the driver’s outgoing queue.
289  *
290  * See video_dequeue() for argument descriptions.
291  */
292 typedef int (*video_api_dequeue_t)(const struct device *dev, enum video_endpoint_id ep,
293 				   struct video_buffer **buf, k_timeout_t timeout);
294 
295 /**
296  * @typedef video_api_flush_t
297  * @brief Flush endpoint buffers, buffer are moved from incoming queue to
298  *        outgoing queue.
299  *
300  * See video_flush() for argument descriptions.
301  */
302 typedef int (*video_api_flush_t)(const struct device *dev, enum video_endpoint_id ep, bool cancel);
303 
304 /**
305  * @typedef video_api_stream_start_t
306  * @brief Start the capture or output process.
307  *
308  * See video_stream_start() for argument descriptions.
309  */
310 typedef int (*video_api_stream_start_t)(const struct device *dev);
311 
312 /**
313  * @typedef video_api_stream_stop_t
314  * @brief Stop the capture or output process.
315  *
316  * See video_stream_stop() for argument descriptions.
317  */
318 typedef int (*video_api_stream_stop_t)(const struct device *dev);
319 
320 /**
321  * @typedef video_api_set_ctrl_t
322  * @brief Set a video control value.
323  *
324  * See video_set_ctrl() for argument descriptions.
325  */
326 typedef int (*video_api_set_ctrl_t)(const struct device *dev, unsigned int cid, void *value);
327 
328 /**
329  * @typedef video_api_get_ctrl_t
330  * @brief Get a video control value.
331  *
332  * See video_get_ctrl() for argument descriptions.
333  */
334 typedef int (*video_api_get_ctrl_t)(const struct device *dev, unsigned int cid, void *value);
335 
336 /**
337  * @typedef video_api_get_caps_t
338  * @brief Get capabilities of a video endpoint.
339  *
340  * See video_get_caps() for argument descriptions.
341  */
342 typedef int (*video_api_get_caps_t)(const struct device *dev, enum video_endpoint_id ep,
343 				    struct video_caps *caps);
344 
345 /**
346  * @typedef video_api_set_signal_t
347  * @brief Register/Unregister poll signal for buffer events.
348  *
349  * See video_set_signal() for argument descriptions.
350  */
351 typedef int (*video_api_set_signal_t)(const struct device *dev, enum video_endpoint_id ep,
352 				      struct k_poll_signal *signal);
353 
354 __subsystem struct video_driver_api {
355 	/* mandatory callbacks */
356 	video_api_set_format_t set_format;
357 	video_api_get_format_t get_format;
358 	video_api_stream_start_t stream_start;
359 	video_api_stream_stop_t stream_stop;
360 	video_api_get_caps_t get_caps;
361 	/* optional callbacks */
362 	video_api_enqueue_t enqueue;
363 	video_api_dequeue_t dequeue;
364 	video_api_flush_t flush;
365 	video_api_set_ctrl_t set_ctrl;
366 	video_api_get_ctrl_t get_ctrl;
367 	video_api_set_signal_t set_signal;
368 	video_api_set_frmival_t set_frmival;
369 	video_api_get_frmival_t get_frmival;
370 	video_api_enum_frmival_t enum_frmival;
371 };
372 
373 /**
374  * @brief Set video format.
375  *
376  * Configure video device with a specific format.
377  *
378  * @param dev Pointer to the device structure for the driver instance.
379  * @param ep Endpoint ID.
380  * @param fmt Pointer to a video format struct.
381  *
382  * @retval 0 Is successful.
383  * @retval -EINVAL If parameters are invalid.
384  * @retval -ENOTSUP If format is not supported.
385  * @retval -EIO General input / output error.
386  */
video_set_format(const struct device * dev,enum video_endpoint_id ep,struct video_format * fmt)387 static inline int video_set_format(const struct device *dev, enum video_endpoint_id ep,
388 				   struct video_format *fmt)
389 {
390 	const struct video_driver_api *api = (const struct video_driver_api *)dev->api;
391 
392 	if (api->set_format == NULL) {
393 		return -ENOSYS;
394 	}
395 
396 	return api->set_format(dev, ep, fmt);
397 }
398 
399 /**
400  * @brief Get video format.
401  *
402  * Get video device current video format.
403  *
404  * @param dev Pointer to the device structure for the driver instance.
405  * @param ep Endpoint ID.
406  * @param fmt Pointer to video format struct.
407  *
408  * @retval pointer to video format
409  */
video_get_format(const struct device * dev,enum video_endpoint_id ep,struct video_format * fmt)410 static inline int video_get_format(const struct device *dev, enum video_endpoint_id ep,
411 				   struct video_format *fmt)
412 {
413 	const struct video_driver_api *api = (const struct video_driver_api *)dev->api;
414 
415 	if (api->get_format == NULL) {
416 		return -ENOSYS;
417 	}
418 
419 	return api->get_format(dev, ep, fmt);
420 }
421 
422 /**
423  * @brief Set video frame interval.
424  *
425  * Configure video device with a specific frame interval.
426  *
427  * Drivers must not return an error solely because the requested interval doesn’t match the device
428  * capabilities. They must instead modify the interval to match what the hardware can provide.
429  *
430  * @param dev Pointer to the device structure for the driver instance.
431  * @param ep Endpoint ID.
432  * @param frmival Pointer to a video frame interval struct.
433  *
434  * @retval 0 If successful.
435  * @retval -ENOSYS If API is not implemented.
436  * @retval -EINVAL If parameters are invalid.
437  * @retval -EIO General input / output error.
438  */
video_set_frmival(const struct device * dev,enum video_endpoint_id ep,struct video_frmival * frmival)439 static inline int video_set_frmival(const struct device *dev, enum video_endpoint_id ep,
440 				    struct video_frmival *frmival)
441 {
442 	const struct video_driver_api *api = (const struct video_driver_api *)dev->api;
443 
444 	if (api->set_frmival == NULL) {
445 		return -ENOSYS;
446 	}
447 
448 	return api->set_frmival(dev, ep, frmival);
449 }
450 
451 /**
452  * @brief Get video frame interval.
453  *
454  * Get current frame interval of the video device.
455  *
456  * @param dev Pointer to the device structure for the driver instance.
457  * @param ep Endpoint ID.
458  * @param frmival Pointer to a video frame interval struct.
459  *
460  * @retval 0 If successful.
461  * @retval -ENOSYS If API is not implemented.
462  * @retval -EINVAL If parameters are invalid.
463  * @retval -EIO General input / output error.
464  */
video_get_frmival(const struct device * dev,enum video_endpoint_id ep,struct video_frmival * frmival)465 static inline int video_get_frmival(const struct device *dev, enum video_endpoint_id ep,
466 				    struct video_frmival *frmival)
467 {
468 	const struct video_driver_api *api = (const struct video_driver_api *)dev->api;
469 
470 	if (api->get_frmival == NULL) {
471 		return -ENOSYS;
472 	}
473 
474 	return api->get_frmival(dev, ep, frmival);
475 }
476 
477 /**
478  * @brief List video frame intervals.
479  *
480  * List all supported video frame intervals of a given format.
481  *
482  * Applications should fill the pixelformat, width and height fields of the
483  * video_frmival_enum struct first to form a query. Then, the index field is
484  * used to iterate through the supported frame intervals list.
485  *
486  * @param dev Pointer to the device structure for the driver instance.
487  * @param ep Endpoint ID.
488  * @param fie Pointer to a video frame interval enumeration struct.
489  *
490  * @retval 0 If successful.
491  * @retval -ENOSYS If API is not implemented.
492  * @retval -EINVAL If parameters are invalid.
493  * @retval -EIO General input / output error.
494  */
video_enum_frmival(const struct device * dev,enum video_endpoint_id ep,struct video_frmival_enum * fie)495 static inline int video_enum_frmival(const struct device *dev, enum video_endpoint_id ep,
496 				     struct video_frmival_enum *fie)
497 {
498 	const struct video_driver_api *api = (const struct video_driver_api *)dev->api;
499 
500 	if (api->enum_frmival == NULL) {
501 		return -ENOSYS;
502 	}
503 
504 	return api->enum_frmival(dev, ep, fie);
505 }
506 
507 /**
508  * @brief Enqueue a video buffer.
509  *
510  * Enqueue an empty (capturing) or filled (output) video buffer in the driver’s
511  * endpoint incoming queue.
512  *
513  * @param dev Pointer to the device structure for the driver instance.
514  * @param ep Endpoint ID.
515  * @param buf Pointer to the video buffer.
516  *
517  * @retval 0 Is successful.
518  * @retval -EINVAL If parameters are invalid.
519  * @retval -EIO General input / output error.
520  */
video_enqueue(const struct device * dev,enum video_endpoint_id ep,struct video_buffer * buf)521 static inline int video_enqueue(const struct device *dev, enum video_endpoint_id ep,
522 				struct video_buffer *buf)
523 {
524 	const struct video_driver_api *api = (const struct video_driver_api *)dev->api;
525 
526 	if (api->enqueue == NULL) {
527 		return -ENOSYS;
528 	}
529 
530 	return api->enqueue(dev, ep, buf);
531 }
532 
533 /**
534  * @brief Dequeue a video buffer.
535  *
536  * Dequeue a filled (capturing) or displayed (output) buffer from the driver’s
537  * endpoint outgoing queue.
538  *
539  * @param dev Pointer to the device structure for the driver instance.
540  * @param ep Endpoint ID.
541  * @param buf Pointer a video buffer pointer.
542  * @param timeout Timeout
543  *
544  * @retval 0 Is successful.
545  * @retval -EINVAL If parameters are invalid.
546  * @retval -EIO General input / output error.
547  */
video_dequeue(const struct device * dev,enum video_endpoint_id ep,struct video_buffer ** buf,k_timeout_t timeout)548 static inline int video_dequeue(const struct device *dev, enum video_endpoint_id ep,
549 				struct video_buffer **buf, k_timeout_t timeout)
550 {
551 	const struct video_driver_api *api = (const struct video_driver_api *)dev->api;
552 
553 	if (api->dequeue == NULL) {
554 		return -ENOSYS;
555 	}
556 
557 	return api->dequeue(dev, ep, buf, timeout);
558 }
559 
560 /**
561  * @brief Flush endpoint buffers.
562  *
563  * A call to flush finishes when all endpoint buffers have been moved from
564  * incoming queue to outgoing queue. Either because canceled or fully processed
565  * through the video function.
566  *
567  * @param dev Pointer to the device structure for the driver instance.
568  * @param ep Endpoint ID.
569  * @param cancel If true, cancel buffer processing instead of waiting for
570  *        completion.
571  *
572  * @retval 0 Is successful, -ERRNO code otherwise.
573  */
video_flush(const struct device * dev,enum video_endpoint_id ep,bool cancel)574 static inline int video_flush(const struct device *dev, enum video_endpoint_id ep, bool cancel)
575 {
576 	const struct video_driver_api *api = (const struct video_driver_api *)dev->api;
577 
578 	if (api->flush == NULL) {
579 		return -ENOSYS;
580 	}
581 
582 	return api->flush(dev, ep, cancel);
583 }
584 
585 /**
586  * @brief Start the video device function.
587  *
588  * video_stream_start is called to enter ‘streaming’ state (capture, output...).
589  * The driver may receive buffers with video_enqueue() before video_stream_start
590  * is called. If driver/device needs a minimum number of buffers before being
591  * able to start streaming, then driver set the min_vbuf_count to the related
592  * endpoint capabilities.
593  *
594  * @retval 0 Is successful.
595  * @retval -EIO General input / output error.
596  */
video_stream_start(const struct device * dev)597 static inline int video_stream_start(const struct device *dev)
598 {
599 	const struct video_driver_api *api = (const struct video_driver_api *)dev->api;
600 
601 	if (api->stream_start == NULL) {
602 		return -ENOSYS;
603 	}
604 
605 	return api->stream_start(dev);
606 }
607 
608 /**
609  * @brief Stop the video device function.
610  *
611  * On video_stream_stop, driver must stop any transactions or wait until they
612  * finish.
613  *
614  * @retval 0 Is successful.
615  * @retval -EIO General input / output error.
616  */
video_stream_stop(const struct device * dev)617 static inline int video_stream_stop(const struct device *dev)
618 {
619 	const struct video_driver_api *api = (const struct video_driver_api *)dev->api;
620 	int ret;
621 
622 	if (api->stream_stop == NULL) {
623 		return -ENOSYS;
624 	}
625 
626 	ret = api->stream_stop(dev);
627 	video_flush(dev, VIDEO_EP_ALL, true);
628 
629 	return ret;
630 }
631 
632 /**
633  * @brief Get the capabilities of a video endpoint.
634  *
635  * @param dev Pointer to the device structure for the driver instance.
636  * @param ep Endpoint ID.
637  * @param caps Pointer to the video_caps struct to fill.
638  *
639  * @retval 0 Is successful, -ERRNO code otherwise.
640  */
video_get_caps(const struct device * dev,enum video_endpoint_id ep,struct video_caps * caps)641 static inline int video_get_caps(const struct device *dev, enum video_endpoint_id ep,
642 				 struct video_caps *caps)
643 {
644 	const struct video_driver_api *api = (const struct video_driver_api *)dev->api;
645 
646 	if (api->get_caps == NULL) {
647 		return -ENOSYS;
648 	}
649 
650 	return api->get_caps(dev, ep, caps);
651 }
652 
653 /**
654  * @brief Set the value of a control.
655  *
656  * This set the value of a video control, value type depends on control ID, and
657  * must be interpreted accordingly.
658  *
659  * @param dev Pointer to the device structure for the driver instance.
660  * @param cid Control ID.
661  * @param value Pointer to the control value.
662  *
663  * @retval 0 Is successful.
664  * @retval -EINVAL If parameters are invalid.
665  * @retval -ENOTSUP If format is not supported.
666  * @retval -EIO General input / output error.
667  */
video_set_ctrl(const struct device * dev,unsigned int cid,void * value)668 static inline int video_set_ctrl(const struct device *dev, unsigned int cid, void *value)
669 {
670 	const struct video_driver_api *api = (const struct video_driver_api *)dev->api;
671 
672 	if (api->set_ctrl == NULL) {
673 		return -ENOSYS;
674 	}
675 
676 	return api->set_ctrl(dev, cid, value);
677 }
678 
679 /**
680  * @brief Get the current value of a control.
681  *
682  * This retrieve the value of a video control, value type depends on control ID,
683  * and must be interpreted accordingly.
684  *
685  * @param dev Pointer to the device structure for the driver instance.
686  * @param cid Control ID.
687  * @param value Pointer to the control value.
688  *
689  * @retval 0 Is successful.
690  * @retval -EINVAL If parameters are invalid.
691  * @retval -ENOTSUP If format is not supported.
692  * @retval -EIO General input / output error.
693  */
video_get_ctrl(const struct device * dev,unsigned int cid,void * value)694 static inline int video_get_ctrl(const struct device *dev, unsigned int cid, void *value)
695 {
696 	const struct video_driver_api *api = (const struct video_driver_api *)dev->api;
697 
698 	if (api->get_ctrl == NULL) {
699 		return -ENOSYS;
700 	}
701 
702 	return api->get_ctrl(dev, cid, value);
703 }
704 
705 /**
706  * @brief Register/Unregister k_poll signal for a video endpoint.
707  *
708  * Register a poll signal to the endpoint, which will be signaled on frame
709  * completion (done, aborted, error). Registering a NULL poll signal
710  * unregisters any previously registered signal.
711  *
712  * @param dev Pointer to the device structure for the driver instance.
713  * @param ep Endpoint ID.
714  * @param signal Pointer to k_poll_signal
715  *
716  * @retval 0 Is successful, -ERRNO code otherwise.
717  */
video_set_signal(const struct device * dev,enum video_endpoint_id ep,struct k_poll_signal * signal)718 static inline int video_set_signal(const struct device *dev, enum video_endpoint_id ep,
719 				   struct k_poll_signal *signal)
720 {
721 	const struct video_driver_api *api = (const struct video_driver_api *)dev->api;
722 
723 	if (api->set_signal == NULL) {
724 		return -ENOSYS;
725 	}
726 
727 	return api->set_signal(dev, ep, signal);
728 }
729 
730 /**
731  * @brief Allocate aligned video buffer.
732  *
733  * @param size Size of the video buffer (in bytes).
734  * @param align Alignment of the requested memory, must be a power of two.
735  * @param timeout Timeout duration or K_NO_WAIT
736  *
737  * @retval pointer to allocated video buffer
738  */
739 struct video_buffer *video_buffer_aligned_alloc(size_t size, size_t align, k_timeout_t timeout);
740 
741 /**
742  * @brief Allocate video buffer.
743  *
744  * @param size Size of the video buffer (in bytes).
745  * @param timeout Timeout duration or K_NO_WAIT
746  *
747  * @retval pointer to allocated video buffer
748  */
749 struct video_buffer *video_buffer_alloc(size_t size, k_timeout_t timeout);
750 
751 /**
752  * @brief Release a video buffer.
753  *
754  * @param buf Pointer to the video buffer to release.
755  */
756 void video_buffer_release(struct video_buffer *buf);
757 
758 /**
759  * @brief Search for a format that matches in a list of capabilities
760  *
761  * @param fmts The format capability list to search.
762  * @param fmt The format to find in the list.
763  * @param idx The pointer to a number of the first format that matches.
764  *
765  * @return 0 when a format is found.
766  * @return -ENOENT when no matching format is found.
767  */
768 int video_format_caps_index(const struct video_format_cap *fmts, const struct video_format *fmt,
769 			    size_t *idx);
770 
771 /**
772  * @brief Compute the difference between two frame intervals
773  *
774  * @param frmival Frame interval to turn into microseconds.
775  *
776  * @return The frame interval value in microseconds.
777  */
video_frmival_nsec(const struct video_frmival * frmival)778 static inline uint64_t video_frmival_nsec(const struct video_frmival *frmival)
779 {
780 	return (uint64_t)NSEC_PER_SEC * frmival->numerator / frmival->denominator;
781 }
782 
783 /**
784  * @brief Find the closest match to a frame interval value within a stepwise frame interval.
785  *
786  * @param stepwise The stepwise frame interval range to search
787  * @param desired The frame interval for which find the closest match
788  * @param match The resulting frame interval closest to @p desired
789  */
790 void video_closest_frmival_stepwise(const struct video_frmival_stepwise *stepwise,
791 				    const struct video_frmival *desired,
792 				    struct video_frmival *match);
793 
794 /**
795  * @brief Find the closest match to a frame interval value within a video device.
796  *
797  * To compute the closest match, fill @p match with the following fields:
798  *
799  * - @c match->format to the @ref video_format of interest.
800  * - @c match->type to @ref VIDEO_FRMIVAL_TYPE_DISCRETE.
801  * - @c match->discrete to the desired frame interval.
802  *
803  * The result will be loaded into @p match, with the following fields set:
804  *
805  * - @c match->discrete to the value of the closest frame interval.
806  * - @c match->index to the index of the closest frame interval.
807  *
808  * @param dev Video device to query.
809  * @param ep Video endpoint ID to query.
810  * @param match Frame interval enumerator with the query, and loaded with the result.
811  */
812 void video_closest_frmival(const struct device *dev, enum video_endpoint_id ep,
813 			   struct video_frmival_enum *match);
814 
815 /* fourcc - four-character-code */
816 #define video_fourcc(a, b, c, d)                                                                   \
817 	((uint32_t)(a) | ((uint32_t)(b) << 8) | ((uint32_t)(c) << 16) | ((uint32_t)(d) << 24))
818 
819 /**
820  * @defgroup video_pixel_formats Video pixel formats
821  * @{
822  */
823 
824 /**
825  * @name Bayer formats
826  * @{
827  */
828 
829 /** BGGR8 pixel format */
830 #define VIDEO_PIX_FMT_BGGR8 video_fourcc('B', 'G', 'G', 'R') /*  8  BGBG.. GRGR.. */
831 /** GBRG8 pixel format */
832 #define VIDEO_PIX_FMT_GBRG8 video_fourcc('G', 'B', 'R', 'G') /*  8  GBGB.. RGRG.. */
833 /** GRBG8 pixel format */
834 #define VIDEO_PIX_FMT_GRBG8 video_fourcc('G', 'R', 'B', 'G') /*  8  GRGR.. BGBG.. */
835 /** RGGB8 pixel format */
836 #define VIDEO_PIX_FMT_RGGB8 video_fourcc('R', 'G', 'G', 'B') /*  8  RGRG.. GBGB.. */
837 
838 /**
839  * @}
840  */
841 
842 /**
843  * @name RGB formats
844  * @{
845  */
846 
847 /** RGB565 pixel format */
848 #define VIDEO_PIX_FMT_RGB565 video_fourcc('R', 'G', 'B', 'P') /* 16  RGB-5-6-5 */
849 
850 /** XRGB32 pixel format */
851 #define VIDEO_PIX_FMT_XRGB32 video_fourcc('B', 'X', '2', '4') /* 32  XRGB-8-8-8-8 */
852 
853 /**
854  * @}
855  */
856 
857 /**
858  * @name YUV formats
859  * @{
860  */
861 
862 /** YUYV pixel format */
863 #define VIDEO_PIX_FMT_YUYV video_fourcc('Y', 'U', 'Y', 'V') /* 16  Y0-Cb0 Y1-Cr0 */
864 
865 /** XYUV32 pixel format */
866 #define VIDEO_PIX_FMT_XYUV32 video_fourcc('X', 'Y', 'U', 'V') /* 32  XYUV-8-8-8-8 */
867 
868 /**
869  *
870  * @}
871  */
872 
873 /**
874  * @name JPEG formats
875  * @{
876  */
877 
878 /** JPEG pixel format */
879 #define VIDEO_PIX_FMT_JPEG video_fourcc('J', 'P', 'E', 'G') /*  8  JPEG */
880 
881 /**
882  * @}
883  */
884 
885 /**
886  * @}
887  */
888 
889 /**
890  * @brief Get number of bytes per pixel of a pixel format
891  *
892  * @param pixfmt FourCC pixel format value (\ref video_pixel_formats).
893  */
video_pix_fmt_bpp(uint32_t pixfmt)894 static inline unsigned int video_pix_fmt_bpp(uint32_t pixfmt)
895 {
896 	switch (pixfmt) {
897 	case VIDEO_PIX_FMT_BGGR8:
898 	case VIDEO_PIX_FMT_GBRG8:
899 	case VIDEO_PIX_FMT_GRBG8:
900 	case VIDEO_PIX_FMT_RGGB8:
901 		return 1;
902 	case VIDEO_PIX_FMT_RGB565:
903 	case VIDEO_PIX_FMT_YUYV:
904 		return 2;
905 	case VIDEO_PIX_FMT_XRGB32:
906 	case VIDEO_PIX_FMT_XYUV32:
907 		return 4;
908 	default:
909 		return 0;
910 	}
911 }
912 
913 #ifdef __cplusplus
914 }
915 #endif
916 
917 /**
918  * @}
919  */
920 
921 #endif /* ZEPHYR_INCLUDE_VIDEO_H_ */
922