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