aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorJavier Martin <javier.martin@vista-silicon.com>2013-01-29 05:12:13 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2013-02-08 11:23:32 -0500
commitd058e23704ad7e0b6876a94b0d8428dcef510b49 (patch)
tree0b8525ed274f5e11f631058a8bc5710d4a19324a /drivers
parent06eae25f162e2a0d9e60f0ad3ec3d14c738fbe68 (diff)
[media] media: ov7670: add support for ov7675
ov7675 and ov7670 share the same registers but there is no way to distinguish them at runtime. However, they require different tweaks to achieve the desired resolution. For this reason this patch adds a new ov7675 entry to the ov7670_id table. Signed-off-by: Javier Martin <javier.martin@vista-silicon.com> Cc: Jonathan Corbet <corbet@lwn.net> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/media/i2c/ov7670.c101
1 files changed, 72 insertions, 29 deletions
diff --git a/drivers/media/i2c/ov7670.c b/drivers/media/i2c/ov7670.c
index 882ddf6f66d3..51b198f79077 100644
--- a/drivers/media/i2c/ov7670.c
+++ b/drivers/media/i2c/ov7670.c
@@ -183,6 +183,27 @@ MODULE_PARM_DESC(debug, "Debug level (0-1)");
183#define REG_HAECC7 0xaa /* Hist AEC/AGC control 7 */ 183#define REG_HAECC7 0xaa /* Hist AEC/AGC control 7 */
184#define REG_BD60MAX 0xab /* 60hz banding step limit */ 184#define REG_BD60MAX 0xab /* 60hz banding step limit */
185 185
186enum ov7670_model {
187 MODEL_OV7670 = 0,
188 MODEL_OV7675,
189};
190
191struct ov7670_win_size {
192 int width;
193 int height;
194 unsigned char com7_bit;
195 int hstart; /* Start/stop values for the camera. Note */
196 int hstop; /* that they do not always make complete */
197 int vstart; /* sense to humans, but evidently the sensor */
198 int vstop; /* will do the right thing... */
199 struct regval_list *regs; /* Regs to tweak */
200};
201
202struct ov7670_devtype {
203 /* formats supported for each model */
204 struct ov7670_win_size *win_sizes;
205 unsigned int n_win_sizes;
206};
186 207
187/* 208/*
188 * Information we maintain about a known sensor. 209 * Information we maintain about a known sensor.
@@ -198,6 +219,7 @@ struct ov7670_info {
198 int clock_speed; /* External clock speed (MHz) */ 219 int clock_speed; /* External clock speed (MHz) */
199 u8 clkrc; /* Clock divider value */ 220 u8 clkrc; /* Clock divider value */
200 bool use_smbus; /* Use smbus I/O instead of I2C */ 221 bool use_smbus; /* Use smbus I/O instead of I2C */
222 const struct ov7670_devtype *devtype; /* Device specifics */
201}; 223};
202 224
203static inline struct ov7670_info *to_state(struct v4l2_subdev *sd) 225static inline struct ov7670_info *to_state(struct v4l2_subdev *sd)
@@ -652,65 +674,70 @@ static struct regval_list ov7670_qcif_regs[] = {
652 { 0xff, 0xff }, 674 { 0xff, 0xff },
653}; 675};
654 676
655static struct ov7670_win_size { 677static struct ov7670_win_size ov7670_win_sizes[] = {
656 int width;
657 int height;
658 unsigned char com7_bit;
659 int hstart; /* Start/stop values for the camera. Note */
660 int hstop; /* that they do not always make complete */
661 int vstart; /* sense to humans, but evidently the sensor */
662 int vstop; /* will do the right thing... */
663 struct regval_list *regs; /* Regs to tweak */
664/* h/vref stuff */
665} ov7670_win_sizes[] = {
666 /* VGA */ 678 /* VGA */
667 { 679 {
668 .width = VGA_WIDTH, 680 .width = VGA_WIDTH,
669 .height = VGA_HEIGHT, 681 .height = VGA_HEIGHT,
670 .com7_bit = COM7_FMT_VGA, 682 .com7_bit = COM7_FMT_VGA,
671 .hstart = 158, /* These values from */ 683 .hstart = 158, /* These values from */
672 .hstop = 14, /* Omnivision */ 684 .hstop = 14, /* Omnivision */
673 .vstart = 10, 685 .vstart = 10,
674 .vstop = 490, 686 .vstop = 490,
675 .regs = NULL, 687 .regs = NULL,
676 }, 688 },
677 /* CIF */ 689 /* CIF */
678 { 690 {
679 .width = CIF_WIDTH, 691 .width = CIF_WIDTH,
680 .height = CIF_HEIGHT, 692 .height = CIF_HEIGHT,
681 .com7_bit = COM7_FMT_CIF, 693 .com7_bit = COM7_FMT_CIF,
682 .hstart = 170, /* Empirically determined */ 694 .hstart = 170, /* Empirically determined */
683 .hstop = 90, 695 .hstop = 90,
684 .vstart = 14, 696 .vstart = 14,
685 .vstop = 494, 697 .vstop = 494,
686 .regs = NULL, 698 .regs = NULL,
687 }, 699 },
688 /* QVGA */ 700 /* QVGA */
689 { 701 {
690 .width = QVGA_WIDTH, 702 .width = QVGA_WIDTH,
691 .height = QVGA_HEIGHT, 703 .height = QVGA_HEIGHT,
692 .com7_bit = COM7_FMT_QVGA, 704 .com7_bit = COM7_FMT_QVGA,
693 .hstart = 168, /* Empirically determined */ 705 .hstart = 168, /* Empirically determined */
694 .hstop = 24, 706 .hstop = 24,
695 .vstart = 12, 707 .vstart = 12,
696 .vstop = 492, 708 .vstop = 492,
697 .regs = NULL, 709 .regs = NULL,
698 }, 710 },
699 /* QCIF */ 711 /* QCIF */
700 { 712 {
701 .width = QCIF_WIDTH, 713 .width = QCIF_WIDTH,
702 .height = QCIF_HEIGHT, 714 .height = QCIF_HEIGHT,
703 .com7_bit = COM7_FMT_VGA, /* see comment above */ 715 .com7_bit = COM7_FMT_VGA, /* see comment above */
704 .hstart = 456, /* Empirically determined */ 716 .hstart = 456, /* Empirically determined */
705 .hstop = 24, 717 .hstop = 24,
706 .vstart = 14, 718 .vstart = 14,
707 .vstop = 494, 719 .vstop = 494,
708 .regs = ov7670_qcif_regs, 720 .regs = ov7670_qcif_regs,
709 }, 721 }
710}; 722};
711 723
712#define N_WIN_SIZES (ARRAY_SIZE(ov7670_win_sizes)) 724static struct ov7670_win_size ov7675_win_sizes[] = {
713 725 /*
726 * Currently, only VGA is supported. Theoretically it could be possible
727 * to support CIF, QVGA and QCIF too. Taking values for ov7670 as a
728 * base and tweak them empirically could be required.
729 */
730 {
731 .width = VGA_WIDTH,
732 .height = VGA_HEIGHT,
733 .com7_bit = COM7_FMT_VGA,
734 .hstart = 158, /* These values from */
735 .hstop = 14, /* Omnivision */
736 .vstart = 14, /* Empirically determined */
737 .vstop = 494,
738 .regs = NULL,
739 }
740};
714 741
715/* 742/*
716 * Store a set of start/stop values into the camera. 743 * Store a set of start/stop values into the camera.
@@ -761,6 +788,8 @@ static int ov7670_try_fmt_internal(struct v4l2_subdev *sd,
761{ 788{
762 int index; 789 int index;
763 struct ov7670_win_size *wsize; 790 struct ov7670_win_size *wsize;
791 struct ov7670_info *info = to_state(sd);
792 unsigned int n_win_sizes = info->devtype->n_win_sizes;
764 793
765 for (index = 0; index < N_OV7670_FMTS; index++) 794 for (index = 0; index < N_OV7670_FMTS; index++)
766 if (ov7670_formats[index].mbus_code == fmt->code) 795 if (ov7670_formats[index].mbus_code == fmt->code)
@@ -780,11 +809,11 @@ static int ov7670_try_fmt_internal(struct v4l2_subdev *sd,
780 * Round requested image size down to the nearest 809 * Round requested image size down to the nearest
781 * we support, but not below the smallest. 810 * we support, but not below the smallest.
782 */ 811 */
783 for (wsize = ov7670_win_sizes; wsize < ov7670_win_sizes + N_WIN_SIZES; 812 for (wsize = info->devtype->win_sizes;
784 wsize++) 813 wsize < info->devtype->win_sizes + n_win_sizes; wsize++)
785 if (fmt->width >= wsize->width && fmt->height >= wsize->height) 814 if (fmt->width >= wsize->width && fmt->height >= wsize->height)
786 break; 815 break;
787 if (wsize >= ov7670_win_sizes + N_WIN_SIZES) 816 if (wsize >= info->devtype->win_sizes + n_win_sizes)
788 wsize--; /* Take the smallest one */ 817 wsize--; /* Take the smallest one */
789 if (ret_wsize != NULL) 818 if (ret_wsize != NULL)
790 *ret_wsize = wsize; 819 *ret_wsize = wsize;
@@ -931,13 +960,14 @@ static int ov7670_enum_framesizes(struct v4l2_subdev *sd,
931 int i; 960 int i;
932 int num_valid = -1; 961 int num_valid = -1;
933 __u32 index = fsize->index; 962 __u32 index = fsize->index;
963 unsigned int n_win_sizes = info->devtype->n_win_sizes;
934 964
935 /* 965 /*
936 * If a minimum width/height was requested, filter out the capture 966 * If a minimum width/height was requested, filter out the capture
937 * windows that fall outside that. 967 * windows that fall outside that.
938 */ 968 */
939 for (i = 0; i < N_WIN_SIZES; i++) { 969 for (i = 0; i < n_win_sizes; i++) {
940 struct ov7670_win_size *win = &ov7670_win_sizes[index]; 970 struct ov7670_win_size *win = &info->devtype->win_sizes[index];
941 if (info->min_width && win->width < info->min_width) 971 if (info->min_width && win->width < info->min_width)
942 continue; 972 continue;
943 if (info->min_height && win->height < info->min_height) 973 if (info->min_height && win->height < info->min_height)
@@ -1510,6 +1540,17 @@ static const struct v4l2_subdev_ops ov7670_ops = {
1510 1540
1511/* ----------------------------------------------------------------------- */ 1541/* ----------------------------------------------------------------------- */
1512 1542
1543static const struct ov7670_devtype ov7670_devdata[] = {
1544 [MODEL_OV7670] = {
1545 .win_sizes = ov7670_win_sizes,
1546 .n_win_sizes = ARRAY_SIZE(ov7670_win_sizes),
1547 },
1548 [MODEL_OV7675] = {
1549 .win_sizes = ov7675_win_sizes,
1550 .n_win_sizes = ARRAY_SIZE(ov7675_win_sizes),
1551 },
1552};
1553
1513static int ov7670_probe(struct i2c_client *client, 1554static int ov7670_probe(struct i2c_client *client,
1514 const struct i2c_device_id *id) 1555 const struct i2c_device_id *id)
1515{ 1556{
@@ -1551,6 +1592,7 @@ static int ov7670_probe(struct i2c_client *client,
1551 v4l_info(client, "chip found @ 0x%02x (%s)\n", 1592 v4l_info(client, "chip found @ 0x%02x (%s)\n",
1552 client->addr << 1, client->adapter->name); 1593 client->addr << 1, client->adapter->name);
1553 1594
1595 info->devtype = &ov7670_devdata[id->driver_data];
1554 info->fmt = &ov7670_formats[0]; 1596 info->fmt = &ov7670_formats[0];
1555 info->sat = 128; /* Review this */ 1597 info->sat = 128; /* Review this */
1556 info->clkrc = info->clock_speed / 30; 1598 info->clkrc = info->clock_speed / 30;
@@ -1568,7 +1610,8 @@ static int ov7670_remove(struct i2c_client *client)
1568} 1610}
1569 1611
1570static const struct i2c_device_id ov7670_id[] = { 1612static const struct i2c_device_id ov7670_id[] = {
1571 { "ov7670", 0 }, 1613 { "ov7670", MODEL_OV7670 },
1614 { "ov7675", MODEL_OV7675 },
1572 { } 1615 { }
1573}; 1616};
1574MODULE_DEVICE_TABLE(i2c, ov7670_id); 1617MODULE_DEVICE_TABLE(i2c, ov7670_id);