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