1/* 2 * Driver for Samsung S5K6AAFX SXGA 1/6" 1.3M CMOS Image Sensor 3 * with embedded SoC ISP. 4 * 5 * Copyright (C) 2011, Samsung Electronics Co., Ltd. 6 * Sylwester Nawrocki <s.nawrocki@samsung.com> 7 * 8 * Based on a driver authored by Dongsoo Nathaniel Kim. 9 * Copyright (C) 2009, Dongsoo Nathaniel Kim <dongsoo45.kim@samsung.com> 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/delay.h> 19#include <linux/gpio.h> 20#include <linux/i2c.h> 21#include <linux/media.h> 22#include <linux/module.h> 23#include <linux/regulator/consumer.h> 24#include <linux/slab.h> 25 26#include <media/media-entity.h> 27#include <media/v4l2-ctrls.h> 28#include <media/v4l2-device.h> 29#include <media/v4l2-subdev.h> 30#include <media/v4l2-mediabus.h> 31#include <media/s5k6aa.h> 32 33static int debug; 34module_param(debug, int, 0644); 35 36#define DRIVER_NAME "S5K6AA" 37 38/* The token to indicate array termination */ 39#define S5K6AA_TERM 0xffff 40#define S5K6AA_OUT_WIDTH_DEF 640 41#define S5K6AA_OUT_HEIGHT_DEF 480 42#define S5K6AA_WIN_WIDTH_MAX 1280 43#define S5K6AA_WIN_HEIGHT_MAX 1024 44#define S5K6AA_WIN_WIDTH_MIN 8 45#define S5K6AA_WIN_HEIGHT_MIN 8 46 47/* 48 * H/W register Interface (0xD0000000 - 0xD0000FFF) 49 */ 50#define AHB_MSB_ADDR_PTR 0xfcfc 51#define GEN_REG_OFFSH 0xd000 52#define REG_CMDWR_ADDRH 0x0028 53#define REG_CMDWR_ADDRL 0x002a 54#define REG_CMDRD_ADDRH 0x002c 55#define REG_CMDRD_ADDRL 0x002e 56#define REG_CMDBUF0_ADDR 0x0f12 57#define REG_CMDBUF1_ADDR 0x0f10 58 59/* 60 * Host S/W Register interface (0x70000000 - 0x70002000) 61 * The value of the two most significant address bytes is 0x7000, 62 * (HOST_SWIF_OFFS_H). The register addresses below specify 2 LSBs. 63 */ 64#define HOST_SWIF_OFFSH 0x7000 65 66/* Initialization parameters */ 67/* Master clock frequency in KHz */ 68#define REG_I_INCLK_FREQ_L 0x01b8 69#define REG_I_INCLK_FREQ_H 0x01ba 70#define MIN_MCLK_FREQ_KHZ 6000U 71#define MAX_MCLK_FREQ_KHZ 27000U 72#define REG_I_USE_NPVI_CLOCKS 0x01c6 73#define REG_I_USE_NMIPI_CLOCKS 0x01c8 74 75/* Clock configurations, n = 0..2. REG_I_* frequency unit is 4 kHz. */ 76#define REG_I_OPCLK_4KHZ(n) ((n) * 6 + 0x01cc) 77#define REG_I_MIN_OUTRATE_4KHZ(n) ((n) * 6 + 0x01ce) 78#define REG_I_MAX_OUTRATE_4KHZ(n) ((n) * 6 + 0x01d0) 79#define SYS_PLL_OUT_FREQ (48000000 / 4000) 80#define PCLK_FREQ_MIN (24000000 / 4000) 81#define PCLK_FREQ_MAX (48000000 / 4000) 82#define REG_I_INIT_PARAMS_UPDATED 0x01e0 83#define REG_I_ERROR_INFO 0x01e2 84 85/* General purpose parameters */ 86#define REG_USER_BRIGHTNESS 0x01e4 87#define REG_USER_CONTRAST 0x01e6 88#define REG_USER_SATURATION 0x01e8 89#define REG_USER_SHARPBLUR 0x01ea 90 91#define REG_G_SPEC_EFFECTS 0x01ee 92#define REG_G_ENABLE_PREV 0x01f0 93#define REG_G_ENABLE_PREV_CHG 0x01f2 94#define REG_G_NEW_CFG_SYNC 0x01f8 95#define REG_G_PREVZOOM_IN_WIDTH 0x020a 96#define REG_G_PREVZOOM_IN_HEIGHT 0x020c 97#define REG_G_PREVZOOM_IN_XOFFS 0x020e 98#define REG_G_PREVZOOM_IN_YOFFS 0x0210 99#define REG_G_INPUTS_CHANGE_REQ 0x021a 100#define REG_G_ACTIVE_PREV_CFG 0x021c 101#define REG_G_PREV_CFG_CHG 0x021e 102#define REG_G_PREV_OPEN_AFTER_CH 0x0220 103#define REG_G_PREV_CFG_ERROR 0x0222 104 105/* Preview control section. n = 0...4. */ 106#define PREG(n, x) ((n) * 0x26 + x) 107#define REG_P_OUT_WIDTH(n) PREG(n, 0x0242) 108#define REG_P_OUT_HEIGHT(n) PREG(n, 0x0244) 109#define REG_P_FMT(n) PREG(n, 0x0246) 110#define REG_P_MAX_OUT_RATE(n) PREG(n, 0x0248) 111#define REG_P_MIN_OUT_RATE(n) PREG(n, 0x024a) 112#define REG_P_PVI_MASK(n) PREG(n, 0x024c) 113#define REG_P_CLK_INDEX(n) PREG(n, 0x024e) 114#define REG_P_FR_RATE_TYPE(n) PREG(n, 0x0250) 115#define FR_RATE_DYNAMIC 0 116#define FR_RATE_FIXED 1 117#define FR_RATE_FIXED_ACCURATE 2 118#define REG_P_FR_RATE_Q_TYPE(n) PREG(n, 0x0252) 119#define FR_RATE_Q_BEST_FRRATE 1 /* Binning enabled */ 120#define FR_RATE_Q_BEST_QUALITY 2 /* Binning disabled */ 121/* Frame period in 0.1 ms units */ 122#define REG_P_MAX_FR_TIME(n) PREG(n, 0x0254) 123#define REG_P_MIN_FR_TIME(n) PREG(n, 0x0256) 124/* Conversion to REG_P_[MAX/MIN]_FR_TIME value; __t: time in us */ 125#define US_TO_FR_TIME(__t) ((__t) / 100) 126#define S5K6AA_MIN_FR_TIME 33300 /* us */ 127#define S5K6AA_MAX_FR_TIME 650000 /* us */ 128#define S5K6AA_MAX_HIGHRES_FR_TIME 666 /* x100 us */ 129/* The below 5 registers are for "device correction" values */ 130#define REG_P_COLORTEMP(n) PREG(n, 0x025e) 131#define REG_P_PREV_MIRROR(n) PREG(n, 0x0262) 132 133/* Extended image property controls */ 134/* Exposure time in 10 us units */ 135#define REG_SF_USR_EXPOSURE_L 0x03c6 136#define REG_SF_USR_EXPOSURE_H 0x03c8 137#define REG_SF_USR_EXPOSURE_CHG 0x03ca 138#define REG_SF_USR_TOT_GAIN 0x03cc 139#define REG_SF_USR_TOT_GAIN_CHG 0x03ce 140#define REG_SF_RGAIN 0x03d0 141#define REG_SF_RGAIN_CHG 0x03d2 142#define REG_SF_GGAIN 0x03d4 143#define REG_SF_GGAIN_CHG 0x03d6 144#define REG_SF_BGAIN 0x03d8 145#define REG_SF_BGAIN_CHG 0x03da 146#define REG_SF_FLICKER_QUANT 0x03dc 147#define REG_SF_FLICKER_QUANT_CHG 0x03de 148 149/* Output interface (parallel/MIPI) setup */ 150#define REG_OIF_EN_MIPI_LANES 0x03fa 151#define REG_OIF_EN_PACKETS 0x03fc 152#define REG_OIF_CFG_CHG 0x03fe 153 154/* Auto-algorithms enable mask */ 155#define REG_DBG_AUTOALG_EN 0x0400 156#define AALG_ALL_EN_MASK (1 << 0) 157#define AALG_AE_EN_MASK (1 << 1) 158#define AALG_DIVLEI_EN_MASK (1 << 2) 159#define AALG_WB_EN_MASK (1 << 3) 160#define AALG_FLICKER_EN_MASK (1 << 5) 161#define AALG_FIT_EN_MASK (1 << 6) 162#define AALG_WRHW_EN_MASK (1 << 7) 163 164/* Firmware revision information */ 165#define REG_FW_APIVER 0x012e 166#define S5K6AAFX_FW_APIVER 0x0001 167#define REG_FW_REVISION 0x0130 168 169/* For now we use only one user configuration register set */ 170#define S5K6AA_MAX_PRESETS 1 171 172static const char * const s5k6aa_supply_names[] = { 173 "vdd_core", /* Digital core supply 1.5V (1.4V to 1.6V) */ 174 "vdda", /* Analog power supply 2.8V (2.6V to 3.0V) */ 175 "vdd_reg", /* Regulator input power 1.8V (1.7V to 1.9V) 176 or 2.8V (2.6V to 3.0) */ 177 "vddio", /* I/O supply 1.8V (1.65V to 1.95V) 178 or 2.8V (2.5V to 3.1V) */ 179}; 180#define S5K6AA_NUM_SUPPLIES ARRAY_SIZE(s5k6aa_supply_names) 181 182enum s5k6aa_gpio_id { 183 STBY, 184 RST, 185 GPIO_NUM, 186}; 187 188struct s5k6aa_regval { 189 u16 addr; 190 u16 val; 191}; 192 193struct s5k6aa_pixfmt { 194 u32 code; 195 u32 colorspace; 196 /* REG_P_FMT(x) register value */ 197 u16 reg_p_fmt; 198}; 199 200struct s5k6aa_preset { 201 /* output pixel format and resolution */ 202 struct v4l2_mbus_framefmt mbus_fmt; 203 u8 clk_id; 204 u8 index; 205}; 206 207struct s5k6aa_ctrls { 208 struct v4l2_ctrl_handler handler; 209 /* Auto / manual white balance cluster */ 210 struct v4l2_ctrl *awb; 211 struct v4l2_ctrl *gain_red; 212 struct v4l2_ctrl *gain_blue; 213 struct v4l2_ctrl *gain_green; 214 /* Mirror cluster */ 215 struct v4l2_ctrl *hflip; 216 struct v4l2_ctrl *vflip; 217 /* Auto exposure / manual exposure and gain cluster */ 218 struct v4l2_ctrl *auto_exp; 219 struct v4l2_ctrl *exposure; 220 struct v4l2_ctrl *gain; 221}; 222 223struct s5k6aa_interval { 224 u16 reg_fr_time; 225 struct v4l2_fract interval; 226 /* Maximum rectangle for the interval */ 227 struct v4l2_frmsize_discrete size; 228}; 229 230struct s5k6aa { 231 struct v4l2_subdev sd; 232 struct media_pad pad; 233 234 enum v4l2_mbus_type bus_type; 235 u8 mipi_lanes; 236 237 int (*s_power)(int enable); 238 struct regulator_bulk_data supplies[S5K6AA_NUM_SUPPLIES]; 239 struct s5k6aa_gpio gpio[GPIO_NUM]; 240 241 /* external master clock frequency */ 242 unsigned long mclk_frequency; 243 /* ISP internal master clock frequency */ 244 u16 clk_fop; 245 /* output pixel clock frequency range */ 246 u16 pclk_fmin; 247 u16 pclk_fmax; 248 249 unsigned int inv_hflip:1; 250 unsigned int inv_vflip:1; 251 252 /* protects the struct members below */ 253 struct mutex lock; 254 255 /* sensor matrix scan window */ 256 struct v4l2_rect ccd_rect; 257 258 struct s5k6aa_ctrls ctrls; 259 struct s5k6aa_preset presets[S5K6AA_MAX_PRESETS]; 260 struct s5k6aa_preset *preset; 261 const struct s5k6aa_interval *fiv; 262 263 unsigned int streaming:1; 264 unsigned int apply_cfg:1; 265 unsigned int apply_crop:1; 266 unsigned int power; 267}; 268 269static struct s5k6aa_regval s5k6aa_analog_config[] = { 270 /* Analog settings */ 271 { 0x112a, 0x0000 }, { 0x1132, 0x0000 }, 272 { 0x113e, 0x0000 }, { 0x115c, 0x0000 }, 273 { 0x1164, 0x0000 }, { 0x1174, 0x0000 }, 274 { 0x1178, 0x0000 }, { 0x077a, 0x0000 }, 275 { 0x077c, 0x0000 }, { 0x077e, 0x0000 }, 276 { 0x0780, 0x0000 }, { 0x0782, 0x0000 }, 277 { 0x0784, 0x0000 }, { 0x0786, 0x0000 }, 278 { 0x0788, 0x0000 }, { 0x07a2, 0x0000 }, 279 { 0x07a4, 0x0000 }, { 0x07a6, 0x0000 }, 280 { 0x07a8, 0x0000 }, { 0x07b6, 0x0000 }, 281 { 0x07b8, 0x0002 }, { 0x07ba, 0x0004 }, 282 { 0x07bc, 0x0004 }, { 0x07be, 0x0005 }, 283 { 0x07c0, 0x0005 }, { S5K6AA_TERM, 0 }, 284}; 285 286/* TODO: Add RGB888 and Bayer format */ 287static const struct s5k6aa_pixfmt s5k6aa_formats[] = { 288 { MEDIA_BUS_FMT_YUYV8_2X8, V4L2_COLORSPACE_JPEG, 5 }, 289 /* range 16-240 */ 290 { MEDIA_BUS_FMT_YUYV8_2X8, V4L2_COLORSPACE_REC709, 6 }, 291 { MEDIA_BUS_FMT_RGB565_2X8_BE, V4L2_COLORSPACE_JPEG, 0 }, 292}; 293 294static const struct s5k6aa_interval s5k6aa_intervals[] = { 295 { 1000, {10000, 1000000}, {1280, 1024} }, /* 10 fps */ 296 { 666, {15000, 1000000}, {1280, 1024} }, /* 15 fps */ 297 { 500, {20000, 1000000}, {1280, 720} }, /* 20 fps */ 298 { 400, {25000, 1000000}, {640, 480} }, /* 25 fps */ 299 { 333, {33300, 1000000}, {640, 480} }, /* 30 fps */ 300}; 301 302#define S5K6AA_INTERVAL_DEF_INDEX 1 /* 15 fps */ 303 304static inline struct v4l2_subdev *ctrl_to_sd(struct v4l2_ctrl *ctrl) 305{ 306 return &container_of(ctrl->handler, struct s5k6aa, ctrls.handler)->sd; 307} 308 309static inline struct s5k6aa *to_s5k6aa(struct v4l2_subdev *sd) 310{ 311 return container_of(sd, struct s5k6aa, sd); 312} 313 314/* Set initial values for all preview presets */ 315static void s5k6aa_presets_data_init(struct s5k6aa *s5k6aa) 316{ 317 struct s5k6aa_preset *preset = &s5k6aa->presets[0]; 318 int i; 319 320 for (i = 0; i < S5K6AA_MAX_PRESETS; i++) { 321 preset->mbus_fmt.width = S5K6AA_OUT_WIDTH_DEF; 322 preset->mbus_fmt.height = S5K6AA_OUT_HEIGHT_DEF; 323 preset->mbus_fmt.code = s5k6aa_formats[0].code; 324 preset->index = i; 325 preset->clk_id = 0; 326 preset++; 327 } 328 329 s5k6aa->fiv = &s5k6aa_intervals[S5K6AA_INTERVAL_DEF_INDEX]; 330 s5k6aa->preset = &s5k6aa->presets[0]; 331} 332 333static int s5k6aa_i2c_read(struct i2c_client *client, u16 addr, u16 *val) 334{ 335 u8 wbuf[2] = {addr >> 8, addr & 0xFF}; 336 struct i2c_msg msg[2]; 337 u8 rbuf[2]; 338 int ret; 339 340 msg[0].addr = client->addr; 341 msg[0].flags = 0; 342 msg[0].len = 2; 343 msg[0].buf = wbuf; 344 345 msg[1].addr = client->addr; 346 msg[1].flags = I2C_M_RD; 347 msg[1].len = 2; 348 msg[1].buf = rbuf; 349 350 ret = i2c_transfer(client->adapter, msg, 2); 351 *val = be16_to_cpu(*((__be16 *)rbuf)); 352 353 v4l2_dbg(3, debug, client, "i2c_read: 0x%04X : 0x%04x\n", addr, *val); 354 355 return ret == 2 ? 0 : ret; 356} 357 358static int s5k6aa_i2c_write(struct i2c_client *client, u16 addr, u16 val) 359{ 360 u8 buf[4] = {addr >> 8, addr & 0xFF, val >> 8, val & 0xFF}; 361 362 int ret = i2c_master_send(client, buf, 4); 363 v4l2_dbg(3, debug, client, "i2c_write: 0x%04X : 0x%04x\n", addr, val); 364 365 return ret == 4 ? 0 : ret; 366} 367 368/* The command register write, assumes Command_Wr_addH = 0x7000. */ 369static int s5k6aa_write(struct i2c_client *c, u16 addr, u16 val) 370{ 371 int ret = s5k6aa_i2c_write(c, REG_CMDWR_ADDRL, addr); 372 if (ret) 373 return ret; 374 return s5k6aa_i2c_write(c, REG_CMDBUF0_ADDR, val); 375} 376 377/* The command register read, assumes Command_Rd_addH = 0x7000. */ 378static int s5k6aa_read(struct i2c_client *client, u16 addr, u16 *val) 379{ 380 int ret = s5k6aa_i2c_write(client, REG_CMDRD_ADDRL, addr); 381 if (ret) 382 return ret; 383 return s5k6aa_i2c_read(client, REG_CMDBUF0_ADDR, val); 384} 385 386static int s5k6aa_write_array(struct v4l2_subdev *sd, 387 const struct s5k6aa_regval *msg) 388{ 389 struct i2c_client *client = v4l2_get_subdevdata(sd); 390 u16 addr_incr = 0; 391 int ret = 0; 392 393 while (msg->addr != S5K6AA_TERM) { 394 if (addr_incr != 2) 395 ret = s5k6aa_i2c_write(client, REG_CMDWR_ADDRL, 396 msg->addr); 397 if (ret) 398 break; 399 ret = s5k6aa_i2c_write(client, REG_CMDBUF0_ADDR, msg->val); 400 if (ret) 401 break; 402 /* Assume that msg->addr is always less than 0xfffc */ 403 addr_incr = (msg + 1)->addr - msg->addr; 404 msg++; 405 } 406 407 return ret; 408} 409 410/* Configure the AHB high address bytes for GTG registers access */ 411static int s5k6aa_set_ahb_address(struct i2c_client *client) 412{ 413 int ret = s5k6aa_i2c_write(client, AHB_MSB_ADDR_PTR, GEN_REG_OFFSH); 414 if (ret) 415 return ret; 416 ret = s5k6aa_i2c_write(client, REG_CMDRD_ADDRH, HOST_SWIF_OFFSH); 417 if (ret) 418 return ret; 419 return s5k6aa_i2c_write(client, REG_CMDWR_ADDRH, HOST_SWIF_OFFSH); 420} 421 422/** 423 * s5k6aa_configure_pixel_clock - apply ISP main clock/PLL configuration 424 * 425 * Configure the internal ISP PLL for the required output frequency. 426 * Locking: called with s5k6aa.lock mutex held. 427 */ 428static int s5k6aa_configure_pixel_clocks(struct s5k6aa *s5k6aa) 429{ 430 struct i2c_client *c = v4l2_get_subdevdata(&s5k6aa->sd); 431 unsigned long fmclk = s5k6aa->mclk_frequency / 1000; 432 u16 status; 433 int ret; 434 435 if (WARN(fmclk < MIN_MCLK_FREQ_KHZ || fmclk > MAX_MCLK_FREQ_KHZ, 436 "Invalid clock frequency: %ld\n", fmclk)) 437 return -EINVAL; 438 439 s5k6aa->pclk_fmin = PCLK_FREQ_MIN; 440 s5k6aa->pclk_fmax = PCLK_FREQ_MAX; 441 s5k6aa->clk_fop = SYS_PLL_OUT_FREQ; 442 443 /* External input clock frequency in kHz */ 444 ret = s5k6aa_write(c, REG_I_INCLK_FREQ_H, fmclk >> 16); 445 if (!ret) 446 ret = s5k6aa_write(c, REG_I_INCLK_FREQ_L, fmclk & 0xFFFF); 447 if (!ret) 448 ret = s5k6aa_write(c, REG_I_USE_NPVI_CLOCKS, 1); 449 /* Internal PLL frequency */ 450 if (!ret) 451 ret = s5k6aa_write(c, REG_I_OPCLK_4KHZ(0), s5k6aa->clk_fop); 452 if (!ret) 453 ret = s5k6aa_write(c, REG_I_MIN_OUTRATE_4KHZ(0), 454 s5k6aa->pclk_fmin); 455 if (!ret) 456 ret = s5k6aa_write(c, REG_I_MAX_OUTRATE_4KHZ(0), 457 s5k6aa->pclk_fmax); 458 if (!ret) 459 ret = s5k6aa_write(c, REG_I_INIT_PARAMS_UPDATED, 1); 460 if (!ret) 461 ret = s5k6aa_read(c, REG_I_ERROR_INFO, &status); 462 463 return ret ? ret : (status ? -EINVAL : 0); 464} 465 466/* Set horizontal and vertical image flipping */ 467static int s5k6aa_set_mirror(struct s5k6aa *s5k6aa, int horiz_flip) 468{ 469 struct i2c_client *client = v4l2_get_subdevdata(&s5k6aa->sd); 470 int index = s5k6aa->preset->index; 471 472 unsigned int vflip = s5k6aa->ctrls.vflip->val ^ s5k6aa->inv_vflip; 473 unsigned int flip = (horiz_flip ^ s5k6aa->inv_hflip) | (vflip << 1); 474 475 return s5k6aa_write(client, REG_P_PREV_MIRROR(index), flip); 476} 477 478/* Configure auto/manual white balance and R/G/B gains */ 479static int s5k6aa_set_awb(struct s5k6aa *s5k6aa, int awb) 480{ 481 struct i2c_client *c = v4l2_get_subdevdata(&s5k6aa->sd); 482 struct s5k6aa_ctrls *ctrls = &s5k6aa->ctrls; 483 u16 reg; 484 485 int ret = s5k6aa_read(c, REG_DBG_AUTOALG_EN, ®); 486 487 if (!ret && !awb) { 488 ret = s5k6aa_write(c, REG_SF_RGAIN, ctrls->gain_red->val); 489 if (!ret) 490 ret = s5k6aa_write(c, REG_SF_RGAIN_CHG, 1); 491 if (ret) 492 return ret; 493 494 ret = s5k6aa_write(c, REG_SF_GGAIN, ctrls->gain_green->val); 495 if (!ret) 496 ret = s5k6aa_write(c, REG_SF_GGAIN_CHG, 1); 497 if (ret) 498 return ret; 499 500 ret = s5k6aa_write(c, REG_SF_BGAIN, ctrls->gain_blue->val); 501 if (!ret) 502 ret = s5k6aa_write(c, REG_SF_BGAIN_CHG, 1); 503 } 504 if (!ret) { 505 reg = awb ? reg | AALG_WB_EN_MASK : reg & ~AALG_WB_EN_MASK; 506 ret = s5k6aa_write(c, REG_DBG_AUTOALG_EN, reg); 507 } 508 509 return ret; 510} 511 512/* Program FW with exposure time, 'exposure' in us units */ 513static int s5k6aa_set_user_exposure(struct i2c_client *client, int exposure) 514{ 515 unsigned int time = exposure / 10; 516 517 int ret = s5k6aa_write(client, REG_SF_USR_EXPOSURE_L, time & 0xffff); 518 if (!ret) 519 ret = s5k6aa_write(client, REG_SF_USR_EXPOSURE_H, time >> 16); 520 if (ret) 521 return ret; 522 return s5k6aa_write(client, REG_SF_USR_EXPOSURE_CHG, 1); 523} 524 525static int s5k6aa_set_user_gain(struct i2c_client *client, int gain) 526{ 527 int ret = s5k6aa_write(client, REG_SF_USR_TOT_GAIN, gain); 528 if (ret) 529 return ret; 530 return s5k6aa_write(client, REG_SF_USR_TOT_GAIN_CHG, 1); 531} 532 533/* Set auto/manual exposure and total gain */ 534static int s5k6aa_set_auto_exposure(struct s5k6aa *s5k6aa, int value) 535{ 536 struct i2c_client *c = v4l2_get_subdevdata(&s5k6aa->sd); 537 unsigned int exp_time = s5k6aa->ctrls.exposure->val; 538 u16 auto_alg; 539 540 int ret = s5k6aa_read(c, REG_DBG_AUTOALG_EN, &auto_alg); 541 if (ret) 542 return ret; 543 544 v4l2_dbg(1, debug, c, "man_exp: %d, auto_exp: %d, a_alg: 0x%x\n", 545 exp_time, value, auto_alg); 546 547 if (value == V4L2_EXPOSURE_AUTO) { 548 auto_alg |= AALG_AE_EN_MASK | AALG_DIVLEI_EN_MASK; 549 } else { 550 ret = s5k6aa_set_user_exposure(c, exp_time); 551 if (ret) 552 return ret; 553 ret = s5k6aa_set_user_gain(c, s5k6aa->ctrls.gain->val); 554 if (ret) 555 return ret; 556 auto_alg &= ~(AALG_AE_EN_MASK | AALG_DIVLEI_EN_MASK); 557 } 558 559 return s5k6aa_write(c, REG_DBG_AUTOALG_EN, auto_alg); 560} 561 562static int s5k6aa_set_anti_flicker(struct s5k6aa *s5k6aa, int value) 563{ 564 struct i2c_client *client = v4l2_get_subdevdata(&s5k6aa->sd); 565 u16 auto_alg; 566 int ret; 567 568 ret = s5k6aa_read(client, REG_DBG_AUTOALG_EN, &auto_alg); 569 if (ret) 570 return ret; 571 572 if (value == V4L2_CID_POWER_LINE_FREQUENCY_AUTO) { 573 auto_alg |= AALG_FLICKER_EN_MASK; 574 } else { 575 auto_alg &= ~AALG_FLICKER_EN_MASK; 576 /* The V4L2_CID_LINE_FREQUENCY control values match 577 * the register values */ 578 ret = s5k6aa_write(client, REG_SF_FLICKER_QUANT, value); 579 if (ret) 580 return ret; 581 ret = s5k6aa_write(client, REG_SF_FLICKER_QUANT_CHG, 1); 582 if (ret) 583 return ret; 584 } 585 586 return s5k6aa_write(client, REG_DBG_AUTOALG_EN, auto_alg); 587} 588 589static int s5k6aa_set_colorfx(struct s5k6aa *s5k6aa, int val) 590{ 591 struct i2c_client *client = v4l2_get_subdevdata(&s5k6aa->sd); 592 static const struct v4l2_control colorfx[] = { 593 { V4L2_COLORFX_NONE, 0 }, 594 { V4L2_COLORFX_BW, 1 }, 595 { V4L2_COLORFX_NEGATIVE, 2 }, 596 { V4L2_COLORFX_SEPIA, 3 }, 597 { V4L2_COLORFX_SKY_BLUE, 4 }, 598 { V4L2_COLORFX_SKETCH, 5 }, 599 }; 600 int i; 601 602 for (i = 0; i < ARRAY_SIZE(colorfx); i++) { 603 if (colorfx[i].id == val) 604 return s5k6aa_write(client, REG_G_SPEC_EFFECTS, 605 colorfx[i].value); 606 } 607 return -EINVAL; 608} 609 610static int s5k6aa_preview_config_status(struct i2c_client *client) 611{ 612 u16 error = 0; 613 int ret = s5k6aa_read(client, REG_G_PREV_CFG_ERROR, &error); 614 615 v4l2_dbg(1, debug, client, "error: 0x%x (%d)\n", error, ret); 616 return ret ? ret : (error ? -EINVAL : 0); 617} 618 619static int s5k6aa_get_pixfmt_index(struct s5k6aa *s5k6aa, 620 struct v4l2_mbus_framefmt *mf) 621{ 622 unsigned int i; 623 624 for (i = 0; i < ARRAY_SIZE(s5k6aa_formats); i++) 625 if (mf->colorspace == s5k6aa_formats[i].colorspace && 626 mf->code == s5k6aa_formats[i].code) 627 return i; 628 return 0; 629} 630 631static int s5k6aa_set_output_framefmt(struct s5k6aa *s5k6aa, 632 struct s5k6aa_preset *preset) 633{ 634 struct i2c_client *client = v4l2_get_subdevdata(&s5k6aa->sd); 635 int fmt_index = s5k6aa_get_pixfmt_index(s5k6aa, &preset->mbus_fmt); 636 int ret; 637 638 ret = s5k6aa_write(client, REG_P_OUT_WIDTH(preset->index), 639 preset->mbus_fmt.width); 640 if (!ret) 641 ret = s5k6aa_write(client, REG_P_OUT_HEIGHT(preset->index), 642 preset->mbus_fmt.height); 643 if (!ret) 644 ret = s5k6aa_write(client, REG_P_FMT(preset->index), 645 s5k6aa_formats[fmt_index].reg_p_fmt); 646 return ret; 647} 648 649static int s5k6aa_set_input_params(struct s5k6aa *s5k6aa) 650{ 651 struct i2c_client *c = v4l2_get_subdevdata(&s5k6aa->sd); 652 struct v4l2_rect *r = &s5k6aa->ccd_rect; 653 int ret; 654 655 ret = s5k6aa_write(c, REG_G_PREVZOOM_IN_WIDTH, r->width); 656 if (!ret) 657 ret = s5k6aa_write(c, REG_G_PREVZOOM_IN_HEIGHT, r->height); 658 if (!ret) 659 ret = s5k6aa_write(c, REG_G_PREVZOOM_IN_XOFFS, r->left); 660 if (!ret) 661 ret = s5k6aa_write(c, REG_G_PREVZOOM_IN_YOFFS, r->top); 662 if (!ret) 663 ret = s5k6aa_write(c, REG_G_INPUTS_CHANGE_REQ, 1); 664 if (!ret) 665 s5k6aa->apply_crop = 0; 666 667 return ret; 668} 669 670/** 671 * s5k6aa_configure_video_bus - configure the video output interface 672 * @bus_type: video bus type: parallel or MIPI-CSI 673 * @nlanes: number of MIPI lanes to be used (MIPI-CSI only) 674 * 675 * Note: Only parallel bus operation has been tested. 676 */ 677static int s5k6aa_configure_video_bus(struct s5k6aa *s5k6aa, 678 enum v4l2_mbus_type bus_type, int nlanes) 679{ 680 struct i2c_client *client = v4l2_get_subdevdata(&s5k6aa->sd); 681 u16 cfg = 0; 682 int ret; 683 684 /* 685 * TODO: The sensor is supposed to support BT.601 and BT.656 686 * but there is nothing indicating how to switch between both 687 * in the datasheet. For now default BT.601 interface is assumed. 688 */ 689 if (bus_type == V4L2_MBUS_CSI2) 690 cfg = nlanes; 691 else if (bus_type != V4L2_MBUS_PARALLEL) 692 return -EINVAL; 693 694 ret = s5k6aa_write(client, REG_OIF_EN_MIPI_LANES, cfg); 695 if (ret) 696 return ret; 697 return s5k6aa_write(client, REG_OIF_CFG_CHG, 1); 698} 699 700/* This function should be called when switching to new user configuration set*/ 701static int s5k6aa_new_config_sync(struct i2c_client *client, int timeout, 702 int cid) 703{ 704 unsigned long end = jiffies + msecs_to_jiffies(timeout); 705 u16 reg = 1; 706 int ret; 707 708 ret = s5k6aa_write(client, REG_G_ACTIVE_PREV_CFG, cid); 709 if (!ret) 710 ret = s5k6aa_write(client, REG_G_PREV_CFG_CHG, 1); 711 if (!ret) 712 ret = s5k6aa_write(client, REG_G_NEW_CFG_SYNC, 1); 713 if (timeout == 0) 714 return ret; 715 716 while (ret >= 0 && time_is_after_jiffies(end)) { 717 ret = s5k6aa_read(client, REG_G_NEW_CFG_SYNC, ®); 718 if (!reg) 719 return 0; 720 usleep_range(1000, 5000); 721 } 722 return ret ? ret : -ETIMEDOUT; 723} 724 725/** 726 * s5k6aa_set_prev_config - write user preview register set 727 * 728 * Configure output resolution and color fromat, pixel clock 729 * frequency range, device frame rate type and frame period range. 730 */ 731static int s5k6aa_set_prev_config(struct s5k6aa *s5k6aa, 732 struct s5k6aa_preset *preset) 733{ 734 struct i2c_client *client = v4l2_get_subdevdata(&s5k6aa->sd); 735 int idx = preset->index; 736 u16 frame_rate_q; 737 int ret; 738 739 if (s5k6aa->fiv->reg_fr_time >= S5K6AA_MAX_HIGHRES_FR_TIME) 740 frame_rate_q = FR_RATE_Q_BEST_FRRATE; 741 else 742 frame_rate_q = FR_RATE_Q_BEST_QUALITY; 743 744 ret = s5k6aa_set_output_framefmt(s5k6aa, preset); 745 if (!ret) 746 ret = s5k6aa_write(client, REG_P_MAX_OUT_RATE(idx), 747 s5k6aa->pclk_fmax); 748 if (!ret) 749 ret = s5k6aa_write(client, REG_P_MIN_OUT_RATE(idx), 750 s5k6aa->pclk_fmin); 751 if (!ret) 752 ret = s5k6aa_write(client, REG_P_CLK_INDEX(idx), 753 preset->clk_id); 754 if (!ret) 755 ret = s5k6aa_write(client, REG_P_FR_RATE_TYPE(idx), 756 FR_RATE_DYNAMIC); 757 if (!ret) 758 ret = s5k6aa_write(client, REG_P_FR_RATE_Q_TYPE(idx), 759 frame_rate_q); 760 if (!ret) 761 ret = s5k6aa_write(client, REG_P_MAX_FR_TIME(idx), 762 s5k6aa->fiv->reg_fr_time + 33); 763 if (!ret) 764 ret = s5k6aa_write(client, REG_P_MIN_FR_TIME(idx), 765 s5k6aa->fiv->reg_fr_time - 33); 766 if (!ret) 767 ret = s5k6aa_new_config_sync(client, 250, idx); 768 if (!ret) 769 ret = s5k6aa_preview_config_status(client); 770 if (!ret) 771 s5k6aa->apply_cfg = 0; 772 773 v4l2_dbg(1, debug, client, "Frame interval: %d +/- 3.3ms. (%d)\n", 774 s5k6aa->fiv->reg_fr_time, ret); 775 return ret; 776} 777 778/** 779 * s5k6aa_initialize_isp - basic ISP MCU initialization 780 * 781 * Configure AHB addresses for registers read/write; configure PLLs for 782 * required output pixel clock. The ISP power supply needs to be already 783 * enabled, with an optional H/W reset. 784 * Locking: called with s5k6aa.lock mutex held. 785 */ 786static int s5k6aa_initialize_isp(struct v4l2_subdev *sd) 787{ 788 struct i2c_client *client = v4l2_get_subdevdata(sd); 789 struct s5k6aa *s5k6aa = to_s5k6aa(sd); 790 int ret; 791 792 s5k6aa->apply_crop = 1; 793 s5k6aa->apply_cfg = 1; 794 msleep(100); 795 796 ret = s5k6aa_set_ahb_address(client); 797 if (ret) 798 return ret; 799 ret = s5k6aa_configure_video_bus(s5k6aa, s5k6aa->bus_type, 800 s5k6aa->mipi_lanes); 801 if (ret) 802 return ret; 803 ret = s5k6aa_write_array(sd, s5k6aa_analog_config); 804 if (ret) 805 return ret; 806 msleep(20); 807 808 return s5k6aa_configure_pixel_clocks(s5k6aa); 809} 810 811static int s5k6aa_gpio_set_value(struct s5k6aa *priv, int id, u32 val) 812{ 813 if (!gpio_is_valid(priv->gpio[id].gpio)) 814 return 0; 815 gpio_set_value(priv->gpio[id].gpio, !!val); 816 return 1; 817} 818 819static int s5k6aa_gpio_assert(struct s5k6aa *priv, int id) 820{ 821 return s5k6aa_gpio_set_value(priv, id, priv->gpio[id].level); 822} 823 824static int s5k6aa_gpio_deassert(struct s5k6aa *priv, int id) 825{ 826 return s5k6aa_gpio_set_value(priv, id, !priv->gpio[id].level); 827} 828 829static int __s5k6aa_power_on(struct s5k6aa *s5k6aa) 830{ 831 int ret; 832 833 ret = regulator_bulk_enable(S5K6AA_NUM_SUPPLIES, s5k6aa->supplies); 834 if (ret) 835 return ret; 836 if (s5k6aa_gpio_deassert(s5k6aa, STBY)) 837 usleep_range(150, 200); 838 839 if (s5k6aa->s_power) 840 ret = s5k6aa->s_power(1); 841 usleep_range(4000, 4000); 842 843 if (s5k6aa_gpio_deassert(s5k6aa, RST)) 844 msleep(20); 845 846 return ret; 847} 848 849static int __s5k6aa_power_off(struct s5k6aa *s5k6aa) 850{ 851 int ret; 852 853 if (s5k6aa_gpio_assert(s5k6aa, RST)) 854 usleep_range(100, 150); 855 856 if (s5k6aa->s_power) { 857 ret = s5k6aa->s_power(0); 858 if (ret) 859 return ret; 860 } 861 if (s5k6aa_gpio_assert(s5k6aa, STBY)) 862 usleep_range(50, 100); 863 s5k6aa->streaming = 0; 864 865 return regulator_bulk_disable(S5K6AA_NUM_SUPPLIES, s5k6aa->supplies); 866} 867 868/* 869 * V4L2 subdev core and video operations 870 */ 871static int s5k6aa_set_power(struct v4l2_subdev *sd, int on) 872{ 873 struct s5k6aa *s5k6aa = to_s5k6aa(sd); 874 int ret = 0; 875 876 mutex_lock(&s5k6aa->lock); 877 878 if (!on == s5k6aa->power) { 879 if (on) { 880 ret = __s5k6aa_power_on(s5k6aa); 881 if (!ret) 882 ret = s5k6aa_initialize_isp(sd); 883 } else { 884 ret = __s5k6aa_power_off(s5k6aa); 885 } 886 887 if (!ret) 888 s5k6aa->power += on ? 1 : -1; 889 } 890 891 mutex_unlock(&s5k6aa->lock); 892 893 if (!on || ret || s5k6aa->power != 1) 894 return ret; 895 896 return v4l2_ctrl_handler_setup(sd->ctrl_handler); 897} 898 899static int __s5k6aa_stream(struct s5k6aa *s5k6aa, int enable) 900{ 901 struct i2c_client *client = v4l2_get_subdevdata(&s5k6aa->sd); 902 int ret = 0; 903 904 ret = s5k6aa_write(client, REG_G_ENABLE_PREV, enable); 905 if (!ret) 906 ret = s5k6aa_write(client, REG_G_ENABLE_PREV_CHG, 1); 907 if (!ret) 908 s5k6aa->streaming = enable; 909 910 return ret; 911} 912 913static int s5k6aa_s_stream(struct v4l2_subdev *sd, int on) 914{ 915 struct s5k6aa *s5k6aa = to_s5k6aa(sd); 916 int ret = 0; 917 918 mutex_lock(&s5k6aa->lock); 919 920 if (s5k6aa->streaming == !on) { 921 if (!ret && s5k6aa->apply_cfg) 922 ret = s5k6aa_set_prev_config(s5k6aa, s5k6aa->preset); 923 if (s5k6aa->apply_crop) 924 ret = s5k6aa_set_input_params(s5k6aa); 925 if (!ret) 926 ret = __s5k6aa_stream(s5k6aa, !!on); 927 } 928 mutex_unlock(&s5k6aa->lock); 929 930 return ret; 931} 932 933static int s5k6aa_g_frame_interval(struct v4l2_subdev *sd, 934 struct v4l2_subdev_frame_interval *fi) 935{ 936 struct s5k6aa *s5k6aa = to_s5k6aa(sd); 937 938 mutex_lock(&s5k6aa->lock); 939 fi->interval = s5k6aa->fiv->interval; 940 mutex_unlock(&s5k6aa->lock); 941 942 return 0; 943} 944 945static int __s5k6aa_set_frame_interval(struct s5k6aa *s5k6aa, 946 struct v4l2_subdev_frame_interval *fi) 947{ 948 struct v4l2_mbus_framefmt *mbus_fmt = &s5k6aa->preset->mbus_fmt; 949 const struct s5k6aa_interval *fiv = &s5k6aa_intervals[0]; 950 unsigned int err, min_err = UINT_MAX; 951 unsigned int i, fr_time; 952 953 if (fi->interval.denominator == 0) 954 return -EINVAL; 955 956 fr_time = fi->interval.numerator * 10000 / fi->interval.denominator; 957 958 for (i = 0; i < ARRAY_SIZE(s5k6aa_intervals); i++) { 959 const struct s5k6aa_interval *iv = &s5k6aa_intervals[i]; 960 961 if (mbus_fmt->width > iv->size.width || 962 mbus_fmt->height > iv->size.height) 963 continue; 964 965 err = abs(iv->reg_fr_time - fr_time); 966 if (err < min_err) { 967 fiv = iv; 968 min_err = err; 969 } 970 } 971 s5k6aa->fiv = fiv; 972 973 v4l2_dbg(1, debug, &s5k6aa->sd, "Changed frame interval to %d us\n", 974 fiv->reg_fr_time * 100); 975 return 0; 976} 977 978static int s5k6aa_s_frame_interval(struct v4l2_subdev *sd, 979 struct v4l2_subdev_frame_interval *fi) 980{ 981 struct s5k6aa *s5k6aa = to_s5k6aa(sd); 982 int ret; 983 984 v4l2_dbg(1, debug, sd, "Setting %d/%d frame interval\n", 985 fi->interval.numerator, fi->interval.denominator); 986 987 mutex_lock(&s5k6aa->lock); 988 ret = __s5k6aa_set_frame_interval(s5k6aa, fi); 989 s5k6aa->apply_cfg = 1; 990 991 mutex_unlock(&s5k6aa->lock); 992 return ret; 993} 994 995/* 996 * V4L2 subdev pad level and video operations 997 */ 998static int s5k6aa_enum_frame_interval(struct v4l2_subdev *sd, 999 struct v4l2_subdev_pad_config *cfg, 1000 struct v4l2_subdev_frame_interval_enum *fie) 1001{ 1002 struct s5k6aa *s5k6aa = to_s5k6aa(sd); 1003 const struct s5k6aa_interval *fi; 1004 int ret = 0; 1005 1006 if (fie->index >= ARRAY_SIZE(s5k6aa_intervals)) 1007 return -EINVAL; 1008 1009 v4l_bound_align_image(&fie->width, S5K6AA_WIN_WIDTH_MIN, 1010 S5K6AA_WIN_WIDTH_MAX, 1, 1011 &fie->height, S5K6AA_WIN_HEIGHT_MIN, 1012 S5K6AA_WIN_HEIGHT_MAX, 1, 0); 1013 1014 mutex_lock(&s5k6aa->lock); 1015 fi = &s5k6aa_intervals[fie->index]; 1016 if (fie->width > fi->size.width || fie->height > fi->size.height) 1017 ret = -EINVAL; 1018 else 1019 fie->interval = fi->interval; 1020 mutex_unlock(&s5k6aa->lock); 1021 1022 return ret; 1023} 1024 1025static int s5k6aa_enum_mbus_code(struct v4l2_subdev *sd, 1026 struct v4l2_subdev_pad_config *cfg, 1027 struct v4l2_subdev_mbus_code_enum *code) 1028{ 1029 if (code->index >= ARRAY_SIZE(s5k6aa_formats)) 1030 return -EINVAL; 1031 1032 code->code = s5k6aa_formats[code->index].code; 1033 return 0; 1034} 1035 1036static int s5k6aa_enum_frame_size(struct v4l2_subdev *sd, 1037 struct v4l2_subdev_pad_config *cfg, 1038 struct v4l2_subdev_frame_size_enum *fse) 1039{ 1040 int i = ARRAY_SIZE(s5k6aa_formats); 1041 1042 if (fse->index > 0) 1043 return -EINVAL; 1044 1045 while (--i) 1046 if (fse->code == s5k6aa_formats[i].code) 1047 break; 1048 1049 fse->code = s5k6aa_formats[i].code; 1050 fse->min_width = S5K6AA_WIN_WIDTH_MIN; 1051 fse->max_width = S5K6AA_WIN_WIDTH_MAX; 1052 fse->max_height = S5K6AA_WIN_HEIGHT_MIN; 1053 fse->min_height = S5K6AA_WIN_HEIGHT_MAX; 1054 1055 return 0; 1056} 1057 1058static struct v4l2_rect * 1059__s5k6aa_get_crop_rect(struct s5k6aa *s5k6aa, struct v4l2_subdev_pad_config *cfg, 1060 enum v4l2_subdev_format_whence which) 1061{ 1062 if (which == V4L2_SUBDEV_FORMAT_ACTIVE) 1063 return &s5k6aa->ccd_rect; 1064 1065 WARN_ON(which != V4L2_SUBDEV_FORMAT_TRY); 1066 return v4l2_subdev_get_try_crop(&s5k6aa->sd, cfg, 0); 1067} 1068 1069static void s5k6aa_try_format(struct s5k6aa *s5k6aa, 1070 struct v4l2_mbus_framefmt *mf) 1071{ 1072 unsigned int index; 1073 1074 v4l_bound_align_image(&mf->width, S5K6AA_WIN_WIDTH_MIN, 1075 S5K6AA_WIN_WIDTH_MAX, 1, 1076 &mf->height, S5K6AA_WIN_HEIGHT_MIN, 1077 S5K6AA_WIN_HEIGHT_MAX, 1, 0); 1078 1079 if (mf->colorspace != V4L2_COLORSPACE_JPEG && 1080 mf->colorspace != V4L2_COLORSPACE_REC709) 1081 mf->colorspace = V4L2_COLORSPACE_JPEG; 1082 1083 index = s5k6aa_get_pixfmt_index(s5k6aa, mf); 1084 1085 mf->colorspace = s5k6aa_formats[index].colorspace; 1086 mf->code = s5k6aa_formats[index].code; 1087 mf->field = V4L2_FIELD_NONE; 1088} 1089 1090static int s5k6aa_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg, 1091 struct v4l2_subdev_format *fmt) 1092{ 1093 struct s5k6aa *s5k6aa = to_s5k6aa(sd); 1094 struct v4l2_mbus_framefmt *mf; 1095 1096 memset(fmt->reserved, 0, sizeof(fmt->reserved)); 1097 1098 if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { 1099 mf = v4l2_subdev_get_try_format(sd, cfg, 0); 1100 fmt->format = *mf; 1101 return 0; 1102 } 1103 1104 mutex_lock(&s5k6aa->lock); 1105 fmt->format = s5k6aa->preset->mbus_fmt; 1106 mutex_unlock(&s5k6aa->lock); 1107 1108 return 0; 1109} 1110 1111static int s5k6aa_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg, 1112 struct v4l2_subdev_format *fmt) 1113{ 1114 struct s5k6aa *s5k6aa = to_s5k6aa(sd); 1115 struct s5k6aa_preset *preset = s5k6aa->preset; 1116 struct v4l2_mbus_framefmt *mf; 1117 struct v4l2_rect *crop; 1118 int ret = 0; 1119 1120 mutex_lock(&s5k6aa->lock); 1121 s5k6aa_try_format(s5k6aa, &fmt->format); 1122 1123 if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { 1124 mf = v4l2_subdev_get_try_format(sd, cfg, fmt->pad); 1125 crop = v4l2_subdev_get_try_crop(sd, cfg, 0); 1126 } else { 1127 if (s5k6aa->streaming) { 1128 ret = -EBUSY; 1129 } else { 1130 mf = &preset->mbus_fmt; 1131 crop = &s5k6aa->ccd_rect; 1132 s5k6aa->apply_cfg = 1; 1133 } 1134 } 1135 1136 if (ret == 0) { 1137 struct v4l2_subdev_frame_interval fiv = { 1138 .interval = {0, 1} 1139 }; 1140 1141 *mf = fmt->format; 1142 /* 1143 * Make sure the crop window is valid, i.e. its size is 1144 * greater than the output window, as the ISP supports 1145 * only down-scaling. 1146 */ 1147 crop->width = clamp_t(unsigned int, crop->width, mf->width, 1148 S5K6AA_WIN_WIDTH_MAX); 1149 crop->height = clamp_t(unsigned int, crop->height, mf->height, 1150 S5K6AA_WIN_HEIGHT_MAX); 1151 crop->left = clamp_t(unsigned int, crop->left, 0, 1152 S5K6AA_WIN_WIDTH_MAX - crop->width); 1153 crop->top = clamp_t(unsigned int, crop->top, 0, 1154 S5K6AA_WIN_HEIGHT_MAX - crop->height); 1155 1156 /* Reset to minimum possible frame interval */ 1157 ret = __s5k6aa_set_frame_interval(s5k6aa, &fiv); 1158 } 1159 mutex_unlock(&s5k6aa->lock); 1160 1161 return ret; 1162} 1163 1164static int s5k6aa_get_selection(struct v4l2_subdev *sd, 1165 struct v4l2_subdev_pad_config *cfg, 1166 struct v4l2_subdev_selection *sel) 1167{ 1168 struct s5k6aa *s5k6aa = to_s5k6aa(sd); 1169 struct v4l2_rect *rect; 1170 1171 if (sel->target != V4L2_SEL_TGT_CROP) 1172 return -EINVAL; 1173 1174 memset(sel->reserved, 0, sizeof(sel->reserved)); 1175 1176 mutex_lock(&s5k6aa->lock); 1177 rect = __s5k6aa_get_crop_rect(s5k6aa, cfg, sel->which); 1178 sel->r = *rect; 1179 mutex_unlock(&s5k6aa->lock); 1180 1181 v4l2_dbg(1, debug, sd, "Current crop rectangle: (%d,%d)/%dx%d\n", 1182 rect->left, rect->top, rect->width, rect->height); 1183 1184 return 0; 1185} 1186 1187static int s5k6aa_set_selection(struct v4l2_subdev *sd, 1188 struct v4l2_subdev_pad_config *cfg, 1189 struct v4l2_subdev_selection *sel) 1190{ 1191 struct s5k6aa *s5k6aa = to_s5k6aa(sd); 1192 struct v4l2_mbus_framefmt *mf; 1193 unsigned int max_x, max_y; 1194 struct v4l2_rect *crop_r; 1195 1196 if (sel->target != V4L2_SEL_TGT_CROP) 1197 return -EINVAL; 1198 1199 mutex_lock(&s5k6aa->lock); 1200 crop_r = __s5k6aa_get_crop_rect(s5k6aa, cfg, sel->which); 1201 1202 if (sel->which == V4L2_SUBDEV_FORMAT_ACTIVE) { 1203 mf = &s5k6aa->preset->mbus_fmt; 1204 s5k6aa->apply_crop = 1; 1205 } else { 1206 mf = v4l2_subdev_get_try_format(sd, cfg, 0); 1207 } 1208 v4l_bound_align_image(&sel->r.width, mf->width, 1209 S5K6AA_WIN_WIDTH_MAX, 1, 1210 &sel->r.height, mf->height, 1211 S5K6AA_WIN_HEIGHT_MAX, 1, 0); 1212 1213 max_x = (S5K6AA_WIN_WIDTH_MAX - sel->r.width) & ~1; 1214 max_y = (S5K6AA_WIN_HEIGHT_MAX - sel->r.height) & ~1; 1215 1216 sel->r.left = clamp_t(unsigned int, sel->r.left, 0, max_x); 1217 sel->r.top = clamp_t(unsigned int, sel->r.top, 0, max_y); 1218 1219 *crop_r = sel->r; 1220 1221 mutex_unlock(&s5k6aa->lock); 1222 1223 v4l2_dbg(1, debug, sd, "Set crop rectangle: (%d,%d)/%dx%d\n", 1224 crop_r->left, crop_r->top, crop_r->width, crop_r->height); 1225 1226 return 0; 1227} 1228 1229static const struct v4l2_subdev_pad_ops s5k6aa_pad_ops = { 1230 .enum_mbus_code = s5k6aa_enum_mbus_code, 1231 .enum_frame_size = s5k6aa_enum_frame_size, 1232 .enum_frame_interval = s5k6aa_enum_frame_interval, 1233 .get_fmt = s5k6aa_get_fmt, 1234 .set_fmt = s5k6aa_set_fmt, 1235 .get_selection = s5k6aa_get_selection, 1236 .set_selection = s5k6aa_set_selection, 1237}; 1238 1239static const struct v4l2_subdev_video_ops s5k6aa_video_ops = { 1240 .g_frame_interval = s5k6aa_g_frame_interval, 1241 .s_frame_interval = s5k6aa_s_frame_interval, 1242 .s_stream = s5k6aa_s_stream, 1243}; 1244 1245/* 1246 * V4L2 subdev controls 1247 */ 1248 1249static int s5k6aa_s_ctrl(struct v4l2_ctrl *ctrl) 1250{ 1251 struct v4l2_subdev *sd = ctrl_to_sd(ctrl); 1252 struct i2c_client *client = v4l2_get_subdevdata(sd); 1253 struct s5k6aa *s5k6aa = to_s5k6aa(sd); 1254 int idx, err = 0; 1255 1256 v4l2_dbg(1, debug, sd, "ctrl: 0x%x, value: %d\n", ctrl->id, ctrl->val); 1257 1258 mutex_lock(&s5k6aa->lock); 1259 /* 1260 * If the device is not powered up by the host driver do 1261 * not apply any controls to H/W at this time. Instead 1262 * the controls will be restored right after power-up. 1263 */ 1264 if (s5k6aa->power == 0) 1265 goto unlock; 1266 idx = s5k6aa->preset->index; 1267 1268 switch (ctrl->id) { 1269 case V4L2_CID_AUTO_WHITE_BALANCE: 1270 err = s5k6aa_set_awb(s5k6aa, ctrl->val); 1271 break; 1272 1273 case V4L2_CID_BRIGHTNESS: 1274 err = s5k6aa_write(client, REG_USER_BRIGHTNESS, ctrl->val); 1275 break; 1276 1277 case V4L2_CID_COLORFX: 1278 err = s5k6aa_set_colorfx(s5k6aa, ctrl->val); 1279 break; 1280 1281 case V4L2_CID_CONTRAST: 1282 err = s5k6aa_write(client, REG_USER_CONTRAST, ctrl->val); 1283 break; 1284 1285 case V4L2_CID_EXPOSURE_AUTO: 1286 err = s5k6aa_set_auto_exposure(s5k6aa, ctrl->val); 1287 break; 1288 1289 case V4L2_CID_HFLIP: 1290 err = s5k6aa_set_mirror(s5k6aa, ctrl->val); 1291 if (err) 1292 break; 1293 err = s5k6aa_write(client, REG_G_PREV_CFG_CHG, 1); 1294 break; 1295 1296 case V4L2_CID_POWER_LINE_FREQUENCY: 1297 err = s5k6aa_set_anti_flicker(s5k6aa, ctrl->val); 1298 break; 1299 1300 case V4L2_CID_SATURATION: 1301 err = s5k6aa_write(client, REG_USER_SATURATION, ctrl->val); 1302 break; 1303 1304 case V4L2_CID_SHARPNESS: 1305 err = s5k6aa_write(client, REG_USER_SHARPBLUR, ctrl->val); 1306 break; 1307 1308 case V4L2_CID_WHITE_BALANCE_TEMPERATURE: 1309 err = s5k6aa_write(client, REG_P_COLORTEMP(idx), ctrl->val); 1310 if (err) 1311 break; 1312 err = s5k6aa_write(client, REG_G_PREV_CFG_CHG, 1); 1313 break; 1314 } 1315unlock: 1316 mutex_unlock(&s5k6aa->lock); 1317 return err; 1318} 1319 1320static const struct v4l2_ctrl_ops s5k6aa_ctrl_ops = { 1321 .s_ctrl = s5k6aa_s_ctrl, 1322}; 1323 1324static int s5k6aa_log_status(struct v4l2_subdev *sd) 1325{ 1326 v4l2_ctrl_handler_log_status(sd->ctrl_handler, sd->name); 1327 return 0; 1328} 1329 1330#define V4L2_CID_RED_GAIN (V4L2_CTRL_CLASS_CAMERA | 0x1001) 1331#define V4L2_CID_GREEN_GAIN (V4L2_CTRL_CLASS_CAMERA | 0x1002) 1332#define V4L2_CID_BLUE_GAIN (V4L2_CTRL_CLASS_CAMERA | 0x1003) 1333 1334static const struct v4l2_ctrl_config s5k6aa_ctrls[] = { 1335 { 1336 .ops = &s5k6aa_ctrl_ops, 1337 .id = V4L2_CID_RED_GAIN, 1338 .type = V4L2_CTRL_TYPE_INTEGER, 1339 .name = "Gain, Red", 1340 .min = 0, 1341 .max = 256, 1342 .def = 127, 1343 .step = 1, 1344 }, { 1345 .ops = &s5k6aa_ctrl_ops, 1346 .id = V4L2_CID_GREEN_GAIN, 1347 .type = V4L2_CTRL_TYPE_INTEGER, 1348 .name = "Gain, Green", 1349 .min = 0, 1350 .max = 256, 1351 .def = 127, 1352 .step = 1, 1353 }, { 1354 .ops = &s5k6aa_ctrl_ops, 1355 .id = V4L2_CID_BLUE_GAIN, 1356 .type = V4L2_CTRL_TYPE_INTEGER, 1357 .name = "Gain, Blue", 1358 .min = 0, 1359 .max = 256, 1360 .def = 127, 1361 .step = 1, 1362 }, 1363}; 1364 1365static int s5k6aa_initialize_ctrls(struct s5k6aa *s5k6aa) 1366{ 1367 const struct v4l2_ctrl_ops *ops = &s5k6aa_ctrl_ops; 1368 struct s5k6aa_ctrls *ctrls = &s5k6aa->ctrls; 1369 struct v4l2_ctrl_handler *hdl = &ctrls->handler; 1370 1371 int ret = v4l2_ctrl_handler_init(hdl, 16); 1372 if (ret) 1373 return ret; 1374 /* Auto white balance cluster */ 1375 ctrls->awb = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_AUTO_WHITE_BALANCE, 1376 0, 1, 1, 1); 1377 ctrls->gain_red = v4l2_ctrl_new_custom(hdl, &s5k6aa_ctrls[0], NULL); 1378 ctrls->gain_green = v4l2_ctrl_new_custom(hdl, &s5k6aa_ctrls[1], NULL); 1379 ctrls->gain_blue = v4l2_ctrl_new_custom(hdl, &s5k6aa_ctrls[2], NULL); 1380 v4l2_ctrl_auto_cluster(4, &ctrls->awb, 0, false); 1381 1382 ctrls->hflip = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_HFLIP, 0, 1, 1, 0); 1383 ctrls->vflip = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_VFLIP, 0, 1, 1, 0); 1384 v4l2_ctrl_cluster(2, &ctrls->hflip); 1385 1386 ctrls->auto_exp = v4l2_ctrl_new_std_menu(hdl, ops, 1387 V4L2_CID_EXPOSURE_AUTO, 1388 V4L2_EXPOSURE_MANUAL, 0, V4L2_EXPOSURE_AUTO); 1389 /* Exposure time: x 1 us */ 1390 ctrls->exposure = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_EXPOSURE, 1391 0, 6000000U, 1, 100000U); 1392 /* Total gain: 256 <=> 1x */ 1393 ctrls->gain = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_GAIN, 1394 0, 256, 1, 256); 1395 v4l2_ctrl_auto_cluster(3, &ctrls->auto_exp, 0, false); 1396 1397 v4l2_ctrl_new_std_menu(hdl, ops, V4L2_CID_POWER_LINE_FREQUENCY, 1398 V4L2_CID_POWER_LINE_FREQUENCY_AUTO, 0, 1399 V4L2_CID_POWER_LINE_FREQUENCY_AUTO); 1400 1401 v4l2_ctrl_new_std_menu(hdl, ops, V4L2_CID_COLORFX, 1402 V4L2_COLORFX_SKY_BLUE, ~0x6f, V4L2_COLORFX_NONE); 1403 1404 v4l2_ctrl_new_std(hdl, ops, V4L2_CID_WHITE_BALANCE_TEMPERATURE, 1405 0, 256, 1, 0); 1406 1407 v4l2_ctrl_new_std(hdl, ops, V4L2_CID_SATURATION, -127, 127, 1, 0); 1408 v4l2_ctrl_new_std(hdl, ops, V4L2_CID_BRIGHTNESS, -127, 127, 1, 0); 1409 v4l2_ctrl_new_std(hdl, ops, V4L2_CID_CONTRAST, -127, 127, 1, 0); 1410 v4l2_ctrl_new_std(hdl, ops, V4L2_CID_SHARPNESS, -127, 127, 1, 0); 1411 1412 if (hdl->error) { 1413 ret = hdl->error; 1414 v4l2_ctrl_handler_free(hdl); 1415 return ret; 1416 } 1417 1418 s5k6aa->sd.ctrl_handler = hdl; 1419 return 0; 1420} 1421 1422/* 1423 * V4L2 subdev internal operations 1424 */ 1425static int s5k6aa_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) 1426{ 1427 struct v4l2_mbus_framefmt *format = v4l2_subdev_get_try_format(sd, fh->pad, 0); 1428 struct v4l2_rect *crop = v4l2_subdev_get_try_crop(sd, fh->pad, 0); 1429 1430 format->colorspace = s5k6aa_formats[0].colorspace; 1431 format->code = s5k6aa_formats[0].code; 1432 format->width = S5K6AA_OUT_WIDTH_DEF; 1433 format->height = S5K6AA_OUT_HEIGHT_DEF; 1434 format->field = V4L2_FIELD_NONE; 1435 1436 crop->width = S5K6AA_WIN_WIDTH_MAX; 1437 crop->height = S5K6AA_WIN_HEIGHT_MAX; 1438 crop->left = 0; 1439 crop->top = 0; 1440 1441 return 0; 1442} 1443 1444static int s5k6aa_check_fw_revision(struct s5k6aa *s5k6aa) 1445{ 1446 struct i2c_client *client = v4l2_get_subdevdata(&s5k6aa->sd); 1447 u16 api_ver = 0, fw_rev = 0; 1448 1449 int ret = s5k6aa_set_ahb_address(client); 1450 1451 if (!ret) 1452 ret = s5k6aa_read(client, REG_FW_APIVER, &api_ver); 1453 if (!ret) 1454 ret = s5k6aa_read(client, REG_FW_REVISION, &fw_rev); 1455 if (ret) { 1456 v4l2_err(&s5k6aa->sd, "FW revision check failed!\n"); 1457 return ret; 1458 } 1459 1460 v4l2_info(&s5k6aa->sd, "FW API ver.: 0x%X, FW rev.: 0x%X\n", 1461 api_ver, fw_rev); 1462 1463 return api_ver == S5K6AAFX_FW_APIVER ? 0 : -ENODEV; 1464} 1465 1466static int s5k6aa_registered(struct v4l2_subdev *sd) 1467{ 1468 struct s5k6aa *s5k6aa = to_s5k6aa(sd); 1469 int ret; 1470 1471 mutex_lock(&s5k6aa->lock); 1472 ret = __s5k6aa_power_on(s5k6aa); 1473 if (!ret) { 1474 msleep(100); 1475 ret = s5k6aa_check_fw_revision(s5k6aa); 1476 __s5k6aa_power_off(s5k6aa); 1477 } 1478 mutex_unlock(&s5k6aa->lock); 1479 1480 return ret; 1481} 1482 1483static const struct v4l2_subdev_internal_ops s5k6aa_subdev_internal_ops = { 1484 .registered = s5k6aa_registered, 1485 .open = s5k6aa_open, 1486}; 1487 1488static const struct v4l2_subdev_core_ops s5k6aa_core_ops = { 1489 .s_power = s5k6aa_set_power, 1490 .log_status = s5k6aa_log_status, 1491}; 1492 1493static const struct v4l2_subdev_ops s5k6aa_subdev_ops = { 1494 .core = &s5k6aa_core_ops, 1495 .pad = &s5k6aa_pad_ops, 1496 .video = &s5k6aa_video_ops, 1497}; 1498 1499/* 1500 * GPIO setup 1501 */ 1502 1503static int s5k6aa_configure_gpios(struct s5k6aa *s5k6aa, 1504 const struct s5k6aa_platform_data *pdata) 1505{ 1506 struct i2c_client *client = v4l2_get_subdevdata(&s5k6aa->sd); 1507 const struct s5k6aa_gpio *gpio; 1508 unsigned long flags; 1509 int ret; 1510 1511 s5k6aa->gpio[STBY].gpio = -EINVAL; 1512 s5k6aa->gpio[RST].gpio = -EINVAL; 1513 1514 gpio = &pdata->gpio_stby; 1515 if (gpio_is_valid(gpio->gpio)) { 1516 flags = (gpio->level ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW) 1517 | GPIOF_EXPORT; 1518 ret = devm_gpio_request_one(&client->dev, gpio->gpio, flags, 1519 "S5K6AA_STBY"); 1520 if (ret < 0) 1521 return ret; 1522 1523 s5k6aa->gpio[STBY] = *gpio; 1524 } 1525 1526 gpio = &pdata->gpio_reset; 1527 if (gpio_is_valid(gpio->gpio)) { 1528 flags = (gpio->level ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW) 1529 | GPIOF_EXPORT; 1530 ret = devm_gpio_request_one(&client->dev, gpio->gpio, flags, 1531 "S5K6AA_RST"); 1532 if (ret < 0) 1533 return ret; 1534 1535 s5k6aa->gpio[RST] = *gpio; 1536 } 1537 1538 return 0; 1539} 1540 1541static int s5k6aa_probe(struct i2c_client *client, 1542 const struct i2c_device_id *id) 1543{ 1544 const struct s5k6aa_platform_data *pdata = client->dev.platform_data; 1545 struct v4l2_subdev *sd; 1546 struct s5k6aa *s5k6aa; 1547 int i, ret; 1548 1549 if (pdata == NULL) { 1550 dev_err(&client->dev, "Platform data not specified\n"); 1551 return -EINVAL; 1552 } 1553 1554 if (pdata->mclk_frequency == 0) { 1555 dev_err(&client->dev, "MCLK frequency not specified\n"); 1556 return -EINVAL; 1557 } 1558 1559 s5k6aa = devm_kzalloc(&client->dev, sizeof(*s5k6aa), GFP_KERNEL); 1560 if (!s5k6aa) 1561 return -ENOMEM; 1562 1563 mutex_init(&s5k6aa->lock); 1564 1565 s5k6aa->mclk_frequency = pdata->mclk_frequency; 1566 s5k6aa->bus_type = pdata->bus_type; 1567 s5k6aa->mipi_lanes = pdata->nlanes; 1568 s5k6aa->s_power = pdata->set_power; 1569 s5k6aa->inv_hflip = pdata->horiz_flip; 1570 s5k6aa->inv_vflip = pdata->vert_flip; 1571 1572 sd = &s5k6aa->sd; 1573 v4l2_i2c_subdev_init(sd, client, &s5k6aa_subdev_ops); 1574 strlcpy(sd->name, DRIVER_NAME, sizeof(sd->name)); 1575 1576 sd->internal_ops = &s5k6aa_subdev_internal_ops; 1577 sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; 1578 1579 s5k6aa->pad.flags = MEDIA_PAD_FL_SOURCE; 1580 sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV_SENSOR; 1581 ret = media_entity_init(&sd->entity, 1, &s5k6aa->pad, 0); 1582 if (ret) 1583 return ret; 1584 1585 ret = s5k6aa_configure_gpios(s5k6aa, pdata); 1586 if (ret) 1587 goto out_err; 1588 1589 for (i = 0; i < S5K6AA_NUM_SUPPLIES; i++) 1590 s5k6aa->supplies[i].supply = s5k6aa_supply_names[i]; 1591 1592 ret = devm_regulator_bulk_get(&client->dev, S5K6AA_NUM_SUPPLIES, 1593 s5k6aa->supplies); 1594 if (ret) { 1595 dev_err(&client->dev, "Failed to get regulators\n"); 1596 goto out_err; 1597 } 1598 1599 ret = s5k6aa_initialize_ctrls(s5k6aa); 1600 if (ret) 1601 goto out_err; 1602 1603 s5k6aa_presets_data_init(s5k6aa); 1604 1605 s5k6aa->ccd_rect.width = S5K6AA_WIN_WIDTH_MAX; 1606 s5k6aa->ccd_rect.height = S5K6AA_WIN_HEIGHT_MAX; 1607 s5k6aa->ccd_rect.left = 0; 1608 s5k6aa->ccd_rect.top = 0; 1609 1610 return 0; 1611 1612out_err: 1613 media_entity_cleanup(&s5k6aa->sd.entity); 1614 return ret; 1615} 1616 1617static int s5k6aa_remove(struct i2c_client *client) 1618{ 1619 struct v4l2_subdev *sd = i2c_get_clientdata(client); 1620 1621 v4l2_device_unregister_subdev(sd); 1622 v4l2_ctrl_handler_free(sd->ctrl_handler); 1623 media_entity_cleanup(&sd->entity); 1624 1625 return 0; 1626} 1627 1628static const struct i2c_device_id s5k6aa_id[] = { 1629 { DRIVER_NAME, 0 }, 1630 { }, 1631}; 1632MODULE_DEVICE_TABLE(i2c, s5k6aa_id); 1633 1634 1635static struct i2c_driver s5k6aa_i2c_driver = { 1636 .driver = { 1637 .name = DRIVER_NAME 1638 }, 1639 .probe = s5k6aa_probe, 1640 .remove = s5k6aa_remove, 1641 .id_table = s5k6aa_id, 1642}; 1643 1644module_i2c_driver(s5k6aa_i2c_driver); 1645 1646MODULE_DESCRIPTION("Samsung S5K6AA(FX) SXGA camera driver"); 1647MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>"); 1648MODULE_LICENSE("GPL"); 1649