1 // SPDX-License-Identifier: GPL-2.0
3 * Support for Medifield PNW Camera Imaging ISP subsystem.
5 * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
7 * Copyright (c) 2010 Silicon Hive www.siliconhive.com.
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License version
11 * 2 as published by the Free Software Foundation.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
21 #include <linux/delay.h>
22 #include <linux/pci.h>
24 #include <media/v4l2-ioctl.h>
25 #include <media/v4l2-event.h>
27 #include "atomisp_cmd.h"
28 #include "atomisp_common.h"
29 #include "atomisp_fops.h"
30 #include "atomisp_internal.h"
31 #include "atomisp_ioctl.h"
32 #include "atomisp-regs.h"
33 #include "atomisp_compat.h"
35 #include "sh_css_hrt.h"
37 #include "gp_device.h"
38 #include "device_access.h"
41 static const char *DRIVER
= "atomisp"; /* max size 15 */
42 static const char *CARD
= "ATOM ISP"; /* max size 31 */
45 * FIXME: ISP should not know beforehand all CIDs supported by sensor.
46 * Instead, it needs to propagate to sensor unkonwn CIDs.
48 static struct v4l2_queryctrl ci_v4l2_controls
[] = {
50 .id
= V4L2_CID_AUTO_WHITE_BALANCE
,
51 .type
= V4L2_CTRL_TYPE_BOOLEAN
,
52 .name
= "Automatic White Balance",
59 .id
= V4L2_CID_RED_BALANCE
,
60 .type
= V4L2_CTRL_TYPE_INTEGER
,
61 .name
= "Red Balance",
65 .default_value
= 0x00,
68 .id
= V4L2_CID_BLUE_BALANCE
,
69 .type
= V4L2_CTRL_TYPE_INTEGER
,
70 .name
= "Blue Balance",
74 .default_value
= 0x00,
78 .type
= V4L2_CTRL_TYPE_INTEGER
,
83 .default_value
= 0x00,
86 .id
= V4L2_CID_POWER_LINE_FREQUENCY
,
87 .type
= V4L2_CTRL_TYPE_MENU
,
88 .name
= "Light frequency filter",
95 .id
= V4L2_CID_COLORFX
,
96 .type
= V4L2_CTRL_TYPE_INTEGER
,
97 .name
= "Image Color Effect",
104 .id
= V4L2_CID_COLORFX_CBCR
,
105 .type
= V4L2_CTRL_TYPE_INTEGER
,
106 .name
= "Image Color Effect CbCr",
113 .id
= V4L2_CID_ATOMISP_BAD_PIXEL_DETECTION
,
114 .type
= V4L2_CTRL_TYPE_INTEGER
,
115 .name
= "Bad Pixel Correction",
122 .id
= V4L2_CID_ATOMISP_POSTPROCESS_GDC_CAC
,
123 .type
= V4L2_CTRL_TYPE_INTEGER
,
131 .id
= V4L2_CID_ATOMISP_VIDEO_STABLIZATION
,
132 .type
= V4L2_CTRL_TYPE_INTEGER
,
133 .name
= "Video Stablization",
140 .id
= V4L2_CID_ATOMISP_FIXED_PATTERN_NR
,
141 .type
= V4L2_CTRL_TYPE_INTEGER
,
142 .name
= "Fixed Pattern Noise Reduction",
149 .id
= V4L2_CID_ATOMISP_FALSE_COLOR_CORRECTION
,
150 .type
= V4L2_CTRL_TYPE_INTEGER
,
151 .name
= "False Color Correction",
158 .id
= V4L2_CID_REQUEST_FLASH
,
159 .type
= V4L2_CTRL_TYPE_INTEGER
,
160 .name
= "Request flash frames",
167 .id
= V4L2_CID_ATOMISP_LOW_LIGHT
,
168 .type
= V4L2_CTRL_TYPE_BOOLEAN
,
169 .name
= "Low light mode",
176 .id
= V4L2_CID_2A_STATUS
,
177 .type
= V4L2_CTRL_TYPE_BITMASK
,
178 .name
= "AE and AWB status",
180 .maximum
= V4L2_2A_STATUS_AE_READY
| V4L2_2A_STATUS_AWB_READY
,
185 .id
= V4L2_CID_EXPOSURE
,
186 .type
= V4L2_CTRL_TYPE_INTEGER
,
194 .id
= V4L2_CID_EXPOSURE_ZONE_NUM
,
195 .type
= V4L2_CTRL_TYPE_INTEGER
,
196 .name
= "one-time exposure zone number",
203 .id
= V4L2_CID_EXPOSURE_AUTO_PRIORITY
,
204 .type
= V4L2_CTRL_TYPE_INTEGER
,
205 .name
= "Exposure auto priority",
206 .minimum
= V4L2_EXPOSURE_AUTO
,
207 .maximum
= V4L2_EXPOSURE_APERTURE_PRIORITY
,
209 .default_value
= V4L2_EXPOSURE_AUTO
,
212 .id
= V4L2_CID_SCENE_MODE
,
213 .type
= V4L2_CTRL_TYPE_INTEGER
,
214 .name
= "scene mode",
221 .id
= V4L2_CID_ISO_SENSITIVITY
,
222 .type
= V4L2_CTRL_TYPE_INTEGER
,
230 .id
= V4L2_CID_ISO_SENSITIVITY_AUTO
,
231 .type
= V4L2_CTRL_TYPE_INTEGER
,
233 .minimum
= V4L2_ISO_SENSITIVITY_MANUAL
,
234 .maximum
= V4L2_ISO_SENSITIVITY_AUTO
,
236 .default_value
= V4L2_ISO_SENSITIVITY_AUTO
,
239 .id
= V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE
,
240 .type
= V4L2_CTRL_TYPE_INTEGER
,
241 .name
= "white balance",
248 .id
= V4L2_CID_EXPOSURE_METERING
,
249 .type
= V4L2_CTRL_TYPE_MENU
,
257 .id
= V4L2_CID_3A_LOCK
,
258 .type
= V4L2_CTRL_TYPE_BITMASK
,
261 .maximum
= V4L2_LOCK_EXPOSURE
| V4L2_LOCK_WHITE_BALANCE
267 .id
= V4L2_CID_TEST_PATTERN
,
268 .type
= V4L2_CTRL_TYPE_INTEGER
,
269 .name
= "Test Pattern",
276 .id
= V4L2_CID_TEST_PATTERN_COLOR_R
,
277 .type
= V4L2_CTRL_TYPE_INTEGER
,
278 .name
= "Test Pattern Solid Color R",
285 .id
= V4L2_CID_TEST_PATTERN_COLOR_GR
,
286 .type
= V4L2_CTRL_TYPE_INTEGER
,
287 .name
= "Test Pattern Solid Color GR",
294 .id
= V4L2_CID_TEST_PATTERN_COLOR_GB
,
295 .type
= V4L2_CTRL_TYPE_INTEGER
,
296 .name
= "Test Pattern Solid Color GB",
303 .id
= V4L2_CID_TEST_PATTERN_COLOR_B
,
304 .type
= V4L2_CTRL_TYPE_INTEGER
,
305 .name
= "Test Pattern Solid Color B",
313 static const u32 ctrls_num
= ARRAY_SIZE(ci_v4l2_controls
);
316 * supported V4L2 fmts and resolutions
318 const struct atomisp_format_bridge atomisp_output_fmts
[] = {
320 .pixelformat
= V4L2_PIX_FMT_YUV420
,
322 .mbus_code
= V4L2_MBUS_FMT_CUSTOM_YUV420
,
323 .sh_fmt
= IA_CSS_FRAME_FORMAT_YUV420
,
324 .description
= "YUV420, planar",
327 .pixelformat
= V4L2_PIX_FMT_YVU420
,
329 .mbus_code
= V4L2_MBUS_FMT_CUSTOM_YVU420
,
330 .sh_fmt
= IA_CSS_FRAME_FORMAT_YV12
,
331 .description
= "YVU420, planar",
334 .pixelformat
= V4L2_PIX_FMT_YUV422P
,
336 .mbus_code
= V4L2_MBUS_FMT_CUSTOM_YUV422P
,
337 .sh_fmt
= IA_CSS_FRAME_FORMAT_YUV422
,
338 .description
= "YUV422, planar",
341 .pixelformat
= V4L2_PIX_FMT_YUV444
,
343 .mbus_code
= V4L2_MBUS_FMT_CUSTOM_YUV444
,
344 .sh_fmt
= IA_CSS_FRAME_FORMAT_YUV444
,
345 .description
= "YUV444"
347 .pixelformat
= V4L2_PIX_FMT_NV12
,
349 .mbus_code
= V4L2_MBUS_FMT_CUSTOM_NV12
,
350 .sh_fmt
= IA_CSS_FRAME_FORMAT_NV12
,
351 .description
= "NV12, Y-plane, CbCr interleaved",
354 .pixelformat
= V4L2_PIX_FMT_NV21
,
356 .mbus_code
= V4L2_MBUS_FMT_CUSTOM_NV21
,
357 .sh_fmt
= IA_CSS_FRAME_FORMAT_NV21
,
358 .description
= "NV21, Y-plane, CbCr interleaved",
361 .pixelformat
= V4L2_PIX_FMT_NV16
,
363 .mbus_code
= V4L2_MBUS_FMT_CUSTOM_NV16
,
364 .sh_fmt
= IA_CSS_FRAME_FORMAT_NV16
,
365 .description
= "NV16, Y-plane, CbCr interleaved",
368 .pixelformat
= V4L2_PIX_FMT_YUYV
,
370 .mbus_code
= V4L2_MBUS_FMT_CUSTOM_YUYV
,
371 .sh_fmt
= IA_CSS_FRAME_FORMAT_YUYV
,
372 .description
= "YUYV, interleaved"
374 .pixelformat
= V4L2_PIX_FMT_UYVY
,
376 .mbus_code
= MEDIA_BUS_FMT_UYVY8_1X16
,
377 .sh_fmt
= IA_CSS_FRAME_FORMAT_UYVY
,
378 .description
= "UYVY, interleaved"
379 }, { /* This one is for parallel sensors! DO NOT USE! */
380 .pixelformat
= V4L2_PIX_FMT_UYVY
,
382 .mbus_code
= MEDIA_BUS_FMT_UYVY8_2X8
,
383 .sh_fmt
= IA_CSS_FRAME_FORMAT_UYVY
,
384 .description
= "UYVY, interleaved"
386 .pixelformat
= V4L2_PIX_FMT_SBGGR16
,
388 .mbus_code
= V4L2_MBUS_FMT_CUSTOM_SBGGR16
,
389 .sh_fmt
= IA_CSS_FRAME_FORMAT_RAW
,
390 .description
= "Bayer 16"
392 .pixelformat
= V4L2_PIX_FMT_SBGGR8
,
394 .mbus_code
= MEDIA_BUS_FMT_SBGGR8_1X8
,
395 .sh_fmt
= IA_CSS_FRAME_FORMAT_RAW
,
396 .description
= "Bayer 8"
398 .pixelformat
= V4L2_PIX_FMT_SGBRG8
,
400 .mbus_code
= MEDIA_BUS_FMT_SGBRG8_1X8
,
401 .sh_fmt
= IA_CSS_FRAME_FORMAT_RAW
,
402 .description
= "Bayer 8"
404 .pixelformat
= V4L2_PIX_FMT_SGRBG8
,
406 .mbus_code
= MEDIA_BUS_FMT_SGRBG8_1X8
,
407 .sh_fmt
= IA_CSS_FRAME_FORMAT_RAW
,
408 .description
= "Bayer 8"
410 .pixelformat
= V4L2_PIX_FMT_SRGGB8
,
412 .mbus_code
= MEDIA_BUS_FMT_SRGGB8_1X8
,
413 .sh_fmt
= IA_CSS_FRAME_FORMAT_RAW
,
414 .description
= "Bayer 8"
416 .pixelformat
= V4L2_PIX_FMT_SBGGR10
,
418 .mbus_code
= MEDIA_BUS_FMT_SBGGR10_1X10
,
419 .sh_fmt
= IA_CSS_FRAME_FORMAT_RAW
,
420 .description
= "Bayer 10"
422 .pixelformat
= V4L2_PIX_FMT_SGBRG10
,
424 .mbus_code
= MEDIA_BUS_FMT_SGBRG10_1X10
,
425 .sh_fmt
= IA_CSS_FRAME_FORMAT_RAW
,
426 .description
= "Bayer 10"
428 .pixelformat
= V4L2_PIX_FMT_SGRBG10
,
430 .mbus_code
= MEDIA_BUS_FMT_SGRBG10_1X10
,
431 .sh_fmt
= IA_CSS_FRAME_FORMAT_RAW
,
432 .description
= "Bayer 10"
434 .pixelformat
= V4L2_PIX_FMT_SRGGB10
,
436 .mbus_code
= MEDIA_BUS_FMT_SRGGB10_1X10
,
437 .sh_fmt
= IA_CSS_FRAME_FORMAT_RAW
,
438 .description
= "Bayer 10"
440 .pixelformat
= V4L2_PIX_FMT_SBGGR12
,
442 .mbus_code
= MEDIA_BUS_FMT_SBGGR12_1X12
,
443 .sh_fmt
= IA_CSS_FRAME_FORMAT_RAW
,
444 .description
= "Bayer 12"
446 .pixelformat
= V4L2_PIX_FMT_SGBRG12
,
448 .mbus_code
= MEDIA_BUS_FMT_SGBRG12_1X12
,
449 .sh_fmt
= IA_CSS_FRAME_FORMAT_RAW
,
450 .description
= "Bayer 12"
452 .pixelformat
= V4L2_PIX_FMT_SGRBG12
,
454 .mbus_code
= MEDIA_BUS_FMT_SGRBG12_1X12
,
455 .sh_fmt
= IA_CSS_FRAME_FORMAT_RAW
,
456 .description
= "Bayer 12"
458 .pixelformat
= V4L2_PIX_FMT_SRGGB12
,
460 .mbus_code
= MEDIA_BUS_FMT_SRGGB12_1X12
,
461 .sh_fmt
= IA_CSS_FRAME_FORMAT_RAW
,
462 .description
= "Bayer 12"
464 .pixelformat
= V4L2_PIX_FMT_RGB32
,
466 .mbus_code
= V4L2_MBUS_FMT_CUSTOM_RGB32
,
467 .sh_fmt
= IA_CSS_FRAME_FORMAT_RGBA888
,
468 .description
= "32 RGB 8-8-8-8"
470 .pixelformat
= V4L2_PIX_FMT_RGB565
,
472 .mbus_code
= MEDIA_BUS_FMT_BGR565_2X8_LE
,
473 .sh_fmt
= IA_CSS_FRAME_FORMAT_RGB565
,
474 .description
= "16 RGB 5-6-5"
477 .pixelformat
= V4L2_PIX_FMT_JPEG
,
479 .mbus_code
= MEDIA_BUS_FMT_JPEG_1X8
,
480 .sh_fmt
= IA_CSS_FRAME_FORMAT_BINARY_8
,
481 .description
= "JPEG"
483 /* This is a custom format being used by M10MO to send the RAW data */
484 .pixelformat
= V4L2_PIX_FMT_CUSTOM_M10MO_RAW
,
486 .mbus_code
= V4L2_MBUS_FMT_CUSTOM_M10MO_RAW
,
487 .sh_fmt
= IA_CSS_FRAME_FORMAT_BINARY_8
,
488 .description
= "Custom RAW for M10MO"
493 const struct atomisp_format_bridge
*
494 atomisp_get_format_bridge(unsigned int pixelformat
)
498 for (i
= 0; i
< ARRAY_SIZE(atomisp_output_fmts
); i
++) {
499 if (atomisp_output_fmts
[i
].pixelformat
== pixelformat
)
500 return &atomisp_output_fmts
[i
];
506 const struct atomisp_format_bridge
*
507 atomisp_get_format_bridge_from_mbus(u32 mbus_code
)
511 for (i
= 0; i
< ARRAY_SIZE(atomisp_output_fmts
); i
++) {
512 if (mbus_code
== atomisp_output_fmts
[i
].mbus_code
)
513 return &atomisp_output_fmts
[i
];
519 int atomisp_pipe_check(struct atomisp_video_pipe
*pipe
, bool settings_change
)
521 lockdep_assert_held(&pipe
->isp
->mutex
);
523 if (pipe
->isp
->isp_fatal_error
)
526 if (settings_change
&& vb2_is_busy(&pipe
->vb_queue
)) {
527 dev_err(pipe
->isp
->dev
, "Set fmt/input IOCTL while streaming\n");
536 * return ISP capabilities
538 static int atomisp_querycap(struct file
*file
, void *fh
,
539 struct v4l2_capability
*cap
)
541 struct video_device
*vdev
= video_devdata(file
);
542 struct atomisp_device
*isp
= video_get_drvdata(vdev
);
544 strscpy(cap
->driver
, DRIVER
, sizeof(cap
->driver
));
545 strscpy(cap
->card
, CARD
, sizeof(cap
->card
));
546 snprintf(cap
->bus_info
, sizeof(cap
->bus_info
), "PCI:%s", dev_name(isp
->dev
));
552 * enum input are used to check primary/secondary camera
554 static int atomisp_enum_input(struct file
*file
, void *fh
,
555 struct v4l2_input
*input
)
557 struct video_device
*vdev
= video_devdata(file
);
558 struct atomisp_device
*isp
= video_get_drvdata(vdev
);
559 int index
= input
->index
;
560 struct v4l2_subdev
*motor
;
562 if (index
>= isp
->input_cnt
)
565 if (!isp
->inputs
[index
].camera
)
568 memset(input
, 0, sizeof(struct v4l2_input
));
569 strscpy(input
->name
, isp
->inputs
[index
].camera
->name
,
570 sizeof(input
->name
));
573 * HACK: append actuator's name to sensor's
574 * As currently userspace can't talk directly to subdev nodes, this
575 * ioctl is the only way to enum inputs + possible external actuators
576 * for 3A tuning purpose.
579 motor
= isp
->inputs
[index
].motor
;
583 if (motor
&& strlen(motor
->name
) > 0) {
584 const int cur_len
= strlen(input
->name
);
585 const int max_size
= sizeof(input
->name
) - cur_len
- 1;
588 input
->name
[cur_len
] = '+';
589 strscpy(&input
->name
[cur_len
+ 1],
590 motor
->name
, max_size
);
594 input
->type
= V4L2_INPUT_TYPE_CAMERA
;
595 input
->index
= index
;
596 input
->reserved
[0] = isp
->inputs
[index
].type
;
597 input
->reserved
[1] = isp
->inputs
[index
].port
;
603 * get input are used to get current primary/secondary camera
605 static int atomisp_g_input(struct file
*file
, void *fh
, unsigned int *input
)
607 struct video_device
*vdev
= video_devdata(file
);
608 struct atomisp_sub_device
*asd
= atomisp_to_video_pipe(vdev
)->asd
;
610 *input
= asd
->input_curr
;
614 static int atomisp_s_fmt_cap(struct file
*file
, void *fh
,
615 struct v4l2_format
*f
)
617 struct video_device
*vdev
= video_devdata(file
);
619 return atomisp_set_fmt(vdev
, f
);
623 * set input are used to set current primary/secondary camera
625 static int atomisp_s_input(struct file
*file
, void *fh
, unsigned int input
)
627 struct video_device
*vdev
= video_devdata(file
);
628 struct atomisp_device
*isp
= video_get_drvdata(vdev
);
629 struct atomisp_video_pipe
*pipe
= atomisp_to_video_pipe(vdev
);
630 struct atomisp_sub_device
*asd
= pipe
->asd
;
631 struct v4l2_subdev
*camera
= NULL
;
632 struct v4l2_subdev
*motor
;
635 ret
= atomisp_pipe_check(pipe
, true);
639 if (input
>= ATOM_ISP_MAX_INPUTS
|| input
>= isp
->input_cnt
) {
640 dev_dbg(isp
->dev
, "input_cnt: %d\n", isp
->input_cnt
);
644 camera
= isp
->inputs
[input
].camera
;
646 dev_err(isp
->dev
, "%s, no camera\n", __func__
);
650 /* power off the current owned sensor, as it is not used this time */
651 if (isp
->inputs
[asd
->input_curr
].asd
== asd
&&
652 asd
->input_curr
!= input
) {
653 ret
= v4l2_subdev_call(isp
->inputs
[asd
->input_curr
].camera
,
655 if (ret
&& ret
!= -ENOIOCTLCMD
)
657 "Failed to power-off sensor\n");
658 /* clear the asd field to show this camera is not used */
659 isp
->inputs
[asd
->input_curr
].asd
= NULL
;
662 /* powe on the new sensor */
663 ret
= v4l2_subdev_call(isp
->inputs
[input
].camera
, core
, s_power
, 1);
664 if (ret
&& ret
!= -ENOIOCTLCMD
) {
665 dev_err(isp
->dev
, "Failed to power-on sensor\n");
669 /* select operating sensor */
670 ret
= v4l2_subdev_call(isp
->inputs
[input
].camera
, video
, s_routing
,
672 if (ret
&& (ret
!= -ENOIOCTLCMD
)) {
673 dev_err(isp
->dev
, "Failed to select sensor\n");
678 motor
= isp
->inputs
[input
].motor
;
682 ret
= v4l2_subdev_call(motor
, core
, s_power
, 1);
686 ret
= v4l2_subdev_call(motor
, core
, init
, 1);
688 asd
->input_curr
= input
;
689 /* mark this camera is used by the current stream */
690 isp
->inputs
[input
].asd
= asd
;
696 * With crop any framesize <= sensor-size can be made, give
697 * userspace a list of sizes to choice from.
699 static int atomisp_enum_framesizes_crop_inner(struct atomisp_device
*isp
,
700 struct v4l2_frmsizeenum
*fsize
,
701 const struct v4l2_rect
*active
,
702 const struct v4l2_rect
*native
,
705 static const struct v4l2_frmsize_discrete frame_sizes
[] = {
718 u32 padding_w
, padding_h
;
721 for (i
= 0; i
< ARRAY_SIZE(frame_sizes
); i
++) {
722 atomisp_get_padding(isp
, frame_sizes
[i
].width
, frame_sizes
[i
].height
,
723 &padding_w
, &padding_h
);
725 if ((frame_sizes
[i
].width
+ padding_w
) > native
->width
||
726 (frame_sizes
[i
].height
+ padding_h
) > native
->height
)
730 * Skip sizes where width and height are less then 5/8th of the
731 * sensor size to avoid sizes with a too small field of view.
733 if (frame_sizes
[i
].width
< (active
->width
* 5 / 8) &&
734 frame_sizes
[i
].height
< (active
->height
* 5 / 8))
737 if (*valid_sizes
== fsize
->index
) {
738 fsize
->type
= V4L2_FRMSIZE_TYPE_DISCRETE
;
739 fsize
->discrete
= frame_sizes
[i
];
749 static int atomisp_enum_framesizes_crop(struct atomisp_device
*isp
,
750 struct v4l2_frmsizeenum
*fsize
)
752 struct atomisp_input_subdev
*input
= &isp
->inputs
[isp
->asd
.input_curr
];
753 struct v4l2_rect active
= input
->active_rect
;
754 struct v4l2_rect native
= input
->native_rect
;
755 int ret
, valid_sizes
= 0;
757 ret
= atomisp_enum_framesizes_crop_inner(isp
, fsize
, &active
, &native
, &valid_sizes
);
761 if (!input
->binning_support
)
769 return atomisp_enum_framesizes_crop_inner(isp
, fsize
, &active
, &native
, &valid_sizes
);
772 static int atomisp_enum_framesizes(struct file
*file
, void *priv
,
773 struct v4l2_frmsizeenum
*fsize
)
775 struct video_device
*vdev
= video_devdata(file
);
776 struct atomisp_device
*isp
= video_get_drvdata(vdev
);
777 struct atomisp_sub_device
*asd
= atomisp_to_video_pipe(vdev
)->asd
;
778 struct atomisp_input_subdev
*input
= &isp
->inputs
[asd
->input_curr
];
779 struct v4l2_subdev_frame_size_enum fse
= {
780 .index
= fsize
->index
,
781 .which
= V4L2_SUBDEV_FORMAT_ACTIVE
,
786 if (input
->crop_support
)
787 return atomisp_enum_framesizes_crop(isp
, fsize
);
789 ret
= v4l2_subdev_call(input
->camera
, pad
, enum_frame_size
, NULL
, &fse
);
793 fsize
->type
= V4L2_FRMSIZE_TYPE_DISCRETE
;
794 fsize
->discrete
.width
= fse
.max_width
- pad_w
;
795 fsize
->discrete
.height
= fse
.max_height
- pad_h
;
800 static int atomisp_enum_frameintervals(struct file
*file
, void *priv
,
801 struct v4l2_frmivalenum
*fival
)
803 struct video_device
*vdev
= video_devdata(file
);
804 struct atomisp_device
*isp
= video_get_drvdata(vdev
);
805 struct atomisp_sub_device
*asd
= atomisp_to_video_pipe(vdev
)->asd
;
806 struct v4l2_subdev_frame_interval_enum fie
= {
807 .code
= atomisp_in_fmt_conv
[0].code
,
808 .index
= fival
->index
,
809 .width
= fival
->width
,
810 .height
= fival
->height
,
811 .which
= V4L2_SUBDEV_FORMAT_ACTIVE
,
815 ret
= v4l2_subdev_call(isp
->inputs
[asd
->input_curr
].camera
,
816 pad
, enum_frame_interval
, NULL
,
821 fival
->type
= V4L2_FRMIVAL_TYPE_DISCRETE
;
822 fival
->discrete
= fie
.interval
;
827 static int atomisp_enum_fmt_cap(struct file
*file
, void *fh
,
828 struct v4l2_fmtdesc
*f
)
830 struct video_device
*vdev
= video_devdata(file
);
831 struct atomisp_device
*isp
= video_get_drvdata(vdev
);
832 struct atomisp_sub_device
*asd
= atomisp_to_video_pipe(vdev
)->asd
;
833 struct v4l2_subdev_mbus_code_enum code
= {
834 .which
= V4L2_SUBDEV_FORMAT_ACTIVE
,
836 const struct atomisp_format_bridge
*format
;
837 struct v4l2_subdev
*camera
;
838 unsigned int i
, fi
= 0;
841 camera
= isp
->inputs
[asd
->input_curr
].camera
;
843 dev_err(isp
->dev
, "%s(): camera is NULL, device is %s\n",
844 __func__
, vdev
->name
);
848 rval
= v4l2_subdev_call(camera
, pad
, enum_mbus_code
, NULL
, &code
);
849 if (rval
== -ENOIOCTLCMD
) {
851 "enum_mbus_code pad op not supported by %s. Please fix your sensor driver!\n",
858 for (i
= 0; i
< ARRAY_SIZE(atomisp_output_fmts
); i
++) {
859 format
= &atomisp_output_fmts
[i
];
862 * Is the atomisp-supported format is valid for the
863 * sensor (configuration)? If not, skip it.
865 * FIXME: fix the pipeline to allow sensor format too.
867 if (format
->sh_fmt
== IA_CSS_FRAME_FORMAT_RAW
)
870 /* Found a match. Now let's pick f->index'th one. */
876 strscpy(f
->description
, format
->description
,
877 sizeof(f
->description
));
878 f
->pixelformat
= format
->pixelformat
;
885 /* This function looks up the closest available resolution. */
886 static int atomisp_try_fmt_cap(struct file
*file
, void *fh
,
887 struct v4l2_format
*f
)
889 struct video_device
*vdev
= video_devdata(file
);
890 struct atomisp_device
*isp
= video_get_drvdata(vdev
);
892 return atomisp_try_fmt(isp
, &f
->fmt
.pix
, NULL
, NULL
);
895 static int atomisp_g_fmt_cap(struct file
*file
, void *fh
,
896 struct v4l2_format
*f
)
898 struct video_device
*vdev
= video_devdata(file
);
899 struct atomisp_video_pipe
*pipe
;
901 pipe
= atomisp_to_video_pipe(vdev
);
903 f
->fmt
.pix
= pipe
->pix
;
905 /* If s_fmt was issued, just return whatever is was previouly set */
906 if (f
->fmt
.pix
.sizeimage
)
909 f
->fmt
.pix
.pixelformat
= V4L2_PIX_FMT_YUV420
;
910 f
->fmt
.pix
.width
= 10000;
911 f
->fmt
.pix
.height
= 10000;
913 return atomisp_try_fmt_cap(file
, fh
, f
);
916 int atomisp_alloc_css_stat_bufs(struct atomisp_sub_device
*asd
,
919 struct atomisp_device
*isp
= asd
->isp
;
920 struct atomisp_s3a_buf
*s3a_buf
= NULL
, *_s3a_buf
;
921 struct atomisp_dis_buf
*dis_buf
= NULL
, *_dis_buf
;
922 struct atomisp_metadata_buf
*md_buf
= NULL
, *_md_buf
;
924 struct ia_css_dvs_grid_info
*dvs_grid_info
=
925 atomisp_css_get_dvs_grid_info(&asd
->params
.curr_grid_info
);
928 if (list_empty(&asd
->s3a_stats
) &&
929 asd
->params
.curr_grid_info
.s3a_grid
.enable
) {
930 count
= ATOMISP_CSS_Q_DEPTH
+
931 ATOMISP_S3A_BUF_QUEUE_DEPTH_FOR_HAL
;
932 dev_dbg(isp
->dev
, "allocating %d 3a buffers\n", count
);
934 s3a_buf
= kzalloc(sizeof(struct atomisp_s3a_buf
), GFP_KERNEL
);
938 if (atomisp_css_allocate_stat_buffers(
939 asd
, stream_id
, s3a_buf
, NULL
, NULL
)) {
944 list_add_tail(&s3a_buf
->list
, &asd
->s3a_stats
);
948 if (list_empty(&asd
->dis_stats
) && dvs_grid_info
&&
949 dvs_grid_info
->enable
) {
950 count
= ATOMISP_CSS_Q_DEPTH
+ 1;
951 dev_dbg(isp
->dev
, "allocating %d dis buffers\n", count
);
953 dis_buf
= kzalloc(sizeof(struct atomisp_dis_buf
), GFP_KERNEL
);
956 if (atomisp_css_allocate_stat_buffers(
957 asd
, stream_id
, NULL
, dis_buf
, NULL
)) {
962 list_add_tail(&dis_buf
->list
, &asd
->dis_stats
);
966 for (i
= 0; i
< ATOMISP_METADATA_TYPE_NUM
; i
++) {
967 if (list_empty(&asd
->metadata
[i
]) &&
968 list_empty(&asd
->metadata_ready
[i
]) &&
969 list_empty(&asd
->metadata_in_css
[i
])) {
970 count
= ATOMISP_CSS_Q_DEPTH
+
971 ATOMISP_METADATA_QUEUE_DEPTH_FOR_HAL
;
972 dev_dbg(isp
->dev
, "allocating %d metadata buffers for type %d\n",
975 md_buf
= kzalloc(sizeof(struct atomisp_metadata_buf
),
980 if (atomisp_css_allocate_stat_buffers(
981 asd
, stream_id
, NULL
, NULL
, md_buf
)) {
985 list_add_tail(&md_buf
->list
, &asd
->metadata
[i
]);
992 dev_err(isp
->dev
, "failed to allocate statistics buffers\n");
994 list_for_each_entry_safe(dis_buf
, _dis_buf
, &asd
->dis_stats
, list
) {
995 atomisp_css_free_dis_buffer(dis_buf
);
996 list_del(&dis_buf
->list
);
1000 list_for_each_entry_safe(s3a_buf
, _s3a_buf
, &asd
->s3a_stats
, list
) {
1001 atomisp_css_free_3a_buffer(s3a_buf
);
1002 list_del(&s3a_buf
->list
);
1006 for (i
= 0; i
< ATOMISP_METADATA_TYPE_NUM
; i
++) {
1007 list_for_each_entry_safe(md_buf
, _md_buf
, &asd
->metadata
[i
],
1009 atomisp_css_free_metadata_buffer(md_buf
);
1010 list_del(&md_buf
->list
);
1018 * FIXME the abuse of buf->reserved2 in the qbuf and dqbuf wrappers comes from
1019 * the original atomisp buffer handling and should be replaced with proper V4L2
1020 * per frame parameters use.
1022 * Once this is fixed these wrappers can be removed, replacing them with direct
1023 * calls to vb2_ioctl_[d]qbuf().
1025 static int atomisp_qbuf_wrapper(struct file
*file
, void *fh
, struct v4l2_buffer
*buf
)
1027 struct video_device
*vdev
= video_devdata(file
);
1028 struct atomisp_device
*isp
= video_get_drvdata(vdev
);
1029 struct atomisp_video_pipe
*pipe
= atomisp_to_video_pipe(vdev
);
1031 if (buf
->index
>= vb2_get_num_buffers(vdev
->queue
))
1034 if (buf
->reserved2
& ATOMISP_BUFFER_HAS_PER_FRAME_SETTING
) {
1035 /* this buffer will have a per-frame parameter */
1036 pipe
->frame_request_config_id
[buf
->index
] = buf
->reserved2
&
1037 ~ATOMISP_BUFFER_HAS_PER_FRAME_SETTING
;
1039 "This buffer requires per_frame setting which has isp_config_id %d\n",
1040 pipe
->frame_request_config_id
[buf
->index
]);
1042 pipe
->frame_request_config_id
[buf
->index
] = 0;
1045 return vb2_ioctl_qbuf(file
, fh
, buf
);
1048 static int atomisp_dqbuf_wrapper(struct file
*file
, void *fh
, struct v4l2_buffer
*buf
)
1050 struct video_device
*vdev
= video_devdata(file
);
1051 struct atomisp_video_pipe
*pipe
= atomisp_to_video_pipe(vdev
);
1052 struct atomisp_sub_device
*asd
= pipe
->asd
;
1053 struct atomisp_device
*isp
= video_get_drvdata(vdev
);
1054 struct ia_css_frame
*frame
;
1055 struct vb2_buffer
*vb
;
1058 ret
= vb2_ioctl_dqbuf(file
, fh
, buf
);
1062 vb
= vb2_get_buffer(&pipe
->vb_queue
, buf
->index
);
1063 frame
= vb_to_frame(vb
);
1065 buf
->reserved
= asd
->frame_status
[buf
->index
];
1069 * Currently frame_status in the enum type which takes no more lower
1071 * use bit[31:16] for exp_id as it is only in the range of 1~255
1073 buf
->reserved
&= 0x0000ffff;
1074 if (!(buf
->flags
& V4L2_BUF_FLAG_ERROR
))
1075 buf
->reserved
|= frame
->exp_id
;
1076 buf
->reserved2
= pipe
->frame_config_id
[buf
->index
];
1079 "dqbuf buffer %d (%s) with exp_id %d, isp_config_id %d\n",
1080 buf
->index
, vdev
->name
, buf
->reserved
>> 16, buf
->reserved2
);
1084 /* Input system HW workaround */
1085 /* Input system address translation corrupts burst during */
1086 /* invalidate. SW workaround for this is to set burst length */
1087 /* manually to 128 in case of 13MPx snapshot and to 1 otherwise. */
1088 static void atomisp_dma_burst_len_cfg(struct atomisp_sub_device
*asd
)
1090 struct v4l2_mbus_framefmt
*sink
;
1092 sink
= atomisp_subdev_get_ffmt(&asd
->subdev
, NULL
,
1093 V4L2_SUBDEV_FORMAT_ACTIVE
,
1094 ATOMISP_SUBDEV_PAD_SINK
);
1096 if (sink
->width
* sink
->height
>= 4096 * 3072)
1097 atomisp_css2_hw_store_32(DMA_BURST_SIZE_REG
, 0x7F);
1099 atomisp_css2_hw_store_32(DMA_BURST_SIZE_REG
, 0x00);
1102 int atomisp_start_streaming(struct vb2_queue
*vq
, unsigned int count
)
1104 struct atomisp_video_pipe
*pipe
= vq_to_pipe(vq
);
1105 struct atomisp_sub_device
*asd
= pipe
->asd
;
1106 struct atomisp_device
*isp
= asd
->isp
;
1107 struct pci_dev
*pdev
= to_pci_dev(isp
->dev
);
1108 unsigned long irqflags
;
1111 dev_dbg(isp
->dev
, "Start stream\n");
1113 mutex_lock(&isp
->mutex
);
1115 ret
= atomisp_pipe_check(pipe
, false);
1119 /* Input system HW workaround */
1120 atomisp_dma_burst_len_cfg(asd
);
1122 /* Invalidate caches. FIXME: should flush only necessary buffers */
1125 if (asd
->params
.css_update_params_needed
) {
1126 atomisp_apply_css_parameters(asd
, &asd
->params
.css_param
);
1127 if (asd
->params
.css_param
.update_flag
.dz_config
)
1128 asd
->params
.config
.dz_config
= &asd
->params
.css_param
.dz_config
;
1129 atomisp_css_update_isp_params(asd
);
1130 asd
->params
.css_update_params_needed
= false;
1131 memset(&asd
->params
.css_param
.update_flag
, 0,
1132 sizeof(struct atomisp_parameters
));
1134 asd
->params
.dvs_6axis
= NULL
;
1136 ret
= atomisp_css_start(asd
);
1138 atomisp_flush_video_pipe(pipe
, VB2_BUF_STATE_QUEUED
, true);
1142 spin_lock_irqsave(&isp
->lock
, irqflags
);
1143 asd
->streaming
= true;
1144 spin_unlock_irqrestore(&isp
->lock
, irqflags
);
1145 atomic_set(&asd
->sof_count
, -1);
1146 atomic_set(&asd
->sequence
, -1);
1147 atomic_set(&asd
->sequence_temp
, -1);
1149 asd
->params
.dis_proj_data_valid
= false;
1150 asd
->latest_preview_exp_id
= 0;
1151 asd
->postview_exp_id
= 1;
1152 asd
->preview_exp_id
= 1;
1154 /* handle per_frame_setting parameter and buffers */
1155 atomisp_handle_parameter_and_buffer(pipe
);
1157 atomisp_qbuffers_to_css(asd
);
1160 asd
->params
.num_flash_frames
= 0;
1161 asd
->params
.flash_state
= ATOMISP_FLASH_IDLE
;
1162 atomisp_setup_flash(asd
);
1165 atomisp_css_irq_enable(isp
, IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF
,
1166 atomisp_css_valid_sof(isp
));
1167 atomisp_csi2_configure(asd
);
1169 if (atomisp_freq_scaling(isp
, ATOMISP_DFS_MODE_AUTO
, false) < 0)
1170 dev_dbg(isp
->dev
, "DFS auto mode failed!\n");
1172 /* Enable the CSI interface on ANN B0/K0 */
1173 if (isp
->media_dev
.hw_revision
>= ((ATOMISP_HW_REVISION_ISP2401
<<
1174 ATOMISP_HW_REVISION_SHIFT
) | ATOMISP_HW_STEPPING_B0
)) {
1175 pci_write_config_word(pdev
, MRFLD_PCI_CSI_CONTROL
,
1176 isp
->saved_regs
.csi_control
| MRFLD_PCI_CSI_CONTROL_CSI_READY
);
1179 /* stream on the sensor */
1180 ret
= v4l2_subdev_call(isp
->inputs
[asd
->input_curr
].camera
,
1181 video
, s_stream
, 1);
1183 dev_err(isp
->dev
, "Starting sensor stream failed: %d\n", ret
);
1184 spin_lock_irqsave(&isp
->lock
, irqflags
);
1185 asd
->streaming
= false;
1186 spin_unlock_irqrestore(&isp
->lock
, irqflags
);
1192 mutex_unlock(&isp
->mutex
);
1196 void atomisp_stop_streaming(struct vb2_queue
*vq
)
1198 struct atomisp_video_pipe
*pipe
= vq_to_pipe(vq
);
1199 struct atomisp_sub_device
*asd
= pipe
->asd
;
1200 struct atomisp_device
*isp
= asd
->isp
;
1201 struct pci_dev
*pdev
= to_pci_dev(isp
->dev
);
1202 unsigned long flags
;
1205 dev_dbg(isp
->dev
, "Stop stream\n");
1207 mutex_lock(&isp
->mutex
);
1209 * There is no guarantee that the buffers queued to / owned by the ISP
1210 * will properly be returned to the queue when stopping. Set a flag to
1211 * avoid new buffers getting queued and then wait for all the current
1212 * buffers to finish.
1214 pipe
->stopping
= true;
1215 mutex_unlock(&isp
->mutex
);
1216 /* wait max 1 second */
1217 ret
= wait_event_timeout(pipe
->vb_queue
.done_wq
,
1218 atomisp_buffers_in_css(pipe
) == 0, HZ
);
1219 mutex_lock(&isp
->mutex
);
1220 pipe
->stopping
= false;
1222 dev_warn(isp
->dev
, "Warning timeout waiting for CSS to return buffers\n");
1224 spin_lock_irqsave(&isp
->lock
, flags
);
1225 asd
->streaming
= false;
1226 spin_unlock_irqrestore(&isp
->lock
, flags
);
1228 atomisp_clear_css_buffer_counters(asd
);
1229 atomisp_css_irq_enable(isp
, IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF
, false);
1231 atomisp_css_stop(asd
, false);
1233 atomisp_flush_video_pipe(pipe
, VB2_BUF_STATE_ERROR
, true);
1235 atomisp_subdev_cleanup_pending_events(asd
);
1237 ret
= v4l2_subdev_call(isp
->inputs
[asd
->input_curr
].camera
,
1238 video
, s_stream
, 0);
1240 dev_warn(isp
->dev
, "Stopping sensor stream failed: %d\n", ret
);
1243 asd
->params
.num_flash_frames
= 0;
1244 asd
->params
.flash_state
= ATOMISP_FLASH_IDLE
;
1247 /* Disable the CSI interface on ANN B0/K0 */
1248 if (isp
->media_dev
.hw_revision
>= ((ATOMISP_HW_REVISION_ISP2401
<<
1249 ATOMISP_HW_REVISION_SHIFT
) | ATOMISP_HW_STEPPING_B0
)) {
1250 pci_write_config_word(pdev
, MRFLD_PCI_CSI_CONTROL
,
1251 isp
->saved_regs
.csi_control
& ~MRFLD_PCI_CSI_CONTROL_CSI_READY
);
1254 if (atomisp_freq_scaling(isp
, ATOMISP_DFS_MODE_LOW
, false))
1255 dev_warn(isp
->dev
, "DFS failed.\n");
1258 * ISP work around, need to reset ISP to allow next stream on to work.
1259 * Streams have already been destroyed by atomisp_css_stop().
1260 * Disable PUNIT/ISP acknowlede/handshake - SRSE=3 and then reset.
1262 pci_write_config_dword(pdev
, PCI_I_CONTROL
,
1263 isp
->saved_regs
.i_control
| MRFLD_PCI_I_CONTROL_SRSE_RESET_MASK
);
1266 /* Streams were destroyed by atomisp_css_stop(), recreate them. */
1267 ret
= atomisp_create_pipes_stream(&isp
->asd
);
1269 dev_warn(isp
->dev
, "Recreating streams failed: %d\n", ret
);
1271 mutex_unlock(&isp
->mutex
);
1275 * To get the current value of a control.
1276 * applications initialize the id field of a struct v4l2_control and
1277 * call this ioctl with a pointer to this structure
1279 static int atomisp_g_ctrl(struct file
*file
, void *fh
,
1280 struct v4l2_control
*control
)
1282 struct video_device
*vdev
= video_devdata(file
);
1283 struct atomisp_sub_device
*asd
= atomisp_to_video_pipe(vdev
)->asd
;
1284 struct atomisp_device
*isp
= video_get_drvdata(vdev
);
1285 int i
, ret
= -EINVAL
;
1287 for (i
= 0; i
< ctrls_num
; i
++) {
1288 if (ci_v4l2_controls
[i
].id
== control
->id
) {
1297 switch (control
->id
) {
1298 case V4L2_CID_IRIS_ABSOLUTE
:
1299 case V4L2_CID_EXPOSURE_ABSOLUTE
:
1300 case V4L2_CID_2A_STATUS
:
1301 case V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE
:
1302 case V4L2_CID_EXPOSURE
:
1303 case V4L2_CID_EXPOSURE_AUTO
:
1304 case V4L2_CID_SCENE_MODE
:
1305 case V4L2_CID_ISO_SENSITIVITY
:
1306 case V4L2_CID_ISO_SENSITIVITY_AUTO
:
1307 case V4L2_CID_CONTRAST
:
1308 case V4L2_CID_SATURATION
:
1309 case V4L2_CID_SHARPNESS
:
1310 case V4L2_CID_3A_LOCK
:
1311 case V4L2_CID_EXPOSURE_ZONE_NUM
:
1312 case V4L2_CID_TEST_PATTERN
:
1313 case V4L2_CID_TEST_PATTERN_COLOR_R
:
1314 case V4L2_CID_TEST_PATTERN_COLOR_GR
:
1315 case V4L2_CID_TEST_PATTERN_COLOR_GB
:
1316 case V4L2_CID_TEST_PATTERN_COLOR_B
:
1317 return v4l2_g_ctrl(isp
->inputs
[asd
->input_curr
].camera
->
1318 ctrl_handler
, control
);
1319 case V4L2_CID_COLORFX
:
1320 ret
= atomisp_color_effect(asd
, 0, &control
->value
);
1322 case V4L2_CID_ATOMISP_BAD_PIXEL_DETECTION
:
1323 ret
= atomisp_bad_pixel(asd
, 0, &control
->value
);
1325 case V4L2_CID_ATOMISP_POSTPROCESS_GDC_CAC
:
1326 ret
= atomisp_gdc_cac(asd
, 0, &control
->value
);
1328 case V4L2_CID_ATOMISP_VIDEO_STABLIZATION
:
1329 ret
= atomisp_video_stable(asd
, 0, &control
->value
);
1331 case V4L2_CID_ATOMISP_FIXED_PATTERN_NR
:
1332 ret
= atomisp_fixed_pattern(asd
, 0, &control
->value
);
1334 case V4L2_CID_ATOMISP_FALSE_COLOR_CORRECTION
:
1335 ret
= atomisp_false_color(asd
, 0, &control
->value
);
1337 case V4L2_CID_ATOMISP_LOW_LIGHT
:
1338 ret
= atomisp_low_light(asd
, 0, &control
->value
);
1349 * To change the value of a control.
1350 * applications initialize the id and value fields of a struct v4l2_control
1351 * and call this ioctl.
1353 static int atomisp_s_ctrl(struct file
*file
, void *fh
,
1354 struct v4l2_control
*control
)
1356 struct video_device
*vdev
= video_devdata(file
);
1357 struct atomisp_sub_device
*asd
= atomisp_to_video_pipe(vdev
)->asd
;
1358 struct atomisp_device
*isp
= video_get_drvdata(vdev
);
1359 int i
, ret
= -EINVAL
;
1361 for (i
= 0; i
< ctrls_num
; i
++) {
1362 if (ci_v4l2_controls
[i
].id
== control
->id
) {
1371 switch (control
->id
) {
1372 case V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE
:
1373 case V4L2_CID_EXPOSURE
:
1374 case V4L2_CID_EXPOSURE_AUTO
:
1375 case V4L2_CID_EXPOSURE_AUTO_PRIORITY
:
1376 case V4L2_CID_SCENE_MODE
:
1377 case V4L2_CID_ISO_SENSITIVITY
:
1378 case V4L2_CID_ISO_SENSITIVITY_AUTO
:
1379 case V4L2_CID_POWER_LINE_FREQUENCY
:
1380 case V4L2_CID_EXPOSURE_METERING
:
1381 case V4L2_CID_CONTRAST
:
1382 case V4L2_CID_SATURATION
:
1383 case V4L2_CID_SHARPNESS
:
1384 case V4L2_CID_3A_LOCK
:
1385 case V4L2_CID_COLORFX_CBCR
:
1386 case V4L2_CID_TEST_PATTERN
:
1387 case V4L2_CID_TEST_PATTERN_COLOR_R
:
1388 case V4L2_CID_TEST_PATTERN_COLOR_GR
:
1389 case V4L2_CID_TEST_PATTERN_COLOR_GB
:
1390 case V4L2_CID_TEST_PATTERN_COLOR_B
:
1391 return v4l2_s_ctrl(NULL
,
1392 isp
->inputs
[asd
->input_curr
].camera
->
1393 ctrl_handler
, control
);
1394 case V4L2_CID_COLORFX
:
1395 ret
= atomisp_color_effect(asd
, 1, &control
->value
);
1397 case V4L2_CID_ATOMISP_BAD_PIXEL_DETECTION
:
1398 ret
= atomisp_bad_pixel(asd
, 1, &control
->value
);
1400 case V4L2_CID_ATOMISP_POSTPROCESS_GDC_CAC
:
1401 ret
= atomisp_gdc_cac(asd
, 1, &control
->value
);
1403 case V4L2_CID_ATOMISP_VIDEO_STABLIZATION
:
1404 ret
= atomisp_video_stable(asd
, 1, &control
->value
);
1406 case V4L2_CID_ATOMISP_FIXED_PATTERN_NR
:
1407 ret
= atomisp_fixed_pattern(asd
, 1, &control
->value
);
1409 case V4L2_CID_ATOMISP_FALSE_COLOR_CORRECTION
:
1410 ret
= atomisp_false_color(asd
, 1, &control
->value
);
1412 case V4L2_CID_REQUEST_FLASH
:
1413 ret
= atomisp_flash_enable(asd
, control
->value
);
1415 case V4L2_CID_ATOMISP_LOW_LIGHT
:
1416 ret
= atomisp_low_light(asd
, 1, &control
->value
);
1426 * To query the attributes of a control.
1427 * applications set the id field of a struct v4l2_queryctrl and call the
1428 * this ioctl with a pointer to this structure. The driver fills
1429 * the rest of the structure.
1431 static int atomisp_queryctl(struct file
*file
, void *fh
,
1432 struct v4l2_queryctrl
*qc
)
1434 int i
, ret
= -EINVAL
;
1435 struct video_device
*vdev
= video_devdata(file
);
1436 struct atomisp_sub_device
*asd
= atomisp_to_video_pipe(vdev
)->asd
;
1437 struct atomisp_device
*isp
= video_get_drvdata(vdev
);
1440 case V4L2_CID_FOCUS_ABSOLUTE
:
1441 case V4L2_CID_FOCUS_RELATIVE
:
1442 case V4L2_CID_FOCUS_STATUS
:
1444 return v4l2_queryctrl(isp
->inputs
[asd
->input_curr
].camera
->
1449 return v4l2_queryctrl(isp
->motor
->ctrl_handler
, qc
);
1451 return v4l2_queryctrl(isp
->inputs
[asd
->input_curr
].
1452 camera
->ctrl_handler
, qc
);
1455 if (qc
->id
& V4L2_CTRL_FLAG_NEXT_CTRL
)
1458 for (i
= 0; i
< ctrls_num
; i
++) {
1459 if (ci_v4l2_controls
[i
].id
== qc
->id
) {
1460 memcpy(qc
, &ci_v4l2_controls
[i
],
1461 sizeof(struct v4l2_queryctrl
));
1462 qc
->reserved
[0] = 0;
1468 qc
->flags
= V4L2_CTRL_FLAG_DISABLED
;
1473 static int atomisp_camera_g_ext_ctrls(struct file
*file
, void *fh
,
1474 struct v4l2_ext_controls
*c
)
1476 struct video_device
*vdev
= video_devdata(file
);
1477 struct atomisp_sub_device
*asd
= atomisp_to_video_pipe(vdev
)->asd
;
1478 struct atomisp_device
*isp
= video_get_drvdata(vdev
);
1479 struct v4l2_subdev
*motor
;
1480 struct v4l2_control ctrl
;
1485 motor
= isp
->inputs
[asd
->input_curr
].motor
;
1489 for (i
= 0; i
< c
->count
; i
++) {
1490 ctrl
.id
= c
->controls
[i
].id
;
1491 ctrl
.value
= c
->controls
[i
].value
;
1493 case V4L2_CID_EXPOSURE_ABSOLUTE
:
1494 case V4L2_CID_EXPOSURE_AUTO
:
1495 case V4L2_CID_IRIS_ABSOLUTE
:
1496 case V4L2_CID_3A_LOCK
:
1497 case V4L2_CID_TEST_PATTERN
:
1498 case V4L2_CID_TEST_PATTERN_COLOR_R
:
1499 case V4L2_CID_TEST_PATTERN_COLOR_GR
:
1500 case V4L2_CID_TEST_PATTERN_COLOR_GB
:
1501 case V4L2_CID_TEST_PATTERN_COLOR_B
:
1503 * Exposure related control will be handled by sensor
1507 v4l2_g_ctrl(isp
->inputs
[asd
->input_curr
].camera
->
1508 ctrl_handler
, &ctrl
);
1510 case V4L2_CID_FOCUS_ABSOLUTE
:
1511 case V4L2_CID_FOCUS_RELATIVE
:
1512 case V4L2_CID_FOCUS_STATUS
:
1513 case V4L2_CID_FOCUS_AUTO
:
1515 ret
= v4l2_g_ctrl(motor
->ctrl_handler
, &ctrl
);
1517 case V4L2_CID_FLASH_STATUS
:
1518 case V4L2_CID_FLASH_INTENSITY
:
1519 case V4L2_CID_FLASH_TORCH_INTENSITY
:
1520 case V4L2_CID_FLASH_INDICATOR_INTENSITY
:
1521 case V4L2_CID_FLASH_TIMEOUT
:
1522 case V4L2_CID_FLASH_STROBE
:
1523 case V4L2_CID_FLASH_MODE
:
1524 case V4L2_CID_FLASH_STATUS_REGISTER
:
1527 v4l2_g_ctrl(isp
->flash
->ctrl_handler
,
1530 case V4L2_CID_ZOOM_ABSOLUTE
:
1531 ret
= atomisp_digital_zoom(asd
, 0, &ctrl
.value
);
1533 case V4L2_CID_G_SKIP_FRAMES
:
1534 ret
= v4l2_subdev_call(
1535 isp
->inputs
[asd
->input_curr
].camera
,
1536 sensor
, g_skip_frames
, (u32
*)&ctrl
.value
);
1546 c
->controls
[i
].value
= ctrl
.value
;
1551 /* This ioctl allows the application to get multiple controls by class */
1552 static int atomisp_g_ext_ctrls(struct file
*file
, void *fh
,
1553 struct v4l2_ext_controls
*c
)
1555 struct v4l2_control ctrl
;
1559 * input_lock is not need for the Camera related IOCTLs
1560 * The input_lock downgrade the FPS of 3A
1562 ret
= atomisp_camera_g_ext_ctrls(file
, fh
, c
);
1566 for (i
= 0; i
< c
->count
; i
++) {
1567 ctrl
.id
= c
->controls
[i
].id
;
1568 ctrl
.value
= c
->controls
[i
].value
;
1569 ret
= atomisp_g_ctrl(file
, fh
, &ctrl
);
1570 c
->controls
[i
].value
= ctrl
.value
;
1579 static int atomisp_camera_s_ext_ctrls(struct file
*file
, void *fh
,
1580 struct v4l2_ext_controls
*c
)
1582 struct video_device
*vdev
= video_devdata(file
);
1583 struct atomisp_sub_device
*asd
= atomisp_to_video_pipe(vdev
)->asd
;
1584 struct atomisp_device
*isp
= video_get_drvdata(vdev
);
1585 struct v4l2_subdev
*motor
;
1586 struct v4l2_control ctrl
;
1591 motor
= isp
->inputs
[asd
->input_curr
].motor
;
1595 for (i
= 0; i
< c
->count
; i
++) {
1596 struct v4l2_ctrl
*ctr
;
1598 ctrl
.id
= c
->controls
[i
].id
;
1599 ctrl
.value
= c
->controls
[i
].value
;
1601 case V4L2_CID_EXPOSURE_ABSOLUTE
:
1602 case V4L2_CID_EXPOSURE_AUTO
:
1603 case V4L2_CID_EXPOSURE_METERING
:
1604 case V4L2_CID_IRIS_ABSOLUTE
:
1605 case V4L2_CID_VCM_TIMING
:
1606 case V4L2_CID_VCM_SLEW
:
1607 case V4L2_CID_3A_LOCK
:
1608 case V4L2_CID_TEST_PATTERN
:
1609 case V4L2_CID_TEST_PATTERN_COLOR_R
:
1610 case V4L2_CID_TEST_PATTERN_COLOR_GR
:
1611 case V4L2_CID_TEST_PATTERN_COLOR_GB
:
1612 case V4L2_CID_TEST_PATTERN_COLOR_B
:
1613 ret
= v4l2_s_ctrl(NULL
,
1614 isp
->inputs
[asd
->input_curr
].camera
->
1615 ctrl_handler
, &ctrl
);
1617 case V4L2_CID_FOCUS_ABSOLUTE
:
1618 case V4L2_CID_FOCUS_RELATIVE
:
1619 case V4L2_CID_FOCUS_STATUS
:
1620 case V4L2_CID_FOCUS_AUTO
:
1622 ret
= v4l2_s_ctrl(NULL
, motor
->ctrl_handler
,
1625 ret
= v4l2_s_ctrl(NULL
,
1626 isp
->inputs
[asd
->input_curr
].
1627 camera
->ctrl_handler
, &ctrl
);
1629 case V4L2_CID_FLASH_STATUS
:
1630 case V4L2_CID_FLASH_INTENSITY
:
1631 case V4L2_CID_FLASH_TORCH_INTENSITY
:
1632 case V4L2_CID_FLASH_INDICATOR_INTENSITY
:
1633 case V4L2_CID_FLASH_TIMEOUT
:
1634 case V4L2_CID_FLASH_STROBE
:
1635 case V4L2_CID_FLASH_MODE
:
1636 case V4L2_CID_FLASH_STATUS_REGISTER
:
1639 v4l2_s_ctrl(NULL
, isp
->flash
->ctrl_handler
,
1642 * When flash mode is changed we need to reset
1645 if (ctrl
.id
== V4L2_CID_FLASH_MODE
) {
1646 asd
->params
.flash_state
=
1648 asd
->params
.num_flash_frames
= 0;
1652 case V4L2_CID_ZOOM_ABSOLUTE
:
1653 ret
= atomisp_digital_zoom(asd
, 1, &ctrl
.value
);
1656 ctr
= v4l2_ctrl_find(&asd
->ctrl_handler
, ctrl
.id
);
1658 ret
= v4l2_ctrl_s_ctrl(ctr
, ctrl
.value
);
1667 c
->controls
[i
].value
= ctrl
.value
;
1672 /* This ioctl allows the application to set multiple controls by class */
1673 static int atomisp_s_ext_ctrls(struct file
*file
, void *fh
,
1674 struct v4l2_ext_controls
*c
)
1676 struct v4l2_control ctrl
;
1680 * input_lock is not need for the Camera related IOCTLs
1681 * The input_lock downgrade the FPS of 3A
1683 ret
= atomisp_camera_s_ext_ctrls(file
, fh
, c
);
1687 for (i
= 0; i
< c
->count
; i
++) {
1688 ctrl
.id
= c
->controls
[i
].id
;
1689 ctrl
.value
= c
->controls
[i
].value
;
1690 ret
= atomisp_s_ctrl(file
, fh
, &ctrl
);
1691 c
->controls
[i
].value
= ctrl
.value
;
1701 * vidioc_g/s_param are used to switch isp running mode
1703 static int atomisp_g_parm(struct file
*file
, void *fh
,
1704 struct v4l2_streamparm
*parm
)
1706 struct video_device
*vdev
= video_devdata(file
);
1707 struct atomisp_sub_device
*asd
= atomisp_to_video_pipe(vdev
)->asd
;
1708 struct atomisp_device
*isp
= video_get_drvdata(vdev
);
1710 if (parm
->type
!= V4L2_BUF_TYPE_VIDEO_CAPTURE
) {
1711 dev_err(isp
->dev
, "unsupported v4l2 buf type\n");
1715 parm
->parm
.capture
.capturemode
= asd
->run_mode
->val
;
1720 static int atomisp_s_parm(struct file
*file
, void *fh
,
1721 struct v4l2_streamparm
*parm
)
1723 struct video_device
*vdev
= video_devdata(file
);
1724 struct atomisp_device
*isp
= video_get_drvdata(vdev
);
1725 struct atomisp_sub_device
*asd
= atomisp_to_video_pipe(vdev
)->asd
;
1730 if (parm
->type
!= V4L2_BUF_TYPE_VIDEO_CAPTURE
) {
1731 dev_err(isp
->dev
, "unsupported v4l2 buf type\n");
1735 asd
->high_speed_mode
= false;
1736 switch (parm
->parm
.capture
.capturemode
) {
1737 case CI_MODE_NONE
: {
1738 struct v4l2_subdev_frame_interval fi
= {0};
1740 fi
.interval
= parm
->parm
.capture
.timeperframe
;
1742 rval
= v4l2_subdev_call_state_active(isp
->inputs
[asd
->input_curr
].camera
,
1743 pad
, set_frame_interval
, &fi
);
1745 parm
->parm
.capture
.timeperframe
= fi
.interval
;
1747 if (fi
.interval
.numerator
!= 0) {
1748 fps
= fi
.interval
.denominator
/ fi
.interval
.numerator
;
1750 asd
->high_speed_mode
= true;
1753 return rval
== -ENOIOCTLCMD
? 0 : rval
;
1756 mode
= ATOMISP_RUN_MODE_VIDEO
;
1758 case CI_MODE_STILL_CAPTURE
:
1759 mode
= ATOMISP_RUN_MODE_STILL_CAPTURE
;
1761 case CI_MODE_PREVIEW
:
1762 mode
= ATOMISP_RUN_MODE_PREVIEW
;
1768 rval
= v4l2_ctrl_s_ctrl(asd
->run_mode
, mode
);
1770 return rval
== -ENOIOCTLCMD
? 0 : rval
;
1773 static long atomisp_vidioc_default(struct file
*file
, void *fh
,
1774 bool valid_prio
, unsigned int cmd
, void *arg
)
1776 struct video_device
*vdev
= video_devdata(file
);
1777 struct atomisp_device
*isp
= video_get_drvdata(vdev
);
1778 struct atomisp_sub_device
*asd
= atomisp_to_video_pipe(vdev
)->asd
;
1782 case ATOMISP_IOC_G_XNR
:
1783 err
= atomisp_xnr(asd
, 0, arg
);
1786 case ATOMISP_IOC_S_XNR
:
1787 err
= atomisp_xnr(asd
, 1, arg
);
1790 case ATOMISP_IOC_G_NR
:
1791 err
= atomisp_nr(asd
, 0, arg
);
1794 case ATOMISP_IOC_S_NR
:
1795 err
= atomisp_nr(asd
, 1, arg
);
1798 case ATOMISP_IOC_G_TNR
:
1799 err
= atomisp_tnr(asd
, 0, arg
);
1802 case ATOMISP_IOC_S_TNR
:
1803 err
= atomisp_tnr(asd
, 1, arg
);
1806 case ATOMISP_IOC_G_BLACK_LEVEL_COMP
:
1807 err
= atomisp_black_level(asd
, 0, arg
);
1810 case ATOMISP_IOC_S_BLACK_LEVEL_COMP
:
1811 err
= atomisp_black_level(asd
, 1, arg
);
1814 case ATOMISP_IOC_G_EE
:
1815 err
= atomisp_ee(asd
, 0, arg
);
1818 case ATOMISP_IOC_S_EE
:
1819 err
= atomisp_ee(asd
, 1, arg
);
1822 case ATOMISP_IOC_G_DIS_STAT
:
1823 err
= atomisp_get_dis_stat(asd
, arg
);
1826 case ATOMISP_IOC_G_DVS2_BQ_RESOLUTIONS
:
1827 err
= atomisp_get_dvs2_bq_resolutions(asd
, arg
);
1830 case ATOMISP_IOC_S_DIS_COEFS
:
1831 err
= atomisp_css_cp_dvs2_coefs(asd
, arg
,
1832 &asd
->params
.css_param
, true);
1834 asd
->params
.css_update_params_needed
= true;
1837 case ATOMISP_IOC_S_DIS_VECTOR
:
1838 err
= atomisp_cp_dvs_6axis_config(asd
, arg
,
1839 &asd
->params
.css_param
, true);
1841 asd
->params
.css_update_params_needed
= true;
1844 case ATOMISP_IOC_G_ISP_PARM
:
1845 err
= atomisp_param(asd
, 0, arg
);
1848 case ATOMISP_IOC_S_ISP_PARM
:
1849 err
= atomisp_param(asd
, 1, arg
);
1852 case ATOMISP_IOC_G_3A_STAT
:
1853 err
= atomisp_3a_stat(asd
, 0, arg
);
1856 case ATOMISP_IOC_G_ISP_GAMMA
:
1857 err
= atomisp_gamma(asd
, 0, arg
);
1860 case ATOMISP_IOC_S_ISP_GAMMA
:
1861 err
= atomisp_gamma(asd
, 1, arg
);
1864 case ATOMISP_IOC_G_ISP_GDC_TAB
:
1865 err
= atomisp_gdc_cac_table(asd
, 0, arg
);
1868 case ATOMISP_IOC_S_ISP_GDC_TAB
:
1869 err
= atomisp_gdc_cac_table(asd
, 1, arg
);
1872 case ATOMISP_IOC_G_ISP_MACC
:
1873 err
= atomisp_macc_table(asd
, 0, arg
);
1876 case ATOMISP_IOC_S_ISP_MACC
:
1877 err
= atomisp_macc_table(asd
, 1, arg
);
1880 case ATOMISP_IOC_G_ISP_BAD_PIXEL_DETECTION
:
1881 err
= atomisp_bad_pixel_param(asd
, 0, arg
);
1884 case ATOMISP_IOC_S_ISP_BAD_PIXEL_DETECTION
:
1885 err
= atomisp_bad_pixel_param(asd
, 1, arg
);
1888 case ATOMISP_IOC_G_ISP_FALSE_COLOR_CORRECTION
:
1889 err
= atomisp_false_color_param(asd
, 0, arg
);
1892 case ATOMISP_IOC_S_ISP_FALSE_COLOR_CORRECTION
:
1893 err
= atomisp_false_color_param(asd
, 1, arg
);
1896 case ATOMISP_IOC_G_ISP_CTC
:
1897 err
= atomisp_ctc(asd
, 0, arg
);
1900 case ATOMISP_IOC_S_ISP_CTC
:
1901 err
= atomisp_ctc(asd
, 1, arg
);
1904 case ATOMISP_IOC_G_ISP_WHITE_BALANCE
:
1905 err
= atomisp_white_balance_param(asd
, 0, arg
);
1908 case ATOMISP_IOC_S_ISP_WHITE_BALANCE
:
1909 err
= atomisp_white_balance_param(asd
, 1, arg
);
1912 case ATOMISP_IOC_G_3A_CONFIG
:
1913 err
= atomisp_3a_config_param(asd
, 0, arg
);
1916 case ATOMISP_IOC_S_3A_CONFIG
:
1917 err
= atomisp_3a_config_param(asd
, 1, arg
);
1920 case ATOMISP_IOC_S_ISP_FPN_TABLE
:
1921 err
= atomisp_fixed_pattern_table(asd
, arg
);
1924 case ATOMISP_IOC_S_EXPOSURE
:
1925 err
= v4l2_subdev_call(isp
->inputs
[asd
->input_curr
].camera
,
1926 core
, ioctl
, cmd
, arg
);
1929 case ATOMISP_IOC_S_ISP_SHD_TAB
:
1930 err
= atomisp_set_shading_table(asd
, arg
);
1933 case ATOMISP_IOC_G_ISP_GAMMA_CORRECTION
:
1934 err
= atomisp_gamma_correction(asd
, 0, arg
);
1937 case ATOMISP_IOC_S_ISP_GAMMA_CORRECTION
:
1938 err
= atomisp_gamma_correction(asd
, 1, arg
);
1941 case ATOMISP_IOC_S_PARAMETERS
:
1942 err
= atomisp_set_parameters(vdev
, arg
);
1945 case ATOMISP_IOC_EXT_ISP_CTRL
:
1946 err
= v4l2_subdev_call(isp
->inputs
[asd
->input_curr
].camera
,
1947 core
, ioctl
, cmd
, arg
);
1949 case ATOMISP_IOC_EXP_ID_UNLOCK
:
1950 err
= atomisp_exp_id_unlock(asd
, arg
);
1952 case ATOMISP_IOC_EXP_ID_CAPTURE
:
1953 err
= atomisp_exp_id_capture(asd
, arg
);
1955 case ATOMISP_IOC_S_ENABLE_DZ_CAPT_PIPE
:
1956 err
= atomisp_enable_dz_capt_pipe(asd
, arg
);
1958 case ATOMISP_IOC_G_FORMATS_CONFIG
:
1959 err
= atomisp_formats(asd
, 0, arg
);
1962 case ATOMISP_IOC_S_FORMATS_CONFIG
:
1963 err
= atomisp_formats(asd
, 1, arg
);
1965 case ATOMISP_IOC_INJECT_A_FAKE_EVENT
:
1966 err
= atomisp_inject_a_fake_event(asd
, arg
);
1968 case ATOMISP_IOC_S_ARRAY_RESOLUTION
:
1969 err
= atomisp_set_array_res(asd
, arg
);
1979 const struct v4l2_ioctl_ops atomisp_ioctl_ops
= {
1980 .vidioc_querycap
= atomisp_querycap
,
1981 .vidioc_enum_input
= atomisp_enum_input
,
1982 .vidioc_g_input
= atomisp_g_input
,
1983 .vidioc_s_input
= atomisp_s_input
,
1984 .vidioc_queryctrl
= atomisp_queryctl
,
1985 .vidioc_s_ctrl
= atomisp_s_ctrl
,
1986 .vidioc_g_ctrl
= atomisp_g_ctrl
,
1987 .vidioc_s_ext_ctrls
= atomisp_s_ext_ctrls
,
1988 .vidioc_g_ext_ctrls
= atomisp_g_ext_ctrls
,
1989 .vidioc_enum_framesizes
= atomisp_enum_framesizes
,
1990 .vidioc_enum_frameintervals
= atomisp_enum_frameintervals
,
1991 .vidioc_enum_fmt_vid_cap
= atomisp_enum_fmt_cap
,
1992 .vidioc_try_fmt_vid_cap
= atomisp_try_fmt_cap
,
1993 .vidioc_g_fmt_vid_cap
= atomisp_g_fmt_cap
,
1994 .vidioc_s_fmt_vid_cap
= atomisp_s_fmt_cap
,
1995 .vidioc_reqbufs
= vb2_ioctl_reqbufs
,
1996 .vidioc_querybuf
= vb2_ioctl_querybuf
,
1997 .vidioc_qbuf
= atomisp_qbuf_wrapper
,
1998 .vidioc_dqbuf
= atomisp_dqbuf_wrapper
,
1999 .vidioc_streamon
= vb2_ioctl_streamon
,
2000 .vidioc_streamoff
= vb2_ioctl_streamoff
,
2001 .vidioc_default
= atomisp_vidioc_default
,
2002 .vidioc_s_parm
= atomisp_s_parm
,
2003 .vidioc_g_parm
= atomisp_g_parm
,