1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Support for Medifield PNW Camera Imaging ISP subsystem. 4 * 5 * Copyright (c) 2010 Intel Corporation. All Rights Reserved. 6 * 7 * Copyright (c) 2010 Silicon Hive www.siliconhive.com. 8 * 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. 12 * 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. 17 * 18 * 19 */ 20 21 #include <linux/delay.h> 22 #include <linux/pci.h> 23 24 #include <media/v4l2-ioctl.h> 25 #include <media/v4l2-event.h> 26 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" 34 35 #include "sh_css_hrt.h" 36 37 #include "gp_device.h" 38 #include "device_access.h" 39 #include "irq.h" 40 41 static const char *DRIVER = "atomisp"; /* max size 15 */ 42 static const char *CARD = "ATOM ISP"; /* max size 31 */ 43 44 /* 45 * FIXME: ISP should not know beforehand all CIDs supported by sensor. 46 * Instead, it needs to propagate to sensor unkonwn CIDs. 47 */ 48 static struct v4l2_queryctrl ci_v4l2_controls[] = { 49 { 50 .id = V4L2_CID_AUTO_WHITE_BALANCE, 51 .type = V4L2_CTRL_TYPE_BOOLEAN, 52 .name = "Automatic White Balance", 53 .minimum = 0, 54 .maximum = 1, 55 .step = 1, 56 .default_value = 0, 57 }, 58 { 59 .id = V4L2_CID_RED_BALANCE, 60 .type = V4L2_CTRL_TYPE_INTEGER, 61 .name = "Red Balance", 62 .minimum = 0x00, 63 .maximum = 0xff, 64 .step = 1, 65 .default_value = 0x00, 66 }, 67 { 68 .id = V4L2_CID_BLUE_BALANCE, 69 .type = V4L2_CTRL_TYPE_INTEGER, 70 .name = "Blue Balance", 71 .minimum = 0x00, 72 .maximum = 0xff, 73 .step = 1, 74 .default_value = 0x00, 75 }, 76 { 77 .id = V4L2_CID_GAMMA, 78 .type = V4L2_CTRL_TYPE_INTEGER, 79 .name = "Gamma", 80 .minimum = 0x00, 81 .maximum = 0xff, 82 .step = 1, 83 .default_value = 0x00, 84 }, 85 { 86 .id = V4L2_CID_POWER_LINE_FREQUENCY, 87 .type = V4L2_CTRL_TYPE_MENU, 88 .name = "Light frequency filter", 89 .minimum = 1, 90 .maximum = 2, 91 .step = 1, 92 .default_value = 1, 93 }, 94 { 95 .id = V4L2_CID_COLORFX, 96 .type = V4L2_CTRL_TYPE_INTEGER, 97 .name = "Image Color Effect", 98 .minimum = 0, 99 .maximum = 9, 100 .step = 1, 101 .default_value = 0, 102 }, 103 { 104 .id = V4L2_CID_COLORFX_CBCR, 105 .type = V4L2_CTRL_TYPE_INTEGER, 106 .name = "Image Color Effect CbCr", 107 .minimum = 0, 108 .maximum = 0xffff, 109 .step = 1, 110 .default_value = 0, 111 }, 112 { 113 .id = V4L2_CID_ATOMISP_BAD_PIXEL_DETECTION, 114 .type = V4L2_CTRL_TYPE_INTEGER, 115 .name = "Bad Pixel Correction", 116 .minimum = 0, 117 .maximum = 1, 118 .step = 1, 119 .default_value = 0, 120 }, 121 { 122 .id = V4L2_CID_ATOMISP_POSTPROCESS_GDC_CAC, 123 .type = V4L2_CTRL_TYPE_INTEGER, 124 .name = "GDC/CAC", 125 .minimum = 0, 126 .maximum = 1, 127 .step = 1, 128 .default_value = 0, 129 }, 130 { 131 .id = V4L2_CID_ATOMISP_VIDEO_STABLIZATION, 132 .type = V4L2_CTRL_TYPE_INTEGER, 133 .name = "Video Stablization", 134 .minimum = 0, 135 .maximum = 1, 136 .step = 1, 137 .default_value = 0, 138 }, 139 { 140 .id = V4L2_CID_ATOMISP_FIXED_PATTERN_NR, 141 .type = V4L2_CTRL_TYPE_INTEGER, 142 .name = "Fixed Pattern Noise Reduction", 143 .minimum = 0, 144 .maximum = 1, 145 .step = 1, 146 .default_value = 0, 147 }, 148 { 149 .id = V4L2_CID_ATOMISP_FALSE_COLOR_CORRECTION, 150 .type = V4L2_CTRL_TYPE_INTEGER, 151 .name = "False Color Correction", 152 .minimum = 0, 153 .maximum = 1, 154 .step = 1, 155 .default_value = 0, 156 }, 157 { 158 .id = V4L2_CID_REQUEST_FLASH, 159 .type = V4L2_CTRL_TYPE_INTEGER, 160 .name = "Request flash frames", 161 .minimum = 0, 162 .maximum = 10, 163 .step = 1, 164 .default_value = 1, 165 }, 166 { 167 .id = V4L2_CID_ATOMISP_LOW_LIGHT, 168 .type = V4L2_CTRL_TYPE_BOOLEAN, 169 .name = "Low light mode", 170 .minimum = 0, 171 .maximum = 1, 172 .step = 1, 173 .default_value = 1, 174 }, 175 { 176 .id = V4L2_CID_2A_STATUS, 177 .type = V4L2_CTRL_TYPE_BITMASK, 178 .name = "AE and AWB status", 179 .minimum = 0, 180 .maximum = V4L2_2A_STATUS_AE_READY | V4L2_2A_STATUS_AWB_READY, 181 .step = 1, 182 .default_value = 0, 183 }, 184 { 185 .id = V4L2_CID_EXPOSURE, 186 .type = V4L2_CTRL_TYPE_INTEGER, 187 .name = "exposure", 188 .minimum = -4, 189 .maximum = 4, 190 .step = 1, 191 .default_value = 0, 192 }, 193 { 194 .id = V4L2_CID_EXPOSURE_ZONE_NUM, 195 .type = V4L2_CTRL_TYPE_INTEGER, 196 .name = "one-time exposure zone number", 197 .minimum = 0x0, 198 .maximum = 0xffff, 199 .step = 1, 200 .default_value = 0, 201 }, 202 { 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, 208 .step = 1, 209 .default_value = V4L2_EXPOSURE_AUTO, 210 }, 211 { 212 .id = V4L2_CID_SCENE_MODE, 213 .type = V4L2_CTRL_TYPE_INTEGER, 214 .name = "scene mode", 215 .minimum = 0, 216 .maximum = 13, 217 .step = 1, 218 .default_value = 0, 219 }, 220 { 221 .id = V4L2_CID_ISO_SENSITIVITY, 222 .type = V4L2_CTRL_TYPE_INTEGER, 223 .name = "iso", 224 .minimum = -4, 225 .maximum = 4, 226 .step = 1, 227 .default_value = 0, 228 }, 229 { 230 .id = V4L2_CID_ISO_SENSITIVITY_AUTO, 231 .type = V4L2_CTRL_TYPE_INTEGER, 232 .name = "iso mode", 233 .minimum = V4L2_ISO_SENSITIVITY_MANUAL, 234 .maximum = V4L2_ISO_SENSITIVITY_AUTO, 235 .step = 1, 236 .default_value = V4L2_ISO_SENSITIVITY_AUTO, 237 }, 238 { 239 .id = V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE, 240 .type = V4L2_CTRL_TYPE_INTEGER, 241 .name = "white balance", 242 .minimum = 0, 243 .maximum = 9, 244 .step = 1, 245 .default_value = 0, 246 }, 247 { 248 .id = V4L2_CID_EXPOSURE_METERING, 249 .type = V4L2_CTRL_TYPE_MENU, 250 .name = "metering", 251 .minimum = 0, 252 .maximum = 3, 253 .step = 1, 254 .default_value = 1, 255 }, 256 { 257 .id = V4L2_CID_3A_LOCK, 258 .type = V4L2_CTRL_TYPE_BITMASK, 259 .name = "3a lock", 260 .minimum = 0, 261 .maximum = V4L2_LOCK_EXPOSURE | V4L2_LOCK_WHITE_BALANCE 262 | V4L2_LOCK_FOCUS, 263 .step = 1, 264 .default_value = 0, 265 }, 266 { 267 .id = V4L2_CID_TEST_PATTERN, 268 .type = V4L2_CTRL_TYPE_INTEGER, 269 .name = "Test Pattern", 270 .minimum = 0, 271 .maximum = 0xffff, 272 .step = 1, 273 .default_value = 0, 274 }, 275 { 276 .id = V4L2_CID_TEST_PATTERN_COLOR_R, 277 .type = V4L2_CTRL_TYPE_INTEGER, 278 .name = "Test Pattern Solid Color R", 279 .minimum = INT_MIN, 280 .maximum = INT_MAX, 281 .step = 1, 282 .default_value = 0, 283 }, 284 { 285 .id = V4L2_CID_TEST_PATTERN_COLOR_GR, 286 .type = V4L2_CTRL_TYPE_INTEGER, 287 .name = "Test Pattern Solid Color GR", 288 .minimum = INT_MIN, 289 .maximum = INT_MAX, 290 .step = 1, 291 .default_value = 0, 292 }, 293 { 294 .id = V4L2_CID_TEST_PATTERN_COLOR_GB, 295 .type = V4L2_CTRL_TYPE_INTEGER, 296 .name = "Test Pattern Solid Color GB", 297 .minimum = INT_MIN, 298 .maximum = INT_MAX, 299 .step = 1, 300 .default_value = 0, 301 }, 302 { 303 .id = V4L2_CID_TEST_PATTERN_COLOR_B, 304 .type = V4L2_CTRL_TYPE_INTEGER, 305 .name = "Test Pattern Solid Color B", 306 .minimum = INT_MIN, 307 .maximum = INT_MAX, 308 .step = 1, 309 .default_value = 0, 310 }, 311 }; 312 313 static const u32 ctrls_num = ARRAY_SIZE(ci_v4l2_controls); 314 315 /* 316 * supported V4L2 fmts and resolutions 317 */ 318 const struct atomisp_format_bridge atomisp_output_fmts[] = { 319 { 320 .pixelformat = V4L2_PIX_FMT_YUV420, 321 .depth = 12, 322 .mbus_code = V4L2_MBUS_FMT_CUSTOM_YUV420, 323 .sh_fmt = IA_CSS_FRAME_FORMAT_YUV420, 324 .description = "YUV420, planar", 325 .planar = true 326 }, { 327 .pixelformat = V4L2_PIX_FMT_YVU420, 328 .depth = 12, 329 .mbus_code = V4L2_MBUS_FMT_CUSTOM_YVU420, 330 .sh_fmt = IA_CSS_FRAME_FORMAT_YV12, 331 .description = "YVU420, planar", 332 .planar = true 333 }, { 334 .pixelformat = V4L2_PIX_FMT_YUV422P, 335 .depth = 16, 336 .mbus_code = V4L2_MBUS_FMT_CUSTOM_YUV422P, 337 .sh_fmt = IA_CSS_FRAME_FORMAT_YUV422, 338 .description = "YUV422, planar", 339 .planar = true 340 }, { 341 .pixelformat = V4L2_PIX_FMT_YUV444, 342 .depth = 24, 343 .mbus_code = V4L2_MBUS_FMT_CUSTOM_YUV444, 344 .sh_fmt = IA_CSS_FRAME_FORMAT_YUV444, 345 .description = "YUV444" 346 }, { 347 .pixelformat = V4L2_PIX_FMT_NV12, 348 .depth = 12, 349 .mbus_code = V4L2_MBUS_FMT_CUSTOM_NV12, 350 .sh_fmt = IA_CSS_FRAME_FORMAT_NV12, 351 .description = "NV12, Y-plane, CbCr interleaved", 352 .planar = true 353 }, { 354 .pixelformat = V4L2_PIX_FMT_NV21, 355 .depth = 12, 356 .mbus_code = V4L2_MBUS_FMT_CUSTOM_NV21, 357 .sh_fmt = IA_CSS_FRAME_FORMAT_NV21, 358 .description = "NV21, Y-plane, CbCr interleaved", 359 .planar = true 360 }, { 361 .pixelformat = V4L2_PIX_FMT_NV16, 362 .depth = 16, 363 .mbus_code = V4L2_MBUS_FMT_CUSTOM_NV16, 364 .sh_fmt = IA_CSS_FRAME_FORMAT_NV16, 365 .description = "NV16, Y-plane, CbCr interleaved", 366 .planar = true 367 }, { 368 .pixelformat = V4L2_PIX_FMT_YUYV, 369 .depth = 16, 370 .mbus_code = V4L2_MBUS_FMT_CUSTOM_YUYV, 371 .sh_fmt = IA_CSS_FRAME_FORMAT_YUYV, 372 .description = "YUYV, interleaved" 373 }, { 374 .pixelformat = V4L2_PIX_FMT_UYVY, 375 .depth = 16, 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, 381 .depth = 16, 382 .mbus_code = MEDIA_BUS_FMT_UYVY8_2X8, 383 .sh_fmt = IA_CSS_FRAME_FORMAT_UYVY, 384 .description = "UYVY, interleaved" 385 }, { 386 .pixelformat = V4L2_PIX_FMT_SBGGR16, 387 .depth = 16, 388 .mbus_code = V4L2_MBUS_FMT_CUSTOM_SBGGR16, 389 .sh_fmt = IA_CSS_FRAME_FORMAT_RAW, 390 .description = "Bayer 16" 391 }, { 392 .pixelformat = V4L2_PIX_FMT_SBGGR8, 393 .depth = 8, 394 .mbus_code = MEDIA_BUS_FMT_SBGGR8_1X8, 395 .sh_fmt = IA_CSS_FRAME_FORMAT_RAW, 396 .description = "Bayer 8" 397 }, { 398 .pixelformat = V4L2_PIX_FMT_SGBRG8, 399 .depth = 8, 400 .mbus_code = MEDIA_BUS_FMT_SGBRG8_1X8, 401 .sh_fmt = IA_CSS_FRAME_FORMAT_RAW, 402 .description = "Bayer 8" 403 }, { 404 .pixelformat = V4L2_PIX_FMT_SGRBG8, 405 .depth = 8, 406 .mbus_code = MEDIA_BUS_FMT_SGRBG8_1X8, 407 .sh_fmt = IA_CSS_FRAME_FORMAT_RAW, 408 .description = "Bayer 8" 409 }, { 410 .pixelformat = V4L2_PIX_FMT_SRGGB8, 411 .depth = 8, 412 .mbus_code = MEDIA_BUS_FMT_SRGGB8_1X8, 413 .sh_fmt = IA_CSS_FRAME_FORMAT_RAW, 414 .description = "Bayer 8" 415 }, { 416 .pixelformat = V4L2_PIX_FMT_SBGGR10, 417 .depth = 16, 418 .mbus_code = MEDIA_BUS_FMT_SBGGR10_1X10, 419 .sh_fmt = IA_CSS_FRAME_FORMAT_RAW, 420 .description = "Bayer 10" 421 }, { 422 .pixelformat = V4L2_PIX_FMT_SGBRG10, 423 .depth = 16, 424 .mbus_code = MEDIA_BUS_FMT_SGBRG10_1X10, 425 .sh_fmt = IA_CSS_FRAME_FORMAT_RAW, 426 .description = "Bayer 10" 427 }, { 428 .pixelformat = V4L2_PIX_FMT_SGRBG10, 429 .depth = 16, 430 .mbus_code = MEDIA_BUS_FMT_SGRBG10_1X10, 431 .sh_fmt = IA_CSS_FRAME_FORMAT_RAW, 432 .description = "Bayer 10" 433 }, { 434 .pixelformat = V4L2_PIX_FMT_SRGGB10, 435 .depth = 16, 436 .mbus_code = MEDIA_BUS_FMT_SRGGB10_1X10, 437 .sh_fmt = IA_CSS_FRAME_FORMAT_RAW, 438 .description = "Bayer 10" 439 }, { 440 .pixelformat = V4L2_PIX_FMT_SBGGR12, 441 .depth = 16, 442 .mbus_code = MEDIA_BUS_FMT_SBGGR12_1X12, 443 .sh_fmt = IA_CSS_FRAME_FORMAT_RAW, 444 .description = "Bayer 12" 445 }, { 446 .pixelformat = V4L2_PIX_FMT_SGBRG12, 447 .depth = 16, 448 .mbus_code = MEDIA_BUS_FMT_SGBRG12_1X12, 449 .sh_fmt = IA_CSS_FRAME_FORMAT_RAW, 450 .description = "Bayer 12" 451 }, { 452 .pixelformat = V4L2_PIX_FMT_SGRBG12, 453 .depth = 16, 454 .mbus_code = MEDIA_BUS_FMT_SGRBG12_1X12, 455 .sh_fmt = IA_CSS_FRAME_FORMAT_RAW, 456 .description = "Bayer 12" 457 }, { 458 .pixelformat = V4L2_PIX_FMT_SRGGB12, 459 .depth = 16, 460 .mbus_code = MEDIA_BUS_FMT_SRGGB12_1X12, 461 .sh_fmt = IA_CSS_FRAME_FORMAT_RAW, 462 .description = "Bayer 12" 463 }, { 464 .pixelformat = V4L2_PIX_FMT_RGB32, 465 .depth = 32, 466 .mbus_code = V4L2_MBUS_FMT_CUSTOM_RGB32, 467 .sh_fmt = IA_CSS_FRAME_FORMAT_RGBA888, 468 .description = "32 RGB 8-8-8-8" 469 }, { 470 .pixelformat = V4L2_PIX_FMT_RGB565, 471 .depth = 16, 472 .mbus_code = MEDIA_BUS_FMT_BGR565_2X8_LE, 473 .sh_fmt = IA_CSS_FRAME_FORMAT_RGB565, 474 .description = "16 RGB 5-6-5" 475 #if 0 476 }, { 477 .pixelformat = V4L2_PIX_FMT_JPEG, 478 .depth = 8, 479 .mbus_code = MEDIA_BUS_FMT_JPEG_1X8, 480 .sh_fmt = IA_CSS_FRAME_FORMAT_BINARY_8, 481 .description = "JPEG" 482 }, { 483 /* This is a custom format being used by M10MO to send the RAW data */ 484 .pixelformat = V4L2_PIX_FMT_CUSTOM_M10MO_RAW, 485 .depth = 8, 486 .mbus_code = V4L2_MBUS_FMT_CUSTOM_M10MO_RAW, 487 .sh_fmt = IA_CSS_FRAME_FORMAT_BINARY_8, 488 .description = "Custom RAW for M10MO" 489 #endif 490 }, 491 }; 492 493 const struct atomisp_format_bridge * 494 atomisp_get_format_bridge(unsigned int pixelformat) 495 { 496 unsigned int i; 497 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]; 501 } 502 503 return NULL; 504 } 505 506 const struct atomisp_format_bridge * 507 atomisp_get_format_bridge_from_mbus(u32 mbus_code) 508 { 509 unsigned int i; 510 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]; 514 } 515 516 return NULL; 517 } 518 519 int atomisp_pipe_check(struct atomisp_video_pipe *pipe, bool settings_change) 520 { 521 lockdep_assert_held(&pipe->isp->mutex); 522 523 if (pipe->isp->isp_fatal_error) 524 return -EIO; 525 526 if (settings_change && vb2_is_busy(&pipe->vb_queue)) { 527 dev_err(pipe->isp->dev, "Set fmt/input IOCTL while streaming\n"); 528 return -EBUSY; 529 } 530 531 return 0; 532 } 533 534 /* 535 * v4l2 ioctls 536 * return ISP capabilities 537 */ 538 static int atomisp_querycap(struct file *file, void *fh, 539 struct v4l2_capability *cap) 540 { 541 struct video_device *vdev = video_devdata(file); 542 struct atomisp_device *isp = video_get_drvdata(vdev); 543 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)); 547 548 return 0; 549 } 550 551 /* 552 * enum input are used to check primary/secondary camera 553 */ 554 static int atomisp_enum_input(struct file *file, void *fh, 555 struct v4l2_input *input) 556 { 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; 561 562 if (index >= isp->input_cnt) 563 return -EINVAL; 564 565 if (!isp->inputs[index].camera) 566 return -EINVAL; 567 568 memset(input, 0, sizeof(struct v4l2_input)); 569 strscpy(input->name, isp->inputs[index].camera->name, 570 sizeof(input->name)); 571 572 /* 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. 577 */ 578 if (!IS_ISP2401) 579 motor = isp->inputs[index].motor; 580 else 581 motor = isp->motor; 582 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; 586 587 if (max_size > 1) { 588 input->name[cur_len] = '+'; 589 strscpy(&input->name[cur_len + 1], 590 motor->name, max_size); 591 } 592 } 593 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; 598 599 return 0; 600 } 601 602 /* 603 * get input are used to get current primary/secondary camera 604 */ 605 static int atomisp_g_input(struct file *file, void *fh, unsigned int *input) 606 { 607 struct video_device *vdev = video_devdata(file); 608 struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd; 609 610 *input = asd->input_curr; 611 return 0; 612 } 613 614 static int atomisp_s_fmt_cap(struct file *file, void *fh, 615 struct v4l2_format *f) 616 { 617 struct video_device *vdev = video_devdata(file); 618 619 return atomisp_set_fmt(vdev, f); 620 } 621 622 /* 623 * set input are used to set current primary/secondary camera 624 */ 625 static int atomisp_s_input(struct file *file, void *fh, unsigned int input) 626 { 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; 633 int ret; 634 635 ret = atomisp_pipe_check(pipe, true); 636 if (ret) 637 return ret; 638 639 if (input >= ATOM_ISP_MAX_INPUTS || input >= isp->input_cnt) { 640 dev_dbg(isp->dev, "input_cnt: %d\n", isp->input_cnt); 641 return -EINVAL; 642 } 643 644 camera = isp->inputs[input].camera; 645 if (!camera) { 646 dev_err(isp->dev, "%s, no camera\n", __func__); 647 return -EINVAL; 648 } 649 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, 654 core, s_power, 0); 655 if (ret && ret != -ENOIOCTLCMD) 656 dev_warn(isp->dev, 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; 660 } 661 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"); 666 return ret; 667 } 668 /* 669 * Some sensor driver resets the run mode during power-on, thus force 670 * update the run mode to sensor after power-on. 671 */ 672 atomisp_update_run_mode(asd); 673 674 /* select operating sensor */ 675 ret = v4l2_subdev_call(isp->inputs[input].camera, video, s_routing, 676 0, 0, 0); 677 if (ret && (ret != -ENOIOCTLCMD)) { 678 dev_err(isp->dev, "Failed to select sensor\n"); 679 return ret; 680 } 681 682 if (!IS_ISP2401) { 683 motor = isp->inputs[input].motor; 684 } else { 685 motor = isp->motor; 686 if (motor) 687 ret = v4l2_subdev_call(motor, core, s_power, 1); 688 } 689 690 if (motor) 691 ret = v4l2_subdev_call(motor, core, init, 1); 692 693 asd->input_curr = input; 694 /* mark this camera is used by the current stream */ 695 isp->inputs[input].asd = asd; 696 697 return 0; 698 } 699 700 static int atomisp_enum_framesizes(struct file *file, void *priv, 701 struct v4l2_frmsizeenum *fsize) 702 { 703 struct video_device *vdev = video_devdata(file); 704 struct atomisp_device *isp = video_get_drvdata(vdev); 705 struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd; 706 struct atomisp_input_subdev *input = &isp->inputs[asd->input_curr]; 707 struct v4l2_subdev_frame_size_enum fse = { 708 .index = fsize->index, 709 .which = V4L2_SUBDEV_FORMAT_ACTIVE, 710 }; 711 int ret; 712 713 ret = v4l2_subdev_call(input->camera, pad, enum_frame_size, NULL, &fse); 714 if (ret) 715 return ret; 716 717 fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; 718 fsize->discrete.width = fse.max_width - pad_w; 719 fsize->discrete.height = fse.max_height - pad_h; 720 721 return 0; 722 } 723 724 static int atomisp_enum_frameintervals(struct file *file, void *priv, 725 struct v4l2_frmivalenum *fival) 726 { 727 struct video_device *vdev = video_devdata(file); 728 struct atomisp_device *isp = video_get_drvdata(vdev); 729 struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd; 730 struct v4l2_subdev_frame_interval_enum fie = { 731 .code = atomisp_in_fmt_conv[0].code, 732 .index = fival->index, 733 .width = fival->width, 734 .height = fival->height, 735 .which = V4L2_SUBDEV_FORMAT_ACTIVE, 736 }; 737 int ret; 738 739 ret = v4l2_subdev_call(isp->inputs[asd->input_curr].camera, 740 pad, enum_frame_interval, NULL, 741 &fie); 742 if (ret) 743 return ret; 744 745 fival->type = V4L2_FRMIVAL_TYPE_DISCRETE; 746 fival->discrete = fie.interval; 747 748 return ret; 749 } 750 751 static int atomisp_enum_fmt_cap(struct file *file, void *fh, 752 struct v4l2_fmtdesc *f) 753 { 754 struct video_device *vdev = video_devdata(file); 755 struct atomisp_device *isp = video_get_drvdata(vdev); 756 struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd; 757 struct v4l2_subdev_mbus_code_enum code = { 758 .which = V4L2_SUBDEV_FORMAT_ACTIVE, 759 }; 760 const struct atomisp_format_bridge *format; 761 struct v4l2_subdev *camera; 762 unsigned int i, fi = 0; 763 int rval; 764 765 camera = isp->inputs[asd->input_curr].camera; 766 if(!camera) { 767 dev_err(isp->dev, "%s(): camera is NULL, device is %s\n", 768 __func__, vdev->name); 769 return -EINVAL; 770 } 771 772 rval = v4l2_subdev_call(camera, pad, enum_mbus_code, NULL, &code); 773 if (rval == -ENOIOCTLCMD) { 774 dev_warn(isp->dev, 775 "enum_mbus_code pad op not supported by %s. Please fix your sensor driver!\n", 776 camera->name); 777 } 778 779 if (rval) 780 return rval; 781 782 for (i = 0; i < ARRAY_SIZE(atomisp_output_fmts); i++) { 783 format = &atomisp_output_fmts[i]; 784 785 /* 786 * Is the atomisp-supported format is valid for the 787 * sensor (configuration)? If not, skip it. 788 * 789 * FIXME: fix the pipeline to allow sensor format too. 790 */ 791 if (format->sh_fmt == IA_CSS_FRAME_FORMAT_RAW) 792 continue; 793 794 /* Found a match. Now let's pick f->index'th one. */ 795 if (fi < f->index) { 796 fi++; 797 continue; 798 } 799 800 strscpy(f->description, format->description, 801 sizeof(f->description)); 802 f->pixelformat = format->pixelformat; 803 return 0; 804 } 805 806 return -EINVAL; 807 } 808 809 /* This function looks up the closest available resolution. */ 810 static int atomisp_try_fmt_cap(struct file *file, void *fh, 811 struct v4l2_format *f) 812 { 813 struct video_device *vdev = video_devdata(file); 814 struct atomisp_device *isp = video_get_drvdata(vdev); 815 816 return atomisp_try_fmt(isp, &f->fmt.pix, NULL, NULL); 817 } 818 819 static int atomisp_g_fmt_cap(struct file *file, void *fh, 820 struct v4l2_format *f) 821 { 822 struct video_device *vdev = video_devdata(file); 823 struct atomisp_video_pipe *pipe; 824 825 pipe = atomisp_to_video_pipe(vdev); 826 827 f->fmt.pix = pipe->pix; 828 829 /* If s_fmt was issued, just return whatever is was previouly set */ 830 if (f->fmt.pix.sizeimage) 831 return 0; 832 833 f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420; 834 f->fmt.pix.width = 10000; 835 f->fmt.pix.height = 10000; 836 837 return atomisp_try_fmt_cap(file, fh, f); 838 } 839 840 int atomisp_alloc_css_stat_bufs(struct atomisp_sub_device *asd, 841 uint16_t stream_id) 842 { 843 struct atomisp_device *isp = asd->isp; 844 struct atomisp_s3a_buf *s3a_buf = NULL, *_s3a_buf; 845 struct atomisp_dis_buf *dis_buf = NULL, *_dis_buf; 846 struct atomisp_metadata_buf *md_buf = NULL, *_md_buf; 847 int count; 848 struct ia_css_dvs_grid_info *dvs_grid_info = 849 atomisp_css_get_dvs_grid_info(&asd->params.curr_grid_info); 850 unsigned int i; 851 852 if (list_empty(&asd->s3a_stats) && 853 asd->params.curr_grid_info.s3a_grid.enable) { 854 count = ATOMISP_CSS_Q_DEPTH + 855 ATOMISP_S3A_BUF_QUEUE_DEPTH_FOR_HAL; 856 dev_dbg(isp->dev, "allocating %d 3a buffers\n", count); 857 while (count--) { 858 s3a_buf = kzalloc(sizeof(struct atomisp_s3a_buf), GFP_KERNEL); 859 if (!s3a_buf) 860 goto error; 861 862 if (atomisp_css_allocate_stat_buffers( 863 asd, stream_id, s3a_buf, NULL, NULL)) { 864 kfree(s3a_buf); 865 goto error; 866 } 867 868 list_add_tail(&s3a_buf->list, &asd->s3a_stats); 869 } 870 } 871 872 if (list_empty(&asd->dis_stats) && dvs_grid_info && 873 dvs_grid_info->enable) { 874 count = ATOMISP_CSS_Q_DEPTH + 1; 875 dev_dbg(isp->dev, "allocating %d dis buffers\n", count); 876 while (count--) { 877 dis_buf = kzalloc(sizeof(struct atomisp_dis_buf), GFP_KERNEL); 878 if (!dis_buf) 879 goto error; 880 if (atomisp_css_allocate_stat_buffers( 881 asd, stream_id, NULL, dis_buf, NULL)) { 882 kfree(dis_buf); 883 goto error; 884 } 885 886 list_add_tail(&dis_buf->list, &asd->dis_stats); 887 } 888 } 889 890 for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) { 891 if (list_empty(&asd->metadata[i]) && 892 list_empty(&asd->metadata_ready[i]) && 893 list_empty(&asd->metadata_in_css[i])) { 894 count = ATOMISP_CSS_Q_DEPTH + 895 ATOMISP_METADATA_QUEUE_DEPTH_FOR_HAL; 896 dev_dbg(isp->dev, "allocating %d metadata buffers for type %d\n", 897 count, i); 898 while (count--) { 899 md_buf = kzalloc(sizeof(struct atomisp_metadata_buf), 900 GFP_KERNEL); 901 if (!md_buf) 902 goto error; 903 904 if (atomisp_css_allocate_stat_buffers( 905 asd, stream_id, NULL, NULL, md_buf)) { 906 kfree(md_buf); 907 goto error; 908 } 909 list_add_tail(&md_buf->list, &asd->metadata[i]); 910 } 911 } 912 } 913 return 0; 914 915 error: 916 dev_err(isp->dev, "failed to allocate statistics buffers\n"); 917 918 list_for_each_entry_safe(dis_buf, _dis_buf, &asd->dis_stats, list) { 919 atomisp_css_free_dis_buffer(dis_buf); 920 list_del(&dis_buf->list); 921 kfree(dis_buf); 922 } 923 924 list_for_each_entry_safe(s3a_buf, _s3a_buf, &asd->s3a_stats, list) { 925 atomisp_css_free_3a_buffer(s3a_buf); 926 list_del(&s3a_buf->list); 927 kfree(s3a_buf); 928 } 929 930 for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) { 931 list_for_each_entry_safe(md_buf, _md_buf, &asd->metadata[i], 932 list) { 933 atomisp_css_free_metadata_buffer(md_buf); 934 list_del(&md_buf->list); 935 kfree(md_buf); 936 } 937 } 938 return -ENOMEM; 939 } 940 941 /* 942 * FIXME the abuse of buf->reserved2 in the qbuf and dqbuf wrappers comes from 943 * the original atomisp buffer handling and should be replaced with proper V4L2 944 * per frame parameters use. 945 * 946 * Once this is fixed these wrappers can be removed, replacing them with direct 947 * calls to vb2_ioctl_[d]qbuf(). 948 */ 949 static int atomisp_qbuf_wrapper(struct file *file, void *fh, struct v4l2_buffer *buf) 950 { 951 struct video_device *vdev = video_devdata(file); 952 struct atomisp_device *isp = video_get_drvdata(vdev); 953 struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev); 954 955 if (buf->index >= vdev->queue->num_buffers) 956 return -EINVAL; 957 958 if (buf->reserved2 & ATOMISP_BUFFER_HAS_PER_FRAME_SETTING) { 959 /* this buffer will have a per-frame parameter */ 960 pipe->frame_request_config_id[buf->index] = buf->reserved2 & 961 ~ATOMISP_BUFFER_HAS_PER_FRAME_SETTING; 962 dev_dbg(isp->dev, 963 "This buffer requires per_frame setting which has isp_config_id %d\n", 964 pipe->frame_request_config_id[buf->index]); 965 } else { 966 pipe->frame_request_config_id[buf->index] = 0; 967 } 968 969 return vb2_ioctl_qbuf(file, fh, buf); 970 } 971 972 static int atomisp_dqbuf_wrapper(struct file *file, void *fh, struct v4l2_buffer *buf) 973 { 974 struct video_device *vdev = video_devdata(file); 975 struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev); 976 struct atomisp_sub_device *asd = pipe->asd; 977 struct atomisp_device *isp = video_get_drvdata(vdev); 978 struct ia_css_frame *frame; 979 struct vb2_buffer *vb; 980 int ret; 981 982 ret = vb2_ioctl_dqbuf(file, fh, buf); 983 if (ret) 984 return ret; 985 986 vb = pipe->vb_queue.bufs[buf->index]; 987 frame = vb_to_frame(vb); 988 989 buf->reserved = asd->frame_status[buf->index]; 990 991 /* 992 * Hack: 993 * Currently frame_status in the enum type which takes no more lower 994 * 8 bit. 995 * use bit[31:16] for exp_id as it is only in the range of 1~255 996 */ 997 buf->reserved &= 0x0000ffff; 998 if (!(buf->flags & V4L2_BUF_FLAG_ERROR)) 999 buf->reserved |= frame->exp_id; 1000 buf->reserved2 = pipe->frame_config_id[buf->index]; 1001 1002 dev_dbg(isp->dev, 1003 "dqbuf buffer %d (%s) with exp_id %d, isp_config_id %d\n", 1004 buf->index, vdev->name, buf->reserved >> 16, buf->reserved2); 1005 return 0; 1006 } 1007 1008 /* Input system HW workaround */ 1009 /* Input system address translation corrupts burst during */ 1010 /* invalidate. SW workaround for this is to set burst length */ 1011 /* manually to 128 in case of 13MPx snapshot and to 1 otherwise. */ 1012 static void atomisp_dma_burst_len_cfg(struct atomisp_sub_device *asd) 1013 { 1014 struct v4l2_mbus_framefmt *sink; 1015 1016 sink = atomisp_subdev_get_ffmt(&asd->subdev, NULL, 1017 V4L2_SUBDEV_FORMAT_ACTIVE, 1018 ATOMISP_SUBDEV_PAD_SINK); 1019 1020 if (sink->width * sink->height >= 4096 * 3072) 1021 atomisp_css2_hw_store_32(DMA_BURST_SIZE_REG, 0x7F); 1022 else 1023 atomisp_css2_hw_store_32(DMA_BURST_SIZE_REG, 0x00); 1024 } 1025 1026 int atomisp_start_streaming(struct vb2_queue *vq, unsigned int count) 1027 { 1028 struct atomisp_video_pipe *pipe = vq_to_pipe(vq); 1029 struct atomisp_sub_device *asd = pipe->asd; 1030 struct atomisp_device *isp = asd->isp; 1031 struct pci_dev *pdev = to_pci_dev(isp->dev); 1032 unsigned long irqflags; 1033 int ret; 1034 1035 dev_dbg(isp->dev, "Start stream\n"); 1036 1037 mutex_lock(&isp->mutex); 1038 1039 ret = atomisp_pipe_check(pipe, false); 1040 if (ret) 1041 goto out_unlock; 1042 1043 /* Input system HW workaround */ 1044 atomisp_dma_burst_len_cfg(asd); 1045 1046 /* Invalidate caches. FIXME: should flush only necessary buffers */ 1047 wbinvd(); 1048 1049 if (asd->params.css_update_params_needed) { 1050 atomisp_apply_css_parameters(asd, &asd->params.css_param); 1051 if (asd->params.css_param.update_flag.dz_config) 1052 asd->params.config.dz_config = &asd->params.css_param.dz_config; 1053 atomisp_css_update_isp_params(asd); 1054 asd->params.css_update_params_needed = false; 1055 memset(&asd->params.css_param.update_flag, 0, 1056 sizeof(struct atomisp_parameters)); 1057 } 1058 asd->params.dvs_6axis = NULL; 1059 1060 ret = atomisp_css_start(asd); 1061 if (ret) { 1062 atomisp_flush_video_pipe(pipe, VB2_BUF_STATE_QUEUED, true); 1063 goto out_unlock; 1064 } 1065 1066 spin_lock_irqsave(&isp->lock, irqflags); 1067 asd->streaming = true; 1068 spin_unlock_irqrestore(&isp->lock, irqflags); 1069 atomic_set(&asd->sof_count, -1); 1070 atomic_set(&asd->sequence, -1); 1071 atomic_set(&asd->sequence_temp, -1); 1072 1073 asd->params.dis_proj_data_valid = false; 1074 asd->latest_preview_exp_id = 0; 1075 asd->postview_exp_id = 1; 1076 asd->preview_exp_id = 1; 1077 1078 /* handle per_frame_setting parameter and buffers */ 1079 atomisp_handle_parameter_and_buffer(pipe); 1080 1081 atomisp_qbuffers_to_css(asd); 1082 1083 if (isp->flash) { 1084 asd->params.num_flash_frames = 0; 1085 asd->params.flash_state = ATOMISP_FLASH_IDLE; 1086 atomisp_setup_flash(asd); 1087 } 1088 1089 atomisp_css_irq_enable(isp, IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF, 1090 atomisp_css_valid_sof(isp)); 1091 atomisp_csi2_configure(asd); 1092 1093 if (atomisp_freq_scaling(isp, ATOMISP_DFS_MODE_AUTO, false) < 0) 1094 dev_dbg(isp->dev, "DFS auto mode failed!\n"); 1095 1096 /* Enable the CSI interface on ANN B0/K0 */ 1097 if (isp->media_dev.hw_revision >= ((ATOMISP_HW_REVISION_ISP2401 << 1098 ATOMISP_HW_REVISION_SHIFT) | ATOMISP_HW_STEPPING_B0)) { 1099 pci_write_config_word(pdev, MRFLD_PCI_CSI_CONTROL, 1100 isp->saved_regs.csi_control | MRFLD_PCI_CSI_CONTROL_CSI_READY); 1101 } 1102 1103 /* stream on the sensor */ 1104 ret = v4l2_subdev_call(isp->inputs[asd->input_curr].camera, 1105 video, s_stream, 1); 1106 if (ret) { 1107 dev_err(isp->dev, "Starting sensor stream failed: %d\n", ret); 1108 spin_lock_irqsave(&isp->lock, irqflags); 1109 asd->streaming = false; 1110 spin_unlock_irqrestore(&isp->lock, irqflags); 1111 ret = -EINVAL; 1112 goto out_unlock; 1113 } 1114 1115 out_unlock: 1116 mutex_unlock(&isp->mutex); 1117 return ret; 1118 } 1119 1120 void atomisp_stop_streaming(struct vb2_queue *vq) 1121 { 1122 struct atomisp_video_pipe *pipe = vq_to_pipe(vq); 1123 struct atomisp_sub_device *asd = pipe->asd; 1124 struct atomisp_device *isp = asd->isp; 1125 struct pci_dev *pdev = to_pci_dev(isp->dev); 1126 unsigned long flags; 1127 int ret; 1128 1129 dev_dbg(isp->dev, "Stop stream\n"); 1130 1131 mutex_lock(&isp->mutex); 1132 /* 1133 * There is no guarantee that the buffers queued to / owned by the ISP 1134 * will properly be returned to the queue when stopping. Set a flag to 1135 * avoid new buffers getting queued and then wait for all the current 1136 * buffers to finish. 1137 */ 1138 pipe->stopping = true; 1139 mutex_unlock(&isp->mutex); 1140 /* wait max 1 second */ 1141 ret = wait_event_timeout(pipe->vb_queue.done_wq, 1142 atomisp_buffers_in_css(pipe) == 0, HZ); 1143 mutex_lock(&isp->mutex); 1144 pipe->stopping = false; 1145 if (ret == 0) 1146 dev_warn(isp->dev, "Warning timeout waiting for CSS to return buffers\n"); 1147 1148 spin_lock_irqsave(&isp->lock, flags); 1149 asd->streaming = false; 1150 spin_unlock_irqrestore(&isp->lock, flags); 1151 1152 atomisp_clear_css_buffer_counters(asd); 1153 atomisp_css_irq_enable(isp, IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF, false); 1154 1155 atomisp_css_stop(asd, false); 1156 1157 atomisp_flush_video_pipe(pipe, VB2_BUF_STATE_ERROR, true); 1158 1159 atomisp_subdev_cleanup_pending_events(asd); 1160 1161 ret = v4l2_subdev_call(isp->inputs[asd->input_curr].camera, 1162 video, s_stream, 0); 1163 if (ret) 1164 dev_warn(isp->dev, "Stopping sensor stream failed: %d\n", ret); 1165 1166 if (isp->flash) { 1167 asd->params.num_flash_frames = 0; 1168 asd->params.flash_state = ATOMISP_FLASH_IDLE; 1169 } 1170 1171 /* Disable the CSI interface on ANN B0/K0 */ 1172 if (isp->media_dev.hw_revision >= ((ATOMISP_HW_REVISION_ISP2401 << 1173 ATOMISP_HW_REVISION_SHIFT) | ATOMISP_HW_STEPPING_B0)) { 1174 pci_write_config_word(pdev, MRFLD_PCI_CSI_CONTROL, 1175 isp->saved_regs.csi_control & ~MRFLD_PCI_CSI_CONTROL_CSI_READY); 1176 } 1177 1178 if (atomisp_freq_scaling(isp, ATOMISP_DFS_MODE_LOW, false)) 1179 dev_warn(isp->dev, "DFS failed.\n"); 1180 1181 /* 1182 * ISP work around, need to reset ISP to allow next stream on to work. 1183 * Streams have already been destroyed by atomisp_css_stop(). 1184 * Disable PUNIT/ISP acknowlede/handshake - SRSE=3 and then reset. 1185 */ 1186 pci_write_config_dword(pdev, PCI_I_CONTROL, 1187 isp->saved_regs.i_control | MRFLD_PCI_I_CONTROL_SRSE_RESET_MASK); 1188 atomisp_reset(isp); 1189 1190 /* Streams were destroyed by atomisp_css_stop(), recreate them. */ 1191 ret = atomisp_create_pipes_stream(&isp->asd); 1192 if (ret) 1193 dev_warn(isp->dev, "Recreating streams failed: %d\n", ret); 1194 1195 mutex_unlock(&isp->mutex); 1196 } 1197 1198 /* 1199 * To get the current value of a control. 1200 * applications initialize the id field of a struct v4l2_control and 1201 * call this ioctl with a pointer to this structure 1202 */ 1203 static int atomisp_g_ctrl(struct file *file, void *fh, 1204 struct v4l2_control *control) 1205 { 1206 struct video_device *vdev = video_devdata(file); 1207 struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd; 1208 struct atomisp_device *isp = video_get_drvdata(vdev); 1209 int i, ret = -EINVAL; 1210 1211 for (i = 0; i < ctrls_num; i++) { 1212 if (ci_v4l2_controls[i].id == control->id) { 1213 ret = 0; 1214 break; 1215 } 1216 } 1217 1218 if (ret) 1219 return ret; 1220 1221 switch (control->id) { 1222 case V4L2_CID_IRIS_ABSOLUTE: 1223 case V4L2_CID_EXPOSURE_ABSOLUTE: 1224 case V4L2_CID_2A_STATUS: 1225 case V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE: 1226 case V4L2_CID_EXPOSURE: 1227 case V4L2_CID_EXPOSURE_AUTO: 1228 case V4L2_CID_SCENE_MODE: 1229 case V4L2_CID_ISO_SENSITIVITY: 1230 case V4L2_CID_ISO_SENSITIVITY_AUTO: 1231 case V4L2_CID_CONTRAST: 1232 case V4L2_CID_SATURATION: 1233 case V4L2_CID_SHARPNESS: 1234 case V4L2_CID_3A_LOCK: 1235 case V4L2_CID_EXPOSURE_ZONE_NUM: 1236 case V4L2_CID_TEST_PATTERN: 1237 case V4L2_CID_TEST_PATTERN_COLOR_R: 1238 case V4L2_CID_TEST_PATTERN_COLOR_GR: 1239 case V4L2_CID_TEST_PATTERN_COLOR_GB: 1240 case V4L2_CID_TEST_PATTERN_COLOR_B: 1241 return v4l2_g_ctrl(isp->inputs[asd->input_curr].camera-> 1242 ctrl_handler, control); 1243 case V4L2_CID_COLORFX: 1244 ret = atomisp_color_effect(asd, 0, &control->value); 1245 break; 1246 case V4L2_CID_ATOMISP_BAD_PIXEL_DETECTION: 1247 ret = atomisp_bad_pixel(asd, 0, &control->value); 1248 break; 1249 case V4L2_CID_ATOMISP_POSTPROCESS_GDC_CAC: 1250 ret = atomisp_gdc_cac(asd, 0, &control->value); 1251 break; 1252 case V4L2_CID_ATOMISP_VIDEO_STABLIZATION: 1253 ret = atomisp_video_stable(asd, 0, &control->value); 1254 break; 1255 case V4L2_CID_ATOMISP_FIXED_PATTERN_NR: 1256 ret = atomisp_fixed_pattern(asd, 0, &control->value); 1257 break; 1258 case V4L2_CID_ATOMISP_FALSE_COLOR_CORRECTION: 1259 ret = atomisp_false_color(asd, 0, &control->value); 1260 break; 1261 case V4L2_CID_ATOMISP_LOW_LIGHT: 1262 ret = atomisp_low_light(asd, 0, &control->value); 1263 break; 1264 default: 1265 ret = -EINVAL; 1266 break; 1267 } 1268 1269 return ret; 1270 } 1271 1272 /* 1273 * To change the value of a control. 1274 * applications initialize the id and value fields of a struct v4l2_control 1275 * and call this ioctl. 1276 */ 1277 static int atomisp_s_ctrl(struct file *file, void *fh, 1278 struct v4l2_control *control) 1279 { 1280 struct video_device *vdev = video_devdata(file); 1281 struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd; 1282 struct atomisp_device *isp = video_get_drvdata(vdev); 1283 int i, ret = -EINVAL; 1284 1285 for (i = 0; i < ctrls_num; i++) { 1286 if (ci_v4l2_controls[i].id == control->id) { 1287 ret = 0; 1288 break; 1289 } 1290 } 1291 1292 if (ret) 1293 return ret; 1294 1295 switch (control->id) { 1296 case V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE: 1297 case V4L2_CID_EXPOSURE: 1298 case V4L2_CID_EXPOSURE_AUTO: 1299 case V4L2_CID_EXPOSURE_AUTO_PRIORITY: 1300 case V4L2_CID_SCENE_MODE: 1301 case V4L2_CID_ISO_SENSITIVITY: 1302 case V4L2_CID_ISO_SENSITIVITY_AUTO: 1303 case V4L2_CID_POWER_LINE_FREQUENCY: 1304 case V4L2_CID_EXPOSURE_METERING: 1305 case V4L2_CID_CONTRAST: 1306 case V4L2_CID_SATURATION: 1307 case V4L2_CID_SHARPNESS: 1308 case V4L2_CID_3A_LOCK: 1309 case V4L2_CID_COLORFX_CBCR: 1310 case V4L2_CID_TEST_PATTERN: 1311 case V4L2_CID_TEST_PATTERN_COLOR_R: 1312 case V4L2_CID_TEST_PATTERN_COLOR_GR: 1313 case V4L2_CID_TEST_PATTERN_COLOR_GB: 1314 case V4L2_CID_TEST_PATTERN_COLOR_B: 1315 return v4l2_s_ctrl(NULL, 1316 isp->inputs[asd->input_curr].camera-> 1317 ctrl_handler, control); 1318 case V4L2_CID_COLORFX: 1319 ret = atomisp_color_effect(asd, 1, &control->value); 1320 break; 1321 case V4L2_CID_ATOMISP_BAD_PIXEL_DETECTION: 1322 ret = atomisp_bad_pixel(asd, 1, &control->value); 1323 break; 1324 case V4L2_CID_ATOMISP_POSTPROCESS_GDC_CAC: 1325 ret = atomisp_gdc_cac(asd, 1, &control->value); 1326 break; 1327 case V4L2_CID_ATOMISP_VIDEO_STABLIZATION: 1328 ret = atomisp_video_stable(asd, 1, &control->value); 1329 break; 1330 case V4L2_CID_ATOMISP_FIXED_PATTERN_NR: 1331 ret = atomisp_fixed_pattern(asd, 1, &control->value); 1332 break; 1333 case V4L2_CID_ATOMISP_FALSE_COLOR_CORRECTION: 1334 ret = atomisp_false_color(asd, 1, &control->value); 1335 break; 1336 case V4L2_CID_REQUEST_FLASH: 1337 ret = atomisp_flash_enable(asd, control->value); 1338 break; 1339 case V4L2_CID_ATOMISP_LOW_LIGHT: 1340 ret = atomisp_low_light(asd, 1, &control->value); 1341 break; 1342 default: 1343 ret = -EINVAL; 1344 break; 1345 } 1346 return ret; 1347 } 1348 1349 /* 1350 * To query the attributes of a control. 1351 * applications set the id field of a struct v4l2_queryctrl and call the 1352 * this ioctl with a pointer to this structure. The driver fills 1353 * the rest of the structure. 1354 */ 1355 static int atomisp_queryctl(struct file *file, void *fh, 1356 struct v4l2_queryctrl *qc) 1357 { 1358 int i, ret = -EINVAL; 1359 struct video_device *vdev = video_devdata(file); 1360 struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd; 1361 struct atomisp_device *isp = video_get_drvdata(vdev); 1362 1363 switch (qc->id) { 1364 case V4L2_CID_FOCUS_ABSOLUTE: 1365 case V4L2_CID_FOCUS_RELATIVE: 1366 case V4L2_CID_FOCUS_STATUS: 1367 if (!IS_ISP2401) { 1368 return v4l2_queryctrl(isp->inputs[asd->input_curr].camera-> 1369 ctrl_handler, qc); 1370 } 1371 /* ISP2401 */ 1372 if (isp->motor) 1373 return v4l2_queryctrl(isp->motor->ctrl_handler, qc); 1374 else 1375 return v4l2_queryctrl(isp->inputs[asd->input_curr]. 1376 camera->ctrl_handler, qc); 1377 } 1378 1379 if (qc->id & V4L2_CTRL_FLAG_NEXT_CTRL) 1380 return ret; 1381 1382 for (i = 0; i < ctrls_num; i++) { 1383 if (ci_v4l2_controls[i].id == qc->id) { 1384 memcpy(qc, &ci_v4l2_controls[i], 1385 sizeof(struct v4l2_queryctrl)); 1386 qc->reserved[0] = 0; 1387 ret = 0; 1388 break; 1389 } 1390 } 1391 if (ret != 0) 1392 qc->flags = V4L2_CTRL_FLAG_DISABLED; 1393 1394 return ret; 1395 } 1396 1397 static int atomisp_camera_g_ext_ctrls(struct file *file, void *fh, 1398 struct v4l2_ext_controls *c) 1399 { 1400 struct video_device *vdev = video_devdata(file); 1401 struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd; 1402 struct atomisp_device *isp = video_get_drvdata(vdev); 1403 struct v4l2_subdev *motor; 1404 struct v4l2_control ctrl; 1405 int i; 1406 int ret = 0; 1407 1408 if (!IS_ISP2401) 1409 motor = isp->inputs[asd->input_curr].motor; 1410 else 1411 motor = isp->motor; 1412 1413 for (i = 0; i < c->count; i++) { 1414 ctrl.id = c->controls[i].id; 1415 ctrl.value = c->controls[i].value; 1416 switch (ctrl.id) { 1417 case V4L2_CID_EXPOSURE_ABSOLUTE: 1418 case V4L2_CID_EXPOSURE_AUTO: 1419 case V4L2_CID_IRIS_ABSOLUTE: 1420 case V4L2_CID_3A_LOCK: 1421 case V4L2_CID_TEST_PATTERN: 1422 case V4L2_CID_TEST_PATTERN_COLOR_R: 1423 case V4L2_CID_TEST_PATTERN_COLOR_GR: 1424 case V4L2_CID_TEST_PATTERN_COLOR_GB: 1425 case V4L2_CID_TEST_PATTERN_COLOR_B: 1426 /* 1427 * Exposure related control will be handled by sensor 1428 * driver 1429 */ 1430 ret = 1431 v4l2_g_ctrl(isp->inputs[asd->input_curr].camera-> 1432 ctrl_handler, &ctrl); 1433 break; 1434 case V4L2_CID_FOCUS_ABSOLUTE: 1435 case V4L2_CID_FOCUS_RELATIVE: 1436 case V4L2_CID_FOCUS_STATUS: 1437 case V4L2_CID_FOCUS_AUTO: 1438 if (motor) 1439 ret = v4l2_g_ctrl(motor->ctrl_handler, &ctrl); 1440 break; 1441 case V4L2_CID_FLASH_STATUS: 1442 case V4L2_CID_FLASH_INTENSITY: 1443 case V4L2_CID_FLASH_TORCH_INTENSITY: 1444 case V4L2_CID_FLASH_INDICATOR_INTENSITY: 1445 case V4L2_CID_FLASH_TIMEOUT: 1446 case V4L2_CID_FLASH_STROBE: 1447 case V4L2_CID_FLASH_MODE: 1448 case V4L2_CID_FLASH_STATUS_REGISTER: 1449 if (isp->flash) 1450 ret = 1451 v4l2_g_ctrl(isp->flash->ctrl_handler, 1452 &ctrl); 1453 break; 1454 case V4L2_CID_ZOOM_ABSOLUTE: 1455 ret = atomisp_digital_zoom(asd, 0, &ctrl.value); 1456 break; 1457 case V4L2_CID_G_SKIP_FRAMES: 1458 ret = v4l2_subdev_call( 1459 isp->inputs[asd->input_curr].camera, 1460 sensor, g_skip_frames, (u32 *)&ctrl.value); 1461 break; 1462 default: 1463 ret = -EINVAL; 1464 } 1465 1466 if (ret) { 1467 c->error_idx = i; 1468 break; 1469 } 1470 c->controls[i].value = ctrl.value; 1471 } 1472 return ret; 1473 } 1474 1475 /* This ioctl allows the application to get multiple controls by class */ 1476 static int atomisp_g_ext_ctrls(struct file *file, void *fh, 1477 struct v4l2_ext_controls *c) 1478 { 1479 struct v4l2_control ctrl; 1480 int i, ret = 0; 1481 1482 /* 1483 * input_lock is not need for the Camera related IOCTLs 1484 * The input_lock downgrade the FPS of 3A 1485 */ 1486 ret = atomisp_camera_g_ext_ctrls(file, fh, c); 1487 if (ret != -EINVAL) 1488 return ret; 1489 1490 for (i = 0; i < c->count; i++) { 1491 ctrl.id = c->controls[i].id; 1492 ctrl.value = c->controls[i].value; 1493 ret = atomisp_g_ctrl(file, fh, &ctrl); 1494 c->controls[i].value = ctrl.value; 1495 if (ret) { 1496 c->error_idx = i; 1497 break; 1498 } 1499 } 1500 return ret; 1501 } 1502 1503 static int atomisp_camera_s_ext_ctrls(struct file *file, void *fh, 1504 struct v4l2_ext_controls *c) 1505 { 1506 struct video_device *vdev = video_devdata(file); 1507 struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd; 1508 struct atomisp_device *isp = video_get_drvdata(vdev); 1509 struct v4l2_subdev *motor; 1510 struct v4l2_control ctrl; 1511 int i; 1512 int ret = 0; 1513 1514 if (!IS_ISP2401) 1515 motor = isp->inputs[asd->input_curr].motor; 1516 else 1517 motor = isp->motor; 1518 1519 for (i = 0; i < c->count; i++) { 1520 struct v4l2_ctrl *ctr; 1521 1522 ctrl.id = c->controls[i].id; 1523 ctrl.value = c->controls[i].value; 1524 switch (ctrl.id) { 1525 case V4L2_CID_EXPOSURE_ABSOLUTE: 1526 case V4L2_CID_EXPOSURE_AUTO: 1527 case V4L2_CID_EXPOSURE_METERING: 1528 case V4L2_CID_IRIS_ABSOLUTE: 1529 case V4L2_CID_VCM_TIMING: 1530 case V4L2_CID_VCM_SLEW: 1531 case V4L2_CID_3A_LOCK: 1532 case V4L2_CID_TEST_PATTERN: 1533 case V4L2_CID_TEST_PATTERN_COLOR_R: 1534 case V4L2_CID_TEST_PATTERN_COLOR_GR: 1535 case V4L2_CID_TEST_PATTERN_COLOR_GB: 1536 case V4L2_CID_TEST_PATTERN_COLOR_B: 1537 ret = v4l2_s_ctrl(NULL, 1538 isp->inputs[asd->input_curr].camera-> 1539 ctrl_handler, &ctrl); 1540 break; 1541 case V4L2_CID_FOCUS_ABSOLUTE: 1542 case V4L2_CID_FOCUS_RELATIVE: 1543 case V4L2_CID_FOCUS_STATUS: 1544 case V4L2_CID_FOCUS_AUTO: 1545 if (motor) 1546 ret = v4l2_s_ctrl(NULL, motor->ctrl_handler, 1547 &ctrl); 1548 else 1549 ret = v4l2_s_ctrl(NULL, 1550 isp->inputs[asd->input_curr]. 1551 camera->ctrl_handler, &ctrl); 1552 break; 1553 case V4L2_CID_FLASH_STATUS: 1554 case V4L2_CID_FLASH_INTENSITY: 1555 case V4L2_CID_FLASH_TORCH_INTENSITY: 1556 case V4L2_CID_FLASH_INDICATOR_INTENSITY: 1557 case V4L2_CID_FLASH_TIMEOUT: 1558 case V4L2_CID_FLASH_STROBE: 1559 case V4L2_CID_FLASH_MODE: 1560 case V4L2_CID_FLASH_STATUS_REGISTER: 1561 if (isp->flash) { 1562 ret = 1563 v4l2_s_ctrl(NULL, isp->flash->ctrl_handler, 1564 &ctrl); 1565 /* 1566 * When flash mode is changed we need to reset 1567 * flash state 1568 */ 1569 if (ctrl.id == V4L2_CID_FLASH_MODE) { 1570 asd->params.flash_state = 1571 ATOMISP_FLASH_IDLE; 1572 asd->params.num_flash_frames = 0; 1573 } 1574 } 1575 break; 1576 case V4L2_CID_ZOOM_ABSOLUTE: 1577 ret = atomisp_digital_zoom(asd, 1, &ctrl.value); 1578 break; 1579 default: 1580 ctr = v4l2_ctrl_find(&asd->ctrl_handler, ctrl.id); 1581 if (ctr) 1582 ret = v4l2_ctrl_s_ctrl(ctr, ctrl.value); 1583 else 1584 ret = -EINVAL; 1585 } 1586 1587 if (ret) { 1588 c->error_idx = i; 1589 break; 1590 } 1591 c->controls[i].value = ctrl.value; 1592 } 1593 return ret; 1594 } 1595 1596 /* This ioctl allows the application to set multiple controls by class */ 1597 static int atomisp_s_ext_ctrls(struct file *file, void *fh, 1598 struct v4l2_ext_controls *c) 1599 { 1600 struct v4l2_control ctrl; 1601 int i, ret = 0; 1602 1603 /* 1604 * input_lock is not need for the Camera related IOCTLs 1605 * The input_lock downgrade the FPS of 3A 1606 */ 1607 ret = atomisp_camera_s_ext_ctrls(file, fh, c); 1608 if (ret != -EINVAL) 1609 return ret; 1610 1611 for (i = 0; i < c->count; i++) { 1612 ctrl.id = c->controls[i].id; 1613 ctrl.value = c->controls[i].value; 1614 ret = atomisp_s_ctrl(file, fh, &ctrl); 1615 c->controls[i].value = ctrl.value; 1616 if (ret) { 1617 c->error_idx = i; 1618 break; 1619 } 1620 } 1621 return ret; 1622 } 1623 1624 /* 1625 * vidioc_g/s_param are used to switch isp running mode 1626 */ 1627 static int atomisp_g_parm(struct file *file, void *fh, 1628 struct v4l2_streamparm *parm) 1629 { 1630 struct video_device *vdev = video_devdata(file); 1631 struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd; 1632 struct atomisp_device *isp = video_get_drvdata(vdev); 1633 1634 if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { 1635 dev_err(isp->dev, "unsupported v4l2 buf type\n"); 1636 return -EINVAL; 1637 } 1638 1639 parm->parm.capture.capturemode = asd->run_mode->val; 1640 1641 return 0; 1642 } 1643 1644 static int atomisp_s_parm(struct file *file, void *fh, 1645 struct v4l2_streamparm *parm) 1646 { 1647 struct video_device *vdev = video_devdata(file); 1648 struct atomisp_device *isp = video_get_drvdata(vdev); 1649 struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd; 1650 int mode; 1651 int rval; 1652 int fps; 1653 1654 if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { 1655 dev_err(isp->dev, "unsupported v4l2 buf type\n"); 1656 return -EINVAL; 1657 } 1658 1659 asd->high_speed_mode = false; 1660 switch (parm->parm.capture.capturemode) { 1661 case CI_MODE_NONE: { 1662 struct v4l2_subdev_frame_interval fi = {0}; 1663 1664 fi.interval = parm->parm.capture.timeperframe; 1665 1666 rval = v4l2_subdev_call(isp->inputs[asd->input_curr].camera, 1667 video, s_frame_interval, &fi); 1668 if (!rval) 1669 parm->parm.capture.timeperframe = fi.interval; 1670 1671 if (fi.interval.numerator != 0) { 1672 fps = fi.interval.denominator / fi.interval.numerator; 1673 if (fps > 30) 1674 asd->high_speed_mode = true; 1675 } 1676 1677 return rval == -ENOIOCTLCMD ? 0 : rval; 1678 } 1679 case CI_MODE_VIDEO: 1680 mode = ATOMISP_RUN_MODE_VIDEO; 1681 break; 1682 case CI_MODE_STILL_CAPTURE: 1683 mode = ATOMISP_RUN_MODE_STILL_CAPTURE; 1684 break; 1685 case CI_MODE_PREVIEW: 1686 mode = ATOMISP_RUN_MODE_PREVIEW; 1687 break; 1688 default: 1689 return -EINVAL; 1690 } 1691 1692 rval = v4l2_ctrl_s_ctrl(asd->run_mode, mode); 1693 1694 return rval == -ENOIOCTLCMD ? 0 : rval; 1695 } 1696 1697 static long atomisp_vidioc_default(struct file *file, void *fh, 1698 bool valid_prio, unsigned int cmd, void *arg) 1699 { 1700 struct video_device *vdev = video_devdata(file); 1701 struct atomisp_device *isp = video_get_drvdata(vdev); 1702 struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd; 1703 int err; 1704 1705 switch (cmd) { 1706 case ATOMISP_IOC_S_SENSOR_RUNMODE: 1707 if (IS_ISP2401) 1708 err = atomisp_set_sensor_runmode(asd, arg); 1709 else 1710 err = -EINVAL; 1711 break; 1712 1713 case ATOMISP_IOC_G_XNR: 1714 err = atomisp_xnr(asd, 0, arg); 1715 break; 1716 1717 case ATOMISP_IOC_S_XNR: 1718 err = atomisp_xnr(asd, 1, arg); 1719 break; 1720 1721 case ATOMISP_IOC_G_NR: 1722 err = atomisp_nr(asd, 0, arg); 1723 break; 1724 1725 case ATOMISP_IOC_S_NR: 1726 err = atomisp_nr(asd, 1, arg); 1727 break; 1728 1729 case ATOMISP_IOC_G_TNR: 1730 err = atomisp_tnr(asd, 0, arg); 1731 break; 1732 1733 case ATOMISP_IOC_S_TNR: 1734 err = atomisp_tnr(asd, 1, arg); 1735 break; 1736 1737 case ATOMISP_IOC_G_BLACK_LEVEL_COMP: 1738 err = atomisp_black_level(asd, 0, arg); 1739 break; 1740 1741 case ATOMISP_IOC_S_BLACK_LEVEL_COMP: 1742 err = atomisp_black_level(asd, 1, arg); 1743 break; 1744 1745 case ATOMISP_IOC_G_EE: 1746 err = atomisp_ee(asd, 0, arg); 1747 break; 1748 1749 case ATOMISP_IOC_S_EE: 1750 err = atomisp_ee(asd, 1, arg); 1751 break; 1752 1753 case ATOMISP_IOC_G_DIS_STAT: 1754 err = atomisp_get_dis_stat(asd, arg); 1755 break; 1756 1757 case ATOMISP_IOC_G_DVS2_BQ_RESOLUTIONS: 1758 err = atomisp_get_dvs2_bq_resolutions(asd, arg); 1759 break; 1760 1761 case ATOMISP_IOC_S_DIS_COEFS: 1762 err = atomisp_css_cp_dvs2_coefs(asd, arg, 1763 &asd->params.css_param, true); 1764 if (!err && arg) 1765 asd->params.css_update_params_needed = true; 1766 break; 1767 1768 case ATOMISP_IOC_S_DIS_VECTOR: 1769 err = atomisp_cp_dvs_6axis_config(asd, arg, 1770 &asd->params.css_param, true); 1771 if (!err && arg) 1772 asd->params.css_update_params_needed = true; 1773 break; 1774 1775 case ATOMISP_IOC_G_ISP_PARM: 1776 err = atomisp_param(asd, 0, arg); 1777 break; 1778 1779 case ATOMISP_IOC_S_ISP_PARM: 1780 err = atomisp_param(asd, 1, arg); 1781 break; 1782 1783 case ATOMISP_IOC_G_3A_STAT: 1784 err = atomisp_3a_stat(asd, 0, arg); 1785 break; 1786 1787 case ATOMISP_IOC_G_ISP_GAMMA: 1788 err = atomisp_gamma(asd, 0, arg); 1789 break; 1790 1791 case ATOMISP_IOC_S_ISP_GAMMA: 1792 err = atomisp_gamma(asd, 1, arg); 1793 break; 1794 1795 case ATOMISP_IOC_G_ISP_GDC_TAB: 1796 err = atomisp_gdc_cac_table(asd, 0, arg); 1797 break; 1798 1799 case ATOMISP_IOC_S_ISP_GDC_TAB: 1800 err = atomisp_gdc_cac_table(asd, 1, arg); 1801 break; 1802 1803 case ATOMISP_IOC_G_ISP_MACC: 1804 err = atomisp_macc_table(asd, 0, arg); 1805 break; 1806 1807 case ATOMISP_IOC_S_ISP_MACC: 1808 err = atomisp_macc_table(asd, 1, arg); 1809 break; 1810 1811 case ATOMISP_IOC_G_ISP_BAD_PIXEL_DETECTION: 1812 err = atomisp_bad_pixel_param(asd, 0, arg); 1813 break; 1814 1815 case ATOMISP_IOC_S_ISP_BAD_PIXEL_DETECTION: 1816 err = atomisp_bad_pixel_param(asd, 1, arg); 1817 break; 1818 1819 case ATOMISP_IOC_G_ISP_FALSE_COLOR_CORRECTION: 1820 err = atomisp_false_color_param(asd, 0, arg); 1821 break; 1822 1823 case ATOMISP_IOC_S_ISP_FALSE_COLOR_CORRECTION: 1824 err = atomisp_false_color_param(asd, 1, arg); 1825 break; 1826 1827 case ATOMISP_IOC_G_ISP_CTC: 1828 err = atomisp_ctc(asd, 0, arg); 1829 break; 1830 1831 case ATOMISP_IOC_S_ISP_CTC: 1832 err = atomisp_ctc(asd, 1, arg); 1833 break; 1834 1835 case ATOMISP_IOC_G_ISP_WHITE_BALANCE: 1836 err = atomisp_white_balance_param(asd, 0, arg); 1837 break; 1838 1839 case ATOMISP_IOC_S_ISP_WHITE_BALANCE: 1840 err = atomisp_white_balance_param(asd, 1, arg); 1841 break; 1842 1843 case ATOMISP_IOC_G_3A_CONFIG: 1844 err = atomisp_3a_config_param(asd, 0, arg); 1845 break; 1846 1847 case ATOMISP_IOC_S_3A_CONFIG: 1848 err = atomisp_3a_config_param(asd, 1, arg); 1849 break; 1850 1851 case ATOMISP_IOC_S_ISP_FPN_TABLE: 1852 err = atomisp_fixed_pattern_table(asd, arg); 1853 break; 1854 1855 case ATOMISP_IOC_S_EXPOSURE: 1856 err = v4l2_subdev_call(isp->inputs[asd->input_curr].camera, 1857 core, ioctl, cmd, arg); 1858 break; 1859 1860 case ATOMISP_IOC_S_ISP_SHD_TAB: 1861 err = atomisp_set_shading_table(asd, arg); 1862 break; 1863 1864 case ATOMISP_IOC_G_ISP_GAMMA_CORRECTION: 1865 err = atomisp_gamma_correction(asd, 0, arg); 1866 break; 1867 1868 case ATOMISP_IOC_S_ISP_GAMMA_CORRECTION: 1869 err = atomisp_gamma_correction(asd, 1, arg); 1870 break; 1871 1872 case ATOMISP_IOC_S_PARAMETERS: 1873 err = atomisp_set_parameters(vdev, arg); 1874 break; 1875 1876 case ATOMISP_IOC_EXT_ISP_CTRL: 1877 err = v4l2_subdev_call(isp->inputs[asd->input_curr].camera, 1878 core, ioctl, cmd, arg); 1879 break; 1880 case ATOMISP_IOC_EXP_ID_UNLOCK: 1881 err = atomisp_exp_id_unlock(asd, arg); 1882 break; 1883 case ATOMISP_IOC_EXP_ID_CAPTURE: 1884 err = atomisp_exp_id_capture(asd, arg); 1885 break; 1886 case ATOMISP_IOC_S_ENABLE_DZ_CAPT_PIPE: 1887 err = atomisp_enable_dz_capt_pipe(asd, arg); 1888 break; 1889 case ATOMISP_IOC_G_FORMATS_CONFIG: 1890 err = atomisp_formats(asd, 0, arg); 1891 break; 1892 1893 case ATOMISP_IOC_S_FORMATS_CONFIG: 1894 err = atomisp_formats(asd, 1, arg); 1895 break; 1896 case ATOMISP_IOC_INJECT_A_FAKE_EVENT: 1897 err = atomisp_inject_a_fake_event(asd, arg); 1898 break; 1899 case ATOMISP_IOC_S_ARRAY_RESOLUTION: 1900 err = atomisp_set_array_res(asd, arg); 1901 break; 1902 default: 1903 err = -EINVAL; 1904 break; 1905 } 1906 1907 return err; 1908 } 1909 1910 const struct v4l2_ioctl_ops atomisp_ioctl_ops = { 1911 .vidioc_querycap = atomisp_querycap, 1912 .vidioc_enum_input = atomisp_enum_input, 1913 .vidioc_g_input = atomisp_g_input, 1914 .vidioc_s_input = atomisp_s_input, 1915 .vidioc_queryctrl = atomisp_queryctl, 1916 .vidioc_s_ctrl = atomisp_s_ctrl, 1917 .vidioc_g_ctrl = atomisp_g_ctrl, 1918 .vidioc_s_ext_ctrls = atomisp_s_ext_ctrls, 1919 .vidioc_g_ext_ctrls = atomisp_g_ext_ctrls, 1920 .vidioc_enum_framesizes = atomisp_enum_framesizes, 1921 .vidioc_enum_frameintervals = atomisp_enum_frameintervals, 1922 .vidioc_enum_fmt_vid_cap = atomisp_enum_fmt_cap, 1923 .vidioc_try_fmt_vid_cap = atomisp_try_fmt_cap, 1924 .vidioc_g_fmt_vid_cap = atomisp_g_fmt_cap, 1925 .vidioc_s_fmt_vid_cap = atomisp_s_fmt_cap, 1926 .vidioc_reqbufs = vb2_ioctl_reqbufs, 1927 .vidioc_querybuf = vb2_ioctl_querybuf, 1928 .vidioc_qbuf = atomisp_qbuf_wrapper, 1929 .vidioc_dqbuf = atomisp_dqbuf_wrapper, 1930 .vidioc_streamon = vb2_ioctl_streamon, 1931 .vidioc_streamoff = vb2_ioctl_streamoff, 1932 .vidioc_default = atomisp_vidioc_default, 1933 .vidioc_s_parm = atomisp_s_parm, 1934 .vidioc_g_parm = atomisp_g_parm, 1935 }; 1936