aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/i2c/mt9v032.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/i2c/mt9v032.c')
-rw-r--r--drivers/media/i2c/mt9v032.c170
1 files changed, 94 insertions, 76 deletions
diff --git a/drivers/media/i2c/mt9v032.c b/drivers/media/i2c/mt9v032.c
index 40172b8d8ea2..d044bce312e0 100644
--- a/drivers/media/i2c/mt9v032.c
+++ b/drivers/media/i2c/mt9v032.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Driver for MT9V032 CMOS Image Sensor from Micron 2 * Driver for MT9V022, MT9V024, MT9V032, and MT9V034 CMOS Image Sensors
3 * 3 *
4 * Copyright (C) 2010, Laurent Pinchart <laurent.pinchart@ideasonboard.com> 4 * Copyright (C) 2010, Laurent Pinchart <laurent.pinchart@ideasonboard.com>
5 * 5 *
@@ -17,6 +17,7 @@
17#include <linux/i2c.h> 17#include <linux/i2c.h>
18#include <linux/log2.h> 18#include <linux/log2.h>
19#include <linux/mutex.h> 19#include <linux/mutex.h>
20#include <linux/regmap.h>
20#include <linux/slab.h> 21#include <linux/slab.h>
21#include <linux/videodev2.h> 22#include <linux/videodev2.h>
22#include <linux/v4l2-mediabus.h> 23#include <linux/v4l2-mediabus.h>
@@ -87,6 +88,7 @@
87#define MT9V032_READ_MODE_COLUMN_FLIP (1 << 5) 88#define MT9V032_READ_MODE_COLUMN_FLIP (1 << 5)
88#define MT9V032_READ_MODE_DARK_COLUMNS (1 << 6) 89#define MT9V032_READ_MODE_DARK_COLUMNS (1 << 6)
89#define MT9V032_READ_MODE_DARK_ROWS (1 << 7) 90#define MT9V032_READ_MODE_DARK_ROWS (1 << 7)
91#define MT9V032_READ_MODE_RESERVED 0x0300
90#define MT9V032_PIXEL_OPERATION_MODE 0x0f 92#define MT9V032_PIXEL_OPERATION_MODE 0x0f
91#define MT9V034_PIXEL_OPERATION_MODE_HDR (1 << 0) 93#define MT9V034_PIXEL_OPERATION_MODE_HDR (1 << 0)
92#define MT9V034_PIXEL_OPERATION_MODE_COLOR (1 << 1) 94#define MT9V034_PIXEL_OPERATION_MODE_COLOR (1 << 1)
@@ -133,8 +135,12 @@
133#define MT9V032_THERMAL_INFO 0xc1 135#define MT9V032_THERMAL_INFO 0xc1
134 136
135enum mt9v032_model { 137enum mt9v032_model {
136 MT9V032_MODEL_V032_COLOR, 138 MT9V032_MODEL_V022_COLOR, /* MT9V022IX7ATC */
137 MT9V032_MODEL_V032_MONO, 139 MT9V032_MODEL_V022_MONO, /* MT9V022IX7ATM */
140 MT9V032_MODEL_V024_COLOR, /* MT9V024IA7XTC */
141 MT9V032_MODEL_V024_MONO, /* MT9V024IA7XTM */
142 MT9V032_MODEL_V032_COLOR, /* MT9V032C12STM */
143 MT9V032_MODEL_V032_MONO, /* MT9V032C12STC */
138 MT9V032_MODEL_V034_COLOR, 144 MT9V032_MODEL_V034_COLOR,
139 MT9V032_MODEL_V034_MONO, 145 MT9V032_MODEL_V034_MONO,
140}; 146};
@@ -160,14 +166,14 @@ struct mt9v032_model_info {
160}; 166};
161 167
162static const struct mt9v032_model_version mt9v032_versions[] = { 168static const struct mt9v032_model_version mt9v032_versions[] = {
163 { MT9V032_CHIP_ID_REV1, "MT9V032 rev1/2" }, 169 { MT9V032_CHIP_ID_REV1, "MT9V022/MT9V032 rev1/2" },
164 { MT9V032_CHIP_ID_REV3, "MT9V032 rev3" }, 170 { MT9V032_CHIP_ID_REV3, "MT9V022/MT9V032 rev3" },
165 { MT9V034_CHIP_ID_REV1, "MT9V034 rev1" }, 171 { MT9V034_CHIP_ID_REV1, "MT9V024/MT9V034 rev1" },
166}; 172};
167 173
168static const struct mt9v032_model_data mt9v032_model_data[] = { 174static const struct mt9v032_model_data mt9v032_model_data[] = {
169 { 175 {
170 /* MT9V032 revisions 1/2/3 */ 176 /* MT9V022, MT9V032 revisions 1/2/3 */
171 .min_row_time = 660, 177 .min_row_time = 660,
172 .min_hblank = MT9V032_HORIZONTAL_BLANKING_MIN, 178 .min_hblank = MT9V032_HORIZONTAL_BLANKING_MIN,
173 .min_vblank = MT9V032_VERTICAL_BLANKING_MIN, 179 .min_vblank = MT9V032_VERTICAL_BLANKING_MIN,
@@ -176,7 +182,7 @@ static const struct mt9v032_model_data mt9v032_model_data[] = {
176 .max_shutter = MT9V032_TOTAL_SHUTTER_WIDTH_MAX, 182 .max_shutter = MT9V032_TOTAL_SHUTTER_WIDTH_MAX,
177 .pclk_reg = MT9V032_PIXEL_CLOCK, 183 .pclk_reg = MT9V032_PIXEL_CLOCK,
178 }, { 184 }, {
179 /* MT9V034 */ 185 /* MT9V024, MT9V034 */
180 .min_row_time = 690, 186 .min_row_time = 690,
181 .min_hblank = MT9V034_HORIZONTAL_BLANKING_MIN, 187 .min_hblank = MT9V034_HORIZONTAL_BLANKING_MIN,
182 .min_vblank = MT9V034_VERTICAL_BLANKING_MIN, 188 .min_vblank = MT9V034_VERTICAL_BLANKING_MIN,
@@ -188,6 +194,22 @@ static const struct mt9v032_model_data mt9v032_model_data[] = {
188}; 194};
189 195
190static const struct mt9v032_model_info mt9v032_models[] = { 196static const struct mt9v032_model_info mt9v032_models[] = {
197 [MT9V032_MODEL_V022_COLOR] = {
198 .data = &mt9v032_model_data[0],
199 .color = true,
200 },
201 [MT9V032_MODEL_V022_MONO] = {
202 .data = &mt9v032_model_data[0],
203 .color = false,
204 },
205 [MT9V032_MODEL_V024_COLOR] = {
206 .data = &mt9v032_model_data[1],
207 .color = true,
208 },
209 [MT9V032_MODEL_V024_MONO] = {
210 .data = &mt9v032_model_data[1],
211 .color = false,
212 },
191 [MT9V032_MODEL_V032_COLOR] = { 213 [MT9V032_MODEL_V032_COLOR] = {
192 .data = &mt9v032_model_data[0], 214 .data = &mt9v032_model_data[0],
193 .color = true, 215 .color = true,
@@ -224,6 +246,7 @@ struct mt9v032 {
224 struct mutex power_lock; 246 struct mutex power_lock;
225 int power_count; 247 int power_count;
226 248
249 struct regmap *regmap;
227 struct clk *clk; 250 struct clk *clk;
228 251
229 struct mt9v032_platform_data *pdata; 252 struct mt9v032_platform_data *pdata;
@@ -231,7 +254,6 @@ struct mt9v032 {
231 const struct mt9v032_model_version *version; 254 const struct mt9v032_model_version *version;
232 255
233 u32 sysclk; 256 u32 sysclk;
234 u16 chip_control;
235 u16 aec_agc; 257 u16 aec_agc;
236 u16 hblank; 258 u16 hblank;
237 struct { 259 struct {
@@ -245,40 +267,10 @@ static struct mt9v032 *to_mt9v032(struct v4l2_subdev *sd)
245 return container_of(sd, struct mt9v032, subdev); 267 return container_of(sd, struct mt9v032, subdev);
246} 268}
247 269
248static int mt9v032_read(struct i2c_client *client, const u8 reg)
249{
250 s32 data = i2c_smbus_read_word_swapped(client, reg);
251 dev_dbg(&client->dev, "%s: read 0x%04x from 0x%02x\n", __func__,
252 data, reg);
253 return data;
254}
255
256static int mt9v032_write(struct i2c_client *client, const u8 reg,
257 const u16 data)
258{
259 dev_dbg(&client->dev, "%s: writing 0x%04x to 0x%02x\n", __func__,
260 data, reg);
261 return i2c_smbus_write_word_swapped(client, reg, data);
262}
263
264static int mt9v032_set_chip_control(struct mt9v032 *mt9v032, u16 clear, u16 set)
265{
266 struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev);
267 u16 value = (mt9v032->chip_control & ~clear) | set;
268 int ret;
269
270 ret = mt9v032_write(client, MT9V032_CHIP_CONTROL, value);
271 if (ret < 0)
272 return ret;
273
274 mt9v032->chip_control = value;
275 return 0;
276}
277
278static int 270static int
279mt9v032_update_aec_agc(struct mt9v032 *mt9v032, u16 which, int enable) 271mt9v032_update_aec_agc(struct mt9v032 *mt9v032, u16 which, int enable)
280{ 272{
281 struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev); 273 struct regmap *map = mt9v032->regmap;
282 u16 value = mt9v032->aec_agc; 274 u16 value = mt9v032->aec_agc;
283 int ret; 275 int ret;
284 276
@@ -287,7 +279,7 @@ mt9v032_update_aec_agc(struct mt9v032 *mt9v032, u16 which, int enable)
287 else 279 else
288 value &= ~which; 280 value &= ~which;
289 281
290 ret = mt9v032_write(client, MT9V032_AEC_AGC_ENABLE, value); 282 ret = regmap_write(map, MT9V032_AEC_AGC_ENABLE, value);
291 if (ret < 0) 283 if (ret < 0)
292 return ret; 284 return ret;
293 285
@@ -298,23 +290,23 @@ mt9v032_update_aec_agc(struct mt9v032 *mt9v032, u16 which, int enable)
298static int 290static int
299mt9v032_update_hblank(struct mt9v032 *mt9v032) 291mt9v032_update_hblank(struct mt9v032 *mt9v032)
300{ 292{
301 struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev);
302 struct v4l2_rect *crop = &mt9v032->crop; 293 struct v4l2_rect *crop = &mt9v032->crop;
303 unsigned int min_hblank = mt9v032->model->data->min_hblank; 294 unsigned int min_hblank = mt9v032->model->data->min_hblank;
304 unsigned int hblank; 295 unsigned int hblank;
305 296
306 if (mt9v032->version->version == MT9V034_CHIP_ID_REV1) 297 if (mt9v032->version->version == MT9V034_CHIP_ID_REV1)
307 min_hblank += (mt9v032->hratio - 1) * 10; 298 min_hblank += (mt9v032->hratio - 1) * 10;
308 min_hblank = max_t(unsigned int, (int)mt9v032->model->data->min_row_time - crop->width, 299 min_hblank = max_t(int, mt9v032->model->data->min_row_time - crop->width,
309 (int)min_hblank); 300 min_hblank);
310 hblank = max_t(unsigned int, mt9v032->hblank, min_hblank); 301 hblank = max_t(unsigned int, mt9v032->hblank, min_hblank);
311 302
312 return mt9v032_write(client, MT9V032_HORIZONTAL_BLANKING, hblank); 303 return regmap_write(mt9v032->regmap, MT9V032_HORIZONTAL_BLANKING,
304 hblank);
313} 305}
314 306
315static int mt9v032_power_on(struct mt9v032 *mt9v032) 307static int mt9v032_power_on(struct mt9v032 *mt9v032)
316{ 308{
317 struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev); 309 struct regmap *map = mt9v032->regmap;
318 int ret; 310 int ret;
319 311
320 ret = clk_set_rate(mt9v032->clk, mt9v032->sysclk); 312 ret = clk_set_rate(mt9v032->clk, mt9v032->sysclk);
@@ -328,15 +320,15 @@ static int mt9v032_power_on(struct mt9v032 *mt9v032)
328 udelay(1); 320 udelay(1);
329 321
330 /* Reset the chip and stop data read out */ 322 /* Reset the chip and stop data read out */
331 ret = mt9v032_write(client, MT9V032_RESET, 1); 323 ret = regmap_write(map, MT9V032_RESET, 1);
332 if (ret < 0) 324 if (ret < 0)
333 return ret; 325 return ret;
334 326
335 ret = mt9v032_write(client, MT9V032_RESET, 0); 327 ret = regmap_write(map, MT9V032_RESET, 0);
336 if (ret < 0) 328 if (ret < 0)
337 return ret; 329 return ret;
338 330
339 return mt9v032_write(client, MT9V032_CHIP_CONTROL, 0); 331 return regmap_write(map, MT9V032_CHIP_CONTROL, 0);
340} 332}
341 333
342static void mt9v032_power_off(struct mt9v032 *mt9v032) 334static void mt9v032_power_off(struct mt9v032 *mt9v032)
@@ -346,7 +338,7 @@ static void mt9v032_power_off(struct mt9v032 *mt9v032)
346 338
347static int __mt9v032_set_power(struct mt9v032 *mt9v032, bool on) 339static int __mt9v032_set_power(struct mt9v032 *mt9v032, bool on)
348{ 340{
349 struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev); 341 struct regmap *map = mt9v032->regmap;
350 int ret; 342 int ret;
351 343
352 if (!on) { 344 if (!on) {
@@ -360,14 +352,14 @@ static int __mt9v032_set_power(struct mt9v032 *mt9v032, bool on)
360 352
361 /* Configure the pixel clock polarity */ 353 /* Configure the pixel clock polarity */
362 if (mt9v032->pdata && mt9v032->pdata->clk_pol) { 354 if (mt9v032->pdata && mt9v032->pdata->clk_pol) {
363 ret = mt9v032_write(client, mt9v032->model->data->pclk_reg, 355 ret = regmap_write(map, mt9v032->model->data->pclk_reg,
364 MT9V032_PIXEL_CLOCK_INV_PXL_CLK); 356 MT9V032_PIXEL_CLOCK_INV_PXL_CLK);
365 if (ret < 0) 357 if (ret < 0)
366 return ret; 358 return ret;
367 } 359 }
368 360
369 /* Disable the noise correction algorithm and restore the controls. */ 361 /* Disable the noise correction algorithm and restore the controls. */
370 ret = mt9v032_write(client, MT9V032_ROW_NOISE_CORR_CONTROL, 0); 362 ret = regmap_write(map, MT9V032_ROW_NOISE_CORR_CONTROL, 0);
371 if (ret < 0) 363 if (ret < 0)
372 return ret; 364 return ret;
373 365
@@ -411,38 +403,39 @@ static int mt9v032_s_stream(struct v4l2_subdev *subdev, int enable)
411 const u16 mode = MT9V032_CHIP_CONTROL_MASTER_MODE 403 const u16 mode = MT9V032_CHIP_CONTROL_MASTER_MODE
412 | MT9V032_CHIP_CONTROL_DOUT_ENABLE 404 | MT9V032_CHIP_CONTROL_DOUT_ENABLE
413 | MT9V032_CHIP_CONTROL_SEQUENTIAL; 405 | MT9V032_CHIP_CONTROL_SEQUENTIAL;
414 struct i2c_client *client = v4l2_get_subdevdata(subdev);
415 struct mt9v032 *mt9v032 = to_mt9v032(subdev); 406 struct mt9v032 *mt9v032 = to_mt9v032(subdev);
416 struct v4l2_rect *crop = &mt9v032->crop; 407 struct v4l2_rect *crop = &mt9v032->crop;
408 struct regmap *map = mt9v032->regmap;
417 unsigned int hbin; 409 unsigned int hbin;
418 unsigned int vbin; 410 unsigned int vbin;
419 int ret; 411 int ret;
420 412
421 if (!enable) 413 if (!enable)
422 return mt9v032_set_chip_control(mt9v032, mode, 0); 414 return regmap_update_bits(map, MT9V032_CHIP_CONTROL, mode, 0);
423 415
424 /* Configure the window size and row/column bin */ 416 /* Configure the window size and row/column bin */
425 hbin = fls(mt9v032->hratio) - 1; 417 hbin = fls(mt9v032->hratio) - 1;
426 vbin = fls(mt9v032->vratio) - 1; 418 vbin = fls(mt9v032->vratio) - 1;
427 ret = mt9v032_write(client, MT9V032_READ_MODE, 419 ret = regmap_update_bits(map, MT9V032_READ_MODE,
428 hbin << MT9V032_READ_MODE_COLUMN_BIN_SHIFT | 420 ~MT9V032_READ_MODE_RESERVED,
429 vbin << MT9V032_READ_MODE_ROW_BIN_SHIFT); 421 hbin << MT9V032_READ_MODE_COLUMN_BIN_SHIFT |
422 vbin << MT9V032_READ_MODE_ROW_BIN_SHIFT);
430 if (ret < 0) 423 if (ret < 0)
431 return ret; 424 return ret;
432 425
433 ret = mt9v032_write(client, MT9V032_COLUMN_START, crop->left); 426 ret = regmap_write(map, MT9V032_COLUMN_START, crop->left);
434 if (ret < 0) 427 if (ret < 0)
435 return ret; 428 return ret;
436 429
437 ret = mt9v032_write(client, MT9V032_ROW_START, crop->top); 430 ret = regmap_write(map, MT9V032_ROW_START, crop->top);
438 if (ret < 0) 431 if (ret < 0)
439 return ret; 432 return ret;
440 433
441 ret = mt9v032_write(client, MT9V032_WINDOW_WIDTH, crop->width); 434 ret = regmap_write(map, MT9V032_WINDOW_WIDTH, crop->width);
442 if (ret < 0) 435 if (ret < 0)
443 return ret; 436 return ret;
444 437
445 ret = mt9v032_write(client, MT9V032_WINDOW_HEIGHT, crop->height); 438 ret = regmap_write(map, MT9V032_WINDOW_HEIGHT, crop->height);
446 if (ret < 0) 439 if (ret < 0)
447 return ret; 440 return ret;
448 441
@@ -451,7 +444,7 @@ static int mt9v032_s_stream(struct v4l2_subdev *subdev, int enable)
451 return ret; 444 return ret;
452 445
453 /* Switch to master "normal" mode */ 446 /* Switch to master "normal" mode */
454 return mt9v032_set_chip_control(mt9v032, 0, mode); 447 return regmap_update_bits(map, MT9V032_CHIP_CONTROL, mode, mode);
455} 448}
456 449
457static int mt9v032_enum_mbus_code(struct v4l2_subdev *subdev, 450static int mt9v032_enum_mbus_code(struct v4l2_subdev *subdev,
@@ -633,7 +626,7 @@ static int mt9v032_s_ctrl(struct v4l2_ctrl *ctrl)
633{ 626{
634 struct mt9v032 *mt9v032 = 627 struct mt9v032 *mt9v032 =
635 container_of(ctrl->handler, struct mt9v032, ctrls); 628 container_of(ctrl->handler, struct mt9v032, ctrls);
636 struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev); 629 struct regmap *map = mt9v032->regmap;
637 u32 freq; 630 u32 freq;
638 u16 data; 631 u16 data;
639 632
@@ -643,23 +636,23 @@ static int mt9v032_s_ctrl(struct v4l2_ctrl *ctrl)
643 ctrl->val); 636 ctrl->val);
644 637
645 case V4L2_CID_GAIN: 638 case V4L2_CID_GAIN:
646 return mt9v032_write(client, MT9V032_ANALOG_GAIN, ctrl->val); 639 return regmap_write(map, MT9V032_ANALOG_GAIN, ctrl->val);
647 640
648 case V4L2_CID_EXPOSURE_AUTO: 641 case V4L2_CID_EXPOSURE_AUTO:
649 return mt9v032_update_aec_agc(mt9v032, MT9V032_AEC_ENABLE, 642 return mt9v032_update_aec_agc(mt9v032, MT9V032_AEC_ENABLE,
650 !ctrl->val); 643 !ctrl->val);
651 644
652 case V4L2_CID_EXPOSURE: 645 case V4L2_CID_EXPOSURE:
653 return mt9v032_write(client, MT9V032_TOTAL_SHUTTER_WIDTH, 646 return regmap_write(map, MT9V032_TOTAL_SHUTTER_WIDTH,
654 ctrl->val); 647 ctrl->val);
655 648
656 case V4L2_CID_HBLANK: 649 case V4L2_CID_HBLANK:
657 mt9v032->hblank = ctrl->val; 650 mt9v032->hblank = ctrl->val;
658 return mt9v032_update_hblank(mt9v032); 651 return mt9v032_update_hblank(mt9v032);
659 652
660 case V4L2_CID_VBLANK: 653 case V4L2_CID_VBLANK:
661 return mt9v032_write(client, MT9V032_VERTICAL_BLANKING, 654 return regmap_write(map, MT9V032_VERTICAL_BLANKING,
662 ctrl->val); 655 ctrl->val);
663 656
664 case V4L2_CID_PIXEL_RATE: 657 case V4L2_CID_PIXEL_RATE:
665 case V4L2_CID_LINK_FREQ: 658 case V4L2_CID_LINK_FREQ:
@@ -667,7 +660,7 @@ static int mt9v032_s_ctrl(struct v4l2_ctrl *ctrl)
667 break; 660 break;
668 661
669 freq = mt9v032->pdata->link_freqs[mt9v032->link_freq->val]; 662 freq = mt9v032->pdata->link_freqs[mt9v032->link_freq->val];
670 mt9v032->pixel_rate->val64 = freq; 663 *mt9v032->pixel_rate->p_new.p_s64 = freq;
671 mt9v032->sysclk = freq; 664 mt9v032->sysclk = freq;
672 break; 665 break;
673 666
@@ -696,7 +689,7 @@ static int mt9v032_s_ctrl(struct v4l2_ctrl *ctrl)
696 | MT9V032_TEST_PATTERN_FLIP; 689 | MT9V032_TEST_PATTERN_FLIP;
697 break; 690 break;
698 } 691 }
699 return mt9v032_write(client, MT9V032_TEST_PATTERN, data); 692 return regmap_write(map, MT9V032_TEST_PATTERN, data);
700 } 693 }
701 694
702 return 0; 695 return 0;
@@ -764,7 +757,7 @@ static int mt9v032_registered(struct v4l2_subdev *subdev)
764 struct i2c_client *client = v4l2_get_subdevdata(subdev); 757 struct i2c_client *client = v4l2_get_subdevdata(subdev);
765 struct mt9v032 *mt9v032 = to_mt9v032(subdev); 758 struct mt9v032 *mt9v032 = to_mt9v032(subdev);
766 unsigned int i; 759 unsigned int i;
767 s32 version; 760 u32 version;
768 int ret; 761 int ret;
769 762
770 dev_info(&client->dev, "Probing MT9V032 at address 0x%02x\n", 763 dev_info(&client->dev, "Probing MT9V032 at address 0x%02x\n",
@@ -777,10 +770,10 @@ static int mt9v032_registered(struct v4l2_subdev *subdev)
777 } 770 }
778 771
779 /* Read and check the sensor version */ 772 /* Read and check the sensor version */
780 version = mt9v032_read(client, MT9V032_CHIP_VERSION); 773 ret = regmap_read(mt9v032->regmap, MT9V032_CHIP_VERSION, &version);
781 if (version < 0) { 774 if (ret < 0) {
782 dev_err(&client->dev, "Failed reading chip version\n"); 775 dev_err(&client->dev, "Failed reading chip version\n");
783 return version; 776 return ret;
784 } 777 }
785 778
786 for (i = 0; i < ARRAY_SIZE(mt9v032_versions); ++i) { 779 for (i = 0; i < ARRAY_SIZE(mt9v032_versions); ++i) {
@@ -867,6 +860,13 @@ static const struct v4l2_subdev_internal_ops mt9v032_subdev_internal_ops = {
867 .close = mt9v032_close, 860 .close = mt9v032_close,
868}; 861};
869 862
863static const struct regmap_config mt9v032_regmap_config = {
864 .reg_bits = 8,
865 .val_bits = 16,
866 .max_register = 0xff,
867 .cache_type = REGCACHE_RBTREE,
868};
869
870/* ----------------------------------------------------------------------------- 870/* -----------------------------------------------------------------------------
871 * Driver initialization and probing 871 * Driver initialization and probing
872 */ 872 */
@@ -890,6 +890,10 @@ static int mt9v032_probe(struct i2c_client *client,
890 if (!mt9v032) 890 if (!mt9v032)
891 return -ENOMEM; 891 return -ENOMEM;
892 892
893 mt9v032->regmap = devm_regmap_init_i2c(client, &mt9v032_regmap_config);
894 if (IS_ERR(mt9v032->regmap))
895 return PTR_ERR(mt9v032->regmap);
896
893 mt9v032->clk = devm_clk_get(&client->dev, NULL); 897 mt9v032->clk = devm_clk_get(&client->dev, NULL);
894 if (IS_ERR(mt9v032->clk)) 898 if (IS_ERR(mt9v032->clk))
895 return PTR_ERR(mt9v032->clk); 899 return PTR_ERR(mt9v032->clk);
@@ -931,7 +935,7 @@ static int mt9v032_probe(struct i2c_client *client,
931 935
932 mt9v032->pixel_rate = 936 mt9v032->pixel_rate =
933 v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops, 937 v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops,
934 V4L2_CID_PIXEL_RATE, 0, 0, 1, 0); 938 V4L2_CID_PIXEL_RATE, 1, INT_MAX, 1, 1);
935 939
936 if (pdata && pdata->link_freqs) { 940 if (pdata && pdata->link_freqs) {
937 unsigned int def = 0; 941 unsigned int def = 0;
@@ -984,10 +988,19 @@ static int mt9v032_probe(struct i2c_client *client,
984 988
985 mt9v032->pad.flags = MEDIA_PAD_FL_SOURCE; 989 mt9v032->pad.flags = MEDIA_PAD_FL_SOURCE;
986 ret = media_entity_init(&mt9v032->subdev.entity, 1, &mt9v032->pad, 0); 990 ret = media_entity_init(&mt9v032->subdev.entity, 1, &mt9v032->pad, 0);
991 if (ret < 0)
992 goto err;
987 993
994 mt9v032->subdev.dev = &client->dev;
995 ret = v4l2_async_register_subdev(&mt9v032->subdev);
988 if (ret < 0) 996 if (ret < 0)
989 v4l2_ctrl_handler_free(&mt9v032->ctrls); 997 goto err;
990 998
999 return 0;
1000
1001err:
1002 media_entity_cleanup(&mt9v032->subdev.entity);
1003 v4l2_ctrl_handler_free(&mt9v032->ctrls);
991 return ret; 1004 return ret;
992} 1005}
993 1006
@@ -996,6 +1009,7 @@ static int mt9v032_remove(struct i2c_client *client)
996 struct v4l2_subdev *subdev = i2c_get_clientdata(client); 1009 struct v4l2_subdev *subdev = i2c_get_clientdata(client);
997 struct mt9v032 *mt9v032 = to_mt9v032(subdev); 1010 struct mt9v032 *mt9v032 = to_mt9v032(subdev);
998 1011
1012 v4l2_async_unregister_subdev(subdev);
999 v4l2_ctrl_handler_free(&mt9v032->ctrls); 1013 v4l2_ctrl_handler_free(&mt9v032->ctrls);
1000 v4l2_device_unregister_subdev(subdev); 1014 v4l2_device_unregister_subdev(subdev);
1001 media_entity_cleanup(&subdev->entity); 1015 media_entity_cleanup(&subdev->entity);
@@ -1004,6 +1018,10 @@ static int mt9v032_remove(struct i2c_client *client)
1004} 1018}
1005 1019
1006static const struct i2c_device_id mt9v032_id[] = { 1020static const struct i2c_device_id mt9v032_id[] = {
1021 { "mt9v022", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V022_COLOR] },
1022 { "mt9v022m", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V022_MONO] },
1023 { "mt9v024", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V024_COLOR] },
1024 { "mt9v024m", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V024_MONO] },
1007 { "mt9v032", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V032_COLOR] }, 1025 { "mt9v032", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V032_COLOR] },
1008 { "mt9v032m", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V032_MONO] }, 1026 { "mt9v032m", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V032_MONO] },
1009 { "mt9v034", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V034_COLOR] }, 1027 { "mt9v034", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V034_COLOR] },