linux/drivers/media/i2c/s5k4ecgx.c
<<
>>
Prefs
   1/*
   2 * Driver for Samsung S5K4ECGX 1/4" 5Mp CMOS Image Sensor SoC
   3 * with an Embedded Image Signal Processor.
   4 *
   5 * Copyright (C) 2012, Linaro, Sangwook Lee <sangwook.lee@linaro.org>
   6 * Copyright (C) 2012, Insignal Co,. Ltd, Homin Lee <suapapa@insignal.co.kr>
   7 *
   8 * Based on s5k6aa and noon010pc30 driver
   9 * Copyright (C) 2011, Samsung Electronics Co., Ltd.
  10 *
  11 * This program is free software; you can redistribute it and/or modify
  12 * it under the terms of the GNU General Public License as published by
  13 * the Free Software Foundation; either version 2 of the License, or
  14 * (at your option) any later version.
  15 */
  16
  17#include <linux/clk.h>
  18#include <linux/crc32.h>
  19#include <linux/ctype.h>
  20#include <linux/delay.h>
  21#include <linux/firmware.h>
  22#include <linux/gpio.h>
  23#include <linux/i2c.h>
  24#include <linux/module.h>
  25#include <linux/regulator/consumer.h>
  26#include <linux/slab.h>
  27#include <asm/unaligned.h>
  28
  29#include <media/media-entity.h>
  30#include <media/i2c/s5k4ecgx.h>
  31#include <media/v4l2-ctrls.h>
  32#include <media/v4l2-device.h>
  33#include <media/v4l2-mediabus.h>
  34#include <media/v4l2-subdev.h>
  35
  36static int debug;
  37module_param(debug, int, 0644);
  38
  39#define S5K4ECGX_DRIVER_NAME            "s5k4ecgx"
  40#define S5K4ECGX_FIRMWARE               "s5k4ecgx.bin"
  41
  42/* Firmware revision information */
  43#define REG_FW_REVISION                 0x700001a6
  44#define REG_FW_VERSION                  0x700001a4
  45#define S5K4ECGX_REVISION_1_1           0x11
  46#define S5K4ECGX_FW_VERSION             0x4ec0
  47
  48/* General purpose parameters */
  49#define REG_USER_BRIGHTNESS             0x7000022c
  50#define REG_USER_CONTRAST               0x7000022e
  51#define REG_USER_SATURATION             0x70000230
  52
  53#define REG_G_ENABLE_PREV               0x7000023e
  54#define REG_G_ENABLE_PREV_CHG           0x70000240
  55#define REG_G_NEW_CFG_SYNC              0x7000024a
  56#define REG_G_PREV_IN_WIDTH             0x70000250
  57#define REG_G_PREV_IN_HEIGHT            0x70000252
  58#define REG_G_PREV_IN_XOFFS             0x70000254
  59#define REG_G_PREV_IN_YOFFS             0x70000256
  60#define REG_G_CAP_IN_WIDTH              0x70000258
  61#define REG_G_CAP_IN_HEIGHT             0x7000025a
  62#define REG_G_CAP_IN_XOFFS              0x7000025c
  63#define REG_G_CAP_IN_YOFFS              0x7000025e
  64#define REG_G_INPUTS_CHANGE_REQ         0x70000262
  65#define REG_G_ACTIVE_PREV_CFG           0x70000266
  66#define REG_G_PREV_CFG_CHG              0x70000268
  67#define REG_G_PREV_OPEN_AFTER_CH        0x7000026a
  68
  69/* Preview context register sets. n = 0...4. */
  70#define PREG(n, x)                      ((n) * 0x30 + (x))
  71#define REG_P_OUT_WIDTH(n)              PREG(n, 0x700002a6)
  72#define REG_P_OUT_HEIGHT(n)             PREG(n, 0x700002a8)
  73#define REG_P_FMT(n)                    PREG(n, 0x700002aa)
  74#define REG_P_PVI_MASK(n)               PREG(n, 0x700002b4)
  75#define REG_P_FR_TIME_TYPE(n)           PREG(n, 0x700002be)
  76#define  FR_TIME_DYNAMIC                0
  77#define  FR_TIME_FIXED                  1
  78#define  FR_TIME_FIXED_ACCURATE         2
  79#define REG_P_FR_TIME_Q_TYPE(n)         PREG(n, 0x700002c0)
  80#define  FR_TIME_Q_DYNAMIC              0
  81#define  FR_TIME_Q_BEST_FRRATE          1
  82#define  FR_TIME_Q_BEST_QUALITY         2
  83
  84/* Frame period in 0.1 ms units */
  85#define REG_P_MAX_FR_TIME(n)            PREG(n, 0x700002c2)
  86#define REG_P_MIN_FR_TIME(n)            PREG(n, 0x700002c4)
  87#define  US_TO_FR_TIME(__t)             ((__t) / 100)
  88#define REG_P_PREV_MIRROR(n)            PREG(n, 0x700002d0)
  89#define REG_P_CAP_MIRROR(n)             PREG(n, 0x700002d2)
  90
  91#define REG_G_PREVZOOM_IN_WIDTH         0x70000494
  92#define REG_G_PREVZOOM_IN_HEIGHT        0x70000496
  93#define REG_G_PREVZOOM_IN_XOFFS         0x70000498
  94#define REG_G_PREVZOOM_IN_YOFFS         0x7000049a
  95#define REG_G_CAPZOOM_IN_WIDTH          0x7000049c
  96#define REG_G_CAPZOOM_IN_HEIGHT         0x7000049e
  97#define REG_G_CAPZOOM_IN_XOFFS          0x700004a0
  98#define REG_G_CAPZOOM_IN_YOFFS          0x700004a2
  99
 100/* n = 0...4 */
 101#define REG_USER_SHARPNESS(n)           (0x70000a28 + (n) * 0xb6)
 102
 103/* Reduce sharpness range for user space API */
 104#define SHARPNESS_DIV                   8208
 105#define TOK_TERM                        0xffffffff
 106
 107/*
 108 * FIXME: This is copied from s5k6aa, because of no information
 109 * in the S5K4ECGX datasheet.
 110 * H/W register Interface (0xd0000000 - 0xd0000fff)
 111 */
 112#define AHB_MSB_ADDR_PTR                0xfcfc
 113#define GEN_REG_OFFSH                   0xd000
 114#define REG_CMDWR_ADDRH                 0x0028
 115#define REG_CMDWR_ADDRL                 0x002a
 116#define REG_CMDRD_ADDRH                 0x002c
 117#define REG_CMDRD_ADDRL                 0x002e
 118#define REG_CMDBUF0_ADDR                0x0f12
 119
 120struct s5k4ecgx_frmsize {
 121        struct v4l2_frmsize_discrete size;
 122        /* Fixed sensor matrix crop rectangle */
 123        struct v4l2_rect input_window;
 124};
 125
 126struct regval_list {
 127        u32 addr;
 128        u16 val;
 129};
 130
 131/*
 132 * TODO: currently only preview is supported and snapshot (capture)
 133 * is not implemented yet
 134 */
 135static const struct s5k4ecgx_frmsize s5k4ecgx_prev_sizes[] = {
 136        {
 137                .size = { 176, 144 },
 138                .input_window = { 0x00, 0x00, 0x928, 0x780 },
 139        }, {
 140                .size = { 352, 288 },
 141                .input_window = { 0x00, 0x00, 0x928, 0x780 },
 142        }, {
 143                .size = { 640, 480 },
 144                .input_window = { 0x00, 0x00, 0xa00, 0x780 },
 145        }, {
 146                .size = { 720, 480 },
 147                .input_window = { 0x00, 0x00, 0xa00, 0x6a8 },
 148        }
 149};
 150
 151#define S5K4ECGX_NUM_PREV ARRAY_SIZE(s5k4ecgx_prev_sizes)
 152
 153struct s5k4ecgx_pixfmt {
 154        u32 code;
 155        u32 colorspace;
 156        /* REG_TC_PCFG_Format register value */
 157        u16 reg_p_format;
 158};
 159
 160/* By default value, output from sensor will be YUV422 0-255 */
 161static const struct s5k4ecgx_pixfmt s5k4ecgx_formats[] = {
 162        { MEDIA_BUS_FMT_YUYV8_2X8, V4L2_COLORSPACE_JPEG, 5 },
 163};
 164
 165static const char * const s5k4ecgx_supply_names[] = {
 166        /*
 167         * Usually 2.8V is used for analog power (vdda)
 168         * and digital IO (vddio, vdddcore)
 169         */
 170        "vdda",
 171        "vddio",
 172        "vddcore",
 173        "vddreg", /* The internal s5k4ecgx regulator's supply (1.8V) */
 174};
 175
 176#define S5K4ECGX_NUM_SUPPLIES ARRAY_SIZE(s5k4ecgx_supply_names)
 177
 178enum s5k4ecgx_gpio_id {
 179        STBY,
 180        RST,
 181        GPIO_NUM,
 182};
 183
 184struct s5k4ecgx {
 185        struct v4l2_subdev sd;
 186        struct media_pad pad;
 187        struct v4l2_ctrl_handler handler;
 188
 189        struct s5k4ecgx_platform_data *pdata;
 190        const struct s5k4ecgx_pixfmt *curr_pixfmt;
 191        const struct s5k4ecgx_frmsize *curr_frmsize;
 192        struct mutex lock;
 193        u8 streaming;
 194        u8 set_params;
 195
 196        struct regulator_bulk_data supplies[S5K4ECGX_NUM_SUPPLIES];
 197        struct s5k4ecgx_gpio gpio[GPIO_NUM];
 198};
 199
 200static inline struct s5k4ecgx *to_s5k4ecgx(struct v4l2_subdev *sd)
 201{
 202        return container_of(sd, struct s5k4ecgx, sd);
 203}
 204
 205static int s5k4ecgx_i2c_read(struct i2c_client *client, u16 addr, u16 *val)
 206{
 207        u8 wbuf[2] = { addr >> 8, addr & 0xff };
 208        struct i2c_msg msg[2];
 209        u8 rbuf[2];
 210        int ret;
 211
 212        msg[0].addr = client->addr;
 213        msg[0].flags = 0;
 214        msg[0].len = 2;
 215        msg[0].buf = wbuf;
 216
 217        msg[1].addr = client->addr;
 218        msg[1].flags = I2C_M_RD;
 219        msg[1].len = 2;
 220        msg[1].buf = rbuf;
 221
 222        ret = i2c_transfer(client->adapter, msg, 2);
 223        *val = be16_to_cpu(*((__be16 *)rbuf));
 224
 225        v4l2_dbg(4, debug, client, "i2c_read: 0x%04X : 0x%04x\n", addr, *val);
 226
 227        return ret == 2 ? 0 : ret;
 228}
 229
 230static int s5k4ecgx_i2c_write(struct i2c_client *client, u16 addr, u16 val)
 231{
 232        u8 buf[4] = { addr >> 8, addr & 0xff, val >> 8, val & 0xff };
 233
 234        int ret = i2c_master_send(client, buf, 4);
 235        v4l2_dbg(4, debug, client, "i2c_write: 0x%04x : 0x%04x\n", addr, val);
 236
 237        return ret == 4 ? 0 : ret;
 238}
 239
 240static int s5k4ecgx_write(struct i2c_client *client, u32 addr, u16 val)
 241{
 242        u16 high = addr >> 16, low = addr & 0xffff;
 243        int ret;
 244
 245        v4l2_dbg(3, debug, client, "write: 0x%08x : 0x%04x\n", addr, val);
 246
 247        ret = s5k4ecgx_i2c_write(client, REG_CMDWR_ADDRH, high);
 248        if (!ret)
 249                ret = s5k4ecgx_i2c_write(client, REG_CMDWR_ADDRL, low);
 250        if (!ret)
 251                ret = s5k4ecgx_i2c_write(client, REG_CMDBUF0_ADDR, val);
 252
 253        return ret;
 254}
 255
 256static int s5k4ecgx_read(struct i2c_client *client, u32 addr, u16 *val)
 257{
 258        u16 high = addr >> 16, low =  addr & 0xffff;
 259        int ret;
 260
 261        ret = s5k4ecgx_i2c_write(client, REG_CMDRD_ADDRH, high);
 262        if (!ret)
 263                ret = s5k4ecgx_i2c_write(client, REG_CMDRD_ADDRL, low);
 264        if (!ret)
 265                ret = s5k4ecgx_i2c_read(client, REG_CMDBUF0_ADDR, val);
 266        if (!ret)
 267                dev_err(&client->dev, "Failed to execute read command\n");
 268
 269        return ret;
 270}
 271
 272static int s5k4ecgx_read_fw_ver(struct v4l2_subdev *sd)
 273{
 274        struct i2c_client *client = v4l2_get_subdevdata(sd);
 275        u16 hw_rev, fw_ver = 0;
 276        int ret;
 277
 278        ret = s5k4ecgx_read(client, REG_FW_VERSION, &fw_ver);
 279        if (ret < 0 || fw_ver != S5K4ECGX_FW_VERSION) {
 280                v4l2_err(sd, "FW version check failed!\n");
 281                return -ENODEV;
 282        }
 283
 284        ret = s5k4ecgx_read(client, REG_FW_REVISION, &hw_rev);
 285        if (ret < 0)
 286                return ret;
 287
 288        v4l2_info(sd, "chip found FW ver: 0x%x, HW rev: 0x%x\n",
 289                                                fw_ver, hw_rev);
 290        return 0;
 291}
 292
 293static int s5k4ecgx_set_ahb_address(struct v4l2_subdev *sd)
 294{
 295        struct i2c_client *client = v4l2_get_subdevdata(sd);
 296        int ret;
 297
 298        /* Set APB peripherals start address */
 299        ret = s5k4ecgx_i2c_write(client, AHB_MSB_ADDR_PTR, GEN_REG_OFFSH);
 300        if (ret < 0)
 301                return ret;
 302        /*
 303         * FIXME: This is copied from s5k6aa, because of no information
 304         * in s5k4ecgx's datasheet.
 305         * sw_reset is activated to put device into idle status
 306         */
 307        ret = s5k4ecgx_i2c_write(client, 0x0010, 0x0001);
 308        if (ret < 0)
 309                return ret;
 310
 311        ret = s5k4ecgx_i2c_write(client, 0x1030, 0x0000);
 312        if (ret < 0)
 313                return ret;
 314        /* Halt ARM CPU */
 315        return s5k4ecgx_i2c_write(client, 0x0014, 0x0001);
 316}
 317
 318#define FW_CRC_SIZE     4
 319/* Register address, value are 4, 2 bytes */
 320#define FW_RECORD_SIZE  6
 321/*
 322 * The firmware has following format:
 323 * < total number of records (4 bytes + 2 bytes padding) N >,
 324 * < record 0 >, ..., < record N - 1 >, < CRC32-CCITT (4-bytes) >,
 325 * where "record" is a 4-byte register address followed by 2-byte
 326 * register value (little endian).
 327 * The firmware generator can be found in following git repository:
 328 * git://git.linaro.org/people/sangwook/fimc-v4l2-app.git
 329 */
 330static int s5k4ecgx_load_firmware(struct v4l2_subdev *sd)
 331{
 332        struct i2c_client *client = v4l2_get_subdevdata(sd);
 333        const struct firmware *fw;
 334        const u8 *ptr;
 335        int err, i, regs_num;
 336        u32 addr, crc, crc_file, addr_inc = 0;
 337        u16 val;
 338
 339        err = request_firmware(&fw, S5K4ECGX_FIRMWARE, sd->v4l2_dev->dev);
 340        if (err) {
 341                v4l2_err(sd, "Failed to read firmware %s\n", S5K4ECGX_FIRMWARE);
 342                return err;
 343        }
 344        regs_num = get_unaligned_le32(fw->data);
 345
 346        v4l2_dbg(3, debug, sd, "FW: %s size %zu register sets %d\n",
 347                 S5K4ECGX_FIRMWARE, fw->size, regs_num);
 348
 349        regs_num++; /* Add header */
 350        if (fw->size != regs_num * FW_RECORD_SIZE + FW_CRC_SIZE) {
 351                err = -EINVAL;
 352                goto fw_out;
 353        }
 354        crc_file = get_unaligned_le32(fw->data + regs_num * FW_RECORD_SIZE);
 355        crc = crc32_le(~0, fw->data, regs_num * FW_RECORD_SIZE);
 356        if (crc != crc_file) {
 357                v4l2_err(sd, "FW: invalid crc (%#x:%#x)\n", crc, crc_file);
 358                err = -EINVAL;
 359                goto fw_out;
 360        }
 361        ptr = fw->data + FW_RECORD_SIZE;
 362        for (i = 1; i < regs_num; i++) {
 363                addr = get_unaligned_le32(ptr);
 364                ptr += sizeof(u32);
 365                val = get_unaligned_le16(ptr);
 366                ptr += sizeof(u16);
 367                if (addr - addr_inc != 2)
 368                        err = s5k4ecgx_write(client, addr, val);
 369                else
 370                        err = s5k4ecgx_i2c_write(client, REG_CMDBUF0_ADDR, val);
 371                if (err)
 372                        break;
 373                addr_inc = addr;
 374        }
 375fw_out:
 376        release_firmware(fw);
 377        return err;
 378}
 379
 380/* Set preview and capture input window */
 381static int s5k4ecgx_set_input_window(struct i2c_client *c,
 382                                     const struct v4l2_rect *r)
 383{
 384        int ret;
 385
 386        ret = s5k4ecgx_write(c, REG_G_PREV_IN_WIDTH, r->width);
 387        if (!ret)
 388                ret = s5k4ecgx_write(c, REG_G_PREV_IN_HEIGHT, r->height);
 389        if (!ret)
 390                ret = s5k4ecgx_write(c, REG_G_PREV_IN_XOFFS, r->left);
 391        if (!ret)
 392                ret = s5k4ecgx_write(c, REG_G_PREV_IN_YOFFS, r->top);
 393        if (!ret)
 394                ret = s5k4ecgx_write(c, REG_G_CAP_IN_WIDTH, r->width);
 395        if (!ret)
 396                ret = s5k4ecgx_write(c, REG_G_CAP_IN_HEIGHT, r->height);
 397        if (!ret)
 398                ret = s5k4ecgx_write(c, REG_G_CAP_IN_XOFFS, r->left);
 399        if (!ret)
 400                ret = s5k4ecgx_write(c, REG_G_CAP_IN_YOFFS, r->top);
 401
 402        return ret;
 403}
 404
 405/* Set preview and capture zoom input window */
 406static int s5k4ecgx_set_zoom_window(struct i2c_client *c,
 407                                    const struct v4l2_rect *r)
 408{
 409        int ret;
 410
 411        ret = s5k4ecgx_write(c, REG_G_PREVZOOM_IN_WIDTH, r->width);
 412        if (!ret)
 413                ret = s5k4ecgx_write(c, REG_G_PREVZOOM_IN_HEIGHT, r->height);
 414        if (!ret)
 415                ret = s5k4ecgx_write(c, REG_G_PREVZOOM_IN_XOFFS, r->left);
 416        if (!ret)
 417                ret = s5k4ecgx_write(c, REG_G_PREVZOOM_IN_YOFFS, r->top);
 418        if (!ret)
 419                ret = s5k4ecgx_write(c, REG_G_CAPZOOM_IN_WIDTH, r->width);
 420        if (!ret)
 421                ret = s5k4ecgx_write(c, REG_G_CAPZOOM_IN_HEIGHT, r->height);
 422        if (!ret)
 423                ret = s5k4ecgx_write(c, REG_G_CAPZOOM_IN_XOFFS, r->left);
 424        if (!ret)
 425                ret = s5k4ecgx_write(c, REG_G_CAPZOOM_IN_YOFFS, r->top);
 426
 427        return ret;
 428}
 429
 430static int s5k4ecgx_set_output_framefmt(struct s5k4ecgx *priv)
 431{
 432        struct i2c_client *client = v4l2_get_subdevdata(&priv->sd);
 433        int ret;
 434
 435        ret = s5k4ecgx_write(client, REG_P_OUT_WIDTH(0),
 436                             priv->curr_frmsize->size.width);
 437        if (!ret)
 438                ret = s5k4ecgx_write(client, REG_P_OUT_HEIGHT(0),
 439                                     priv->curr_frmsize->size.height);
 440        if (!ret)
 441                ret = s5k4ecgx_write(client, REG_P_FMT(0),
 442                                     priv->curr_pixfmt->reg_p_format);
 443        return ret;
 444}
 445
 446static int s5k4ecgx_init_sensor(struct v4l2_subdev *sd)
 447{
 448        int ret;
 449
 450        ret = s5k4ecgx_set_ahb_address(sd);
 451
 452        /* The delay is from manufacturer's settings */
 453        msleep(100);
 454
 455        if (!ret)
 456                ret = s5k4ecgx_load_firmware(sd);
 457        if (ret)
 458                v4l2_err(sd, "Failed to write initial settings\n");
 459
 460        return ret;
 461}
 462
 463static int s5k4ecgx_gpio_set_value(struct s5k4ecgx *priv, int id, u32 val)
 464{
 465        if (!gpio_is_valid(priv->gpio[id].gpio))
 466                return 0;
 467        gpio_set_value(priv->gpio[id].gpio, val);
 468
 469        return 1;
 470}
 471
 472static int __s5k4ecgx_power_on(struct s5k4ecgx *priv)
 473{
 474        int ret;
 475
 476        ret = regulator_bulk_enable(S5K4ECGX_NUM_SUPPLIES, priv->supplies);
 477        if (ret)
 478                return ret;
 479        usleep_range(30, 50);
 480
 481        /* The polarity of STBY is controlled by TSP */
 482        if (s5k4ecgx_gpio_set_value(priv, STBY, priv->gpio[STBY].level))
 483                usleep_range(30, 50);
 484
 485        if (s5k4ecgx_gpio_set_value(priv, RST, priv->gpio[RST].level))
 486                usleep_range(30, 50);
 487
 488        return 0;
 489}
 490
 491static int __s5k4ecgx_power_off(struct s5k4ecgx *priv)
 492{
 493        if (s5k4ecgx_gpio_set_value(priv, RST, !priv->gpio[RST].level))
 494                usleep_range(30, 50);
 495
 496        if (s5k4ecgx_gpio_set_value(priv, STBY, !priv->gpio[STBY].level))
 497                usleep_range(30, 50);
 498
 499        priv->streaming = 0;
 500
 501        return regulator_bulk_disable(S5K4ECGX_NUM_SUPPLIES, priv->supplies);
 502}
 503
 504/* Find nearest matching image pixel size. */
 505static int s5k4ecgx_try_frame_size(struct v4l2_mbus_framefmt *mf,
 506                                  const struct s5k4ecgx_frmsize **size)
 507{
 508        unsigned int min_err = ~0;
 509        int i = ARRAY_SIZE(s5k4ecgx_prev_sizes);
 510        const struct s5k4ecgx_frmsize *fsize = &s5k4ecgx_prev_sizes[0],
 511                *match = NULL;
 512
 513        while (i--) {
 514                int err = abs(fsize->size.width - mf->width)
 515                                + abs(fsize->size.height - mf->height);
 516                if (err < min_err) {
 517                        min_err = err;
 518                        match = fsize;
 519                }
 520                fsize++;
 521        }
 522        if (match) {
 523                mf->width  = match->size.width;
 524                mf->height = match->size.height;
 525                if (size)
 526                        *size = match;
 527                return 0;
 528        }
 529
 530        return -EINVAL;
 531}
 532
 533static int s5k4ecgx_enum_mbus_code(struct v4l2_subdev *sd,
 534                                   struct v4l2_subdev_pad_config *cfg,
 535                                   struct v4l2_subdev_mbus_code_enum *code)
 536{
 537        if (code->index >= ARRAY_SIZE(s5k4ecgx_formats))
 538                return -EINVAL;
 539        code->code = s5k4ecgx_formats[code->index].code;
 540
 541        return 0;
 542}
 543
 544static int s5k4ecgx_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg,
 545                           struct v4l2_subdev_format *fmt)
 546{
 547        struct s5k4ecgx *priv = to_s5k4ecgx(sd);
 548        struct v4l2_mbus_framefmt *mf;
 549
 550        if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
 551                if (cfg) {
 552                        mf = v4l2_subdev_get_try_format(sd, cfg, 0);
 553                        fmt->format = *mf;
 554                }
 555                return 0;
 556        }
 557
 558        mf = &fmt->format;
 559
 560        mutex_lock(&priv->lock);
 561        mf->width = priv->curr_frmsize->size.width;
 562        mf->height = priv->curr_frmsize->size.height;
 563        mf->code = priv->curr_pixfmt->code;
 564        mf->colorspace = priv->curr_pixfmt->colorspace;
 565        mf->field = V4L2_FIELD_NONE;
 566        mutex_unlock(&priv->lock);
 567
 568        return 0;
 569}
 570
 571static const struct s5k4ecgx_pixfmt *s5k4ecgx_try_fmt(struct v4l2_subdev *sd,
 572                                            struct v4l2_mbus_framefmt *mf)
 573{
 574        int i = ARRAY_SIZE(s5k4ecgx_formats);
 575
 576        while (--i)
 577                if (mf->code == s5k4ecgx_formats[i].code)
 578                        break;
 579        mf->code = s5k4ecgx_formats[i].code;
 580
 581        return &s5k4ecgx_formats[i];
 582}
 583
 584static int s5k4ecgx_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg,
 585                            struct v4l2_subdev_format *fmt)
 586{
 587        struct s5k4ecgx *priv = to_s5k4ecgx(sd);
 588        const struct s5k4ecgx_frmsize *fsize = NULL;
 589        const struct s5k4ecgx_pixfmt *pf;
 590        struct v4l2_mbus_framefmt *mf;
 591        int ret = 0;
 592
 593        pf = s5k4ecgx_try_fmt(sd, &fmt->format);
 594        s5k4ecgx_try_frame_size(&fmt->format, &fsize);
 595        fmt->format.colorspace = V4L2_COLORSPACE_JPEG;
 596        fmt->format.field = V4L2_FIELD_NONE;
 597
 598        if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
 599                if (cfg) {
 600                        mf = v4l2_subdev_get_try_format(sd, cfg, 0);
 601                        *mf = fmt->format;
 602                }
 603                return 0;
 604        }
 605
 606        mutex_lock(&priv->lock);
 607        if (!priv->streaming) {
 608                priv->curr_frmsize = fsize;
 609                priv->curr_pixfmt = pf;
 610                priv->set_params = 1;
 611        } else {
 612                ret = -EBUSY;
 613        }
 614        mutex_unlock(&priv->lock);
 615
 616        return ret;
 617}
 618
 619static const struct v4l2_subdev_pad_ops s5k4ecgx_pad_ops = {
 620        .enum_mbus_code = s5k4ecgx_enum_mbus_code,
 621        .get_fmt        = s5k4ecgx_get_fmt,
 622        .set_fmt        = s5k4ecgx_set_fmt,
 623};
 624
 625/*
 626 * V4L2 subdev controls
 627 */
 628static int s5k4ecgx_s_ctrl(struct v4l2_ctrl *ctrl)
 629{
 630        struct v4l2_subdev *sd = &container_of(ctrl->handler, struct s5k4ecgx,
 631                                                handler)->sd;
 632        struct i2c_client *client = v4l2_get_subdevdata(sd);
 633        struct s5k4ecgx *priv = to_s5k4ecgx(sd);
 634        unsigned int i;
 635        int err = 0;
 636
 637        v4l2_dbg(1, debug, sd, "ctrl: 0x%x, value: %d\n", ctrl->id, ctrl->val);
 638
 639        mutex_lock(&priv->lock);
 640        switch (ctrl->id) {
 641        case V4L2_CID_CONTRAST:
 642                err = s5k4ecgx_write(client, REG_USER_CONTRAST, ctrl->val);
 643                break;
 644
 645        case V4L2_CID_SATURATION:
 646                err = s5k4ecgx_write(client, REG_USER_SATURATION, ctrl->val);
 647                break;
 648
 649        case V4L2_CID_SHARPNESS:
 650                /* TODO: Revisit, is this setting for all presets ? */
 651                for (i = 0; i < 4 && !err; i++)
 652                        err = s5k4ecgx_write(client, REG_USER_SHARPNESS(i),
 653                                             ctrl->val * SHARPNESS_DIV);
 654                break;
 655
 656        case V4L2_CID_BRIGHTNESS:
 657                err = s5k4ecgx_write(client, REG_USER_BRIGHTNESS, ctrl->val);
 658                break;
 659        }
 660        mutex_unlock(&priv->lock);
 661        if (err < 0)
 662                v4l2_err(sd, "Failed to write s_ctrl err %d\n", err);
 663
 664        return err;
 665}
 666
 667static const struct v4l2_ctrl_ops s5k4ecgx_ctrl_ops = {
 668        .s_ctrl = s5k4ecgx_s_ctrl,
 669};
 670
 671/*
 672 * Reading s5k4ecgx version information
 673 */
 674static int s5k4ecgx_registered(struct v4l2_subdev *sd)
 675{
 676        int ret;
 677        struct s5k4ecgx *priv = to_s5k4ecgx(sd);
 678
 679        mutex_lock(&priv->lock);
 680        ret = __s5k4ecgx_power_on(priv);
 681        if (!ret) {
 682                ret = s5k4ecgx_read_fw_ver(sd);
 683                __s5k4ecgx_power_off(priv);
 684        }
 685        mutex_unlock(&priv->lock);
 686
 687        return ret;
 688}
 689
 690/*
 691 * V4L2 subdev internal operations
 692 */
 693static int s5k4ecgx_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
 694{
 695        struct v4l2_mbus_framefmt *mf = v4l2_subdev_get_try_format(sd, fh->pad, 0);
 696
 697        mf->width = s5k4ecgx_prev_sizes[0].size.width;
 698        mf->height = s5k4ecgx_prev_sizes[0].size.height;
 699        mf->code = s5k4ecgx_formats[0].code;
 700        mf->colorspace = V4L2_COLORSPACE_JPEG;
 701        mf->field = V4L2_FIELD_NONE;
 702
 703        return 0;
 704}
 705
 706static const struct v4l2_subdev_internal_ops s5k4ecgx_subdev_internal_ops = {
 707        .registered = s5k4ecgx_registered,
 708        .open = s5k4ecgx_open,
 709};
 710
 711static int s5k4ecgx_s_power(struct v4l2_subdev *sd, int on)
 712{
 713        struct s5k4ecgx *priv = to_s5k4ecgx(sd);
 714        int ret;
 715
 716        v4l2_dbg(1, debug, sd, "Switching %s\n", on ? "on" : "off");
 717
 718        if (on) {
 719                ret = __s5k4ecgx_power_on(priv);
 720                if (ret < 0)
 721                        return ret;
 722                /* Time to stabilize sensor */
 723                msleep(100);
 724                ret = s5k4ecgx_init_sensor(sd);
 725                if (ret < 0)
 726                        __s5k4ecgx_power_off(priv);
 727                else
 728                        priv->set_params = 1;
 729        } else {
 730                ret = __s5k4ecgx_power_off(priv);
 731        }
 732
 733        return ret;
 734}
 735
 736static int s5k4ecgx_log_status(struct v4l2_subdev *sd)
 737{
 738        v4l2_ctrl_handler_log_status(sd->ctrl_handler, sd->name);
 739
 740        return 0;
 741}
 742
 743static const struct v4l2_subdev_core_ops s5k4ecgx_core_ops = {
 744        .s_power        = s5k4ecgx_s_power,
 745        .log_status     = s5k4ecgx_log_status,
 746};
 747
 748static int __s5k4ecgx_s_params(struct s5k4ecgx *priv)
 749{
 750        struct i2c_client *client = v4l2_get_subdevdata(&priv->sd);
 751        const struct v4l2_rect *crop_rect = &priv->curr_frmsize->input_window;
 752        int ret;
 753
 754        ret = s5k4ecgx_set_input_window(client, crop_rect);
 755        if (!ret)
 756                ret = s5k4ecgx_set_zoom_window(client, crop_rect);
 757        if (!ret)
 758                ret = s5k4ecgx_write(client, REG_G_INPUTS_CHANGE_REQ, 1);
 759        if (!ret)
 760                ret = s5k4ecgx_write(client, 0x70000a1e, 0x28);
 761        if (!ret)
 762                ret = s5k4ecgx_write(client, 0x70000ad4, 0x3c);
 763        if (!ret)
 764                ret = s5k4ecgx_set_output_framefmt(priv);
 765        if (!ret)
 766                ret = s5k4ecgx_write(client, REG_P_PVI_MASK(0), 0x52);
 767        if (!ret)
 768                ret = s5k4ecgx_write(client, REG_P_FR_TIME_TYPE(0),
 769                                     FR_TIME_DYNAMIC);
 770        if (!ret)
 771                ret = s5k4ecgx_write(client, REG_P_FR_TIME_Q_TYPE(0),
 772                                     FR_TIME_Q_BEST_FRRATE);
 773        if (!ret)
 774                ret = s5k4ecgx_write(client,  REG_P_MIN_FR_TIME(0),
 775                                     US_TO_FR_TIME(33300));
 776        if (!ret)
 777                ret = s5k4ecgx_write(client, REG_P_MAX_FR_TIME(0),
 778                                     US_TO_FR_TIME(66600));
 779        if (!ret)
 780                ret = s5k4ecgx_write(client, REG_P_PREV_MIRROR(0), 0);
 781        if (!ret)
 782                ret = s5k4ecgx_write(client, REG_P_CAP_MIRROR(0), 0);
 783        if (!ret)
 784                ret = s5k4ecgx_write(client, REG_G_ACTIVE_PREV_CFG, 0);
 785        if (!ret)
 786                ret = s5k4ecgx_write(client, REG_G_PREV_OPEN_AFTER_CH, 1);
 787        if (!ret)
 788                ret = s5k4ecgx_write(client, REG_G_NEW_CFG_SYNC, 1);
 789        if (!ret)
 790                ret = s5k4ecgx_write(client, REG_G_PREV_CFG_CHG, 1);
 791
 792        return ret;
 793}
 794
 795static int __s5k4ecgx_s_stream(struct s5k4ecgx *priv, int on)
 796{
 797        struct i2c_client *client = v4l2_get_subdevdata(&priv->sd);
 798        int ret;
 799
 800        if (on && priv->set_params) {
 801                ret = __s5k4ecgx_s_params(priv);
 802                if (ret < 0)
 803                        return ret;
 804                priv->set_params = 0;
 805        }
 806        /*
 807         * This enables/disables preview stream only. Capture requests
 808         * are not supported yet.
 809         */
 810        ret = s5k4ecgx_write(client, REG_G_ENABLE_PREV, on);
 811        if (ret < 0)
 812                return ret;
 813        return s5k4ecgx_write(client, REG_G_ENABLE_PREV_CHG, 1);
 814}
 815
 816static int s5k4ecgx_s_stream(struct v4l2_subdev *sd, int on)
 817{
 818        struct s5k4ecgx *priv = to_s5k4ecgx(sd);
 819        int ret = 0;
 820
 821        v4l2_dbg(1, debug, sd, "Turn streaming %s\n", on ? "on" : "off");
 822
 823        mutex_lock(&priv->lock);
 824
 825        if (priv->streaming == !on) {
 826                ret = __s5k4ecgx_s_stream(priv, on);
 827                if (!ret)
 828                        priv->streaming = on & 1;
 829        }
 830
 831        mutex_unlock(&priv->lock);
 832        return ret;
 833}
 834
 835static const struct v4l2_subdev_video_ops s5k4ecgx_video_ops = {
 836        .s_stream = s5k4ecgx_s_stream,
 837};
 838
 839static const struct v4l2_subdev_ops s5k4ecgx_ops = {
 840        .core = &s5k4ecgx_core_ops,
 841        .pad = &s5k4ecgx_pad_ops,
 842        .video = &s5k4ecgx_video_ops,
 843};
 844
 845/*
 846 * GPIO setup
 847 */
 848static int s5k4ecgx_config_gpio(int nr, int val, const char *name)
 849{
 850        unsigned long flags = val ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW;
 851        int ret;
 852
 853        if (!gpio_is_valid(nr))
 854                return 0;
 855        ret = gpio_request_one(nr, flags, name);
 856        if (!ret)
 857                gpio_export(nr, 0);
 858
 859        return ret;
 860}
 861
 862static void s5k4ecgx_free_gpios(struct s5k4ecgx *priv)
 863{
 864        int i;
 865
 866        for (i = 0; i < ARRAY_SIZE(priv->gpio); i++) {
 867                if (!gpio_is_valid(priv->gpio[i].gpio))
 868                        continue;
 869                gpio_free(priv->gpio[i].gpio);
 870                priv->gpio[i].gpio = -EINVAL;
 871        }
 872}
 873
 874static int s5k4ecgx_config_gpios(struct s5k4ecgx *priv,
 875                                  const struct s5k4ecgx_platform_data *pdata)
 876{
 877        const struct s5k4ecgx_gpio *gpio = &pdata->gpio_stby;
 878        int ret;
 879
 880        priv->gpio[STBY].gpio = -EINVAL;
 881        priv->gpio[RST].gpio  = -EINVAL;
 882
 883        ret = s5k4ecgx_config_gpio(gpio->gpio, gpio->level, "S5K4ECGX_STBY");
 884
 885        if (ret) {
 886                s5k4ecgx_free_gpios(priv);
 887                return ret;
 888        }
 889        priv->gpio[STBY] = *gpio;
 890        if (gpio_is_valid(gpio->gpio))
 891                gpio_set_value(gpio->gpio, 0);
 892
 893        gpio = &pdata->gpio_reset;
 894
 895        ret = s5k4ecgx_config_gpio(gpio->gpio, gpio->level, "S5K4ECGX_RST");
 896        if (ret) {
 897                s5k4ecgx_free_gpios(priv);
 898                return ret;
 899        }
 900        priv->gpio[RST] = *gpio;
 901        if (gpio_is_valid(gpio->gpio))
 902                gpio_set_value(gpio->gpio, 0);
 903
 904        return 0;
 905}
 906
 907static int s5k4ecgx_init_v4l2_ctrls(struct s5k4ecgx *priv)
 908{
 909        const struct v4l2_ctrl_ops *ops = &s5k4ecgx_ctrl_ops;
 910        struct v4l2_ctrl_handler *hdl = &priv->handler;
 911        int ret;
 912
 913        ret = v4l2_ctrl_handler_init(hdl, 4);
 914        if (ret)
 915                return ret;
 916
 917        v4l2_ctrl_new_std(hdl, ops, V4L2_CID_BRIGHTNESS, -208, 127, 1, 0);
 918        v4l2_ctrl_new_std(hdl, ops, V4L2_CID_CONTRAST, -127, 127, 1, 0);
 919        v4l2_ctrl_new_std(hdl, ops, V4L2_CID_SATURATION, -127, 127, 1, 0);
 920
 921        /* Sharpness default is 24612, and then (24612/SHARPNESS_DIV) = 2 */
 922        v4l2_ctrl_new_std(hdl, ops, V4L2_CID_SHARPNESS, -32704/SHARPNESS_DIV,
 923                          24612/SHARPNESS_DIV, 1, 2);
 924        if (hdl->error) {
 925                ret = hdl->error;
 926                v4l2_ctrl_handler_free(hdl);
 927                return ret;
 928        }
 929        priv->sd.ctrl_handler = hdl;
 930
 931        return 0;
 932};
 933
 934static int s5k4ecgx_probe(struct i2c_client *client,
 935                          const struct i2c_device_id *id)
 936{
 937        struct s5k4ecgx_platform_data *pdata = client->dev.platform_data;
 938        struct v4l2_subdev *sd;
 939        struct s5k4ecgx *priv;
 940        int ret, i;
 941
 942        if (pdata == NULL) {
 943                dev_err(&client->dev, "platform data is missing!\n");
 944                return -EINVAL;
 945        }
 946
 947        priv = devm_kzalloc(&client->dev, sizeof(struct s5k4ecgx), GFP_KERNEL);
 948        if (!priv)
 949                return -ENOMEM;
 950
 951        mutex_init(&priv->lock);
 952        priv->streaming = 0;
 953
 954        sd = &priv->sd;
 955        /* Registering subdev */
 956        v4l2_i2c_subdev_init(sd, client, &s5k4ecgx_ops);
 957        strlcpy(sd->name, S5K4ECGX_DRIVER_NAME, sizeof(sd->name));
 958
 959        sd->internal_ops = &s5k4ecgx_subdev_internal_ops;
 960        /* Support v4l2 sub-device user space API */
 961        sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
 962
 963        priv->pad.flags = MEDIA_PAD_FL_SOURCE;
 964        sd->entity.function = MEDIA_ENT_F_CAM_SENSOR;
 965        ret = media_entity_pads_init(&sd->entity, 1, &priv->pad);
 966        if (ret)
 967                return ret;
 968
 969        ret = s5k4ecgx_config_gpios(priv, pdata);
 970        if (ret) {
 971                dev_err(&client->dev, "Failed to set gpios\n");
 972                goto out_err1;
 973        }
 974        for (i = 0; i < S5K4ECGX_NUM_SUPPLIES; i++)
 975                priv->supplies[i].supply = s5k4ecgx_supply_names[i];
 976
 977        ret = devm_regulator_bulk_get(&client->dev, S5K4ECGX_NUM_SUPPLIES,
 978                                 priv->supplies);
 979        if (ret) {
 980                dev_err(&client->dev, "Failed to get regulators\n");
 981                goto out_err2;
 982        }
 983        ret = s5k4ecgx_init_v4l2_ctrls(priv);
 984        if (ret)
 985                goto out_err2;
 986
 987        priv->curr_pixfmt = &s5k4ecgx_formats[0];
 988        priv->curr_frmsize = &s5k4ecgx_prev_sizes[0];
 989
 990        return 0;
 991
 992out_err2:
 993        s5k4ecgx_free_gpios(priv);
 994out_err1:
 995        media_entity_cleanup(&priv->sd.entity);
 996
 997        return ret;
 998}
 999
