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 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License version 9 * 2 as published by the Free Software Foundation. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * 17 */ 18 #include <linux/module.h> 19 #include <linux/uaccess.h> 20 #include <linux/delay.h> 21 #include <linux/device.h> 22 #include <linux/mm.h> 23 #include <linux/sched.h> 24 #include <linux/slab.h> 25 26 #include <media/v4l2-event.h> 27 #include <media/v4l2-mediabus.h> 28 #include "atomisp_cmd.h" 29 #include "atomisp_common.h" 30 #include "atomisp_compat.h" 31 #include "atomisp_internal.h" 32 33 const struct atomisp_in_fmt_conv atomisp_in_fmt_conv[] = { 34 { MEDIA_BUS_FMT_SBGGR8_1X8, 8, 8, ATOMISP_INPUT_FORMAT_RAW_8, IA_CSS_BAYER_ORDER_BGGR }, 35 { MEDIA_BUS_FMT_SGBRG8_1X8, 8, 8, ATOMISP_INPUT_FORMAT_RAW_8, IA_CSS_BAYER_ORDER_GBRG }, 36 { MEDIA_BUS_FMT_SGRBG8_1X8, 8, 8, ATOMISP_INPUT_FORMAT_RAW_8, IA_CSS_BAYER_ORDER_GRBG }, 37 { MEDIA_BUS_FMT_SRGGB8_1X8, 8, 8, ATOMISP_INPUT_FORMAT_RAW_8, IA_CSS_BAYER_ORDER_RGGB }, 38 { MEDIA_BUS_FMT_SBGGR10_1X10, 10, 10, ATOMISP_INPUT_FORMAT_RAW_10, IA_CSS_BAYER_ORDER_BGGR }, 39 { MEDIA_BUS_FMT_SGBRG10_1X10, 10, 10, ATOMISP_INPUT_FORMAT_RAW_10, IA_CSS_BAYER_ORDER_GBRG }, 40 { MEDIA_BUS_FMT_SGRBG10_1X10, 10, 10, ATOMISP_INPUT_FORMAT_RAW_10, IA_CSS_BAYER_ORDER_GRBG }, 41 { MEDIA_BUS_FMT_SRGGB10_1X10, 10, 10, ATOMISP_INPUT_FORMAT_RAW_10, IA_CSS_BAYER_ORDER_RGGB }, 42 { MEDIA_BUS_FMT_SBGGR12_1X12, 12, 12, ATOMISP_INPUT_FORMAT_RAW_12, IA_CSS_BAYER_ORDER_BGGR }, 43 { MEDIA_BUS_FMT_SGBRG12_1X12, 12, 12, ATOMISP_INPUT_FORMAT_RAW_12, IA_CSS_BAYER_ORDER_GBRG }, 44 { MEDIA_BUS_FMT_SGRBG12_1X12, 12, 12, ATOMISP_INPUT_FORMAT_RAW_12, IA_CSS_BAYER_ORDER_GRBG }, 45 { MEDIA_BUS_FMT_SRGGB12_1X12, 12, 12, ATOMISP_INPUT_FORMAT_RAW_12, IA_CSS_BAYER_ORDER_RGGB }, 46 { MEDIA_BUS_FMT_UYVY8_1X16, 8, 8, ATOMISP_INPUT_FORMAT_YUV422_8, 0 }, 47 { MEDIA_BUS_FMT_YUYV8_1X16, 8, 8, ATOMISP_INPUT_FORMAT_YUV422_8, 0 }, 48 #if 0 // disabled due to clang warnings 49 { MEDIA_BUS_FMT_JPEG_1X8, 8, 8, IA_CSS_FRAME_FORMAT_BINARY_8, 0 }, 50 { V4L2_MBUS_FMT_CUSTOM_NV12, 12, 12, IA_CSS_FRAME_FORMAT_NV12, 0 }, 51 { V4L2_MBUS_FMT_CUSTOM_NV21, 12, 12, IA_CSS_FRAME_FORMAT_NV21, 0 }, 52 #endif 53 { V4L2_MBUS_FMT_CUSTOM_YUV420, 12, 12, ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY, 0 }, 54 #if 0 55 { V4L2_MBUS_FMT_CUSTOM_M10MO_RAW, 8, 8, IA_CSS_FRAME_FORMAT_BINARY_8, 0 }, 56 #endif 57 /* no valid V4L2 MBUS code for metadata format, so leave it 0. */ 58 { 0, 0, 0, ATOMISP_INPUT_FORMAT_EMBEDDED, 0 }, 59 {} 60 }; 61 62 static const struct { 63 u32 code; 64 u32 compressed; 65 } compressed_codes[] = { 66 { MEDIA_BUS_FMT_SBGGR10_1X10, MEDIA_BUS_FMT_SBGGR10_DPCM8_1X8 }, 67 { MEDIA_BUS_FMT_SGBRG10_1X10, MEDIA_BUS_FMT_SGBRG10_DPCM8_1X8 }, 68 { MEDIA_BUS_FMT_SGRBG10_1X10, MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8 }, 69 { MEDIA_BUS_FMT_SRGGB10_1X10, MEDIA_BUS_FMT_SRGGB10_DPCM8_1X8 }, 70 }; 71 72 u32 atomisp_subdev_uncompressed_code(u32 code) 73 { 74 unsigned int i; 75 76 for (i = 0; i < ARRAY_SIZE(compressed_codes); i++) 77 if (code == compressed_codes[i].compressed) 78 return compressed_codes[i].code; 79 80 return code; 81 } 82 83 bool atomisp_subdev_is_compressed(u32 code) 84 { 85 int i; 86 87 for (i = 0; i < ARRAY_SIZE(atomisp_in_fmt_conv) - 1; i++) 88 if (code == atomisp_in_fmt_conv[i].code) 89 return atomisp_in_fmt_conv[i].bpp != 90 atomisp_in_fmt_conv[i].depth; 91 92 return false; 93 } 94 95 const struct atomisp_in_fmt_conv *atomisp_find_in_fmt_conv(u32 code) 96 { 97 int i; 98 99 for (i = 0; i < ARRAY_SIZE(atomisp_in_fmt_conv) - 1; i++) 100 if (code == atomisp_in_fmt_conv[i].code) 101 return atomisp_in_fmt_conv + i; 102 103 return NULL; 104 } 105 106 const struct atomisp_in_fmt_conv *atomisp_find_in_fmt_conv_by_atomisp_in_fmt( 107 enum atomisp_input_format atomisp_in_fmt) 108 { 109 int i; 110 111 for (i = 0; i < ARRAY_SIZE(atomisp_in_fmt_conv) - 1; i++) 112 if (atomisp_in_fmt_conv[i].atomisp_in_fmt == atomisp_in_fmt) 113 return atomisp_in_fmt_conv + i; 114 115 return NULL; 116 } 117 118 bool atomisp_subdev_format_conversion(struct atomisp_sub_device *asd, 119 unsigned int source_pad) 120 { 121 struct v4l2_mbus_framefmt *sink, *src; 122 123 sink = atomisp_subdev_get_ffmt(&asd->subdev, NULL, 124 V4L2_SUBDEV_FORMAT_ACTIVE, 125 ATOMISP_SUBDEV_PAD_SINK); 126 src = atomisp_subdev_get_ffmt(&asd->subdev, NULL, 127 V4L2_SUBDEV_FORMAT_ACTIVE, source_pad); 128 129 return atomisp_is_mbuscode_raw(sink->code) 130 && !atomisp_is_mbuscode_raw(src->code); 131 } 132 133 uint16_t atomisp_subdev_source_pad(struct video_device *vdev) 134 { 135 struct media_link *link; 136 u16 ret = 0; 137 138 list_for_each_entry(link, &vdev->entity.links, list) { 139 if (link->source) { 140 ret = link->source->index; 141 break; 142 } 143 } 144 return ret; 145 } 146 147 /* 148 * V4L2 subdev operations 149 */ 150 151 /* 152 * isp_subdev_ioctl - CCDC module private ioctl's 153 * @sd: ISP V4L2 subdevice 154 * @cmd: ioctl command 155 * @arg: ioctl argument 156 * 157 * Return 0 on success or a negative error code otherwise. 158 */ 159 static long isp_subdev_ioctl(struct v4l2_subdev *sd, 160 unsigned int cmd, void *arg) 161 { 162 return 0; 163 } 164 165 /* 166 * isp_subdev_set_power - Power on/off the CCDC module 167 * @sd: ISP V4L2 subdevice 168 * @on: power on/off 169 * 170 * Return 0 on success or a negative error code otherwise. 171 */ 172 static int isp_subdev_set_power(struct v4l2_subdev *sd, int on) 173 { 174 return 0; 175 } 176 177 static int isp_subdev_subscribe_event(struct v4l2_subdev *sd, 178 struct v4l2_fh *fh, 179 struct v4l2_event_subscription *sub) 180 { 181 struct atomisp_sub_device *isp_sd = v4l2_get_subdevdata(sd); 182 struct atomisp_device *isp = isp_sd->isp; 183 184 if (sub->type != V4L2_EVENT_FRAME_SYNC && 185 sub->type != V4L2_EVENT_FRAME_END && 186 sub->type != V4L2_EVENT_ATOMISP_3A_STATS_READY && 187 sub->type != V4L2_EVENT_ATOMISP_METADATA_READY && 188 sub->type != V4L2_EVENT_ATOMISP_PAUSE_BUFFER && 189 sub->type != V4L2_EVENT_ATOMISP_CSS_RESET && 190 sub->type != V4L2_EVENT_ATOMISP_RAW_BUFFERS_ALLOC_DONE && 191 sub->type != V4L2_EVENT_ATOMISP_ACC_COMPLETE) 192 return -EINVAL; 193 194 if (sub->type == V4L2_EVENT_FRAME_SYNC && 195 !atomisp_css_valid_sof(isp)) 196 return -EINVAL; 197 198 return v4l2_event_subscribe(fh, sub, 16, NULL); 199 } 200 201 static int isp_subdev_unsubscribe_event(struct v4l2_subdev *sd, 202 struct v4l2_fh *fh, 203 struct v4l2_event_subscription *sub) 204 { 205 return v4l2_event_unsubscribe(fh, sub); 206 } 207 208 /* 209 * isp_subdev_enum_mbus_code - Handle pixel format enumeration 210 * @sd: pointer to v4l2 subdev structure 211 * @fh : V4L2 subdev file handle 212 * @code: pointer to v4l2_subdev_pad_mbus_code_enum structure 213 * return -EINVAL or zero on success 214 */ 215 static int isp_subdev_enum_mbus_code(struct v4l2_subdev *sd, 216 struct v4l2_subdev_state *sd_state, 217 struct v4l2_subdev_mbus_code_enum *code) 218 { 219 if (code->index >= ARRAY_SIZE(atomisp_in_fmt_conv) - 1) 220 return -EINVAL; 221 222 code->code = atomisp_in_fmt_conv[code->index].code; 223 224 return 0; 225 } 226 227 static int isp_subdev_validate_rect(struct v4l2_subdev *sd, uint32_t pad, 228 uint32_t target) 229 { 230 switch (pad) { 231 case ATOMISP_SUBDEV_PAD_SINK: 232 switch (target) { 233 case V4L2_SEL_TGT_CROP: 234 return 0; 235 } 236 break; 237 default: 238 switch (target) { 239 case V4L2_SEL_TGT_COMPOSE: 240 return 0; 241 } 242 break; 243 } 244 245 return -EINVAL; 246 } 247 248 struct v4l2_rect *atomisp_subdev_get_rect(struct v4l2_subdev *sd, 249 struct v4l2_subdev_state *sd_state, 250 u32 which, uint32_t pad, 251 uint32_t target) 252 { 253 struct atomisp_sub_device *isp_sd = v4l2_get_subdevdata(sd); 254 255 if (which == V4L2_SUBDEV_FORMAT_TRY) { 256 switch (target) { 257 case V4L2_SEL_TGT_CROP: 258 return v4l2_subdev_get_try_crop(sd, sd_state, pad); 259 case V4L2_SEL_TGT_COMPOSE: 260 return v4l2_subdev_get_try_compose(sd, sd_state, pad); 261 } 262 } 263 264 switch (target) { 265 case V4L2_SEL_TGT_CROP: 266 return &isp_sd->fmt[pad].crop; 267 case V4L2_SEL_TGT_COMPOSE: 268 return &isp_sd->fmt[pad].compose; 269 } 270 271 return NULL; 272 } 273 274 struct v4l2_mbus_framefmt 275 *atomisp_subdev_get_ffmt(struct v4l2_subdev *sd, 276 struct v4l2_subdev_state *sd_state, uint32_t which, 277 uint32_t pad) 278 { 279 struct atomisp_sub_device *isp_sd = v4l2_get_subdevdata(sd); 280 281 if (which == V4L2_SUBDEV_FORMAT_TRY) 282 return v4l2_subdev_get_try_format(sd, sd_state, pad); 283 284 return &isp_sd->fmt[pad].fmt; 285 } 286 287 static void isp_get_fmt_rect(struct v4l2_subdev *sd, 288 struct v4l2_subdev_state *sd_state, 289 uint32_t which, 290 struct v4l2_mbus_framefmt **ffmt, 291 struct v4l2_rect *crop[ATOMISP_SUBDEV_PADS_NUM], 292 struct v4l2_rect *comp[ATOMISP_SUBDEV_PADS_NUM]) 293 { 294 unsigned int i; 295 296 for (i = 0; i < ATOMISP_SUBDEV_PADS_NUM; i++) { 297 ffmt[i] = atomisp_subdev_get_ffmt(sd, sd_state, which, i); 298 crop[i] = atomisp_subdev_get_rect(sd, sd_state, which, i, 299 V4L2_SEL_TGT_CROP); 300 comp[i] = atomisp_subdev_get_rect(sd, sd_state, which, i, 301 V4L2_SEL_TGT_COMPOSE); 302 } 303 } 304 305 static void isp_subdev_propagate(struct v4l2_subdev *sd, 306 struct v4l2_subdev_state *sd_state, 307 u32 which, uint32_t pad, uint32_t target, 308 uint32_t flags) 309 { 310 struct v4l2_mbus_framefmt *ffmt[ATOMISP_SUBDEV_PADS_NUM]; 311 struct v4l2_rect *crop[ATOMISP_SUBDEV_PADS_NUM], 312 *comp[ATOMISP_SUBDEV_PADS_NUM]; 313 314 if (flags & V4L2_SEL_FLAG_KEEP_CONFIG) 315 return; 316 317 isp_get_fmt_rect(sd, sd_state, which, ffmt, crop, comp); 318 319 switch (pad) { 320 case ATOMISP_SUBDEV_PAD_SINK: { 321 struct v4l2_rect r = {0}; 322 323 /* Only crop target supported on sink pad. */ 324 r.width = ffmt[pad]->width; 325 r.height = ffmt[pad]->height; 326 327 atomisp_subdev_set_selection(sd, sd_state, which, pad, 328 target, flags, &r); 329 break; 330 } 331 } 332 } 333 334 static int isp_subdev_get_selection(struct v4l2_subdev *sd, 335 struct v4l2_subdev_state *sd_state, 336 struct v4l2_subdev_selection *sel) 337 { 338 struct v4l2_rect *rec; 339 int rval = isp_subdev_validate_rect(sd, sel->pad, sel->target); 340 341 if (rval) 342 return rval; 343 344 rec = atomisp_subdev_get_rect(sd, sd_state, sel->which, sel->pad, 345 sel->target); 346 if (!rec) 347 return -EINVAL; 348 349 sel->r = *rec; 350 return 0; 351 } 352 353 static const char *atomisp_pad_str(unsigned int pad) 354 { 355 static const char *const pad_str[] = { 356 "ATOMISP_SUBDEV_PAD_SINK", 357 "ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE", 358 "ATOMISP_SUBDEV_PAD_SOURCE_VF", 359 "ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW", 360 "ATOMISP_SUBDEV_PAD_SOURCE_VIDEO", 361 }; 362 363 if (pad >= ARRAY_SIZE(pad_str)) 364 return "ATOMISP_INVALID_PAD"; 365 return pad_str[pad]; 366 } 367 368 int atomisp_subdev_set_selection(struct v4l2_subdev *sd, 369 struct v4l2_subdev_state *sd_state, 370 u32 which, uint32_t pad, uint32_t target, 371 u32 flags, struct v4l2_rect *r) 372 { 373 struct atomisp_sub_device *isp_sd = v4l2_get_subdevdata(sd); 374 struct atomisp_device *isp = isp_sd->isp; 375 struct v4l2_mbus_framefmt *ffmt[ATOMISP_SUBDEV_PADS_NUM]; 376 struct v4l2_rect *crop[ATOMISP_SUBDEV_PADS_NUM], 377 *comp[ATOMISP_SUBDEV_PADS_NUM]; 378 unsigned int i; 379 unsigned int padding_w = pad_w; 380 unsigned int padding_h = pad_h; 381 382 isp_get_fmt_rect(sd, sd_state, which, ffmt, crop, comp); 383 384 dev_dbg(isp->dev, 385 "sel: pad %s tgt %s l %d t %d w %d h %d which %s f 0x%8.8x\n", 386 atomisp_pad_str(pad), target == V4L2_SEL_TGT_CROP 387 ? "V4L2_SEL_TGT_CROP" : "V4L2_SEL_TGT_COMPOSE", 388 r->left, r->top, r->width, r->height, 389 which == V4L2_SUBDEV_FORMAT_TRY ? "V4L2_SUBDEV_FORMAT_TRY" 390 : "V4L2_SUBDEV_FORMAT_ACTIVE", flags); 391 392 r->width = rounddown(r->width, ATOM_ISP_STEP_WIDTH); 393 r->height = rounddown(r->height, ATOM_ISP_STEP_HEIGHT); 394 395 switch (pad) { 396 case ATOMISP_SUBDEV_PAD_SINK: { 397 /* Only crop target supported on sink pad. */ 398 unsigned int dvs_w, dvs_h; 399 400 crop[pad]->width = ffmt[pad]->width; 401 crop[pad]->height = ffmt[pad]->height; 402 403 /* Workaround for BYT 1080p perfectshot since the maxinum resolution of 404 * front camera ov2722 is 1932x1092 and cannot use pad_w > 12*/ 405 if (!strncmp(isp->inputs[isp_sd->input_curr].camera->name, 406 "ov2722", 6) && crop[pad]->height == 1092) { 407 padding_w = 12; 408 padding_h = 12; 409 } 410 411 if (isp->inputs[isp_sd->input_curr].type == SOC_CAMERA) { 412 padding_w = 0; 413 padding_h = 0; 414 } 415 416 if (atomisp_subdev_format_conversion(isp_sd, 417 isp_sd->capture_pad) 418 && crop[pad]->width && crop[pad]->height) { 419 crop[pad]->width -= padding_w; 420 crop[pad]->height -= padding_h; 421 } 422 423 /* if subdev type is SOC camera,we do not need to set DVS */ 424 if (isp->inputs[isp_sd->input_curr].type == SOC_CAMERA) 425 isp_sd->params.video_dis_en = 0; 426 427 if (isp_sd->params.video_dis_en && 428 isp_sd->run_mode->val == ATOMISP_RUN_MODE_VIDEO && 429 !isp_sd->continuous_mode->val) { 430 /* This resolution contains 20 % of DVS slack 431 * (of the desired captured image before 432 * scaling, or 1 / 6 of what we get from the 433 * sensor) in both width and height. Remove 434 * it. */ 435 crop[pad]->width = roundup(crop[pad]->width * 5 / 6, 436 ATOM_ISP_STEP_WIDTH); 437 crop[pad]->height = roundup(crop[pad]->height * 5 / 6, 438 ATOM_ISP_STEP_HEIGHT); 439 } 440 441 crop[pad]->width = min(crop[pad]->width, r->width); 442 crop[pad]->height = min(crop[pad]->height, r->height); 443 444 if (!(flags & V4L2_SEL_FLAG_KEEP_CONFIG)) { 445 for (i = ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE; 446 i < ATOMISP_SUBDEV_PADS_NUM; i++) { 447 struct v4l2_rect tmp = *crop[pad]; 448 449 atomisp_subdev_set_selection( 450 sd, sd_state, which, i, 451 V4L2_SEL_TGT_COMPOSE, 452 flags, &tmp); 453 } 454 } 455 456 if (which == V4L2_SUBDEV_FORMAT_TRY) 457 break; 458 459 if (isp_sd->params.video_dis_en && 460 isp_sd->run_mode->val == ATOMISP_RUN_MODE_VIDEO && 461 !isp_sd->continuous_mode->val) { 462 dvs_w = rounddown(crop[pad]->width / 5, 463 ATOM_ISP_STEP_WIDTH); 464 dvs_h = rounddown(crop[pad]->height / 5, 465 ATOM_ISP_STEP_HEIGHT); 466 } else if (!isp_sd->params.video_dis_en && 467 isp_sd->run_mode->val == ATOMISP_RUN_MODE_VIDEO) { 468 /* 469 * For CSS2.0, digital zoom needs to set dvs envelope to 12 470 * when dvs is disabled. 471 */ 472 dvs_w = dvs_h = 12; 473 } else { 474 dvs_w = dvs_h = 0; 475 } 476 atomisp_css_video_set_dis_envelope(isp_sd, dvs_w, dvs_h); 477 atomisp_css_input_set_effective_resolution(isp_sd, 478 ATOMISP_INPUT_STREAM_GENERAL, 479 crop[pad]->width, 480 crop[pad]->height); 481 break; 482 } 483 case ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE: 484 case ATOMISP_SUBDEV_PAD_SOURCE_VIDEO: { 485 /* Only compose target is supported on source pads. */ 486 487 if (isp_sd->vfpp->val == ATOMISP_VFPP_DISABLE_LOWLAT) { 488 /* Scaling is disabled in this mode */ 489 r->width = crop[ATOMISP_SUBDEV_PAD_SINK]->width; 490 r->height = crop[ATOMISP_SUBDEV_PAD_SINK]->height; 491 } 492 493 if (crop[ATOMISP_SUBDEV_PAD_SINK]->width == r->width 494 && crop[ATOMISP_SUBDEV_PAD_SINK]->height == r->height) 495 isp_sd->params.yuv_ds_en = false; 496 else 497 isp_sd->params.yuv_ds_en = true; 498 499 comp[pad]->width = r->width; 500 comp[pad]->height = r->height; 501 502 if (r->width == 0 || r->height == 0 || 503 crop[ATOMISP_SUBDEV_PAD_SINK]->width == 0 || 504 crop[ATOMISP_SUBDEV_PAD_SINK]->height == 0) 505 break; 506 /* 507 * do cropping on sensor input if ratio of required resolution 508 * is different with sensor output resolution ratio: 509 * 510 * ratio = width / height 511 * 512 * if ratio_output < ratio_sensor: 513 * effect_width = sensor_height * out_width / out_height; 514 * effect_height = sensor_height; 515 * else 516 * effect_width = sensor_width; 517 * effect_height = sensor_width * out_height / out_width; 518 * 519 */ 520 if (r->width * crop[ATOMISP_SUBDEV_PAD_SINK]->height < 521 crop[ATOMISP_SUBDEV_PAD_SINK]->width * r->height) 522 atomisp_css_input_set_effective_resolution(isp_sd, 523 ATOMISP_INPUT_STREAM_GENERAL, 524 rounddown(crop[ATOMISP_SUBDEV_PAD_SINK]-> 525 height * r->width / r->height, 526 ATOM_ISP_STEP_WIDTH), 527 crop[ATOMISP_SUBDEV_PAD_SINK]->height); 528 else 529 atomisp_css_input_set_effective_resolution(isp_sd, 530 ATOMISP_INPUT_STREAM_GENERAL, 531 crop[ATOMISP_SUBDEV_PAD_SINK]->width, 532 rounddown(crop[ATOMISP_SUBDEV_PAD_SINK]-> 533 width * r->height / r->width, 534 ATOM_ISP_STEP_WIDTH)); 535 536 break; 537 } 538 case ATOMISP_SUBDEV_PAD_SOURCE_VF: 539 case ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW: 540 comp[pad]->width = r->width; 541 comp[pad]->height = r->height; 542 break; 543 default: 544 return -EINVAL; 545 } 546 547 /* Set format dimensions on non-sink pads as well. */ 548 if (pad != ATOMISP_SUBDEV_PAD_SINK) { 549 ffmt[pad]->width = comp[pad]->width; 550 ffmt[pad]->height = comp[pad]->height; 551 } 552 553 if (!atomisp_subdev_get_rect(sd, sd_state, which, pad, target)) 554 return -EINVAL; 555 *r = *atomisp_subdev_get_rect(sd, sd_state, which, pad, target); 556 557 dev_dbg(isp->dev, "sel actual: l %d t %d w %d h %d\n", 558 r->left, r->top, r->width, r->height); 559 560 return 0; 561 } 562 563 static int isp_subdev_set_selection(struct v4l2_subdev *sd, 564 struct v4l2_subdev_state *sd_state, 565 struct v4l2_subdev_selection *sel) 566 { 567 int rval = isp_subdev_validate_rect(sd, sel->pad, sel->target); 568 569 if (rval) 570 return rval; 571 572 return atomisp_subdev_set_selection(sd, sd_state, sel->which, 573 sel->pad, 574 sel->target, sel->flags, &sel->r); 575 } 576 577 static int atomisp_get_sensor_bin_factor(struct atomisp_sub_device *asd) 578 { 579 struct v4l2_control ctrl = {0}; 580 struct atomisp_device *isp = asd->isp; 581 int hbin, vbin; 582 int ret; 583 584 if (isp->inputs[asd->input_curr].type == FILE_INPUT || 585 isp->inputs[asd->input_curr].type == TEST_PATTERN) 586 return 0; 587 588 ctrl.id = V4L2_CID_BIN_FACTOR_HORZ; 589 ret = 590 v4l2_g_ctrl(isp->inputs[asd->input_curr].camera->ctrl_handler, 591 &ctrl); 592 hbin = ctrl.value; 593 ctrl.id = V4L2_CID_BIN_FACTOR_VERT; 594 ret |= 595 v4l2_g_ctrl(isp->inputs[asd->input_curr].camera->ctrl_handler, 596 &ctrl); 597 vbin = ctrl.value; 598 599 /* 600 * ISP needs to know binning factor from sensor. 601 * In case horizontal and vertical sensor's binning factors 602 * are different or sensor does not support binning factor CID, 603 * ISP will apply default 0 value. 604 */ 605 if (ret || hbin != vbin) 606 hbin = 0; 607 608 return hbin; 609 } 610 611 void atomisp_subdev_set_ffmt(struct v4l2_subdev *sd, 612 struct v4l2_subdev_state *sd_state, 613 uint32_t which, 614 u32 pad, struct v4l2_mbus_framefmt *ffmt) 615 { 616 struct atomisp_sub_device *isp_sd = v4l2_get_subdevdata(sd); 617 struct atomisp_device *isp = isp_sd->isp; 618 struct v4l2_mbus_framefmt *__ffmt = 619 atomisp_subdev_get_ffmt(sd, sd_state, which, pad); 620 621 dev_dbg(isp->dev, "ffmt: pad %s w %d h %d code 0x%8.8x which %s\n", 622 atomisp_pad_str(pad), ffmt->width, ffmt->height, ffmt->code, 623 which == V4L2_SUBDEV_FORMAT_TRY ? "V4L2_SUBDEV_FORMAT_TRY" 624 : "V4L2_SUBDEV_FORMAT_ACTIVE"); 625 626 switch (pad) { 627 case ATOMISP_SUBDEV_PAD_SINK: { 628 const struct atomisp_in_fmt_conv *fc = 629 atomisp_find_in_fmt_conv(ffmt->code); 630 631 if (!fc) { 632 fc = atomisp_in_fmt_conv; 633 ffmt->code = fc->code; 634 dev_dbg(isp->dev, "using 0x%8.8x instead\n", 635 ffmt->code); 636 } 637 638 *__ffmt = *ffmt; 639 640 isp_subdev_propagate(sd, sd_state, which, pad, 641 V4L2_SEL_TGT_CROP, 0); 642 643 if (which == V4L2_SUBDEV_FORMAT_ACTIVE) { 644 atomisp_css_input_set_resolution(isp_sd, 645 ATOMISP_INPUT_STREAM_GENERAL, ffmt); 646 atomisp_css_input_set_binning_factor(isp_sd, 647 ATOMISP_INPUT_STREAM_GENERAL, 648 atomisp_get_sensor_bin_factor(isp_sd)); 649 atomisp_css_input_set_bayer_order(isp_sd, ATOMISP_INPUT_STREAM_GENERAL, 650 fc->bayer_order); 651 atomisp_css_input_set_format(isp_sd, ATOMISP_INPUT_STREAM_GENERAL, 652 fc->atomisp_in_fmt); 653 atomisp_css_set_default_isys_config(isp_sd, ATOMISP_INPUT_STREAM_GENERAL, 654 ffmt); 655 } 656 657 break; 658 } 659 case ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE: 660 case ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW: 661 case ATOMISP_SUBDEV_PAD_SOURCE_VF: 662 case ATOMISP_SUBDEV_PAD_SOURCE_VIDEO: 663 __ffmt->code = ffmt->code; 664 break; 665 } 666 } 667 668 /* 669 * isp_subdev_get_format - Retrieve the video format on a pad 670 * @sd : ISP V4L2 subdevice 671 * @fh : V4L2 subdev file handle 672 * @pad: Pad number 673 * @fmt: Format 674 * 675 * Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond 676 * to the format type. 677 */ 678 static int isp_subdev_get_format(struct v4l2_subdev *sd, 679 struct v4l2_subdev_state *sd_state, 680 struct v4l2_subdev_format *fmt) 681 { 682 fmt->format = *atomisp_subdev_get_ffmt(sd, sd_state, fmt->which, 683 fmt->pad); 684 685 return 0; 686 } 687 688 /* 689 * isp_subdev_set_format - Set the video format on a pad 690 * @sd : ISP subdev V4L2 subdevice 691 * @fh : V4L2 subdev file handle 692 * @pad: Pad number 693 * @fmt: Format 694 * 695 * Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond 696 * to the format type. 697 */ 698 static int isp_subdev_set_format(struct v4l2_subdev *sd, 699 struct v4l2_subdev_state *sd_state, 700 struct v4l2_subdev_format *fmt) 701 { 702 atomisp_subdev_set_ffmt(sd, sd_state, fmt->which, fmt->pad, 703 &fmt->format); 704 705 return 0; 706 } 707 708 /* V4L2 subdev core operations */ 709 static const struct v4l2_subdev_core_ops isp_subdev_v4l2_core_ops = { 710 .ioctl = isp_subdev_ioctl, .s_power = isp_subdev_set_power, 711 .subscribe_event = isp_subdev_subscribe_event, 712 .unsubscribe_event = isp_subdev_unsubscribe_event, 713 }; 714 715 /* V4L2 subdev pad operations */ 716 static const struct v4l2_subdev_pad_ops isp_subdev_v4l2_pad_ops = { 717 .enum_mbus_code = isp_subdev_enum_mbus_code, 718 .get_fmt = isp_subdev_get_format, 719 .set_fmt = isp_subdev_set_format, 720 .get_selection = isp_subdev_get_selection, 721 .set_selection = isp_subdev_set_selection, 722 .link_validate = v4l2_subdev_link_validate_default, 723 }; 724 725 /* V4L2 subdev operations */ 726 static const struct v4l2_subdev_ops isp_subdev_v4l2_ops = { 727 .core = &isp_subdev_v4l2_core_ops, 728 .pad = &isp_subdev_v4l2_pad_ops, 729 }; 730 731 static void isp_subdev_init_params(struct atomisp_sub_device *asd) 732 { 733 unsigned int i; 734 735 /* parameters initialization */ 736 INIT_LIST_HEAD(&asd->s3a_stats); 737 INIT_LIST_HEAD(&asd->s3a_stats_in_css); 738 INIT_LIST_HEAD(&asd->s3a_stats_ready); 739 INIT_LIST_HEAD(&asd->dis_stats); 740 INIT_LIST_HEAD(&asd->dis_stats_in_css); 741 spin_lock_init(&asd->dis_stats_lock); 742 for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) { 743 INIT_LIST_HEAD(&asd->metadata[i]); 744 INIT_LIST_HEAD(&asd->metadata_in_css[i]); 745 INIT_LIST_HEAD(&asd->metadata_ready[i]); 746 } 747 } 748 749 /* 750 * isp_subdev_link_setup - Setup isp subdev connections 751 * @entity: ispsubdev media entity 752 * @local: Pad at the local end of the link 753 * @remote: Pad at the remote end of the link 754 * @flags: Link flags 755 * 756 * return -EINVAL or zero on success 757 */ 758 static int isp_subdev_link_setup(struct media_entity *entity, 759 const struct media_pad *local, 760 const struct media_pad *remote, u32 flags) 761 { 762 struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity); 763 struct atomisp_sub_device *isp_sd = v4l2_get_subdevdata(sd); 764 struct atomisp_device *isp = isp_sd->isp; 765 unsigned int i; 766 767 switch (local->index | is_media_entity_v4l2_subdev(remote->entity)) { 768 case ATOMISP_SUBDEV_PAD_SINK | MEDIA_ENT_F_V4L2_SUBDEV_UNKNOWN: 769 /* Read from the sensor CSI2-ports. */ 770 if (!(flags & MEDIA_LNK_FL_ENABLED)) { 771 isp_sd->input = ATOMISP_SUBDEV_INPUT_NONE; 772 break; 773 } 774 775 if (isp_sd->input != ATOMISP_SUBDEV_INPUT_NONE) 776 return -EBUSY; 777 778 for (i = 0; i < ATOMISP_CAMERA_NR_PORTS; i++) { 779 if (remote->entity != &isp->csi2_port[i].subdev.entity) 780 continue; 781 782 isp_sd->input = ATOMISP_SUBDEV_INPUT_CSI2_PORT1 + i; 783 return 0; 784 } 785 786 return -EINVAL; 787 788 case ATOMISP_SUBDEV_PAD_SINK | MEDIA_ENT_F_OLD_BASE: 789 /* read from memory */ 790 if (flags & MEDIA_LNK_FL_ENABLED) { 791 if (isp_sd->input >= ATOMISP_SUBDEV_INPUT_CSI2_PORT1 && 792 isp_sd->input < (ATOMISP_SUBDEV_INPUT_CSI2_PORT1 793 + ATOMISP_CAMERA_NR_PORTS)) 794 return -EBUSY; 795 isp_sd->input = ATOMISP_SUBDEV_INPUT_MEMORY; 796 } else { 797 if (isp_sd->input == ATOMISP_SUBDEV_INPUT_MEMORY) 798 isp_sd->input = ATOMISP_SUBDEV_INPUT_NONE; 799 } 800 break; 801 802 case ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW | MEDIA_ENT_F_OLD_BASE: 803 /* always write to memory */ 804 break; 805 806 case ATOMISP_SUBDEV_PAD_SOURCE_VF | MEDIA_ENT_F_OLD_BASE: 807 /* always write to memory */ 808 break; 809 810 case ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE | MEDIA_ENT_F_OLD_BASE: 811 /* always write to memory */ 812 break; 813 814 case ATOMISP_SUBDEV_PAD_SOURCE_VIDEO | MEDIA_ENT_F_OLD_BASE: 815 /* always write to memory */ 816 break; 817 818 default: 819 return -EINVAL; 820 } 821 822 return 0; 823 } 824 825 /* media operations */ 826 static const struct media_entity_operations isp_subdev_media_ops = { 827 .link_setup = isp_subdev_link_setup, 828 .link_validate = v4l2_subdev_link_validate, 829 /* .set_power = v4l2_subdev_set_power, */ 830 }; 831 832 static int __atomisp_update_run_mode(struct atomisp_sub_device *asd) 833 { 834 struct atomisp_device *isp = asd->isp; 835 struct v4l2_ctrl *ctrl = asd->run_mode; 836 struct v4l2_ctrl *c; 837 s32 mode; 838 839 if (ctrl->val != ATOMISP_RUN_MODE_VIDEO && 840 asd->continuous_mode->val) 841 mode = ATOMISP_RUN_MODE_PREVIEW; 842 else 843 mode = ctrl->val; 844 845 c = v4l2_ctrl_find( 846 isp->inputs[asd->input_curr].camera->ctrl_handler, 847 V4L2_CID_RUN_MODE); 848 849 if (c) 850 return v4l2_ctrl_s_ctrl(c, mode); 851 852 return 0; 853 } 854 855 int atomisp_update_run_mode(struct atomisp_sub_device *asd) 856 { 857 int rval; 858 859 mutex_lock(asd->ctrl_handler.lock); 860 rval = __atomisp_update_run_mode(asd); 861 mutex_unlock(asd->ctrl_handler.lock); 862 863 return rval; 864 } 865 866 static int s_ctrl(struct v4l2_ctrl *ctrl) 867 { 868 struct atomisp_sub_device *asd = container_of( 869 ctrl->handler, struct atomisp_sub_device, ctrl_handler); 870 unsigned int streaming; 871 unsigned long flags; 872 873 switch (ctrl->id) { 874 case V4L2_CID_RUN_MODE: 875 return __atomisp_update_run_mode(asd); 876 case V4L2_CID_DEPTH_MODE: 877 /* Use spinlock instead of mutex to avoid possible locking issues */ 878 spin_lock_irqsave(&asd->isp->lock, flags); 879 streaming = asd->streaming; 880 spin_unlock_irqrestore(&asd->isp->lock, flags); 881 if (streaming != ATOMISP_DEVICE_STREAMING_DISABLED) { 882 dev_err(asd->isp->dev, 883 "ISP is streaming, it is not supported to change the depth mode\n"); 884 return -EINVAL; 885 } 886 break; 887 } 888 889 return 0; 890 } 891 892 static const struct v4l2_ctrl_ops ctrl_ops = { 893 .s_ctrl = &s_ctrl, 894 }; 895 896 static const struct v4l2_ctrl_config ctrl_fmt_auto = { 897 .ops = &ctrl_ops, 898 .id = V4L2_CID_FMT_AUTO, 899 .name = "Automatic format guessing", 900 .type = V4L2_CTRL_TYPE_BOOLEAN, 901 .min = 0, 902 .max = 1, 903 .step = 1, 904 .def = 1, 905 }; 906 907 static const char *const ctrl_run_mode_menu[] = { 908 NULL, 909 "Video", 910 "Still capture", 911 "Continuous capture", 912 "Preview", 913 }; 914 915 static const struct v4l2_ctrl_config ctrl_run_mode = { 916 .ops = &ctrl_ops, 917 .id = V4L2_CID_RUN_MODE, 918 .name = "Atomisp run mode", 919 .type = V4L2_CTRL_TYPE_MENU, 920 .min = 1, 921 .def = 1, 922 .max = 4, 923 .qmenu = ctrl_run_mode_menu, 924 }; 925 926 static const char *const ctrl_vfpp_mode_menu[] = { 927 "Enable", /* vfpp always enabled */ 928 "Disable to scaler mode", /* CSS into video mode and disable */ 929 "Disable to low latency mode", /* CSS into still mode and disable */ 930 }; 931 932 static const struct v4l2_ctrl_config ctrl_vfpp = { 933 .id = V4L2_CID_VFPP, 934 .name = "Atomisp vf postprocess", 935 .type = V4L2_CTRL_TYPE_MENU, 936 .min = 0, 937 .def = 0, 938 .max = 2, 939 .qmenu = ctrl_vfpp_mode_menu, 940 }; 941 942 /* 943 * Control for ISP continuous mode 944 * 945 * When enabled, capture processing is possible without 946 * stopping the preview pipeline. When disabled, ISP needs 947 * to be restarted between preview and capture. 948 */ 949 static const struct v4l2_ctrl_config ctrl_continuous_mode = { 950 .ops = &ctrl_ops, 951 .id = V4L2_CID_ATOMISP_CONTINUOUS_MODE, 952 .type = V4L2_CTRL_TYPE_BOOLEAN, 953 .name = "Continuous mode", 954 .min = 0, 955 .max = 1, 956 .step = 1, 957 .def = 0, 958 }; 959 960 /* 961 * Control for continuous mode raw buffer size 962 * 963 * The size of the RAW ringbuffer sets limit on how much 964 * back in time application can go when requesting capture 965 * frames to be rendered, and how many frames can be rendered 966 * in a burst at full sensor rate. 967 * 968 * Note: this setting has a big impact on memory consumption of 969 * the CSS subsystem. 970 */ 971 static const struct v4l2_ctrl_config ctrl_continuous_raw_buffer_size = { 972 .ops = &ctrl_ops, 973 .id = V4L2_CID_ATOMISP_CONTINUOUS_RAW_BUFFER_SIZE, 974 .type = V4L2_CTRL_TYPE_INTEGER, 975 .name = "Continuous raw ringbuffer size", 976 .min = 1, 977 .max = 100, /* depends on CSS version, runtime checked */ 978 .step = 1, 979 .def = 3, 980 }; 981 982 /* 983 * Control for enabling continuous viewfinder 984 * 985 * When enabled, and ISP is in continuous mode (see ctrl_continuous_mode ), 986 * preview pipeline continues concurrently with capture 987 * processing. When disabled, and continuous mode is used, 988 * preview is paused while captures are processed, but 989 * full pipeline restart is not needed. 990 * 991 * By setting this to disabled, capture processing is 992 * essentially given priority over preview, and the effective 993 * capture output rate may be higher than with continuous 994 * viewfinder enabled. 995 */ 996 static const struct v4l2_ctrl_config ctrl_continuous_viewfinder = { 997 .id = V4L2_CID_ATOMISP_CONTINUOUS_VIEWFINDER, 998 .type = V4L2_CTRL_TYPE_BOOLEAN, 999 .name = "Continuous viewfinder", 1000 .min = 0, 1001 .max = 1, 1002 .step = 1, 1003 .def = 0, 1004 }; 1005 1006 /* 1007 * Control for enabling Lock&Unlock Raw Buffer mechanism 1008 * 1009 * When enabled, Raw Buffer can be locked and unlocked. 1010 * Application can hold the exp_id of Raw Buffer 1011 * and unlock it when no longer needed. 1012 * Note: Make sure set this configuration before creating stream. 1013 */ 1014 static const struct v4l2_ctrl_config ctrl_enable_raw_buffer_lock = { 1015 .id = V4L2_CID_ENABLE_RAW_BUFFER_LOCK, 1016 .type = V4L2_CTRL_TYPE_BOOLEAN, 1017 .name = "Lock Unlock Raw Buffer", 1018 .min = 0, 1019 .max = 1, 1020 .step = 1, 1021 .def = 0, 1022 }; 1023 1024 /* 1025 * Control to disable digital zoom of the whole stream 1026 * 1027 * When it is true, pipe configuration enable_dz will be set to false. 1028 * This can help get a better performance by disabling pp binary. 1029 * 1030 * Note: Make sure set this configuration before creating stream. 1031 */ 1032 static const struct v4l2_ctrl_config ctrl_disable_dz = { 1033 .id = V4L2_CID_DISABLE_DZ, 1034 .type = V4L2_CTRL_TYPE_BOOLEAN, 1035 .name = "Disable digital zoom", 1036 .min = 0, 1037 .max = 1, 1038 .step = 1, 1039 .def = 0, 1040 }; 1041 1042 /* 1043 * Control for ISP depth mode 1044 * 1045 * When enabled, that means ISP will deal with dual streams and sensors will be 1046 * in slave/master mode. 1047 * slave sensor will have no output until master sensor is streamed on. 1048 */ 1049 static const struct v4l2_ctrl_config ctrl_depth_mode = { 1050 .ops = &ctrl_ops, 1051 .id = V4L2_CID_DEPTH_MODE, 1052 .type = V4L2_CTRL_TYPE_BOOLEAN, 1053 .name = "Depth mode", 1054 .min = 0, 1055 .max = 1, 1056 .step = 1, 1057 .def = 0, 1058 }; 1059 1060 static void atomisp_init_subdev_pipe(struct atomisp_sub_device *asd, 1061 struct atomisp_video_pipe *pipe, enum v4l2_buf_type buf_type) 1062 { 1063 pipe->type = buf_type; 1064 pipe->asd = asd; 1065 pipe->isp = asd->isp; 1066 spin_lock_init(&pipe->irq_lock); 1067 mutex_init(&pipe->vb_queue_mutex); 1068 INIT_LIST_HEAD(&pipe->buffers_in_css); 1069 INIT_LIST_HEAD(&pipe->activeq); 1070 INIT_LIST_HEAD(&pipe->buffers_waiting_for_param); 1071 INIT_LIST_HEAD(&pipe->per_frame_params); 1072 memset(pipe->frame_request_config_id, 1073 0, VIDEO_MAX_FRAME * sizeof(unsigned int)); 1074 memset(pipe->frame_params, 1075 0, VIDEO_MAX_FRAME * 1076 sizeof(struct atomisp_css_params_with_list *)); 1077 } 1078 1079 /* 1080 * isp_subdev_init_entities - Initialize V4L2 subdev and media entity 1081 * @asd: ISP CCDC module 1082 * 1083 * Return 0 on success and a negative error code on failure. 1084 */ 1085 static int isp_subdev_init_entities(struct atomisp_sub_device *asd) 1086 { 1087 struct v4l2_subdev *sd = &asd->subdev; 1088 struct media_pad *pads = asd->pads; 1089 struct media_entity *me = &sd->entity; 1090 int ret; 1091 1092 asd->input = ATOMISP_SUBDEV_INPUT_NONE; 1093 1094 v4l2_subdev_init(sd, &isp_subdev_v4l2_ops); 1095 sprintf(sd->name, "ATOMISP_SUBDEV_%d", asd->index); 1096 v4l2_set_subdevdata(sd, asd); 1097 sd->flags |= V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_HAS_DEVNODE; 1098 1099 pads[ATOMISP_SUBDEV_PAD_SINK].flags = MEDIA_PAD_FL_SINK; 1100 pads[ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW].flags = MEDIA_PAD_FL_SOURCE; 1101 pads[ATOMISP_SUBDEV_PAD_SOURCE_VF].flags = MEDIA_PAD_FL_SOURCE; 1102 pads[ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE].flags = MEDIA_PAD_FL_SOURCE; 1103 pads[ATOMISP_SUBDEV_PAD_SOURCE_VIDEO].flags = MEDIA_PAD_FL_SOURCE; 1104 1105 asd->fmt[ATOMISP_SUBDEV_PAD_SINK].fmt.code = 1106 MEDIA_BUS_FMT_SBGGR10_1X10; 1107 asd->fmt[ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW].fmt.code = 1108 MEDIA_BUS_FMT_SBGGR10_1X10; 1109 asd->fmt[ATOMISP_SUBDEV_PAD_SOURCE_VF].fmt.code = 1110 MEDIA_BUS_FMT_SBGGR10_1X10; 1111 asd->fmt[ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE].fmt.code = 1112 MEDIA_BUS_FMT_SBGGR10_1X10; 1113 asd->fmt[ATOMISP_SUBDEV_PAD_SOURCE_VIDEO].fmt.code = 1114 MEDIA_BUS_FMT_SBGGR10_1X10; 1115 1116 me->ops = &isp_subdev_media_ops; 1117 me->function = MEDIA_ENT_F_V4L2_SUBDEV_UNKNOWN; 1118 ret = media_entity_pads_init(me, ATOMISP_SUBDEV_PADS_NUM, pads); 1119 if (ret < 0) 1120 return ret; 1121 1122 atomisp_init_subdev_pipe(asd, &asd->video_out_preview, 1123 V4L2_BUF_TYPE_VIDEO_CAPTURE); 1124 1125 atomisp_init_subdev_pipe(asd, &asd->video_out_vf, 1126 V4L2_BUF_TYPE_VIDEO_CAPTURE); 1127 1128 atomisp_init_subdev_pipe(asd, &asd->video_out_capture, 1129 V4L2_BUF_TYPE_VIDEO_CAPTURE); 1130 1131 atomisp_init_subdev_pipe(asd, &asd->video_out_video_capture, 1132 V4L2_BUF_TYPE_VIDEO_CAPTURE); 1133 1134 ret = atomisp_video_init(&asd->video_out_capture, "CAPTURE", 1135 ATOMISP_RUN_MODE_STILL_CAPTURE); 1136 if (ret < 0) 1137 return ret; 1138 1139 ret = atomisp_video_init(&asd->video_out_vf, "VIEWFINDER", 1140 ATOMISP_RUN_MODE_CONTINUOUS_CAPTURE); 1141 if (ret < 0) 1142 return ret; 1143 1144 ret = atomisp_video_init(&asd->video_out_preview, "PREVIEW", 1145 ATOMISP_RUN_MODE_PREVIEW); 1146 if (ret < 0) 1147 return ret; 1148 1149 ret = atomisp_video_init(&asd->video_out_video_capture, "VIDEO", 1150 ATOMISP_RUN_MODE_VIDEO); 1151 if (ret < 0) 1152 return ret; 1153 1154 ret = v4l2_ctrl_handler_init(&asd->ctrl_handler, 1); 1155 if (ret) 1156 return ret; 1157 1158 asd->fmt_auto = v4l2_ctrl_new_custom(&asd->ctrl_handler, 1159 &ctrl_fmt_auto, NULL); 1160 asd->run_mode = v4l2_ctrl_new_custom(&asd->ctrl_handler, 1161 &ctrl_run_mode, NULL); 1162 asd->vfpp = v4l2_ctrl_new_custom(&asd->ctrl_handler, 1163 &ctrl_vfpp, NULL); 1164 asd->continuous_mode = v4l2_ctrl_new_custom(&asd->ctrl_handler, 1165 &ctrl_continuous_mode, NULL); 1166 asd->continuous_viewfinder = v4l2_ctrl_new_custom(&asd->ctrl_handler, 1167 &ctrl_continuous_viewfinder, 1168 NULL); 1169 asd->continuous_raw_buffer_size = 1170 v4l2_ctrl_new_custom(&asd->ctrl_handler, 1171 &ctrl_continuous_raw_buffer_size, 1172 NULL); 1173 1174 asd->enable_raw_buffer_lock = 1175 v4l2_ctrl_new_custom(&asd->ctrl_handler, 1176 &ctrl_enable_raw_buffer_lock, 1177 NULL); 1178 asd->depth_mode = 1179 v4l2_ctrl_new_custom(&asd->ctrl_handler, 1180 &ctrl_depth_mode, 1181 NULL); 1182 asd->disable_dz = 1183 v4l2_ctrl_new_custom(&asd->ctrl_handler, 1184 &ctrl_disable_dz, 1185 NULL); 1186 1187 /* Make controls visible on subdev as well. */ 1188 asd->subdev.ctrl_handler = &asd->ctrl_handler; 1189 spin_lock_init(&asd->raw_buffer_bitmap_lock); 1190 return asd->ctrl_handler.error; 1191 } 1192 1193 int atomisp_create_pads_links(struct atomisp_device *isp) 1194 { 1195 struct atomisp_sub_device *asd; 1196 int i, j, ret = 0; 1197 1198 isp->num_of_streams = 2; 1199 for (i = 0; i < ATOMISP_CAMERA_NR_PORTS; i++) { 1200 for (j = 0; j < isp->num_of_streams; j++) { 1201 ret = 1202 media_create_pad_link(&isp->csi2_port[i].subdev. 1203 entity, CSI2_PAD_SOURCE, 1204 &isp->asd[j].subdev.entity, 1205 ATOMISP_SUBDEV_PAD_SINK, 0); 1206 if (ret < 0) 1207 return ret; 1208 } 1209 } 1210 for (i = 0; i < isp->input_cnt; i++) { 1211 /* Don't create links for the test-pattern-generator */ 1212 if (isp->inputs[i].type == TEST_PATTERN) 1213 continue; 1214 1215 ret = media_create_pad_link(&isp->inputs[i].camera->entity, 0, 1216 &isp->csi2_port[isp->inputs[i]. 1217 port].subdev.entity, 1218 CSI2_PAD_SINK, 1219 MEDIA_LNK_FL_ENABLED | 1220 MEDIA_LNK_FL_IMMUTABLE); 1221 if (ret < 0) 1222 return ret; 1223 } 1224 for (i = 0; i < isp->num_of_streams; i++) { 1225 asd = &isp->asd[i]; 1226 ret = media_create_pad_link(&asd->subdev.entity, 1227 ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW, 1228 &asd->video_out_preview.vdev.entity, 1229 0, 0); 1230 if (ret < 0) 1231 return ret; 1232 ret = media_create_pad_link(&asd->subdev.entity, 1233 ATOMISP_SUBDEV_PAD_SOURCE_VF, 1234 &asd->video_out_vf.vdev.entity, 0, 1235 0); 1236 if (ret < 0) 1237 return ret; 1238 ret = media_create_pad_link(&asd->subdev.entity, 1239 ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE, 1240 &asd->video_out_capture.vdev.entity, 1241 0, 0); 1242 if (ret < 0) 1243 return ret; 1244 ret = media_create_pad_link(&asd->subdev.entity, 1245 ATOMISP_SUBDEV_PAD_SOURCE_VIDEO, 1246 &asd->video_out_video_capture.vdev. 1247 entity, 0, 0); 1248 if (ret < 0) 1249 return ret; 1250 } 1251 return 0; 1252 } 1253 1254 static void atomisp_subdev_cleanup_entities(struct atomisp_sub_device *asd) 1255 { 1256 v4l2_ctrl_handler_free(&asd->ctrl_handler); 1257 1258 media_entity_cleanup(&asd->subdev.entity); 1259 } 1260 1261 void atomisp_subdev_cleanup_pending_events(struct atomisp_sub_device *asd) 1262 { 1263 struct v4l2_fh *fh, *fh_tmp; 1264 struct v4l2_event event; 1265 unsigned int i, pending_event; 1266 1267 list_for_each_entry_safe(fh, fh_tmp, 1268 &asd->subdev.devnode->fh_list, list) { 1269 pending_event = v4l2_event_pending(fh); 1270 for (i = 0; i < pending_event; i++) 1271 v4l2_event_dequeue(fh, &event, 1); 1272 } 1273 } 1274 1275 void atomisp_subdev_unregister_entities(struct atomisp_sub_device *asd) 1276 { 1277 atomisp_subdev_cleanup_entities(asd); 1278 v4l2_device_unregister_subdev(&asd->subdev); 1279 atomisp_video_unregister(&asd->video_out_preview); 1280 atomisp_video_unregister(&asd->video_out_vf); 1281 atomisp_video_unregister(&asd->video_out_capture); 1282 atomisp_video_unregister(&asd->video_out_video_capture); 1283 } 1284 1285 int atomisp_subdev_register_subdev(struct atomisp_sub_device *asd, 1286 struct v4l2_device *vdev) 1287 { 1288 return v4l2_device_register_subdev(vdev, &asd->subdev); 1289 } 1290 1291 int atomisp_subdev_register_video_nodes(struct atomisp_sub_device *asd, 1292 struct v4l2_device *vdev) 1293 { 1294 int ret; 1295 1296 /* 1297 * FIXME: check if all device caps are properly initialized. 1298 * Should any of those use V4L2_CAP_META_CAPTURE? Probably yes. 1299 */ 1300 1301 asd->video_out_preview.vdev.v4l2_dev = vdev; 1302 asd->video_out_preview.vdev.device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; 1303 ret = video_register_device(&asd->video_out_preview.vdev, 1304 VFL_TYPE_VIDEO, -1); 1305 if (ret < 0) 1306 goto error; 1307 1308 asd->video_out_capture.vdev.v4l2_dev = vdev; 1309 asd->video_out_capture.vdev.device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; 1310 ret = video_register_device(&asd->video_out_capture.vdev, 1311 VFL_TYPE_VIDEO, -1); 1312 if (ret < 0) 1313 goto error; 1314 1315 asd->video_out_vf.vdev.v4l2_dev = vdev; 1316 asd->video_out_vf.vdev.device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; 1317 ret = video_register_device(&asd->video_out_vf.vdev, 1318 VFL_TYPE_VIDEO, -1); 1319 if (ret < 0) 1320 goto error; 1321 1322 asd->video_out_video_capture.vdev.v4l2_dev = vdev; 1323 asd->video_out_video_capture.vdev.device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; 1324 ret = video_register_device(&asd->video_out_video_capture.vdev, 1325 VFL_TYPE_VIDEO, -1); 1326 if (ret < 0) 1327 goto error; 1328 1329 return 0; 1330 1331 error: 1332 atomisp_subdev_unregister_entities(asd); 1333 return ret; 1334 } 1335 1336 /* 1337 * atomisp_subdev_init - ISP Subdevice initialization. 1338 * @dev: Device pointer specific to the ATOM ISP. 1339 * 1340 * TODO: Get the initialisation values from platform data. 1341 * 1342 * Return 0 on success or a negative error code otherwise. 1343 */ 1344 int atomisp_subdev_init(struct atomisp_device *isp) 1345 { 1346 struct atomisp_sub_device *asd; 1347 int i, ret = 0; 1348 1349 /* 1350 * CSS2.0 running ISP2400 support 1351 * multiple streams 1352 */ 1353 isp->num_of_streams = 2; 1354 isp->asd = devm_kzalloc(isp->dev, sizeof(struct atomisp_sub_device) * 1355 isp->num_of_streams, GFP_KERNEL); 1356 if (!isp->asd) 1357 return -ENOMEM; 1358 for (i = 0; i < isp->num_of_streams; i++) { 1359 asd = &isp->asd[i]; 1360 asd->isp = isp; 1361 isp_subdev_init_params(asd); 1362 asd->index = i; 1363 ret = isp_subdev_init_entities(asd); 1364 if (ret < 0) { 1365 atomisp_subdev_cleanup_entities(asd); 1366 break; 1367 } 1368 } 1369 1370 return ret; 1371 } 1372