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_set_stream_t
306  * @brief Start or stop streaming on the video device.
307  *
308  * Start (enable == true) or stop (enable == false) streaming on the video device.
309  *
310  * @param dev Pointer to the device structure.
311  * @param enable If true, start streaming, otherwise stop streaming.
312  *
313  * @retval 0 on success, otherwise a negative errno code.
314  */
315 typedef int (*video_api_set_stream_t)(const struct device *dev, bool enable);
316 
317 /**
318  * @typedef video_api_set_ctrl_t
319  * @brief Set a video control value.
320  *
321  * See video_set_ctrl() for argument descriptions.
322  */
323 typedef int (*video_api_set_ctrl_t)(const struct device *dev, unsigned int cid, void *value);
324 
325 /**
326  * @typedef video_api_get_ctrl_t
327  * @brief Get a video control value.
328  *
329  * See video_get_ctrl() for argument descriptions.
330  */
331 typedef int (*video_api_get_ctrl_t)(const struct device *dev, unsigned int cid, void *value);
332 
333 /**
334  * @typedef video_api_get_caps_t
335  * @brief Get capabilities of a video endpoint.
336  *
337  * See video_get_caps() for argument descriptions.
338  */
339 typedef int (*video_api_get_caps_t)(const struct device *dev, enum video_endpoint_id ep,
340 				    struct video_caps *caps);
341 
342 /**
343  * @typedef video_api_set_signal_t
344  * @brief Register/Unregister poll signal for buffer events.
345  *
346  * See video_set_signal() for argument descriptions.
347  */
348 typedef int (*video_api_set_signal_t)(const struct device *dev, enum video_endpoint_id ep,
349 				      struct k_poll_signal *signal);
350 
351 __subsystem struct video_driver_api {
352 	/* mandatory callbacks */
353 	video_api_set_format_t set_format;
354 	video_api_get_format_t get_format;
355 	video_api_set_stream_t set_stream;
356 	video_api_get_caps_t get_caps;
357 	/* optional callbacks */
358 	video_api_enqueue_t enqueue;
359 	video_api_dequeue_t dequeue;
360 	video_api_flush_t flush;
361 	video_api_set_ctrl_t set_ctrl;
362 	video_api_get_ctrl_t get_ctrl;
363 	video_api_set_signal_t set_signal;
364 	video_api_set_frmival_t set_frmival;
365 	video_api_get_frmival_t get_frmival;
366 	video_api_enum_frmival_t enum_frmival;
367 };
368 
369 /**
370  * @brief Set video format.
371  *
372  * Configure video device with a specific format.
373  *
374  * @param dev Pointer to the device structure for the driver instance.
375  * @param ep Endpoint ID.
376  * @param fmt Pointer to a video format struct.
377  *
378  * @retval 0 Is successful.
379  * @retval -EINVAL If parameters are invalid.
380  * @retval -ENOTSUP If format is not supported.
381  * @retval -EIO General input / output error.
382  */
video_set_format(const struct device * dev,enum video_endpoint_id ep,struct video_format * fmt)383 static inline int video_set_format(const struct device *dev, enum video_endpoint_id ep,
384 				   struct video_format *fmt)
385 {
386 	const struct video_driver_api *api = (const struct video_driver_api *)dev->api;
387 
388 	if (api->set_format == NULL) {
389 		return -ENOSYS;
390 	}
391 
392 	return api->set_format(dev, ep, fmt);
393 }
394 
395 /**
396  * @brief Get video format.
397  *
398  * Get video device current video format.
399  *
400  * @param dev Pointer to the device structure for the driver instance.
401  * @param ep Endpoint ID.
402  * @param fmt Pointer to video format struct.
403  *
404  * @retval pointer to video format
405  */
video_get_format(const struct device * dev,enum video_endpoint_id ep,struct video_format * fmt)406 static inline int video_get_format(const struct device *dev, enum video_endpoint_id ep,
407 				   struct video_format *fmt)
408 {
409 	const struct video_driver_api *api = (const struct video_driver_api *)dev->api;
410 
411 	if (api->get_format == NULL) {
412 		return -ENOSYS;
413 	}
414 
415 	return api->get_format(dev, ep, fmt);
416 }
417 
418 /**
419  * @brief Set video frame interval.
420  *
421  * Configure video device with a specific frame interval.
422  *
423  * Drivers must not return an error solely because the requested interval doesn’t match the device
424  * capabilities. They must instead modify the interval to match what the hardware can provide.
425  *
426  * @param dev Pointer to the device structure for the driver instance.
427  * @param ep Endpoint ID.
428  * @param frmival Pointer to a video frame interval struct.
429  *
430  * @retval 0 If successful.
431  * @retval -ENOSYS If API is not implemented.
432  * @retval -EINVAL If parameters are invalid.
433  * @retval -EIO General input / output error.
434  */
video_set_frmival(const struct device * dev,enum video_endpoint_id ep,struct video_frmival * frmival)435 static inline int video_set_frmival(const struct device *dev, enum video_endpoint_id ep,
436 				    struct video_frmival *frmival)
437 {
438 	const struct video_driver_api *api = (const struct video_driver_api *)dev->api;
439 
440 	if (api->set_frmival == NULL) {
441 		return -ENOSYS;
442 	}
443 
444 	return api->set_frmival(dev, ep, frmival);
445 }
446 
447 /**
448  * @brief Get video frame interval.
449  *
450  * Get current frame interval of the video device.
451  *
452  * @param dev Pointer to the device structure for the driver instance.
453  * @param ep Endpoint ID.
454  * @param frmival Pointer to a video frame interval struct.
455  *
456  * @retval 0 If successful.
457  * @retval -ENOSYS If API is not implemented.
458  * @retval -EINVAL If parameters are invalid.
459  * @retval -EIO General input / output error.
460  */
video_get_frmival(const struct device * dev,enum video_endpoint_id ep,struct video_frmival * frmival)461 static inline int video_get_frmival(const struct device *dev, enum video_endpoint_id ep,
462 				    struct video_frmival *frmival)
463 {
464 	const struct video_driver_api *api = (const struct video_driver_api *)dev->api;
465 
466 	if (api->get_frmival == NULL) {
467 		return -ENOSYS;
468 	}
469 
470 	return api->get_frmival(dev, ep, frmival);
471 }
472 
473 /**
474  * @brief List video frame intervals.
475  *
476  * List all supported video frame intervals of a given format.
477  *
478  * Applications should fill the pixelformat, width and height fields of the
479  * video_frmival_enum struct first to form a query. Then, the index field is
480  * used to iterate through the supported frame intervals list.
481  *
482  * @param dev Pointer to the device structure for the driver instance.
483  * @param ep Endpoint ID.
484  * @param fie Pointer to a video frame interval enumeration struct.
485  *
486  * @retval 0 If successful.
487  * @retval -ENOSYS If API is not implemented.
488  * @retval -EINVAL If parameters are invalid.
489  * @retval -EIO General input / output error.
490  */
video_enum_frmival(const struct device * dev,enum video_endpoint_id ep,struct video_frmival_enum * fie)491 static inline int video_enum_frmival(const struct device *dev, enum video_endpoint_id ep,
492 				     struct video_frmival_enum *fie)
493 {
494 	const struct video_driver_api *api = (const struct video_driver_api *)dev->api;
495 
496 	if (api->enum_frmival == NULL) {
497 		return -ENOSYS;
498 	}
499 
500 	return api->enum_frmival(dev, ep, fie);
501 }
502 
503 /**
504  * @brief Enqueue a video buffer.
505  *
506  * Enqueue an empty (capturing) or filled (output) video buffer in the driver’s
507  * endpoint incoming queue.
508  *
509  * @param dev Pointer to the device structure for the driver instance.
510  * @param ep Endpoint ID.
511  * @param buf Pointer to the video buffer.
512  *
513  * @retval 0 Is successful.
514  * @retval -EINVAL If parameters are invalid.
515  * @retval -EIO General input / output error.
516  */
video_enqueue(const struct device * dev,enum video_endpoint_id ep,struct video_buffer * buf)517 static inline int video_enqueue(const struct device *dev, enum video_endpoint_id ep,
518 				struct video_buffer *buf)
519 {
520 	const struct video_driver_api *api = (const struct video_driver_api *)dev->api;
521 
522 	if (api->enqueue == NULL) {
523 		return -ENOSYS;
524 	}
525 
526 	return api->enqueue(dev, ep, buf);
527 }
528 
529 /**
530  * @brief Dequeue a video buffer.
531  *
532  * Dequeue a filled (capturing) or displayed (output) buffer from the driver’s
533  * endpoint outgoing queue.
534  *
535  * @param dev Pointer to the device structure for the driver instance.
536  * @param ep Endpoint ID.
537  * @param buf Pointer a video buffer pointer.
538  * @param timeout Timeout
539  *
540  * @retval 0 Is successful.
541  * @retval -EINVAL If parameters are invalid.
542  * @retval -EIO General input / output error.
543  */
video_dequeue(const struct device * dev,enum video_endpoint_id ep,struct video_buffer ** buf,k_timeout_t timeout)544 static inline int video_dequeue(const struct device *dev, enum video_endpoint_id ep,
545 				struct video_buffer **buf, k_timeout_t timeout)
546 {
547 	const struct video_driver_api *api = (const struct video_driver_api *)dev->api;
548 
549 	if (api->dequeue == NULL) {
550 		return -ENOSYS;
551 	}
552 
553 	return api->dequeue(dev, ep, buf, timeout);
554 }
555 
556 /**
557  * @brief Flush endpoint buffers.
558  *
559  * A call to flush finishes when all endpoint buffers have been moved from
560  * incoming queue to outgoing queue. Either because canceled or fully processed
561  * through the video function.
562  *
563  * @param dev Pointer to the device structure for the driver instance.
564  * @param ep Endpoint ID.
565  * @param cancel If true, cancel buffer processing instead of waiting for
566  *        completion.
567  *
568  * @retval 0 Is successful, -ERRNO code otherwise.
569  */
video_flush(const struct device * dev,enum video_endpoint_id ep,bool cancel)570 static inline int video_flush(const struct device *dev, enum video_endpoint_id ep, bool cancel)
571 {
572 	const struct video_driver_api *api = (const struct video_driver_api *)dev->api;
573 
574 	if (api->flush == NULL) {
575 		return -ENOSYS;
576 	}
577 
578 	return api->flush(dev, ep, cancel);
579 }
580 
581 /**
582  * @brief Start the video device function.
583  *
584  * video_stream_start is called to enter ‘streaming’ state (capture, output...).
585  * The driver may receive buffers with video_enqueue() before video_stream_start
586  * is called. If driver/device needs a minimum number of buffers before being
587  * able to start streaming, then driver set the min_vbuf_count to the related
588  * endpoint capabilities.
589  *
590  * @retval 0 Is successful.
591  * @retval -EIO General input / output error.
592  */
video_stream_start(const struct device * dev)593 static inline int video_stream_start(const struct device *dev)
594 {
595 	const struct video_driver_api *api = (const struct video_driver_api *)dev->api;
596 
597 	if (api->set_stream == NULL) {
598 		return -ENOSYS;
599 	}
600 
601 	return api->set_stream(dev, true);
602 }
603 
604 /**
605  * @brief Stop the video device function.
606  *
607  * On video_stream_stop, driver must stop any transactions or wait until they
608  * finish.
609  *
610  * @retval 0 Is successful.
611  * @retval -EIO General input / output error.
612  */
video_stream_stop(const struct device * dev)613 static inline int video_stream_stop(const struct device *dev)
614 {
615 	const struct video_driver_api *api = (const struct video_driver_api *)dev->api;
616 	int ret;
617 
618 	if (api->set_stream == NULL) {
619 		return -ENOSYS;
620 	}
621 
622 	ret = api->set_stream(dev, false);
623 	video_flush(dev, VIDEO_EP_ALL, true);
624 
625 	return ret;
626 }
627 
628 /**
629  * @brief Get the capabilities of a video endpoint.
630  *
631  * @param dev Pointer to the device structure for the driver instance.
632  * @param ep Endpoint ID.
633  * @param caps Pointer to the video_caps struct to fill.
634  *
635  * @retval 0 Is successful, -ERRNO code otherwise.
636  */
video_get_caps(const struct device * dev,enum video_endpoint_id ep,struct video_caps * caps)637 static inline int video_get_caps(const struct device *dev, enum video_endpoint_id ep,
638 				 struct video_caps *caps)
639 {
640 	const struct video_driver_api *api = (const struct video_driver_api *)dev->api;
641 
642 	if (api->get_caps == NULL) {
643 		return -ENOSYS;
644 	}
645 
646 	return api->get_caps(dev, ep, caps);
647 }
648 
649 /**
650  * @brief Set the value of a control.
651  *
652  * This set the value of a video control, value type depends on control ID, and
653  * must be interpreted accordingly.
654  *
655  * @param dev Pointer to the device structure for the driver instance.
656  * @param cid Control ID.
657  * @param value Pointer to the control value.
658  *
659  * @retval 0 Is successful.
660  * @retval -EINVAL If parameters are invalid.
661  * @retval -ENOTSUP If format is not supported.
662  * @retval -EIO General input / output error.
663  */
video_set_ctrl(const struct device * dev,unsigned int cid,void * value)664 static inline int video_set_ctrl(const struct device *dev, unsigned int cid, void *value)
665 {
666 	const struct video_driver_api *api = (const struct video_driver_api *)dev->api;
667 
668 	if (api->set_ctrl == NULL) {
669 		return -ENOSYS;
670 	}
671 
672 	return api->set_ctrl(dev, cid, value);
673 }
674 
675 /**
676  * @brief Get the current value of a control.
677  *
678  * This retrieve the value of a video control, value type depends on control ID,
679  * and must be interpreted accordingly.
680  *
681  * @param dev Pointer to the device structure for the driver instance.
682  * @param cid Control ID.
683  * @param value Pointer to the control value.
684  *
685  * @retval 0 Is successful.
686  * @retval -EINVAL If parameters are invalid.
687  * @retval -ENOTSUP If format is not supported.
688  * @retval -EIO General input / output error.
689  */
video_get_ctrl(const struct device * dev,unsigned int cid,void * value)690 static inline int video_get_ctrl(const struct device *dev, unsigned int cid, void *value)
691 {
692 	const struct video_driver_api *api = (const struct video_driver_api *)dev->api;
693 
694 	if (api->get_ctrl == NULL) {
695 		return -ENOSYS;
696 	}
697 
698 	return api->get_ctrl(dev, cid, value);
699 }
700 
701 /**
702  * @brief Register/Unregister k_poll signal for a video endpoint.
703  *
704  * Register a poll signal to the endpoint, which will be signaled on frame
705  * completion (done, aborted, error). Registering a NULL poll signal
706  * unregisters any previously registered signal.
707  *
708  * @param dev Pointer to the device structure for the driver instance.
709  * @param ep Endpoint ID.
710  * @param signal Pointer to k_poll_signal
711  *
712  * @retval 0 Is successful, -ERRNO code otherwise.
713  */
video_set_signal(const struct device * dev,enum video_endpoint_id ep,struct k_poll_signal * signal)714 static inline int video_set_signal(const struct device *dev, enum video_endpoint_id ep,
715 				   struct k_poll_signal *signal)
716 {
717 	const struct video_driver_api *api = (const struct video_driver_api *)dev->api;
718 
719 	if (api->set_signal == NULL) {
720 		return -ENOSYS;
721 	}
722 
723 	return api->set_signal(dev, ep, signal);
724 }
725 
726 /**
727  * @brief Allocate aligned video buffer.
728  *
729  * @param size Size of the video buffer (in bytes).
730  * @param align Alignment of the requested memory, must be a power of two.
731  * @param timeout Timeout duration or K_NO_WAIT
732  *
733  * @retval pointer to allocated video buffer
734  */
735 struct video_buffer *video_buffer_aligned_alloc(size_t size, size_t align, k_timeout_t timeout);
736 
737 /**
738  * @brief Allocate video buffer.
739  *
740  * @param size Size of the video buffer (in bytes).
741  * @param timeout Timeout duration or K_NO_WAIT
742  *
743  * @retval pointer to allocated video buffer
744  */
745 struct video_buffer *video_buffer_alloc(size_t size, k_timeout_t timeout);
746 
747 /**
748  * @brief Release a video buffer.
749  *
750  * @param buf Pointer to the video buffer to release.
751  */
752 void video_buffer_release(struct video_buffer *buf);
753 
754 /**
755  * @brief Search for a format that matches in a list of capabilities
756  *
757  * @param fmts The format capability list to search.
758  * @param fmt The format to find in the list.
759  * @param idx The pointer to a number of the first format that matches.
760  *
761  * @return 0 when a format is found.
762  * @return -ENOENT when no matching format is found.
763  */
764 int video_format_caps_index(const struct video_format_cap *fmts, const struct video_format *fmt,
765 			    size_t *idx);
766 
767 /**
768  * @brief Compute the difference between two frame intervals
769  *
770  * @param frmival Frame interval to turn into microseconds.
771  *
772  * @return The frame interval value in microseconds.
773  */
video_frmival_nsec(const struct video_frmival * frmival)774 static inline uint64_t video_frmival_nsec(const struct video_frmival *frmival)
775 {
776 	return (uint64_t)NSEC_PER_SEC * frmival->numerator / frmival->denominator;
777 }
778 
779 /**
780  * @brief Find the closest match to a frame interval value within a stepwise frame interval.
781  *
782  * @param stepwise The stepwise frame interval range to search
783  * @param desired The frame interval for which find the closest match
784  * @param match The resulting frame interval closest to @p desired
785  */
786 void video_closest_frmival_stepwise(const struct video_frmival_stepwise *stepwise,
787 				    const struct video_frmival *desired,
788 				    struct video_frmival *match);
789 
790 /**
791  * @brief Find the closest match to a frame interval value within a video device.
792  *
793  * To compute the closest match, fill @p match with the following fields:
794  *
795  * - @c match->format to the @ref video_format of interest.
796  * - @c match->type to @ref VIDEO_FRMIVAL_TYPE_DISCRETE.
797  * - @c match->discrete to the desired frame interval.
798  *
799  * The result will be loaded into @p match, with the following fields set:
800  *
801  * - @c match->discrete to the value of the closest frame interval.
802  * - @c match->index to the index of the closest frame interval.
803  *
804  * @param dev Video device to query.
805  * @param ep Video endpoint ID to query.
806  * @param match Frame interval enumerator with the query, and loaded with the result.
807  */
808 void video_closest_frmival(const struct device *dev, enum video_endpoint_id ep,
809 			   struct video_frmival_enum *match);
810 
811 /**
812  * @defgroup video_pixel_formats Video pixel formats
813  * The @c | characters separate the pixels, and spaces separate the bytes.
814  * The uppercase letter represents the most significant bit.
815  * The lowercase letters represent the rest of the bits.
816  * @{
817  */
818 
819 /**
820  * @brief Four-character-code uniquely identifying the pixel format
821  */
822 #define VIDEO_FOURCC(a, b, c, d)                                                                   \
823 	((uint32_t)(a) | ((uint32_t)(b) << 8) | ((uint32_t)(c) << 16) | ((uint32_t)(d) << 24))
824 
825 /**
826  * @brief Convert a four-character-string to a four-character-code
827  *
828  * Convert a string literal or variable into a four-character-code
829  * as defined by @ref VIDEO_FOURCC.
830  *
831  * @param str String to be converted
832  * @return Four-character-code.
833  */
834 #define VIDEO_FOURCC_FROM_STR(str) VIDEO_FOURCC((str)[0], (str)[1], (str)[2], (str)[3])
835 
836 /**
837  * @brief Convert a four-character-code to a four-character-string
838  *
839  * Convert a four-character code as defined by @ref VIDEO_FOURCC into a string that can be used
840  * anywhere, such as in debug logs with the %s print formatter.
841  *
842  * @param fourcc The 32-bit four-character-code integer to be converted, in CPU-native endinaness.
843  * @return Four-character-string built out of it.
844  */
845 #define VIDEO_FOURCC_TO_STR(fourcc)                                                                \
846 	((char[]){                                                                                 \
847 		(char)((fourcc) & 0xFF),                                                           \
848 		(char)(((fourcc) >> 8) & 0xFF),                                                    \
849 		(char)(((fourcc) >> 16) & 0xFF),                                                   \
850 		(char)(((fourcc) >> 24) & 0xFF),                                                   \
851 		'\0'                                                                               \
852 	})
853 
854 /**
855  * @name Bayer formats (R, G, B channels).
856  *
857  * The full color information is spread over multiple pixels.
858  *
859  * @{
860  */
861 
862 /**
863  * @verbatim
864  * | Bbbbbbbb | Gggggggg | Bbbbbbbb | Gggggggg | Bbbbbbbb | Gggggggg | ...
865  * | Gggggggg | Rrrrrrrr | Gggggggg | Rrrrrrrr | Gggggggg | Rrrrrrrr | ...
866  * @endverbatim
867  */
868 #define VIDEO_PIX_FMT_BGGR8 VIDEO_FOURCC('B', 'A', '8', '1')
869 
870 /**
871  * @verbatim
872  * | Gggggggg | Bbbbbbbb | Gggggggg | Bbbbbbbb | Gggggggg | Bbbbbbbb | ...
873  * | Rrrrrrrr | Gggggggg | Rrrrrrrr | Gggggggg | Rrrrrrrr | Gggggggg | ...
874  * @endverbatim
875  */
876 #define VIDEO_PIX_FMT_GBRG8 VIDEO_FOURCC('G', 'B', 'R', 'G')
877 
878 /**
879  * @verbatim
880  * | Gggggggg | Rrrrrrrr | Gggggggg | Rrrrrrrr | Gggggggg | Rrrrrrrr | ...
881  * | Bbbbbbbb | Gggggggg | Bbbbbbbb | Gggggggg | Bbbbbbbb | Gggggggg | ...
882  * @endverbatim
883  */
884 #define VIDEO_PIX_FMT_GRBG8 VIDEO_FOURCC('G', 'R', 'B', 'G')
885 
886 /**
887  * @verbatim
888  * | Rrrrrrrr | Gggggggg | Rrrrrrrr | Gggggggg | Rrrrrrrr | Gggggggg | ...
889  * | Gggggggg | Bbbbbbbb | Gggggggg | Bbbbbbbb | Gggggggg | Bbbbbbbb | ...
890  * @endverbatim
891  */
892 #define VIDEO_PIX_FMT_RGGB8 VIDEO_FOURCC('R', 'G', 'G', 'B')
893 
894 /**
895  * @}
896  */
897 
898 /**
899  * @name RGB formats
900  * Per-color (R, G, B) channels.
901  * @{
902  */
903 
904 /**
905  * 5 red bits [15:11], 6 green bits [10:5], 5 blue bits [4:0].
906  * This 16-bit integer is then packed in big endian format over two bytes:
907  *
908  * @verbatim
909  *   15.....8 7......0
910  * | RrrrrGgg gggBbbbb | ...
911  * @endverbatim
912  */
913 #define VIDEO_PIX_FMT_RGB565X VIDEO_FOURCC('R', 'G', 'B', 'R')
914 
915 /**
916  * 5 red bits [15:11], 6 green bits [10:5], 5 blue bits [4:0].
917  * This 16-bit integer is then packed in little endian format over two bytes:
918  *
919  * @verbatim
920  *   7......0 15.....8
921  * | gggBbbbb RrrrrGgg | ...
922  * @endverbatim
923  */
924 #define VIDEO_PIX_FMT_RGB565 VIDEO_FOURCC('R', 'G', 'B', 'P')
925 
926 /**
927  * The first byte is empty (X) for each pixel.
928  *
929  * @verbatim
930  * | Xxxxxxxx Rrrrrrrr Gggggggg Bbbbbbbb | ...
931  * @endverbatim
932  */
933 #define VIDEO_PIX_FMT_XRGB32 VIDEO_FOURCC('B', 'X', '2', '4')
934 
935 /**
936  * @}
937  */
938 
939 /**
940  * @name YUV formats
941  * Luminance (Y) and chrominance (U, V) channels.
942  * @{
943  */
944 
945 /**
946  * There is either a missing channel per pixel, U or V.
947  * The value is to be averaged over 2 pixels to get the value of individual pixel.
948  *
949  * @verbatim
950  * | Yyyyyyyy Uuuuuuuu | Yyyyyyyy Vvvvvvvv | ...
951  * @endverbatim
952  */
953 #define VIDEO_PIX_FMT_YUYV VIDEO_FOURCC('Y', 'U', 'Y', 'V')
954 
955 /**
956  * The first byte is empty (X) for each pixel.
957  *
958  * @verbatim
959  * | Xxxxxxxx Yyyyyyyy Uuuuuuuu Vvvvvvvv | ...
960  * @endverbatim
961  */
962 #define VIDEO_PIX_FMT_XYUV32 VIDEO_FOURCC('X', 'Y', 'U', 'V')
963 
964 /**
965  * @}
966  */
967 
968 /**
969  * @name Compressed formats
970  * @{
971  */
972 
973 /**
974  * Both JPEG (single frame) and Motion-JPEG (MJPEG, multiple JPEG frames concatenated)
975  */
976 #define VIDEO_PIX_FMT_JPEG VIDEO_FOURCC('J', 'P', 'E', 'G')
977 
978 /**
979  * @}
980  */
981 
982 /**
983  * @brief Get number of bits per pixel of a pixel format
984  *
985  * @param pixfmt FourCC pixel format value (@ref video_pixel_formats).
986  *
987  * @retval 0 if the format is unhandled or if it is variable number of bits
988  * @retval bit size of one pixel for this format
989  */
video_bits_per_pixel(uint32_t pixfmt)990 static inline unsigned int video_bits_per_pixel(uint32_t pixfmt)
991 {
992 	switch (pixfmt) {
993 	case VIDEO_PIX_FMT_BGGR8:
994 	case VIDEO_PIX_FMT_GBRG8:
995 	case VIDEO_PIX_FMT_GRBG8:
996 	case VIDEO_PIX_FMT_RGGB8:
997 		return 8;
998 	case VIDEO_PIX_FMT_RGB565:
999 	case VIDEO_PIX_FMT_YUYV:
1000 		return 16;
1001 	case VIDEO_PIX_FMT_XRGB32:
1002 	case VIDEO_PIX_FMT_XYUV32:
1003 		return 32;
1004 	default:
1005 		/* Variable number of bits per pixel or unknown format */
1006 		return 0;
1007 	}
1008 }
1009 
1010 /**
1011  * @}
1012  */
1013 
1014 #ifdef __cplusplus
1015 }
1016 #endif
1017 
1018 /**
1019  * @}
1020  */
1021 
1022 #endif /* ZEPHYR_INCLUDE_VIDEO_H_ */
1023