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#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
 568static 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
 593static 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
 600static 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
 610static 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
 625static 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
 634static 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
 641static 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
 648static 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
 655static 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
 687static 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
 705static 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 */
 743static 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
 753unsigned 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
 763static 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
 833dev_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
 867init_subdev:
 868        if (atomisp_subdev_users(asd))
 869                goto done;
 870
 871        atomisp_subdev_init_struct(asd);
 872
 873done:
 874
 875        if (acc_node)
 876                acc_pipe->users++;
 877        else
 878                pipe->users++;
 879        rt_mutex_unlock(&isp->mutex);
 880        return 0;
 881
 882css_error:
 883        atomisp_css_uninit(isp);
 884error:
 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
 891static 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        }
 970subdev_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
1017done:
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 */
1034static 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
1056static 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
1078int 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 */
1129static 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
1156remove_pad_error:
1157        kfree(buffer);
1158        return ret;
1159}
1160
1161static 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
1247error:
1248        rt_mutex_unlock(&isp->mutex);
1249
1250        return ret;
1251}
1252
1253static 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
1261static __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
1278const 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
1293const 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