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>
26 #include <media/videobuf-vmalloc.h>
28 #include "atomisp_cmd.h"
29 #include "atomisp_common.h"
30 #include "atomisp_fops.h"
31 #include "atomisp_internal.h"
32 #include "atomisp_ioctl.h"
33 #include "atomisp-regs.h"
34 #include "atomisp_compat.h"
36 #include "sh_css_hrt.h"
38 #include "gp_device.h"
39 #include "device_access.h"
42 static const char *DRIVER = "atomisp"; /* max size 15 */
43 static const char *CARD = "ATOM ISP"; /* max size 31 */
46 * FIXME: ISP should not know beforehand all CIDs supported by sensor.
47 * Instead, it needs to propagate to sensor unkonwn CIDs.
49 static struct v4l2_queryctrl ci_v4l2_controls[] = {
51 .id = V4L2_CID_AUTO_WHITE_BALANCE,
52 .type = V4L2_CTRL_TYPE_BOOLEAN,
53 .name = "Automatic White Balance",
60 .id = V4L2_CID_RED_BALANCE,
61 .type = V4L2_CTRL_TYPE_INTEGER,
62 .name = "Red Balance",
66 .default_value = 0x00,
69 .id = V4L2_CID_BLUE_BALANCE,
70 .type = V4L2_CTRL_TYPE_INTEGER,
71 .name = "Blue Balance",
75 .default_value = 0x00,
79 .type = V4L2_CTRL_TYPE_INTEGER,
84 .default_value = 0x00,
87 .id = V4L2_CID_POWER_LINE_FREQUENCY,
88 .type = V4L2_CTRL_TYPE_MENU,
89 .name = "Light frequency filter",
96 .id = V4L2_CID_COLORFX,
97 .type = V4L2_CTRL_TYPE_INTEGER,
98 .name = "Image Color Effect",
105 .id = V4L2_CID_COLORFX_CBCR,
106 .type = V4L2_CTRL_TYPE_INTEGER,
107 .name = "Image Color Effect CbCr",
114 .id = V4L2_CID_ATOMISP_BAD_PIXEL_DETECTION,
115 .type = V4L2_CTRL_TYPE_INTEGER,
116 .name = "Bad Pixel Correction",
123 .id = V4L2_CID_ATOMISP_POSTPROCESS_GDC_CAC,
124 .type = V4L2_CTRL_TYPE_INTEGER,
132 .id = V4L2_CID_ATOMISP_VIDEO_STABLIZATION,
133 .type = V4L2_CTRL_TYPE_INTEGER,
134 .name = "Video Stablization",
141 .id = V4L2_CID_ATOMISP_FIXED_PATTERN_NR,
142 .type = V4L2_CTRL_TYPE_INTEGER,
143 .name = "Fixed Pattern Noise Reduction",
150 .id = V4L2_CID_ATOMISP_FALSE_COLOR_CORRECTION,
151 .type = V4L2_CTRL_TYPE_INTEGER,
152 .name = "False Color Correction",
159 .id = V4L2_CID_REQUEST_FLASH,
160 .type = V4L2_CTRL_TYPE_INTEGER,
161 .name = "Request flash frames",
168 .id = V4L2_CID_ATOMISP_LOW_LIGHT,
169 .type = V4L2_CTRL_TYPE_BOOLEAN,
170 .name = "Low light mode",
177 .id = V4L2_CID_BIN_FACTOR_HORZ,
178 .type = V4L2_CTRL_TYPE_INTEGER,
179 .name = "Horizontal binning factor",
186 .id = V4L2_CID_BIN_FACTOR_VERT,
187 .type = V4L2_CTRL_TYPE_INTEGER,
188 .name = "Vertical binning factor",
195 .id = V4L2_CID_2A_STATUS,
196 .type = V4L2_CTRL_TYPE_BITMASK,
197 .name = "AE and AWB status",
199 .maximum = V4L2_2A_STATUS_AE_READY | V4L2_2A_STATUS_AWB_READY,
204 .id = V4L2_CID_EXPOSURE,
205 .type = V4L2_CTRL_TYPE_INTEGER,
213 .id = V4L2_CID_EXPOSURE_ZONE_NUM,
214 .type = V4L2_CTRL_TYPE_INTEGER,
215 .name = "one-time exposure zone number",
222 .id = V4L2_CID_EXPOSURE_AUTO_PRIORITY,
223 .type = V4L2_CTRL_TYPE_INTEGER,
224 .name = "Exposure auto priority",
225 .minimum = V4L2_EXPOSURE_AUTO,
226 .maximum = V4L2_EXPOSURE_APERTURE_PRIORITY,
228 .default_value = V4L2_EXPOSURE_AUTO,
231 .id = V4L2_CID_SCENE_MODE,
232 .type = V4L2_CTRL_TYPE_INTEGER,
233 .name = "scene mode",
240 .id = V4L2_CID_ISO_SENSITIVITY,
241 .type = V4L2_CTRL_TYPE_INTEGER,
249 .id = V4L2_CID_ISO_SENSITIVITY_AUTO,
250 .type = V4L2_CTRL_TYPE_INTEGER,
252 .minimum = V4L2_ISO_SENSITIVITY_MANUAL,
253 .maximum = V4L2_ISO_SENSITIVITY_AUTO,
255 .default_value = V4L2_ISO_SENSITIVITY_AUTO,
258 .id = V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE,
259 .type = V4L2_CTRL_TYPE_INTEGER,
260 .name = "white balance",
267 .id = V4L2_CID_EXPOSURE_METERING,
268 .type = V4L2_CTRL_TYPE_MENU,
276 .id = V4L2_CID_3A_LOCK,
277 .type = V4L2_CTRL_TYPE_BITMASK,
280 .maximum = V4L2_LOCK_EXPOSURE | V4L2_LOCK_WHITE_BALANCE
286 .id = V4L2_CID_TEST_PATTERN,
287 .type = V4L2_CTRL_TYPE_INTEGER,
288 .name = "Test Pattern",
295 .id = V4L2_CID_TEST_PATTERN_COLOR_R,
296 .type = V4L2_CTRL_TYPE_INTEGER,
297 .name = "Test Pattern Solid Color R",
304 .id = V4L2_CID_TEST_PATTERN_COLOR_GR,
305 .type = V4L2_CTRL_TYPE_INTEGER,
306 .name = "Test Pattern Solid Color GR",
313 .id = V4L2_CID_TEST_PATTERN_COLOR_GB,
314 .type = V4L2_CTRL_TYPE_INTEGER,
315 .name = "Test Pattern Solid Color GB",
322 .id = V4L2_CID_TEST_PATTERN_COLOR_B,
323 .type = V4L2_CTRL_TYPE_INTEGER,
324 .name = "Test Pattern Solid Color B",
332 static const u32 ctrls_num = ARRAY_SIZE(ci_v4l2_controls);
335 * supported V4L2 fmts and resolutions
337 const struct atomisp_format_bridge atomisp_output_fmts[] = {
339 .pixelformat = V4L2_PIX_FMT_YUV420,
341 .mbus_code = V4L2_MBUS_FMT_CUSTOM_YUV420,
342 .sh_fmt = IA_CSS_FRAME_FORMAT_YUV420,
343 .description = "YUV420, planar",
346 .pixelformat = V4L2_PIX_FMT_YVU420,
348 .mbus_code = V4L2_MBUS_FMT_CUSTOM_YVU420,
349 .sh_fmt = IA_CSS_FRAME_FORMAT_YV12,
350 .description = "YVU420, planar",
353 .pixelformat = V4L2_PIX_FMT_YUV422P,
355 .mbus_code = V4L2_MBUS_FMT_CUSTOM_YUV422P,
356 .sh_fmt = IA_CSS_FRAME_FORMAT_YUV422,
357 .description = "YUV422, planar",
360 .pixelformat = V4L2_PIX_FMT_YUV444,
362 .mbus_code = V4L2_MBUS_FMT_CUSTOM_YUV444,
363 .sh_fmt = IA_CSS_FRAME_FORMAT_YUV444,
364 .description = "YUV444"
366 .pixelformat = V4L2_PIX_FMT_NV12,
368 .mbus_code = V4L2_MBUS_FMT_CUSTOM_NV12,
369 .sh_fmt = IA_CSS_FRAME_FORMAT_NV12,
370 .description = "NV12, Y-plane, CbCr interleaved",
373 .pixelformat = V4L2_PIX_FMT_NV21,
375 .mbus_code = V4L2_MBUS_FMT_CUSTOM_NV21,
376 .sh_fmt = IA_CSS_FRAME_FORMAT_NV21,
377 .description = "NV21, Y-plane, CbCr interleaved",
380 .pixelformat = V4L2_PIX_FMT_NV16,
382 .mbus_code = V4L2_MBUS_FMT_CUSTOM_NV16,
383 .sh_fmt = IA_CSS_FRAME_FORMAT_NV16,
384 .description = "NV16, Y-plane, CbCr interleaved",
387 .pixelformat = V4L2_PIX_FMT_YUYV,
389 .mbus_code = V4L2_MBUS_FMT_CUSTOM_YUYV,
390 .sh_fmt = IA_CSS_FRAME_FORMAT_YUYV,
391 .description = "YUYV, interleaved"
393 .pixelformat = V4L2_PIX_FMT_UYVY,
395 .mbus_code = MEDIA_BUS_FMT_UYVY8_1X16,
396 .sh_fmt = IA_CSS_FRAME_FORMAT_UYVY,
397 .description = "UYVY, interleaved"
398 }, { /* This one is for parallel sensors! DO NOT USE! */
399 .pixelformat = V4L2_PIX_FMT_UYVY,
401 .mbus_code = MEDIA_BUS_FMT_UYVY8_2X8,
402 .sh_fmt = IA_CSS_FRAME_FORMAT_UYVY,
403 .description = "UYVY, interleaved"
405 .pixelformat = V4L2_PIX_FMT_SBGGR16,
407 .mbus_code = V4L2_MBUS_FMT_CUSTOM_SBGGR16,
408 .sh_fmt = IA_CSS_FRAME_FORMAT_RAW,
409 .description = "Bayer 16"
411 .pixelformat = V4L2_PIX_FMT_SBGGR8,
413 .mbus_code = MEDIA_BUS_FMT_SBGGR8_1X8,
414 .sh_fmt = IA_CSS_FRAME_FORMAT_RAW,
415 .description = "Bayer 8"
417 .pixelformat = V4L2_PIX_FMT_SGBRG8,
419 .mbus_code = MEDIA_BUS_FMT_SGBRG8_1X8,
420 .sh_fmt = IA_CSS_FRAME_FORMAT_RAW,
421 .description = "Bayer 8"
423 .pixelformat = V4L2_PIX_FMT_SGRBG8,
425 .mbus_code = MEDIA_BUS_FMT_SGRBG8_1X8,
426 .sh_fmt = IA_CSS_FRAME_FORMAT_RAW,
427 .description = "Bayer 8"
429 .pixelformat = V4L2_PIX_FMT_SRGGB8,
431 .mbus_code = MEDIA_BUS_FMT_SRGGB8_1X8,
432 .sh_fmt = IA_CSS_FRAME_FORMAT_RAW,
433 .description = "Bayer 8"
435 .pixelformat = V4L2_PIX_FMT_SBGGR10,
437 .mbus_code = MEDIA_BUS_FMT_SBGGR10_1X10,
438 .sh_fmt = IA_CSS_FRAME_FORMAT_RAW,
439 .description = "Bayer 10"
441 .pixelformat = V4L2_PIX_FMT_SGBRG10,
443 .mbus_code = MEDIA_BUS_FMT_SGBRG10_1X10,
444 .sh_fmt = IA_CSS_FRAME_FORMAT_RAW,
445 .description = "Bayer 10"
447 .pixelformat = V4L2_PIX_FMT_SGRBG10,
449 .mbus_code = MEDIA_BUS_FMT_SGRBG10_1X10,
450 .sh_fmt = IA_CSS_FRAME_FORMAT_RAW,
451 .description = "Bayer 10"
453 .pixelformat = V4L2_PIX_FMT_SRGGB10,
455 .mbus_code = MEDIA_BUS_FMT_SRGGB10_1X10,
456 .sh_fmt = IA_CSS_FRAME_FORMAT_RAW,
457 .description = "Bayer 10"
459 .pixelformat = V4L2_PIX_FMT_SBGGR12,
461 .mbus_code = MEDIA_BUS_FMT_SBGGR12_1X12,
462 .sh_fmt = IA_CSS_FRAME_FORMAT_RAW,
463 .description = "Bayer 12"
465 .pixelformat = V4L2_PIX_FMT_SGBRG12,
467 .mbus_code = MEDIA_BUS_FMT_SGBRG12_1X12,
468 .sh_fmt = IA_CSS_FRAME_FORMAT_RAW,
469 .description = "Bayer 12"
471 .pixelformat = V4L2_PIX_FMT_SGRBG12,
473 .mbus_code = MEDIA_BUS_FMT_SGRBG12_1X12,
474 .sh_fmt = IA_CSS_FRAME_FORMAT_RAW,
475 .description = "Bayer 12"
477 .pixelformat = V4L2_PIX_FMT_SRGGB12,
479 .mbus_code = MEDIA_BUS_FMT_SRGGB12_1X12,
480 .sh_fmt = IA_CSS_FRAME_FORMAT_RAW,
481 .description = "Bayer 12"
483 .pixelformat = V4L2_PIX_FMT_RGB32,
485 .mbus_code = V4L2_MBUS_FMT_CUSTOM_RGB32,
486 .sh_fmt = IA_CSS_FRAME_FORMAT_RGBA888,
487 .description = "32 RGB 8-8-8-8"
489 .pixelformat = V4L2_PIX_FMT_RGB565,
491 .mbus_code = MEDIA_BUS_FMT_BGR565_2X8_LE,
492 .sh_fmt = IA_CSS_FRAME_FORMAT_RGB565,
493 .description = "16 RGB 5-6-5"
496 .pixelformat = V4L2_PIX_FMT_JPEG,
498 .mbus_code = MEDIA_BUS_FMT_JPEG_1X8,
499 .sh_fmt = IA_CSS_FRAME_FORMAT_BINARY_8,
500 .description = "JPEG"
502 /* This is a custom format being used by M10MO to send the RAW data */
503 .pixelformat = V4L2_PIX_FMT_CUSTOM_M10MO_RAW,
505 .mbus_code = V4L2_MBUS_FMT_CUSTOM_M10MO_RAW,
506 .sh_fmt = IA_CSS_FRAME_FORMAT_BINARY_8,
507 .description = "Custom RAW for M10MO"
512 const struct atomisp_format_bridge *
513 atomisp_get_format_bridge(unsigned int pixelformat)
517 for (i = 0; i < ARRAY_SIZE(atomisp_output_fmts); i++) {
518 if (atomisp_output_fmts[i].pixelformat == pixelformat)
519 return &atomisp_output_fmts[i];
525 const struct atomisp_format_bridge *
526 atomisp_get_format_bridge_from_mbus(u32 mbus_code)
530 for (i = 0; i < ARRAY_SIZE(atomisp_output_fmts); i++) {
531 if (mbus_code == atomisp_output_fmts[i].mbus_code)
532 return &atomisp_output_fmts[i];
538 int atomisp_pipe_check(struct atomisp_video_pipe *pipe, bool settings_change)
540 lockdep_assert_held(&pipe->isp->mutex);
542 if (pipe->isp->isp_fatal_error)
545 switch (pipe->asd->streaming) {
546 case ATOMISP_DEVICE_STREAMING_DISABLED:
548 case ATOMISP_DEVICE_STREAMING_ENABLED:
549 if (settings_change) {
550 dev_err(pipe->isp->dev, "Set fmt/input IOCTL while streaming\n");
554 case ATOMISP_DEVICE_STREAMING_STOPPING:
555 dev_err(pipe->isp->dev, "IOCTL issued while stopping\n");
566 * return ISP capabilities
568 static int atomisp_querycap(struct file *file, void *fh,
569 struct v4l2_capability *cap)
571 struct video_device *vdev = video_devdata(file);
572 struct atomisp_device *isp = video_get_drvdata(vdev);
574 strscpy(cap->driver, DRIVER, sizeof(cap->driver));
575 strscpy(cap->card, CARD, sizeof(cap->card));
576 snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s", dev_name(isp->dev));
582 * enum input are used to check primary/secondary camera
584 static int atomisp_enum_input(struct file *file, void *fh,
585 struct v4l2_input *input)
587 struct video_device *vdev = video_devdata(file);
588 struct atomisp_device *isp = video_get_drvdata(vdev);
589 int index = input->index;
590 struct v4l2_subdev *motor;
592 if (index >= isp->input_cnt)
595 if (!isp->inputs[index].camera)
598 memset(input, 0, sizeof(struct v4l2_input));
599 strscpy(input->name, isp->inputs[index].camera->name,
600 sizeof(input->name));
603 * HACK: append actuator's name to sensor's
604 * As currently userspace can't talk directly to subdev nodes, this
605 * ioctl is the only way to enum inputs + possible external actuators
606 * for 3A tuning purpose.
609 motor = isp->inputs[index].motor;
613 if (motor && strlen(motor->name) > 0) {
614 const int cur_len = strlen(input->name);
615 const int max_size = sizeof(input->name) - cur_len - 1;
618 input->name[cur_len] = '+';
619 strscpy(&input->name[cur_len + 1],
620 motor->name, max_size);
624 input->type = V4L2_INPUT_TYPE_CAMERA;
625 input->index = index;
626 input->reserved[0] = isp->inputs[index].type;
627 input->reserved[1] = isp->inputs[index].port;
633 atomisp_subdev_streaming_count(struct atomisp_sub_device *asd)
635 return asd->video_out_preview.capq.streaming
636 + asd->video_out_capture.capq.streaming
637 + asd->video_out_video_capture.capq.streaming
638 + asd->video_out_vf.capq.streaming;
641 unsigned int atomisp_streaming_count(struct atomisp_device *isp)
645 for (i = 0, sum = 0; i < isp->num_of_streams; i++)
646 sum += isp->asd[i].streaming ==
647 ATOMISP_DEVICE_STREAMING_ENABLED;
653 * get input are used to get current primary/secondary camera
655 static int atomisp_g_input(struct file *file, void *fh, unsigned int *input)
657 struct video_device *vdev = video_devdata(file);
658 struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd;
660 *input = asd->input_curr;
665 * set input are used to set current primary/secondary camera
667 static int atomisp_s_input(struct file *file, void *fh, unsigned int input)
669 struct video_device *vdev = video_devdata(file);
670 struct atomisp_device *isp = video_get_drvdata(vdev);
671 struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev);
672 struct atomisp_sub_device *asd = pipe->asd;
673 struct v4l2_subdev *camera = NULL;
674 struct v4l2_subdev *motor;
677 ret = atomisp_pipe_check(pipe, true);
681 if (input >= ATOM_ISP_MAX_INPUTS || input >= isp->input_cnt) {
682 dev_dbg(isp->dev, "input_cnt: %d\n", isp->input_cnt);
687 * check whether the request camera:
689 * 2: if in use, whether it is used by other streams
691 if (isp->inputs[input].asd && isp->inputs[input].asd != asd) {
693 "%s, camera is already used by stream: %d\n", __func__,
694 isp->inputs[input].asd->index);
698 camera = isp->inputs[input].camera;
700 dev_err(isp->dev, "%s, no camera\n", __func__);
704 /* power off the current owned sensor, as it is not used this time */
705 if (isp->inputs[asd->input_curr].asd == asd &&
706 asd->input_curr != input) {
707 ret = v4l2_subdev_call(isp->inputs[asd->input_curr].camera,
711 "Failed to power-off sensor\n");
712 /* clear the asd field to show this camera is not used */
713 isp->inputs[asd->input_curr].asd = NULL;
716 /* powe on the new sensor */
717 ret = v4l2_subdev_call(isp->inputs[input].camera, core, s_power, 1);
719 dev_err(isp->dev, "Failed to power-on sensor\n");
723 * Some sensor driver resets the run mode during power-on, thus force
724 * update the run mode to sensor after power-on.
726 atomisp_update_run_mode(asd);
728 /* select operating sensor */
729 ret = v4l2_subdev_call(isp->inputs[input].camera, video, s_routing,
730 0, isp->inputs[input].sensor_index, 0);
731 if (ret && (ret != -ENOIOCTLCMD)) {
732 dev_err(isp->dev, "Failed to select sensor\n");
737 motor = isp->inputs[input].motor;
741 ret = v4l2_subdev_call(motor, core, s_power, 1);
745 ret = v4l2_subdev_call(motor, core, init, 1);
747 asd->input_curr = input;
748 /* mark this camera is used by the current stream */
749 isp->inputs[input].asd = asd;
754 static int atomisp_enum_framesizes(struct file *file, void *priv,
755 struct v4l2_frmsizeenum *fsize)
757 struct video_device *vdev = video_devdata(file);
758 struct atomisp_device *isp = video_get_drvdata(vdev);
759 struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd;
760 struct v4l2_subdev_frame_size_enum fse = {
761 .index = fsize->index,
762 .which = V4L2_SUBDEV_FORMAT_ACTIVE,
766 ret = v4l2_subdev_call(isp->inputs[asd->input_curr].camera,
767 pad, enum_frame_size, NULL, &fse);
771 fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
772 fsize->discrete.width = fse.max_width - pad_w;
773 fsize->discrete.height = fse.max_height - pad_h;
778 static int atomisp_enum_frameintervals(struct file *file, void *priv,
779 struct v4l2_frmivalenum *fival)
781 struct video_device *vdev = video_devdata(file);
782 struct atomisp_device *isp = video_get_drvdata(vdev);
783 struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd;
784 struct v4l2_subdev_frame_interval_enum fie = {
785 .code = atomisp_in_fmt_conv[0].code,
786 .index = fival->index,
787 .width = fival->width,
788 .height = fival->height,
789 .which = V4L2_SUBDEV_FORMAT_ACTIVE,
793 ret = v4l2_subdev_call(isp->inputs[asd->input_curr].camera,
794 pad, enum_frame_interval, NULL,
799 fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
800 fival->discrete = fie.interval;
805 static int atomisp_enum_fmt_cap(struct file *file, void *fh,
806 struct v4l2_fmtdesc *f)
808 struct video_device *vdev = video_devdata(file);
809 struct atomisp_device *isp = video_get_drvdata(vdev);
810 struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd;
811 struct v4l2_subdev_mbus_code_enum code = {
812 .which = V4L2_SUBDEV_FORMAT_ACTIVE,
814 const struct atomisp_format_bridge *format;
815 struct v4l2_subdev *camera;
816 unsigned int i, fi = 0;
819 camera = isp->inputs[asd->input_curr].camera;
821 dev_err(isp->dev, "%s(): camera is NULL, device is %s\n",
822 __func__, vdev->name);
826 rval = v4l2_subdev_call(camera, pad, enum_mbus_code, NULL, &code);
827 if (rval == -ENOIOCTLCMD) {
829 "enum_mbus_code pad op not supported by %s. Please fix your sensor driver!\n",
836 for (i = 0; i < ARRAY_SIZE(atomisp_output_fmts); i++) {
837 format = &atomisp_output_fmts[i];
840 * Is the atomisp-supported format is valid for the
841 * sensor (configuration)? If not, skip it.
843 * FIXME: fix the pipeline to allow sensor format too.
845 if (format->sh_fmt == IA_CSS_FRAME_FORMAT_RAW)
848 /* Found a match. Now let's pick f->index'th one. */
854 strscpy(f->description, format->description,
855 sizeof(f->description));
856 f->pixelformat = format->pixelformat;
863 static int atomisp_adjust_fmt(struct v4l2_format *f)
865 const struct atomisp_format_bridge *format_bridge;
868 format_bridge = atomisp_get_format_bridge(f->fmt.pix.pixelformat);
870 padded_width = f->fmt.pix.width + pad_w;
872 if (format_bridge->planar) {
873 f->fmt.pix.bytesperline = padded_width;
874 f->fmt.pix.sizeimage = PAGE_ALIGN(f->fmt.pix.height *
875 DIV_ROUND_UP(format_bridge->depth *
878 f->fmt.pix.bytesperline = DIV_ROUND_UP(format_bridge->depth *
880 f->fmt.pix.sizeimage = PAGE_ALIGN(f->fmt.pix.height * f->fmt.pix.bytesperline);
883 if (f->fmt.pix.field == V4L2_FIELD_ANY)
884 f->fmt.pix.field = V4L2_FIELD_NONE;
886 format_bridge = atomisp_get_format_bridge(f->fmt.pix.pixelformat);
890 /* Currently, raw formats are broken!!! */
891 if (format_bridge->sh_fmt == IA_CSS_FRAME_FORMAT_RAW) {
892 f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420;
894 format_bridge = atomisp_get_format_bridge(f->fmt.pix.pixelformat);
899 padded_width = f->fmt.pix.width + pad_w;
901 if (format_bridge->planar) {
902 f->fmt.pix.bytesperline = padded_width;
903 f->fmt.pix.sizeimage = PAGE_ALIGN(f->fmt.pix.height *
904 DIV_ROUND_UP(format_bridge->depth *
907 f->fmt.pix.bytesperline = DIV_ROUND_UP(format_bridge->depth *
909 f->fmt.pix.sizeimage = PAGE_ALIGN(f->fmt.pix.height * f->fmt.pix.bytesperline);
912 if (f->fmt.pix.field == V4L2_FIELD_ANY)
913 f->fmt.pix.field = V4L2_FIELD_NONE;
916 * FIXME: do we need to setup this differently, depending on the
917 * sensor or the pipeline?
919 f->fmt.pix.colorspace = V4L2_COLORSPACE_REC709;
920 f->fmt.pix.ycbcr_enc = V4L2_YCBCR_ENC_709;
921 f->fmt.pix.xfer_func = V4L2_XFER_FUNC_709;
923 f->fmt.pix.width -= pad_w;
924 f->fmt.pix.height -= pad_h;
929 /* This function looks up the closest available resolution. */
930 static int atomisp_try_fmt_cap(struct file *file, void *fh,
931 struct v4l2_format *f)
933 struct video_device *vdev = video_devdata(file);
937 * atomisp_try_fmt() gived results with padding included, note
938 * (this gets removed again by the atomisp_adjust_fmt() call below.
940 f->fmt.pix.width += pad_w;
941 f->fmt.pix.height += pad_h;
943 ret = atomisp_try_fmt(vdev, &f->fmt.pix, NULL);
947 return atomisp_adjust_fmt(f);
950 static int atomisp_g_fmt_cap(struct file *file, void *fh,
951 struct v4l2_format *f)
953 struct video_device *vdev = video_devdata(file);
954 struct atomisp_video_pipe *pipe;
956 pipe = atomisp_to_video_pipe(vdev);
958 f->fmt.pix = pipe->pix;
960 /* If s_fmt was issued, just return whatever is was previouly set */
961 if (f->fmt.pix.sizeimage)
964 f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
965 f->fmt.pix.width = 10000;
966 f->fmt.pix.height = 10000;
968 return atomisp_try_fmt_cap(file, fh, f);
971 static int atomisp_s_fmt_cap(struct file *file, void *fh,
972 struct v4l2_format *f)
974 struct video_device *vdev = video_devdata(file);
976 return atomisp_set_fmt(vdev, f);
980 * Free videobuffer buffer priv data
982 void atomisp_videobuf_free_buf(struct videobuf_buffer *vb)
984 struct videobuf_vmalloc_memory *vm_mem;
990 if (vm_mem && vm_mem->vaddr) {
991 ia_css_frame_free(vm_mem->vaddr);
992 vm_mem->vaddr = NULL;
997 * this function is used to free video buffer queue
999 static void atomisp_videobuf_free_queue(struct videobuf_queue *q)
1003 for (i = 0; i < VIDEO_MAX_FRAME; i++) {
1004 atomisp_videobuf_free_buf(q->bufs[i]);
1010 int atomisp_alloc_css_stat_bufs(struct atomisp_sub_device *asd,
1013 struct atomisp_device *isp = asd->isp;
1014 struct atomisp_s3a_buf *s3a_buf = NULL, *_s3a_buf;
1015 struct atomisp_dis_buf *dis_buf = NULL, *_dis_buf;
1016 struct atomisp_metadata_buf *md_buf = NULL, *_md_buf;
1018 struct ia_css_dvs_grid_info *dvs_grid_info =
1019 atomisp_css_get_dvs_grid_info(&asd->params.curr_grid_info);
1022 if (list_empty(&asd->s3a_stats) &&
1023 asd->params.curr_grid_info.s3a_grid.enable) {
1024 count = ATOMISP_CSS_Q_DEPTH +
1025 ATOMISP_S3A_BUF_QUEUE_DEPTH_FOR_HAL;
1026 dev_dbg(isp->dev, "allocating %d 3a buffers\n", count);
1028 s3a_buf = kzalloc(sizeof(struct atomisp_s3a_buf), GFP_KERNEL);
1032 if (atomisp_css_allocate_stat_buffers(
1033 asd, stream_id, s3a_buf, NULL, NULL)) {
1038 list_add_tail(&s3a_buf->list, &asd->s3a_stats);
1042 if (list_empty(&asd->dis_stats) && dvs_grid_info &&
1043 dvs_grid_info->enable) {
1044 count = ATOMISP_CSS_Q_DEPTH + 1;
1045 dev_dbg(isp->dev, "allocating %d dis buffers\n", count);
1047 dis_buf = kzalloc(sizeof(struct atomisp_dis_buf), GFP_KERNEL);
1050 if (atomisp_css_allocate_stat_buffers(
1051 asd, stream_id, NULL, dis_buf, NULL)) {
1056 list_add_tail(&dis_buf->list, &asd->dis_stats);
1060 for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) {
1061 if (list_empty(&asd->metadata[i]) &&
1062 list_empty(&asd->metadata_ready[i]) &&
1063 list_empty(&asd->metadata_in_css[i])) {
1064 count = ATOMISP_CSS_Q_DEPTH +
1065 ATOMISP_METADATA_QUEUE_DEPTH_FOR_HAL;
1066 dev_dbg(isp->dev, "allocating %d metadata buffers for type %d\n",
1069 md_buf = kzalloc(sizeof(struct atomisp_metadata_buf),
1074 if (atomisp_css_allocate_stat_buffers(
1075 asd, stream_id, NULL, NULL, md_buf)) {
1079 list_add_tail(&md_buf->list, &asd->metadata[i]);
1086 dev_err(isp->dev, "failed to allocate statistics buffers\n");
1088 list_for_each_entry_safe(dis_buf, _dis_buf, &asd->dis_stats, list) {
1089 atomisp_css_free_dis_buffer(dis_buf);
1090 list_del(&dis_buf->list);
1094 list_for_each_entry_safe(s3a_buf, _s3a_buf, &asd->s3a_stats, list) {
1095 atomisp_css_free_3a_buffer(s3a_buf);
1096 list_del(&s3a_buf->list);
1100 for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) {
1101 list_for_each_entry_safe(md_buf, _md_buf, &asd->metadata[i],
1103 atomisp_css_free_metadata_buffer(md_buf);
1104 list_del(&md_buf->list);
1112 * Initiate Memory Mapping or User Pointer I/O
1114 int __atomisp_reqbufs(struct file *file, void *fh,
1115 struct v4l2_requestbuffers *req)
1117 struct video_device *vdev = video_devdata(file);
1118 struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev);
1119 struct atomisp_sub_device *asd = pipe->asd;
1120 struct ia_css_frame_info frame_info;
1121 struct ia_css_frame *frame;
1122 struct videobuf_vmalloc_memory *vm_mem;
1123 u16 source_pad = atomisp_subdev_source_pad(vdev);
1127 stream_id = atomisp_source_pad_to_stream_id(asd, source_pad);
1129 if (req->count == 0) {
1130 mutex_lock(&pipe->capq.vb_lock);
1131 if (!list_empty(&pipe->capq.stream))
1132 videobuf_queue_cancel(&pipe->capq);
1134 atomisp_videobuf_free_queue(&pipe->capq);
1135 mutex_unlock(&pipe->capq.vb_lock);
1136 /* clear request config id */
1137 memset(pipe->frame_request_config_id, 0,
1138 VIDEO_MAX_FRAME * sizeof(unsigned int));
1139 memset(pipe->frame_params, 0,
1141 sizeof(struct atomisp_css_params_with_list *));
1145 ret = videobuf_reqbufs(&pipe->capq, req);
1149 atomisp_alloc_css_stat_bufs(asd, stream_id);
1152 * for user pointer type, buffers are not really allocated here,
1153 * buffers are setup in QBUF operation through v4l2_buffer structure
1155 if (req->memory == V4L2_MEMORY_USERPTR)
1158 ret = atomisp_get_css_frame_info(asd, source_pad, &frame_info);
1163 * Allocate the real frame here for selected node using our
1164 * memory management function
1166 for (i = 0; i < req->count; i++) {
1167 if (ia_css_frame_allocate_from_info(&frame, &frame_info))
1169 vm_mem = pipe->capq.bufs[i]->priv;
1170 vm_mem->vaddr = frame;
1177 vm_mem = pipe->capq.bufs[i]->priv;
1178 ia_css_frame_free(vm_mem->vaddr);
1182 ia_css_frame_free(asd->vf_frame);
1187 int atomisp_reqbufs(struct file *file, void *fh,
1188 struct v4l2_requestbuffers *req)
1190 return __atomisp_reqbufs(file, fh, req);
1193 /* application query the status of a buffer */
1194 static int atomisp_querybuf(struct file *file, void *fh,
1195 struct v4l2_buffer *buf)
1197 struct video_device *vdev = video_devdata(file);
1198 struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev);
1200 return videobuf_querybuf(&pipe->capq, buf);
1204 * Applications call the VIDIOC_QBUF ioctl to enqueue an empty (capturing) or
1205 * filled (output) buffer in the drivers incoming queue.
1207 static int atomisp_qbuf(struct file *file, void *fh, struct v4l2_buffer *buf)
1209 static const int NOFLUSH_FLAGS = V4L2_BUF_FLAG_NO_CACHE_INVALIDATE |
1210 V4L2_BUF_FLAG_NO_CACHE_CLEAN;
1211 struct video_device *vdev = video_devdata(file);
1212 struct atomisp_device *isp = video_get_drvdata(vdev);
1213 struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev);
1214 struct atomisp_sub_device *asd = pipe->asd;
1215 struct videobuf_buffer *vb;
1216 struct videobuf_vmalloc_memory *vm_mem;
1217 struct ia_css_frame_info frame_info;
1218 struct ia_css_frame *handle = NULL;
1223 ret = atomisp_pipe_check(pipe, false);
1227 if (!buf || buf->index >= VIDEO_MAX_FRAME ||
1228 !pipe->capq.bufs[buf->index]) {
1229 dev_err(isp->dev, "Invalid index for qbuf.\n");
1234 * For userptr type frame, we convert user space address to physic
1235 * address and reprograme out page table properly
1237 if (buf->memory == V4L2_MEMORY_USERPTR) {
1238 if (offset_in_page(buf->m.userptr)) {
1239 dev_err(isp->dev, "Error userptr is not page aligned.\n");
1243 vb = pipe->capq.bufs[buf->index];
1249 pgnr = (length + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
1251 if (vb->baddr == buf->m.userptr && vm_mem->vaddr)
1254 if (atomisp_get_css_frame_info(asd,
1255 atomisp_subdev_source_pad(vdev), &frame_info))
1258 ret = ia_css_frame_map(&handle, &frame_info,
1259 (void __user *)buf->m.userptr,
1262 dev_err(isp->dev, "Failed to map user buffer\n");
1266 if (vm_mem->vaddr) {
1267 mutex_lock(&pipe->capq.vb_lock);
1268 ia_css_frame_free(vm_mem->vaddr);
1269 vm_mem->vaddr = NULL;
1270 vb->state = VIDEOBUF_NEEDS_INIT;
1271 mutex_unlock(&pipe->capq.vb_lock);
1274 vm_mem->vaddr = handle;
1276 buf->flags &= ~V4L2_BUF_FLAG_MAPPED;
1277 buf->flags |= V4L2_BUF_FLAG_QUEUED;
1278 buf->flags &= ~V4L2_BUF_FLAG_DONE;
1279 } else if (buf->memory == V4L2_MEMORY_MMAP) {
1280 buf->flags |= V4L2_BUF_FLAG_MAPPED;
1281 buf->flags |= V4L2_BUF_FLAG_QUEUED;
1282 buf->flags &= ~V4L2_BUF_FLAG_DONE;
1285 * For mmap, frames were allocated at request buffers
1290 if (!((buf->flags & NOFLUSH_FLAGS) == NOFLUSH_FLAGS))
1293 if (!atomisp_is_vf_pipe(pipe) &&
1294 (buf->reserved2 & ATOMISP_BUFFER_HAS_PER_FRAME_SETTING)) {
1295 /* this buffer will have a per-frame parameter */
1296 pipe->frame_request_config_id[buf->index] = buf->reserved2 &
1297 ~ATOMISP_BUFFER_HAS_PER_FRAME_SETTING;
1299 "This buffer requires per_frame setting which has isp_config_id %d\n",
1300 pipe->frame_request_config_id[buf->index]);
1302 pipe->frame_request_config_id[buf->index] = 0;
1305 pipe->frame_params[buf->index] = NULL;
1307 mutex_unlock(&isp->mutex);
1308 ret = videobuf_qbuf(&pipe->capq, buf);
1309 mutex_lock(&isp->mutex);
1313 /* TODO: do this better, not best way to queue to css */
1314 if (asd->streaming == ATOMISP_DEVICE_STREAMING_ENABLED) {
1315 if (!list_empty(&pipe->buffers_waiting_for_param)) {
1316 atomisp_handle_parameter_and_buffer(pipe);
1318 atomisp_qbuffers_to_css(asd);
1323 * Workaround: Due to the design of HALv3,
1324 * sometimes in ZSL or SDV mode HAL needs to
1325 * capture multiple images within one streaming cycle.
1326 * But the capture number cannot be determined by HAL.
1327 * So HAL only sets the capture number to be 1 and queue multiple
1328 * buffers. Atomisp driver needs to check this case and re-trigger
1329 * CSS to do capture when new buffer is queued.
1331 if (asd->continuous_mode->val &&
1332 atomisp_subdev_source_pad(vdev)
1333 == ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE &&
1334 pipe->capq.streaming &&
1335 !asd->enable_raw_buffer_lock->val &&
1336 asd->params.offline_parm.num_captures == 1) {
1337 asd->pending_capture_request++;
1338 dev_dbg(isp->dev, "Add one pending capture request.\n");
1341 dev_dbg(isp->dev, "qbuf buffer %d (%s) for asd%d\n", buf->index,
1342 vdev->name, asd->index);
1347 static int __get_frame_exp_id(struct atomisp_video_pipe *pipe,
1348 struct v4l2_buffer *buf)
1350 struct videobuf_vmalloc_memory *vm_mem;
1351 struct ia_css_frame *handle;
1354 for (i = 0; pipe->capq.bufs[i]; i++) {
1355 vm_mem = pipe->capq.bufs[i]->priv;
1356 handle = vm_mem->vaddr;
1357 if (buf->index == pipe->capq.bufs[i]->i && handle)
1358 return handle->exp_id;
1364 * Applications call the VIDIOC_DQBUF ioctl to dequeue a filled (capturing) or
1365 * displayed (output buffer)from the driver's outgoing queue
1367 static int atomisp_dqbuf(struct file *file, void *fh, struct v4l2_buffer *buf)
1369 struct video_device *vdev = video_devdata(file);
1370 struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev);
1371 struct atomisp_sub_device *asd = pipe->asd;
1372 struct atomisp_device *isp = video_get_drvdata(vdev);
1375 ret = atomisp_pipe_check(pipe, false);
1379 mutex_unlock(&isp->mutex);
1380 ret = videobuf_dqbuf(&pipe->capq, buf, file->f_flags & O_NONBLOCK);
1381 mutex_lock(&isp->mutex);
1384 dev_dbg(isp->dev, "<%s: %d\n", __func__, ret);
1388 buf->bytesused = pipe->pix.sizeimage;
1389 buf->reserved = asd->frame_status[buf->index];
1393 * Currently frame_status in the enum type which takes no more lower
1395 * use bit[31:16] for exp_id as it is only in the range of 1~255
1397 buf->reserved &= 0x0000ffff;
1398 if (!(buf->flags & V4L2_BUF_FLAG_ERROR))
1399 buf->reserved |= __get_frame_exp_id(pipe, buf) << 16;
1400 buf->reserved2 = pipe->frame_config_id[buf->index];
1403 "dqbuf buffer %d (%s) for asd%d with exp_id %d, isp_config_id %d\n",
1404 buf->index, vdev->name, asd->index, buf->reserved >> 16,
1409 enum ia_css_pipe_id atomisp_get_css_pipe_id(struct atomisp_sub_device *asd)
1411 if (ATOMISP_USE_YUVPP(asd))
1412 return IA_CSS_PIPE_ID_YUVPP;
1414 if (asd->continuous_mode->val) {
1415 if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO)
1416 return IA_CSS_PIPE_ID_VIDEO;
1418 return IA_CSS_PIPE_ID_PREVIEW;
1422 * Disable vf_pp and run CSS in video mode. This allows using ISP
1423 * scaling but it has one frame delay due to CSS internal buffering.
1425 if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_SCALER)
1426 return IA_CSS_PIPE_ID_VIDEO;
1429 * Disable vf_pp and run CSS in still capture mode. In this mode
1430 * CSS does not cause extra latency with buffering, but scaling
1433 if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_LOWLAT)
1434 return IA_CSS_PIPE_ID_CAPTURE;
1436 switch (asd->run_mode->val) {
1437 case ATOMISP_RUN_MODE_PREVIEW:
1438 return IA_CSS_PIPE_ID_PREVIEW;
1439 case ATOMISP_RUN_MODE_VIDEO:
1440 return IA_CSS_PIPE_ID_VIDEO;
1441 case ATOMISP_RUN_MODE_STILL_CAPTURE:
1443 return IA_CSS_PIPE_ID_CAPTURE;
1447 static unsigned int atomisp_sensor_start_stream(struct atomisp_sub_device *asd)
1449 struct atomisp_device *isp = asd->isp;
1451 if (isp->inputs[asd->input_curr].camera_caps->
1452 sensor[asd->sensor_curr].stream_num > 1) {
1453 if (asd->high_speed_mode)
1459 if (asd->vfpp->val != ATOMISP_VFPP_ENABLE ||
1463 if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO ||
1464 (asd->run_mode->val == ATOMISP_RUN_MODE_STILL_CAPTURE &&
1465 !atomisp_is_mbuscode_raw(
1467 asd->capture_pad].fmt.code) &&
1468 !asd->continuous_mode->val))
1474 int atomisp_stream_on_master_slave_sensor(struct atomisp_device *isp,
1477 unsigned int master = -1, slave = -1, delay_slave = 0;
1481 * ISP only support 2 streams now so ignore multiple master/slave
1482 * case to reduce the delay between 2 stream_on calls.
1484 for (i = 0; i < isp->num_of_streams; i++) {
1485 int sensor_index = isp->asd[i].input_curr;
1487 if (isp->inputs[sensor_index].camera_caps->
1488 sensor[isp->asd[i].sensor_curr].is_slave)
1489 slave = sensor_index;
1491 master = sensor_index;
1494 if (master == -1 || slave == -1) {
1495 master = ATOMISP_DEPTH_DEFAULT_MASTER_SENSOR;
1496 slave = ATOMISP_DEPTH_DEFAULT_SLAVE_SENSOR;
1498 "depth mode use default master=%s.slave=%s.\n",
1499 isp->inputs[master].camera->name,
1500 isp->inputs[slave].camera->name);
1503 ret = v4l2_subdev_call(isp->inputs[master].camera, core,
1504 ioctl, ATOMISP_IOC_G_DEPTH_SYNC_COMP,
1508 "get depth sensor %s compensation delay failed.\n",
1509 isp->inputs[master].camera->name);
1511 ret = v4l2_subdev_call(isp->inputs[master].camera,
1512 video, s_stream, 1);
1514 dev_err(isp->dev, "depth mode master sensor %s stream-on failed.\n",
1515 isp->inputs[master].camera->name);
1519 if (delay_slave != 0)
1520 udelay(delay_slave);
1522 ret = v4l2_subdev_call(isp->inputs[slave].camera,
1523 video, s_stream, 1);
1525 dev_err(isp->dev, "depth mode slave sensor %s stream-on failed.\n",
1526 isp->inputs[slave].camera->name);
1527 v4l2_subdev_call(isp->inputs[master].camera, video, s_stream, 0);
1535 static void atomisp_pause_buffer_event(struct atomisp_device *isp)
1537 struct v4l2_event event = {0};
1540 event.type = V4L2_EVENT_ATOMISP_PAUSE_BUFFER;
1542 for (i = 0; i < isp->num_of_streams; i++) {
1543 int sensor_index = isp->asd[i].input_curr;
1545 if (isp->inputs[sensor_index].camera_caps->
1546 sensor[isp->asd[i].sensor_curr].is_slave) {
1547 v4l2_event_queue(isp->asd[i].subdev.devnode, &event);
1553 /* Input system HW workaround */
1554 /* Input system address translation corrupts burst during */
1555 /* invalidate. SW workaround for this is to set burst length */
1556 /* manually to 128 in case of 13MPx snapshot and to 1 otherwise. */
1557 static void atomisp_dma_burst_len_cfg(struct atomisp_sub_device *asd)
1559 struct v4l2_mbus_framefmt *sink;
1561 sink = atomisp_subdev_get_ffmt(&asd->subdev, NULL,
1562 V4L2_SUBDEV_FORMAT_ACTIVE,
1563 ATOMISP_SUBDEV_PAD_SINK);
1565 if (sink->width * sink->height >= 4096 * 3072)
1566 atomisp_css2_hw_store_32(DMA_BURST_SIZE_REG, 0x7F);
1568 atomisp_css2_hw_store_32(DMA_BURST_SIZE_REG, 0x00);
1572 * This ioctl start the capture during streaming I/O.
1574 static int atomisp_streamon(struct file *file, void *fh,
1575 enum v4l2_buf_type type)
1577 struct video_device *vdev = video_devdata(file);
1578 struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev);
1579 struct atomisp_sub_device *asd = pipe->asd;
1580 struct atomisp_device *isp = video_get_drvdata(vdev);
1581 struct pci_dev *pdev = to_pci_dev(isp->dev);
1582 enum ia_css_pipe_id css_pipe_id;
1583 unsigned int sensor_start_stream;
1584 unsigned long irqflags;
1587 dev_dbg(isp->dev, "Start stream on pad %d for asd%d\n",
1588 atomisp_subdev_source_pad(vdev), asd->index);
1590 if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
1591 dev_dbg(isp->dev, "unsupported v4l2 buf type\n");
1595 ret = atomisp_pipe_check(pipe, false);
1599 if (pipe->capq.streaming)
1602 /* Input system HW workaround */
1603 atomisp_dma_burst_len_cfg(asd);
1606 * The number of streaming video nodes is based on which
1607 * binary is going to be run.
1609 sensor_start_stream = atomisp_sensor_start_stream(asd);
1611 spin_lock_irqsave(&pipe->irq_lock, irqflags);
1612 if (list_empty(&pipe->capq.stream)) {
1613 spin_unlock_irqrestore(&pipe->irq_lock, irqflags);
1614 dev_dbg(isp->dev, "no buffer in the queue\n");
1617 spin_unlock_irqrestore(&pipe->irq_lock, irqflags);
1619 ret = videobuf_streamon(&pipe->capq);
1623 /* Reset pending capture request count. */
1624 asd->pending_capture_request = 0;
1626 if ((atomisp_subdev_streaming_count(asd) > sensor_start_stream) &&
1627 (!isp->inputs[asd->input_curr].camera_caps->multi_stream_ctrl)) {
1628 /* trigger still capture */
1629 if (asd->continuous_mode->val &&
1630 atomisp_subdev_source_pad(vdev)
1631 == ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE) {
1632 if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO)
1633 dev_dbg(isp->dev, "SDV last video raw buffer id: %u\n",
1634 asd->latest_preview_exp_id);
1636 dev_dbg(isp->dev, "ZSL last preview raw buffer id: %u\n",
1637 asd->latest_preview_exp_id);
1639 if (asd->delayed_init == ATOMISP_DELAYED_INIT_QUEUED) {
1640 flush_work(&asd->delayed_init_work);
1641 mutex_unlock(&isp->mutex);
1642 ret = wait_for_completion_interruptible(&asd->init_done);
1643 mutex_lock(&isp->mutex);
1645 return -ERESTARTSYS;
1648 /* handle per_frame_setting parameter and buffers */
1649 atomisp_handle_parameter_and_buffer(pipe);
1652 * only ZSL/SDV capture request will be here, raise
1653 * the ISP freq to the highest possible to minimize
1656 atomisp_freq_scaling(isp, ATOMISP_DFS_MODE_MAX, false);
1658 * When asd->enable_raw_buffer_lock->val is true,
1659 * An extra IOCTL is needed to call
1660 * atomisp_css_exp_id_capture and trigger real capture
1662 if (!asd->enable_raw_buffer_lock->val) {
1663 ret = atomisp_css_offline_capture_configure(asd,
1664 asd->params.offline_parm.num_captures,
1665 asd->params.offline_parm.skip_frames,
1666 asd->params.offline_parm.offset);
1670 if (asd->depth_mode->val)
1671 atomisp_pause_buffer_event(isp);
1674 atomisp_qbuffers_to_css(asd);
1678 if (asd->streaming == ATOMISP_DEVICE_STREAMING_ENABLED) {
1679 atomisp_qbuffers_to_css(asd);
1683 css_pipe_id = atomisp_get_css_pipe_id(asd);
1685 /* Invalidate caches. FIXME: should flush only necessary buffers */
1688 if (asd->params.css_update_params_needed) {
1689 atomisp_apply_css_parameters(asd, &asd->params.css_param);
1690 if (asd->params.css_param.update_flag.dz_config)
1691 asd->params.config.dz_config = &asd->params.css_param.dz_config;
1692 atomisp_css_update_isp_params(asd);
1693 asd->params.css_update_params_needed = false;
1694 memset(&asd->params.css_param.update_flag, 0,
1695 sizeof(struct atomisp_parameters));
1697 asd->params.dvs_6axis = NULL;
1699 ret = atomisp_css_start(asd, css_pipe_id, false);
1703 spin_lock_irqsave(&isp->lock, irqflags);
1704 asd->streaming = ATOMISP_DEVICE_STREAMING_ENABLED;
1705 spin_unlock_irqrestore(&isp->lock, irqflags);
1706 atomic_set(&asd->sof_count, -1);
1707 atomic_set(&asd->sequence, -1);
1708 atomic_set(&asd->sequence_temp, -1);
1710 asd->params.dis_proj_data_valid = false;
1711 asd->latest_preview_exp_id = 0;
1712 asd->postview_exp_id = 1;
1713 asd->preview_exp_id = 1;
1715 /* handle per_frame_setting parameter and buffers */
1716 atomisp_handle_parameter_and_buffer(pipe);
1718 atomisp_qbuffers_to_css(asd);
1720 /* Only start sensor when the last streaming instance started */
1721 if (atomisp_subdev_streaming_count(asd) < sensor_start_stream)
1726 asd->params.num_flash_frames = 0;
1727 asd->params.flash_state = ATOMISP_FLASH_IDLE;
1728 atomisp_setup_flash(asd);
1731 atomisp_css_irq_enable(isp, IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF,
1732 atomisp_css_valid_sof(isp));
1733 atomisp_csi2_configure(asd);
1735 * set freq to max when streaming count > 1 which indicate
1736 * dual camera would run
1738 if (atomisp_streaming_count(isp) > 1) {
1739 if (atomisp_freq_scaling(isp,
1740 ATOMISP_DFS_MODE_MAX, false) < 0)
1741 dev_dbg(isp->dev, "DFS max mode failed!\n");
1743 if (atomisp_freq_scaling(isp,
1744 ATOMISP_DFS_MODE_AUTO, false) < 0)
1745 dev_dbg(isp->dev, "DFS auto mode failed!\n");
1748 if (asd->depth_mode->val && atomisp_streaming_count(isp) ==
1749 ATOMISP_DEPTH_SENSOR_STREAMON_COUNT) {
1750 ret = atomisp_stream_on_master_slave_sensor(isp, false);
1752 dev_err(isp->dev, "master slave sensor stream on failed!\n");
1755 goto start_delay_wq;
1756 } else if (asd->depth_mode->val && (atomisp_streaming_count(isp) <
1757 ATOMISP_DEPTH_SENSOR_STREAMON_COUNT)) {
1758 goto start_delay_wq;
1761 /* Enable the CSI interface on ANN B0/K0 */
1762 if (isp->media_dev.hw_revision >= ((ATOMISP_HW_REVISION_ISP2401 <<
1763 ATOMISP_HW_REVISION_SHIFT) | ATOMISP_HW_STEPPING_B0)) {
1764 pci_write_config_word(pdev, MRFLD_PCI_CSI_CONTROL,
1765 isp->saved_regs.csi_control | MRFLD_PCI_CSI_CONTROL_CSI_READY);
1768 /* stream on the sensor */
1769 ret = v4l2_subdev_call(isp->inputs[asd->input_curr].camera,
1770 video, s_stream, 1);
1772 spin_lock_irqsave(&isp->lock, irqflags);
1773 asd->streaming = ATOMISP_DEVICE_STREAMING_DISABLED;
1774 spin_unlock_irqrestore(&isp->lock, irqflags);
1779 if (asd->continuous_mode->val) {
1780 struct v4l2_mbus_framefmt *sink;
1782 sink = atomisp_subdev_get_ffmt(&asd->subdev, NULL,
1783 V4L2_SUBDEV_FORMAT_ACTIVE,
1784 ATOMISP_SUBDEV_PAD_SINK);
1786 reinit_completion(&asd->init_done);
1787 asd->delayed_init = ATOMISP_DELAYED_INIT_QUEUED;
1788 queue_work(asd->delayed_init_workq, &asd->delayed_init_work);
1790 asd->delayed_init = ATOMISP_DELAYED_INIT_NOT_QUEUED;
1796 int __atomisp_streamoff(struct file *file, void *fh, enum v4l2_buf_type type)
1798 struct video_device *vdev = video_devdata(file);
1799 struct atomisp_device *isp = video_get_drvdata(vdev);
1800 struct pci_dev *pdev = to_pci_dev(isp->dev);
1801 struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev);
1802 struct atomisp_sub_device *asd = pipe->asd;
1803 struct atomisp_video_pipe *capture_pipe = NULL;
1804 struct atomisp_video_pipe *vf_pipe = NULL;
1805 struct atomisp_video_pipe *preview_pipe = NULL;
1806 struct atomisp_video_pipe *video_pipe = NULL;
1807 struct videobuf_buffer *vb, *_vb;
1808 enum ia_css_pipe_id css_pipe_id;
1810 unsigned long flags;
1811 bool first_streamoff = false;
1813 dev_dbg(isp->dev, "Stop stream on pad %d for asd%d\n",
1814 atomisp_subdev_source_pad(vdev), asd->index);
1816 lockdep_assert_held(&isp->mutex);
1818 if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
1819 dev_dbg(isp->dev, "unsupported v4l2 buf type\n");
1824 * do only videobuf_streamoff for capture & vf pipes in
1825 * case of continuous capture
1827 if ((asd->continuous_mode->val ||
1828 isp->inputs[asd->input_curr].camera_caps->multi_stream_ctrl) &&
1829 atomisp_subdev_source_pad(vdev) !=
1830 ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW &&
1831 atomisp_subdev_source_pad(vdev) !=
1832 ATOMISP_SUBDEV_PAD_SOURCE_VIDEO) {
1833 if (isp->inputs[asd->input_curr].camera_caps->multi_stream_ctrl) {
1834 v4l2_subdev_call(isp->inputs[asd->input_curr].camera,
1835 video, s_stream, 0);
1836 } else if (atomisp_subdev_source_pad(vdev)
1837 == ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE) {
1838 /* stop continuous still capture if needed */
1839 if (asd->params.offline_parm.num_captures == -1)
1840 atomisp_css_offline_capture_configure(asd,
1842 atomisp_freq_scaling(isp, ATOMISP_DFS_MODE_AUTO, false);
1845 * Currently there is no way to flush buffers queued to css.
1846 * When doing videobuf_streamoff, active buffers will be
1847 * marked as VIDEOBUF_NEEDS_INIT. HAL will be able to use
1848 * these buffers again, and these buffers might be queued to
1849 * css more than once! Warn here, if HAL has not dequeued all
1850 * buffers back before calling streamoff.
1852 if (pipe->buffers_in_css != 0) {
1853 WARN(1, "%s: buffers of vdev %s still in CSS!\n",
1854 __func__, pipe->vdev.name);
1857 * Buffers remained in css maybe dequeued out in the
1858 * next stream on, while this will causes serious
1859 * issues as buffers already get invalid after
1860 * previous stream off.
1862 * No way to flush buffers but to reset the whole css
1864 dev_warn(isp->dev, "Reset CSS to clean up css buffers.\n");
1865 atomisp_css_flush(isp);
1868 return videobuf_streamoff(&pipe->capq);
1871 if (!pipe->capq.streaming)
1874 if (asd->streaming == ATOMISP_DEVICE_STREAMING_ENABLED)
1875 first_streamoff = true;
1877 spin_lock_irqsave(&isp->lock, flags);
1878 if (atomisp_subdev_streaming_count(asd) == 1)
1879 asd->streaming = ATOMISP_DEVICE_STREAMING_DISABLED;
1881 asd->streaming = ATOMISP_DEVICE_STREAMING_STOPPING;
1882 spin_unlock_irqrestore(&isp->lock, flags);
1884 if (!first_streamoff) {
1885 ret = videobuf_streamoff(&pipe->capq);
1891 atomisp_clear_css_buffer_counters(asd);
1892 atomisp_css_irq_enable(isp, IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF, false);
1894 if (asd->delayed_init == ATOMISP_DELAYED_INIT_QUEUED) {
1895 cancel_work_sync(&asd->delayed_init_work);
1896 asd->delayed_init = ATOMISP_DELAYED_INIT_NOT_QUEUED;
1898 if (first_streamoff) {
1899 css_pipe_id = atomisp_get_css_pipe_id(asd);
1900 atomisp_css_stop(asd, css_pipe_id, false);
1902 /* cancel work queue*/
1903 if (asd->video_out_capture.users) {
1904 capture_pipe = &asd->video_out_capture;
1905 wake_up_interruptible(&capture_pipe->capq.wait);
1907 if (asd->video_out_vf.users) {
1908 vf_pipe = &asd->video_out_vf;
1909 wake_up_interruptible(&vf_pipe->capq.wait);
1911 if (asd->video_out_preview.users) {
1912 preview_pipe = &asd->video_out_preview;
1913 wake_up_interruptible(&preview_pipe->capq.wait);
1915 if (asd->video_out_video_capture.users) {
1916 video_pipe = &asd->video_out_video_capture;
1917 wake_up_interruptible(&video_pipe->capq.wait);
1919 ret = videobuf_streamoff(&pipe->capq);
1923 /* cleanup css here */
1924 /* no need for this, as ISP will be reset anyway */
1925 /*atomisp_flush_bufs_in_css(isp);*/
1927 spin_lock_irqsave(&pipe->irq_lock, flags);
1928 list_for_each_entry_safe(vb, _vb, &pipe->activeq, queue) {
1929 vb->state = VIDEOBUF_PREPARED;
1930 list_del(&vb->queue);
1932 list_for_each_entry_safe(vb, _vb, &pipe->buffers_waiting_for_param, queue) {
1933 vb->state = VIDEOBUF_PREPARED;
1934 list_del(&vb->queue);
1935 pipe->frame_request_config_id[vb->i] = 0;
1937 spin_unlock_irqrestore(&pipe->irq_lock, flags);
1939 atomisp_subdev_cleanup_pending_events(asd);
1941 if (atomisp_subdev_streaming_count(asd) + 1
1942 != atomisp_sensor_start_stream(asd))
1945 ret = v4l2_subdev_call(isp->inputs[asd->input_curr].camera,
1946 video, s_stream, 0);
1949 asd->params.num_flash_frames = 0;
1950 asd->params.flash_state = ATOMISP_FLASH_IDLE;
1953 /* if other streams are running, isp should not be powered off */
1954 if (atomisp_streaming_count(isp)) {
1955 atomisp_css_flush(isp);
1959 /* Disable the CSI interface on ANN B0/K0 */
1960 if (isp->media_dev.hw_revision >= ((ATOMISP_HW_REVISION_ISP2401 <<
1961 ATOMISP_HW_REVISION_SHIFT) | ATOMISP_HW_STEPPING_B0)) {
1962 pci_write_config_word(pdev, MRFLD_PCI_CSI_CONTROL,
1963 isp->saved_regs.csi_control & ~MRFLD_PCI_CSI_CONTROL_CSI_READY);
1966 if (atomisp_freq_scaling(isp, ATOMISP_DFS_MODE_LOW, false))
1967 dev_warn(isp->dev, "DFS failed.\n");
1969 * ISP work around, need to reset isp
1970 * Is it correct time to reset ISP when first node does streamoff?
1972 if (isp->sw_contex.power_state == ATOM_ISP_POWER_UP) {
1974 bool recreate_streams[MAX_STREAM_NUM] = {0};
1976 if (isp->isp_timeout)
1977 dev_err(isp->dev, "%s: Resetting with WA activated",
1980 * It is possible that the other asd stream is in the stage
1981 * that v4l2_setfmt is just get called on it, which will
1982 * create css stream on that stream. But at this point, there
1983 * is no way to destroy the css stream created on that stream.
1985 * So force stream destroy here.
1987 for (i = 0; i < isp->num_of_streams; i++) {
1988 if (isp->asd[i].stream_prepared) {
1989 atomisp_destroy_pipes_stream_force(&isp->
1991 recreate_streams[i] = true;
1995 /* disable PUNIT/ISP acknowlede/handshake - SRSE=3 */
1996 pci_write_config_dword(pdev, PCI_I_CONTROL,
1997 isp->saved_regs.i_control | MRFLD_PCI_I_CONTROL_SRSE_RESET_MASK);
1998 dev_err(isp->dev, "atomisp_reset");
2000 for (i = 0; i < isp->num_of_streams; i++) {
2001 if (recreate_streams[i]) {
2004 ret2 = atomisp_create_pipes_stream(&isp->asd[i]);
2006 dev_err(isp->dev, "%s error re-creating streams: %d\n",
2013 isp->isp_timeout = false;
2018 static int atomisp_streamoff(struct file *file, void *fh,
2019 enum v4l2_buf_type type)
2021 return __atomisp_streamoff(file, fh, type);
2025 * To get the current value of a control.
2026 * applications initialize the id field of a struct v4l2_control and
2027 * call this ioctl with a pointer to this structure
2029 static int atomisp_g_ctrl(struct file *file, void *fh,
2030 struct v4l2_control *control)
2032 struct video_device *vdev = video_devdata(file);
2033 struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd;
2034 struct atomisp_device *isp = video_get_drvdata(vdev);
2035 int i, ret = -EINVAL;
2037 for (i = 0; i < ctrls_num; i++) {
2038 if (ci_v4l2_controls[i].id == control->id) {
2047 switch (control->id) {
2048 case V4L2_CID_IRIS_ABSOLUTE:
2049 case V4L2_CID_EXPOSURE_ABSOLUTE:
2050 case V4L2_CID_FNUMBER_ABSOLUTE:
2051 case V4L2_CID_2A_STATUS:
2052 case V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE:
2053 case V4L2_CID_EXPOSURE:
2054 case V4L2_CID_EXPOSURE_AUTO:
2055 case V4L2_CID_SCENE_MODE:
2056 case V4L2_CID_ISO_SENSITIVITY:
2057 case V4L2_CID_ISO_SENSITIVITY_AUTO:
2058 case V4L2_CID_CONTRAST:
2059 case V4L2_CID_SATURATION:
2060 case V4L2_CID_SHARPNESS:
2061 case V4L2_CID_3A_LOCK:
2062 case V4L2_CID_EXPOSURE_ZONE_NUM:
2063 case V4L2_CID_TEST_PATTERN:
2064 case V4L2_CID_TEST_PATTERN_COLOR_R:
2065 case V4L2_CID_TEST_PATTERN_COLOR_GR:
2066 case V4L2_CID_TEST_PATTERN_COLOR_GB:
2067 case V4L2_CID_TEST_PATTERN_COLOR_B:
2068 return v4l2_g_ctrl(isp->inputs[asd->input_curr].camera->
2069 ctrl_handler, control);
2070 case V4L2_CID_COLORFX:
2071 ret = atomisp_color_effect(asd, 0, &control->value);
2073 case V4L2_CID_ATOMISP_BAD_PIXEL_DETECTION:
2074 ret = atomisp_bad_pixel(asd, 0, &control->value);
2076 case V4L2_CID_ATOMISP_POSTPROCESS_GDC_CAC:
2077 ret = atomisp_gdc_cac(asd, 0, &control->value);
2079 case V4L2_CID_ATOMISP_VIDEO_STABLIZATION:
2080 ret = atomisp_video_stable(asd, 0, &control->value);
2082 case V4L2_CID_ATOMISP_FIXED_PATTERN_NR:
2083 ret = atomisp_fixed_pattern(asd, 0, &control->value);
2085 case V4L2_CID_ATOMISP_FALSE_COLOR_CORRECTION:
2086 ret = atomisp_false_color(asd, 0, &control->value);
2088 case V4L2_CID_ATOMISP_LOW_LIGHT:
2089 ret = atomisp_low_light(asd, 0, &control->value);
2100 * To change the value of a control.
2101 * applications initialize the id and value fields of a struct v4l2_control
2102 * and call this ioctl.
2104 static int atomisp_s_ctrl(struct file *file, void *fh,
2105 struct v4l2_control *control)
2107 struct video_device *vdev = video_devdata(file);
2108 struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd;
2109 struct atomisp_device *isp = video_get_drvdata(vdev);
2110 int i, ret = -EINVAL;
2112 for (i = 0; i < ctrls_num; i++) {
2113 if (ci_v4l2_controls[i].id == control->id) {
2122 switch (control->id) {
2123 case V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE:
2124 case V4L2_CID_EXPOSURE:
2125 case V4L2_CID_EXPOSURE_AUTO:
2126 case V4L2_CID_EXPOSURE_AUTO_PRIORITY:
2127 case V4L2_CID_SCENE_MODE:
2128 case V4L2_CID_ISO_SENSITIVITY:
2129 case V4L2_CID_ISO_SENSITIVITY_AUTO:
2130 case V4L2_CID_POWER_LINE_FREQUENCY:
2131 case V4L2_CID_EXPOSURE_METERING:
2132 case V4L2_CID_CONTRAST:
2133 case V4L2_CID_SATURATION:
2134 case V4L2_CID_SHARPNESS:
2135 case V4L2_CID_3A_LOCK:
2136 case V4L2_CID_COLORFX_CBCR:
2137 case V4L2_CID_TEST_PATTERN:
2138 case V4L2_CID_TEST_PATTERN_COLOR_R:
2139 case V4L2_CID_TEST_PATTERN_COLOR_GR:
2140 case V4L2_CID_TEST_PATTERN_COLOR_GB:
2141 case V4L2_CID_TEST_PATTERN_COLOR_B:
2142 return v4l2_s_ctrl(NULL,
2143 isp->inputs[asd->input_curr].camera->
2144 ctrl_handler, control);
2145 case V4L2_CID_COLORFX:
2146 ret = atomisp_color_effect(asd, 1, &control->value);
2148 case V4L2_CID_ATOMISP_BAD_PIXEL_DETECTION:
2149 ret = atomisp_bad_pixel(asd, 1, &control->value);
2151 case V4L2_CID_ATOMISP_POSTPROCESS_GDC_CAC:
2152 ret = atomisp_gdc_cac(asd, 1, &control->value);
2154 case V4L2_CID_ATOMISP_VIDEO_STABLIZATION:
2155 ret = atomisp_video_stable(asd, 1, &control->value);
2157 case V4L2_CID_ATOMISP_FIXED_PATTERN_NR:
2158 ret = atomisp_fixed_pattern(asd, 1, &control->value);
2160 case V4L2_CID_ATOMISP_FALSE_COLOR_CORRECTION:
2161 ret = atomisp_false_color(asd, 1, &control->value);
2163 case V4L2_CID_REQUEST_FLASH:
2164 ret = atomisp_flash_enable(asd, control->value);
2166 case V4L2_CID_ATOMISP_LOW_LIGHT:
2167 ret = atomisp_low_light(asd, 1, &control->value);
2177 * To query the attributes of a control.
2178 * applications set the id field of a struct v4l2_queryctrl and call the
2179 * this ioctl with a pointer to this structure. The driver fills
2180 * the rest of the structure.
2182 static int atomisp_queryctl(struct file *file, void *fh,
2183 struct v4l2_queryctrl *qc)
2185 int i, ret = -EINVAL;
2186 struct video_device *vdev = video_devdata(file);
2187 struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd;
2188 struct atomisp_device *isp = video_get_drvdata(vdev);
2191 case V4L2_CID_FOCUS_ABSOLUTE:
2192 case V4L2_CID_FOCUS_RELATIVE:
2193 case V4L2_CID_FOCUS_STATUS:
2195 return v4l2_queryctrl(isp->inputs[asd->input_curr].camera->
2200 return v4l2_queryctrl(isp->motor->ctrl_handler, qc);
2202 return v4l2_queryctrl(isp->inputs[asd->input_curr].
2203 camera->ctrl_handler, qc);
2206 if (qc->id & V4L2_CTRL_FLAG_NEXT_CTRL)
2209 for (i = 0; i < ctrls_num; i++) {
2210 if (ci_v4l2_controls[i].id == qc->id) {
2211 memcpy(qc, &ci_v4l2_controls[i],
2212 sizeof(struct v4l2_queryctrl));
2213 qc->reserved[0] = 0;
2219 qc->flags = V4L2_CTRL_FLAG_DISABLED;
2224 static int atomisp_camera_g_ext_ctrls(struct file *file, void *fh,
2225 struct v4l2_ext_controls *c)
2227 struct video_device *vdev = video_devdata(file);
2228 struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd;
2229 struct atomisp_device *isp = video_get_drvdata(vdev);
2230 struct v4l2_subdev *motor;
2231 struct v4l2_control ctrl;
2236 motor = isp->inputs[asd->input_curr].motor;
2240 for (i = 0; i < c->count; i++) {
2241 ctrl.id = c->controls[i].id;
2242 ctrl.value = c->controls[i].value;
2244 case V4L2_CID_EXPOSURE_ABSOLUTE:
2245 case V4L2_CID_EXPOSURE_AUTO:
2246 case V4L2_CID_IRIS_ABSOLUTE:
2247 case V4L2_CID_FNUMBER_ABSOLUTE:
2248 case V4L2_CID_BIN_FACTOR_HORZ:
2249 case V4L2_CID_BIN_FACTOR_VERT:
2250 case V4L2_CID_3A_LOCK:
2251 case V4L2_CID_TEST_PATTERN:
2252 case V4L2_CID_TEST_PATTERN_COLOR_R:
2253 case V4L2_CID_TEST_PATTERN_COLOR_GR:
2254 case V4L2_CID_TEST_PATTERN_COLOR_GB:
2255 case V4L2_CID_TEST_PATTERN_COLOR_B:
2257 * Exposure related control will be handled by sensor
2261 v4l2_g_ctrl(isp->inputs[asd->input_curr].camera->
2262 ctrl_handler, &ctrl);
2264 case V4L2_CID_FOCUS_ABSOLUTE:
2265 case V4L2_CID_FOCUS_RELATIVE:
2266 case V4L2_CID_FOCUS_STATUS:
2267 case V4L2_CID_FOCUS_AUTO:
2269 ret = v4l2_g_ctrl(motor->ctrl_handler, &ctrl);
2271 case V4L2_CID_FLASH_STATUS:
2272 case V4L2_CID_FLASH_INTENSITY:
2273 case V4L2_CID_FLASH_TORCH_INTENSITY:
2274 case V4L2_CID_FLASH_INDICATOR_INTENSITY:
2275 case V4L2_CID_FLASH_TIMEOUT:
2276 case V4L2_CID_FLASH_STROBE:
2277 case V4L2_CID_FLASH_MODE:
2278 case V4L2_CID_FLASH_STATUS_REGISTER:
2281 v4l2_g_ctrl(isp->flash->ctrl_handler,
2284 case V4L2_CID_ZOOM_ABSOLUTE:
2285 ret = atomisp_digital_zoom(asd, 0, &ctrl.value);
2287 case V4L2_CID_G_SKIP_FRAMES:
2288 ret = v4l2_subdev_call(
2289 isp->inputs[asd->input_curr].camera,
2290 sensor, g_skip_frames, (u32 *)&ctrl.value);
2300 c->controls[i].value = ctrl.value;
2305 /* This ioctl allows the application to get multiple controls by class */
2306 static int atomisp_g_ext_ctrls(struct file *file, void *fh,
2307 struct v4l2_ext_controls *c)
2309 struct v4l2_control ctrl;
2313 * input_lock is not need for the Camera related IOCTLs
2314 * The input_lock downgrade the FPS of 3A
2316 ret = atomisp_camera_g_ext_ctrls(file, fh, c);
2320 for (i = 0; i < c->count; i++) {
2321 ctrl.id = c->controls[i].id;
2322 ctrl.value = c->controls[i].value;
2323 ret = atomisp_g_ctrl(file, fh, &ctrl);
2324 c->controls[i].value = ctrl.value;
2333 static int atomisp_camera_s_ext_ctrls(struct file *file, void *fh,
2334 struct v4l2_ext_controls *c)
2336 struct video_device *vdev = video_devdata(file);
2337 struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd;
2338 struct atomisp_device *isp = video_get_drvdata(vdev);
2339 struct v4l2_subdev *motor;
2340 struct v4l2_control ctrl;
2345 motor = isp->inputs[asd->input_curr].motor;
2349 for (i = 0; i < c->count; i++) {
2350 struct v4l2_ctrl *ctr;
2352 ctrl.id = c->controls[i].id;
2353 ctrl.value = c->controls[i].value;
2355 case V4L2_CID_EXPOSURE_ABSOLUTE:
2356 case V4L2_CID_EXPOSURE_AUTO:
2357 case V4L2_CID_EXPOSURE_METERING:
2358 case V4L2_CID_IRIS_ABSOLUTE:
2359 case V4L2_CID_FNUMBER_ABSOLUTE:
2360 case V4L2_CID_VCM_TIMING:
2361 case V4L2_CID_VCM_SLEW:
2362 case V4L2_CID_3A_LOCK:
2363 case V4L2_CID_TEST_PATTERN:
2364 case V4L2_CID_TEST_PATTERN_COLOR_R:
2365 case V4L2_CID_TEST_PATTERN_COLOR_GR:
2366 case V4L2_CID_TEST_PATTERN_COLOR_GB:
2367 case V4L2_CID_TEST_PATTERN_COLOR_B:
2368 ret = v4l2_s_ctrl(NULL,
2369 isp->inputs[asd->input_curr].camera->
2370 ctrl_handler, &ctrl);
2372 case V4L2_CID_FOCUS_ABSOLUTE:
2373 case V4L2_CID_FOCUS_RELATIVE:
2374 case V4L2_CID_FOCUS_STATUS:
2375 case V4L2_CID_FOCUS_AUTO:
2377 ret = v4l2_s_ctrl(NULL, motor->ctrl_handler,
2380 ret = v4l2_s_ctrl(NULL,
2381 isp->inputs[asd->input_curr].
2382 camera->ctrl_handler, &ctrl);
2384 case V4L2_CID_FLASH_STATUS:
2385 case V4L2_CID_FLASH_INTENSITY:
2386 case V4L2_CID_FLASH_TORCH_INTENSITY:
2387 case V4L2_CID_FLASH_INDICATOR_INTENSITY:
2388 case V4L2_CID_FLASH_TIMEOUT:
2389 case V4L2_CID_FLASH_STROBE:
2390 case V4L2_CID_FLASH_MODE:
2391 case V4L2_CID_FLASH_STATUS_REGISTER:
2394 v4l2_s_ctrl(NULL, isp->flash->ctrl_handler,
2397 * When flash mode is changed we need to reset
2400 if (ctrl.id == V4L2_CID_FLASH_MODE) {
2401 asd->params.flash_state =
2403 asd->params.num_flash_frames = 0;
2407 case V4L2_CID_ZOOM_ABSOLUTE:
2408 ret = atomisp_digital_zoom(asd, 1, &ctrl.value);
2411 ctr = v4l2_ctrl_find(&asd->ctrl_handler, ctrl.id);
2413 ret = v4l2_ctrl_s_ctrl(ctr, ctrl.value);
2422 c->controls[i].value = ctrl.value;
2427 /* This ioctl allows the application to set multiple controls by class */
2428 static int atomisp_s_ext_ctrls(struct file *file, void *fh,
2429 struct v4l2_ext_controls *c)
2431 struct v4l2_control ctrl;
2435 * input_lock is not need for the Camera related IOCTLs
2436 * The input_lock downgrade the FPS of 3A
2438 ret = atomisp_camera_s_ext_ctrls(file, fh, c);
2442 for (i = 0; i < c->count; i++) {
2443 ctrl.id = c->controls[i].id;
2444 ctrl.value = c->controls[i].value;
2445 ret = atomisp_s_ctrl(file, fh, &ctrl);
2446 c->controls[i].value = ctrl.value;
2456 * vidioc_g/s_param are used to switch isp running mode
2458 static int atomisp_g_parm(struct file *file, void *fh,
2459 struct v4l2_streamparm *parm)
2461 struct video_device *vdev = video_devdata(file);
2462 struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd;
2463 struct atomisp_device *isp = video_get_drvdata(vdev);
2465 if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
2466 dev_err(isp->dev, "unsupported v4l2 buf type\n");
2470 parm->parm.capture.capturemode = asd->run_mode->val;
2475 static int atomisp_s_parm(struct file *file, void *fh,
2476 struct v4l2_streamparm *parm)
2478 struct video_device *vdev = video_devdata(file);
2479 struct atomisp_device *isp = video_get_drvdata(vdev);
2480 struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd;
2485 if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
2486 dev_err(isp->dev, "unsupported v4l2 buf type\n");
2490 asd->high_speed_mode = false;
2491 switch (parm->parm.capture.capturemode) {
2492 case CI_MODE_NONE: {
2493 struct v4l2_subdev_frame_interval fi = {0};
2495 fi.interval = parm->parm.capture.timeperframe;
2497 rval = v4l2_subdev_call(isp->inputs[asd->input_curr].camera,
2498 video, s_frame_interval, &fi);
2500 parm->parm.capture.timeperframe = fi.interval;
2502 if (fi.interval.numerator != 0) {
2503 fps = fi.interval.denominator / fi.interval.numerator;
2505 asd->high_speed_mode = true;
2508 return rval == -ENOIOCTLCMD ? 0 : rval;
2511 mode = ATOMISP_RUN_MODE_VIDEO;
2513 case CI_MODE_STILL_CAPTURE:
2514 mode = ATOMISP_RUN_MODE_STILL_CAPTURE;
2516 case CI_MODE_CONTINUOUS:
2517 mode = ATOMISP_RUN_MODE_CONTINUOUS_CAPTURE;
2519 case CI_MODE_PREVIEW:
2520 mode = ATOMISP_RUN_MODE_PREVIEW;
2526 rval = v4l2_ctrl_s_ctrl(asd->run_mode, mode);
2528 return rval == -ENOIOCTLCMD ? 0 : rval;
2531 static long atomisp_vidioc_default(struct file *file, void *fh,
2532 bool valid_prio, unsigned int cmd, void *arg)
2534 struct video_device *vdev = video_devdata(file);
2535 struct atomisp_device *isp = video_get_drvdata(vdev);
2536 struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd;
2537 struct v4l2_subdev *motor;
2541 motor = isp->inputs[asd->input_curr].motor;
2546 case ATOMISP_IOC_S_SENSOR_RUNMODE:
2548 err = atomisp_set_sensor_runmode(asd, arg);
2553 case ATOMISP_IOC_G_XNR:
2554 err = atomisp_xnr(asd, 0, arg);
2557 case ATOMISP_IOC_S_XNR:
2558 err = atomisp_xnr(asd, 1, arg);
2561 case ATOMISP_IOC_G_NR:
2562 err = atomisp_nr(asd, 0, arg);
2565 case ATOMISP_IOC_S_NR:
2566 err = atomisp_nr(asd, 1, arg);
2569 case ATOMISP_IOC_G_TNR:
2570 err = atomisp_tnr(asd, 0, arg);
2573 case ATOMISP_IOC_S_TNR:
2574 err = atomisp_tnr(asd, 1, arg);
2577 case ATOMISP_IOC_G_BLACK_LEVEL_COMP:
2578 err = atomisp_black_level(asd, 0, arg);
2581 case ATOMISP_IOC_S_BLACK_LEVEL_COMP:
2582 err = atomisp_black_level(asd, 1, arg);
2585 case ATOMISP_IOC_G_EE:
2586 err = atomisp_ee(asd, 0, arg);
2589 case ATOMISP_IOC_S_EE:
2590 err = atomisp_ee(asd, 1, arg);
2593 case ATOMISP_IOC_G_DIS_STAT:
2594 err = atomisp_get_dis_stat(asd, arg);
2597 case ATOMISP_IOC_G_DVS2_BQ_RESOLUTIONS:
2598 err = atomisp_get_dvs2_bq_resolutions(asd, arg);
2601 case ATOMISP_IOC_S_DIS_COEFS:
2602 err = atomisp_css_cp_dvs2_coefs(asd, arg,
2603 &asd->params.css_param, true);
2605 asd->params.css_update_params_needed = true;
2608 case ATOMISP_IOC_S_DIS_VECTOR:
2609 err = atomisp_cp_dvs_6axis_config(asd, arg,
2610 &asd->params.css_param, true);
2612 asd->params.css_update_params_needed = true;
2615 case ATOMISP_IOC_G_ISP_PARM:
2616 err = atomisp_param(asd, 0, arg);
2619 case ATOMISP_IOC_S_ISP_PARM:
2620 err = atomisp_param(asd, 1, arg);
2623 case ATOMISP_IOC_G_3A_STAT:
2624 err = atomisp_3a_stat(asd, 0, arg);
2627 case ATOMISP_IOC_G_ISP_GAMMA:
2628 err = atomisp_gamma(asd, 0, arg);
2631 case ATOMISP_IOC_S_ISP_GAMMA:
2632 err = atomisp_gamma(asd, 1, arg);
2635 case ATOMISP_IOC_G_ISP_GDC_TAB:
2636 err = atomisp_gdc_cac_table(asd, 0, arg);
2639 case ATOMISP_IOC_S_ISP_GDC_TAB:
2640 err = atomisp_gdc_cac_table(asd, 1, arg);
2643 case ATOMISP_IOC_G_ISP_MACC:
2644 err = atomisp_macc_table(asd, 0, arg);
2647 case ATOMISP_IOC_S_ISP_MACC:
2648 err = atomisp_macc_table(asd, 1, arg);
2651 case ATOMISP_IOC_G_ISP_BAD_PIXEL_DETECTION:
2652 err = atomisp_bad_pixel_param(asd, 0, arg);
2655 case ATOMISP_IOC_S_ISP_BAD_PIXEL_DETECTION:
2656 err = atomisp_bad_pixel_param(asd, 1, arg);
2659 case ATOMISP_IOC_G_ISP_FALSE_COLOR_CORRECTION:
2660 err = atomisp_false_color_param(asd, 0, arg);
2663 case ATOMISP_IOC_S_ISP_FALSE_COLOR_CORRECTION:
2664 err = atomisp_false_color_param(asd, 1, arg);
2667 case ATOMISP_IOC_G_ISP_CTC:
2668 err = atomisp_ctc(asd, 0, arg);
2671 case ATOMISP_IOC_S_ISP_CTC:
2672 err = atomisp_ctc(asd, 1, arg);
2675 case ATOMISP_IOC_G_ISP_WHITE_BALANCE:
2676 err = atomisp_white_balance_param(asd, 0, arg);
2679 case ATOMISP_IOC_S_ISP_WHITE_BALANCE:
2680 err = atomisp_white_balance_param(asd, 1, arg);
2683 case ATOMISP_IOC_G_3A_CONFIG:
2684 err = atomisp_3a_config_param(asd, 0, arg);
2687 case ATOMISP_IOC_S_3A_CONFIG:
2688 err = atomisp_3a_config_param(asd, 1, arg);
2691 case ATOMISP_IOC_S_ISP_FPN_TABLE:
2692 err = atomisp_fixed_pattern_table(asd, arg);
2695 case ATOMISP_IOC_ISP_MAKERNOTE:
2696 err = atomisp_exif_makernote(asd, arg);
2699 case ATOMISP_IOC_G_SENSOR_MODE_DATA:
2700 err = atomisp_get_sensor_mode_data(asd, arg);
2703 case ATOMISP_IOC_G_MOTOR_PRIV_INT_DATA:
2705 err = v4l2_subdev_call(motor, core, ioctl, cmd, arg);
2707 err = v4l2_subdev_call(isp->inputs[asd->input_curr].camera,
2708 core, ioctl, cmd, arg);
2711 case ATOMISP_IOC_S_EXPOSURE:
2712 case ATOMISP_IOC_G_SENSOR_CALIBRATION_GROUP:
2713 case ATOMISP_IOC_G_SENSOR_PRIV_INT_DATA:
2714 case ATOMISP_IOC_G_SENSOR_AE_BRACKETING_INFO:
2715 case ATOMISP_IOC_S_SENSOR_AE_BRACKETING_MODE:
2716 case ATOMISP_IOC_G_SENSOR_AE_BRACKETING_MODE:
2717 case ATOMISP_IOC_S_SENSOR_AE_BRACKETING_LUT:
2718 err = v4l2_subdev_call(isp->inputs[asd->input_curr].camera,
2719 core, ioctl, cmd, arg);
2721 case ATOMISP_IOC_G_UPDATE_EXPOSURE:
2723 err = v4l2_subdev_call(isp->inputs[asd->input_curr].camera,
2724 core, ioctl, cmd, arg);
2729 case ATOMISP_IOC_S_ISP_SHD_TAB:
2730 err = atomisp_set_shading_table(asd, arg);
2733 case ATOMISP_IOC_G_ISP_GAMMA_CORRECTION:
2734 err = atomisp_gamma_correction(asd, 0, arg);
2737 case ATOMISP_IOC_S_ISP_GAMMA_CORRECTION:
2738 err = atomisp_gamma_correction(asd, 1, arg);
2741 case ATOMISP_IOC_S_PARAMETERS:
2742 err = atomisp_set_parameters(vdev, arg);
2745 case ATOMISP_IOC_S_CONT_CAPTURE_CONFIG:
2746 err = atomisp_offline_capture_configure(asd, arg);
2748 case ATOMISP_IOC_G_METADATA:
2749 err = atomisp_get_metadata(asd, 0, arg);
2751 case ATOMISP_IOC_G_METADATA_BY_TYPE:
2752 err = atomisp_get_metadata_by_type(asd, 0, arg);
2754 case ATOMISP_IOC_EXT_ISP_CTRL:
2755 err = v4l2_subdev_call(isp->inputs[asd->input_curr].camera,
2756 core, ioctl, cmd, arg);
2758 case ATOMISP_IOC_EXP_ID_UNLOCK:
2759 err = atomisp_exp_id_unlock(asd, arg);
2761 case ATOMISP_IOC_EXP_ID_CAPTURE:
2762 err = atomisp_exp_id_capture(asd, arg);
2764 case ATOMISP_IOC_S_ENABLE_DZ_CAPT_PIPE:
2765 err = atomisp_enable_dz_capt_pipe(asd, arg);
2767 case ATOMISP_IOC_G_FORMATS_CONFIG:
2768 err = atomisp_formats(asd, 0, arg);
2771 case ATOMISP_IOC_S_FORMATS_CONFIG:
2772 err = atomisp_formats(asd, 1, arg);
2774 case ATOMISP_IOC_S_EXPOSURE_WINDOW:
2775 err = atomisp_s_ae_window(asd, arg);
2777 case ATOMISP_IOC_INJECT_A_FAKE_EVENT:
2778 err = atomisp_inject_a_fake_event(asd, arg);
2780 case ATOMISP_IOC_G_INVALID_FRAME_NUM:
2781 err = atomisp_get_invalid_frame_num(vdev, arg);
2783 case ATOMISP_IOC_S_ARRAY_RESOLUTION:
2784 err = atomisp_set_array_res(asd, arg);
2794 const struct v4l2_ioctl_ops atomisp_ioctl_ops = {
2795 .vidioc_querycap = atomisp_querycap,
2796 .vidioc_enum_input = atomisp_enum_input,
2797 .vidioc_g_input = atomisp_g_input,
2798 .vidioc_s_input = atomisp_s_input,
2799 .vidioc_queryctrl = atomisp_queryctl,
2800 .vidioc_s_ctrl = atomisp_s_ctrl,
2801 .vidioc_g_ctrl = atomisp_g_ctrl,
2802 .vidioc_s_ext_ctrls = atomisp_s_ext_ctrls,
2803 .vidioc_g_ext_ctrls = atomisp_g_ext_ctrls,
2804 .vidioc_enum_framesizes = atomisp_enum_framesizes,
2805 .vidioc_enum_frameintervals = atomisp_enum_frameintervals,
2806 .vidioc_enum_fmt_vid_cap = atomisp_enum_fmt_cap,
2807 .vidioc_try_fmt_vid_cap = atomisp_try_fmt_cap,
2808 .vidioc_g_fmt_vid_cap = atomisp_g_fmt_cap,
2809 .vidioc_s_fmt_vid_cap = atomisp_s_fmt_cap,
2810 .vidioc_reqbufs = atomisp_reqbufs,
2811 .vidioc_querybuf = atomisp_querybuf,
2812 .vidioc_qbuf = atomisp_qbuf,
2813 .vidioc_dqbuf = atomisp_dqbuf,
2814 .vidioc_streamon = atomisp_streamon,
2815 .vidioc_streamoff = atomisp_streamoff,
2816 .vidioc_default = atomisp_vidioc_default,
2817 .vidioc_s_parm = atomisp_s_parm,
2818 .vidioc_g_parm = atomisp_g_parm,