linux/drivers/media/i2c/vs6624.c
<<
>>
Prefs
   1/*
   2 * vs6624.c ST VS6624 CMOS image sensor driver
   3 *
   4 * Copyright (c) 2011 Analog Devices Inc.
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License version 2 as
   8 * published by the Free Software Foundation.
   9 *
  10 * This program is distributed in the hope that it will be useful,
  11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13 * GNU General Public License for more details.
  14 *
  15 * You should have received a copy of the GNU General Public License
  16 * along with this program; if not, write to the Free Software
  17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18 */
  19
  20#include <linux/delay.h>
  21#include <linux/errno.h>
  22#include <linux/gpio.h>
  23#include <linux/i2c.h>
  24#include <linux/init.h>
  25#include <linux/module.h>
  26#include <linux/slab.h>
  27#include <linux/types.h>
  28#include <linux/videodev2.h>
  29
  30#include <media/v4l2-ctrls.h>
  31#include <media/v4l2-device.h>
  32#include <media/v4l2-mediabus.h>
  33
  34#include "vs6624_regs.h"
  35
  36#define VGA_WIDTH       640
  37#define VGA_HEIGHT      480
  38#define QVGA_WIDTH      320
  39#define QVGA_HEIGHT     240
  40#define QQVGA_WIDTH     160
  41#define QQVGA_HEIGHT    120
  42#define CIF_WIDTH       352
  43#define CIF_HEIGHT      288
  44#define QCIF_WIDTH      176
  45#define QCIF_HEIGHT     144
  46#define QQCIF_WIDTH     88
  47#define QQCIF_HEIGHT    72
  48
  49#define MAX_FRAME_RATE  30
  50
  51struct vs6624 {
  52        struct v4l2_subdev sd;
  53        struct v4l2_ctrl_handler hdl;
  54        struct v4l2_fract frame_rate;
  55        struct v4l2_mbus_framefmt fmt;
  56        unsigned ce_pin;
  57};
  58
  59static const struct vs6624_format {
  60        enum v4l2_mbus_pixelcode mbus_code;
  61        enum v4l2_colorspace colorspace;
  62} vs6624_formats[] = {
  63        {
  64                .mbus_code      = V4L2_MBUS_FMT_UYVY8_2X8,
  65                .colorspace     = V4L2_COLORSPACE_JPEG,
  66        },
  67        {
  68                .mbus_code      = V4L2_MBUS_FMT_YUYV8_2X8,
  69                .colorspace     = V4L2_COLORSPACE_JPEG,
  70        },
  71        {
  72                .mbus_code      = V4L2_MBUS_FMT_RGB565_2X8_LE,
  73                .colorspace     = V4L2_COLORSPACE_SRGB,
  74        },
  75};
  76
  77static struct v4l2_mbus_framefmt vs6624_default_fmt = {
  78        .width = VGA_WIDTH,
  79        .height = VGA_HEIGHT,
  80        .code = V4L2_MBUS_FMT_UYVY8_2X8,
  81        .field = V4L2_FIELD_NONE,
  82        .colorspace = V4L2_COLORSPACE_JPEG,
  83};
  84
  85static const u16 vs6624_p1[] = {
  86        0x8104, 0x03,
  87        0x8105, 0x01,
  88        0xc900, 0x03,
  89        0xc904, 0x47,
  90        0xc905, 0x10,
  91        0xc906, 0x80,
  92        0xc907, 0x3a,
  93        0x903a, 0x02,
  94        0x903b, 0x47,
  95        0x903c, 0x15,
  96        0xc908, 0x31,
  97        0xc909, 0xdc,
  98        0xc90a, 0x80,
  99        0xc90b, 0x44,
 100        0x9044, 0x02,
 101        0x9045, 0x31,
 102        0x9046, 0xe2,
 103        0xc90c, 0x07,
 104        0xc90d, 0xe0,
 105        0xc90e, 0x80,
 106        0xc90f, 0x47,
 107        0x9047, 0x90,
 108        0x9048, 0x83,
 109        0x9049, 0x81,
 110        0x904a, 0xe0,
 111        0x904b, 0x60,
 112        0x904c, 0x08,
 113        0x904d, 0x90,
 114        0x904e, 0xc0,
 115        0x904f, 0x43,
 116        0x9050, 0x74,
 117        0x9051, 0x01,
 118        0x9052, 0xf0,
 119        0x9053, 0x80,
 120        0x9054, 0x05,
 121        0x9055, 0xE4,
 122        0x9056, 0x90,
 123        0x9057, 0xc0,
 124        0x9058, 0x43,
 125        0x9059, 0xf0,
 126        0x905a, 0x02,
 127        0x905b, 0x07,
 128        0x905c, 0xec,
 129        0xc910, 0x5d,
 130        0xc911, 0xca,
 131        0xc912, 0x80,
 132        0xc913, 0x5d,
 133        0x905d, 0xa3,
 134        0x905e, 0x04,
 135        0x905f, 0xf0,
 136        0x9060, 0xa3,
 137        0x9061, 0x04,
 138        0x9062, 0xf0,
 139        0x9063, 0x22,
 140        0xc914, 0x72,
 141        0xc915, 0x92,
 142        0xc916, 0x80,
 143        0xc917, 0x64,
 144        0x9064, 0x74,
 145        0x9065, 0x01,
 146        0x9066, 0x02,
 147        0x9067, 0x72,
 148        0x9068, 0x95,
 149        0xc918, 0x47,
 150        0xc919, 0xf2,
 151        0xc91a, 0x81,
 152        0xc91b, 0x69,
 153        0x9169, 0x74,
 154        0x916a, 0x02,
 155        0x916b, 0xf0,
 156        0x916c, 0xec,
 157        0x916d, 0xb4,
 158        0x916e, 0x10,
 159        0x916f, 0x0a,
 160        0x9170, 0x90,
 161        0x9171, 0x80,
 162        0x9172, 0x16,
 163        0x9173, 0xe0,
 164        0x9174, 0x70,
 165        0x9175, 0x04,
 166        0x9176, 0x90,
 167        0x9177, 0xd3,
 168        0x9178, 0xc4,
 169        0x9179, 0xf0,
 170        0x917a, 0x22,
 171        0xc91c, 0x0a,
 172        0xc91d, 0xbe,
 173        0xc91e, 0x80,
 174        0xc91f, 0x73,
 175        0x9073, 0xfc,
 176        0x9074, 0xa3,
 177        0x9075, 0xe0,
 178        0x9076, 0xf5,
 179        0x9077, 0x82,
 180        0x9078, 0x8c,
 181        0x9079, 0x83,
 182        0x907a, 0xa3,
 183        0x907b, 0xa3,
 184        0x907c, 0xe0,
 185        0x907d, 0xfc,
 186        0x907e, 0xa3,
 187        0x907f, 0xe0,
 188        0x9080, 0xc3,
 189        0x9081, 0x9f,
 190        0x9082, 0xff,
 191        0x9083, 0xec,
 192        0x9084, 0x9e,
 193        0x9085, 0xfe,
 194        0x9086, 0x02,
 195        0x9087, 0x0a,
 196        0x9088, 0xea,
 197        0xc920, 0x47,
 198        0xc921, 0x38,
 199        0xc922, 0x80,
 200        0xc923, 0x89,
 201        0x9089, 0xec,
 202        0x908a, 0xd3,
 203        0x908b, 0x94,
 204        0x908c, 0x20,
 205        0x908d, 0x40,
 206        0x908e, 0x01,
 207        0x908f, 0x1c,
 208        0x9090, 0x90,
 209        0x9091, 0xd3,
 210        0x9092, 0xd4,
 211        0x9093, 0xec,
 212        0x9094, 0xf0,
 213        0x9095, 0x02,
 214        0x9096, 0x47,
 215        0x9097, 0x3d,
 216        0xc924, 0x45,
 217        0xc925, 0xca,
 218        0xc926, 0x80,
 219        0xc927, 0x98,
 220        0x9098, 0x12,
 221        0x9099, 0x77,
 222        0x909a, 0xd6,
 223        0x909b, 0x02,
 224        0x909c, 0x45,
 225        0x909d, 0xcd,
 226        0xc928, 0x20,
 227        0xc929, 0xd5,
 228        0xc92a, 0x80,
 229        0xc92b, 0x9e,
 230        0x909e, 0x90,
 231        0x909f, 0x82,
 232        0x90a0, 0x18,
 233        0x90a1, 0xe0,
 234        0x90a2, 0xb4,
 235        0x90a3, 0x03,
 236        0x90a4, 0x0e,
 237        0x90a5, 0x90,
 238        0x90a6, 0x83,
 239        0x90a7, 0xbf,
 240        0x90a8, 0xe0,
 241        0x90a9, 0x60,
 242        0x90aa, 0x08,
 243        0x90ab, 0x90,
 244        0x90ac, 0x81,
 245        0x90ad, 0xfc,
 246        0x90ae, 0xe0,
 247        0x90af, 0xff,
 248        0x90b0, 0xc3,
 249        0x90b1, 0x13,
 250        0x90b2, 0xf0,
 251        0x90b3, 0x90,
 252        0x90b4, 0x81,
 253        0x90b5, 0xfc,
 254        0x90b6, 0xe0,
 255        0x90b7, 0xff,
 256        0x90b8, 0x02,
 257        0x90b9, 0x20,
 258        0x90ba, 0xda,
 259        0xc92c, 0x70,
 260        0xc92d, 0xbc,
 261        0xc92e, 0x80,
 262        0xc92f, 0xbb,
 263        0x90bb, 0x90,
 264        0x90bc, 0x82,
 265        0x90bd, 0x18,
 266        0x90be, 0xe0,
 267        0x90bf, 0xb4,
 268        0x90c0, 0x03,
 269        0x90c1, 0x06,
 270        0x90c2, 0x90,
 271        0x90c3, 0xc1,
 272        0x90c4, 0x06,
 273        0x90c5, 0x74,
 274        0x90c6, 0x05,
 275        0x90c7, 0xf0,
 276        0x90c8, 0x90,
 277        0x90c9, 0xd3,
 278        0x90ca, 0xa0,
 279        0x90cb, 0x02,
 280        0x90cc, 0x70,
 281        0x90cd, 0xbf,
 282        0xc930, 0x72,
 283        0xc931, 0x21,
 284        0xc932, 0x81,
 285        0xc933, 0x3b,
 286        0x913b, 0x7d,
 287        0x913c, 0x02,
 288        0x913d, 0x7f,
 289        0x913e, 0x7b,
 290        0x913f, 0x02,
 291        0x9140, 0x72,
 292        0x9141, 0x25,
 293        0xc934, 0x28,
 294        0xc935, 0xae,
 295        0xc936, 0x80,
 296        0xc937, 0xd2,
 297        0x90d2, 0xf0,
 298        0x90d3, 0x90,
 299        0x90d4, 0xd2,
 300        0x90d5, 0x0a,
 301        0x90d6, 0x02,
 302        0x90d7, 0x28,
 303        0x90d8, 0xb4,
 304        0xc938, 0x28,
 305        0xc939, 0xb1,
 306        0xc93a, 0x80,
 307        0xc93b, 0xd9,
 308        0x90d9, 0x90,
 309        0x90da, 0x83,
 310        0x90db, 0xba,
 311        0x90dc, 0xe0,
 312        0x90dd, 0xff,
 313        0x90de, 0x90,
 314        0x90df, 0xd2,
 315        0x90e0, 0x08,
 316        0x90e1, 0xe0,
 317        0x90e2, 0xe4,
 318        0x90e3, 0xef,
 319        0x90e4, 0xf0,
 320        0x90e5, 0xa3,
 321        0x90e6, 0xe0,
 322        0x90e7, 0x74,
 323        0x90e8, 0xff,
 324        0x90e9, 0xf0,
 325        0x90ea, 0x90,
 326        0x90eb, 0xd2,
 327        0x90ec, 0x0a,
 328        0x90ed, 0x02,
 329        0x90ee, 0x28,
 330        0x90ef, 0xb4,
 331        0xc93c, 0x29,
 332        0xc93d, 0x79,
 333        0xc93e, 0x80,
 334        0xc93f, 0xf0,
 335        0x90f0, 0xf0,
 336        0x90f1, 0x90,
 337        0x90f2, 0xd2,
 338        0x90f3, 0x0e,
 339        0x90f4, 0x02,
 340        0x90f5, 0x29,
 341        0x90f6, 0x7f,
 342        0xc940, 0x29,
 343        0xc941, 0x7c,
 344        0xc942, 0x80,
 345        0xc943, 0xf7,
 346        0x90f7, 0x90,
 347        0x90f8, 0x83,
 348        0x90f9, 0xba,
 349        0x90fa, 0xe0,
 350        0x90fb, 0xff,
 351        0x90fc, 0x90,
 352        0x90fd, 0xd2,
 353        0x90fe, 0x0c,
 354        0x90ff, 0xe0,
 355        0x9100, 0xe4,
 356        0x9101, 0xef,
 357        0x9102, 0xf0,
 358        0x9103, 0xa3,
 359        0x9104, 0xe0,
 360        0x9105, 0x74,
 361        0x9106, 0xff,
 362        0x9107, 0xf0,
 363        0x9108, 0x90,
 364        0x9109, 0xd2,
 365        0x910a, 0x0e,
 366        0x910b, 0x02,
 367        0x910c, 0x29,
 368        0x910d, 0x7f,
 369        0xc944, 0x2a,
 370        0xc945, 0x42,
 371        0xc946, 0x81,
 372        0xc947, 0x0e,
 373        0x910e, 0xf0,
 374        0x910f, 0x90,
 375        0x9110, 0xd2,
 376        0x9111, 0x12,
 377        0x9112, 0x02,
 378        0x9113, 0x2a,
 379        0x9114, 0x48,
 380        0xc948, 0x2a,
 381        0xc949, 0x45,
 382        0xc94a, 0x81,
 383        0xc94b, 0x15,
 384        0x9115, 0x90,
 385        0x9116, 0x83,
 386        0x9117, 0xba,
 387        0x9118, 0xe0,
 388        0x9119, 0xff,
 389        0x911a, 0x90,
 390        0x911b, 0xd2,
 391        0x911c, 0x10,
 392        0x911d, 0xe0,
 393        0x911e, 0xe4,
 394        0x911f, 0xef,
 395        0x9120, 0xf0,
 396        0x9121, 0xa3,
 397        0x9122, 0xe0,
 398        0x9123, 0x74,
 399        0x9124, 0xff,
 400        0x9125, 0xf0,
 401        0x9126, 0x90,
 402        0x9127, 0xd2,
 403        0x9128, 0x12,
 404        0x9129, 0x02,
 405        0x912a, 0x2a,
 406        0x912b, 0x48,
 407        0xc900, 0x01,
 408        0x0000, 0x00,
 409};
 410
 411static const u16 vs6624_p2[] = {
 412        0x806f, 0x01,
 413        0x058c, 0x01,
 414        0x0000, 0x00,
 415};
 416
 417static const u16 vs6624_run_setup[] = {
 418        0x1d18, 0x00,                           /* Enableconstrainedwhitebalance */
 419        VS6624_PEAK_MIN_OUT_G_MSB, 0x3c,        /* Damper PeakGain Output MSB */
 420        VS6624_PEAK_MIN_OUT_G_LSB, 0x66,        /* Damper PeakGain Output LSB */
 421        VS6624_CM_LOW_THR_MSB, 0x65,            /* Damper Low MSB */
 422        VS6624_CM_LOW_THR_LSB, 0xd1,            /* Damper Low LSB */
 423        VS6624_CM_HIGH_THR_MSB, 0x66,           /* Damper High MSB */
 424        VS6624_CM_HIGH_THR_LSB, 0x62,           /* Damper High LSB */
 425        VS6624_CM_MIN_OUT_MSB, 0x00,            /* Damper Min output MSB */
 426        VS6624_CM_MIN_OUT_LSB, 0x00,            /* Damper Min output LSB */
 427        VS6624_NORA_DISABLE, 0x00,              /* Nora fDisable */
 428        VS6624_NORA_USAGE, 0x04,                /* Nora usage */
 429        VS6624_NORA_LOW_THR_MSB, 0x63,          /* Damper Low MSB Changed 0x63 to 0x65 */
 430        VS6624_NORA_LOW_THR_LSB, 0xd1,          /* Damper Low LSB */
 431        VS6624_NORA_HIGH_THR_MSB, 0x68,         /* Damper High MSB */
 432        VS6624_NORA_HIGH_THR_LSB, 0xdd,         /* Damper High LSB */
 433        VS6624_NORA_MIN_OUT_MSB, 0x3a,          /* Damper Min output MSB */
 434        VS6624_NORA_MIN_OUT_LSB, 0x00,          /* Damper Min output LSB */
 435        VS6624_F2B_DISABLE, 0x00,               /* Disable */
 436        0x1d8a, 0x30,                           /* MAXWeightHigh */
 437        0x1d91, 0x62,                           /* fpDamperLowThresholdHigh MSB */
 438        0x1d92, 0x4a,                           /* fpDamperLowThresholdHigh LSB */
 439        0x1d95, 0x65,                           /* fpDamperHighThresholdHigh MSB */
 440        0x1d96, 0x0e,                           /* fpDamperHighThresholdHigh LSB */
 441        0x1da1, 0x3a,                           /* fpMinimumDamperOutputLow MSB */
 442        0x1da2, 0xb8,                           /* fpMinimumDamperOutputLow LSB */
 443        0x1e08, 0x06,                           /* MAXWeightLow */
 444        0x1e0a, 0x0a,                           /* MAXWeightHigh */
 445        0x1601, 0x3a,                           /* Red A MSB */
 446        0x1602, 0x14,                           /* Red A LSB */
 447        0x1605, 0x3b,                           /* Blue A MSB */
 448        0x1606, 0x85,                           /* BLue A LSB */
 449        0x1609, 0x3b,                           /* RED B MSB */
 450        0x160a, 0x85,                           /* RED B LSB */
 451        0x160d, 0x3a,                           /* Blue B MSB */
 452        0x160e, 0x14,                           /* Blue B LSB */
 453        0x1611, 0x30,                           /* Max Distance from Locus MSB */
 454        0x1612, 0x8f,                           /* Max Distance from Locus MSB */
 455        0x1614, 0x01,                           /* Enable constrainer */
 456        0x0000, 0x00,
 457};
 458
 459static const u16 vs6624_default[] = {
 460        VS6624_CONTRAST0, 0x84,
 461        VS6624_SATURATION0, 0x75,
 462        VS6624_GAMMA0, 0x11,
 463        VS6624_CONTRAST1, 0x84,
 464        VS6624_SATURATION1, 0x75,
 465        VS6624_GAMMA1, 0x11,
 466        VS6624_MAN_RG, 0x80,
 467        VS6624_MAN_GG, 0x80,
 468        VS6624_MAN_BG, 0x80,
 469        VS6624_WB_MODE, 0x1,
 470        VS6624_EXPO_COMPENSATION, 0xfe,
 471        VS6624_EXPO_METER, 0x0,
 472        VS6624_LIGHT_FREQ, 0x64,
 473        VS6624_PEAK_GAIN, 0xe,
 474        VS6624_PEAK_LOW_THR, 0x28,
 475        VS6624_HMIRROR0, 0x0,
 476        VS6624_VFLIP0, 0x0,
 477        VS6624_ZOOM_HSTEP0_MSB, 0x0,
 478        VS6624_ZOOM_HSTEP0_LSB, 0x1,
 479        VS6624_ZOOM_VSTEP0_MSB, 0x0,
 480        VS6624_ZOOM_VSTEP0_LSB, 0x1,
 481        VS6624_PAN_HSTEP0_MSB, 0x0,
 482        VS6624_PAN_HSTEP0_LSB, 0xf,
 483        VS6624_PAN_VSTEP0_MSB, 0x0,
 484        VS6624_PAN_VSTEP0_LSB, 0xf,
 485        VS6624_SENSOR_MODE, 0x1,
 486        VS6624_SYNC_CODE_SETUP, 0x21,
 487        VS6624_DISABLE_FR_DAMPER, 0x0,
 488        VS6624_FR_DEN, 0x1,
 489        VS6624_FR_NUM_LSB, 0xf,
 490        VS6624_INIT_PIPE_SETUP, 0x0,
 491        VS6624_IMG_FMT0, 0x0,
 492        VS6624_YUV_SETUP, 0x1,
 493        VS6624_IMAGE_SIZE0, 0x2,
 494        0x0000, 0x00,
 495};
 496
 497static inline struct vs6624 *to_vs6624(struct v4l2_subdev *sd)
 498{
 499        return container_of(sd, struct vs6624, sd);
 500}
 501static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
 502{
 503        return &container_of(ctrl->handler, struct vs6624, hdl)->sd;
 504}
 505
 506static int vs6624_read(struct v4l2_subdev *sd, u16 index)
 507{
 508        struct i2c_client *client = v4l2_get_subdevdata(sd);
 509        u8 buf[2];
 510
 511        buf[0] = index >> 8;
 512        buf[1] = index;
 513        i2c_master_send(client, buf, 2);
 514        i2c_master_recv(client, buf, 1);
 515
 516        return buf[0];
 517}
 518
 519static int vs6624_write(struct v4l2_subdev *sd, u16 index,
 520                                u8 value)
 521{
 522        struct i2c_client *client = v4l2_get_subdevdata(sd);
 523        u8 buf[3];
 524
 525        buf[0] = index >> 8;
 526        buf[1] = index;
 527        buf[2] = value;
 528
 529        return i2c_master_send(client, buf, 3);
 530}
 531
 532static int vs6624_writeregs(struct v4l2_subdev *sd, const u16 *regs)
 533{
 534        u16 reg;
 535        u8 data;
 536
 537        while (*regs != 0x00) {
 538                reg = *regs++;
 539                data = *regs++;
 540
 541                vs6624_write(sd, reg, data);
 542        }
 543        return 0;
 544}
 545
 546static int vs6624_s_ctrl(struct v4l2_ctrl *ctrl)
 547{
 548        struct v4l2_subdev *sd = to_sd(ctrl);
 549
 550        switch (ctrl->id) {
 551        case V4L2_CID_CONTRAST:
 552                vs6624_write(sd, VS6624_CONTRAST0, ctrl->val);
 553                break;
 554        case V4L2_CID_SATURATION:
 555                vs6624_write(sd, VS6624_SATURATION0, ctrl->val);
 556                break;
 557        case V4L2_CID_HFLIP:
 558                vs6624_write(sd, VS6624_HMIRROR0, ctrl->val);
 559                break;
 560        case V4L2_CID_VFLIP:
 561                vs6624_write(sd, VS6624_VFLIP0, ctrl->val);
 562                break;
 563        default:
 564                return -EINVAL;
 565        }
 566
 567        return 0;
 568}
 569
 570static int vs6624_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned index,
 571                                enum v4l2_mbus_pixelcode *code)
 572{
 573        if (index >= ARRAY_SIZE(vs6624_formats))
 574                return -EINVAL;
 575
 576        *code = vs6624_formats[index].mbus_code;
 577        return 0;
 578}
 579
 580static int vs6624_try_mbus_fmt(struct v4l2_subdev *sd,
 581                                struct v4l2_mbus_framefmt *fmt)
 582{
 583        int index;
 584
 585        for (index = 0; index < ARRAY_SIZE(vs6624_formats); index++)
 586                if (vs6624_formats[index].mbus_code == fmt->code)
 587                        break;
 588        if (index >= ARRAY_SIZE(vs6624_formats)) {
 589                /* default to first format */
 590                index = 0;
 591                fmt->code = vs6624_formats[0].mbus_code;
 592        }
 593
 594        /* sensor mode is VGA */
 595        if (fmt->width > VGA_WIDTH)
 596                fmt->width = VGA_WIDTH;
 597        if (fmt->height > VGA_HEIGHT)
 598                fmt->height = VGA_HEIGHT;
 599        fmt->width = fmt->width & (~3);
 600        fmt->height = fmt->height & (~3);
 601        fmt->field = V4L2_FIELD_NONE;
 602        fmt->colorspace = vs6624_formats[index].colorspace;
 603        return 0;
 604}
 605
 606static int vs6624_s_mbus_fmt(struct v4l2_subdev *sd,
 607                                struct v4l2_mbus_framefmt *fmt)
 608{
 609        struct vs6624 *sensor = to_vs6624(sd);
 610        int ret;
 611
 612        ret = vs6624_try_mbus_fmt(sd, fmt);
 613        if (ret)
 614                return ret;
 615
 616        /* set image format */
 617        switch (fmt->code) {
 618        case V4L2_MBUS_FMT_UYVY8_2X8:
 619                vs6624_write(sd, VS6624_IMG_FMT0, 0x0);
 620                vs6624_write(sd, VS6624_YUV_SETUP, 0x1);
 621                break;
 622        case V4L2_MBUS_FMT_YUYV8_2X8:
 623                vs6624_write(sd, VS6624_IMG_FMT0, 0x0);
 624                vs6624_write(sd, VS6624_YUV_SETUP, 0x3);
 625                break;
 626        case V4L2_MBUS_FMT_RGB565_2X8_LE:
 627                vs6624_write(sd, VS6624_IMG_FMT0, 0x4);
 628                vs6624_write(sd, VS6624_RGB_SETUP, 0x0);
 629                break;
 630        default:
 631                return -EINVAL;
 632        }
 633
 634        /* set image size */
 635        if ((fmt->width == VGA_WIDTH) && (fmt->height == VGA_HEIGHT))
 636                vs6624_write(sd, VS6624_IMAGE_SIZE0, 0x2);
 637        else if ((fmt->width == QVGA_WIDTH) && (fmt->height == QVGA_HEIGHT))
 638                vs6624_write(sd, VS6624_IMAGE_SIZE0, 0x4);
 639        else if ((fmt->width == QQVGA_WIDTH) && (fmt->height == QQVGA_HEIGHT))
 640                vs6624_write(sd, VS6624_IMAGE_SIZE0, 0x6);
 641        else if ((fmt->width == CIF_WIDTH) && (fmt->height == CIF_HEIGHT))
 642                vs6624_write(sd, VS6624_IMAGE_SIZE0, 0x3);
 643        else if ((fmt->width == QCIF_WIDTH) && (fmt->height == QCIF_HEIGHT))
 644                vs6624_write(sd, VS6624_IMAGE_SIZE0, 0x5);
 645        else if ((fmt->width == QQCIF_WIDTH) && (fmt->height == QQCIF_HEIGHT))
 646                vs6624_write(sd, VS6624_IMAGE_SIZE0, 0x7);
 647        else {
 648                vs6624_write(sd, VS6624_IMAGE_SIZE0, 0x8);
 649                vs6624_write(sd, VS6624_MAN_HSIZE0_MSB, fmt->width >> 8);
 650                vs6624_write(sd, VS6624_MAN_HSIZE0_LSB, fmt->width & 0xFF);
 651                vs6624_write(sd, VS6624_MAN_VSIZE0_MSB, fmt->height >> 8);
 652                vs6624_write(sd, VS6624_MAN_VSIZE0_LSB, fmt->height & 0xFF);
 653                vs6624_write(sd, VS6624_CROP_CTRL0, 0x1);
 654        }
 655
 656        sensor->fmt = *fmt;
 657
 658        return 0;
 659}
 660
 661static int vs6624_g_mbus_fmt(struct v4l2_subdev *sd,
 662                                struct v4l2_mbus_framefmt *fmt)
 663{
 664        struct vs6624 *sensor = to_vs6624(sd);
 665
 666        *fmt = sensor->fmt;
 667        return 0;
 668}
 669
 670static int vs6624_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms)
 671{
 672        struct vs6624 *sensor = to_vs6624(sd);
 673        struct v4l2_captureparm *cp = &parms->parm.capture;
 674
 675        if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
 676                return -EINVAL;
 677
 678        memset(cp, 0, sizeof(*cp));
 679        cp->capability = V4L2_CAP_TIMEPERFRAME;
 680        cp->timeperframe.numerator = sensor->frame_rate.denominator;
 681        cp->timeperframe.denominator = sensor->frame_rate.numerator;
 682        return 0;
 683}
 684
 685static int vs6624_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms)
 686{
 687        struct vs6624 *sensor = to_vs6624(sd);
 688        struct v4l2_captureparm *cp = &parms->parm.capture;
 689        struct v4l2_fract *tpf = &cp->timeperframe;
 690
 691        if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
 692                return -EINVAL;
 693        if (cp->extendedmode != 0)
 694                return -EINVAL;
 695
 696        if (tpf->numerator == 0 || tpf->denominator == 0
 697                || (tpf->denominator > tpf->numerator * MAX_FRAME_RATE)) {
 698                /* reset to max frame rate */
 699                tpf->numerator = 1;
 700                tpf->denominator = MAX_FRAME_RATE;
 701        }
 702        sensor->frame_rate.numerator = tpf->denominator;
 703        sensor->frame_rate.denominator = tpf->numerator;
 704        vs6624_write(sd, VS6624_DISABLE_FR_DAMPER, 0x0);
 705        vs6624_write(sd, VS6624_FR_NUM_MSB,
 706                        sensor->frame_rate.numerator >> 8);
 707        vs6624_write(sd, VS6624_FR_NUM_LSB,
 708                        sensor->frame_rate.numerator & 0xFF);
 709        vs6624_write(sd, VS6624_FR_DEN,
 710                        sensor->frame_rate.denominator & 0xFF);
 711        return 0;
 712}
 713
 714static int vs6624_s_stream(struct v4l2_subdev *sd, int enable)
 715{
 716        if (enable)
 717                vs6624_write(sd, VS6624_USER_CMD, 0x2);
 718        else
 719                vs6624_write(sd, VS6624_USER_CMD, 0x4);
 720        udelay(100);
 721        return 0;
 722}
 723
 724#ifdef CONFIG_VIDEO_ADV_DEBUG
 725static int vs6624_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
 726{
 727        reg->val = vs6624_read(sd, reg->reg & 0xffff);
 728        reg->size = 1;
 729        return 0;
 730}
 731
 732static int vs6624_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg)
 733{
 734        vs6624_write(sd, reg->reg & 0xffff, reg->val & 0xff);
 735        return 0;
 736}
 737#endif
 738
 739static const struct v4l2_ctrl_ops vs6624_ctrl_ops = {
 740        .s_ctrl = vs6624_s_ctrl,
 741};
 742
 743static const struct v4l2_subdev_core_ops vs6624_core_ops = {
 744#ifdef CONFIG_VIDEO_ADV_DEBUG
 745        .g_register = vs6624_g_register,
 746        .s_register = vs6624_s_register,
 747#endif
 748};
 749
 750static const struct v4l2_subdev_video_ops vs6624_video_ops = {
 751        .enum_mbus_fmt = vs6624_enum_mbus_fmt,
 752        .try_mbus_fmt = vs6624_try_mbus_fmt,
 753        .s_mbus_fmt = vs6624_s_mbus_fmt,
 754        .g_mbus_fmt = vs6624_g_mbus_fmt,
 755        .s_parm = vs6624_s_parm,
 756        .g_parm = vs6624_g_parm,
 757        .s_stream = vs6624_s_stream,
 758};
 759
 760static const struct v4l2_subdev_ops vs6624_ops = {
 761        .core = &vs6624_core_ops,
 762        .video = &vs6624_video_ops,
 763};
 764
 765static int vs6624_probe(struct i2c_client *client,
 766                        const struct i2c_device_id *id)
 767{
 768        struct vs6624 *sensor;
 769        struct v4l2_subdev *sd;
 770        struct v4l2_ctrl_handler *hdl;
 771        const unsigned *ce;
 772        int ret;
 773
 774        /* Check if the adapter supports the needed features */
 775        if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
 776                return -EIO;
 777
 778        ce = client->dev.platform_data;
 779        if (ce == NULL)
 780                return -EINVAL;
 781
 782        ret = devm_gpio_request_one(&client->dev, *ce, GPIOF_OUT_INIT_HIGH,
 783                                    "VS6624 Chip Enable");
 784        if (ret) {
 785                v4l_err(client, "failed to request GPIO %d\n", *ce);
 786                return ret;
 787        }
 788        /* wait 100ms before any further i2c writes are performed */
 789        mdelay(100);
 790
 791        sensor = devm_kzalloc(&client->dev, sizeof(*sensor), GFP_KERNEL);
 792        if (sensor == NULL)
 793                return -ENOMEM;
 794
 795        sd = &sensor->sd;
 796        v4l2_i2c_subdev_init(sd, client, &vs6624_ops);
 797
 798        vs6624_writeregs(sd, vs6624_p1);
 799        vs6624_write(sd, VS6624_MICRO_EN, 0x2);
 800        vs6624_write(sd, VS6624_DIO_EN, 0x1);
 801        mdelay(10);
 802        vs6624_writeregs(sd, vs6624_p2);
 803
 804        vs6624_writeregs(sd, vs6624_default);
 805        vs6624_write(sd, VS6624_HSYNC_SETUP, 0xF);
 806        vs6624_writeregs(sd, vs6624_run_setup);
 807
 808        /* set frame rate */
 809        sensor->frame_rate.numerator = MAX_FRAME_RATE;
 810        sensor->frame_rate.denominator = 1;
 811        vs6624_write(sd, VS6624_DISABLE_FR_DAMPER, 0x0);
 812        vs6624_write(sd, VS6624_FR_NUM_MSB,
 813                        sensor->frame_rate.numerator >> 8);
 814        vs6624_write(sd, VS6624_FR_NUM_LSB,
 815                        sensor->frame_rate.numerator & 0xFF);
 816        vs6624_write(sd, VS6624_FR_DEN,
 817                        sensor->frame_rate.denominator & 0xFF);
 818
 819        sensor->fmt = vs6624_default_fmt;
 820        sensor->ce_pin = *ce;
 821
 822        v4l_info(client, "chip found @ 0x%02x (%s)\n",
 823                        client->addr << 1, client->adapter->name);
 824
 825        hdl = &sensor->hdl;
 826        v4l2_ctrl_handler_init(hdl, 4);
 827        v4l2_ctrl_new_std(hdl, &vs6624_ctrl_ops,
 828                        V4L2_CID_CONTRAST, 0, 0xFF, 1, 0x87);
 829        v4l2_ctrl_new_std(hdl, &vs6624_ctrl_ops,
 830                        V4L2_CID_SATURATION, 0, 0xFF, 1, 0x78);
 831        v4l2_ctrl_new_std(hdl, &vs6624_ctrl_ops,
 832                        V4L2_CID_HFLIP, 0, 1, 1, 0);
 833        v4l2_ctrl_new_std(hdl, &vs6624_ctrl_ops,
 834                        V4L2_CID_VFLIP, 0, 1, 1, 0);
 835        /* hook the control handler into the driver */
 836        sd->ctrl_handler = hdl;
 837        if (hdl->error) {
 838                int err = hdl->error;
 839
 840                v4l2_ctrl_handler_free(hdl);
 841                return err;
 842        }
 843
 844        /* initialize the hardware to the default control values */
 845        ret = v4l2_ctrl_handler_setup(hdl);
 846        if (ret)
 847                v4l2_ctrl_handler_free(hdl);
 848        return ret;
 849}
 850
 851static int vs6624_remove(struct i2c_client *client)
 852{
 853        struct v4l2_subdev *sd = i2c_get_clientdata(client);
 854
 855        v4l2_device_unregister_subdev(sd);
 856        v4l2_ctrl_handler_free(sd->ctrl_handler);
 857        return 0;
 858}
 859
 860static const struct i2c_device_id vs6624_id[] = {
 861        {"vs6624", 0},
 862        {},
 863};
 864
 865MODULE_DEVICE_TABLE(i2c, vs6624_id);
 866
 867static struct i2c_driver vs6624_driver = {
 868        .driver = {
 869                .owner  = THIS_MODULE,
 870                .name   = "vs6624",
 871        },
 872        .probe          = vs6624_probe,
 873        .remove         = vs6624_remove,
 874        .id_table       = vs6624_id,
 875};
 876
 877module_i2c_driver(vs6624_driver);
 878
 879MODULE_DESCRIPTION("VS6624 sensor driver");
 880MODULE_AUTHOR("Scott Jiang <Scott.Jiang.Linux@gmail.com>");
 881MODULE_LICENSE("GPL v2");
 882