1 /*
2 * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6 #pragma once
7
8 #include <stdbool.h>
9 #include "hal/misc.h"
10 #include "hal/assert.h"
11 #include "soc/lcd_cam_struct.h"
12 #include "soc/system_struct.h"
13 #include "hal/cam_types.h"
14
15 #ifdef __cplusplus
16 extern "C" {
17 #endif
18
19 #define CAM_LL_GET_HW(id) (((id) == 0) ? (&LCD_CAM) : NULL)
20
21 #define CAM_LL_CLK_FRAC_DIV_N_MAX 256 // CAM_CLK = CAM_CLK_S / (N + b/a), the N register is 8 bit-width
22 #define CAM_LL_CLK_FRAC_DIV_AB_MAX 64 // CAM_CLK = CAM_CLK_S / (N + b/a), the a/b register is 6 bit-width
23
24 /**
25 * @brief Enable the bus clock for CAM module
26 *
27 * @param group_id Group ID
28 * @param enable true to enable, false to disable
29 */
cam_ll_enable_bus_clock(int group_id,bool en)30 static inline void cam_ll_enable_bus_clock(int group_id, bool en)
31 {
32 (void)group_id;
33 SYSTEM.perip_clk_en1.lcd_cam_clk_en = en;
34 }
35
36 /// use a macro to wrap the function, force the caller to use it in a critical section
37 /// the critical section needs to declare the __DECLARE_RCC_RC_ATOMIC_ENV variable in advance
38 #define cam_ll_enable_bus_clock(...) (void)__DECLARE_RCC_RC_ATOMIC_ENV; cam_ll_enable_bus_clock(__VA_ARGS__)
39
40 /**
41 * @brief Reset the CAM module
42 *
43 * @param group_id Group ID
44 */
cam_ll_reset_register(int group_id)45 static inline void cam_ll_reset_register(int group_id)
46 {
47 (void)group_id;
48 SYSTEM.perip_rst_en1.lcd_cam_rst = 0x01;
49 SYSTEM.perip_rst_en1.lcd_cam_rst = 0x00;
50 }
51
52 /// use a macro to wrap the function, force the caller to use it in a critical section
53 /// the critical section needs to declare the __DECLARE_RCC_RC_ATOMIC_ENV variable in advance
54 #define cam_ll_reset_register(...) (void)__DECLARE_RCC_RC_ATOMIC_ENV; cam_ll_reset_register(__VA_ARGS__)
55
56 /**
57 * @brief Enable clock gating
58 *
59 * @param group_id Group ID
60 * @param en True to enable, False to disable
61 */
cam_ll_enable_clk(int group_id,bool en)62 static inline void cam_ll_enable_clk(int group_id, bool en)
63 {
64 (void)group_id;
65 LCD_CAM.lcd_clock.clk_en = en;
66 }
67
68 /// use a macro to wrap the function, force the caller to use it in a critical section
69 /// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
70 #define cam_ll_enable_clk(...) (void)__DECLARE_RCC_ATOMIC_ENV; cam_ll_enable_clk(__VA_ARGS__)
71
72 /**
73 * @brief Get the clock status for the CAM module
74 *
75 * @return True when enabled, false when disabled
76 */
cam_ll_get_clk_status(int group_id)77 static inline bool cam_ll_get_clk_status(int group_id)
78 {
79 (void)group_id;
80 return LCD_CAM.lcd_clock.clk_en;
81 }
82
83 /// use a macro to wrap the function, force the caller to use it in a critical section
84 /// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
85 #define cam_ll_get_clk_status(...) (void)__DECLARE_RCC_ATOMIC_ENV; cam_ll_get_clk_status(__VA_ARGS__)
86
87 /**
88 * @brief Select clock source for CAM peripheral
89 *
90 * @param group_id Group ID
91 * @param src Clock source
92 */
cam_ll_select_clk_src(int group_id,cam_clock_source_t src)93 static inline void cam_ll_select_clk_src(int group_id, cam_clock_source_t src)
94 {
95 switch (src) {
96 case LCD_CLK_SRC_PLL160M:
97 LCD_CAM.cam_ctrl.cam_clk_sel = 3;
98 break;
99 case LCD_CLK_SRC_PLL240M:
100 LCD_CAM.cam_ctrl.cam_clk_sel = 2;
101 break;
102 case LCD_CLK_SRC_XTAL:
103 LCD_CAM.cam_ctrl.cam_clk_sel = 1;
104 break;
105 default:
106 // disable LCD clock source
107 LCD_CAM.cam_ctrl.cam_clk_sel = 0;
108 HAL_ASSERT(false);
109 break;
110 }
111 }
112
113 /// use a macro to wrap the function, force the caller to use it in a critical section
114 /// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
115 // #define cam_ll_select_clk_src(...) (void)__DECLARE_RCC_ATOMIC_ENV; cam_ll_select_clk_src(__VA_ARGS__)
116
117 /**
118 * @brief Get the CAM source clock type
119 *
120 * @param dev CAM register base address
121 * @param src The pointer to accept the CAM source clock type
122 */
cam_ll_get_clk_src(lcd_cam_dev_t * dev,cam_clock_source_t * src)123 static inline void cam_ll_get_clk_src(lcd_cam_dev_t *dev, cam_clock_source_t *src)
124 {
125 switch (LCD_CAM.cam_ctrl.cam_clk_sel) {
126 case 1:
127 *src = LCD_CLK_SRC_XTAL;
128 break;
129 case 2:
130 *src = LCD_CLK_SRC_PLL240M;
131 break;
132 case 3:
133 *src = LCD_CLK_SRC_PLL160M;
134 break;
135 default:
136 HAL_ASSERT(false);
137 break;
138 }
139 }
140
141 /**
142 * @brief Set clock coefficient of CAM peripheral
143 *
144 * @param group_id Group ID
145 * @param div_num Integer part of the divider
146 * @param div_a denominator of the divider
147 * @param div_b numerator of the divider
148 */
149 __attribute__((always_inline))
cam_ll_set_group_clock_coeff(int group_id,int div_num,int div_a,int div_b)150 static inline void cam_ll_set_group_clock_coeff(int group_id, int div_num, int div_a, int div_b)
151 {
152 // cam_clk = module_clock_src / (div_num + div_b / div_a)
153 HAL_ASSERT(div_num >= 2 && div_num < CAM_LL_CLK_FRAC_DIV_N_MAX);
154
155 HAL_FORCE_MODIFY_U32_REG_FIELD(LCD_CAM.cam_ctrl, cam_clkm_div_num, div_num);
156 LCD_CAM.cam_ctrl.cam_clkm_div_a = div_a;
157 LCD_CAM.cam_ctrl.cam_clkm_div_b = div_b;
158
159 }
160
161 /// use a macro to wrap the function, force the caller to use it in a critical section
162 /// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
163 // #define cam_ll_set_group_clock_coeff(...) (void)__DECLARE_RCC_ATOMIC_ENV; cam_ll_set_group_clock_coeff(__VA_ARGS__)
164
165 /**
166 * @brief Enable stop signal for CAM peripheral
167 *
168 * @param dev CAM register base address
169 * @param en True to stop when GDMA Rx FIFO is full, False to not stop
170 */
cam_ll_enable_stop_signal(lcd_cam_dev_t * dev,bool en)171 static inline void cam_ll_enable_stop_signal(lcd_cam_dev_t *dev, bool en)
172 {
173 dev->cam_ctrl.cam_stop_en = en;
174 }
175
176 /**
177 * @brief Set vsync filter threshold value
178 *
179 * @param dev CAM register base address
180 * @param value Filter threshold value for CAM_VSYNC_SIGNAL, range [0, 7]
181 */
cam_ll_set_vsync_filter_thres(lcd_cam_dev_t * dev,uint32_t value)182 static inline void cam_ll_set_vsync_filter_thres(lcd_cam_dev_t *dev, uint32_t value)
183 {
184 dev->cam_ctrl.cam_vsync_filter_thres = value;
185 }
186
187 /**
188 * @brief Enable to generate LCD_CAM_CAM_HS_INT
189 *
190 * @param dev CAM register base address
191 * @param en True to enable to generate LCD_CAM_CAM_HS_INT, False to disable
192 */
cam_ll_enable_hs_line_int(lcd_cam_dev_t * dev,bool en)193 static inline void cam_ll_enable_hs_line_int(lcd_cam_dev_t *dev, bool en)
194 {
195 dev->cam_ctrl.cam_line_int_en = en;
196 }
197
198 /**
199 * @brief Enable CAM_VSYNC to generate in_suc_eof
200 *
201 * @param dev CAM register base address
202 * @param en True to enable CAM_VSYNC to generate in_suc_eof, False to use LCD_CAM_CAM_REC_DATA_BYTELEN to control in_suc_eof
203 */
cam_ll_enable_vsync_generate_eof(lcd_cam_dev_t * dev,bool en)204 static inline void cam_ll_enable_vsync_generate_eof(lcd_cam_dev_t *dev, bool en)
205 {
206 dev->cam_ctrl.cam_vs_eof_en = en;
207 }
208
209 /**
210 * @brief Enable to swap every two 8-bit input data
211 *
212 * @param dev CAM register base address
213 * @param en True to enable invert, False to disable invert
214 */
cam_ll_enable_8bits_data_invert(lcd_cam_dev_t * dev,bool en)215 static inline void cam_ll_enable_8bits_data_invert(lcd_cam_dev_t *dev, bool en)
216 {
217 dev->cam_rgb_yuv.cam_conv_8bits_data_inv = en;
218 }
219
220 /**
221 * @brief Enable YUV-RGB converter
222 *
223 * @param dev CAM register base address
224 * @param en True to enable converter, False to disable converter
225 */
cam_ll_enable_rgb_yuv_convert(lcd_cam_dev_t * dev,bool en)226 static inline void cam_ll_enable_rgb_yuv_convert(lcd_cam_dev_t *dev, bool en)
227 {
228 dev->cam_rgb_yuv.cam_conv_bypass = en;
229 }
230
231 /**
232 * @brief Set convert data line width
233 *
234 * @param dev CAM register base address
235 * @param width data line width (8 or 16)
236 */
cam_ll_set_convert_data_width(lcd_cam_dev_t * dev,uint32_t width)237 static inline void cam_ll_set_convert_data_width(lcd_cam_dev_t *dev, uint32_t width)
238 {
239 HAL_ASSERT(width == 8 || width == 16);
240 dev->cam_rgb_yuv.cam_conv_mode_8bits_on = (width == 8) ? 1 : 0;
241 }
242
243 /**
244 * @brief Set the color range of input data
245 *
246 * @param dev CAM register base address
247 * @param range Color range
248 */
cam_ll_set_input_color_range(lcd_cam_dev_t * dev,color_range_t range)249 static inline void cam_ll_set_input_color_range(lcd_cam_dev_t *dev, color_range_t range)
250 {
251 if (range == COLOR_RANGE_LIMIT) {
252 dev->cam_rgb_yuv.cam_conv_data_in_mode = 0;
253 } else if (range == COLOR_RANGE_FULL) {
254 dev->cam_rgb_yuv.cam_conv_data_in_mode = 1;
255 }
256 }
257
258 /**
259 * @brief Set the color range of output data
260 *
261 * @param dev CAM register base address
262 * @param range Color range
263 */
cam_ll_set_output_color_range(lcd_cam_dev_t * dev,color_range_t range)264 static inline void cam_ll_set_output_color_range(lcd_cam_dev_t *dev, color_range_t range)
265 {
266 if (range == COLOR_RANGE_LIMIT) {
267 dev->cam_rgb_yuv.cam_conv_data_out_mode = 0;
268 } else if (range == COLOR_RANGE_FULL) {
269 dev->cam_rgb_yuv.cam_conv_data_out_mode = 1;
270 }
271 }
272
273 /**
274 * @brief Set YUV conversion standard
275 *
276 * @param dev CAM register base address
277 * @param std YUV conversion standard
278 */
cam_ll_set_yuv_convert_std(lcd_cam_dev_t * dev,color_conv_std_rgb_yuv_t std)279 static inline void cam_ll_set_yuv_convert_std(lcd_cam_dev_t *dev, color_conv_std_rgb_yuv_t std)
280 {
281 if (std == COLOR_CONV_STD_RGB_YUV_BT601) {
282 dev->cam_rgb_yuv.cam_conv_protocol_mode = 0;
283 } else if (std == COLOR_CONV_STD_RGB_YUV_BT709) {
284 dev->cam_rgb_yuv.cam_conv_protocol_mode = 1;
285 }
286 }
287
288 /**
289 * @brief Set the converter mode: RGB565 to YUV
290 *
291 * @param dev CAM register base address
292 * @param yuv_sample YUV sample mode
293 */
cam_ll_set_convert_mode_rgb_to_yuv(lcd_cam_dev_t * dev,color_pixel_yuv_format_t yuv_sample)294 static inline void cam_ll_set_convert_mode_rgb_to_yuv(lcd_cam_dev_t *dev, color_pixel_yuv_format_t yuv_sample)
295 {
296 dev->cam_rgb_yuv.cam_conv_trans_mode = 1;
297 dev->cam_rgb_yuv.cam_conv_yuv2yuv_mode = 3;
298 switch (yuv_sample) {
299 case COLOR_PIXEL_YUV422:
300 dev->cam_rgb_yuv.cam_conv_yuv_mode = 0;
301 break;
302 case COLOR_PIXEL_YUV420:
303 dev->cam_rgb_yuv.cam_conv_yuv_mode = 1;
304 break;
305 case COLOR_PIXEL_YUV411:
306 dev->cam_rgb_yuv.cam_conv_yuv_mode = 2;
307 break;
308 default:
309 abort();
310 }
311 }
312
313 /**
314 * @brief Set the converter mode: YUV to RGB565
315 *
316 * @param dev CAM register base address
317 * @param yuv_sample YUV sample mode
318 */
cam_ll_set_convert_mode_yuv_to_rgb(lcd_cam_dev_t * dev,color_pixel_yuv_format_t yuv_sample)319 static inline void cam_ll_set_convert_mode_yuv_to_rgb(lcd_cam_dev_t *dev, color_pixel_yuv_format_t yuv_sample)
320 {
321 dev->cam_rgb_yuv.cam_conv_trans_mode = 0;
322 dev->cam_rgb_yuv.cam_conv_yuv2yuv_mode = 3;
323 switch (yuv_sample) {
324 case COLOR_PIXEL_YUV422:
325 dev->cam_rgb_yuv.cam_conv_yuv_mode = 0;
326 break;
327 case COLOR_PIXEL_YUV420:
328 dev->cam_rgb_yuv.cam_conv_yuv_mode = 1;
329 break;
330 case COLOR_PIXEL_YUV411:
331 dev->cam_rgb_yuv.cam_conv_yuv_mode = 2;
332 break;
333 default:
334 abort();
335 }
336 }
337
338 /**
339 * @brief Set the converter mode: YUV to YUV
340 *
341 * @param dev CAM register base address
342 * @param src_sample Source YUV sample mode
343 * @param dst_sample Destination YUV sample mode
344 */
cam_ll_set_convert_mode_yuv_to_yuv(lcd_cam_dev_t * dev,color_pixel_yuv_format_t src_sample,color_pixel_yuv_format_t dst_sample)345 static inline void cam_ll_set_convert_mode_yuv_to_yuv(lcd_cam_dev_t *dev, color_pixel_yuv_format_t src_sample, color_pixel_yuv_format_t dst_sample)
346 {
347 HAL_ASSERT(src_sample != dst_sample);
348 dev->cam_rgb_yuv.cam_conv_trans_mode = 1;
349 switch (src_sample) {
350 case COLOR_PIXEL_YUV422:
351 dev->cam_rgb_yuv.cam_conv_yuv_mode = 0;
352 break;
353 case COLOR_PIXEL_YUV420:
354 dev->cam_rgb_yuv.cam_conv_yuv_mode = 1;
355 break;
356 case COLOR_PIXEL_YUV411:
357 dev->cam_rgb_yuv.cam_conv_yuv_mode = 2;
358 break;
359 default:
360 abort();
361 }
362 switch (dst_sample) {
363 case COLOR_PIXEL_YUV422:
364 dev->cam_rgb_yuv.cam_conv_yuv2yuv_mode = 0;
365 break;
366 case COLOR_PIXEL_YUV420:
367 dev->cam_rgb_yuv.cam_conv_yuv2yuv_mode = 1;
368 break;
369 case COLOR_PIXEL_YUV411:
370 dev->cam_rgb_yuv.cam_conv_yuv2yuv_mode = 2;
371 break;
372 default:
373 abort();
374 }
375 }
376
377 /**
378 * @brief Set camera received data byte length
379 *
380 * @param dev CAM register base address
381 * @param length received data byte length, range [0, 0xFFFF]
382 */
cam_ll_set_recv_data_bytelen(lcd_cam_dev_t * dev,uint32_t length)383 static inline void cam_ll_set_recv_data_bytelen(lcd_cam_dev_t *dev, uint32_t length)
384 {
385 HAL_FORCE_MODIFY_U32_REG_FIELD(dev->cam_ctrl1, cam_rec_data_bytelen, length);
386 }
387
388 /**
389 * @brief Set line number to trigger interrupt
390 *
391 * @param dev CAM register base address
392 * @param number line number to trigger hs interrupt, range [0, 0x3F]
393 */
cam_ll_set_line_int_num(lcd_cam_dev_t * dev,uint32_t number)394 static inline void cam_ll_set_line_int_num(lcd_cam_dev_t *dev, uint32_t number)
395 {
396 dev->cam_ctrl1.cam_line_int_num = number;
397 }
398
399 /**
400 * @brief Whether to invert the input signal CAM_PCLK
401 *
402 * @param dev CAM register base address
403 * @param en True to invert, False to not invert
404 */
cam_ll_enable_invert_pclk(lcd_cam_dev_t * dev,bool en)405 static inline void cam_ll_enable_invert_pclk(lcd_cam_dev_t *dev, bool en)
406 {
407 dev->cam_ctrl1.cam_clk_inv = en;
408 }
409
410 /**
411 * @brief Enable CAM_VSYNC filter function
412 *
413 * @param dev CAM register base address
414 * @param en True to enable, False to bypass
415 */
cam_ll_enable_vsync_filter(lcd_cam_dev_t * dev,bool en)416 static inline void cam_ll_enable_vsync_filter(lcd_cam_dev_t *dev, bool en)
417 {
418 dev->cam_ctrl1.cam_vsync_filter_en = en;
419 }
420
421 /**
422 * @brief Set CAM input data width
423 *
424 * @param dev CAM register base address
425 * @param stride 16: The bit number of input data is 9~16. 8: The bit number of input data is 0~8.
426 */
cam_ll_set_input_data_width(lcd_cam_dev_t * dev,uint32_t stride)427 static inline void cam_ll_set_input_data_width(lcd_cam_dev_t *dev, uint32_t stride)
428 {
429 switch (stride) {
430 case 8:
431 dev->cam_ctrl1.cam_2byte_en = 0;
432 break;
433 case 16:
434 dev->cam_ctrl1.cam_2byte_en = 1;
435 break;
436 default:
437 HAL_ASSERT(false);
438 break;
439 }
440 }
441
442 /**
443 * @brief Whether to invert CAM_DE
444 *
445 * @param dev CAM register base address
446 * @param en True to invert, False to not invert
447 */
cam_ll_enable_invert_de(lcd_cam_dev_t * dev,bool en)448 static inline void cam_ll_enable_invert_de(lcd_cam_dev_t *dev, bool en)
449 {
450 dev->cam_ctrl1.cam_de_inv = en;
451 }
452
453 /**
454 * @brief Whether to invert CAM_HSYNC
455 *
456 * @param dev CAM register base address
457 * @param en True to invert, False to not invert
458 */
cam_ll_enable_invert_hsync(lcd_cam_dev_t * dev,bool en)459 static inline void cam_ll_enable_invert_hsync(lcd_cam_dev_t *dev, bool en)
460 {
461 dev->cam_ctrl1.cam_hsync_inv = en;
462 }
463
464 /**
465 * @brief Whether to invert CAM_VSYNC
466 *
467 * @param dev CAM register base address
468 * @param en True to invert, False to not invert
469 */
cam_ll_enable_invert_vsync(lcd_cam_dev_t * dev,bool en)470 static inline void cam_ll_enable_invert_vsync(lcd_cam_dev_t *dev, bool en)
471 {
472 dev->cam_ctrl1.cam_vsync_inv = en;
473 }
474
475 /**
476 * @brief Enable the mode to control the input control signals
477 *
478 * @param dev CAM register base address
479 * @param mode 1: Input control signals are CAM_DE, CAM_HSYNC and CAM_VSYNC;
480 * 0: Input control signals are CAM_DE and CAM_VSYNC. CAM_HSYNC and CAM_DE are all 1 the the same time.
481 */
cam_ll_set_vh_de_mode(lcd_cam_dev_t * dev,bool enable)482 static inline void cam_ll_set_vh_de_mode(lcd_cam_dev_t *dev, bool enable)
483 {
484 dev->cam_ctrl1.cam_vh_de_mode_en = enable;
485 }
486
487 /**
488 * @brief Get the mode of input control signals
489 *
490 * @param dev CAM register base address
491 * @param en The pointer to accept the vh_de mode status. 1: Input control signals are CAM_DE, CAM_HSYNC and CAM_VSYNC;
492 * 0: Input control signals are CAM_DE and CAM_VSYNC. CAM_HSYNC and CAM_DE are all 1 the the same time.
493 */
cam_ll_get_vh_de_mode(lcd_cam_dev_t * dev,bool * en)494 static inline void cam_ll_get_vh_de_mode(lcd_cam_dev_t *dev, bool *en)
495 {
496 *en = dev->cam_ctrl1.cam_vh_de_mode_en;
497 }
498
499 /**
500 * @brief Set the wire width of CAM output
501 *
502 * @param dev CAM register base address
503 * @param width CAM output wire width
504 */
cam_ll_set_data_wire_width(lcd_cam_dev_t * dev,uint32_t width)505 static inline void cam_ll_set_data_wire_width(lcd_cam_dev_t *dev, uint32_t width)
506 {
507 // data line width is same as data stride that set in `cam_ll_set_input_data_width`
508 }
509
510 /**
511 * @brief Start the CAM transaction
512 *
513 * @param dev CAM register base address
514 */
515 __attribute__((always_inline))
cam_ll_start(lcd_cam_dev_t * dev)516 static inline void cam_ll_start(lcd_cam_dev_t *dev)
517 {
518 dev->cam_ctrl.cam_update = 1;
519 dev->cam_ctrl1.cam_start = 1;
520 }
521
522 /**
523 * @brief Stop the CAM transaction
524 *
525 * @param dev CAM register base address
526 */
527 __attribute__((always_inline))
cam_ll_stop(lcd_cam_dev_t * dev)528 static inline void cam_ll_stop(lcd_cam_dev_t *dev)
529 {
530 dev->cam_ctrl1.cam_start = 0;
531 dev->cam_ctrl.cam_update = 1; // self clear
532 }
533
534 /**
535 * @brief Whether to reverse the data bit order
536 *
537 * @note It acts before the YUV-RGB converter
538 *
539 * @param dev CAM register base address
540 * @param en True to reverse, False to not reverse
541 */
542 __attribute__((always_inline))
cam_ll_reverse_dma_data_bit_order(lcd_cam_dev_t * dev,bool en)543 static inline void cam_ll_reverse_dma_data_bit_order(lcd_cam_dev_t *dev, bool en)
544 {
545 dev->cam_ctrl.cam_bit_order = en;
546 }
547
548 /**
549 * @brief Whether to swap adjacent two bytes
550 *
551 * @note This acts before the YUV-RGB converter, mainly to change the data endian.
552 * {B1,B0},{B3,B2} => {B0,B1}{B2,B3}
553 *
554 * @param dev CAM register base address
555 * @param en True to swap the byte order, False to not swap
556 */
557 __attribute__((always_inline))
cam_ll_swap_dma_data_byte_order(lcd_cam_dev_t * dev,bool en)558 static inline void cam_ll_swap_dma_data_byte_order(lcd_cam_dev_t *dev, bool en)
559 {
560 dev->cam_ctrl.cam_byte_order = en;
561 }
562
563 /**
564 * @brief Reset camera module
565 *
566 * @param dev CAM register base address
567 */
568 __attribute__((always_inline))
cam_ll_reset(lcd_cam_dev_t * dev)569 static inline void cam_ll_reset(lcd_cam_dev_t *dev)
570 {
571 dev->cam_ctrl1.cam_reset = 1; // self clear
572 }
573
574 /**
575 * @brief Reset Async RX FIFO
576 *
577 * @param dev CAM register base address
578 */
579 __attribute__((always_inline))
cam_ll_fifo_reset(lcd_cam_dev_t * dev)580 static inline void cam_ll_fifo_reset(lcd_cam_dev_t *dev)
581 {
582 dev->cam_ctrl1.cam_afifo_reset = 1; // self clear
583 }
584
585 /**
586 * @brief Enable/disable interrupt by mask
587 *
588 * @param dev CAM register base address
589 * @param mask Interrupt mask
590 * @param en True to enable interrupt, False to disable interrupt
591 */
cam_ll_enable_interrupt(lcd_cam_dev_t * dev,uint32_t mask,bool en)592 static inline void cam_ll_enable_interrupt(lcd_cam_dev_t *dev, uint32_t mask, bool en)
593 {
594 if (en) {
595 dev->lc_dma_int_ena.val |= mask & 0x0c;
596 } else {
597 dev->lc_dma_int_ena.val &= ~(mask & 0x0c);
598 }
599 }
600
601 /**
602 * @brief Get interrupt status value
603 *
604 * @param dev CAM register base address
605 * @return Interrupt status value
606 */
607 __attribute__((always_inline))
cam_ll_get_interrupt_status(lcd_cam_dev_t * dev)608 static inline uint32_t cam_ll_get_interrupt_status(lcd_cam_dev_t *dev)
609 {
610 return dev->lc_dma_int_st.val & 0x0c;
611 }
612
613 /**
614 * @brief Clear interrupt status by mask
615 *
616 * @param dev CAM register base address
617 * @param mask Interrupt status mask
618 */
619 __attribute__((always_inline))
cam_ll_clear_interrupt_status(lcd_cam_dev_t * dev,uint32_t mask)620 static inline void cam_ll_clear_interrupt_status(lcd_cam_dev_t *dev, uint32_t mask)
621 {
622 dev->lc_dma_int_clr.val = mask & 0x0c;
623 }
624
625 /**
626 * @brief Get address of interrupt status register address
627 *
628 * @param dev CAM register base address
629 * @return Interrupt status register address
630 */
cam_ll_get_interrupt_status_reg(lcd_cam_dev_t * dev)631 static inline volatile void *cam_ll_get_interrupt_status_reg(lcd_cam_dev_t *dev)
632 {
633 return &dev->lc_dma_int_st;
634 }
635
636 #ifdef __cplusplus
637 }
638 #endif
639