linux/drivers/staging/media/atomisp/pci/atomisp_subdev.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 * This program is free software; you can redistribute it and/or
   8 * modify it under the terms of the GNU General Public License version
   9 * 2 as published by the Free Software Foundation.
  10 *
  11 * This program is distributed in the hope that it will be useful,
  12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14 * GNU General Public License for more details.
  15 *
  16 *
  17 */
  18#include <linux/module.h>
  19#include <linux/uaccess.h>
  20#include <linux/delay.h>
  21#include <linux/device.h>
  22#include <linux/mm.h>
  23#include <linux/sched.h>
  24#include <linux/slab.h>
  25
  26#include <media/v4l2-event.h>
  27#include <media/v4l2-mediabus.h>
  28#include "atomisp_cmd.h"
  29#include "atomisp_common.h"
  30#include "atomisp_compat.h"
  31#include "atomisp_internal.h"
  32
  33const struct atomisp_in_fmt_conv atomisp_in_fmt_conv[] = {
  34        { MEDIA_BUS_FMT_SBGGR8_1X8, 8, 8, ATOMISP_INPUT_FORMAT_RAW_8, IA_CSS_BAYER_ORDER_BGGR },
  35        { MEDIA_BUS_FMT_SGBRG8_1X8, 8, 8, ATOMISP_INPUT_FORMAT_RAW_8, IA_CSS_BAYER_ORDER_GBRG },
  36        { MEDIA_BUS_FMT_SGRBG8_1X8, 8, 8, ATOMISP_INPUT_FORMAT_RAW_8, IA_CSS_BAYER_ORDER_GRBG },
  37        { MEDIA_BUS_FMT_SRGGB8_1X8, 8, 8, ATOMISP_INPUT_FORMAT_RAW_8, IA_CSS_BAYER_ORDER_RGGB },
  38        { MEDIA_BUS_FMT_SBGGR10_1X10, 10, 10, ATOMISP_INPUT_FORMAT_RAW_10, IA_CSS_BAYER_ORDER_BGGR },
  39        { MEDIA_BUS_FMT_SGBRG10_1X10, 10, 10, ATOMISP_INPUT_FORMAT_RAW_10, IA_CSS_BAYER_ORDER_GBRG },
  40        { MEDIA_BUS_FMT_SGRBG10_1X10, 10, 10, ATOMISP_INPUT_FORMAT_RAW_10, IA_CSS_BAYER_ORDER_GRBG },
  41        { MEDIA_BUS_FMT_SRGGB10_1X10, 10, 10, ATOMISP_INPUT_FORMAT_RAW_10, IA_CSS_BAYER_ORDER_RGGB },
  42        { MEDIA_BUS_FMT_SBGGR12_1X12, 12, 12, ATOMISP_INPUT_FORMAT_RAW_12, IA_CSS_BAYER_ORDER_BGGR },
  43        { MEDIA_BUS_FMT_SGBRG12_1X12, 12, 12, ATOMISP_INPUT_FORMAT_RAW_12, IA_CSS_BAYER_ORDER_GBRG },
  44        { MEDIA_BUS_FMT_SGRBG12_1X12, 12, 12, ATOMISP_INPUT_FORMAT_RAW_12, IA_CSS_BAYER_ORDER_GRBG },
  45        { MEDIA_BUS_FMT_SRGGB12_1X12, 12, 12, ATOMISP_INPUT_FORMAT_RAW_12, IA_CSS_BAYER_ORDER_RGGB },
  46        { MEDIA_BUS_FMT_UYVY8_1X16, 8, 8, ATOMISP_INPUT_FORMAT_YUV422_8, 0 },
  47        { MEDIA_BUS_FMT_YUYV8_1X16, 8, 8, ATOMISP_INPUT_FORMAT_YUV422_8, 0 },
  48#if 0 // disabled due to clang warnings
  49        { MEDIA_BUS_FMT_JPEG_1X8, 8, 8, IA_CSS_FRAME_FORMAT_BINARY_8, 0 },
  50        { V4L2_MBUS_FMT_CUSTOM_NV12, 12, 12, IA_CSS_FRAME_FORMAT_NV12, 0 },
  51        { V4L2_MBUS_FMT_CUSTOM_NV21, 12, 12, IA_CSS_FRAME_FORMAT_NV21, 0 },
  52#endif
  53        { V4L2_MBUS_FMT_CUSTOM_YUV420, 12, 12, ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY, 0 },
  54#if 0
  55        { V4L2_MBUS_FMT_CUSTOM_M10MO_RAW, 8, 8, IA_CSS_FRAME_FORMAT_BINARY_8, 0 },
  56#endif
  57        /* no valid V4L2 MBUS code for metadata format, so leave it 0. */
  58        { 0, 0, 0, ATOMISP_INPUT_FORMAT_EMBEDDED, 0 },
  59        {}
  60};
  61
  62static const struct {
  63        u32 code;
  64        u32 compressed;
  65} compressed_codes[] = {
  66        { MEDIA_BUS_FMT_SBGGR10_1X10, MEDIA_BUS_FMT_SBGGR10_DPCM8_1X8 },
  67        { MEDIA_BUS_FMT_SGBRG10_1X10, MEDIA_BUS_FMT_SGBRG10_DPCM8_1X8 },
  68        { MEDIA_BUS_FMT_SGRBG10_1X10, MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8 },
  69        { MEDIA_BUS_FMT_SRGGB10_1X10, MEDIA_BUS_FMT_SRGGB10_DPCM8_1X8 },
  70};
  71
  72u32 atomisp_subdev_uncompressed_code(u32 code)
  73{
  74        unsigned int i;
  75
  76        for (i = 0; i < ARRAY_SIZE(compressed_codes); i++)
  77                if (code == compressed_codes[i].compressed)
  78                        return compressed_codes[i].code;
  79
  80        return code;
  81}
  82
  83bool atomisp_subdev_is_compressed(u32 code)
  84{
  85        int i;
  86
  87        for (i = 0; i < ARRAY_SIZE(atomisp_in_fmt_conv) - 1; i++)
  88                if (code == atomisp_in_fmt_conv[i].code)
  89                        return atomisp_in_fmt_conv[i].bpp !=
  90                               atomisp_in_fmt_conv[i].depth;
  91
  92        return false;
  93}
  94
  95const struct atomisp_in_fmt_conv *atomisp_find_in_fmt_conv(u32 code)
  96{
  97        int i;
  98
  99        for (i = 0; i < ARRAY_SIZE(atomisp_in_fmt_conv) - 1; i++)
 100                if (code == atomisp_in_fmt_conv[i].code)
 101                        return atomisp_in_fmt_conv + i;
 102
 103        return NULL;
 104}
 105
 106const struct atomisp_in_fmt_conv *atomisp_find_in_fmt_conv_by_atomisp_in_fmt(
 107    enum atomisp_input_format atomisp_in_fmt)
 108{
 109        int i;
 110
 111        for (i = 0; i < ARRAY_SIZE(atomisp_in_fmt_conv) - 1; i++)
 112                if (atomisp_in_fmt_conv[i].atomisp_in_fmt == atomisp_in_fmt)
 113                        return atomisp_in_fmt_conv + i;
 114
 115        return NULL;
 116}
 117
 118bool atomisp_subdev_format_conversion(struct atomisp_sub_device *asd,
 119                                      unsigned int source_pad)
 120{
 121        struct v4l2_mbus_framefmt *sink, *src;
 122
 123        sink = atomisp_subdev_get_ffmt(&asd->subdev, NULL,
 124                                       V4L2_SUBDEV_FORMAT_ACTIVE,
 125                                       ATOMISP_SUBDEV_PAD_SINK);
 126        src = atomisp_subdev_get_ffmt(&asd->subdev, NULL,
 127                                      V4L2_SUBDEV_FORMAT_ACTIVE, source_pad);
 128
 129        return atomisp_is_mbuscode_raw(sink->code)
 130               && !atomisp_is_mbuscode_raw(src->code);
 131}
 132
 133uint16_t atomisp_subdev_source_pad(struct video_device *vdev)
 134{
 135        struct media_link *link;
 136        u16 ret = 0;
 137
 138        list_for_each_entry(link, &vdev->entity.links, list) {
 139                if (link->source) {
 140                        ret = link->source->index;
 141                        break;
 142                }
 143        }
 144        return ret;
 145}
 146
 147/*
 148 * V4L2 subdev operations
 149 */
 150
 151/*
 152 * isp_subdev_ioctl - CCDC module private ioctl's
 153 * @sd: ISP V4L2 subdevice
 154 * @cmd: ioctl command
 155 * @arg: ioctl argument
 156 *
 157 * Return 0 on success or a negative error code otherwise.
 158 */
 159static long isp_subdev_ioctl(struct v4l2_subdev *sd,
 160                             unsigned int cmd, void *arg)
 161{
 162        return 0;
 163}
 164
 165/*
 166 * isp_subdev_set_power - Power on/off the CCDC module
 167 * @sd: ISP V4L2 subdevice
 168 * @on: power on/off
 169 *
 170 * Return 0 on success or a negative error code otherwise.
 171 */
 172static int isp_subdev_set_power(struct v4l2_subdev *sd, int on)
 173{
 174        return 0;
 175}
 176
 177static int isp_subdev_subscribe_event(struct v4l2_subdev *sd,
 178                                      struct v4l2_fh *fh,
 179                                      struct v4l2_event_subscription *sub)
 180{
 181        struct atomisp_sub_device *isp_sd = v4l2_get_subdevdata(sd);
 182        struct atomisp_device *isp = isp_sd->isp;
 183
 184        if (sub->type != V4L2_EVENT_FRAME_SYNC &&
 185            sub->type != V4L2_EVENT_FRAME_END &&
 186            sub->type != V4L2_EVENT_ATOMISP_3A_STATS_READY &&
 187            sub->type != V4L2_EVENT_ATOMISP_METADATA_READY &&
 188            sub->type != V4L2_EVENT_ATOMISP_PAUSE_BUFFER &&
 189            sub->type != V4L2_EVENT_ATOMISP_CSS_RESET &&
 190            sub->type != V4L2_EVENT_ATOMISP_RAW_BUFFERS_ALLOC_DONE &&
 191            sub->type != V4L2_EVENT_ATOMISP_ACC_COMPLETE)
 192                return -EINVAL;
 193
 194        if (sub->type == V4L2_EVENT_FRAME_SYNC &&
 195            !atomisp_css_valid_sof(isp))
 196                return -EINVAL;
 197
 198        return v4l2_event_subscribe(fh, sub, 16, NULL);
 199}
 200
 201static int isp_subdev_unsubscribe_event(struct v4l2_subdev *sd,
 202                                        struct v4l2_fh *fh,
 203                                        struct v4l2_event_subscription *sub)
 204{
 205        return v4l2_event_unsubscribe(fh, sub);
 206}
 207
 208/*
 209 * isp_subdev_enum_mbus_code - Handle pixel format enumeration
 210 * @sd: pointer to v4l2 subdev structure
 211 * @fh : V4L2 subdev file handle
 212 * @code: pointer to v4l2_subdev_pad_mbus_code_enum structure
 213 * return -EINVAL or zero on success
 214 */
 215static int isp_subdev_enum_mbus_code(struct v4l2_subdev *sd,
 216                                     struct v4l2_subdev_state *sd_state,
 217                                     struct v4l2_subdev_mbus_code_enum *code)
 218{
 219        if (code->index >= ARRAY_SIZE(atomisp_in_fmt_conv) - 1)
 220                return -EINVAL;
 221
 222        code->code = atomisp_in_fmt_conv[code->index].code;
 223
 224        return 0;
 225}
 226
 227static int isp_subdev_validate_rect(struct v4l2_subdev *sd, uint32_t pad,
 228                                    uint32_t target)
 229{
 230        switch (pad) {
 231        case ATOMISP_SUBDEV_PAD_SINK:
 232                switch (target) {
 233                case V4L2_SEL_TGT_CROP:
 234                        return 0;
 235                }
 236                break;
 237        default:
 238                switch (target) {
 239                case V4L2_SEL_TGT_COMPOSE:
 240                        return 0;
 241                }
 242                break;
 243        }
 244
 245        return -EINVAL;
 246}
 247
 248struct v4l2_rect *atomisp_subdev_get_rect(struct v4l2_subdev *sd,
 249        struct v4l2_subdev_state *sd_state,
 250        u32 which, uint32_t pad,
 251        uint32_t target)
 252{
 253        struct atomisp_sub_device *isp_sd = v4l2_get_subdevdata(sd);
 254
 255        if (which == V4L2_SUBDEV_FORMAT_TRY) {
 256                switch (target) {
 257                case V4L2_SEL_TGT_CROP:
 258                        return v4l2_subdev_get_try_crop(sd, sd_state, pad);
 259                case V4L2_SEL_TGT_COMPOSE:
 260                        return v4l2_subdev_get_try_compose(sd, sd_state, pad);
 261                }
 262        }
 263
 264        switch (target) {
 265        case V4L2_SEL_TGT_CROP:
 266                return &isp_sd->fmt[pad].crop;
 267        case V4L2_SEL_TGT_COMPOSE:
 268                return &isp_sd->fmt[pad].compose;
 269        }
 270
 271        return NULL;
 272}
 273
 274struct v4l2_mbus_framefmt
 275*atomisp_subdev_get_ffmt(struct v4l2_subdev *sd,
 276                         struct v4l2_subdev_state *sd_state, uint32_t which,
 277                         uint32_t pad)
 278{
 279        struct atomisp_sub_device *isp_sd = v4l2_get_subdevdata(sd);
 280
 281        if (which == V4L2_SUBDEV_FORMAT_TRY)
 282                return v4l2_subdev_get_try_format(sd, sd_state, pad);
 283
 284        return &isp_sd->fmt[pad].fmt;
 285}
 286
 287static void isp_get_fmt_rect(struct v4l2_subdev *sd,
 288                             struct v4l2_subdev_state *sd_state,
 289                             uint32_t which,
 290                             struct v4l2_mbus_framefmt **ffmt,
 291                             struct v4l2_rect *crop[ATOMISP_SUBDEV_PADS_NUM],
 292                             struct v4l2_rect *comp[ATOMISP_SUBDEV_PADS_NUM])
 293{
 294        unsigned int i;
 295
 296        for (i = 0; i < ATOMISP_SUBDEV_PADS_NUM; i++) {
 297                ffmt[i] = atomisp_subdev_get_ffmt(sd, sd_state, which, i);
 298                crop[i] = atomisp_subdev_get_rect(sd, sd_state, which, i,
 299                                                  V4L2_SEL_TGT_CROP);
 300                comp[i] = atomisp_subdev_get_rect(sd, sd_state, which, i,
 301                                                  V4L2_SEL_TGT_COMPOSE);
 302        }
 303}
 304
 305static void isp_subdev_propagate(struct v4l2_subdev *sd,
 306                                 struct v4l2_subdev_state *sd_state,
 307                                 u32 which, uint32_t pad, uint32_t target,
 308                                 uint32_t flags)
 309{
 310        struct v4l2_mbus_framefmt *ffmt[ATOMISP_SUBDEV_PADS_NUM];
 311        struct v4l2_rect *crop[ATOMISP_SUBDEV_PADS_NUM],
 312                       *comp[ATOMISP_SUBDEV_PADS_NUM];
 313
 314        if (flags & V4L2_SEL_FLAG_KEEP_CONFIG)
 315                return;
 316
 317        isp_get_fmt_rect(sd, sd_state, which, ffmt, crop, comp);
 318
 319        switch (pad) {
 320        case ATOMISP_SUBDEV_PAD_SINK: {
 321                struct v4l2_rect r = {0};
 322
 323                /* Only crop target supported on sink pad. */
 324                r.width = ffmt[pad]->width;
 325                r.height = ffmt[pad]->height;
 326
 327                atomisp_subdev_set_selection(sd, sd_state, which, pad,
 328                                             target, flags, &r);
 329                break;
 330        }
 331        }
 332}
 333
 334static int isp_subdev_get_selection(struct v4l2_subdev *sd,
 335                                    struct v4l2_subdev_state *sd_state,
 336                                    struct v4l2_subdev_selection *sel)
 337{
 338        struct v4l2_rect *rec;
 339        int rval = isp_subdev_validate_rect(sd, sel->pad, sel->target);
 340
 341        if (rval)
 342                return rval;
 343
 344        rec = atomisp_subdev_get_rect(sd, sd_state, sel->which, sel->pad,
 345                                      sel->target);
 346        if (!rec)
 347                return -EINVAL;
 348
 349        sel->r = *rec;
 350        return 0;
 351}
 352
 353static const char *atomisp_pad_str(unsigned int pad)
 354{
 355        static const char *const pad_str[] = {
 356                "ATOMISP_SUBDEV_PAD_SINK",
 357                "ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE",
 358                "ATOMISP_SUBDEV_PAD_SOURCE_VF",
 359                "ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW",
 360                "ATOMISP_SUBDEV_PAD_SOURCE_VIDEO",
 361        };
 362
 363        if (pad >= ARRAY_SIZE(pad_str))
 364                return "ATOMISP_INVALID_PAD";
 365        return pad_str[pad];
 366}
 367
 368int atomisp_subdev_set_selection(struct v4l2_subdev *sd,
 369                                 struct v4l2_subdev_state *sd_state,
 370                                 u32 which, uint32_t pad, uint32_t target,
 371                                 u32 flags, struct v4l2_rect *r)
 372{
 373        struct atomisp_sub_device *isp_sd = v4l2_get_subdevdata(sd);
 374        struct atomisp_device *isp = isp_sd->isp;
 375        struct v4l2_mbus_framefmt *ffmt[ATOMISP_SUBDEV_PADS_NUM];
 376        u16 vdev_pad = atomisp_subdev_source_pad(sd->devnode);
 377        struct v4l2_rect *crop[ATOMISP_SUBDEV_PADS_NUM],
 378                       *comp[ATOMISP_SUBDEV_PADS_NUM];
 379        enum atomisp_input_stream_id stream_id;
 380        unsigned int i;
 381        unsigned int padding_w = pad_w;
 382        unsigned int padding_h = pad_h;
 383
 384        stream_id = atomisp_source_pad_to_stream_id(isp_sd, vdev_pad);
 385
 386        isp_get_fmt_rect(sd, sd_state, which, ffmt, crop, comp);
 387
 388        dev_dbg(isp->dev,
 389                "sel: pad %s tgt %s l %d t %d w %d h %d which %s f 0x%8.8x\n",
 390                atomisp_pad_str(pad), target == V4L2_SEL_TGT_CROP
 391                ? "V4L2_SEL_TGT_CROP" : "V4L2_SEL_TGT_COMPOSE",
 392                r->left, r->top, r->width, r->height,
 393                which == V4L2_SUBDEV_FORMAT_TRY ? "V4L2_SUBDEV_FORMAT_TRY"
 394                : "V4L2_SUBDEV_FORMAT_ACTIVE", flags);
 395
 396        r->width = rounddown(r->width, ATOM_ISP_STEP_WIDTH);
 397        r->height = rounddown(r->height, ATOM_ISP_STEP_HEIGHT);
 398
 399        switch (pad) {
 400        case ATOMISP_SUBDEV_PAD_SINK: {
 401                /* Only crop target supported on sink pad. */
 402                unsigned int dvs_w, dvs_h;
 403
 404                crop[pad]->width = ffmt[pad]->width;
 405                crop[pad]->height = ffmt[pad]->height;
 406
 407                /* Workaround for BYT 1080p perfectshot since the maxinum resolution of
 408                 * front camera ov2722 is 1932x1092 and cannot use pad_w > 12*/
 409                if (!strncmp(isp->inputs[isp_sd->input_curr].camera->name,
 410                             "ov2722", 6) && crop[pad]->height == 1092) {
 411                        padding_w = 12;
 412                        padding_h = 12;
 413                }
 414
 415                if (isp->inputs[isp_sd->input_curr].type == SOC_CAMERA) {
 416                        padding_w = 0;
 417                        padding_h = 0;
 418                }
 419
 420                if (atomisp_subdev_format_conversion(isp_sd,
 421                                                     isp_sd->capture_pad)
 422                    && crop[pad]->width && crop[pad]->height) {
 423                        crop[pad]->width -= padding_w;
 424                        crop[pad]->height -= padding_h;
 425                }
 426
 427                /* if subdev type is SOC camera,we do not need to set DVS */
 428                if (isp->inputs[isp_sd->input_curr].type == SOC_CAMERA)
 429                        isp_sd->params.video_dis_en = 0;
 430
 431                if (isp_sd->params.video_dis_en &&
 432                    isp_sd->run_mode->val == ATOMISP_RUN_MODE_VIDEO &&
 433                    !isp_sd->continuous_mode->val) {
 434                        /* This resolution contains 20 % of DVS slack
 435                         * (of the desired captured image before
 436                         * scaling, or 1 / 6 of what we get from the
 437                         * sensor) in both width and height. Remove
 438                         * it. */
 439                        crop[pad]->width = roundup(crop[pad]->width * 5 / 6,
 440                                                   ATOM_ISP_STEP_WIDTH);
 441                        crop[pad]->height = roundup(crop[pad]->height * 5 / 6,
 442                                                    ATOM_ISP_STEP_HEIGHT);
 443                }
 444
 445                crop[pad]->width = min(crop[pad]->width, r->width);
 446                crop[pad]->height = min(crop[pad]->height, r->height);
 447
 448                if (!(flags & V4L2_SEL_FLAG_KEEP_CONFIG)) {
 449                        for (i = ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE;
 450                             i < ATOMISP_SUBDEV_PADS_NUM; i++) {
 451                                struct v4l2_rect tmp = *crop[pad];
 452
 453                                atomisp_subdev_set_selection(
 454                                    sd, sd_state, which, i,
 455                                    V4L2_SEL_TGT_COMPOSE,
 456                                    flags, &tmp);
 457                        }
 458                }
 459
 460                if (which == V4L2_SUBDEV_FORMAT_TRY)
 461                        break;
 462
 463                if (isp_sd->params.video_dis_en &&
 464                    isp_sd->run_mode->val == ATOMISP_RUN_MODE_VIDEO &&
 465                    !isp_sd->continuous_mode->val) {
 466                        dvs_w = rounddown(crop[pad]->width / 5,
 467                                          ATOM_ISP_STEP_WIDTH);
 468                        dvs_h = rounddown(crop[pad]->height / 5,
 469                                          ATOM_ISP_STEP_HEIGHT);
 470                } else if (!isp_sd->params.video_dis_en &&
 471                           isp_sd->run_mode->val == ATOMISP_RUN_MODE_VIDEO) {
 472                        /*
 473                         * For CSS2.0, digital zoom needs to set dvs envelope to 12
 474                         * when dvs is disabled.
 475                         */
 476                        dvs_w = dvs_h = 12;
 477                } else {
 478                        dvs_w = dvs_h = 0;
 479                }
 480                atomisp_css_video_set_dis_envelope(isp_sd, dvs_w, dvs_h);
 481                atomisp_css_input_set_effective_resolution(isp_sd, stream_id,
 482                        crop[pad]->width, crop[pad]->height);
 483
 484                break;
 485        }
 486        case ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE:
 487        case ATOMISP_SUBDEV_PAD_SOURCE_VIDEO: {
 488                /* Only compose target is supported on source pads. */
 489
 490                if (isp_sd->vfpp->val == ATOMISP_VFPP_DISABLE_LOWLAT) {
 491                        /* Scaling is disabled in this mode */
 492                        r->width = crop[ATOMISP_SUBDEV_PAD_SINK]->width;
 493                        r->height = crop[ATOMISP_SUBDEV_PAD_SINK]->height;
 494                }
 495
 496                if (crop[ATOMISP_SUBDEV_PAD_SINK]->width == r->width
 497                    && crop[ATOMISP_SUBDEV_PAD_SINK]->height == r->height)
 498                        isp_sd->params.yuv_ds_en = false;
 499                else
 500                        isp_sd->params.yuv_ds_en = true;
 501
 502                comp[pad]->width = r->width;
 503                comp[pad]->height = r->height;
 504
 505                if (r->width == 0 || r->height == 0 ||
 506                    crop[ATOMISP_SUBDEV_PAD_SINK]->width == 0 ||
 507                    crop[ATOMISP_SUBDEV_PAD_SINK]->height == 0)
 508                        break;
 509                /*
 510                 * do cropping on sensor input if ratio of required resolution
 511                 * is different with sensor output resolution ratio:
 512                 *
 513                 * ratio = width / height
 514                 *
 515                 * if ratio_output < ratio_sensor:
 516                 *      effect_width = sensor_height * out_width / out_height;
 517                 *      effect_height = sensor_height;
 518                 * else
 519                 *      effect_width = sensor_width;
 520                 *      effect_height = sensor_width * out_height / out_width;
 521                 *
 522                 */
 523                if (r->width * crop[ATOMISP_SUBDEV_PAD_SINK]->height <
 524                    crop[ATOMISP_SUBDEV_PAD_SINK]->width * r->height)
 525                        atomisp_css_input_set_effective_resolution(isp_sd,
 526                                stream_id,
 527                                rounddown(crop[ATOMISP_SUBDEV_PAD_SINK]->
 528                                          height * r->width / r->height,
 529                                          ATOM_ISP_STEP_WIDTH),
 530                                crop[ATOMISP_SUBDEV_PAD_SINK]->height);
 531                else
 532                        atomisp_css_input_set_effective_resolution(isp_sd,
 533                                stream_id,
 534                                crop[ATOMISP_SUBDEV_PAD_SINK]->width,
 535                                rounddown(crop[ATOMISP_SUBDEV_PAD_SINK]->
 536                                          width * r->height / r->width,
 537                                          ATOM_ISP_STEP_WIDTH));
 538
 539                break;
 540        }
 541        case ATOMISP_SUBDEV_PAD_SOURCE_VF:
 542        case ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW:
 543                comp[pad]->width = r->width;
 544                comp[pad]->height = r->height;
 545                break;
 546        default:
 547                return -EINVAL;
 548        }
 549
 550        /* Set format dimensions on non-sink pads as well. */
 551        if (pad != ATOMISP_SUBDEV_PAD_SINK) {
 552                ffmt[pad]->width = comp[pad]->width;
 553                ffmt[pad]->height = comp[pad]->height;
 554        }
 555
 556        if (!atomisp_subdev_get_rect(sd, sd_state, which, pad, target))
 557                return -EINVAL;
 558        *r = *atomisp_subdev_get_rect(sd, sd_state, which, pad, target);
 559
 560        dev_dbg(isp->dev, "sel actual: l %d t %d w %d h %d\n",
 561                r->left, r->top, r->width, r->height);
 562
 563        return 0;
 564}
 565
 566static int isp_subdev_set_selection(struct v4l2_subdev *sd,
 567                                    struct v4l2_subdev_state *sd_state,
 568                                    struct v4l2_subdev_selection *sel)
 569{
 570        int rval = isp_subdev_validate_rect(sd, sel->pad, sel->target);
 571
 572        if (rval)
 573                return rval;
 574
 575        return atomisp_subdev_set_selection(sd, sd_state, sel->which,
 576                                            sel->pad,
 577                                            sel->target, sel->flags, &sel->r);
 578}
 579
 580static int atomisp_get_sensor_bin_factor(struct atomisp_sub_device *asd)
 581{
 582        struct v4l2_control ctrl = {0};
 583        struct atomisp_device *isp = asd->isp;
 584        int hbin, vbin;
 585        int ret;
 586
 587        if (isp->inputs[asd->input_curr].type == FILE_INPUT ||
 588            isp->inputs[asd->input_curr].type == TEST_PATTERN)
 589                return 0;
 590
 591        ctrl.id = V4L2_CID_BIN_FACTOR_HORZ;
 592        ret =
 593            v4l2_g_ctrl(isp->inputs[asd->input_curr].camera->ctrl_handler,
 594                        &ctrl);
 595        hbin = ctrl.value;
 596        ctrl.id = V4L2_CID_BIN_FACTOR_VERT;
 597        ret |=
 598            v4l2_g_ctrl(isp->inputs[asd->input_curr].camera->ctrl_handler,
 599                        &ctrl);
 600        vbin = ctrl.value;
 601
 602        /*
 603         * ISP needs to know binning factor from sensor.
 604         * In case horizontal and vertical sensor's binning factors
 605         * are different or sensor does not support binning factor CID,
 606         * ISP will apply default 0 value.
 607         */
 608        if (ret || hbin != vbin)
 609                hbin = 0;
 610
 611        return hbin;
 612}
 613
 614void atomisp_subdev_set_ffmt(struct v4l2_subdev *sd,
 615                             struct v4l2_subdev_state *sd_state,
 616                             uint32_t which,
 617                             u32 pad, struct v4l2_mbus_framefmt *ffmt)
 618{
 619        struct atomisp_sub_device *isp_sd = v4l2_get_subdevdata(sd);
 620        struct atomisp_device *isp = isp_sd->isp;
 621        struct v4l2_mbus_framefmt *__ffmt =
 622            atomisp_subdev_get_ffmt(sd, sd_state, which, pad);
 623        u16 vdev_pad = atomisp_subdev_source_pad(sd->devnode);
 624        enum atomisp_input_stream_id stream_id;
 625
 626        dev_dbg(isp->dev, "ffmt: pad %s w %d h %d code 0x%8.8x which %s\n",
 627                atomisp_pad_str(pad), ffmt->width, ffmt->height, ffmt->code,
 628                which == V4L2_SUBDEV_FORMAT_TRY ? "V4L2_SUBDEV_FORMAT_TRY"
 629                : "V4L2_SUBDEV_FORMAT_ACTIVE");
 630
 631        stream_id = atomisp_source_pad_to_stream_id(isp_sd, vdev_pad);
 632
 633        switch (pad) {
 634        case ATOMISP_SUBDEV_PAD_SINK: {
 635                const struct atomisp_in_fmt_conv *fc =
 636                    atomisp_find_in_fmt_conv(ffmt->code);
 637
 638                if (!fc) {
 639                        fc = atomisp_in_fmt_conv;
 640                        ffmt->code = fc->code;
 641                        dev_dbg(isp->dev, "using 0x%8.8x instead\n",
 642                                ffmt->code);
 643                }
 644
 645                *__ffmt = *ffmt;
 646
 647                isp_subdev_propagate(sd, sd_state, which, pad,
 648                                     V4L2_SEL_TGT_CROP, 0);
 649
 650                if (which == V4L2_SUBDEV_FORMAT_ACTIVE) {
 651                        atomisp_css_input_set_resolution(isp_sd,
 652                                                         stream_id, ffmt);
 653                        atomisp_css_input_set_binning_factor(isp_sd,
 654                                                             stream_id,
 655                                                             atomisp_get_sensor_bin_factor(isp_sd));
 656                        atomisp_css_input_set_bayer_order(isp_sd, stream_id,
 657                                                          fc->bayer_order);
 658                        atomisp_css_input_set_format(isp_sd, stream_id,
 659                                                     fc->atomisp_in_fmt);
 660                        atomisp_css_set_default_isys_config(isp_sd, stream_id,
 661                                                            ffmt);
 662                }
 663
 664                break;
 665        }
 666        case ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE:
 667        case ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW:
 668        case ATOMISP_SUBDEV_PAD_SOURCE_VF:
 669        case ATOMISP_SUBDEV_PAD_SOURCE_VIDEO:
 670                __ffmt->code = ffmt->code;
 671                break;
 672        }
 673}
 674
 675/*
 676 * isp_subdev_get_format - Retrieve the video format on a pad
 677 * @sd : ISP V4L2 subdevice
 678 * @fh : V4L2 subdev file handle
 679 * @pad: Pad number
 680 * @fmt: Format
 681 *
 682 * Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond
 683 * to the format type.
 684 */
 685static int isp_subdev_get_format(struct v4l2_subdev *sd,
 686                                 struct v4l2_subdev_state *sd_state,
 687                                 struct v4l2_subdev_format *fmt)
 688{
 689        fmt->format = *atomisp_subdev_get_ffmt(sd, sd_state, fmt->which,
 690                                               fmt->pad);
 691
 692        return 0;
 693}
 694
 695/*
 696 * isp_subdev_set_format - Set the video format on a pad
 697 * @sd : ISP subdev V4L2 subdevice
 698 * @fh : V4L2 subdev file handle
 699 * @pad: Pad number
 700 * @fmt: Format
 701 *
 702 * Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond
 703 * to the format type.
 704 */
 705static int isp_subdev_set_format(struct v4l2_subdev *sd,
 706                                 struct v4l2_subdev_state *sd_state,
 707                                 struct v4l2_subdev_format *fmt)
 708{
 709        atomisp_subdev_set_ffmt(sd, sd_state, fmt->which, fmt->pad,
 710                                &fmt->format);
 711
 712        return 0;
 713}
 714
 715/* V4L2 subdev core operations */
 716static const struct v4l2_subdev_core_ops isp_subdev_v4l2_core_ops = {
 717        .ioctl = isp_subdev_ioctl, .s_power = isp_subdev_set_power,
 718        .subscribe_event = isp_subdev_subscribe_event,
 719        .unsubscribe_event = isp_subdev_unsubscribe_event,
 720};
 721
 722/* V4L2 subdev pad operations */
 723static const struct v4l2_subdev_pad_ops isp_subdev_v4l2_pad_ops = {
 724        .enum_mbus_code = isp_subdev_enum_mbus_code,
 725        .get_fmt = isp_subdev_get_format,
 726        .set_fmt = isp_subdev_set_format,
 727        .get_selection = isp_subdev_get_selection,
 728        .set_selection = isp_subdev_set_selection,
 729        .link_validate = v4l2_subdev_link_validate_default,
 730};
 731
 732/* V4L2 subdev operations */
 733static const struct v4l2_subdev_ops isp_subdev_v4l2_ops = {
 734        .core = &isp_subdev_v4l2_core_ops,
 735        .pad = &isp_subdev_v4l2_pad_ops,
 736};
 737
 738static void isp_subdev_init_params(struct atomisp_sub_device *asd)
 739{
 740        unsigned int i;
 741
 742        /* parameters initialization */
 743        INIT_LIST_HEAD(&asd->s3a_stats);
 744        INIT_LIST_HEAD(&asd->s3a_stats_in_css);
 745        INIT_LIST_HEAD(&asd->s3a_stats_ready);
 746        INIT_LIST_HEAD(&asd->dis_stats);
 747        INIT_LIST_HEAD(&asd->dis_stats_in_css);
 748        spin_lock_init(&asd->dis_stats_lock);
 749        for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) {
 750                INIT_LIST_HEAD(&asd->metadata[i]);
 751                INIT_LIST_HEAD(&asd->metadata_in_css[i]);
 752                INIT_LIST_HEAD(&asd->metadata_ready[i]);
 753        }
 754}
 755
 756/*
 757* isp_subdev_link_setup - Setup isp subdev connections
 758* @entity: ispsubdev media entity
 759* @local: Pad at the local end of the link
 760* @remote: Pad at the remote end of the link
 761* @flags: Link flags
 762*
 763* return -EINVAL or zero on success
 764*/
 765static int isp_subdev_link_setup(struct media_entity *entity,
 766                                 const struct media_pad *local,
 767                                 const struct media_pad *remote, u32 flags)
 768{
 769        struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
 770        struct atomisp_sub_device *isp_sd = v4l2_get_subdevdata(sd);
 771        struct atomisp_device *isp = isp_sd->isp;
 772        unsigned int i;
 773
 774        switch (local->index | is_media_entity_v4l2_subdev(remote->entity)) {
 775        case ATOMISP_SUBDEV_PAD_SINK | MEDIA_ENT_F_V4L2_SUBDEV_UNKNOWN:
 776                /* Read from the sensor CSI2-ports. */
 777                if (!(flags & MEDIA_LNK_FL_ENABLED)) {
 778                        isp_sd->input = ATOMISP_SUBDEV_INPUT_NONE;
 779                        break;
 780                }
 781
 782                if (isp_sd->input != ATOMISP_SUBDEV_INPUT_NONE)
 783                        return -EBUSY;
 784
 785                for (i = 0; i < ATOMISP_CAMERA_NR_PORTS; i++) {
 786                        if (remote->entity != &isp->csi2_port[i].subdev.entity)
 787                                continue;
 788
 789                        isp_sd->input = ATOMISP_SUBDEV_INPUT_CSI2_PORT1 + i;
 790                        return 0;
 791                }
 792
 793                return -EINVAL;
 794
 795        case ATOMISP_SUBDEV_PAD_SINK | MEDIA_ENT_F_OLD_BASE:
 796                /* read from memory */
 797                if (flags & MEDIA_LNK_FL_ENABLED) {
 798                        if (isp_sd->input >= ATOMISP_SUBDEV_INPUT_CSI2_PORT1 &&
 799                            isp_sd->input < (ATOMISP_SUBDEV_INPUT_CSI2_PORT1
 800                                             + ATOMISP_CAMERA_NR_PORTS))
 801                                return -EBUSY;
 802                        isp_sd->input = ATOMISP_SUBDEV_INPUT_MEMORY;
 803                } else {
 804                        if (isp_sd->input == ATOMISP_SUBDEV_INPUT_MEMORY)
 805                                isp_sd->input = ATOMISP_SUBDEV_INPUT_NONE;
 806                }
 807                break;
 808
 809        case ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW | MEDIA_ENT_F_OLD_BASE:
 810                /* always write to memory */
 811                break;
 812
 813        case ATOMISP_SUBDEV_PAD_SOURCE_VF | MEDIA_ENT_F_OLD_BASE:
 814                /* always write to memory */
 815                break;
 816
 817        case ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE | MEDIA_ENT_F_OLD_BASE:
 818                /* always write to memory */
 819                break;
 820
 821        case ATOMISP_SUBDEV_PAD_SOURCE_VIDEO | MEDIA_ENT_F_OLD_BASE:
 822                /* always write to memory */
 823                break;
 824
 825        default:
 826                return -EINVAL;
 827        }
 828
 829        return 0;
 830}
 831
 832/* media operations */
 833static const struct media_entity_operations isp_subdev_media_ops = {
 834        .link_setup = isp_subdev_link_setup,
 835        .link_validate = v4l2_subdev_link_validate,
 836        /*       .set_power = v4l2_subdev_set_power,    */
 837};
 838
 839static int __atomisp_update_run_mode(struct atomisp_sub_device *asd)
 840{
 841        struct atomisp_device *isp = asd->isp;
 842        struct v4l2_ctrl *ctrl = asd->run_mode;
 843        struct v4l2_ctrl *c;
 844        s32 mode;
 845
 846        if (ctrl->val != ATOMISP_RUN_MODE_VIDEO &&
 847            asd->continuous_mode->val)
 848                mode = ATOMISP_RUN_MODE_PREVIEW;
 849        else
 850                mode = ctrl->val;
 851
 852        c = v4l2_ctrl_find(
 853                isp->inputs[asd->input_curr].camera->ctrl_handler,
 854                V4L2_CID_RUN_MODE);
 855
 856        if (c)
 857                return v4l2_ctrl_s_ctrl(c, mode);
 858
 859        return 0;
 860}
 861
 862int atomisp_update_run_mode(struct atomisp_sub_device *asd)
 863{
 864        int rval;
 865
 866        mutex_lock(asd->ctrl_handler.lock);
 867        rval = __atomisp_update_run_mode(asd);
 868        mutex_unlock(asd->ctrl_handler.lock);
 869
 870        return rval;
 871}
 872
 873static int s_ctrl(struct v4l2_ctrl *ctrl)
 874{
 875        struct atomisp_sub_device *asd = container_of(
 876                                             ctrl->handler, struct atomisp_sub_device, ctrl_handler);
 877
 878        switch (ctrl->id) {
 879        case V4L2_CID_RUN_MODE:
 880                return __atomisp_update_run_mode(asd);
 881        case V4L2_CID_DEPTH_MODE:
 882                if (asd->streaming != ATOMISP_DEVICE_STREAMING_DISABLED) {
 883                        dev_err(asd->isp->dev,
 884                                "ISP is streaming, it is not supported to change the depth mode\n");
 885                        return -EINVAL;
 886                }
 887                break;
 888        }
 889
 890        return 0;
 891}
 892
 893static const struct v4l2_ctrl_ops ctrl_ops = {
 894        .s_ctrl = &s_ctrl,
 895};
 896
 897static const struct v4l2_ctrl_config ctrl_fmt_auto = {
 898        .ops = &ctrl_ops,
 899        .id = V4L2_CID_FMT_AUTO,
 900        .name = "Automatic format guessing",
 901        .type = V4L2_CTRL_TYPE_BOOLEAN,
 902        .min = 0,
 903        .max = 1,
 904        .step = 1,
 905        .def = 1,
 906};
 907
 908static const char *const ctrl_run_mode_menu[] = {
 909        NULL,
 910        "Video",
 911        "Still capture",
 912        "Continuous capture",
 913        "Preview",
 914};
 915
 916static const struct v4l2_ctrl_config ctrl_run_mode = {
 917        .ops = &ctrl_ops,
 918        .id = V4L2_CID_RUN_MODE,
 919        .name = "Atomisp run mode",
 920        .type = V4L2_CTRL_TYPE_MENU,
 921        .min = 1,
 922        .def = 1,
 923        .max = 4,
 924        .qmenu = ctrl_run_mode_menu,
 925};
 926
 927static const char *const ctrl_vfpp_mode_menu[] = {
 928        "Enable",                       /* vfpp always enabled */
 929        "Disable to scaler mode",       /* CSS into video mode and disable */
 930        "Disable to low latency mode",  /* CSS into still mode and disable */
 931};
 932
 933static const struct v4l2_ctrl_config ctrl_vfpp = {
 934        .id = V4L2_CID_VFPP,
 935        .name = "Atomisp vf postprocess",
 936        .type = V4L2_CTRL_TYPE_MENU,
 937        .min = 0,
 938        .def = 0,
 939        .max = 2,
 940        .qmenu = ctrl_vfpp_mode_menu,
 941};
 942
 943/*
 944 * Control for ISP continuous mode
 945 *
 946 * When enabled, capture processing is possible without
 947 * stopping the preview pipeline. When disabled, ISP needs
 948 * to be restarted between preview and capture.
 949 */
 950static const struct v4l2_ctrl_config ctrl_continuous_mode = {
 951        .ops = &ctrl_ops,
 952        .id = V4L2_CID_ATOMISP_CONTINUOUS_MODE,
 953        .type = V4L2_CTRL_TYPE_BOOLEAN,
 954        .name = "Continuous mode",
 955        .min = 0,
 956        .max = 1,
 957        .step = 1,
 958        .def = 0,
 959};
 960
 961/*
 962 * Control for continuous mode raw buffer size
 963 *
 964 * The size of the RAW ringbuffer sets limit on how much
 965 * back in time application can go when requesting capture
 966 * frames to be rendered, and how many frames can be rendered
 967 * in a burst at full sensor rate.
 968 *
 969 * Note: this setting has a big impact on memory consumption of
 970 * the CSS subsystem.
 971 */
 972static const struct v4l2_ctrl_config ctrl_continuous_raw_buffer_size = {
 973        .ops = &ctrl_ops,
 974        .id = V4L2_CID_ATOMISP_CONTINUOUS_RAW_BUFFER_SIZE,
 975        .type = V4L2_CTRL_TYPE_INTEGER,
 976        .name = "Continuous raw ringbuffer size",
 977        .min = 1,
 978        .max = 100, /* depends on CSS version, runtime checked */
 979        .step = 1,
 980        .def = 3,
 981};
 982
 983/*
 984 * Control for enabling continuous viewfinder
 985 *
 986 * When enabled, and ISP is in continuous mode (see ctrl_continuous_mode ),
 987 * preview pipeline continues concurrently with capture
 988 * processing. When disabled, and continuous mode is used,
 989 * preview is paused while captures are processed, but
 990 * full pipeline restart is not needed.
 991 *
 992 * By setting this to disabled, capture processing is
 993 * essentially given priority over preview, and the effective
 994 * capture output rate may be higher than with continuous
 995 * viewfinder enabled.
 996 */
 997static const struct v4l2_ctrl_config ctrl_continuous_viewfinder = {
 998        .id = V4L2_CID_ATOMISP_CONTINUOUS_VIEWFINDER,
 999        .type = V4L2_CTRL_TYPE_BOOLEAN,
1000        .name = "Continuous viewfinder",
1001        .min = 0,
1002        .max = 1,
1003        .step = 1,
1004        .def = 0,
1005};
1006
1007/*
1008 * Control for enabling Lock&Unlock Raw Buffer mechanism
1009 *
1010 * When enabled, Raw Buffer can be locked and unlocked.
1011 * Application can hold the exp_id of Raw Buffer
1012 * and unlock it when no longer needed.
1013 * Note: Make sure set this configuration before creating stream.
1014 */
1015static const struct v4l2_ctrl_config ctrl_enable_raw_buffer_lock = {
1016        .id = V4L2_CID_ENABLE_RAW_BUFFER_LOCK,
1017        .type = V4L2_CTRL_TYPE_BOOLEAN,
1018        .name = "Lock Unlock Raw Buffer",
1019        .min = 0,
1020        .max = 1,
1021        .step = 1,
1022        .def = 0,
1023};
1024
1025/*
1026 * Control to disable digital zoom of the whole stream
1027 *
1028 * When it is true, pipe configuration enable_dz will be set to false.
1029 * This can help get a better performance by disabling pp binary.
1030 *
1031 * Note: Make sure set this configuration before creating stream.
1032 */
1033static const struct v4l2_ctrl_config ctrl_disable_dz = {
1034        .id = V4L2_CID_DISABLE_DZ,
1035        .type = V4L2_CTRL_TYPE_BOOLEAN,
1036        .name = "Disable digital zoom",
1037        .min = 0,
1038        .max = 1,
1039        .step = 1,
1040        .def = 0,
1041};
1042
1043/*
1044 * Control for ISP depth mode
1045 *
1046 * When enabled, that means ISP will deal with dual streams and sensors will be
1047 * in slave/master mode.
1048 * slave sensor will have no output until master sensor is streamed on.
1049 */
1050static const struct v4l2_ctrl_config ctrl_depth_mode = {
1051        .ops = &ctrl_ops,
1052        .id = V4L2_CID_DEPTH_MODE,
1053        .type = V4L2_CTRL_TYPE_BOOLEAN,
1054        .name = "Depth mode",
1055        .min = 0,
1056        .max = 1,
1057        .step = 1,
1058        .def = 0,
1059};
1060
1061/*
1062 * Control for selectting ISP version
1063 *
1064 * When enabled, that means ISP version will be used ISP2.7. when disable, the
1065 * isp will default to use ISP2.2.
1066 * Note: Make sure set this configuration before creating stream.
1067 */
1068static const struct v4l2_ctrl_config ctrl_select_isp_version = {
1069        .ops = &ctrl_ops,
1070        .id = V4L2_CID_ATOMISP_SELECT_ISP_VERSION,
1071        .type = V4L2_CTRL_TYPE_BOOLEAN,
1072        .name = "Select Isp version",
1073        .min = 0,
1074        .max = 1,
1075        .step = 1,
1076        .def = 0,
1077};
1078
1079static void atomisp_init_subdev_pipe(struct atomisp_sub_device *asd,
1080                                     struct atomisp_video_pipe *pipe, enum v4l2_buf_type buf_type)
1081{
1082        pipe->type = buf_type;
1083        pipe->asd = asd;
1084        pipe->isp = asd->isp;
1085        spin_lock_init(&pipe->irq_lock);
1086        INIT_LIST_HEAD(&pipe->activeq);
1087        INIT_LIST_HEAD(&pipe->activeq_out);
1088        INIT_LIST_HEAD(&pipe->buffers_waiting_for_param);
1089        INIT_LIST_HEAD(&pipe->per_frame_params);
1090        memset(pipe->frame_request_config_id,
1091               0, VIDEO_MAX_FRAME * sizeof(unsigned int));
1092        memset(pipe->frame_params,
1093               0, VIDEO_MAX_FRAME *
1094               sizeof(struct atomisp_css_params_with_list *));
1095}
1096
1097static void atomisp_init_acc_pipe(struct atomisp_sub_device *asd,
1098                                  struct atomisp_acc_pipe *pipe)
1099{
1100        pipe->asd = asd;
1101        pipe->isp = asd->isp;
1102        INIT_LIST_HEAD(&asd->acc.fw);
1103        INIT_LIST_HEAD(&asd->acc.memory_maps);
1104        ida_init(&asd->acc.ida);
1105}
1106
1107/*
1108 * isp_subdev_init_entities - Initialize V4L2 subdev and media entity
1109 * @asd: ISP CCDC module
1110 *
1111 * Return 0 on success and a negative error code on failure.
1112 */
1113static int isp_subdev_init_entities(struct atomisp_sub_device *asd)
1114{
1115        struct v4l2_subdev *sd = &asd->subdev;
1116        struct media_pad *pads = asd->pads;
1117        struct media_entity *me = &sd->entity;
1118        int ret;
1119
1120        asd->input = ATOMISP_SUBDEV_INPUT_NONE;
1121
1122        v4l2_subdev_init(sd, &isp_subdev_v4l2_ops);
1123        sprintf(sd->name, "ATOMISP_SUBDEV_%d", asd->index);
1124        v4l2_set_subdevdata(sd, asd);
1125        sd->flags |= V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_HAS_DEVNODE;
1126
1127        pads[ATOMISP_SUBDEV_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
1128        pads[ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW].flags = MEDIA_PAD_FL_SOURCE;
1129        pads[ATOMISP_SUBDEV_PAD_SOURCE_VF].flags = MEDIA_PAD_FL_SOURCE;
1130        pads[ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE].flags = MEDIA_PAD_FL_SOURCE;
1131        pads[ATOMISP_SUBDEV_PAD_SOURCE_VIDEO].flags = MEDIA_PAD_FL_SOURCE;
1132
1133        asd->fmt[ATOMISP_SUBDEV_PAD_SINK].fmt.code =
1134            MEDIA_BUS_FMT_SBGGR10_1X10;
1135        asd->fmt[ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW].fmt.code =
1136            MEDIA_BUS_FMT_SBGGR10_1X10;
1137        asd->fmt[ATOMISP_SUBDEV_PAD_SOURCE_VF].fmt.code =
1138            MEDIA_BUS_FMT_SBGGR10_1X10;
1139        asd->fmt[ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE].fmt.code =
1140            MEDIA_BUS_FMT_SBGGR10_1X10;
1141        asd->fmt[ATOMISP_SUBDEV_PAD_SOURCE_VIDEO].fmt.code =
1142            MEDIA_BUS_FMT_SBGGR10_1X10;
1143
1144        me->ops = &isp_subdev_media_ops;
1145        me->function = MEDIA_ENT_F_V4L2_SUBDEV_UNKNOWN;
1146        ret = media_entity_pads_init(me, ATOMISP_SUBDEV_PADS_NUM, pads);
1147        if (ret < 0)
1148                return ret;
1149
1150        atomisp_init_subdev_pipe(asd, &asd->video_in,
1151                                 V4L2_BUF_TYPE_VIDEO_OUTPUT);
1152
1153        atomisp_init_subdev_pipe(asd, &asd->video_out_preview,
1154                                 V4L2_BUF_TYPE_VIDEO_CAPTURE);
1155
1156        atomisp_init_subdev_pipe(asd, &asd->video_out_vf,
1157                                 V4L2_BUF_TYPE_VIDEO_CAPTURE);
1158
1159        atomisp_init_subdev_pipe(asd, &asd->video_out_capture,
1160                                 V4L2_BUF_TYPE_VIDEO_CAPTURE);
1161
1162        atomisp_init_subdev_pipe(asd, &asd->video_out_video_capture,
1163                                 V4L2_BUF_TYPE_VIDEO_CAPTURE);
1164
1165        atomisp_init_acc_pipe(asd, &asd->video_acc);
1166
1167        ret = atomisp_video_init(&asd->video_in, "MEMORY");
1168        if (ret < 0)
1169                return ret;
1170
1171        ret = atomisp_video_init(&asd->video_out_capture, "CAPTURE");
1172        if (ret < 0)
1173                return ret;
1174
1175        ret = atomisp_video_init(&asd->video_out_vf, "VIEWFINDER");
1176        if (ret < 0)
1177                return ret;
1178
1179        ret = atomisp_video_init(&asd->video_out_preview, "PREVIEW");
1180        if (ret < 0)
1181                return ret;
1182
1183        ret = atomisp_video_init(&asd->video_out_video_capture, "VIDEO");
1184        if (ret < 0)
1185                return ret;
1186
1187        atomisp_acc_init(&asd->video_acc, "ACC");
1188
1189        ret = v4l2_ctrl_handler_init(&asd->ctrl_handler, 1);
1190        if (ret)
1191                return ret;
1192
1193        asd->fmt_auto = v4l2_ctrl_new_custom(&asd->ctrl_handler,
1194                                             &ctrl_fmt_auto, NULL);
1195        asd->run_mode = v4l2_ctrl_new_custom(&asd->ctrl_handler,
1196                                             &ctrl_run_mode, NULL);
1197        asd->vfpp = v4l2_ctrl_new_custom(&asd->ctrl_handler,
1198                                         &ctrl_vfpp, NULL);
1199        asd->continuous_mode = v4l2_ctrl_new_custom(&asd->ctrl_handler,
1200                               &ctrl_continuous_mode, NULL);
1201        asd->continuous_viewfinder = v4l2_ctrl_new_custom(&asd->ctrl_handler,
1202                                     &ctrl_continuous_viewfinder,
1203                                     NULL);
1204        asd->continuous_raw_buffer_size =
1205            v4l2_ctrl_new_custom(&asd->ctrl_handler,
1206                                 &ctrl_continuous_raw_buffer_size,
1207                                 NULL);
1208
1209        asd->enable_raw_buffer_lock =
1210            v4l2_ctrl_new_custom(&asd->ctrl_handler,
1211                                 &ctrl_enable_raw_buffer_lock,
1212                                 NULL);
1213        asd->depth_mode =
1214            v4l2_ctrl_new_custom(&asd->ctrl_handler,
1215                                 &ctrl_depth_mode,
1216                                 NULL);
1217        asd->disable_dz =
1218            v4l2_ctrl_new_custom(&asd->ctrl_handler,
1219                                 &ctrl_disable_dz,
1220                                 NULL);
1221        if (IS_ISP2401) {
1222                asd->select_isp_version = v4l2_ctrl_new_custom(&asd->ctrl_handler,
1223                                                               &ctrl_select_isp_version,
1224                                                               NULL);
1225        }
1226
1227        /* Make controls visible on subdev as well. */
1228        asd->subdev.ctrl_handler = &asd->ctrl_handler;
1229        spin_lock_init(&asd->raw_buffer_bitmap_lock);
1230        return asd->ctrl_handler.error;
1231}
1232
1233int atomisp_create_pads_links(struct atomisp_device *isp)
1234{
1235        struct atomisp_sub_device *asd;
1236        int i, j, ret = 0;
1237
1238        isp->num_of_streams = 2;
1239        for (i = 0; i < ATOMISP_CAMERA_NR_PORTS; i++) {
1240                for (j = 0; j < isp->num_of_streams; j++) {
1241                        ret =
1242                            media_create_pad_link(&isp->csi2_port[i].subdev.
1243                                                  entity, CSI2_PAD_SOURCE,
1244                                                  &isp->asd[j].subdev.entity,
1245                                                  ATOMISP_SUBDEV_PAD_SINK, 0);
1246                        if (ret < 0)
1247                                return ret;
1248                }
1249        }
1250        for (i = 0; i < isp->input_cnt - 2; i++) {
1251                ret = media_create_pad_link(&isp->inputs[i].camera->entity, 0,
1252                                            &isp->csi2_port[isp->inputs[i].
1253                                                    port].subdev.entity,
1254                                            CSI2_PAD_SINK,
1255                                            MEDIA_LNK_FL_ENABLED |
1256                                            MEDIA_LNK_FL_IMMUTABLE);
1257                if (ret < 0)
1258                        return ret;
1259        }
1260        for (i = 0; i < isp->num_of_streams; i++) {
1261                asd = &isp->asd[i];
1262                ret = media_create_pad_link(&asd->subdev.entity,
1263                                            ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW,
1264                                            &asd->video_out_preview.vdev.entity,
1265                                            0, 0);
1266                if (ret < 0)
1267                        return ret;
1268                ret = media_create_pad_link(&asd->subdev.entity,
1269                                            ATOMISP_SUBDEV_PAD_SOURCE_VF,
1270                                            &asd->video_out_vf.vdev.entity, 0,
1271                                            0);
1272                if (ret < 0)
1273                        return ret;
1274                ret = media_create_pad_link(&asd->subdev.entity,
1275                                            ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE,
1276                                            &asd->video_out_capture.vdev.entity,
1277                                            0, 0);
1278                if (ret < 0)
1279                        return ret;
1280                ret = media_create_pad_link(&asd->subdev.entity,
1281                                            ATOMISP_SUBDEV_PAD_SOURCE_VIDEO,
1282                                            &asd->video_out_video_capture.vdev.
1283                                            entity, 0, 0);
1284                if (ret < 0)
1285                        return ret;
1286                /*
1287                 * file input only supported on subdev0
1288                 * so do not create pad link for subdevs other then subdev0
1289                 */
1290                if (asd->index)
1291                        return 0;
1292                ret = media_create_pad_link(&asd->video_in.vdev.entity,
1293                                            0, &asd->subdev.entity,
1294                                            ATOMISP_SUBDEV_PAD_SINK, 0);
1295                if (ret < 0)
1296                        return ret;
1297        }
1298        return 0;
1299}
1300
1301static void atomisp_subdev_cleanup_entities(struct atomisp_sub_device *asd)
1302{
1303        v4l2_ctrl_handler_free(&asd->ctrl_handler);
1304
1305        media_entity_cleanup(&asd->subdev.entity);
1306}
1307
1308void atomisp_subdev_cleanup_pending_events(struct atomisp_sub_device *asd)
1309{
1310        struct v4l2_fh *fh, *fh_tmp;
1311        struct v4l2_event event;
1312        unsigned int i, pending_event;
1313
1314        list_for_each_entry_safe(fh, fh_tmp,
1315                                 &asd->subdev.devnode->fh_list, list) {
1316                pending_event = v4l2_event_pending(fh);
1317                for (i = 0; i < pending_event; i++)
1318                        v4l2_event_dequeue(fh, &event, 1);
1319        }
1320}
1321
1322void atomisp_subdev_unregister_entities(struct atomisp_sub_device *asd)
1323{
1324        atomisp_subdev_cleanup_entities(asd);
1325        v4l2_device_unregister_subdev(&asd->subdev);
1326        atomisp_video_unregister(&asd->video_in);
1327        atomisp_video_unregister(&asd->video_out_preview);
1328        atomisp_video_unregister(&asd->video_out_vf);
1329        atomisp_video_unregister(&asd->video_out_capture);
1330        atomisp_video_unregister(&asd->video_out_video_capture);
1331        atomisp_acc_unregister(&asd->video_acc);
1332}
1333
1334int atomisp_subdev_register_entities(struct atomisp_sub_device *asd,
1335                                     struct v4l2_device *vdev)
1336{
1337        int ret;
1338        u32 device_caps;
1339
1340        /*
1341         * FIXME: check if all device caps are properly initialized.
1342         * Should any of those use V4L2_CAP_META_OUTPUT? Probably yes.
1343         */
1344
1345        device_caps = V4L2_CAP_VIDEO_CAPTURE |
1346                      V4L2_CAP_STREAMING;
1347
1348        /* Register the subdev and video node. */
1349
1350        ret = v4l2_device_register_subdev(vdev, &asd->subdev);
1351        if (ret < 0)
1352                goto error;
1353
1354        asd->video_out_capture.vdev.v4l2_dev = vdev;
1355        asd->video_out_capture.vdev.device_caps = device_caps |
1356                                                  V4L2_CAP_VIDEO_OUTPUT;
1357        ret = video_register_device(&asd->video_out_capture.vdev,
1358                                    VFL_TYPE_VIDEO, -1);
1359        if (ret < 0)
1360                goto error;
1361
1362        asd->video_out_vf.vdev.v4l2_dev = vdev;
1363        asd->video_out_vf.vdev.device_caps = device_caps |
1364                                             V4L2_CAP_VIDEO_OUTPUT;
1365        ret = video_register_device(&asd->video_out_vf.vdev,
1366                                    VFL_TYPE_VIDEO, -1);
1367        if (ret < 0)
1368                goto error;
1369        asd->video_out_preview.vdev.v4l2_dev = vdev;
1370        asd->video_out_preview.vdev.device_caps = device_caps |
1371                                                  V4L2_CAP_VIDEO_OUTPUT;
1372        ret = video_register_device(&asd->video_out_preview.vdev,
1373                                    VFL_TYPE_VIDEO, -1);
1374        if (ret < 0)
1375                goto error;
1376        asd->video_out_video_capture.vdev.v4l2_dev = vdev;
1377        asd->video_out_video_capture.vdev.device_caps = device_caps |
1378                                                        V4L2_CAP_VIDEO_OUTPUT;
1379        ret = video_register_device(&asd->video_out_video_capture.vdev,
1380                                    VFL_TYPE_VIDEO, -1);
1381        if (ret < 0)
1382                goto error;
1383        asd->video_acc.vdev.v4l2_dev = vdev;
1384        asd->video_acc.vdev.device_caps = device_caps |
1385                                          V4L2_CAP_VIDEO_OUTPUT;
1386        ret = video_register_device(&asd->video_acc.vdev,
1387                                    VFL_TYPE_VIDEO, -1);
1388        if (ret < 0)
1389                goto error;
1390
1391        /*
1392         * file input only supported on subdev0
1393         * so do not create video node for subdevs other then subdev0
1394         */
1395        if (asd->index)
1396                return 0;
1397
1398        asd->video_in.vdev.v4l2_dev = vdev;
1399        asd->video_in.vdev.device_caps = device_caps |
1400                                          V4L2_CAP_VIDEO_CAPTURE;
1401        ret = video_register_device(&asd->video_in.vdev,
1402                                    VFL_TYPE_VIDEO, -1);
1403        if (ret < 0)
1404                goto error;
1405
1406        return 0;
1407
1408error:
1409        atomisp_subdev_unregister_entities(asd);
1410        return ret;
1411}
1412
1413/*
1414 * atomisp_subdev_init - ISP Subdevice  initialization.
1415 * @dev: Device pointer specific to the ATOM ISP.
1416 *
1417 * TODO: Get the initialisation values from platform data.
1418 *
1419 * Return 0 on success or a negative error code otherwise.
1420 */
1421int atomisp_subdev_init(struct atomisp_device *isp)
1422{
1423        struct atomisp_sub_device *asd;
1424        int i, ret = 0;
1425
1426        /*
1427         * CSS2.0 running ISP2400 support
1428         * multiple streams
1429         */
1430        isp->num_of_streams = 2;
1431        isp->asd = devm_kzalloc(isp->dev, sizeof(struct atomisp_sub_device) *
1432                                isp->num_of_streams, GFP_KERNEL);
1433        if (!isp->asd)
1434                return -ENOMEM;
1435        for (i = 0; i < isp->num_of_streams; i++) {
1436                asd = &isp->asd[i];
1437                spin_lock_init(&asd->lock);
1438                asd->isp = isp;
1439                isp_subdev_init_params(asd);
1440                asd->index = i;
1441                ret = isp_subdev_init_entities(asd);
1442                if (ret < 0) {
1443                        atomisp_subdev_cleanup_entities(asd);
1444                        break;
1445                }
1446        }
1447
1448        return ret;
1449}
1450