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