linux/drivers/media/i2c/sr030pc30.c
<<
>>
Prefs
   1/*
   2 * Driver for SiliconFile SR030PC30 VGA (1/10-Inch) Image Sensor with ISP
   3 *
   4 * Copyright (C) 2010 Samsung Electronics Co., Ltd
   5 * Author: Sylwester Nawrocki, s.nawrocki@samsung.com
   6 *
   7 * Based on original driver authored by Dongsoo Nathaniel Kim
   8 * and HeungJun Kim <riverful.kim@samsung.com>.
   9 *
  10 * Based on mt9v011 Micron Digital Image Sensor driver
  11 * Copyright (c) 2009 Mauro Carvalho Chehab (mchehab@redhat.com)
  12 *
  13 * This program is free software; you can redistribute it and/or modify
  14 * it under the terms of the GNU General Public License as published by
  15 * the Free Software Foundation; either version 2 of the License, or
  16 * (at your option) any later version.
  17 */
  18
  19#include <linux/i2c.h>
  20#include <linux/delay.h>
  21#include <linux/slab.h>
  22#include <linux/module.h>
  23#include <media/v4l2-device.h>
  24#include <media/v4l2-subdev.h>
  25#include <media/v4l2-mediabus.h>
  26#include <media/v4l2-ctrls.h>
  27#include <media/sr030pc30.h>
  28
  29static int debug;
  30module_param(debug, int, 0644);
  31
  32#define MODULE_NAME     "SR030PC30"
  33
  34/*
  35 * Register offsets within a page
  36 * b15..b8 - page id, b7..b0 - register address
  37 */
  38#define POWER_CTRL_REG          0x0001
  39#define PAGEMODE_REG            0x03
  40#define DEVICE_ID_REG           0x0004
  41#define NOON010PC30_ID          0x86
  42#define SR030PC30_ID            0x8C
  43#define VDO_CTL1_REG            0x0010
  44#define SUBSAMPL_NONE_VGA       0
  45#define SUBSAMPL_QVGA           0x10
  46#define SUBSAMPL_QQVGA          0x20
  47#define VDO_CTL2_REG            0x0011
  48#define SYNC_CTL_REG            0x0012
  49#define WIN_ROWH_REG            0x0020
  50#define WIN_ROWL_REG            0x0021
  51#define WIN_COLH_REG            0x0022
  52#define WIN_COLL_REG            0x0023
  53#define WIN_HEIGHTH_REG         0x0024
  54#define WIN_HEIGHTL_REG         0x0025
  55#define WIN_WIDTHH_REG          0x0026
  56#define WIN_WIDTHL_REG          0x0027
  57#define HBLANKH_REG             0x0040
  58#define HBLANKL_REG             0x0041
  59#define VSYNCH_REG              0x0042
  60#define VSYNCL_REG              0x0043
  61/* page 10 */
  62#define ISP_CTL_REG(n)          (0x1010 + (n))
  63#define YOFS_REG                0x1040
  64#define DARK_YOFS_REG           0x1041
  65#define AG_ABRTH_REG            0x1050
  66#define SAT_CTL_REG             0x1060
  67#define BSAT_REG                0x1061
  68#define RSAT_REG                0x1062
  69#define AG_SAT_TH_REG           0x1063
  70/* page 11 */
  71#define ZLPF_CTRL_REG           0x1110
  72#define ZLPF_CTRL2_REG          0x1112
  73#define ZLPF_AGH_THR_REG        0x1121
  74#define ZLPF_THR_REG            0x1160
  75#define ZLPF_DYN_THR_REG        0x1160
  76/* page 12 */
  77#define YCLPF_CTL1_REG          0x1240
  78#define YCLPF_CTL2_REG          0x1241
  79#define YCLPF_THR_REG           0x1250
  80#define BLPF_CTL_REG            0x1270
  81#define BLPF_THR1_REG           0x1274
  82#define BLPF_THR2_REG           0x1275
  83/* page 14 - Lens Shading Compensation */
  84#define LENS_CTRL_REG           0x1410
  85#define LENS_XCEN_REG           0x1420
  86#define LENS_YCEN_REG           0x1421
  87#define LENS_R_COMP_REG         0x1422
  88#define LENS_G_COMP_REG         0x1423
  89#define LENS_B_COMP_REG         0x1424
  90/* page 15 - Color correction */
  91#define CMC_CTL_REG             0x1510
  92#define CMC_OFSGH_REG           0x1514
  93#define CMC_OFSGL_REG           0x1516
  94#define CMC_SIGN_REG            0x1517
  95/* Color correction coefficients */
  96#define CMC_COEF_REG(n)         (0x1530 + (n))
  97/* Color correction offset coefficients */
  98#define CMC_OFS_REG(n)          (0x1540 + (n))
  99/* page 16 - Gamma correction */
 100#define GMA_CTL_REG             0x1610
 101/* Gamma correction coefficients 0.14 */
 102#define GMA_COEF_REG(n)         (0x1630 + (n))
 103/* page 20 - Auto Exposure */
 104#define AE_CTL1_REG             0x2010
 105#define AE_CTL2_REG             0x2011
 106#define AE_FRM_CTL_REG          0x2020
 107#define AE_FINE_CTL_REG(n)      (0x2028 + (n))
 108#define EXP_TIMEH_REG           0x2083
 109#define EXP_TIMEM_REG           0x2084
 110#define EXP_TIMEL_REG           0x2085
 111#define EXP_MMINH_REG           0x2086
 112#define EXP_MMINL_REG           0x2087
 113#define EXP_MMAXH_REG           0x2088
 114#define EXP_MMAXM_REG           0x2089
 115#define EXP_MMAXL_REG           0x208A
 116/* page 22 - Auto White Balance */
 117#define AWB_CTL1_REG            0x2210
 118#define AWB_ENABLE              0x80
 119#define AWB_CTL2_REG            0x2211
 120#define MWB_ENABLE              0x01
 121/* RGB gain control (manual WB) when AWB_CTL1[7]=0 */
 122#define AWB_RGAIN_REG           0x2280
 123#define AWB_GGAIN_REG           0x2281
 124#define AWB_BGAIN_REG           0x2282
 125#define AWB_RMAX_REG            0x2283
 126#define AWB_RMIN_REG            0x2284
 127#define AWB_BMAX_REG            0x2285
 128#define AWB_BMIN_REG            0x2286
 129/* R, B gain range in bright light conditions */
 130#define AWB_RMAXB_REG           0x2287
 131#define AWB_RMINB_REG           0x2288
 132#define AWB_BMAXB_REG           0x2289
 133#define AWB_BMINB_REG           0x228A
 134/* manual white balance, when AWB_CTL2[0]=1 */
 135#define MWB_RGAIN_REG           0x22B2
 136#define MWB_BGAIN_REG           0x22B3
 137/* the token to mark an array end */
 138#define REG_TERM                0xFFFF
 139
 140/* Minimum and maximum exposure time in ms */
 141#define EXPOS_MIN_MS            1
 142#define EXPOS_MAX_MS            125
 143
 144struct sr030pc30_info {
 145        struct v4l2_subdev sd;
 146        struct v4l2_ctrl_handler hdl;
 147        const struct sr030pc30_platform_data *pdata;
 148        const struct sr030pc30_format *curr_fmt;
 149        const struct sr030pc30_frmsize *curr_win;
 150        unsigned int hflip:1;
 151        unsigned int vflip:1;
 152        unsigned int sleep:1;
 153        struct {
 154                /* auto whitebalance control cluster */
 155                struct v4l2_ctrl *awb;
 156                struct v4l2_ctrl *red;
 157                struct v4l2_ctrl *blue;
 158        };
 159        struct {
 160                /* auto exposure control cluster */
 161                struct v4l2_ctrl *autoexp;
 162                struct v4l2_ctrl *exp;
 163        };
 164        u8 i2c_reg_page;
 165};
 166
 167struct sr030pc30_format {
 168        enum v4l2_mbus_pixelcode code;
 169        enum v4l2_colorspace colorspace;
 170        u16 ispctl1_reg;
 171};
 172
 173struct sr030pc30_frmsize {
 174        u16 width;
 175        u16 height;
 176        int vid_ctl1;
 177};
 178
 179struct i2c_regval {
 180        u16 addr;
 181        u16 val;
 182};
 183
 184/* supported resolutions */
 185static const struct sr030pc30_frmsize sr030pc30_sizes[] = {
 186        {
 187                .width          = 640,
 188                .height         = 480,
 189                .vid_ctl1       = SUBSAMPL_NONE_VGA,
 190        }, {
 191                .width          = 320,
 192                .height         = 240,
 193                .vid_ctl1       = SUBSAMPL_QVGA,
 194        }, {
 195                .width          = 160,
 196                .height         = 120,
 197                .vid_ctl1       = SUBSAMPL_QQVGA,
 198        },
 199};
 200
 201/* supported pixel formats */
 202static const struct sr030pc30_format sr030pc30_formats[] = {
 203        {
 204                .code           = V4L2_MBUS_FMT_YUYV8_2X8,
 205                .colorspace     = V4L2_COLORSPACE_JPEG,
 206                .ispctl1_reg    = 0x03,
 207        }, {
 208                .code           = V4L2_MBUS_FMT_YVYU8_2X8,
 209                .colorspace     = V4L2_COLORSPACE_JPEG,
 210                .ispctl1_reg    = 0x02,
 211        }, {
 212                .code           = V4L2_MBUS_FMT_VYUY8_2X8,
 213                .colorspace     = V4L2_COLORSPACE_JPEG,
 214                .ispctl1_reg    = 0,
 215        }, {
 216                .code           = V4L2_MBUS_FMT_UYVY8_2X8,
 217                .colorspace     = V4L2_COLORSPACE_JPEG,
 218                .ispctl1_reg    = 0x01,
 219        }, {
 220                .code           = V4L2_MBUS_FMT_RGB565_2X8_BE,
 221                .colorspace     = V4L2_COLORSPACE_JPEG,
 222                .ispctl1_reg    = 0x40,
 223        },
 224};
 225
 226static const struct i2c_regval sr030pc30_base_regs[] = {
 227        /* Window size and position within pixel matrix */
 228        { WIN_ROWH_REG,         0x00 }, { WIN_ROWL_REG,         0x06 },
 229        { WIN_COLH_REG,         0x00 }, { WIN_COLL_REG,         0x06 },
 230        { WIN_HEIGHTH_REG,      0x01 }, { WIN_HEIGHTL_REG,      0xE0 },
 231        { WIN_WIDTHH_REG,       0x02 }, { WIN_WIDTHL_REG,       0x80 },
 232        { HBLANKH_REG,          0x01 }, { HBLANKL_REG,          0x50 },
 233        { VSYNCH_REG,           0x00 }, { VSYNCL_REG,           0x14 },
 234        { SYNC_CTL_REG,         0 },
 235        /* Color corection and saturation */
 236        { ISP_CTL_REG(0),       0x30 }, { YOFS_REG,             0x80 },
 237        { DARK_YOFS_REG,        0x04 }, { AG_ABRTH_REG,         0x78 },
 238        { SAT_CTL_REG,          0x1F }, { BSAT_REG,             0x90 },
 239        { AG_SAT_TH_REG,        0xF0 }, { 0x1064,               0x80 },
 240        { CMC_CTL_REG,          0x03 }, { CMC_OFSGH_REG,        0x3C },
 241        { CMC_OFSGL_REG,        0x2C }, { CMC_SIGN_REG,         0x2F },
 242        { CMC_COEF_REG(0),      0xCB }, { CMC_OFS_REG(0),       0x87 },
 243        { CMC_COEF_REG(1),      0x61 }, { CMC_OFS_REG(1),       0x18 },
 244        { CMC_COEF_REG(2),      0x16 }, { CMC_OFS_REG(2),       0x91 },
 245        { CMC_COEF_REG(3),      0x23 }, { CMC_OFS_REG(3),       0x94 },
 246        { CMC_COEF_REG(4),      0xCE }, { CMC_OFS_REG(4),       0x9f },
 247        { CMC_COEF_REG(5),      0x2B }, { CMC_OFS_REG(5),       0x33 },
 248        { CMC_COEF_REG(6),      0x01 }, { CMC_OFS_REG(6),       0x00 },
 249        { CMC_COEF_REG(7),      0x34 }, { CMC_OFS_REG(7),       0x94 },
 250        { CMC_COEF_REG(8),      0x75 }, { CMC_OFS_REG(8),       0x14 },
 251        /* Color corection coefficients */
 252        { GMA_CTL_REG,          0x03 }, { GMA_COEF_REG(0),      0x00 },
 253        { GMA_COEF_REG(1),      0x19 }, { GMA_COEF_REG(2),      0x26 },
 254        { GMA_COEF_REG(3),      0x3B }, { GMA_COEF_REG(4),      0x5D },
 255        { GMA_COEF_REG(5),      0x79 }, { GMA_COEF_REG(6),      0x8E },
 256        { GMA_COEF_REG(7),      0x9F }, { GMA_COEF_REG(8),      0xAF },
 257        { GMA_COEF_REG(9),      0xBD }, { GMA_COEF_REG(10),     0xCA },
 258        { GMA_COEF_REG(11),     0xDD }, { GMA_COEF_REG(12),     0xEC },
 259        { GMA_COEF_REG(13),     0xF7 }, { GMA_COEF_REG(14),     0xFF },
 260        /* Noise reduction, Z-LPF, YC-LPF and BLPF filters setup */
 261        { ZLPF_CTRL_REG,        0x99 }, { ZLPF_CTRL2_REG,       0x0E },
 262        { ZLPF_AGH_THR_REG,     0x29 }, { ZLPF_THR_REG,         0x0F },
 263        { ZLPF_DYN_THR_REG,     0x63 }, { YCLPF_CTL1_REG,       0x23 },
 264        { YCLPF_CTL2_REG,       0x3B }, { YCLPF_THR_REG,        0x05 },
 265        { BLPF_CTL_REG,         0x1D }, { BLPF_THR1_REG,        0x05 },
 266        { BLPF_THR2_REG,        0x04 },
 267        /* Automatic white balance */
 268        { AWB_CTL1_REG,         0xFB }, { AWB_CTL2_REG,         0x26 },
 269        { AWB_RMAX_REG,         0x54 }, { AWB_RMIN_REG,         0x2B },
 270        { AWB_BMAX_REG,         0x57 }, { AWB_BMIN_REG,         0x29 },
 271        { AWB_RMAXB_REG,        0x50 }, { AWB_RMINB_REG,        0x43 },
 272        { AWB_BMAXB_REG,        0x30 }, { AWB_BMINB_REG,        0x22 },
 273        /* Auto exposure */
 274        { AE_CTL1_REG,          0x8C }, { AE_CTL2_REG,          0x04 },
 275        { AE_FRM_CTL_REG,       0x01 }, { AE_FINE_CTL_REG(0),   0x3F },
 276        { AE_FINE_CTL_REG(1),   0xA3 }, { AE_FINE_CTL_REG(3),   0x34 },
 277        /* Lens shading compensation */
 278        { LENS_CTRL_REG,        0x01 }, { LENS_XCEN_REG,        0x80 },
 279        { LENS_YCEN_REG,        0x70 }, { LENS_R_COMP_REG,      0x53 },
 280        { LENS_G_COMP_REG,      0x40 }, { LENS_B_COMP_REG,      0x3e },
 281        { REG_TERM,             0 },
 282};
 283
 284static inline struct sr030pc30_info *to_sr030pc30(struct v4l2_subdev *sd)
 285{
 286        return container_of(sd, struct sr030pc30_info, sd);
 287}
 288
 289static inline int set_i2c_page(struct sr030pc30_info *info,
 290                               struct i2c_client *client, unsigned int reg)
 291{
 292        int ret = 0;
 293        u32 page = reg >> 8 & 0xFF;
 294
 295        if (info->i2c_reg_page != page && (reg & 0xFF) != 0x03) {
 296                ret = i2c_smbus_write_byte_data(client, PAGEMODE_REG, page);
 297                if (!ret)
 298                        info->i2c_reg_page = page;
 299        }
 300        return ret;
 301}
 302
 303static int cam_i2c_read(struct v4l2_subdev *sd, u32 reg_addr)
 304{
 305        struct i2c_client *client = v4l2_get_subdevdata(sd);
 306        struct sr030pc30_info *info = to_sr030pc30(sd);
 307
 308        int ret = set_i2c_page(info, client, reg_addr);
 309        if (!ret)
 310                ret = i2c_smbus_read_byte_data(client, reg_addr & 0xFF);
 311        return ret;
 312}
 313
 314static int cam_i2c_write(struct v4l2_subdev *sd, u32 reg_addr, u32 val)
 315{
 316        struct i2c_client *client = v4l2_get_subdevdata(sd);
 317        struct sr030pc30_info *info = to_sr030pc30(sd);
 318
 319        int ret = set_i2c_page(info, client, reg_addr);
 320        if (!ret)
 321                ret = i2c_smbus_write_byte_data(
 322                        client, reg_addr & 0xFF, val);
 323        return ret;
 324}
 325
 326static inline int sr030pc30_bulk_write_reg(struct v4l2_subdev *sd,
 327                                const struct i2c_regval *msg)
 328{
 329        while (msg->addr != REG_TERM) {
 330                int ret = cam_i2c_write(sd, msg->addr, msg->val);
 331                if (ret)
 332                        return ret;
 333                msg++;
 334        }
 335        return 0;
 336}
 337
 338/* Device reset and sleep mode control */
 339static int sr030pc30_pwr_ctrl(struct v4l2_subdev *sd,
 340                                     bool reset, bool sleep)
 341{
 342        struct sr030pc30_info *info = to_sr030pc30(sd);
 343        u8 reg = sleep ? 0xF1 : 0xF0;
 344        int ret = 0;
 345
 346        if (reset)
 347                ret = cam_i2c_write(sd, POWER_CTRL_REG, reg | 0x02);
 348        if (!ret) {
 349                ret = cam_i2c_write(sd, POWER_CTRL_REG, reg);
 350                if (!ret) {
 351                        info->sleep = sleep;
 352                        if (reset)
 353                                info->i2c_reg_page = -1;
 354                }
 355        }
 356        return ret;
 357}
 358
 359static int sr030pc30_set_flip(struct v4l2_subdev *sd)
 360{
 361        struct sr030pc30_info *info = to_sr030pc30(sd);
 362
 363        s32 reg = cam_i2c_read(sd, VDO_CTL2_REG);
 364        if (reg < 0)
 365                return reg;
 366
 367        reg &= 0x7C;
 368        if (info->hflip)
 369                reg |= 0x01;
 370        if (info->vflip)
 371                reg |= 0x02;
 372        return cam_i2c_write(sd, VDO_CTL2_REG, reg | 0x80);
 373}
 374
 375/* Configure resolution, color format and image flip */
 376static int sr030pc30_set_params(struct v4l2_subdev *sd)
 377{
 378        struct sr030pc30_info *info = to_sr030pc30(sd);
 379        int ret;
 380
 381        if (!info->curr_win)
 382                return -EINVAL;
 383
 384        /* Configure the resolution through subsampling */
 385        ret = cam_i2c_write(sd, VDO_CTL1_REG,
 386                            info->curr_win->vid_ctl1);
 387
 388        if (!ret && info->curr_fmt)
 389                ret = cam_i2c_write(sd, ISP_CTL_REG(0),
 390                                info->curr_fmt->ispctl1_reg);
 391        if (!ret)
 392                ret = sr030pc30_set_flip(sd);
 393
 394        return ret;
 395}
 396
 397/* Find nearest matching image pixel size. */
 398static int sr030pc30_try_frame_size(struct v4l2_mbus_framefmt *mf)
 399{
 400        unsigned int min_err = ~0;
 401        int i = ARRAY_SIZE(sr030pc30_sizes);
 402        const struct sr030pc30_frmsize *fsize = &sr030pc30_sizes[0],
 403                                        *match = NULL;
 404        while (i--) {
 405                int err = abs(fsize->width - mf->width)
 406                                + abs(fsize->height - mf->height);
 407                if (err < min_err) {
 408                        min_err = err;
 409                        match = fsize;
 410                }
 411                fsize++;
 412        }
 413        if (match) {
 414                mf->width  = match->width;
 415                mf->height = match->height;
 416                return 0;
 417        }
 418        return -EINVAL;
 419}
 420
 421static int sr030pc30_s_ctrl(struct v4l2_ctrl *ctrl)
 422{
 423        struct sr030pc30_info *info =
 424                container_of(ctrl->handler, struct sr030pc30_info, hdl);
 425        struct v4l2_subdev *sd = &info->sd;
 426        int ret = 0;
 427
 428        v4l2_dbg(1, debug, sd, "%s: ctrl_id: %d, value: %d\n",
 429                         __func__, ctrl->id, ctrl->val);
 430
 431        switch (ctrl->id) {
 432        case V4L2_CID_AUTO_WHITE_BALANCE:
 433                if (ctrl->is_new) {
 434                        ret = cam_i2c_write(sd, AWB_CTL2_REG,
 435                                        ctrl->val ? 0x2E : 0x2F);
 436                        if (!ret)
 437                                ret = cam_i2c_write(sd, AWB_CTL1_REG,
 438                                                ctrl->val ? 0xFB : 0x7B);
 439                }
 440                if (!ret && info->blue->is_new)
 441                        ret = cam_i2c_write(sd, MWB_BGAIN_REG, info->blue->val);
 442                if (!ret && info->red->is_new)
 443                        ret = cam_i2c_write(sd, MWB_RGAIN_REG, info->red->val);
 444                return ret;
 445
 446        case V4L2_CID_EXPOSURE_AUTO:
 447                /* auto anti-flicker is also enabled here */
 448                if (ctrl->is_new)
 449                        ret = cam_i2c_write(sd, AE_CTL1_REG,
 450                                ctrl->val == V4L2_EXPOSURE_AUTO ? 0xDC : 0x0C);
 451                if (info->exp->is_new) {
 452                        unsigned long expos = info->exp->val;
 453
 454                        expos = expos * info->pdata->clk_rate / (8 * 1000);
 455
 456                        if (!ret)
 457                                ret = cam_i2c_write(sd, EXP_TIMEH_REG,
 458                                                expos >> 16 & 0xFF);
 459                        if (!ret)
 460                                ret = cam_i2c_write(sd, EXP_TIMEM_REG,
 461                                                expos >> 8 & 0xFF);
 462                        if (!ret)
 463                                ret = cam_i2c_write(sd, EXP_TIMEL_REG,
 464                                                expos & 0xFF);
 465                }
 466                return ret;
 467        default:
 468                return -EINVAL;
 469        }
 470
 471        return 0;
 472}
 473
 474static int sr030pc30_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
 475                              enum v4l2_mbus_pixelcode *code)
 476{
 477        if (!code || index >= ARRAY_SIZE(sr030pc30_formats))
 478                return -EINVAL;
 479
 480        *code = sr030pc30_formats[index].code;
 481        return 0;
 482}
 483
 484static int sr030pc30_g_fmt(struct v4l2_subdev *sd,
 485                           struct v4l2_mbus_framefmt *mf)
 486{
 487        struct sr030pc30_info *info = to_sr030pc30(sd);
 488        int ret;
 489
 490        if (!mf)
 491                return -EINVAL;
 492
 493        if (!info->curr_win || !info->curr_fmt) {
 494                ret = sr030pc30_set_params(sd);
 495                if (ret)
 496                        return ret;
 497        }
 498
 499        mf->width       = info->curr_win->width;
 500        mf->height      = info->curr_win->height;
 501        mf->code        = info->curr_fmt->code;
 502        mf->colorspace  = info->curr_fmt->colorspace;
 503        mf->field       = V4L2_FIELD_NONE;
 504
 505        return 0;
 506}
 507
 508/* Return nearest media bus frame format. */
 509static const struct sr030pc30_format *try_fmt(struct v4l2_subdev *sd,
 510                                              struct v4l2_mbus_framefmt *mf)
 511{
 512        int i = ARRAY_SIZE(sr030pc30_formats);
 513
 514        sr030pc30_try_frame_size(mf);
 515
 516        while (i--)
 517                if (mf->code == sr030pc30_formats[i].code)
 518                        break;
 519
 520        mf->code = sr030pc30_formats[i].code;
 521
 522        return &sr030pc30_formats[i];
 523}
 524
 525/* Return nearest media bus frame format. */
 526static int sr030pc30_try_fmt(struct v4l2_subdev *sd,
 527                             struct v4l2_mbus_framefmt *mf)
 528{
 529        if (!sd || !mf)
 530                return -EINVAL;
 531
 532        try_fmt(sd, mf);
 533        return 0;
 534}
 535
 536static int sr030pc30_s_fmt(struct v4l2_subdev *sd,
 537                           struct v4l2_mbus_framefmt *mf)
 538{
 539        struct sr030pc30_info *info = to_sr030pc30(sd);
 540
 541        if (!sd || !mf)
 542                return -EINVAL;
 543
 544        info->curr_fmt = try_fmt(sd, mf);
 545
 546        return sr030pc30_set_params(sd);
 547}
 548
 549static int sr030pc30_base_config(struct v4l2_subdev *sd)
 550{
 551        struct sr030pc30_info *info = to_sr030pc30(sd);
 552        int ret;
 553        unsigned long expmin, expmax;
 554
 555        ret = sr030pc30_bulk_write_reg(sd, sr030pc30_base_regs);
 556        if (!ret) {
 557                info->curr_fmt = &sr030pc30_formats[0];
 558                info->curr_win = &sr030pc30_sizes[0];
 559                ret = sr030pc30_set_params(sd);
 560        }
 561        if (!ret)
 562                ret = sr030pc30_pwr_ctrl(sd, false, false);
 563
 564        if (!ret && !info->pdata)
 565                return ret;
 566
 567        expmin = EXPOS_MIN_MS * info->pdata->clk_rate / (8 * 1000);
 568        expmax = EXPOS_MAX_MS * info->pdata->clk_rate / (8 * 1000);
 569
 570        v4l2_dbg(1, debug, sd, "%s: expmin= %lx, expmax= %lx", __func__,
 571                 expmin, expmax);
 572
 573        /* Setting up manual exposure time range */
 574        ret = cam_i2c_write(sd, EXP_MMINH_REG, expmin >> 8 & 0xFF);
 575        if (!ret)
 576                ret = cam_i2c_write(sd, EXP_MMINL_REG, expmin & 0xFF);
 577        if (!ret)
 578                ret = cam_i2c_write(sd, EXP_MMAXH_REG, expmax >> 16 & 0xFF);
 579        if (!ret)
 580                ret = cam_i2c_write(sd, EXP_MMAXM_REG, expmax >> 8 & 0xFF);
 581        if (!ret)
 582                ret = cam_i2c_write(sd, EXP_MMAXL_REG, expmax & 0xFF);
 583
 584        return ret;
 585}
 586
 587static int sr030pc30_s_power(struct v4l2_subdev *sd, int on)
 588{
 589        struct i2c_client *client = v4l2_get_subdevdata(sd);
 590        struct sr030pc30_info *info = to_sr030pc30(sd);
 591        const struct sr030pc30_platform_data *pdata = info->pdata;
 592        int ret;
 593
 594        if (pdata == NULL) {
 595                WARN(1, "No platform data!\n");
 596                return -EINVAL;
 597        }
 598
 599        /*
 600         * Put sensor into power sleep mode before switching off
 601         * power and disabling MCLK.
 602         */
 603        if (!on)
 604                sr030pc30_pwr_ctrl(sd, false, true);
 605
 606        /* set_power controls sensor's power and clock */
 607        if (pdata->set_power) {
 608                ret = pdata->set_power(&client->dev, on);
 609                if (ret)
 610                        return ret;
 611        }
 612
 613        if (on) {
 614                ret = sr030pc30_base_config(sd);
 615        } else {
 616                ret = 0;
 617                info->curr_win = NULL;
 618                info->curr_fmt = NULL;
 619        }
 620
 621        return ret;
 622}
 623
 624static const struct v4l2_ctrl_ops sr030pc30_ctrl_ops = {
 625        .s_ctrl = sr030pc30_s_ctrl,
 626};
 627
 628static const struct v4l2_subdev_core_ops sr030pc30_core_ops = {
 629        .s_power        = sr030pc30_s_power,
 630        .g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
 631        .try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
 632        .s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
 633        .g_ctrl = v4l2_subdev_g_ctrl,
 634        .s_ctrl = v4l2_subdev_s_ctrl,
 635        .queryctrl = v4l2_subdev_queryctrl,
 636        .querymenu = v4l2_subdev_querymenu,
 637};
 638
 639static const struct v4l2_subdev_video_ops sr030pc30_video_ops = {
 640        .g_mbus_fmt     = sr030pc30_g_fmt,
 641        .s_mbus_fmt     = sr030pc30_s_fmt,
 642        .try_mbus_fmt   = sr030pc30_try_fmt,
 643        .enum_mbus_fmt  = sr030pc30_enum_fmt,
 644};
 645
 646static const struct v4l2_subdev_ops sr030pc30_ops = {
 647        .core   = &sr030pc30_core_ops,
 648        .video  = &sr030pc30_video_ops,
 649};
 650
 651/*
 652 * Detect sensor type. Return 0 if SR030PC30 was detected
 653 * or -ENODEV otherwise.
 654 */
 655static int sr030pc30_detect(struct i2c_client *client)
 656{
 657        const struct sr030pc30_platform_data *pdata
 658                = client->dev.platform_data;
 659        int ret;
 660
 661        /* Enable sensor's power and clock */
 662        if (pdata->set_power) {
 663                ret = pdata->set_power(&client->dev, 1);
 664                if (ret)
 665                        return ret;
 666        }
 667
 668        ret = i2c_smbus_read_byte_data(client, DEVICE_ID_REG);
 669
 670        if (pdata->set_power)
 671                pdata->set_power(&client->dev, 0);
 672
 673        if (ret < 0) {
 674                dev_err(&client->dev, "%s: I2C read failed\n", __func__);
 675                return ret;
 676        }
 677
 678        return ret == SR030PC30_ID ? 0 : -ENODEV;
 679}
 680
 681
 682static int sr030pc30_probe(struct i2c_client *client,
 683                           const struct i2c_device_id *id)
 684{
 685        struct sr030pc30_info *info;
 686        struct v4l2_subdev *sd;
 687        struct v4l2_ctrl_handler *hdl;
 688        const struct sr030pc30_platform_data *pdata
 689                = client->dev.platform_data;
 690        int ret;
 691
 692        if (!pdata) {
 693                dev_err(&client->dev, "No platform data!");
 694                return -EIO;
 695        }
 696
 697        ret = sr030pc30_detect(client);
 698        if (ret)
 699                return ret;
 700
 701        info = devm_kzalloc(&client->dev, sizeof(*info), GFP_KERNEL);
 702        if (!info)
 703                return -ENOMEM;
 704
 705        sd = &info->sd;
 706        strcpy(sd->name, MODULE_NAME);
 707        info->pdata = client->dev.platform_data;
 708
 709        v4l2_i2c_subdev_init(sd, client, &sr030pc30_ops);
 710
 711        hdl = &info->hdl;
 712        v4l2_ctrl_handler_init(hdl, 6);
 713        info->awb = v4l2_ctrl_new_std(hdl, &sr030pc30_ctrl_ops,
 714                        V4L2_CID_AUTO_WHITE_BALANCE, 0, 1, 1, 1);
 715        info->red = v4l2_ctrl_new_std(hdl, &sr030pc30_ctrl_ops,
 716                        V4L2_CID_RED_BALANCE, 0, 127, 1, 64);
 717        info->blue = v4l2_ctrl_new_std(hdl, &sr030pc30_ctrl_ops,
 718                        V4L2_CID_BLUE_BALANCE, 0, 127, 1, 64);
 719        info->autoexp = v4l2_ctrl_new_std(hdl, &sr030pc30_ctrl_ops,
 720                        V4L2_CID_EXPOSURE_AUTO, 0, 1, 1, 1);
 721        info->exp = v4l2_ctrl_new_std(hdl, &sr030pc30_ctrl_ops,
 722                        V4L2_CID_EXPOSURE, EXPOS_MIN_MS, EXPOS_MAX_MS, 1, 30);
 723        sd->ctrl_handler = hdl;
 724        if (hdl->error) {
 725                int err = hdl->error;
 726
 727                v4l2_ctrl_handler_free(hdl);
 728                return err;
 729        }
 730        v4l2_ctrl_auto_cluster(3, &info->awb, 0, false);
 731        v4l2_ctrl_auto_cluster(2, &info->autoexp, V4L2_EXPOSURE_MANUAL, false);
 732        v4l2_ctrl_handler_setup(hdl);
 733
 734        info->i2c_reg_page      = -1;
 735        info->hflip             = 1;
 736
 737        return 0;
 738}
 739
 740static int sr030pc30_remove(struct i2c_client *client)
 741{
 742        struct v4l2_subdev *sd = i2c_get_clientdata(client);
 743
 744        v4l2_device_unregister_subdev(sd);
 745        v4l2_ctrl_handler_free(sd->ctrl_handler);
 746        return 0;
 747}
 748
 749static const struct i2c_device_id sr030pc30_id[] = {
 750        { MODULE_NAME, 0 },
 751        { },
 752};
 753MODULE_DEVICE_TABLE(i2c, sr030pc30_id);
 754
 755
 756static struct i2c_driver sr030pc30_i2c_driver = {
 757        .driver = {
 758                .name = MODULE_NAME
 759        },
 760        .probe          = sr030pc30_probe,
 761        .remove         = sr030pc30_remove,
 762        .id_table       = sr030pc30_id,
 763};
 764
 765module_i2c_driver(sr030pc30_i2c_driver);
 766
 767MODULE_DESCRIPTION("Siliconfile SR030PC30 camera driver");
 768MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>");
 769MODULE_LICENSE("GPL");
 770