1 | // SPDX-License-Identifier: GPL-2.0 |
2 | // Copyright (c) 2020 Intel Corporation. |
3 | |
4 | #include <asm/unaligned.h> |
5 | #include <linux/acpi.h> |
6 | #include <linux/delay.h> |
7 | #include <linux/i2c.h> |
8 | #include <linux/module.h> |
9 | #include <linux/pm_runtime.h> |
10 | #include <media/v4l2-ctrls.h> |
11 | #include <media/v4l2-device.h> |
12 | #include <media/v4l2-fwnode.h> |
13 | |
14 | #define OV9734_LINK_FREQ_180MHZ 180000000ULL |
15 | #define OV9734_SCLK 36000000LL |
16 | #define OV9734_MCLK 19200000 |
17 | /* ov9734 only support 1-lane mipi output */ |
18 | #define OV9734_DATA_LANES 1 |
19 | #define OV9734_RGB_DEPTH 10 |
20 | |
21 | #define OV9734_REG_CHIP_ID 0x300a |
22 | #define OV9734_CHIP_ID 0x9734 |
23 | |
24 | #define OV9734_REG_MODE_SELECT 0x0100 |
25 | #define OV9734_MODE_STANDBY 0x00 |
26 | #define OV9734_MODE_STREAMING 0x01 |
27 | |
28 | /* vertical-timings from sensor */ |
29 | #define OV9734_REG_VTS 0x380e |
30 | #define OV9734_VTS_30FPS 0x0322 |
31 | #define OV9734_VTS_30FPS_MIN 0x0322 |
32 | #define OV9734_VTS_MAX 0x7fff |
33 | |
34 | /* horizontal-timings from sensor */ |
35 | #define OV9734_REG_HTS 0x380c |
36 | |
37 | /* Exposure controls from sensor */ |
38 | #define OV9734_REG_EXPOSURE 0x3500 |
39 | #define OV9734_EXPOSURE_MIN 4 |
40 | #define OV9734_EXPOSURE_MAX_MARGIN 4 |
41 | #define OV9734_EXPOSURE_STEP 1 |
42 | |
43 | /* Analog gain controls from sensor */ |
44 | #define OV9734_REG_ANALOG_GAIN 0x350a |
45 | #define OV9734_ANAL_GAIN_MIN 16 |
46 | #define OV9734_ANAL_GAIN_MAX 248 |
47 | #define OV9734_ANAL_GAIN_STEP 1 |
48 | |
49 | /* Digital gain controls from sensor */ |
50 | #define OV9734_REG_MWB_R_GAIN 0x5180 |
51 | #define OV9734_REG_MWB_G_GAIN 0x5182 |
52 | #define OV9734_REG_MWB_B_GAIN 0x5184 |
53 | #define OV9734_DGTL_GAIN_MIN 256 |
54 | #define OV9734_DGTL_GAIN_MAX 1023 |
55 | #define OV9734_DGTL_GAIN_STEP 1 |
56 | #define OV9734_DGTL_GAIN_DEFAULT 256 |
57 | |
58 | /* Test Pattern Control */ |
59 | #define OV9734_REG_TEST_PATTERN 0x5080 |
60 | #define OV9734_TEST_PATTERN_ENABLE BIT(7) |
61 | #define OV9734_TEST_PATTERN_BAR_SHIFT 2 |
62 | |
63 | /* Group Access */ |
64 | #define OV9734_REG_GROUP_ACCESS 0x3208 |
65 | #define OV9734_GROUP_HOLD_START 0x0 |
66 | #define OV9734_GROUP_HOLD_END 0x10 |
67 | #define OV9734_GROUP_HOLD_LAUNCH 0xa0 |
68 | |
69 | enum { |
70 | OV9734_LINK_FREQ_180MHZ_INDEX, |
71 | }; |
72 | |
73 | struct ov9734_reg { |
74 | u16 address; |
75 | u8 val; |
76 | }; |
77 | |
78 | struct ov9734_reg_list { |
79 | u32 num_of_regs; |
80 | const struct ov9734_reg *regs; |
81 | }; |
82 | |
83 | struct ov9734_link_freq_config { |
84 | const struct ov9734_reg_list reg_list; |
85 | }; |
86 | |
87 | struct ov9734_mode { |
88 | /* Frame width in pixels */ |
89 | u32 width; |
90 | |
91 | /* Frame height in pixels */ |
92 | u32 height; |
93 | |
94 | /* Horizontal timining size */ |
95 | u32 hts; |
96 | |
97 | /* Default vertical timining size */ |
98 | u32 vts_def; |
99 | |
100 | /* Min vertical timining size */ |
101 | u32 vts_min; |
102 | |
103 | /* Link frequency needed for this resolution */ |
104 | u32 link_freq_index; |
105 | |
106 | /* Sensor register settings for this resolution */ |
107 | const struct ov9734_reg_list reg_list; |
108 | }; |
109 | |
110 | static const struct ov9734_reg mipi_data_rate_360mbps[] = { |
111 | {0x3030, 0x19}, |
112 | {0x3080, 0x02}, |
113 | {0x3081, 0x4b}, |
114 | {0x3082, 0x04}, |
115 | {0x3083, 0x00}, |
116 | {0x3084, 0x02}, |
117 | {0x3085, 0x01}, |
118 | {0x3086, 0x01}, |
119 | {0x3089, 0x01}, |
120 | {0x308a, 0x00}, |
121 | {0x301e, 0x15}, |
122 | {0x3103, 0x01}, |
123 | }; |
124 | |
125 | static const struct ov9734_reg mode_1296x734_regs[] = { |
126 | {0x3001, 0x00}, |
127 | {0x3002, 0x00}, |
128 | {0x3007, 0x00}, |
129 | {0x3010, 0x00}, |
130 | {0x3011, 0x08}, |
131 | {0x3014, 0x22}, |
132 | {0x3600, 0x55}, |
133 | {0x3601, 0x02}, |
134 | {0x3605, 0x22}, |
135 | {0x3611, 0xe7}, |
136 | {0x3654, 0x10}, |
137 | {0x3655, 0x77}, |
138 | {0x3656, 0x77}, |
139 | {0x3657, 0x07}, |
140 | {0x3658, 0x22}, |
141 | {0x3659, 0x22}, |
142 | {0x365a, 0x02}, |
143 | {0x3784, 0x05}, |
144 | {0x3785, 0x55}, |
145 | {0x37c0, 0x07}, |
146 | {0x3800, 0x00}, |
147 | {0x3801, 0x04}, |
148 | {0x3802, 0x00}, |
149 | {0x3803, 0x04}, |
150 | {0x3804, 0x05}, |
151 | {0x3805, 0x0b}, |
152 | {0x3806, 0x02}, |
153 | {0x3807, 0xdb}, |
154 | {0x3808, 0x05}, |
155 | {0x3809, 0x00}, |
156 | {0x380a, 0x02}, |
157 | {0x380b, 0xd0}, |
158 | {0x380c, 0x05}, |
159 | {0x380d, 0xc6}, |
160 | {0x380e, 0x03}, |
161 | {0x380f, 0x22}, |
162 | {0x3810, 0x00}, |
163 | {0x3811, 0x04}, |
164 | {0x3812, 0x00}, |
165 | {0x3813, 0x04}, |
166 | {0x3816, 0x00}, |
167 | {0x3817, 0x00}, |
168 | {0x3818, 0x00}, |
169 | {0x3819, 0x04}, |
170 | {0x3820, 0x18}, |
171 | {0x3821, 0x00}, |
172 | {0x382c, 0x06}, |
173 | {0x3500, 0x00}, |
174 | {0x3501, 0x31}, |
175 | {0x3502, 0x00}, |
176 | {0x3503, 0x03}, |
177 | {0x3504, 0x00}, |
178 | {0x3505, 0x00}, |
179 | {0x3509, 0x10}, |
180 | {0x350a, 0x00}, |
181 | {0x350b, 0x40}, |
182 | {0x3d00, 0x00}, |
183 | {0x3d01, 0x00}, |
184 | {0x3d02, 0x00}, |
185 | {0x3d03, 0x00}, |
186 | {0x3d04, 0x00}, |
187 | {0x3d05, 0x00}, |
188 | {0x3d06, 0x00}, |
189 | {0x3d07, 0x00}, |
190 | {0x3d08, 0x00}, |
191 | {0x3d09, 0x00}, |
192 | {0x3d0a, 0x00}, |
193 | {0x3d0b, 0x00}, |
194 | {0x3d0c, 0x00}, |
195 | {0x3d0d, 0x00}, |
196 | {0x3d0e, 0x00}, |
197 | {0x3d0f, 0x00}, |
198 | {0x3d80, 0x00}, |
199 | {0x3d81, 0x00}, |
200 | {0x3d82, 0x38}, |
201 | {0x3d83, 0xa4}, |
202 | {0x3d84, 0x00}, |
203 | {0x3d85, 0x00}, |
204 | {0x3d86, 0x1f}, |
205 | {0x3d87, 0x03}, |
206 | {0x3d8b, 0x00}, |
207 | {0x3d8f, 0x00}, |
208 | {0x4001, 0xe0}, |
209 | {0x4009, 0x0b}, |
210 | {0x4300, 0x03}, |
211 | {0x4301, 0xff}, |
212 | {0x4304, 0x00}, |
213 | {0x4305, 0x00}, |
214 | {0x4309, 0x00}, |
215 | {0x4600, 0x00}, |
216 | {0x4601, 0x80}, |
217 | {0x4800, 0x00}, |
218 | {0x4805, 0x00}, |
219 | {0x4821, 0x50}, |
220 | {0x4823, 0x50}, |
221 | {0x4837, 0x2d}, |
222 | {0x4a00, 0x00}, |
223 | {0x4f00, 0x80}, |
224 | {0x4f01, 0x10}, |
225 | {0x4f02, 0x00}, |
226 | {0x4f03, 0x00}, |
227 | {0x4f04, 0x00}, |
228 | {0x4f05, 0x00}, |
229 | {0x4f06, 0x00}, |
230 | {0x4f07, 0x00}, |
231 | {0x4f08, 0x00}, |
232 | {0x4f09, 0x00}, |
233 | {0x5000, 0x2f}, |
234 | {0x500c, 0x00}, |
235 | {0x500d, 0x00}, |
236 | {0x500e, 0x00}, |
237 | {0x500f, 0x00}, |
238 | {0x5010, 0x00}, |
239 | {0x5011, 0x00}, |
240 | {0x5012, 0x00}, |
241 | {0x5013, 0x00}, |
242 | {0x5014, 0x00}, |
243 | {0x5015, 0x00}, |
244 | {0x5016, 0x00}, |
245 | {0x5017, 0x00}, |
246 | {0x5080, 0x00}, |
247 | {0x5180, 0x01}, |
248 | {0x5181, 0x00}, |
249 | {0x5182, 0x01}, |
250 | {0x5183, 0x00}, |
251 | {0x5184, 0x01}, |
252 | {0x5185, 0x00}, |
253 | {0x5708, 0x06}, |
254 | {0x380f, 0x2a}, |
255 | {0x5780, 0x3e}, |
256 | {0x5781, 0x0f}, |
257 | {0x5782, 0x44}, |
258 | {0x5783, 0x02}, |
259 | {0x5784, 0x01}, |
260 | {0x5785, 0x01}, |
261 | {0x5786, 0x00}, |
262 | {0x5787, 0x04}, |
263 | {0x5788, 0x02}, |
264 | {0x5789, 0x0f}, |
265 | {0x578a, 0xfd}, |
266 | {0x578b, 0xf5}, |
267 | {0x578c, 0xf5}, |
268 | {0x578d, 0x03}, |
269 | {0x578e, 0x08}, |
270 | {0x578f, 0x0c}, |
271 | {0x5790, 0x08}, |
272 | {0x5791, 0x04}, |
273 | {0x5792, 0x00}, |
274 | {0x5793, 0x52}, |
275 | {0x5794, 0xa3}, |
276 | {0x5000, 0x3f}, |
277 | {0x3801, 0x00}, |
278 | {0x3803, 0x00}, |
279 | {0x3805, 0x0f}, |
280 | {0x3807, 0xdf}, |
281 | {0x3809, 0x10}, |
282 | {0x380b, 0xde}, |
283 | {0x3811, 0x00}, |
284 | {0x3813, 0x01}, |
285 | }; |
286 | |
287 | static const char * const [] = { |
288 | "Disabled" , |
289 | "Standard Color Bar" , |
290 | "Top-Bottom Darker Color Bar" , |
291 | "Right-Left Darker Color Bar" , |
292 | "Bottom-Top Darker Color Bar" , |
293 | }; |
294 | |
295 | static const s64 [] = { |
296 | OV9734_LINK_FREQ_180MHZ, |
297 | }; |
298 | |
299 | static const struct ov9734_link_freq_config link_freq_configs[] = { |
300 | [OV9734_LINK_FREQ_180MHZ_INDEX] = { |
301 | .reg_list = { |
302 | .num_of_regs = ARRAY_SIZE(mipi_data_rate_360mbps), |
303 | .regs = mipi_data_rate_360mbps, |
304 | } |
305 | }, |
306 | }; |
307 | |
308 | static const struct ov9734_mode supported_modes[] = { |
309 | { |
310 | .width = 1296, |
311 | .height = 734, |
312 | .hts = 0x5c6, |
313 | .vts_def = OV9734_VTS_30FPS, |
314 | .vts_min = OV9734_VTS_30FPS_MIN, |
315 | .reg_list = { |
316 | .num_of_regs = ARRAY_SIZE(mode_1296x734_regs), |
317 | .regs = mode_1296x734_regs, |
318 | }, |
319 | .link_freq_index = OV9734_LINK_FREQ_180MHZ_INDEX, |
320 | }, |
321 | }; |
322 | |
323 | struct ov9734 { |
324 | struct v4l2_subdev sd; |
325 | struct media_pad pad; |
326 | struct v4l2_ctrl_handler ctrl_handler; |
327 | |
328 | /* V4L2 Controls */ |
329 | struct v4l2_ctrl *link_freq; |
330 | struct v4l2_ctrl *pixel_rate; |
331 | struct v4l2_ctrl *vblank; |
332 | struct v4l2_ctrl *hblank; |
333 | struct v4l2_ctrl *exposure; |
334 | |
335 | /* Current mode */ |
336 | const struct ov9734_mode *cur_mode; |
337 | |
338 | /* To serialize asynchronus callbacks */ |
339 | struct mutex mutex; |
340 | }; |
341 | |
342 | static inline struct ov9734 *to_ov9734(struct v4l2_subdev *subdev) |
343 | { |
344 | return container_of(subdev, struct ov9734, sd); |
345 | } |
346 | |
347 | static u64 to_pixel_rate(u32 f_index) |
348 | { |
349 | u64 pixel_rate = link_freq_menu_items[f_index] * 2 * OV9734_DATA_LANES; |
350 | |
351 | do_div(pixel_rate, OV9734_RGB_DEPTH); |
352 | |
353 | return pixel_rate; |
354 | } |
355 | |
356 | static u64 to_pixels_per_line(u32 hts, u32 f_index) |
357 | { |
358 | u64 ppl = hts * to_pixel_rate(f_index); |
359 | |
360 | do_div(ppl, OV9734_SCLK); |
361 | |
362 | return ppl; |
363 | } |
364 | |
365 | static int ov9734_read_reg(struct ov9734 *ov9734, u16 reg, u16 len, u32 *val) |
366 | { |
367 | struct i2c_client *client = v4l2_get_subdevdata(sd: &ov9734->sd); |
368 | struct i2c_msg msgs[2]; |
369 | u8 addr_buf[2]; |
370 | u8 data_buf[4] = {0}; |
371 | int ret; |
372 | |
373 | if (len > sizeof(data_buf)) |
374 | return -EINVAL; |
375 | |
376 | put_unaligned_be16(val: reg, p: addr_buf); |
377 | msgs[0].addr = client->addr; |
378 | msgs[0].flags = 0; |
379 | msgs[0].len = sizeof(addr_buf); |
380 | msgs[0].buf = addr_buf; |
381 | msgs[1].addr = client->addr; |
382 | msgs[1].flags = I2C_M_RD; |
383 | msgs[1].len = len; |
384 | msgs[1].buf = &data_buf[sizeof(data_buf) - len]; |
385 | |
386 | ret = i2c_transfer(adap: client->adapter, msgs, ARRAY_SIZE(msgs)); |
387 | if (ret != ARRAY_SIZE(msgs)) |
388 | return ret < 0 ? ret : -EIO; |
389 | |
390 | *val = get_unaligned_be32(p: data_buf); |
391 | |
392 | return 0; |
393 | } |
394 | |
395 | static int ov9734_write_reg(struct ov9734 *ov9734, u16 reg, u16 len, u32 val) |
396 | { |
397 | struct i2c_client *client = v4l2_get_subdevdata(sd: &ov9734->sd); |
398 | u8 buf[6]; |
399 | int ret = 0; |
400 | |
401 | if (len > 4) |
402 | return -EINVAL; |
403 | |
404 | put_unaligned_be16(val: reg, p: buf); |
405 | put_unaligned_be32(val: val << 8 * (4 - len), p: buf + 2); |
406 | |
407 | ret = i2c_master_send(client, buf, count: len + 2); |
408 | if (ret != len + 2) |
409 | return ret < 0 ? ret : -EIO; |
410 | |
411 | return 0; |
412 | } |
413 | |
414 | static int ov9734_write_reg_list(struct ov9734 *ov9734, |
415 | const struct ov9734_reg_list *r_list) |
416 | { |
417 | struct i2c_client *client = v4l2_get_subdevdata(sd: &ov9734->sd); |
418 | unsigned int i; |
419 | int ret; |
420 | |
421 | for (i = 0; i < r_list->num_of_regs; i++) { |
422 | ret = ov9734_write_reg(ov9734, reg: r_list->regs[i].address, len: 1, |
423 | val: r_list->regs[i].val); |
424 | if (ret) { |
425 | dev_err_ratelimited(&client->dev, |
426 | "write reg 0x%4.4x return err = %d" , |
427 | r_list->regs[i].address, ret); |
428 | return ret; |
429 | } |
430 | } |
431 | |
432 | return 0; |
433 | } |
434 | |
435 | static int ov9734_update_digital_gain(struct ov9734 *ov9734, u32 d_gain) |
436 | { |
437 | int ret; |
438 | |
439 | ret = ov9734_write_reg(ov9734, OV9734_REG_GROUP_ACCESS, len: 1, |
440 | OV9734_GROUP_HOLD_START); |
441 | if (ret) |
442 | return ret; |
443 | |
444 | ret = ov9734_write_reg(ov9734, OV9734_REG_MWB_R_GAIN, len: 2, val: d_gain); |
445 | if (ret) |
446 | return ret; |
447 | |
448 | ret = ov9734_write_reg(ov9734, OV9734_REG_MWB_G_GAIN, len: 2, val: d_gain); |
449 | if (ret) |
450 | return ret; |
451 | |
452 | ret = ov9734_write_reg(ov9734, OV9734_REG_MWB_B_GAIN, len: 2, val: d_gain); |
453 | if (ret) |
454 | return ret; |
455 | |
456 | ret = ov9734_write_reg(ov9734, OV9734_REG_GROUP_ACCESS, len: 1, |
457 | OV9734_GROUP_HOLD_END); |
458 | if (ret) |
459 | return ret; |
460 | |
461 | ret = ov9734_write_reg(ov9734, OV9734_REG_GROUP_ACCESS, len: 1, |
462 | OV9734_GROUP_HOLD_LAUNCH); |
463 | return ret; |
464 | } |
465 | |
466 | static int ov9734_test_pattern(struct ov9734 *ov9734, u32 pattern) |
467 | { |
468 | if (pattern) |
469 | pattern = (pattern - 1) << OV9734_TEST_PATTERN_BAR_SHIFT | |
470 | OV9734_TEST_PATTERN_ENABLE; |
471 | |
472 | return ov9734_write_reg(ov9734, OV9734_REG_TEST_PATTERN, len: 1, val: pattern); |
473 | } |
474 | |
475 | static int ov9734_set_ctrl(struct v4l2_ctrl *ctrl) |
476 | { |
477 | struct ov9734 *ov9734 = container_of(ctrl->handler, |
478 | struct ov9734, ctrl_handler); |
479 | struct i2c_client *client = v4l2_get_subdevdata(sd: &ov9734->sd); |
480 | s64 exposure_max; |
481 | int ret = 0; |
482 | |
483 | /* Propagate change of current control to all related controls */ |
484 | if (ctrl->id == V4L2_CID_VBLANK) { |
485 | /* Update max exposure while meeting expected vblanking */ |
486 | exposure_max = ov9734->cur_mode->height + ctrl->val - |
487 | OV9734_EXPOSURE_MAX_MARGIN; |
488 | __v4l2_ctrl_modify_range(ctrl: ov9734->exposure, |
489 | min: ov9734->exposure->minimum, |
490 | max: exposure_max, step: ov9734->exposure->step, |
491 | def: exposure_max); |
492 | } |
493 | |
494 | /* V4L2 controls values will be applied only when power is already up */ |
495 | if (!pm_runtime_get_if_in_use(dev: &client->dev)) |
496 | return 0; |
497 | |
498 | switch (ctrl->id) { |
499 | case V4L2_CID_ANALOGUE_GAIN: |
500 | ret = ov9734_write_reg(ov9734, OV9734_REG_ANALOG_GAIN, |
501 | len: 2, val: ctrl->val); |
502 | break; |
503 | |
504 | case V4L2_CID_DIGITAL_GAIN: |
505 | ret = ov9734_update_digital_gain(ov9734, d_gain: ctrl->val); |
506 | break; |
507 | |
508 | case V4L2_CID_EXPOSURE: |
509 | /* 4 least significant bits of expsoure are fractional part */ |
510 | ret = ov9734_write_reg(ov9734, OV9734_REG_EXPOSURE, |
511 | len: 3, val: ctrl->val << 4); |
512 | break; |
513 | |
514 | case V4L2_CID_VBLANK: |
515 | ret = ov9734_write_reg(ov9734, OV9734_REG_VTS, len: 2, |
516 | val: ov9734->cur_mode->height + ctrl->val); |
517 | break; |
518 | |
519 | case V4L2_CID_TEST_PATTERN: |
520 | ret = ov9734_test_pattern(ov9734, pattern: ctrl->val); |
521 | break; |
522 | |
523 | default: |
524 | ret = -EINVAL; |
525 | break; |
526 | } |
527 | |
528 | pm_runtime_put(dev: &client->dev); |
529 | |
530 | return ret; |
531 | } |
532 | |
533 | static const struct v4l2_ctrl_ops ov9734_ctrl_ops = { |
534 | .s_ctrl = ov9734_set_ctrl, |
535 | }; |
536 | |
537 | static int ov9734_init_controls(struct ov9734 *ov9734) |
538 | { |
539 | struct v4l2_ctrl_handler *ctrl_hdlr; |
540 | const struct ov9734_mode *cur_mode; |
541 | s64 exposure_max, h_blank, pixel_rate; |
542 | u32 vblank_min, vblank_max, vblank_default; |
543 | int ret, size; |
544 | |
545 | ctrl_hdlr = &ov9734->ctrl_handler; |
546 | ret = v4l2_ctrl_handler_init(ctrl_hdlr, 8); |
547 | if (ret) |
548 | return ret; |
549 | |
550 | ctrl_hdlr->lock = &ov9734->mutex; |
551 | cur_mode = ov9734->cur_mode; |
552 | size = ARRAY_SIZE(link_freq_menu_items); |
553 | ov9734->link_freq = v4l2_ctrl_new_int_menu(hdl: ctrl_hdlr, ops: &ov9734_ctrl_ops, |
554 | V4L2_CID_LINK_FREQ, |
555 | max: size - 1, def: 0, |
556 | qmenu_int: link_freq_menu_items); |
557 | if (ov9734->link_freq) |
558 | ov9734->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY; |
559 | |
560 | pixel_rate = to_pixel_rate(f_index: OV9734_LINK_FREQ_180MHZ_INDEX); |
561 | ov9734->pixel_rate = v4l2_ctrl_new_std(hdl: ctrl_hdlr, ops: &ov9734_ctrl_ops, |
562 | V4L2_CID_PIXEL_RATE, min: 0, |
563 | max: pixel_rate, step: 1, def: pixel_rate); |
564 | vblank_min = cur_mode->vts_min - cur_mode->height; |
565 | vblank_max = OV9734_VTS_MAX - cur_mode->height; |
566 | vblank_default = cur_mode->vts_def - cur_mode->height; |
567 | ov9734->vblank = v4l2_ctrl_new_std(hdl: ctrl_hdlr, ops: &ov9734_ctrl_ops, |
568 | V4L2_CID_VBLANK, min: vblank_min, |
569 | max: vblank_max, step: 1, def: vblank_default); |
570 | h_blank = to_pixels_per_line(hts: cur_mode->hts, f_index: cur_mode->link_freq_index); |
571 | h_blank -= cur_mode->width; |
572 | ov9734->hblank = v4l2_ctrl_new_std(hdl: ctrl_hdlr, ops: &ov9734_ctrl_ops, |
573 | V4L2_CID_HBLANK, min: h_blank, max: h_blank, step: 1, |
574 | def: h_blank); |
575 | if (ov9734->hblank) |
576 | ov9734->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY; |
577 | |
578 | v4l2_ctrl_new_std(hdl: ctrl_hdlr, ops: &ov9734_ctrl_ops, V4L2_CID_ANALOGUE_GAIN, |
579 | OV9734_ANAL_GAIN_MIN, OV9734_ANAL_GAIN_MAX, |
580 | OV9734_ANAL_GAIN_STEP, OV9734_ANAL_GAIN_MIN); |
581 | v4l2_ctrl_new_std(hdl: ctrl_hdlr, ops: &ov9734_ctrl_ops, V4L2_CID_DIGITAL_GAIN, |
582 | OV9734_DGTL_GAIN_MIN, OV9734_DGTL_GAIN_MAX, |
583 | OV9734_DGTL_GAIN_STEP, OV9734_DGTL_GAIN_DEFAULT); |
584 | exposure_max = ov9734->cur_mode->vts_def - OV9734_EXPOSURE_MAX_MARGIN; |
585 | ov9734->exposure = v4l2_ctrl_new_std(hdl: ctrl_hdlr, ops: &ov9734_ctrl_ops, |
586 | V4L2_CID_EXPOSURE, |
587 | OV9734_EXPOSURE_MIN, max: exposure_max, |
588 | OV9734_EXPOSURE_STEP, |
589 | def: exposure_max); |
590 | v4l2_ctrl_new_std_menu_items(hdl: ctrl_hdlr, ops: &ov9734_ctrl_ops, |
591 | V4L2_CID_TEST_PATTERN, |
592 | ARRAY_SIZE(ov9734_test_pattern_menu) - 1, |
593 | mask: 0, def: 0, qmenu: ov9734_test_pattern_menu); |
594 | if (ctrl_hdlr->error) |
595 | return ctrl_hdlr->error; |
596 | |
597 | ov9734->sd.ctrl_handler = ctrl_hdlr; |
598 | |
599 | return 0; |
600 | } |
601 | |
602 | static void ov9734_update_pad_format(const struct ov9734_mode *mode, |
603 | struct v4l2_mbus_framefmt *fmt) |
604 | { |
605 | fmt->width = mode->width; |
606 | fmt->height = mode->height; |
607 | fmt->code = MEDIA_BUS_FMT_SGRBG10_1X10; |
608 | fmt->field = V4L2_FIELD_NONE; |
609 | } |
610 | |
611 | static int ov9734_start_streaming(struct ov9734 *ov9734) |
612 | { |
613 | struct i2c_client *client = v4l2_get_subdevdata(sd: &ov9734->sd); |
614 | const struct ov9734_reg_list *reg_list; |
615 | int link_freq_index, ret; |
616 | |
617 | link_freq_index = ov9734->cur_mode->link_freq_index; |
618 | reg_list = &link_freq_configs[link_freq_index].reg_list; |
619 | ret = ov9734_write_reg_list(ov9734, r_list: reg_list); |
620 | if (ret) { |
621 | dev_err(&client->dev, "failed to set plls" ); |
622 | return ret; |
623 | } |
624 | |
625 | reg_list = &ov9734->cur_mode->reg_list; |
626 | ret = ov9734_write_reg_list(ov9734, r_list: reg_list); |
627 | if (ret) { |
628 | dev_err(&client->dev, "failed to set mode" ); |
629 | return ret; |
630 | } |
631 | |
632 | ret = __v4l2_ctrl_handler_setup(hdl: ov9734->sd.ctrl_handler); |
633 | if (ret) |
634 | return ret; |
635 | |
636 | ret = ov9734_write_reg(ov9734, OV9734_REG_MODE_SELECT, |
637 | len: 1, OV9734_MODE_STREAMING); |
638 | if (ret) |
639 | dev_err(&client->dev, "failed to start stream" ); |
640 | |
641 | return ret; |
642 | } |
643 | |
644 | static void ov9734_stop_streaming(struct ov9734 *ov9734) |
645 | { |
646 | struct i2c_client *client = v4l2_get_subdevdata(sd: &ov9734->sd); |
647 | |
648 | if (ov9734_write_reg(ov9734, OV9734_REG_MODE_SELECT, |
649 | len: 1, OV9734_MODE_STANDBY)) |
650 | dev_err(&client->dev, "failed to stop stream" ); |
651 | } |
652 | |
653 | static int ov9734_set_stream(struct v4l2_subdev *sd, int enable) |
654 | { |
655 | struct ov9734 *ov9734 = to_ov9734(subdev: sd); |
656 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
657 | int ret = 0; |
658 | |
659 | mutex_lock(&ov9734->mutex); |
660 | |
661 | if (enable) { |
662 | ret = pm_runtime_resume_and_get(dev: &client->dev); |
663 | if (ret < 0) { |
664 | mutex_unlock(lock: &ov9734->mutex); |
665 | return ret; |
666 | } |
667 | |
668 | ret = ov9734_start_streaming(ov9734); |
669 | if (ret) { |
670 | enable = 0; |
671 | ov9734_stop_streaming(ov9734); |
672 | pm_runtime_put(dev: &client->dev); |
673 | } |
674 | } else { |
675 | ov9734_stop_streaming(ov9734); |
676 | pm_runtime_put(dev: &client->dev); |
677 | } |
678 | |
679 | mutex_unlock(lock: &ov9734->mutex); |
680 | |
681 | return ret; |
682 | } |
683 | |
684 | static int ov9734_set_format(struct v4l2_subdev *sd, |
685 | struct v4l2_subdev_state *sd_state, |
686 | struct v4l2_subdev_format *fmt) |
687 | { |
688 | struct ov9734 *ov9734 = to_ov9734(subdev: sd); |
689 | const struct ov9734_mode *mode; |
690 | s32 vblank_def, h_blank; |
691 | |
692 | mode = v4l2_find_nearest_size(supported_modes, |
693 | ARRAY_SIZE(supported_modes), width, |
694 | height, fmt->format.width, |
695 | fmt->format.height); |
696 | |
697 | mutex_lock(&ov9734->mutex); |
698 | ov9734_update_pad_format(mode, fmt: &fmt->format); |
699 | if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { |
700 | *v4l2_subdev_state_get_format(sd_state, fmt->pad) = fmt->format; |
701 | } else { |
702 | ov9734->cur_mode = mode; |
703 | __v4l2_ctrl_s_ctrl(ctrl: ov9734->link_freq, val: mode->link_freq_index); |
704 | __v4l2_ctrl_s_ctrl_int64(ctrl: ov9734->pixel_rate, |
705 | val: to_pixel_rate(f_index: mode->link_freq_index)); |
706 | |
707 | /* Update limits and set FPS to default */ |
708 | vblank_def = mode->vts_def - mode->height; |
709 | __v4l2_ctrl_modify_range(ctrl: ov9734->vblank, |
710 | min: mode->vts_min - mode->height, |
711 | OV9734_VTS_MAX - mode->height, step: 1, |
712 | def: vblank_def); |
713 | __v4l2_ctrl_s_ctrl(ctrl: ov9734->vblank, val: vblank_def); |
714 | h_blank = to_pixels_per_line(hts: mode->hts, f_index: mode->link_freq_index) - |
715 | mode->width; |
716 | __v4l2_ctrl_modify_range(ctrl: ov9734->hblank, min: h_blank, max: h_blank, step: 1, |
717 | def: h_blank); |
718 | } |
719 | |
720 | mutex_unlock(lock: &ov9734->mutex); |
721 | |
722 | return 0; |
723 | } |
724 | |
725 | static int ov9734_get_format(struct v4l2_subdev *sd, |
726 | struct v4l2_subdev_state *sd_state, |
727 | struct v4l2_subdev_format *fmt) |
728 | { |
729 | struct ov9734 *ov9734 = to_ov9734(subdev: sd); |
730 | |
731 | mutex_lock(&ov9734->mutex); |
732 | if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) |
733 | fmt->format = *v4l2_subdev_state_get_format(sd_state, |
734 | fmt->pad); |
735 | else |
736 | ov9734_update_pad_format(mode: ov9734->cur_mode, fmt: &fmt->format); |
737 | |
738 | mutex_unlock(lock: &ov9734->mutex); |
739 | |
740 | return 0; |
741 | } |
742 | |
743 | static int ov9734_enum_mbus_code(struct v4l2_subdev *sd, |
744 | struct v4l2_subdev_state *sd_state, |
745 | struct v4l2_subdev_mbus_code_enum *code) |
746 | { |
747 | if (code->index > 0) |
748 | return -EINVAL; |
749 | |
750 | code->code = MEDIA_BUS_FMT_SGRBG10_1X10; |
751 | |
752 | return 0; |
753 | } |
754 | |
755 | static int ov9734_enum_frame_size(struct v4l2_subdev *sd, |
756 | struct v4l2_subdev_state *sd_state, |
757 | struct v4l2_subdev_frame_size_enum *fse) |
758 | { |
759 | if (fse->index >= ARRAY_SIZE(supported_modes)) |
760 | return -EINVAL; |
761 | |
762 | if (fse->code != MEDIA_BUS_FMT_SGRBG10_1X10) |
763 | return -EINVAL; |
764 | |
765 | fse->min_width = supported_modes[fse->index].width; |
766 | fse->max_width = fse->min_width; |
767 | fse->min_height = supported_modes[fse->index].height; |
768 | fse->max_height = fse->min_height; |
769 | |
770 | return 0; |
771 | } |
772 | |
773 | static int ov9734_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) |
774 | { |
775 | struct ov9734 *ov9734 = to_ov9734(subdev: sd); |
776 | |
777 | mutex_lock(&ov9734->mutex); |
778 | ov9734_update_pad_format(mode: &supported_modes[0], |
779 | v4l2_subdev_state_get_format(fh->state, 0)); |
780 | mutex_unlock(lock: &ov9734->mutex); |
781 | |
782 | return 0; |
783 | } |
784 | |
785 | static const struct v4l2_subdev_video_ops ov9734_video_ops = { |
786 | .s_stream = ov9734_set_stream, |
787 | }; |
788 | |
789 | static const struct v4l2_subdev_pad_ops ov9734_pad_ops = { |
790 | .set_fmt = ov9734_set_format, |
791 | .get_fmt = ov9734_get_format, |
792 | .enum_mbus_code = ov9734_enum_mbus_code, |
793 | .enum_frame_size = ov9734_enum_frame_size, |
794 | }; |
795 | |
796 | static const struct v4l2_subdev_ops ov9734_subdev_ops = { |
797 | .video = &ov9734_video_ops, |
798 | .pad = &ov9734_pad_ops, |
799 | }; |
800 | |
801 | static const struct media_entity_operations ov9734_subdev_entity_ops = { |
802 | .link_validate = v4l2_subdev_link_validate, |
803 | }; |
804 | |
805 | static const struct v4l2_subdev_internal_ops ov9734_internal_ops = { |
806 | .open = ov9734_open, |
807 | }; |
808 | |
809 | static int ov9734_identify_module(struct ov9734 *ov9734) |
810 | { |
811 | struct i2c_client *client = v4l2_get_subdevdata(sd: &ov9734->sd); |
812 | int ret; |
813 | u32 val; |
814 | |
815 | ret = ov9734_read_reg(ov9734, OV9734_REG_CHIP_ID, len: 2, val: &val); |
816 | if (ret) |
817 | return ret; |
818 | |
819 | if (val != OV9734_CHIP_ID) { |
820 | dev_err(&client->dev, "chip id mismatch: %x!=%x" , |
821 | OV9734_CHIP_ID, val); |
822 | return -ENXIO; |
823 | } |
824 | |
825 | return 0; |
826 | } |
827 | |
828 | static int ov9734_check_hwcfg(struct device *dev) |
829 | { |
830 | struct fwnode_handle *ep; |
831 | struct fwnode_handle *fwnode = dev_fwnode(dev); |
832 | struct v4l2_fwnode_endpoint bus_cfg = { |
833 | .bus_type = V4L2_MBUS_CSI2_DPHY |
834 | }; |
835 | u32 mclk; |
836 | int ret; |
837 | unsigned int i, j; |
838 | |
839 | if (!fwnode) |
840 | return -ENXIO; |
841 | |
842 | ret = fwnode_property_read_u32(fwnode, propname: "clock-frequency" , val: &mclk); |
843 | if (ret) |
844 | return ret; |
845 | |
846 | if (mclk != OV9734_MCLK) { |
847 | dev_err(dev, "external clock %d is not supported" , mclk); |
848 | return -EINVAL; |
849 | } |
850 | |
851 | ep = fwnode_graph_get_next_endpoint(fwnode, NULL); |
852 | if (!ep) |
853 | return -ENXIO; |
854 | |
855 | ret = v4l2_fwnode_endpoint_alloc_parse(fwnode: ep, vep: &bus_cfg); |
856 | fwnode_handle_put(fwnode: ep); |
857 | if (ret) |
858 | return ret; |
859 | |
860 | if (!bus_cfg.nr_of_link_frequencies) { |
861 | dev_err(dev, "no link frequencies defined" ); |
862 | ret = -EINVAL; |
863 | goto check_hwcfg_error; |
864 | } |
865 | |
866 | for (i = 0; i < ARRAY_SIZE(link_freq_menu_items); i++) { |
867 | for (j = 0; j < bus_cfg.nr_of_link_frequencies; j++) { |
868 | if (link_freq_menu_items[i] == |
869 | bus_cfg.link_frequencies[j]) |
870 | break; |
871 | } |
872 | |
873 | if (j == bus_cfg.nr_of_link_frequencies) { |
874 | dev_err(dev, "no link frequency %lld supported" , |
875 | link_freq_menu_items[i]); |
876 | ret = -EINVAL; |
877 | goto check_hwcfg_error; |
878 | } |
879 | } |
880 | |
881 | check_hwcfg_error: |
882 | v4l2_fwnode_endpoint_free(vep: &bus_cfg); |
883 | |
884 | return ret; |
885 | } |
886 | |
887 | static void ov9734_remove(struct i2c_client *client) |
888 | { |
889 | struct v4l2_subdev *sd = i2c_get_clientdata(client); |
890 | struct ov9734 *ov9734 = to_ov9734(subdev: sd); |
891 | |
892 | v4l2_async_unregister_subdev(sd); |
893 | media_entity_cleanup(entity: &sd->entity); |
894 | v4l2_ctrl_handler_free(hdl: sd->ctrl_handler); |
895 | pm_runtime_disable(dev: &client->dev); |
896 | pm_runtime_set_suspended(dev: &client->dev); |
897 | mutex_destroy(lock: &ov9734->mutex); |
898 | } |
899 | |
900 | static int ov9734_probe(struct i2c_client *client) |
901 | { |
902 | struct ov9734 *ov9734; |
903 | int ret; |
904 | |
905 | ret = ov9734_check_hwcfg(dev: &client->dev); |
906 | if (ret) { |
907 | dev_err(&client->dev, "failed to check HW configuration: %d" , |
908 | ret); |
909 | return ret; |
910 | } |
911 | |
912 | ov9734 = devm_kzalloc(dev: &client->dev, size: sizeof(*ov9734), GFP_KERNEL); |
913 | if (!ov9734) |
914 | return -ENOMEM; |
915 | |
916 | v4l2_i2c_subdev_init(sd: &ov9734->sd, client, ops: &ov9734_subdev_ops); |
917 | ret = ov9734_identify_module(ov9734); |
918 | if (ret) { |
919 | dev_err(&client->dev, "failed to find sensor: %d" , ret); |
920 | return ret; |
921 | } |
922 | |
923 | mutex_init(&ov9734->mutex); |
924 | ov9734->cur_mode = &supported_modes[0]; |
925 | ret = ov9734_init_controls(ov9734); |
926 | if (ret) { |
927 | dev_err(&client->dev, "failed to init controls: %d" , ret); |
928 | goto probe_error_v4l2_ctrl_handler_free; |
929 | } |
930 | |
931 | ov9734->sd.internal_ops = &ov9734_internal_ops; |
932 | ov9734->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; |
933 | ov9734->sd.entity.ops = &ov9734_subdev_entity_ops; |
934 | ov9734->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; |
935 | ov9734->pad.flags = MEDIA_PAD_FL_SOURCE; |
936 | ret = media_entity_pads_init(entity: &ov9734->sd.entity, num_pads: 1, pads: &ov9734->pad); |
937 | if (ret) { |
938 | dev_err(&client->dev, "failed to init entity pads: %d" , ret); |
939 | goto probe_error_v4l2_ctrl_handler_free; |
940 | } |
941 | |
942 | /* |
943 | * Device is already turned on by i2c-core with ACPI domain PM. |
944 | * Enable runtime PM and turn off the device. |
945 | */ |
946 | pm_runtime_set_active(dev: &client->dev); |
947 | pm_runtime_enable(dev: &client->dev); |
948 | pm_runtime_idle(dev: &client->dev); |
949 | |
950 | ret = v4l2_async_register_subdev_sensor(sd: &ov9734->sd); |
951 | if (ret < 0) { |
952 | dev_err(&client->dev, "failed to register V4L2 subdev: %d" , |
953 | ret); |
954 | goto probe_error_media_entity_cleanup_pm; |
955 | } |
956 | |
957 | return 0; |
958 | |
959 | probe_error_media_entity_cleanup_pm: |
960 | pm_runtime_disable(dev: &client->dev); |
961 | pm_runtime_set_suspended(dev: &client->dev); |
962 | media_entity_cleanup(entity: &ov9734->sd.entity); |
963 | |
964 | probe_error_v4l2_ctrl_handler_free: |
965 | v4l2_ctrl_handler_free(hdl: ov9734->sd.ctrl_handler); |
966 | mutex_destroy(lock: &ov9734->mutex); |
967 | |
968 | return ret; |
969 | } |
970 | |
971 | static const struct acpi_device_id ov9734_acpi_ids[] = { |
972 | { "OVTI9734" , }, |
973 | {} |
974 | }; |
975 | |
976 | MODULE_DEVICE_TABLE(acpi, ov9734_acpi_ids); |
977 | |
978 | static struct i2c_driver ov9734_i2c_driver = { |
979 | .driver = { |
980 | .name = "ov9734" , |
981 | .acpi_match_table = ov9734_acpi_ids, |
982 | }, |
983 | .probe = ov9734_probe, |
984 | .remove = ov9734_remove, |
985 | }; |
986 | |
987 | module_i2c_driver(ov9734_i2c_driver); |
988 | |
989 | MODULE_AUTHOR("Qiu, Tianshu <tian.shu.qiu@intel.com>" ); |
990 | MODULE_AUTHOR("Bingbu Cao <bingbu.cao@intel.com>" ); |
991 | MODULE_DESCRIPTION("OmniVision OV9734 sensor driver" ); |
992 | MODULE_LICENSE("GPL v2" ); |
993 | |