Skip to content

Commit d9db3cb

Browse files
committed
[WIP]drivers: video: Implement buffer management with RTIO backend
- Application side nearly unchanged, except a call to video_release_buf() after finishing with the full buffer to queue it back to sqe. RTIO is opaque to application. - Driver just needs to hold an io_q and deal a bit with the buffer from sqe in isr. No need to implement rtio_iodev_api's submit() - The video subsystem does everything needed for buffer management. Signed-off-by: Phi Bang Nguyen <[email protected]> Co-developed-by: Josuah Demangeon <[email protected]>
1 parent c8d7560 commit d9db3cb

File tree

7 files changed

+124
-184
lines changed

7 files changed

+124
-184
lines changed

drivers/video/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#
99
menuconfig VIDEO
1010
bool "Video drivers"
11+
imply RTIO
1112
help
1213
Enable support for the VIDEO.
1314

drivers/video/video_common.c

Lines changed: 59 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,12 @@
1313
#include <zephyr/drivers/video-controls.h>
1414
#include <zephyr/kernel.h>
1515
#include <zephyr/logging/log.h>
16+
#include <zephyr/rtio/rtio.h>
1617
#include <zephyr/sys/byteorder.h>
1718
#include <zephyr/sys/util.h>
1819

1920
#include "video_common.h"
21+
#include "video_device.h"
2022

2123
LOG_MODULE_REGISTER(video_common, CONFIG_VIDEO_LOG_LEVEL);
2224

@@ -125,24 +127,73 @@ int video_request_buffers(uint8_t count, size_t size, enum video_buf_type type)
125127
return 0;
126128
}
127129

130+
RTIO_DEFINE(rtio, CONFIG_VIDEO_BUFFER_POOL_NUM_MAX, CONFIG_VIDEO_BUFFER_POOL_NUM_MAX);
131+
128132
int video_enqueue(const struct device *dev, uint8_t index)
129133
{
130-
const struct video_driver_api *api = (const struct video_driver_api *)dev->api;
131-
132134
__ASSERT_NO_MSG(dev != NULL);
133135

134-
api = (const struct video_driver_api *)dev->api;
135-
if (api->enqueue == NULL) {
136-
return -ENOSYS;
137-
}
138-
139136
if (video_buf[index].state != VIDEO_BUF_STATE_DONE) {
140137
return -EINVAL;
141138
}
142139

143140
video_buf[index].state = VIDEO_BUF_STATE_QUEUED;
144141

145-
return api->enqueue(dev, &video_buf[index]);
142+
/* RTIO submission */
143+
struct rtio_iodev *ri = video_find_iodev(dev);
144+
struct rtio_sqe *sqe = rtio_sqe_acquire(&rtio);
145+
146+
__ASSERT_NO_MSG(ri != NULL);
147+
__ASSERT_NO_MSG(sqe != NULL);
148+
149+
rtio_sqe_prep_read(sqe, ri, RTIO_PRIO_NORM, video_buf[index].buffer,
150+
video_buf[index].size, &video_buf[index]);
151+
152+
sqe->flags |= RTIO_SQE_MULTISHOT;
153+
154+
/* Do not wait for complete */
155+
rtio_submit(&rtio, 0);
156+
157+
return 0;
158+
}
159+
160+
int video_dequeue(struct video_buffer **buf)
161+
{
162+
struct rtio_cqe *cqe = rtio_cqe_consume_block(&rtio);
163+
*buf = cqe->userdata;
164+
165+
if (cqe->result < 0) {
166+
LOG_ERR("I/O operation failed");
167+
return cqe->result;
168+
}
169+
170+
return 0;
171+
}
172+
173+
void video_release_buf()
174+
{
175+
/* Buffer will be re-queued thanks to RTIO_SQE_MULTISHOT */
176+
rtio_cqe_release(&rtio, rtio_cqe_consume_block(&rtio));
177+
}
178+
179+
struct video_buffer *video_get_buf_sqe(struct mpsc *io_q)
180+
{
181+
struct mpsc_node *node = mpsc_pop(io_q);
182+
if (node == NULL) {
183+
return NULL;
184+
}
185+
186+
struct rtio_iodev_sqe *iodev_sqe = CONTAINER_OF(node, struct rtio_iodev_sqe, q);
187+
struct rtio_sqe *sqe = &iodev_sqe->sqe;
188+
189+
if (sqe->op != RTIO_OP_RX) {
190+
LOG_ERR("Invalid operation %d of length %u for submission %p", sqe->op,
191+
sqe->rx.buf_len, (void *)iodev_sqe);
192+
rtio_iodev_sqe_err(iodev_sqe, -EINVAL);
193+
return NULL;
194+
}
195+
196+
return sqe->userdata;
146197
}
147198

