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 * Copyright (c) 2010 Silicon Hive www.siliconhive.com. 8 * 9 * This program is free software; you can redistribute it and/or 10 * modify it under the terms of the GNU General Public License version 11 * 2 as published by the Free Software Foundation. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * 19 */ 20 21 #include <linux/module.h> 22 #include <linux/pm_runtime.h> 23 24 #include <media/v4l2-ioctl.h> 25 #include <media/videobuf-vmalloc.h> 26 27 #include "atomisp_cmd.h" 28 #include "atomisp_common.h" 29 #include "atomisp_fops.h" 30 #include "atomisp_internal.h" 31 #include "atomisp_ioctl.h" 32 #include "atomisp_compat.h" 33 #include "atomisp_subdev.h" 34 #include "atomisp_v4l2.h" 35 #include "atomisp-regs.h" 36 #include "hmm/hmm.h" 37 38 #include "type_support.h" 39 #include "device_access/device_access.h" 40 41 #define ISP_LEFT_PAD 128 /* equal to 2*NWAY */ 42 43 /* 44 * input image data, and current frame resolution for test 45 */ 46 #define ISP_PARAM_MMAP_OFFSET 0xfffff000 47 48 #define MAGIC_CHECK(is, should) \ 49 do { \ 50 if (unlikely((is) != (should))) { \ 51 pr_err("magic mismatch: %x (expected %x)\n", \ 52 is, should); \ 53 BUG(); \ 54 } \ 55 } while (0) 56 57 /* 58 * Videobuf ops 59 */ 60 static int atomisp_buf_setup(struct videobuf_queue *vq, unsigned int *count, 61 unsigned int *size) 62 { 63 struct atomisp_video_pipe *pipe = vq->priv_data; 64 65 *size = pipe->pix.sizeimage; 66 67 return 0; 68 } 69 70 static int atomisp_buf_prepare(struct videobuf_queue *vq, 71 struct videobuf_buffer *vb, 72 enum v4l2_field field) 73 { 74 struct atomisp_video_pipe *pipe = vq->priv_data; 75 76 vb->size = pipe->pix.sizeimage; 77 vb->width = pipe->pix.width; 78 vb->height = pipe->pix.height; 79 vb->field = field; 80 vb->state = VIDEOBUF_PREPARED; 81 82 return 0; 83 } 84 85 static int atomisp_q_one_metadata_buffer(struct atomisp_sub_device *asd, 86 enum atomisp_input_stream_id stream_id, 87 enum ia_css_pipe_id css_pipe_id) 88 { 89 struct atomisp_metadata_buf *metadata_buf; 90 enum atomisp_metadata_type md_type = 91 atomisp_get_metadata_type(asd, css_pipe_id); 92 struct list_head *metadata_list; 93 94 if (asd->metadata_bufs_in_css[stream_id][css_pipe_id] >= 95 ATOMISP_CSS_Q_DEPTH) 96 return 0; /* we have reached CSS queue depth */ 97 98 if (!list_empty(&asd->metadata[md_type])) { 99 metadata_list = &asd->metadata[md_type]; 100 } else if (!list_empty(&asd->metadata_ready[md_type])) { 101 metadata_list = &asd->metadata_ready[md_type]; 102 } else { 103 dev_warn(asd->isp->dev, "%s: No metadata buffers available for type %d!\n", 104 __func__, md_type); 105 return -EINVAL; 106 } 107 108 metadata_buf = list_entry(metadata_list->next, 109 struct atomisp_metadata_buf, list); 110 list_del_init(&metadata_buf->list); 111 112 if (atomisp_q_metadata_buffer_to_css(asd, metadata_buf, 113 stream_id, css_pipe_id)) { 114 list_add(&metadata_buf->list, metadata_list); 115 return -EINVAL; 116 } else { 117 list_add_tail(&metadata_buf->list, 118 &asd->metadata_in_css[md_type]); 119 } 120 asd->metadata_bufs_in_css[stream_id][css_pipe_id]++; 121 122 return 0; 123 } 124 125 static int atomisp_q_one_s3a_buffer(struct atomisp_sub_device *asd, 126 enum atomisp_input_stream_id stream_id, 127 enum ia_css_pipe_id css_pipe_id) 128 { 129 struct atomisp_s3a_buf *s3a_buf; 130 struct list_head *s3a_list; 131 unsigned int exp_id; 132 133 if (asd->s3a_bufs_in_css[css_pipe_id] >= ATOMISP_CSS_Q_DEPTH) 134 return 0; /* we have reached CSS queue depth */ 135 136 if (!list_empty(&asd->s3a_stats)) { 137 s3a_list = &asd->s3a_stats; 138 } else if (!list_empty(&asd->s3a_stats_ready)) { 139 s3a_list = &asd->s3a_stats_ready; 140 } else { 141 dev_warn(asd->isp->dev, "%s: No s3a buffers available!\n", 142 __func__); 143 return -EINVAL; 144 } 145 146 s3a_buf = list_entry(s3a_list->next, struct atomisp_s3a_buf, list); 147 list_del_init(&s3a_buf->list); 148 exp_id = s3a_buf->s3a_data->exp_id; 149 150 hmm_flush_vmap(s3a_buf->s3a_data->data_ptr); 151 if (atomisp_q_s3a_buffer_to_css(asd, s3a_buf, 152 stream_id, css_pipe_id)) { 153 /* got from head, so return back to the head */ 154 list_add(&s3a_buf->list, s3a_list); 155 return -EINVAL; 156 } else { 157 list_add_tail(&s3a_buf->list, &asd->s3a_stats_in_css); 158 if (s3a_list == &asd->s3a_stats_ready) 159 dev_warn(asd->isp->dev, "%s: drop one s3a stat which has exp_id %d!\n", 160 __func__, exp_id); 161 } 162 163 asd->s3a_bufs_in_css[css_pipe_id]++; 164 return 0; 165 } 166 167 static int atomisp_q_one_dis_buffer(struct atomisp_sub_device *asd, 168 enum atomisp_input_stream_id stream_id, 169 enum ia_css_pipe_id css_pipe_id) 170 { 171 struct atomisp_dis_buf *dis_buf; 172 unsigned long irqflags; 173 174 if (asd->dis_bufs_in_css >= ATOMISP_CSS_Q_DEPTH) 175 return 0; /* we have reached CSS queue depth */ 176 177 spin_lock_irqsave(&asd->dis_stats_lock, irqflags); 178 if (list_empty(&asd->dis_stats)) { 179 spin_unlock_irqrestore(&asd->dis_stats_lock, irqflags); 180 dev_warn(asd->isp->dev, "%s: No dis buffers available!\n", 181 __func__); 182 return -EINVAL; 183 } 184 185 dis_buf = list_entry(asd->dis_stats.prev, 186 struct atomisp_dis_buf, list); 187 list_del_init(&dis_buf->list); 188 spin_unlock_irqrestore(&asd->dis_stats_lock, irqflags); 189 190 hmm_flush_vmap(dis_buf->dis_data->data_ptr); 191 if (atomisp_q_dis_buffer_to_css(asd, dis_buf, 192 stream_id, css_pipe_id)) { 193 spin_lock_irqsave(&asd->dis_stats_lock, irqflags); 194 /* got from tail, so return back to the tail */ 195 list_add_tail(&dis_buf->list, &asd->dis_stats); 196 spin_unlock_irqrestore(&asd->dis_stats_lock, irqflags); 197 return -EINVAL; 198 } else { 199 spin_lock_irqsave(&asd->dis_stats_lock, irqflags); 200 list_add_tail(&dis_buf->list, &asd->dis_stats_in_css); 201 spin_unlock_irqrestore(&asd->dis_stats_lock, irqflags); 202 } 203 204 asd->dis_bufs_in_css++; 205 206 return 0; 207 } 208 209 int atomisp_q_video_buffers_to_css(struct atomisp_sub_device *asd, 210 struct atomisp_video_pipe *pipe, 211 enum atomisp_input_stream_id stream_id, 212 enum ia_css_buffer_type css_buf_type, 213 enum ia_css_pipe_id css_pipe_id) 214 { 215 struct videobuf_vmalloc_memory *vm_mem; 216 struct atomisp_css_params_with_list *param; 217 struct ia_css_dvs_grid_info *dvs_grid = 218 atomisp_css_get_dvs_grid_info(&asd->params.curr_grid_info); 219 unsigned long irqflags; 220 int err = 0; 221 222 if (WARN_ON(css_pipe_id >= IA_CSS_PIPE_ID_NUM)) 223 return -EINVAL; 224 225 while (pipe->buffers_in_css < ATOMISP_CSS_Q_DEPTH) { 226 struct videobuf_buffer *vb; 227 228 spin_lock_irqsave(&pipe->irq_lock, irqflags); 229 if (list_empty(&pipe->activeq)) { 230 spin_unlock_irqrestore(&pipe->irq_lock, irqflags); 231 return -EINVAL; 232 } 233 vb = list_entry(pipe->activeq.next, 234 struct videobuf_buffer, queue); 235 list_del_init(&vb->queue); 236 vb->state = VIDEOBUF_ACTIVE; 237 spin_unlock_irqrestore(&pipe->irq_lock, irqflags); 238 239 /* 240 * If there is a per_frame setting to apply on the buffer, 241 * do it before buffer en-queueing. 242 */ 243 vm_mem = vb->priv; 244 245 param = pipe->frame_params[vb->i]; 246 if (param) { 247 atomisp_makeup_css_parameters(asd, 248 &asd->params.css_param.update_flag, 249 ¶m->params); 250 atomisp_apply_css_parameters(asd, ¶m->params); 251 252 if (param->params.update_flag.dz_config && 253 asd->run_mode->val != ATOMISP_RUN_MODE_VIDEO) { 254 err = atomisp_calculate_real_zoom_region(asd, 255 ¶m->params.dz_config, css_pipe_id); 256 if (!err) 257 asd->params.config.dz_config = ¶m->params.dz_config; 258 } 259 atomisp_css_set_isp_config_applied_frame(asd, 260 vm_mem->vaddr); 261 atomisp_css_update_isp_params_on_pipe(asd, 262 asd->stream_env[stream_id].pipes[css_pipe_id]); 263 asd->params.dvs_6axis = (struct ia_css_dvs_6axis_config *) 264 param->params.dvs_6axis; 265 266 /* 267 * WORKAROUND: 268 * Because the camera halv3 can't ensure to set zoom 269 * region to per_frame setting and global setting at 270 * same time and only set zoom region to pre_frame 271 * setting now.so when the pre_frame setting include 272 * zoom region,I will set it to global setting. 273 */ 274 if (param->params.update_flag.dz_config && 275 asd->run_mode->val != ATOMISP_RUN_MODE_VIDEO 276 && !err) { 277 memcpy(&asd->params.css_param.dz_config, 278 ¶m->params.dz_config, 279 sizeof(struct ia_css_dz_config)); 280 asd->params.css_param.update_flag.dz_config = 281 (struct atomisp_dz_config *) 282 &asd->params.css_param.dz_config; 283 asd->params.css_update_params_needed = true; 284 } 285 } 286 /* Enqueue buffer */ 287 err = atomisp_q_video_buffer_to_css(asd, vm_mem, stream_id, 288 css_buf_type, css_pipe_id); 289 if (err) { 290 spin_lock_irqsave(&pipe->irq_lock, irqflags); 291 list_add_tail(&vb->queue, &pipe->activeq); 292 vb->state = VIDEOBUF_QUEUED; 293 spin_unlock_irqrestore(&pipe->irq_lock, irqflags); 294 dev_err(asd->isp->dev, "%s, css q fails: %d\n", 295 __func__, err); 296 return -EINVAL; 297 } 298 pipe->buffers_in_css++; 299 300 /* enqueue 3A/DIS/metadata buffers */ 301 if (asd->params.curr_grid_info.s3a_grid.enable && 302 css_pipe_id == asd->params.s3a_enabled_pipe && 303 css_buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME) 304 atomisp_q_one_s3a_buffer(asd, stream_id, 305 css_pipe_id); 306 307 if (asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream_info. 308 metadata_info.size && 309 css_buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME) 310 atomisp_q_one_metadata_buffer(asd, stream_id, 311 css_pipe_id); 312 313 if (dvs_grid && dvs_grid->enable && 314 css_pipe_id == IA_CSS_PIPE_ID_VIDEO && 315 css_buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME) 316 atomisp_q_one_dis_buffer(asd, stream_id, 317 css_pipe_id); 318 } 319 320 return 0; 321 } 322 323 static int atomisp_get_css_buf_type(struct atomisp_sub_device *asd, 324 enum ia_css_pipe_id pipe_id, 325 uint16_t source_pad) 326 { 327 if (ATOMISP_USE_YUVPP(asd)) { 328 /* when run ZSL case */ 329 if (asd->continuous_mode->val && 330 asd->run_mode->val == ATOMISP_RUN_MODE_PREVIEW) { 331 if (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE) 332 return IA_CSS_BUFFER_TYPE_OUTPUT_FRAME; 333 else if (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW) 334 return IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME; 335 else 336 return IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME; 337 } 338 339 /*when run SDV case*/ 340 if (asd->continuous_mode->val && 341 asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO) { 342 if (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE) 343 return IA_CSS_BUFFER_TYPE_OUTPUT_FRAME; 344 else if (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW) 345 return IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME; 346 else if (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_VIDEO) 347 return IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME; 348 else 349 return IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME; 350 } 351 352 /*other case: default setting*/ 353 if (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE || 354 source_pad == ATOMISP_SUBDEV_PAD_SOURCE_VIDEO || 355 (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW && 356 asd->run_mode->val != ATOMISP_RUN_MODE_VIDEO)) 357 return IA_CSS_BUFFER_TYPE_OUTPUT_FRAME; 358 else 359 return IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME; 360 } 361 362 if (pipe_id == IA_CSS_PIPE_ID_COPY || 363 source_pad == ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE || 364 source_pad == ATOMISP_SUBDEV_PAD_SOURCE_VIDEO || 365 (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW && 366 asd->run_mode->val != ATOMISP_RUN_MODE_VIDEO)) 367 return IA_CSS_BUFFER_TYPE_OUTPUT_FRAME; 368 else 369 return IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME; 370 } 371 372 /* queue all available buffers to css */ 373 int atomisp_qbuffers_to_css(struct atomisp_sub_device *asd) 374 { 375 enum ia_css_buffer_type buf_type; 376 enum ia_css_pipe_id css_capture_pipe_id = IA_CSS_PIPE_ID_NUM; 377 enum ia_css_pipe_id css_preview_pipe_id = IA_CSS_PIPE_ID_NUM; 378 enum ia_css_pipe_id css_video_pipe_id = IA_CSS_PIPE_ID_NUM; 379 enum atomisp_input_stream_id input_stream_id; 380 struct atomisp_video_pipe *capture_pipe = NULL; 381 struct atomisp_video_pipe *vf_pipe = NULL; 382 struct atomisp_video_pipe *preview_pipe = NULL; 383 struct atomisp_video_pipe *video_pipe = NULL; 384 bool raw_mode = atomisp_is_mbuscode_raw( 385 asd->fmt[asd->capture_pad].fmt.code); 386 387 if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_SCALER) { 388 video_pipe = &asd->video_out_video_capture; 389 css_video_pipe_id = IA_CSS_PIPE_ID_VIDEO; 390 } else if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_LOWLAT) { 391 preview_pipe = &asd->video_out_capture; 392 css_preview_pipe_id = IA_CSS_PIPE_ID_CAPTURE; 393 } else if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO) { 394 if (asd->continuous_mode->val) { 395 capture_pipe = &asd->video_out_capture; 396 vf_pipe = &asd->video_out_vf; 397 css_capture_pipe_id = IA_CSS_PIPE_ID_CAPTURE; 398 } 399 video_pipe = &asd->video_out_video_capture; 400 preview_pipe = &asd->video_out_preview; 401 css_video_pipe_id = IA_CSS_PIPE_ID_VIDEO; 402 css_preview_pipe_id = IA_CSS_PIPE_ID_VIDEO; 403 } else if (asd->continuous_mode->val) { 404 capture_pipe = &asd->video_out_capture; 405 vf_pipe = &asd->video_out_vf; 406 preview_pipe = &asd->video_out_preview; 407 408 css_preview_pipe_id = IA_CSS_PIPE_ID_PREVIEW; 409 css_capture_pipe_id = IA_CSS_PIPE_ID_CAPTURE; 410 } else if (asd->run_mode->val == ATOMISP_RUN_MODE_PREVIEW) { 411 preview_pipe = &asd->video_out_preview; 412 css_preview_pipe_id = IA_CSS_PIPE_ID_PREVIEW; 413 } else { 414 /* ATOMISP_RUN_MODE_STILL_CAPTURE */ 415 capture_pipe = &asd->video_out_capture; 416 if (!raw_mode) 417 vf_pipe = &asd->video_out_vf; 418 css_capture_pipe_id = IA_CSS_PIPE_ID_CAPTURE; 419 } 420 421 if (IS_ISP2401 && asd->copy_mode) { 422 css_capture_pipe_id = IA_CSS_PIPE_ID_COPY; 423 css_preview_pipe_id = IA_CSS_PIPE_ID_COPY; 424 css_video_pipe_id = IA_CSS_PIPE_ID_COPY; 425 } 426 427 if (asd->yuvpp_mode) { 428 capture_pipe = &asd->video_out_capture; 429 video_pipe = &asd->video_out_video_capture; 430 preview_pipe = &asd->video_out_preview; 431 css_capture_pipe_id = IA_CSS_PIPE_ID_COPY; 432 css_video_pipe_id = IA_CSS_PIPE_ID_YUVPP; 433 css_preview_pipe_id = IA_CSS_PIPE_ID_YUVPP; 434 } 435 436 if (capture_pipe) { 437 buf_type = atomisp_get_css_buf_type( 438 asd, css_capture_pipe_id, 439 atomisp_subdev_source_pad(&capture_pipe->vdev)); 440 input_stream_id = ATOMISP_INPUT_STREAM_GENERAL; 441 442 /* 443 * use yuvpp pipe for SOC camera. 444 */ 445 if (ATOMISP_USE_YUVPP(asd)) 446 css_capture_pipe_id = IA_CSS_PIPE_ID_YUVPP; 447 448 atomisp_q_video_buffers_to_css(asd, capture_pipe, 449 input_stream_id, 450 buf_type, css_capture_pipe_id); 451 } 452 453 if (vf_pipe) { 454 buf_type = atomisp_get_css_buf_type( 455 asd, css_capture_pipe_id, 456 atomisp_subdev_source_pad(&vf_pipe->vdev)); 457 if (asd->stream_env[ATOMISP_INPUT_STREAM_POSTVIEW].stream) 458 input_stream_id = ATOMISP_INPUT_STREAM_POSTVIEW; 459 else 460 input_stream_id = ATOMISP_INPUT_STREAM_GENERAL; 461 462 /* 463 * use yuvpp pipe for SOC camera. 464 */ 465 if (ATOMISP_USE_YUVPP(asd)) 466 css_capture_pipe_id = IA_CSS_PIPE_ID_YUVPP; 467 atomisp_q_video_buffers_to_css(asd, vf_pipe, 468 input_stream_id, 469 buf_type, css_capture_pipe_id); 470 } 471 472 if (preview_pipe) { 473 buf_type = atomisp_get_css_buf_type( 474 asd, css_preview_pipe_id, 475 atomisp_subdev_source_pad(&preview_pipe->vdev)); 476 if (ATOMISP_SOC_CAMERA(asd) && css_preview_pipe_id == IA_CSS_PIPE_ID_YUVPP) 477 input_stream_id = ATOMISP_INPUT_STREAM_GENERAL; 478 /* else for ext isp use case */ 479 else if (css_preview_pipe_id == IA_CSS_PIPE_ID_YUVPP) 480 input_stream_id = ATOMISP_INPUT_STREAM_VIDEO; 481 else if (asd->stream_env[ATOMISP_INPUT_STREAM_PREVIEW].stream) 482 input_stream_id = ATOMISP_INPUT_STREAM_PREVIEW; 483 else 484 input_stream_id = ATOMISP_INPUT_STREAM_GENERAL; 485 486 /* 487 * use yuvpp pipe for SOC camera. 488 */ 489 if (ATOMISP_USE_YUVPP(asd)) 490 css_preview_pipe_id = IA_CSS_PIPE_ID_YUVPP; 491 492 atomisp_q_video_buffers_to_css(asd, preview_pipe, 493 input_stream_id, 494 buf_type, css_preview_pipe_id); 495 } 496 497 if (video_pipe) { 498 buf_type = atomisp_get_css_buf_type( 499 asd, css_video_pipe_id, 500 atomisp_subdev_source_pad(&video_pipe->vdev)); 501 if (asd->stream_env[ATOMISP_INPUT_STREAM_VIDEO].stream) 502 input_stream_id = ATOMISP_INPUT_STREAM_VIDEO; 503 else 504 input_stream_id = ATOMISP_INPUT_STREAM_GENERAL; 505 506 /* 507 * use yuvpp pipe for SOC camera. 508 */ 509 if (ATOMISP_USE_YUVPP(asd)) 510 css_video_pipe_id = IA_CSS_PIPE_ID_YUVPP; 511 512 atomisp_q_video_buffers_to_css(asd, video_pipe, 513 input_stream_id, 514 buf_type, css_video_pipe_id); 515 } 516 517 return 0; 518 } 519 520 static void atomisp_buf_queue(struct videobuf_queue *vq, 521 struct videobuf_buffer *vb) 522 { 523 struct atomisp_video_pipe *pipe = vq->priv_data; 524 525 /* 526 * when a frame buffer meets following conditions, it should be put into 527 * the waiting list: 528 * 1. It is not a main output frame, and it has a per-frame parameter 529 * to go with it. 530 * 2. It is not a main output frame, and the waiting buffer list is not 531 * empty, to keep the FIFO sequence of frame buffer processing, it 532 * is put to waiting list until previous per-frame parameter buffers 533 * get enqueued. 534 */ 535 if (!atomisp_is_vf_pipe(pipe) && 536 (pipe->frame_request_config_id[vb->i] || 537 !list_empty(&pipe->buffers_waiting_for_param))) 538 list_add_tail(&vb->queue, &pipe->buffers_waiting_for_param); 539 else 540 list_add_tail(&vb->queue, &pipe->activeq); 541 542 vb->state = VIDEOBUF_QUEUED; 543 } 544 545 static void atomisp_buf_release(struct videobuf_queue *vq, 546 struct videobuf_buffer *vb) 547 { 548 vb->state = VIDEOBUF_NEEDS_INIT; 549 atomisp_videobuf_free_buf(vb); 550 } 551 552 static const struct videobuf_queue_ops videobuf_qops = { 553 .buf_setup = atomisp_buf_setup, 554 .buf_prepare = atomisp_buf_prepare, 555 .buf_queue = atomisp_buf_queue, 556 .buf_release = atomisp_buf_release, 557 }; 558 559 static int atomisp_init_pipe(struct atomisp_video_pipe *pipe) 560 { 561 /* init locks */ 562 spin_lock_init(&pipe->irq_lock); 563 564 videobuf_queue_vmalloc_init(&pipe->capq, &videobuf_qops, NULL, 565 &pipe->irq_lock, 566 V4L2_BUF_TYPE_VIDEO_CAPTURE, 567 V4L2_FIELD_NONE, 568 sizeof(struct atomisp_buffer), pipe, 569 NULL); /* ext_lock: NULL */ 570 571 INIT_LIST_HEAD(&pipe->activeq); 572 INIT_LIST_HEAD(&pipe->buffers_waiting_for_param); 573 INIT_LIST_HEAD(&pipe->per_frame_params); 574 memset(pipe->frame_request_config_id, 0, 575 VIDEO_MAX_FRAME * sizeof(unsigned int)); 576 memset(pipe->frame_params, 0, 577 VIDEO_MAX_FRAME * 578 sizeof(struct atomisp_css_params_with_list *)); 579 580 return 0; 581 } 582 583 static void atomisp_dev_init_struct(struct atomisp_device *isp) 584 { 585 unsigned int i; 586 587 isp->need_gfx_throttle = true; 588 isp->isp_fatal_error = false; 589 isp->mipi_frame_size = 0; 590 591 for (i = 0; i < isp->input_cnt; i++) 592 isp->inputs[i].asd = NULL; 593 /* 594 * For Merrifield, frequency is scalable. 595 * After boot-up, the default frequency is 200MHz. 596 */ 597 isp->sw_contex.running_freq = ISP_FREQ_200MHZ; 598 } 599 600 static void atomisp_subdev_init_struct(struct atomisp_sub_device *asd) 601 { 602 v4l2_ctrl_s_ctrl(asd->run_mode, ATOMISP_RUN_MODE_STILL_CAPTURE); 603 memset(&asd->params.css_param, 0, sizeof(asd->params.css_param)); 604 asd->params.color_effect = V4L2_COLORFX_NONE; 605 asd->params.bad_pixel_en = true; 606 asd->params.gdc_cac_en = false; 607 asd->params.video_dis_en = false; 608 asd->params.sc_en = false; 609 asd->params.fpn_en = false; 610 asd->params.xnr_en = false; 611 asd->params.false_color = 0; 612 asd->params.online_process = 1; 613 asd->params.yuv_ds_en = 0; 614 /* s3a grid not enabled for any pipe */ 615 asd->params.s3a_enabled_pipe = IA_CSS_PIPE_ID_NUM; 616 617 asd->params.offline_parm.num_captures = 1; 618 asd->params.offline_parm.skip_frames = 0; 619 asd->params.offline_parm.offset = 0; 620 asd->delayed_init = ATOMISP_DELAYED_INIT_NOT_QUEUED; 621 /* Add for channel */ 622 asd->input_curr = 0; 623 624 asd->mipi_frame_size = 0; 625 asd->copy_mode = false; 626 asd->yuvpp_mode = false; 627 628 asd->stream_prepared = false; 629 asd->high_speed_mode = false; 630 asd->sensor_array_res.height = 0; 631 asd->sensor_array_res.width = 0; 632 atomisp_css_init_struct(asd); 633 } 634 635 /* 636 * file operation functions 637 */ 638 static unsigned int atomisp_subdev_users(struct atomisp_sub_device *asd) 639 { 640 return asd->video_out_preview.users + 641 asd->video_out_vf.users + 642 asd->video_out_capture.users + 643 asd->video_out_video_capture.users; 644 } 645 646 unsigned int atomisp_dev_users(struct atomisp_device *isp) 647 { 648 unsigned int i, sum; 649 650 for (i = 0, sum = 0; i < isp->num_of_streams; i++) 651 sum += atomisp_subdev_users(&isp->asd[i]); 652 653 return sum; 654 } 655 656 static int atomisp_open(struct file *file) 657 { 658 struct video_device *vdev = video_devdata(file); 659 struct atomisp_device *isp = video_get_drvdata(vdev); 660 struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev); 661 struct atomisp_sub_device *asd = pipe->asd; 662 int ret; 663 664 dev_dbg(isp->dev, "open device %s\n", vdev->name); 665 666 ret = v4l2_fh_open(file); 667 if (ret) 668 return ret; 669 670 mutex_lock(&isp->mutex); 671 672 asd->subdev.devnode = vdev; 673 /* Deferred firmware loading case. */ 674 if (isp->css_env.isp_css_fw.bytes == 0) { 675 dev_err(isp->dev, "Deferred firmware load.\n"); 676 isp->firmware = atomisp_load_firmware(isp); 677 if (!isp->firmware) { 678 dev_err(isp->dev, "Failed to load ISP firmware.\n"); 679 ret = -ENOENT; 680 goto error; 681 } 682 ret = atomisp_css_load_firmware(isp); 683 if (ret) { 684 dev_err(isp->dev, "Failed to init css.\n"); 685 goto error; 686 } 687 /* No need to keep FW in memory anymore. */ 688 release_firmware(isp->firmware); 689 isp->firmware = NULL; 690 isp->css_env.isp_css_fw.data = NULL; 691 } 692 693 if (!isp->input_cnt) { 694 dev_err(isp->dev, "no camera attached\n"); 695 ret = -EINVAL; 696 goto error; 697 } 698 699 /* 700 * atomisp does not allow multiple open 701 */ 702 if (pipe->users) { 703 dev_dbg(isp->dev, "video node already opened\n"); 704 mutex_unlock(&isp->mutex); 705 return -EBUSY; 706 } 707 708 ret = atomisp_init_pipe(pipe); 709 if (ret) 710 goto error; 711 712 if (atomisp_dev_users(isp)) { 713 dev_dbg(isp->dev, "skip init isp in open\n"); 714 goto init_subdev; 715 } 716 717 /* runtime power management, turn on ISP */ 718 ret = pm_runtime_resume_and_get(vdev->v4l2_dev->dev); 719 if (ret < 0) { 720 dev_err(isp->dev, "Failed to power on device\n"); 721 goto error; 722 } 723 724 /* Init ISP */ 725 if (atomisp_css_init(isp)) { 726 ret = -EINVAL; 727 /* Need to clean up CSS init if it fails. */ 728 goto css_error; 729 } 730 731 atomisp_dev_init_struct(isp); 732 733 ret = v4l2_subdev_call(isp->flash, core, s_power, 1); 734 if (ret < 0 && ret != -ENODEV && ret != -ENOIOCTLCMD) { 735 dev_err(isp->dev, "Failed to power-on flash\n"); 736 goto css_error; 737 } 738 739 init_subdev: 740 if (atomisp_subdev_users(asd)) 741 goto done; 742 743 atomisp_subdev_init_struct(asd); 744 745 done: 746 pipe->users++; 747 mutex_unlock(&isp->mutex); 748 749 /* Ensure that a mode is set */ 750 v4l2_ctrl_s_ctrl(asd->run_mode, pipe->default_run_mode); 751 752 return 0; 753 754 css_error: 755 atomisp_css_uninit(isp); 756 pm_runtime_put(vdev->v4l2_dev->dev); 757 error: 758 mutex_unlock(&isp->mutex); 759 v4l2_fh_release(file); 760 return ret; 761 } 762 763 static int atomisp_release(struct file *file) 764 { 765 struct video_device *vdev = video_devdata(file); 766 struct atomisp_device *isp = video_get_drvdata(vdev); 767 struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev); 768 struct atomisp_sub_device *asd = pipe->asd; 769 struct v4l2_requestbuffers req; 770 struct v4l2_subdev_fh fh; 771 struct v4l2_rect clear_compose = {0}; 772 unsigned long flags; 773 int ret = 0; 774 775 v4l2_fh_init(&fh.vfh, vdev); 776 777 req.count = 0; 778 if (!isp) 779 return -EBADF; 780 781 mutex_lock(&isp->mutex); 782 783 dev_dbg(isp->dev, "release device %s\n", vdev->name); 784 785 asd->subdev.devnode = vdev; 786 787 pipe->users--; 788 789 if (pipe->capq.streaming) 790 dev_warn(isp->dev, 791 "%s: ISP still streaming while closing!", 792 __func__); 793 794 if (pipe->capq.streaming && 795 atomisp_streamoff(file, NULL, V4L2_BUF_TYPE_VIDEO_CAPTURE)) { 796 dev_err(isp->dev, "atomisp_streamoff failed on release, driver bug"); 797 goto done; 798 } 799 800 if (pipe->users) 801 goto done; 802 803 if (atomisp_reqbufs(file, NULL, &req)) { 804 dev_err(isp->dev, "atomisp_reqbufs failed on release, driver bug"); 805 goto done; 806 } 807 808 /* 809 * A little trick here: 810 * file injection input resolution is recorded in the sink pad, 811 * therefore can not be cleared when releaseing one device node. 812 * The sink pad setting can only be cleared when all device nodes 813 * get released. 814 */ 815 if (asd->fmt_auto->val) { 816 struct v4l2_mbus_framefmt isp_sink_fmt = { 0 }; 817 818 atomisp_subdev_set_ffmt(&asd->subdev, fh.state, 819 V4L2_SUBDEV_FORMAT_ACTIVE, 820 ATOMISP_SUBDEV_PAD_SINK, &isp_sink_fmt); 821 } 822 823 if (atomisp_subdev_users(asd)) 824 goto done; 825 826 atomisp_css_free_stat_buffers(asd); 827 atomisp_free_internal_buffers(asd); 828 ret = v4l2_subdev_call(isp->inputs[asd->input_curr].camera, 829 core, s_power, 0); 830 if (ret) 831 dev_warn(isp->dev, "Failed to power-off sensor\n"); 832 833 /* clear the asd field to show this camera is not used */ 834 isp->inputs[asd->input_curr].asd = NULL; 835 spin_lock_irqsave(&isp->lock, flags); 836 asd->streaming = ATOMISP_DEVICE_STREAMING_DISABLED; 837 spin_unlock_irqrestore(&isp->lock, flags); 838 839 if (atomisp_dev_users(isp)) 840 goto done; 841 842 atomisp_destroy_pipes_stream_force(asd); 843 atomisp_css_uninit(isp); 844 845 if (defer_fw_load) { 846 ia_css_unload_firmware(); 847 isp->css_env.isp_css_fw.data = NULL; 848 isp->css_env.isp_css_fw.bytes = 0; 849 } 850 851 ret = v4l2_subdev_call(isp->flash, core, s_power, 0); 852 if (ret < 0 && ret != -ENODEV && ret != -ENOIOCTLCMD) 853 dev_warn(isp->dev, "Failed to power-off flash\n"); 854 855 if (pm_runtime_put_sync(vdev->v4l2_dev->dev) < 0) 856 dev_err(isp->dev, "Failed to power off device\n"); 857 858 done: 859 atomisp_subdev_set_selection(&asd->subdev, fh.state, 860 V4L2_SUBDEV_FORMAT_ACTIVE, 861 atomisp_subdev_source_pad(vdev), 862 V4L2_SEL_TGT_COMPOSE, 0, 863 &clear_compose); 864 mutex_unlock(&isp->mutex); 865 866 return v4l2_fh_release(file); 867 } 868 869 /* 870 * Memory help functions for image frame and private parameters 871 */ 872 static int do_isp_mm_remap(struct atomisp_device *isp, 873 struct vm_area_struct *vma, 874 ia_css_ptr isp_virt, u32 host_virt, u32 pgnr) 875 { 876 u32 pfn; 877 878 while (pgnr) { 879 pfn = hmm_virt_to_phys(isp_virt) >> PAGE_SHIFT; 880 if (remap_pfn_range(vma, host_virt, pfn, 881 PAGE_SIZE, PAGE_SHARED)) { 882 dev_err(isp->dev, "remap_pfn_range err.\n"); 883 return -EAGAIN; 884 } 885 886 isp_virt += PAGE_SIZE; 887 host_virt += PAGE_SIZE; 888 pgnr--; 889 } 890 891 return 0; 892 } 893 894 static int frame_mmap(struct atomisp_device *isp, 895 const struct ia_css_frame *frame, struct vm_area_struct *vma) 896 { 897 ia_css_ptr isp_virt; 898 u32 host_virt; 899 u32 pgnr; 900 901 if (!frame) { 902 dev_err(isp->dev, "%s: NULL frame pointer.\n", __func__); 903 return -EINVAL; 904 } 905 906 host_virt = vma->vm_start; 907 isp_virt = frame->data; 908 pgnr = DIV_ROUND_UP(frame->data_bytes, PAGE_SIZE); 909 910 if (do_isp_mm_remap(isp, vma, isp_virt, host_virt, pgnr)) 911 return -EAGAIN; 912 913 return 0; 914 } 915 916 int atomisp_videobuf_mmap_mapper(struct videobuf_queue *q, 917 struct vm_area_struct *vma) 918 { 919 u32 offset = vma->vm_pgoff << PAGE_SHIFT; 920 int ret = -EINVAL, i; 921 struct atomisp_device *isp = 922 ((struct atomisp_video_pipe *)(q->priv_data))->isp; 923 struct videobuf_vmalloc_memory *vm_mem; 924 struct videobuf_mapping *map; 925 926 MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); 927 if (!(vma->vm_flags & VM_WRITE) || !(vma->vm_flags & VM_SHARED)) { 928 dev_err(isp->dev, "map appl bug: PROT_WRITE and MAP_SHARED are required\n"); 929 return -EINVAL; 930 } 931 932 mutex_lock(&q->vb_lock); 933 for (i = 0; i < VIDEO_MAX_FRAME; i++) { 934 struct videobuf_buffer *buf = q->bufs[i]; 935 936 if (!buf) 937 continue; 938 939 map = kzalloc(sizeof(struct videobuf_mapping), GFP_KERNEL); 940 if (!map) { 941 mutex_unlock(&q->vb_lock); 942 return -ENOMEM; 943 } 944 945 buf->map = map; 946 map->q = q; 947 948 buf->baddr = vma->vm_start; 949 950 if (buf && buf->memory == V4L2_MEMORY_MMAP && 951 buf->boff == offset) { 952 vm_mem = buf->priv; 953 ret = frame_mmap(isp, vm_mem->vaddr, vma); 954 vma->vm_flags |= VM_IO | VM_DONTEXPAND | VM_DONTDUMP; 955 break; 956 } 957 } 958 mutex_unlock(&q->vb_lock); 959 960 return ret; 961 } 962 963 /* The input frame contains left and right padding that need to be removed. 964 * There is always ISP_LEFT_PAD padding on the left side. 965 * There is also padding on the right (padded_width - width). 966 */ 967 static int remove_pad_from_frame(struct atomisp_device *isp, 968 struct ia_css_frame *in_frame, __u32 width, __u32 height) 969 { 970 unsigned int i; 971 unsigned short *buffer; 972 int ret = 0; 973 ia_css_ptr load = in_frame->data; 974 ia_css_ptr store = load; 975 976 buffer = kmalloc_array(width, sizeof(load), GFP_KERNEL); 977 if (!buffer) 978 return -ENOMEM; 979 980 load += ISP_LEFT_PAD; 981 for (i = 0; i < height; i++) { 982 ret = hmm_load(load, buffer, width * sizeof(load)); 983 if (ret < 0) 984 goto remove_pad_error; 985 986 ret = hmm_store(store, buffer, width * sizeof(store)); 987 if (ret < 0) 988 goto remove_pad_error; 989 990 load += in_frame->info.padded_width; 991 store += width; 992 } 993 994 remove_pad_error: 995 kfree(buffer); 996 return ret; 997 } 998 999 static int atomisp_mmap(struct file *file, struct vm_area_struct *vma) 1000 { 1001 struct video_device *vdev = video_devdata(file); 1002 struct atomisp_device *isp = video_get_drvdata(vdev); 1003 struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev); 1004 struct atomisp_sub_device *asd = pipe->asd; 1005 struct ia_css_frame *raw_virt_addr; 1006 u32 start = vma->vm_start; 1007 u32 end = vma->vm_end; 1008 u32 size = end - start; 1009 u32 origin_size, new_size; 1010 int ret; 1011 1012 if (!asd) { 1013 dev_err(isp->dev, "%s(): asd is NULL, device is %s\n", 1014 __func__, vdev->name); 1015 return -EINVAL; 1016 } 1017 1018 if (!(vma->vm_flags & (VM_WRITE | VM_READ))) 1019 return -EACCES; 1020 1021 mutex_lock(&isp->mutex); 1022 1023 if (!(vma->vm_flags & VM_SHARED)) { 1024 /* Map private buffer. 1025 * Set VM_SHARED to the flags since we need 1026 * to map the buffer page by page. 1027 * Without VM_SHARED, remap_pfn_range() treats 1028 * this kind of mapping as invalid. 1029 */ 1030 vma->vm_flags |= VM_SHARED; 1031 ret = hmm_mmap(vma, vma->vm_pgoff << PAGE_SHIFT); 1032 mutex_unlock(&isp->mutex); 1033 return ret; 1034 } 1035 1036 /* mmap for ISP offline raw data */ 1037 if (atomisp_subdev_source_pad(vdev) 1038 == ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE && 1039 vma->vm_pgoff == (ISP_PARAM_MMAP_OFFSET >> PAGE_SHIFT)) { 1040 new_size = pipe->pix.width * pipe->pix.height * 2; 1041 if (asd->params.online_process != 0) { 1042 ret = -EINVAL; 1043 goto error; 1044 } 1045 raw_virt_addr = asd->raw_output_frame; 1046 if (!raw_virt_addr) { 1047 dev_err(isp->dev, "Failed to request RAW frame\n"); 1048 ret = -EINVAL; 1049 goto error; 1050 } 1051 1052 ret = remove_pad_from_frame(isp, raw_virt_addr, 1053 pipe->pix.width, pipe->pix.height); 1054 if (ret < 0) { 1055 dev_err(isp->dev, "remove pad failed.\n"); 1056 goto error; 1057 } 1058 origin_size = raw_virt_addr->data_bytes; 1059 raw_virt_addr->data_bytes = new_size; 1060 1061 if (size != PAGE_ALIGN(new_size)) { 1062 dev_err(isp->dev, "incorrect size for mmap ISP Raw Frame\n"); 1063 ret = -EINVAL; 1064 goto error; 1065 } 1066 1067 if (frame_mmap(isp, raw_virt_addr, vma)) { 1068 dev_err(isp->dev, "frame_mmap failed.\n"); 1069 raw_virt_addr->data_bytes = origin_size; 1070 ret = -EAGAIN; 1071 goto error; 1072 } 1073 raw_virt_addr->data_bytes = origin_size; 1074 vma->vm_flags |= VM_IO | VM_DONTEXPAND | VM_DONTDUMP; 1075 mutex_unlock(&isp->mutex); 1076 return 0; 1077 } 1078 1079 /* 1080 * mmap for normal frames 1081 */ 1082 if (size != pipe->pix.sizeimage) { 1083 dev_err(isp->dev, "incorrect size for mmap ISP frames\n"); 1084 ret = -EINVAL; 1085 goto error; 1086 } 1087 mutex_unlock(&isp->mutex); 1088 1089 return atomisp_videobuf_mmap_mapper(&pipe->capq, vma); 1090 1091 error: 1092 mutex_unlock(&isp->mutex); 1093 1094 return ret; 1095 } 1096 1097 static __poll_t atomisp_poll(struct file *file, 1098 struct poll_table_struct *pt) 1099 { 1100 struct video_device *vdev = video_devdata(file); 1101 struct atomisp_device *isp = video_get_drvdata(vdev); 1102 struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev); 1103 1104 mutex_lock(&isp->mutex); 1105 if (pipe->capq.streaming != 1) { 1106 mutex_unlock(&isp->mutex); 1107 return EPOLLERR; 1108 } 1109 mutex_unlock(&isp->mutex); 1110 1111 return videobuf_poll_stream(file, &pipe->capq, pt); 1112 } 1113 1114 const struct v4l2_file_operations atomisp_fops = { 1115 .owner = THIS_MODULE, 1116 .open = atomisp_open, 1117 .release = atomisp_release, 1118 .mmap = atomisp_mmap, 1119 .unlocked_ioctl = video_ioctl2, 1120 #ifdef CONFIG_COMPAT 1121 /* 1122 * this was removed because of bugs, the interface 1123 * needs to be made safe for compat tasks instead. 1124 .compat_ioctl32 = atomisp_compat_ioctl32, 1125 */ 1126 #endif 1127 .poll = atomisp_poll, 1128 }; 1129