1153e4ad4SBenjamin Mugnier // SPDX-License-Identifier: GPL-2.0
2153e4ad4SBenjamin Mugnier /*
3153e4ad4SBenjamin Mugnier * Driver for VGXY61 global shutter sensor family driver
4153e4ad4SBenjamin Mugnier *
5153e4ad4SBenjamin Mugnier * Copyright (C) 2022 STMicroelectronics SA
6153e4ad4SBenjamin Mugnier */
7153e4ad4SBenjamin Mugnier
8153e4ad4SBenjamin Mugnier #include <linux/clk.h>
9153e4ad4SBenjamin Mugnier #include <linux/delay.h>
10153e4ad4SBenjamin Mugnier #include <linux/gpio/consumer.h>
11153e4ad4SBenjamin Mugnier #include <linux/i2c.h>
12153e4ad4SBenjamin Mugnier #include <linux/iopoll.h>
13153e4ad4SBenjamin Mugnier #include <linux/module.h>
14153e4ad4SBenjamin Mugnier #include <linux/pm_runtime.h>
15153e4ad4SBenjamin Mugnier #include <linux/regulator/consumer.h>
16153e4ad4SBenjamin Mugnier #include <linux/units.h>
1751c2bf13SAndy Shevchenko
1851c2bf13SAndy Shevchenko #include <asm/unaligned.h>
1951c2bf13SAndy Shevchenko
20153e4ad4SBenjamin Mugnier #include <media/mipi-csi2.h>
21153e4ad4SBenjamin Mugnier #include <media/v4l2-async.h>
22153e4ad4SBenjamin Mugnier #include <media/v4l2-ctrls.h>
23153e4ad4SBenjamin Mugnier #include <media/v4l2-device.h>
24153e4ad4SBenjamin Mugnier #include <media/v4l2-fwnode.h>
25153e4ad4SBenjamin Mugnier #include <media/v4l2-subdev.h>
26153e4ad4SBenjamin Mugnier
27153e4ad4SBenjamin Mugnier #define VGXY61_REG_8BIT(n) ((1 << 16) | (n))
28153e4ad4SBenjamin Mugnier #define VGXY61_REG_16BIT(n) ((2 << 16) | (n))
29153e4ad4SBenjamin Mugnier #define VGXY61_REG_32BIT(n) ((4 << 16) | (n))
30153e4ad4SBenjamin Mugnier #define VGXY61_REG_SIZE_SHIFT 16
31153e4ad4SBenjamin Mugnier #define VGXY61_REG_ADDR_MASK 0xffff
32153e4ad4SBenjamin Mugnier
33153e4ad4SBenjamin Mugnier #define VGXY61_REG_MODEL_ID VGXY61_REG_16BIT(0x0000)
34153e4ad4SBenjamin Mugnier #define VG5661_MODEL_ID 0x5661
35153e4ad4SBenjamin Mugnier #define VG5761_MODEL_ID 0x5761
36153e4ad4SBenjamin Mugnier #define VGXY61_REG_REVISION VGXY61_REG_16BIT(0x0002)
37153e4ad4SBenjamin Mugnier #define VGXY61_REG_FWPATCH_REVISION VGXY61_REG_16BIT(0x0014)
38153e4ad4SBenjamin Mugnier #define VGXY61_REG_FWPATCH_START_ADDR VGXY61_REG_8BIT(0x2000)
39153e4ad4SBenjamin Mugnier #define VGXY61_REG_SYSTEM_FSM VGXY61_REG_8BIT(0x0020)
40153e4ad4SBenjamin Mugnier #define VGXY61_SYSTEM_FSM_SW_STBY 0x03
41153e4ad4SBenjamin Mugnier #define VGXY61_SYSTEM_FSM_STREAMING 0x04
42153e4ad4SBenjamin Mugnier #define VGXY61_REG_NVM VGXY61_REG_8BIT(0x0023)
43153e4ad4SBenjamin Mugnier #define VGXY61_NVM_OK 0x04
44153e4ad4SBenjamin Mugnier #define VGXY61_REG_STBY VGXY61_REG_8BIT(0x0201)
45153e4ad4SBenjamin Mugnier #define VGXY61_STBY_NO_REQ 0
46153e4ad4SBenjamin Mugnier #define VGXY61_STBY_REQ_TMP_READ BIT(2)
47153e4ad4SBenjamin Mugnier #define VGXY61_REG_STREAMING VGXY61_REG_8BIT(0x0202)
48153e4ad4SBenjamin Mugnier #define VGXY61_STREAMING_NO_REQ 0
49153e4ad4SBenjamin Mugnier #define VGXY61_STREAMING_REQ_STOP BIT(0)
50153e4ad4SBenjamin Mugnier #define VGXY61_STREAMING_REQ_START BIT(1)
51153e4ad4SBenjamin Mugnier #define VGXY61_REG_EXT_CLOCK VGXY61_REG_32BIT(0x0220)
52153e4ad4SBenjamin Mugnier #define VGXY61_REG_CLK_PLL_PREDIV VGXY61_REG_8BIT(0x0224)
53153e4ad4SBenjamin Mugnier #define VGXY61_REG_CLK_SYS_PLL_MULT VGXY61_REG_8BIT(0x0225)
54153e4ad4SBenjamin Mugnier #define VGXY61_REG_GPIO_0_CTRL VGXY61_REG_8BIT(0x0236)
55153e4ad4SBenjamin Mugnier #define VGXY61_REG_GPIO_1_CTRL VGXY61_REG_8BIT(0x0237)
56153e4ad4SBenjamin Mugnier #define VGXY61_REG_GPIO_2_CTRL VGXY61_REG_8BIT(0x0238)
57153e4ad4SBenjamin Mugnier #define VGXY61_REG_GPIO_3_CTRL VGXY61_REG_8BIT(0x0239)
58153e4ad4SBenjamin Mugnier #define VGXY61_REG_SIGNALS_POLARITY_CTRL VGXY61_REG_8BIT(0x023b)
59153e4ad4SBenjamin Mugnier #define VGXY61_REG_LINE_LENGTH VGXY61_REG_16BIT(0x0300)
60153e4ad4SBenjamin Mugnier #define VGXY61_REG_ORIENTATION VGXY61_REG_8BIT(0x0302)
61153e4ad4SBenjamin Mugnier #define VGXY61_REG_VT_CTRL VGXY61_REG_8BIT(0x0304)
62153e4ad4SBenjamin Mugnier #define VGXY61_REG_FORMAT_CTRL VGXY61_REG_8BIT(0x0305)
63153e4ad4SBenjamin Mugnier #define VGXY61_REG_OIF_CTRL VGXY61_REG_16BIT(0x0306)
64153e4ad4SBenjamin Mugnier #define VGXY61_REG_OIF_ROI0_CTRL VGXY61_REG_8BIT(0x030a)
65153e4ad4SBenjamin Mugnier #define VGXY61_REG_ROI0_START_H VGXY61_REG_16BIT(0x0400)
66153e4ad4SBenjamin Mugnier #define VGXY61_REG_ROI0_START_V VGXY61_REG_16BIT(0x0402)
67153e4ad4SBenjamin Mugnier #define VGXY61_REG_ROI0_END_H VGXY61_REG_16BIT(0x0404)
68153e4ad4SBenjamin Mugnier #define VGXY61_REG_ROI0_END_V VGXY61_REG_16BIT(0x0406)
69153e4ad4SBenjamin Mugnier #define VGXY61_REG_PATGEN_CTRL VGXY61_REG_32BIT(0x0440)
70153e4ad4SBenjamin Mugnier #define VGXY61_PATGEN_LONG_ENABLE BIT(16)
71153e4ad4SBenjamin Mugnier #define VGXY61_PATGEN_SHORT_ENABLE BIT(0)
72153e4ad4SBenjamin Mugnier #define VGXY61_PATGEN_LONG_TYPE_SHIFT 18
73153e4ad4SBenjamin Mugnier #define VGXY61_PATGEN_SHORT_TYPE_SHIFT 4
74153e4ad4SBenjamin Mugnier #define VGXY61_REG_FRAME_CONTENT_CTRL VGXY61_REG_8BIT(0x0478)
75153e4ad4SBenjamin Mugnier #define VGXY61_REG_COARSE_EXPOSURE_LONG VGXY61_REG_16BIT(0x0500)
76153e4ad4SBenjamin Mugnier #define VGXY61_REG_COARSE_EXPOSURE_SHORT VGXY61_REG_16BIT(0x0504)
77153e4ad4SBenjamin Mugnier #define VGXY61_REG_ANALOG_GAIN VGXY61_REG_8BIT(0x0508)
78153e4ad4SBenjamin Mugnier #define VGXY61_REG_DIGITAL_GAIN_LONG VGXY61_REG_16BIT(0x050a)
79153e4ad4SBenjamin Mugnier #define VGXY61_REG_DIGITAL_GAIN_SHORT VGXY61_REG_16BIT(0x0512)
80153e4ad4SBenjamin Mugnier #define VGXY61_REG_FRAME_LENGTH VGXY61_REG_16BIT(0x051a)
81153e4ad4SBenjamin Mugnier #define VGXY61_REG_SIGNALS_CTRL VGXY61_REG_16BIT(0x0522)
82153e4ad4SBenjamin Mugnier #define VGXY61_SIGNALS_GPIO_ID_SHIFT 4
83153e4ad4SBenjamin Mugnier #define VGXY61_REG_READOUT_CTRL VGXY61_REG_8BIT(0x0530)
84153e4ad4SBenjamin Mugnier #define VGXY61_REG_HDR_CTRL VGXY61_REG_8BIT(0x0532)
85153e4ad4SBenjamin Mugnier #define VGXY61_REG_PATGEN_LONG_DATA_GR VGXY61_REG_16BIT(0x092c)
86153e4ad4SBenjamin Mugnier #define VGXY61_REG_PATGEN_LONG_DATA_R VGXY61_REG_16BIT(0x092e)
87153e4ad4SBenjamin Mugnier #define VGXY61_REG_PATGEN_LONG_DATA_B VGXY61_REG_16BIT(0x0930)
88153e4ad4SBenjamin Mugnier #define VGXY61_REG_PATGEN_LONG_DATA_GB VGXY61_REG_16BIT(0x0932)
89153e4ad4SBenjamin Mugnier #define VGXY61_REG_PATGEN_SHORT_DATA_GR VGXY61_REG_16BIT(0x0950)
90153e4ad4SBenjamin Mugnier #define VGXY61_REG_PATGEN_SHORT_DATA_R VGXY61_REG_16BIT(0x0952)
91153e4ad4SBenjamin Mugnier #define VGXY61_REG_PATGEN_SHORT_DATA_B VGXY61_REG_16BIT(0x0954)
92153e4ad4SBenjamin Mugnier #define VGXY61_REG_PATGEN_SHORT_DATA_GB VGXY61_REG_16BIT(0x0956)
93153e4ad4SBenjamin Mugnier #define VGXY61_REG_BYPASS_CTRL VGXY61_REG_8BIT(0x0a60)
94153e4ad4SBenjamin Mugnier
95153e4ad4SBenjamin Mugnier #define VGX661_WIDTH 1464
96153e4ad4SBenjamin Mugnier #define VGX661_HEIGHT 1104
97153e4ad4SBenjamin Mugnier #define VGX761_WIDTH 1944
98153e4ad4SBenjamin Mugnier #define VGX761_HEIGHT 1204
99153e4ad4SBenjamin Mugnier #define VGX661_DEFAULT_MODE 1
100153e4ad4SBenjamin Mugnier #define VGX761_DEFAULT_MODE 1
101153e4ad4SBenjamin Mugnier #define VGX661_SHORT_ROT_TERM 93
102153e4ad4SBenjamin Mugnier #define VGX761_SHORT_ROT_TERM 90
103153e4ad4SBenjamin Mugnier #define VGXY61_EXPOS_ROT_TERM 66
104153e4ad4SBenjamin Mugnier #define VGXY61_WRITE_MULTIPLE_CHUNK_MAX 16
105153e4ad4SBenjamin Mugnier #define VGXY61_NB_GPIOS 4
106153e4ad4SBenjamin Mugnier #define VGXY61_NB_POLARITIES 5
107153e4ad4SBenjamin Mugnier #define VGXY61_FRAME_LENGTH_DEF 1313
108153e4ad4SBenjamin Mugnier #define VGXY61_MIN_FRAME_LENGTH 1288
109153e4ad4SBenjamin Mugnier #define VGXY61_MIN_EXPOSURE 10
110153e4ad4SBenjamin Mugnier #define VGXY61_HDR_LINEAR_RATIO 10
111153e4ad4SBenjamin Mugnier #define VGXY61_TIMEOUT_MS 500
112153e4ad4SBenjamin Mugnier #define VGXY61_MEDIA_BUS_FMT_DEF MEDIA_BUS_FMT_Y8_1X8
113153e4ad4SBenjamin Mugnier
114153e4ad4SBenjamin Mugnier #define VGXY61_FWPATCH_REVISION_MAJOR 2
115153e4ad4SBenjamin Mugnier #define VGXY61_FWPATCH_REVISION_MINOR 0
116153e4ad4SBenjamin Mugnier #define VGXY61_FWPATCH_REVISION_MICRO 5
117153e4ad4SBenjamin Mugnier
118153e4ad4SBenjamin Mugnier static const u8 patch_array[] = {
119153e4ad4SBenjamin Mugnier 0xbf, 0x00, 0x05, 0x20, 0x06, 0x01, 0xe0, 0xe0, 0x04, 0x80, 0xe6, 0x45,
120153e4ad4SBenjamin Mugnier 0xed, 0x6f, 0xfe, 0xff, 0x14, 0x80, 0x1f, 0x84, 0x10, 0x42, 0x05, 0x7c,
121153e4ad4SBenjamin Mugnier 0x01, 0xc4, 0x1e, 0x80, 0xb6, 0x42, 0x00, 0xe0, 0x1e, 0x82, 0x1e, 0xc0,
122153e4ad4SBenjamin Mugnier 0x93, 0xdd, 0xc3, 0xc1, 0x0c, 0x04, 0x00, 0xfa, 0x86, 0x0d, 0x70, 0xe1,
123153e4ad4SBenjamin Mugnier 0x04, 0x98, 0x15, 0x00, 0x28, 0xe0, 0x14, 0x02, 0x08, 0xfc, 0x15, 0x40,
124153e4ad4SBenjamin Mugnier 0x28, 0xe0, 0x98, 0x58, 0xe0, 0xef, 0x04, 0x98, 0x0e, 0x04, 0x00, 0xf0,
125153e4ad4SBenjamin Mugnier 0x15, 0x00, 0x28, 0xe0, 0x19, 0xc8, 0x15, 0x40, 0x28, 0xe0, 0xc6, 0x41,
126153e4ad4SBenjamin Mugnier 0xfc, 0xe0, 0x14, 0x80, 0x1f, 0x84, 0x14, 0x02, 0xa0, 0xfc, 0x1e, 0x80,
127153e4ad4SBenjamin Mugnier 0x14, 0x80, 0x14, 0x02, 0x80, 0xfb, 0x14, 0x02, 0xe0, 0xfc, 0x1e, 0x80,
128153e4ad4SBenjamin Mugnier 0x14, 0xc0, 0x1f, 0x84, 0x14, 0x02, 0xa4, 0xfc, 0x1e, 0xc0, 0x14, 0xc0,
129153e4ad4SBenjamin Mugnier 0x14, 0x02, 0x80, 0xfb, 0x14, 0x02, 0xe4, 0xfc, 0x1e, 0xc0, 0x0c, 0x0c,
130153e4ad4SBenjamin Mugnier 0x00, 0xf2, 0x93, 0xdd, 0x86, 0x00, 0xf8, 0xe0, 0x04, 0x80, 0xc6, 0x03,
131153e4ad4SBenjamin Mugnier 0x70, 0xe1, 0x0e, 0x84, 0x93, 0xdd, 0xc3, 0xc1, 0x0c, 0x04, 0x00, 0xfa,
132153e4ad4SBenjamin Mugnier 0x6b, 0x80, 0x06, 0x40, 0x6c, 0xe1, 0x04, 0x80, 0x09, 0x00, 0xe0, 0xe0,
133153e4ad4SBenjamin Mugnier 0x0b, 0xa1, 0x95, 0x84, 0x05, 0x0c, 0x1c, 0xe0, 0x86, 0x02, 0xf9, 0x60,
134153e4ad4SBenjamin Mugnier 0xe0, 0xcf, 0x78, 0x6e, 0x80, 0xef, 0x25, 0x0c, 0x18, 0xe0, 0x05, 0x4c,
135153e4ad4SBenjamin Mugnier 0x1c, 0xe0, 0x86, 0x02, 0xf9, 0x60, 0xe0, 0xcf, 0x0b, 0x84, 0xd8, 0x6d,
136153e4ad4SBenjamin Mugnier 0x80, 0xef, 0x05, 0x4c, 0x18, 0xe0, 0x04, 0xd8, 0x0b, 0xa5, 0x95, 0x84,
137153e4ad4SBenjamin Mugnier 0x05, 0x0c, 0x2c, 0xe0, 0x06, 0x02, 0x01, 0x60, 0xe0, 0xce, 0x18, 0x6d,
138153e4ad4SBenjamin Mugnier 0x80, 0xef, 0x25, 0x0c, 0x30, 0xe0, 0x05, 0x4c, 0x2c, 0xe0, 0x06, 0x02,
139153e4ad4SBenjamin Mugnier 0x01, 0x60, 0xe0, 0xce, 0x0b, 0x84, 0x78, 0x6c, 0x80, 0xef, 0x05, 0x4c,
140153e4ad4SBenjamin Mugnier 0x30, 0xe0, 0x0c, 0x0c, 0x00, 0xf2, 0x93, 0xdd, 0x46, 0x01, 0x70, 0xe1,
141153e4ad4SBenjamin Mugnier 0x08, 0x80, 0x0b, 0xa1, 0x08, 0x5c, 0x00, 0xda, 0x06, 0x01, 0x68, 0xe1,
142153e4ad4SBenjamin Mugnier 0x04, 0x80, 0x4a, 0x40, 0x84, 0xe0, 0x08, 0x5c, 0x00, 0x9a, 0x06, 0x01,
143153e4ad4SBenjamin Mugnier 0xe0, 0xe0, 0x04, 0x80, 0x15, 0x00, 0x60, 0xe0, 0x19, 0xc4, 0x15, 0x40,
144153e4ad4SBenjamin Mugnier 0x60, 0xe0, 0x15, 0x00, 0x78, 0xe0, 0x19, 0xc4, 0x15, 0x40, 0x78, 0xe0,
145153e4ad4SBenjamin Mugnier 0x93, 0xdd, 0xc3, 0xc1, 0x46, 0x01, 0x70, 0xe1, 0x08, 0x80, 0x0b, 0xa1,
146153e4ad4SBenjamin Mugnier 0x08, 0x5c, 0x00, 0xda, 0x06, 0x01, 0x68, 0xe1, 0x04, 0x80, 0x4a, 0x40,
147153e4ad4SBenjamin Mugnier 0x84, 0xe0, 0x08, 0x5c, 0x00, 0x9a, 0x06, 0x01, 0xe0, 0xe0, 0x14, 0x80,
148153e4ad4SBenjamin Mugnier 0x25, 0x02, 0x54, 0xe0, 0x29, 0xc4, 0x25, 0x42, 0x54, 0xe0, 0x24, 0x80,
149153e4ad4SBenjamin Mugnier 0x35, 0x04, 0x6c, 0xe0, 0x39, 0xc4, 0x35, 0x44, 0x6c, 0xe0, 0x25, 0x02,
150153e4ad4SBenjamin Mugnier 0x64, 0xe0, 0x29, 0xc4, 0x25, 0x42, 0x64, 0xe0, 0x04, 0x80, 0x15, 0x00,
151153e4ad4SBenjamin Mugnier 0x7c, 0xe0, 0x19, 0xc4, 0x15, 0x40, 0x7c, 0xe0, 0x93, 0xdd, 0xc3, 0xc1,
152153e4ad4SBenjamin Mugnier 0x4c, 0x04, 0x7c, 0xfa, 0x86, 0x40, 0x98, 0xe0, 0x14, 0x80, 0x1b, 0xa1,
153153e4ad4SBenjamin Mugnier 0x06, 0x00, 0x00, 0xc0, 0x08, 0x42, 0x38, 0xdc, 0x08, 0x64, 0xa0, 0xef,
154153e4ad4SBenjamin Mugnier 0x86, 0x42, 0x3c, 0xe0, 0x68, 0x49, 0x80, 0xef, 0x6b, 0x80, 0x78, 0x53,
155153e4ad4SBenjamin Mugnier 0xc8, 0xef, 0xc6, 0x54, 0x6c, 0xe1, 0x7b, 0x80, 0xb5, 0x14, 0x0c, 0xf8,
156153e4ad4SBenjamin Mugnier 0x05, 0x14, 0x14, 0xf8, 0x1a, 0xac, 0x8a, 0x80, 0x0b, 0x90, 0x38, 0x55,
157153e4ad4SBenjamin Mugnier 0x80, 0xef, 0x1a, 0xae, 0x17, 0xc2, 0x03, 0x82, 0x88, 0x65, 0x80, 0xef,
158153e4ad4SBenjamin Mugnier 0x1b, 0x80, 0x0b, 0x8e, 0x68, 0x65, 0x80, 0xef, 0x9b, 0x80, 0x0b, 0x8c,
159153e4ad4SBenjamin Mugnier 0x08, 0x65, 0x80, 0xef, 0x6b, 0x80, 0x0b, 0x92, 0x1b, 0x8c, 0x98, 0x64,
160153e4ad4SBenjamin Mugnier 0x80, 0xef, 0x1a, 0xec, 0x9b, 0x80, 0x0b, 0x90, 0x95, 0x54, 0x10, 0xe0,
161153e4ad4SBenjamin Mugnier 0xa8, 0x53, 0x80, 0xef, 0x1a, 0xee, 0x17, 0xc2, 0x03, 0x82, 0xf8, 0x63,
162153e4ad4SBenjamin Mugnier 0x80, 0xef, 0x1b, 0x80, 0x0b, 0x8e, 0xd8, 0x63, 0x80, 0xef, 0x1b, 0x8c,
163153e4ad4SBenjamin Mugnier 0x68, 0x63, 0x80, 0xef, 0x6b, 0x80, 0x0b, 0x92, 0x65, 0x54, 0x14, 0xe0,
164153e4ad4SBenjamin Mugnier 0x08, 0x65, 0x84, 0xef, 0x68, 0x63, 0x80, 0xef, 0x7b, 0x80, 0x0b, 0x8c,
165153e4ad4SBenjamin Mugnier 0xa8, 0x64, 0x84, 0xef, 0x08, 0x63, 0x80, 0xef, 0x14, 0xe8, 0x46, 0x44,
166153e4ad4SBenjamin Mugnier 0x94, 0xe1, 0x24, 0x88, 0x4a, 0x4e, 0x04, 0xe0, 0x14, 0xea, 0x1a, 0x04,
167153e4ad4SBenjamin Mugnier 0x08, 0xe0, 0x0a, 0x40, 0x84, 0xed, 0x0c, 0x04, 0x00, 0xe2, 0x4a, 0x40,
168153e4ad4SBenjamin Mugnier 0x04, 0xe0, 0x19, 0x16, 0xc0, 0xe0, 0x0a, 0x40, 0x84, 0xed, 0x21, 0x54,
169153e4ad4SBenjamin Mugnier 0x60, 0xe0, 0x0c, 0x04, 0x00, 0xe2, 0x1b, 0xa5, 0x0e, 0xea, 0x01, 0x89,
170153e4ad4SBenjamin Mugnier 0x21, 0x54, 0x64, 0xe0, 0x7e, 0xe8, 0x65, 0x82, 0x1b, 0xa7, 0x26, 0x00,
171153e4ad4SBenjamin Mugnier 0x00, 0x80, 0xa5, 0x82, 0x1b, 0xa9, 0x65, 0x82, 0x1b, 0xa3, 0x01, 0x85,
172153e4ad4SBenjamin Mugnier 0x16, 0x00, 0x00, 0xc0, 0x01, 0x54, 0x04, 0xf8, 0x06, 0xaa, 0x01, 0x83,
173153e4ad4SBenjamin Mugnier 0x06, 0xa8, 0x65, 0x81, 0x06, 0xa8, 0x01, 0x54, 0x04, 0xf8, 0x01, 0x83,
174153e4ad4SBenjamin Mugnier 0x06, 0xaa, 0x09, 0x14, 0x18, 0xf8, 0x0b, 0xa1, 0x05, 0x84, 0xc6, 0x42,
175153e4ad4SBenjamin Mugnier 0xd4, 0xe0, 0x14, 0x84, 0x01, 0x83, 0x01, 0x54, 0x60, 0xe0, 0x01, 0x54,
176153e4ad4SBenjamin Mugnier 0x64, 0xe0, 0x0b, 0x02, 0x90, 0xe0, 0x10, 0x02, 0x90, 0xe5, 0x01, 0x54,
177153e4ad4SBenjamin Mugnier 0x88, 0xe0, 0xb5, 0x81, 0xc6, 0x40, 0xd4, 0xe0, 0x14, 0x80, 0x0b, 0x02,
178153e4ad4SBenjamin Mugnier 0xe0, 0xe4, 0x10, 0x02, 0x31, 0x66, 0x02, 0xc0, 0x01, 0x54, 0x88, 0xe0,
179153e4ad4SBenjamin Mugnier 0x1a, 0x84, 0x29, 0x14, 0x10, 0xe0, 0x1c, 0xaa, 0x2b, 0xa1, 0xf5, 0x82,
180153e4ad4SBenjamin Mugnier 0x25, 0x14, 0x10, 0xf8, 0x2b, 0x04, 0xa8, 0xe0, 0x20, 0x44, 0x0d, 0x70,
181153e4ad4SBenjamin Mugnier 0x03, 0xc0, 0x2b, 0xa1, 0x04, 0x00, 0x80, 0x9a, 0x02, 0x40, 0x84, 0x90,
182153e4ad4SBenjamin Mugnier 0x03, 0x54, 0x04, 0x80, 0x4c, 0x0c, 0x7c, 0xf2, 0x93, 0xdd, 0x00, 0x00,
183153e4ad4SBenjamin Mugnier 0x02, 0xa9, 0x00, 0x00, 0x64, 0x4a, 0x40, 0x00, 0x08, 0x2d, 0x58, 0xe0,
184153e4ad4SBenjamin Mugnier 0xa8, 0x98, 0x40, 0x00, 0x28, 0x07, 0x34, 0xe0, 0x05, 0xb9, 0x00, 0x00,
185153e4ad4SBenjamin Mugnier 0x28, 0x00, 0x41, 0x05, 0x88, 0x00, 0x41, 0x3c, 0x98, 0x00, 0x41, 0x52,
186153e4ad4SBenjamin Mugnier 0x04, 0x01, 0x41, 0x79, 0x3c, 0x01, 0x41, 0x6a, 0x3d, 0xfe, 0x00, 0x00,
187153e4ad4SBenjamin Mugnier };
188153e4ad4SBenjamin Mugnier
189153e4ad4SBenjamin Mugnier static const char * const vgxy61_test_pattern_menu[] = {
190153e4ad4SBenjamin Mugnier "Disabled",
191153e4ad4SBenjamin Mugnier "Solid",
192153e4ad4SBenjamin Mugnier "Colorbar",
193153e4ad4SBenjamin Mugnier "Gradbar",
194153e4ad4SBenjamin Mugnier "Hgrey",
195153e4ad4SBenjamin Mugnier "Vgrey",
196153e4ad4SBenjamin Mugnier "Dgrey",
197153e4ad4SBenjamin Mugnier "PN28",
198153e4ad4SBenjamin Mugnier };
199153e4ad4SBenjamin Mugnier
200153e4ad4SBenjamin Mugnier static const char * const vgxy61_hdr_mode_menu[] = {
201153e4ad4SBenjamin Mugnier "HDR linearize",
202153e4ad4SBenjamin Mugnier "HDR substraction",
203153e4ad4SBenjamin Mugnier "No HDR",
204153e4ad4SBenjamin Mugnier };
205153e4ad4SBenjamin Mugnier
206153e4ad4SBenjamin Mugnier static const char * const vgxy61_supply_name[] = {
207153e4ad4SBenjamin Mugnier "VCORE",
208153e4ad4SBenjamin Mugnier "VDDIO",
209153e4ad4SBenjamin Mugnier "VANA",
210153e4ad4SBenjamin Mugnier };
211153e4ad4SBenjamin Mugnier
212153e4ad4SBenjamin Mugnier static const s64 link_freq[] = {
213153e4ad4SBenjamin Mugnier /*
214153e4ad4SBenjamin Mugnier * MIPI output freq is 804Mhz / 2, as it uses both rising edge and
215153e4ad4SBenjamin Mugnier * falling edges to send data
216153e4ad4SBenjamin Mugnier */
217153e4ad4SBenjamin Mugnier 402000000ULL
218153e4ad4SBenjamin Mugnier };
219153e4ad4SBenjamin Mugnier
220153e4ad4SBenjamin Mugnier enum vgxy61_bin_mode {
221153e4ad4SBenjamin Mugnier VGXY61_BIN_MODE_NORMAL,
222153e4ad4SBenjamin Mugnier VGXY61_BIN_MODE_DIGITAL_X2,
223153e4ad4SBenjamin Mugnier VGXY61_BIN_MODE_DIGITAL_X4,
224153e4ad4SBenjamin Mugnier };
225153e4ad4SBenjamin Mugnier
226153e4ad4SBenjamin Mugnier enum vgxy61_hdr_mode {
227153e4ad4SBenjamin Mugnier VGXY61_HDR_LINEAR,
228153e4ad4SBenjamin Mugnier VGXY61_HDR_SUB,
229153e4ad4SBenjamin Mugnier VGXY61_NO_HDR,
230153e4ad4SBenjamin Mugnier };
231153e4ad4SBenjamin Mugnier
232153e4ad4SBenjamin Mugnier enum vgxy61_strobe_mode {
233153e4ad4SBenjamin Mugnier VGXY61_STROBE_DISABLED,
234153e4ad4SBenjamin Mugnier VGXY61_STROBE_LONG,
235153e4ad4SBenjamin Mugnier VGXY61_STROBE_ENABLED,
236153e4ad4SBenjamin Mugnier };
237153e4ad4SBenjamin Mugnier
238153e4ad4SBenjamin Mugnier struct vgxy61_mode_info {
239153e4ad4SBenjamin Mugnier u32 width;
240153e4ad4SBenjamin Mugnier u32 height;
241153e4ad4SBenjamin Mugnier enum vgxy61_bin_mode bin_mode;
242153e4ad4SBenjamin Mugnier struct v4l2_rect crop;
243153e4ad4SBenjamin Mugnier };
244153e4ad4SBenjamin Mugnier
245153e4ad4SBenjamin Mugnier struct vgxy61_fmt_desc {
246153e4ad4SBenjamin Mugnier u32 code;
247153e4ad4SBenjamin Mugnier u8 bpp;
248153e4ad4SBenjamin Mugnier u8 data_type;
249153e4ad4SBenjamin Mugnier };
250153e4ad4SBenjamin Mugnier
251153e4ad4SBenjamin Mugnier static const struct vgxy61_fmt_desc vgxy61_supported_codes[] = {
252153e4ad4SBenjamin Mugnier {
253153e4ad4SBenjamin Mugnier .code = MEDIA_BUS_FMT_Y8_1X8,
254153e4ad4SBenjamin Mugnier .bpp = 8,
255153e4ad4SBenjamin Mugnier .data_type = MIPI_CSI2_DT_RAW8,
256153e4ad4SBenjamin Mugnier },
257153e4ad4SBenjamin Mugnier {
258153e4ad4SBenjamin Mugnier .code = MEDIA_BUS_FMT_Y10_1X10,
259153e4ad4SBenjamin Mugnier .bpp = 10,
260153e4ad4SBenjamin Mugnier .data_type = MIPI_CSI2_DT_RAW10,
261153e4ad4SBenjamin Mugnier },
262153e4ad4SBenjamin Mugnier {
263153e4ad4SBenjamin Mugnier .code = MEDIA_BUS_FMT_Y12_1X12,
264153e4ad4SBenjamin Mugnier .bpp = 12,
265153e4ad4SBenjamin Mugnier .data_type = MIPI_CSI2_DT_RAW12,
266153e4ad4SBenjamin Mugnier },
267153e4ad4SBenjamin Mugnier {
268153e4ad4SBenjamin Mugnier .code = MEDIA_BUS_FMT_Y14_1X14,
269153e4ad4SBenjamin Mugnier .bpp = 14,
270153e4ad4SBenjamin Mugnier .data_type = MIPI_CSI2_DT_RAW14,
271153e4ad4SBenjamin Mugnier },
272153e4ad4SBenjamin Mugnier {
273153e4ad4SBenjamin Mugnier .code = MEDIA_BUS_FMT_Y16_1X16,
274153e4ad4SBenjamin Mugnier .bpp = 16,
275153e4ad4SBenjamin Mugnier .data_type = MIPI_CSI2_DT_RAW16,
276153e4ad4SBenjamin Mugnier },
277153e4ad4SBenjamin Mugnier };
278153e4ad4SBenjamin Mugnier
279153e4ad4SBenjamin Mugnier static const struct vgxy61_mode_info vgx661_mode_data[] = {
280153e4ad4SBenjamin Mugnier {
281153e4ad4SBenjamin Mugnier .width = VGX661_WIDTH,
282153e4ad4SBenjamin Mugnier .height = VGX661_HEIGHT,
283153e4ad4SBenjamin Mugnier .bin_mode = VGXY61_BIN_MODE_NORMAL,
284153e4ad4SBenjamin Mugnier .crop = {
285153e4ad4SBenjamin Mugnier .left = 0,
286153e4ad4SBenjamin Mugnier .top = 0,
287153e4ad4SBenjamin Mugnier .width = VGX661_WIDTH,
288153e4ad4SBenjamin Mugnier .height = VGX661_HEIGHT,
289153e4ad4SBenjamin Mugnier },
290153e4ad4SBenjamin Mugnier },
291153e4ad4SBenjamin Mugnier {
292153e4ad4SBenjamin Mugnier .width = 1280,
293153e4ad4SBenjamin Mugnier .height = 720,
294153e4ad4SBenjamin Mugnier .bin_mode = VGXY61_BIN_MODE_NORMAL,
295153e4ad4SBenjamin Mugnier .crop = {
296153e4ad4SBenjamin Mugnier .left = 92,
297153e4ad4SBenjamin Mugnier .top = 192,
298153e4ad4SBenjamin Mugnier .width = 1280,
299153e4ad4SBenjamin Mugnier .height = 720,
300153e4ad4SBenjamin Mugnier },
301153e4ad4SBenjamin Mugnier },
302153e4ad4SBenjamin Mugnier {
303153e4ad4SBenjamin Mugnier .width = 640,
304153e4ad4SBenjamin Mugnier .height = 480,
305153e4ad4SBenjamin Mugnier .bin_mode = VGXY61_BIN_MODE_DIGITAL_X2,
306153e4ad4SBenjamin Mugnier .crop = {
307153e4ad4SBenjamin Mugnier .left = 92,
308153e4ad4SBenjamin Mugnier .top = 72,
309153e4ad4SBenjamin Mugnier .width = 1280,
310153e4ad4SBenjamin Mugnier .height = 960,
311153e4ad4SBenjamin Mugnier },
312153e4ad4SBenjamin Mugnier },
313153e4ad4SBenjamin Mugnier {
314153e4ad4SBenjamin Mugnier .width = 320,
315153e4ad4SBenjamin Mugnier .height = 240,
316153e4ad4SBenjamin Mugnier .bin_mode = VGXY61_BIN_MODE_DIGITAL_X4,
317153e4ad4SBenjamin Mugnier .crop = {
318153e4ad4SBenjamin Mugnier .left = 92,
319153e4ad4SBenjamin Mugnier .top = 72,
320153e4ad4SBenjamin Mugnier .width = 1280,
321153e4ad4SBenjamin Mugnier .height = 960,
322153e4ad4SBenjamin Mugnier },
323153e4ad4SBenjamin Mugnier },
324153e4ad4SBenjamin Mugnier };
325153e4ad4SBenjamin Mugnier
326153e4ad4SBenjamin Mugnier static const struct vgxy61_mode_info vgx761_mode_data[] = {
327153e4ad4SBenjamin Mugnier {
328153e4ad4SBenjamin Mugnier .width = VGX761_WIDTH,
329153e4ad4SBenjamin Mugnier .height = VGX761_HEIGHT,
330153e4ad4SBenjamin Mugnier .bin_mode = VGXY61_BIN_MODE_NORMAL,
331153e4ad4SBenjamin Mugnier .crop = {
332153e4ad4SBenjamin Mugnier .left = 0,
333153e4ad4SBenjamin Mugnier .top = 0,
334153e4ad4SBenjamin Mugnier .width = VGX761_WIDTH,
335153e4ad4SBenjamin Mugnier .height = VGX761_HEIGHT,
336153e4ad4SBenjamin Mugnier },
337153e4ad4SBenjamin Mugnier },
338153e4ad4SBenjamin Mugnier {
339153e4ad4SBenjamin Mugnier .width = 1920,
340153e4ad4SBenjamin Mugnier .height = 1080,
341153e4ad4SBenjamin Mugnier .bin_mode = VGXY61_BIN_MODE_NORMAL,
342153e4ad4SBenjamin Mugnier .crop = {
343153e4ad4SBenjamin Mugnier .left = 12,
344153e4ad4SBenjamin Mugnier .top = 62,
345153e4ad4SBenjamin Mugnier .width = 1920,
346153e4ad4SBenjamin Mugnier .height = 1080,
347153e4ad4SBenjamin Mugnier },
348153e4ad4SBenjamin Mugnier },
349153e4ad4SBenjamin Mugnier {
350153e4ad4SBenjamin Mugnier .width = 1280,
351153e4ad4SBenjamin Mugnier .height = 720,
352153e4ad4SBenjamin Mugnier .bin_mode = VGXY61_BIN_MODE_NORMAL,
353153e4ad4SBenjamin Mugnier .crop = {
354153e4ad4SBenjamin Mugnier .left = 332,
355153e4ad4SBenjamin Mugnier .top = 242,
356153e4ad4SBenjamin Mugnier .width = 1280,
357153e4ad4SBenjamin Mugnier .height = 720,
358153e4ad4SBenjamin Mugnier },
359153e4ad4SBenjamin Mugnier },
360153e4ad4SBenjamin Mugnier {
361153e4ad4SBenjamin Mugnier .width = 640,
362153e4ad4SBenjamin Mugnier .height = 480,
363153e4ad4SBenjamin Mugnier .bin_mode = VGXY61_BIN_MODE_DIGITAL_X2,
364153e4ad4SBenjamin Mugnier .crop = {
365153e4ad4SBenjamin Mugnier .left = 332,
366153e4ad4SBenjamin Mugnier .top = 122,
367153e4ad4SBenjamin Mugnier .width = 1280,
368153e4ad4SBenjamin Mugnier .height = 960,
369153e4ad4SBenjamin Mugnier },
370153e4ad4SBenjamin Mugnier },
371153e4ad4SBenjamin Mugnier {
372153e4ad4SBenjamin Mugnier .width = 320,
373153e4ad4SBenjamin Mugnier .height = 240,
374153e4ad4SBenjamin Mugnier .bin_mode = VGXY61_BIN_MODE_DIGITAL_X4,
375153e4ad4SBenjamin Mugnier .crop = {
376153e4ad4SBenjamin Mugnier .left = 332,
377153e4ad4SBenjamin Mugnier .top = 122,
378153e4ad4SBenjamin Mugnier .width = 1280,
379153e4ad4SBenjamin Mugnier .height = 960,
380153e4ad4SBenjamin Mugnier },
381153e4ad4SBenjamin Mugnier },
382153e4ad4SBenjamin Mugnier };
383153e4ad4SBenjamin Mugnier
384153e4ad4SBenjamin Mugnier struct vgxy61_dev {
385153e4ad4SBenjamin Mugnier struct i2c_client *i2c_client;
386153e4ad4SBenjamin Mugnier struct v4l2_subdev sd;
387153e4ad4SBenjamin Mugnier struct media_pad pad;
388153e4ad4SBenjamin Mugnier struct regulator_bulk_data supplies[ARRAY_SIZE(vgxy61_supply_name)];
389153e4ad4SBenjamin Mugnier struct gpio_desc *reset_gpio;
390153e4ad4SBenjamin Mugnier struct clk *xclk;
391153e4ad4SBenjamin Mugnier u32 clk_freq;
392153e4ad4SBenjamin Mugnier u16 id;
393153e4ad4SBenjamin Mugnier u16 sensor_width;
394153e4ad4SBenjamin Mugnier u16 sensor_height;
395153e4ad4SBenjamin Mugnier u16 oif_ctrl;
396153e4ad4SBenjamin Mugnier unsigned int nb_of_lane;
397153e4ad4SBenjamin Mugnier u32 data_rate_in_mbps;
398153e4ad4SBenjamin Mugnier u32 pclk;
399153e4ad4SBenjamin Mugnier u16 line_length;
400153e4ad4SBenjamin Mugnier u16 rot_term;
401153e4ad4SBenjamin Mugnier bool gpios_polarity;
402153e4ad4SBenjamin Mugnier /* Lock to protect all members below */
403153e4ad4SBenjamin Mugnier struct mutex lock;
404153e4ad4SBenjamin Mugnier struct v4l2_ctrl_handler ctrl_handler;
405153e4ad4SBenjamin Mugnier struct v4l2_ctrl *pixel_rate_ctrl;
406153e4ad4SBenjamin Mugnier struct v4l2_ctrl *expo_ctrl;
407153e4ad4SBenjamin Mugnier struct v4l2_ctrl *vblank_ctrl;
408153e4ad4SBenjamin Mugnier struct v4l2_ctrl *vflip_ctrl;
409153e4ad4SBenjamin Mugnier struct v4l2_ctrl *hflip_ctrl;
410153e4ad4SBenjamin Mugnier bool streaming;
411153e4ad4SBenjamin Mugnier struct v4l2_mbus_framefmt fmt;
412153e4ad4SBenjamin Mugnier const struct vgxy61_mode_info *sensor_modes;
413153e4ad4SBenjamin Mugnier unsigned int sensor_modes_nb;
414153e4ad4SBenjamin Mugnier const struct vgxy61_mode_info *default_mode;
415153e4ad4SBenjamin Mugnier const struct vgxy61_mode_info *current_mode;
416153e4ad4SBenjamin Mugnier bool hflip;
417153e4ad4SBenjamin Mugnier bool vflip;
418153e4ad4SBenjamin Mugnier enum vgxy61_hdr_mode hdr;
419153e4ad4SBenjamin Mugnier u16 expo_long;
420153e4ad4SBenjamin Mugnier u16 expo_short;
421153e4ad4SBenjamin Mugnier u16 expo_max;
422153e4ad4SBenjamin Mugnier u16 expo_min;
423153e4ad4SBenjamin Mugnier u16 vblank;
424153e4ad4SBenjamin Mugnier u16 vblank_min;
425153e4ad4SBenjamin Mugnier u16 frame_length;
426153e4ad4SBenjamin Mugnier u16 digital_gain;
427153e4ad4SBenjamin Mugnier u8 analog_gain;
428153e4ad4SBenjamin Mugnier enum vgxy61_strobe_mode strobe_mode;
429153e4ad4SBenjamin Mugnier u32 pattern;
430153e4ad4SBenjamin Mugnier };
431153e4ad4SBenjamin Mugnier
get_bpp_by_code(__u32 code)432153e4ad4SBenjamin Mugnier static u8 get_bpp_by_code(__u32 code)
433153e4ad4SBenjamin Mugnier {
434153e4ad4SBenjamin Mugnier unsigned int i;
435153e4ad4SBenjamin Mugnier
436153e4ad4SBenjamin Mugnier for (i = 0; i < ARRAY_SIZE(vgxy61_supported_codes); i++) {
437153e4ad4SBenjamin Mugnier if (vgxy61_supported_codes[i].code == code)
438153e4ad4SBenjamin Mugnier return vgxy61_supported_codes[i].bpp;
439153e4ad4SBenjamin Mugnier }
440153e4ad4SBenjamin Mugnier /* Should never happen */
441153e4ad4SBenjamin Mugnier WARN(1, "Unsupported code %d. default to 8 bpp", code);
442153e4ad4SBenjamin Mugnier return 8;
443153e4ad4SBenjamin Mugnier }
444153e4ad4SBenjamin Mugnier
get_data_type_by_code(__u32 code)445153e4ad4SBenjamin Mugnier static u8 get_data_type_by_code(__u32 code)
446153e4ad4SBenjamin Mugnier {
447153e4ad4SBenjamin Mugnier unsigned int i;
448153e4ad4SBenjamin Mugnier
449153e4ad4SBenjamin Mugnier for (i = 0; i < ARRAY_SIZE(vgxy61_supported_codes); i++) {
450153e4ad4SBenjamin Mugnier if (vgxy61_supported_codes[i].code == code)
451153e4ad4SBenjamin Mugnier return vgxy61_supported_codes[i].data_type;
452153e4ad4SBenjamin Mugnier }
453153e4ad4SBenjamin Mugnier /* Should never happen */
454153e4ad4SBenjamin Mugnier WARN(1, "Unsupported code %d. default to MIPI_CSI2_DT_RAW8 data type",
455153e4ad4SBenjamin Mugnier code);
456153e4ad4SBenjamin Mugnier return MIPI_CSI2_DT_RAW8;
457153e4ad4SBenjamin Mugnier }
458153e4ad4SBenjamin Mugnier
compute_pll_parameters_by_freq(u32 freq,u8 * prediv,u8 * mult)459153e4ad4SBenjamin Mugnier static void compute_pll_parameters_by_freq(u32 freq, u8 *prediv, u8 *mult)
460153e4ad4SBenjamin Mugnier {
461153e4ad4SBenjamin Mugnier const unsigned int predivs[] = {1, 2, 4};
462153e4ad4SBenjamin Mugnier unsigned int i;
463153e4ad4SBenjamin Mugnier
464153e4ad4SBenjamin Mugnier /*
465153e4ad4SBenjamin Mugnier * Freq range is [6Mhz-27Mhz] already checked.
466153e4ad4SBenjamin Mugnier * Output of divider should be in [6Mhz-12Mhz[.
467153e4ad4SBenjamin Mugnier */
468153e4ad4SBenjamin Mugnier for (i = 0; i < ARRAY_SIZE(predivs); i++) {
469153e4ad4SBenjamin Mugnier *prediv = predivs[i];
470153e4ad4SBenjamin Mugnier if (freq / *prediv < 12 * HZ_PER_MHZ)
471153e4ad4SBenjamin Mugnier break;
472153e4ad4SBenjamin Mugnier }
473153e4ad4SBenjamin Mugnier WARN_ON(i == ARRAY_SIZE(predivs));
474153e4ad4SBenjamin Mugnier
475153e4ad4SBenjamin Mugnier /*
476153e4ad4SBenjamin Mugnier * Target freq is 804Mhz. Don't change this as it will impact image
477153e4ad4SBenjamin Mugnier * quality.
478153e4ad4SBenjamin Mugnier */
479153e4ad4SBenjamin Mugnier *mult = ((804 * HZ_PER_MHZ) * (*prediv) + freq / 2) / freq;
480153e4ad4SBenjamin Mugnier }
481153e4ad4SBenjamin Mugnier
get_pixel_rate(struct vgxy61_dev * sensor)482153e4ad4SBenjamin Mugnier static s32 get_pixel_rate(struct vgxy61_dev *sensor)
483153e4ad4SBenjamin Mugnier {
484153e4ad4SBenjamin Mugnier return div64_u64((u64)sensor->data_rate_in_mbps * sensor->nb_of_lane,
485153e4ad4SBenjamin Mugnier get_bpp_by_code(sensor->fmt.code));
486153e4ad4SBenjamin Mugnier }
487153e4ad4SBenjamin Mugnier
to_vgxy61_dev(struct v4l2_subdev * sd)488153e4ad4SBenjamin Mugnier static inline struct vgxy61_dev *to_vgxy61_dev(struct v4l2_subdev *sd)
489153e4ad4SBenjamin Mugnier {
490153e4ad4SBenjamin Mugnier return container_of(sd, struct vgxy61_dev, sd);
491153e4ad4SBenjamin Mugnier }
492153e4ad4SBenjamin Mugnier
ctrl_to_sd(struct v4l2_ctrl * ctrl)493153e4ad4SBenjamin Mugnier static inline struct v4l2_subdev *ctrl_to_sd(struct v4l2_ctrl *ctrl)
494153e4ad4SBenjamin Mugnier {
495153e4ad4SBenjamin Mugnier return &container_of(ctrl->handler, struct vgxy61_dev,
496153e4ad4SBenjamin Mugnier ctrl_handler)->sd;
497153e4ad4SBenjamin Mugnier }
498153e4ad4SBenjamin Mugnier
get_chunk_size(struct vgxy61_dev * sensor)499153e4ad4SBenjamin Mugnier static unsigned int get_chunk_size(struct vgxy61_dev *sensor)
500153e4ad4SBenjamin Mugnier {
501153e4ad4SBenjamin Mugnier struct i2c_adapter *adapter = sensor->i2c_client->adapter;
502153e4ad4SBenjamin Mugnier int max_write_len = VGXY61_WRITE_MULTIPLE_CHUNK_MAX;
503153e4ad4SBenjamin Mugnier
504153e4ad4SBenjamin Mugnier if (adapter->quirks && adapter->quirks->max_write_len)
505153e4ad4SBenjamin Mugnier max_write_len = adapter->quirks->max_write_len - 2;
506153e4ad4SBenjamin Mugnier
507153e4ad4SBenjamin Mugnier max_write_len = min(max_write_len, VGXY61_WRITE_MULTIPLE_CHUNK_MAX);
508153e4ad4SBenjamin Mugnier
509153e4ad4SBenjamin Mugnier return max(max_write_len, 1);
510153e4ad4SBenjamin Mugnier }
511153e4ad4SBenjamin Mugnier
vgxy61_read_multiple(struct vgxy61_dev * sensor,u32 reg,unsigned int len)512153e4ad4SBenjamin Mugnier static int vgxy61_read_multiple(struct vgxy61_dev *sensor, u32 reg,
513153e4ad4SBenjamin Mugnier unsigned int len)
514153e4ad4SBenjamin Mugnier {
515153e4ad4SBenjamin Mugnier struct i2c_client *client = sensor->i2c_client;
516153e4ad4SBenjamin Mugnier struct i2c_msg msg[2];
517153e4ad4SBenjamin Mugnier u8 buf[2];
518153e4ad4SBenjamin Mugnier u8 val[sizeof(u32)] = {0};
519153e4ad4SBenjamin Mugnier int ret;
520153e4ad4SBenjamin Mugnier
521153e4ad4SBenjamin Mugnier if (len > sizeof(u32))
522153e4ad4SBenjamin Mugnier return -EINVAL;
523153e4ad4SBenjamin Mugnier buf[0] = reg >> 8;
524153e4ad4SBenjamin Mugnier buf[1] = reg & 0xff;
525153e4ad4SBenjamin Mugnier
526153e4ad4SBenjamin Mugnier msg[0].addr = client->addr;
527153e4ad4SBenjamin Mugnier msg[0].flags = client->flags;
528153e4ad4SBenjamin Mugnier msg[0].buf = buf;
529153e4ad4SBenjamin Mugnier msg[0].len = sizeof(buf);
530153e4ad4SBenjamin Mugnier
531153e4ad4SBenjamin Mugnier msg[1].addr = client->addr;
532153e4ad4SBenjamin Mugnier msg[1].flags = client->flags | I2C_M_RD;
533153e4ad4SBenjamin Mugnier msg[1].buf = val;
534153e4ad4SBenjamin Mugnier msg[1].len = len;
535153e4ad4SBenjamin Mugnier
536153e4ad4SBenjamin Mugnier ret = i2c_transfer(client->adapter, msg, 2);
537153e4ad4SBenjamin Mugnier if (ret < 0) {
538153e4ad4SBenjamin Mugnier dev_dbg(&client->dev, "%s: %x i2c_transfer, reg: %x => %d\n",
539153e4ad4SBenjamin Mugnier __func__, client->addr, reg, ret);
540153e4ad4SBenjamin Mugnier return ret;
541153e4ad4SBenjamin Mugnier }
542153e4ad4SBenjamin Mugnier
543153e4ad4SBenjamin Mugnier return get_unaligned_le32(val);
544153e4ad4SBenjamin Mugnier }
545153e4ad4SBenjamin Mugnier
vgxy61_read_reg(struct vgxy61_dev * sensor,u32 reg)546153e4ad4SBenjamin Mugnier static inline int vgxy61_read_reg(struct vgxy61_dev *sensor, u32 reg)
547153e4ad4SBenjamin Mugnier {
548153e4ad4SBenjamin Mugnier return vgxy61_read_multiple(sensor, reg & VGXY61_REG_ADDR_MASK,
549153e4ad4SBenjamin Mugnier (reg >> VGXY61_REG_SIZE_SHIFT) & 7);
550153e4ad4SBenjamin Mugnier }
551153e4ad4SBenjamin Mugnier
vgxy61_write_multiple(struct vgxy61_dev * sensor,u32 reg,const u8 * data,unsigned int len,int * err)552153e4ad4SBenjamin Mugnier static int vgxy61_write_multiple(struct vgxy61_dev *sensor, u32 reg,
553153e4ad4SBenjamin Mugnier const u8 *data, unsigned int len, int *err)
554153e4ad4SBenjamin Mugnier {
555153e4ad4SBenjamin Mugnier struct i2c_client *client = sensor->i2c_client;
556153e4ad4SBenjamin Mugnier struct i2c_msg msg;
557153e4ad4SBenjamin Mugnier u8 buf[VGXY61_WRITE_MULTIPLE_CHUNK_MAX + 2];
558153e4ad4SBenjamin Mugnier unsigned int i;
559153e4ad4SBenjamin Mugnier int ret;
560153e4ad4SBenjamin Mugnier
561153e4ad4SBenjamin Mugnier if (err && *err)
562153e4ad4SBenjamin Mugnier return *err;
563153e4ad4SBenjamin Mugnier
564153e4ad4SBenjamin Mugnier if (len > VGXY61_WRITE_MULTIPLE_CHUNK_MAX)
565153e4ad4SBenjamin Mugnier return -EINVAL;
566153e4ad4SBenjamin Mugnier buf[0] = reg >> 8;
567153e4ad4SBenjamin Mugnier buf[1] = reg & 0xff;
568153e4ad4SBenjamin Mugnier for (i = 0; i < len; i++)
569153e4ad4SBenjamin Mugnier buf[i + 2] = data[i];
570153e4ad4SBenjamin Mugnier
571153e4ad4SBenjamin Mugnier msg.addr = client->addr;
572153e4ad4SBenjamin Mugnier msg.flags = client->flags;
573153e4ad4SBenjamin Mugnier msg.buf = buf;
574153e4ad4SBenjamin Mugnier msg.len = len + 2;
575153e4ad4SBenjamin Mugnier
576153e4ad4SBenjamin Mugnier ret = i2c_transfer(client->adapter, &msg, 1);
577153e4ad4SBenjamin Mugnier if (ret < 0) {
578153e4ad4SBenjamin Mugnier dev_dbg(&client->dev, "%s: i2c_transfer, reg: %x => %d\n",
579153e4ad4SBenjamin Mugnier __func__, reg, ret);
580153e4ad4SBenjamin Mugnier if (err)
581153e4ad4SBenjamin Mugnier *err = ret;
582153e4ad4SBenjamin Mugnier return ret;
583153e4ad4SBenjamin Mugnier }
584153e4ad4SBenjamin Mugnier
585153e4ad4SBenjamin Mugnier return 0;
586153e4ad4SBenjamin Mugnier }
587153e4ad4SBenjamin Mugnier
vgxy61_write_array(struct vgxy61_dev * sensor,u32 reg,unsigned int nb,const u8 * array)588153e4ad4SBenjamin Mugnier static int vgxy61_write_array(struct vgxy61_dev *sensor, u32 reg,
589153e4ad4SBenjamin Mugnier unsigned int nb, const u8 *array)
590153e4ad4SBenjamin Mugnier {
591153e4ad4SBenjamin Mugnier const unsigned int chunk_size = get_chunk_size(sensor);
592153e4ad4SBenjamin Mugnier int ret;
593153e4ad4SBenjamin Mugnier unsigned int sz;
594153e4ad4SBenjamin Mugnier
595153e4ad4SBenjamin Mugnier while (nb) {
596153e4ad4SBenjamin Mugnier sz = min(nb, chunk_size);
597153e4ad4SBenjamin Mugnier ret = vgxy61_write_multiple(sensor, reg, array, sz, NULL);
598153e4ad4SBenjamin Mugnier if (ret < 0)
599153e4ad4SBenjamin Mugnier return ret;
600153e4ad4SBenjamin Mugnier nb -= sz;
601153e4ad4SBenjamin Mugnier reg += sz;
602153e4ad4SBenjamin Mugnier array += sz;
603153e4ad4SBenjamin Mugnier }
604153e4ad4SBenjamin Mugnier
605153e4ad4SBenjamin Mugnier return 0;
606153e4ad4SBenjamin Mugnier }
607153e4ad4SBenjamin Mugnier
vgxy61_write_reg(struct vgxy61_dev * sensor,u32 reg,u32 val,int * err)608153e4ad4SBenjamin Mugnier static inline int vgxy61_write_reg(struct vgxy61_dev *sensor, u32 reg, u32 val,
609153e4ad4SBenjamin Mugnier int *err)
610153e4ad4SBenjamin Mugnier {
611153e4ad4SBenjamin Mugnier return vgxy61_write_multiple(sensor, reg & VGXY61_REG_ADDR_MASK,
612153e4ad4SBenjamin Mugnier (u8 *)&val,
613153e4ad4SBenjamin Mugnier (reg >> VGXY61_REG_SIZE_SHIFT) & 7, err);
614153e4ad4SBenjamin Mugnier }
615153e4ad4SBenjamin Mugnier
vgxy61_poll_reg(struct vgxy61_dev * sensor,u32 reg,u8 poll_val,unsigned int timeout_ms)616153e4ad4SBenjamin Mugnier static int vgxy61_poll_reg(struct vgxy61_dev *sensor, u32 reg, u8 poll_val,
617153e4ad4SBenjamin Mugnier unsigned int timeout_ms)
618153e4ad4SBenjamin Mugnier {
619153e4ad4SBenjamin Mugnier const unsigned int loop_delay_ms = 10;
620153e4ad4SBenjamin Mugnier int ret;
621153e4ad4SBenjamin Mugnier
622153e4ad4SBenjamin Mugnier return read_poll_timeout(vgxy61_read_reg, ret,
623153e4ad4SBenjamin Mugnier ((ret < 0) || (ret == poll_val)),
624153e4ad4SBenjamin Mugnier loop_delay_ms * 1000, timeout_ms * 1000,
625153e4ad4SBenjamin Mugnier false, sensor, reg);
626153e4ad4SBenjamin Mugnier }
627153e4ad4SBenjamin Mugnier
vgxy61_wait_state(struct vgxy61_dev * sensor,int state,unsigned int timeout_ms)628153e4ad4SBenjamin Mugnier static int vgxy61_wait_state(struct vgxy61_dev *sensor, int state,
629153e4ad4SBenjamin Mugnier unsigned int timeout_ms)
630153e4ad4SBenjamin Mugnier {
631153e4ad4SBenjamin Mugnier return vgxy61_poll_reg(sensor, VGXY61_REG_SYSTEM_FSM, state,
632153e4ad4SBenjamin Mugnier timeout_ms);
633153e4ad4SBenjamin Mugnier }
634153e4ad4SBenjamin Mugnier
vgxy61_check_bw(struct vgxy61_dev * sensor)635153e4ad4SBenjamin Mugnier static int vgxy61_check_bw(struct vgxy61_dev *sensor)
636153e4ad4SBenjamin Mugnier {
637153e4ad4SBenjamin Mugnier /*
638153e4ad4SBenjamin Mugnier * Simplification of time needed to send short packets and for the MIPI
639153e4ad4SBenjamin Mugnier * to add transition times (EoT, LPS, and SoT packet delimiters) needed
640153e4ad4SBenjamin Mugnier * by the protocol to go in low power between 2 packets of data. This
641153e4ad4SBenjamin Mugnier * is a mipi IP constant for the sensor.
642153e4ad4SBenjamin Mugnier */
643153e4ad4SBenjamin Mugnier const unsigned int mipi_margin = 1056;
644153e4ad4SBenjamin Mugnier unsigned int binning_scale = sensor->current_mode->crop.height /
645153e4ad4SBenjamin Mugnier sensor->current_mode->height;
646153e4ad4SBenjamin Mugnier u8 bpp = get_bpp_by_code(sensor->fmt.code);
647153e4ad4SBenjamin Mugnier unsigned int max_bit_per_line;
648153e4ad4SBenjamin Mugnier unsigned int bit_per_line;
649153e4ad4SBenjamin Mugnier u64 line_rate;
650153e4ad4SBenjamin Mugnier
651153e4ad4SBenjamin Mugnier line_rate = sensor->nb_of_lane * (u64)sensor->data_rate_in_mbps *
652153e4ad4SBenjamin Mugnier sensor->line_length;
653153e4ad4SBenjamin Mugnier max_bit_per_line = div64_u64(line_rate, sensor->pclk) - mipi_margin;
654153e4ad4SBenjamin Mugnier bit_per_line = (bpp * sensor->current_mode->width) / binning_scale;
655153e4ad4SBenjamin Mugnier
656153e4ad4SBenjamin Mugnier return bit_per_line > max_bit_per_line ? -EINVAL : 0;
657153e4ad4SBenjamin Mugnier }
658153e4ad4SBenjamin Mugnier
vgxy61_apply_exposure(struct vgxy61_dev * sensor)659153e4ad4SBenjamin Mugnier static int vgxy61_apply_exposure(struct vgxy61_dev *sensor)
660153e4ad4SBenjamin Mugnier {
661153e4ad4SBenjamin Mugnier int ret = 0;
662153e4ad4SBenjamin Mugnier
663153e4ad4SBenjamin Mugnier /* We first set expo to zero to avoid forbidden parameters couple */
664153e4ad4SBenjamin Mugnier vgxy61_write_reg(sensor, VGXY61_REG_COARSE_EXPOSURE_SHORT, 0, &ret);
665153e4ad4SBenjamin Mugnier vgxy61_write_reg(sensor, VGXY61_REG_COARSE_EXPOSURE_LONG,
666153e4ad4SBenjamin Mugnier sensor->expo_long, &ret);
667153e4ad4SBenjamin Mugnier vgxy61_write_reg(sensor, VGXY61_REG_COARSE_EXPOSURE_SHORT,
668153e4ad4SBenjamin Mugnier sensor->expo_short, &ret);
669153e4ad4SBenjamin Mugnier
670153e4ad4SBenjamin Mugnier return ret;
671153e4ad4SBenjamin Mugnier }
672153e4ad4SBenjamin Mugnier
vgxy61_get_regulators(struct vgxy61_dev * sensor)673153e4ad4SBenjamin Mugnier static int vgxy61_get_regulators(struct vgxy61_dev *sensor)
674153e4ad4SBenjamin Mugnier {
675153e4ad4SBenjamin Mugnier unsigned int i;
676153e4ad4SBenjamin Mugnier
677153e4ad4SBenjamin Mugnier for (i = 0; i < ARRAY_SIZE(vgxy61_supply_name); i++)
678153e4ad4SBenjamin Mugnier sensor->supplies[i].supply = vgxy61_supply_name[i];
679153e4ad4SBenjamin Mugnier
680153e4ad4SBenjamin Mugnier return devm_regulator_bulk_get(&sensor->i2c_client->dev,
681153e4ad4SBenjamin Mugnier ARRAY_SIZE(vgxy61_supply_name),
682153e4ad4SBenjamin Mugnier sensor->supplies);
683153e4ad4SBenjamin Mugnier }
684153e4ad4SBenjamin Mugnier
vgxy61_apply_reset(struct vgxy61_dev * sensor)685153e4ad4SBenjamin Mugnier static int vgxy61_apply_reset(struct vgxy61_dev *sensor)
686153e4ad4SBenjamin Mugnier {
687153e4ad4SBenjamin Mugnier gpiod_set_value_cansleep(sensor->reset_gpio, 0);
688153e4ad4SBenjamin Mugnier usleep_range(5000, 10000);
689153e4ad4SBenjamin Mugnier gpiod_set_value_cansleep(sensor->reset_gpio, 1);
690153e4ad4SBenjamin Mugnier usleep_range(5000, 10000);
691153e4ad4SBenjamin Mugnier gpiod_set_value_cansleep(sensor->reset_gpio, 0);
692153e4ad4SBenjamin Mugnier usleep_range(40000, 100000);
693153e4ad4SBenjamin Mugnier return vgxy61_wait_state(sensor, VGXY61_SYSTEM_FSM_SW_STBY,
694153e4ad4SBenjamin Mugnier VGXY61_TIMEOUT_MS);
695153e4ad4SBenjamin Mugnier }
696153e4ad4SBenjamin Mugnier
vgxy61_fill_framefmt(struct vgxy61_dev * sensor,const struct vgxy61_mode_info * mode,struct v4l2_mbus_framefmt * fmt,u32 code)697153e4ad4SBenjamin Mugnier static void vgxy61_fill_framefmt(struct vgxy61_dev *sensor,
698153e4ad4SBenjamin Mugnier const struct vgxy61_mode_info *mode,
699153e4ad4SBenjamin Mugnier struct v4l2_mbus_framefmt *fmt, u32 code)
700153e4ad4SBenjamin Mugnier {
701153e4ad4SBenjamin Mugnier fmt->code = code;
702153e4ad4SBenjamin Mugnier fmt->width = mode->width;
703153e4ad4SBenjamin Mugnier fmt->height = mode->height;
704153e4ad4SBenjamin Mugnier fmt->colorspace = V4L2_COLORSPACE_RAW;
705153e4ad4SBenjamin Mugnier fmt->field = V4L2_FIELD_NONE;
706153e4ad4SBenjamin Mugnier fmt->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
707153e4ad4SBenjamin Mugnier fmt->quantization = V4L2_QUANTIZATION_DEFAULT;
708153e4ad4SBenjamin Mugnier fmt->xfer_func = V4L2_XFER_FUNC_DEFAULT;
709153e4ad4SBenjamin Mugnier }
710153e4ad4SBenjamin Mugnier
vgxy61_try_fmt_internal(struct v4l2_subdev * sd,struct v4l2_mbus_framefmt * fmt,const struct vgxy61_mode_info ** new_mode)711153e4ad4SBenjamin Mugnier static int vgxy61_try_fmt_internal(struct v4l2_subdev *sd,
712153e4ad4SBenjamin Mugnier struct v4l2_mbus_framefmt *fmt,
713153e4ad4SBenjamin Mugnier const struct vgxy61_mode_info **new_mode)
714153e4ad4SBenjamin Mugnier {
715153e4ad4SBenjamin Mugnier struct vgxy61_dev *sensor = to_vgxy61_dev(sd);
716153e4ad4SBenjamin Mugnier const struct vgxy61_mode_info *mode = sensor->sensor_modes;
717153e4ad4SBenjamin Mugnier unsigned int index;
718153e4ad4SBenjamin Mugnier
719153e4ad4SBenjamin Mugnier for (index = 0; index < ARRAY_SIZE(vgxy61_supported_codes); index++) {
720153e4ad4SBenjamin Mugnier if (vgxy61_supported_codes[index].code == fmt->code)
721153e4ad4SBenjamin Mugnier break;
722153e4ad4SBenjamin Mugnier }
723153e4ad4SBenjamin Mugnier if (index == ARRAY_SIZE(vgxy61_supported_codes))
724153e4ad4SBenjamin Mugnier index = 0;
725153e4ad4SBenjamin Mugnier
726153e4ad4SBenjamin Mugnier mode = v4l2_find_nearest_size(sensor->sensor_modes,
727153e4ad4SBenjamin Mugnier sensor->sensor_modes_nb, width, height,
728153e4ad4SBenjamin Mugnier fmt->width, fmt->height);
729153e4ad4SBenjamin Mugnier if (new_mode)
730153e4ad4SBenjamin Mugnier *new_mode = mode;
731153e4ad4SBenjamin Mugnier
732153e4ad4SBenjamin Mugnier vgxy61_fill_framefmt(sensor, mode, fmt,
733153e4ad4SBenjamin Mugnier vgxy61_supported_codes[index].code);
734153e4ad4SBenjamin Mugnier
735153e4ad4SBenjamin Mugnier return 0;
736153e4ad4SBenjamin Mugnier }
737153e4ad4SBenjamin Mugnier
vgxy61_get_selection(struct v4l2_subdev * sd,struct v4l2_subdev_state * sd_state,struct v4l2_subdev_selection * sel)738153e4ad4SBenjamin Mugnier static int vgxy61_get_selection(struct v4l2_subdev *sd,
739153e4ad4SBenjamin Mugnier struct v4l2_subdev_state *sd_state,
740153e4ad4SBenjamin Mugnier struct v4l2_subdev_selection *sel)
741153e4ad4SBenjamin Mugnier {
742153e4ad4SBenjamin Mugnier struct vgxy61_dev *sensor = to_vgxy61_dev(sd);
743153e4ad4SBenjamin Mugnier
744153e4ad4SBenjamin Mugnier switch (sel->target) {
745153e4ad4SBenjamin Mugnier case V4L2_SEL_TGT_CROP:
746153e4ad4SBenjamin Mugnier sel->r = sensor->current_mode->crop;
747153e4ad4SBenjamin Mugnier return 0;
748153e4ad4SBenjamin Mugnier case V4L2_SEL_TGT_NATIVE_SIZE:
749153e4ad4SBenjamin Mugnier case V4L2_SEL_TGT_CROP_DEFAULT:
750153e4ad4SBenjamin Mugnier case V4L2_SEL_TGT_CROP_BOUNDS:
751153e4ad4SBenjamin Mugnier sel->r.top = 0;
752153e4ad4SBenjamin Mugnier sel->r.left = 0;
753153e4ad4SBenjamin Mugnier sel->r.width = sensor->sensor_width;
754153e4ad4SBenjamin Mugnier sel->r.height = sensor->sensor_height;
755153e4ad4SBenjamin Mugnier return 0;
756153e4ad4SBenjamin Mugnier }
757153e4ad4SBenjamin Mugnier
758153e4ad4SBenjamin Mugnier return -EINVAL;
759153e4ad4SBenjamin Mugnier }
760153e4ad4SBenjamin Mugnier
vgxy61_enum_mbus_code(struct v4l2_subdev * sd,struct v4l2_subdev_state * sd_state,struct v4l2_subdev_mbus_code_enum * code)761153e4ad4SBenjamin Mugnier static int vgxy61_enum_mbus_code(struct v4l2_subdev *sd,
762153e4ad4SBenjamin Mugnier struct v4l2_subdev_state *sd_state,
763153e4ad4SBenjamin Mugnier struct v4l2_subdev_mbus_code_enum *code)
764153e4ad4SBenjamin Mugnier {
765153e4ad4SBenjamin Mugnier if (code->index >= ARRAY_SIZE(vgxy61_supported_codes))
766153e4ad4SBenjamin Mugnier return -EINVAL;
767153e4ad4SBenjamin Mugnier
768153e4ad4SBenjamin Mugnier code->code = vgxy61_supported_codes[code->index].code;
769153e4ad4SBenjamin Mugnier
770153e4ad4SBenjamin Mugnier return 0;
771153e4ad4SBenjamin Mugnier }
772153e4ad4SBenjamin Mugnier
vgxy61_get_fmt(struct v4l2_subdev * sd,struct v4l2_subdev_state * sd_state,struct v4l2_subdev_format * format)773153e4ad4SBenjamin Mugnier static int vgxy61_get_fmt(struct v4l2_subdev *sd,
774153e4ad4SBenjamin Mugnier struct v4l2_subdev_state *sd_state,
775153e4ad4SBenjamin Mugnier struct v4l2_subdev_format *format)
776153e4ad4SBenjamin Mugnier {
777153e4ad4SBenjamin Mugnier struct vgxy61_dev *sensor = to_vgxy61_dev(sd);
778153e4ad4SBenjamin Mugnier struct v4l2_mbus_framefmt *fmt;
779153e4ad4SBenjamin Mugnier
780153e4ad4SBenjamin Mugnier mutex_lock(&sensor->lock);
781153e4ad4SBenjamin Mugnier
782153e4ad4SBenjamin Mugnier if (format->which == V4L2_SUBDEV_FORMAT_TRY)
783153e4ad4SBenjamin Mugnier fmt = v4l2_subdev_get_try_format(&sensor->sd, sd_state,
784153e4ad4SBenjamin Mugnier format->pad);
785153e4ad4SBenjamin Mugnier else
786153e4ad4SBenjamin Mugnier fmt = &sensor->fmt;
787153e4ad4SBenjamin Mugnier
788153e4ad4SBenjamin Mugnier format->format = *fmt;
789153e4ad4SBenjamin Mugnier
790153e4ad4SBenjamin Mugnier mutex_unlock(&sensor->lock);
791153e4ad4SBenjamin Mugnier
792153e4ad4SBenjamin Mugnier return 0;
793153e4ad4SBenjamin Mugnier }
794153e4ad4SBenjamin Mugnier
vgxy61_get_vblank_min(struct vgxy61_dev * sensor,enum vgxy61_hdr_mode hdr)795153e4ad4SBenjamin Mugnier static u16 vgxy61_get_vblank_min(struct vgxy61_dev *sensor,
796153e4ad4SBenjamin Mugnier enum vgxy61_hdr_mode hdr)
797153e4ad4SBenjamin Mugnier {
798153e4ad4SBenjamin Mugnier u16 min_vblank = VGXY61_MIN_FRAME_LENGTH -
799153e4ad4SBenjamin Mugnier sensor->current_mode->crop.height;
800153e4ad4SBenjamin Mugnier /* Ensure the first rule of thumb can't be negative */
801153e4ad4SBenjamin Mugnier u16 min_vblank_hdr = VGXY61_MIN_EXPOSURE + sensor->rot_term + 1;
802153e4ad4SBenjamin Mugnier
803153e4ad4SBenjamin Mugnier if (hdr != VGXY61_NO_HDR)
804153e4ad4SBenjamin Mugnier return max(min_vblank, min_vblank_hdr);
805153e4ad4SBenjamin Mugnier return min_vblank;
806153e4ad4SBenjamin Mugnier }
807153e4ad4SBenjamin Mugnier
vgxy61_enum_frame_size(struct v4l2_subdev * sd,struct v4l2_subdev_state * sd_state,struct v4l2_subdev_frame_size_enum * fse)808153e4ad4SBenjamin Mugnier static int vgxy61_enum_frame_size(struct v4l2_subdev *sd,
809153e4ad4SBenjamin Mugnier struct v4l2_subdev_state *sd_state,
810153e4ad4SBenjamin Mugnier struct v4l2_subdev_frame_size_enum *fse)
811153e4ad4SBenjamin Mugnier {
812153e4ad4SBenjamin Mugnier struct vgxy61_dev *sensor = to_vgxy61_dev(sd);
813153e4ad4SBenjamin Mugnier
814153e4ad4SBenjamin Mugnier if (fse->index >= sensor->sensor_modes_nb)
815153e4ad4SBenjamin Mugnier return -EINVAL;
816153e4ad4SBenjamin Mugnier
817153e4ad4SBenjamin Mugnier fse->min_width = sensor->sensor_modes[fse->index].width;
818153e4ad4SBenjamin Mugnier fse->max_width = fse->min_width;
819153e4ad4SBenjamin Mugnier fse->min_height = sensor->sensor_modes[fse->index].height;
820153e4ad4SBenjamin Mugnier fse->max_height = fse->min_height;
821153e4ad4SBenjamin Mugnier
822153e4ad4SBenjamin Mugnier return 0;
823153e4ad4SBenjamin Mugnier }
824153e4ad4SBenjamin Mugnier
vgxy61_update_analog_gain(struct vgxy61_dev * sensor,u32 target)825153e4ad4SBenjamin Mugnier static int vgxy61_update_analog_gain(struct vgxy61_dev *sensor, u32 target)
826153e4ad4SBenjamin Mugnier {
827153e4ad4SBenjamin Mugnier sensor->analog_gain = target;
828153e4ad4SBenjamin Mugnier
829153e4ad4SBenjamin Mugnier if (sensor->streaming)
830153e4ad4SBenjamin Mugnier return vgxy61_write_reg(sensor, VGXY61_REG_ANALOG_GAIN, target,
831153e4ad4SBenjamin Mugnier NULL);
832153e4ad4SBenjamin Mugnier return 0;
833153e4ad4SBenjamin Mugnier }
834153e4ad4SBenjamin Mugnier
vgxy61_apply_digital_gain(struct vgxy61_dev * sensor,u32 digital_gain)835153e4ad4SBenjamin Mugnier static int vgxy61_apply_digital_gain(struct vgxy61_dev *sensor,
836153e4ad4SBenjamin Mugnier u32 digital_gain)
837153e4ad4SBenjamin Mugnier {
838153e4ad4SBenjamin Mugnier int ret = 0;
839153e4ad4SBenjamin Mugnier
840153e4ad4SBenjamin Mugnier /*
841153e4ad4SBenjamin Mugnier * For a monochrome version, configuring DIGITAL_GAIN_LONG_CH0 and
842153e4ad4SBenjamin Mugnier * DIGITAL_GAIN_SHORT_CH0 is enough to configure the gain of all
843153e4ad4SBenjamin Mugnier * four sub pixels.
844153e4ad4SBenjamin Mugnier */
845153e4ad4SBenjamin Mugnier vgxy61_write_reg(sensor, VGXY61_REG_DIGITAL_GAIN_LONG, digital_gain,
846153e4ad4SBenjamin Mugnier &ret);
847153e4ad4SBenjamin Mugnier vgxy61_write_reg(sensor, VGXY61_REG_DIGITAL_GAIN_SHORT, digital_gain,
848153e4ad4SBenjamin Mugnier &ret);
849153e4ad4SBenjamin Mugnier
850153e4ad4SBenjamin Mugnier return ret;
851153e4ad4SBenjamin Mugnier }
852153e4ad4SBenjamin Mugnier
vgxy61_update_digital_gain(struct vgxy61_dev * sensor,u32 target)853153e4ad4SBenjamin Mugnier static int vgxy61_update_digital_gain(struct vgxy61_dev *sensor, u32 target)
854153e4ad4SBenjamin Mugnier {
855153e4ad4SBenjamin Mugnier sensor->digital_gain = target;
856153e4ad4SBenjamin Mugnier
857153e4ad4SBenjamin Mugnier if (sensor->streaming)
858153e4ad4SBenjamin Mugnier return vgxy61_apply_digital_gain(sensor, sensor->digital_gain);
859153e4ad4SBenjamin Mugnier return 0;
860153e4ad4SBenjamin Mugnier }
861153e4ad4SBenjamin Mugnier
vgxy61_apply_patgen(struct vgxy61_dev * sensor,u32 index)862153e4ad4SBenjamin Mugnier static int vgxy61_apply_patgen(struct vgxy61_dev *sensor, u32 index)
863153e4ad4SBenjamin Mugnier {
864153e4ad4SBenjamin Mugnier static const u8 index2val[] = {
865153e4ad4SBenjamin Mugnier 0x0, 0x1, 0x2, 0x3, 0x10, 0x11, 0x12, 0x13
866153e4ad4SBenjamin Mugnier };
867153e4ad4SBenjamin Mugnier u32 pattern = index2val[index];
868153e4ad4SBenjamin Mugnier u32 reg = (pattern << VGXY61_PATGEN_LONG_TYPE_SHIFT) |
869153e4ad4SBenjamin Mugnier (pattern << VGXY61_PATGEN_SHORT_TYPE_SHIFT);
870153e4ad4SBenjamin Mugnier
871153e4ad4SBenjamin Mugnier if (pattern)
872153e4ad4SBenjamin Mugnier reg |= VGXY61_PATGEN_LONG_ENABLE | VGXY61_PATGEN_SHORT_ENABLE;
873153e4ad4SBenjamin Mugnier return vgxy61_write_reg(sensor, VGXY61_REG_PATGEN_CTRL, reg, NULL);
874153e4ad4SBenjamin Mugnier }
875153e4ad4SBenjamin Mugnier
vgxy61_update_patgen(struct vgxy61_dev * sensor,u32 pattern)876153e4ad4SBenjamin Mugnier static int vgxy61_update_patgen(struct vgxy61_dev *sensor, u32 pattern)
877153e4ad4SBenjamin Mugnier {
878153e4ad4SBenjamin Mugnier sensor->pattern = pattern;
879153e4ad4SBenjamin Mugnier
880153e4ad4SBenjamin Mugnier if (sensor->streaming)
881153e4ad4SBenjamin Mugnier return vgxy61_apply_patgen(sensor, sensor->pattern);
882153e4ad4SBenjamin Mugnier return 0;
883153e4ad4SBenjamin Mugnier }
884153e4ad4SBenjamin Mugnier
vgxy61_apply_gpiox_strobe_mode(struct vgxy61_dev * sensor,enum vgxy61_strobe_mode mode,unsigned int idx)885153e4ad4SBenjamin Mugnier static int vgxy61_apply_gpiox_strobe_mode(struct vgxy61_dev *sensor,
886153e4ad4SBenjamin Mugnier enum vgxy61_strobe_mode mode,
887153e4ad4SBenjamin Mugnier unsigned int idx)
888153e4ad4SBenjamin Mugnier {
889153e4ad4SBenjamin Mugnier static const u8 index2val[] = {0x0, 0x1, 0x3};
890483af3feSBenjamin Mugnier int reg;
891153e4ad4SBenjamin Mugnier
892153e4ad4SBenjamin Mugnier reg = vgxy61_read_reg(sensor, VGXY61_REG_SIGNALS_CTRL);
893153e4ad4SBenjamin Mugnier if (reg < 0)
894153e4ad4SBenjamin Mugnier return reg;
895153e4ad4SBenjamin Mugnier reg &= ~(0xf << (idx * VGXY61_SIGNALS_GPIO_ID_SHIFT));
896153e4ad4SBenjamin Mugnier reg |= index2val[mode] << (idx * VGXY61_SIGNALS_GPIO_ID_SHIFT);
897153e4ad4SBenjamin Mugnier
898153e4ad4SBenjamin Mugnier return vgxy61_write_reg(sensor, VGXY61_REG_SIGNALS_CTRL, reg, NULL);
899153e4ad4SBenjamin Mugnier }
900153e4ad4SBenjamin Mugnier
vgxy61_update_gpios_strobe_mode(struct vgxy61_dev * sensor,enum vgxy61_hdr_mode hdr)901153e4ad4SBenjamin Mugnier static int vgxy61_update_gpios_strobe_mode(struct vgxy61_dev *sensor,
902153e4ad4SBenjamin Mugnier enum vgxy61_hdr_mode hdr)
903153e4ad4SBenjamin Mugnier {
904153e4ad4SBenjamin Mugnier unsigned int i;
905153e4ad4SBenjamin Mugnier int ret;
906153e4ad4SBenjamin Mugnier
907153e4ad4SBenjamin Mugnier switch (hdr) {
908153e4ad4SBenjamin Mugnier case VGXY61_HDR_LINEAR:
909153e4ad4SBenjamin Mugnier sensor->strobe_mode = VGXY61_STROBE_ENABLED;
910153e4ad4SBenjamin Mugnier break;
911153e4ad4SBenjamin Mugnier case VGXY61_HDR_SUB:
912153e4ad4SBenjamin Mugnier case VGXY61_NO_HDR:
913153e4ad4SBenjamin Mugnier sensor->strobe_mode = VGXY61_STROBE_LONG;
914153e4ad4SBenjamin Mugnier break;
915153e4ad4SBenjamin Mugnier default:
916153e4ad4SBenjamin Mugnier /* Should never happen */
917153e4ad4SBenjamin Mugnier WARN_ON(true);
918153e4ad4SBenjamin Mugnier break;
919153e4ad4SBenjamin Mugnier }
920153e4ad4SBenjamin Mugnier
921153e4ad4SBenjamin Mugnier if (!sensor->streaming)
922153e4ad4SBenjamin Mugnier return 0;
923153e4ad4SBenjamin Mugnier
924153e4ad4SBenjamin Mugnier for (i = 0; i < VGXY61_NB_GPIOS; i++) {
925153e4ad4SBenjamin Mugnier ret = vgxy61_apply_gpiox_strobe_mode(sensor,
926153e4ad4SBenjamin Mugnier sensor->strobe_mode,
927153e4ad4SBenjamin Mugnier i);
928153e4ad4SBenjamin Mugnier if (ret)
929153e4ad4SBenjamin Mugnier return ret;
930153e4ad4SBenjamin Mugnier }
931153e4ad4SBenjamin Mugnier
932153e4ad4SBenjamin Mugnier return 0;
933153e4ad4SBenjamin Mugnier }
934153e4ad4SBenjamin Mugnier
vgxy61_update_gpios_strobe_polarity(struct vgxy61_dev * sensor,bool polarity)935153e4ad4SBenjamin Mugnier static int vgxy61_update_gpios_strobe_polarity(struct vgxy61_dev *sensor,
936153e4ad4SBenjamin Mugnier bool polarity)
937153e4ad4SBenjamin Mugnier {
938153e4ad4SBenjamin Mugnier int ret = 0;
939153e4ad4SBenjamin Mugnier
940153e4ad4SBenjamin Mugnier if (sensor->streaming)
941153e4ad4SBenjamin Mugnier return -EBUSY;
942153e4ad4SBenjamin Mugnier
943153e4ad4SBenjamin Mugnier vgxy61_write_reg(sensor, VGXY61_REG_GPIO_0_CTRL, polarity << 1, &ret);
944153e4ad4SBenjamin Mugnier vgxy61_write_reg(sensor, VGXY61_REG_GPIO_1_CTRL, polarity << 1, &ret);
945153e4ad4SBenjamin Mugnier vgxy61_write_reg(sensor, VGXY61_REG_GPIO_2_CTRL, polarity << 1, &ret);
946153e4ad4SBenjamin Mugnier vgxy61_write_reg(sensor, VGXY61_REG_GPIO_3_CTRL, polarity << 1, &ret);
947153e4ad4SBenjamin Mugnier vgxy61_write_reg(sensor, VGXY61_REG_SIGNALS_POLARITY_CTRL, polarity,
948153e4ad4SBenjamin Mugnier &ret);
949153e4ad4SBenjamin Mugnier
950153e4ad4SBenjamin Mugnier return ret;
951153e4ad4SBenjamin Mugnier }
952153e4ad4SBenjamin Mugnier
vgxy61_get_expo_long_max(struct vgxy61_dev * sensor,unsigned int short_expo_ratio)953153e4ad4SBenjamin Mugnier static u32 vgxy61_get_expo_long_max(struct vgxy61_dev *sensor,
954153e4ad4SBenjamin Mugnier unsigned int short_expo_ratio)
955153e4ad4SBenjamin Mugnier {
956153e4ad4SBenjamin Mugnier u32 first_rot_max_expo, second_rot_max_expo, third_rot_max_expo;
957153e4ad4SBenjamin Mugnier
958153e4ad4SBenjamin Mugnier /* Apply sensor's rules of thumb */
959153e4ad4SBenjamin Mugnier /*
960153e4ad4SBenjamin Mugnier * Short exposure + height must be less than frame length to avoid bad
961153e4ad4SBenjamin Mugnier * pixel line at the botom of the image
962153e4ad4SBenjamin Mugnier */
963153e4ad4SBenjamin Mugnier first_rot_max_expo =
964153e4ad4SBenjamin Mugnier ((sensor->frame_length - sensor->current_mode->crop.height -
965153e4ad4SBenjamin Mugnier sensor->rot_term) * short_expo_ratio) - 1;
966153e4ad4SBenjamin Mugnier
967153e4ad4SBenjamin Mugnier /*
968153e4ad4SBenjamin Mugnier * Total exposition time must be less than frame length to avoid sensor
969153e4ad4SBenjamin Mugnier * crash
970153e4ad4SBenjamin Mugnier */
971153e4ad4SBenjamin Mugnier second_rot_max_expo =
972153e4ad4SBenjamin Mugnier (((sensor->frame_length - VGXY61_EXPOS_ROT_TERM) *
973153e4ad4SBenjamin Mugnier short_expo_ratio) / (short_expo_ratio + 1)) - 1;
974153e4ad4SBenjamin Mugnier
975153e4ad4SBenjamin Mugnier /*
976153e4ad4SBenjamin Mugnier * Short exposure times 71 must be less than frame length to avoid
977153e4ad4SBenjamin Mugnier * sensor crash
978153e4ad4SBenjamin Mugnier */
979153e4ad4SBenjamin Mugnier third_rot_max_expo = (sensor->frame_length / 71) * short_expo_ratio;
980153e4ad4SBenjamin Mugnier
981153e4ad4SBenjamin Mugnier /* Take the minimum from all rules */
982153e4ad4SBenjamin Mugnier return min(min(first_rot_max_expo, second_rot_max_expo),
983153e4ad4SBenjamin Mugnier third_rot_max_expo);
984153e4ad4SBenjamin Mugnier }
985153e4ad4SBenjamin Mugnier
vgxy61_update_exposure(struct vgxy61_dev * sensor,u16 new_expo_long,enum vgxy61_hdr_mode hdr)986153e4ad4SBenjamin Mugnier static int vgxy61_update_exposure(struct vgxy61_dev *sensor, u16 new_expo_long,
987153e4ad4SBenjamin Mugnier enum vgxy61_hdr_mode hdr)
988153e4ad4SBenjamin Mugnier {
989153e4ad4SBenjamin Mugnier struct i2c_client *client = sensor->i2c_client;
990153e4ad4SBenjamin Mugnier u16 new_expo_short = 0;
991153e4ad4SBenjamin Mugnier u16 expo_short_max = 0;
992153e4ad4SBenjamin Mugnier u16 expo_long_min = VGXY61_MIN_EXPOSURE;
993483af3feSBenjamin Mugnier u16 expo_long_max = 0;
994153e4ad4SBenjamin Mugnier
995153e4ad4SBenjamin Mugnier /* Compute short exposure according to hdr mode and long exposure */
996153e4ad4SBenjamin Mugnier switch (hdr) {
997153e4ad4SBenjamin Mugnier case VGXY61_HDR_LINEAR:
998153e4ad4SBenjamin Mugnier /*
999153e4ad4SBenjamin Mugnier * Take ratio into account for minimal exposures in
1000153e4ad4SBenjamin Mugnier * VGXY61_HDR_LINEAR
1001153e4ad4SBenjamin Mugnier */
1002153e4ad4SBenjamin Mugnier expo_long_min = VGXY61_MIN_EXPOSURE * VGXY61_HDR_LINEAR_RATIO;
1003153e4ad4SBenjamin Mugnier new_expo_long = max(expo_long_min, new_expo_long);
1004153e4ad4SBenjamin Mugnier
1005153e4ad4SBenjamin Mugnier expo_long_max =
1006153e4ad4SBenjamin Mugnier vgxy61_get_expo_long_max(sensor,
1007153e4ad4SBenjamin Mugnier VGXY61_HDR_LINEAR_RATIO);
1008153e4ad4SBenjamin Mugnier expo_short_max = (expo_long_max +
1009153e4ad4SBenjamin Mugnier (VGXY61_HDR_LINEAR_RATIO / 2)) /
1010153e4ad4SBenjamin Mugnier VGXY61_HDR_LINEAR_RATIO;
1011153e4ad4SBenjamin Mugnier new_expo_short = (new_expo_long +
1012153e4ad4SBenjamin Mugnier (VGXY61_HDR_LINEAR_RATIO / 2)) /
1013153e4ad4SBenjamin Mugnier VGXY61_HDR_LINEAR_RATIO;
1014153e4ad4SBenjamin Mugnier break;
1015153e4ad4SBenjamin Mugnier case VGXY61_HDR_SUB:
1016153e4ad4SBenjamin Mugnier new_expo_long = max(expo_long_min, new_expo_long);
1017153e4ad4SBenjamin Mugnier
1018153e4ad4SBenjamin Mugnier expo_long_max = vgxy61_get_expo_long_max(sensor, 1);
1019153e4ad4SBenjamin Mugnier /* Short and long are the same in VGXY61_HDR_SUB */
1020153e4ad4SBenjamin Mugnier expo_short_max = expo_long_max;
1021153e4ad4SBenjamin Mugnier new_expo_short = new_expo_long;
1022153e4ad4SBenjamin Mugnier break;
1023153e4ad4SBenjamin Mugnier case VGXY61_NO_HDR:
1024153e4ad4SBenjamin Mugnier new_expo_long = max(expo_long_min, new_expo_long);
1025153e4ad4SBenjamin Mugnier
1026153e4ad4SBenjamin Mugnier /*
1027153e4ad4SBenjamin Mugnier * As short expo is 0 here, only the second rule of thumb
1028153e4ad4SBenjamin Mugnier * applies, see vgxy61_get_expo_long_max for more
1029153e4ad4SBenjamin Mugnier */
1030153e4ad4SBenjamin Mugnier expo_long_max = sensor->frame_length - VGXY61_EXPOS_ROT_TERM;
1031153e4ad4SBenjamin Mugnier break;
1032153e4ad4SBenjamin Mugnier default:
1033153e4ad4SBenjamin Mugnier /* Should never happen */
1034153e4ad4SBenjamin Mugnier WARN_ON(true);
1035153e4ad4SBenjamin Mugnier break;
1036153e4ad4SBenjamin Mugnier }
1037153e4ad4SBenjamin Mugnier
1038153e4ad4SBenjamin Mugnier /* If this happens, something is wrong with formulas */
1039153e4ad4SBenjamin Mugnier WARN_ON(expo_long_min > expo_long_max);
1040153e4ad4SBenjamin Mugnier
1041153e4ad4SBenjamin Mugnier if (new_expo_long > expo_long_max) {
1042153e4ad4SBenjamin Mugnier dev_warn(&client->dev, "Exposure %d too high, clamping to %d\n",
1043153e4ad4SBenjamin Mugnier new_expo_long, expo_long_max);
1044153e4ad4SBenjamin Mugnier new_expo_long = expo_long_max;
1045153e4ad4SBenjamin Mugnier new_expo_short = expo_short_max;
1046153e4ad4SBenjamin Mugnier }
1047153e4ad4SBenjamin Mugnier
1048153e4ad4SBenjamin Mugnier sensor->expo_long = new_expo_long;
1049153e4ad4SBenjamin Mugnier sensor->expo_short = new_expo_short;
1050153e4ad4SBenjamin Mugnier sensor->expo_max = expo_long_max;
1051153e4ad4SBenjamin Mugnier sensor->expo_min = expo_long_min;
1052153e4ad4SBenjamin Mugnier
1053153e4ad4SBenjamin Mugnier if (sensor->streaming)
1054153e4ad4SBenjamin Mugnier return vgxy61_apply_exposure(sensor);
1055153e4ad4SBenjamin Mugnier return 0;
1056153e4ad4SBenjamin Mugnier }
1057153e4ad4SBenjamin Mugnier
vgxy61_apply_framelength(struct vgxy61_dev * sensor)1058153e4ad4SBenjamin Mugnier static int vgxy61_apply_framelength(struct vgxy61_dev *sensor)
1059153e4ad4SBenjamin Mugnier {
1060153e4ad4SBenjamin Mugnier return vgxy61_write_reg(sensor, VGXY61_REG_FRAME_LENGTH,
1061153e4ad4SBenjamin Mugnier sensor->frame_length, NULL);
1062153e4ad4SBenjamin Mugnier }
1063153e4ad4SBenjamin Mugnier
vgxy61_update_vblank(struct vgxy61_dev * sensor,u16 vblank,enum vgxy61_hdr_mode hdr)1064153e4ad4SBenjamin Mugnier static int vgxy61_update_vblank(struct vgxy61_dev *sensor, u16 vblank,
1065153e4ad4SBenjamin Mugnier enum vgxy61_hdr_mode hdr)
1066153e4ad4SBenjamin Mugnier {
1067153e4ad4SBenjamin Mugnier int ret;
1068153e4ad4SBenjamin Mugnier
1069153e4ad4SBenjamin Mugnier sensor->vblank_min = vgxy61_get_vblank_min(sensor, hdr);
1070153e4ad4SBenjamin Mugnier sensor->vblank = max(sensor->vblank_min, vblank);
1071153e4ad4SBenjamin Mugnier sensor->frame_length = sensor->current_mode->crop.height +
1072153e4ad4SBenjamin Mugnier sensor->vblank;
1073153e4ad4SBenjamin Mugnier
1074153e4ad4SBenjamin Mugnier /* Update exposure according to vblank */
1075153e4ad4SBenjamin Mugnier ret = vgxy61_update_exposure(sensor, sensor->expo_long, hdr);
1076153e4ad4SBenjamin Mugnier if (ret)
1077153e4ad4SBenjamin Mugnier return ret;
1078153e4ad4SBenjamin Mugnier
1079153e4ad4SBenjamin Mugnier if (sensor->streaming)
1080153e4ad4SBenjamin Mugnier return vgxy61_apply_framelength(sensor);
1081153e4ad4SBenjamin Mugnier return 0;
1082153e4ad4SBenjamin Mugnier }
1083153e4ad4SBenjamin Mugnier
vgxy61_apply_hdr(struct vgxy61_dev * sensor,enum vgxy61_hdr_mode index)1084153e4ad4SBenjamin Mugnier static int vgxy61_apply_hdr(struct vgxy61_dev *sensor,
1085153e4ad4SBenjamin Mugnier enum vgxy61_hdr_mode index)
1086153e4ad4SBenjamin Mugnier {
1087153e4ad4SBenjamin Mugnier static const u8 index2val[] = {0x1, 0x4, 0xa};
1088153e4ad4SBenjamin Mugnier
1089153e4ad4SBenjamin Mugnier return vgxy61_write_reg(sensor, VGXY61_REG_HDR_CTRL, index2val[index],
1090153e4ad4SBenjamin Mugnier NULL);
1091153e4ad4SBenjamin Mugnier }
1092153e4ad4SBenjamin Mugnier
vgxy61_update_hdr(struct vgxy61_dev * sensor,enum vgxy61_hdr_mode index)1093153e4ad4SBenjamin Mugnier static int vgxy61_update_hdr(struct vgxy61_dev *sensor,
1094153e4ad4SBenjamin Mugnier enum vgxy61_hdr_mode index)
1095153e4ad4SBenjamin Mugnier {
1096153e4ad4SBenjamin Mugnier int ret;
1097153e4ad4SBenjamin Mugnier
1098153e4ad4SBenjamin Mugnier /*
1099153e4ad4SBenjamin Mugnier * vblank and short exposure change according to HDR mode, do it first
1100153e4ad4SBenjamin Mugnier * as it can violate sensors 'rule of thumbs' and therefore will require
1101153e4ad4SBenjamin Mugnier * to change the long exposure.
1102153e4ad4SBenjamin Mugnier */
1103153e4ad4SBenjamin Mugnier ret = vgxy61_update_vblank(sensor, sensor->vblank, index);
1104153e4ad4SBenjamin Mugnier if (ret)
1105153e4ad4SBenjamin Mugnier return ret;
1106153e4ad4SBenjamin Mugnier
1107153e4ad4SBenjamin Mugnier /* Update strobe mode according to HDR */
1108153e4ad4SBenjamin Mugnier ret = vgxy61_update_gpios_strobe_mode(sensor, index);
1109153e4ad4SBenjamin Mugnier if (ret)
1110153e4ad4SBenjamin Mugnier return ret;
1111153e4ad4SBenjamin Mugnier
1112153e4ad4SBenjamin Mugnier sensor->hdr = index;
1113153e4ad4SBenjamin Mugnier
1114153e4ad4SBenjamin Mugnier if (sensor->streaming)
1115153e4ad4SBenjamin Mugnier return vgxy61_apply_hdr(sensor, sensor->hdr);
1116153e4ad4SBenjamin Mugnier return 0;
1117153e4ad4SBenjamin Mugnier }
1118153e4ad4SBenjamin Mugnier
vgxy61_apply_settings(struct vgxy61_dev * sensor)1119153e4ad4SBenjamin Mugnier static int vgxy61_apply_settings(struct vgxy61_dev *sensor)
1120153e4ad4SBenjamin Mugnier {
1121153e4ad4SBenjamin Mugnier int ret;
1122153e4ad4SBenjamin Mugnier unsigned int i;
1123153e4ad4SBenjamin Mugnier
1124153e4ad4SBenjamin Mugnier ret = vgxy61_apply_hdr(sensor, sensor->hdr);
1125153e4ad4SBenjamin Mugnier if (ret)
1126153e4ad4SBenjamin Mugnier return ret;
1127153e4ad4SBenjamin Mugnier
1128153e4ad4SBenjamin Mugnier ret = vgxy61_apply_framelength(sensor);
1129153e4ad4SBenjamin Mugnier if (ret)
1130153e4ad4SBenjamin Mugnier return ret;
1131153e4ad4SBenjamin Mugnier
1132153e4ad4SBenjamin Mugnier ret = vgxy61_apply_exposure(sensor);
1133153e4ad4SBenjamin Mugnier if (ret)
1134153e4ad4SBenjamin Mugnier return ret;
1135153e4ad4SBenjamin Mugnier
1136153e4ad4SBenjamin Mugnier ret = vgxy61_write_reg(sensor, VGXY61_REG_ANALOG_GAIN,
1137153e4ad4SBenjamin Mugnier sensor->analog_gain, NULL);
1138153e4ad4SBenjamin Mugnier if (ret)
1139153e4ad4SBenjamin Mugnier return ret;
1140153e4ad4SBenjamin Mugnier ret = vgxy61_apply_digital_gain(sensor, sensor->digital_gain);
1141153e4ad4SBenjamin Mugnier if (ret)
1142153e4ad4SBenjamin Mugnier return ret;
1143153e4ad4SBenjamin Mugnier
1144153e4ad4SBenjamin Mugnier ret = vgxy61_write_reg(sensor, VGXY61_REG_ORIENTATION,
1145153e4ad4SBenjamin Mugnier sensor->hflip | (sensor->vflip << 1), NULL);
1146153e4ad4SBenjamin Mugnier if (ret)
1147153e4ad4SBenjamin Mugnier return ret;
1148153e4ad4SBenjamin Mugnier
1149153e4ad4SBenjamin Mugnier ret = vgxy61_apply_patgen(sensor, sensor->pattern);
1150153e4ad4SBenjamin Mugnier if (ret)
1151153e4ad4SBenjamin Mugnier return ret;
1152153e4ad4SBenjamin Mugnier
1153153e4ad4SBenjamin Mugnier for (i = 0; i < VGXY61_NB_GPIOS; i++) {
1154153e4ad4SBenjamin Mugnier ret = vgxy61_apply_gpiox_strobe_mode(sensor,
1155153e4ad4SBenjamin Mugnier sensor->strobe_mode, i);
1156153e4ad4SBenjamin Mugnier if (ret)
1157153e4ad4SBenjamin Mugnier return ret;
1158153e4ad4SBenjamin Mugnier }
1159153e4ad4SBenjamin Mugnier
1160153e4ad4SBenjamin Mugnier return 0;
1161153e4ad4SBenjamin Mugnier }
1162153e4ad4SBenjamin Mugnier
vgxy61_stream_enable(struct vgxy61_dev * sensor)1163153e4ad4SBenjamin Mugnier static int vgxy61_stream_enable(struct vgxy61_dev *sensor)
1164153e4ad4SBenjamin Mugnier {
1165153e4ad4SBenjamin Mugnier struct i2c_client *client = v4l2_get_subdevdata(&sensor->sd);
1166153e4ad4SBenjamin Mugnier const struct v4l2_rect *crop = &sensor->current_mode->crop;
1167153e4ad4SBenjamin Mugnier int ret = 0;
1168153e4ad4SBenjamin Mugnier
1169153e4ad4SBenjamin Mugnier ret = vgxy61_check_bw(sensor);
1170153e4ad4SBenjamin Mugnier if (ret)
1171153e4ad4SBenjamin Mugnier return ret;
1172153e4ad4SBenjamin Mugnier
1173153e4ad4SBenjamin Mugnier ret = pm_runtime_get_sync(&client->dev);
1174153e4ad4SBenjamin Mugnier if (ret < 0) {
1175153e4ad4SBenjamin Mugnier pm_runtime_put_autosuspend(&client->dev);
1176153e4ad4SBenjamin Mugnier return ret;
1177153e4ad4SBenjamin Mugnier }
1178153e4ad4SBenjamin Mugnier
1179483af3feSBenjamin Mugnier /* pm_runtime_get_sync() can return 1 as a valid return code */
1180483af3feSBenjamin Mugnier ret = 0;
1181483af3feSBenjamin Mugnier
1182153e4ad4SBenjamin Mugnier vgxy61_write_reg(sensor, VGXY61_REG_FORMAT_CTRL,
1183153e4ad4SBenjamin Mugnier get_bpp_by_code(sensor->fmt.code), &ret);
1184153e4ad4SBenjamin Mugnier vgxy61_write_reg(sensor, VGXY61_REG_OIF_ROI0_CTRL,
1185153e4ad4SBenjamin Mugnier get_data_type_by_code(sensor->fmt.code), &ret);
1186153e4ad4SBenjamin Mugnier
1187153e4ad4SBenjamin Mugnier vgxy61_write_reg(sensor, VGXY61_REG_READOUT_CTRL,
1188153e4ad4SBenjamin Mugnier sensor->current_mode->bin_mode, &ret);
1189153e4ad4SBenjamin Mugnier vgxy61_write_reg(sensor, VGXY61_REG_ROI0_START_H, crop->left, &ret);
1190153e4ad4SBenjamin Mugnier vgxy61_write_reg(sensor, VGXY61_REG_ROI0_END_H,
1191153e4ad4SBenjamin Mugnier crop->left + crop->width - 1, &ret);
1192153e4ad4SBenjamin Mugnier vgxy61_write_reg(sensor, VGXY61_REG_ROI0_START_V, crop->top, &ret);
1193153e4ad4SBenjamin Mugnier vgxy61_write_reg(sensor, VGXY61_REG_ROI0_END_V,
1194153e4ad4SBenjamin Mugnier crop->top + crop->height - 1, &ret);
1195153e4ad4SBenjamin Mugnier if (ret)
1196153e4ad4SBenjamin Mugnier goto err_rpm_put;
1197153e4ad4SBenjamin Mugnier
1198153e4ad4SBenjamin Mugnier ret = vgxy61_apply_settings(sensor);
1199153e4ad4SBenjamin Mugnier if (ret)
1200153e4ad4SBenjamin Mugnier goto err_rpm_put;
1201153e4ad4SBenjamin Mugnier
1202153e4ad4SBenjamin Mugnier ret = vgxy61_write_reg(sensor, VGXY61_REG_STREAMING,
1203153e4ad4SBenjamin Mugnier VGXY61_STREAMING_REQ_START, NULL);
1204153e4ad4SBenjamin Mugnier if (ret)
1205153e4ad4SBenjamin Mugnier goto err_rpm_put;
1206153e4ad4SBenjamin Mugnier
1207153e4ad4SBenjamin Mugnier ret = vgxy61_poll_reg(sensor, VGXY61_REG_STREAMING,
1208153e4ad4SBenjamin Mugnier VGXY61_STREAMING_NO_REQ, VGXY61_TIMEOUT_MS);
1209153e4ad4SBenjamin Mugnier if (ret)
1210153e4ad4SBenjamin Mugnier goto err_rpm_put;
1211153e4ad4SBenjamin Mugnier
1212153e4ad4SBenjamin Mugnier ret = vgxy61_wait_state(sensor, VGXY61_SYSTEM_FSM_STREAMING,
1213153e4ad4SBenjamin Mugnier VGXY61_TIMEOUT_MS);
1214153e4ad4SBenjamin Mugnier if (ret)
1215153e4ad4SBenjamin Mugnier goto err_rpm_put;
1216153e4ad4SBenjamin Mugnier
1217153e4ad4SBenjamin Mugnier /* vflip and hflip cannot change during streaming */
1218153e4ad4SBenjamin Mugnier __v4l2_ctrl_grab(sensor->vflip_ctrl, true);
1219153e4ad4SBenjamin Mugnier __v4l2_ctrl_grab(sensor->hflip_ctrl, true);
1220153e4ad4SBenjamin Mugnier
1221153e4ad4SBenjamin Mugnier return 0;
1222153e4ad4SBenjamin Mugnier
1223153e4ad4SBenjamin Mugnier err_rpm_put:
1224153e4ad4SBenjamin Mugnier pm_runtime_put(&client->dev);
1225153e4ad4SBenjamin Mugnier return ret;
1226153e4ad4SBenjamin Mugnier }
1227153e4ad4SBenjamin Mugnier
vgxy61_stream_disable(struct vgxy61_dev * sensor)1228153e4ad4SBenjamin Mugnier static int vgxy61_stream_disable(struct vgxy61_dev *sensor)
1229153e4ad4SBenjamin Mugnier {
1230153e4ad4SBenjamin Mugnier struct i2c_client *client = v4l2_get_subdevdata(&sensor->sd);
1231153e4ad4SBenjamin Mugnier int ret;
1232153e4ad4SBenjamin Mugnier
1233153e4ad4SBenjamin Mugnier ret = vgxy61_write_reg(sensor, VGXY61_REG_STREAMING,
1234153e4ad4SBenjamin Mugnier VGXY61_STREAMING_REQ_STOP, NULL);
1235153e4ad4SBenjamin Mugnier if (ret)
1236153e4ad4SBenjamin Mugnier goto err_str_dis;
1237153e4ad4SBenjamin Mugnier
1238153e4ad4SBenjamin Mugnier ret = vgxy61_poll_reg(sensor, VGXY61_REG_STREAMING,
1239153e4ad4SBenjamin Mugnier VGXY61_STREAMING_NO_REQ, 2000);
1240153e4ad4SBenjamin Mugnier if (ret)
1241153e4ad4SBenjamin Mugnier goto err_str_dis;
1242153e4ad4SBenjamin Mugnier
1243153e4ad4SBenjamin Mugnier ret = vgxy61_wait_state(sensor, VGXY61_SYSTEM_FSM_SW_STBY,
1244153e4ad4SBenjamin Mugnier VGXY61_TIMEOUT_MS);
1245153e4ad4SBenjamin Mugnier if (ret)
1246153e4ad4SBenjamin Mugnier goto err_str_dis;
1247153e4ad4SBenjamin Mugnier
1248153e4ad4SBenjamin Mugnier __v4l2_ctrl_grab(sensor->vflip_ctrl, false);
1249153e4ad4SBenjamin Mugnier __v4l2_ctrl_grab(sensor->hflip_ctrl, false);
1250153e4ad4SBenjamin Mugnier
1251153e4ad4SBenjamin Mugnier err_str_dis:
1252153e4ad4SBenjamin Mugnier if (ret)
1253153e4ad4SBenjamin Mugnier WARN(1, "Can't disable stream");
1254153e4ad4SBenjamin Mugnier pm_runtime_put(&client->dev);
1255153e4ad4SBenjamin Mugnier
1256153e4ad4SBenjamin Mugnier return ret;
1257153e4ad4SBenjamin Mugnier }
1258153e4ad4SBenjamin Mugnier
vgxy61_s_stream(struct v4l2_subdev * sd,int enable)1259153e4ad4SBenjamin Mugnier static int vgxy61_s_stream(struct v4l2_subdev *sd, int enable)
1260153e4ad4SBenjamin Mugnier {
1261153e4ad4SBenjamin Mugnier struct vgxy61_dev *sensor = to_vgxy61_dev(sd);
1262153e4ad4SBenjamin Mugnier int ret = 0;
1263153e4ad4SBenjamin Mugnier
1264153e4ad4SBenjamin Mugnier mutex_lock(&sensor->lock);
1265153e4ad4SBenjamin Mugnier
1266153e4ad4SBenjamin Mugnier ret = enable ? vgxy61_stream_enable(sensor) :
1267153e4ad4SBenjamin Mugnier vgxy61_stream_disable(sensor);
1268153e4ad4SBenjamin Mugnier if (!ret)
1269153e4ad4SBenjamin Mugnier sensor->streaming = enable;
1270153e4ad4SBenjamin Mugnier
1271153e4ad4SBenjamin Mugnier mutex_unlock(&sensor->lock);
1272153e4ad4SBenjamin Mugnier
1273153e4ad4SBenjamin Mugnier return ret;
1274153e4ad4SBenjamin Mugnier }
1275153e4ad4SBenjamin Mugnier
vgxy61_set_fmt(struct v4l2_subdev * sd,struct v4l2_subdev_state * sd_state,struct v4l2_subdev_format * format)1276153e4ad4SBenjamin Mugnier static int vgxy61_set_fmt(struct v4l2_subdev *sd,
1277153e4ad4SBenjamin Mugnier struct v4l2_subdev_state *sd_state,
1278153e4ad4SBenjamin Mugnier struct v4l2_subdev_format *format)
1279153e4ad4SBenjamin Mugnier {
1280153e4ad4SBenjamin Mugnier struct vgxy61_dev *sensor = to_vgxy61_dev(sd);
1281153e4ad4SBenjamin Mugnier const struct vgxy61_mode_info *new_mode;
1282153e4ad4SBenjamin Mugnier struct v4l2_mbus_framefmt *fmt;
1283153e4ad4SBenjamin Mugnier int ret;
1284153e4ad4SBenjamin Mugnier
1285153e4ad4SBenjamin Mugnier mutex_lock(&sensor->lock);
1286153e4ad4SBenjamin Mugnier
1287153e4ad4SBenjamin Mugnier if (sensor->streaming) {
1288153e4ad4SBenjamin Mugnier ret = -EBUSY;
1289153e4ad4SBenjamin Mugnier goto out;
1290153e4ad4SBenjamin Mugnier }
1291153e4ad4SBenjamin Mugnier
1292153e4ad4SBenjamin Mugnier ret = vgxy61_try_fmt_internal(sd, &format->format, &new_mode);
1293153e4ad4SBenjamin Mugnier if (ret)
1294153e4ad4SBenjamin Mugnier goto out;
1295153e4ad4SBenjamin Mugnier
1296153e4ad4SBenjamin Mugnier if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
1297153e4ad4SBenjamin Mugnier fmt = v4l2_subdev_get_try_format(sd, sd_state, 0);
1298153e4ad4SBenjamin Mugnier *fmt = format->format;
1299153e4ad4SBenjamin Mugnier } else if (sensor->current_mode != new_mode ||
1300153e4ad4SBenjamin Mugnier sensor->fmt.code != format->format.code) {
1301153e4ad4SBenjamin Mugnier fmt = &sensor->fmt;
1302153e4ad4SBenjamin Mugnier *fmt = format->format;
1303153e4ad4SBenjamin Mugnier
1304153e4ad4SBenjamin Mugnier sensor->current_mode = new_mode;
1305153e4ad4SBenjamin Mugnier
1306153e4ad4SBenjamin Mugnier /* Reset vblank and framelength to default */
1307153e4ad4SBenjamin Mugnier ret = vgxy61_update_vblank(sensor,
1308153e4ad4SBenjamin Mugnier VGXY61_FRAME_LENGTH_DEF -
1309153e4ad4SBenjamin Mugnier new_mode->crop.height,
1310153e4ad4SBenjamin Mugnier sensor->hdr);
1311153e4ad4SBenjamin Mugnier
1312153e4ad4SBenjamin Mugnier /* Update controls to reflect new mode */
1313153e4ad4SBenjamin Mugnier __v4l2_ctrl_s_ctrl_int64(sensor->pixel_rate_ctrl,
1314153e4ad4SBenjamin Mugnier get_pixel_rate(sensor));
1315153e4ad4SBenjamin Mugnier __v4l2_ctrl_modify_range(sensor->vblank_ctrl,
1316153e4ad4SBenjamin Mugnier sensor->vblank_min,
1317153e4ad4SBenjamin Mugnier 0xffff - new_mode->crop.height,
1318153e4ad4SBenjamin Mugnier 1, sensor->vblank);
1319153e4ad4SBenjamin Mugnier __v4l2_ctrl_s_ctrl(sensor->vblank_ctrl, sensor->vblank);
1320153e4ad4SBenjamin Mugnier __v4l2_ctrl_modify_range(sensor->expo_ctrl, sensor->expo_min,
1321153e4ad4SBenjamin Mugnier sensor->expo_max, 1,
1322153e4ad4SBenjamin Mugnier sensor->expo_long);
1323153e4ad4SBenjamin Mugnier }
1324153e4ad4SBenjamin Mugnier
1325153e4ad4SBenjamin Mugnier out:
1326153e4ad4SBenjamin Mugnier mutex_unlock(&sensor->lock);
1327153e4ad4SBenjamin Mugnier
1328153e4ad4SBenjamin Mugnier return ret;
1329153e4ad4SBenjamin Mugnier }
1330153e4ad4SBenjamin Mugnier
vgxy61_init_cfg(struct v4l2_subdev * sd,struct v4l2_subdev_state * sd_state)1331153e4ad4SBenjamin Mugnier static int vgxy61_init_cfg(struct v4l2_subdev *sd,
1332153e4ad4SBenjamin Mugnier struct v4l2_subdev_state *sd_state)
1333153e4ad4SBenjamin Mugnier {
1334153e4ad4SBenjamin Mugnier struct vgxy61_dev *sensor = to_vgxy61_dev(sd);
1335153e4ad4SBenjamin Mugnier struct v4l2_subdev_format fmt = { 0 };
1336153e4ad4SBenjamin Mugnier
1337153e4ad4SBenjamin Mugnier vgxy61_fill_framefmt(sensor, sensor->current_mode, &fmt.format,
1338153e4ad4SBenjamin Mugnier VGXY61_MEDIA_BUS_FMT_DEF);
1339153e4ad4SBenjamin Mugnier
1340153e4ad4SBenjamin Mugnier return vgxy61_set_fmt(sd, sd_state, &fmt);
1341153e4ad4SBenjamin Mugnier }
1342153e4ad4SBenjamin Mugnier
vgxy61_s_ctrl(struct v4l2_ctrl * ctrl)1343153e4ad4SBenjamin Mugnier static int vgxy61_s_ctrl(struct v4l2_ctrl *ctrl)
1344153e4ad4SBenjamin Mugnier {
1345153e4ad4SBenjamin Mugnier struct v4l2_subdev *sd = ctrl_to_sd(ctrl);
1346153e4ad4SBenjamin Mugnier struct vgxy61_dev *sensor = to_vgxy61_dev(sd);
1347153e4ad4SBenjamin Mugnier const struct vgxy61_mode_info *cur_mode = sensor->current_mode;
1348153e4ad4SBenjamin Mugnier int ret;
1349153e4ad4SBenjamin Mugnier
1350153e4ad4SBenjamin Mugnier switch (ctrl->id) {
1351153e4ad4SBenjamin Mugnier case V4L2_CID_EXPOSURE:
1352153e4ad4SBenjamin Mugnier ret = vgxy61_update_exposure(sensor, ctrl->val, sensor->hdr);
1353153e4ad4SBenjamin Mugnier ctrl->val = sensor->expo_long;
1354153e4ad4SBenjamin Mugnier break;
1355153e4ad4SBenjamin Mugnier case V4L2_CID_ANALOGUE_GAIN:
1356153e4ad4SBenjamin Mugnier ret = vgxy61_update_analog_gain(sensor, ctrl->val);
1357153e4ad4SBenjamin Mugnier break;
1358153e4ad4SBenjamin Mugnier case V4L2_CID_DIGITAL_GAIN:
1359153e4ad4SBenjamin Mugnier ret = vgxy61_update_digital_gain(sensor, ctrl->val);
1360153e4ad4SBenjamin Mugnier break;
1361153e4ad4SBenjamin Mugnier case V4L2_CID_VFLIP:
1362153e4ad4SBenjamin Mugnier case V4L2_CID_HFLIP:
1363153e4ad4SBenjamin Mugnier if (sensor->streaming) {
1364153e4ad4SBenjamin Mugnier ret = -EBUSY;
1365153e4ad4SBenjamin Mugnier break;
1366153e4ad4SBenjamin Mugnier }
1367153e4ad4SBenjamin Mugnier if (ctrl->id == V4L2_CID_VFLIP)
1368153e4ad4SBenjamin Mugnier sensor->vflip = ctrl->val;
1369153e4ad4SBenjamin Mugnier if (ctrl->id == V4L2_CID_HFLIP)
1370153e4ad4SBenjamin Mugnier sensor->hflip = ctrl->val;
1371153e4ad4SBenjamin Mugnier ret = 0;
1372153e4ad4SBenjamin Mugnier break;
1373153e4ad4SBenjamin Mugnier case V4L2_CID_TEST_PATTERN:
1374153e4ad4SBenjamin Mugnier ret = vgxy61_update_patgen(sensor, ctrl->val);
1375153e4ad4SBenjamin Mugnier break;
1376153e4ad4SBenjamin Mugnier case V4L2_CID_HDR_SENSOR_MODE:
1377153e4ad4SBenjamin Mugnier ret = vgxy61_update_hdr(sensor, ctrl->val);
1378153e4ad4SBenjamin Mugnier /* Update vblank and exposure controls to match new hdr */
1379153e4ad4SBenjamin Mugnier __v4l2_ctrl_modify_range(sensor->vblank_ctrl,
1380153e4ad4SBenjamin Mugnier sensor->vblank_min,
1381153e4ad4SBenjamin Mugnier 0xffff - cur_mode->crop.height,
1382153e4ad4SBenjamin Mugnier 1, sensor->vblank);
1383153e4ad4SBenjamin Mugnier __v4l2_ctrl_modify_range(sensor->expo_ctrl, sensor->expo_min,
1384153e4ad4SBenjamin Mugnier sensor->expo_max, 1,
1385153e4ad4SBenjamin Mugnier sensor->expo_long);
1386153e4ad4SBenjamin Mugnier break;
1387153e4ad4SBenjamin Mugnier case V4L2_CID_VBLANK:
1388153e4ad4SBenjamin Mugnier ret = vgxy61_update_vblank(sensor, ctrl->val, sensor->hdr);
1389153e4ad4SBenjamin Mugnier /* Update exposure control to match new vblank */
1390153e4ad4SBenjamin Mugnier __v4l2_ctrl_modify_range(sensor->expo_ctrl, sensor->expo_min,
1391153e4ad4SBenjamin Mugnier sensor->expo_max, 1,
1392153e4ad4SBenjamin Mugnier sensor->expo_long);
1393153e4ad4SBenjamin Mugnier break;
1394153e4ad4SBenjamin Mugnier default:
1395153e4ad4SBenjamin Mugnier ret = -EINVAL;
1396153e4ad4SBenjamin Mugnier break;
1397153e4ad4SBenjamin Mugnier }
1398153e4ad4SBenjamin Mugnier
1399153e4ad4SBenjamin Mugnier return ret;
1400153e4ad4SBenjamin Mugnier }
1401153e4ad4SBenjamin Mugnier
1402153e4ad4SBenjamin Mugnier static const struct v4l2_ctrl_ops vgxy61_ctrl_ops = {
1403153e4ad4SBenjamin Mugnier .s_ctrl = vgxy61_s_ctrl,
1404153e4ad4SBenjamin Mugnier };
1405153e4ad4SBenjamin Mugnier
vgxy61_init_controls(struct vgxy61_dev * sensor)1406153e4ad4SBenjamin Mugnier static int vgxy61_init_controls(struct vgxy61_dev *sensor)
1407153e4ad4SBenjamin Mugnier {
1408153e4ad4SBenjamin Mugnier const struct v4l2_ctrl_ops *ops = &vgxy61_ctrl_ops;
1409153e4ad4SBenjamin Mugnier struct v4l2_ctrl_handler *hdl = &sensor->ctrl_handler;
1410153e4ad4SBenjamin Mugnier const struct vgxy61_mode_info *cur_mode = sensor->current_mode;
1411153e4ad4SBenjamin Mugnier struct v4l2_ctrl *ctrl;
1412153e4ad4SBenjamin Mugnier int ret;
1413153e4ad4SBenjamin Mugnier
1414153e4ad4SBenjamin Mugnier v4l2_ctrl_handler_init(hdl, 16);
1415153e4ad4SBenjamin Mugnier /* We can use our own mutex for the ctrl lock */
1416153e4ad4SBenjamin Mugnier hdl->lock = &sensor->lock;
1417153e4ad4SBenjamin Mugnier v4l2_ctrl_new_std(hdl, ops, V4L2_CID_ANALOGUE_GAIN, 0, 0x1c, 1,
1418153e4ad4SBenjamin Mugnier sensor->analog_gain);
1419153e4ad4SBenjamin Mugnier v4l2_ctrl_new_std(hdl, ops, V4L2_CID_DIGITAL_GAIN, 0, 0xfff, 1,
1420153e4ad4SBenjamin Mugnier sensor->digital_gain);
1421153e4ad4SBenjamin Mugnier v4l2_ctrl_new_std_menu_items(hdl, ops, V4L2_CID_TEST_PATTERN,
1422153e4ad4SBenjamin Mugnier ARRAY_SIZE(vgxy61_test_pattern_menu) - 1,
1423153e4ad4SBenjamin Mugnier 0, 0, vgxy61_test_pattern_menu);
1424153e4ad4SBenjamin Mugnier ctrl = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_HBLANK, 0,
1425153e4ad4SBenjamin Mugnier sensor->line_length, 1,
1426153e4ad4SBenjamin Mugnier sensor->line_length - cur_mode->width);
1427153e4ad4SBenjamin Mugnier if (ctrl)
1428153e4ad4SBenjamin Mugnier ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
1429153e4ad4SBenjamin Mugnier ctrl = v4l2_ctrl_new_int_menu(hdl, ops, V4L2_CID_LINK_FREQ,
1430153e4ad4SBenjamin Mugnier ARRAY_SIZE(link_freq) - 1, 0, link_freq);
1431153e4ad4SBenjamin Mugnier if (ctrl)
1432153e4ad4SBenjamin Mugnier ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
1433153e4ad4SBenjamin Mugnier v4l2_ctrl_new_std_menu_items(hdl, ops, V4L2_CID_HDR_SENSOR_MODE,
1434153e4ad4SBenjamin Mugnier ARRAY_SIZE(vgxy61_hdr_mode_menu) - 1, 0,
1435153e4ad4SBenjamin Mugnier VGXY61_NO_HDR, vgxy61_hdr_mode_menu);
1436153e4ad4SBenjamin Mugnier
1437153e4ad4SBenjamin Mugnier /*
1438153e4ad4SBenjamin Mugnier * Keep a pointer to these controls as we need to update them when
1439153e4ad4SBenjamin Mugnier * setting the format
1440153e4ad4SBenjamin Mugnier */
1441153e4ad4SBenjamin Mugnier sensor->pixel_rate_ctrl = v4l2_ctrl_new_std(hdl, ops,
1442153e4ad4SBenjamin Mugnier V4L2_CID_PIXEL_RATE, 1,
1443153e4ad4SBenjamin Mugnier INT_MAX, 1,
1444153e4ad4SBenjamin Mugnier get_pixel_rate(sensor));
1445153e4ad4SBenjamin Mugnier if (sensor->pixel_rate_ctrl)
1446153e4ad4SBenjamin Mugnier sensor->pixel_rate_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
1447153e4ad4SBenjamin Mugnier sensor->expo_ctrl = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_EXPOSURE,
1448153e4ad4SBenjamin Mugnier sensor->expo_min,
1449153e4ad4SBenjamin Mugnier sensor->expo_max, 1,
1450153e4ad4SBenjamin Mugnier sensor->expo_long);
1451153e4ad4SBenjamin Mugnier sensor->vblank_ctrl = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_VBLANK,
1452153e4ad4SBenjamin Mugnier sensor->vblank_min,
1453153e4ad4SBenjamin Mugnier 0xffff - cur_mode->crop.height,
1454153e4ad4SBenjamin Mugnier 1, sensor->vblank);
1455153e4ad4SBenjamin Mugnier sensor->vflip_ctrl = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_VFLIP,
1456153e4ad4SBenjamin Mugnier 0, 1, 1, sensor->vflip);
1457153e4ad4SBenjamin Mugnier sensor->hflip_ctrl = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_HFLIP,
1458153e4ad4SBenjamin Mugnier 0, 1, 1, sensor->hflip);
1459153e4ad4SBenjamin Mugnier
1460153e4ad4SBenjamin Mugnier if (hdl->error) {
1461153e4ad4SBenjamin Mugnier ret = hdl->error;
1462153e4ad4SBenjamin Mugnier goto free_ctrls;
1463153e4ad4SBenjamin Mugnier }
1464153e4ad4SBenjamin Mugnier
1465153e4ad4SBenjamin Mugnier sensor->sd.ctrl_handler = hdl;
1466153e4ad4SBenjamin Mugnier return 0;
1467153e4ad4SBenjamin Mugnier
1468153e4ad4SBenjamin Mugnier free_ctrls:
1469153e4ad4SBenjamin Mugnier v4l2_ctrl_handler_free(hdl);
1470153e4ad4SBenjamin Mugnier return ret;
1471153e4ad4SBenjamin Mugnier }
1472153e4ad4SBenjamin Mugnier
1473153e4ad4SBenjamin Mugnier static const struct v4l2_subdev_video_ops vgxy61_video_ops = {
1474153e4ad4SBenjamin Mugnier .s_stream = vgxy61_s_stream,
1475153e4ad4SBenjamin Mugnier };
1476153e4ad4SBenjamin Mugnier
1477153e4ad4SBenjamin Mugnier static const struct v4l2_subdev_pad_ops vgxy61_pad_ops = {
1478153e4ad4SBenjamin Mugnier .init_cfg = vgxy61_init_cfg,
1479153e4ad4SBenjamin Mugnier .enum_mbus_code = vgxy61_enum_mbus_code,
1480153e4ad4SBenjamin Mugnier .get_fmt = vgxy61_get_fmt,
1481153e4ad4SBenjamin Mugnier .set_fmt = vgxy61_set_fmt,
1482153e4ad4SBenjamin Mugnier .get_selection = vgxy61_get_selection,
1483153e4ad4SBenjamin Mugnier .enum_frame_size = vgxy61_enum_frame_size,
1484153e4ad4SBenjamin Mugnier };
1485153e4ad4SBenjamin Mugnier
1486153e4ad4SBenjamin Mugnier static const struct v4l2_subdev_ops vgxy61_subdev_ops = {
1487153e4ad4SBenjamin Mugnier .video = &vgxy61_video_ops,
1488153e4ad4SBenjamin Mugnier .pad = &vgxy61_pad_ops,
1489153e4ad4SBenjamin Mugnier };
1490153e4ad4SBenjamin Mugnier
1491153e4ad4SBenjamin Mugnier static const struct media_entity_operations vgxy61_subdev_entity_ops = {
1492153e4ad4SBenjamin Mugnier .link_validate = v4l2_subdev_link_validate,
1493153e4ad4SBenjamin Mugnier };
1494153e4ad4SBenjamin Mugnier
vgxy61_tx_from_ep(struct vgxy61_dev * sensor,struct fwnode_handle * handle)1495153e4ad4SBenjamin Mugnier static int vgxy61_tx_from_ep(struct vgxy61_dev *sensor,
1496153e4ad4SBenjamin Mugnier struct fwnode_handle *handle)
1497153e4ad4SBenjamin Mugnier {
1498153e4ad4SBenjamin Mugnier struct v4l2_fwnode_endpoint ep = { .bus_type = V4L2_MBUS_CSI2_DPHY };
1499153e4ad4SBenjamin Mugnier struct i2c_client *client = sensor->i2c_client;
1500153e4ad4SBenjamin Mugnier u32 log2phy[VGXY61_NB_POLARITIES] = {~0, ~0, ~0, ~0, ~0};
1501153e4ad4SBenjamin Mugnier u32 phy2log[VGXY61_NB_POLARITIES] = {~0, ~0, ~0, ~0, ~0};
1502153e4ad4SBenjamin Mugnier int polarities[VGXY61_NB_POLARITIES] = {0, 0, 0, 0, 0};
1503153e4ad4SBenjamin Mugnier int l_nb;
1504153e4ad4SBenjamin Mugnier unsigned int p, l, i;
1505153e4ad4SBenjamin Mugnier int ret;
1506153e4ad4SBenjamin Mugnier
1507153e4ad4SBenjamin Mugnier ret = v4l2_fwnode_endpoint_alloc_parse(handle, &ep);
1508153e4ad4SBenjamin Mugnier if (ret)
1509153e4ad4SBenjamin Mugnier return -EINVAL;
1510153e4ad4SBenjamin Mugnier
1511153e4ad4SBenjamin Mugnier l_nb = ep.bus.mipi_csi2.num_data_lanes;
1512153e4ad4SBenjamin Mugnier if (l_nb != 1 && l_nb != 2 && l_nb != 4) {
1513153e4ad4SBenjamin Mugnier dev_err(&client->dev, "invalid data lane number %d\n", l_nb);
1514153e4ad4SBenjamin Mugnier goto error_ep;
1515153e4ad4SBenjamin Mugnier }
1516153e4ad4SBenjamin Mugnier
1517153e4ad4SBenjamin Mugnier /* Build log2phy, phy2log and polarities from ep info */
1518153e4ad4SBenjamin Mugnier log2phy[0] = ep.bus.mipi_csi2.clock_lane;
1519153e4ad4SBenjamin Mugnier phy2log[log2phy[0]] = 0;
1520153e4ad4SBenjamin Mugnier for (l = 1; l < l_nb + 1; l++) {
1521153e4ad4SBenjamin Mugnier log2phy[l] = ep.bus.mipi_csi2.data_lanes[l - 1];
1522153e4ad4SBenjamin Mugnier phy2log[log2phy[l]] = l;
1523153e4ad4SBenjamin Mugnier }
1524153e4ad4SBenjamin Mugnier /*
1525153e4ad4SBenjamin Mugnier * Then fill remaining slots for every physical slot to have something
1526153e4ad4SBenjamin Mugnier * valid for hardware stuff.
1527153e4ad4SBenjamin Mugnier */
1528153e4ad4SBenjamin Mugnier for (p = 0; p < VGXY61_NB_POLARITIES; p++) {
1529153e4ad4SBenjamin Mugnier if (phy2log[p] != ~0)
1530153e4ad4SBenjamin Mugnier continue;
1531153e4ad4SBenjamin Mugnier phy2log[p] = l;
1532153e4ad4SBenjamin Mugnier log2phy[l] = p;
1533153e4ad4SBenjamin Mugnier l++;
1534153e4ad4SBenjamin Mugnier }
1535153e4ad4SBenjamin Mugnier for (l = 0; l < l_nb + 1; l++)
1536153e4ad4SBenjamin Mugnier polarities[l] = ep.bus.mipi_csi2.lane_polarities[l];
1537153e4ad4SBenjamin Mugnier
1538153e4ad4SBenjamin Mugnier if (log2phy[0] != 0) {
1539153e4ad4SBenjamin Mugnier dev_err(&client->dev, "clk lane must be map to physical lane 0\n");
1540153e4ad4SBenjamin Mugnier goto error_ep;
1541153e4ad4SBenjamin Mugnier }
1542153e4ad4SBenjamin Mugnier sensor->oif_ctrl = (polarities[4] << 15) + ((phy2log[4] - 1) << 13) +
1543153e4ad4SBenjamin Mugnier (polarities[3] << 12) + ((phy2log[3] - 1) << 10) +
1544153e4ad4SBenjamin Mugnier (polarities[2] << 9) + ((phy2log[2] - 1) << 7) +
1545153e4ad4SBenjamin Mugnier (polarities[1] << 6) + ((phy2log[1] - 1) << 4) +
1546153e4ad4SBenjamin Mugnier (polarities[0] << 3) +
1547153e4ad4SBenjamin Mugnier l_nb;
1548153e4ad4SBenjamin Mugnier sensor->nb_of_lane = l_nb;
1549153e4ad4SBenjamin Mugnier
1550153e4ad4SBenjamin Mugnier dev_dbg(&client->dev, "tx uses %d lanes", l_nb);
1551*c2402afcSBenjamin Mugnier for (i = 0; i < VGXY61_NB_POLARITIES; i++) {
1552153e4ad4SBenjamin Mugnier dev_dbg(&client->dev, "log2phy[%d] = %d\n", i, log2phy[i]);
1553153e4ad4SBenjamin Mugnier dev_dbg(&client->dev, "phy2log[%d] = %d\n", i, phy2log[i]);
1554153e4ad4SBenjamin Mugnier dev_dbg(&client->dev, "polarity[%d] = %d\n", i, polarities[i]);
1555153e4ad4SBenjamin Mugnier }
1556153e4ad4SBenjamin Mugnier dev_dbg(&client->dev, "oif_ctrl = 0x%04x\n", sensor->oif_ctrl);
1557153e4ad4SBenjamin Mugnier
1558153e4ad4SBenjamin Mugnier v4l2_fwnode_endpoint_free(&ep);
1559153e4ad4SBenjamin Mugnier
1560153e4ad4SBenjamin Mugnier return 0;
1561153e4ad4SBenjamin Mugnier
1562153e4ad4SBenjamin Mugnier error_ep:
1563153e4ad4SBenjamin Mugnier v4l2_fwnode_endpoint_free(&ep);
1564153e4ad4SBenjamin Mugnier
1565153e4ad4SBenjamin Mugnier return -EINVAL;
1566153e4ad4SBenjamin Mugnier }
1567153e4ad4SBenjamin Mugnier
vgxy61_configure(struct vgxy61_dev * sensor)1568153e4ad4SBenjamin Mugnier static int vgxy61_configure(struct vgxy61_dev *sensor)
1569153e4ad4SBenjamin Mugnier {
1570153e4ad4SBenjamin Mugnier u32 sensor_freq;
1571153e4ad4SBenjamin Mugnier u8 prediv, mult;
1572483af3feSBenjamin Mugnier int line_length;
1573153e4ad4SBenjamin Mugnier int ret = 0;
1574153e4ad4SBenjamin Mugnier
1575153e4ad4SBenjamin Mugnier compute_pll_parameters_by_freq(sensor->clk_freq, &prediv, &mult);
1576153e4ad4SBenjamin Mugnier sensor_freq = (mult * sensor->clk_freq) / prediv;
1577153e4ad4SBenjamin Mugnier /* Frequency to data rate is 1:1 ratio for MIPI */
1578153e4ad4SBenjamin Mugnier sensor->data_rate_in_mbps = sensor_freq;
1579153e4ad4SBenjamin Mugnier /* Video timing ISP path (pixel clock) requires 804/5 mhz = 160 mhz */
1580153e4ad4SBenjamin Mugnier sensor->pclk = sensor_freq / 5;
1581153e4ad4SBenjamin Mugnier
1582153e4ad4SBenjamin Mugnier line_length = vgxy61_read_reg(sensor, VGXY61_REG_LINE_LENGTH);
1583153e4ad4SBenjamin Mugnier if (line_length < 0)
1584153e4ad4SBenjamin Mugnier return line_length;
1585153e4ad4SBenjamin Mugnier sensor->line_length = line_length;
1586153e4ad4SBenjamin Mugnier vgxy61_write_reg(sensor, VGXY61_REG_EXT_CLOCK, sensor->clk_freq, &ret);
1587153e4ad4SBenjamin Mugnier vgxy61_write_reg(sensor, VGXY61_REG_CLK_PLL_PREDIV, prediv, &ret);
1588153e4ad4SBenjamin Mugnier vgxy61_write_reg(sensor, VGXY61_REG_CLK_SYS_PLL_MULT, mult, &ret);
1589153e4ad4SBenjamin Mugnier vgxy61_write_reg(sensor, VGXY61_REG_OIF_CTRL, sensor->oif_ctrl, &ret);
1590153e4ad4SBenjamin Mugnier vgxy61_write_reg(sensor, VGXY61_REG_FRAME_CONTENT_CTRL, 0, &ret);
1591153e4ad4SBenjamin Mugnier vgxy61_write_reg(sensor, VGXY61_REG_BYPASS_CTRL, 4, &ret);
1592153e4ad4SBenjamin Mugnier if (ret)
1593153e4ad4SBenjamin Mugnier return ret;
1594153e4ad4SBenjamin Mugnier vgxy61_update_gpios_strobe_polarity(sensor, sensor->gpios_polarity);
1595153e4ad4SBenjamin Mugnier /* Set pattern generator solid to middle value */
1596153e4ad4SBenjamin Mugnier vgxy61_write_reg(sensor, VGXY61_REG_PATGEN_LONG_DATA_GR, 0x800, &ret);
1597153e4ad4SBenjamin Mugnier vgxy61_write_reg(sensor, VGXY61_REG_PATGEN_LONG_DATA_R, 0x800, &ret);
1598153e4ad4SBenjamin Mugnier vgxy61_write_reg(sensor, VGXY61_REG_PATGEN_LONG_DATA_B, 0x800, &ret);
1599153e4ad4SBenjamin Mugnier vgxy61_write_reg(sensor, VGXY61_REG_PATGEN_LONG_DATA_GB, 0x800, &ret);
1600153e4ad4SBenjamin Mugnier vgxy61_write_reg(sensor, VGXY61_REG_PATGEN_SHORT_DATA_GR, 0x800, &ret);
1601153e4ad4SBenjamin Mugnier vgxy61_write_reg(sensor, VGXY61_REG_PATGEN_SHORT_DATA_R, 0x800, &ret);
1602153e4ad4SBenjamin Mugnier vgxy61_write_reg(sensor, VGXY61_REG_PATGEN_SHORT_DATA_B, 0x800, &ret);
1603153e4ad4SBenjamin Mugnier vgxy61_write_reg(sensor, VGXY61_REG_PATGEN_SHORT_DATA_GB, 0x800, &ret);
1604153e4ad4SBenjamin Mugnier if (ret)
1605153e4ad4SBenjamin Mugnier return ret;
1606153e4ad4SBenjamin Mugnier
1607153e4ad4SBenjamin Mugnier return 0;
1608153e4ad4SBenjamin Mugnier }
1609153e4ad4SBenjamin Mugnier
vgxy61_patch(struct vgxy61_dev * sensor)1610153e4ad4SBenjamin Mugnier static int vgxy61_patch(struct vgxy61_dev *sensor)
1611153e4ad4SBenjamin Mugnier {
1612153e4ad4SBenjamin Mugnier struct i2c_client *client = sensor->i2c_client;
1613483af3feSBenjamin Mugnier int patch, ret;
1614153e4ad4SBenjamin Mugnier
1615153e4ad4SBenjamin Mugnier ret = vgxy61_write_array(sensor, VGXY61_REG_FWPATCH_START_ADDR,
1616153e4ad4SBenjamin Mugnier sizeof(patch_array), patch_array);
1617153e4ad4SBenjamin Mugnier if (ret)
1618153e4ad4SBenjamin Mugnier return ret;
1619153e4ad4SBenjamin Mugnier
1620153e4ad4SBenjamin Mugnier ret = vgxy61_write_reg(sensor, VGXY61_REG_STBY, 0x10, NULL);
1621153e4ad4SBenjamin Mugnier if (ret)
1622153e4ad4SBenjamin Mugnier return ret;
1623153e4ad4SBenjamin Mugnier
1624153e4ad4SBenjamin Mugnier ret = vgxy61_poll_reg(sensor, VGXY61_REG_STBY, 0, VGXY61_TIMEOUT_MS);
1625153e4ad4SBenjamin Mugnier if (ret)
1626153e4ad4SBenjamin Mugnier return ret;
1627153e4ad4SBenjamin Mugnier
1628153e4ad4SBenjamin Mugnier patch = vgxy61_read_reg(sensor, VGXY61_REG_FWPATCH_REVISION);
1629153e4ad4SBenjamin Mugnier if (patch < 0)
1630153e4ad4SBenjamin Mugnier return patch;
1631153e4ad4SBenjamin Mugnier
1632153e4ad4SBenjamin Mugnier if (patch != (VGXY61_FWPATCH_REVISION_MAJOR << 12) +
1633153e4ad4SBenjamin Mugnier (VGXY61_FWPATCH_REVISION_MINOR << 8) +
1634153e4ad4SBenjamin Mugnier VGXY61_FWPATCH_REVISION_MICRO) {
1635153e4ad4SBenjamin Mugnier dev_err(&client->dev, "bad patch version expected %d.%d.%d got %d.%d.%d\n",
1636153e4ad4SBenjamin Mugnier VGXY61_FWPATCH_REVISION_MAJOR,
1637153e4ad4SBenjamin Mugnier VGXY61_FWPATCH_REVISION_MINOR,
1638153e4ad4SBenjamin Mugnier VGXY61_FWPATCH_REVISION_MICRO,
1639153e4ad4SBenjamin Mugnier patch >> 12, (patch >> 8) & 0x0f, patch & 0xff);
1640153e4ad4SBenjamin Mugnier return -ENODEV;
1641153e4ad4SBenjamin Mugnier }
1642153e4ad4SBenjamin Mugnier dev_dbg(&client->dev, "patch %d.%d.%d applied\n",
1643153e4ad4SBenjamin Mugnier patch >> 12, (patch >> 8) & 0x0f, patch & 0xff);
1644153e4ad4SBenjamin Mugnier
1645153e4ad4SBenjamin Mugnier return 0;
1646153e4ad4SBenjamin Mugnier }
1647153e4ad4SBenjamin Mugnier
vgxy61_detect_cut_version(struct vgxy61_dev * sensor)1648153e4ad4SBenjamin Mugnier static int vgxy61_detect_cut_version(struct vgxy61_dev *sensor)
1649153e4ad4SBenjamin Mugnier {
1650153e4ad4SBenjamin Mugnier struct i2c_client *client = sensor->i2c_client;
1651483af3feSBenjamin Mugnier int device_rev;
1652153e4ad4SBenjamin Mugnier
1653153e4ad4SBenjamin Mugnier device_rev = vgxy61_read_reg(sensor, VGXY61_REG_REVISION);
1654153e4ad4SBenjamin Mugnier if (device_rev < 0)
1655153e4ad4SBenjamin Mugnier return device_rev;
1656153e4ad4SBenjamin Mugnier
1657153e4ad4SBenjamin Mugnier switch (device_rev >> 8) {
1658153e4ad4SBenjamin Mugnier case 0xA:
1659153e4ad4SBenjamin Mugnier dev_dbg(&client->dev, "Cut1 detected\n");
1660153e4ad4SBenjamin Mugnier dev_err(&client->dev, "Cut1 not supported by this driver\n");
1661153e4ad4SBenjamin Mugnier return -ENODEV;
1662153e4ad4SBenjamin Mugnier case 0xB:
1663153e4ad4SBenjamin Mugnier dev_dbg(&client->dev, "Cut2 detected\n");
1664153e4ad4SBenjamin Mugnier return 0;
1665153e4ad4SBenjamin Mugnier case 0xC:
1666153e4ad4SBenjamin Mugnier dev_dbg(&client->dev, "Cut3 detected\n");
1667153e4ad4SBenjamin Mugnier return 0;
1668153e4ad4SBenjamin Mugnier default:
1669153e4ad4SBenjamin Mugnier dev_err(&client->dev, "Unable to detect cut version\n");
1670153e4ad4SBenjamin Mugnier return -ENODEV;
1671153e4ad4SBenjamin Mugnier }
1672153e4ad4SBenjamin Mugnier }
1673153e4ad4SBenjamin Mugnier
vgxy61_detect(struct vgxy61_dev * sensor)1674153e4ad4SBenjamin Mugnier static int vgxy61_detect(struct vgxy61_dev *sensor)
1675153e4ad4SBenjamin Mugnier {
1676153e4ad4SBenjamin Mugnier struct i2c_client *client = sensor->i2c_client;
1677483af3feSBenjamin Mugnier int id = 0;
1678483af3feSBenjamin Mugnier int ret, st;
1679153e4ad4SBenjamin Mugnier
1680153e4ad4SBenjamin Mugnier id = vgxy61_read_reg(sensor, VGXY61_REG_MODEL_ID);
1681153e4ad4SBenjamin Mugnier if (id < 0)
1682153e4ad4SBenjamin Mugnier return id;
1683153e4ad4SBenjamin Mugnier if (id != VG5661_MODEL_ID && id != VG5761_MODEL_ID) {
1684153e4ad4SBenjamin Mugnier dev_warn(&client->dev, "Unsupported sensor id %x\n", id);
1685153e4ad4SBenjamin Mugnier return -ENODEV;
1686153e4ad4SBenjamin Mugnier }
1687153e4ad4SBenjamin Mugnier dev_dbg(&client->dev, "detected sensor id = 0x%04x\n", id);
1688153e4ad4SBenjamin Mugnier sensor->id = id;
1689153e4ad4SBenjamin Mugnier
1690153e4ad4SBenjamin Mugnier ret = vgxy61_wait_state(sensor, VGXY61_SYSTEM_FSM_SW_STBY,
1691153e4ad4SBenjamin Mugnier VGXY61_TIMEOUT_MS);
1692153e4ad4SBenjamin Mugnier if (ret)
1693153e4ad4SBenjamin Mugnier return ret;
1694153e4ad4SBenjamin Mugnier
1695153e4ad4SBenjamin Mugnier st = vgxy61_read_reg(sensor, VGXY61_REG_NVM);
1696153e4ad4SBenjamin Mugnier if (st < 0)
1697153e4ad4SBenjamin Mugnier return st;
1698153e4ad4SBenjamin Mugnier if (st != VGXY61_NVM_OK)
1699153e4ad4SBenjamin Mugnier dev_warn(&client->dev, "Bad nvm state got %d\n", st);
1700153e4ad4SBenjamin Mugnier
1701153e4ad4SBenjamin Mugnier ret = vgxy61_detect_cut_version(sensor);
1702153e4ad4SBenjamin Mugnier if (ret)
1703153e4ad4SBenjamin Mugnier return ret;
1704153e4ad4SBenjamin Mugnier
1705153e4ad4SBenjamin Mugnier return 0;
1706153e4ad4SBenjamin Mugnier }
1707153e4ad4SBenjamin Mugnier
1708153e4ad4SBenjamin Mugnier /* Power/clock management functions */
vgxy61_power_on(struct device * dev)1709153e4ad4SBenjamin Mugnier static int vgxy61_power_on(struct device *dev)
1710153e4ad4SBenjamin Mugnier {
1711153e4ad4SBenjamin Mugnier struct i2c_client *client = to_i2c_client(dev);
1712153e4ad4SBenjamin Mugnier struct v4l2_subdev *sd = i2c_get_clientdata(client);
1713153e4ad4SBenjamin Mugnier struct vgxy61_dev *sensor = to_vgxy61_dev(sd);
1714153e4ad4SBenjamin Mugnier int ret;
1715153e4ad4SBenjamin Mugnier
171674b681bdSBenjamin Mugnier ret = regulator_bulk_enable(ARRAY_SIZE(vgxy61_supply_name),
171774b681bdSBenjamin Mugnier sensor->supplies);
171874b681bdSBenjamin Mugnier if (ret) {
171974b681bdSBenjamin Mugnier dev_err(&client->dev, "failed to enable regulators %d\n", ret);
172074b681bdSBenjamin Mugnier return ret;
172174b681bdSBenjamin Mugnier }
172274b681bdSBenjamin Mugnier
1723153e4ad4SBenjamin Mugnier ret = clk_prepare_enable(sensor->xclk);
1724153e4ad4SBenjamin Mugnier if (ret) {
1725153e4ad4SBenjamin Mugnier dev_err(&client->dev, "failed to enable clock %d\n", ret);
1726153e4ad4SBenjamin Mugnier goto disable_bulk;
1727153e4ad4SBenjamin Mugnier }
1728153e4ad4SBenjamin Mugnier
1729153e4ad4SBenjamin Mugnier if (sensor->reset_gpio) {
1730153e4ad4SBenjamin Mugnier ret = vgxy61_apply_reset(sensor);
1731153e4ad4SBenjamin Mugnier if (ret) {
1732153e4ad4SBenjamin Mugnier dev_err(&client->dev, "sensor reset failed %d\n", ret);
1733153e4ad4SBenjamin Mugnier goto disable_clock;
1734153e4ad4SBenjamin Mugnier }
1735153e4ad4SBenjamin Mugnier }
1736153e4ad4SBenjamin Mugnier
1737985ed1d7SBenjamin Mugnier ret = vgxy61_detect(sensor);
1738985ed1d7SBenjamin Mugnier if (ret) {
1739985ed1d7SBenjamin Mugnier dev_err(&client->dev, "sensor detect failed %d\n", ret);
1740985ed1d7SBenjamin Mugnier goto disable_clock;
1741985ed1d7SBenjamin Mugnier }
1742985ed1d7SBenjamin Mugnier
1743153e4ad4SBenjamin Mugnier ret = vgxy61_patch(sensor);
1744153e4ad4SBenjamin Mugnier if (ret) {
1745153e4ad4SBenjamin Mugnier dev_err(&client->dev, "sensor patch failed %d\n", ret);
1746153e4ad4SBenjamin Mugnier goto disable_clock;
1747153e4ad4SBenjamin Mugnier }
1748153e4ad4SBenjamin Mugnier
1749153e4ad4SBenjamin Mugnier ret = vgxy61_configure(sensor);
1750153e4ad4SBenjamin Mugnier if (ret) {
1751153e4ad4SBenjamin Mugnier dev_err(&client->dev, "sensor configuration failed %d\n", ret);
1752153e4ad4SBenjamin Mugnier goto disable_clock;
1753153e4ad4SBenjamin Mugnier }
1754153e4ad4SBenjamin Mugnier
1755153e4ad4SBenjamin Mugnier return 0;
1756153e4ad4SBenjamin Mugnier
1757153e4ad4SBenjamin Mugnier disable_clock:
1758153e4ad4SBenjamin Mugnier clk_disable_unprepare(sensor->xclk);
1759153e4ad4SBenjamin Mugnier disable_bulk:
1760153e4ad4SBenjamin Mugnier regulator_bulk_disable(ARRAY_SIZE(vgxy61_supply_name),
1761153e4ad4SBenjamin Mugnier sensor->supplies);
1762153e4ad4SBenjamin Mugnier
1763153e4ad4SBenjamin Mugnier return ret;
1764153e4ad4SBenjamin Mugnier }
1765153e4ad4SBenjamin Mugnier
vgxy61_power_off(struct device * dev)1766153e4ad4SBenjamin Mugnier static int vgxy61_power_off(struct device *dev)
1767153e4ad4SBenjamin Mugnier {
1768153e4ad4SBenjamin Mugnier struct i2c_client *client = to_i2c_client(dev);
1769153e4ad4SBenjamin Mugnier struct v4l2_subdev *sd = i2c_get_clientdata(client);
1770153e4ad4SBenjamin Mugnier struct vgxy61_dev *sensor = to_vgxy61_dev(sd);
1771153e4ad4SBenjamin Mugnier
1772153e4ad4SBenjamin Mugnier clk_disable_unprepare(sensor->xclk);
1773153e4ad4SBenjamin Mugnier regulator_bulk_disable(ARRAY_SIZE(vgxy61_supply_name),
1774153e4ad4SBenjamin Mugnier sensor->supplies);
1775153e4ad4SBenjamin Mugnier return 0;
1776153e4ad4SBenjamin Mugnier }
1777153e4ad4SBenjamin Mugnier
vgxy61_fill_sensor_param(struct vgxy61_dev * sensor)1778153e4ad4SBenjamin Mugnier static void vgxy61_fill_sensor_param(struct vgxy61_dev *sensor)
1779153e4ad4SBenjamin Mugnier {
1780153e4ad4SBenjamin Mugnier if (sensor->id == VG5761_MODEL_ID) {
1781153e4ad4SBenjamin Mugnier sensor->sensor_width = VGX761_WIDTH;
1782153e4ad4SBenjamin Mugnier sensor->sensor_height = VGX761_HEIGHT;
1783153e4ad4SBenjamin Mugnier sensor->sensor_modes = vgx761_mode_data;
1784153e4ad4SBenjamin Mugnier sensor->sensor_modes_nb = ARRAY_SIZE(vgx761_mode_data);
1785153e4ad4SBenjamin Mugnier sensor->default_mode = &vgx761_mode_data[VGX761_DEFAULT_MODE];
1786153e4ad4SBenjamin Mugnier sensor->rot_term = VGX761_SHORT_ROT_TERM;
1787153e4ad4SBenjamin Mugnier } else if (sensor->id == VG5661_MODEL_ID) {
1788153e4ad4SBenjamin Mugnier sensor->sensor_width = VGX661_WIDTH;
1789153e4ad4SBenjamin Mugnier sensor->sensor_height = VGX661_HEIGHT;
1790153e4ad4SBenjamin Mugnier sensor->sensor_modes = vgx661_mode_data;
1791153e4ad4SBenjamin Mugnier sensor->sensor_modes_nb = ARRAY_SIZE(vgx661_mode_data);
1792153e4ad4SBenjamin Mugnier sensor->default_mode = &vgx661_mode_data[VGX661_DEFAULT_MODE];
1793153e4ad4SBenjamin Mugnier sensor->rot_term = VGX661_SHORT_ROT_TERM;
1794153e4ad4SBenjamin Mugnier } else {
1795153e4ad4SBenjamin Mugnier /* Should never happen */
1796153e4ad4SBenjamin Mugnier WARN_ON(true);
1797153e4ad4SBenjamin Mugnier }
1798153e4ad4SBenjamin Mugnier sensor->current_mode = sensor->default_mode;
1799153e4ad4SBenjamin Mugnier }
1800153e4ad4SBenjamin Mugnier
vgxy61_probe(struct i2c_client * client)1801153e4ad4SBenjamin Mugnier static int vgxy61_probe(struct i2c_client *client)
1802153e4ad4SBenjamin Mugnier {
1803153e4ad4SBenjamin Mugnier struct device *dev = &client->dev;
1804153e4ad4SBenjamin Mugnier struct fwnode_handle *handle;
1805153e4ad4SBenjamin Mugnier struct vgxy61_dev *sensor;
1806153e4ad4SBenjamin Mugnier int ret;
1807153e4ad4SBenjamin Mugnier
1808153e4ad4SBenjamin Mugnier sensor = devm_kzalloc(dev, sizeof(*sensor), GFP_KERNEL);
1809153e4ad4SBenjamin Mugnier if (!sensor)
1810153e4ad4SBenjamin Mugnier return -ENOMEM;
1811153e4ad4SBenjamin Mugnier
1812153e4ad4SBenjamin Mugnier sensor->i2c_client = client;
1813153e4ad4SBenjamin Mugnier sensor->streaming = false;
1814153e4ad4SBenjamin Mugnier sensor->hdr = VGXY61_NO_HDR;
1815153e4ad4SBenjamin Mugnier sensor->expo_long = 200;
1816153e4ad4SBenjamin Mugnier sensor->expo_short = 0;
1817153e4ad4SBenjamin Mugnier sensor->hflip = false;
1818153e4ad4SBenjamin Mugnier sensor->vflip = false;
1819153e4ad4SBenjamin Mugnier sensor->analog_gain = 0;
1820153e4ad4SBenjamin Mugnier sensor->digital_gain = 256;
1821153e4ad4SBenjamin Mugnier
1822153e4ad4SBenjamin Mugnier handle = fwnode_graph_get_endpoint_by_id(dev_fwnode(dev), 0, 0, 0);
1823153e4ad4SBenjamin Mugnier if (!handle) {
1824153e4ad4SBenjamin Mugnier dev_err(dev, "handle node not found\n");
1825153e4ad4SBenjamin Mugnier return -EINVAL;
1826153e4ad4SBenjamin Mugnier }
1827153e4ad4SBenjamin Mugnier
1828153e4ad4SBenjamin Mugnier ret = vgxy61_tx_from_ep(sensor, handle);
1829153e4ad4SBenjamin Mugnier fwnode_handle_put(handle);
1830153e4ad4SBenjamin Mugnier if (ret) {
1831153e4ad4SBenjamin Mugnier dev_err(dev, "Failed to parse handle %d\n", ret);
1832153e4ad4SBenjamin Mugnier return ret;
1833153e4ad4SBenjamin Mugnier }
1834153e4ad4SBenjamin Mugnier
1835153e4ad4SBenjamin Mugnier sensor->xclk = devm_clk_get(dev, NULL);
1836153e4ad4SBenjamin Mugnier if (IS_ERR(sensor->xclk)) {
1837153e4ad4SBenjamin Mugnier dev_err(dev, "failed to get xclk\n");
1838153e4ad4SBenjamin Mugnier return PTR_ERR(sensor->xclk);
1839153e4ad4SBenjamin Mugnier }
1840153e4ad4SBenjamin Mugnier sensor->clk_freq = clk_get_rate(sensor->xclk);
1841153e4ad4SBenjamin Mugnier if (sensor->clk_freq < 6 * HZ_PER_MHZ ||
1842153e4ad4SBenjamin Mugnier sensor->clk_freq > 27 * HZ_PER_MHZ) {
1843153e4ad4SBenjamin Mugnier dev_err(dev, "Only 6Mhz-27Mhz clock range supported. provide %lu MHz\n",
1844153e4ad4SBenjamin Mugnier sensor->clk_freq / HZ_PER_MHZ);
1845153e4ad4SBenjamin Mugnier return -EINVAL;
1846153e4ad4SBenjamin Mugnier }
1847153e4ad4SBenjamin Mugnier sensor->gpios_polarity =
1848153e4ad4SBenjamin Mugnier device_property_read_bool(dev, "st,strobe-gpios-polarity");
1849153e4ad4SBenjamin Mugnier
1850153e4ad4SBenjamin Mugnier v4l2_i2c_subdev_init(&sensor->sd, client, &vgxy61_subdev_ops);
1851153e4ad4SBenjamin Mugnier sensor->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
1852153e4ad4SBenjamin Mugnier sensor->pad.flags = MEDIA_PAD_FL_SOURCE;
1853153e4ad4SBenjamin Mugnier sensor->sd.entity.ops = &vgxy61_subdev_entity_ops;
1854153e4ad4SBenjamin Mugnier sensor->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
1855153e4ad4SBenjamin Mugnier
1856153e4ad4SBenjamin Mugnier sensor->reset_gpio = devm_gpiod_get_optional(dev, "reset",
1857153e4ad4SBenjamin Mugnier GPIOD_OUT_HIGH);
1858153e4ad4SBenjamin Mugnier
1859153e4ad4SBenjamin Mugnier ret = vgxy61_get_regulators(sensor);
1860153e4ad4SBenjamin Mugnier if (ret) {
1861153e4ad4SBenjamin Mugnier dev_err(&client->dev, "failed to get regulators %d\n", ret);
1862153e4ad4SBenjamin Mugnier return ret;
1863153e4ad4SBenjamin Mugnier }
1864153e4ad4SBenjamin Mugnier
1865153e4ad4SBenjamin Mugnier ret = vgxy61_power_on(dev);
1866153e4ad4SBenjamin Mugnier if (ret)
1867153e4ad4SBenjamin Mugnier return ret;
1868153e4ad4SBenjamin Mugnier
1869153e4ad4SBenjamin Mugnier vgxy61_fill_sensor_param(sensor);
1870153e4ad4SBenjamin Mugnier vgxy61_fill_framefmt(sensor, sensor->current_mode, &sensor->fmt,
1871153e4ad4SBenjamin Mugnier VGXY61_MEDIA_BUS_FMT_DEF);
1872153e4ad4SBenjamin Mugnier
187344b22d45SBenjamin Mugnier mutex_init(&sensor->lock);
187444b22d45SBenjamin Mugnier
1875153e4ad4SBenjamin Mugnier ret = vgxy61_update_hdr(sensor, sensor->hdr);
1876153e4ad4SBenjamin Mugnier if (ret)
187744b22d45SBenjamin Mugnier goto error_power_off;
1878153e4ad4SBenjamin Mugnier
1879153e4ad4SBenjamin Mugnier ret = vgxy61_init_controls(sensor);
1880153e4ad4SBenjamin Mugnier if (ret) {
1881153e4ad4SBenjamin Mugnier dev_err(&client->dev, "controls initialization failed %d\n",
1882153e4ad4SBenjamin Mugnier ret);
1883153e4ad4SBenjamin Mugnier goto error_power_off;
1884153e4ad4SBenjamin Mugnier }
1885153e4ad4SBenjamin Mugnier
1886153e4ad4SBenjamin Mugnier ret = media_entity_pads_init(&sensor->sd.entity, 1, &sensor->pad);
1887153e4ad4SBenjamin Mugnier if (ret) {
1888153e4ad4SBenjamin Mugnier dev_err(&client->dev, "pads init failed %d\n", ret);
1889153e4ad4SBenjamin Mugnier goto error_handler_free;
1890153e4ad4SBenjamin Mugnier }
1891153e4ad4SBenjamin Mugnier
1892153e4ad4SBenjamin Mugnier /* Enable runtime PM and turn off the device */
1893153e4ad4SBenjamin Mugnier pm_runtime_set_active(dev);
1894153e4ad4SBenjamin Mugnier pm_runtime_enable(dev);
1895153e4ad4SBenjamin Mugnier pm_runtime_idle(dev);
1896153e4ad4SBenjamin Mugnier
1897153e4ad4SBenjamin Mugnier ret = v4l2_async_register_subdev(&sensor->sd);
1898153e4ad4SBenjamin Mugnier if (ret) {
1899153e4ad4SBenjamin Mugnier dev_err(&client->dev, "async subdev register failed %d\n", ret);
1900153e4ad4SBenjamin Mugnier goto error_pm_runtime;
1901153e4ad4SBenjamin Mugnier }
1902153e4ad4SBenjamin Mugnier
1903153e4ad4SBenjamin Mugnier pm_runtime_set_autosuspend_delay(&client->dev, 1000);
1904153e4ad4SBenjamin Mugnier pm_runtime_use_autosuspend(&client->dev);
1905153e4ad4SBenjamin Mugnier
1906153e4ad4SBenjamin Mugnier dev_dbg(&client->dev, "vgxy61 probe successfully\n");
1907153e4ad4SBenjamin Mugnier
1908153e4ad4SBenjamin Mugnier return 0;
1909153e4ad4SBenjamin Mugnier
1910153e4ad4SBenjamin Mugnier error_pm_runtime:
1911153e4ad4SBenjamin Mugnier pm_runtime_disable(&client->dev);
1912153e4ad4SBenjamin Mugnier pm_runtime_set_suspended(&client->dev);
1913153e4ad4SBenjamin Mugnier media_entity_cleanup(&sensor->sd.entity);
1914153e4ad4SBenjamin Mugnier error_handler_free:
1915153e4ad4SBenjamin Mugnier v4l2_ctrl_handler_free(sensor->sd.ctrl_handler);
1916153e4ad4SBenjamin Mugnier error_power_off:
191744b22d45SBenjamin Mugnier mutex_destroy(&sensor->lock);
1918153e4ad4SBenjamin Mugnier vgxy61_power_off(dev);
1919153e4ad4SBenjamin Mugnier
1920153e4ad4SBenjamin Mugnier return ret;
1921153e4ad4SBenjamin Mugnier }
1922153e4ad4SBenjamin Mugnier
vgxy61_remove(struct i2c_client * client)1923153e4ad4SBenjamin Mugnier static void vgxy61_remove(struct i2c_client *client)
1924153e4ad4SBenjamin Mugnier {
1925153e4ad4SBenjamin Mugnier struct v4l2_subdev *sd = i2c_get_clientdata(client);
1926153e4ad4SBenjamin Mugnier struct vgxy61_dev *sensor = to_vgxy61_dev(sd);
1927153e4ad4SBenjamin Mugnier
1928153e4ad4SBenjamin Mugnier v4l2_async_unregister_subdev(&sensor->sd);
1929153e4ad4SBenjamin Mugnier mutex_destroy(&sensor->lock);
1930153e4ad4SBenjamin Mugnier media_entity_cleanup(&sensor->sd.entity);
1931153e4ad4SBenjamin Mugnier
1932153e4ad4SBenjamin Mugnier pm_runtime_disable(&client->dev);
1933153e4ad4SBenjamin Mugnier if (!pm_runtime_status_suspended(&client->dev))
1934153e4ad4SBenjamin Mugnier vgxy61_power_off(&client->dev);
1935153e4ad4SBenjamin Mugnier pm_runtime_set_suspended(&client->dev);
1936153e4ad4SBenjamin Mugnier }
1937153e4ad4SBenjamin Mugnier
1938153e4ad4SBenjamin Mugnier static const struct of_device_id vgxy61_dt_ids[] = {
1939153e4ad4SBenjamin Mugnier { .compatible = "st,st-vgxy61" },
1940153e4ad4SBenjamin Mugnier { /* sentinel */ }
1941153e4ad4SBenjamin Mugnier };
1942153e4ad4SBenjamin Mugnier MODULE_DEVICE_TABLE(of, vgxy61_dt_ids);
1943153e4ad4SBenjamin Mugnier
1944153e4ad4SBenjamin Mugnier static const struct dev_pm_ops vgxy61_pm_ops = {
1945153e4ad4SBenjamin Mugnier SET_RUNTIME_PM_OPS(vgxy61_power_off, vgxy61_power_on, NULL)
1946153e4ad4SBenjamin Mugnier };
1947153e4ad4SBenjamin Mugnier
1948153e4ad4SBenjamin Mugnier static struct i2c_driver vgxy61_i2c_driver = {
1949153e4ad4SBenjamin Mugnier .driver = {
1950153e4ad4SBenjamin Mugnier .name = "st-vgxy61",
1951153e4ad4SBenjamin Mugnier .of_match_table = vgxy61_dt_ids,
1952153e4ad4SBenjamin Mugnier .pm = &vgxy61_pm_ops,
1953153e4ad4SBenjamin Mugnier },
1954153e4ad4SBenjamin Mugnier .probe = vgxy61_probe,
1955153e4ad4SBenjamin Mugnier .remove = vgxy61_remove,
1956153e4ad4SBenjamin Mugnier };
1957153e4ad4SBenjamin Mugnier
1958153e4ad4SBenjamin Mugnier module_i2c_driver(vgxy61_i2c_driver);
1959153e4ad4SBenjamin Mugnier
1960153e4ad4SBenjamin Mugnier MODULE_AUTHOR("Benjamin Mugnier <benjamin.mugnier@foss.st.com>");
1961153e4ad4SBenjamin Mugnier MODULE_AUTHOR("Mickael Guene <mickael.guene@st.com>");
1962153e4ad4SBenjamin Mugnier MODULE_AUTHOR("Sylvain Petinot <sylvain.petinot@foss.st.com>");
1963153e4ad4SBenjamin Mugnier MODULE_DESCRIPTION("VGXY61 camera subdev driver");
1964153e4ad4SBenjamin Mugnier MODULE_LICENSE("GPL");
1965