1000static int s5k4ecgx_remove(struct i2c_client *client)
1001{
1002        struct v4l2_subdev *sd = i2c_get_clientdata(client);
1003        struct s5k4ecgx *priv = to_s5k4ecgx(sd);
1004
1005        mutex_destroy(&priv->lock);
1006        s5k4ecgx_free_gpios(priv);
1007        v4l2_device_unregister_subdev(sd);
1008        v4l2_ctrl_handler_free(&priv->handler);
1009        media_entity_cleanup(&sd->entity);
1010
1011        return 0;
1012}
1013
1014static const struct i2c_device_id s5k4ecgx_id[] = {
1015        { S5K4ECGX_DRIVER_NAME, 0 },
1016        {}
1017};
1018MODULE_DEVICE_TABLE(i2c, s5k4ecgx_id);
1019
1020static struct i2c_driver v4l2_i2c_driver = {
1021        .driver = {
1022                .name = S5K4ECGX_DRIVER_NAME,
1023        },
1024        .probe = s5k4ecgx_probe,
1025        .remove = s5k4ecgx_remove,
1026        .id_table = s5k4ecgx_id,
1027};
1028
1029module_i2c_driver(v4l2_i2c_driver);
1030
1031MODULE_DESCRIPTION("Samsung S5K4ECGX 5MP SOC camera");
1032MODULE_AUTHOR("Sangwook Lee <sangwook.lee@linaro.org>");
1033MODULE_AUTHOR("Seok-Young Jang <quartz.jang@samsung.com>");
1034MODULE_LICENSE("GPL");
1035MODULE_FIRMWARE(S5K4ECGX_FIRMWARE);
1036