| .. | .. |
|---|
| 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, |
|---|