linux/drivers/media/i2c/soc_camera/ov5642.c
<<
>>
Prefs
   1/*
   2 * Driver for OV5642 CMOS Image Sensor from Omnivision
   3 *
   4 * Copyright (C) 2011, Bastian Hecht <hechtb@gmail.com>
   5 *
   6 * Based on Sony IMX074 Camera Driver
   7 * Copyright (C) 2010, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
   8 *
   9 * Based on Omnivision OV7670 Camera Driver
  10 * Copyright (C) 2006-7 Jonathan Corbet <corbet@lwn.net>
  11 *
  12 * This program is free software; you can redistribute it and/or modify
  13 * it under the terms of the GNU General Public License version 2 as
  14 * published by the Free Software Foundation.
  15 */
  16
  17#include <linux/bitops.h>
  18#include <linux/delay.h>
  19#include <linux/i2c.h>
  20#include <linux/kernel.h>
  21#include <linux/slab.h>
  22#include <linux/videodev2.h>
  23#include <linux/module.h>
  24#include <linux/v4l2-mediabus.h>
  25
  26#include <media/soc_camera.h>
  27#include <media/v4l2-clk.h>
  28#include <media/v4l2-subdev.h>
  29
  30/* OV5642 registers */
  31#define REG_CHIP_ID_HIGH                0x300a
  32#define REG_CHIP_ID_LOW                 0x300b
  33
  34#define REG_WINDOW_START_X_HIGH         0x3800
  35#define REG_WINDOW_START_X_LOW          0x3801
  36#define REG_WINDOW_START_Y_HIGH         0x3802
  37#define REG_WINDOW_START_Y_LOW          0x3803
  38#define REG_WINDOW_WIDTH_HIGH           0x3804
  39#define REG_WINDOW_WIDTH_LOW            0x3805
  40#define REG_WINDOW_HEIGHT_HIGH          0x3806
  41#define REG_WINDOW_HEIGHT_LOW           0x3807
  42#define REG_OUT_WIDTH_HIGH              0x3808
  43#define REG_OUT_WIDTH_LOW               0x3809
  44#define REG_OUT_HEIGHT_HIGH             0x380a
  45#define REG_OUT_HEIGHT_LOW              0x380b
  46#define REG_OUT_TOTAL_WIDTH_HIGH        0x380c
  47#define REG_OUT_TOTAL_WIDTH_LOW         0x380d
  48#define REG_OUT_TOTAL_HEIGHT_HIGH       0x380e
  49#define REG_OUT_TOTAL_HEIGHT_LOW        0x380f
  50#define REG_OUTPUT_FORMAT               0x4300
  51#define REG_ISP_CTRL_01                 0x5001
  52#define REG_AVG_WINDOW_END_X_HIGH       0x5682
  53#define REG_AVG_WINDOW_END_X_LOW        0x5683
  54#define REG_AVG_WINDOW_END_Y_HIGH       0x5686
  55#define REG_AVG_WINDOW_END_Y_LOW        0x5687
  56
  57/* active pixel array size */
  58#define OV5642_SENSOR_SIZE_X    2592
  59#define OV5642_SENSOR_SIZE_Y    1944
  60
  61/*
  62 * About OV5642 resolution, cropping and binning:
  63 * This sensor supports it all, at least in the feature description.
  64 * Unfortunately, no combination of appropriate registers settings could make
  65 * the chip work the intended way. As it works with predefined register lists,
  66 * some undocumented registers are presumably changed there to achieve their
  67 * goals.
  68 * This driver currently only works for resolutions up to 720 lines with a
  69 * 1:1 scale. Hopefully these restrictions will be removed in the future.
  70 */
  71#define OV5642_MAX_WIDTH        OV5642_SENSOR_SIZE_X
  72#define OV5642_MAX_HEIGHT       720
  73
  74/* default sizes */
  75#define OV5642_DEFAULT_WIDTH    1280
  76#define OV5642_DEFAULT_HEIGHT   OV5642_MAX_HEIGHT
  77
  78/* minimum extra blanking */
  79#define BLANKING_EXTRA_WIDTH            500
  80#define BLANKING_EXTRA_HEIGHT           20
  81
  82/*
  83 * the sensor's autoexposure is buggy when setting total_height low.
  84 * It tries to expose longer than 1 frame period without taking care of it
  85 * and this leads to weird output. So we set 1000 lines as minimum.
  86 */
  87#define BLANKING_MIN_HEIGHT             1000
  88
  89struct regval_list {
  90        u16 reg_num;
  91        u8 value;
  92};
  93
  94static struct regval_list ov5642_default_regs_init[] = {
  95        { 0x3103, 0x93 },
  96        { 0x3008, 0x82 },
  97        { 0x3017, 0x7f },
  98        { 0x3018, 0xfc },
  99        { 0x3810, 0xc2 },
 100        { 0x3615, 0xf0 },
 101        { 0x3000, 0x0  },
 102        { 0x3001, 0x0  },
 103        { 0x3002, 0x0  },
 104        { 0x3003, 0x0  },
 105        { 0x3004, 0xff },
 106        { 0x3030, 0x2b },
 107        { 0x3011, 0x8  },
 108        { 0x3010, 0x10 },
 109        { 0x3604, 0x60 },
 110        { 0x3622, 0x60 },
 111        { 0x3621, 0x9  },
 112        { 0x3709, 0x0  },
 113        { 0x4000, 0x21 },
 114        { 0x401d, 0x22 },
 115        { 0x3600, 0x54 },
 116        { 0x3605, 0x4  },
 117        { 0x3606, 0x3f },
 118        { 0x3c01, 0x80 },
 119        { 0x300d, 0x22 },
 120        { 0x3623, 0x22 },
 121        { 0x5000, 0x4f },
 122        { 0x5020, 0x4  },
 123        { 0x5181, 0x79 },
 124        { 0x5182, 0x0  },
 125        { 0x5185, 0x22 },
 126        { 0x5197, 0x1  },
 127        { 0x5500, 0xa  },
 128        { 0x5504, 0x0  },
 129        { 0x5505, 0x7f },
 130        { 0x5080, 0x8  },
 131        { 0x300e, 0x18 },
 132        { 0x4610, 0x0  },
 133        { 0x471d, 0x5  },
 134        { 0x4708, 0x6  },
 135        { 0x370c, 0xa0 },
 136        { 0x5687, 0x94 },
 137        { 0x501f, 0x0  },
 138        { 0x5000, 0x4f },
 139        { 0x5001, 0xcf },
 140        { 0x4300, 0x30 },
 141        { 0x4300, 0x30 },
 142        { 0x460b, 0x35 },
 143        { 0x471d, 0x0  },
 144        { 0x3002, 0xc  },
 145        { 0x3002, 0x0  },
 146        { 0x4713, 0x3  },
 147        { 0x471c, 0x50 },
 148        { 0x4721, 0x2  },
 149        { 0x4402, 0x90 },
 150        { 0x460c, 0x22 },
 151        { 0x3815, 0x44 },
 152        { 0x3503, 0x7  },
 153        { 0x3501, 0x73 },
 154        { 0x3502, 0x80 },
 155        { 0x350b, 0x0  },
 156        { 0x3818, 0xc8 },
 157        { 0x3824, 0x11 },
 158        { 0x3a00, 0x78 },
 159        { 0x3a1a, 0x4  },
 160        { 0x3a13, 0x30 },
 161        { 0x3a18, 0x0  },
 162        { 0x3a19, 0x7c },
 163        { 0x3a08, 0x12 },
 164        { 0x3a09, 0xc0 },
 165        { 0x3a0a, 0xf  },
 166        { 0x3a0b, 0xa0 },
 167        { 0x350c, 0x7  },
 168        { 0x350d, 0xd0 },
 169        { 0x3a0d, 0x8  },
 170        { 0x3a0e, 0x6  },
 171        { 0x3500, 0x0  },
 172        { 0x3501, 0x0  },
 173        { 0x3502, 0x0  },
 174        { 0x350a, 0x0  },
 175        { 0x350b, 0x0  },
 176        { 0x3503, 0x0  },
 177        { 0x3a0f, 0x3c },
 178        { 0x3a10, 0x32 },
 179        { 0x3a1b, 0x3c },
 180        { 0x3a1e, 0x32 },
 181        { 0x3a11, 0x80 },
 182        { 0x3a1f, 0x20 },
 183        { 0x3030, 0x2b },
 184        { 0x3a02, 0x0  },
 185        { 0x3a03, 0x7d },
 186        { 0x3a04, 0x0  },
 187        { 0x3a14, 0x0  },
 188        { 0x3a15, 0x7d },
 189        { 0x3a16, 0x0  },
 190        { 0x3a00, 0x78 },
 191        { 0x3a08, 0x9  },
 192        { 0x3a09, 0x60 },
 193        { 0x3a0a, 0x7  },
 194        { 0x3a0b, 0xd0 },
 195        { 0x3a0d, 0x10 },
 196        { 0x3a0e, 0xd  },
 197        { 0x4407, 0x4  },
 198        { 0x5193, 0x70 },
 199        { 0x589b, 0x0  },
 200        { 0x589a, 0xc0 },
 201        { 0x401e, 0x20 },
 202        { 0x4001, 0x42 },
 203        { 0x401c, 0x6  },
 204        { 0x3825, 0xac },
 205        { 0x3827, 0xc  },
 206        { 0x528a, 0x1  },
 207        { 0x528b, 0x4  },
 208        { 0x528c, 0x8  },
 209        { 0x528d, 0x10 },
 210        { 0x528e, 0x20 },
 211        { 0x528f, 0x28 },
 212        { 0x5290, 0x30 },
 213        { 0x5292, 0x0  },
 214        { 0x5293, 0x1  },
 215        { 0x5294, 0x0  },
 216        { 0x5295, 0x4  },
 217        { 0x5296, 0x0  },
 218        { 0x5297, 0x8  },
 219        { 0x5298, 0x0  },
 220        { 0x5299, 0x10 },
 221        { 0x529a, 0x0  },
 222        { 0x529b, 0x20 },
 223        { 0x529c, 0x0  },
 224        { 0x529d, 0x28 },
 225        { 0x529e, 0x0  },
 226        { 0x529f, 0x30 },
 227        { 0x5282, 0x0  },
 228        { 0x5300, 0x0  },
 229        { 0x5301, 0x20 },
 230        { 0x5302, 0x0  },
 231        { 0x5303, 0x7c },
 232        { 0x530c, 0x0  },
 233        { 0x530d, 0xc  },
 234        { 0x530e, 0x20 },
 235        { 0x530f, 0x80 },
 236        { 0x5310, 0x20 },
 237        { 0x5311, 0x80 },
 238        { 0x5308, 0x20 },
 239        { 0x5309, 0x40 },
 240        { 0x5304, 0x0  },
 241        { 0x5305, 0x30 },
 242        { 0x5306, 0x0  },
 243        { 0x5307, 0x80 },
 244        { 0x5314, 0x8  },
 245        { 0x5315, 0x20 },
 246        { 0x5319, 0x30 },
 247        { 0x5316, 0x10 },
 248        { 0x5317, 0x0  },
 249        { 0x5318, 0x2  },
 250        { 0x5380, 0x1  },
 251        { 0x5381, 0x0  },
 252        { 0x5382, 0x0  },
 253        { 0x5383, 0x4e },
 254        { 0x5384, 0x0  },
 255        { 0x5385, 0xf  },
 256        { 0x5386, 0x0  },
 257        { 0x5387, 0x0  },
 258        { 0x5388, 0x1  },
 259        { 0x5389, 0x15 },
 260        { 0x538a, 0x0  },
 261        { 0x538b, 0x31 },
 262        { 0x538c, 0x0  },
 263        { 0x538d, 0x0  },
 264        { 0x538e, 0x0  },
 265        { 0x538f, 0xf  },
 266        { 0x5390, 0x0  },
 267        { 0x5391, 0xab },
 268        { 0x5392, 0x0  },
 269        { 0x5393, 0xa2 },
 270        { 0x5394, 0x8  },
 271        { 0x5480, 0x14 },
 272        { 0x5481, 0x21 },
 273        { 0x5482, 0x36 },
 274        { 0x5483, 0x57 },
 275        { 0x5484, 0x65 },
 276        { 0x5485, 0x71 },
 277        { 0x5486, 0x7d },
 278        { 0x5487, 0x87 },
 279        { 0x5488, 0x91 },
 280        { 0x5489, 0x9a },
 281        { 0x548a, 0xaa },
 282        { 0x548b, 0xb8 },
 283        { 0x548c, 0xcd },
 284        { 0x548d, 0xdd },
 285        { 0x548e, 0xea },
 286        { 0x548f, 0x1d },
 287        { 0x5490, 0x5  },
 288        { 0x5491, 0x0  },
 289        { 0x5492, 0x4  },
 290        { 0x5493, 0x20 },
 291        { 0x5494, 0x3  },
 292        { 0x5495, 0x60 },
 293        { 0x5496, 0x2  },
 294        { 0x5497, 0xb8 },
 295        { 0x5498, 0x2  },
 296        { 0x5499, 0x86 },
 297        { 0x549a, 0x2  },
 298        { 0x549b, 0x5b },
 299        { 0x549c, 0x2  },
 300        { 0x549d, 0x3b },
 301        { 0x549e, 0x2  },
 302        { 0x549f, 0x1c },
 303        { 0x54a0, 0x2  },
 304        { 0x54a1, 0x4  },
 305        { 0x54a2, 0x1  },
 306        { 0x54a3, 0xed },
 307        { 0x54a4, 0x1  },
 308        { 0x54a5, 0xc5 },
 309        { 0x54a6, 0x1  },
 310        { 0x54a7, 0xa5 },
 311        { 0x54a8, 0x1  },
 312        { 0x54a9, 0x6c },
 313        { 0x54aa, 0x1  },
 314        { 0x54ab, 0x41 },
 315        { 0x54ac, 0x1  },
 316        { 0x54ad, 0x20 },
 317        { 0x54ae, 0x0  },
 318        { 0x54af, 0x16 },
 319        { 0x54b0, 0x1  },
 320        { 0x54b1, 0x20 },
 321        { 0x54b2, 0x0  },
 322        { 0x54b3, 0x10 },
 323        { 0x54b4, 0x0  },
 324        { 0x54b5, 0xf0 },
 325        { 0x54b6, 0x0  },
 326        { 0x54b7, 0xdf },
 327        { 0x5402, 0x3f },
 328        { 0x5403, 0x0  },
 329        { 0x3406, 0x0  },
 330        { 0x5180, 0xff },
 331        { 0x5181, 0x52 },
 332        { 0x5182, 0x11 },
 333        { 0x5183, 0x14 },
 334        { 0x5184, 0x25 },
 335        { 0x5185, 0x24 },
 336        { 0x5186, 0x6  },
 337        { 0x5187, 0x8  },
 338        { 0x5188, 0x8  },
 339        { 0x5189, 0x7c },
 340        { 0x518a, 0x60 },
 341        { 0x518b, 0xb2 },
 342        { 0x518c, 0xb2 },
 343        { 0x518d, 0x44 },
 344        { 0x518e, 0x3d },
 345        { 0x518f, 0x58 },
 346        { 0x5190, 0x46 },
 347        { 0x5191, 0xf8 },
 348        { 0x5192, 0x4  },
 349        { 0x5193, 0x70 },
 350        { 0x5194, 0xf0 },
 351        { 0x5195, 0xf0 },
 352        { 0x5196, 0x3  },
 353        { 0x5197, 0x1  },
 354        { 0x5198, 0x4  },
 355        { 0x5199, 0x12 },
 356        { 0x519a, 0x4  },
 357        { 0x519b, 0x0  },
 358        { 0x519c, 0x6  },
 359        { 0x519d, 0x82 },
 360        { 0x519e, 0x0  },
 361        { 0x5025, 0x80 },
 362        { 0x3a0f, 0x38 },
 363        { 0x3a10, 0x30 },
 364        { 0x3a1b, 0x3a },
 365        { 0x3a1e, 0x2e },
 366        { 0x3a11, 0x60 },
 367        { 0x3a1f, 0x10 },
 368        { 0x5688, 0xa6 },
 369        { 0x5689, 0x6a },
 370        { 0x568a, 0xea },
 371        { 0x568b, 0xae },
 372        { 0x568c, 0xa6 },
 373        { 0x568d, 0x6a },
 374        { 0x568e, 0x62 },
 375        { 0x568f, 0x26 },
 376        { 0x5583, 0x40 },
 377        { 0x5584, 0x40 },
 378        { 0x5580, 0x2  },
 379        { 0x5000, 0xcf },
 380        { 0x5800, 0x27 },
 381        { 0x5801, 0x19 },
 382        { 0x5802, 0x12 },
 383        { 0x5803, 0xf  },
 384        { 0x5804, 0x10 },
 385        { 0x5805, 0x15 },
 386        { 0x5806, 0x1e },
 387        { 0x5807, 0x2f },
 388        { 0x5808, 0x15 },
 389        { 0x5809, 0xd  },
 390        { 0x580a, 0xa  },
 391        { 0x580b, 0x9  },
 392        { 0x580c, 0xa  },
 393        { 0x580d, 0xc  },
 394        { 0x580e, 0x12 },
 395        { 0x580f, 0x19 },
 396        { 0x5810, 0xb  },
 397        { 0x5811, 0x7  },
 398        { 0x5812, 0x4  },
 399        { 0x5813, 0x3  },
 400        { 0x5814, 0x3  },
 401        { 0x5815, 0x6  },
 402        { 0x5816, 0xa  },
 403        { 0x5817, 0xf  },
 404        { 0x5818, 0xa  },
 405        { 0x5819, 0x5  },
 406        { 0x581a, 0x1  },
 407        { 0x581b, 0x0  },
 408        { 0x581c, 0x0  },
 409        { 0x581d, 0x3  },
 410        { 0x581e, 0x8  },
 411        { 0x581f, 0xc  },
 412        { 0x5820, 0xa  },
 413        { 0x5821, 0x5  },
 414        { 0x5822, 0x1  },
 415        { 0x5823, 0x0  },
 416        { 0x5824, 0x0  },
 417        { 0x5825, 0x3  },
 418        { 0x5826, 0x8  },
 419        { 0x5827, 0xc  },
 420        { 0x5828, 0xe  },
 421        { 0x5829, 0x8  },
 422        { 0x582a, 0x6  },
 423        { 0x582b, 0x4  },
 424        { 0x582c, 0x5  },
 425        { 0x582d, 0x7  },
 426        { 0x582e, 0xb  },
 427        { 0x582f, 0x12 },
 428        { 0x5830, 0x18 },
 429        { 0x5831, 0x10 },
 430        { 0x5832, 0xc  },
 431        { 0x5833, 0xa  },
 432        { 0x5834, 0xb  },
 433        { 0x5835, 0xe  },
 434        { 0x5836, 0x15 },
 435        { 0x5837, 0x19 },
 436        { 0x5838, 0x32 },
 437        { 0x5839, 0x1f },
 438        { 0x583a, 0x18 },
 439        { 0x583b, 0x16 },
 440        { 0x583c, 0x17 },
 441        { 0x583d, 0x1e },
 442        { 0x583e, 0x26 },
 443        { 0x583f, 0x53 },
 444        { 0x5840, 0x10 },
 445        { 0x5841, 0xf  },
 446        { 0x5842, 0xd  },
 447        { 0x5843, 0xc  },
 448        { 0x5844, 0xe  },
 449        { 0x5845, 0x9  },
 450        { 0x5846, 0x11 },
 451        { 0x5847, 0x10 },
 452        { 0x5848, 0x10 },
 453        { 0x5849, 0x10 },
 454        { 0x584a, 0x10 },
 455        { 0x584b, 0xe  },
 456        { 0x584c, 0x10 },
 457        { 0x584d, 0x10 },
 458        { 0x584e, 0x11 },
 459        { 0x584f, 0x10 },
 460        { 0x5850, 0xf  },
 461        { 0x5851, 0xc  },
 462        { 0x5852, 0xf  },
 463        { 0x5853, 0x10 },
 464        { 0x5854, 0x10 },
 465        { 0x5855, 0xf  },
 466        { 0x5856, 0xe  },
 467        { 0x5857, 0xb  },
 468        { 0x5858, 0x10 },
 469        { 0x5859, 0xd  },
 470        { 0x585a, 0xd  },
 471        { 0x585b, 0xc  },
 472        { 0x585c, 0xc  },
 473        { 0x585d, 0xc  },
 474        { 0x585e, 0xb  },
 475        { 0x585f, 0xc  },
 476        { 0x5860, 0xc  },
 477        { 0x5861, 0xc  },
 478        { 0x5862, 0xd  },
 479        { 0x5863, 0x8  },
 480        { 0x5864, 0x11 },
 481        { 0x5865, 0x18 },
 482        { 0x5866, 0x18 },
 483        { 0x5867, 0x19 },
 484        { 0x5868, 0x17 },
 485        { 0x5869, 0x19 },
 486        { 0x586a, 0x16 },
 487        { 0x586b, 0x13 },
 488        { 0x586c, 0x13 },
 489        { 0x586d, 0x12 },
 490        { 0x586e, 0x13 },
 491        { 0x586f, 0x16 },
 492        { 0x5870, 0x14 },
 493        { 0x5871, 0x12 },
 494        { 0x5872, 0x10 },
 495        { 0x5873, 0x11 },
 496        { 0x5874, 0x11 },
 497        { 0x5875, 0x16 },
 498        { 0x5876, 0x14 },
 499        { 0x5877, 0x11 },
 500        { 0x5878, 0x10 },
 501        { 0x5879, 0xf  },
 502        { 0x587a, 0x10 },
 503        { 0x587b, 0x14 },
 504        { 0x587c, 0x13 },
 505        { 0x587d, 0x12 },
 506        { 0x587e, 0x11 },
 507        { 0x587f, 0x11 },
 508        { 0x5880, 0x12 },
 509        { 0x5881, 0x15 },
 510        { 0x5882, 0x14 },
 511        { 0x5883, 0x15 },
 512        { 0x5884, 0x15 },
 513        { 0x5885, 0x15 },
 514        { 0x5886, 0x13 },
 515        { 0x5887, 0x17 },
 516        { 0x3710, 0x10 },
 517        { 0x3632, 0x51 },
 518        { 0x3702, 0x10 },
 519        { 0x3703, 0xb2 },
 520        { 0x3704, 0x18 },
 521        { 0x370b, 0x40 },
 522        { 0x370d, 0x3  },
 523        { 0x3631, 0x1  },
 524        { 0x3632, 0x52 },
 525        { 0x3606, 0x24 },
 526        { 0x3620, 0x96 },
 527        { 0x5785, 0x7  },
 528        { 0x3a13, 0x30 },
 529        { 0x3600, 0x52 },
 530        { 0x3604, 0x48 },
 531        { 0x3606, 0x1b },
 532        { 0x370d, 0xb  },
 533        { 0x370f, 0xc0 },
 534        { 0x3709, 0x1  },
 535        { 0x3823, 0x0  },
 536        { 0x5007, 0x0  },
 537        { 0x5009, 0x0  },
 538        { 0x5011, 0x0  },
 539        { 0x5013, 0x0  },
 540        { 0x519e, 0x0  },
 541        { 0x5086, 0x0  },
 542        { 0x5087, 0x0  },
 543        { 0x5088, 0x0  },
 544        { 0x5089, 0x0  },
 545        { 0x302b, 0x0  },
 546        { 0x3503, 0x7  },
 547        { 0x3011, 0x8  },
 548        { 0x350c, 0x2  },
 549        { 0x350d, 0xe4 },
 550        { 0x3621, 0xc9 },
 551        { 0x370a, 0x81 },
 552        { 0xffff, 0xff },
 553};
 554
 555static struct regval_list ov5642_default_regs_finalise[] = {
 556        { 0x3810, 0xc2 },
 557        { 0x3818, 0xc9 },
 558        { 0x381c, 0x10 },
 559        { 0x381d, 0xa0 },
 560        { 0x381e, 0x5  },
 561        { 0x381f, 0xb0 },
 562        { 0x3820, 0x0  },
 563        { 0x3821, 0x0  },
 564        { 0x3824, 0x11 },
 565        { 0x3a08, 0x1b },
 566        { 0x3a09, 0xc0 },
 567        { 0x3a0a, 0x17 },
 568        { 0x3a0b, 0x20 },
 569        { 0x3a0d, 0x2  },
 570        { 0x3a0e, 0x1  },
 571        { 0x401c, 0x4  },
 572        { 0x5682, 0x5  },
 573        { 0x5683, 0x0  },
 574        { 0x5686, 0x2  },
 575        { 0x5687, 0xcc },
 576        { 0x5001, 0x4f },
 577        { 0x589b, 0x6  },
 578        { 0x589a, 0xc5 },
 579        { 0x3503, 0x0  },
 580        { 0x460c, 0x20 },
 581        { 0x460b, 0x37 },
 582        { 0x471c, 0xd0 },
 583        { 0x471d, 0x5  },
 584        { 0x3815, 0x1  },
 585        { 0x3818, 0xc1 },
 586        { 0x501f, 0x0  },
 587        { 0x5002, 0xe0 },
 588        { 0x4300, 0x32 }, /* UYVY */
 589        { 0x3002, 0x1c },
 590        { 0x4800, 0x14 },
 591        { 0x4801, 0xf  },
 592        { 0x3007, 0x3b },
 593        { 0x300e, 0x4  },
 594        { 0x4803, 0x50 },
 595        { 0x3815, 0x1  },
 596        { 0x4713, 0x2  },
 597        { 0x4842, 0x1  },
 598        { 0x300f, 0xe  },
 599        { 0x3003, 0x3  },
 600        { 0x3003, 0x1  },
 601        { 0xffff, 0xff },
 602};
 603
 604struct ov5642_datafmt {
 605        u32     code;
 606        enum v4l2_colorspace            colorspace;
 607};
 608
 609struct ov5642 {
 610        struct v4l2_subdev              subdev;
 611        const struct ov5642_datafmt     *fmt;
 612        struct v4l2_rect                crop_rect;
 613        struct v4l2_clk                 *clk;
 614
 615        /* blanking information */
 616        int total_width;
 617        int total_height;
 618};
 619
 620static const struct ov5642_datafmt ov5642_colour_fmts[] = {
 621        {MEDIA_BUS_FMT_UYVY8_2X8, V4L2_COLORSPACE_JPEG},
 622};
 623
 624static struct ov5642 *to_ov5642(const struct i2c_client *client)
 625{
 626        return container_of(i2c_get_clientdata(client), struct ov5642, subdev);
 627}
 628
 629/* Find a data format by a pixel code in an array */
 630static const struct ov5642_datafmt
 631                        *ov5642_find_datafmt(u32 code)
 632{
 633        int i;
 634
 635        for (i = 0; i < ARRAY_SIZE(ov5642_colour_fmts); i++)
 636                if (ov5642_colour_fmts[i].code == code)
 637                        return ov5642_colour_fmts + i;
 638
 639        return NULL;
 640}
 641
 642static int reg_read(struct i2c_client *client, u16 reg, u8 *val)
 643{
 644        int ret;
 645        /* We have 16-bit i2c addresses - care for endianness */
 646        unsigned char data[2] = { reg >> 8, reg & 0xff };
 647
 648        ret = i2c_master_send(client, data, 2);
 649        if (ret < 2) {
 650                dev_err(&client->dev, "%s: i2c read error, reg: %x\n",
 651                        __func__, reg);
 652                return ret < 0 ? ret : -EIO;
 653        }
 654
 655        ret = i2c_master_recv(client, val, 1);
 656        if (ret < 1) {
 657                dev_err(&client->dev, "%s: i2c read error, reg: %x\n",
 658                                __func__, reg);
 659                return ret < 0 ? ret : -EIO;
 660        }
 661        return 0;
 662}
 663
 664static int reg_write(struct i2c_client *client, u16 reg, u8 val)
 665{
 666        int ret;
 667        unsigned char data[3] = { reg >> 8, reg & 0xff, val };
 668
 669        ret = i2c_master_send(client, data, 3);
 670        if (ret < 3) {
 671                dev_err(&client->dev, "%s: i2c write error, reg: %x\n",
 672                        __func__, reg);
 673                return ret < 0 ? ret : -EIO;
 674        }
 675
 676        return 0;
 677}
 678
 679/*
 680 * convenience function to write 16 bit register values that are split up
 681 * into two consecutive high and low parts
 682 */
 683static int reg_write16(struct i2c_client *client, u16 reg, u16 val16)
 684{
 685        int ret;
 686
 687        ret = reg_write(client, reg, val16 >> 8);
 688        if (ret)
 689                return ret;
 690        return reg_write(client, reg + 1, val16 & 0x00ff);
 691}
 692
 693#ifdef CONFIG_VIDEO_ADV_DEBUG
 694static int ov5642_get_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
 695{
 696        struct i2c_client *client = v4l2_get_subdevdata(sd);
 697        int ret;
 698        u8 val;
 699
 700        if (reg->reg & ~0xffff)
 701                return -EINVAL;
 702
 703        reg->size = 1;
 704
 705        ret = reg_read(client, reg->reg, &val);
 706        if (!ret)
 707                reg->val = (__u64)val;
 708
 709        return ret;
 710}
 711
 712static int ov5642_set_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg)
 713{
 714        struct i2c_client *client = v4l2_get_subdevdata(sd);
 715
 716        if (reg->reg & ~0xffff || reg->val & ~0xff)
 717                return -EINVAL;
 718
 719        return reg_write(client, reg->reg, reg->val);
 720}
 721#endif
 722
 723static int ov5642_write_array(struct i2c_client *client,
 724                                struct regval_list *vals)
 725{
 726        while (vals->reg_num != 0xffff || vals->value != 0xff) {
 727                int ret = reg_write(client, vals->reg_num, vals->value);
 728                if (ret < 0)
 729                        return ret;
 730                vals++;
 731        }
 732        dev_dbg(&client->dev, "Register list loaded\n");
 733        return 0;
 734}
 735
 736static int ov5642_set_resolution(struct v4l2_subdev *sd)
 737{
 738        struct i2c_client *client = v4l2_get_subdevdata(sd);
 739        struct ov5642 *priv = to_ov5642(client);
 740        int width = priv->crop_rect.width;
 741        int height = priv->crop_rect.height;
 742        int total_width = priv->total_width;
 743        int total_height = priv->total_height;
 744        int start_x = (OV5642_SENSOR_SIZE_X - width) / 2;
 745        int start_y = (OV5642_SENSOR_SIZE_Y - height) / 2;
 746        int ret;
 747
 748        /*
 749         * This should set the starting point for cropping.
 750         * Doesn't work so far.
 751         */
 752        ret = reg_write16(client, REG_WINDOW_START_X_HIGH, start_x);
 753        if (!ret)
 754                ret = reg_write16(client, REG_WINDOW_START_Y_HIGH, start_y);
 755        if (!ret) {
 756                priv->crop_rect.left = start_x;
 757                priv->crop_rect.top = start_y;
 758        }
 759
 760        if (!ret)
 761                ret = reg_write16(client, REG_WINDOW_WIDTH_HIGH, width);
 762        if (!ret)
 763                ret = reg_write16(client, REG_WINDOW_HEIGHT_HIGH, height);
 764        if (ret)
 765                return ret;
 766        priv->crop_rect.width = width;
 767        priv->crop_rect.height = height;
 768
 769        /* Set the output window size. Only 1:1 scale is supported so far. */
 770        ret = reg_write16(client, REG_OUT_WIDTH_HIGH, width);
 771        if (!ret)
 772                ret = reg_write16(client, REG_OUT_HEIGHT_HIGH, height);
 773
 774        /* Total width = output size + blanking */
 775        if (!ret)
 776                ret = reg_write16(client, REG_OUT_TOTAL_WIDTH_HIGH, total_width);
 777        if (!ret)
 778                ret = reg_write16(client, REG_OUT_TOTAL_HEIGHT_HIGH, total_height);
 779
 780        /* Sets the window for AWB calculations */
 781        if (!ret)
 782                ret = reg_write16(client, REG_AVG_WINDOW_END_X_HIGH, width);
 783        if (!ret)
 784                ret = reg_write16(client, REG_AVG_WINDOW_END_Y_HIGH, height);
 785
 786        return ret;
 787}
 788
 789static int ov5642_set_fmt(struct v4l2_subdev *sd,
 790                struct v4l2_subdev_pad_config *cfg,
 791                struct v4l2_subdev_format *format)
 792{
 793        struct v4l2_mbus_framefmt *mf = &format->format;
 794        struct i2c_client *client = v4l2_get_subdevdata(sd);
 795        struct ov5642 *priv = to_ov5642(client);
 796        const struct ov5642_datafmt *fmt = ov5642_find_datafmt(mf->code);
 797
 798        if (format->pad)
 799                return -EINVAL;
 800
 801        mf->width = priv->crop_rect.width;
 802        mf->height = priv->crop_rect.height;
 803
 804        if (!fmt) {
 805                if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE)
 806                        return -EINVAL;
 807                mf->code        = ov5642_colour_fmts[0].code;
 808                mf->colorspace  = ov5642_colour_fmts[0].colorspace;
 809        }
 810
 811        mf->field       = V4L2_FIELD_NONE;
 812
 813        if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE)
 814                priv->fmt = ov5642_find_datafmt(mf->code);
 815        else
 816                cfg->try_fmt = *mf;
 817        return 0;
 818}
 819
 820static int ov5642_get_fmt(struct v4l2_subdev *sd,
 821                struct v4l2_subdev_pad_config *cfg,
 822                struct v4l2_subdev_format *format)
 823{
 824        struct v4l2_mbus_framefmt *mf = &format->format;
 825        struct i2c_client *client = v4l2_get_subdevdata(sd);
 826        struct ov5642 *priv = to_ov5642(client);
 827
 828        const struct ov5642_datafmt *fmt = priv->fmt;
 829
 830        if (format->pad)
 831                return -EINVAL;
 832
 833        mf->code        = fmt->code;
 834        mf->colorspace  = fmt->colorspace;
 835        mf->width       = priv->crop_rect.width;
 836        mf->height      = priv->crop_rect.height;
 837        mf->field       = V4L2_FIELD_NONE;
 838
 839        return 0;
 840}
 841
 842static int ov5642_enum_mbus_code(struct v4l2_subdev *sd,
 843                struct v4l2_subdev_pad_config *cfg,
 844                struct v4l2_subdev_mbus_code_enum *code)
 845{
 846        if (code->pad || code->index >= ARRAY_SIZE(ov5642_colour_fmts))
 847                return -EINVAL;
 848
 849        code->code = ov5642_colour_fmts[code->index].code;
 850        return 0;
 851}
 852
 853static int ov5642_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a)
 854{
 855        struct i2c_client *client = v4l2_get_subdevdata(sd);
 856        struct ov5642 *priv = to_ov5642(client);
 857        struct v4l2_rect rect = a->c;
 858        int ret;
 859
 860        v4l_bound_align_image(&rect.width, 48, OV5642_MAX_WIDTH, 1,
 861                              &rect.height, 32, OV5642_MAX_HEIGHT, 1, 0);
 862
 863        priv->crop_rect.width   = rect.width;
 864        priv->crop_rect.height  = rect.height;
 865        priv->total_width       = rect.width + BLANKING_EXTRA_WIDTH;
 866        priv->total_height      = max_t(int, rect.height +
 867                                                        BLANKING_EXTRA_HEIGHT,
 868                                                        BLANKING_MIN_HEIGHT);
 869        priv->crop_rect.width           = rect.width;
 870        priv->crop_rect.height          = rect.height;
 871
 872        ret = ov5642_write_array(client, ov5642_default_regs_init);
 873        if (!ret)
 874                ret = ov5642_set_resolution(sd);
 875        if (!ret)
 876                ret = ov5642_write_array(client, ov5642_default_regs_finalise);
 877
 878        return ret;
 879}
 880
 881static int ov5642_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
 882{
 883        struct i2c_client *client = v4l2_get_subdevdata(sd);
 884        struct ov5642 *priv = to_ov5642(client);
 885        struct v4l2_rect *rect = &a->c;
 886
 887        if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
 888                return -EINVAL;
 889
 890        *rect = priv->crop_rect;
 891
 892        return 0;
 893}
 894
 895static int ov5642_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
 896{
 897        a->bounds.left                  = 0;
 898        a->bounds.top                   = 0;
 899        a->bounds.width                 = OV5642_MAX_WIDTH;
 900        a->bounds.height                = OV5642_MAX_HEIGHT;
 901        a->defrect                      = a->bounds;
 902        a->type                         = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 903        a->pixelaspect.numerator        = 1;
 904        a->pixelaspect.denominator      = 1;
 905
 906        return 0;
 907}
 908
 909static int ov5642_g_mbus_config(struct v4l2_subdev *sd,
 910                                struct v4l2_mbus_config *cfg)
 911{
 912        cfg->type = V4L2_MBUS_CSI2;
 913        cfg->flags = V4L2_MBUS_CSI2_2_LANE | V4L2_MBUS_CSI2_CHANNEL_0 |
 914                                        V4L2_MBUS_CSI2_CONTINUOUS_CLOCK;
 915
 916        return 0;
 917}
 918
 919static int ov5642_s_power(struct v4l2_subdev *sd, int on)
 920{
 921        struct i2c_client *client = v4l2_get_subdevdata(sd);
 922        struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client);
 923        struct ov5642 *priv = to_ov5642(client);
 924        int ret;
 925
 926        if (!on)
 927                return soc_camera_power_off(&client->dev, ssdd, priv->clk);
 928
 929        ret = soc_camera_power_on(&client->dev, ssdd, priv->clk);
 930        if (ret < 0)
 931                return ret;
 932
 933        ret = ov5642_write_array(client, ov5642_default_regs_init);
 934        if (!ret)
 935                ret = ov5642_set_resolution(sd);
 936        if (!ret)
 937                ret = ov5642_write_array(client, ov5642_default_regs_finalise);
 938
 939        return ret;
 940}
 941
 942static struct v4l2_subdev_video_ops ov5642_subdev_video_ops = {
 943        .s_crop         = ov5642_s_crop,
 944        .g_crop         = ov5642_g_crop,
 945        .cropcap        = ov5642_cropcap,
 946        .g_mbus_config  = ov5642_g_mbus_config,
 947};
 948
 949static const struct v4l2_subdev_pad_ops ov5642_subdev_pad_ops = {
 950        .enum_mbus_code = ov5642_enum_mbus_code,
 951        .get_fmt        = ov5642_get_fmt,
 952        .set_fmt        = ov5642_set_fmt,
 953};
 954
 955static struct v4l2_subdev_core_ops ov5642_subdev_core_ops = {
 956        .s_power        = ov5642_s_power,
 957#ifdef CONFIG_VIDEO_ADV_DEBUG
 958        .g_register     = ov5642_get_register,
 959        .s_register     = ov5642_set_register,
 960#endif
 961};
 962
 963static struct v4l2_subdev_ops ov5642_subdev_ops = {
 964        .core   = &ov5642_subdev_core_ops,
 965        .video  = &ov5642_subdev_video_ops,
 966        .pad    = &ov5642_subdev_pad_ops,
 967};
 968
 969static int ov5642_video_probe(struct i2c_client *client)
 970{
 971        struct v4l2_subdev *subdev = i2c_get_clientdata(client);
 972        int ret;
 973        u8 id_high, id_low;
 974        u16 id;
 975
 976        ret = ov5642_s_power(subdev, 1);
 977        if (ret < 0)
 978                return ret;
 979
 980        /* Read sensor Model ID */
 981        ret = reg_read(client, REG_CHIP_ID_HIGH, &id_high);
 982        if (ret < 0)
 983                goto done;
 984
 985        id = id_high << 8;
 986
 987        ret = reg_read(client, REG_CHIP_ID_LOW, &id_low);
 988        if (ret < 0)
 989                goto done;
 990
 991        id |= id_low;
 992
 993        dev_info(&client->dev, "Chip ID 0x%04x detected\n", id);
 994
 995        if (id != 0x5642) {
 996                ret = -ENODEV;
 997                goto done;
 998        }
 999
1000        ret = 0;
1001
1002done:
1003        ov5642_s_power(subdev, 0);
1004        return ret;
1005}
1006
1007static int ov5642_probe(struct i2c_client *client,
1008                        const struct i2c_device_id *did)
1009{
1010        struct ov5642 *priv;
1011        struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client);
1012        int ret;
1013
1014        if (!ssdd) {
1015                dev_err(&client->dev, "OV5642: missing platform data!\n");
1016                return -EINVAL;
1017        }
1018
1019        priv = devm_kzalloc(&client->dev, sizeof(struct ov5642), GFP_KERNEL);
1020        if (!priv)
1021                return -ENOMEM;
1022
1023        v4l2_i2c_subdev_init(&priv->subdev, client, &ov5642_subdev_ops);
1024
1025        priv->fmt               = &ov5642_colour_fmts[0];
1026
1027        priv->crop_rect.width   = OV5642_DEFAULT_WIDTH;
1028        priv->crop_rect.height  = OV5642_DEFAULT_HEIGHT;
1029        priv->crop_rect.left    = (OV5642_MAX_WIDTH - OV5642_DEFAULT_WIDTH) / 2;
1030        priv->crop_rect.top     = (OV5642_MAX_HEIGHT - OV5642_DEFAULT_HEIGHT) / 2;
1031        priv->total_width = OV5642_DEFAULT_WIDTH + BLANKING_EXTRA_WIDTH;
1032        priv->total_height = BLANKING_MIN_HEIGHT;
1033
1034        priv->clk = v4l2_clk_get(&client->dev, "mclk");
1035        if (IS_ERR(priv->clk))
1036                return PTR_ERR(priv->clk);
1037
1038        ret = ov5642_video_probe(client);
1039        if (ret < 0)
1040                v4l2_clk_put(priv->clk);
1041
1042        return ret;
1043}
1044
1045static int ov5642_remove(struct i2c_client *client)
1046{
1047        struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client);
1048        struct ov5642 *priv = to_ov5642(client);
1049
1050        v4l2_clk_put(priv->clk);
1051        if (ssdd->free_bus)
1052                ssdd->free_bus(ssdd);
1053
1054        return 0;
1055}
1056
1057static const struct i2c_device_id ov5642_id[] = {
1058        { "ov5642", 0 },
1059        { }
1060};
1061MODULE_DEVICE_TABLE(i2c, ov5642_id);
1062
1063static struct i2c_driver ov5642_i2c_driver = {
1064        .driver = {
1065                .name = "ov5642",
1066        },
1067        .probe          = ov5642_probe,
1068        .remove         = ov5642_remove,
1069        .id_table       = ov5642_id,
1070};
1071
1072module_i2c_driver(ov5642_i2c_driver);
1073
1074MODULE_DESCRIPTION("Omnivision OV5642 Camera driver");
1075MODULE_AUTHOR("Bastian Hecht <hechtb@gmail.com>");
1076MODULE_LICENSE("GPL v2");
1077