linux/drivers/staging/media/atomisp/pci/atomisp_fops.c
<<
>>
Prefs
   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 */
  62static 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
  72static 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
  87static 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
 127static 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
 169static 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
 211int 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                                                      &param->params);
 252                        atomisp_apply_css_parameters(asd, &param->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                                        &param->params.dz_config, css_pipe_id);
 258                                if (!err)
 259                                        asd->params.config.dz_config = &param->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                                       &param->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
 325static 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
 374static 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 */
 414int 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        if (IS_ISP2401 && asd->copy_mode) {
 468                css_capture_pipe_id = IA_CSS_PIPE_ID_COPY;
 469                css_preview_pipe_id = IA_CSS_PIPE_ID_COPY;
 470                css_video_pipe_id = IA_CSS_PIPE_ID_COPY;
 471        }
 472
 473        if (asd->yuvpp_mode) {
 474                capture_pipe = &asd->video_out_capture;
 475                video_pipe   = &asd->video_out_video_capture;
 476                preview_pipe = &asd->video_out_preview;
 477                css_capture_pipe_id = IA_CSS_PIPE_ID_COPY;
 478                css_video_pipe_id   = IA_CSS_PIPE_ID_YUVPP;
 479                css_preview_pipe_id = IA_CSS_PIPE_ID_YUVPP;
 480        }
 481
 482        if (capture_pipe) {
 483                buf_type = atomisp_get_css_buf_type(
 484                               asd, css_capture_pipe_id,
 485                               atomisp_subdev_source_pad(&capture_pipe->vdev));
 486                input_stream_id = ATOMISP_INPUT_STREAM_GENERAL;
 487
 488                /*
 489                 * use yuvpp pipe for SOC camera.
 490                 */
 491                if (ATOMISP_USE_YUVPP(asd))
 492                        css_capture_pipe_id = IA_CSS_PIPE_ID_YUVPP;
 493
 494                atomisp_q_video_buffers_to_css(asd, capture_pipe,
 495                                               input_stream_id,
 496                                               buf_type, css_capture_pipe_id);
 497        }
 498
 499        if (vf_pipe) {
 500                buf_type = atomisp_get_css_buf_type(
 501                               asd, css_capture_pipe_id,
 502                               atomisp_subdev_source_pad(&vf_pipe->vdev));
 503                if (asd->stream_env[ATOMISP_INPUT_STREAM_POSTVIEW].stream)
 504                        input_stream_id = ATOMISP_INPUT_STREAM_POSTVIEW;
 505                else
 506                        input_stream_id = ATOMISP_INPUT_STREAM_GENERAL;
 507
 508                /*
 509                 * use yuvpp pipe for SOC camera.
 510                 */
 511                if (ATOMISP_USE_YUVPP(asd))
 512                        css_capture_pipe_id = IA_CSS_PIPE_ID_YUVPP;
 513                atomisp_q_video_buffers_to_css(asd, vf_pipe,
 514                                               input_stream_id,
 515                                               buf_type, css_capture_pipe_id);
 516        }
 517
 518        if (preview_pipe) {
 519                buf_type = atomisp_get_css_buf_type(
 520                               asd, css_preview_pipe_id,
 521                               atomisp_subdev_source_pad(&preview_pipe->vdev));
 522                if (ATOMISP_SOC_CAMERA(asd) && css_preview_pipe_id == IA_CSS_PIPE_ID_YUVPP)
 523                        input_stream_id = ATOMISP_INPUT_STREAM_GENERAL;
 524                /* else for ext isp use case */
 525                else if (css_preview_pipe_id == IA_CSS_PIPE_ID_YUVPP)
 526                        input_stream_id = ATOMISP_INPUT_STREAM_VIDEO;
 527                else if (asd->stream_env[ATOMISP_INPUT_STREAM_PREVIEW].stream)
 528                        input_stream_id = ATOMISP_INPUT_STREAM_PREVIEW;
 529                else
 530                        input_stream_id = ATOMISP_INPUT_STREAM_GENERAL;
 531
 532                /*
 533                 * use yuvpp pipe for SOC camera.
 534                 */
 535                if (ATOMISP_USE_YUVPP(asd))
 536                        css_preview_pipe_id = IA_CSS_PIPE_ID_YUVPP;
 537
 538                atomisp_q_video_buffers_to_css(asd, preview_pipe,
 539                                               input_stream_id,
 540                                               buf_type, css_preview_pipe_id);
 541        }
 542
 543        if (video_pipe) {
 544                buf_type = atomisp_get_css_buf_type(
 545                               asd, css_video_pipe_id,
 546                               atomisp_subdev_source_pad(&video_pipe->vdev));
 547                if (asd->stream_env[ATOMISP_INPUT_STREAM_VIDEO].stream)
 548                        input_stream_id = ATOMISP_INPUT_STREAM_VIDEO;
 549                else
 550                        input_stream_id = ATOMISP_INPUT_STREAM_GENERAL;
 551
 552                /*
 553                 * use yuvpp pipe for SOC camera.
 554                 */
 555                if (ATOMISP_USE_YUVPP(asd))
 556                        css_video_pipe_id = IA_CSS_PIPE_ID_YUVPP;
 557
 558                atomisp_q_video_buffers_to_css(asd, video_pipe,
 559                                               input_stream_id,
 560                                               buf_type, css_video_pipe_id);
 561        }
 562
 563        return 0;
 564}
 565
 566static void atomisp_buf_queue(struct videobuf_queue *vq,
 567                              struct videobuf_buffer *vb)
 568{
 569        struct atomisp_video_pipe *pipe = vq->priv_data;
 570
 571        /*
 572         * when a frame buffer meets following conditions, it should be put into
 573         * the waiting list:
 574         * 1.  It is not a main output frame, and it has a per-frame parameter
 575         *     to go with it.
 576         * 2.  It is not a main output frame, and the waiting buffer list is not
 577         *     empty, to keep the FIFO sequence of frame buffer processing, it
 578         *     is put to waiting list until previous per-frame parameter buffers
 579         *     get enqueued.
 580         */
 581        if (!atomisp_is_vf_pipe(pipe) &&
 582            (pipe->frame_request_config_id[vb->i] ||
 583             !list_empty(&pipe->buffers_waiting_for_param)))
 584                list_add_tail(&vb->queue, &pipe->buffers_waiting_for_param);
 585        else
 586                list_add_tail(&vb->queue, &pipe->activeq);
 587
 588        vb->state = VIDEOBUF_QUEUED;
 589}
 590
 591static void atomisp_buf_release(struct videobuf_queue *vq,
 592                                struct videobuf_buffer *vb)
 593{
 594        vb->state = VIDEOBUF_NEEDS_INIT;
 595        atomisp_videobuf_free_buf(vb);
 596}
 597
 598static int atomisp_buf_setup_output(struct videobuf_queue *vq,
 599                                    unsigned int *count, unsigned int *size)
 600{
 601        struct atomisp_video_pipe *pipe = vq->priv_data;
 602
 603        *size = pipe->pix.sizeimage;
 604
 605        return 0;
 606}
 607
 608static int atomisp_buf_prepare_output(struct videobuf_queue *vq,
 609                                      struct videobuf_buffer *vb,
 610                                      enum v4l2_field field)
 611{
 612        struct atomisp_video_pipe *pipe = vq->priv_data;
 613
 614        vb->size = pipe->pix.sizeimage;
 615        vb->width = pipe->pix.width;
 616        vb->height = pipe->pix.height;
 617        vb->field = field;
 618        vb->state = VIDEOBUF_PREPARED;
 619
 620        return 0;
 621}
 622
 623static void atomisp_buf_queue_output(struct videobuf_queue *vq,
 624                                     struct videobuf_buffer *vb)
 625{
 626        struct atomisp_video_pipe *pipe = vq->priv_data;
 627
 628        list_add_tail(&vb->queue, &pipe->activeq_out);
 629        vb->state = VIDEOBUF_QUEUED;
 630}
 631
 632static void atomisp_buf_release_output(struct videobuf_queue *vq,
 633                                       struct videobuf_buffer *vb)
 634{
 635        videobuf_vmalloc_free(vb);
 636        vb->state = VIDEOBUF_NEEDS_INIT;
 637}
 638
 639static const struct videobuf_queue_ops videobuf_qops = {
 640        .buf_setup      = atomisp_buf_setup,
 641        .buf_prepare    = atomisp_buf_prepare,
 642        .buf_queue      = atomisp_buf_queue,
 643        .buf_release    = atomisp_buf_release,
 644};
 645
 646static const struct videobuf_queue_ops videobuf_qops_output = {
 647        .buf_setup      = atomisp_buf_setup_output,
 648        .buf_prepare    = atomisp_buf_prepare_output,
 649        .buf_queue      = atomisp_buf_queue_output,
 650        .buf_release    = atomisp_buf_release_output,
 651};
 652
 653static int atomisp_init_pipe(struct atomisp_video_pipe *pipe)
 654{
 655        /* init locks */
 656        spin_lock_init(&pipe->irq_lock);
 657
 658        videobuf_queue_vmalloc_init(&pipe->capq, &videobuf_qops, NULL,
 659                                    &pipe->irq_lock,
 660                                    V4L2_BUF_TYPE_VIDEO_CAPTURE,
 661                                    V4L2_FIELD_NONE,
 662                                    sizeof(struct atomisp_buffer), pipe,
 663                                    NULL);      /* ext_lock: NULL */
 664
 665        videobuf_queue_vmalloc_init(&pipe->outq, &videobuf_qops_output, NULL,
 666                                    &pipe->irq_lock,
 667                                    V4L2_BUF_TYPE_VIDEO_OUTPUT,
 668                                    V4L2_FIELD_NONE,
 669                                    sizeof(struct atomisp_buffer), pipe,
 670                                    NULL);      /* ext_lock: NULL */
 671
 672        INIT_LIST_HEAD(&pipe->activeq);
 673        INIT_LIST_HEAD(&pipe->activeq_out);
 674        INIT_LIST_HEAD(&pipe->buffers_waiting_for_param);
 675        INIT_LIST_HEAD(&pipe->per_frame_params);
 676        memset(pipe->frame_request_config_id, 0,
 677               VIDEO_MAX_FRAME * sizeof(unsigned int));
 678        memset(pipe->frame_params, 0,
 679               VIDEO_MAX_FRAME *
 680               sizeof(struct atomisp_css_params_with_list *));
 681
 682        return 0;
 683}
 684
 685static void atomisp_dev_init_struct(struct atomisp_device *isp)
 686{
 687        unsigned int i;
 688
 689        isp->sw_contex.file_input = false;
 690        isp->need_gfx_throttle = true;
 691        isp->isp_fatal_error = false;
 692        isp->mipi_frame_size = 0;
 693
 694        for (i = 0; i < isp->input_cnt; i++)
 695                isp->inputs[i].asd = NULL;
 696        /*
 697         * For Merrifield, frequency is scalable.
 698         * After boot-up, the default frequency is 200MHz.
 699         */
 700        isp->sw_contex.running_freq = ISP_FREQ_200MHZ;
 701}
 702
 703static void atomisp_subdev_init_struct(struct atomisp_sub_device *asd)
 704{
 705        v4l2_ctrl_s_ctrl(asd->run_mode, ATOMISP_RUN_MODE_STILL_CAPTURE);
 706        memset(&asd->params.css_param, 0, sizeof(asd->params.css_param));
 707        asd->params.color_effect = V4L2_COLORFX_NONE;
 708        asd->params.bad_pixel_en = true;
 709        asd->params.gdc_cac_en = false;
 710        asd->params.video_dis_en = false;
 711        asd->params.sc_en = false;
 712        asd->params.fpn_en = false;
 713        asd->params.xnr_en = false;
 714        asd->params.false_color = 0;
 715        asd->params.online_process = 1;
 716        asd->params.yuv_ds_en = 0;
 717        /* s3a grid not enabled for any pipe */
 718        asd->params.s3a_enabled_pipe = IA_CSS_PIPE_ID_NUM;
 719
 720        asd->params.offline_parm.num_captures = 1;
 721        asd->params.offline_parm.skip_frames = 0;
 722        asd->params.offline_parm.offset = 0;
 723        asd->delayed_init = ATOMISP_DELAYED_INIT_NOT_QUEUED;
 724        /* Add for channel */
 725        asd->input_curr = 0;
 726
 727        asd->mipi_frame_size = 0;
 728        asd->copy_mode = false;
 729        asd->yuvpp_mode = false;
 730
 731        asd->stream_prepared = false;
 732        asd->high_speed_mode = false;
 733        asd->sensor_array_res.height = 0;
 734        asd->sensor_array_res.width = 0;
 735        atomisp_css_init_struct(asd);
 736}
 737
 738/*
 739 * file operation functions
 740 */
 741static unsigned int atomisp_subdev_users(struct atomisp_sub_device *asd)
 742{
 743        return asd->video_out_preview.users +
 744               asd->video_out_vf.users +
 745               asd->video_out_capture.users +
 746               asd->video_out_video_capture.users +
 747               asd->video_acc.users +
 748               asd->video_in.users;
 749}
 750
 751unsigned int atomisp_dev_users(struct atomisp_device *isp)
 752{
 753        unsigned int i, sum;
 754
 755        for (i = 0, sum = 0; i < isp->num_of_streams; i++)
 756                sum += atomisp_subdev_users(&isp->asd[i]);
 757
 758        return sum;
 759}
 760
 761static int atomisp_open(struct file *file)
 762{
 763        struct video_device *vdev = video_devdata(file);
 764        struct atomisp_device *isp = video_get_drvdata(vdev);
 765        struct atomisp_video_pipe *pipe = NULL;
 766        struct atomisp_acc_pipe *acc_pipe = NULL;
 767        struct atomisp_sub_device *asd;
 768        bool acc_node = false;
 769        int ret;
 770
 771        dev_dbg(isp->dev, "open device %s\n", vdev->name);
 772
 773        /*
 774         * Ensure that if we are still loading we block. Once the loading
 775         * is over we can proceed. We can't blindly hold the lock until
 776         * that occurs as if the load fails we'll deadlock the unload
 777         */
 778        rt_mutex_lock(&isp->loading);
 779        /*
 780         * FIXME: revisit this with a better check once the code structure
 781         * is cleaned up a bit more
 782         */
 783        ret = v4l2_fh_open(file);
 784        if (ret) {
 785                dev_err(isp->dev,
 786                        "%s: v4l2_fh_open() returned error %d\n",
 787                       __func__, ret);
 788                rt_mutex_unlock(&isp->loading);
 789                return ret;
 790        }
 791        if (!isp->ready) {
 792                rt_mutex_unlock(&isp->loading);
 793                return -ENXIO;
 794        }
 795        rt_mutex_unlock(&isp->loading);
 796
 797        rt_mutex_lock(&isp->mutex);
 798
 799        acc_node = !strcmp(vdev->name, "ATOMISP ISP ACC");
 800        if (acc_node) {
 801                acc_pipe = atomisp_to_acc_pipe(vdev);
 802                asd = acc_pipe->asd;
 803        } else {
 804                pipe = atomisp_to_video_pipe(vdev);
 805                asd = pipe->asd;
 806        }
 807        asd->subdev.devnode = vdev;
 808        /* Deferred firmware loading case. */
 809        if (isp->css_env.isp_css_fw.bytes == 0) {
 810                dev_err(isp->dev, "Deferred firmware load.\n");
 811                isp->firmware = atomisp_load_firmware(isp);
 812                if (!isp->firmware) {
 813                        dev_err(isp->dev, "Failed to load ISP firmware.\n");
 814                        ret = -ENOENT;
 815                        goto error;
 816                }
 817                ret = atomisp_css_load_firmware(isp);
 818                if (ret) {
 819                        dev_err(isp->dev, "Failed to init css.\n");
 820                        goto error;
 821                }
 822                /* No need to keep FW in memory anymore. */
 823                release_firmware(isp->firmware);
 824                isp->firmware = NULL;
 825                isp->css_env.isp_css_fw.data = NULL;
 826        }
 827
 828        if (acc_node && acc_pipe->users) {
 829                dev_dbg(isp->dev, "acc node already opened\n");
 830                rt_mutex_unlock(&isp->mutex);
 831                return -EBUSY;
 832        } else if (acc_node) {
 833                goto dev_init;
 834        }
 835
 836        if (!isp->input_cnt) {
 837                dev_err(isp->dev, "no camera attached\n");
 838                ret = -EINVAL;
 839                goto error;
 840        }
 841
 842        /*
 843         * atomisp does not allow multiple open
 844         */
 845        if (pipe->users) {
 846                dev_dbg(isp->dev, "video node already opened\n");
 847                rt_mutex_unlock(&isp->mutex);
 848                return -EBUSY;
 849        }
 850
 851        ret = atomisp_init_pipe(pipe);
 852        if (ret)
 853                goto error;
 854
 855dev_init:
 856        if (atomisp_dev_users(isp)) {
 857                dev_dbg(isp->dev, "skip init isp in open\n");
 858                goto init_subdev;
 859        }
 860
 861        /* runtime power management, turn on ISP */
 862        ret = pm_runtime_resume_and_get(vdev->v4l2_dev->dev);
 863        if (ret < 0) {
 864                dev_err(isp->dev, "Failed to power on device\n");
 865                goto error;
 866        }
 867
 868        if (dypool_enable) {
 869                ret = hmm_pool_register(dypool_pgnr, HMM_POOL_TYPE_DYNAMIC);
 870                if (ret)
 871                        dev_err(isp->dev, "Failed to register dynamic memory pool.\n");
 872        }
 873
 874        /* Init ISP */
 875        if (atomisp_css_init(isp)) {
 876                ret = -EINVAL;
 877                /* Need to clean up CSS init if it fails. */
 878                goto css_error;
 879        }
 880
 881        atomisp_dev_init_struct(isp);
 882
 883        ret = v4l2_subdev_call(isp->flash, core, s_power, 1);
 884        if (ret < 0 && ret != -ENODEV && ret != -ENOIOCTLCMD) {
 885                dev_err(isp->dev, "Failed to power-on flash\n");
 886                goto css_error;
 887        }
 888
 889init_subdev:
 890        if (atomisp_subdev_users(asd))
 891                goto done;
 892
 893        atomisp_subdev_init_struct(asd);
 894
 895done:
 896
 897        if (acc_node)
 898                acc_pipe->users++;
 899        else
 900                pipe->users++;
 901        rt_mutex_unlock(&isp->mutex);
 902
 903        /* Ensure that a mode is set */
 904        if (!acc_node)
 905                v4l2_ctrl_s_ctrl(asd->run_mode, pipe->default_run_mode);
 906
 907        return 0;
 908
 909css_error:
 910        atomisp_css_uninit(isp);
 911        pm_runtime_put(vdev->v4l2_dev->dev);
 912error:
 913        hmm_pool_unregister(HMM_POOL_TYPE_DYNAMIC);
 914        rt_mutex_unlock(&isp->mutex);
 915        return ret;
 916}
 917
 918static int atomisp_release(struct file *file)
 919{
 920        struct video_device *vdev = video_devdata(file);
 921        struct atomisp_device *isp = video_get_drvdata(vdev);
 922        struct atomisp_video_pipe *pipe;
 923        struct atomisp_acc_pipe *acc_pipe;
 924        struct atomisp_sub_device *asd;
 925        bool acc_node;
 926        struct v4l2_requestbuffers req;
 927        struct v4l2_subdev_fh fh;
 928        struct v4l2_rect clear_compose = {0};
 929        int ret = 0;
 930
 931        v4l2_fh_init(&fh.vfh, vdev);
 932
 933        req.count = 0;
 934        if (!isp)
 935                return -EBADF;
 936
 937        mutex_lock(&isp->streamoff_mutex);
 938        rt_mutex_lock(&isp->mutex);
 939
 940        dev_dbg(isp->dev, "release device %s\n", vdev->name);
 941        acc_node = !strcmp(vdev->name, "ATOMISP ISP ACC");
 942        if (acc_node) {
 943                acc_pipe = atomisp_to_acc_pipe(vdev);
 944                asd = acc_pipe->asd;
 945        } else {
 946                pipe = atomisp_to_video_pipe(vdev);
 947                asd = pipe->asd;
 948        }
 949        asd->subdev.devnode = vdev;
 950        if (acc_node) {
 951                acc_pipe->users--;
 952                goto subdev_uninit;
 953        }
 954        pipe->users--;
 955
 956        if (pipe->capq.streaming)
 957                dev_warn(isp->dev,
 958                         "%s: ISP still streaming while closing!",
 959                         __func__);
 960
 961        if (pipe->capq.streaming &&
 962            __atomisp_streamoff(file, NULL, V4L2_BUF_TYPE_VIDEO_CAPTURE)) {
 963                dev_err(isp->dev,
 964                        "atomisp_streamoff failed on release, driver bug");
 965                goto done;
 966        }
 967
 968        if (pipe->users)
 969                goto done;
 970
 971        if (__atomisp_reqbufs(file, NULL, &req)) {
 972                dev_err(isp->dev,
 973                        "atomisp_reqbufs failed on release, driver bug");
 974                goto done;
 975        }
 976
 977        if (pipe->outq.bufs[0]) {
 978                mutex_lock(&pipe->outq.vb_lock);
 979                videobuf_queue_cancel(&pipe->outq);
 980                mutex_unlock(&pipe->outq.vb_lock);
 981        }
 982
 983        /*
 984         * A little trick here:
 985         * file injection input resolution is recorded in the sink pad,
 986         * therefore can not be cleared when releaseing one device node.
 987         * The sink pad setting can only be cleared when all device nodes
 988         * get released.
 989         */
 990        if (!isp->sw_contex.file_input && asd->fmt_auto->val) {
 991                struct v4l2_mbus_framefmt isp_sink_fmt = { 0 };
 992
 993                atomisp_subdev_set_ffmt(&asd->subdev, fh.state,
 994                                        V4L2_SUBDEV_FORMAT_ACTIVE,
 995                                        ATOMISP_SUBDEV_PAD_SINK, &isp_sink_fmt);
 996        }
 997subdev_uninit:
 998        if (atomisp_subdev_users(asd))
 999                goto done;
1000
1001        /* clear the sink pad for file input */
1002        if (isp->sw_contex.file_input && asd->fmt_auto->val) {
1003                struct v4l2_mbus_framefmt isp_sink_fmt = { 0 };
1004
1005                atomisp_subdev_set_ffmt(&asd->subdev, fh.state,
1006                                        V4L2_SUBDEV_FORMAT_ACTIVE,
1007                                        ATOMISP_SUBDEV_PAD_SINK, &isp_sink_fmt);
1008        }
1009
1010        atomisp_css_free_stat_buffers(asd);
1011        atomisp_free_internal_buffers(asd);
1012        ret = v4l2_subdev_call(isp->inputs[asd->input_curr].camera,
1013                               core, s_power, 0);
1014        if (ret)
1015                dev_warn(isp->dev, "Failed to power-off sensor\n");
1016
1017        /* clear the asd field to show this camera is not used */
1018        isp->inputs[asd->input_curr].asd = NULL;
1019        asd->streaming = ATOMISP_DEVICE_STREAMING_DISABLED;
1020
1021        if (atomisp_dev_users(isp))
1022                goto done;
1023
1024        atomisp_acc_release(asd);
1025
1026        atomisp_destroy_pipes_stream_force(asd);
1027        atomisp_css_uninit(isp);
1028
1029        if (defer_fw_load) {
1030                ia_css_unload_firmware();
1031                isp->css_env.isp_css_fw.data = NULL;
1032                isp->css_env.isp_css_fw.bytes = 0;
1033        }
1034
1035        hmm_pool_unregister(HMM_POOL_TYPE_DYNAMIC);
1036
1037        ret = v4l2_subdev_call(isp->flash, core, s_power, 0);
1038        if (ret < 0 && ret != -ENODEV && ret != -ENOIOCTLCMD)
1039                dev_warn(isp->dev, "Failed to power-off flash\n");
1040
1041        if (pm_runtime_put_sync(vdev->v4l2_dev->dev) < 0)
1042                dev_err(isp->dev, "Failed to power off device\n");
1043
1044done:
1045        if (!acc_node) {
1046                atomisp_subdev_set_selection(&asd->subdev, fh.state,
1047                                             V4L2_SUBDEV_FORMAT_ACTIVE,
1048                                             atomisp_subdev_source_pad(vdev),
1049                                             V4L2_SEL_TGT_COMPOSE, 0,
1050                                             &clear_compose);
1051        }
1052        rt_mutex_unlock(&isp->mutex);
1053        mutex_unlock(&isp->streamoff_mutex);
1054
1055        return v4l2_fh_release(file);
1056}
1057
1058/*
1059 * Memory help functions for image frame and private parameters
1060 */
1061static int do_isp_mm_remap(struct atomisp_device *isp,
1062                           struct vm_area_struct *vma,
1063                           ia_css_ptr isp_virt, u32 host_virt, u32 pgnr)
1064{
1065        u32 pfn;
1066
1067        while (pgnr) {
1068                pfn = hmm_virt_to_phys(isp_virt) >> PAGE_SHIFT;
1069                if (remap_pfn_range(vma, host_virt, pfn,
1070                                    PAGE_SIZE, PAGE_SHARED)) {
1071                        dev_err(isp->dev, "remap_pfn_range err.\n");
1072                        return -EAGAIN;
1073                }
1074
1075                isp_virt += PAGE_SIZE;
1076                host_virt += PAGE_SIZE;
1077                pgnr--;
1078        }
1079
1080        return 0;
1081}
1082
1083static int frame_mmap(struct atomisp_device *isp,
1084                      const struct ia_css_frame *frame, struct vm_area_struct *vma)
1085{
1086        ia_css_ptr isp_virt;
1087        u32 host_virt;
1088        u32 pgnr;
1089
1090        if (!frame) {
1091                dev_err(isp->dev, "%s: NULL frame pointer.\n", __func__);
1092                return -EINVAL;
1093        }
1094
1095        host_virt = vma->vm_start;
1096        isp_virt = frame->data;
1097        pgnr = DIV_ROUND_UP(frame->data_bytes, PAGE_SIZE);
1098
1099        if (do_isp_mm_remap(isp, vma, isp_virt, host_virt, pgnr))
1100                return -EAGAIN;
1101
1102        return 0;
1103}
1104
1105int atomisp_videobuf_mmap_mapper(struct videobuf_queue *q,
1106                                 struct vm_area_struct *vma)
1107{
1108        u32 offset = vma->vm_pgoff << PAGE_SHIFT;
1109        int ret = -EINVAL, i;
1110        struct atomisp_device *isp =
1111            ((struct atomisp_video_pipe *)(q->priv_data))->isp;
1112        struct videobuf_vmalloc_memory *vm_mem;
1113        struct videobuf_mapping *map;
1114
1115        MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS);
1116        if (!(vma->vm_flags & VM_WRITE) || !(vma->vm_flags & VM_SHARED)) {
1117                dev_err(isp->dev, "map appl bug: PROT_WRITE and MAP_SHARED are required\n");
1118                return -EINVAL;
1119        }
1120
1121        mutex_lock(&q->vb_lock);
1122        for (i = 0; i < VIDEO_MAX_FRAME; i++) {
1123                struct videobuf_buffer *buf = q->bufs[i];
1124
1125                if (!buf)
1126                        continue;
1127
1128                map = kzalloc(sizeof(struct videobuf_mapping), GFP_KERNEL);
1129                if (!map) {
1130                        mutex_unlock(&q->vb_lock);
1131                        return -ENOMEM;
1132                }
1133
1134                buf->map = map;
1135                map->q = q;
1136
1137                buf->baddr = vma->vm_start;
1138
1139                if (buf && buf->memory == V4L2_MEMORY_MMAP &&
1140                    buf->boff == offset) {
1141                        vm_mem = buf->priv;
1142                        ret = frame_mmap(isp, vm_mem->vaddr, vma);
1143                        vma->vm_flags |= VM_IO | VM_DONTEXPAND | VM_DONTDUMP;
1144                        break;
1145                }
1146        }
1147        mutex_unlock(&q->vb_lock);
1148
1149        return ret;
1150}
1151
1152/* The input frame contains left and right padding that need to be removed.
1153 * There is always ISP_LEFT_PAD padding on the left side.
1154 * There is also padding on the right (padded_width - width).
1155 */
1156static int remove_pad_from_frame(struct atomisp_device *isp,
1157                                 struct ia_css_frame *in_frame, __u32 width, __u32 height)
1158{
1159        unsigned int i;
1160        unsigned short *buffer;
1161        int ret = 0;
1162        ia_css_ptr load = in_frame->data;
1163        ia_css_ptr store = load;
1164
1165        buffer = kmalloc_array(width, sizeof(load), GFP_KERNEL);
1166        if (!buffer)
1167                return -ENOMEM;
1168
1169        load += ISP_LEFT_PAD;
1170        for (i = 0; i < height; i++) {
1171                ret = hmm_load(load, buffer, width * sizeof(load));
1172                if (ret < 0)
1173                        goto remove_pad_error;
1174
1175                ret = hmm_store(store, buffer, width * sizeof(store));
1176                if (ret < 0)
1177                        goto remove_pad_error;
1178
1179                load  += in_frame->info.padded_width;
1180                store += width;
1181        }
1182
1183remove_pad_error:
1184        kfree(buffer);
1185        return ret;
1186}
1187
1188static int atomisp_mmap(struct file *file, struct vm_area_struct *vma)
1189{
1190        struct video_device *vdev = video_devdata(file);
1191        struct atomisp_device *isp = video_get_drvdata(vdev);
1192        struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev);
1193        struct atomisp_sub_device *asd = pipe->asd;
1194        struct ia_css_frame *raw_virt_addr;
1195        u32 start = vma->vm_start;
1196        u32 end = vma->vm_end;
1197        u32 size = end - start;
1198        u32 origin_size, new_size;
1199        int ret;
1200
1201        if (!asd) {
1202                dev_err(isp->dev, "%s(): asd is NULL, device is %s\n",
1203                        __func__, vdev->name);
1204                return -EINVAL;
1205        }
1206
1207        if (!(vma->vm_flags & (VM_WRITE | VM_READ)))
1208                return -EACCES;
1209
1210        rt_mutex_lock(&isp->mutex);
1211
1212        if (!(vma->vm_flags & VM_SHARED)) {
1213                /* Map private buffer.
1214                 * Set VM_SHARED to the flags since we need
1215                 * to map the buffer page by page.
1216                 * Without VM_SHARED, remap_pfn_range() treats
1217                 * this kind of mapping as invalid.
1218                 */
1219                vma->vm_flags |= VM_SHARED;
1220                ret = hmm_mmap(vma, vma->vm_pgoff << PAGE_SHIFT);
1221                rt_mutex_unlock(&isp->mutex);
1222                return ret;
1223        }
1224
1225        /* mmap for ISP offline raw data */
1226        if (atomisp_subdev_source_pad(vdev)
1227            == ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE &&
1228            vma->vm_pgoff == (ISP_PARAM_MMAP_OFFSET >> PAGE_SHIFT)) {
1229                new_size = pipe->pix.width * pipe->pix.height * 2;
1230                if (asd->params.online_process != 0) {
1231                        ret = -EINVAL;
1232                        goto error;
1233                }
1234                raw_virt_addr = asd->raw_output_frame;
1235                if (!raw_virt_addr) {
1236                        dev_err(isp->dev, "Failed to request RAW frame\n");
1237                        ret = -EINVAL;
1238                        goto error;
1239                }
1240
1241                ret = remove_pad_from_frame(isp, raw_virt_addr,
1242                                            pipe->pix.width, pipe->pix.height);
1243                if (ret < 0) {
1244                        dev_err(isp->dev, "remove pad failed.\n");
1245                        goto error;
1246                }
1247                origin_size = raw_virt_addr->data_bytes;
1248                raw_virt_addr->data_bytes = new_size;
1249
1250                if (size != PAGE_ALIGN(new_size)) {
1251                        dev_err(isp->dev, "incorrect size for mmap ISP  Raw Frame\n");
1252                        ret = -EINVAL;
1253                        goto error;
1254                }
1255
1256                if (frame_mmap(isp, raw_virt_addr, vma)) {
1257                        dev_err(isp->dev, "frame_mmap failed.\n");
1258                        raw_virt_addr->data_bytes = origin_size;
1259                        ret = -EAGAIN;
1260                        goto error;
1261                }
1262                raw_virt_addr->data_bytes = origin_size;
1263                vma->vm_flags |= VM_IO | VM_DONTEXPAND | VM_DONTDUMP;
1264                rt_mutex_unlock(&isp->mutex);
1265                return 0;
1266        }
1267
1268        /*
1269         * mmap for normal frames
1270         */
1271        if (size != pipe->pix.sizeimage) {
1272                dev_err(isp->dev, "incorrect size for mmap ISP frames\n");
1273                ret = -EINVAL;
1274                goto error;
1275        }
1276        rt_mutex_unlock(&isp->mutex);
1277
1278        return atomisp_videobuf_mmap_mapper(&pipe->capq, vma);
1279
1280error:
1281        rt_mutex_unlock(&isp->mutex);
1282
1283        return ret;
1284}
1285
1286static int atomisp_file_mmap(struct file *file, struct vm_area_struct *vma)
1287{
1288        struct video_device *vdev = video_devdata(file);
1289        struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev);
1290
1291        return videobuf_mmap_mapper(&pipe->outq, vma);
1292}
1293
1294static __poll_t atomisp_poll(struct file *file,
1295                             struct poll_table_struct *pt)
1296{
1297        struct video_device *vdev = video_devdata(file);
1298        struct atomisp_device *isp = video_get_drvdata(vdev);
1299        struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev);
1300
1301        rt_mutex_lock(&isp->mutex);
1302        if (pipe->capq.streaming != 1) {
1303                rt_mutex_unlock(&isp->mutex);
1304                return EPOLLERR;
1305        }
1306        rt_mutex_unlock(&isp->mutex);
1307
1308        return videobuf_poll_stream(file, &pipe->capq, pt);
1309}
1310
1311const struct v4l2_file_operations atomisp_fops = {
1312        .owner = THIS_MODULE,
1313        .open = atomisp_open,
1314        .release = atomisp_release,
1315        .mmap = atomisp_mmap,
1316        .unlocked_ioctl = video_ioctl2,
1317#ifdef CONFIG_COMPAT
1318        /*
1319         * this was removed because of bugs, the interface
1320         * needs to be made safe for compat tasks instead.
1321        .compat_ioctl32 = atomisp_compat_ioctl32,
1322         */
1323#endif
1324        .poll = atomisp_poll,
1325};
1326
1327const struct v4l2_file_operations atomisp_file_fops = {
1328        .owner = THIS_MODULE,
1329        .open = atomisp_open,
1330        .release = atomisp_release,
1331        .mmap = atomisp_file_mmap,
1332        .unlocked_ioctl = video_ioctl2,
1333#ifdef CONFIG_COMPAT
1334        /* .compat_ioctl32 = atomisp_compat_ioctl32, */
1335#endif
1336        .poll = atomisp_poll,
1337};
1338