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 .code = input->code, 711 }; 712 int ret; 713 714 ret = v4l2_subdev_call(input->camera, pad, enum_frame_size, NULL, &fse); 715 if (ret) 716 return ret; 717 718 fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; 719 fsize->discrete.width = fse.max_width - pad_w; 720 fsize->discrete.height = fse.max_height - pad_h; 721 722 return 0; 723 } 724 725 static int atomisp_enum_frameintervals(struct file *file, void *priv, 726 struct v4l2_frmivalenum *fival) 727 { 728 struct video_device *vdev = video_devdata(file); 729 struct atomisp_device *isp = video_get_drvdata(vdev); 730 struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd; 731 struct v4l2_subdev_frame_interval_enum fie = { 732 .code = atomisp_in_fmt_conv[0].code, 733 .index = fival->index, 734 .width = fival->width, 735 .height = fival->height, 736 .which = V4L2_SUBDEV_FORMAT_ACTIVE, 737 }; 738 int ret; 739 740 ret = v4l2_subdev_call(isp->inputs[asd->input_curr].camera, 741 pad, enum_frame_interval, NULL, 742 &fie); 743 if (ret) 744 return ret; 745 746 fival->type = V4L2_FRMIVAL_TYPE_DISCRETE; 747 fival->discrete = fie.interval; 748 749 return ret; 750 } 751 752 static int atomisp_enum_fmt_cap(struct file *file, void *fh, 753 struct v4l2_fmtdesc *f) 754 { 755 struct video_device *vdev = video_devdata(file); 756 struct atomisp_device *isp = video_get_drvdata(vdev); 757 struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd; 758 struct v4l2_subdev_mbus_code_enum code = { 759 .which = V4L2_SUBDEV_FORMAT_ACTIVE, 760 }; 761 const struct atomisp_format_bridge *format; 762 struct v4l2_subdev *camera; 763 unsigned int i, fi = 0; 764 int rval; 765 766 camera = isp->inputs[asd->input_curr].camera; 767 if(!camera) { 768 dev_err(isp->dev, "%s(): camera is NULL, device is %s\n", 769 __func__, vdev->name); 770 return -EINVAL; 771 } 772 773 rval = v4l2_subdev_call(camera, pad, enum_mbus_code, NULL, &code); 774 if (rval == -ENOIOCTLCMD) { 775 dev_warn(isp->dev, 776 "enum_mbus_code pad op not supported by %s. Please fix your sensor driver!\n", 777 camera->name); 778 } 779 780 if (rval) 781 return rval; 782 783 for (i = 0; i < ARRAY_SIZE(atomisp_output_fmts); i++) { 784 format = &atomisp_output_fmts[i]; 785 786 /* 787 * Is the atomisp-supported format is valid for the 788 * sensor (configuration)? If not, skip it. 789 * 790 * FIXME: fix the pipeline to allow sensor format too. 791 */ 792 if (format->sh_fmt == IA_CSS_FRAME_FORMAT_RAW) 793 continue; 794 795 /* Found a match. Now let's pick f->index'th one. */ 796 if (fi < f->index) { 797 fi++; 798 continue; 799 } 800 801 strscpy(f->description, format->description, 802 sizeof(f->description)); 803 f->pixelformat = format->pixelformat; 804 return 0; 805 } 806 807 return -EINVAL; 808 } 809 810 /* This function looks up the closest available resolution. */ 811 static int atomisp_try_fmt_cap(struct file *file, void *fh, 812 struct v4l2_format *f) 813 { 814 struct video_device *vdev = video_devdata(file); 815 struct atomisp_device *isp = video_get_drvdata(vdev); 816 817 return atomisp_try_fmt(isp, &f->fmt.pix, NULL, NULL); 818 } 819 820 static int atomisp_g_fmt_cap(struct file *file, void *fh, 821 struct v4l2_format *f) 822 { 823 struct video_device *vdev = video_devdata(file); 824 struct atomisp_video_pipe *pipe; 825 826 pipe = atomisp_to_video_pipe(vdev); 827 828 f->fmt.pix = pipe->pix; 829 830 /* If s_fmt was issued, just return whatever is was previouly set */ 831 if (f->fmt.pix.sizeimage) 832 return 0; 833 834 f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420; 835 f->fmt.pix.width = 10000; 836 f->fmt.pix.height = 10000; 837 838 return atomisp_try_fmt_cap(file, fh, f); 839 } 840 841 int atomisp_alloc_css_stat_bufs(struct atomisp_sub_device *asd, 842 uint16_t stream_id) 843 { 844 struct atomisp_device *isp = asd->isp; 845 struct atomisp_s3a_buf *s3a_buf = NULL, *_s3a_buf; 846 struct atomisp_dis_buf *dis_buf = NULL, *_dis_buf; 847 struct atomisp_metadata_buf *md_buf = NULL, *_md_buf; 848 int count; 849 struct ia_css_dvs_grid_info *dvs_grid_info = 850 atomisp_css_get_dvs_grid_info(&asd->params.curr_grid_info); 851 unsigned int i; 852 853 if (list_empty(&asd->s3a_stats) && 854 asd->params.curr_grid_info.s3a_grid.enable) { 855 count = ATOMISP_CSS_Q_DEPTH + 856 ATOMISP_S3A_BUF_QUEUE_DEPTH_FOR_HAL; 857 dev_dbg(isp->dev, "allocating %d 3a buffers\n", count); 858 while (count--) { 859 s3a_buf = kzalloc(sizeof(struct atomisp_s3a_buf), GFP_KERNEL); 860 if (!s3a_buf) 861 goto error; 862 863 if (atomisp_css_allocate_stat_buffers( 864 asd, stream_id, s3a_buf, NULL, NULL)) { 865 kfree(s3a_buf); 866 goto error; 867 } 868 869 list_add_tail(&s3a_buf->list, &asd->s3a_stats); 870 } 871 } 872 873 if (list_empty(&asd->dis_stats) && dvs_grid_info && 874 dvs_grid_info->enable) { 875 count = ATOMISP_CSS_Q_DEPTH + 1; 876 dev_dbg(isp->dev, "allocating %d dis buffers\n", count); 877 while (count--) { 878 dis_buf = kzalloc(sizeof(struct atomisp_dis_buf), GFP_KERNEL); 879 if (!dis_buf) 880 goto error; 881 if (atomisp_css_allocate_stat_buffers( 882 asd, stream_id, NULL, dis_buf, NULL)) { 883 kfree(dis_buf); 884 goto error; 885 } 886 887 list_add_tail(&dis_buf->list, &asd->dis_stats); 888 } 889 } 890 891 for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) { 892 if (list_empty(&asd->metadata[i]) && 893 list_empty(&asd->metadata_ready[i]) && 894 list_empty(&asd->metadata_in_css[i])) { 895 count = ATOMISP_CSS_Q_DEPTH + 896 ATOMISP_METADATA_QUEUE_DEPTH_FOR_HAL; 897 dev_dbg(isp->dev, "allocating %d metadata buffers for type %d\n", 898 count, i); 899 while (count--) { 900 md_buf = kzalloc(sizeof(struct atomisp_metadata_buf), 901 GFP_KERNEL); 902 if (!md_buf) 903 goto error; 904 905 if (atomisp_css_allocate_stat_buffers( 906 asd, stream_id, NULL, NULL, md_buf)) { 907 kfree(md_buf); 908 goto error; 909 } 910 list_add_tail(&md_buf->list, &asd->metadata[i]); 911 } 912 } 913 } 914 return 0; 915 916 error: 917 dev_err(isp->dev, "failed to allocate statistics buffers\n"); 918 919 list_for_each_entry_safe(dis_buf, _dis_buf, &asd->dis_stats, list) { 920 atomisp_css_free_dis_buffer(dis_buf); 921 list_del(&dis_buf->list); 922 kfree(dis_buf); 923 } 924 925 list_for_each_entry_safe(s3a_buf, _s3a_buf, &asd->s3a_stats, list) { 926 atomisp_css_free_3a_buffer(s3a_buf); 927 list_del(&s3a_buf->list); 928 kfree(s3a_buf); 929 } 930 931 for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) { 932 list_for_each_entry_safe(md_buf, _md_buf, &asd->metadata[i], 933 list) { 934 atomisp_css_free_metadata_buffer(md_buf); 935 list_del(&md_buf->list); 936 kfree(md_buf); 937 } 938 } 939 return -ENOMEM; 940 } 941 942 /* 943 * FIXME the abuse of buf->reserved2 in the qbuf and dqbuf wrappers comes from 944 * the original atomisp buffer handling and should be replaced with proper V4L2 945 * per frame parameters use. 946 * 947 * Once this is fixed these wrappers can be removed, replacing them with direct 948 * calls to vb2_ioctl_[d]qbuf(). 949 */ 950 static int atomisp_qbuf_wrapper(struct file *file, void *fh, struct v4l2_buffer *buf) 951 { 952 struct video_device *vdev = video_devdata(file); 953 struct atomisp_device *isp = video_get_drvdata(vdev); 954 struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev); 955 956 if (buf->index >= vdev->queue->num_buffers) 957 return -EINVAL; 958 959 if (buf->reserved2 & ATOMISP_BUFFER_HAS_PER_FRAME_SETTING) { 960 /* this buffer will have a per-frame parameter */ 961 pipe->frame_request_config_id[buf->index] = buf->reserved2 & 962 ~ATOMISP_BUFFER_HAS_PER_FRAME_SETTING; 963 dev_dbg(isp->dev, 964 "This buffer requires per_frame setting which has isp_config_id %d\n", 965 pipe->frame_request_config_id[buf->index]); 966 } else { 967 pipe->frame_request_config_id[buf->index] = 0; 968 } 969 970 return vb2_ioctl_qbuf(file, fh, buf); 971 } 972 973 static int atomisp_dqbuf_wrapper(struct file *file, void *fh, struct v4l2_buffer *buf) 974 { 975 struct video_device *vdev = video_devdata(file); 976 struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev); 977 struct atomisp_sub_device *asd = pipe->asd; 978 struct atomisp_device *isp = video_get_drvdata(vdev); 979 struct ia_css_frame *frame; 980 struct vb2_buffer *vb; 981 int ret; 982 983 ret = vb2_ioctl_dqbuf(file, fh, buf); 984 if (ret) 985 return ret; 986 987 vb = pipe->vb_queue.bufs[buf->index]; 988 frame = vb_to_frame(vb); 989 990 buf->reserved = asd->frame_status[buf->index]; 991 992 /* 993 * Hack: 994 * Currently frame_status in the enum type which takes no more lower 995 * 8 bit. 996 * use bit[31:16] for exp_id as it is only in the range of 1~255 997 */ 998 buf->reserved &= 0x0000ffff; 999 if (!(buf->flags & V4L2_BUF_FLAG_ERROR)) 1000 buf->reserved |= frame->exp_id; 1001 buf->reserved2 = pipe->frame_config_id[buf->index]; 1002 1003 dev_dbg(isp->dev, 1004 "dqbuf buffer %d (%s) with exp_id %d, isp_config_id %d\n", 1005 buf->index, vdev->name, buf->reserved >> 16, buf->reserved2); 1006 return 0; 1007 } 1008 1009 /* Input system HW workaround */ 1010 /* Input system address translation corrupts burst during */ 1011 /* invalidate. SW workaround for this is to set burst length */ 1012 /* manually to 128 in case of 13MPx snapshot and to 1 otherwise. */ 1013 static void atomisp_dma_burst_len_cfg(struct atomisp_sub_device *asd) 1014 { 1015 struct v4l2_mbus_framefmt *sink; 1016 1017 sink = atomisp_subdev_get_ffmt(&asd->subdev, NULL, 1018 V4L2_SUBDEV_FORMAT_ACTIVE, 1019 ATOMISP_SUBDEV_PAD_SINK); 1020 1021 if (sink->width * sink->height >= 4096 * 3072) 1022 atomisp_css2_hw_store_32(DMA_BURST_SIZE_REG, 0x7F); 1023 else 1024 atomisp_css2_hw_store_32(DMA_BURST_SIZE_REG, 0x00); 1025 } 1026 1027 int atomisp_start_streaming(struct vb2_queue *vq, unsigned int count) 1028 { 1029 struct atomisp_video_pipe *pipe = vq_to_pipe(vq); 1030 struct atomisp_sub_device *asd = pipe->asd; 1031 struct atomisp_device *isp = asd->isp; 1032 struct pci_dev *pdev = to_pci_dev(isp->dev); 1033 unsigned long irqflags; 1034 int ret; 1035 1036 dev_dbg(isp->dev, "Start stream\n"); 1037 1038 mutex_lock(&isp->mutex); 1039 1040 ret = atomisp_pipe_check(pipe, false); 1041 if (ret) 1042 goto out_unlock; 1043 1044 /* Input system HW workaround */ 1045 atomisp_dma_burst_len_cfg(asd); 1046 1047 /* Invalidate caches. FIXME: should flush only necessary buffers */ 1048 wbinvd(); 1049 1050 if (asd->params.css_update_params_needed) { 1051 atomisp_apply_css_parameters(asd, &asd->params.css_param); 1052 if (asd->params.css_param.update_flag.dz_config) 1053 asd->params.config.dz_config = &asd->params.css_param.dz_config; 1054 atomisp_css_update_isp_params(asd); 1055 asd->params.css_update_params_needed = false; 1056 memset(&asd->params.css_param.update_flag, 0, 1057 sizeof(struct atomisp_parameters)); 1058 } 1059 asd->params.dvs_6axis = NULL; 1060 1061 ret = atomisp_css_start(asd); 1062 if (ret) { 1063 atomisp_flush_video_pipe(pipe, VB2_BUF_STATE_QUEUED, true); 1064 goto out_unlock; 1065 } 1066 1067 spin_lock_irqsave(&isp->lock, irqflags); 1068 asd->streaming = true; 1069 spin_unlock_irqrestore(&isp->lock, irqflags); 1070 atomic_set(&asd->sof_count, -1); 1071 atomic_set(&asd->sequence, -1); 1072 atomic_set(&asd->sequence_temp, -1); 1073 1074 asd->params.dis_proj_data_valid = false; 1075 asd->latest_preview_exp_id = 0; 1076 asd->postview_exp_id = 1; 1077 asd->preview_exp_id = 1; 1078 1079 /* handle per_frame_setting parameter and buffers */ 1080 atomisp_handle_parameter_and_buffer(pipe); 1081 1082 atomisp_qbuffers_to_css(asd); 1083 1084 if (isp->flash) { 1085 asd->params.num_flash_frames = 0; 1086 asd->params.flash_state = ATOMISP_FLASH_IDLE; 1087 atomisp_setup_flash(asd); 1088 } 1089 1090 atomisp_css_irq_enable(isp, IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF, 1091 atomisp_css_valid_sof(isp)); 1092 atomisp_csi2_configure(asd); 1093 1094 if (atomisp_freq_scaling(isp, ATOMISP_DFS_MODE_AUTO, false) < 0) 1095 dev_dbg(isp->dev, "DFS auto mode failed!\n"); 1096 1097 /* Enable the CSI interface on ANN B0/K0 */ 1098 if (isp->media_dev.hw_revision >= ((ATOMISP_HW_REVISION_ISP2401 << 1099 ATOMISP_HW_REVISION_SHIFT) | ATOMISP_HW_STEPPING_B0)) { 1100 pci_write_config_word(pdev, MRFLD_PCI_CSI_CONTROL, 1101 isp->saved_regs.csi_control | MRFLD_PCI_CSI_CONTROL_CSI_READY); 1102 } 1103 1104 /* stream on the sensor */ 1105 ret = v4l2_subdev_call(isp->inputs[asd->input_curr].camera, 1106 video, s_stream, 1); 1107 if (ret) { 1108 dev_err(isp->dev, "Starting sensor stream failed: %d\n", ret); 1109 spin_lock_irqsave(&isp->lock, irqflags); 1110 asd->streaming = false; 1111 spin_unlock_irqrestore(&isp->lock, irqflags); 1112 ret = -EINVAL; 1113 goto out_unlock; 1114 } 1115 1116 out_unlock: 1117 mutex_unlock(&isp->mutex); 1118 return ret; 1119 } 1120 1121 void atomisp_stop_streaming(struct vb2_queue *vq) 1122 { 1123 struct atomisp_video_pipe *pipe = vq_to_pipe(vq); 1124 struct atomisp_sub_device *asd = pipe->asd; 1125 struct atomisp_device *isp = asd->isp; 1126 struct pci_dev *pdev = to_pci_dev(isp->dev); 1127 unsigned long flags; 1128 int ret; 1129 1130 dev_dbg(isp->dev, "Stop stream\n"); 1131 1132 mutex_lock(&isp->mutex); 1133 /* 1134 * There is no guarantee that the buffers queued to / owned by the ISP 1135 * will properly be returned to the queue when stopping. Set a flag to 1136 * avoid new buffers getting queued and then wait for all the current 1137 * buffers to finish. 1138 */ 1139 pipe->stopping = true; 1140 mutex_unlock(&isp->mutex); 1141 /* wait max 1 second */ 1142 ret = wait_event_timeout(pipe->vb_queue.done_wq, 1143 atomisp_buffers_in_css(pipe) == 0, HZ); 1144 mutex_lock(&isp->mutex); 1145 pipe->stopping = false; 1146 if (ret == 0) 1147 dev_warn(isp->dev, "Warning timeout waiting for CSS to return buffers\n"); 1148 1149 spin_lock_irqsave(&isp->lock, flags); 1150 asd->streaming = false; 1151 spin_unlock_irqrestore(&isp->lock, flags); 1152 1153 atomisp_clear_css_buffer_counters(asd); 1154 atomisp_css_irq_enable(isp, IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF, false); 1155 1156 atomisp_css_stop(asd, false); 1157 1158 atomisp_flush_video_pipe(pipe, VB2_BUF_STATE_ERROR, true); 1159 1160 atomisp_subdev_cleanup_pending_events(asd); 1161 1162 ret = v4l2_subdev_call(isp->inputs[asd->input_curr].camera, 1163 video, s_stream, 0); 1164 if (ret) 1165 dev_warn(isp->dev, "Stopping sensor stream failed: %d\n", ret); 1166 1167 if (isp->flash) { 1168 asd->params.num_flash_frames = 0; 1169 asd->params.flash_state = ATOMISP_FLASH_IDLE; 1170 } 1171 1172 /* Disable the CSI interface on ANN B0/K0 */ 1173 if (isp->media_dev.hw_revision >= ((ATOMISP_HW_REVISION_ISP2401 << 1174 ATOMISP_HW_REVISION_SHIFT) | ATOMISP_HW_STEPPING_B0)) { 1175 pci_write_config_word(pdev, MRFLD_PCI_CSI_CONTROL, 1176 isp->saved_regs.csi_control & ~MRFLD_PCI_CSI_CONTROL_CSI_READY); 1177 } 1178 1179 if (atomisp_freq_scaling(isp, ATOMISP_DFS_MODE_LOW, false)) 1180 dev_warn(isp->dev, "DFS failed.\n"); 1181 1182 /* 1183 * ISP work around, need to reset ISP to allow next stream on to work. 1184 * Streams have already been destroyed by atomisp_css_stop(). 1185 * Disable PUNIT/ISP acknowlede/handshake - SRSE=3 and then reset. 1186 */ 1187 pci_write_config_dword(pdev, PCI_I_CONTROL, 1188 isp->saved_regs.i_control | MRFLD_PCI_I_CONTROL_SRSE_RESET_MASK); 1189 atomisp_reset(isp); 1190 1191 /* Streams were destroyed by atomisp_css_stop(), recreate them. */ 1192 ret = atomisp_create_pipes_stream(&isp->asd); 1193 if (ret) 1194 dev_warn(isp->dev, "Recreating streams failed: %d\n", ret); 1195 1196 mutex_unlock(&isp->mutex); 1197 } 1198 1199 /* 1200 * To get the current value of a control. 1201 * applications initialize the id field of a struct v4l2_control and 1202 * call this ioctl with a pointer to this structure 1203 */ 1204 static int atomisp_g_ctrl(struct file *file, void *fh, 1205 struct v4l2_control *control) 1206 { 1207 struct video_device *vdev = video_devdata(file); 1208 struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd; 1209 struct atomisp_device *isp = video_get_drvdata(vdev); 1210 int i, ret = -EINVAL; 1211 1212 for (i = 0; i < ctrls_num; i++) { 1213 if (ci_v4l2_controls[i].id == control->id) { 1214 ret = 0; 1215 break; 1216 } 1217 } 1218 1219 if (ret) 1220 return ret; 1221 1222 switch (control->id) { 1223 case V4L2_CID_IRIS_ABSOLUTE: 1224 case V4L2_CID_EXPOSURE_ABSOLUTE: 1225 case V4L2_CID_2A_STATUS: 1226 case V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE: 1227 case V4L2_CID_EXPOSURE: 1228 case V4L2_CID_EXPOSURE_AUTO: 1229 case V4L2_CID_SCENE_MODE: 1230 case V4L2_CID_ISO_SENSITIVITY: 1231 case V4L2_CID_ISO_SENSITIVITY_AUTO: 1232 case V4L2_CID_CONTRAST: 1233 case V4L2_CID_SATURATION: 1234 case V4L2_CID_SHARPNESS: 1235 case V4L2_CID_3A_LOCK: 1236 case V4L2_CID_EXPOSURE_ZONE_NUM: 1237 case V4L2_CID_TEST_PATTERN: 1238 case V4L2_CID_TEST_PATTERN_COLOR_R: 1239 case V4L2_CID_TEST_PATTERN_COLOR_GR: 1240 case V4L2_CID_TEST_PATTERN_COLOR_GB: 1241 case V4L2_CID_TEST_PATTERN_COLOR_B: 1242 return v4l2_g_ctrl(isp->inputs[asd->input_curr].camera-> 1243 ctrl_handler, control); 1244 case V4L2_CID_COLORFX: 1245 ret = atomisp_color_effect(asd, 0, &control->value); 1246 break; 1247 case V4L2_CID_ATOMISP_BAD_PIXEL_DETECTION: 1248 ret = atomisp_bad_pixel(asd, 0, &control->value); 1249 break; 1250 case V4L2_CID_ATOMISP_POSTPROCESS_GDC_CAC: 1251 ret = atomisp_gdc_cac(asd, 0, &control->value); 1252 break; 1253 case V4L2_CID_ATOMISP_VIDEO_STABLIZATION: 1254 ret = atomisp_video_stable(asd, 0, &control->value); 1255 break; 1256 case V4L2_CID_ATOMISP_FIXED_PATTERN_NR: 1257 ret = atomisp_fixed_pattern(asd, 0, &control->value); 1258 break; 1259 case V4L2_CID_ATOMISP_FALSE_COLOR_CORRECTION: 1260 ret = atomisp_false_color(asd, 0, &control->value); 1261 break; 1262 case V4L2_CID_ATOMISP_LOW_LIGHT: 1263 ret = atomisp_low_light(asd, 0, &control->value); 1264 break; 1265 default: 1266 ret = -EINVAL; 1267 break; 1268 } 1269 1270 return ret; 1271 } 1272 1273 /* 1274 * To change the value of a control. 1275 * applications initialize the id and value fields of a struct v4l2_control 1276 * and call this ioctl. 1277 */ 1278 static int atomisp_s_ctrl(struct file *file, void *fh, 1279 struct v4l2_control *control) 1280 { 1281 struct video_device *vdev = video_devdata(file); 1282 struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd; 1283 struct atomisp_device *isp = video_get_drvdata(vdev); 1284 int i, ret = -EINVAL; 1285 1286 for (i = 0; i < ctrls_num; i++) { 1287 if (ci_v4l2_controls[i].id == control->id) { 1288 ret = 0; 1289 break; 1290 } 1291 } 1292 1293 if (ret) 1294 return ret; 1295 1296 switch (control->id) { 1297 case V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE: 1298 case V4L2_CID_EXPOSURE: 1299 case V4L2_CID_EXPOSURE_AUTO: 1300 case V4L2_CID_EXPOSURE_AUTO_PRIORITY: 1301 case V4L2_CID_SCENE_MODE: 1302 case V4L2_CID_ISO_SENSITIVITY: 1303 case V4L2_CID_ISO_SENSITIVITY_AUTO: 1304 case V4L2_CID_POWER_LINE_FREQUENCY: 1305 case V4L2_CID_EXPOSURE_METERING: 1306 case V4L2_CID_CONTRAST: 1307 case V4L2_CID_SATURATION: 1308 case V4L2_CID_SHARPNESS: 1309 case V4L2_CID_3A_LOCK: 1310 case V4L2_CID_COLORFX_CBCR: 1311 case V4L2_CID_TEST_PATTERN: 1312 case V4L2_CID_TEST_PATTERN_COLOR_R: 1313 case V4L2_CID_TEST_PATTERN_COLOR_GR: 1314 case V4L2_CID_TEST_PATTERN_COLOR_GB: 1315 case V4L2_CID_TEST_PATTERN_COLOR_B: 1316 return v4l2_s_ctrl(NULL, 1317 isp->inputs[asd->input_curr].camera-> 1318 ctrl_handler, control); 1319 case V4L2_CID_COLORFX: 1320 ret = atomisp_color_effect(asd, 1, &control->value); 1321 break; 1322 case V4L2_CID_ATOMISP_BAD_PIXEL_DETECTION: 1323 ret = atomisp_bad_pixel(asd, 1, &control->value); 1324 break; 1325 case V4L2_CID_ATOMISP_POSTPROCESS_GDC_CAC: 1326 ret = atomisp_gdc_cac(asd, 1, &control->value); 1327 break; 1328 case V4L2_CID_ATOMISP_VIDEO_STABLIZATION: 1329 ret = atomisp_video_stable(asd, 1, &control->value); 1330 break; 1331 case V4L2_CID_ATOMISP_FIXED_PATTERN_NR: 1332 ret = atomisp_fixed_pattern(asd, 1, &control->value); 1333 break; 1334 case V4L2_CID_ATOMISP_FALSE_COLOR_CORRECTION: 1335 ret = atomisp_false_color(asd, 1, &control->value); 1336 break; 1337 case V4L2_CID_REQUEST_FLASH: 1338 ret = atomisp_flash_enable(asd, control->value); 1339 break; 1340 case V4L2_CID_ATOMISP_LOW_LIGHT: 1341 ret = atomisp_low_light(asd, 1, &control->value); 1342 break; 1343 default: 1344 ret = -EINVAL; 1345 break; 1346 } 1347 return ret; 1348 } 1349 1350 /* 1351 * To query the attributes of a control. 1352 * applications set the id field of a struct v4l2_queryctrl and call the 1353 * this ioctl with a pointer to this structure. The driver fills 1354 * the rest of the structure. 1355 */ 1356 static int atomisp_queryctl(struct file *file, void *fh, 1357 struct v4l2_queryctrl *qc) 1358 { 1359 int i, ret = -EINVAL; 1360 struct video_device *vdev = video_devdata(file); 1361 struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd; 1362 struct atomisp_device *isp = video_get_drvdata(vdev); 1363 1364 switch (qc->id) { 1365 case V4L2_CID_FOCUS_ABSOLUTE: 1366 case V4L2_CID_FOCUS_RELATIVE: 1367 case V4L2_CID_FOCUS_STATUS: 1368 if (!IS_ISP2401) { 1369 return v4l2_queryctrl(isp->inputs[asd->input_curr].camera-> 1370 ctrl_handler, qc); 1371 } 1372 /* ISP2401 */ 1373 if (isp->motor) 1374 return v4l2_queryctrl(isp->motor->ctrl_handler, qc); 1375 else 1376 return v4l2_queryctrl(isp->inputs[asd->input_curr]. 1377 camera->ctrl_handler, qc); 1378 } 1379 1380 if (qc->id & V4L2_CTRL_FLAG_NEXT_CTRL) 1381 return ret; 1382 1383 for (i = 0; i < ctrls_num; i++) { 1384 if (ci_v4l2_controls[i].id == qc->id) { 1385 memcpy(qc, &ci_v4l2_controls[i], 1386 sizeof(struct v4l2_queryctrl)); 1387 qc->reserved[0] = 0; 1388 ret = 0; 1389 break; 1390 } 1391 } 1392 if (ret != 0) 1393 qc->flags = V4L2_CTRL_FLAG_DISABLED; 1394 1395 return ret; 1396 } 1397 1398 static int atomisp_camera_g_ext_ctrls(struct file *file, void *fh, 1399 struct v4l2_ext_controls *c) 1400 { 1401 struct video_device *vdev = video_devdata(file); 1402 struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd; 1403 struct atomisp_device *isp = video_get_drvdata(vdev); 1404 struct v4l2_subdev *motor; 1405 struct v4l2_control ctrl; 1406 int i; 1407 int ret = 0; 1408 1409 if (!IS_ISP2401) 1410 motor = isp->inputs[asd->input_curr].motor; 1411 else 1412 motor = isp->motor; 1413 1414 for (i = 0; i < c->count; i++) { 1415 ctrl.id = c->controls[i].id; 1416 ctrl.value = c->controls[i].value; 1417 switch (ctrl.id) { 1418 case V4L2_CID_EXPOSURE_ABSOLUTE: 1419 case V4L2_CID_EXPOSURE_AUTO: 1420 case V4L2_CID_IRIS_ABSOLUTE: 1421 case V4L2_CID_3A_LOCK: 1422 case V4L2_CID_TEST_PATTERN: 1423 case V4L2_CID_TEST_PATTERN_COLOR_R: 1424 case V4L2_CID_TEST_PATTERN_COLOR_GR: 1425 case V4L2_CID_TEST_PATTERN_COLOR_GB: 1426 case V4L2_CID_TEST_PATTERN_COLOR_B: 1427 /* 1428 * Exposure related control will be handled by sensor 1429 * driver 1430 */ 1431 ret = 1432 v4l2_g_ctrl(isp->inputs[asd->input_curr].camera-> 1433 ctrl_handler, &ctrl); 1434 break; 1435 case V4L2_CID_FOCUS_ABSOLUTE: 1436 case V4L2_CID_FOCUS_RELATIVE: 1437 case V4L2_CID_FOCUS_STATUS: 1438 case V4L2_CID_FOCUS_AUTO: 1439 if (motor) 1440 ret = v4l2_g_ctrl(motor->ctrl_handler, &ctrl); 1441 break; 1442 case V4L2_CID_FLASH_STATUS: 1443 case V4L2_CID_FLASH_INTENSITY: 1444 case V4L2_CID_FLASH_TORCH_INTENSITY: 1445 case V4L2_CID_FLASH_INDICATOR_INTENSITY: 1446 case V4L2_CID_FLASH_TIMEOUT: 1447 case V4L2_CID_FLASH_STROBE: 1448 case V4L2_CID_FLASH_MODE: 1449 case V4L2_CID_FLASH_STATUS_REGISTER: 1450 if (isp->flash) 1451 ret = 1452 v4l2_g_ctrl(isp->flash->ctrl_handler, 1453 &ctrl); 1454 break; 1455 case V4L2_CID_ZOOM_ABSOLUTE: 1456 ret = atomisp_digital_zoom(asd, 0, &ctrl.value); 1457 break; 1458 case V4L2_CID_G_SKIP_FRAMES: 1459 ret = v4l2_subdev_call( 1460 isp->inputs[asd->input_curr].camera, 1461 sensor, g_skip_frames, (u32 *)&ctrl.value); 1462 break; 1463 default: 1464 ret = -EINVAL; 1465 } 1466 1467 if (ret) { 1468 c->error_idx = i; 1469 break; 1470 } 1471 c->controls[i].value = ctrl.value; 1472 } 1473 return ret; 1474 } 1475 1476 /* This ioctl allows the application to get multiple controls by class */ 1477 static int atomisp_g_ext_ctrls(struct file *file, void *fh, 1478 struct v4l2_ext_controls *c) 1479 { 1480 struct v4l2_control ctrl; 1481 int i, ret = 0; 1482 1483 /* 1484 * input_lock is not need for the Camera related IOCTLs 1485 * The input_lock downgrade the FPS of 3A 1486 */ 1487 ret = atomisp_camera_g_ext_ctrls(file, fh, c); 1488 if (ret != -EINVAL) 1489 return ret; 1490 1491 for (i = 0; i < c->count; i++) { 1492 ctrl.id = c->controls[i].id; 1493 ctrl.value = c->controls[i].value; 1494 ret = atomisp_g_ctrl(file, fh, &ctrl); 1495 c->controls[i].value = ctrl.value; 1496 if (ret) { 1497 c->error_idx = i; 1498 break; 1499 } 1500 } 1501 return ret; 1502 } 1503 1504 static int atomisp_camera_s_ext_ctrls(struct file *file, void *fh, 1505 struct v4l2_ext_controls *c) 1506 { 1507 struct video_device *vdev = video_devdata(file); 1508 struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd; 1509 struct atomisp_device *isp = video_get_drvdata(vdev); 1510 struct v4l2_subdev *motor; 1511 struct v4l2_control ctrl; 1512 int i; 1513 int ret = 0; 1514 1515 if (!IS_ISP2401) 1516 motor = isp->inputs[asd->input_curr].motor; 1517 else 1518 motor = isp->motor; 1519 1520 for (i = 0; i < c->count; i++) { 1521 struct v4l2_ctrl *ctr; 1522 1523 ctrl.id = c->controls[i].id; 1524 ctrl.value = c->controls[i].value; 1525 switch (ctrl.id) { 1526 case V4L2_CID_EXPOSURE_ABSOLUTE: 1527 case V4L2_CID_EXPOSURE_AUTO: 1528 case V4L2_CID_EXPOSURE_METERING: 1529 case V4L2_CID_IRIS_ABSOLUTE: 1530 case V4L2_CID_VCM_TIMING: 1531 case V4L2_CID_VCM_SLEW: 1532 case V4L2_CID_3A_LOCK: 1533 case V4L2_CID_TEST_PATTERN: 1534 case V4L2_CID_TEST_PATTERN_COLOR_R: 1535 case V4L2_CID_TEST_PATTERN_COLOR_GR: 1536 case V4L2_CID_TEST_PATTERN_COLOR_GB: 1537 case V4L2_CID_TEST_PATTERN_COLOR_B: 1538 ret = v4l2_s_ctrl(NULL, 1539 isp->inputs[asd->input_curr].camera-> 1540 ctrl_handler, &ctrl); 1541 break; 1542 case V4L2_CID_FOCUS_ABSOLUTE: 1543 case V4L2_CID_FOCUS_RELATIVE: 1544 case V4L2_CID_FOCUS_STATUS: 1545 case V4L2_CID_FOCUS_AUTO: 1546 if (motor) 1547 ret = v4l2_s_ctrl(NULL, motor->ctrl_handler, 1548 &ctrl); 1549 else 1550 ret = v4l2_s_ctrl(NULL, 1551 isp->inputs[asd->input_curr]. 1552 camera->ctrl_handler, &ctrl); 1553 break; 1554 case V4L2_CID_FLASH_STATUS: 1555 case V4L2_CID_FLASH_INTENSITY: 1556 case V4L2_CID_FLASH_TORCH_INTENSITY: 1557 case V4L2_CID_FLASH_INDICATOR_INTENSITY: 1558 case V4L2_CID_FLASH_TIMEOUT: 1559 case V4L2_CID_FLASH_STROBE: 1560 case V4L2_CID_FLASH_MODE: 1561 case V4L2_CID_FLASH_STATUS_REGISTER: 1562 if (isp->flash) { 1563 ret = 1564 v4l2_s_ctrl(NULL, isp->flash->ctrl_handler, 1565 &ctrl); 1566 /* 1567 * When flash mode is changed we need to reset 1568 * flash state 1569 */ 1570 if (ctrl.id == V4L2_CID_FLASH_MODE) { 1571 asd->params.flash_state = 1572 ATOMISP_FLASH_IDLE; 1573 asd->params.num_flash_frames = 0; 1574 } 1575 } 1576 break; 1577 case V4L2_CID_ZOOM_ABSOLUTE: 1578 ret = atomisp_digital_zoom(asd, 1, &ctrl.value); 1579 break; 1580 default: 1581 ctr = v4l2_ctrl_find(&asd->ctrl_handler, ctrl.id); 1582 if (ctr) 1583 ret = v4l2_ctrl_s_ctrl(ctr, ctrl.value); 1584 else 1585 ret = -EINVAL; 1586 } 1587 1588 if (ret) { 1589 c->error_idx = i; 1590 break; 1591 } 1592 c->controls[i].value = ctrl.value; 1593 } 1594 return ret; 1595 } 1596 1597 /* This ioctl allows the application to set multiple controls by class */ 1598 static int atomisp_s_ext_ctrls(struct file *file, void *fh, 1599 struct v4l2_ext_controls *c) 1600 { 1601 struct v4l2_control ctrl; 1602 int i, ret = 0; 1603 1604 /* 1605 * input_lock is not need for the Camera related IOCTLs 1606 * The input_lock downgrade the FPS of 3A 1607 */ 1608 ret = atomisp_camera_s_ext_ctrls(file, fh, c); 1609 if (ret != -EINVAL) 1610 return ret; 1611 1612 for (i = 0; i < c->count; i++) { 1613 ctrl.id = c->controls[i].id; 1614 ctrl.value = c->controls[i].value; 1615 ret = atomisp_s_ctrl(file, fh, &ctrl); 1616 c->controls[i].value = ctrl.value; 1617 if (ret) { 1618 c->error_idx = i; 1619 break; 1620 } 1621 } 1622 return ret; 1623 } 1624 1625 /* 1626 * vidioc_g/s_param are used to switch isp running mode 1627 */ 1628 static int atomisp_g_parm(struct file *file, void *fh, 1629 struct v4l2_streamparm *parm) 1630 { 1631 struct video_device *vdev = video_devdata(file); 1632 struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd; 1633 struct atomisp_device *isp = video_get_drvdata(vdev); 1634 1635 if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { 1636 dev_err(isp->dev, "unsupported v4l2 buf type\n"); 1637 return -EINVAL; 1638 } 1639 1640 parm->parm.capture.capturemode = asd->run_mode->val; 1641 1642 return 0; 1643 } 1644 1645 static int atomisp_s_parm(struct file *file, void *fh, 1646 struct v4l2_streamparm *parm) 1647 { 1648 struct video_device *vdev = video_devdata(file); 1649 struct atomisp_device *isp = video_get_drvdata(vdev); 1650 struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd; 1651 int mode; 1652 int rval; 1653 int fps; 1654 1655 if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { 1656 dev_err(isp->dev, "unsupported v4l2 buf type\n"); 1657 return -EINVAL; 1658 } 1659 1660 asd->high_speed_mode = false; 1661 switch (parm->parm.capture.capturemode) { 1662 case CI_MODE_NONE: { 1663 struct v4l2_subdev_frame_interval fi = {0}; 1664 1665 fi.interval = parm->parm.capture.timeperframe; 1666 1667 rval = v4l2_subdev_call(isp->inputs[asd->input_curr].camera, 1668 video, s_frame_interval, &fi); 1669 if (!rval) 1670 parm->parm.capture.timeperframe = fi.interval; 1671 1672 if (fi.interval.numerator != 0) { 1673 fps = fi.interval.denominator / fi.interval.numerator; 1674 if (fps > 30) 1675 asd->high_speed_mode = true; 1676 } 1677 1678 return rval == -ENOIOCTLCMD ? 0 : rval; 1679 } 1680 case CI_MODE_VIDEO: 1681 mode = ATOMISP_RUN_MODE_VIDEO; 1682 break; 1683 case CI_MODE_STILL_CAPTURE: 1684 mode = ATOMISP_RUN_MODE_STILL_CAPTURE; 1685 break; 1686 case CI_MODE_PREVIEW: 1687 mode = ATOMISP_RUN_MODE_PREVIEW; 1688 break; 1689 default: 1690 return -EINVAL; 1691 } 1692 1693 rval = v4l2_ctrl_s_ctrl(asd->run_mode, mode); 1694 1695 return rval == -ENOIOCTLCMD ? 0 : rval; 1696 } 1697 1698 static long atomisp_vidioc_default(struct file *file, void *fh, 1699 bool valid_prio, unsigned int cmd, void *arg) 1700 { 1701 struct video_device *vdev = video_devdata(file); 1702 struct atomisp_device *isp = video_get_drvdata(vdev); 1703 struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd; 1704 int err; 1705 1706 switch (cmd) { 1707 case ATOMISP_IOC_S_SENSOR_RUNMODE: 1708 if (IS_ISP2401) 1709 err = atomisp_set_sensor_runmode(asd, arg); 1710 else 1711 err = -EINVAL; 1712 break; 1713 1714 case ATOMISP_IOC_G_XNR: 1715 err = atomisp_xnr(asd, 0, arg); 1716 break; 1717 1718 case ATOMISP_IOC_S_XNR: 1719 err = atomisp_xnr(asd, 1, arg); 1720 break; 1721 1722 case ATOMISP_IOC_G_NR: 1723 err = atomisp_nr(asd, 0, arg); 1724 break; 1725 1726 case ATOMISP_IOC_S_NR: 1727 err = atomisp_nr(asd, 1, arg); 1728 break; 1729 1730 case ATOMISP_IOC_G_TNR: 1731 err = atomisp_tnr(asd, 0, arg); 1732 break; 1733 1734 case ATOMISP_IOC_S_TNR: 1735 err = atomisp_tnr(asd, 1, arg); 1736 break; 1737 1738 case ATOMISP_IOC_G_BLACK_LEVEL_COMP: 1739 err = atomisp_black_level(asd, 0, arg); 1740 break; 1741 1742 case ATOMISP_IOC_S_BLACK_LEVEL_COMP: 1743 err = atomisp_black_level(asd, 1, arg); 1744 break; 1745 1746 case ATOMISP_IOC_G_EE: 1747 err = atomisp_ee(asd, 0, arg); 1748 break; 1749 1750 case ATOMISP_IOC_S_EE: 1751 err = atomisp_ee(asd, 1, arg); 1752 break; 1753 1754 case ATOMISP_IOC_G_DIS_STAT: 1755 err = atomisp_get_dis_stat(asd, arg); 1756 break; 1757 1758 case ATOMISP_IOC_G_DVS2_BQ_RESOLUTIONS: 1759 err = atomisp_get_dvs2_bq_resolutions(asd, arg); 1760 break; 1761 1762 case ATOMISP_IOC_S_DIS_COEFS: 1763 err = atomisp_css_cp_dvs2_coefs(asd, arg, 1764 &asd->params.css_param, true); 1765 if (!err && arg) 1766 asd->params.css_update_params_needed = true; 1767 break; 1768 1769 case ATOMISP_IOC_S_DIS_VECTOR: 1770 err = atomisp_cp_dvs_6axis_config(asd, arg, 1771 &asd->params.css_param, true); 1772 if (!err && arg) 1773 asd->params.css_update_params_needed = true; 1774 break; 1775 1776 case ATOMISP_IOC_G_ISP_PARM: 1777 err = atomisp_param(asd, 0, arg); 1778 break; 1779 1780 case ATOMISP_IOC_S_ISP_PARM: 1781 err = atomisp_param(asd, 1, arg); 1782 break; 1783 1784 case ATOMISP_IOC_G_3A_STAT: 1785 err = atomisp_3a_stat(asd, 0, arg); 1786 break; 1787 1788 case ATOMISP_IOC_G_ISP_GAMMA: 1789 err = atomisp_gamma(asd, 0, arg); 1790 break; 1791 1792 case ATOMISP_IOC_S_ISP_GAMMA: 1793 err = atomisp_gamma(asd, 1, arg); 1794 break; 1795 1796 case ATOMISP_IOC_G_ISP_GDC_TAB: 1797 err = atomisp_gdc_cac_table(asd, 0, arg); 1798 break; 1799 1800 case ATOMISP_IOC_S_ISP_GDC_TAB: 1801 err = atomisp_gdc_cac_table(asd, 1, arg); 1802 break; 1803 1804 case ATOMISP_IOC_G_ISP_MACC: 1805 err = atomisp_macc_table(asd, 0, arg); 1806 break; 1807 1808 case ATOMISP_IOC_S_ISP_MACC: 1809 err = atomisp_macc_table(asd, 1, arg); 1810 break; 1811 1812 case ATOMISP_IOC_G_ISP_BAD_PIXEL_DETECTION: 1813 err = atomisp_bad_pixel_param(asd, 0, arg); 1814 break; 1815 1816 case ATOMISP_IOC_S_ISP_BAD_PIXEL_DETECTION: 1817 err = atomisp_bad_pixel_param(asd, 1, arg); 1818 break; 1819 1820 case ATOMISP_IOC_G_ISP_FALSE_COLOR_CORRECTION: 1821 err = atomisp_false_color_param(asd, 0, arg); 1822 break; 1823 1824 case ATOMISP_IOC_S_ISP_FALSE_COLOR_CORRECTION: 1825 err = atomisp_false_color_param(asd, 1, arg); 1826 break; 1827 1828 case ATOMISP_IOC_G_ISP_CTC: 1829 err = atomisp_ctc(asd, 0, arg); 1830 break; 1831 1832 case ATOMISP_IOC_S_ISP_CTC: 1833 err = atomisp_ctc(asd, 1, arg); 1834 break; 1835 1836 case ATOMISP_IOC_G_ISP_WHITE_BALANCE: 1837 err = atomisp_white_balance_param(asd, 0, arg); 1838 break; 1839 1840 case ATOMISP_IOC_S_ISP_WHITE_BALANCE: 1841 err = atomisp_white_balance_param(asd, 1, arg); 1842 break; 1843 1844 case ATOMISP_IOC_G_3A_CONFIG: 1845 err = atomisp_3a_config_param(asd, 0, arg); 1846 break; 1847 1848 case ATOMISP_IOC_S_3A_CONFIG: 1849 err = atomisp_3a_config_param(asd, 1, arg); 1850 break; 1851 1852 case ATOMISP_IOC_S_ISP_FPN_TABLE: 1853 err = atomisp_fixed_pattern_table(asd, arg); 1854 break; 1855 1856 case ATOMISP_IOC_S_EXPOSURE: 1857 err = v4l2_subdev_call(isp->inputs[asd->input_curr].camera, 1858 core, ioctl, cmd, arg); 1859 break; 1860 1861 case ATOMISP_IOC_S_ISP_SHD_TAB: 1862 err = atomisp_set_shading_table(asd, arg); 1863 break; 1864 1865 case ATOMISP_IOC_G_ISP_GAMMA_CORRECTION: 1866 err = atomisp_gamma_correction(asd, 0, arg); 1867 break; 1868 1869 case ATOMISP_IOC_S_ISP_GAMMA_CORRECTION: 1870 err = atomisp_gamma_correction(asd, 1, arg); 1871 break; 1872 1873 case ATOMISP_IOC_S_PARAMETERS: 1874 err = atomisp_set_parameters(vdev, arg); 1875 break; 1876 1877 case ATOMISP_IOC_EXT_ISP_CTRL: 1878 err = v4l2_subdev_call(isp->inputs[asd->input_curr].camera, 1879 core, ioctl, cmd, arg); 1880 break; 1881 case ATOMISP_IOC_EXP_ID_UNLOCK: 1882 err = atomisp_exp_id_unlock(asd, arg); 1883 break; 1884 case ATOMISP_IOC_EXP_ID_CAPTURE: 1885 err = atomisp_exp_id_capture(asd, arg); 1886 break; 1887 case ATOMISP_IOC_S_ENABLE_DZ_CAPT_PIPE: 1888 err = atomisp_enable_dz_capt_pipe(asd, arg); 1889 break; 1890 case ATOMISP_IOC_G_FORMATS_CONFIG: 1891 err = atomisp_formats(asd, 0, arg); 1892 break; 1893 1894 case ATOMISP_IOC_S_FORMATS_CONFIG: 1895 err = atomisp_formats(asd, 1, arg); 1896 break; 1897 case ATOMISP_IOC_INJECT_A_FAKE_EVENT: 1898 err = atomisp_inject_a_fake_event(asd, arg); 1899 break; 1900 case ATOMISP_IOC_S_ARRAY_RESOLUTION: 1901 err = atomisp_set_array_res(asd, arg); 1902 break; 1903 default: 1904 err = -EINVAL; 1905 break; 1906 } 1907 1908 return err; 1909 } 1910 1911 const struct v4l2_ioctl_ops atomisp_ioctl_ops = { 1912 .vidioc_querycap = atomisp_querycap, 1913 .vidioc_enum_input = atomisp_enum_input, 1914 .vidioc_g_input = atomisp_g_input, 1915 .vidioc_s_input = atomisp_s_input, 1916 .vidioc_queryctrl = atomisp_queryctl, 1917 .vidioc_s_ctrl = atomisp_s_ctrl, 1918 .vidioc_g_ctrl = atomisp_g_ctrl, 1919 .vidioc_s_ext_ctrls = atomisp_s_ext_ctrls, 1920 .vidioc_g_ext_ctrls = atomisp_g_ext_ctrls, 1921 .vidioc_enum_framesizes = atomisp_enum_framesizes, 1922 .vidioc_enum_frameintervals = atomisp_enum_frameintervals, 1923 .vidioc_enum_fmt_vid_cap = atomisp_enum_fmt_cap, 1924 .vidioc_try_fmt_vid_cap = atomisp_try_fmt_cap, 1925 .vidioc_g_fmt_vid_cap = atomisp_g_fmt_cap, 1926 .vidioc_s_fmt_vid_cap = atomisp_s_fmt_cap, 1927 .vidioc_reqbufs = vb2_ioctl_reqbufs, 1928 .vidioc_querybuf = vb2_ioctl_querybuf, 1929 .vidioc_qbuf = atomisp_qbuf_wrapper, 1930 .vidioc_dqbuf = atomisp_dqbuf_wrapper, 1931 .vidioc_streamon = vb2_ioctl_streamon, 1932 .vidioc_streamoff = vb2_ioctl_streamoff, 1933 .vidioc_default = atomisp_vidioc_default, 1934 .vidioc_s_parm = atomisp_s_parm, 1935 .vidioc_g_parm = atomisp_g_parm, 1936 }; 1937