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