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