linux/drivers/media/i2c/imx319.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2// Copyright (C) 2018 Intel Corporation
   3
   4#include <asm/unaligned.h>
   5#include <linux/acpi.h>
   6#include <linux/i2c.h>
   7#include <linux/module.h>
   8#include <linux/pm_runtime.h>
   9#include <media/v4l2-ctrls.h>
  10#include <media/v4l2-device.h>
  11#include <media/v4l2-event.h>
  12#include <media/v4l2-fwnode.h>
  13
  14#define IMX319_REG_MODE_SELECT          0x0100
  15#define IMX319_MODE_STANDBY             0x00
  16#define IMX319_MODE_STREAMING           0x01
  17
  18/* Chip ID */
  19#define IMX319_REG_CHIP_ID              0x0016
  20#define IMX319_CHIP_ID                  0x0319
  21
  22/* V_TIMING internal */
  23#define IMX319_REG_FLL                  0x0340
  24#define IMX319_FLL_MAX                  0xffff
  25
  26/* Exposure control */
  27#define IMX319_REG_EXPOSURE             0x0202
  28#define IMX319_EXPOSURE_MIN             1
  29#define IMX319_EXPOSURE_STEP            1
  30#define IMX319_EXPOSURE_DEFAULT         0x04f6
  31
  32/*
  33 *  the digital control register for all color control looks like:
  34 *  +-----------------+------------------+
  35 *  |      [7:0]      |       [15:8]     |
  36 *  +-----------------+------------------+
  37 *  |     0x020f      |       0x020e     |
  38 *  --------------------------------------
  39 *  it is used to calculate the digital gain times value(integral + fractional)
  40 *  the [15:8] bits is the fractional part and [7:0] bits is the integral
  41 *  calculation equation is:
  42 *      gain value (unit: times) = REG[15:8] + REG[7:0]/0x100
  43 *  Only value in 0x0100 ~ 0x0FFF range is allowed.
  44 *  Analog gain use 10 bits in the registers and allowed range is 0 ~ 960
  45 */
  46/* Analog gain control */
  47#define IMX319_REG_ANALOG_GAIN          0x0204
  48#define IMX319_ANA_GAIN_MIN             0
  49#define IMX319_ANA_GAIN_MAX             960
  50#define IMX319_ANA_GAIN_STEP            1
  51#define IMX319_ANA_GAIN_DEFAULT         0
  52
  53/* Digital gain control */
  54#define IMX319_REG_DPGA_USE_GLOBAL_GAIN 0x3ff9
  55#define IMX319_REG_DIG_GAIN_GLOBAL      0x020e
  56#define IMX319_DGTL_GAIN_MIN            256
  57#define IMX319_DGTL_GAIN_MAX            4095
  58#define IMX319_DGTL_GAIN_STEP           1
  59#define IMX319_DGTL_GAIN_DEFAULT        256
  60
  61/* Test Pattern Control */
  62#define IMX319_REG_TEST_PATTERN         0x0600
  63#define IMX319_TEST_PATTERN_DISABLED            0
  64#define IMX319_TEST_PATTERN_SOLID_COLOR         1
  65#define IMX319_TEST_PATTERN_COLOR_BARS          2
  66#define IMX319_TEST_PATTERN_GRAY_COLOR_BARS     3
  67#define IMX319_TEST_PATTERN_PN9                 4
  68
  69/* Flip Control */
  70#define IMX319_REG_ORIENTATION          0x0101
  71
  72/* default link frequency and external clock */
  73#define IMX319_LINK_FREQ_DEFAULT        482400000
  74#define IMX319_EXT_CLK                  19200000
  75#define IMX319_LINK_FREQ_INDEX          0
  76
  77struct imx319_reg {
  78        u16 address;
  79        u8 val;
  80};
  81
  82struct imx319_reg_list {
  83        u32 num_of_regs;
  84        const struct imx319_reg *regs;
  85};
  86
  87/* Mode : resolution and related config&values */
  88struct imx319_mode {
  89        /* Frame width */
  90        u32 width;
  91        /* Frame height */
  92        u32 height;
  93
  94        /* V-timing */
  95        u32 fll_def;
  96        u32 fll_min;
  97
  98        /* H-timing */
  99        u32 llp;
 100
 101        /* index of link frequency */
 102        u32 link_freq_index;
 103
 104        /* Default register values */
 105        struct imx319_reg_list reg_list;
 106};
 107
 108struct imx319_hwcfg {
 109        u32 ext_clk;                    /* sensor external clk */
 110        s64 *link_freqs;                /* CSI-2 link frequencies */
 111        unsigned int nr_of_link_freqs;
 112};
 113
 114struct imx319 {
 115        struct v4l2_subdev sd;
 116        struct media_pad pad;
 117
 118        struct v4l2_ctrl_handler ctrl_handler;
 119        /* V4L2 Controls */
 120        struct v4l2_ctrl *link_freq;
 121        struct v4l2_ctrl *pixel_rate;
 122        struct v4l2_ctrl *vblank;
 123        struct v4l2_ctrl *hblank;
 124        struct v4l2_ctrl *exposure;
 125        struct v4l2_ctrl *vflip;
 126        struct v4l2_ctrl *hflip;
 127
 128        /* Current mode */
 129        const struct imx319_mode *cur_mode;
 130
 131        struct imx319_hwcfg *hwcfg;
 132        s64 link_def_freq;      /* CSI-2 link default frequency */
 133
 134        /*
 135         * Mutex for serialized access:
 136         * Protect sensor set pad format and start/stop streaming safely.
 137         * Protect access to sensor v4l2 controls.
 138         */
 139        struct mutex mutex;
 140
 141        /* Streaming on/off */
 142        bool streaming;
 143};
 144
 145static const struct imx319_reg imx319_global_regs[] = {
 146        { 0x0136, 0x13 },
 147        { 0x0137, 0x33 },
 148        { 0x3c7e, 0x05 },
 149        { 0x3c7f, 0x07 },
 150        { 0x4d39, 0x0b },
 151        { 0x4d41, 0x33 },
 152        { 0x4d43, 0x0c },
 153        { 0x4d49, 0x89 },
 154        { 0x4e05, 0x0b },
 155        { 0x4e0d, 0x33 },
 156        { 0x4e0f, 0x0c },
 157        { 0x4e15, 0x89 },
 158        { 0x4e49, 0x2a },
 159        { 0x4e51, 0x33 },
 160        { 0x4e53, 0x0c },
 161        { 0x4e59, 0x89 },
 162        { 0x5601, 0x4f },
 163        { 0x560b, 0x45 },
 164        { 0x562f, 0x0a },
 165        { 0x5643, 0x0a },
 166        { 0x5645, 0x0c },
 167        { 0x56ef, 0x51 },
 168        { 0x586f, 0x33 },
 169        { 0x5873, 0x89 },
 170        { 0x5905, 0x33 },
 171        { 0x5907, 0x89 },
 172        { 0x590d, 0x33 },
 173        { 0x590f, 0x89 },
 174        { 0x5915, 0x33 },
 175        { 0x5917, 0x89 },
 176        { 0x5969, 0x1c },
 177        { 0x596b, 0x72 },
 178        { 0x5971, 0x33 },
 179        { 0x5973, 0x89 },
 180        { 0x5975, 0x33 },
 181        { 0x5977, 0x89 },
 182        { 0x5979, 0x1c },
 183        { 0x597b, 0x72 },
 184        { 0x5985, 0x33 },
 185        { 0x5987, 0x89 },
 186        { 0x5999, 0x1c },
 187        { 0x599b, 0x72 },
 188        { 0x59a5, 0x33 },
 189        { 0x59a7, 0x89 },
 190        { 0x7485, 0x08 },
 191        { 0x7487, 0x0c },
 192        { 0x7489, 0xc7 },
 193        { 0x748b, 0x8b },
 194        { 0x9004, 0x09 },
 195        { 0x9200, 0x6a },
 196        { 0x9201, 0x22 },
 197        { 0x9202, 0x6a },
 198        { 0x9203, 0x23 },
 199        { 0x9204, 0x5f },
 200        { 0x9205, 0x23 },
 201        { 0x9206, 0x5f },
 202        { 0x9207, 0x24 },
 203        { 0x9208, 0x5f },
 204        { 0x9209, 0x26 },
 205        { 0x920a, 0x5f },
 206        { 0x920b, 0x27 },
 207        { 0x920c, 0x5f },
 208        { 0x920d, 0x29 },
 209        { 0x920e, 0x5f },
 210        { 0x920f, 0x2a },
 211        { 0x9210, 0x5f },
 212        { 0x9211, 0x2c },
 213        { 0xbc22, 0x1a },
 214        { 0xf01f, 0x04 },
 215        { 0xf021, 0x03 },
 216        { 0xf023, 0x02 },
 217        { 0xf03d, 0x05 },
 218        { 0xf03f, 0x03 },
 219        { 0xf041, 0x02 },
 220        { 0xf0af, 0x04 },
 221        { 0xf0b1, 0x03 },
 222        { 0xf0b3, 0x02 },
 223        { 0xf0cd, 0x05 },
 224        { 0xf0cf, 0x03 },
 225        { 0xf0d1, 0x02 },
 226        { 0xf13f, 0x04 },
 227        { 0xf141, 0x03 },
 228        { 0xf143, 0x02 },
 229        { 0xf15d, 0x05 },
 230        { 0xf15f, 0x03 },
 231        { 0xf161, 0x02 },
 232        { 0xf1cf, 0x04 },
 233        { 0xf1d1, 0x03 },
 234        { 0xf1d3, 0x02 },
 235        { 0xf1ed, 0x05 },
 236        { 0xf1ef, 0x03 },
 237        { 0xf1f1, 0x02 },
 238        { 0xf287, 0x04 },
 239        { 0xf289, 0x03 },
 240        { 0xf28b, 0x02 },
 241        { 0xf2a5, 0x05 },
 242        { 0xf2a7, 0x03 },
 243        { 0xf2a9, 0x02 },
 244        { 0xf2b7, 0x04 },
 245        { 0xf2b9, 0x03 },
 246        { 0xf2bb, 0x02 },
 247        { 0xf2d5, 0x05 },
 248        { 0xf2d7, 0x03 },
 249        { 0xf2d9, 0x02 },
 250};
 251
 252static const struct imx319_reg_list imx319_global_setting = {
 253        .num_of_regs = ARRAY_SIZE(imx319_global_regs),
 254        .regs = imx319_global_regs,
 255};
 256
 257static const struct imx319_reg mode_3264x2448_regs[] = {
 258        { 0x0112, 0x0a },
 259        { 0x0113, 0x0a },
 260        { 0x0114, 0x03 },
 261        { 0x0342, 0x0f },
 262        { 0x0343, 0x80 },
 263        { 0x0340, 0x0c },
 264        { 0x0341, 0xaa },
 265        { 0x0344, 0x00 },
 266        { 0x0345, 0x00 },
 267        { 0x0346, 0x00 },
 268        { 0x0347, 0x00 },
 269        { 0x0348, 0x0c },
 270        { 0x0349, 0xcf },
 271        { 0x034a, 0x09 },
 272        { 0x034b, 0x9f },
 273        { 0x0220, 0x00 },
 274        { 0x0221, 0x11 },
 275        { 0x0381, 0x01 },
 276        { 0x0383, 0x01 },
 277        { 0x0385, 0x01 },
 278        { 0x0387, 0x01 },
 279        { 0x0900, 0x00 },
 280        { 0x0901, 0x11 },
 281        { 0x0902, 0x0a },
 282        { 0x3140, 0x02 },
 283        { 0x3141, 0x00 },
 284        { 0x3f0d, 0x0a },
 285        { 0x3f14, 0x01 },
 286        { 0x3f3c, 0x01 },
 287        { 0x3f4d, 0x01 },
 288        { 0x3f4c, 0x01 },
 289        { 0x4254, 0x7f },
 290        { 0x0401, 0x00 },
 291        { 0x0404, 0x00 },
 292        { 0x0405, 0x10 },
 293        { 0x0408, 0x00 },
 294        { 0x0409, 0x08 },
 295        { 0x040a, 0x00 },
 296        { 0x040b, 0x08 },
 297        { 0x040c, 0x0c },
 298        { 0x040d, 0xc0 },
 299        { 0x040e, 0x09 },
 300        { 0x040f, 0x90 },
 301        { 0x034c, 0x0c },
 302        { 0x034d, 0xc0 },
 303        { 0x034e, 0x09 },
 304        { 0x034f, 0x90 },
 305        { 0x3261, 0x00 },
 306        { 0x3264, 0x00 },
 307        { 0x3265, 0x10 },
 308        { 0x0301, 0x05 },
 309        { 0x0303, 0x04 },
 310        { 0x0305, 0x04 },
 311        { 0x0306, 0x01 },
 312        { 0x0307, 0x92 },
 313        { 0x0309, 0x0a },
 314        { 0x030b, 0x02 },
 315        { 0x030d, 0x02 },
 316        { 0x030e, 0x00 },
 317        { 0x030f, 0xfa },
 318        { 0x0310, 0x00 },
 319        { 0x0820, 0x0f },
 320        { 0x0821, 0x13 },
 321        { 0x0822, 0x33 },
 322        { 0x0823, 0x33 },
 323        { 0x3e20, 0x01 },
 324        { 0x3e37, 0x00 },
 325        { 0x3e3b, 0x01 },
 326        { 0x38a3, 0x01 },
 327        { 0x38a8, 0x00 },
 328        { 0x38a9, 0x00 },
 329        { 0x38aa, 0x00 },
 330        { 0x38ab, 0x00 },
 331        { 0x3234, 0x00 },
 332        { 0x3fc1, 0x00 },
 333        { 0x3235, 0x00 },
 334        { 0x3802, 0x00 },
 335        { 0x3143, 0x04 },
 336        { 0x360a, 0x00 },
 337        { 0x0b00, 0x00 },
 338        { 0x0106, 0x00 },
 339        { 0x0b05, 0x01 },
 340        { 0x0b06, 0x01 },
 341        { 0x3230, 0x00 },
 342        { 0x3602, 0x01 },
 343        { 0x3607, 0x01 },
 344        { 0x3c00, 0x00 },
 345        { 0x3c01, 0x48 },
 346        { 0x3c02, 0xc8 },
 347        { 0x3c03, 0xaa },
 348        { 0x3c04, 0x91 },
 349        { 0x3c05, 0x54 },
 350        { 0x3c06, 0x26 },
 351        { 0x3c07, 0x20 },
 352        { 0x3c08, 0x51 },
 353        { 0x3d80, 0x00 },
 354        { 0x3f50, 0x00 },
 355        { 0x3f56, 0x00 },
 356        { 0x3f57, 0x30 },
 357        { 0x3f78, 0x01 },
 358        { 0x3f79, 0x18 },
 359        { 0x3f7c, 0x00 },
 360        { 0x3f7d, 0x00 },
 361        { 0x3fba, 0x00 },
 362        { 0x3fbb, 0x00 },
 363        { 0xa081, 0x00 },
 364        { 0xe014, 0x00 },
 365        { 0x0202, 0x0a },
 366        { 0x0203, 0x7a },
 367        { 0x0224, 0x01 },
 368        { 0x0225, 0xf4 },
 369        { 0x0204, 0x00 },
 370        { 0x0205, 0x00 },
 371        { 0x0216, 0x00 },
 372        { 0x0217, 0x00 },
 373        { 0x020e, 0x01 },
 374        { 0x020f, 0x00 },
 375        { 0x0210, 0x01 },
 376        { 0x0211, 0x00 },
 377        { 0x0212, 0x01 },
 378        { 0x0213, 0x00 },
 379        { 0x0214, 0x01 },
 380        { 0x0215, 0x00 },
 381        { 0x0218, 0x01 },
 382        { 0x0219, 0x00 },
 383        { 0x3614, 0x00 },
 384        { 0x3616, 0x0d },
 385        { 0x3617, 0x56 },
 386        { 0xb612, 0x20 },
 387        { 0xb613, 0x20 },
 388        { 0xb614, 0x20 },
 389        { 0xb615, 0x20 },
 390        { 0xb616, 0x0a },
 391        { 0xb617, 0x0a },
 392        { 0xb618, 0x20 },
 393        { 0xb619, 0x20 },
 394        { 0xb61a, 0x20 },
 395        { 0xb61b, 0x20 },
 396        { 0xb61c, 0x0a },
 397        { 0xb61d, 0x0a },
 398        { 0xb666, 0x30 },
 399        { 0xb667, 0x30 },
 400        { 0xb668, 0x30 },
 401        { 0xb669, 0x30 },
 402        { 0xb66a, 0x14 },
 403        { 0xb66b, 0x14 },
 404        { 0xb66c, 0x20 },
 405        { 0xb66d, 0x20 },
 406        { 0xb66e, 0x20 },
 407        { 0xb66f, 0x20 },
 408        { 0xb670, 0x10 },
 409        { 0xb671, 0x10 },
 410        { 0x3237, 0x00 },
 411        { 0x3900, 0x00 },
 412        { 0x3901, 0x00 },
 413        { 0x3902, 0x00 },
 414        { 0x3904, 0x00 },
 415        { 0x3905, 0x00 },
 416        { 0x3906, 0x00 },
 417        { 0x3907, 0x00 },
 418        { 0x3908, 0x00 },
 419        { 0x3909, 0x00 },
 420        { 0x3912, 0x00 },
 421        { 0x3930, 0x00 },
 422        { 0x3931, 0x00 },
 423        { 0x3933, 0x00 },
 424        { 0x3934, 0x00 },
 425        { 0x3935, 0x00 },
 426        { 0x3936, 0x00 },
 427        { 0x3937, 0x00 },
 428        { 0x30ac, 0x00 },
 429};
 430
 431static const struct imx319_reg mode_3280x2464_regs[] = {
 432        { 0x0112, 0x0a },
 433        { 0x0113, 0x0a },
 434        { 0x0114, 0x03 },
 435        { 0x0342, 0x0f },
 436        { 0x0343, 0x80 },
 437        { 0x0340, 0x0c },
 438        { 0x0341, 0xaa },
 439        { 0x0344, 0x00 },
 440        { 0x0345, 0x00 },
 441        { 0x0346, 0x00 },
 442        { 0x0347, 0x00 },
 443        { 0x0348, 0x0c },
 444        { 0x0349, 0xcf },
 445        { 0x034a, 0x09 },
 446        { 0x034b, 0x9f },
 447        { 0x0220, 0x00 },
 448        { 0x0221, 0x11 },
 449        { 0x0381, 0x01 },
 450        { 0x0383, 0x01 },
 451        { 0x0385, 0x01 },
 452        { 0x0387, 0x01 },
 453        { 0x0900, 0x00 },
 454        { 0x0901, 0x11 },
 455        { 0x0902, 0x0a },
 456        { 0x3140, 0x02 },
 457        { 0x3141, 0x00 },
 458        { 0x3f0d, 0x0a },
 459        { 0x3f14, 0x01 },
 460        { 0x3f3c, 0x01 },
 461        { 0x3f4d, 0x01 },
 462        { 0x3f4c, 0x01 },
 463        { 0x4254, 0x7f },
 464        { 0x0401, 0x00 },
 465        { 0x0404, 0x00 },
 466        { 0x0405, 0x10 },
 467        { 0x0408, 0x00 },
 468        { 0x0409, 0x00 },
 469        { 0x040a, 0x00 },
 470        { 0x040b, 0x00 },
 471        { 0x040c, 0x0c },
 472        { 0x040d, 0xd0 },
 473        { 0x040e, 0x09 },
 474        { 0x040f, 0xa0 },
 475        { 0x034c, 0x0c },
 476        { 0x034d, 0xd0 },
 477        { 0x034e, 0x09 },
 478        { 0x034f, 0xa0 },
 479        { 0x3261, 0x00 },
 480        { 0x3264, 0x00 },
 481        { 0x3265, 0x10 },
 482        { 0x0301, 0x05 },
 483        { 0x0303, 0x04 },
 484        { 0x0305, 0x04 },
 485        { 0x0306, 0x01 },
 486        { 0x0307, 0x92 },
 487        { 0x0309, 0x0a },
 488        { 0x030b, 0x02 },
 489        { 0x030d, 0x02 },
 490        { 0x030e, 0x00 },
 491        { 0x030f, 0xfa },
 492        { 0x0310, 0x00 },
 493        { 0x0820, 0x0f },
 494        { 0x0821, 0x13 },
 495        { 0x0822, 0x33 },
 496        { 0x0823, 0x33 },
 497        { 0x3e20, 0x01 },
 498        { 0x3e37, 0x00 },
 499        { 0x3e3b, 0x01 },
 500        { 0x38a3, 0x01 },
 501        { 0x38a8, 0x00 },
 502        { 0x38a9, 0x00 },
 503        { 0x38aa, 0x00 },
 504        { 0x38ab, 0x00 },
 505        { 0x3234, 0x00 },
 506        { 0x3fc1, 0x00 },
 507        { 0x3235, 0x00 },
 508        { 0x3802, 0x00 },
 509        { 0x3143, 0x04 },
 510        { 0x360a, 0x00 },
 511        { 0x0b00, 0x00 },
 512        { 0x0106, 0x00 },
 513        { 0x0b05, 0x01 },
 514        { 0x0b06, 0x01 },
 515        { 0x3230, 0x00 },
 516        { 0x3602, 0x01 },
 517        { 0x3607, 0x01 },
 518        { 0x3c00, 0x00 },
 519        { 0x3c01, 0x48 },
 520        { 0x3c02, 0xc8 },
 521        { 0x3c03, 0xaa },
 522        { 0x3c04, 0x91 },
 523        { 0x3c05, 0x54 },
 524        { 0x3c06, 0x26 },
 525        { 0x3c07, 0x20 },
 526        { 0x3c08, 0x51 },
 527        { 0x3d80, 0x00 },
 528        { 0x3f50, 0x00 },
 529        { 0x3f56, 0x00 },
 530        { 0x3f57, 0x30 },
 531        { 0x3f78, 0x01 },
 532        { 0x3f79, 0x18 },
 533        { 0x3f7c, 0x00 },
 534        { 0x3f7d, 0x00 },
 535        { 0x3fba, 0x00 },
 536        { 0x3fbb, 0x00 },
 537        { 0xa081, 0x00 },
 538        { 0xe014, 0x00 },
 539        { 0x0202, 0x0a },
 540        { 0x0203, 0x7a },
 541        { 0x0224, 0x01 },
 542        { 0x0225, 0xf4 },
 543        { 0x0204, 0x00 },
 544        { 0x0205, 0x00 },
 545        { 0x0216, 0x00 },
 546        { 0x0217, 0x00 },
 547        { 0x020e, 0x01 },
 548        { 0x020f, 0x00 },
 549        { 0x0210, 0x01 },
 550        { 0x0211, 0x00 },
 551        { 0x0212, 0x01 },
 552        { 0x0213, 0x00 },
 553        { 0x0214, 0x01 },
 554        { 0x0215, 0x00 },
 555        { 0x0218, 0x01 },
 556        { 0x0219, 0x00 },
 557        { 0x3614, 0x00 },
 558        { 0x3616, 0x0d },
 559        { 0x3617, 0x56 },
 560        { 0xb612, 0x20 },
 561        { 0xb613, 0x20 },
 562        { 0xb614, 0x20 },
 563        { 0xb615, 0x20 },
 564        { 0xb616, 0x0a },
 565        { 0xb617, 0x0a },
 566        { 0xb618, 0x20 },
 567        { 0xb619, 0x20 },
 568        { 0xb61a, 0x20 },
 569        { 0xb61b, 0x20 },
 570        { 0xb61c, 0x0a },
 571        { 0xb61d, 0x0a },
 572        { 0xb666, 0x30 },
 573        { 0xb667, 0x30 },
 574        { 0xb668, 0x30 },
 575        { 0xb669, 0x30 },
 576        { 0xb66a, 0x14 },
 577        { 0xb66b, 0x14 },
 578        { 0xb66c, 0x20 },
 579        { 0xb66d, 0x20 },
 580        { 0xb66e, 0x20 },
 581        { 0xb66f, 0x20 },
 582        { 0xb670, 0x10 },
 583        { 0xb671, 0x10 },
 584        { 0x3237, 0x00 },
 585        { 0x3900, 0x00 },
 586        { 0x3901, 0x00 },
 587        { 0x3902, 0x00 },
 588        { 0x3904, 0x00 },
 589        { 0x3905, 0x00 },
 590        { 0x3906, 0x00 },
 591        { 0x3907, 0x00 },
 592        { 0x3908, 0x00 },
 593        { 0x3909, 0x00 },
 594        { 0x3912, 0x00 },
 595        { 0x3930, 0x00 },
 596        { 0x3931, 0x00 },
 597        { 0x3933, 0x00 },
 598        { 0x3934, 0x00 },
 599        { 0x3935, 0x00 },
 600        { 0x3936, 0x00 },
 601        { 0x3937, 0x00 },
 602        { 0x30ac, 0x00 },
 603};
 604
 605static const struct imx319_reg mode_1936x1096_regs[] = {
 606        { 0x0112, 0x0a },
 607        { 0x0113, 0x0a },
 608        { 0x0114, 0x03 },
 609        { 0x0342, 0x0f },
 610        { 0x0343, 0x80 },
 611        { 0x0340, 0x0c },
 612        { 0x0341, 0xaa },
 613        { 0x0344, 0x00 },
 614        { 0x0345, 0x00 },
 615        { 0x0346, 0x02 },
 616        { 0x0347, 0xac },
 617        { 0x0348, 0x0c },
 618        { 0x0349, 0xcf },
 619        { 0x034a, 0x06 },
 620        { 0x034b, 0xf3 },
 621        { 0x0220, 0x00 },
 622        { 0x0221, 0x11 },
 623        { 0x0381, 0x01 },
 624        { 0x0383, 0x01 },
 625        { 0x0385, 0x01 },
 626        { 0x0387, 0x01 },
 627        { 0x0900, 0x00 },
 628        { 0x0901, 0x11 },
 629        { 0x0902, 0x0a },
 630        { 0x3140, 0x02 },
 631        { 0x3141, 0x00 },
 632        { 0x3f0d, 0x0a },
 633        { 0x3f14, 0x01 },
 634        { 0x3f3c, 0x01 },
 635        { 0x3f4d, 0x01 },
 636        { 0x3f4c, 0x01 },
 637        { 0x4254, 0x7f },
 638        { 0x0401, 0x00 },
 639        { 0x0404, 0x00 },
 640        { 0x0405, 0x10 },
 641        { 0x0408, 0x02 },
 642        { 0x0409, 0xa0 },
 643        { 0x040a, 0x00 },
 644        { 0x040b, 0x00 },
 645        { 0x040c, 0x07 },
 646        { 0x040d, 0x90 },
 647        { 0x040e, 0x04 },
 648        { 0x040f, 0x48 },
 649        { 0x034c, 0x07 },
 650        { 0x034d, 0x90 },
 651        { 0x034e, 0x04 },
 652        { 0x034f, 0x48 },
 653        { 0x3261, 0x00 },
 654        { 0x3264, 0x00 },
 655        { 0x3265, 0x10 },
 656        { 0x0301, 0x05 },
 657        { 0x0303, 0x04 },
 658        { 0x0305, 0x04 },
 659        { 0x0306, 0x01 },
 660        { 0x0307, 0x92 },
 661        { 0x0309, 0x0a },
 662        { 0x030b, 0x02 },
 663        { 0x030d, 0x02 },
 664        { 0x030e, 0x00 },
 665        { 0x030f, 0xfa },
 666        { 0x0310, 0x00 },
 667        { 0x0820, 0x0f },
 668        { 0x0821, 0x13 },
 669        { 0x0822, 0x33 },
 670        { 0x0823, 0x33 },
 671        { 0x3e20, 0x01 },
 672        { 0x3e37, 0x00 },
 673        { 0x3e3b, 0x01 },
 674        { 0x38a3, 0x01 },
 675        { 0x38a8, 0x00 },
 676        { 0x38a9, 0x00 },
 677        { 0x38aa, 0x00 },
 678        { 0x38ab, 0x00 },
 679        { 0x3234, 0x00 },
 680        { 0x3fc1, 0x00 },
 681        { 0x3235, 0x00 },
 682        { 0x3802, 0x00 },
 683        { 0x3143, 0x04 },
 684        { 0x360a, 0x00 },
 685        { 0x0b00, 0x00 },
 686        { 0x0106, 0x00 },
 687        { 0x0b05, 0x01 },
 688        { 0x0b06, 0x01 },
 689        { 0x3230, 0x00 },
 690        { 0x3602, 0x01 },
 691        { 0x3607, 0x01 },
 692        { 0x3c00, 0x00 },
 693        { 0x3c01, 0x48 },
 694        { 0x3c02, 0xc8 },
 695        { 0x3c03, 0xaa },
 696        { 0x3c04, 0x91 },
 697        { 0x3c05, 0x54 },
 698        { 0x3c06, 0x26 },
 699        { 0x3c07, 0x20 },
 700        { 0x3c08, 0x51 },
 701        { 0x3d80, 0x00 },
 702        { 0x3f50, 0x00 },
 703        { 0x3f56, 0x00 },
 704        { 0x3f57, 0x30 },
 705        { 0x3f78, 0x01 },
 706        { 0x3f79, 0x18 },
 707        { 0x3f7c, 0x00 },
 708        { 0x3f7d, 0x00 },
 709        { 0x3fba, 0x00 },
 710        { 0x3fbb, 0x00 },
 711        { 0xa081, 0x00 },
 712        { 0xe014, 0x00 },
 713        { 0x0202, 0x05 },
 714        { 0x0203, 0x34 },
 715        { 0x0224, 0x01 },
 716        { 0x0225, 0xf4 },
 717        { 0x0204, 0x00 },
 718        { 0x0205, 0x00 },
 719        { 0x0216, 0x00 },
 720        { 0x0217, 0x00 },
 721        { 0x020e, 0x01 },
 722        { 0x020f, 0x00 },
 723        { 0x0210, 0x01 },
 724        { 0x0211, 0x00 },
 725        { 0x0212, 0x01 },
 726        { 0x0213, 0x00 },
 727        { 0x0214, 0x01 },
 728        { 0x0215, 0x00 },
 729        { 0x0218, 0x01 },
 730        { 0x0219, 0x00 },
 731        { 0x3614, 0x00 },
 732        { 0x3616, 0x0d },
 733        { 0x3617, 0x56 },
 734        { 0xb612, 0x20 },
 735        { 0xb613, 0x20 },
 736        { 0xb614, 0x20 },
 737        { 0xb615, 0x20 },
 738        { 0xb616, 0x0a },
 739        { 0xb617, 0x0a },
 740        { 0xb618, 0x20 },
 741        { 0xb619, 0x20 },
 742        { 0xb61a, 0x20 },
 743        { 0xb61b, 0x20 },
 744        { 0xb61c, 0x0a },
 745        { 0xb61d, 0x0a },
 746        { 0xb666, 0x30 },
 747        { 0xb667, 0x30 },
 748        { 0xb668, 0x30 },
 749        { 0xb669, 0x30 },
 750        { 0xb66a, 0x14 },
 751        { 0xb66b, 0x14 },
 752        { 0xb66c, 0x20 },
 753        { 0xb66d, 0x20 },
 754        { 0xb66e, 0x20 },
 755        { 0xb66f, 0x20 },
 756        { 0xb670, 0x10 },
 757        { 0xb671, 0x10 },
 758        { 0x3237, 0x00 },
 759        { 0x3900, 0x00 },
 760        { 0x3901, 0x00 },
 761        { 0x3902, 0x00 },
 762        { 0x3904, 0x00 },
 763        { 0x3905, 0x00 },
 764        { 0x3906, 0x00 },
 765        { 0x3907, 0x00 },
 766        { 0x3908, 0x00 },
 767        { 0x3909, 0x00 },
 768        { 0x3912, 0x00 },
 769        { 0x3930, 0x00 },
 770        { 0x3931, 0x00 },
 771        { 0x3933, 0x00 },
 772        { 0x3934, 0x00 },
 773        { 0x3935, 0x00 },
 774        { 0x3936, 0x00 },
 775        { 0x3937, 0x00 },
 776        { 0x30ac, 0x00 },
 777};
 778
 779static const struct imx319_reg mode_1920x1080_regs[] = {
 780        { 0x0112, 0x0a },
 781        { 0x0113, 0x0a },
 782        { 0x0114, 0x03 },
 783        { 0x0342, 0x0f },
 784        { 0x0343, 0x80 },
 785        { 0x0340, 0x0c },
 786        { 0x0341, 0xaa },
 787        { 0x0344, 0x00 },
 788        { 0x0345, 0x00 },
 789        { 0x0346, 0x02 },
 790        { 0x0347, 0xb4 },
 791        { 0x0348, 0x0c },
 792        { 0x0349, 0xcf },
 793        { 0x034a, 0x06 },
 794        { 0x034b, 0xeb },
 795        { 0x0220, 0x00 },
 796        { 0x0221, 0x11 },
 797        { 0x0381, 0x01 },
 798        { 0x0383, 0x01 },
 799        { 0x0385, 0x01 },
 800        { 0x0387, 0x01 },
 801        { 0x0900, 0x00 },
 802        { 0x0901, 0x11 },
 803        { 0x0902, 0x0a },
 804        { 0x3140, 0x02 },
 805        { 0x3141, 0x00 },
 806        { 0x3f0d, 0x0a },
 807        { 0x3f14, 0x01 },
 808        { 0x3f3c, 0x01 },
 809        { 0x3f4d, 0x01 },
 810        { 0x3f4c, 0x01 },
 811        { 0x4254, 0x7f },
 812        { 0x0401, 0x00 },
 813        { 0x0404, 0x00 },
 814        { 0x0405, 0x10 },
 815        { 0x0408, 0x02 },
 816        { 0x0409, 0xa8 },
 817        { 0x040a, 0x00 },
 818        { 0x040b, 0x00 },
 819        { 0x040c, 0x07 },
 820        { 0x040d, 0x80 },
 821        { 0x040e, 0x04 },
 822        { 0x040f, 0x38 },
 823        { 0x034c, 0x07 },
 824        { 0x034d, 0x80 },
 825        { 0x034e, 0x04 },
 826        { 0x034f, 0x38 },
 827        { 0x3261, 0x00 },
 828        { 0x3264, 0x00 },
 829        { 0x3265, 0x10 },
 830        { 0x0301, 0x05 },
 831        { 0x0303, 0x04 },
 832        { 0x0305, 0x04 },
 833        { 0x0306, 0x01 },
 834        { 0x0307, 0x92 },
 835        { 0x0309, 0x0a },
 836        { 0x030b, 0x02 },
 837        { 0x030d, 0x02 },
 838        { 0x030e, 0x00 },
 839        { 0x030f, 0xfa },
 840        { 0x0310, 0x00 },
 841        { 0x0820, 0x0f },
 842        { 0x0821, 0x13 },
 843        { 0x0822, 0x33 },
 844        { 0x0823, 0x33 },
 845        { 0x3e20, 0x01 },
 846        { 0x3e37, 0x00 },
 847        { 0x3e3b, 0x01 },
 848        { 0x38a3, 0x01 },
 849        { 0x38a8, 0x00 },
 850        { 0x38a9, 0x00 },
 851        { 0x38aa, 0x00 },
 852        { 0x38ab, 0x00 },
 853        { 0x3234, 0x00 },
 854        { 0x3fc1, 0x00 },
 855        { 0x3235, 0x00 },
 856        { 0x3802, 0x00 },
 857        { 0x3143, 0x04 },
 858        { 0x360a, 0x00 },
 859        { 0x0b00, 0x00 },
 860        { 0x0106, 0x00 },
 861        { 0x0b05, 0x01 },
 862        { 0x0b06, 0x01 },
 863        { 0x3230, 0x00 },
 864        { 0x3602, 0x01 },
 865        { 0x3607, 0x01 },
 866        { 0x3c00, 0x00 },
 867        { 0x3c01, 0x48 },
 868        { 0x3c02, 0xc8 },
 869        { 0x3c03, 0xaa },
 870        { 0x3c04, 0x91 },
 871        { 0x3c05, 0x54 },
 872        { 0x3c06, 0x26 },
 873        { 0x3c07, 0x20 },
 874        { 0x3c08, 0x51 },
 875        { 0x3d80, 0x00 },
 876        { 0x3f50, 0x00 },
 877        { 0x3f56, 0x00 },
 878        { 0x3f57, 0x30 },
 879        { 0x3f78, 0x01 },
 880        { 0x3f79, 0x18 },
 881        { 0x3f7c, 0x00 },
 882        { 0x3f7d, 0x00 },
 883        { 0x3fba, 0x00 },
 884        { 0x3fbb, 0x00 },
 885        { 0xa081, 0x00 },
 886        { 0xe014, 0x00 },
 887        { 0x0202, 0x05 },
 888        { 0x0203, 0x34 },
 889        { 0x0224, 0x01 },
 890        { 0x0225, 0xf4 },
 891        { 0x0204, 0x00 },
 892        { 0x0205, 0x00 },
 893        { 0x0216, 0x00 },
 894        { 0x0217, 0x00 },
 895        { 0x020e, 0x01 },
 896        { 0x020f, 0x00 },
 897        { 0x0210, 0x01 },
 898        { 0x0211, 0x00 },
 899        { 0x0212, 0x01 },
 900        { 0x0213, 0x00 },
 901        { 0x0214, 0x01 },
 902        { 0x0215, 0x00 },
 903        { 0x0218, 0x01 },
 904        { 0x0219, 0x00 },
 905        { 0x3614, 0x00 },
 906        { 0x3616, 0x0d },
 907        { 0x3617, 0x56 },
 908        { 0xb612, 0x20 },
 909        { 0xb613, 0x20 },
 910        { 0xb614, 0x20 },
 911        { 0xb615, 0x20 },
 912        { 0xb616, 0x0a },
 913        { 0xb617, 0x0a },
 914        { 0xb618, 0x20 },
 915        { 0xb619, 0x20 },
 916        { 0xb61a, 0x20 },
 917        { 0xb61b, 0x20 },
 918        { 0xb61c, 0x0a },
 919        { 0xb61d, 0x0a },
 920        { 0xb666, 0x30 },
 921        { 0xb667, 0x30 },
 922        { 0xb668, 0x30 },
 923        { 0xb669, 0x30 },
 924        { 0xb66a, 0x14 },
 925        { 0xb66b, 0x14 },
 926        { 0xb66c, 0x20 },
 927        { 0xb66d, 0x20 },
 928        { 0xb66e, 0x20 },
 929        { 0xb66f, 0x20 },
 930        { 0xb670, 0x10 },
 931        { 0xb671, 0x10 },
 932        { 0x3237, 0x00 },
 933        { 0x3900, 0x00 },
 934        { 0x3901, 0x00 },
 935        { 0x3902, 0x00 },
 936        { 0x3904, 0x00 },
 937        { 0x3905, 0x00 },
 938        { 0x3906, 0x00 },
 939        { 0x3907, 0x00 },
 940        { 0x3908, 0x00 },
 941        { 0x3909, 0x00 },
 942        { 0x3912, 0x00 },
 943        { 0x3930, 0x00 },
 944        { 0x3931, 0x00 },
 945        { 0x3933, 0x00 },
 946        { 0x3934, 0x00 },
 947        { 0x3935, 0x00 },
 948        { 0x3936, 0x00 },
 949        { 0x3937, 0x00 },
 950        { 0x30ac, 0x00 },
 951};
 952
 953static const struct imx319_reg mode_1640x1232_regs[] = {
 954        { 0x0112, 0x0a },
 955        { 0x0113, 0x0a },
 956        { 0x0114, 0x03 },
 957        { 0x0342, 0x08 },
 958        { 0x0343, 0x20 },
 959        { 0x0340, 0x18 },
 960        { 0x0341, 0x2a },
 961        { 0x0344, 0x00 },
 962        { 0x0345, 0x00 },
 963        { 0x0346, 0x00 },
 964        { 0x0347, 0x00 },
 965        { 0x0348, 0x0c },
 966        { 0x0349, 0xcf },
 967        { 0x034a, 0x09 },
 968        { 0x034b, 0x9f },
 969        { 0x0220, 0x00 },
 970        { 0x0221, 0x11 },
 971        { 0x0381, 0x01 },
 972        { 0x0383, 0x01 },
 973        { 0x0385, 0x01 },
 974        { 0x0387, 0x01 },
 975        { 0x0900, 0x01 },
 976        { 0x0901, 0x22 },
 977        { 0x0902, 0x0a },
 978        { 0x3140, 0x02 },
 979        { 0x3141, 0x00 },
 980        { 0x3f0d, 0x0a },
 981        { 0x3f14, 0x01 },
 982        { 0x3f3c, 0x02 },
 983        { 0x3f4d, 0x01 },
 984        { 0x3f4c, 0x01 },
 985        { 0x4254, 0x7f },
 986        { 0x0401, 0x00 },
 987        { 0x0404, 0x00 },
 988        { 0x0405, 0x10 },
 989        { 0x0408, 0x00 },
 990        { 0x0409, 0x00 },
 991        { 0x040a, 0x00 },
 992        { 0x040b, 0x00 },
 993        { 0x040c, 0x06 },
 994        { 0x040d, 0x68 },
 995        { 0x040e, 0x04 },
 996        { 0x040f, 0xd0 },
 997        { 0x034c, 0x06 },
 998        { 0x034d, 0x68 },
 999        { 0x034e, 0x04 },
1000        { 0x034f, 0xd0 },
1001        { 0x3261, 0x00 },
1002        { 0x3264, 0x00 },
1003        { 0x3265, 0x10 },
1004        { 0x0301, 0x05 },
1005        { 0x0303, 0x04 },
1006        { 0x0305, 0x04 },
1007        { 0x0306, 0x01 },
1008        { 0x0307, 0x92 },
1009        { 0x0309, 0x0a },
1010        { 0x030b, 0x02 },
1011        { 0x030d, 0x02 },
1012        { 0x030e, 0x00 },
1013        { 0x030f, 0xfa },
1014        { 0x0310, 0x00 },
1015        { 0x0820, 0x0f },
1016        { 0x0821, 0x13 },
1017        { 0x0822, 0x33 },
1018        { 0x0823, 0x33 },
1019        { 0x3e20, 0x01 },
1020        { 0x3e37, 0x00 },
1021        { 0x3e3b, 0x01 },
1022        { 0x38a3, 0x01 },
1023        { 0x38a8, 0x00 },
1024        { 0x38a9, 0x00 },
1025        { 0x38aa, 0x00 },
1026        { 0x38ab, 0x00 },
1027        { 0x3234, 0x00 },
1028        { 0x3fc1, 0x00 },
1029        { 0x3235, 0x00 },
1030        { 0x3802, 0x00 },
1031        { 0x3143, 0x04 },
1032        { 0x360a, 0x00 },
1033        { 0x0b00, 0x00 },
1034        { 0x0106, 0x00 },
1035        { 0x0b05, 0x01 },
1036        { 0x0b06, 0x01 },
1037        { 0x3230, 0x00 },
1038        { 0x3602, 0x01 },
1039        { 0x3607, 0x01 },
1040        { 0x3c00, 0x00 },
1041        { 0x3c01, 0xba },
1042        { 0x3c02, 0xc8 },
1043        { 0x3c03, 0xaa },
1044        { 0x3c04, 0x91 },
1045        { 0x3c05, 0x54 },
1046        { 0x3c06, 0x26 },
1047        { 0x3c07, 0x20 },
1048        { 0x3c08, 0x51 },
1049        { 0x3d80, 0x00 },
1050        { 0x3f50, 0x00 },
1051        { 0x3f56, 0x00 },
1052        { 0x3f57, 0x30 },
1053        { 0x3f78, 0x00 },
1054        { 0x3f79, 0x34 },
1055        { 0x3f7c, 0x00 },
1056        { 0x3f7d, 0x00 },
1057        { 0x3fba, 0x00 },
1058        { 0x3fbb, 0x00 },
1059        { 0xa081, 0x04 },
1060        { 0xe014, 0x00 },
1061        { 0x0202, 0x04 },
1062        { 0x0203, 0xf6 },
1063        { 0x0224, 0x01 },
1064        { 0x0225, 0xf4 },
1065        { 0x0204, 0x00 },
1066        { 0x0205, 0x00 },
1067        { 0x0216, 0x00 },
1068        { 0x0217, 0x00 },
1069        { 0x020e, 0x01 },
1070        { 0x020f, 0x00 },
1071        { 0x0210, 0x01 },
1072        { 0x0211, 0x00 },
1073        { 0x0212, 0x01 },
1074        { 0x0213, 0x00 },
1075        { 0x0214, 0x01 },
1076        { 0x0215, 0x00 },
1077        { 0x0218, 0x01 },
1078        { 0x0219, 0x00 },
1079        { 0x3614, 0x00 },
1080        { 0x3616, 0x0d },
1081        { 0x3617, 0x56 },
1082        { 0xb612, 0x20 },
1083        { 0xb613, 0x20 },
1084        { 0xb614, 0x20 },
1085        { 0xb615, 0x20 },
1086        { 0xb616, 0x0a },
1087        { 0xb617, 0x0a },
1088        { 0xb618, 0x20 },
1089        { 0xb619, 0x20 },
1090        { 0xb61a, 0x20 },
1091        { 0xb61b, 0x20 },
1092        { 0xb61c, 0x0a },
1093        { 0xb61d, 0x0a },
1094        { 0xb666, 0x30 },
1095        { 0xb667, 0x30 },
1096        { 0xb668, 0x30 },
1097        { 0xb669, 0x30 },
1098        { 0xb66a, 0x14 },
1099        { 0xb66b, 0x14 },
1100        { 0xb66c, 0x20 },
1101        { 0xb66d, 0x20 },
1102        { 0xb66e, 0x20 },
1103        { 0xb66f, 0x20 },
1104        { 0xb670, 0x10 },
1105        { 0xb671, 0x10 },
1106        { 0x3237, 0x00 },
1107        { 0x3900, 0x00 },
1108        { 0x3901, 0x00 },
1109        { 0x3902, 0x00 },
1110        { 0x3904, 0x00 },
1111        { 0x3905, 0x00 },
1112        { 0x3906, 0x00 },
1113        { 0x3907, 0x00 },
1114        { 0x3908, 0x00 },
1115        { 0x3909, 0x00 },
1116        { 0x3912, 0x00 },
1117        { 0x3930, 0x00 },
1118        { 0x3931, 0x00 },
1119        { 0x3933, 0x00 },
1120        { 0x3934, 0x00 },
1121        { 0x3935, 0x00 },
1122        { 0x3936, 0x00 },
1123        { 0x3937, 0x00 },
1124        { 0x30ac, 0x00 },
1125};
1126
1127static const struct imx319_reg mode_1640x922_regs[] = {
1128        { 0x0112, 0x0a },
1129        { 0x0113, 0x0a },
1130        { 0x0114, 0x03 },
1131        { 0x0342, 0x08 },
1132        { 0x0343, 0x20 },
1133        { 0x0340, 0x18 },
1134        { 0x0341, 0x2a },
1135        { 0x0344, 0x00 },
1136        { 0x0345, 0x00 },
1137        { 0x0346, 0x01 },
1138        { 0x0347, 0x30 },
1139        { 0x0348, 0x0c },
1140        { 0x0349, 0xcf },
1141        { 0x034a, 0x08 },
1142        { 0x034b, 0x6f },
1143        { 0x0220, 0x00 },
1144        { 0x0221, 0x11 },
1145        { 0x0381, 0x01 },
1146        { 0x0383, 0x01 },
1147        { 0x0385, 0x01 },
1148        { 0x0387, 0x01 },
1149        { 0x0900, 0x01 },
1150        { 0x0901, 0x22 },
1151        { 0x0902, 0x0a },
1152        { 0x3140, 0x02 },
1153        { 0x3141, 0x00 },
1154        { 0x3f0d, 0x0a },
1155        { 0x3f14, 0x01 },
1156        { 0x3f3c, 0x02 },
1157        { 0x3f4d, 0x01 },
1158        { 0x3f4c, 0x01 },
1159        { 0x4254, 0x7f },
1160        { 0x0401, 0x00 },
1161        { 0x0404, 0x00 },
1162        { 0x0405, 0x10 },
1163        { 0x0408, 0x00 },
1164        { 0x0409, 0x00 },
1165        { 0x040a, 0x00 },
1166        { 0x040b, 0x02 },
1167        { 0x040c, 0x06 },
1168        { 0x040d, 0x68 },
1169        { 0x040e, 0x03 },
1170        { 0x040f, 0x9a },
1171        { 0x034c, 0x06 },
1172        { 0x034d, 0x68 },
1173        { 0x034e, 0x03 },
1174        { 0x034f, 0x9a },
1175        { 0x3261, 0x00 },
1176        { 0x3264, 0x00 },
1177        { 0x3265, 0x10 },
1178        { 0x0301, 0x05 },
1179        { 0x0303, 0x04 },
1180        { 0x0305, 0x04 },
1181        { 0x0306, 0x01 },
1182        { 0x0307, 0x92 },
1183        { 0x0309, 0x0a },
1184        { 0x030b, 0x02 },
1185        { 0x030d, 0x02 },
1186        { 0x030e, 0x00 },
1187        { 0x030f, 0xfa },
1188        { 0x0310, 0x00 },
1189        { 0x0820, 0x0f },
1190        { 0x0821, 0x13 },
1191        { 0x0822, 0x33 },
1192        { 0x0823, 0x33 },
1193        { 0x3e20, 0x01 },
1194        { 0x3e37, 0x00 },
1195        { 0x3e3b, 0x01 },
1196        { 0x38a3, 0x01 },
1197        { 0x38a8, 0x00 },
1198        { 0x38a9, 0x00 },
1199        { 0x38aa, 0x00 },
1200        { 0x38ab, 0x00 },
1201        { 0x3234, 0x00 },
1202        { 0x3fc1, 0x00 },
1203        { 0x3235, 0x00 },
1204        { 0x3802, 0x00 },
1205        { 0x3143, 0x04 },
1206        { 0x360a, 0x00 },
1207        { 0x0b00, 0x00 },
1208        { 0x0106, 0x00 },
1209        { 0x0b05, 0x01 },
1210        { 0x0b06, 0x01 },
1211        { 0x3230, 0x00 },
1212        { 0x3602, 0x01 },
1213        { 0x3607, 0x01 },
1214        { 0x3c00, 0x00 },
1215        { 0x3c01, 0xba },
1216        { 0x3c02, 0xc8 },
1217        { 0x3c03, 0xaa },
1218        { 0x3c04, 0x91 },
1219        { 0x3c05, 0x54 },
1220        { 0x3c06, 0x26 },
1221        { 0x3c07, 0x20 },
1222        { 0x3c08, 0x51 },
1223        { 0x3d80, 0x00 },
1224        { 0x3f50, 0x00 },
1225        { 0x3f56, 0x00 },
1226        { 0x3f57, 0x30 },
1227        { 0x3f78, 0x00 },
1228        { 0x3f79, 0x34 },
1229        { 0x3f7c, 0x00 },
1230        { 0x3f7d, 0x00 },
1231        { 0x3fba, 0x00 },
1232        { 0x3fbb, 0x00 },
1233        { 0xa081, 0x04 },
1234        { 0xe014, 0x00 },
1235        { 0x0202, 0x04 },
1236        { 0x0203, 0xf6 },
1237        { 0x0224, 0x01 },
1238        { 0x0225, 0xf4 },
1239        { 0x0204, 0x00 },
1240        { 0x0205, 0x00 },
1241        { 0x0216, 0x00 },
1242        { 0x0217, 0x00 },
1243        { 0x020e, 0x01 },
1244        { 0x020f, 0x00 },
1245        { 0x0210, 0x01 },
1246        { 0x0211, 0x00 },
1247        { 0x0212, 0x01 },
1248        { 0x0213, 0x00 },
1249        { 0x0214, 0x01 },
1250        { 0x0215, 0x00 },
1251        { 0x0218, 0x01 },
1252        { 0x0219, 0x00 },
1253        { 0x3614, 0x00 },
1254        { 0x3616, 0x0d },
1255        { 0x3617, 0x56 },
1256        { 0xb612, 0x20 },
1257        { 0xb613, 0x20 },
1258        { 0xb614, 0x20 },
1259        { 0xb615, 0x20 },
1260        { 0xb616, 0x0a },
1261        { 0xb617, 0x0a },
1262        { 0xb618, 0x20 },
1263        { 0xb619, 0x20 },
1264        { 0xb61a, 0x20 },
1265        { 0xb61b, 0x20 },
1266        { 0xb61c, 0x0a },
1267        { 0xb61d, 0x0a },
1268        { 0xb666, 0x30 },
1269        { 0xb667, 0x30 },
1270        { 0xb668, 0x30 },
1271        { 0xb669, 0x30 },
1272        { 0xb66a, 0x14 },
1273        { 0xb66b, 0x14 },
1274        { 0xb66c, 0x20 },
1275        { 0xb66d, 0x20 },
1276        { 0xb66e, 0x20 },
1277        { 0xb66f, 0x20 },
1278        { 0xb670, 0x10 },
1279        { 0xb671, 0x10 },
1280        { 0x3237, 0x00 },
1281        { 0x3900, 0x00 },
1282        { 0x3901, 0x00 },
1283        { 0x3902, 0x00 },
1284        { 0x3904, 0x00 },
1285        { 0x3905, 0x00 },
1286        { 0x3906, 0x00 },
1287        { 0x3907, 0x00 },
1288        { 0x3908, 0x00 },
1289        { 0x3909, 0x00 },
1290        { 0x3912, 0x00 },
1291        { 0x3930, 0x00 },
1292        { 0x3931, 0x00 },
1293        { 0x3933, 0x00 },
1294        { 0x3934, 0x00 },
1295        { 0x3935, 0x00 },
1296        { 0x3936, 0x00 },
1297        { 0x3937, 0x00 },
1298        { 0x30ac, 0x00 },
1299};
1300
1301static const struct imx319_reg mode_1296x736_regs[] = {
1302        { 0x0112, 0x0a },
1303        { 0x0113, 0x0a },
1304        { 0x0114, 0x03 },
1305        { 0x0342, 0x08 },
1306        { 0x0343, 0x20 },
1307        { 0x0340, 0x18 },
1308        { 0x0341, 0x2a },
1309        { 0x0344, 0x00 },
1310        { 0x0345, 0x00 },
1311        { 0x0346, 0x01 },
1312        { 0x0347, 0xf0 },
1313        { 0x0348, 0x0c },
1314        { 0x0349, 0xcf },
1315        { 0x034a, 0x07 },
1316        { 0x034b, 0xaf },
1317        { 0x0220, 0x00 },
1318        { 0x0221, 0x11 },
1319        { 0x0381, 0x01 },
1320        { 0x0383, 0x01 },
1321        { 0x0385, 0x01 },
1322        { 0x0387, 0x01 },
1323        { 0x0900, 0x01 },
1324        { 0x0901, 0x22 },
1325        { 0x0902, 0x0a },
1326        { 0x3140, 0x02 },
1327        { 0x3141, 0x00 },
1328        { 0x3f0d, 0x0a },
1329        { 0x3f14, 0x01 },
1330        { 0x3f3c, 0x02 },
1331        { 0x3f4d, 0x01 },
1332        { 0x3f4c, 0x01 },
1333        { 0x4254, 0x7f },
1334        { 0x0401, 0x00 },
1335        { 0x0404, 0x00 },
1336        { 0x0405, 0x10 },
1337        { 0x0408, 0x00 },
1338        { 0x0409, 0xac },
1339        { 0x040a, 0x00 },
1340        { 0x040b, 0x00 },
1341        { 0x040c, 0x05 },
1342        { 0x040d, 0x10 },
1343        { 0x040e, 0x02 },
1344        { 0x040f, 0xe0 },
1345        { 0x034c, 0x05 },
1346        { 0x034d, 0x10 },
1347        { 0x034e, 0x02 },
1348        { 0x034f, 0xe0 },
1349        { 0x3261, 0x00 },
1350        { 0x3264, 0x00 },
1351        { 0x3265, 0x10 },
1352        { 0x0301, 0x05 },
1353        { 0x0303, 0x04 },
1354        { 0x0305, 0x04 },
1355        { 0x0306, 0x01 },
1356        { 0x0307, 0x92 },
1357        { 0x0309, 0x0a },
1358        { 0x030b, 0x02 },
1359        { 0x030d, 0x02 },
1360        { 0x030e, 0x00 },
1361        { 0x030f, 0xfa },
1362        { 0x0310, 0x00 },
1363        { 0x0820, 0x0f },
1364        { 0x0821, 0x13 },
1365        { 0x0822, 0x33 },
1366        { 0x0823, 0x33 },
1367        { 0x3e20, 0x01 },
1368        { 0x3e37, 0x00 },
1369        { 0x3e3b, 0x01 },
1370        { 0x38a3, 0x01 },
1371        { 0x38a8, 0x00 },
1372        { 0x38a9, 0x00 },
1373        { 0x38aa, 0x00 },
1374        { 0x38ab, 0x00 },
1375        { 0x3234, 0x00 },
1376        { 0x3fc1, 0x00 },
1377        { 0x3235, 0x00 },
1378        { 0x3802, 0x00 },
1379        { 0x3143, 0x04 },
1380        { 0x360a, 0x00 },
1381        { 0x0b00, 0x00 },
1382        { 0x0106, 0x00 },
1383        { 0x0b05, 0x01 },
1384        { 0x0b06, 0x01 },
1385        { 0x3230, 0x00 },
1386        { 0x3602, 0x01 },
1387        { 0x3607, 0x01 },
1388        { 0x3c00, 0x00 },
1389        { 0x3c01, 0xba },
1390        { 0x3c02, 0xc8 },
1391        { 0x3c03, 0xaa },
1392        { 0x3c04, 0x91 },
1393        { 0x3c05, 0x54 },
1394        { 0x3c06, 0x26 },
1395        { 0x3c07, 0x20 },
1396        { 0x3c08, 0x51 },
1397        { 0x3d80, 0x00 },
1398        { 0x3f50, 0x00 },
1399        { 0x3f56, 0x00 },
1400        { 0x3f57, 0x30 },
1401        { 0x3f78, 0x00 },
1402        { 0x3f79, 0x34 },
1403        { 0x3f7c, 0x00 },
1404        { 0x3f7d, 0x00 },
1405        { 0x3fba, 0x00 },
1406        { 0x3fbb, 0x00 },
1407        { 0xa081, 0x04 },
1408        { 0xe014, 0x00 },
1409        { 0x0202, 0x04 },
1410        { 0x0203, 0xf6 },
1411        { 0x0224, 0x01 },
1412        { 0x0225, 0xf4 },
1413        { 0x0204, 0x00 },
1414        { 0x0205, 0x00 },
1415        { 0x0216, 0x00 },
1416        { 0x0217, 0x00 },
1417        { 0x020e, 0x01 },
1418        { 0x020f, 0x00 },
1419        { 0x0210, 0x01 },
1420        { 0x0211, 0x00 },
1421        { 0x0212, 0x01 },
1422        { 0x0213, 0x00 },
1423        { 0x0214, 0x01 },
1424        { 0x0215, 0x00 },
1425        { 0x0218, 0x01 },
1426        { 0x0219, 0x00 },
1427        { 0x3614, 0x00 },
1428        { 0x3616, 0x0d },
1429        { 0x3617, 0x56 },
1430        { 0xb612, 0x20 },
1431        { 0xb613, 0x20 },
1432        { 0xb614, 0x20 },
1433        { 0xb615, 0x20 },
1434        { 0xb616, 0x0a },
1435        { 0xb617, 0x0a },
1436        { 0xb618, 0x20 },
1437        { 0xb619, 0x20 },
1438        { 0xb61a, 0x20 },
1439        { 0xb61b, 0x20 },
1440        { 0xb61c, 0x0a },
1441        { 0xb61d, 0x0a },
1442        { 0xb666, 0x30 },
1443        { 0xb667, 0x30 },
1444        { 0xb668, 0x30 },
1445        { 0xb669, 0x30 },
1446        { 0xb66a, 0x14 },
1447        { 0xb66b, 0x14 },
1448        { 0xb66c, 0x20 },
1449        { 0xb66d, 0x20 },
1450        { 0xb66e, 0x20 },
1451        { 0xb66f, 0x20 },
1452        { 0xb670, 0x10 },
1453        { 0xb671, 0x10 },
1454        { 0x3237, 0x00 },
1455        { 0x3900, 0x00 },
1456        { 0x3901, 0x00 },
1457        { 0x3902, 0x00 },
1458        { 0x3904, 0x00 },
1459        { 0x3905, 0x00 },
1460        { 0x3906, 0x00 },
1461        { 0x3907, 0x00 },
1462        { 0x3908, 0x00 },
1463        { 0x3909, 0x00 },
1464        { 0x3912, 0x00 },
1465        { 0x3930, 0x00 },
1466        { 0x3931, 0x00 },
1467        { 0x3933, 0x00 },
1468        { 0x3934, 0x00 },
1469        { 0x3935, 0x00 },
1470        { 0x3936, 0x00 },
1471        { 0x3937, 0x00 },
1472        { 0x30ac, 0x00 },
1473};
1474
1475static const struct imx319_reg mode_1280x720_regs[] = {
1476        { 0x0112, 0x0a },
1477        { 0x0113, 0x0a },
1478        { 0x0114, 0x03 },
1479        { 0x0342, 0x08 },
1480        { 0x0343, 0x20 },
1481        { 0x0340, 0x18 },
1482        { 0x0341, 0x2a },
1483        { 0x0344, 0x00 },
1484        { 0x0345, 0x00 },
1485        { 0x0346, 0x02 },
1486        { 0x0347, 0x00 },
1487        { 0x0348, 0x0c },
1488        { 0x0349, 0xcf },
1489        { 0x034a, 0x07 },
1490        { 0x034b, 0x9f },
1491        { 0x0220, 0x00 },
1492        { 0x0221, 0x11 },
1493        { 0x0381, 0x01 },
1494        { 0x0383, 0x01 },
1495        { 0x0385, 0x01 },
1496        { 0x0387, 0x01 },
1497        { 0x0900, 0x01 },
1498        { 0x0901, 0x22 },
1499        { 0x0902, 0x0a },
1500        { 0x3140, 0x02 },
1501        { 0x3141, 0x00 },
1502        { 0x3f0d, 0x0a },
1503        { 0x3f14, 0x01 },
1504        { 0x3f3c, 0x02 },
1505        { 0x3f4d, 0x01 },
1506        { 0x3f4c, 0x01 },
1507        { 0x4254, 0x7f },
1508        { 0x0401, 0x00 },
1509        { 0x0404, 0x00 },
1510        { 0x0405, 0x10 },
1511        { 0x0408, 0x00 },
1512        { 0x0409, 0xb4 },
1513        { 0x040a, 0x00 },
1514        { 0x040b, 0x00 },
1515        { 0x040c, 0x05 },
1516        { 0x040d, 0x00 },
1517        { 0x040e, 0x02 },
1518        { 0x040f, 0xd0 },
1519        { 0x034c, 0x05 },
1520        { 0x034d, 0x00 },
1521        { 0x034e, 0x02 },
1522        { 0x034f, 0xd0 },
1523        { 0x3261, 0x00 },
1524        { 0x3264, 0x00 },
1525        { 0x3265, 0x10 },
1526        { 0x0301, 0x05 },
1527        { 0x0303, 0x04 },
1528        { 0x0305, 0x04 },
1529        { 0x0306, 0x01 },
1530        { 0x0307, 0x92 },
1531        { 0x0309, 0x0a },
1532        { 0x030b, 0x02 },
1533        { 0x030d, 0x02 },
1534        { 0x030e, 0x00 },
1535        { 0x030f, 0xfa },
1536        { 0x0310, 0x00 },
1537        { 0x0820, 0x0f },
1538        { 0x0821, 0x13 },
1539        { 0x0822, 0x33 },
1540        { 0x0823, 0x33 },
1541        { 0x3e20, 0x01 },
1542        { 0x3e37, 0x00 },
1543        { 0x3e3b, 0x01 },
1544        { 0x38a3, 0x01 },
1545        { 0x38a8, 0x00 },
1546        { 0x38a9, 0x00 },
1547        { 0x38aa, 0x00 },
1548        { 0x38ab, 0x00 },
1549        { 0x3234, 0x00 },
1550        { 0x3fc1, 0x00 },
1551        { 0x3235, 0x00 },
1552        { 0x3802, 0x00 },
1553        { 0x3143, 0x04 },
1554        { 0x360a, 0x00 },
1555        { 0x0b00, 0x00 },
1556        { 0x0106, 0x00 },
1557        { 0x0b05, 0x01 },
1558        { 0x0b06, 0x01 },
1559        { 0x3230, 0x00 },
1560        { 0x3602, 0x01 },
1561        { 0x3607, 0x01 },
1562        { 0x3c00, 0x00 },
1563        { 0x3c01, 0xba },
1564        { 0x3c02, 0xc8 },
1565        { 0x3c03, 0xaa },
1566        { 0x3c04, 0x91 },
1567        { 0x3c05, 0x54 },
1568        { 0x3c06, 0x26 },
1569        { 0x3c07, 0x20 },
1570        { 0x3c08, 0x51 },
1571        { 0x3d80, 0x00 },
1572        { 0x3f50, 0x00 },
1573        { 0x3f56, 0x00 },
1574        { 0x3f57, 0x30 },
1575        { 0x3f78, 0x00 },
1576        { 0x3f79, 0x34 },
1577        { 0x3f7c, 0x00 },
1578        { 0x3f7d, 0x00 },
1579        { 0x3fba, 0x00 },
1580        { 0x3fbb, 0x00 },
1581        { 0xa081, 0x04 },
1582        { 0xe014, 0x00 },
1583        { 0x0202, 0x04 },
1584        { 0x0203, 0xf6 },
1585        { 0x0224, 0x01 },
1586        { 0x0225, 0xf4 },
1587        { 0x0204, 0x00 },
1588        { 0x0205, 0x00 },
1589        { 0x0216, 0x00 },
1590        { 0x0217, 0x00 },
1591        { 0x020e, 0x01 },
1592        { 0x020f, 0x00 },
1593        { 0x0210, 0x01 },
1594        { 0x0211, 0x00 },
1595        { 0x0212, 0x01 },
1596        { 0x0213, 0x00 },
1597        { 0x0214, 0x01 },
1598        { 0x0215, 0x00 },
1599        { 0x0218, 0x01 },
1600        { 0x0219, 0x00 },
1601        { 0x3614, 0x00 },
1602        { 0x3616, 0x0d },
1603        { 0x3617, 0x56 },
1604        { 0xb612, 0x20 },
1605        { 0xb613, 0x20 },
1606        { 0xb614, 0x20 },
1607        { 0xb615, 0x20 },
1608        { 0xb616, 0x0a },
1609        { 0xb617, 0x0a },
1610        { 0xb618, 0x20 },
1611        { 0xb619, 0x20 },
1612        { 0xb61a, 0x20 },
1613        { 0xb61b, 0x20 },
1614        { 0xb61c, 0x0a },
1615        { 0xb61d, 0x0a },
1616        { 0xb666, 0x30 },
1617        { 0xb667, 0x30 },
1618        { 0xb668, 0x30 },
1619        { 0xb669, 0x30 },
1620        { 0xb66a, 0x14 },
1621        { 0xb66b, 0x14 },
1622        { 0xb66c, 0x20 },
1623        { 0xb66d, 0x20 },
1624        { 0xb66e, 0x20 },
1625        { 0xb66f, 0x20 },
1626        { 0xb670, 0x10 },
1627        { 0xb671, 0x10 },
1628        { 0x3237, 0x00 },
1629        { 0x3900, 0x00 },
1630        { 0x3901, 0x00 },
1631        { 0x3902, 0x00 },
1632        { 0x3904, 0x00 },
1633        { 0x3905, 0x00 },
1634        { 0x3906, 0x00 },
1635        { 0x3907, 0x00 },
1636        { 0x3908, 0x00 },
1637        { 0x3909, 0x00 },
1638        { 0x3912, 0x00 },
1639        { 0x3930, 0x00 },
1640        { 0x3931, 0x00 },
1641        { 0x3933, 0x00 },
1642        { 0x3934, 0x00 },
1643        { 0x3935, 0x00 },
1644        { 0x3936, 0x00 },
1645        { 0x3937, 0x00 },
1646        { 0x30ac, 0x00 },
1647};
1648
1649static const char * const imx319_test_pattern_menu[] = {
1650        "Disabled",
1651        "Solid Colour",
1652        "Eight Vertical Colour Bars",
1653        "Colour Bars With Fade to Grey",
1654        "Pseudorandom Sequence (PN9)",
1655};
1656
1657/* supported link frequencies */
1658static const s64 link_freq_menu_items[] = {
1659        IMX319_LINK_FREQ_DEFAULT,
1660};
1661
1662/* Mode configs */
1663static const struct imx319_mode supported_modes[] = {
1664        {
1665                .width = 3280,
1666                .height = 2464,
1667                .fll_def = 3242,
1668                .fll_min = 3242,
1669                .llp = 3968,
1670                .link_freq_index = IMX319_LINK_FREQ_INDEX,
1671                .reg_list = {
1672                        .num_of_regs = ARRAY_SIZE(mode_3280x2464_regs),
1673                        .regs = mode_3280x2464_regs,
1674                },
1675        },
1676        {
1677                .width = 3264,
1678                .height = 2448,
1679                .fll_def = 3242,
1680                .fll_min = 3242,
1681                .llp = 3968,
1682                .link_freq_index = IMX319_LINK_FREQ_INDEX,
1683                .reg_list = {
1684                        .num_of_regs = ARRAY_SIZE(mode_3264x2448_regs),
1685                        .regs = mode_3264x2448_regs,
1686                },
1687        },
1688        {
1689                .width = 1936,
1690                .height = 1096,
1691                .fll_def = 3242,
1692                .fll_min = 3242,
1693                .llp = 3968,
1694                .link_freq_index = IMX319_LINK_FREQ_INDEX,
1695                .reg_list = {
1696                        .num_of_regs = ARRAY_SIZE(mode_1936x1096_regs),
1697                        .regs = mode_1936x1096_regs,
1698                },
1699        },
1700        {
1701                .width = 1920,
1702                .height = 1080,
1703                .fll_def = 3242,
1704                .fll_min = 3242,
1705                .llp = 3968,
1706                .link_freq_index = IMX319_LINK_FREQ_INDEX,
1707                .reg_list = {
1708                        .num_of_regs = ARRAY_SIZE(mode_1920x1080_regs),
1709                        .regs = mode_1920x1080_regs,
1710                },
1711        },
1712        {
1713                .width = 1640,
1714                .height = 1232,
1715                .fll_def = 5146,
1716                .fll_min = 5146,
1717                .llp = 2500,
1718                .link_freq_index = IMX319_LINK_FREQ_INDEX,
1719                .reg_list = {
1720                        .num_of_regs = ARRAY_SIZE(mode_1640x1232_regs),
1721                        .regs = mode_1640x1232_regs,
1722                },
1723        },
1724        {
1725                .width = 1640,
1726                .height = 922,
1727                .fll_def = 5146,
1728                .fll_min = 5146,
1729                .llp = 2500,
1730                .link_freq_index = IMX319_LINK_FREQ_INDEX,
1731                .reg_list = {
1732                        .num_of_regs = ARRAY_SIZE(mode_1640x922_regs),
1733                        .regs = mode_1640x922_regs,
1734                },
1735        },
1736        {
1737                .width = 1296,
1738                .height = 736,
1739                .fll_def = 5146,
1740                .fll_min = 5146,
1741                .llp = 2500,
1742                .link_freq_index = IMX319_LINK_FREQ_INDEX,
1743                .reg_list = {
1744                        .num_of_regs = ARRAY_SIZE(mode_1296x736_regs),
1745                        .regs = mode_1296x736_regs,
1746                },
1747        },
1748        {
1749                .width = 1280,
1750                .height = 720,
1751                .fll_def = 5146,
1752                .fll_min = 5146,
1753                .llp = 2500,
1754                .link_freq_index = IMX319_LINK_FREQ_INDEX,
1755                .reg_list = {
1756                        .num_of_regs = ARRAY_SIZE(mode_1280x720_regs),
1757                        .regs = mode_1280x720_regs,
1758                },
1759        },
1760};
1761
1762static inline struct imx319 *to_imx319(struct v4l2_subdev *_sd)
1763{
1764        return container_of(_sd, struct imx319, sd);
1765}
1766
1767/* Get bayer order based on flip setting. */
1768static u32 imx319_get_format_code(struct imx319 *imx319)
1769{
1770        /*
1771         * Only one bayer order is supported.
1772         * It depends on the flip settings.
1773         */
1774        u32 code;
1775        static const u32 codes[2][2] = {
1776                { MEDIA_BUS_FMT_SRGGB10_1X10, MEDIA_BUS_FMT_SGRBG10_1X10, },
1777                { MEDIA_BUS_FMT_SGBRG10_1X10, MEDIA_BUS_FMT_SBGGR10_1X10, },
1778        };
1779
1780        lockdep_assert_held(&imx319->mutex);
1781        code = codes[imx319->vflip->val][imx319->hflip->val];
1782
1783        return code;
1784}
1785
1786/* Read registers up to 4 at a time */
1787static int imx319_read_reg(struct imx319 *imx319, u16 reg, u32 len, u32 *val)
1788{
1789        struct i2c_client *client = v4l2_get_subdevdata(&imx319->sd);
1790        struct i2c_msg msgs[2];
1791        u8 addr_buf[2];
1792        u8 data_buf[4] = { 0 };
1793        int ret;
1794
1795        if (len > 4)
1796                return -EINVAL;
1797
1798        put_unaligned_be16(reg, addr_buf);
1799        /* Write register address */
1800        msgs[0].addr = client->addr;
1801        msgs[0].flags = 0;
1802        msgs[0].len = ARRAY_SIZE(addr_buf);
1803        msgs[0].buf = addr_buf;
1804
1805        /* Read data from register */
1806        msgs[1].addr = client->addr;
1807        msgs[1].flags = I2C_M_RD;
1808        msgs[1].len = len;
1809        msgs[1].buf = &data_buf[4 - len];
1810
1811        ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
1812        if (ret != ARRAY_SIZE(msgs))
1813                return -EIO;
1814
1815        *val = get_unaligned_be32(data_buf);
1816
1817        return 0;
1818}
1819
1820/* Write registers up to 4 at a time */
1821static int imx319_write_reg(struct imx319 *imx319, u16 reg, u32 len, u32 val)
1822{
1823        struct i2c_client *client = v4l2_get_subdevdata(&imx319->sd);
1824        u8 buf[6];
1825
1826        if (len > 4)
1827                return -EINVAL;
1828
1829        put_unaligned_be16(reg, buf);
1830        put_unaligned_be32(val << (8 * (4 - len)), buf + 2);
1831        if (i2c_master_send(client, buf, len + 2) != len + 2)
1832                return -EIO;
1833
1834        return 0;
1835}
1836
1837/* Write a list of registers */
1838static int imx319_write_regs(struct imx319 *imx319,
1839                             const struct imx319_reg *regs, u32 len)
1840{
1841        struct i2c_client *client = v4l2_get_subdevdata(&imx319->sd);
1842        int ret;
1843        u32 i;
1844
1845        for (i = 0; i < len; i++) {
1846                ret = imx319_write_reg(imx319, regs[i].address, 1, regs[i].val);
1847                if (ret) {
1848                        dev_err_ratelimited(&client->dev,
1849                                            "write reg 0x%4.4x return err %d",
1850                                            regs[i].address, ret);
1851                        return ret;
1852                }
1853        }
1854
1855        return 0;
1856}
1857
1858/* Open sub-device */
1859static int imx319_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
1860{
1861        struct imx319 *imx319 = to_imx319(sd);
1862        struct v4l2_mbus_framefmt *try_fmt =
1863                v4l2_subdev_get_try_format(sd, fh->state, 0);
1864
1865        mutex_lock(&imx319->mutex);
1866
1867        /* Initialize try_fmt */
1868        try_fmt->width = imx319->cur_mode->width;
1869        try_fmt->height = imx319->cur_mode->height;
1870        try_fmt->code = imx319_get_format_code(imx319);
1871        try_fmt->field = V4L2_FIELD_NONE;
1872
1873        mutex_unlock(&imx319->mutex);
1874
1875        return 0;
1876}
1877
1878static int imx319_set_ctrl(struct v4l2_ctrl *ctrl)
1879{
1880        struct imx319 *imx319 = container_of(ctrl->handler,
1881                                             struct imx319, ctrl_handler);
1882        struct i2c_client *client = v4l2_get_subdevdata(&imx319->sd);
1883        s64 max;
1884        int ret;
1885
1886        /* Propagate change of current control to all related controls */
1887        switch (ctrl->id) {
1888        case V4L2_CID_VBLANK:
1889                /* Update max exposure while meeting expected vblanking */
1890                max = imx319->cur_mode->height + ctrl->val - 18;
1891                __v4l2_ctrl_modify_range(imx319->exposure,
1892                                         imx319->exposure->minimum,
1893                                         max, imx319->exposure->step, max);
1894                break;
1895        }
1896
1897        /*
1898         * Applying V4L2 control value only happens
1899         * when power is up for streaming
1900         */
1901        if (!pm_runtime_get_if_in_use(&client->dev))
1902                return 0;
1903
1904        switch (ctrl->id) {
1905        case V4L2_CID_ANALOGUE_GAIN:
1906                /* Analog gain = 1024/(1024 - ctrl->val) times */
1907                ret = imx319_write_reg(imx319, IMX319_REG_ANALOG_GAIN, 2,
1908                                       ctrl->val);
1909                break;
1910        case V4L2_CID_DIGITAL_GAIN:
1911                ret = imx319_write_reg(imx319, IMX319_REG_DIG_GAIN_GLOBAL, 2,
1912                                       ctrl->val);
1913                break;
1914        case V4L2_CID_EXPOSURE:
1915                ret = imx319_write_reg(imx319, IMX319_REG_EXPOSURE, 2,
1916                                       ctrl->val);
1917                break;
1918        case V4L2_CID_VBLANK:
1919                /* Update FLL that meets expected vertical blanking */
1920                ret = imx319_write_reg(imx319, IMX319_REG_FLL, 2,
1921                                       imx319->cur_mode->height + ctrl->val);
1922                break;
1923        case V4L2_CID_TEST_PATTERN:
1924                ret = imx319_write_reg(imx319, IMX319_REG_TEST_PATTERN,
1925                                       2, ctrl->val);
1926                break;
1927        case V4L2_CID_HFLIP:
1928        case V4L2_CID_VFLIP:
1929                ret = imx319_write_reg(imx319, IMX319_REG_ORIENTATION, 1,
1930                                       imx319->hflip->val |
1931                                       imx319->vflip->val << 1);
1932                break;
1933        default:
1934                ret = -EINVAL;
1935                dev_info(&client->dev, "ctrl(id:0x%x,val:0x%x) is not handled",
1936                         ctrl->id, ctrl->val);
1937                break;
1938        }
1939
1940        pm_runtime_put(&client->dev);
1941
1942        return ret;
1943}
1944
1945static const struct v4l2_ctrl_ops imx319_ctrl_ops = {
1946        .s_ctrl = imx319_set_ctrl,
1947};
1948
1949static int imx319_enum_mbus_code(struct v4l2_subdev *sd,
1950                                 struct v4l2_subdev_state *sd_state,
1951                                 struct v4l2_subdev_mbus_code_enum *code)
1952{
1953        struct imx319 *imx319 = to_imx319(sd);
1954
1955        if (code->index > 0)
1956                return -EINVAL;
1957
1958        mutex_lock(&imx319->mutex);
1959        code->code = imx319_get_format_code(imx319);
1960        mutex_unlock(&imx319->mutex);
1961
1962        return 0;
1963}
1964
1965static int imx319_enum_frame_size(struct v4l2_subdev *sd,
1966                                  struct v4l2_subdev_state *sd_state,
1967                                  struct v4l2_subdev_frame_size_enum *fse)
1968{
1969        struct imx319 *imx319 = to_imx319(sd);
1970
1971        if (fse->index >= ARRAY_SIZE(supported_modes))
1972                return -EINVAL;
1973
1974        mutex_lock(&imx319->mutex);
1975        if (fse->code != imx319_get_format_code(imx319)) {
1976                mutex_unlock(&imx319->mutex);
1977                return -EINVAL;
1978        }
1979        mutex_unlock(&imx319->mutex);
1980
1981        fse->min_width = supported_modes[fse->index].width;
1982        fse->max_width = fse->min_width;
1983        fse->min_height = supported_modes[fse->index].height;
1984        fse->max_height = fse->min_height;
1985
1986        return 0;
1987}
1988
1989static void imx319_update_pad_format(struct imx319 *imx319,
1990                                     const struct imx319_mode *mode,
1991                                     struct v4l2_subdev_format *fmt)
1992{
1993        fmt->format.width = mode->width;
1994        fmt->format.height = mode->height;
1995        fmt->format.code = imx319_get_format_code(imx319);
1996        fmt->format.field = V4L2_FIELD_NONE;
1997}
1998
1999static int imx319_do_get_pad_format(struct imx319 *imx319,
2000                                    struct v4l2_subdev_state *sd_state,
2001                                    struct v4l2_subdev_format *fmt)
2002{
2003        struct v4l2_mbus_framefmt *framefmt;
2004        struct v4l2_subdev *sd = &imx319->sd;
2005
2006        if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
2007                framefmt = v4l2_subdev_get_try_format(sd, sd_state, fmt->pad);
2008                fmt->format = *framefmt;
2009        } else {
2010                imx319_update_pad_format(imx319, imx319->cur_mode, fmt);
2011        }
2012
2013        return 0;
2014}
2015
2016static int imx319_get_pad_format(struct v4l2_subdev *sd,
2017                                 struct v4l2_subdev_state *sd_state,
2018                                 struct v4l2_subdev_format *fmt)
2019{
2020        struct imx319 *imx319 = to_imx319(sd);
2021        int ret;
2022
2023        mutex_lock(&imx319->mutex);
2024        ret = imx319_do_get_pad_format(imx319, sd_state, fmt);
2025        mutex_unlock(&imx319->mutex);
2026
2027        return ret;
2028}
2029
2030static int
2031imx319_set_pad_format(struct v4l2_subdev *sd,
2032                      struct v4l2_subdev_state *sd_state,
2033                      struct v4l2_subdev_format *fmt)
2034{
2035        struct imx319 *imx319 = to_imx319(sd);
2036        const struct imx319_mode *mode;
2037        struct v4l2_mbus_framefmt *framefmt;
2038        s32 vblank_def;
2039        s32 vblank_min;
2040        s64 h_blank;
2041        u64 pixel_rate;
2042        u32 height;
2043
2044        mutex_lock(&imx319->mutex);
2045
2046        /*
2047         * Only one bayer order is supported.
2048         * It depends on the flip settings.
2049         */
2050        fmt->format.code = imx319_get_format_code(imx319);
2051
2052        mode = v4l2_find_nearest_size(supported_modes,
2053                                      ARRAY_SIZE(supported_modes),
2054                                      width, height,
2055                                      fmt->format.width, fmt->format.height);
2056        imx319_update_pad_format(imx319, mode, fmt);
2057        if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
2058                framefmt = v4l2_subdev_get_try_format(sd, sd_state, fmt->pad);
2059                *framefmt = fmt->format;
2060        } else {
2061                imx319->cur_mode = mode;
2062                pixel_rate = imx319->link_def_freq * 2 * 4;
2063                do_div(pixel_rate, 10);
2064                __v4l2_ctrl_s_ctrl_int64(imx319->pixel_rate, pixel_rate);
2065                /* Update limits and set FPS to default */
2066                height = imx319->cur_mode->height;
2067                vblank_def = imx319->cur_mode->fll_def - height;
2068                vblank_min = imx319->cur_mode->fll_min - height;
2069                height = IMX319_FLL_MAX - height;
2070                __v4l2_ctrl_modify_range(imx319->vblank, vblank_min, height, 1,
2071                                         vblank_def);
2072                __v4l2_ctrl_s_ctrl(imx319->vblank, vblank_def);
2073                h_blank = mode->llp - imx319->cur_mode->width;
2074                /*
2075                 * Currently hblank is not changeable.
2076                 * So FPS control is done only by vblank.
2077                 */
2078                __v4l2_ctrl_modify_range(imx319->hblank, h_blank,
2079                                         h_blank, 1, h_blank);
2080        }
2081
2082        mutex_unlock(&imx319->mutex);
2083
2084        return 0;
2085}
2086
2087/* Start streaming */
2088static int imx319_start_streaming(struct imx319 *imx319)
2089{
2090        struct i2c_client *client = v4l2_get_subdevdata(&imx319->sd);
2091        const struct imx319_reg_list *reg_list;
2092        int ret;
2093
2094        /* Global Setting */
2095        reg_list = &imx319_global_setting;
2096        ret = imx319_write_regs(imx319, reg_list->regs, reg_list->num_of_regs);
2097        if (ret) {
2098                dev_err(&client->dev, "failed to set global settings");
2099                return ret;
2100        }
2101
2102        /* Apply default values of current mode */
2103        reg_list = &imx319->cur_mode->reg_list;
2104        ret = imx319_write_regs(imx319, reg_list->regs, reg_list->num_of_regs);
2105        if (ret) {
2106                dev_err(&client->dev, "failed to set mode");
2107                return ret;
2108        }
2109
2110        /* set digital gain control to all color mode */
2111        ret = imx319_write_reg(imx319, IMX319_REG_DPGA_USE_GLOBAL_GAIN, 1, 1);
2112        if (ret)
2113                return ret;
2114
2115        /* Apply customized values from user */
2116        ret =  __v4l2_ctrl_handler_setup(imx319->sd.ctrl_handler);
2117        if (ret)
2118                return ret;
2119
2120        return imx319_write_reg(imx319, IMX319_REG_MODE_SELECT,
2121                                1, IMX319_MODE_STREAMING);
2122}
2123
2124/* Stop streaming */
2125static int imx319_stop_streaming(struct imx319 *imx319)
2126{
2127        return imx319_write_reg(imx319, IMX319_REG_MODE_SELECT,
2128                                1, IMX319_MODE_STANDBY);
2129}
2130
2131static int imx319_set_stream(struct v4l2_subdev *sd, int enable)
2132{
2133        struct imx319 *imx319 = to_imx319(sd);
2134        struct i2c_client *client = v4l2_get_subdevdata(sd);
2135        int ret = 0;
2136
2137        mutex_lock(&imx319->mutex);
2138        if (imx319->streaming == enable) {
2139                mutex_unlock(&imx319->mutex);
2140                return 0;
2141        }
2142
2143        if (enable) {
2144                ret = pm_runtime_resume_and_get(&client->dev);
2145                if (ret < 0)
2146                        goto err_unlock;
2147
2148                /*
2149                 * Apply default & customized values
2150                 * and then start streaming.
2151                 */
2152                ret = imx319_start_streaming(imx319);
2153                if (ret)
2154                        goto err_rpm_put;
2155        } else {
2156                imx319_stop_streaming(imx319);
2157                pm_runtime_put(&client->dev);
2158        }
2159
2160        imx319->streaming = enable;
2161
2162        /* vflip and hflip cannot change during streaming */
2163        __v4l2_ctrl_grab(imx319->vflip, enable);
2164        __v4l2_ctrl_grab(imx319->hflip, enable);
2165
2166        mutex_unlock(&imx319->mutex);
2167
2168        return ret;
2169
2170err_rpm_put:
2171        pm_runtime_put(&client->dev);
2172err_unlock:
2173        mutex_unlock(&imx319->mutex);
2174
2175        return ret;
2176}
2177
2178static int __maybe_unused imx319_suspend(struct device *dev)
2179{
2180        struct v4l2_subdev *sd = dev_get_drvdata(dev);
2181        struct imx319 *imx319 = to_imx319(sd);
2182
2183        if (imx319->streaming)
2184                imx319_stop_streaming(imx319);
2185
2186        return 0;
2187}
2188
2189static int __maybe_unused imx319_resume(struct device *dev)
2190{
2191        struct v4l2_subdev *sd = dev_get_drvdata(dev);
2192        struct imx319 *imx319 = to_imx319(sd);
2193        int ret;
2194
2195        if (imx319->streaming) {
2196                ret = imx319_start_streaming(imx319);
2197                if (ret)
2198                        goto error;
2199        }
2200
2201        return 0;
2202
2203error:
2204        imx319_stop_streaming(imx319);
2205        imx319->streaming = 0;
2206        return ret;
2207}
2208
2209/* Verify chip ID */
2210static int imx319_identify_module(struct imx319 *imx319)
2211{
2212        struct i2c_client *client = v4l2_get_subdevdata(&imx319->sd);
2213        int ret;
2214        u32 val;
2215
2216        ret = imx319_read_reg(imx319, IMX319_REG_CHIP_ID, 2, &val);
2217        if (ret)
2218                return ret;
2219
2220        if (val != IMX319_CHIP_ID) {
2221                dev_err(&client->dev, "chip id mismatch: %x!=%x",
2222                        IMX319_CHIP_ID, val);
2223                return -EIO;
2224        }
2225
2226        return 0;
2227}
2228
2229static const struct v4l2_subdev_core_ops imx319_subdev_core_ops = {
2230        .subscribe_event = v4l2_ctrl_subdev_subscribe_event,
2231        .unsubscribe_event = v4l2_event_subdev_unsubscribe,
2232};
2233
2234static const struct v4l2_subdev_video_ops imx319_video_ops = {
2235        .s_stream = imx319_set_stream,
2236};
2237
2238static const struct v4l2_subdev_pad_ops imx319_pad_ops = {
2239        .enum_mbus_code = imx319_enum_mbus_code,
2240        .get_fmt = imx319_get_pad_format,
2241        .set_fmt = imx319_set_pad_format,
2242        .enum_frame_size = imx319_enum_frame_size,
2243};
2244
2245static const struct v4l2_subdev_ops imx319_subdev_ops = {
2246        .core = &imx319_subdev_core_ops,
2247        .video = &imx319_video_ops,
2248        .pad = &imx319_pad_ops,
2249};
2250
2251static const struct media_entity_operations imx319_subdev_entity_ops = {
2252        .link_validate = v4l2_subdev_link_validate,
2253};
2254
2255static const struct v4l2_subdev_internal_ops imx319_internal_ops = {
2256        .open = imx319_open,
2257};
2258
2259/* Initialize control handlers */
2260static int imx319_init_controls(struct imx319 *imx319)
2261{
2262        struct i2c_client *client = v4l2_get_subdevdata(&imx319->sd);
2263        struct v4l2_ctrl_handler *ctrl_hdlr;
2264        s64 exposure_max;
2265        s64 vblank_def;
2266        s64 vblank_min;
2267        s64 hblank;
2268        u64 pixel_rate;
2269        const struct imx319_mode *mode;
2270        u32 max;
2271        int ret;
2272
2273        ctrl_hdlr = &imx319->ctrl_handler;
2274        ret = v4l2_ctrl_handler_init(ctrl_hdlr, 10);
2275        if (ret)
2276                return ret;
2277
2278        ctrl_hdlr->lock = &imx319->mutex;
2279        max = ARRAY_SIZE(link_freq_menu_items) - 1;
2280        imx319->link_freq = v4l2_ctrl_new_int_menu(ctrl_hdlr, &imx319_ctrl_ops,
2281                                                   V4L2_CID_LINK_FREQ, max, 0,
2282                                                   link_freq_menu_items);
2283        if (imx319->link_freq)
2284                imx319->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
2285
2286        /* pixel_rate = link_freq * 2 * nr_of_lanes / bits_per_sample */
2287        pixel_rate = imx319->link_def_freq * 2 * 4;
2288        do_div(pixel_rate, 10);
2289        /* By default, PIXEL_RATE is read only */
2290        imx319->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &imx319_ctrl_ops,
2291                                               V4L2_CID_PIXEL_RATE, pixel_rate,
2292                                               pixel_rate, 1, pixel_rate);
2293
2294        /* Initial vblank/hblank/exposure parameters based on current mode */
2295        mode = imx319->cur_mode;
2296        vblank_def = mode->fll_def - mode->height;
2297        vblank_min = mode->fll_min - mode->height;
2298        imx319->vblank = v4l2_ctrl_new_std(ctrl_hdlr, &imx319_ctrl_ops,
2299                                           V4L2_CID_VBLANK, vblank_min,
2300                                           IMX319_FLL_MAX - mode->height,
2301                                           1, vblank_def);
2302
2303        hblank = mode->llp - mode->width;
2304        imx319->hblank = v4l2_ctrl_new_std(ctrl_hdlr, &imx319_ctrl_ops,
2305                                           V4L2_CID_HBLANK, hblank, hblank,
2306                                           1, hblank);
2307        if (imx319->hblank)
2308                imx319->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
2309
2310        /* fll >= exposure time + adjust parameter (default value is 18) */
2311        exposure_max = mode->fll_def - 18;
2312        imx319->exposure = v4l2_ctrl_new_std(ctrl_hdlr, &imx319_ctrl_ops,
2313                                             V4L2_CID_EXPOSURE,
2314                                             IMX319_EXPOSURE_MIN, exposure_max,
2315                                             IMX319_EXPOSURE_STEP,
2316                                             IMX319_EXPOSURE_DEFAULT);
2317
2318        imx319->hflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx319_ctrl_ops,
2319                                          V4L2_CID_HFLIP, 0, 1, 1, 0);
2320        imx319->vflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx319_ctrl_ops,
2321                                          V4L2_CID_VFLIP, 0, 1, 1, 0);
2322
2323        v4l2_ctrl_new_std(ctrl_hdlr, &imx319_ctrl_ops, V4L2_CID_ANALOGUE_GAIN,
2324                          IMX319_ANA_GAIN_MIN, IMX319_ANA_GAIN_MAX,
2325                          IMX319_ANA_GAIN_STEP, IMX319_ANA_GAIN_DEFAULT);
2326
2327        /* Digital gain */
2328        v4l2_ctrl_new_std(ctrl_hdlr, &imx319_ctrl_ops, V4L2_CID_DIGITAL_GAIN,
2329                          IMX319_DGTL_GAIN_MIN, IMX319_DGTL_GAIN_MAX,
2330                          IMX319_DGTL_GAIN_STEP, IMX319_DGTL_GAIN_DEFAULT);
2331
2332        v4l2_ctrl_new_std_menu_items(ctrl_hdlr, &imx319_ctrl_ops,
2333                                     V4L2_CID_TEST_PATTERN,
2334                                     ARRAY_SIZE(imx319_test_pattern_menu) - 1,
2335                                     0, 0, imx319_test_pattern_menu);
2336        if (ctrl_hdlr->error) {
2337                ret = ctrl_hdlr->error;
2338                dev_err(&client->dev, "control init failed: %d", ret);
2339                goto error;
2340        }
2341
2342        imx319->sd.ctrl_handler = ctrl_hdlr;
2343
2344        return 0;
2345
2346error:
2347        v4l2_ctrl_handler_free(ctrl_hdlr);
2348
2349        return ret;
2350}
2351
2352static struct imx319_hwcfg *imx319_get_hwcfg(struct device *dev)
2353{
2354        struct imx319_hwcfg *cfg;
2355        struct v4l2_fwnode_endpoint bus_cfg = {
2356                .bus_type = V4L2_MBUS_CSI2_DPHY
2357        };
2358        struct fwnode_handle *ep;
2359        struct fwnode_handle *fwnode = dev_fwnode(dev);
2360        unsigned int i;
2361        int ret;
2362
2363        if (!fwnode)
2364                return NULL;
2365
2366        ep = fwnode_graph_get_next_endpoint(fwnode, NULL);
2367        if (!ep)
2368                return NULL;
2369
2370        ret = v4l2_fwnode_endpoint_alloc_parse(ep, &bus_cfg);
2371        if (ret)
2372                goto out_err;
2373
2374        cfg = devm_kzalloc(dev, sizeof(*cfg), GFP_KERNEL);
2375        if (!cfg)
2376                goto out_err;
2377
2378        ret = fwnode_property_read_u32(dev_fwnode(dev), "clock-frequency",
2379                                       &cfg->ext_clk);
2380        if (ret) {
2381                dev_err(dev, "can't get clock frequency");
2382                goto out_err;
2383        }
2384
2385        dev_dbg(dev, "ext clk: %d", cfg->ext_clk);
2386        if (cfg->ext_clk != IMX319_EXT_CLK) {
2387                dev_err(dev, "external clock %d is not supported",
2388                        cfg->ext_clk);
2389                goto out_err;
2390        }
2391
2392        dev_dbg(dev, "num of link freqs: %d", bus_cfg.nr_of_link_frequencies);
2393        if (!bus_cfg.nr_of_link_frequencies) {
2394                dev_warn(dev, "no link frequencies defined");
2395                goto out_err;
2396        }
2397
2398        cfg->nr_of_link_freqs = bus_cfg.nr_of_link_frequencies;
2399        cfg->link_freqs = devm_kcalloc(dev,
2400                                       bus_cfg.nr_of_link_frequencies + 1,
2401                                       sizeof(*cfg->link_freqs), GFP_KERNEL);
2402        if (!cfg->link_freqs)
2403                goto out_err;
2404
2405        for (i = 0; i < bus_cfg.nr_of_link_frequencies; i++) {
2406                cfg->link_freqs[i] = bus_cfg.link_frequencies[i];
2407                dev_dbg(dev, "link_freq[%d] = %lld", i, cfg->link_freqs[i]);
2408        }
2409
2410        v4l2_fwnode_endpoint_free(&bus_cfg);
2411        fwnode_handle_put(ep);
2412        return cfg;
2413
2414out_err:
2415        v4l2_fwnode_endpoint_free(&bus_cfg);
2416        fwnode_handle_put(ep);
2417        return NULL;
2418}
2419
2420static int imx319_probe(struct i2c_client *client)
2421{
2422        struct imx319 *imx319;
2423        int ret;
2424        u32 i;
2425
2426        imx319 = devm_kzalloc(&client->dev, sizeof(*imx319), GFP_KERNEL);
2427        if (!imx319)
2428                return -ENOMEM;
2429
2430        mutex_init(&imx319->mutex);
2431
2432        /* Initialize subdev */
2433        v4l2_i2c_subdev_init(&imx319->sd, client, &imx319_subdev_ops);
2434
2435        /* Check module identity */
2436        ret = imx319_identify_module(imx319);
2437        if (ret) {
2438                dev_err(&client->dev, "failed to find sensor: %d", ret);
2439                goto error_probe;
2440        }
2441
2442        imx319->hwcfg = imx319_get_hwcfg(&client->dev);
2443        if (!imx319->hwcfg) {
2444                dev_err(&client->dev, "failed to get hwcfg");
2445                ret = -ENODEV;
2446                goto error_probe;
2447        }
2448
2449        imx319->link_def_freq = link_freq_menu_items[IMX319_LINK_FREQ_INDEX];
2450        for (i = 0; i < imx319->hwcfg->nr_of_link_freqs; i++) {
2451                if (imx319->hwcfg->link_freqs[i] == imx319->link_def_freq) {
2452                        dev_dbg(&client->dev, "link freq index %d matched", i);
2453                        break;
2454                }
2455        }
2456
2457        if (i == imx319->hwcfg->nr_of_link_freqs) {
2458                dev_err(&client->dev, "no link frequency supported");
2459                ret = -EINVAL;
2460                goto error_probe;
2461        }
2462
2463        /* Set default mode to max resolution */
2464        imx319->cur_mode = &supported_modes[0];
2465
2466        ret = imx319_init_controls(imx319);
2467        if (ret) {
2468                dev_err(&client->dev, "failed to init controls: %d", ret);
2469                goto error_probe;
2470        }
2471
2472        /* Initialize subdev */
2473        imx319->sd.internal_ops = &imx319_internal_ops;
2474        imx319->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
2475                V4L2_SUBDEV_FL_HAS_EVENTS;
2476        imx319->sd.entity.ops = &imx319_subdev_entity_ops;
2477        imx319->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
2478
2479        /* Initialize source pad */
2480        imx319->pad.flags = MEDIA_PAD_FL_SOURCE;
2481        ret = media_entity_pads_init(&imx319->sd.entity, 1, &imx319->pad);
2482        if (ret) {
2483                dev_err(&client->dev, "failed to init entity pads: %d", ret);
2484                goto error_handler_free;
2485        }
2486
2487        ret = v4l2_async_register_subdev_sensor(&imx319->sd);
2488        if (ret < 0)
2489                goto error_media_entity;
2490
2491        /*
2492         * Device is already turned on by i2c-core with ACPI domain PM.
2493         * Enable runtime PM and turn off the device.
2494         */
2495        pm_runtime_set_active(&client->dev);
2496        pm_runtime_enable(&client->dev);
2497        pm_runtime_idle(&client->dev);
2498
2499        return 0;
2500
2501error_media_entity:
2502        media_entity_cleanup(&imx319->sd.entity);
2503
2504error_handler_free:
2505        v4l2_ctrl_handler_free(imx319->sd.ctrl_handler);
2506
2507error_probe:
2508        mutex_destroy(&imx319->mutex);
2509
2510        return ret;
2511}
2512
2513static int imx319_remove(struct i2c_client *client)
2514{
2515        struct v4l2_subdev *sd = i2c_get_clientdata(client);
2516        struct imx319 *imx319 = to_imx319(sd);
2517
2518        v4l2_async_unregister_subdev(sd);
2519        media_entity_cleanup(&sd->entity);
2520        v4l2_ctrl_handler_free(sd->ctrl_handler);
2521
2522        pm_runtime_disable(&client->dev);
2523        pm_runtime_set_suspended(&client->dev);
2524
2525        mutex_destroy(&imx319->mutex);
2526
2527        return 0;
2528}
2529
2530static const struct dev_pm_ops imx319_pm_ops = {
2531        SET_SYSTEM_SLEEP_PM_OPS(imx319_suspend, imx319_resume)
2532};
2533
2534static const struct acpi_device_id imx319_acpi_ids[] __maybe_unused = {
2535        { "SONY319A" },
2536        { /* sentinel */ }
2537};
2538MODULE_DEVICE_TABLE(acpi, imx319_acpi_ids);
2539
2540static struct i2c_driver imx319_i2c_driver = {
2541        .driver = {
2542                .name = "imx319",
2543                .pm = &imx319_pm_ops,
2544                .acpi_match_table = ACPI_PTR(imx319_acpi_ids),
2545        },
2546        .probe_new = imx319_probe,
2547        .remove = imx319_remove,
2548};
2549module_i2c_driver(imx319_i2c_driver);
2550
2551MODULE_AUTHOR("Qiu, Tianshu <tian.shu.qiu@intel.com>");
2552MODULE_AUTHOR("Rapolu, Chiranjeevi <chiranjeevi.rapolu@intel.com>");
2553MODULE_AUTHOR("Bingbu Cao <bingbu.cao@intel.com>");
2554MODULE_AUTHOR("Yang, Hyungwoo <hyungwoo.yang@intel.com>");
2555MODULE_DESCRIPTION("Sony imx319 sensor driver");
2556MODULE_LICENSE("GPL v2");
2557