xref: /openbmc/linux/drivers/media/i2c/hi847.c (revision 2f164822)
1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (c) 2022 Intel Corporation.
3 
4 #include <asm/unaligned.h>
5 #include <linux/acpi.h>
6 #include <linux/delay.h>
7 #include <linux/i2c.h>
8 #include <linux/module.h>
9 #include <linux/pm_runtime.h>
10 #include <media/v4l2-ctrls.h>
11 #include <media/v4l2-device.h>
12 #include <media/v4l2-fwnode.h>
13 
14 #define HI847_REG_VALUE_08BIT		1
15 #define HI847_REG_VALUE_16BIT		2
16 #define HI847_REG_VALUE_24BIT		3
17 
18 #define HI847_LINK_FREQ_400MHZ		400000000ULL
19 #define HI847_LINK_FREQ_200MHZ		200000000ULL
20 #define HI847_SCLK			72000000ULL
21 #define HI847_MCLK			19200000
22 #define HI847_DATA_LANES		4
23 #define HI847_RGB_DEPTH			10
24 
25 #define HI847_REG_CHIP_ID		0x0716
26 #define HI847_CHIP_ID			0x0847
27 
28 #define HI847_REG_MODE_SELECT		0x0B00
29 #define HI847_MODE_STANDBY		0x0000
30 #define HI847_MODE_STREAMING		0x0100
31 
32 #define HI847_REG_MODE_TG		0x027E
33 #define HI847_REG_MODE_TG_ENABLE	0x0100
34 #define HI847_REG_MODE_TG_DISABLE	0x0000
35 
36 /* vertical-timings from sensor */
37 #define HI847_REG_FLL			0x020E
38 #define HI847_FLL_30FPS			0x0B51
39 #define HI847_FLL_30FPS_MIN		0x0B51
40 #define HI847_FLL_60FPS			0x05A9
41 #define HI847_FLL_60FPS_MIN		0x05A9
42 #define HI847_FLL_MAX			0x7fff
43 
44 /* horizontal-timings from sensor */
45 #define HI847_REG_LLP			0x0206
46 
47 /* Exposure controls from sensor */
48 #define HI847_REG_EXPOSURE		0x020A
49 #define HI847_EXPOSURE_MIN		4
50 #define HI847_EXPOSURE_MAX_MARGIN	4
51 #define HI847_EXPOSURE_STEP		1
52 
53 /* Analog gain controls from sensor */
54 #define HI847_REG_ANALOG_GAIN		0x0212
55 #define HI847_ANAL_GAIN_MIN		0
56 #define HI847_ANAL_GAIN_MAX		240
57 #define HI847_ANAL_GAIN_STEP		1
58 
59 /* Digital gain controls from sensor */
60 #define HI847_REG_MWB_GR_GAIN		0x0214
61 #define HI847_REG_MWB_GB_GAIN		0x0216
62 #define HI847_REG_MWB_R_GAIN		0x0218
63 #define HI847_REG_MWB_B_GAIN		0x021A
64 #define HI847_DGTL_GAIN_MIN		1
65 #define HI847_DGTL_GAIN_MAX		8191
66 #define HI847_DGTL_GAIN_STEP		1
67 #define HI847_DGTL_GAIN_DEFAULT		512
68 
69 /* Test Pattern Control */
70 #define HI847_REG_ISP			0X0B04
71 #define HI847_REG_ISP_TPG_EN		0x0001
72 #define HI847_REG_TEST_PATTERN		0x0C0A
73 
74 /* Flip Mirror Controls from sensor */
75 #define HI847_REG_MIRROR_FLIP	0x0202
76 
77 #define HI847_REG_FORMAT_X	0x0F04
78 #define HI847_REG_FORMAT_Y	0x0F06
79 
80 enum {
81 	HI847_LINK_FREQ_400MHZ_INDEX,
82 	HI847_LINK_FREQ_200MHZ_INDEX,
83 };
84 
85 struct hi847_reg {
86 	u16 address;
87 	u16 val;
88 };
89 
90 struct hi847_reg_list {
91 	u32 num_of_regs;
92 	const struct hi847_reg *regs;
93 };
94 
95 struct hi847_link_freq_config {
96 	const struct hi847_reg_list reg_list;
97 };
98 
99 struct hi847_mode {
100 	/* Frame width in pixels */
101 	u32 width;
102 
103 	/* Frame height in pixels */
104 	u32 height;
105 
106 	/* Horizontal timining size */
107 	u32 llp;
108 
109 	/* Default vertical timining size */
110 	u32 fll_def;
111 
112 	/* Min vertical timining size */
113 	u32 fll_min;
114 
115 	/* Link frequency needed for this resolution */
116 	u32 link_freq_index;
117 
118 	/* Sensor register settings for this resolution */
119 	const struct hi847_reg_list reg_list;
120 };
121 
122 #define to_hi847(_sd) container_of(_sd, struct hi847, sd)
123 
124 //SENSOR_INITIALIZATION
125 static const struct hi847_reg mipi_data_rate_lane_4[] = {
126 	{0x0790, 0x0100},
127 	{0x2000, 0x0000},
128 	{0x2002, 0x0058},
129 	{0x2006, 0x40B2},
130 	{0x2008, 0xB05C},
131 	{0x200A, 0x8446},
132 	{0x200C, 0x40B2},
133 	{0x200E, 0xB082},
134 	{0x2010, 0x8450},
135 	{0x2012, 0x40B2},
136 	{0x2014, 0xB0AE},
137 	{0x2016, 0x84C6},
138 	{0x2018, 0x40B2},
139 	{0x201A, 0xB11A},
140 	{0x201C, 0x84BC},
141 	{0x201E, 0x40B2},
142 	{0x2020, 0xB34A},
143 	{0x2022, 0x84B4},
144 	{0x2024, 0x40B2},
145 	{0x2026, 0xB386},
146 	{0x2028, 0x84B0},
147 	{0x202A, 0x40B2},
148 	{0x202C, 0xB3B4},
149 	{0x202E, 0x84B8},
150 	{0x2030, 0x40B2},
151 	{0x2032, 0xB0F4},
152 	{0x2034, 0x8470},
153 	{0x2036, 0x40B2},
154 	{0x2038, 0xB3EA},
155 	{0x203A, 0x847C},
156 	{0x203C, 0x40B2},
157 	{0x203E, 0xB658},
158 	{0x2040, 0x8478},
159 	{0x2042, 0x40B2},
160 	{0x2044, 0xB67E},
161 	{0x2046, 0x847E},
162 	{0x2048, 0x40B2},
163 	{0x204A, 0xB78E},
164 	{0x204C, 0x843A},
165 	{0x204E, 0x40B2},
166 	{0x2050, 0xB980},
167 	{0x2052, 0x845C},
168 	{0x2054, 0x40B2},
169 	{0x2056, 0xB9B0},
170 	{0x2058, 0x845E},
171 	{0x205A, 0x4130},
172 	{0x205C, 0x1292},
173 	{0x205E, 0xD016},
174 	{0x2060, 0xB3D2},
175 	{0x2062, 0x0B00},
176 	{0x2064, 0x2002},
177 	{0x2066, 0xD2E2},
178 	{0x2068, 0x0381},
179 	{0x206A, 0x93C2},
180 	{0x206C, 0x0263},
181 	{0x206E, 0x2001},
182 	{0x2070, 0x4130},
183 	{0x2072, 0x422D},
184 	{0x2074, 0x403E},
185 	{0x2076, 0x888E},
186 	{0x2078, 0x403F},
187 	{0x207A, 0x192A},
188 	{0x207C, 0x1292},
189 	{0x207E, 0x843E},
190 	{0x2080, 0x3FF7},
191 	{0x2082, 0x422D},
192 	{0x2084, 0x403E},
193 	{0x2086, 0x192A},
194 	{0x2088, 0x403F},
195 	{0x208A, 0x888E},
196 	{0x208C, 0x1292},
197 	{0x208E, 0x843E},
198 	{0x2090, 0xB3D2},
199 	{0x2092, 0x0267},
200 	{0x2094, 0x2403},
201 	{0x2096, 0xD0F2},
202 	{0x2098, 0x0040},
203 	{0x209A, 0x0381},
204 	{0x209C, 0x90F2},
205 	{0x209E, 0x0010},
206 	{0x20A0, 0x0260},
207 	{0x20A2, 0x2002},
208 	{0x20A4, 0x1292},
209 	{0x20A6, 0x84BC},
210 	{0x20A8, 0x1292},
211 	{0x20AA, 0xD020},
212 	{0x20AC, 0x4130},
213 	{0x20AE, 0x1292},
214 	{0x20B0, 0x8470},
215 	{0x20B2, 0x1292},
216 	{0x20B4, 0x8452},
217 	{0x20B6, 0x0900},
218 	{0x20B8, 0x7118},
219 	{0x20BA, 0x1292},
220 	{0x20BC, 0x848E},
221 	{0x20BE, 0x0900},
222 	{0x20C0, 0x7112},
223 	{0x20C2, 0x0800},
224 	{0x20C4, 0x7A20},
225 	{0x20C6, 0x4292},
226 	{0x20C8, 0x87DE},
227 	{0x20CA, 0x7334},
228 	{0x20CC, 0x0F00},
229 	{0x20CE, 0x7304},
230 	{0x20D0, 0x421F},
231 	{0x20D2, 0x8718},
232 	{0x20D4, 0x1292},
233 	{0x20D6, 0x846E},
234 	{0x20D8, 0x1292},
235 	{0x20DA, 0x8488},
236 	{0x20DC, 0x0B00},
237 	{0x20DE, 0x7114},
238 	{0x20E0, 0x0002},
239 	{0x20E2, 0x1292},
240 	{0x20E4, 0x848C},
241 	{0x20E6, 0x1292},
242 	{0x20E8, 0x8454},
243 	{0x20EA, 0x43C2},
244 	{0x20EC, 0x86EE},
245 	{0x20EE, 0x1292},
246 	{0x20F0, 0x8444},
247 	{0x20F2, 0x4130},
248 	{0x20F4, 0x4392},
249 	{0x20F6, 0x7360},
250 	{0x20F8, 0xB3D2},
251 	{0x20FA, 0x0B00},
252 	{0x20FC, 0x2402},
253 	{0x20FE, 0xC2E2},
254 	{0x2100, 0x0381},
255 	{0x2102, 0x0900},
256 	{0x2104, 0x732C},
257 	{0x2106, 0x4382},
258 	{0x2108, 0x7360},
259 	{0x210A, 0x422D},
260 	{0x210C, 0x403E},
261 	{0x210E, 0x87F0},
262 	{0x2110, 0x403F},
263 	{0x2112, 0x87E8},
264 	{0x2114, 0x1292},
265 	{0x2116, 0x843E},
266 	{0x2118, 0x4130},
267 	{0x211A, 0x120B},
268 	{0x211C, 0x120A},
269 	{0x211E, 0x4392},
270 	{0x2120, 0x87FA},
271 	{0x2122, 0x4392},
272 	{0x2124, 0x760E},
273 	{0x2126, 0x0900},
274 	{0x2128, 0x760C},
275 	{0x212A, 0x421B},
276 	{0x212C, 0x760A},
277 	{0x212E, 0x903B},
278 	{0x2130, 0x0201},
279 	{0x2132, 0x2408},
280 	{0x2134, 0x903B},
281 	{0x2136, 0x0102},
282 	{0x2138, 0x2405},
283 	{0x213A, 0x4292},
284 	{0x213C, 0x030A},
285 	{0x213E, 0x87F8},
286 	{0x2140, 0x1292},
287 	{0x2142, 0x849A},
288 	{0x2144, 0x903B},
289 	{0x2146, 0x0020},
290 	{0x2148, 0x2010},
291 	{0x214A, 0x403B},
292 	{0x214C, 0x8498},
293 	{0x214E, 0x422F},
294 	{0x2150, 0x12AB},
295 	{0x2152, 0x403F},
296 	{0x2154, 0x0028},
297 	{0x2156, 0x12AB},
298 	{0x2158, 0x403B},
299 	{0x215A, 0x84C4},
300 	{0x215C, 0x407F},
301 	{0x215E, 0xFFAA},
302 	{0x2160, 0x12AB},
303 	{0x2162, 0x407F},
304 	{0x2164, 0x0055},
305 	{0x2166, 0x12AB},
306 	{0x2168, 0x3FDC},
307 	{0x216A, 0x903B},
308 	{0x216C, 0x0021},
309 	{0x216E, 0x2890},
310 	{0x2170, 0x903B},
311 	{0x2172, 0x0100},
312 	{0x2174, 0x200D},
313 	{0x2176, 0x403F},
314 	{0x2178, 0x0028},
315 	{0x217A, 0x1292},
316 	{0x217C, 0x8498},
317 	{0x217E, 0x425F},
318 	{0x2180, 0x0306},
319 	{0x2182, 0x1292},
320 	{0x2184, 0x84C4},
321 	{0x2186, 0x4FC2},
322 	{0x2188, 0x0318},
323 	{0x218A, 0x0261},
324 	{0x218C, 0x0000},
325 	{0x218E, 0x3FC9},
326 	{0x2190, 0x903B},
327 	{0x2192, 0x0101},
328 	{0x2194, 0x2858},
329 	{0x2196, 0x903B},
330 	{0x2198, 0x0200},
331 	{0x219A, 0x2450},
332 	{0x219C, 0x903B},
333 	{0x219E, 0x0201},
334 	{0x21A0, 0x2C47},
335 	{0x21A2, 0x903B},
336 	{0x21A4, 0x0102},
337 	{0x21A6, 0x2041},
338 	{0x21A8, 0x93E2},
339 	{0x21AA, 0x0262},
340 	{0x21AC, 0x240A},
341 	{0x21AE, 0x425F},
342 	{0x21B0, 0x0306},
343 	{0x21B2, 0x1292},
344 	{0x21B4, 0x84C4},
345 	{0x21B6, 0x4F4E},
346 	{0x21B8, 0x4EC2},
347 	{0x21BA, 0x0318},
348 	{0x21BC, 0x0260},
349 	{0x21BE, 0x0000},
350 	{0x21C0, 0x3FB0},
351 	{0x21C2, 0x403A},
352 	{0x21C4, 0x8030},
353 	{0x21C6, 0x4382},
354 	{0x21C8, 0x0326},
355 	{0x21CA, 0x4382},
356 	{0x21CC, 0x0328},
357 	{0x21CE, 0x421B},
358 	{0x21D0, 0x030C},
359 	{0x21D2, 0x930B},
360 	{0x21D4, 0x2420},
361 	{0x21D6, 0x4A5F},
362 	{0x21D8, 0x0001},
363 	{0x21DA, 0x1292},
364 	{0x21DC, 0x84C4},
365 	{0x21DE, 0x4F4E},
366 	{0x21E0, 0x4A5F},
367 	{0x21E2, 0x0001},
368 	{0x21E4, 0x9F0E},
369 	{0x21E6, 0x2402},
370 	{0x21E8, 0x5392},
371 	{0x21EA, 0x0326},
372 	{0x21EC, 0x4ECA},
373 	{0x21EE, 0x0001},
374 	{0x21F0, 0x533B},
375 	{0x21F2, 0x2411},
376 	{0x21F4, 0x4A6F},
377 	{0x21F6, 0x1292},
378 	{0x21F8, 0x84C4},
379 	{0x21FA, 0x4F4E},
380 	{0x21FC, 0x4A6F},
381 	{0x21FE, 0x9F0E},
382 	{0x2200, 0x2402},
383 	{0x2202, 0x5392},
384 	{0x2204, 0x0326},
385 	{0x2206, 0x4ECA},
386 	{0x2208, 0x0000},
387 	{0x220A, 0x533B},
388 	{0x220C, 0x532A},
389 	{0x220E, 0x0260},
390 	{0x2210, 0x0000},
391 	{0x2212, 0x930B},
392 	{0x2214, 0x23E0},
393 	{0x2216, 0x40B2},
394 	{0x2218, 0xAA55},
395 	{0x221A, 0x0328},
396 	{0x221C, 0xB0F2},
397 	{0x221E, 0x0040},
398 	{0x2220, 0x0381},
399 	{0x2222, 0x277F},
400 	{0x2224, 0xD3D2},
401 	{0x2226, 0x0267},
402 	{0x2228, 0x3F7C},
403 	{0x222A, 0x0261},
404 	{0x222C, 0x0000},
405 	{0x222E, 0x3F79},
406 	{0x2230, 0x903B},
407 	{0x2232, 0x0201},
408 	{0x2234, 0x23FA},
409 	{0x2236, 0x1292},
410 	{0x2238, 0x84C0},
411 	{0x223A, 0x3F73},
412 	{0x223C, 0x1292},
413 	{0x223E, 0x84C0},
414 	{0x2240, 0x0261},
415 	{0x2242, 0x0000},
416 	{0x2244, 0x3F6E},
417 	{0x2246, 0x903B},
418 	{0x2248, 0x0040},
419 	{0x224A, 0x2018},
420 	{0x224C, 0x422F},
421 	{0x224E, 0x1292},
422 	{0x2250, 0x8498},
423 	{0x2252, 0x12B0},
424 	{0x2254, 0xF0EA},
425 	{0x2256, 0x907F},
426 	{0x2258, 0xFFAA},
427 	{0x225A, 0x240D},
428 	{0x225C, 0x5392},
429 	{0x225E, 0x0312},
430 	{0x2260, 0x12B0},
431 	{0x2262, 0xF0EA},
432 	{0x2264, 0x907F},
433 	{0x2266, 0x0055},
434 	{0x2268, 0x2403},
435 	{0x226A, 0x5392},
436 	{0x226C, 0x0312},
437 	{0x226E, 0x3F59},
438 	{0x2270, 0x5392},
439 	{0x2272, 0x0310},
440 	{0x2274, 0x3F56},
441 	{0x2276, 0x5392},
442 	{0x2278, 0x0310},
443 	{0x227A, 0x3FF2},
444 	{0x227C, 0x903B},
445 	{0x227E, 0x0080},
446 	{0x2280, 0x23D4},
447 	{0x2282, 0x4382},
448 	{0x2284, 0x0312},
449 	{0x2286, 0x4382},
450 	{0x2288, 0x0310},
451 	{0x228A, 0x0261},
452 	{0x228C, 0x0000},
453 	{0x228E, 0x3F49},
454 	{0x2290, 0x932B},
455 	{0x2292, 0x2005},
456 	{0x2294, 0x403F},
457 	{0x2296, 0x0028},
458 	{0x2298, 0x1292},
459 	{0x229A, 0x8498},
460 	{0x229C, 0x3F42},
461 	{0x229E, 0x903B},
462 	{0x22A0, 0x0003},
463 	{0x22A2, 0x284B},
464 	{0x22A4, 0x923B},
465 	{0x22A6, 0x2015},
466 	{0x22A8, 0x403F},
467 	{0x22AA, 0x0023},
468 	{0x22AC, 0x1292},
469 	{0x22AE, 0x8498},
470 	{0x22B0, 0x421B},
471 	{0x22B2, 0x87F8},
472 	{0x22B4, 0x421F},
473 	{0x22B6, 0x030C},
474 	{0x22B8, 0x9F0B},
475 	{0x22BA, 0x2F33},
476 	{0x22BC, 0x1292},
477 	{0x22BE, 0x84BA},
478 	{0x22C0, 0x930F},
479 	{0x22C2, 0x2004},
480 	{0x22C4, 0x5392},
481 	{0x22C6, 0x0312},
482 	{0x22C8, 0x531B},
483 	{0x22CA, 0x3FF4},
484 	{0x22CC, 0x5392},
485 	{0x22CE, 0x0310},
486 	{0x22D0, 0x3FFB},
487 	{0x22D2, 0x903B},
488 	{0x22D4, 0x0009},
489 	{0x22D6, 0x2818},
490 	{0x22D8, 0x903B},
491 	{0x22DA, 0x0010},
492 	{0x22DC, 0x23A6},
493 	{0x22DE, 0x403F},
494 	{0x22E0, 0x0027},
495 	{0x22E2, 0x1292},
496 	{0x22E4, 0x8498},
497 	{0x22E6, 0x421B},
498 	{0x22E8, 0x87F8},
499 	{0x22EA, 0x421F},
500 	{0x22EC, 0x030C},
501 	{0x22EE, 0x9F0B},
502 	{0x22F0, 0x2F18},
503 	{0x22F2, 0x1292},
504 	{0x22F4, 0x84BA},
505 	{0x22F6, 0x930F},
506 	{0x22F8, 0x2004},
507 	{0x22FA, 0x5392},
508 	{0x22FC, 0x0312},
509 	{0x22FE, 0x531B},
510 	{0x2300, 0x3FF4},
511 	{0x2302, 0x5392},
512 	{0x2304, 0x0310},
513 	{0x2306, 0x3FFB},
514 	{0x2308, 0x922B},
515 	{0x230A, 0x238F},
516 	{0x230C, 0x421B},
517 	{0x230E, 0x87F8},
518 	{0x2310, 0x421F},
519 	{0x2312, 0x030C},
520 	{0x2314, 0x9F0B},
521 	{0x2316, 0x2C0B},
522 	{0x2318, 0x1292},
523 	{0x231A, 0x84C2},
524 	{0x231C, 0x934F},
525 	{0x231E, 0x240A},
526 	{0x2320, 0x5392},
527 	{0x2322, 0x0312},
528 	{0x2324, 0x531B},
529 	{0x2326, 0x421F},
530 	{0x2328, 0x030C},
531 	{0x232A, 0x9F0B},
532 	{0x232C, 0x2BF5},
533 	{0x232E, 0x0261},
534 	{0x2330, 0x0000},
535 	{0x2332, 0x3EF7},
536 	{0x2334, 0x5392},
537 	{0x2336, 0x0310},
538 	{0x2338, 0x3FF5},
539 	{0x233A, 0x930B},
540 	{0x233C, 0x277F},
541 	{0x233E, 0x931B},
542 	{0x2340, 0x277A},
543 	{0x2342, 0x3F73},
544 	{0x2344, 0x413A},
545 	{0x2346, 0x413B},
546 	{0x2348, 0x4130},
547 	{0x234A, 0x4F0C},
548 	{0x234C, 0x403F},
549 	{0x234E, 0x0267},
550 	{0x2350, 0xF0FF},
551 	{0x2352, 0xFFDF},
552 	{0x2354, 0x0000},
553 	{0x2356, 0xF0FF},
554 	{0x2358, 0xFFEF},
555 	{0x235A, 0x0000},
556 	{0x235C, 0x421D},
557 	{0x235E, 0x84B0},
558 	{0x2360, 0x403E},
559 	{0x2362, 0x06F9},
560 	{0x2364, 0x4C0F},
561 	{0x2366, 0x1292},
562 	{0x2368, 0x84AC},
563 	{0x236A, 0x4F4E},
564 	{0x236C, 0xB31E},
565 	{0x236E, 0x2403},
566 	{0x2370, 0xD0F2},
567 	{0x2372, 0x0020},
568 	{0x2374, 0x0267},
569 	{0x2376, 0xB32E},
570 	{0x2378, 0x2403},
571 	{0x237A, 0xD0F2},
572 	{0x237C, 0x0010},
573 	{0x237E, 0x0267},
574 	{0x2380, 0xC3E2},
575 	{0x2382, 0x0267},
576 	{0x2384, 0x4130},
577 	{0x2386, 0x120B},
578 	{0x2388, 0x120A},
579 	{0x238A, 0x403A},
580 	{0x238C, 0x1140},
581 	{0x238E, 0x1292},
582 	{0x2390, 0xD080},
583 	{0x2392, 0x430B},
584 	{0x2394, 0x4A0F},
585 	{0x2396, 0x532A},
586 	{0x2398, 0x1292},
587 	{0x239A, 0x84A4},
588 	{0x239C, 0x4F0E},
589 	{0x239E, 0x430F},
590 	{0x23A0, 0x5E82},
591 	{0x23A2, 0x87FC},
592 	{0x23A4, 0x6F82},
593 	{0x23A6, 0x87FE},
594 	{0x23A8, 0x531B},
595 	{0x23AA, 0x923B},
596 	{0x23AC, 0x2BF3},
597 	{0x23AE, 0x413A},
598 	{0x23B0, 0x413B},
599 	{0x23B2, 0x4130},
600 	{0x23B4, 0xF0F2},
601 	{0x23B6, 0x007F},
602 	{0x23B8, 0x0267},
603 	{0x23BA, 0x421D},
604 	{0x23BC, 0x84B6},
605 	{0x23BE, 0x403E},
606 	{0x23C0, 0x01F9},
607 	{0x23C2, 0x1292},
608 	{0x23C4, 0x84AC},
609 	{0x23C6, 0x4F4E},
610 	{0x23C8, 0xF35F},
611 	{0x23CA, 0x2403},
612 	{0x23CC, 0xD0F2},
613 	{0x23CE, 0xFF80},
614 	{0x23D0, 0x0267},
615 	{0x23D2, 0xB36E},
616 	{0x23D4, 0x2404},
617 	{0x23D6, 0xD0F2},
618 	{0x23D8, 0x0040},
619 	{0x23DA, 0x0267},
620 	{0x23DC, 0x3C03},
621 	{0x23DE, 0xF0F2},
622 	{0x23E0, 0xFFBF},
623 	{0x23E2, 0x0267},
624 	{0x23E4, 0xC2E2},
625 	{0x23E6, 0x0267},
626 	{0x23E8, 0x4130},
627 	{0x23EA, 0x120B},
628 	{0x23EC, 0x120A},
629 	{0x23EE, 0x8231},
630 	{0x23F0, 0x430B},
631 	{0x23F2, 0x93C2},
632 	{0x23F4, 0x0C0A},
633 	{0x23F6, 0x2404},
634 	{0x23F8, 0xB3D2},
635 	{0x23FA, 0x0B05},
636 	{0x23FC, 0x2401},
637 	{0x23FE, 0x431B},
638 	{0x2400, 0x422D},
639 	{0x2402, 0x403E},
640 	{0x2404, 0x192A},
641 	{0x2406, 0x403F},
642 	{0x2408, 0x888E},
643 	{0x240A, 0x1292},
644 	{0x240C, 0x843E},
645 	{0x240E, 0x930B},
646 	{0x2410, 0x20F4},
647 	{0x2412, 0x93E2},
648 	{0x2414, 0x0241},
649 	{0x2416, 0x24EB},
650 	{0x2418, 0x403A},
651 	{0x241A, 0x0292},
652 	{0x241C, 0x4AA2},
653 	{0x241E, 0x0A00},
654 	{0x2420, 0xB2E2},
655 	{0x2422, 0x0361},
656 	{0x2424, 0x2405},
657 	{0x2426, 0x4A2F},
658 	{0x2428, 0x1292},
659 	{0x242A, 0x8474},
660 	{0x242C, 0x4F82},
661 	{0x242E, 0x0A1C},
662 	{0x2430, 0x93C2},
663 	{0x2432, 0x0360},
664 	{0x2434, 0x34CD},
665 	{0x2436, 0x430C},
666 	{0x2438, 0x4C0F},
667 	{0x243A, 0x5F0F},
668 	{0x243C, 0x4F0D},
669 	{0x243E, 0x510D},
670 	{0x2440, 0x4F0E},
671 	{0x2442, 0x5A0E},
672 	{0x2444, 0x4E1E},
673 	{0x2446, 0x0002},
674 	{0x2448, 0x4F1F},
675 	{0x244A, 0x192A},
676 	{0x244C, 0x1202},
677 	{0x244E, 0xC232},
678 	{0x2450, 0x4303},
679 	{0x2452, 0x4E82},
680 	{0x2454, 0x0130},
681 	{0x2456, 0x4F82},
682 	{0x2458, 0x0138},
683 	{0x245A, 0x421E},
684 	{0x245C, 0x013A},
685 	{0x245E, 0x421F},
686 	{0x2460, 0x013C},
687 	{0x2462, 0x4132},
688 	{0x2464, 0x108E},
689 	{0x2466, 0x108F},
690 	{0x2468, 0xEF4E},
691 	{0x246A, 0xEF0E},
692 	{0x246C, 0xF37F},
693 	{0x246E, 0xC312},
694 	{0x2470, 0x100F},
695 	{0x2472, 0x100E},
696 	{0x2474, 0x4E8D},
697 	{0x2476, 0x0000},
698 	{0x2478, 0x531C},
699 	{0x247A, 0x922C},
700 	{0x247C, 0x2BDD},
701 	{0x247E, 0xB3D2},
702 	{0x2480, 0x1921},
703 	{0x2482, 0x2403},
704 	{0x2484, 0x410F},
705 	{0x2486, 0x1292},
706 	{0x2488, 0x847E},
707 	{0x248A, 0x403B},
708 	{0x248C, 0x843E},
709 	{0x248E, 0x422D},
710 	{0x2490, 0x410E},
711 	{0x2492, 0x403F},
712 	{0x2494, 0x1908},
713 	{0x2496, 0x12AB},
714 	{0x2498, 0x403D},
715 	{0x249A, 0x0005},
716 	{0x249C, 0x403E},
717 	{0x249E, 0x0292},
718 	{0x24A0, 0x403F},
719 	{0x24A2, 0x86E4},
720 	{0x24A4, 0x12AB},
721 	{0x24A6, 0x421F},
722 	{0x24A8, 0x060E},
723 	{0x24AA, 0x9F82},
724 	{0x24AC, 0x8720},
725 	{0x24AE, 0x288D},
726 	{0x24B0, 0x9382},
727 	{0x24B2, 0x060E},
728 	{0x24B4, 0x248A},
729 	{0x24B6, 0x90BA},
730 	{0x24B8, 0x0010},
731 	{0x24BA, 0x0000},
732 	{0x24BC, 0x2C0B},
733 	{0x24BE, 0x93C2},
734 	{0x24C0, 0x86EE},
735 	{0x24C2, 0x2008},
736 	{0x24C4, 0x403F},
737 	{0x24C6, 0x06A7},
738 	{0x24C8, 0xD0FF},
739 	{0x24CA, 0x0007},
740 	{0x24CC, 0x0000},
741 	{0x24CE, 0xF0FF},
742 	{0x24D0, 0xFFF8},
743 	{0x24D2, 0x0000},
744 	{0x24D4, 0x4392},
745 	{0x24D6, 0x8720},
746 	{0x24D8, 0x403F},
747 	{0x24DA, 0x06A7},
748 	{0x24DC, 0xD2EF},
749 	{0x24DE, 0x0000},
750 	{0x24E0, 0xC2EF},
751 	{0x24E2, 0x0000},
752 	{0x24E4, 0x93C2},
753 	{0x24E6, 0x87D3},
754 	{0x24E8, 0x2068},
755 	{0x24EA, 0xB0F2},
756 	{0x24EC, 0x0040},
757 	{0x24EE, 0x0B05},
758 	{0x24F0, 0x2461},
759 	{0x24F2, 0xD3D2},
760 	{0x24F4, 0x0410},
761 	{0x24F6, 0xB3E2},
762 	{0x24F8, 0x0381},
763 	{0x24FA, 0x2089},
764 	{0x24FC, 0x90B2},
765 	{0x24FE, 0x0030},
766 	{0x2500, 0x0A00},
767 	{0x2502, 0x2C52},
768 	{0x2504, 0x93C2},
769 	{0x2506, 0x86EE},
770 	{0x2508, 0x204F},
771 	{0x250A, 0x430E},
772 	{0x250C, 0x430C},
773 	{0x250E, 0x4C0F},
774 	{0x2510, 0x5F0F},
775 	{0x2512, 0x5F0F},
776 	{0x2514, 0x5F0F},
777 	{0x2516, 0x4F1F},
778 	{0x2518, 0x8668},
779 	{0x251A, 0xF03F},
780 	{0x251C, 0x07FF},
781 	{0x251E, 0x903F},
782 	{0x2520, 0x0400},
783 	{0x2522, 0x343E},
784 	{0x2524, 0x5F0E},
785 	{0x2526, 0x531C},
786 	{0x2528, 0x923C},
787 	{0x252A, 0x2BF1},
788 	{0x252C, 0x4E0F},
789 	{0x252E, 0x930E},
790 	{0x2530, 0x3834},
791 	{0x2532, 0x110F},
792 	{0x2534, 0x110F},
793 	{0x2536, 0x110F},
794 	{0x2538, 0x9382},
795 	{0x253A, 0x86EE},
796 	{0x253C, 0x2023},
797 	{0x253E, 0x5F82},
798 	{0x2540, 0x87D6},
799 	{0x2542, 0x403B},
800 	{0x2544, 0x87D6},
801 	{0x2546, 0x4B2F},
802 	{0x2548, 0x12B0},
803 	{0x254A, 0xB624},
804 	{0x254C, 0x4F8B},
805 	{0x254E, 0x0000},
806 	{0x2550, 0x430C},
807 	{0x2552, 0x4C0D},
808 	{0x2554, 0x5D0D},
809 	{0x2556, 0x5D0D},
810 	{0x2558, 0x5D0D},
811 	{0x255A, 0x403A},
812 	{0x255C, 0x87D8},
813 	{0x255E, 0x421B},
814 	{0x2560, 0x87D6},
815 	{0x2562, 0x4B0F},
816 	{0x2564, 0x8A2F},
817 	{0x2566, 0x4F0E},
818 	{0x2568, 0x4E0F},
819 	{0x256A, 0x5F0F},
820 	{0x256C, 0x7F0F},
821 	{0x256E, 0xE33F},
822 	{0x2570, 0x8E8D},
823 	{0x2572, 0x8668},
824 	{0x2574, 0x7F8D},
825 	{0x2576, 0x866A},
826 	{0x2578, 0x531C},
827 	{0x257A, 0x923C},
828 	{0x257C, 0x2BEA},
829 	{0x257E, 0x4B8A},
830 	{0x2580, 0x0000},
831 	{0x2582, 0x3C45},
832 	{0x2584, 0x9382},
833 	{0x2586, 0x86F0},
834 	{0x2588, 0x2005},
835 	{0x258A, 0x4382},
836 	{0x258C, 0x87D6},
837 	{0x258E, 0x4382},
838 	{0x2590, 0x87D8},
839 	{0x2592, 0x3FD7},
840 	{0x2594, 0x4F82},
841 	{0x2596, 0x87D6},
842 	{0x2598, 0x3FD4},
843 	{0x259A, 0x503F},
844 	{0x259C, 0x0007},
845 	{0x259E, 0x3FC9},
846 	{0x25A0, 0x5F0E},
847 	{0x25A2, 0x503E},
848 	{0x25A4, 0xF800},
849 	{0x25A6, 0x3FBF},
850 	{0x25A8, 0x430F},
851 	{0x25AA, 0x12B0},
852 	{0x25AC, 0xB624},
853 	{0x25AE, 0x4382},
854 	{0x25B0, 0x87D6},
855 	{0x25B2, 0x3C2D},
856 	{0x25B4, 0xC3D2},
857 	{0x25B6, 0x0410},
858 	{0x25B8, 0x3F9E},
859 	{0x25BA, 0x430D},
860 	{0x25BC, 0x403E},
861 	{0x25BE, 0x0050},
862 	{0x25C0, 0x403F},
863 	{0x25C2, 0x85C8},
864 	{0x25C4, 0x1292},
865 	{0x25C6, 0x844E},
866 	{0x25C8, 0x3F90},
867 	{0x25CA, 0x5392},
868 	{0x25CC, 0x8720},
869 	{0x25CE, 0x3F84},
870 	{0x25D0, 0x403B},
871 	{0x25D2, 0x843E},
872 	{0x25D4, 0x4A0F},
873 	{0x25D6, 0x532F},
874 	{0x25D8, 0x422D},
875 	{0x25DA, 0x4F0E},
876 	{0x25DC, 0x403F},
877 	{0x25DE, 0x0E08},
878 	{0x25E0, 0x12AB},
879 	{0x25E2, 0x422D},
880 	{0x25E4, 0x403E},
881 	{0x25E6, 0x192A},
882 	{0x25E8, 0x410F},
883 	{0x25EA, 0x12AB},
884 	{0x25EC, 0x3F48},
885 	{0x25EE, 0x93C2},
886 	{0x25F0, 0x86EE},
887 	{0x25F2, 0x2312},
888 	{0x25F4, 0x403A},
889 	{0x25F6, 0x86E4},
890 	{0x25F8, 0x3F11},
891 	{0x25FA, 0x403D},
892 	{0x25FC, 0x0200},
893 	{0x25FE, 0x422E},
894 	{0x2600, 0x403F},
895 	{0x2602, 0x192A},
896 	{0x2604, 0x1292},
897 	{0x2606, 0x844E},
898 	{0x2608, 0xC3D2},
899 	{0x260A, 0x1921},
900 	{0x260C, 0x3F02},
901 	{0x260E, 0x422D},
902 	{0x2610, 0x403E},
903 	{0x2612, 0x888E},
904 	{0x2614, 0x403F},
905 	{0x2616, 0x192A},
906 	{0x2618, 0x1292},
907 	{0x261A, 0x843E},
908 	{0x261C, 0x5231},
909 	{0x261E, 0x413A},
910 	{0x2620, 0x413B},
911 	{0x2622, 0x4130},
912 	{0x2624, 0x4382},
913 	{0x2626, 0x052C},
914 	{0x2628, 0x4F0D},
915 	{0x262A, 0x930D},
916 	{0x262C, 0x3402},
917 	{0x262E, 0xE33D},
918 	{0x2630, 0x531D},
919 	{0x2632, 0xF03D},
920 	{0x2634, 0x07F0},
921 	{0x2636, 0x4D0E},
922 	{0x2638, 0xC312},
923 	{0x263A, 0x100E},
924 	{0x263C, 0x110E},
925 	{0x263E, 0x110E},
926 	{0x2640, 0x110E},
927 	{0x2642, 0x930F},
928 	{0x2644, 0x3803},
929 	{0x2646, 0x4EC2},
930 	{0x2648, 0x052C},
931 	{0x264A, 0x3C04},
932 	{0x264C, 0x4EC2},
933 	{0x264E, 0x052D},
934 	{0x2650, 0xE33D},
935 	{0x2652, 0x531D},
936 	{0x2654, 0x4D0F},
937 	{0x2656, 0x4130},
938 	{0x2658, 0x1292},
939 	{0x265A, 0xD048},
940 	{0x265C, 0x93C2},
941 	{0x265E, 0x86EE},
942 	{0x2660, 0x200D},
943 	{0x2662, 0xB0F2},
944 	{0x2664, 0x0020},
945 	{0x2666, 0x0381},
946 	{0x2668, 0x2407},
947 	{0x266A, 0x9292},
948 	{0x266C, 0x8722},
949 	{0x266E, 0x0384},
950 	{0x2670, 0x2C03},
951 	{0x2672, 0xD3D2},
952 	{0x2674, 0x0649},
953 	{0x2676, 0x4130},
954 	{0x2678, 0xC3D2},
955 	{0x267A, 0x0649},
956 	{0x267C, 0x4130},
957 	{0x267E, 0x120B},
958 	{0x2680, 0x120A},
959 	{0x2682, 0x1209},
960 	{0x2684, 0x1208},
961 	{0x2686, 0x1207},
962 	{0x2688, 0x1206},
963 	{0x268A, 0x1205},
964 	{0x268C, 0x1204},
965 	{0x268E, 0x8231},
966 	{0x2690, 0x4F81},
967 	{0x2692, 0x0000},
968 	{0x2694, 0x4381},
969 	{0x2696, 0x0002},
970 	{0x2698, 0x4304},
971 	{0x269A, 0x411C},
972 	{0x269C, 0x0002},
973 	{0x269E, 0x5C0C},
974 	{0x26A0, 0x4C0F},
975 	{0x26A2, 0x5F0F},
976 	{0x26A4, 0x5F0F},
977 	{0x26A6, 0x5F0F},
978 	{0x26A8, 0x5F0F},
979 	{0x26AA, 0x5F0F},
980 	{0x26AC, 0x503F},
981 	{0x26AE, 0x1980},
982 	{0x26B0, 0x440D},
983 	{0x26B2, 0x5D0D},
984 	{0x26B4, 0x4D0E},
985 	{0x26B6, 0x5F0E},
986 	{0x26B8, 0x4E2E},
987 	{0x26BA, 0x4D05},
988 	{0x26BC, 0x5505},
989 	{0x26BE, 0x5F05},
990 	{0x26C0, 0x4516},
991 	{0x26C2, 0x0008},
992 	{0x26C4, 0x4517},
993 	{0x26C6, 0x000A},
994 	{0x26C8, 0x460A},
995 	{0x26CA, 0x470B},
996 	{0x26CC, 0xF30A},
997 	{0x26CE, 0xF32B},
998 	{0x26D0, 0x4A81},
999 	{0x26D2, 0x0004},
1000 	{0x26D4, 0x4B81},
1001 	{0x26D6, 0x0006},
1002 	{0x26D8, 0xB03E},
1003 	{0x26DA, 0x2000},
1004 	{0x26DC, 0x2404},
1005 	{0x26DE, 0xF03E},
1006 	{0x26E0, 0x1FFF},
1007 	{0x26E2, 0xE33E},
1008 	{0x26E4, 0x531E},
1009 	{0x26E6, 0xF317},
1010 	{0x26E8, 0x503E},
1011 	{0x26EA, 0x2000},
1012 	{0x26EC, 0x4E0F},
1013 	{0x26EE, 0x5F0F},
1014 	{0x26F0, 0x7F0F},
1015 	{0x26F2, 0xE33F},
1016 	{0x26F4, 0x512C},
1017 	{0x26F6, 0x4C28},
1018 	{0x26F8, 0x4309},
1019 	{0x26FA, 0x4E0A},
1020 	{0x26FC, 0x4F0B},
1021 	{0x26FE, 0x480C},
1022 	{0x2700, 0x490D},
1023 	{0x2702, 0x1202},
1024 	{0x2704, 0xC232},
1025 	{0x2706, 0x12B0},
1026 	{0x2708, 0xFFC0},
1027 	{0x270A, 0x4132},
1028 	{0x270C, 0x108E},
1029 	{0x270E, 0x108F},
1030 	{0x2710, 0xEF4E},
1031 	{0x2712, 0xEF0E},
1032 	{0x2714, 0xF37F},
1033 	{0x2716, 0xC312},
1034 	{0x2718, 0x100F},
1035 	{0x271A, 0x100E},
1036 	{0x271C, 0x4E85},
1037 	{0x271E, 0x0018},
1038 	{0x2720, 0x4F85},
1039 	{0x2722, 0x001A},
1040 	{0x2724, 0x480A},
1041 	{0x2726, 0x490B},
1042 	{0x2728, 0x460C},
1043 	{0x272A, 0x470D},
1044 	{0x272C, 0x1202},
1045 	{0x272E, 0xC232},
1046 	{0x2730, 0x12B0},
1047 	{0x2732, 0xFFC0},
1048 	{0x2734, 0x4132},
1049 	{0x2736, 0x4E0C},
1050 	{0x2738, 0x4F0D},
1051 	{0x273A, 0x108C},
1052 	{0x273C, 0x108D},
1053 	{0x273E, 0xED4C},
1054 	{0x2740, 0xED0C},
1055 	{0x2742, 0xF37D},
1056 	{0x2744, 0xC312},
1057 	{0x2746, 0x100D},
1058 	{0x2748, 0x100C},
1059 	{0x274A, 0x411E},
1060 	{0x274C, 0x0004},
1061 	{0x274E, 0x411F},
1062 	{0x2750, 0x0006},
1063 	{0x2752, 0x5E0E},
1064 	{0x2754, 0x6F0F},
1065 	{0x2756, 0x5E0E},
1066 	{0x2758, 0x6F0F},
1067 	{0x275A, 0x5E0E},
1068 	{0x275C, 0x6F0F},
1069 	{0x275E, 0xDE0C},
1070 	{0x2760, 0xDF0D},
1071 	{0x2762, 0x4C85},
1072 	{0x2764, 0x002C},
1073 	{0x2766, 0x4D85},
1074 	{0x2768, 0x002E},
1075 	{0x276A, 0x5314},
1076 	{0x276C, 0x9224},
1077 	{0x276E, 0x2B95},
1078 	{0x2770, 0x5391},
1079 	{0x2772, 0x0002},
1080 	{0x2774, 0x92A1},
1081 	{0x2776, 0x0002},
1082 	{0x2778, 0x2B8F},
1083 	{0x277A, 0x5231},
1084 	{0x277C, 0x4134},
1085 	{0x277E, 0x4135},
1086 	{0x2780, 0x4136},
1087 	{0x2782, 0x4137},
1088 	{0x2784, 0x4138},
1089 	{0x2786, 0x4139},
1090 	{0x2788, 0x413A},
1091 	{0x278A, 0x413B},
1092 	{0x278C, 0x4130},
1093 	{0x278E, 0x120B},
1094 	{0x2790, 0x120A},
1095 	{0x2792, 0x1209},
1096 	{0x2794, 0x8031},
1097 	{0x2796, 0x000C},
1098 	{0x2798, 0x425F},
1099 	{0x279A, 0x0205},
1100 	{0x279C, 0xC312},
1101 	{0x279E, 0x104F},
1102 	{0x27A0, 0x114F},
1103 	{0x27A2, 0x114F},
1104 	{0x27A4, 0x114F},
1105 	{0x27A6, 0x114F},
1106 	{0x27A8, 0x114F},
1107 	{0x27AA, 0xF37F},
1108 	{0x27AC, 0x4F0B},
1109 	{0x27AE, 0xF31B},
1110 	{0x27B0, 0x5B0B},
1111 	{0x27B2, 0x5B0B},
1112 	{0x27B4, 0x5B0B},
1113 	{0x27B6, 0x503B},
1114 	{0x27B8, 0xD194},
1115 	{0x27BA, 0x4219},
1116 	{0x27BC, 0x0508},
1117 	{0x27BE, 0xF039},
1118 	{0x27C0, 0x2000},
1119 	{0x27C2, 0x4F0A},
1120 	{0x27C4, 0xC312},
1121 	{0x27C6, 0x100A},
1122 	{0x27C8, 0xE31A},
1123 	{0x27CA, 0x421F},
1124 	{0x27CC, 0x87DE},
1125 	{0x27CE, 0x503F},
1126 	{0x27D0, 0xFF60},
1127 	{0x27D2, 0x903F},
1128 	{0x27D4, 0x00C8},
1129 	{0x27D6, 0x2C02},
1130 	{0x27D8, 0x403F},
1131 	{0x27DA, 0x00C8},
1132 	{0x27DC, 0x4F82},
1133 	{0x27DE, 0x7322},
1134 	{0x27E0, 0xB3D2},
1135 	{0x27E2, 0x0381},
1136 	{0x27E4, 0x2009},
1137 	{0x27E6, 0x421F},
1138 	{0x27E8, 0x86F0},
1139 	{0x27EA, 0xD21F},
1140 	{0x27EC, 0x86EE},
1141 	{0x27EE, 0x930F},
1142 	{0x27F0, 0x24B9},
1143 	{0x27F2, 0x40F2},
1144 	{0x27F4, 0xFF80},
1145 	{0x27F6, 0x0619},
1146 	{0x27F8, 0x1292},
1147 	{0x27FA, 0xD00A},
1148 	{0x27FC, 0xB3D2},
1149 	{0x27FE, 0x0385},
1150 	{0x2800, 0x2405},
1151 	{0x2802, 0x421F},
1152 	{0x2804, 0x880A},
1153 	{0x2806, 0x4F92},
1154 	{0x2808, 0x0002},
1155 	{0x280A, 0x8714},
1156 	{0x280C, 0x430D},
1157 	{0x280E, 0x93C2},
1158 	{0x2810, 0x87D0},
1159 	{0x2812, 0x2003},
1160 	{0x2814, 0xB2F2},
1161 	{0x2816, 0x0360},
1162 	{0x2818, 0x2001},
1163 	{0x281A, 0x431D},
1164 	{0x281C, 0x425F},
1165 	{0x281E, 0x87D3},
1166 	{0x2820, 0xD25F},
1167 	{0x2822, 0x87D2},
1168 	{0x2824, 0xF37F},
1169 	{0x2826, 0x5F0F},
1170 	{0x2828, 0x425E},
1171 	{0x282A, 0x87CD},
1172 	{0x282C, 0xDE0F},
1173 	{0x282E, 0x5F0F},
1174 	{0x2830, 0x5B0F},
1175 	{0x2832, 0x4FA2},
1176 	{0x2834, 0x0402},
1177 	{0x2836, 0x930D},
1178 	{0x2838, 0x2007},
1179 	{0x283A, 0x930A},
1180 	{0x283C, 0x248E},
1181 	{0x283E, 0x4F5F},
1182 	{0x2840, 0x0001},
1183 	{0x2842, 0xF37F},
1184 	{0x2844, 0x4FC2},
1185 	{0x2846, 0x0403},
1186 	{0x2848, 0x93C2},
1187 	{0x284A, 0x87CD},
1188 	{0x284C, 0x2483},
1189 	{0x284E, 0xC2F2},
1190 	{0x2850, 0x0400},
1191 	{0x2852, 0xB2E2},
1192 	{0x2854, 0x0265},
1193 	{0x2856, 0x2407},
1194 	{0x2858, 0x421F},
1195 	{0x285A, 0x0508},
1196 	{0x285C, 0xF03F},
1197 	{0x285E, 0xFFDF},
1198 	{0x2860, 0xD90F},
1199 	{0x2862, 0x4F82},
1200 	{0x2864, 0x0508},
1201 	{0x2866, 0xB3D2},
1202 	{0x2868, 0x0383},
1203 	{0x286A, 0x2484},
1204 	{0x286C, 0x403F},
1205 	{0x286E, 0x0508},
1206 	{0x2870, 0x4FB1},
1207 	{0x2872, 0x0000},
1208 	{0x2874, 0x4FB1},
1209 	{0x2876, 0x0002},
1210 	{0x2878, 0x4FB1},
1211 	{0x287A, 0x0004},
1212 	{0x287C, 0x403F},
1213 	{0x287E, 0x0500},
1214 	{0x2880, 0x4FB1},
1215 	{0x2882, 0x0006},
1216 	{0x2884, 0x4FB1},
1217 	{0x2886, 0x0008},
1218 	{0x2888, 0x4FB1},
1219 	{0x288A, 0x000A},
1220 	{0x288C, 0xB3E2},
1221 	{0x288E, 0x0383},
1222 	{0x2890, 0x2412},
1223 	{0x2892, 0xC2E1},
1224 	{0x2894, 0x0002},
1225 	{0x2896, 0xB2E2},
1226 	{0x2898, 0x0383},
1227 	{0x289A, 0x434F},
1228 	{0x289C, 0x634F},
1229 	{0x289E, 0xF37F},
1230 	{0x28A0, 0x4F4E},
1231 	{0x28A2, 0x114E},
1232 	{0x28A4, 0x434E},
1233 	{0x28A6, 0x104E},
1234 	{0x28A8, 0x415F},
1235 	{0x28AA, 0x0007},
1236 	{0x28AC, 0xF07F},
1237 	{0x28AE, 0x007F},
1238 	{0x28B0, 0xDE4F},
1239 	{0x28B2, 0x4FC1},
1240 	{0x28B4, 0x0007},
1241 	{0x28B6, 0xB2F2},
1242 	{0x28B8, 0x0383},
1243 	{0x28BA, 0x2415},
1244 	{0x28BC, 0xF0F1},
1245 	{0x28BE, 0xFFBF},
1246 	{0x28C0, 0x0000},
1247 	{0x28C2, 0xB0F2},
1248 	{0x28C4, 0x0010},
1249 	{0x28C6, 0x0383},
1250 	{0x28C8, 0x434E},
1251 	{0x28CA, 0x634E},
1252 	{0x28CC, 0x5E4E},
1253 	{0x28CE, 0x5E4E},
1254 	{0x28D0, 0x5E4E},
1255 	{0x28D2, 0x5E4E},
1256 	{0x28D4, 0x5E4E},
1257 	{0x28D6, 0x5E4E},
1258 	{0x28D8, 0x415F},
1259 	{0x28DA, 0x0006},
1260 	{0x28DC, 0xF07F},
1261 	{0x28DE, 0xFFBF},
1262 	{0x28E0, 0xDE4F},
1263 	{0x28E2, 0x4FC1},
1264 	{0x28E4, 0x0006},
1265 	{0x28E6, 0xB0F2},
1266 	{0x28E8, 0x0020},
1267 	{0x28EA, 0x0383},
1268 	{0x28EC, 0x2410},
1269 	{0x28EE, 0xF0F1},
1270 	{0x28F0, 0xFFDF},
1271 	{0x28F2, 0x0002},
1272 	{0x28F4, 0xB0F2},
1273 	{0x28F6, 0x0040},
1274 	{0x28F8, 0x0383},
1275 	{0x28FA, 0x434E},
1276 	{0x28FC, 0x634E},
1277 	{0x28FE, 0x5E4E},
1278 	{0x2900, 0x5E4E},
1279 	{0x2902, 0x415F},
1280 	{0x2904, 0x0008},
1281 	{0x2906, 0xC26F},
1282 	{0x2908, 0xDE4F},
1283 	{0x290A, 0x4FC1},
1284 	{0x290C, 0x0008},
1285 	{0x290E, 0x93C2},
1286 	{0x2910, 0x0383},
1287 	{0x2912, 0x3412},
1288 	{0x2914, 0xF0F1},
1289 	{0x2916, 0xFFDF},
1290 	{0x2918, 0x0000},
1291 	{0x291A, 0x425E},
1292 	{0x291C, 0x0382},
1293 	{0x291E, 0xF35E},
1294 	{0x2920, 0x5E4E},
1295 	{0x2922, 0x5E4E},
1296 	{0x2924, 0x5E4E},
1297 	{0x2926, 0x5E4E},
1298 	{0x2928, 0x5E4E},
1299 	{0x292A, 0x415F},
1300 	{0x292C, 0x0006},
1301 	{0x292E, 0xF07F},
1302 	{0x2930, 0xFFDF},
1303 	{0x2932, 0xDE4F},
1304 	{0x2934, 0x4FC1},
1305 	{0x2936, 0x0006},
1306 	{0x2938, 0x410F},
1307 	{0x293A, 0x4FB2},
1308 	{0x293C, 0x0508},
1309 	{0x293E, 0x4FB2},
1310 	{0x2940, 0x050A},
1311 	{0x2942, 0x4FB2},
1312 	{0x2944, 0x050C},
1313 	{0x2946, 0x4FB2},
1314 	{0x2948, 0x0500},
1315 	{0x294A, 0x4FB2},
1316 	{0x294C, 0x0502},
1317 	{0x294E, 0x4FB2},
1318 	{0x2950, 0x0504},
1319 	{0x2952, 0x3C10},
1320 	{0x2954, 0xD2F2},
1321 	{0x2956, 0x0400},
1322 	{0x2958, 0x3F7C},
1323 	{0x295A, 0x4F6F},
1324 	{0x295C, 0xF37F},
1325 	{0x295E, 0x4FC2},
1326 	{0x2960, 0x0402},
1327 	{0x2962, 0x3F72},
1328 	{0x2964, 0x90F2},
1329 	{0x2966, 0x0011},
1330 	{0x2968, 0x0619},
1331 	{0x296A, 0x2B46},
1332 	{0x296C, 0x50F2},
1333 	{0x296E, 0xFFF0},
1334 	{0x2970, 0x0619},
1335 	{0x2972, 0x3F42},
1336 	{0x2974, 0x5031},
1337 	{0x2976, 0x000C},
1338 	{0x2978, 0x4139},
1339 	{0x297A, 0x413A},
1340 	{0x297C, 0x413B},
1341 	{0x297E, 0x4130},
1342 	{0x2980, 0x0900},
1343 	{0x2982, 0x7312},
1344 	{0x2984, 0x421F},
1345 	{0x2986, 0x0A08},
1346 	{0x2988, 0xF03F},
1347 	{0x298A, 0xF7FF},
1348 	{0x298C, 0x4F82},
1349 	{0x298E, 0x0A88},
1350 	{0x2990, 0x0900},
1351 	{0x2992, 0x7312},
1352 	{0x2994, 0x421F},
1353 	{0x2996, 0x0A0E},
1354 	{0x2998, 0xF03F},
1355 	{0x299A, 0x7FFF},
1356 	{0x299C, 0x4F82},
1357 	{0x299E, 0x0A8E},
1358 	{0x29A0, 0x0900},
1359 	{0x29A2, 0x7312},
1360 	{0x29A4, 0x421F},
1361 	{0x29A6, 0x0A1E},
1362 	{0x29A8, 0xC31F},
1363 	{0x29AA, 0x4F82},
1364 	{0x29AC, 0x0A9E},
1365 	{0x29AE, 0x4130},
1366 	{0x29B0, 0x4292},
1367 	{0x29B2, 0x0A08},
1368 	{0x29B4, 0x0A88},
1369 	{0x29B6, 0x0900},
1370 	{0x29B8, 0x7312},
1371 	{0x29BA, 0x4292},
1372 	{0x29BC, 0x0A0E},
1373 	{0x29BE, 0x0A8E},
1374 	{0x29C0, 0x0900},
1375 	{0x29C2, 0x7312},
1376 	{0x29C4, 0x4292},
1377 	{0x29C6, 0x0A1E},
1378 	{0x29C8, 0x0A9E},
1379 	{0x29CA, 0x4130},
1380 	{0x29CC, 0x7400},
1381 	{0x29CE, 0x8058},
1382 	{0x29D0, 0x1807},
1383 	{0x29D2, 0x00E0},
1384 	{0x29D4, 0x7002},
1385 	{0x29D6, 0x17C7},
1386 	{0x29D8, 0x0045},
1387 	{0x29DA, 0x0006},
1388 	{0x29DC, 0x17CC},
1389 	{0x29DE, 0x0015},
1390 	{0x29E0, 0x1512},
1391 	{0x29E2, 0x216F},
1392 	{0x29E4, 0x005B},
1393 	{0x29E6, 0x005D},
1394 	{0x29E8, 0x00DE},
1395 	{0x29EA, 0x00DD},
1396 	{0x29EC, 0x5023},
1397 	{0x29EE, 0x00DE},
1398 	{0x29F0, 0x005B},
1399 	{0x29F2, 0x0410},
1400 	{0x29F4, 0x0091},
1401 	{0x29F6, 0x0015},
1402 	{0x29F8, 0x0040},
1403 	{0x29FA, 0x7023},
1404 	{0x29FC, 0x1653},
1405 	{0x29FE, 0x0156},
1406 	{0x2A00, 0x0001},
1407 	{0x2A02, 0x2081},
1408 	{0x2A04, 0x7020},
1409 	{0x2A06, 0x2F99},
1410 	{0x2A08, 0x005C},
1411 	{0x2A0A, 0x0000},
1412 	{0x2A0C, 0x5040},
1413 	{0x2A0E, 0x0045},
1414 	{0x2A10, 0x213A},
1415 	{0x2A12, 0x0303},
1416 	{0x2A14, 0x0148},
1417 	{0x2A16, 0x0049},
1418 	{0x2A18, 0x0045},
1419 	{0x2A1A, 0x0046},
1420 	{0x2A1C, 0x05DD},
1421 	{0x2A1E, 0x00DE},
1422 	{0x2A20, 0x00DD},
1423 	{0x2A22, 0x00DC},
1424 	{0x2A24, 0x00DE},
1425 	{0x2A26, 0x04D6},
1426 	{0x2A28, 0x2014},
1427 	{0x2A2A, 0x2081},
1428 	{0x2A2C, 0x7087},
1429 	{0x2A2E, 0x2F99},
1430 	{0x2A30, 0x005C},
1431 	{0x2A32, 0x0002},
1432 	{0x2A34, 0x5060},
1433 	{0x2A36, 0x31C0},
1434 	{0x2A38, 0x2122},
1435 	{0x2A3A, 0x7800},
1436 	{0x2A3C, 0xC08C},
1437 	{0x2A3E, 0x0001},
1438 	{0x2A40, 0x9038},
1439 	{0x2A42, 0x59F7},
1440 	{0x2A44, 0x907A},
1441 	{0x2A46, 0x03D8},
1442 	{0x2A48, 0x8D90},
1443 	{0x2A4A, 0x01C0},
1444 	{0x2A4C, 0x7400},
1445 	{0x2A4E, 0x8058},
1446 	{0x2A50, 0x1807},
1447 	{0x2A52, 0x00E0},
1448 	{0x2A54, 0x7002},
1449 	{0x2A56, 0x17C7},
1450 	{0x2A58, 0x0045},
1451 	{0x2A5A, 0x0006},
1452 	{0x2A5C, 0x17CC},
1453 	{0x2A5E, 0x0015},
1454 	{0x2A60, 0x1512},
1455 	{0x2A62, 0x216F},
1456 	{0x2A64, 0x005B},
1457 	{0x2A66, 0x005D},
1458 	{0x2A68, 0x00DE},
1459 	{0x2A6A, 0x00DD},
1460 	{0x2A6C, 0x5023},
1461 	{0x2A6E, 0x00DE},
1462 	{0x2A70, 0x005B},
1463 	{0x2A72, 0x0410},
1464 	{0x2A74, 0x0091},
1465 	{0x2A76, 0x0015},
1466 	{0x2A78, 0x0040},
1467 	{0x2A7A, 0x7023},
1468 	{0x2A7C, 0x1653},
1469 	{0x2A7E, 0x0156},
1470 	{0x2A80, 0x0001},
1471 	{0x2A82, 0x2081},
1472 	{0x2A84, 0x7020},
1473 	{0x2A86, 0x2F99},
1474 	{0x2A88, 0x005C},
1475 	{0x2A8A, 0x0000},
1476 	{0x2A8C, 0x5040},
1477 	{0x2A8E, 0x0045},
1478 	{0x2A90, 0x213A},
1479 	{0x2A92, 0x0303},
1480 	{0x2A94, 0x0148},
1481 	{0x2A96, 0x0049},
1482 	{0x2A98, 0x0045},
1483 	{0x2A9A, 0x0046},
1484 	{0x2A9C, 0x05DD},
1485 	{0x2A9E, 0x00DE},
1486 	{0x2AA0, 0x00DD},
1487 	{0x2AA2, 0x00DC},
1488 	{0x2AA4, 0x00DE},
1489 	{0x2AA6, 0x0296},
1490 	{0x2AA8, 0x2014},
1491 	{0x2AAA, 0x2081},
1492 	{0x2AAC, 0x7087},
1493 	{0x2AAE, 0x2F99},
1494 	{0x2AB0, 0x005C},
1495 	{0x2AB2, 0x0002},
1496 	{0x2AB4, 0x5060},
1497 	{0x2AB6, 0x31C0},
1498 	{0x2AB8, 0x2122},
1499 	{0x2ABA, 0x7800},
1500 	{0x2ABC, 0xC08C},
1501 	{0x2ABE, 0x0001},
1502 	{0x2AC0, 0x9038},
1503 	{0x2AC2, 0x59F7},
1504 	{0x2AC4, 0x907A},
1505 	{0x2AC6, 0x03D8},
1506 	{0x2AC8, 0x8D90},
1507 	{0x2ACA, 0x01C0},
1508 	{0x2ACC, 0x7400},
1509 	{0x2ACE, 0x2002},
1510 	{0x2AD0, 0x70DF},
1511 	{0x2AD2, 0x2F21},
1512 	{0x2AD4, 0x04C1},
1513 	{0x2AD6, 0x0D80},
1514 	{0x2AD8, 0x7800},
1515 	{0x2ADA, 0x0041},
1516 	{0x2ADC, 0x7400},
1517 	{0x2ADE, 0x2004},
1518 	{0x2AE0, 0x70DF},
1519 	{0x2AE2, 0x2F21},
1520 	{0x2AE4, 0x04C2},
1521 	{0x2AE6, 0x0D80},
1522 	{0x2AE8, 0x7800},
1523 	{0x2AEA, 0x7400},
1524 	{0x2AEC, 0x2008},
1525 	{0x2AEE, 0x70DF},
1526 	{0x2AF0, 0x2F21},
1527 	{0x2AF2, 0x04C3},
1528 	{0x2AF4, 0x0D80},
1529 	{0x2AF6, 0x7800},
1530 	{0x2AF8, 0x7400},
1531 	{0x2AFA, 0x0004},
1532 	{0x2AFC, 0x70DF},
1533 	{0x2AFE, 0x2F22},
1534 	{0x2B00, 0x7008},
1535 	{0x2B02, 0x2F1F},
1536 	{0x2B04, 0x7021},
1537 	{0x2B06, 0x2F01},
1538 	{0x2B08, 0x7800},
1539 	{0x2B0A, 0x7400},
1540 	{0x2B0C, 0x0002},
1541 	{0x2B0E, 0x70DF},
1542 	{0x2B10, 0x3F5F},
1543 	{0x2B12, 0x703A},
1544 	{0x2B14, 0x2F01},
1545 	{0x2B16, 0x7800},
1546 	{0x2B18, 0x7400},
1547 	{0x2B1A, 0x2010},
1548 	{0x2B1C, 0x70DF},
1549 	{0x2B1E, 0x3F40},
1550 	{0x2B20, 0x700A},
1551 	{0x2B22, 0x0FC0},
1552 	{0x2B24, 0x7800},
1553 	{0x2B26, 0x7400},
1554 	{0x2B28, 0x2004},
1555 	{0x2B2A, 0x70DF},
1556 	{0x2B2C, 0x2F21},
1557 	{0x2B2E, 0x04C2},
1558 	{0x2B30, 0x0D80},
1559 	{0x2B32, 0x7800},
1560 	{0x2B34, 0x0041},
1561 	{0x2B36, 0x7400},
1562 	{0x2B38, 0x2002},
1563 	{0x2B3A, 0x70DF},
1564 	{0x2B3C, 0x2F22},
1565 	{0x2B3E, 0x04C1},
1566 	{0x2B40, 0x0D80},
1567 	{0x2B42, 0x7800},
1568 	{0x2B44, 0x7400},
1569 	{0x2B46, 0x0001},
1570 	{0x2B48, 0x70DF},
1571 	{0x2B4A, 0x3F5F},
1572 	{0x2B4C, 0x703A},
1573 	{0x2B4E, 0x2F01},
1574 	{0x2B50, 0x7800},
1575 	{0x2B52, 0x7400},
1576 	{0x2B54, 0x200A},
1577 	{0x2B56, 0x70DF},
1578 	{0x2B58, 0x3F40},
1579 	{0x2B5A, 0x700A},
1580 	{0x2B5C, 0x0FC0},
1581 	{0x2B5E, 0x7800},
1582 	{0x2B60, 0x7400},
1583 	{0x2B62, 0x2015},
1584 	{0x2B64, 0x70DF},
1585 	{0x2B66, 0x3F5F},
1586 	{0x2B68, 0x703A},
1587 	{0x2B6A, 0x2F01},
1588 	{0x2B6C, 0x7800},
1589 	{0x2B6E, 0x7400},
1590 	{0x2B70, 0x7800},
1591 	{0x2B72, 0x007F},
1592 	{0x2B74, 0x0000},
1593 	{0x2B76, 0xB9CC},
1594 	{0x2B78, 0x0000},
1595 	{0x2B7A, 0xB9CC},
1596 	{0x2B7C, 0xBA3C},
1597 	{0x2B7E, 0x0002},
1598 	{0x2B80, 0x0000},
1599 	{0x2B82, 0xBA4C},
1600 	{0x2B84, 0x0000},
1601 	{0x2B86, 0xBA4C},
1602 	{0x2B88, 0xBABC},
1603 	{0x2B8A, 0x0002},
1604 	{0x2B8C, 0x0063},
1605 	{0x2B8E, 0xBB26},
1606 	{0x2B90, 0x0063},
1607 	{0x2B92, 0xBB36},
1608 	{0x2B94, 0x0063},
1609 	{0x2B96, 0xBAEA},
1610 	{0x2B98, 0x0063},
1611 	{0x2B9A, 0xBAF8},
1612 	{0x2B9C, 0xBADA},
1613 	{0x2B9E, 0x0004},
1614 	{0x2BA0, 0x0063},
1615 	{0x2BA2, 0xBAEA},
1616 	{0x2BA4, 0x0063},
1617 	{0x2BA6, 0xBB18},
1618 	{0x2BA8, 0x0063},
1619 	{0x2BAA, 0xBB26},
1620 	{0x2BAC, 0x0063},
1621 	{0x2BAE, 0xBB44},
1622 	{0x2BB0, 0xBADA},
1623 	{0x2BB2, 0x0004},
1624 	{0x2BB4, 0x0063},
1625 	{0x2BB6, 0xBACC},
1626 	{0x2BB8, 0x0063},
1627 	{0x2BBA, 0xBADC},
1628 	{0x2BBC, 0x0063},
1629 	{0x2BBE, 0xBAEA},
1630 	{0x2BC0, 0x0063},
1631 	{0x2BC2, 0xBAF8},
1632 	{0x2BC4, 0xBADA},
1633 	{0x2BC6, 0x0004},
1634 	{0x2BC8, 0x0063},
1635 	{0x2BCA, 0xBAEA},
1636 	{0x2BCC, 0x0063},
1637 	{0x2BCE, 0xBB18},
1638 	{0x2BD0, 0x0063},
1639 	{0x2BD2, 0xBACC},
1640 	{0x2BD4, 0x0063},
1641 	{0x2BD6, 0xBB0A},
1642 	{0x2BD8, 0xBADA},
1643 	{0x2BDA, 0x0004},
1644 	{0x2BDC, 0x0063},
1645 	{0x2BDE, 0xBACC},
1646 	{0x2BE0, 0x0063},
1647 	{0x2BE2, 0xBADC},
1648 	{0x2BE4, 0x0063},
1649 	{0x2BE6, 0xBAEA},
1650 	{0x2BE8, 0x0063},
1651 	{0x2BEA, 0xBB18},
1652 	{0x2BEC, 0xBADA},
1653 	{0x2BEE, 0x0004},
1654 	{0x2BF0, 0xFFFF},
1655 	{0x2BF2, 0xBB6E},
1656 	{0x2BF4, 0x0000},
1657 	{0x2BF6, 0x0000},
1658 	{0x2BF8, 0x0000},
1659 	{0x2BFA, 0x0000},
1660 	{0x2BFC, 0x0000},
1661 	{0x2BFE, 0x0000},
1662 	{0x2C00, 0xBB72},
1663 	{0x2C02, 0x0001},
1664 	{0x2C04, 0x0063},
1665 	{0x2C06, 0xBB52},
1666 	{0x2C08, 0x0063},
1667 	{0x2C0A, 0xBB60},
1668 	{0x2C0C, 0x0000},
1669 	{0x2C0E, 0x0000},
1670 	{0x2C10, 0x0000},
1671 	{0x2C12, 0x0000},
1672 	{0x2C14, 0xBADA},
1673 	{0x2C16, 0x0002},
1674 	{0x2C18, 0x0066},
1675 	{0x2C1A, 0x0067},
1676 	{0x2C1C, 0x00AF},
1677 	{0x2C1E, 0x01CF},
1678 	{0x2C20, 0x0087},
1679 	{0x2C22, 0x0083},
1680 	{0x2C24, 0x011B},
1681 	{0x2C26, 0x035A},
1682 	{0x2C28, 0x00FA},
1683 	{0x2C2A, 0x00F2},
1684 	{0x2C2C, 0x00A6},
1685 	{0x2C2E, 0x00A4},
1686 	{0x2C30, 0xFFFF},
1687 	{0x2C32, 0x002C},
1688 	{0x2C34, 0x0058},
1689 	{0x2C36, 0x0000},
1690 	{0x2C38, 0x0000},
1691 	{0x2C3A, 0xBC18},
1692 	{0x2C3C, 0xBB74},
1693 	{0x2C3E, 0xBB80},
1694 	{0x2C40, 0xBC32},
1695 	{0x2C42, 0xBB8C},
1696 	{0x2C44, 0xBBA0},
1697 	{0x2C46, 0xBB8C},
1698 	{0x2C48, 0xBBA0},
1699 	{0x2C4A, 0xBC04},
1700 	{0x2C4C, 0xBC04},
1701 	{0x2C4E, 0xBBF0},
1702 	{0x2C50, 0xBBF0},
1703 	{0x2C52, 0xBBB4},
1704 	{0x2C54, 0xBBC8},
1705 	{0x2C56, 0xBBB4},
1706 	{0x2C58, 0xBBC8},
1707 	{0x2C5A, 0xBC04},
1708 	{0x2C5C, 0xBC04},
1709 	{0x2C5E, 0xBBF0},
1710 	{0x2C60, 0xBBF0},
1711 	{0x2C62, 0xBB8C},
1712 	{0x2C64, 0xBBA0},
1713 	{0x2C66, 0xBB8C},
1714 	{0x2C68, 0xBBA0},
1715 	{0x2C6A, 0xBC04},
1716 	{0x2C6C, 0xBC04},
1717 	{0x2C6E, 0xBBF0},
1718 	{0x2C70, 0xBBF0},
1719 	{0x2C72, 0xBBB4},
1720 	{0x2C74, 0xBBC8},
1721 	{0x2C76, 0xBBB4},
1722 	{0x2C78, 0xBBC8},
1723 	{0x2C7A, 0xBC04},
1724 	{0x2C7C, 0xBC04},
1725 	{0x2C7E, 0xBBF0},
1726 	{0x2C80, 0xBBF0},
1727 	{0x3800, 0x880E},
1728 	{0x3802, 0xBC62},
1729 	{0x3804, 0xBC40},
1730 	{0x3806, 0xD13E},
1731 	{0x3808, 0xBC42},
1732 	{0x380A, 0xBC3C},
1733 	{0x380C, 0x0000},
1734 	{0x380E, 0x0040},
1735 	{0x3810, 0x0040},
1736 	{0x3812, 0x0040},
1737 	{0x3814, 0x0043},
1738 	{0x3816, 0x0046},
1739 	{0x3818, 0x004B},
1740 	{0x381A, 0x004D},
1741 	{0x381C, 0x0051},
1742 	{0x381E, 0x0055},
1743 	{0x3820, 0x005A},
1744 	{0x3822, 0x005E},
1745 	{0x3824, 0x0062},
1746 	{0x3826, 0x0067},
1747 	{0x3828, 0x006C},
1748 	{0x382A, 0x0070},
1749 	{0x382C, 0x0078},
1750 	{0x382E, 0x0086},
1751 	{0x3830, 0x0090},
1752 	{0x3832, 0x0096},
1753 	{0x3834, 0x009D},
1754 	{0x3836, 0x00A5},
1755 	{0x3838, 0x00AD},
1756 	{0x383A, 0x00B4},
1757 	{0x383C, 0x00B9},
1758 	{0x383E, 0x00BE},
1759 	{0x3840, 0x00C3},
1760 	{0x3842, 0x00C8},
1761 	{0x3844, 0x00CD},
1762 	{0x3846, 0x00D2},
1763 	{0x3848, 0x00D7},
1764 	{0x384A, 0x00DC},
1765 	{0x384C, 0x00DC},
1766 	{0x384E, 0x0000},
1767 	{0x3850, 0x0000},
1768 	{0x3852, 0x0000},
1769 	{0x3854, 0x0000},
1770 	{0x3856, 0x0000},
1771 	{0x3858, 0x0000},
1772 	{0x385A, 0x0000},
1773 	{0x385C, 0x0000},
1774 	{0x385E, 0x0000},
1775 	{0x3860, 0x0000},
1776 	{0x3862, 0x0000},
1777 	{0x3864, 0x0000},
1778 	{0x3866, 0x0000},
1779 	{0x3868, 0x0000},
1780 	{0x386A, 0x0000},
1781 	{0x386C, 0x0000},
1782 	{0x386E, 0x0000},
1783 	{0x3870, 0x0000},
1784 	{0x3872, 0x0000},
1785 	{0x3874, 0x0000},
1786 	{0x3876, 0x0000},
1787 	{0x3878, 0x0000},
1788 	{0x387A, 0x0000},
1789 	{0x387C, 0x0000},
1790 	{0x387E, 0x0000},
1791 	{0x3880, 0x0000},
1792 	{0x3882, 0x0000},
1793 	{0x3884, 0x0000},
1794 	{0x3886, 0x0000},
1795 	{0x3888, 0x0000},
1796 	{0x388A, 0x0000},
1797 	{0x388C, 0x0000},
1798 	{0x026A, 0xFFFF},
1799 	{0x026C, 0x00FF},
1800 	{0x026E, 0x0000},
1801 	{0x0360, 0x1E8E},
1802 	{0x040E, 0x01EB},
1803 	{0x0600, 0x1130},
1804 	{0x0602, 0x3112},
1805 	{0x0604, 0x8048},
1806 	{0x0606, 0x00E9},
1807 	{0x067A, 0x0404},
1808 	{0x067C, 0x0404},
1809 	{0x06A8, 0x0240},
1810 	{0x06AA, 0x00CA},
1811 	{0x06AC, 0x0041},
1812 	{0x06B4, 0x3FFF},
1813 	{0x06DE, 0x0404},
1814 	{0x06E0, 0x0404},
1815 	{0x06E2, 0xFF00},
1816 	{0x06E4, 0x8333},
1817 	{0x06E6, 0x8333},
1818 	{0x06E8, 0x8333},
1819 	{0x06EA, 0x8333},
1820 	{0x052A, 0x0000},
1821 	{0x052C, 0x0000},
1822 	{0x0F06, 0x0002},
1823 	{0x0A04, 0xB4C5},
1824 	{0x0A06, 0xC400},
1825 	{0x0A08, 0x988A},
1826 	{0x0A0A, 0xA387},
1827 	{0x0A0E, 0xEEC0},
1828 	{0x0A12, 0x0000},
1829 	{0x0A18, 0x0010},
1830 	{0x0A1C, 0x0040},
1831 	{0x0A20, 0x0015},
1832 	{0x0C00, 0x0021},
1833 	{0x0C16, 0x0002},
1834 	{0x0708, 0x6FC0},
1835 	{0x070C, 0x0000},
1836 	{0x120C, 0x1428},
1837 	{0x121A, 0x0000},
1838 	{0x121C, 0x1896},
1839 	{0x121E, 0x0032},
1840 	{0x1220, 0x0000},
1841 	{0x1222, 0x96FF},
1842 	{0x1244, 0x0000},
1843 	{0x105C, 0x0F0B},
1844 	{0x1958, 0x0000},
1845 	{0x195A, 0x004C},
1846 	{0x195C, 0x0097},
1847 	{0x195E, 0x0221},
1848 	{0x1960, 0x03FE},
1849 	{0x1980, 0x00E0},
1850 	{0x1982, 0x0010},
1851 	{0x1984, 0x2018},
1852 	{0x1986, 0x0008},
1853 	{0x1988, 0x0000},
1854 	{0x198A, 0x0000},
1855 	{0x198C, 0x0880},
1856 	{0x198E, 0x0000},
1857 	{0x1990, 0x1A00},
1858 	{0x1992, 0x0000},
1859 	{0x1994, 0x2800},
1860 	{0x1996, 0x0002},
1861 	{0x1962, 0x0000},
1862 	{0x1964, 0x004C},
1863 	{0x1966, 0x0097},
1864 	{0x1968, 0x0221},
1865 	{0x196A, 0x03FE},
1866 	{0x19C0, 0x00E0},
1867 	{0x19C2, 0x0010},
1868 	{0x19C4, 0x2018},
1869 	{0x19C6, 0x0008},
1870 	{0x19C8, 0x0000},
1871 	{0x19CA, 0x0000},
1872 	{0x19CC, 0x0880},
1873 	{0x19CE, 0x0000},
1874 	{0x19D0, 0x1A00},
1875 	{0x19D2, 0x0000},
1876 	{0x19D4, 0x2800},
1877 	{0x19D6, 0x0002},
1878 	{0x196C, 0x0000},
1879 	{0x196E, 0x004C},
1880 	{0x1970, 0x0097},
1881 	{0x1972, 0x0221},
1882 	{0x1974, 0x03FE},
1883 	{0x1A00, 0x00E0},
1884 	{0x1A02, 0x0010},
1885 	{0x1A04, 0x2018},
1886 	{0x1A06, 0x0008},
1887 	{0x1A08, 0x0000},
1888 	{0x1A0A, 0x0000},
1889 	{0x1A0C, 0x0880},
1890 	{0x1A0E, 0x0000},
1891 	{0x1A10, 0x1A00},
1892 	{0x1A12, 0x0000},
1893 	{0x1A14, 0x2800},
1894 	{0x1A16, 0x0002},
1895 	{0x1976, 0x0000},
1896 	{0x1978, 0x004C},
1897 	{0x197A, 0x0097},
1898 	{0x197C, 0x0221},
1899 	{0x197E, 0x03FE},
1900 	{0x1A40, 0x00E0},
1901 	{0x1A42, 0x0010},
1902 	{0x1A44, 0x2018},
1903 	{0x1A46, 0x0008},
1904 	{0x1A48, 0x0000},
1905 	{0x1A4A, 0x0000},
1906 	{0x1A4C, 0x0880},
1907 	{0x1A4E, 0x0000},
1908 	{0x1A50, 0x1A00},
1909 	{0x1A52, 0x0000},
1910 	{0x1A54, 0x2800},
1911 	{0x1A56, 0x0002},
1912 	{0x192A, 0x0201},
1913 	{0x0384, 0x0001},
1914 	{0x027E, 0x0100},
1915 };
1916 
1917 static const struct hi847_reg mode_3264x2448_regs[] = {
1918 	{0x0B00, 0x0000},
1919 	{0x0204, 0x0000},
1920 	{0x0206, 0x033C},
1921 	{0x020A, 0x0B4D},
1922 	{0x020E, 0x0B51},
1923 	{0x0214, 0x0200},
1924 	{0x0216, 0x0200},
1925 	{0x0218, 0x0200},
1926 	{0x021A, 0x0200},
1927 	{0x0224, 0x002E},
1928 	{0x022A, 0x0017},
1929 	{0x022C, 0x0E1F},
1930 	{0x022E, 0x09C1},
1931 	{0x0234, 0x1111},
1932 	{0x0236, 0x1111},
1933 	{0x0238, 0x1111},
1934 	{0x023A, 0x1111},
1935 	{0x0250, 0x0000},
1936 	{0x0252, 0x0006},
1937 	{0x0254, 0x0000},
1938 	{0x0256, 0x0000},
1939 	{0x0258, 0x0000},
1940 	{0x025A, 0x0000},
1941 	{0x025C, 0x0000},
1942 	{0x025E, 0x0202},
1943 	{0x0268, 0x00CD},
1944 	{0x0440, 0x0002},
1945 	{0x0F00, 0x0000},
1946 	{0x0F04, 0x0008},
1947 	{0x0F06, 0x0002},
1948 	{0x0B02, 0x0100},
1949 	{0x0B04, 0x00DC},
1950 	{0x0B12, 0x0CC0},
1951 	{0x0B14, 0x0990},
1952 	{0x0B20, 0x0100},
1953 	{0x1100, 0x1100},
1954 	{0x1102, 0x0008},
1955 	{0x1108, 0x0202},
1956 	{0x1118, 0x0000},
1957 	{0x0A10, 0xB040},
1958 	{0x0C14, 0x0008},
1959 	{0x0C18, 0x0CC0},
1960 	{0x0C1A, 0x0990},
1961 	{0x0730, 0x0001},
1962 	{0x0732, 0x0000},
1963 	{0x0734, 0x0300},
1964 	{0x0736, 0x004B},
1965 	{0x0738, 0x0001},
1966 	{0x073C, 0x0900},
1967 	{0x0740, 0x0000},
1968 	{0x0742, 0x0000},
1969 	{0x0744, 0x0300},
1970 	{0x0746, 0x007D},
1971 	{0x0748, 0x0002},
1972 	{0x074A, 0x0900},
1973 	{0x074C, 0x0000},
1974 	{0x074E, 0x0100},
1975 	{0x0750, 0x0000},
1976 	{0x1200, 0x0946},
1977 	{0x1202, 0x1A00},
1978 	{0x120E, 0x6027},
1979 	{0x1210, 0x8027},
1980 	{0x1246, 0x0105},
1981 	{0x1000, 0x0300},
1982 	{0x1002, 0xC311},
1983 	{0x1004, 0x2BB0},
1984 	{0x1010, 0x087B},
1985 	{0x1012, 0x0040},
1986 	{0x1014, 0x0020},
1987 	{0x1016, 0x0020},
1988 	{0x101A, 0x0020},
1989 	{0x1020, 0xC107},
1990 	{0x1022, 0x081E},
1991 	{0x1024, 0x0509},
1992 	{0x1026, 0x0B0A},
1993 	{0x1028, 0x1409},
1994 	{0x102A, 0x0B05},
1995 	{0x102C, 0x1400},
1996 	{0x1038, 0x0000},
1997 	{0x103E, 0x0001},
1998 	{0x1040, 0x0000},
1999 	{0x1042, 0x0008},
2000 	{0x1044, 0x0120},
2001 	{0x1046, 0x01B0},
2002 	{0x1048, 0x0090},
2003 	{0x1066, 0x089C},
2004 	{0x1600, 0x0000},
2005 	{0x1608, 0x0028},
2006 	{0x160A, 0x0C80},
2007 	{0x160C, 0x001A},
2008 	{0x160E, 0x0960},
2009 	{0x0252, 0x0009},
2010 	{0x0202, 0x0000},
2011 };
2012 
2013 static const struct hi847_reg mode_1632x1224_regs[] = {
2014 	{0x0B00, 0x0000},
2015 	{0x0204, 0x0200},
2016 	{0x0206, 0x033C},
2017 	{0x020A, 0x05A5},
2018 	{0x020E, 0x05A9},
2019 	{0x0214, 0x0200},
2020 	{0x0216, 0x0200},
2021 	{0x0218, 0x0200},
2022 	{0x021A, 0x0200},
2023 	{0x0224, 0x002C},
2024 	{0x022A, 0x0015},
2025 	{0x022C, 0x0E2D},
2026 	{0x022E, 0x09C1},
2027 	{0x0234, 0x3311},
2028 	{0x0236, 0x3311},
2029 	{0x0238, 0x3311},
2030 	{0x023A, 0x2222},
2031 	{0x0250, 0x0000},
2032 	{0x0252, 0x0006},
2033 	{0x0254, 0x0000},
2034 	{0x0256, 0x0000},
2035 	{0x0258, 0x0000},
2036 	{0x025A, 0x0000},
2037 	{0x025C, 0x0000},
2038 	{0x025E, 0x0202},
2039 	{0x0268, 0x00CD},
2040 	{0x0440, 0x0002},
2041 	{0x0F00, 0x0400},
2042 	{0x0F04, 0x0004},
2043 	{0x0F06, 0x0002},
2044 	{0x0B02, 0x0100},
2045 	{0x0B04, 0x00FC},
2046 	{0x0B12, 0x0660},
2047 	{0x0B14, 0x04C8},
2048 	{0x0B20, 0x0200},
2049 	{0x1100, 0x1100},
2050 	{0x1102, 0x0008},
2051 	{0x1108, 0x0402},
2052 	{0x1118, 0x0000},
2053 	{0x0A10, 0xB060},
2054 	{0x0C14, 0x0008},
2055 	{0x0C18, 0x0CC0},
2056 	{0x0C1A, 0x04C8},
2057 	{0x0730, 0x0001},
2058 	{0x0732, 0x0000},
2059 	{0x0734, 0x0300},
2060 	{0x0736, 0x004B},
2061 	{0x0738, 0x0001},
2062 	{0x073C, 0x0900},
2063 	{0x0740, 0x0000},
2064 	{0x0742, 0x0000},
2065 	{0x0744, 0x0300},
2066 	{0x0746, 0x007D},
2067 	{0x0748, 0x0002},
2068 	{0x074A, 0x0900},
2069 	{0x074C, 0x0100},
2070 	{0x074E, 0x0100},
2071 	{0x0750, 0x0000},
2072 	{0x1200, 0x0946},
2073 	{0x1202, 0x1A00},
2074 	{0x120E, 0x6027},
2075 	{0x1210, 0x8027},
2076 	{0x1246, 0x0105},
2077 	{0x1000, 0x0300},
2078 	{0x1002, 0xC311},
2079 	{0x1004, 0x2BB0},
2080 	{0x1010, 0x042B},
2081 	{0x1012, 0x0012},
2082 	{0x1014, 0x0020},
2083 	{0x1016, 0x0020},
2084 	{0x101A, 0x0020},
2085 	{0x1020, 0xC103},
2086 	{0x1022, 0x040F},
2087 	{0x1024, 0x0304},
2088 	{0x1026, 0x0607},
2089 	{0x1028, 0x0D06},
2090 	{0x102A, 0x0605},
2091 	{0x102C, 0x0C00},
2092 	{0x1038, 0x0000},
2093 	{0x103E, 0x0101},
2094 	{0x1040, 0x0000},
2095 	{0x1042, 0x0008},
2096 	{0x1044, 0x0120},
2097 	{0x1046, 0x01B0},
2098 	{0x1048, 0x0090},
2099 	{0x1066, 0x043B},
2100 	{0x1600, 0x0400},
2101 	{0x1608, 0x0028},
2102 	{0x160A, 0x0C80},
2103 	{0x160C, 0x001A},
2104 	{0x160E, 0x0960},
2105 	{0x0252, 0x0009},
2106 	{0x0202, 0x0000},
2107 };
2108 
2109 static const char * const hi847_test_pattern_menu[] = {
2110 	"No Pattern",
2111 	"Solid Colour",
2112 	"100% Colour Bars",
2113 	"Fade To Grey Colour Bars",
2114 	"PN9",
2115 	"Horizontal Gradient Pattern",
2116 	"Vertical Gradient Pattern",
2117 	"Check Board",
2118 	"Slant Pattern",
2119 };
2120 
2121 static const s64 link_freq_menu_items[] = {
2122 	HI847_LINK_FREQ_400MHZ,
2123 	HI847_LINK_FREQ_200MHZ,
2124 };
2125 
2126 static const struct hi847_link_freq_config link_freq_configs[] = {
2127 	[HI847_LINK_FREQ_400MHZ_INDEX] = {
2128 		.reg_list = {
2129 			.num_of_regs = ARRAY_SIZE(mipi_data_rate_lane_4),
2130 			.regs = mipi_data_rate_lane_4,
2131 		}
2132 	},
2133 	[HI847_LINK_FREQ_200MHZ_INDEX] = {
2134 		.reg_list = {
2135 			.num_of_regs = ARRAY_SIZE(mipi_data_rate_lane_4),
2136 			.regs = mipi_data_rate_lane_4,
2137 		}
2138 	}
2139 };
2140 
2141 static const struct hi847_mode supported_modes[] = {
2142 	{
2143 		.width = 3264,
2144 		.height = 2448,
2145 		.fll_def = HI847_FLL_30FPS,
2146 		.fll_min = HI847_FLL_30FPS_MIN,
2147 		.llp = 0x033C,
2148 		.reg_list = {
2149 			.num_of_regs = ARRAY_SIZE(mode_3264x2448_regs),
2150 			.regs = mode_3264x2448_regs,
2151 		},
2152 		.link_freq_index = HI847_LINK_FREQ_400MHZ_INDEX,
2153 	},
2154 	{
2155 		.width = 1632,
2156 		.height = 1224,
2157 		.fll_def = HI847_FLL_60FPS,
2158 		.fll_min = HI847_FLL_60FPS_MIN,
2159 		.llp = 0x033C,
2160 		.reg_list = {
2161 			.num_of_regs = ARRAY_SIZE(mode_1632x1224_regs),
2162 			.regs = mode_1632x1224_regs,
2163 		},
2164 		.link_freq_index = HI847_LINK_FREQ_200MHZ_INDEX,
2165 	}
2166 };
2167 
2168 struct hi847 {
2169 	struct v4l2_subdev sd;
2170 	struct media_pad pad;
2171 	struct v4l2_ctrl_handler ctrl_handler;
2172 
2173 	/* V4L2 Controls */
2174 	struct v4l2_ctrl *link_freq;
2175 	struct v4l2_ctrl *pixel_rate;
2176 	struct v4l2_ctrl *vblank;
2177 	struct v4l2_ctrl *hblank;
2178 	struct v4l2_ctrl *exposure;
2179 	struct v4l2_ctrl *vflip;
2180 	struct v4l2_ctrl *hflip;
2181 
2182 	/* Current mode */
2183 	const struct hi847_mode *cur_mode;
2184 
2185 	/* To serialize asynchronus callbacks */
2186 	struct mutex mutex;
2187 
2188 	/* Streaming on/off */
2189 	bool streaming;
2190 };
2191 
2192 static u64 to_pixel_rate(u32 f_index)
2193 {
2194 	u64 pixel_rate = link_freq_menu_items[f_index] * 2 * HI847_DATA_LANES;
2195 
2196 	do_div(pixel_rate, HI847_RGB_DEPTH);
2197 
2198 	return pixel_rate;
2199 }
2200 
2201 static int hi847_read_reg(struct hi847 *hi847, u16 reg, u16 len, u32 *val)
2202 {
2203 	struct i2c_client *client = v4l2_get_subdevdata(&hi847->sd);
2204 	struct i2c_msg msgs[2];
2205 	u8 addr_buf[2];
2206 	u8 data_buf[4] = {0};
2207 	int ret;
2208 
2209 	if (len > 4)
2210 		return -EINVAL;
2211 
2212 	put_unaligned_be16(reg, addr_buf);
2213 	msgs[0].addr = client->addr;
2214 	msgs[0].flags = 0;
2215 	msgs[0].len = sizeof(addr_buf);
2216 	msgs[0].buf = addr_buf;
2217 	msgs[1].addr = client->addr;
2218 	msgs[1].flags = I2C_M_RD;
2219 	msgs[1].len = len;
2220 	msgs[1].buf = &data_buf[4 - len];
2221 
2222 	ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
2223 	if (ret != ARRAY_SIZE(msgs))
2224 		return -EIO;
2225 
2226 	*val = get_unaligned_be32(data_buf);
2227 
2228 	return 0;
2229 }
2230 
2231 static int hi847_write_reg(struct hi847 *hi847, u16 reg, u16 len, u32 val)
2232 {
2233 	struct i2c_client *client = v4l2_get_subdevdata(&hi847->sd);
2234 	u8 buf[6];
2235 
2236 	if (len > 4)
2237 		return -EINVAL;
2238 
2239 	put_unaligned_be16(reg, buf);
2240 	put_unaligned_be32(val << 8 * (4 - len), buf + 2);
2241 	if (i2c_master_send(client, buf, len + 2) != len + 2)
2242 		return -EIO;
2243 
2244 	return 0;
2245 }
2246 
2247 static int hi847_write_reg_list(struct hi847 *hi847,
2248 				const struct hi847_reg_list *r_list)
2249 {
2250 	struct i2c_client *client = v4l2_get_subdevdata(&hi847->sd);
2251 	unsigned int i;
2252 	int ret;
2253 
2254 	for (i = 0; i < r_list->num_of_regs; i++) {
2255 		ret = hi847_write_reg(hi847, r_list->regs[i].address,
2256 				      HI847_REG_VALUE_16BIT,
2257 				      r_list->regs[i].val);
2258 		if (ret) {
2259 			dev_err_ratelimited(&client->dev,
2260 					    "failed to write reg 0x%4.4x. error = %d",
2261 					    r_list->regs[i].address, ret);
2262 			return ret;
2263 		}
2264 	}
2265 
2266 	return 0;
2267 }
2268 
2269 static int hi847_update_digital_gain(struct hi847 *hi847, u32 d_gain)
2270 {
2271 	int ret;
2272 
2273 	ret = hi847_write_reg(hi847, HI847_REG_MWB_GR_GAIN,
2274 			      HI847_REG_VALUE_16BIT, d_gain);
2275 	if (ret)
2276 		return ret;
2277 
2278 	ret = hi847_write_reg(hi847, HI847_REG_MWB_GB_GAIN,
2279 			      HI847_REG_VALUE_16BIT, d_gain);
2280 	if (ret)
2281 		return ret;
2282 
2283 	ret = hi847_write_reg(hi847, HI847_REG_MWB_R_GAIN,
2284 			      HI847_REG_VALUE_16BIT, d_gain);
2285 	if (ret)
2286 		return ret;
2287 
2288 	return hi847_write_reg(hi847, HI847_REG_MWB_B_GAIN,
2289 			       HI847_REG_VALUE_16BIT, d_gain);
2290 }
2291 
2292 static int hi847_test_pattern(struct hi847 *hi847, u32 pattern)
2293 {
2294 	int ret;
2295 	u32 val;
2296 
2297 	if (pattern) {
2298 		ret = hi847_read_reg(hi847, HI847_REG_ISP,
2299 				     HI847_REG_VALUE_16BIT, &val);
2300 		if (ret)
2301 			return ret;
2302 
2303 		ret = hi847_write_reg(hi847, HI847_REG_ISP,
2304 				      HI847_REG_VALUE_16BIT,
2305 				      val | HI847_REG_ISP_TPG_EN);
2306 		if (ret)
2307 			return ret;
2308 	}
2309 
2310 	ret = hi847_read_reg(hi847, HI847_REG_TEST_PATTERN,
2311 			     HI847_REG_VALUE_16BIT, &val);
2312 	if (ret)
2313 		return ret;
2314 
2315 	return hi847_write_reg(hi847, HI847_REG_TEST_PATTERN,
2316 			       HI847_REG_VALUE_16BIT, val | pattern << 8);
2317 }
2318 
2319 static int hi847_grbg_shift(struct hi847 *hi847)
2320 {
2321 	int ret;
2322 	int hflip, vflip;
2323 
2324 	/* regs shift for full size */
2325 	static const u32 FORMAT_X_SHIFT_1[2][2] = {
2326 		{ 0x0008, 0x0007, },
2327 		{ 0x0008, 0x0007, },
2328 	};
2329 
2330 	static const u32 FORMAT_Y_SHIFT_1[2][2] = {
2331 		{ 0x0002, 0x0002, },
2332 		{ 0x0001, 0x0001, },
2333 	};
2334 
2335 	/* regs shift for binning size */
2336 	static const u32 FORMAT_X_SHIFT_2[2][2] = {
2337 		{ 0x0004, 0x0003, },
2338 		{ 0x0004, 0x0003, },
2339 	};
2340 
2341 	static const u32 FORMAT_Y_SHIFT_2[2][2] = {
2342 		{ 0x0002, 0x0002, },
2343 		{ 0x0001, 0x0001, },
2344 	};
2345 
2346 	hflip = hi847->hflip->val;
2347 	vflip = hi847->vflip->val;
2348 
2349 	if (hi847->cur_mode->width == 3264) {
2350 		ret = hi847_write_reg(hi847, HI847_REG_FORMAT_X,
2351 				      HI847_REG_VALUE_16BIT,
2352 				      FORMAT_X_SHIFT_1[vflip][hflip]);
2353 		if (ret)
2354 			return ret;
2355 
2356 		return hi847_write_reg(hi847, HI847_REG_FORMAT_Y,
2357 				       HI847_REG_VALUE_16BIT,
2358 				       FORMAT_Y_SHIFT_1[vflip][hflip]);
2359 	} else {
2360 		ret = hi847_write_reg(hi847, HI847_REG_FORMAT_X,
2361 				      HI847_REG_VALUE_16BIT,
2362 				      FORMAT_X_SHIFT_2[vflip][hflip]);
2363 		if (ret)
2364 			return ret;
2365 
2366 		return hi847_write_reg(hi847, HI847_REG_FORMAT_Y,
2367 				       HI847_REG_VALUE_16BIT,
2368 				       FORMAT_Y_SHIFT_2[vflip][hflip]);
2369 	}
2370 }
2371 
2372 static int hi847_set_ctrl_hflip(struct hi847 *hi847, u32 ctrl_val)
2373 {
2374 	int ret;
2375 	u32 val;
2376 
2377 	ret = hi847_read_reg(hi847, HI847_REG_MIRROR_FLIP,
2378 			     HI847_REG_VALUE_16BIT, &val);
2379 	if (ret)
2380 		return ret;
2381 
2382 	ret = hi847_grbg_shift(hi847);
2383 	if (ret)
2384 		return ret;
2385 
2386 	return hi847_write_reg(hi847, HI847_REG_MIRROR_FLIP,
2387 			       HI847_REG_VALUE_16BIT,
2388 			       ctrl_val ? val | BIT(8) : val & ~BIT(8));
2389 }
2390 
2391 static int hi847_set_ctrl_vflip(struct hi847 *hi847, u8 ctrl_val)
2392 {
2393 	int ret;
2394 	u32 val;
2395 
2396 	ret = hi847_read_reg(hi847, HI847_REG_MIRROR_FLIP,
2397 			     HI847_REG_VALUE_16BIT, &val);
2398 	if (ret)
2399 		return ret;
2400 
2401 	ret = hi847_grbg_shift(hi847);
2402 	if (ret)
2403 		return ret;
2404 
2405 	return hi847_write_reg(hi847, HI847_REG_MIRROR_FLIP,
2406 			       HI847_REG_VALUE_16BIT,
2407 			       ctrl_val ? val | BIT(9) : val & ~BIT(9));
2408 }
2409 
2410 static int hi847_set_ctrl(struct v4l2_ctrl *ctrl)
2411 {
2412 	struct hi847 *hi847 = container_of(ctrl->handler,
2413 					     struct hi847, ctrl_handler);
2414 	struct i2c_client *client = v4l2_get_subdevdata(&hi847->sd);
2415 	s64 exposure_max;
2416 	int ret = 0;
2417 
2418 	/* Propagate change of current control to all related controls */
2419 	if (ctrl->id == V4L2_CID_VBLANK) {
2420 		/* Update max exposure while meeting expected vblanking */
2421 		exposure_max = hi847->cur_mode->height + ctrl->val -
2422 			       HI847_EXPOSURE_MAX_MARGIN;
2423 		__v4l2_ctrl_modify_range(hi847->exposure,
2424 					 hi847->exposure->minimum,
2425 					 exposure_max, hi847->exposure->step,
2426 					 exposure_max);
2427 	}
2428 
2429 	/* V4L2 controls values will be applied only when power is already up */
2430 	if (!pm_runtime_get_if_in_use(&client->dev))
2431 		return 0;
2432 
2433 	switch (ctrl->id) {
2434 	case V4L2_CID_ANALOGUE_GAIN:
2435 		ret = hi847_write_reg(hi847, HI847_REG_ANALOG_GAIN,
2436 				      HI847_REG_VALUE_16BIT, ctrl->val);
2437 		break;
2438 
2439 	case V4L2_CID_DIGITAL_GAIN:
2440 		ret = hi847_update_digital_gain(hi847, ctrl->val);
2441 		break;
2442 
2443 	case V4L2_CID_EXPOSURE:
2444 		ret = hi847_write_reg(hi847, HI847_REG_EXPOSURE,
2445 				      HI847_REG_VALUE_16BIT, ctrl->val);
2446 		break;
2447 
2448 	case V4L2_CID_VBLANK:
2449 		/* Update FLL that meets expected vertical blanking */
2450 		ret = hi847_write_reg(hi847, HI847_REG_FLL,
2451 				      HI847_REG_VALUE_16BIT,
2452 				      hi847->cur_mode->height + ctrl->val);
2453 		break;
2454 
2455 	case V4L2_CID_TEST_PATTERN:
2456 		ret = hi847_test_pattern(hi847, ctrl->val);
2457 		break;
2458 
2459 	case V4L2_CID_HFLIP:
2460 		hi847_set_ctrl_hflip(hi847, ctrl->val);
2461 		break;
2462 
2463 	case V4L2_CID_VFLIP:
2464 		hi847_set_ctrl_vflip(hi847, ctrl->val);
2465 		break;
2466 
2467 	default:
2468 		ret = -EINVAL;
2469 		break;
2470 	}
2471 
2472 	pm_runtime_put(&client->dev);
2473 
2474 	return ret;
2475 }
2476 
2477 static const struct v4l2_ctrl_ops hi847_ctrl_ops = {
2478 	.s_ctrl = hi847_set_ctrl,
2479 };
2480 
2481 static int hi847_init_controls(struct hi847 *hi847)
2482 {
2483 	struct v4l2_ctrl_handler *ctrl_hdlr;
2484 	s64 exposure_max, h_blank;
2485 	int ret;
2486 
2487 	ctrl_hdlr = &hi847->ctrl_handler;
2488 	ret = v4l2_ctrl_handler_init(ctrl_hdlr, 8);
2489 	if (ret)
2490 		return ret;
2491 
2492 	ctrl_hdlr->lock = &hi847->mutex;
2493 	hi847->link_freq = v4l2_ctrl_new_int_menu(ctrl_hdlr, &hi847_ctrl_ops,
2494 						  V4L2_CID_LINK_FREQ,
2495 					ARRAY_SIZE(link_freq_menu_items) - 1,
2496 					0, link_freq_menu_items);
2497 	if (hi847->link_freq)
2498 		hi847->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
2499 
2500 	hi847->pixel_rate = v4l2_ctrl_new_std
2501 			    (ctrl_hdlr, &hi847_ctrl_ops,
2502 			     V4L2_CID_PIXEL_RATE, 0,
2503 			     to_pixel_rate(HI847_LINK_FREQ_400MHZ_INDEX),
2504 			     1,
2505 			     to_pixel_rate(HI847_LINK_FREQ_400MHZ_INDEX));
2506 	hi847->vblank = v4l2_ctrl_new_std(ctrl_hdlr, &hi847_ctrl_ops,
2507 					  V4L2_CID_VBLANK,
2508 					  hi847->cur_mode->fll_min -
2509 					  hi847->cur_mode->height,
2510 					  HI847_FLL_MAX -
2511 					  hi847->cur_mode->height, 1,
2512 					  hi847->cur_mode->fll_def -
2513 					  hi847->cur_mode->height);
2514 
2515 	h_blank = hi847->cur_mode->llp - hi847->cur_mode->width;
2516 
2517 	hi847->hblank = v4l2_ctrl_new_std(ctrl_hdlr, &hi847_ctrl_ops,
2518 					  V4L2_CID_HBLANK, h_blank, h_blank, 1,
2519 					  h_blank);
2520 	if (hi847->hblank)
2521 		hi847->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
2522 
2523 	v4l2_ctrl_new_std(ctrl_hdlr, &hi847_ctrl_ops, V4L2_CID_ANALOGUE_GAIN,
2524 			  HI847_ANAL_GAIN_MIN, HI847_ANAL_GAIN_MAX,
2525 			  HI847_ANAL_GAIN_STEP, HI847_ANAL_GAIN_MIN);
2526 	v4l2_ctrl_new_std(ctrl_hdlr, &hi847_ctrl_ops, V4L2_CID_DIGITAL_GAIN,
2527 			  HI847_DGTL_GAIN_MIN, HI847_DGTL_GAIN_MAX,
2528 			  HI847_DGTL_GAIN_STEP, HI847_DGTL_GAIN_DEFAULT);
2529 	exposure_max = hi847->cur_mode->fll_def - HI847_EXPOSURE_MAX_MARGIN;
2530 	hi847->exposure = v4l2_ctrl_new_std(ctrl_hdlr, &hi847_ctrl_ops,
2531 					    V4L2_CID_EXPOSURE,
2532 					    HI847_EXPOSURE_MIN, exposure_max,
2533 					    HI847_EXPOSURE_STEP,
2534 					    exposure_max);
2535 	v4l2_ctrl_new_std_menu_items(ctrl_hdlr, &hi847_ctrl_ops,
2536 				     V4L2_CID_TEST_PATTERN,
2537 				     ARRAY_SIZE(hi847_test_pattern_menu) - 1,
2538 				     0, 0, hi847_test_pattern_menu);
2539 	hi847->hflip = v4l2_ctrl_new_std(ctrl_hdlr, &hi847_ctrl_ops,
2540 					 V4L2_CID_HFLIP, 0, 1, 1, 0);
2541 	hi847->vflip = v4l2_ctrl_new_std(ctrl_hdlr, &hi847_ctrl_ops,
2542 					 V4L2_CID_VFLIP, 0, 1, 1, 0);
2543 
2544 	if (ctrl_hdlr->error)
2545 		return ctrl_hdlr->error;
2546 
2547 	hi847->sd.ctrl_handler = ctrl_hdlr;
2548 
2549 	return 0;
2550 }
2551 
2552 static void hi847_assign_pad_format(const struct hi847_mode *mode,
2553 				    struct v4l2_mbus_framefmt *fmt)
2554 {
2555 	fmt->width = mode->width;
2556 	fmt->height = mode->height;
2557 	fmt->code = MEDIA_BUS_FMT_SGRBG10_1X10;
2558 	fmt->field = V4L2_FIELD_NONE;
2559 }
2560 
2561 static int hi847_start_streaming(struct hi847 *hi847)
2562 {
2563 	struct i2c_client *client = v4l2_get_subdevdata(&hi847->sd);
2564 	const struct hi847_reg_list *reg_list;
2565 	int link_freq_index, ret;
2566 
2567 	link_freq_index = hi847->cur_mode->link_freq_index;
2568 	reg_list = &link_freq_configs[link_freq_index].reg_list;
2569 	ret = hi847_write_reg_list(hi847, reg_list);
2570 	if (ret) {
2571 		dev_err(&client->dev, "failed to set plls");
2572 		return ret;
2573 	}
2574 
2575 	reg_list = &hi847->cur_mode->reg_list;
2576 	ret = hi847_write_reg_list(hi847, reg_list);
2577 	if (ret) {
2578 		dev_err(&client->dev, "failed to set mode");
2579 		return ret;
2580 	}
2581 
2582 	ret = __v4l2_ctrl_handler_setup(hi847->sd.ctrl_handler);
2583 	if (ret)
2584 		return ret;
2585 
2586 	ret = hi847_write_reg(hi847, HI847_REG_MODE_TG,
2587 			      HI847_REG_VALUE_16BIT, HI847_REG_MODE_TG_ENABLE);
2588 
2589 	ret = hi847_write_reg(hi847, HI847_REG_MODE_SELECT,
2590 			      HI847_REG_VALUE_16BIT, HI847_MODE_STREAMING);
2591 
2592 	if (ret) {
2593 		dev_err(&client->dev, "failed to set stream");
2594 		return ret;
2595 	}
2596 
2597 	return 0;
2598 }
2599 
2600 static void hi847_stop_streaming(struct hi847 *hi847)
2601 {
2602 	struct i2c_client *client = v4l2_get_subdevdata(&hi847->sd);
2603 
2604 	if (hi847_write_reg(hi847, HI847_REG_MODE_TG,
2605 			    HI847_REG_VALUE_16BIT, HI847_REG_MODE_TG_DISABLE))
2606 		dev_err(&client->dev, "failed to set stream 0x%x",
2607 			HI847_REG_MODE_TG);
2608 
2609 	if (hi847_write_reg(hi847, HI847_REG_MODE_SELECT,
2610 			    HI847_REG_VALUE_16BIT, HI847_MODE_STANDBY))
2611 		dev_err(&client->dev, "failed to set stream 0x%x",
2612 		HI847_REG_MODE_SELECT);
2613 }
2614 
2615 static int hi847_set_stream(struct v4l2_subdev *sd, int enable)
2616 {
2617 	struct hi847 *hi847 = to_hi847(sd);
2618 	struct i2c_client *client = v4l2_get_subdevdata(sd);
2619 	int ret = 0;
2620 
2621 	if (hi847->streaming == enable)
2622 		return 0;
2623 
2624 	mutex_lock(&hi847->mutex);
2625 	if (enable) {
2626 		ret = pm_runtime_get_sync(&client->dev);
2627 		if (ret < 0) {
2628 			pm_runtime_put_noidle(&client->dev);
2629 			mutex_unlock(&hi847->mutex);
2630 			return ret;
2631 		}
2632 
2633 		ret = hi847_start_streaming(hi847);
2634 		if (ret) {
2635 			enable = 0;
2636 			hi847_stop_streaming(hi847);
2637 			pm_runtime_put(&client->dev);
2638 		}
2639 	} else {
2640 		hi847_stop_streaming(hi847);
2641 		pm_runtime_put(&client->dev);
2642 	}
2643 
2644 	hi847->streaming = enable;
2645 	mutex_unlock(&hi847->mutex);
2646 
2647 	return ret;
2648 }
2649 
2650 static int __maybe_unused hi847_suspend(struct device *dev)
2651 {
2652 	struct i2c_client *client = to_i2c_client(dev);
2653 	struct v4l2_subdev *sd = i2c_get_clientdata(client);
2654 	struct hi847 *hi847 = to_hi847(sd);
2655 
2656 	mutex_lock(&hi847->mutex);
2657 	if (hi847->streaming)
2658 		hi847_stop_streaming(hi847);
2659 
2660 	mutex_unlock(&hi847->mutex);
2661 
2662 	return 0;
2663 }
2664 
2665 static int __maybe_unused hi847_resume(struct device *dev)
2666 {
2667 	struct i2c_client *client = to_i2c_client(dev);
2668 	struct v4l2_subdev *sd = i2c_get_clientdata(client);
2669 	struct hi847 *hi847 = to_hi847(sd);
2670 	int ret;
2671 
2672 	mutex_lock(&hi847->mutex);
2673 	if (hi847->streaming) {
2674 		ret = hi847_start_streaming(hi847);
2675 		if (ret)
2676 			goto error;
2677 	}
2678 
2679 	mutex_unlock(&hi847->mutex);
2680 
2681 	return 0;
2682 
2683 error:
2684 	hi847_stop_streaming(hi847);
2685 	hi847->streaming = 0;
2686 	mutex_unlock(&hi847->mutex);
2687 	return ret;
2688 }
2689 
2690 static int hi847_set_format(struct v4l2_subdev *sd,
2691 			    struct v4l2_subdev_state *sd_state,
2692 			    struct v4l2_subdev_format *fmt)
2693 {
2694 	struct hi847 *hi847 = to_hi847(sd);
2695 	const struct hi847_mode *mode;
2696 	s32 vblank_def, h_blank;
2697 
2698 	mode = v4l2_find_nearest_size(supported_modes,
2699 				      ARRAY_SIZE(supported_modes), width,
2700 				      height, fmt->format.width,
2701 				      fmt->format.height);
2702 
2703 	mutex_lock(&hi847->mutex);
2704 	hi847_assign_pad_format(mode, &fmt->format);
2705 	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
2706 		*v4l2_subdev_get_try_format(sd, sd_state, fmt->pad) =
2707 			fmt->format;
2708 	} else {
2709 		hi847->cur_mode = mode;
2710 		__v4l2_ctrl_s_ctrl(hi847->link_freq, mode->link_freq_index);
2711 		__v4l2_ctrl_s_ctrl_int64(hi847->pixel_rate,
2712 					 to_pixel_rate(mode->link_freq_index));
2713 
2714 		/* Update limits and set FPS to default */
2715 		vblank_def = mode->fll_def - mode->height;
2716 		__v4l2_ctrl_modify_range(hi847->vblank,
2717 					 mode->fll_min - mode->height,
2718 					 HI847_FLL_MAX - mode->height, 1,
2719 					 vblank_def);
2720 		__v4l2_ctrl_s_ctrl(hi847->vblank, vblank_def);
2721 
2722 		h_blank = hi847->cur_mode->llp - hi847->cur_mode->width;
2723 
2724 		__v4l2_ctrl_modify_range(hi847->hblank, h_blank, h_blank, 1,
2725 					 h_blank);
2726 	}
2727 
2728 	mutex_unlock(&hi847->mutex);
2729 
2730 	return 0;
2731 }
2732 
2733 static int hi847_get_format(struct v4l2_subdev *sd,
2734 			    struct v4l2_subdev_state *sd_state,
2735 			    struct v4l2_subdev_format *fmt)
2736 {
2737 	struct hi847 *hi847 = to_hi847(sd);
2738 
2739 	mutex_lock(&hi847->mutex);
2740 	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY)
2741 		fmt->format = *v4l2_subdev_get_try_format(&hi847->sd,
2742 							  sd_state,
2743 							  fmt->pad);
2744 	else
2745 		hi847_assign_pad_format(hi847->cur_mode, &fmt->format);
2746 
2747 	mutex_unlock(&hi847->mutex);
2748 
2749 	return 0;
2750 }
2751 
2752 static int hi847_enum_mbus_code(struct v4l2_subdev *sd,
2753 				struct v4l2_subdev_state *sd_state,
2754 				struct v4l2_subdev_mbus_code_enum *code)
2755 {
2756 	if (code->index > 0)
2757 		return -EINVAL;
2758 
2759 	code->code = MEDIA_BUS_FMT_SGRBG10_1X10;
2760 
2761 	return 0;
2762 }
2763 
2764 static int hi847_enum_frame_size(struct v4l2_subdev *sd,
2765 				 struct v4l2_subdev_state *sd_state,
2766 				 struct v4l2_subdev_frame_size_enum *fse)
2767 {
2768 	if (fse->index >= ARRAY_SIZE(supported_modes))
2769 		return -EINVAL;
2770 
2771 	if (fse->code != MEDIA_BUS_FMT_SGRBG10_1X10)
2772 		return -EINVAL;
2773 
2774 	fse->min_width = supported_modes[fse->index].width;
2775 	fse->max_width = fse->min_width;
2776 	fse->min_height = supported_modes[fse->index].height;
2777 	fse->max_height = fse->min_height;
2778 
2779 	return 0;
2780 }
2781 
2782 static int hi847_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
2783 {
2784 	struct hi847 *hi847 = to_hi847(sd);
2785 
2786 	mutex_lock(&hi847->mutex);
2787 	hi847_assign_pad_format(&supported_modes[0],
2788 				v4l2_subdev_get_try_format(sd, fh->state, 0));
2789 	mutex_unlock(&hi847->mutex);
2790 
2791 	return 0;
2792 }
2793 
2794 static const struct v4l2_subdev_video_ops hi847_video_ops = {
2795 	.s_stream = hi847_set_stream,
2796 };
2797 
2798 static const struct v4l2_subdev_pad_ops hi847_pad_ops = {
2799 	.set_fmt = hi847_set_format,
2800 	.get_fmt = hi847_get_format,
2801 	.enum_mbus_code = hi847_enum_mbus_code,
2802 	.enum_frame_size = hi847_enum_frame_size,
2803 };
2804 
2805 static const struct v4l2_subdev_ops hi847_subdev_ops = {
2806 	.video = &hi847_video_ops,
2807 	.pad = &hi847_pad_ops,
2808 };
2809 
2810 static const struct media_entity_operations hi847_subdev_entity_ops = {
2811 	.link_validate = v4l2_subdev_link_validate,
2812 };
2813 
2814 static const struct v4l2_subdev_internal_ops hi847_internal_ops = {
2815 	.open = hi847_open,
2816 };
2817 
2818 static int hi847_identify_module(struct hi847 *hi847)
2819 {
2820 	struct i2c_client *client = v4l2_get_subdevdata(&hi847->sd);
2821 	int ret;
2822 	u32 val;
2823 
2824 	ret = hi847_read_reg(hi847, HI847_REG_CHIP_ID,
2825 			     HI847_REG_VALUE_16BIT, &val);
2826 	if (ret)
2827 		return ret;
2828 
2829 	if (val != HI847_CHIP_ID) {
2830 		dev_err(&client->dev, "chip id mismatch: %x!=%x",
2831 			HI847_CHIP_ID, val);
2832 		return -ENXIO;
2833 	}
2834 
2835 	return 0;
2836 }
2837 
2838 static int hi847_check_hwcfg(struct device *dev)
2839 {
2840 	struct fwnode_handle *ep;
2841 	struct fwnode_handle *fwnode = dev_fwnode(dev);
2842 	struct v4l2_fwnode_endpoint bus_cfg = {
2843 		.bus_type = V4L2_MBUS_CSI2_DPHY
2844 	};
2845 	u32 mclk;
2846 	int ret;
2847 	unsigned int i, j;
2848 
2849 	if (!fwnode)
2850 		return -ENXIO;
2851 
2852 	ret = fwnode_property_read_u32(fwnode, "clock-frequency", &mclk);
2853 	if (ret) {
2854 		dev_err(dev, "can't get clock frequency");
2855 		return ret;
2856 	}
2857 
2858 	if (mclk != HI847_MCLK) {
2859 		dev_err(dev, "external clock %d is not supported", mclk);
2860 		return -EINVAL;
2861 	}
2862 
2863 	ep = fwnode_graph_get_next_endpoint(fwnode, NULL);
2864 	if (!ep)
2865 		return -ENXIO;
2866 
2867 	ret = v4l2_fwnode_endpoint_alloc_parse(ep, &bus_cfg);
2868 	fwnode_handle_put(ep);
2869 	if (ret)
2870 		return ret;
2871 
2872 	if (bus_cfg.bus.mipi_csi2.num_data_lanes != HI847_DATA_LANES) {
2873 		dev_err(dev, "number of CSI2 data lanes %d is not supported",
2874 			bus_cfg.bus.mipi_csi2.num_data_lanes);
2875 		ret = -EINVAL;
2876 		goto check_hwcfg_error;
2877 	}
2878 
2879 	if (!bus_cfg.nr_of_link_frequencies) {
2880 		dev_err(dev, "no link frequencies defined");
2881 		ret = -EINVAL;
2882 		goto check_hwcfg_error;
2883 	}
2884 
2885 	for (i = 0; i < ARRAY_SIZE(link_freq_menu_items); i++) {
2886 		for (j = 0; j < bus_cfg.nr_of_link_frequencies; j++) {
2887 			if (link_freq_menu_items[i] ==
2888 				bus_cfg.link_frequencies[j])
2889 				break;
2890 		}
2891 
2892 		if (j == bus_cfg.nr_of_link_frequencies) {
2893 			dev_err(dev, "no link frequency %lld supported",
2894 				link_freq_menu_items[i]);
2895 			ret = -EINVAL;
2896 			goto check_hwcfg_error;
2897 		}
2898 	}
2899 
2900 check_hwcfg_error:
2901 	v4l2_fwnode_endpoint_free(&bus_cfg);
2902 
2903 	return ret;
2904 }
2905 
2906 static void hi847_remove(struct i2c_client *client)
2907 {
2908 	struct v4l2_subdev *sd = i2c_get_clientdata(client);
2909 	struct hi847 *hi847 = to_hi847(sd);
2910 
2911 	v4l2_async_unregister_subdev(sd);
2912 	media_entity_cleanup(&sd->entity);
2913 	v4l2_ctrl_handler_free(sd->ctrl_handler);
2914 	pm_runtime_disable(&client->dev);
2915 	mutex_destroy(&hi847->mutex);
2916 }
2917 
2918 static int hi847_probe(struct i2c_client *client)
2919 {
2920 	struct hi847 *hi847;
2921 	int ret;
2922 
2923 	hi847 = devm_kzalloc(&client->dev, sizeof(*hi847), GFP_KERNEL);
2924 	if (!hi847)
2925 		return -ENOMEM;
2926 
2927 	ret = hi847_check_hwcfg(&client->dev);
2928 	if (ret) {
2929 		dev_err(&client->dev, "failed to get HW configuration: %d",
2930 			ret);
2931 		return ret;
2932 	}
2933 
2934 	v4l2_i2c_subdev_init(&hi847->sd, client, &hi847_subdev_ops);
2935 	ret = hi847_identify_module(hi847);
2936 	if (ret) {
2937 		dev_err(&client->dev, "failed to find sensor: %d", ret);
2938 		return ret;
2939 	}
2940 
2941 	mutex_init(&hi847->mutex);
2942 	hi847->cur_mode = &supported_modes[0];
2943 	ret = hi847_init_controls(hi847);
2944 	if (ret) {
2945 		dev_err(&client->dev, "failed to init controls: %d", ret);
2946 		goto probe_error_v4l2_ctrl_handler_free;
2947 	}
2948 
2949 	hi847->sd.internal_ops = &hi847_internal_ops;
2950 	hi847->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
2951 	hi847->sd.entity.ops = &hi847_subdev_entity_ops;
2952 	hi847->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
2953 	hi847->pad.flags = MEDIA_PAD_FL_SOURCE;
2954 	ret = media_entity_pads_init(&hi847->sd.entity, 1, &hi847->pad);
2955 	if (ret) {
2956 		dev_err(&client->dev, "failed to init entity pads: %d", ret);
2957 		goto probe_error_v4l2_ctrl_handler_free;
2958 	}
2959 
2960 	ret = v4l2_async_register_subdev_sensor(&hi847->sd);
2961 	if (ret < 0) {
2962 		dev_err(&client->dev, "failed to register V4L2 subdev: %d",
2963 			ret);
2964 		goto probe_error_media_entity_cleanup;
2965 	}
2966 
2967 	pm_runtime_set_active(&client->dev);
2968 	pm_runtime_enable(&client->dev);
2969 	pm_runtime_idle(&client->dev);
2970 
2971 	return 0;
2972 
2973 probe_error_media_entity_cleanup:
2974 	media_entity_cleanup(&hi847->sd.entity);
2975 
2976 probe_error_v4l2_ctrl_handler_free:
2977 	v4l2_ctrl_handler_free(hi847->sd.ctrl_handler);
2978 	mutex_destroy(&hi847->mutex);
2979 
2980 	return ret;
2981 }
2982 
2983 static const struct dev_pm_ops hi847_pm_ops = {
2984 	SET_SYSTEM_SLEEP_PM_OPS(hi847_suspend, hi847_resume)
2985 };
2986 
2987 #ifdef CONFIG_ACPI
2988 static const struct acpi_device_id hi847_acpi_ids[] = {
2989 	{"HYV0847"},
2990 	{}
2991 };
2992 
2993 MODULE_DEVICE_TABLE(acpi, hi847_acpi_ids);
2994 #endif
2995 
2996 static struct i2c_driver hi847_i2c_driver = {
2997 	.driver = {
2998 		.name = "hi847",
2999 		.pm = &hi847_pm_ops,
3000 		.acpi_match_table = ACPI_PTR(hi847_acpi_ids),
3001 	},
3002 	.probe_new = hi847_probe,
3003 	.remove = hi847_remove,
3004 };
3005 
3006 module_i2c_driver(hi847_i2c_driver);
3007 
3008 MODULE_AUTHOR("Shawn Tu <shawnx.tu@intel.com>");
3009 MODULE_DESCRIPTION("Hynix HI847 sensor driver");
3010 MODULE_LICENSE("GPL v2");
3011