1 /*
2 * Copyright (c) 2024 espros photonics Co.
3 * Copyright (c) 2024 Espressif Systems (Shanghai) CO LTD.
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8 #define DT_DRV_COMPAT espressif_esp32_lcd_cam
9
10 #include <soc/gdma_channel.h>
11 #include <zephyr/device.h>
12 #include <zephyr/drivers/clock_control.h>
13 #include <zephyr/drivers/clock_control/esp32_clock_control.h>
14 #include <zephyr/drivers/dma.h>
15 #include <zephyr/drivers/dma/dma_esp32.h>
16 #include <zephyr/drivers/pinctrl.h>
17 #include <zephyr/drivers/video.h>
18 #include <zephyr/drivers/interrupt_controller/intc_esp32.h>
19 #include <zephyr/kernel.h>
20 #include <hal/cam_hal.h>
21 #include <hal/cam_ll.h>
22
23 #include <zephyr/logging/log.h>
24 LOG_MODULE_REGISTER(video_esp32_lcd_cam, CONFIG_VIDEO_LOG_LEVEL);
25
26 #define VIDEO_ESP32_DMA_BUFFER_MAX_SIZE 4095
27 #define VIDEO_ESP32_VSYNC_MASK 0x04
28
29 #ifdef CONFIG_POLL
30 #define VIDEO_ESP32_RAISE_OUT_SIG_IF_ENABLED(result) \
31 if (data->signal_out) { \
32 k_poll_signal_raise(data->signal_out, result); \
33 }
34 #else
35 #define VIDEO_ESP32_RAISE_OUT_SIG_IF_ENABLED(result)
36 #endif
37
38 enum video_esp32_cam_clk_sel_values {
39 VIDEO_ESP32_CAM_CLK_SEL_NONE = 0,
40 VIDEO_ESP32_CAM_CLK_SEL_XTAL = 1,
41 VIDEO_ESP32_CAM_CLK_SEL_PLL_DIV2 = 2,
42 VIDEO_ESP32_CAM_CLK_SEL_PLL_F160M = 3,
43 };
44
45 struct video_esp32_config {
46 const struct pinctrl_dev_config *pcfg;
47 const struct device *clock_dev;
48 const clock_control_subsys_t clock_subsys;
49 const struct device *dma_dev;
50 const struct device *source_dev;
51 uint32_t cam_clk;
52 uint8_t rx_dma_channel;
53 uint8_t data_width;
54 uint8_t invert_de;
55 uint8_t invert_byte_order;
56 uint8_t invert_bit_order;
57 uint8_t invert_pclk;
58 uint8_t invert_hsync;
59 uint8_t invert_vsync;
60 };
61
62 struct video_esp32_data {
63 cam_hal_context_t hal;
64 const struct video_esp32_config *config;
65 struct video_format video_format;
66 struct video_buffer *active_vbuf;
67 bool is_streaming;
68 struct k_fifo fifo_in;
69 struct k_fifo fifo_out;
70 struct dma_block_config dma_blocks[CONFIG_DMA_ESP32_MAX_DESCRIPTOR_NUM];
71 #ifdef CONFIG_POLL
72 struct k_poll_signal *signal_out;
73 #endif
74 };
75
video_esp32_reload_dma(struct video_esp32_data * data)76 static int video_esp32_reload_dma(struct video_esp32_data *data)
77 {
78 const struct video_esp32_config *cfg = data->config;
79 int ret = 0;
80
81 if (data->active_vbuf == NULL) {
82 LOG_ERR("No video buffer available. Enqueue some buffers first.");
83 return -EAGAIN;
84 }
85
86 ret = dma_reload(cfg->dma_dev, cfg->rx_dma_channel, 0, (uint32_t)data->active_vbuf->buffer,
87 data->active_vbuf->bytesused);
88 if (ret) {
89 LOG_ERR("Unable to reload DMA (%d)", ret);
90 return ret;
91 }
92
93 ret = dma_start(cfg->dma_dev, cfg->rx_dma_channel);
94 if (ret) {
95 LOG_ERR("Unable to start DMA (%d)", ret);
96 return ret;
97 }
98
99 return 0;
100 }
101
video_esp32_dma_rx_done(const struct device * dev,void * user_data,uint32_t channel,int status)102 void video_esp32_dma_rx_done(const struct device *dev, void *user_data, uint32_t channel,
103 int status)
104 {
105 struct video_esp32_data *data = user_data;
106
107 if (status == DMA_STATUS_BLOCK) {
108 LOG_DBG("received block");
109 return;
110 }
111
112 if (status != DMA_STATUS_COMPLETE) {
113 VIDEO_ESP32_RAISE_OUT_SIG_IF_ENABLED(VIDEO_BUF_ERROR)
114 LOG_ERR("DMA error: %d", status);
115 return;
116 }
117
118 if (data->active_vbuf == NULL) {
119 VIDEO_ESP32_RAISE_OUT_SIG_IF_ENABLED(VIDEO_BUF_ERROR)
120 LOG_ERR("No video buffer available. Enque some buffers first.");
121 return;
122 }
123
124 k_fifo_put(&data->fifo_out, data->active_vbuf);
125 VIDEO_ESP32_RAISE_OUT_SIG_IF_ENABLED(VIDEO_BUF_DONE)
126 data->active_vbuf = k_fifo_get(&data->fifo_in, K_NO_WAIT);
127
128 if (data->active_vbuf == NULL) {
129 LOG_WRN("Frame dropped. No buffer available");
130 VIDEO_ESP32_RAISE_OUT_SIG_IF_ENABLED(VIDEO_BUF_ERROR)
131 return;
132 }
133 video_esp32_reload_dma(data);
134 }
135
video_esp32_set_stream(const struct device * dev,bool enable)136 static int video_esp32_set_stream(const struct device *dev, bool enable)
137 {
138 const struct video_esp32_config *cfg = dev->config;
139 struct video_esp32_data *data = dev->data;
140 struct dma_status dma_status = {0};
141 struct dma_config dma_cfg = {0};
142 struct dma_block_config *dma_block_iter = data->dma_blocks;
143 uint32_t buffer_size = 0;
144 int error = 0;
145
146 if (!enable) {
147 LOG_DBG("Stop streaming");
148
149 if (video_stream_stop(cfg->source_dev)) {
150 return -EIO;
151 }
152
153 data->is_streaming = false;
154 error = dma_stop(cfg->dma_dev, cfg->rx_dma_channel);
155 if (error) {
156 LOG_ERR("Unable to stop DMA (%d)", error);
157 return error;
158 }
159
160 cam_hal_stop_streaming(&data->hal);
161
162 return 0;
163 }
164
165 if (data->is_streaming) {
166 return -EBUSY;
167 }
168
169 LOG_DBG("Start streaming");
170
171 error = dma_get_status(cfg->dma_dev, cfg->rx_dma_channel, &dma_status);
172
173 if (error) {
174 LOG_ERR("Unable to get Rx status (%d)", error);
175 return error;
176 }
177
178 if (dma_status.busy) {
179 LOG_ERR("Rx DMA Channel %d is busy", cfg->rx_dma_channel);
180 return -EBUSY;
181 }
182
183 data->active_vbuf = k_fifo_get(&data->fifo_in, K_NO_WAIT);
184 if (!data->active_vbuf) {
185 LOG_ERR("No enqueued video buffers available.");
186 return -EAGAIN;
187 }
188
189 buffer_size = data->active_vbuf->bytesused;
190 memset(data->dma_blocks, 0, sizeof(data->dma_blocks));
191 for (int i = 0; i < CONFIG_DMA_ESP32_MAX_DESCRIPTOR_NUM; ++i) {
192 dma_block_iter->dest_address =
193 (uint32_t)data->active_vbuf->buffer + (i * VIDEO_ESP32_DMA_BUFFER_MAX_SIZE);
194 if (buffer_size < VIDEO_ESP32_DMA_BUFFER_MAX_SIZE) {
195 dma_block_iter->block_size = buffer_size;
196 dma_block_iter->next_block = NULL;
197 dma_cfg.block_count = i + 1;
198 break;
199 }
200 dma_block_iter->block_size = VIDEO_ESP32_DMA_BUFFER_MAX_SIZE;
201 dma_block_iter->next_block = dma_block_iter + 1;
202 dma_block_iter++;
203 buffer_size -= VIDEO_ESP32_DMA_BUFFER_MAX_SIZE;
204 }
205
206 if (dma_block_iter->next_block) {
207 LOG_ERR("Not enough descriptors available. Increase "
208 "CONFIG_DMA_ESP32_MAX_DESCRIPTOR_NUM");
209 return -ENOBUFS;
210 }
211
212 dma_cfg.channel_direction = PERIPHERAL_TO_MEMORY;
213 dma_cfg.dma_callback = video_esp32_dma_rx_done;
214 dma_cfg.user_data = data;
215 dma_cfg.dma_slot = SOC_GDMA_TRIG_PERIPH_CAM0;
216 dma_cfg.complete_callback_en = 1;
217 dma_cfg.head_block = &data->dma_blocks[0];
218
219 error = dma_config(cfg->dma_dev, cfg->rx_dma_channel, &dma_cfg);
220 if (error) {
221 LOG_ERR("Unable to configure DMA (%d)", error);
222 return error;
223 }
224
225 error = dma_start(cfg->dma_dev, cfg->rx_dma_channel);
226 if (error) {
227 LOG_ERR("Unable to start DMA (%d)", error);
228 return error;
229 }
230
231 cam_hal_start_streaming(&data->hal);
232
233 if (video_stream_start(cfg->source_dev)) {
234 return -EIO;
235 }
236 data->is_streaming = true;
237
238 return 0;
239 }
240
video_esp32_get_caps(const struct device * dev,enum video_endpoint_id ep,struct video_caps * caps)241 static int video_esp32_get_caps(const struct device *dev, enum video_endpoint_id ep,
242 struct video_caps *caps)
243 {
244 const struct video_esp32_config *config = dev->config;
245
246 if (ep != VIDEO_EP_OUT) {
247 return -EINVAL;
248 }
249
250 /* ESP32 produces full frames */
251 caps->min_line_count = caps->max_line_count = LINE_COUNT_HEIGHT;
252
253 /* Forward the message to the source device */
254 return video_get_caps(config->source_dev, ep, caps);
255 }
256
video_esp32_get_fmt(const struct device * dev,enum video_endpoint_id ep,struct video_format * fmt)257 static int video_esp32_get_fmt(const struct device *dev, enum video_endpoint_id ep,
258 struct video_format *fmt)
259 {
260 const struct video_esp32_config *cfg = dev->config;
261 int ret = 0;
262
263 LOG_DBG("Get format");
264
265 if (fmt == NULL || ep != VIDEO_EP_OUT) {
266 return -EINVAL;
267 }
268
269 ret = video_get_format(cfg->source_dev, ep, fmt);
270 if (ret) {
271 LOG_ERR("Failed to get format from source");
272 return ret;
273 }
274
275 return 0;
276 }
277
video_esp32_set_fmt(const struct device * dev,enum video_endpoint_id ep,struct video_format * fmt)278 static int video_esp32_set_fmt(const struct device *dev, enum video_endpoint_id ep,
279 struct video_format *fmt)
280 {
281 const struct video_esp32_config *cfg = dev->config;
282 struct video_esp32_data *data = dev->data;
283
284 if (fmt == NULL || ep != VIDEO_EP_OUT) {
285 return -EINVAL;
286 }
287
288 data->video_format = *fmt;
289
290 return video_set_format(cfg->source_dev, ep, fmt);
291 }
292
video_esp32_enqueue(const struct device * dev,enum video_endpoint_id ep,struct video_buffer * vbuf)293 static int video_esp32_enqueue(const struct device *dev, enum video_endpoint_id ep,
294 struct video_buffer *vbuf)
295 {
296 struct video_esp32_data *data = dev->data;
297
298 if (ep != VIDEO_EP_OUT) {
299 return -EINVAL;
300 }
301
302 vbuf->bytesused = data->video_format.pitch * data->video_format.height;
303 vbuf->line_offset = 0;
304
305 k_fifo_put(&data->fifo_in, vbuf);
306
307 return 0;
308 }
309
video_esp32_dequeue(const struct device * dev,enum video_endpoint_id ep,struct video_buffer ** vbuf,k_timeout_t timeout)310 static int video_esp32_dequeue(const struct device *dev, enum video_endpoint_id ep,
311 struct video_buffer **vbuf, k_timeout_t timeout)
312 {
313 struct video_esp32_data *data = dev->data;
314
315 if (ep != VIDEO_EP_OUT) {
316 return -EINVAL;
317 }
318
319 *vbuf = k_fifo_get(&data->fifo_out, timeout);
320 LOG_DBG("Dequeue done, vbuf = %p", *vbuf);
321 if (*vbuf == NULL) {
322 return -EAGAIN;
323 }
324
325 return 0;
326 }
327
video_esp32_set_ctrl(const struct device * dev,unsigned int cid,void * value)328 static int video_esp32_set_ctrl(const struct device *dev, unsigned int cid, void *value)
329 {
330 const struct video_esp32_config *cfg = dev->config;
331
332 return video_set_ctrl(cfg->source_dev, cid, value);
333 }
334
video_esp32_get_ctrl(const struct device * dev,unsigned int cid,void * value)335 static int video_esp32_get_ctrl(const struct device *dev, unsigned int cid, void *value)
336 {
337 const struct video_esp32_config *cfg = dev->config;
338
339 return video_get_ctrl(cfg->source_dev, cid, value);
340 }
341
video_esp32_flush(const struct device * dev,enum video_endpoint_id ep,bool cancel)342 static int video_esp32_flush(const struct device *dev, enum video_endpoint_id ep, bool cancel)
343 {
344 struct video_esp32_data *data = dev->data;
345 struct video_buffer *vbuf = NULL;
346
347 if (cancel) {
348 if (data->is_streaming) {
349 video_esp32_set_stream(dev, false);
350 }
351 if (data->active_vbuf) {
352 k_fifo_put(&data->fifo_out, data->active_vbuf);
353 data->active_vbuf = NULL;
354 }
355 while ((vbuf = k_fifo_get(&data->fifo_in, K_NO_WAIT)) != NULL) {
356 k_fifo_put(&data->fifo_out, vbuf);
357 #ifdef CONFIG_POLL
358 if (data->signal_out) {
359 k_poll_signal_raise(data->signal_out, VIDEO_BUF_ABORTED);
360 }
361 #endif
362 }
363 } else {
364 while (!k_fifo_is_empty(&data->fifo_in)) {
365 k_sleep(K_MSEC(1));
366 }
367 }
368
369 return 0;
370 }
371
372 #ifdef CONFIG_POLL
video_esp32_set_signal(const struct device * dev,enum video_endpoint_id ep,struct k_poll_signal * sig)373 int video_esp32_set_signal(const struct device *dev, enum video_endpoint_id ep,
374 struct k_poll_signal *sig)
375 {
376 struct video_esp32_data *data = dev->data;
377
378 if (ep != VIDEO_EP_OUT && ep != VIDEO_EP_ALL) {
379 LOG_ERR("Invalid endpoint id");
380 return -EINVAL;
381 }
382 data->signal_out = sig;
383 return 0;
384 }
385 #endif
386
video_esp32_cam_ctrl_init(const struct device * dev)387 static void video_esp32_cam_ctrl_init(const struct device *dev)
388 {
389 const struct video_esp32_config *cfg = dev->config;
390 struct video_esp32_data *data = dev->data;
391
392 const cam_hal_config_t hal_cfg = {
393 .port = 0,
394 .byte_swap_en = cfg->invert_byte_order,
395 };
396
397 cam_hal_init(&data->hal, &hal_cfg);
398
399 cam_ll_reverse_dma_data_bit_order(data->hal.hw, cfg->invert_bit_order);
400 cam_ll_enable_invert_pclk(data->hal.hw, cfg->invert_pclk);
401 cam_ll_set_input_data_width(data->hal.hw, cfg->data_width);
402 cam_ll_enable_invert_de(data->hal.hw, cfg->invert_de);
403 cam_ll_enable_invert_vsync(data->hal.hw, cfg->invert_vsync);
404 cam_ll_enable_invert_hsync(data->hal.hw, cfg->invert_hsync);
405 }
406
video_esp32_init(const struct device * dev)407 static int video_esp32_init(const struct device *dev)
408 {
409 const struct video_esp32_config *cfg = dev->config;
410 struct video_esp32_data *data = dev->data;
411
412 k_fifo_init(&data->fifo_in);
413 k_fifo_init(&data->fifo_out);
414 data->config = cfg;
415 video_esp32_cam_ctrl_init(dev);
416
417 if (!device_is_ready(cfg->dma_dev)) {
418 LOG_ERR("DMA device not ready");
419 return -ENODEV;
420 }
421
422 return 0;
423 }
424
425 static DEVICE_API(video, esp32_driver_api) = {
426 /* mandatory callbacks */
427 .set_format = video_esp32_set_fmt,
428 .get_format = video_esp32_get_fmt,
429 .set_stream = video_esp32_set_stream,
430 .get_caps = video_esp32_get_caps,
431 /* optional callbacks */
432 .enqueue = video_esp32_enqueue,
433 .dequeue = video_esp32_dequeue,
434 .flush = video_esp32_flush,
435 .set_ctrl = video_esp32_set_ctrl,
436 .get_ctrl = video_esp32_get_ctrl,
437 #ifdef CONFIG_POLL
438 .set_signal = video_esp32_set_signal,
439 #endif
440 };
441
442 PINCTRL_DT_INST_DEFINE(0);
443
444 static const struct video_esp32_config esp32_config = {
445 .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(0),
446 .source_dev = DEVICE_DT_GET(DT_INST_PHANDLE(0, source)),
447 .dma_dev = ESP32_DT_INST_DMA_CTLR(0, rx),
448 .rx_dma_channel = DT_INST_DMAS_CELL_BY_NAME(0, rx, channel),
449 .data_width = DT_INST_PROP_OR(0, data_width, 8),
450 .invert_bit_order = DT_INST_PROP(0, invert_bit_order),
451 .invert_byte_order = DT_INST_PROP(0, invert_byte_order),
452 .invert_pclk = DT_INST_PROP(0, invert_pclk),
453 .invert_de = DT_INST_PROP(0, invert_de),
454 .invert_hsync = DT_INST_PROP(0, invert_hsync),
455 .invert_vsync = DT_INST_PROP(0, invert_vsync),
456 .cam_clk = DT_INST_PROP_OR(0, cam_clk, 0),
457 .clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(0)),
458 .clock_subsys = (clock_control_subsys_t)DT_INST_CLOCKS_CELL(0, offset),
459 };
460
461 static struct video_esp32_data esp32_data = {0};
462
463 DEVICE_DT_INST_DEFINE(0, video_esp32_init, NULL, &esp32_data, &esp32_config, POST_KERNEL,
464 CONFIG_VIDEO_INIT_PRIORITY, &esp32_driver_api);
465
video_esp32_cam_init_master_clock(void)466 static int video_esp32_cam_init_master_clock(void)
467 {
468 int ret = 0;
469
470 ret = pinctrl_apply_state(esp32_config.pcfg, PINCTRL_STATE_DEFAULT);
471 if (ret < 0) {
472 printk("video pinctrl setup failed (%d)", ret);
473 return ret;
474 }
475
476 /* Enable peripheral */
477 if (!device_is_ready(esp32_config.clock_dev)) {
478 return -ENODEV;
479 }
480
481 clock_control_on(esp32_config.clock_dev, esp32_config.clock_subsys);
482
483 if (!esp32_config.cam_clk) {
484 printk("No cam_clk specified\n");
485 return -EINVAL;
486 }
487
488 if (ESP32_CLK_CPU_PLL_160M % esp32_config.cam_clk) {
489 printk("Invalid cam_clk value. It must be a divisor of 160M\n");
490 return -EINVAL;
491 }
492
493 /* Enable camera master clock output */
494 cam_ll_select_clk_src(0, LCD_CLK_SRC_PLL160M);
495 cam_ll_set_group_clock_coeff(0, ESP32_CLK_CPU_PLL_160M / esp32_config.cam_clk, 0, 0);
496
497 return 0;
498 }
499
500 SYS_INIT(video_esp32_cam_init_master_clock, PRE_KERNEL_2, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
501