1 #include "bflb_cam.h"
2 #include "hardware/cam_reg.h"
3 #if !defined(BL702)
4 #include "hardware/cam_front_reg.h"
5 #include "bflb_clock.h"
6 #endif
7 
8 #if defined(BL616)
9 #define CAM_FRONT_BASE 0x20050000
10 #endif
11 #if defined(BL808)
12 #define CAM_FRONT_BASE 0x30010000
13 #endif
14 
bflb_cam_init(struct bflb_device_s * dev,const struct bflb_cam_config_s * config)15 void bflb_cam_init(struct bflb_device_s *dev, const struct bflb_cam_config_s *config)
16 {
17     uint32_t reg_base;
18     uint32_t regval;
19     uint8_t data_mode = 0;
20     uint16_t resolution_x, resolution_y;
21     uint32_t frame_size;
22 #if !defined(BL702)
23     uint32_t threshold;
24 #endif
25 #if defined(BL808)
26     uint32_t tmpval;
27 
28     if (config->input_source) {
29         tmpval = 0x15;
30         regval = getreg32(CAM_FRONT_BASE + CAM_FRONT_PIX_DATA_CTRL_OFFSET);
31         regval |= CAM_FRONT_REG_ISP_DTSRC_SRC;
32         putreg32(regval, CAM_FRONT_BASE + CAM_FRONT_PIX_DATA_CTRL_OFFSET);
33 
34         regval = getreg32(CAM_FRONT_BASE + CAM_FRONT_ADJA_CTRL_2_OFFSET);
35         regval |= 1;
36         putreg32(regval, CAM_FRONT_BASE + CAM_FRONT_ADJA_CTRL_2_OFFSET);
37     } else {
38         tmpval = 0x24;
39         regval = getreg32(CAM_FRONT_BASE + CAM_FRONT_PIX_DATA_CTRL_OFFSET);
40         regval &= ~CAM_FRONT_REG_ISP_DTSRC_SRC;
41         putreg32(regval, CAM_FRONT_BASE + CAM_FRONT_PIX_DATA_CTRL_OFFSET);
42     }
43 #endif
44 
45     reg_base = dev->reg_base;
46     putreg32(config->output_bufaddr, reg_base + CAM_DVP2AXI_ADDR_START_OFFSET);
47     putreg32(config->resolution_y << 16 | config->resolution_x, reg_base + CAM_DVP2AXI_FRAM_EXM_OFFSET);
48     putreg32(data_mode, reg_base + CAM_DVP_DEBUG_OFFSET);
49 
50     regval = getreg32(reg_base + CAM_DVP2AXI_HSYNC_CROP_OFFSET);
51 #if defined(BL702)
52     if ((regval & 0xffff) > 2 * config->resolution_x) {
53         resolution_x = config->resolution_x;
54     } else {
55         resolution_x = ((regval & 0xffff) - (regval >> 16 & 0xffff)) / 2;
56     }
57 #else
58     if ((regval & 0xffff) > config->resolution_x) {
59         resolution_x = config->resolution_x;
60     } else {
61         resolution_x = (regval & 0xffff) - (regval >> 16 & 0xffff);
62     }
63 #endif
64     regval = getreg32(reg_base + CAM_DVP2AXI_VSYNC_CROP_OFFSET);
65     if ((regval & 0xffff) > config->resolution_y) {
66         resolution_y = config->resolution_y;
67     } else {
68         resolution_y = (regval & 0xffff) - (regval >> 16 & 0xffff);
69     }
70 
71 #if defined(BL616)
72     putreg32(0, CAM_FRONT_BASE + CAM_FRONT_DVP2BUS_SRC_SEL_1_OFFSET);
73 #endif
74 
75 #if !defined(BL702)
76 #if defined(BL808)
77     if (config->input_source != CAM_INPUT_SOURCE_CSI) {
78 #endif
79         regval = bflb_clk_get_system_clock(BFLB_SYSTEM_PBCLK);
80         if (regval == 0) {
81             regval = 80;
82         }
83         threshold = (config->h_blank + 4 * config->resolution_x - 2 * config->resolution_x * (config->pixel_clock / 1000000) / regval) / 4;
84 
85         regval = getreg32(CAM_FRONT_BASE + CAM_FRONT_CONFIG_OFFSET);
86         regval &= ~CAM_FRONT_RG_DVPAS_FIFO_TH_MASK;
87         regval |= threshold << CAM_FRONT_RG_DVPAS_FIFO_TH_SHIFT;
88         putreg32(regval, CAM_FRONT_BASE + CAM_FRONT_CONFIG_OFFSET);
89 #if defined(BL808)
90     }
91 #endif
92 #endif
93 
94     /* Set output format */
95     frame_size = resolution_x * resolution_y * 2;
96     regval = getreg32(reg_base + CAM_DVP2AXI_CONFIGUE_OFFSET);
97     if (config->with_mjpeg) {
98         regval &= ~CAM_REG_SW_MODE;
99     } else {
100         regval |= CAM_REG_SW_MODE;
101     }
102 #if defined(BL702)
103     regval |= CAM_REG_INTERLV_MODE;
104     regval &= ~(CAM_REG_DROP_EN | CAM_REG_DROP_EVEN | CAM_REG_SUBSAMPLE_EN | CAM_REG_SUBSAMPLE_EVEN);
105 #else
106     regval &= ~(CAM_REG_DROP_EN | CAM_REG_DROP_EVEN | CAM_REG_DVP_DATA_MODE_MASK | CAM_REG_DVP_DATA_BSEL | CAM_REG_V_SUBSAMPLE_EN | CAM_REG_V_SUBSAMPLE_POL);
107 #endif
108     switch (config->input_format) {
109         case CAM_INPUT_FORMAT_YUV422_YUYV:
110 #if defined(BL808)
111             if (config->output_format >= CAM_OUTPUT_FORMAT_RGB888_OR_BGR888 && config->output_format <= CAM_OUTPUT_FORMAT_RGB888_TO_RGBA8888) {
112                 tmpval = 0x23;
113                 if (config->input_source) {
114                     putreg32(0x18000000, CAM_FRONT_BASE + CAM_FRONT_Y2RA_CONFIG_0_OFFSET);
115                 } else {
116                     putreg32(0xa8000000, CAM_FRONT_BASE + CAM_FRONT_Y2RA_CONFIG_0_OFFSET);
117                 }
118                 putreg32(0xff80, CAM_FRONT_BASE + CAM_FRONT_Y2RA_CONFIG_1_OFFSET);
119                 putreg32(0xff80, CAM_FRONT_BASE + CAM_FRONT_Y2RA_CONFIG_2_OFFSET);
120                 putreg32(0x200, CAM_FRONT_BASE + CAM_FRONT_Y2RA_CONFIG_3_OFFSET);
121                 putreg32(0x20002ce, CAM_FRONT_BASE + CAM_FRONT_Y2RA_CONFIG_4_OFFSET);
122                 putreg32(0xfe92ff50, CAM_FRONT_BASE + CAM_FRONT_Y2RA_CONFIG_5_OFFSET);
123                 putreg32(0x38b0200, CAM_FRONT_BASE + CAM_FRONT_Y2RA_CONFIG_6_OFFSET);
124                 putreg32(0, CAM_FRONT_BASE + CAM_FRONT_Y2RA_CONFIG_7_OFFSET);
125 
126                 if (config->output_format == CAM_OUTPUT_FORMAT_RGB888_OR_BGR888) {
127                     data_mode = 1;
128                     frame_size = resolution_x * resolution_y * 3;
129                     break;
130                 } else if (config->output_format == CAM_OUTPUT_FORMAT_RGB888_TO_RGB565) {
131                     data_mode = 2;
132                     frame_size = resolution_x * resolution_y * 2;
133                     putreg32(5 << CAM_REG_FORMAT_565_SHIFT, reg_base + CAM_DVP2AXI_MISC_OFFSET);
134                     break;
135                 } else if (config->output_format == CAM_OUTPUT_FORMAT_RGB888_TO_BGR565) {
136                     data_mode = 2;
137                     frame_size = resolution_x * resolution_y * 2;
138                     putreg32(0, reg_base + CAM_DVP2AXI_MISC_OFFSET);
139                     break;
140                 } else if (config->output_format == CAM_OUTPUT_FORMAT_RGB888_TO_RGBA8888) {
141                     data_mode = 3;
142                     frame_size = resolution_x * resolution_y * 4;
143                     break;
144                 }
145             }
146 #endif
147         case CAM_INPUT_FORMAT_YUV422_YVYU:
148             if (config->output_format == CAM_OUTPUT_FORMAT_AUTO || config->output_format == CAM_OUTPUT_FORMAT_YUV422) {
149                 data_mode = 0;
150                 frame_size = resolution_x * resolution_y * 2;
151             } else if (config->output_format == CAM_OUTPUT_FORMAT_GRAY) {
152 #if defined(BL702)
153                 regval |= CAM_REG_DROP_EN;
154 #endif
155                 data_mode = 4;
156                 frame_size = resolution_x * resolution_y;
157             } else if (config->output_format == CAM_OUTPUT_FORMAT_YUV422_UV) {
158 #if defined(BL702)
159                 regval |= CAM_REG_DROP_EN | CAM_REG_DROP_EVEN;
160 #else
161                 regval |= CAM_REG_DVP_DATA_BSEL;
162 #endif
163                 data_mode = 4;
164                 frame_size = resolution_x * resolution_y;
165             } else if (config->output_format == CAM_OUTPUT_FORMAT_YUV420_UV) {
166 #if defined(BL702)
167                 regval |= CAM_REG_DROP_EN | CAM_REG_DROP_EVEN | CAM_REG_SUBSAMPLE_EN;
168 #else
169                 regval |= CAM_REG_DVP_DATA_BSEL | CAM_REG_V_SUBSAMPLE_EN | CAM_REG_V_SUBSAMPLE_POL;
170 #endif
171                 data_mode = 4;
172                 frame_size = resolution_x * resolution_y / 2;
173 #if defined(BL616)
174                 putreg32(1, CAM_FRONT_BASE + CAM_FRONT_DVP2BUS_SRC_SEL_1_OFFSET);
175 #endif
176             }
177             break;
178 
179         case CAM_INPUT_FORMAT_YUV422_UYVY:
180 #if defined(BL808)
181             if (config->output_format >= CAM_OUTPUT_FORMAT_RGB888_OR_BGR888 && config->output_format <= CAM_OUTPUT_FORMAT_RGB888_TO_RGBA8888) {
182                 bflb_cam_swap_input_yu_order(dev, true);
183                 tmpval = 0x23;
184                 if (config->input_source) {
185                     putreg32(0x18000000, CAM_FRONT_BASE + CAM_FRONT_Y2RA_CONFIG_0_OFFSET);
186                 } else {
187                     putreg32(0xa8000000, CAM_FRONT_BASE + CAM_FRONT_Y2RA_CONFIG_0_OFFSET);
188                 }
189                 putreg32(0xff80, CAM_FRONT_BASE + CAM_FRONT_Y2RA_CONFIG_1_OFFSET);
190                 putreg32(0xff80, CAM_FRONT_BASE + CAM_FRONT_Y2RA_CONFIG_2_OFFSET);
191                 putreg32(0x200, CAM_FRONT_BASE + CAM_FRONT_Y2RA_CONFIG_3_OFFSET);
192                 putreg32(0x20002ce, CAM_FRONT_BASE + CAM_FRONT_Y2RA_CONFIG_4_OFFSET);
193                 putreg32(0xfe92ff50, CAM_FRONT_BASE + CAM_FRONT_Y2RA_CONFIG_5_OFFSET);
194                 putreg32(0x38b0200, CAM_FRONT_BASE + CAM_FRONT_Y2RA_CONFIG_6_OFFSET);
195                 putreg32(0, CAM_FRONT_BASE + CAM_FRONT_Y2RA_CONFIG_7_OFFSET);
196 
197                 if (config->output_format == CAM_OUTPUT_FORMAT_RGB888_OR_BGR888) {
198                     data_mode = 1;
199                     frame_size = resolution_x * resolution_y * 3;
200                     break;
201                 } else if (config->output_format == CAM_OUTPUT_FORMAT_RGB888_TO_RGB565) {
202                     data_mode = 2;
203                     frame_size = resolution_x * resolution_y * 2;
204                     putreg32(5 << CAM_REG_FORMAT_565_SHIFT, reg_base + CAM_DVP2AXI_MISC_OFFSET);
205                     break;
206                 } else if (config->output_format == CAM_OUTPUT_FORMAT_RGB888_TO_BGR565) {
207                     data_mode = 2;
208                     frame_size = resolution_x * resolution_y * 2;
209                     putreg32(0, reg_base + CAM_DVP2AXI_MISC_OFFSET);
210                     break;
211                 } else if (config->output_format == CAM_OUTPUT_FORMAT_RGB888_TO_RGBA8888) {
212                     data_mode = 3;
213                     frame_size = resolution_x * resolution_y * 4;
214                     break;
215                 }
216             }
217 #endif
218         case CAM_INPUT_FORMAT_YUV422_VYUY:
219             if (config->output_format == CAM_OUTPUT_FORMAT_AUTO || config->output_format == CAM_OUTPUT_FORMAT_YUV422) {
220                 data_mode = 0;
221                 frame_size = resolution_x * resolution_y * 2;
222             } else if (config->output_format == CAM_OUTPUT_FORMAT_GRAY) {
223 #if defined(BL702)
224                 regval |= CAM_REG_DROP_EN | CAM_REG_DROP_EVEN;
225 #else
226                 regval |= CAM_REG_DVP_DATA_BSEL;
227 #endif
228                 data_mode = 4;
229                 frame_size = resolution_x * resolution_y;
230             } else if (config->output_format == CAM_OUTPUT_FORMAT_YUV422_UV) {
231 #if defined(BL702)
232                 regval |= CAM_REG_DROP_EN;
233 #endif
234                 data_mode = 4;
235                 frame_size = resolution_x * resolution_y;
236             } else if (config->output_format == CAM_OUTPUT_FORMAT_YUV420_UV) {
237 #if defined(BL702)
238                 regval |= CAM_REG_DROP_EN | CAM_REG_DROP_EVEN | CAM_REG_SUBSAMPLE_EN | CAM_REG_SUBSAMPLE_EVEN;
239 #else
240                 regval |= CAM_REG_V_SUBSAMPLE_EN;
241 #endif
242                 data_mode = 4;
243                 frame_size = resolution_x * resolution_y / 2;
244 #if defined(BL616)
245                 putreg32(1, CAM_FRONT_BASE + CAM_FRONT_DVP2BUS_SRC_SEL_1_OFFSET);
246 #endif
247             }
248             break;
249 
250         case CAM_INPUT_FORMAT_GRAY:
251             if (config->output_format == CAM_OUTPUT_FORMAT_AUTO || config->output_format == CAM_OUTPUT_FORMAT_GRAY) {
252                 data_mode = 0;
253                 frame_size = resolution_x * resolution_y;
254             }
255             break;
256 
257         case CAM_INPUT_FORMAT_RGB565:
258             /* Same as CAM_INPUT_FORMAT_BGR565 */
259         case CAM_INPUT_FORMAT_BGR565:
260             if (config->output_format == CAM_OUTPUT_FORMAT_AUTO || config->output_format == CAM_OUTPUT_FORMAT_RGB565_OR_BGR565) {
261                 data_mode = 0;
262                 frame_size = resolution_x * resolution_y * 2;
263             }
264             break;
265 
266         case CAM_INPUT_FORMAT_RGB888:
267             /* Same as CAM_INPUT_FORMAT_BGR888 */
268         case CAM_INPUT_FORMAT_BGR888:
269             if (config->output_format == CAM_OUTPUT_FORMAT_AUTO || config->output_format == CAM_OUTPUT_FORMAT_RGB888_OR_BGR888) {
270                 data_mode = 1;
271                 frame_size = resolution_x * resolution_y * 3;
272 #if !defined(BL702)
273             } else if (config->output_format == CAM_OUTPUT_FORMAT_RGB888_TO_RGB565) {
274                 data_mode = 2;
275                 frame_size = resolution_x * resolution_y * 2;
276                 putreg32(5 << CAM_REG_FORMAT_565_SHIFT, reg_base + CAM_DVP2AXI_MISC_OFFSET);
277             } else if (config->output_format == CAM_OUTPUT_FORMAT_RGB888_TO_BGR565) {
278                 data_mode = 2;
279                 frame_size = resolution_x * resolution_y * 2;
280                 putreg32(0, reg_base + CAM_DVP2AXI_MISC_OFFSET);
281             } else if (config->output_format == CAM_OUTPUT_FORMAT_RGB888_TO_RGBA8888) {
282                 /* Default A = 0 */
283                 data_mode = 3;
284                 frame_size = resolution_x * resolution_y * 4;
285 #endif
286             }
287             break;
288 
289         default:
290             break;
291     }
292 #if !defined(BL702)
293     putreg32(frame_size, reg_base + CAM_DVP2AXI_FRAME_BCNT_OFFSET);
294     regval |= data_mode << CAM_REG_DVP_DATA_MODE_SHIFT;
295 #endif
296     putreg32(regval, reg_base + CAM_DVP2AXI_CONFIGUE_OFFSET);
297 
298     /* Set output buffer burst count */
299     regval = getreg32(reg_base + CAM_DVP2AXI_CONFIGUE_OFFSET);
300     regval = (regval & CAM_REG_XLEN_MASK) >> CAM_REG_XLEN_SHIFT;
301     switch (regval) {
302         case CAM_BURST_INCR1:
303 #if defined(BL702)
304             regval = config->output_bufsize >> 2;
305             frame_size = frame_size >> 2;
306 #else
307             regval = config->output_bufsize >> 3;
308 #endif
309             break;
310 
311         case CAM_BURST_INCR4:
312 #if defined(BL702)
313             regval = config->output_bufsize >> 4;
314             frame_size = frame_size >> 4;
315 #else
316             regval = config->output_bufsize >> 5;
317 #endif
318             break;
319 
320         case CAM_BURST_INCR8:
321 #if defined(BL702)
322             regval = config->output_bufsize >> 5;
323             frame_size = frame_size >> 5;
324 #else
325             regval = config->output_bufsize >> 6;
326 #endif
327             break;
328 
329         case CAM_BURST_INCR16:
330 #if defined(BL702)
331             regval = config->output_bufsize >> 6;
332             frame_size = frame_size >> 6;
333 #else
334             regval = config->output_bufsize >> 7;
335 #endif
336             break;
337 
338 #if !defined(BL702)
339         case CAM_BURST_INCR32:
340             regval = config->output_bufsize >> 8;
341             break;
342 
343         case CAM_BURST_INCR64:
344             regval = config->output_bufsize >> 9;
345             break;
346 #endif
347 
348         default:
349             regval = config->output_bufsize >> 7;
350             frame_size = frame_size >> 6;
351             break;
352     }
353     putreg32(regval, reg_base + CAM_DVP2AXI_MEM_BCNT_OFFSET);
354 
355 #if defined(BL702)
356     putreg32(frame_size, reg_base + CAM_DVP2AXI_FRAME_BCNT_0_OFFSET);
357 #endif
358 
359 #if defined(BL808)
360     if (dev->idx < 4) {
361         regval = getreg32(CAM_FRONT_BASE + CAM_FRONT_DVP2BUS_SRC_SEL_1_OFFSET);
362         regval &= ~(0x3f << (dev->idx * 8));
363         regval |= tmpval << (dev->idx * 8);
364         putreg32(regval, CAM_FRONT_BASE + CAM_FRONT_DVP2BUS_SRC_SEL_1_OFFSET);
365     } else {
366         regval = getreg32(CAM_FRONT_BASE + CAM_FRONT_DVP2BUS_SRC_SEL_2_OFFSET);
367         regval &= ~(0x3f << ((dev->idx - 4) * 8));
368         regval |= tmpval << ((dev->idx - 4) * 8);
369         putreg32(regval, CAM_FRONT_BASE + CAM_FRONT_DVP2BUS_SRC_SEL_2_OFFSET);
370     }
371 #endif
372 
373 #if !defined(BL702)
374 #if defined(BL808)
375     if (config->input_source == 0) {
376         regval = getreg32(CAM_FRONT_BASE + CAM_FRONT_CONFIG_OFFSET);
377         regval |= CAM_FRONT_RG_DVPAS_ENABLE;
378         putreg32(regval, CAM_FRONT_BASE + CAM_FRONT_CONFIG_OFFSET);
379     }
380 #else
381     regval = getreg32(CAM_FRONT_BASE + CAM_FRONT_CONFIG_OFFSET);
382     regval |= CAM_FRONT_RG_DVPAS_ENABLE;
383     putreg32(regval, CAM_FRONT_BASE + CAM_FRONT_CONFIG_OFFSET);
384 #endif
385 #endif
386 }
387 
bflb_cam_start(struct bflb_device_s * dev)388 void bflb_cam_start(struct bflb_device_s *dev)
389 {
390     uint32_t reg_base;
391     uint32_t regval;
392 
393     reg_base = dev->reg_base;
394     regval = getreg32(reg_base + CAM_DVP2AXI_CONFIGUE_OFFSET);
395     regval |= CAM_REG_DVP_ENABLE;
396     putreg32(regval, reg_base + CAM_DVP2AXI_CONFIGUE_OFFSET);
397 }
398 
bflb_cam_stop(struct bflb_device_s * dev)399 void bflb_cam_stop(struct bflb_device_s *dev)
400 {
401     uint32_t reg_base;
402     uint32_t regval;
403 
404     reg_base = dev->reg_base;
405     regval = getreg32(reg_base + CAM_DVP2AXI_CONFIGUE_OFFSET);
406     regval &= ~CAM_REG_DVP_ENABLE;
407     putreg32(regval, reg_base + CAM_DVP2AXI_CONFIGUE_OFFSET);
408 }
409 
bflb_cam_int_mask(struct bflb_device_s * dev,uint32_t int_type,bool mask)410 void bflb_cam_int_mask(struct bflb_device_s *dev, uint32_t int_type, bool mask)
411 {
412     uint32_t reg_base;
413     uint32_t regval;
414 
415     reg_base = dev->reg_base;
416 #if defined(BL702)
417     regval = getreg32(reg_base + CAM_INT_CONTROL_OFFSET);
418 #else
419     regval = getreg32(reg_base + CAM_DVP_STATUS_AND_ERROR_OFFSET);
420 #endif
421     if (mask) {
422         regval &= ~int_type;
423     } else {
424         regval |= int_type;
425     }
426 #if defined(BL702)
427     putreg32(regval, reg_base + CAM_INT_CONTROL_OFFSET);
428 #else
429     putreg32(regval, reg_base + CAM_DVP_STATUS_AND_ERROR_OFFSET);
430 #endif
431 }
432 
bflb_cam_int_clear(struct bflb_device_s * dev,uint32_t int_type)433 void bflb_cam_int_clear(struct bflb_device_s *dev, uint32_t int_type)
434 {
435     putreg32(int_type, dev->reg_base + CAM_DVP_FRAME_FIFO_POP_OFFSET);
436 }
437 
bflb_cam_crop_vsync(struct bflb_device_s * dev,uint16_t start_line,uint16_t end_line)438 void bflb_cam_crop_vsync(struct bflb_device_s *dev, uint16_t start_line, uint16_t end_line)
439 {
440     /* Get start_line ~ (end_line - 1), not include end_line */
441     putreg32(start_line << 16 | end_line, dev->reg_base + CAM_DVP2AXI_VSYNC_CROP_OFFSET);
442 }
443 
bflb_cam_crop_hsync(struct bflb_device_s * dev,uint16_t start_pixel,uint16_t end_pixel)444 void bflb_cam_crop_hsync(struct bflb_device_s *dev, uint16_t start_pixel, uint16_t end_pixel)
445 {
446 #if defined(BL702)
447     start_pixel = start_pixel * 2;
448     end_pixel = end_pixel * 2;
449 #endif
450     /* Get start_pixel ~ (end_pixel - 1), not include end_pixel */
451     putreg32(start_pixel << 16 | end_pixel, dev->reg_base + CAM_DVP2AXI_HSYNC_CROP_OFFSET);
452 }
453 
bflb_cam_pop_one_frame(struct bflb_device_s * dev)454 void bflb_cam_pop_one_frame(struct bflb_device_s *dev)
455 {
456 #if defined(BL702)
457     putreg32(3, dev->reg_base + CAM_DVP_FRAME_FIFO_POP_OFFSET);
458 #else
459     putreg32(1, dev->reg_base + CAM_DVP_FRAME_FIFO_POP_OFFSET);
460 #endif
461 }
462 
463 #if !defined(BL702)
bflb_cam_swap_input_yu_order(struct bflb_device_s * dev,bool enable)464 void bflb_cam_swap_input_yu_order(struct bflb_device_s *dev, bool enable)
465 {
466     uint32_t regval;
467 
468     /* If image sensor output format is YUYV, it will be changed to UYVY */
469     regval = getreg32(CAM_FRONT_BASE + CAM_FRONT_CONFIG_OFFSET);
470     if (enable) {
471         regval |= CAM_FRONT_RG_DVPAS_DA_ORDER;
472     } else {
473         regval &= ~CAM_FRONT_RG_DVPAS_DA_ORDER;
474     }
475     putreg32(regval, CAM_FRONT_BASE + CAM_FRONT_CONFIG_OFFSET);
476 }
477 
bflb_cam_filter_frame_period(struct bflb_device_s * dev,uint8_t frame_count,uint32_t frame_valid)478 void bflb_cam_filter_frame_period(struct bflb_device_s *dev, uint8_t frame_count, uint32_t frame_valid)
479 {
480     /* For example: frame_count is 4, frame_valid is 0x14 (10100b). Third/fifth frame will be retained,
481        First/second/fourth frame will be dropped in every (4 + 1) frames */
482     putreg32(frame_count, dev->reg_base + CAM_DVP2AXI_FRAME_PERIOD_OFFSET);
483     putreg32(frame_valid, dev->reg_base + CAM_DVP2AXI_FRAME_VLD_OFFSET);
484 }
485 #endif
486 
bflb_cam_get_frame_count(struct bflb_device_s * dev)487 uint8_t bflb_cam_get_frame_count(struct bflb_device_s *dev)
488 {
489     uint32_t reg_base;
490     uint32_t regval;
491 
492     reg_base = dev->reg_base;
493     regval = getreg32(reg_base + CAM_DVP_STATUS_AND_ERROR_OFFSET);
494     regval &= CAM_FRAME_VALID_CNT_MASK;
495     return (regval >> CAM_FRAME_VALID_CNT_SHIFT);
496 }
497 
bflb_cam_get_frame_info(struct bflb_device_s * dev,uint8_t ** pic)498 uint32_t bflb_cam_get_frame_info(struct bflb_device_s *dev, uint8_t **pic)
499 {
500     uint32_t reg_base;
501 
502     reg_base = dev->reg_base;
503     *pic = (uint8_t *)getreg32(reg_base + CAM_FRAME_START_ADDR0_OFFSET);
504 #if defined(BL702)
505     return (getreg32(reg_base + CAM_FRAME_BYTE_CNT0_0_OFFSET));
506 #else
507     return (getreg32(reg_base + CAM_DVP2AXI_FRAME_BCNT_OFFSET));
508 #endif
509 }
510 
bflb_cam_get_intstatus(struct bflb_device_s * dev)511 uint32_t bflb_cam_get_intstatus(struct bflb_device_s *dev)
512 {
513     return (getreg32(dev->reg_base + CAM_DVP_STATUS_AND_ERROR_OFFSET));
514 }
515 
bflb_cam_feature_control(struct bflb_device_s * dev,int cmd,size_t arg)516 int bflb_cam_feature_control(struct bflb_device_s *dev, int cmd, size_t arg)
517 {
518     int ret = 0;
519     uint32_t reg_base;
520     uint32_t regval;
521 
522     reg_base = dev->reg_base;
523 
524     switch (cmd) {
525         case CAM_CMD_SET_VSYNC_POLARITY:
526             /* Set vsync polarity, arg use @ref CAM_POLARITY */
527             regval = getreg32(reg_base + CAM_DVP2AXI_CONFIGUE_OFFSET);
528             if (arg) {
529                 regval |= CAM_REG_FRAM_VLD_POL;
530             } else {
531                 regval &= ~CAM_REG_FRAM_VLD_POL;
532             }
533             putreg32(regval, reg_base + CAM_DVP2AXI_CONFIGUE_OFFSET);
534             break;
535 
536         case CAM_CMD_SET_HSYNC_POLARITY:
537             /* Set hsync polarity, arg use @ref CAM_POLARITY */
538             regval = getreg32(reg_base + CAM_DVP2AXI_CONFIGUE_OFFSET);
539             if (arg) {
540                 regval |= CAM_REG_LINE_VLD_POL;
541             } else {
542                 regval &= ~CAM_REG_LINE_VLD_POL;
543             }
544             putreg32(regval, reg_base + CAM_DVP2AXI_CONFIGUE_OFFSET);
545             break;
546 
547         case CAM_CMD_SET_BURST:
548             /* Set burst length, arg use @ref CAM_BURST */
549             regval = getreg32(reg_base + CAM_DVP2AXI_CONFIGUE_OFFSET);
550             regval &= ~CAM_REG_XLEN_MASK;
551             regval |= (arg << CAM_REG_XLEN_SHIFT) & CAM_REG_XLEN_MASK;
552             putreg32(regval, reg_base + CAM_DVP2AXI_CONFIGUE_OFFSET);
553             break;
554 
555 #if !defined(BL702)
556         case CAM_CMD_SET_RGBA8888_ALPHA:
557             /* Set alpha value of RGBA8888 output, arg is alpha */
558             regval = getreg32(reg_base + CAM_DVP2AXI_MISC_OFFSET);
559             regval &= ~CAM_REG_ALPHA_MASK;
560             regval |= arg & CAM_REG_ALPHA_MASK;
561             putreg32(regval, reg_base + CAM_DVP2AXI_MISC_OFFSET);
562             break;
563 
564         case CAM_CMD_GET_FRAME_ID:
565             /* Get frame id */
566             *(uint16_t *)arg = getreg32(reg_base + CAM_FRAME_ID_STS01_OFFSET) & 0xffff;
567             break;
568 #endif
569 
570         case CAM_CMD_WRAP_MODE:
571             /* Wrap to output buffer start address, only effective in mjpeg mode, arg use ENABLE or DISABLE */
572             regval = getreg32(reg_base + CAM_DVP2AXI_CONFIGUE_OFFSET);
573             if (arg) {
574                 regval |= CAM_REG_HW_MODE_FWRAP;
575             } else {
576                 regval &= ~CAM_REG_HW_MODE_FWRAP;
577             }
578             putreg32(regval, reg_base + CAM_DVP2AXI_CONFIGUE_OFFSET);
579             break;
580 
581         case CAM_CMD_COUNT_TRIGGER_NORMAL_INT:
582             /* Set frame count to trigger normal interrupt, arg is frame count */
583 #if defined(BL702)
584             regval = getreg32(reg_base + CAM_INT_CONTROL_OFFSET);
585             regval &= ~CAM_REG_FRAME_CNT_TRGR_INT_MASK;
586             regval |= arg << CAM_REG_FRAME_CNT_TRGR_INT_SHIFT;
587             putreg32(regval, reg_base + CAM_INT_CONTROL_OFFSET);
588 #else
589             regval = getreg32(reg_base + CAM_DVP_STATUS_AND_ERROR_OFFSET);
590             regval &= ~CAM_REG_FRAME_CNT_TRGR_INT_MASK;
591             regval |= arg & CAM_REG_FRAME_CNT_TRGR_INT_MASK;
592             putreg32(regval, reg_base + CAM_DVP_STATUS_AND_ERROR_OFFSET);
593 #endif
594             break;
595 
596 #if !defined(BL702)
597         case CAM_CMD_FRAME_ID_RESET:
598             /* Reset frame id */
599             regval = getreg32(CAM_FRONT_BASE + CAM_FRONT_ISP_ID_YUV_OFFSET);
600             regval |= CAM_FRONT_REG_YUV_IDGEN_RST;
601             putreg32(regval, CAM_FRONT_BASE + CAM_FRONT_ISP_ID_YUV_OFFSET);
602             break;
603 
604         case CAM_CMD_INVERSE_VSYNC_POLARITY:
605             /* Inverse vsync polarity */
606             regval = getreg32(CAM_FRONT_BASE + CAM_FRONT_CONFIG_OFFSET);
607             regval |= CAM_FRONT_RG_DVPAS_VS_INV;
608             putreg32(regval, CAM_FRONT_BASE + CAM_FRONT_CONFIG_OFFSET);
609             break;
610 
611         case CAM_CMD_INVERSE_HSYNC_POLARITY:
612             /* Inverse hsync polarity */
613             regval = getreg32(CAM_FRONT_BASE + CAM_FRONT_CONFIG_OFFSET);
614             regval |= CAM_FRONT_RG_DVPAS_HS_INV;
615             putreg32(regval, CAM_FRONT_BASE + CAM_FRONT_CONFIG_OFFSET);
616             break;
617 #endif
618 
619         default:
620             ret = -EPERM;
621             break;
622     }
623     return ret;
624 }
625