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 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 u32 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 = MEDIA_BUS_FMT_YUYV8_2X8, 205 .colorspace = V4L2_COLORSPACE_JPEG, 206 .ispctl1_reg = 0x03, 207 }, { 208 .code = MEDIA_BUS_FMT_YVYU8_2X8, 209 .colorspace = V4L2_COLORSPACE_JPEG, 210 .ispctl1_reg = 0x02, 211 }, { 212 .code = MEDIA_BUS_FMT_VYUY8_2X8, 213 .colorspace = V4L2_COLORSPACE_JPEG, 214 .ispctl1_reg = 0, 215 }, { 216 .code = MEDIA_BUS_FMT_UYVY8_2X8, 217 .colorspace = V4L2_COLORSPACE_JPEG, 218 .ispctl1_reg = 0x01, 219 }, { 220 .code = MEDIA_BUS_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 u32 *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