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