.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0 |
---|
1 | 2 | /* |
---|
2 | 3 | * ov2685 driver |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright (C) 2017 Fuzhou Rockchip Electronics Co., Ltd. |
---|
5 | | - * |
---|
6 | | - * This program is free software; you can redistribute it and/or modify |
---|
7 | | - * it under the terms of the GNU General Public License as published by |
---|
8 | | - * the Free Software Foundation; either version 2 of the License, or |
---|
9 | | - * (at your option) any later version. |
---|
10 | | - * V0.0X01.0X01 add enum_frame_interval function. |
---|
11 | | - * V0.0X01.0X02 add quick stream on/off |
---|
12 | | - * V0.0X01.0X03 add function g_mbus_config |
---|
13 | 6 | */ |
---|
14 | 7 | |
---|
15 | 8 | #include <linux/clk.h> |
---|
.. | .. |
---|
21 | 14 | #include <linux/pm_runtime.h> |
---|
22 | 15 | #include <linux/regulator/consumer.h> |
---|
23 | 16 | #include <linux/sysfs.h> |
---|
24 | | -#include <linux/slab.h> |
---|
25 | | -#include <linux/version.h> |
---|
26 | | -#include <linux/rk-camera-module.h> |
---|
27 | 17 | #include <media/media-entity.h> |
---|
28 | 18 | #include <media/v4l2-async.h> |
---|
29 | 19 | #include <media/v4l2-ctrls.h> |
---|
30 | 20 | #include <media/v4l2-subdev.h> |
---|
31 | 21 | |
---|
32 | | -#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x3) |
---|
33 | | - |
---|
34 | 22 | #define CHIP_ID 0x2685 |
---|
35 | 23 | #define OV2685_REG_CHIP_ID 0x300a |
---|
| 24 | + |
---|
| 25 | +#define OV2685_XVCLK_FREQ 24000000 |
---|
36 | 26 | |
---|
37 | 27 | #define REG_SC_CTRL_MODE 0x0100 |
---|
38 | 28 | #define SC_CTRL_MODE_STANDBY 0x0 |
---|
.. | .. |
---|
54 | 44 | #define OV2685_REG_TEST_PATTERN 0x5080 |
---|
55 | 45 | #define OV2685_TEST_PATTERN_DISABLED 0x00 |
---|
56 | 46 | #define OV2685_TEST_PATTERN_COLOR_BAR 0x80 |
---|
57 | | -#define OV2685_TEST_PATTERN_RND 0x81 |
---|
| 47 | +#define OV2685_TEST_PATTERN_RANDOM 0x81 |
---|
58 | 48 | #define OV2685_TEST_PATTERN_COLOR_BAR_FADE 0x88 |
---|
59 | 49 | #define OV2685_TEST_PATTERN_BW_SQUARE 0x92 |
---|
60 | 50 | #define OV2685_TEST_PATTERN_COLOR_SQUARE 0x82 |
---|
.. | .. |
---|
68 | 58 | #define OV2685_LANES 1 |
---|
69 | 59 | #define OV2685_BITS_PER_SAMPLE 10 |
---|
70 | 60 | |
---|
71 | | -#define OV2685_NAME "ov2685" |
---|
| 61 | +static const char * const ov2685_supply_names[] = { |
---|
| 62 | + "avdd", /* Analog power */ |
---|
| 63 | + "dovdd", /* Digital I/O power */ |
---|
| 64 | + "dvdd", /* Digital core power */ |
---|
| 65 | +}; |
---|
| 66 | + |
---|
| 67 | +#define OV2685_NUM_SUPPLIES ARRAY_SIZE(ov2685_supply_names) |
---|
72 | 68 | |
---|
73 | 69 | struct regval { |
---|
74 | 70 | u16 addr; |
---|
.. | .. |
---|
81 | 77 | u32 exp_def; |
---|
82 | 78 | u32 hts_def; |
---|
83 | 79 | u32 vts_def; |
---|
84 | | - struct v4l2_fract max_fps; |
---|
85 | 80 | const struct regval *reg_list; |
---|
86 | 81 | }; |
---|
87 | 82 | |
---|
88 | 83 | struct ov2685 { |
---|
89 | 84 | struct i2c_client *client; |
---|
90 | 85 | struct clk *xvclk; |
---|
91 | | - struct regulator *avdd_regulator; /* Analog power */ |
---|
92 | | - struct regulator *dovdd_regulator; /* Digital I/O power */ |
---|
93 | | - /* use internal DVDD power */ |
---|
94 | 86 | struct gpio_desc *reset_gpio; |
---|
| 87 | + struct regulator_bulk_data supplies[OV2685_NUM_SUPPLIES]; |
---|
95 | 88 | |
---|
96 | 89 | bool streaming; |
---|
97 | 90 | struct mutex mutex; |
---|
.. | .. |
---|
105 | 98 | struct v4l2_ctrl_handler ctrl_handler; |
---|
106 | 99 | |
---|
107 | 100 | const struct ov2685_mode *cur_mode; |
---|
108 | | - u32 module_index; |
---|
109 | | - const char *module_facing; |
---|
110 | | - const char *module_name; |
---|
111 | | - const char *len_name; |
---|
112 | 101 | }; |
---|
| 102 | + |
---|
113 | 103 | #define to_ov2685(sd) container_of(sd, struct ov2685, subdev) |
---|
114 | 104 | |
---|
115 | 105 | /* PLL settings bases on 24M xvclk */ |
---|
.. | .. |
---|
129 | 119 | {0x3087, 0x00}, |
---|
130 | 120 | {0x3501, 0x4e}, |
---|
131 | 121 | {0x3502, 0xe0}, |
---|
132 | | - {0x3503, 0x07}, |
---|
| 122 | + {0x3503, 0x27}, |
---|
133 | 123 | {0x350b, 0x36}, |
---|
134 | 124 | {0x3600, 0xb4}, |
---|
135 | 125 | {0x3603, 0x35}, |
---|
.. | .. |
---|
225 | 215 | static const char * const ov2685_test_pattern_menu[] = { |
---|
226 | 216 | "Disabled", |
---|
227 | 217 | "Color Bar", |
---|
228 | | - "RND PATTERN", |
---|
229 | 218 | "Color Bar FADE", |
---|
230 | | - "BW SQUARE", |
---|
231 | | - "COLOR SQUARE" |
---|
| 219 | + "Random Data", |
---|
| 220 | + "Black White Square", |
---|
| 221 | + "Color Square" |
---|
232 | 222 | }; |
---|
233 | 223 | |
---|
234 | 224 | static const int ov2685_test_pattern_val[] = { |
---|
235 | 225 | OV2685_TEST_PATTERN_DISABLED, |
---|
236 | 226 | OV2685_TEST_PATTERN_COLOR_BAR, |
---|
237 | | - OV2685_TEST_PATTERN_RND, |
---|
238 | 227 | OV2685_TEST_PATTERN_COLOR_BAR_FADE, |
---|
| 228 | + OV2685_TEST_PATTERN_RANDOM, |
---|
239 | 229 | OV2685_TEST_PATTERN_BW_SQUARE, |
---|
240 | 230 | OV2685_TEST_PATTERN_COLOR_SQUARE, |
---|
241 | 231 | }; |
---|
.. | .. |
---|
247 | 237 | .exp_def = 0x04ee, |
---|
248 | 238 | .hts_def = 0x06a4, |
---|
249 | 239 | .vts_def = 0x050e, |
---|
250 | | - .max_fps = { |
---|
251 | | - .numerator = 10000, |
---|
252 | | - .denominator = 300000, |
---|
253 | | - }, |
---|
254 | 240 | .reg_list = ov2685_1600x1200_regs, |
---|
255 | 241 | }, |
---|
256 | 242 | }; |
---|
257 | 243 | |
---|
258 | 244 | /* Write registers up to 4 at a time */ |
---|
259 | 245 | static int ov2685_write_reg(struct i2c_client *client, u16 reg, |
---|
260 | | - unsigned int len, u32 val) |
---|
| 246 | + u32 len, u32 val) |
---|
261 | 247 | { |
---|
262 | | - int buf_i; |
---|
263 | | - int val_i; |
---|
| 248 | + u32 val_i, buf_i; |
---|
264 | 249 | u8 buf[6]; |
---|
265 | 250 | u8 *val_p; |
---|
266 | 251 | __be32 val_be; |
---|
.. | .. |
---|
288 | 273 | static int ov2685_write_array(struct i2c_client *client, |
---|
289 | 274 | const struct regval *regs) |
---|
290 | 275 | { |
---|
291 | | - int i, ret = 0; |
---|
| 276 | + int ret = 0; |
---|
| 277 | + u32 i; |
---|
292 | 278 | |
---|
293 | 279 | for (i = 0; ret == 0 && regs[i].addr != REG_NULL; i++) |
---|
294 | 280 | ret = ov2685_write_reg(client, regs[i].addr, |
---|
.. | .. |
---|
299 | 285 | |
---|
300 | 286 | /* Read registers up to 4 at a time */ |
---|
301 | 287 | static int ov2685_read_reg(struct i2c_client *client, u16 reg, |
---|
302 | | - unsigned int len, u32 *val) |
---|
| 288 | + u32 len, u32 *val) |
---|
303 | 289 | { |
---|
304 | 290 | struct i2c_msg msgs[2]; |
---|
305 | 291 | u8 *data_be_p; |
---|
.. | .. |
---|
332 | 318 | return 0; |
---|
333 | 319 | } |
---|
334 | 320 | |
---|
335 | | -static void ov2685_fill_fmt(struct ov2685 *ov2685, |
---|
| 321 | +static void ov2685_fill_fmt(const struct ov2685_mode *mode, |
---|
336 | 322 | struct v4l2_mbus_framefmt *fmt) |
---|
337 | 323 | { |
---|
338 | 324 | fmt->code = MEDIA_BUS_FMT_SBGGR10_1X10; |
---|
339 | | - fmt->width = ov2685->cur_mode->width; |
---|
340 | | - fmt->height = ov2685->cur_mode->height; |
---|
| 325 | + fmt->width = mode->width; |
---|
| 326 | + fmt->height = mode->height; |
---|
341 | 327 | fmt->field = V4L2_FIELD_NONE; |
---|
342 | 328 | } |
---|
343 | 329 | |
---|
.. | .. |
---|
348 | 334 | struct ov2685 *ov2685 = to_ov2685(sd); |
---|
349 | 335 | struct v4l2_mbus_framefmt *mbus_fmt = &fmt->format; |
---|
350 | 336 | |
---|
351 | | - ov2685_fill_fmt(ov2685, mbus_fmt); |
---|
| 337 | + /* only one mode supported for now */ |
---|
| 338 | + ov2685_fill_fmt(ov2685->cur_mode, mbus_fmt); |
---|
352 | 339 | |
---|
353 | 340 | return 0; |
---|
354 | 341 | } |
---|
.. | .. |
---|
360 | 347 | struct ov2685 *ov2685 = to_ov2685(sd); |
---|
361 | 348 | struct v4l2_mbus_framefmt *mbus_fmt = &fmt->format; |
---|
362 | 349 | |
---|
363 | | - ov2685_fill_fmt(ov2685, mbus_fmt); |
---|
| 350 | + ov2685_fill_fmt(ov2685->cur_mode, mbus_fmt); |
---|
364 | 351 | |
---|
365 | 352 | return 0; |
---|
366 | 353 | } |
---|
.. | .. |
---|
373 | 360 | return -EINVAL; |
---|
374 | 361 | |
---|
375 | 362 | code->code = MEDIA_BUS_FMT_SBGGR10_1X10; |
---|
| 363 | + |
---|
376 | 364 | return 0; |
---|
377 | 365 | } |
---|
378 | 366 | |
---|
.. | .. |
---|
395 | 383 | return 0; |
---|
396 | 384 | } |
---|
397 | 385 | |
---|
398 | | -static inline void ov2685_set_exposure(struct ov2685 *ov2685, s32 val) |
---|
| 386 | +/* Calculate the delay in us by clock rate and clock cycles */ |
---|
| 387 | +static inline u32 ov2685_cal_delay(u32 cycles) |
---|
399 | 388 | { |
---|
400 | | - ov2685_write_reg(ov2685->client, OV2685_REG_EXPOSURE, |
---|
401 | | - OV2685_REG_VALUE_24BIT, val << 4); |
---|
402 | | -} |
---|
403 | | - |
---|
404 | | -static inline void ov2685_set_gain(struct ov2685 *ov2685, s32 val) |
---|
405 | | -{ |
---|
406 | | - ov2685_write_reg(ov2685->client, OV2685_REG_GAIN, |
---|
407 | | - OV2685_REG_VALUE_16BIT, val & OV2685_GAIN_MAX); |
---|
408 | | -} |
---|
409 | | - |
---|
410 | | -static inline void ov2685_set_vts(struct ov2685 *ov2685, s32 val) |
---|
411 | | -{ |
---|
412 | | - val += ov2685->cur_mode->height; |
---|
413 | | - ov2685_write_reg(ov2685->client, OV2685_REG_VTS, |
---|
414 | | - OV2685_REG_VALUE_16BIT, val); |
---|
415 | | -} |
---|
416 | | - |
---|
417 | | -static inline void ov2685_enable_test_pattern(struct ov2685 *ov2685, u32 pat) |
---|
418 | | -{ |
---|
419 | | - ov2685_write_reg(ov2685->client, OV2685_REG_TEST_PATTERN, |
---|
420 | | - OV2685_REG_VALUE_08BIT, ov2685_test_pattern_val[pat]); |
---|
| 389 | + return DIV_ROUND_UP(cycles, OV2685_XVCLK_FREQ / 1000 / 1000); |
---|
421 | 390 | } |
---|
422 | 391 | |
---|
423 | 392 | static int __ov2685_power_on(struct ov2685 *ov2685) |
---|
424 | 393 | { |
---|
425 | 394 | int ret; |
---|
| 395 | + u32 delay_us; |
---|
426 | 396 | struct device *dev = &ov2685->client->dev; |
---|
427 | 397 | |
---|
428 | 398 | ret = clk_prepare_enable(ov2685->xvclk); |
---|
.. | .. |
---|
430 | 400 | dev_err(dev, "Failed to enable xvclk\n"); |
---|
431 | 401 | return ret; |
---|
432 | 402 | } |
---|
433 | | - clk_set_rate(ov2685->xvclk, 24000000); |
---|
434 | 403 | |
---|
435 | 404 | gpiod_set_value_cansleep(ov2685->reset_gpio, 1); |
---|
436 | | - /* AVDD and DOVDD may rise in any order */ |
---|
437 | | - ret = regulator_enable(ov2685->avdd_regulator); |
---|
| 405 | + |
---|
| 406 | + ret = regulator_bulk_enable(OV2685_NUM_SUPPLIES, ov2685->supplies); |
---|
438 | 407 | if (ret < 0) { |
---|
439 | | - dev_err(dev, "Failed to enable AVDD regulator\n"); |
---|
440 | | - goto disable_xvclk; |
---|
| 408 | + dev_err(dev, "Failed to enable regulators\n"); |
---|
| 409 | + goto disable_clk; |
---|
441 | 410 | } |
---|
442 | | - ret = regulator_enable(ov2685->dovdd_regulator); |
---|
443 | | - if (ret < 0) { |
---|
444 | | - dev_err(dev, "Failed to enable DOVDD regulator\n"); |
---|
445 | | - goto disable_avdd; |
---|
446 | | - } |
---|
447 | | - /* The minimum delay between AVDD and reset rising can be 0 */ |
---|
| 411 | + |
---|
| 412 | + /* The minimum delay between power supplies and reset rising can be 0 */ |
---|
448 | 413 | gpiod_set_value_cansleep(ov2685->reset_gpio, 0); |
---|
449 | | - /* 8192 xvclk cycles prior to the first SCCB transaction. |
---|
450 | | - * NOTE: An additional 1ms must be added to wait for |
---|
451 | | - * SCCB to become stable when using internal DVDD. |
---|
452 | | - */ |
---|
453 | | - usleep_range(1350, 1500); |
---|
| 414 | + /* 8192 xvclk cycles prior to the first SCCB transaction */ |
---|
| 415 | + delay_us = ov2685_cal_delay(8192); |
---|
| 416 | + usleep_range(delay_us, delay_us * 2); |
---|
454 | 417 | |
---|
455 | 418 | /* HACK: ov2685 would output messy data after reset(R0103), |
---|
456 | 419 | * writing register before .s_stream() as a workaround |
---|
457 | 420 | */ |
---|
458 | 421 | ret = ov2685_write_array(ov2685->client, ov2685->cur_mode->reg_list); |
---|
| 422 | + if (ret) |
---|
| 423 | + goto disable_supplies; |
---|
459 | 424 | |
---|
460 | | - return ret; |
---|
461 | | -disable_avdd: |
---|
462 | | - regulator_disable(ov2685->avdd_regulator); |
---|
463 | | -disable_xvclk: |
---|
| 425 | + return 0; |
---|
| 426 | + |
---|
| 427 | +disable_supplies: |
---|
| 428 | + regulator_bulk_disable(OV2685_NUM_SUPPLIES, ov2685->supplies); |
---|
| 429 | +disable_clk: |
---|
464 | 430 | clk_disable_unprepare(ov2685->xvclk); |
---|
465 | 431 | |
---|
466 | 432 | return ret; |
---|
.. | .. |
---|
469 | 435 | static void __ov2685_power_off(struct ov2685 *ov2685) |
---|
470 | 436 | { |
---|
471 | 437 | /* 512 xvclk cycles after the last SCCB transaction or MIPI frame end */ |
---|
472 | | - usleep_range(30, 50); |
---|
| 438 | + u32 delay_us = ov2685_cal_delay(512); |
---|
| 439 | + |
---|
| 440 | + usleep_range(delay_us, delay_us * 2); |
---|
473 | 441 | clk_disable_unprepare(ov2685->xvclk); |
---|
474 | 442 | gpiod_set_value_cansleep(ov2685->reset_gpio, 1); |
---|
475 | | - regulator_disable(ov2685->dovdd_regulator); |
---|
476 | | - regulator_disable(ov2685->avdd_regulator); |
---|
| 443 | + regulator_bulk_disable(OV2685_NUM_SUPPLIES, ov2685->supplies); |
---|
477 | 444 | } |
---|
478 | | - |
---|
479 | | -static int ov2685_s_power(struct v4l2_subdev *sd, int on) |
---|
480 | | -{ |
---|
481 | | - struct ov2685 *ov2685 = to_ov2685(sd); |
---|
482 | | - int ret = 0; |
---|
483 | | - |
---|
484 | | - mutex_lock(&ov2685->mutex); |
---|
485 | | - |
---|
486 | | - if (on) |
---|
487 | | - ret = pm_runtime_get_sync(&ov2685->client->dev); |
---|
488 | | - else |
---|
489 | | - ret = pm_runtime_put(&ov2685->client->dev); |
---|
490 | | - |
---|
491 | | - mutex_unlock(&ov2685->mutex); |
---|
492 | | - |
---|
493 | | - return ret; |
---|
494 | | -} |
---|
495 | | - |
---|
496 | | -static void ov2685_get_module_inf(struct ov2685 *ov2685, |
---|
497 | | - struct rkmodule_inf *inf) |
---|
498 | | -{ |
---|
499 | | - memset(inf, 0, sizeof(*inf)); |
---|
500 | | - strlcpy(inf->base.sensor, OV2685_NAME, sizeof(inf->base.sensor)); |
---|
501 | | - strlcpy(inf->base.module, ov2685->module_name, |
---|
502 | | - sizeof(inf->base.module)); |
---|
503 | | - strlcpy(inf->base.lens, ov2685->len_name, sizeof(inf->base.lens)); |
---|
504 | | -} |
---|
505 | | - |
---|
506 | | -static long ov2685_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) |
---|
507 | | -{ |
---|
508 | | - struct ov2685 *ov2685 = to_ov2685(sd); |
---|
509 | | - long ret = 0; |
---|
510 | | - u32 stream = 0; |
---|
511 | | - |
---|
512 | | - switch (cmd) { |
---|
513 | | - case RKMODULE_GET_MODULE_INFO: |
---|
514 | | - ov2685_get_module_inf(ov2685, (struct rkmodule_inf *)arg); |
---|
515 | | - break; |
---|
516 | | - case RKMODULE_SET_QUICK_STREAM: |
---|
517 | | - |
---|
518 | | - stream = *((u32 *)arg); |
---|
519 | | - |
---|
520 | | - if (stream) |
---|
521 | | - ret = ov2685_write_reg(ov2685->client, REG_SC_CTRL_MODE, |
---|
522 | | - OV2685_REG_VALUE_08BIT, SC_CTRL_MODE_STREAMING); |
---|
523 | | - else |
---|
524 | | - ret = ov2685_write_reg(ov2685->client, REG_SC_CTRL_MODE, |
---|
525 | | - OV2685_REG_VALUE_08BIT, SC_CTRL_MODE_STANDBY); |
---|
526 | | - break; |
---|
527 | | - default: |
---|
528 | | - ret = -ENOIOCTLCMD; |
---|
529 | | - break; |
---|
530 | | - } |
---|
531 | | - |
---|
532 | | - return ret; |
---|
533 | | -} |
---|
534 | | - |
---|
535 | | -#ifdef CONFIG_COMPAT |
---|
536 | | -static long ov2685_compat_ioctl32(struct v4l2_subdev *sd, |
---|
537 | | - unsigned int cmd, unsigned long arg) |
---|
538 | | -{ |
---|
539 | | - void __user *up = compat_ptr(arg); |
---|
540 | | - struct rkmodule_inf *inf; |
---|
541 | | - struct rkmodule_awb_cfg *cfg; |
---|
542 | | - long ret; |
---|
543 | | - u32 stream = 0; |
---|
544 | | - |
---|
545 | | - switch (cmd) { |
---|
546 | | - case RKMODULE_GET_MODULE_INFO: |
---|
547 | | - inf = kzalloc(sizeof(*inf), GFP_KERNEL); |
---|
548 | | - if (!inf) { |
---|
549 | | - ret = -ENOMEM; |
---|
550 | | - return ret; |
---|
551 | | - } |
---|
552 | | - |
---|
553 | | - ret = ov2685_ioctl(sd, cmd, inf); |
---|
554 | | - if (!ret) |
---|
555 | | - ret = copy_to_user(up, inf, sizeof(*inf)); |
---|
556 | | - kfree(inf); |
---|
557 | | - break; |
---|
558 | | - case RKMODULE_AWB_CFG: |
---|
559 | | - cfg = kzalloc(sizeof(*cfg), GFP_KERNEL); |
---|
560 | | - if (!cfg) { |
---|
561 | | - ret = -ENOMEM; |
---|
562 | | - return ret; |
---|
563 | | - } |
---|
564 | | - |
---|
565 | | - ret = copy_from_user(cfg, up, sizeof(*cfg)); |
---|
566 | | - if (!ret) |
---|
567 | | - ret = ov2685_ioctl(sd, cmd, cfg); |
---|
568 | | - kfree(cfg); |
---|
569 | | - break; |
---|
570 | | - case RKMODULE_SET_QUICK_STREAM: |
---|
571 | | - ret = copy_from_user(&stream, up, sizeof(u32)); |
---|
572 | | - if (!ret) |
---|
573 | | - ret = ov2685_ioctl(sd, cmd, &stream); |
---|
574 | | - break; |
---|
575 | | - default: |
---|
576 | | - ret = -ENOIOCTLCMD; |
---|
577 | | - break; |
---|
578 | | - } |
---|
579 | | - |
---|
580 | | - return ret; |
---|
581 | | -} |
---|
582 | | -#endif |
---|
583 | 445 | |
---|
584 | 446 | static int ov2685_s_stream(struct v4l2_subdev *sd, int on) |
---|
585 | 447 | { |
---|
.. | .. |
---|
594 | 456 | goto unlock_and_return; |
---|
595 | 457 | |
---|
596 | 458 | if (on) { |
---|
597 | | - /* In case these controls are set before streaming */ |
---|
598 | | - ov2685_set_exposure(ov2685, ov2685->exposure->val); |
---|
599 | | - ov2685_set_gain(ov2685, ov2685->anal_gain->val); |
---|
600 | | - ov2685_set_vts(ov2685, ov2685->vblank->val); |
---|
601 | | - ov2685_enable_test_pattern(ov2685, ov2685->test_pattern->val); |
---|
602 | | - |
---|
| 459 | + ret = pm_runtime_get_sync(&ov2685->client->dev); |
---|
| 460 | + if (ret < 0) { |
---|
| 461 | + pm_runtime_put_noidle(&client->dev); |
---|
| 462 | + goto unlock_and_return; |
---|
| 463 | + } |
---|
| 464 | + ret = __v4l2_ctrl_handler_setup(&ov2685->ctrl_handler); |
---|
| 465 | + if (ret) { |
---|
| 466 | + pm_runtime_put(&client->dev); |
---|
| 467 | + goto unlock_and_return; |
---|
| 468 | + } |
---|
603 | 469 | ret = ov2685_write_reg(client, REG_SC_CTRL_MODE, |
---|
604 | 470 | OV2685_REG_VALUE_08BIT, SC_CTRL_MODE_STREAMING); |
---|
605 | | - if (ret) |
---|
| 471 | + if (ret) { |
---|
| 472 | + pm_runtime_put(&client->dev); |
---|
606 | 473 | goto unlock_and_return; |
---|
| 474 | + } |
---|
607 | 475 | } else { |
---|
608 | | - ret = ov2685_write_reg(client, REG_SC_CTRL_MODE, |
---|
| 476 | + ov2685_write_reg(client, REG_SC_CTRL_MODE, |
---|
609 | 477 | OV2685_REG_VALUE_08BIT, SC_CTRL_MODE_STANDBY); |
---|
610 | | - if (ret) |
---|
611 | | - goto unlock_and_return; |
---|
| 478 | + pm_runtime_put(&ov2685->client->dev); |
---|
612 | 479 | } |
---|
613 | 480 | |
---|
614 | 481 | ov2685->streaming = on; |
---|
615 | 482 | |
---|
616 | 483 | unlock_and_return: |
---|
617 | 484 | mutex_unlock(&ov2685->mutex); |
---|
| 485 | + |
---|
618 | 486 | return ret; |
---|
619 | 487 | } |
---|
620 | 488 | |
---|
.. | .. |
---|
628 | 496 | |
---|
629 | 497 | try_fmt = v4l2_subdev_get_try_format(sd, fh->pad, 0); |
---|
630 | 498 | /* Initialize try_fmt */ |
---|
631 | | - ov2685_fill_fmt(ov2685, try_fmt); |
---|
| 499 | + ov2685_fill_fmt(&supported_modes[0], try_fmt); |
---|
632 | 500 | |
---|
633 | 501 | mutex_unlock(&ov2685->mutex); |
---|
634 | 502 | |
---|
.. | .. |
---|
636 | 504 | } |
---|
637 | 505 | #endif |
---|
638 | 506 | |
---|
639 | | -static int ov2685_runtime_resume(struct device *dev) |
---|
| 507 | +static int __maybe_unused ov2685_runtime_resume(struct device *dev) |
---|
640 | 508 | { |
---|
641 | 509 | struct i2c_client *client = to_i2c_client(dev); |
---|
642 | 510 | struct v4l2_subdev *sd = i2c_get_clientdata(client); |
---|
643 | 511 | struct ov2685 *ov2685 = to_ov2685(sd); |
---|
644 | | - int ret; |
---|
645 | 512 | |
---|
646 | | - ret = __ov2685_power_on(ov2685); |
---|
647 | | - if (ret) |
---|
648 | | - return ret; |
---|
649 | | - |
---|
650 | | - if (ov2685->streaming) { |
---|
651 | | - ret = ov2685_s_stream(sd, 1); |
---|
652 | | - if (ret) |
---|
653 | | - __ov2685_power_off(ov2685); |
---|
654 | | - } |
---|
655 | | - |
---|
656 | | - return ret; |
---|
| 513 | + return __ov2685_power_on(ov2685); |
---|
657 | 514 | } |
---|
658 | 515 | |
---|
659 | | -static int ov2685_runtime_suspend(struct device *dev) |
---|
| 516 | +static int __maybe_unused ov2685_runtime_suspend(struct device *dev) |
---|
660 | 517 | { |
---|
661 | 518 | struct i2c_client *client = to_i2c_client(dev); |
---|
662 | 519 | struct v4l2_subdev *sd = i2c_get_clientdata(client); |
---|
.. | .. |
---|
677 | 534 | struct ov2685 *ov2685 = container_of(ctrl->handler, |
---|
678 | 535 | struct ov2685, ctrl_handler); |
---|
679 | 536 | struct i2c_client *client = ov2685->client; |
---|
680 | | - s64 max; |
---|
681 | | - int ret = 0; |
---|
| 537 | + s64 max_expo; |
---|
| 538 | + int ret; |
---|
682 | 539 | |
---|
683 | 540 | /* Propagate change of current control to all related controls */ |
---|
684 | 541 | switch (ctrl->id) { |
---|
685 | 542 | case V4L2_CID_VBLANK: |
---|
686 | 543 | /* Update max exposure while meeting expected vblanking */ |
---|
687 | | - max = ov2685->cur_mode->height + ctrl->val - 4; |
---|
| 544 | + max_expo = ov2685->cur_mode->height + ctrl->val - 4; |
---|
688 | 545 | __v4l2_ctrl_modify_range(ov2685->exposure, |
---|
689 | | - ov2685->exposure->minimum, max, |
---|
| 546 | + ov2685->exposure->minimum, max_expo, |
---|
690 | 547 | ov2685->exposure->step, |
---|
691 | 548 | ov2685->exposure->default_value); |
---|
692 | 549 | break; |
---|
.. | .. |
---|
694 | 551 | |
---|
695 | 552 | if (!pm_runtime_get_if_in_use(&client->dev)) |
---|
696 | 553 | return 0; |
---|
| 554 | + |
---|
697 | 555 | switch (ctrl->id) { |
---|
698 | 556 | case V4L2_CID_EXPOSURE: |
---|
699 | | - ov2685_set_exposure(ov2685, ctrl->val); |
---|
| 557 | + ret = ov2685_write_reg(ov2685->client, OV2685_REG_EXPOSURE, |
---|
| 558 | + OV2685_REG_VALUE_24BIT, ctrl->val << 4); |
---|
700 | 559 | break; |
---|
701 | 560 | case V4L2_CID_ANALOGUE_GAIN: |
---|
702 | | - ov2685_set_gain(ov2685, ctrl->val); |
---|
| 561 | + ret = ov2685_write_reg(ov2685->client, OV2685_REG_GAIN, |
---|
| 562 | + OV2685_REG_VALUE_16BIT, ctrl->val); |
---|
703 | 563 | break; |
---|
704 | 564 | case V4L2_CID_VBLANK: |
---|
705 | | - ov2685_set_vts(ov2685, ctrl->val); |
---|
| 565 | + ret = ov2685_write_reg(ov2685->client, OV2685_REG_VTS, |
---|
| 566 | + OV2685_REG_VALUE_16BIT, |
---|
| 567 | + ctrl->val + ov2685->cur_mode->height); |
---|
706 | 568 | break; |
---|
707 | 569 | case V4L2_CID_TEST_PATTERN: |
---|
708 | | - ov2685_enable_test_pattern(ov2685, ctrl->val); |
---|
| 570 | + ret = ov2685_write_reg(ov2685->client, OV2685_REG_TEST_PATTERN, |
---|
| 571 | + OV2685_REG_VALUE_08BIT, |
---|
| 572 | + ov2685_test_pattern_val[ctrl->val]); |
---|
709 | 573 | break; |
---|
710 | 574 | default: |
---|
711 | 575 | dev_warn(&client->dev, "%s Unhandled id:0x%x, val:0x%x\n", |
---|
712 | 576 | __func__, ctrl->id, ctrl->val); |
---|
| 577 | + ret = -EINVAL; |
---|
713 | 578 | break; |
---|
714 | | - }; |
---|
| 579 | + } |
---|
| 580 | + |
---|
715 | 581 | pm_runtime_put(&client->dev); |
---|
716 | 582 | |
---|
717 | 583 | return ret; |
---|
718 | 584 | } |
---|
719 | 585 | |
---|
720 | | -static int ov2685_enum_frame_interval(struct v4l2_subdev *sd, |
---|
721 | | - struct v4l2_subdev_pad_config *cfg, |
---|
722 | | - struct v4l2_subdev_frame_interval_enum *fie) |
---|
723 | | -{ |
---|
724 | | - if (fie->index >= ARRAY_SIZE(supported_modes)) |
---|
725 | | - return -EINVAL; |
---|
726 | | - |
---|
727 | | - if (fie->code != MEDIA_BUS_FMT_SBGGR10_1X10) |
---|
728 | | - return -EINVAL; |
---|
729 | | - |
---|
730 | | - fie->width = supported_modes[fie->index].width; |
---|
731 | | - fie->height = supported_modes[fie->index].height; |
---|
732 | | - fie->interval = supported_modes[fie->index].max_fps; |
---|
733 | | - return 0; |
---|
734 | | -} |
---|
735 | | - |
---|
736 | | -static int ov2685_g_mbus_config(struct v4l2_subdev *sd, |
---|
737 | | - struct v4l2_mbus_config *config) |
---|
738 | | -{ |
---|
739 | | - u32 val = 0; |
---|
740 | | - |
---|
741 | | - val = 1 << (OV2685_LANES - 1) | |
---|
742 | | - V4L2_MBUS_CSI2_CHANNEL_0 | |
---|
743 | | - V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; |
---|
744 | | - config->type = V4L2_MBUS_CSI2; |
---|
745 | | - config->flags = val; |
---|
746 | | - |
---|
747 | | - return 0; |
---|
748 | | -} |
---|
749 | | - |
---|
750 | | -static struct v4l2_subdev_core_ops ov2685_core_ops = { |
---|
751 | | - .s_power = ov2685_s_power, |
---|
752 | | - .ioctl = ov2685_ioctl, |
---|
753 | | -#ifdef CONFIG_COMPAT |
---|
754 | | - .compat_ioctl32 = ov2685_compat_ioctl32, |
---|
755 | | -#endif |
---|
756 | | -}; |
---|
757 | | - |
---|
758 | | -static struct v4l2_subdev_video_ops ov2685_video_ops = { |
---|
| 586 | +static const struct v4l2_subdev_video_ops ov2685_video_ops = { |
---|
759 | 587 | .s_stream = ov2685_s_stream, |
---|
760 | | - .g_mbus_config = ov2685_g_mbus_config, |
---|
761 | 588 | }; |
---|
762 | 589 | |
---|
763 | | -static struct v4l2_subdev_pad_ops ov2685_pad_ops = { |
---|
| 590 | +static const struct v4l2_subdev_pad_ops ov2685_pad_ops = { |
---|
764 | 591 | .enum_mbus_code = ov2685_enum_mbus_code, |
---|
765 | 592 | .enum_frame_size = ov2685_enum_frame_sizes, |
---|
766 | | - .enum_frame_interval = ov2685_enum_frame_interval, |
---|
767 | 593 | .get_fmt = ov2685_get_fmt, |
---|
768 | 594 | .set_fmt = ov2685_set_fmt, |
---|
769 | 595 | }; |
---|
770 | 596 | |
---|
771 | | -static struct v4l2_subdev_ops ov2685_subdev_ops = { |
---|
772 | | - .core = &ov2685_core_ops, |
---|
| 597 | +static const struct v4l2_subdev_ops ov2685_subdev_ops = { |
---|
773 | 598 | .video = &ov2685_video_ops, |
---|
774 | 599 | .pad = &ov2685_pad_ops, |
---|
775 | 600 | }; |
---|
.. | .. |
---|
795 | 620 | |
---|
796 | 621 | handler = &ov2685->ctrl_handler; |
---|
797 | 622 | mode = ov2685->cur_mode; |
---|
798 | | - ret = v4l2_ctrl_handler_init(handler, 1); |
---|
| 623 | + ret = v4l2_ctrl_handler_init(handler, 8); |
---|
799 | 624 | if (ret) |
---|
800 | 625 | return ret; |
---|
801 | 626 | handler->lock = &ov2685->mutex; |
---|
.. | .. |
---|
838 | 663 | 0, 0, ov2685_test_pattern_menu); |
---|
839 | 664 | |
---|
840 | 665 | if (handler->error) { |
---|
841 | | - v4l2_ctrl_handler_free(handler); |
---|
842 | | - return handler->error; |
---|
| 666 | + ret = handler->error; |
---|
| 667 | + dev_err(&ov2685->client->dev, |
---|
| 668 | + "Failed to init controls(%d)\n", ret); |
---|
| 669 | + goto err_free_handler; |
---|
843 | 670 | } |
---|
844 | 671 | |
---|
845 | 672 | ov2685->subdev.ctrl_handler = handler; |
---|
846 | 673 | |
---|
847 | 674 | return 0; |
---|
| 675 | + |
---|
| 676 | +err_free_handler: |
---|
| 677 | + v4l2_ctrl_handler_free(handler); |
---|
| 678 | + |
---|
| 679 | + return ret; |
---|
848 | 680 | } |
---|
849 | 681 | |
---|
850 | 682 | static int ov2685_check_sensor_id(struct ov2685 *ov2685, |
---|
851 | 683 | struct i2c_client *client) |
---|
852 | 684 | { |
---|
853 | 685 | struct device *dev = &ov2685->client->dev; |
---|
854 | | - int id, ret; |
---|
| 686 | + int ret; |
---|
| 687 | + u32 id = 0; |
---|
855 | 688 | |
---|
856 | | - ret = __ov2685_power_on(ov2685); |
---|
857 | | - if (ret) |
---|
858 | | - return ret; |
---|
859 | | - ov2685_read_reg(client, OV2685_REG_CHIP_ID, |
---|
860 | | - OV2685_REG_VALUE_16BIT, &id); |
---|
861 | | - __ov2685_power_off(ov2685); |
---|
862 | | - |
---|
| 689 | + ret = ov2685_read_reg(client, OV2685_REG_CHIP_ID, |
---|
| 690 | + OV2685_REG_VALUE_16BIT, &id); |
---|
863 | 691 | if (id != CHIP_ID) { |
---|
864 | | - dev_err(dev, "Wrong camera sensor id(%04x)\n", id); |
---|
865 | | - return -EINVAL; |
---|
| 692 | + dev_err(dev, "Unexpected sensor id(%04x), ret(%d)\n", id, ret); |
---|
| 693 | + return ret; |
---|
866 | 694 | } |
---|
867 | 695 | |
---|
868 | 696 | dev_info(dev, "Detected OV%04x sensor\n", CHIP_ID); |
---|
.. | .. |
---|
870 | 698 | return 0; |
---|
871 | 699 | } |
---|
872 | 700 | |
---|
| 701 | +static int ov2685_configure_regulators(struct ov2685 *ov2685) |
---|
| 702 | +{ |
---|
| 703 | + int i; |
---|
| 704 | + |
---|
| 705 | + for (i = 0; i < OV2685_NUM_SUPPLIES; i++) |
---|
| 706 | + ov2685->supplies[i].supply = ov2685_supply_names[i]; |
---|
| 707 | + |
---|
| 708 | + return devm_regulator_bulk_get(&ov2685->client->dev, |
---|
| 709 | + OV2685_NUM_SUPPLIES, |
---|
| 710 | + ov2685->supplies); |
---|
| 711 | +} |
---|
| 712 | + |
---|
873 | 713 | static int ov2685_probe(struct i2c_client *client, |
---|
874 | 714 | const struct i2c_device_id *id) |
---|
875 | 715 | { |
---|
876 | 716 | struct device *dev = &client->dev; |
---|
877 | | - struct device_node *node = dev->of_node; |
---|
878 | 717 | struct ov2685 *ov2685; |
---|
879 | | - struct v4l2_subdev *sd; |
---|
880 | | - char facing[2]; |
---|
881 | 718 | int ret; |
---|
882 | | - |
---|
883 | | - dev_info(dev, "driver version: %02x.%02x.%02x", |
---|
884 | | - DRIVER_VERSION >> 16, |
---|
885 | | - (DRIVER_VERSION & 0xff00) >> 8, |
---|
886 | | - DRIVER_VERSION & 0x00ff); |
---|
887 | 719 | |
---|
888 | 720 | ov2685 = devm_kzalloc(dev, sizeof(*ov2685), GFP_KERNEL); |
---|
889 | 721 | if (!ov2685) |
---|
890 | 722 | return -ENOMEM; |
---|
891 | | - |
---|
892 | | - ret = of_property_read_u32(node, RKMODULE_CAMERA_MODULE_INDEX, |
---|
893 | | - &ov2685->module_index); |
---|
894 | | - ret |= of_property_read_string(node, RKMODULE_CAMERA_MODULE_FACING, |
---|
895 | | - &ov2685->module_facing); |
---|
896 | | - ret |= of_property_read_string(node, RKMODULE_CAMERA_MODULE_NAME, |
---|
897 | | - &ov2685->module_name); |
---|
898 | | - ret |= of_property_read_string(node, RKMODULE_CAMERA_LENS_NAME, |
---|
899 | | - &ov2685->len_name); |
---|
900 | | - if (ret) { |
---|
901 | | - dev_err(dev, "could not get module information!\n"); |
---|
902 | | - return -EINVAL; |
---|
903 | | - } |
---|
904 | 723 | |
---|
905 | 724 | ov2685->client = client; |
---|
906 | 725 | ov2685->cur_mode = &supported_modes[0]; |
---|
.. | .. |
---|
910 | 729 | dev_err(dev, "Failed to get xvclk\n"); |
---|
911 | 730 | return -EINVAL; |
---|
912 | 731 | } |
---|
| 732 | + ret = clk_set_rate(ov2685->xvclk, OV2685_XVCLK_FREQ); |
---|
| 733 | + if (ret < 0) { |
---|
| 734 | + dev_err(dev, "Failed to set xvclk rate (24MHz)\n"); |
---|
| 735 | + return ret; |
---|
| 736 | + } |
---|
| 737 | + if (clk_get_rate(ov2685->xvclk) != OV2685_XVCLK_FREQ) |
---|
| 738 | + dev_warn(dev, "xvclk mismatched, modes are based on 24MHz\n"); |
---|
913 | 739 | |
---|
914 | 740 | ov2685->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); |
---|
915 | 741 | if (IS_ERR(ov2685->reset_gpio)) { |
---|
.. | .. |
---|
917 | 743 | return -EINVAL; |
---|
918 | 744 | } |
---|
919 | 745 | |
---|
920 | | - ov2685->avdd_regulator = devm_regulator_get(dev, "avdd"); |
---|
921 | | - if (IS_ERR(ov2685->avdd_regulator)) { |
---|
922 | | - dev_err(dev, "Failed to get avdd-supply\n"); |
---|
923 | | - return -EINVAL; |
---|
924 | | - } |
---|
925 | | - ov2685->dovdd_regulator = devm_regulator_get(dev, "dovdd"); |
---|
926 | | - if (IS_ERR(ov2685->dovdd_regulator)) { |
---|
927 | | - dev_err(dev, "Failed to get dovdd-supply\n"); |
---|
928 | | - return -EINVAL; |
---|
| 746 | + ret = ov2685_configure_regulators(ov2685); |
---|
| 747 | + if (ret) { |
---|
| 748 | + dev_err(dev, "Failed to get power regulators\n"); |
---|
| 749 | + return ret; |
---|
929 | 750 | } |
---|
930 | 751 | |
---|
931 | 752 | mutex_init(&ov2685->mutex); |
---|
932 | 753 | v4l2_i2c_subdev_init(&ov2685->subdev, client, &ov2685_subdev_ops); |
---|
933 | 754 | ret = ov2685_initialize_controls(ov2685); |
---|
934 | 755 | if (ret) |
---|
935 | | - goto destroy_mutex; |
---|
| 756 | + goto err_destroy_mutex; |
---|
| 757 | + |
---|
| 758 | + ret = __ov2685_power_on(ov2685); |
---|
| 759 | + if (ret) |
---|
| 760 | + goto err_free_handler; |
---|
936 | 761 | |
---|
937 | 762 | ret = ov2685_check_sensor_id(ov2685, client); |
---|
938 | 763 | if (ret) |
---|
939 | | - return ret; |
---|
| 764 | + goto err_power_off; |
---|
940 | 765 | |
---|
941 | 766 | #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API |
---|
942 | 767 | ov2685->subdev.internal_ops = &ov2685_internal_ops; |
---|
| 768 | + ov2685->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; |
---|
943 | 769 | #endif |
---|
944 | 770 | #if defined(CONFIG_MEDIA_CONTROLLER) |
---|
945 | 771 | ov2685->pad.flags = MEDIA_PAD_FL_SOURCE; |
---|
946 | | - ov2685->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | |
---|
947 | | - V4L2_SUBDEV_FL_HAS_EVENTS; |
---|
948 | 772 | ov2685->subdev.entity.function = MEDIA_ENT_F_CAM_SENSOR; |
---|
949 | 773 | ret = media_entity_pads_init(&ov2685->subdev.entity, 1, &ov2685->pad); |
---|
950 | 774 | if (ret < 0) |
---|
951 | | - goto free_ctrl_handler; |
---|
| 775 | + goto err_power_off; |
---|
952 | 776 | #endif |
---|
953 | 777 | |
---|
954 | | - sd = &ov2685->subdev; |
---|
955 | | - memset(facing, 0, sizeof(facing)); |
---|
956 | | - if (strcmp(ov2685->module_facing, "back") == 0) |
---|
957 | | - facing[0] = 'b'; |
---|
958 | | - else |
---|
959 | | - facing[0] = 'f'; |
---|
960 | | - |
---|
961 | | - snprintf(sd->name, sizeof(sd->name), "m%02d_%s_%s %s", |
---|
962 | | - ov2685->module_index, facing, |
---|
963 | | - OV2685_NAME, dev_name(sd->dev)); |
---|
964 | | - ret = v4l2_async_register_subdev_sensor_common(sd); |
---|
| 778 | + ret = v4l2_async_register_subdev(&ov2685->subdev); |
---|
965 | 779 | if (ret) { |
---|
966 | 780 | dev_err(dev, "v4l2 async register subdev failed\n"); |
---|
967 | | - goto clean_entity; |
---|
| 781 | + goto err_clean_entity; |
---|
968 | 782 | } |
---|
969 | 783 | |
---|
| 784 | + pm_runtime_set_active(dev); |
---|
970 | 785 | pm_runtime_enable(dev); |
---|
| 786 | + pm_runtime_idle(dev); |
---|
| 787 | + |
---|
971 | 788 | return 0; |
---|
972 | 789 | |
---|
973 | | -clean_entity: |
---|
| 790 | +err_clean_entity: |
---|
974 | 791 | #if defined(CONFIG_MEDIA_CONTROLLER) |
---|
975 | 792 | media_entity_cleanup(&ov2685->subdev.entity); |
---|
976 | 793 | #endif |
---|
977 | | -free_ctrl_handler: |
---|
| 794 | +err_power_off: |
---|
| 795 | + __ov2685_power_off(ov2685); |
---|
| 796 | +err_free_handler: |
---|
978 | 797 | v4l2_ctrl_handler_free(&ov2685->ctrl_handler); |
---|
979 | | -destroy_mutex: |
---|
| 798 | +err_destroy_mutex: |
---|
980 | 799 | mutex_destroy(&ov2685->mutex); |
---|
981 | 800 | |
---|
982 | 801 | return ret; |
---|
.. | .. |
---|
984 | 803 | |
---|
985 | 804 | static int ov2685_remove(struct i2c_client *client) |
---|
986 | 805 | { |
---|
987 | | - struct ov2685 *ov2685 = i2c_get_clientdata(client); |
---|
| 806 | + struct v4l2_subdev *sd = i2c_get_clientdata(client); |
---|
| 807 | + struct ov2685 *ov2685 = to_ov2685(sd); |
---|
988 | 808 | |
---|
989 | | - __ov2685_power_off(ov2685); |
---|
990 | | - v4l2_async_unregister_subdev(&ov2685->subdev); |
---|
991 | | - media_entity_cleanup(&ov2685->subdev.entity); |
---|
| 809 | + v4l2_async_unregister_subdev(sd); |
---|
| 810 | +#if defined(CONFIG_MEDIA_CONTROLLER) |
---|
| 811 | + media_entity_cleanup(&sd->entity); |
---|
| 812 | +#endif |
---|
992 | 813 | v4l2_ctrl_handler_free(&ov2685->ctrl_handler); |
---|
993 | 814 | mutex_destroy(&ov2685->mutex); |
---|
| 815 | + |
---|
| 816 | + pm_runtime_disable(&client->dev); |
---|
| 817 | + if (!pm_runtime_status_suspended(&client->dev)) |
---|
| 818 | + __ov2685_power_off(ov2685); |
---|
| 819 | + pm_runtime_set_suspended(&client->dev); |
---|
994 | 820 | |
---|
995 | 821 | return 0; |
---|
996 | 822 | } |
---|
997 | 823 | |
---|
| 824 | +#if IS_ENABLED(CONFIG_OF) |
---|
998 | 825 | static const struct of_device_id ov2685_of_match[] = { |
---|
999 | 826 | { .compatible = "ovti,ov2685" }, |
---|
1000 | 827 | {}, |
---|
1001 | 828 | }; |
---|
| 829 | +MODULE_DEVICE_TABLE(of, ov2685_of_match); |
---|
| 830 | +#endif |
---|
1002 | 831 | |
---|
1003 | 832 | static struct i2c_driver ov2685_i2c_driver = { |
---|
1004 | 833 | .driver = { |
---|
1005 | | - .name = OV2685_NAME, |
---|
1006 | | - .owner = THIS_MODULE, |
---|
| 834 | + .name = "ov2685", |
---|
1007 | 835 | .pm = &ov2685_pm_ops, |
---|
1008 | | - .of_match_table = ov2685_of_match |
---|
| 836 | + .of_match_table = of_match_ptr(ov2685_of_match), |
---|
1009 | 837 | }, |
---|
1010 | 838 | .probe = &ov2685_probe, |
---|
1011 | 839 | .remove = &ov2685_remove, |
---|