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