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_stream_start(const struct device * dev)136 static int video_esp32_stream_start(const struct device *dev)
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 (data->is_streaming) {
147 return -EBUSY;
148 }
149
150 LOG_DBG("Start streaming");
151
152 error = dma_get_status(cfg->dma_dev, cfg->rx_dma_channel, &dma_status);
153
154 if (error) {
155 LOG_ERR("Unable to get Rx status (%d)", error);
156 return error;
157 }
158
159 if (dma_status.busy) {
160 LOG_ERR("Rx DMA Channel %d is busy", cfg->rx_dma_channel);
161 return -EBUSY;
162 }
163
164 data->active_vbuf = k_fifo_get(&data->fifo_in, K_NO_WAIT);
165 if (!data->active_vbuf) {
166 LOG_ERR("No enqueued video buffers available.");
167 return -EAGAIN;
168 }
169
170 buffer_size = data->active_vbuf->bytesused;
171 memset(data->dma_blocks, 0, sizeof(data->dma_blocks));
172 for (int i = 0; i < CONFIG_DMA_ESP32_MAX_DESCRIPTOR_NUM; ++i) {
173 dma_block_iter->dest_address =
174 (uint32_t)data->active_vbuf->buffer + (i * VIDEO_ESP32_DMA_BUFFER_MAX_SIZE);
175 if (buffer_size < VIDEO_ESP32_DMA_BUFFER_MAX_SIZE) {
176 dma_block_iter->block_size = buffer_size;
177 dma_block_iter->next_block = NULL;
178 dma_cfg.block_count = i + 1;
179 break;
180 }
181 dma_block_iter->block_size = VIDEO_ESP32_DMA_BUFFER_MAX_SIZE;
182 dma_block_iter->next_block = dma_block_iter + 1;
183 dma_block_iter++;
184 buffer_size -= VIDEO_ESP32_DMA_BUFFER_MAX_SIZE;
185 }
186
187 if (dma_block_iter->next_block) {
188 LOG_ERR("Not enough descriptors available. Increase "
189 "CONFIG_DMA_ESP32_MAX_DESCRIPTOR_NUM");
190 return -ENOBUFS;
191 }
192
193 dma_cfg.channel_direction = PERIPHERAL_TO_MEMORY;
194 dma_cfg.dma_callback = video_esp32_dma_rx_done;
195 dma_cfg.user_data = data;
196 dma_cfg.dma_slot = SOC_GDMA_TRIG_PERIPH_CAM0;
197 dma_cfg.complete_callback_en = 1;
198 dma_cfg.head_block = &data->dma_blocks[0];
199
200 error = dma_config(cfg->dma_dev, cfg->rx_dma_channel, &dma_cfg);
201 if (error) {
202 LOG_ERR("Unable to configure DMA (%d)", error);
203 return error;
204 }
205
206 error = dma_start(cfg->dma_dev, cfg->rx_dma_channel);
207 if (error) {
208 LOG_ERR("Unable to start DMA (%d)", error);
209 return error;
210 }
211
212 cam_hal_start_streaming(&data->hal);
213
214 if (video_stream_start(cfg->source_dev)) {
215 return -EIO;
216 }
217 data->is_streaming = true;
218
219 return 0;
220 }
221
video_esp32_stream_stop(const struct device * dev)222 static int video_esp32_stream_stop(const struct device *dev)
223 {
224 const struct video_esp32_config *cfg = dev->config;
225 struct video_esp32_data *data = dev->data;
226 int ret = 0;
227
228 LOG_DBG("Stop streaming");
229
230 if (video_stream_stop(cfg->source_dev)) {
231 return -EIO;
232 }
233
234 data->is_streaming = false;
235 ret = dma_stop(cfg->dma_dev, cfg->rx_dma_channel);
236 if (ret) {
237 LOG_ERR("Unable to stop DMA (%d)", ret);
238 return ret;
239 }
240
241 cam_hal_stop_streaming(&data->hal);
242 return 0;
243 }
244
video_esp32_get_caps(const struct device * dev,enum video_endpoint_id ep,struct video_caps * caps)245 static int video_esp32_get_caps(const struct device *dev, enum video_endpoint_id ep,
246 struct video_caps *caps)
247 {
248 const struct video_esp32_config *config = dev->config;
249
250 if (ep != VIDEO_EP_OUT) {
251 return -EINVAL;
252 }
253
254 /* ESP32 produces full frames */
255 caps->min_line_count = caps->max_line_count = LINE_COUNT_HEIGHT;
256
257 /* Forward the message to the source device */
258 return video_get_caps(config->source_dev, ep, caps);
259 }
260
video_esp32_get_fmt(const struct device * dev,enum video_endpoint_id ep,struct video_format * fmt)261 static int video_esp32_get_fmt(const struct device *dev, enum video_endpoint_id ep,
262 struct video_format *fmt)
263 {
264 const struct video_esp32_config *cfg = dev->config;
265 int ret = 0;
266
267 LOG_DBG("Get format");
268
269 if (fmt == NULL || ep != VIDEO_EP_OUT) {
270 return -EINVAL;
271 }
272
273 ret = video_get_format(cfg->source_dev, ep, fmt);
274 if (ret) {
275 LOG_ERR("Failed to get format from source");
276 return ret;
277 }
278
279 return 0;
280 }
281
video_esp32_set_fmt(const struct device * dev,enum video_endpoint_id ep,struct video_format * fmt)282 static int video_esp32_set_fmt(const struct device *dev, enum video_endpoint_id ep,
283 struct video_format *fmt)
284 {
285 const struct video_esp32_config *cfg = dev->config;
286 struct video_esp32_data *data = dev->data;
287
288 if (fmt == NULL || ep != VIDEO_EP_OUT) {
289 return -EINVAL;
290 }
291
292 data->video_format = *fmt;
293
294 return video_set_format(cfg->source_dev, ep, fmt);
295 }
296
video_esp32_enqueue(const struct device * dev,enum video_endpoint_id ep,struct video_buffer * vbuf)297 static int video_esp32_enqueue(const struct device *dev, enum video_endpoint_id ep,
298 struct video_buffer *vbuf)
299 {
300 struct video_esp32_data *data = dev->data;
301
302 if (ep != VIDEO_EP_OUT) {
303 return -EINVAL;
304 }
305
306 vbuf->bytesused = data->video_format.pitch * data->video_format.height;
307 vbuf->line_offset = 0;
308
309 k_fifo_put(&data->fifo_in, vbuf);
310
311 return 0;
312 }
313
video_esp32_dequeue(const struct device * dev,enum video_endpoint_id ep,struct video_buffer ** vbuf,k_timeout_t timeout)314 static int video_esp32_dequeue(const struct device *dev, enum video_endpoint_id ep,
315 struct video_buffer **vbuf, k_timeout_t timeout)
316 {
317 struct video_esp32_data *data = dev->data;
318
319 if (ep != VIDEO_EP_OUT) {
320 return -EINVAL;
321 }
322
323 *vbuf = k_fifo_get(&data->fifo_out, timeout);
324 LOG_DBG("Dequeue done, vbuf = %p", *vbuf);
325 if (*vbuf == NULL) {
326 return -EAGAIN;
327 }
328
329 return 0;
330 }
331
video_esp32_set_ctrl(const struct device * dev,unsigned int cid,void * value)332 static int video_esp32_set_ctrl(const struct device *dev, unsigned int cid, void *value)
333 {
334 const struct video_esp32_config *cfg = dev->config;
335
336 return video_set_ctrl(cfg->source_dev, cid, value);
337 }
338
video_esp32_get_ctrl(const struct device * dev,unsigned int cid,void * value)339 static int video_esp32_get_ctrl(const struct device *dev, unsigned int cid, void *value)
340 {
341 const struct video_esp32_config *cfg = dev->config;
342
343 return video_get_ctrl(cfg->source_dev, cid, value);
344 }
345
346 #ifdef CONFIG_POLL
video_esp32_set_signal(const struct device * dev,enum video_endpoint_id ep,struct k_poll_signal * sig)347 int video_esp32_set_signal(const struct device *dev, enum video_endpoint_id ep,
348 struct k_poll_signal *sig)
349 {
350 struct video_esp32_data *data = dev->data;
351
352 if (ep != VIDEO_EP_OUT && ep != VIDEO_EP_ALL) {
353 LOG_ERR("Invalid endpoint id");
354 return -EINVAL;
355 }
356 data->signal_out = sig;
357 return 0;
358 }
359 #endif
360
video_esp32_cam_ctrl_init(const struct device * dev)361 static void video_esp32_cam_ctrl_init(const struct device *dev)
362 {
363 const struct video_esp32_config *cfg = dev->config;
364 struct video_esp32_data *data = dev->data;
365
366 const cam_hal_config_t hal_cfg = {
367 .port = 0,
368 .byte_swap_en = cfg->invert_byte_order,
369 };
370
371 cam_hal_init(&data->hal, &hal_cfg);
372
373 cam_ll_reverse_dma_data_bit_order(data->hal.hw, cfg->invert_bit_order);
374 cam_ll_enable_invert_pclk(data->hal.hw, cfg->invert_pclk);
375 cam_ll_set_input_data_width(data->hal.hw, cfg->data_width);
376 cam_ll_enable_invert_de(data->hal.hw, cfg->invert_de);
377 cam_ll_enable_invert_vsync(data->hal.hw, cfg->invert_vsync);
378 cam_ll_enable_invert_hsync(data->hal.hw, cfg->invert_hsync);
379 }
380
video_esp32_init(const struct device * dev)381 static int video_esp32_init(const struct device *dev)
382 {
383 const struct video_esp32_config *cfg = dev->config;
384 struct video_esp32_data *data = dev->data;
385
386 k_fifo_init(&data->fifo_in);
387 k_fifo_init(&data->fifo_out);
388 data->config = cfg;
389 video_esp32_cam_ctrl_init(dev);
390
391 if (!device_is_ready(cfg->dma_dev)) {
392 LOG_ERR("DMA device not ready");
393 return -ENODEV;
394 }
395
396 return 0;
397 }
398
399 static DEVICE_API(video, esp32_driver_api) = {
400 /* mandatory callbacks */
401 .set_format = video_esp32_set_fmt,
402 .get_format = video_esp32_get_fmt,
403 .stream_start = video_esp32_stream_start,
404 .stream_stop = video_esp32_stream_stop,
405 .get_caps = video_esp32_get_caps,
406 /* optional callbacks */
407 .enqueue = video_esp32_enqueue,
408 .dequeue = video_esp32_dequeue,
409 .flush = NULL,
410 .set_ctrl = video_esp32_set_ctrl,
411 .get_ctrl = video_esp32_get_ctrl,
412 #ifdef CONFIG_POLL
413 .set_signal = video_esp32_set_signal,
414 #endif
415 };
416
417 PINCTRL_DT_INST_DEFINE(0);
418
419 static const struct video_esp32_config esp32_config = {
420 .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(0),
421 .source_dev = DEVICE_DT_GET(DT_INST_PHANDLE(0, source)),
422 .dma_dev = ESP32_DT_INST_DMA_CTLR(0, rx),
423 .rx_dma_channel = DT_INST_DMAS_CELL_BY_NAME(0, rx, channel),
424 .data_width = DT_INST_PROP_OR(0, data_width, 8),
425 .invert_bit_order = DT_INST_PROP(0, invert_bit_order),
426 .invert_byte_order = DT_INST_PROP(0, invert_byte_order),
427 .invert_pclk = DT_INST_PROP(0, invert_pclk),
428 .invert_de = DT_INST_PROP(0, invert_de),
429 .invert_hsync = DT_INST_PROP(0, invert_hsync),
430 .invert_vsync = DT_INST_PROP(0, invert_vsync),
431 .cam_clk = DT_INST_PROP_OR(0, cam_clk, 0),
432 .clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(0)),
433 .clock_subsys = (clock_control_subsys_t)DT_INST_CLOCKS_CELL(0, offset),
434 };
435
436 static struct video_esp32_data esp32_data = {0};
437
438 DEVICE_DT_INST_DEFINE(0, video_esp32_init, NULL, &esp32_data, &esp32_config, POST_KERNEL,
439 CONFIG_VIDEO_INIT_PRIORITY, &esp32_driver_api);
440
video_esp32_cam_init_master_clock(void)441 static int video_esp32_cam_init_master_clock(void)
442 {
443 int ret = 0;
444
445 ret = pinctrl_apply_state(esp32_config.pcfg, PINCTRL_STATE_DEFAULT);
446 if (ret < 0) {
447 printk("video pinctrl setup failed (%d)", ret);
448 return ret;
449 }
450
451 /* Enable peripheral */
452 if (!device_is_ready(esp32_config.clock_dev)) {
453 return -ENODEV;
454 }
455
456 clock_control_on(esp32_config.clock_dev, esp32_config.clock_subsys);
457
458 if (!esp32_config.cam_clk) {
459 printk("No cam_clk specified\n");
460 return -EINVAL;
461 }
462
463 if (ESP32_CLK_CPU_PLL_160M % esp32_config.cam_clk) {
464 printk("Invalid cam_clk value. It must be a divisor of 160M\n");
465 return -EINVAL;
466 }
467
468 /* Enable camera master clock output */
469 cam_ll_select_clk_src(0, LCD_CLK_SRC_PLL160M);
470 cam_ll_set_group_clock_coeff(0, ESP32_CLK_CPU_PLL_160M / esp32_config.cam_clk, 0, 0);
471
472 return 0;
473 }
474
475 SYS_INIT(video_esp32_cam_init_master_clock, PRE_KERNEL_2, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
476