File Index
Files and directories
Sign in
FILE

vd55g1.c

File preview with syntax highlighting.

linux-6.19.14/drivers/media/i2c/vd55g1.c C
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Driver for VD55G1 global shutter sensor family driver
   4 *
   5 * Copyright (C) 2025 STMicroelectronics SA
   6 */
   7
   8#include <linux/clk.h>
   9#include <linux/delay.h>
  10#include <linux/gpio/consumer.h>
  11#include <linux/i2c.h>
  12#include <linux/iopoll.h>
  13#include <linux/module.h>
  14#include <linux/pm_runtime.h>
  15#include <linux/property.h>
  16#include <linux/regmap.h>
  17#include <linux/regulator/consumer.h>
  18#include <linux/unaligned.h>
  19#include <linux/units.h>
  20
  21#include <media/mipi-csi2.h>
  22#include <media/v4l2-async.h>
  23#include <media/v4l2-cci.h>
  24#include <media/v4l2-ctrls.h>
  25#include <media/v4l2-device.h>
  26#include <media/v4l2-event.h>
  27#include <media/v4l2-fwnode.h>
  28#include <media/v4l2-subdev.h>
  29
  30/* Register Map */
  31#define VD55G1_REG_MODEL_ID				CCI_REG32_LE(0x0000)
  32#define VD55G1_MODEL_ID_VD55G1				0x53354731 /* Mono */
  33#define VD55G1_MODEL_ID_VD65G4				0x53354733 /* RGB */
  34#define VD55G1_REG_REVISION				CCI_REG16_LE(0x0004)
  35#define VD55G1_REVISION_CCB				0x2020
  36#define VD55G1_REVISION_BAYER				0x3030
  37#define VD55G1_REG_FWPATCH_REVISION			CCI_REG16_LE(0x0012)
  38#define VD55G1_REG_FWPATCH_START_ADDR			CCI_REG8(0x2000)
  39#define VD55G1_REG_SYSTEM_FSM				CCI_REG8(0x001c)
  40#define VD55G1_SYSTEM_FSM_READY_TO_BOOT			0x01
  41#define VD55G1_SYSTEM_FSM_SW_STBY			0x02
  42#define VD55G1_SYSTEM_FSM_STREAMING			0x03
  43#define VD55G1_REG_BOOT					CCI_REG8(0x0200)
  44#define VD55G1_BOOT_BOOT				1
  45#define VD55G1_BOOT_PATCH_AND_BOOT			2
  46#define VD55G1_REG_STBY					CCI_REG8(0x0201)
  47#define VD55G1_STBY_START_STREAM			1
  48#define VD55G1_REG_STREAMING				CCI_REG8(0x0202)
  49#define VD55G1_STREAMING_STOP_STREAM			1
  50#define VD55G1_REG_EXT_CLOCK				CCI_REG32_LE(0x0220)
  51#define VD55G1_REG_LINE_LENGTH				CCI_REG16_LE(0x0300)
  52#define VD55G1_REG_ORIENTATION				CCI_REG8(0x0302)
  53#define VD55G1_REG_FORMAT_CTRL				CCI_REG8(0x030a)
  54#define VD55G1_REG_OIF_CTRL				CCI_REG16_LE(0x030c)
  55#define VD55G1_REG_ISL_ENABLE				CCI_REG16_LE(0x326)
  56#define VD55G1_REG_OIF_IMG_CTRL				CCI_REG8(0x030f)
  57#define VD55G1_REG_MIPI_DATA_RATE			CCI_REG32_LE(0x0224)
  58#define VD55G1_REG_PATGEN_CTRL				CCI_REG16_LE(0x0304)
  59#define VD55G1_PATGEN_TYPE_SHIFT			4
  60#define VD55G1_PATGEN_ENABLE				BIT(0)
  61#define VD55G1_REG_MANUAL_ANALOG_GAIN			CCI_REG8(0x0501)
  62#define VD55G1_REG_MANUAL_COARSE_EXPOSURE		CCI_REG16_LE(0x0502)
  63#define VD55G1_REG_MANUAL_DIGITAL_GAIN			CCI_REG16_LE(0x0504)
  64#define VD55G1_REG_APPLIED_COARSE_EXPOSURE		CCI_REG16_LE(0x00e8)
  65#define VD55G1_REG_APPLIED_ANALOG_GAIN			CCI_REG16_LE(0x00ea)
  66#define VD55G1_REG_APPLIED_DIGITAL_GAIN			CCI_REG16_LE(0x00ec)
  67#define VD55G1_REG_AE_FORCE_COLDSTART			CCI_REG8(0x0308)
  68#define VD55G1_REG_AE_COLDSTART_EXP_TIME		CCI_REG32_LE(0x0374)
  69#define VD55G1_REG_READOUT_CTRL				CCI_REG8(0x052e)
  70#define VD55G1_READOUT_CTRL_BIN_MODE_NORMAL		0
  71#define VD55G1_READOUT_CTRL_BIN_MODE_DIGITAL_X2		1
  72#define VD55G1_REG_DUSTER_CTRL				CCI_REG8(0x03ae)
  73#define VD55G1_DUSTER_ENABLE				BIT(0)
  74#define VD55G1_DUSTER_DISABLE				0
  75#define VD55G1_DUSTER_DYN_ENABLE			BIT(1)
  76#define VD55G1_DUSTER_RING_ENABLE			BIT(4)
  77#define VD55G1_REG_AE_TARGET_PERCENTAGE			CCI_REG8(0x0486)
  78#define VD55G1_REG_NEXT_CTX				CCI_REG16_LE(0x03e4)
  79#define VD55G1_REG_EXPOSURE_USE_CASES			CCI_REG8(0x0312)
  80#define VD55G1_EXPOSURE_USE_CASES_MULTI_CONTEXT		BIT(2)
  81#define VD55G1_REG_EXPOSURE_MAX_COARSE			CCI_REG16_LE(0x0372)
  82#define VD55G1_EXPOSURE_MAX_COARSE_DEF			0x7fff
  83#define VD55G1_EXPOSURE_MAX_COARSE_SUB			446
  84#define VD55G1_REG_CTX_REPEAT_COUNT_CTX0		CCI_REG16_LE(0x03dc)
  85#define VD55G1_REG_CTX_REPEAT_COUNT_CTX1		CCI_REG16_LE(0x03de)
  86
  87#define VD55G1_REG_EXP_MODE(ctx) \
  88	CCI_REG8(0x0500 + VD55G1_CTX_OFFSET * (ctx))
  89#define VD55G1_REG_FRAME_LENGTH(ctx) \
  90	CCI_REG32_LE(0x050c + VD55G1_CTX_OFFSET * (ctx))
  91#define VD55G1_REG_X_START(ctx) \
  92	CCI_REG16_LE(0x0514 + VD55G1_CTX_OFFSET * (ctx))
  93#define VD55G1_REG_X_WIDTH(ctx) \
  94	CCI_REG16_LE(0x0516 + VD55G1_CTX_OFFSET * (ctx))
  95#define VD55G1_REG_Y_START(ctx) \
  96	CCI_REG16_LE(0x0510 + VD55G1_CTX_OFFSET * (ctx))
  97#define VD55G1_REG_Y_HEIGHT(ctx) \
  98	CCI_REG16_LE(0x0512 + VD55G1_CTX_OFFSET * (ctx))
  99#define VD55G1_REG_GPIO_0_CTRL(ctx) \
 100	CCI_REG8(0x051d + VD55G1_CTX_OFFSET * (ctx))
 101#define VD55G1_GPIO_MODE_FSYNC_OUT			0x00
 102#define VD55G1_GPIO_MODE_IN				0x01
 103#define VD55G1_GPIO_MODE_STROBE				0x02
 104#define VD55G1_REG_VT_MODE(ctx) \
 105	CCI_REG8(0x0536 + VD55G1_CTX_OFFSET * (ctx))
 106#define VD55G1_VT_MODE_NORMAL				0
 107#define VD55G1_VT_MODE_SUBTRACTION			1
 108#define VD55G1_REG_MASK_FRAME_CTRL(ctx) \
 109	CCI_REG8(0x0537 + VD55G1_CTX_OFFSET * (ctx))
 110#define VD55G1_MASK_FRAME_CTRL_OUTPUT			0
 111#define VD55G1_MASK_FRAME_CTRL_MASK			1
 112#define VD55G1_REG_EXPOSURE_INSTANCE(ctx) \
 113	CCI_REG32_LE(0x52D + VD55G1_CTX_OFFSET * (ctx))
 114
 115#define VD55G1_WIDTH					804
 116#define VD55G1_HEIGHT					704
 117#define VD55G1_MODE_DEF					0
 118#define VD55G1_NB_GPIOS					4
 119#define VD55G1_MBUS_CODE_DEF				0
 120#define VD55G1_DGAIN_DEF				256
 121#define VD55G1_AGAIN_DEF				19
 122#define VD55G1_EXPO_MAX_TERM				64
 123#define VD55G1_EXPO_DEF					500
 124#define VD55G1_LINE_LENGTH_MIN				1128
 125#define VD55G1_LINE_LENGTH_SUB_MIN			1344
 126#define VD55G1_VBLANK_MIN				86
 127#define VD55G1_VBLANK_MAX				0xffff
 128#define VD55G1_FRAME_LENGTH_DEF				1860 /* 60 fps */
 129#define VD55G1_MIPI_MARGIN				900
 130#define VD55G1_CTX_OFFSET				0x50
 131#define VD55G1_FWPATCH_REVISION_MAJOR			2
 132#define VD55G1_FWPATCH_REVISION_MINOR			9
 133#define VD55G1_XCLK_FREQ_MIN				(6 * HZ_PER_MHZ)
 134#define VD55G1_XCLK_FREQ_MAX				(27 * HZ_PER_MHZ)
 135#define VD55G1_MIPI_RATE_MIN				(250 * MEGA)
 136#define VD55G1_MIPI_RATE_MAX				(1200 * MEGA)
 137
 138#define VD55G1_MODEL_ID_NAME(id) \
 139	((id) == VD55G1_MODEL_ID_VD55G1 ? "vd55g1" : "vd65g4")
 140
 141static const u8 vd55g1_patch_array[] = {
 142	0x44, 0x03, 0x09, 0x02, 0xe6, 0x01, 0x42, 0x00, 0xea, 0x01, 0x42, 0x00,
 143	0xf0, 0x01, 0x42, 0x00, 0xe6, 0x01, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00,
 144	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 145	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 146	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 147	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 148	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 149	0x00, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0xfa, 0x68, 0x40, 0x00, 0xe8,
 150	0x09, 0xbe, 0x4c, 0x08, 0x00, 0xf2, 0x93, 0xdd, 0x1c, 0x00, 0xc0, 0xe2,
 151	0x93, 0xdd, 0xc3, 0xc1, 0x0c, 0x04, 0x00, 0xfa, 0x6b, 0x80, 0x98, 0x7f,
 152	0xfc, 0xef, 0x11, 0xc1, 0x0f, 0x82, 0x69, 0xbe, 0x0f, 0xac, 0x58, 0x40,
 153	0x00, 0xe8, 0x0c, 0x0c, 0x00, 0xf2, 0x93, 0xdd, 0x1c, 0x00, 0x40, 0xe3,
 154	0x93, 0xdd, 0xc3, 0xc1, 0x0c, 0x04, 0x84, 0xfa, 0x46, 0x0e, 0xe8, 0xe0,
 155	0x08, 0xde, 0x4a, 0x40, 0x84, 0xe0, 0xa5, 0x86, 0xa8, 0x7d, 0xfc, 0xef,
 156	0x6b, 0x80, 0x01, 0xbf, 0x28, 0x77, 0x0c, 0xef, 0x0b, 0x0e, 0x21, 0x78,
 157	0x06, 0xc0, 0x0b, 0xa5, 0xb5, 0x84, 0x06, 0x42, 0x98, 0xe1, 0x01, 0x81,
 158	0x01, 0x42, 0x38, 0xe0, 0x0c, 0xc4, 0x0e, 0x84, 0x46, 0x02, 0x84, 0xe0,
 159	0x0c, 0x84, 0x11, 0x81, 0x21, 0x81, 0x31, 0x81, 0x41, 0x81, 0x51, 0x81,
 160	0xc1, 0x81, 0x05, 0x83, 0x0c, 0x0c, 0x84, 0xf2, 0x93, 0xdd, 0x06, 0x40,
 161	0x98, 0xe1, 0xc8, 0x80, 0x58, 0x82, 0x48, 0xc0, 0x38, 0xc2, 0x29, 0x00,
 162	0x10, 0xe0, 0x19, 0x00, 0x14, 0xe0, 0x09, 0x00, 0x38, 0xe0, 0x5f, 0xb8,
 163	0x5f, 0xa8, 0x5f, 0xa6, 0x5f, 0xa4, 0x5f, 0xa2, 0x5f, 0xa0, 0x56, 0x41,
 164	0x98, 0xe1, 0x18, 0x82, 0x28, 0x80, 0x38, 0xc0, 0x5f, 0xa2, 0x19, 0x00,
 165	0x20, 0xf8, 0x5f, 0xa4, 0x28, 0xc2, 0x5f, 0xa6, 0x39, 0x00, 0x10, 0xe0,
 166	0x5f, 0xa2, 0x19, 0x00, 0x14, 0xe0, 0x5f, 0xa4, 0x29, 0x00, 0x18, 0xe0,
 167	0x5f, 0xa6, 0x39, 0x00, 0x40, 0xe0, 0x5f, 0xa2, 0x19, 0x00, 0x44, 0xe0,
 168	0x5f, 0xa4, 0x29, 0x00, 0x1c, 0xe0, 0x5f, 0xa6, 0x39, 0x00, 0x38, 0xe0,
 169	0x5f, 0xa2, 0x19, 0x00, 0x20, 0xe0, 0x5f, 0xa4, 0x29, 0x00, 0x24, 0xe0,
 170	0x5f, 0xa6, 0x39, 0x00, 0x28, 0xe0, 0x5f, 0xa2, 0x19, 0x00, 0x2c, 0xe0,
 171	0x5f, 0xa4, 0x29, 0x00, 0x30, 0xe0, 0x5f, 0xa6, 0x09, 0x00, 0x34, 0xe0,
 172	0x5f, 0xa2, 0x5f, 0xa4, 0x5f, 0xa0, 0x4a, 0x0a, 0xfc, 0xfb, 0xe5, 0x82,
 173	0x08, 0xde, 0x4a, 0x40, 0x88, 0xe0, 0xf6, 0x40, 0x00, 0xe0, 0x01, 0x4e,
 174	0x99, 0x78, 0x0a, 0xc0, 0x85, 0x80, 0x98, 0x40, 0x00, 0xe8, 0x35, 0x81,
 175	0xa8, 0x40, 0x00, 0xe8, 0x0b, 0x8c, 0x0c, 0x0c, 0x84, 0xf2, 0xd5, 0xed,
 176	0x83, 0xc1, 0x13, 0xc5, 0x93, 0xdd, 0xc3, 0xc1, 0x83, 0xc1, 0x13, 0xc3,
 177	0x93, 0xdd, 0xc3, 0xc1, 0x4c, 0x04, 0x04, 0xfa, 0xc6, 0x0f, 0x94, 0xe0,
 178	0x19, 0x0e, 0xc9, 0x65, 0x01, 0xc0, 0x28, 0xde, 0x0a, 0x42, 0x80, 0xe0,
 179	0x24, 0x02, 0x00, 0xfc, 0x16, 0xde, 0xa5, 0x8a, 0x19, 0x00, 0xb8, 0xe0,
 180	0x10, 0x02, 0x0c, 0xec, 0x1d, 0xe6, 0x14, 0x02, 0x88, 0x80, 0x4e, 0x04,
 181	0x01, 0x00, 0x10, 0x80, 0x25, 0x02, 0x08, 0x9c, 0x86, 0x02, 0x00, 0x80,
 182	0x08, 0x44, 0x00, 0x98, 0x55, 0x81, 0x11, 0x85, 0x45, 0x81, 0x11, 0x89,
 183	0x25, 0x81, 0x11, 0x83, 0x2b, 0x00, 0x24, 0xe0, 0x64, 0xc2, 0x0b, 0x84,
 184	0x08, 0x51, 0x00, 0xef, 0x2b, 0x80, 0x01, 0x83, 0x1b, 0x8c, 0x38, 0x7d,
 185	0x5c, 0xef, 0x18, 0xde, 0x0b, 0xa1, 0x25, 0x82, 0x0b, 0x0e, 0x88, 0xf9,
 186	0x0a, 0x00, 0x00, 0xe8, 0x10, 0x42, 0x04, 0x9c, 0x11, 0x4e, 0x0c, 0x80,
 187	0x10, 0x40, 0x04, 0xf0, 0x4e, 0x05, 0x01, 0x60, 0x10, 0xc0, 0x06, 0x88,
 188	0x10, 0x40, 0xf8, 0xf3, 0x06, 0xde, 0x4c, 0x0c, 0x04, 0xf2, 0x93, 0xdd,
 189	0x0c, 0x04, 0x1c, 0xfe, 0xf6, 0x0f, 0x94, 0xe0, 0x38, 0x9c, 0x46, 0x51,
 190	0xfc, 0xe0, 0x46, 0x49, 0x38, 0xe2, 0x30, 0x46, 0xf8, 0xf3, 0x36, 0x9c,
 191	0xc6, 0x46, 0x0c, 0xe1, 0x34, 0x8c, 0x94, 0xa0, 0x4e, 0xa0, 0x39, 0x06,
 192	0x80, 0xe0, 0x4a, 0x46, 0x94, 0xe0, 0x05, 0x8c, 0x6a, 0x40, 0x80, 0xe0,
 193	0x2c, 0x0c, 0x00, 0xe2, 0x0b, 0x8c, 0xb8, 0x7c, 0x5c, 0xef, 0x0b, 0x8c,
 194	0x9e, 0xa0, 0xf8, 0x40, 0x60, 0xef, 0x0b, 0xa1, 0x5a, 0x40, 0x80, 0xe0,
 195	0x65, 0x88, 0x28, 0x02, 0x01, 0x40, 0x00, 0x80, 0x2a, 0x42, 0x9c, 0xe1,
 196	0x28, 0x49, 0x60, 0xef, 0x96, 0x4d, 0x9c, 0xe1, 0x01, 0x81, 0x06, 0x98,
 197	0xd5, 0x81, 0x09, 0x0e, 0xa1, 0x64, 0x01, 0xc0, 0x4a, 0x40, 0x88, 0xe0,
 198	0x85, 0x80, 0xb8, 0x77, 0xfc, 0xef, 0x35, 0x81, 0xc8, 0x77, 0xfc, 0xef,
 199	0x08, 0x98, 0x4a, 0x00, 0xfc, 0xfb, 0x55, 0xfc, 0xe8, 0x4a, 0x60, 0xef,
 200	0x1a, 0x44, 0x9c, 0xe1, 0x35, 0x81, 0x1a, 0x4e, 0x9c, 0xe9, 0x1c, 0x00,
 201	0x00, 0xe2, 0x0c, 0x0c, 0x1c, 0xf6, 0x93, 0xdd, 0x0d, 0xc3, 0x1a, 0x41,
 202	0x08, 0xe4, 0x0a, 0x40, 0x84, 0xe1, 0x0c, 0x00, 0x00, 0xe2, 0x93, 0xdd,
 203	0x4c, 0x04, 0x1c, 0xfa, 0x86, 0x52, 0xec, 0xe1, 0x08, 0xa6, 0x65, 0x12,
 204	0x24, 0xf8, 0x0e, 0x02, 0x99, 0x7a, 0x00, 0xc0, 0x00, 0x40, 0xa0, 0xf3,
 205	0x06, 0xa6, 0x0b, 0x8c, 0x08, 0x49, 0x00, 0xef, 0x85, 0x12, 0x28, 0xf8,
 206	0x02, 0x02, 0xfc, 0xed, 0xf6, 0x47, 0xfd, 0x6f, 0xe0, 0xff, 0x04, 0xe2,
 207	0x14, 0x04, 0xc0, 0xe0, 0x0f, 0x86, 0x2f, 0xa0, 0x0b, 0x8c, 0x2e, 0xe2,
 208	0x08, 0x48, 0x00, 0xef, 0x86, 0x02, 0x84, 0xfe, 0x0e, 0x05, 0x09, 0x7d,
 209	0x00, 0xc0, 0x05, 0x52, 0x08, 0xf8, 0x18, 0x7d, 0xfc, 0xef, 0x4a, 0x40,
 210	0x80, 0xe0, 0x09, 0x12, 0x04, 0xc0, 0x65, 0x12, 0x20, 0xf8, 0x00, 0x40,
 211	0x40, 0xdc, 0x01, 0x52, 0x04, 0xc0, 0x0e, 0x00, 0x41, 0x78, 0xf5, 0xc5,
 212	0x6d, 0xc0, 0xb5, 0x82, 0x05, 0x10, 0x10, 0xe0, 0x11, 0xf1, 0x0f, 0x82,
 213	0x05, 0x50, 0x10, 0xe0, 0x05, 0x10, 0x10, 0xe0, 0xfe, 0x02, 0xf0, 0xff,
 214	0x0f, 0x82, 0x85, 0x83, 0x15, 0x10, 0x10, 0xe0, 0x16, 0x00, 0x91, 0x6e,
 215	0x69, 0xcd, 0x21, 0xf1, 0x6d, 0xc1, 0x01, 0x83, 0x2f, 0x82, 0x26, 0x00,
 216	0x00, 0x80, 0x2f, 0xa0, 0x25, 0x50, 0x10, 0xe0, 0x05, 0x10, 0x10, 0xe0,
 217	0x11, 0xa1, 0xfe, 0x04, 0xf0, 0xff, 0x06, 0x42, 0x00, 0x80, 0x0f, 0x84,
 218	0x0f, 0xa2, 0x05, 0x50, 0x10, 0xe0, 0x16, 0x00, 0x91, 0x6e, 0x69, 0xcd,
 219	0x6d, 0xc1, 0x71, 0x8d, 0x16, 0x00, 0x79, 0x61, 0x2d, 0xcb, 0x86, 0x0e,
 220	0x00, 0x80, 0x6d, 0xc1, 0x56, 0x0e, 0x00, 0xc0, 0x0b, 0x8c, 0x1b, 0x8e,
 221	0x71, 0x52, 0x0c, 0xf8, 0x08, 0x43, 0x00, 0xef, 0x05, 0x52, 0x14, 0xf8,
 222	0x15, 0x10, 0x28, 0xe0, 0x70, 0x04, 0x04, 0xec, 0x31, 0xe1, 0x29, 0x9e,
 223	0x1f, 0x86, 0x1f, 0xa4, 0x15, 0x50, 0x28, 0xe0, 0x86, 0x42, 0x3c, 0xe0,
 224	0x0e, 0x04, 0x9d, 0x64, 0x9b, 0xc2, 0x05, 0x52, 0x1c, 0xf8, 0x78, 0xa6,
 225	0x48, 0x77, 0xfc, 0xef, 0x4a, 0x40, 0x80, 0xe0, 0x70, 0x4e, 0x10, 0xdc,
 226	0x1e, 0x00, 0x81, 0x70, 0xeb, 0xcb, 0x70, 0x4e, 0xec, 0x93, 0x6d, 0xc1,
 227	0x11, 0x85, 0x36, 0x02, 0x00, 0x80, 0x76, 0xa6, 0x11, 0x52, 0x10, 0xf8,
 228	0x05, 0x10, 0x40, 0xe0, 0xfe, 0x47, 0x0c, 0xff, 0x14, 0x04, 0xa0, 0xe0,
 229	0x0f, 0x86, 0x0f, 0xa4, 0x05, 0x50, 0x40, 0xe0, 0x05, 0x10, 0x28, 0xe0,
 230	0xfe, 0x47, 0xfd, 0x7f, 0xe3, 0xff, 0x14, 0x04, 0xd0, 0xe0, 0x0f, 0x86,
 231	0x2f, 0xa0, 0x20, 0x00, 0x01, 0x6c, 0x00, 0xd0, 0x05, 0x50, 0x28, 0xe0,
 232	0x0b, 0x8c, 0xf8, 0x7e, 0xfc, 0xee, 0x0e, 0x03, 0x59, 0x78, 0xf5, 0xc5,
 233	0x0d, 0xc2, 0x05, 0x52, 0x0c, 0xf8, 0x08, 0xa6, 0x46, 0x42, 0xb4, 0xe0,
 234	0x18, 0x84, 0x00, 0x40, 0xf4, 0x93, 0x00, 0x40, 0x08, 0xdc, 0x1b, 0xa1,
 235	0x06, 0xa6, 0x05, 0x10, 0x40, 0x80, 0x04, 0x00, 0x50, 0x9c, 0x65, 0x8a,
 236	0x05, 0x10, 0x44, 0xe0, 0xf6, 0x43, 0xfd, 0x6f, 0x00, 0xf8, 0x0f, 0x82,
 237	0x06, 0x02, 0x01, 0x60, 0x1e, 0xc0, 0x0f, 0xa2, 0x05, 0x50, 0x44, 0xe0,
 238	0x05, 0x10, 0x44, 0xe0, 0x0e, 0x02, 0x00, 0xf8, 0x0f, 0x82, 0x09, 0xf6,
 239	0x05, 0x50, 0x44, 0xe0, 0x05, 0x10, 0x40, 0xe0, 0x04, 0x00, 0x54, 0xfc,
 240	0x05, 0x50, 0x40, 0xe0, 0x05, 0x10, 0x40, 0xe0, 0x04, 0x00, 0xcc, 0xfc,
 241	0x05, 0x50, 0x40, 0xe0, 0x05, 0x10, 0x40, 0xe0, 0x04, 0x00, 0x4c, 0xfc,
 242	0x05, 0x50, 0x40, 0xe0, 0x05, 0x10, 0x40, 0xe0, 0x04, 0x00, 0xd0, 0xfc,
 243	0x05, 0x50, 0x40, 0xe0, 0x4c, 0x0c, 0x1c, 0xf2, 0x93, 0xdd, 0xc3, 0xc1,
 244	0xc6, 0x40, 0xfc, 0xe0, 0x04, 0x80, 0xc6, 0x44, 0x0c, 0xe1, 0x15, 0x04,
 245	0x0c, 0xf8, 0x0a, 0x80, 0x06, 0x07, 0x04, 0xe0, 0x03, 0x42, 0x48, 0xe1,
 246	0x46, 0x02, 0x40, 0xe2, 0x08, 0xc6, 0x44, 0x88, 0x06, 0x46, 0x0e, 0xe0,
 247	0x86, 0x01, 0x84, 0xe0, 0x33, 0x80, 0x39, 0x06, 0xd8, 0xef, 0x0a, 0x46,
 248	0x80, 0xe0, 0x31, 0xbf, 0x06, 0x06, 0x00, 0xc0, 0x31, 0x48, 0x60, 0xe0,
 249	0x34, 0x88, 0x49, 0x06, 0x40, 0xe1, 0x40, 0x48, 0x7c, 0xf3, 0x41, 0x46,
 250	0x40, 0xe1, 0x24, 0x8a, 0x39, 0x04, 0x10, 0xe0, 0x39, 0xc2, 0x31, 0x44,
 251	0x10, 0xe0, 0x14, 0xc4, 0x1b, 0xa5, 0x11, 0x83, 0x11, 0x40, 0x25, 0x6a,
 252	0x01, 0xc0, 0x08, 0x5c, 0x00, 0xda, 0x15, 0x00, 0xcc, 0xe0, 0x25, 0x00,
 253	0xf8, 0xe0, 0x1b, 0x85, 0x08, 0x5c, 0x00, 0x9a, 0x4e, 0x03, 0x01, 0x60,
 254	0x10, 0xc0, 0x29, 0x00, 0x1c, 0xe4, 0x18, 0x84, 0x20, 0x44, 0xf8, 0xf3,
 255	0x2f, 0xa2, 0x21, 0x40, 0x1c, 0xe4, 0x93, 0xdd, 0x0c, 0x00, 0x80, 0xfa,
 256	0x15, 0x00, 0x3c, 0xe0, 0x21, 0x81, 0x31, 0x85, 0x21, 0x42, 0x60, 0xe0,
 257	0x15, 0x00, 0x44, 0xe0, 0x31, 0x42, 0x40, 0xe1, 0x15, 0x00, 0x34, 0xe0,
 258	0x21, 0x42, 0x20, 0xe0, 0x15, 0x00, 0x34, 0xe0, 0xd6, 0x04, 0x10, 0xe0,
 259	0x23, 0x42, 0x30, 0xe0, 0x15, 0x00, 0x34, 0xe0, 0x86, 0x44, 0x04, 0xe0,
 260	0x23, 0x42, 0x38, 0xe0, 0x05, 0x00, 0x30, 0xe0, 0xc6, 0x02, 0x08, 0xe0,
 261	0x13, 0x40, 0x10, 0xe3, 0xe8, 0x56, 0x40, 0xef, 0x06, 0x40, 0x0c, 0xe1,
 262	0x04, 0x80, 0x06, 0x02, 0x94, 0xe0, 0x2b, 0x02, 0xc4, 0xea, 0x3b, 0x00,
 263	0x78, 0xe2, 0x20, 0x44, 0xfd, 0x73, 0x07, 0xc0, 0x30, 0x46, 0x01, 0x70,
 264	0xf8, 0xc0, 0x3f, 0xa4, 0x33, 0x40, 0x78, 0xe2, 0x0a, 0x84, 0x0c, 0x08,
 265	0x80, 0xf2, 0xf8, 0x3b, 0x3c, 0xff, 0xc3, 0xc1, 0x06, 0x40, 0x0c, 0xe1,
 266	0x04, 0x80, 0x1b, 0x00, 0x40, 0xe4, 0x19, 0xc2, 0x13, 0x40, 0x40, 0xe4,
 267	0x1b, 0x00, 0x40, 0xe4, 0x19, 0xc4, 0x13, 0x40, 0x40, 0xe4, 0x93, 0xdd,
 268	0xc6, 0x43, 0xec, 0xe0, 0x46, 0x41, 0xfc, 0xe0, 0x24, 0x84, 0x04, 0x80,
 269	0x31, 0x81, 0x4a, 0x44, 0x80, 0xe0, 0x86, 0x44, 0x0c, 0xe1, 0x09, 0x00,
 270	0x6c, 0xe0, 0xc4, 0x8a, 0x8e, 0x47, 0xfc, 0x9f, 0x01, 0x42, 0x51, 0x78,
 271	0x0c, 0xc0, 0x31, 0x58, 0x90, 0xe0, 0x34, 0x8a, 0x41, 0xbf, 0x06, 0x08,
 272	0x00, 0xc0, 0x41, 0x46, 0xa0, 0xe0, 0x34, 0x8a, 0x51, 0x81, 0xf6, 0x0b,
 273	0x00, 0xc0, 0x51, 0x46, 0xd0, 0xe0, 0x34, 0x8a, 0x01, 0xbf, 0x51, 0x46,
 274	0xe0, 0xe0, 0x44, 0x84, 0x0a, 0x48, 0x84, 0xe0, 0x75, 0x86, 0x54, 0xca,
 275	0x49, 0x88, 0x44, 0x06, 0x88, 0xe1, 0x36, 0x94, 0x4a, 0x46, 0x80, 0xe0,
 276	0x34, 0xca, 0x47, 0xc6, 0x11, 0x8d, 0x41, 0x46, 0xd0, 0xe0, 0x34, 0x88,
 277	0x76, 0x02, 0x00, 0xc0, 0x06, 0x00, 0x00, 0xc0, 0x16, 0x8c, 0x14, 0x88,
 278	0x01, 0x42, 0xc0, 0xe1, 0x01, 0x42, 0xe0, 0xe1, 0x01, 0x42, 0xf0, 0xe1,
 279	0x93, 0xdd, 0x34, 0xca, 0x41, 0x85, 0x46, 0x8c, 0x34, 0xca, 0x06, 0x48,
 280	0x00, 0xe0, 0x41, 0x46, 0xd0, 0xe0, 0x34, 0x88, 0x41, 0x83, 0x46, 0x8c,
 281	0x34, 0x88, 0x01, 0x46, 0xc0, 0xe1, 0x01, 0x46, 0xe0, 0xe1, 0x01, 0x46,
 282	0xf0, 0xe1, 0x09, 0x02, 0x20, 0xe0, 0x14, 0xca, 0x03, 0x42, 0x58, 0xe0,
 283	0x93, 0xdd, 0xc3, 0xc1, 0x4c, 0x04, 0x04, 0xfa, 0x46, 0x4e, 0x08, 0xe1,
 284	0x06, 0x4c, 0x0c, 0xe1, 0x0a, 0x9e, 0x14, 0x98, 0x05, 0x42, 0x44, 0xe0,
 285	0x10, 0x00, 0xe1, 0x65, 0x03, 0xc0, 0x78, 0x41, 0x00, 0xe8, 0x08, 0x9c,
 286	0x0b, 0xa1, 0x04, 0x98, 0x06, 0x02, 0x10, 0x80, 0x13, 0x40, 0xf8, 0x86,
 287	0x65, 0x82, 0x00, 0x00, 0xe1, 0x65, 0x03, 0xc0, 0xa8, 0x40, 0x00, 0xe8,
 288	0x14, 0x98, 0x04, 0x00, 0xa0, 0xfc, 0x03, 0x42, 0x00, 0xe7, 0x4c, 0x0c,
 289	0x04, 0xf2, 0x93, 0xdd, 0x0a, 0x80, 0x93, 0xdd, 0x0c, 0x04, 0x00, 0xfa,
 290	0x06, 0x02, 0xec, 0xe1, 0x64, 0x84, 0x15, 0x0c, 0x2c, 0xe0, 0x14, 0x02,
 291	0xa0, 0xfc, 0x15, 0x4c, 0x2c, 0xe0, 0xd8, 0x40, 0x00, 0xe8, 0x14, 0xd8,
 292	0x09, 0x82, 0x14, 0x02, 0x00, 0xfc, 0x1f, 0xa0, 0x1e, 0xd8, 0x01, 0x85,
 293	0x0c, 0x0c, 0x00, 0xf2, 0xe8, 0x32, 0x2c, 0xff, 0x93, 0xdd, 0xc3, 0xc1,
 294	0x0c, 0x04, 0x00, 0xfa, 0x6b, 0x80, 0xf6, 0x01, 0x94, 0xe0, 0x08, 0x80,
 295	0x4a, 0x40, 0x80, 0xe0, 0x45, 0x86, 0x06, 0x40, 0x0c, 0xe1, 0x04, 0x80,
 296	0xc6, 0x02, 0x40, 0xe2, 0x09, 0x00, 0xd0, 0xe0, 0x14, 0x84, 0x1b, 0xa5,
 297	0x15, 0x84, 0x07, 0xc5, 0x09, 0x82, 0x18, 0x41, 0x00, 0xe8, 0x46, 0x43,
 298	0xfc, 0xe0, 0x14, 0x84, 0x19, 0x02, 0xd8, 0xe0, 0x19, 0x82, 0x0b, 0x83,
 299	0x16, 0x00, 0x00, 0xc0, 0x01, 0x4c, 0x00, 0xc0, 0x0c, 0x0c, 0x00, 0xf2,
 300	0x93, 0xdd, 0xc3, 0xc1, 0x4a, 0x00, 0x00, 0xe0, 0x0c, 0x00, 0x00, 0xe2,
 301	0x93, 0xdd, 0xc3, 0xc1, 0x46, 0x40, 0x84, 0xe0, 0x11, 0xaf, 0x13, 0x40,
 302	0x6c, 0xec, 0x11, 0xb3, 0x13, 0x40, 0x70, 0xec, 0xc6, 0x43, 0xf0, 0xe0,
 303	0x13, 0x40, 0xdc, 0xec, 0xc6, 0x02, 0x24, 0xe0, 0x1c, 0x80, 0x93, 0xdd,
 304	0x4c, 0x00, 0x00, 0xfa, 0xc8, 0x60, 0x7c, 0xef, 0xe8, 0x61, 0x7c, 0xef,
 305	0x28, 0x7e, 0x80, 0xef, 0xc6, 0x40, 0x98, 0xe1, 0x11, 0x83, 0x16, 0x80,
 306	0x46, 0x01, 0x10, 0xe1, 0x11, 0x81, 0x16, 0x80, 0x4c, 0x08, 0x00, 0xf2,
 307	0x93, 0xdd, 0xc3, 0xc1, 0x0c, 0x04, 0x0c, 0xfa, 0x6b, 0x80, 0x04, 0x98,
 308	0x7b, 0x82, 0x56, 0x42, 0xb4, 0xe0, 0x88, 0x84, 0x05, 0x00, 0x10, 0xe0,
 309	0x09, 0x86, 0x0b, 0xa5, 0x46, 0x02, 0x00, 0x80, 0x06, 0x05, 0x00, 0x80,
 310	0x25, 0x82, 0x0b, 0xa3, 0xa5, 0x80, 0x0b, 0xa1, 0x06, 0x00, 0xf4, 0xef,
 311	0xd5, 0x84, 0x11, 0x85, 0x21, 0x91, 0x0b, 0x8e, 0x88, 0x74, 0x10, 0xef,
 312	0x0b, 0xa1, 0xf5, 0x82, 0x0a, 0x9e, 0x1a, 0x9c, 0x24, 0x98, 0x07, 0xe0,
 313	0x0f, 0xa2, 0x0e, 0xca, 0x0a, 0xde, 0x1a, 0xdc, 0x24, 0x98, 0x03, 0xb0,
 314	0x07, 0xe0, 0x0f, 0xa2, 0x0e, 0xc8, 0x01, 0x81, 0x0c, 0x0c, 0x0c, 0xf2,
 315	0x93, 0xdd, 0xc3, 0xc1, 0x0c, 0x04, 0x7c, 0xfa, 0x46, 0x42, 0x9c, 0xe0,
 316	0x0b, 0x02, 0x04, 0xe3, 0xf0, 0x1e, 0x30, 0xec, 0x0b, 0xa3, 0x35, 0x96,
 317	0x8e, 0x01, 0x01, 0x60, 0x10, 0xc0, 0x0e, 0xfc, 0xc6, 0x05, 0xd0, 0xe1,
 318	0x0b, 0x82, 0x31, 0x81, 0x10, 0x16, 0x00, 0xe5, 0x20, 0x10, 0x20, 0xe7,
 319	0x0e, 0xbe, 0xb5, 0x85, 0x94, 0xfc, 0xa4, 0xbe, 0x82, 0x4c, 0x9c, 0xf0,
 320	0x05, 0x0c, 0x40, 0xe0, 0x11, 0x89, 0x93, 0x8e, 0xa3, 0x8e, 0x58, 0x44,
 321	0x00, 0xe8, 0x15, 0x0c, 0xc0, 0xf8, 0x04, 0x0c, 0x80, 0xfb, 0x0c, 0xed,
 322	0x0b, 0x82, 0x1b, 0x8c, 0x48, 0x44, 0x00, 0xe8, 0x15, 0x10, 0x1c, 0xfc,
 323	0x0e, 0xa8, 0x0b, 0x82, 0x1b, 0x8c, 0xd8, 0x43, 0x00, 0xe8, 0x71, 0x88,
 324	0x0e, 0xa4, 0x0a, 0x0e, 0x40, 0xe0, 0x35, 0xf8, 0x04, 0xbe, 0x14, 0xbc,
 325	0x81, 0xa0, 0x03, 0x8e, 0x0e, 0xbe, 0x04, 0xfc, 0x11, 0x82, 0x3b, 0x82,
 326	0x03, 0x8e, 0x0e, 0xfc, 0x3b, 0xa9, 0x06, 0x0e, 0x00, 0xc0, 0x35, 0x5e,
 327	0x00, 0xc0, 0xd5, 0xfa, 0xc6, 0x01, 0xd0, 0xe1, 0x7b, 0x80, 0x04, 0x9e,
 328	0x11, 0x91, 0x98, 0x41, 0x00, 0xe8, 0x24, 0x9c, 0x46, 0x42, 0x9c, 0xe0,
 329	0x6b, 0x82, 0x03, 0x4c, 0xc4, 0xe0, 0x11, 0x91, 0x0b, 0x84, 0xf8, 0x40,
 330	0x00, 0xe8, 0x19, 0x0e, 0x20, 0xe5, 0x03, 0x4c, 0xc0, 0xe0, 0x0b, 0x82,
 331	0x08, 0x72, 0xfc, 0xef, 0x01, 0x4c, 0x24, 0xf9, 0xf1, 0x98, 0x0c, 0x0c,
 332	0x7c, 0xf2, 0x93, 0xdd, 0x4c, 0x00, 0x00, 0xfa, 0x48, 0x65, 0x2c, 0xef,
 333	0x4c, 0x08, 0x00, 0xf2, 0x93, 0xdd, 0xc3, 0xc1, 0x0c, 0x04, 0x00, 0xfa,
 334	0x6b, 0x82, 0x78, 0x6e, 0xfc, 0xee, 0x46, 0x42, 0xec, 0xe0, 0x24, 0x84,
 335	0x24, 0x02, 0x80, 0xfa, 0x1d, 0xcc, 0x11, 0x83, 0xf5, 0x82, 0x24, 0x02,
 336	0xa0, 0xe1, 0x14, 0x02, 0x80, 0xfa, 0x1d, 0xcc, 0x11, 0x85, 0x15, 0x82,
 337	0x27, 0xe1, 0x24, 0x02, 0x80, 0xfa, 0x1d, 0xcc, 0x11, 0x89, 0x86, 0x02,
 338	0x00, 0x80, 0x0c, 0x0c, 0x00, 0xf2, 0x18, 0x17, 0xfc, 0xfe, 0xc3, 0xc1,
 339	0x0c, 0x04, 0x00, 0xfa, 0x06, 0x41, 0x8c, 0xe0, 0x1b, 0x00, 0xec, 0xe4,
 340	0x1b, 0xa3, 0x75, 0x84, 0x11, 0x81, 0x8e, 0x05, 0x01, 0x60, 0x10, 0xc0,
 341	0x00, 0x06, 0xc0, 0xe5, 0x95, 0x81, 0x44, 0x88, 0x1d, 0xee, 0x75, 0x80,
 342	0x4e, 0xc1, 0x25, 0x81, 0x4e, 0xcd, 0x21, 0x88, 0x11, 0x82, 0x0a, 0x02,
 343	0x40, 0xe0, 0xd5, 0xfc, 0x56, 0x00, 0x00, 0xe1, 0x18, 0x80, 0x1b, 0xa1,
 344	0xc5, 0x84, 0x08, 0x82, 0x4a, 0x00, 0xfc, 0xfb, 0x45, 0x84, 0x86, 0x4d,
 345	0x84, 0xe1, 0x04, 0x98, 0x05, 0x00, 0x10, 0xe0, 0x4a, 0x40, 0x80, 0xe0,
 346	0x45, 0x82, 0x11, 0x81, 0x0b, 0x8c, 0x58, 0x76, 0x28, 0xef, 0x0b, 0x8c,
 347	0x0c, 0x0c, 0x00, 0xf2, 0x88, 0x35, 0x28, 0xff, 0x0c, 0x0c, 0x00, 0xf2,
 348	0x93, 0xdd, 0xc3, 0xc1, 0x46, 0x41, 0xfc, 0xe0, 0x04, 0x80, 0x09, 0x00,
 349	0x80, 0xe0, 0x09, 0x9e, 0x0b, 0xa3, 0x75, 0x82, 0x46, 0x41, 0x80, 0xe1,
 350	0x04, 0x80, 0xc6, 0x42, 0x8c, 0xe0, 0x04, 0xc2, 0x00, 0x40, 0x00, 0xf2,
 351	0x07, 0xcf, 0x06, 0x84, 0x06, 0x40, 0x84, 0xe0, 0x15, 0x00, 0x28, 0xe5,
 352	0x1c, 0xc2, 0x93, 0xdd, 0x0b, 0xa1, 0xc6, 0x00, 0xa0, 0xe1, 0x15, 0x00,
 353	0x04, 0xf8, 0x05, 0x84, 0x21, 0x8b, 0x2c, 0x84, 0x14, 0x80, 0x2c, 0x84,
 354	0x14, 0x82, 0x2c, 0x84, 0x15, 0x00, 0x10, 0xe0, 0x21, 0xa1, 0x21, 0x42,
 355	0x10, 0xe0, 0x05, 0x00, 0x14, 0xe0, 0x01, 0x88, 0x75, 0x83, 0x21, 0x85,
 356	0x2c, 0x84, 0x14, 0x80, 0x06, 0x46, 0x00, 0xe0, 0x2c, 0x84, 0x14, 0x82,
 357	0x2c, 0x84, 0x14, 0xc0, 0x21, 0xa1, 0x21, 0x42, 0x20, 0xe0, 0x14, 0xc2,
 358	0x31, 0x42, 0x20, 0xe0, 0x15, 0x00, 0x10, 0xe0, 0x21, 0x42, 0x20, 0xe0,
 359	0x05, 0x00, 0x14, 0xe0, 0x01, 0x90, 0x06, 0x42, 0x00, 0xe0, 0x16, 0x80,
 360	0x93, 0xdd, 0xc3, 0xc1, 0x0c, 0x04, 0x7c, 0xfa, 0x4a, 0x40, 0x80, 0xe0,
 361	0xf0, 0x1e, 0x30, 0xec, 0xe5, 0x82, 0xa6, 0x40, 0x00, 0xe1, 0x1a, 0x80,
 362	0x2a, 0xc0, 0x3a, 0xc2, 0x13, 0x40, 0x10, 0xe0, 0x1a, 0x82, 0x23, 0x40,
 363	0x18, 0xe0, 0x33, 0x40, 0x1c, 0xe0, 0x13, 0x40, 0x14, 0xe0, 0xf8, 0x61,
 364	0x68, 0xef, 0xc6, 0x13, 0x00, 0xe1, 0x15, 0x12, 0x28, 0xf8, 0x0b, 0x02,
 365	0x2c, 0xe0, 0x1b, 0x02, 0x24, 0xe0, 0x8a, 0x00, 0xa5, 0x64, 0x03, 0xc0,
 366	0x35, 0x82, 0x0a, 0x4e, 0x9c, 0xe1, 0x1a, 0x03, 0x11, 0x6f, 0x02, 0xc0,
 367	0xe8, 0x13, 0x01, 0x20, 0x00, 0xc0, 0x1f, 0xa0, 0x5a, 0x42, 0x80, 0xe0,
 368	0x0a, 0x4e, 0x9c, 0xe1, 0x68, 0x13, 0x00, 0xa0, 0x09, 0x12, 0x78, 0xf8,
 369	0xa1, 0x81, 0xf0, 0x02, 0x10, 0xe4, 0x07, 0xc4, 0x0c, 0xfc, 0xf0, 0x00,
 370	0x20, 0xe4, 0xa6, 0x91, 0xa8, 0x53, 0x74, 0xef, 0x05, 0x12, 0x30, 0xf8,
 371	0x25, 0x12, 0x28, 0xf8, 0x61, 0x87, 0x09, 0x00, 0x48, 0xe0, 0x81, 0x85,
 372	0x09, 0x86, 0x0b, 0xa7, 0x26, 0x0c, 0x00, 0xc0, 0x0b, 0xa1, 0x0b, 0x04,
 373	0x28, 0xe0, 0x16, 0x0c, 0x00, 0x80, 0x03, 0x52, 0x04, 0xf8, 0x0b, 0x04,
 374	0x20, 0xe0, 0x0c, 0xa6, 0x1b, 0x04, 0x2c, 0xe0, 0x3b, 0x04, 0x28, 0xe0,
 375	0x4b, 0x04, 0x20, 0xe0, 0x13, 0x86, 0x3b, 0x04, 0x24, 0xe0, 0x10, 0x0a,
 376	0x04, 0xec, 0x1a, 0xfc, 0x33, 0x88, 0x30, 0x06, 0x04, 0xec, 0x12, 0x4e,
 377	0x94, 0xf0, 0x32, 0x48, 0x84, 0xf0, 0x4c, 0xe4, 0x7c, 0xa4, 0xcb, 0x04,
 378	0x28, 0xe0, 0x14, 0x08, 0x84, 0xe1, 0xcd, 0xc9, 0xc2, 0x58, 0x90, 0x91,
 379	0x42, 0x4e, 0x94, 0x90, 0xc3, 0x52, 0x04, 0x98, 0x73, 0x52, 0x00, 0x80,
 380	0x5b, 0x04, 0x20, 0xe0, 0x5d, 0xc9, 0x52, 0x40, 0x90, 0x91, 0x42, 0x48,
 381	0x8c, 0x90, 0x03, 0x52, 0x04, 0x80, 0x43, 0x52, 0x08, 0x80, 0x3b, 0x04,
 382	0x2c, 0xe0, 0x49, 0x04, 0xb8, 0xe0, 0x33, 0x52, 0x1c, 0xf8, 0x2b, 0x04,
 383	0x24, 0xe0, 0x4b, 0xab, 0x23, 0x52, 0x18, 0xf8, 0x65, 0x8a, 0x4b, 0xa9,
 384	0xe5, 0x90, 0x4b, 0xa7, 0x22, 0x44, 0x84, 0xd0, 0x32, 0x46, 0x84, 0xd0,
 385	0x33, 0x52, 0x1c, 0xd8, 0x23, 0x52, 0x18, 0xd8, 0x95, 0x96, 0x20, 0x44,
 386	0xf9, 0x73, 0xff, 0xc0, 0x27, 0xc3, 0x23, 0x82, 0x23, 0x52, 0x18, 0xf8,
 387	0x24, 0x02, 0x80, 0xfb, 0x04, 0x00, 0x80, 0xfb, 0x2b, 0x8c, 0x58, 0x52,
 388	0x74, 0xef, 0x1b, 0x12, 0x1c, 0xf8, 0x2a, 0xfc, 0x0c, 0xe4, 0x17, 0xc3,
 389	0x13, 0x84, 0x13, 0x52, 0x1c, 0xf8, 0x0b, 0x12, 0x04, 0xf8, 0x14, 0x02,
 390	0x80, 0xfb, 0x2b, 0x8c, 0x68, 0x51, 0x74, 0xef, 0xc5, 0x87, 0x20, 0x44,
 391	0xe1, 0x73, 0xff, 0xc0, 0x27, 0xc7, 0x23, 0x82, 0x23, 0x52, 0x18, 0xf8,
 392	0x24, 0x02, 0x80, 0xfb, 0x04, 0x00, 0x80, 0xfb, 0x2b, 0x8c, 0x78, 0x57,
 393	0x74, 0xef, 0x1b, 0x12, 0x1c, 0xf8, 0x2a, 0xfc, 0x0c, 0xe4, 0x17, 0xc7,
 394	0x13, 0x84, 0x13, 0x52, 0x1c, 0xf8, 0x0b, 0x12, 0x04, 0xf8, 0x14, 0x02,
 395	0x80, 0xfb, 0x2b, 0x8c, 0x88, 0x56, 0x74, 0xef, 0xe5, 0x83, 0x20, 0x44,
 396	0xf1, 0x73, 0xff, 0xc0, 0x27, 0xc5, 0x23, 0x82, 0x23, 0x52, 0x18, 0xf8,
 397	0x24, 0x02, 0x80, 0xfb, 0x04, 0x00, 0x80, 0xfb, 0x2b, 0x8c, 0x18, 0x52,
 398	0x74, 0xef, 0x1b, 0x12, 0x1c, 0xf8, 0x2a, 0xfc, 0x0c, 0xe4, 0x17, 0xc5,
 399	0x13, 0x84, 0x13, 0x52, 0x1c, 0xf8, 0x0b, 0x12, 0x04, 0xf8, 0x14, 0x02,
 400	0x80, 0xfb, 0x2b, 0x8c, 0x28, 0x51, 0x74, 0xef, 0x7b, 0x80, 0x7c, 0xa4,
 401	0x08, 0x91, 0xa3, 0x52, 0x1c, 0xe0, 0xa3, 0x52, 0x24, 0xe0, 0x0b, 0xa1,
 402	0x83, 0x52, 0x1c, 0x80, 0x83, 0x52, 0x24, 0x80, 0x89, 0x12, 0x78, 0xf8,
 403	0xf6, 0x57, 0xfc, 0xef, 0x6b, 0x12, 0x1c, 0xf8, 0xab, 0x12, 0x18, 0xf8,
 404	0xd6, 0x57, 0xfc, 0x8f, 0x8b, 0xa3, 0xa0, 0x40, 0x00, 0x9c, 0xa5, 0x86,
 405	0x64, 0x00, 0x80, 0xfb, 0x1b, 0x90, 0xf8, 0x7d, 0xf8, 0xee, 0x6b, 0x80,
 406	0xa4, 0x00, 0x80, 0xfb, 0x1b, 0x90, 0x98, 0x7d, 0xf8, 0xee, 0x15, 0x12,
 407	0x28, 0xf8, 0x19, 0x02, 0xb8, 0xe0, 0x1b, 0xad, 0x95, 0x82, 0x1a, 0xa6,
 408	0xa0, 0x44, 0xf9, 0x73, 0xff, 0xc0, 0x27, 0xc3, 0x13, 0x94, 0x10, 0x02,
 409	0x08, 0xec, 0x1c, 0xe4, 0x23, 0x52, 0x18, 0xf8, 0x1b, 0x12, 0x04, 0xf8,
 410	0x03, 0x96, 0x03, 0x52, 0x28, 0xe0, 0x1c, 0xe6, 0x0a, 0xa6, 0x1a, 0xe4,
 411	0x63, 0x96, 0x63, 0x52, 0x20, 0xe0, 0x73, 0x52, 0x10, 0xe0, 0x03, 0x52,
 412	0x14, 0xe0, 0x13, 0x52, 0x18, 0xe0, 0x98, 0x52, 0x74, 0xef, 0x09, 0x12,
 413	0x8c, 0xe0, 0x0b, 0xa1, 0x01, 0x81, 0x01, 0x52, 0x90, 0xe0, 0x65, 0x82,
 414	0x05, 0x12, 0x30, 0xf8, 0x09, 0x00, 0xa8, 0xe0, 0x0a, 0x00, 0x0c, 0xf8,
 415	0x16, 0x00, 0x00, 0xc0, 0x01, 0x52, 0x90, 0xc0, 0x46, 0x41, 0x84, 0xe0,
 416	0x0a, 0x80, 0x0a, 0x4e, 0x9c, 0xe9, 0x1a, 0x00, 0x08, 0xe0, 0x38, 0x01,
 417	0x01, 0x20, 0x00, 0xc0, 0x0b, 0x12, 0x1c, 0xe0, 0x1b, 0x12, 0x24, 0xe0,
 418	0x2b, 0x12, 0x28, 0xe0, 0x03, 0x52, 0x2c, 0xe0, 0x0b, 0x12, 0x20, 0xe0,
 419	0x13, 0x52, 0x34, 0xe0, 0x23, 0x52, 0x38, 0xe0, 0x03, 0x52, 0x30, 0xe0,
 420	0x0c, 0x00, 0x00, 0xe2, 0xf1, 0x98, 0x0c, 0x0c, 0x7c, 0xf2, 0x93, 0xdd,
 421	0x13, 0xa9, 0x00, 0x00, 0xa8, 0xc1, 0x40, 0x00, 0x68, 0x04, 0xa0, 0xe0,
 422	0x40, 0x6c, 0x40, 0x00, 0xe8, 0x34, 0xc8, 0xe0, 0xfc, 0x91, 0x40, 0x00,
 423	0x68, 0x1f, 0xb8, 0xe0, 0x30, 0x16, 0x41, 0x00, 0x28, 0x39, 0x74, 0xe0,
 424	0xb0, 0x7e, 0x40, 0x00, 0xe8, 0x38, 0xc0, 0xe0, 0x30, 0x04, 0x41, 0x00,
 425	0x48, 0x1b, 0x80, 0xe0, 0x30, 0x2e, 0x40, 0x00, 0x88, 0x0c, 0xec, 0xe0,
 426	0x10, 0x9f, 0x40, 0x00, 0x88, 0x08, 0xb4, 0xe0, 0x10, 0x01, 0x41, 0x00,
 427	0x68, 0x01, 0x84, 0xe0, 0x54, 0xd6, 0x40, 0x00, 0xc8, 0x1a, 0x98, 0xe0,
 428	0xd0, 0xc8, 0x40, 0x00, 0x68, 0x08, 0xa0, 0xe0, 0x80, 0xdb, 0x40, 0x00,
 429	0xe8, 0x35, 0x94, 0xe0, 0x74, 0xff, 0x40, 0x00, 0xa8, 0x11, 0x80, 0xe0,
 430	0xf8, 0x89, 0x40, 0x00, 0x88, 0x16, 0xbc, 0xe0, 0x00, 0x90, 0x40, 0x00,
 431	0x08, 0x35, 0xb8, 0xe0, 0x7c, 0x73, 0x40, 0x00, 0x88, 0x1b, 0xc8, 0xe0,
 432	0xf4, 0xff, 0x40, 0x00, 0x68, 0x39, 0x80, 0xe0, 0xa4, 0xa4, 0x40, 0x00,
 433	0xa8, 0x16, 0xb0, 0xe0, 0x50, 0xc9, 0x40, 0x00, 0x28, 0x3a, 0x98, 0xe0,
 434	0x00, 0xb9, 0x00, 0x00, 0xb6, 0x85, 0x00, 0x00,
 435};
 436
 437static const char * const vd55g1_tp_menu[] = {
 438	"Disabled",
 439	"Diagonal Grey Scale",
 440	"Pseudo-random Noise",
 441};
 442
 443static const s64 vd55g1_ev_bias_menu[] = {
 444	-3000, -2500, -2000, -1500, -1000, -500,
 445	    0,
 446	  500,  1000,  1500,  2000,  2500, 3000,
 447};
 448
 449static const char * const vd55g1_hdr_menu[] = {
 450	"No HDR",
 451	/*
 452	 * This mode acquires 2 frames on the sensor, the first one is ditched
 453	 * out and only used for auto exposure data, the second one is output to
 454	 * the host
 455	 */
 456	"Internal subtraction",
 457};
 458
 459static const char * const vd55g1_supply_name[] = {
 460	"vcore",
 461	"vddio",
 462	"vana",
 463};
 464
 465enum vd55g1_hdr_mode {
 466	VD55G1_NO_HDR,
 467	VD55G1_HDR_SUB,
 468};
 469
 470struct vd55g1_mode {
 471	u32 width;
 472	u32 height;
 473};
 474
 475static const u32 vd55g1_mbus_formats_mono[] = {
 476	MEDIA_BUS_FMT_Y8_1X8,
 477	MEDIA_BUS_FMT_Y10_1X10,
 478};
 479
 480/* Format order is : no flip, hflip, vflip, both */
 481static const u32 vd55g1_mbus_formats_bayer[][4] = {
 482	{
 483		MEDIA_BUS_FMT_SRGGB8_1X8,
 484		MEDIA_BUS_FMT_SGRBG8_1X8,
 485		MEDIA_BUS_FMT_SGBRG8_1X8,
 486		MEDIA_BUS_FMT_SBGGR8_1X8,
 487	},
 488	{
 489		MEDIA_BUS_FMT_SRGGB10_1X10,
 490		MEDIA_BUS_FMT_SGRBG10_1X10,
 491		MEDIA_BUS_FMT_SGBRG10_1X10,
 492		MEDIA_BUS_FMT_SBGGR10_1X10,
 493	},
 494};
 495
 496static const struct vd55g1_mode vd55g1_supported_modes[] = {
 497	{
 498		.width = VD55G1_WIDTH,
 499		.height = VD55G1_HEIGHT,
 500	},
 501	{
 502		.width = 800,
 503		.height = VD55G1_HEIGHT,
 504	},
 505	{
 506		.width = 800,
 507		.height = 600,
 508	},
 509	{
 510		.width = 640,
 511		.height = 480,
 512	},
 513	{
 514		.width = 320,
 515		.height = 240,
 516	},
 517};
 518
 519enum vd55g1_expo_state {
 520	VD55G1_EXP_AUTO,
 521	VD55G1_EXP_FREEZE,
 522	VD55G1_EXP_MANUAL,
 523	VD55G1_EXP_SINGLE_STEP,
 524	VD55G1_EXP_BYPASS,
 525};
 526
 527struct vd55g1_vblank_limits {
 528	u16 min;
 529	u16 def;
 530	u16 max;
 531};
 532
 533struct vd55g1 {
 534	struct device *dev;
 535	unsigned int id;
 536	struct v4l2_subdev sd;
 537	struct media_pad pad;
 538	struct regulator_bulk_data supplies[ARRAY_SIZE(vd55g1_supply_name)];
 539	struct gpio_desc *reset_gpio;
 540	struct clk *xclk;
 541	struct regmap *regmap;
 542	u32 xclk_freq;
 543	u16 oif_ctrl;
 544	u8 gpios[VD55G1_NB_GPIOS];
 545	unsigned long ext_leds_mask;
 546	u32 mipi_rate;
 547	u32 pixel_clock;
 548	u64 link_freq;
 549	struct v4l2_ctrl_handler ctrl_handler;
 550	struct v4l2_ctrl *pixel_rate_ctrl;
 551	struct v4l2_ctrl *vblank_ctrl;
 552	struct v4l2_ctrl *hblank_ctrl;
 553	struct {
 554		struct v4l2_ctrl *hflip_ctrl;
 555		struct v4l2_ctrl *vflip_ctrl;
 556	};
 557	struct v4l2_ctrl *patgen_ctrl;
 558	struct {
 559		struct v4l2_ctrl *ae_ctrl;
 560		struct v4l2_ctrl *expo_ctrl;
 561		struct v4l2_ctrl *again_ctrl;
 562		struct v4l2_ctrl *dgain_ctrl;
 563	};
 564	struct v4l2_ctrl *ae_lock_ctrl;
 565	struct v4l2_ctrl *ae_bias_ctrl;
 566	struct v4l2_ctrl *led_ctrl;
 567	struct v4l2_ctrl *hdr_ctrl;
 568};
 569
 570static inline struct vd55g1 *to_vd55g1(struct v4l2_subdev *sd)
 571{
 572	return container_of_const(sd, struct vd55g1, sd);
 573}
 574
 575static inline struct vd55g1 *ctrl_to_vd55g1(struct v4l2_ctrl *ctrl)
 576{
 577	struct v4l2_subdev *sd = &container_of_const(ctrl->handler,
 578						     struct vd55g1,
 579						     ctrl_handler)->sd;
 580
 581	return to_vd55g1(sd);
 582}
 583
 584static unsigned int vd55g1_get_fmt_bpp(u32 code)
 585{
 586	switch (code) {
 587	case MEDIA_BUS_FMT_Y8_1X8:
 588	case MEDIA_BUS_FMT_SRGGB8_1X8:
 589	case MEDIA_BUS_FMT_SGRBG8_1X8:
 590	case MEDIA_BUS_FMT_SGBRG8_1X8:
 591	case MEDIA_BUS_FMT_SBGGR8_1X8:
 592	default:
 593		return 8;
 594
 595	case MEDIA_BUS_FMT_Y10_1X10:
 596	case MEDIA_BUS_FMT_SRGGB10_1X10:
 597	case MEDIA_BUS_FMT_SGRBG10_1X10:
 598	case MEDIA_BUS_FMT_SGBRG10_1X10:
 599	case MEDIA_BUS_FMT_SBGGR10_1X10:
 600		return 10;
 601	}
 602}
 603
 604static unsigned int vd55g1_get_fmt_data_type(u32 code)
 605{
 606	switch (code) {
 607	case MEDIA_BUS_FMT_Y8_1X8:
 608	case MEDIA_BUS_FMT_SRGGB8_1X8:
 609	case MEDIA_BUS_FMT_SGRBG8_1X8:
 610	case MEDIA_BUS_FMT_SGBRG8_1X8:
 611	case MEDIA_BUS_FMT_SBGGR8_1X8:
 612	default:
 613		return MIPI_CSI2_DT_RAW8;
 614
 615	case MEDIA_BUS_FMT_Y10_1X10:
 616	case MEDIA_BUS_FMT_SRGGB10_1X10:
 617	case MEDIA_BUS_FMT_SGRBG10_1X10:
 618	case MEDIA_BUS_FMT_SGBRG10_1X10:
 619	case MEDIA_BUS_FMT_SBGGR10_1X10:
 620		return MIPI_CSI2_DT_RAW10;
 621	}
 622}
 623
 624static u32 vd55g1_get_fmt_code(struct vd55g1 *sensor, u32 code)
 625{
 626	unsigned int i, j;
 627
 628	if (sensor->id == VD55G1_MODEL_ID_VD55G1)
 629		return code;
 630
 631	for (i = 0; i < ARRAY_SIZE(vd55g1_mbus_formats_bayer); i++) {
 632		for (j = 0; j < ARRAY_SIZE(vd55g1_mbus_formats_bayer[i]); j++) {
 633			if (vd55g1_mbus_formats_bayer[i][j] == code)
 634				goto adapt_bayer_pattern;
 635		}
 636	}
 637	dev_warn(sensor->dev, "Unsupported mbus format\n");
 638
 639	return code;
 640
 641adapt_bayer_pattern:
 642	j = 0;
 643	/* In first init_state() call, controls might not be initialized yet */
 644	if (sensor->hflip_ctrl && sensor->vflip_ctrl) {
 645		j = (sensor->hflip_ctrl->val ? 1 : 0) +
 646			(sensor->vflip_ctrl->val ? 2 : 0);
 647	}
 648
 649	return vd55g1_mbus_formats_bayer[i][j];
 650}
 651
 652static s32 vd55g1_get_pixel_rate(struct vd55g1 *sensor,
 653				 struct v4l2_mbus_framefmt *format)
 654{
 655	return sensor->mipi_rate / vd55g1_get_fmt_bpp(format->code);
 656}
 657
 658static unsigned int vd55g1_get_hblank_min(struct vd55g1 *sensor,
 659					  struct v4l2_mbus_framefmt *format,
 660					  struct v4l2_rect *crop)
 661{
 662	u32 mipi_req_line_time;
 663	u32 mipi_req_line_length;
 664	u32 min_line_length;
 665
 666	/* MIPI required time */
 667	mipi_req_line_time = (crop->width *
 668			      vd55g1_get_fmt_bpp(format->code) +
 669			      VD55G1_MIPI_MARGIN) /
 670			      (sensor->mipi_rate / MEGA);
 671	mipi_req_line_length = mipi_req_line_time * sensor->pixel_clock /
 672			       HZ_PER_MHZ;
 673
 674	/* Absolute time required for ADCs to convert pixels */
 675	min_line_length = VD55G1_LINE_LENGTH_MIN;
 676	if (sensor->hdr_ctrl->val == VD55G1_HDR_SUB)
 677		min_line_length = VD55G1_LINE_LENGTH_SUB_MIN;
 678
 679	/* Respect both constraint */
 680	min_line_length = max(min_line_length, mipi_req_line_length);
 681
 682	return min_line_length - crop->width;
 683}
 684
 685static void vd55g1_get_vblank_limits(struct vd55g1 *sensor,
 686				     struct v4l2_rect *crop,
 687				     struct vd55g1_vblank_limits *limits)
 688{
 689	limits->min = VD55G1_VBLANK_MIN;
 690	limits->def = VD55G1_FRAME_LENGTH_DEF - crop->height;
 691	limits->max = VD55G1_VBLANK_MAX - crop->height;
 692}
 693
 694#define vd55g1_read(sensor, reg, val, err) \
 695	cci_read((sensor)->regmap, reg, val, err)
 696
 697#define vd55g1_write(sensor, reg, val, err) \
 698	cci_write((sensor)->regmap, reg, val, err)
 699
 700static int vd55g1_write_array(struct vd55g1 *sensor, u32 reg, unsigned int len,
 701			      const u8 *array, int *err)
 702{
 703	unsigned int chunk_sz = 1024;
 704	unsigned int sz;
 705	int ret = 0;
 706
 707	if (err && *err)
 708		return *err;
 709
 710	/*
 711	 * This loop isn't necessary but in certains conditions (platforms, cpu
 712	 * load, etc.) it has been observed that the bulk write could timeout.
 713	 */
 714	while (len) {
 715		sz = min(len, chunk_sz);
 716		ret = regmap_bulk_write(sensor->regmap, reg, array, sz);
 717		if (ret < 0)
 718			goto out;
 719		len -= sz;
 720		reg += sz;
 721		array += sz;
 722	}
 723
 724out:
 725	if (ret && err)
 726		*err = ret;
 727
 728	return ret;
 729}
 730
 731static int vd55g1_poll_reg(struct vd55g1 *sensor, u32 reg, u8 poll_val,
 732			   int *err)
 733{
 734	unsigned int val = 0;
 735	int ret;
 736
 737	if (err && *err)
 738		return *err;
 739
 740	ret = regmap_read_poll_timeout(sensor->regmap, CCI_REG_ADDR(reg), val,
 741				       (val == poll_val), 2000,
 742				       500 * USEC_PER_MSEC);
 743
 744	if (ret && err)
 745		*err = ret;
 746
 747	return ret;
 748}
 749
 750static int vd55g1_wait_state(struct vd55g1 *sensor, int state, int *err)
 751{
 752	return vd55g1_poll_reg(sensor, VD55G1_REG_SYSTEM_FSM, state, err);
 753}
 754
 755static int vd55g1_prepare_clock_tree(struct vd55g1 *sensor)
 756{
 757	u32 sys_clk, mipi_div, pixel_div;
 758
 759	if (sensor->xclk_freq < VD55G1_XCLK_FREQ_MIN ||
 760	    sensor->xclk_freq > VD55G1_XCLK_FREQ_MAX) {
 761		dev_err(sensor->dev,
 762			"Only %luMhz-%luMhz clock range supported. Provided %lu MHz\n",
 763			VD55G1_XCLK_FREQ_MIN / HZ_PER_MHZ,
 764			VD55G1_XCLK_FREQ_MAX / HZ_PER_MHZ,
 765			sensor->xclk_freq / HZ_PER_MHZ);
 766		return -EINVAL;
 767	}
 768
 769	/* MIPI bus is double data rate */
 770	sensor->mipi_rate = sensor->link_freq * 2;
 771
 772	if (sensor->mipi_rate < VD55G1_MIPI_RATE_MIN ||
 773	    sensor->mipi_rate > VD55G1_MIPI_RATE_MAX) {
 774		dev_err(sensor->dev,
 775			"Only %luMbps-%luMbps data rate range supported. Provided %lu Mbps\n",
 776			VD55G1_MIPI_RATE_MIN / MEGA,
 777			VD55G1_MIPI_RATE_MAX / MEGA,
 778			sensor->mipi_rate / MEGA);
 779		return -EINVAL;
 780	}
 781
 782	if (sensor->mipi_rate <= 300 * MEGA)
 783		mipi_div = 4;
 784	else if (sensor->mipi_rate <= 600 * MEGA)
 785		mipi_div = 2;
 786	else
 787		mipi_div = 1;
 788
 789	sys_clk = sensor->mipi_rate * mipi_div;
 790
 791	if (sys_clk <= 780 * HZ_PER_MHZ)
 792		pixel_div = 5;
 793	else if (sys_clk <= 900 * HZ_PER_MHZ)
 794		pixel_div = 6;
 795	else
 796		pixel_div = 8;
 797
 798	sensor->pixel_clock = sys_clk / pixel_div;
 799
 800	return 0;
 801}
 802
 803static int vd55g1_update_patgen(struct vd55g1 *sensor, u32 patgen_index)
 804{
 805	static const u8 index2val[] = {
 806		0x0, 0x22, 0x28
 807	};
 808	u32 pattern = index2val[patgen_index];
 809	u32 reg = pattern << VD55G1_PATGEN_TYPE_SHIFT;
 810	u8 duster = VD55G1_DUSTER_RING_ENABLE | VD55G1_DUSTER_DYN_ENABLE |
 811		    VD55G1_DUSTER_ENABLE;
 812	int ret = 0;
 813
 814	BUILD_BUG_ON(ARRAY_SIZE(index2val) != ARRAY_SIZE(vd55g1_tp_menu));
 815
 816	if (pattern != 0) {
 817		reg |= VD55G1_PATGEN_ENABLE;
 818		/* Take care of duster to not mess up the test pattern output */
 819		duster = VD55G1_DUSTER_DISABLE;
 820	}
 821
 822	vd55g1_write(sensor, VD55G1_REG_DUSTER_CTRL, duster, &ret);
 823	vd55g1_write(sensor, VD55G1_REG_PATGEN_CTRL, reg, &ret);
 824
 825	return ret;
 826}
 827
 828static int vd55g1_update_expo_cluster(struct vd55g1 *sensor, bool is_auto)
 829{
 830	enum vd55g1_expo_state expo_state = is_auto ? VD55G1_EXP_AUTO :
 831						      VD55G1_EXP_MANUAL;
 832	int ret = 0;
 833
 834	if (sensor->ae_ctrl->is_new)
 835		vd55g1_write(sensor, VD55G1_REG_EXP_MODE(0), expo_state, &ret);
 836
 837	if (sensor->hdr_ctrl->val == VD55G1_HDR_SUB &&
 838	    sensor->hdr_ctrl->is_new) {
 839		vd55g1_write(sensor, VD55G1_REG_EXP_MODE(1), VD55G1_EXP_BYPASS,
 840			     &ret);
 841		if (ret)
 842			return ret;
 843	}
 844
 845	if (!is_auto && sensor->expo_ctrl->is_new)
 846		vd55g1_write(sensor, VD55G1_REG_MANUAL_COARSE_EXPOSURE,
 847			     sensor->expo_ctrl->val, &ret);
 848
 849	if (!is_auto && sensor->again_ctrl->is_new)
 850		vd55g1_write(sensor, VD55G1_REG_MANUAL_ANALOG_GAIN,
 851			     sensor->again_ctrl->val, &ret);
 852
 853	if (!is_auto && sensor->dgain_ctrl->is_new)
 854		vd55g1_write(sensor, VD55G1_REG_MANUAL_DIGITAL_GAIN,
 855			     sensor->dgain_ctrl->val, &ret);
 856
 857	return ret;
 858}
 859
 860static int vd55g1_lock_exposure(struct vd55g1 *sensor, u32 lock_val)
 861{
 862	bool ae_lock = lock_val & V4L2_LOCK_EXPOSURE;
 863	enum vd55g1_expo_state expo_state = ae_lock ? VD55G1_EXP_FREEZE :
 864						      VD55G1_EXP_AUTO;
 865	int ret = 0;
 866
 867	if (sensor->ae_ctrl->val == V4L2_EXPOSURE_AUTO)
 868		vd55g1_write(sensor, VD55G1_REG_EXP_MODE(0), expo_state, &ret);
 869
 870	return ret;
 871}
 872
 873static int vd55g1_read_expo_cluster(struct vd55g1 *sensor)
 874{
 875	u64 exposure = 0;
 876	u64 again = 0;
 877	u64 dgain = 0;
 878	int ret = 0;
 879
 880	vd55g1_read(sensor, VD55G1_REG_APPLIED_COARSE_EXPOSURE, &exposure,
 881		    &ret);
 882	vd55g1_read(sensor, VD55G1_REG_APPLIED_ANALOG_GAIN, &again, &ret);
 883	vd55g1_read(sensor, VD55G1_REG_APPLIED_DIGITAL_GAIN, &dgain, &ret);
 884	if (ret)
 885		return ret;
 886
 887	sensor->expo_ctrl->cur.val = exposure;
 888	sensor->again_ctrl->cur.val = again;
 889	sensor->dgain_ctrl->cur.val = dgain;
 890
 891	return 0;
 892}
 893
 894static int vd55g1_update_frame_length(struct vd55g1 *sensor,
 895				      unsigned int frame_length)
 896{
 897	int ret = 0;
 898
 899	if (sensor->hdr_ctrl->val == VD55G1_HDR_SUB)
 900		vd55g1_write(sensor, VD55G1_REG_FRAME_LENGTH(1), frame_length,
 901			     &ret);
 902	vd55g1_write(sensor, VD55G1_REG_FRAME_LENGTH(0), frame_length, &ret);
 903
 904	return ret;
 905}
 906
 907static int vd55g1_update_exposure_target(struct vd55g1 *sensor, int index)
 908{
 909	/*
 910	 * Find auto exposure target with: default target exposure * 2^EV
 911	 * Defaut target exposure being 27 for the sensor.
 912	 */
 913	static const unsigned int index2exposure_target[] = {
 914		3, 5, 7, 10, 14, 19, 27, 38, 54, 76, 108, 153, 216,
 915	};
 916	int exposure_target = index2exposure_target[index];
 917
 918	return vd55g1_write(sensor, VD55G1_REG_AE_TARGET_PERCENTAGE,
 919			    exposure_target, NULL);
 920}
 921
 922static int vd55g1_apply_cold_start(struct vd55g1 *sensor,
 923				   struct v4l2_rect *crop)
 924{
 925	/*
 926	 * Cold start register is a single register expressed as exposure time
 927	 * in us. This differ from status registers being a combination of
 928	 * exposure, digital gain, and analog gain, requiring the following
 929	 * format conversion.
 930	 */
 931	unsigned int line_length = crop->width + sensor->hblank_ctrl->val;
 932	unsigned int line_time_us = DIV_ROUND_UP(line_length * MEGA,
 933						 sensor->pixel_clock);
 934	u8 d_gain = DIV_ROUND_CLOSEST(sensor->dgain_ctrl->val, 1 << 8);
 935	u8 a_gain = DIV_ROUND_CLOSEST(32, (32 - sensor->again_ctrl->val));
 936	unsigned int expo_us = sensor->expo_ctrl->val * d_gain * a_gain *
 937			       line_time_us;
 938	int ret = 0;
 939
 940	vd55g1_write(sensor, VD55G1_REG_AE_FORCE_COLDSTART, 1, &ret);
 941	vd55g1_write(sensor, VD55G1_REG_AE_COLDSTART_EXP_TIME, expo_us, &ret);
 942
 943	return ret;
 944}
 945
 946static void vd55g1_update_pad_fmt(struct vd55g1 *sensor,
 947				  const struct vd55g1_mode *mode, u32 code,
 948				  struct v4l2_mbus_framefmt *fmt)
 949{
 950	fmt->code = vd55g1_get_fmt_code(sensor, code);
 951	fmt->width = mode->width;
 952	fmt->height = mode->height;
 953	fmt->colorspace = V4L2_COLORSPACE_RAW;
 954	fmt->field = V4L2_FIELD_NONE;
 955	fmt->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
 956	fmt->quantization = V4L2_QUANTIZATION_DEFAULT;
 957	fmt->xfer_func = V4L2_XFER_FUNC_DEFAULT;
 958}
 959
 960static int vd55g1_update_hdr_mode(struct vd55g1 *sensor)
 961{
 962	int ret = 0;
 963
 964	switch (sensor->hdr_ctrl->val) {
 965	case VD55G1_NO_HDR:
 966		vd55g1_write(sensor, VD55G1_REG_EXPOSURE_MAX_COARSE,
 967			     VD55G1_EXPOSURE_MAX_COARSE_DEF, &ret);
 968		vd55g1_write(sensor, VD55G1_REG_EXPOSURE_USE_CASES, 0, &ret);
 969		vd55g1_write(sensor, VD55G1_REG_NEXT_CTX, 0x0, &ret);
 970
 971		vd55g1_write(sensor, VD55G1_REG_CTX_REPEAT_COUNT_CTX0, 0, &ret);
 972
 973		vd55g1_write(sensor, VD55G1_REG_VT_MODE(0),
 974			     VD55G1_VT_MODE_NORMAL, &ret);
 975		vd55g1_write(sensor, VD55G1_REG_MASK_FRAME_CTRL(0),
 976			     VD55G1_MASK_FRAME_CTRL_OUTPUT, &ret);
 977		break;
 978	case VD55G1_HDR_SUB:
 979		vd55g1_write(sensor, VD55G1_REG_EXPOSURE_MAX_COARSE,
 980			     VD55G1_EXPOSURE_MAX_COARSE_SUB, &ret);
 981		vd55g1_write(sensor, VD55G1_REG_EXPOSURE_USE_CASES,
 982			     VD55G1_EXPOSURE_USE_CASES_MULTI_CONTEXT, &ret);
 983		vd55g1_write(sensor, VD55G1_REG_NEXT_CTX, 0x0001, &ret);
 984
 985		vd55g1_write(sensor, VD55G1_REG_CTX_REPEAT_COUNT_CTX0, 1, &ret);
 986		vd55g1_write(sensor, VD55G1_REG_CTX_REPEAT_COUNT_CTX1, 1, &ret);
 987
 988		vd55g1_write(sensor, VD55G1_REG_VT_MODE(0),
 989			     VD55G1_VT_MODE_NORMAL, &ret);
 990		vd55g1_write(sensor, VD55G1_REG_MASK_FRAME_CTRL(0),
 991			     VD55G1_MASK_FRAME_CTRL_MASK, &ret);
 992		vd55g1_write(sensor, VD55G1_REG_EXPOSURE_INSTANCE(0), 0, &ret);
 993		vd55g1_write(sensor, VD55G1_REG_VT_MODE(1),
 994			     VD55G1_VT_MODE_SUBTRACTION, &ret);
 995		vd55g1_write(sensor, VD55G1_REG_MASK_FRAME_CTRL(1),
 996			     VD55G1_MASK_FRAME_CTRL_OUTPUT, &ret);
 997		vd55g1_write(sensor, VD55G1_REG_EXPOSURE_INSTANCE(1), 1, &ret);
 998		break;
 999	default:
1000		ret = -EINVAL;
1001	}
1002
1003	return ret;
1004}
1005
1006static int vd55g1_set_framefmt(struct vd55g1 *sensor,
1007			       struct v4l2_mbus_framefmt *format,
1008			       struct v4l2_rect *crop)
1009{
1010	u8 binning;
1011	int ret = 0;
1012
1013	vd55g1_write(sensor, VD55G1_REG_FORMAT_CTRL,
1014		     vd55g1_get_fmt_bpp(format->code), &ret);
1015	vd55g1_write(sensor, VD55G1_REG_OIF_IMG_CTRL,
1016		     vd55g1_get_fmt_data_type(format->code), &ret);
1017
1018	switch (crop->width / format->width) {
1019	case 1:
1020	default:
1021		binning = VD55G1_READOUT_CTRL_BIN_MODE_NORMAL;
1022		break;
1023	case 2:
1024		binning = VD55G1_READOUT_CTRL_BIN_MODE_DIGITAL_X2;
1025		break;
1026	}
1027	vd55g1_write(sensor, VD55G1_REG_READOUT_CTRL, binning, &ret);
1028
1029	vd55g1_write(sensor, VD55G1_REG_X_START(0), crop->left, &ret);
1030	vd55g1_write(sensor, VD55G1_REG_X_WIDTH(0), crop->width, &ret);
1031	vd55g1_write(sensor, VD55G1_REG_Y_START(0), crop->top, &ret);
1032	vd55g1_write(sensor, VD55G1_REG_Y_HEIGHT(0), crop->height, &ret);
1033
1034	vd55g1_write(sensor, VD55G1_REG_X_START(1), crop->left, &ret);
1035	vd55g1_write(sensor, VD55G1_REG_X_WIDTH(1), crop->width, &ret);
1036	vd55g1_write(sensor, VD55G1_REG_Y_START(1), crop->top, &ret);
1037	vd55g1_write(sensor, VD55G1_REG_Y_HEIGHT(1), crop->height, &ret);
1038
1039	return ret;
1040}
1041
1042static int vd55g1_update_gpios(struct vd55g1 *sensor, unsigned long gpio_mask)
1043{
1044	unsigned long io;
1045	u8 gpio_val;
1046	int ret = 0;
1047
1048	for_each_set_bit(io, &gpio_mask, VD55G1_NB_GPIOS) {
1049		gpio_val = sensor->gpios[io];
1050
1051		if (gpio_val == VD55G1_GPIO_MODE_STROBE &&
1052		    sensor->led_ctrl->val == V4L2_FLASH_LED_MODE_NONE) {
1053			gpio_val = VD55G1_GPIO_MODE_IN;
1054			if (sensor->hdr_ctrl->val == VD55G1_HDR_SUB) {
1055				/* Make its context 1 counterpart strobe too */
1056				vd55g1_write(sensor,
1057					     VD55G1_REG_GPIO_0_CTRL(1) + io,
1058					     gpio_val, &ret);
1059			}
1060		}
1061
1062		ret = vd55g1_write(sensor, VD55G1_REG_GPIO_0_CTRL(0) + io,
1063				   gpio_val, &ret);
1064	}
1065
1066	return ret;
1067}
1068
1069static int vd55g1_ro_ctrls_setup(struct vd55g1 *sensor, struct v4l2_rect *crop)
1070{
1071	return vd55g1_write(sensor, VD55G1_REG_LINE_LENGTH,
1072			    crop->width + sensor->hblank_ctrl->val, NULL);
1073}
1074
1075static void vd55g1_grab_ctrls(struct vd55g1 *sensor, bool enable)
1076{
1077	/* These settings cannot change during stream */
1078	v4l2_ctrl_grab(sensor->hflip_ctrl, enable);
1079	v4l2_ctrl_grab(sensor->vflip_ctrl, enable);
1080	v4l2_ctrl_grab(sensor->patgen_ctrl, enable);
1081	v4l2_ctrl_grab(sensor->hdr_ctrl, enable);
1082}
1083
1084static int vd55g1_enable_streams(struct v4l2_subdev *sd,
1085				 struct v4l2_subdev_state *state, u32 pad,
1086				 u64 streams_mask)
1087{
1088	struct vd55g1 *sensor = to_vd55g1(sd);
1089	struct v4l2_rect *crop =
1090		v4l2_subdev_state_get_crop(state, 0);
1091	struct v4l2_mbus_framefmt *format =
1092		v4l2_subdev_state_get_format(state, 0);
1093	int ret;
1094
1095	ret = pm_runtime_resume_and_get(sensor->dev);
1096	if (ret < 0)
1097		return ret;
1098
1099	/* Configure output */
1100	vd55g1_write(sensor, VD55G1_REG_MIPI_DATA_RATE,
1101		     sensor->mipi_rate, &ret);
1102	vd55g1_write(sensor, VD55G1_REG_OIF_CTRL, sensor->oif_ctrl, &ret);
1103	vd55g1_write(sensor, VD55G1_REG_ISL_ENABLE, 0, &ret);
1104	if (ret)
1105		goto err_rpm_put;
1106
1107	ret = vd55g1_set_framefmt(sensor, format, crop);
1108	if (ret)
1109		goto err_rpm_put;
1110
1111	/* Setup default GPIO values; could be overridden by V4L2 ctrl setup */
1112	ret = vd55g1_update_gpios(sensor, GENMASK(VD55G1_NB_GPIOS - 1, 0));
1113	if (ret)
1114		goto err_rpm_put;
1115
1116	ret = vd55g1_apply_cold_start(sensor, crop);
1117	if (ret)
1118		goto err_rpm_put;
1119
1120	/* Apply settings from V4L2 ctrls */
1121	ret = __v4l2_ctrl_handler_setup(&sensor->ctrl_handler);
1122	if (ret)
1123		goto err_rpm_put;
1124
1125	/* Also apply settings from read-only V4L2 ctrls */
1126	ret = vd55g1_ro_ctrls_setup(sensor, crop);
1127	if (ret)
1128		goto err_rpm_put;
1129
1130	/* Start streaming */
1131	vd55g1_write(sensor, VD55G1_REG_STBY, VD55G1_STBY_START_STREAM, &ret);
1132	vd55g1_poll_reg(sensor, VD55G1_REG_STBY, 0, &ret);
1133	vd55g1_wait_state(sensor, VD55G1_SYSTEM_FSM_STREAMING, &ret);
1134	if (ret)
1135		goto err_rpm_put;
1136
1137	vd55g1_grab_ctrls(sensor, true);
1138
1139	return 0;
1140
1141err_rpm_put:
1142	pm_runtime_put(sensor->dev);
1143	return -EINVAL;
1144}
1145
1146static int vd55g1_disable_streams(struct v4l2_subdev *sd,
1147				  struct v4l2_subdev_state *state, u32 pad,
1148				  u64 streams_mask)
1149{
1150	struct vd55g1 *sensor = to_vd55g1(sd);
1151	int ret = 0;
1152
1153	/* Retrieve Expo cluster to enable coldstart of AE */
1154	ret = vd55g1_read_expo_cluster(sensor);
1155
1156	vd55g1_write(sensor, VD55G1_REG_STREAMING, VD55G1_STREAMING_STOP_STREAM,
1157		     &ret);
1158	vd55g1_poll_reg(sensor, VD55G1_REG_STREAMING, 0, &ret);
1159	vd55g1_wait_state(sensor, VD55G1_SYSTEM_FSM_SW_STBY, &ret);
1160
1161	if (ret)
1162		dev_warn(sensor->dev, "Can't disable stream\n");
1163
1164	vd55g1_grab_ctrls(sensor, false);
1165
1166	pm_runtime_put_autosuspend(sensor->dev);
1167
1168	return ret;
1169}
1170
1171static int vd55g1_patch(struct vd55g1 *sensor)
1172{
1173	u64 patch;
1174	int ret = 0;
1175
1176	/* vd55g1 needs a patch while vd65g4 does not */
1177	if (sensor->id == VD55G1_MODEL_ID_VD55G1) {
1178		vd55g1_write_array(sensor, VD55G1_REG_FWPATCH_START_ADDR,
1179				   sizeof(vd55g1_patch_array),
1180				   vd55g1_patch_array, &ret);
1181		vd55g1_write(sensor, VD55G1_REG_BOOT,
1182			     VD55G1_BOOT_PATCH_AND_BOOT, &ret);
1183		vd55g1_poll_reg(sensor, VD55G1_REG_BOOT, 0, &ret);
1184		if (ret) {
1185			dev_err(sensor->dev, "Failed to apply patch\n");
1186			return ret;
1187		}
1188
1189		vd55g1_read(sensor, VD55G1_REG_FWPATCH_REVISION, &patch, &ret);
1190		if (patch != (VD55G1_FWPATCH_REVISION_MAJOR << 8) +
1191		    VD55G1_FWPATCH_REVISION_MINOR) {
1192			dev_err(sensor->dev, "Bad patch version expected %d.%d got %d.%d\n",
1193				VD55G1_FWPATCH_REVISION_MAJOR,
1194				VD55G1_FWPATCH_REVISION_MINOR,
1195				(u8)(patch >> 8), (u8)(patch & 0xff));
1196			return -ENODEV;
1197		}
1198		dev_dbg(sensor->dev, "patch %d.%d applied\n",
1199			(u8)(patch >> 8), (u8)(patch & 0xff));
1200
1201	} else {
1202		vd55g1_write(sensor, VD55G1_REG_BOOT, VD55G1_BOOT_BOOT, &ret);
1203		vd55g1_poll_reg(sensor, VD55G1_REG_BOOT, 0, &ret);
1204		if (ret) {
1205			dev_err(sensor->dev, "Failed to boot\n");
1206			return ret;
1207		}
1208	}
1209
1210	ret = vd55g1_wait_state(sensor, VD55G1_SYSTEM_FSM_SW_STBY, NULL);
1211	if (ret) {
1212		dev_err(sensor->dev, "Sensor waiting after boot failed\n");
1213		return ret;
1214	}
1215
1216	return 0;
1217}
1218
1219static int vd55g1_get_selection(struct v4l2_subdev *sd,
1220				struct v4l2_subdev_state *sd_state,
1221				struct v4l2_subdev_selection *sel)
1222{
1223	const struct v4l2_rect *crop = v4l2_subdev_state_get_crop(sd_state, 0);
1224
1225	switch (sel->target) {
1226	case V4L2_SEL_TGT_CROP:
1227		sel->r = *crop;
1228		return 0;
1229	case V4L2_SEL_TGT_NATIVE_SIZE:
1230	case V4L2_SEL_TGT_CROP_DEFAULT:
1231	case V4L2_SEL_TGT_CROP_BOUNDS:
1232		sel->r.top = 0;
1233		sel->r.left = 0;
1234		sel->r.width = VD55G1_WIDTH;
1235		sel->r.height = VD55G1_HEIGHT;
1236		return 0;
1237	}
1238
1239	return -EINVAL;
1240}
1241
1242static int vd55g1_enum_mbus_code(struct v4l2_subdev *sd,
1243				 struct v4l2_subdev_state *sd_state,
1244				 struct v4l2_subdev_mbus_code_enum *code)
1245{
1246	struct vd55g1 *sensor = to_vd55g1(sd);
1247	u32 base_code;
1248
1249	if (sensor->id == VD55G1_MODEL_ID_VD55G1) {
1250		if (code->index >= ARRAY_SIZE(vd55g1_mbus_formats_mono))
1251			return -EINVAL;
1252		base_code = vd55g1_mbus_formats_mono[code->index];
1253	} else {
1254		if (code->index >= ARRAY_SIZE(vd55g1_mbus_formats_bayer))
1255			return -EINVAL;
1256		base_code = vd55g1_mbus_formats_bayer[code->index][0];
1257	}
1258	code->code = vd55g1_get_fmt_code(sensor, base_code);
1259
1260	return 0;
1261}
1262
1263static int vd55g1_new_format_change_controls(struct vd55g1 *sensor,
1264					     struct v4l2_mbus_framefmt *format,
1265					     struct v4l2_rect *crop)
1266{
1267	struct vd55g1_vblank_limits vblank;
1268	unsigned int hblank;
1269	unsigned int frame_length = 0;
1270	unsigned int expo_max;
1271	int ret;
1272
1273	/* Reset vblank and frame length to default */
1274	vd55g1_get_vblank_limits(sensor, crop, &vblank);
1275	ret = __v4l2_ctrl_modify_range(sensor->vblank_ctrl, vblank.min,
1276				       vblank.max, 1, vblank.def);
1277	if (ret)
1278		return ret;
1279
1280	/* Max exposure changes with vblank */
1281	frame_length = crop->height + sensor->vblank_ctrl->val;
1282	expo_max = frame_length - VD55G1_EXPO_MAX_TERM;
1283	ret = __v4l2_ctrl_modify_range(sensor->expo_ctrl, 0, expo_max, 1,
1284				       VD55G1_EXPO_DEF);
1285	if (ret)
1286		return ret;
1287
1288	/* Update pixel rate to reflect new bpp */
1289	ret = __v4l2_ctrl_s_ctrl_int64(sensor->pixel_rate_ctrl,
1290				       vd55g1_get_pixel_rate(sensor, format));
1291	if (ret)
1292		return ret;
1293
1294	/* Update hblank according to new width */
1295	hblank = vd55g1_get_hblank_min(sensor, format, crop);
1296	ret = __v4l2_ctrl_modify_range(sensor->hblank_ctrl, hblank, hblank, 1,
1297				       hblank);
1298
1299	return ret;
1300}
1301
1302static int vd55g1_set_pad_fmt(struct v4l2_subdev *sd,
1303			      struct v4l2_subdev_state *sd_state,
1304			      struct v4l2_subdev_format *sd_fmt)
1305{
1306	struct vd55g1 *sensor = to_vd55g1(sd);
1307	const struct vd55g1_mode *new_mode;
1308	struct v4l2_mbus_framefmt *format;
1309	struct v4l2_rect pad_crop;
1310	unsigned int binning;
1311
1312	new_mode = v4l2_find_nearest_size(vd55g1_supported_modes,
1313					  ARRAY_SIZE(vd55g1_supported_modes),
1314					  width, height, sd_fmt->format.width,
1315					  sd_fmt->format.height);
1316
1317	vd55g1_update_pad_fmt(sensor, new_mode, sd_fmt->format.code,
1318			      &sd_fmt->format);
1319
1320	/*
1321	 * Use binning to maximize the crop rectangle size, and centre it in the
1322	 * sensor.
1323	 */
1324	binning = min(VD55G1_WIDTH / sd_fmt->format.width,
1325		      VD55G1_HEIGHT / sd_fmt->format.height);
1326	binning = min(binning, 2U);
1327	pad_crop.width = sd_fmt->format.width * binning;
1328	pad_crop.height = sd_fmt->format.height * binning;
1329	pad_crop.left = (VD55G1_WIDTH - pad_crop.width) / 2;
1330	pad_crop.top = (VD55G1_HEIGHT - pad_crop.height) / 2;
1331
1332	format = v4l2_subdev_state_get_format(sd_state, sd_fmt->pad);
1333
1334	*format = sd_fmt->format;
1335
1336	*v4l2_subdev_state_get_crop(sd_state, sd_fmt->pad) = pad_crop;
1337	if (sd_fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE)
1338		return vd55g1_new_format_change_controls(sensor,
1339							 &sd_fmt->format,
1340							 &pad_crop);
1341
1342	return 0;
1343}
1344
1345static int vd55g1_init_state(struct v4l2_subdev *sd,
1346			     struct v4l2_subdev_state *sd_state)
1347{
1348	struct vd55g1 *sensor = to_vd55g1(sd);
1349	struct v4l2_subdev_format fmt = { 0 };
1350	struct v4l2_subdev_route routes[] = {
1351		{ .flags = V4L2_SUBDEV_ROUTE_FL_ACTIVE }
1352	};
1353	struct v4l2_subdev_krouting routing = {
1354	    .num_routes = ARRAY_SIZE(routes),
1355	    .routes = routes,
1356	};
1357	int ret;
1358
1359	/* Needed by v4l2_subdev_s_stream_helper(), even with 1 stream only */
1360	ret = v4l2_subdev_set_routing(sd, sd_state, &routing);
1361	if (ret)
1362		return ret;
1363
1364	vd55g1_update_pad_fmt(sensor, &vd55g1_supported_modes[VD55G1_MODE_DEF],
1365			      vd55g1_get_fmt_code(sensor, VD55G1_MBUS_CODE_DEF),
1366			      &fmt.format);
1367
1368	return vd55g1_set_pad_fmt(sd, sd_state, &fmt);
1369}
1370
1371static int vd55g1_enum_frame_size(struct v4l2_subdev *sd,
1372				  struct v4l2_subdev_state *sd_state,
1373				  struct v4l2_subdev_frame_size_enum *fse)
1374{
1375	struct vd55g1 *sensor = to_vd55g1(sd);
1376	u32 code;
1377
1378	if (fse->index >= ARRAY_SIZE(vd55g1_supported_modes))
1379		return -EINVAL;
1380
1381	code = vd55g1_get_fmt_code(sensor, fse->code);
1382	if (fse->code != code)
1383		return -EINVAL;
1384
1385	fse->min_width = vd55g1_supported_modes[fse->index].width;
1386	fse->max_width = fse->min_width;
1387	fse->min_height = vd55g1_supported_modes[fse->index].height;
1388	fse->max_height = fse->min_height;
1389
1390	return 0;
1391}
1392
1393static const struct v4l2_subdev_internal_ops vd55g1_internal_ops = {
1394	.init_state = vd55g1_init_state,
1395};
1396
1397static const struct v4l2_subdev_pad_ops vd55g1_pad_ops = {
1398	.enum_mbus_code = vd55g1_enum_mbus_code,
1399	.get_fmt = v4l2_subdev_get_fmt,
1400	.set_fmt = vd55g1_set_pad_fmt,
1401	.get_selection = vd55g1_get_selection,
1402	.enum_frame_size = vd55g1_enum_frame_size,
1403	.enable_streams = vd55g1_enable_streams,
1404	.disable_streams = vd55g1_disable_streams,
1405};
1406
1407static const struct v4l2_subdev_video_ops vd55g1_video_ops = {
1408	.s_stream = v4l2_subdev_s_stream_helper,
1409};
1410
1411static const struct v4l2_subdev_ops vd55g1_subdev_ops = {
1412	.video = &vd55g1_video_ops,
1413	.pad = &vd55g1_pad_ops,
1414};
1415
1416static int vd55g1_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
1417{
1418	struct vd55g1 *sensor = ctrl_to_vd55g1(ctrl);
1419	int ret = 0;
1420
1421	/* Interact with HW only when it is powered ON */
1422	if (!pm_runtime_get_if_in_use(sensor->dev))
1423		return 0;
1424
1425	switch (ctrl->id) {
1426	case V4L2_CID_EXPOSURE_AUTO:
1427		ret = vd55g1_read_expo_cluster(sensor);
1428		break;
1429	default:
1430		ret = -EINVAL;
1431		break;
1432	}
1433
1434	pm_runtime_put_autosuspend(sensor->dev);
1435
1436	return ret;
1437}
1438
1439static int vd55g1_s_ctrl(struct v4l2_ctrl *ctrl)
1440{
1441	struct vd55g1 *sensor = ctrl_to_vd55g1(ctrl);
1442	unsigned int frame_length = 0;
1443	unsigned int expo_max;
1444	struct v4l2_subdev_state *state =
1445		v4l2_subdev_get_locked_active_state(&sensor->sd);
1446	struct v4l2_rect *crop =
1447		v4l2_subdev_state_get_crop(state, 0);
1448	struct v4l2_mbus_framefmt *format =
1449		v4l2_subdev_state_get_format(state, 0);
1450	unsigned int hblank = vd55g1_get_hblank_min(sensor, format, crop);
1451	bool is_auto = false;
1452	int ret = 0;
1453
1454	if (ctrl->flags & V4L2_CTRL_FLAG_READ_ONLY)
1455		return 0;
1456
1457	/* Update controls state, range, etc. whatever the state of the HW */
1458	switch (ctrl->id) {
1459	case V4L2_CID_VBLANK:
1460		frame_length = crop->height + ctrl->val;
1461		expo_max = frame_length - VD55G1_EXPO_MAX_TERM;
1462		ret = __v4l2_ctrl_modify_range(sensor->expo_ctrl, 0, expo_max,
1463					       1, VD55G1_EXPO_DEF);
1464		break;
1465	case V4L2_CID_EXPOSURE_AUTO:
1466		is_auto = (ctrl->val == V4L2_EXPOSURE_AUTO);
1467		__v4l2_ctrl_grab(sensor->ae_lock_ctrl, !is_auto);
1468		__v4l2_ctrl_grab(sensor->ae_bias_ctrl, !is_auto);
1469		break;
1470	case V4L2_CID_HDR_SENSOR_MODE:
1471		/* Discriminate if the userspace changed the control value */
1472		if (ctrl->val != ctrl->cur.val) {
1473			/* Max horizontal blanking changes with hdr mode */
1474			ret = __v4l2_ctrl_modify_range(sensor->hblank_ctrl,
1475						       hblank, hblank, 1,
1476						       hblank);
1477		}
1478		break;
1479	default:
1480		break;
1481	}
1482
1483	/* Don't modify hardware if controls modification failed */
1484	if (ret)
1485		return ret;
1486
1487	/* Interact with HW only when it is powered ON */
1488	if (!pm_runtime_get_if_in_use(sensor->dev))
1489		return 0;
1490
1491	switch (ctrl->id) {
1492	case V4L2_CID_HFLIP:
1493		ret = vd55g1_write(sensor, VD55G1_REG_ORIENTATION,
1494				   sensor->hflip_ctrl->val |
1495					   (sensor->vflip_ctrl->val << 1),
1496				   NULL);
1497		break;
1498	case V4L2_CID_TEST_PATTERN:
1499		ret = vd55g1_update_patgen(sensor, ctrl->val);
1500		break;
1501	case V4L2_CID_EXPOSURE_AUTO:
1502		ret = vd55g1_update_expo_cluster(sensor, is_auto);
1503		break;
1504	case V4L2_CID_3A_LOCK:
1505		ret = vd55g1_lock_exposure(sensor, ctrl->val);
1506		break;
1507	case V4L2_CID_AUTO_EXPOSURE_BIAS:
1508		/*
1509		 * We use auto exposure target percentage register to control
1510		 * exposure bias for more precision.
1511		 */
1512		ret = vd55g1_update_exposure_target(sensor, ctrl->val);
1513		break;
1514	case V4L2_CID_VBLANK:
1515		ret = vd55g1_update_frame_length(sensor, frame_length);
1516		break;
1517	case V4L2_CID_FLASH_LED_MODE:
1518		ret = vd55g1_update_gpios(sensor, sensor->ext_leds_mask);
1519		break;
1520	case V4L2_CID_HDR_SENSOR_MODE:
1521		ret = vd55g1_update_hdr_mode(sensor);
1522		break;
1523	default:
1524		ret = -EINVAL;
1525		break;
1526	}
1527
1528	pm_runtime_put_autosuspend(sensor->dev);
1529
1530	return ret;
1531}
1532
1533static const struct v4l2_ctrl_ops vd55g1_ctrl_ops = {
1534	.g_volatile_ctrl = vd55g1_g_volatile_ctrl,
1535	.s_ctrl = vd55g1_s_ctrl,
1536};
1537
1538static int vd55g1_init_ctrls(struct vd55g1 *sensor)
1539{
1540	const struct v4l2_ctrl_ops *ops = &vd55g1_ctrl_ops;
1541	struct v4l2_ctrl_handler *hdl = &sensor->ctrl_handler;
1542	struct v4l2_ctrl *ctrl;
1543	struct v4l2_fwnode_device_properties fwnode_props;
1544	struct vd55g1_vblank_limits vblank;
1545	unsigned int hblank;
1546	struct v4l2_subdev_state *state =
1547		v4l2_subdev_lock_and_get_active_state(&sensor->sd);
1548	struct v4l2_rect *crop =
1549		v4l2_subdev_state_get_crop(state, 0);
1550	struct v4l2_mbus_framefmt *format =
1551		v4l2_subdev_state_get_format(state, 0);
1552	s32 pixel_rate = vd55g1_get_pixel_rate(sensor, format);
1553	int ret;
1554
1555	v4l2_ctrl_handler_init(hdl, 16);
1556
1557	/* Flip cluster */
1558	sensor->hflip_ctrl = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_HFLIP,
1559					       0, 1, 1, 0);
1560	if (sensor->hflip_ctrl)
1561		sensor->hflip_ctrl->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT;
1562	sensor->vflip_ctrl = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_VFLIP,
1563					       0, 1, 1, 0);
1564	if (sensor->vflip_ctrl)
1565		sensor->vflip_ctrl->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT;
1566	v4l2_ctrl_cluster(2, &sensor->hflip_ctrl);
1567
1568	/* Exposition cluster */
1569	sensor->ae_ctrl = v4l2_ctrl_new_std_menu(hdl, ops,
1570						 V4L2_CID_EXPOSURE_AUTO, 1,
1571						 ~0x3, V4L2_EXPOSURE_AUTO);
1572	sensor->again_ctrl = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_ANALOGUE_GAIN,
1573					       0, 0x1c, 1, VD55G1_AGAIN_DEF);
1574	sensor->dgain_ctrl = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_DIGITAL_GAIN,
1575					       256, 0xffff, 1,
1576					       VD55G1_DGAIN_DEF);
1577	sensor->expo_ctrl = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_EXPOSURE, 0,
1578					      VD55G1_FRAME_LENGTH_DEF -
1579					      VD55G1_EXPO_MAX_TERM,
1580					      1, VD55G1_EXPO_DEF);
1581	v4l2_ctrl_auto_cluster(4, &sensor->ae_ctrl, V4L2_EXPOSURE_MANUAL, true);
1582
1583	sensor->patgen_ctrl =
1584		v4l2_ctrl_new_std_menu_items(hdl, ops, V4L2_CID_TEST_PATTERN,
1585					     ARRAY_SIZE(vd55g1_tp_menu) - 1, 0,
1586					     0, vd55g1_tp_menu);
1587	ctrl = v4l2_ctrl_new_int_menu(hdl, ops, V4L2_CID_LINK_FREQ,
1588				      0, 0, &sensor->link_freq);
1589	if (ctrl)
1590		ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
1591	sensor->pixel_rate_ctrl = v4l2_ctrl_new_std(hdl, ops,
1592						    V4L2_CID_PIXEL_RATE, 1,
1593						    INT_MAX, 1,
1594						    pixel_rate);
1595	if (sensor->pixel_rate_ctrl)
1596		sensor->pixel_rate_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
1597	sensor->ae_lock_ctrl = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_3A_LOCK,
1598						 0, 1, 0, 0);
1599	sensor->ae_bias_ctrl =
1600		v4l2_ctrl_new_int_menu(hdl, ops,
1601				       V4L2_CID_AUTO_EXPOSURE_BIAS,
1602				       ARRAY_SIZE(vd55g1_ev_bias_menu) - 1,
1603				       ARRAY_SIZE(vd55g1_ev_bias_menu) / 2,
1604				       vd55g1_ev_bias_menu);
1605	sensor->hdr_ctrl =
1606		v4l2_ctrl_new_std_menu_items(hdl, ops,
1607					     V4L2_CID_HDR_SENSOR_MODE,
1608					     ARRAY_SIZE(vd55g1_hdr_menu) - 1, 0,
1609					     VD55G1_NO_HDR, vd55g1_hdr_menu);
1610	hblank = vd55g1_get_hblank_min(sensor, format, crop);
1611	sensor->hblank_ctrl = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_HBLANK,
1612						hblank, hblank, 1, hblank);
1613	if (sensor->hblank_ctrl)
1614		sensor->hblank_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
1615	vd55g1_get_vblank_limits(sensor, crop, &vblank);
1616	sensor->vblank_ctrl = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_VBLANK,
1617						vblank.min, vblank.max,
1618						1, vblank.def);
1619
1620	/* Additional controls based on device tree properties */
1621	if (sensor->ext_leds_mask) {
1622		sensor->led_ctrl =
1623			v4l2_ctrl_new_std_menu(hdl, ops,
1624					       V4L2_CID_FLASH_LED_MODE,
1625					       V4L2_FLASH_LED_MODE_FLASH, 0,
1626					       V4L2_FLASH_LED_MODE_NONE);
1627	}
1628
1629	ret = v4l2_fwnode_device_parse(sensor->dev, &fwnode_props);
1630	if (ret)
1631		goto free_ctrls;
1632
1633	ret = v4l2_ctrl_new_fwnode_properties(hdl, ops, &fwnode_props);
1634	if (ret)
1635		goto free_ctrls;
1636
1637	sensor->sd.ctrl_handler = hdl;
1638	goto unlock_state;
1639
1640free_ctrls:
1641	v4l2_ctrl_handler_free(hdl);
1642unlock_state:
1643	v4l2_subdev_unlock_state(state);
1644	return ret;
1645}
1646
1647static int vd55g1_detect(struct vd55g1 *sensor)
1648{
1649	unsigned int dt_id = (uintptr_t)device_get_match_data(sensor->dev);
1650	u64 rev, id;
1651	int ret;
1652
1653	ret = vd55g1_read(sensor, VD55G1_REG_MODEL_ID, &id, NULL);
1654	if (ret)
1655		return ret;
1656
1657	if (id != VD55G1_MODEL_ID_VD55G1 && id != VD55G1_MODEL_ID_VD65G4) {
1658		dev_warn(sensor->dev, "Unsupported sensor id 0x%x\n",
1659			 (u32)id);
1660		return -ENODEV;
1661	}
1662	if (id != dt_id) {
1663		dev_err(sensor->dev, "Probed sensor %s and device tree definition (%s) mismatch",
1664			VD55G1_MODEL_ID_NAME(id), VD55G1_MODEL_ID_NAME(dt_id));
1665		return -ENODEV;
1666	}
1667	sensor->id = id;
1668
1669	ret = vd55g1_read(sensor, VD55G1_REG_REVISION, &rev, NULL);
1670	if (ret)
1671		return ret;
1672
1673	if ((id == VD55G1_MODEL_ID_VD55G1 && rev != VD55G1_REVISION_CCB) &&
1674	    (id == VD55G1_MODEL_ID_VD65G4 && rev != VD55G1_REVISION_BAYER)) {
1675		dev_err(sensor->dev, "Unsupported sensor revision 0x%x for sensor %s\n",
1676			(u16)rev, VD55G1_MODEL_ID_NAME(id));
1677		return -ENODEV;
1678	}
1679
1680	return 0;
1681}
1682
1683static int vd55g1_power_on(struct device *dev)
1684{
1685	struct v4l2_subdev *sd = dev_get_drvdata(dev);
1686	struct vd55g1 *sensor = to_vd55g1(sd);
1687	int ret;
1688
1689	ret = regulator_bulk_enable(ARRAY_SIZE(vd55g1_supply_name),
1690				    sensor->supplies);
1691	if (ret) {
1692		dev_err(dev, "Failed to enable regulators %d\n", ret);
1693		return ret;
1694	}
1695
1696	ret = clk_prepare_enable(sensor->xclk);
1697	if (ret) {
1698		dev_err(dev, "Failed to enable clock %d\n", ret);
1699		goto disable_bulk;
1700	}
1701
1702	gpiod_set_value_cansleep(sensor->reset_gpio, 0);
1703	usleep_range(5000, 10000);
1704	ret = vd55g1_wait_state(sensor, VD55G1_SYSTEM_FSM_READY_TO_BOOT, NULL);
1705	if (ret) {
1706		dev_err(dev, "Sensor reset failed %d\n", ret);
1707		goto disable_clock;
1708	}
1709
1710	ret = vd55g1_detect(sensor);
1711	if (ret) {
1712		dev_err(dev, "Sensor detect failed %d\n", ret);
1713		goto disable_clock;
1714	}
1715
1716	/* Setup clock now to advance through system FSM states */
1717	vd55g1_write(sensor, VD55G1_REG_EXT_CLOCK, sensor->xclk_freq, &ret);
1718
1719	ret = vd55g1_patch(sensor);
1720	if (ret) {
1721		dev_err(dev, "Sensor patch failed %d\n", ret);
1722		goto disable_clock;
1723	}
1724
1725	return 0;
1726
1727disable_clock:
1728	gpiod_set_value_cansleep(sensor->reset_gpio, 1);
1729	clk_disable_unprepare(sensor->xclk);
1730disable_bulk:
1731	regulator_bulk_disable(ARRAY_SIZE(vd55g1_supply_name),
1732			       sensor->supplies);
1733
1734	return ret;
1735}
1736
1737static int vd55g1_power_off(struct device *dev)
1738{
1739	struct v4l2_subdev *sd = dev_get_drvdata(dev);
1740	struct vd55g1 *sensor = to_vd55g1(sd);
1741
1742	gpiod_set_value_cansleep(sensor->reset_gpio, 1);
1743	clk_disable_unprepare(sensor->xclk);
1744	regulator_bulk_disable(ARRAY_SIZE(sensor->supplies), sensor->supplies);
1745
1746	return 0;
1747}
1748
1749static int vd55g1_check_csi_conf(struct vd55g1 *sensor,
1750				 struct fwnode_handle *endpoint)
1751{
1752	struct v4l2_fwnode_endpoint ep = { .bus_type = V4L2_MBUS_CSI2_DPHY };
1753	u8 n_lanes;
1754	int ret;
1755
1756	ret = v4l2_fwnode_endpoint_alloc_parse(endpoint, &ep);
1757	if (ret)
1758		return -EINVAL;
1759
1760	/* Check lanes number */
1761	n_lanes = ep.bus.mipi_csi2.num_data_lanes;
1762	if (n_lanes != 1) {
1763		dev_err(sensor->dev, "Sensor only supports 1 lane, found %d\n",
1764			n_lanes);
1765		ret = -EINVAL;
1766		goto done;
1767	}
1768
1769	/* Clock lane must be first */
1770	if (ep.bus.mipi_csi2.clock_lane != 0) {
1771		dev_err(sensor->dev, "Clock lane must be mapped to lane 0\n");
1772		ret = -EINVAL;
1773		goto done;
1774	}
1775
1776	/* Handle polarities in sensor configuration */
1777	sensor->oif_ctrl = (ep.bus.mipi_csi2.lane_polarities[0] << 3) |
1778			   (ep.bus.mipi_csi2.lane_polarities[1] << 6);
1779
1780	/* Check the link frequency set in device tree */
1781	if (!ep.nr_of_link_frequencies) {
1782		dev_err(sensor->dev, "link-frequency property not found in DT\n");
1783		ret = -EINVAL;
1784		goto done;
1785	}
1786	if (ep.nr_of_link_frequencies != 1) {
1787		dev_err(sensor->dev, "Multiple link frequencies not supported\n");
1788		ret = -EINVAL;
1789		goto done;
1790	}
1791	sensor->link_freq = ep.link_frequencies[0];
1792
1793done:
1794	v4l2_fwnode_endpoint_free(&ep);
1795
1796	return ret;
1797}
1798
1799static int vd55g1_parse_dt_gpios_array(struct vd55g1 *sensor,
1800				       char *prop_name, u32 *array, int *nb)
1801{
1802	unsigned int i;
1803	int ret;
1804
1805	*nb = device_property_count_u32(sensor->dev, prop_name);
1806	if (*nb == -EINVAL) {
1807		/* Property not found */
1808		*nb = 0;
1809		return 0;
1810	}
1811
1812	ret = device_property_read_u32_array(sensor->dev,
1813					     prop_name, array, *nb);
1814	if (ret) {
1815		dev_err(sensor->dev, "Failed to read %s prop\n", prop_name);
1816		return ret;
1817	}
1818	for (i = 0; i < *nb;  i++) {
1819		if (array[i] >= VD55G1_NB_GPIOS) {
1820			dev_err(sensor->dev, "Invalid GPIO number %d\n",
1821				array[i]);
1822			return -EINVAL;
1823		}
1824	}
1825
1826	return 0;
1827}
1828
1829static int vd55g1_parse_dt_gpios(struct vd55g1 *sensor)
1830{
1831	u32 led_gpios[VD55G1_NB_GPIOS];
1832	int nb_gpios_leds;
1833	unsigned int i;
1834	int ret;
1835
1836	/* Initialize GPIOs to default */
1837	for (i = 0; i < VD55G1_NB_GPIOS; i++)
1838		sensor->gpios[i] = VD55G1_GPIO_MODE_IN;
1839	sensor->ext_leds_mask = 0;
1840
1841	/* Take into account optional 'st,leds' output for GPIOs */
1842	ret = vd55g1_parse_dt_gpios_array(sensor, "st,leds", led_gpios,
1843					  &nb_gpios_leds);
1844	if (ret)
1845		return ret;
1846
1847	for (i = 0; i < nb_gpios_leds; i++) {
1848		sensor->gpios[led_gpios[i]] = VD55G1_GPIO_MODE_STROBE;
1849		set_bit(led_gpios[i], &sensor->ext_leds_mask);
1850	}
1851
1852	return 0;
1853}
1854
1855static int vd55g1_parse_dt(struct vd55g1 *sensor)
1856{
1857	struct fwnode_handle *endpoint;
1858	int ret;
1859
1860	endpoint = fwnode_graph_get_endpoint_by_id(dev_fwnode(sensor->dev),
1861						   0, 0, 0);
1862	if (!endpoint) {
1863		dev_err(sensor->dev, "Endpoint node not found\n");
1864		return -EINVAL;
1865	}
1866
1867	ret = vd55g1_check_csi_conf(sensor, endpoint);
1868	fwnode_handle_put(endpoint);
1869	if (ret)
1870		return ret;
1871
1872	return vd55g1_parse_dt_gpios(sensor);
1873}
1874
1875static int vd55g1_subdev_init(struct vd55g1 *sensor)
1876{
1877	int ret;
1878
1879	/* Init sub device */
1880	sensor->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
1881	sensor->sd.internal_ops = &vd55g1_internal_ops;
1882
1883	/* Init source pad */
1884	sensor->pad.flags = MEDIA_PAD_FL_SOURCE;
1885	sensor->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
1886	ret = media_entity_pads_init(&sensor->sd.entity, 1, &sensor->pad);
1887	if (ret) {
1888		dev_err(sensor->dev, "Failed to init media entity: %d\n", ret);
1889		return ret;
1890	}
1891
1892	sensor->sd.state_lock = sensor->ctrl_handler.lock;
1893	ret = v4l2_subdev_init_finalize(&sensor->sd);
1894	if (ret) {
1895		dev_err(sensor->dev, "Subdev init error: %d\n", ret);
1896		goto err_ctrls;
1897	}
1898
1899	/*
1900	 * Initialize controls after v4l2_subdev_init_finalize() to make sure
1901	 * active state is set
1902	 */
1903	ret = vd55g1_init_ctrls(sensor);
1904	if (ret) {
1905		dev_err(sensor->dev, "Controls initialization failed %d\n",
1906			ret);
1907		goto err_media;
1908	}
1909
1910	return 0;
1911
1912err_ctrls:
1913	v4l2_ctrl_handler_free(sensor->sd.ctrl_handler);
1914
1915err_media:
1916	media_entity_cleanup(&sensor->sd.entity);
1917	return ret;
1918}
1919
1920static void vd55g1_subdev_cleanup(struct vd55g1 *sensor)
1921{
1922	v4l2_async_unregister_subdev(&sensor->sd);
1923	v4l2_subdev_cleanup(&sensor->sd);
1924	media_entity_cleanup(&sensor->sd.entity);
1925	v4l2_ctrl_handler_free(sensor->sd.ctrl_handler);
1926}
1927
1928static int vd55g1_get_regulators(struct vd55g1 *sensor)
1929{
1930	unsigned int i;
1931
1932	for (i = 0; i < ARRAY_SIZE(vd55g1_supply_name); i++)
1933		sensor->supplies[i].supply = vd55g1_supply_name[i];
1934
1935	return devm_regulator_bulk_get(sensor->dev,
1936				       ARRAY_SIZE(vd55g1_supply_name),
1937				       sensor->supplies);
1938}
1939
1940static int vd55g1_probe(struct i2c_client *client)
1941{
1942	struct device *dev = &client->dev;
1943	struct vd55g1 *sensor;
1944	int ret;
1945
1946	sensor = devm_kzalloc(dev, sizeof(*sensor), GFP_KERNEL);
1947	if (!sensor)
1948		return -ENOMEM;
1949	sensor->dev = &client->dev;
1950
1951	v4l2_i2c_subdev_init(&sensor->sd, client, &vd55g1_subdev_ops);
1952
1953	ret = vd55g1_parse_dt(sensor);
1954	if (ret)
1955		return dev_err_probe(dev, ret, "Failed to parse Device Tree\n");
1956
1957	/* Get (and check) resources : power regs, ext clock, reset gpio */
1958	ret = vd55g1_get_regulators(sensor);
1959	if (ret)
1960		return dev_err_probe(dev, ret, "Failed to get regulators\n");
1961
1962	sensor->xclk = devm_v4l2_sensor_clk_get(dev, NULL);
1963	if (IS_ERR(sensor->xclk))
1964		return dev_err_probe(dev, PTR_ERR(sensor->xclk),
1965				     "Failed to get xclk\n");
1966
1967	sensor->xclk_freq = clk_get_rate(sensor->xclk);
1968	ret = vd55g1_prepare_clock_tree(sensor);
1969	if (ret)
1970		return ret;
1971
1972	sensor->reset_gpio = devm_gpiod_get_optional(dev, "reset",
1973						     GPIOD_OUT_HIGH);
1974	if (IS_ERR(sensor->reset_gpio))
1975		return dev_err_probe(dev, PTR_ERR(sensor->reset_gpio),
1976				     "Failed to get reset gpio\n");
1977
1978	sensor->regmap = devm_cci_regmap_init_i2c(client, 16);
1979	if (IS_ERR(sensor->regmap))
1980		return dev_err_probe(dev, PTR_ERR(sensor->regmap),
1981				     "Failed to init regmap\n");
1982
1983	/* Detect if sensor is present and if its revision is supported */
1984	ret = vd55g1_power_on(dev);
1985	if (ret)
1986		return ret;
1987
1988	/* Enable pm_runtime and power off the sensor */
1989	pm_runtime_set_active(dev);
1990	pm_runtime_get_noresume(dev);
1991	pm_runtime_enable(dev);
1992	pm_runtime_set_autosuspend_delay(dev, 4000);
1993	pm_runtime_use_autosuspend(dev);
1994	pm_runtime_put_autosuspend(dev);
1995
1996	ret = vd55g1_subdev_init(sensor);
1997	if (ret) {
1998		dev_err(dev, "V4l2 init failed: %d\n", ret);
1999		goto err_power_off;
2000	}
2001
2002	ret = v4l2_async_register_subdev(&sensor->sd);
2003	if (ret) {
2004		dev_err(dev, "async subdev register failed %d\n", ret);
2005		goto err_subdev;
2006	}
2007
2008	return 0;
2009
2010err_subdev:
2011	vd55g1_subdev_cleanup(sensor);
2012err_power_off:
2013	pm_runtime_disable(dev);
2014	pm_runtime_put_noidle(dev);
2015	pm_runtime_dont_use_autosuspend(dev);
2016	vd55g1_power_off(dev);
2017
2018	return ret;
2019}
2020
2021static void vd55g1_remove(struct i2c_client *client)
2022{
2023	struct v4l2_subdev *sd = i2c_get_clientdata(client);
2024	struct vd55g1 *sensor = to_vd55g1(sd);
2025
2026	vd55g1_subdev_cleanup(sensor);
2027
2028	pm_runtime_disable(&client->dev);
2029	if (!pm_runtime_status_suspended(&client->dev))
2030		vd55g1_power_off(&client->dev);
2031	pm_runtime_set_suspended(&client->dev);
2032	pm_runtime_dont_use_autosuspend(&client->dev);
2033}
2034
2035static const struct of_device_id vd55g1_dt_ids[] = {
2036	{ .compatible = "st,vd55g1", .data = (void *)VD55G1_MODEL_ID_VD55G1 },
2037	{ .compatible = "st,vd65g4", .data = (void *)VD55G1_MODEL_ID_VD65G4 },
2038	{ /* sentinel */ }
2039};
2040MODULE_DEVICE_TABLE(of, vd55g1_dt_ids);
2041
2042static const struct dev_pm_ops vd55g1_pm_ops = {
2043	SET_RUNTIME_PM_OPS(vd55g1_power_off, vd55g1_power_on, NULL)
2044};
2045
2046static struct i2c_driver vd55g1_i2c_driver = {
2047	.driver = {
2048		.name  = "vd55g1",
2049		.of_match_table = vd55g1_dt_ids,
2050		.pm = &vd55g1_pm_ops,
2051	},
2052	.probe = vd55g1_probe,
2053	.remove = vd55g1_remove,
2054};
2055
2056module_i2c_driver(vd55g1_i2c_driver);
2057
2058MODULE_AUTHOR("Benjamin Mugnier <benjamin.mugnier@foss.st.com>");
2059MODULE_AUTHOR("Sylvain Petinot <sylvain.petinot@foss.st.com>");
2060MODULE_DESCRIPTION("VD55G1 camera subdev driver");
2061MODULE_LICENSE("GPL");
~/ Read-only file preview.