1315 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Driver for the OV5645 camera sensor.4 *5 * Copyright (c) 2011-2015, The Linux Foundation. All rights reserved.6 * Copyright (C) 2015 By Tech Design S.L. All Rights Reserved.7 * Copyright (C) 2012-2013 Freescale Semiconductor, Inc. All Rights Reserved.8 *9 * Based on:10 * - the OV5645 driver from QC msm-3.10 kernel on codeaurora.org:11 * https://us.codeaurora.org/cgit/quic/la/kernel/msm-3.10/tree/drivers/12 * media/platform/msm/camera_v2/sensor/ov5645.c?h=LA.BR.1.2.4_rb1.4113 * - the OV5640 driver posted on linux-media:14 * https://www.mail-archive.com/linux-media%40vger.kernel.org/msg92671.html15 */16 17#include <linux/bitops.h>18#include <linux/clk.h>19#include <linux/delay.h>20#include <linux/device.h>21#include <linux/gpio/consumer.h>22#include <linux/i2c.h>23#include <linux/init.h>24#include <linux/module.h>25#include <linux/of.h>26#include <linux/of_graph.h>27#include <linux/pm_runtime.h>28#include <linux/regulator/consumer.h>29#include <linux/slab.h>30#include <linux/types.h>31#include <media/v4l2-ctrls.h>32#include <media/v4l2-fwnode.h>33#include <media/v4l2-subdev.h>34 35#define OV5645_SYSTEM_CTRL0 0x300836#define OV5645_SYSTEM_CTRL0_START 0x0237#define OV5645_SYSTEM_CTRL0_STOP 0x4238#define OV5645_CHIP_ID_HIGH 0x300a39#define OV5645_CHIP_ID_HIGH_BYTE 0x5640#define OV5645_CHIP_ID_LOW 0x300b41#define OV5645_CHIP_ID_LOW_BYTE 0x4542#define OV5645_IO_MIPI_CTRL00 0x300e43#define OV5645_PAD_OUTPUT00 0x301944#define OV5645_AWB_MANUAL_CONTROL 0x340645#define OV5645_AWB_MANUAL_ENABLE BIT(0)46#define OV5645_AEC_PK_MANUAL 0x350347#define OV5645_AEC_MANUAL_ENABLE BIT(0)48#define OV5645_AGC_MANUAL_ENABLE BIT(1)49#define OV5645_TIMING_TC_REG20 0x382050#define OV5645_SENSOR_VFLIP BIT(1)51#define OV5645_ISP_VFLIP BIT(2)52#define OV5645_TIMING_TC_REG21 0x382153#define OV5645_SENSOR_MIRROR BIT(1)54#define OV5645_MIPI_CTRL00 0x480055#define OV5645_PRE_ISP_TEST_SETTING_1 0x503d56#define OV5645_TEST_PATTERN_MASK 0x357#define OV5645_SET_TEST_PATTERN(x) ((x) & OV5645_TEST_PATTERN_MASK)58#define OV5645_TEST_PATTERN_ENABLE BIT(7)59#define OV5645_SDE_SAT_U 0x558360#define OV5645_SDE_SAT_V 0x558461 62/* regulator supplies */63static const char * const ov5645_supply_name[] = {64 "vdddo", /* Digital I/O (1.8V) supply */65 "vdda", /* Analog (2.8V) supply */66 "vddd", /* Digital Core (1.5V) supply */67};68 69#define OV5645_NUM_SUPPLIES ARRAY_SIZE(ov5645_supply_name)70 71struct reg_value {72 u16 reg;73 u8 val;74};75 76struct ov5645_mode_info {77 u32 width;78 u32 height;79 const struct reg_value *data;80 u32 data_size;81 u32 pixel_clock;82 u32 link_freq;83};84 85struct ov5645 {86 struct i2c_client *i2c_client;87 struct device *dev;88 struct v4l2_subdev sd;89 struct media_pad pad;90 struct v4l2_fwnode_endpoint ep;91 struct v4l2_mbus_framefmt fmt;92 struct v4l2_rect crop;93 struct clk *xclk;94 95 struct regulator_bulk_data supplies[OV5645_NUM_SUPPLIES];96 97 const struct ov5645_mode_info *current_mode;98 99 struct v4l2_ctrl_handler ctrls;100 struct v4l2_ctrl *pixel_clock;101 struct v4l2_ctrl *link_freq;102 103 /* Cached register values */104 u8 aec_pk_manual;105 u8 timing_tc_reg20;106 u8 timing_tc_reg21;107 108 struct mutex power_lock; /* lock to protect power state */109 110 struct gpio_desc *enable_gpio;111 struct gpio_desc *rst_gpio;112};113 114static inline struct ov5645 *to_ov5645(struct v4l2_subdev *sd)115{116 return container_of(sd, struct ov5645, sd);117}118 119static const struct reg_value ov5645_global_init_setting[] = {120 { 0x3103, 0x11 },121 { 0x3008, 0x42 },122 { 0x3103, 0x03 },123 { 0x3503, 0x07 },124 { 0x3002, 0x1c },125 { 0x3006, 0xc3 },126 { 0x3017, 0x00 },127 { 0x3018, 0x00 },128 { 0x302e, 0x0b },129 { 0x3037, 0x13 },130 { 0x3108, 0x01 },131 { 0x3611, 0x06 },132 { 0x3500, 0x00 },133 { 0x3501, 0x01 },134 { 0x3502, 0x00 },135 { 0x350a, 0x00 },136 { 0x350b, 0x3f },137 { 0x3620, 0x33 },138 { 0x3621, 0xe0 },139 { 0x3622, 0x01 },140 { 0x3630, 0x2e },141 { 0x3631, 0x00 },142 { 0x3632, 0x32 },143 { 0x3633, 0x52 },144 { 0x3634, 0x70 },145 { 0x3635, 0x13 },146 { 0x3636, 0x03 },147 { 0x3703, 0x5a },148 { 0x3704, 0xa0 },149 { 0x3705, 0x1a },150 { 0x3709, 0x12 },151 { 0x370b, 0x61 },152 { 0x370f, 0x10 },153 { 0x3715, 0x78 },154 { 0x3717, 0x01 },155 { 0x371b, 0x20 },156 { 0x3731, 0x12 },157 { 0x3901, 0x0a },158 { 0x3905, 0x02 },159 { 0x3906, 0x10 },160 { 0x3719, 0x86 },161 { 0x3810, 0x00 },162 { 0x3811, 0x10 },163 { 0x3812, 0x00 },164 { 0x3821, 0x01 },165 { 0x3824, 0x01 },166 { 0x3826, 0x03 },167 { 0x3828, 0x08 },168 { 0x3a19, 0xf8 },169 { 0x3c01, 0x34 },170 { 0x3c04, 0x28 },171 { 0x3c05, 0x98 },172 { 0x3c07, 0x07 },173 { 0x3c09, 0xc2 },174 { 0x3c0a, 0x9c },175 { 0x3c0b, 0x40 },176 { 0x3c01, 0x34 },177 { 0x4001, 0x02 },178 { 0x4514, 0x00 },179 { 0x4520, 0xb0 },180 { 0x460b, 0x37 },181 { 0x460c, 0x20 },182 { 0x4818, 0x01 },183 { 0x481d, 0xf0 },184 { 0x481f, 0x50 },185 { 0x4823, 0x70 },186 { 0x4831, 0x14 },187 { 0x5000, 0xa7 },188 { 0x5001, 0x83 },189 { 0x501d, 0x00 },190 { 0x501f, 0x00 },191 { 0x503d, 0x00 },192 { 0x505c, 0x30 },193 { 0x5181, 0x59 },194 { 0x5183, 0x00 },195 { 0x5191, 0xf0 },196 { 0x5192, 0x03 },197 { 0x5684, 0x10 },198 { 0x5685, 0xa0 },199 { 0x5686, 0x0c },200 { 0x5687, 0x78 },201 { 0x5a00, 0x08 },202 { 0x5a21, 0x00 },203 { 0x5a24, 0x00 },204 { 0x3008, 0x02 },205 { 0x3503, 0x00 },206 { 0x5180, 0xff },207 { 0x5181, 0xf2 },208 { 0x5182, 0x00 },209 { 0x5183, 0x14 },210 { 0x5184, 0x25 },211 { 0x5185, 0x24 },212 { 0x5186, 0x09 },213 { 0x5187, 0x09 },214 { 0x5188, 0x0a },215 { 0x5189, 0x75 },216 { 0x518a, 0x52 },217 { 0x518b, 0xea },218 { 0x518c, 0xa8 },219 { 0x518d, 0x42 },220 { 0x518e, 0x38 },221 { 0x518f, 0x56 },222 { 0x5190, 0x42 },223 { 0x5191, 0xf8 },224 { 0x5192, 0x04 },225 { 0x5193, 0x70 },226 { 0x5194, 0xf0 },227 { 0x5195, 0xf0 },228 { 0x5196, 0x03 },229 { 0x5197, 0x01 },230 { 0x5198, 0x04 },231 { 0x5199, 0x12 },232 { 0x519a, 0x04 },233 { 0x519b, 0x00 },234 { 0x519c, 0x06 },235 { 0x519d, 0x82 },236 { 0x519e, 0x38 },237 { 0x5381, 0x1e },238 { 0x5382, 0x5b },239 { 0x5383, 0x08 },240 { 0x5384, 0x0a },241 { 0x5385, 0x7e },242 { 0x5386, 0x88 },243 { 0x5387, 0x7c },244 { 0x5388, 0x6c },245 { 0x5389, 0x10 },246 { 0x538a, 0x01 },247 { 0x538b, 0x98 },248 { 0x5300, 0x08 },249 { 0x5301, 0x30 },250 { 0x5302, 0x10 },251 { 0x5303, 0x00 },252 { 0x5304, 0x08 },253 { 0x5305, 0x30 },254 { 0x5306, 0x08 },255 { 0x5307, 0x16 },256 { 0x5309, 0x08 },257 { 0x530a, 0x30 },258 { 0x530b, 0x04 },259 { 0x530c, 0x06 },260 { 0x5480, 0x01 },261 { 0x5481, 0x08 },262 { 0x5482, 0x14 },263 { 0x5483, 0x28 },264 { 0x5484, 0x51 },265 { 0x5485, 0x65 },266 { 0x5486, 0x71 },267 { 0x5487, 0x7d },268 { 0x5488, 0x87 },269 { 0x5489, 0x91 },270 { 0x548a, 0x9a },271 { 0x548b, 0xaa },272 { 0x548c, 0xb8 },273 { 0x548d, 0xcd },274 { 0x548e, 0xdd },275 { 0x548f, 0xea },276 { 0x5490, 0x1d },277 { 0x5580, 0x02 },278 { 0x5583, 0x40 },279 { 0x5584, 0x10 },280 { 0x5589, 0x10 },281 { 0x558a, 0x00 },282 { 0x558b, 0xf8 },283 { 0x5800, 0x3f },284 { 0x5801, 0x16 },285 { 0x5802, 0x0e },286 { 0x5803, 0x0d },287 { 0x5804, 0x17 },288 { 0x5805, 0x3f },289 { 0x5806, 0x0b },290 { 0x5807, 0x06 },291 { 0x5808, 0x04 },292 { 0x5809, 0x04 },293 { 0x580a, 0x06 },294 { 0x580b, 0x0b },295 { 0x580c, 0x09 },296 { 0x580d, 0x03 },297 { 0x580e, 0x00 },298 { 0x580f, 0x00 },299 { 0x5810, 0x03 },300 { 0x5811, 0x08 },301 { 0x5812, 0x0a },302 { 0x5813, 0x03 },303 { 0x5814, 0x00 },304 { 0x5815, 0x00 },305 { 0x5816, 0x04 },306 { 0x5817, 0x09 },307 { 0x5818, 0x0f },308 { 0x5819, 0x08 },309 { 0x581a, 0x06 },310 { 0x581b, 0x06 },311 { 0x581c, 0x08 },312 { 0x581d, 0x0c },313 { 0x581e, 0x3f },314 { 0x581f, 0x1e },315 { 0x5820, 0x12 },316 { 0x5821, 0x13 },317 { 0x5822, 0x21 },318 { 0x5823, 0x3f },319 { 0x5824, 0x68 },320 { 0x5825, 0x28 },321 { 0x5826, 0x2c },322 { 0x5827, 0x28 },323 { 0x5828, 0x08 },324 { 0x5829, 0x48 },325 { 0x582a, 0x64 },326 { 0x582b, 0x62 },327 { 0x582c, 0x64 },328 { 0x582d, 0x28 },329 { 0x582e, 0x46 },330 { 0x582f, 0x62 },331 { 0x5830, 0x60 },332 { 0x5831, 0x62 },333 { 0x5832, 0x26 },334 { 0x5833, 0x48 },335 { 0x5834, 0x66 },336 { 0x5835, 0x44 },337 { 0x5836, 0x64 },338 { 0x5837, 0x28 },339 { 0x5838, 0x66 },340 { 0x5839, 0x48 },341 { 0x583a, 0x2c },342 { 0x583b, 0x28 },343 { 0x583c, 0x26 },344 { 0x583d, 0xae },345 { 0x5025, 0x00 },346 { 0x3a0f, 0x30 },347 { 0x3a10, 0x28 },348 { 0x3a1b, 0x30 },349 { 0x3a1e, 0x26 },350 { 0x3a11, 0x60 },351 { 0x3a1f, 0x14 },352 { 0x0601, 0x02 },353 { 0x3008, 0x42 },354 { 0x3008, 0x02 },355 { OV5645_IO_MIPI_CTRL00, 0x40 },356 { OV5645_MIPI_CTRL00, 0x24 },357 { OV5645_PAD_OUTPUT00, 0x70 }358};359 360static const struct reg_value ov5645_setting_sxga[] = {361 { 0x3612, 0xa9 },362 { 0x3614, 0x50 },363 { 0x3618, 0x00 },364 { 0x3034, 0x18 },365 { 0x3035, 0x21 },366 { 0x3036, 0x70 },367 { 0x3600, 0x09 },368 { 0x3601, 0x43 },369 { 0x3708, 0x66 },370 { 0x370c, 0xc3 },371 { 0x3800, 0x00 },372 { 0x3801, 0x00 },373 { 0x3802, 0x00 },374 { 0x3803, 0x06 },375 { 0x3804, 0x0a },376 { 0x3805, 0x3f },377 { 0x3806, 0x07 },378 { 0x3807, 0x9d },379 { 0x3808, 0x05 },380 { 0x3809, 0x00 },381 { 0x380a, 0x03 },382 { 0x380b, 0xc0 },383 { 0x380c, 0x07 },384 { 0x380d, 0x68 },385 { 0x380e, 0x03 },386 { 0x380f, 0xd8 },387 { 0x3813, 0x06 },388 { 0x3814, 0x31 },389 { 0x3815, 0x31 },390 { 0x3820, 0x47 },391 { 0x3a02, 0x03 },392 { 0x3a03, 0xd8 },393 { 0x3a08, 0x01 },394 { 0x3a09, 0xf8 },395 { 0x3a0a, 0x01 },396 { 0x3a0b, 0xa4 },397 { 0x3a0e, 0x02 },398 { 0x3a0d, 0x02 },399 { 0x3a14, 0x03 },400 { 0x3a15, 0xd8 },401 { 0x3a18, 0x00 },402 { 0x4004, 0x02 },403 { 0x4005, 0x18 },404 { 0x4300, 0x32 },405 { 0x4202, 0x00 }406};407 408static const struct reg_value ov5645_setting_1080p[] = {409 { 0x3612, 0xab },410 { 0x3614, 0x50 },411 { 0x3618, 0x04 },412 { 0x3034, 0x18 },413 { 0x3035, 0x11 },414 { 0x3036, 0x54 },415 { 0x3600, 0x08 },416 { 0x3601, 0x33 },417 { 0x3708, 0x63 },418 { 0x370c, 0xc0 },419 { 0x3800, 0x01 },420 { 0x3801, 0x50 },421 { 0x3802, 0x01 },422 { 0x3803, 0xb2 },423 { 0x3804, 0x08 },424 { 0x3805, 0xef },425 { 0x3806, 0x05 },426 { 0x3807, 0xf1 },427 { 0x3808, 0x07 },428 { 0x3809, 0x80 },429 { 0x380a, 0x04 },430 { 0x380b, 0x38 },431 { 0x380c, 0x09 },432 { 0x380d, 0xc4 },433 { 0x380e, 0x04 },434 { 0x380f, 0x60 },435 { 0x3813, 0x04 },436 { 0x3814, 0x11 },437 { 0x3815, 0x11 },438 { 0x3820, 0x47 },439 { 0x4514, 0x88 },440 { 0x3a02, 0x04 },441 { 0x3a03, 0x60 },442 { 0x3a08, 0x01 },443 { 0x3a09, 0x50 },444 { 0x3a0a, 0x01 },445 { 0x3a0b, 0x18 },446 { 0x3a0e, 0x03 },447 { 0x3a0d, 0x04 },448 { 0x3a14, 0x04 },449 { 0x3a15, 0x60 },450 { 0x3a18, 0x00 },451 { 0x4004, 0x06 },452 { 0x4005, 0x18 },453 { 0x4300, 0x32 },454 { 0x4202, 0x00 },455 { 0x4837, 0x0b }456};457 458static const struct reg_value ov5645_setting_full[] = {459 { 0x3612, 0xab },460 { 0x3614, 0x50 },461 { 0x3618, 0x04 },462 { 0x3034, 0x18 },463 { 0x3035, 0x11 },464 { 0x3036, 0x54 },465 { 0x3600, 0x08 },466 { 0x3601, 0x33 },467 { 0x3708, 0x63 },468 { 0x370c, 0xc0 },469 { 0x3800, 0x00 },470 { 0x3801, 0x00 },471 { 0x3802, 0x00 },472 { 0x3803, 0x00 },473 { 0x3804, 0x0a },474 { 0x3805, 0x3f },475 { 0x3806, 0x07 },476 { 0x3807, 0x9f },477 { 0x3808, 0x0a },478 { 0x3809, 0x20 },479 { 0x380a, 0x07 },480 { 0x380b, 0x98 },481 { 0x380c, 0x0b },482 { 0x380d, 0x1c },483 { 0x380e, 0x07 },484 { 0x380f, 0xb0 },485 { 0x3813, 0x06 },486 { 0x3814, 0x11 },487 { 0x3815, 0x11 },488 { 0x3820, 0x47 },489 { 0x4514, 0x88 },490 { 0x3a02, 0x07 },491 { 0x3a03, 0xb0 },492 { 0x3a08, 0x01 },493 { 0x3a09, 0x27 },494 { 0x3a0a, 0x00 },495 { 0x3a0b, 0xf6 },496 { 0x3a0e, 0x06 },497 { 0x3a0d, 0x08 },498 { 0x3a14, 0x07 },499 { 0x3a15, 0xb0 },500 { 0x3a18, 0x01 },501 { 0x4004, 0x06 },502 { 0x4005, 0x18 },503 { 0x4300, 0x32 },504 { 0x4837, 0x0b },505 { 0x4202, 0x00 }506};507 508static const s64 link_freq[] = {509 224000000,510 336000000511};512 513static const struct ov5645_mode_info ov5645_mode_info_data[] = {514 {515 .width = 1280,516 .height = 960,517 .data = ov5645_setting_sxga,518 .data_size = ARRAY_SIZE(ov5645_setting_sxga),519 .pixel_clock = 112000000,520 .link_freq = 0 /* an index in link_freq[] */521 },522 {523 .width = 1920,524 .height = 1080,525 .data = ov5645_setting_1080p,526 .data_size = ARRAY_SIZE(ov5645_setting_1080p),527 .pixel_clock = 168000000,528 .link_freq = 1 /* an index in link_freq[] */529 },530 {531 .width = 2592,532 .height = 1944,533 .data = ov5645_setting_full,534 .data_size = ARRAY_SIZE(ov5645_setting_full),535 .pixel_clock = 168000000,536 .link_freq = 1 /* an index in link_freq[] */537 },538};539 540static int ov5645_write_reg(struct ov5645 *ov5645, u16 reg, u8 val)541{542 u8 regbuf[3];543 int ret;544 545 regbuf[0] = reg >> 8;546 regbuf[1] = reg & 0xff;547 regbuf[2] = val;548 549 ret = i2c_master_send(ov5645->i2c_client, regbuf, 3);550 if (ret < 0) {551 dev_err(ov5645->dev, "%s: write reg error %d: reg=%x, val=%x\n",552 __func__, ret, reg, val);553 return ret;554 }555 556 return 0;557}558 559static int ov5645_read_reg(struct ov5645 *ov5645, u16 reg, u8 *val)560{561 u8 regbuf[2];562 int ret;563 564 regbuf[0] = reg >> 8;565 regbuf[1] = reg & 0xff;566 567 ret = i2c_master_send(ov5645->i2c_client, regbuf, 2);568 if (ret < 0) {569 dev_err(ov5645->dev, "%s: write reg error %d: reg=%x\n",570 __func__, ret, reg);571 return ret;572 }573 574 ret = i2c_master_recv(ov5645->i2c_client, val, 1);575 if (ret < 0) {576 dev_err(ov5645->dev, "%s: read reg error %d: reg=%x\n",577 __func__, ret, reg);578 return ret;579 }580 581 return 0;582}583 584static int ov5645_set_aec_mode(struct ov5645 *ov5645, u32 mode)585{586 u8 val = ov5645->aec_pk_manual;587 int ret;588 589 if (mode == V4L2_EXPOSURE_AUTO)590 val &= ~OV5645_AEC_MANUAL_ENABLE;591 else /* V4L2_EXPOSURE_MANUAL */592 val |= OV5645_AEC_MANUAL_ENABLE;593 594 ret = ov5645_write_reg(ov5645, OV5645_AEC_PK_MANUAL, val);595 if (!ret)596 ov5645->aec_pk_manual = val;597 598 return ret;599}600 601static int ov5645_set_agc_mode(struct ov5645 *ov5645, u32 enable)602{603 u8 val = ov5645->aec_pk_manual;604 int ret;605 606 if (enable)607 val &= ~OV5645_AGC_MANUAL_ENABLE;608 else609 val |= OV5645_AGC_MANUAL_ENABLE;610 611 ret = ov5645_write_reg(ov5645, OV5645_AEC_PK_MANUAL, val);612 if (!ret)613 ov5645->aec_pk_manual = val;614 615 return ret;616}617 618static int ov5645_set_register_array(struct ov5645 *ov5645,619 const struct reg_value *settings,620 unsigned int num_settings)621{622 unsigned int i;623 int ret;624 625 for (i = 0; i < num_settings; ++i, ++settings) {626 ret = ov5645_write_reg(ov5645, settings->reg, settings->val);627 if (ret < 0)628 return ret;629 630 if (settings->reg == OV5645_SYSTEM_CTRL0 &&631 settings->val == OV5645_SYSTEM_CTRL0_START)632 usleep_range(1000, 2000);633 }634 635 return 0;636}637 638static void __ov5645_set_power_off(struct device *dev)639{640 struct v4l2_subdev *sd = dev_get_drvdata(dev);641 struct ov5645 *ov5645 = to_ov5645(sd);642 643 ov5645_write_reg(ov5645, OV5645_IO_MIPI_CTRL00, 0x58);644 gpiod_set_value_cansleep(ov5645->rst_gpio, 1);645 gpiod_set_value_cansleep(ov5645->enable_gpio, 0);646 regulator_bulk_disable(OV5645_NUM_SUPPLIES, ov5645->supplies);647}648 649static int ov5645_set_power_off(struct device *dev)650{651 struct v4l2_subdev *sd = dev_get_drvdata(dev);652 struct ov5645 *ov5645 = to_ov5645(sd);653 654 __ov5645_set_power_off(dev);655 clk_disable_unprepare(ov5645->xclk);656 657 return 0;658}659 660static int ov5645_set_power_on(struct device *dev)661{662 struct v4l2_subdev *sd = dev_get_drvdata(dev);663 struct ov5645 *ov5645 = to_ov5645(sd);664 int ret;665 666 ret = regulator_bulk_enable(OV5645_NUM_SUPPLIES, ov5645->supplies);667 if (ret < 0)668 return ret;669 670 ret = clk_prepare_enable(ov5645->xclk);671 if (ret < 0) {672 dev_err(ov5645->dev, "clk prepare enable failed\n");673 regulator_bulk_disable(OV5645_NUM_SUPPLIES, ov5645->supplies);674 return ret;675 }676 677 usleep_range(5000, 15000);678 gpiod_set_value_cansleep(ov5645->enable_gpio, 1);679 680 usleep_range(1000, 2000);681 gpiod_set_value_cansleep(ov5645->rst_gpio, 0);682 683 msleep(20);684 685 ret = ov5645_set_register_array(ov5645, ov5645_global_init_setting,686 ARRAY_SIZE(ov5645_global_init_setting));687 if (ret < 0) {688 dev_err(ov5645->dev, "could not set init registers\n");689 goto exit;690 }691 692 usleep_range(500, 1000);693 694 return 0;695 696exit:697 __ov5645_set_power_off(dev);698 clk_disable_unprepare(ov5645->xclk);699 return ret;700}701 702static int ov5645_set_saturation(struct ov5645 *ov5645, s32 value)703{704 u32 reg_value = (value * 0x10) + 0x40;705 int ret;706 707 ret = ov5645_write_reg(ov5645, OV5645_SDE_SAT_U, reg_value);708 if (ret < 0)709 return ret;710 711 return ov5645_write_reg(ov5645, OV5645_SDE_SAT_V, reg_value);712}713 714static int ov5645_set_hflip(struct ov5645 *ov5645, s32 value)715{716 u8 val = ov5645->timing_tc_reg21;717 int ret;718 719 if (value == 0)720 val &= ~(OV5645_SENSOR_MIRROR);721 else722 val |= (OV5645_SENSOR_MIRROR);723 724 ret = ov5645_write_reg(ov5645, OV5645_TIMING_TC_REG21, val);725 if (!ret)726 ov5645->timing_tc_reg21 = val;727 728 return ret;729}730 731static int ov5645_set_vflip(struct ov5645 *ov5645, s32 value)732{733 u8 val = ov5645->timing_tc_reg20;734 int ret;735 736 if (value == 0)737 val |= (OV5645_SENSOR_VFLIP | OV5645_ISP_VFLIP);738 else739 val &= ~(OV5645_SENSOR_VFLIP | OV5645_ISP_VFLIP);740 741 ret = ov5645_write_reg(ov5645, OV5645_TIMING_TC_REG20, val);742 if (!ret)743 ov5645->timing_tc_reg20 = val;744 745 return ret;746}747 748static int ov5645_set_test_pattern(struct ov5645 *ov5645, s32 value)749{750 u8 val = 0;751 752 if (value) {753 val = OV5645_SET_TEST_PATTERN(value - 1);754 val |= OV5645_TEST_PATTERN_ENABLE;755 }756 757 return ov5645_write_reg(ov5645, OV5645_PRE_ISP_TEST_SETTING_1, val);758}759 760static const char * const ov5645_test_pattern_menu[] = {761 "Disabled",762 "Vertical Color Bars",763 "Pseudo-Random Data",764 "Color Square",765 "Black Image",766};767 768static int ov5645_set_awb(struct ov5645 *ov5645, s32 enable_auto)769{770 u8 val = 0;771 772 if (!enable_auto)773 val = OV5645_AWB_MANUAL_ENABLE;774 775 return ov5645_write_reg(ov5645, OV5645_AWB_MANUAL_CONTROL, val);776}777 778static int ov5645_s_ctrl(struct v4l2_ctrl *ctrl)779{780 struct ov5645 *ov5645 = container_of(ctrl->handler,781 struct ov5645, ctrls);782 int ret;783 784 mutex_lock(&ov5645->power_lock);785 if (!pm_runtime_get_if_in_use(ov5645->dev)) {786 mutex_unlock(&ov5645->power_lock);787 return 0;788 }789 790 switch (ctrl->id) {791 case V4L2_CID_SATURATION:792 ret = ov5645_set_saturation(ov5645, ctrl->val);793 break;794 case V4L2_CID_AUTO_WHITE_BALANCE:795 ret = ov5645_set_awb(ov5645, ctrl->val);796 break;797 case V4L2_CID_AUTOGAIN:798 ret = ov5645_set_agc_mode(ov5645, ctrl->val);799 break;800 case V4L2_CID_EXPOSURE_AUTO:801 ret = ov5645_set_aec_mode(ov5645, ctrl->val);802 break;803 case V4L2_CID_TEST_PATTERN:804 ret = ov5645_set_test_pattern(ov5645, ctrl->val);805 break;806 case V4L2_CID_HFLIP:807 ret = ov5645_set_hflip(ov5645, ctrl->val);808 break;809 case V4L2_CID_VFLIP:810 ret = ov5645_set_vflip(ov5645, ctrl->val);811 break;812 default:813 ret = -EINVAL;814 break;815 }816 817 pm_runtime_mark_last_busy(ov5645->dev);818 pm_runtime_put_autosuspend(ov5645->dev);819 mutex_unlock(&ov5645->power_lock);820 821 return ret;822}823 824static const struct v4l2_ctrl_ops ov5645_ctrl_ops = {825 .s_ctrl = ov5645_s_ctrl,826};827 828static int ov5645_enum_mbus_code(struct v4l2_subdev *sd,829 struct v4l2_subdev_state *sd_state,830 struct v4l2_subdev_mbus_code_enum *code)831{832 if (code->index > 0)833 return -EINVAL;834 835 code->code = MEDIA_BUS_FMT_UYVY8_1X16;836 837 return 0;838}839 840static int ov5645_enum_frame_size(struct v4l2_subdev *subdev,841 struct v4l2_subdev_state *sd_state,842 struct v4l2_subdev_frame_size_enum *fse)843{844 if (fse->code != MEDIA_BUS_FMT_UYVY8_1X16)845 return -EINVAL;846 847 if (fse->index >= ARRAY_SIZE(ov5645_mode_info_data))848 return -EINVAL;849 850 fse->min_width = ov5645_mode_info_data[fse->index].width;851 fse->max_width = ov5645_mode_info_data[fse->index].width;852 fse->min_height = ov5645_mode_info_data[fse->index].height;853 fse->max_height = ov5645_mode_info_data[fse->index].height;854 855 return 0;856}857 858static struct v4l2_mbus_framefmt *859__ov5645_get_pad_format(struct ov5645 *ov5645,860 struct v4l2_subdev_state *sd_state,861 unsigned int pad,862 enum v4l2_subdev_format_whence which)863{864 switch (which) {865 case V4L2_SUBDEV_FORMAT_TRY:866 return v4l2_subdev_state_get_format(sd_state, pad);867 case V4L2_SUBDEV_FORMAT_ACTIVE:868 return &ov5645->fmt;869 default:870 return NULL;871 }872}873 874static int ov5645_get_format(struct v4l2_subdev *sd,875 struct v4l2_subdev_state *sd_state,876 struct v4l2_subdev_format *format)877{878 struct ov5645 *ov5645 = to_ov5645(sd);879 880 format->format = *__ov5645_get_pad_format(ov5645, sd_state,881 format->pad,882 format->which);883 return 0;884}885 886static struct v4l2_rect *887__ov5645_get_pad_crop(struct ov5645 *ov5645,888 struct v4l2_subdev_state *sd_state,889 unsigned int pad, enum v4l2_subdev_format_whence which)890{891 switch (which) {892 case V4L2_SUBDEV_FORMAT_TRY:893 return v4l2_subdev_state_get_crop(sd_state, pad);894 case V4L2_SUBDEV_FORMAT_ACTIVE:895 return &ov5645->crop;896 default:897 return NULL;898 }899}900 901static int ov5645_set_format(struct v4l2_subdev *sd,902 struct v4l2_subdev_state *sd_state,903 struct v4l2_subdev_format *format)904{905 struct ov5645 *ov5645 = to_ov5645(sd);906 struct v4l2_mbus_framefmt *__format;907 struct v4l2_rect *__crop;908 const struct ov5645_mode_info *new_mode;909 int ret;910 911 __crop = __ov5645_get_pad_crop(ov5645, sd_state, format->pad,912 format->which);913 914 new_mode = v4l2_find_nearest_size(ov5645_mode_info_data,915 ARRAY_SIZE(ov5645_mode_info_data),916 width, height,917 format->format.width, format->format.height);918 919 __crop->width = new_mode->width;920 __crop->height = new_mode->height;921 922 if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE) {923 ret = v4l2_ctrl_s_ctrl_int64(ov5645->pixel_clock,924 new_mode->pixel_clock);925 if (ret < 0)926 return ret;927 928 ret = v4l2_ctrl_s_ctrl(ov5645->link_freq,929 new_mode->link_freq);930 if (ret < 0)931 return ret;932 933 ov5645->current_mode = new_mode;934 }935 936 __format = __ov5645_get_pad_format(ov5645, sd_state, format->pad,937 format->which);938 __format->width = __crop->width;939 __format->height = __crop->height;940 __format->code = MEDIA_BUS_FMT_UYVY8_1X16;941 __format->field = V4L2_FIELD_NONE;942 __format->colorspace = V4L2_COLORSPACE_SRGB;943 944 format->format = *__format;945 946 return 0;947}948 949static int ov5645_init_state(struct v4l2_subdev *subdev,950 struct v4l2_subdev_state *sd_state)951{952 struct v4l2_subdev_format fmt = { 0 };953 954 fmt.which = sd_state ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;955 fmt.format.width = 1920;956 fmt.format.height = 1080;957 958 ov5645_set_format(subdev, sd_state, &fmt);959 960 return 0;961}962 963static int ov5645_get_selection(struct v4l2_subdev *sd,964 struct v4l2_subdev_state *sd_state,965 struct v4l2_subdev_selection *sel)966{967 struct ov5645 *ov5645 = to_ov5645(sd);968 969 if (sel->target != V4L2_SEL_TGT_CROP)970 return -EINVAL;971 972 sel->r = *__ov5645_get_pad_crop(ov5645, sd_state, sel->pad,973 sel->which);974 return 0;975}976 977static int ov5645_s_stream(struct v4l2_subdev *subdev, int enable)978{979 struct ov5645 *ov5645 = to_ov5645(subdev);980 int ret;981 982 if (enable) {983 ret = pm_runtime_resume_and_get(ov5645->dev);984 if (ret < 0)985 return ret;986 987 ret = ov5645_set_register_array(ov5645,988 ov5645->current_mode->data,989 ov5645->current_mode->data_size);990 if (ret < 0) {991 dev_err(ov5645->dev, "could not set mode %dx%d\n",992 ov5645->current_mode->width,993 ov5645->current_mode->height);994 goto err_rpm_put;995 }996 ret = v4l2_ctrl_handler_setup(&ov5645->ctrls);997 if (ret < 0) {998 dev_err(ov5645->dev, "could not sync v4l2 controls\n");999 goto err_rpm_put;1000 }1001 1002 ret = ov5645_write_reg(ov5645, OV5645_IO_MIPI_CTRL00, 0x45);1003 if (ret < 0)1004 goto err_rpm_put;1005 1006 ret = ov5645_write_reg(ov5645, OV5645_SYSTEM_CTRL0,1007 OV5645_SYSTEM_CTRL0_START);1008 if (ret < 0)1009 goto err_rpm_put;1010 } else {1011 ret = ov5645_write_reg(ov5645, OV5645_IO_MIPI_CTRL00, 0x40);1012 if (ret < 0)1013 goto stream_off_rpm_put;1014 1015 ret = ov5645_write_reg(ov5645, OV5645_SYSTEM_CTRL0,1016 OV5645_SYSTEM_CTRL0_STOP);1017 1018 goto stream_off_rpm_put;1019 }1020 1021 return 0;1022 1023err_rpm_put:1024 pm_runtime_put_sync(ov5645->dev);1025 return ret;1026 1027stream_off_rpm_put:1028 pm_runtime_mark_last_busy(ov5645->dev);1029 pm_runtime_put_autosuspend(ov5645->dev);1030 return ret;1031}1032 1033static const struct v4l2_subdev_video_ops ov5645_video_ops = {1034 .s_stream = ov5645_s_stream,1035};1036 1037static const struct v4l2_subdev_pad_ops ov5645_subdev_pad_ops = {1038 .enum_mbus_code = ov5645_enum_mbus_code,1039 .enum_frame_size = ov5645_enum_frame_size,1040 .get_fmt = ov5645_get_format,1041 .set_fmt = ov5645_set_format,1042 .get_selection = ov5645_get_selection,1043};1044 1045static const struct v4l2_subdev_ops ov5645_subdev_ops = {1046 .video = &ov5645_video_ops,1047 .pad = &ov5645_subdev_pad_ops,1048};1049 1050static const struct v4l2_subdev_internal_ops ov5645_internal_ops = {1051 .init_state = ov5645_init_state,1052};1053 1054static int ov5645_probe(struct i2c_client *client)1055{1056 struct device *dev = &client->dev;1057 struct device_node *endpoint;1058 struct ov5645 *ov5645;1059 u8 chip_id_high, chip_id_low;1060 unsigned int i;1061 u32 xclk_freq;1062 int ret;1063 1064 ov5645 = devm_kzalloc(dev, sizeof(struct ov5645), GFP_KERNEL);1065 if (!ov5645)1066 return -ENOMEM;1067 1068 ov5645->i2c_client = client;1069 ov5645->dev = dev;1070 1071 endpoint = of_graph_get_endpoint_by_regs(dev->of_node, 0, -1);1072 if (!endpoint) {1073 dev_err(dev, "endpoint node not found\n");1074 return -EINVAL;1075 }1076 1077 ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(endpoint),1078 &ov5645->ep);1079 1080 of_node_put(endpoint);1081 1082 if (ret < 0) {1083 dev_err(dev, "parsing endpoint node failed\n");1084 return ret;1085 }1086 1087 if (ov5645->ep.bus_type != V4L2_MBUS_CSI2_DPHY) {1088 dev_err(dev, "invalid bus type, must be CSI2\n");1089 return -EINVAL;1090 }1091 1092 /* get system clock (xclk) */1093 ov5645->xclk = devm_clk_get(dev, NULL);1094 if (IS_ERR(ov5645->xclk)) {1095 dev_err(dev, "could not get xclk");1096 return PTR_ERR(ov5645->xclk);1097 }1098 1099 ret = of_property_read_u32(dev->of_node, "clock-frequency", &xclk_freq);1100 if (ret) {1101 dev_err(dev, "could not get xclk frequency\n");1102 return ret;1103 }1104 1105 /* external clock must be 24MHz, allow 1% tolerance */1106 if (xclk_freq < 23760000 || xclk_freq > 24240000) {1107 dev_err(dev, "external clock frequency %u is not supported\n",1108 xclk_freq);1109 return -EINVAL;1110 }1111 1112 ret = clk_set_rate(ov5645->xclk, xclk_freq);1113 if (ret) {1114 dev_err(dev, "could not set xclk frequency\n");1115 return ret;1116 }1117 1118 for (i = 0; i < OV5645_NUM_SUPPLIES; i++)1119 ov5645->supplies[i].supply = ov5645_supply_name[i];1120 1121 ret = devm_regulator_bulk_get(dev, OV5645_NUM_SUPPLIES,1122 ov5645->supplies);1123 if (ret < 0)1124 return ret;1125 1126 ov5645->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_HIGH);1127 if (IS_ERR(ov5645->enable_gpio)) {1128 dev_err(dev, "cannot get enable gpio\n");1129 return PTR_ERR(ov5645->enable_gpio);1130 }1131 1132 ov5645->rst_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);1133 if (IS_ERR(ov5645->rst_gpio)) {1134 dev_err(dev, "cannot get reset gpio\n");1135 return PTR_ERR(ov5645->rst_gpio);1136 }1137 1138 mutex_init(&ov5645->power_lock);1139 1140 v4l2_ctrl_handler_init(&ov5645->ctrls, 9);1141 v4l2_ctrl_new_std(&ov5645->ctrls, &ov5645_ctrl_ops,1142 V4L2_CID_SATURATION, -4, 4, 1, 0);1143 v4l2_ctrl_new_std(&ov5645->ctrls, &ov5645_ctrl_ops,1144 V4L2_CID_HFLIP, 0, 1, 1, 0);1145 v4l2_ctrl_new_std(&ov5645->ctrls, &ov5645_ctrl_ops,1146 V4L2_CID_VFLIP, 0, 1, 1, 0);1147 v4l2_ctrl_new_std(&ov5645->ctrls, &ov5645_ctrl_ops,1148 V4L2_CID_AUTOGAIN, 0, 1, 1, 1);1149 v4l2_ctrl_new_std(&ov5645->ctrls, &ov5645_ctrl_ops,1150 V4L2_CID_AUTO_WHITE_BALANCE, 0, 1, 1, 1);1151 v4l2_ctrl_new_std_menu(&ov5645->ctrls, &ov5645_ctrl_ops,1152 V4L2_CID_EXPOSURE_AUTO, V4L2_EXPOSURE_MANUAL,1153 0, V4L2_EXPOSURE_AUTO);1154 v4l2_ctrl_new_std_menu_items(&ov5645->ctrls, &ov5645_ctrl_ops,1155 V4L2_CID_TEST_PATTERN,1156 ARRAY_SIZE(ov5645_test_pattern_menu) - 1,1157 0, 0, ov5645_test_pattern_menu);1158 ov5645->pixel_clock = v4l2_ctrl_new_std(&ov5645->ctrls,1159 &ov5645_ctrl_ops,1160 V4L2_CID_PIXEL_RATE,1161 1, INT_MAX, 1, 1);1162 ov5645->link_freq = v4l2_ctrl_new_int_menu(&ov5645->ctrls,1163 &ov5645_ctrl_ops,1164 V4L2_CID_LINK_FREQ,1165 ARRAY_SIZE(link_freq) - 1,1166 0, link_freq);1167 if (ov5645->link_freq)1168 ov5645->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;1169 1170 ov5645->sd.ctrl_handler = &ov5645->ctrls;1171 1172 if (ov5645->ctrls.error) {1173 dev_err(dev, "%s: control initialization error %d\n",1174 __func__, ov5645->ctrls.error);1175 ret = ov5645->ctrls.error;1176 goto free_ctrl;1177 }1178 1179 v4l2_i2c_subdev_init(&ov5645->sd, client, &ov5645_subdev_ops);1180 ov5645->sd.internal_ops = &ov5645_internal_ops;1181 ov5645->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;1182 ov5645->pad.flags = MEDIA_PAD_FL_SOURCE;1183 ov5645->sd.dev = &client->dev;1184 ov5645->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;1185 1186 ret = media_entity_pads_init(&ov5645->sd.entity, 1, &ov5645->pad);1187 if (ret < 0) {1188 dev_err(dev, "could not register media entity\n");1189 goto free_ctrl;1190 }1191 1192 ret = ov5645_set_power_on(dev);1193 if (ret)1194 goto free_entity;1195 1196 ret = ov5645_read_reg(ov5645, OV5645_CHIP_ID_HIGH, &chip_id_high);1197 if (ret < 0 || chip_id_high != OV5645_CHIP_ID_HIGH_BYTE) {1198 dev_err(dev, "could not read ID high\n");1199 ret = -ENODEV;1200 goto power_down;1201 }1202 ret = ov5645_read_reg(ov5645, OV5645_CHIP_ID_LOW, &chip_id_low);1203 if (ret < 0 || chip_id_low != OV5645_CHIP_ID_LOW_BYTE) {1204 dev_err(dev, "could not read ID low\n");1205 ret = -ENODEV;1206 goto power_down;1207 }1208 1209 dev_info(dev, "OV5645 detected at address 0x%02x\n", client->addr);1210 1211 ret = ov5645_read_reg(ov5645, OV5645_AEC_PK_MANUAL,1212 &ov5645->aec_pk_manual);1213 if (ret < 0) {1214 dev_err(dev, "could not read AEC/AGC mode\n");1215 ret = -ENODEV;1216 goto power_down;1217 }1218 1219 ret = ov5645_read_reg(ov5645, OV5645_TIMING_TC_REG20,1220 &ov5645->timing_tc_reg20);1221 if (ret < 0) {1222 dev_err(dev, "could not read vflip value\n");1223 ret = -ENODEV;1224 goto power_down;1225 }1226 1227 ret = ov5645_read_reg(ov5645, OV5645_TIMING_TC_REG21,1228 &ov5645->timing_tc_reg21);1229 if (ret < 0) {1230 dev_err(dev, "could not read hflip value\n");1231 ret = -ENODEV;1232 goto power_down;1233 }1234 1235 pm_runtime_set_active(dev);1236 pm_runtime_get_noresume(dev);1237 pm_runtime_enable(dev);1238 1239 ov5645_init_state(&ov5645->sd, NULL);1240 1241 ret = v4l2_async_register_subdev(&ov5645->sd);1242 if (ret < 0) {1243 dev_err(dev, "could not register v4l2 device\n");1244 goto err_pm_runtime;1245 }1246 1247 pm_runtime_set_autosuspend_delay(dev, 1000);1248 pm_runtime_use_autosuspend(dev);1249 pm_runtime_mark_last_busy(dev);1250 pm_runtime_put_autosuspend(dev);1251 1252 return 0;1253 1254err_pm_runtime:1255 pm_runtime_disable(dev);1256 pm_runtime_put_noidle(dev);1257power_down:1258 ov5645_set_power_off(dev);1259free_entity:1260 media_entity_cleanup(&ov5645->sd.entity);1261free_ctrl:1262 v4l2_ctrl_handler_free(&ov5645->ctrls);1263 mutex_destroy(&ov5645->power_lock);1264 1265 return ret;1266}1267 1268static void ov5645_remove(struct i2c_client *client)1269{1270 struct v4l2_subdev *sd = i2c_get_clientdata(client);1271 struct ov5645 *ov5645 = to_ov5645(sd);1272 1273 v4l2_async_unregister_subdev(&ov5645->sd);1274 media_entity_cleanup(&ov5645->sd.entity);1275 v4l2_ctrl_handler_free(&ov5645->ctrls);1276 pm_runtime_disable(ov5645->dev);1277 if (!pm_runtime_status_suspended(ov5645->dev))1278 ov5645_set_power_off(ov5645->dev);1279 pm_runtime_set_suspended(ov5645->dev);1280 mutex_destroy(&ov5645->power_lock);1281}1282 1283static const struct i2c_device_id ov5645_id[] = {1284 { "ov5645" },1285 {}1286};1287MODULE_DEVICE_TABLE(i2c, ov5645_id);1288 1289static const struct of_device_id ov5645_of_match[] = {1290 { .compatible = "ovti,ov5645" },1291 { /* sentinel */ }1292};1293MODULE_DEVICE_TABLE(of, ov5645_of_match);1294 1295static const struct dev_pm_ops ov5645_pm_ops = {1296 SET_RUNTIME_PM_OPS(ov5645_set_power_off, ov5645_set_power_on, NULL)1297};1298 1299static struct i2c_driver ov5645_i2c_driver = {1300 .driver = {1301 .of_match_table = ov5645_of_match,1302 .name = "ov5645",1303 .pm = &ov5645_pm_ops,1304 },1305 .probe = ov5645_probe,1306 .remove = ov5645_remove,1307 .id_table = ov5645_id,1308};1309 1310module_i2c_driver(ov5645_i2c_driver);1311 1312MODULE_DESCRIPTION("Omnivision OV5645 Camera Driver");1313MODULE_AUTHOR("Todor Tomov <todor.tomov@linaro.org>");1314MODULE_LICENSE("GPL v2");1315