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