Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[media] v4l: Add driver for Micron MT9M032 camera sensor

The MT9M032 is a parallel 1.6MP sensor from Micron controlled through I2C.

The driver creates a V4L2 subdevice. It currently supports cropping, gain,
exposure and v/h flipping controls in monochrome mode with an
external pixel clock.

[Lots of clean up, fixes and enhancements]

Signed-off-by: Martin Hostettler <martin@neutronstar.dyndns.org>
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Acked-by: Sakari Ailus <sakari.ailus@iki.fi>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>

authored by

Martin Hostettler and committed by
Mauro Carvalho Chehab
251cb88e 08cd43cc

+913
+8
drivers/media/video/Kconfig
··· 490 490 To compile this driver as a module, choose M here: the 491 491 module will be called vs6624. 492 492 493 + config VIDEO_MT9M032 494 + tristate "MT9M032 camera sensor support" 495 + depends on I2C && VIDEO_V4L2 496 + select VIDEO_APTINA_PLL 497 + ---help--- 498 + This driver supports MT9M032 camera sensors from Aptina, monochrome 499 + models only. 500 + 493 501 config VIDEO_MT9P031 494 502 tristate "Aptina MT9P031 support" 495 503 depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
+1
drivers/media/video/Makefile
··· 70 70 obj-$(CONFIG_VIDEO_OV7670) += ov7670.o 71 71 obj-$(CONFIG_VIDEO_TCM825X) += tcm825x.o 72 72 obj-$(CONFIG_VIDEO_TVEEPROM) += tveeprom.o 73 + obj-$(CONFIG_VIDEO_MT9M032) += mt9m032.o 73 74 obj-$(CONFIG_VIDEO_MT9P031) += mt9p031.o 74 75 obj-$(CONFIG_VIDEO_MT9T001) += mt9t001.o 75 76 obj-$(CONFIG_VIDEO_MT9V011) += mt9v011.o
+868
drivers/media/video/mt9m032.c
··· 1 + /* 2 + * Driver for MT9M032 CMOS Image Sensor from Micron 3 + * 4 + * Copyright (C) 2010-2011 Lund Engineering 5 + * Contact: Gil Lund <gwlund@lundeng.com> 6 + * Author: Martin Hostettler <martin@neutronstar.dyndns.org> 7 + * 8 + * This program is free software; you can redistribute it and/or 9 + * modify it under the terms of the GNU General Public License 10 + * version 2 as published by the Free Software Foundation. 11 + * 12 + * This program is distributed in the hope that it will be useful, but 13 + * WITHOUT ANY WARRANTY; without even the implied warranty of 14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 + * General Public License for more details. 16 + * 17 + * You should have received a copy of the GNU General Public License 18 + * along with this program; if not, write to the Free Software 19 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 20 + * 02110-1301 USA 21 + */ 22 + 23 + #include <linux/delay.h> 24 + #include <linux/i2c.h> 25 + #include <linux/init.h> 26 + #include <linux/kernel.h> 27 + #include <linux/math64.h> 28 + #include <linux/module.h> 29 + #include <linux/mutex.h> 30 + #include <linux/slab.h> 31 + #include <linux/v4l2-mediabus.h> 32 + 33 + #include <media/media-entity.h> 34 + #include <media/mt9m032.h> 35 + #include <media/v4l2-ctrls.h> 36 + #include <media/v4l2-device.h> 37 + #include <media/v4l2-subdev.h> 38 + 39 + #include "aptina-pll.h" 40 + 41 + /* 42 + * width and height include active boundary and black parts 43 + * 44 + * column 0- 15 active boundary 45 + * column 16-1455 image 46 + * column 1456-1471 active boundary 47 + * column 1472-1599 black 48 + * 49 + * row 0- 51 black 50 + * row 53- 59 active boundary 51 + * row 60-1139 image 52 + * row 1140-1147 active boundary 53 + * row 1148-1151 black 54 + */ 55 + 56 + #define MT9M032_PIXEL_ARRAY_WIDTH 1600 57 + #define MT9M032_PIXEL_ARRAY_HEIGHT 1152 58 + 59 + #define MT9M032_CHIP_VERSION 0x00 60 + #define MT9M032_CHIP_VERSION_VALUE 0x1402 61 + #define MT9M032_ROW_START 0x01 62 + #define MT9M032_ROW_START_MIN 0 63 + #define MT9M032_ROW_START_MAX 1152 64 + #define MT9M032_ROW_START_DEF 60 65 + #define MT9M032_COLUMN_START 0x02 66 + #define MT9M032_COLUMN_START_MIN 0 67 + #define MT9M032_COLUMN_START_MAX 1600 68 + #define MT9M032_COLUMN_START_DEF 16 69 + #define MT9M032_ROW_SIZE 0x03 70 + #define MT9M032_ROW_SIZE_MIN 32 71 + #define MT9M032_ROW_SIZE_MAX 1152 72 + #define MT9M032_ROW_SIZE_DEF 1080 73 + #define MT9M032_COLUMN_SIZE 0x04 74 + #define MT9M032_COLUMN_SIZE_MIN 32 75 + #define MT9M032_COLUMN_SIZE_MAX 1600 76 + #define MT9M032_COLUMN_SIZE_DEF 1440 77 + #define MT9M032_HBLANK 0x05 78 + #define MT9M032_VBLANK 0x06 79 + #define MT9M032_VBLANK_MAX 0x7ff 80 + #define MT9M032_SHUTTER_WIDTH_HIGH 0x08 81 + #define MT9M032_SHUTTER_WIDTH_LOW 0x09 82 + #define MT9M032_SHUTTER_WIDTH_MIN 1 83 + #define MT9M032_SHUTTER_WIDTH_MAX 1048575 84 + #define MT9M032_SHUTTER_WIDTH_DEF 1943 85 + #define MT9M032_PIX_CLK_CTRL 0x0a 86 + #define MT9M032_PIX_CLK_CTRL_INV_PIXCLK 0x8000 87 + #define MT9M032_RESTART 0x0b 88 + #define MT9M032_RESET 0x0d 89 + #define MT9M032_PLL_CONFIG1 0x11 90 + #define MT9M032_PLL_CONFIG1_OUTDIV_MASK 0x3f 91 + #define MT9M032_PLL_CONFIG1_MUL_SHIFT 8 92 + #define MT9M032_READ_MODE1 0x1e 93 + #define MT9M032_READ_MODE2 0x20 94 + #define MT9M032_READ_MODE2_VFLIP_SHIFT 15 95 + #define MT9M032_READ_MODE2_HFLIP_SHIFT 14 96 + #define MT9M032_READ_MODE2_ROW_BLC 0x40 97 + #define MT9M032_GAIN_GREEN1 0x2b 98 + #define MT9M032_GAIN_BLUE 0x2c 99 + #define MT9M032_GAIN_RED 0x2d 100 + #define MT9M032_GAIN_GREEN2 0x2e 101 + 102 + /* write only */ 103 + #define MT9M032_GAIN_ALL 0x35 104 + #define MT9M032_GAIN_DIGITAL_MASK 0x7f 105 + #define MT9M032_GAIN_DIGITAL_SHIFT 8 106 + #define MT9M032_GAIN_AMUL_SHIFT 6 107 + #define MT9M032_GAIN_ANALOG_MASK 0x3f 108 + #define MT9M032_FORMATTER1 0x9e 109 + #define MT9M032_FORMATTER2 0x9f 110 + #define MT9M032_FORMATTER2_DOUT_EN 0x1000 111 + #define MT9M032_FORMATTER2_PIXCLK_EN 0x2000 112 + 113 + /* 114 + * The available MT9M032 datasheet is missing documentation for register 0x10 115 + * MT9P031 seems to be close enough, so use constants from that datasheet for 116 + * now. 117 + * But keep the name MT9P031 to remind us, that this isn't really confirmed 118 + * for this sensor. 119 + */ 120 + #define MT9P031_PLL_CONTROL 0x10 121 + #define MT9P031_PLL_CONTROL_PWROFF 0x0050 122 + #define MT9P031_PLL_CONTROL_PWRON 0x0051 123 + #define MT9P031_PLL_CONTROL_USEPLL 0x0052 124 + #define MT9P031_PLL_CONFIG2 0x11 125 + #define MT9P031_PLL_CONFIG2_P1_DIV_MASK 0x1f 126 + 127 + struct mt9m032 { 128 + struct v4l2_subdev subdev; 129 + struct media_pad pad; 130 + struct mt9m032_platform_data *pdata; 131 + 132 + unsigned int pix_clock; 133 + 134 + struct v4l2_ctrl_handler ctrls; 135 + struct { 136 + struct v4l2_ctrl *hflip; 137 + struct v4l2_ctrl *vflip; 138 + }; 139 + 140 + struct mutex lock; /* Protects streaming, format, interval and crop */ 141 + 142 + bool streaming; 143 + 144 + struct v4l2_mbus_framefmt format; 145 + struct v4l2_rect crop; 146 + struct v4l2_fract frame_interval; 147 + }; 148 + 149 + #define to_mt9m032(sd) container_of(sd, struct mt9m032, subdev) 150 + #define to_dev(sensor) \ 151 + (&((struct i2c_client *)v4l2_get_subdevdata(&(sensor)->subdev))->dev) 152 + 153 + static int mt9m032_read(struct i2c_client *client, u8 reg) 154 + { 155 + return i2c_smbus_read_word_swapped(client, reg); 156 + } 157 + 158 + static int mt9m032_write(struct i2c_client *client, u8 reg, const u16 data) 159 + { 160 + return i2c_smbus_write_word_swapped(client, reg, data); 161 + } 162 + 163 + static u32 mt9m032_row_time(struct mt9m032 *sensor, unsigned int width) 164 + { 165 + unsigned int effective_width; 166 + u32 ns; 167 + 168 + effective_width = width + 716; /* empirical value */ 169 + ns = div_u64(1000000000ULL * effective_width, sensor->pix_clock); 170 + dev_dbg(to_dev(sensor), "MT9M032 line time: %u ns\n", ns); 171 + return ns; 172 + } 173 + 174 + static int mt9m032_update_timing(struct mt9m032 *sensor, 175 + struct v4l2_fract *interval) 176 + { 177 + struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev); 178 + struct v4l2_rect *crop = &sensor->crop; 179 + unsigned int min_vblank; 180 + unsigned int vblank; 181 + u32 row_time; 182 + 183 + if (!interval) 184 + interval = &sensor->frame_interval; 185 + 186 + row_time = mt9m032_row_time(sensor, crop->width); 187 + 188 + vblank = div_u64(1000000000ULL * interval->numerator, 189 + (u64)row_time * interval->denominator) 190 + - crop->height; 191 + 192 + if (vblank > MT9M032_VBLANK_MAX) { 193 + /* hardware limits to 11 bit values */ 194 + interval->denominator = 1000; 195 + interval->numerator = 196 + div_u64((crop->height + MT9M032_VBLANK_MAX) * 197 + (u64)row_time * interval->denominator, 198 + 1000000000ULL); 199 + vblank = div_u64(1000000000ULL * interval->numerator, 200 + (u64)row_time * interval->denominator) 201 + - crop->height; 202 + } 203 + /* enforce minimal 1.6ms blanking time. */ 204 + min_vblank = 1600000 / row_time; 205 + vblank = clamp_t(unsigned int, vblank, min_vblank, MT9M032_VBLANK_MAX); 206 + 207 + return mt9m032_write(client, MT9M032_VBLANK, vblank); 208 + } 209 + 210 + static int mt9m032_update_geom_timing(struct mt9m032 *sensor) 211 + { 212 + struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev); 213 + int ret; 214 + 215 + ret = mt9m032_write(client, MT9M032_COLUMN_SIZE, 216 + sensor->crop.width - 1); 217 + if (!ret) 218 + ret = mt9m032_write(client, MT9M032_ROW_SIZE, 219 + sensor->crop.height - 1); 220 + if (!ret) 221 + ret = mt9m032_write(client, MT9M032_COLUMN_START, 222 + sensor->crop.left); 223 + if (!ret) 224 + ret = mt9m032_write(client, MT9M032_ROW_START, 225 + sensor->crop.top); 226 + if (!ret) 227 + ret = mt9m032_update_timing(sensor, NULL); 228 + return ret; 229 + } 230 + 231 + static int update_formatter2(struct mt9m032 *sensor, bool streaming) 232 + { 233 + struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev); 234 + u16 reg_val = MT9M032_FORMATTER2_DOUT_EN 235 + | 0x0070; /* parts reserved! */ 236 + /* possibly for changing to 14-bit mode */ 237 + 238 + if (streaming) 239 + reg_val |= MT9M032_FORMATTER2_PIXCLK_EN; /* pixclock enable */ 240 + 241 + return mt9m032_write(client, MT9M032_FORMATTER2, reg_val); 242 + } 243 + 244 + static int mt9m032_setup_pll(struct mt9m032 *sensor) 245 + { 246 + static const struct aptina_pll_limits limits = { 247 + .ext_clock_min = 8000000, 248 + .ext_clock_max = 16500000, 249 + .int_clock_min = 2000000, 250 + .int_clock_max = 24000000, 251 + .out_clock_min = 322000000, 252 + .out_clock_max = 693000000, 253 + .pix_clock_max = 99000000, 254 + .n_min = 1, 255 + .n_max = 64, 256 + .m_min = 16, 257 + .m_max = 255, 258 + .p1_min = 1, 259 + .p1_max = 128, 260 + }; 261 + 262 + struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev); 263 + struct mt9m032_platform_data *pdata = sensor->pdata; 264 + struct aptina_pll pll; 265 + int ret; 266 + 267 + pll.ext_clock = pdata->ext_clock; 268 + pll.pix_clock = pdata->pix_clock; 269 + 270 + ret = aptina_pll_calculate(&client->dev, &limits, &pll); 271 + if (ret < 0) 272 + return ret; 273 + 274 + sensor->pix_clock = pdata->pix_clock; 275 + 276 + ret = mt9m032_write(client, MT9M032_PLL_CONFIG1, 277 + (pll.m << MT9M032_PLL_CONFIG1_MUL_SHIFT) 278 + | (pll.p1 - 1)); 279 + if (!ret) 280 + ret = mt9m032_write(client, MT9P031_PLL_CONFIG2, pll.n - 1); 281 + if (!ret) 282 + ret = mt9m032_write(client, MT9P031_PLL_CONTROL, 283 + MT9P031_PLL_CONTROL_PWRON | 284 + MT9P031_PLL_CONTROL_USEPLL); 285 + if (!ret) /* more reserved, Continuous, Master Mode */ 286 + ret = mt9m032_write(client, MT9M032_READ_MODE1, 0x8006); 287 + if (!ret) /* Set 14-bit mode, select 7 divider */ 288 + ret = mt9m032_write(client, MT9M032_FORMATTER1, 0x111e); 289 + 290 + return ret; 291 + } 292 + 293 + /* ----------------------------------------------------------------------------- 294 + * Subdev pad operations 295 + */ 296 + 297 + static int mt9m032_enum_mbus_code(struct v4l2_subdev *subdev, 298 + struct v4l2_subdev_fh *fh, 299 + struct v4l2_subdev_mbus_code_enum *code) 300 + { 301 + if (code->index != 0) 302 + return -EINVAL; 303 + 304 + code->code = V4L2_MBUS_FMT_Y8_1X8; 305 + return 0; 306 + } 307 + 308 + static int mt9m032_enum_frame_size(struct v4l2_subdev *subdev, 309 + struct v4l2_subdev_fh *fh, 310 + struct v4l2_subdev_frame_size_enum *fse) 311 + { 312 + if (fse->index != 0 || fse->code != V4L2_MBUS_FMT_Y8_1X8) 313 + return -EINVAL; 314 + 315 + fse->min_width = MT9M032_COLUMN_SIZE_DEF; 316 + fse->max_width = MT9M032_COLUMN_SIZE_DEF; 317 + fse->min_height = MT9M032_ROW_SIZE_DEF; 318 + fse->max_height = MT9M032_ROW_SIZE_DEF; 319 + 320 + return 0; 321 + } 322 + 323 + /** 324 + * __mt9m032_get_pad_crop() - get crop rect 325 + * @sensor: pointer to the sensor struct 326 + * @fh: file handle for getting the try crop rect from 327 + * @which: select try or active crop rect 328 + * 329 + * Returns a pointer the current active or fh relative try crop rect 330 + */ 331 + static struct v4l2_rect * 332 + __mt9m032_get_pad_crop(struct mt9m032 *sensor, struct v4l2_subdev_fh *fh, 333 + enum v4l2_subdev_format_whence which) 334 + { 335 + switch (which) { 336 + case V4L2_SUBDEV_FORMAT_TRY: 337 + return v4l2_subdev_get_try_crop(fh, 0); 338 + case V4L2_SUBDEV_FORMAT_ACTIVE: 339 + return &sensor->crop; 340 + default: 341 + return NULL; 342 + } 343 + } 344 + 345 + /** 346 + * __mt9m032_get_pad_format() - get format 347 + * @sensor: pointer to the sensor struct 348 + * @fh: file handle for getting the try format from 349 + * @which: select try or active format 350 + * 351 + * Returns a pointer the current active or fh relative try format 352 + */ 353 + static struct v4l2_mbus_framefmt * 354 + __mt9m032_get_pad_format(struct mt9m032 *sensor, struct v4l2_subdev_fh *fh, 355 + enum v4l2_subdev_format_whence which) 356 + { 357 + switch (which) { 358 + case V4L2_SUBDEV_FORMAT_TRY: 359 + return v4l2_subdev_get_try_format(fh, 0); 360 + case V4L2_SUBDEV_FORMAT_ACTIVE: 361 + return &sensor->format; 362 + default: 363 + return NULL; 364 + } 365 + } 366 + 367 + static int mt9m032_get_pad_format(struct v4l2_subdev *subdev, 368 + struct v4l2_subdev_fh *fh, 369 + struct v4l2_subdev_format *fmt) 370 + { 371 + struct mt9m032 *sensor = to_mt9m032(subdev); 372 + 373 + mutex_lock(&sensor->lock); 374 + fmt->format = *__mt9m032_get_pad_format(sensor, fh, fmt->which); 375 + mutex_unlock(&sensor->lock); 376 + 377 + return 0; 378 + } 379 + 380 + static int mt9m032_set_pad_format(struct v4l2_subdev *subdev, 381 + struct v4l2_subdev_fh *fh, 382 + struct v4l2_subdev_format *fmt) 383 + { 384 + struct mt9m032 *sensor = to_mt9m032(subdev); 385 + int ret; 386 + 387 + mutex_lock(&sensor->lock); 388 + 389 + if (sensor->streaming && fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) { 390 + ret = -EBUSY; 391 + goto done; 392 + } 393 + 394 + /* Scaling is not supported, the format is thus fixed. */ 395 + ret = mt9m032_get_pad_format(subdev, fh, fmt); 396 + 397 + done: 398 + mutex_lock(&sensor->lock); 399 + return ret; 400 + } 401 + 402 + static int mt9m032_get_pad_crop(struct v4l2_subdev *subdev, 403 + struct v4l2_subdev_fh *fh, 404 + struct v4l2_subdev_crop *crop) 405 + { 406 + struct mt9m032 *sensor = to_mt9m032(subdev); 407 + 408 + mutex_lock(&sensor->lock); 409 + crop->rect = *__mt9m032_get_pad_crop(sensor, fh, crop->which); 410 + mutex_unlock(&sensor->lock); 411 + 412 + return 0; 413 + } 414 + 415 + static int mt9m032_set_pad_crop(struct v4l2_subdev *subdev, 416 + struct v4l2_subdev_fh *fh, 417 + struct v4l2_subdev_crop *crop) 418 + { 419 + struct mt9m032 *sensor = to_mt9m032(subdev); 420 + struct v4l2_mbus_framefmt *format; 421 + struct v4l2_rect *__crop; 422 + struct v4l2_rect rect; 423 + int ret = 0; 424 + 425 + mutex_lock(&sensor->lock); 426 + 427 + if (sensor->streaming && crop->which == V4L2_SUBDEV_FORMAT_ACTIVE) { 428 + ret = -EBUSY; 429 + goto done; 430 + } 431 + 432 + /* Clamp the crop rectangle boundaries and align them to a multiple of 2 433 + * pixels to ensure a GRBG Bayer pattern. 434 + */ 435 + rect.left = clamp(ALIGN(crop->rect.left, 2), MT9M032_COLUMN_START_MIN, 436 + MT9M032_COLUMN_START_MAX); 437 + rect.top = clamp(ALIGN(crop->rect.top, 2), MT9M032_ROW_START_MIN, 438 + MT9M032_ROW_START_MAX); 439 + rect.width = clamp(ALIGN(crop->rect.width, 2), MT9M032_COLUMN_SIZE_MIN, 440 + MT9M032_COLUMN_SIZE_MAX); 441 + rect.height = clamp(ALIGN(crop->rect.height, 2), MT9M032_ROW_SIZE_MIN, 442 + MT9M032_ROW_SIZE_MAX); 443 + 444 + rect.width = min(rect.width, MT9M032_PIXEL_ARRAY_WIDTH - rect.left); 445 + rect.height = min(rect.height, MT9M032_PIXEL_ARRAY_HEIGHT - rect.top); 446 + 447 + __crop = __mt9m032_get_pad_crop(sensor, fh, crop->which); 448 + 449 + if (rect.width != __crop->width || rect.height != __crop->height) { 450 + /* Reset the output image size if the crop rectangle size has 451 + * been modified. 452 + */ 453 + format = __mt9m032_get_pad_format(sensor, fh, crop->which); 454 + format->width = rect.width; 455 + format->height = rect.height; 456 + } 457 + 458 + *__crop = rect; 459 + crop->rect = rect; 460 + 461 + if (crop->which == V4L2_SUBDEV_FORMAT_ACTIVE) 462 + ret = mt9m032_update_geom_timing(sensor); 463 + 464 + done: 465 + mutex_unlock(&sensor->lock); 466 + return ret; 467 + } 468 + 469 + static int mt9m032_get_frame_interval(struct v4l2_subdev *subdev, 470 + struct v4l2_subdev_frame_interval *fi) 471 + { 472 + struct mt9m032 *sensor = to_mt9m032(subdev); 473 + 474 + mutex_lock(&sensor->lock); 475 + memset(fi, 0, sizeof(*fi)); 476 + fi->interval = sensor->frame_interval; 477 + mutex_unlock(&sensor->lock); 478 + 479 + return 0; 480 + } 481 + 482 + static int mt9m032_set_frame_interval(struct v4l2_subdev *subdev, 483 + struct v4l2_subdev_frame_interval *fi) 484 + { 485 + struct mt9m032 *sensor = to_mt9m032(subdev); 486 + int ret; 487 + 488 + mutex_lock(&sensor->lock); 489 + 490 + if (sensor->streaming) { 491 + ret = -EBUSY; 492 + goto done; 493 + } 494 + 495 + /* Avoid divisions by 0. */ 496 + if (fi->interval.denominator == 0) 497 + fi->interval.denominator = 1; 498 + 499 + ret = mt9m032_update_timing(sensor, &fi->interval); 500 + if (!ret) 501 + sensor->frame_interval = fi->interval; 502 + 503 + done: 504 + mutex_unlock(&sensor->lock); 505 + return ret; 506 + } 507 + 508 + static int mt9m032_s_stream(struct v4l2_subdev *subdev, int streaming) 509 + { 510 + struct mt9m032 *sensor = to_mt9m032(subdev); 511 + int ret; 512 + 513 + mutex_lock(&sensor->lock); 514 + ret = update_formatter2(sensor, streaming); 515 + if (!ret) 516 + sensor->streaming = streaming; 517 + mutex_unlock(&sensor->lock); 518 + 519 + return ret; 520 + } 521 + 522 + /* ----------------------------------------------------------------------------- 523 + * V4L2 subdev core operations 524 + */ 525 + 526 + #ifdef CONFIG_VIDEO_ADV_DEBUG 527 + static int mt9m032_g_register(struct v4l2_subdev *sd, 528 + struct v4l2_dbg_register *reg) 529 + { 530 + struct mt9m032 *sensor = to_mt9m032(sd); 531 + struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev); 532 + int val; 533 + 534 + if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) 535 + return -EINVAL; 536 + if (reg->match.addr != client->addr) 537 + return -ENODEV; 538 + 539 + val = mt9m032_read(client, reg->reg); 540 + if (val < 0) 541 + return -EIO; 542 + 543 + reg->size = 2; 544 + reg->val = val; 545 + 546 + return 0; 547 + } 548 + 549 + static int mt9m032_s_register(struct v4l2_subdev *sd, 550 + struct v4l2_dbg_register *reg) 551 + { 552 + struct mt9m032 *sensor = to_mt9m032(sd); 553 + struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev); 554 + 555 + if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) 556 + return -EINVAL; 557 + 558 + if (reg->match.addr != client->addr) 559 + return -ENODEV; 560 + 561 + return mt9m032_write(client, reg->reg, reg->val); 562 + } 563 + #endif 564 + 565 + /* ----------------------------------------------------------------------------- 566 + * V4L2 subdev control operations 567 + */ 568 + 569 + static int update_read_mode2(struct mt9m032 *sensor, bool vflip, bool hflip) 570 + { 571 + struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev); 572 + int reg_val = (vflip << MT9M032_READ_MODE2_VFLIP_SHIFT) 573 + | (hflip << MT9M032_READ_MODE2_HFLIP_SHIFT) 574 + | MT9M032_READ_MODE2_ROW_BLC 575 + | 0x0007; 576 + 577 + return mt9m032_write(client, MT9M032_READ_MODE2, reg_val); 578 + } 579 + 580 + static int mt9m032_set_gain(struct mt9m032 *sensor, s32 val) 581 + { 582 + struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev); 583 + int digital_gain_val; /* in 1/8th (0..127) */ 584 + int analog_mul; /* 0 or 1 */ 585 + int analog_gain_val; /* in 1/16th. (0..63) */ 586 + u16 reg_val; 587 + 588 + digital_gain_val = 51; /* from setup example */ 589 + 590 + if (val < 63) { 591 + analog_mul = 0; 592 + analog_gain_val = val; 593 + } else { 594 + analog_mul = 1; 595 + analog_gain_val = val / 2; 596 + } 597 + 598 + /* a_gain = (1 + analog_mul) + (analog_gain_val + 1) / 16 */ 599 + /* overall_gain = a_gain * (1 + digital_gain_val / 8) */ 600 + 601 + reg_val = ((digital_gain_val & MT9M032_GAIN_DIGITAL_MASK) 602 + << MT9M032_GAIN_DIGITAL_SHIFT) 603 + | ((analog_mul & 1) << MT9M032_GAIN_AMUL_SHIFT) 604 + | (analog_gain_val & MT9M032_GAIN_ANALOG_MASK); 605 + 606 + return mt9m032_write(client, MT9M032_GAIN_ALL, reg_val); 607 + } 608 + 609 + static int mt9m032_try_ctrl(struct v4l2_ctrl *ctrl) 610 + { 611 + if (ctrl->id == V4L2_CID_GAIN && ctrl->val >= 63) { 612 + /* round because of multiplier used for values >= 63 */ 613 + ctrl->val &= ~1; 614 + } 615 + 616 + return 0; 617 + } 618 + 619 + static int mt9m032_set_ctrl(struct v4l2_ctrl *ctrl) 620 + { 621 + struct mt9m032 *sensor = 622 + container_of(ctrl->handler, struct mt9m032, ctrls); 623 + struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev); 624 + int ret; 625 + 626 + switch (ctrl->id) { 627 + case V4L2_CID_GAIN: 628 + return mt9m032_set_gain(sensor, ctrl->val); 629 + 630 + case V4L2_CID_HFLIP: 631 + /* case V4L2_CID_VFLIP: -- In the same cluster */ 632 + return update_read_mode2(sensor, sensor->vflip->val, 633 + sensor->hflip->val); 634 + 635 + case V4L2_CID_EXPOSURE: 636 + ret = mt9m032_write(client, MT9M032_SHUTTER_WIDTH_HIGH, 637 + (ctrl->val >> 16) & 0xffff); 638 + if (ret < 0) 639 + return ret; 640 + 641 + return mt9m032_write(client, MT9M032_SHUTTER_WIDTH_LOW, 642 + ctrl->val & 0xffff); 643 + } 644 + 645 + return 0; 646 + } 647 + 648 + static struct v4l2_ctrl_ops mt9m032_ctrl_ops = { 649 + .s_ctrl = mt9m032_set_ctrl, 650 + .try_ctrl = mt9m032_try_ctrl, 651 + }; 652 + 653 + /* -------------------------------------------------------------------------- */ 654 + 655 + static const struct v4l2_subdev_core_ops mt9m032_core_ops = { 656 + #ifdef CONFIG_VIDEO_ADV_DEBUG 657 + .g_register = mt9m032_g_register, 658 + .s_register = mt9m032_s_register, 659 + #endif 660 + }; 661 + 662 + static const struct v4l2_subdev_video_ops mt9m032_video_ops = { 663 + .s_stream = mt9m032_s_stream, 664 + .g_frame_interval = mt9m032_get_frame_interval, 665 + .s_frame_interval = mt9m032_set_frame_interval, 666 + }; 667 + 668 + static const struct v4l2_subdev_pad_ops mt9m032_pad_ops = { 669 + .enum_mbus_code = mt9m032_enum_mbus_code, 670 + .enum_frame_size = mt9m032_enum_frame_size, 671 + .get_fmt = mt9m032_get_pad_format, 672 + .set_fmt = mt9m032_set_pad_format, 673 + .set_crop = mt9m032_set_pad_crop, 674 + .get_crop = mt9m032_get_pad_crop, 675 + }; 676 + 677 + static const struct v4l2_subdev_ops mt9m032_ops = { 678 + .core = &mt9m032_core_ops, 679 + .video = &mt9m032_video_ops, 680 + .pad = &mt9m032_pad_ops, 681 + }; 682 + 683 + /* ----------------------------------------------------------------------------- 684 + * Driver initialization and probing 685 + */ 686 + 687 + static int mt9m032_probe(struct i2c_client *client, 688 + const struct i2c_device_id *devid) 689 + { 690 + struct i2c_adapter *adapter = client->adapter; 691 + struct mt9m032 *sensor; 692 + int chip_version; 693 + int ret; 694 + 695 + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) { 696 + dev_warn(&client->dev, 697 + "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n"); 698 + return -EIO; 699 + } 700 + 701 + if (!client->dev.platform_data) 702 + return -ENODEV; 703 + 704 + sensor = kzalloc(sizeof(*sensor), GFP_KERNEL); 705 + if (sensor == NULL) 706 + return -ENOMEM; 707 + 708 + mutex_init(&sensor->lock); 709 + 710 + sensor->pdata = client->dev.platform_data; 711 + 712 + v4l2_i2c_subdev_init(&sensor->subdev, client, &mt9m032_ops); 713 + sensor->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; 714 + 715 + chip_version = mt9m032_read(client, MT9M032_CHIP_VERSION); 716 + if (chip_version != MT9M032_CHIP_VERSION_VALUE) { 717 + dev_err(&client->dev, "MT9M032 not detected, wrong version " 718 + "0x%04x\n", chip_version); 719 + ret = -ENODEV; 720 + goto error_sensor; 721 + } 722 + 723 + dev_info(&client->dev, "MT9M032 detected at address 0x%02x\n", 724 + client->addr); 725 + 726 + sensor->frame_interval.numerator = 1; 727 + sensor->frame_interval.denominator = 30; 728 + 729 + sensor->crop.left = MT9M032_COLUMN_START_DEF; 730 + sensor->crop.top = MT9M032_ROW_START_DEF; 731 + sensor->crop.width = MT9M032_COLUMN_SIZE_DEF; 732 + sensor->crop.height = MT9M032_ROW_SIZE_DEF; 733 + 734 + sensor->format.width = sensor->crop.width; 735 + sensor->format.height = sensor->crop.height; 736 + sensor->format.code = V4L2_MBUS_FMT_Y8_1X8; 737 + sensor->format.field = V4L2_FIELD_NONE; 738 + sensor->format.colorspace = V4L2_COLORSPACE_SRGB; 739 + 740 + v4l2_ctrl_handler_init(&sensor->ctrls, 4); 741 + 742 + v4l2_ctrl_new_std(&sensor->ctrls, &mt9m032_ctrl_ops, 743 + V4L2_CID_GAIN, 0, 127, 1, 64); 744 + 745 + sensor->hflip = v4l2_ctrl_new_std(&sensor->ctrls, 746 + &mt9m032_ctrl_ops, 747 + V4L2_CID_HFLIP, 0, 1, 1, 0); 748 + sensor->vflip = v4l2_ctrl_new_std(&sensor->ctrls, 749 + &mt9m032_ctrl_ops, 750 + V4L2_CID_VFLIP, 0, 1, 1, 0); 751 + 752 + v4l2_ctrl_new_std(&sensor->ctrls, &mt9m032_ctrl_ops, 753 + V4L2_CID_EXPOSURE, MT9M032_SHUTTER_WIDTH_MIN, 754 + MT9M032_SHUTTER_WIDTH_MAX, 1, 755 + MT9M032_SHUTTER_WIDTH_DEF); 756 + 757 + if (sensor->ctrls.error) { 758 + ret = sensor->ctrls.error; 759 + dev_err(&client->dev, "control initialization error %d\n", ret); 760 + goto error_ctrl; 761 + } 762 + 763 + v4l2_ctrl_cluster(2, &sensor->hflip); 764 + 765 + sensor->subdev.ctrl_handler = &sensor->ctrls; 766 + sensor->pad.flags = MEDIA_PAD_FL_SOURCE; 767 + ret = media_entity_init(&sensor->subdev.entity, 1, &sensor->pad, 0); 768 + if (ret < 0) 769 + goto error_ctrl; 770 + 771 + ret = mt9m032_write(client, MT9M032_RESET, 1); /* reset on */ 772 + if (ret < 0) 773 + goto error_entity; 774 + mt9m032_write(client, MT9M032_RESET, 0); /* reset off */ 775 + if (ret < 0) 776 + goto error_entity; 777 + 778 + ret = mt9m032_setup_pll(sensor); 779 + if (ret < 0) 780 + goto error_entity; 781 + usleep_range(10000, 11000); 782 + 783 + ret = v4l2_ctrl_handler_setup(&sensor->ctrls); 784 + if (ret < 0) 785 + goto error_entity; 786 + 787 + /* SIZE */ 788 + ret = mt9m032_update_geom_timing(sensor); 789 + if (ret < 0) 790 + goto error_entity; 791 + 792 + ret = mt9m032_write(client, 0x41, 0x0000); /* reserved !!! */ 793 + if (ret < 0) 794 + goto error_entity; 795 + ret = mt9m032_write(client, 0x42, 0x0003); /* reserved !!! */ 796 + if (ret < 0) 797 + goto error_entity; 798 + ret = mt9m032_write(client, 0x43, 0x0003); /* reserved !!! */ 799 + if (ret < 0) 800 + goto error_entity; 801 + ret = mt9m032_write(client, 0x7f, 0x0000); /* reserved !!! */ 802 + if (ret < 0) 803 + goto error_entity; 804 + if (sensor->pdata->invert_pixclock) { 805 + ret = mt9m032_write(client, MT9M032_PIX_CLK_CTRL, 806 + MT9M032_PIX_CLK_CTRL_INV_PIXCLK); 807 + if (ret < 0) 808 + goto error_entity; 809 + } 810 + 811 + ret = mt9m032_write(client, MT9M032_RESTART, 1); /* Restart on */ 812 + if (ret < 0) 813 + goto error_entity; 814 + msleep(100); 815 + ret = mt9m032_write(client, MT9M032_RESTART, 0); /* Restart off */ 816 + if (ret < 0) 817 + goto error_entity; 818 + msleep(100); 819 + ret = update_formatter2(sensor, false); 820 + if (ret < 0) 821 + goto error_entity; 822 + 823 + return ret; 824 + 825 + error_entity: 826 + media_entity_cleanup(&sensor->subdev.entity); 827 + error_ctrl: 828 + v4l2_ctrl_handler_free(&sensor->ctrls); 829 + error_sensor: 830 + mutex_destroy(&sensor->lock); 831 + kfree(sensor); 832 + return ret; 833 + } 834 + 835 + static int mt9m032_remove(struct i2c_client *client) 836 + { 837 + struct v4l2_subdev *subdev = i2c_get_clientdata(client); 838 + struct mt9m032 *sensor = to_mt9m032(subdev); 839 + 840 + v4l2_device_unregister_subdev(&sensor->subdev); 841 + v4l2_ctrl_handler_free(&sensor->ctrls); 842 + media_entity_cleanup(&sensor->subdev.entity); 843 + mutex_destroy(&sensor->lock); 844 + kfree(sensor); 845 + return 0; 846 + } 847 + 848 + static const struct i2c_device_id mt9m032_id_table[] = { 849 + { MT9M032_NAME, 0 }, 850 + { } 851 + }; 852 + 853 + MODULE_DEVICE_TABLE(i2c, mt9m032_id_table); 854 + 855 + static struct i2c_driver mt9m032_i2c_driver = { 856 + .driver = { 857 + .name = MT9M032_NAME, 858 + }, 859 + .probe = mt9m032_probe, 860 + .remove = mt9m032_remove, 861 + .id_table = mt9m032_id_table, 862 + }; 863 + 864 + module_i2c_driver(mt9m032_i2c_driver); 865 + 866 + MODULE_AUTHOR("Martin Hostettler <martin@neutronstar.dyndns.org>"); 867 + MODULE_DESCRIPTION("MT9M032 camera sensor driver"); 868 + MODULE_LICENSE("GPL v2");
+36
include/media/mt9m032.h
··· 1 + /* 2 + * Driver for MT9M032 CMOS Image Sensor from Micron 3 + * 4 + * Copyright (C) 2010-2011 Lund Engineering 5 + * Contact: Gil Lund <gwlund@lundeng.com> 6 + * Author: Martin Hostettler <martin@neutronstar.dyndns.org> 7 + * 8 + * This program is free software; you can redistribute it and/or 9 + * modify it under the terms of the GNU General Public License 10 + * version 2 as published by the Free Software Foundation. 11 + * 12 + * This program is distributed in the hope that it will be useful, but 13 + * WITHOUT ANY WARRANTY; without even the implied warranty of 14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 + * General Public License for more details. 16 + * 17 + * You should have received a copy of the GNU General Public License 18 + * along with this program; if not, write to the Free Software 19 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 20 + * 02110-1301 USA 21 + * 22 + */ 23 + 24 + #ifndef MT9M032_H 25 + #define MT9M032_H 26 + 27 + #define MT9M032_NAME "mt9m032" 28 + #define MT9M032_I2C_ADDR (0xb8 >> 1) 29 + 30 + struct mt9m032_platform_data { 31 + u32 ext_clock; 32 + u32 pix_clock; 33 + bool invert_pixclock; 34 + 35 + }; 36 + #endif /* MT9M032_H */