1/* 2 * Driver for IMX074 CMOS Image Sensor from Sony 3 * 4 * Copyright (C) 2010, Guennadi Liakhovetski <g.liakhovetski@gmx.de> 5 * 6 * Partially inspired by the IMX074 driver from the Android / MSM tree 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License version 2 as 10 * published by the Free Software Foundation. 11 */ 12 13#include <linux/delay.h> 14#include <linux/i2c.h> 15#include <linux/v4l2-mediabus.h> 16#include <linux/slab.h> 17#include <linux/videodev2.h> 18#include <linux/module.h> 19 20#include <media/soc_camera.h> 21#include <media/v4l2-async.h> 22#include <media/v4l2-clk.h> 23#include <media/v4l2-subdev.h> 24 25/* IMX074 registers */ 26 27#define MODE_SELECT 0x0100 28#define IMAGE_ORIENTATION 0x0101 29#define GROUPED_PARAMETER_HOLD 0x0104 30 31/* Integration Time */ 32#define COARSE_INTEGRATION_TIME_HI 0x0202 33#define COARSE_INTEGRATION_TIME_LO 0x0203 34/* Gain */ 35#define ANALOGUE_GAIN_CODE_GLOBAL_HI 0x0204 36#define ANALOGUE_GAIN_CODE_GLOBAL_LO 0x0205 37 38/* PLL registers */ 39#define PRE_PLL_CLK_DIV 0x0305 40#define PLL_MULTIPLIER 0x0307 41#define PLSTATIM 0x302b 42#define VNDMY_ABLMGSHLMT 0x300a 43#define Y_OPBADDR_START_DI 0x3014 44/* mode setting */ 45#define FRAME_LENGTH_LINES_HI 0x0340 46#define FRAME_LENGTH_LINES_LO 0x0341 47#define LINE_LENGTH_PCK_HI 0x0342 48#define LINE_LENGTH_PCK_LO 0x0343 49#define YADDR_START 0x0347 50#define YADDR_END 0x034b 51#define X_OUTPUT_SIZE_MSB 0x034c 52#define X_OUTPUT_SIZE_LSB 0x034d 53#define Y_OUTPUT_SIZE_MSB 0x034e 54#define Y_OUTPUT_SIZE_LSB 0x034f 55#define X_EVEN_INC 0x0381 56#define X_ODD_INC 0x0383 57#define Y_EVEN_INC 0x0385 58#define Y_ODD_INC 0x0387 59 60#define HMODEADD 0x3001 61#define VMODEADD 0x3016 62#define VAPPLINE_START 0x3069 63#define VAPPLINE_END 0x306b 64#define SHUTTER 0x3086 65#define HADDAVE 0x30e8 66#define LANESEL 0x3301 67 68/* IMX074 supported geometry */ 69#define IMX074_WIDTH 1052 70#define IMX074_HEIGHT 780 71 72/* IMX074 has only one fixed colorspace per pixelcode */ 73struct imx074_datafmt { 74 u32 code; 75 enum v4l2_colorspace colorspace; 76}; 77 78struct imx074 { 79 struct v4l2_subdev subdev; 80 const struct imx074_datafmt *fmt; 81 struct v4l2_clk *clk; 82}; 83 84static const struct imx074_datafmt imx074_colour_fmts[] = { 85 {MEDIA_BUS_FMT_SBGGR8_1X8, V4L2_COLORSPACE_SRGB}, 86}; 87 88static struct imx074 *to_imx074(const struct i2c_client *client) 89{ 90 return container_of(i2c_get_clientdata(client), struct imx074, subdev); 91} 92 93/* Find a data format by a pixel code in an array */ 94static const struct imx074_datafmt *imx074_find_datafmt(u32 code) 95{ 96 int i; 97 98 for (i = 0; i < ARRAY_SIZE(imx074_colour_fmts); i++) 99 if (imx074_colour_fmts[i].code == code) 100 return imx074_colour_fmts + i; 101 102 return NULL; 103} 104 105static int reg_write(struct i2c_client *client, const u16 addr, const u8 data) 106{ 107 struct i2c_adapter *adap = client->adapter; 108 struct i2c_msg msg; 109 unsigned char tx[3]; 110 int ret; 111 112 msg.addr = client->addr; 113 msg.buf = tx; 114 msg.len = 3; 115 msg.flags = 0; 116 117 tx[0] = addr >> 8; 118 tx[1] = addr & 0xff; 119 tx[2] = data; 120 121 ret = i2c_transfer(adap, &msg, 1); 122 123 mdelay(2); 124 125 return ret == 1 ? 0 : -EIO; 126} 127 128static int reg_read(struct i2c_client *client, const u16 addr) 129{ 130 u8 buf[2] = {addr >> 8, addr & 0xff}; 131 int ret; 132 struct i2c_msg msgs[] = { 133 { 134 .addr = client->addr, 135 .flags = 0, 136 .len = 2, 137 .buf = buf, 138 }, { 139 .addr = client->addr, 140 .flags = I2C_M_RD, 141 .len = 2, 142 .buf = buf, 143 }, 144 }; 145 146 ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); 147 if (ret < 0) { 148 dev_warn(&client->dev, "Reading register %x from %x failed\n", 149 addr, client->addr); 150 return ret; 151 } 152 153 return buf[0] & 0xff; /* no sign-extension */ 154} 155 156static int imx074_set_fmt(struct v4l2_subdev *sd, 157 struct v4l2_subdev_pad_config *cfg, 158 struct v4l2_subdev_format *format) 159{ 160 struct v4l2_mbus_framefmt *mf = &format->format; 161 const struct imx074_datafmt *fmt = imx074_find_datafmt(mf->code); 162 struct i2c_client *client = v4l2_get_subdevdata(sd); 163 struct imx074 *priv = to_imx074(client); 164 165 if (format->pad) 166 return -EINVAL; 167 168 dev_dbg(sd->v4l2_dev->dev, "%s(%u)\n", __func__, mf->code); 169 170 if (!fmt) { 171 /* MIPI CSI could have changed the format, double-check */ 172 if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE) 173 return -EINVAL; 174 mf->code = imx074_colour_fmts[0].code; 175 mf->colorspace = imx074_colour_fmts[0].colorspace; 176 } 177 178 mf->width = IMX074_WIDTH; 179 mf->height = IMX074_HEIGHT; 180 mf->field = V4L2_FIELD_NONE; 181 182 if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE) 183 priv->fmt = imx074_find_datafmt(mf->code); 184 else 185 cfg->try_fmt = *mf; 186 187 return 0; 188} 189 190static int imx074_get_fmt(struct v4l2_subdev *sd, 191 struct v4l2_subdev_pad_config *cfg, 192 struct v4l2_subdev_format *format) 193{ 194 struct v4l2_mbus_framefmt *mf = &format->format; 195 struct i2c_client *client = v4l2_get_subdevdata(sd); 196 struct imx074 *priv = to_imx074(client); 197 198 const struct imx074_datafmt *fmt = priv->fmt; 199 200 if (format->pad) 201 return -EINVAL; 202 203 mf->code = fmt->code; 204 mf->colorspace = fmt->colorspace; 205 mf->width = IMX074_WIDTH; 206 mf->height = IMX074_HEIGHT; 207 mf->field = V4L2_FIELD_NONE; 208 209 return 0; 210} 211 212static int imx074_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) 213{ 214 struct v4l2_rect *rect = &a->c; 215 216 a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 217 rect->top = 0; 218 rect->left = 0; 219 rect->width = IMX074_WIDTH; 220 rect->height = IMX074_HEIGHT; 221 222 return 0; 223} 224 225static int imx074_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) 226{ 227 a->bounds.left = 0; 228 a->bounds.top = 0; 229 a->bounds.width = IMX074_WIDTH; 230 a->bounds.height = IMX074_HEIGHT; 231 a->defrect = a->bounds; 232 a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 233 a->pixelaspect.numerator = 1; 234 a->pixelaspect.denominator = 1; 235 236 return 0; 237} 238 239static int imx074_enum_mbus_code(struct v4l2_subdev *sd, 240 struct v4l2_subdev_pad_config *cfg, 241 struct v4l2_subdev_mbus_code_enum *code) 242{ 243 if (code->pad || 244 (unsigned int)code->index >= ARRAY_SIZE(imx074_colour_fmts)) 245 return -EINVAL; 246 247 code->code = imx074_colour_fmts[code->index].code; 248 return 0; 249} 250 251static int imx074_s_stream(struct v4l2_subdev *sd, int enable) 252{ 253 struct i2c_client *client = v4l2_get_subdevdata(sd); 254 255 /* MODE_SELECT: stream or standby */ 256 return reg_write(client, MODE_SELECT, !!enable); 257} 258 259static int imx074_s_power(struct v4l2_subdev *sd, int on) 260{ 261 struct i2c_client *client = v4l2_get_subdevdata(sd); 262 struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); 263 struct imx074 *priv = to_imx074(client); 264 265 return soc_camera_set_power(&client->dev, ssdd, priv->clk, on); 266} 267 268static int imx074_g_mbus_config(struct v4l2_subdev *sd, 269 struct v4l2_mbus_config *cfg) 270{ 271 cfg->type = V4L2_MBUS_CSI2; 272 cfg->flags = V4L2_MBUS_CSI2_2_LANE | 273 V4L2_MBUS_CSI2_CHANNEL_0 | 274 V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; 275 276 return 0; 277} 278 279static struct v4l2_subdev_video_ops imx074_subdev_video_ops = { 280 .s_stream = imx074_s_stream, 281 .g_crop = imx074_g_crop, 282 .cropcap = imx074_cropcap, 283 .g_mbus_config = imx074_g_mbus_config, 284}; 285 286static struct v4l2_subdev_core_ops imx074_subdev_core_ops = { 287 .s_power = imx074_s_power, 288}; 289 290static const struct v4l2_subdev_pad_ops imx074_subdev_pad_ops = { 291 .enum_mbus_code = imx074_enum_mbus_code, 292 .get_fmt = imx074_get_fmt, 293 .set_fmt = imx074_set_fmt, 294}; 295 296static struct v4l2_subdev_ops imx074_subdev_ops = { 297 .core = &imx074_subdev_core_ops, 298 .video = &imx074_subdev_video_ops, 299 .pad = &imx074_subdev_pad_ops, 300}; 301 302static int imx074_video_probe(struct i2c_client *client) 303{ 304 struct v4l2_subdev *subdev = i2c_get_clientdata(client); 305 int ret; 306 u16 id; 307 308 ret = imx074_s_power(subdev, 1); 309 if (ret < 0) 310 return ret; 311 312 /* Read sensor Model ID */ 313 ret = reg_read(client, 0); 314 if (ret < 0) 315 goto done; 316 317 id = ret << 8; 318 319 ret = reg_read(client, 1); 320 if (ret < 0) 321 goto done; 322 323 id |= ret; 324 325 dev_info(&client->dev, "Chip ID 0x%04x detected\n", id); 326 327 if (id != 0x74) { 328 ret = -ENODEV; 329 goto done; 330 } 331 332 /* PLL Setting EXTCLK=24MHz, 22.5times */ 333 reg_write(client, PLL_MULTIPLIER, 0x2D); 334 reg_write(client, PRE_PLL_CLK_DIV, 0x02); 335 reg_write(client, PLSTATIM, 0x4B); 336 337 /* 2-lane mode */ 338 reg_write(client, 0x3024, 0x00); 339 340 reg_write(client, IMAGE_ORIENTATION, 0x00); 341 342 /* select RAW mode: 343 * 0x08+0x08 = top 8 bits 344 * 0x0a+0x08 = compressed 8-bits 345 * 0x0a+0x0a = 10 bits 346 */ 347 reg_write(client, 0x0112, 0x08); 348 reg_write(client, 0x0113, 0x08); 349 350 /* Base setting for High frame mode */ 351 reg_write(client, VNDMY_ABLMGSHLMT, 0x80); 352 reg_write(client, Y_OPBADDR_START_DI, 0x08); 353 reg_write(client, 0x3015, 0x37); 354 reg_write(client, 0x301C, 0x01); 355 reg_write(client, 0x302C, 0x05); 356 reg_write(client, 0x3031, 0x26); 357 reg_write(client, 0x3041, 0x60); 358 reg_write(client, 0x3051, 0x24); 359 reg_write(client, 0x3053, 0x34); 360 reg_write(client, 0x3057, 0xC0); 361 reg_write(client, 0x305C, 0x09); 362 reg_write(client, 0x305D, 0x07); 363 reg_write(client, 0x3060, 0x30); 364 reg_write(client, 0x3065, 0x00); 365 reg_write(client, 0x30AA, 0x08); 366 reg_write(client, 0x30AB, 0x1C); 367 reg_write(client, 0x30B0, 0x32); 368 reg_write(client, 0x30B2, 0x83); 369 reg_write(client, 0x30D3, 0x04); 370 reg_write(client, 0x3106, 0x78); 371 reg_write(client, 0x310C, 0x82); 372 reg_write(client, 0x3304, 0x05); 373 reg_write(client, 0x3305, 0x04); 374 reg_write(client, 0x3306, 0x11); 375 reg_write(client, 0x3307, 0x02); 376 reg_write(client, 0x3308, 0x0C); 377 reg_write(client, 0x3309, 0x06); 378 reg_write(client, 0x330A, 0x08); 379 reg_write(client, 0x330B, 0x04); 380 reg_write(client, 0x330C, 0x08); 381 reg_write(client, 0x330D, 0x06); 382 reg_write(client, 0x330E, 0x01); 383 reg_write(client, 0x3381, 0x00); 384 385 /* V : 1/2V-addition (1,3), H : 1/2H-averaging (1,3) -> Full HD */ 386 /* 1608 = 1560 + 48 (black lines) */ 387 reg_write(client, FRAME_LENGTH_LINES_HI, 0x06); 388 reg_write(client, FRAME_LENGTH_LINES_LO, 0x48); 389 reg_write(client, YADDR_START, 0x00); 390 reg_write(client, YADDR_END, 0x2F); 391 /* 0x838 == 2104 */ 392 reg_write(client, X_OUTPUT_SIZE_MSB, 0x08); 393 reg_write(client, X_OUTPUT_SIZE_LSB, 0x38); 394 /* 0x618 == 1560 */ 395 reg_write(client, Y_OUTPUT_SIZE_MSB, 0x06); 396 reg_write(client, Y_OUTPUT_SIZE_LSB, 0x18); 397 reg_write(client, X_EVEN_INC, 0x01); 398 reg_write(client, X_ODD_INC, 0x03); 399 reg_write(client, Y_EVEN_INC, 0x01); 400 reg_write(client, Y_ODD_INC, 0x03); 401 reg_write(client, HMODEADD, 0x00); 402 reg_write(client, VMODEADD, 0x16); 403 reg_write(client, VAPPLINE_START, 0x24); 404 reg_write(client, VAPPLINE_END, 0x53); 405 reg_write(client, SHUTTER, 0x00); 406 reg_write(client, HADDAVE, 0x80); 407 408 reg_write(client, LANESEL, 0x00); 409 410 reg_write(client, GROUPED_PARAMETER_HOLD, 0x00); /* off */ 411 412 ret = 0; 413 414done: 415 imx074_s_power(subdev, 0); 416 return ret; 417} 418 419static int imx074_probe(struct i2c_client *client, 420 const struct i2c_device_id *did) 421{ 422 struct imx074 *priv; 423 struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); 424 struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); 425 int ret; 426 427 if (!ssdd) { 428 dev_err(&client->dev, "IMX074: missing platform data!\n"); 429 return -EINVAL; 430 } 431 432 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { 433 dev_warn(&adapter->dev, 434 "I2C-Adapter doesn't support I2C_FUNC_SMBUS_BYTE\n"); 435 return -EIO; 436 } 437 438 priv = devm_kzalloc(&client->dev, sizeof(struct imx074), GFP_KERNEL); 439 if (!priv) 440 return -ENOMEM; 441 442 v4l2_i2c_subdev_init(&priv->subdev, client, &imx074_subdev_ops); 443 444 priv->fmt = &imx074_colour_fmts[0]; 445 446 priv->clk = v4l2_clk_get(&client->dev, "mclk"); 447 if (IS_ERR(priv->clk)) { 448 dev_info(&client->dev, "Error %ld getting clock\n", PTR_ERR(priv->clk)); 449 return -EPROBE_DEFER; 450 } 451 452 ret = soc_camera_power_init(&client->dev, ssdd); 453 if (ret < 0) 454 goto epwrinit; 455 456 ret = imx074_video_probe(client); 457 if (ret < 0) 458 goto eprobe; 459 460 ret = v4l2_async_register_subdev(&priv->subdev); 461 if (!ret) 462 return 0; 463 464epwrinit: 465eprobe: 466 v4l2_clk_put(priv->clk); 467 return ret; 468} 469 470static int imx074_remove(struct i2c_client *client) 471{ 472 struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); 473 struct imx074 *priv = to_imx074(client); 474 475 v4l2_async_unregister_subdev(&priv->subdev); 476 v4l2_clk_put(priv->clk); 477 478 if (ssdd->free_bus) 479 ssdd->free_bus(ssdd); 480 481 return 0; 482} 483 484static const struct i2c_device_id imx074_id[] = { 485 { "imx074", 0 }, 486 { } 487}; 488MODULE_DEVICE_TABLE(i2c, imx074_id); 489 490static struct i2c_driver imx074_i2c_driver = { 491 .driver = { 492 .name = "imx074", 493 }, 494 .probe = imx074_probe, 495 .remove = imx074_remove, 496 .id_table = imx074_id, 497}; 498 499module_i2c_driver(imx074_i2c_driver); 500 501MODULE_DESCRIPTION("Sony IMX074 Camera driver"); 502MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>"); 503MODULE_LICENSE("GPL v2"); 504