FILE
atomisp_ioctl.c
File preview with syntax highlighting.
linux-6.19.14/drivers/staging/media/atomisp/pci/atomisp_ioctl.c
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 10#include <linux/delay.h> 11#include <linux/pci.h> 12 13#include <media/v4l2-ioctl.h> 14#include <media/v4l2-event.h> 15 16#include "atomisp_cmd.h" 17#include "atomisp_common.h" 18#include "atomisp_fops.h" 19#include "atomisp_internal.h" 20#include "atomisp_ioctl.h" 21#include "atomisp-regs.h" 22#include "atomisp_compat.h" 23 24#include "sh_css_hrt.h" 25 26#include "gp_device.h" 27#include "device_access.h" 28#include "irq.h" 29 30static const char *DRIVER = "atomisp"; /* max size 15 */ 31static const char *CARD = "ATOM ISP"; /* max size 31 */ 32 33/* 34 * FIXME: ISP should not know beforehand all CIDs supported by sensor. 35 * Instead, it needs to propagate to sensor unknown CIDs. 36 */ 37static struct v4l2_query_ext_ctrl ci_v4l2_controls[] = { 38 { 39 .id = V4L2_CID_AUTO_WHITE_BALANCE, 40 .type = V4L2_CTRL_TYPE_BOOLEAN, 41 .name = "Automatic White Balance", 42 .minimum = 0, 43 .maximum = 1, 44 .step = 1, 45 .default_value = 0, 46 }, 47 { 48 .id = V4L2_CID_RED_BALANCE, 49 .type = V4L2_CTRL_TYPE_INTEGER, 50 .name = "Red Balance", 51 .minimum = 0x00, 52 .maximum = 0xff, 53 .step = 1, 54 .default_value = 0x00, 55 }, 56 { 57 .id = V4L2_CID_BLUE_BALANCE, 58 .type = V4L2_CTRL_TYPE_INTEGER, 59 .name = "Blue Balance", 60 .minimum = 0x00, 61 .maximum = 0xff, 62 .step = 1, 63 .default_value = 0x00, 64 }, 65 { 66 .id = V4L2_CID_GAMMA, 67 .type = V4L2_CTRL_TYPE_INTEGER, 68 .name = "Gamma", 69 .minimum = 0x00, 70 .maximum = 0xff, 71 .step = 1, 72 .default_value = 0x00, 73 }, 74 { 75 .id = V4L2_CID_COLORFX, 76 .type = V4L2_CTRL_TYPE_INTEGER, 77 .name = "Image Color Effect", 78 .minimum = 0, 79 .maximum = 9, 80 .step = 1, 81 .default_value = 0, 82 }, 83 { 84 .id = V4L2_CID_ATOMISP_BAD_PIXEL_DETECTION, 85 .type = V4L2_CTRL_TYPE_INTEGER, 86 .name = "Bad Pixel Correction", 87 .minimum = 0, 88 .maximum = 1, 89 .step = 1, 90 .default_value = 0, 91 }, 92 { 93 .id = V4L2_CID_ATOMISP_POSTPROCESS_GDC_CAC, 94 .type = V4L2_CTRL_TYPE_INTEGER, 95 .name = "GDC/CAC", 96 .minimum = 0, 97 .maximum = 1, 98 .step = 1, 99 .default_value = 0, 100 }, 101 { 102 .id = V4L2_CID_ATOMISP_VIDEO_STABLIZATION, 103 .type = V4L2_CTRL_TYPE_INTEGER, 104 .name = "Video Stabilization", 105 .minimum = 0, 106 .maximum = 1, 107 .step = 1, 108 .default_value = 0, 109 }, 110 { 111 .id = V4L2_CID_ATOMISP_FIXED_PATTERN_NR, 112 .type = V4L2_CTRL_TYPE_INTEGER, 113 .name = "Fixed Pattern Noise Reduction", 114 .minimum = 0, 115 .maximum = 1, 116 .step = 1, 117 .default_value = 0, 118 }, 119 { 120 .id = V4L2_CID_ATOMISP_FALSE_COLOR_CORRECTION, 121 .type = V4L2_CTRL_TYPE_INTEGER, 122 .name = "False Color Correction", 123 .minimum = 0, 124 .maximum = 1, 125 .step = 1, 126 .default_value = 0, 127 }, 128 { 129 .id = V4L2_CID_ATOMISP_LOW_LIGHT, 130 .type = V4L2_CTRL_TYPE_BOOLEAN, 131 .name = "Low light mode", 132 .minimum = 0, 133 .maximum = 1, 134 .step = 1, 135 .default_value = 1, 136 }, 137}; 138 139static const u32 ctrls_num = ARRAY_SIZE(ci_v4l2_controls); 140 141/* 142 * supported V4L2 fmts and resolutions 143 */ 144const struct atomisp_format_bridge atomisp_output_fmts[] = { 145 { 146 .pixelformat = V4L2_PIX_FMT_YUV420, 147 .depth = 12, 148 .mbus_code = V4L2_MBUS_FMT_CUSTOM_YUV420, 149 .sh_fmt = IA_CSS_FRAME_FORMAT_YUV420, 150 .description = "YUV420, planar", 151 .planar = true 152 }, { 153 .pixelformat = V4L2_PIX_FMT_YVU420, 154 .depth = 12, 155 .mbus_code = V4L2_MBUS_FMT_CUSTOM_YVU420, 156 .sh_fmt = IA_CSS_FRAME_FORMAT_YV12, 157 .description = "YVU420, planar", 158 .planar = true 159 }, { 160 .pixelformat = V4L2_PIX_FMT_YUV422P, 161 .depth = 16, 162 .mbus_code = V4L2_MBUS_FMT_CUSTOM_YUV422P, 163 .sh_fmt = IA_CSS_FRAME_FORMAT_YUV422, 164 .description = "YUV422, planar", 165 .planar = true 166 }, { 167 .pixelformat = V4L2_PIX_FMT_YUV444, 168 .depth = 24, 169 .mbus_code = V4L2_MBUS_FMT_CUSTOM_YUV444, 170 .sh_fmt = IA_CSS_FRAME_FORMAT_YUV444, 171 .description = "YUV444" 172 }, { 173 .pixelformat = V4L2_PIX_FMT_NV12, 174 .depth = 12, 175 .mbus_code = V4L2_MBUS_FMT_CUSTOM_NV12, 176 .sh_fmt = IA_CSS_FRAME_FORMAT_NV12, 177 .description = "NV12, Y-plane, CbCr interleaved", 178 .planar = true 179 }, { 180 .pixelformat = V4L2_PIX_FMT_NV21, 181 .depth = 12, 182 .mbus_code = V4L2_MBUS_FMT_CUSTOM_NV21, 183 .sh_fmt = IA_CSS_FRAME_FORMAT_NV21, 184 .description = "NV21, Y-plane, CbCr interleaved", 185 .planar = true 186 }, { 187 .pixelformat = V4L2_PIX_FMT_NV16, 188 .depth = 16, 189 .mbus_code = V4L2_MBUS_FMT_CUSTOM_NV16, 190 .sh_fmt = IA_CSS_FRAME_FORMAT_NV16, 191 .description = "NV16, Y-plane, CbCr interleaved", 192 .planar = true 193 }, { 194 .pixelformat = V4L2_PIX_FMT_YUYV, 195 .depth = 16, 196 .mbus_code = V4L2_MBUS_FMT_CUSTOM_YUYV, 197 .sh_fmt = IA_CSS_FRAME_FORMAT_YUYV, 198 .description = "YUYV, interleaved" 199 }, { 200 .pixelformat = V4L2_PIX_FMT_UYVY, 201 .depth = 16, 202 .mbus_code = MEDIA_BUS_FMT_UYVY8_1X16, 203 .sh_fmt = IA_CSS_FRAME_FORMAT_UYVY, 204 .description = "UYVY, interleaved" 205 }, { 206 .pixelformat = V4L2_PIX_FMT_SBGGR16, 207 .depth = 16, 208 .mbus_code = V4L2_MBUS_FMT_CUSTOM_SBGGR16, 209 .sh_fmt = IA_CSS_FRAME_FORMAT_RAW, 210 .description = "Bayer 16" 211 }, { 212 .pixelformat = V4L2_PIX_FMT_SBGGR8, 213 .depth = 8, 214 .mbus_code = MEDIA_BUS_FMT_SBGGR8_1X8, 215 .sh_fmt = IA_CSS_FRAME_FORMAT_RAW, 216 .description = "Bayer 8" 217 }, { 218 .pixelformat = V4L2_PIX_FMT_SGBRG8, 219 .depth = 8, 220 .mbus_code = MEDIA_BUS_FMT_SGBRG8_1X8, 221 .sh_fmt = IA_CSS_FRAME_FORMAT_RAW, 222 .description = "Bayer 8" 223 }, { 224 .pixelformat = V4L2_PIX_FMT_SGRBG8, 225 .depth = 8, 226 .mbus_code = MEDIA_BUS_FMT_SGRBG8_1X8, 227 .sh_fmt = IA_CSS_FRAME_FORMAT_RAW, 228 .description = "Bayer 8" 229 }, { 230 .pixelformat = V4L2_PIX_FMT_SRGGB8, 231 .depth = 8, 232 .mbus_code = MEDIA_BUS_FMT_SRGGB8_1X8, 233 .sh_fmt = IA_CSS_FRAME_FORMAT_RAW, 234 .description = "Bayer 8" 235 }, { 236 .pixelformat = V4L2_PIX_FMT_SBGGR10, 237 .depth = 16, 238 .mbus_code = MEDIA_BUS_FMT_SBGGR10_1X10, 239 .sh_fmt = IA_CSS_FRAME_FORMAT_RAW, 240 .description = "Bayer 10" 241 }, { 242 .pixelformat = V4L2_PIX_FMT_SGBRG10, 243 .depth = 16, 244 .mbus_code = MEDIA_BUS_FMT_SGBRG10_1X10, 245 .sh_fmt = IA_CSS_FRAME_FORMAT_RAW, 246 .description = "Bayer 10" 247 }, { 248 .pixelformat = V4L2_PIX_FMT_SGRBG10, 249 .depth = 16, 250 .mbus_code = MEDIA_BUS_FMT_SGRBG10_1X10, 251 .sh_fmt = IA_CSS_FRAME_FORMAT_RAW, 252 .description = "Bayer 10" 253 }, { 254 .pixelformat = V4L2_PIX_FMT_SRGGB10, 255 .depth = 16, 256 .mbus_code = MEDIA_BUS_FMT_SRGGB10_1X10, 257 .sh_fmt = IA_CSS_FRAME_FORMAT_RAW, 258 .description = "Bayer 10" 259 }, { 260 .pixelformat = V4L2_PIX_FMT_SBGGR12, 261 .depth = 16, 262 .mbus_code = MEDIA_BUS_FMT_SBGGR12_1X12, 263 .sh_fmt = IA_CSS_FRAME_FORMAT_RAW, 264 .description = "Bayer 12" 265 }, { 266 .pixelformat = V4L2_PIX_FMT_SGBRG12, 267 .depth = 16, 268 .mbus_code = MEDIA_BUS_FMT_SGBRG12_1X12, 269 .sh_fmt = IA_CSS_FRAME_FORMAT_RAW, 270 .description = "Bayer 12" 271 }, { 272 .pixelformat = V4L2_PIX_FMT_SGRBG12, 273 .depth = 16, 274 .mbus_code = MEDIA_BUS_FMT_SGRBG12_1X12, 275 .sh_fmt = IA_CSS_FRAME_FORMAT_RAW, 276 .description = "Bayer 12" 277 }, { 278 .pixelformat = V4L2_PIX_FMT_SRGGB12, 279 .depth = 16, 280 .mbus_code = MEDIA_BUS_FMT_SRGGB12_1X12, 281 .sh_fmt = IA_CSS_FRAME_FORMAT_RAW, 282 .description = "Bayer 12" 283 }, { 284 .pixelformat = V4L2_PIX_FMT_RGB565, 285 .depth = 16, 286 .mbus_code = MEDIA_BUS_FMT_BGR565_2X8_LE, 287 .sh_fmt = IA_CSS_FRAME_FORMAT_RGB565, 288 .description = "16 RGB 5-6-5" 289#if 0 290 }, { 291 /* 292 * Broken, showing vertical columns with random data. 293 * For each 128 pixels in a row the last 28 (32?) or so pixels 294 * contain random data. 295 */ 296 .pixelformat = V4L2_PIX_FMT_RGBX32, 297 .depth = 32, 298 .mbus_code = V4L2_MBUS_FMT_CUSTOM_RGB32, 299 .sh_fmt = IA_CSS_FRAME_FORMAT_RGBA888, 300 .description = "32 RGB 8-8-8-8" 301 }, { 302 .pixelformat = V4L2_PIX_FMT_JPEG, 303 .depth = 8, 304 .mbus_code = MEDIA_BUS_FMT_JPEG_1X8, 305 .sh_fmt = IA_CSS_FRAME_FORMAT_BINARY_8, 306 .description = "JPEG" 307 }, { 308 /* This is a custom format being used by M10MO to send the RAW data */ 309 .pixelformat = V4L2_PIX_FMT_CUSTOM_M10MO_RAW, 310 .depth = 8, 311 .mbus_code = V4L2_MBUS_FMT_CUSTOM_M10MO_RAW, 312 .sh_fmt = IA_CSS_FRAME_FORMAT_BINARY_8, 313 .description = "Custom RAW for M10MO" 314#endif 315 }, 316}; 317 318const struct atomisp_format_bridge * 319atomisp_get_format_bridge(unsigned int pixelformat) 320{ 321 unsigned int i; 322 323 for (i = 0; i < ARRAY_SIZE(atomisp_output_fmts); i++) { 324 if (atomisp_output_fmts[i].pixelformat == pixelformat) 325 return &atomisp_output_fmts[i]; 326 } 327 328 return NULL; 329} 330 331const struct atomisp_format_bridge * 332atomisp_get_format_bridge_from_mbus(u32 mbus_code) 333{ 334 unsigned int i; 335 336 for (i = 0; i < ARRAY_SIZE(atomisp_output_fmts); i++) { 337 if (mbus_code == atomisp_output_fmts[i].mbus_code) 338 return &atomisp_output_fmts[i]; 339 } 340 341 return NULL; 342} 343 344int atomisp_pipe_check(struct atomisp_video_pipe *pipe, bool settings_change) 345{ 346 lockdep_assert_held(&pipe->isp->mutex); 347 348 if (pipe->isp->isp_fatal_error) 349 return -EIO; 350 351 if (settings_change && vb2_is_busy(&pipe->vb_queue)) { 352 dev_err(pipe->isp->dev, "Set fmt/input IOCTL while streaming\n"); 353 return -EBUSY; 354 } 355 356 return 0; 357} 358 359/* 360 * v4l2 ioctls 361 * return ISP capabilities 362 */ 363static int atomisp_querycap(struct file *file, void *fh, 364 struct v4l2_capability *cap) 365{ 366 struct video_device *vdev = video_devdata(file); 367 struct atomisp_device *isp = video_get_drvdata(vdev); 368 369 strscpy(cap->driver, DRIVER, sizeof(cap->driver)); 370 strscpy(cap->card, CARD, sizeof(cap->card)); 371 snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s", dev_name(isp->dev)); 372 373 return 0; 374} 375 376/* 377 * enum input are used to check primary/secondary camera 378 */ 379static int atomisp_enum_input(struct file *file, void *fh, 380 struct v4l2_input *input) 381{ 382 struct video_device *vdev = video_devdata(file); 383 struct atomisp_device *isp = video_get_drvdata(vdev); 384 int index = input->index; 385 386 if (index >= isp->input_cnt) 387 return -EINVAL; 388 389 if (!isp->inputs[index].sensor) 390 return -EINVAL; 391 392 memset(input, 0, sizeof(struct v4l2_input)); 393 strscpy(input->name, isp->inputs[index].sensor->name, 394 sizeof(input->name)); 395 396 input->type = V4L2_INPUT_TYPE_CAMERA; 397 input->index = index; 398 input->reserved[1] = isp->inputs[index].port; 399 400 return 0; 401} 402 403/* 404 * get input are used to get current primary/secondary camera 405 */ 406static int atomisp_g_input(struct file *file, void *fh, unsigned int *input) 407{ 408 struct video_device *vdev = video_devdata(file); 409 struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd; 410 411 *input = asd->input_curr; 412 return 0; 413} 414 415static int atomisp_s_fmt_cap(struct file *file, void *fh, 416 struct v4l2_format *f) 417{ 418 struct video_device *vdev = video_devdata(file); 419 420 return atomisp_set_fmt(vdev, f); 421} 422 423/* 424 * set input are used to set current primary/secondary camera 425 */ 426static int atomisp_s_input(struct file *file, void *fh, unsigned int input) 427{ 428 struct video_device *vdev = video_devdata(file); 429 struct atomisp_device *isp = video_get_drvdata(vdev); 430 struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev); 431 int ret; 432 433 if (input >= isp->input_cnt) 434 return -EINVAL; 435 436 if (!isp->inputs[input].sensor) 437 return -EINVAL; 438 439 ret = atomisp_pipe_check(pipe, true); 440 if (ret) 441 return ret; 442 443 mutex_lock(&isp->media_dev.graph_mutex); 444 ret = atomisp_select_input(isp, input); 445 mutex_unlock(&isp->media_dev.graph_mutex); 446 447 return ret; 448} 449 450/* 451 * With crop any framesize <= sensor-size can be made, give 452 * userspace a list of sizes to choice from. 453 */ 454static int atomisp_enum_framesizes_crop_inner(struct atomisp_device *isp, 455 struct v4l2_frmsizeenum *fsize, 456 const struct v4l2_rect *active, 457 const struct v4l2_rect *native, 458 int *valid_sizes) 459{ 460 static const struct v4l2_frmsize_discrete frame_sizes[] = { 461 { 1920, 1440 }, 462 { 1920, 1200 }, 463 { 1920, 1080 }, 464 { 1600, 1200 }, 465 { 1600, 1080 }, 466 { 1600, 900 }, 467 { 1440, 1080 }, 468 { 1280, 960 }, 469 { 1280, 720 }, 470 { 800, 600 }, 471 { 640, 480 }, 472 }; 473 u32 padding_w, padding_h; 474 int i; 475 476 for (i = 0; i < ARRAY_SIZE(frame_sizes); i++) { 477 atomisp_get_padding(isp, frame_sizes[i].width, frame_sizes[i].height, 478 &padding_w, &padding_h); 479 480 if ((frame_sizes[i].width + padding_w) > native->width || 481 (frame_sizes[i].height + padding_h) > native->height) 482 continue; 483 484 /* 485 * Skip sizes where width and height are less then 5/8th of the 486 * sensor size to avoid sizes with a too small field of view. 487 */ 488 if (frame_sizes[i].width < (active->width * 5 / 8) && 489 frame_sizes[i].height < (active->height * 5 / 8)) 490 continue; 491 492 if (*valid_sizes == fsize->index) { 493 fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; 494 fsize->discrete = frame_sizes[i]; 495 return 0; 496 } 497 498 (*valid_sizes)++; 499 } 500 501 return -EINVAL; 502} 503 504static int atomisp_enum_framesizes_crop(struct atomisp_device *isp, 505 struct v4l2_frmsizeenum *fsize) 506{ 507 struct atomisp_input_subdev *input = &isp->inputs[isp->asd.input_curr]; 508 struct v4l2_rect active = input->active_rect; 509 struct v4l2_rect native = input->native_rect; 510 int ret, valid_sizes = 0; 511 512 ret = atomisp_enum_framesizes_crop_inner(isp, fsize, &active, &native, &valid_sizes); 513 if (ret == 0) 514 return 0; 515 516 if (!input->binning_support) 517 return -EINVAL; 518 519 active.width /= 2; 520 active.height /= 2; 521 native.width /= 2; 522 native.height /= 2; 523 524 return atomisp_enum_framesizes_crop_inner(isp, fsize, &active, &native, &valid_sizes); 525} 526 527static int atomisp_enum_framesizes(struct file *file, void *priv, 528 struct v4l2_frmsizeenum *fsize) 529{ 530 struct video_device *vdev = video_devdata(file); 531 struct atomisp_device *isp = video_get_drvdata(vdev); 532 struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd; 533 struct atomisp_input_subdev *input = &isp->inputs[asd->input_curr]; 534 struct v4l2_subdev_frame_size_enum fse = { 535 .index = fsize->index, 536 .which = V4L2_SUBDEV_FORMAT_ACTIVE, 537 .code = input->code, 538 }; 539 struct v4l2_subdev_state *act_sd_state; 540 int ret; 541 542 if (!input->sensor) 543 return -EINVAL; 544 545 if (input->crop_support) 546 return atomisp_enum_framesizes_crop(isp, fsize); 547 548 act_sd_state = v4l2_subdev_lock_and_get_active_state(input->sensor); 549 ret = v4l2_subdev_call(input->sensor, pad, enum_frame_size, 550 act_sd_state, &fse); 551 if (act_sd_state) 552 v4l2_subdev_unlock_state(act_sd_state); 553 if (ret) 554 return ret; 555 556 fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; 557 fsize->discrete.width = fse.max_width - pad_w; 558 fsize->discrete.height = fse.max_height - pad_h; 559 560 return 0; 561} 562 563static int atomisp_enum_frameintervals(struct file *file, void *priv, 564 struct v4l2_frmivalenum *fival) 565{ 566 struct video_device *vdev = video_devdata(file); 567 struct atomisp_device *isp = video_get_drvdata(vdev); 568 struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd; 569 struct atomisp_input_subdev *input = &isp->inputs[asd->input_curr]; 570 struct v4l2_subdev_frame_interval_enum fie = { 571 .code = atomisp_in_fmt_conv[0].code, 572 .index = fival->index, 573 .width = fival->width, 574 .height = fival->height, 575 .which = V4L2_SUBDEV_FORMAT_ACTIVE, 576 }; 577 struct v4l2_subdev_state *act_sd_state; 578 int ret; 579 580 if (!input->sensor) 581 return -EINVAL; 582 583 act_sd_state = v4l2_subdev_lock_and_get_active_state(input->sensor); 584 ret = v4l2_subdev_call(input->sensor, pad, enum_frame_interval, 585 act_sd_state, &fie); 586 if (act_sd_state) 587 v4l2_subdev_unlock_state(act_sd_state); 588 if (ret) 589 return ret; 590 591 fival->type = V4L2_FRMIVAL_TYPE_DISCRETE; 592 fival->discrete = fie.interval; 593 594 return ret; 595} 596 597static int atomisp_enum_fmt_cap(struct file *file, void *fh, 598 struct v4l2_fmtdesc *f) 599{ 600 struct video_device *vdev = video_devdata(file); 601 struct atomisp_device *isp = video_get_drvdata(vdev); 602 struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd; 603 struct atomisp_input_subdev *input = &isp->inputs[asd->input_curr]; 604 struct v4l2_subdev_mbus_code_enum code = { 605 .which = V4L2_SUBDEV_FORMAT_ACTIVE, 606 }; 607 const struct atomisp_format_bridge *format; 608 struct v4l2_subdev_state *act_sd_state; 609 unsigned int i, fi = 0; 610 int ret; 611 612 if (!input->sensor) 613 return -EINVAL; 614 615 act_sd_state = v4l2_subdev_lock_and_get_active_state(input->sensor); 616 ret = v4l2_subdev_call(input->sensor, pad, enum_mbus_code, 617 act_sd_state, &code); 618 if (act_sd_state) 619 v4l2_subdev_unlock_state(act_sd_state); 620 if (ret) 621 return ret; 622 623 for (i = 0; i < ARRAY_SIZE(atomisp_output_fmts); i++) { 624 format = &atomisp_output_fmts[i]; 625 626 /* 627 * Is the atomisp-supported format is valid for the 628 * sensor (configuration)? If not, skip it. 629 * 630 * FIXME: fix the pipeline to allow sensor format too. 631 */ 632 if (format->sh_fmt == IA_CSS_FRAME_FORMAT_RAW) 633 continue; 634 635 /* Found a match. Now let's pick f->index'th one. */ 636 if (fi < f->index) { 637 fi++; 638 continue; 639 } 640 641 strscpy(f->description, format->description, 642 sizeof(f->description)); 643 f->pixelformat = format->pixelformat; 644 return 0; 645 } 646 647 return -EINVAL; 648} 649 650/* This function looks up the closest available resolution. */ 651static int atomisp_try_fmt_cap(struct file *file, void *fh, 652 struct v4l2_format *f) 653{ 654 struct video_device *vdev = video_devdata(file); 655 struct atomisp_device *isp = video_get_drvdata(vdev); 656 657 return atomisp_try_fmt(isp, &f->fmt.pix, NULL, NULL); 658} 659 660static int atomisp_g_fmt_cap(struct file *file, void *fh, 661 struct v4l2_format *f) 662{ 663 struct video_device *vdev = video_devdata(file); 664 struct atomisp_video_pipe *pipe; 665 666 pipe = atomisp_to_video_pipe(vdev); 667 668 f->fmt.pix = pipe->pix; 669 670 /* If s_fmt was issued, just return whatever is was previously set */ 671 if (f->fmt.pix.sizeimage) 672 return 0; 673 674 f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420; 675 f->fmt.pix.width = 10000; 676 f->fmt.pix.height = 10000; 677 678 return atomisp_try_fmt_cap(file, fh, f); 679} 680 681int atomisp_alloc_css_stat_bufs(struct atomisp_sub_device *asd, 682 uint16_t stream_id) 683{ 684 struct atomisp_device *isp = asd->isp; 685 struct atomisp_s3a_buf *s3a_buf = NULL, *_s3a_buf; 686 struct atomisp_dis_buf *dis_buf = NULL, *_dis_buf; 687 struct atomisp_metadata_buf *md_buf = NULL, *_md_buf; 688 int count; 689 struct ia_css_dvs_grid_info *dvs_grid_info = 690 atomisp_css_get_dvs_grid_info(&asd->params.curr_grid_info); 691 unsigned int i; 692 693 if (list_empty(&asd->s3a_stats) && 694 asd->params.curr_grid_info.s3a_grid.enable) { 695 count = ATOMISP_CSS_Q_DEPTH + 696 ATOMISP_S3A_BUF_QUEUE_DEPTH_FOR_HAL; 697 dev_dbg(isp->dev, "allocating %d 3a buffers\n", count); 698 while (count--) { 699 s3a_buf = kzalloc(sizeof(struct atomisp_s3a_buf), GFP_KERNEL); 700 if (!s3a_buf) 701 goto error; 702 703 if (atomisp_css_allocate_stat_buffers( 704 asd, stream_id, s3a_buf, NULL, NULL)) { 705 kfree(s3a_buf); 706 goto error; 707 } 708 709 list_add_tail(&s3a_buf->list, &asd->s3a_stats); 710 } 711 } 712 713 if (list_empty(&asd->dis_stats) && dvs_grid_info && 714 dvs_grid_info->enable) { 715 count = ATOMISP_CSS_Q_DEPTH + 1; 716 dev_dbg(isp->dev, "allocating %d dis buffers\n", count); 717 while (count--) { 718 dis_buf = kzalloc(sizeof(struct atomisp_dis_buf), GFP_KERNEL); 719 if (!dis_buf) 720 goto error; 721 if (atomisp_css_allocate_stat_buffers( 722 asd, stream_id, NULL, dis_buf, NULL)) { 723 kfree(dis_buf); 724 goto error; 725 } 726 727 list_add_tail(&dis_buf->list, &asd->dis_stats); 728 } 729 } 730 731 for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) { 732 if (list_empty(&asd->metadata[i]) && 733 list_empty(&asd->metadata_ready[i]) && 734 list_empty(&asd->metadata_in_css[i])) { 735 count = ATOMISP_CSS_Q_DEPTH + 736 ATOMISP_METADATA_QUEUE_DEPTH_FOR_HAL; 737 dev_dbg(isp->dev, "allocating %d metadata buffers for type %d\n", 738 count, i); 739 while (count--) { 740 md_buf = kzalloc(sizeof(struct atomisp_metadata_buf), 741 GFP_KERNEL); 742 if (!md_buf) 743 goto error; 744 745 if (atomisp_css_allocate_stat_buffers( 746 asd, stream_id, NULL, NULL, md_buf)) { 747 kfree(md_buf); 748 goto error; 749 } 750 list_add_tail(&md_buf->list, &asd->metadata[i]); 751 } 752 } 753 } 754 return 0; 755 756error: 757 dev_err(isp->dev, "failed to allocate statistics buffers\n"); 758 759 list_for_each_entry_safe(dis_buf, _dis_buf, &asd->dis_stats, list) { 760 atomisp_css_free_dis_buffer(dis_buf); 761 list_del(&dis_buf->list); 762 kfree(dis_buf); 763 } 764 765 list_for_each_entry_safe(s3a_buf, _s3a_buf, &asd->s3a_stats, list) { 766 atomisp_css_free_3a_buffer(s3a_buf); 767 list_del(&s3a_buf->list); 768 kfree(s3a_buf); 769 } 770 771 for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) { 772 list_for_each_entry_safe(md_buf, _md_buf, &asd->metadata[i], 773 list) { 774 atomisp_css_free_metadata_buffer(md_buf); 775 list_del(&md_buf->list); 776 kfree(md_buf); 777 } 778 } 779 return -ENOMEM; 780} 781 782/* 783 * FIXME the abuse of buf->reserved2 in the qbuf and dqbuf wrappers comes from 784 * the original atomisp buffer handling and should be replaced with proper V4L2 785 * per frame parameters use. 786 * 787 * Once this is fixed these wrappers can be removed, replacing them with direct 788 * calls to vb2_ioctl_[d]qbuf(). 789 */ 790static int atomisp_qbuf_wrapper(struct file *file, void *fh, struct v4l2_buffer *buf) 791{ 792 struct video_device *vdev = video_devdata(file); 793 struct atomisp_device *isp = video_get_drvdata(vdev); 794 struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev); 795 796 if (buf->index >= vb2_get_num_buffers(vdev->queue)) 797 return -EINVAL; 798 799 if (buf->reserved2 & ATOMISP_BUFFER_HAS_PER_FRAME_SETTING) { 800 /* this buffer will have a per-frame parameter */ 801 pipe->frame_request_config_id[buf->index] = buf->reserved2 & 802 ~ATOMISP_BUFFER_HAS_PER_FRAME_SETTING; 803 dev_dbg(isp->dev, 804 "This buffer requires per_frame setting which has isp_config_id %d\n", 805 pipe->frame_request_config_id[buf->index]); 806 } else { 807 pipe->frame_request_config_id[buf->index] = 0; 808 } 809 810 return vb2_ioctl_qbuf(file, fh, buf); 811} 812 813static int atomisp_dqbuf_wrapper(struct file *file, void *fh, struct v4l2_buffer *buf) 814{ 815 struct video_device *vdev = video_devdata(file); 816 struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev); 817 struct atomisp_device *isp = video_get_drvdata(vdev); 818 struct ia_css_frame *frame; 819 struct vb2_buffer *vb; 820 int ret; 821 822 ret = vb2_ioctl_dqbuf(file, fh, buf); 823 if (ret) 824 return ret; 825 826 vb = vb2_get_buffer(&pipe->vb_queue, buf->index); 827 frame = vb_to_frame(vb); 828 829 /* reserved bit[31:16] is used for exp_id */ 830 buf->reserved = 0; 831 if (!(buf->flags & V4L2_BUF_FLAG_ERROR)) 832 buf->reserved |= frame->exp_id; 833 buf->reserved2 = pipe->frame_config_id[buf->index]; 834 835 dev_dbg(isp->dev, 836 "dqbuf buffer %d (%s) with exp_id %d, isp_config_id %d\n", 837 buf->index, vdev->name, buf->reserved >> 16, buf->reserved2); 838 return 0; 839} 840 841/* Input system HW workaround */ 842/* Input system address translation corrupts burst during */ 843/* invalidate. SW workaround for this is to set burst length */ 844/* manually to 128 in case of 13MPx snapshot and to 1 otherwise. */ 845static void atomisp_dma_burst_len_cfg(struct atomisp_sub_device *asd) 846{ 847 struct v4l2_mbus_framefmt *sink; 848 849 sink = atomisp_subdev_get_ffmt(&asd->subdev, NULL, 850 V4L2_SUBDEV_FORMAT_ACTIVE, 851 ATOMISP_SUBDEV_PAD_SINK); 852 853 if (sink->width * sink->height >= 4096 * 3072) 854 atomisp_css2_hw_store_32(DMA_BURST_SIZE_REG, 0x7F); 855 else 856 atomisp_css2_hw_store_32(DMA_BURST_SIZE_REG, 0x00); 857} 858 859static void atomisp_stop_stream(struct atomisp_video_pipe *pipe, 860 bool stop_sensor, enum vb2_buffer_state state) 861{ 862 struct atomisp_sub_device *asd = pipe->asd; 863 struct atomisp_device *isp = asd->isp; 864 struct pci_dev *pdev = to_pci_dev(isp->dev); 865 unsigned long flags; 866 int ret; 867 868 spin_lock_irqsave(&isp->lock, flags); 869 asd->streaming = false; 870 spin_unlock_irqrestore(&isp->lock, flags); 871 872 atomisp_clear_css_buffer_counters(asd); 873 atomisp_css_irq_enable(isp, IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF, false); 874 875 atomisp_css_stop(asd, false); 876 877 atomisp_subdev_cleanup_pending_events(asd); 878 879 if (stop_sensor) { 880 ret = v4l2_subdev_call(isp->inputs[asd->input_curr].csi_remote_source, 881 video, s_stream, 0); 882 if (ret) 883 dev_warn(isp->dev, "Stopping sensor stream failed: %d\n", ret); 884 } 885 886 /* Disable the CSI interface on ANN B0/K0 */ 887 if (isp->media_dev.hw_revision >= ((ATOMISP_HW_REVISION_ISP2401 << 888 ATOMISP_HW_REVISION_SHIFT) | ATOMISP_HW_STEPPING_B0)) { 889 pci_write_config_word(pdev, MRFLD_PCI_CSI_CONTROL, 890 isp->saved_regs.csi_control & ~MRFLD_PCI_CSI_CONTROL_CSI_READY); 891 } 892 893 if (atomisp_freq_scaling(isp, ATOMISP_DFS_MODE_LOW, false)) 894 dev_warn(isp->dev, "DFS failed.\n"); 895 896 /* 897 * ISP work around, need to reset ISP to allow next stream on to work. 898 * Streams have already been destroyed by atomisp_css_stop(). 899 * Disable PUNIT/ISP acknowledge/handshake - SRSE=3 and then reset. 900 */ 901 pci_write_config_dword(pdev, PCI_I_CONTROL, 902 isp->saved_regs.i_control | MRFLD_PCI_I_CONTROL_SRSE_RESET_MASK); 903 atomisp_reset(isp); 904 905 atomisp_flush_video_pipe(pipe, state, false); 906 907 /* Streams were destroyed by atomisp_css_stop(), recreate them. */ 908 ret = atomisp_create_pipes_stream(&isp->asd); 909 if (ret) 910 dev_warn(isp->dev, "Recreating streams failed: %d\n", ret); 911 912 media_pipeline_stop(&asd->video_out.vdev.entity.pads[0]); 913} 914 915int atomisp_start_streaming(struct vb2_queue *vq, unsigned int count) 916{ 917 struct atomisp_video_pipe *pipe = vq_to_pipe(vq); 918 struct atomisp_sub_device *asd = pipe->asd; 919 struct atomisp_device *isp = asd->isp; 920 struct pci_dev *pdev = to_pci_dev(isp->dev); 921 unsigned long irqflags; 922 int ret; 923 924 dev_dbg(isp->dev, "Start stream\n"); 925 926 mutex_lock(&isp->mutex); 927 928 ret = atomisp_pipe_check(pipe, false); 929 if (ret) { 930 atomisp_flush_video_pipe(pipe, VB2_BUF_STATE_QUEUED, true); 931 goto out_unlock; 932 } 933 934 /* 935 * When running a classic v4l2 app after a media-controller aware 936 * app, the CSI-receiver -> ISP link for the current sensor may be 937 * disabled. Fix this up before marking the pipeline as started. 938 */ 939 mutex_lock(&isp->media_dev.graph_mutex); 940 atomisp_setup_input_links(isp); 941 ret = __media_pipeline_start(&asd->video_out.vdev.entity.pads[0], &asd->video_out.pipe); 942 mutex_unlock(&isp->media_dev.graph_mutex); 943 if (ret) { 944 dev_err(isp->dev, "Error starting mc pipeline: %d\n", ret); 945 atomisp_flush_video_pipe(pipe, VB2_BUF_STATE_QUEUED, true); 946 goto out_unlock; 947 } 948 949 /* Input system HW workaround */ 950 atomisp_dma_burst_len_cfg(asd); 951 952 /* Invalidate caches. FIXME: should flush only necessary buffers */ 953 wbinvd(); 954 955 if (asd->params.css_update_params_needed) { 956 atomisp_apply_css_parameters(asd, &asd->params.css_param); 957 if (asd->params.css_param.update_flag.dz_config) 958 asd->params.config.dz_config = &asd->params.css_param.dz_config; 959 atomisp_css_update_isp_params(asd); 960 asd->params.css_update_params_needed = false; 961 memset(&asd->params.css_param.update_flag, 0, 962 sizeof(struct atomisp_parameters)); 963 } 964 asd->params.dvs_6axis = NULL; 965 966 ret = atomisp_css_start(asd); 967 if (ret) { 968 atomisp_flush_video_pipe(pipe, VB2_BUF_STATE_QUEUED, true); 969 media_pipeline_stop(&asd->video_out.vdev.entity.pads[0]); 970 goto out_unlock; 971 } 972 973 spin_lock_irqsave(&isp->lock, irqflags); 974 asd->streaming = true; 975 spin_unlock_irqrestore(&isp->lock, irqflags); 976 atomic_set(&asd->sof_count, 0); 977 atomic_set(&asd->sequence, 0); 978 atomic_set(&asd->sequence_temp, 0); 979 980 asd->params.dis_proj_data_valid = false; 981 asd->latest_preview_exp_id = 0; 982 asd->postview_exp_id = 1; 983 asd->preview_exp_id = 1; 984 985 /* handle per_frame_setting parameter and buffers */ 986 atomisp_handle_parameter_and_buffer(pipe); 987 988 atomisp_qbuffers_to_css(asd); 989 990 atomisp_css_irq_enable(isp, IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF, 991 atomisp_css_valid_sof(isp)); 992 atomisp_csi2_configure(asd); 993 994 if (atomisp_freq_scaling(isp, ATOMISP_DFS_MODE_AUTO, false) < 0) 995 dev_dbg(isp->dev, "DFS auto mode failed!\n"); 996 997 /* Enable the CSI interface on ANN B0/K0 */ 998 if (isp->media_dev.hw_revision >= ((ATOMISP_HW_REVISION_ISP2401 << 999 ATOMISP_HW_REVISION_SHIFT) | ATOMISP_HW_STEPPING_B0)) { 1000 pci_write_config_word(pdev, MRFLD_PCI_CSI_CONTROL, 1001 isp->saved_regs.csi_control | MRFLD_PCI_CSI_CONTROL_CSI_READY); 1002 } 1003 1004 /* stream on the sensor */ 1005 ret = v4l2_subdev_call(isp->inputs[asd->input_curr].csi_remote_source, 1006 video, s_stream, 1); 1007 if (ret) { 1008 dev_err(isp->dev, "Starting sensor stream failed: %d\n", ret); 1009 atomisp_stop_stream(pipe, false, VB2_BUF_STATE_QUEUED); 1010 } 1011 1012out_unlock: 1013 mutex_unlock(&isp->mutex); 1014 return ret; 1015} 1016 1017void atomisp_stop_streaming(struct vb2_queue *vq) 1018{ 1019 struct atomisp_video_pipe *pipe = vq_to_pipe(vq); 1020 struct atomisp_device *isp = pipe->asd->isp; 1021 1022 dev_dbg(isp->dev, "Stop stream\n"); 1023 1024 mutex_lock(&isp->mutex); 1025 atomisp_stop_stream(pipe, true, VB2_BUF_STATE_ERROR); 1026 mutex_unlock(&isp->mutex); 1027} 1028 1029/* 1030 * To get the current value of a control. 1031 * applications initialize the id field of a struct v4l2_control and 1032 * call this ioctl with a pointer to this structure 1033 */ 1034static int atomisp_g_ctrl(struct file *file, void *fh, 1035 struct v4l2_control *control) 1036{ 1037 struct video_device *vdev = video_devdata(file); 1038 struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd; 1039 int i, ret = -EINVAL; 1040 1041 for (i = 0; i < ctrls_num; i++) { 1042 if (ci_v4l2_controls[i].id == control->id) { 1043 ret = 0; 1044 break; 1045 } 1046 } 1047 1048 if (ret) 1049 return ret; 1050 1051 switch (control->id) { 1052 case V4L2_CID_COLORFX: 1053 ret = atomisp_color_effect(asd, 0, &control->value); 1054 break; 1055 case V4L2_CID_ATOMISP_BAD_PIXEL_DETECTION: 1056 ret = atomisp_bad_pixel(asd, 0, &control->value); 1057 break; 1058 case V4L2_CID_ATOMISP_POSTPROCESS_GDC_CAC: 1059 ret = atomisp_gdc_cac(asd, 0, &control->value); 1060 break; 1061 case V4L2_CID_ATOMISP_VIDEO_STABLIZATION: 1062 ret = atomisp_video_stable(asd, 0, &control->value); 1063 break; 1064 case V4L2_CID_ATOMISP_FIXED_PATTERN_NR: 1065 ret = atomisp_fixed_pattern(asd, 0, &control->value); 1066 break; 1067 case V4L2_CID_ATOMISP_FALSE_COLOR_CORRECTION: 1068 ret = atomisp_false_color(asd, 0, &control->value); 1069 break; 1070 case V4L2_CID_ATOMISP_LOW_LIGHT: 1071 ret = atomisp_low_light(asd, 0, &control->value); 1072 break; 1073 default: 1074 ret = -EINVAL; 1075 break; 1076 } 1077 1078 return ret; 1079} 1080 1081/* 1082 * To change the value of a control. 1083 * applications initialize the id and value fields of a struct v4l2_control 1084 * and call this ioctl. 1085 */ 1086static int atomisp_s_ctrl(struct file *file, void *fh, 1087 struct v4l2_control *control) 1088{ 1089 struct video_device *vdev = video_devdata(file); 1090 struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd; 1091 int i, ret = -EINVAL; 1092 1093 for (i = 0; i < ctrls_num; i++) { 1094 if (ci_v4l2_controls[i].id == control->id) { 1095 ret = 0; 1096 break; 1097 } 1098 } 1099 1100 if (ret) 1101 return ret; 1102 1103 switch (control->id) { 1104 case V4L2_CID_COLORFX: 1105 ret = atomisp_color_effect(asd, 1, &control->value); 1106 break; 1107 case V4L2_CID_ATOMISP_BAD_PIXEL_DETECTION: 1108 ret = atomisp_bad_pixel(asd, 1, &control->value); 1109 break; 1110 case V4L2_CID_ATOMISP_POSTPROCESS_GDC_CAC: 1111 ret = atomisp_gdc_cac(asd, 1, &control->value); 1112 break; 1113 case V4L2_CID_ATOMISP_VIDEO_STABLIZATION: 1114 ret = atomisp_video_stable(asd, 1, &control->value); 1115 break; 1116 case V4L2_CID_ATOMISP_FIXED_PATTERN_NR: 1117 ret = atomisp_fixed_pattern(asd, 1, &control->value); 1118 break; 1119 case V4L2_CID_ATOMISP_FALSE_COLOR_CORRECTION: 1120 ret = atomisp_false_color(asd, 1, &control->value); 1121 break; 1122 case V4L2_CID_ATOMISP_LOW_LIGHT: 1123 ret = atomisp_low_light(asd, 1, &control->value); 1124 break; 1125 default: 1126 ret = -EINVAL; 1127 break; 1128 } 1129 return ret; 1130} 1131 1132/* 1133 * To query the attributes of a control. 1134 * applications set the id field of a struct v4l2_query_ext_ctrl and call the 1135 * this ioctl with a pointer to this structure. The driver fills 1136 * the rest of the structure. 1137 */ 1138static int atomisp_query_ext_ctrl(struct file *file, void *fh, 1139 struct v4l2_query_ext_ctrl *qc) 1140{ 1141 int i; 1142 1143 /* TODO: implement V4L2_CTRL_FLAG_NEXT_CTRL */ 1144 if (qc->id & V4L2_CTRL_FLAG_NEXT_CTRL) 1145 return -EINVAL; 1146 1147 for (i = 0; i < ctrls_num; i++) { 1148 if (ci_v4l2_controls[i].id == qc->id) { 1149 *qc = ci_v4l2_controls[i]; 1150 qc->elems = 1; 1151 qc->elem_size = 4; 1152 return 0; 1153 } 1154 } 1155 1156 /* 1157 * This is probably not needed, but this flag has been set for 1158 * many kernel versions. Leave it to avoid breaking any apps. 1159 */ 1160 qc->flags = V4L2_CTRL_FLAG_DISABLED; 1161 return -EINVAL; 1162} 1163 1164static int atomisp_camera_g_ext_ctrls(struct file *file, void *fh, 1165 struct v4l2_ext_controls *c) 1166{ 1167 struct video_device *vdev = video_devdata(file); 1168 struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd; 1169 struct v4l2_control ctrl; 1170 int i; 1171 int ret = 0; 1172 1173 for (i = 0; i < c->count; i++) { 1174 ctrl.id = c->controls[i].id; 1175 ctrl.value = c->controls[i].value; 1176 switch (ctrl.id) { 1177 case V4L2_CID_ZOOM_ABSOLUTE: 1178 ret = atomisp_digital_zoom(asd, 0, &ctrl.value); 1179 break; 1180 default: 1181 ret = -EINVAL; 1182 } 1183 1184 if (ret) { 1185 c->error_idx = i; 1186 break; 1187 } 1188 c->controls[i].value = ctrl.value; 1189 } 1190 return ret; 1191} 1192 1193/* This ioctl allows the application to get multiple controls by class */ 1194static int atomisp_g_ext_ctrls(struct file *file, void *fh, 1195 struct v4l2_ext_controls *c) 1196{ 1197 struct v4l2_control ctrl; 1198 int i, ret = 0; 1199 1200 /* 1201 * input_lock is not need for the Camera related IOCTLs 1202 * The input_lock downgrade the FPS of 3A 1203 */ 1204 ret = atomisp_camera_g_ext_ctrls(file, fh, c); 1205 if (ret != -EINVAL) 1206 return ret; 1207 1208 for (i = 0; i < c->count; i++) { 1209 ctrl.id = c->controls[i].id; 1210 ctrl.value = c->controls[i].value; 1211 ret = atomisp_g_ctrl(file, fh, &ctrl); 1212 c->controls[i].value = ctrl.value; 1213 if (ret) { 1214 c->error_idx = i; 1215 break; 1216 } 1217 } 1218 return ret; 1219} 1220 1221static int atomisp_camera_s_ext_ctrls(struct file *file, void *fh, 1222 struct v4l2_ext_controls *c) 1223{ 1224 struct video_device *vdev = video_devdata(file); 1225 struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd; 1226 struct v4l2_control ctrl; 1227 int i; 1228 int ret = 0; 1229 1230 for (i = 0; i < c->count; i++) { 1231 struct v4l2_ctrl *ctr; 1232 1233 ctrl.id = c->controls[i].id; 1234 ctrl.value = c->controls[i].value; 1235 switch (ctrl.id) { 1236 case V4L2_CID_ZOOM_ABSOLUTE: 1237 ret = atomisp_digital_zoom(asd, 1, &ctrl.value); 1238 break; 1239 default: 1240 ctr = v4l2_ctrl_find(&asd->ctrl_handler, ctrl.id); 1241 if (ctr) 1242 ret = v4l2_ctrl_s_ctrl(ctr, ctrl.value); 1243 else 1244 ret = -EINVAL; 1245 } 1246 1247 if (ret) { 1248 c->error_idx = i; 1249 break; 1250 } 1251 c->controls[i].value = ctrl.value; 1252 } 1253 return ret; 1254} 1255 1256/* This ioctl allows the application to set multiple controls by class */ 1257static int atomisp_s_ext_ctrls(struct file *file, void *fh, 1258 struct v4l2_ext_controls *c) 1259{ 1260 struct v4l2_control ctrl; 1261 int i, ret = 0; 1262 1263 /* 1264 * input_lock is not need for the Camera related IOCTLs 1265 * The input_lock downgrade the FPS of 3A 1266 */ 1267 ret = atomisp_camera_s_ext_ctrls(file, fh, c); 1268 if (ret != -EINVAL) 1269 return ret; 1270 1271 for (i = 0; i < c->count; i++) { 1272 ctrl.id = c->controls[i].id; 1273 ctrl.value = c->controls[i].value; 1274 ret = atomisp_s_ctrl(file, fh, &ctrl); 1275 c->controls[i].value = ctrl.value; 1276 if (ret) { 1277 c->error_idx = i; 1278 break; 1279 } 1280 } 1281 return ret; 1282} 1283 1284/* 1285 * vidioc_g/s_param are used to switch isp running mode 1286 */ 1287static int atomisp_g_parm(struct file *file, void *fh, 1288 struct v4l2_streamparm *parm) 1289{ 1290 struct video_device *vdev = video_devdata(file); 1291 struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd; 1292 struct atomisp_device *isp = video_get_drvdata(vdev); 1293 1294 if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { 1295 dev_err(isp->dev, "unsupported v4l2 buf type\n"); 1296 return -EINVAL; 1297 } 1298 1299 parm->parm.capture.capturemode = asd->run_mode->val; 1300 1301 return 0; 1302} 1303 1304static int atomisp_s_parm(struct file *file, void *fh, 1305 struct v4l2_streamparm *parm) 1306{ 1307 struct video_device *vdev = video_devdata(file); 1308 struct atomisp_device *isp = video_get_drvdata(vdev); 1309 struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd; 1310 int mode; 1311 int rval; 1312 int fps; 1313 1314 if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { 1315 dev_err(isp->dev, "unsupported v4l2 buf type\n"); 1316 return -EINVAL; 1317 } 1318 1319 asd->high_speed_mode = false; 1320 switch (parm->parm.capture.capturemode) { 1321 case CI_MODE_NONE: { 1322 struct v4l2_subdev_frame_interval fi = {0}; 1323 1324 fi.interval = parm->parm.capture.timeperframe; 1325 1326 rval = v4l2_subdev_call_state_active(isp->inputs[asd->input_curr].csi_remote_source, 1327 pad, set_frame_interval, &fi); 1328 if (!rval) 1329 parm->parm.capture.timeperframe = fi.interval; 1330 1331 if (fi.interval.numerator != 0) { 1332 fps = fi.interval.denominator / fi.interval.numerator; 1333 if (fps > 30) 1334 asd->high_speed_mode = true; 1335 } 1336 1337 return rval == -ENOIOCTLCMD ? 0 : rval; 1338 } 1339 case CI_MODE_VIDEO: 1340 mode = ATOMISP_RUN_MODE_VIDEO; 1341 break; 1342 case CI_MODE_STILL_CAPTURE: 1343 mode = ATOMISP_RUN_MODE_STILL_CAPTURE; 1344 break; 1345 case CI_MODE_PREVIEW: 1346 mode = ATOMISP_RUN_MODE_PREVIEW; 1347 break; 1348 default: 1349 return -EINVAL; 1350 } 1351 1352 rval = v4l2_ctrl_s_ctrl(asd->run_mode, mode); 1353 1354 return rval == -ENOIOCTLCMD ? 0 : rval; 1355} 1356 1357static long atomisp_vidioc_default(struct file *file, void *fh, 1358 bool valid_prio, unsigned int cmd, void *arg) 1359{ 1360 struct video_device *vdev = video_devdata(file); 1361 struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd; 1362 int err; 1363 1364 switch (cmd) { 1365 case ATOMISP_IOC_G_XNR: 1366 err = atomisp_xnr(asd, 0, arg); 1367 break; 1368 1369 case ATOMISP_IOC_S_XNR: 1370 err = atomisp_xnr(asd, 1, arg); 1371 break; 1372 1373 case ATOMISP_IOC_G_NR: 1374 err = atomisp_nr(asd, 0, arg); 1375 break; 1376 1377 case ATOMISP_IOC_S_NR: 1378 err = atomisp_nr(asd, 1, arg); 1379 break; 1380 1381 case ATOMISP_IOC_G_TNR: 1382 err = atomisp_tnr(asd, 0, arg); 1383 break; 1384 1385 case ATOMISP_IOC_S_TNR: 1386 err = atomisp_tnr(asd, 1, arg); 1387 break; 1388 1389 case ATOMISP_IOC_G_BLACK_LEVEL_COMP: 1390 err = atomisp_black_level(asd, 0, arg); 1391 break; 1392 1393 case ATOMISP_IOC_S_BLACK_LEVEL_COMP: 1394 err = atomisp_black_level(asd, 1, arg); 1395 break; 1396 1397 case ATOMISP_IOC_G_EE: 1398 err = atomisp_ee(asd, 0, arg); 1399 break; 1400 1401 case ATOMISP_IOC_S_EE: 1402 err = atomisp_ee(asd, 1, arg); 1403 break; 1404 1405 case ATOMISP_IOC_G_DIS_STAT: 1406 err = atomisp_get_dis_stat(asd, arg); 1407 break; 1408 1409 case ATOMISP_IOC_G_DVS2_BQ_RESOLUTIONS: 1410 err = atomisp_get_dvs2_bq_resolutions(asd, arg); 1411 break; 1412 1413 case ATOMISP_IOC_S_DIS_COEFS: 1414 err = atomisp_css_cp_dvs2_coefs(asd, arg, 1415 &asd->params.css_param, true); 1416 if (!err && arg) 1417 asd->params.css_update_params_needed = true; 1418 break; 1419 1420 case ATOMISP_IOC_S_DIS_VECTOR: 1421 err = atomisp_cp_dvs_6axis_config(asd, arg, 1422 &asd->params.css_param, true); 1423 if (!err && arg) 1424 asd->params.css_update_params_needed = true; 1425 break; 1426 1427 case ATOMISP_IOC_G_ISP_PARM: 1428 err = atomisp_param(asd, 0, arg); 1429 break; 1430 1431 case ATOMISP_IOC_S_ISP_PARM: 1432 err = atomisp_param(asd, 1, arg); 1433 break; 1434 1435 case ATOMISP_IOC_G_3A_STAT: 1436 err = atomisp_3a_stat(asd, 0, arg); 1437 break; 1438 1439 case ATOMISP_IOC_G_ISP_GAMMA: 1440 err = atomisp_gamma(asd, 0, arg); 1441 break; 1442 1443 case ATOMISP_IOC_S_ISP_GAMMA: 1444 err = atomisp_gamma(asd, 1, arg); 1445 break; 1446 1447 case ATOMISP_IOC_G_ISP_GDC_TAB: 1448 err = atomisp_gdc_cac_table(asd, 0, arg); 1449 break; 1450 1451 case ATOMISP_IOC_S_ISP_GDC_TAB: 1452 err = atomisp_gdc_cac_table(asd, 1, arg); 1453 break; 1454 1455 case ATOMISP_IOC_G_ISP_MACC: 1456 err = atomisp_macc_table(asd, 0, arg); 1457 break; 1458 1459 case ATOMISP_IOC_S_ISP_MACC: 1460 err = atomisp_macc_table(asd, 1, arg); 1461 break; 1462 1463 case ATOMISP_IOC_G_ISP_BAD_PIXEL_DETECTION: 1464 err = atomisp_bad_pixel_param(asd, 0, arg); 1465 break; 1466 1467 case ATOMISP_IOC_S_ISP_BAD_PIXEL_DETECTION: 1468 err = atomisp_bad_pixel_param(asd, 1, arg); 1469 break; 1470 1471 case ATOMISP_IOC_G_ISP_FALSE_COLOR_CORRECTION: 1472 err = atomisp_false_color_param(asd, 0, arg); 1473 break; 1474 1475 case ATOMISP_IOC_S_ISP_FALSE_COLOR_CORRECTION: 1476 err = atomisp_false_color_param(asd, 1, arg); 1477 break; 1478 1479 case ATOMISP_IOC_G_ISP_CTC: 1480 err = atomisp_ctc(asd, 0, arg); 1481 break; 1482 1483 case ATOMISP_IOC_S_ISP_CTC: 1484 err = atomisp_ctc(asd, 1, arg); 1485 break; 1486 1487 case ATOMISP_IOC_G_ISP_WHITE_BALANCE: 1488 err = atomisp_white_balance_param(asd, 0, arg); 1489 break; 1490 1491 case ATOMISP_IOC_S_ISP_WHITE_BALANCE: 1492 err = atomisp_white_balance_param(asd, 1, arg); 1493 break; 1494 1495 case ATOMISP_IOC_G_3A_CONFIG: 1496 err = atomisp_3a_config_param(asd, 0, arg); 1497 break; 1498 1499 case ATOMISP_IOC_S_3A_CONFIG: 1500 err = atomisp_3a_config_param(asd, 1, arg); 1501 break; 1502 1503 case ATOMISP_IOC_S_ISP_FPN_TABLE: 1504 err = atomisp_fixed_pattern_table(asd, arg); 1505 break; 1506 1507 case ATOMISP_IOC_S_ISP_SHD_TAB: 1508 err = atomisp_set_shading_table(asd, arg); 1509 break; 1510 1511 case ATOMISP_IOC_G_ISP_GAMMA_CORRECTION: 1512 err = atomisp_gamma_correction(asd, 0, arg); 1513 break; 1514 1515 case ATOMISP_IOC_S_ISP_GAMMA_CORRECTION: 1516 err = atomisp_gamma_correction(asd, 1, arg); 1517 break; 1518 1519 case ATOMISP_IOC_S_PARAMETERS: 1520 err = atomisp_set_parameters(vdev, arg); 1521 break; 1522 1523 case ATOMISP_IOC_EXP_ID_UNLOCK: 1524 err = atomisp_exp_id_unlock(asd, arg); 1525 break; 1526 case ATOMISP_IOC_EXP_ID_CAPTURE: 1527 err = atomisp_exp_id_capture(asd, arg); 1528 break; 1529 case ATOMISP_IOC_S_ENABLE_DZ_CAPT_PIPE: 1530 err = atomisp_enable_dz_capt_pipe(asd, arg); 1531 break; 1532 case ATOMISP_IOC_G_FORMATS_CONFIG: 1533 err = atomisp_formats(asd, 0, arg); 1534 break; 1535 1536 case ATOMISP_IOC_S_FORMATS_CONFIG: 1537 err = atomisp_formats(asd, 1, arg); 1538 break; 1539 case ATOMISP_IOC_INJECT_A_FAKE_EVENT: 1540 err = atomisp_inject_a_fake_event(asd, arg); 1541 break; 1542 case ATOMISP_IOC_S_ARRAY_RESOLUTION: 1543 err = atomisp_set_array_res(asd, arg); 1544 break; 1545 default: 1546 err = -EINVAL; 1547 break; 1548 } 1549 1550 return err; 1551} 1552 1553const struct v4l2_ioctl_ops atomisp_ioctl_ops = { 1554 .vidioc_querycap = atomisp_querycap, 1555 .vidioc_enum_input = atomisp_enum_input, 1556 .vidioc_g_input = atomisp_g_input, 1557 .vidioc_s_input = atomisp_s_input, 1558 .vidioc_query_ext_ctrl = atomisp_query_ext_ctrl, 1559 .vidioc_s_ext_ctrls = atomisp_s_ext_ctrls, 1560 .vidioc_g_ext_ctrls = atomisp_g_ext_ctrls, 1561 .vidioc_enum_framesizes = atomisp_enum_framesizes, 1562 .vidioc_enum_frameintervals = atomisp_enum_frameintervals, 1563 .vidioc_enum_fmt_vid_cap = atomisp_enum_fmt_cap, 1564 .vidioc_try_fmt_vid_cap = atomisp_try_fmt_cap, 1565 .vidioc_g_fmt_vid_cap = atomisp_g_fmt_cap, 1566 .vidioc_s_fmt_vid_cap = atomisp_s_fmt_cap, 1567 .vidioc_reqbufs = vb2_ioctl_reqbufs, 1568 .vidioc_querybuf = vb2_ioctl_querybuf, 1569 .vidioc_qbuf = atomisp_qbuf_wrapper, 1570 .vidioc_dqbuf = atomisp_dqbuf_wrapper, 1571 .vidioc_expbuf = vb2_ioctl_expbuf, 1572 .vidioc_streamon = vb2_ioctl_streamon, 1573 .vidioc_streamoff = vb2_ioctl_streamoff, 1574 .vidioc_default = atomisp_vidioc_default, 1575 .vidioc_s_parm = atomisp_s_parm, 1576 .vidioc_g_parm = atomisp_g_parm, 1577};
~/
Read-only file preview.