aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/ov7670.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/ov7670.c')
-rw-r--r--drivers/media/video/ov7670.c268
1 files changed, 182 insertions, 86 deletions
diff --git a/drivers/media/video/ov7670.c b/drivers/media/video/ov7670.c
index 91c886ab15c6..c881a64b41fd 100644
--- a/drivers/media/video/ov7670.c
+++ b/drivers/media/video/ov7670.c
@@ -18,8 +18,9 @@
18#include <linux/videodev2.h> 18#include <linux/videodev2.h>
19#include <media/v4l2-device.h> 19#include <media/v4l2-device.h>
20#include <media/v4l2-chip-ident.h> 20#include <media/v4l2-chip-ident.h>
21#include <media/v4l2-i2c-drv.h> 21#include <media/v4l2-mediabus.h>
22 22
23#include "ov7670.h"
23 24
24MODULE_AUTHOR("Jonathan Corbet <corbet@lwn.net>"); 25MODULE_AUTHOR("Jonathan Corbet <corbet@lwn.net>");
25MODULE_DESCRIPTION("A low-level driver for OmniVision ov7670 sensors"); 26MODULE_DESCRIPTION("A low-level driver for OmniVision ov7670 sensors");
@@ -43,11 +44,6 @@ MODULE_PARM_DESC(debug, "Debug level (0-1)");
43#define QCIF_HEIGHT 144 44#define QCIF_HEIGHT 144
44 45
45/* 46/*
46 * Our nominal (default) frame rate.
47 */
48#define OV7670_FRAME_RATE 30
49
50/*
51 * The 7670 sits on i2c with ID 0x42 47 * The 7670 sits on i2c with ID 0x42
52 */ 48 */
53#define OV7670_I2C_ADDR 0x42 49#define OV7670_I2C_ADDR 0x42
@@ -198,7 +194,11 @@ struct ov7670_info {
198 struct ov7670_format_struct *fmt; /* Current format */ 194 struct ov7670_format_struct *fmt; /* Current format */
199 unsigned char sat; /* Saturation value */ 195 unsigned char sat; /* Saturation value */
200 int hue; /* Hue value */ 196 int hue; /* Hue value */
197 int min_width; /* Filter out smaller sizes */
198 int min_height; /* Filter out smaller sizes */
199 int clock_speed; /* External clock speed (MHz) */
201 u8 clkrc; /* Clock divider value */ 200 u8 clkrc; /* Clock divider value */
201 bool use_smbus; /* Use smbus I/O instead of I2C */
202}; 202};
203 203
204static inline struct ov7670_info *to_state(struct v4l2_subdev *sd) 204static inline struct ov7670_info *to_state(struct v4l2_subdev *sd)
@@ -415,8 +415,7 @@ static struct regval_list ov7670_fmt_raw[] = {
415 * ov7670 is not really an SMBUS device, though, so the communication 415 * ov7670 is not really an SMBUS device, though, so the communication
416 * is not always entirely reliable. 416 * is not always entirely reliable.
417 */ 417 */
418#ifdef CONFIG_OLPC_XO_1 418static int ov7670_read_smbus(struct v4l2_subdev *sd, unsigned char reg,
419static int ov7670_read(struct v4l2_subdev *sd, unsigned char reg,
420 unsigned char *value) 419 unsigned char *value)
421{ 420{
422 struct i2c_client *client = v4l2_get_subdevdata(sd); 421 struct i2c_client *client = v4l2_get_subdevdata(sd);
@@ -431,7 +430,7 @@ static int ov7670_read(struct v4l2_subdev *sd, unsigned char reg,
431} 430}
432 431
433 432
434static int ov7670_write(struct v4l2_subdev *sd, unsigned char reg, 433static int ov7670_write_smbus(struct v4l2_subdev *sd, unsigned char reg,
435 unsigned char value) 434 unsigned char value)
436{ 435{
437 struct i2c_client *client = v4l2_get_subdevdata(sd); 436 struct i2c_client *client = v4l2_get_subdevdata(sd);
@@ -442,11 +441,10 @@ static int ov7670_write(struct v4l2_subdev *sd, unsigned char reg,
442 return ret; 441 return ret;
443} 442}
444 443
445#else /* ! CONFIG_OLPC_XO_1 */
446/* 444/*
447 * On most platforms, we'd rather do straight i2c I/O. 445 * On most platforms, we'd rather do straight i2c I/O.
448 */ 446 */
449static int ov7670_read(struct v4l2_subdev *sd, unsigned char reg, 447static int ov7670_read_i2c(struct v4l2_subdev *sd, unsigned char reg,
450 unsigned char *value) 448 unsigned char *value)
451{ 449{
452 struct i2c_client *client = v4l2_get_subdevdata(sd); 450 struct i2c_client *client = v4l2_get_subdevdata(sd);
@@ -479,7 +477,7 @@ static int ov7670_read(struct v4l2_subdev *sd, unsigned char reg,
479} 477}
480 478
481 479
482static int ov7670_write(struct v4l2_subdev *sd, unsigned char reg, 480static int ov7670_write_i2c(struct v4l2_subdev *sd, unsigned char reg,
483 unsigned char value) 481 unsigned char value)
484{ 482{
485 struct i2c_client *client = v4l2_get_subdevdata(sd); 483 struct i2c_client *client = v4l2_get_subdevdata(sd);
@@ -498,8 +496,26 @@ static int ov7670_write(struct v4l2_subdev *sd, unsigned char reg,
498 msleep(5); /* Wait for reset to run */ 496 msleep(5); /* Wait for reset to run */
499 return ret; 497 return ret;
500} 498}
501#endif /* CONFIG_OLPC_XO_1 */
502 499
500static int ov7670_read(struct v4l2_subdev *sd, unsigned char reg,
501 unsigned char *value)
502{
503 struct ov7670_info *info = to_state(sd);
504 if (info->use_smbus)
505 return ov7670_read_smbus(sd, reg, value);
506 else
507 return ov7670_read_i2c(sd, reg, value);
508}
509
510static int ov7670_write(struct v4l2_subdev *sd, unsigned char reg,
511 unsigned char value)
512{
513 struct ov7670_info *info = to_state(sd);
514 if (info->use_smbus)
515 return ov7670_write_smbus(sd, reg, value);
516 else
517 return ov7670_write_i2c(sd, reg, value);
518}
503 519
504/* 520/*
505 * Write a list of register settings; ff/ff stops the process. 521 * Write a list of register settings; ff/ff stops the process.
@@ -572,42 +588,37 @@ static int ov7670_detect(struct v4l2_subdev *sd)
572/* 588/*
573 * Store information about the video data format. The color matrix 589 * Store information about the video data format. The color matrix
574 * is deeply tied into the format, so keep the relevant values here. 590 * is deeply tied into the format, so keep the relevant values here.
575 * The magic matrix nubmers come from OmniVision. 591 * The magic matrix numbers come from OmniVision.
576 */ 592 */
577static struct ov7670_format_struct { 593static struct ov7670_format_struct {
578 __u8 *desc; 594 enum v4l2_mbus_pixelcode mbus_code;
579 __u32 pixelformat; 595 enum v4l2_colorspace colorspace;
580 struct regval_list *regs; 596 struct regval_list *regs;
581 int cmatrix[CMATRIX_LEN]; 597 int cmatrix[CMATRIX_LEN];
582 int bpp; /* Bytes per pixel */
583} ov7670_formats[] = { 598} ov7670_formats[] = {
584 { 599 {
585 .desc = "YUYV 4:2:2", 600 .mbus_code = V4L2_MBUS_FMT_YUYV8_2X8,
586 .pixelformat = V4L2_PIX_FMT_YUYV, 601 .colorspace = V4L2_COLORSPACE_JPEG,
587 .regs = ov7670_fmt_yuv422, 602 .regs = ov7670_fmt_yuv422,
588 .cmatrix = { 128, -128, 0, -34, -94, 128 }, 603 .cmatrix = { 128, -128, 0, -34, -94, 128 },
589 .bpp = 2,
590 }, 604 },
591 { 605 {
592 .desc = "RGB 444", 606 .mbus_code = V4L2_MBUS_FMT_RGB444_2X8_PADHI_LE,
593 .pixelformat = V4L2_PIX_FMT_RGB444, 607 .colorspace = V4L2_COLORSPACE_SRGB,
594 .regs = ov7670_fmt_rgb444, 608 .regs = ov7670_fmt_rgb444,
595 .cmatrix = { 179, -179, 0, -61, -176, 228 }, 609 .cmatrix = { 179, -179, 0, -61, -176, 228 },
596 .bpp = 2,
597 }, 610 },
598 { 611 {
599 .desc = "RGB 565", 612 .mbus_code = V4L2_MBUS_FMT_RGB565_2X8_LE,
600 .pixelformat = V4L2_PIX_FMT_RGB565, 613 .colorspace = V4L2_COLORSPACE_SRGB,
601 .regs = ov7670_fmt_rgb565, 614 .regs = ov7670_fmt_rgb565,
602 .cmatrix = { 179, -179, 0, -61, -176, 228 }, 615 .cmatrix = { 179, -179, 0, -61, -176, 228 },
603 .bpp = 2,
604 }, 616 },
605 { 617 {
606 .desc = "Raw RGB Bayer", 618 .mbus_code = V4L2_MBUS_FMT_SBGGR8_1X8,
607 .pixelformat = V4L2_PIX_FMT_SBGGR8, 619 .colorspace = V4L2_COLORSPACE_SRGB,
608 .regs = ov7670_fmt_raw, 620 .regs = ov7670_fmt_raw,
609 .cmatrix = { 0, 0, 0, 0, 0, 0 }, 621 .cmatrix = { 0, 0, 0, 0, 0, 0 },
610 .bpp = 1
611 }, 622 },
612}; 623};
613#define N_OV7670_FMTS ARRAY_SIZE(ov7670_formats) 624#define N_OV7670_FMTS ARRAY_SIZE(ov7670_formats)
@@ -680,10 +691,10 @@ static struct ov7670_win_size {
680 .width = QVGA_WIDTH, 691 .width = QVGA_WIDTH,
681 .height = QVGA_HEIGHT, 692 .height = QVGA_HEIGHT,
682 .com7_bit = COM7_FMT_QVGA, 693 .com7_bit = COM7_FMT_QVGA,
683 .hstart = 164, /* Empirically determined */ 694 .hstart = 168, /* Empirically determined */
684 .hstop = 20, 695 .hstop = 24,
685 .vstart = 14, 696 .vstart = 12,
686 .vstop = 494, 697 .vstop = 492,
687 .regs = NULL, 698 .regs = NULL,
688 }, 699 },
689 /* QCIF */ 700 /* QCIF */
@@ -734,51 +745,45 @@ static int ov7670_set_hw(struct v4l2_subdev *sd, int hstart, int hstop,
734} 745}
735 746
736 747
737static int ov7670_enum_fmt(struct v4l2_subdev *sd, struct v4l2_fmtdesc *fmt) 748static int ov7670_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned index,
749 enum v4l2_mbus_pixelcode *code)
738{ 750{
739 struct ov7670_format_struct *ofmt; 751 if (index >= N_OV7670_FMTS)
740
741 if (fmt->index >= N_OV7670_FMTS)
742 return -EINVAL; 752 return -EINVAL;
743 753
744 ofmt = ov7670_formats + fmt->index; 754 *code = ov7670_formats[index].mbus_code;
745 fmt->flags = 0;
746 strcpy(fmt->description, ofmt->desc);
747 fmt->pixelformat = ofmt->pixelformat;
748 return 0; 755 return 0;
749} 756}
750 757
751
752static int ov7670_try_fmt_internal(struct v4l2_subdev *sd, 758static int ov7670_try_fmt_internal(struct v4l2_subdev *sd,
753 struct v4l2_format *fmt, 759 struct v4l2_mbus_framefmt *fmt,
754 struct ov7670_format_struct **ret_fmt, 760 struct ov7670_format_struct **ret_fmt,
755 struct ov7670_win_size **ret_wsize) 761 struct ov7670_win_size **ret_wsize)
756{ 762{
757 int index; 763 int index;
758 struct ov7670_win_size *wsize; 764 struct ov7670_win_size *wsize;
759 struct v4l2_pix_format *pix = &fmt->fmt.pix;
760 765
761 for (index = 0; index < N_OV7670_FMTS; index++) 766 for (index = 0; index < N_OV7670_FMTS; index++)
762 if (ov7670_formats[index].pixelformat == pix->pixelformat) 767 if (ov7670_formats[index].mbus_code == fmt->code)
763 break; 768 break;
764 if (index >= N_OV7670_FMTS) { 769 if (index >= N_OV7670_FMTS) {
765 /* default to first format */ 770 /* default to first format */
766 index = 0; 771 index = 0;
767 pix->pixelformat = ov7670_formats[0].pixelformat; 772 fmt->code = ov7670_formats[0].mbus_code;
768 } 773 }
769 if (ret_fmt != NULL) 774 if (ret_fmt != NULL)
770 *ret_fmt = ov7670_formats + index; 775 *ret_fmt = ov7670_formats + index;
771 /* 776 /*
772 * Fields: the OV devices claim to be progressive. 777 * Fields: the OV devices claim to be progressive.
773 */ 778 */
774 pix->field = V4L2_FIELD_NONE; 779 fmt->field = V4L2_FIELD_NONE;
775 /* 780 /*
776 * Round requested image size down to the nearest 781 * Round requested image size down to the nearest
777 * we support, but not below the smallest. 782 * we support, but not below the smallest.
778 */ 783 */
779 for (wsize = ov7670_win_sizes; wsize < ov7670_win_sizes + N_WIN_SIZES; 784 for (wsize = ov7670_win_sizes; wsize < ov7670_win_sizes + N_WIN_SIZES;
780 wsize++) 785 wsize++)
781 if (pix->width >= wsize->width && pix->height >= wsize->height) 786 if (fmt->width >= wsize->width && fmt->height >= wsize->height)
782 break; 787 break;
783 if (wsize >= ov7670_win_sizes + N_WIN_SIZES) 788 if (wsize >= ov7670_win_sizes + N_WIN_SIZES)
784 wsize--; /* Take the smallest one */ 789 wsize--; /* Take the smallest one */
@@ -787,14 +792,14 @@ static int ov7670_try_fmt_internal(struct v4l2_subdev *sd,
787 /* 792 /*
788 * Note the size we'll actually handle. 793 * Note the size we'll actually handle.
789 */ 794 */
790 pix->width = wsize->width; 795 fmt->width = wsize->width;
791 pix->height = wsize->height; 796 fmt->height = wsize->height;
792 pix->bytesperline = pix->width*ov7670_formats[index].bpp; 797 fmt->colorspace = ov7670_formats[index].colorspace;
793 pix->sizeimage = pix->height*pix->bytesperline;
794 return 0; 798 return 0;
795} 799}
796 800
797static int ov7670_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) 801static int ov7670_try_mbus_fmt(struct v4l2_subdev *sd,
802 struct v4l2_mbus_framefmt *fmt)
798{ 803{
799 return ov7670_try_fmt_internal(sd, fmt, NULL, NULL); 804 return ov7670_try_fmt_internal(sd, fmt, NULL, NULL);
800} 805}
@@ -802,15 +807,17 @@ static int ov7670_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
802/* 807/*
803 * Set a format. 808 * Set a format.
804 */ 809 */
805static int ov7670_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) 810static int ov7670_s_mbus_fmt(struct v4l2_subdev *sd,
811 struct v4l2_mbus_framefmt *fmt)
806{ 812{
807 int ret;
808 struct ov7670_format_struct *ovfmt; 813 struct ov7670_format_struct *ovfmt;
809 struct ov7670_win_size *wsize; 814 struct ov7670_win_size *wsize;
810 struct ov7670_info *info = to_state(sd); 815 struct ov7670_info *info = to_state(sd);
811 unsigned char com7; 816 unsigned char com7;
817 int ret;
812 818
813 ret = ov7670_try_fmt_internal(sd, fmt, &ovfmt, &wsize); 819 ret = ov7670_try_fmt_internal(sd, fmt, &ovfmt, &wsize);
820
814 if (ret) 821 if (ret)
815 return ret; 822 return ret;
816 /* 823 /*
@@ -845,7 +852,7 @@ static int ov7670_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
845 */ 852 */
846 if (ret == 0) 853 if (ret == 0)
847 ret = ov7670_write(sd, REG_CLKRC, info->clkrc); 854 ret = ov7670_write(sd, REG_CLKRC, info->clkrc);
848 return ret; 855 return 0;
849} 856}
850 857
851/* 858/*
@@ -863,7 +870,7 @@ static int ov7670_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms)
863 memset(cp, 0, sizeof(struct v4l2_captureparm)); 870 memset(cp, 0, sizeof(struct v4l2_captureparm));
864 cp->capability = V4L2_CAP_TIMEPERFRAME; 871 cp->capability = V4L2_CAP_TIMEPERFRAME;
865 cp->timeperframe.numerator = 1; 872 cp->timeperframe.numerator = 1;
866 cp->timeperframe.denominator = OV7670_FRAME_RATE; 873 cp->timeperframe.denominator = info->clock_speed;
867 if ((info->clkrc & CLK_EXT) == 0 && (info->clkrc & CLK_SCALE) > 1) 874 if ((info->clkrc & CLK_EXT) == 0 && (info->clkrc & CLK_SCALE) > 1)
868 cp->timeperframe.denominator /= (info->clkrc & CLK_SCALE); 875 cp->timeperframe.denominator /= (info->clkrc & CLK_SCALE);
869 return 0; 876 return 0;
@@ -884,26 +891,72 @@ static int ov7670_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms)
884 if (tpf->numerator == 0 || tpf->denominator == 0) 891 if (tpf->numerator == 0 || tpf->denominator == 0)
885 div = 1; /* Reset to full rate */ 892 div = 1; /* Reset to full rate */
886 else 893 else
887 div = (tpf->numerator*OV7670_FRAME_RATE)/tpf->denominator; 894 div = (tpf->numerator * info->clock_speed) / tpf->denominator;
888 if (div == 0) 895 if (div == 0)
889 div = 1; 896 div = 1;
890 else if (div > CLK_SCALE) 897 else if (div > CLK_SCALE)
891 div = CLK_SCALE; 898 div = CLK_SCALE;
892 info->clkrc = (info->clkrc & 0x80) | div; 899 info->clkrc = (info->clkrc & 0x80) | div;
893 tpf->numerator = 1; 900 tpf->numerator = 1;
894 tpf->denominator = OV7670_FRAME_RATE/div; 901 tpf->denominator = info->clock_speed / div;
895 return ov7670_write(sd, REG_CLKRC, info->clkrc); 902 return ov7670_write(sd, REG_CLKRC, info->clkrc);
896} 903}
897 904
898 905
899
900/* 906/*
901 * Code for dealing with controls. 907 * Frame intervals. Since frame rates are controlled with the clock
908 * divider, we can only do 30/n for integer n values. So no continuous
909 * or stepwise options. Here we just pick a handful of logical values.
902 */ 910 */
903 911
912static int ov7670_frame_rates[] = { 30, 15, 10, 5, 1 };
913
914static int ov7670_enum_frameintervals(struct v4l2_subdev *sd,
915 struct v4l2_frmivalenum *interval)
916{
917 if (interval->index >= ARRAY_SIZE(ov7670_frame_rates))
918 return -EINVAL;
919 interval->type = V4L2_FRMIVAL_TYPE_DISCRETE;
920 interval->discrete.numerator = 1;
921 interval->discrete.denominator = ov7670_frame_rates[interval->index];
922 return 0;
923}
924
925/*
926 * Frame size enumeration
927 */
928static int ov7670_enum_framesizes(struct v4l2_subdev *sd,
929 struct v4l2_frmsizeenum *fsize)
930{
931 struct ov7670_info *info = to_state(sd);
932 int i;
933 int num_valid = -1;
934 __u32 index = fsize->index;
904 935
936 /*
937 * If a minimum width/height was requested, filter out the capture
938 * windows that fall outside that.
939 */
940 for (i = 0; i < N_WIN_SIZES; i++) {
941 struct ov7670_win_size *win = &ov7670_win_sizes[index];
942 if (info->min_width && win->width < info->min_width)
943 continue;
944 if (info->min_height && win->height < info->min_height)
945 continue;
946 if (index == ++num_valid) {
947 fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
948 fsize->discrete.width = win->width;
949 fsize->discrete.height = win->height;
950 return 0;
951 }
952 }
905 953
954 return -EINVAL;
955}
906 956
957/*
958 * Code for dealing with controls.
959 */
907 960
908static int ov7670_store_cmatrix(struct v4l2_subdev *sd, 961static int ov7670_store_cmatrix(struct v4l2_subdev *sd,
909 int matrix[CMATRIX_LEN]) 962 int matrix[CMATRIX_LEN])
@@ -1396,6 +1449,47 @@ static int ov7670_g_chip_ident(struct v4l2_subdev *sd,
1396 return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_OV7670, 0); 1449 return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_OV7670, 0);
1397} 1450}
1398 1451
1452static int ov7670_s_config(struct v4l2_subdev *sd, int dumb, void *data)
1453{
1454 struct i2c_client *client = v4l2_get_subdevdata(sd);
1455 struct ov7670_config *config = data;
1456 struct ov7670_info *info = to_state(sd);
1457 int ret;
1458
1459 info->clock_speed = 30; /* default: a guess */
1460
1461 /*
1462 * Must apply configuration before initializing device, because it
1463 * selects I/O method.
1464 */
1465 if (config) {
1466 info->min_width = config->min_width;
1467 info->min_height = config->min_height;
1468 info->use_smbus = config->use_smbus;
1469
1470 if (config->clock_speed)
1471 info->clock_speed = config->clock_speed;
1472 }
1473
1474 /* Make sure it's an ov7670 */
1475 ret = ov7670_detect(sd);
1476 if (ret) {
1477 v4l_dbg(1, debug, client,
1478 "chip found @ 0x%x (%s) is not an ov7670 chip.\n",
1479 client->addr << 1, client->adapter->name);
1480 kfree(info);
1481 return ret;
1482 }
1483 v4l_info(client, "chip found @ 0x%02x (%s)\n",
1484 client->addr << 1, client->adapter->name);
1485
1486 info->fmt = &ov7670_formats[0];
1487 info->sat = 128; /* Review this */
1488 info->clkrc = info->clock_speed / 30;
1489
1490 return 0;
1491}
1492
1399#ifdef CONFIG_VIDEO_ADV_DEBUG 1493#ifdef CONFIG_VIDEO_ADV_DEBUG
1400static int ov7670_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) 1494static int ov7670_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
1401{ 1495{
@@ -1434,6 +1528,7 @@ static const struct v4l2_subdev_core_ops ov7670_core_ops = {
1434 .s_ctrl = ov7670_s_ctrl, 1528 .s_ctrl = ov7670_s_ctrl,
1435 .queryctrl = ov7670_queryctrl, 1529 .queryctrl = ov7670_queryctrl,
1436 .reset = ov7670_reset, 1530 .reset = ov7670_reset,
1531 .s_config = ov7670_s_config,
1437 .init = ov7670_init, 1532 .init = ov7670_init,
1438#ifdef CONFIG_VIDEO_ADV_DEBUG 1533#ifdef CONFIG_VIDEO_ADV_DEBUG
1439 .g_register = ov7670_g_register, 1534 .g_register = ov7670_g_register,
@@ -1442,11 +1537,13 @@ static const struct v4l2_subdev_core_ops ov7670_core_ops = {
1442}; 1537};
1443 1538
1444static const struct v4l2_subdev_video_ops ov7670_video_ops = { 1539static const struct v4l2_subdev_video_ops ov7670_video_ops = {
1445 .enum_fmt = ov7670_enum_fmt, 1540 .enum_mbus_fmt = ov7670_enum_mbus_fmt,
1446 .try_fmt = ov7670_try_fmt, 1541 .try_mbus_fmt = ov7670_try_mbus_fmt,
1447 .s_fmt = ov7670_s_fmt, 1542 .s_mbus_fmt = ov7670_s_mbus_fmt,
1448 .s_parm = ov7670_s_parm, 1543 .s_parm = ov7670_s_parm,
1449 .g_parm = ov7670_g_parm, 1544 .g_parm = ov7670_g_parm,
1545 .enum_frameintervals = ov7670_enum_frameintervals,
1546 .enum_framesizes = ov7670_enum_framesizes,
1450}; 1547};
1451 1548
1452static const struct v4l2_subdev_ops ov7670_ops = { 1549static const struct v4l2_subdev_ops ov7670_ops = {
@@ -1461,7 +1558,6 @@ static int ov7670_probe(struct i2c_client *client,
1461{ 1558{
1462 struct v4l2_subdev *sd; 1559 struct v4l2_subdev *sd;
1463 struct ov7670_info *info; 1560 struct ov7670_info *info;
1464 int ret;
1465 1561
1466 info = kzalloc(sizeof(struct ov7670_info), GFP_KERNEL); 1562 info = kzalloc(sizeof(struct ov7670_info), GFP_KERNEL);
1467 if (info == NULL) 1563 if (info == NULL)
@@ -1469,22 +1565,6 @@ static int ov7670_probe(struct i2c_client *client,
1469 sd = &info->sd; 1565 sd = &info->sd;
1470 v4l2_i2c_subdev_init(sd, client, &ov7670_ops); 1566 v4l2_i2c_subdev_init(sd, client, &ov7670_ops);
1471 1567
1472 /* Make sure it's an ov7670 */
1473 ret = ov7670_detect(sd);
1474 if (ret) {
1475 v4l_dbg(1, debug, client,
1476 "chip found @ 0x%x (%s) is not an ov7670 chip.\n",
1477 client->addr << 1, client->adapter->name);
1478 kfree(info);
1479 return ret;
1480 }
1481 v4l_info(client, "chip found @ 0x%02x (%s)\n",
1482 client->addr << 1, client->adapter->name);
1483
1484 info->fmt = &ov7670_formats[0];
1485 info->sat = 128; /* Review this */
1486 info->clkrc = 1; /* 30fps */
1487
1488 return 0; 1568 return 0;
1489} 1569}
1490 1570
@@ -1504,9 +1584,25 @@ static const struct i2c_device_id ov7670_id[] = {
1504}; 1584};
1505MODULE_DEVICE_TABLE(i2c, ov7670_id); 1585MODULE_DEVICE_TABLE(i2c, ov7670_id);
1506 1586
1507static struct v4l2_i2c_driver_data v4l2_i2c_data = { 1587static struct i2c_driver ov7670_driver = {
1508 .name = "ov7670", 1588 .driver = {
1509 .probe = ov7670_probe, 1589 .owner = THIS_MODULE,
1510 .remove = ov7670_remove, 1590 .name = "ov7670",
1511 .id_table = ov7670_id, 1591 },
1592 .probe = ov7670_probe,
1593 .remove = ov7670_remove,
1594 .id_table = ov7670_id,
1512}; 1595};
1596
1597static __init int init_ov7670(void)
1598{
1599 return i2c_add_driver(&ov7670_driver);
1600}
1601
1602static __exit void exit_ov7670(void)
1603{
1604 i2c_del_driver(&ov7670_driver);
1605}
1606
1607module_init(init_ov7670);
1608module_exit(exit_ov7670);