File Index
Files and directories
Sign in
FILE

alvium-csi2.c

File preview with syntax highlighting.

linux-6.19.14/drivers/media/i2c/alvium-csi2.c C
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Allied Vision Technologies GmbH Alvium camera driver
   4 *
   5 * Copyright (C) 2023 Tommaso Merciai
   6 * Copyright (C) 2023 Martin Hecht
   7 * Copyright (C) 2023 Avnet EMG GmbH
   8 */
   9
  10#include <linux/i2c.h>
  11#include <linux/module.h>
  12#include <linux/pm_runtime.h>
  13#include <linux/regmap.h>
  14#include <linux/regulator/consumer.h>
  15#include <media/mipi-csi2.h>
  16#include <media/v4l2-async.h>
  17#include <media/v4l2-ctrls.h>
  18#include <media/v4l2-device.h>
  19#include <media/v4l2-fwnode.h>
  20#include <media/v4l2-subdev.h>
  21
  22#include "alvium-csi2.h"
  23
  24static const struct v4l2_mbus_framefmt alvium_csi2_default_fmt = {
  25	.code = MEDIA_BUS_FMT_UYVY8_1X16,
  26	.width = 640,
  27	.height = 480,
  28	.colorspace = V4L2_COLORSPACE_SRGB,
  29	.ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(V4L2_COLORSPACE_SRGB),
  30	.quantization = V4L2_QUANTIZATION_FULL_RANGE,
  31	.xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(V4L2_COLORSPACE_SRGB),
  32	.field = V4L2_FIELD_NONE,
  33};
  34
  35static const struct alvium_pixfmt alvium_csi2_fmts[] = {
  36	{
  37		/* UYVY8_2X8 */
  38		.id = ALVIUM_FMT_UYVY8_2X8,
  39		.code = MEDIA_BUS_FMT_UYVY8_2X8,
  40		.colorspace = V4L2_COLORSPACE_SRGB,
  41		.fmt_av_bit = ALVIUM_BIT_YUV422_8,
  42		.bay_av_bit = ALVIUM_BIT_BAY_NONE,
  43		.mipi_fmt_regval = MIPI_CSI2_DT_YUV422_8B,
  44		.bay_fmt_regval = -1,
  45		.is_raw = 0,
  46	}, {
  47		/* UYVY8_1X16 */
  48		.id = ALVIUM_FMT_UYVY8_1X16,
  49		.code = MEDIA_BUS_FMT_UYVY8_1X16,
  50		.colorspace = V4L2_COLORSPACE_SRGB,
  51		.fmt_av_bit = ALVIUM_BIT_YUV422_8,
  52		.bay_av_bit = ALVIUM_BIT_BAY_NONE,
  53		.mipi_fmt_regval = MIPI_CSI2_DT_YUV422_8B,
  54		.bay_fmt_regval = -1,
  55		.is_raw = 0,
  56	}, {
  57		/* YUYV8_1X16 */
  58		.id = ALVIUM_FMT_YUYV8_1X16,
  59		.code = MEDIA_BUS_FMT_YUYV8_1X16,
  60		.colorspace = V4L2_COLORSPACE_SRGB,
  61		.fmt_av_bit = ALVIUM_BIT_YUV422_8,
  62		.bay_av_bit = ALVIUM_BIT_BAY_NONE,
  63		.mipi_fmt_regval = MIPI_CSI2_DT_YUV422_8B,
  64		.bay_fmt_regval = -1,
  65		.is_raw = 0,
  66	}, {
  67		/* YUYV8_2X8 */
  68		.id = ALVIUM_FMT_YUYV8_2X8,
  69		.code = MEDIA_BUS_FMT_YUYV8_2X8,
  70		.colorspace = V4L2_COLORSPACE_SRGB,
  71		.fmt_av_bit = ALVIUM_BIT_YUV422_8,
  72		.bay_av_bit = ALVIUM_BIT_BAY_NONE,
  73		.mipi_fmt_regval = MIPI_CSI2_DT_YUV422_8B,
  74		.bay_fmt_regval = -1,
  75		.is_raw = 0,
  76	}, {
  77		/* YUYV10_1X20 */
  78		.id = ALVIUM_FMT_YUYV10_1X20,
  79		.code = MEDIA_BUS_FMT_YUYV10_1X20,
  80		.colorspace = V4L2_COLORSPACE_SRGB,
  81		.fmt_av_bit = ALVIUM_BIT_YUV422_10,
  82		.bay_av_bit = ALVIUM_BIT_BAY_NONE,
  83		.mipi_fmt_regval = MIPI_CSI2_DT_YUV422_10B,
  84		.bay_fmt_regval = -1,
  85		.is_raw = 0,
  86	}, {
  87		/* RGB888_1X24 */
  88		.id = ALVIUM_FMT_RGB888_1X24,
  89		.code = MEDIA_BUS_FMT_RGB888_1X24,
  90		.colorspace = V4L2_COLORSPACE_SRGB,
  91		.fmt_av_bit = ALVIUM_BIT_RGB888,
  92		.bay_av_bit = ALVIUM_BIT_BAY_NONE,
  93		.mipi_fmt_regval = MIPI_CSI2_DT_RGB888,
  94		.bay_fmt_regval = -1,
  95		.is_raw = 0,
  96	}, {
  97		/* RBG888_1X24 */
  98		.id = ALVIUM_FMT_RBG888_1X24,
  99		.code = MEDIA_BUS_FMT_RBG888_1X24,
 100		.colorspace = V4L2_COLORSPACE_SRGB,
 101		.fmt_av_bit = ALVIUM_BIT_RGB888,
 102		.bay_av_bit = ALVIUM_BIT_BAY_NONE,
 103		.mipi_fmt_regval = MIPI_CSI2_DT_RGB888,
 104		.bay_fmt_regval = -1,
 105		.is_raw = 0,
 106	}, {
 107		/* BGR888_1X24 */
 108		.id = ALVIUM_FMT_BGR888_1X24,
 109		.code = MEDIA_BUS_FMT_BGR888_1X24,
 110		.colorspace = V4L2_COLORSPACE_SRGB,
 111		.fmt_av_bit = ALVIUM_BIT_RGB888,
 112		.bay_av_bit = ALVIUM_BIT_BAY_NONE,
 113		.mipi_fmt_regval = MIPI_CSI2_DT_RGB888,
 114		.bay_fmt_regval = -1,
 115		.is_raw = 0,
 116	}, {
 117		/* RGB888_3X8 */
 118		.id = ALVIUM_FMT_RGB888_3X8,
 119		.code = MEDIA_BUS_FMT_RGB888_3X8,
 120		.colorspace = V4L2_COLORSPACE_SRGB,
 121		.fmt_av_bit = ALVIUM_BIT_RGB888,
 122		.bay_av_bit = ALVIUM_BIT_BAY_NONE,
 123		.mipi_fmt_regval = MIPI_CSI2_DT_RGB888,
 124		.bay_fmt_regval = -1,
 125		.is_raw = 0,
 126	}, {
 127		/* Y8_1X8 */
 128		.id = ALVIUM_FMT_Y8_1X8,
 129		.code = MEDIA_BUS_FMT_Y8_1X8,
 130		.colorspace = V4L2_COLORSPACE_RAW,
 131		.fmt_av_bit = ALVIUM_BIT_RAW8,
 132		.bay_av_bit = ALVIUM_BIT_BAY_MONO,
 133		.mipi_fmt_regval = MIPI_CSI2_DT_RAW8,
 134		.bay_fmt_regval = 0x00,
 135		.is_raw = 1,
 136	}, {
 137		/* SGRBG8_1X8 */
 138		.id = ALVIUM_FMT_SGRBG8_1X8,
 139		.code = MEDIA_BUS_FMT_SGRBG8_1X8,
 140		.colorspace = V4L2_COLORSPACE_RAW,
 141		.fmt_av_bit = ALVIUM_BIT_RAW8,
 142		.bay_av_bit = ALVIUM_BIT_BAY_GR,
 143		.mipi_fmt_regval = MIPI_CSI2_DT_RAW8,
 144		.bay_fmt_regval = 0x01,
 145		.is_raw = 1,
 146	}, {
 147		/* SRGGB8_1X8 */
 148		.id = ALVIUM_FMT_SRGGB8_1X8,
 149		.code = MEDIA_BUS_FMT_SRGGB8_1X8,
 150		.colorspace = V4L2_COLORSPACE_RAW,
 151		.fmt_av_bit = ALVIUM_BIT_RAW8,
 152		.bay_av_bit = ALVIUM_BIT_BAY_RG,
 153		.mipi_fmt_regval = MIPI_CSI2_DT_RAW8,
 154		.bay_fmt_regval = 0x02,
 155		.is_raw = 1,
 156	}, {
 157		/* SGBRG8_1X8 */
 158		.id = ALVIUM_FMT_SGBRG8_1X8,
 159		.code = MEDIA_BUS_FMT_SGBRG8_1X8,
 160		.colorspace = V4L2_COLORSPACE_RAW,
 161		.fmt_av_bit = ALVIUM_BIT_RAW8,
 162		.bay_av_bit = ALVIUM_BIT_BAY_GB,
 163		.mipi_fmt_regval = MIPI_CSI2_DT_RAW8,
 164		.bay_fmt_regval = 0x03,
 165		.is_raw = 1,
 166	}, {
 167		/* SBGGR8_1X8 */
 168		.id = ALVIUM_FMT_SBGGR8_1X8,
 169		.code = MEDIA_BUS_FMT_SBGGR8_1X8,
 170		.colorspace = V4L2_COLORSPACE_RAW,
 171		.fmt_av_bit = ALVIUM_BIT_RAW8,
 172		.bay_av_bit = ALVIUM_BIT_BAY_BG,
 173		.mipi_fmt_regval = MIPI_CSI2_DT_RAW8,
 174		.bay_fmt_regval = 0x04,
 175		.is_raw = 1,
 176	}, {
 177		/* Y10_1X10 */
 178		.id = ALVIUM_FMT_Y10_1X10,
 179		.code = MEDIA_BUS_FMT_Y10_1X10,
 180		.colorspace = V4L2_COLORSPACE_RAW,
 181		.fmt_av_bit = ALVIUM_BIT_RAW10,
 182		.bay_av_bit = ALVIUM_BIT_BAY_MONO,
 183		.mipi_fmt_regval = MIPI_CSI2_DT_RAW10,
 184		.bay_fmt_regval = 0x00,
 185		.is_raw = 1,
 186	}, {
 187		/* SGRBG10_1X10 */
 188		.id = ALVIUM_FMT_SGRBG10_1X10,
 189		.code = MEDIA_BUS_FMT_SGRBG10_1X10,
 190		.colorspace = V4L2_COLORSPACE_RAW,
 191		.fmt_av_bit = ALVIUM_BIT_RAW10,
 192		.bay_av_bit = ALVIUM_BIT_BAY_GR,
 193		.mipi_fmt_regval = MIPI_CSI2_DT_RAW10,
 194		.bay_fmt_regval = 0x01,
 195		.is_raw = 1,
 196	}, {
 197		/* SRGGB10_1X10 */
 198		.id = ALVIUM_FMT_SRGGB10_1X10,
 199		.code = MEDIA_BUS_FMT_SRGGB10_1X10,
 200		.colorspace = V4L2_COLORSPACE_RAW,
 201		.fmt_av_bit = ALVIUM_BIT_RAW10,
 202		.bay_av_bit = ALVIUM_BIT_BAY_RG,
 203		.mipi_fmt_regval = MIPI_CSI2_DT_RAW10,
 204		.bay_fmt_regval = 0x02,
 205		.is_raw = 1,
 206	}, {
 207		/* SGBRG10_1X10 */
 208		.id = ALVIUM_FMT_SGBRG10_1X10,
 209		.code = MEDIA_BUS_FMT_SGBRG10_1X10,
 210		.colorspace = V4L2_COLORSPACE_RAW,
 211		.fmt_av_bit = ALVIUM_BIT_RAW10,
 212		.bay_av_bit = ALVIUM_BIT_BAY_GB,
 213		.mipi_fmt_regval = MIPI_CSI2_DT_RAW10,
 214		.bay_fmt_regval = 0x03,
 215		.is_raw = 1,
 216	}, {
 217		/* SBGGR10_1X10 */
 218		.id = ALVIUM_FMT_SBGGR10_1X10,
 219		.code = MEDIA_BUS_FMT_SBGGR10_1X10,
 220		.colorspace = V4L2_COLORSPACE_RAW,
 221		.fmt_av_bit = ALVIUM_BIT_RAW10,
 222		.bay_av_bit = ALVIUM_BIT_BAY_BG,
 223		.mipi_fmt_regval = MIPI_CSI2_DT_RAW10,
 224		.bay_fmt_regval = 0x04,
 225		.is_raw = 1,
 226	}, {
 227		/* Y12_1X12 */
 228		.id = ALVIUM_FMT_Y12_1X12,
 229		.code = MEDIA_BUS_FMT_Y12_1X12,
 230		.colorspace = V4L2_COLORSPACE_RAW,
 231		.fmt_av_bit = ALVIUM_BIT_RAW12,
 232		.bay_av_bit = ALVIUM_BIT_BAY_MONO,
 233		.mipi_fmt_regval = MIPI_CSI2_DT_RAW12,
 234		.bay_fmt_regval = 0x00,
 235		.is_raw = 1,
 236	}, {
 237		/* SGRBG12_1X12 */
 238		.id = ALVIUM_FMT_SGRBG12_1X12,
 239		.code = MEDIA_BUS_FMT_SGRBG12_1X12,
 240		.colorspace = V4L2_COLORSPACE_RAW,
 241		.fmt_av_bit = ALVIUM_BIT_RAW12,
 242		.bay_av_bit = ALVIUM_BIT_BAY_GR,
 243		.mipi_fmt_regval = MIPI_CSI2_DT_RAW12,
 244		.bay_fmt_regval = 0x01,
 245		.is_raw = 1,
 246	}, {
 247		/* SRGGB12_1X12 */
 248		.id = ALVIUM_FMT_SRGGB12_1X12,
 249		.code = MEDIA_BUS_FMT_SRGGB12_1X12,
 250		.colorspace = V4L2_COLORSPACE_RAW,
 251		.fmt_av_bit = ALVIUM_BIT_RAW12,
 252		.bay_av_bit = ALVIUM_BIT_BAY_RG,
 253		.mipi_fmt_regval = MIPI_CSI2_DT_RAW12,
 254		.bay_fmt_regval = 0x02,
 255		.is_raw = 1,
 256	}, {
 257		/* SGBRG12_1X12 */
 258		.id = ALVIUM_FMT_SGBRG12_1X12,
 259		.code = MEDIA_BUS_FMT_SGBRG12_1X12,
 260		.colorspace = V4L2_COLORSPACE_RAW,
 261		.fmt_av_bit = ALVIUM_BIT_RAW12,
 262		.bay_av_bit = ALVIUM_BIT_BAY_GB,
 263		.mipi_fmt_regval = MIPI_CSI2_DT_RAW12,
 264		.bay_fmt_regval = 0x03,
 265		.is_raw = 1,
 266	}, {
 267		/* SBGGR12_1X12 */
 268		.id = ALVIUM_FMT_SBGGR12_1X12,
 269		.code = MEDIA_BUS_FMT_SBGGR12_1X12,
 270		.colorspace = V4L2_COLORSPACE_RAW,
 271		.fmt_av_bit = ALVIUM_BIT_RAW12,
 272		.bay_av_bit = ALVIUM_BIT_BAY_BG,
 273		.mipi_fmt_regval = MIPI_CSI2_DT_RAW12,
 274		.bay_fmt_regval = 0x04,
 275		.is_raw = 1,
 276	}, {
 277		/* SBGGR14_1X14 */
 278		.id = ALVIUM_FMT_SBGGR14_1X14,
 279		.code = MEDIA_BUS_FMT_SBGGR14_1X14,
 280		.colorspace = V4L2_COLORSPACE_RAW,
 281		.fmt_av_bit = ALVIUM_BIT_RAW14,
 282		.bay_av_bit = ALVIUM_BIT_BAY_GR,
 283		.mipi_fmt_regval = MIPI_CSI2_DT_RAW14,
 284		.bay_fmt_regval = 0x01,
 285		.is_raw = 1,
 286	}, {
 287		/* SGBRG14_1X14 */
 288		.id = ALVIUM_FMT_SGBRG14_1X14,
 289		.code = MEDIA_BUS_FMT_SGBRG14_1X14,
 290		.colorspace = V4L2_COLORSPACE_RAW,
 291		.fmt_av_bit = ALVIUM_BIT_RAW14,
 292		.bay_av_bit = ALVIUM_BIT_BAY_RG,
 293		.mipi_fmt_regval = MIPI_CSI2_DT_RAW14,
 294		.bay_fmt_regval = 0x02,
 295		.is_raw = 1,
 296	}, {
 297		/* SRGGB14_1X14 */
 298		.id = ALVIUM_FMT_SRGGB14_1X14,
 299		.code = MEDIA_BUS_FMT_SRGGB14_1X14,
 300		.colorspace = V4L2_COLORSPACE_RAW,
 301		.fmt_av_bit = ALVIUM_BIT_RAW14,
 302		.bay_av_bit = ALVIUM_BIT_BAY_GB,
 303		.mipi_fmt_regval = MIPI_CSI2_DT_RAW14,
 304		.bay_fmt_regval = 0x03,
 305		.is_raw = 1,
 306	}, {
 307		/* SGRBG14_1X14 */
 308		.id = ALVIUM_FMT_SGRBG14_1X14,
 309		.code = MEDIA_BUS_FMT_SGRBG14_1X14,
 310		.colorspace = V4L2_COLORSPACE_RAW,
 311		.fmt_av_bit = ALVIUM_BIT_RAW14,
 312		.bay_av_bit = ALVIUM_BIT_BAY_BG,
 313		.mipi_fmt_regval = MIPI_CSI2_DT_RAW14,
 314		.bay_fmt_regval = 0x04,
 315		.is_raw = 1,
 316	},
 317	{ /* sentinel */ }
 318};
 319
 320static int alvium_read(struct alvium_dev *alvium, u32 reg, u64 *val, int *err)
 321{
 322	if (reg & REG_BCRM_V4L2) {
 323		reg &= ~REG_BCRM_V4L2;
 324		reg += alvium->bcrm_addr;
 325	}
 326
 327	return cci_read(alvium->regmap, reg, val, err);
 328}
 329
 330static int alvium_write(struct alvium_dev *alvium, u32 reg, u64 val, int *err)
 331{
 332	if (reg & REG_BCRM_V4L2) {
 333		reg &= ~REG_BCRM_V4L2;
 334		reg += alvium->bcrm_addr;
 335	}
 336
 337	return cci_write(alvium->regmap, reg, val, err);
 338}
 339
 340static int alvium_write_hshake(struct alvium_dev *alvium, u32 reg, u64 val)
 341{
 342	struct device *dev = &alvium->i2c_client->dev;
 343	u64 hshake_bit;
 344	int ret = 0;
 345
 346	/* reset handshake bit and write alvium reg */
 347	alvium_write(alvium, REG_BCRM_WRITE_HANDSHAKE_RW, 0, &ret);
 348	alvium_write(alvium, reg, val, &ret);
 349	if (ret) {
 350		dev_err(dev, "Fail to write reg\n");
 351		return ret;
 352	}
 353
 354	/* poll handshake bit since bit0 = 1 */
 355	read_poll_timeout(alvium_read, hshake_bit,
 356			  ((hshake_bit & BCRM_HANDSHAKE_W_DONE_EN_BIT) == 1),
 357			  15000, 45000, true,
 358			  alvium, REG_BCRM_WRITE_HANDSHAKE_RW,
 359			  &hshake_bit, &ret);
 360	if (ret) {
 361		dev_err(dev, "poll bit[0] = 1, hshake reg fail\n");
 362		return ret;
 363	}
 364
 365	/* reset handshake bit, write 0 to bit0 */
 366	alvium_write(alvium, REG_BCRM_WRITE_HANDSHAKE_RW, 0, &ret);
 367	if (ret) {
 368		dev_err(dev, "Fail to reset hshake reg\n");
 369		return ret;
 370	}
 371
 372	/* poll handshake bit since bit0 = 0 */
 373	read_poll_timeout(alvium_read, hshake_bit,
 374			  ((hshake_bit & BCRM_HANDSHAKE_W_DONE_EN_BIT) == 0),
 375			  15000, 45000, true,
 376			  alvium, REG_BCRM_WRITE_HANDSHAKE_RW,
 377			  &hshake_bit, &ret);
 378	if (ret) {
 379		dev_err(dev, "poll bit[0] = 0, hshake reg fail\n");
 380		return ret;
 381	}
 382
 383	return 0;
 384}
 385
 386static int alvium_get_bcrm_vers(struct alvium_dev *alvium)
 387{
 388	struct device *dev = &alvium->i2c_client->dev;
 389	u64 min, maj;
 390	int ret = 0;
 391
 392	ret = alvium_read(alvium, REG_BCRM_MINOR_VERSION_R, &min, &ret);
 393	ret = alvium_read(alvium, REG_BCRM_MAJOR_VERSION_R, &maj, &ret);
 394	if (ret)
 395		return ret;
 396
 397	dev_info(dev, "bcrm version: %llu.%llu\n", min, maj);
 398
 399	return 0;
 400}
 401
 402static int alvium_get_fw_version(struct alvium_dev *alvium)
 403{
 404	struct device *dev = &alvium->i2c_client->dev;
 405	u64 val;
 406	int ret;
 407
 408	ret = alvium_read(alvium, REG_BCRM_DEVICE_FW, &val, NULL);
 409	if (ret)
 410		return ret;
 411
 412	dev_info(dev, "fw version: %02u.%02u.%04u.%08x\n",
 413		 (u8)((val & BCRM_DEVICE_FW_SPEC_MASK) >>
 414		       BCRM_DEVICE_FW_SPEC_SHIFT),
 415		 (u8)((val & BCRM_DEVICE_FW_MAJOR_MASK) >>
 416		       BCRM_DEVICE_FW_MAJOR_SHIFT),
 417		 (u16)((val & BCRM_DEVICE_FW_MINOR_MASK) >>
 418			BCRM_DEVICE_FW_MINOR_SHIFT),
 419		 (u32)((val & BCRM_DEVICE_FW_PATCH_MASK) >>
 420			BCRM_DEVICE_FW_PATCH_SHIFT));
 421
 422	return 0;
 423}
 424
 425static int alvium_get_bcrm_addr(struct alvium_dev *alvium)
 426{
 427	u64 val;
 428	int ret;
 429
 430	ret = alvium_read(alvium, REG_BCRM_REG_ADDR_R, &val, NULL);
 431	if (ret)
 432		return ret;
 433
 434	alvium->bcrm_addr = val;
 435
 436	return 0;
 437}
 438
 439static int alvium_is_alive(struct alvium_dev *alvium)
 440{
 441	u64 bcrm, hbeat;
 442	int ret = 0;
 443
 444	alvium_read(alvium, REG_BCRM_MINOR_VERSION_R, &bcrm, &ret);
 445	alvium_read(alvium, REG_BCRM_HEARTBEAT_RW, &hbeat, &ret);
 446	if (ret)
 447		return ret;
 448
 449	return hbeat;
 450}
 451
 452static void alvium_print_avail_mipi_fmt(struct alvium_dev *alvium)
 453{
 454	struct device *dev = &alvium->i2c_client->dev;
 455
 456	dev_dbg(dev, "avail mipi_fmt yuv420_8_leg: %u\n",
 457		alvium->is_mipi_fmt_avail[ALVIUM_BIT_YUV420_8_LEG]);
 458	dev_dbg(dev, "avail mipi_fmt yuv420_8: %u\n",
 459		alvium->is_mipi_fmt_avail[ALVIUM_BIT_YUV420_8]);
 460	dev_dbg(dev, "avail mipi_fmt yuv420_10: %u\n",
 461		alvium->is_mipi_fmt_avail[ALVIUM_BIT_YUV420_10]);
 462	dev_dbg(dev, "avail mipi_fmt yuv420_8_csps: %u\n",
 463		alvium->is_mipi_fmt_avail[ALVIUM_BIT_YUV420_8_CSPS]);
 464	dev_dbg(dev, "avail mipi_fmt yuv420_10_csps: %u\n",
 465		alvium->is_mipi_fmt_avail[ALVIUM_BIT_YUV420_10_CSPS]);
 466	dev_dbg(dev, "avail mipi_fmt yuv422_8: %u\n",
 467		alvium->is_mipi_fmt_avail[ALVIUM_BIT_YUV422_8]);
 468	dev_dbg(dev, "avail mipi_fmt yuv422_10: %u\n",
 469		alvium->is_mipi_fmt_avail[ALVIUM_BIT_YUV422_10]);
 470	dev_dbg(dev, "avail mipi_fmt rgb888: %u\n",
 471		alvium->is_mipi_fmt_avail[ALVIUM_BIT_RGB888]);
 472	dev_dbg(dev, "avail mipi_fmt rgb666: %u\n",
 473		alvium->is_mipi_fmt_avail[ALVIUM_BIT_RGB666]);
 474	dev_dbg(dev, "avail mipi_fmt rgb565: %u\n",
 475		alvium->is_mipi_fmt_avail[ALVIUM_BIT_RGB565]);
 476	dev_dbg(dev, "avail mipi_fmt rgb555: %u\n",
 477		alvium->is_mipi_fmt_avail[ALVIUM_BIT_RGB555]);
 478	dev_dbg(dev, "avail mipi_fmt rgb444: %u\n",
 479		alvium->is_mipi_fmt_avail[ALVIUM_BIT_RGB444]);
 480	dev_dbg(dev, "avail mipi_fmt raw6: %u\n",
 481		alvium->is_mipi_fmt_avail[ALVIUM_BIT_RAW6]);
 482	dev_dbg(dev, "avail mipi_fmt raw7: %u\n",
 483		alvium->is_mipi_fmt_avail[ALVIUM_BIT_RAW7]);
 484	dev_dbg(dev, "avail mipi_fmt raw8: %u\n",
 485		alvium->is_mipi_fmt_avail[ALVIUM_BIT_RAW8]);
 486	dev_dbg(dev, "avail mipi_fmt raw10: %u\n",
 487		alvium->is_mipi_fmt_avail[ALVIUM_BIT_RAW10]);
 488	dev_dbg(dev, "avail mipi_fmt raw12: %u\n",
 489		alvium->is_mipi_fmt_avail[ALVIUM_BIT_RAW12]);
 490	dev_dbg(dev, "avail mipi_fmt raw14: %u\n",
 491		alvium->is_mipi_fmt_avail[ALVIUM_BIT_RAW14]);
 492	dev_dbg(dev, "avail mipi_fmt jpeg: %u\n",
 493		alvium->is_mipi_fmt_avail[ALVIUM_BIT_JPEG]);
 494}
 495
 496static void alvium_print_avail_feat(struct alvium_dev *alvium)
 497{
 498	struct device *dev = &alvium->i2c_client->dev;
 499
 500	dev_dbg(dev, "feature rev_x: %u\n", alvium->avail_ft.rev_x);
 501	dev_dbg(dev, "feature rev_y: %u\n", alvium->avail_ft.rev_y);
 502	dev_dbg(dev, "feature int_autop: %u\n", alvium->avail_ft.int_autop);
 503	dev_dbg(dev, "feature black_lvl: %u\n", alvium->avail_ft.black_lvl);
 504	dev_dbg(dev, "feature gain: %u\n", alvium->avail_ft.gain);
 505	dev_dbg(dev, "feature gamma: %u\n", alvium->avail_ft.gamma);
 506	dev_dbg(dev, "feature contrast: %u\n", alvium->avail_ft.contrast);
 507	dev_dbg(dev, "feature sat: %u\n", alvium->avail_ft.sat);
 508	dev_dbg(dev, "feature hue: %u\n", alvium->avail_ft.hue);
 509	dev_dbg(dev, "feature whiteb: %u\n", alvium->avail_ft.whiteb);
 510	dev_dbg(dev, "feature sharp: %u\n", alvium->avail_ft.sharp);
 511	dev_dbg(dev, "feature auto_exp: %u\n", alvium->avail_ft.auto_exp);
 512	dev_dbg(dev, "feature auto_gain: %u\n", alvium->avail_ft.auto_gain);
 513	dev_dbg(dev, "feature auto_whiteb: %u\n", alvium->avail_ft.auto_whiteb);
 514	dev_dbg(dev, "feature dev_temp: %u\n", alvium->avail_ft.dev_temp);
 515	dev_dbg(dev, "feature acq_abort: %u\n", alvium->avail_ft.acq_abort);
 516	dev_dbg(dev, "feature acq_fr: %u\n", alvium->avail_ft.acq_fr);
 517	dev_dbg(dev, "feature fr_trigger: %u\n", alvium->avail_ft.fr_trigger);
 518	dev_dbg(dev, "feature exp_acq_line: %u\n",
 519		alvium->avail_ft.exp_acq_line);
 520}
 521
 522static void alvium_print_avail_bayer(struct alvium_dev *alvium)
 523{
 524	struct device *dev = &alvium->i2c_client->dev;
 525
 526	dev_dbg(dev, "avail bayer mono: %u\n",
 527		alvium->is_bay_avail[ALVIUM_BIT_BAY_MONO]);
 528	dev_dbg(dev, "avail bayer gr: %u\n",
 529		alvium->is_bay_avail[ALVIUM_BIT_BAY_GR]);
 530	dev_dbg(dev, "avail bayer rg: %u\n",
 531		alvium->is_bay_avail[ALVIUM_BIT_BAY_RG]);
 532	dev_dbg(dev, "avail bayer gb: %u\n",
 533		alvium->is_bay_avail[ALVIUM_BIT_BAY_GB]);
 534	dev_dbg(dev, "avail bayer bg: %u\n",
 535		alvium->is_bay_avail[ALVIUM_BIT_BAY_BG]);
 536}
 537
 538static int alvium_get_feat_inq(struct alvium_dev *alvium)
 539{
 540	struct alvium_avail_feat *f;
 541	u64 val;
 542	int ret;
 543
 544	ret = alvium_read(alvium, REG_BCRM_FEATURE_INQUIRY_R, &val, NULL);
 545	if (ret)
 546		return ret;
 547
 548	f = (struct alvium_avail_feat *)&val;
 549	alvium->avail_ft = *f;
 550	alvium_print_avail_feat(alvium);
 551
 552	return 0;
 553}
 554
 555static int alvium_get_host_supp_csi_lanes(struct alvium_dev *alvium)
 556{
 557	u64 val;
 558	int ret;
 559
 560	ret = alvium_read(alvium, REG_BCRM_CSI2_LANE_COUNT_RW, &val, NULL);
 561	if (ret)
 562		return ret;
 563
 564	alvium->h_sup_csi_lanes = val;
 565
 566	return 0;
 567}
 568
 569static int alvium_set_csi_lanes(struct alvium_dev *alvium)
 570{
 571	struct device *dev = &alvium->i2c_client->dev;
 572	u64 num_lanes;
 573	int ret;
 574
 575	num_lanes = alvium->ep.bus.mipi_csi2.num_data_lanes;
 576
 577	if (num_lanes > alvium->h_sup_csi_lanes)
 578		return -EINVAL;
 579
 580	ret = alvium_write_hshake(alvium, REG_BCRM_CSI2_LANE_COUNT_RW,
 581				  num_lanes);
 582	if (ret) {
 583		dev_err(dev, "Fail to set csi lanes reg\n");
 584		return ret;
 585	}
 586
 587	return 0;
 588}
 589
 590static int alvium_set_lp2hs_delay(struct alvium_dev *alvium)
 591{
 592	struct device *dev = &alvium->i2c_client->dev;
 593	int ret = 0;
 594
 595	/*
 596	 * The purpose of this reg is force a DPhy reset
 597	 * for the period described by the millisecond on
 598	 * the reg, before it starts streaming.
 599	 *
 600	 * To be clear, with that value bigger than 0 the
 601	 * Alvium forces a dphy-reset on all lanes for that period.
 602	 * That means all lanes go up into low power state.
 603	 *
 604	 */
 605	alvium_write(alvium, REG_BCRM_LP2HS_DELAY_RW,
 606		     ALVIUM_LP2HS_DELAY_MS, &ret);
 607	if (ret) {
 608		dev_err(dev, "Fail to set lp2hs delay reg\n");
 609		return ret;
 610	}
 611
 612	return 0;
 613}
 614
 615static int alvium_get_csi_clk_params(struct alvium_dev *alvium)
 616{
 617	u64 min_csi_clk, max_csi_clk;
 618	int ret = 0;
 619
 620	alvium_read(alvium, REG_BCRM_CSI2_CLOCK_MIN_R, &min_csi_clk, &ret);
 621	alvium_read(alvium, REG_BCRM_CSI2_CLOCK_MAX_R, &max_csi_clk, &ret);
 622	if (ret)
 623		return ret;
 624
 625	alvium->min_csi_clk = min_csi_clk;
 626	alvium->max_csi_clk = max_csi_clk;
 627
 628	return 0;
 629}
 630
 631static int alvium_set_csi_clk(struct alvium_dev *alvium)
 632{
 633	struct device *dev = &alvium->i2c_client->dev;
 634	u64 csi_clk;
 635	int ret;
 636
 637	csi_clk = clamp(alvium->ep.link_frequencies[0],
 638			(u64)alvium->min_csi_clk, (u64)alvium->max_csi_clk);
 639
 640	if (alvium->ep.link_frequencies[0] != (u64)csi_clk) {
 641		dev_warn(dev,
 642			 "requested csi clock (%llu MHz) out of range [%u, %u] Adjusted to %llu\n",
 643			 alvium->ep.link_frequencies[0],
 644			 alvium->min_csi_clk, alvium->max_csi_clk, csi_clk);
 645	}
 646
 647	ret = alvium_write_hshake(alvium, REG_BCRM_CSI2_CLOCK_RW, csi_clk);
 648	if (ret) {
 649		dev_err(dev, "Fail to set csi clock reg\n");
 650		return ret;
 651	}
 652
 653	alvium->link_freq = csi_clk;
 654
 655	return 0;
 656}
 657
 658static int alvium_get_img_width_params(struct alvium_dev *alvium)
 659{
 660	u64 imgw, imgw_min, imgw_max, imgw_inc;
 661	int ret = 0;
 662
 663	alvium_read(alvium, REG_BCRM_IMG_WIDTH_RW, &imgw, &ret);
 664	alvium_read(alvium, REG_BCRM_IMG_WIDTH_MIN_R, &imgw_min, &ret);
 665	alvium_read(alvium, REG_BCRM_IMG_WIDTH_MAX_R, &imgw_max, &ret);
 666	alvium_read(alvium, REG_BCRM_IMG_WIDTH_INC_R, &imgw_inc, &ret);
 667	if (ret)
 668		return ret;
 669
 670	alvium->dft_img_width = imgw;
 671	alvium->img_min_width = imgw_min;
 672	alvium->img_max_width = imgw_max;
 673	alvium->img_inc_width = imgw_inc;
 674
 675	return 0;
 676}
 677
 678static int alvium_get_img_height_params(struct alvium_dev *alvium)
 679{
 680	u64 imgh, imgh_min, imgh_max, imgh_inc;
 681	int ret = 0;
 682
 683	alvium_read(alvium, REG_BCRM_IMG_HEIGHT_RW, &imgh, &ret);
 684	alvium_read(alvium, REG_BCRM_IMG_HEIGHT_MIN_R, &imgh_min, &ret);
 685	alvium_read(alvium, REG_BCRM_IMG_HEIGHT_MAX_R, &imgh_max, &ret);
 686	alvium_read(alvium, REG_BCRM_IMG_HEIGHT_INC_R, &imgh_inc, &ret);
 687	if (ret)
 688		return ret;
 689
 690	alvium->dft_img_height = imgh;
 691	alvium->img_min_height = imgh_min;
 692	alvium->img_max_height = imgh_max;
 693	alvium->img_inc_height = imgh_inc;
 694
 695	return 0;
 696}
 697
 698static int alvium_set_img_width(struct alvium_dev *alvium, u32 width)
 699{
 700	struct device *dev = &alvium->i2c_client->dev;
 701	int ret;
 702
 703	ret = alvium_write_hshake(alvium, REG_BCRM_IMG_WIDTH_RW, width);
 704	if (ret) {
 705		dev_err(dev, "Fail to set img width\n");
 706		return ret;
 707	}
 708
 709	return 0;
 710}
 711
 712static int alvium_set_img_height(struct alvium_dev *alvium, u32 height)
 713{
 714	struct device *dev = &alvium->i2c_client->dev;
 715	int ret;
 716
 717	ret = alvium_write_hshake(alvium, REG_BCRM_IMG_HEIGHT_RW, height);
 718	if (ret) {
 719		dev_err(dev, "Fail to set img height\n");
 720		return ret;
 721	}
 722
 723	return 0;
 724}
 725
 726static int alvium_set_img_offx(struct alvium_dev *alvium, u32 offx)
 727{
 728	struct device *dev = &alvium->i2c_client->dev;
 729	int ret;
 730
 731	ret = alvium_write_hshake(alvium, REG_BCRM_IMG_OFFSET_X_RW, offx);
 732	if (ret) {
 733		dev_err(dev, "Fail to set img offx\n");
 734		return ret;
 735	}
 736
 737	return 0;
 738}
 739
 740static int alvium_set_img_offy(struct alvium_dev *alvium, u32 offy)
 741{
 742	struct device *dev = &alvium->i2c_client->dev;
 743	int ret;
 744
 745	ret = alvium_write_hshake(alvium, REG_BCRM_IMG_OFFSET_Y_RW, offy);
 746	if (ret) {
 747		dev_err(dev, "Fail to set img offy\n");
 748		return ret;
 749	}
 750
 751	return 0;
 752}
 753
 754static int alvium_get_offx_params(struct alvium_dev *alvium)
 755{
 756	u64 min_offx, max_offx, inc_offx;
 757	int ret = 0;
 758
 759	alvium_read(alvium, REG_BCRM_IMG_OFFSET_X_MIN_R, &min_offx, &ret);
 760	alvium_read(alvium, REG_BCRM_IMG_OFFSET_X_MAX_R, &max_offx, &ret);
 761	alvium_read(alvium, REG_BCRM_IMG_OFFSET_X_INC_R, &inc_offx, &ret);
 762	if (ret)
 763		return ret;
 764
 765	alvium->min_offx = min_offx;
 766	alvium->max_offx = max_offx;
 767	alvium->inc_offx = inc_offx;
 768
 769	return 0;
 770}
 771
 772static int alvium_get_offy_params(struct alvium_dev *alvium)
 773{
 774	u64 min_offy, max_offy, inc_offy;
 775	int ret = 0;
 776
 777	alvium_read(alvium, REG_BCRM_IMG_OFFSET_Y_MIN_R, &min_offy, &ret);
 778	alvium_read(alvium, REG_BCRM_IMG_OFFSET_Y_MAX_R, &max_offy, &ret);
 779	alvium_read(alvium, REG_BCRM_IMG_OFFSET_Y_INC_R, &inc_offy, &ret);
 780	if (ret)
 781		return ret;
 782
 783	alvium->min_offy = min_offy;
 784	alvium->max_offy = max_offy;
 785	alvium->inc_offy = inc_offy;
 786
 787	return 0;
 788}
 789
 790static int alvium_get_gain_params(struct alvium_dev *alvium)
 791{
 792	u64 dft_gain, min_gain, max_gain, inc_gain;
 793	int ret = 0;
 794
 795	alvium_read(alvium, REG_BCRM_GAIN_RW, &dft_gain, &ret);
 796	alvium_read(alvium, REG_BCRM_GAIN_MIN_R, &min_gain, &ret);
 797	alvium_read(alvium, REG_BCRM_GAIN_MAX_R, &max_gain, &ret);
 798	alvium_read(alvium, REG_BCRM_GAIN_INC_R, &inc_gain, &ret);
 799	if (ret)
 800		return ret;
 801
 802	alvium->dft_gain = dft_gain;
 803	alvium->min_gain = min_gain;
 804	alvium->max_gain = max_gain;
 805	alvium->inc_gain = inc_gain;
 806
 807	return 0;
 808}
 809
 810static int alvium_get_exposure_params(struct alvium_dev *alvium)
 811{
 812	u64 dft_exp, min_exp, max_exp, inc_exp;
 813	int ret = 0;
 814
 815	alvium_read(alvium, REG_BCRM_EXPOSURE_TIME_RW, &dft_exp, &ret);
 816	alvium_read(alvium, REG_BCRM_EXPOSURE_TIME_MIN_R, &min_exp, &ret);
 817	alvium_read(alvium, REG_BCRM_EXPOSURE_TIME_MAX_R, &max_exp, &ret);
 818	alvium_read(alvium, REG_BCRM_EXPOSURE_TIME_INC_R, &inc_exp, &ret);
 819	if (ret)
 820		return ret;
 821
 822	alvium->dft_exp = dft_exp;
 823	alvium->min_exp = min_exp;
 824	alvium->max_exp = max_exp;
 825	alvium->inc_exp = inc_exp;
 826
 827	return 0;
 828}
 829
 830static int alvium_get_red_balance_ratio_params(struct alvium_dev *alvium)
 831{
 832	u64 dft_rb, min_rb, max_rb, inc_rb;
 833	int ret = 0;
 834
 835	alvium_read(alvium, REG_BCRM_RED_BALANCE_RATIO_RW, &dft_rb, &ret);
 836	alvium_read(alvium, REG_BCRM_RED_BALANCE_RATIO_MIN_R, &min_rb, &ret);
 837	alvium_read(alvium, REG_BCRM_RED_BALANCE_RATIO_MAX_R, &max_rb, &ret);
 838	alvium_read(alvium, REG_BCRM_RED_BALANCE_RATIO_INC_R, &inc_rb, &ret);
 839	if (ret)
 840		return ret;
 841
 842	alvium->dft_rbalance = dft_rb;
 843	alvium->min_rbalance = min_rb;
 844	alvium->max_rbalance = max_rb;
 845	alvium->inc_rbalance = inc_rb;
 846
 847	return 0;
 848}
 849
 850static int alvium_get_blue_balance_ratio_params(struct alvium_dev *alvium)
 851{
 852	u64 dft_bb, min_bb, max_bb, inc_bb;
 853	int ret = 0;
 854
 855	alvium_read(alvium, REG_BCRM_BLUE_BALANCE_RATIO_RW, &dft_bb, &ret);
 856	alvium_read(alvium, REG_BCRM_BLUE_BALANCE_RATIO_MIN_R, &min_bb, &ret);
 857	alvium_read(alvium, REG_BCRM_BLUE_BALANCE_RATIO_MAX_R, &max_bb, &ret);
 858	alvium_read(alvium, REG_BCRM_BLUE_BALANCE_RATIO_INC_R, &inc_bb, &ret);
 859	if (ret)
 860		return ret;
 861
 862	alvium->dft_bbalance = dft_bb;
 863	alvium->min_bbalance = min_bb;
 864	alvium->max_bbalance = max_bb;
 865	alvium->inc_bbalance = inc_bb;
 866
 867	return 0;
 868}
 869
 870static int alvium_get_hue_params(struct alvium_dev *alvium)
 871{
 872	u64 dft_hue, min_hue, max_hue, inc_hue;
 873	int ret = 0;
 874
 875	alvium_read(alvium, REG_BCRM_HUE_RW, &dft_hue, &ret);
 876	alvium_read(alvium, REG_BCRM_HUE_MIN_R, &min_hue, &ret);
 877	alvium_read(alvium, REG_BCRM_HUE_MAX_R, &max_hue, &ret);
 878	alvium_read(alvium, REG_BCRM_HUE_INC_R, &inc_hue, &ret);
 879	if (ret)
 880		return ret;
 881
 882	alvium->dft_hue = (s32)dft_hue;
 883	alvium->min_hue = (s32)min_hue;
 884	alvium->max_hue = (s32)max_hue;
 885	alvium->inc_hue = (s32)inc_hue;
 886
 887	return 0;
 888}
 889
 890static int alvium_get_black_lvl_params(struct alvium_dev *alvium)
 891{
 892	u64 dft_blvl, min_blvl, max_blvl, inc_blvl;
 893	int ret = 0;
 894
 895	alvium_read(alvium, REG_BCRM_BLACK_LEVEL_RW, &dft_blvl, &ret);
 896	alvium_read(alvium, REG_BCRM_BLACK_LEVEL_MIN_R, &min_blvl, &ret);
 897	alvium_read(alvium, REG_BCRM_BLACK_LEVEL_MAX_R, &max_blvl, &ret);
 898	alvium_read(alvium, REG_BCRM_BLACK_LEVEL_INC_R, &inc_blvl, &ret);
 899	if (ret)
 900		return ret;
 901
 902	alvium->dft_black_lvl = (s32)dft_blvl;
 903	alvium->min_black_lvl = (s32)min_blvl;
 904	alvium->max_black_lvl = (s32)max_blvl;
 905	alvium->inc_black_lvl = (s32)inc_blvl;
 906
 907	return 0;
 908}
 909
 910static int alvium_get_gamma_params(struct alvium_dev *alvium)
 911{
 912	u64 dft_g, min_g, max_g, inc_g;
 913	int ret = 0;
 914
 915	alvium_read(alvium, REG_BCRM_GAMMA_RW, &dft_g, &ret);
 916	alvium_read(alvium, REG_BCRM_GAMMA_MIN_R, &min_g, &ret);
 917	alvium_read(alvium, REG_BCRM_GAMMA_MAX_R, &max_g, &ret);
 918	alvium_read(alvium, REG_BCRM_GAMMA_INC_R, &inc_g, &ret);
 919	if (ret)
 920		return ret;
 921
 922	alvium->dft_gamma = dft_g;
 923	alvium->min_gamma = min_g;
 924	alvium->max_gamma = max_g;
 925	alvium->inc_gamma = inc_g;
 926
 927	return 0;
 928}
 929
 930static int alvium_get_sharpness_params(struct alvium_dev *alvium)
 931{
 932	u64 dft_sh, min_sh, max_sh, inc_sh;
 933	int ret = 0;
 934
 935	alvium_read(alvium, REG_BCRM_SHARPNESS_RW, &dft_sh, &ret);
 936	alvium_read(alvium, REG_BCRM_SHARPNESS_MIN_R, &min_sh, &ret);
 937	alvium_read(alvium, REG_BCRM_BLACK_LEVEL_MAX_R, &max_sh, &ret);
 938	alvium_read(alvium, REG_BCRM_SHARPNESS_INC_R, &inc_sh, &ret);
 939	if (ret)
 940		return ret;
 941
 942	alvium->dft_sharp = (s32)dft_sh;
 943	alvium->min_sharp = (s32)min_sh;
 944	alvium->max_sharp = (s32)max_sh;
 945	alvium->inc_sharp = (s32)inc_sh;
 946
 947	return 0;
 948}
 949
 950static int alvium_get_contrast_params(struct alvium_dev *alvium)
 951{
 952	u64 dft_c, min_c, max_c, inc_c;
 953	int ret = 0;
 954
 955	alvium_read(alvium, REG_BCRM_CONTRAST_VALUE_RW, &dft_c, &ret);
 956	alvium_read(alvium, REG_BCRM_CONTRAST_VALUE_MIN_R, &min_c, &ret);
 957	alvium_read(alvium, REG_BCRM_CONTRAST_VALUE_MAX_R, &max_c, &ret);
 958	alvium_read(alvium, REG_BCRM_CONTRAST_VALUE_INC_R, &inc_c, &ret);
 959	if (ret)
 960		return ret;
 961
 962	alvium->dft_contrast = dft_c;
 963	alvium->min_contrast = min_c;
 964	alvium->max_contrast = max_c;
 965	alvium->inc_contrast = inc_c;
 966
 967	return 0;
 968}
 969
 970static int alvium_get_saturation_params(struct alvium_dev *alvium)
 971{
 972	u64 dft_sat, min_sat, max_sat, inc_sat;
 973	int ret = 0;
 974
 975	alvium_read(alvium, REG_BCRM_SATURATION_RW, &dft_sat, &ret);
 976	alvium_read(alvium, REG_BCRM_SATURATION_MIN_R, &min_sat, &ret);
 977	alvium_read(alvium, REG_BCRM_SATURATION_MAX_R, &max_sat, &ret);
 978	alvium_read(alvium, REG_BCRM_SATURATION_INC_R, &inc_sat, &ret);
 979	if (ret)
 980		return ret;
 981
 982	alvium->dft_sat = dft_sat;
 983	alvium->min_sat = min_sat;
 984	alvium->max_sat = max_sat;
 985	alvium->inc_sat = inc_sat;
 986
 987	return 0;
 988}
 989
 990static int alvium_set_bcm_mode(struct alvium_dev *alvium)
 991{
 992	int ret = 0;
 993
 994	alvium_write(alvium, REG_GENCP_CHANGEMODE_W, ALVIUM_BCM_MODE, &ret);
 995	alvium->bcrm_mode = ALVIUM_BCM_MODE;
 996
 997	return ret;
 998}
 999
