aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/media/atomisp/pci/atomisp2/atomisp_subdev.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/media/atomisp/pci/atomisp2/atomisp_subdev.c')
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp2/atomisp_subdev.c1422
1 files changed, 0 insertions, 1422 deletions
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/atomisp_subdev.c b/drivers/staging/media/atomisp/pci/atomisp2/atomisp_subdev.c
deleted file mode 100644
index 49a9973b4289..000000000000
--- a/drivers/staging/media/atomisp/pci/atomisp2/atomisp_subdev.c
+++ /dev/null
@@ -1,1422 +0,0 @@
-/*
- * Support for Medifield PNW Camera Imaging ISP subsystem.
- *
- * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License version
- * 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- *
- */
-#include <linux/module.h>
-#include <linux/uaccess.h>
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/mm.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-
-#include <media/v4l2-event.h>
-#include <media/v4l2-mediabus.h>
-#include "atomisp_cmd.h"
-#include "atomisp_common.h"
-#include "atomisp_compat.h"
-#include "atomisp_internal.h"
-
-const struct atomisp_in_fmt_conv atomisp_in_fmt_conv[] = {
- { MEDIA_BUS_FMT_SBGGR8_1X8, 8, 8, ATOMISP_INPUT_FORMAT_RAW_8, CSS_BAYER_ORDER_BGGR, CSS_FORMAT_RAW_8 },
- { MEDIA_BUS_FMT_SGBRG8_1X8, 8, 8, ATOMISP_INPUT_FORMAT_RAW_8, CSS_BAYER_ORDER_GBRG, CSS_FORMAT_RAW_8 },
- { MEDIA_BUS_FMT_SGRBG8_1X8, 8, 8, ATOMISP_INPUT_FORMAT_RAW_8, CSS_BAYER_ORDER_GRBG, CSS_FORMAT_RAW_8 },
- { MEDIA_BUS_FMT_SRGGB8_1X8, 8, 8, ATOMISP_INPUT_FORMAT_RAW_8, CSS_BAYER_ORDER_RGGB, CSS_FORMAT_RAW_8 },
- { MEDIA_BUS_FMT_SBGGR10_1X10, 10, 10, ATOMISP_INPUT_FORMAT_RAW_10, CSS_BAYER_ORDER_BGGR, CSS_FORMAT_RAW_10 },
- { MEDIA_BUS_FMT_SGBRG10_1X10, 10, 10, ATOMISP_INPUT_FORMAT_RAW_10, CSS_BAYER_ORDER_GBRG, CSS_FORMAT_RAW_10 },
- { MEDIA_BUS_FMT_SGRBG10_1X10, 10, 10, ATOMISP_INPUT_FORMAT_RAW_10, CSS_BAYER_ORDER_GRBG, CSS_FORMAT_RAW_10 },
- { MEDIA_BUS_FMT_SRGGB10_1X10, 10, 10, ATOMISP_INPUT_FORMAT_RAW_10, CSS_BAYER_ORDER_RGGB, CSS_FORMAT_RAW_10 },
- { MEDIA_BUS_FMT_SBGGR12_1X12, 12, 12, ATOMISP_INPUT_FORMAT_RAW_12, CSS_BAYER_ORDER_BGGR, CSS_FORMAT_RAW_12 },
- { MEDIA_BUS_FMT_SGBRG12_1X12, 12, 12, ATOMISP_INPUT_FORMAT_RAW_12, CSS_BAYER_ORDER_GBRG, CSS_FORMAT_RAW_12 },
- { MEDIA_BUS_FMT_SGRBG12_1X12, 12, 12, ATOMISP_INPUT_FORMAT_RAW_12, CSS_BAYER_ORDER_GRBG, CSS_FORMAT_RAW_12 },
- { MEDIA_BUS_FMT_SRGGB12_1X12, 12, 12, ATOMISP_INPUT_FORMAT_RAW_12, CSS_BAYER_ORDER_RGGB, CSS_FORMAT_RAW_12 },
- { MEDIA_BUS_FMT_UYVY8_1X16, 8, 8, ATOMISP_INPUT_FORMAT_YUV422_8, 0, ATOMISP_INPUT_FORMAT_YUV422_8 },
- { MEDIA_BUS_FMT_YUYV8_1X16, 8, 8, ATOMISP_INPUT_FORMAT_YUV422_8, 0, ATOMISP_INPUT_FORMAT_YUV422_8 },
- { MEDIA_BUS_FMT_JPEG_1X8, 8, 8, CSS_FRAME_FORMAT_BINARY_8, 0, ATOMISP_INPUT_FORMAT_BINARY_8 },
- { V4L2_MBUS_FMT_CUSTOM_NV12, 12, 12, CSS_FRAME_FORMAT_NV12, 0, CSS_FRAME_FORMAT_NV12 },
- { V4L2_MBUS_FMT_CUSTOM_NV21, 12, 12, CSS_FRAME_FORMAT_NV21, 0, CSS_FRAME_FORMAT_NV21 },
- { V4L2_MBUS_FMT_CUSTOM_YUV420, 12, 12, ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY, 0, ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY },
-#if 0
- { V4L2_MBUS_FMT_CUSTOM_M10MO_RAW, 8, 8, CSS_FRAME_FORMAT_BINARY_8, 0, ATOMISP_INPUT_FORMAT_BINARY_8 },
-#endif
- /* no valid V4L2 MBUS code for metadata format, so leave it 0. */
- { 0, 0, 0, ATOMISP_INPUT_FORMAT_EMBEDDED, 0, ATOMISP_INPUT_FORMAT_EMBEDDED },
- {}
-};
-
-static const struct {
- u32 code;
- u32 compressed;
-} compressed_codes[] = {
- { MEDIA_BUS_FMT_SBGGR10_1X10, MEDIA_BUS_FMT_SBGGR10_DPCM8_1X8 },
- { MEDIA_BUS_FMT_SGBRG10_1X10, MEDIA_BUS_FMT_SGBRG10_DPCM8_1X8 },
- { MEDIA_BUS_FMT_SGRBG10_1X10, MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8 },
- { MEDIA_BUS_FMT_SRGGB10_1X10, MEDIA_BUS_FMT_SRGGB10_DPCM8_1X8 },
-};
-
-u32 atomisp_subdev_uncompressed_code(u32 code)
-{
- unsigned int i;
-
- for (i = 0; i < ARRAY_SIZE(compressed_codes); i++)
- if (code == compressed_codes[i].compressed)
- return compressed_codes[i].code;
-
- return code;
-}
-
-bool atomisp_subdev_is_compressed(u32 code)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(atomisp_in_fmt_conv) - 1; i++)
- if (code == atomisp_in_fmt_conv[i].code)
- return atomisp_in_fmt_conv[i].bpp !=
- atomisp_in_fmt_conv[i].depth;
-
- return false;
-}
-
-const struct atomisp_in_fmt_conv *atomisp_find_in_fmt_conv(u32 code)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(atomisp_in_fmt_conv) - 1; i++)
- if (code == atomisp_in_fmt_conv[i].code)
- return atomisp_in_fmt_conv + i;
-
- return NULL;
-}
-
-const struct atomisp_in_fmt_conv *atomisp_find_in_fmt_conv_by_atomisp_in_fmt(
- enum atomisp_input_format atomisp_in_fmt)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(atomisp_in_fmt_conv) - 1; i++)
- if (atomisp_in_fmt_conv[i].atomisp_in_fmt == atomisp_in_fmt)
- return atomisp_in_fmt_conv + i;
-
- return NULL;
-}
-
-bool atomisp_subdev_format_conversion(struct atomisp_sub_device *asd,
- unsigned int source_pad)
-{
- struct v4l2_mbus_framefmt *sink, *src;
-
- sink = atomisp_subdev_get_ffmt(&asd->subdev, NULL,
- V4L2_SUBDEV_FORMAT_ACTIVE,
- ATOMISP_SUBDEV_PAD_SINK);
- src = atomisp_subdev_get_ffmt(&asd->subdev, NULL,
- V4L2_SUBDEV_FORMAT_ACTIVE, source_pad);
-
- return atomisp_is_mbuscode_raw(sink->code)
- && !atomisp_is_mbuscode_raw(src->code);
-}
-
-uint16_t atomisp_subdev_source_pad(struct video_device * vdev)
-{
- struct media_link *link;
- uint16_t ret = 0;
- list_for_each_entry(link, &vdev->entity.links, list) {
- if (link->source) {
- ret = link->source->index;
- break;
- }
- }
- return ret;
-}
-
-/*
- * V4L2 subdev operations
- */
-
-/*
- * isp_subdev_ioctl - CCDC module private ioctl's
- * @sd: ISP V4L2 subdevice
- * @cmd: ioctl command
- * @arg: ioctl argument
- *
- * Return 0 on success or a negative error code otherwise.
- */
-static long isp_subdev_ioctl(struct v4l2_subdev *sd,
- unsigned int cmd, void *arg)
-{
- return 0;
-}
-
-/*
- * isp_subdev_set_power - Power on/off the CCDC module
- * @sd: ISP V4L2 subdevice
- * @on: power on/off
- *
- * Return 0 on success or a negative error code otherwise.
- */
-static int isp_subdev_set_power(struct v4l2_subdev *sd, int on)
-{
- return 0;
-}
-
-static int isp_subdev_subscribe_event(struct v4l2_subdev *sd,
- struct v4l2_fh *fh,
- struct v4l2_event_subscription *sub)
-{
- struct atomisp_sub_device *isp_sd = v4l2_get_subdevdata(sd);
- struct atomisp_device *isp = isp_sd->isp;
-
- if (sub->type != V4L2_EVENT_FRAME_SYNC &&
- sub->type != V4L2_EVENT_FRAME_END &&
- sub->type != V4L2_EVENT_ATOMISP_3A_STATS_READY &&
- sub->type != V4L2_EVENT_ATOMISP_METADATA_READY &&
- sub->type != V4L2_EVENT_ATOMISP_PAUSE_BUFFER &&
- sub->type != V4L2_EVENT_ATOMISP_CSS_RESET &&
- sub->type != V4L2_EVENT_ATOMISP_RAW_BUFFERS_ALLOC_DONE &&
- sub->type != V4L2_EVENT_ATOMISP_ACC_COMPLETE)
- return -EINVAL;
-
- if (sub->type == V4L2_EVENT_FRAME_SYNC &&
- !atomisp_css_valid_sof(isp))
- return -EINVAL;
-
- return v4l2_event_subscribe(fh, sub, 16, NULL);
-}
-
-static int isp_subdev_unsubscribe_event(struct v4l2_subdev *sd,
- struct v4l2_fh *fh,
- struct v4l2_event_subscription *sub)
-{
- return v4l2_event_unsubscribe(fh, sub);
-}
-
-/*
- * isp_subdev_enum_mbus_code - Handle pixel format enumeration
- * @sd: pointer to v4l2 subdev structure
- * @fh : V4L2 subdev file handle
- * @code: pointer to v4l2_subdev_pad_mbus_code_enum structure
- * return -EINVAL or zero on success
- */
-static int isp_subdev_enum_mbus_code(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
- struct v4l2_subdev_mbus_code_enum *code)
-{
- if (code->index >= ARRAY_SIZE(atomisp_in_fmt_conv) - 1)
- return -EINVAL;
-
- code->code = atomisp_in_fmt_conv[code->index].code;
-
- return 0;
-}
-
-static int isp_subdev_validate_rect(struct v4l2_subdev *sd, uint32_t pad,
- uint32_t target)
-{
- switch (pad) {
- case ATOMISP_SUBDEV_PAD_SINK:
- switch (target) {
- case V4L2_SEL_TGT_CROP:
- return 0;
- }
- break;
- default:
- switch (target) {
- case V4L2_SEL_TGT_COMPOSE:
- return 0;
- }
- break;
- }
-
- return -EINVAL;
-}
-
-struct v4l2_rect *atomisp_subdev_get_rect(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
- uint32_t which, uint32_t pad,
- uint32_t target)
-{
- struct atomisp_sub_device *isp_sd = v4l2_get_subdevdata(sd);
-
- if (which == V4L2_SUBDEV_FORMAT_TRY) {
- switch (target) {
- case V4L2_SEL_TGT_CROP:
- return v4l2_subdev_get_try_crop(sd, cfg, pad);
- case V4L2_SEL_TGT_COMPOSE:
- return v4l2_subdev_get_try_compose(sd, cfg, pad);
- }
- }
-
- switch (target) {
- case V4L2_SEL_TGT_CROP:
- return &isp_sd->fmt[pad].crop;
- case V4L2_SEL_TGT_COMPOSE:
- return &isp_sd->fmt[pad].compose;
- }
-
- return NULL;
-}
-
-struct v4l2_mbus_framefmt
-*atomisp_subdev_get_ffmt(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg, uint32_t which,
- uint32_t pad)
-{
- struct atomisp_sub_device *isp_sd = v4l2_get_subdevdata(sd);
-
- if (which == V4L2_SUBDEV_FORMAT_TRY)
- return v4l2_subdev_get_try_format(sd, cfg, pad);
-
- return &isp_sd->fmt[pad].fmt;
-}
-
-static void isp_get_fmt_rect(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg, uint32_t which,
- struct v4l2_mbus_framefmt **ffmt,
- struct v4l2_rect *crop[ATOMISP_SUBDEV_PADS_NUM],
- struct v4l2_rect *comp[ATOMISP_SUBDEV_PADS_NUM])
-{
- unsigned int i;
-
- for (i = 0; i < ATOMISP_SUBDEV_PADS_NUM; i++) {
- ffmt[i] = atomisp_subdev_get_ffmt(sd, cfg, which, i);
- crop[i] = atomisp_subdev_get_rect(sd, cfg, which, i,
- V4L2_SEL_TGT_CROP);
- comp[i] = atomisp_subdev_get_rect(sd, cfg, which, i,
- V4L2_SEL_TGT_COMPOSE);
- }
-}
-
-static void isp_subdev_propagate(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
- uint32_t which, uint32_t pad, uint32_t target,
- uint32_t flags)
-{
- struct v4l2_mbus_framefmt *ffmt[ATOMISP_SUBDEV_PADS_NUM];
- struct v4l2_rect *crop[ATOMISP_SUBDEV_PADS_NUM],
- *comp[ATOMISP_SUBDEV_PADS_NUM];
-
- if (flags & V4L2_SEL_FLAG_KEEP_CONFIG)
- return;
-
- isp_get_fmt_rect(sd, cfg, which, ffmt, crop, comp);
-
- switch (pad) {
- case ATOMISP_SUBDEV_PAD_SINK: {
- struct v4l2_rect r = {0};
-
- /* Only crop target supported on sink pad. */
- r.width = ffmt[pad]->width;
- r.height = ffmt[pad]->height;
-
- atomisp_subdev_set_selection(sd, cfg, which, pad,
- target, flags, &r);
- break;
- }
- }
-}
-
-static int isp_subdev_get_selection(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
- struct v4l2_subdev_selection *sel)
-{
- struct v4l2_rect *rec;
- int rval = isp_subdev_validate_rect(sd, sel->pad, sel->target);
-
- if (rval)
- return rval;
-
- rec = atomisp_subdev_get_rect(sd, cfg, sel->which, sel->pad,
- sel->target);
- if (!rec)
- return -EINVAL;
-
- sel->r = *rec;
- return 0;
-}
-
-static char *atomisp_pad_str[] = { "ATOMISP_SUBDEV_PAD_SINK",
- "ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE",
- "ATOMISP_SUBDEV_PAD_SOURCE_VF",
- "ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW",
- "ATOMISP_SUBDEV_PAD_SOURCE_VIDEO"};
-
-int atomisp_subdev_set_selection(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
- uint32_t which, uint32_t pad, uint32_t target,
- uint32_t flags, struct v4l2_rect *r)
-{
- struct atomisp_sub_device *isp_sd = v4l2_get_subdevdata(sd);
- struct atomisp_device *isp = isp_sd->isp;
- struct v4l2_mbus_framefmt *ffmt[ATOMISP_SUBDEV_PADS_NUM];
- uint16_t vdev_pad = atomisp_subdev_source_pad(sd->devnode);
- struct v4l2_rect *crop[ATOMISP_SUBDEV_PADS_NUM],
- *comp[ATOMISP_SUBDEV_PADS_NUM];
- enum atomisp_input_stream_id stream_id;
- unsigned int i;
- unsigned int padding_w = pad_w;
- unsigned int padding_h = pad_h;
-
- stream_id = atomisp_source_pad_to_stream_id(isp_sd, vdev_pad);
-
- isp_get_fmt_rect(sd, cfg, which, ffmt, crop, comp);
-
- dev_dbg(isp->dev,
- "sel: pad %s tgt %s l %d t %d w %d h %d which %s f 0x%8.8x\n",
- atomisp_pad_str[pad], target == V4L2_SEL_TGT_CROP
- ? "V4L2_SEL_TGT_CROP" : "V4L2_SEL_TGT_COMPOSE",
- r->left, r->top, r->width, r->height,
- which == V4L2_SUBDEV_FORMAT_TRY ? "V4L2_SUBDEV_FORMAT_TRY"
- : "V4L2_SUBDEV_FORMAT_ACTIVE", flags);
-
- r->width = rounddown(r->width, ATOM_ISP_STEP_WIDTH);
- r->height = rounddown(r->height, ATOM_ISP_STEP_HEIGHT);
-
- switch (pad) {
- case ATOMISP_SUBDEV_PAD_SINK: {
- /* Only crop target supported on sink pad. */
- unsigned int dvs_w, dvs_h;
-
- crop[pad]->width = ffmt[pad]->width;
- crop[pad]->height = ffmt[pad]->height;
-
- /* Workaround for BYT 1080p perfectshot since the maxinum resolution of
- * front camera ov2722 is 1932x1092 and cannot use pad_w > 12*/
- if (!strncmp(isp->inputs[isp_sd->input_curr].camera->name,
- "ov2722", 6) && crop[pad]->height == 1092) {
- padding_w = 12;
- padding_h = 12;
- }
-
- if (isp->inputs[isp_sd->input_curr].type == SOC_CAMERA) {
- padding_w = 0;
- padding_h = 0;
- }
-
- if (atomisp_subdev_format_conversion(isp_sd,
- isp_sd->capture_pad)
- && crop[pad]->width && crop[pad]->height)
- crop[pad]->width -= padding_w, crop[pad]->height -= padding_h;
-
- /* if subdev type is SOC camera,we do not need to set DVS */
- if (isp->inputs[isp_sd->input_curr].type == SOC_CAMERA)
- isp_sd->params.video_dis_en = 0;
-
- if (isp_sd->params.video_dis_en &&
- isp_sd->run_mode->val == ATOMISP_RUN_MODE_VIDEO &&
- !isp_sd->continuous_mode->val) {
- /* This resolution contains 20 % of DVS slack
- * (of the desired captured image before
- * scaling, or 1 / 6 of what we get from the
- * sensor) in both width and height. Remove
- * it. */
- crop[pad]->width = roundup(crop[pad]->width * 5 / 6,
- ATOM_ISP_STEP_WIDTH);
- crop[pad]->height = roundup(crop[pad]->height * 5 / 6,
- ATOM_ISP_STEP_HEIGHT);
- }
-
- crop[pad]->width = min(crop[pad]->width, r->width);
- crop[pad]->height = min(crop[pad]->height, r->height);
-
- if (!(flags & V4L2_SEL_FLAG_KEEP_CONFIG)) {
- for (i = ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE;
- i < ATOMISP_SUBDEV_PADS_NUM; i++) {
- struct v4l2_rect tmp = *crop[pad];
-
- atomisp_subdev_set_selection(
- sd, cfg, which, i, V4L2_SEL_TGT_COMPOSE,
- flags, &tmp);
- }
- }
-
- if (which == V4L2_SUBDEV_FORMAT_TRY)
- break;
-
- if (isp_sd->params.video_dis_en &&
- isp_sd->run_mode->val == ATOMISP_RUN_MODE_VIDEO &&
- !isp_sd->continuous_mode->val) {
- dvs_w = rounddown(crop[pad]->width / 5,
- ATOM_ISP_STEP_WIDTH);
- dvs_h = rounddown(crop[pad]->height / 5,
- ATOM_ISP_STEP_HEIGHT);
- } else if (!isp_sd->params.video_dis_en &&
- isp_sd->run_mode->val == ATOMISP_RUN_MODE_VIDEO) {
- /*
- * For CSS2.0, digital zoom needs to set dvs envelope to 12
- * when dvs is disabled.
- */
- dvs_w = dvs_h = 12;
- } else
- dvs_w = dvs_h = 0;
-
- atomisp_css_video_set_dis_envelope(isp_sd, dvs_w, dvs_h);
- atomisp_css_input_set_effective_resolution(isp_sd, stream_id,
- crop[pad]->width, crop[pad]->height);
-
- break;
- }
- case ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE:
- case ATOMISP_SUBDEV_PAD_SOURCE_VIDEO: {
- /* Only compose target is supported on source pads. */
-
- if (isp_sd->vfpp->val == ATOMISP_VFPP_DISABLE_LOWLAT) {
- /* Scaling is disabled in this mode */
- r->width = crop[ATOMISP_SUBDEV_PAD_SINK]->width;
- r->height = crop[ATOMISP_SUBDEV_PAD_SINK]->height;
- }
-
- if (crop[ATOMISP_SUBDEV_PAD_SINK]->width == r->width
- && crop[ATOMISP_SUBDEV_PAD_SINK]->height == r->height)
- isp_sd->params.yuv_ds_en = false;
- else
- isp_sd->params.yuv_ds_en = true;
-
- comp[pad]->width = r->width;
- comp[pad]->height = r->height;
-
- if (r->width == 0 || r->height == 0 ||
- crop[ATOMISP_SUBDEV_PAD_SINK]->width == 0 ||
- crop[ATOMISP_SUBDEV_PAD_SINK]->height == 0)
- break;
- /*
- * do cropping on sensor input if ratio of required resolution
- * is different with sensor output resolution ratio:
- *
- * ratio = width / height
- *
- * if ratio_output < ratio_sensor:
- * effect_width = sensor_height * out_width / out_height;
- * effect_height = sensor_height;
- * else
- * effect_width = sensor_width;
- * effect_height = sensor_width * out_height / out_width;
- *
- */
- if (r->width * crop[ATOMISP_SUBDEV_PAD_SINK]->height <
- crop[ATOMISP_SUBDEV_PAD_SINK]->width * r->height)
- atomisp_css_input_set_effective_resolution(isp_sd,
- stream_id,
- rounddown(crop[ATOMISP_SUBDEV_PAD_SINK]->
- height * r->width / r->height,
- ATOM_ISP_STEP_WIDTH),
- crop[ATOMISP_SUBDEV_PAD_SINK]->height);
- else
- atomisp_css_input_set_effective_resolution(isp_sd,
- stream_id,
- crop[ATOMISP_SUBDEV_PAD_SINK]->width,
- rounddown(crop[ATOMISP_SUBDEV_PAD_SINK]->
- width * r->height / r->width,
- ATOM_ISP_STEP_WIDTH));
-
- break;
- }
- case ATOMISP_SUBDEV_PAD_SOURCE_VF:
- case ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW:
- comp[pad]->width = r->width;
- comp[pad]->height = r->height;
- break;
- default:
- return -EINVAL;
- }
-
- /* Set format dimensions on non-sink pads as well. */
- if (pad != ATOMISP_SUBDEV_PAD_SINK) {
- ffmt[pad]->width = comp[pad]->width;
- ffmt[pad]->height = comp[pad]->height;
- }
-
- if (!atomisp_subdev_get_rect(sd, cfg, which, pad, target))
- return -EINVAL;
- *r = *atomisp_subdev_get_rect(sd, cfg, which, pad, target);
-
- dev_dbg(isp->dev, "sel actual: l %d t %d w %d h %d\n",
- r->left, r->top, r->width, r->height);
-
- return 0;
-}
-
-static int isp_subdev_set_selection(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
- struct v4l2_subdev_selection *sel)
-{
- int rval = isp_subdev_validate_rect(sd, sel->pad, sel->target);
- if (rval)
- return rval;
-
- return atomisp_subdev_set_selection(sd, cfg, sel->which, sel->pad,
- sel->target, sel->flags, &sel->r);
-}
-
-static int atomisp_get_sensor_bin_factor(struct atomisp_sub_device *asd)
-{
- struct v4l2_control ctrl = {0};
- struct atomisp_device *isp = asd->isp;
- int hbin, vbin;
- int ret;
-
- if (isp->inputs[asd->input_curr].type == FILE_INPUT ||
- isp->inputs[asd->input_curr].type == TEST_PATTERN)
- return 0;
-
- ctrl.id = V4L2_CID_BIN_FACTOR_HORZ;
- ret =
- v4l2_g_ctrl(isp->inputs[asd->input_curr].camera->ctrl_handler,
- &ctrl);
- hbin = ctrl.value;
- ctrl.id = V4L2_CID_BIN_FACTOR_VERT;
- ret |=
- v4l2_g_ctrl(isp->inputs[asd->input_curr].camera->ctrl_handler,
- &ctrl);
- vbin = ctrl.value;
-
- /*
- * ISP needs to know binning factor from sensor.
- * In case horizontal and vertical sensor's binning factors
- * are different or sensor does not support binning factor CID,
- * ISP will apply default 0 value.
- */
- if (ret || hbin != vbin)
- hbin = 0;
-
- return hbin;
-}
-
-void atomisp_subdev_set_ffmt(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg, uint32_t which,
- uint32_t pad, struct v4l2_mbus_framefmt *ffmt)
-{
- struct atomisp_sub_device *isp_sd = v4l2_get_subdevdata(sd);
- struct atomisp_device *isp = isp_sd->isp;
- struct v4l2_mbus_framefmt *__ffmt =
- atomisp_subdev_get_ffmt(sd, cfg, which, pad);
- uint16_t vdev_pad = atomisp_subdev_source_pad(sd->devnode);
- enum atomisp_input_stream_id stream_id;
-
- dev_dbg(isp->dev, "ffmt: pad %s w %d h %d code 0x%8.8x which %s\n",
- atomisp_pad_str[pad], ffmt->width, ffmt->height, ffmt->code,
- which == V4L2_SUBDEV_FORMAT_TRY ? "V4L2_SUBDEV_FORMAT_TRY"
- : "V4L2_SUBDEV_FORMAT_ACTIVE");
-
- stream_id = atomisp_source_pad_to_stream_id(isp_sd, vdev_pad);
-
- switch (pad) {
- case ATOMISP_SUBDEV_PAD_SINK: {
- const struct atomisp_in_fmt_conv *fc =
- atomisp_find_in_fmt_conv(ffmt->code);
-
- if (!fc) {
- fc = atomisp_in_fmt_conv;
- ffmt->code = fc->code;
- dev_dbg(isp->dev, "using 0x%8.8x instead\n",
- ffmt->code);
- }
-
- *__ffmt = *ffmt;
-
- isp_subdev_propagate(sd, cfg, which, pad,
- V4L2_SEL_TGT_CROP, 0);
-
- if (which == V4L2_SUBDEV_FORMAT_ACTIVE) {
- atomisp_css_input_set_resolution(isp_sd,
- stream_id, ffmt);
- atomisp_css_input_set_binning_factor(isp_sd,
- stream_id,
- atomisp_get_sensor_bin_factor(isp_sd));
- atomisp_css_input_set_bayer_order(isp_sd, stream_id,
- fc->bayer_order);
- atomisp_css_input_set_format(isp_sd, stream_id,
- fc->css_stream_fmt);
- atomisp_css_set_default_isys_config(isp_sd, stream_id,
- ffmt);
- }
-
- break;
- }
- case ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE:
- case ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW:
- case ATOMISP_SUBDEV_PAD_SOURCE_VF:
- case ATOMISP_SUBDEV_PAD_SOURCE_VIDEO:
- __ffmt->code = ffmt->code;
- break;
- }
-}
-
-/*
- * isp_subdev_get_format - Retrieve the video format on a pad
- * @sd : ISP V4L2 subdevice
- * @fh : V4L2 subdev file handle
- * @pad: Pad number
- * @fmt: Format
- *
- * Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond
- * to the format type.
- */
-static int isp_subdev_get_format(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
- struct v4l2_subdev_format *fmt)
-{
- fmt->format = *atomisp_subdev_get_ffmt(sd, cfg, fmt->which, fmt->pad);
-
- return 0;
-}
-
-/*
- * isp_subdev_set_format - Set the video format on a pad
- * @sd : ISP subdev V4L2 subdevice
- * @fh : V4L2 subdev file handle
- * @pad: Pad number
- * @fmt: Format
- *
- * Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond
- * to the format type.
- */
-static int isp_subdev_set_format(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
- struct v4l2_subdev_format *fmt)
-{
- atomisp_subdev_set_ffmt(sd, cfg, fmt->which, fmt->pad, &fmt->format);
-
- return 0;
-}
-
-/* V4L2 subdev core operations */
-static const struct v4l2_subdev_core_ops isp_subdev_v4l2_core_ops = {
- .ioctl = isp_subdev_ioctl, .s_power = isp_subdev_set_power,
- .subscribe_event = isp_subdev_subscribe_event,
- .unsubscribe_event = isp_subdev_unsubscribe_event,
-};
-
-/* V4L2 subdev pad operations */
-static const struct v4l2_subdev_pad_ops isp_subdev_v4l2_pad_ops = {
- .enum_mbus_code = isp_subdev_enum_mbus_code,
- .get_fmt = isp_subdev_get_format,
- .set_fmt = isp_subdev_set_format,
- .get_selection = isp_subdev_get_selection,
- .set_selection = isp_subdev_set_selection,
- .link_validate = v4l2_subdev_link_validate_default,
-};
-
-/* V4L2 subdev operations */
-static const struct v4l2_subdev_ops isp_subdev_v4l2_ops = {
- .core = &isp_subdev_v4l2_core_ops,
- .pad = &isp_subdev_v4l2_pad_ops,
-};
-
-static void isp_subdev_init_params(struct atomisp_sub_device *asd)
-{
- unsigned int i;
-
- /* parameters initialization */
- INIT_LIST_HEAD(&asd->s3a_stats);
- INIT_LIST_HEAD(&asd->s3a_stats_in_css);
- INIT_LIST_HEAD(&asd->s3a_stats_ready);
- INIT_LIST_HEAD(&asd->dis_stats);
- INIT_LIST_HEAD(&asd->dis_stats_in_css);
- spin_lock_init(&asd->dis_stats_lock);
- for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) {
- INIT_LIST_HEAD(&asd->metadata[i]);
- INIT_LIST_HEAD(&asd->metadata_in_css[i]);
- INIT_LIST_HEAD(&asd->metadata_ready[i]);
- }
-}
-
-/*
-* isp_subdev_link_setup - Setup isp subdev connections
-* @entity: ispsubdev media entity
-* @local: Pad at the local end of the link
-* @remote: Pad at the remote end of the link
-* @flags: Link flags
-*
-* return -EINVAL or zero on success
-*/
-static int isp_subdev_link_setup(struct media_entity *entity,
- const struct media_pad *local,
- const struct media_pad *remote, u32 flags)
-{
- struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
- struct atomisp_sub_device *isp_sd = v4l2_get_subdevdata(sd);
- struct atomisp_device *isp = isp_sd->isp;
- unsigned int i;
-
- switch (local->index | is_media_entity_v4l2_subdev(remote->entity)) {
- case ATOMISP_SUBDEV_PAD_SINK | MEDIA_ENT_F_V4L2_SUBDEV_UNKNOWN:
- /* Read from the sensor CSI2-ports. */
- if (!(flags & MEDIA_LNK_FL_ENABLED)) {
- isp_sd->input = ATOMISP_SUBDEV_INPUT_NONE;
- break;
- }
-
- if (isp_sd->input != ATOMISP_SUBDEV_INPUT_NONE)
- return -EBUSY;
-
- for (i = 0; i < ATOMISP_CAMERA_NR_PORTS; i++) {
- if (remote->entity != &isp->csi2_port[i].subdev.entity)
- continue;
-
- isp_sd->input = ATOMISP_SUBDEV_INPUT_CSI2_PORT1 + i;
- return 0;
- }
-
- return -EINVAL;
-
- case ATOMISP_SUBDEV_PAD_SINK | MEDIA_ENT_F_OLD_BASE:
- /* read from memory */
- if (flags & MEDIA_LNK_FL_ENABLED) {
- if (isp_sd->input >= ATOMISP_SUBDEV_INPUT_CSI2_PORT1 &&
- isp_sd->input < (ATOMISP_SUBDEV_INPUT_CSI2_PORT1
- + ATOMISP_CAMERA_NR_PORTS))
- return -EBUSY;
- isp_sd->input = ATOMISP_SUBDEV_INPUT_MEMORY;
- } else {
- if (isp_sd->input == ATOMISP_SUBDEV_INPUT_MEMORY)
- isp_sd->input = ATOMISP_SUBDEV_INPUT_NONE;
- }
- break;
-
- case ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW | MEDIA_ENT_F_OLD_BASE:
- /* always write to memory */
- break;
-
- case ATOMISP_SUBDEV_PAD_SOURCE_VF | MEDIA_ENT_F_OLD_BASE:
- /* always write to memory */
- break;
-
- case ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE | MEDIA_ENT_F_OLD_BASE:
- /* always write to memory */
- break;
-
- case ATOMISP_SUBDEV_PAD_SOURCE_VIDEO | MEDIA_ENT_F_OLD_BASE:
- /* always write to memory */
- break;
-
- default:
- return -EINVAL;
- }
-
- return 0;
-}
-
-/* media operations */
-static const struct media_entity_operations isp_subdev_media_ops = {
- .link_setup = isp_subdev_link_setup,
- .link_validate = v4l2_subdev_link_validate,
-/* .set_power = v4l2_subdev_set_power, */
-};
-
-static int __atomisp_update_run_mode(struct atomisp_sub_device *asd)
-{
- struct atomisp_device *isp = asd->isp;
- struct v4l2_ctrl *ctrl = asd->run_mode;
- struct v4l2_ctrl *c;
- s32 mode;
-
- if (ctrl->val != ATOMISP_RUN_MODE_VIDEO &&
- asd->continuous_mode->val)
- mode = ATOMISP_RUN_MODE_PREVIEW;
- else
- mode = ctrl->val;
-
- c = v4l2_ctrl_find(
- isp->inputs[asd->input_curr].camera->ctrl_handler,
- V4L2_CID_RUN_MODE);
-
- if (c)
- return v4l2_ctrl_s_ctrl(c, mode);
-
- return 0;
-}
-
-int atomisp_update_run_mode(struct atomisp_sub_device *asd)
-{
- int rval;
-
- mutex_lock(asd->ctrl_handler.lock);
- rval = __atomisp_update_run_mode(asd);
- mutex_unlock(asd->ctrl_handler.lock);
-
- return rval;
-}
-
-static int s_ctrl(struct v4l2_ctrl *ctrl)
-{
- struct atomisp_sub_device *asd = container_of(
- ctrl->handler, struct atomisp_sub_device, ctrl_handler);
-
- switch (ctrl->id) {
- case V4L2_CID_RUN_MODE:
- return __atomisp_update_run_mode(asd);
- case V4L2_CID_DEPTH_MODE:
- if (asd->streaming != ATOMISP_DEVICE_STREAMING_DISABLED) {
- dev_err(asd->isp->dev, "ISP is streaming, it is not supported to change the depth mode\n");
- return -EINVAL;
- }
- break;
- }
-
- return 0;
-}
-
-static const struct v4l2_ctrl_ops ctrl_ops = {
- .s_ctrl = &s_ctrl,
-};
-
-static const struct v4l2_ctrl_config ctrl_fmt_auto = {
- .ops = &ctrl_ops,
- .id = V4L2_CID_FMT_AUTO,
- .name = "Automatic format guessing",
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- .min = 0,
- .max = 1,
- .step = 1,
- .def = 1,
-};
-
-static const char * const ctrl_run_mode_menu[] = {
- NULL,
- "Video",
- "Still capture",
- "Continuous capture",
- "Preview",
-};
-
-static const struct v4l2_ctrl_config ctrl_run_mode = {
- .ops = &ctrl_ops,
- .id = V4L2_CID_RUN_MODE,
- .name = "Atomisp run mode",
- .type = V4L2_CTRL_TYPE_MENU,
- .min = 1,
- .def = 1,
- .max = 4,
- .qmenu = ctrl_run_mode_menu,
-};
-
-static const char * const ctrl_vfpp_mode_menu[] = {
- "Enable", /* vfpp always enabled */
- "Disable to scaler mode", /* CSS into video mode and disable */
- "Disable to low latency mode", /* CSS into still mode and disable */
-};
-
-static const struct v4l2_ctrl_config ctrl_vfpp = {
- .id = V4L2_CID_VFPP,
- .name = "Atomisp vf postprocess",
- .type = V4L2_CTRL_TYPE_MENU,
- .min = 0,
- .def = 0,
- .max = 2,
- .qmenu = ctrl_vfpp_mode_menu,
-};
-
-/*
- * Control for ISP continuous mode
- *
- * When enabled, capture processing is possible without
- * stopping the preview pipeline. When disabled, ISP needs
- * to be restarted between preview and capture.
- */
-static const struct v4l2_ctrl_config ctrl_continuous_mode = {
- .ops = &ctrl_ops,
- .id = V4L2_CID_ATOMISP_CONTINUOUS_MODE,
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- .name = "Continuous mode",
- .min = 0,
- .max = 1,
- .step = 1,
- .def = 0,
-};
-
-/*
- * Control for continuous mode raw buffer size
- *
- * The size of the RAW ringbuffer sets limit on how much
- * back in time application can go when requesting capture
- * frames to be rendered, and how many frames can be rendered
- * in a burst at full sensor rate.
- *
- * Note: this setting has a big impact on memory consumption of
- * the CSS subsystem.
- */
-static const struct v4l2_ctrl_config ctrl_continuous_raw_buffer_size = {
- .ops = &ctrl_ops,
- .id = V4L2_CID_ATOMISP_CONTINUOUS_RAW_BUFFER_SIZE,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "Continuous raw ringbuffer size",
- .min = 1,
- .max = 100, /* depends on CSS version, runtime checked */
- .step = 1,
- .def = 3,
-};
-
-/*
- * Control for enabling continuous viewfinder
- *
- * When enabled, and ISP is in continuous mode (see ctrl_continuous_mode ),
- * preview pipeline continues concurrently with capture
- * processing. When disabled, and continuous mode is used,
- * preview is paused while captures are processed, but
- * full pipeline restart is not needed.
- *
- * By setting this to disabled, capture processing is
- * essentially given priority over preview, and the effective
- * capture output rate may be higher than with continuous
- * viewfinder enabled.
- */
-static const struct v4l2_ctrl_config ctrl_continuous_viewfinder = {
- .id = V4L2_CID_ATOMISP_CONTINUOUS_VIEWFINDER,
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- .name = "Continuous viewfinder",
- .min = 0,
- .max = 1,
- .step = 1,
- .def = 0,
-};
-
-/*
- * Control for enabling Lock&Unlock Raw Buffer mechanism
- *
- * When enabled, Raw Buffer can be locked and unlocked.
- * Application can hold the exp_id of Raw Buffer
- * and unlock it when no longer needed.
- * Note: Make sure set this configuration before creating stream.
- */
-static const struct v4l2_ctrl_config ctrl_enable_raw_buffer_lock = {
- .id = V4L2_CID_ENABLE_RAW_BUFFER_LOCK,
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- .name = "Lock Unlock Raw Buffer",
- .min = 0,
- .max = 1,
- .step = 1,
- .def = 0,
-};
-
-/*
- * Control to disable digital zoom of the whole stream
- *
- * When it is true, pipe configuation enable_dz will be set to false.
- * This can help get a better performance by disabling pp binary.
- *
- * Note: Make sure set this configuration before creating stream.
- */
-static const struct v4l2_ctrl_config ctrl_disable_dz = {
- .id = V4L2_CID_DISABLE_DZ,
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- .name = "Disable digital zoom",
- .min = 0,
- .max = 1,
- .step = 1,
- .def = 0,
-};
-
-/*
- * Control for ISP depth mode
- *
- * When enabled, that means ISP will deal with dual streams and sensors will be
- * in slave/master mode.
- * slave sensor will have no output until master sensor is streamed on.
- */
-static const struct v4l2_ctrl_config ctrl_depth_mode = {
- .ops = &ctrl_ops,
- .id = V4L2_CID_DEPTH_MODE,
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- .name = "Depth mode",
- .min = 0,
- .max = 1,
- .step = 1,
- .def = 0,
-};
-
-#ifdef ISP2401
-/*
- * Control for selectting ISP version
- *
- * When enabled, that means ISP version will be used ISP2.7. when disable, the
- * isp will default to use ISP2.2.
- * Note: Make sure set this configuration before creating stream.
- */
-static const struct v4l2_ctrl_config ctrl_select_isp_version = {
- .ops = &ctrl_ops,
- .id = V4L2_CID_ATOMISP_SELECT_ISP_VERSION,
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- .name = "Select Isp version",
- .min = 0,
- .max = 1,
- .step = 1,
- .def = 0,
-};
-
-#ifdef CONFIG_ION
-/*
- * Control for ISP ion device fd
- *
- * userspace will open ion device and pass the fd to kernel.
- * this fd will be used to map shared fd to buffer.
- */
-static const struct v4l2_ctrl_config ctrl_ion_dev_fd = {
- .ops = &ctrl_ops,
- .id = V4L2_CID_ATOMISP_ION_DEVICE_FD,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "Ion Device Fd",
- .min = -1,
- .max = 1024,
- .step = 1,
- .def = ION_FD_UNSET
-};
-#endif
-
-#endif
-static void atomisp_init_subdev_pipe(struct atomisp_sub_device *asd,
- struct atomisp_video_pipe *pipe, enum v4l2_buf_type buf_type)
-{
- pipe->type = buf_type;
- pipe->asd = asd;
- pipe->isp = asd->isp;
- spin_lock_init(&pipe->irq_lock);
- INIT_LIST_HEAD(&pipe->activeq);
- INIT_LIST_HEAD(&pipe->activeq_out);
- INIT_LIST_HEAD(&pipe->buffers_waiting_for_param);
- INIT_LIST_HEAD(&pipe->per_frame_params);
- memset(pipe->frame_request_config_id,
- 0, VIDEO_MAX_FRAME * sizeof(unsigned int));
- memset(pipe->frame_params,
- 0, VIDEO_MAX_FRAME *
- sizeof(struct atomisp_css_params_with_list *));
-}
-
-static void atomisp_init_acc_pipe(struct atomisp_sub_device *asd,
- struct atomisp_acc_pipe *pipe)
-{
- pipe->asd = asd;
- pipe->isp = asd->isp;
- INIT_LIST_HEAD(&asd->acc.fw);
- INIT_LIST_HEAD(&asd->acc.memory_maps);
- ida_init(&asd->acc.ida);
-}
-
-/*
- * isp_subdev_init_entities - Initialize V4L2 subdev and media entity
- * @asd: ISP CCDC module
- *
- * Return 0 on success and a negative error code on failure.
- */
-static int isp_subdev_init_entities(struct atomisp_sub_device *asd)
-{
- struct v4l2_subdev *sd = &asd->subdev;
- struct media_pad *pads = asd->pads;
- struct media_entity *me = &sd->entity;
- int ret;
-
- asd->input = ATOMISP_SUBDEV_INPUT_NONE;
-
- v4l2_subdev_init(sd, &isp_subdev_v4l2_ops);
- sprintf(sd->name, "ATOMISP_SUBDEV_%d", asd->index);
- v4l2_set_subdevdata(sd, asd);
- sd->flags |= V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_HAS_DEVNODE;
-
- pads[ATOMISP_SUBDEV_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
- pads[ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW].flags = MEDIA_PAD_FL_SOURCE;
- pads[ATOMISP_SUBDEV_PAD_SOURCE_VF].flags = MEDIA_PAD_FL_SOURCE;
- pads[ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE].flags = MEDIA_PAD_FL_SOURCE;
- pads[ATOMISP_SUBDEV_PAD_SOURCE_VIDEO].flags = MEDIA_PAD_FL_SOURCE;
-
- asd->fmt[ATOMISP_SUBDEV_PAD_SINK].fmt.code =
- MEDIA_BUS_FMT_SBGGR10_1X10;
- asd->fmt[ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW].fmt.code =
- MEDIA_BUS_FMT_SBGGR10_1X10;
- asd->fmt[ATOMISP_SUBDEV_PAD_SOURCE_VF].fmt.code =
- MEDIA_BUS_FMT_SBGGR10_1X10;
- asd->fmt[ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE].fmt.code =
- MEDIA_BUS_FMT_SBGGR10_1X10;
- asd->fmt[ATOMISP_SUBDEV_PAD_SOURCE_VIDEO].fmt.code =
- MEDIA_BUS_FMT_SBGGR10_1X10;
-
- me->ops = &isp_subdev_media_ops;
- me->function = MEDIA_ENT_F_V4L2_SUBDEV_UNKNOWN;
- ret = media_entity_pads_init(me, ATOMISP_SUBDEV_PADS_NUM, pads);
- if (ret < 0)
- return ret;
-
- atomisp_init_subdev_pipe(asd, &asd->video_in,
- V4L2_BUF_TYPE_VIDEO_OUTPUT);
-
- atomisp_init_subdev_pipe(asd, &asd->video_out_preview,
- V4L2_BUF_TYPE_VIDEO_CAPTURE);
-
- atomisp_init_subdev_pipe(asd, &asd->video_out_vf,
- V4L2_BUF_TYPE_VIDEO_CAPTURE);
-
- atomisp_init_subdev_pipe(asd, &asd->video_out_capture,
- V4L2_BUF_TYPE_VIDEO_CAPTURE);
-
- atomisp_init_subdev_pipe(asd, &asd->video_out_video_capture,
- V4L2_BUF_TYPE_VIDEO_CAPTURE);
-
- atomisp_init_acc_pipe(asd, &asd->video_acc);
-
- ret = atomisp_video_init(&asd->video_in, "MEMORY");
- if (ret < 0)
- return ret;
-
- ret = atomisp_video_init(&asd->video_out_capture, "CAPTURE");
- if (ret < 0)
- return ret;
-
- ret = atomisp_video_init(&asd->video_out_vf, "VIEWFINDER");
- if (ret < 0)
- return ret;
-
- ret = atomisp_video_init(&asd->video_out_preview, "PREVIEW");
- if (ret < 0)
- return ret;
-
- ret = atomisp_video_init(&asd->video_out_video_capture, "VIDEO");
- if (ret < 0)
- return ret;
-
- atomisp_acc_init(&asd->video_acc, "ACC");
-
- ret = v4l2_ctrl_handler_init(&asd->ctrl_handler, 1);
- if (ret)
- return ret;
-
- asd->fmt_auto = v4l2_ctrl_new_custom(&asd->ctrl_handler,
- &ctrl_fmt_auto, NULL);
- asd->run_mode = v4l2_ctrl_new_custom(&asd->ctrl_handler,
- &ctrl_run_mode, NULL);
- asd->vfpp = v4l2_ctrl_new_custom(&asd->ctrl_handler,
- &ctrl_vfpp, NULL);
- asd->continuous_mode = v4l2_ctrl_new_custom(&asd->ctrl_handler,
- &ctrl_continuous_mode, NULL);
- asd->continuous_viewfinder = v4l2_ctrl_new_custom(&asd->ctrl_handler,
- &ctrl_continuous_viewfinder,
- NULL);
- asd->continuous_raw_buffer_size =
- v4l2_ctrl_new_custom(&asd->ctrl_handler,
- &ctrl_continuous_raw_buffer_size,
- NULL);
-
- asd->enable_raw_buffer_lock =
- v4l2_ctrl_new_custom(&asd->ctrl_handler,
- &ctrl_enable_raw_buffer_lock,
- NULL);
- asd->depth_mode =
- v4l2_ctrl_new_custom(&asd->ctrl_handler,
- &ctrl_depth_mode,
- NULL);
- asd->disable_dz =
- v4l2_ctrl_new_custom(&asd->ctrl_handler,
- &ctrl_disable_dz,
- NULL);
-#ifdef ISP2401
- asd->select_isp_version =
- v4l2_ctrl_new_custom(&asd->ctrl_handler,
- &ctrl_select_isp_version,
- NULL);
-
-#ifdef CONFIG_ION
- asd->ion_dev_fd =
- v4l2_ctrl_new_custom(&asd->ctrl_handler,
- &ctrl_ion_dev_fd,
- NULL);
-#endif
-#endif
-
- /* Make controls visible on subdev as well. */
- asd->subdev.ctrl_handler = &asd->ctrl_handler;
- spin_lock_init(&asd->raw_buffer_bitmap_lock);
- return asd->ctrl_handler.error;
-}
-
-int atomisp_create_pads_links(struct atomisp_device *isp)
-{
- struct atomisp_sub_device *asd;
- int i, j, ret = 0;
- isp->num_of_streams = 2;
- for (i = 0; i < ATOMISP_CAMERA_NR_PORTS; i++) {
- for (j = 0; j < isp->num_of_streams; j++) {
- ret =
- media_create_pad_link(&isp->csi2_port[i].subdev.
- entity, CSI2_PAD_SOURCE,
- &isp->asd[j].subdev.entity,
- ATOMISP_SUBDEV_PAD_SINK, 0);
- if (ret < 0)
- return ret;
- }
- }
- for (i = 0; i < isp->input_cnt - 2; i++) {
- ret = media_create_pad_link(&isp->inputs[i].camera->entity, 0,
- &isp->csi2_port[isp->inputs[i].
- port].subdev.entity,
- CSI2_PAD_SINK,
- MEDIA_LNK_FL_ENABLED |
- MEDIA_LNK_FL_IMMUTABLE);
- if (ret < 0)
- return ret;
- }
- for (i = 0; i < isp->num_of_streams; i++) {
- asd = &isp->asd[i];
- ret = media_create_pad_link(&asd->subdev.entity,
- ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW,
- &asd->video_out_preview.vdev.entity,
- 0, 0);
- if (ret < 0)
- return ret;
- ret = media_create_pad_link(&asd->subdev.entity,
- ATOMISP_SUBDEV_PAD_SOURCE_VF,
- &asd->video_out_vf.vdev.entity, 0,
- 0);
- if (ret < 0)
- return ret;
- ret = media_create_pad_link(&asd->subdev.entity,
- ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE,
- &asd->video_out_capture.vdev.entity,
- 0, 0);
- if (ret < 0)
- return ret;
- ret = media_create_pad_link(&asd->subdev.entity,
- ATOMISP_SUBDEV_PAD_SOURCE_VIDEO,
- &asd->video_out_video_capture.vdev.
- entity, 0, 0);
- if (ret < 0)
- return ret;
- /*
- * file input only supported on subdev0
- * so do not create pad link for subdevs other then subdev0
- */
- if (asd->index)
- return 0;
- ret = media_create_pad_link(&asd->video_in.vdev.entity,
- 0, &asd->subdev.entity,
- ATOMISP_SUBDEV_PAD_SINK, 0);
- if (ret < 0)
- return ret;
- }
- return 0;
-}
-
-static void atomisp_subdev_cleanup_entities(struct atomisp_sub_device *asd)
-{
- v4l2_ctrl_handler_free(&asd->ctrl_handler);
-
- media_entity_cleanup(&asd->subdev.entity);
-}
-
-void atomisp_subdev_cleanup_pending_events(struct atomisp_sub_device *asd)
-{
- struct v4l2_fh *fh, *fh_tmp;
- struct v4l2_event event;
- unsigned int i, pending_event;
-
- list_for_each_entry_safe(fh, fh_tmp,
- &asd->subdev.devnode->fh_list, list) {
- pending_event = v4l2_event_pending(fh);
- for (i = 0; i < pending_event; i++)
- v4l2_event_dequeue(fh, &event, 1);
- }
-}
-
-void atomisp_subdev_unregister_entities(struct atomisp_sub_device *asd)
-{
- atomisp_subdev_cleanup_entities(asd);
- v4l2_device_unregister_subdev(&asd->subdev);
- atomisp_video_unregister(&asd->video_in);
- atomisp_video_unregister(&asd->video_out_preview);
- atomisp_video_unregister(&asd->video_out_vf);
- atomisp_video_unregister(&asd->video_out_capture);
- atomisp_video_unregister(&asd->video_out_video_capture);
- atomisp_acc_unregister(&asd->video_acc);
-}
-
-int atomisp_subdev_register_entities(struct atomisp_sub_device *asd,
- struct v4l2_device *vdev)
-{
- int ret;
-
- /* Register the subdev and video node. */
- ret = v4l2_device_register_subdev(vdev, &asd->subdev);
- if (ret < 0)
- goto error;
-
- ret = atomisp_video_register(&asd->video_out_capture, vdev);
- if (ret < 0)
- goto error;
-
- ret = atomisp_video_register(&asd->video_out_vf, vdev);
- if (ret < 0)
- goto error;
-
- ret = atomisp_video_register(&asd->video_out_preview, vdev);
- if (ret < 0)
- goto error;
-
- ret = atomisp_video_register(&asd->video_out_video_capture, vdev);
- if (ret < 0)
- goto error;
-
- ret = atomisp_acc_register(&asd->video_acc, vdev);
- if (ret < 0)
- goto error;
-
- /*
- * file input only supported on subdev0
- * so do not create video node for subdevs other then subdev0
- */
- if (asd->index)
- return 0;
- ret = atomisp_video_register(&asd->video_in, vdev);
- if (ret < 0)
- goto error;
-
- return 0;
-
-error:
- atomisp_subdev_unregister_entities(asd);
- return ret;
-}
-
-/*
- * atomisp_subdev_init - ISP Subdevice initialization.
- * @dev: Device pointer specific to the ATOM ISP.
- *
- * TODO: Get the initialisation values from platform data.
- *
- * Return 0 on success or a negative error code otherwise.
- */
-int atomisp_subdev_init(struct atomisp_device *isp)
-{
- struct atomisp_sub_device *asd;
- int i, ret = 0;
-
- /*
- * CSS2.0 running ISP2400 support
- * multiple streams
- */
- isp->num_of_streams = 2;
- isp->asd = devm_kzalloc(isp->dev, sizeof(struct atomisp_sub_device) *
- isp->num_of_streams, GFP_KERNEL);
- if (!isp->asd)
- return -ENOMEM;
- for (i = 0; i < isp->num_of_streams; i++) {
- asd = &isp->asd[i];
- spin_lock_init(&asd->lock);
- asd->isp = isp;
- isp_subdev_init_params(asd);
- asd->index = i;
- ret = isp_subdev_init_entities(asd);
- if (ret < 0) {
- atomisp_subdev_cleanup_entities(asd);
- break;
- }
- }
-
- return ret;
-}