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