1bf27502bSShawn Tu // SPDX-License-Identifier: GPL-2.0
2bf27502bSShawn Tu // Copyright (c) 2019 Intel Corporation.
3bf27502bSShawn Tu
4bf27502bSShawn Tu #include <asm/unaligned.h>
5bf27502bSShawn Tu #include <linux/acpi.h>
649d9ad71SQuentin Schulz #include <linux/clk.h>
7bf27502bSShawn Tu #include <linux/delay.h>
849d9ad71SQuentin Schulz #include <linux/gpio/consumer.h>
9bf27502bSShawn Tu #include <linux/i2c.h>
1049d9ad71SQuentin Schulz #include <linux/mod_devicetable.h>
11bf27502bSShawn Tu #include <linux/module.h>
12bf27502bSShawn Tu #include <linux/pm_runtime.h>
1349d9ad71SQuentin Schulz #include <linux/regulator/consumer.h>
14bf27502bSShawn Tu #include <media/v4l2-ctrls.h>
15bf27502bSShawn Tu #include <media/v4l2-device.h>
16bf27502bSShawn Tu #include <media/v4l2-fwnode.h>
17bf27502bSShawn Tu
18bf27502bSShawn Tu #define OV5675_REG_VALUE_08BIT 1
19bf27502bSShawn Tu #define OV5675_REG_VALUE_16BIT 2
20bf27502bSShawn Tu #define OV5675_REG_VALUE_24BIT 3
21bf27502bSShawn Tu
22bf27502bSShawn Tu #define OV5675_LINK_FREQ_450MHZ 450000000ULL
23bf27502bSShawn Tu #define OV5675_SCLK 90000000LL
2449d9ad71SQuentin Schulz #define OV5675_XVCLK_19_2 19200000
25bf27502bSShawn Tu #define OV5675_DATA_LANES 2
26bf27502bSShawn Tu #define OV5675_RGB_DEPTH 10
27bf27502bSShawn Tu
28bf27502bSShawn Tu #define OV5675_REG_CHIP_ID 0x300a
29bf27502bSShawn Tu #define OV5675_CHIP_ID 0x5675
30bf27502bSShawn Tu
31bf27502bSShawn Tu #define OV5675_REG_MODE_SELECT 0x0100
32bf27502bSShawn Tu #define OV5675_MODE_STANDBY 0x00
33bf27502bSShawn Tu #define OV5675_MODE_STREAMING 0x01
34bf27502bSShawn Tu
35bf27502bSShawn Tu /* vertical-timings from sensor */
36bf27502bSShawn Tu #define OV5675_REG_VTS 0x380e
37bf27502bSShawn Tu #define OV5675_VTS_30FPS 0x07e4
38bf27502bSShawn Tu #define OV5675_VTS_30FPS_MIN 0x07e4
39bf27502bSShawn Tu #define OV5675_VTS_MAX 0x7fff
40bf27502bSShawn Tu
41bf27502bSShawn Tu /* horizontal-timings from sensor */
42bf27502bSShawn Tu #define OV5675_REG_HTS 0x380c
43bf27502bSShawn Tu
44bf27502bSShawn Tu /* Exposure controls from sensor */
45bf27502bSShawn Tu #define OV5675_REG_EXPOSURE 0x3500
46bf27502bSShawn Tu #define OV5675_EXPOSURE_MIN 4
47bf27502bSShawn Tu #define OV5675_EXPOSURE_MAX_MARGIN 4
48bf27502bSShawn Tu #define OV5675_EXPOSURE_STEP 1
49bf27502bSShawn Tu
50bf27502bSShawn Tu /* Analog gain controls from sensor */
51bf27502bSShawn Tu #define OV5675_REG_ANALOG_GAIN 0x3508
52bf27502bSShawn Tu #define OV5675_ANAL_GAIN_MIN 128
53bf27502bSShawn Tu #define OV5675_ANAL_GAIN_MAX 2047
54bf27502bSShawn Tu #define OV5675_ANAL_GAIN_STEP 1
55bf27502bSShawn Tu
56bf27502bSShawn Tu /* Digital gain controls from sensor */
5724e9edc1SBingbu Cao #define OV5675_REG_DIGITAL_GAIN 0x350a
58bf27502bSShawn Tu #define OV5675_REG_MWB_R_GAIN 0x5019
59bf27502bSShawn Tu #define OV5675_REG_MWB_G_GAIN 0x501b
60bf27502bSShawn Tu #define OV5675_REG_MWB_B_GAIN 0x501d
6124e9edc1SBingbu Cao #define OV5675_DGTL_GAIN_MIN 1024
62bf27502bSShawn Tu #define OV5675_DGTL_GAIN_MAX 4095
63bf27502bSShawn Tu #define OV5675_DGTL_GAIN_STEP 1
64bf27502bSShawn Tu #define OV5675_DGTL_GAIN_DEFAULT 1024
65bf27502bSShawn Tu
6624e9edc1SBingbu Cao /* Group Access */
6724e9edc1SBingbu Cao #define OV5675_REG_GROUP_ACCESS 0x3208
6824e9edc1SBingbu Cao #define OV5675_GROUP_HOLD_START 0x0
6924e9edc1SBingbu Cao #define OV5675_GROUP_HOLD_END 0x10
7024e9edc1SBingbu Cao #define OV5675_GROUP_HOLD_LAUNCH 0xa0
7124e9edc1SBingbu Cao
72bf27502bSShawn Tu /* Test Pattern Control */
73bf27502bSShawn Tu #define OV5675_REG_TEST_PATTERN 0x4503
74bf27502bSShawn Tu #define OV5675_TEST_PATTERN_ENABLE BIT(7)
75bf27502bSShawn Tu #define OV5675_TEST_PATTERN_BAR_SHIFT 2
76bf27502bSShawn Tu
77e8882e1bSShawn Tu /* Flip Mirror Controls from sensor */
78e8882e1bSShawn Tu #define OV5675_REG_FORMAT1 0x3820
79e8882e1bSShawn Tu #define OV5675_REG_FORMAT2 0x373d
80e8882e1bSShawn Tu
81bf27502bSShawn Tu #define to_ov5675(_sd) container_of(_sd, struct ov5675, sd)
82bf27502bSShawn Tu
8349d9ad71SQuentin Schulz static const char * const ov5675_supply_names[] = {
8449d9ad71SQuentin Schulz "avdd", /* Analog power */
8549d9ad71SQuentin Schulz "dovdd", /* Digital I/O power */
8649d9ad71SQuentin Schulz "dvdd", /* Digital core power */
8749d9ad71SQuentin Schulz };
8849d9ad71SQuentin Schulz
8949d9ad71SQuentin Schulz #define OV5675_NUM_SUPPLIES ARRAY_SIZE(ov5675_supply_names)
9049d9ad71SQuentin Schulz
91bf27502bSShawn Tu enum {
92bf27502bSShawn Tu OV5675_LINK_FREQ_900MBPS,
93bf27502bSShawn Tu };
94bf27502bSShawn Tu
95bf27502bSShawn Tu struct ov5675_reg {
96bf27502bSShawn Tu u16 address;
97bf27502bSShawn Tu u8 val;
98bf27502bSShawn Tu };
99bf27502bSShawn Tu
100bf27502bSShawn Tu struct ov5675_reg_list {
101bf27502bSShawn Tu u32 num_of_regs;
102bf27502bSShawn Tu const struct ov5675_reg *regs;
103bf27502bSShawn Tu };
104bf27502bSShawn Tu
105bf27502bSShawn Tu struct ov5675_link_freq_config {
106bf27502bSShawn Tu const struct ov5675_reg_list reg_list;
107bf27502bSShawn Tu };
108bf27502bSShawn Tu
109bf27502bSShawn Tu struct ov5675_mode {
110bf27502bSShawn Tu /* Frame width in pixels */
111bf27502bSShawn Tu u32 width;
112bf27502bSShawn Tu
113bf27502bSShawn Tu /* Frame height in pixels */
114bf27502bSShawn Tu u32 height;
115bf27502bSShawn Tu
116bf27502bSShawn Tu /* Horizontal timining size */
117bf27502bSShawn Tu u32 hts;
118bf27502bSShawn Tu
119bf27502bSShawn Tu /* Default vertical timining size */
120bf27502bSShawn Tu u32 vts_def;
121bf27502bSShawn Tu
122bf27502bSShawn Tu /* Min vertical timining size */
123bf27502bSShawn Tu u32 vts_min;
124bf27502bSShawn Tu
125bf27502bSShawn Tu /* Link frequency needed for this resolution */
126bf27502bSShawn Tu u32 link_freq_index;
127bf27502bSShawn Tu
128bf27502bSShawn Tu /* Sensor register settings for this resolution */
129bf27502bSShawn Tu const struct ov5675_reg_list reg_list;
130bf27502bSShawn Tu };
131bf27502bSShawn Tu
132bf27502bSShawn Tu static const struct ov5675_reg mipi_data_rate_900mbps[] = {
133bf27502bSShawn Tu {0x0103, 0x01},
134bf27502bSShawn Tu {0x0100, 0x00},
135bf27502bSShawn Tu {0x0300, 0x04},
136bf27502bSShawn Tu {0x0302, 0x8d},
137bf27502bSShawn Tu {0x0303, 0x00},
138bf27502bSShawn Tu {0x030d, 0x26},
139bf27502bSShawn Tu };
140bf27502bSShawn Tu
141bf27502bSShawn Tu static const struct ov5675_reg mode_2592x1944_regs[] = {
142bf27502bSShawn Tu {0x3002, 0x21},
143bf27502bSShawn Tu {0x3107, 0x23},
144bf27502bSShawn Tu {0x3501, 0x20},
145bf27502bSShawn Tu {0x3503, 0x0c},
146bf27502bSShawn Tu {0x3508, 0x03},
147bf27502bSShawn Tu {0x3509, 0x00},
148bf27502bSShawn Tu {0x3600, 0x66},
149bf27502bSShawn Tu {0x3602, 0x30},
150bf27502bSShawn Tu {0x3610, 0xa5},
151bf27502bSShawn Tu {0x3612, 0x93},
152bf27502bSShawn Tu {0x3620, 0x80},
153bf27502bSShawn Tu {0x3642, 0x0e},
154bf27502bSShawn Tu {0x3661, 0x00},
155bf27502bSShawn Tu {0x3662, 0x10},
156bf27502bSShawn Tu {0x3664, 0xf3},
157bf27502bSShawn Tu {0x3665, 0x9e},
158bf27502bSShawn Tu {0x3667, 0xa5},
159bf27502bSShawn Tu {0x366e, 0x55},
160bf27502bSShawn Tu {0x366f, 0x55},
161bf27502bSShawn Tu {0x3670, 0x11},
162bf27502bSShawn Tu {0x3671, 0x11},
163bf27502bSShawn Tu {0x3672, 0x11},
164bf27502bSShawn Tu {0x3673, 0x11},
165bf27502bSShawn Tu {0x3714, 0x24},
166bf27502bSShawn Tu {0x371a, 0x3e},
167bf27502bSShawn Tu {0x3733, 0x10},
168bf27502bSShawn Tu {0x3734, 0x00},
169bf27502bSShawn Tu {0x373d, 0x24},
170bf27502bSShawn Tu {0x3764, 0x20},
171bf27502bSShawn Tu {0x3765, 0x20},
172bf27502bSShawn Tu {0x3766, 0x12},
173bf27502bSShawn Tu {0x37a1, 0x14},
174bf27502bSShawn Tu {0x37a8, 0x1c},
175bf27502bSShawn Tu {0x37ab, 0x0f},
176bf27502bSShawn Tu {0x37c2, 0x04},
177bf27502bSShawn Tu {0x37cb, 0x00},
178bf27502bSShawn Tu {0x37cc, 0x00},
179bf27502bSShawn Tu {0x37cd, 0x00},
180bf27502bSShawn Tu {0x37ce, 0x00},
181bf27502bSShawn Tu {0x37d8, 0x02},
182bf27502bSShawn Tu {0x37d9, 0x08},
183bf27502bSShawn Tu {0x37dc, 0x04},
184bf27502bSShawn Tu {0x3800, 0x00},
185bf27502bSShawn Tu {0x3801, 0x00},
186bf27502bSShawn Tu {0x3802, 0x00},
187bf27502bSShawn Tu {0x3803, 0x04},
188bf27502bSShawn Tu {0x3804, 0x0a},
189bf27502bSShawn Tu {0x3805, 0x3f},
190bf27502bSShawn Tu {0x3806, 0x07},
191bf27502bSShawn Tu {0x3807, 0xb3},
192bf27502bSShawn Tu {0x3808, 0x0a},
193bf27502bSShawn Tu {0x3809, 0x20},
194bf27502bSShawn Tu {0x380a, 0x07},
195bf27502bSShawn Tu {0x380b, 0x98},
196bf27502bSShawn Tu {0x380c, 0x02},
197bf27502bSShawn Tu {0x380d, 0xee},
198bf27502bSShawn Tu {0x380e, 0x07},
199bf27502bSShawn Tu {0x380f, 0xe4},
200bf27502bSShawn Tu {0x3811, 0x10},
201bf27502bSShawn Tu {0x3813, 0x0d},
202bf27502bSShawn Tu {0x3814, 0x01},
203bf27502bSShawn Tu {0x3815, 0x01},
204bf27502bSShawn Tu {0x3816, 0x01},
205bf27502bSShawn Tu {0x3817, 0x01},
206bf27502bSShawn Tu {0x381e, 0x02},
207bf27502bSShawn Tu {0x3820, 0x88},
208bf27502bSShawn Tu {0x3821, 0x01},
209bf27502bSShawn Tu {0x3832, 0x04},
210bf27502bSShawn Tu {0x3c80, 0x01},
211bf27502bSShawn Tu {0x3c82, 0x00},
212bf27502bSShawn Tu {0x3c83, 0xc8},
213bf27502bSShawn Tu {0x3c8c, 0x0f},
214bf27502bSShawn Tu {0x3c8d, 0xa0},
215bf27502bSShawn Tu {0x3c90, 0x07},
216bf27502bSShawn Tu {0x3c91, 0x00},
217bf27502bSShawn Tu {0x3c92, 0x00},
218bf27502bSShawn Tu {0x3c93, 0x00},
219bf27502bSShawn Tu {0x3c94, 0xd0},
220bf27502bSShawn Tu {0x3c95, 0x50},
221bf27502bSShawn Tu {0x3c96, 0x35},
222bf27502bSShawn Tu {0x3c97, 0x00},
223bf27502bSShawn Tu {0x4001, 0xe0},
224bf27502bSShawn Tu {0x4008, 0x02},
225bf27502bSShawn Tu {0x4009, 0x0d},
226bf27502bSShawn Tu {0x400f, 0x80},
227bf27502bSShawn Tu {0x4013, 0x02},
228bf27502bSShawn Tu {0x4040, 0x00},
229bf27502bSShawn Tu {0x4041, 0x07},
230bf27502bSShawn Tu {0x404c, 0x50},
231bf27502bSShawn Tu {0x404e, 0x20},
232bf27502bSShawn Tu {0x4500, 0x06},
233bf27502bSShawn Tu {0x4503, 0x00},
234bf27502bSShawn Tu {0x450a, 0x04},
235bf27502bSShawn Tu {0x4809, 0x04},
236bf27502bSShawn Tu {0x480c, 0x12},
237bf27502bSShawn Tu {0x4819, 0x70},
238bf27502bSShawn Tu {0x4825, 0x32},
239bf27502bSShawn Tu {0x4826, 0x32},
240bf27502bSShawn Tu {0x482a, 0x06},
241bf27502bSShawn Tu {0x4833, 0x08},
242bf27502bSShawn Tu {0x4837, 0x0d},
243bf27502bSShawn Tu {0x5000, 0x77},
244bf27502bSShawn Tu {0x5b00, 0x01},
245bf27502bSShawn Tu {0x5b01, 0x10},
246bf27502bSShawn Tu {0x5b02, 0x01},
247bf27502bSShawn Tu {0x5b03, 0xdb},
248bf27502bSShawn Tu {0x5b05, 0x6c},
249bf27502bSShawn Tu {0x5e10, 0xfc},
250bf27502bSShawn Tu {0x3500, 0x00},
251bf27502bSShawn Tu {0x3501, 0x3E},
252bf27502bSShawn Tu {0x3502, 0x60},
253bf27502bSShawn Tu {0x3503, 0x08},
254bf27502bSShawn Tu {0x3508, 0x04},
255bf27502bSShawn Tu {0x3509, 0x00},
256bf27502bSShawn Tu {0x3832, 0x48},
257bf27502bSShawn Tu {0x5780, 0x3e},
258bf27502bSShawn Tu {0x5781, 0x0f},
259bf27502bSShawn Tu {0x5782, 0x44},
260bf27502bSShawn Tu {0x5783, 0x02},
261bf27502bSShawn Tu {0x5784, 0x01},
262bf27502bSShawn Tu {0x5785, 0x01},
263bf27502bSShawn Tu {0x5786, 0x00},
264bf27502bSShawn Tu {0x5787, 0x04},
265bf27502bSShawn Tu {0x5788, 0x02},
266bf27502bSShawn Tu {0x5789, 0x0f},
267bf27502bSShawn Tu {0x578a, 0xfd},
268bf27502bSShawn Tu {0x578b, 0xf5},
269bf27502bSShawn Tu {0x578c, 0xf5},
270bf27502bSShawn Tu {0x578d, 0x03},
271bf27502bSShawn Tu {0x578e, 0x08},
272bf27502bSShawn Tu {0x578f, 0x0c},
273bf27502bSShawn Tu {0x5790, 0x08},
274bf27502bSShawn Tu {0x5791, 0x06},
275bf27502bSShawn Tu {0x5792, 0x00},
276bf27502bSShawn Tu {0x5793, 0x52},
277bf27502bSShawn Tu {0x5794, 0xa3},
278bf27502bSShawn Tu {0x4003, 0x40},
279bf27502bSShawn Tu {0x3107, 0x01},
280bf27502bSShawn Tu {0x3c80, 0x08},
281bf27502bSShawn Tu {0x3c83, 0xb1},
282bf27502bSShawn Tu {0x3c8c, 0x10},
283bf27502bSShawn Tu {0x3c8d, 0x00},
284bf27502bSShawn Tu {0x3c90, 0x00},
285bf27502bSShawn Tu {0x3c94, 0x00},
286bf27502bSShawn Tu {0x3c95, 0x00},
287bf27502bSShawn Tu {0x3c96, 0x00},
288bf27502bSShawn Tu {0x37cb, 0x09},
289bf27502bSShawn Tu {0x37cc, 0x15},
290bf27502bSShawn Tu {0x37cd, 0x1f},
291bf27502bSShawn Tu {0x37ce, 0x1f},
292bf27502bSShawn Tu };
293bf27502bSShawn Tu
294bf27502bSShawn Tu static const struct ov5675_reg mode_1296x972_regs[] = {
295bf27502bSShawn Tu {0x3002, 0x21},
296bf27502bSShawn Tu {0x3107, 0x23},
297bf27502bSShawn Tu {0x3501, 0x20},
298bf27502bSShawn Tu {0x3503, 0x0c},
299bf27502bSShawn Tu {0x3508, 0x03},
300bf27502bSShawn Tu {0x3509, 0x00},
301bf27502bSShawn Tu {0x3600, 0x66},
302bf27502bSShawn Tu {0x3602, 0x30},
303bf27502bSShawn Tu {0x3610, 0xa5},
304bf27502bSShawn Tu {0x3612, 0x93},
305bf27502bSShawn Tu {0x3620, 0x80},
306bf27502bSShawn Tu {0x3642, 0x0e},
307bf27502bSShawn Tu {0x3661, 0x00},
308bf27502bSShawn Tu {0x3662, 0x08},
309bf27502bSShawn Tu {0x3664, 0xf3},
310bf27502bSShawn Tu {0x3665, 0x9e},
311bf27502bSShawn Tu {0x3667, 0xa5},
312bf27502bSShawn Tu {0x366e, 0x55},
313bf27502bSShawn Tu {0x366f, 0x55},
314bf27502bSShawn Tu {0x3670, 0x11},
315bf27502bSShawn Tu {0x3671, 0x11},
316bf27502bSShawn Tu {0x3672, 0x11},
317bf27502bSShawn Tu {0x3673, 0x11},
318bf27502bSShawn Tu {0x3714, 0x28},
319bf27502bSShawn Tu {0x371a, 0x3e},
320bf27502bSShawn Tu {0x3733, 0x10},
321bf27502bSShawn Tu {0x3734, 0x00},
322bf27502bSShawn Tu {0x373d, 0x24},
323bf27502bSShawn Tu {0x3764, 0x20},
324bf27502bSShawn Tu {0x3765, 0x20},
325bf27502bSShawn Tu {0x3766, 0x12},
326bf27502bSShawn Tu {0x37a1, 0x14},
327bf27502bSShawn Tu {0x37a8, 0x1c},
328bf27502bSShawn Tu {0x37ab, 0x0f},
329bf27502bSShawn Tu {0x37c2, 0x14},
330bf27502bSShawn Tu {0x37cb, 0x00},
331bf27502bSShawn Tu {0x37cc, 0x00},
332bf27502bSShawn Tu {0x37cd, 0x00},
333bf27502bSShawn Tu {0x37ce, 0x00},
334bf27502bSShawn Tu {0x37d8, 0x02},
335bf27502bSShawn Tu {0x37d9, 0x04},
336bf27502bSShawn Tu {0x37dc, 0x04},
337bf27502bSShawn Tu {0x3800, 0x00},
338bf27502bSShawn Tu {0x3801, 0x00},
339bf27502bSShawn Tu {0x3802, 0x00},
340e8882e1bSShawn Tu {0x3803, 0x00},
341bf27502bSShawn Tu {0x3804, 0x0a},
342bf27502bSShawn Tu {0x3805, 0x3f},
343e8882e1bSShawn Tu {0x3806, 0x07},
344e8882e1bSShawn Tu {0x3807, 0xb7},
345bf27502bSShawn Tu {0x3808, 0x05},
346e8882e1bSShawn Tu {0x3809, 0x10},
347e8882e1bSShawn Tu {0x380a, 0x03},
348e8882e1bSShawn Tu {0x380b, 0xcc},
349bf27502bSShawn Tu {0x380c, 0x02},
350bf27502bSShawn Tu {0x380d, 0xee},
351bf27502bSShawn Tu {0x380e, 0x07},
352e8882e1bSShawn Tu {0x380f, 0xd0},
353e8882e1bSShawn Tu {0x3811, 0x08},
354e8882e1bSShawn Tu {0x3813, 0x0d},
355bf27502bSShawn Tu {0x3814, 0x03},
356bf27502bSShawn Tu {0x3815, 0x01},
357bf27502bSShawn Tu {0x3816, 0x03},
358bf27502bSShawn Tu {0x3817, 0x01},
359bf27502bSShawn Tu {0x381e, 0x02},
360bf27502bSShawn Tu {0x3820, 0x8b},
361bf27502bSShawn Tu {0x3821, 0x01},
362bf27502bSShawn Tu {0x3832, 0x04},
363bf27502bSShawn Tu {0x3c80, 0x01},
364bf27502bSShawn Tu {0x3c82, 0x00},
365bf27502bSShawn Tu {0x3c83, 0xc8},
366bf27502bSShawn Tu {0x3c8c, 0x0f},
367bf27502bSShawn Tu {0x3c8d, 0xa0},
368bf27502bSShawn Tu {0x3c90, 0x07},
369bf27502bSShawn Tu {0x3c91, 0x00},
370bf27502bSShawn Tu {0x3c92, 0x00},
371bf27502bSShawn Tu {0x3c93, 0x00},
372bf27502bSShawn Tu {0x3c94, 0xd0},
373bf27502bSShawn Tu {0x3c95, 0x50},
374bf27502bSShawn Tu {0x3c96, 0x35},
375bf27502bSShawn Tu {0x3c97, 0x00},
376bf27502bSShawn Tu {0x4001, 0xe0},
377bf27502bSShawn Tu {0x4008, 0x00},
378bf27502bSShawn Tu {0x4009, 0x07},
379bf27502bSShawn Tu {0x400f, 0x80},
380bf27502bSShawn Tu {0x4013, 0x02},
381bf27502bSShawn Tu {0x4040, 0x00},
382bf27502bSShawn Tu {0x4041, 0x03},
383bf27502bSShawn Tu {0x404c, 0x50},
384bf27502bSShawn Tu {0x404e, 0x20},
385bf27502bSShawn Tu {0x4500, 0x06},
386bf27502bSShawn Tu {0x4503, 0x00},
387bf27502bSShawn Tu {0x450a, 0x04},
388bf27502bSShawn Tu {0x4809, 0x04},
389bf27502bSShawn Tu {0x480c, 0x12},
390bf27502bSShawn Tu {0x4819, 0x70},
391bf27502bSShawn Tu {0x4825, 0x32},
392bf27502bSShawn Tu {0x4826, 0x32},
393bf27502bSShawn Tu {0x482a, 0x06},
394bf27502bSShawn Tu {0x4833, 0x08},
395bf27502bSShawn Tu {0x4837, 0x0d},
396bf27502bSShawn Tu {0x5000, 0x77},
397bf27502bSShawn Tu {0x5b00, 0x01},
398bf27502bSShawn Tu {0x5b01, 0x10},
399bf27502bSShawn Tu {0x5b02, 0x01},
400bf27502bSShawn Tu {0x5b03, 0xdb},
401bf27502bSShawn Tu {0x5b05, 0x6c},
402bf27502bSShawn Tu {0x5e10, 0xfc},
403bf27502bSShawn Tu {0x3500, 0x00},
404bf27502bSShawn Tu {0x3501, 0x1F},
405bf27502bSShawn Tu {0x3502, 0x20},
406bf27502bSShawn Tu {0x3503, 0x08},
407bf27502bSShawn Tu {0x3508, 0x04},
408bf27502bSShawn Tu {0x3509, 0x00},
409bf27502bSShawn Tu {0x3832, 0x48},
410bf27502bSShawn Tu {0x5780, 0x3e},
411bf27502bSShawn Tu {0x5781, 0x0f},
412bf27502bSShawn Tu {0x5782, 0x44},
413bf27502bSShawn Tu {0x5783, 0x02},
414bf27502bSShawn Tu {0x5784, 0x01},
415bf27502bSShawn Tu {0x5785, 0x01},
416bf27502bSShawn Tu {0x5786, 0x00},
417bf27502bSShawn Tu {0x5787, 0x04},
418bf27502bSShawn Tu {0x5788, 0x02},
419bf27502bSShawn Tu {0x5789, 0x0f},
420bf27502bSShawn Tu {0x578a, 0xfd},
421bf27502bSShawn Tu {0x578b, 0xf5},
422bf27502bSShawn Tu {0x578c, 0xf5},
423bf27502bSShawn Tu {0x578d, 0x03},
424bf27502bSShawn Tu {0x578e, 0x08},
425bf27502bSShawn Tu {0x578f, 0x0c},
426bf27502bSShawn Tu {0x5790, 0x08},
427bf27502bSShawn Tu {0x5791, 0x06},
428bf27502bSShawn Tu {0x5792, 0x00},
429bf27502bSShawn Tu {0x5793, 0x52},
430bf27502bSShawn Tu {0x5794, 0xa3},
431bf27502bSShawn Tu {0x4003, 0x40},
432bf27502bSShawn Tu {0x3107, 0x01},
433bf27502bSShawn Tu {0x3c80, 0x08},
434bf27502bSShawn Tu {0x3c83, 0xb1},
435bf27502bSShawn Tu {0x3c8c, 0x10},
436bf27502bSShawn Tu {0x3c8d, 0x00},
437bf27502bSShawn Tu {0x3c90, 0x00},
438bf27502bSShawn Tu {0x3c94, 0x00},
439bf27502bSShawn Tu {0x3c95, 0x00},
440bf27502bSShawn Tu {0x3c96, 0x00},
441bf27502bSShawn Tu {0x37cb, 0x09},
442bf27502bSShawn Tu {0x37cc, 0x15},
443bf27502bSShawn Tu {0x37cd, 0x1f},
444bf27502bSShawn Tu {0x37ce, 0x1f},
445bf27502bSShawn Tu };
446bf27502bSShawn Tu
447bf27502bSShawn Tu static const char * const ov5675_test_pattern_menu[] = {
448bf27502bSShawn Tu "Disabled",
449bf27502bSShawn Tu "Standard Color Bar",
450bf27502bSShawn Tu "Top-Bottom Darker Color Bar",
451bf27502bSShawn Tu "Right-Left Darker Color Bar",
452bf27502bSShawn Tu "Bottom-Top Darker Color Bar"
453bf27502bSShawn Tu };
454bf27502bSShawn Tu
455bf27502bSShawn Tu static const s64 link_freq_menu_items[] = {
456bf27502bSShawn Tu OV5675_LINK_FREQ_450MHZ,
457bf27502bSShawn Tu };
458bf27502bSShawn Tu
459bf27502bSShawn Tu static const struct ov5675_link_freq_config link_freq_configs[] = {
460bf27502bSShawn Tu [OV5675_LINK_FREQ_900MBPS] = {
461bf27502bSShawn Tu .reg_list = {
462bf27502bSShawn Tu .num_of_regs = ARRAY_SIZE(mipi_data_rate_900mbps),
463bf27502bSShawn Tu .regs = mipi_data_rate_900mbps,
464bf27502bSShawn Tu }
465bf27502bSShawn Tu }
466bf27502bSShawn Tu };
467bf27502bSShawn Tu
468bf27502bSShawn Tu static const struct ov5675_mode supported_modes[] = {
469bf27502bSShawn Tu {
470bf27502bSShawn Tu .width = 2592,
471bf27502bSShawn Tu .height = 1944,
472bf27502bSShawn Tu .hts = 1500,
473bf27502bSShawn Tu .vts_def = OV5675_VTS_30FPS,
474bf27502bSShawn Tu .vts_min = OV5675_VTS_30FPS_MIN,
475bf27502bSShawn Tu .reg_list = {
476bf27502bSShawn Tu .num_of_regs = ARRAY_SIZE(mode_2592x1944_regs),
477bf27502bSShawn Tu .regs = mode_2592x1944_regs,
478bf27502bSShawn Tu },
479bf27502bSShawn Tu .link_freq_index = OV5675_LINK_FREQ_900MBPS,
480bf27502bSShawn Tu },
481bf27502bSShawn Tu {
482bf27502bSShawn Tu .width = 1296,
483bf27502bSShawn Tu .height = 972,
484bf27502bSShawn Tu .hts = 1500,
485bf27502bSShawn Tu .vts_def = OV5675_VTS_30FPS,
486bf27502bSShawn Tu .vts_min = OV5675_VTS_30FPS_MIN,
487bf27502bSShawn Tu .reg_list = {
488bf27502bSShawn Tu .num_of_regs = ARRAY_SIZE(mode_1296x972_regs),
489bf27502bSShawn Tu .regs = mode_1296x972_regs,
490bf27502bSShawn Tu },
491bf27502bSShawn Tu .link_freq_index = OV5675_LINK_FREQ_900MBPS,
492bf27502bSShawn Tu }
493bf27502bSShawn Tu };
494bf27502bSShawn Tu
495bf27502bSShawn Tu struct ov5675 {
496bf27502bSShawn Tu struct v4l2_subdev sd;
497bf27502bSShawn Tu struct media_pad pad;
498bf27502bSShawn Tu struct v4l2_ctrl_handler ctrl_handler;
49949d9ad71SQuentin Schulz struct clk *xvclk;
50049d9ad71SQuentin Schulz struct gpio_desc *reset_gpio;
50149d9ad71SQuentin Schulz struct regulator_bulk_data supplies[OV5675_NUM_SUPPLIES];
502bf27502bSShawn Tu
503bf27502bSShawn Tu /* V4L2 Controls */
504bf27502bSShawn Tu struct v4l2_ctrl *link_freq;
505bf27502bSShawn Tu struct v4l2_ctrl *pixel_rate;
506bf27502bSShawn Tu struct v4l2_ctrl *vblank;
507bf27502bSShawn Tu struct v4l2_ctrl *hblank;
508bf27502bSShawn Tu struct v4l2_ctrl *exposure;
509bf27502bSShawn Tu
510bf27502bSShawn Tu /* Current mode */
511bf27502bSShawn Tu const struct ov5675_mode *cur_mode;
512bf27502bSShawn Tu
513bf27502bSShawn Tu /* To serialize asynchronus callbacks */
514bf27502bSShawn Tu struct mutex mutex;
515bf27502bSShawn Tu
516bf27502bSShawn Tu /* Streaming on/off */
517bf27502bSShawn Tu bool streaming;
5185525fd86SBingbu Cao
5195525fd86SBingbu Cao /* True if the device has been identified */
5205525fd86SBingbu Cao bool identified;
521bf27502bSShawn Tu };
522bf27502bSShawn Tu
to_pixel_rate(u32 f_index)523bf27502bSShawn Tu static u64 to_pixel_rate(u32 f_index)
524bf27502bSShawn Tu {
525bf27502bSShawn Tu u64 pixel_rate = link_freq_menu_items[f_index] * 2 * OV5675_DATA_LANES;
526bf27502bSShawn Tu
527bf27502bSShawn Tu do_div(pixel_rate, OV5675_RGB_DEPTH);
528bf27502bSShawn Tu
529bf27502bSShawn Tu return pixel_rate;
530bf27502bSShawn Tu }
531bf27502bSShawn Tu
to_pixels_per_line(u32 hts,u32 f_index)532bf27502bSShawn Tu static u64 to_pixels_per_line(u32 hts, u32 f_index)
533bf27502bSShawn Tu {
534bf27502bSShawn Tu u64 ppl = hts * to_pixel_rate(f_index);
535bf27502bSShawn Tu
536bf27502bSShawn Tu do_div(ppl, OV5675_SCLK);
537bf27502bSShawn Tu
538bf27502bSShawn Tu return ppl;
539bf27502bSShawn Tu }
540bf27502bSShawn Tu
ov5675_read_reg(struct ov5675 * ov5675,u16 reg,u16 len,u32 * val)541bf27502bSShawn Tu static int ov5675_read_reg(struct ov5675 *ov5675, u16 reg, u16 len, u32 *val)
542bf27502bSShawn Tu {
543bf27502bSShawn Tu struct i2c_client *client = v4l2_get_subdevdata(&ov5675->sd);
544bf27502bSShawn Tu struct i2c_msg msgs[2];
545bf27502bSShawn Tu u8 addr_buf[2];
546bf27502bSShawn Tu u8 data_buf[4] = {0};
547bf27502bSShawn Tu int ret;
548bf27502bSShawn Tu
549bf27502bSShawn Tu if (len > 4)
550bf27502bSShawn Tu return -EINVAL;
551bf27502bSShawn Tu
552bf27502bSShawn Tu put_unaligned_be16(reg, addr_buf);
553bf27502bSShawn Tu msgs[0].addr = client->addr;
554bf27502bSShawn Tu msgs[0].flags = 0;
555bf27502bSShawn Tu msgs[0].len = sizeof(addr_buf);
556bf27502bSShawn Tu msgs[0].buf = addr_buf;
557bf27502bSShawn Tu msgs[1].addr = client->addr;
558bf27502bSShawn Tu msgs[1].flags = I2C_M_RD;
559bf27502bSShawn Tu msgs[1].len = len;
560bf27502bSShawn Tu msgs[1].buf = &data_buf[4 - len];
561bf27502bSShawn Tu
562bf27502bSShawn Tu ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
563bf27502bSShawn Tu if (ret != ARRAY_SIZE(msgs))
564bf27502bSShawn Tu return -EIO;
565bf27502bSShawn Tu
566bf27502bSShawn Tu *val = get_unaligned_be32(data_buf);
567bf27502bSShawn Tu
568bf27502bSShawn Tu return 0;
569bf27502bSShawn Tu }
570bf27502bSShawn Tu
ov5675_write_reg(struct ov5675 * ov5675,u16 reg,u16 len,u32 val)571bf27502bSShawn Tu static int ov5675_write_reg(struct ov5675 *ov5675, u16 reg, u16 len, u32 val)
572bf27502bSShawn Tu {
573bf27502bSShawn Tu struct i2c_client *client = v4l2_get_subdevdata(&ov5675->sd);
574bf27502bSShawn Tu u8 buf[6];
575bf27502bSShawn Tu
576bf27502bSShawn Tu if (len > 4)
577bf27502bSShawn Tu return -EINVAL;
578bf27502bSShawn Tu
579bf27502bSShawn Tu put_unaligned_be16(reg, buf);
580bf27502bSShawn Tu put_unaligned_be32(val << 8 * (4 - len), buf + 2);
581bf27502bSShawn Tu if (i2c_master_send(client, buf, len + 2) != len + 2)
582bf27502bSShawn Tu return -EIO;
583bf27502bSShawn Tu
584bf27502bSShawn Tu return 0;
585bf27502bSShawn Tu }
586bf27502bSShawn Tu
ov5675_write_reg_list(struct ov5675 * ov5675,const struct ov5675_reg_list * r_list)587bf27502bSShawn Tu static int ov5675_write_reg_list(struct ov5675 *ov5675,
588bf27502bSShawn Tu const struct ov5675_reg_list *r_list)
589bf27502bSShawn Tu {
590bf27502bSShawn Tu struct i2c_client *client = v4l2_get_subdevdata(&ov5675->sd);
591bf27502bSShawn Tu unsigned int i;
592bf27502bSShawn Tu int ret;
593bf27502bSShawn Tu
594bf27502bSShawn Tu for (i = 0; i < r_list->num_of_regs; i++) {
595bf27502bSShawn Tu ret = ov5675_write_reg(ov5675, r_list->regs[i].address, 1,
596bf27502bSShawn Tu r_list->regs[i].val);
597bf27502bSShawn Tu if (ret) {
598bf27502bSShawn Tu dev_err_ratelimited(&client->dev,
599bf27502bSShawn Tu "failed to write reg 0x%4.4x. error = %d",
600bf27502bSShawn Tu r_list->regs[i].address, ret);
601bf27502bSShawn Tu return ret;
602bf27502bSShawn Tu }
603bf27502bSShawn Tu }
604bf27502bSShawn Tu
605bf27502bSShawn Tu return 0;
606bf27502bSShawn Tu }
607bf27502bSShawn Tu
ov5675_update_digital_gain(struct ov5675 * ov5675,u32 d_gain)608bf27502bSShawn Tu static int ov5675_update_digital_gain(struct ov5675 *ov5675, u32 d_gain)
609bf27502bSShawn Tu {
610bf27502bSShawn Tu int ret;
611bf27502bSShawn Tu
61224e9edc1SBingbu Cao ret = ov5675_write_reg(ov5675, OV5675_REG_GROUP_ACCESS,
61324e9edc1SBingbu Cao OV5675_REG_VALUE_08BIT,
61424e9edc1SBingbu Cao OV5675_GROUP_HOLD_START);
61524e9edc1SBingbu Cao if (ret)
61624e9edc1SBingbu Cao return ret;
61724e9edc1SBingbu Cao
618bf27502bSShawn Tu ret = ov5675_write_reg(ov5675, OV5675_REG_MWB_R_GAIN,
619bf27502bSShawn Tu OV5675_REG_VALUE_16BIT, d_gain);
620bf27502bSShawn Tu if (ret)
621bf27502bSShawn Tu return ret;
622bf27502bSShawn Tu
623bf27502bSShawn Tu ret = ov5675_write_reg(ov5675, OV5675_REG_MWB_G_GAIN,
624bf27502bSShawn Tu OV5675_REG_VALUE_16BIT, d_gain);
625bf27502bSShawn Tu if (ret)
626bf27502bSShawn Tu return ret;
627bf27502bSShawn Tu
62824e9edc1SBingbu Cao ret = ov5675_write_reg(ov5675, OV5675_REG_MWB_B_GAIN,
629bf27502bSShawn Tu OV5675_REG_VALUE_16BIT, d_gain);
63024e9edc1SBingbu Cao if (ret)
63124e9edc1SBingbu Cao return ret;
63224e9edc1SBingbu Cao
63324e9edc1SBingbu Cao ret = ov5675_write_reg(ov5675, OV5675_REG_GROUP_ACCESS,
63424e9edc1SBingbu Cao OV5675_REG_VALUE_08BIT,
63524e9edc1SBingbu Cao OV5675_GROUP_HOLD_END);
63624e9edc1SBingbu Cao if (ret)
63724e9edc1SBingbu Cao return ret;
63824e9edc1SBingbu Cao
63924e9edc1SBingbu Cao ret = ov5675_write_reg(ov5675, OV5675_REG_GROUP_ACCESS,
64024e9edc1SBingbu Cao OV5675_REG_VALUE_08BIT,
64124e9edc1SBingbu Cao OV5675_GROUP_HOLD_LAUNCH);
64224e9edc1SBingbu Cao return ret;
643bf27502bSShawn Tu }
644bf27502bSShawn Tu
ov5675_test_pattern(struct ov5675 * ov5675,u32 pattern)645bf27502bSShawn Tu static int ov5675_test_pattern(struct ov5675 *ov5675, u32 pattern)
646bf27502bSShawn Tu {
647bf27502bSShawn Tu if (pattern)
648bf27502bSShawn Tu pattern = (pattern - 1) << OV5675_TEST_PATTERN_BAR_SHIFT |
649bf27502bSShawn Tu OV5675_TEST_PATTERN_ENABLE;
650bf27502bSShawn Tu
651bf27502bSShawn Tu return ov5675_write_reg(ov5675, OV5675_REG_TEST_PATTERN,
652bf27502bSShawn Tu OV5675_REG_VALUE_08BIT, pattern);
653bf27502bSShawn Tu }
654bf27502bSShawn Tu
655e8882e1bSShawn Tu /*
656e8882e1bSShawn Tu * OV5675 supports keeping the pixel order by mirror and flip function
657e8882e1bSShawn Tu * The Bayer order isn't affected by the flip controls
658e8882e1bSShawn Tu */
ov5675_set_ctrl_hflip(struct ov5675 * ov5675,u32 ctrl_val)659e8882e1bSShawn Tu static int ov5675_set_ctrl_hflip(struct ov5675 *ov5675, u32 ctrl_val)
660e8882e1bSShawn Tu {
661e8882e1bSShawn Tu int ret;
662e8882e1bSShawn Tu u32 val;
663e8882e1bSShawn Tu
664e8882e1bSShawn Tu ret = ov5675_read_reg(ov5675, OV5675_REG_FORMAT1,
665e8882e1bSShawn Tu OV5675_REG_VALUE_08BIT, &val);
666e8882e1bSShawn Tu if (ret)
667e8882e1bSShawn Tu return ret;
668e8882e1bSShawn Tu
669e8882e1bSShawn Tu return ov5675_write_reg(ov5675, OV5675_REG_FORMAT1,
670e8882e1bSShawn Tu OV5675_REG_VALUE_08BIT,
6716f862f84SShawn Tu ctrl_val ? val & ~BIT(3) : val | BIT(3));
672e8882e1bSShawn Tu }
673e8882e1bSShawn Tu
ov5675_set_ctrl_vflip(struct ov5675 * ov5675,u8 ctrl_val)674e8882e1bSShawn Tu static int ov5675_set_ctrl_vflip(struct ov5675 *ov5675, u8 ctrl_val)
675e8882e1bSShawn Tu {
676e8882e1bSShawn Tu int ret;
677e8882e1bSShawn Tu u32 val;
678e8882e1bSShawn Tu
679e8882e1bSShawn Tu ret = ov5675_read_reg(ov5675, OV5675_REG_FORMAT1,
680e8882e1bSShawn Tu OV5675_REG_VALUE_08BIT, &val);
681e8882e1bSShawn Tu if (ret)
682e8882e1bSShawn Tu return ret;
683e8882e1bSShawn Tu
684e8882e1bSShawn Tu ret = ov5675_write_reg(ov5675, OV5675_REG_FORMAT1,
685e8882e1bSShawn Tu OV5675_REG_VALUE_08BIT,
6866f862f84SShawn Tu ctrl_val ? val | BIT(4) | BIT(5) : val & ~BIT(4) & ~BIT(5));
687e8882e1bSShawn Tu
688e8882e1bSShawn Tu if (ret)
689e8882e1bSShawn Tu return ret;
690e8882e1bSShawn Tu
691e8882e1bSShawn Tu ret = ov5675_read_reg(ov5675, OV5675_REG_FORMAT2,
692e8882e1bSShawn Tu OV5675_REG_VALUE_08BIT, &val);
693e8882e1bSShawn Tu
694e8882e1bSShawn Tu if (ret)
695e8882e1bSShawn Tu return ret;
696e8882e1bSShawn Tu
697e8882e1bSShawn Tu return ov5675_write_reg(ov5675, OV5675_REG_FORMAT2,
698e8882e1bSShawn Tu OV5675_REG_VALUE_08BIT,
6996f862f84SShawn Tu ctrl_val ? val | BIT(1) : val & ~BIT(1));
700e8882e1bSShawn Tu }
701e8882e1bSShawn Tu
ov5675_set_ctrl(struct v4l2_ctrl * ctrl)702bf27502bSShawn Tu static int ov5675_set_ctrl(struct v4l2_ctrl *ctrl)
703bf27502bSShawn Tu {
704bf27502bSShawn Tu struct ov5675 *ov5675 = container_of(ctrl->handler,
705bf27502bSShawn Tu struct ov5675, ctrl_handler);
706bf27502bSShawn Tu struct i2c_client *client = v4l2_get_subdevdata(&ov5675->sd);
707bf27502bSShawn Tu s64 exposure_max;
708bf27502bSShawn Tu int ret = 0;
709bf27502bSShawn Tu
710bf27502bSShawn Tu /* Propagate change of current control to all related controls */
711bf27502bSShawn Tu if (ctrl->id == V4L2_CID_VBLANK) {
712bf27502bSShawn Tu /* Update max exposure while meeting expected vblanking */
713ab3d4b41SBingbu Cao exposure_max = ov5675->cur_mode->height + ctrl->val -
714ab3d4b41SBingbu Cao OV5675_EXPOSURE_MAX_MARGIN;
715bf27502bSShawn Tu __v4l2_ctrl_modify_range(ov5675->exposure,
716bf27502bSShawn Tu ov5675->exposure->minimum,
717bf27502bSShawn Tu exposure_max, ov5675->exposure->step,
718bf27502bSShawn Tu exposure_max);
719bf27502bSShawn Tu }
720bf27502bSShawn Tu
721bf27502bSShawn Tu /* V4L2 controls values will be applied only when power is already up */
722bf27502bSShawn Tu if (!pm_runtime_get_if_in_use(&client->dev))
723bf27502bSShawn Tu return 0;
724bf27502bSShawn Tu
725bf27502bSShawn Tu switch (ctrl->id) {
726bf27502bSShawn Tu case V4L2_CID_ANALOGUE_GAIN:
727bf27502bSShawn Tu ret = ov5675_write_reg(ov5675, OV5675_REG_ANALOG_GAIN,
728bf27502bSShawn Tu OV5675_REG_VALUE_16BIT, ctrl->val);
729bf27502bSShawn Tu break;
730bf27502bSShawn Tu
731bf27502bSShawn Tu case V4L2_CID_DIGITAL_GAIN:
732bf27502bSShawn Tu ret = ov5675_update_digital_gain(ov5675, ctrl->val);
733bf27502bSShawn Tu break;
734bf27502bSShawn Tu
735bf27502bSShawn Tu case V4L2_CID_EXPOSURE:
736ab3d4b41SBingbu Cao /* 4 least significant bits of expsoure are fractional part
737ab3d4b41SBingbu Cao * val = val << 4
738ab3d4b41SBingbu Cao * for ov5675, the unit of exposure is differnt from other
739ab3d4b41SBingbu Cao * OmniVision sensors, its exposure value is twice of the
740ab3d4b41SBingbu Cao * register value, the exposure should be divided by 2 before
741ab3d4b41SBingbu Cao * set register, e.g. val << 3.
742ab3d4b41SBingbu Cao */
743bf27502bSShawn Tu ret = ov5675_write_reg(ov5675, OV5675_REG_EXPOSURE,
744bf27502bSShawn Tu OV5675_REG_VALUE_24BIT, ctrl->val << 3);
745bf27502bSShawn Tu break;
746bf27502bSShawn Tu
747bf27502bSShawn Tu case V4L2_CID_VBLANK:
748bf27502bSShawn Tu ret = ov5675_write_reg(ov5675, OV5675_REG_VTS,
749bf27502bSShawn Tu OV5675_REG_VALUE_16BIT,
750bf27502bSShawn Tu ov5675->cur_mode->height + ctrl->val +
751bf27502bSShawn Tu 10);
752bf27502bSShawn Tu break;
753bf27502bSShawn Tu
754bf27502bSShawn Tu case V4L2_CID_TEST_PATTERN:
755bf27502bSShawn Tu ret = ov5675_test_pattern(ov5675, ctrl->val);
756bf27502bSShawn Tu break;
757bf27502bSShawn Tu
758e8882e1bSShawn Tu case V4L2_CID_HFLIP:
759e8882e1bSShawn Tu ov5675_set_ctrl_hflip(ov5675, ctrl->val);
760e8882e1bSShawn Tu break;
761e8882e1bSShawn Tu
762e8882e1bSShawn Tu case V4L2_CID_VFLIP:
763e8882e1bSShawn Tu ov5675_set_ctrl_vflip(ov5675, ctrl->val);
764e8882e1bSShawn Tu break;
765e8882e1bSShawn Tu
766bf27502bSShawn Tu default:
767bf27502bSShawn Tu ret = -EINVAL;
768bf27502bSShawn Tu break;
769bf27502bSShawn Tu }
770bf27502bSShawn Tu
771bf27502bSShawn Tu pm_runtime_put(&client->dev);
772bf27502bSShawn Tu
773bf27502bSShawn Tu return ret;
774bf27502bSShawn Tu }
775bf27502bSShawn Tu
776bf27502bSShawn Tu static const struct v4l2_ctrl_ops ov5675_ctrl_ops = {
777bf27502bSShawn Tu .s_ctrl = ov5675_set_ctrl,
778bf27502bSShawn Tu };
779bf27502bSShawn Tu
ov5675_init_controls(struct ov5675 * ov5675)780bf27502bSShawn Tu static int ov5675_init_controls(struct ov5675 *ov5675)
781bf27502bSShawn Tu {
782c8aa2111SQuentin Schulz struct i2c_client *client = v4l2_get_subdevdata(&ov5675->sd);
783c8aa2111SQuentin Schulz struct v4l2_fwnode_device_properties props;
784bf27502bSShawn Tu struct v4l2_ctrl_handler *ctrl_hdlr;
785bf27502bSShawn Tu s64 exposure_max, h_blank;
786bf27502bSShawn Tu int ret;
787bf27502bSShawn Tu
788bf27502bSShawn Tu ctrl_hdlr = &ov5675->ctrl_handler;
789c8aa2111SQuentin Schulz ret = v4l2_ctrl_handler_init(ctrl_hdlr, 10);
790bf27502bSShawn Tu if (ret)
791bf27502bSShawn Tu return ret;
792bf27502bSShawn Tu
793bf27502bSShawn Tu ctrl_hdlr->lock = &ov5675->mutex;
794bf27502bSShawn Tu ov5675->link_freq = v4l2_ctrl_new_int_menu(ctrl_hdlr, &ov5675_ctrl_ops,
795bf27502bSShawn Tu V4L2_CID_LINK_FREQ,
796bf27502bSShawn Tu ARRAY_SIZE(link_freq_menu_items) - 1,
797bf27502bSShawn Tu 0, link_freq_menu_items);
798bf27502bSShawn Tu if (ov5675->link_freq)
799bf27502bSShawn Tu ov5675->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
800bf27502bSShawn Tu
801bf27502bSShawn Tu ov5675->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &ov5675_ctrl_ops,
802bf27502bSShawn Tu V4L2_CID_PIXEL_RATE, 0,
803bf27502bSShawn Tu to_pixel_rate(OV5675_LINK_FREQ_900MBPS),
804bf27502bSShawn Tu 1,
805bf27502bSShawn Tu to_pixel_rate(OV5675_LINK_FREQ_900MBPS));
806bf27502bSShawn Tu ov5675->vblank = v4l2_ctrl_new_std(ctrl_hdlr, &ov5675_ctrl_ops,
807bf27502bSShawn Tu V4L2_CID_VBLANK,
808bf27502bSShawn Tu ov5675->cur_mode->vts_min - ov5675->cur_mode->height,
809bf27502bSShawn Tu OV5675_VTS_MAX - ov5675->cur_mode->height, 1,
810bf27502bSShawn Tu ov5675->cur_mode->vts_def - ov5675->cur_mode->height);
811bf27502bSShawn Tu h_blank = to_pixels_per_line(ov5675->cur_mode->hts,
812bf27502bSShawn Tu ov5675->cur_mode->link_freq_index) - ov5675->cur_mode->width;
813bf27502bSShawn Tu ov5675->hblank = v4l2_ctrl_new_std(ctrl_hdlr, &ov5675_ctrl_ops,
814bf27502bSShawn Tu V4L2_CID_HBLANK, h_blank, h_blank, 1,
815bf27502bSShawn Tu h_blank);
816bf27502bSShawn Tu if (ov5675->hblank)
817bf27502bSShawn Tu ov5675->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
818bf27502bSShawn Tu
819bf27502bSShawn Tu v4l2_ctrl_new_std(ctrl_hdlr, &ov5675_ctrl_ops, V4L2_CID_ANALOGUE_GAIN,
820bf27502bSShawn Tu OV5675_ANAL_GAIN_MIN, OV5675_ANAL_GAIN_MAX,
821bf27502bSShawn Tu OV5675_ANAL_GAIN_STEP, OV5675_ANAL_GAIN_MIN);
822bf27502bSShawn Tu v4l2_ctrl_new_std(ctrl_hdlr, &ov5675_ctrl_ops, V4L2_CID_DIGITAL_GAIN,
823bf27502bSShawn Tu OV5675_DGTL_GAIN_MIN, OV5675_DGTL_GAIN_MAX,
824bf27502bSShawn Tu OV5675_DGTL_GAIN_STEP, OV5675_DGTL_GAIN_DEFAULT);
825ab3d4b41SBingbu Cao exposure_max = (ov5675->cur_mode->vts_def - OV5675_EXPOSURE_MAX_MARGIN);
826bf27502bSShawn Tu ov5675->exposure = v4l2_ctrl_new_std(ctrl_hdlr, &ov5675_ctrl_ops,
827bf27502bSShawn Tu V4L2_CID_EXPOSURE,
828bf27502bSShawn Tu OV5675_EXPOSURE_MIN, exposure_max,
829bf27502bSShawn Tu OV5675_EXPOSURE_STEP,
830bf27502bSShawn Tu exposure_max);
831bf27502bSShawn Tu v4l2_ctrl_new_std_menu_items(ctrl_hdlr, &ov5675_ctrl_ops,
832bf27502bSShawn Tu V4L2_CID_TEST_PATTERN,
833bf27502bSShawn Tu ARRAY_SIZE(ov5675_test_pattern_menu) - 1,
834bf27502bSShawn Tu 0, 0, ov5675_test_pattern_menu);
835e8882e1bSShawn Tu v4l2_ctrl_new_std(ctrl_hdlr, &ov5675_ctrl_ops,
836e8882e1bSShawn Tu V4L2_CID_HFLIP, 0, 1, 1, 0);
837e8882e1bSShawn Tu v4l2_ctrl_new_std(ctrl_hdlr, &ov5675_ctrl_ops,
838e8882e1bSShawn Tu V4L2_CID_VFLIP, 0, 1, 1, 0);
839e8882e1bSShawn Tu
840dd74ed6cSShang XiaoJing if (ctrl_hdlr->error) {
841dd74ed6cSShang XiaoJing v4l2_ctrl_handler_free(ctrl_hdlr);
842bf27502bSShawn Tu return ctrl_hdlr->error;
843dd74ed6cSShang XiaoJing }
844bf27502bSShawn Tu
845c8aa2111SQuentin Schulz ret = v4l2_fwnode_device_parse(&client->dev, &props);
846c8aa2111SQuentin Schulz if (ret)
847c8aa2111SQuentin Schulz goto error;
848c8aa2111SQuentin Schulz
849c8aa2111SQuentin Schulz ret = v4l2_ctrl_new_fwnode_properties(ctrl_hdlr, &ov5675_ctrl_ops,
850c8aa2111SQuentin Schulz &props);
851c8aa2111SQuentin Schulz if (ret)
852c8aa2111SQuentin Schulz goto error;
853c8aa2111SQuentin Schulz
854bf27502bSShawn Tu ov5675->sd.ctrl_handler = ctrl_hdlr;
855bf27502bSShawn Tu
856bf27502bSShawn Tu return 0;
857c8aa2111SQuentin Schulz
858c8aa2111SQuentin Schulz error:
859c8aa2111SQuentin Schulz v4l2_ctrl_handler_free(ctrl_hdlr);
860c8aa2111SQuentin Schulz
861c8aa2111SQuentin Schulz return ret;
862bf27502bSShawn Tu }
863bf27502bSShawn Tu
ov5675_update_pad_format(const struct ov5675_mode * mode,struct v4l2_mbus_framefmt * fmt)864bf27502bSShawn Tu static void ov5675_update_pad_format(const struct ov5675_mode *mode,
865bf27502bSShawn Tu struct v4l2_mbus_framefmt *fmt)
866bf27502bSShawn Tu {
867bf27502bSShawn Tu fmt->width = mode->width;
868bf27502bSShawn Tu fmt->height = mode->height;
869bf27502bSShawn Tu fmt->code = MEDIA_BUS_FMT_SGRBG10_1X10;
870bf27502bSShawn Tu fmt->field = V4L2_FIELD_NONE;
871bf27502bSShawn Tu }
872bf27502bSShawn Tu
ov5675_identify_module(struct ov5675 * ov5675)8735525fd86SBingbu Cao static int ov5675_identify_module(struct ov5675 *ov5675)
8745525fd86SBingbu Cao {
8755525fd86SBingbu Cao struct i2c_client *client = v4l2_get_subdevdata(&ov5675->sd);
8765525fd86SBingbu Cao int ret;
8775525fd86SBingbu Cao u32 val;
8785525fd86SBingbu Cao
8795525fd86SBingbu Cao if (ov5675->identified)
8805525fd86SBingbu Cao return 0;
8815525fd86SBingbu Cao
8825525fd86SBingbu Cao ret = ov5675_read_reg(ov5675, OV5675_REG_CHIP_ID,
8835525fd86SBingbu Cao OV5675_REG_VALUE_24BIT, &val);
8845525fd86SBingbu Cao if (ret)
8855525fd86SBingbu Cao return ret;
8865525fd86SBingbu Cao
8875525fd86SBingbu Cao if (val != OV5675_CHIP_ID) {
8885525fd86SBingbu Cao dev_err(&client->dev, "chip id mismatch: %x!=%x",
8895525fd86SBingbu Cao OV5675_CHIP_ID, val);
8905525fd86SBingbu Cao return -ENXIO;
8915525fd86SBingbu Cao }
8925525fd86SBingbu Cao
8935525fd86SBingbu Cao ov5675->identified = true;
8945525fd86SBingbu Cao
8955525fd86SBingbu Cao return 0;
8965525fd86SBingbu Cao }
8975525fd86SBingbu Cao
ov5675_start_streaming(struct ov5675 * ov5675)898bf27502bSShawn Tu static int ov5675_start_streaming(struct ov5675 *ov5675)
899bf27502bSShawn Tu {
900bf27502bSShawn Tu struct i2c_client *client = v4l2_get_subdevdata(&ov5675->sd);
901bf27502bSShawn Tu const struct ov5675_reg_list *reg_list;
902bf27502bSShawn Tu int link_freq_index, ret;
903bf27502bSShawn Tu
9045525fd86SBingbu Cao ret = ov5675_identify_module(ov5675);
9055525fd86SBingbu Cao if (ret)
9065525fd86SBingbu Cao return ret;
9075525fd86SBingbu Cao
908bf27502bSShawn Tu link_freq_index = ov5675->cur_mode->link_freq_index;
909bf27502bSShawn Tu reg_list = &link_freq_configs[link_freq_index].reg_list;
910bf27502bSShawn Tu ret = ov5675_write_reg_list(ov5675, reg_list);
911bf27502bSShawn Tu if (ret) {
912bf27502bSShawn Tu dev_err(&client->dev, "failed to set plls");
913bf27502bSShawn Tu return ret;
914bf27502bSShawn Tu }
915bf27502bSShawn Tu
916bf27502bSShawn Tu reg_list = &ov5675->cur_mode->reg_list;
917bf27502bSShawn Tu ret = ov5675_write_reg_list(ov5675, reg_list);
918bf27502bSShawn Tu if (ret) {
919bf27502bSShawn Tu dev_err(&client->dev, "failed to set mode");
920bf27502bSShawn Tu return ret;
921bf27502bSShawn Tu }
922bf27502bSShawn Tu
923bf27502bSShawn Tu ret = __v4l2_ctrl_handler_setup(ov5675->sd.ctrl_handler);
924bf27502bSShawn Tu if (ret)
925bf27502bSShawn Tu return ret;
926bf27502bSShawn Tu
927bf27502bSShawn Tu ret = ov5675_write_reg(ov5675, OV5675_REG_MODE_SELECT,
928bf27502bSShawn Tu OV5675_REG_VALUE_08BIT, OV5675_MODE_STREAMING);
929bf27502bSShawn Tu if (ret) {
930bf27502bSShawn Tu dev_err(&client->dev, "failed to set stream");
931bf27502bSShawn Tu return ret;
932bf27502bSShawn Tu }
933bf27502bSShawn Tu
934bf27502bSShawn Tu return 0;
935bf27502bSShawn Tu }
936bf27502bSShawn Tu
ov5675_stop_streaming(struct ov5675 * ov5675)937bf27502bSShawn Tu static void ov5675_stop_streaming(struct ov5675 *ov5675)
938bf27502bSShawn Tu {
939bf27502bSShawn Tu struct i2c_client *client = v4l2_get_subdevdata(&ov5675->sd);
940bf27502bSShawn Tu
941bf27502bSShawn Tu if (ov5675_write_reg(ov5675, OV5675_REG_MODE_SELECT,
942bf27502bSShawn Tu OV5675_REG_VALUE_08BIT, OV5675_MODE_STANDBY))
943bf27502bSShawn Tu dev_err(&client->dev, "failed to set stream");
944bf27502bSShawn Tu }
945bf27502bSShawn Tu
ov5675_set_stream(struct v4l2_subdev * sd,int enable)946bf27502bSShawn Tu static int ov5675_set_stream(struct v4l2_subdev *sd, int enable)
947bf27502bSShawn Tu {
948bf27502bSShawn Tu struct ov5675 *ov5675 = to_ov5675(sd);
949bf27502bSShawn Tu struct i2c_client *client = v4l2_get_subdevdata(sd);
950bf27502bSShawn Tu int ret = 0;
951bf27502bSShawn Tu
952bf27502bSShawn Tu if (ov5675->streaming == enable)
953bf27502bSShawn Tu return 0;
954bf27502bSShawn Tu
955bf27502bSShawn Tu mutex_lock(&ov5675->mutex);
956bf27502bSShawn Tu if (enable) {
957f236bb24SMauro Carvalho Chehab ret = pm_runtime_resume_and_get(&client->dev);
958bf27502bSShawn Tu if (ret < 0) {
959bf27502bSShawn Tu mutex_unlock(&ov5675->mutex);
960bf27502bSShawn Tu return ret;
961bf27502bSShawn Tu }
962bf27502bSShawn Tu
963bf27502bSShawn Tu ret = ov5675_start_streaming(ov5675);
964bf27502bSShawn Tu if (ret) {
965bf27502bSShawn Tu enable = 0;
966bf27502bSShawn Tu ov5675_stop_streaming(ov5675);
967bf27502bSShawn Tu pm_runtime_put(&client->dev);
968bf27502bSShawn Tu }
969bf27502bSShawn Tu } else {
970bf27502bSShawn Tu ov5675_stop_streaming(ov5675);
971bf27502bSShawn Tu pm_runtime_put(&client->dev);
972bf27502bSShawn Tu }
973bf27502bSShawn Tu
974bf27502bSShawn Tu ov5675->streaming = enable;
975bf27502bSShawn Tu mutex_unlock(&ov5675->mutex);
976bf27502bSShawn Tu
977bf27502bSShawn Tu return ret;
978bf27502bSShawn Tu }
979bf27502bSShawn Tu
ov5675_power_off(struct device * dev)98049d9ad71SQuentin Schulz static int ov5675_power_off(struct device *dev)
98149d9ad71SQuentin Schulz {
98249d9ad71SQuentin Schulz /* 512 xvclk cycles after the last SCCB transation or MIPI frame end */
98349d9ad71SQuentin Schulz u32 delay_us = DIV_ROUND_UP(512, OV5675_XVCLK_19_2 / 1000 / 1000);
98449d9ad71SQuentin Schulz struct v4l2_subdev *sd = dev_get_drvdata(dev);
98549d9ad71SQuentin Schulz struct ov5675 *ov5675 = to_ov5675(sd);
98649d9ad71SQuentin Schulz
98749d9ad71SQuentin Schulz usleep_range(delay_us, delay_us * 2);
98849d9ad71SQuentin Schulz
98949d9ad71SQuentin Schulz clk_disable_unprepare(ov5675->xvclk);
99049d9ad71SQuentin Schulz gpiod_set_value_cansleep(ov5675->reset_gpio, 1);
99149d9ad71SQuentin Schulz regulator_bulk_disable(OV5675_NUM_SUPPLIES, ov5675->supplies);
99249d9ad71SQuentin Schulz
99349d9ad71SQuentin Schulz return 0;
99449d9ad71SQuentin Schulz }
99549d9ad71SQuentin Schulz
ov5675_power_on(struct device * dev)99649d9ad71SQuentin Schulz static int ov5675_power_on(struct device *dev)
99749d9ad71SQuentin Schulz {
99849d9ad71SQuentin Schulz u32 delay_us = DIV_ROUND_UP(8192, OV5675_XVCLK_19_2 / 1000 / 1000);
99949d9ad71SQuentin Schulz struct v4l2_subdev *sd = dev_get_drvdata(dev);
100049d9ad71SQuentin Schulz struct ov5675 *ov5675 = to_ov5675(sd);
100149d9ad71SQuentin Schulz int ret;
100249d9ad71SQuentin Schulz
100349d9ad71SQuentin Schulz ret = clk_prepare_enable(ov5675->xvclk);
100449d9ad71SQuentin Schulz if (ret < 0) {
100549d9ad71SQuentin Schulz dev_err(dev, "failed to enable xvclk: %d\n", ret);
100649d9ad71SQuentin Schulz return ret;
100749d9ad71SQuentin Schulz }
100849d9ad71SQuentin Schulz
100949d9ad71SQuentin Schulz gpiod_set_value_cansleep(ov5675->reset_gpio, 1);
101049d9ad71SQuentin Schulz
101149d9ad71SQuentin Schulz ret = regulator_bulk_enable(OV5675_NUM_SUPPLIES, ov5675->supplies);
101249d9ad71SQuentin Schulz if (ret) {
101349d9ad71SQuentin Schulz clk_disable_unprepare(ov5675->xvclk);
101449d9ad71SQuentin Schulz return ret;
101549d9ad71SQuentin Schulz }
101649d9ad71SQuentin Schulz
101749d9ad71SQuentin Schulz /* Reset pulse should be at least 2ms and reset gpio released only once
101849d9ad71SQuentin Schulz * regulators are stable.
101949d9ad71SQuentin Schulz */
102049d9ad71SQuentin Schulz usleep_range(2000, 2200);
102149d9ad71SQuentin Schulz
102249d9ad71SQuentin Schulz gpiod_set_value_cansleep(ov5675->reset_gpio, 0);
102349d9ad71SQuentin Schulz
102449d9ad71SQuentin Schulz /* 8192 xvclk cycles prior to the first SCCB transation */
102549d9ad71SQuentin Schulz usleep_range(delay_us, delay_us * 2);
102649d9ad71SQuentin Schulz
102749d9ad71SQuentin Schulz return 0;
102849d9ad71SQuentin Schulz }
102949d9ad71SQuentin Schulz
ov5675_suspend(struct device * dev)1030bf27502bSShawn Tu static int __maybe_unused ov5675_suspend(struct device *dev)
1031bf27502bSShawn Tu {
10321a747125SKrzysztof Kozlowski struct v4l2_subdev *sd = dev_get_drvdata(dev);
1033bf27502bSShawn Tu struct ov5675 *ov5675 = to_ov5675(sd);
1034bf27502bSShawn Tu
1035bf27502bSShawn Tu mutex_lock(&ov5675->mutex);
1036bf27502bSShawn Tu if (ov5675->streaming)
1037bf27502bSShawn Tu ov5675_stop_streaming(ov5675);
1038bf27502bSShawn Tu
1039bf27502bSShawn Tu mutex_unlock(&ov5675->mutex);
1040bf27502bSShawn Tu
1041bf27502bSShawn Tu return 0;
1042bf27502bSShawn Tu }
1043bf27502bSShawn Tu
ov5675_resume(struct device * dev)1044bf27502bSShawn Tu static int __maybe_unused ov5675_resume(struct device *dev)
1045bf27502bSShawn Tu {
10461a747125SKrzysztof Kozlowski struct v4l2_subdev *sd = dev_get_drvdata(dev);
1047bf27502bSShawn Tu struct ov5675 *ov5675 = to_ov5675(sd);
1048bf27502bSShawn Tu int ret;
1049bf27502bSShawn Tu
1050bf27502bSShawn Tu mutex_lock(&ov5675->mutex);
1051bf27502bSShawn Tu if (ov5675->streaming) {
1052bf27502bSShawn Tu ret = ov5675_start_streaming(ov5675);
1053bf27502bSShawn Tu if (ret) {
1054bf27502bSShawn Tu ov5675->streaming = false;
1055bf27502bSShawn Tu ov5675_stop_streaming(ov5675);
1056bf27502bSShawn Tu mutex_unlock(&ov5675->mutex);
1057bf27502bSShawn Tu return ret;
1058bf27502bSShawn Tu }
1059bf27502bSShawn Tu }
1060bf27502bSShawn Tu
1061bf27502bSShawn Tu mutex_unlock(&ov5675->mutex);
1062bf27502bSShawn Tu
1063bf27502bSShawn Tu return 0;
1064bf27502bSShawn Tu }
1065bf27502bSShawn Tu
ov5675_set_format(struct v4l2_subdev * sd,struct v4l2_subdev_state * sd_state,struct v4l2_subdev_format * fmt)1066bf27502bSShawn Tu static int ov5675_set_format(struct v4l2_subdev *sd,
10670d346d2aSTomi Valkeinen struct v4l2_subdev_state *sd_state,
1068bf27502bSShawn Tu struct v4l2_subdev_format *fmt)
1069bf27502bSShawn Tu {
1070bf27502bSShawn Tu struct ov5675 *ov5675 = to_ov5675(sd);
1071bf27502bSShawn Tu const struct ov5675_mode *mode;
1072bf27502bSShawn Tu s32 vblank_def, h_blank;
1073bf27502bSShawn Tu
1074bf27502bSShawn Tu mode = v4l2_find_nearest_size(supported_modes,
1075bf27502bSShawn Tu ARRAY_SIZE(supported_modes), width,
1076bf27502bSShawn Tu height, fmt->format.width,
1077bf27502bSShawn Tu fmt->format.height);
1078bf27502bSShawn Tu
1079bf27502bSShawn Tu mutex_lock(&ov5675->mutex);
1080bf27502bSShawn Tu ov5675_update_pad_format(mode, &fmt->format);
1081bf27502bSShawn Tu if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
10820d346d2aSTomi Valkeinen *v4l2_subdev_get_try_format(sd, sd_state, fmt->pad) = fmt->format;
1083bf27502bSShawn Tu } else {
1084bf27502bSShawn Tu ov5675->cur_mode = mode;
1085bf27502bSShawn Tu __v4l2_ctrl_s_ctrl(ov5675->link_freq, mode->link_freq_index);
1086bf27502bSShawn Tu __v4l2_ctrl_s_ctrl_int64(ov5675->pixel_rate,
1087bf27502bSShawn Tu to_pixel_rate(mode->link_freq_index));
1088bf27502bSShawn Tu
1089bf27502bSShawn Tu /* Update limits and set FPS to default */
1090bf27502bSShawn Tu vblank_def = mode->vts_def - mode->height;
1091bf27502bSShawn Tu __v4l2_ctrl_modify_range(ov5675->vblank,
1092bf27502bSShawn Tu mode->vts_min - mode->height,
1093bf27502bSShawn Tu OV5675_VTS_MAX - mode->height, 1,
1094bf27502bSShawn Tu vblank_def);
1095bf27502bSShawn Tu __v4l2_ctrl_s_ctrl(ov5675->vblank, vblank_def);
1096bf27502bSShawn Tu h_blank = to_pixels_per_line(mode->hts, mode->link_freq_index) -
1097bf27502bSShawn Tu mode->width;
1098bf27502bSShawn Tu __v4l2_ctrl_modify_range(ov5675->hblank, h_blank, h_blank, 1,
1099bf27502bSShawn Tu h_blank);
1100bf27502bSShawn Tu }
1101bf27502bSShawn Tu
1102bf27502bSShawn Tu mutex_unlock(&ov5675->mutex);
1103bf27502bSShawn Tu
1104bf27502bSShawn Tu return 0;
1105bf27502bSShawn Tu }
1106bf27502bSShawn Tu
ov5675_get_format(struct v4l2_subdev * sd,struct v4l2_subdev_state * sd_state,struct v4l2_subdev_format * fmt)1107bf27502bSShawn Tu static int ov5675_get_format(struct v4l2_subdev *sd,
11080d346d2aSTomi Valkeinen struct v4l2_subdev_state *sd_state,
1109bf27502bSShawn Tu struct v4l2_subdev_format *fmt)
1110bf27502bSShawn Tu {
1111bf27502bSShawn Tu struct ov5675 *ov5675 = to_ov5675(sd);
1112bf27502bSShawn Tu
1113bf27502bSShawn Tu mutex_lock(&ov5675->mutex);
1114bf27502bSShawn Tu if (fmt->which == V4L2_SUBDEV_FORMAT_TRY)
11150d346d2aSTomi Valkeinen fmt->format = *v4l2_subdev_get_try_format(&ov5675->sd,
11160d346d2aSTomi Valkeinen sd_state,
1117bf27502bSShawn Tu fmt->pad);
1118bf27502bSShawn Tu else
1119bf27502bSShawn Tu ov5675_update_pad_format(ov5675->cur_mode, &fmt->format);
1120bf27502bSShawn Tu
1121bf27502bSShawn Tu mutex_unlock(&ov5675->mutex);
1122bf27502bSShawn Tu
1123bf27502bSShawn Tu return 0;
1124bf27502bSShawn Tu }
1125bf27502bSShawn Tu
ov5675_get_selection(struct v4l2_subdev * sd,struct v4l2_subdev_state * state,struct v4l2_subdev_selection * sel)1126221827eeSQuentin Schulz static int ov5675_get_selection(struct v4l2_subdev *sd,
1127221827eeSQuentin Schulz struct v4l2_subdev_state *state,
1128221827eeSQuentin Schulz struct v4l2_subdev_selection *sel)
1129221827eeSQuentin Schulz {
1130221827eeSQuentin Schulz if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE)
1131221827eeSQuentin Schulz return -EINVAL;
1132221827eeSQuentin Schulz
1133221827eeSQuentin Schulz switch (sel->target) {
1134221827eeSQuentin Schulz case V4L2_SEL_TGT_CROP_BOUNDS:
1135221827eeSQuentin Schulz sel->r.top = 0;
1136221827eeSQuentin Schulz sel->r.left = 0;
1137221827eeSQuentin Schulz sel->r.width = 2624;
1138221827eeSQuentin Schulz sel->r.height = 2000;
1139221827eeSQuentin Schulz return 0;
1140221827eeSQuentin Schulz case V4L2_SEL_TGT_CROP:
1141221827eeSQuentin Schulz case V4L2_SEL_TGT_CROP_DEFAULT:
1142221827eeSQuentin Schulz sel->r.top = 16;
1143221827eeSQuentin Schulz sel->r.left = 16;
1144221827eeSQuentin Schulz sel->r.width = 2592;
1145221827eeSQuentin Schulz sel->r.height = 1944;
1146221827eeSQuentin Schulz return 0;
1147221827eeSQuentin Schulz }
1148221827eeSQuentin Schulz return -EINVAL;
1149221827eeSQuentin Schulz }
1150221827eeSQuentin Schulz
ov5675_enum_mbus_code(struct v4l2_subdev * sd,struct v4l2_subdev_state * sd_state,struct v4l2_subdev_mbus_code_enum * code)1151bf27502bSShawn Tu static int ov5675_enum_mbus_code(struct v4l2_subdev *sd,
11520d346d2aSTomi Valkeinen struct v4l2_subdev_state *sd_state,
1153bf27502bSShawn Tu struct v4l2_subdev_mbus_code_enum *code)
1154bf27502bSShawn Tu {
1155bf27502bSShawn Tu if (code->index > 0)
1156bf27502bSShawn Tu return -EINVAL;
1157bf27502bSShawn Tu
1158bf27502bSShawn Tu code->code = MEDIA_BUS_FMT_SGRBG10_1X10;
1159bf27502bSShawn Tu
1160bf27502bSShawn Tu return 0;
1161bf27502bSShawn Tu }
1162bf27502bSShawn Tu
ov5675_enum_frame_size(struct v4l2_subdev * sd,struct v4l2_subdev_state * sd_state,struct v4l2_subdev_frame_size_enum * fse)1163bf27502bSShawn Tu static int ov5675_enum_frame_size(struct v4l2_subdev *sd,
11640d346d2aSTomi Valkeinen struct v4l2_subdev_state *sd_state,
1165bf27502bSShawn Tu struct v4l2_subdev_frame_size_enum *fse)
1166bf27502bSShawn Tu {
1167bf27502bSShawn Tu if (fse->index >= ARRAY_SIZE(supported_modes))
1168bf27502bSShawn Tu return -EINVAL;
1169bf27502bSShawn Tu
1170bf27502bSShawn Tu if (fse->code != MEDIA_BUS_FMT_SGRBG10_1X10)
1171bf27502bSShawn Tu return -EINVAL;
1172bf27502bSShawn Tu
1173bf27502bSShawn Tu fse->min_width = supported_modes[fse->index].width;
1174bf27502bSShawn Tu fse->max_width = fse->min_width;
1175bf27502bSShawn Tu fse->min_height = supported_modes[fse->index].height;
1176bf27502bSShawn Tu fse->max_height = fse->min_height;
1177bf27502bSShawn Tu
1178bf27502bSShawn Tu return 0;
1179bf27502bSShawn Tu }
1180bf27502bSShawn Tu
ov5675_open(struct v4l2_subdev * sd,struct v4l2_subdev_fh * fh)1181bf27502bSShawn Tu static int ov5675_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
1182bf27502bSShawn Tu {
1183bf27502bSShawn Tu struct ov5675 *ov5675 = to_ov5675(sd);
1184bf27502bSShawn Tu
1185bf27502bSShawn Tu mutex_lock(&ov5675->mutex);
1186bf27502bSShawn Tu ov5675_update_pad_format(&supported_modes[0],
11870d346d2aSTomi Valkeinen v4l2_subdev_get_try_format(sd, fh->state, 0));
1188bf27502bSShawn Tu mutex_unlock(&ov5675->mutex);
1189bf27502bSShawn Tu
1190bf27502bSShawn Tu return 0;
1191bf27502bSShawn Tu }
1192bf27502bSShawn Tu
1193bf27502bSShawn Tu static const struct v4l2_subdev_video_ops ov5675_video_ops = {
1194bf27502bSShawn Tu .s_stream = ov5675_set_stream,
1195bf27502bSShawn Tu };
1196bf27502bSShawn Tu
1197bf27502bSShawn Tu static const struct v4l2_subdev_pad_ops ov5675_pad_ops = {
1198bf27502bSShawn Tu .set_fmt = ov5675_set_format,
1199bf27502bSShawn Tu .get_fmt = ov5675_get_format,
1200221827eeSQuentin Schulz .get_selection = ov5675_get_selection,
1201bf27502bSShawn Tu .enum_mbus_code = ov5675_enum_mbus_code,
1202bf27502bSShawn Tu .enum_frame_size = ov5675_enum_frame_size,
1203bf27502bSShawn Tu };
1204bf27502bSShawn Tu
1205bf27502bSShawn Tu static const struct v4l2_subdev_ops ov5675_subdev_ops = {
1206bf27502bSShawn Tu .video = &ov5675_video_ops,
1207bf27502bSShawn Tu .pad = &ov5675_pad_ops,
1208bf27502bSShawn Tu };
1209bf27502bSShawn Tu
1210bf27502bSShawn Tu static const struct media_entity_operations ov5675_subdev_entity_ops = {
1211bf27502bSShawn Tu .link_validate = v4l2_subdev_link_validate,
1212bf27502bSShawn Tu };
1213bf27502bSShawn Tu
1214bf27502bSShawn Tu static const struct v4l2_subdev_internal_ops ov5675_internal_ops = {
1215bf27502bSShawn Tu .open = ov5675_open,
1216bf27502bSShawn Tu };
1217bf27502bSShawn Tu
ov5675_get_hwcfg(struct ov5675 * ov5675,struct device * dev)121849d9ad71SQuentin Schulz static int ov5675_get_hwcfg(struct ov5675 *ov5675, struct device *dev)
1219bf27502bSShawn Tu {
1220bf27502bSShawn Tu struct fwnode_handle *ep;
1221bf27502bSShawn Tu struct fwnode_handle *fwnode = dev_fwnode(dev);
1222bf27502bSShawn Tu struct v4l2_fwnode_endpoint bus_cfg = {
1223bf27502bSShawn Tu .bus_type = V4L2_MBUS_CSI2_DPHY
1224bf27502bSShawn Tu };
122549d9ad71SQuentin Schulz u32 xvclk_rate;
1226bf27502bSShawn Tu int ret;
1227bf27502bSShawn Tu unsigned int i, j;
1228bf27502bSShawn Tu
1229bf27502bSShawn Tu if (!fwnode)
1230bf27502bSShawn Tu return -ENXIO;
1231bf27502bSShawn Tu
123249d9ad71SQuentin Schulz ov5675->xvclk = devm_clk_get_optional(dev, NULL);
123349d9ad71SQuentin Schulz if (IS_ERR(ov5675->xvclk))
123449d9ad71SQuentin Schulz return dev_err_probe(dev, PTR_ERR(ov5675->xvclk),
123549d9ad71SQuentin Schulz "failed to get xvclk: %ld\n",
123649d9ad71SQuentin Schulz PTR_ERR(ov5675->xvclk));
123749d9ad71SQuentin Schulz
123849d9ad71SQuentin Schulz if (ov5675->xvclk) {
123949d9ad71SQuentin Schulz xvclk_rate = clk_get_rate(ov5675->xvclk);
124049d9ad71SQuentin Schulz } else {
124149d9ad71SQuentin Schulz ret = fwnode_property_read_u32(fwnode, "clock-frequency",
124249d9ad71SQuentin Schulz &xvclk_rate);
1243bf27502bSShawn Tu
1244bf27502bSShawn Tu if (ret) {
1245bf27502bSShawn Tu dev_err(dev, "can't get clock frequency");
1246bf27502bSShawn Tu return ret;
1247bf27502bSShawn Tu }
124849d9ad71SQuentin Schulz }
1249bf27502bSShawn Tu
125049d9ad71SQuentin Schulz if (xvclk_rate != OV5675_XVCLK_19_2) {
125149d9ad71SQuentin Schulz dev_err(dev, "external clock rate %u is unsupported",
125249d9ad71SQuentin Schulz xvclk_rate);
1253bf27502bSShawn Tu return -EINVAL;
1254bf27502bSShawn Tu }
1255bf27502bSShawn Tu
125649d9ad71SQuentin Schulz ov5675->reset_gpio = devm_gpiod_get_optional(dev, "reset",
125749d9ad71SQuentin Schulz GPIOD_OUT_HIGH);
125849d9ad71SQuentin Schulz if (IS_ERR(ov5675->reset_gpio)) {
125949d9ad71SQuentin Schulz ret = PTR_ERR(ov5675->reset_gpio);
126049d9ad71SQuentin Schulz dev_err(dev, "failed to get reset-gpios: %d\n", ret);
126149d9ad71SQuentin Schulz return ret;
126249d9ad71SQuentin Schulz }
126349d9ad71SQuentin Schulz
126449d9ad71SQuentin Schulz for (i = 0; i < OV5675_NUM_SUPPLIES; i++)
126549d9ad71SQuentin Schulz ov5675->supplies[i].supply = ov5675_supply_names[i];
126649d9ad71SQuentin Schulz
126749d9ad71SQuentin Schulz ret = devm_regulator_bulk_get(dev, OV5675_NUM_SUPPLIES,
126849d9ad71SQuentin Schulz ov5675->supplies);
126949d9ad71SQuentin Schulz if (ret)
127049d9ad71SQuentin Schulz return ret;
127149d9ad71SQuentin Schulz
1272bf27502bSShawn Tu ep = fwnode_graph_get_next_endpoint(fwnode, NULL);
1273bf27502bSShawn Tu if (!ep)
1274bf27502bSShawn Tu return -ENXIO;
1275bf27502bSShawn Tu
1276bf27502bSShawn Tu ret = v4l2_fwnode_endpoint_alloc_parse(ep, &bus_cfg);
1277bf27502bSShawn Tu fwnode_handle_put(ep);
1278bf27502bSShawn Tu if (ret)
1279bf27502bSShawn Tu return ret;
1280bf27502bSShawn Tu
1281bf27502bSShawn Tu if (bus_cfg.bus.mipi_csi2.num_data_lanes != OV5675_DATA_LANES) {
1282bf27502bSShawn Tu dev_err(dev, "number of CSI2 data lanes %d is not supported",
1283bf27502bSShawn Tu bus_cfg.bus.mipi_csi2.num_data_lanes);
1284bf27502bSShawn Tu ret = -EINVAL;
1285bf27502bSShawn Tu goto check_hwcfg_error;
1286bf27502bSShawn Tu }
1287bf27502bSShawn Tu
1288bf27502bSShawn Tu if (!bus_cfg.nr_of_link_frequencies) {
1289bf27502bSShawn Tu dev_err(dev, "no link frequencies defined");
1290bf27502bSShawn Tu ret = -EINVAL;
1291bf27502bSShawn Tu goto check_hwcfg_error;
1292bf27502bSShawn Tu }
1293bf27502bSShawn Tu
1294bf27502bSShawn Tu for (i = 0; i < ARRAY_SIZE(link_freq_menu_items); i++) {
1295bf27502bSShawn Tu for (j = 0; j < bus_cfg.nr_of_link_frequencies; j++) {
1296bf27502bSShawn Tu if (link_freq_menu_items[i] ==
1297bf27502bSShawn Tu bus_cfg.link_frequencies[j])
1298bf27502bSShawn Tu break;
1299bf27502bSShawn Tu }
1300bf27502bSShawn Tu
1301bf27502bSShawn Tu if (j == bus_cfg.nr_of_link_frequencies) {
1302bf27502bSShawn Tu dev_err(dev, "no link frequency %lld supported",
1303bf27502bSShawn Tu link_freq_menu_items[i]);
1304bf27502bSShawn Tu ret = -EINVAL;
1305bf27502bSShawn Tu goto check_hwcfg_error;
1306bf27502bSShawn Tu }
1307bf27502bSShawn Tu }
1308bf27502bSShawn Tu
1309bf27502bSShawn Tu check_hwcfg_error:
1310bf27502bSShawn Tu v4l2_fwnode_endpoint_free(&bus_cfg);
1311bf27502bSShawn Tu
1312bf27502bSShawn Tu return ret;
1313bf27502bSShawn Tu }
1314bf27502bSShawn Tu
ov5675_remove(struct i2c_client * client)1315ed5c2f5fSUwe Kleine-König static void ov5675_remove(struct i2c_client *client)
1316bf27502bSShawn Tu {
1317bf27502bSShawn Tu struct v4l2_subdev *sd = i2c_get_clientdata(client);
1318bf27502bSShawn Tu struct ov5675 *ov5675 = to_ov5675(sd);
1319bf27502bSShawn Tu
1320bf27502bSShawn Tu v4l2_async_unregister_subdev(sd);
1321bf27502bSShawn Tu media_entity_cleanup(&sd->entity);
1322bf27502bSShawn Tu v4l2_ctrl_handler_free(sd->ctrl_handler);
1323bf27502bSShawn Tu pm_runtime_disable(&client->dev);
1324bf27502bSShawn Tu mutex_destroy(&ov5675->mutex);
132549d9ad71SQuentin Schulz
132649d9ad71SQuentin Schulz if (!pm_runtime_status_suspended(&client->dev))
132749d9ad71SQuentin Schulz ov5675_power_off(&client->dev);
132849d9ad71SQuentin Schulz pm_runtime_set_suspended(&client->dev);
1329bf27502bSShawn Tu }
1330bf27502bSShawn Tu
ov5675_probe(struct i2c_client * client)1331bf27502bSShawn Tu static int ov5675_probe(struct i2c_client *client)
1332bf27502bSShawn Tu {
1333bf27502bSShawn Tu struct ov5675 *ov5675;
13345525fd86SBingbu Cao bool full_power;
1335bf27502bSShawn Tu int ret;
1336bf27502bSShawn Tu
1337bf27502bSShawn Tu ov5675 = devm_kzalloc(&client->dev, sizeof(*ov5675), GFP_KERNEL);
1338bf27502bSShawn Tu if (!ov5675)
1339bf27502bSShawn Tu return -ENOMEM;
1340bf27502bSShawn Tu
134149d9ad71SQuentin Schulz ret = ov5675_get_hwcfg(ov5675, &client->dev);
134249d9ad71SQuentin Schulz if (ret) {
134349d9ad71SQuentin Schulz dev_err(&client->dev, "failed to get HW configuration: %d",
134449d9ad71SQuentin Schulz ret);
134549d9ad71SQuentin Schulz return ret;
134649d9ad71SQuentin Schulz }
134749d9ad71SQuentin Schulz
1348bf27502bSShawn Tu v4l2_i2c_subdev_init(&ov5675->sd, client, &ov5675_subdev_ops);
13495525fd86SBingbu Cao
135049d9ad71SQuentin Schulz ret = ov5675_power_on(&client->dev);
135149d9ad71SQuentin Schulz if (ret) {
135249d9ad71SQuentin Schulz dev_err(&client->dev, "failed to power on: %d\n", ret);
135349d9ad71SQuentin Schulz return ret;
135449d9ad71SQuentin Schulz }
135549d9ad71SQuentin Schulz
13565525fd86SBingbu Cao full_power = acpi_dev_state_d0(&client->dev);
13575525fd86SBingbu Cao if (full_power) {
1358bf27502bSShawn Tu ret = ov5675_identify_module(ov5675);
1359bf27502bSShawn Tu if (ret) {
1360bf27502bSShawn Tu dev_err(&client->dev, "failed to find sensor: %d", ret);
136149d9ad71SQuentin Schulz goto probe_power_off;
1362bf27502bSShawn Tu }
13635525fd86SBingbu Cao }
1364bf27502bSShawn Tu
1365bf27502bSShawn Tu mutex_init(&ov5675->mutex);
1366bf27502bSShawn Tu ov5675->cur_mode = &supported_modes[0];
1367bf27502bSShawn Tu ret = ov5675_init_controls(ov5675);
1368bf27502bSShawn Tu if (ret) {
1369bf27502bSShawn Tu dev_err(&client->dev, "failed to init controls: %d", ret);
1370bf27502bSShawn Tu goto probe_error_v4l2_ctrl_handler_free;
1371bf27502bSShawn Tu }
1372bf27502bSShawn Tu
1373bf27502bSShawn Tu ov5675->sd.internal_ops = &ov5675_internal_ops;
1374bf27502bSShawn Tu ov5675->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
1375bf27502bSShawn Tu ov5675->sd.entity.ops = &ov5675_subdev_entity_ops;
1376bf27502bSShawn Tu ov5675->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
1377bf27502bSShawn Tu ov5675->pad.flags = MEDIA_PAD_FL_SOURCE;
1378bf27502bSShawn Tu ret = media_entity_pads_init(&ov5675->sd.entity, 1, &ov5675->pad);
1379bf27502bSShawn Tu if (ret) {
1380bf27502bSShawn Tu dev_err(&client->dev, "failed to init entity pads: %d", ret);
1381bf27502bSShawn Tu goto probe_error_v4l2_ctrl_handler_free;
1382bf27502bSShawn Tu }
1383bf27502bSShawn Tu
138415786f7bSSakari Ailus ret = v4l2_async_register_subdev_sensor(&ov5675->sd);
1385bf27502bSShawn Tu if (ret < 0) {
1386bf27502bSShawn Tu dev_err(&client->dev, "failed to register V4L2 subdev: %d",
1387bf27502bSShawn Tu ret);
1388bf27502bSShawn Tu goto probe_error_media_entity_cleanup;
1389bf27502bSShawn Tu }
1390bf27502bSShawn Tu
13915525fd86SBingbu Cao /* Set the device's state to active if it's in D0 state. */
13925525fd86SBingbu Cao if (full_power)
1393bf27502bSShawn Tu pm_runtime_set_active(&client->dev);
1394bf27502bSShawn Tu pm_runtime_enable(&client->dev);
1395bf27502bSShawn Tu pm_runtime_idle(&client->dev);
1396bf27502bSShawn Tu
1397bf27502bSShawn Tu return 0;
1398bf27502bSShawn Tu
1399bf27502bSShawn Tu probe_error_media_entity_cleanup:
1400bf27502bSShawn Tu media_entity_cleanup(&ov5675->sd.entity);
1401bf27502bSShawn Tu
1402bf27502bSShawn Tu probe_error_v4l2_ctrl_handler_free:
1403bf27502bSShawn Tu v4l2_ctrl_handler_free(ov5675->sd.ctrl_handler);
1404bf27502bSShawn Tu mutex_destroy(&ov5675->mutex);
140549d9ad71SQuentin Schulz probe_power_off:
140649d9ad71SQuentin Schulz ov5675_power_off(&client->dev);
1407bf27502bSShawn Tu
1408bf27502bSShawn Tu return ret;
1409bf27502bSShawn Tu }
1410bf27502bSShawn Tu
1411bf27502bSShawn Tu static const struct dev_pm_ops ov5675_pm_ops = {
1412bf27502bSShawn Tu SET_SYSTEM_SLEEP_PM_OPS(ov5675_suspend, ov5675_resume)
141349d9ad71SQuentin Schulz SET_RUNTIME_PM_OPS(ov5675_power_off, ov5675_power_on, NULL)
1414bf27502bSShawn Tu };
1415bf27502bSShawn Tu
1416bf27502bSShawn Tu #ifdef CONFIG_ACPI
1417bf27502bSShawn Tu static const struct acpi_device_id ov5675_acpi_ids[] = {
1418bf27502bSShawn Tu {"OVTI5675"},
1419bf27502bSShawn Tu {}
1420bf27502bSShawn Tu };
1421bf27502bSShawn Tu
1422bf27502bSShawn Tu MODULE_DEVICE_TABLE(acpi, ov5675_acpi_ids);
1423bf27502bSShawn Tu #endif
1424bf27502bSShawn Tu
142549d9ad71SQuentin Schulz static const struct of_device_id ov5675_of_match[] = {
142649d9ad71SQuentin Schulz { .compatible = "ovti,ov5675", },
142749d9ad71SQuentin Schulz { /* sentinel */ },
142849d9ad71SQuentin Schulz };
142949d9ad71SQuentin Schulz MODULE_DEVICE_TABLE(of, ov5675_of_match);
143049d9ad71SQuentin Schulz
1431bf27502bSShawn Tu static struct i2c_driver ov5675_i2c_driver = {
1432bf27502bSShawn Tu .driver = {
1433bf27502bSShawn Tu .name = "ov5675",
1434bf27502bSShawn Tu .pm = &ov5675_pm_ops,
1435bf27502bSShawn Tu .acpi_match_table = ACPI_PTR(ov5675_acpi_ids),
143649d9ad71SQuentin Schulz .of_match_table = ov5675_of_match,
1437bf27502bSShawn Tu },
1438aaeb31c0SUwe Kleine-König .probe = ov5675_probe,
1439bf27502bSShawn Tu .remove = ov5675_remove,
14405525fd86SBingbu Cao .flags = I2C_DRV_ACPI_WAIVE_D0_PROBE,
1441bf27502bSShawn Tu };
1442bf27502bSShawn Tu
1443bf27502bSShawn Tu module_i2c_driver(ov5675_i2c_driver);
1444bf27502bSShawn Tu
1445*4106cd72SSakari Ailus MODULE_AUTHOR("Shawn Tu");
1446bf27502bSShawn Tu MODULE_DESCRIPTION("OmniVision OV5675 sensor driver");
1447bf27502bSShawn Tu MODULE_LICENSE("GPL v2");
1448