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 u16 vdev_pad = atomisp_subdev_source_pad(sd->devnode); 377 struct v4l2_rect *crop[ATOMISP_SUBDEV_PADS_NUM], 378 *comp[ATOMISP_SUBDEV_PADS_NUM]; 379 enum atomisp_input_stream_id stream_id; 380 unsigned int i; 381 unsigned int padding_w = pad_w; 382 unsigned int padding_h = pad_h; 383 384 stream_id = atomisp_source_pad_to_stream_id(isp_sd, vdev_pad); 385 386 isp_get_fmt_rect(sd, sd_state, which, ffmt, crop, comp); 387 388 dev_dbg(isp->dev, 389 "sel: pad %s tgt %s l %d t %d w %d h %d which %s f 0x%8.8x\n", 390 atomisp_pad_str(pad), target == V4L2_SEL_TGT_CROP 391 ? "V4L2_SEL_TGT_CROP" : "V4L2_SEL_TGT_COMPOSE", 392 r->left, r->top, r->width, r->height, 393 which == V4L2_SUBDEV_FORMAT_TRY ? "V4L2_SUBDEV_FORMAT_TRY" 394 : "V4L2_SUBDEV_FORMAT_ACTIVE", flags); 395 396 r->width = rounddown(r->width, ATOM_ISP_STEP_WIDTH); 397 r->height = rounddown(r->height, ATOM_ISP_STEP_HEIGHT); 398 399 switch (pad) { 400 case ATOMISP_SUBDEV_PAD_SINK: { 401 /* Only crop target supported on sink pad. */ 402 unsigned int dvs_w, dvs_h; 403 404 crop[pad]->width = ffmt[pad]->width; 405 crop[pad]->height = ffmt[pad]->height; 406 407 /* Workaround for BYT 1080p perfectshot since the maxinum resolution of 408 * front camera ov2722 is 1932x1092 and cannot use pad_w > 12*/ 409 if (!strncmp(isp->inputs[isp_sd->input_curr].camera->name, 410 "ov2722", 6) && crop[pad]->height == 1092) { 411 padding_w = 12; 412 padding_h = 12; 413 } 414 415 if (isp->inputs[isp_sd->input_curr].type == SOC_CAMERA) { 416 padding_w = 0; 417 padding_h = 0; 418 } 419 420 if (atomisp_subdev_format_conversion(isp_sd, 421 isp_sd->capture_pad) 422 && crop[pad]->width && crop[pad]->height) { 423 crop[pad]->width -= padding_w; 424 crop[pad]->height -= padding_h; 425 } 426 427 /* if subdev type is SOC camera,we do not need to set DVS */ 428 if (isp->inputs[isp_sd->input_curr].type == SOC_CAMERA) 429 isp_sd->params.video_dis_en = 0; 430 431 if (isp_sd->params.video_dis_en && 432 isp_sd->run_mode->val == ATOMISP_RUN_MODE_VIDEO && 433 !isp_sd->continuous_mode->val) { 434 /* This resolution contains 20 % of DVS slack 435 * (of the desired captured image before 436 * scaling, or 1 / 6 of what we get from the 437 * sensor) in both width and height. Remove 438 * it. */ 439 crop[pad]->width = roundup(crop[pad]->width * 5 / 6, 440 ATOM_ISP_STEP_WIDTH); 441 crop[pad]->height = roundup(crop[pad]->height * 5 / 6, 442 ATOM_ISP_STEP_HEIGHT); 443 } 444 445 crop[pad]->width = min(crop[pad]->width, r->width); 446 crop[pad]->height = min(crop[pad]->height, r->height); 447 448 if (!(flags & V4L2_SEL_FLAG_KEEP_CONFIG)) { 449 for (i = ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE; 450 i < ATOMISP_SUBDEV_PADS_NUM; i++) { 451 struct v4l2_rect tmp = *crop[pad]; 452 453 atomisp_subdev_set_selection( 454 sd, sd_state, which, i, 455 V4L2_SEL_TGT_COMPOSE, 456 flags, &tmp); 457 } 458 } 459 460 if (which == V4L2_SUBDEV_FORMAT_TRY) 461 break; 462 463 if (isp_sd->params.video_dis_en && 464 isp_sd->run_mode->val == ATOMISP_RUN_MODE_VIDEO && 465 !isp_sd->continuous_mode->val) { 466 dvs_w = rounddown(crop[pad]->width / 5, 467 ATOM_ISP_STEP_WIDTH); 468 dvs_h = rounddown(crop[pad]->height / 5, 469 ATOM_ISP_STEP_HEIGHT); 470 } else if (!isp_sd->params.video_dis_en && 471 isp_sd->run_mode->val == ATOMISP_RUN_MODE_VIDEO) { 472 /* 473 * For CSS2.0, digital zoom needs to set dvs envelope to 12 474 * when dvs is disabled. 475 */ 476 dvs_w = dvs_h = 12; 477 } else { 478 dvs_w = dvs_h = 0; 479 } 480 atomisp_css_video_set_dis_envelope(isp_sd, dvs_w, dvs_h); 481 atomisp_css_input_set_effective_resolution(isp_sd, stream_id, 482 crop[pad]->width, crop[pad]->height); 483 484 break; 485 } 486 case ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE: 487 case ATOMISP_SUBDEV_PAD_SOURCE_VIDEO: { 488 /* Only compose target is supported on source pads. */ 489 490 if (isp_sd->vfpp->val == ATOMISP_VFPP_DISABLE_LOWLAT) { 491 /* Scaling is disabled in this mode */ 492 r->width = crop[ATOMISP_SUBDEV_PAD_SINK]->width; 493 r->height = crop[ATOMISP_SUBDEV_PAD_SINK]->height; 494 } 495 496 if (crop[ATOMISP_SUBDEV_PAD_SINK]->width == r->width 497 && crop[ATOMISP_SUBDEV_PAD_SINK]->height == r->height) 498 isp_sd->params.yuv_ds_en = false; 499 else 500 isp_sd->params.yuv_ds_en = true; 501 502 comp[pad]->width = r->width; 503 comp[pad]->height = r->height; 504 505 if (r->width == 0 || r->height == 0 || 506 crop[ATOMISP_SUBDEV_PAD_SINK]->width == 0 || 507 crop[ATOMISP_SUBDEV_PAD_SINK]->height == 0) 508 break; 509 /* 510 * do cropping on sensor input if ratio of required resolution 511 * is different with sensor output resolution ratio: 512 * 513 * ratio = width / height 514 * 515 * if ratio_output < ratio_sensor: 516 * effect_width = sensor_height * out_width / out_height; 517 * effect_height = sensor_height; 518 * else 519 * effect_width = sensor_width; 520 * effect_height = sensor_width * out_height / out_width; 521 * 522 */ 523 if (r->width * crop[ATOMISP_SUBDEV_PAD_SINK]->height < 524 crop[ATOMISP_SUBDEV_PAD_SINK]->width * r->height) 525 atomisp_css_input_set_effective_resolution(isp_sd, 526 stream_id, 527 rounddown(crop[ATOMISP_SUBDEV_PAD_SINK]-> 528 height * r->width / r->height, 529 ATOM_ISP_STEP_WIDTH), 530 crop[ATOMISP_SUBDEV_PAD_SINK]->height); 531 else 532 atomisp_css_input_set_effective_resolution(isp_sd, 533 stream_id, 534 crop[ATOMISP_SUBDEV_PAD_SINK]->width, 535 rounddown(crop[ATOMISP_SUBDEV_PAD_SINK]-> 536 width * r->height / r->width, 537 ATOM_ISP_STEP_WIDTH)); 538 539 break; 540 } 541 case ATOMISP_SUBDEV_PAD_SOURCE_VF: 542 case ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW: 543 comp[pad]->width = r->width; 544 comp[pad]->height = r->height; 545 break; 546 default: 547 return -EINVAL; 548 } 549 550 /* Set format dimensions on non-sink pads as well. */ 551 if (pad != ATOMISP_SUBDEV_PAD_SINK) { 552 ffmt[pad]->width = comp[pad]->width; 553 ffmt[pad]->height = comp[pad]->height; 554 } 555 556 if (!atomisp_subdev_get_rect(sd, sd_state, which, pad, target)) 557 return -EINVAL; 558 *r = *atomisp_subdev_get_rect(sd, sd_state, which, pad, target); 559 560 dev_dbg(isp->dev, "sel actual: l %d t %d w %d h %d\n", 561 r->left, r->top, r->width, r->height); 562 563 return 0; 564 } 565 566 static int isp_subdev_set_selection(struct v4l2_subdev *sd, 567 struct v4l2_subdev_state *sd_state, 568 struct v4l2_subdev_selection *sel) 569 { 570 int rval = isp_subdev_validate_rect(sd, sel->pad, sel->target); 571 572 if (rval) 573 return rval; 574 575 return atomisp_subdev_set_selection(sd, sd_state, sel->which, 576 sel->pad, 577 sel->target, sel->flags, &sel->r); 578 } 579 580 static int atomisp_get_sensor_bin_factor(struct atomisp_sub_device *asd) 581 { 582 struct v4l2_control ctrl = {0}; 583 struct atomisp_device *isp = asd->isp; 584 int hbin, vbin; 585 int ret; 586 587 if (isp->inputs[asd->input_curr].type == FILE_INPUT || 588 isp->inputs[asd->input_curr].type == TEST_PATTERN) 589 return 0; 590 591 ctrl.id = V4L2_CID_BIN_FACTOR_HORZ; 592 ret = 593 v4l2_g_ctrl(isp->inputs[asd->input_curr].camera->ctrl_handler, 594 &ctrl); 595 hbin = ctrl.value; 596 ctrl.id = V4L2_CID_BIN_FACTOR_VERT; 597 ret |= 598 v4l2_g_ctrl(isp->inputs[asd->input_curr].camera->ctrl_handler, 599 &ctrl); 600 vbin = ctrl.value; 601 602 /* 603 * ISP needs to know binning factor from sensor. 604 * In case horizontal and vertical sensor's binning factors 605 * are different or sensor does not support binning factor CID, 606 * ISP will apply default 0 value. 607 */ 608 if (ret || hbin != vbin) 609 hbin = 0; 610 611 return hbin; 612 } 613 614 void atomisp_subdev_set_ffmt(struct v4l2_subdev *sd, 615 struct v4l2_subdev_state *sd_state, 616 uint32_t which, 617 u32 pad, struct v4l2_mbus_framefmt *ffmt) 618 { 619 struct atomisp_sub_device *isp_sd = v4l2_get_subdevdata(sd); 620 struct atomisp_device *isp = isp_sd->isp; 621 struct v4l2_mbus_framefmt *__ffmt = 622 atomisp_subdev_get_ffmt(sd, sd_state, which, pad); 623 u16 vdev_pad = atomisp_subdev_source_pad(sd->devnode); 624 enum atomisp_input_stream_id stream_id; 625 626 dev_dbg(isp->dev, "ffmt: pad %s w %d h %d code 0x%8.8x which %s\n", 627 atomisp_pad_str(pad), ffmt->width, ffmt->height, ffmt->code, 628 which == V4L2_SUBDEV_FORMAT_TRY ? "V4L2_SUBDEV_FORMAT_TRY" 629 : "V4L2_SUBDEV_FORMAT_ACTIVE"); 630 631 stream_id = atomisp_source_pad_to_stream_id(isp_sd, vdev_pad); 632 633 switch (pad) { 634 case ATOMISP_SUBDEV_PAD_SINK: { 635 const struct atomisp_in_fmt_conv *fc = 636 atomisp_find_in_fmt_conv(ffmt->code); 637 638 if (!fc) { 639 fc = atomisp_in_fmt_conv; 640 ffmt->code = fc->code; 641 dev_dbg(isp->dev, "using 0x%8.8x instead\n", 642 ffmt->code); 643 } 644 645 *__ffmt = *ffmt; 646 647 isp_subdev_propagate(sd, sd_state, which, pad, 648 V4L2_SEL_TGT_CROP, 0); 649 650 if (which == V4L2_SUBDEV_FORMAT_ACTIVE) { 651 atomisp_css_input_set_resolution(isp_sd, 652 stream_id, ffmt); 653 atomisp_css_input_set_binning_factor(isp_sd, 654 stream_id, 655 atomisp_get_sensor_bin_factor(isp_sd)); 656 atomisp_css_input_set_bayer_order(isp_sd, stream_id, 657 fc->bayer_order); 658 atomisp_css_input_set_format(isp_sd, stream_id, 659 fc->atomisp_in_fmt); 660 atomisp_css_set_default_isys_config(isp_sd, stream_id, 661 ffmt); 662 } 663 664 break; 665 } 666 case ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE: 667 case ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW: 668 case ATOMISP_SUBDEV_PAD_SOURCE_VF: 669 case ATOMISP_SUBDEV_PAD_SOURCE_VIDEO: 670 __ffmt->code = ffmt->code; 671 break; 672 } 673 } 674 675 /* 676 * isp_subdev_get_format - Retrieve the video format on a pad 677 * @sd : ISP V4L2 subdevice 678 * @fh : V4L2 subdev file handle 679 * @pad: Pad number 680 * @fmt: Format 681 * 682 * Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond 683 * to the format type. 684 */ 685 static int isp_subdev_get_format(struct v4l2_subdev *sd, 686 struct v4l2_subdev_state *sd_state, 687 struct v4l2_subdev_format *fmt) 688 { 689 fmt->format = *atomisp_subdev_get_ffmt(sd, sd_state, fmt->which, 690 fmt->pad); 691 692 return 0; 693 } 694 695 /* 696 * isp_subdev_set_format - Set the video format on a pad 697 * @sd : ISP subdev V4L2 subdevice 698 * @fh : V4L2 subdev file handle 699 * @pad: Pad number 700 * @fmt: Format 701 * 702 * Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond 703 * to the format type. 704 */ 705 static int isp_subdev_set_format(struct v4l2_subdev *sd, 706 struct v4l2_subdev_state *sd_state, 707 struct v4l2_subdev_format *fmt) 708 { 709 atomisp_subdev_set_ffmt(sd, sd_state, fmt->which, fmt->pad, 710 &fmt->format); 711 712 return 0; 713 } 714 715 /* V4L2 subdev core operations */ 716 static const struct v4l2_subdev_core_ops isp_subdev_v4l2_core_ops = { 717 .ioctl = isp_subdev_ioctl, .s_power = isp_subdev_set_power, 718 .subscribe_event = isp_subdev_subscribe_event, 719 .unsubscribe_event = isp_subdev_unsubscribe_event, 720 }; 721 722 /* V4L2 subdev pad operations */ 723 static const struct v4l2_subdev_pad_ops isp_subdev_v4l2_pad_ops = { 724 .enum_mbus_code = isp_subdev_enum_mbus_code, 725 .get_fmt = isp_subdev_get_format, 726 .set_fmt = isp_subdev_set_format, 727 .get_selection = isp_subdev_get_selection, 728 .set_selection = isp_subdev_set_selection, 729 .link_validate = v4l2_subdev_link_validate_default, 730 }; 731 732 /* V4L2 subdev operations */ 733 static const struct v4l2_subdev_ops isp_subdev_v4l2_ops = { 734 .core = &isp_subdev_v4l2_core_ops, 735 .pad = &isp_subdev_v4l2_pad_ops, 736 }; 737 738 static void isp_subdev_init_params(struct atomisp_sub_device *asd) 739 { 740 unsigned int i; 741 742 /* parameters initialization */ 743 INIT_LIST_HEAD(&asd->s3a_stats); 744 INIT_LIST_HEAD(&asd->s3a_stats_in_css); 745 INIT_LIST_HEAD(&asd->s3a_stats_ready); 746 INIT_LIST_HEAD(&asd->dis_stats); 747 INIT_LIST_HEAD(&asd->dis_stats_in_css); 748 spin_lock_init(&asd->dis_stats_lock); 749 for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) { 750 INIT_LIST_HEAD(&asd->metadata[i]); 751 INIT_LIST_HEAD(&asd->metadata_in_css[i]); 752 INIT_LIST_HEAD(&asd->metadata_ready[i]); 753 } 754 } 755 756 /* 757 * isp_subdev_link_setup - Setup isp subdev connections 758 * @entity: ispsubdev media entity 759 * @local: Pad at the local end of the link 760 * @remote: Pad at the remote end of the link 761 * @flags: Link flags 762 * 763 * return -EINVAL or zero on success 764 */ 765 static int isp_subdev_link_setup(struct media_entity *entity, 766 const struct media_pad *local, 767 const struct media_pad *remote, u32 flags) 768 { 769 struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity); 770 struct atomisp_sub_device *isp_sd = v4l2_get_subdevdata(sd); 771 struct atomisp_device *isp = isp_sd->isp; 772 unsigned int i; 773 774 switch (local->index | is_media_entity_v4l2_subdev(remote->entity)) { 775 case ATOMISP_SUBDEV_PAD_SINK | MEDIA_ENT_F_V4L2_SUBDEV_UNKNOWN: 776 /* Read from the sensor CSI2-ports. */ 777 if (!(flags & MEDIA_LNK_FL_ENABLED)) { 778 isp_sd->input = ATOMISP_SUBDEV_INPUT_NONE; 779 break; 780 } 781 782 if (isp_sd->input != ATOMISP_SUBDEV_INPUT_NONE) 783 return -EBUSY; 784 785 for (i = 0; i < ATOMISP_CAMERA_NR_PORTS; i++) { 786 if (remote->entity != &isp->csi2_port[i].subdev.entity) 787 continue; 788 789 isp_sd->input = ATOMISP_SUBDEV_INPUT_CSI2_PORT1 + i; 790 return 0; 791 } 792 793 return -EINVAL; 794 795 case ATOMISP_SUBDEV_PAD_SINK | MEDIA_ENT_F_OLD_BASE: 796 /* read from memory */ 797 if (flags & MEDIA_LNK_FL_ENABLED) { 798 if (isp_sd->input >= ATOMISP_SUBDEV_INPUT_CSI2_PORT1 && 799 isp_sd->input < (ATOMISP_SUBDEV_INPUT_CSI2_PORT1 800 + ATOMISP_CAMERA_NR_PORTS)) 801 return -EBUSY; 802 isp_sd->input = ATOMISP_SUBDEV_INPUT_MEMORY; 803 } else { 804 if (isp_sd->input == ATOMISP_SUBDEV_INPUT_MEMORY) 805 isp_sd->input = ATOMISP_SUBDEV_INPUT_NONE; 806 } 807 break; 808 809 case ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW | MEDIA_ENT_F_OLD_BASE: 810 /* always write to memory */ 811 break; 812 813 case ATOMISP_SUBDEV_PAD_SOURCE_VF | MEDIA_ENT_F_OLD_BASE: 814 /* always write to memory */ 815 break; 816 817 case ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE | MEDIA_ENT_F_OLD_BASE: 818 /* always write to memory */ 819 break; 820 821 case ATOMISP_SUBDEV_PAD_SOURCE_VIDEO | MEDIA_ENT_F_OLD_BASE: 822 /* always write to memory */ 823 break; 824 825 default: 826 return -EINVAL; 827 } 828 829 return 0; 830 } 831 832 /* media operations */ 833 static const struct media_entity_operations isp_subdev_media_ops = { 834 .link_setup = isp_subdev_link_setup, 835 .link_validate = v4l2_subdev_link_validate, 836 /* .set_power = v4l2_subdev_set_power, */ 837 }; 838 839 static int __atomisp_update_run_mode(struct atomisp_sub_device *asd) 840 { 841 struct atomisp_device *isp = asd->isp; 842 struct v4l2_ctrl *ctrl = asd->run_mode; 843 struct v4l2_ctrl *c; 844 s32 mode; 845 846 if (ctrl->val != ATOMISP_RUN_MODE_VIDEO && 847 asd->continuous_mode->val) 848 mode = ATOMISP_RUN_MODE_PREVIEW; 849 else 850 mode = ctrl->val; 851 852 c = v4l2_ctrl_find( 853 isp->inputs[asd->input_curr].camera->ctrl_handler, 854 V4L2_CID_RUN_MODE); 855 856 if (c) 857 return v4l2_ctrl_s_ctrl(c, mode); 858 859 return 0; 860 } 861 862 int atomisp_update_run_mode(struct atomisp_sub_device *asd) 863 { 864 int rval; 865 866 mutex_lock(asd->ctrl_handler.lock); 867 rval = __atomisp_update_run_mode(asd); 868 mutex_unlock(asd->ctrl_handler.lock); 869 870 return rval; 871 } 872 873 static int s_ctrl(struct v4l2_ctrl *ctrl) 874 { 875 struct atomisp_sub_device *asd = container_of( 876 ctrl->handler, struct atomisp_sub_device, ctrl_handler); 877 878 switch (ctrl->id) { 879 case V4L2_CID_RUN_MODE: 880 return __atomisp_update_run_mode(asd); 881 case V4L2_CID_DEPTH_MODE: 882 if (asd->streaming != ATOMISP_DEVICE_STREAMING_DISABLED) { 883 dev_err(asd->isp->dev, 884 "ISP is streaming, it is not supported to change the depth mode\n"); 885 return -EINVAL; 886 } 887 break; 888 } 889 890 return 0; 891 } 892 893 static const struct v4l2_ctrl_ops ctrl_ops = { 894 .s_ctrl = &s_ctrl, 895 }; 896 897 static const struct v4l2_ctrl_config ctrl_fmt_auto = { 898 .ops = &ctrl_ops, 899 .id = V4L2_CID_FMT_AUTO, 900 .name = "Automatic format guessing", 901 .type = V4L2_CTRL_TYPE_BOOLEAN, 902 .min = 0, 903 .max = 1, 904 .step = 1, 905 .def = 1, 906 }; 907 908 static const char *const ctrl_run_mode_menu[] = { 909 NULL, 910 "Video", 911 "Still capture", 912 "Continuous capture", 913 "Preview", 914 }; 915 916 static const struct v4l2_ctrl_config ctrl_run_mode = { 917 .ops = &ctrl_ops, 918 .id = V4L2_CID_RUN_MODE, 919 .name = "Atomisp run mode", 920 .type = V4L2_CTRL_TYPE_MENU, 921 .min = 1, 922 .def = 1, 923 .max = 4, 924 .qmenu = ctrl_run_mode_menu, 925 }; 926 927 static const char *const ctrl_vfpp_mode_menu[] = { 928 "Enable", /* vfpp always enabled */ 929 "Disable to scaler mode", /* CSS into video mode and disable */ 930 "Disable to low latency mode", /* CSS into still mode and disable */ 931 }; 932 933 static const struct v4l2_ctrl_config ctrl_vfpp = { 934 .id = V4L2_CID_VFPP, 935 .name = "Atomisp vf postprocess", 936 .type = V4L2_CTRL_TYPE_MENU, 937 .min = 0, 938 .def = 0, 939 .max = 2, 940 .qmenu = ctrl_vfpp_mode_menu, 941 }; 942 943 /* 944 * Control for ISP continuous mode 945 * 946 * When enabled, capture processing is possible without 947 * stopping the preview pipeline. When disabled, ISP needs 948 * to be restarted between preview and capture. 949 */ 950 static const struct v4l2_ctrl_config ctrl_continuous_mode = { 951 .ops = &ctrl_ops, 952 .id = V4L2_CID_ATOMISP_CONTINUOUS_MODE, 953 .type = V4L2_CTRL_TYPE_BOOLEAN, 954 .name = "Continuous mode", 955 .min = 0, 956 .max = 1, 957 .step = 1, 958 .def = 0, 959 }; 960 961 /* 962 * Control for continuous mode raw buffer size 963 * 964 * The size of the RAW ringbuffer sets limit on how much 965 * back in time application can go when requesting capture 966 * frames to be rendered, and how many frames can be rendered 967 * in a burst at full sensor rate. 968 * 969 * Note: this setting has a big impact on memory consumption of 970 * the CSS subsystem. 971 */ 972 static const struct v4l2_ctrl_config ctrl_continuous_raw_buffer_size = { 973 .ops = &ctrl_ops, 974 .id = V4L2_CID_ATOMISP_CONTINUOUS_RAW_BUFFER_SIZE, 975 .type = V4L2_CTRL_TYPE_INTEGER, 976 .name = "Continuous raw ringbuffer size", 977 .min = 1, 978 .max = 100, /* depends on CSS version, runtime checked */ 979 .step = 1, 980 .def = 3, 981 }; 982 983 /* 984 * Control for enabling continuous viewfinder 985 * 986 * When enabled, and ISP is in continuous mode (see ctrl_continuous_mode ), 987 * preview pipeline continues concurrently with capture 988 * processing. When disabled, and continuous mode is used, 989 * preview is paused while captures are processed, but 990 * full pipeline restart is not needed. 991 * 992 * By setting this to disabled, capture processing is 993 * essentially given priority over preview, and the effective 994 * capture output rate may be higher than with continuous 995 * viewfinder enabled. 996 */ 997 static const struct v4l2_ctrl_config ctrl_continuous_viewfinder = { 998 .id = V4L2_CID_ATOMISP_CONTINUOUS_VIEWFINDER, 999 .type = V4L2_CTRL_TYPE_BOOLEAN, 1000 .name = "Continuous viewfinder", 1001 .min = 0, 1002 .max = 1, 1003 .step = 1, 1004 .def = 0, 1005 }; 1006 1007 /* 1008 * Control for enabling Lock&Unlock Raw Buffer mechanism 1009 * 1010 * When enabled, Raw Buffer can be locked and unlocked. 1011 * Application can hold the exp_id of Raw Buffer 1012 * and unlock it when no longer needed. 1013 * Note: Make sure set this configuration before creating stream. 1014 */ 1015 static const struct v4l2_ctrl_config ctrl_enable_raw_buffer_lock = { 1016 .id = V4L2_CID_ENABLE_RAW_BUFFER_LOCK, 1017 .type = V4L2_CTRL_TYPE_BOOLEAN, 1018 .name = "Lock Unlock Raw Buffer", 1019 .min = 0, 1020 .max = 1, 1021 .step = 1, 1022 .def = 0, 1023 }; 1024 1025 /* 1026 * Control to disable digital zoom of the whole stream 1027 * 1028 * When it is true, pipe configuration enable_dz will be set to false. 1029 * This can help get a better performance by disabling pp binary. 1030 * 1031 * Note: Make sure set this configuration before creating stream. 1032 */ 1033 static const struct v4l2_ctrl_config ctrl_disable_dz = { 1034 .id = V4L2_CID_DISABLE_DZ, 1035 .type = V4L2_CTRL_TYPE_BOOLEAN, 1036 .name = "Disable digital zoom", 1037 .min = 0, 1038 .max = 1, 1039 .step = 1, 1040 .def = 0, 1041 }; 1042 1043 /* 1044 * Control for ISP depth mode 1045 * 1046 * When enabled, that means ISP will deal with dual streams and sensors will be 1047 * in slave/master mode. 1048 * slave sensor will have no output until master sensor is streamed on. 1049 */ 1050 static const struct v4l2_ctrl_config ctrl_depth_mode = { 1051 .ops = &ctrl_ops, 1052 .id = V4L2_CID_DEPTH_MODE, 1053 .type = V4L2_CTRL_TYPE_BOOLEAN, 1054 .name = "Depth mode", 1055 .min = 0, 1056 .max = 1, 1057 .step = 1, 1058 .def = 0, 1059 }; 1060 1061 /* 1062 * Control for selectting ISP version 1063 * 1064 * When enabled, that means ISP version will be used ISP2.7. when disable, the 1065 * isp will default to use ISP2.2. 1066 * Note: Make sure set this configuration before creating stream. 1067 */ 1068 static const struct v4l2_ctrl_config ctrl_select_isp_version = { 1069 .ops = &ctrl_ops, 1070 .id = V4L2_CID_ATOMISP_SELECT_ISP_VERSION, 1071 .type = V4L2_CTRL_TYPE_BOOLEAN, 1072 .name = "Select Isp version", 1073 .min = 0, 1074 .max = 1, 1075 .step = 1, 1076 .def = 0, 1077 }; 1078 1079 static void atomisp_init_subdev_pipe(struct atomisp_sub_device *asd, 1080 struct atomisp_video_pipe *pipe, enum v4l2_buf_type buf_type) 1081 { 1082 pipe->type = buf_type; 1083 pipe->asd = asd; 1084 pipe->isp = asd->isp; 1085 spin_lock_init(&pipe->irq_lock); 1086 INIT_LIST_HEAD(&pipe->activeq); 1087 INIT_LIST_HEAD(&pipe->activeq_out); 1088 INIT_LIST_HEAD(&pipe->buffers_waiting_for_param); 1089 INIT_LIST_HEAD(&pipe->per_frame_params); 1090 memset(pipe->frame_request_config_id, 1091 0, VIDEO_MAX_FRAME * sizeof(unsigned int)); 1092 memset(pipe->frame_params, 1093 0, VIDEO_MAX_FRAME * 1094 sizeof(struct atomisp_css_params_with_list *)); 1095 } 1096 1097 static void atomisp_init_acc_pipe(struct atomisp_sub_device *asd, 1098 struct atomisp_acc_pipe *pipe) 1099 { 1100 pipe->asd = asd; 1101 pipe->isp = asd->isp; 1102 INIT_LIST_HEAD(&asd->acc.fw); 1103 INIT_LIST_HEAD(&asd->acc.memory_maps); 1104 ida_init(&asd->acc.ida); 1105 } 1106 1107 /* 1108 * isp_subdev_init_entities - Initialize V4L2 subdev and media entity 1109 * @asd: ISP CCDC module 1110 * 1111 * Return 0 on success and a negative error code on failure. 1112 */ 1113 static int isp_subdev_init_entities(struct atomisp_sub_device *asd) 1114 { 1115 struct v4l2_subdev *sd = &asd->subdev; 1116 struct media_pad *pads = asd->pads; 1117 struct media_entity *me = &sd->entity; 1118 int ret; 1119 1120 asd->input = ATOMISP_SUBDEV_INPUT_NONE; 1121 1122 v4l2_subdev_init(sd, &isp_subdev_v4l2_ops); 1123 sprintf(sd->name, "ATOMISP_SUBDEV_%d", asd->index); 1124 v4l2_set_subdevdata(sd, asd); 1125 sd->flags |= V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_HAS_DEVNODE; 1126 1127 pads[ATOMISP_SUBDEV_PAD_SINK].flags = MEDIA_PAD_FL_SINK; 1128 pads[ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW].flags = MEDIA_PAD_FL_SOURCE; 1129 pads[ATOMISP_SUBDEV_PAD_SOURCE_VF].flags = MEDIA_PAD_FL_SOURCE; 1130 pads[ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE].flags = MEDIA_PAD_FL_SOURCE; 1131 pads[ATOMISP_SUBDEV_PAD_SOURCE_VIDEO].flags = MEDIA_PAD_FL_SOURCE; 1132 1133 asd->fmt[ATOMISP_SUBDEV_PAD_SINK].fmt.code = 1134 MEDIA_BUS_FMT_SBGGR10_1X10; 1135 asd->fmt[ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW].fmt.code = 1136 MEDIA_BUS_FMT_SBGGR10_1X10; 1137 asd->fmt[ATOMISP_SUBDEV_PAD_SOURCE_VF].fmt.code = 1138 MEDIA_BUS_FMT_SBGGR10_1X10; 1139 asd->fmt[ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE].fmt.code = 1140 MEDIA_BUS_FMT_SBGGR10_1X10; 1141 asd->fmt[ATOMISP_SUBDEV_PAD_SOURCE_VIDEO].fmt.code = 1142 MEDIA_BUS_FMT_SBGGR10_1X10; 1143 1144 me->ops = &isp_subdev_media_ops; 1145 me->function = MEDIA_ENT_F_V4L2_SUBDEV_UNKNOWN; 1146 ret = media_entity_pads_init(me, ATOMISP_SUBDEV_PADS_NUM, pads); 1147 if (ret < 0) 1148 return ret; 1149 1150 atomisp_init_subdev_pipe(asd, &asd->video_in, 1151 V4L2_BUF_TYPE_VIDEO_OUTPUT); 1152 1153 atomisp_init_subdev_pipe(asd, &asd->video_out_preview, 1154 V4L2_BUF_TYPE_VIDEO_CAPTURE); 1155 1156 atomisp_init_subdev_pipe(asd, &asd->video_out_vf, 1157 V4L2_BUF_TYPE_VIDEO_CAPTURE); 1158 1159 atomisp_init_subdev_pipe(asd, &asd->video_out_capture, 1160 V4L2_BUF_TYPE_VIDEO_CAPTURE); 1161 1162 atomisp_init_subdev_pipe(asd, &asd->video_out_video_capture, 1163 V4L2_BUF_TYPE_VIDEO_CAPTURE); 1164 1165 atomisp_init_acc_pipe(asd, &asd->video_acc); 1166 1167 ret = atomisp_video_init(&asd->video_in, "MEMORY"); 1168 if (ret < 0) 1169 return ret; 1170 1171 ret = atomisp_video_init(&asd->video_out_capture, "CAPTURE"); 1172 if (ret < 0) 1173 return ret; 1174 1175 ret = atomisp_video_init(&asd->video_out_vf, "VIEWFINDER"); 1176 if (ret < 0) 1177 return ret; 1178 1179 ret = atomisp_video_init(&asd->video_out_preview, "PREVIEW"); 1180 if (ret < 0) 1181 return ret; 1182 1183 ret = atomisp_video_init(&asd->video_out_video_capture, "VIDEO"); 1184 if (ret < 0) 1185 return ret; 1186 1187 atomisp_acc_init(&asd->video_acc, "ACC"); 1188 1189 ret = v4l2_ctrl_handler_init(&asd->ctrl_handler, 1); 1190 if (ret) 1191 return ret; 1192 1193 asd->fmt_auto = v4l2_ctrl_new_custom(&asd->ctrl_handler, 1194 &ctrl_fmt_auto, NULL); 1195 asd->run_mode = v4l2_ctrl_new_custom(&asd->ctrl_handler, 1196 &ctrl_run_mode, NULL); 1197 asd->vfpp = v4l2_ctrl_new_custom(&asd->ctrl_handler, 1198 &ctrl_vfpp, NULL); 1199 asd->continuous_mode = v4l2_ctrl_new_custom(&asd->ctrl_handler, 1200 &ctrl_continuous_mode, NULL); 1201 asd->continuous_viewfinder = v4l2_ctrl_new_custom(&asd->ctrl_handler, 1202 &ctrl_continuous_viewfinder, 1203 NULL); 1204 asd->continuous_raw_buffer_size = 1205 v4l2_ctrl_new_custom(&asd->ctrl_handler, 1206 &ctrl_continuous_raw_buffer_size, 1207 NULL); 1208 1209 asd->enable_raw_buffer_lock = 1210 v4l2_ctrl_new_custom(&asd->ctrl_handler, 1211 &ctrl_enable_raw_buffer_lock, 1212 NULL); 1213 asd->depth_mode = 1214 v4l2_ctrl_new_custom(&asd->ctrl_handler, 1215 &ctrl_depth_mode, 1216 NULL); 1217 asd->disable_dz = 1218 v4l2_ctrl_new_custom(&asd->ctrl_handler, 1219 &ctrl_disable_dz, 1220 NULL); 1221 if (IS_ISP2401) { 1222 asd->select_isp_version = v4l2_ctrl_new_custom(&asd->ctrl_handler, 1223 &ctrl_select_isp_version, 1224 NULL); 1225 } 1226 1227 /* Make controls visible on subdev as well. */ 1228 asd->subdev.ctrl_handler = &asd->ctrl_handler; 1229 spin_lock_init(&asd->raw_buffer_bitmap_lock); 1230 return asd->ctrl_handler.error; 1231 } 1232 1233 int atomisp_create_pads_links(struct atomisp_device *isp) 1234 { 1235 struct atomisp_sub_device *asd; 1236 int i, j, ret = 0; 1237 1238 isp->num_of_streams = 2; 1239 for (i = 0; i < ATOMISP_CAMERA_NR_PORTS; i++) { 1240 for (j = 0; j < isp->num_of_streams; j++) { 1241 ret = 1242 media_create_pad_link(&isp->csi2_port[i].subdev. 1243 entity, CSI2_PAD_SOURCE, 1244 &isp->asd[j].subdev.entity, 1245 ATOMISP_SUBDEV_PAD_SINK, 0); 1246 if (ret < 0) 1247 return ret; 1248 } 1249 } 1250 for (i = 0; i < isp->input_cnt - 2; i++) { 1251 ret = media_create_pad_link(&isp->inputs[i].camera->entity, 0, 1252 &isp->csi2_port[isp->inputs[i]. 1253 port].subdev.entity, 1254 CSI2_PAD_SINK, 1255 MEDIA_LNK_FL_ENABLED | 1256 MEDIA_LNK_FL_IMMUTABLE); 1257 if (ret < 0) 1258 return ret; 1259 } 1260 for (i = 0; i < isp->num_of_streams; i++) { 1261 asd = &isp->asd[i]; 1262 ret = media_create_pad_link(&asd->subdev.entity, 1263 ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW, 1264 &asd->video_out_preview.vdev.entity, 1265 0, 0); 1266 if (ret < 0) 1267 return ret; 1268 ret = media_create_pad_link(&asd->subdev.entity, 1269 ATOMISP_SUBDEV_PAD_SOURCE_VF, 1270 &asd->video_out_vf.vdev.entity, 0, 1271 0); 1272 if (ret < 0) 1273 return ret; 1274 ret = media_create_pad_link(&asd->subdev.entity, 1275 ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE, 1276 &asd->video_out_capture.vdev.entity, 1277 0, 0); 1278 if (ret < 0) 1279 return ret; 1280 ret = media_create_pad_link(&asd->subdev.entity, 1281 ATOMISP_SUBDEV_PAD_SOURCE_VIDEO, 1282 &asd->video_out_video_capture.vdev. 1283 entity, 0, 0); 1284 if (ret < 0) 1285 return ret; 1286 /* 1287 * file input only supported on subdev0 1288 * so do not create pad link for subdevs other then subdev0 1289 */ 1290 if (asd->index) 1291 return 0; 1292 ret = media_create_pad_link(&asd->video_in.vdev.entity, 1293 0, &asd->subdev.entity, 1294 ATOMISP_SUBDEV_PAD_SINK, 0); 1295 if (ret < 0) 1296 return ret; 1297 } 1298 return 0; 1299 } 1300 1301 static void atomisp_subdev_cleanup_entities(struct atomisp_sub_device *asd) 1302 { 1303 v4l2_ctrl_handler_free(&asd->ctrl_handler); 1304 1305 media_entity_cleanup(&asd->subdev.entity); 1306 } 1307 1308 void atomisp_subdev_cleanup_pending_events(struct atomisp_sub_device *asd) 1309 { 1310 struct v4l2_fh *fh, *fh_tmp; 1311 struct v4l2_event event; 1312 unsigned int i, pending_event; 1313 1314 list_for_each_entry_safe(fh, fh_tmp, 1315 &asd->subdev.devnode->fh_list, list) { 1316 pending_event = v4l2_event_pending(fh); 1317 for (i = 0; i < pending_event; i++) 1318 v4l2_event_dequeue(fh, &event, 1); 1319 } 1320 } 1321 1322 void atomisp_subdev_unregister_entities(struct atomisp_sub_device *asd) 1323 { 1324 atomisp_subdev_cleanup_entities(asd); 1325 v4l2_device_unregister_subdev(&asd->subdev); 1326 atomisp_video_unregister(&asd->video_in); 1327 atomisp_video_unregister(&asd->video_out_preview); 1328 atomisp_video_unregister(&asd->video_out_vf); 1329 atomisp_video_unregister(&asd->video_out_capture); 1330 atomisp_video_unregister(&asd->video_out_video_capture); 1331 atomisp_acc_unregister(&asd->video_acc); 1332 } 1333 1334 int atomisp_subdev_register_entities(struct atomisp_sub_device *asd, 1335 struct v4l2_device *vdev) 1336 { 1337 int ret; 1338 u32 device_caps; 1339 1340 /* 1341 * FIXME: check if all device caps are properly initialized. 1342 * Should any of those use V4L2_CAP_META_OUTPUT? Probably yes. 1343 */ 1344 1345 device_caps = V4L2_CAP_VIDEO_CAPTURE | 1346 V4L2_CAP_STREAMING; 1347 1348 /* Register the subdev and video node. */ 1349 1350 ret = v4l2_device_register_subdev(vdev, &asd->subdev); 1351 if (ret < 0) 1352 goto error; 1353 1354 asd->video_out_capture.vdev.v4l2_dev = vdev; 1355 asd->video_out_capture.vdev.device_caps = device_caps | 1356 V4L2_CAP_VIDEO_OUTPUT; 1357 ret = video_register_device(&asd->video_out_capture.vdev, 1358 VFL_TYPE_VIDEO, -1); 1359 if (ret < 0) 1360 goto error; 1361 1362 asd->video_out_vf.vdev.v4l2_dev = vdev; 1363 asd->video_out_vf.vdev.device_caps = device_caps | 1364 V4L2_CAP_VIDEO_OUTPUT; 1365 ret = video_register_device(&asd->video_out_vf.vdev, 1366 VFL_TYPE_VIDEO, -1); 1367 if (ret < 0) 1368 goto error; 1369 asd->video_out_preview.vdev.v4l2_dev = vdev; 1370 asd->video_out_preview.vdev.device_caps = device_caps | 1371 V4L2_CAP_VIDEO_OUTPUT; 1372 ret = video_register_device(&asd->video_out_preview.vdev, 1373 VFL_TYPE_VIDEO, -1); 1374 if (ret < 0) 1375 goto error; 1376 asd->video_out_video_capture.vdev.v4l2_dev = vdev; 1377 asd->video_out_video_capture.vdev.device_caps = device_caps | 1378 V4L2_CAP_VIDEO_OUTPUT; 1379 ret = video_register_device(&asd->video_out_video_capture.vdev, 1380 VFL_TYPE_VIDEO, -1); 1381 if (ret < 0) 1382 goto error; 1383 asd->video_acc.vdev.v4l2_dev = vdev; 1384 asd->video_acc.vdev.device_caps = device_caps | 1385 V4L2_CAP_VIDEO_OUTPUT; 1386 ret = video_register_device(&asd->video_acc.vdev, 1387 VFL_TYPE_VIDEO, -1); 1388 if (ret < 0) 1389 goto error; 1390 1391 /* 1392 * file input only supported on subdev0 1393 * so do not create video node for subdevs other then subdev0 1394 */ 1395 if (asd->index) 1396 return 0; 1397 1398 asd->video_in.vdev.v4l2_dev = vdev; 1399 asd->video_in.vdev.device_caps = device_caps | 1400 V4L2_CAP_VIDEO_CAPTURE; 1401 ret = video_register_device(&asd->video_in.vdev, 1402 VFL_TYPE_VIDEO, -1); 1403 if (ret < 0) 1404 goto error; 1405 1406 return 0; 1407 1408 error: 1409 atomisp_subdev_unregister_entities(asd); 1410 return ret; 1411 } 1412 1413 /* 1414 * atomisp_subdev_init - ISP Subdevice initialization. 1415 * @dev: Device pointer specific to the ATOM ISP. 1416 * 1417 * TODO: Get the initialisation values from platform data. 1418 * 1419 * Return 0 on success or a negative error code otherwise. 1420 */ 1421 int atomisp_subdev_init(struct atomisp_device *isp) 1422 { 1423 struct atomisp_sub_device *asd; 1424 int i, ret = 0; 1425 1426 /* 1427 * CSS2.0 running ISP2400 support 1428 * multiple streams 1429 */ 1430 isp->num_of_streams = 2; 1431 isp->asd = devm_kzalloc(isp->dev, sizeof(struct atomisp_sub_device) * 1432 isp->num_of_streams, GFP_KERNEL); 1433 if (!isp->asd) 1434 return -ENOMEM; 1435 for (i = 0; i < isp->num_of_streams; i++) { 1436 asd = &isp->asd[i]; 1437 spin_lock_init(&asd->lock); 1438 asd->isp = isp; 1439 isp_subdev_init_params(asd); 1440 asd->index = i; 1441 ret = isp_subdev_init_entities(asd); 1442 if (ret < 0) { 1443 atomisp_subdev_cleanup_entities(asd); 1444 break; 1445 } 1446 } 1447 1448 return ret; 1449 } 1450