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