148199
int video_format_caps_index(const struct video_format_cap *fmts, const struct video_format *fmt,

drivers/video/video_device.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
* SPDX-License-Identifier: Apache-2.0
55
*/
66

7+
#include <zephyr/rtio/rtio.h>
8+
79
#include "video_device.h"
810

911
struct video_device *video_find_vdev(const struct device *dev)
@@ -20,3 +22,32 @@ struct video_device *video_find_vdev(const struct device *dev)
2022

2123
return NULL;
2224
}
25+
26+
struct rtio_iodev *video_find_iodev(const struct device *dev)
27+
{
28+
struct video_interface *vi;
29+
30+
if (!dev) {
31+
return NULL;
32+
}
33+
34+
STRUCT_SECTION_FOREACH(rtio_iodev, ri) {
35+
vi = ri->data;
36+
if (vi->dev == dev) {
37+
return ri;
38+
}
39+
}
40+
41+
return NULL;
42+
}
43+
44+
static void video_iodev_submit(struct rtio_iodev_sqe *iodev_sqe)
45+
{
46+
struct video_interface *vi = iodev_sqe->sqe.iodev->data;
47+
48+
mpsc_push(vi->io_q, &iodev_sqe->q);
49+
}
50+
51+
const struct rtio_iodev_api _video_iodev_api = {
52+
.submit = video_iodev_submit,
53+
};

drivers/video/video_device.h

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#define ZEPHYR_INCLUDE_DRIVERS_VIDEO_VIDEO_DEVICE_H_
99

1010
#include <zephyr/device.h>
11+
#include <zephyr/rtio/rtio.h>
1112
#include <zephyr/sys/dlist.h>
1213

1314
struct video_device {
@@ -18,20 +19,28 @@ struct video_device {
1819

1920
struct video_interface {
2021
const struct device *dev;
22+
struct mpsc *io_q;
2123
};
2224

25+
extern const struct rtio_iodev_api _video_iodev_api;
26+
2327
#define VIDEO_DEVICE_DEFINE(name, device, source) \
2428
static STRUCT_SECTION_ITERABLE(video_device, name) = { \
2529
.dev = device, \
2630
.src_dev = source, \
2731
.ctrls = SYS_DLIST_STATIC_INIT(&name.ctrls), \
2832
}
2933

30-
#define VIDEO_INTERFACE_DEFINE(name, device) \
31-
static STRUCT_SECTION_ITERABLE(video_interface, name) = { \
34+
#define VIDEO_INTERFACE_DEFINE(name, device, io_queue) \
35+
static STRUCT_SECTION_ITERABLE(video_interface, name) = { \
3236
.dev = device, \
33-
}
37+
.io_q = io_queue, \
38+
}; \
39+
RTIO_IODEV_DEFINE(name##_iodev, &_video_iodev_api, &name)
3440

3541
struct video_device *video_find_vdev(const struct device *dev);
42+
struct rtio_iodev *video_find_iodev(const struct device *dev);
43+
44+
struct video_buffer *video_get_buf_sqe(struct mpsc *io_q);
3645

3746
#endif /* ZEPHYR_INCLUDE_DRIVERS_VIDEO_VIDEO_DEVICE_H_ */

0 commit comments

Comments
 (0)