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
5165525fd86SBingbu Cao /* True if the device has been identified */
5175525fd86SBingbu Cao bool identified;
518bf27502bSShawn Tu };
519bf27502bSShawn Tu
to_pixel_rate(u32 f_index)520bf27502bSShawn Tu static u64 to_pixel_rate(u32 f_index)
521bf27502bSShawn Tu {
522bf27502bSShawn Tu u64 pixel_rate = link_freq_menu_items[f_index] * 2 * OV5675_DATA_LANES;
523bf27502bSShawn Tu
524bf27502bSShawn Tu do_div(pixel_rate, OV5675_RGB_DEPTH);
525bf27502bSShawn Tu
526bf27502bSShawn Tu return pixel_rate;
527bf27502bSShawn Tu }
528bf27502bSShawn Tu
to_pixels_per_line(u32 hts,u32 f_index)529bf27502bSShawn Tu static u64 to_pixels_per_line(u32 hts, u32 f_index)
530bf27502bSShawn Tu {
531bf27502bSShawn Tu u64 ppl = hts * to_pixel_rate(f_index);
532bf27502bSShawn Tu
533bf27502bSShawn Tu do_div(ppl, OV5675_SCLK);
534bf27502bSShawn Tu
535bf27502bSShawn Tu return ppl;
536bf27502bSShawn Tu }
537bf27502bSShawn Tu
ov5675_read_reg(struct ov5675 * ov5675,u16 reg,u16 len,u32 * val)538bf27502bSShawn Tu static int ov5675_read_reg(struct ov5675 *ov5675, u16 reg, u16 len, u32 *val)
539bf27502bSShawn Tu {
540bf27502bSShawn Tu struct i2c_client *client = v4l2_get_subdevdata(&ov5675->sd);
541bf27502bSShawn Tu struct i2c_msg msgs[2];
542bf27502bSShawn Tu u8 addr_buf[2];
543bf27502bSShawn Tu u8 data_buf[4] = {0};
544bf27502bSShawn Tu int ret;
545bf27502bSShawn Tu
546bf27502bSShawn Tu if (len > 4)
547bf27502bSShawn Tu return -EINVAL;
548bf27502bSShawn Tu
549bf27502bSShawn Tu put_unaligned_be16(reg, addr_buf);
550bf27502bSShawn Tu msgs[0].addr = client->addr;
551bf27502bSShawn Tu msgs[0].flags = 0;
552bf27502bSShawn Tu msgs[0].len = sizeof(addr_buf);
553bf27502bSShawn Tu msgs[0].buf = addr_buf;
554bf27502bSShawn Tu msgs[1].addr = client->addr;
555bf27502bSShawn Tu msgs[1].flags = I2C_M_RD;
556bf27502bSShawn Tu msgs[1].len = len;
557bf27502bSShawn Tu msgs[1].buf = &data_buf[4 - len];
558bf27502bSShawn Tu
559bf27502bSShawn Tu ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
560bf27502bSShawn Tu if (ret != ARRAY_SIZE(msgs))
561bf27502bSShawn Tu return -EIO;
562bf27502bSShawn Tu
563bf27502bSShawn Tu *val = get_unaligned_be32(data_buf);
564bf27502bSShawn Tu
565bf27502bSShawn Tu return 0;
566bf27502bSShawn Tu }
567bf27502bSShawn Tu
ov5675_write_reg(struct ov5675 * ov5675,u16 reg,u16 len,u32 val)568bf27502bSShawn Tu static int ov5675_write_reg(struct ov5675 *ov5675, u16 reg, u16 len, u32 val)
569bf27502bSShawn Tu {
570bf27502bSShawn Tu struct i2c_client *client = v4l2_get_subdevdata(&ov5675->sd);
571bf27502bSShawn Tu u8 buf[6];
572bf27502bSShawn Tu
573bf27502bSShawn Tu if (len > 4)
574bf27502bSShawn Tu return -EINVAL;
575bf27502bSShawn Tu
576bf27502bSShawn Tu put_unaligned_be16(reg, buf);
577bf27502bSShawn Tu put_unaligned_be32(val << 8 * (4 - len), buf + 2);
578bf27502bSShawn Tu if (i2c_master_send(client, buf, len + 2) != len + 2)
579bf27502bSShawn Tu return -EIO;
580bf27502bSShawn Tu
581bf27502bSShawn Tu return 0;
582bf27502bSShawn Tu }
583bf27502bSShawn Tu
ov5675_write_reg_list(struct ov5675 * ov5675,const struct ov5675_reg_list * r_list)584bf27502bSShawn Tu static int ov5675_write_reg_list(struct ov5675 *ov5675,
585bf27502bSShawn Tu const struct ov5675_reg_list *r_list)
586bf27502bSShawn Tu {
587bf27502bSShawn Tu struct i2c_client *client = v4l2_get_subdevdata(&ov5675->sd);
588bf27502bSShawn Tu unsigned int i;
589bf27502bSShawn Tu int ret;
590bf27502bSShawn Tu
591bf27502bSShawn Tu for (i = 0; i < r_list->num_of_regs; i++) {
592bf27502bSShawn Tu ret = ov5675_write_reg(ov5675, r_list->regs[i].address, 1,
593bf27502bSShawn Tu r_list->regs[i].val);
594bf27502bSShawn Tu if (ret) {
595bf27502bSShawn Tu dev_err_ratelimited(&client->dev,
596bf27502bSShawn Tu "failed to write reg 0x%4.4x. error = %d",
597bf27502bSShawn Tu r_list->regs[i].address, ret);
598bf27502bSShawn Tu return ret;
599bf27502bSShawn Tu }
600bf27502bSShawn Tu }
601bf27502bSShawn Tu
602bf27502bSShawn Tu return 0;
603bf27502bSShawn Tu }
604bf27502bSShawn Tu
ov5675_update_digital_gain(struct ov5675 * ov5675,u32 d_gain)605bf27502bSShawn Tu static int ov5675_update_digital_gain(struct ov5675 *ov5675, u32 d_gain)
606bf27502bSShawn Tu {
607bf27502bSShawn Tu int ret;
608bf27502bSShawn Tu
60924e9edc1SBingbu Cao ret = ov5675_write_reg(ov5675, OV5675_REG_GROUP_ACCESS,
61024e9edc1SBingbu Cao OV5675_REG_VALUE_08BIT,
61124e9edc1SBingbu Cao OV5675_GROUP_HOLD_START);
61224e9edc1SBingbu Cao if (ret)
61324e9edc1SBingbu Cao return ret;
61424e9edc1SBingbu Cao
615bf27502bSShawn Tu ret = ov5675_write_reg(ov5675, OV5675_REG_MWB_R_GAIN,
616bf27502bSShawn Tu OV5675_REG_VALUE_16BIT, d_gain);
617bf27502bSShawn Tu if (ret)
618bf27502bSShawn Tu return ret;
619bf27502bSShawn Tu
620bf27502bSShawn Tu ret = ov5675_write_reg(ov5675, OV5675_REG_MWB_G_GAIN,
621bf27502bSShawn Tu OV5675_REG_VALUE_16BIT, d_gain);
622bf27502bSShawn Tu if (ret)
623bf27502bSShawn Tu return ret;
624bf27502bSShawn Tu
62524e9edc1SBingbu Cao ret = ov5675_write_reg(ov5675, OV5675_REG_MWB_B_GAIN,
626bf27502bSShawn Tu OV5675_REG_VALUE_16BIT, d_gain);
62724e9edc1SBingbu Cao if (ret)
62824e9edc1SBingbu Cao return ret;
62924e9edc1SBingbu Cao
63024e9edc1SBingbu Cao ret = ov5675_write_reg(ov5675, OV5675_REG_GROUP_ACCESS,
63124e9edc1SBingbu Cao OV5675_REG_VALUE_08BIT,
63224e9edc1SBingbu Cao OV5675_GROUP_HOLD_END);
63324e9edc1SBingbu Cao if (ret)
63424e9edc1SBingbu Cao return ret;
63524e9edc1SBingbu Cao
63624e9edc1SBingbu Cao ret = ov5675_write_reg(ov5675, OV5675_REG_GROUP_ACCESS,
63724e9edc1SBingbu Cao OV5675_REG_VALUE_08BIT,
63824e9edc1SBingbu Cao OV5675_GROUP_HOLD_LAUNCH);
63924e9edc1SBingbu Cao return ret;
640bf27502bSShawn Tu }
641bf27502bSShawn Tu
ov5675_test_pattern(struct ov5675 * ov5675,u32 pattern)642bf27502bSShawn Tu static int ov5675_test_pattern(struct ov5675 *ov5675, u32 pattern)
643bf27502bSShawn Tu {
644bf27502bSShawn Tu if (pattern)
645bf27502bSShawn Tu pattern = (pattern - 1) << OV5675_TEST_PATTERN_BAR_SHIFT |
646bf27502bSShawn Tu OV5675_TEST_PATTERN_ENABLE;
647bf27502bSShawn Tu
648bf27502bSShawn Tu return ov5675_write_reg(ov5675, OV5675_REG_TEST_PATTERN,
649bf27502bSShawn Tu OV5675_REG_VALUE_08BIT, pattern);
650bf27502bSShawn Tu }
651bf27502bSShawn Tu
652e8882e1bSShawn Tu /*
653e8882e1bSShawn Tu * OV5675 supports keeping the pixel order by mirror and flip function
654e8882e1bSShawn Tu * The Bayer order isn't affected by the flip controls
655e8882e1bSShawn Tu */
ov5675_set_ctrl_hflip(struct ov5675 * ov5675,u32 ctrl_val)656e8882e1bSShawn Tu static int ov5675_set_ctrl_hflip(struct ov5675 *ov5675, u32 ctrl_val)
657e8882e1bSShawn Tu {
658e8882e1bSShawn Tu int ret;
659e8882e1bSShawn Tu u32 val;
660e8882e1bSShawn Tu
661e8882e1bSShawn Tu ret = ov5675_read_reg(ov5675, OV5675_REG_FORMAT1,
662e8882e1bSShawn Tu OV5675_REG_VALUE_08BIT, &val);
663e8882e1bSShawn Tu if (ret)
664e8882e1bSShawn Tu return ret;
665e8882e1bSShawn Tu
666e8882e1bSShawn Tu return ov5675_write_reg(ov5675, OV5675_REG_FORMAT1,
667e8882e1bSShawn Tu OV5675_REG_VALUE_08BIT,
6686f862f84SShawn Tu ctrl_val ? val & ~BIT(3) : val | BIT(3));
669e8882e1bSShawn Tu }
670e8882e1bSShawn Tu
ov5675_set_ctrl_vflip(struct ov5675 * ov5675,u8 ctrl_val)671e8882e1bSShawn Tu static int ov5675_set_ctrl_vflip(struct ov5675 *ov5675, u8 ctrl_val)
672e8882e1bSShawn Tu {
673e8882e1bSShawn Tu int ret;
674e8882e1bSShawn Tu u32 val;
675e8882e1bSShawn Tu
676e8882e1bSShawn Tu ret = ov5675_read_reg(ov5675, OV5675_REG_FORMAT1,
677e8882e1bSShawn Tu OV5675_REG_VALUE_08BIT, &val);
678e8882e1bSShawn Tu if (ret)
679e8882e1bSShawn Tu return ret;
680e8882e1bSShawn Tu
681e8882e1bSShawn Tu ret = ov5675_write_reg(ov5675, OV5675_REG_FORMAT1,
682e8882e1bSShawn Tu OV5675_REG_VALUE_08BIT,
6836f862f84SShawn Tu ctrl_val ? val | BIT(4) | BIT(5) : val & ~BIT(4) & ~BIT(5));
684e8882e1bSShawn Tu
685e8882e1bSShawn Tu if (ret)
686e8882e1bSShawn Tu return ret;
687e8882e1bSShawn Tu
688e8882e1bSShawn Tu ret = ov5675_read_reg(ov5675, OV5675_REG_FORMAT2,
689e8882e1bSShawn Tu OV5675_REG_VALUE_08BIT, &val);
690e8882e1bSShawn Tu
691e8882e1bSShawn Tu if (ret)
692e8882e1bSShawn Tu return ret;
693e8882e1bSShawn Tu
694e8882e1bSShawn Tu return ov5675_write_reg(ov5675, OV5675_REG_FORMAT2,
695e8882e1bSShawn Tu OV5675_REG_VALUE_08BIT,
6966f862f84SShawn Tu ctrl_val ? val | BIT(1) : val & ~BIT(1));
697e8882e1bSShawn Tu }
698e8882e1bSShawn Tu
ov5675_set_ctrl(struct v4l2_ctrl * ctrl)699bf27502bSShawn Tu static int ov5675_set_ctrl(struct v4l2_ctrl *ctrl)
700bf27502bSShawn Tu {
701bf27502bSShawn Tu struct ov5675 *ov5675 = container_of(ctrl->handler,
702bf27502bSShawn Tu struct ov5675, ctrl_handler);
703bf27502bSShawn Tu struct i2c_client *client = v4l2_get_subdevdata(&ov5675->sd);
704bf27502bSShawn Tu s64 exposure_max;
705bf27502bSShawn Tu int ret = 0;
706bf27502bSShawn Tu
707bf27502bSShawn Tu /* Propagate change of current control to all related controls */
708bf27502bSShawn Tu if (ctrl->id == V4L2_CID_VBLANK) {
709bf27502bSShawn Tu /* Update max exposure while meeting expected vblanking */
710ab3d4b41SBingbu Cao exposure_max = ov5675->cur_mode->height + ctrl->val -
711ab3d4b41SBingbu Cao OV5675_EXPOSURE_MAX_MARGIN;
712bf27502bSShawn Tu __v4l2_ctrl_modify_range(ov5675->exposure,
713bf27502bSShawn Tu ov5675->exposure->minimum,
714bf27502bSShawn Tu exposure_max, ov5675->exposure->step,
715bf27502bSShawn Tu exposure_max);
716bf27502bSShawn Tu }
717bf27502bSShawn Tu
718bf27502bSShawn Tu /* V4L2 controls values will be applied only when power is already up */
719bf27502bSShawn Tu if (!pm_runtime_get_if_in_use(&client->dev))
720bf27502bSShawn Tu return 0;
721bf27502bSShawn Tu
722bf27502bSShawn Tu switch (ctrl->id) {
723bf27502bSShawn Tu case V4L2_CID_ANALOGUE_GAIN:
724bf27502bSShawn Tu ret = ov5675_write_reg(ov5675, OV5675_REG_ANALOG_GAIN,
725bf27502bSShawn Tu OV5675_REG_VALUE_16BIT, ctrl->val);
726bf27502bSShawn Tu break;
727bf27502bSShawn Tu
728bf27502bSShawn Tu case V4L2_CID_DIGITAL_GAIN:
729bf27502bSShawn Tu ret = ov5675_update_digital_gain(ov5675, ctrl->val);
730bf27502bSShawn Tu break;
731bf27502bSShawn Tu
732bf27502bSShawn Tu case V4L2_CID_EXPOSURE:
733ab3d4b41SBingbu Cao /* 4 least significant bits of expsoure are fractional part
734ab3d4b41SBingbu Cao * val = val << 4
735ab3d4b41SBingbu Cao * for ov5675, the unit of exposure is differnt from other
736ab3d4b41SBingbu Cao * OmniVision sensors, its exposure value is twice of the
737ab3d4b41SBingbu Cao * register value, the exposure should be divided by 2 before
738ab3d4b41SBingbu Cao * set register, e.g. val << 3.
739ab3d4b41SBingbu Cao */
740bf27502bSShawn Tu ret = ov5675_write_reg(ov5675, OV5675_REG_EXPOSURE,
741bf27502bSShawn Tu OV5675_REG_VALUE_24BIT, ctrl->val << 3);
742bf27502bSShawn Tu break;
743bf27502bSShawn Tu
744bf27502bSShawn Tu case V4L2_CID_VBLANK:
745bf27502bSShawn Tu ret = ov5675_write_reg(ov5675, OV5675_REG_VTS,
746bf27502bSShawn Tu OV5675_REG_VALUE_16BIT,
747bf27502bSShawn Tu ov5675->cur_mode->height + ctrl->val +
748bf27502bSShawn Tu 10);
749bf27502bSShawn Tu break;
750bf27502bSShawn Tu
751bf27502bSShawn Tu case V4L2_CID_TEST_PATTERN:
752bf27502bSShawn Tu ret = ov5675_test_pattern(ov5675, ctrl->val);
753bf27502bSShawn Tu break;
754bf27502bSShawn Tu
755e8882e1bSShawn Tu case V4L2_CID_HFLIP:
756e8882e1bSShawn Tu ov5675_set_ctrl_hflip(ov5675, ctrl->val);
757e8882e1bSShawn Tu break;
758e8882e1bSShawn Tu
759e8882e1bSShawn Tu case V4L2_CID_VFLIP:
760e8882e1bSShawn Tu ov5675_set_ctrl_vflip(ov5675, ctrl->val);
761e8882e1bSShawn Tu break;
762e8882e1bSShawn Tu
763bf27502bSShawn Tu default:
764bf27502bSShawn Tu ret = -EINVAL;
765bf27502bSShawn Tu break;
766bf27502bSShawn Tu }
767bf27502bSShawn Tu
768bf27502bSShawn Tu pm_runtime_put(&client->dev);
769bf27502bSShawn Tu
770bf27502bSShawn Tu return ret;
771bf27502bSShawn Tu }
772bf27502bSShawn Tu
773bf27502bSShawn Tu static const struct v4l2_ctrl_ops ov5675_ctrl_ops = {
774bf27502bSShawn Tu .s_ctrl = ov5675_set_ctrl,
775bf27502bSShawn Tu };
776bf27502bSShawn Tu
ov5675_init_controls(struct ov5675 * ov5675)777bf27502bSShawn Tu static int ov5675_init_controls(struct ov5675 *ov5675)
778bf27502bSShawn Tu {
779c8aa2111SQuentin Schulz struct i2c_client *client = v4l2_get_subdevdata(&ov5675->sd);
780c8aa2111SQuentin Schulz struct v4l2_fwnode_device_properties props;
781bf27502bSShawn Tu struct v4l2_ctrl_handler *ctrl_hdlr;
782bf27502bSShawn Tu s64 exposure_max, h_blank;
783bf27502bSShawn Tu int ret;
784bf27502bSShawn Tu
785bf27502bSShawn Tu ctrl_hdlr = &ov5675->ctrl_handler;
786c8aa2111SQuentin Schulz ret = v4l2_ctrl_handler_init(ctrl_hdlr, 10);
787bf27502bSShawn Tu if (ret)
788bf27502bSShawn Tu return ret;
789bf27502bSShawn Tu
790bf27502bSShawn Tu ctrl_hdlr->lock = &ov5675->mutex;
791bf27502bSShawn Tu ov5675->link_freq = v4l2_ctrl_new_int_menu(ctrl_hdlr, &ov5675_ctrl_ops,
792bf27502bSShawn Tu V4L2_CID_LINK_FREQ,
793bf27502bSShawn Tu ARRAY_SIZE(link_freq_menu_items) - 1,
794bf27502bSShawn Tu 0, link_freq_menu_items);
795bf27502bSShawn Tu if (ov5675->link_freq)
796bf27502bSShawn Tu ov5675->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
797bf27502bSShawn Tu
798bf27502bSShawn Tu ov5675->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &ov5675_ctrl_ops,
799bf27502bSShawn Tu V4L2_CID_PIXEL_RATE, 0,
800bf27502bSShawn Tu to_pixel_rate(OV5675_LINK_FREQ_900MBPS),
801bf27502bSShawn Tu 1,
802bf27502bSShawn Tu to_pixel_rate(OV5675_LINK_FREQ_900MBPS));
803bf27502bSShawn Tu ov5675->vblank = v4l2_ctrl_new_std(ctrl_hdlr, &ov5675_ctrl_ops,
804bf27502bSShawn Tu V4L2_CID_VBLANK,
805bf27502bSShawn Tu ov5675->cur_mode->vts_min - ov5675->cur_mode->height,
806bf27502bSShawn Tu OV5675_VTS_MAX - ov5675->cur_mode->height, 1,
807bf27502bSShawn Tu ov5675->cur_mode->vts_def - ov5675->cur_mode->height);
808bf27502bSShawn Tu h_blank = to_pixels_per_line(ov5675->cur_mode->hts,
809bf27502bSShawn Tu ov5675->cur_mode->link_freq_index) - ov5675->cur_mode->width;
810bf27502bSShawn Tu ov5675->hblank = v4l2_ctrl_new_std(ctrl_hdlr, &ov5675_ctrl_ops,
811bf27502bSShawn Tu V4L2_CID_HBLANK, h_blank, h_blank, 1,
812bf27502bSShawn Tu h_blank);
813bf27502bSShawn Tu if (ov5675->hblank)
814bf27502bSShawn Tu ov5675->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
815bf27502bSShawn Tu
816bf27502bSShawn Tu v4l2_ctrl_new_std(ctrl_hdlr, &ov5675_ctrl_ops, V4L2_CID_ANALOGUE_GAIN,
817bf27502bSShawn Tu OV5675_ANAL_GAIN_MIN, OV5675_ANAL_GAIN_MAX,
818bf27502bSShawn Tu OV5675_ANAL_GAIN_STEP, OV5675_ANAL_GAIN_MIN);
819bf27502bSShawn Tu v4l2_ctrl_new_std(ctrl_hdlr, &ov5675_ctrl_ops, V4L2_CID_DIGITAL_GAIN,
820bf27502bSShawn Tu OV5675_DGTL_GAIN_MIN, OV5675_DGTL_GAIN_MAX,
821bf27502bSShawn Tu OV5675_DGTL_GAIN_STEP, OV5675_DGTL_GAIN_DEFAULT);
822ab3d4b41SBingbu Cao exposure_max = (ov5675->cur_mode->vts_def - OV5675_EXPOSURE_MAX_MARGIN);
823bf27502bSShawn Tu ov5675->exposure = v4l2_ctrl_new_std(ctrl_hdlr, &ov5675_ctrl_ops,
824bf27502bSShawn Tu V4L2_CID_EXPOSURE,
825bf27502bSShawn Tu OV5675_EXPOSURE_MIN, exposure_max,
826bf27502bSShawn Tu OV5675_EXPOSURE_STEP,
827bf27502bSShawn Tu exposure_max);
828bf27502bSShawn Tu v4l2_ctrl_new_std_menu_items(ctrl_hdlr, &ov5675_ctrl_ops,
829bf27502bSShawn Tu V4L2_CID_TEST_PATTERN,
830bf27502bSShawn Tu ARRAY_SIZE(ov5675_test_pattern_menu) - 1,
831bf27502bSShawn Tu 0, 0, ov5675_test_pattern_menu);
832e8882e1bSShawn Tu v4l2_ctrl_new_std(ctrl_hdlr, &ov5675_ctrl_ops,
833e8882e1bSShawn Tu V4L2_CID_HFLIP, 0, 1, 1, 0);
834e8882e1bSShawn Tu v4l2_ctrl_new_std(ctrl_hdlr, &ov5675_ctrl_ops,
835e8882e1bSShawn Tu V4L2_CID_VFLIP, 0, 1, 1, 0);
836e8882e1bSShawn Tu
837dd74ed6cSShang XiaoJing if (ctrl_hdlr->error) {
838dd74ed6cSShang XiaoJing v4l2_ctrl_handler_free(ctrl_hdlr);
839bf27502bSShawn Tu return ctrl_hdlr->error;
840dd74ed6cSShang XiaoJing }
841bf27502bSShawn Tu
842c8aa2111SQuentin Schulz ret = v4l2_fwnode_device_parse(&client->dev, &props);
843c8aa2111SQuentin Schulz if (ret)
844c8aa2111SQuentin Schulz goto error;
845c8aa2111SQuentin Schulz
846c8aa2111SQuentin Schulz ret = v4l2_ctrl_new_fwnode_properties(ctrl_hdlr, &ov5675_ctrl_ops,
847c8aa2111SQuentin Schulz &props);
848c8aa2111SQuentin Schulz if (ret)
849c8aa2111SQuentin Schulz goto error;
850c8aa2111SQuentin Schulz
851bf27502bSShawn Tu ov5675->sd.ctrl_handler = ctrl_hdlr;
852bf27502bSShawn Tu
853bf27502bSShawn Tu return 0;
854c8aa2111SQuentin Schulz
855c8aa2111SQuentin Schulz error:
856c8aa2111SQuentin Schulz v4l2_ctrl_handler_free(ctrl_hdlr);
857c8aa2111SQuentin Schulz
858c8aa2111SQuentin Schulz return ret;
859bf27502bSShawn Tu }
860bf27502bSShawn Tu
ov5675_update_pad_format(const struct ov5675_mode * mode,struct v4l2_mbus_framefmt * fmt)861bf27502bSShawn Tu static void ov5675_update_pad_format(const struct ov5675_mode *mode,
862bf27502bSShawn Tu struct v4l2_mbus_framefmt *fmt)
863bf27502bSShawn Tu {
864bf27502bSShawn Tu fmt->width = mode->width;
865bf27502bSShawn Tu fmt->height = mode->height;
866bf27502bSShawn Tu fmt->code = MEDIA_BUS_FMT_SGRBG10_1X10;
867bf27502bSShawn Tu fmt->field = V4L2_FIELD_NONE;
868bf27502bSShawn Tu }
869bf27502bSShawn Tu
ov5675_identify_module(struct ov5675 * ov5675)8705525fd86SBingbu Cao static int ov5675_identify_module(struct ov5675 *ov5675)
8715525fd86SBingbu Cao {
8725525fd86SBingbu Cao struct i2c_client *client = v4l2_get_subdevdata(&ov5675->sd);
8735525fd86SBingbu Cao int ret;
8745525fd86SBingbu Cao u32 val;
8755525fd86SBingbu Cao
8765525fd86SBingbu Cao if (ov5675->identified)
8775525fd86SBingbu Cao return 0;
8785525fd86SBingbu Cao
8795525fd86SBingbu Cao ret = ov5675_read_reg(ov5675, OV5675_REG_CHIP_ID,
8805525fd86SBingbu Cao OV5675_REG_VALUE_24BIT, &val);
8815525fd86SBingbu Cao if (ret)
8825525fd86SBingbu Cao return ret;
8835525fd86SBingbu Cao
8845525fd86SBingbu Cao if (val != OV5675_CHIP_ID) {
8855525fd86SBingbu Cao dev_err(&client->dev, "chip id mismatch: %x!=%x",
8865525fd86SBingbu Cao OV5675_CHIP_ID, val);
8875525fd86SBingbu Cao return -ENXIO;
8885525fd86SBingbu Cao }
8895525fd86SBingbu Cao
8905525fd86SBingbu Cao ov5675->identified = true;
8915525fd86SBingbu Cao
8925525fd86SBingbu Cao return 0;
8935525fd86SBingbu Cao }
8945525fd86SBingbu Cao
ov5675_start_streaming(struct ov5675 * ov5675)895bf27502bSShawn Tu static int ov5675_start_streaming(struct ov5675 *ov5675)
896bf27502bSShawn Tu {
897bf27502bSShawn Tu struct i2c_client *client = v4l2_get_subdevdata(&ov5675->sd);
898bf27502bSShawn Tu const struct ov5675_reg_list *reg_list;
899bf27502bSShawn Tu int link_freq_index, ret;
900bf27502bSShawn Tu
9015525fd86SBingbu Cao ret = ov5675_identify_module(ov5675);
9025525fd86SBingbu Cao if (ret)
9035525fd86SBingbu Cao return ret;
9045525fd86SBingbu Cao
905bf27502bSShawn Tu link_freq_index = ov5675->cur_mode->link_freq_index;
906bf27502bSShawn Tu reg_list = &link_freq_configs[link_freq_index].reg_list;
907bf27502bSShawn Tu ret = ov5675_write_reg_list(ov5675, reg_list);
908bf27502bSShawn Tu if (ret) {
909bf27502bSShawn Tu dev_err(&client->dev, "failed to set plls");
910bf27502bSShawn Tu return ret;
911bf27502bSShawn Tu }
912bf27502bSShawn Tu
913bf27502bSShawn Tu reg_list = &ov5675->cur_mode->reg_list;
914bf27502bSShawn Tu ret = ov5675_write_reg_list(ov5675, reg_list);
915bf27502bSShawn Tu if (ret) {
916bf27502bSShawn Tu dev_err(&client->dev, "failed to set mode");
917bf27502bSShawn Tu return ret;
918bf27502bSShawn Tu }
919bf27502bSShawn Tu
920bf27502bSShawn Tu ret = __v4l2_ctrl_handler_setup(ov5675->sd.ctrl_handler);
921bf27502bSShawn Tu if (ret)
922bf27502bSShawn Tu return ret;
923bf27502bSShawn Tu
924bf27502bSShawn Tu ret = ov5675_write_reg(ov5675, OV5675_REG_MODE_SELECT,
925bf27502bSShawn Tu OV5675_REG_VALUE_08BIT, OV5675_MODE_STREAMING);
926bf27502bSShawn Tu if (ret) {
927bf27502bSShawn Tu dev_err(&client->dev, "failed to set stream");
928bf27502bSShawn Tu return ret;
929bf27502bSShawn Tu }
930bf27502bSShawn Tu
931bf27502bSShawn Tu return 0;
932bf27502bSShawn Tu }
933bf27502bSShawn Tu
ov5675_stop_streaming(struct ov5675 * ov5675)934bf27502bSShawn Tu static void ov5675_stop_streaming(struct ov5675 *ov5675)
935bf27502bSShawn Tu {
936bf27502bSShawn Tu struct i2c_client *client = v4l2_get_subdevdata(&ov5675->sd);
937bf27502bSShawn Tu
938bf27502bSShawn Tu if (ov5675_write_reg(ov5675, OV5675_REG_MODE_SELECT,
939bf27502bSShawn Tu OV5675_REG_VALUE_08BIT, OV5675_MODE_STANDBY))
940bf27502bSShawn Tu dev_err(&client->dev, "failed to set stream");
941bf27502bSShawn Tu }
942bf27502bSShawn Tu
ov5675_set_stream(struct v4l2_subdev * sd,int enable)943bf27502bSShawn Tu static int ov5675_set_stream(struct v4l2_subdev *sd, int enable)
944bf27502bSShawn Tu {
945bf27502bSShawn Tu struct ov5675 *ov5675 = to_ov5675(sd);
946bf27502bSShawn Tu struct i2c_client *client = v4l2_get_subdevdata(sd);
947bf27502bSShawn Tu int ret = 0;
948bf27502bSShawn Tu
949bf27502bSShawn Tu mutex_lock(&ov5675->mutex);
950bf27502bSShawn Tu if (enable) {
951f236bb24SMauro Carvalho Chehab ret = pm_runtime_resume_and_get(&client->dev);
952bf27502bSShawn Tu if (ret < 0) {
953bf27502bSShawn Tu mutex_unlock(&ov5675->mutex);
954bf27502bSShawn Tu return ret;
955bf27502bSShawn Tu }
956bf27502bSShawn Tu
957bf27502bSShawn Tu ret = ov5675_start_streaming(ov5675);
958bf27502bSShawn Tu if (ret) {
959bf27502bSShawn Tu enable = 0;
960bf27502bSShawn Tu ov5675_stop_streaming(ov5675);
961bf27502bSShawn Tu pm_runtime_put(&client->dev);
962bf27502bSShawn Tu }
963bf27502bSShawn Tu } else {
964bf27502bSShawn Tu ov5675_stop_streaming(ov5675);
965bf27502bSShawn Tu pm_runtime_put(&client->dev);
966bf27502bSShawn Tu }
967bf27502bSShawn Tu
968bf27502bSShawn Tu mutex_unlock(&ov5675->mutex);
969bf27502bSShawn Tu
970bf27502bSShawn Tu return ret;
971bf27502bSShawn Tu }
972bf27502bSShawn Tu
ov5675_power_off(struct device * dev)97349d9ad71SQuentin Schulz static int ov5675_power_off(struct device *dev)
97449d9ad71SQuentin Schulz {
97549d9ad71SQuentin Schulz /* 512 xvclk cycles after the last SCCB transation or MIPI frame end */
97649d9ad71SQuentin Schulz u32 delay_us = DIV_ROUND_UP(512, OV5675_XVCLK_19_2 / 1000 / 1000);
97749d9ad71SQuentin Schulz struct v4l2_subdev *sd = dev_get_drvdata(dev);
97849d9ad71SQuentin Schulz struct ov5675 *ov5675 = to_ov5675(sd);
97949d9ad71SQuentin Schulz
98049d9ad71SQuentin Schulz usleep_range(delay_us, delay_us * 2);
98149d9ad71SQuentin Schulz
98249d9ad71SQuentin Schulz clk_disable_unprepare(ov5675->xvclk);
98349d9ad71SQuentin Schulz gpiod_set_value_cansleep(ov5675->reset_gpio, 1);
98449d9ad71SQuentin Schulz regulator_bulk_disable(OV5675_NUM_SUPPLIES, ov5675->supplies);
98549d9ad71SQuentin Schulz
98649d9ad71SQuentin Schulz return 0;
98749d9ad71SQuentin Schulz }
98849d9ad71SQuentin Schulz
ov5675_power_on(struct device * dev)98949d9ad71SQuentin Schulz static int ov5675_power_on(struct device *dev)
99049d9ad71SQuentin Schulz {
99149d9ad71SQuentin Schulz u32 delay_us = DIV_ROUND_UP(8192, OV5675_XVCLK_19_2 / 1000 / 1000);
99249d9ad71SQuentin Schulz struct v4l2_subdev *sd = dev_get_drvdata(dev);
99349d9ad71SQuentin Schulz struct ov5675 *ov5675 = to_ov5675(sd);
99449d9ad71SQuentin Schulz int ret;
99549d9ad71SQuentin Schulz
99649d9ad71SQuentin Schulz ret = clk_prepare_enable(ov5675->xvclk);
99749d9ad71SQuentin Schulz if (ret < 0) {
99849d9ad71SQuentin Schulz dev_err(dev, "failed to enable xvclk: %d\n", ret);
99949d9ad71SQuentin Schulz return ret;
100049d9ad71SQuentin Schulz }
100149d9ad71SQuentin Schulz
100249d9ad71SQuentin Schulz gpiod_set_value_cansleep(ov5675->reset_gpio, 1);
100349d9ad71SQuentin Schulz
100449d9ad71SQuentin Schulz ret = regulator_bulk_enable(OV5675_NUM_SUPPLIES, ov5675->supplies);
100549d9ad71SQuentin Schulz if (ret) {
100649d9ad71SQuentin Schulz clk_disable_unprepare(ov5675->xvclk);
100749d9ad71SQuentin Schulz return ret;
100849d9ad71SQuentin Schulz }
100949d9ad71SQuentin Schulz
101049d9ad71SQuentin Schulz /* Reset pulse should be at least 2ms and reset gpio released only once
101149d9ad71SQuentin Schulz * regulators are stable.
101249d9ad71SQuentin Schulz */
101349d9ad71SQuentin Schulz usleep_range(2000, 2200);
101449d9ad71SQuentin Schulz
101549d9ad71SQuentin Schulz gpiod_set_value_cansleep(ov5675->reset_gpio, 0);
101649d9ad71SQuentin Schulz
101749d9ad71SQuentin Schulz /* 8192 xvclk cycles prior to the first SCCB transation */
101849d9ad71SQuentin Schulz usleep_range(delay_us, delay_us * 2);
101949d9ad71SQuentin Schulz
102049d9ad71SQuentin Schulz return 0;
102149d9ad71SQuentin Schulz }
102249d9ad71SQuentin Schulz
ov5675_set_format(struct v4l2_subdev * sd,struct v4l2_subdev_state * sd_state,struct v4l2_subdev_format * fmt)1023bf27502bSShawn Tu static int ov5675_set_format(struct v4l2_subdev *sd,
10240d346d2aSTomi Valkeinen struct v4l2_subdev_state *sd_state,
1025bf27502bSShawn Tu struct v4l2_subdev_format *fmt)
1026bf27502bSShawn Tu {
1027bf27502bSShawn Tu struct ov5675 *ov5675 = to_ov5675(sd);
1028bf27502bSShawn Tu const struct ov5675_mode *mode;
1029bf27502bSShawn Tu s32 vblank_def, h_blank;
1030bf27502bSShawn Tu
1031bf27502bSShawn Tu mode = v4l2_find_nearest_size(supported_modes,
1032bf27502bSShawn Tu ARRAY_SIZE(supported_modes), width,
1033bf27502bSShawn Tu height, fmt->format.width,
1034bf27502bSShawn Tu fmt->format.height);
1035bf27502bSShawn Tu
1036bf27502bSShawn Tu mutex_lock(&ov5675->mutex);
1037bf27502bSShawn Tu ov5675_update_pad_format(mode, &fmt->format);
1038bf27502bSShawn Tu if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
1039*bc0e8d91SSakari Ailus *v4l2_subdev_state_get_format(sd_state, fmt->pad) = fmt->format;
1040bf27502bSShawn Tu } else {
1041bf27502bSShawn Tu ov5675->cur_mode = mode;
1042bf27502bSShawn Tu __v4l2_ctrl_s_ctrl(ov5675->link_freq, mode->link_freq_index);
1043bf27502bSShawn Tu __v4l2_ctrl_s_ctrl_int64(ov5675->pixel_rate,
1044bf27502bSShawn Tu to_pixel_rate(mode->link_freq_index));
1045bf27502bSShawn Tu
1046bf27502bSShawn Tu /* Update limits and set FPS to default */
1047bf27502bSShawn Tu vblank_def = mode->vts_def - mode->height;
1048bf27502bSShawn Tu __v4l2_ctrl_modify_range(ov5675->vblank,
1049bf27502bSShawn Tu mode->vts_min - mode->height,
1050bf27502bSShawn Tu OV5675_VTS_MAX - mode->height, 1,
1051bf27502bSShawn Tu vblank_def);
1052bf27502bSShawn Tu __v4l2_ctrl_s_ctrl(ov5675->vblank, vblank_def);
1053bf27502bSShawn Tu h_blank = to_pixels_per_line(mode->hts, mode->link_freq_index) -
1054bf27502bSShawn Tu mode->width;
1055bf27502bSShawn Tu __v4l2_ctrl_modify_range(ov5675->hblank, h_blank, h_blank, 1,
1056bf27502bSShawn Tu h_blank);
1057bf27502bSShawn Tu }
1058bf27502bSShawn Tu
1059bf27502bSShawn Tu mutex_unlock(&ov5675->mutex);
1060bf27502bSShawn Tu
1061bf27502bSShawn Tu return 0;
1062bf27502bSShawn Tu }
1063bf27502bSShawn Tu
ov5675_get_format(struct v4l2_subdev * sd,struct v4l2_subdev_state * sd_state,struct v4l2_subdev_format * fmt)1064bf27502bSShawn Tu static int ov5675_get_format(struct v4l2_subdev *sd,
10650d346d2aSTomi Valkeinen struct v4l2_subdev_state *sd_state,
1066bf27502bSShawn Tu struct v4l2_subdev_format *fmt)
1067bf27502bSShawn Tu {
1068bf27502bSShawn Tu struct ov5675 *ov5675 = to_ov5675(sd);
1069bf27502bSShawn Tu
1070bf27502bSShawn Tu mutex_lock(&ov5675->mutex);
1071bf27502bSShawn Tu if (fmt->which == V4L2_SUBDEV_FORMAT_TRY)
1072*bc0e8d91SSakari Ailus fmt->format = *v4l2_subdev_state_get_format(sd_state,
1073bf27502bSShawn Tu fmt->pad);
1074bf27502bSShawn Tu else
1075bf27502bSShawn Tu ov5675_update_pad_format(ov5675->cur_mode, &fmt->format);
1076bf27502bSShawn Tu
1077bf27502bSShawn Tu mutex_unlock(&ov5675->mutex);
1078bf27502bSShawn Tu
1079bf27502bSShawn Tu return 0;
1080bf27502bSShawn Tu }
1081bf27502bSShawn Tu
ov5675_get_selection(struct v4l2_subdev * sd,struct v4l2_subdev_state * state,struct v4l2_subdev_selection * sel)1082221827eeSQuentin Schulz static int ov5675_get_selection(struct v4l2_subdev *sd,
1083221827eeSQuentin Schulz struct v4l2_subdev_state *state,
1084221827eeSQuentin Schulz struct v4l2_subdev_selection *sel)
1085221827eeSQuentin Schulz {
1086221827eeSQuentin Schulz if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE)
1087221827eeSQuentin Schulz return -EINVAL;
1088221827eeSQuentin Schulz
1089221827eeSQuentin Schulz switch (sel->target) {
1090221827eeSQuentin Schulz case V4L2_SEL_TGT_CROP_BOUNDS:
1091221827eeSQuentin Schulz sel->r.top = 0;
1092221827eeSQuentin Schulz sel->r.left = 0;
1093221827eeSQuentin Schulz sel->r.width = 2624;
1094221827eeSQuentin Schulz sel->r.height = 2000;
1095221827eeSQuentin Schulz return 0;
1096221827eeSQuentin Schulz case V4L2_SEL_TGT_CROP:
1097221827eeSQuentin Schulz case V4L2_SEL_TGT_CROP_DEFAULT:
1098221827eeSQuentin Schulz sel->r.top = 16;
1099221827eeSQuentin Schulz sel->r.left = 16;
1100221827eeSQuentin Schulz sel->r.width = 2592;
1101221827eeSQuentin Schulz sel->r.height = 1944;
1102221827eeSQuentin Schulz return 0;
1103221827eeSQuentin Schulz }
1104221827eeSQuentin Schulz return -EINVAL;
1105221827eeSQuentin Schulz }
1106221827eeSQuentin Schulz
ov5675_enum_mbus_code(struct v4l2_subdev * sd,struct v4l2_subdev_state * sd_state,struct v4l2_subdev_mbus_code_enum * code)1107bf27502bSShawn Tu static int ov5675_enum_mbus_code(struct v4l2_subdev *sd,
11080d346d2aSTomi Valkeinen struct v4l2_subdev_state *sd_state,
1109bf27502bSShawn Tu struct v4l2_subdev_mbus_code_enum *code)
1110bf27502bSShawn Tu {
1111bf27502bSShawn Tu if (code->index > 0)
1112bf27502bSShawn Tu return -EINVAL;
1113bf27502bSShawn Tu
1114bf27502bSShawn Tu code->code = MEDIA_BUS_FMT_SGRBG10_1X10;
1115bf27502bSShawn Tu
1116bf27502bSShawn Tu return 0;
1117bf27502bSShawn Tu }
1118bf27502bSShawn Tu
ov5675_enum_frame_size(struct v4l2_subdev * sd,struct v4l2_subdev_state * sd_state,struct v4l2_subdev_frame_size_enum * fse)1119bf27502bSShawn Tu static int ov5675_enum_frame_size(struct v4l2_subdev *sd,
11200d346d2aSTomi Valkeinen struct v4l2_subdev_state *sd_state,
1121bf27502bSShawn Tu struct v4l2_subdev_frame_size_enum *fse)
1122bf27502bSShawn Tu {
1123bf27502bSShawn Tu if (fse->index >= ARRAY_SIZE(supported_modes))
1124bf27502bSShawn Tu return -EINVAL;
1125bf27502bSShawn Tu
1126bf27502bSShawn Tu if (fse->code != MEDIA_BUS_FMT_SGRBG10_1X10)
1127bf27502bSShawn Tu return -EINVAL;
1128bf27502bSShawn Tu
1129bf27502bSShawn Tu fse->min_width = supported_modes[fse->index].width;
1130bf27502bSShawn Tu fse->max_width = fse->min_width;
1131bf27502bSShawn Tu fse->min_height = supported_modes[fse->index].height;
1132bf27502bSShawn Tu fse->max_height = fse->min_height;
1133bf27502bSShawn Tu
1134bf27502bSShawn Tu return 0;
1135bf27502bSShawn Tu }
1136bf27502bSShawn Tu
ov5675_open(struct v4l2_subdev * sd,struct v4l2_subdev_fh * fh)1137bf27502bSShawn Tu static int ov5675_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
1138bf27502bSShawn Tu {
1139bf27502bSShawn Tu struct ov5675 *ov5675 = to_ov5675(sd);
1140bf27502bSShawn Tu
1141bf27502bSShawn Tu mutex_lock(&ov5675->mutex);
1142bf27502bSShawn Tu ov5675_update_pad_format(&supported_modes[0],
1143*bc0e8d91SSakari Ailus v4l2_subdev_state_get_format(fh->state, 0));
1144bf27502bSShawn Tu mutex_unlock(&ov5675->mutex);
1145bf27502bSShawn Tu
1146bf27502bSShawn Tu return 0;
1147bf27502bSShawn Tu }
1148bf27502bSShawn Tu
1149bf27502bSShawn Tu static const struct v4l2_subdev_video_ops ov5675_video_ops = {
1150bf27502bSShawn Tu .s_stream = ov5675_set_stream,
1151bf27502bSShawn Tu };
1152bf27502bSShawn Tu
1153bf27502bSShawn Tu static const struct v4l2_subdev_pad_ops ov5675_pad_ops = {
1154bf27502bSShawn Tu .set_fmt = ov5675_set_format,
1155bf27502bSShawn Tu .get_fmt = ov5675_get_format,
1156221827eeSQuentin Schulz .get_selection = ov5675_get_selection,
1157bf27502bSShawn Tu .enum_mbus_code = ov5675_enum_mbus_code,
1158bf27502bSShawn Tu .enum_frame_size = ov5675_enum_frame_size,
1159bf27502bSShawn Tu };
1160bf27502bSShawn Tu
1161bf27502bSShawn Tu static const struct v4l2_subdev_ops ov5675_subdev_ops = {
1162bf27502bSShawn Tu .video = &ov5675_video_ops,
1163bf27502bSShawn Tu .pad = &ov5675_pad_ops,
1164bf27502bSShawn Tu };
1165bf27502bSShawn Tu
1166bf27502bSShawn Tu static const struct media_entity_operations ov5675_subdev_entity_ops = {
1167bf27502bSShawn Tu .link_validate = v4l2_subdev_link_validate,
1168bf27502bSShawn Tu };
1169bf27502bSShawn Tu
1170bf27502bSShawn Tu static const struct v4l2_subdev_internal_ops ov5675_internal_ops = {
1171bf27502bSShawn Tu .open = ov5675_open,
1172bf27502bSShawn Tu };
1173bf27502bSShawn Tu
ov5675_get_hwcfg(struct ov5675 * ov5675,struct device * dev)117449d9ad71SQuentin Schulz static int ov5675_get_hwcfg(struct ov5675 *ov5675, struct device *dev)
1175bf27502bSShawn Tu {
1176bf27502bSShawn Tu struct fwnode_handle *ep;
1177bf27502bSShawn Tu struct fwnode_handle *fwnode = dev_fwnode(dev);
1178bf27502bSShawn Tu struct v4l2_fwnode_endpoint bus_cfg = {
1179bf27502bSShawn Tu .bus_type = V4L2_MBUS_CSI2_DPHY
1180bf27502bSShawn Tu };
118149d9ad71SQuentin Schulz u32 xvclk_rate;
1182bf27502bSShawn Tu int ret;
1183bf27502bSShawn Tu unsigned int i, j;
1184bf27502bSShawn Tu
1185bf27502bSShawn Tu if (!fwnode)
1186bf27502bSShawn Tu return -ENXIO;
1187bf27502bSShawn Tu
118849d9ad71SQuentin Schulz ov5675->xvclk = devm_clk_get_optional(dev, NULL);
118949d9ad71SQuentin Schulz if (IS_ERR(ov5675->xvclk))
119049d9ad71SQuentin Schulz return dev_err_probe(dev, PTR_ERR(ov5675->xvclk),
119149d9ad71SQuentin Schulz "failed to get xvclk: %ld\n",
119249d9ad71SQuentin Schulz PTR_ERR(ov5675->xvclk));
119349d9ad71SQuentin Schulz
119449d9ad71SQuentin Schulz if (ov5675->xvclk) {
119549d9ad71SQuentin Schulz xvclk_rate = clk_get_rate(ov5675->xvclk);
119649d9ad71SQuentin Schulz } else {
119749d9ad71SQuentin Schulz ret = fwnode_property_read_u32(fwnode, "clock-frequency",
119849d9ad71SQuentin Schulz &xvclk_rate);
1199bf27502bSShawn Tu
1200bf27502bSShawn Tu if (ret) {
1201bf27502bSShawn Tu dev_err(dev, "can't get clock frequency");
1202bf27502bSShawn Tu return ret;
1203bf27502bSShawn Tu }
120449d9ad71SQuentin Schulz }
1205bf27502bSShawn Tu
120649d9ad71SQuentin Schulz if (xvclk_rate != OV5675_XVCLK_19_2) {
120749d9ad71SQuentin Schulz dev_err(dev, "external clock rate %u is unsupported",
120849d9ad71SQuentin Schulz xvclk_rate);
1209bf27502bSShawn Tu return -EINVAL;
1210bf27502bSShawn Tu }
1211bf27502bSShawn Tu
121249d9ad71SQuentin Schulz ov5675->reset_gpio = devm_gpiod_get_optional(dev, "reset",
121349d9ad71SQuentin Schulz GPIOD_OUT_HIGH);
121449d9ad71SQuentin Schulz if (IS_ERR(ov5675->reset_gpio)) {
121549d9ad71SQuentin Schulz ret = PTR_ERR(ov5675->reset_gpio);
121649d9ad71SQuentin Schulz dev_err(dev, "failed to get reset-gpios: %d\n", ret);
121749d9ad71SQuentin Schulz return ret;
121849d9ad71SQuentin Schulz }
121949d9ad71SQuentin Schulz
122049d9ad71SQuentin Schulz for (i = 0; i < OV5675_NUM_SUPPLIES; i++)
122149d9ad71SQuentin Schulz ov5675->supplies[i].supply = ov5675_supply_names[i];
122249d9ad71SQuentin Schulz
122349d9ad71SQuentin Schulz ret = devm_regulator_bulk_get(dev, OV5675_NUM_SUPPLIES,
122449d9ad71SQuentin Schulz ov5675->supplies);
122549d9ad71SQuentin Schulz if (ret)
122649d9ad71SQuentin Schulz return ret;
122749d9ad71SQuentin Schulz
1228bf27502bSShawn Tu ep = fwnode_graph_get_next_endpoint(fwnode, NULL);
1229bf27502bSShawn Tu if (!ep)
1230bf27502bSShawn Tu return -ENXIO;
1231bf27502bSShawn Tu
1232bf27502bSShawn Tu ret = v4l2_fwnode_endpoint_alloc_parse(ep, &bus_cfg);
1233bf27502bSShawn Tu fwnode_handle_put(ep);
1234bf27502bSShawn Tu if (ret)
1235bf27502bSShawn Tu return ret;
1236bf27502bSShawn Tu
1237bf27502bSShawn Tu if (bus_cfg.bus.mipi_csi2.num_data_lanes != OV5675_DATA_LANES) {
1238bf27502bSShawn Tu dev_err(dev, "number of CSI2 data lanes %d is not supported",
1239bf27502bSShawn Tu bus_cfg.bus.mipi_csi2.num_data_lanes);
1240bf27502bSShawn Tu ret = -EINVAL;
1241bf27502bSShawn Tu goto check_hwcfg_error;
1242bf27502bSShawn Tu }
1243bf27502bSShawn Tu
1244bf27502bSShawn Tu if (!bus_cfg.nr_of_link_frequencies) {
1245bf27502bSShawn Tu dev_err(dev, "no link frequencies defined");
1246bf27502bSShawn Tu ret = -EINVAL;
1247bf27502bSShawn Tu goto check_hwcfg_error;
1248bf27502bSShawn Tu }
1249bf27502bSShawn Tu
1250bf27502bSShawn Tu for (i = 0; i < ARRAY_SIZE(link_freq_menu_items); i++) {
1251bf27502bSShawn Tu for (j = 0; j < bus_cfg.nr_of_link_frequencies; j++) {
1252bf27502bSShawn Tu if (link_freq_menu_items[i] ==
1253bf27502bSShawn Tu bus_cfg.link_frequencies[j])
1254bf27502bSShawn Tu break;
1255bf27502bSShawn Tu }
1256bf27502bSShawn Tu
1257bf27502bSShawn Tu if (j == bus_cfg.nr_of_link_frequencies) {
1258bf27502bSShawn Tu dev_err(dev, "no link frequency %lld supported",
1259bf27502bSShawn Tu link_freq_menu_items[i]);
1260bf27502bSShawn Tu ret = -EINVAL;
1261bf27502bSShawn Tu goto check_hwcfg_error;
1262bf27502bSShawn Tu }
1263bf27502bSShawn Tu }
1264bf27502bSShawn Tu
1265bf27502bSShawn Tu check_hwcfg_error:
1266bf27502bSShawn Tu v4l2_fwnode_endpoint_free(&bus_cfg);
1267bf27502bSShawn Tu
1268bf27502bSShawn Tu return ret;
1269bf27502bSShawn Tu }
1270bf27502bSShawn Tu
ov5675_remove(struct i2c_client * client)1271ed5c2f5fSUwe Kleine-König static void ov5675_remove(struct i2c_client *client)
1272bf27502bSShawn Tu {
1273bf27502bSShawn Tu struct v4l2_subdev *sd = i2c_get_clientdata(client);
1274bf27502bSShawn Tu struct ov5675 *ov5675 = to_ov5675(sd);
1275bf27502bSShawn Tu
1276bf27502bSShawn Tu v4l2_async_unregister_subdev(sd);
1277bf27502bSShawn Tu media_entity_cleanup(&sd->entity);
1278bf27502bSShawn Tu v4l2_ctrl_handler_free(sd->ctrl_handler);
1279bf27502bSShawn Tu pm_runtime_disable(&client->dev);
1280bf27502bSShawn Tu mutex_destroy(&ov5675->mutex);
128149d9ad71SQuentin Schulz
128249d9ad71SQuentin Schulz if (!pm_runtime_status_suspended(&client->dev))
128349d9ad71SQuentin Schulz ov5675_power_off(&client->dev);
128449d9ad71SQuentin Schulz pm_runtime_set_suspended(&client->dev);
1285bf27502bSShawn Tu }
1286bf27502bSShawn Tu
ov5675_probe(struct i2c_client * client)1287bf27502bSShawn Tu static int ov5675_probe(struct i2c_client *client)
1288bf27502bSShawn Tu {
1289bf27502bSShawn Tu struct ov5675 *ov5675;
12905525fd86SBingbu Cao bool full_power;
1291bf27502bSShawn Tu int ret;
1292bf27502bSShawn Tu
1293bf27502bSShawn Tu ov5675 = devm_kzalloc(&client->dev, sizeof(*ov5675), GFP_KERNEL);
1294bf27502bSShawn Tu if (!ov5675)
1295bf27502bSShawn Tu return -ENOMEM;
1296bf27502bSShawn Tu
129749d9ad71SQuentin Schulz ret = ov5675_get_hwcfg(ov5675, &client->dev);
129849d9ad71SQuentin Schulz if (ret) {
129949d9ad71SQuentin Schulz dev_err(&client->dev, "failed to get HW configuration: %d",
130049d9ad71SQuentin Schulz ret);
130149d9ad71SQuentin Schulz return ret;
130249d9ad71SQuentin Schulz }
130349d9ad71SQuentin Schulz
1304bf27502bSShawn Tu v4l2_i2c_subdev_init(&ov5675->sd, client, &ov5675_subdev_ops);
13055525fd86SBingbu Cao
130649d9ad71SQuentin Schulz ret = ov5675_power_on(&client->dev);
130749d9ad71SQuentin Schulz if (ret) {
130849d9ad71SQuentin Schulz dev_err(&client->dev, "failed to power on: %d\n", ret);
130949d9ad71SQuentin Schulz return ret;
131049d9ad71SQuentin Schulz }
131149d9ad71SQuentin Schulz
13125525fd86SBingbu Cao full_power = acpi_dev_state_d0(&client->dev);
13135525fd86SBingbu Cao if (full_power) {
1314bf27502bSShawn Tu ret = ov5675_identify_module(ov5675);
1315bf27502bSShawn Tu if (ret) {
1316bf27502bSShawn Tu dev_err(&client->dev, "failed to find sensor: %d", ret);
131749d9ad71SQuentin Schulz goto probe_power_off;
1318bf27502bSShawn Tu }
13195525fd86SBingbu Cao }
1320bf27502bSShawn Tu
1321bf27502bSShawn Tu mutex_init(&ov5675->mutex);
1322bf27502bSShawn Tu ov5675->cur_mode = &supported_modes[0];
1323bf27502bSShawn Tu ret = ov5675_init_controls(ov5675);
1324bf27502bSShawn Tu if (ret) {
1325bf27502bSShawn Tu dev_err(&client->dev, "failed to init controls: %d", ret);
1326bf27502bSShawn Tu goto probe_error_v4l2_ctrl_handler_free;
1327bf27502bSShawn Tu }
1328bf27502bSShawn Tu
1329bf27502bSShawn Tu ov5675->sd.internal_ops = &ov5675_internal_ops;
1330bf27502bSShawn Tu ov5675->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
1331bf27502bSShawn Tu ov5675->sd.entity.ops = &ov5675_subdev_entity_ops;
1332bf27502bSShawn Tu ov5675->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
1333bf27502bSShawn Tu ov5675->pad.flags = MEDIA_PAD_FL_SOURCE;
1334bf27502bSShawn Tu ret = media_entity_pads_init(&ov5675->sd.entity, 1, &ov5675->pad);
1335bf27502bSShawn Tu if (ret) {
1336bf27502bSShawn Tu dev_err(&client->dev, "failed to init entity pads: %d", ret);
1337bf27502bSShawn Tu goto probe_error_v4l2_ctrl_handler_free;
1338bf27502bSShawn Tu }
1339bf27502bSShawn Tu
134015786f7bSSakari Ailus ret = v4l2_async_register_subdev_sensor(&ov5675->sd);
1341bf27502bSShawn Tu if (ret < 0) {
1342bf27502bSShawn Tu dev_err(&client->dev, "failed to register V4L2 subdev: %d",
1343bf27502bSShawn Tu ret);
1344bf27502bSShawn Tu goto probe_error_media_entity_cleanup;
1345bf27502bSShawn Tu }
1346bf27502bSShawn Tu
13475525fd86SBingbu Cao /* Set the device's state to active if it's in D0 state. */
13485525fd86SBingbu Cao if (full_power)
1349bf27502bSShawn Tu pm_runtime_set_active(&client->dev);
1350bf27502bSShawn Tu pm_runtime_enable(&client->dev);
1351bf27502bSShawn Tu pm_runtime_idle(&client->dev);
1352bf27502bSShawn Tu
1353bf27502bSShawn Tu return 0;
1354bf27502bSShawn Tu
1355bf27502bSShawn Tu probe_error_media_entity_cleanup:
1356bf27502bSShawn Tu media_entity_cleanup(&ov5675->sd.entity);
1357bf27502bSShawn Tu
1358bf27502bSShawn Tu probe_error_v4l2_ctrl_handler_free:
1359bf27502bSShawn Tu v4l2_ctrl_handler_free(ov5675->sd.ctrl_handler);
1360bf27502bSShawn Tu mutex_destroy(&ov5675->mutex);
136149d9ad71SQuentin Schulz probe_power_off:
136249d9ad71SQuentin Schulz ov5675_power_off(&client->dev);
1363bf27502bSShawn Tu
1364bf27502bSShawn Tu return ret;
1365bf27502bSShawn Tu }
1366bf27502bSShawn Tu
1367bf27502bSShawn Tu static const struct dev_pm_ops ov5675_pm_ops = {
136849d9ad71SQuentin Schulz SET_RUNTIME_PM_OPS(ov5675_power_off, ov5675_power_on, NULL)
1369bf27502bSShawn Tu };
1370bf27502bSShawn Tu
1371bf27502bSShawn Tu #ifdef CONFIG_ACPI
1372bf27502bSShawn Tu static const struct acpi_device_id ov5675_acpi_ids[] = {
1373bf27502bSShawn Tu {"OVTI5675"},
1374bf27502bSShawn Tu {}
1375bf27502bSShawn Tu };
1376bf27502bSShawn Tu
1377bf27502bSShawn Tu MODULE_DEVICE_TABLE(acpi, ov5675_acpi_ids);
1378bf27502bSShawn Tu #endif
1379bf27502bSShawn Tu
138049d9ad71SQuentin Schulz static const struct of_device_id ov5675_of_match[] = {
138149d9ad71SQuentin Schulz { .compatible = "ovti,ov5675", },
138249d9ad71SQuentin Schulz { /* sentinel */ },
138349d9ad71SQuentin Schulz };
138449d9ad71SQuentin Schulz MODULE_DEVICE_TABLE(of, ov5675_of_match);
138549d9ad71SQuentin Schulz
1386bf27502bSShawn Tu static struct i2c_driver ov5675_i2c_driver = {
1387bf27502bSShawn Tu .driver = {
1388bf27502bSShawn Tu .name = "ov5675",
1389bf27502bSShawn Tu .pm = &ov5675_pm_ops,
1390bf27502bSShawn Tu .acpi_match_table = ACPI_PTR(ov5675_acpi_ids),
139149d9ad71SQuentin Schulz .of_match_table = ov5675_of_match,
1392bf27502bSShawn Tu },
1393aaeb31c0SUwe Kleine-König .probe = ov5675_probe,
1394bf27502bSShawn Tu .remove = ov5675_remove,
13955525fd86SBingbu Cao .flags = I2C_DRV_ACPI_WAIVE_D0_PROBE,
1396bf27502bSShawn Tu };
1397bf27502bSShawn Tu
1398bf27502bSShawn Tu module_i2c_driver(ov5675_i2c_driver);
1399bf27502bSShawn Tu
14004106cd72SSakari Ailus MODULE_AUTHOR("Shawn Tu");
1401bf27502bSShawn Tu MODULE_DESCRIPTION("OmniVision OV5675 sensor driver");
1402bf27502bSShawn Tu MODULE_LICENSE("GPL v2");
1403