File Index
Files and directories
Sign in
FILE

atomisp_ioctl.c

File preview with syntax highlighting.

linux-6.19.14/drivers/staging/media/atomisp/pci/atomisp_ioctl.c C
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Support for Medifield PNW Camera Imaging ISP subsystem.
   4 *
   5 * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
   6 *
   7 * Copyright (c) 2010 Silicon Hive www.siliconhive.com.
   8 */
   9
  10#include <linux/delay.h>
  11#include <linux/pci.h>
  12
  13#include <media/v4l2-ioctl.h>
  14#include <media/v4l2-event.h>
  15
  16#include "atomisp_cmd.h"
  17#include "atomisp_common.h"
  18#include "atomisp_fops.h"
  19#include "atomisp_internal.h"
  20#include "atomisp_ioctl.h"
  21#include "atomisp-regs.h"
  22#include "atomisp_compat.h"
  23
  24#include "sh_css_hrt.h"
  25
  26#include "gp_device.h"
  27#include "device_access.h"
  28#include "irq.h"
  29
  30static const char *DRIVER = "atomisp";	/* max size 15 */
  31static const char *CARD = "ATOM ISP";	/* max size 31 */
  32
  33/*
  34 * FIXME: ISP should not know beforehand all CIDs supported by sensor.
  35 * Instead, it needs to propagate to sensor unknown CIDs.
  36 */
  37static struct v4l2_query_ext_ctrl ci_v4l2_controls[] = {
  38	{
  39		.id = V4L2_CID_AUTO_WHITE_BALANCE,
  40		.type = V4L2_CTRL_TYPE_BOOLEAN,
  41		.name = "Automatic White Balance",
  42		.minimum = 0,
  43		.maximum = 1,
  44		.step = 1,
  45		.default_value = 0,
  46	},
  47	{
  48		.id = V4L2_CID_RED_BALANCE,
  49		.type = V4L2_CTRL_TYPE_INTEGER,
  50		.name = "Red Balance",
  51		.minimum = 0x00,
  52		.maximum = 0xff,
  53		.step = 1,
  54		.default_value = 0x00,
  55	},
  56	{
  57		.id = V4L2_CID_BLUE_BALANCE,
  58		.type = V4L2_CTRL_TYPE_INTEGER,
  59		.name = "Blue Balance",
  60		.minimum = 0x00,
  61		.maximum = 0xff,
  62		.step = 1,
  63		.default_value = 0x00,
  64	},
  65	{
  66		.id = V4L2_CID_GAMMA,
  67		.type = V4L2_CTRL_TYPE_INTEGER,
  68		.name = "Gamma",
  69		.minimum = 0x00,
  70		.maximum = 0xff,
  71		.step = 1,
  72		.default_value = 0x00,
  73	},
  74	{
  75		.id = V4L2_CID_COLORFX,
  76		.type = V4L2_CTRL_TYPE_INTEGER,
  77		.name = "Image Color Effect",
  78		.minimum = 0,
  79		.maximum = 9,
  80		.step = 1,
  81		.default_value = 0,
  82	},
  83	{
  84		.id = V4L2_CID_ATOMISP_BAD_PIXEL_DETECTION,
  85		.type = V4L2_CTRL_TYPE_INTEGER,
  86		.name = "Bad Pixel Correction",
  87		.minimum = 0,
  88		.maximum = 1,
  89		.step = 1,
  90		.default_value = 0,
  91	},
  92	{
  93		.id = V4L2_CID_ATOMISP_POSTPROCESS_GDC_CAC,
  94		.type = V4L2_CTRL_TYPE_INTEGER,
  95		.name = "GDC/CAC",
  96		.minimum = 0,
  97		.maximum = 1,
  98		.step = 1,
  99		.default_value = 0,
 100	},
 101	{
 102		.id = V4L2_CID_ATOMISP_VIDEO_STABLIZATION,
 103		.type = V4L2_CTRL_TYPE_INTEGER,
 104		.name = "Video Stabilization",
 105		.minimum = 0,
 106		.maximum = 1,
 107		.step = 1,
 108		.default_value = 0,
 109	},
 110	{
 111		.id = V4L2_CID_ATOMISP_FIXED_PATTERN_NR,
 112		.type = V4L2_CTRL_TYPE_INTEGER,
 113		.name = "Fixed Pattern Noise Reduction",
 114		.minimum = 0,
 115		.maximum = 1,
 116		.step = 1,
 117		.default_value = 0,
 118	},
 119	{
 120		.id = V4L2_CID_ATOMISP_FALSE_COLOR_CORRECTION,
 121		.type = V4L2_CTRL_TYPE_INTEGER,
 122		.name = "False Color Correction",
 123		.minimum = 0,
 124		.maximum = 1,
 125		.step = 1,
 126		.default_value = 0,
 127	},
 128	{
 129		.id = V4L2_CID_ATOMISP_LOW_LIGHT,
 130		.type = V4L2_CTRL_TYPE_BOOLEAN,
 131		.name = "Low light mode",
 132		.minimum = 0,
 133		.maximum = 1,
 134		.step = 1,
 135		.default_value = 1,
 136	},
 137};
 138
 139static const u32 ctrls_num = ARRAY_SIZE(ci_v4l2_controls);
 140
 141/*
 142 * supported V4L2 fmts and resolutions
 143 */
 144const struct atomisp_format_bridge atomisp_output_fmts[] = {
 145	{
 146		.pixelformat = V4L2_PIX_FMT_YUV420,
 147		.depth = 12,
 148		.mbus_code = V4L2_MBUS_FMT_CUSTOM_YUV420,
 149		.sh_fmt = IA_CSS_FRAME_FORMAT_YUV420,
 150		.description = "YUV420, planar",
 151		.planar = true
 152	}, {
 153		.pixelformat = V4L2_PIX_FMT_YVU420,
 154		.depth = 12,
 155		.mbus_code = V4L2_MBUS_FMT_CUSTOM_YVU420,
 156		.sh_fmt = IA_CSS_FRAME_FORMAT_YV12,
 157		.description = "YVU420, planar",
 158		.planar = true
 159	}, {
 160		.pixelformat = V4L2_PIX_FMT_YUV422P,
 161		.depth = 16,
 162		.mbus_code = V4L2_MBUS_FMT_CUSTOM_YUV422P,
 163		.sh_fmt = IA_CSS_FRAME_FORMAT_YUV422,
 164		.description = "YUV422, planar",
 165		.planar = true
 166	}, {
 167		.pixelformat = V4L2_PIX_FMT_YUV444,
 168		.depth = 24,
 169		.mbus_code = V4L2_MBUS_FMT_CUSTOM_YUV444,
 170		.sh_fmt = IA_CSS_FRAME_FORMAT_YUV444,
 171		.description = "YUV444"
 172	}, {
 173		.pixelformat = V4L2_PIX_FMT_NV12,
 174		.depth = 12,
 175		.mbus_code = V4L2_MBUS_FMT_CUSTOM_NV12,
 176		.sh_fmt = IA_CSS_FRAME_FORMAT_NV12,
 177		.description = "NV12, Y-plane, CbCr interleaved",
 178		.planar = true
 179	}, {
 180		.pixelformat = V4L2_PIX_FMT_NV21,
 181		.depth = 12,
 182		.mbus_code = V4L2_MBUS_FMT_CUSTOM_NV21,
 183		.sh_fmt = IA_CSS_FRAME_FORMAT_NV21,
 184		.description = "NV21, Y-plane, CbCr interleaved",
 185		.planar = true
 186	}, {
 187		.pixelformat = V4L2_PIX_FMT_NV16,
 188		.depth = 16,
 189		.mbus_code = V4L2_MBUS_FMT_CUSTOM_NV16,
 190		.sh_fmt = IA_CSS_FRAME_FORMAT_NV16,
 191		.description = "NV16, Y-plane, CbCr interleaved",
 192		.planar = true
 193	}, {
 194		.pixelformat = V4L2_PIX_FMT_YUYV,
 195		.depth = 16,
 196		.mbus_code = V4L2_MBUS_FMT_CUSTOM_YUYV,
 197		.sh_fmt = IA_CSS_FRAME_FORMAT_YUYV,
 198		.description = "YUYV, interleaved"
 199	}, {
 200		.pixelformat = V4L2_PIX_FMT_UYVY,
 201		.depth = 16,
 202		.mbus_code = MEDIA_BUS_FMT_UYVY8_1X16,
 203		.sh_fmt = IA_CSS_FRAME_FORMAT_UYVY,
 204		.description = "UYVY, interleaved"
 205	}, {
 206		.pixelformat = V4L2_PIX_FMT_SBGGR16,
 207		.depth = 16,
 208		.mbus_code = V4L2_MBUS_FMT_CUSTOM_SBGGR16,
 209		.sh_fmt = IA_CSS_FRAME_FORMAT_RAW,
 210		.description = "Bayer 16"
 211	}, {
 212		.pixelformat = V4L2_PIX_FMT_SBGGR8,
 213		.depth = 8,
 214		.mbus_code = MEDIA_BUS_FMT_SBGGR8_1X8,
 215		.sh_fmt = IA_CSS_FRAME_FORMAT_RAW,
 216		.description = "Bayer 8"
 217	}, {
 218		.pixelformat = V4L2_PIX_FMT_SGBRG8,
 219		.depth = 8,
 220		.mbus_code = MEDIA_BUS_FMT_SGBRG8_1X8,
 221		.sh_fmt = IA_CSS_FRAME_FORMAT_RAW,
 222		.description = "Bayer 8"
 223	}, {
 224		.pixelformat = V4L2_PIX_FMT_SGRBG8,
 225		.depth = 8,
 226		.mbus_code = MEDIA_BUS_FMT_SGRBG8_1X8,
 227		.sh_fmt = IA_CSS_FRAME_FORMAT_RAW,
 228		.description = "Bayer 8"
 229	}, {
 230		.pixelformat = V4L2_PIX_FMT_SRGGB8,
 231		.depth = 8,
 232		.mbus_code = MEDIA_BUS_FMT_SRGGB8_1X8,
 233		.sh_fmt = IA_CSS_FRAME_FORMAT_RAW,
 234		.description = "Bayer 8"
 235	}, {
 236		.pixelformat = V4L2_PIX_FMT_SBGGR10,
 237		.depth = 16,
 238		.mbus_code = MEDIA_BUS_FMT_SBGGR10_1X10,
 239		.sh_fmt = IA_CSS_FRAME_FORMAT_RAW,
 240		.description = "Bayer 10"
 241	}, {
 242		.pixelformat = V4L2_PIX_FMT_SGBRG10,
 243		.depth = 16,
 244		.mbus_code = MEDIA_BUS_FMT_SGBRG10_1X10,
 245		.sh_fmt = IA_CSS_FRAME_FORMAT_RAW,
 246		.description = "Bayer 10"
 247	}, {
 248		.pixelformat = V4L2_PIX_FMT_SGRBG10,
 249		.depth = 16,
 250		.mbus_code = MEDIA_BUS_FMT_SGRBG10_1X10,
 251		.sh_fmt = IA_CSS_FRAME_FORMAT_RAW,
 252		.description = "Bayer 10"
 253	}, {
 254		.pixelformat = V4L2_PIX_FMT_SRGGB10,
 255		.depth = 16,
 256		.mbus_code = MEDIA_BUS_FMT_SRGGB10_1X10,
 257		.sh_fmt = IA_CSS_FRAME_FORMAT_RAW,
 258		.description = "Bayer 10"
 259	}, {
 260		.pixelformat = V4L2_PIX_FMT_SBGGR12,
 261		.depth = 16,
 262		.mbus_code = MEDIA_BUS_FMT_SBGGR12_1X12,
 263		.sh_fmt = IA_CSS_FRAME_FORMAT_RAW,
 264		.description = "Bayer 12"
 265	}, {
 266		.pixelformat = V4L2_PIX_FMT_SGBRG12,
 267		.depth = 16,
 268		.mbus_code = MEDIA_BUS_FMT_SGBRG12_1X12,
 269		.sh_fmt = IA_CSS_FRAME_FORMAT_RAW,
 270		.description = "Bayer 12"
 271	}, {
 272		.pixelformat = V4L2_PIX_FMT_SGRBG12,
 273		.depth = 16,
 274		.mbus_code = MEDIA_BUS_FMT_SGRBG12_1X12,
 275		.sh_fmt = IA_CSS_FRAME_FORMAT_RAW,
 276		.description = "Bayer 12"
 277	}, {
 278		.pixelformat = V4L2_PIX_FMT_SRGGB12,
 279		.depth = 16,
 280		.mbus_code = MEDIA_BUS_FMT_SRGGB12_1X12,
 281		.sh_fmt = IA_CSS_FRAME_FORMAT_RAW,
 282		.description = "Bayer 12"
 283	}, {
 284		.pixelformat = V4L2_PIX_FMT_RGB565,
 285		.depth = 16,
 286		.mbus_code = MEDIA_BUS_FMT_BGR565_2X8_LE,
 287		.sh_fmt = IA_CSS_FRAME_FORMAT_RGB565,
 288		.description = "16 RGB 5-6-5"
 289#if 0
 290	}, {
 291		/*
 292		 * Broken, showing vertical columns with random data.
 293		 * For each 128 pixels in a row the last 28 (32?) or so pixels
 294		 * contain random data.
 295		 */
 296		.pixelformat = V4L2_PIX_FMT_RGBX32,
 297		.depth = 32,
 298		.mbus_code = V4L2_MBUS_FMT_CUSTOM_RGB32,
 299		.sh_fmt = IA_CSS_FRAME_FORMAT_RGBA888,
 300		.description = "32 RGB 8-8-8-8"
 301	}, {
 302		.pixelformat = V4L2_PIX_FMT_JPEG,
 303		.depth = 8,
 304		.mbus_code = MEDIA_BUS_FMT_JPEG_1X8,
 305		.sh_fmt = IA_CSS_FRAME_FORMAT_BINARY_8,
 306		.description = "JPEG"
 307	}, {
 308		/* This is a custom format being used by M10MO to send the RAW data */
 309		.pixelformat = V4L2_PIX_FMT_CUSTOM_M10MO_RAW,
 310		.depth = 8,
 311		.mbus_code = V4L2_MBUS_FMT_CUSTOM_M10MO_RAW,
 312		.sh_fmt = IA_CSS_FRAME_FORMAT_BINARY_8,
 313		.description = "Custom RAW for M10MO"
 314#endif
 315	},
 316};
 317
 318const struct atomisp_format_bridge *
 319atomisp_get_format_bridge(unsigned int pixelformat)
 320{
 321	unsigned int i;
 322
 323	for (i = 0; i < ARRAY_SIZE(atomisp_output_fmts); i++) {
 324		if (atomisp_output_fmts[i].pixelformat == pixelformat)
 325			return &atomisp_output_fmts[i];
 326	}
 327
 328	return NULL;
 329}
 330
 331const struct atomisp_format_bridge *
 332atomisp_get_format_bridge_from_mbus(u32 mbus_code)
 333{
 334	unsigned int i;
 335
 336	for (i = 0; i < ARRAY_SIZE(atomisp_output_fmts); i++) {
 337		if (mbus_code == atomisp_output_fmts[i].mbus_code)
 338			return &atomisp_output_fmts[i];
 339	}
 340
 341	return NULL;
 342}
 343
 344int atomisp_pipe_check(struct atomisp_video_pipe *pipe, bool settings_change)
 345{
 346	lockdep_assert_held(&pipe->isp->mutex);
 347
 348	if (pipe->isp->isp_fatal_error)
 349		return -EIO;
 350
 351	if (settings_change && vb2_is_busy(&pipe->vb_queue)) {
 352		dev_err(pipe->isp->dev, "Set fmt/input IOCTL while streaming\n");
 353		return -EBUSY;
 354	}
 355
 356	return 0;
 357}
 358
 359/*
 360 * v4l2 ioctls
 361 * return ISP capabilities
 362 */
 363static int atomisp_querycap(struct file *file, void *fh,
 364			    struct v4l2_capability *cap)
 365{
 366	struct video_device *vdev = video_devdata(file);
 367	struct atomisp_device *isp = video_get_drvdata(vdev);
 368
 369	strscpy(cap->driver, DRIVER, sizeof(cap->driver));
 370	strscpy(cap->card, CARD, sizeof(cap->card));
 371	snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s", dev_name(isp->dev));
 372
 373	return 0;
 374}
 375
 376/*
 377 * enum input are used to check primary/secondary camera
 378 */
 379static int atomisp_enum_input(struct file *file, void *fh,
 380			      struct v4l2_input *input)
 381{
 382	struct video_device *vdev = video_devdata(file);
 383	struct atomisp_device *isp = video_get_drvdata(vdev);
 384	int index = input->index;
 385
 386	if (index >= isp->input_cnt)
 387		return -EINVAL;
 388
 389	if (!isp->inputs[index].sensor)
 390		return -EINVAL;
 391
 392	memset(input, 0, sizeof(struct v4l2_input));
 393	strscpy(input->name, isp->inputs[index].sensor->name,
 394		sizeof(input->name));
 395
 396	input->type = V4L2_INPUT_TYPE_CAMERA;
 397	input->index = index;
 398	input->reserved[1] = isp->inputs[index].port;
 399
 400	return 0;
 401}
 402
 403/*
 404 * get input are used to get current primary/secondary camera
 405 */
 406static int atomisp_g_input(struct file *file, void *fh, unsigned int *input)
 407{
 408	struct video_device *vdev = video_devdata(file);
 409	struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd;
 410
 411	*input = asd->input_curr;
 412	return 0;
 413}
 414
 415static int atomisp_s_fmt_cap(struct file *file, void *fh,
 416			     struct v4l2_format *f)
 417{
 418	struct video_device *vdev = video_devdata(file);
 419
 420	return atomisp_set_fmt(vdev, f);
 421}
 422
 423/*
 424 * set input are used to set current primary/secondary camera
 425 */
 426static int atomisp_s_input(struct file *file, void *fh, unsigned int input)
 427{
 428	struct video_device *vdev = video_devdata(file);
 429	struct atomisp_device *isp = video_get_drvdata(vdev);
 430	struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev);
 431	int ret;
 432
 433	if (input >= isp->input_cnt)
 434		return -EINVAL;
 435
 436	if (!isp->inputs[input].sensor)
 437		return -EINVAL;
 438
 439	ret = atomisp_pipe_check(pipe, true);
 440	if (ret)
 441		return ret;
 442
 443	mutex_lock(&isp->media_dev.graph_mutex);
 444	ret = atomisp_select_input(isp, input);
 445	mutex_unlock(&isp->media_dev.graph_mutex);
 446
 447	return ret;
 448}
 449
 450/*
 451 * With crop any framesize <= sensor-size can be made, give
 452 * userspace a list of sizes to choice from.
 453 */
 454static int atomisp_enum_framesizes_crop_inner(struct atomisp_device *isp,
 455					      struct v4l2_frmsizeenum *fsize,
 456					      const struct v4l2_rect *active,
 457					      const struct v4l2_rect *native,
 458					      int *valid_sizes)
 459{
 460	static const struct v4l2_frmsize_discrete frame_sizes[] = {
 461		{ 1920, 1440 },
 462		{ 1920, 1200 },
 463		{ 1920, 1080 },
 464		{ 1600, 1200 },
 465		{ 1600, 1080 },
 466		{ 1600,  900 },
 467		{ 1440, 1080 },
 468		{ 1280,  960 },
 469		{ 1280,  720 },
 470		{  800,  600 },
 471		{  640,  480 },
 472	};
 473	u32 padding_w, padding_h;
 474	int i;
 475
 476	for (i = 0; i < ARRAY_SIZE(frame_sizes); i++) {
 477		atomisp_get_padding(isp, frame_sizes[i].width, frame_sizes[i].height,
 478				    &padding_w, &padding_h);
 479
 480		if ((frame_sizes[i].width + padding_w) > native->width ||
 481		    (frame_sizes[i].height + padding_h) > native->height)
 482			continue;
 483
 484		/*
 485		 * Skip sizes where width and height are less then 5/8th of the
 486		 * sensor size to avoid sizes with a too small field of view.
 487		 */
 488		if (frame_sizes[i].width < (active->width * 5 / 8) &&
 489		    frame_sizes[i].height < (active->height * 5 / 8))
 490			continue;
 491
 492		if (*valid_sizes == fsize->index) {
 493			fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
 494			fsize->discrete = frame_sizes[i];
 495			return 0;
 496		}
 497
 498		(*valid_sizes)++;
 499	}
 500
 501	return -EINVAL;
 502}
 503
 504static int atomisp_enum_framesizes_crop(struct atomisp_device *isp,
 505					struct v4l2_frmsizeenum *fsize)
 506{
 507	struct atomisp_input_subdev *input = &isp->inputs[isp->asd.input_curr];
 508	struct v4l2_rect active = input->active_rect;
 509	struct v4l2_rect native = input->native_rect;
 510	int ret, valid_sizes = 0;
 511
 512	ret = atomisp_enum_framesizes_crop_inner(isp, fsize, &active, &native, &valid_sizes);
 513	if (ret == 0)
 514		return 0;
 515
 516	if (!input->binning_support)
 517		return -EINVAL;
 518
 519	active.width /= 2;
 520	active.height /= 2;
 521	native.width /= 2;
 522	native.height /= 2;
 523
 524	return atomisp_enum_framesizes_crop_inner(isp, fsize, &active, &native, &valid_sizes);
 525}
 526
 527static int atomisp_enum_framesizes(struct file *file, void *priv,
 528				   struct v4l2_frmsizeenum *fsize)
 529{
 530	struct video_device *vdev = video_devdata(file);
 531	struct atomisp_device *isp = video_get_drvdata(vdev);
 532	struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd;
 533	struct atomisp_input_subdev *input = &isp->inputs[asd->input_curr];
 534	struct v4l2_subdev_frame_size_enum fse = {
 535		.index = fsize->index,
 536		.which = V4L2_SUBDEV_FORMAT_ACTIVE,
 537		.code = input->code,
 538	};
 539	struct v4l2_subdev_state *act_sd_state;
 540	int ret;
 541
 542	if (!input->sensor)
 543		return -EINVAL;
 544
 545	if (input->crop_support)
 546		return atomisp_enum_framesizes_crop(isp, fsize);
 547
 548	act_sd_state = v4l2_subdev_lock_and_get_active_state(input->sensor);
 549	ret = v4l2_subdev_call(input->sensor, pad, enum_frame_size,
 550			       act_sd_state, &fse);
 551	if (act_sd_state)
 552		v4l2_subdev_unlock_state(act_sd_state);
 553	if (ret)
 554		return ret;
 555
 556	fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
 557	fsize->discrete.width = fse.max_width - pad_w;
 558	fsize->discrete.height = fse.max_height - pad_h;
 559
 560	return 0;
 561}
 562
 563static int atomisp_enum_frameintervals(struct file *file, void *priv,
 564				       struct v4l2_frmivalenum *fival)
 565{
 566	struct video_device *vdev = video_devdata(file);
 567	struct atomisp_device *isp = video_get_drvdata(vdev);
 568	struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd;
 569	struct atomisp_input_subdev *input = &isp->inputs[asd->input_curr];
 570	struct v4l2_subdev_frame_interval_enum fie = {
 571		.code = atomisp_in_fmt_conv[0].code,
 572		.index = fival->index,
 573		.width = fival->width,
 574		.height = fival->height,
 575		.which = V4L2_SUBDEV_FORMAT_ACTIVE,
 576	};
 577	struct v4l2_subdev_state *act_sd_state;
 578	int ret;
 579
 580	if (!input->sensor)
 581		return -EINVAL;
 582
 583	act_sd_state = v4l2_subdev_lock_and_get_active_state(input->sensor);
 584	ret = v4l2_subdev_call(input->sensor, pad, enum_frame_interval,
 585			       act_sd_state, &fie);
 586	if (act_sd_state)
 587		v4l2_subdev_unlock_state(act_sd_state);
 588	if (ret)
 589		return ret;
 590
 591	fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
 592	fival->discrete = fie.interval;
 593
 594	return ret;
 595}
 596
 597static int atomisp_enum_fmt_cap(struct file *file, void *fh,
 598				struct v4l2_fmtdesc *f)
 599{
 600	struct video_device *vdev = video_devdata(file);
 601	struct atomisp_device *isp = video_get_drvdata(vdev);
 602	struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd;
 603	struct atomisp_input_subdev *input = &isp->inputs[asd->input_curr];
 604	struct v4l2_subdev_mbus_code_enum code = {
 605		.which = V4L2_SUBDEV_FORMAT_ACTIVE,
 606	};
 607	const struct atomisp_format_bridge *format;
 608	struct v4l2_subdev_state *act_sd_state;
 609	unsigned int i, fi = 0;
 610	int ret;
 611
 612	if (!input->sensor)
 613		return -EINVAL;
 614
 615	act_sd_state = v4l2_subdev_lock_and_get_active_state(input->sensor);
 616	ret = v4l2_subdev_call(input->sensor, pad, enum_mbus_code,
 617			       act_sd_state, &code);
 618	if (act_sd_state)
 619		v4l2_subdev_unlock_state(act_sd_state);
 620	if (ret)
 621		return ret;
 622
 623	for (i = 0; i < ARRAY_SIZE(atomisp_output_fmts); i++) {
 624		format = &atomisp_output_fmts[i];
 625
 626		/*
 627		 * Is the atomisp-supported format is valid for the
 628		 * sensor (configuration)? If not, skip it.
 629		 *
 630		 * FIXME: fix the pipeline to allow sensor format too.
 631		 */
 632		if (format->sh_fmt == IA_CSS_FRAME_FORMAT_RAW)
 633			continue;
 634
 635		/* Found a match. Now let's pick f->index'th one. */
 636		if (fi < f->index) {
 637			fi++;
 638			continue;
 639		}
 640
 641		strscpy(f->description, format->description,
 642			sizeof(f->description));
 643		f->pixelformat = format->pixelformat;
 644		return 0;
 645	}
 646
 647	return -EINVAL;
 648}
 649
 650/* This function looks up the closest available resolution. */
 651static int atomisp_try_fmt_cap(struct file *file, void *fh,
 652			       struct v4l2_format *f)
 653{
 654	struct video_device *vdev = video_devdata(file);
 655	struct atomisp_device *isp = video_get_drvdata(vdev);
 656
 657	return atomisp_try_fmt(isp, &f->fmt.pix, NULL, NULL);
 658}
 659
 660static int atomisp_g_fmt_cap(struct file *file, void *fh,
 661			     struct v4l2_format *f)
 662{
 663	struct video_device *vdev = video_devdata(file);
 664	struct atomisp_video_pipe *pipe;
 665
 666	pipe = atomisp_to_video_pipe(vdev);
 667
 668	f->fmt.pix = pipe->pix;
 669
 670	/* If s_fmt was issued, just return whatever is was previously set */
 671	if (f->fmt.pix.sizeimage)
 672		return 0;
 673
 674	f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420;
 675	f->fmt.pix.width = 10000;
 676	f->fmt.pix.height = 10000;
 677
 678	return atomisp_try_fmt_cap(file, fh, f);
 679}
 680
 681int atomisp_alloc_css_stat_bufs(struct atomisp_sub_device *asd,
 682				uint16_t stream_id)
 683{
 684	struct atomisp_device *isp = asd->isp;
 685	struct atomisp_s3a_buf *s3a_buf = NULL, *_s3a_buf;
 686	struct atomisp_dis_buf *dis_buf = NULL, *_dis_buf;
 687	struct atomisp_metadata_buf *md_buf = NULL, *_md_buf;
 688	int count;
 689	struct ia_css_dvs_grid_info *dvs_grid_info =
 690	    atomisp_css_get_dvs_grid_info(&asd->params.curr_grid_info);
 691	unsigned int i;
 692
 693	if (list_empty(&asd->s3a_stats) &&
 694	    asd->params.curr_grid_info.s3a_grid.enable) {
 695		count = ATOMISP_CSS_Q_DEPTH +
 696			ATOMISP_S3A_BUF_QUEUE_DEPTH_FOR_HAL;
 697		dev_dbg(isp->dev, "allocating %d 3a buffers\n", count);
 698		while (count--) {
 699			s3a_buf = kzalloc(sizeof(struct atomisp_s3a_buf), GFP_KERNEL);
 700			if (!s3a_buf)
 701				goto error;
 702
 703			if (atomisp_css_allocate_stat_buffers(
 704				asd, stream_id, s3a_buf, NULL, NULL)) {
 705				kfree(s3a_buf);
 706				goto error;
 707			}
 708
 709			list_add_tail(&s3a_buf->list, &asd->s3a_stats);
 710		}
 711	}
 712
 713	if (list_empty(&asd->dis_stats) && dvs_grid_info &&
 714	    dvs_grid_info->enable) {
 715		count = ATOMISP_CSS_Q_DEPTH + 1;
 716		dev_dbg(isp->dev, "allocating %d dis buffers\n", count);
 717		while (count--) {
 718			dis_buf = kzalloc(sizeof(struct atomisp_dis_buf), GFP_KERNEL);
 719			if (!dis_buf)
 720				goto error;
 721			if (atomisp_css_allocate_stat_buffers(
 722				asd, stream_id, NULL, dis_buf, NULL)) {
 723				kfree(dis_buf);
 724				goto error;
 725			}
 726
 727			list_add_tail(&dis_buf->list, &asd->dis_stats);
 728		}
 729	}
 730
 731	for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) {
 732		if (list_empty(&asd->metadata[i]) &&
 733		    list_empty(&asd->metadata_ready[i]) &&
 734		    list_empty(&asd->metadata_in_css[i])) {
 735			count = ATOMISP_CSS_Q_DEPTH +
 736				ATOMISP_METADATA_QUEUE_DEPTH_FOR_HAL;
 737			dev_dbg(isp->dev, "allocating %d metadata buffers for type %d\n",
 738				count, i);
 739			while (count--) {
 740				md_buf = kzalloc(sizeof(struct atomisp_metadata_buf),
 741						 GFP_KERNEL);
 742				if (!md_buf)
 743					goto error;
 744
 745				if (atomisp_css_allocate_stat_buffers(
 746					asd, stream_id, NULL, NULL, md_buf)) {
 747					kfree(md_buf);
 748					goto error;
 749				}
 750				list_add_tail(&md_buf->list, &asd->metadata[i]);
 751			}
 752		}
 753	}
 754	return 0;
 755
 756error:
 757	dev_err(isp->dev, "failed to allocate statistics buffers\n");
 758
 759	list_for_each_entry_safe(dis_buf, _dis_buf, &asd->dis_stats, list) {
 760		atomisp_css_free_dis_buffer(dis_buf);
 761		list_del(&dis_buf->list);
 762		kfree(dis_buf);
 763	}
 764
 765	list_for_each_entry_safe(s3a_buf, _s3a_buf, &asd->s3a_stats, list) {
 766		atomisp_css_free_3a_buffer(s3a_buf);
 767		list_del(&s3a_buf->list);
 768		kfree(s3a_buf);
 769	}
 770
 771	for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) {
 772		list_for_each_entry_safe(md_buf, _md_buf, &asd->metadata[i],
 773					 list) {
 774			atomisp_css_free_metadata_buffer(md_buf);
 775			list_del(&md_buf->list);
 776			kfree(md_buf);
 777		}
 778	}
 779	return -ENOMEM;
 780}
 781
 782/*
 783 * FIXME the abuse of buf->reserved2 in the qbuf and dqbuf wrappers comes from
 784 * the original atomisp buffer handling and should be replaced with proper V4L2
 785 * per frame parameters use.
 786 *
 787 * Once this is fixed these wrappers can be removed, replacing them with direct
 788 * calls to vb2_ioctl_[d]qbuf().
 789 */
 790static int atomisp_qbuf_wrapper(struct file *file, void *fh, struct v4l2_buffer *buf)
 791{
 792	struct video_device *vdev = video_devdata(file);
 793	struct atomisp_device *isp = video_get_drvdata(vdev);
 794	struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev);
 795
 796	if (buf->index >= vb2_get_num_buffers(vdev->queue))
 797		return -EINVAL;
 798
 799	if (buf->reserved2 & ATOMISP_BUFFER_HAS_PER_FRAME_SETTING) {
 800		/* this buffer will have a per-frame parameter */
 801		pipe->frame_request_config_id[buf->index] = buf->reserved2 &
 802			~ATOMISP_BUFFER_HAS_PER_FRAME_SETTING;
 803		dev_dbg(isp->dev,
 804			"This buffer requires per_frame setting which has isp_config_id %d\n",
 805			pipe->frame_request_config_id[buf->index]);
 806	} else {
 807		pipe->frame_request_config_id[buf->index] = 0;
 808	}
 809
 810	return vb2_ioctl_qbuf(file, fh, buf);
 811}
 812
 813static int atomisp_dqbuf_wrapper(struct file *file, void *fh, struct v4l2_buffer *buf)
 814{
 815	struct video_device *vdev = video_devdata(file);
 816	struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev);
 817	struct atomisp_device *isp = video_get_drvdata(vdev);
 818	struct ia_css_frame *frame;
 819	struct vb2_buffer *vb;
 820	int ret;
 821
 822	ret = vb2_ioctl_dqbuf(file, fh, buf);
 823	if (ret)
 824		return ret;
 825
 826	vb = vb2_get_buffer(&pipe->vb_queue, buf->index);
 827	frame = vb_to_frame(vb);
 828
 829	/* reserved bit[31:16] is used for exp_id */
 830	buf->reserved = 0;
 831	if (!(buf->flags & V4L2_BUF_FLAG_ERROR))
 832		buf->reserved |= frame->exp_id;
 833	buf->reserved2 = pipe->frame_config_id[buf->index];
 834
 835	dev_dbg(isp->dev,
 836		"dqbuf buffer %d (%s) with exp_id %d, isp_config_id %d\n",
 837		buf->index, vdev->name, buf->reserved >> 16, buf->reserved2);
 838	return 0;
 839}
 840
 841/* Input system HW workaround */
 842/* Input system address translation corrupts burst during */
 843/* invalidate. SW workaround for this is to set burst length */
 844/* manually to 128 in case of 13MPx snapshot and to 1 otherwise. */
 845static void atomisp_dma_burst_len_cfg(struct atomisp_sub_device *asd)
 846{
 847	struct v4l2_mbus_framefmt *sink;
 848
 849	sink = atomisp_subdev_get_ffmt(&asd->subdev, NULL,
 850				       V4L2_SUBDEV_FORMAT_ACTIVE,
 851				       ATOMISP_SUBDEV_PAD_SINK);
 852
 853	if (sink->width * sink->height >= 4096 * 3072)
 854		atomisp_css2_hw_store_32(DMA_BURST_SIZE_REG, 0x7F);
 855	else
 856		atomisp_css2_hw_store_32(DMA_BURST_SIZE_REG, 0x00);
 857}
 858
 859static void atomisp_stop_stream(struct atomisp_video_pipe *pipe,
 860				bool stop_sensor, enum vb2_buffer_state state)
 861{
 862	struct atomisp_sub_device *asd = pipe->asd;
 863	struct atomisp_device *isp = asd->isp;
 864	struct pci_dev *pdev = to_pci_dev(isp->dev);
 865	unsigned long flags;
 866	int ret;
 867
 868	spin_lock_irqsave(&isp->lock, flags);
 869	asd->streaming = false;
 870	spin_unlock_irqrestore(&isp->lock, flags);
 871
 872	atomisp_clear_css_buffer_counters(asd);
 873	atomisp_css_irq_enable(isp, IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF, false);
 874
 875	atomisp_css_stop(asd, false);
 876
 877	atomisp_subdev_cleanup_pending_events(asd);
 878
 879	if (stop_sensor) {
 880		ret = v4l2_subdev_call(isp->inputs[asd->input_curr].csi_remote_source,
 881				       video, s_stream, 0);
 882		if (ret)
 883			dev_warn(isp->dev, "Stopping sensor stream failed: %d\n", ret);
 884	}
 885
 886	/* Disable the CSI interface on ANN B0/K0 */
 887	if (isp->media_dev.hw_revision >= ((ATOMISP_HW_REVISION_ISP2401 <<
 888					    ATOMISP_HW_REVISION_SHIFT) | ATOMISP_HW_STEPPING_B0)) {
 889		pci_write_config_word(pdev, MRFLD_PCI_CSI_CONTROL,
 890				      isp->saved_regs.csi_control & ~MRFLD_PCI_CSI_CONTROL_CSI_READY);
 891	}
 892
 893	if (atomisp_freq_scaling(isp, ATOMISP_DFS_MODE_LOW, false))
 894		dev_warn(isp->dev, "DFS failed.\n");
 895
 896	/*
 897	 * ISP work around, need to reset ISP to allow next stream on to work.
 898	 * Streams have already been destroyed by atomisp_css_stop().
 899	 * Disable PUNIT/ISP acknowledge/handshake - SRSE=3 and then reset.
 900	 */
 901	pci_write_config_dword(pdev, PCI_I_CONTROL,
 902			       isp->saved_regs.i_control | MRFLD_PCI_I_CONTROL_SRSE_RESET_MASK);
 903	atomisp_reset(isp);
 904
 905	atomisp_flush_video_pipe(pipe, state, false);
 906
 907	/* Streams were destroyed by atomisp_css_stop(), recreate them. */
 908	ret = atomisp_create_pipes_stream(&isp->asd);
 909	if (ret)
 910		dev_warn(isp->dev, "Recreating streams failed: %d\n", ret);
 911
 912	media_pipeline_stop(&asd->video_out.vdev.entity.pads[0]);
 913}
 914
 915int atomisp_start_streaming(struct vb2_queue *vq, unsigned int count)
 916{
 917	struct atomisp_video_pipe *pipe = vq_to_pipe(vq);
 918	struct atomisp_sub_device *asd = pipe->asd;
 919	struct atomisp_device *isp = asd->isp;
 920	struct pci_dev *pdev = to_pci_dev(isp->dev);
 921	unsigned long irqflags;
 922	int ret;
 923
 924	dev_dbg(isp->dev, "Start stream\n");
 925
 926	mutex_lock(&isp->mutex);
 927
 928	ret = atomisp_pipe_check(pipe, false);
 929	if (ret) {
 930		atomisp_flush_video_pipe(pipe, VB2_BUF_STATE_QUEUED, true);
 931		goto out_unlock;
 932	}
 933
 934	/*
 935	 * When running a classic v4l2 app after a media-controller aware
 936	 * app, the CSI-receiver -> ISP link for the current sensor may be
 937	 * disabled. Fix this up before marking the pipeline as started.
 938	 */
 939	mutex_lock(&isp->media_dev.graph_mutex);
 940	atomisp_setup_input_links(isp);
 941	ret = __media_pipeline_start(&asd->video_out.vdev.entity.pads[0], &asd->video_out.pipe);
 942	mutex_unlock(&isp->media_dev.graph_mutex);
 943	if (ret) {
 944		dev_err(isp->dev, "Error starting mc pipeline: %d\n", ret);
 945		atomisp_flush_video_pipe(pipe, VB2_BUF_STATE_QUEUED, true);
 946		goto out_unlock;
 947	}
 948
 949	/* Input system HW workaround */
 950	atomisp_dma_burst_len_cfg(asd);
 951
 952	/* Invalidate caches. FIXME: should flush only necessary buffers */
 953	wbinvd();
 954
 955	if (asd->params.css_update_params_needed) {
 956		atomisp_apply_css_parameters(asd, &asd->params.css_param);
 957		if (asd->params.css_param.update_flag.dz_config)
 958			asd->params.config.dz_config = &asd->params.css_param.dz_config;
 959		atomisp_css_update_isp_params(asd);
 960		asd->params.css_update_params_needed = false;
 961		memset(&asd->params.css_param.update_flag, 0,
 962		       sizeof(struct atomisp_parameters));
 963	}
 964	asd->params.dvs_6axis = NULL;
 965
 966	ret = atomisp_css_start(asd);
 967	if (ret) {
 968		atomisp_flush_video_pipe(pipe, VB2_BUF_STATE_QUEUED, true);
 969		media_pipeline_stop(&asd->video_out.vdev.entity.pads[0]);
 970		goto out_unlock;
 971	}
 972
 973	spin_lock_irqsave(&isp->lock, irqflags);
 974	asd->streaming = true;
 975	spin_unlock_irqrestore(&isp->lock, irqflags);
 976	atomic_set(&asd->sof_count, 0);
 977	atomic_set(&asd->sequence, 0);
 978	atomic_set(&asd->sequence_temp, 0);
 979
 980	asd->params.dis_proj_data_valid = false;
 981	asd->latest_preview_exp_id = 0;
 982	asd->postview_exp_id = 1;
 983	asd->preview_exp_id = 1;
 984
 985	/* handle per_frame_setting parameter and buffers */
 986	atomisp_handle_parameter_and_buffer(pipe);
 987
 988	atomisp_qbuffers_to_css(asd);
 989
 990	atomisp_css_irq_enable(isp, IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF,
 991			       atomisp_css_valid_sof(isp));
 992	atomisp_csi2_configure(asd);
 993
 994	if (atomisp_freq_scaling(isp, ATOMISP_DFS_MODE_AUTO, false) < 0)
 995		dev_dbg(isp->dev, "DFS auto mode failed!\n");
 996
 997	/* Enable the CSI interface on ANN B0/K0 */
 998	if (isp->media_dev.hw_revision >= ((ATOMISP_HW_REVISION_ISP2401 <<
 999					    ATOMISP_HW_REVISION_SHIFT) | ATOMISP_HW_STEPPING_B0)) {
1000		pci_write_config_word(pdev, MRFLD_PCI_CSI_CONTROL,
1001				      isp->saved_regs.csi_control | MRFLD_PCI_CSI_CONTROL_CSI_READY);
1002	}
1003
1004	/* stream on the sensor */
1005	ret = v4l2_subdev_call(isp->inputs[asd->input_curr].csi_remote_source,
1006			       video, s_stream, 1);
1007	if (ret) {
1008		dev_err(isp->dev, "Starting sensor stream failed: %d\n", ret);
1009		atomisp_stop_stream(pipe, false, VB2_BUF_STATE_QUEUED);
1010	}
1011
1012out_unlock:
1013	mutex_unlock(&isp->mutex);
1014	return ret;
1015}
1016
1017void atomisp_stop_streaming(struct vb2_queue *vq)
1018{
1019	struct atomisp_video_pipe *pipe = vq_to_pipe(vq);
1020	struct atomisp_device *isp = pipe->asd->isp;
1021
1022	dev_dbg(isp->dev, "Stop stream\n");
1023
1024	mutex_lock(&isp->mutex);
1025	atomisp_stop_stream(pipe, true, VB2_BUF_STATE_ERROR);
1026	mutex_unlock(&isp->mutex);
1027}
1028
1029/*
1030 * To get the current value of a control.
1031 * applications initialize the id field of a struct v4l2_control and
1032 * call this ioctl with a pointer to this structure
1033 */
1034static int atomisp_g_ctrl(struct file *file, void *fh,
1035			  struct v4l2_control *control)
1036{
1037	struct video_device *vdev = video_devdata(file);
1038	struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd;
1039	int i, ret = -EINVAL;
1040
1041	for (i = 0; i < ctrls_num; i++) {
1042		if (ci_v4l2_controls[i].id == control->id) {
1043			ret = 0;
1044			break;
1045		}
1046	}
1047
1048	if (ret)
1049		return ret;
1050
1051	switch (control->id) {
1052	case V4L2_CID_COLORFX:
1053		ret = atomisp_color_effect(asd, 0, &control->value);
1054		break;
1055	case V4L2_CID_ATOMISP_BAD_PIXEL_DETECTION:
1056		ret = atomisp_bad_pixel(asd, 0, &control->value);
1057		break;
1058	case V4L2_CID_ATOMISP_POSTPROCESS_GDC_CAC:
1059		ret = atomisp_gdc_cac(asd, 0, &control->value);
1060		break;
1061	case V4L2_CID_ATOMISP_VIDEO_STABLIZATION:
1062		ret = atomisp_video_stable(asd, 0, &control->value);
1063		break;
1064	case V4L2_CID_ATOMISP_FIXED_PATTERN_NR:
1065		ret = atomisp_fixed_pattern(asd, 0, &control->value);
1066		break;
1067	case V4L2_CID_ATOMISP_FALSE_COLOR_CORRECTION:
1068		ret = atomisp_false_color(asd, 0, &control->value);
1069		break;
1070	case V4L2_CID_ATOMISP_LOW_LIGHT:
1071		ret = atomisp_low_light(asd, 0, &control->value);
1072		break;
1073	default:
1074		ret = -EINVAL;
1075		break;
1076	}
1077
1078	return ret;
1079}
1080
1081/*
1082 * To change the value of a control.
1083 * applications initialize the id and value fields of a struct v4l2_control
1084 * and call this ioctl.
1085 */
1086static int atomisp_s_ctrl(struct file *file, void *fh,
1087			  struct v4l2_control *control)
1088{
1089	struct video_device *vdev = video_devdata(file);
1090	struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd;
1091	int i, ret = -EINVAL;
1092
1093	for (i = 0; i < ctrls_num; i++) {
1094		if (ci_v4l2_controls[i].id == control->id) {
1095			ret = 0;
1096			break;
1097		}
1098	}
1099
1100	if (ret)
1101		return ret;
1102
1103	switch (control->id) {
1104	case V4L2_CID_COLORFX:
1105		ret = atomisp_color_effect(asd, 1, &control->value);
1106		break;
1107	case V4L2_CID_ATOMISP_BAD_PIXEL_DETECTION:
1108		ret = atomisp_bad_pixel(asd, 1, &control->value);
1109		break;
1110	case V4L2_CID_ATOMISP_POSTPROCESS_GDC_CAC:
1111		ret = atomisp_gdc_cac(asd, 1, &control->value);
1112		break;
1113	case V4L2_CID_ATOMISP_VIDEO_STABLIZATION:
1114		ret = atomisp_video_stable(asd, 1, &control->value);
1115		break;
1116	case V4L2_CID_ATOMISP_FIXED_PATTERN_NR:
1117		ret = atomisp_fixed_pattern(asd, 1, &control->value);
1118		break;
1119	case V4L2_CID_ATOMISP_FALSE_COLOR_CORRECTION:
1120		ret = atomisp_false_color(asd, 1, &control->value);
1121		break;
1122	case V4L2_CID_ATOMISP_LOW_LIGHT:
1123		ret = atomisp_low_light(asd, 1, &control->value);
1124		break;
1125	default:
1126		ret = -EINVAL;
1127		break;
1128	}
1129	return ret;
1130}
1131
1132/*
1133 * To query the attributes of a control.
1134 * applications set the id field of a struct v4l2_query_ext_ctrl and call the
1135 * this ioctl with a pointer to this structure. The driver fills
1136 * the rest of the structure.
1137 */
1138static int atomisp_query_ext_ctrl(struct file *file, void *fh,
1139				  struct v4l2_query_ext_ctrl *qc)
1140{
1141	int i;
1142
1143	/* TODO: implement V4L2_CTRL_FLAG_NEXT_CTRL */
1144	if (qc->id & V4L2_CTRL_FLAG_NEXT_CTRL)
1145		return -EINVAL;
1146
1147	for (i = 0; i < ctrls_num; i++) {
1148		if (ci_v4l2_controls[i].id == qc->id) {
1149			*qc = ci_v4l2_controls[i];
1150			qc->elems = 1;
1151			qc->elem_size = 4;
1152			return 0;
1153		}
1154	}
1155
1156	/*
1157	 * This is probably not needed, but this flag has been set for
1158	 * many kernel versions. Leave it to avoid breaking any apps.
1159	 */
1160	qc->flags = V4L2_CTRL_FLAG_DISABLED;
1161	return -EINVAL;
1162}
1163
1164static int atomisp_camera_g_ext_ctrls(struct file *file, void *fh,
1165				      struct v4l2_ext_controls *c)
1166{
1167	struct video_device *vdev = video_devdata(file);
1168	struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd;
1169	struct v4l2_control ctrl;
1170	int i;
1171	int ret = 0;
1172
1173	for (i = 0; i < c->count; i++) {
1174		ctrl.id = c->controls[i].id;
1175		ctrl.value = c->controls[i].value;
1176		switch (ctrl.id) {
1177		case V4L2_CID_ZOOM_ABSOLUTE:
1178			ret = atomisp_digital_zoom(asd, 0, &ctrl.value);
1179			break;
1180		default:
1181			ret = -EINVAL;
1182		}
1183
1184		if (ret) {
1185			c->error_idx = i;
1186			break;
1187		}
1188		c->controls[i].value = ctrl.value;
1189	}
1190	return ret;
1191}
1192
1193/* This ioctl allows the application to get multiple controls by class */
1194static int atomisp_g_ext_ctrls(struct file *file, void *fh,
1195			       struct v4l2_ext_controls *c)
1196{
1197	struct v4l2_control ctrl;
1198	int i, ret = 0;
1199
1200	/*
1201	 * input_lock is not need for the Camera related IOCTLs
1202	 * The input_lock downgrade the FPS of 3A
1203	 */
1204	ret = atomisp_camera_g_ext_ctrls(file, fh, c);
1205	if (ret != -EINVAL)
1206		return ret;
1207
1208	for (i = 0; i < c->count; i++) {
1209		ctrl.id = c->controls[i].id;
1210		ctrl.value = c->controls[i].value;
1211		ret = atomisp_g_ctrl(file, fh, &ctrl);
1212		c->controls[i].value = ctrl.value;
1213		if (ret) {
1214			c->error_idx = i;
1215			break;
1216		}
1217	}
1218	return ret;
1219}
1220
1221static int atomisp_camera_s_ext_ctrls(struct file *file, void *fh,
1222				      struct v4l2_ext_controls *c)
1223{
1224	struct video_device *vdev = video_devdata(file);
1225	struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd;
1226	struct v4l2_control ctrl;
1227	int i;
1228	int ret = 0;
1229
1230	for (i = 0; i < c->count; i++) {
1231		struct v4l2_ctrl *ctr;
1232
1233		ctrl.id = c->controls[i].id;
1234		ctrl.value = c->controls[i].value;
1235		switch (ctrl.id) {
1236		case V4L2_CID_ZOOM_ABSOLUTE:
1237			ret = atomisp_digital_zoom(asd, 1, &ctrl.value);
1238			break;
1239		default:
1240			ctr = v4l2_ctrl_find(&asd->ctrl_handler, ctrl.id);
1241			if (ctr)
1242				ret = v4l2_ctrl_s_ctrl(ctr, ctrl.value);
1243			else
1244				ret = -EINVAL;
1245		}
1246
1247		if (ret) {
1248			c->error_idx = i;
1249			break;
1250		}
1251		c->controls[i].value = ctrl.value;
1252	}
1253	return ret;
1254}
1255
1256/* This ioctl allows the application to set multiple controls by class */
1257static int atomisp_s_ext_ctrls(struct file *file, void *fh,
1258			       struct v4l2_ext_controls *c)
1259{
1260	struct v4l2_control ctrl;
1261	int i, ret = 0;
1262
1263	/*
1264	 * input_lock is not need for the Camera related IOCTLs
1265	 * The input_lock downgrade the FPS of 3A
1266	 */
1267	ret = atomisp_camera_s_ext_ctrls(file, fh, c);
1268	if (ret != -EINVAL)
1269		return ret;
1270
1271	for (i = 0; i < c->count; i++) {
1272		ctrl.id = c->controls[i].id;
1273		ctrl.value = c->controls[i].value;
1274		ret = atomisp_s_ctrl(file, fh, &ctrl);
1275		c->controls[i].value = ctrl.value;
1276		if (ret) {
1277			c->error_idx = i;
1278			break;
1279		}
1280	}
1281	return ret;
1282}
1283
1284/*
1285 * vidioc_g/s_param are used to switch isp running mode
1286 */
1287static int atomisp_g_parm(struct file *file, void *fh,
1288			  struct v4l2_streamparm *parm)
1289{
1290	struct video_device *vdev = video_devdata(file);
1291	struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd;
1292	struct atomisp_device *isp = video_get_drvdata(vdev);
1293
1294	if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
1295		dev_err(isp->dev, "unsupported v4l2 buf type\n");
1296		return -EINVAL;
1297	}
1298
1299	parm->parm.capture.capturemode = asd->run_mode->val;
1300
1301	return 0;
1302}
1303
1304static int atomisp_s_parm(struct file *file, void *fh,
1305			  struct v4l2_streamparm *parm)
1306{
1307	struct video_device *vdev = video_devdata(file);
1308	struct atomisp_device *isp = video_get_drvdata(vdev);
1309	struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd;
1310	int mode;
1311	int rval;
1312	int fps;
1313
1314	if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
1315		dev_err(isp->dev, "unsupported v4l2 buf type\n");
1316		return -EINVAL;
1317	}
1318
1319	asd->high_speed_mode = false;
1320	switch (parm->parm.capture.capturemode) {
1321	case CI_MODE_NONE: {
1322		struct v4l2_subdev_frame_interval fi = {0};
1323
1324		fi.interval = parm->parm.capture.timeperframe;
1325
1326		rval = v4l2_subdev_call_state_active(isp->inputs[asd->input_curr].csi_remote_source,
1327						     pad, set_frame_interval, &fi);
1328		if (!rval)
1329			parm->parm.capture.timeperframe = fi.interval;
1330
1331		if (fi.interval.numerator != 0) {
1332			fps = fi.interval.denominator / fi.interval.numerator;
1333			if (fps > 30)
1334				asd->high_speed_mode = true;
1335		}
1336
1337		return rval == -ENOIOCTLCMD ? 0 : rval;
1338	}
1339	case CI_MODE_VIDEO:
1340		mode = ATOMISP_RUN_MODE_VIDEO;
1341		break;
1342	case CI_MODE_STILL_CAPTURE:
1343		mode = ATOMISP_RUN_MODE_STILL_CAPTURE;
1344		break;
1345	case CI_MODE_PREVIEW:
1346		mode = ATOMISP_RUN_MODE_PREVIEW;
1347		break;
1348	default:
1349		return -EINVAL;
1350	}
1351
1352	rval = v4l2_ctrl_s_ctrl(asd->run_mode, mode);
1353
1354	return rval == -ENOIOCTLCMD ? 0 : rval;
1355}
1356
1357static long atomisp_vidioc_default(struct file *file, void *fh,
1358				   bool valid_prio, unsigned int cmd, void *arg)
1359{
1360	struct video_device *vdev = video_devdata(file);
1361	struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd;
1362	int err;
1363
1364	switch (cmd) {
1365	case ATOMISP_IOC_G_XNR:
1366		err = atomisp_xnr(asd, 0, arg);
1367		break;
1368
1369	case ATOMISP_IOC_S_XNR:
1370		err = atomisp_xnr(asd, 1, arg);
1371		break;
1372
1373	case ATOMISP_IOC_G_NR:
1374		err = atomisp_nr(asd, 0, arg);
1375		break;
1376
1377	case ATOMISP_IOC_S_NR:
1378		err = atomisp_nr(asd, 1, arg);
1379		break;
1380
1381	case ATOMISP_IOC_G_TNR:
1382		err = atomisp_tnr(asd, 0, arg);
1383		break;
1384
1385	case ATOMISP_IOC_S_TNR:
1386		err = atomisp_tnr(asd, 1, arg);
1387		break;
1388
1389	case ATOMISP_IOC_G_BLACK_LEVEL_COMP:
1390		err = atomisp_black_level(asd, 0, arg);
1391		break;
1392
1393	case ATOMISP_IOC_S_BLACK_LEVEL_COMP:
1394		err = atomisp_black_level(asd, 1, arg);
1395		break;
1396
1397	case ATOMISP_IOC_G_EE:
1398		err = atomisp_ee(asd, 0, arg);
1399		break;
1400
1401	case ATOMISP_IOC_S_EE:
1402		err = atomisp_ee(asd, 1, arg);
1403		break;
1404
1405	case ATOMISP_IOC_G_DIS_STAT:
1406		err = atomisp_get_dis_stat(asd, arg);
1407		break;
1408
1409	case ATOMISP_IOC_G_DVS2_BQ_RESOLUTIONS:
1410		err = atomisp_get_dvs2_bq_resolutions(asd, arg);
1411		break;
1412
1413	case ATOMISP_IOC_S_DIS_COEFS:
1414		err = atomisp_css_cp_dvs2_coefs(asd, arg,
1415						&asd->params.css_param, true);
1416		if (!err && arg)
1417			asd->params.css_update_params_needed = true;
1418		break;
1419
1420	case ATOMISP_IOC_S_DIS_VECTOR:
1421		err = atomisp_cp_dvs_6axis_config(asd, arg,
1422						  &asd->params.css_param, true);
1423		if (!err && arg)
1424			asd->params.css_update_params_needed = true;
1425		break;
1426
1427	case ATOMISP_IOC_G_ISP_PARM:
1428		err = atomisp_param(asd, 0, arg);
1429		break;
1430
1431	case ATOMISP_IOC_S_ISP_PARM:
1432		err = atomisp_param(asd, 1, arg);
1433		break;
1434
1435	case ATOMISP_IOC_G_3A_STAT:
1436		err = atomisp_3a_stat(asd, 0, arg);
1437		break;
1438
1439	case ATOMISP_IOC_G_ISP_GAMMA:
1440		err = atomisp_gamma(asd, 0, arg);
1441		break;
1442
1443	case ATOMISP_IOC_S_ISP_GAMMA:
1444		err = atomisp_gamma(asd, 1, arg);
1445		break;
1446
1447	case ATOMISP_IOC_G_ISP_GDC_TAB:
1448		err = atomisp_gdc_cac_table(asd, 0, arg);
1449		break;
1450
1451	case ATOMISP_IOC_S_ISP_GDC_TAB:
1452		err = atomisp_gdc_cac_table(asd, 1, arg);
1453		break;
1454
1455	case ATOMISP_IOC_G_ISP_MACC:
1456		err = atomisp_macc_table(asd, 0, arg);
1457		break;
1458
1459	case ATOMISP_IOC_S_ISP_MACC:
1460		err = atomisp_macc_table(asd, 1, arg);
1461		break;
1462
1463	case ATOMISP_IOC_G_ISP_BAD_PIXEL_DETECTION:
1464		err = atomisp_bad_pixel_param(asd, 0, arg);
1465		break;
1466
1467	case ATOMISP_IOC_S_ISP_BAD_PIXEL_DETECTION:
1468		err = atomisp_bad_pixel_param(asd, 1, arg);
1469		break;
1470
1471	case ATOMISP_IOC_G_ISP_FALSE_COLOR_CORRECTION:
1472		err = atomisp_false_color_param(asd, 0, arg);
1473		break;
1474
1475	case ATOMISP_IOC_S_ISP_FALSE_COLOR_CORRECTION:
1476		err = atomisp_false_color_param(asd, 1, arg);
1477		break;
1478
1479	case ATOMISP_IOC_G_ISP_CTC:
1480		err = atomisp_ctc(asd, 0, arg);
1481		break;
1482
1483	case ATOMISP_IOC_S_ISP_CTC:
1484		err = atomisp_ctc(asd, 1, arg);
1485		break;
1486
1487	case ATOMISP_IOC_G_ISP_WHITE_BALANCE:
1488		err = atomisp_white_balance_param(asd, 0, arg);
1489		break;
1490
1491	case ATOMISP_IOC_S_ISP_WHITE_BALANCE:
1492		err = atomisp_white_balance_param(asd, 1, arg);
1493		break;
1494
1495	case ATOMISP_IOC_G_3A_CONFIG:
1496		err = atomisp_3a_config_param(asd, 0, arg);
1497		break;
1498
1499	case ATOMISP_IOC_S_3A_CONFIG:
1500		err = atomisp_3a_config_param(asd, 1, arg);
1501		break;
1502
1503	case ATOMISP_IOC_S_ISP_FPN_TABLE:
1504		err = atomisp_fixed_pattern_table(asd, arg);
1505		break;
1506
1507	case ATOMISP_IOC_S_ISP_SHD_TAB:
1508		err = atomisp_set_shading_table(asd, arg);
1509		break;
1510
1511	case ATOMISP_IOC_G_ISP_GAMMA_CORRECTION:
1512		err = atomisp_gamma_correction(asd, 0, arg);
1513		break;
1514
1515	case ATOMISP_IOC_S_ISP_GAMMA_CORRECTION:
1516		err = atomisp_gamma_correction(asd, 1, arg);
1517		break;
1518
1519	case ATOMISP_IOC_S_PARAMETERS:
1520		err = atomisp_set_parameters(vdev, arg);
1521		break;
1522
1523	case ATOMISP_IOC_EXP_ID_UNLOCK:
1524		err = atomisp_exp_id_unlock(asd, arg);
1525		break;
1526	case ATOMISP_IOC_EXP_ID_CAPTURE:
1527		err = atomisp_exp_id_capture(asd, arg);
1528		break;
1529	case ATOMISP_IOC_S_ENABLE_DZ_CAPT_PIPE:
1530		err = atomisp_enable_dz_capt_pipe(asd, arg);
1531		break;
1532	case ATOMISP_IOC_G_FORMATS_CONFIG:
1533		err = atomisp_formats(asd, 0, arg);
1534		break;
1535
1536	case ATOMISP_IOC_S_FORMATS_CONFIG:
1537		err = atomisp_formats(asd, 1, arg);
1538		break;
1539	case ATOMISP_IOC_INJECT_A_FAKE_EVENT:
1540		err = atomisp_inject_a_fake_event(asd, arg);
1541		break;
1542	case ATOMISP_IOC_S_ARRAY_RESOLUTION:
1543		err = atomisp_set_array_res(asd, arg);
1544		break;
1545	default:
1546		err = -EINVAL;
1547		break;
1548	}
1549
1550	return err;
1551}
1552
1553const struct v4l2_ioctl_ops atomisp_ioctl_ops = {
1554	.vidioc_querycap = atomisp_querycap,
1555	.vidioc_enum_input = atomisp_enum_input,
1556	.vidioc_g_input = atomisp_g_input,
1557	.vidioc_s_input = atomisp_s_input,
1558	.vidioc_query_ext_ctrl = atomisp_query_ext_ctrl,
1559	.vidioc_s_ext_ctrls = atomisp_s_ext_ctrls,
1560	.vidioc_g_ext_ctrls = atomisp_g_ext_ctrls,
1561	.vidioc_enum_framesizes   = atomisp_enum_framesizes,
1562	.vidioc_enum_frameintervals = atomisp_enum_frameintervals,
1563	.vidioc_enum_fmt_vid_cap = atomisp_enum_fmt_cap,
1564	.vidioc_try_fmt_vid_cap = atomisp_try_fmt_cap,
1565	.vidioc_g_fmt_vid_cap = atomisp_g_fmt_cap,
1566	.vidioc_s_fmt_vid_cap = atomisp_s_fmt_cap,
1567	.vidioc_reqbufs = vb2_ioctl_reqbufs,
1568	.vidioc_querybuf = vb2_ioctl_querybuf,
1569	.vidioc_qbuf = atomisp_qbuf_wrapper,
1570	.vidioc_dqbuf = atomisp_dqbuf_wrapper,
1571	.vidioc_expbuf = vb2_ioctl_expbuf,
1572	.vidioc_streamon = vb2_ioctl_streamon,
1573	.vidioc_streamoff = vb2_ioctl_streamoff,
1574	.vidioc_default = atomisp_vidioc_default,
1575	.vidioc_s_parm = atomisp_s_parm,
1576	.vidioc_g_parm = atomisp_g_parm,
1577};
~/ Read-only file preview.