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