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