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