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  * @ingroup io_interfaces
19  * @{
20  */
21 
22 #include <device.h>
23 #include <stddef.h>
24 #include <zephyr.h>
25 
26 #include <zephyr/types.h>
27 
28 #include <drivers/video-controls.h>
29 
30 #ifdef __cplusplus
31 extern "C" {
32 #endif
33 
34 
35 /**
36  * @brief video format structure
37  *
38  * Used to configure frame format.
39  *
40  * @param pixelformat is the fourcc pixel format value.
41  * @param width is the frame width in pixels.
42  * @param height is the frame height in pixels.
43  * @param pitch is the line stride, the number of bytes that needs to be added
44  *    to the address in the first pixel of a row in order to go to the address
45  *    of the first pixel of the next row (>=width).
46  */
47 struct video_format {
48 	uint32_t pixelformat;
49 	uint32_t width;
50 	uint32_t height;
51 	uint32_t pitch;
52 };
53 
54 /**
55  * @brief video format capability
56  *
57  * Used to describe a video endpoint format capability.
58  *
59  * @param pixelformat is a list of supported pixel formats (0 terminated).
60  * @param width_min is the minimum supported frame width.
61  * @param width_max is the maximum supported frame width.
62  * @param height_min is the minimum supported frame width.
63  * @param height_max is the maximum supported frame width.
64  * @param width_step is the width step size.
65  * @param height_step is the height step size.
66  */
67 struct video_format_cap {
68 	uint32_t pixelformat;
69 	uint32_t width_min;
70 	uint32_t width_max;
71 	uint32_t height_min;
72 	uint32_t height_max;
73 	uint16_t width_step;
74 	uint16_t height_step;
75 };
76 
77 /**
78  * @brief video capabilities
79  *
80  * Used to describe video endpoint capabilities.
81  *
82  * @param format_caps is a list of video format capabilities (zero terminated).
83  * @param min_vbuf_count is the minimal count of video buffers to enqueue
84  *    before being able to start the stream.
85  */
86 struct video_caps {
87 	const struct video_format_cap *format_caps;
88 	uint8_t min_vbuf_count;
89 };
90 
91 /**
92  * @brief video buffer structure
93  *
94  * Represent a video frame.
95  *
96  * @param driver_data is a pointer to driver specific data.
97  * @param buffer is a pointer to the start of the buffer.
98  * @param size is the size in bytes of the buffer.
99  * @param bytesused is the number of bytes occupied by the valid data in
100  *        the buffer.
101  * @param timestamp is a time reference in milliseconds at which the last data
102  *        byte was actually received for input endpoints or to be consumed for
103  *        output endpoints.
104  */
105 struct video_buffer {
106 	void *driver_data;
107 	uint8_t *buffer;
108 	uint32_t size;
109 	uint32_t bytesused;
110 	uint32_t timestamp;
111 };
112 
113 /**
114  * @brief video_endpoint_id enum
115  * Identify the video device endpoint.
116  */
117 enum video_endpoint_id {
118 	VIDEO_EP_NONE,
119 	VIDEO_EP_ANY,
120 	VIDEO_EP_IN,
121 	VIDEO_EP_OUT,
122 };
123 
124 /**
125  * @brief video_event enum
126  * Identify video event.
127  */
128 enum video_signal_result {
129 	VIDEO_BUF_DONE,
130 	VIDEO_BUF_ABORTED,
131 	VIDEO_BUF_ERROR,
132 };
133 
134 /**
135  * @typedef video_api_set_format_t
136  * @brief Set video format
137  * See video_set_format() for argument descriptions.
138  */
139 typedef int (*video_api_set_format_t)(const struct device *dev,
140 				      enum video_endpoint_id ep,
141 				      struct video_format *fmt);
142 
143 /**
144  * @typedef video_api_get_format_t
145  * @brief get current video format
146  * See video_get_format() for argument descriptions.
147  */
148 typedef int (*video_api_get_format_t)(const struct device *dev,
149 				      enum video_endpoint_id ep,
150 				      struct video_format *fmt);
151 
152 /**
153  * @typedef video_api_enqueue_t
154  * @brief Enqueue a buffer in the driver’s incoming queue.
155  * See video_enqueue() for argument descriptions.
156  */
157 typedef int (*video_api_enqueue_t)(const struct device *dev,
158 				   enum video_endpoint_id ep,
159 				   struct video_buffer *buf);
160 
161 /**
162  * @typedef video_api_dequeue_t
163  * @brief Dequeue a buffer from the driver’s outgoing queue.
164  * See video_dequeue() for argument descriptions.
165  */
166 typedef int (*video_api_dequeue_t)(const struct device *dev,
167 				   enum video_endpoint_id ep,
168 				   struct video_buffer **buf,
169 				   k_timeout_t timeout);
170 
171 /**
172  * @typedef video_api_flush_t
173  * @brief Flush endpoint buffers, buffer are moved from incoming queue to
174  *        outgoing queue.
175  * See video_flush() for argument descriptions.
176  */
177 typedef int (*video_api_flush_t)(const struct device *dev,
178 				 enum video_endpoint_id ep,
179 				 bool cancel);
180 
181 /**
182  * @typedef video_api_stream_start_t
183  * @brief Start the capture or output process.
184  * See video_stream_start() for argument descriptions.
185  */
186 typedef int (*video_api_stream_start_t)(const struct device *dev);
187 
188 /**
189  * @typedef video_api_stream_stop_t
190  * @brief Stop the capture or output process.
191  * See video_stream_stop() for argument descriptions.
192  */
193 typedef int (*video_api_stream_stop_t)(const struct device *dev);
194 
195 /**
196  * @typedef video_api_set_ctrl_t
197  * @brief set a video control value.
198  * See video_set_ctrl() for argument descriptions.
199  */
200 typedef int (*video_api_set_ctrl_t)(const struct device *dev,
201 				    unsigned int cid,
202 				    void *value);
203 
204 /**
205  * @typedef video_api_get_ctrl_t
206  * @brief get a video control value.
207  * See video_get_ctrl() for argument descriptions.
208  */
209 typedef int (*video_api_get_ctrl_t)(const struct device *dev,
210 				    unsigned int cid,
211 				    void *value);
212 
213 /**
214  * @typedef video_api_get_caps_t
215  * @brief Get capabilities of a video endpoint.
216  * See video_get_caps() for argument descriptions.
217  */
218 typedef int (*video_api_get_caps_t)(const struct device *dev,
219 				    enum video_endpoint_id ep,
220 				    struct video_caps *caps);
221 
222 /**
223  * @typedef video_api_set_signal_t
224  * @brief Register/Unregister poll signal for buffer events.
225  * See video_set_signal() for argument descriptions.
226  */
227 typedef int (*video_api_set_signal_t)(const struct device *dev,
228 				      enum video_endpoint_id ep,
229 				      struct k_poll_signal *signal);
230 
231 struct video_driver_api {
232 	/* mandatory callbacks */
233 	video_api_set_format_t set_format;
234 	video_api_get_format_t get_format;
235 	video_api_stream_start_t stream_start;
236 	video_api_stream_stop_t stream_stop;
237 	video_api_get_caps_t get_caps;
238 	/* optional callbacks */
239 	video_api_enqueue_t enqueue;
240 	video_api_dequeue_t dequeue;
241 	video_api_flush_t flush;
242 	video_api_set_ctrl_t set_ctrl;
243 	video_api_set_ctrl_t get_ctrl;
244 	video_api_set_signal_t set_signal;
245 };
246 
247 /**
248  * @brief Set video format.
249  *
250  * Configure video device with a specific format.
251  *
252  * @param dev Pointer to the device structure for the driver instance.
253  * @param ep Endpoint ID.
254  * @param fmt Pointer to a video format struct.
255  *
256  * @retval 0 Is successful.
257  * @retval -EINVAL If parameters are invalid.
258  * @retval -ENOTSUP If format is not supported.
259  * @retval -EIO General input / output error.
260  */
video_set_format(const struct device * dev,enum video_endpoint_id ep,struct video_format * fmt)261 static inline int video_set_format(const struct device *dev,
262 				   enum video_endpoint_id ep,
263 				   struct video_format *fmt)
264 {
265 	const struct video_driver_api *api =
266 		(const struct video_driver_api *)dev->api;
267 
268 	if (api->set_format == NULL) {
269 		return -ENOSYS;
270 	}
271 
272 	return api->set_format(dev, ep, fmt);
273 }
274 
275 /**
276  * @brief Get video format.
277  *
278  * Get video device current video format.
279  *
280  * @param dev Pointer to the device structure for the driver instance.
281  * @param ep Endpoint ID.
282  * @param fmt Pointer to video format struct.
283  *
284  * @retval pointer to video format
285  */
video_get_format(const struct device * dev,enum video_endpoint_id ep,struct video_format * fmt)286 static inline int video_get_format(const struct device *dev,
287 				   enum video_endpoint_id ep,
288 				   struct video_format *fmt)
289 {
290 	const struct video_driver_api *api =
291 		(const struct video_driver_api *)dev->api;
292 
293 	if (api->get_format == NULL) {
294 		return -ENOSYS;
295 	}
296 
297 	return api->get_format(dev, ep, fmt);
298 }
299 
300 /**
301  * @brief Enqueue a video buffer.
302  *
303  * Enqueue an empty (capturing) or filled (output) video buffer in the driver’s
304  * endpoint incoming queue.
305  *
306  * @param dev Pointer to the device structure for the driver instance.
307  * @param ep Endpoint ID.
308  * @param buf Pointer to the video buffer.
309  *
310  * @retval 0 Is successful.
311  * @retval -EINVAL If parameters are invalid.
312  * @retval -EIO General input / output error.
313  */
video_enqueue(const struct device * dev,enum video_endpoint_id ep,struct video_buffer * buf)314 static inline int video_enqueue(const struct device *dev,
315 				enum video_endpoint_id ep,
316 				struct video_buffer *buf)
317 {
318 	const struct video_driver_api *api =
319 		(const struct video_driver_api *)dev->api;
320 
321 	if (api->enqueue == NULL) {
322 		return -ENOSYS;
323 	}
324 
325 	return api->enqueue(dev, ep, buf);
326 }
327 
328 /**
329  * @brief Dequeue a video buffer.
330  *
331  * Dequeue a filled (capturing) or displayed (output) buffer from the driver’s
332  * enpoint outgoing queue.
333  *
334  * @param dev Pointer to the device structure for the driver instance.
335  * @param ep Endpoint ID.
336  * @param buf Pointer a video buffer pointer.
337  * @param timeout Timeout
338  *
339  * @retval 0 Is successful.
340  * @retval -EINVAL If parameters are invalid.
341  * @retval -EIO General input / output error.
342  */
video_dequeue(const struct device * dev,enum video_endpoint_id ep,struct video_buffer ** buf,k_timeout_t timeout)343 static inline int video_dequeue(const struct device *dev,
344 				enum video_endpoint_id ep,
345 				struct video_buffer **buf,
346 				k_timeout_t timeout)
347 {
348 	const struct video_driver_api *api =
349 		(const struct video_driver_api *)dev->api;
350 
351 	if (api->dequeue == NULL) {
352 		return -ENOSYS;
353 	}
354 
355 	return api->dequeue(dev, ep, buf, timeout);
356 }
357 
358 
359 /**
360  * @brief Flush endpoint buffers.
361  *
362  * A call to flush finishes when all endpoint buffers have been moved from
363  * incoming queue to outgoing queue. Either because canceled or fully processed
364  * through the video function.
365  *
366  * @param dev Pointer to the device structure for the driver instance.
367  * @param ep Endpoint ID.
368  * @param cancel If true, cancel buffer processing instead of waiting for
369  *        completion.
370  *
371  * @retval 0 Is successful, -ERRNO code otherwise.
372  */
video_flush(const struct device * dev,enum video_endpoint_id ep,bool cancel)373 static inline int video_flush(const struct device *dev,
374 			      enum video_endpoint_id ep,
375 			      bool cancel)
376 {
377 	const struct video_driver_api *api =
378 		(const struct video_driver_api *)dev->api;
379 
380 	if (api->flush == NULL) {
381 		return -ENOSYS;
382 	}
383 
384 	return api->flush(dev, ep, cancel);
385 }
386 
387 /**
388  * @brief Start the video device function.
389  *
390  * video_stream_start is called to enter ‘streaming’ state (capture, output...).
391  * The driver may receive buffers with video_enqueue() before video_stream_start
392  * is called. If driver/device needs a minimum number of buffers before being
393  * able to start streaming, then driver set the min_vbuf_count to the related
394  * endpoint capabilities.
395  *
396  * @retval 0 Is successful.
397  * @retval -EIO General input / output error.
398  */
video_stream_start(const struct device * dev)399 static inline int video_stream_start(const struct device *dev)
400 {
401 	const struct video_driver_api *api =
402 		(const struct video_driver_api *)dev->api;
403 
404 	if (api->stream_start == NULL) {
405 		return -ENOSYS;
406 	}
407 
408 	return api->stream_start(dev);
409 }
410 
411 /**
412  * @brief Stop the video device function.
413  *
414  * On video_stream_stop, driver must stop any transactions or wait until they
415  * finish.
416  *
417  * @retval 0 Is successful.
418  * @retval -EIO General input / output error.
419  */
video_stream_stop(const struct device * dev)420 static inline int video_stream_stop(const struct device *dev)
421 {
422 	const struct video_driver_api *api =
423 		(const struct video_driver_api *)dev->api;
424 	int ret;
425 
426 	if (api->stream_stop) {
427 		return -ENOSYS;
428 	}
429 
430 	ret = api->stream_stop(dev);
431 	video_flush(dev, VIDEO_EP_ANY, true);
432 
433 	return ret;
434 }
435 
436 /**
437  * @brief Get the capabilities of a video endpoint.
438  *
439  * @param dev Pointer to the device structure for the driver instance.
440  * @param ep Endpoint ID.
441  * @param caps Pointer to the video_caps struct to fill.
442  *
443  * @retval 0 Is successful, -ERRNO code otherwise.
444  */
video_get_caps(const struct device * dev,enum video_endpoint_id ep,struct video_caps * caps)445 static inline int video_get_caps(const struct device *dev,
446 				 enum video_endpoint_id ep,
447 				 struct video_caps *caps)
448 {
449 	const struct video_driver_api *api =
450 		(const struct video_driver_api *)dev->api;
451 
452 	if (api->get_caps == NULL) {
453 		return -ENOSYS;
454 	}
455 
456 	return api->get_caps(dev, ep, caps);
457 }
458 
459 /**
460  * @brief Set the value of a control.
461  *
462  * This set the value of a video control, value type depends on control ID, and
463  * must be interpreted accordingly.
464  *
465  * @param dev Pointer to the device structure for the driver instance.
466  * @param cid Control ID.
467  * @param value Pointer to the control value.
468  *
469  * @retval 0 Is successful.
470  * @retval -EINVAL If parameters are invalid.
471  * @retval -ENOTSUP If format is not supported.
472  * @retval -EIO General input / output error.
473  */
video_set_ctrl(const struct device * dev,unsigned int cid,void * value)474 static inline int video_set_ctrl(const struct device *dev, unsigned int cid,
475 				 void *value)
476 {
477 	const struct video_driver_api *api =
478 		(const struct video_driver_api *)dev->api;
479 
480 	if (api->set_ctrl == NULL) {
481 		return -ENOSYS;
482 	}
483 
484 	return api->set_ctrl(dev, cid, value);
485 }
486 
487 /**
488  * @brief Get the current value of a control.
489  *
490  * This retrieve the value of a video control, value type depends on control ID,
491  * and must be interpreted accordingly.
492  *
493  * @param dev Pointer to the device structure for the driver instance.
494  * @param cid Control ID.
495  * @param value Pointer to the control value.
496  *
497  * @retval 0 Is successful.
498  * @retval -EINVAL If parameters are invalid.
499  * @retval -ENOTSUP If format is not supported.
500  * @retval -EIO General input / output error.
501  */
video_get_ctrl(const struct device * dev,unsigned int cid,void * value)502 static inline int video_get_ctrl(const struct device *dev, unsigned int cid,
503 				 void *value)
504 {
505 	const struct video_driver_api *api =
506 		(const struct video_driver_api *)dev->api;
507 
508 	if (api->get_ctrl == NULL) {
509 		return -ENOSYS;
510 	}
511 
512 	return api->get_ctrl(dev, cid, value);
513 }
514 
515 /**
516  * @brief Register/Unregister k_poll signal for a video endpoint.
517  *
518  * Register a poll signal to the endpoint, which will be signaled on frame
519  * completion (done, aborted, error). Registering a NULL poll signal
520  * unregisters any previously registered signal.
521  *
522  * @param dev Pointer to the device structure for the driver instance.
523  * @param ep Endpoint ID.
524  * @param signal Pointer to k_poll_signal
525  *
526  * @retval 0 Is successful, -ERRNO code otherwise.
527  */
video_set_signal(const struct device * dev,enum video_endpoint_id ep,struct k_poll_signal * signal)528 static inline int video_set_signal(const struct device *dev,
529 				   enum video_endpoint_id ep,
530 				   struct k_poll_signal *signal)
531 {
532 	const struct video_driver_api *api =
533 		(const struct video_driver_api *)dev->api;
534 
535 	if (api->set_signal == NULL) {
536 		return -ENOSYS;
537 	}
538 
539 	return api->set_signal(dev, ep, signal);
540 }
541 
542 /**
543  * @brief Allocate video buffer.
544  *
545  * @param size Size of the video buffer.
546  *
547  * @retval pointer to allocated video buffer
548  */
549 struct video_buffer *video_buffer_alloc(size_t size);
550 
551 /**
552  * @brief Release a video buffer.
553  *
554  * @param buf Pointer to the video buffer to release.
555  */
556 void video_buffer_release(struct video_buffer *buf);
557 
558 
559 /* fourcc - four-character-code */
560 #define video_fourcc(a, b, c, d)\
561 	((uint32_t)(a) | ((uint32_t)(b) << 8) | ((uint32_t)(c) << 16) | ((uint32_t)(d) << 24))
562 
563 /* Raw bayer formats */
564 #define VIDEO_PIX_FMT_BGGR8  video_fourcc('B', 'G', 'G', 'R') /*  8  BGBG.. GRGR.. */
565 #define VIDEO_PIX_FMT_GBRG8  video_fourcc('G', 'B', 'R', 'G') /*  8  GBGB.. RGRG.. */
566 #define VIDEO_PIX_FMT_GRBG8  video_fourcc('G', 'R', 'B', 'G') /*  8  GRGR.. BGBG.. */
567 #define VIDEO_PIX_FMT_RGGB8  video_fourcc('R', 'G', 'G', 'B') /*  8  RGRG.. GBGB.. */
568 
569 /* RGB formats */
570 #define VIDEO_PIX_FMT_RGB565 video_fourcc('R', 'G', 'B', 'P') /* 16  RGB-5-6-5 */
571 
572 /* JPEG formats */
573 #define VIDEO_PIX_FMT_JPEG   video_fourcc('J', 'P', 'E', 'G') /*  8  JPEG */
574 
575 #ifdef __cplusplus
576 }
577 #endif
578 
579 /**
580  * @}
581  */
582 
583 #endif /* ZEPHYR_INCLUDE_VIDEO_H_ */
584