1 /*
2 * linux-5.4/drivers/media/platform/sunxi-vin/vin-isp/sunxi_isp.c
3 *
4 * Copyright (c) 2007-2017 Allwinnertech Co., Ltd.
5 *
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 */
16
17 #include <linux/platform_device.h>
18 #include <linux/kernel.h>
19 #include <linux/module.h>
20 #include <media/v4l2-device.h>
21 #include <media/v4l2-mediabus.h>
22 #include <media/v4l2-subdev.h>
23 #include <media/v4l2-event.h>
24 #include <media/v4l2-ctrls.h>
25 #include "../platform/platform_cfg.h"
26 #include "sunxi_isp.h"
27
28 #include "../vin-csi/sunxi_csi.h"
29 #include "../vin-vipp/sunxi_scaler.h"
30 #include "../vin-video/vin_core.h"
31 #include "../utility/vin_io.h"
32 #include "isp_default_tbl.h"
33
34 #define ISP_MODULE_NAME "vin_isp"
35
36 struct isp_dev *glb_isp[VIN_MAX_ISP];
37
38 #ifdef CONFIG_D3D_COMPRESS_EN
39 #define D3D_RAW_LBC_MODE 16 /* <=10 = lossless, 12 = 1.2x, 30 = 3x(< 3x)*/
40 #define D3D_K_LBC_MODE 20 /* <=10 = lossless, 12 = 1.2x, 20 = 2x(< 2x)*/
41 #else
42 #define D3D_RAW_LBC_MODE 10 /* <=10 = lossless, 12 = 1.2x, 30 = 3x(< 3x)*/
43 #define D3D_K_LBC_MODE 10 /* <=10 = lossless, 12 = 1.2x, 20 = 2x(< 2x)*/
44 #endif
45
46 #ifdef CONFIG_WDR_COMPRESS_EN
47 #define WDR_RAW_LBC_MODE 26 /* <=10 = lossless, 12 = 1.2x, 30 = 3x(< 3x)*/
48 #else
49 #define WDR_RAW_LBC_MODE 10 /* <=10 = lossless, 12 = 1.2x, 30 = 3x(< 3x)*/
50 #endif
51
52 #define LARGE_IMAGE_OFF 32
53
54 #define MIN_IN_WIDTH 192
55 #define MIN_IN_HEIGHT 128
56 #define MAX_IN_WIDTH 4224
57 #define MAX_IN_HEIGHT 4224
58
59 static struct isp_pix_fmt sunxi_isp_formats[] = {
60 {
61 .fourcc = V4L2_PIX_FMT_SBGGR8,
62 .mbus_code = MEDIA_BUS_FMT_SBGGR8_1X8,
63 .infmt = ISP_BGGR,
64 }, {
65 .fourcc = V4L2_PIX_FMT_SGBRG8,
66 .mbus_code = MEDIA_BUS_FMT_SGBRG8_1X8,
67 .infmt = ISP_GBRG,
68 }, {
69 .fourcc = V4L2_PIX_FMT_SGRBG8,
70 .mbus_code = MEDIA_BUS_FMT_SGRBG8_1X8,
71 .infmt = ISP_GRBG,
72 }, {
73 .fourcc = V4L2_PIX_FMT_SRGGB8,
74 .mbus_code = MEDIA_BUS_FMT_SRGGB8_1X8,
75 .infmt = ISP_RGGB,
76 }, {
77 .fourcc = V4L2_PIX_FMT_SBGGR10,
78 .mbus_code = MEDIA_BUS_FMT_SBGGR10_1X10,
79 .infmt = ISP_BGGR,
80 }, {
81 .fourcc = V4L2_PIX_FMT_SGBRG8,
82 .mbus_code = MEDIA_BUS_FMT_SGBRG10_1X10,
83 .infmt = ISP_GBRG,
84 }, {
85 .fourcc = V4L2_PIX_FMT_SGRBG10,
86 .mbus_code = MEDIA_BUS_FMT_SGRBG10_1X10,
87 .infmt = ISP_GRBG,
88 }, {
89 .fourcc = V4L2_PIX_FMT_SRGGB10,
90 .mbus_code = MEDIA_BUS_FMT_SRGGB10_1X10,
91 .infmt = ISP_RGGB,
92 }, {
93 .fourcc = V4L2_PIX_FMT_SBGGR12,
94 .mbus_code = MEDIA_BUS_FMT_SBGGR12_1X12,
95 .infmt = ISP_BGGR,
96 }, {
97 .fourcc = V4L2_PIX_FMT_SGBRG12,
98 .mbus_code = MEDIA_BUS_FMT_SGBRG12_1X12,
99 .infmt = ISP_GBRG,
100 }, {
101 .fourcc = V4L2_PIX_FMT_SGRBG12,
102 .mbus_code = MEDIA_BUS_FMT_SGRBG12_1X12,
103 .infmt = ISP_GRBG,
104 }, {
105 .fourcc = V4L2_PIX_FMT_SRGGB12,
106 .mbus_code = MEDIA_BUS_FMT_SRGGB12_1X12,
107 .infmt = ISP_RGGB,
108 },
109 };
110
__isp_s_sensor_stby_handle(struct work_struct * work)111 static void __isp_s_sensor_stby_handle(struct work_struct *work)
112 {
113 int sensor_stby_stat, i;
114 struct isp_dev *isp =
115 container_of(work, struct isp_dev, s_sensor_stby_task);
116 struct vin_md *vind = dev_get_drvdata(isp->subdev.v4l2_dev->dev);
117 struct vin_core *vinc = NULL;
118
119 for (i = 0; i < VIN_MAX_DEV; i++) {
120 if (vind->vinc[i] == NULL)
121 continue;
122 if (!vin_streaming(&vind->vinc[i]->vid_cap))
123 continue;
124
125 vinc = vind->vinc[i];
126 if (vinc->isp_sel == isp->id)
127 break;
128 }
129
130 sensor_stby_stat = STBY_ON;
131 v4l2_subdev_call(vinc->vid_cap.pipe.sd[VIN_IND_SENSOR], core, ioctl,
132 SET_SENSOR_STANDBY, &sensor_stby_stat);
133
134 sensor_stby_stat = STBY_OFF;
135 v4l2_subdev_call(vinc->vid_cap.pipe.sd[VIN_IND_SENSOR], core, ioctl,
136 SET_SENSOR_STANDBY, &sensor_stby_stat);
137
138
139 vin_print("%s done, %s is standby and then on!\n", __func__, vinc->vid_cap.pipe.sd[VIN_IND_SENSOR]->name);
140 }
141
142 #if defined CONFIG_D3D
isp_3d_pingpong_alloc(struct isp_dev * isp)143 static int isp_3d_pingpong_alloc(struct isp_dev *isp)
144 {
145 int ret = 0;
146 #if defined CONFIG_ARCH_SUN8IW19P1
147 int cmp_ratio, bitdepth, wth;
148
149 if (D3D_K_LBC_MODE > 10) {
150 if (D3D_K_LBC_MODE > 20)
151 cmp_ratio = 1000/2;
152 else
153 cmp_ratio = 1000*10/D3D_K_LBC_MODE;
154 } else
155 cmp_ratio = 1000;
156 bitdepth = 5;
157 wth = roundup(isp->mf.width, 16);
158 if (D3D_K_LBC_MODE <= 10)
159 isp->d3d_k_lbc.line_tar_bits = roundup(wth*bitdepth + wth/16*2, 512);
160 else
161 isp->d3d_k_lbc.line_tar_bits = roundup(cmp_ratio*wth*bitdepth/1000, 512);
162 isp->d3d_k_lbc.mb_min_bit = clamp((cmp_ratio*bitdepth*16)/1000, 0, 127);
163
164 if (D3D_RAW_LBC_MODE > 10) {
165 if (D3D_RAW_LBC_MODE > 30)
166 cmp_ratio = 1000/3;
167 else
168 cmp_ratio = 1000*10/D3D_RAW_LBC_MODE;
169 } else
170 cmp_ratio = 1000;
171 bitdepth = 12;
172 wth = roundup(isp->mf.width, 32);
173 if (D3D_RAW_LBC_MODE <= 10)
174 isp->d3d_raw_lbc.line_tar_bits = roundup(wth*bitdepth + wth/32*2, 512);
175 else
176 isp->d3d_raw_lbc.line_tar_bits = roundup(cmp_ratio*wth*bitdepth/1000, 512);
177 isp->d3d_raw_lbc.mb_min_bit = clamp(((cmp_ratio*bitdepth + 500)/1000-1)*32+6, 0, 511);
178
179 isp->d3d_pingpong[0].size = isp->d3d_k_lbc.line_tar_bits * isp->mf.height / 8;
180 isp->d3d_pingpong[1].size = isp->d3d_raw_lbc.line_tar_bits * isp->mf.height / 8;
181 #if defined CONFIG_D3D_LTF_EN
182 isp->d3d_pingpong[2].size = isp->d3d_raw_lbc.line_tar_bits * isp->mf.height / 8;
183 ret = os_mem_alloc(&isp->pdev->dev, &isp->d3d_pingpong[2]);
184 if (ret < 0) {
185 vin_err("isp 3d pingpong buf2 requset failed!\n");
186 return -ENOMEM;
187 }
188 #endif
189 #elif defined CONFIG_ARCH_SUN8IW16P1
190 #if defined CONFIG_D3D_LTF_EN
191 isp->d3d_pingpong[0].size = roundup(isp->mf.width, 64) * isp->mf.height * 29 / 8;
192 isp->d3d_pingpong[1].size = roundup(isp->mf.width, 64) * isp->mf.height * 29 / 8;
193 #else
194 isp->d3d_pingpong[0].size = roundup(isp->mf.width, 64) * isp->mf.height * 17 / 8;
195 isp->d3d_pingpong[1].size = roundup(isp->mf.width, 64) * isp->mf.height * 17 / 8;
196 #endif
197 #else
198 isp->d3d_pingpong[0].size = roundup(isp->mf.width, 64) * isp->mf.height * 29 / 8;
199 isp->d3d_pingpong[1].size = roundup(isp->mf.width, 64) * isp->mf.height * 29 / 8;
200 #endif
201 ret = os_mem_alloc(&isp->pdev->dev, &isp->d3d_pingpong[0]);
202 if (ret < 0) {
203 vin_err("isp 3d pingpong buf0 requset failed!\n");
204 return -ENOMEM;
205 }
206
207 ret = os_mem_alloc(&isp->pdev->dev, &isp->d3d_pingpong[1]);
208 if (ret < 0) {
209 vin_err("isp 3d pingpong buf1 requset failed!\n");
210 return -ENOMEM;
211 }
212 return ret;
213 }
isp_3d_pingpong_free(struct isp_dev * isp)214 static void isp_3d_pingpong_free(struct isp_dev *isp)
215 {
216 os_mem_free(&isp->pdev->dev, &isp->d3d_pingpong[0]);
217 os_mem_free(&isp->pdev->dev, &isp->d3d_pingpong[1]);
218 #if defined CONFIG_ARCH_SUN8IW19P1
219 #if defined CONFIG_D3D_LTF_EN
220 os_mem_free(&isp->pdev->dev, &isp->d3d_pingpong[2]);
221 #endif
222 #endif
223 }
224
isp_3d_pingpong_update(struct isp_dev * isp)225 static int isp_3d_pingpong_update(struct isp_dev *isp)
226 {
227 dma_addr_t addr;
228
229 #if defined CONFIG_ARCH_SUN8IW19P1
230 addr = (dma_addr_t)isp->d3d_pingpong[0].dma_addr;
231 bsp_isp_set_d3d_ref_k_addr(isp->id, addr);
232 addr = (dma_addr_t)isp->d3d_pingpong[1].dma_addr;
233 bsp_isp_set_d3d_ref_raw_addr(isp->id, addr);
234 #if defined CONFIG_D3D_LTF_EN
235 addr = (dma_addr_t)isp->d3d_pingpong[2].dma_addr;
236 bsp_isp_set_d3d_ltf_raw_addr(isp->id, addr);
237 #endif
238
239 if (D3D_K_LBC_MODE <= 10)
240 bsp_isp_set_d3d_k_lbc_ctrl(isp->id, &isp->d3d_k_lbc, 0);
241 else
242 bsp_isp_set_d3d_k_lbc_ctrl(isp->id, &isp->d3d_k_lbc, 1);
243
244 if (D3D_RAW_LBC_MODE <= 10)
245 bsp_isp_set_d3d_raw_lbc_ctrl(isp->id, &isp->d3d_raw_lbc, 0);
246 else
247 bsp_isp_set_d3d_raw_lbc_ctrl(isp->id, &isp->d3d_raw_lbc, 1);
248
249 bsp_isp_set_d3d_stride(isp->id, isp->d3d_k_lbc.line_tar_bits/32, isp->d3d_raw_lbc.line_tar_bits/32);
250 bsp_isp_d3d_fifo_en(isp->id, 1);
251 #else
252 struct vin_mm tmp;
253
254 tmp = isp->d3d_pingpong[0];
255 isp->d3d_pingpong[0] = isp->d3d_pingpong[1];
256 isp->d3d_pingpong[1] = tmp;
257
258 addr = (dma_addr_t)isp->d3d_pingpong[0].dma_addr;
259 bsp_isp_set_d3d_addr0(isp->id, addr);
260 addr = (dma_addr_t)isp->d3d_pingpong[1].dma_addr;
261 bsp_isp_set_d3d_addr1(isp->id, addr);
262 #if defined CONFIG_ARCH_SUN8IW16P1 && !defined CONFIG_D3D_LTF_EN
263 /* close d3d long time frame */
264 writel(readl(isp->isp_load.vir_addr + 0x2d4) & ~(1 << 24), isp->isp_load.vir_addr + 0x2d4);
265 #endif
266 #endif
267 return 0;
268 }
269 #else
isp_3d_pingpong_alloc(struct isp_dev * isp)270 static int isp_3d_pingpong_alloc(struct isp_dev *isp)
271 {
272 return 0;
273 }
isp_3d_pingpong_free(struct isp_dev * isp)274 static void isp_3d_pingpong_free(struct isp_dev *isp)
275 {
276
277 }
isp_3d_pingpong_update(struct isp_dev * isp)278 static int isp_3d_pingpong_update(struct isp_dev *isp)
279 {
280 return 0;
281 }
282 #endif
283
284 #if defined CONFIG_WDR
isp_wdr_pingpong_alloc(struct isp_dev * isp)285 static int isp_wdr_pingpong_alloc(struct isp_dev *isp)
286 {
287 int ret = 0, i;
288 #if !defined CONFIG_ARCH_SUN8IW16P1 && !defined CONFIG_ARCH_SUN8IW19P1
289 short *wdr_tbl = isp->isp_lut_tbl.vir_addr + ISP_WDR_GAMMA_FE_MEM_OFS;
290 #else
291 short *wdr_tbl = isp->isp_load.vir_addr + ISP_LOAD_REG_SIZE + ISP_FE_TBL_SIZE + ISP_S0_LC_TBL_SIZE;
292 #endif
293
294 #if defined CONFIG_ARCH_SUN8IW19P1
295 int cmp_ratio, bitdepth, wth;
296
297 if (WDR_RAW_LBC_MODE > 10) {
298 if (WDR_RAW_LBC_MODE > 30)
299 cmp_ratio = 1000/3;
300 else
301 cmp_ratio = 1000*10/WDR_RAW_LBC_MODE;
302 } else
303 cmp_ratio = 1000;
304 bitdepth = 12;
305 wth = roundup(isp->mf.width, 32);
306 if (WDR_RAW_LBC_MODE <= 10)
307 isp->wdr_raw_lbc.line_tar_bits = roundup(wth*bitdepth + wth/32*2, 512);
308 else
309 isp->wdr_raw_lbc.line_tar_bits = roundup(cmp_ratio*wth*bitdepth/1000, 512);
310 isp->wdr_raw_lbc.mb_min_bit = clamp(((cmp_ratio*bitdepth + 500)/1000-1)*32+16, 0, 511);
311
312 isp->wdr_pingpong[0].size = isp->wdr_raw_lbc.line_tar_bits * isp->mf.height / 8;
313 #else
314 isp->wdr_pingpong[0].size = isp->mf.width * isp->mf.height * 2;
315 isp->wdr_pingpong[1].size = isp->mf.width * isp->mf.height * 2;
316
317 ret = os_mem_alloc(&isp->pdev->dev, &isp->wdr_pingpong[1]);
318 if (ret < 0) {
319 vin_err("isp wdr pingpong buf1 requset failed!\n");
320 return -ENOMEM;
321 }
322 #endif
323 ret = os_mem_alloc(&isp->pdev->dev, &isp->wdr_pingpong[0]);
324 if (ret < 0) {
325 vin_err("isp wdr pingpong buf0 requset failed!\n");
326 return -ENOMEM;
327 }
328
329 for (i = 0; i < 4096; i++) {
330 wdr_tbl[i] = i;
331 wdr_tbl[i + 4096] = i*16;
332 }
333
334 return ret;
335 }
isp_wdr_pingpong_free(struct isp_dev * isp)336 static void isp_wdr_pingpong_free(struct isp_dev *isp)
337 {
338 #if defined CONFIG_ARCH_SUN8IW19P1
339 os_mem_free(&isp->pdev->dev, &isp->wdr_pingpong[0]);
340 #else
341 os_mem_free(&isp->pdev->dev, &isp->wdr_pingpong[0]);
342 os_mem_free(&isp->pdev->dev, &isp->wdr_pingpong[1]);
343 #endif
344 }
345
isp_wdr_pingpong_set(struct isp_dev * isp)346 static int isp_wdr_pingpong_set(struct isp_dev *isp)
347 {
348 dma_addr_t addr;
349 #if defined CONFIG_ARCH_SUN8IW19P1
350 addr = (dma_addr_t)isp->wdr_pingpong[0].dma_addr;
351 bsp_isp_set_wdr_addr0(isp->id, addr);
352 if (WDR_RAW_LBC_MODE <= 10)
353 bsp_isp_set_wdr_raw_lbc_ctrl(isp->id, &isp->wdr_raw_lbc, 0);
354 else
355 bsp_isp_set_wdr_raw_lbc_ctrl(isp->id, &isp->wdr_raw_lbc, 1);
356 bsp_isp_set_wdr_stride(isp->id, isp->wdr_raw_lbc.line_tar_bits / 32);
357 bsp_isp_wdr_fifo_en(isp->id, 1);
358 #else
359 addr = (dma_addr_t)isp->wdr_pingpong[0].dma_addr;
360 bsp_isp_set_wdr_addr0(isp->id, addr);
361 addr = (dma_addr_t)isp->wdr_pingpong[1].dma_addr;
362 bsp_isp_set_wdr_addr1(isp->id, addr);
363 #endif
364 return 0;
365 }
366 #else
isp_wdr_pingpong_alloc(struct isp_dev * isp)367 static int isp_wdr_pingpong_alloc(struct isp_dev *isp)
368 {
369 isp->wdr_mode = ISP_NORMAL_MODE;
370
371 return 0;
372 }
isp_wdr_pingpong_free(struct isp_dev * isp)373 static void isp_wdr_pingpong_free(struct isp_dev *isp) {}
isp_wdr_pingpong_set(struct isp_dev * isp)374 static int isp_wdr_pingpong_set(struct isp_dev *isp)
375 {
376 return 0;
377 }
378 #endif
379
380 #ifdef SUPPORT_ISP_TDM
__sunxi_isp_tdm_off(struct isp_dev * isp)381 static int __sunxi_isp_tdm_off(struct isp_dev *isp)
382 {
383 struct vin_md *vind = dev_get_drvdata(isp->subdev.v4l2_dev->dev);
384 struct vin_core *vinc = NULL;
385 int i, j;
386
387 for (i = 0; i < VIN_MAX_DEV; i++) {
388 if (vind->vinc[i] == NULL)
389 continue;
390 if (!vin_streaming(&vind->vinc[i]->vid_cap))
391 continue;
392 vinc = vind->vinc[i];
393 for (j = 0; j < VIN_MAX_ISP; j++) {
394 if (vinc->isp_sel == j)
395 return -1;
396 }
397 }
398 return 0;
399 }
400 #endif
401
sunxi_isp_cal_bandwidth_memory(struct v4l2_subdev * sd,unsigned int on)402 static void sunxi_isp_cal_bandwidth_memory(struct v4l2_subdev *sd, unsigned int on)
403 {
404 struct isp_dev *isp = v4l2_get_subdevdata(sd);
405 struct vin_md *vind = dev_get_drvdata(isp->subdev.v4l2_dev->dev);
406 struct v4l2_mbus_framefmt *mf = &isp->mf;
407 __maybe_unused struct mbus_framefmt_res *res = (void *)mf->reserved;
408 unsigned int bandw;
409
410 bandw = 0;
411 #if defined CONFIG_D3D
412 bandw += isp->mf.height * isp->mf.width * 5 / 8 * 2 * res->fps * 10 / D3D_RAW_LBC_MODE;
413 #endif
414
415 #if defined CONFIG_WDR
416 if (res->res_wdr_mode == ISP_DOL_WDR_MODE)
417 bandw += isp->mf.height * isp->mf.width * 3 / 2 * 2 * res->fps * 10 / WDR_RAW_LBC_MODE;
418 #endif
419
420 if (on)
421 vind->isp_bd_tatol += bandw;
422 else
423 vind->isp_bd_tatol -= bandw;
424
425 vin_log(VIN_LOG_ISP, "isp%d %s bandwidth = %d.\n", isp->id, on ? "use" : "release", bandw);
426 }
427
sunxi_isp_subdev_s_stream(struct v4l2_subdev * sd,int enable)428 static int sunxi_isp_subdev_s_stream(struct v4l2_subdev *sd, int enable)
429 {
430 struct isp_dev *isp = v4l2_get_subdevdata(sd);
431 struct v4l2_mbus_framefmt *mf = &isp->mf;
432 struct mbus_framefmt_res *res = (void *)mf->reserved;
433 struct v4l2_event event;
434 #if defined CONFIG_ARCH_SUN8IW16P1 || defined CONFIG_ARCH_SUN8IW19P1 || defined CONFIG_ARCH_SUN50IW10
435 struct isp_wdr_mode_cfg wdr_cfg;
436 #endif
437 unsigned int load_val;
438 __maybe_unused int i;
439
440 if (!isp->use_isp)
441 return 0;
442
443 switch (res->res_pix_fmt) {
444 case V4L2_PIX_FMT_SBGGR8:
445 case V4L2_PIX_FMT_SGBRG8:
446 case V4L2_PIX_FMT_SGRBG8:
447 case V4L2_PIX_FMT_SRGGB8:
448 case V4L2_PIX_FMT_SBGGR10:
449 case V4L2_PIX_FMT_SGBRG10:
450 case V4L2_PIX_FMT_SGRBG10:
451 case V4L2_PIX_FMT_SRGGB10:
452 case V4L2_PIX_FMT_SBGGR12:
453 case V4L2_PIX_FMT_SGBRG12:
454 case V4L2_PIX_FMT_SGRBG12:
455 case V4L2_PIX_FMT_SRGGB12:
456 vin_log(VIN_LOG_FMT, "%s output fmt is raw, return directly\n", __func__);
457 if (isp->isp_dbg.debug_en) {
458 bsp_isp_debug_output_cfg(isp->id, 1, isp->isp_dbg.debug_sel);
459 break;
460 } else {
461 return 0;
462 }
463 default:
464 break;
465 }
466
467 if (enable) {
468 isp->h3a_stat.frame_number = 0;
469 isp->ptn_isp_cnt = 0;
470 isp->isp_ob.set_cnt = 0;
471 isp->sensor_lp_mode = res->res_lp_mode;
472 /*when normal to wdr, old register would lead timeout, so we clean it up*/
473 if (isp->wdr_mode != res->res_wdr_mode) {
474 isp->wdr_mode = res->res_wdr_mode;
475 memcpy(isp->isp_load.vir_addr, &isp_default_reg[0], ISP_LOAD_REG_SIZE);
476 }
477 if (isp->load_flag)
478 memcpy(isp->isp_load.vir_addr, &isp->load_shadow[0], ISP_LOAD_DRAM_SIZE);
479
480 if (isp->large_image == 0) {
481 if (isp->runtime_flag == 0) {
482 if (isp_3d_pingpong_alloc(isp))
483 return -ENOMEM;
484 isp_3d_pingpong_update(isp);
485 } else
486 isp->runtime_flag = 0;
487 }
488 if (isp->wdr_mode != ISP_NORMAL_MODE) {
489 if (isp_wdr_pingpong_alloc(isp)) {
490 isp_3d_pingpong_free(isp);
491 return -ENOMEM;
492 }
493 isp_wdr_pingpong_set(isp);
494 }
495 #ifndef SUPPORT_ISP_TDM
496 bsp_isp_enable(isp->id, 1);
497 #else
498 for (i = 0; i < VIN_MAX_ISP; i++)
499 bsp_isp_enable(i, 1);
500 #endif
501 bsp_isp_clr_irq_status(isp->id, ISP_IRQ_EN_ALL);
502 #if !defined CONFIG_ARCH_SUN8IW16P1 && !defined CONFIG_ARCH_SUN8IW19P1 && !defined CONFIG_ARCH_SUN50IW10
503 bsp_isp_irq_enable(isp->id, FINISH_INT_EN | PARA_LOAD_INT_EN | SRC0_FIFO_INT_EN
504 | FRAME_ERROR_INT_EN | FRAME_LOST_INT_EN);
505
506 load_val = bsp_isp_load_update_flag(isp->id);
507 if (isp->wdr_mode == ISP_DOL_WDR_MODE) {
508 load_val = load_val | WDR_UPDATE;
509 bsp_isp_module_enable(isp->id, WDR_EN);
510 bsp_isp_set_wdr_mode(isp->id, ISP_DOL_WDR_MODE);
511 bsp_isp_ch_enable(isp->id, ISP_CH1, 1);
512 } else if (isp->wdr_mode == ISP_COMANDING_MODE) {
513 load_val = load_val | WDR_UPDATE;
514 bsp_isp_module_enable(isp->id, WDR_EN);
515 bsp_isp_set_wdr_mode(isp->id, ISP_COMANDING_MODE);
516 } else {
517 load_val = load_val & ~WDR_UPDATE;
518 bsp_isp_module_disable(isp->id, WDR_EN);
519 bsp_isp_set_wdr_mode(isp->id, ISP_NORMAL_MODE);
520 }
521 #else
522 bsp_isp_irq_enable(isp->id, FINISH_INT_EN | S0_PARA_LOAD_INT_EN | S0_FIFO_INT_EN
523 | S0_FRAME_ERROR_INT_EN | S0_FRAME_LOST_INT_EN);
524 #if defined CONFIG_ARCH_SUN8IW19P1
525 bsp_isp_irq_enable(isp->id, S0_BTYPE_ERROR_INT_EN | ADDR_ERROR_INT_EN | LBC_ERROR_INT_EN);
526 #endif
527
528 load_val = bsp_isp_load_update_flag(isp->id);
529 if (isp->wdr_mode == ISP_DOL_WDR_MODE) {
530 load_val = load_val | WDR_UPDATE;
531 wdr_cfg.wdr_exp_seq = 0;
532 wdr_cfg.wdr_ch_seq = 0;
533 wdr_cfg.wdr_mode = 0;
534 bsp_isp_module_enable(isp->id, WDR_EN);
535 bsp_isp_wdr_mode_cfg(isp->id, &wdr_cfg);
536 bsp_isp_ch_enable(isp->id, ISP_CH1, 1);
537 } else if (isp->wdr_mode == ISP_COMANDING_MODE) {
538 load_val = load_val | WDR_UPDATE;
539 wdr_cfg.wdr_exp_seq = 0;
540 wdr_cfg.wdr_ch_seq = 0;
541 wdr_cfg.wdr_mode = ISP_COMANDING_MODE;
542 bsp_isp_module_enable(isp->id, WDR_EN);
543 bsp_isp_wdr_mode_cfg(isp->id, &wdr_cfg);
544 } else {
545 load_val = load_val & ~WDR_UPDATE;
546 bsp_isp_module_disable(isp->id, WDR_EN);
547 }
548 #endif
549
550 #if !defined CONFIG_D3D
551 bsp_isp_module_disable(isp->id, D3D_EN);
552 load_val = load_val & ~D3D_UPDATE;
553 #endif
554 if (isp->large_image == 2)
555 bsp_isp_module_disable(isp->id, PLTM_EN | D3D_EN | AE_EN | AWB_EN | AF_EN | HIST_EN);
556 bsp_isp_update_table(isp->id, load_val);
557
558 bsp_isp_module_enable(isp->id, SRC0_EN);
559 bsp_isp_set_input_fmt(isp->id, isp->isp_fmt->infmt);
560 bsp_isp_set_size(isp->id, &isp->isp_ob);
561 bsp_isp_set_para_ready_mode(isp->id, 1);
562 bsp_isp_set_para_ready(isp->id, PARA_READY);
563 bsp_isp_set_last_blank_cycle(isp->id, 5);
564 bsp_isp_set_speed_mode(isp->id, 3);
565 #if !defined CONFIG_D3D_LTF_EN && !defined CONFIG_WDR
566 bsp_isp_set_fifo_mode(isp->id, 0);
567 bsp_isp_fifo_raw_write(isp->id, 0x200);
568 #endif
569 bsp_isp_ch_enable(isp->id, ISP_CH0, 1);
570 bsp_isp_capture_start(isp->id);
571 } else {
572 if (!isp->nosend_ispoff && !isp->runtime_flag) {
573 memset(&event, 0, sizeof(event));
574 event.type = V4L2_EVENT_VIN_ISP_OFF;
575 event.id = 0;
576 v4l2_event_queue(isp->subdev.devnode, &event);
577 }
578 bsp_isp_capture_stop(isp->id);
579 bsp_isp_module_disable(isp->id, SRC0_EN);
580 bsp_isp_ch_enable(isp->id, ISP_CH0, 0);
581 bsp_isp_irq_disable(isp->id, ISP_IRQ_EN_ALL);
582 bsp_isp_clr_irq_status(isp->id, ISP_IRQ_EN_ALL);
583 #ifndef SUPPORT_ISP_TDM
584 bsp_isp_enable(isp->id, 0);
585 #else
586 if (__sunxi_isp_tdm_off(isp) == 0) {
587 for (i = 0; i < VIN_MAX_ISP; i++)
588 bsp_isp_enable(i, 0);
589
590 } else
591 vin_warn("ISP is used in TDM mode, ISP%d cannot be closing when other isp is used!\n", isp->id);
592 #endif
593 if (isp->large_image == 0) {
594 if (isp->runtime_flag == 0)
595 isp_3d_pingpong_free(isp);
596 else
597 isp->runtime_flag = 0;
598 }
599 if (isp->wdr_mode != ISP_NORMAL_MODE) {
600 bsp_isp_ch_enable(isp->id, ISP_CH1, 0);
601 isp_wdr_pingpong_free(isp);
602 }
603 isp->f1_after_librun = 0;
604 }
605
606 sunxi_isp_cal_bandwidth_memory(sd, enable);
607
608 vin_log(VIN_LOG_FMT, "isp%d %s, %d*%d hoff: %d voff: %d code: %x field: %d\n",
609 isp->id, enable ? "stream on" : "stream off",
610 isp->isp_ob.ob_valid.width, isp->isp_ob.ob_valid.height,
611 isp->isp_ob.ob_start.hor, isp->isp_ob.ob_start.ver,
612 mf->code, mf->field);
613
614 return 0;
615 }
616
__isp_try_format(struct isp_dev * isp,struct v4l2_mbus_framefmt * mf)617 static struct isp_pix_fmt *__isp_try_format(struct isp_dev *isp,
618 struct v4l2_mbus_framefmt *mf)
619 {
620 struct isp_pix_fmt *isp_fmt = NULL;
621 struct isp_size_settings *ob = &isp->isp_ob;
622 unsigned int i;
623
624 for (i = 0; i < ARRAY_SIZE(sunxi_isp_formats); ++i)
625 if (mf->code == sunxi_isp_formats[i].mbus_code)
626 isp_fmt = &sunxi_isp_formats[i];
627
628 if (isp_fmt == NULL)
629 isp_fmt = &sunxi_isp_formats[0];
630
631 ob->ob_black.width = mf->width;
632 ob->ob_black.height = mf->height;
633
634 if (!isp->large_image) {
635 if (isp->id == 1) {
636 mf->width = clamp_t(u32, mf->width, MIN_IN_WIDTH, 3264);
637 mf->height = clamp_t(u32, mf->height, MIN_IN_HEIGHT, 3264);
638 } else {
639 mf->width = clamp_t(u32, mf->width, MIN_IN_WIDTH, 4224);
640 mf->height = clamp_t(u32, mf->height, MIN_IN_HEIGHT, 4224);
641 }
642 }
643
644 ob->ob_valid.width = mf->width;
645 ob->ob_valid.height = mf->height;
646 ob->ob_start.hor = (ob->ob_black.width - ob->ob_valid.width) / 2;
647 ob->ob_start.ver = (ob->ob_black.height - ob->ob_valid.height) / 2;
648
649 if (isp->large_image == 2) {
650 isp->left_right = 0;
651 isp->isp_ob.ob_valid.width = mf->width / 2 + LARGE_IMAGE_OFF;
652 }
653
654 switch (mf->colorspace) {
655 case V4L2_COLORSPACE_REC709:
656 mf->colorspace = V4L2_COLORSPACE_REC709;
657 break;
658 case V4L2_COLORSPACE_BT2020:
659 mf->colorspace = V4L2_COLORSPACE_BT2020;
660 break;
661 default:
662 mf->colorspace = V4L2_COLORSPACE_JPEG;
663 break;
664 }
665 return isp_fmt;
666 }
667
sunxi_isp_s_parm(struct v4l2_subdev * sd,struct v4l2_streamparm * parms)668 int sunxi_isp_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms)
669 {
670 struct v4l2_captureparm *cp = &parms->parm.capture;
671 struct isp_dev *isp = v4l2_get_subdevdata(sd);
672
673 if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
674 return -EINVAL;
675
676 isp->capture_mode = cp->capturemode;
677 isp->large_image = cp->reserved[2];
678
679 return 0;
680 }
681
sunxi_isp_g_parm(struct v4l2_subdev * sd,struct v4l2_streamparm * parms)682 int sunxi_isp_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms)
683 {
684 struct v4l2_captureparm *cp = &parms->parm.capture;
685 struct isp_dev *isp = v4l2_get_subdevdata(sd);
686
687 if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
688 return -EINVAL;
689
690 memset(cp, 0, sizeof(struct v4l2_captureparm));
691 cp->capability = V4L2_CAP_TIMEPERFRAME;
692 cp->capturemode = isp->capture_mode;
693
694 return 0;
695 }
696
sunxi_isp_subdev_get_fmt(struct v4l2_subdev * sd,struct v4l2_subdev_pad_config * cfg,struct v4l2_subdev_format * fmt)697 static int sunxi_isp_subdev_get_fmt(struct v4l2_subdev *sd,
698 struct v4l2_subdev_pad_config *cfg,
699 struct v4l2_subdev_format *fmt)
700 {
701 struct isp_dev *isp = v4l2_get_subdevdata(sd);
702
703 mutex_lock(&isp->subdev_lock);
704 fmt->format = isp->mf;
705 mutex_unlock(&isp->subdev_lock);
706 return 0;
707 }
708
sunxi_isp_subdev_set_fmt(struct v4l2_subdev * sd,struct v4l2_subdev_pad_config * cfg,struct v4l2_subdev_format * fmt)709 static int sunxi_isp_subdev_set_fmt(struct v4l2_subdev *sd,
710 struct v4l2_subdev_pad_config *cfg,
711 struct v4l2_subdev_format *fmt)
712 {
713 struct isp_dev *isp = v4l2_get_subdevdata(sd);
714 struct v4l2_mbus_framefmt *mf = &isp->mf;
715 struct isp_pix_fmt *isp_fmt;
716
717 vin_log(VIN_LOG_FMT, "%s %d*%d %x %d\n", __func__,
718 fmt->format.width, fmt->format.height,
719 fmt->format.code, fmt->format.field);
720
721 if (fmt->pad == ISP_PAD_SOURCE) {
722 if (mf) {
723 mutex_lock(&isp->subdev_lock);
724 fmt->format = *mf;
725 mutex_unlock(&isp->subdev_lock);
726 }
727 return 0;
728 }
729 isp_fmt = __isp_try_format(isp, &fmt->format);
730 if (mf) {
731 mutex_lock(&isp->subdev_lock);
732 *mf = fmt->format;
733 if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE)
734 isp->isp_fmt = isp_fmt;
735 mutex_unlock(&isp->subdev_lock);
736 }
737
738 return 0;
739
740 }
741
sunxi_isp_subdev_init(struct v4l2_subdev * sd,u32 val)742 int sunxi_isp_subdev_init(struct v4l2_subdev *sd, u32 val)
743 {
744 struct isp_dev *isp = v4l2_get_subdevdata(sd);
745 struct vin_md *vind = dev_get_drvdata(isp->subdev.v4l2_dev->dev);
746
747 if (!isp->use_isp)
748 return 0;
749
750 if (val && isp->use_cnt++ > 0)
751 return 0;
752 else if (!val && (isp->use_cnt == 0 || --isp->use_cnt > 0))
753 return 0;
754
755 vin_log(VIN_LOG_ISP, "isp%d %s use_cnt = %d.\n", isp->id,
756 val ? "init" : "uninit", isp->use_cnt);
757
758 if (val) {
759 bsp_isp_ver_read_en(isp->id, 1);
760 bsp_isp_get_isp_ver(isp->id, &vind->isp_ver_major, &vind->isp_ver_minor);
761 bsp_isp_ver_read_en(isp->id, 0);
762 if (!isp->have_init) {
763 memcpy(isp->isp_load.vir_addr, &isp_default_reg[0], ISP_LOAD_REG_SIZE);
764 memset(&isp->load_shadow[0], 0, ISP_LOAD_DRAM_SIZE);
765 isp->load_flag = 0;
766 isp->have_init = 1;
767 } else {
768 #if defined CONFIG_D3D
769 if ((isp->load_shadow[0x2d4 + 0x3]) & (1<<1)) {
770 /* clear D3D rec_en */
771 isp->load_shadow[0x2d4 + 0x3] = (isp->load_shadow[0x2d4 + 0x3]) & (~(1<<1));
772 memcpy(isp->isp_load.vir_addr, &isp->load_shadow[0], ISP_LOAD_DRAM_SIZE);
773 }
774 #endif
775 }
776 isp->isp_frame_number = 0;
777 isp->h3a_stat.buf[0].empty = 1;
778 isp->h3a_stat.buf[0].dma_addr = isp->isp_stat.dma_addr;
779 isp->h3a_stat.buf[0].virt_addr = isp->isp_stat.vir_addr;
780 bsp_isp_set_statistics_addr(isp->id, (dma_addr_t)isp->isp_stat.dma_addr);
781 bsp_isp_set_saved_addr(isp->id, (unsigned long)isp->isp_save.dma_addr);
782 #if !defined CONFIG_ARCH_SUN8IW16P1 && !defined CONFIG_ARCH_SUN8IW19P1 && !defined CONFIG_ARCH_SUN50IW10
783 bsp_isp_set_load_addr(isp->id, (unsigned long)isp->isp_load.dma_addr);
784 bsp_isp_set_table_addr(isp->id, LENS_GAMMA_TABLE, (unsigned long)(isp->isp_lut_tbl.dma_addr));
785 bsp_isp_set_table_addr(isp->id, DRC_TABLE, (unsigned long)(isp->isp_drc_tbl.dma_addr));
786 #else
787 bsp_isp_set_load_addr0(isp->id, (dma_addr_t)isp->isp_load.dma_addr);
788 bsp_isp_set_load_addr1(isp->id, (dma_addr_t)isp->isp_load.dma_addr);
789 #endif
790 bsp_isp_set_para_ready(isp->id, PARA_NOT_READY);
791 }
792
793 return 0;
794 }
795
__isp_set_load_reg(struct v4l2_subdev * sd,struct isp_table_reg_map * reg)796 static int __isp_set_load_reg(struct v4l2_subdev *sd, struct isp_table_reg_map *reg)
797 {
798 struct isp_dev *isp = v4l2_get_subdevdata(sd);
799
800 if (!isp->use_isp)
801 return 0;
802
803 if (reg->size > ISP_LOAD_DRAM_SIZE) {
804 vin_err("user ask for 0x%x data, it more than isp load_data 0x%x\n", reg->size, ISP_LOAD_DRAM_SIZE);
805 return -EINVAL;
806 }
807
808 isp->load_flag = 1;
809 return copy_from_user(&isp->load_shadow[0], reg->addr, reg->size);
810 }
811
812 #if !defined CONFIG_ARCH_SUN8IW16P1 && !defined CONFIG_ARCH_SUN8IW19P1 && !defined CONFIG_ARCH_SUN50IW10
__isp_set_table1_map(struct v4l2_subdev * sd,struct isp_table_reg_map * tbl)813 static int __isp_set_table1_map(struct v4l2_subdev *sd, struct isp_table_reg_map *tbl)
814 {
815 struct isp_dev *isp = v4l2_get_subdevdata(sd);
816 int ret;
817
818 if (!isp->use_isp)
819 return 0;
820
821 if (tbl->size > ISP_TABLE_MAPPING1_SIZE) {
822 vin_err("user ask for 0x%x data, it more than isp table1_data 0x%x\n", tbl->size, ISP_TABLE_MAPPING1_SIZE);
823 return -EINVAL;
824 }
825
826 ret = copy_from_user(&isp->load_shadow[0] + ISP_LOAD_REG_SIZE, tbl->addr, tbl->size);
827 if (ret < 0) {
828 vin_err("copy table mapping1 from usr error!\n");
829 return ret;
830 }
831
832 return 0;
833 }
834
__isp_set_table2_map(struct v4l2_subdev * sd,struct isp_table_reg_map * tbl)835 static int __isp_set_table2_map(struct v4l2_subdev *sd, struct isp_table_reg_map *tbl)
836 {
837 struct isp_dev *isp = v4l2_get_subdevdata(sd);
838 int ret;
839
840 if (!isp->use_isp)
841 return 0;
842
843 if (tbl->size > ISP_TABLE_MAPPING2_SIZE) {
844 vin_err("user ask for 0x%x data, it more than isp table1_data 0x%x\n", tbl->size, ISP_TABLE_MAPPING2_SIZE);
845 return -EINVAL;
846 }
847
848 ret = copy_from_user(&isp->load_shadow[0] + ISP_LOAD_REG_SIZE + ISP_TABLE_MAPPING1_SIZE, tbl->addr, tbl->size);
849 if (ret < 0) {
850 vin_err("copy table mapping2 from usr error!\n");
851 return ret;
852 }
853
854 return 0;
855 }
856 #endif
857
sunxi_isp_subdev_ioctl(struct v4l2_subdev * sd,unsigned int cmd,void * arg)858 static long sunxi_isp_subdev_ioctl(struct v4l2_subdev *sd, unsigned int cmd,
859 void *arg)
860 {
861 int ret = 0;
862
863 switch (cmd) {
864 case VIDIOC_VIN_ISP_LOAD_REG:
865 ret = __isp_set_load_reg(sd, (struct isp_table_reg_map *)arg);
866 break;
867 #if !defined CONFIG_ARCH_SUN8IW16P1 && !defined CONFIG_ARCH_SUN8IW19P1 && !defined CONFIG_ARCH_SUN50IW10
868 case VIDIOC_VIN_ISP_TABLE1_MAP:
869 ret = __isp_set_table1_map(sd, (struct isp_table_reg_map *)arg);
870 break;
871 case VIDIOC_VIN_ISP_TABLE2_MAP:
872 ret = __isp_set_table2_map(sd, (struct isp_table_reg_map *)arg);
873 break;
874 #endif
875 default:
876 return -ENOIOCTLCMD;
877 }
878
879 return ret;
880 }
881
882 #ifdef CONFIG_COMPAT
883
884 struct isp_table_reg_map32 {
885 compat_caddr_t addr;
886 unsigned int size;
887 };
888
889 #define VIDIOC_VIN_ISP_LOAD_REG32 \
890 _IOWR('V', BASE_VIDIOC_PRIVATE + 70, struct isp_table_reg_map32)
891
892 #define VIDIOC_VIN_ISP_TABLE1_MAP32 \
893 _IOWR('V', BASE_VIDIOC_PRIVATE + 71, struct isp_table_reg_map32)
894
895 #define VIDIOC_VIN_ISP_TABLE2_MAP32 \
896 _IOWR('V', BASE_VIDIOC_PRIVATE + 72, struct isp_table_reg_map32)
897
get_isp_table_reg_map32(struct isp_table_reg_map * kp,struct isp_table_reg_map32 __user * up)898 static int get_isp_table_reg_map32(struct isp_table_reg_map *kp,
899 struct isp_table_reg_map32 __user *up)
900 {
901 u32 tmp;
902
903 if (!access_ok(up, sizeof(struct isp_table_reg_map32)) ||
904 get_user(kp->size, &up->size) || get_user(tmp, &up->addr))
905 return -EFAULT;
906 kp->addr = compat_ptr(tmp);
907 return 0;
908 }
909
put_isp_table_reg_map32(struct isp_table_reg_map * kp,struct isp_table_reg_map32 __user * up)910 static int put_isp_table_reg_map32(struct isp_table_reg_map *kp,
911 struct isp_table_reg_map32 __user *up)
912 {
913 u32 tmp = (u32) ((unsigned long)kp->addr);
914
915 if (!access_ok(up, sizeof(struct isp_table_reg_map32)) ||
916 put_user(kp->size, &up->size) || put_user(tmp, &up->addr))
917 return -EFAULT;
918 return 0;
919 }
920
isp_compat_ioctl32(struct v4l2_subdev * sd,unsigned int cmd,unsigned long arg)921 static long isp_compat_ioctl32(struct v4l2_subdev *sd,
922 unsigned int cmd, unsigned long arg)
923 {
924 union {
925 struct isp_table_reg_map isd;
926 } karg;
927 void __user *up = compat_ptr(arg);
928 int compatible_arg = 1;
929 long err = 0;
930
931 vin_log(VIN_LOG_ISP, "%s cmd is %d\n", __func__, cmd);
932
933 switch (cmd) {
934 case VIDIOC_VIN_ISP_LOAD_REG32:
935 cmd = VIDIOC_VIN_ISP_LOAD_REG;
936 break;
937 case VIDIOC_VIN_ISP_TABLE1_MAP32:
938 cmd = VIDIOC_VIN_ISP_TABLE1_MAP;
939 break;
940 case VIDIOC_VIN_ISP_TABLE2_MAP32:
941 cmd = VIDIOC_VIN_ISP_TABLE2_MAP;
942 break;
943 }
944
945 switch (cmd) {
946 case VIDIOC_VIN_ISP_LOAD_REG:
947 case VIDIOC_VIN_ISP_TABLE1_MAP:
948 case VIDIOC_VIN_ISP_TABLE2_MAP:
949 err = get_isp_table_reg_map32(&karg.isd, up);
950 compatible_arg = 0;
951 break;
952 }
953
954 if (err)
955 return err;
956
957 if (compatible_arg)
958 err = sunxi_isp_subdev_ioctl(sd, cmd, up);
959 else {
960 mm_segment_t old_fs = get_fs();
961
962 set_fs(KERNEL_DS);
963 err = sunxi_isp_subdev_ioctl(sd, cmd, &karg);
964 set_fs(old_fs);
965 }
966
967 switch (cmd) {
968 case VIDIOC_VIN_ISP_LOAD_REG:
969 case VIDIOC_VIN_ISP_TABLE1_MAP:
970 case VIDIOC_VIN_ISP_TABLE2_MAP:
971 err = put_isp_table_reg_map32(&karg.isd, up);
972 break;
973 }
974
975 return err;
976 }
977 #endif
978
979 /*
980 * must reset all the pipeline through isp.
981 */
sunxi_isp_reset(struct isp_dev * isp)982 void sunxi_isp_reset(struct isp_dev *isp)
983 {
984 #ifndef SUPPORT_ISP_TDM
985 struct vin_md *vind = dev_get_drvdata(isp->subdev.v4l2_dev->dev);
986 struct vin_core *vinc = NULL;
987 struct prs_cap_mode mode = {.mode = VCAP};
988 bool flags = 1;
989 int i = 0;
990
991 if (!isp->use_isp)
992 return;
993
994 if (!isp->subdev.entity.stream_count) {
995 vin_err("isp%d is not used, cannot be resetted!!!\n", isp->id);
996 return;
997 }
998
999 vin_print("%s:isp%d reset!!!,ISP frame number is %d\n", __func__, isp->id, isp->isp_frame_number);
1000
1001 bsp_isp_set_para_ready(isp->id, PARA_NOT_READY);
1002 #if defined CONFIG_D3D
1003 if ((isp->load_shadow[0x2d4 + 0x3]) & (1<<1)) {
1004 /* clear D3D rec_en 0x2d4 bit25*/
1005 isp->load_shadow[0x2d4 + 0x3] = (isp->load_shadow[0x2d4 + 0x3]) & (~(1<<1));
1006 memcpy(isp->isp_load.vir_addr, &isp->load_shadow[0], ISP_LOAD_DRAM_SIZE);
1007 }
1008 #endif
1009
1010 /*****************stop*******************/
1011 for (i = 0; i < VIN_MAX_DEV; i++) {
1012 if (vind->vinc[i] == NULL)
1013 continue;
1014 if (!vin_streaming(&vind->vinc[i]->vid_cap))
1015 continue;
1016
1017 if (vind->vinc[i]->isp_sel == isp->id) {
1018 vinc = vind->vinc[i];
1019 vinc->vid_cap.frame_delay_cnt = 1;
1020
1021 if (flags) {
1022 csic_prs_capture_stop(vinc->csi_sel);
1023
1024 #if defined CONFIG_ARCH_SUN8IW16P1
1025 if (vinc->mipi_sel == 0)
1026 cmb_rx_disable(vinc->mipi_sel);
1027 #endif
1028 csic_prs_disable(vinc->csi_sel);
1029 csic_isp_bridge_disable(0);
1030
1031 bsp_isp_clr_irq_status(isp->id, ISP_IRQ_EN_ALL);
1032 bsp_isp_enable(isp->id, 0);
1033 bsp_isp_capture_stop(isp->id);
1034 flags = 0;
1035 }
1036 vipp_disable(vinc->vipp_sel);
1037 vipp_top_clk_en(vinc->vipp_sel, 0);
1038 csic_dma_int_clear_status(vinc->vipp_sel, DMA_INT_ALL);
1039 csic_dma_top_disable(vinc->vipp_sel);
1040 }
1041 }
1042
1043 /*****************start*******************/
1044 flags = 1;
1045 for (i = 0; i < VIN_MAX_DEV; i++) {
1046 if (vind->vinc[i] == NULL)
1047 continue;
1048 if (!vin_streaming(&vind->vinc[i]->vid_cap))
1049 continue;
1050
1051 if (vind->vinc[i]->isp_sel == isp->id) {
1052 vinc = vind->vinc[i];
1053
1054 csic_dma_top_enable(vinc->vipp_sel);
1055 vipp_top_clk_en(vinc->vipp_sel, 1);
1056 vipp_enable(vinc->vipp_sel);
1057 vinc->vin_status.frame_cnt = 0;
1058 vinc->vin_status.lost_cnt = 0;
1059
1060 if (flags) {
1061 bsp_isp_enable(isp->id, 1);
1062 bsp_isp_set_para_ready(isp->id, PARA_READY);
1063 bsp_isp_capture_start(isp->id);
1064 isp->isp_frame_number = 0;
1065
1066 csic_isp_bridge_enable(0);
1067
1068 csic_prs_enable(vinc->csi_sel);
1069
1070 #if defined CONFIG_ARCH_SUN8IW16P1
1071 if (vinc->mipi_sel == 0)
1072 cmb_rx_enable(vinc->mipi_sel);
1073 #endif
1074
1075 csic_prs_capture_start(vinc->csi_sel, 1, &mode);
1076 flags = 0;
1077 }
1078 }
1079 }
1080
1081 if (isp->sensor_lp_mode)
1082 schedule_work(&isp->s_sensor_stby_task);
1083 #endif
1084 }
1085
sunxi_isp_frame_sync_isr(struct v4l2_subdev * sd)1086 void sunxi_isp_frame_sync_isr(struct v4l2_subdev *sd)
1087 {
1088 struct isp_dev *isp = v4l2_get_subdevdata(sd);
1089 struct v4l2_event event;
1090 static short isp_log_param;
1091 bool send_event = 0;
1092
1093 memset(&event, 0, sizeof(event));
1094 event.type = V4L2_EVENT_FRAME_SYNC;
1095 event.id = 0;
1096 event.u.data[0] = 1;/*load type (0: load seperate; 1: load together)*/
1097 switch (isp->mf.colorspace) {
1098 case V4L2_COLORSPACE_REC709:
1099 event.u.data[1] = 1;
1100 break;
1101 case V4L2_COLORSPACE_BT2020:
1102 event.u.data[1] = 2;
1103 break;
1104 default:
1105 event.u.data[1] = 0;
1106 break;
1107 }
1108 if (isp_log_param != (vin_log_mask >> 16)) {
1109 isp_log_param = vin_log_mask >> 16;
1110 send_event = 1;
1111 } else {
1112 send_event = 0;
1113 }
1114 event.u.data[2] = isp_log_param;
1115 event.u.data[3] = isp_log_param >> 8;
1116 if ((isp->h3a_stat.frame_number < 2) || send_event)
1117 v4l2_event_queue(isp->subdev.devnode, &event);
1118
1119 isp_stat_isr(&isp->h3a_stat);
1120 }
1121
sunxi_isp_subscribe_event(struct v4l2_subdev * sd,struct v4l2_fh * fh,struct v4l2_event_subscription * sub)1122 int sunxi_isp_subscribe_event(struct v4l2_subdev *sd,
1123 struct v4l2_fh *fh,
1124 struct v4l2_event_subscription *sub)
1125 {
1126 vin_log(VIN_LOG_ISP, "%s id = %d\n", __func__, sub->id);
1127 if (sub->type == V4L2_EVENT_CTRL)
1128 return v4l2_ctrl_subdev_subscribe_event(sd, fh, sub);
1129 else
1130 return v4l2_event_subscribe(fh, sub, 1, NULL);
1131 }
1132
1133 static const struct v4l2_subdev_core_ops sunxi_isp_subdev_core_ops = {
1134 .init = sunxi_isp_subdev_init,
1135 .ioctl = sunxi_isp_subdev_ioctl,
1136 #ifdef CONFIG_COMPAT
1137 .compat_ioctl32 = isp_compat_ioctl32,
1138 #endif
1139 .subscribe_event = sunxi_isp_subscribe_event,
1140 .unsubscribe_event = v4l2_event_subdev_unsubscribe,
1141 };
1142
1143 static const struct v4l2_subdev_video_ops sunxi_isp_subdev_video_ops = {
1144 .s_stream = sunxi_isp_subdev_s_stream,
1145 };
1146
1147 static const struct v4l2_subdev_pad_ops sunxi_isp_subdev_pad_ops = {
1148 .get_fmt = sunxi_isp_subdev_get_fmt,
1149 .set_fmt = sunxi_isp_subdev_set_fmt,
1150 };
1151
1152 static struct v4l2_subdev_ops sunxi_isp_subdev_ops = {
1153 .core = &sunxi_isp_subdev_core_ops,
1154 .video = &sunxi_isp_subdev_video_ops,
1155 .pad = &sunxi_isp_subdev_pad_ops,
1156 };
1157
__sunxi_isp_ctrl(struct isp_dev * isp,struct v4l2_ctrl * ctrl)1158 static int __sunxi_isp_ctrl(struct isp_dev *isp, struct v4l2_ctrl *ctrl)
1159 {
1160 int ret = 0;
1161
1162 if (ctrl->flags & V4L2_CTRL_FLAG_INACTIVE)
1163 return 0;
1164
1165 switch (ctrl->id) {
1166 case V4L2_CID_BRIGHTNESS:
1167 case V4L2_CID_CONTRAST:
1168 case V4L2_CID_SATURATION:
1169 case V4L2_CID_HUE:
1170 case V4L2_CID_AUTO_WHITE_BALANCE:
1171 case V4L2_CID_EXPOSURE:
1172 case V4L2_CID_AUTOGAIN:
1173 case V4L2_CID_GAIN:
1174 case V4L2_CID_POWER_LINE_FREQUENCY:
1175 case V4L2_CID_HUE_AUTO:
1176 case V4L2_CID_WHITE_BALANCE_TEMPERATURE:
1177 case V4L2_CID_SHARPNESS:
1178 case V4L2_CID_CHROMA_AGC:
1179 case V4L2_CID_COLORFX:
1180 case V4L2_CID_AUTOBRIGHTNESS:
1181 case V4L2_CID_BAND_STOP_FILTER:
1182 case V4L2_CID_ILLUMINATORS_1:
1183 case V4L2_CID_ILLUMINATORS_2:
1184 case V4L2_CID_EXPOSURE_AUTO:
1185 case V4L2_CID_EXPOSURE_ABSOLUTE:
1186 case V4L2_CID_EXPOSURE_AUTO_PRIORITY:
1187 case V4L2_CID_FOCUS_ABSOLUTE:
1188 case V4L2_CID_FOCUS_RELATIVE:
1189 case V4L2_CID_FOCUS_AUTO:
1190 case V4L2_CID_AUTO_EXPOSURE_BIAS:
1191 case V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE:
1192 case V4L2_CID_WIDE_DYNAMIC_RANGE:
1193 case V4L2_CID_IMAGE_STABILIZATION:
1194 case V4L2_CID_ISO_SENSITIVITY:
1195 case V4L2_CID_ISO_SENSITIVITY_AUTO:
1196 case V4L2_CID_EXPOSURE_METERING:
1197 case V4L2_CID_SCENE_MODE:
1198 case V4L2_CID_3A_LOCK:
1199 case V4L2_CID_AUTO_FOCUS_START:
1200 case V4L2_CID_AUTO_FOCUS_STOP:
1201 case V4L2_CID_AUTO_FOCUS_RANGE:
1202 case V4L2_CID_FLASH_LED_MODE:
1203 case V4L2_CID_AUTO_FOCUS_INIT:
1204 case V4L2_CID_AUTO_FOCUS_RELEASE:
1205 case V4L2_CID_FLASH_LED_MODE_V1:
1206 case V4L2_CID_TAKE_PICTURE:
1207 break;
1208 default:
1209 break;
1210 }
1211 return ret;
1212 }
1213
1214 #define ctrl_to_sunxi_isp(ctrl) \
1215 container_of(ctrl->handler, struct isp_dev, ctrls.handler)
1216
sunxi_isp_s_ctrl(struct v4l2_ctrl * ctrl)1217 static int sunxi_isp_s_ctrl(struct v4l2_ctrl *ctrl)
1218 {
1219 struct isp_dev *isp = ctrl_to_sunxi_isp(ctrl);
1220 unsigned long flags;
1221 int ret;
1222
1223 vin_log(VIN_LOG_ISP, "%s, val = %d, cur.val = %d\n",
1224 v4l2_ctrl_get_name(ctrl->id), ctrl->val, ctrl->cur.val);
1225 spin_lock_irqsave(&isp->slock, flags);
1226 ret = __sunxi_isp_ctrl(isp, ctrl);
1227 spin_unlock_irqrestore(&isp->slock, flags);
1228
1229 return ret;
1230 }
1231
sunxi_isp_try_ctrl(struct v4l2_ctrl * ctrl)1232 static int sunxi_isp_try_ctrl(struct v4l2_ctrl *ctrl)
1233 {
1234 /*
1235 * to cheat control framework, because of when ctrl->cur.val == ctrl->val
1236 * s_ctrl would not be called
1237 */
1238 if ((ctrl->minimum == 0) && (ctrl->maximum == 1)) {
1239 if (ctrl->val)
1240 ctrl->cur.val = 0;
1241 else
1242 ctrl->cur.val = 1;
1243 } else {
1244 if (ctrl->val == ctrl->maximum)
1245 ctrl->cur.val = ctrl->val - 1;
1246 else
1247 ctrl->cur.val = ctrl->val + 1;
1248 }
1249
1250 /*
1251 * to cheat control framework, because of when ctrl->flags is
1252 * V4L2_CTRL_FLAG_VOLATILE, s_ctrl would not be called
1253 */
1254 switch (ctrl->id) {
1255 case V4L2_CID_EXPOSURE:
1256 case V4L2_CID_EXPOSURE_ABSOLUTE:
1257 case V4L2_CID_GAIN:
1258 if (ctrl->val != ctrl->cur.val)
1259 ctrl->flags &= ~V4L2_CTRL_FLAG_VOLATILE;
1260 break;
1261 default:
1262 break;
1263 }
1264 return 0;
1265 }
1266
1267 static const struct v4l2_ctrl_ops sunxi_isp_ctrl_ops = {
1268 .s_ctrl = sunxi_isp_s_ctrl,
1269 .try_ctrl = sunxi_isp_try_ctrl,
1270 };
1271
1272 static const struct v4l2_ctrl_config ae_win_ctrls[] = {
1273 {
1274 .ops = &sunxi_isp_ctrl_ops,
1275 .id = V4L2_CID_AE_WIN_X1,
1276 .name = "R GAIN",
1277 .type = V4L2_CTRL_TYPE_INTEGER,
1278 .min = 32,
1279 .max = 3264,
1280 .step = 16,
1281 .def = 256,
1282 .flags = V4L2_CTRL_FLAG_VOLATILE,
1283 }, {
1284 .ops = &sunxi_isp_ctrl_ops,
1285 .id = V4L2_CID_AE_WIN_Y1,
1286 .name = "R GAIN",
1287 .type = V4L2_CTRL_TYPE_INTEGER,
1288 .min = 32,
1289 .max = 3264,
1290 .step = 16,
1291 .def = 256,
1292 .flags = V4L2_CTRL_FLAG_VOLATILE,
1293 }, {
1294 .ops = &sunxi_isp_ctrl_ops,
1295 .id = V4L2_CID_AE_WIN_X2,
1296 .name = "R GAIN",
1297 .type = V4L2_CTRL_TYPE_INTEGER,
1298 .min = 32,
1299 .max = 3264,
1300 .step = 16,
1301 .def = 256,
1302 .flags = V4L2_CTRL_FLAG_VOLATILE,
1303 }, {
1304 .ops = &sunxi_isp_ctrl_ops,
1305 .id = V4L2_CID_AE_WIN_Y2,
1306 .name = "R GAIN",
1307 .type = V4L2_CTRL_TYPE_INTEGER,
1308 .min = 32,
1309 .max = 3264,
1310 .step = 16,
1311 .def = 256,
1312 .flags = V4L2_CTRL_FLAG_VOLATILE,
1313 }
1314 };
1315
1316 static const struct v4l2_ctrl_config af_win_ctrls[] = {
1317 {
1318 .ops = &sunxi_isp_ctrl_ops,
1319 .id = V4L2_CID_AF_WIN_X1,
1320 .name = "R GAIN",
1321 .type = V4L2_CTRL_TYPE_INTEGER,
1322 .min = 32,
1323 .max = 3264,
1324 .step = 16,
1325 .def = 256,
1326 .flags = V4L2_CTRL_FLAG_VOLATILE,
1327 }, {
1328 .ops = &sunxi_isp_ctrl_ops,
1329 .id = V4L2_CID_AF_WIN_Y1,
1330 .name = "R GAIN",
1331 .type = V4L2_CTRL_TYPE_INTEGER,
1332 .min = 32,
1333 .max = 3264,
1334 .step = 16,
1335 .def = 256,
1336 .flags = V4L2_CTRL_FLAG_VOLATILE,
1337 }, {
1338 .ops = &sunxi_isp_ctrl_ops,
1339 .id = V4L2_CID_AF_WIN_X2,
1340 .name = "R GAIN",
1341 .type = V4L2_CTRL_TYPE_INTEGER,
1342 .min = 32,
1343 .max = 3264,
1344 .step = 16,
1345 .def = 256,
1346 .flags = V4L2_CTRL_FLAG_VOLATILE,
1347 }, {
1348 .ops = &sunxi_isp_ctrl_ops,
1349 .id = V4L2_CID_AF_WIN_Y2,
1350 .name = "R GAIN",
1351 .type = V4L2_CTRL_TYPE_INTEGER,
1352 .min = 32,
1353 .max = 3264,
1354 .step = 16,
1355 .def = 256,
1356 .flags = V4L2_CTRL_FLAG_VOLATILE,
1357 }
1358 };
1359
1360 static const struct v4l2_ctrl_config custom_ctrls[] = {
1361 {
1362 .ops = &sunxi_isp_ctrl_ops,
1363 .id = V4L2_CID_FOCUS_LENGTH,
1364 .name = "Focus Length",
1365 .type = V4L2_CTRL_TYPE_INTEGER,
1366 .min = 0,
1367 .max = 1000,
1368 .step = 1,
1369 .def = 280,
1370 .flags = V4L2_CTRL_FLAG_VOLATILE,
1371 }, {
1372 .ops = &sunxi_isp_ctrl_ops,
1373 .id = V4L2_CID_AUTO_FOCUS_INIT,
1374 .name = "AutoFocus Initial",
1375 .type = V4L2_CTRL_TYPE_BUTTON,
1376 .min = 0,
1377 .max = 0,
1378 .step = 0,
1379 .def = 0,
1380 }, {
1381 .ops = &sunxi_isp_ctrl_ops,
1382 .id = V4L2_CID_AUTO_FOCUS_RELEASE,
1383 .name = "AutoFocus Release",
1384 .type = V4L2_CTRL_TYPE_BUTTON,
1385 .min = 0,
1386 .max = 0,
1387 .step = 0,
1388 .def = 0,
1389 }, {
1390 .ops = &sunxi_isp_ctrl_ops,
1391 .id = V4L2_CID_TAKE_PICTURE,
1392 .name = "Take Picture",
1393 .type = V4L2_CTRL_TYPE_INTEGER,
1394 .min = 0,
1395 .max = 16,
1396 .step = 1,
1397 .def = 0,
1398 }, {
1399 .ops = &sunxi_isp_ctrl_ops,
1400 .id = V4L2_CID_FLASH_LED_MODE_V1,
1401 .name = "VIN Flash ctrl",
1402 .type = V4L2_CTRL_TYPE_MENU,
1403 .min = 0,
1404 .max = 2,
1405 .def = 0,
1406 .menu_skip_mask = 0x0,
1407 .qmenu = flash_led_mode_v1,
1408 .flags = 0,
1409 .step = 0,
1410 },
1411 };
1412 static const s64 iso_qmenu[] = {
1413 100, 200, 400, 800, 1600, 3200, 6400,
1414 };
1415 static const s64 exp_bias_qmenu[] = {
1416 -4, -3, -2, -1, 0, 1, 2, 3, 4,
1417 };
1418
__isp_init_subdev(struct isp_dev * isp)1419 int __isp_init_subdev(struct isp_dev *isp)
1420 {
1421 struct v4l2_ctrl_handler *handler = &isp->ctrls.handler;
1422 struct v4l2_subdev *sd = &isp->subdev;
1423 struct sunxi_isp_ctrls *ctrls = &isp->ctrls;
1424 struct v4l2_ctrl *ctrl;
1425 int i, ret;
1426
1427 mutex_init(&isp->subdev_lock);
1428 v4l2_subdev_init(sd, &sunxi_isp_subdev_ops);
1429 sd->grp_id = VIN_GRP_ID_ISP;
1430 sd->flags |= V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_HAS_DEVNODE;
1431 snprintf(sd->name, sizeof(sd->name), "sunxi_isp.%u", isp->id);
1432 v4l2_set_subdevdata(sd, isp);
1433
1434 v4l2_ctrl_handler_init(handler, 38 + ARRAY_SIZE(ae_win_ctrls)
1435 + ARRAY_SIZE(af_win_ctrls) + ARRAY_SIZE(custom_ctrls));
1436
1437 for (i = 0; i < ARRAY_SIZE(ae_win_ctrls); i++)
1438 ctrls->ae_win[i] = v4l2_ctrl_new_custom(handler,
1439 &ae_win_ctrls[i], NULL);
1440 v4l2_ctrl_cluster(ARRAY_SIZE(ae_win_ctrls), &ctrls->ae_win[0]);
1441
1442 for (i = 0; i < ARRAY_SIZE(af_win_ctrls); i++)
1443 ctrls->af_win[i] = v4l2_ctrl_new_custom(handler,
1444 &af_win_ctrls[i], NULL);
1445 v4l2_ctrl_cluster(ARRAY_SIZE(af_win_ctrls), &ctrls->af_win[0]);
1446
1447 v4l2_ctrl_new_std(handler, &sunxi_isp_ctrl_ops, V4L2_CID_BRIGHTNESS, -128, 128, 1, 0);
1448 v4l2_ctrl_new_std(handler, &sunxi_isp_ctrl_ops, V4L2_CID_CONTRAST, -128, 128, 1, 0);
1449 v4l2_ctrl_new_std(handler, &sunxi_isp_ctrl_ops, V4L2_CID_SATURATION, -256, 512, 1, 0);
1450 v4l2_ctrl_new_std(handler, &sunxi_isp_ctrl_ops, V4L2_CID_HUE, -180, 180, 1, 0);
1451 v4l2_ctrl_new_std(handler, &sunxi_isp_ctrl_ops, V4L2_CID_AUTO_WHITE_BALANCE, 0, 1, 1, 1);
1452 v4l2_ctrl_new_std(handler, &sunxi_isp_ctrl_ops, V4L2_CID_EXPOSURE, 1, 65536 * 16, 1, 1);
1453 v4l2_ctrl_new_std(handler, &sunxi_isp_ctrl_ops, V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
1454 v4l2_ctrl_new_std(handler, &sunxi_isp_ctrl_ops, V4L2_CID_GAIN, 16, 6000 * 16, 1, 16);
1455
1456 v4l2_ctrl_new_std_menu(handler, &sunxi_isp_ctrl_ops,
1457 V4L2_CID_POWER_LINE_FREQUENCY,
1458 V4L2_CID_POWER_LINE_FREQUENCY_AUTO, 0,
1459 V4L2_CID_POWER_LINE_FREQUENCY_AUTO);
1460 v4l2_ctrl_new_std(handler, &sunxi_isp_ctrl_ops, V4L2_CID_HUE_AUTO, 0, 1, 1, 1);
1461 v4l2_ctrl_new_std(handler, &sunxi_isp_ctrl_ops,
1462 V4L2_CID_WHITE_BALANCE_TEMPERATURE, 2800, 10000, 1, 6500);
1463 v4l2_ctrl_new_std(handler, &sunxi_isp_ctrl_ops, V4L2_CID_SHARPNESS, 0, 1000, 1, 0);
1464 v4l2_ctrl_new_std(handler, &sunxi_isp_ctrl_ops, V4L2_CID_CHROMA_AGC, 0, 1, 1, 1);
1465 v4l2_ctrl_new_std_menu(handler, &sunxi_isp_ctrl_ops, V4L2_CID_COLORFX,
1466 V4L2_COLORFX_SET_CBCR, 0, V4L2_COLORFX_NONE);
1467 v4l2_ctrl_new_std(handler, &sunxi_isp_ctrl_ops, V4L2_CID_AUTOBRIGHTNESS, 0, 1, 1, 1);
1468 v4l2_ctrl_new_std(handler, &sunxi_isp_ctrl_ops, V4L2_CID_BAND_STOP_FILTER, 0, 1, 1, 1);
1469 v4l2_ctrl_new_std(handler, &sunxi_isp_ctrl_ops, V4L2_CID_ILLUMINATORS_1, 0, 1, 1, 0);
1470 v4l2_ctrl_new_std(handler, &sunxi_isp_ctrl_ops, V4L2_CID_ILLUMINATORS_2, 0, 1, 1, 0);
1471 v4l2_ctrl_new_std_menu(handler, &sunxi_isp_ctrl_ops, V4L2_CID_EXPOSURE_AUTO,
1472 V4L2_EXPOSURE_APERTURE_PRIORITY, 0,
1473 V4L2_EXPOSURE_AUTO);
1474 v4l2_ctrl_new_std(handler, &sunxi_isp_ctrl_ops, V4L2_CID_EXPOSURE_ABSOLUTE, 1, 30 * 1000000, 1, 1);
1475 v4l2_ctrl_new_std(handler, &sunxi_isp_ctrl_ops, V4L2_CID_EXPOSURE_AUTO_PRIORITY, 0, 1, 1, 0);
1476 v4l2_ctrl_new_std(handler, &sunxi_isp_ctrl_ops, V4L2_CID_FOCUS_ABSOLUTE, 0, 127, 1, 0);
1477 v4l2_ctrl_new_std(handler, &sunxi_isp_ctrl_ops, V4L2_CID_FOCUS_RELATIVE, -127, 127, 1, 0);
1478 v4l2_ctrl_new_std(handler, &sunxi_isp_ctrl_ops, V4L2_CID_FOCUS_AUTO, 0, 1, 1, 1);
1479 v4l2_ctrl_new_int_menu(handler, &sunxi_isp_ctrl_ops, V4L2_CID_AUTO_EXPOSURE_BIAS,
1480 ARRAY_SIZE(exp_bias_qmenu) - 1,
1481 ARRAY_SIZE(exp_bias_qmenu) / 2, exp_bias_qmenu);
1482 v4l2_ctrl_new_std_menu(handler, &sunxi_isp_ctrl_ops,
1483 V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE,
1484 V4L2_WHITE_BALANCE_SHADE, 0,
1485 V4L2_WHITE_BALANCE_AUTO);
1486 v4l2_ctrl_new_std(handler, &sunxi_isp_ctrl_ops, V4L2_CID_WIDE_DYNAMIC_RANGE, 0, 1, 1, 0);
1487 v4l2_ctrl_new_std(handler, &sunxi_isp_ctrl_ops, V4L2_CID_IMAGE_STABILIZATION, 0, 1, 1, 0);
1488 v4l2_ctrl_new_int_menu(handler, &sunxi_isp_ctrl_ops, V4L2_CID_ISO_SENSITIVITY,
1489 ARRAY_SIZE(iso_qmenu) - 1,
1490 ARRAY_SIZE(iso_qmenu) / 2 - 1, iso_qmenu);
1491 v4l2_ctrl_new_std_menu(handler, &sunxi_isp_ctrl_ops,
1492 V4L2_CID_ISO_SENSITIVITY_AUTO,
1493 V4L2_ISO_SENSITIVITY_AUTO, 0,
1494 V4L2_ISO_SENSITIVITY_AUTO);
1495 v4l2_ctrl_new_std_menu(handler, &sunxi_isp_ctrl_ops,
1496 V4L2_CID_EXPOSURE_METERING,
1497 V4L2_EXPOSURE_METERING_MATRIX, 0,
1498 V4L2_EXPOSURE_METERING_AVERAGE);
1499 v4l2_ctrl_new_std_menu(handler, &sunxi_isp_ctrl_ops, V4L2_CID_SCENE_MODE,
1500 V4L2_SCENE_MODE_TEXT, 0, V4L2_SCENE_MODE_NONE);
1501 ctrl = v4l2_ctrl_new_std(handler, &sunxi_isp_ctrl_ops, V4L2_CID_3A_LOCK, 0, 7, 0, 0);
1502 if (ctrl != NULL)
1503 ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
1504
1505 v4l2_ctrl_new_std(handler, &sunxi_isp_ctrl_ops, V4L2_CID_AUTO_FOCUS_START, 0, 0, 0, 0);
1506 v4l2_ctrl_new_std(handler, &sunxi_isp_ctrl_ops, V4L2_CID_AUTO_FOCUS_STOP, 0, 0, 0, 0);
1507 ctrl = v4l2_ctrl_new_std(handler, &sunxi_isp_ctrl_ops, V4L2_CID_AUTO_FOCUS_STATUS, 0, 7, 0, 0);
1508 if (ctrl != NULL)
1509 ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
1510
1511 v4l2_ctrl_new_std_menu(handler, &sunxi_isp_ctrl_ops, V4L2_CID_AUTO_FOCUS_RANGE,
1512 V4L2_AUTO_FOCUS_RANGE_INFINITY, 0,
1513 V4L2_AUTO_FOCUS_RANGE_AUTO);
1514 v4l2_ctrl_new_std_menu(handler, &sunxi_isp_ctrl_ops, V4L2_CID_FLASH_LED_MODE,
1515 V4L2_FLASH_LED_MODE_RED_EYE, 0,
1516 V4L2_FLASH_LED_MODE_NONE);
1517
1518 for (i = 0; i < ARRAY_SIZE(custom_ctrls); i++)
1519 v4l2_ctrl_new_custom(handler, &custom_ctrls[i], NULL);
1520
1521 if (handler->error)
1522 return handler->error;
1523
1524 /*sd->entity->ops = &isp_media_ops;*/
1525 isp->isp_pads[ISP_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
1526 isp->isp_pads[ISP_PAD_SOURCE_ST].flags = MEDIA_PAD_FL_SOURCE;
1527 isp->isp_pads[ISP_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
1528 sd->entity.function = MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER;
1529
1530 ret = media_entity_pads_init(&sd->entity, ISP_PAD_NUM, isp->isp_pads);
1531 if (ret < 0)
1532 return ret;
1533
1534 sd->ctrl_handler = handler;
1535 /*sd->internal_ops = &sunxi_isp_sd_internal_ops;*/
1536 return 0;
1537 }
1538
isp_resource_alloc(struct isp_dev * isp)1539 static int isp_resource_alloc(struct isp_dev *isp)
1540 {
1541 int ret = 0;
1542 #if !defined CONFIG_ARCH_SUN8IW16P1 && !defined CONFIG_ARCH_SUN8IW19P1 && !defined CONFIG_ARCH_SUN50IW10
1543 isp->isp_stat.size = ISP_SAVE_DRAM_SIZE + ISP_LOAD_DRAM_SIZE;
1544 ret = os_mem_alloc(&isp->pdev->dev, &isp->isp_stat);
1545 if (ret < 0) {
1546 vin_err("isp statistic buf requset failed!\n");
1547 return -ENOMEM;
1548 }
1549 isp->isp_save.dma_addr = isp->isp_stat.dma_addr + ISP_STAT_TOTAL_SIZE;
1550 isp->isp_save.vir_addr = isp->isp_stat.vir_addr + ISP_STAT_TOTAL_SIZE;
1551 isp->isp_load.dma_addr = isp->isp_save.dma_addr + ISP_SAVED_REG_SIZE;
1552 isp->isp_load.vir_addr = isp->isp_save.vir_addr + ISP_SAVED_REG_SIZE;
1553 isp->isp_lut_tbl.dma_addr = isp->isp_load.dma_addr + ISP_LOAD_REG_SIZE;
1554 isp->isp_lut_tbl.vir_addr = isp->isp_load.vir_addr + ISP_LOAD_REG_SIZE;
1555 isp->isp_drc_tbl.dma_addr = isp->isp_lut_tbl.dma_addr + ISP_TABLE_MAPPING1_SIZE;
1556 isp->isp_drc_tbl.vir_addr = isp->isp_lut_tbl.vir_addr + ISP_TABLE_MAPPING1_SIZE;
1557 #else
1558 isp->isp_stat.size = ISP_SAVE_DRAM_SIZE + ISP_LOAD_DRAM_SIZE;
1559 ret = os_mem_alloc(&isp->pdev->dev, &isp->isp_stat);
1560 if (ret < 0) {
1561 vin_err("isp statistic buf requset failed!\n");
1562 return -ENOMEM;
1563 }
1564 isp->isp_load.dma_addr = isp->isp_stat.dma_addr + ISP_STAT_TOTAL_SIZE;
1565 isp->isp_load.vir_addr = isp->isp_stat.vir_addr + ISP_STAT_TOTAL_SIZE;
1566 isp->isp_save.dma_addr = isp->isp_stat.dma_addr;
1567 isp->isp_save.vir_addr = isp->isp_stat.vir_addr;
1568 #endif
1569 return ret;
1570 }
isp_resource_free(struct isp_dev * isp)1571 static void isp_resource_free(struct isp_dev *isp)
1572 {
1573 os_mem_free(&isp->pdev->dev, &isp->isp_stat);
1574 }
1575
isp_isr(int irq,void * priv)1576 static irqreturn_t isp_isr(int irq, void *priv)
1577 {
1578 struct isp_dev *isp = (struct isp_dev *)priv;
1579 unsigned int load_val;
1580 unsigned long flags;
1581
1582 if (!isp->use_isp)
1583 return 0;
1584
1585 if (isp->subdev.entity.stream_count == 0) {
1586 bsp_isp_clr_irq_status(isp->id, ISP_IRQ_EN_ALL);
1587 return IRQ_HANDLED;
1588 }
1589
1590 vin_log(VIN_LOG_ISP, "isp%d interrupt, status is 0x%x!!!\n", isp->id,
1591 bsp_isp_get_irq_status(isp->id, ISP_IRQ_STATUS_ALL));
1592
1593 spin_lock_irqsave(&isp->slock, flags);
1594 #if !defined CONFIG_ARCH_SUN8IW16P1 && !defined CONFIG_ARCH_SUN8IW19P1 && !defined CONFIG_ARCH_SUN50IW10
1595 if (bsp_isp_get_irq_status(isp->id, SRC0_FIFO_OF_PD)) {
1596 vin_err("isp%d source0 fifo overflow\n", isp->id);
1597 bsp_isp_clr_irq_status(isp->id, SRC0_FIFO_OF_PD);
1598 if (bsp_isp_get_irq_status(isp->id, CIN_FIFO_OF_PD)) {
1599 vin_err("isp%d Cin0 fifo overflow\n", isp->id);
1600 bsp_isp_clr_irq_status(isp->id, CIN_FIFO_OF_PD);
1601 }
1602 if (bsp_isp_get_irq_status(isp->id, DPC_FIFO_OF_PD)) {
1603 vin_err("isp%d DPC fifo overflow\n", isp->id);
1604 bsp_isp_clr_irq_status(isp->id, DPC_FIFO_OF_PD);
1605 }
1606 if (bsp_isp_get_irq_status(isp->id, D2D_FIFO_OF_PD)) {
1607 vin_err("isp%d D2D fifo overflow\n", isp->id);
1608 bsp_isp_clr_irq_status(isp->id, D2D_FIFO_OF_PD);
1609 }
1610 if (bsp_isp_get_irq_status(isp->id, BIS_FIFO_OF_PD)) {
1611 vin_err("isp%d BIS fifo overflow\n", isp->id);
1612 bsp_isp_clr_irq_status(isp->id, BIS_FIFO_OF_PD);
1613 }
1614 if (bsp_isp_get_irq_status(isp->id, CNR_FIFO_OF_PD)) {
1615 vin_err("isp%d CNR fifo overflow\n", isp->id);
1616 bsp_isp_clr_irq_status(isp->id, CNR_FIFO_OF_PD);
1617 }
1618 if (bsp_isp_get_irq_status(isp->id, PLTM_FIFO_OF_PD)) {
1619 vin_err("isp%d PLTM fifo overflow\n", isp->id);
1620 bsp_isp_clr_irq_status(isp->id, PLTM_FIFO_OF_PD);
1621 }
1622 if (bsp_isp_get_irq_status(isp->id, D3D_WRITE_FIFO_OF_PD)) {
1623 vin_err("isp%d D3D cmp write to DDR fifo overflow\n", isp->id);
1624 bsp_isp_clr_irq_status(isp->id, D3D_WRITE_FIFO_OF_PD);
1625 }
1626 if (bsp_isp_get_irq_status(isp->id, D3D_READ_FIFO_OF_PD)) {
1627 vin_err("isp%d D3D umcmp read from DDR fifo empty\n", isp->id);
1628 bsp_isp_clr_irq_status(isp->id, D3D_READ_FIFO_OF_PD);
1629 }
1630 if (bsp_isp_get_irq_status(isp->id, D3D_WT2CMP_FIFO_OF_PD)) {
1631 vin_err("isp%d D3D write to cmp fifo overflow\n", isp->id);
1632 bsp_isp_clr_irq_status(isp->id, D3D_WT2CMP_FIFO_OF_PD);
1633 }
1634
1635 if (bsp_isp_get_irq_status(isp->id, WDR_WRITE_FIFO_OF_PD)) {
1636 vin_err("isp%d WDR cmp write to DDR fifo overflow\n", isp->id);
1637 bsp_isp_clr_irq_status(isp->id, WDR_WRITE_FIFO_OF_PD);
1638 }
1639 if (bsp_isp_get_irq_status(isp->id, WDR_READ_FIFO_OF_PD)) {
1640 vin_err("isp%d WDR umcmp read from DDR fifo empty\n", isp->id);
1641 bsp_isp_clr_irq_status(isp->id, WDR_READ_FIFO_OF_PD);
1642 }
1643 if (bsp_isp_get_irq_status(isp->id, WDR_WT2CMP_FIFO_OF_PD)) {
1644 vin_err("isp%d WDR write to cmp fifo overflow\n", isp->id);
1645 bsp_isp_clr_irq_status(isp->id, WDR_WT2CMP_FIFO_OF_PD);
1646 }
1647 if (bsp_isp_get_irq_status(isp->id, D3D_HB_PD)) {
1648 vin_err("isp%d Hblanking is not enough for D3D\n", isp->id);
1649 bsp_isp_clr_irq_status(isp->id, D3D_HB_PD);
1650 }
1651 /*isp reset*/
1652 sunxi_isp_reset(isp);
1653 }
1654 #else
1655 if (bsp_isp_get_irq_status(isp->id, S0_FIFO_OF_PD)) {
1656 vin_err("isp%d source0 fifo overflow\n", isp->id);
1657 bsp_isp_clr_irq_status(isp->id, S0_FIFO_OF_PD);
1658 if (bsp_isp_get_internal_status0(isp->id, S0_CIN_FIFO_OF_PD)) {
1659 vin_err("isp%d Cin0 fifo overflow\n", isp->id);
1660 bsp_isp_clr_internal_status0(isp->id, S0_CIN_FIFO_OF_PD);
1661 }
1662 if (bsp_isp_get_internal_status0(isp->id, BIS_FIFO_OF_PD)) {
1663 vin_err("isp%d BIS fifo overflow\n", isp->id);
1664 bsp_isp_clr_internal_status0(isp->id, BIS_FIFO_OF_PD);
1665 }
1666 #if !defined CONFIG_ARCH_SUN50IW10
1667 if (bsp_isp_get_internal_status0(isp->id, DPC_FIFO_OF_PD)) {
1668 vin_err("isp%d DPC fifo overflow\n", isp->id);
1669 bsp_isp_clr_internal_status0(isp->id, DPC_FIFO_OF_PD);
1670 }
1671 if (bsp_isp_get_internal_status0(isp->id, CNR_FIFO_OF_PD)) {
1672 vin_err("isp%d CNR fifo overflow\n", isp->id);
1673 bsp_isp_clr_internal_status0(isp->id, CNR_FIFO_OF_PD);
1674 }
1675 if (bsp_isp_get_internal_status0(isp->id, PLTM_FIFO_OF_PD)) {
1676 vin_err("isp%d PLTM fifo overflow\n", isp->id);
1677 bsp_isp_clr_internal_status0(isp->id, PLTM_FIFO_OF_PD);
1678 }
1679 if (bsp_isp_get_internal_status0(isp->id, D3D_WRITE_FIFO_OF_PD)) {
1680 vin_err("isp%d D3D cmp write to DDR fifo overflow\n", isp->id);
1681 bsp_isp_clr_internal_status0(isp->id, D3D_WRITE_FIFO_OF_PD);
1682 }
1683 if (bsp_isp_get_internal_status0(isp->id, D3D_READ_FIFO_OF_PD)) {
1684 vin_err("isp%d D3D umcmp read from DDR fifo empty\n", isp->id);
1685 bsp_isp_clr_internal_status0(isp->id, D3D_READ_FIFO_OF_PD);
1686 }
1687 if (bsp_isp_get_internal_status0(isp->id, WDR_WRITE_FIFO_OF_PD)) {
1688 vin_err("isp%d WDR cmp write to DDR fifo overflow\n", isp->id);
1689 bsp_isp_clr_internal_status0(isp->id, WDR_WRITE_FIFO_OF_PD);
1690 }
1691 if (bsp_isp_get_internal_status0(isp->id, WDR_READ_FIFO_OF_PD)) {
1692 vin_err("isp%d WDR umcmp read from DDR fifo empty\n", isp->id);
1693 bsp_isp_clr_internal_status0(isp->id, WDR_READ_FIFO_OF_PD);
1694 }
1695 #endif
1696 #if defined CONFIG_ARCH_SUN8IW19P1
1697 if (bsp_isp_get_internal_status0(isp->id, LCA_RGB_FIFO_R_EMP_PD)) {
1698 vin_err("isp%d RGB fifo of LCA read empty\n", isp->id);
1699 bsp_isp_clr_internal_status0(isp->id, LCA_RGB_FIFO_R_EMP_PD);
1700 }
1701 if (bsp_isp_get_internal_status0(isp->id, LCA_RGB_FIFO_W_FULL_PD)) {
1702 vin_err("isp%d RGB fifo of LCA write full\n", isp->id);
1703 bsp_isp_clr_internal_status0(isp->id, LCA_RGB_FIFO_W_FULL_PD);
1704 }
1705 if (bsp_isp_get_internal_status0(isp->id, LCA_BY_FIFO_R_EMP_PD)) {
1706 vin_err("isp%d bayer fifo of LCA read empty\n", isp->id);
1707 bsp_isp_clr_internal_status0(isp->id, LCA_BY_FIFO_R_EMP_PD);
1708 }
1709 if (bsp_isp_get_internal_status0(isp->id, LCA_BY_FIFO_W_FULL_PD)) {
1710 vin_err("isp%d bayer fifo of LCA write full\n", isp->id);
1711 bsp_isp_clr_internal_status0(isp->id, LCA_BY_FIFO_W_FULL_PD);
1712 }
1713 if (bsp_isp_get_internal_status0(isp->id, D3D_K_FIFO_W_FULL_PD)) {
1714 vin_err("isp%d write fifo of D3D K data full\n", isp->id);
1715 bsp_isp_clr_internal_status0(isp->id, D3D_K_FIFO_W_FULL_PD);
1716 }
1717 if (bsp_isp_get_internal_status0(isp->id, D3D_RAW_FIFO_W_FULL_PD)) {
1718 vin_err("isp%d write fifo of D3D RAW data full\n", isp->id);
1719 bsp_isp_clr_internal_status0(isp->id, D3D_RAW_FIFO_W_FULL_PD);
1720 }
1721 if (bsp_isp_get_internal_status0(isp->id, D3D_K_FIFO_R_EMP_PD)) {
1722 vin_err("isp%d read fifo of D3D K data empty\n", isp->id);
1723 bsp_isp_clr_internal_status0(isp->id, D3D_K_FIFO_R_EMP_PD);
1724 }
1725 if (bsp_isp_get_internal_status0(isp->id, D3D_REF_FIFO_R_EMP_PD)) {
1726 vin_err("isp%d read fifo of D3D REF data empty\n", isp->id);
1727 bsp_isp_clr_internal_status0(isp->id, D3D_REF_FIFO_R_EMP_PD);
1728 }
1729 if (bsp_isp_get_internal_status0(isp->id, D3D_LTF_FIFO_R_EMP_PD)) {
1730 vin_err("isp%d read fifo of D3D LTF data empty\n", isp->id);
1731 bsp_isp_clr_internal_status0(isp->id, D3D_LTF_FIFO_R_EMP_PD);
1732 }
1733 #endif
1734 /*isp reset*/
1735 sunxi_isp_reset(isp);
1736 }
1737 #endif
1738 if (bsp_isp_get_irq_status(isp->id, HB_SHORT_PD)) {
1739 vin_err("isp%d Hblanking is short (less than 96 cycles)\n", isp->id);
1740 bsp_isp_clr_irq_status(isp->id, HB_SHORT_PD);
1741 }
1742
1743 if (bsp_isp_get_irq_status(isp->id, FRAME_ERROR_PD)) {
1744 bsp_isp_get_s0_ch_fmerr_cnt(isp->id, &isp->err_size);
1745 bsp_isp_get_s0_ch_hb_cnt(isp->id, &isp->hb_max, &isp->hb_min);
1746 vin_err("isp%d frame error, size %d %d, hblank max %d min %d!!\n", isp->id,
1747 isp->err_size.width, isp->err_size.height, isp->hb_max, isp->hb_min);
1748 bsp_isp_clr_irq_status(isp->id, FRAME_ERROR_PD);
1749 sunxi_isp_reset(isp);
1750 }
1751
1752 if (bsp_isp_get_irq_status(isp->id, FRAME_LOST_PD)) {
1753 vin_err("isp%d frame lost\n", isp->id);
1754 bsp_isp_clr_irq_status(isp->id, FRAME_LOST_PD);
1755 sunxi_isp_reset(isp);
1756 }
1757
1758 #if defined CONFIG_ARCH_SUN8IW19P1
1759 if (bsp_isp_get_irq_status(isp->id, S0_BTYPE_ERROR_PD)) {
1760 vin_err("isp%d input btype error\n", isp->id);
1761 bsp_isp_clr_irq_status(isp->id, S0_BTYPE_ERROR_PD);
1762 }
1763
1764 if (bsp_isp_get_irq_status(isp->id, ADDR_ERROR_PD)) {
1765 vin_err("isp%d aligned addr error\n", isp->id);
1766 bsp_isp_clr_irq_status(isp->id, ADDR_ERROR_PD);
1767 }
1768
1769 if (bsp_isp_get_irq_status(isp->id, LBC_ERROR_PD)) {
1770 vin_err("isp%d LBC de-compress error\n", isp->id);
1771 bsp_isp_clr_irq_status(isp->id, LBC_ERROR_PD);
1772 if (bsp_isp_get_lbc_internal_status(isp->id, WDR_LBC_DEC_ERR_PD)) {
1773 vin_err("isp%d WDR LBC decode error\n", isp->id);
1774 if (bsp_isp_get_lbc_internal_status(isp->id, LBC_MSQ_DEC_ERR_PD << WDR_LBC_DEC_ERR_OFF)) {
1775 vin_err("isp%d msq decode error\n", isp->id);
1776 bsp_isp_clr_lbc_internal_status(isp->id, LBC_MSQ_DEC_ERR_PD << WDR_LBC_DEC_ERR_OFF);
1777 }
1778 if (bsp_isp_get_lbc_internal_status(isp->id, LBC_DTS_DEC_ERR_PD << WDR_LBC_DEC_ERR_OFF)) {
1779 vin_err("isp%d dts decode error\n", isp->id);
1780 bsp_isp_clr_lbc_internal_status(isp->id, LBC_DTS_DEC_ERR_PD << WDR_LBC_DEC_ERR_OFF);
1781 }
1782 if (bsp_isp_get_lbc_internal_status(isp->id, LBC_QP_DEC_ERR_PD << WDR_LBC_DEC_ERR_OFF)) {
1783 vin_err("isp%d qp decode error\n", isp->id);
1784 bsp_isp_clr_lbc_internal_status(isp->id, LBC_QP_DEC_ERR_PD << WDR_LBC_DEC_ERR_OFF);
1785 }
1786 if (bsp_isp_get_lbc_internal_status(isp->id, LBC_CODEC_BIT_LOST_PD << WDR_LBC_DEC_ERR_OFF)) {
1787 vin_err("isp%d codec bit lost error\n", isp->id);
1788 bsp_isp_clr_lbc_internal_status(isp->id, LBC_CODEC_BIT_LOST_PD << WDR_LBC_DEC_ERR_OFF);
1789 }
1790 if (bsp_isp_get_lbc_internal_status(isp->id, LBC_CODEC_RED_ERR_PD << WDR_LBC_DEC_ERR_OFF)) {
1791 vin_err("isp%d codec redundancy error\n", isp->id);
1792 bsp_isp_clr_lbc_internal_status(isp->id, LBC_CODEC_RED_ERR_PD << WDR_LBC_DEC_ERR_OFF);
1793 }
1794 }
1795 if (bsp_isp_get_lbc_internal_status(isp->id, D3D_K_LBC_DEC_ERR_PD)) {
1796 vin_err("isp%d D3D K LBC decode error\n", isp->id);
1797 if (bsp_isp_get_lbc_internal_status(isp->id, LBC_MSQ_DEC_ERR_PD << D3D_K_LBC_DEC_ERR_OFF)) {
1798 vin_err("isp%d msq decode error\n", isp->id);
1799 bsp_isp_clr_lbc_internal_status(isp->id, LBC_MSQ_DEC_ERR_PD << D3D_K_LBC_DEC_ERR_OFF);
1800 }
1801 if (bsp_isp_get_lbc_internal_status(isp->id, LBC_DTS_DEC_ERR_PD << D3D_K_LBC_DEC_ERR_OFF)) {
1802 vin_err("isp%d dts decode error\n", isp->id);
1803 bsp_isp_clr_lbc_internal_status(isp->id, LBC_DTS_DEC_ERR_PD << D3D_K_LBC_DEC_ERR_OFF);
1804 }
1805 if (bsp_isp_get_lbc_internal_status(isp->id, LBC_QP_DEC_ERR_PD << D3D_K_LBC_DEC_ERR_OFF)) {
1806 vin_err("isp%d qp decode error\n", isp->id);
1807 bsp_isp_clr_lbc_internal_status(isp->id, LBC_QP_DEC_ERR_PD << D3D_K_LBC_DEC_ERR_OFF);
1808 }
1809 if (bsp_isp_get_lbc_internal_status(isp->id, LBC_CODEC_BIT_LOST_PD << D3D_K_LBC_DEC_ERR_OFF)) {
1810 vin_err("isp%d codec bit lost error\n", isp->id);
1811 bsp_isp_clr_lbc_internal_status(isp->id, LBC_CODEC_BIT_LOST_PD << D3D_K_LBC_DEC_ERR_OFF);
1812 }
1813 if (bsp_isp_get_lbc_internal_status(isp->id, LBC_CODEC_RED_ERR_PD << D3D_K_LBC_DEC_ERR_OFF)) {
1814 vin_err("isp%d codec redundancy error\n", isp->id);
1815 bsp_isp_clr_lbc_internal_status(isp->id, LBC_CODEC_RED_ERR_PD << D3D_K_LBC_DEC_ERR_OFF);
1816 }
1817 }
1818 if (bsp_isp_get_lbc_internal_status(isp->id, D3D_REF_LBC_DEC_ERR_PD)) {
1819 vin_err("isp%d D3D reference frame LBC decode error\n", isp->id);
1820 if (bsp_isp_get_lbc_internal_status(isp->id, LBC_MSQ_DEC_ERR_PD << D3D_REF_LBC_DEC_ERR_OFF)) {
1821 vin_err("isp%d msq decode error\n", isp->id);
1822 bsp_isp_clr_lbc_internal_status(isp->id, LBC_MSQ_DEC_ERR_PD << D3D_REF_LBC_DEC_ERR_OFF);
1823 }
1824 if (bsp_isp_get_lbc_internal_status(isp->id, LBC_DTS_DEC_ERR_PD << D3D_REF_LBC_DEC_ERR_OFF)) {
1825 vin_err("isp%d dts decode error\n", isp->id);
1826 bsp_isp_clr_lbc_internal_status(isp->id, LBC_DTS_DEC_ERR_PD << D3D_REF_LBC_DEC_ERR_OFF);
1827 }
1828 if (bsp_isp_get_lbc_internal_status(isp->id, LBC_QP_DEC_ERR_PD << D3D_REF_LBC_DEC_ERR_OFF)) {
1829 vin_err("isp%d qp decode error\n", isp->id);
1830 bsp_isp_clr_lbc_internal_status(isp->id, LBC_QP_DEC_ERR_PD << D3D_REF_LBC_DEC_ERR_OFF);
1831 }
1832 if (bsp_isp_get_lbc_internal_status(isp->id, LBC_CODEC_BIT_LOST_PD << D3D_REF_LBC_DEC_ERR_OFF)) {
1833 vin_err("isp%d codec bit lost error\n", isp->id);
1834 bsp_isp_clr_lbc_internal_status(isp->id, LBC_CODEC_BIT_LOST_PD << D3D_REF_LBC_DEC_ERR_OFF);
1835 }
1836 if (bsp_isp_get_lbc_internal_status(isp->id, LBC_CODEC_RED_ERR_PD << D3D_REF_LBC_DEC_ERR_OFF)) {
1837 vin_err("isp%d codec redundancy error\n", isp->id);
1838 bsp_isp_clr_lbc_internal_status(isp->id, LBC_CODEC_RED_ERR_PD << D3D_REF_LBC_DEC_ERR_OFF);
1839 }
1840 }
1841 if (bsp_isp_get_lbc_internal_status(isp->id, D3D_LTF_LBC_DEV_ERR_PD)) {
1842 vin_err("isp%d D3D long time reference frame LBC decode error\n", isp->id);
1843 if (bsp_isp_get_lbc_internal_status(isp->id, LBC_MSQ_DEC_ERR_PD << D3D_LTF_LBC_DEV_ERR_OFF)) {
1844 vin_err("isp%d msq decode error\n", isp->id);
1845 bsp_isp_clr_lbc_internal_status(isp->id, LBC_MSQ_DEC_ERR_PD << D3D_LTF_LBC_DEV_ERR_OFF);
1846 }
1847 if (bsp_isp_get_lbc_internal_status(isp->id, LBC_DTS_DEC_ERR_PD << D3D_LTF_LBC_DEV_ERR_OFF)) {
1848 vin_err("isp%d dts decode error\n", isp->id);
1849 bsp_isp_clr_lbc_internal_status(isp->id, LBC_DTS_DEC_ERR_PD << D3D_LTF_LBC_DEV_ERR_OFF);
1850 }
1851 if (bsp_isp_get_lbc_internal_status(isp->id, LBC_QP_DEC_ERR_PD << D3D_LTF_LBC_DEV_ERR_OFF)) {
1852 vin_err("isp%d qp decode error\n", isp->id);
1853 bsp_isp_clr_lbc_internal_status(isp->id, LBC_QP_DEC_ERR_PD << D3D_LTF_LBC_DEV_ERR_OFF);
1854 }
1855 if (bsp_isp_get_lbc_internal_status(isp->id, LBC_CODEC_BIT_LOST_PD << D3D_LTF_LBC_DEV_ERR_OFF)) {
1856 vin_err("isp%d codec bit lost error\n", isp->id);
1857 bsp_isp_clr_lbc_internal_status(isp->id, LBC_CODEC_BIT_LOST_PD << D3D_LTF_LBC_DEV_ERR_OFF);
1858 }
1859 if (bsp_isp_get_lbc_internal_status(isp->id, LBC_CODEC_RED_ERR_PD << D3D_LTF_LBC_DEV_ERR_OFF)) {
1860 vin_err("isp%d codec redundancy error\n", isp->id);
1861 bsp_isp_clr_lbc_internal_status(isp->id, LBC_CODEC_RED_ERR_PD << D3D_LTF_LBC_DEV_ERR_OFF);
1862 }
1863 }
1864 }
1865 #endif
1866
1867 if (bsp_isp_get_irq_status(isp->id, PARA_LOAD_PD)) {
1868 bsp_isp_clr_irq_status(isp->id, PARA_LOAD_PD);
1869 if (isp->ptn_type) {
1870 spin_unlock_irqrestore(&isp->slock, flags);
1871 return IRQ_HANDLED;
1872 }
1873 bsp_isp_set_para_ready(isp->id, PARA_NOT_READY);
1874 if (isp->load_flag)
1875 memcpy(isp->isp_load.vir_addr, &isp->load_shadow[0], ISP_LOAD_DRAM_SIZE);
1876 isp->isp_ob.set_cnt++;
1877 load_val = bsp_isp_load_update_flag(isp->id);
1878 if (isp->wdr_mode != ISP_NORMAL_MODE)
1879 isp_wdr_pingpong_set(isp);
1880 else {
1881 vin_log(VIN_LOG_ISP, "please close wdr in normal mode!!\n");
1882 load_val = load_val & ~WDR_UPDATE;
1883 bsp_isp_module_disable(isp->id, WDR_EN);
1884 #if !defined CONFIG_ARCH_SUN8IW16P1 && !defined CONFIG_ARCH_SUN8IW19P1 && !defined CONFIG_ARCH_SUN50IW10
1885 bsp_isp_set_wdr_mode(isp->id, ISP_NORMAL_MODE);
1886 #endif
1887 }
1888 if (isp->large_image == 2) {
1889 bsp_isp_module_disable(isp->id, PLTM_EN | D3D_EN | AE_EN | AWB_EN | AF_EN | HIST_EN);
1890 if (isp->left_right == 1) {
1891 isp->left_right = 0;
1892 isp->isp_ob.ob_start.hor -= isp->isp_ob.ob_valid.width - LARGE_IMAGE_OFF * 2;
1893 } else {
1894 isp->left_right = 1;
1895 isp->isp_ob.ob_start.hor += isp->isp_ob.ob_valid.width - LARGE_IMAGE_OFF * 2;
1896 }
1897 }
1898 #if !defined CONFIG_D3D
1899 bsp_isp_module_disable(isp->id, D3D_EN);
1900 load_val = load_val & ~D3D_UPDATE;
1901 #endif
1902 bsp_isp_set_size(isp->id, &isp->isp_ob);
1903 bsp_isp_update_table(isp->id, (unsigned short)load_val);
1904 #if defined CONFIG_ARCH_SUN8IW12P1 || defined CONFIG_ARCH_SUN8IW17P1 || defined CONFIG_ARCH_SUN8IW19P1
1905 isp_3d_pingpong_update(isp);
1906 #endif
1907 bsp_isp_set_para_ready(isp->id, PARA_READY);
1908 }
1909 spin_unlock_irqrestore(&isp->slock, flags);
1910
1911 if (bsp_isp_get_irq_status(isp->id, FINISH_PD)) {
1912 isp->isp_frame_number++;
1913 bsp_isp_clr_irq_status(isp->id, FINISH_PD);
1914 #ifdef SUPPORT_PTN
1915 if (isp->ptn_type) {
1916 bsp_isp_set_para_ready(isp->id, PARA_NOT_READY);
1917 memcpy(isp->isp_load.vir_addr, &isp->load_shadow[0] + (isp->ptn_isp_cnt%3) * ISP_LOAD_DRAM_SIZE, ISP_LOAD_DRAM_SIZE);
1918 isp->ptn_isp_cnt++;
1919 load_val = bsp_isp_load_update_flag(isp->id);
1920 bsp_isp_set_size(isp->id, &isp->isp_ob);
1921 bsp_isp_update_table(isp->id, (unsigned short)load_val);
1922 isp_3d_pingpong_update(isp);
1923 bsp_isp_set_para_ready(isp->id, PARA_READY);
1924 }
1925 #endif
1926 if (!isp->f1_after_librun) {
1927 sunxi_isp_frame_sync_isr(&isp->subdev);
1928 if (isp->h3a_stat.stat_en_flag)
1929 isp->f1_after_librun = 1;
1930 } else {
1931 if (isp->load_flag || (isp->event_lost_cnt == 10)) {
1932 sunxi_isp_frame_sync_isr(&isp->subdev);
1933 isp->event_lost_cnt = 0;
1934 } else {
1935 isp->event_lost_cnt++;
1936 }
1937 }
1938 isp->load_flag = 0;
1939 }
1940
1941 return IRQ_HANDLED;
1942 }
1943
1944 static unsigned int isp_id;
1945
isp_probe(struct platform_device * pdev)1946 static int isp_probe(struct platform_device *pdev)
1947 {
1948 struct device_node *np = pdev->dev.of_node;
1949 struct isp_dev *isp = NULL;
1950 int ret = 0;
1951
1952 if (np == NULL) {
1953 vin_err("ISP failed to get of node\n");
1954 return -ENODEV;
1955 }
1956
1957 isp = kzalloc(sizeof(struct isp_dev), GFP_KERNEL);
1958 if (!isp) {
1959 ret = -ENOMEM;
1960 goto ekzalloc;
1961 }
1962
1963 of_property_read_u32(np, "device_id", &pdev->id);
1964 if (pdev->id < 0) {
1965 vin_err("ISP failed to get device id\n");
1966 ret = -EINVAL;
1967 goto freedev;
1968 }
1969
1970 isp->id = pdev->id;
1971 isp->pdev = pdev;
1972 isp->nosend_ispoff = 0;
1973
1974 if (isp->id > 0xf0) {
1975 isp->is_empty = 1;
1976 isp->id = isp_id;
1977 isp_id++;
1978 } else {
1979 isp->base = of_iomap(np, 0);
1980 isp->is_empty = 0;
1981 /*get irq resource */
1982 isp->irq = irq_of_parse_and_map(np, 0);
1983 if (isp->irq <= 0) {
1984 vin_err("failed to get ISP IRQ resource\n");
1985 goto unmap;
1986 }
1987
1988 ret = request_irq(isp->irq, isp_isr, IRQF_SHARED, isp->pdev->name, isp);
1989 if (ret) {
1990 vin_err("isp%d request irq failed\n", isp->id);
1991 goto unmap;
1992 }
1993 if (isp_resource_alloc(isp) < 0) {
1994 ret = -ENOMEM;
1995 goto freeirq;
1996 }
1997 bsp_isp_map_reg_addr(isp->id, (unsigned long)isp->base);
1998 bsp_isp_map_load_dram_addr(isp->id, (unsigned long)isp->isp_load.vir_addr);
1999 }
2000
2001 __isp_init_subdev(isp);
2002
2003 spin_lock_init(&isp->slock);
2004
2005 ret = vin_isp_h3a_init(isp);
2006 if (ret < 0) {
2007 vin_err("VIN H3A initialization failed\n");
2008 goto free_res;
2009 }
2010
2011 INIT_WORK(&isp->s_sensor_stby_task, __isp_s_sensor_stby_handle);
2012
2013 platform_set_drvdata(pdev, isp);
2014 glb_isp[isp->id] = isp;
2015
2016 vin_log(VIN_LOG_ISP, "isp%d probe end!\n", isp->id);
2017 return 0;
2018 free_res:
2019 isp_resource_free(isp);
2020 freeirq:
2021 if (!isp->is_empty)
2022 free_irq(isp->irq, isp);
2023 unmap:
2024 if (!isp->is_empty)
2025 iounmap(isp->base);
2026 else
2027 kfree(isp->base);
2028 freedev:
2029 kfree(isp);
2030 ekzalloc:
2031 vin_err("isp probe err!\n");
2032 return ret;
2033 }
2034
isp_remove(struct platform_device * pdev)2035 static int isp_remove(struct platform_device *pdev)
2036 {
2037 struct isp_dev *isp = platform_get_drvdata(pdev);
2038 struct v4l2_subdev *sd = &isp->subdev;
2039
2040 platform_set_drvdata(pdev, NULL);
2041 v4l2_ctrl_handler_free(sd->ctrl_handler);
2042 v4l2_set_subdevdata(sd, NULL);
2043
2044 if (!isp->is_empty) {
2045 isp_resource_free(isp);
2046 free_irq(isp->irq, isp);
2047 if (isp->base)
2048 iounmap(isp->base);
2049 }
2050 vin_isp_h3a_cleanup(isp);
2051 media_entity_cleanup(&isp->subdev.entity);
2052 kfree(isp);
2053 return 0;
2054 }
2055
2056 static const struct of_device_id sunxi_isp_match[] = {
2057 {.compatible = "allwinner,sunxi-isp",},
2058 {},
2059 };
2060
2061 static struct platform_driver isp_platform_driver = {
2062 .probe = isp_probe,
2063 .remove = isp_remove,
2064 .driver = {
2065 .name = ISP_MODULE_NAME,
2066 .owner = THIS_MODULE,
2067 .of_match_table = sunxi_isp_match,
2068 },
2069 };
2070
sunxi_isp_sensor_type(struct v4l2_subdev * sd,int use_isp)2071 void sunxi_isp_sensor_type(struct v4l2_subdev *sd, int use_isp)
2072 {
2073 struct isp_dev *isp = v4l2_get_subdevdata(sd);
2074
2075 isp->use_isp = use_isp;
2076 if (isp->is_empty)
2077 isp->use_isp = 0;
2078 }
2079
sunxi_isp_sensor_fps(struct v4l2_subdev * sd,int fps)2080 void sunxi_isp_sensor_fps(struct v4l2_subdev *sd, int fps)
2081 {
2082 struct isp_dev *isp = v4l2_get_subdevdata(sd);
2083
2084 isp->h3a_stat.sensor_fps = fps;
2085 }
2086
sunxi_isp_debug(struct v4l2_subdev * sd,struct isp_debug_mode * isp_debug)2087 void sunxi_isp_debug(struct v4l2_subdev *sd, struct isp_debug_mode *isp_debug)
2088 {
2089 struct isp_dev *isp = v4l2_get_subdevdata(sd);
2090
2091 isp->isp_dbg = *isp_debug;
2092 }
2093
sunxi_isp_ptn(struct v4l2_subdev * sd,unsigned int ptn_type)2094 void sunxi_isp_ptn(struct v4l2_subdev *sd, unsigned int ptn_type)
2095 {
2096 struct isp_dev *isp = v4l2_get_subdevdata(sd);
2097 isp->ptn_type = ptn_type;
2098 }
2099
sunxi_isp_get_subdev(int id)2100 struct v4l2_subdev *sunxi_isp_get_subdev(int id)
2101 {
2102 if (id < VIN_MAX_ISP)
2103 return &glb_isp[id]->subdev;
2104 else
2105 return NULL;
2106 }
2107
sunxi_stat_get_subdev(int id)2108 struct v4l2_subdev *sunxi_stat_get_subdev(int id)
2109 {
2110 if (id < VIN_MAX_ISP && glb_isp[id])
2111 return &glb_isp[id]->h3a_stat.sd;
2112 else
2113 return NULL;
2114 }
2115
sunxi_isp_platform_register(void)2116 int sunxi_isp_platform_register(void)
2117 {
2118 return platform_driver_register(&isp_platform_driver);
2119 }
2120
sunxi_isp_platform_unregister(void)2121 void sunxi_isp_platform_unregister(void)
2122 {
2123 platform_driver_unregister(&isp_platform_driver);
2124 vin_log(VIN_LOG_ISP, "isp_exit end\n");
2125 }
2126