aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/ov7670.c
diff options
context:
space:
mode:
authorHans Verkuil <hverkuil@xs4all.nl>2009-03-18 12:01:06 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-03-30 11:43:30 -0400
commit14386c2b7793652a656021a3345cff3b0f6771f9 (patch)
tree86c85efca5742e5b2e23484c2bcb915ce9019e31 /drivers/media/video/ov7670.c
parent2da9479aaa331bdfaadab0d14f75fd76bfa5e56a (diff)
V4L/DVB (11113): ov7670: convert to v4l2_subdev
Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl> Acked-by: Jonathan Corbet <corbet@lwn.net> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/ov7670.c')
-rw-r--r--drivers/media/video/ov7670.c376
1 files changed, 180 insertions, 196 deletions
diff --git a/drivers/media/video/ov7670.c b/drivers/media/video/ov7670.c
index 003120c07482..78bd430716c8 100644
--- a/drivers/media/video/ov7670.c
+++ b/drivers/media/video/ov7670.c
@@ -12,18 +12,22 @@
12 */ 12 */
13#include <linux/init.h> 13#include <linux/init.h>
14#include <linux/module.h> 14#include <linux/module.h>
15#include <linux/slab.h> 15#include <linux/i2c.h>
16#include <linux/delay.h> 16#include <linux/delay.h>
17#include <linux/videodev2.h> 17#include <linux/videodev2.h>
18#include <media/v4l2-common.h> 18#include <media/v4l2-device.h>
19#include <media/v4l2-chip-ident.h> 19#include <media/v4l2-chip-ident.h>
20#include <linux/i2c.h> 20#include <media/v4l2-i2c-drv-legacy.h>
21 21
22 22
23MODULE_AUTHOR("Jonathan Corbet <corbet@lwn.net>"); 23MODULE_AUTHOR("Jonathan Corbet <corbet@lwn.net>");
24MODULE_DESCRIPTION("A low-level driver for OmniVision ov7670 sensors"); 24MODULE_DESCRIPTION("A low-level driver for OmniVision ov7670 sensors");
25MODULE_LICENSE("GPL"); 25MODULE_LICENSE("GPL");
26 26
27static int debug;
28module_param(debug, bool, 0644);
29MODULE_PARM_DESC(debug, "Debug level (0-1)");
30
27/* 31/*
28 * Basic window sizes. These probably belong somewhere more globally 32 * Basic window sizes. These probably belong somewhere more globally
29 * useful. 33 * useful.
@@ -189,11 +193,16 @@ MODULE_LICENSE("GPL");
189 */ 193 */
190struct ov7670_format_struct; /* coming later */ 194struct ov7670_format_struct; /* coming later */
191struct ov7670_info { 195struct ov7670_info {
196 struct v4l2_subdev sd;
192 struct ov7670_format_struct *fmt; /* Current format */ 197 struct ov7670_format_struct *fmt; /* Current format */
193 unsigned char sat; /* Saturation value */ 198 unsigned char sat; /* Saturation value */
194 int hue; /* Hue value */ 199 int hue; /* Hue value */
195}; 200};
196 201
202static inline struct ov7670_info *to_state(struct v4l2_subdev *sd)
203{
204 return container_of(sd, struct ov7670_info, sd);
205}
197 206
198 207
199 208
@@ -400,24 +409,27 @@ static struct regval_list ov7670_fmt_raw[] = {
400 * Low-level register I/O. 409 * Low-level register I/O.
401 */ 410 */
402 411
403static int ov7670_read(struct i2c_client *c, unsigned char reg, 412static int ov7670_read(struct v4l2_subdev *sd, unsigned char reg,
404 unsigned char *value) 413 unsigned char *value)
405{ 414{
415 struct i2c_client *client = v4l2_get_subdevdata(sd);
406 int ret; 416 int ret;
407 417
408 ret = i2c_smbus_read_byte_data(c, reg); 418 ret = i2c_smbus_read_byte_data(client, reg);
409 if (ret >= 0) { 419 if (ret >= 0) {
410 *value = (unsigned char) ret; 420 *value = (unsigned char)ret;
411 ret = 0; 421 ret = 0;
412 } 422 }
413 return ret; 423 return ret;
414} 424}
415 425
416 426
417static int ov7670_write(struct i2c_client *c, unsigned char reg, 427static int ov7670_write(struct v4l2_subdev *sd, unsigned char reg,
418 unsigned char value) 428 unsigned char value)
419{ 429{
420 int ret = i2c_smbus_write_byte_data(c, reg, value); 430 struct i2c_client *client = v4l2_get_subdevdata(sd);
431 int ret = i2c_smbus_write_byte_data(client, reg, value);
432
421 if (reg == REG_COM7 && (value & COM7_RESET)) 433 if (reg == REG_COM7 && (value & COM7_RESET))
422 msleep(2); /* Wait for reset to run */ 434 msleep(2); /* Wait for reset to run */
423 return ret; 435 return ret;
@@ -427,10 +439,10 @@ static int ov7670_write(struct i2c_client *c, unsigned char reg,
427/* 439/*
428 * Write a list of register settings; ff/ff stops the process. 440 * Write a list of register settings; ff/ff stops the process.
429 */ 441 */
430static int ov7670_write_array(struct i2c_client *c, struct regval_list *vals) 442static int ov7670_write_array(struct v4l2_subdev *sd, struct regval_list *vals)
431{ 443{
432 while (vals->reg_num != 0xff || vals->value != 0xff) { 444 while (vals->reg_num != 0xff || vals->value != 0xff) {
433 int ret = ov7670_write(c, vals->reg_num, vals->value); 445 int ret = ov7670_write(sd, vals->reg_num, vals->value);
434 if (ret < 0) 446 if (ret < 0)
435 return ret; 447 return ret;
436 vals++; 448 vals++;
@@ -442,34 +454,35 @@ static int ov7670_write_array(struct i2c_client *c, struct regval_list *vals)
442/* 454/*
443 * Stuff that knows about the sensor. 455 * Stuff that knows about the sensor.
444 */ 456 */
445static void ov7670_reset(struct i2c_client *client) 457static int ov7670_reset(struct v4l2_subdev *sd, u32 val)
446{ 458{
447 ov7670_write(client, REG_COM7, COM7_RESET); 459 ov7670_write(sd, REG_COM7, COM7_RESET);
448 msleep(1); 460 msleep(1);
461 return 0;
449} 462}
450 463
451 464
452static int ov7670_init(struct i2c_client *client) 465static int ov7670_init(struct v4l2_subdev *sd, u32 val)
453{ 466{
454 return ov7670_write_array(client, ov7670_default_regs); 467 return ov7670_write_array(sd, ov7670_default_regs);
455} 468}
456 469
457 470
458 471
459static int ov7670_detect(struct i2c_client *client) 472static int ov7670_detect(struct v4l2_subdev *sd)
460{ 473{
461 unsigned char v; 474 unsigned char v;
462 int ret; 475 int ret;
463 476
464 ret = ov7670_init(client); 477 ret = ov7670_init(sd, 0);
465 if (ret < 0) 478 if (ret < 0)
466 return ret; 479 return ret;
467 ret = ov7670_read(client, REG_MIDH, &v); 480 ret = ov7670_read(sd, REG_MIDH, &v);
468 if (ret < 0) 481 if (ret < 0)
469 return ret; 482 return ret;
470 if (v != 0x7f) /* OV manuf. id. */ 483 if (v != 0x7f) /* OV manuf. id. */
471 return -ENODEV; 484 return -ENODEV;
472 ret = ov7670_read(client, REG_MIDL, &v); 485 ret = ov7670_read(sd, REG_MIDL, &v);
473 if (ret < 0) 486 if (ret < 0)
474 return ret; 487 return ret;
475 if (v != 0xa2) 488 if (v != 0xa2)
@@ -477,12 +490,12 @@ static int ov7670_detect(struct i2c_client *client)
477 /* 490 /*
478 * OK, we know we have an OmniVision chip...but which one? 491 * OK, we know we have an OmniVision chip...but which one?
479 */ 492 */
480 ret = ov7670_read(client, REG_PID, &v); 493 ret = ov7670_read(sd, REG_PID, &v);
481 if (ret < 0) 494 if (ret < 0)
482 return ret; 495 return ret;
483 if (v != 0x76) /* PID + VER = 0x76 / 0x73 */ 496 if (v != 0x76) /* PID + VER = 0x76 / 0x73 */
484 return -ENODEV; 497 return -ENODEV;
485 ret = ov7670_read(client, REG_VER, &v); 498 ret = ov7670_read(sd, REG_VER, &v);
486 if (ret < 0) 499 if (ret < 0)
487 return ret; 500 return ret;
488 if (v != 0x73) /* PID + VER = 0x76 / 0x73 */ 501 if (v != 0x73) /* PID + VER = 0x76 / 0x73 */
@@ -627,7 +640,7 @@ static struct ov7670_win_size {
627/* 640/*
628 * Store a set of start/stop values into the camera. 641 * Store a set of start/stop values into the camera.
629 */ 642 */
630static int ov7670_set_hw(struct i2c_client *client, int hstart, int hstop, 643static int ov7670_set_hw(struct v4l2_subdev *sd, int hstart, int hstop,
631 int vstart, int vstop) 644 int vstart, int vstop)
632{ 645{
633 int ret; 646 int ret;
@@ -637,26 +650,26 @@ static int ov7670_set_hw(struct i2c_client *client, int hstart, int hstop,
637 * hstart are in href[2:0], bottom 3 of hstop in href[5:3]. There is 650 * hstart are in href[2:0], bottom 3 of hstop in href[5:3]. There is
638 * a mystery "edge offset" value in the top two bits of href. 651 * a mystery "edge offset" value in the top two bits of href.
639 */ 652 */
640 ret = ov7670_write(client, REG_HSTART, (hstart >> 3) & 0xff); 653 ret = ov7670_write(sd, REG_HSTART, (hstart >> 3) & 0xff);
641 ret += ov7670_write(client, REG_HSTOP, (hstop >> 3) & 0xff); 654 ret += ov7670_write(sd, REG_HSTOP, (hstop >> 3) & 0xff);
642 ret += ov7670_read(client, REG_HREF, &v); 655 ret += ov7670_read(sd, REG_HREF, &v);
643 v = (v & 0xc0) | ((hstop & 0x7) << 3) | (hstart & 0x7); 656 v = (v & 0xc0) | ((hstop & 0x7) << 3) | (hstart & 0x7);
644 msleep(10); 657 msleep(10);
645 ret += ov7670_write(client, REG_HREF, v); 658 ret += ov7670_write(sd, REG_HREF, v);
646/* 659/*
647 * Vertical: similar arrangement, but only 10 bits. 660 * Vertical: similar arrangement, but only 10 bits.
648 */ 661 */
649 ret += ov7670_write(client, REG_VSTART, (vstart >> 2) & 0xff); 662 ret += ov7670_write(sd, REG_VSTART, (vstart >> 2) & 0xff);
650 ret += ov7670_write(client, REG_VSTOP, (vstop >> 2) & 0xff); 663 ret += ov7670_write(sd, REG_VSTOP, (vstop >> 2) & 0xff);
651 ret += ov7670_read(client, REG_VREF, &v); 664 ret += ov7670_read(sd, REG_VREF, &v);
652 v = (v & 0xf0) | ((vstop & 0x3) << 2) | (vstart & 0x3); 665 v = (v & 0xf0) | ((vstop & 0x3) << 2) | (vstart & 0x3);
653 msleep(10); 666 msleep(10);
654 ret += ov7670_write(client, REG_VREF, v); 667 ret += ov7670_write(sd, REG_VREF, v);
655 return ret; 668 return ret;
656} 669}
657 670
658 671
659static int ov7670_enum_fmt(struct i2c_client *c, struct v4l2_fmtdesc *fmt) 672static int ov7670_enum_fmt(struct v4l2_subdev *sd, struct v4l2_fmtdesc *fmt)
660{ 673{
661 struct ov7670_format_struct *ofmt; 674 struct ov7670_format_struct *ofmt;
662 675
@@ -671,7 +684,8 @@ static int ov7670_enum_fmt(struct i2c_client *c, struct v4l2_fmtdesc *fmt)
671} 684}
672 685
673 686
674static int ov7670_try_fmt(struct i2c_client *c, struct v4l2_format *fmt, 687static int ov7670_try_fmt_internal(struct v4l2_subdev *sd,
688 struct v4l2_format *fmt,
675 struct ov7670_format_struct **ret_fmt, 689 struct ov7670_format_struct **ret_fmt,
676 struct ov7670_win_size **ret_wsize) 690 struct ov7670_win_size **ret_wsize)
677{ 691{
@@ -715,18 +729,23 @@ static int ov7670_try_fmt(struct i2c_client *c, struct v4l2_format *fmt,
715 return 0; 729 return 0;
716} 730}
717 731
732static int ov7670_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
733{
734 return ov7670_try_fmt_internal(sd, fmt, NULL, NULL);
735}
736
718/* 737/*
719 * Set a format. 738 * Set a format.
720 */ 739 */
721static int ov7670_s_fmt(struct i2c_client *c, struct v4l2_format *fmt) 740static int ov7670_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
722{ 741{
723 int ret; 742 int ret;
724 struct ov7670_format_struct *ovfmt; 743 struct ov7670_format_struct *ovfmt;
725 struct ov7670_win_size *wsize; 744 struct ov7670_win_size *wsize;
726 struct ov7670_info *info = i2c_get_clientdata(c); 745 struct ov7670_info *info = to_state(sd);
727 unsigned char com7, clkrc; 746 unsigned char com7, clkrc = 0;
728 747
729 ret = ov7670_try_fmt(c, fmt, &ovfmt, &wsize); 748 ret = ov7670_try_fmt_internal(sd, fmt, &ovfmt, &wsize);
730 if (ret) 749 if (ret)
731 return ret; 750 return ret;
732 /* 751 /*
@@ -735,7 +754,7 @@ static int ov7670_s_fmt(struct i2c_client *c, struct v4l2_format *fmt)
735 * the colors. 754 * the colors.
736 */ 755 */
737 if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_RGB565) { 756 if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_RGB565) {
738 ret = ov7670_read(c, REG_CLKRC, &clkrc); 757 ret = ov7670_read(sd, REG_CLKRC, &clkrc);
739 if (ret) 758 if (ret)
740 return ret; 759 return ret;
741 } 760 }
@@ -747,20 +766,20 @@ static int ov7670_s_fmt(struct i2c_client *c, struct v4l2_format *fmt)
747 */ 766 */
748 com7 = ovfmt->regs[0].value; 767 com7 = ovfmt->regs[0].value;
749 com7 |= wsize->com7_bit; 768 com7 |= wsize->com7_bit;
750 ov7670_write(c, REG_COM7, com7); 769 ov7670_write(sd, REG_COM7, com7);
751 /* 770 /*
752 * Now write the rest of the array. Also store start/stops 771 * Now write the rest of the array. Also store start/stops
753 */ 772 */
754 ov7670_write_array(c, ovfmt->regs + 1); 773 ov7670_write_array(sd, ovfmt->regs + 1);
755 ov7670_set_hw(c, wsize->hstart, wsize->hstop, wsize->vstart, 774 ov7670_set_hw(sd, wsize->hstart, wsize->hstop, wsize->vstart,
756 wsize->vstop); 775 wsize->vstop);
757 ret = 0; 776 ret = 0;
758 if (wsize->regs) 777 if (wsize->regs)
759 ret = ov7670_write_array(c, wsize->regs); 778 ret = ov7670_write_array(sd, wsize->regs);
760 info->fmt = ovfmt; 779 info->fmt = ovfmt;
761 780
762 if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_RGB565 && ret == 0) 781 if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_RGB565 && ret == 0)
763 ret = ov7670_write(c, REG_CLKRC, clkrc); 782 ret = ov7670_write(sd, REG_CLKRC, clkrc);
764 return ret; 783 return ret;
765} 784}
766 785
@@ -768,7 +787,7 @@ static int ov7670_s_fmt(struct i2c_client *c, struct v4l2_format *fmt)
768 * Implement G/S_PARM. There is a "high quality" mode we could try 787 * Implement G/S_PARM. There is a "high quality" mode we could try
769 * to do someday; for now, we just do the frame rate tweak. 788 * to do someday; for now, we just do the frame rate tweak.
770 */ 789 */
771static int ov7670_g_parm(struct i2c_client *c, struct v4l2_streamparm *parms) 790static int ov7670_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms)
772{ 791{
773 struct v4l2_captureparm *cp = &parms->parm.capture; 792 struct v4l2_captureparm *cp = &parms->parm.capture;
774 unsigned char clkrc; 793 unsigned char clkrc;
@@ -776,7 +795,7 @@ static int ov7670_g_parm(struct i2c_client *c, struct v4l2_streamparm *parms)
776 795
777 if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) 796 if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
778 return -EINVAL; 797 return -EINVAL;
779 ret = ov7670_read(c, REG_CLKRC, &clkrc); 798 ret = ov7670_read(sd, REG_CLKRC, &clkrc);
780 if (ret < 0) 799 if (ret < 0)
781 return ret; 800 return ret;
782 memset(cp, 0, sizeof(struct v4l2_captureparm)); 801 memset(cp, 0, sizeof(struct v4l2_captureparm));
@@ -788,7 +807,7 @@ static int ov7670_g_parm(struct i2c_client *c, struct v4l2_streamparm *parms)
788 return 0; 807 return 0;
789} 808}
790 809
791static int ov7670_s_parm(struct i2c_client *c, struct v4l2_streamparm *parms) 810static int ov7670_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms)
792{ 811{
793 struct v4l2_captureparm *cp = &parms->parm.capture; 812 struct v4l2_captureparm *cp = &parms->parm.capture;
794 struct v4l2_fract *tpf = &cp->timeperframe; 813 struct v4l2_fract *tpf = &cp->timeperframe;
@@ -802,7 +821,7 @@ static int ov7670_s_parm(struct i2c_client *c, struct v4l2_streamparm *parms)
802 /* 821 /*
803 * CLKRC has a reserved bit, so let's preserve it. 822 * CLKRC has a reserved bit, so let's preserve it.
804 */ 823 */
805 ret = ov7670_read(c, REG_CLKRC, &clkrc); 824 ret = ov7670_read(sd, REG_CLKRC, &clkrc);
806 if (ret < 0) 825 if (ret < 0)
807 return ret; 826 return ret;
808 if (tpf->numerator == 0 || tpf->denominator == 0) 827 if (tpf->numerator == 0 || tpf->denominator == 0)
@@ -816,7 +835,7 @@ static int ov7670_s_parm(struct i2c_client *c, struct v4l2_streamparm *parms)
816 clkrc = (clkrc & 0x80) | div; 835 clkrc = (clkrc & 0x80) | div;
817 tpf->numerator = 1; 836 tpf->numerator = 1;
818 tpf->denominator = OV7670_FRAME_RATE/div; 837 tpf->denominator = OV7670_FRAME_RATE/div;
819 return ov7670_write(c, REG_CLKRC, clkrc); 838 return ov7670_write(sd, REG_CLKRC, clkrc);
820} 839}
821 840
822 841
@@ -829,7 +848,7 @@ static int ov7670_s_parm(struct i2c_client *c, struct v4l2_streamparm *parms)
829 848
830 849
831 850
832static int ov7670_store_cmatrix(struct i2c_client *client, 851static int ov7670_store_cmatrix(struct v4l2_subdev *sd,
833 int matrix[CMATRIX_LEN]) 852 int matrix[CMATRIX_LEN])
834{ 853{
835 int i, ret; 854 int i, ret;
@@ -839,7 +858,7 @@ static int ov7670_store_cmatrix(struct i2c_client *client,
839 * Weird crap seems to exist in the upper part of 858 * Weird crap seems to exist in the upper part of
840 * the sign bits register, so let's preserve it. 859 * the sign bits register, so let's preserve it.
841 */ 860 */
842 ret = ov7670_read(client, REG_CMATRIX_SIGN, &signbits); 861 ret = ov7670_read(sd, REG_CMATRIX_SIGN, &signbits);
843 signbits &= 0xc0; 862 signbits &= 0xc0;
844 863
845 for (i = 0; i < CMATRIX_LEN; i++) { 864 for (i = 0; i < CMATRIX_LEN; i++) {
@@ -858,9 +877,9 @@ static int ov7670_store_cmatrix(struct i2c_client *client,
858 else 877 else
859 raw = matrix[i] & 0xff; 878 raw = matrix[i] & 0xff;
860 } 879 }
861 ret += ov7670_write(client, REG_CMATRIX_BASE + i, raw); 880 ret += ov7670_write(sd, REG_CMATRIX_BASE + i, raw);
862 } 881 }
863 ret += ov7670_write(client, REG_CMATRIX_SIGN, signbits); 882 ret += ov7670_write(sd, REG_CMATRIX_SIGN, signbits);
864 return ret; 883 return ret;
865} 884}
866 885
@@ -943,29 +962,29 @@ static void ov7670_calc_cmatrix(struct ov7670_info *info,
943 962
944 963
945 964
946static int ov7670_t_sat(struct i2c_client *client, int value) 965static int ov7670_t_sat(struct v4l2_subdev *sd, int value)
947{ 966{
948 struct ov7670_info *info = i2c_get_clientdata(client); 967 struct ov7670_info *info = to_state(sd);
949 int matrix[CMATRIX_LEN]; 968 int matrix[CMATRIX_LEN];
950 int ret; 969 int ret;
951 970
952 info->sat = value; 971 info->sat = value;
953 ov7670_calc_cmatrix(info, matrix); 972 ov7670_calc_cmatrix(info, matrix);
954 ret = ov7670_store_cmatrix(client, matrix); 973 ret = ov7670_store_cmatrix(sd, matrix);
955 return ret; 974 return ret;
956} 975}
957 976
958static int ov7670_q_sat(struct i2c_client *client, __s32 *value) 977static int ov7670_q_sat(struct v4l2_subdev *sd, __s32 *value)
959{ 978{
960 struct ov7670_info *info = i2c_get_clientdata(client); 979 struct ov7670_info *info = to_state(sd);
961 980
962 *value = info->sat; 981 *value = info->sat;
963 return 0; 982 return 0;
964} 983}
965 984
966static int ov7670_t_hue(struct i2c_client *client, int value) 985static int ov7670_t_hue(struct v4l2_subdev *sd, int value)
967{ 986{
968 struct ov7670_info *info = i2c_get_clientdata(client); 987 struct ov7670_info *info = to_state(sd);
969 int matrix[CMATRIX_LEN]; 988 int matrix[CMATRIX_LEN];
970 int ret; 989 int ret;
971 990
@@ -973,14 +992,14 @@ static int ov7670_t_hue(struct i2c_client *client, int value)
973 return -EINVAL; 992 return -EINVAL;
974 info->hue = value; 993 info->hue = value;
975 ov7670_calc_cmatrix(info, matrix); 994 ov7670_calc_cmatrix(info, matrix);
976 ret = ov7670_store_cmatrix(client, matrix); 995 ret = ov7670_store_cmatrix(sd, matrix);
977 return ret; 996 return ret;
978} 997}
979 998
980 999
981static int ov7670_q_hue(struct i2c_client *client, __s32 *value) 1000static int ov7670_q_hue(struct v4l2_subdev *sd, __s32 *value)
982{ 1001{
983 struct ov7670_info *info = i2c_get_clientdata(client); 1002 struct ov7670_info *info = to_state(sd);
984 1003
985 *value = info->hue; 1004 *value = info->hue;
986 return 0; 1005 return 0;
@@ -994,8 +1013,7 @@ static unsigned char ov7670_sm_to_abs(unsigned char v)
994{ 1013{
995 if ((v & 0x80) == 0) 1014 if ((v & 0x80) == 0)
996 return v + 128; 1015 return v + 128;
997 else 1016 return 128 - (v & 0x7f);
998 return 128 - (v & 0x7f);
999} 1017}
1000 1018
1001 1019
@@ -1003,105 +1021,104 @@ static unsigned char ov7670_abs_to_sm(unsigned char v)
1003{ 1021{
1004 if (v > 127) 1022 if (v > 127)
1005 return v & 0x7f; 1023 return v & 0x7f;
1006 else 1024 return (128 - v) | 0x80;
1007 return (128 - v) | 0x80;
1008} 1025}
1009 1026
1010static int ov7670_t_brightness(struct i2c_client *client, int value) 1027static int ov7670_t_brightness(struct v4l2_subdev *sd, int value)
1011{ 1028{
1012 unsigned char com8 = 0, v; 1029 unsigned char com8 = 0, v;
1013 int ret; 1030 int ret;
1014 1031
1015 ov7670_read(client, REG_COM8, &com8); 1032 ov7670_read(sd, REG_COM8, &com8);
1016 com8 &= ~COM8_AEC; 1033 com8 &= ~COM8_AEC;
1017 ov7670_write(client, REG_COM8, com8); 1034 ov7670_write(sd, REG_COM8, com8);
1018 v = ov7670_abs_to_sm(value); 1035 v = ov7670_abs_to_sm(value);
1019 ret = ov7670_write(client, REG_BRIGHT, v); 1036 ret = ov7670_write(sd, REG_BRIGHT, v);
1020 return ret; 1037 return ret;
1021} 1038}
1022 1039
1023static int ov7670_q_brightness(struct i2c_client *client, __s32 *value) 1040static int ov7670_q_brightness(struct v4l2_subdev *sd, __s32 *value)
1024{ 1041{
1025 unsigned char v = 0; 1042 unsigned char v = 0;
1026 int ret = ov7670_read(client, REG_BRIGHT, &v); 1043 int ret = ov7670_read(sd, REG_BRIGHT, &v);
1027 1044
1028 *value = ov7670_sm_to_abs(v); 1045 *value = ov7670_sm_to_abs(v);
1029 return ret; 1046 return ret;
1030} 1047}
1031 1048
1032static int ov7670_t_contrast(struct i2c_client *client, int value) 1049static int ov7670_t_contrast(struct v4l2_subdev *sd, int value)
1033{ 1050{
1034 return ov7670_write(client, REG_CONTRAS, (unsigned char) value); 1051 return ov7670_write(sd, REG_CONTRAS, (unsigned char) value);
1035} 1052}
1036 1053
1037static int ov7670_q_contrast(struct i2c_client *client, __s32 *value) 1054static int ov7670_q_contrast(struct v4l2_subdev *sd, __s32 *value)
1038{ 1055{
1039 unsigned char v = 0; 1056 unsigned char v = 0;
1040 int ret = ov7670_read(client, REG_CONTRAS, &v); 1057 int ret = ov7670_read(sd, REG_CONTRAS, &v);
1041 1058
1042 *value = v; 1059 *value = v;
1043 return ret; 1060 return ret;
1044} 1061}
1045 1062
1046static int ov7670_q_hflip(struct i2c_client *client, __s32 *value) 1063static int ov7670_q_hflip(struct v4l2_subdev *sd, __s32 *value)
1047{ 1064{
1048 int ret; 1065 int ret;
1049 unsigned char v = 0; 1066 unsigned char v = 0;
1050 1067
1051 ret = ov7670_read(client, REG_MVFP, &v); 1068 ret = ov7670_read(sd, REG_MVFP, &v);
1052 *value = (v & MVFP_MIRROR) == MVFP_MIRROR; 1069 *value = (v & MVFP_MIRROR) == MVFP_MIRROR;
1053 return ret; 1070 return ret;
1054} 1071}
1055 1072
1056 1073
1057static int ov7670_t_hflip(struct i2c_client *client, int value) 1074static int ov7670_t_hflip(struct v4l2_subdev *sd, int value)
1058{ 1075{
1059 unsigned char v = 0; 1076 unsigned char v = 0;
1060 int ret; 1077 int ret;
1061 1078
1062 ret = ov7670_read(client, REG_MVFP, &v); 1079 ret = ov7670_read(sd, REG_MVFP, &v);
1063 if (value) 1080 if (value)
1064 v |= MVFP_MIRROR; 1081 v |= MVFP_MIRROR;
1065 else 1082 else
1066 v &= ~MVFP_MIRROR; 1083 v &= ~MVFP_MIRROR;
1067 msleep(10); /* FIXME */ 1084 msleep(10); /* FIXME */
1068 ret += ov7670_write(client, REG_MVFP, v); 1085 ret += ov7670_write(sd, REG_MVFP, v);
1069 return ret; 1086 return ret;
1070} 1087}
1071 1088
1072 1089
1073 1090
1074static int ov7670_q_vflip(struct i2c_client *client, __s32 *value) 1091static int ov7670_q_vflip(struct v4l2_subdev *sd, __s32 *value)
1075{ 1092{
1076 int ret; 1093 int ret;
1077 unsigned char v = 0; 1094 unsigned char v = 0;
1078 1095
1079 ret = ov7670_read(client, REG_MVFP, &v); 1096 ret = ov7670_read(sd, REG_MVFP, &v);
1080 *value = (v & MVFP_FLIP) == MVFP_FLIP; 1097 *value = (v & MVFP_FLIP) == MVFP_FLIP;
1081 return ret; 1098 return ret;
1082} 1099}
1083 1100
1084 1101
1085static int ov7670_t_vflip(struct i2c_client *client, int value) 1102static int ov7670_t_vflip(struct v4l2_subdev *sd, int value)
1086{ 1103{
1087 unsigned char v = 0; 1104 unsigned char v = 0;
1088 int ret; 1105 int ret;
1089 1106
1090 ret = ov7670_read(client, REG_MVFP, &v); 1107 ret = ov7670_read(sd, REG_MVFP, &v);
1091 if (value) 1108 if (value)
1092 v |= MVFP_FLIP; 1109 v |= MVFP_FLIP;
1093 else 1110 else
1094 v &= ~MVFP_FLIP; 1111 v &= ~MVFP_FLIP;
1095 msleep(10); /* FIXME */ 1112 msleep(10); /* FIXME */
1096 ret += ov7670_write(client, REG_MVFP, v); 1113 ret += ov7670_write(sd, REG_MVFP, v);
1097 return ret; 1114 return ret;
1098} 1115}
1099 1116
1100 1117
1101static struct ov7670_control { 1118static struct ov7670_control {
1102 struct v4l2_queryctrl qc; 1119 struct v4l2_queryctrl qc;
1103 int (*query)(struct i2c_client *c, __s32 *value); 1120 int (*query)(struct v4l2_subdev *sd, __s32 *value);
1104 int (*tweak)(struct i2c_client *c, int value); 1121 int (*tweak)(struct v4l2_subdev *sd, int value);
1105} ov7670_controls[] = 1122} ov7670_controls[] =
1106{ 1123{
1107 { 1124 {
@@ -1200,7 +1217,7 @@ static struct ov7670_control *ov7670_find_control(__u32 id)
1200} 1217}
1201 1218
1202 1219
1203static int ov7670_queryctrl(struct i2c_client *client, 1220static int ov7670_queryctrl(struct v4l2_subdev *sd,
1204 struct v4l2_queryctrl *qc) 1221 struct v4l2_queryctrl *qc)
1205{ 1222{
1206 struct ov7670_control *ctrl = ov7670_find_control(qc->id); 1223 struct ov7670_control *ctrl = ov7670_find_control(qc->id);
@@ -1211,161 +1228,128 @@ static int ov7670_queryctrl(struct i2c_client *client,
1211 return 0; 1228 return 0;
1212} 1229}
1213 1230
1214static int ov7670_g_ctrl(struct i2c_client *client, struct v4l2_control *ctrl) 1231static int ov7670_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
1215{ 1232{
1216 struct ov7670_control *octrl = ov7670_find_control(ctrl->id); 1233 struct ov7670_control *octrl = ov7670_find_control(ctrl->id);
1217 int ret; 1234 int ret;
1218 1235
1219 if (octrl == NULL) 1236 if (octrl == NULL)
1220 return -EINVAL; 1237 return -EINVAL;
1221 ret = octrl->query(client, &ctrl->value); 1238 ret = octrl->query(sd, &ctrl->value);
1222 if (ret >= 0) 1239 if (ret >= 0)
1223 return 0; 1240 return 0;
1224 return ret; 1241 return ret;
1225} 1242}
1226 1243
1227static int ov7670_s_ctrl(struct i2c_client *client, struct v4l2_control *ctrl) 1244static int ov7670_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
1228{ 1245{
1229 struct ov7670_control *octrl = ov7670_find_control(ctrl->id); 1246 struct ov7670_control *octrl = ov7670_find_control(ctrl->id);
1230 int ret; 1247 int ret;
1231 1248
1232 if (octrl == NULL) 1249 if (octrl == NULL)
1233 return -EINVAL; 1250 return -EINVAL;
1234 ret = octrl->tweak(client, ctrl->value); 1251 ret = octrl->tweak(sd, ctrl->value);
1235 if (ret >= 0) 1252 if (ret >= 0)
1236 return 0; 1253 return 0;
1237 return ret; 1254 return ret;
1238} 1255}
1239 1256
1257static int ov7670_g_chip_ident(struct v4l2_subdev *sd,
1258 struct v4l2_dbg_chip_ident *chip)
1259{
1260 struct i2c_client *client = v4l2_get_subdevdata(sd);
1261
1262 return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_OV7670, 0);
1263}
1264
1265static int ov7670_command(struct i2c_client *client, unsigned cmd, void *arg)
1266{
1267 return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg);
1268}
1240 1269
1270/* ----------------------------------------------------------------------- */
1241 1271
1272static const struct v4l2_subdev_core_ops ov7670_core_ops = {
1273 .g_chip_ident = ov7670_g_chip_ident,
1274 .g_ctrl = ov7670_g_ctrl,
1275 .s_ctrl = ov7670_s_ctrl,
1276 .queryctrl = ov7670_queryctrl,
1277 .reset = ov7670_reset,
1278 .init = ov7670_init,
1279};
1242 1280
1281static const struct v4l2_subdev_video_ops ov7670_video_ops = {
1282 .enum_fmt = ov7670_enum_fmt,
1283 .try_fmt = ov7670_try_fmt,
1284 .s_fmt = ov7670_s_fmt,
1285 .s_parm = ov7670_s_parm,
1286 .g_parm = ov7670_g_parm,
1287};
1243 1288
1289static const struct v4l2_subdev_ops ov7670_ops = {
1290 .core = &ov7670_core_ops,
1291 .video = &ov7670_video_ops,
1292};
1244 1293
1245/* 1294/* ----------------------------------------------------------------------- */
1246 * Basic i2c stuff.
1247 */
1248static struct i2c_driver ov7670_driver;
1249 1295
1250static int ov7670_attach(struct i2c_adapter *adapter) 1296static int ov7670_probe(struct i2c_client *client,
1297 const struct i2c_device_id *id)
1251{ 1298{
1252 int ret; 1299 struct v4l2_subdev *sd;
1253 struct i2c_client *client;
1254 struct ov7670_info *info; 1300 struct ov7670_info *info;
1301 int ret;
1255 1302
1256 /* 1303 /*
1257 * For now: only deal with adapters we recognize. 1304 * For now: only deal with adapters we recognize.
1258 */ 1305 */
1259 if (adapter->id != I2C_HW_SMBUS_CAFE) 1306 if (client->adapter->id != I2C_HW_SMBUS_CAFE)
1260 return -ENODEV; 1307 return -ENODEV;
1261 1308 info = kzalloc(sizeof(struct ov7670_info), GFP_KERNEL);
1262 client = kzalloc(sizeof (struct i2c_client), GFP_KERNEL); 1309 if (info == NULL)
1263 if (! client)
1264 return -ENOMEM; 1310 return -ENOMEM;
1265 client->adapter = adapter; 1311 sd = &info->sd;
1266 client->addr = OV7670_I2C_ADDR; 1312 v4l2_i2c_subdev_init(sd, client, &ov7670_ops);
1267 client->driver = &ov7670_driver, 1313
1268 strcpy(client->name, "OV7670"); 1314 /* Make sure it's an ov7670 */
1269 /* 1315 ret = ov7670_detect(sd);
1270 * Set up our info structure. 1316 if (ret) {
1271 */ 1317 v4l_dbg(1, debug, client,
1272 info = kzalloc(sizeof (struct ov7670_info), GFP_KERNEL); 1318 "chip found @ 0x%x (%s) is not an ov7670 chip.\n",
1273 if (! info) { 1319 client->addr << 1, client->adapter->name);
1274 ret = -ENOMEM; 1320 kfree(info);
1275 goto out_free; 1321 return ret;
1276 } 1322 }
1323 v4l_info(client, "chip found @ 0x%02x (%s)\n",
1324 client->addr << 1, client->adapter->name);
1325
1277 info->fmt = &ov7670_formats[0]; 1326 info->fmt = &ov7670_formats[0];
1278 info->sat = 128; /* Review this */ 1327 info->sat = 128; /* Review this */
1279 i2c_set_clientdata(client, info);
1280 1328
1281 /*
1282 * Make sure it's an ov7670
1283 */
1284 ret = ov7670_detect(client);
1285 if (ret)
1286 goto out_free_info;
1287 ret = i2c_attach_client(client);
1288 if (ret)
1289 goto out_free_info;
1290 return 0; 1329 return 0;
1291
1292 out_free_info:
1293 kfree(info);
1294 out_free:
1295 kfree(client);
1296 return ret;
1297} 1330}
1298 1331
1299 1332
1300static int ov7670_detach(struct i2c_client *client) 1333static int ov7670_remove(struct i2c_client *client)
1301{ 1334{
1302 i2c_detach_client(client); 1335 struct v4l2_subdev *sd = i2c_get_clientdata(client);
1303 kfree(i2c_get_clientdata(client));
1304 kfree(client);
1305 return 0;
1306}
1307 1336
1308 1337 v4l2_device_unregister_subdev(sd);
1309static int ov7670_command(struct i2c_client *client, unsigned int cmd, 1338 kfree(to_state(sd));
1310 void *arg) 1339 return 0;
1311{
1312 switch (cmd) {
1313 case VIDIOC_DBG_G_CHIP_IDENT:
1314 return v4l2_chip_ident_i2c_client(client, arg, V4L2_IDENT_OV7670, 0);
1315
1316 case VIDIOC_INT_RESET:
1317 ov7670_reset(client);
1318 return 0;
1319
1320 case VIDIOC_INT_INIT:
1321 return ov7670_init(client);
1322
1323 case VIDIOC_ENUM_FMT:
1324 return ov7670_enum_fmt(client, (struct v4l2_fmtdesc *) arg);
1325 case VIDIOC_TRY_FMT:
1326 return ov7670_try_fmt(client, (struct v4l2_format *) arg, NULL, NULL);
1327 case VIDIOC_S_FMT:
1328 return ov7670_s_fmt(client, (struct v4l2_format *) arg);
1329 case VIDIOC_QUERYCTRL:
1330 return ov7670_queryctrl(client, (struct v4l2_queryctrl *) arg);
1331 case VIDIOC_S_CTRL:
1332 return ov7670_s_ctrl(client, (struct v4l2_control *) arg);
1333 case VIDIOC_G_CTRL:
1334 return ov7670_g_ctrl(client, (struct v4l2_control *) arg);
1335 case VIDIOC_S_PARM:
1336 return ov7670_s_parm(client, (struct v4l2_streamparm *) arg);
1337 case VIDIOC_G_PARM:
1338 return ov7670_g_parm(client, (struct v4l2_streamparm *) arg);
1339 }
1340 return -EINVAL;
1341} 1340}
1342 1341
1343 1342static const struct i2c_device_id ov7670_id[] = {
1344 1343 { "ov7670", 0 },
1345static struct i2c_driver ov7670_driver = { 1344 { }
1346 .driver = { 1345};
1347 .name = "ov7670", 1346MODULE_DEVICE_TABLE(i2c, ov7670_id);
1348 }, 1347
1349 .id = I2C_DRIVERID_OV7670, 1348static struct v4l2_i2c_driver_data v4l2_i2c_data = {
1350 .attach_adapter = ov7670_attach, 1349 .name = "ov7670",
1351 .detach_client = ov7670_detach, 1350 .command = ov7670_command,
1352 .command = ov7670_command, 1351 .probe = ov7670_probe,
1352 .remove = ov7670_remove,
1353 .legacy_class = I2C_CLASS_TV_ANALOG,
1354 .id_table = ov7670_id,
1353}; 1355};
1354
1355
1356/*
1357 * Module initialization
1358 */
1359static int __init ov7670_mod_init(void)
1360{
1361 printk(KERN_NOTICE "OmniVision ov7670 sensor driver, at your service\n");
1362 return i2c_add_driver(&ov7670_driver);
1363}
1364
1365static void __exit ov7670_mod_exit(void)
1366{
1367 i2c_del_driver(&ov7670_driver);
1368}
1369
1370module_init(ov7670_mod_init);
1371module_exit(ov7670_mod_exit);