1000static int alvium_get_mode(struct alvium_dev *alvium)
1001{
1002	u64 bcrm_mode;
1003	int ret;
1004
1005	ret = alvium_read(alvium, REG_GENCP_CURRENTMODE_R, &bcrm_mode, NULL);
1006	if (ret)
1007		return ret;
1008
1009	switch (bcrm_mode) {
1010	case ALVIUM_BCM_MODE:
1011		alvium->bcrm_mode = ALVIUM_BCM_MODE;
1012		break;
1013	case ALVIUM_GENCP_MODE:
1014		alvium->bcrm_mode = ALVIUM_GENCP_MODE;
1015		break;
1016	}
1017
1018	return 0;
1019}
1020
1021static int alvium_get_avail_mipi_data_format(struct alvium_dev *alvium)
1022{
1023	struct alvium_avail_mipi_fmt *avail_fmt;
1024	u64 val;
1025	int ret;
1026
1027	ret = alvium_read(alvium, REG_BCRM_IMG_AVAILABLE_MIPI_DATA_FORMATS_R,
1028			  &val, NULL);
1029	if (ret)
1030		return ret;
1031
1032	avail_fmt = (struct alvium_avail_mipi_fmt *)&val;
1033
1034	alvium->is_mipi_fmt_avail[ALVIUM_BIT_YUV420_8_LEG] =
1035				  avail_fmt->yuv420_8_leg;
1036	alvium->is_mipi_fmt_avail[ALVIUM_BIT_YUV420_8] =
1037				  avail_fmt->yuv420_8;
1038	alvium->is_mipi_fmt_avail[ALVIUM_BIT_YUV420_10] =
1039				  avail_fmt->yuv420_10;
1040	alvium->is_mipi_fmt_avail[ALVIUM_BIT_YUV420_8_CSPS] =
1041				  avail_fmt->yuv420_8_csps;
1042	alvium->is_mipi_fmt_avail[ALVIUM_BIT_YUV420_10_CSPS] =
1043				  avail_fmt->yuv420_10_csps;
1044	alvium->is_mipi_fmt_avail[ALVIUM_BIT_YUV422_8] =
1045				  avail_fmt->yuv422_8;
1046	alvium->is_mipi_fmt_avail[ALVIUM_BIT_YUV422_10] =
1047				  avail_fmt->yuv422_10;
1048	alvium->is_mipi_fmt_avail[ALVIUM_BIT_RGB888] =
1049				  avail_fmt->rgb888;
1050	alvium->is_mipi_fmt_avail[ALVIUM_BIT_RGB666] =
1051				  avail_fmt->rgb666;
1052	alvium->is_mipi_fmt_avail[ALVIUM_BIT_RGB565] =
1053				  avail_fmt->rgb565;
1054	alvium->is_mipi_fmt_avail[ALVIUM_BIT_RGB555] =
1055				  avail_fmt->rgb555;
1056	alvium->is_mipi_fmt_avail[ALVIUM_BIT_RGB444] =
1057				  avail_fmt->rgb444;
1058	alvium->is_mipi_fmt_avail[ALVIUM_BIT_RAW6] =
1059				  avail_fmt->raw6;
1060	alvium->is_mipi_fmt_avail[ALVIUM_BIT_RAW7] =
1061				  avail_fmt->raw7;
1062	alvium->is_mipi_fmt_avail[ALVIUM_BIT_RAW8] =
1063				  avail_fmt->raw8;
1064	alvium->is_mipi_fmt_avail[ALVIUM_BIT_RAW10] =
1065				  avail_fmt->raw10;
1066	alvium->is_mipi_fmt_avail[ALVIUM_BIT_RAW12] =
1067				  avail_fmt->raw12;
1068	alvium->is_mipi_fmt_avail[ALVIUM_BIT_RAW14] =
1069				  avail_fmt->raw14;
1070	alvium->is_mipi_fmt_avail[ALVIUM_BIT_JPEG] =
1071				  avail_fmt->jpeg;
1072
1073	alvium_print_avail_mipi_fmt(alvium);
1074
1075	return 0;
1076}
1077
1078static int alvium_setup_mipi_fmt(struct alvium_dev *alvium)
1079{
1080	unsigned int avail_fmt_cnt = 0;
1081	unsigned int fmt = 0;
1082	size_t sz = 0;
1083
1084	/* calculate fmt array size */
1085	for (fmt = 0; fmt < ALVIUM_NUM_SUPP_MIPI_DATA_FMT; fmt++) {
1086		if (!alvium->is_mipi_fmt_avail[alvium_csi2_fmts[fmt].fmt_av_bit])
1087			continue;
1088
1089		if (!alvium_csi2_fmts[fmt].is_raw ||
1090		    alvium->is_bay_avail[alvium_csi2_fmts[fmt].bay_av_bit])
1091			sz++;
1092	}
1093
1094	/* init alvium_csi2_fmt array */
1095	alvium->alvium_csi2_fmt_n = sz;
1096	alvium->alvium_csi2_fmt =
1097		kmalloc_array(sz, sizeof(struct alvium_pixfmt), GFP_KERNEL);
1098	if (!alvium->alvium_csi2_fmt)
1099		return -ENOMEM;
1100
1101	/* Create the alvium_csi2 fmt array from formats available */
1102	for (fmt = 0; fmt < ALVIUM_NUM_SUPP_MIPI_DATA_FMT; fmt++) {
1103		if (!alvium->is_mipi_fmt_avail[alvium_csi2_fmts[fmt].fmt_av_bit])
1104			continue;
1105
1106		if (!alvium_csi2_fmts[fmt].is_raw ||
1107		    alvium->is_bay_avail[alvium_csi2_fmts[fmt].bay_av_bit]) {
1108			alvium->alvium_csi2_fmt[avail_fmt_cnt] =
1109				alvium_csi2_fmts[fmt];
1110			avail_fmt_cnt++;
1111		}
1112	}
1113
1114	return 0;
1115}
1116
1117static int alvium_set_mipi_fmt(struct alvium_dev *alvium,
1118			       const struct alvium_pixfmt *pixfmt)
1119{
1120	struct device *dev = &alvium->i2c_client->dev;
1121	int ret;
1122
1123	ret = alvium_write_hshake(alvium, REG_BCRM_IMG_MIPI_DATA_FORMAT_RW,
1124				  pixfmt->mipi_fmt_regval);
1125	if (ret) {
1126		dev_err(dev, "Fail to set mipi fmt\n");
1127		return ret;
1128	}
1129
1130	return 0;
1131}
1132
1133static int alvium_get_avail_bayer(struct alvium_dev *alvium)
1134{
1135	struct alvium_avail_bayer *avail_bay;
1136	u64 val;
1137	int ret;
1138
1139	ret = alvium_read(alvium, REG_BCRM_IMG_BAYER_PATTERN_INQUIRY_R,
1140			  &val, NULL);
1141	if (ret)
1142		return ret;
1143
1144	avail_bay = (struct alvium_avail_bayer *)&val;
1145
1146	alvium->is_bay_avail[ALVIUM_BIT_BAY_MONO] = avail_bay->mono;
1147	alvium->is_bay_avail[ALVIUM_BIT_BAY_GR] = avail_bay->gr;
1148	alvium->is_bay_avail[ALVIUM_BIT_BAY_RG] = avail_bay->rg;
1149	alvium->is_bay_avail[ALVIUM_BIT_BAY_GB] = avail_bay->gb;
1150	alvium->is_bay_avail[ALVIUM_BIT_BAY_BG] = avail_bay->bg;
1151
1152	alvium_print_avail_bayer(alvium);
1153
1154	return 0;
1155}
1156
1157static int alvium_set_bayer_pattern(struct alvium_dev *alvium,
1158				    const struct alvium_pixfmt *pixfmt)
1159{
1160	struct device *dev = &alvium->i2c_client->dev;
1161	int ret;
1162
1163	ret = alvium_write_hshake(alvium, REG_BCRM_IMG_BAYER_PATTERN_RW,
1164				  pixfmt->bay_fmt_regval);
1165	if (ret) {
1166		dev_err(dev, "Fail to set bayer pattern\n");
1167		return ret;
1168	}
1169
1170	return 0;
1171}
1172
1173static int alvium_get_frame_interval(struct alvium_dev *alvium,
1174				     u64 *min_fr, u64 *max_fr)
1175{
1176	int ret = 0;
1177
1178	alvium_read(alvium, REG_BCRM_ACQUISITION_FRAME_RATE_MIN_R,
1179		    min_fr, &ret);
1180	alvium_read(alvium, REG_BCRM_ACQUISITION_FRAME_RATE_MAX_R,
1181		    max_fr, &ret);
1182
1183	return ret;
1184}
1185
1186static int alvium_set_frame_rate(struct alvium_dev *alvium, u64 fr)
1187{
1188	struct device *dev = &alvium->i2c_client->dev;
1189	int ret;
1190
1191	ret = alvium_write_hshake(alvium, REG_BCRM_ACQUISITION_FRAME_RATE_EN_RW,
1192				  1);
1193	if (ret) {
1194		dev_err(dev, "Fail to set acquisition frame rate enable reg\n");
1195		return ret;
1196	}
1197
1198	ret = alvium_write_hshake(alvium, REG_BCRM_FRAME_START_TRIGGER_MODE_RW,
1199				  0);
1200	if (ret) {
1201		dev_err(dev, "Fail to set frame start trigger mode reg\n");
1202		return ret;
1203	}
1204
1205	ret = alvium_write_hshake(alvium, REG_BCRM_ACQUISITION_FRAME_RATE_RW,
1206				  fr);
1207	if (ret) {
1208		dev_err(dev, "Fail to set frame rate lanes reg\n");
1209		return ret;
1210	}
1211
1212	dev_dbg(dev, "set frame rate: %llu us\n", fr);
1213
1214	return 0;
1215}
1216
1217static int alvium_set_stream_mipi(struct alvium_dev *alvium, bool on)
1218{
1219	struct device *dev = &alvium->i2c_client->dev;
1220	int ret;
1221
1222	ret = alvium_write_hshake(alvium, on ? REG_BCRM_ACQUISITION_START_RW :
1223				  REG_BCRM_ACQUISITION_STOP_RW, 0x01);
1224	if (ret) {
1225		dev_err(dev, "Fail set_stream_mipi\n");
1226		return ret;
1227	}
1228
1229	return 0;
1230}
1231
1232static int alvium_get_gain(struct alvium_dev *alvium)
1233{
1234	u64 gain;
1235	int ret;
1236
1237	/* The unit is millibel (1 mB = 0.01 dB) */
1238	ret = alvium_read(alvium, REG_BCRM_GAIN_RW, &gain, NULL);
1239	if (ret)
1240		return ret;
1241
1242	return gain;
1243}
1244
1245static int alvium_set_ctrl_gain(struct alvium_dev *alvium, int gain)
1246{
1247	struct device *dev = &alvium->i2c_client->dev;
1248	int ret;
1249
1250	/* The unit is millibel (1 mB = 0.01 dB) */
1251	ret = alvium_write_hshake(alvium, REG_BCRM_GAIN_RW, (u64)gain);
1252	if (ret) {
1253		dev_err(dev, "Fail to set gain value reg\n");
1254		return ret;
1255	}
1256
1257	return 0;
1258}
1259
1260static int alvium_set_ctrl_auto_gain(struct alvium_dev *alvium, bool on)
1261{
1262	struct device *dev = &alvium->i2c_client->dev;
1263	int ret;
1264
1265	ret = alvium_write_hshake(alvium, REG_BCRM_GAIN_AUTO_RW,
1266				  on ? 0x02 : 0x00);
1267	if (ret) {
1268		dev_err(dev, "Fail to set autogain reg\n");
1269		return ret;
1270	}
1271
1272	return 0;
1273}
1274
1275static int alvium_get_exposure(struct alvium_dev *alvium)
1276{
1277	u64 exp;
1278	int ret;
1279
1280	/* Exposure time in ns */
1281	ret = alvium_read(alvium, REG_BCRM_EXPOSURE_TIME_RW, &exp, NULL);
1282	if (ret)
1283		return ret;
1284
1285	return exp;
1286}
1287
1288static int alvium_set_ctrl_auto_exposure(struct alvium_dev *alvium, bool on)
1289{
1290	struct device *dev = &alvium->i2c_client->dev;
1291	int ret;
1292
1293	ret = alvium_write_hshake(alvium, REG_BCRM_WHITE_BALANCE_AUTO_RW,
1294				  on ? 0x02 : 0x00);
1295	if (ret) {
1296		dev_err(dev, "Fail to set autoexposure reg\n");
1297		return ret;
1298	}
1299
1300	return 0;
1301}
1302
1303static int alvium_set_ctrl_exposure(struct alvium_dev *alvium, int exposure_ns)
1304{
1305	struct device *dev = &alvium->i2c_client->dev;
1306	int ret;
1307
1308	ret = alvium_write_hshake(alvium, REG_BCRM_EXPOSURE_TIME_RW,
1309				  (u64)exposure_ns);
1310	if (ret) {
1311		dev_err(dev, "Fail to set exposure value reg\n");
1312		return ret;
1313	}
1314
1315	return 0;
1316}
1317
1318static int alvium_set_ctrl_blue_balance_ratio(struct alvium_dev *alvium,
1319					      int blue)
1320{
1321	struct device *dev = &alvium->i2c_client->dev;
1322	int ret;
1323
1324	ret = alvium_write_hshake(alvium, REG_BCRM_BLUE_BALANCE_RATIO_RW,
1325				  (u64)blue);
1326	if (ret) {
1327		dev_err(dev, "Fail to set blue ratio value reg\n");
1328		return ret;
1329	}
1330
1331	return 0;
1332}
1333
1334static int alvium_set_ctrl_red_balance_ratio(struct alvium_dev *alvium, int red)
1335{
1336	struct device *dev = &alvium->i2c_client->dev;
1337	int ret;
1338
1339	ret = alvium_write_hshake(alvium, REG_BCRM_RED_BALANCE_RATIO_RW,
1340				  (u64)red);
1341	if (ret) {
1342		dev_err(dev, "Fail to set red ratio value reg\n");
1343		return ret;
1344	}
1345
1346	return 0;
1347}
1348
1349static int alvium_set_ctrl_awb(struct alvium_dev *alvium, bool on)
1350{
1351	struct device *dev = &alvium->i2c_client->dev;
1352	int ret;
1353
1354	ret = alvium_write_hshake(alvium, REG_BCRM_WHITE_BALANCE_AUTO_RW,
1355				  on ? 0x02 : 0x00);
1356	if (ret) {
1357		dev_err(dev, "Fail to set awb reg\n");
1358		return ret;
1359	}
1360
1361	return 0;
1362}
1363
1364static int alvium_set_ctrl_hue(struct alvium_dev *alvium, int val)
1365{
1366	struct device *dev = &alvium->i2c_client->dev;
1367	int ret;
1368
1369	ret = alvium_write_hshake(alvium, REG_BCRM_HUE_RW, (u64)val);
1370	if (ret) {
1371		dev_err(dev, "Fail to set hue value reg\n");
1372		return ret;
1373	}
1374
1375	return 0;
1376}
1377
1378static int alvium_set_ctrl_contrast(struct alvium_dev *alvium, int val)
1379{
1380	struct device *dev = &alvium->i2c_client->dev;
1381	int ret;
1382
1383	ret = alvium_write_hshake(alvium, REG_BCRM_CONTRAST_VALUE_RW, (u64)val);
1384	if (ret) {
1385		dev_err(dev, "Fail to set contrast value reg\n");
1386		return ret;
1387	}
1388
1389	return 0;
1390}
1391
1392static int alvium_set_ctrl_saturation(struct alvium_dev *alvium, int val)
1393{
1394	struct device *dev = &alvium->i2c_client->dev;
1395	int ret;
1396
1397	ret = alvium_write_hshake(alvium, REG_BCRM_SATURATION_RW, (u64)val);
1398	if (ret) {
1399		dev_err(dev, "Fail to set contrast value reg\n");
1400		return ret;
1401	}
1402
1403	return 0;
1404}
1405
1406static int alvium_set_ctrl_gamma(struct alvium_dev *alvium, int val)
1407{
1408	struct device *dev = &alvium->i2c_client->dev;
1409	int ret;
1410
1411	ret = alvium_write_hshake(alvium, REG_BCRM_GAMMA_RW, (u64)val);
1412	if (ret) {
1413		dev_err(dev, "Fail to set gamma value reg\n");
1414		return ret;
1415	}
1416
1417	return 0;
1418}
1419
1420static int alvium_set_ctrl_sharpness(struct alvium_dev *alvium, int val)
1421{
1422	struct device *dev = &alvium->i2c_client->dev;
1423	int ret;
1424
1425	ret = alvium_write_hshake(alvium, REG_BCRM_SHARPNESS_RW, (u64)val);
1426	if (ret) {
1427		dev_err(dev, "Fail to set sharpness value reg\n");
1428		return ret;
1429	}
1430
1431	return 0;
1432}
1433
1434static int alvium_set_ctrl_hflip(struct alvium_dev *alvium, int val)
1435{
1436	struct device *dev = &alvium->i2c_client->dev;
1437	int ret;
1438
1439	ret = alvium_write_hshake(alvium, REG_BCRM_IMG_REVERSE_X_RW, (u64)val);
1440	if (ret) {
1441		dev_err(dev, "Fail to set reverse_x value reg\n");
1442		return ret;
1443	}
1444
1445	return 0;
1446}
1447
1448static int alvium_set_ctrl_vflip(struct alvium_dev *alvium, int val)
1449{
1450	struct device *dev = &alvium->i2c_client->dev;
1451	int ret;
1452
1453	ret = alvium_write_hshake(alvium, REG_BCRM_IMG_REVERSE_Y_RW, (u64)val);
1454	if (ret) {
1455		dev_err(dev, "Fail to set reverse_y value reg\n");
1456		return ret;
1457	}
1458
1459	return 0;
1460}
1461
1462static int alvium_get_hw_features_params(struct alvium_dev *alvium)
1463{
1464	struct device *dev = &alvium->i2c_client->dev;
1465	int ret;
1466
1467	ret = alvium_get_csi_clk_params(alvium);
1468	if (ret) {
1469		dev_err(dev, "Fail to read min/max csi clock regs\n");
1470		return ret;
1471	}
1472
1473	ret = alvium_get_img_width_params(alvium);
1474	if (ret) {
1475		dev_err(dev, "Fail to read img width regs\n");
1476		return ret;
1477	}
1478
1479	ret = alvium_get_img_height_params(alvium);
1480	if (ret) {
1481		dev_err(dev, "Fail to read img height regs\n");
1482		return ret;
1483	}
1484
1485	ret = alvium_get_offx_params(alvium);
1486	if (ret) {
1487		dev_err(dev, "Fail to read offx regs\n");
1488		return ret;
1489	}
1490
1491	ret = alvium_get_offy_params(alvium);
1492	if (ret) {
1493		dev_err(dev, "Fail to read offy regs\n");
1494		return ret;
1495	}
1496
1497	ret = alvium_get_gain_params(alvium);
1498	if (ret) {
1499		dev_err(dev, "Fail to read gain regs\n");
1500		return ret;
1501	}
1502
1503	ret = alvium_get_exposure_params(alvium);
1504	if (ret) {
1505		dev_err(dev, "Fail to read min/max exp regs\n");
1506		return ret;
1507	}
1508
1509	ret = alvium_get_red_balance_ratio_params(alvium);
1510	if (ret) {
1511		dev_err(dev, "Fail to read red balance ratio regs\n");
1512		return ret;
1513	}
1514
1515	ret = alvium_get_blue_balance_ratio_params(alvium);
1516	if (ret) {
1517		dev_err(dev, "Fail to read blue balance ratio regs\n");
1518		return ret;
1519	}
1520
1521	ret = alvium_get_hue_params(alvium);
1522	if (ret) {
1523		dev_err(dev, "Fail to read hue regs\n");
1524		return ret;
1525	}
1526
1527	ret = alvium_get_contrast_params(alvium);
1528	if (ret) {
1529		dev_err(dev, "Fail to read contrast regs\n");
1530		return ret;
1531	}
1532
1533	ret = alvium_get_saturation_params(alvium);
1534	if (ret) {
1535		dev_err(dev, "Fail to read saturation regs\n");
1536		return ret;
1537	}
1538
1539	ret = alvium_get_black_lvl_params(alvium);
1540	if (ret) {
1541		dev_err(dev, "Fail to read black lvl regs\n");
1542		return ret;
1543	}
1544
1545	ret = alvium_get_gamma_params(alvium);
1546	if (ret) {
1547		dev_err(dev, "Fail to read gamma regs\n");
1548		return ret;
1549	}
1550
1551	ret = alvium_get_sharpness_params(alvium);
1552	if (ret) {
1553		dev_err(dev, "Fail to read sharpness regs\n");
1554		return ret;
1555	}
1556
1557	return 0;
1558}
1559
1560static int alvium_get_hw_info(struct alvium_dev *alvium)
1561{
1562	struct device *dev = &alvium->i2c_client->dev;
1563	int ret;
1564
1565	ret = alvium_get_bcrm_vers(alvium);
1566	if (ret) {
1567		dev_err(dev, "Fail to read bcrm version reg\n");
1568		return ret;
1569	}
1570
1571	ret = alvium_get_bcrm_addr(alvium);
1572	if (ret) {
1573		dev_err(dev, "Fail to bcrm address reg\n");
1574		return ret;
1575	}
1576
1577	ret = alvium_get_fw_version(alvium);
1578	if (ret) {
1579		dev_err(dev, "Fail to read fw version reg\n");
1580		return ret;
1581	}
1582
1583	ret = alvium_get_host_supp_csi_lanes(alvium);
1584	if (ret) {
1585		dev_err(dev, "Fail to read host supported csi lanes reg\n");
1586		return ret;
1587	}
1588
1589	ret = alvium_get_feat_inq(alvium);
1590	if (ret) {
1591		dev_err(dev, "Fail to read bcrm feature inquiry reg\n");
1592		return ret;
1593	}
1594
1595	ret = alvium_get_hw_features_params(alvium);
1596	if (ret) {
1597		dev_err(dev, "Fail to read features params regs\n");
1598		return ret;
1599	}
1600
1601	ret = alvium_get_avail_mipi_data_format(alvium);
1602	if (ret) {
1603		dev_err(dev, "Fail to read available mipi data formats reg\n");
1604		return ret;
1605	}
1606
1607	ret = alvium_get_avail_bayer(alvium);
1608	if (ret) {
1609		dev_err(dev, "Fail to read available Bayer patterns reg\n");
1610		return ret;
1611	}
1612
1613	ret = alvium_get_mode(alvium);
1614	if (ret) {
1615		dev_err(dev, "Fail to get current mode reg\n");
1616		return ret;
1617	}
1618
1619	return 0;
1620}
1621
1622static int alvium_hw_init(struct alvium_dev *alvium)
1623{
1624	struct device *dev = &alvium->i2c_client->dev;
1625	int ret;
1626
1627	/* Set Alvium BCM mode*/
1628	ret = alvium_set_bcm_mode(alvium);
1629	if (ret) {
1630		dev_err(dev, "Fail to set BCM mode\n");
1631		return ret;
1632	}
1633
1634	ret = alvium_set_csi_lanes(alvium);
1635	if (ret) {
1636		dev_err(dev, "Fail to set csi lanes\n");
1637		return ret;
1638	}
1639
1640	ret = alvium_set_csi_clk(alvium);
1641	if (ret) {
1642		dev_err(dev, "Fail to set csi clk\n");
1643		return ret;
1644	}
1645
1646	ret = alvium_set_lp2hs_delay(alvium);
1647	if (ret) {
1648		dev_err(dev, "Fail to set lp2hs reg\n");
1649		return ret;
1650	}
1651
1652	return 0;
1653}
1654
1655/* --------------- Subdev Operations --------------- */
1656static int alvium_s_frame_interval(struct v4l2_subdev *sd,
1657				   struct v4l2_subdev_state *sd_state,
1658				   struct v4l2_subdev_frame_interval *fi)
1659{
1660	struct alvium_dev *alvium = sd_to_alvium(sd);
1661	struct device *dev = &alvium->i2c_client->dev;
1662	u64 req_fr, min_fr, max_fr;
1663	struct v4l2_fract *interval;
1664	int ret;
1665
1666	if (alvium->streaming)
1667		return -EBUSY;
1668
1669	if (fi->interval.denominator == 0)
1670		return -EINVAL;
1671
1672	ret = alvium_get_frame_interval(alvium, &min_fr, &max_fr);
1673	if (ret) {
1674		dev_err(dev, "Fail to get frame interval\n");
1675		return ret;
1676	}
1677
1678	dev_dbg(dev, "fi->interval.numerator = %d\n",
1679		fi->interval.numerator);
1680	dev_dbg(dev, "fi->interval.denominator = %d\n",
1681		fi->interval.denominator);
1682
1683	req_fr = (u64)((fi->interval.denominator * USEC_PER_SEC) /
1684		       fi->interval.numerator);
1685	req_fr = clamp(req_fr, min_fr, max_fr);
1686
1687	interval = v4l2_subdev_state_get_interval(sd_state, 0);
1688
1689	interval->numerator = fi->interval.numerator;
1690	interval->denominator = fi->interval.denominator;
1691
1692	if (fi->which != V4L2_SUBDEV_FORMAT_ACTIVE)
1693		return 0;
1694
1695	return alvium_set_frame_rate(alvium, req_fr);
1696}
1697
1698static int alvium_enum_mbus_code(struct v4l2_subdev *sd,
1699				 struct v4l2_subdev_state *sd_state,
1700				 struct v4l2_subdev_mbus_code_enum *code)
1701{
1702	struct alvium_dev *alvium = sd_to_alvium(sd);
1703
1704	if (code->index >= alvium->alvium_csi2_fmt_n)
1705		return -EINVAL;
1706
1707	code->code = alvium->alvium_csi2_fmt[code->index].code;
1708
1709	return 0;
1710}
1711
1712static const struct alvium_pixfmt *
1713alvium_code_to_pixfmt(struct alvium_dev *alvium, u32 code)
1714{
1715	unsigned int i;
1716
1717	for (i = 0; alvium->alvium_csi2_fmt[i].code; ++i)
1718		if (alvium->alvium_csi2_fmt[i].code == code)
1719			return &alvium->alvium_csi2_fmt[i];
1720
1721	return &alvium->alvium_csi2_fmt[0];
1722}
1723
1724static int alvium_enum_frame_size(struct v4l2_subdev *sd,
1725				  struct v4l2_subdev_state *state,
1726				  struct v4l2_subdev_frame_size_enum *fse)
1727{
1728	struct alvium_dev *alvium = sd_to_alvium(sd);
1729	const struct alvium_pixfmt *alvium_csi2_fmt;
1730
1731	if (fse->index)
1732		return -EINVAL;
1733
1734	alvium_csi2_fmt = alvium_code_to_pixfmt(alvium, fse->code);
1735	if (fse->code != alvium_csi2_fmt->code)
1736		return -EINVAL;
1737
1738	fse->min_width = alvium->img_min_width;
1739	fse->max_width = alvium->img_max_width;
1740	fse->min_height = alvium->img_min_height;
1741	fse->max_height = alvium->img_max_height;
1742	return 0;
1743}
1744
1745static int alvium_set_mode(struct alvium_dev *alvium,
1746			   struct v4l2_subdev_state *state)
1747{
1748	struct v4l2_mbus_framefmt *fmt;
1749	struct v4l2_rect *crop;
1750	int ret;
1751
1752	crop = v4l2_subdev_state_get_crop(state, 0);
1753	fmt = v4l2_subdev_state_get_format(state, 0);
1754
1755	v4l_bound_align_image(&fmt->width, alvium->img_min_width,
1756			      alvium->img_max_width, 0,
1757			      &fmt->height, alvium->img_min_height,
1758			      alvium->img_max_height, 0, 0);
1759
1760	/* alvium don't accept negative crop left/top */
1761	crop->left = clamp((u32)max(0, crop->left), alvium->min_offx,
1762			   (u32)(alvium->img_max_width - fmt->width));
1763	crop->top = clamp((u32)max(0, crop->top), alvium->min_offy,
1764			  (u32)(alvium->img_max_height - fmt->height));
1765
1766	ret = alvium_set_img_width(alvium, fmt->width);
1767	if (ret)
1768		return ret;
1769
1770	ret = alvium_set_img_height(alvium, fmt->height);
1771	if (ret)
1772		return ret;
1773
1774	ret = alvium_set_img_offx(alvium, crop->left);
1775	if (ret)
1776		return ret;
1777
1778	ret = alvium_set_img_offy(alvium, crop->top);
1779	if (ret)
1780		return ret;
1781
1782	return 0;
1783}
1784
1785static int alvium_set_framefmt(struct alvium_dev *alvium,
1786			       struct v4l2_mbus_framefmt *format)
1787{
1788	struct device *dev = &alvium->i2c_client->dev;
1789	const struct alvium_pixfmt *alvium_csi2_fmt;
1790	int ret = 0;
1791
1792	alvium_csi2_fmt = alvium_code_to_pixfmt(alvium, format->code);
1793
1794	ret = alvium_set_mipi_fmt(alvium, alvium_csi2_fmt);
1795	if (ret)
1796		return ret;
1797
1798	if (alvium_csi2_fmt->is_raw) {
1799		ret = alvium_set_bayer_pattern(alvium, alvium_csi2_fmt);
1800		if (ret)
1801			return ret;
1802	}
1803
1804	dev_dbg(dev, "start: %s, mipi_fmt_regval regval = 0x%llx",
1805		__func__, alvium_csi2_fmt->mipi_fmt_regval);
1806
1807	return ret;
1808}
1809
1810static int alvium_s_stream(struct v4l2_subdev *sd, int enable)
1811{
1812	struct alvium_dev *alvium = sd_to_alvium(sd);
1813	struct i2c_client *client = v4l2_get_subdevdata(&alvium->sd);
1814	struct v4l2_mbus_framefmt *fmt;
1815	struct v4l2_subdev_state *state;
1816	int ret = 0;
1817
1818	state = v4l2_subdev_lock_and_get_active_state(sd);
1819
1820	if (enable) {
1821		ret = pm_runtime_resume_and_get(&client->dev);
1822		if (ret < 0)
1823			goto out;
1824
1825		ret = __v4l2_ctrl_handler_setup(&alvium->ctrls.handler);
1826		if (ret)
1827			goto out;
1828
1829		ret = alvium_set_mode(alvium, state);
1830		if (ret)
1831			goto out;
1832
1833		fmt = v4l2_subdev_state_get_format(state, 0);
1834		ret = alvium_set_framefmt(alvium, fmt);
1835		if (ret)
1836			goto out;
1837
1838		ret = alvium_set_stream_mipi(alvium, enable);
1839		if (ret)
1840			goto out;
1841
1842	} else {
1843		alvium_set_stream_mipi(alvium, enable);
1844		pm_runtime_put_autosuspend(&client->dev);
1845	}
1846
1847	alvium->streaming = !!enable;
1848	v4l2_subdev_unlock_state(state);
1849
1850	return 0;
1851
1852out:
1853	pm_runtime_put(&client->dev);
1854	v4l2_subdev_unlock_state(state);
1855	return ret;
1856}
1857
1858static int alvium_init_state(struct v4l2_subdev *sd,
1859			     struct v4l2_subdev_state *state)
1860{
1861	struct alvium_dev *alvium = sd_to_alvium(sd);
1862	struct alvium_mode *mode = &alvium->mode;
1863	struct v4l2_fract *interval;
1864	struct v4l2_subdev_format sd_fmt = {
1865		.which = V4L2_SUBDEV_FORMAT_TRY,
1866		.format = alvium_csi2_default_fmt,
1867	};
1868	struct v4l2_subdev_crop sd_crop = {
1869		.which = V4L2_SUBDEV_FORMAT_TRY,
1870		.rect = {
1871			.left = mode->crop.left,
1872			.top = mode->crop.top,
1873			.width = mode->crop.width,
1874			.height = mode->crop.height,
1875		},
1876	};
1877
1878	*v4l2_subdev_state_get_crop(state, 0) = sd_crop.rect;
1879	*v4l2_subdev_state_get_format(state, 0) = sd_fmt.format;
1880
1881	/* Setup initial frame interval*/
1882	interval = v4l2_subdev_state_get_interval(state, 0);
1883	interval->numerator = 1;
1884	interval->denominator = ALVIUM_DEFAULT_FR_HZ;
1885
1886	return 0;
1887}
1888
1889static int alvium_set_fmt(struct v4l2_subdev *sd,
1890			  struct v4l2_subdev_state *sd_state,
1891			  struct v4l2_subdev_format *format)
1892{
1893	struct alvium_dev *alvium = sd_to_alvium(sd);
1894	const struct alvium_pixfmt *alvium_csi2_fmt;
1895	struct v4l2_mbus_framefmt *fmt;
1896	struct v4l2_rect *crop;
1897
1898	fmt = v4l2_subdev_state_get_format(sd_state, 0);
1899	crop = v4l2_subdev_state_get_crop(sd_state, 0);
1900
1901	v4l_bound_align_image(&format->format.width, alvium->img_min_width,
1902			      alvium->img_max_width, 0,
1903			      &format->format.height, alvium->img_min_height,
1904			      alvium->img_max_height, 0, 0);
1905
1906	/* Adjust left and top to prevent roll over sensor area */
1907	crop->left = clamp((u32)crop->left, (u32)0,
1908			   (alvium->img_max_width - fmt->width));
1909	crop->top = clamp((u32)crop->top, (u32)0,
1910			  (alvium->img_max_height - fmt->height));
1911
1912	/* Set also the crop width and height when set a new fmt */
1913	crop->width = fmt->width;
1914	crop->height = fmt->height;
1915
1916	alvium_csi2_fmt = alvium_code_to_pixfmt(alvium, format->format.code);
1917	fmt->code = alvium_csi2_fmt->code;
1918
1919	*fmt = format->format;
1920
1921	return 0;
1922}
1923
1924static int alvium_set_selection(struct v4l2_subdev *sd,
1925				struct v4l2_subdev_state *sd_state,
1926				struct v4l2_subdev_selection *sel)
1927{
1928	struct alvium_dev *alvium = sd_to_alvium(sd);
1929	struct v4l2_mbus_framefmt *fmt;
1930	struct v4l2_rect *crop;
1931
1932	if (sel->target != V4L2_SEL_TGT_CROP)
1933		return -EINVAL;
1934
1935	crop = v4l2_subdev_state_get_crop(sd_state, 0);
1936	fmt = v4l2_subdev_state_get_format(sd_state, 0);
1937
1938	/*
1939	 * Alvium can only shift the origin of the img
1940	 * then we accept only value with the same value of the actual fmt
1941	 */
1942	if (sel->r.width != fmt->width)
1943		sel->r.width = fmt->width;
1944
1945	if (sel->r.height != fmt->height)
1946		sel->r.height = fmt->height;
1947
1948	/* alvium don't accept negative crop left/top */
1949	crop->left = clamp((u32)max(0, sel->r.left), alvium->min_offx,
1950			   alvium->img_max_width - sel->r.width);
1951	crop->top = clamp((u32)max(0, sel->r.top), alvium->min_offy,
1952			  alvium->img_max_height - sel->r.height);
1953
1954	sel->r = *crop;
1955
1956	return 0;
1957}
1958
1959static int alvium_get_selection(struct v4l2_subdev *sd,
1960				struct v4l2_subdev_state *sd_state,
1961				struct v4l2_subdev_selection *sel)
1962{
1963	struct alvium_dev *alvium = sd_to_alvium(sd);
1964
1965	switch (sel->target) {
1966	/* Current cropping area */
1967	case V4L2_SEL_TGT_CROP:
1968		sel->r = *v4l2_subdev_state_get_crop(sd_state, 0);
1969		break;
1970	/* Cropping bounds */
1971	case V4L2_SEL_TGT_NATIVE_SIZE:
1972		sel->r.top = 0;
1973		sel->r.left = 0;
1974		sel->r.width = alvium->img_max_width;
1975		sel->r.height = alvium->img_max_height;
1976		break;
1977	/* Default cropping area */
1978	case V4L2_SEL_TGT_CROP_BOUNDS:
1979	case V4L2_SEL_TGT_CROP_DEFAULT:
1980		sel->r.top = alvium->min_offy;
1981		sel->r.left = alvium->min_offx;
1982		sel->r.width = alvium->img_max_width;
1983		sel->r.height = alvium->img_max_height;
1984		break;
1985	default:
1986		return -EINVAL;
1987	}
1988
1989	return 0;
1990}
1991
1992static int alvium_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
1993{
1994	struct v4l2_subdev *sd = ctrl_to_sd(ctrl);
1995	struct alvium_dev *alvium = sd_to_alvium(sd);
1996	int val;
1997
1998	switch (ctrl->id) {
1999	case V4L2_CID_ANALOGUE_GAIN:
2000		val = alvium_get_gain(alvium);
2001		if (val < 0)
2002			return val;
2003		alvium->ctrls.gain->val = val;
2004		break;
2005	case V4L2_CID_EXPOSURE:
2006		val = alvium_get_exposure(alvium);
2007		if (val < 0)
2008			return val;
2009		alvium->ctrls.exposure->val = val;
2010		break;
2011	}
2012
2013	return 0;
2014}
2015
2016static int alvium_s_ctrl(struct v4l2_ctrl *ctrl)
2017{
2018	struct v4l2_subdev *sd = ctrl_to_sd(ctrl);
2019	struct alvium_dev *alvium = sd_to_alvium(sd);
2020	struct i2c_client *client = v4l2_get_subdevdata(&alvium->sd);
2021	int ret;
2022
2023	/*
2024	 * Applying V4L2 control value only happens
2025	 * when power is up for streaming
2026	 */
2027	if (!pm_runtime_get_if_in_use(&client->dev))
2028		return 0;
2029
2030	switch (ctrl->id) {
2031	case V4L2_CID_ANALOGUE_GAIN:
2032		ret = alvium_set_ctrl_gain(alvium, ctrl->val);
2033		break;
2034	case V4L2_CID_AUTOGAIN:
2035		ret = alvium_set_ctrl_auto_gain(alvium, ctrl->val);
2036		break;
2037	case V4L2_CID_EXPOSURE:
2038		ret = alvium_set_ctrl_exposure(alvium, ctrl->val);
2039		break;
2040	case V4L2_CID_EXPOSURE_AUTO:
2041		ret = alvium_set_ctrl_auto_exposure(alvium, ctrl->val);
2042		break;
2043	case V4L2_CID_RED_BALANCE:
2044		ret = alvium_set_ctrl_red_balance_ratio(alvium, ctrl->val);
2045		break;
2046	case V4L2_CID_BLUE_BALANCE:
2047		ret = alvium_set_ctrl_blue_balance_ratio(alvium, ctrl->val);
2048		break;
2049	case V4L2_CID_AUTO_WHITE_BALANCE:
2050		ret = alvium_set_ctrl_awb(alvium, ctrl->val);
2051		break;
2052	case V4L2_CID_HUE:
2053		ret = alvium_set_ctrl_hue(alvium, ctrl->val);
2054		break;
2055	case V4L2_CID_CONTRAST:
2056		ret = alvium_set_ctrl_contrast(alvium, ctrl->val);
2057		break;
2058	case V4L2_CID_SATURATION:
2059		ret = alvium_set_ctrl_saturation(alvium, ctrl->val);
2060		break;
2061	case V4L2_CID_GAMMA:
2062		ret = alvium_set_ctrl_gamma(alvium, ctrl->val);
2063		break;
2064	case V4L2_CID_SHARPNESS:
2065		ret = alvium_set_ctrl_sharpness(alvium, ctrl->val);
2066		break;
2067	case V4L2_CID_HFLIP:
2068		ret = alvium_set_ctrl_hflip(alvium, ctrl->val);
2069		break;
2070	case V4L2_CID_VFLIP:
2071		ret = alvium_set_ctrl_vflip(alvium, ctrl->val);
2072		break;
2073	default:
2074		ret = -EINVAL;
2075		break;
2076	}
2077
2078	pm_runtime_put(&client->dev);
2079
2080	return ret;
2081}
2082
2083static const struct v4l2_ctrl_ops alvium_ctrl_ops = {
2084	.g_volatile_ctrl = alvium_g_volatile_ctrl,
2085	.s_ctrl = alvium_s_ctrl,
2086};
2087
2088static int alvium_ctrl_init(struct alvium_dev *alvium)
2089{
2090	const struct v4l2_ctrl_ops *ops = &alvium_ctrl_ops;
2091	struct alvium_ctrls *ctrls = &alvium->ctrls;
2092	struct v4l2_ctrl_handler *hdl = &ctrls->handler;
2093	struct v4l2_fwnode_device_properties props;
2094	int ret;
2095
2096	v4l2_ctrl_handler_init(hdl, 32);
2097
2098	/* Pixel rate is fixed */
2099	ctrls->pixel_rate = v4l2_ctrl_new_std(hdl, ops,
2100					      V4L2_CID_PIXEL_RATE, 0,
2101					      ALVIUM_DEFAULT_PIXEL_RATE_MHZ, 1,
2102					      ALVIUM_DEFAULT_PIXEL_RATE_MHZ);
2103	ctrls->pixel_rate->flags |= V4L2_CTRL_FLAG_READ_ONLY;
2104
2105	/* Link freq is fixed */
2106	ctrls->link_freq = v4l2_ctrl_new_int_menu(hdl, ops,
2107						  V4L2_CID_LINK_FREQ,
2108						  0, 0, &alvium->link_freq);
2109	ctrls->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
2110
2111	/* Auto/manual white balance */
2112	if (alvium->avail_ft.auto_whiteb) {
2113		ctrls->auto_wb = v4l2_ctrl_new_std(hdl, ops,
2114						   V4L2_CID_AUTO_WHITE_BALANCE,
2115						   0, 1, 1, 1);
2116		v4l2_ctrl_auto_cluster(3, &ctrls->auto_wb, 0, false);
2117	}
2118
2119	ctrls->blue_balance = v4l2_ctrl_new_std(hdl, ops,
2120						V4L2_CID_BLUE_BALANCE,
2121						alvium->min_bbalance,
2122						alvium->max_bbalance,
2123						alvium->inc_bbalance,
2124						alvium->dft_bbalance);
2125	ctrls->red_balance = v4l2_ctrl_new_std(hdl, ops,
2126					       V4L2_CID_RED_BALANCE,
2127					       alvium->min_rbalance,
2128					       alvium->max_rbalance,
2129					       alvium->inc_rbalance,
2130					       alvium->dft_rbalance);
2131
2132	/* Auto/manual exposure */
2133	if (alvium->avail_ft.auto_exp) {
2134		ctrls->auto_exp =
2135			v4l2_ctrl_new_std_menu(hdl, ops,
2136					       V4L2_CID_EXPOSURE_AUTO,
2137					       V4L2_EXPOSURE_MANUAL, 0,
2138					       V4L2_EXPOSURE_AUTO);
2139		v4l2_ctrl_auto_cluster(2, &ctrls->auto_exp, 1, true);
2140	}
2141
2142	ctrls->exposure = v4l2_ctrl_new_std(hdl, ops,
2143					    V4L2_CID_EXPOSURE,
2144					    alvium->min_exp,
2145					    alvium->max_exp,
2146					    alvium->inc_exp,
2147					    alvium->dft_exp);
2148	ctrls->exposure->flags |= V4L2_CTRL_FLAG_VOLATILE;
2149
2150	/* Auto/manual gain */
2151	if (alvium->avail_ft.auto_gain) {
2152		ctrls->auto_gain = v4l2_ctrl_new_std(hdl, ops,
2153						     V4L2_CID_AUTOGAIN,
2154						     0, 1, 1, 1);
2155		v4l2_ctrl_auto_cluster(2, &ctrls->auto_gain, 0, true);
2156	}
2157
2158	if (alvium->avail_ft.gain) {
2159		ctrls->gain = v4l2_ctrl_new_std(hdl, ops,
2160						V4L2_CID_ANALOGUE_GAIN,
2161						alvium->min_gain,
2162						alvium->max_gain,
2163						alvium->inc_gain,
2164						alvium->dft_gain);
2165		ctrls->gain->flags |= V4L2_CTRL_FLAG_VOLATILE;
2166	}
2167
2168	if (alvium->avail_ft.sat)
2169		ctrls->saturation = v4l2_ctrl_new_std(hdl, ops,
2170						      V4L2_CID_SATURATION,
2171						      alvium->min_sat,
2172						      alvium->max_sat,
2173						      alvium->inc_sat,
2174						      alvium->dft_sat);
2175
2176	if (alvium->avail_ft.hue)
2177		ctrls->hue = v4l2_ctrl_new_std(hdl, ops,
2178					       V4L2_CID_HUE,
2179					       alvium->min_hue,
2180					       alvium->max_hue,
2181					       alvium->inc_hue,
2182					       alvium->dft_hue);
2183
2184	if (alvium->avail_ft.contrast)
2185		ctrls->contrast = v4l2_ctrl_new_std(hdl, ops,
2186						    V4L2_CID_CONTRAST,
2187						    alvium->min_contrast,
2188						    alvium->max_contrast,
2189						    alvium->inc_contrast,
2190						    alvium->dft_contrast);
2191
2192	if (alvium->avail_ft.gamma)
2193		ctrls->gamma = v4l2_ctrl_new_std(hdl, ops,
2194						 V4L2_CID_GAMMA,
2195						 alvium->min_gamma,
2196						 alvium->max_gamma,
2197						 alvium->inc_gamma,
2198						 alvium->dft_gamma);
2199
2200	if (alvium->avail_ft.sharp)
2201		ctrls->sharpness = v4l2_ctrl_new_std(hdl, ops,
2202						     V4L2_CID_SHARPNESS,
2203						     alvium->min_sharp,
2204						     alvium->max_sharp,
2205						     alvium->inc_sharp,
2206						     alvium->dft_sharp);
2207
2208	if (alvium->avail_ft.rev_x)
2209		ctrls->hflip = v4l2_ctrl_new_std(hdl, ops,
2210						 V4L2_CID_HFLIP,
2211						 0, 1, 1, 0);
2212
2213	if (alvium->avail_ft.rev_y)
2214		ctrls->vflip = v4l2_ctrl_new_std(hdl, ops,
2215						 V4L2_CID_VFLIP,
2216						 0, 1, 1, 0);
2217
2218	if (hdl->error) {
2219		ret = hdl->error;
2220		goto free_ctrls;
2221	}
2222
2223	ret = v4l2_fwnode_device_parse(&alvium->i2c_client->dev, &props);
2224	if (ret)
2225		goto free_ctrls;
2226
2227	ret = v4l2_ctrl_new_fwnode_properties(hdl, ops, &props);
2228	if (ret)
2229		goto free_ctrls;
2230
2231	alvium->sd.ctrl_handler = hdl;
2232	return 0;
2233
2234free_ctrls:
2235	v4l2_ctrl_handler_free(hdl);
2236	return ret;
2237}
2238
2239static const struct v4l2_subdev_core_ops alvium_core_ops = {
2240	.log_status = v4l2_ctrl_subdev_log_status,
2241};
2242
2243static const struct v4l2_subdev_video_ops alvium_video_ops = {
2244	.s_stream		= alvium_s_stream,
2245};
2246
2247static const struct v4l2_subdev_pad_ops alvium_pad_ops = {
2248	.enum_mbus_code = alvium_enum_mbus_code,
2249	.enum_frame_size = alvium_enum_frame_size,
2250	.get_fmt = v4l2_subdev_get_fmt,
2251	.set_fmt = alvium_set_fmt,
2252	.get_selection = alvium_get_selection,
2253	.set_selection = alvium_set_selection,
2254	.get_frame_interval = v4l2_subdev_get_frame_interval,
2255	.set_frame_interval = alvium_s_frame_interval,
2256};
2257
2258static const struct v4l2_subdev_internal_ops alvium_internal_ops = {
2259	.init_state = alvium_init_state,
2260};
2261
2262static const struct v4l2_subdev_ops alvium_subdev_ops = {
2263	.core	= &alvium_core_ops,
2264	.pad	= &alvium_pad_ops,
2265	.video	= &alvium_video_ops,
2266};
2267
2268static int alvium_subdev_init(struct alvium_dev *alvium)
2269{
2270	struct i2c_client *client = alvium->i2c_client;
2271	struct device *dev = &alvium->i2c_client->dev;
2272	struct v4l2_subdev *sd = &alvium->sd;
2273	int ret;
2274
2275	/* Setup the initial mode */
2276	alvium->mode.fmt = alvium_csi2_default_fmt;
2277	alvium->mode.width = alvium_csi2_default_fmt.width;
2278	alvium->mode.height = alvium_csi2_default_fmt.height;
2279	alvium->mode.crop.left = alvium->min_offx;
2280	alvium->mode.crop.top = alvium->min_offy;
2281	alvium->mode.crop.width = alvium_csi2_default_fmt.width;
2282	alvium->mode.crop.height = alvium_csi2_default_fmt.height;
2283
2284	/* init alvium sd */
2285	v4l2_i2c_subdev_init(sd, client, &alvium_subdev_ops);
2286
2287	sd->internal_ops = &alvium_internal_ops;
2288	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
2289	alvium->pad.flags = MEDIA_PAD_FL_SOURCE;
2290	sd->entity.function = MEDIA_ENT_F_CAM_SENSOR;
2291
2292	ret = media_entity_pads_init(&sd->entity, 1, &alvium->pad);
2293	if (ret) {
2294		dev_err(dev, "Could not register media entity\n");
2295		return ret;
2296	}
2297
2298	ret = alvium_ctrl_init(alvium);
2299	if (ret) {
2300		dev_err(dev, "Control initialization error %d\n", ret);
2301		goto entity_cleanup;
2302	}
2303
2304	alvium->sd.state_lock = alvium->ctrls.handler.lock;
2305
2306	ret = v4l2_subdev_init_finalize(sd);
2307	if (ret < 0) {
2308		dev_err(dev, "subdev initialization error %d\n", ret);
2309		goto err_ctrls;
2310	}
2311
2312	return 0;
2313
2314err_ctrls:
2315	v4l2_ctrl_handler_free(&alvium->ctrls.handler);
2316entity_cleanup:
2317	media_entity_cleanup(&alvium->sd.entity);
2318	return ret;
2319}
2320
2321static void alvium_subdev_cleanup(struct alvium_dev *alvium)
2322{
2323	v4l2_fwnode_endpoint_free(&alvium->ep);
2324	v4l2_subdev_cleanup(&alvium->sd);
2325	media_entity_cleanup(&alvium->sd.entity);
2326	v4l2_ctrl_handler_free(&alvium->ctrls.handler);
2327}
2328
2329static int alvium_get_dt_data(struct alvium_dev *alvium)
2330{
2331	struct device *dev = &alvium->i2c_client->dev;
2332	struct fwnode_handle *fwnode = dev_fwnode(dev);
2333	struct fwnode_handle *endpoint;
2334
2335	if (!fwnode)
2336		return -EINVAL;
2337
2338	/* Only CSI2 is supported for now: */
2339	alvium->ep.bus_type = V4L2_MBUS_CSI2_DPHY;
2340
2341	endpoint = fwnode_graph_get_endpoint_by_id(fwnode, 0, 0, 0);
2342	if (!endpoint) {
2343		dev_err(dev, "endpoint node not found\n");
2344		return -EINVAL;
2345	}
2346
2347	if (v4l2_fwnode_endpoint_alloc_parse(endpoint, &alvium->ep)) {
2348		dev_err(dev, "could not parse endpoint\n");
2349		goto error_out;
2350	}
2351
2352	if (!alvium->ep.nr_of_link_frequencies) {
2353		dev_err(dev, "no link frequencies defined");
2354		goto error_out;
2355	}
2356
2357	return 0;
2358
2359error_out:
2360	v4l2_fwnode_endpoint_free(&alvium->ep);
2361	fwnode_handle_put(endpoint);
2362
2363	return -EINVAL;
2364}
2365
2366static int alvium_set_power(struct alvium_dev *alvium, bool on)
2367{
2368	int ret;
2369
2370	if (!on)
2371		return regulator_disable(alvium->reg_vcc);
2372
2373	ret = regulator_enable(alvium->reg_vcc);
2374	if (ret)
2375		return ret;
2376
2377	/* alvium boot time 7s */
2378	msleep(7000);
2379	return 0;
2380}
2381
2382static int alvium_runtime_resume(struct device *dev)
2383{
2384	struct v4l2_subdev *sd = dev_get_drvdata(dev);
2385	struct alvium_dev *alvium = sd_to_alvium(sd);
2386	int ret;
2387
2388	ret = alvium_set_power(alvium, true);
2389	if (ret)
2390		return ret;
2391
2392	ret = alvium_hw_init(alvium);
2393	if (ret) {
2394		alvium_set_power(alvium, false);
2395		return ret;
2396	}
2397
2398	return 0;
2399}
2400
2401static int alvium_runtime_suspend(struct device *dev)
2402{
2403	struct v4l2_subdev *sd = dev_get_drvdata(dev);
2404	struct alvium_dev *alvium = sd_to_alvium(sd);
2405
2406	alvium_set_power(alvium, false);
2407
2408	return 0;
2409}
2410
2411static const struct dev_pm_ops alvium_pm_ops = {
2412	RUNTIME_PM_OPS(alvium_runtime_suspend, alvium_runtime_resume, NULL)
2413};
2414
2415static int alvium_probe(struct i2c_client *client)
2416{
2417	struct device *dev = &client->dev;
2418	struct alvium_dev *alvium;
2419	int ret;
2420
2421	alvium = devm_kzalloc(dev, sizeof(*alvium), GFP_KERNEL);
2422	if (!alvium)
2423		return -ENOMEM;
2424
2425	alvium->i2c_client = client;
2426
2427	alvium->regmap = devm_cci_regmap_init_i2c(client, 16);
2428	if (IS_ERR(alvium->regmap))
2429		return PTR_ERR(alvium->regmap);
2430
2431	ret = alvium_get_dt_data(alvium);
2432	if (ret)
2433		return ret;
2434
2435	alvium->reg_vcc = devm_regulator_get_optional(dev, "vcc-ext-in");
2436	if (IS_ERR(alvium->reg_vcc))
2437		return dev_err_probe(dev, PTR_ERR(alvium->reg_vcc),
2438				     "no vcc-ext-in regulator provided\n");
2439
2440	ret = alvium_set_power(alvium, true);
2441	if (ret)
2442		goto err_powerdown;
2443
2444	if (!alvium_is_alive(alvium)) {
2445		ret = -ENODEV;
2446		dev_err_probe(dev, ret, "Device detection failed\n");
2447		goto err_powerdown;
2448	}
2449
2450	ret = alvium_get_hw_info(alvium);
2451	if (ret) {
2452		dev_err_probe(dev, ret, "get_hw_info fail\n");
2453		goto err_powerdown;
2454	}
2455
2456	ret = alvium_hw_init(alvium);
2457	if (ret) {
2458		dev_err_probe(dev, ret, "hw_init fail\n");
2459		goto err_powerdown;
2460	}
2461
2462	ret = alvium_setup_mipi_fmt(alvium);
2463	if (ret) {
2464		dev_err_probe(dev, ret, "setup_mipi_fmt fail\n");
2465		goto err_powerdown;
2466	}
2467
2468	/*
2469	 * Enable runtime PM without autosuspend:
2470	 *
2471	 * Don't use pm autosuspend (alvium have ~7s boot time).
2472	 * Alvium has been powered manually:
2473	 *  - mark it as active
2474	 *  - increase the usage count without resuming the device.
2475	 */
2476	pm_runtime_set_active(dev);
2477	pm_runtime_get_noresume(dev);
2478	pm_runtime_enable(dev);
2479
2480	/* Initialize the V4L2 subdev. */
2481	ret = alvium_subdev_init(alvium);
2482	if (ret)
2483		goto err_pm;
2484
2485	ret = v4l2_async_register_subdev(&alvium->sd);
2486	if (ret < 0) {
2487		dev_err_probe(dev, ret, "Could not register v4l2 device\n");
2488		goto err_subdev;
2489	}
2490
2491	return 0;
2492
2493err_subdev:
2494	alvium_subdev_cleanup(alvium);
2495err_pm:
2496	pm_runtime_disable(dev);
2497	pm_runtime_put_noidle(dev);
2498	kfree(alvium->alvium_csi2_fmt);
2499err_powerdown:
2500	alvium_set_power(alvium, false);
2501
2502	return ret;
2503}
2504
2505static void alvium_remove(struct i2c_client *client)
2506{
2507	struct v4l2_subdev *sd = i2c_get_clientdata(client);
2508	struct alvium_dev *alvium = sd_to_alvium(sd);
2509	struct device *dev = &alvium->i2c_client->dev;
2510
2511	v4l2_async_unregister_subdev(sd);
2512	alvium_subdev_cleanup(alvium);
2513	kfree(alvium->alvium_csi2_fmt);
2514	/*
2515	 * Disable runtime PM. In case runtime PM is disabled in the kernel,
2516	 * make sure to turn power off manually.
2517	 */
2518	pm_runtime_disable(dev);
2519	if (!pm_runtime_status_suspended(dev))
2520		alvium_set_power(alvium, false);
2521	pm_runtime_set_suspended(dev);
2522}
2523
2524static const struct of_device_id alvium_of_ids[] = {
2525	{ .compatible = "alliedvision,alvium-csi2", },
2526	{ }
2527};
2528MODULE_DEVICE_TABLE(of, alvium_of_ids);
2529
2530static struct i2c_driver alvium_i2c_driver = {
2531	.driver = {
2532		.name = "alvium-csi2",
2533		.pm = pm_ptr(&alvium_pm_ops),
2534		.of_match_table = alvium_of_ids,
2535	},
2536	.probe = alvium_probe,
2537	.remove = alvium_remove,
2538};
2539
2540module_i2c_driver(alvium_i2c_driver);
2541
2542MODULE_DESCRIPTION("Allied Vision's Alvium Camera Driver");
2543MODULE_AUTHOR("Tommaso Merciai <tomm.merciai@gmail.com>");
2544MODULE_AUTHOR("Martin Hecht <martin.hecht@avnet.eu>");
2545MODULE_AUTHOR("Avnet Silica Software & Services EMEA");
2546MODULE_LICENSE("GPL");
~/ Read-only file preview.