diff options
Diffstat (limited to 'drivers/media/video/mt9m111.c')
-rw-r--r-- | drivers/media/video/mt9m111.c | 309 |
1 files changed, 129 insertions, 180 deletions
diff --git a/drivers/media/video/mt9m111.c b/drivers/media/video/mt9m111.c index 95c2f089605f..29f976afd465 100644 --- a/drivers/media/video/mt9m111.c +++ b/drivers/media/video/mt9m111.c | |||
@@ -148,6 +148,7 @@ enum mt9m111_context { | |||
148 | }; | 148 | }; |
149 | 149 | ||
150 | struct mt9m111 { | 150 | struct mt9m111 { |
151 | struct v4l2_subdev subdev; | ||
151 | int model; /* V4L2_IDENT_MT9M11x* codes from v4l2-chip-ident.h */ | 152 | int model; /* V4L2_IDENT_MT9M11x* codes from v4l2-chip-ident.h */ |
152 | enum mt9m111_context context; | 153 | enum mt9m111_context context; |
153 | struct v4l2_rect rect; | 154 | struct v4l2_rect rect; |
@@ -164,6 +165,11 @@ struct mt9m111 { | |||
164 | unsigned int autowhitebalance:1; | 165 | unsigned int autowhitebalance:1; |
165 | }; | 166 | }; |
166 | 167 | ||
168 | static struct mt9m111 *to_mt9m111(const struct i2c_client *client) | ||
169 | { | ||
170 | return container_of(i2c_get_clientdata(client), struct mt9m111, subdev); | ||
171 | } | ||
172 | |||
167 | static int reg_page_map_set(struct i2c_client *client, const u16 reg) | 173 | static int reg_page_map_set(struct i2c_client *client, const u16 reg) |
168 | { | 174 | { |
169 | int ret; | 175 | int ret; |
@@ -227,10 +233,9 @@ static int mt9m111_reg_clear(struct i2c_client *client, const u16 reg, | |||
227 | return mt9m111_reg_write(client, reg, ret & ~data); | 233 | return mt9m111_reg_write(client, reg, ret & ~data); |
228 | } | 234 | } |
229 | 235 | ||
230 | static int mt9m111_set_context(struct soc_camera_device *icd, | 236 | static int mt9m111_set_context(struct i2c_client *client, |
231 | enum mt9m111_context ctxt) | 237 | enum mt9m111_context ctxt) |
232 | { | 238 | { |
233 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); | ||
234 | int valB = MT9M111_CTXT_CTRL_RESTART | MT9M111_CTXT_CTRL_DEFECTCOR_B | 239 | int valB = MT9M111_CTXT_CTRL_RESTART | MT9M111_CTXT_CTRL_DEFECTCOR_B |
235 | | MT9M111_CTXT_CTRL_RESIZE_B | MT9M111_CTXT_CTRL_CTRL2_B | 240 | | MT9M111_CTXT_CTRL_RESIZE_B | MT9M111_CTXT_CTRL_CTRL2_B |
236 | | MT9M111_CTXT_CTRL_GAMMA_B | MT9M111_CTXT_CTRL_READ_MODE_B | 241 | | MT9M111_CTXT_CTRL_GAMMA_B | MT9M111_CTXT_CTRL_READ_MODE_B |
@@ -244,11 +249,10 @@ static int mt9m111_set_context(struct soc_camera_device *icd, | |||
244 | return reg_write(CONTEXT_CONTROL, valA); | 249 | return reg_write(CONTEXT_CONTROL, valA); |
245 | } | 250 | } |
246 | 251 | ||
247 | static int mt9m111_setup_rect(struct soc_camera_device *icd, | 252 | static int mt9m111_setup_rect(struct i2c_client *client, |
248 | struct v4l2_rect *rect) | 253 | struct v4l2_rect *rect) |
249 | { | 254 | { |
250 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); | 255 | struct mt9m111 *mt9m111 = to_mt9m111(client); |
251 | struct mt9m111 *mt9m111 = i2c_get_clientdata(client); | ||
252 | int ret, is_raw_format; | 256 | int ret, is_raw_format; |
253 | int width = rect->width; | 257 | int width = rect->width; |
254 | int height = rect->height; | 258 | int height = rect->height; |
@@ -290,9 +294,8 @@ static int mt9m111_setup_rect(struct soc_camera_device *icd, | |||
290 | return ret; | 294 | return ret; |
291 | } | 295 | } |
292 | 296 | ||
293 | static int mt9m111_setup_pixfmt(struct soc_camera_device *icd, u16 outfmt) | 297 | static int mt9m111_setup_pixfmt(struct i2c_client *client, u16 outfmt) |
294 | { | 298 | { |
295 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); | ||
296 | int ret; | 299 | int ret; |
297 | 300 | ||
298 | ret = reg_write(OUTPUT_FORMAT_CTRL2_A, outfmt); | 301 | ret = reg_write(OUTPUT_FORMAT_CTRL2_A, outfmt); |
@@ -301,20 +304,19 @@ static int mt9m111_setup_pixfmt(struct soc_camera_device *icd, u16 outfmt) | |||
301 | return ret; | 304 | return ret; |
302 | } | 305 | } |
303 | 306 | ||
304 | static int mt9m111_setfmt_bayer8(struct soc_camera_device *icd) | 307 | static int mt9m111_setfmt_bayer8(struct i2c_client *client) |
305 | { | 308 | { |
306 | return mt9m111_setup_pixfmt(icd, MT9M111_OUTFMT_PROCESSED_BAYER); | 309 | return mt9m111_setup_pixfmt(client, MT9M111_OUTFMT_PROCESSED_BAYER); |
307 | } | 310 | } |
308 | 311 | ||
309 | static int mt9m111_setfmt_bayer10(struct soc_camera_device *icd) | 312 | static int mt9m111_setfmt_bayer10(struct i2c_client *client) |
310 | { | 313 | { |
311 | return mt9m111_setup_pixfmt(icd, MT9M111_OUTFMT_BYPASS_IFP); | 314 | return mt9m111_setup_pixfmt(client, MT9M111_OUTFMT_BYPASS_IFP); |
312 | } | 315 | } |
313 | 316 | ||
314 | static int mt9m111_setfmt_rgb565(struct soc_camera_device *icd) | 317 | static int mt9m111_setfmt_rgb565(struct i2c_client *client) |
315 | { | 318 | { |
316 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); | 319 | struct mt9m111 *mt9m111 = to_mt9m111(client); |
317 | struct mt9m111 *mt9m111 = i2c_get_clientdata(client); | ||
318 | int val = 0; | 320 | int val = 0; |
319 | 321 | ||
320 | if (mt9m111->swap_rgb_red_blue) | 322 | if (mt9m111->swap_rgb_red_blue) |
@@ -323,13 +325,12 @@ static int mt9m111_setfmt_rgb565(struct soc_camera_device *icd) | |||
323 | val |= MT9M111_OUTFMT_SWAP_RGB_EVEN; | 325 | val |= MT9M111_OUTFMT_SWAP_RGB_EVEN; |
324 | val |= MT9M111_OUTFMT_RGB | MT9M111_OUTFMT_RGB565; | 326 | val |= MT9M111_OUTFMT_RGB | MT9M111_OUTFMT_RGB565; |
325 | 327 | ||
326 | return mt9m111_setup_pixfmt(icd, val); | 328 | return mt9m111_setup_pixfmt(client, val); |
327 | } | 329 | } |
328 | 330 | ||
329 | static int mt9m111_setfmt_rgb555(struct soc_camera_device *icd) | 331 | static int mt9m111_setfmt_rgb555(struct i2c_client *client) |
330 | { | 332 | { |
331 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); | 333 | struct mt9m111 *mt9m111 = to_mt9m111(client); |
332 | struct mt9m111 *mt9m111 = i2c_get_clientdata(client); | ||
333 | int val = 0; | 334 | int val = 0; |
334 | 335 | ||
335 | if (mt9m111->swap_rgb_red_blue) | 336 | if (mt9m111->swap_rgb_red_blue) |
@@ -338,13 +339,12 @@ static int mt9m111_setfmt_rgb555(struct soc_camera_device *icd) | |||
338 | val |= MT9M111_OUTFMT_SWAP_RGB_EVEN; | 339 | val |= MT9M111_OUTFMT_SWAP_RGB_EVEN; |
339 | val |= MT9M111_OUTFMT_RGB | MT9M111_OUTFMT_RGB555; | 340 | val |= MT9M111_OUTFMT_RGB | MT9M111_OUTFMT_RGB555; |
340 | 341 | ||
341 | return mt9m111_setup_pixfmt(icd, val); | 342 | return mt9m111_setup_pixfmt(client, val); |
342 | } | 343 | } |
343 | 344 | ||
344 | static int mt9m111_setfmt_yuv(struct soc_camera_device *icd) | 345 | static int mt9m111_setfmt_yuv(struct i2c_client *client) |
345 | { | 346 | { |
346 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); | 347 | struct mt9m111 *mt9m111 = to_mt9m111(client); |
347 | struct mt9m111 *mt9m111 = i2c_get_clientdata(client); | ||
348 | int val = 0; | 348 | int val = 0; |
349 | 349 | ||
350 | if (mt9m111->swap_yuv_cb_cr) | 350 | if (mt9m111->swap_yuv_cb_cr) |
@@ -352,52 +352,22 @@ static int mt9m111_setfmt_yuv(struct soc_camera_device *icd) | |||
352 | if (mt9m111->swap_yuv_y_chromas) | 352 | if (mt9m111->swap_yuv_y_chromas) |
353 | val |= MT9M111_OUTFMT_SWAP_YCbCr_C_Y; | 353 | val |= MT9M111_OUTFMT_SWAP_YCbCr_C_Y; |
354 | 354 | ||
355 | return mt9m111_setup_pixfmt(icd, val); | 355 | return mt9m111_setup_pixfmt(client, val); |
356 | } | 356 | } |
357 | 357 | ||
358 | static int mt9m111_enable(struct soc_camera_device *icd) | 358 | static int mt9m111_enable(struct i2c_client *client) |
359 | { | 359 | { |
360 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); | 360 | struct mt9m111 *mt9m111 = to_mt9m111(client); |
361 | struct soc_camera_link *icl = to_soc_camera_link(icd); | ||
362 | struct mt9m111 *mt9m111 = i2c_get_clientdata(client); | ||
363 | int ret; | 361 | int ret; |
364 | 362 | ||
365 | if (icl->power) { | ||
366 | ret = icl->power(&client->dev, 1); | ||
367 | if (ret < 0) { | ||
368 | dev_err(icd->vdev->parent, | ||
369 | "Platform failed to power-on the camera.\n"); | ||
370 | return ret; | ||
371 | } | ||
372 | } | ||
373 | |||
374 | ret = reg_set(RESET, MT9M111_RESET_CHIP_ENABLE); | 363 | ret = reg_set(RESET, MT9M111_RESET_CHIP_ENABLE); |
375 | if (!ret) | 364 | if (!ret) |
376 | mt9m111->powered = 1; | 365 | mt9m111->powered = 1; |
377 | return ret; | 366 | return ret; |
378 | } | 367 | } |
379 | 368 | ||
380 | static int mt9m111_disable(struct soc_camera_device *icd) | 369 | static int mt9m111_reset(struct i2c_client *client) |
381 | { | ||
382 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); | ||
383 | struct soc_camera_link *icl = to_soc_camera_link(icd); | ||
384 | struct mt9m111 *mt9m111 = i2c_get_clientdata(client); | ||
385 | int ret; | ||
386 | |||
387 | ret = reg_clear(RESET, MT9M111_RESET_CHIP_ENABLE); | ||
388 | if (!ret) | ||
389 | mt9m111->powered = 0; | ||
390 | |||
391 | if (icl->power) | ||
392 | icl->power(&client->dev, 0); | ||
393 | |||
394 | return ret; | ||
395 | } | ||
396 | |||
397 | static int mt9m111_reset(struct soc_camera_device *icd) | ||
398 | { | 370 | { |
399 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); | ||
400 | struct soc_camera_link *icl = to_soc_camera_link(icd); | ||
401 | int ret; | 371 | int ret; |
402 | 372 | ||
403 | ret = reg_set(RESET, MT9M111_RESET_RESET_MODE); | 373 | ret = reg_set(RESET, MT9M111_RESET_RESET_MODE); |
@@ -407,22 +377,9 @@ static int mt9m111_reset(struct soc_camera_device *icd) | |||
407 | ret = reg_clear(RESET, MT9M111_RESET_RESET_MODE | 377 | ret = reg_clear(RESET, MT9M111_RESET_RESET_MODE |
408 | | MT9M111_RESET_RESET_SOC); | 378 | | MT9M111_RESET_RESET_SOC); |
409 | 379 | ||
410 | if (icl->reset) | ||
411 | icl->reset(&client->dev); | ||
412 | |||
413 | return ret; | 380 | return ret; |
414 | } | 381 | } |
415 | 382 | ||
416 | static int mt9m111_start_capture(struct soc_camera_device *icd) | ||
417 | { | ||
418 | return 0; | ||
419 | } | ||
420 | |||
421 | static int mt9m111_stop_capture(struct soc_camera_device *icd) | ||
422 | { | ||
423 | return 0; | ||
424 | } | ||
425 | |||
426 | static unsigned long mt9m111_query_bus_param(struct soc_camera_device *icd) | 383 | static unsigned long mt9m111_query_bus_param(struct soc_camera_device *icd) |
427 | { | 384 | { |
428 | struct soc_camera_link *icl = to_soc_camera_link(icd); | 385 | struct soc_camera_link *icl = to_soc_camera_link(icd); |
@@ -442,60 +399,59 @@ static int mt9m111_set_crop(struct soc_camera_device *icd, | |||
442 | struct v4l2_rect *rect) | 399 | struct v4l2_rect *rect) |
443 | { | 400 | { |
444 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); | 401 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
445 | struct mt9m111 *mt9m111 = i2c_get_clientdata(client); | 402 | struct mt9m111 *mt9m111 = to_mt9m111(client); |
446 | int ret; | 403 | int ret; |
447 | 404 | ||
448 | dev_dbg(&icd->dev, "%s left=%d, top=%d, width=%d, height=%d\n", | 405 | dev_dbg(&icd->dev, "%s left=%d, top=%d, width=%d, height=%d\n", |
449 | __func__, rect->left, rect->top, rect->width, | 406 | __func__, rect->left, rect->top, rect->width, |
450 | rect->height); | 407 | rect->height); |
451 | 408 | ||
452 | ret = mt9m111_setup_rect(icd, rect); | 409 | ret = mt9m111_setup_rect(client, rect); |
453 | if (!ret) | 410 | if (!ret) |
454 | mt9m111->rect = *rect; | 411 | mt9m111->rect = *rect; |
455 | return ret; | 412 | return ret; |
456 | } | 413 | } |
457 | 414 | ||
458 | static int mt9m111_set_pixfmt(struct soc_camera_device *icd, u32 pixfmt) | 415 | static int mt9m111_set_pixfmt(struct i2c_client *client, u32 pixfmt) |
459 | { | 416 | { |
460 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); | 417 | struct mt9m111 *mt9m111 = to_mt9m111(client); |
461 | struct mt9m111 *mt9m111 = i2c_get_clientdata(client); | ||
462 | int ret; | 418 | int ret; |
463 | 419 | ||
464 | switch (pixfmt) { | 420 | switch (pixfmt) { |
465 | case V4L2_PIX_FMT_SBGGR8: | 421 | case V4L2_PIX_FMT_SBGGR8: |
466 | ret = mt9m111_setfmt_bayer8(icd); | 422 | ret = mt9m111_setfmt_bayer8(client); |
467 | break; | 423 | break; |
468 | case V4L2_PIX_FMT_SBGGR16: | 424 | case V4L2_PIX_FMT_SBGGR16: |
469 | ret = mt9m111_setfmt_bayer10(icd); | 425 | ret = mt9m111_setfmt_bayer10(client); |
470 | break; | 426 | break; |
471 | case V4L2_PIX_FMT_RGB555: | 427 | case V4L2_PIX_FMT_RGB555: |
472 | ret = mt9m111_setfmt_rgb555(icd); | 428 | ret = mt9m111_setfmt_rgb555(client); |
473 | break; | 429 | break; |
474 | case V4L2_PIX_FMT_RGB565: | 430 | case V4L2_PIX_FMT_RGB565: |
475 | ret = mt9m111_setfmt_rgb565(icd); | 431 | ret = mt9m111_setfmt_rgb565(client); |
476 | break; | 432 | break; |
477 | case V4L2_PIX_FMT_UYVY: | 433 | case V4L2_PIX_FMT_UYVY: |
478 | mt9m111->swap_yuv_y_chromas = 0; | 434 | mt9m111->swap_yuv_y_chromas = 0; |
479 | mt9m111->swap_yuv_cb_cr = 0; | 435 | mt9m111->swap_yuv_cb_cr = 0; |
480 | ret = mt9m111_setfmt_yuv(icd); | 436 | ret = mt9m111_setfmt_yuv(client); |
481 | break; | 437 | break; |
482 | case V4L2_PIX_FMT_VYUY: | 438 | case V4L2_PIX_FMT_VYUY: |
483 | mt9m111->swap_yuv_y_chromas = 0; | 439 | mt9m111->swap_yuv_y_chromas = 0; |
484 | mt9m111->swap_yuv_cb_cr = 1; | 440 | mt9m111->swap_yuv_cb_cr = 1; |
485 | ret = mt9m111_setfmt_yuv(icd); | 441 | ret = mt9m111_setfmt_yuv(client); |
486 | break; | 442 | break; |
487 | case V4L2_PIX_FMT_YUYV: | 443 | case V4L2_PIX_FMT_YUYV: |
488 | mt9m111->swap_yuv_y_chromas = 1; | 444 | mt9m111->swap_yuv_y_chromas = 1; |
489 | mt9m111->swap_yuv_cb_cr = 0; | 445 | mt9m111->swap_yuv_cb_cr = 0; |
490 | ret = mt9m111_setfmt_yuv(icd); | 446 | ret = mt9m111_setfmt_yuv(client); |
491 | break; | 447 | break; |
492 | case V4L2_PIX_FMT_YVYU: | 448 | case V4L2_PIX_FMT_YVYU: |
493 | mt9m111->swap_yuv_y_chromas = 1; | 449 | mt9m111->swap_yuv_y_chromas = 1; |
494 | mt9m111->swap_yuv_cb_cr = 1; | 450 | mt9m111->swap_yuv_cb_cr = 1; |
495 | ret = mt9m111_setfmt_yuv(icd); | 451 | ret = mt9m111_setfmt_yuv(client); |
496 | break; | 452 | break; |
497 | default: | 453 | default: |
498 | dev_err(&icd->dev, "Pixel format not handled : %x\n", pixfmt); | 454 | dev_err(&client->dev, "Pixel format not handled : %x\n", pixfmt); |
499 | ret = -EINVAL; | 455 | ret = -EINVAL; |
500 | } | 456 | } |
501 | 457 | ||
@@ -505,11 +461,10 @@ static int mt9m111_set_pixfmt(struct soc_camera_device *icd, u32 pixfmt) | |||
505 | return ret; | 461 | return ret; |
506 | } | 462 | } |
507 | 463 | ||
508 | static int mt9m111_set_fmt(struct soc_camera_device *icd, | 464 | static int mt9m111_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) |
509 | struct v4l2_format *f) | ||
510 | { | 465 | { |
511 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); | 466 | struct i2c_client *client = sd->priv; |
512 | struct mt9m111 *mt9m111 = i2c_get_clientdata(client); | 467 | struct mt9m111 *mt9m111 = to_mt9m111(client); |
513 | struct v4l2_pix_format *pix = &f->fmt.pix; | 468 | struct v4l2_pix_format *pix = &f->fmt.pix; |
514 | struct v4l2_rect rect = { | 469 | struct v4l2_rect rect = { |
515 | .left = mt9m111->rect.left, | 470 | .left = mt9m111->rect.left, |
@@ -519,20 +474,19 @@ static int mt9m111_set_fmt(struct soc_camera_device *icd, | |||
519 | }; | 474 | }; |
520 | int ret; | 475 | int ret; |
521 | 476 | ||
522 | dev_dbg(&icd->dev, "%s fmt=%x left=%d, top=%d, width=%d, height=%d\n", | 477 | dev_dbg(&client->dev, "%s fmt=%x left=%d, top=%d, width=%d, height=%d\n", |
523 | __func__, pix->pixelformat, rect.left, rect.top, rect.width, | 478 | __func__, pix->pixelformat, rect.left, rect.top, rect.width, |
524 | rect.height); | 479 | rect.height); |
525 | 480 | ||
526 | ret = mt9m111_setup_rect(icd, &rect); | 481 | ret = mt9m111_setup_rect(client, &rect); |
527 | if (!ret) | 482 | if (!ret) |
528 | ret = mt9m111_set_pixfmt(icd, pix->pixelformat); | 483 | ret = mt9m111_set_pixfmt(client, pix->pixelformat); |
529 | if (!ret) | 484 | if (!ret) |
530 | mt9m111->rect = rect; | 485 | mt9m111->rect = rect; |
531 | return ret; | 486 | return ret; |
532 | } | 487 | } |
533 | 488 | ||
534 | static int mt9m111_try_fmt(struct soc_camera_device *icd, | 489 | static int mt9m111_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) |
535 | struct v4l2_format *f) | ||
536 | { | 490 | { |
537 | struct v4l2_pix_format *pix = &f->fmt.pix; | 491 | struct v4l2_pix_format *pix = &f->fmt.pix; |
538 | 492 | ||
@@ -544,11 +498,11 @@ static int mt9m111_try_fmt(struct soc_camera_device *icd, | |||
544 | return 0; | 498 | return 0; |
545 | } | 499 | } |
546 | 500 | ||
547 | static int mt9m111_get_chip_id(struct soc_camera_device *icd, | 501 | static int mt9m111_g_chip_ident(struct v4l2_subdev *sd, |
548 | struct v4l2_dbg_chip_ident *id) | 502 | struct v4l2_dbg_chip_ident *id) |
549 | { | 503 | { |
550 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); | 504 | struct i2c_client *client = sd->priv; |
551 | struct mt9m111 *mt9m111 = i2c_get_clientdata(client); | 505 | struct mt9m111 *mt9m111 = to_mt9m111(client); |
552 | 506 | ||
553 | if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR) | 507 | if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR) |
554 | return -EINVAL; | 508 | return -EINVAL; |
@@ -563,10 +517,10 @@ static int mt9m111_get_chip_id(struct soc_camera_device *icd, | |||
563 | } | 517 | } |
564 | 518 | ||
565 | #ifdef CONFIG_VIDEO_ADV_DEBUG | 519 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
566 | static int mt9m111_get_register(struct soc_camera_device *icd, | 520 | static int mt9m111_g_register(struct v4l2_subdev *sd, |
567 | struct v4l2_dbg_register *reg) | 521 | struct v4l2_dbg_register *reg) |
568 | { | 522 | { |
569 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); | 523 | struct i2c_client *client = sd->priv; |
570 | int val; | 524 | int val; |
571 | 525 | ||
572 | if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x2ff) | 526 | if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x2ff) |
@@ -584,10 +538,10 @@ static int mt9m111_get_register(struct soc_camera_device *icd, | |||
584 | return 0; | 538 | return 0; |
585 | } | 539 | } |
586 | 540 | ||
587 | static int mt9m111_set_register(struct soc_camera_device *icd, | 541 | static int mt9m111_s_register(struct v4l2_subdev *sd, |
588 | struct v4l2_dbg_register *reg) | 542 | struct v4l2_dbg_register *reg) |
589 | { | 543 | { |
590 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); | 544 | struct i2c_client *client = sd->priv; |
591 | 545 | ||
592 | if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x2ff) | 546 | if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x2ff) |
593 | return -EINVAL; | 547 | return -EINVAL; |
@@ -639,41 +593,24 @@ static const struct v4l2_queryctrl mt9m111_controls[] = { | |||
639 | } | 593 | } |
640 | }; | 594 | }; |
641 | 595 | ||
642 | static int mt9m111_get_control(struct soc_camera_device *, | ||
643 | struct v4l2_control *); | ||
644 | static int mt9m111_set_control(struct soc_camera_device *, | ||
645 | struct v4l2_control *); | ||
646 | static int mt9m111_resume(struct soc_camera_device *icd); | 596 | static int mt9m111_resume(struct soc_camera_device *icd); |
647 | static int mt9m111_init(struct soc_camera_device *icd); | 597 | static int mt9m111_init(struct soc_camera_device *icd); |
648 | static int mt9m111_release(struct soc_camera_device *icd); | 598 | static int mt9m111_release(struct soc_camera_device *icd); |
649 | 599 | ||
650 | static struct soc_camera_ops mt9m111_ops = { | 600 | static struct soc_camera_ops mt9m111_ops = { |
651 | .owner = THIS_MODULE, | ||
652 | .init = mt9m111_init, | 601 | .init = mt9m111_init, |
653 | .resume = mt9m111_resume, | 602 | .resume = mt9m111_resume, |
654 | .release = mt9m111_release, | 603 | .release = mt9m111_release, |
655 | .start_capture = mt9m111_start_capture, | ||
656 | .stop_capture = mt9m111_stop_capture, | ||
657 | .set_crop = mt9m111_set_crop, | 604 | .set_crop = mt9m111_set_crop, |
658 | .set_fmt = mt9m111_set_fmt, | ||
659 | .try_fmt = mt9m111_try_fmt, | ||
660 | .query_bus_param = mt9m111_query_bus_param, | 605 | .query_bus_param = mt9m111_query_bus_param, |
661 | .set_bus_param = mt9m111_set_bus_param, | 606 | .set_bus_param = mt9m111_set_bus_param, |
662 | .controls = mt9m111_controls, | 607 | .controls = mt9m111_controls, |
663 | .num_controls = ARRAY_SIZE(mt9m111_controls), | 608 | .num_controls = ARRAY_SIZE(mt9m111_controls), |
664 | .get_control = mt9m111_get_control, | ||
665 | .set_control = mt9m111_set_control, | ||
666 | .get_chip_id = mt9m111_get_chip_id, | ||
667 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
668 | .get_register = mt9m111_get_register, | ||
669 | .set_register = mt9m111_set_register, | ||
670 | #endif | ||
671 | }; | 609 | }; |
672 | 610 | ||
673 | static int mt9m111_set_flip(struct soc_camera_device *icd, int flip, int mask) | 611 | static int mt9m111_set_flip(struct i2c_client *client, int flip, int mask) |
674 | { | 612 | { |
675 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); | 613 | struct mt9m111 *mt9m111 = to_mt9m111(client); |
676 | struct mt9m111 *mt9m111 = i2c_get_clientdata(client); | ||
677 | int ret; | 614 | int ret; |
678 | 615 | ||
679 | if (mt9m111->context == HIGHPOWER) { | 616 | if (mt9m111->context == HIGHPOWER) { |
@@ -691,9 +628,8 @@ static int mt9m111_set_flip(struct soc_camera_device *icd, int flip, int mask) | |||
691 | return ret; | 628 | return ret; |
692 | } | 629 | } |
693 | 630 | ||
694 | static int mt9m111_get_global_gain(struct soc_camera_device *icd) | 631 | static int mt9m111_get_global_gain(struct i2c_client *client) |
695 | { | 632 | { |
696 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); | ||
697 | int data; | 633 | int data; |
698 | 634 | ||
699 | data = reg_read(GLOBAL_GAIN); | 635 | data = reg_read(GLOBAL_GAIN); |
@@ -703,9 +639,9 @@ static int mt9m111_get_global_gain(struct soc_camera_device *icd) | |||
703 | return data; | 639 | return data; |
704 | } | 640 | } |
705 | 641 | ||
706 | static int mt9m111_set_global_gain(struct soc_camera_device *icd, int gain) | 642 | static int mt9m111_set_global_gain(struct i2c_client *client, int gain) |
707 | { | 643 | { |
708 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); | 644 | struct soc_camera_device *icd = client->dev.platform_data; |
709 | u16 val; | 645 | u16 val; |
710 | 646 | ||
711 | if (gain > 63 * 2 * 2) | 647 | if (gain > 63 * 2 * 2) |
@@ -722,10 +658,9 @@ static int mt9m111_set_global_gain(struct soc_camera_device *icd, int gain) | |||
722 | return reg_write(GLOBAL_GAIN, val); | 658 | return reg_write(GLOBAL_GAIN, val); |
723 | } | 659 | } |
724 | 660 | ||
725 | static int mt9m111_set_autoexposure(struct soc_camera_device *icd, int on) | 661 | static int mt9m111_set_autoexposure(struct i2c_client *client, int on) |
726 | { | 662 | { |
727 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); | 663 | struct mt9m111 *mt9m111 = to_mt9m111(client); |
728 | struct mt9m111 *mt9m111 = i2c_get_clientdata(client); | ||
729 | int ret; | 664 | int ret; |
730 | 665 | ||
731 | if (on) | 666 | if (on) |
@@ -739,10 +674,9 @@ static int mt9m111_set_autoexposure(struct soc_camera_device *icd, int on) | |||
739 | return ret; | 674 | return ret; |
740 | } | 675 | } |
741 | 676 | ||
742 | static int mt9m111_set_autowhitebalance(struct soc_camera_device *icd, int on) | 677 | static int mt9m111_set_autowhitebalance(struct i2c_client *client, int on) |
743 | { | 678 | { |
744 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); | 679 | struct mt9m111 *mt9m111 = to_mt9m111(client); |
745 | struct mt9m111 *mt9m111 = i2c_get_clientdata(client); | ||
746 | int ret; | 680 | int ret; |
747 | 681 | ||
748 | if (on) | 682 | if (on) |
@@ -756,11 +690,10 @@ static int mt9m111_set_autowhitebalance(struct soc_camera_device *icd, int on) | |||
756 | return ret; | 690 | return ret; |
757 | } | 691 | } |
758 | 692 | ||
759 | static int mt9m111_get_control(struct soc_camera_device *icd, | 693 | static int mt9m111_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) |
760 | struct v4l2_control *ctrl) | ||
761 | { | 694 | { |
762 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); | 695 | struct i2c_client *client = sd->priv; |
763 | struct mt9m111 *mt9m111 = i2c_get_clientdata(client); | 696 | struct mt9m111 *mt9m111 = to_mt9m111(client); |
764 | int data; | 697 | int data; |
765 | 698 | ||
766 | switch (ctrl->id) { | 699 | switch (ctrl->id) { |
@@ -785,7 +718,7 @@ static int mt9m111_get_control(struct soc_camera_device *icd, | |||
785 | ctrl->value = !!(data & MT9M111_RMB_MIRROR_COLS); | 718 | ctrl->value = !!(data & MT9M111_RMB_MIRROR_COLS); |
786 | break; | 719 | break; |
787 | case V4L2_CID_GAIN: | 720 | case V4L2_CID_GAIN: |
788 | data = mt9m111_get_global_gain(icd); | 721 | data = mt9m111_get_global_gain(client); |
789 | if (data < 0) | 722 | if (data < 0) |
790 | return data; | 723 | return data; |
791 | ctrl->value = data; | 724 | ctrl->value = data; |
@@ -800,38 +733,36 @@ static int mt9m111_get_control(struct soc_camera_device *icd, | |||
800 | return 0; | 733 | return 0; |
801 | } | 734 | } |
802 | 735 | ||
803 | static int mt9m111_set_control(struct soc_camera_device *icd, | 736 | static int mt9m111_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) |
804 | struct v4l2_control *ctrl) | ||
805 | { | 737 | { |
806 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); | 738 | struct i2c_client *client = sd->priv; |
807 | struct mt9m111 *mt9m111 = i2c_get_clientdata(client); | 739 | struct mt9m111 *mt9m111 = to_mt9m111(client); |
808 | const struct v4l2_queryctrl *qctrl; | 740 | const struct v4l2_queryctrl *qctrl; |
809 | int ret; | 741 | int ret; |
810 | 742 | ||
811 | qctrl = soc_camera_find_qctrl(&mt9m111_ops, ctrl->id); | 743 | qctrl = soc_camera_find_qctrl(&mt9m111_ops, ctrl->id); |
812 | |||
813 | if (!qctrl) | 744 | if (!qctrl) |
814 | return -EINVAL; | 745 | return -EINVAL; |
815 | 746 | ||
816 | switch (ctrl->id) { | 747 | switch (ctrl->id) { |
817 | case V4L2_CID_VFLIP: | 748 | case V4L2_CID_VFLIP: |
818 | mt9m111->vflip = ctrl->value; | 749 | mt9m111->vflip = ctrl->value; |
819 | ret = mt9m111_set_flip(icd, ctrl->value, | 750 | ret = mt9m111_set_flip(client, ctrl->value, |
820 | MT9M111_RMB_MIRROR_ROWS); | 751 | MT9M111_RMB_MIRROR_ROWS); |
821 | break; | 752 | break; |
822 | case V4L2_CID_HFLIP: | 753 | case V4L2_CID_HFLIP: |
823 | mt9m111->hflip = ctrl->value; | 754 | mt9m111->hflip = ctrl->value; |
824 | ret = mt9m111_set_flip(icd, ctrl->value, | 755 | ret = mt9m111_set_flip(client, ctrl->value, |
825 | MT9M111_RMB_MIRROR_COLS); | 756 | MT9M111_RMB_MIRROR_COLS); |
826 | break; | 757 | break; |
827 | case V4L2_CID_GAIN: | 758 | case V4L2_CID_GAIN: |
828 | ret = mt9m111_set_global_gain(icd, ctrl->value); | 759 | ret = mt9m111_set_global_gain(client, ctrl->value); |
829 | break; | 760 | break; |
830 | case V4L2_CID_EXPOSURE_AUTO: | 761 | case V4L2_CID_EXPOSURE_AUTO: |
831 | ret = mt9m111_set_autoexposure(icd, ctrl->value); | 762 | ret = mt9m111_set_autoexposure(client, ctrl->value); |
832 | break; | 763 | break; |
833 | case V4L2_CID_AUTO_WHITE_BALANCE: | 764 | case V4L2_CID_AUTO_WHITE_BALANCE: |
834 | ret = mt9m111_set_autowhitebalance(icd, ctrl->value); | 765 | ret = mt9m111_set_autowhitebalance(client, ctrl->value); |
835 | break; | 766 | break; |
836 | default: | 767 | default: |
837 | ret = -EINVAL; | 768 | ret = -EINVAL; |
@@ -840,34 +771,34 @@ static int mt9m111_set_control(struct soc_camera_device *icd, | |||
840 | return ret; | 771 | return ret; |
841 | } | 772 | } |
842 | 773 | ||
843 | static int mt9m111_restore_state(struct soc_camera_device *icd) | 774 | static int mt9m111_restore_state(struct i2c_client *client) |
844 | { | 775 | { |
845 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); | 776 | struct mt9m111 *mt9m111 = to_mt9m111(client); |
846 | struct mt9m111 *mt9m111 = i2c_get_clientdata(client); | 777 | struct soc_camera_device *icd = client->dev.platform_data; |
847 | 778 | ||
848 | mt9m111_set_context(icd, mt9m111->context); | 779 | mt9m111_set_context(client, mt9m111->context); |
849 | mt9m111_set_pixfmt(icd, mt9m111->pixfmt); | 780 | mt9m111_set_pixfmt(client, mt9m111->pixfmt); |
850 | mt9m111_setup_rect(icd, &mt9m111->rect); | 781 | mt9m111_setup_rect(client, &mt9m111->rect); |
851 | mt9m111_set_flip(icd, mt9m111->hflip, MT9M111_RMB_MIRROR_COLS); | 782 | mt9m111_set_flip(client, mt9m111->hflip, MT9M111_RMB_MIRROR_COLS); |
852 | mt9m111_set_flip(icd, mt9m111->vflip, MT9M111_RMB_MIRROR_ROWS); | 783 | mt9m111_set_flip(client, mt9m111->vflip, MT9M111_RMB_MIRROR_ROWS); |
853 | mt9m111_set_global_gain(icd, icd->gain); | 784 | mt9m111_set_global_gain(client, icd->gain); |
854 | mt9m111_set_autoexposure(icd, mt9m111->autoexposure); | 785 | mt9m111_set_autoexposure(client, mt9m111->autoexposure); |
855 | mt9m111_set_autowhitebalance(icd, mt9m111->autowhitebalance); | 786 | mt9m111_set_autowhitebalance(client, mt9m111->autowhitebalance); |
856 | return 0; | 787 | return 0; |
857 | } | 788 | } |
858 | 789 | ||
859 | static int mt9m111_resume(struct soc_camera_device *icd) | 790 | static int mt9m111_resume(struct soc_camera_device *icd) |
860 | { | 791 | { |
861 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); | 792 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
862 | struct mt9m111 *mt9m111 = i2c_get_clientdata(client); | 793 | struct mt9m111 *mt9m111 = to_mt9m111(client); |
863 | int ret = 0; | 794 | int ret = 0; |
864 | 795 | ||
865 | if (mt9m111->powered) { | 796 | if (mt9m111->powered) { |
866 | ret = mt9m111_enable(icd); | 797 | ret = mt9m111_enable(client); |
867 | if (!ret) | 798 | if (!ret) |
868 | ret = mt9m111_reset(icd); | 799 | ret = mt9m111_reset(client); |
869 | if (!ret) | 800 | if (!ret) |
870 | ret = mt9m111_restore_state(icd); | 801 | ret = mt9m111_restore_state(client); |
871 | } | 802 | } |
872 | return ret; | 803 | return ret; |
873 | } | 804 | } |
@@ -875,17 +806,17 @@ static int mt9m111_resume(struct soc_camera_device *icd) | |||
875 | static int mt9m111_init(struct soc_camera_device *icd) | 806 | static int mt9m111_init(struct soc_camera_device *icd) |
876 | { | 807 | { |
877 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); | 808 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
878 | struct mt9m111 *mt9m111 = i2c_get_clientdata(client); | 809 | struct mt9m111 *mt9m111 = to_mt9m111(client); |
879 | int ret; | 810 | int ret; |
880 | 811 | ||
881 | mt9m111->context = HIGHPOWER; | 812 | mt9m111->context = HIGHPOWER; |
882 | ret = mt9m111_enable(icd); | 813 | ret = mt9m111_enable(client); |
883 | if (!ret) | 814 | if (!ret) |
884 | ret = mt9m111_reset(icd); | 815 | ret = mt9m111_reset(client); |
885 | if (!ret) | 816 | if (!ret) |
886 | ret = mt9m111_set_context(icd, mt9m111->context); | 817 | ret = mt9m111_set_context(client, mt9m111->context); |
887 | if (!ret) | 818 | if (!ret) |
888 | ret = mt9m111_set_autoexposure(icd, mt9m111->autoexposure); | 819 | ret = mt9m111_set_autoexposure(client, mt9m111->autoexposure); |
889 | if (ret) | 820 | if (ret) |
890 | dev_err(&icd->dev, "mt9m11x init failed: %d\n", ret); | 821 | dev_err(&icd->dev, "mt9m11x init failed: %d\n", ret); |
891 | return ret; | 822 | return ret; |
@@ -893,9 +824,14 @@ static int mt9m111_init(struct soc_camera_device *icd) | |||
893 | 824 | ||
894 | static int mt9m111_release(struct soc_camera_device *icd) | 825 | static int mt9m111_release(struct soc_camera_device *icd) |
895 | { | 826 | { |
827 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); | ||
828 | struct mt9m111 *mt9m111 = to_mt9m111(client); | ||
896 | int ret; | 829 | int ret; |
897 | 830 | ||
898 | ret = mt9m111_disable(icd); | 831 | ret = reg_clear(RESET, MT9M111_RESET_CHIP_ENABLE); |
832 | if (!ret) | ||
833 | mt9m111->powered = 0; | ||
834 | |||
899 | if (ret < 0) | 835 | if (ret < 0) |
900 | dev_err(&icd->dev, "mt9m11x release failed: %d\n", ret); | 836 | dev_err(&icd->dev, "mt9m11x release failed: %d\n", ret); |
901 | 837 | ||
@@ -909,7 +845,7 @@ static int mt9m111_release(struct soc_camera_device *icd) | |||
909 | static int mt9m111_video_probe(struct soc_camera_device *icd, | 845 | static int mt9m111_video_probe(struct soc_camera_device *icd, |
910 | struct i2c_client *client) | 846 | struct i2c_client *client) |
911 | { | 847 | { |
912 | struct mt9m111 *mt9m111 = i2c_get_clientdata(client); | 848 | struct mt9m111 *mt9m111 = to_mt9m111(client); |
913 | s32 data; | 849 | s32 data; |
914 | int ret; | 850 | int ret; |
915 | 851 | ||
@@ -921,15 +857,10 @@ static int mt9m111_video_probe(struct soc_camera_device *icd, | |||
921 | to_soc_camera_host(icd->dev.parent)->nr != icd->iface) | 857 | to_soc_camera_host(icd->dev.parent)->nr != icd->iface) |
922 | return -ENODEV; | 858 | return -ENODEV; |
923 | 859 | ||
924 | /* Switch master clock on */ | 860 | ret = mt9m111_enable(client); |
925 | ret = soc_camera_video_start(icd, &client->dev); | ||
926 | if (ret) | ||
927 | goto evstart; | ||
928 | |||
929 | ret = mt9m111_enable(icd); | ||
930 | if (ret) | 861 | if (ret) |
931 | goto ei2c; | 862 | goto ei2c; |
932 | ret = mt9m111_reset(icd); | 863 | ret = mt9m111_reset(client); |
933 | if (ret) | 864 | if (ret) |
934 | goto ei2c; | 865 | goto ei2c; |
935 | 866 | ||
@@ -961,11 +892,29 @@ static int mt9m111_video_probe(struct soc_camera_device *icd, | |||
961 | mt9m111->swap_rgb_red_blue = 1; | 892 | mt9m111->swap_rgb_red_blue = 1; |
962 | 893 | ||
963 | ei2c: | 894 | ei2c: |
964 | soc_camera_video_stop(icd); | ||
965 | evstart: | ||
966 | return ret; | 895 | return ret; |
967 | } | 896 | } |
968 | 897 | ||
898 | static struct v4l2_subdev_core_ops mt9m111_subdev_core_ops = { | ||
899 | .g_ctrl = mt9m111_g_ctrl, | ||
900 | .s_ctrl = mt9m111_s_ctrl, | ||
901 | .g_chip_ident = mt9m111_g_chip_ident, | ||
902 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
903 | .g_register = mt9m111_g_register, | ||
904 | .s_register = mt9m111_s_register, | ||
905 | #endif | ||
906 | }; | ||
907 | |||
908 | static struct v4l2_subdev_video_ops mt9m111_subdev_video_ops = { | ||
909 | .s_fmt = mt9m111_s_fmt, | ||
910 | .try_fmt = mt9m111_try_fmt, | ||
911 | }; | ||
912 | |||
913 | static struct v4l2_subdev_ops mt9m111_subdev_ops = { | ||
914 | .core = &mt9m111_subdev_core_ops, | ||
915 | .video = &mt9m111_subdev_video_ops, | ||
916 | }; | ||
917 | |||
969 | static int mt9m111_probe(struct i2c_client *client, | 918 | static int mt9m111_probe(struct i2c_client *client, |
970 | const struct i2c_device_id *did) | 919 | const struct i2c_device_id *did) |
971 | { | 920 | { |
@@ -996,7 +945,7 @@ static int mt9m111_probe(struct i2c_client *client, | |||
996 | if (!mt9m111) | 945 | if (!mt9m111) |
997 | return -ENOMEM; | 946 | return -ENOMEM; |
998 | 947 | ||
999 | i2c_set_clientdata(client, mt9m111); | 948 | v4l2_i2c_subdev_init(&mt9m111->subdev, client, &mt9m111_subdev_ops); |
1000 | 949 | ||
1001 | /* Second stage probe - when a capture adapter is there */ | 950 | /* Second stage probe - when a capture adapter is there */ |
1002 | icd->ops = &mt9m111_ops; | 951 | icd->ops = &mt9m111_ops; |
@@ -1022,7 +971,7 @@ static int mt9m111_probe(struct i2c_client *client, | |||
1022 | 971 | ||
1023 | static int mt9m111_remove(struct i2c_client *client) | 972 | static int mt9m111_remove(struct i2c_client *client) |
1024 | { | 973 | { |
1025 | struct mt9m111 *mt9m111 = i2c_get_clientdata(client); | 974 | struct mt9m111 *mt9m111 = to_mt9m111(client); |
1026 | struct soc_camera_device *icd = client->dev.platform_data; | 975 | struct soc_camera_device *icd = client->dev.platform_data; |
1027 | 976 | ||
1028 | icd->ops = NULL; | 977 | icd->ops = NULL; |