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